Change the double tap and long press events on top of no text actions to highlight.
[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::Visual::Type GetVisualTypeFromMap( const Property::Map& map )
690   {
691     Property::Value* typeValue = map.Find( Toolkit::Visual::Property::TYPE, VISUAL_TYPE  );
692     Toolkit::Visual::Type type = Toolkit::Visual::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::Visual::Type fromType = GetVisualTypeFromMap( fromMap );
725         Toolkit::Visual::Type toType = GetVisualTypeFromMap( toMap );
726
727         if( fromType != toType )
728         {
729           recreate = true;
730         }
731         else
732         {
733           if( fromType == Toolkit::Visual::IMAGE )
734           {
735             Property::Value* fromUrl = fromMap.Find( Toolkit::ImageVisual::Property::URL, IMAGE_URL_NAME );
736             Property::Value* toUrl = toMap.Find( Toolkit::ImageVisual::Property::URL, IMAGE_URL_NAME );
737
738             if( fromUrl && toUrl )
739             {
740               std::string fromUrlString;
741               std::string toUrlString;
742               fromUrl->Get(fromUrlString);
743               toUrl->Get(toUrlString);
744
745               if( fromUrlString != toUrlString )
746               {
747                 recreate = true;
748               }
749             }
750           }
751         }
752
753         const Property::Map* instancedMap = instancedProperties.FindConst( visualName );
754         if( recreate || instancedMap )
755         {
756           RemoveVisual( mVisuals, visualName );
757           Style::ApplyVisual( handle, visualName, toMap, instancedMap );
758         }
759         else
760         {
761           // @todo check to see if we can apply toMap without recreating the visual
762           // e.g. by setting only animatable properties
763           // For now, recreate all visuals, but merge in instance data.
764           RemoveVisual( mVisuals, visualName );
765           Style::ApplyVisual( handle, visualName, toMap, instancedMap );
766         }
767       }
768     }
769   }
770
771   void ReplaceStateVisualsAndProperties( const StylePtr oldState, const StylePtr newState, const std::string& subState )
772   {
773     // Collect all old visual names
774     DictionaryKeys stateVisualsToRemove;
775     if( oldState )
776     {
777       oldState->visuals.GetKeys( stateVisualsToRemove );
778       if( ! subState.empty() )
779       {
780         const StylePtr* oldSubState = oldState->subStates.FindConst(subState);
781         if( oldSubState )
782         {
783           DictionaryKeys subStateVisualsToRemove;
784           (*oldSubState)->visuals.GetKeys( subStateVisualsToRemove );
785           Merge( stateVisualsToRemove, subStateVisualsToRemove );
786         }
787       }
788     }
789
790     // Collect all new visual properties
791     Dictionary<Property::Map> stateVisualsToAdd;
792     if( newState )
793     {
794       stateVisualsToAdd = newState->visuals;
795       if( ! subState.empty() )
796       {
797         const StylePtr* newSubState = newState->subStates.FindConst(subState);
798         if( newSubState )
799         {
800           stateVisualsToAdd.Merge( (*newSubState)->visuals );
801         }
802       }
803     }
804
805     // If a name is in both add/remove, move it to change list.
806     Dictionary<Property::Map> stateVisualsToChange;
807     FindChangableVisuals( stateVisualsToAdd, stateVisualsToChange, stateVisualsToRemove);
808
809     // Copy instanced properties (e.g. text label) of current visuals
810     Dictionary<Property::Map> instancedProperties;
811     CopyInstancedProperties( mVisuals, instancedProperties );
812
813     // For each visual in remove list, remove from mVisuals
814     RemoveVisuals( mVisuals, stateVisualsToRemove );
815
816     // For each visual in add list, create and add to mVisuals
817     Dali::CustomActor handle( mControlImpl.GetOwner() );
818     Style::ApplyVisuals( handle, stateVisualsToAdd, instancedProperties );
819
820     // For each visual in change list, if it requires a new visual,
821     // remove old visual, create and add to mVisuals
822     RecreateChangedVisuals( stateVisualsToChange, instancedProperties );
823   }
824
825   void SetState( DevelControl::State newState, bool withTransitions=true )
826   {
827     DevelControl::State oldState = mState;
828     Dali::CustomActor handle( mControlImpl.GetOwner() );
829     DALI_LOG_INFO(gLogFilter, Debug::Concise, "Control::Impl::SetState: %s\n",
830                   (mState == DevelControl::NORMAL ? "NORMAL" :(
831                     mState == DevelControl::FOCUSED ?"FOCUSED" : (
832                       mState == DevelControl::DISABLED?"DISABLED":"NONE" ))));
833
834     if( mState != newState )
835     {
836       // If mState was Disabled, and new state is Focused, should probably
837       // store that fact, e.g. in another property that FocusManager can access.
838       mState = newState;
839
840       // Trigger state change and transitions
841       // Apply new style, if stylemanager is available
842       Toolkit::StyleManager styleManager = Toolkit::StyleManager::Get();
843       if( styleManager )
844       {
845         const StylePtr stylePtr = GetImpl( styleManager ).GetRecordedStyle( Toolkit::Control( mControlImpl.GetOwner() ) );
846
847         if( stylePtr )
848         {
849           std::string oldStateName = Scripting::GetEnumerationName< Toolkit::DevelControl::State >( oldState, ControlStateTable, ControlStateTableCount );
850           std::string newStateName = Scripting::GetEnumerationName< Toolkit::DevelControl::State >( newState, ControlStateTable, ControlStateTableCount );
851
852           const StylePtr* newStateStyle = stylePtr->subStates.Find( newStateName );
853           const StylePtr* oldStateStyle = stylePtr->subStates.Find( oldStateName );
854           if( oldStateStyle && newStateStyle )
855           {
856             // Only change if both state styles exist
857             ReplaceStateVisualsAndProperties( *oldStateStyle, *newStateStyle, mSubStateName );
858           }
859         }
860       }
861     }
862   }
863
864   void SetSubState( const std::string& subStateName, bool withTransitions=true )
865   {
866     if( mSubStateName != subStateName )
867     {
868       // Get existing sub-state visuals, and unregister them
869       Dali::CustomActor handle( mControlImpl.GetOwner() );
870
871       Toolkit::StyleManager styleManager = Toolkit::StyleManager::Get();
872       if( styleManager )
873       {
874         const StylePtr stylePtr = GetImpl( styleManager ).GetRecordedStyle( Toolkit::Control( mControlImpl.GetOwner() ) );
875         if( stylePtr )
876         {
877           // Stringify state
878           std::string stateName = Scripting::GetEnumerationName< Toolkit::DevelControl::State >( mState, ControlStateTable, ControlStateTableCount );
879
880           const StylePtr* state = stylePtr->subStates.Find( stateName );
881           if( state )
882           {
883             StylePtr stateStyle(*state);
884
885             const StylePtr* newStateStyle = stateStyle->subStates.Find( subStateName );
886             const StylePtr* oldStateStyle = stateStyle->subStates.Find( mSubStateName );
887             if( oldStateStyle && newStateStyle )
888             {
889               std::string empty;
890               ReplaceStateVisualsAndProperties( *oldStateStyle, *newStateStyle, empty );
891             }
892           }
893         }
894       }
895
896       mSubStateName = subStateName;
897     }
898   }
899
900   // Data
901
902   Control& mControlImpl;
903   DevelControl::State mState;
904   std::string mSubStateName;
905
906   int mLeftFocusableActorId;       ///< Actor ID of Left focusable control.
907   int mRightFocusableActorId;      ///< Actor ID of Right focusable control.
908   int mUpFocusableActorId;         ///< Actor ID of Up focusable control.
909   int mDownFocusableActorId;       ///< Actor ID of Down focusable control.
910
911   RegisteredVisualContainer mVisuals; // Stores visuals needed by the control, non trivial type so std::vector used.
912   std::string mStyleName;
913   Vector4 mBackgroundColor;                       ///< The color of the background visual
914   Vector3* mStartingPinchScale;      ///< The scale when a pinch gesture starts, TODO: consider removing this
915   Toolkit::Control::KeyEventSignalType mKeyEventSignal;
916   Toolkit::Control::KeyInputFocusSignalType mKeyInputFocusGainedSignal;
917   Toolkit::Control::KeyInputFocusSignalType mKeyInputFocusLostSignal;
918
919   // Gesture Detection
920   PinchGestureDetector mPinchGestureDetector;
921   PanGestureDetector mPanGestureDetector;
922   TapGestureDetector mTapGestureDetector;
923   LongPressGestureDetector mLongPressGestureDetector;
924
925   // Tooltip
926   TooltipPtr mTooltip;
927
928   ControlBehaviour mFlags : CONTROL_BEHAVIOUR_FLAG_COUNT;    ///< Flags passed in from constructor.
929   bool mIsKeyboardNavigationSupported :1;  ///< Stores whether keyboard navigation is supported by the control.
930   bool mIsKeyboardFocusGroup :1;           ///< Stores whether the control is a focus group.
931
932   // Properties - these need to be members of Internal::Control::Impl as they access private methods/data of Internal::Control and Internal::Control::Impl.
933   static const PropertyRegistration PROPERTY_1;
934   static const PropertyRegistration PROPERTY_2;
935   static const PropertyRegistration PROPERTY_3;
936   static const PropertyRegistration PROPERTY_4;
937   static const PropertyRegistration PROPERTY_5;
938   static const PropertyRegistration PROPERTY_6;
939   static const PropertyRegistration PROPERTY_7;
940   static const PropertyRegistration PROPERTY_8;
941   static const PropertyRegistration PROPERTY_9;
942   static const PropertyRegistration PROPERTY_10;
943   static const PropertyRegistration PROPERTY_11;
944   static const PropertyRegistration PROPERTY_12;
945 };
946
947 // Properties registered without macro to use specific member variables.
948 const PropertyRegistration Control::Impl::PROPERTY_1( typeRegistration, "styleName",              Toolkit::Control::Property::STYLE_NAME,                   Property::STRING,  &Control::Impl::SetProperty, &Control::Impl::GetProperty );
949 const PropertyRegistration Control::Impl::PROPERTY_2( typeRegistration, "backgroundColor",        Toolkit::Control::Property::BACKGROUND_COLOR,             Property::VECTOR4, &Control::Impl::SetProperty, &Control::Impl::GetProperty );
950 const PropertyRegistration Control::Impl::PROPERTY_3( typeRegistration, "backgroundImage",        Toolkit::Control::Property::BACKGROUND_IMAGE,             Property::MAP,     &Control::Impl::SetProperty, &Control::Impl::GetProperty );
951 const PropertyRegistration Control::Impl::PROPERTY_4( typeRegistration, "keyInputFocus",          Toolkit::Control::Property::KEY_INPUT_FOCUS,              Property::BOOLEAN, &Control::Impl::SetProperty, &Control::Impl::GetProperty );
952 const PropertyRegistration Control::Impl::PROPERTY_5( typeRegistration, "background",             Toolkit::Control::Property::BACKGROUND,                   Property::MAP,     &Control::Impl::SetProperty, &Control::Impl::GetProperty );
953 const PropertyRegistration Control::Impl::PROPERTY_6( typeRegistration, "tooltip",                Toolkit::DevelControl::Property::TOOLTIP,                 Property::MAP,     &Control::Impl::SetProperty, &Control::Impl::GetProperty );
954 const PropertyRegistration Control::Impl::PROPERTY_7( typeRegistration, "state",                  Toolkit::DevelControl::Property::STATE,                   Property::STRING,  &Control::Impl::SetProperty, &Control::Impl::GetProperty );
955 const PropertyRegistration Control::Impl::PROPERTY_8( typeRegistration, "subState",               Toolkit::DevelControl::Property::SUB_STATE,               Property::STRING,  &Control::Impl::SetProperty, &Control::Impl::GetProperty );
956 const PropertyRegistration Control::Impl::PROPERTY_9( typeRegistration, "leftFocusableActorId",   Toolkit::DevelControl::Property::LEFT_FOCUSABLE_ACTOR_ID, Property::INTEGER, &Control::Impl::SetProperty, &Control::Impl::GetProperty );
957 const PropertyRegistration Control::Impl::PROPERTY_10( typeRegistration, "rightFocusableActorId", Toolkit::DevelControl::Property::RIGHT_FOCUSABLE_ACTOR_ID,Property::INTEGER, &Control::Impl::SetProperty, &Control::Impl::GetProperty );
958 const PropertyRegistration Control::Impl::PROPERTY_11( typeRegistration, "upFocusableActorId",    Toolkit::DevelControl::Property::UP_FOCUSABLE_ACTOR_ID,   Property::INTEGER, &Control::Impl::SetProperty, &Control::Impl::GetProperty );
959 const PropertyRegistration Control::Impl::PROPERTY_12( typeRegistration, "downFocusableActorId",  Toolkit::DevelControl::Property::DOWN_FOCUSABLE_ACTOR_ID, Property::INTEGER, &Control::Impl::SetProperty, &Control::Impl::GetProperty );
960
961 Toolkit::Control Control::New()
962 {
963   // Create the implementation, temporarily owned on stack
964   IntrusivePtr<Control> controlImpl = new Control( ControlBehaviour( CONTROL_BEHAVIOUR_DEFAULT ) );
965
966   // Pass ownership to handle
967   Toolkit::Control handle( *controlImpl );
968
969   // Second-phase init of the implementation
970   // This can only be done after the CustomActor connection has been made...
971   controlImpl->Initialize();
972
973   return handle;
974 }
975
976 void Control::SetStyleName( const std::string& styleName )
977 {
978   if( styleName != mImpl->mStyleName )
979   {
980     mImpl->mStyleName = styleName;
981
982     // Apply new style, if stylemanager is available
983     Toolkit::StyleManager styleManager = Toolkit::StyleManager::Get();
984     if( styleManager )
985     {
986       GetImpl( styleManager ).ApplyThemeStyle( Toolkit::Control( GetOwner() ) );
987     }
988   }
989 }
990
991 const std::string& Control::GetStyleName() const
992 {
993   return mImpl->mStyleName;
994 }
995
996 void Control::SetBackgroundColor( const Vector4& color )
997 {
998   mImpl->mBackgroundColor = color;
999   Property::Map map;
1000   map[ Toolkit::DevelVisual::Property::TYPE ] = Toolkit::Visual::COLOR;
1001   map[ Toolkit::ColorVisual::Property::MIX_COLOR ] = color;
1002
1003   SetBackground( map );
1004 }
1005
1006 Vector4 Control::GetBackgroundColor() const
1007 {
1008   return mImpl->mBackgroundColor;
1009 }
1010
1011 void Control::SetBackground( const Property::Map& map )
1012 {
1013   Toolkit::Visual::Base visual = Toolkit::VisualFactory::Get().CreateVisual( map );
1014   if( visual )
1015   {
1016     RegisterVisual( Toolkit::Control::Property::BACKGROUND, visual );
1017     visual.SetDepthIndex( DepthIndex::BACKGROUND );
1018
1019     // Trigger a size negotiation request that may be needed by the new visual to relayout its contents.
1020     RelayoutRequest();
1021   }
1022 }
1023
1024 void Control::SetBackgroundImage( Image image )
1025 {
1026   Toolkit::Visual::Base visual = Toolkit::VisualFactory::Get().CreateVisual( image );
1027   if( visual )
1028   {
1029     RegisterVisual( Toolkit::Control::Property::BACKGROUND, visual );
1030     visual.SetDepthIndex( DepthIndex::BACKGROUND );
1031   }
1032 }
1033
1034 void Control::ClearBackground()
1035 {
1036    UnregisterVisual( Toolkit::Control::Property::BACKGROUND );
1037    mImpl->mBackgroundColor = Color::TRANSPARENT;
1038
1039    // Trigger a size negotiation request that may be needed when unregistering a visual.
1040    RelayoutRequest();
1041 }
1042
1043 void Control::EnableGestureDetection(Gesture::Type type)
1044 {
1045   if ( (type & Gesture::Pinch) && !mImpl->mPinchGestureDetector )
1046   {
1047     mImpl->mPinchGestureDetector = PinchGestureDetector::New();
1048     mImpl->mPinchGestureDetector.DetectedSignal().Connect(mImpl, &Impl::PinchDetected);
1049     mImpl->mPinchGestureDetector.Attach(Self());
1050   }
1051
1052   if ( (type & Gesture::Pan) && !mImpl->mPanGestureDetector )
1053   {
1054     mImpl->mPanGestureDetector = PanGestureDetector::New();
1055     mImpl->mPanGestureDetector.DetectedSignal().Connect(mImpl, &Impl::PanDetected);
1056     mImpl->mPanGestureDetector.Attach(Self());
1057   }
1058
1059   if ( (type & Gesture::Tap) && !mImpl->mTapGestureDetector )
1060   {
1061     mImpl->mTapGestureDetector = TapGestureDetector::New();
1062     mImpl->mTapGestureDetector.DetectedSignal().Connect(mImpl, &Impl::TapDetected);
1063     mImpl->mTapGestureDetector.Attach(Self());
1064   }
1065
1066   if ( (type & Gesture::LongPress) && !mImpl->mLongPressGestureDetector )
1067   {
1068     mImpl->mLongPressGestureDetector = LongPressGestureDetector::New();
1069     mImpl->mLongPressGestureDetector.DetectedSignal().Connect(mImpl, &Impl::LongPressDetected);
1070     mImpl->mLongPressGestureDetector.Attach(Self());
1071   }
1072 }
1073
1074 void Control::DisableGestureDetection(Gesture::Type type)
1075 {
1076   if ( (type & Gesture::Pinch) && mImpl->mPinchGestureDetector )
1077   {
1078     mImpl->mPinchGestureDetector.Detach(Self());
1079     mImpl->mPinchGestureDetector.Reset();
1080   }
1081
1082   if ( (type & Gesture::Pan) && mImpl->mPanGestureDetector )
1083   {
1084     mImpl->mPanGestureDetector.Detach(Self());
1085     mImpl->mPanGestureDetector.Reset();
1086   }
1087
1088   if ( (type & Gesture::Tap) && mImpl->mTapGestureDetector )
1089   {
1090     mImpl->mTapGestureDetector.Detach(Self());
1091     mImpl->mTapGestureDetector.Reset();
1092   }
1093
1094   if ( (type & Gesture::LongPress) && mImpl->mLongPressGestureDetector)
1095   {
1096     mImpl->mLongPressGestureDetector.Detach(Self());
1097     mImpl->mLongPressGestureDetector.Reset();
1098   }
1099 }
1100
1101 PinchGestureDetector Control::GetPinchGestureDetector() const
1102 {
1103   return mImpl->mPinchGestureDetector;
1104 }
1105
1106 PanGestureDetector Control::GetPanGestureDetector() const
1107 {
1108   return mImpl->mPanGestureDetector;
1109 }
1110
1111 TapGestureDetector Control::GetTapGestureDetector() const
1112 {
1113   return mImpl->mTapGestureDetector;
1114 }
1115
1116 LongPressGestureDetector Control::GetLongPressGestureDetector() const
1117 {
1118   return mImpl->mLongPressGestureDetector;
1119 }
1120
1121 void Control::SetKeyboardNavigationSupport(bool isSupported)
1122 {
1123   mImpl->mIsKeyboardNavigationSupported = isSupported;
1124 }
1125
1126 bool Control::IsKeyboardNavigationSupported()
1127 {
1128   return mImpl->mIsKeyboardNavigationSupported;
1129 }
1130
1131 void Control::SetKeyInputFocus()
1132 {
1133   if( Self().OnStage() )
1134   {
1135     Toolkit::KeyInputFocusManager::Get().SetFocus(Toolkit::Control::DownCast(Self()));
1136   }
1137 }
1138
1139 bool Control::HasKeyInputFocus()
1140 {
1141   bool result = false;
1142   if( Self().OnStage() )
1143   {
1144     result = Toolkit::KeyInputFocusManager::Get().IsKeyboardListener(Toolkit::Control::DownCast(Self()));
1145   }
1146   return result;
1147 }
1148
1149 void Control::ClearKeyInputFocus()
1150 {
1151   if( Self().OnStage() )
1152   {
1153     Toolkit::KeyInputFocusManager::Get().RemoveFocus(Toolkit::Control::DownCast(Self()));
1154   }
1155 }
1156
1157 void Control::SetAsKeyboardFocusGroup(bool isFocusGroup)
1158 {
1159   mImpl->mIsKeyboardFocusGroup = isFocusGroup;
1160
1161   // The following line will be removed when the deprecated API in KeyboardFocusManager is deleted
1162   Toolkit::KeyboardFocusManager::Get().SetAsFocusGroup(Self(), isFocusGroup);
1163 }
1164
1165 bool Control::IsKeyboardFocusGroup()
1166 {
1167   return Toolkit::KeyboardFocusManager::Get().IsFocusGroup(Self());
1168 }
1169
1170 void Control::AccessibilityActivate()
1171 {
1172   // Inform deriving classes
1173   OnAccessibilityActivated();
1174 }
1175
1176 void Control::KeyboardEnter()
1177 {
1178   // Inform deriving classes
1179   OnKeyboardEnter();
1180 }
1181
1182 void Control::RegisterVisual( Property::Index index, Toolkit::Visual::Base& visual )
1183 {
1184   RegisterVisual( index, visual, true );
1185 }
1186
1187 void Control::RegisterVisual( Property::Index index, Toolkit::Visual::Base& visual, bool enabled )
1188 {
1189   bool visualReplaced ( false );
1190   Actor self = Self();
1191
1192   if( !mImpl->mVisuals.Empty() )
1193   {
1194     RegisteredVisualContainer::Iterator iter;
1195     // Check if visual (index) is already registered.  Replace if so.
1196     if ( FindVisual( index, mImpl->mVisuals, iter ) )
1197     {
1198       if( (*iter)->visual && self.OnStage() )
1199       {
1200         Toolkit::GetImplementation((*iter)->visual).SetOffStage( self );
1201       }
1202       (*iter)->visual = visual;
1203       visualReplaced = true;
1204     }
1205   }
1206
1207   // If not set, set the name of the visual to the same name as the control's property.
1208   // ( If the control has been type registered )
1209   if( visual.GetName().empty() )
1210   {
1211     // Check if the control has been type registered:
1212     TypeInfo typeInfo = TypeRegistry::Get().GetTypeInfo( typeid(*this) );
1213     if( typeInfo )
1214     {
1215       // Check if the property index has been registered:
1216       Property::IndexContainer indices;
1217       typeInfo.GetPropertyIndices( indices );
1218       Property::IndexContainer::Iterator iter = std::find( indices.Begin(), indices.End(), index );
1219       if( iter != indices.End() )
1220       {
1221         // If it has, then get it's name and use that for the visual
1222         std::string visualName = typeInfo.GetPropertyName( index );
1223         visual.SetName( visualName );
1224       }
1225     }
1226   }
1227
1228   if( !visualReplaced ) // New registration entry
1229   {
1230     mImpl->mVisuals.PushBack( new RegisteredVisual( index, visual, enabled ) );
1231   }
1232
1233   if( visual && self.OnStage() && enabled )
1234   {
1235     Toolkit::GetImplementation(visual).SetOnStage( self );
1236   }
1237
1238   DALI_LOG_INFO( gLogFilter, Debug::Verbose, "Control::RegisterVisual() Registered %s(%d), enabled:%s\n",  visual.GetName().c_str(), index, enabled?"T":"F" );
1239 }
1240
1241 void Control::UnregisterVisual( Property::Index index )
1242 {
1243    RegisteredVisualContainer::Iterator iter;
1244    if ( FindVisual( index, mImpl->mVisuals, iter ) )
1245    {
1246      Actor self( Self() );
1247      Toolkit::GetImplementation((*iter)->visual).SetOffStage( self );
1248      (*iter)->visual.Reset();
1249      mImpl->mVisuals.Erase( iter );
1250    }
1251 }
1252
1253 Toolkit::Visual::Base Control::GetVisual( Property::Index index ) const
1254 {
1255   RegisteredVisualContainer::Iterator iter;
1256   if ( FindVisual( index, mImpl->mVisuals, iter ) )
1257   {
1258     return (*iter)->visual;
1259   }
1260
1261   return Toolkit::Visual::Base();
1262 }
1263
1264 void Control::EnableVisual( Property::Index index, bool enable )
1265 {
1266   RegisteredVisualContainer::Iterator iter;
1267   if ( FindVisual( index, mImpl->mVisuals, iter ) )
1268   {
1269     if (  (*iter)->enabled == enable )
1270     {
1271       DALI_LOG_INFO( gLogFilter, Debug::Verbose, "Control::EnableVisual Visual %s(%d) already %s\n", (*iter)->visual.GetName().c_str(), index, enable?"enabled":"disabled");
1272       return;
1273     }
1274
1275     (*iter)->enabled = enable;
1276     Actor parentActor = Self();
1277     if ( Self().OnStage() ) // If control not on Stage then Visual will be added when StageConnection is called.
1278     {
1279       if ( enable )
1280       {
1281         DALI_LOG_INFO( gLogFilter, Debug::Verbose, "Control::EnableVisual Setting %s(%d) on stage \n", (*iter)->visual.GetName().c_str(), index );
1282         Toolkit::GetImplementation((*iter)->visual).SetOnStage( parentActor );
1283       }
1284       else
1285       {
1286         DALI_LOG_INFO( gLogFilter, Debug::Verbose, "Control::EnableVisual Setting %s(%d) off stage \n", (*iter)->visual.GetName().c_str(), index );
1287         Toolkit::GetImplementation((*iter)->visual).SetOffStage( parentActor );  // No need to call if control not staged.
1288       }
1289     }
1290   }
1291 }
1292
1293 bool Control::IsVisualEnabled( Property::Index index ) const
1294 {
1295   RegisteredVisualContainer::Iterator iter;
1296   if ( FindVisual( index, mImpl->mVisuals, iter ) )
1297   {
1298     return (*iter)->enabled;
1299   }
1300   return false;
1301 }
1302
1303 Dali::Animation Control::CreateTransition( const Toolkit::TransitionData& handle )
1304 {
1305   Dali::Animation transition;
1306   const Internal::TransitionData& transitionData = Toolkit::GetImplementation( handle );
1307
1308   if( transitionData.Count() > 0 )
1309   {
1310     // Setup a Transition from TransitionData.
1311     TransitionData::Iterator end = transitionData.End();
1312     for( TransitionData::Iterator iter = transitionData.Begin() ;
1313          iter != end; ++iter )
1314     {
1315       TransitionData::Animator* animator = (*iter);
1316
1317       Toolkit::Visual::Base visual = GetVisualByName( mImpl->mVisuals, animator->objectName );
1318
1319       if( visual )
1320       {
1321         Internal::Visual::Base& visualImpl = Toolkit::GetImplementation( visual );
1322         visualImpl.AnimateProperty( transition, *animator );
1323       }
1324       else
1325       {
1326         // Otherwise, try any actor children of control (Including the control)
1327         Actor child = Self().FindChildByName( animator->objectName );
1328         if( child )
1329         {
1330           Property::Index propertyIndex = DevelHandle::GetPropertyIndex( child, animator->propertyKey );
1331           if( propertyIndex != Property::INVALID_INDEX )
1332           {
1333             if( animator->animate == false )
1334             {
1335               if( animator->targetValue.GetType() != Property::NONE )
1336               {
1337                 child.SetProperty( propertyIndex, animator->targetValue );
1338               }
1339             }
1340             else // animate the property
1341             {
1342               if( animator->initialValue.GetType() != Property::NONE )
1343               {
1344                 child.SetProperty( propertyIndex, animator->initialValue );
1345               }
1346
1347               if( ! transition )
1348               {
1349                 transition = Dali::Animation::New( 0.1f );
1350               }
1351
1352               transition.AnimateTo( Property( child, propertyIndex ),
1353                                     animator->targetValue,
1354                                     animator->alphaFunction,
1355                                     TimePeriod( animator->timePeriodDelay,
1356                                                 animator->timePeriodDuration ) );
1357             }
1358           }
1359         }
1360       }
1361     }
1362   }
1363
1364   return transition;
1365 }
1366
1367 bool Control::OnAccessibilityActivated()
1368 {
1369   return false; // Accessibility activation is not handled by default
1370 }
1371
1372 bool Control::OnKeyboardEnter()
1373 {
1374   return false; // Keyboard enter is not handled by default
1375 }
1376
1377 bool Control::OnAccessibilityPan(PanGesture gesture)
1378 {
1379   return false; // Accessibility pan gesture is not handled by default
1380 }
1381
1382 bool Control::OnAccessibilityTouch(const TouchEvent& touchEvent)
1383 {
1384   return false; // Accessibility touch event is not handled by default
1385 }
1386
1387 bool Control::OnAccessibilityValueChange(bool isIncrease)
1388 {
1389   return false; // Accessibility value change action is not handled by default
1390 }
1391
1392 bool Control::OnAccessibilityZoom()
1393 {
1394   return false; // Accessibility zoom action is not handled by default
1395 }
1396
1397 Actor Control::GetNextKeyboardFocusableActor(Actor currentFocusedActor, Toolkit::Control::KeyboardFocus::Direction direction, bool loopEnabled)
1398 {
1399   return Actor();
1400 }
1401
1402 void Control::OnKeyboardFocusChangeCommitted(Actor commitedFocusableActor)
1403 {
1404 }
1405
1406 Toolkit::Control::KeyEventSignalType& Control::KeyEventSignal()
1407 {
1408   return mImpl->mKeyEventSignal;
1409 }
1410
1411 Toolkit::Control::KeyInputFocusSignalType& Control::KeyInputFocusGainedSignal()
1412 {
1413   return mImpl->mKeyInputFocusGainedSignal;
1414 }
1415
1416 Toolkit::Control::KeyInputFocusSignalType& Control::KeyInputFocusLostSignal()
1417 {
1418   return mImpl->mKeyInputFocusLostSignal;
1419 }
1420
1421 bool Control::EmitKeyEventSignal( const KeyEvent& event )
1422 {
1423   // Guard against destruction during signal emission
1424   Dali::Toolkit::Control handle( GetOwner() );
1425
1426   bool consumed = false;
1427
1428   // signals are allocated dynamically when someone connects
1429   if ( !mImpl->mKeyEventSignal.Empty() )
1430   {
1431     consumed = mImpl->mKeyEventSignal.Emit( handle, event );
1432   }
1433
1434   if (!consumed)
1435   {
1436     // Notification for derived classes
1437     consumed = OnKeyEvent(event);
1438   }
1439
1440   return consumed;
1441 }
1442
1443 Control::Control( ControlBehaviour behaviourFlags )
1444 : CustomActorImpl( static_cast< ActorFlags >( behaviourFlags ) ),
1445   mImpl(new Impl(*this))
1446 {
1447   mImpl->mFlags = behaviourFlags;
1448 }
1449
1450 Control::~Control()
1451 {
1452   delete mImpl;
1453 }
1454
1455 void Control::Initialize()
1456 {
1457   // Call deriving classes so initialised before styling is applied to them.
1458   OnInitialize();
1459
1460   if( (mImpl->mFlags & REQUIRES_STYLE_CHANGE_SIGNALS) ||
1461       !(mImpl->mFlags & DISABLE_STYLE_CHANGE_SIGNALS) )
1462   {
1463     Toolkit::StyleManager styleManager = StyleManager::Get();
1464
1465     // if stylemanager is available
1466     if( styleManager )
1467     {
1468       StyleManager& styleManagerImpl = GetImpl( styleManager );
1469
1470       // Register for style changes
1471       styleManagerImpl.ControlStyleChangeSignal().Connect( this, &Control::OnStyleChange );
1472
1473       // Apply the current style
1474       styleManagerImpl.ApplyThemeStyleAtInit( Toolkit::Control( GetOwner() ) );
1475     }
1476   }
1477
1478   if( mImpl->mFlags & REQUIRES_KEYBOARD_NAVIGATION_SUPPORT )
1479   {
1480     SetKeyboardNavigationSupport( true );
1481   }
1482 }
1483
1484 void Control::OnInitialize()
1485 {
1486 }
1487
1488 void Control::OnControlChildAdd( Actor& child )
1489 {
1490 }
1491
1492 void Control::OnControlChildRemove( Actor& child )
1493 {
1494 }
1495
1496 void Control::OnStyleChange( Toolkit::StyleManager styleManager, StyleChange::Type change )
1497 {
1498   // By default the control is only interested in theme (not font) changes
1499   if( styleManager && change == StyleChange::THEME_CHANGE )
1500   {
1501     GetImpl( styleManager ).ApplyThemeStyle( Toolkit::Control( GetOwner() ) );
1502   }
1503   RelayoutRequest();
1504 }
1505
1506 void Control::OnPinch(const PinchGesture& pinch)
1507 {
1508   if( !( mImpl->mStartingPinchScale ) )
1509   {
1510     // lazy allocate
1511     mImpl->mStartingPinchScale = new Vector3;
1512   }
1513
1514   if( pinch.state == Gesture::Started )
1515   {
1516     *( mImpl->mStartingPinchScale ) = Self().GetCurrentScale();
1517   }
1518
1519   Self().SetScale( *( mImpl->mStartingPinchScale ) * pinch.scale );
1520 }
1521
1522 void Control::OnPan( const PanGesture& pan )
1523 {
1524 }
1525
1526 void Control::OnTap(const TapGesture& tap)
1527 {
1528 }
1529
1530 void Control::OnLongPress( const LongPressGesture& longPress )
1531 {
1532 }
1533
1534 void Control::EmitKeyInputFocusSignal( bool focusGained )
1535 {
1536   Dali::Toolkit::Control handle( GetOwner() );
1537
1538   if ( focusGained )
1539   {
1540     // signals are allocated dynamically when someone connects
1541     if ( !mImpl->mKeyInputFocusGainedSignal.Empty() )
1542     {
1543       mImpl->mKeyInputFocusGainedSignal.Emit( handle );
1544     }
1545   }
1546   else
1547   {
1548     // signals are allocated dynamically when someone connects
1549     if ( !mImpl->mKeyInputFocusLostSignal.Empty() )
1550     {
1551       mImpl->mKeyInputFocusLostSignal.Emit( handle );
1552     }
1553   }
1554 }
1555
1556 void Control::OnStageConnection( int depth )
1557 {
1558   DALI_LOG_INFO( gLogFilter, Debug::Verbose, "Control::OnStageConnection number of registered visuals(%d)\n",  mImpl->mVisuals.Size() );
1559
1560   Actor self( Self() );
1561
1562   for(RegisteredVisualContainer::Iterator iter = mImpl->mVisuals.Begin(); iter!= mImpl->mVisuals.End(); iter++)
1563   {
1564     // Check whether the visual is empty and enabled
1565     if( (*iter)->visual && (*iter)->enabled )
1566     {
1567       DALI_LOG_INFO( gLogFilter, Debug::Verbose, "Control::OnStageConnection Setting visual(%d) on stage\n", (*iter)->index );
1568       Toolkit::GetImplementation((*iter)->visual).SetOnStage( self );
1569     }
1570   }
1571
1572   if( mImpl->mVisuals.Empty() && ! self.GetRendererCount() )
1573   {
1574     Property::Value clippingValue = self.GetProperty( Actor::Property::CLIPPING_MODE );
1575     int clippingMode = ClippingMode::DISABLED;
1576     if( clippingValue.Get( clippingMode ) )
1577     {
1578       // Add a transparent background if we do not have any renderers or visuals so we clip our children
1579
1580       if( clippingMode == ClippingMode::CLIP_CHILDREN )
1581       {
1582         // Create a transparent background visual which will also get staged.
1583         SetBackgroundColor( Color::TRANSPARENT );
1584       }
1585     }
1586   }
1587 }
1588
1589 void Control::OnStageDisconnection()
1590 {
1591   for(RegisteredVisualContainer::Iterator iter = mImpl->mVisuals.Begin(); iter!= mImpl->mVisuals.End(); iter++)
1592   {
1593     // Check whether the visual is empty
1594     if( (*iter)->visual )
1595     {
1596       DALI_LOG_INFO( gLogFilter, Debug::Verbose, "Control::OnStageDisconnection Setting visual(%d) off stage\n", (*iter)->index );
1597       Actor self( Self() );
1598       Toolkit::GetImplementation((*iter)->visual).SetOffStage( self );
1599     }
1600   }
1601 }
1602
1603 void Control::OnKeyInputFocusGained()
1604 {
1605   EmitKeyInputFocusSignal( true );
1606 }
1607
1608 void Control::OnKeyInputFocusLost()
1609 {
1610   EmitKeyInputFocusSignal( false );
1611 }
1612
1613 void Control::OnChildAdd(Actor& child)
1614 {
1615   // Notify derived classes.
1616   OnControlChildAdd( child );
1617 }
1618
1619 void Control::OnChildRemove(Actor& child)
1620 {
1621   // Notify derived classes.
1622   OnControlChildRemove( child );
1623 }
1624
1625 void Control::OnPropertySet( Property::Index index, Property::Value propertyValue )
1626 {
1627   Actor self( Self() );
1628   if( index == Actor::Property::CLIPPING_MODE )
1629   {
1630     // Only set the background if we're already on the stage and have no renderers or visuals
1631
1632     if( mImpl->mVisuals.Empty() && ! self.GetRendererCount() && self.OnStage() )
1633     {
1634       ClippingMode::Type clippingMode = ClippingMode::DISABLED;
1635       if( Scripting::GetEnumerationProperty< ClippingMode::Type >( propertyValue, CLIPPING_MODE_TABLE, CLIPPING_MODE_TABLE_COUNT, clippingMode ) )
1636       {
1637         // Add a transparent background if we do not have one so we clip children
1638
1639         if( clippingMode == ClippingMode::CLIP_CHILDREN )
1640         {
1641           SetBackgroundColor( Color::TRANSPARENT );
1642         }
1643       }
1644     }
1645   }
1646 }
1647
1648 void Control::OnSizeSet(const Vector3& targetSize)
1649 {
1650   Toolkit::Visual::Base visual = GetVisual( Toolkit::Control::Property::BACKGROUND );
1651   if( visual )
1652   {
1653     Vector2 size( targetSize );
1654     visual.SetTransformAndSize( Property::Map(), size ); // Send an empty map as we do not want to modify the visual's set transform
1655   }
1656 }
1657
1658 void Control::OnSizeAnimation(Animation& animation, const Vector3& targetSize)
1659 {
1660   // @todo size negotiate background to new size, animate as well?
1661 }
1662
1663 bool Control::OnTouchEvent(const TouchEvent& event)
1664 {
1665   return false; // Do not consume
1666 }
1667
1668 bool Control::OnHoverEvent(const HoverEvent& event)
1669 {
1670   return false; // Do not consume
1671 }
1672
1673 bool Control::OnKeyEvent(const KeyEvent& event)
1674 {
1675   return false; // Do not consume
1676 }
1677
1678 bool Control::OnWheelEvent(const WheelEvent& event)
1679 {
1680   return false; // Do not consume
1681 }
1682
1683 void Control::OnRelayout( const Vector2& size, RelayoutContainer& container )
1684 {
1685   for( unsigned int i = 0, numChildren = Self().GetChildCount(); i < numChildren; ++i )
1686   {
1687     container.Add( Self().GetChildAt( i ), size );
1688   }
1689
1690   Toolkit::Visual::Base visual = GetVisual( Toolkit::Control::Property::BACKGROUND );
1691   if( visual )
1692   {
1693     visual.SetTransformAndSize( Property::Map(), size ); // Send an empty map as we do not want to modify the visual's set transform
1694   }
1695 }
1696
1697 void Control::OnSetResizePolicy( ResizePolicy::Type policy, Dimension::Type dimension )
1698 {
1699 }
1700
1701 Vector3 Control::GetNaturalSize()
1702 {
1703   Toolkit::Visual::Base visual = GetVisual( Toolkit::Control::Property::BACKGROUND );
1704   if( visual )
1705   {
1706     Vector2 naturalSize;
1707     visual.GetNaturalSize( naturalSize );
1708     return Vector3( naturalSize );
1709   }
1710   return Vector3::ZERO;
1711 }
1712
1713 float Control::CalculateChildSize( const Dali::Actor& child, Dimension::Type dimension )
1714 {
1715   return CalculateChildSizeBase( child, dimension );
1716 }
1717
1718 float Control::GetHeightForWidth( float width )
1719 {
1720   return GetHeightForWidthBase( width );
1721 }
1722
1723 float Control::GetWidthForHeight( float height )
1724 {
1725   return GetWidthForHeightBase( height );
1726 }
1727
1728 bool Control::RelayoutDependentOnChildren( Dimension::Type dimension )
1729 {
1730   return RelayoutDependentOnChildrenBase( dimension );
1731 }
1732
1733 void Control::OnCalculateRelayoutSize( Dimension::Type dimension )
1734 {
1735 }
1736
1737 void Control::OnLayoutNegotiated( float size, Dimension::Type dimension )
1738 {
1739 }
1740
1741 void Control::SignalConnected( SlotObserver* slotObserver, CallbackBase* callback )
1742 {
1743   mImpl->SignalConnected( slotObserver, callback );
1744 }
1745
1746 void Control::SignalDisconnected( SlotObserver* slotObserver, CallbackBase* callback )
1747 {
1748   mImpl->SignalDisconnected( slotObserver, callback );
1749 }
1750
1751 Control& GetImplementation( Dali::Toolkit::Control& handle )
1752 {
1753   CustomActorImpl& customInterface = handle.GetImplementation();
1754   // downcast to control
1755   Control& impl = dynamic_cast< Internal::Control& >( customInterface );
1756   return impl;
1757 }
1758
1759 const Control& GetImplementation( const Dali::Toolkit::Control& handle )
1760 {
1761   const CustomActorImpl& customInterface = handle.GetImplementation();
1762   // downcast to control
1763   const Control& impl = dynamic_cast< const Internal::Control& >( customInterface );
1764   return impl;
1765 }
1766
1767 } // namespace Internal
1768
1769 } // namespace Toolkit
1770
1771 } // namespace Dali