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