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