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