Rename of Control Renderers to Visuals
[platform/core/uifw/dali-toolkit.git] / docs / content / shared-javascript-and-cpp-documentation / creating-custom-controls.md
1 <!--
2 /**-->
3
4 [TOC]
5
6 # Creating Custom UI Controls {#creating-custom-controls}
7
8 DALi provides the ability to create custom UI controls.
9 This can be done by extending Dali::Toolkit::Control and Dali::Toolkit::Internal::Control classes.
10  
11 Custom controls are created using the [handle/body idiom](@ref handle-body-idiom) used in DALi.
12  
13 ![ ](../assets/img/creating-custom-controls/control-handle-body.png)
14 ![ ](creating-custom-controls/control-handle-body.png)
15  
16 ### General Guidelines:
17 + Try to avoid adding C++ APIs as they become difficult to maintain.
18   + Use **properties** as much as possible as Controls should be data driven.
19   + These controls will be used through JavaScript and JSON files so need to be compatible.
20 + Bear in mind that the Control is required to update when the properties change, not just the first time they are set (to deal with style change).
21 + Accessibility actions should be considered when designing the Control.
22 + Consider using signals if the application needs to be react to changes in the control state.
23  
24 ___________________________________________________________________________________________________
25
26 ## Rendering Content {#creating-controls-rendering-content}
27
28 To render content, the required actors can be created and added to the control itself as its children.
29 However, this solution is not fully optimised and means extra actors will be added, and thus, need to be processed by DALi.
30  
31 Controls should be as generic as possible so the recommendation is to re-use control renderers to create the content required as described in the [Visuals](@ref visuals) section.
32 Currently, this is devel-api though, so is subject to change.
33  
34 ![ ](../assets/img/creating-custom-controls/rendering.png)
35 ![ ](creating-custom-controls/rendering.png)
36  
37 ___________________________________________________________________________________________________
38
39 ## Ensuring Control is Stylable {#creating-controls-stylable}
40
41 DALi's property system allows custom controls to be easily styled.
42 The [JSON Syntax](@ref script-json-specification) is used in the stylesheets:
43  
44 **JSON Styling Syntax Example:**
45 ~~~
46 {
47   "styles":
48   {
49     "textfield":
50     {
51       "pointSize":18,
52       "primaryCursorColor":[0.0,0.72,0.9,1.0],
53       "secondaryCursorColor":[0.0,0.72,0.9,1.0],
54       "cursorWidth":1,
55       "selectionHighlightColor":[0.75,0.96,1.0,1.0],
56       "grabHandleImage" : "{DALI_STYLE_IMAGE_DIR}cursor_handler_drop_center.png",
57       "selectionHandleImageLeft" : {"filename":"{DALI_STYLE_IMAGE_DIR}selection_handle_drop_left.png" },
58       "selectionHandleImageRight": {"filename":"{DALI_STYLE_IMAGE_DIR}selection_handle_drop_right.png" }
59     }
60   }
61 }
62 ~~~
63  
64 Styling gives the UI designer the ability to change the look and feel of the control without any code changes.
65  
66 | Normal Style | Customized Style |
67 |:------------:|:----------------:|
68 |![ ](../assets/img/creating-custom-controls/popup-normal.png) ![ ](creating-custom-controls/popup-normal.png) | ![ ](../assets/img/creating-custom-controls/popup-styled.png) ![ ](creating-custom-controls/popup-styled.png)|
69  
70 More information regarding styling can be found in the [Styling](@ref styling) section.
71 ___________________________________________________________________________________________________
72
73 ### Type Registration {#creating-controls-type-registration}
74
75 The TypeRegistry is used to register your custom control.
76 This allows the creation of the control via a JSON file, as well as registering properties, signals and actions.
77  
78 To ensure your control is stylable, the process described in [Type Registration](@ref type-registration) should be followed.
79 To aid development, some macros are provided for registering properties which are described in the [Property](@ref properties) section.
80  
81 Control properties can be one of three types:
82  + **Event-side only:** A function is called to set this property or to retrieve the value of this property.
83                         Usually, the value is stored as a member parameter of the Impl class.
84                         Other operations can also be done, as required, in this called function.
85  + **Animatable Properties:** These are double-buffered properties that can be animated.
86  + **Custom Properties:** These are dynamic properties that are created for every single instance of the control.
87                           Therefore, these tend to take a lot of memory and are usually used by applications or other controls to dynamically set certain attributes on their children.
88                           The index for these properties can also be different for every instance.
89  
90 Careful consideration must be taken when choosing which property type to use for the properties of the custom control.
91 For example, an Animatable property type can be animated but requires a lot more resources (both in its execution and memory footprint) compared to an event-side only property.
92 ___________________________________________________________________________________________________
93
94 ## Control Services {#creating-controls-control-services}
95
96 ### Initialization {#creating-controls-init}
97
98 Controls are initialized in two steps: in the constructor, and then in the Initialize() method.
99 This is so that a handle/body connection is made within DALi Core.
100 See Dali::CustomActor & Dali::CustomActorImpl for more information.
101  
102 It is recommended to do provide a New() method in the custom control implementation where the Initialize() method should be called.
103
104 ~~~{.cpp}
105 // C++
106 MyUIControl MyUIControlImpl::New()
107 {
108   // Create the implementation, temporarily owned on stack
109   IntrusivePtr< MyUIControlImpl > controlImpl = new MyUIControlImpl;
110
111   // Pass ownership to handle
112   MyUIControl handle( *controlImpl );
113
114   // Second-phase init of the implementation
115   controlImpl->Initialize();
116
117   return handle;
118 }
119 ~~~
120 Another advantage of using a New() method is that the constructor for MyUIControl can be made private (or protected).
121  
122 This will trigger the Dali::Toolkit::Internal::Control Initialize() method which will in-turn, call the virtual method OnInitialize().
123 This should be overridden by the custom ui control.
124 ~~~{.cpp}
125 // C++
126 void MyUIControlImpl::OnInitialize()
127 {
128   // Create renderers, register events etc.
129 }
130 ~~~
131 ___________________________________________________________________________________________________
132
133 ### Control Behaviour {#creating-controls-behaviour}
134
135 Dali::Toolkit::Internal::Control provides several behaviours which are specified through its constructor (@ref Dali::Toolkit::Internal::Control::Control()).
136  
137 | Behaviour                            | Description                                                             |
138 |--------------------------------------|-------------------------------------------------------------------------|
139 | ACTOR_BEHAVIOUR_NONE                 | No behaviour required.                                                  |
140 | REQUIRES_HOVER_EVENTS                | If our control requires [hover events](@ref creating-controls-events).  |
141 | REQUIRES_WHEEL_EVENTS                | If our control requires [wheel events](@ref creating-controls-events).  |
142 | REQUIRES_STYLE_CHANGE_SIGNALS        | True if need to monitor style change signals such as Theme/Font change. |
143 | REQUIRES_KEYBOARD_NAVIGATION_SUPPORT | True if need to support keyboard navigation.                            |
144 ___________________________________________________________________________________________________
145
146 ### Touch, Hover & Wheel Events {#creating-controls-events}
147
148 + A **touch** is when any touch occurs within the bounds of the custom actor. Connect to Dali::Actor::TouchSignal().
149 + A **hover event** is when a pointer moves within the bounds of a custom actor (e.g. mouse pointer or hover pointer).
150 + A **wheel event** is when the mouse wheel (or similar) is moved while hovering over an actor (via a mouse pointer or hover pointer).
151  
152 If the control needs to utilise hover and wheel events, then the correct behaviour flag should be used when constructing the control and then the appropriate method should be overridden.
153 ~~~{.cpp}
154 // C++
155 bool MyUIControlImpl::OnHoverEvent( const HoverEvent& event )
156 {
157   bool consumed = false;
158
159   // Handle hover event
160
161   // Return true if handled/consumed, false otherwise
162   return consumed;
163 }
164 ~~~
165 ~~~{.cpp}
166 // C++
167 bool MyUIControlImpl::OnWheelEvent( const WheelEvent& event )
168 {
169   bool consumed = false;
170
171   // Handle wheel event
172
173   // Return true if handled/consumed, false otherwise
174   return consumed;
175 }
176 ~~~
177 ___________________________________________________________________________________________________
178
179 ### Gestures {#creating-controls-gestures}
180
181 DALi has a gesture system which analyses a stream of touch events and attempts to determine the intention of the user.
182 The following gesture detectors are provided:
183  
184  + **Pan:** When the user starts panning (or dragging) one or more fingers.
185             The panning should start from within the bounds of the control.
186  + **Pinch:** Detects when two touch points move towards or away from each other.
187               The center point of the pinch should be within the bounds of the control.
188  + **Tap:** When the user taps within the bounds of the control.
189  + **LongPress:** When the user presses and holds on a certain point within the bounds of a control.
190  
191 The control base class provides basic set up to detect these gestures.
192 If any of these detectors are required then this can be specified in the OnInitialize() method (or as required).
193  
194 ~~~{.cpp}
195 // C++
196 void MyUIControlImpl::OnInitialize()
197 {
198   // Only enable pan gesture detection
199   EnableGestureDetection( Gesture::Pan );
200
201   // Or if several gestures are required
202   EnableGestureDetection( Gesture::Type( Gesture::Pinch | Gesture::Tap | Gesture::LongPress ) );
203 }
204 ~~~
205  
206 The above snippet of code will only enable the default gesture detection for each type.
207 If customization of the gesture detection is required, then the gesture-detector can be retrieved and set up accordingly in the same method.
208  
209 ~~~{.cpp}
210 // C++
211 PanGestureDetector panGestureDetector = GetPanGestureDetector();
212 panGestureDetector.AddDirection( PanGestureDetector::DIRECTION_VERTICAL );
213 ~~~
214  
215 Finally, the appropriate method should be overridden:
216 ~~~{.cpp}
217 // C++
218 void MyUIControlImpl::OnPan( const PanGesture& pan )
219 {
220   // Handle pan-gesture
221 }
222 ~~~
223 ~~~{.cpp}
224 // C++
225 void MyUIControlImpl::OnPinch( const PinchGesture& pinch )
226 {
227   // Handle pinch-event
228 }
229 ~~~
230 ~~~{.cpp}
231 // C++
232 void MyUIControlImpl::OnTap( const TapGesture& tap )
233 {
234   // Handle tap-gesture
235 }
236 ~~~
237 ~~~{.cpp}
238 // C++
239 void MyUIControlImpl::OnLongPress( const LongPressGesture& longPress )
240 {
241   // Handle long-press-gesture
242 }
243 ~~~
244  
245 ___________________________________________________________________________________________________
246
247 ### Accessibility {#creating-controls-accessibility}
248
249 Accessibility is functionality that has been designed to aid usage by the visually impaired.
250 More information can be found in the [Accessibility](@ref accessibility) section.
251  
252 Accessibility behaviour can be customized in the control by overriding certain virtual methods.
253 This is detailed [here](@ref accessibilitycustomcontrol).
254  
255 ___________________________________________________________________________________________________
256
257 ### Signals {#creating-controls-signals}
258
259 If applications need to react to changes in the control state, controls can inform those applications using Dali::Signal.
260
261 First, create a signature of the function the signal will call in the handle header file:
262 ~~~{.cpp}
263 // C++: my-ui-control.h
264 typedef Signal< void () > SignalType;
265 ~~~
266  
267 Then Create methods to get to the signal:
268 ~~~{.cpp}
269 // C++: my-ui-control.h
270 MyUIControl::SignalType& MyCustomSignal();
271 ~~~
272
273 The source file should just call the impl:
274 ~~~{.cpp}
275 // C++: my-ui-control.cpp
276 MyUIControl::SignalType& MyUIControl::MyCustomSignal()
277 {
278   return Dali::Toolkit::GetImplementation( *this ).MyCustomSignal();
279 }
280 ~~~
281  
282 In the impl file, create an instance of the signal as follows and return it in the appropriate method:
283 ~~~{.cpp}
284 // C++: my-ui-control-impl.h
285 public:
286
287   MyUIControl::SignalType MyUIControl::MyCustomSignal()
288   {
289     return mMyCustomSignal;
290   }
291
292 private:
293
294   MyUIControl::SignalType mMyCustomSignal;
295 ~~~
296  
297 Then, when you wish to emit this signal:
298 ~~~{.cpp}
299 // C++: my-ui-control-impl.cpp
300 mMyCustomSignal.Emit();
301 ~~~
302 There is no need to check if there is anything connected to this signal as this is done by the framework.
303  
304 The application can then connect to the signal as follows:
305 ~~~{.cpp}
306 void AppFunction()
307 {
308   // Do Something
309 }
310
311 ...
312
313 customControl.MyCustomSignal.Connect( this, &AppFunction );
314 ~~~
315  
316 ___________________________________________________________________________________________________
317
318 ### Children Added/Removed {#creating-controls-children}
319
320 Methods are provided that can be overridden if notification is required when a child is added or removed from our control.
321 An up call to the Control class is necessary if these methods are overridden.
322  
323 ~~~{.cpp}
324 // C++
325 void MyUIControlImpl::OnChildAdd( Actor& child );
326 {
327   // Up call to Control first
328   Control::OnChildAdd( child );
329
330   // Do any other operations required upon child addition
331 }
332 ~~~
333 ~~~{.cpp}
334 // C++
335 void MyUIControlImpl::OnChildRemove( Actor& child );
336 {
337   // Do any other operations required upon child removal
338
339   // Up call to Control at the end
340   Control::OnChildRemove( child );
341 }
342 ~~~
343  
344 Avoid adding or removing the child again within these methods.
345  
346 ___________________________________________________________________________________________________
347
348 ### Stage Connection {#creating-controls-stage}
349
350 Methods are provided that can be overridden if notification is required when our control is connected to or disconnected from the stage.
351 An up call to the Control class is necessary if these methods are overridden.
352  
353 ~~~{.cpp}
354 // C++
355 void MyUIControlImpl::OnStageConnection( int depth )
356 {
357   // Up call to Control first
358   Control::OnStageConnection( depth );
359
360   // Do any other operations required upon stage connection
361 }
362 ~~~
363 ~~~{.cpp}
364 // C++
365 void MyUIControlImpl::OnStageDisconnection()
366 {
367   // Do any other operations required upon stage disconnection
368
369   // Up call to Control at the end
370   Control::OnStageDisconnection();
371 }
372 ~~~
373  
374 ___________________________________________________________________________________________________
375
376 ### Size {#creating-controls-size}
377
378 Methods are provided that can be overridden if notification is required when our control's size is manipulated.
379 An up call to the Control class is necessary if these methods are overridden.
380  
381 ~~~{.cpp}
382 // C++
383 void MyUIControlImpl::OnSizeSet( const Vector3& targetSize )
384 {
385   // Up call to Control
386   Control::OnSizeSet( targetSize );
387
388   // Do any other operations required upon size set
389 }
390 ~~~
391 ~~~{.cpp}
392 // C++
393 void MyUIControlImpl::OnSizeAnimation( Animation& animation, const Vector3& targetSize )
394 {
395   // Up call to Control
396   Control::OnSizeAnimation( animation, targetSize );
397
398   // Do any other operations required upon size animation
399 }
400 ~~~
401  
402 ___________________________________________________________________________________________________
403
404 ### Other Features {#creating-controls-other}
405
406  + [Background](@ref background)
407  
408 ___________________________________________________________________________________________________
409
410 @class _Guide_Creating_UI_Controls
411
412 */