Merge "If the height is small even if scrolling is enabled, it should be elide."...
[platform/core/uifw/dali-toolkit.git] / docs / content / shared-javascript-and-cpp-documentation / creating-custom-controls.md
index c6e1380..c5d3a7c 100644 (file)
@@ -13,13 +13,26 @@ Custom controls are created using the [handle/body idiom](@ref handle-body-idiom
 ![ ](../assets/img/creating-custom-controls/control-handle-body.png)
 ![ ](creating-custom-controls/control-handle-body.png)
  
+Namespaces are important
++ The handle & body classes should have the same name but in different namespaces
++ TypeRegistry relies on this convention
++ Here our custom control requires
+  + MyUIControl
+  + Internal::MyUIControl
 ### General Guidelines:
 + Try to avoid adding C++ APIs as they become difficult to maintain.
   + Use **properties** as much as possible as Controls should be data driven.
   + These controls will be used through JavaScript and JSON files so need to be compatible.
-+ 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).
++ Bear in mind that the Control can be updated when the properties change (e.g. style change)
+  + Ensure control deals with these property changes gracefully
+  + Not just the first time they are set
++ Use Visuals rather than creating several child Actors
+  + DALi rendering pipeline more efficient
 + Accessibility actions should be considered when designing the Control.
 + Consider using signals if the application needs to be react to changes in the control state.
++ Use of Gestures should be preferred over analysing raw touch events
++ Check if you need to chain up to base class if overriding certain methods
  
 ___________________________________________________________________________________________________
 
@@ -33,7 +46,34 @@ Currently, this is devel-api though, so is subject to change.
  
 ![ ](../assets/img/creating-custom-controls/rendering.png)
 ![ ](creating-custom-controls/rendering.png)
+
+To add a visual to a control, first create a Property for the visual of type MAP, and ensure the name has a suffix of "_VISUAL". Then the visual is normally defined in the stylesheet, and the definition sent via SetProperty(), where you would then create the visual:
+
+~~~{.cpp}
+// C++
+void Internal::MyUIControl::SetProperty( BaseObject* object, Property::Index index, const Property::Value& value )
+{
+  MyUIControl control = MyUIControl::DownCast( Dali::BaseHandle( object ) );
+  switch( index )
+  {
+    case MyUIControl::Property::MY_VISUAL:
+    {
+      Toolkit::VisualFactory visualFactory = Toolkit::VisualFactory::Get();
+      const Property::Map *map = value.GetMap();
+      if( map && !map->Empty() )
+      {
+        Toolkit::Visual::Base visual = visualFactory.CreateVisual( *map );
+        GetImplementation( control ).RegisterVisual( index, visual );
+      }
+      break;
+    }
+    //...
+  }
+}
+~~~
+
+The [Visuals](@ref visuals) section describes the property maps that can be used for each visual type.
+
 ___________________________________________________________________________________________________
 
 ## Ensuring Control is Stylable {#creating-controls-stylable}
@@ -76,6 +116,8 @@ The TypeRegistry is used to register your custom control.
 This allows the creation of the control via a JSON file, as well as registering properties, signals and actions.
  
 To ensure your control is stylable, the process described in [Type Registration](@ref type-registration) should be followed.
+
+#### Properties
 To aid development, some macros are provided for registering properties which are described in the [Property](@ref properties) section.
  
 Control properties can be one of three types:
@@ -103,10 +145,10 @@ It is recommended to do provide a New() method in the custom control implementat
 
 ~~~{.cpp}
 // C++
