Prevent fighting of setting scroll position property by ItemView and ScrollBar
[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, &ControlImpl::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     // This OnStyleChange(StyleChange change ) is deprecated, use OnFontChange instead
957     OnStyleChange( change );
958
959     OnFontChange( change.defaultFontChange, change.defaultFontSizeChange );
960   }
961 }
962
963 Toolkit::Control::KeyEventSignalV2& Control::KeyEventSignal()
964 {
965   return mImpl->mKeyEventSignalV2;
966 }
967
968 void Control::SetSizePolicy( Toolkit::Control::SizePolicy widthPolicy, Toolkit::Control::SizePolicy heightPolicy )
969 {
970   bool relayoutRequest( false );
971
972   if ( ( mImpl->mWidthPolicy != widthPolicy ) || ( mImpl->mHeightPolicy != heightPolicy ) )
973   {
974     relayoutRequest = true;
975   }
976
977   mImpl->mWidthPolicy = widthPolicy;
978   mImpl->mHeightPolicy = heightPolicy;
979
980   // Ensure RelayoutRequest is called AFTER new policies have been set.
981   if ( relayoutRequest )
982   {
983     RelayoutRequest();
984   }
985 }
986
987 void Control::GetSizePolicy( Toolkit::Control::SizePolicy& widthPolicy, Toolkit::Control::SizePolicy& heightPolicy ) const
988 {
989   widthPolicy = mImpl->mWidthPolicy;
990   heightPolicy = mImpl->mHeightPolicy;
991 }
992
993 void Control::SetMinimumSize( const Vector3& size )
994 {
995   const Vector3& minSize = mImpl->GetMinimumSize();
996   if ( fabsf( minSize.width - size.width ) > Math::MACHINE_EPSILON_1000 ||
997        fabsf( minSize.height - size.height ) > Math::MACHINE_EPSILON_1000 )
998   {
999     mImpl->SetMinimumSize( size );
1000
1001     // Only relayout if our control is using the minimum or range policy.
1002     if ( ( mImpl->mHeightPolicy == Toolkit::Control::Minimum ) || ( mImpl->mWidthPolicy  == Toolkit::Control::Minimum ) ||
1003          ( mImpl->mHeightPolicy == Toolkit::Control::Range   ) || ( mImpl->mWidthPolicy  == Toolkit::Control::Range   ) )
1004     {
1005       RelayoutRequest();
1006     }
1007   }
1008 }
1009
1010 const Vector3& Control::GetMinimumSize() const
1011 {
1012   return mImpl->GetMinimumSize();
1013 }
1014
1015 void Control::SetMaximumSize( const Vector3& size )
1016 {
1017   const Vector3& maxSize = mImpl->GetMaximumSize();
1018   if ( fabsf( maxSize.width - size.width ) > Math::MACHINE_EPSILON_1000 ||
1019        fabsf( maxSize.height - size.height ) > Math::MACHINE_EPSILON_1000 )
1020   {
1021     mImpl->SetMaximumSize( size );
1022
1023     // Only relayout if our control is using the maximum or range policy.
1024     if ( ( mImpl->mHeightPolicy == Toolkit::Control::Maximum ) || ( mImpl->mWidthPolicy  == Toolkit::Control::Maximum ) ||
1025          ( mImpl->mHeightPolicy == Toolkit::Control::Range   ) || ( mImpl->mWidthPolicy  == Toolkit::Control::Range   ) )
1026     {
1027       RelayoutRequest();
1028     }
1029   }
1030 }
1031
1032 const Vector3& Control::GetMaximumSize() const
1033 {
1034   return mImpl->GetMaximumSize();
1035 }
1036
1037 Vector3 Control::GetNaturalSize()
1038 {
1039   // could be overridden in derived classes.
1040   return mImpl->mNaturalSize;
1041 }
1042
1043 float Control::GetHeightForWidth( float width )
1044 {
1045   // could be overridden in derived classes.
1046   float height( 0.0f );
1047   if ( mImpl->mNaturalSize.width > 0.0f )
1048   {
1049     height = mImpl->mNaturalSize.height * width / mImpl->mNaturalSize.width;
1050   }
1051   return height;
1052 }
1053
1054 float Control::GetWidthForHeight( float height )
1055 {
1056   // could be overridden in derived classes.
1057   float width( 0.0f );
1058   if ( mImpl->mNaturalSize.height > 0.0f )
1059   {
1060     width = mImpl->mNaturalSize.width * height / mImpl->mNaturalSize.height;
1061   }
1062   return width;
1063 }
1064
1065 const Vector3& Control::GetControlSize() const
1066 {
1067   return mImpl->mCurrentSize;
1068 }
1069
1070 const Vector3& Control::GetSizeSet() const
1071 {
1072   return mImpl->mNaturalSize;
1073 }
1074
1075 void Control::SetKeyInputFocus()
1076 {
1077   if( Self().OnStage() )
1078   {
1079     Toolkit::KeyInputFocusManager::Get().SetFocus(Toolkit::Control::DownCast(Self()));
1080   }
1081 }
1082
1083 bool Control::HasKeyInputFocus()
1084 {
1085   bool result = false;
1086   if( Self().OnStage() )
1087   {
1088     result = Toolkit::KeyInputFocusManager::Get().IsKeyboardListener(Toolkit::Control::DownCast(Self()));
1089   }
1090   return result;
1091 }
1092
1093 void Control::ClearKeyInputFocus()
1094 {
1095   if( Self().OnStage() )
1096   {
1097     Toolkit::KeyInputFocusManager::Get().RemoveFocus(Toolkit::Control::DownCast(Self()));
1098   }
1099 }
1100
1101 void Control::RelayoutRequest()
1102 {
1103   // unfortunate double negative but thats to guarantee new controls get size negotiation
1104   // by default and have to "opt-out" if they dont want it
1105   if( !(mImpl->mFlags & NO_SIZE_NEGOTIATION) )
1106   {
1107     Internal::RelayoutController::Request();
1108   }
1109 }
1110
1111 void Control::Relayout(Vector2 size, ActorSizeContainer& container)
1112 {
1113   // Avoids relayout again when OnSizeSet callback arrives.
1114   mImpl->mInsideRelayout = true;
1115   Self().SetSize( size );
1116   // @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
1117   mImpl->mInsideRelayout = false;
1118
1119   // Only relayout controls which requested to be relaid out.
1120   OnRelaidOut( size, container );
1121 }
1122
1123 void Control::Relayout( Actor actor, Vector2 size, ActorSizeContainer& container )
1124 {
1125   if ( actor )
1126   {
1127     Toolkit::Control control( Toolkit::Control::DownCast( actor ) );
1128     if( control )
1129     {
1130       control.GetImplementation().NegotiateSize( size, container );
1131     }
1132     else
1133     {
1134       container.push_back( ActorSizePair( actor, size ) );
1135     }
1136   }
1137 }
1138
1139 void Control::OnRelaidOut( Vector2 size, ActorSizeContainer& container )
1140 {
1141   unsigned int numChildren = Self().GetChildCount();
1142
1143   for( unsigned int i=0; i<numChildren; ++i )
1144   {
1145     container.push_back( ActorSizePair( Self().GetChildAt(i), size ) );
1146   }
1147 }
1148
1149 void Control::NegotiateSize( Vector2 allocatedSize, ActorSizeContainer& container )
1150 {
1151   Vector2 size;
1152
1153   if ( mImpl->mWidthPolicy == Toolkit::Control::Fixed )
1154   {
1155     if ( mImpl->mHeightPolicy == Toolkit::Control::Fixed )
1156     {
1157       // If a control says it has a fixed size, then use the size set by the application / control.
1158       Vector2 setSize( mImpl->mNaturalSize );
1159       if ( setSize != Vector2::ZERO )
1160       {
1161         size = setSize;
1162
1163         // Policy is set to Fixed, so if the application / control has not set one of the dimensions,
1164         // then we should use the natural size of the control rather than the full allocation.
1165         if ( EqualsZero( size.width ) )
1166         {
1167           size.width = GetWidthForHeight( size.height );
1168         }
1169         else if ( EqualsZero( size.height ) )
1170         {
1171           size.height = GetHeightForWidth( size.width );
1172         }
1173       }
1174       else
1175       {
1176         // If that is not set then set the size to the control's natural size
1177         size = Vector2( GetNaturalSize() );
1178       }
1179     }
1180     else
1181     {
1182       // Width is fixed so if the application / control has set it, then use that.
1183       if ( !EqualsZero( mImpl->mNaturalSize.width ) )
1184       {
1185         size.width = mImpl->mNaturalSize.width;
1186       }
1187       else
1188       {
1189         // Otherwise, set the width to what has been allocated.
1190         size.width = allocatedSize.width;
1191       }
1192
1193       // Height is flexible so ask control what the height should be for our width.
1194       size.height = GetHeightForWidth( size.width );
1195
1196       // Ensure height is within our policy rules
1197       size.height = Calculate( mImpl->mHeightPolicy, GetMinimumSize().height, GetMaximumSize().height, size.height );
1198     }
1199   }
1200   else
1201   {
1202     if ( mImpl->mHeightPolicy == Toolkit::Control::Fixed )
1203     {
1204       // Height is fixed so if the application / control has set it, then use that.
1205       if ( !EqualsZero( mImpl->mNaturalSize.height ) )
1206       {
1207         size.height = mImpl->mNaturalSize.height;
1208       }
1209       else
1210       {
1211         // Otherwise, set the height to what has been allocated.
1212         size.height = allocatedSize.height;
1213       }
1214
1215       // Width is flexible so ask control what the width should be for our height.
1216       size.width = GetWidthForHeight( size.height );
1217
1218       // Ensure width is within our policy rules
1219       size.width = Calculate( mImpl->mWidthPolicy, mImpl->GetMinimumSize().width, mImpl->GetMaximumSize().width, size.width );
1220     }
1221     else
1222     {
1223       // Width and height are BOTH flexible.
1224       // Calculate the width and height using the policy rules.
1225       size.width = Calculate( mImpl->mWidthPolicy, mImpl->GetMinimumSize().width, mImpl->GetMaximumSize().width, allocatedSize.width );
1226       size.height = Calculate( mImpl->mHeightPolicy, mImpl->GetMinimumSize().height, mImpl->GetMaximumSize().height, allocatedSize.height );
1227     }
1228   }
1229
1230   // If the width has not been set, then set to the allocated width.
1231   // Also if the width set is greater than the allocated, then set to allocated (no exceed support).
1232   if ( EqualsZero( size.width ) || ( size.width > allocatedSize.width ) )
1233   {
1234     size.width = allocatedSize.width;
1235   }
1236
1237   // If the height has not been set, then set to the allocated height.
1238   // Also if the height set is greater than the allocated, then set to allocated (no exceed support).
1239   if ( EqualsZero( size.height ) || ( size.height > allocatedSize.height ) )
1240   {
1241     size.height = allocatedSize.height;
1242   }
1243
1244   DALI_LOG_INFO( gLogFilter, Debug::Verbose,
1245                  "%p: Natural: [%.2f, %.2f] Allocated: [%.2f, %.2f] Set: [%.2f, %.2f]\n",
1246                  Self().GetObjectPtr(),
1247                  GetNaturalSize().x, GetNaturalSize().y,
1248                  allocatedSize.x, allocatedSize.y,
1249                  size.x, size.y );
1250
1251   Relayout( size, container );
1252 }
1253
1254 bool Control::EmitKeyEventSignal( const KeyEvent& event )
1255 {
1256   // Guard against destruction during signal emission
1257   Dali::Toolkit::Control handle( GetOwner() );
1258
1259   bool consumed = false;
1260
1261   // signals are allocated dynamically when someone connects
1262   if ( !mImpl->mKeyEventSignalV2.Empty() )
1263   {
1264     consumed = mImpl->mKeyEventSignalV2.Emit( handle, event );
1265   }
1266
1267   if (!consumed)
1268   {
1269     // Notification for derived classes
1270     consumed = OnKeyEvent(event);
1271   }
1272
1273   return consumed;
1274 }
1275
1276 void Control::SignalConnected( SlotObserver* slotObserver, CallbackBase* callback )
1277 {
1278   mImpl->SignalConnected( slotObserver, callback );
1279 }
1280
1281 void Control::SignalDisconnected( SlotObserver* slotObserver, CallbackBase* callback )
1282 {
1283   mImpl->SignalDisconnected( slotObserver, callback );
1284 }
1285
1286 std::size_t Control::GetConnectionCount() const
1287 {
1288   return mImpl->GetConnectionCount();
1289 }
1290
1291 Control::Control( bool requiresTouchEvents )
1292 : CustomActorImpl( requiresTouchEvents ),
1293   mImpl(new Impl(*this))
1294 {
1295 }
1296
1297 Control::Control( ControlBehaviour behaviourFlags )
1298 : CustomActorImpl( behaviourFlags & REQUIRES_TOUCH_EVENTS ),
1299   mImpl(new Impl(*this))
1300 {
1301   mImpl->mFlags = behaviourFlags;
1302 }
1303
1304 } // namespace Internal
1305
1306 } // namespace Toolkit
1307
1308 } // namespace Dali