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