summaryrefslogtreecommitdiff
path: root/libs/pbd
diff options
context:
space:
mode:
authorDavid Robillard <d@drobilla.net>2006-08-10 01:22:45 +0000
committerDavid Robillard <d@drobilla.net>2006-08-10 01:22:45 +0000
commitab6f1ed9bafa869648b6e94ee5186ff317b32c3e (patch)
treed61dba7f9b6f1ae755803afc4b79bcff06a36005 /libs/pbd
parent38c7d34d8c449c7ce5f7da9575c24e60c6b31b1a (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/SConscript1
-rw-r--r--libs/pbd/command.cc10
-rw-r--r--libs/pbd/id.cc8
-rw-r--r--libs/pbd/pbd/command.h37
-rw-r--r--libs/pbd/pbd/id.h1
-rw-r--r--libs/pbd/pbd/memento_command.h99
-rw-r--r--libs/pbd/pbd/undo.h29
-rw-r--r--libs/pbd/undo.cc88
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;
+}