Merge "Fix the warning log in Control causing the wrong position" into devel/master
[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 Namespaces are important
17 + The handle & body classes should have the same name but in different namespaces
18 + TypeRegistry relies on this convention
19 + Here our custom control requires
20   + MyControl
21   + Internal::MyControl
22  
23 ### General Guidelines:
24 + Try to avoid adding C++ APIs as they become difficult to maintain.
25   + Use **properties** as much as possible as Controls should be data driven.
26   + These controls will be used through JavaScript and JSON files so need to be compatible.
27 + Bear in mind that the Control can be updated when the properties change (e.g. style change)
28   + Ensure control deals with these property changes gracefully
29   + Not just the first time they are set
30 + Use Visuals rather than creating several child Actors
31   + DALi rendering pipeline more efficient
32 + Accessibility actions should be considered when designing the Control.
33 + Consider using signals if the application needs to be react to changes in the control state.
34 + Use of Gestures should be preferred over analysing raw touch events
35 + Check if you need to chain up to base class if overriding certain methods
36  
37 ___________________________________________________________________________________________________
38
39 ## Rendering Content {#creating-controls-rendering-content}
40
41 To render content, the required actors can be created and added to the control itself as its children.
42 However, this solution is not fully optimised and means extra actors will be added, and thus, need to be processed by DALi.
43  
44 Controls should be as generic as possible so the recommendation is to re-use visuals to create the content required as described in the [Visuals](@ref visuals) section.
45 Currently, this is devel-api though, so is subject to change.
46  
47 ![ ](../assets/img/creating-custom-controls/rendering.png)
48 ![ ](creating-custom-controls/rendering.png)
49  
50 ___________________________________________________________________________________________________
51
52 ## Ensuring Control is Stylable {#creating-controls-stylable}
53
54 DALi's property system allows custom controls to be easily styled.
55 The [JSON Syntax](@ref script-json-specification) is used in the stylesheets:
56  
57 **JSON Styling Syntax Example:**
58 ~~~
59 {
60   "styles":
61   {
62     "textfield":
63     {
64       "pointSize":18,
65       "primaryCursorColor":[0.0,0.72,0.9,1.0],
66       "secondaryCursorColor":[0.0,0.72,0.9,1.0],
67       "cursorWidth":1,
68       "selectionHighlightColor":[0.75,0.96,1.0,1.0],
69       "grabHandleImage" : "{DALI_STYLE_IMAGE_DIR}cursor_handler_drop_center.png",
70       "selectionHandleImageLeft" : {"filename":"{DALI_STYLE_IMAGE_DIR}selection_handle_drop_left.png" },
71       "selectionHandleImageRight": {"filename":"{DALI_STYLE_IMAGE_DIR}selection_handle_drop_right.png" }
72     }
73   }
74 }
75 ~~~
76  
77 Styling gives the UI designer the ability to change the look and feel of the control without any code changes.
78  
79 | Normal Style | Customized Style |
80 |:------------:|:----------------:|
81 |![ ](../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)|
82  
83 More information regarding styling can be found in the [Styling](@ref styling) section.
84 ___________________________________________________________________________________________________
85
86 ### Type Registration {#creating-controls-type-registration}
87
88 The TypeRegistry is used to register your custom control.
89 This allows the creation of the control via a JSON file, as well as registering properties, signals and actions.
90  
91 To ensure your control is stylable, the process described in [Type Registration](@ref type-registration) should be followed.
92
93 #### Properties
94 To aid development, some macros are provided for registering properties which are described in the [Property](@ref properties) section.
95  
96 Control properties can be one of three types:
97  + **Event-side only:** A function is called to set this property or to retrieve the value of this property.
98                         Usually, the value is stored as a member parameter of the Impl class.
99                         Other operations can also be done, as required, in this called function.
100  + **Animatable Properties:** These are double-buffered properties that can be animated.
101  + **Custom Properties:** These are dynamic properties that are created for every single instance of the control.
102                           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.
103                           The index for these properties can also be different for every instance.
104  
105 Careful consideration must be taken when choosing which property type to use for the properties of the custom control.
106 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.
107 ___________________________________________________________________________________________________
108
109 ## Control Services {#creating-controls-control-services}
110
111 ### Initialization {#creating-controls-init}
112
113 Controls are initialized in two steps: in the constructor, and then in the Initialize() method.
114 This is so that a handle/body connection is made within DALi Core.
115 See Dali::CustomActor & Dali::CustomActorImpl for more information.
116  
117 It is recommended to do provide a New() method in the custom control implementation where the Initialize() method should be called.
118
119 ~~~{.cpp}
120 // C++
121 MyUIControl MyUIControlImpl::New()
122 {
123   // Create the implementation, temporarily owned on stack
124   IntrusivePtr< MyUIControlImpl > controlImpl = new MyUIControlImpl;
125
126   // Pass ownership to handle
127   MyUIControl handle( *controlImpl );
128
129   // Second-phase init of the implementation
130   controlImpl->Initialize();
131
132   return handle;
133 }
134 ~~~
135 Another advantage of using a New() method is that the constructor for MyUIControl can be made private (or protected).
136  
137 This will trigger the Dali::Toolkit::Internal::Control Initialize() method which will in-turn, call the virtual method OnInitialize().
138 This should be overridden by the custom ui control.
139 ~~~{.cpp}
140 // C++
141 void MyUIControlImpl::OnInitialize()
142 {
143   // Create visuals using the VisualFactory, register events etc.
144   // Register any created visuals with Control base class
145 }
146 ~~~
147 ___________________________________________________________________________________________________
148
149 ### Control Behaviour {#creating-controls-behaviour}
150
151 Dali::Toolkit::Internal::Control provides several behaviours which are specified through its constructor (@ref Dali::Toolkit::Internal::Control::Control()).
152  
153 | Behaviour                            | Description                                                                                                    |
154 |--------------------------------------|----------------------------------------------------------------------------------------------------------------|
155 | CONTROL_BEHAVIOUR_DEFAULT              | Default behavior (size negotiation is on, style change is monitored, event callbacks are not called.                                      |
156 | DISABLE_SIZE_NEGOTIATION             | If our control does not need size negotiation, i.e. control will be skipped by the size negotiation algorithm. |
157 | REQUIRES_HOVER_EVENTS                | If our control requires [hover events](@ref creating-controls-events).                                         |
158 | REQUIRES_WHEEL_EVENTS                | If our control requires [wheel events](@ref creating-controls-events).                                         |
159 | DISABLE_STYLE_CHANGE_SIGNALS         | True if control should not monitor style change signals such as Theme/Font change.                                         |
160 | REQUIRES_KEYBOARD_NAVIGATION_SUPPORT | True if need to support keyboard navigation.                                                                   |
161 ___________________________________________________________________________________________________
162
163 ### Touch, Hover & Wheel Events {#creating-controls-events}
164
165 + A **touch** is when any touch occurs within the bounds of the custom actor. Connect to Dali::Actor::TouchSignal().
166 + A **hover event** is when a pointer moves within the bounds of a custom actor (e.g. mouse pointer or hover pointer).
167 + A **wheel event** is when the mouse wheel (or similar) is moved while hovering over an actor (via a mouse pointer or hover pointer).
168  
169 If the control needs to utilize hover and wheel events, then the correct behaviour flag should be used when constructing the control and then the appropriate method should be overridden.
170 ~~~{.cpp}
171 // C++
172 bool MyUIControlImpl::OnHoverEvent( const HoverEvent& event )
173 {
174   bool consumed = false;
175
176   // Handle hover event
177
178   // Return true if handled/consumed, false otherwise
179   return consumed;
180 }
181 ~~~
182 ~~~{.cpp}
183 // C++
184 bool MyUIControlImpl::OnWheelEvent( const WheelEvent& event )
185 {
186   bool consumed = false;
187
188   // Handle wheel event
189
190   // Return true if handled/consumed, false otherwise
191   return consumed;
192 }
193 ~~~
194 ___________________________________________________________________________________________________
195
196 ### Gestures {#creating-controls-gestures}
197
198 DALi has a gesture system which analyses a stream of touch events and attempts to determine the intention of the user.
199 The following gesture detectors are provided:
200  
201  + **Pan:** When the user starts panning (or dragging) one or more fingers.
202             The panning should start from within the bounds of the control.
203  + **Pinch:** Detects when two touch points move towards or away from each other.
204               The center point of the pinch should be within the bounds of the control.
205  + **Tap:** When the user taps within the bounds of the control.
206  + **LongPress:** When the user presses and holds on a certain point within the bounds of a control.
207  
208 The control base class provides basic set up to detect these gestures.
209 If any of these detectors are required then this can be specified in the OnInitialize() method (or as required).
210  
211 ~~~{.cpp}
212 // C++
213 void MyUIControlImpl::OnInitialize()
214 {
215   // Only enable pan gesture detection
216   EnableGestureDetection( Gesture::Pan );
217
218   // Or if several gestures are required
219   EnableGestureDetection( Gesture::Type( Gesture::Pinch | Gesture::Tap | Gesture::LongPress ) );
220 }
221 ~~~
222  
223 The above snippet of code will only enable the default gesture detection for each type.
224 If customization of the gesture detection is required, then the gesture-detector can be retrieved and set up accordingly in the same method.
225  
226 ~~~{.cpp}
227 // C++
228 PanGestureDetector panGestureDetector = GetPanGestureDetector();
229 panGestureDetector.AddDirection( PanGestureDetector::DIRECTION_VERTICAL );
230 ~~~
231  
232 Finally, the appropriate method should be overridden:
233 ~~~{.cpp}
234 // C++
235 void MyUIControlImpl::OnPan( const PanGesture& pan )
236 {
237   // Handle pan-gesture
238 }
239 ~~~
240 ~~~{.cpp}
241 // C++
242 void MyUIControlImpl::OnPinch( const PinchGesture& pinch )
243 {
244   // Handle pinch-event
245 }
246 ~~~
247 ~~~{.cpp}
248 // C++
249 void MyUIControlImpl::OnTap( const TapGesture& tap )
250 {
251   // Handle tap-gesture
252 }
253 ~~~
254 ~~~{.cpp}
255 // C++
256 void MyUIControlImpl::OnLongPress( const LongPressGesture& longPress )
257 {
258   // Handle long-press-gesture
259 }
260 ~~~
261  
262 ___________________________________________________________________________________________________
263
264 ### Accessibility {#creating-controls-accessibility}
265
266 Accessibility is functionality that has been designed to aid usage by the visually impaired.
267 More information can be found in the [Accessibility](@ref accessibility) section.
268  
269 Accessibility behaviour can be customized in the control by overriding certain virtual methods.
270 This is detailed [here](@ref accessibilitycustomcontrol).
271  
272 ___________________________________________________________________________________________________
273
274 ### Signals {#creating-controls-signals}
275
276 If applications need to react to changes in the control state, controls can inform those applications using Dali::Signal.
277
278 First, create a signature of the function the signal will call in the handle header file:
279 ~~~{.cpp}
280 // C++: my-ui-control.h
281 typedef Signal< void () > SignalType;
282 ~~~
283  
284 Then Create methods to get to the signal:
285 ~~~{.cpp}
286 // C++: my-ui-control.h
287 MyUIControl::SignalType& MyCustomSignal();
288 ~~~
289
290 The source file should just call the impl:
291 ~~~{.cpp}
292 // C++: my-ui-control.cpp
293 MyUIControl::SignalType& MyUIControl::MyCustomSignal()
294 {
295   return Dali::Toolkit::GetImplementation( *this ).MyCustomSignal();
296 }
297 ~~~
298  
299 In the impl file, create an instance of the signal as follows and return it in the appropriate method:
300 ~~~{.cpp}
301 // C++: my-ui-control-impl.h
302 public:
303
304   MyUIControl::SignalType MyUIControl::MyCustomSignal()
305   {
306     return mMyCustomSignal;
307   }
308
309 private:
310
311   MyUIControl::SignalType mMyCustomSignal;
312 ~~~
313  
314 Then, when you wish to emit this signal:
315 ~~~{.cpp}
316 // C++: my-ui-control-impl.cpp
317 mMyCustomSignal.Emit();
318 ~~~
319 There is no need to check if there is anything connected to this signal as this is done by the framework.
320  
321 The application can then connect to the signal as follows:
322 ~~~{.cpp}
323 void AppFunction()
324 {
325   // Do Something
326 }
327
328 ...
329
330 customControl.MyCustomSignal.Connect( this, &AppFunction );
331 ~~~
332  
333 ___________________________________________________________________________________________________
334
335 ### Children Added/Removed {#creating-controls-children}
336
337 Methods are provided that can be overridden if notification is required when a child is added or removed from our control.
338 An up call to the Control class is necessary if these methods are overridden.
339  
340 ~~~{.cpp}
341 // C++
342 void MyUIControlImpl::OnChildAdd( Actor& child );
343 {
344   // Do any other operations required upon child addition
345
346   // Up call to Control at the end
347   Control::OnChildAdd( child );
348 }
349 ~~~
350 ~~~{.cpp}
351 // C++
352 void MyUIControlImpl::OnChildRemove( Actor& child );
353 {
354   // Do any other operations required upon child removal
355
356   // Up call to Control at the end
357   Control::OnChildRemove( child );
358 }
359 ~~~
360  
361 Avoid adding or removing the child again within these methods.
362  
363 ___________________________________________________________________________________________________
364
365 ### Stage Connection {#creating-controls-stage}
366
367 Methods are provided that can be overridden if notification is required when our control is connected to or disconnected from the stage.
368 An up call to the Control class is necessary if these methods are overridden.
369  
370 ~~~{.cpp}
371 // C++
372 void MyUIControlImpl::OnStageConnection( int depth )
373 {
374   // Do any other operations required upon stage connection
375
376   // Up call to Control at the end
377   Control::OnStageConnection( depth );
378 }
379 ~~~
380 ~~~{.cpp}
381 // C++
382 void MyUIControlImpl::OnStageDisconnection()
383 {
384   // Do any other operations required upon stage disconnection
385
386   // Up call to Control at the end
387   Control::OnStageDisconnection();
388 }
389 ~~~
390  
391 ___________________________________________________________________________________________________
392
393 ### Size Negotiation {#creating-controls-size-negotiation}
394
395 The following methods must be overridden for size negotiation to work correctly with a custom control.
396  
397 ~~~{.cpp}
398 // C++
399 Vector3 MyUIControlImpl::GetNaturalSize()
400 {
401   // Return the natural size of the control
402   // This depends on our layout
403   // If we have one visual, then we can return the natural size of that
404   // If we have more visuals, then we need to calculate their positions within our control and work out the overall size we would like our control to be
405
406   // After working out the natural size of visuals that belong to this control,
407   // should also chain up to ensure other visuals belonging to the base class are
408   // also taken into account:
409   Vector2 baseSize = Control::GetNaturalSize(); // returns the size of the background.
410 }
411 ~~~
412 ~~~{.cpp}
413 // C++
414 float MyUIControlImpl::GetHeightForWidth( float width )
415 {
416   // Called by the size negotiation algorithm if we have a fixed width
417   // We should calculate the height we would like our control to be for that width
418
419   // Should also chain up to determine the base class's preferred height:
420   float baseHeight = Control::GetHeightForWidth( width );
421
422 }
423 ~~~
424 ~~~{.cpp}
425 // C++
426 float MyUIControlImpl::GetWidthForHeight( float height )
427 {
428   // Called by the size negotiation algorithm if we have a fixed height
429   // We should calculate the width we would like our control to be for that height
430
431   // Should also chain up to determine the base class's preferred width:
432   float baseWidth = Control::GetWidth( height );
433 }
434 ~~~
435 ~~~{.cpp}
436 // C++
437 void MyUIControlImpl::OnRelayout( const Vector2& size, RelayoutContainer& container )
438 {
439   // The size is what we have been given and what our control needs to fit into
440   // Here, we need to set the position and the size of our visuals
441   // If we have other controls/actors as children
442   //  - Add the control/actor to the container paired with the size required
443   //  - To ensure this works, you need to set up the control with a relayout policy of USE_ASSIGNED_SIZE
444   //  - DO NOT CALL SetSize on this control: This will trigger another size negotiation calculation
445   // DO NOT chain up to base class.
446 }
447 ~~~
448 More information on size negotiation can be found [here](@ref size-negotiation-controls).
449  
450 ___________________________________________________________________________________________________
451
452 ### Clipping Support {#creating-controls-clipping}
453
454 When an Actor is set to clip its children, the renderers have to be added manually in order to specify what its children need to clip to.
455 The Control base class automates the creation of the renderers/visuals when it is set to clip its children.
456  
457 This is only done if the application or custom control writer has not added any renderers to the Control or registered any visuals
458 (regardless of whether these visuals are enabled or not).
459  
460 If custom control writers want to define the clipping visuals themselves, then they should register all required visuals before the control is staged.
461  
462 ___________________________________________________________________________________________________
463
464 ### Other Features {#creating-controls-other}
465
466  + [Background](@ref background)
467  
468 ___________________________________________________________________________________________________
469
470 @class _Guide_Creating_UI_Controls
471
472 */