summaryrefslogtreecommitdiff
path: root/src/FbTk/Slot.hh
diff options
context:
space:
mode:
Diffstat (limited to 'src/FbTk/Slot.hh')
-rw-r--r--src/FbTk/Slot.hh294
1 files changed, 294 insertions, 0 deletions
diff --git a/src/FbTk/Slot.hh b/src/FbTk/Slot.hh
new file mode 100644
index 0000000..ba3cfc4
--- /dev/null
+++ b/src/FbTk/Slot.hh
@@ -0,0 +1,294 @@
1// Slot.hh for FbTk, Fluxbox Toolkit
2// Copyright (c) 2008 Henrik Kinnunen (fluxgen at fluxbox dot org)
3//
4// Permission is hereby granted, free of charge, to any person obtaining a
5// copy of this software and associated documentation files (the "Software"),
6// to deal in the Software without restriction, including without limitation
7// the rights to use, copy, modify, merge, publish, distribute, sublicense,
8// and/or sell copies of the Software, and to permit persons to whom the
9// Software is furnished to do so, subject to the following conditions:
10//
11// The above copyright notice and this permission notice shall be included in
12// all copies or substantial portions of the Software.
13//
14// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
17// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
19// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
20// DEALINGS IN THE SOFTWARE.
21
22#ifndef FBTK_SLOT_HH
23#define FBTK_SLOT_HH
24
25namespace FbTk {
26
27/// \namespace Implementation details for signals, do not use anything in this namespace
28namespace SigImpl {
29
30class CallbackHolder;
31
32/// Placeholder type for typed callbacks
33typedef void* (*CallbackFunc)(void *);
34/// Clone function callback type for cloning typed callback holders
35typedef CallbackHolder* (*CloneFunc)(CallbackHolder*);
36/// Kill function callback type for destroying type specific information in
37/// FunctorHolder
38typedef void (*KillFunc)(CallbackHolder*);
39
40/// Holds clone, functor callback, and the kill function for FunctorHolder.
41class CallbackHolder {
42public:
43 /**
44 * @param callback The callback to call when a slot receives a signal.
45 * @param clone The callback to use for cloning a type specific instance of
46 * this classinstance.
47 * @param kill The callback that knows how to free the memory in type
48 * specific instance of this class.
49 */
50 CallbackHolder(CallbackFunc callback,
51 CloneFunc clone,
52 KillFunc kill):
53 m_callback(callback),
54 m_kill(kill),
55 m_clone(clone) { }
56
57 ~CallbackHolder() {
58 (*m_kill)(this);
59 }
60
61 /// @return a clone of this instance
62 CallbackHolder* clone() {
63 return (*m_clone)(this);
64 }
65
66 /// \c Callback to \c Functor specific callback
67 CallbackFunc m_callback;
68
69protected:
70
71 CallbackHolder& operator = (const CallbackHolder& other) {
72 if ( this == &other ) {
73 return *this;
74 }
75 m_callback = other.m_callback;
76 m_clone = other.m_clone;
77 m_kill = other.m_kill;
78
79 return *this;
80 }
81
82 CallbackHolder(const CallbackHolder& other) {
83 *this = other;
84 }
85
86private:
87 /// This function is called to kill this instance
88 KillFunc m_kill;
89 /// Functions that knows how to clone a specific \c Functor type
90 CloneFunc m_clone;
91};
92
93
94/// Holds the functor and creates a clone callback for \c Functor specific type
95template <typename Functor>
96class FunctorHolder: public CallbackHolder {
97public:
98 /// This type.
99 typedef FunctorHolder<Functor> Self;
100 /**
101 * @param functor The functor to be used when a signal is emitted.
102 * @param callback The callback to call when a signal is emitted.
103 */
104 FunctorHolder(const Functor& functor, CallbackFunc callback):
105 CallbackHolder(callback, &clone, &kill),
106 m_functor(functor) {
107 }
108
109 /// Specific clone for this Functor type
110 static CallbackHolder* clone(CallbackHolder* self) {
111 return new Self( static_cast<Self&>(*self));
112 }
113
114 static void kill(CallbackHolder* self) {
115 // Destroy functor
116 static_cast<Self*>( self )->m_functor.~Functor();
117 }
118
119 Functor m_functor; ///< the functor to use when a signal is emitted.
120};
121
122
123
124/// Callback with no arguments.
125template <typename Functor, typename ReturnType >
126struct Callback0 {
127 static ReturnType callback(CallbackHolder* base) {
128 static_cast< FunctorHolder<Functor>* >( base )->m_functor();
129 return ReturnType();
130 }
131
132 static CallbackFunc functionAddress() {
133 return reinterpret_cast<CallbackFunc>(&callback);
134 }
135};
136
137/// Callback with one argument
138template <typename Functor, typename ReturnType, typename Arg1>
139struct Callback1 {
140 typedef ReturnType (Functor::* CallbackType)(CallbackHolder*, Arg1);
141
142 static ReturnType callback(CallbackHolder* base, Arg1 arg1) {
143 static_cast< FunctorHolder<Functor>* >( base )->m_functor(arg1);
144 return ReturnType();
145 }
146
147 static CallbackFunc functionAddress() {
148 return reinterpret_cast<CallbackFunc>(&callback);
149 }
150};
151
152/// Callback with two arguments
153template <typename Functor, typename ReturnType,
154 typename Arg1, typename Arg2>
155struct Callback2 {
156 typedef ReturnType (Functor::* CallbackType)(CallbackHolder*, Arg1, Arg2);
157
158 static ReturnType callback(CallbackHolder* base, Arg1 arg1, Arg2 arg2) {
159 static_cast< FunctorHolder<Functor>* >( base )->m_functor(arg1, arg2);
160 return ReturnType();
161 }
162
163 static CallbackFunc functionAddress() {
164 return reinterpret_cast<CallbackFunc>(&callback);
165 }
166};
167
168/// Callback with three arguments
169template <typename Functor, typename ReturnType,
170 typename Arg1, typename Arg2, typename Arg3>
171struct Callback3 {
172 typedef ReturnType (Functor::* CallbackType)(CallbackHolder*, Arg1, Arg2, Arg3);
173
174 static ReturnType callback(CallbackHolder* base, Arg1 arg1, Arg2 arg2, Arg3 arg3) {
175 static_cast< FunctorHolder<Functor>* >( base )->m_functor( arg1, arg2, arg3 );
176 return ReturnType();
177 }
178
179 static CallbackFunc functionAddress() {
180 return reinterpret_cast<CallbackFunc>(&callback);
181 }
182};
183
184/// Holds callback holder and handles the copying of callback holders for the
185/// \c Slots.
186class SlotHolder {
187public:
188 SlotHolder(const SlotHolder& other):
189 m_holder( other.m_holder ? other.m_holder->clone() : 0 ) {
190 }
191
192 ~SlotHolder() {
193 delete m_holder;
194 }
195
196 SlotHolder& operator = (const SlotHolder& other) {
197 if ( &other == this ) {
198 return *this;
199 }
200 delete m_holder;
201 if ( other.m_holder ) {
202 m_holder = other.m_holder->clone();
203 } else {
204 m_holder = 0;
205 }
206 return *this;
207 }
208
209 SlotHolder():m_holder( 0 ) { }
210
211protected:
212 explicit SlotHolder(CallbackHolder* holder):
213 m_holder( holder ) {
214 }
215
216 CallbackHolder* m_holder;
217};
218
219/// Slot with no argument.
220template <typename ReturnType>
221class Slot0: public SlotHolder {
222public:
223 typedef ReturnType (*CallbackType)(CallbackHolder*);
224
225 template <typename Functor>
226 Slot0( const Functor& functor ):
227 SlotHolder( new FunctorHolder<Functor>
228 (functor, Callback0<Functor, ReturnType>::functionAddress())) {
229 }
230
231 void operator()() {
232 reinterpret_cast<CallbackType>(m_holder->m_callback)( m_holder );
233 }
234};
235
236/// Slot with one argument.
237template <typename ReturnType, typename Arg1>
238class Slot1:public SlotHolder {
239public:
240 typedef ReturnType (*CallbackType)(CallbackHolder*, Arg1);
241
242 template <typename Functor>
243 Slot1( const Functor& functor ):
244 SlotHolder( new FunctorHolder<Functor>
245 (functor, Callback1<Functor, ReturnType, Arg1>::functionAddress())){
246
247 }
248
249 void operator()(Arg1 arg) {
250 reinterpret_cast<CallbackType>(m_holder->m_callback)(m_holder, arg);
251 }
252
253};
254
255/// Slot with two arguments
256template <typename ReturnType, typename Arg1, typename Arg2>
257class Slot2: public SlotHolder {
258public:
259 typedef ReturnType (*CallbackType)(CallbackHolder*, Arg1, Arg2);
260 template <typename Functor>
261 Slot2( const Functor& functor ):
262 SlotHolder( new FunctorHolder<Functor>
263 (functor, Callback2<Functor, ReturnType, Arg1, Arg2>::functionAddress())){
264
265 }
266
267 void operator()(Arg1 arg1, Arg2 arg2) {
268 reinterpret_cast<CallbackType>(m_holder->m_callback)(m_holder, arg1, arg2);
269 }
270};
271
272/// Slot with three arguments
273template <typename ReturnType, typename Arg1, typename Arg2, typename Arg3>
274class Slot3: public SlotHolder {
275public:
276 typedef ReturnType (*CallbackType)(CallbackHolder*, Arg1, Arg2, Arg3);
277 template <typename Functor>
278 Slot3( const Functor& functor ):
279 SlotHolder( new FunctorHolder<Functor>
280 (functor, Callback3<Functor, ReturnType, Arg1, Arg2, Arg3>::functionAddress())){
281
282 }
283
284 void operator()(Arg1 arg1, Arg2 arg2, Arg3 arg3) {
285 reinterpret_cast<CallbackType>(m_holder->m_callback)
286 ( m_holder, arg1, arg2, arg3 );
287 }
288};
289
290} // namespace SigImpl
291
292} // namespace FbTk
293
294#endif // FBTK_SLOT_H