From 20f0efacd725972ccb4b6fbdbc3690802a4dc77f Mon Sep 17 00:00:00 2001 From: twanvl Date: Fri, 20 Oct 2006 14:24:36 +0000 Subject: [PATCH] added 'undone' parameter to onAction git-svn-id: svn://svn.code.sf.net/p/magicseteditor/code/trunk@43 0fc631ac-6414-0410-93d0-97cfa31319b6 --- src/data/action/set.cpp | 8 ++-- src/data/action/set.hpp | 14 +++---- src/data/set.hpp | 2 +- src/data/symbol.hpp | 2 +- src/gui/control/card_list.cpp | 77 ++++++++++++++++++++++++++--------- src/gui/control/card_list.hpp | 8 ++-- src/gui/set/cards_panel.cpp | 4 +- src/gui/set/cards_panel.hpp | 4 +- src/gui/set/panel.hpp | 4 +- src/gui/set/window.cpp | 2 +- src/gui/set/window.hpp | 2 +- src/gui/symbol/control.cpp | 2 +- src/gui/symbol/control.hpp | 2 +- src/gui/symbol/part_list.cpp | 2 +- src/gui/symbol/part_list.hpp | 2 +- src/util/action_stack.cpp | 8 ++-- src/util/action_stack.hpp | 5 ++- 17 files changed, 93 insertions(+), 55 deletions(-) diff --git a/src/data/action/set.cpp b/src/data/action/set.cpp index 1a4fde67..3a4fbfce 100644 --- a/src/data/action/set.cpp +++ b/src/data/action/set.cpp @@ -39,12 +39,10 @@ void AddCardAction::perform(bool to_undo) { RemoveCardAction::RemoveCardAction(Set& set, const CardP& card) : CardListAction(set), card(card) -{ // find the card_id of the card we want to remove - vector::iterator it = find(set.cards.begin(), set.cards.end(), card); - if (it != set.cards.end()) { - card_id = it - set.cards.begin(); - } else { + , card_id(find(set.cards.begin(), set.cards.end(), card) - set.cards.begin()) +{ + if (card_id >= set.cards.size()) { throw InternalError(_("Card to remove not found in set")); } } diff --git a/src/data/action/set.hpp b/src/data/action/set.hpp index 638c25cc..1bd62303 100644 --- a/src/data/action/set.hpp +++ b/src/data/action/set.hpp @@ -40,8 +40,8 @@ class AddCardAction : public CardListAction { virtual String getName(bool to_undo) const; virtual void perform(bool to_undo); - private: - CardP card; ///< The new card + //private: + const CardP card; ///< The new card }; // ----------------------------------------------------------------------------- : Remove card @@ -54,9 +54,9 @@ class RemoveCardAction : public CardListAction { virtual String getName(bool to_undo) const; virtual void perform(bool to_undo); - private: - CardP card; ///< The removed card - size_t card_id; ///< Position of the card in the set + //private: + const CardP card; ///< The removed card + const size_t card_id; ///< Position of the card in the set }; // ----------------------------------------------------------------------------- : Reorder cards @@ -69,8 +69,8 @@ class ReorderCardsAction : public CardListAction { virtual String getName(bool to_undo) const; virtual void perform(bool to_undo); - private: - size_t card_id1, card_id2; ///< Positions of the two cards to swap + //private: + const size_t card_id1, card_id2; ///< Positions of the two cards to swap }; // ----------------------------------------------------------------------------- : EOF diff --git a/src/data/set.hpp b/src/data/set.hpp index e3229fd9..d9d50f59 100644 --- a/src/data/set.hpp +++ b/src/data/set.hpp @@ -55,7 +55,7 @@ class Set : public Packaged { // ----------------------------------------------------------------------------- : SetView /// A 'view' of a Set, is notified when the Set is updated -/** To listen to events, derived classes should override onAction(const Action&) +/** To listen to events, derived classes should override onAction(const Action&, bool undone) */ class SetView : public ActionListener { public: diff --git a/src/data/symbol.hpp b/src/data/symbol.hpp index 53e3a731..c726bede 100644 --- a/src/data/symbol.hpp +++ b/src/data/symbol.hpp @@ -166,7 +166,7 @@ class Symbol { // ----------------------------------------------------------------------------- : SymbolView /// A 'view' of a symbol, is notified when the symbol is updated -/** To listen to events, derived classes should override onAction(const Action&) +/** To listen to events, derived classes should override onAction(const Action&, bool undone) */ class SymbolView : public ActionListener { public: diff --git a/src/gui/control/card_list.cpp b/src/gui/control/card_list.cpp index 59730c9b..45e028b1 100644 --- a/src/gui/control/card_list.cpp +++ b/src/gui/control/card_list.cpp @@ -13,6 +13,7 @@ #include #include #include +#include #include DECLARE_TYPEOF_COLLECTION(CardP); @@ -47,8 +48,44 @@ void CardListBase::onBeforeChangeSet() { void CardListBase::onChangeSet() { rebuild(); } -void CardListBase::onAction(const Action& action) { - // TODO + +void CardListBase::onAction(const Action& action, bool undone) { + TYPE_CASE(action, AddCardAction) { + // select the new card + selectCard(action.card, false /*list will be refreshed anyway*/); + refreshList(); + } + TYPE_CASE(action, RemoveCardAction) { + if (undone) { + // select the re-added card + selectCard(action.card, false /*list will be refreshed anyway*/); + refreshList(); + } else { + long pos = selected_card_pos; + refreshList(); + if (action.card == selected_card) { + // select the next card, if not possible, select the last + if ((size_t)pos + 1 < sorted_card_list.size()) { + selectCardPos(pos, true); + } else { + selectCardPos((long)sorted_card_list.size() - 1, true); + } + } + } + } + TYPE_CASE(action, ReorderCardsAction) { + if (sort_criterium) return; // nothing changes for us + if ((long)action.card_id1 == selected_card_pos || (long)action.card_id2 == selected_card_pos) { + // Selected card has moved; also move in the sorted card list + swap(sorted_card_list[action.card_id1] ,sorted_card_list[action.card_id2]); + // reselect the current card, it has moved + selected_card_pos = (long)action.card_id1 == selected_card_pos ? (long)action.card_id2 : (long)action.card_id1; + // select the right card + selectCurrentCard(); + } + RefreshItem((long)action.card_id1); + RefreshItem((long)action.card_id2); + } } vector& CardListBase::getCards() const { @@ -58,16 +95,18 @@ vector& CardListBase::getCards() const { // ----------------------------------------------------------------------------- : CardListBase : Selection bool CardListBase::canSelectPrevious() const { - return selected_card_pos + 1 >= 0; + return selected_card_pos - 1 >= 0; } bool CardListBase::canSelectNext() const { return selected_card_pos >= 0 && static_cast(selected_card_pos + 1) < sorted_card_list.size(); } void CardListBase::selectPrevious() { -// TODO + assert(selected_card_pos >= 1); + selectCardPos(selected_card_pos - 1, true); } void CardListBase::selectNext() { -// TODO + assert(selected_card_pos + 1 < (long)sorted_card_list.size()); + selectCardPos(selected_card_pos + 1, true); } // ----------------------------------------------------------------------------- : CardListBase : Selection (private) @@ -81,19 +120,19 @@ void CardListBase::selectCard(const CardP& card, bool focus) { selectCurrentCard(); } } -/* -void CardListBase::selectCardPos(size_t pos, bool focus = true, bool force = false) { - if (selectedCardPos == pos && !force) return; // this card is already selected - if (pos < sortedCardList.size()) { + +void CardListBase::selectCardPos(long pos, bool focus) { + if (selected_card_pos == pos && !focus) return; // this card is already selected + if ((size_t)pos < sorted_card_list.size()) { // only if there is something to select - selectCard(getCard(pos), false); + selectCard(sorted_card_list[pos], false); } else { selectCard(CardP(), false); } - selectedCardPos = Long(pos); - if (focus) selectCurrentCard(); + selected_card_pos = pos; + if (focus) selectCurrentCard(); } -*/ + void CardListBase::findSelectedCardPos() { // find the position of the selected card long count = GetItemCount(); @@ -107,7 +146,7 @@ void CardListBase::findSelectedCardPos() { } void CardListBase::selectCurrentCard() { if (GetItemCount() > 0) { - if (selected_card_pos == -1) { + if (selected_card_pos == -1 || (size_t)selected_card_pos > sorted_card_list.size()) { // deselect currently selected item, if any long sel = GetFirstSelected(); Select(sel, false); @@ -190,9 +229,7 @@ void CardListBase::rebuild() { } refreshList(); // select a card if possible -// if (!getCards().empty()) { -// selectCardPos(0, true); -// } + selectCardPos(0, true); } void CardListBase::refreshList() { @@ -273,7 +310,7 @@ void CardListBase::onColumnClick(wxListEvent& ev) { FieldP new_sort_criterium = column_fields[ev.GetColumn()]; if (sort_criterium == new_sort_criterium) { if (sort_ascending) { - sort_ascending = false; // 2nd click on same column -> sort descending + sort_ascending = false; // 2nd click on same column -> sort descending } else { new_sort_criterium.reset(); // 3rd click on same column -> don't sort } @@ -306,12 +343,12 @@ void CardListBase::onSelectColumns(wxCommandEvent&) { } void CardListBase::onItemFocus(wxListEvent& ev) { -// selectCardPos(ev.GetIndex(), false); + selectCardPos(ev.GetIndex(), false); } void CardListBase::onChar(wxKeyEvent& ev) { if (ev.GetKeyCode() == WXK_DELETE) { -// set->actions.add(new_shared2(set.get(), card)); + set->actions.add(new RemoveCardAction(*set, selected_card)); } else if (ev.GetKeyCode() == WXK_TAB) { // send a navigation event to our parent, to select another control // we need this because tabs are not handled on the cards panel diff --git a/src/gui/control/card_list.hpp b/src/gui/control/card_list.hpp index 04f4753c..04bed7be 100644 --- a/src/gui/control/card_list.hpp +++ b/src/gui/control/card_list.hpp @@ -50,7 +50,7 @@ class CardListBase : public wxListView, public SetView { // --------------------------------------------------- : Selection inline CardP getCard() const { return selected_card; } - inline void setCard(const CardP& card) { selectCard(card); } + inline void setCard(const CardP& card) { selectCard(card, true); } /// Is there a previous card to select? bool canSelectPrevious() const; @@ -74,7 +74,7 @@ class CardListBase : public wxListView, public SetView { virtual void onBeforeChangeSet(); virtual void onChangeSet(); - virtual void onAction(const Action&); + virtual void onAction(const Action&, bool undone); // --------------------------------------------------- : The cards protected: @@ -113,9 +113,9 @@ class CardListBase : public wxListView, public SetView { /** If focus then the card is also focused and selected in the actual control. * This should abviously not be done when the card is selected because it was selected (leading to a loop). */ - void selectCard(const CardP& card, bool focus = false); + void selectCard(const CardP& card, bool focus); /// Select a card at the specified position - void selectCardPos(long pos); + void selectCardPos(long pos, bool focus); /// Find the position for the selected_card void findSelectedCardPos(); /// Actually select the card at selected_card_pos in the control diff --git a/src/gui/set/cards_panel.cpp b/src/gui/set/cards_panel.cpp index dd81f682..ae142948 100644 --- a/src/gui/set/cards_panel.cpp +++ b/src/gui/set/cards_panel.cpp @@ -186,11 +186,11 @@ void CardsPanel::onCommand(int id) { // ----------------------------------------------------------------------------- : Actions -bool CardsPanel::wantsToHandle(const Action&) const { +bool CardsPanel::wantsToHandle(const Action&, bool undone) const { return false; } -void CardsPanel::onAction(const Action& action) { +void CardsPanel::onAction(const Action& action, bool undo) { // TODO } diff --git a/src/gui/set/cards_panel.hpp b/src/gui/set/cards_panel.hpp index 704e182b..7971a540 100644 --- a/src/gui/set/cards_panel.hpp +++ b/src/gui/set/cards_panel.hpp @@ -34,8 +34,8 @@ class CardsPanel : public SetWindowPanel { // --------------------------------------------------- : Actions - virtual bool wantsToHandle(const Action&) const; - virtual void onAction(const Action&); + virtual bool wantsToHandle(const Action&, bool undone) const; + virtual void onAction(const Action&, bool undone); virtual void onRenderSettingsChange(); private: void updateSize(); diff --git a/src/gui/set/panel.hpp b/src/gui/set/panel.hpp index 74dc2a38..07570f12 100644 --- a/src/gui/set/panel.hpp +++ b/src/gui/set/panel.hpp @@ -46,9 +46,9 @@ class SetWindowPanel : public wxPanel, public SetView { // --------------------------------------------------- : Actions/Events /// Should return true if this panel wants to get focus to show an action - virtual bool wantsToHandle(const Action&) const { return false; } + virtual bool wantsToHandle(const Action&, bool undone) const { return false; } /// Handle an action that changes the current set - virtual void onAction(const Action&) {} + virtual void onAction(const Action&, bool undone) {} /// The settings for rendering cards have changed, refresh card viewers/editors virtual void onRenderSettingsChange() {} diff --git a/src/gui/set/window.cpp b/src/gui/set/window.cpp index 6205b871..84108ef0 100644 --- a/src/gui/set/window.cpp +++ b/src/gui/set/window.cpp @@ -234,7 +234,7 @@ void SetWindow::onChangeSet() { fixMinWindowSize(); } -void SetWindow::onAction(const Action& action) { +void SetWindow::onAction(const Action& action, bool undone) { // TYPE_CASE_(action, SetStyleChange) { // // The style changed, maybe also the size of the viewer // Layout(); diff --git a/src/gui/set/window.hpp b/src/gui/set/window.hpp index 4397cbd8..eacf1fcd 100644 --- a/src/gui/set/window.hpp +++ b/src/gui/set/window.hpp @@ -80,7 +80,7 @@ class SetWindow : public wxFrame, public SetView { /// We want to respond to set changes virtual void onChangeSet(); /// Actions that change the set - virtual void onAction(const Action&); + virtual void onAction(const Action&, bool undone); private: /// A different card has been selected diff --git a/src/gui/symbol/control.cpp b/src/gui/symbol/control.cpp index 925d5658..38f86f3e 100644 --- a/src/gui/symbol/control.cpp +++ b/src/gui/symbol/control.cpp @@ -68,7 +68,7 @@ void SymbolControl::onExtraTool(wxCommandEvent& ev) { if (editor) editor->onCommand(ev.GetId()); } -void SymbolControl::onAction(const Action& action) { +void SymbolControl::onAction(const Action& action, bool undone) { TYPE_CASE_(action, SymbolPartAction) { Refresh(false); } diff --git a/src/gui/symbol/control.hpp b/src/gui/symbol/control.hpp index a96a5ca9..f792ee47 100644 --- a/src/gui/symbol/control.hpp +++ b/src/gui/symbol/control.hpp @@ -28,7 +28,7 @@ class SymbolControl : public wxControl, public SymbolViewer { virtual void onChangeSymbol(); - virtual void onAction(const Action&); + virtual void onAction(const Action&, bool undone); // Forward command to editor void onExtraTool(wxCommandEvent& ev); diff --git a/src/gui/symbol/part_list.cpp b/src/gui/symbol/part_list.cpp index 49bcb5ec..d4b471fb 100644 --- a/src/gui/symbol/part_list.cpp +++ b/src/gui/symbol/part_list.cpp @@ -39,7 +39,7 @@ void SymbolPartList::onChangeSymbol() { update(); } -void SymbolPartList::onAction(const Action& action) { +void SymbolPartList::onAction(const Action& action, bool undone) { TYPE_CASE(action, ReorderSymbolPartsAction) { if (selected == (long) action.part_id1) { selectItem((long) action.part_id2); diff --git a/src/gui/symbol/part_list.hpp b/src/gui/symbol/part_list.hpp index 8f819b66..05b45c60 100644 --- a/src/gui/symbol/part_list.hpp +++ b/src/gui/symbol/part_list.hpp @@ -39,7 +39,7 @@ class SymbolPartList : public wxListCtrl, public SymbolView { void onChangeSymbol(); /// Event handler for changes to the symbol - virtual void onAction(const Action& a); + virtual void onAction(const Action& a, bool undone); protected: /// Get the text of an item diff --git a/src/util/action_stack.cpp b/src/util/action_stack.cpp index b5be3b35..fcbe87a9 100644 --- a/src/util/action_stack.cpp +++ b/src/util/action_stack.cpp @@ -29,7 +29,7 @@ void ActionStack::add(Action* action, bool allow_merge) { if (!action) return; // no action action->perform(false); // TODO: delete action if perform throws redo_actions.clear(); - tellListeners(*action); + tellListeners(*action, false); // try to merge? if (allow_merge && !undo_actions.empty() && undo_actions.back()->merge(action)) { // merged with top undo action @@ -43,6 +43,7 @@ void ActionStack::undo() { assert(canUndo()); Action* action = undo_actions.back(); action->perform(true); + tellListeners(*action, true); // move to redo stack undo_actions.pop_back(); redo_actions.push_back(action); @@ -51,6 +52,7 @@ void ActionStack::redo() { assert(canRedo()); Action* action = redo_actions.back(); action->perform(false); + tellListeners(*action, false); // move to undo stack redo_actions.pop_back(); undo_actions.push_back(action); @@ -103,6 +105,6 @@ void ActionStack::removeListener(ActionListener* listener) { listeners.end() ); } -void ActionStack::tellListeners(const Action& action) { - FOR_EACH(l, listeners) l->onAction(action); +void ActionStack::tellListeners(const Action& action, bool undone) { + FOR_EACH(l, listeners) l->onAction(action, undone); } diff --git a/src/util/action_stack.hpp b/src/util/action_stack.hpp index c249e503..27d5e8b7 100644 --- a/src/util/action_stack.hpp +++ b/src/util/action_stack.hpp @@ -47,7 +47,8 @@ class Action { /// Base class/interface for objects that listen to actions class ActionListener { public: - virtual void onAction(const Action& a) = 0; + /// Notification that an action a has been performed or undone + virtual void onAction(const Action& a, bool undone) = 0; }; // ----------------------------------------------------------------------------- : Action stack @@ -98,7 +99,7 @@ class ActionStack { /// Remove an action listener void removeListener(ActionListener* listener); /// Tell all listeners about an action - void tellListeners(const Action&); + void tellListeners(const Action&, bool undone); private: /// Actions to be undone