1 /*! \page type-registration Type Registration
5 DALi has a \link Dali::TypeRegistry type registration \endlink system which can be used to register
6 a derived actor/control type along with specifying a method which is used to create this type. This
7 type registration normally takes place at library load time.
9 Once a type is registered, signals, actions and properties can also be registered for all instances
12 This then allows the application writer to create instances using just the type name; connect to
13 signals using only the signal name; activate an action by just using the action name; and finally,
14 getting and setting properties using a property name or index.
19 - @ref register-signal
20 - @ref register-action
21 - @ref register-property
27 @section register-type Registering a Type
29 A type can be registered using Dali::TypeRegistration. This is normally done in an unnamed namespace
30 within the source file of the deriving control as shown in the code below.
32 <b>Please note:</b> This snippet assumes knowledge of the \link Dali::Toolkit::Control Control
33 \endlink / \link Dali::Toolkit::Internal::Control Internal::Control \endlink creation process where
34 <i><b>MyControl</b></i> derives from a Control and <i><b>MyControlImpl</b></i> derives from Internal::Control.
40 Dali::BaseHandle Create()
42 // Create an instance of MyControl and return the handle.
43 return MyControlImpl::New();
46 Dali::TypeRegistration type(
47 typeid( MyControl ), // Type ID of our Control
48 typeid( Dali::Toolkit::Control ), // Type ID of what our Control derives from
49 Create // Function which creates our Control, signature shown above
52 } // unnamed namespace
55 This registration informs DALi of the existence of MyControl type.
57 @section register-signal Registering a Signal
59 Once we've registered a type, we can then inform the type-registry about any signals that our type has:
62 // Define the names of the signals
63 static const char * const SIGNAL_ONE( "signal1" );
64 static const char * const SIGNAL_TWO( "signal2" );
65 static const char * const SIGNAL_THREE( "signal3" );
67 Dali::SignalConnectorType signal1(
68 type, // Reference to type registration object (see above)
69 SIGNAL_ONE, // Name of our signal
70 &MyControl::DoConnectSignal // Function to call when a call to connect to this signal is received
73 // Register more signals
74 Dali::SignalConnectorType signal2( type, SIGNAL_TWO, &MyControl::DoConnectSignal );
75 Dali::SignalConnectorType signal3( type, SIGNAL_THREE, &MyControl::DoConnectSignal );
78 It is recommended to use static members (of MyControl class) for the signal names. That way
79 applications can also use the static member rather than have to look up the name.
81 The method that handles the signal connection has to be static and takes the form:
84 bool MyControl::DoConnectSignal(
85 Dali::BaseObject* object, // A pointer to an instance of MyControl
86 Dali::ConnectionTrackerInterface* tracker, // The object connecting to the signal
87 const std::string& signalName, // The name of the signal to connect to
88 Dali::FunctorDelegate* functor // The functor
91 bool connected( false );
93 // DownCast to MyControl so that we can call the signal connection methods
94 MyControl control = MyControl::DownCast( Dali::BaseHandle ( object ) );
98 if ( signalName == SIGNAL_ONE )
100 control.SignalOne().Connect( tracker, functor );
103 else if ( signalName == SIGNAL_TWO )
105 control.SignalTwo().Connect( tracker, functor );
108 else if ( signalName == SIGNAL_THREE )
110 control.SignalThree().Connect( tracker, functor );
115 return connected; // Return true if connection successfully created
119 @section register-action Registering an Action
121 Created controls are able to perform a variety of default actions. Registering an action with the
122 type registry allows application writers to perform this action by using the name.
124 An action can be added to a type as shown below:
127 // Define the names of the actions
128 static const char * const ACTION_ONE( "action1" );
129 static const char * const ACTION_TWO( "action2" );
130 static const char * const ACTION_THREE( "action3" );
132 Dali::TypeAction action1(
133 type, // Reference to type registration object (see above)
134 ACTION_ONE, // Name of the action
135 &MyControl::DoAction // Function to call when someone wants to perform this action
138 // Register mode actions
139 Dali::TypeAction action2( type, ACTION_TWO, &MyControl::DoAction );
140 Dali::TypeAction action3( type, ACTION_THREE, &MyControl::DoAction );
143 It is recommended to use static members (of MyControl class) for the action names. That way
144 applications can also use the static member rather than have to look up the name.
146 The method that handles the action has to be static and takes the form:
149 bool MyControl::DoAction(
150 Dali::BaseObject* object, // A pointer to an instance of MyControl
151 const std::string& actionName, // The name of the action to perform
152 const std::vector< Dali::Property::Value >& attributes // Any passed in attributes
155 bool performed( false );
157 Dali::BaseHandle handle(object);
159 // DownCast to MyControl so that we can do the specific behaviour
160 MyControl control = MyControl::DownCast( Dali::BaseHandle ( object ) );
164 if ( actionName == ACTION_ONE )
166 // Do action1 e.g. button click etc.
168 else if ( actionName == ACTION_TWO )
170 // Do action2, which can have attributes
171 if ( !attributes.empty() )
173 // Let's assume action2 expects a std::string as an attribute, here's how we'd extract that
174 std::cout << "action2 printing out: " << attributes[0].Get< std::string >() ) << std::endl;
177 else if ( actionName == ACTION_THREE )
183 return performed; // Return true if action successfully performed
187 @section register-property Registering a Property
189 DALi has a property system which can be extended by registering more properties through the type
190 registry. The property index is <b><i>very important</i></b> when registering these properties and
191 all property indices should be between Dali::PROPERTY_REGISTRATION_START_INDEX and
192 Dali::PROPERTY_REGISTRATION_MAX_INDEX.
194 Furthermore, if deriving from \link Dali::Toolkit::Control Control\endlink, the control writer
195 needs to be aware of their parent class's property range. Control reserves a property range between
196 \link Dali::Toolkit::Control::CONTROL_PROPERTY_START_INDEX ControlImpl::CONTROL_PROPERTY_START_INDEX\endlink
197 and \link Dali::Toolkit::Control::CONTROL_PROPERTY_END_INDEX Control::CONTROL_PROPERTY_END_INDEX\endlink.
198 Any deriving control should start their property indices from
199 \link Dali::Toolkit::Control::CONTROL_PROPERTY_END_INDEX Control::CONTROL_PROPERTY_END_INDEX\endlink + 1.
201 Please have a look at \ref property-indices for more information.
203 The following code shows how a property can be added to a type.
206 // Define the indices we will use for the properties
207 static const int PROPERTY_ONE( Dali::Toolkit::Internal::Control::CONTROL_PROPERTY_END_INDEX + 1 );
208 static const int PROPERTY_TWO( Dali::Toolkit::Internal::Control::CONTROL_PROPERTY_END_INDEX + 2 );
209 static const int PROPERTY_THREE( Dali::Toolkit::Internal::Control::CONTROL_PROPERTY_END_INDEX + 3 );
211 Dali::PropertyRegistration property1(
212 type, // Reference to type registration object (see above)
213 "property1", // Name of the property
214 PROPERTY_ONE, // Index of this property
215 Dali::Property::BOOLEAN, // The property type
216 &MyControl::SetProperty, // Method called when property is set
217 &MyControl::GetProperty // Method called when retrieving the value of the property
220 // Register more properties
221 Dali::PropertyRegistration property2(
222 type, "property2", PROPERTY_TWO, Dali::Property::FLOAT,
223 NULL, // SetProperty is NULL, means that this property is a read-only property
224 &MyControl::GetProperty
226 Dali::PropertyRegistration property3( type, "property3", PROPERTY_THREE, Dali::Property::FLOAT, &MyControl::SetProperty, &MyControl::GetProperty);
229 It is recommended to use static members (of MyControl class) for the property indices. That way
230 applications can also use the static member as well. If they require the property name, they can
231 just call the Dali::Handle::GetPropertyName().
233 The method that deals with setting the property has to be static, and follows the format:
236 void MyControl::SetProperty(
237 Dali::BaseObject* object, // A pointer to an instance of MyControl
238 Dali::Property::Index index, // The index of the property to set
239 const Dali::Property::Value& value // The value to set the property to
242 // DownCast to MyControl so that we can do the specific behaviour
243 MyControl control = MyControl::DownCast( Dali::BaseHandle ( object ) );
247 MyControlImpl& controlImpl( GetImplementation( control ) );
253 // Assume we already have a method in MyControl which sets the appropriate value and takes in a boolean
254 controlImpl.SetPropertyOne( value.Get< bool >() );
258 // PROPERTY_TWO is read-only so does not need to be handled
262 // Assume we already have a method in MyControl which sets the appropriate value and takes in a float
263 controlImpl.SetPropertyThree( value.Get< float >() );
271 And the function to retrieve the property value also has to be static and takes the form:
274 Property::Value MyControl::GetProperty(
275 BaseObject* object, // A pointer to an instance of MyControl
276 Property::Index index // The index of the property to retrieve
279 Property::Value value;
281 // DownCast to MyControl so that we can do the specific behaviour
282 MyControl control = MyControl::DownCast( Dali::BaseHandle ( object ) );
286 MyControlImpl& controlImpl( GetImplementation( control ) );
292 // Assume we have a member variable that stores the value of this property
293 value = controlImpl.mPropertyOne;
299 // Assume we have a member variable that stores the value of this property
300 value = controlImpl.mPropertyTwo;
306 // Assume we have a member variable that stores the value of this property
307 value = controlImpl.mPropertyThree;
315 @section using-type Creating an instance of a Registered Type
317 When a type is registered with the \link Dali::TypeRegistry type registry\endlink, it allows the
318 application writer to get information about the type and even create an instance of it.
321 Dali::TypeInfo type = Dali::TypeRegistry::Get().GetTypeInfo( "MyControl" );
323 // If type specified is not found, then type will be NULL.
326 Dali::BaseHandle handle = type.CreateInstance();
328 // Can use DownCast to change to MyControl type if required
331 MyControl control = MyControl::DownCast( handle );
336 Normally we would not do the DownCast, just utilise the signals, actions and properties.
338 @section using-signal Connecting to a Registered Signal
340 The advantage of registering a signal using the \link Dali::TypeRegistry type registry \endlink is
341 that you can connect to a particular signal using just the name of the signal.
343 The application code would look as follows:
350 // Assume this is called when creating MyApp
353 Dali::TypeInfo type = Dali::TypeRegistry::Get().GetTypeInfo( "MyControl" );
357 mHandle = type.CreateInstance();
361 // Connect to signal1 by using its name
362 handle.ConnectSignal( &mConnectionTracker, "signal1", &MyApp::SignalReceived ) )
367 // This method will be called when "signal1" is emitted
368 void SignalReceived()
370 // Do Something when "signal1" is received
371 std::cout << "signal1 received" << std::endl;
375 Dali::BaseHandle mHandle; // Handle to MyControl created via the type-registry
376 Dali::ConnectionTracker mConnectionTracker; // Used for automatic signal disconnection upon its destruction
380 @section using-action Performing a Registered Action
382 Once an action is registered, the application writer can perform that action using the action name:
385 Dali::TypeInfo type = Dali::TypeRegistry::Get().GetTypeInfo( "MyControl" );
389 Dali::BaseHandle handle = type.CreateInstance();
393 // Perform action1, no attributes
394 handle.DoAction( "action1", std::vector< Dali::Property::Value >() );
396 // Create an attribute vector for action2
397 std::vector< Dali::Property::Value > action2Attributes;
398 action2Attributes.push_back( Dali::Property::Value( "Hello-Action-2" ) );
400 // Perform action2, with attributes
401 handle.DoAction( "action2", action2Attributes );
406 @section using-property Setting & Getting Registered Properties
408 Like other properties, type registered properties can also be set and their values can be retrieved
409 in a similar manner. The code below shows how this can be done.
412 Dali::TypeInfo type = Dali::TypeRegistry::Get().GetTypeInfo( "MyControl" );
416 Dali::BaseHandle baseHandle = type.CreateInstance();
420 // Handle deals with properties, so DownCast
421 Dali::Handle handle = Dali::Handle::DownCast( baseHandle );
425 // Setting a property
426 handle.SetProperty( PROPERTY_ONE, true ); // Assume Property indices are publicly accessible
428 // Get the property name
429 std::cout << "Property1 name is: " << handle.GetPropertyName( PROPERTY_ONE ) << std::endl;
432 bool propertyOne = handle.GetProperty< bool >( PROPERTY_ONE );
434 // Attempt to write a read-only property...
435 handle.SetProperty( PROPERTY_TWO, 4.0f ); // !!! Will assert as PROPERTY_TWO is read-only !!!