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