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