Removal of PropertyValueMap, using Property::Map instead
[platform/core/uifw/dali-toolkit.git] / base / dali-toolkit / public-api / controls / control-impl.cpp
1 /*
2  * Copyright (c) 2014 Samsung Electronics Co., Ltd.
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  *
16  */
17
18 #include <dali-toolkit/public-api/controls/control-impl.h>
19
20 #include <stack>
21
22 #include <dali/integration-api/debug.h>
23
24 #include "dali-toolkit/internal/controls/relayout-controller.h"
25 #include "dali-toolkit/internal/controls/relayout-helper.h"
26 #include "dali-toolkit/public-api/focus-manager/keyinput-focus-manager.h"
27 #include "dali-toolkit/public-api/focus-manager/keyboard-focus-manager.h"
28 #include <dali-toolkit/public-api/controls/control.h>
29
30 #include <dali-toolkit/public-api/styling/style-manager.h>
31 #include <dali-toolkit/internal/styling/style-manager-impl.h>
32
33 namespace Dali
34 {
35
36 namespace Toolkit
37 {
38
39 const Property::Index Control::PROPERTY_BACKGROUND_COLOR      = Internal::Control::CONTROL_PROPERTY_START_INDEX;
40 const Property::Index Control::PROPERTY_BACKGROUND            = Internal::Control::CONTROL_PROPERTY_START_INDEX + 1;
41 const Property::Index Control::PROPERTY_WIDTH_POLICY          = Internal::Control::CONTROL_PROPERTY_START_INDEX + 2;
42 const Property::Index Control::PROPERTY_HEIGHT_POLICY         = Internal::Control::CONTROL_PROPERTY_START_INDEX + 3;
43 const Property::Index Control::PROPERTY_MINIMUM_SIZE          = Internal::Control::CONTROL_PROPERTY_START_INDEX + 4;
44 const Property::Index Control::PROPERTY_MAXIMUM_SIZE          = Internal::Control::CONTROL_PROPERTY_START_INDEX + 5;
45 const Property::Index Control::PROPERTY_KEY_INPUT_FOCUS       = Internal::Control::CONTROL_PROPERTY_START_INDEX + 6;
46
47 namespace
48 {
49
50 const Scripting::StringEnum< Control::SizePolicy > SIZE_POLICY_STRING_TABLE[] =
51 {
52   { "FIXED",      Control::Fixed      },
53   { "MINIMUM",    Control::Minimum    },
54   { "MAXIMUM",    Control::Maximum    },
55   { "RANGE",      Control::Range      },
56   { "FLEXIBLE",   Control::Flexible   },
57 };
58 const unsigned int SIZE_POLICY_STRING_TABLE_COUNT = sizeof( SIZE_POLICY_STRING_TABLE ) / sizeof( SIZE_POLICY_STRING_TABLE[0] );
59
60 #if defined(DEBUG_ENABLED)
61 Integration::Log::Filter* gLogFilter  = Integration::Log::Filter::New(Debug::NoLogging, false, "LOG_CONTROL");
62 #endif
63
64 const float MAX_FLOAT_VALUE( std::numeric_limits<float>::max() );
65 const Vector3 MAX_SIZE( MAX_FLOAT_VALUE, MAX_FLOAT_VALUE, MAX_FLOAT_VALUE );
66 const float BACKGROUND_ACTOR_Z_POSITION( -0.1f );
67
68 BaseHandle Create()
69 {
70   return Internal::Control::New();
71 }
72
73 TypeRegistration CONTROL_TYPE( typeid(Control), typeid(CustomActor), Create );
74
75 // Property Registration after Internal::Control::Impl definition below
76
77 TypeAction ACTION_TYPE_1( CONTROL_TYPE, Toolkit::Control::ACTION_CONTROL_ACTIVATED, &Internal::Control::DoAction );
78
79 SignalConnectorType SIGNAL_CONNECTOR_1( CONTROL_TYPE, Toolkit::Control::SIGNAL_KEY_EVENT,     &Internal::Control::DoConnectSignal );
80 SignalConnectorType SIGNAL_CONNECTOR_2( CONTROL_TYPE, Toolkit::Control::SIGNAL_TAPPED,        &Internal::Control::DoConnectSignal );
81 SignalConnectorType SIGNAL_CONNECTOR_3( CONTROL_TYPE, Toolkit::Control::SIGNAL_PANNED,        &Internal::Control::DoConnectSignal );
82 SignalConnectorType SIGNAL_CONNECTOR_4( CONTROL_TYPE, Toolkit::Control::SIGNAL_PINCHED,       &Internal::Control::DoConnectSignal );
83 SignalConnectorType SIGNAL_CONNECTOR_5( CONTROL_TYPE, Toolkit::Control::SIGNAL_LONG_PRESSED,  &Internal::Control::DoConnectSignal );
84
85 /**
86  * Structure which holds information about the background of a control
87  */
88 struct Background
89 {
90   Actor actor;   ///< Either a MeshActor or an ImageActor
91   Vector4 color; ///< The color of the actor.
92
93   /**
94    * Constructor
95    */
96   Background()
97   : actor(),
98     color( Color::WHITE )
99   {
100   }
101 };
102
103 /**
104  * Helper function to calculate a dimension given the policy of that dimension; the minimum &
105  * maximum values that dimension can be; and the allocated value for that dimension.
106  *
107  * @param[in]  policy     The size policy for that dimension.
108  * @param[in]  minimum    The minimum value that dimension can be.
109  * @param[in]  maximum    The maximum value that dimension can be.
110  * @param[in]  allocated  The value allocated for that dimension.
111  *
112  * @return The value that the dimension should be.
113  *
114  * @note This does not handle Control::Fixed policy.
115  */
116 float Calculate( Control::SizePolicy policy, float minimum, float maximum, float allocated )
117 {
118   float size( allocated );
119
120   switch( policy )
121   {
122     case Control::Fixed:
123     {
124       // Use allocated value
125       break;
126     }
127
128     case Control::Minimum:
129     {
130       // Size is always at least the minimum.
131       size = std::max( allocated, minimum );
132       break;
133     }
134
135     case Control::Maximum:
136     {
137       // Size can grow but up to a maximum value.
138       size = std::min( allocated, maximum );
139       break;
140     }
141
142     case Control::Range:
143     {
144       // Size is at least the minimum and can grow up to the maximum
145       size = std::max( size, minimum );
146       size = std::min( size, maximum );
147      break;
148     }
149
150     case Control::Flexible:
151     {
152       // Size grows or shrinks with no limits.
153       size = allocated;
154       break;
155     }
156
157     default:
158     {
159       DALI_ASSERT_DEBUG( false && "This function was not intended to be used by any other policy." );
160       break;
161     }
162   }
163
164   return size;
165 }
166
167 /**
168  * Creates a white coloured Mesh.
169  */
170 Mesh CreateMesh()
171 {
172   Vector3 white( Color::WHITE );
173
174   MeshData meshData;
175
176   // Create vertices with a white color (actual color is set by actor color)
177   MeshData::VertexContainer vertices(4);
178   vertices[ 0 ] = MeshData::Vertex( Vector3( -0.5f, -0.5f, 0.0f ), Vector2::ZERO, white );
179   vertices[ 1 ] = MeshData::Vertex( Vector3(  0.5f, -0.5f, 0.0f ), Vector2::ZERO, white );
180   vertices[ 2 ] = MeshData::Vertex( Vector3( -0.5f,  0.5f, 0.0f ), Vector2::ZERO, white );
181   vertices[ 3 ] = MeshData::Vertex( Vector3(  0.5f,  0.5f, 0.0f ), Vector2::ZERO, white );
182
183   // Specify all the faces
184   MeshData::FaceIndices faces;
185   faces.reserve( 6 ); // 2 triangles in Quad
186   faces.push_back( 0 ); faces.push_back( 3 ); faces.push_back( 1 );
187   faces.push_back( 0 ); faces.push_back( 2 ); faces.push_back( 3 );
188
189   // Create the mesh data from the vertices and faces
190   meshData.SetMaterial( Material::New( "ControlMaterial" ) );
191   meshData.SetVertices( vertices );
192   meshData.SetFaceIndices( faces );
193   meshData.SetHasColor( true );
194
195   return Mesh::New( meshData );
196 }
197
198 /**
199  * Sets all the required properties for the background actor.
200  *
201  * @param[in]  actor              The actor to set the properties on.
202  * @param[in]  constrainingIndex  The property index to constrain the parent's size on.
203  * @param[in]  color              The required color of the actor.
204  */
205 void SetupBackgroundActor( Actor actor, Property::Index constrainingIndex, const Vector4& color )
206 {
207   actor.SetColor( color );
208   actor.SetPositionInheritanceMode( USE_PARENT_POSITION_PLUS_LOCAL_POSITION );
209   actor.SetColorMode( USE_OWN_MULTIPLY_PARENT_COLOR );
210   actor.SetZ( BACKGROUND_ACTOR_Z_POSITION );
211
212   Constraint constraint = Constraint::New<Vector3>( constrainingIndex,
213                                                     ParentSource( Actor::SIZE ),
214                                                     EqualToConstraint() );
215   actor.ApplyConstraint( constraint );
216 }
217
218 } // unnamed namespace
219
220 namespace Internal
221 {
222
223 class Control::Impl : public ConnectionTracker
224 {
225 public:
226
227   /**
228    * Size indices for mMinMaxSize array
229    */
230   enum
231   {
232     MIN_SIZE_INDEX = 0,
233     MAX_SIZE_INDEX = 1
234   };
235
236 public:
237   // Construction & Destruction
238   Impl(Control& controlImpl)
239   : mControlImpl( controlImpl ),
240     mBackground( NULL ),
241     mStartingPinchScale( NULL ),
242     mKeyEventSignalV2(),
243     mPinchGestureDetector(),
244     mPanGestureDetector(),
245     mTapGestureDetector(),
246     mLongPressGestureDetector(),
247     mCurrentSize(),
248     mNaturalSize(),
249     mWidthPolicy( Toolkit::Control::Fixed ),
250     mHeightPolicy( Toolkit::Control::Fixed ),
251     mFlags( Control::CONTROL_BEHAVIOUR_NONE ),
252     mInsideRelayout( false ),
253     mIsKeyboardNavigationSupported( false ),
254     mIsKeyboardFocusGroup( false ),
255     mInitialized( false )
256   {
257   }
258
259   ~Impl()
260   {
261     // All gesture detectors will be destroyed so no need to disconnect.
262     delete mBackground;
263     delete mStartingPinchScale;
264   }
265
266   // Gesture Detection Methods
267
268   void PinchDetected(Actor actor, PinchGesture pinch)
269   {
270     mControlImpl.OnPinch(pinch);
271   }
272
273   void PanDetected(Actor actor, PanGesture pan)
274   {
275     mControlImpl.OnPan(pan);
276   }
277
278   void TapDetected(Actor actor, TapGesture tap)
279   {
280     mControlImpl.OnTap(tap);
281   }
282
283   void LongPressDetected(Actor actor, LongPressGesture longPress)
284   {
285     mControlImpl.OnLongPress(longPress);
286   }
287
288   // Background Methods
289
290   /**
291    * Only creates an instance of the background if we actually use it.
292    * @return A reference to the Background structure.
293    */
294   Background& GetBackground()
295   {
296     if ( !mBackground )
297     {
298       mBackground = new Background;
299     }
300     return *mBackground;
301   }
302
303   // Properties
304
305   /**
306    * Called when a property of an object of this type is set.
307    * @param[in] object The object whose property is set.
308    * @param[in] index The property index.
309    * @param[in] value The new property value.
310    */
311   static void SetProperty( BaseObject* object, Property::Index index, const Property::Value& value )
312   {
313     Toolkit::Control control = Toolkit::Control::DownCast( BaseHandle( object ) );
314
315     if ( control )
316     {
317       Control& controlImpl( control.GetImplementation() );
318
319       switch ( index )
320       {
321         case Toolkit::Control::PROPERTY_BACKGROUND_COLOR:
322         {
323           controlImpl.SetBackgroundColor( value.Get< Vector4 >() );
324           break;
325         }
326
327         case Toolkit::Control::PROPERTY_BACKGROUND:
328         {
329           if ( value.HasKey( "image" ) )
330           {
331             Property::Map imageMap = value.GetValue( "image" ).Get< Property::Map >();
332             Image image = Scripting::NewImage( imageMap );
333
334             if ( image )
335             {
336               controlImpl.SetBackground( image );
337             }
338           }
339           else if ( value.Get< Property::Map >().Empty() )
340           {
341             // An empty map means the background is no longer required
342             controlImpl.ClearBackground();
343           }
344           break;
345         }
346
347         case Toolkit::Control::PROPERTY_WIDTH_POLICY:
348         {
349           controlImpl.mImpl->mWidthPolicy = Scripting::GetEnumeration< Toolkit::Control::SizePolicy >( value.Get< std::string >(), SIZE_POLICY_STRING_TABLE, SIZE_POLICY_STRING_TABLE_COUNT );
350           break;
351         }
352
353         case Toolkit::Control::PROPERTY_HEIGHT_POLICY:
354         {
355           controlImpl.mImpl->mHeightPolicy = Scripting::GetEnumeration< Toolkit::Control::SizePolicy >( value.Get< std::string >(), SIZE_POLICY_STRING_TABLE, SIZE_POLICY_STRING_TABLE_COUNT );
356           break;
357         }
358
359         case Toolkit::Control::PROPERTY_MINIMUM_SIZE:
360         {
361           controlImpl.SetMinimumSize( value.Get< Vector3 >() );
362           break;
363         }
364
365         case Toolkit::Control::PROPERTY_MAXIMUM_SIZE:
366         {
367           controlImpl.SetMaximumSize( value.Get< Vector3 >() );
368           break;
369         }
370
371         case Toolkit::Control::PROPERTY_KEY_INPUT_FOCUS:
372         {
373           if ( value.Get< bool >() )
374           {
375             controlImpl.SetKeyInputFocus();
376           }
377           else
378           {
379             controlImpl.ClearKeyInputFocus();
380           }
381           break;
382         }
383       }
384     }
385   }
386
387   /**
388    * Called to retrieve a property of an object of this type.
389    * @param[in] object The object whose property is to be retrieved.
390    * @param[in] index The property index.
391    * @return The current value of the property.
392    */
393   static Property::Value GetProperty( BaseObject* object, Property::Index index )
394   {
395     Property::Value value;
396
397     Toolkit::Control control = Toolkit::Control::DownCast( BaseHandle( object ) );
398
399     if ( control )
400     {
401       Control& controlImpl( control.GetImplementation() );
402
403       switch ( index )
404       {
405         case Toolkit::Control::PROPERTY_BACKGROUND_COLOR:
406         {
407           value = controlImpl.GetBackgroundColor();
408           break;
409         }
410
411         case Toolkit::Control::PROPERTY_BACKGROUND:
412         {
413           Property::Map map;
414
415           Actor actor = controlImpl.GetBackgroundActor();
416           if ( actor )
417           {
418             ImageActor imageActor = ImageActor::DownCast( actor );
419             if ( imageActor )
420             {
421               Image image = imageActor.GetImage();
422               Property::Map imageMap;
423               Scripting::CreatePropertyMap( image, imageMap );
424               map[ "image" ] = imageMap;
425             }
426           }
427
428           value = map;
429           break;
430         }
431
432         case Toolkit::Control::PROPERTY_WIDTH_POLICY:
433         {
434           value = std::string( Scripting::GetEnumerationName< Toolkit::Control::SizePolicy >( controlImpl.mImpl->mWidthPolicy, SIZE_POLICY_STRING_TABLE, SIZE_POLICY_STRING_TABLE_COUNT ) );
435           break;
436         }
437
438         case Toolkit::Control::PROPERTY_HEIGHT_POLICY:
439         {
440           value = std::string( Scripting::GetEnumerationName< Toolkit::Control::SizePolicy >( controlImpl.mImpl->mHeightPolicy, SIZE_POLICY_STRING_TABLE, SIZE_POLICY_STRING_TABLE_COUNT ) );
441           break;
442         }
443
444         case Toolkit::Control::PROPERTY_MINIMUM_SIZE:
445         {
446           value = controlImpl.mImpl->GetMinimumSize();
447           break;
448         }
449
450         case Toolkit::Control::PROPERTY_MAXIMUM_SIZE:
451         {
452           value = controlImpl.mImpl->GetMaximumSize();
453           break;
454         }
455
456         case Toolkit::Control::PROPERTY_KEY_INPUT_FOCUS:
457         {
458           value = controlImpl.HasKeyInputFocus();
459           break;
460         }
461       }
462     }
463
464     return value;
465   }
466
467   /**
468    * Helper to get minimum size
469    * @return minimum size
470    */
471   inline const Vector3& GetMinimumSize()
472   {
473     if( mMinMaxSize.Count() > MIN_SIZE_INDEX )
474     {
475       return mMinMaxSize[ MIN_SIZE_INDEX ];
476     }
477     else
478     {
479       // its not been allocated so its ZERO
480       return Vector3::ZERO;
481     }
482   }
483   /**
484    * Helper to Set minimum size
485    * @param size to set
486    */
487   inline void SetMinimumSize( const Vector3& size )
488   {
489     if( mMinMaxSize.Count() > MIN_SIZE_INDEX )
490     {
491       mMinMaxSize[ MIN_SIZE_INDEX ] = size;
492     }
493     else
494     {
495       // its not been allocated so push the new value there
496       mMinMaxSize.PushBack( size );
497     }
498   }
499
500   /**
501    * Helper to get maximum size
502    * @return maximum size
503    */
504   inline const Vector3& GetMaximumSize()
505   {
506     if( mMinMaxSize.Count() > MAX_SIZE_INDEX )
507     {
508       return mMinMaxSize[ MAX_SIZE_INDEX ];
509     }
510     else
511     {
512       // its not been allocated so its MAX_SIZE
513       return MAX_SIZE;
514     }
515   }
516
517   /**
518    * Helper to Set minimum size
519    * @param size to set
520    */
521   inline void SetMaximumSize( const Vector3& size )
522   {
523     if( mMinMaxSize.Count() > MAX_SIZE_INDEX )
524     {
525       mMinMaxSize[ MAX_SIZE_INDEX ] = size;
526     }
527     else if( mMinMaxSize.Count() > MIN_SIZE_INDEX )
528     {
529       // max has not been allocated, but min has
530       mMinMaxSize.PushBack( size );
531     }
532     else
533     {
534       // min and max both unallocated so allocate both
535       mMinMaxSize.Resize( 2u ); // this will reserve and default construct two Vector3s
536       mMinMaxSize[ MAX_SIZE_INDEX ] = size;
537     }
538   }
539
540   // Data
541
542   Control& mControlImpl;
543   Background* mBackground;           ///< Only create the background if we use it
544   Vector3* mStartingPinchScale;      ///< The scale when a pinch gesture starts, TODO: consider removing this
545   Toolkit::Control::KeyEventSignalV2 mKeyEventSignalV2;
546
547   // Gesture Detection
548   PinchGestureDetector mPinchGestureDetector;
549   PanGestureDetector mPanGestureDetector;
550   TapGestureDetector mTapGestureDetector;
551   LongPressGestureDetector mLongPressGestureDetector;
552   // @todo change all these to Vector2 when we have a chance to sanitize the public API as well
553   Vector3 mCurrentSize; ///< Stores the current control's size, this is the negotiated size
554   Vector3 mNaturalSize; ///< Stores the size set through the Actor's API. This is size the actor wants to be. Useful when reset to the initial size is needed.
555   Dali::Vector< Vector3 > mMinMaxSize; ///< Stores the minimum and maximum size if they are set
556
557   Toolkit::Control::SizePolicy mWidthPolicy :3;  ///< Stores the width policy. 3 bits covers 8 values
558   Toolkit::Control::SizePolicy mHeightPolicy :3; ///< Stores the height policy. 3 bits covers 8 values
559   ControlBehaviour mFlags :6;             ///< Flags passed in from constructor. Need to increase this size when new enums are added
560   bool mInsideRelayout:1;                 ///< Detect when were in Relayout
561   bool mIsKeyboardNavigationSupported:1;  ///< Stores whether keyboard navigation is supported by the control.
562   bool mIsKeyboardFocusGroup:1;           ///< Stores whether the control is a focus group.
563   bool mInitialized:1;
564
565   // Properties - these need to be members of Internal::Control::Impl as they need to functions within this class.
566   static PropertyRegistration PROPERTY_1;
567   static PropertyRegistration PROPERTY_2;
568   static PropertyRegistration PROPERTY_3;
569   static PropertyRegistration PROPERTY_4;
570   static PropertyRegistration PROPERTY_5;
571   static PropertyRegistration PROPERTY_6;
572   static PropertyRegistration PROPERTY_7;
573 };
574
575 PropertyRegistration Control::Impl::PROPERTY_1( CONTROL_TYPE, "background-color", Toolkit::Control::PROPERTY_BACKGROUND_COLOR, Property::VECTOR4, &Control::Impl::SetProperty, &Control::Impl::GetProperty );
576 PropertyRegistration Control::Impl::PROPERTY_2( CONTROL_TYPE, "background",       Toolkit::Control::PROPERTY_BACKGROUND,       Property::MAP,     &Control::Impl::SetProperty, &Control::Impl::GetProperty );
577 PropertyRegistration Control::Impl::PROPERTY_3( CONTROL_TYPE, "width-policy",     Toolkit::Control::PROPERTY_WIDTH_POLICY,     Property::STRING,  &Control::Impl::SetProperty, &Control::Impl::GetProperty );
578 PropertyRegistration Control::Impl::PROPERTY_4( CONTROL_TYPE, "height-policy",    Toolkit::Control::PROPERTY_HEIGHT_POLICY,    Property::STRING,  &Control::Impl::SetProperty, &Control::Impl::GetProperty );
579 PropertyRegistration Control::Impl::PROPERTY_5( CONTROL_TYPE, "minimum-size",     Toolkit::Control::PROPERTY_MINIMUM_SIZE,     Property::VECTOR3, &Control::Impl::SetProperty, &Control::Impl::GetProperty );
580 PropertyRegistration Control::Impl::PROPERTY_6( CONTROL_TYPE, "maximum-size",     Toolkit::Control::PROPERTY_MAXIMUM_SIZE,     Property::VECTOR3, &Control::Impl::SetProperty, &Control::Impl::GetProperty );
581 PropertyRegistration Control::Impl::PROPERTY_7( CONTROL_TYPE, "key-input-focus",  Toolkit::Control::PROPERTY_KEY_INPUT_FOCUS,  Property::BOOLEAN, &Control::Impl::SetProperty, &Control::Impl::GetProperty );
582
583 Toolkit::Control Control::New()
584 {
585   // Create the implementation, temporarily owned on stack
586   IntrusivePtr<Control> controlImpl = new Control( CONTROL_BEHAVIOUR_NONE );
587
588   // Pass ownership to handle
589   Toolkit::Control handle( *controlImpl );
590
591   // Second-phase init of the implementation
592   // This can only be done after the CustomActor connection has been made...
593   controlImpl->Initialize();
594
595   return handle;
596 }
597
598 Control::~Control()
599 {
600   delete mImpl;
601 }
602
603 void Control::Initialize()
604 {
605
606   // Calling deriving classes
607   OnInitialize();
608
609   if( mImpl->mFlags & REQUIRES_STYLE_CHANGE_SIGNALS )
610   {
611     Toolkit::StyleManager styleManager = Toolkit::StyleManager::Get();
612
613     // Register for style changes
614     styleManager.StyleChangeSignal().Connect( this, &Control::DoStyleChange );
615
616     // SetTheme
617     GetImpl( styleManager ).ApplyThemeStyle( GetOwner() );
618   }
619
620   SetRequiresHoverEvents(mImpl->mFlags & REQUIRES_HOVER_EVENTS);
621   SetRequiresMouseWheelEvents(mImpl->mFlags & REQUIRES_MOUSE_WHEEL_EVENTS);
622
623   mImpl->mInitialized = true;
624 }
625
626 void Control::EnableGestureDetection(Gesture::Type type)
627 {
628   if ( (type & Gesture::Pinch) && !mImpl->mPinchGestureDetector )
629   {
630     mImpl->mPinchGestureDetector = PinchGestureDetector::New();
631     mImpl->mPinchGestureDetector.DetectedSignal().Connect(mImpl, &Impl::PinchDetected);
632     mImpl->mPinchGestureDetector.Attach(Self());
633   }
634
635   if ( (type & Gesture::Pan) && !mImpl->mPanGestureDetector )
636   {
637     mImpl->mPanGestureDetector = PanGestureDetector::New();
638     mImpl->mPanGestureDetector.DetectedSignal().Connect(mImpl, &Impl::PanDetected);
639     mImpl->mPanGestureDetector.Attach(Self());
640   }
641
642   if ( (type & Gesture::Tap) && !mImpl->mTapGestureDetector )
643   {
644     mImpl->mTapGestureDetector = TapGestureDetector::New();
645     mImpl->mTapGestureDetector.DetectedSignal().Connect(mImpl, &Impl::TapDetected);
646     mImpl->mTapGestureDetector.Attach(Self());
647   }
648
649   if ( (type & Gesture::LongPress) && !mImpl->mLongPressGestureDetector )
650   {
651     mImpl->mLongPressGestureDetector = LongPressGestureDetector::New();
652     mImpl->mLongPressGestureDetector.DetectedSignal().Connect(mImpl, &Impl::LongPressDetected);
653     mImpl->mLongPressGestureDetector.Attach(Self());
654   }
655 }
656
657 void Control::DisableGestureDetection(Gesture::Type type)
658 {
659   if ( (type & Gesture::Pinch) && mImpl->mPinchGestureDetector )
660   {
661     mImpl->mPinchGestureDetector.Detach(Self());
662     mImpl->mPinchGestureDetector.Reset();
663   }
664
665   if ( (type & Gesture::Pan) && mImpl->mPanGestureDetector )
666   {
667     mImpl->mPanGestureDetector.Detach(Self());
668     mImpl->mPanGestureDetector.Reset();
669   }
670
671   if ( (type & Gesture::Tap) && mImpl->mTapGestureDetector )
672   {
673     mImpl->mTapGestureDetector.Detach(Self());
674     mImpl->mTapGestureDetector.Reset();
675   }
676
677   if ( (type & Gesture::LongPress) && mImpl->mLongPressGestureDetector)
678   {
679     mImpl->mLongPressGestureDetector.Detach(Self());
680     mImpl->mLongPressGestureDetector.Reset();
681   }
682 }
683
684 PinchGestureDetector Control::GetPinchGestureDetector() const
685 {
686   return mImpl->mPinchGestureDetector;
687 }
688
689 PanGestureDetector Control::GetPanGestureDetector() const
690 {
691   return mImpl->mPanGestureDetector;
692 }
693
694 TapGestureDetector Control::GetTapGestureDetector() const
695 {
696   return mImpl->mTapGestureDetector;
697 }
698
699 LongPressGestureDetector Control::GetLongPressGestureDetector() const
700 {
701   return mImpl->mLongPressGestureDetector;
702 }
703
704 void Control::SetBackgroundColor( const Vector4& color )
705 {
706   Background& background( mImpl->GetBackground() );
707
708   if ( background.actor )
709   {
710     // Just set the actor color
711     background.actor.SetColor( color );
712   }
713   else
714   {
715     // Create Mesh Actor
716     MeshActor meshActor = MeshActor::New( CreateMesh() );
717
718     meshActor.SetAffectedByLighting( false );
719     SetupBackgroundActor( meshActor, Actor::SCALE, color );
720
721     // Set the background actor before adding so that we do not inform deriving classes
722     background.actor = meshActor;
723     Self().Add( meshActor );
724   }
725
726   background.color = color;
727 }
728
729 Vector4 Control::GetBackgroundColor() const
730 {
731   if ( mImpl->mBackground )
732   {
733     return mImpl->mBackground->color;
734   }
735   return Color::TRANSPARENT;
736 }
737
738 void Control::SetBackground( Image image )
739 {
740   Background& background( mImpl->GetBackground() );
741
742   if ( background.actor )
743   {
744     // Remove Current actor, unset AFTER removal so that we do not inform deriving classes
745     Self().Remove( background.actor );
746     background.actor = NULL;
747   }
748
749   ImageActor imageActor = ImageActor::New( image );
750   SetupBackgroundActor( imageActor, Actor::SIZE, background.color );
751
752   // Set the background actor before adding so that we do not inform derived classes
753   background.actor = imageActor;
754   Self().Add( imageActor );
755 }
756
757 void Control::ClearBackground()
758 {
759   if ( mImpl->mBackground )
760   {
761     Background& background( mImpl->GetBackground() );
762     Self().Remove( background.actor );
763
764     delete mImpl->mBackground;
765     mImpl->mBackground = NULL;
766   }
767 }
768
769 Actor Control::GetBackgroundActor() const
770 {
771   if ( mImpl->mBackground )
772   {
773     return mImpl->mBackground->actor;
774   }
775
776   return Actor();
777 }
778
779 void Control::OnThemeChange( Toolkit::StyleManager styleManager )
780 {
781   GetImpl( styleManager ).ApplyThemeStyle( GetOwner() );
782 }
783
784 void Control::OnPinch(PinchGesture pinch)
785 {
786   if( !( mImpl->mStartingPinchScale ) )
787   {
788     // lazy allocate
789     mImpl->mStartingPinchScale = new Vector3;
790   }
791
792   if( pinch.state == Gesture::Started )
793   {
794     *( mImpl->mStartingPinchScale ) = Self().GetCurrentScale();
795   }
796
797   Self().SetScale( *( mImpl->mStartingPinchScale ) * pinch.scale );
798 }
799
800 void Control::OnStageConnection()
801 {
802   RelayoutRequest();
803
804   // Notify derived classes.
805   OnControlStageConnection();
806 }
807
808 void Control::OnStageDisconnection()
809 {
810   // Notify derived classes
811   OnControlStageDisconnection();
812 }
813
814 void Control::OnChildAdd(Actor& child)
815 {
816   // If this is the background actor, then we do not want to relayout or inform deriving classes
817   if ( mImpl->mBackground && ( child == mImpl->mBackground->actor ) )
818   {
819     return;
820   }
821
822   // Request for relayout as we may need to position the new child and old ones
823   RelayoutRequest();
824
825   // Notify derived classes.
826   OnControlChildAdd( child );
827 }
828
829 void Control::OnChildRemove(Actor& child)
830 {
831   // If this is the background actor, then we do not want to relayout or inform deriving classes
832   if ( mImpl->mBackground && ( child == mImpl->mBackground->actor ) )
833   {
834     return;
835   }
836
837   // Request for relayout as we may need to re-position the old child
838   RelayoutRequest();
839
840   // Notify derived classes.
841   OnControlChildRemove( child );
842 }
843
844 void Control::OnSizeSet(const Vector3& targetSize)
845 {
846   if( ( !mImpl->mInsideRelayout ) && ( targetSize != mImpl->mNaturalSize ) )
847   {
848     // Only updates size if set through Actor's API
849     mImpl->mNaturalSize = targetSize;
850   }
851
852   if( targetSize != mImpl->mCurrentSize )
853   {
854     // Update control size.
855     mImpl->mCurrentSize = targetSize;
856
857     // Notify derived classes.
858     OnControlSizeSet( targetSize );
859   }
860 }
861
862 void Control::OnSizeAnimation(Animation& animation, const Vector3& targetSize)
863 {
864   // @todo consider animating negotiated child sizes to target size
865 }
866
867 bool Control::OnTouchEvent(const TouchEvent& event)
868 {
869   return false; // Do not consume
870 }
871
872 bool Control::OnHoverEvent(const HoverEvent& event)
873 {
874   return false; // Do not consume
875 }
876
877 bool Control::OnKeyEvent(const KeyEvent& event)
878 {
879   return false; // Do not consume
880 }
881
882 bool Control::OnMouseWheelEvent(const MouseWheelEvent& event)
883 {
884   return false; // Do not consume
885 }
886
887 void Control::OnKeyInputFocusGained()
888 {
889   // Do Nothing
890 }
891
892 void Control::OnKeyInputFocusLost()
893 {
894   // Do Nothing
895 }
896
897 Actor Control::GetChildByAlias(const std::string& actorAlias)
898 {
899   return Actor();
900 }
901
902 bool Control::OnAccessibilityPan(PanGesture gesture)
903 {
904   return false; // Accessibility pan gesture is not handled by default
905 }
906
907 bool Control::OnAccessibilityTouch(const TouchEvent& touchEvent)
908 {
909   return false; // Accessibility touch event is not handled by default
910 }
911
912 bool Control::OnAccessibilityValueChange(bool isIncrease)
913 {
914   return false; // Accessibility value change action is not handled by default
915 }
916
917
918 void Control::SetKeyboardNavigationSupport(bool isSupported)
919 {
920   mImpl->mIsKeyboardNavigationSupported = isSupported;
921 }
922
923 bool Control::IsKeyboardNavigationSupported()
924 {
925   return mImpl->mIsKeyboardNavigationSupported;
926 }
927
928 void Control::SetAsKeyboardFocusGroup(bool isFocusGroup)
929 {
930   mImpl->mIsKeyboardFocusGroup = isFocusGroup;
931
932   // The following line will be removed when the deprecated API in KeyboardFocusManager is deleted
933   Toolkit::KeyboardFocusManager::Get().SetAsFocusGroup(Self(), isFocusGroup);
934 }
935
936 bool Control::IsKeyboardFocusGroup()
937 {
938   return Toolkit::KeyboardFocusManager::Get().IsFocusGroup(Self());
939 }
940
941 Actor Control::GetNextKeyboardFocusableActor(Actor currentFocusedActor, Toolkit::Control::KeyboardFocusNavigationDirection direction, bool loopEnabled)
942 {
943   return Actor();
944 }
945
946 bool Control::DoAction(BaseObject* object, const std::string& actionName, const std::vector<Property::Value>& attributes)
947 {
948   bool ret = false;
949
950   if( object && (actionName == Toolkit::Control::ACTION_CONTROL_ACTIVATED) )
951   {
952     Toolkit::Control control = Toolkit::Control::DownCast( BaseHandle( object ) );
953     if( control )
954     {
955       // if cast succeeds there is an implementation so no need to check
956       control.GetImplementation().OnActivated();
957     }
958   }
959
960   return ret;
961 }
962
963 bool Control::DoConnectSignal( BaseObject* object, ConnectionTrackerInterface* tracker, const std::string& signalName, FunctorDelegate* functor )
964 {
965   Dali::BaseHandle handle( object );
966
967   bool connected( false );
968   Toolkit::Control control = Toolkit::Control::DownCast(handle);
969   if ( control )
970   {
971     Control& controlImpl( control.GetImplementation() );
972     connected = true;
973
974     if ( Toolkit::Control::SIGNAL_KEY_EVENT == signalName )
975     {
976       controlImpl.KeyEventSignal().Connect( tracker, functor );
977     }
978     else if( Toolkit::Control::SIGNAL_TAPPED == signalName )
979     {
980       controlImpl.EnableGestureDetection( Gesture::Tap );
981       controlImpl.GetTapGestureDetector().DetectedSignal().Connect( tracker, functor );
982     }
983     else if( Toolkit::Control::SIGNAL_PANNED == signalName )
984     {
985       controlImpl.EnableGestureDetection( Gesture::Pan );
986       controlImpl.GetPanGestureDetector().DetectedSignal().Connect( tracker, functor );
987     }
988     else if( Toolkit::Control::SIGNAL_PINCHED == signalName )
989     {
990       controlImpl.EnableGestureDetection( Gesture::Pinch );
991       controlImpl.GetPinchGestureDetector().DetectedSignal().Connect( tracker, functor );
992     }
993     else if( Toolkit::Control::SIGNAL_LONG_PRESSED == signalName )
994     {
995       controlImpl.EnableGestureDetection( Gesture::LongPress );
996       controlImpl.GetLongPressGestureDetector().DetectedSignal().Connect( tracker, functor );
997     }
998     else
999     {
1000       // signalName does not match any signal
1001       connected = false;
1002     }
1003   }
1004   return connected;
1005 }
1006
1007 void Control::DoStyleChange( Toolkit::StyleManager styleManager, StyleChange change )
1008 {
1009   if( change.themeChange )
1010   {
1011     OnThemeChange( styleManager );
1012   }
1013   else if( change.defaultFontChange || change.defaultFontSizeChange )
1014   {
1015     OnFontChange( change.defaultFontChange, change.defaultFontSizeChange );
1016   }
1017 }
1018
1019 Toolkit::Control::KeyEventSignalV2& Control::KeyEventSignal()
1020 {
1021   return mImpl->mKeyEventSignalV2;
1022 }
1023
1024 void Control::SetSizePolicy( Toolkit::Control::SizePolicy widthPolicy, Toolkit::Control::SizePolicy heightPolicy )
1025 {
1026   bool relayoutRequest( false );
1027
1028   if ( ( mImpl->mWidthPolicy != widthPolicy ) || ( mImpl->mHeightPolicy != heightPolicy ) )
1029   {
1030     relayoutRequest = true;
1031   }
1032
1033   mImpl->mWidthPolicy = widthPolicy;
1034   mImpl->mHeightPolicy = heightPolicy;
1035
1036   // Ensure RelayoutRequest is called AFTER new policies have been set.
1037   if ( relayoutRequest )
1038   {
1039     RelayoutRequest();
1040   }
1041 }
1042
1043 void Control::GetSizePolicy( Toolkit::Control::SizePolicy& widthPolicy, Toolkit::Control::SizePolicy& heightPolicy ) const
1044 {
1045   widthPolicy = mImpl->mWidthPolicy;
1046   heightPolicy = mImpl->mHeightPolicy;
1047 }
1048
1049 void Control::SetMinimumSize( const Vector3& size )
1050 {
1051   const Vector3& minSize = mImpl->GetMinimumSize();
1052   if ( fabsf( minSize.width - size.width ) > Math::MACHINE_EPSILON_1000 ||
1053        fabsf( minSize.height - size.height ) > Math::MACHINE_EPSILON_1000 )
1054   {
1055     mImpl->SetMinimumSize( size );
1056
1057     // Only relayout if our control is using the minimum or range policy.
1058     if ( ( mImpl->mHeightPolicy == Toolkit::Control::Minimum ) || ( mImpl->mWidthPolicy  == Toolkit::Control::Minimum ) ||
1059          ( mImpl->mHeightPolicy == Toolkit::Control::Range   ) || ( mImpl->mWidthPolicy  == Toolkit::Control::Range   ) )
1060     {
1061       RelayoutRequest();
1062     }
1063   }
1064 }
1065
1066 const Vector3& Control::GetMinimumSize() const
1067 {
1068   return mImpl->GetMinimumSize();
1069 }
1070
1071 void Control::SetMaximumSize( const Vector3& size )
1072 {
1073   const Vector3& maxSize = mImpl->GetMaximumSize();
1074   if ( fabsf( maxSize.width - size.width ) > Math::MACHINE_EPSILON_1000 ||
1075        fabsf( maxSize.height - size.height ) > Math::MACHINE_EPSILON_1000 )
1076   {
1077     mImpl->SetMaximumSize( size );
1078
1079     // Only relayout if our control is using the maximum or range policy.
1080     if ( ( mImpl->mHeightPolicy == Toolkit::Control::Maximum ) || ( mImpl->mWidthPolicy  == Toolkit::Control::Maximum ) ||
1081          ( mImpl->mHeightPolicy == Toolkit::Control::Range   ) || ( mImpl->mWidthPolicy  == Toolkit::Control::Range   ) )
1082     {
1083       RelayoutRequest();
1084     }
1085   }
1086 }
1087
1088 const Vector3& Control::GetMaximumSize() const
1089 {
1090   return mImpl->GetMaximumSize();
1091 }
1092
1093 Vector3 Control::GetNaturalSize()
1094 {
1095   // could be overridden in derived classes.
1096   return mImpl->mNaturalSize;
1097 }
1098
1099 float Control::GetHeightForWidth( float width )
1100 {
1101   // could be overridden in derived classes.
1102   float height( 0.0f );
1103   if ( mImpl->mNaturalSize.width > 0.0f )
1104   {
1105     height = mImpl->mNaturalSize.height * width / mImpl->mNaturalSize.width;
1106   }
1107   return height;
1108 }
1109
1110 float Control::GetWidthForHeight( float height )
1111 {
1112   // could be overridden in derived classes.
1113   float width( 0.0f );
1114   if ( mImpl->mNaturalSize.height > 0.0f )
1115   {
1116     width = mImpl->mNaturalSize.width * height / mImpl->mNaturalSize.height;
1117   }
1118   return width;
1119 }
1120
1121 const Vector3& Control::GetControlSize() const
1122 {
1123   return mImpl->mCurrentSize;
1124 }
1125
1126 const Vector3& Control::GetSizeSet() const
1127 {
1128   return mImpl->mNaturalSize;
1129 }
1130
1131 void Control::SetKeyInputFocus()
1132 {
1133   if( Self().OnStage() )
1134   {
1135     Toolkit::KeyInputFocusManager::Get().SetFocus(Toolkit::Control::DownCast(Self()));
1136   }
1137 }
1138
1139 bool Control::HasKeyInputFocus()
1140 {
1141   bool result = false;
1142   if( Self().OnStage() )
1143   {
1144     result = Toolkit::KeyInputFocusManager::Get().IsKeyboardListener(Toolkit::Control::DownCast(Self()));
1145   }
1146   return result;
1147 }
1148
1149 void Control::ClearKeyInputFocus()
1150 {
1151   if( Self().OnStage() )
1152   {
1153     Toolkit::KeyInputFocusManager::Get().RemoveFocus(Toolkit::Control::DownCast(Self()));
1154   }
1155 }
1156
1157 void Control::RelayoutRequest()
1158 {
1159   // unfortunate double negative but thats to guarantee new controls get size negotiation
1160   // by default and have to "opt-out" if they dont want it
1161   if( !(mImpl->mFlags & NO_SIZE_NEGOTIATION) )
1162   {
1163     Internal::RelayoutController::Request();
1164   }
1165 }
1166
1167 void Control::Relayout(Vector2 size, ActorSizeContainer& container)
1168 {
1169   // Avoids relayout again when OnSizeSet callback arrives.
1170   mImpl->mInsideRelayout = true;
1171   Self().SetSize( size );
1172   // @todo this really needs to be at the end of method but not sure why the scope used to be only the SetSize, needs to be cleaned up in size negotiation rework
1173   mImpl->mInsideRelayout = false;
1174
1175   // Only relayout controls which requested to be relaid out.
1176   OnRelaidOut( size, container );
1177 }
1178
1179 void Control::Relayout( Actor actor, Vector2 size, ActorSizeContainer& container )
1180 {
1181   if ( actor )
1182   {
1183     Toolkit::Control control( Toolkit::Control::DownCast( actor ) );
1184     if( control )
1185     {
1186       control.GetImplementation().NegotiateSize( size, container );
1187     }
1188     else
1189     {
1190       container.push_back( ActorSizePair( actor, size ) );
1191     }
1192   }
1193 }
1194
1195 void Control::OnRelaidOut( Vector2 size, ActorSizeContainer& container )
1196 {
1197   unsigned int numChildren = Self().GetChildCount();
1198
1199   for( unsigned int i=0; i<numChildren; ++i )
1200   {
1201     container.push_back( ActorSizePair( Self().GetChildAt(i), size ) );
1202   }
1203 }
1204
1205 void Control::NegotiateSize( Vector2 allocatedSize, ActorSizeContainer& container )
1206 {
1207   Vector2 size;
1208
1209   if ( mImpl->mWidthPolicy == Toolkit::Control::Fixed )
1210   {
1211     if ( mImpl->mHeightPolicy == Toolkit::Control::Fixed )
1212     {
1213       // If a control says it has a fixed size, then use the size set by the application / control.
1214       Vector2 setSize( mImpl->mNaturalSize );
1215       if ( setSize != Vector2::ZERO )
1216       {
1217         size = setSize;
1218
1219         // Policy is set to Fixed, so if the application / control has not set one of the dimensions,
1220         // then we should use the natural size of the control rather than the full allocation.
1221         if ( EqualsZero( size.width ) )
1222         {
1223           size.width = GetWidthForHeight( size.height );
1224         }
1225         else if ( EqualsZero( size.height ) )
1226         {
1227           size.height = GetHeightForWidth( size.width );
1228         }
1229       }
1230       else
1231       {
1232         // If that is not set then set the size to the control's natural size
1233         size = Vector2( GetNaturalSize() );
1234       }
1235     }
1236     else
1237     {
1238       // Width is fixed so if the application / control has set it, then use that.
1239       if ( !EqualsZero( mImpl->mNaturalSize.width ) )
1240       {
1241         size.width = mImpl->mNaturalSize.width;
1242       }
1243       else
1244       {
1245         // Otherwise, set the width to what has been allocated.
1246         size.width = allocatedSize.width;
1247       }
1248
1249       // Height is flexible so ask control what the height should be for our width.
1250       size.height = GetHeightForWidth( size.width );
1251
1252       // Ensure height is within our policy rules
1253       size.height = Calculate( mImpl->mHeightPolicy, GetMinimumSize().height, GetMaximumSize().height, size.height );
1254     }
1255   }
1256   else
1257   {
1258     if ( mImpl->mHeightPolicy == Toolkit::Control::Fixed )
1259     {
1260       // Height is fixed so if the application / control has set it, then use that.
1261       if ( !EqualsZero( mImpl->mNaturalSize.height ) )
1262       {
1263         size.height = mImpl->mNaturalSize.height;
1264       }
1265       else
1266       {
1267         // Otherwise, set the height to what has been allocated.
1268         size.height = allocatedSize.height;
1269       }
1270
1271       // Width is flexible so ask control what the width should be for our height.
1272       size.width = GetWidthForHeight( size.height );
1273
1274       // Ensure width is within our policy rules
1275       size.width = Calculate( mImpl->mWidthPolicy, mImpl->GetMinimumSize().width, mImpl->GetMaximumSize().width, size.width );
1276     }
1277     else
1278     {
1279       // Width and height are BOTH flexible.
1280       // Calculate the width and height using the policy rules.
1281       size.width = Calculate( mImpl->mWidthPolicy, mImpl->GetMinimumSize().width, mImpl->GetMaximumSize().width, allocatedSize.width );
1282       size.height = Calculate( mImpl->mHeightPolicy, mImpl->GetMinimumSize().height, mImpl->GetMaximumSize().height, allocatedSize.height );
1283     }
1284   }
1285
1286   // If the width has not been set, then set to the allocated width.
1287   // Also if the width set is greater than the allocated, then set to allocated (no exceed support).
1288   if ( EqualsZero( size.width ) || ( size.width > allocatedSize.width ) )
1289   {
1290     size.width = allocatedSize.width;
1291   }
1292
1293   // If the height has not been set, then set to the allocated height.
1294   // Also if the height set is greater than the allocated, then set to allocated (no exceed support).
1295   if ( EqualsZero( size.height ) || ( size.height > allocatedSize.height ) )
1296   {
1297     size.height = allocatedSize.height;
1298   }
1299
1300   DALI_LOG_INFO( gLogFilter, Debug::Verbose,
1301                  "%p: Natural: [%.2f, %.2f] Allocated: [%.2f, %.2f] Set: [%.2f, %.2f]\n",
1302                  Self().GetObjectPtr(),
1303                  GetNaturalSize().x, GetNaturalSize().y,
1304                  allocatedSize.x, allocatedSize.y,
1305                  size.x, size.y );
1306
1307   Relayout( size, container );
1308 }
1309
1310 bool Control::EmitKeyEventSignal( const KeyEvent& event )
1311 {
1312   // Guard against destruction during signal emission
1313   Dali::Toolkit::Control handle( GetOwner() );
1314
1315   bool consumed = false;
1316
1317   // signals are allocated dynamically when someone connects
1318   if ( !mImpl->mKeyEventSignalV2.Empty() )
1319   {
1320     consumed = mImpl->mKeyEventSignalV2.Emit( handle, event );
1321   }
1322
1323   if (!consumed)
1324   {
1325     // Notification for derived classes
1326     consumed = OnKeyEvent(event);
1327   }
1328
1329   return consumed;
1330 }
1331
1332 void Control::SignalConnected( SlotObserver* slotObserver, CallbackBase* callback )
1333 {
1334   mImpl->SignalConnected( slotObserver, callback );
1335 }
1336
1337 void Control::SignalDisconnected( SlotObserver* slotObserver, CallbackBase* callback )
1338 {
1339   mImpl->SignalDisconnected( slotObserver, callback );
1340 }
1341
1342 Control::Control( ControlBehaviour behaviourFlags )
1343 : CustomActorImpl( behaviourFlags & REQUIRES_TOUCH_EVENTS ),
1344   mImpl(new Impl(*this))
1345 {
1346   mImpl->mFlags = behaviourFlags;
1347 }
1348
1349 } // namespace Internal
1350
1351 } // namespace Toolkit
1352
1353 } // namespace Dali