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 
41 namespace Pt {
42 
43 class 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 
192 template <typename R, typename... As>
193 class 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 
219  void disconnect()
220  {
221  DelegateBase::disconnectSlot();
222  }
223 
226  void disconnect(const BasicSlot<R, As...>& slot)
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 
278 template <typename R, typename... As>
279 class DelegateSlot : public BasicSlot<R, As...>
280 {
281  public:
284  explicit DelegateSlot(Delegate<R, As...>& delegate)
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 
327 template <typename R, typename... As>
329 {
330  return DelegateSlot<R, As...>(delegate);
331 }
332 
337 template <typename R, typename... As>
339 {
340  return delegate.connect(slot);
341 }
342 
343 } // namespace Pt
344 
345 #endif
Core module.
Definition: Allocator.h:33
void invoke(As... args)
Invoke the slot connected to the Delegate.
Definition: Delegate.h:251
Adapter for class methods.
Definition: Method.h:48
Connectable()
Default constructor.
An interface for all callable entities.
Definition: Callable.h:48
Delegate(const Delegate &rhs)
Deeply copies the other Delegate.
Definition: Delegate.h:205
virtual bool equals(const Slot &slot) const
Returns true if two slots are equal in value.
Definition: Delegate.h:313
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
virtual const Callback * callable() const
Returns the callable converted to the type-erased Callback interface.
Definition: Delegate.h:295
Delegate()
Default Constructor.
Definition: Delegate.h:200
void disconnect()
Disconnects from current target.
Definition: Delegate.h:219
Slot * clone() const
Clone this object with new.
Definition: Delegate.h:289
void disconnect(const BasicSlot< R, As... > &slot)
Disconnects from the target.
Definition: Delegate.h:226
virtual Slot * clone() const =0
Clone this object with new.
Connection connect(const BasicSlot< R, As... > &slot)
Connects this object to the given slot and returns that Connection.
Definition: Delegate.h:212
virtual void onDisconnect(const Connection &connection)
Notifies of disconnects.
Definition: Delegate.h:307
Connectable & operator=(const Connectable &rhs)
Assignment operator.
R operator()(As... args)
Same as call()
Definition: Delegate.h:263
Wraps Delegate objects so that they can act as Slots.
Definition: Delegate.h:280
virtual void onConnect(const Connection &connection)
Notifies of connects.
Definition: Delegate.h:301
Endpoint of a signal/slot connection.
Definition: Slot.h:55
DelegateSlot(Delegate< R, As... > &delegate)
Constructs from delegate.
Definition: Delegate.h:284
DelegateSlot< R, As... > slot(Delegate< R, As... > &delegate)
Returns a slot object for the given delegate.
Definition: Delegate.h:328
R call(As... args)
Calls the slot connected to the Delegate.
Definition: Delegate.h:236
Delegates an action to a slot.
Definition: Delegate.h:194
Represents a connection between a Signal/Delegate and a slot.
Definition: Connection.h:96
Connection operator+=(Delegate< R, As... > &delegate, const BasicSlot< R, As... > &slot)
Connect a Delegate to a slot.
Definition: Delegate.h:338
virtual R call(As... args) const =0
Calls the callable entity and returns its result.