diff options
author | David Robillard <d@drobilla.net> | 2006-08-10 01:22:45 +0000 |
---|---|---|
committer | David Robillard <d@drobilla.net> | 2006-08-10 01:22:45 +0000 |
commit | ab6f1ed9bafa869648b6e94ee5186ff317b32c3e (patch) | |
tree | d61dba7f9b6f1ae755803afc4b79bcff06a36005 /libs/pbd | |
parent | 38c7d34d8c449c7ce5f7da9575c24e60c6b31b1a (diff) |
Merged with trunk R776
git-svn-id: svn://localhost/ardour2/branches/midi@777 d708f5d6-7413-0410-9779-e7cbd77b26cf
Diffstat (limited to 'libs/pbd')
-rw-r--r-- | libs/pbd/SConscript | 1 | ||||
-rw-r--r-- | libs/pbd/command.cc | 10 | ||||
-rw-r--r-- | libs/pbd/id.cc | 8 | ||||
-rw-r--r-- | libs/pbd/pbd/command.h | 37 | ||||
-rw-r--r-- | libs/pbd/pbd/id.h | 1 | ||||
-rw-r--r-- | libs/pbd/pbd/memento_command.h | 99 | ||||
-rw-r--r-- | libs/pbd/pbd/undo.h | 29 | ||||
-rw-r--r-- | libs/pbd/undo.cc | 88 |
8 files changed, 224 insertions, 49 deletions
diff --git a/libs/pbd/SConscript b/libs/pbd/SConscript index 36fb02885f..4b15dd70d1 100644 --- a/libs/pbd/SConscript +++ b/libs/pbd/SConscript @@ -21,6 +21,7 @@ pbd_files = Split(""" basename.cc base_ui.cc convert.cc +command.cc controllable.cc dmalloc.cc error.cc diff --git a/libs/pbd/command.cc b/libs/pbd/command.cc new file mode 100644 index 0000000000..5b41691c07 --- /dev/null +++ b/libs/pbd/command.cc @@ -0,0 +1,10 @@ +#include <pbd/command.h> +#include <pbd/xml++.h> + + +XMLNode &Command::get_state() +{ + XMLNode *node = new XMLNode ("Command"); + node->add_content("WARNING: Somebody forgot to subclass Command."); + return *node; +} diff --git a/libs/pbd/id.cc b/libs/pbd/id.cc index f9afa72c98..0de0d052c3 100644 --- a/libs/pbd/id.cc +++ b/libs/pbd/id.cc @@ -8,6 +8,7 @@ #include <inttypes.h> #include <pbd/id.h> +#include <string> using namespace std; using namespace PBD; @@ -45,6 +46,13 @@ ID::print (char* buf) const snprintf (buf, 16, "%" PRIu64, id); } +string ID::to_s() const +{ + char buf[16]; // see print() + print(buf); + return string(buf); +} + ID& ID::operator= (string str) { diff --git a/libs/pbd/pbd/command.h b/libs/pbd/pbd/command.h new file mode 100644 index 0000000000..cd9bf0e08a --- /dev/null +++ b/libs/pbd/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_command_h__ +#define __lib_pbd_command_h__ + +#include <pbd/stateful.h> + +class Command : public Stateful +{ + public: + virtual ~Command() {} + virtual void operator() () = 0; + virtual void undo() = 0; + virtual void redo() { (*this)(); } + virtual XMLNode &get_state(); + virtual int set_state(const XMLNode&) { /* noop */ return 0; } +}; + +#endif // __lib_pbd_command_h_ diff --git a/libs/pbd/pbd/id.h b/libs/pbd/pbd/id.h index 9a3f10478d..1ce448d58b 100644 --- a/libs/pbd/pbd/id.h +++ b/libs/pbd/pbd/id.h @@ -28,6 +28,7 @@ class ID { } void print (char* buf) const; + std::string to_s() const; static uint64_t counter() { return _counter; } static void init_counter (uint64_t val) { _counter = val; } diff --git a/libs/pbd/pbd/memento_command.h b/libs/pbd/pbd/memento_command.h new file mode 100644 index 0000000000..46c724e9ea --- /dev/null +++ b/libs/pbd/pbd/memento_command.h @@ -0,0 +1,99 @@ +/* + 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 132 2006-06-29T18:45:16.609763Z fugalh $ +*/ + +#ifndef __lib_pbd_memento_command_h__ +#define __lib_pbd_memento_command_h__ + +#include <pbd/command.h> +#include <pbd/xml++.h> +#include <sigc++/slot.h> + +/** This command class is initialized with before and after mementos + * (from Stateful::get_state()), so undo becomes restoring the before + * memento, and redo is restoring the after memento. + */ +template <class obj_T> +class MementoCommand : public Command +{ + public: + MementoCommand(obj_T &obj, + XMLNode &before, + XMLNode &after + ) + : obj(obj), before(before), after(after) {} + void operator() () { obj.set_state(after); } + void undo() { obj.set_state(before); } + virtual XMLNode &get_state() + { + XMLNode *node = new XMLNode("MementoCommand"); + node->add_property("obj_id", obj.id().to_s()); + node->add_child_nocopy(before); + node->add_child_nocopy(after); + return *node; + } + // TODO does this need a copy constructor? + protected: + obj_T &obj; + XMLNode &before, &after; +}; + +template <class obj_T> +class MementoUndoCommand : public Command +{ +public: + MementoUndoCommand(obj_T &obj, + XMLNode &before) + : obj(obj), before(before) {} + void operator() () { /* noop */ } + void undo() { obj.set_state(before); } + virtual XMLNode &get_state() + { + XMLNode *node = new XMLNode("MementoUndoCommand"); + node->add_property("obj_id", obj.id().to_s()); + node->add_child_nocopy(before); + return *node; + } +protected: + obj_T &obj; + XMLNode &before; +}; + +template <class obj_T> +class MementoRedoCommand : public Command +{ +public: + MementoRedoCommand(obj_T &obj, + XMLNode &after) + : obj(obj), after(after) {} + void operator() () { obj.set_state(after); } + void undo() { /* noop */ } + virtual XMLNode &get_state() + { + XMLNode *node = new XMLNode("MementoRedoCommand"); + node->add_property("obj_id", obj.id().to_s()); + node->add_child_nocopy(after); + return *node; + } +protected: + obj_T &obj; + XMLNode &after; +}; + +#endif // __lib_pbd_memento_h__ diff --git a/libs/pbd/pbd/undo.h b/libs/pbd/pbd/undo.h index f067635ed3..724e86aaa0 100644 --- a/libs/pbd/pbd/undo.h +++ b/libs/pbd/pbd/undo.h @@ -23,29 +23,33 @@ #include <string> #include <list> +#include <map> #include <sigc++/slot.h> +#include <sigc++/bind.h> #include <sys/time.h> +#include <pbd/command.h> using std::string; using std::list; typedef sigc::slot<void> UndoAction; -class UndoCommand +class UndoTransaction : public Command { public: - UndoCommand (); - UndoCommand (const UndoCommand&); - UndoCommand& operator= (const UndoCommand&); + UndoTransaction (); + UndoTransaction (const UndoTransaction&); + UndoTransaction& operator= (const UndoTransaction&); void clear (); - void add_undo (const UndoAction&); - void add_redo (const UndoAction&); - void add_redo_no_execute (const UndoAction&); + void add_command (Command *const); + void operator() (); void undo(); void redo(); + + XMLNode &get_state(); void set_name (const string& str) { _name = str; @@ -61,8 +65,7 @@ class UndoCommand } private: - list<UndoAction> redo_actions; - list<UndoAction> undo_actions; + list<Command*> actions; struct timeval _timestamp; string _name; }; @@ -73,7 +76,7 @@ class UndoHistory UndoHistory() {} ~UndoHistory() {} - void add (UndoCommand uc); + void add (UndoTransaction ut); void undo (unsigned int n); void redo (unsigned int n); @@ -87,9 +90,11 @@ class UndoHistory void clear_undo (); void clear_redo (); + XMLNode &get_state(); + void save_state(); private: - list<UndoCommand> UndoList; - list<UndoCommand> RedoList; + list<UndoTransaction> UndoList; + list<UndoTransaction> RedoList; }; diff --git a/libs/pbd/undo.cc b/libs/pbd/undo.cc index f2f11b1c5c..8d1b416c16 100644 --- a/libs/pbd/undo.cc +++ b/libs/pbd/undo.cc @@ -21,81 +21,84 @@ #include <iostream> #include <pbd/undo.h> +#include <pbd/xml++.h> +#include <string> using namespace std; using namespace sigc; -UndoCommand::UndoCommand () +UndoTransaction::UndoTransaction () { } -UndoCommand::UndoCommand (const UndoCommand& rhs) +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()); } -UndoCommand& -UndoCommand::operator= (const UndoCommand& rhs) +UndoTransaction& +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 -UndoCommand::add_undo (const UndoAction& action) +UndoTransaction::add_command (Command *const action) { - undo_actions.push_back (action); + actions.push_back (action); } void -UndoCommand::add_redo (const UndoAction& action) +UndoTransaction::clear () { - redo_actions.push_back (action); - redo_actions.back()(); // operator() + actions.clear (); } void -UndoCommand::add_redo_no_execute (const UndoAction& action) +UndoTransaction::operator() () { - redo_actions.push_back (action); -} - -void -UndoCommand::clear () -{ - undo_actions.clear (); - redo_actions.clear (); + for (list<Command*>::iterator i = actions.begin(); i != actions.end(); ++i) { + (*(*i))(); + } } void -UndoCommand::undo () +UndoTransaction::undo () { cerr << "Undo " << _name << endl; - for (list<UndoAction>::reverse_iterator i = undo_actions.rbegin(); i != undo_actions.rend(); ++i) { - (*i)(); + for (list<Command*>::reverse_iterator i = actions.rbegin(); i != actions.rend(); ++i) { + (*i)->undo(); } } void -UndoCommand::redo () +UndoTransaction::redo () { cerr << "Redo " << _name << endl; - for (list<UndoAction>::iterator i = redo_actions.begin(); i != redo_actions.end(); ++i) { - (*i)(); - } + (*this)(); +} + +XMLNode &UndoTransaction::get_state() +{ + XMLNode *node = new XMLNode ("UndoTransaction"); + + list<Command*>::iterator it; + for (it=actions.begin(); it!=actions.end(); it++) + node->add_child_nocopy((*it)->get_state()); + + return *node; } void -UndoHistory::add (UndoCommand uc) +UndoHistory::add (UndoTransaction ut) { - UndoList.push_back (uc); + UndoList.push_back (ut); } void @@ -105,10 +108,10 @@ UndoHistory::undo (unsigned int n) if (UndoList.size() == 0) { return; } - UndoCommand uc = UndoList.back (); + UndoTransaction ut = UndoList.back (); UndoList.pop_back (); - uc.undo (); - RedoList.push_back (uc); + ut.undo (); + RedoList.push_back (ut); } } @@ -119,10 +122,10 @@ UndoHistory::redo (unsigned int n) if (RedoList.size() == 0) { return; } - UndoCommand cmd = RedoList.back (); + UndoTransaction ut = RedoList.back (); RedoList.pop_back (); - cmd.redo (); - UndoList.push_back (cmd); + ut.redo (); + UndoList.push_back (ut); } } @@ -144,3 +147,14 @@ UndoHistory::clear () RedoList.clear (); UndoList.clear (); } + +XMLNode & UndoHistory::get_state() +{ + XMLNode *node = new XMLNode ("UndoHistory"); + + list<UndoTransaction>::iterator it; + for (it=UndoList.begin(); it != UndoList.end(); it++) + node->add_child_nocopy(it->get_state()); + + return *node; +} |