From 6337a1894cb146fcfba9454c0cb41b6bdb3fced1 Mon Sep 17 00:00:00 2001 From: Hans Fugal Date: Thu, 29 Jun 2006 18:49:03 +0000 Subject: [PATCH] r132@gandalf: fugalh | 2006-06-29 12:45:16 -0600 Coding for undo/redo starts in earnest. Paul and I decided to go with a standard gang of four Command pattern, with serialization. This overcomes the terrible difficulties we were having with static type checking and the sigc++ approach. I'm adding the requirement that each command support undo, simplifying undo/redo. NOTE that an important fallout here is that Command::operator()() is the opposite of the old UndoAction::operator()(), i.e. Command::operator()() is execute/redo, and Command::undo() is undo. This commit is a reworking of the infrastructure, and won't compile until creating Command subclasses for the various commands being performed. That is primarily where you find get_memento and/or calls to add_(undo|redo.*). git-svn-id: svn://localhost/ardour2/branches/undo@655 d708f5d6-7413-0410-9779-e7cbd77b26cf --- libs/pbd3/pbd/command.h | 37 +++++++++++++ libs/pbd3/pbd/serializable.h | 2 +- libs/pbd3/pbd/undo.h | 15 ++--- libs/pbd3/pbd/undo_command.h | 104 ----------------------------------- libs/pbd3/undo.cc | 40 +++++--------- 5 files changed, 59 insertions(+), 139 deletions(-) create mode 100644 libs/pbd3/pbd/command.h delete mode 100644 libs/pbd3/pbd/undo_command.h diff --git a/libs/pbd3/pbd/command.h b/libs/pbd3/pbd/command.h new file mode 100644 index 0000000000..b154c6b148 --- /dev/null +++ b/libs/pbd3/pbd/command.h @@ -0,0 +1,37 @@ +/* + Copyright (C) 2006 Hans Fugal & Paul Davis + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + + $Id: /local/undo/libs/pbd3/pbd/undo.h 80 2006-06-22T22:37:01.079855Z fugalh $ +*/ + +#ifndef __lib_pbd_undo_h__ +#define __lib_pbd_undo_h__ + +#include + +class Command : public Serializable +{ + public: + virtual ~Command(); + virtual void operator() () = 0; + virtual void undo() = 0; + virtual void redo() { (*this)(); } + protected: + Command(); +}; + +#endif diff --git a/libs/pbd3/pbd/serializable.h b/libs/pbd3/pbd/serializable.h index 8032f0038a..c0948b9933 100644 --- a/libs/pbd3/pbd/serializable.h +++ b/libs/pbd3/pbd/serializable.h @@ -26,7 +26,7 @@ class Serializable { public: - XMLNode &serialize(); + virtual XMLNode &serialize() = 0; }; #endif // __lib_pbd_serializable_h__ diff --git a/libs/pbd3/pbd/undo.h b/libs/pbd3/pbd/undo.h index d2ad6088cd..b97c8d9249 100644 --- a/libs/pbd3/pbd/undo.h +++ b/libs/pbd3/pbd/undo.h @@ -27,14 +27,14 @@ #include #include #include -#include +#include using std::string; using std::list; -typedef sigc::slot UndoAction; +typedef Command UndoAction; -class UndoTransaction +class UndoTransaction : public Command { public: UndoTransaction (); @@ -43,12 +43,10 @@ class UndoTransaction void clear (); - void add_undo (const UndoAction&); - void add_redo (const UndoAction&); - void add_redo_no_execute (const UndoAction&); + void add_command (const UndoAction&); + void operator() (); void undo(); - void redo(); void set_name (const string& str) { _name = str; @@ -64,8 +62,7 @@ class UndoTransaction } private: - list redo_actions; - list undo_actions; + list actions; struct timeval _timestamp; string _name; }; diff --git a/libs/pbd3/pbd/undo_command.h b/libs/pbd3/pbd/undo_command.h deleted file mode 100644 index 1c9cac7684..0000000000 --- a/libs/pbd3/pbd/undo_command.h +++ /dev/null @@ -1,104 +0,0 @@ -/* - Copyright (C) 2006 Paul Davis - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - - $Id: /local/undo/libs/pbd3/pbd/undo.h 59 2006-06-15T18:16:20.960977Z fugalh $ -*/ - -#ifndef __lib_pbd_undo_command_h__ -#define __lib_pbd_undo_command_h__ - -#include -#include -#include -#include -#include - -using sigc::nil; -using sigc::slot; -using sigc::bind; -using sigc::mem_fun; -using std::list; -using std::string; - - -/* One of the joys of templates is that you have to do everything right here - * in the header file; you can't split this to make undo_command.cc */ - -template -class UndoCommand -{ - public: - /* It only makes sense to use the constructor corresponding to the - * template given. e.g. - * - * UndoCommand cmd(id, key, foo_instance); - */ - UndoCommand(T_obj &object, string key) - : _obj(object), _key(key) - { - _slot = mem_fun( _obj, get_method(_key) ); - } - UndoCommand(T_obj &object, string key, T1 &arg1) - : _obj(object), _key(key) - { - _slot = bind( mem_fun( _obj, get_method(_key) ), - arg1); - _args.push_back(&arg1); - } - UndoCommand(T_obj &object, string key, T1 &arg1, T2 &arg2) - : _obj(object), _key(key) - { - _slot = bind( mem_fun( _obj, get_method(_key) ), - arg1, arg2); - _args.push_back(&arg1); - _args.push_back(&arg2); - } - UndoCommand(T_obj &object, string key, T1 &arg1, T2 &arg2, T3 &arg3) - : _obj(object), _key(key) - { - _slot = bind( mem_fun( _obj, get_method(_key) ), - arg1, arg2, arg3); - _args.push_back(&arg1); - _args.push_back(&arg2); - _args.push_back(&arg3); - } - UndoCommand(T_obj &object, string key, T1 &arg1, T2 &arg2, T3 &arg3, T4 &arg4) - : _obj(object), _key(key) - { - _slot = bind( mem_fun( _obj, get_method(_key) ), - arg1, arg2, arg4); - _args.push_back(&arg1); - _args.push_back(&arg2); - _args.push_back(&arg3); - _args.push_back(&arg4); - } - - void operator() () { return _slot(); } - - XMLNode &serialize(); - protected: - template T_method &get_method(string); - T_obj &_obj; - string _key; - slot _slot; - - // Note that arguments must be instances of Serializable or this will - // rightly cause a compiler error when compiling the constructor. - list _args; -}; - -#endif // __lib_pbd_undo_command_h__ diff --git a/libs/pbd3/undo.cc b/libs/pbd3/undo.cc index 0aac58effc..0a09ffd1e7 100644 --- a/libs/pbd3/undo.cc +++ b/libs/pbd3/undo.cc @@ -33,8 +33,7 @@ UndoTransaction::UndoTransaction (const UndoTransaction& rhs) { _name = rhs._name; clear (); - undo_actions.insert(undo_actions.end(),rhs.undo_actions.begin(),rhs.undo_actions.end()); - redo_actions.insert(redo_actions.end(),rhs.redo_actions.begin(),rhs.redo_actions.end()); + actions.insert(actions.end(),rhs.actions.begin(),rhs.actions.end()); } UndoTransaction& @@ -43,43 +42,36 @@ UndoTransaction::operator= (const UndoTransaction& rhs) if (this == &rhs) return *this; _name = rhs._name; clear (); - undo_actions.insert(undo_actions.end(),rhs.undo_actions.begin(),rhs.undo_actions.end()); - redo_actions.insert(redo_actions.end(),rhs.redo_actions.begin(),rhs.redo_actions.end()); + actions.insert(actions.end(),rhs.actions.begin(),rhs.actions.end()); return *this; } void -UndoTransaction::add_undo (const UndoAction& action) +UndoTransaction::add_command (const UndoAction& action) { - undo_actions.push_back (action); + actions.push_back (action); } void -UndoTransaction::add_redo (const UndoAction& action) -{ - redo_actions.push_back (action); - redo_actions.back()(); // operator() -} - -void -UndoTransaction::add_redo_no_execute (const UndoAction& action) +UndoTransaction::clear () { - redo_actions.push_back (action); + actions.clear (); } void -UndoTransaction::clear () +UndoTransaction::operator() () { - undo_actions.clear (); - redo_actions.clear (); + for (list::iterator i = actions.begin(); i != actions.end(); ++i) { + (*i)(); + } } void UndoTransaction::undo () { cerr << "Undo " << _name << endl; - for (list::reverse_iterator i = undo_actions.rbegin(); i != undo_actions.rend(); ++i) { - (*i)(); + for (list::reverse_iterator i = actions.rbegin(); i != actions.rend(); ++i) { + i->undo(); } } @@ -87,9 +79,7 @@ void UndoTransaction::redo () { cerr << "Redo " << _name << endl; - for (list::iterator i = redo_actions.begin(); i != redo_actions.end(); ++i) { - (*i)(); - } + (*this)(); } void @@ -119,9 +109,9 @@ UndoHistory::redo (unsigned int n) if (RedoList.size() == 0) { return; } - UndoTransaction trans = RedoList.back (); + UndoTransaction ut = RedoList.back (); RedoList.pop_back (); - trans.redo (); + ut.redo (); UndoList.push_back (trans); } } -- 2.30.2