-MyUIControl MyUIControlImpl::New()
+MyUIControl Internal::MyUIControl::New()
 {
   // Create the implementation, temporarily owned on stack
-  IntrusivePtr< MyUIControlImpl > controlImpl = new MyUIControlImpl;
+  IntrusivePtr< Internal::MyUIControl > controlImpl = new Internal::MyUIControl;
 
   // Pass ownership to handle
   MyUIControl handle( *controlImpl );
@@ -123,9 +165,10 @@ This will trigger the Dali::Toolkit::Internal::Control Initialize() method which
 This should be overridden by the custom ui control.
 ~~~{.cpp}
 // C++
-void MyUIControlImpl::OnInitialize()
+void Internal::MyUIControl::OnInitialize()
 {
-  // Create visuals, register events etc.
+  // Create visuals using the VisualFactory, register events etc.
+  // Register any created visuals with Control base class
 }
 ~~~
 ___________________________________________________________________________________________________
@@ -134,13 +177,14 @@ ________________________________________________________________________________
 
 Dali::Toolkit::Internal::Control provides several behaviours which are specified through its constructor (@ref Dali::Toolkit::Internal::Control::Control()).
  
-| Behaviour                            | Description                                                             |
-|--------------------------------------|-------------------------------------------------------------------------|
-| ACTOR_BEHAVIOUR_NONE                 | No behaviour required.                                                  |
-| REQUIRES_HOVER_EVENTS                | If our control requires [hover events](@ref creating-controls-events).  |
-| REQUIRES_WHEEL_EVENTS                | If our control requires [wheel events](@ref creating-controls-events).  |
-| REQUIRES_STYLE_CHANGE_SIGNALS        | True if need to monitor style change signals such as Theme/Font change. |
-| REQUIRES_KEYBOARD_NAVIGATION_SUPPORT | True if need to support keyboard navigation.                            |
+| Behaviour                            | Description                                                                                                    |
+|--------------------------------------|----------------------------------------------------------------------------------------------------------------|
+| CONTROL_BEHAVIOUR_DEFAULT              | Default behavior (size negotiation is on, style change is monitored, event callbacks are not called.                                      |
+| DISABLE_SIZE_NEGOTIATION             | If our control does not need size negotiation, i.e. control will be skipped by the size negotiation algorithm. |
+| REQUIRES_HOVER_EVENTS                | If our control requires [hover events](@ref creating-controls-events).                                         |
+| REQUIRES_WHEEL_EVENTS                | If our control requires [wheel events](@ref creating-controls-events).                                         |
+| DISABLE_STYLE_CHANGE_SIGNALS         | True if control should not monitor style change signals such as Theme/Font change.                                         |
+| REQUIRES_KEYBOARD_NAVIGATION_SUPPORT | True if need to support keyboard navigation.                                                                   |
 ___________________________________________________________________________________________________
 
 ### Touch, Hover & Wheel Events {#creating-controls-events}
@@ -149,10 +193,10 @@ ________________________________________________________________________________
 + A **hover event** is when a pointer moves within the bounds of a custom actor (e.g. mouse pointer or hover pointer).
 + A **wheel event** is when the mouse wheel (or similar) is moved while hovering over an actor (via a mouse pointer or hover pointer).
  
-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.
+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.
 ~~~{.cpp}
 // C++
-bool MyUIControlImpl::OnHoverEvent( const HoverEvent& event )
+bool Internal::MyUIControl::OnHoverEvent( const HoverEvent& event )
 {
   bool consumed = false;
 
@@ -164,7 +208,7 @@ bool MyUIControlImpl::OnHoverEvent( const HoverEvent& event )
 ~~~
 ~~~{.cpp}
 // C++
-bool MyUIControlImpl::OnWheelEvent( const WheelEvent& event )
+bool Internal::MyUIControl::OnWheelEvent( const WheelEvent& event )
 {
   bool consumed = false;
 
@@ -193,7 +237,7 @@ If any of these detectors are required then this can be specified in the OnIniti
  
 ~~~{.cpp}
 // C++
-void MyUIControlImpl::OnInitialize()
+void Internal::MyUIControl::OnInitialize()
 {
   // Only enable pan gesture detection
   EnableGestureDetection( Gesture::Pan );
@@ -215,28 +259,28 @@ panGestureDetector.AddDirection( PanGestureDetector::DIRECTION_VERTICAL );
 Finally, the appropriate method should be overridden:
 ~~~{.cpp}
 // C++
-void MyUIControlImpl::OnPan( const PanGesture& pan )
+void Internal::MyUIControl::OnPan( const PanGesture& pan )
 {
   // Handle pan-gesture
 }
 ~~~
 ~~~{.cpp}
 // C++
-void MyUIControlImpl::OnPinch( const PinchGesture& pinch )
+void Internal::MyUIControl::OnPinch( const PinchGesture& pinch )
 {
   // Handle pinch-event
 }
 ~~~
 ~~~{.cpp}
 // C++
-void MyUIControlImpl::OnTap( const TapGesture& tap )
+void Internal::MyUIControl::OnTap( const TapGesture& tap )
 {
   // Handle tap-gesture
 }
 ~~~
 ~~~{.cpp}
 // C++
-void MyUIControlImpl::OnLongPress( const LongPressGesture& longPress )
+void Internal::MyUIControl::OnLongPress( const LongPressGesture& longPress )
 {
   // Handle long-press-gesture
 }
@@ -322,17 +366,17 @@ An up call to the Control class is necessary if these methods are overridden.
  
 ~~~{.cpp}
 // C++
-void MyUIControlImpl::OnChildAdd( Actor& child );
+void Internal::MyUIControl::OnChildAdd( Actor& child );
 {
-  // Up call to Control first
-  Control::OnChildAdd( child );
-
   // Do any other operations required upon child addition
+
+  // Up call to Control at the end
+  Control::OnChildAdd( child );
 }
 ~~~
 ~~~{.cpp}
 // C++
-void MyUIControlImpl::OnChildRemove( Actor& child );
+void Internal::MyUIControl::OnChildRemove( Actor& child );
 {
   // Do any other operations required upon child removal
 
@@ -352,17 +396,17 @@ An up call to the Control class is necessary if these methods are overridden.
  
 ~~~{.cpp}
 // C++
-void MyUIControlImpl::OnStageConnection( int depth )
+void Internal::MyUIControl::OnStageConnection( int depth )
 {
-  // Up call to Control first
-  Control::OnStageConnection( depth );
-
   // Do any other operations required upon stage connection
+
+  // Up call to Control at the end
+  Control::OnStageConnection( depth );
 }
 ~~~
 ~~~{.cpp}
 // C++
-void MyUIControlImpl::OnStageDisconnection()
+void Internal::MyUIControl::OnStageDisconnection()
 {
   // Do any other operations required upon stage disconnection
 
@@ -373,31 +417,75 @@ void MyUIControlImpl::OnStageDisconnection()
  
 ___________________________________________________________________________________________________
 
-### Size {#creating-controls-size}
+### Size Negotiation {#creating-controls-size-negotiation}
 
-Methods are provided that can be overridden if notification is required when our control's size is manipulated.
-An up call to the Control class is necessary if these methods are overridden.
+The following methods must be overridden for size negotiation to work correctly with a custom control.
  
 ~~~{.cpp}
 // C++
-void MyUIControlImpl::OnSizeSet( const Vector3& targetSize )
+Vector3 Internal::MyUIControl::GetNaturalSize()
 {
-  // Up call to Control
-  Control::OnSizeSet( targetSize );
+  // Return the natural size of the control
+  // This depends on our layout
+  // If we have one visual, then we can return the natural size of that
+  // 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
+
+  // After working out the natural size of visuals that belong to this control,
+  // should also chain up to ensure other visuals belonging to the base class are
+  // also taken into account:
+  Vector2 baseSize = Control::GetNaturalSize(); // returns the size of the background.
+}
+~~~
+~~~{.cpp}
+// C++
+float Internal::MyUIControl::GetHeightForWidth( float width )
+{
+  // Called by the size negotiation algorithm if we have a fixed width
+  // We should calculate the height we would like our control to be for that width
+
+  // Should also chain up to determine the base class's preferred height:
+  float baseHeight = Control::GetHeightForWidth( width );
 
-  // Do any other operations required upon size set
 }
 ~~~
 ~~~{.cpp}
 // C++
-void MyUIControlImpl::OnSizeAnimation( Animation& animation, const Vector3& targetSize )
+float Internal::MyUIControl::GetWidthForHeight( float height )
 {
-  // Up call to Control
-  Control::OnSizeAnimation( animation, targetSize );
+  // Called by the size negotiation algorithm if we have a fixed height
+  // We should calculate the width we would like our control to be for that height
 
-  // Do any other operations required upon size animation
+  // Should also chain up to determine the base class's preferred width:
+  float baseWidth = Control::GetWidth( height );
 }
 ~~~
+~~~{.cpp}
+// C++
+void Internal::MyUIControl::OnRelayout( const Vector2& size, RelayoutContainer& container )
+{
+  // The size is what we have been given and what our control needs to fit into
+  // Here, we need to set the position and the size of our visuals
+  // If we have other controls/actors as children
+  //  - Add the control/actor to the container paired with the size required
+  //  - To ensure this works, you need to set up the control with a relayout policy of USE_ASSIGNED_SIZE
+  //  - DO NOT CALL SetSize on this control: This will trigger another size negotiation calculation
+  // DO NOT chain up to base class.
+}
+~~~
+More information on size negotiation can be found [here](@ref size-negotiation-controls).
+___________________________________________________________________________________________________
+
+### Clipping Support {#creating-controls-clipping}
+
+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.
+The Control base class automates the creation of the visuals when it is set to clip its children.
+This is only done if the application or custom control writer has not
+added any Renderers to the Control or registered any visuals
+(regardless of whether these visuals are enabled or not).
+If custom control writers want to define the clipping visuals themselves, then they should register all required visuals before the control is staged.
  
 ___________________________________________________________________________________________________