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