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