[dali_1.2.29] Merge branch 'devel/master'
[platform/core/uifw/dali-toolkit.git] / dali-toolkit / public-api / controls / control-impl.cpp
1 /*
2  * Copyright (c) 2017 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 <cstring> // for strcmp
23 #include <limits>
24 #include <stack>
25 #include <typeinfo>
26 #include <dali/public-api/animation/constraint.h>
27 #include <dali/public-api/animation/constraints.h>
28 #include <dali/public-api/object/type-registry.h>
29 #include <dali/public-api/object/type-registry-helper.h>
30 #include <dali/public-api/rendering/renderer.h>
31 #include <dali/public-api/size-negotiation/relayout-container.h>
32 #include <dali/devel-api/common/owner-container.h>
33 #include <dali/devel-api/object/handle-devel.h>
34 #include <dali/devel-api/scripting/enum-helper.h>
35 #include <dali/devel-api/scripting/scripting.h>
36 #include <dali/integration-api/debug.h>
37
38 // INTERNAL INCLUDES
39 #include <dali-toolkit/public-api/focus-manager/keyboard-focus-manager.h>
40 #include <dali-toolkit/public-api/controls/control.h>
41 #include <dali-toolkit/public-api/styling/style-manager.h>
42 #include <dali-toolkit/public-api/visuals/color-visual-properties.h>
43 #include <dali-toolkit/devel-api/controls/control-depth-index-ranges.h>
44 #include <dali-toolkit/devel-api/controls/control-devel.h>
45 #include <dali-toolkit/devel-api/visuals/visual-properties-devel.h>
46 #include <dali-toolkit/devel-api/visual-factory/visual-factory.h>
47 #include <dali-toolkit/devel-api/focus-manager/keyinput-focus-manager.h>
48 #include <dali-toolkit/internal/styling/style-manager-impl.h>
49 #include <dali-toolkit/internal/visuals/color/color-visual.h>
50 #include <dali-toolkit/internal/visuals/transition-data-impl.h>
51 #include <dali-toolkit/internal/visuals/visual-string-constants.h>
52 #include <dali-toolkit/devel-api/align-enums.h>
53 #include <dali-toolkit/internal/controls/tooltip/tooltip.h>
54
55 namespace Dali
56 {
57 extern bool CaseInsensitiveStringCompare( const std::string& a, const std::string& b );
58
59 namespace Toolkit
60 {
61
62 namespace Internal
63 {
64
65 extern const Dali::Scripting::StringEnum ControlStateTable[];
66 extern const unsigned int ControlStateTableCount;
67
68
69 // Not static or anonymous - shared with other translation units
70 const Scripting::StringEnum ControlStateTable[] = {
71   { "NORMAL",   Toolkit::DevelControl::NORMAL   },
72   { "FOCUSED",  Toolkit::DevelControl::FOCUSED  },
73   { "DISABLED", Toolkit::DevelControl::DISABLED },
74 }; const unsigned int ControlStateTableCount = sizeof( ControlStateTable ) / sizeof( ControlStateTable[0] );
75
76 } // Internal namespace
77
78 namespace
79 {
80
81 #if defined(DEBUG_ENABLED)
82 Debug::Filter* gLogFilter = Debug::Filter::New( Debug::NoLogging, false, "LOG_CONTROL_VISUALS");
83 #endif
84
85 DALI_ENUM_TO_STRING_TABLE_BEGIN( CLIPPING_MODE )
86 DALI_ENUM_TO_STRING_WITH_SCOPE( ClippingMode, DISABLED )
87 DALI_ENUM_TO_STRING_WITH_SCOPE( ClippingMode, CLIP_CHILDREN )
88 DALI_ENUM_TO_STRING_TABLE_END( CLIPPING_MODE )
89
90 /**
91  * Struct used to store Visual within the control, index is a unique key for each visual.
92  */
93 struct RegisteredVisual
94 {
95   Property::Index index;
96   Toolkit::Visual::Base visual;
97   bool enabled;
98
99   RegisteredVisual( Property::Index aIndex, Toolkit::Visual::Base &aVisual, bool aEnabled)
100   : index(aIndex), visual(aVisual), enabled(aEnabled)
101   {
102   }
103 };
104
105 typedef Dali::OwnerContainer< RegisteredVisual* > RegisteredVisualContainer;
106
107 /**
108  *  Finds visual in given array, returning true if found along with the iterator for that visual as a out parameter
109  */
110 bool FindVisual( Property::Index targetIndex, RegisteredVisualContainer& visuals, RegisteredVisualContainer::Iterator& iter )
111 {
112   for ( iter = visuals.Begin(); iter != visuals.End(); iter++ )
113   {
114     if ( (*iter)->index ==  targetIndex )
115     {
116       return true;
117     }
118   }
119   return false;
120 }
121
122 Toolkit::Visual::Base GetVisualByName(
123   RegisteredVisualContainer& visuals,
124   const std::string& visualName )
125 {
126   Toolkit::Visual::Base visualHandle;
127
128   RegisteredVisualContainer::Iterator iter;
129   for ( iter = visuals.Begin(); iter != visuals.End(); iter++ )
130   {
131     Toolkit::Visual::Base visual = (*iter)->visual;
132     if( visual && visual.GetName() == visualName )
133     {
134       visualHandle = visual;
135       break;
136     }
137   }
138   return visualHandle;
139 }
140
141 /**
142  * Creates control through type registry
143  */
144 BaseHandle Create()
145 {
146   return Internal::Control::New();
147 }
148
149 /**
150  * Performs actions as requested using the action name.
151  * @param[in] object The object on which to perform the action.
152  * @param[in] actionName The action to perform.
153  * @param[in] attributes The attributes with which to perfrom this action.
154  * @return true if action has been accepted by this control
155  */
156 const char* ACTION_ACCESSIBILITY_ACTIVATED = "accessibilityActivated";
157 static bool DoAction( BaseObject* object, const std::string& actionName, const Property::Map& attributes )
158 {
159   bool ret = false;
160
161   if( object && ( 0 == strcmp( actionName.c_str(), ACTION_ACCESSIBILITY_ACTIVATED ) ) )
162   {
163     Toolkit::Control control = Toolkit::Control::DownCast( BaseHandle( object ) );
164     if( control )
165     {
166       // if cast succeeds there is an implementation so no need to check
167       ret = Internal::GetImplementation( control ).OnAccessibilityActivated();
168     }
169   }
170
171   return ret;
172 }
173
174 /**
175  * Connects a callback function with the object's signals.
176  * @param[in] object The object providing the signal.
177  * @param[in] tracker Used to disconnect the signal.
178  * @param[in] signalName The signal to connect to.
179  * @param[in] functor A newly allocated FunctorDelegate.
180  * @return True if the signal was connected.
181  * @post If a signal was connected, ownership of functor was passed to CallbackBase. Otherwise the caller is responsible for deleting the unused functor.
182  */
183 const char* SIGNAL_KEY_EVENT = "keyEvent";
184 const char* SIGNAL_KEY_INPUT_FOCUS_GAINED = "keyInputFocusGained";
185 const char* SIGNAL_KEY_INPUT_FOCUS_LOST = "keyInputFocusLost";
186 const char* SIGNAL_TAPPED = "tapped";
187 const char* SIGNAL_PANNED = "panned";
188 const char* SIGNAL_PINCHED = "pinched";
189 const char* SIGNAL_LONG_PRESSED = "longPressed";
190 static bool DoConnectSignal( BaseObject* object, ConnectionTrackerInterface* tracker, const std::string& signalName, FunctorDelegate* functor )
191 {
192   Dali::BaseHandle handle( object );
193
194   bool connected( false );
195   Toolkit::Control control = Toolkit::Control::DownCast( handle );
196   if ( control )
197   {
198     Internal::Control& controlImpl( Internal::GetImplementation( control ) );
199     connected = true;
200
201     if ( 0 == strcmp( signalName.c_str(), SIGNAL_KEY_EVENT ) )
202     {
203       controlImpl.KeyEventSignal().Connect( tracker, functor );
204     }
205     else if( 0 == strcmp( signalName.c_str(), SIGNAL_KEY_INPUT_FOCUS_GAINED ) )
206     {
207       controlImpl.KeyInputFocusGainedSignal().Connect( tracker, functor );
208     }
209     else if( 0 == strcmp( signalName.c_str(), SIGNAL_KEY_INPUT_FOCUS_LOST ) )
210     {
211       controlImpl.KeyInputFocusLostSignal().Connect( tracker, functor );
212     }
213     else if( 0 == strcmp( signalName.c_str(), SIGNAL_TAPPED ) )
214     {
215       controlImpl.EnableGestureDetection( Gesture::Tap );
216       controlImpl.GetTapGestureDetector().DetectedSignal().Connect( tracker, functor );
217     }
218     else if( 0 == strcmp( signalName.c_str(), SIGNAL_PANNED ) )
219     {
220       controlImpl.EnableGestureDetection( Gesture::Pan );
221       controlImpl.GetPanGestureDetector().DetectedSignal().Connect( tracker, functor );
222     }
223     else if( 0 == strcmp( signalName.c_str(), SIGNAL_PINCHED ) )
224     {
225       controlImpl.EnableGestureDetection( Gesture::Pinch );
226       controlImpl.GetPinchGestureDetector().DetectedSignal().Connect( tracker, functor );
227     }
228     else if( 0 == strcmp( signalName.c_str(), SIGNAL_LONG_PRESSED ) )
229     {
230       controlImpl.EnableGestureDetection( Gesture::LongPress );
231       controlImpl.GetLongPressGestureDetector().DetectedSignal().Connect( tracker, functor );
232     }
233   }
234   return connected;
235 }
236
237 // Setup signals and actions using the type-registry.
238 DALI_TYPE_REGISTRATION_BEGIN( Control, CustomActor, Create );
239
240 // Note: Properties are registered separately below.
241
242 SignalConnectorType registerSignal1( typeRegistration, SIGNAL_KEY_EVENT, &DoConnectSignal );
243 SignalConnectorType registerSignal2( typeRegistration, SIGNAL_KEY_INPUT_FOCUS_GAINED, &DoConnectSignal );
244 SignalConnectorType registerSignal3( typeRegistration, SIGNAL_KEY_INPUT_FOCUS_LOST, &DoConnectSignal );
245 SignalConnectorType registerSignal4( typeRegistration, SIGNAL_TAPPED, &DoConnectSignal );
246 SignalConnectorType registerSignal5( typeRegistration, SIGNAL_PANNED, &DoConnectSignal );
247 SignalConnectorType registerSignal6( typeRegistration, SIGNAL_PINCHED, &DoConnectSignal );
248 SignalConnectorType registerSignal7( typeRegistration, SIGNAL_LONG_PRESSED, &DoConnectSignal );
249
250 TypeAction registerAction( typeRegistration, ACTION_ACCESSIBILITY_ACTIVATED, &DoAction );
251
252 DALI_TYPE_REGISTRATION_END()
253
254 } // unnamed namespace
255
256 namespace Internal
257 {
258
259 class Control::Impl : public ConnectionTracker
260 {
261 public:
262
263   // Construction & Destruction
264   Impl(Control& controlImpl)
265   : mControlImpl( controlImpl ),
266     mState( Toolkit::DevelControl::NORMAL ),
267     mSubStateName(""),
268     mStyleName(""),
269     mBackgroundColor(Color::TRANSPARENT),
270     mStartingPinchScale( NULL ),
271     mKeyEventSignal(),
272     mPinchGestureDetector(),
273     mPanGestureDetector(),
274     mTapGestureDetector(),
275     mLongPressGestureDetector(),
276     mFlags( Control::ControlBehaviour( CONTROL_BEHAVIOUR_DEFAULT ) ),
277     mIsKeyboardNavigationSupported( false ),
278     mIsKeyboardFocusGroup( false )
279   {
280   }
281
282   ~Impl()
283   {
284     // All gesture detectors will be destroyed so no need to disconnect.
285     delete mStartingPinchScale;
286   }
287
288   // Gesture Detection Methods
289
290   void PinchDetected(Actor actor, const PinchGesture& pinch)
291   {
292     mControlImpl.OnPinch(pinch);
293   }
294
295   void PanDetected(Actor actor, const PanGesture& pan)
296   {
297     mControlImpl.OnPan(pan);
298   }
299
300   void TapDetected(Actor actor, const TapGesture& tap)
301   {
302     mControlImpl.OnTap(tap);
303   }
304
305   void LongPressDetected(Actor actor, const LongPressGesture& longPress)
306   {
307     mControlImpl.OnLongPress(longPress);
308   }
309
310   // Properties
311
312   /**
313    * Called when a property of an object of this type is set.
314    * @param[in] object The object whose property is set.
315    * @param[in] index The property index.
316    * @param[in] value The new property value.
317    */
318   static void SetProperty( BaseObject* object, Property::Index index, const Property::Value& value )
319   {
320     Toolkit::Control control = Toolkit::Control::DownCast( BaseHandle( object ) );
321
322     if ( control )
323     {
324       Control& controlImpl( GetImplementation( control ) );
325
326       switch ( index )
327       {
328         case Toolkit::Control::Property::STYLE_NAME:
329         {
330           controlImpl.SetStyleName( value.Get< std::string >() );
331           break;
332         }
333
334         case Toolkit::DevelControl::Property::STATE:
335         {
336           bool withTransitions=true;
337           const Property::Value* valuePtr=&value;
338           Property::Map* map = value.GetMap();
339           if(map)
340           {
341             Property::Value* value2 = map->Find("withTransitions");
342             if( value2 )
343             {
344               withTransitions = value2->Get<bool>();
345             }
346
347             valuePtr = map->Find("state");
348           }
349
350           if( valuePtr )
351           {
352             Toolkit::DevelControl::State state( controlImpl.mImpl->mState );
353             if( Scripting::GetEnumerationProperty< Toolkit::DevelControl::State >( *valuePtr, ControlStateTable, ControlStateTableCount, state ) )
354             {
355               controlImpl.mImpl->SetState( state, withTransitions );
356             }
357           }
358         }
359         break;
360
361         case Toolkit::DevelControl::Property::SUB_STATE:
362         {
363           std::string subState;
364           if( value.Get( subState ) )
365           {
366             controlImpl.mImpl->SetSubState( subState );
367           }
368         }
369         break;
370
371         case Toolkit::Control::Property::BACKGROUND_COLOR:
372         {
373           DALI_LOG_WARNING( "BACKGROUND_COLOR property is deprecated. Use BACKGROUND property instead\n" );
374           controlImpl.SetBackgroundColor( value.Get< Vector4 >() );
375           break;
376         }
377
378         case Toolkit::Control::Property::BACKGROUND_IMAGE:
379         {
380           DALI_LOG_WARNING( "BACKGROUND_IMAGE property is deprecated. Use BACKGROUND property instead\n" );
381           Image image = Scripting::NewImage( value );
382           if ( image )
383           {
384             controlImpl.SetBackgroundImage( image );
385           }
386           else
387           {
388             // An empty image means the background is no longer required
389             controlImpl.ClearBackground();
390           }
391           break;
392         }
393
394         case Toolkit::Control::Property::KEY_INPUT_FOCUS:
395         {
396           if ( value.Get< bool >() )
397           {
398             controlImpl.SetKeyInputFocus();
399           }
400           else
401           {
402             controlImpl.ClearKeyInputFocus();
403           }
404           break;
405         }
406
407         case Toolkit::Control::Property::BACKGROUND:
408         {
409           std::string url;
410           const Property::Map* map = value.GetMap();
411           if( map && !map->Empty() )
412           {
413             controlImpl.SetBackground( *map );
414           }
415           else if( value.Get( url ) )
416           {
417             // don't know the size to load
418             Toolkit::Visual::Base visual = Toolkit::VisualFactory::Get().CreateVisual( url, ImageDimensions() );
419             if( visual )
420             {
421               controlImpl.RegisterVisual( Toolkit::Control::Property::BACKGROUND, visual );
422               visual.SetDepthIndex( DepthIndex::BACKGROUND );
423             }
424           }
425           else
426           {
427             // The background is an empty property map, so we should clear the background
428             controlImpl.ClearBackground();
429           }
430           break;
431         }
432
433         case Toolkit::DevelControl::Property::TOOLTIP:
434         {
435           TooltipPtr& tooltipPtr = controlImpl.mImpl->mTooltip;
436           if( ! tooltipPtr )
437           {
438             tooltipPtr = Tooltip::New( control );
439           }
440           tooltipPtr->SetProperties( value );
441         }
442       }
443     }
444   }
445
446   /**
447    * Called to retrieve a property of an object of this type.
448    * @param[in] object The object whose property is to be retrieved.
449    * @param[in] index The property index.
450    * @return The current value of the property.
451    */
452   static Property::Value GetProperty( BaseObject* object, Property::Index index )
453   {
454     Property::Value value;
455
456     Toolkit::Control control = Toolkit::Control::DownCast( BaseHandle( object ) );
457
458     if ( control )
459     {
460       Control& controlImpl( GetImplementation( control ) );
461
462       switch ( index )
463       {
464         case Toolkit::Control::Property::STYLE_NAME:
465         {
466           value = controlImpl.GetStyleName();
467           break;
468         }
469
470         case Toolkit::DevelControl::Property::STATE:
471         {
472           value = controlImpl.mImpl->mState;
473           break;
474         }
475
476         case Toolkit::DevelControl::Property::SUB_STATE:
477         {
478           value = controlImpl.mImpl->mSubStateName;
479           break;
480         }
481
482         case Toolkit::Control::Property::BACKGROUND_COLOR:
483         {
484           DALI_LOG_WARNING( "BACKGROUND_COLOR property is deprecated. Use BACKGROUND property instead\n" );
485           value = controlImpl.GetBackgroundColor();
486           break;
487         }
488
489         case Toolkit::Control::Property::BACKGROUND_IMAGE:
490         {
491           DALI_LOG_WARNING( "BACKGROUND_IMAGE property is deprecated. Use BACKGROUND property instead\n" );
492           Property::Map map;
493           Toolkit::Visual::Base visual = controlImpl.GetVisual( Toolkit::Control::Property::BACKGROUND );
494           if( visual )
495           {
496             visual.CreatePropertyMap( map );
497           }
498           value = map;
499           break;
500         }
501
502         case Toolkit::Control::Property::KEY_INPUT_FOCUS:
503         {
504           value = controlImpl.HasKeyInputFocus();
505           break;
506         }
507
508         case Toolkit::Control::Property::BACKGROUND:
509         {
510           Property::Map map;
511           Toolkit::Visual::Base visual = controlImpl.GetVisual( Toolkit::Control::Property::BACKGROUND );
512           if( visual )
513           {
514             visual.CreatePropertyMap( map );
515           }
516
517           value = map;
518           break;
519         }
520
521         case Toolkit::DevelControl::Property::TOOLTIP:
522         {
523           Property::Map map;
524           if( controlImpl.mImpl->mTooltip )
525           {
526             controlImpl.mImpl->mTooltip->CreatePropertyMap( map );
527           }
528           value = map;
529           break;
530         }
531
532       }
533     }
534
535     return value;
536   }
537
538   void SetState( DevelControl::State state, bool withTransitions=true )
539   {
540     if( mState != state )
541     {
542       // If mState was Disabled, and new state is Focused, should probably
543       // store that fact, e.g. in another property that FocusManager can access.
544       mState = state;
545
546       // Trigger state change and transitions
547       // Apply new style, if stylemanager is available
548       Toolkit::StyleManager styleManager = Toolkit::StyleManager::Get();
549       if( styleManager )
550       {
551         const StylePtr stylePtr = GetImpl( styleManager ).GetRecordedStyle( Toolkit::Control( mControlImpl.GetOwner() ) );
552         if( stylePtr )
553         {
554           for( int i=mVisuals.Count()-1; i >= 0; i-- )
555           {
556             mControlImpl.UnregisterVisual( mVisuals[i]->index );
557           }
558
559           Dali::CustomActor handle( mControlImpl.GetOwner() );
560           stylePtr->ApplyVisualsAndPropertiesRecursively( handle );
561         }
562       }
563     }
564   }
565
566   void SetSubState( const std::string& subStateName, bool withTransitions=true )
567   {
568     if( mSubStateName != subStateName )
569     {
570       // Get existing sub-state visuals, and unregister them
571       Dali::CustomActor handle( mControlImpl.GetOwner() );
572
573       Toolkit::StyleManager styleManager = Toolkit::StyleManager::Get();
574       if( styleManager )
575       {
576         const StylePtr stylePtr = GetImpl( styleManager ).GetRecordedStyle( Toolkit::Control( mControlImpl.GetOwner() ) );
577         if( stylePtr )
578         {
579           // Stringify state
580           std::string stateName = Scripting::GetEnumerationName< Toolkit::DevelControl::State >( mState, ControlStateTable, ControlStateTableCount );
581
582           const StylePtr* state = stylePtr->subStates.Find( stateName );
583           if( state )
584           {
585             StylePtr stateStyle(*state);
586
587             // Unregister existing visuals of this substate
588             const StylePtr* subState = stateStyle->subStates.Find( mSubStateName );
589             if( subState )
590             {
591               StylePtr subStateStyle(*subState);
592
593               for( Dictionary<Property::Map>::iterator iter = subStateStyle->visuals.Begin(); iter != subStateStyle->visuals.End(); ++iter )
594               {
595                 const std::string& visualName = (*iter).key;
596                 Dali::Property::Index index = handle.GetPropertyIndex( visualName );
597                 if( index != Property::INVALID_INDEX )
598                 {
599                   mControlImpl.UnregisterVisual( index );
600                 }
601               }
602             }
603
604             // Register visuals of the new substate
605             const StylePtr* newSubState = stateStyle->subStates.Find( subStateName );
606             if( newSubState )
607             {
608               StylePtr newSubStateStyle(*newSubState);
609               newSubStateStyle->ApplyVisuals( handle );
610               newSubStateStyle->ApplyProperties( handle );
611             }
612           }
613         }
614       }
615
616       mSubStateName = subStateName;
617     }
618   }
619
620   // Data
621
622   Control& mControlImpl;
623   DevelControl::State mState;
624   std::string mSubStateName;
625
626   RegisteredVisualContainer mVisuals; // Stores visuals needed by the control, non trivial type so std::vector used.
627   std::string mStyleName;
628   Vector4 mBackgroundColor;                       ///< The color of the background visual
629   Vector3* mStartingPinchScale;      ///< The scale when a pinch gesture starts, TODO: consider removing this
630   Toolkit::Control::KeyEventSignalType mKeyEventSignal;
631   Toolkit::Control::KeyInputFocusSignalType mKeyInputFocusGainedSignal;
632   Toolkit::Control::KeyInputFocusSignalType mKeyInputFocusLostSignal;
633
634   // Gesture Detection
635   PinchGestureDetector mPinchGestureDetector;
636   PanGestureDetector mPanGestureDetector;
637   TapGestureDetector mTapGestureDetector;
638   LongPressGestureDetector mLongPressGestureDetector;
639
640   // Tooltip
641   TooltipPtr mTooltip;
642
643   ControlBehaviour mFlags : CONTROL_BEHAVIOUR_FLAG_COUNT;    ///< Flags passed in from constructor.
644   bool mIsKeyboardNavigationSupported :1;  ///< Stores whether keyboard navigation is supported by the control.
645   bool mIsKeyboardFocusGroup :1;           ///< Stores whether the control is a focus group.
646
647   // Properties - these need to be members of Internal::Control::Impl as they access private methods/data of Internal::Control and Internal::Control::Impl.
648   static const PropertyRegistration PROPERTY_1;
649   static const PropertyRegistration PROPERTY_2;
650   static const PropertyRegistration PROPERTY_3;
651   static const PropertyRegistration PROPERTY_4;
652   static const PropertyRegistration PROPERTY_5;
653   static const PropertyRegistration PROPERTY_6;
654   static const PropertyRegistration PROPERTY_7;
655   static const PropertyRegistration PROPERTY_8;
656 };
657
658 // Properties registered without macro to use specific member variables.
659 const PropertyRegistration Control::Impl::PROPERTY_1( typeRegistration, "styleName",       Toolkit::Control::Property::STYLE_NAME,       Property::STRING,  &Control::Impl::SetProperty, &Control::Impl::GetProperty );
660 const PropertyRegistration Control::Impl::PROPERTY_2( typeRegistration, "backgroundColor", Toolkit::Control::Property::BACKGROUND_COLOR, Property::VECTOR4, &Control::Impl::SetProperty, &Control::Impl::GetProperty );
661 const PropertyRegistration Control::Impl::PROPERTY_3( typeRegistration, "backgroundImage", Toolkit::Control::Property::BACKGROUND_IMAGE, Property::MAP,     &Control::Impl::SetProperty, &Control::Impl::GetProperty );
662 const PropertyRegistration Control::Impl::PROPERTY_4( typeRegistration, "keyInputFocus",   Toolkit::Control::Property::KEY_INPUT_FOCUS,  Property::BOOLEAN, &Control::Impl::SetProperty, &Control::Impl::GetProperty );
663 const PropertyRegistration Control::Impl::PROPERTY_5( typeRegistration, "background",      Toolkit::Control::Property::BACKGROUND,       Property::MAP,     &Control::Impl::SetProperty, &Control::Impl::GetProperty );
664 const PropertyRegistration Control::Impl::PROPERTY_6( typeRegistration, "tooltip",         Toolkit::DevelControl::Property::TOOLTIP,     Property::MAP,     &Control::Impl::SetProperty, &Control::Impl::GetProperty );
665 const PropertyRegistration Control::Impl::PROPERTY_7( typeRegistration, "state",           Toolkit::DevelControl::Property::STATE,       Property::STRING,  &Control::Impl::SetProperty, &Control::Impl::GetProperty );
666 const PropertyRegistration Control::Impl::PROPERTY_8( typeRegistration, "subState",        Toolkit::DevelControl::Property::SUB_STATE,   Property::STRING,  &Control::Impl::SetProperty, &Control::Impl::GetProperty );
667
668 Toolkit::Control Control::New()
669 {
670   // Create the implementation, temporarily owned on stack
671   IntrusivePtr<Control> controlImpl = new Control( ControlBehaviour( CONTROL_BEHAVIOUR_DEFAULT ) );
672
673   // Pass ownership to handle
674   Toolkit::Control handle( *controlImpl );
675
676   // Second-phase init of the implementation
677   // This can only be done after the CustomActor connection has been made...
678   controlImpl->Initialize();
679
680   return handle;
681 }
682
683 void Control::SetStyleName( const std::string& styleName )
684 {
685   if( styleName != mImpl->mStyleName )
686   {
687     mImpl->mStyleName = styleName;
688
689     // Apply new style, if stylemanager is available
690     Toolkit::StyleManager styleManager = Toolkit::StyleManager::Get();
691     if( styleManager )
692     {
693       GetImpl( styleManager ).ApplyThemeStyle( Toolkit::Control( GetOwner() ) );
694     }
695   }
696 }
697
698 const std::string& Control::GetStyleName() const
699 {
700   return mImpl->mStyleName;
701 }
702
703 void Control::SetBackgroundColor( const Vector4& color )
704 {
705   mImpl->mBackgroundColor = color;
706   Property::Map map;
707   map[ Toolkit::DevelVisual::Property::TYPE ] = Toolkit::Visual::COLOR;
708   map[ Toolkit::ColorVisual::Property::MIX_COLOR ] = color;
709
710   SetBackground( map );
711 }
712
713 Vector4 Control::GetBackgroundColor() const
714 {
715   return mImpl->mBackgroundColor;
716 }
717
718 void Control::SetBackground( const Property::Map& map )
719 {
720   Toolkit::Visual::Base visual = Toolkit::VisualFactory::Get().CreateVisual( map );
721   if( visual )
722   {
723     RegisterVisual( Toolkit::Control::Property::BACKGROUND, visual );
724     visual.SetDepthIndex( DepthIndex::BACKGROUND );
725
726     // Trigger a size negotiation request that may be needed by the new visual to relayout its contents.
727     RelayoutRequest();
728   }
729 }
730
731 void Control::SetBackgroundImage( Image image )
732 {
733   Toolkit::Visual::Base visual = Toolkit::VisualFactory::Get().CreateVisual( image );
734   if( visual )
735   {
736     RegisterVisual( Toolkit::Control::Property::BACKGROUND, visual );
737     visual.SetDepthIndex( DepthIndex::BACKGROUND );
738   }
739 }
740
741 void Control::ClearBackground()
742 {
743    UnregisterVisual( Toolkit::Control::Property::BACKGROUND );
744    mImpl->mBackgroundColor = Color::TRANSPARENT;
745
746    // Trigger a size negotiation request that may be needed when unregistering a visual.
747    RelayoutRequest();
748 }
749
750 void Control::EnableGestureDetection(Gesture::Type type)
751 {
752   if ( (type & Gesture::Pinch) && !mImpl->mPinchGestureDetector )
753   {
754     mImpl->mPinchGestureDetector = PinchGestureDetector::New();
755     mImpl->mPinchGestureDetector.DetectedSignal().Connect(mImpl, &Impl::PinchDetected);
756     mImpl->mPinchGestureDetector.Attach(Self());
757   }
758
759   if ( (type & Gesture::Pan) && !mImpl->mPanGestureDetector )
760   {
761     mImpl->mPanGestureDetector = PanGestureDetector::New();
762     mImpl->mPanGestureDetector.DetectedSignal().Connect(mImpl, &Impl::PanDetected);
763     mImpl->mPanGestureDetector.Attach(Self());
764   }
765
766   if ( (type & Gesture::Tap) && !mImpl->mTapGestureDetector )
767   {
768     mImpl->mTapGestureDetector = TapGestureDetector::New();
769     mImpl->mTapGestureDetector.DetectedSignal().Connect(mImpl, &Impl::TapDetected);
770     mImpl->mTapGestureDetector.Attach(Self());
771   }
772
773   if ( (type & Gesture::LongPress) && !mImpl->mLongPressGestureDetector )
774   {
775     mImpl->mLongPressGestureDetector = LongPressGestureDetector::New();
776     mImpl->mLongPressGestureDetector.DetectedSignal().Connect(mImpl, &Impl::LongPressDetected);
777     mImpl->mLongPressGestureDetector.Attach(Self());
778   }
779 }
780
781 void Control::DisableGestureDetection(Gesture::Type type)
782 {
783   if ( (type & Gesture::Pinch) && mImpl->mPinchGestureDetector )
784   {
785     mImpl->mPinchGestureDetector.Detach(Self());
786     mImpl->mPinchGestureDetector.Reset();
787   }
788
789   if ( (type & Gesture::Pan) && mImpl->mPanGestureDetector )
790   {
791     mImpl->mPanGestureDetector.Detach(Self());
792     mImpl->mPanGestureDetector.Reset();
793   }
794
795   if ( (type & Gesture::Tap) && mImpl->mTapGestureDetector )
796   {
797     mImpl->mTapGestureDetector.Detach(Self());
798     mImpl->mTapGestureDetector.Reset();
799   }
800
801   if ( (type & Gesture::LongPress) && mImpl->mLongPressGestureDetector)
802   {
803     mImpl->mLongPressGestureDetector.Detach(Self());
804     mImpl->mLongPressGestureDetector.Reset();
805   }
806 }
807
808 PinchGestureDetector Control::GetPinchGestureDetector() const
809 {
810   return mImpl->mPinchGestureDetector;
811 }
812
813 PanGestureDetector Control::GetPanGestureDetector() const
814 {
815   return mImpl->mPanGestureDetector;
816 }
817
818 TapGestureDetector Control::GetTapGestureDetector() const
819 {
820   return mImpl->mTapGestureDetector;
821 }
822
823 LongPressGestureDetector Control::GetLongPressGestureDetector() const
824 {
825   return mImpl->mLongPressGestureDetector;
826 }
827
828 void Control::SetKeyboardNavigationSupport(bool isSupported)
829 {
830   mImpl->mIsKeyboardNavigationSupported = isSupported;
831 }
832
833 bool Control::IsKeyboardNavigationSupported()
834 {
835   return mImpl->mIsKeyboardNavigationSupported;
836 }
837
838 void Control::SetKeyInputFocus()
839 {
840   if( Self().OnStage() )
841   {
842     Toolkit::KeyInputFocusManager::Get().SetFocus(Toolkit::Control::DownCast(Self()));
843   }
844 }
845
846 bool Control::HasKeyInputFocus()
847 {
848   bool result = false;
849   if( Self().OnStage() )
850   {
851     result = Toolkit::KeyInputFocusManager::Get().IsKeyboardListener(Toolkit::Control::DownCast(Self()));
852   }
853   return result;
854 }
855
856 void Control::ClearKeyInputFocus()
857 {
858   if( Self().OnStage() )
859   {
860     Toolkit::KeyInputFocusManager::Get().RemoveFocus(Toolkit::Control::DownCast(Self()));
861   }
862 }
863
864 void Control::SetAsKeyboardFocusGroup(bool isFocusGroup)
865 {
866   mImpl->mIsKeyboardFocusGroup = isFocusGroup;
867
868   // The following line will be removed when the deprecated API in KeyboardFocusManager is deleted
869   Toolkit::KeyboardFocusManager::Get().SetAsFocusGroup(Self(), isFocusGroup);
870 }
871
872 bool Control::IsKeyboardFocusGroup()
873 {
874   return Toolkit::KeyboardFocusManager::Get().IsFocusGroup(Self());
875 }
876
877 void Control::AccessibilityActivate()
878 {
879   // Inform deriving classes
880   OnAccessibilityActivated();
881 }
882
883 void Control::KeyboardEnter()
884 {
885   // Inform deriving classes
886   OnKeyboardEnter();
887 }
888
889 void Control::RegisterVisual( Property::Index index, Toolkit::Visual::Base& visual )
890 {
891   RegisterVisual( index, visual, true );
892 }
893
894 void Control::RegisterVisual( Property::Index index, Toolkit::Visual::Base& visual, bool enabled )
895 {
896   bool visualReplaced ( false );
897   Actor self = Self();
898
899   if( !mImpl->mVisuals.Empty() )
900   {
901     RegisteredVisualContainer::Iterator iter;
902     // Check if visual (index) is already registered.  Replace if so.
903     if ( FindVisual( index, mImpl->mVisuals, iter ) )
904     {
905       if( (*iter)->visual && self.OnStage() )
906       {
907         Toolkit::GetImplementation((*iter)->visual).SetOffStage( self );
908       }
909       (*iter)->visual = visual;
910       visualReplaced = true;
911     }
912   }
913
914   // If not set, set the name of the visual to the same name as the control's property.
915   // ( If the control has been type registered )
916   if( visual.GetName().empty() )
917   {
918     // Check if the control has been type registered:
919     TypeInfo typeInfo = TypeRegistry::Get().GetTypeInfo( typeid(*this) );
920     if( typeInfo )
921     {
922       // Check if the property index has been registered:
923       Property::IndexContainer indices;
924       typeInfo.GetPropertyIndices( indices );
925       Property::IndexContainer::Iterator iter = std::find( indices.Begin(), indices.End(), index );
926       if( iter != indices.End() )
927       {
928         // If it has, then get it's name and use that for the visual
929         std::string visualName = typeInfo.GetPropertyName( index );
930         visual.SetName( visualName );
931       }
932     }
933   }
934
935   if( !visualReplaced ) // New registration entry
936   {
937     mImpl->mVisuals.PushBack( new RegisteredVisual( index, visual, enabled ) );
938   }
939
940   if( visual && self.OnStage() && enabled )
941   {
942     Toolkit::GetImplementation(visual).SetOnStage( self );
943   }
944
945   DALI_LOG_INFO( gLogFilter, Debug::Verbose, "Control::RegisterVisual() Registered %s(%d), enabled:%s\n",  visual.GetName().c_str(), index, enabled?"T":"F" );
946 }
947
948 void Control::UnregisterVisual( Property::Index index )
949 {
950    RegisteredVisualContainer::Iterator iter;
951    if ( FindVisual( index, mImpl->mVisuals, iter ) )
952    {
953      Actor self( Self() );
954      Toolkit::GetImplementation((*iter)->visual).SetOffStage( self );
955      (*iter)->visual.Reset();
956      mImpl->mVisuals.Erase( iter );
957    }
958 }
959
960 Toolkit::Visual::Base Control::GetVisual( Property::Index index ) const
961 {
962   RegisteredVisualContainer::Iterator iter;
963   if ( FindVisual( index, mImpl->mVisuals, iter ) )
964   {
965     return (*iter)->visual;
966   }
967
968   return Toolkit::Visual::Base();
969 }
970
971 void Control::EnableVisual( Property::Index index, bool enable )
972 {
973   RegisteredVisualContainer::Iterator iter;
974   if ( FindVisual( index, mImpl->mVisuals, iter ) )
975   {
976     if (  (*iter)->enabled == enable )
977     {
978       DALI_LOG_INFO( gLogFilter, Debug::Verbose, "Control::EnableVisual Visual %s(%d) already %s\n", (*iter)->visual.GetName().c_str(), index, enable?"enabled":"disabled");
979       return;
980     }
981
982     (*iter)->enabled = enable;
983     Actor parentActor = Self();
984     if ( Self().OnStage() ) // If control not on Stage then Visual will be added when StageConnection is called.
985     {
986       if ( enable )
987       {
988         DALI_LOG_INFO( gLogFilter, Debug::Verbose, "Control::EnableVisual Setting %s(%d) on stage \n", (*iter)->visual.GetName().c_str(), index );
989         Toolkit::GetImplementation((*iter)->visual).SetOnStage( parentActor );
990       }
991       else
992       {
993         DALI_LOG_INFO( gLogFilter, Debug::Verbose, "Control::EnableVisual Setting %s(%d) off stage \n", (*iter)->visual.GetName().c_str(), index );
994         Toolkit::GetImplementation((*iter)->visual).SetOffStage( parentActor );  // No need to call if control not staged.
995       }
996     }
997   }
998 }
999
1000 bool Control::IsVisualEnabled( Property::Index index ) const
1001 {
1002   RegisteredVisualContainer::Iterator iter;
1003   if ( FindVisual( index, mImpl->mVisuals, iter ) )
1004   {
1005     return (*iter)->enabled;
1006   }
1007   return false;
1008 }
1009
1010 Dali::Animation Control::CreateTransition( const Toolkit::TransitionData& handle )
1011 {
1012   Dali::Animation transition;
1013   const Internal::TransitionData& transitionData = Toolkit::GetImplementation( handle );
1014
1015   if( transitionData.Count() > 0 )
1016   {
1017     // Setup a Transition from TransitionData.
1018     TransitionData::Iterator end = transitionData.End();
1019     for( TransitionData::Iterator iter = transitionData.Begin() ;
1020          iter != end; ++iter )
1021     {
1022       TransitionData::Animator* animator = (*iter);
1023
1024       Toolkit::Visual::Base visual = GetVisualByName( mImpl->mVisuals, animator->objectName );
1025
1026       if( visual )
1027       {
1028         Internal::Visual::Base& visualImpl = Toolkit::GetImplementation( visual );
1029         visualImpl.AnimateProperty( transition, *animator );
1030       }
1031       else
1032       {
1033         // Otherwise, try any actor children of control (Including the control)
1034         Actor child = Self().FindChildByName( animator->objectName );
1035         if( child )
1036         {
1037           Property::Index propertyIndex = DevelHandle::GetPropertyIndex( child, animator->propertyKey );
1038           if( propertyIndex != Property::INVALID_INDEX )
1039           {
1040             if( animator->animate == false )
1041             {
1042               if( animator->targetValue.GetType() != Property::NONE )
1043               {
1044                 child.SetProperty( propertyIndex, animator->targetValue );
1045               }
1046             }
1047             else // animate the property
1048             {
1049               if( animator->initialValue.GetType() != Property::NONE )
1050               {
1051                 child.SetProperty( propertyIndex, animator->initialValue );
1052               }
1053
1054               if( ! transition )
1055               {
1056                 transition = Dali::Animation::New( 0.1f );
1057               }
1058
1059               transition.AnimateTo( Property( child, propertyIndex ),
1060                                     animator->targetValue,
1061                                     animator->alphaFunction,
1062                                     TimePeriod( animator->timePeriodDelay,
1063                                                 animator->timePeriodDuration ) );
1064             }
1065           }
1066         }
1067       }
1068     }
1069   }
1070
1071   return transition;
1072 }
1073
1074 bool Control::OnAccessibilityActivated()
1075 {
1076   return false; // Accessibility activation is not handled by default
1077 }
1078
1079 bool Control::OnKeyboardEnter()
1080 {
1081   return false; // Keyboard enter is not handled by default
1082 }
1083
1084 bool Control::OnAccessibilityPan(PanGesture gesture)
1085 {
1086   return false; // Accessibility pan gesture is not handled by default
1087 }
1088
1089 bool Control::OnAccessibilityTouch(const TouchEvent& touchEvent)
1090 {
1091   return false; // Accessibility touch event is not handled by default
1092 }
1093
1094 bool Control::OnAccessibilityValueChange(bool isIncrease)
1095 {
1096   return false; // Accessibility value change action is not handled by default
1097 }
1098
1099 bool Control::OnAccessibilityZoom()
1100 {
1101   return false; // Accessibility zoom action is not handled by default
1102 }
1103
1104 Actor Control::GetNextKeyboardFocusableActor(Actor currentFocusedActor, Toolkit::Control::KeyboardFocus::Direction direction, bool loopEnabled)
1105 {
1106   return Actor();
1107 }
1108
1109 void Control::OnKeyboardFocusChangeCommitted(Actor commitedFocusableActor)
1110 {
1111 }
1112
1113 Toolkit::Control::KeyEventSignalType& Control::KeyEventSignal()
1114 {
1115   return mImpl->mKeyEventSignal;
1116 }
1117
1118 Toolkit::Control::KeyInputFocusSignalType& Control::KeyInputFocusGainedSignal()
1119 {
1120   return mImpl->mKeyInputFocusGainedSignal;
1121 }
1122
1123 Toolkit::Control::KeyInputFocusSignalType& Control::KeyInputFocusLostSignal()
1124 {
1125   return mImpl->mKeyInputFocusLostSignal;
1126 }
1127
1128 bool Control::EmitKeyEventSignal( const KeyEvent& event )
1129 {
1130   // Guard against destruction during signal emission
1131   Dali::Toolkit::Control handle( GetOwner() );
1132
1133   bool consumed = false;
1134
1135   // signals are allocated dynamically when someone connects
1136   if ( !mImpl->mKeyEventSignal.Empty() )
1137   {
1138     consumed = mImpl->mKeyEventSignal.Emit( handle, event );
1139   }
1140
1141   if (!consumed)
1142   {
1143     // Notification for derived classes
1144     consumed = OnKeyEvent(event);
1145   }
1146
1147   return consumed;
1148 }
1149
1150 Control::Control( ControlBehaviour behaviourFlags )
1151 : CustomActorImpl( static_cast< ActorFlags >( behaviourFlags ) ),
1152   mImpl(new Impl(*this))
1153 {
1154   mImpl->mFlags = behaviourFlags;
1155 }
1156
1157 Control::~Control()
1158 {
1159   delete mImpl;
1160 }
1161
1162 void Control::Initialize()
1163 {
1164   // Call deriving classes so initialised before styling is applied to them.
1165   OnInitialize();
1166
1167   if( (mImpl->mFlags & REQUIRES_STYLE_CHANGE_SIGNALS) ||
1168       !(mImpl->mFlags & DISABLE_STYLE_CHANGE_SIGNALS) )
1169   {
1170     Toolkit::StyleManager styleManager = StyleManager::Get();
1171
1172     // if stylemanager is available
1173     if( styleManager )
1174     {
1175       StyleManager& styleManagerImpl = GetImpl( styleManager );
1176
1177       // Register for style changes
1178       styleManagerImpl.ControlStyleChangeSignal().Connect( this, &Control::OnStyleChange );
1179
1180       // Apply the current style
1181       styleManagerImpl.ApplyThemeStyleAtInit( Toolkit::Control( GetOwner() ) );
1182     }
1183   }
1184
1185   if( mImpl->mFlags & REQUIRES_KEYBOARD_NAVIGATION_SUPPORT )
1186   {
1187     SetKeyboardNavigationSupport( true );
1188   }
1189 }
1190
1191 void Control::OnInitialize()
1192 {
1193 }
1194
1195 void Control::OnControlChildAdd( Actor& child )
1196 {
1197 }
1198
1199 void Control::OnControlChildRemove( Actor& child )
1200 {
1201 }
1202
1203 void Control::OnStyleChange( Toolkit::StyleManager styleManager, StyleChange::Type change )
1204 {
1205   // By default the control is only interested in theme (not font) changes
1206   if( styleManager && change == StyleChange::THEME_CHANGE )
1207   {
1208     GetImpl( styleManager ).ApplyThemeStyle( Toolkit::Control( GetOwner() ) );
1209   }
1210   RelayoutRequest();
1211 }
1212
1213 void Control::OnPinch(const PinchGesture& pinch)
1214 {
1215   if( !( mImpl->mStartingPinchScale ) )
1216   {
1217     // lazy allocate
1218     mImpl->mStartingPinchScale = new Vector3;
1219   }
1220
1221   if( pinch.state == Gesture::Started )
1222   {
1223     *( mImpl->mStartingPinchScale ) = Self().GetCurrentScale();
1224   }
1225
1226   Self().SetScale( *( mImpl->mStartingPinchScale ) * pinch.scale );
1227 }
1228
1229 void Control::OnPan( const PanGesture& pan )
1230 {
1231 }
1232
1233 void Control::OnTap(const TapGesture& tap)
1234 {
1235 }
1236
1237 void Control::OnLongPress( const LongPressGesture& longPress )
1238 {
1239 }
1240
1241 void Control::EmitKeyInputFocusSignal( bool focusGained )
1242 {
1243   Dali::Toolkit::Control handle( GetOwner() );
1244
1245   if ( focusGained )
1246   {
1247     // signals are allocated dynamically when someone connects
1248     if ( !mImpl->mKeyInputFocusGainedSignal.Empty() )
1249     {
1250       mImpl->mKeyInputFocusGainedSignal.Emit( handle );
1251     }
1252   }
1253   else
1254   {
1255     // signals are allocated dynamically when someone connects
1256     if ( !mImpl->mKeyInputFocusLostSignal.Empty() )
1257     {
1258       mImpl->mKeyInputFocusLostSignal.Emit( handle );
1259     }
1260   }
1261 }
1262
1263 void Control::OnStageConnection( int depth )
1264 {
1265   DALI_LOG_INFO( gLogFilter, Debug::Verbose, "Control::OnStageConnection number of registered visuals(%d)\n",  mImpl->mVisuals.Size() );
1266
1267   Actor self( Self() );
1268
1269   for(RegisteredVisualContainer::Iterator iter = mImpl->mVisuals.Begin(); iter!= mImpl->mVisuals.End(); iter++)
1270   {
1271     // Check whether the visual is empty and enabled
1272     if( (*iter)->visual && (*iter)->enabled )
1273     {
1274       DALI_LOG_INFO( gLogFilter, Debug::Verbose, "Control::OnStageConnection Setting visual(%d) on stage\n", (*iter)->index );
1275       Toolkit::GetImplementation((*iter)->visual).SetOnStage( self );
1276     }
1277   }
1278
1279   if( mImpl->mVisuals.Empty() && ! self.GetRendererCount() )
1280   {
1281     Property::Value clippingValue = self.GetProperty( Actor::Property::CLIPPING_MODE );
1282     int clippingMode = ClippingMode::DISABLED;
1283     if( clippingValue.Get( clippingMode ) )
1284     {
1285       // Add a transparent background if we do not have any renderers or visuals so we clip our children
1286
1287       if( clippingMode == ClippingMode::CLIP_CHILDREN )
1288       {
1289         // Create a transparent background visual which will also get staged.
1290         SetBackgroundColor( Color::TRANSPARENT );
1291       }
1292     }
1293   }
1294 }
1295
1296 void Control::OnStageDisconnection()
1297 {
1298   for(RegisteredVisualContainer::Iterator iter = mImpl->mVisuals.Begin(); iter!= mImpl->mVisuals.End(); iter++)
1299   {
1300     // Check whether the visual is empty
1301     if( (*iter)->visual )
1302     {
1303       DALI_LOG_INFO( gLogFilter, Debug::Verbose, "Control::OnStageDisconnection Setting visual(%d) off stage\n", (*iter)->index );
1304       Actor self( Self() );
1305       Toolkit::GetImplementation((*iter)->visual).SetOffStage( self );
1306     }
1307   }
1308 }
1309
1310 void Control::OnKeyInputFocusGained()
1311 {
1312   EmitKeyInputFocusSignal( true );
1313 }
1314
1315 void Control::OnKeyInputFocusLost()
1316 {
1317   EmitKeyInputFocusSignal( false );
1318 }
1319
1320 void Control::OnChildAdd(Actor& child)
1321 {
1322   // Notify derived classes.
1323   OnControlChildAdd( child );
1324 }
1325
1326 void Control::OnChildRemove(Actor& child)
1327 {
1328   // Notify derived classes.
1329   OnControlChildRemove( child );
1330 }
1331
1332 void Control::OnPropertySet( Property::Index index, Property::Value propertyValue )
1333 {
1334   Actor self( Self() );
1335   if( index == Actor::Property::CLIPPING_MODE )
1336   {
1337     // Only set the background if we're already on the stage and have no renderers or visuals
1338
1339     if( mImpl->mVisuals.Empty() && ! self.GetRendererCount() && self.OnStage() )
1340     {
1341       ClippingMode::Type clippingMode = ClippingMode::DISABLED;
1342       if( Scripting::GetEnumerationProperty< ClippingMode::Type >( propertyValue, CLIPPING_MODE_TABLE, CLIPPING_MODE_TABLE_COUNT, clippingMode ) )
1343       {
1344         // Add a transparent background if we do not have one so we clip children
1345
1346         if( clippingMode == ClippingMode::CLIP_CHILDREN )
1347         {
1348           SetBackgroundColor( Color::TRANSPARENT );
1349         }
1350       }
1351     }
1352   }
1353 }
1354
1355 void Control::OnSizeSet(const Vector3& targetSize)
1356 {
1357   Toolkit::Visual::Base visual = GetVisual( Toolkit::Control::Property::BACKGROUND );
1358   if( visual )
1359   {
1360     Vector2 size( targetSize );
1361     visual.SetTransformAndSize( Property::Map(), size ); // Send an empty map as we do not want to modify the visual's set transform
1362   }
1363 }
1364
1365 void Control::OnSizeAnimation(Animation& animation, const Vector3& targetSize)
1366 {
1367   // @todo size negotiate background to new size, animate as well?
1368 }
1369
1370 bool Control::OnTouchEvent(const TouchEvent& event)
1371 {
1372   return false; // Do not consume
1373 }
1374
1375 bool Control::OnHoverEvent(const HoverEvent& event)
1376 {
1377   return false; // Do not consume
1378 }
1379
1380 bool Control::OnKeyEvent(const KeyEvent& event)
1381 {
1382   return false; // Do not consume
1383 }
1384
1385 bool Control::OnWheelEvent(const WheelEvent& event)
1386 {
1387   return false; // Do not consume
1388 }
1389
1390 void Control::OnRelayout( const Vector2& size, RelayoutContainer& container )
1391 {
1392   for( unsigned int i = 0, numChildren = Self().GetChildCount(); i < numChildren; ++i )
1393   {
1394     container.Add( Self().GetChildAt( i ), size );
1395   }
1396
1397   Toolkit::Visual::Base visual = GetVisual( Toolkit::Control::Property::BACKGROUND );
1398   if( visual )
1399   {
1400     visual.SetTransformAndSize( Property::Map(), size ); // Send an empty map as we do not want to modify the visual's set transform
1401   }
1402 }
1403
1404 void Control::OnSetResizePolicy( ResizePolicy::Type policy, Dimension::Type dimension )
1405 {
1406 }
1407
1408 Vector3 Control::GetNaturalSize()
1409 {
1410   Toolkit::Visual::Base visual = GetVisual( Toolkit::Control::Property::BACKGROUND );
1411   if( visual )
1412   {
1413     Vector2 naturalSize;
1414     visual.GetNaturalSize( naturalSize );
1415     return Vector3( naturalSize );
1416   }
1417   return Vector3::ZERO;
1418 }
1419
1420 float Control::CalculateChildSize( const Dali::Actor& child, Dimension::Type dimension )
1421 {
1422   return CalculateChildSizeBase( child, dimension );
1423 }
1424
1425 float Control::GetHeightForWidth( float width )
1426 {
1427   return GetHeightForWidthBase( width );
1428 }
1429
1430 float Control::GetWidthForHeight( float height )
1431 {
1432   return GetWidthForHeightBase( height );
1433 }
1434
1435 bool Control::RelayoutDependentOnChildren( Dimension::Type dimension )
1436 {
1437   return RelayoutDependentOnChildrenBase( dimension );
1438 }
1439
1440 void Control::OnCalculateRelayoutSize( Dimension::Type dimension )
1441 {
1442 }
1443
1444 void Control::OnLayoutNegotiated( float size, Dimension::Type dimension )
1445 {
1446 }
1447
1448 void Control::SignalConnected( SlotObserver* slotObserver, CallbackBase* callback )
1449 {
1450   mImpl->SignalConnected( slotObserver, callback );
1451 }
1452
1453 void Control::SignalDisconnected( SlotObserver* slotObserver, CallbackBase* callback )
1454 {
1455   mImpl->SignalDisconnected( slotObserver, callback );
1456 }
1457
1458 Control& GetImplementation( Dali::Toolkit::Control& handle )
1459 {
1460   CustomActorImpl& customInterface = handle.GetImplementation();
1461   // downcast to control
1462   Control& impl = dynamic_cast< Internal::Control& >( customInterface );
1463   return impl;
1464 }
1465
1466 const Control& GetImplementation( const Dali::Toolkit::Control& handle )
1467 {
1468   const CustomActorImpl& customInterface = handle.GetImplementation();
1469   // downcast to control
1470   const Control& impl = dynamic_cast< const Internal::Control& >( customInterface );
1471   return impl;
1472 }
1473
1474 } // namespace Internal
1475
1476 } // namespace Toolkit
1477
1478 } // namespace Dali