From fc4456023802d20fc2bac963af7cbdc754c9c97a Mon Sep 17 00:00:00 2001 From: twanvl Date: Sun, 9 Sep 2007 00:39:01 +0000 Subject: [PATCH] Added 'card' to value actions, this fixes a bug where extra fields get updated with the wrong context, and it should also speed things up. git-svn-id: svn://svn.code.sf.net/p/magicseteditor/code/trunk@673 0fc631ac-6414-0410-93d0-97cfa31319b6 --- src/data/action/value.cpp | 34 ++++++++++----------- src/data/action/value.hpp | 23 +++++++------- src/gui/control/card_list.cpp | 5 ++-- src/gui/control/keyword_list.cpp | 10 ++++--- src/gui/set/keywords_panel.cpp | 24 ++++++++------- src/gui/set/style_panel.cpp | 14 +++++---- src/gui/set/window.cpp | 6 ++-- src/gui/symbol/window.cpp | 6 ++-- src/gui/symbol/window.hpp | 5 ++-- src/gui/value/choice.cpp | 2 +- src/gui/value/color.cpp | 2 +- src/gui/value/editor.hpp | 5 ++++ src/gui/value/image.cpp | 4 +-- src/gui/value/multiple_choice.cpp | 4 +-- src/gui/value/symbol.cpp | 4 +-- src/gui/value/text.cpp | 27 ++++------------- src/render/card/viewer.cpp | 14 +++++---- src/render/card/viewer.hpp | 2 +- src/script/script_manager.cpp | 50 ++++++++++++++++++------------- 19 files changed, 126 insertions(+), 115 deletions(-) diff --git a/src/data/action/value.cpp b/src/data/action/value.cpp index 31d410ce..06841460 100644 --- a/src/data/action/value.cpp +++ b/src/data/action/value.cpp @@ -39,8 +39,8 @@ inline void swap_value(MultipleChoiceValue& a, MultipleChoiceValue::ValueType& b template class SimpleValueAction : public ValueAction { public: - inline SimpleValueAction(const intrusive_ptr& value, const typename T::ValueType& new_value) - : ValueAction(value), new_value(new_value) + inline SimpleValueAction(const Card* card, const intrusive_ptr& value, const typename T::ValueType& new_value) + : ValueAction(card, value), new_value(new_value) {} virtual void perform(bool to_undo) { @@ -64,20 +64,20 @@ class SimpleValueAction : public ValueAction { typename T::ValueType new_value; }; -ValueAction* value_action(const ChoiceValueP& value, const Defaultable& new_value) { return new SimpleValueAction (value, new_value); } -ValueAction* value_action(const ColorValueP& value, const Defaultable& new_value) { return new SimpleValueAction (value, new_value); } -ValueAction* value_action(const ImageValueP& value, const FileName& new_value) { return new SimpleValueAction(value, new_value); } -ValueAction* value_action(const SymbolValueP& value, const FileName& new_value) { return new SimpleValueAction(value, new_value); } -ValueAction* value_action(const MultipleChoiceValueP& value, const Defaultable& new_value, const String& last_change) { +ValueAction* value_action(const Card* card, const ChoiceValueP& value, const Defaultable& new_value) { return new SimpleValueAction (card, value, new_value); } +ValueAction* value_action(const Card* card, const ColorValueP& value, const Defaultable& new_value) { return new SimpleValueAction (card, value, new_value); } +ValueAction* value_action(const Card* card, const ImageValueP& value, const FileName& new_value) { return new SimpleValueAction(card, value, new_value); } +ValueAction* value_action(const Card* card, const SymbolValueP& value, const FileName& new_value) { return new SimpleValueAction(card, value, new_value); } +ValueAction* value_action(const Card* card, const MultipleChoiceValueP& value, const Defaultable& new_value, const String& last_change) { MultipleChoiceValue::ValueType v = { new_value, last_change }; - return new SimpleValueAction(value, v); + return new SimpleValueAction(card, value, v); } // ----------------------------------------------------------------------------- : Text -TextValueAction::TextValueAction(const TextValueP& value, size_t start, size_t end, size_t new_end, const Defaultable& new_value, const String& name) - : ValueAction(value) +TextValueAction::TextValueAction(const Card* card, const TextValueP& value, size_t start, size_t end, size_t new_end, const Defaultable& new_value, const String& name) + : ValueAction(card, value) , selection_start(start), selection_end(end), new_selection_end(new_end) , new_value(new_value) , name(name) @@ -107,7 +107,7 @@ TextValue& TextValueAction::value() const { } -TextValueAction* toggle_format_action(const TextValueP& value, const String& tag, size_t start_i, size_t end_i, size_t start, size_t end, const String& action_name) { +TextValueAction* toggle_format_action(const Card* card, const TextValueP& value, const String& tag, size_t start_i, size_t end_i, size_t start, size_t end, const String& action_name) { if (start > end) { swap(start, end); swap(start_i, end_i); @@ -140,11 +140,11 @@ TextValueAction* toggle_format_action(const TextValueP& value, const String& tag if (value->value() == new_value) { return nullptr; // no changes } else { - return new TextValueAction(value, start, end, end, new_value, action_name); + return new TextValueAction(card, value, start, end, end, new_value, action_name); } } -TextValueAction* typing_action(const TextValueP& value, size_t start_i, size_t end_i, size_t start, size_t end, const String& replacement, const String& action_name) { +TextValueAction* typing_action(const Card* card, const TextValueP& value, size_t start_i, size_t end_i, size_t start, size_t end, const String& replacement, const String& action_name) { bool reverse = start > end; if (reverse) { swap(start, end); @@ -156,17 +156,17 @@ TextValueAction* typing_action(const TextValueP& value, size_t start_i, size_t e return nullptr; } else { if (reverse) { - return new TextValueAction(value, end, start, start+untag(replacement).size(), new_value, action_name); + return new TextValueAction(card, value, end, start, start+untag(replacement).size(), new_value, action_name); } else { - return new TextValueAction(value, start, end, start+untag(replacement).size(), new_value, action_name); + return new TextValueAction(card, value, start, end, start+untag(replacement).size(), new_value, action_name); } } } // ----------------------------------------------------------------------------- : Reminder text -TextToggleReminderAction::TextToggleReminderAction(const TextValueP& value, size_t pos_in) - : ValueAction(value) +TextToggleReminderAction::TextToggleReminderAction(const Card* card, const TextValueP& value, size_t pos_in) + : ValueAction(card, value) { pos = in_tag(value->value(), _("& new_value); -ValueAction* value_action(const MultipleChoiceValueP& value, const Defaultable& new_value, const String& last_change); -ValueAction* value_action(const ColorValueP& value, const Defaultable& new_value); -ValueAction* value_action(const ImageValueP& value, const FileName& new_value); -ValueAction* value_action(const SymbolValueP& value, const FileName& new_value); +ValueAction* value_action(const Card* card, const ChoiceValueP& value, const Defaultable& new_value); +ValueAction* value_action(const Card* card, const MultipleChoiceValueP& value, const Defaultable& new_value, const String& last_change); +ValueAction* value_action(const Card* card, const ColorValueP& value, const Defaultable& new_value); +ValueAction* value_action(const Card* card, const ImageValueP& value, const FileName& new_value); +ValueAction* value_action(const Card* card, const SymbolValueP& value, const FileName& new_value); // ----------------------------------------------------------------------------- : Text /// An action that changes a TextValue class TextValueAction : public ValueAction { public: - TextValueAction(const TextValueP& value, size_t start, size_t end, size_t new_end, const Defaultable& new_value, const String& name); + TextValueAction(const Card* card, const TextValueP& value, size_t start, size_t end, size_t new_end, const Defaultable& new_value, const String& name); virtual String getName(bool to_undo) const; virtual void perform(bool to_undo); @@ -74,18 +75,18 @@ class TextValueAction : public ValueAction { }; /// Action for toggling some formating tag on or off in some range -TextValueAction* toggle_format_action(const TextValueP& value, const String& tag, size_t start_i, size_t end_i, size_t start, size_t end, const String& action_name); +TextValueAction* toggle_format_action(const Card* card, const TextValueP& value, const String& tag, size_t start_i, size_t end_i, size_t start, size_t end, const String& action_name); /// Typing in a TextValue, replace the selection [start...end) with replacement /** start and end are cursor positions, start_i and end_i are indices*/ -TextValueAction* typing_action(const TextValueP& value, size_t start_i, size_t end_i, size_t start, size_t end, const String& replacement, const String& action_name); +TextValueAction* typing_action(const Card* card, const TextValueP& value, size_t start_i, size_t end_i, size_t start, size_t end, const String& replacement, const String& action_name); // ----------------------------------------------------------------------------- : Reminder text /// Toggle reminder text for a keyword on or off class TextToggleReminderAction : public ValueAction { public: - TextToggleReminderAction(const TextValueP& value, size_t pos); + TextToggleReminderAction(const Card* card, const TextValueP& value, size_t pos); virtual String getName(bool to_undo) const; virtual void perform(bool to_undo); @@ -101,7 +102,7 @@ class TextToggleReminderAction : public ValueAction { /// A TextValueAction without the start and end stuff class SimpleTextValueAction : public ValueAction { public: - SimpleTextValueAction(const TextValueP& value, const Defaultable& new_value); + SimpleTextValueAction(const Card* card, const TextValueP& value, const Defaultable& new_value); virtual void perform(bool to_undo); bool merge(const SimpleTextValueAction& action); private: diff --git a/src/gui/control/card_list.cpp b/src/gui/control/card_list.cpp index f94ff606..ac89133b 100644 --- a/src/gui/control/card_list.cpp +++ b/src/gui/control/card_list.cpp @@ -113,9 +113,8 @@ void CardListBase::onAction(const Action& action, bool undone) { // No refresh needed, a ScriptValueEvent is only generated in response to a ValueAction return; } - TYPE_CASE_(action, ValueAction) { - refreshList(); - return; + TYPE_CASE(action, ValueAction) { + if (action.card) refreshList(); } } diff --git a/src/gui/control/keyword_list.cpp b/src/gui/control/keyword_list.cpp index 9d94bfbd..185786c3 100644 --- a/src/gui/control/keyword_list.cpp +++ b/src/gui/control/keyword_list.cpp @@ -75,10 +75,12 @@ void KeywordList::onAction(const Action& action, bool undone) { } } TYPE_CASE(action, ValueAction) { - KeywordTextValue* value = dynamic_cast(action.valueP.get()); - if (value) { - // this is indeed an action on a keyword, refresh - refreshList(); + if (!action.card) { + KeywordTextValue* value = dynamic_cast(action.valueP.get()); + if (value) { + // this is indeed an action on a keyword, refresh + refreshList(); + } } } TYPE_CASE_(action, ChangeKeywordModeAction) { diff --git a/src/gui/set/keywords_panel.cpp b/src/gui/set/keywords_panel.cpp index 9bdec106..0a891c20 100644 --- a/src/gui/set/keywords_panel.cpp +++ b/src/gui/set/keywords_panel.cpp @@ -280,18 +280,20 @@ void KeywordsPanel::onChangeSet() { void KeywordsPanel::onAction(const Action& action, bool undone) { TYPE_CASE(action, ValueAction) { - { - KeywordReminderTextValue* value = dynamic_cast(action.valueP.get()); - if (value && &value->keyword == list->getKeyword().get()) { - // the current keyword's reminder text changed - errors->SetLabel(value->errors); + if (!action.card) { + { + KeywordReminderTextValue* value = dynamic_cast(action.valueP.get()); + if (value && &value->keyword == list->getKeyword().get()) { + // the current keyword's reminder text changed + errors->SetLabel(value->errors); + } } - } - { - KeywordTextValue* value = dynamic_cast(action.valueP.get()); - if (value && value->underlying == &list->getKeyword()->match) { - // match string changes, maybe there are parameters now - ref_param->Enable(!value->keyword.fixed && !value->keyword.parameters.empty()); + { + KeywordTextValue* value = dynamic_cast(action.valueP.get()); + if (value && value->underlying == &list->getKeyword()->match) { + // match string changes, maybe there are parameters now + ref_param->Enable(!value->keyword.fixed && !value->keyword.parameters.empty()); + } } } } diff --git a/src/gui/set/style_panel.cpp b/src/gui/set/style_panel.cpp index a8028623..10ffa0ed 100644 --- a/src/gui/set/style_panel.cpp +++ b/src/gui/set/style_panel.cpp @@ -73,12 +73,14 @@ void StylePanel::onAction(const Action& action, bool undone) { } TYPE_CASE(action, ValueAction) { // is it a styling action? - const StyleSheet& s = set->stylesheetFor(card); - FOR_EACH_CONST(f, s.styling_fields) { - if (action.valueP->fieldP == f) { - // refresh the viewer - preview->redraw(); - return; + if (!action.card) { + const StyleSheet& s = set->stylesheetFor(card); + FOR_EACH_CONST(f, s.styling_fields) { + if (action.valueP->fieldP == f) { + // refresh the viewer + preview->redraw(); + return; + } } } } diff --git a/src/gui/set/window.cpp b/src/gui/set/window.cpp index d0df59e8..b7282af1 100644 --- a/src/gui/set/window.cpp +++ b/src/gui/set/window.cpp @@ -264,8 +264,10 @@ void SetWindow::onChangeSet() { void SetWindow::onAction(const Action& action, bool undone) { TYPE_CASE(action, ValueAction) { - if (set->data.contains(action.valueP) && action.valueP->fieldP->identifying) { - updateTitle(); + if (!action.card) { + if (set->data.contains(action.valueP) && action.valueP->fieldP->identifying) { + updateTitle(); + } } } /* TYPE_CASE_(action, DisplayChangeAction) { diff --git a/src/gui/symbol/window.cpp b/src/gui/symbol/window.cpp index 3064330d..9836ba61 100644 --- a/src/gui/symbol/window.cpp +++ b/src/gui/symbol/window.cpp @@ -35,8 +35,8 @@ SymbolWindow::SymbolWindow(Window* parent, const String& filename) { init(parent, symbol); } -SymbolWindow::SymbolWindow(Window* parent, const SymbolValueP& value, const SetP& set) - : value(value), set(set) +SymbolWindow::SymbolWindow(Window* parent, const SetP& set, const Card* card, const SymbolValueP& value) + : value(value), card(card), set(set) { // attempt to load symbol SymbolP symbol; @@ -236,7 +236,7 @@ void SymbolWindow::onFileStore(wxCommandEvent& ev) { FileName new_filename = set->newFileName(value->field().name,_(".mse-symbol")); // a new unique name in the package Writer writer(set->openOut(new_filename)); writer.handle(control->getSymbol()); - set->actions.add(value_action(value, new_filename)); + set->actions.add(value_action(card, value, new_filename)); } } diff --git a/src/gui/symbol/window.hpp b/src/gui/symbol/window.hpp index b18951af..6bf545e8 100644 --- a/src/gui/symbol/window.hpp +++ b/src/gui/symbol/window.hpp @@ -14,8 +14,8 @@ #include class SymbolControl; -//%%class SymbolPartList; class SymbolPartList; +class Card; DECLARE_POINTER_TYPE(SymbolValue); DECLARE_POINTER_TYPE(Set); @@ -29,7 +29,7 @@ class SymbolWindow : public Frame { /// Construct a SymbolWindow showing a symbol from a file SymbolWindow(Window* parent, const String& filename); /// Construct a SymbolWindow showing a symbol value in a set - SymbolWindow(Window* parent, const SymbolValueP& value, const SetP& set); + SymbolWindow(Window* parent, const SetP& set, const Card* card, const SymbolValueP& value); private: // --------------------------------------------------- : Children @@ -42,6 +42,7 @@ class SymbolWindow : public Frame { // when editing a symbol field SymbolValueP value; + const Card* card; SetP set; // --------------------------------------------------- : Event handling diff --git a/src/gui/value/choice.cpp b/src/gui/value/choice.cpp index d67925a5..907aebdb 100644 --- a/src/gui/value/choice.cpp +++ b/src/gui/value/choice.cpp @@ -307,5 +307,5 @@ void ChoiceValueEditor::determineSize(bool) { } void ChoiceValueEditor::change(const Defaultable& c) { - getSet().actions.add(value_action(valueP(), c)); + perform(value_action(card(), valueP(), c)); } diff --git a/src/gui/value/color.cpp b/src/gui/value/color.cpp index 28d409cb..32c79c5d 100644 --- a/src/gui/value/color.cpp +++ b/src/gui/value/color.cpp @@ -149,7 +149,7 @@ void ColorValueEditor::determineSize(bool) { } void ColorValueEditor::change(const Defaultable& c) { - getSet().actions.add(value_action(valueP(), c)); + perform(value_action(card(), valueP(), c)); } void ColorValueEditor::changeCustom() { Color c = wxGetColourFromUser(0, value().value()); diff --git a/src/gui/value/editor.hpp b/src/gui/value/editor.hpp index e16b544e..81a6da24 100644 --- a/src/gui/value/editor.hpp +++ b/src/gui/value/editor.hpp @@ -133,9 +133,14 @@ class ValueEditor { virtual ValueEditor* getEditor() { return this; } \ virtual void redraw(); \ private: \ + /** Retrieve the parent editor object */ \ inline DataEditor& editor() const { \ return static_cast(viewer); \ } \ + /** Card this editor is on, or nullptr */ \ + inline const Card* card() const { return viewer.getCard().get(); } \ + /** Perform an action */ \ + void perform(Action* a) { getSet().actions.add(a); } \ public: #define IMPLEMENT_VALUE_EDITOR(Type) \ diff --git a/src/gui/value/image.cpp b/src/gui/value/image.cpp index bc3b070d..6191fb95 100644 --- a/src/gui/value/image.cpp +++ b/src/gui/value/image.cpp @@ -48,7 +48,7 @@ void ImageValueEditor::sliceImage(const Image& image) { FileName new_image_file = getSet().newFileName(field().name,_("")); // a new unique name in the package Image img = s.getImage(); img.SaveFile(getSet().nameOut(new_image_file), img.HasAlpha() ? wxBITMAP_TYPE_PNG : wxBITMAP_TYPE_JPEG); - getSet().actions.add(value_action(valueP(), new_image_file)); + perform(value_action(card(), valueP(), new_image_file)); } } @@ -88,7 +88,7 @@ bool ImageValueEditor::doPaste() { } bool ImageValueEditor::doDelete() { - getSet().actions.add(value_action(valueP(), FileName())); + perform(value_action(card(), valueP(), FileName())); return true; } diff --git a/src/gui/value/multiple_choice.cpp b/src/gui/value/multiple_choice.cpp index 42072635..c2e057ce 100644 --- a/src/gui/value/multiple_choice.cpp +++ b/src/gui/value/multiple_choice.cpp @@ -173,9 +173,9 @@ void MultipleChoiceValueEditor::toggle(int id) { if (i == id) toggled_choice = choice; } // store value - getSet().actions.add(value_action(valueP(), new_value, toggled_choice)); + perform(value_action(card(), valueP(), new_value, toggled_choice)); } void MultipleChoiceValueEditor::toggleDefault() { - getSet().actions.add(value_action(valueP(), Defaultable(value().value(), !value().value.isDefault()), _(""))); + perform(value_action(card(), valueP(), Defaultable(value().value(), !value().value.isDefault()), _(""))); } diff --git a/src/gui/value/symbol.cpp b/src/gui/value/symbol.cpp index a38d41bc..574fad62 100644 --- a/src/gui/value/symbol.cpp +++ b/src/gui/value/symbol.cpp @@ -92,7 +92,7 @@ bool SymbolValueEditor::onLeftUp(const RealPoint& pos, wxMouseEvent&) { // edit button_down = -2; viewer.redraw(*this); - SymbolWindow* wnd = new SymbolWindow(nullptr, valueP(), viewer.getSet()); + SymbolWindow* wnd = new SymbolWindow(nullptr, viewer.getSet(), card(), valueP()); wnd->Show(); return true; } else if (button_down == 1) { @@ -109,7 +109,7 @@ bool SymbolValueEditor::onLeftUp(const RealPoint& pos, wxMouseEvent&) { bool SymbolValueEditor::onLeftDClick(const RealPoint& pos, wxMouseEvent&) { // Use SetWindow as parent? Maybe not, the symbol editor will stay open when mainwindow closes - SymbolWindow* wnd = new SymbolWindow(nullptr, valueP(), viewer.getSet()); + SymbolWindow* wnd = new SymbolWindow(nullptr, viewer.getSet(), card(), valueP()); wnd->Show(); return true; } diff --git a/src/gui/value/text.cpp b/src/gui/value/text.cpp index 8d95cdb7..aabe1415 100644 --- a/src/gui/value/text.cpp +++ b/src/gui/value/text.cpp @@ -563,21 +563,6 @@ wxMenu* TextValueEditor::getMenu(int type) const { } } -/* -/// TODO : move to doFormat -void TextValueEditor::onMenu(wxCommandEvent& ev) { - if (ev.GetId() == ID_FORMAT_REMINDER) { - // toggle reminder text - size_t kwpos = in_tag(value().value(), _("getValue()->equals( action.valueP.get() )) { - // refresh the viewer - v->onAction(action, undone); - onChange(); - return; + if (action.card == card.get()) { + FOR_EACH(v, viewers) { + if (v->getValue()->equals( action.valueP.get() )) { + // refresh the viewer + v->onAction(action, undone); + onChange(); + return; + } } } } diff --git a/src/render/card/viewer.hpp b/src/render/card/viewer.hpp index 8997b3f9..e3b7260b 100644 --- a/src/render/card/viewer.hpp +++ b/src/render/card/viewer.hpp @@ -57,7 +57,7 @@ class DataViewer : public SetView { Context& getContext() const; /// The rotation to use virtual Rotation getRotation() const; - /// The card we are viewing + /// The card we are viewing, can be null inline const CardP& getCard() const { return card; } /// Invalidate and redraw (the area of) a single value viewer virtual void redraw(const ValueViewer&) {} diff --git a/src/script/script_manager.cpp b/src/script/script_manager.cpp index 0e2d498a..aaab0929 100644 --- a/src/script/script_manager.cpp +++ b/src/script/script_manager.cpp @@ -151,29 +151,39 @@ void SetScriptManager::initDependencies(Context& ctx, StyleSheet& stylesheet) { void SetScriptManager::onAction(const Action& action, bool undone) { TYPE_CASE(action, ValueAction) { - // is it a keyword's fake value? - KeywordTextValue* value = dynamic_cast(action.valueP.get()); - if (value) { - if (value->underlying == &value->keyword.match) { - // script - Context& ctx = getContext(set.stylesheet); - value->update(ctx); - // changed the 'match' string of a keyword, rebuild database and regex so matching is correct - value->keyword.prepare(set.game->keyword_parameter_types, true); - set.keyword_db.clear(); - } - delay |= DELAY_KEYWORDS; - return; - } - // find the affected card - FOR_EACH(card, set.cards) { - if (card->data.contains(action.valueP)) { - updateValue(*action.valueP, card); + if (action.card) { + #ifdef USE_INTRUSIVE_PTR + // we can just turn the Card* into a CardP + updateValue(*action.valueP, CardP(const_cast(action.card))); + return; + #else + // find the affected card + FOR_EACH(card, set.cards) { + if (card->data.contains(action.valueP)) { + updateValue(*action.valueP, card); + return; + } + } + assert(false); + #endif + } else { + // is it a keyword's fake value? + KeywordTextValue* value = dynamic_cast(action.valueP.get()); + if (value) { + if (value->underlying == &value->keyword.match) { + // script + Context& ctx = getContext(set.stylesheet); + value->update(ctx); + // changed the 'match' string of a keyword, rebuild database and regex so matching is correct + value->keyword.prepare(set.game->keyword_parameter_types, true); + set.keyword_db.clear(); + } + delay |= DELAY_KEYWORDS; return; } + // a set or styling value + updateValue(*action.valueP, CardP()); } - // not a card value - updateValue(*action.valueP, CardP()); } TYPE_CASE_(action, ScriptValueEvent) { return; // Don't go into an infinite loop because of our own events