aboutsummaryrefslogtreecommitdiff
path: root/src/FbTk/Signal.hh
diff options
context:
space:
mode:
Diffstat (limited to 'src/FbTk/Signal.hh')
-rw-r--r--src/FbTk/Signal.hh102
1 files changed, 37 insertions, 65 deletions
diff --git a/src/FbTk/Signal.hh b/src/FbTk/Signal.hh
index 432bb3f..a7b91ba 100644
--- a/src/FbTk/Signal.hh
+++ b/src/FbTk/Signal.hh
@@ -22,7 +22,6 @@
22#ifndef FBTK_SIGNAL_HH 22#ifndef FBTK_SIGNAL_HH
23#define FBTK_SIGNAL_HH 23#define FBTK_SIGNAL_HH
24 24
25#include "RefCount.hh"
26#include "Slot.hh" 25#include "Slot.hh"
27#include <algorithm> 26#include <algorithm>
28#include <list> 27#include <list>
@@ -35,7 +34,7 @@ namespace FbTk {
35namespace SigImpl { 34namespace SigImpl {
36 35
37/** 36/**
38 * Parent class for all \c Signal[0...*] classes. 37 * Parent class for all \c Signal template classes.
39 * It handles the disconnect and holds all the slots. The connect must be 38 * It handles the disconnect and holds all the slots. The connect must be
40 * handled by the child class so it can do the type checking. 39 * handled by the child class so it can do the type checking.
41 */ 40 */
@@ -121,93 +120,66 @@ private:
121 unsigned m_emitting; 120 unsigned m_emitting;
122}; 121};
123 122
124struct EmptyArg {}; 123template <typename Arg1, typename Arg2, typename Arg3>
125 124class SignalTemplate: public SignalHolder {
126} // namespace SigImpl
127
128
129/// Specialization for three arguments.
130template <typename ReturnType,
131 typename Arg1 = SigImpl::EmptyArg, typename Arg2 = SigImpl::EmptyArg, typename Arg3 = SigImpl::EmptyArg >
132class Signal: public SigImpl::SignalHolder {
133public: 125public:
134 void emit(Arg1 arg1, Arg2 arg2, Arg3 arg3) { 126 template<typename Functor>
127 SlotID connect(const Functor& functor) {
128 return SignalHolder::connect(SlotPtr( new Slot<Arg1, Arg2, Arg3, Functor>(functor) ));
129 }
130
131protected:
132 void emit_(Arg1 arg1, Arg2 arg2, Arg3 arg3) {
135 begin_emitting(); 133 begin_emitting();
136 for ( Iterator it = begin(); it != end(); ++it ) { 134 for ( Iterator it = begin(); it != end(); ++it ) {
137 if(*it) 135 if(*it)
138 static_cast<SigImpl::SlotBase3<ReturnType, Arg1, Arg2, Arg3> &>(**it)(arg1, arg2, arg3); 136 static_cast<SigImpl::SlotTemplate<Arg1, Arg2, Arg3> &>(**it)(arg1, arg2, arg3);
139 } 137 }
140 end_emitting(); 138 end_emitting();
141 } 139 }
140};
142 141
143 template<typename Functor> 142} // namespace SigImpl
144 SlotID connect(const Functor& functor) { 143
145 return SignalHolder::connect(SlotPtr( 144
146 new SigImpl::Slot3<ReturnType, Arg1, Arg2, Arg3, Functor>(functor) 145/// Base template for three arguments.
147 )); 146template <typename Arg1 = SigImpl::EmptyArg, typename Arg2 = SigImpl::EmptyArg, typename Arg3 = SigImpl::EmptyArg >
148 } 147class Signal: public SigImpl::SignalTemplate<Arg1, Arg2, Arg3> {
148public:
149 void emit(Arg1 arg1, Arg2 arg2, Arg3 arg3)
150 { SigImpl::SignalTemplate<Arg1, Arg2, Arg3>::emit_(arg1, arg2, arg3); }
149}; 151};
150 152
151/// Specialization for two arguments. 153/// Specialization for two arguments.
152template <typename ReturnType, typename Arg1, typename Arg2> 154template <typename Arg1, typename Arg2>
153class Signal<ReturnType, Arg1, Arg2, SigImpl::EmptyArg>: public SigImpl::SignalHolder { 155class Signal<Arg1, Arg2, SigImpl::EmptyArg>:
156 public SigImpl::SignalTemplate<Arg1, Arg2, SigImpl::EmptyArg> {
154public: 157public:
155 void emit(Arg1 arg1, Arg2 arg2) { 158 void emit(Arg1 arg1, Arg2 arg2) {
156 begin_emitting(); 159 SigImpl::SignalTemplate<Arg1, Arg2, SigImpl::EmptyArg>::
157 for ( Iterator it = begin(); it != end(); ++it ) { 160 emit_(arg1, arg2, SigImpl::EmptyArg());
158 if(*it)
159 static_cast<SigImpl::SlotBase2<ReturnType, Arg1, Arg2> &>(**it)(arg1, arg2);
160 }
161 end_emitting();
162 }
163
164 template<typename Functor>
165 SlotID connect(const Functor& functor) {
166 return SignalHolder::connect(SlotPtr(
167 new SigImpl::Slot2<ReturnType, Arg1, Arg2, Functor>(functor)
168 ));
169 } 161 }
170}; 162};
171 163
172/// Specialization for one argument. 164/// Specialization for one argument.
173template <typename ReturnType, typename Arg1> 165template <typename Arg1>
174class Signal<ReturnType, Arg1, SigImpl::EmptyArg, SigImpl::EmptyArg>: public SigImpl::SignalHolder { 166class Signal<Arg1, SigImpl::EmptyArg, SigImpl::EmptyArg>:
167 public SigImpl::SignalTemplate<Arg1, SigImpl::EmptyArg, SigImpl::EmptyArg> {
175public: 168public:
176 void emit(Arg1 arg) { 169 void emit(Arg1 arg1) {
177 begin_emitting(); 170 SigImpl::SignalTemplate<Arg1, SigImpl::EmptyArg, SigImpl::EmptyArg>
178 for ( Iterator it = begin(); it != end(); ++it ) { 171 ::emit_(arg1, SigImpl::EmptyArg(), SigImpl::EmptyArg());
179 if(*it)
180 static_cast<SigImpl::SlotBase1<ReturnType, Arg1> &>(**it)(arg);
181 }
182 end_emitting();
183 }
184
185 template<typename Functor>
186 SlotID connect(const Functor& functor) {
187 return SignalHolder::connect(SlotPtr(
188 new SigImpl::Slot1<ReturnType, Arg1, Functor>(functor)
189 ));
190 } 172 }
191}; 173};
192 174
193/// Specialization for no arguments. 175/// Specialization for no arguments.
194template <typename ReturnType> 176template <>
195class Signal<ReturnType, SigImpl::EmptyArg, SigImpl::EmptyArg, SigImpl::EmptyArg>: public SigImpl::SignalHolder { 177class Signal<SigImpl::EmptyArg, SigImpl::EmptyArg, SigImpl::EmptyArg>:
178 public SigImpl::SignalTemplate<SigImpl::EmptyArg, SigImpl::EmptyArg, SigImpl::EmptyArg> {
196public: 179public:
197 void emit() { 180 void emit() {
198 begin_emitting(); 181 SigImpl::SignalTemplate<SigImpl::EmptyArg, SigImpl::EmptyArg, SigImpl::EmptyArg>
199 for ( Iterator it = begin(); it != end(); ++it ) { 182 ::emit_(SigImpl::EmptyArg(), SigImpl::EmptyArg(), SigImpl::EmptyArg());
200 if(*it)
201 static_cast<SigImpl::SlotBase0<ReturnType> &>(**it)();
202 }
203 end_emitting();
204 }
205
206 template<typename Functor>
207 SlotID connect(const Functor& functor) {
208 return SignalHolder::connect(SlotPtr(
209 new SigImpl::Slot0<ReturnType, Functor>(functor)
210 ));
211 } 183 }
212}; 184};
213 185