e335f4418e7a34850a2cd087c667b8703bec4b40
[ardour.git] / libs / pbd / pbd / functor_command.h
1 /* 
2    Copyright (C) 2007 Paul Davis
3
4         This program is free software; you can redistribute it and/or modify
5         it under the terms of the GNU General Public License as published by
6         the Free Software Foundation; either version 2 of the License, or
7         (at your option) any later version.
8
9         This program is distributed in the hope that it will be useful,
10         but WITHOUT ANY WARRANTY; without even the implied warranty of
11         MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12         GNU General Public License for more details.
13
14         You should have received a copy of the GNU General Public License
15         along with this program; if not, write to the Free Software
16         Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
17
18 */
19
20 #ifndef __lib_pbd_functor_command_h__
21 #define __lib_pbd_functor_command_h__
22
23 #include <iostream>
24 #include <sstream>
25 #include <string>
26 #include <map>
27
28 #include <pbd/xml++.h>
29 #include <pbd/shiva.h>
30 #include <pbd/command.h>
31 #include <pbd/failed_constructor.h>
32
33 /** This command class is initialized 
34  */
35
36 namespace PBD {
37
38 template <class obj_type, class arg_type>
39 class FunctorCommand : public Command
40 {
41         private:
42         typedef void (obj_type::*functor_type)(arg_type);
43         typedef std::map< std::string, functor_type > FunctorMap;
44         typedef typename FunctorMap::iterator FunctorMapIterator;
45
46         public:
47         FunctorCommand(
48                 std::string functor,
49                 obj_type object,
50                 arg_type b,
51                 arg_type a
52         ) : functor_name(functor), 
53                 object(object),
54                 before(b),
55                 after(a) 
56         {
57                 method = find_functor(functor);
58
59                 /* catch destruction of the object */
60                 new PBD::Shiva< obj_type, FunctorCommand<obj_type, arg_type> > (object, *this);
61         }
62
63         ~FunctorCommand() {
64                 GoingAway();
65         }
66
67         void operator() () {
68                 (object.*method) (after);
69         }
70
71         void undo() { 
72                 (object.*method) (before);
73         }
74
75         virtual XMLNode &get_state() {
76                 std::stringstream ss;
77                 
78                 XMLNode *node = new XMLNode("FunctorCommand");
79                 node->add_property("functor", functor_name);
80                 ss << before;
81                 node->add_property("before", ss.str());
82                 ss.clear ();
83                 ss << after;
84                 node->add_property("after", ss.str());
85
86                 return *node;
87         }
88
89         static void register_functor(std::string name, functor_type f) {
90                 functor_map[name] = f;
91         }
92
93         private:
94         static functor_type find_functor(std::string name) {
95                 FunctorMapIterator iter;
96
97                 if((iter = functor_map.find(name)) == functor_map.end()) {
98                         throw failed_constructor();
99                 }
100
101                 return iter->second;
102         }
103
104         protected:
105         std::string functor_name;
106         obj_type &object;
107         arg_type before;
108         arg_type after;
109         functor_type method;
110         static FunctorMap functor_map;
111 };
112
113 // static initialization of functor_map... 
114 template <class obj_type, class arg_type>
115 typename FunctorCommand<obj_type, arg_type>::FunctorMap
116 FunctorCommand<obj_type, arg_type>::functor_map;
117
118 };
119
120 #endif // __lib_pbd_functor_command_h__
121