Delegate.h
1/*
2 Copyright (C) 2005 by Dr. Marc Boris Duerner
3
4 This library is free software; you can redistribute it and/or
5 modify it under the terms of the GNU Lesser General Public
6 License as published by the Free Software Foundation; either
7 version 2.1 of the License, or (at your option) any later version.
8
9 As a special exception, you may use this file as part of a free
10 software library without restriction. Specifically, if other files
11 instantiate templates or use macros or inline functions from this
12 file, or you compile this file and link it with other files to
13 produce an executable, this file does not by itself cause the
14 resulting executable to be covered by the GNU General Public
15 License. This exception does not however invalidate any other
16 reasons why the executable file might be covered by the GNU Library
17 General Public License.
18
19 This library is distributed in the hope that it will be useful,
20 but WITHOUT ANY WARRANTY; without even the implied warranty of
21 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
22 Lesser General Public License for more details.
23
24 You should have received a copy of the GNU Lesser General Public
25 License along with this library; if not, write to the:
26 Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
27 Boston, MA 02110-1301 USA
28*/
29
30#ifndef Pt_Delegate_h
31#define Pt_Delegate_h
32
33#include <Pt/Void.h>
34#include <Pt/Slot.h>
35#include <Pt/Function.h>
36#include <Pt/Method.h>
37#include <Pt/ConstMethod.h>
38#include <Pt/Connectable.h>
39#include <stdexcept>
40
41namespace Pt {
42
43class DelegateBase : public Connectable
44{
45 public:
46 DelegateBase()
47 { }
48
49 DelegateBase(const DelegateBase& rhs)
50 { DelegateBase::operator=(rhs); }
51
52 DelegateBase& operator=(const DelegateBase& other)
53 {
54 _target.close();
55
56 if( other._target.isValid() )
57 {
58 const Slot* slot = other._target.slot();
59 _target = Connection( *this, slot->clone() );
60 }
61
62 return *this;
63 }
64
67 bool isConnected() const
68 {
69 return _target.isValid();
70 }
71
72 virtual void onConnectionOpen(const Connection& c)
73 {
74 const Connectable* sender = c.sender();
75
76 if( sender == this )
77 {
78 _target.close();
79 _target = c;
80 }
81
82 Connectable::onConnectionOpen(c);
83 }
84
85 virtual void onConnectionClose(const Connection& c)
86 {
87 Connectable::onConnectionClose(c);
88 }
89
90 protected:
91 void disconnectSlot()
92 {
93 _target.close();
94 }
95
96 void disconnectSlot(const Slot& slot)
97 {
98 if( _target.isValid() && _target.slot()->equals(slot) )
99 {
100 _target.close();
101 }
102 }
103
104 protected:
105 Connection _target;
106};
107
192template <typename R, typename... As>
193class Delegate : public DelegateBase
194{
195 public:
196 typedef Callable<R, As...> CallableT;
197
198 public:
201 { }
202
205 Delegate(const Delegate& rhs)
206 {
207 DelegateBase::operator=(rhs);
208 }
209
213 {
214 return Connection(*this, slot.clone());
215 }
216
220 {
221 DelegateBase::disconnectSlot();
222 }
223
227 {
228 DelegateBase::disconnectSlot(slot);
229 }
230
236 R call(As... args)
237 {
238 if( ! _target.isValid() )
239 throw std::logic_error("Delegate::call(): Delegate not connected");
240
241 const CallableT* callable =
242 static_cast<const CallableT*>( _target.callable() );
243 return callable->call(args...);
244 }
245
251 void invoke(As... args)
252 {
253 if( ! _target.isValid() )
254 return;
255
256 const CallableT* callable =
257 static_cast<const CallableT*>( _target.callable() );
258 callable->call(args...);
259 }
260
263 R operator()(As... args)
264 {
265 return this->call(args...);
266 }
267};
268
278template <typename R, typename... As>
279class DelegateSlot : public BasicSlot<R, As...>
280{
281 public:
285 : _method(delegate, &Delegate<R, As...>::call)
286 { }
287
288 // inherit doc
289 Slot* clone() const
290 {
291 return new DelegateSlot(*this);
292 }
293
294 // inherit doc
295 virtual const Callback* callable() const
296 {
297 return &_method;
298 }
299
300 // inherit doc
301 virtual void onConnect(const Connection& connection)
302 {
303 _method.object().onConnectionOpen(connection);
304 }
305
306 // inherit doc
307 virtual void onDisconnect(const Connection& connection)
308 {
309 _method.object().onConnectionClose(connection);
310 }
311
312 // inherit doc
313 virtual bool equals(const Slot& slot) const
314 {
315 const DelegateSlot* other = dynamic_cast<const DelegateSlot*>(&slot);
316 return other && _method == other->_method;
317 }
318
319 private:
320 Method<R, Delegate<R, As...>, As...> _method;
321};
322
327template <typename R, typename... As>
329{
330 return DelegateSlot<R, As...>(delegate);
331}
332
337template <typename R, typename... As>
339{
340 return delegate.connect(slot);
341}
342
343} // namespace Pt
344
345#endif
Base type for various "slot" types.
Definition Slot.h:92
An interface for all callable entities.
Definition Callable.h:48
ConstMethod< R, ClassT, As... > callable(ClassT &object, R(BaseT::*method)(As...) const)
Returns a ConstMethod object for the given object/method pair.
Definition ConstMethod.h:161
Connection Management for Signal and Slot Objects.
Definition Connectable.h:50
Represents a connection between a Signal/Delegate and a slot.
Definition Connection.h:96
Connection()
Default Constructor.
const Connectable * sender() const
Returns the sender.
Definition Connection.h:115
R call(As... args) const
Calls the callable entity and returns its result.
Definition ConstMethod.h:77
Wraps Delegate objects so that they can act as Slots.
Definition Delegate.h:280
DelegateSlot(Delegate< R, As... > &delegate)
Constructs from delegate.
Definition Delegate.h:284
virtual bool equals(const Slot &slot) const
Returns true if two slots are equal in value.
Definition Delegate.h:313
virtual const Callback * callable() const
Returns the callable converted to the type-erased Callback interface.
Definition Delegate.h:295
virtual void onDisconnect(const Connection &connection)
Notifies of disconnects.
Definition Delegate.h:307
virtual void onConnect(const Connection &connection)
Notifies of connects.
Definition Delegate.h:301
Slot * clone() const
Clone this object with new.
Definition Delegate.h:289
Delegates an action to a slot.
Definition Delegate.h:194
Delegate()
Default Constructor.
Definition Delegate.h:200
Connection connect(const BasicSlot< R, As... > &slot)
Connects this object to the given slot and returns that Connection.
Definition Delegate.h:212
void disconnect(const BasicSlot< R, As... > &slot)
Disconnects from the target.
Definition Delegate.h:226
bool isConnected() const
Returns true if connected to a target.
Definition Delegate.h:67
void disconnect()
Disconnects from current target.
Definition Delegate.h:219
Connection operator+=(Delegate< R, As... > &delegate, const BasicSlot< R, As... > &slot)
Connect a Delegate to a slot.
Definition Delegate.h:338
R call(As... args)
Calls the slot connected to the Delegate.
Definition Delegate.h:236
void invoke(As... args)
Invoke the slot connected to the Delegate.
Definition Delegate.h:251
Delegate(const Delegate &rhs)
Deeply copies the other Delegate.
Definition Delegate.h:205
R operator()(As... args)
Same as call().
Definition Delegate.h:263
Adapter for class methods.
Definition Method.h:48
Endpoint of a signal/slot connection.
Definition Slot.h:55
ConstMethodSlot< R, ClassT, As... > slot(ClassT &object, R(BaseT::*method)(As...) const)
Returns a slot object for the given object/member pair.
Definition ConstMethod.h:172
DelegateSlot< R, As... > slot(Delegate< R, As... > &delegate)
Returns a slot object for the given delegate.
Definition Delegate.h:328
Core module.
Definition Allocator.h:33