Revert "[Tizen] Add codes for Dali Windows Backend"
[platform/core/uifw/dali-core.git] / dali / public-api / signals / base-signal.h
1 #ifndef __DALI_BASE_SIGNAL_H__
2 #define __DALI_BASE_SIGNAL_H__
3
4 /*
5  * Copyright (c) 2018 Samsung Electronics Co., Ltd.
6  *
7  * Licensed under the Apache License, Version 2.0 (the "License");
8  * you may not use this file except in compliance with the License.
9  * You may obtain a copy of the License at
10  *
11  * http://www.apache.org/licenses/LICENSE-2.0
12  *
13  * Unless required by applicable law or agreed to in writing, software
14  * distributed under the License is distributed on an "AS IS" BASIS,
15  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16  * See the License for the specific language governing permissions and
17  * limitations under the License.
18  *
19  */
20
21 // INTERNAL INCLUDES
22 #include <dali/public-api/common/dali-common.h>
23 #include <dali/public-api/common/dali-vector.h>
24 #include <dali/public-api/signals/callback.h>
25 #include <dali/public-api/signals/connection-tracker-interface.h>
26 #include <dali/public-api/signals/signal-slot-connections.h>
27
28 namespace Dali
29 {
30 /**
31  * @addtogroup dali_core_signals
32  * @{
33  */
34
35 /**
36  * @brief Implementation class for Dali::Signal.
37  *
38  * A slot can be connected to many signals
39  * A signal can be connected to many slots
40  *
41  * To provide automatic disconnection when either a signal or the object owning the slot dies,
42  * observers are used.
43  *
44  * A signal is an object with state. It holds a list of SignalConnection%s.
45  *
46  * E.g.
47  *  Signal OnTouch. mSignalConnections contains
48  * <table>
49  * <tr><td> %Callback 0 </td><td> Signal Observer 0  </td></tr>
50  * <tr><td> %Callback 1 </td><td> Signal Observer 1  </td></tr>
51  * <tr><td> %Callback 2 </td><td> Signal Observer 2  </td></tr>
52  * </table>
53  *
54  * OnTouch.Emit() will run callbacks 0, 1 and 2.
55  *
56  * When the signal is destroyed. SignalDisconnected() is called on each Signal Observer.
57  *
58  * Slots are just static or member functions, so have no state. E.g. they can't keep
59  * track of how many signals they are connected to.
60  * If the object owning a slot dies, it must automatically disconnected from all signals.
61  * If it doesn't disconnect and the signal is emitted, there will be a crash.
62  *
63  * To keep track of connections between slots and signals, a Connection tracker is used.
64  * It holds a list of SlotConnections.
65  *
66  * <table>
67  * <tr><td> %Callback 0 </td><td> Slot Observer 0  </td></tr>
68  * <tr><td> %Callback 1 </td><td> Slot Observer 1  </td></tr>
69  * <tr><td> %Callback 2 </td><td> Slot Observer 2  </td></tr>
70  * </table>
71  *
72  * When the connection tracker is destroyed, SlotDisconnected() is called on every slot observer ( signal ).
73  * Signals implement the Slot Observer interface, to be told when a slot has disconnected.
74  * Connection tracker implements the Signal Observer interface, to be told when a signal has disconnected (died).
75  *
76  * @SINCE_1_0.0
77  */
78 class DALI_CORE_API BaseSignal : public SlotObserver
79 {
80 public:
81
82   /**
83    * @brief Constructor.
84    * @SINCE_1_0.0
85    */
86   BaseSignal();
87
88   /**
89    * @brief Virtual destructor.
90    * @SINCE_1_0.0
91    */
92   virtual ~BaseSignal();
93
94   /**
95    * @brief Queries whether there are any connected slots.
96    *
97    * @SINCE_1_0.0
98    * @return True if there are any slots connected to the signal.
99    */
100   bool Empty() const;
101
102   /**
103    * @brief Queries the number of slots.
104    *
105    * @SINCE_1_0.0
106    * @return The number of slots connected to this signal
107    */
108   std::size_t GetConnectionCount() const;
109
110   // Templated Emit functions for the Signal implementations
111
112   /**
113    * @brief Used to guard against nested Emit() calls.
114    * @SINCE_1_0.0
115    */
116   struct EmitGuard
117   {
118     /**
119      * @brief Creates the guard.
120      *
121      * @SINCE_1_0.0
122      * @param[in,out] flag This flag will be set to true during Emit() calls
123      */
124     EmitGuard( bool& flag );
125
126     /**
127      * @brief Non-virtual destructor.
128      *
129      * @SINCE_1_0.0
130      */
131     ~EmitGuard();
132
133     /**
134      * @brief Determines if an error occurred.
135      *
136      * @SINCE_1_0.0
137      * @return True if an error occurred i.e. if Emit() was called during Emit()
138      */
139     bool ErrorOccurred();
140
141     bool* mFlag; ///< Pointer to the emit guard flag.
142   };
143
144   /**
145    * @brief Emits a signal with no parameters.
146    *
147    * @SINCE_1_0.0
148    * @pre Cannot be called from inside the same Signal's Emit methods.
149    */
150   void Emit();
151
152   /**
153    * @brief Emits a signal with no parameters.
154    *
155    * @SINCE_1_0.0
156    * @return The value returned by the last callback
157    * @pre Cannot be called from inside the same Signal's Emit methods.
158    */
159   template< typename Ret >
160   Ret EmitReturn()
161   {
162     Ret returnVal = Ret();
163
164     // Guards against nested Emit() calls
165     EmitGuard guard( mEmittingFlag );
166     if( guard.ErrorOccurred() )
167     {
168       return returnVal;
169     }
170
171     // If more connections are added by callbacks, these are ignore until the next Emit()
172     // Note that count cannot be reduced while iterating
173     const std::size_t initialCount( mSignalConnections.Count() );
174
175     for( std::size_t i = 0; i < initialCount; ++i )
176     {
177       CallbackBase* callback( GetCallback(i) );
178
179       // Note that connections will be set to NULL when disconnected
180       // This is preferable to reducing the connection count while iterating
181       if( callback )
182       {
183         returnVal = CallbackBase::ExecuteReturn<Ret>( *callback );
184       }
185     }
186
187     // Cleanup NULL values from Connection container
188     CleanupConnections();
189
190     return returnVal;
191   }
192
193   /**
194    * @brief Emits a signal with 1 parameter.
195    *
196    * @SINCE_1_0.0
197    * @param[in] arg0 The first parameter
198    * @pre Cannot be called from inside the same Signal's Emit methods.
199    */
200   template< typename Arg0 >
201   void Emit( Arg0 arg0 )
202   {
203     // Guards against nested Emit() calls
204     EmitGuard guard( mEmittingFlag ); // Guards against nested Emit() calls
205     if( guard.ErrorOccurred() )
206     {
207       return;
208     }
209
210     // If more connections are added by callbacks, these are ignore until the next Emit()
211     // Note that count cannot be reduced while iterating
212     const std::size_t initialCount( mSignalConnections.Count() );
213
214     for( std::size_t i = 0; i < initialCount; ++i )
215     {
216       CallbackBase* callback( GetCallback(i) );
217
218       // Note that connections will be set to NULL when disconnected
219       // This is preferable to reducing the connection count while iterating
220       if( callback )
221       {
222         CallbackBase::Execute<Arg0 >( *callback, arg0 );
223       }
224     }
225
226     // Cleanup NULL values from Connection container
227     CleanupConnections();
228   }
229
230   /**
231    * @brief Emits a signal with 1 parameter.
232    *
233    * @SINCE_1_0.0
234    * @param[in] arg0 The first parameter
235    * @return The value returned by the last callback
236    * @pre Cannot be called from inside the same Signal's Emit methods.
237    */
238   template< typename Ret, typename Arg0 >
239   Ret EmitReturn( Arg0 arg0 )
240   {
241     Ret returnVal = Ret();
242
243     // Guards against nested Emit() calls
244     EmitGuard guard( mEmittingFlag ); // Guards against nested Emit() calls
245     if( guard.ErrorOccurred() )
246     {
247       return returnVal;
248     }
249
250     // If more connections are added by callbacks, these are ignore until the next Emit()
251     // Note that count cannot be reduced while iterating
252     const std::size_t initialCount( mSignalConnections.Count() );
253
254     for( std::size_t i = 0; i < initialCount; ++i )
255     {
256       CallbackBase* callback( GetCallback(i) );
257
258       // Note that connections will be set to NULL when disconnected
259       // This is preferable to reducing the connection count while iterating
260       if( callback )
261       {
262         returnVal = CallbackBase::ExecuteReturn<Ret,Arg0>( *callback, arg0 );
263       }
264     }
265
266     // Cleanup NULL values from Connection container
267     CleanupConnections();
268
269     return returnVal;
270   }
271
272   /**
273    * @brief Emits a signal with 2 parameters.
274    *
275    * @SINCE_1_0.0
276    * @param[in] arg0 The first parameter
277    * @param[in] arg1 The second parameter
278    * @pre Cannot be called from inside the same Signal's Emit methods.
279    */
280   template< typename Arg0, typename Arg1 >
281   void Emit( Arg0 arg0, Arg1 arg1 )
282   {
283     // Guards against nested Emit() calls
284     EmitGuard guard( mEmittingFlag ); // Guards against nested Emit() calls
285     if( guard.ErrorOccurred() )
286     {
287       return;
288     }
289
290     // If more connections are added by callbacks, these are ignore until the next Emit()
291     // Note that count cannot be reduced while iterating
292     const std::size_t initialCount( mSignalConnections.Count() );
293
294     for( std::size_t i = 0; i < initialCount; ++i )
295     {
296       CallbackBase* callback( GetCallback(i) );
297
298       // Note that connections will be set to NULL when disconnected
299       // This is preferable to reducing the connection count while iterating
300       if( callback )
301       {
302         CallbackBase::Execute<Arg0,Arg1>( *callback, arg0, arg1 );
303       }
304     }
305
306     // Cleanup NULL values from Connection container
307     CleanupConnections();
308   }
309
310   /**
311    * @brief Emits a signal with 2 parameters.
312    *
313    * @SINCE_1_0.0
314    * @param[in] arg0 The first parameter
315    * @param[in] arg1 The second parameter
316    * @return The value returned by the last callback
317    * @pre Cannot be called from inside the same Signal's Emit methods.
318    */
319   template< typename Ret, typename Arg0, typename Arg1 >
320   Ret EmitReturn( Arg0 arg0, Arg1 arg1 )
321   {
322     Ret returnVal = Ret();
323
324     // Guards against nested Emit() calls
325     EmitGuard guard( mEmittingFlag ); // Guards against nested Emit() calls
326     if( guard.ErrorOccurred() )
327     {
328       return returnVal;
329     }
330
331     // If more connections are added by callbacks, these are ignore until the next Emit()
332     // Note that count cannot be reduced while iterating
333     const std::size_t initialCount( mSignalConnections.Count() );
334
335     for( std::size_t i = 0; i < initialCount; ++i )
336     {
337       CallbackBase* callback( GetCallback(i) );
338
339       // Note that connections will be set to NULL when disconnected
340       // This is preferable to reducing the connection count while iterating
341       if( callback )
342       {
343         returnVal = CallbackBase::ExecuteReturn<Ret,Arg0,Arg1>( *callback, arg0, arg1 );
344       }
345     }
346
347     // Cleanup NULL values from Connection container
348     CleanupConnections();
349
350     return returnVal;
351   }
352
353   /**
354    * @brief Emits a signal with 3 parameters.
355    *
356    * @SINCE_1_0.0
357    * @param[in] arg0 The first parameter
358    * @param[in] arg1 The second parameter
359    * @param[in] arg2 The third parameter
360    * @pre Cannot be called from inside the same Signal's Emit methods.
361    */
362   template< typename Arg0, typename Arg1, typename Arg2 >
363   void Emit( Arg0 arg0, Arg1 arg1, Arg2 arg2 )
364   {
365     // Guards against nested Emit() calls
366     EmitGuard guard( mEmittingFlag ); // Guards against nested Emit() calls
367     if( guard.ErrorOccurred() )
368     {
369       return;
370     }
371
372     // If more connections are added by callbacks, these are ignore until the next Emit()
373     // Note that count cannot be reduced while iterating
374     const std::size_t initialCount( mSignalConnections.Count() );
375
376     for( std::size_t i = 0; i < initialCount; ++i )
377     {
378       CallbackBase* callback( GetCallback(i) );
379
380       // Note that connections will be set to NULL when disconnected
381       // This is preferable to reducing the connection count while iterating
382       if( callback )
383       {
384         CallbackBase::Execute<Arg0,Arg1,Arg2>( *callback, arg0, arg1, arg2 );
385       }
386     }
387
388     // Cleanup NULL values from Connection container
389     CleanupConnections();
390   }
391
392   /**
393    * @brief Emits a signal with 3 parameters.
394    *
395    * @SINCE_1_0.0
396    * @param[in] arg0 The first parameter
397    * @param[in] arg1 The second parameter
398    * @param[in] arg2 The third parameter
399    * @return The value returned by the last callback
400    * @pre Cannot be called from inside the same Signal's Emit methods.
401    */
402   template< typename Ret, typename Arg0, typename Arg1, typename Arg2 >
403   Ret EmitReturn( Arg0 arg0, Arg1 arg1, Arg2 arg2 )
404   {
405     Ret returnVal = Ret();
406
407     // Guards against nested Emit() calls
408     EmitGuard guard( mEmittingFlag ); // Guards against nested Emit() calls
409     if( guard.ErrorOccurred() )
410     {
411       return returnVal;
412     }
413
414     // If more connections are added by callbacks, these are ignore until the next Emit()
415     // Note that count cannot be reduced while iterating
416     const std::size_t initialCount( mSignalConnections.Count() );
417
418     for( std::size_t i = 0; i < initialCount; ++i )
419     {
420       CallbackBase* callback( GetCallback(i) );
421
422       // Note that connections will be set to NULL when disconnected
423       // This is preferable to reducing the connection count while iterating
424       if( callback )
425       {
426         returnVal = CallbackBase::ExecuteReturn<Ret,Arg0,Arg1,Arg2>( *callback, arg0, arg1, arg2 );
427       }
428     }
429
430     // Cleanup NULL values from Connection container
431     CleanupConnections();
432
433     return returnVal;
434   }
435
436   // Connect / Disconnect function for use by Signal implementations
437
438   /**
439    * @brief Called by Signal implementations, when the user calls Signal.Connect( ... ).
440    *
441    * @SINCE_1_0.0
442    * @param[in] callback A newly allocated callback object (takes ownership)
443    */
444   void OnConnect( CallbackBase* callback );
445
446   /**
447    * @brief Called by Signal implementations, when the user calls Signal.Disconnect( ... ).
448    *
449    * @SINCE_1_0.0
450    * @param[in] callback A newly allocated callback object (takes ownership)
451    */
452   void OnDisconnect( CallbackBase* callback );
453
454   /**
455    * @brief Called by Signal implementations, when the user calls Signal.Connect( ... ).
456    *
457    * @SINCE_1_0.0
458    * @param[in] tracker The connection tracker
459    * @param[in] callback A newly allocated callback object (takes ownership)
460    */
461   void OnConnect( ConnectionTrackerInterface* tracker, CallbackBase* callback );
462
463   /**
464    * @brief Called by Signal implementations, when the user calls Signal.Disconnect( ... ).
465    *
466    * @SINCE_1_0.0
467    * @param[in] tracker The connection tracker
468    * @param[in] callback A newly allocated callback object (takes ownership)
469    */
470   void OnDisconnect( ConnectionTrackerInterface* tracker, CallbackBase* callback );
471
472 private: // SlotObserver interface, to be told when a slot disconnects
473
474   /**
475    * @copydoc SlotObserver::SlotDisconnected
476    */
477   virtual void SlotDisconnected( CallbackBase* callback );
478
479 private:
480
481   /**
482    * @brief Returns a callback given an index in to the connection array.
483    *
484    * @SINCE_1_0.0
485    * @param[in] connectionIndex The index of the callback
486    * @return The callback, or NULL if the connection has been deleted
487    */
488   CallbackBase* GetCallback( std::size_t connectionIndex ) const;
489
490   /**
491    * @brief Helper to find whether a callback is connected.
492    *
493    * @SINCE_1_0.0
494    * @param[in] callback The call back object
495    * @return A valid index if the callback is connected
496    */
497   int FindCallback( CallbackBase* callback );
498
499   /**
500    * @brief Deletes a connection object from the list of connections.
501    *
502    * @SINCE_1_0.0
503    * @param[in] connectionIndex The index of the callback
504    */
505   void DeleteConnection( std::size_t connectionIndex );
506
507   /**
508    * @brief Helper to remove NULL items from mSignalConnections, which is only safe at the end of Emit()
509    * i.e. not from methods which can be called during a signal Emit(), such as Disconnect().
510    * @SINCE_1_0.0
511    */
512   void CleanupConnections();
513
514   BaseSignal( const BaseSignal& );                   ///< undefined copy constructor, signals don't support copying. @SINCE_1_0.0
515   BaseSignal& operator=( const BaseSignal& );        ///< undefined assignment operator @SINCE_1_0.0
516
517 private:
518
519   Dali::Vector< SignalConnection* > mSignalConnections;   ///< Array of connections
520
521   bool mEmittingFlag; ///< Used to guard against nested Emit() calls
522 };
523
524 /**
525  * @}
526  */
527 } // namespace Dali
528
529 #endif // __DALI_BASE_SIGNAL_H__