Merge "use modern construct '= default' for special functions." into devel/master
[platform/core/uifw/dali-core.git] / dali / devel-api / signals / signal-delegate.h
1 #ifndef DALI_SIGNAL_DELEGATE_H
2 #define DALI_SIGNAL_DELEGATE_H
3
4 /*
5  * Copyright (c) 2020 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/actors/actor.h>
23 #include <dali/public-api/signals/connection-tracker-interface.h>
24
25 namespace Dali
26 {
27 /**
28  * @brief The SignalDelegate object allows direct connection to a signal that has been pre-configured internally.
29  *
30  * EG: The SignalDelegate can be created internally and exposed to the application-developer.
31  * They can then call the connect function to transparently bind to their callback.
32  */
33 class DALI_CORE_API SignalDelegate
34 {
35 public:
36   /**
37    * @brief Create and set up a signal delegate.
38    *
39    * @param[in] connectActor The actor whose signal should be connected to.
40    * @param[in] signalName The name of the signal within the actor to connect to.
41    */
42   SignalDelegate(Dali::Actor connectActor, const std::string& signalName);
43
44   /**
45    * @brief Destructor.
46    */
47   ~SignalDelegate() = default;
48
49 public:
50   /**
51    * @brief Connect to a FunctorDelegate as received from a type-registry signal connection call.
52    *
53    * This is required to allow connection to an actor's signal. Typically this is done in a generic
54    * way (IE. via a string of the signal name) using the ConnectSignal function.
55    * This function requires a functor.
56    *
57    * @param[in] connectionTracker Passed in to the ConnectSignal function of the actor.
58    * @param[in] functorDelegate A functor delegate object that must be executed when the signal is emitted.
59    * @return    True of the connection was made, false otherwise.
60    */
61   bool Connect(ConnectionTrackerInterface* connectionTracker, FunctorDelegate* functorDelegate)
62   {
63     if(!mIsConnected)
64     {
65       // Note: We have to new the CallbackBaseFunctor rather than have it as a concrete object, as it
66       // is converted to a FunctorDelegate again within ConnectSignal. FunctorDelegates gain ownership
67       // of any functor they are created from and therefore always attempt to delete them.
68       CallbackBaseFunctor* callbackFunctor = new CallbackBaseFunctor(new CallbackFunctorDelegate0(functorDelegate));
69       mConnectActor.ConnectSignal(connectionTracker, mSignalName, *callbackFunctor);
70       mIsConnected = true;
71
72       return true;
73     }
74
75     return false;
76   }
77
78   /**
79    * @brief Connect to a non-static member function.
80    *
81    * The object that owns the member function must also inherit from ConnectionTracker.
82    *
83    * @param[in] object Object instance that houses the supplied member-function.
84    * @param[in] memberFunction The member-function to call when the signal is emitted.
85    * @return    True of the connection was made, false otherwise.
86    */
87   template<class T>
88   bool Connect(T* object, void (T::*memberFunction)(void))
89   {
90     if(!mIsConnected)
91     {
92       CallbackBaseFunctor* callbackFunctor = new CallbackBaseFunctor(MakeCallback(object, memberFunction));
93       mConnectActor.ConnectSignal(object, mSignalName, *callbackFunctor);
94       mIsConnected = true;
95
96       return true;
97     }
98
99     return false;
100   }
101
102   /**
103    * @brief Checks if this delegate has been connected yet, so it can be determined if it
104    * can be used or a new delegate must be created to set up a new connection (to the same signal).
105    *
106    * @return True if this SignalDelegate has been connected to it's signal.
107    */
108   bool IsConnected();
109
110 private:
111   /**
112    * This functor is used by SignalDelegate in order to callback to a non-static member function
113    * (after it has been converted to a CallbackBase).
114    * The functor can be passed in to a ConnectSignal function of a BaseHandle and call into an
115    * object's member function on despatch.
116    */
117   struct CallbackBaseFunctor
118   {
119     /**
120      * @brief Create and initialise the functor with the callback to be called.
121      *
122      * @param[in] callback A CallbackBase which can be created from a member function, or a FunctorDelegate.
123      */
124     CallbackBaseFunctor(CallbackBase* callback);
125
126     /**
127      * @brief Executes the functor.
128      */
129     void operator()();
130
131     /**
132      * Destructor.
133      * Note that as this is passed in to a ConnectSignal method, it is converted to a FunctorDelegate.
134      * This means that this functor will automatically have it's destructor called, but we still own
135      * the CallbackBase, which must be destroyed manually here.
136      */
137     ~CallbackBaseFunctor();
138
139   private:
140     CallbackBase* mCallback; ///< Stores (and owns) the callback to be called on execution.
141   };
142
143 private:
144   /**
145    * @brief Not defined.
146    */
147   SignalDelegate(const SignalDelegate& rhs);
148
149   /**
150    * @brief Not defined.
151    */
152   const SignalDelegate& operator=(const SignalDelegate& rhs);
153
154 private:
155   bool        mIsConnected;  ///< Boolean to know if it is connected already.
156   Dali::Actor mConnectActor; ///< The actor owning the signal to connect to.
157   std::string mSignalName;   ///< The name of the signal to connect to.
158 };
159
160 } // namespace Dali
161
162 #endif // DALI_SIGNAL_DELEGATE_H