]> git.tdb.fi Git - libs/gltk.git/blob - source/connector.h
Rework how widget ownership works in Container
[libs/gltk.git] / source / connector.h
1 #ifndef MSP_GLTK_CONNECTOR_H_
2 #define MSP_GLTK_CONNECTOR_H_
3
4 #include <map>
5 #include <string>
6 #include <sigc++/functors/mem_fun.h>
7
8 namespace Msp {
9 namespace GLtk {
10
11 class Connector;
12 class Logic;
13 class Widget;
14
15 class ConnAction
16 {
17 public:
18         virtual void connect(Connector &conn, Widget &wdg, const std::string &data) const =0;
19         virtual ~ConnAction() { }
20 };
21
22 template<typename C, typename W>
23 class ConnFunc0: public ConnAction
24 {
25 public:
26         typedef void (C::*FuncType)(W &);
27
28         ConnFunc0(FuncType f): func(f) { }
29         virtual void connect(Connector &conn, Widget &wdg, const std::string &) const
30         {
31                 (dynamic_cast<C &>(conn).*func)(dynamic_cast<W &>(wdg));
32         }
33
34 private:
35         FuncType func;
36 };
37
38 template<typename C, typename W>
39 class ConnFunc1: public ConnAction
40 {
41 public:
42         typedef void (C::*FuncType)(W &, const std::string &);
43
44         ConnFunc1(FuncType f): func(f) { }
45         virtual void connect(Connector &conn, Widget &wdg, const std::string &data) const
46         {
47                 (dynamic_cast<C &>(conn).*func)(dynamic_cast<W &>(wdg), data);
48         }
49
50 private:
51         FuncType func;
52 };
53
54 template<typename C, typename W, typename S, typename F>
55 class ConnSignal: public ConnAction
56 {
57 public:
58         ConnSignal(S W::*s, F f): signal(s), func(f) { }
59         virtual void connect(Connector &conn, Widget &wdg, const std::string &) const
60         {
61                 (dynamic_cast<W &>(wdg).*signal).connect(sigc::mem_fun(&dynamic_cast<C &>(conn).get_object(), func));
62         }
63
64 private:
65         S W::*signal;
66         F func;
67 };
68
69 /**
70 Provides an interface for associating the bindings stored in a Logic object
71 with actual code.  Derive a class from this and use the add functions to
72 specify handlers for each binding type.
73
74 Bindings are normally handled by member functions of the Connector class.  The
75 function must take a reference to a widget (of any type) as its first parameter.
76 If it takes a second parameter, the binding data is passed in as well.
77
78 As a shortcut for simple connections, signals of widgets can be connected
79 directly to a handler object.  For this to work, the Connector class must be a
80 public inner class of the handler class and it must have a get_object() member
81 function returning a reference to the handler object.
82
83 TODO: lexical_cast the binding data (requires working around references)
84 */
85 class Connector
86 {
87 private:
88         std::map<std::string, ConnAction *> actions;
89
90 protected:
91         Connector() { }
92 public:
93         virtual ~Connector();
94
95         /**
96         Processes all bindings in the Logic object and calls appropriate handlers.
97         */
98         void connect(const Logic &);
99
100 protected:
101         /**
102         Adds a handler function for a binding.
103         */
104         template<typename C, typename W>
105         void add(const std::string &type, void (C::*func)(W &))
106         { add(type, new ConnFunc0<C, W>(func)); }
107
108         /**
109         Adds a handler function for a binding.  The binding data is passed in the
110         second parameter.
111         */
112         template<typename C, typename W>
113         void add(const std::string &type, void (C::*func)(W &, const std::string &))
114         { add(type, new ConnFunc1<C, W>(func)); }
115
116         /**
117         Adds a signal connector for a binding.
118         */
119         template<typename W, typename S, typename H, typename F>
120         void add(const std::string &type, S W::*signal, F H::*func)
121         { add(type, new ConnSignal<typename H::Connector, W, S, F H::*>(signal, func)); }
122
123 private:
124         void add(const std::string &, ConnAction *);
125 };
126
127 } // namespace GLtk
128 } // namespace Msp
129
130 #endif