6cca13209f9c33b436c76f3ac139fcd07c659eed
[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/libpbd_visibility.h"
29 #include "pbd/xml++.h"
30 #include "pbd/shiva.h"
31 #include "pbd/command.h"
32 #include "pbd/failed_constructor.h"
33
34 /** This command class is initialized 
35  */
36
37 namespace PBD {
38
39 template <class obj_type, class arg_type>
40 class /*LIBPBD_API*/ FunctorCommand : public Command
41 {
42         private:
43         typedef void (obj_type::*functor_type)(arg_type);
44         typedef std::map< std::string, functor_type > FunctorMap;
45         typedef typename FunctorMap::iterator FunctorMapIterator;
46
47         public:
48         FunctorCommand(std::string functor, obj_type& object, arg_type b, arg_type a) 
49                 : functor_name(functor)
50                 , object(object)
51                 , before(b)
52                 , after(a) 
53         {
54                 method = find_functor(functor);
55
56                 /* catch destruction of the object */
57                 new PBD::Shiva< obj_type, FunctorCommand<obj_type, arg_type> > (object, *this);
58         }
59
60         ~FunctorCommand() {
61                 GoingAway();
62         }
63
64         void operator() () {
65                 (object.*method) (after);
66         }
67
68         void undo() { 
69                 (object.*method) (before);
70         }
71
72         virtual XMLNode &get_state() {
73                 std::stringstream ss;
74                 
75                 XMLNode *node = new XMLNode("FunctorCommand");
76                 node->add_property("type_name", typeid(obj_type).name());
77                 node->add_property("functor", functor_name);
78                 ss << before;
79                 node->add_property("before", ss.str());
80                 ss.clear ();
81                 ss << after;
82                 node->add_property("after", ss.str());
83
84                 return *node;
85         }
86
87         static void register_functor(std::string name, functor_type f) {
88                 functor_map[name] = f;
89         }
90
91         private:
92         static functor_type find_functor(std::string name) {
93                 FunctorMapIterator iter;
94
95                 if((iter = functor_map.find(name)) == functor_map.end()) {
96                         throw failed_constructor();
97                 }
98
99                 return iter->second;
100         }
101
102         protected:
103         std::string functor_name;
104         obj_type &object;
105         arg_type before;
106         arg_type after;
107         functor_type method;
108         static FunctorMap functor_map;
109 };
110
111 // static initialization of functor_map... 
112 template <class obj_type, class arg_type>
113 typename FunctorCommand<obj_type, arg_type>::FunctorMap
114 FunctorCommand<obj_type, arg_type>::functor_map;
115
116 };
117
118 #endif // __lib_pbd_functor_command_h__
119