Merge "Fix BackgroundImage and BackgroudColor properties in C# View" 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           Vector4 color;
413           const Property::Map* map = value.GetMap();
414           if( map && !map->Empty() )
415           {
416             controlImpl.SetBackground( *map );
417           }
418           else if( value.Get( url ) )
419           {
420             // don't know the size to load
421             Toolkit::Visual::Base visual = Toolkit::VisualFactory::Get().CreateVisual( url, ImageDimensions() );
422             if( visual )
423             {
424               controlImpl.RegisterVisual( Toolkit::Control::Property::BACKGROUND, visual );
425               visual.SetDepthIndex( DepthIndex::BACKGROUND );
426             }
427           }
428           else if( value.Get( color ) )
429           {
430             controlImpl.SetBackgroundColor(color);
431           }
432           else
433           {
434             // The background is an empty property map, so we should clear the background
435             controlImpl.ClearBackground();
436           }
437           break;
438         }
439
440         case Toolkit::DevelControl::Property::TOOLTIP:
441         {
442           TooltipPtr& tooltipPtr = controlImpl.mImpl->mTooltip;
443           if( ! tooltipPtr )
444           {
445             tooltipPtr = Tooltip::New( control );
446           }
447           tooltipPtr->SetProperties( value );
448         }
449       }
450     }
451   }
452
453   /**
454    * Called to retrieve a property of an object of this type.
455    * @param[in] object The object whose property is to be retrieved.
456    * @param[in] index The property index.
457    * @return The current value of the property.
458    */
459   static Property::Value GetProperty( BaseObject* object, Property::Index index )
460   {
461     Property::Value value;
462
463     Toolkit::Control control = Toolkit::Control::DownCast( BaseHandle( object ) );
464
465     if ( control )
466     {
467       Control& controlImpl( GetImplementation( control ) );
468
469       switch ( index )
470       {
471         case Toolkit::Control::Property::STYLE_NAME:
472         {
473           value = controlImpl.GetStyleName();
474           break;
475         }
476
477         case Toolkit::DevelControl::Property::STATE:
478         {
479           value = controlImpl.mImpl->mState;
480           break;
481         }
482
483         case Toolkit::DevelControl::Property::SUB_STATE:
484         {
485           value = controlImpl.mImpl->mSubStateName;
486           break;
487         }
488
489         case Toolkit::Control::Property::BACKGROUND_COLOR:
490         {
491           DALI_LOG_WARNING( "BACKGROUND_COLOR property is deprecated. Use BACKGROUND property instead\n" );
492           value = controlImpl.GetBackgroundColor();
493           break;
494         }
495
496         case Toolkit::Control::Property::BACKGROUND_IMAGE:
497         {
498           DALI_LOG_WARNING( "BACKGROUND_IMAGE property is deprecated. Use BACKGROUND property instead\n" );
499           Property::Map map;
500           Toolkit::Visual::Base visual = controlImpl.GetVisual( Toolkit::Control::Property::BACKGROUND );
501           if( visual )
502           {
503             visual.CreatePropertyMap( map );
504           }
505           value = map;
506           break;
507         }
508
509         case Toolkit::Control::Property::KEY_INPUT_FOCUS:
510         {
511           value = controlImpl.HasKeyInputFocus();
512           break;
513         }
514
515         case Toolkit::Control::Property::BACKGROUND:
516         {
517           Property::Map map;
518           Toolkit::Visual::Base visual = controlImpl.GetVisual( Toolkit::Control::Property::BACKGROUND );
519           if( visual )
520           {
521             visual.CreatePropertyMap( map );
522           }
523
524           value = map;
525           break;
526         }
527
528         case Toolkit::DevelControl::Property::TOOLTIP:
529         {
530           Property::Map map;
531           if( controlImpl.mImpl->mTooltip )
532           {
533             controlImpl.mImpl->mTooltip->CreatePropertyMap( map );
534           }
535           value = map;
536           break;
537         }
538
539       }
540     }
541
542     return value;
543   }
544
545
546   void CopyInstancedProperties( RegisteredVisualContainer& visuals, Dictionary<Property::Map>& instancedProperties )
547   {
548     for(RegisteredVisualContainer::Iterator iter = visuals.Begin(); iter!= visuals.End(); iter++)
549     {
550       if( (*iter)->visual )
551       {
552         Property::Map instanceMap;
553         Toolkit::GetImplementation((*iter)->visual).CreateInstancePropertyMap(instanceMap);
554         instancedProperties.Add( (*iter)->visual.GetName(), instanceMap );
555       }
556     }
557   }
558
559   template<typename T>
560   void Remove( Dictionary<T>& keyValues, const std::string& name )
561   {
562     keyValues.Remove(name);
563   }
564
565   void Remove( DictionaryKeys& keys, const std::string& name )
566   {
567     DictionaryKeys::iterator iter = std::find( keys.begin(), keys.end(), name );
568     if( iter != keys.end())
569     {
570       keys.erase(iter);
571     }
572   }
573
574   void FindChangableVisuals( Dictionary<Property::Map>& stateVisualsToAdd,
575                              Dictionary<Property::Map>& stateVisualsToChange,
576                              DictionaryKeys& stateVisualsToRemove)
577   {
578     DictionaryKeys copyOfStateVisualsToRemove = stateVisualsToRemove;
579
580     for( DictionaryKeys::iterator iter = copyOfStateVisualsToRemove.begin();
581          iter != copyOfStateVisualsToRemove.end(); ++iter )
582     {
583       const std::string& visualName = (*iter);
584       Property::Map* toMap = stateVisualsToAdd.Find( visualName );
585       if( toMap )
586       {
587         stateVisualsToChange.Add( visualName, *toMap );
588         stateVisualsToAdd.Remove( visualName );
589         Remove( stateVisualsToRemove, visualName );
590       }
591     }
592   }
593
594   void RemoveVisual( RegisteredVisualContainer& visuals, const std::string& visualName )
595   {
596     Actor self( mControlImpl.Self() );
597
598     for ( RegisteredVisualContainer::Iterator visualIter = visuals.Begin();
599           visualIter != visuals.End(); ++visualIter )
600     {
601       Toolkit::Visual::Base visual = (*visualIter)->visual;
602       if( visual && visual.GetName() == visualName )
603       {
604         Toolkit::GetImplementation(visual).SetOffStage( self );
605         (*visualIter)->visual.Reset();
606         visuals.Erase( visualIter );
607         break;
608       }
609     }
610   }
611
612   void RemoveVisuals( RegisteredVisualContainer& visuals, DictionaryKeys& removeVisuals )
613   {
614     Actor self( mControlImpl.Self() );
615     for( DictionaryKeys::iterator iter = removeVisuals.begin(); iter != removeVisuals.end(); ++iter )
616     {
617       const std::string visualName = *iter;
618       RemoveVisual( visuals, visualName );
619     }
620   }
621
622   Toolkit::Visual::Type GetVisualTypeFromMap( const Property::Map& map )
623   {
624     Property::Value* typeValue = map.Find( Toolkit::Visual::Property::TYPE, VISUAL_TYPE  );
625     Toolkit::Visual::Type type = Toolkit::Visual::IMAGE;
626     if( typeValue )
627     {
628       Scripting::GetEnumerationProperty( *typeValue, VISUAL_TYPE_TABLE, VISUAL_TYPE_TABLE_COUNT, type );
629     }
630     return type;
631   }
632
633   /**
634    * Go through the list of visuals that are common to both states.
635    * If they are different types, or are both image types with different
636    * URLs, then the existing visual needs moving and the new visual creating
637    */
638   void RecreateChangedVisuals( Dictionary<Property::Map>& stateVisualsToChange,
639                                Dictionary<Property::Map>& instancedProperties )
640   {
641     Dali::CustomActor handle( mControlImpl.GetOwner() );
642     for( Dictionary<Property::Map>::iterator iter = stateVisualsToChange.Begin();
643          iter != stateVisualsToChange.End(); ++iter )
644     {
645       const std::string& visualName = (*iter).key;
646       const Property::Map& toMap = (*iter).entry;
647
648       // is it a candidate for re-creation?
649       bool recreate = false;
650
651       Toolkit::Visual::Base visual = GetVisualByName( mVisuals, visualName );
652       if( visual )
653       {
654         Property::Map fromMap;
655         visual.CreatePropertyMap( fromMap );
656
657         Toolkit::Visual::Type fromType = GetVisualTypeFromMap( fromMap );
658         Toolkit::Visual::Type toType = GetVisualTypeFromMap( toMap );
659
660         if( fromType != toType )
661         {
662           recreate = true;
663         }
664         else
665         {
666           if( fromType == Toolkit::Visual::IMAGE )
667           {
668             Property::Value* fromUrl = fromMap.Find( Toolkit::ImageVisual::Property::URL, IMAGE_URL_NAME );
669             Property::Value* toUrl = toMap.Find( Toolkit::ImageVisual::Property::URL, IMAGE_URL_NAME );
670
671             if( fromUrl && toUrl )
672             {
673               std::string fromUrlString;
674               std::string toUrlString;
675               fromUrl->Get(fromUrlString);
676               toUrl->Get(toUrlString);
677
678               if( fromUrlString != toUrlString )
679               {
680                 recreate = true;
681               }
682             }
683           }
684         }
685
686         const Property::Map* instancedMap = instancedProperties.FindConst( visualName );
687         if( recreate || instancedMap )
688         {
689           RemoveVisual( mVisuals, visualName );
690           Style::ApplyVisual( handle, visualName, toMap, instancedMap );
691         }
692         else
693         {
694           // @todo check to see if we can apply toMap without recreating the visual
695           // e.g. by setting only animatable properties
696           // For now, recreate all visuals, but merge in instance data.
697           RemoveVisual( mVisuals, visualName );
698           Style::ApplyVisual( handle, visualName, toMap, instancedMap );
699         }
700       }
701     }
702   }
703
704   void ReplaceStateVisualsAndProperties( const StylePtr oldState, const StylePtr newState, const std::string& subState )
705   {
706     // Collect all old visual names
707     DictionaryKeys stateVisualsToRemove;
708     if( oldState )
709     {
710       oldState->visuals.GetKeys( stateVisualsToRemove );
711       if( ! subState.empty() )
712       {
713         const StylePtr* oldSubState = oldState->subStates.FindConst(subState);
714         if( oldSubState )
715         {
716           DictionaryKeys subStateVisualsToRemove;
717           (*oldSubState)->visuals.GetKeys( subStateVisualsToRemove );
718           Merge( stateVisualsToRemove, subStateVisualsToRemove );
719         }
720       }
721     }
722
723     // Collect all new visual properties
724     Dictionary<Property::Map> stateVisualsToAdd;
725     if( newState )
726     {
727       stateVisualsToAdd = newState->visuals;
728       if( ! subState.empty() )
729       {
730         const StylePtr* newSubState = newState->subStates.FindConst(subState);
731         if( newSubState )
732         {
733           stateVisualsToAdd.Merge( (*newSubState)->visuals );
734         }
735       }
736     }
737
738     // If a name is in both add/remove, move it to change list.
739     Dictionary<Property::Map> stateVisualsToChange;
740     FindChangableVisuals( stateVisualsToAdd, stateVisualsToChange, stateVisualsToRemove);
741
742     // Copy instanced properties (e.g. text label) of current visuals
743     Dictionary<Property::Map> instancedProperties;
744     CopyInstancedProperties( mVisuals, instancedProperties );
745
746     // For each visual in remove list, remove from mVisuals
747     RemoveVisuals( mVisuals, stateVisualsToRemove );
748
749     // For each visual in add list, create and add to mVisuals
750     Dali::CustomActor handle( mControlImpl.GetOwner() );
751     Style::ApplyVisuals( handle, stateVisualsToAdd, instancedProperties );
752
753     // For each visual in change list, if it requires a new visual,
754     // remove old visual, create and add to mVisuals
755     RecreateChangedVisuals( stateVisualsToChange, instancedProperties );
756   }
757
758   void SetState( DevelControl::State newState, bool withTransitions=true )
759   {
760     DevelControl::State oldState = mState;
761     Dali::CustomActor handle( mControlImpl.GetOwner() );
762     DALI_LOG_INFO(gLogFilter, Debug::Concise, "Control::Impl::SetState: %s\n",
763                   (mState == DevelControl::NORMAL ? "NORMAL" :(
764                     mState == DevelControl::FOCUSED ?"FOCUSED" : (
765                       mState == DevelControl::DISABLED?"DISABLED":"NONE" ))));
766
767     if( mState != newState )
768     {
769       // If mState was Disabled, and new state is Focused, should probably
770       // store that fact, e.g. in another property that FocusManager can access.
771       mState = newState;
772
773       // Trigger state change and transitions
774       // Apply new style, if stylemanager is available
775       Toolkit::StyleManager styleManager = Toolkit::StyleManager::Get();
776       if( styleManager )
777       {
778         const StylePtr stylePtr = GetImpl( styleManager ).GetRecordedStyle( Toolkit::Control( mControlImpl.GetOwner() ) );
779
780         if( stylePtr )
781         {
782           std::string oldStateName = Scripting::GetEnumerationName< Toolkit::DevelControl::State >( oldState, ControlStateTable, ControlStateTableCount );
783           std::string newStateName = Scripting::GetEnumerationName< Toolkit::DevelControl::State >( newState, ControlStateTable, ControlStateTableCount );
784
785           const StylePtr* newStateStyle = stylePtr->subStates.Find( newStateName );
786           const StylePtr* oldStateStyle = stylePtr->subStates.Find( oldStateName );
787           if( oldStateStyle && newStateStyle )
788           {
789             // Only change if both state styles exist
790             ReplaceStateVisualsAndProperties( *oldStateStyle, *newStateStyle, mSubStateName );
791           }
792         }
793       }
794     }
795   }
796
797   void SetSubState( const std::string& subStateName, bool withTransitions=true )
798   {
799     if( mSubStateName != subStateName )
800     {
801       // Get existing sub-state visuals, and unregister them
802       Dali::CustomActor handle( mControlImpl.GetOwner() );
803
804       Toolkit::StyleManager styleManager = Toolkit::StyleManager::Get();
805       if( styleManager )
806       {
807         const StylePtr stylePtr = GetImpl( styleManager ).GetRecordedStyle( Toolkit::Control( mControlImpl.GetOwner() ) );
808         if( stylePtr )
809         {
810           // Stringify state
811           std::string stateName = Scripting::GetEnumerationName< Toolkit::DevelControl::State >( mState, ControlStateTable, ControlStateTableCount );
812
813           const StylePtr* state = stylePtr->subStates.Find( stateName );
814           if( state )
815           {
816             StylePtr stateStyle(*state);
817
818             const StylePtr* newStateStyle = stateStyle->subStates.Find( subStateName );
819             const StylePtr* oldStateStyle = stateStyle->subStates.Find( mSubStateName );
820             if( oldStateStyle && newStateStyle )
821             {
822               std::string empty;
823               ReplaceStateVisualsAndProperties( *oldStateStyle, *newStateStyle, empty );
824             }
825           }
826         }
827       }
828
829       mSubStateName = subStateName;
830     }
831   }
832
833   // Data
834
835   Control& mControlImpl;
836   DevelControl::State mState;
837   std::string mSubStateName;
838
839   RegisteredVisualContainer mVisuals; // Stores visuals needed by the control, non trivial type so std::vector used.
840   std::string mStyleName;
841   Vector4 mBackgroundColor;                       ///< The color of the background visual
842   Vector3* mStartingPinchScale;      ///< The scale when a pinch gesture starts, TODO: consider removing this
843   Toolkit::Control::KeyEventSignalType mKeyEventSignal;
844   Toolkit::Control::KeyInputFocusSignalType mKeyInputFocusGainedSignal;
845   Toolkit::Control::KeyInputFocusSignalType mKeyInputFocusLostSignal;
846
847   // Gesture Detection
848   PinchGestureDetector mPinchGestureDetector;
849   PanGestureDetector mPanGestureDetector;
850   TapGestureDetector mTapGestureDetector;
851   LongPressGestureDetector mLongPressGestureDetector;
852
853   // Tooltip
854   TooltipPtr mTooltip;
855
856   ControlBehaviour mFlags : CONTROL_BEHAVIOUR_FLAG_COUNT;    ///< Flags passed in from constructor.
857   bool mIsKeyboardNavigationSupported :1;  ///< Stores whether keyboard navigation is supported by the control.
858   bool mIsKeyboardFocusGroup :1;           ///< Stores whether the control is a focus group.
859
860   // Properties - these need to be members of Internal::Control::Impl as they access private methods/data of Internal::Control and Internal::Control::Impl.
861   static const PropertyRegistration PROPERTY_1;
862   static const PropertyRegistration PROPERTY_2;
863   static const PropertyRegistration PROPERTY_3;
864   static const PropertyRegistration PROPERTY_4;
865   static const PropertyRegistration PROPERTY_5;
866   static const PropertyRegistration PROPERTY_6;
867   static const PropertyRegistration PROPERTY_7;
868   static const PropertyRegistration PROPERTY_8;
869 };
870
871 // Properties registered without macro to use specific member variables.
872 const PropertyRegistration Control::Impl::PROPERTY_1( typeRegistration, "styleName",       Toolkit::Control::Property::STYLE_NAME,       Property::STRING,  &Control::Impl::SetProperty, &Control::Impl::GetProperty );
873 const PropertyRegistration Control::Impl::PROPERTY_2( typeRegistration, "backgroundColor", Toolkit::Control::Property::BACKGROUND_COLOR, Property::VECTOR4, &Control::Impl::SetProperty, &Control::Impl::GetProperty );
874 const PropertyRegistration Control::Impl::PROPERTY_3( typeRegistration, "backgroundImage", Toolkit::Control::Property::BACKGROUND_IMAGE, Property::MAP,     &Control::Impl::SetProperty, &Control::Impl::GetProperty );
875 const PropertyRegistration Control::Impl::PROPERTY_4( typeRegistration, "keyInputFocus",   Toolkit::Control::Property::KEY_INPUT_FOCUS,  Property::BOOLEAN, &Control::Impl::SetProperty, &Control::Impl::GetProperty );
876 const PropertyRegistration Control::Impl::PROPERTY_5( typeRegistration, "background",      Toolkit::Control::Property::BACKGROUND,       Property::MAP,     &Control::Impl::SetProperty, &Control::Impl::GetProperty );
877 const PropertyRegistration Control::Impl::PROPERTY_6( typeRegistration, "tooltip",         Toolkit::DevelControl::Property::TOOLTIP,     Property::MAP,     &Control::Impl::SetProperty, &Control::Impl::GetProperty );
878 const PropertyRegistration Control::Impl::PROPERTY_7( typeRegistration, "state",           Toolkit::DevelControl::Property::STATE,       Property::STRING,  &Control::Impl::SetProperty, &Control::Impl::GetProperty );
879 const PropertyRegistration Control::Impl::PROPERTY_8( typeRegistration, "subState",        Toolkit::DevelControl::Property::SUB_STATE,   Property::STRING,  &Control::Impl::SetProperty, &Control::Impl::GetProperty );
880
881 Toolkit::Control Control::New()
882 {
883   // Create the implementation, temporarily owned on stack
884   IntrusivePtr<Control> controlImpl = new Control( ControlBehaviour( CONTROL_BEHAVIOUR_DEFAULT ) );
885
886   // Pass ownership to handle
887   Toolkit::Control handle( *controlImpl );
888
889   // Second-phase init of the implementation
890   // This can only be done after the CustomActor connection has been made...
891   controlImpl->Initialize();
892
893   return handle;
894 }
895
896 void Control::SetStyleName( const std::string& styleName )
897 {
898   if( styleName != mImpl->mStyleName )
899   {
900     mImpl->mStyleName = styleName;
901
902     // Apply new style, if stylemanager is available
903     Toolkit::StyleManager styleManager = Toolkit::StyleManager::Get();
904     if( styleManager )
905     {
906       GetImpl( styleManager ).ApplyThemeStyle( Toolkit::Control( GetOwner() ) );
907     }
908   }
909 }
910
911 const std::string& Control::GetStyleName() const
912 {
913   return mImpl->mStyleName;
914 }
915
916 void Control::SetBackgroundColor( const Vector4& color )
917 {
918   mImpl->mBackgroundColor = color;
919   Property::Map map;
920   map[ Toolkit::DevelVisual::Property::TYPE ] = Toolkit::Visual::COLOR;
921   map[ Toolkit::ColorVisual::Property::MIX_COLOR ] = color;
922
923   SetBackground( map );
924 }
925
926 Vector4 Control::GetBackgroundColor() const
927 {
928   return mImpl->mBackgroundColor;
929 }
930
931 void Control::SetBackground( const Property::Map& map )
932 {
933   Toolkit::Visual::Base visual = Toolkit::VisualFactory::Get().CreateVisual( map );
934   if( visual )
935   {
936     RegisterVisual( Toolkit::Control::Property::BACKGROUND, visual );
937     visual.SetDepthIndex( DepthIndex::BACKGROUND );
938
939     // Trigger a size negotiation request that may be needed by the new visual to relayout its contents.
940     RelayoutRequest();
941   }
942 }
943
944 void Control::SetBackgroundImage( Image image )
945 {
946   Toolkit::Visual::Base visual = Toolkit::VisualFactory::Get().CreateVisual( image );
947   if( visual )
948   {
949     RegisterVisual( Toolkit::Control::Property::BACKGROUND, visual );
950     visual.SetDepthIndex( DepthIndex::BACKGROUND );
951   }
952 }
953
954 void Control::ClearBackground()
955 {
956    UnregisterVisual( Toolkit::Control::Property::BACKGROUND );
957    mImpl->mBackgroundColor = Color::TRANSPARENT;
958
959    // Trigger a size negotiation request that may be needed when unregistering a visual.
960    RelayoutRequest();
961 }
962
963 void Control::EnableGestureDetection(Gesture::Type type)
964 {
965   if ( (type & Gesture::Pinch) && !mImpl->mPinchGestureDetector )
966   {
967     mImpl->mPinchGestureDetector = PinchGestureDetector::New();
968     mImpl->mPinchGestureDetector.DetectedSignal().Connect(mImpl, &Impl::PinchDetected);
969     mImpl->mPinchGestureDetector.Attach(Self());
970   }
971
972   if ( (type & Gesture::Pan) && !mImpl->mPanGestureDetector )
973   {
974     mImpl->mPanGestureDetector = PanGestureDetector::New();
975     mImpl->mPanGestureDetector.DetectedSignal().Connect(mImpl, &Impl::PanDetected);
976     mImpl->mPanGestureDetector.Attach(Self());
977   }
978
979   if ( (type & Gesture::Tap) && !mImpl->mTapGestureDetector )
980   {
981     mImpl->mTapGestureDetector = TapGestureDetector::New();
982     mImpl->mTapGestureDetector.DetectedSignal().Connect(mImpl, &Impl::TapDetected);
983     mImpl->mTapGestureDetector.Attach(Self());
984   }
985
986   if ( (type & Gesture::LongPress) && !mImpl->mLongPressGestureDetector )
987   {
988     mImpl->mLongPressGestureDetector = LongPressGestureDetector::New();
989     mImpl->mLongPressGestureDetector.DetectedSignal().Connect(mImpl, &Impl::LongPressDetected);
990     mImpl->mLongPressGestureDetector.Attach(Self());
991   }
992 }
993
994 void Control::DisableGestureDetection(Gesture::Type type)
995 {
996   if ( (type & Gesture::Pinch) && mImpl->mPinchGestureDetector )
997   {
998     mImpl->mPinchGestureDetector.Detach(Self());
999     mImpl->mPinchGestureDetector.Reset();
1000   }
1001
1002   if ( (type & Gesture::Pan) && mImpl->mPanGestureDetector )
1003   {
1004     mImpl->mPanGestureDetector.Detach(Self());
1005     mImpl->mPanGestureDetector.Reset();
1006   }
1007
1008   if ( (type & Gesture::Tap) && mImpl->mTapGestureDetector )
1009   {
1010     mImpl->mTapGestureDetector.Detach(Self());
1011     mImpl->mTapGestureDetector.Reset();
1012   }
1013
1014   if ( (type & Gesture::LongPress) && mImpl->mLongPressGestureDetector)
1015   {
1016     mImpl->mLongPressGestureDetector.Detach(Self());
1017     mImpl->mLongPressGestureDetector.Reset();
1018   }
1019 }
1020
1021 PinchGestureDetector Control::GetPinchGestureDetector() const
1022 {
1023   return mImpl->mPinchGestureDetector;
1024 }
1025
1026 PanGestureDetector Control::GetPanGestureDetector() const
1027 {
1028   return mImpl->mPanGestureDetector;
1029 }
1030
1031 TapGestureDetector Control::GetTapGestureDetector() const
1032 {
1033   return mImpl->mTapGestureDetector;
1034 }
1035
1036 LongPressGestureDetector Control::GetLongPressGestureDetector() const
1037 {
1038   return mImpl->mLongPressGestureDetector;
1039 }
1040
1041 void Control::SetKeyboardNavigationSupport(bool isSupported)
1042 {
1043   mImpl->mIsKeyboardNavigationSupported = isSupported;
1044 }
1045
1046 bool Control::IsKeyboardNavigationSupported()
1047 {
1048   return mImpl->mIsKeyboardNavigationSupported;
1049 }
1050
1051 void Control::SetKeyInputFocus()
1052 {
1053   if( Self().OnStage() )
1054   {
1055     Toolkit::KeyInputFocusManager::Get().SetFocus(Toolkit::Control::DownCast(Self()));
1056   }
1057 }
1058
1059 bool Control::HasKeyInputFocus()
1060 {
1061   bool result = false;
1062   if( Self().OnStage() )
1063   {
1064     result = Toolkit::KeyInputFocusManager::Get().IsKeyboardListener(Toolkit::Control::DownCast(Self()));
1065   }
1066   return result;
1067 }
1068
1069 void Control::ClearKeyInputFocus()
1070 {
1071   if( Self().OnStage() )
1072   {
1073     Toolkit::KeyInputFocusManager::Get().RemoveFocus(Toolkit::Control::DownCast(Self()));
1074   }
1075 }
1076
1077 void Control::SetAsKeyboardFocusGroup(bool isFocusGroup)
1078 {
1079   mImpl->mIsKeyboardFocusGroup = isFocusGroup;
1080
1081   // The following line will be removed when the deprecated API in KeyboardFocusManager is deleted
1082   Toolkit::KeyboardFocusManager::Get().SetAsFocusGroup(Self(), isFocusGroup);
1083 }
1084
1085 bool Control::IsKeyboardFocusGroup()
1086 {
1087   return Toolkit::KeyboardFocusManager::Get().IsFocusGroup(Self());
1088 }
1089
1090 void Control::AccessibilityActivate()
1091 {
1092   // Inform deriving classes
1093   OnAccessibilityActivated();
1094 }
1095
1096 void Control::KeyboardEnter()
1097 {
1098   // Inform deriving classes
1099   OnKeyboardEnter();
1100 }
1101
1102 void Control::RegisterVisual( Property::Index index, Toolkit::Visual::Base& visual )
1103 {
1104   RegisterVisual( index, visual, true );
1105 }
1106
1107 void Control::RegisterVisual( Property::Index index, Toolkit::Visual::Base& visual, bool enabled )
1108 {
1109   bool visualReplaced ( false );
1110   Actor self = Self();
1111
1112   if( !mImpl->mVisuals.Empty() )
1113   {
1114     RegisteredVisualContainer::Iterator iter;
1115     // Check if visual (index) is already registered.  Replace if so.
1116     if ( FindVisual( index, mImpl->mVisuals, iter ) )
1117     {
1118       if( (*iter)->visual && self.OnStage() )
1119       {
1120         Toolkit::GetImplementation((*iter)->visual).SetOffStage( self );
1121       }
1122       (*iter)->visual = visual;
1123       visualReplaced = true;
1124     }
1125   }
1126
1127   // If not set, set the name of the visual to the same name as the control's property.
1128   // ( If the control has been type registered )
1129   if( visual.GetName().empty() )
1130   {
1131     // Check if the control has been type registered:
1132     TypeInfo typeInfo = TypeRegistry::Get().GetTypeInfo( typeid(*this) );
1133     if( typeInfo )
1134     {
1135       // Check if the property index has been registered:
1136       Property::IndexContainer indices;
1137       typeInfo.GetPropertyIndices( indices );
1138       Property::IndexContainer::Iterator iter = std::find( indices.Begin(), indices.End(), index );
1139       if( iter != indices.End() )
1140       {
1141         // If it has, then get it's name and use that for the visual
1142         std::string visualName = typeInfo.GetPropertyName( index );
1143         visual.SetName( visualName );
1144       }
1145     }
1146   }
1147
1148   if( !visualReplaced ) // New registration entry
1149   {
1150     mImpl->mVisuals.PushBack( new RegisteredVisual( index, visual, enabled ) );
1151   }
1152
1153   if( visual && self.OnStage() && enabled )
1154   {
1155     Toolkit::GetImplementation(visual).SetOnStage( self );
1156   }
1157
1158   DALI_LOG_INFO( gLogFilter, Debug::Verbose, "Control::RegisterVisual() Registered %s(%d), enabled:%s\n",  visual.GetName().c_str(), index, enabled?"T":"F" );
1159 }
1160
1161 void Control::UnregisterVisual( Property::Index index )
1162 {
1163    RegisteredVisualContainer::Iterator iter;
1164    if ( FindVisual( index, mImpl->mVisuals, iter ) )
1165    {
1166      Actor self( Self() );
1167      Toolkit::GetImplementation((*iter)->visual).SetOffStage( self );
1168      (*iter)->visual.Reset();
1169      mImpl->mVisuals.Erase( iter );
1170    }
1171 }
1172
1173 Toolkit::Visual::Base Control::GetVisual( Property::Index index ) const
1174 {
1175   RegisteredVisualContainer::Iterator iter;
1176   if ( FindVisual( index, mImpl->mVisuals, iter ) )
1177   {
1178     return (*iter)->visual;
1179   }
1180
1181   return Toolkit::Visual::Base();
1182 }
1183
1184 void Control::EnableVisual( Property::Index index, bool enable )
1185 {
1186   RegisteredVisualContainer::Iterator iter;
1187   if ( FindVisual( index, mImpl->mVisuals, iter ) )
1188   {
1189     if (  (*iter)->enabled == enable )
1190     {
1191       DALI_LOG_INFO( gLogFilter, Debug::Verbose, "Control::EnableVisual Visual %s(%d) already %s\n", (*iter)->visual.GetName().c_str(), index, enable?"enabled":"disabled");
1192       return;
1193     }
1194
1195     (*iter)->enabled = enable;
1196     Actor parentActor = Self();
1197     if ( Self().OnStage() ) // If control not on Stage then Visual will be added when StageConnection is called.
1198     {
1199       if ( enable )
1200       {
1201         DALI_LOG_INFO( gLogFilter, Debug::Verbose, "Control::EnableVisual Setting %s(%d) on stage \n", (*iter)->visual.GetName().c_str(), index );
1202         Toolkit::GetImplementation((*iter)->visual).SetOnStage( parentActor );
1203       }
1204       else
1205       {
1206         DALI_LOG_INFO( gLogFilter, Debug::Verbose, "Control::EnableVisual Setting %s(%d) off stage \n", (*iter)->visual.GetName().c_str(), index );
1207         Toolkit::GetImplementation((*iter)->visual).SetOffStage( parentActor );  // No need to call if control not staged.
1208       }
1209     }
1210   }
1211 }
1212
1213 bool Control::IsVisualEnabled( Property::Index index ) const
1214 {
1215   RegisteredVisualContainer::Iterator iter;
1216   if ( FindVisual( index, mImpl->mVisuals, iter ) )
1217   {
1218     return (*iter)->enabled;
1219   }
1220   return false;
1221 }
1222
1223 Dali::Animation Control::CreateTransition( const Toolkit::TransitionData& handle )
1224 {
1225   Dali::Animation transition;
1226   const Internal::TransitionData& transitionData = Toolkit::GetImplementation( handle );
1227
1228   if( transitionData.Count() > 0 )
1229   {
1230     // Setup a Transition from TransitionData.
1231     TransitionData::Iterator end = transitionData.End();
1232     for( TransitionData::Iterator iter = transitionData.Begin() ;
1233          iter != end; ++iter )
1234     {
1235       TransitionData::Animator* animator = (*iter);
1236
1237       Toolkit::Visual::Base visual = GetVisualByName( mImpl->mVisuals, animator->objectName );
1238
1239       if( visual )
1240       {
1241         Internal::Visual::Base& visualImpl = Toolkit::GetImplementation( visual );
1242         visualImpl.AnimateProperty( transition, *animator );
1243       }
1244       else
1245       {
1246         // Otherwise, try any actor children of control (Including the control)
1247         Actor child = Self().FindChildByName( animator->objectName );
1248         if( child )
1249         {
1250           Property::Index propertyIndex = DevelHandle::GetPropertyIndex( child, animator->propertyKey );
1251           if( propertyIndex != Property::INVALID_INDEX )
1252           {
1253             if( animator->animate == false )
1254             {
1255               if( animator->targetValue.GetType() != Property::NONE )
1256               {
1257                 child.SetProperty( propertyIndex, animator->targetValue );
1258               }
1259             }
1260             else // animate the property
1261             {
1262               if( animator->initialValue.GetType() != Property::NONE )
1263               {
1264                 child.SetProperty( propertyIndex, animator->initialValue );
1265               }
1266
1267               if( ! transition )
1268               {
1269                 transition = Dali::Animation::New( 0.1f );
1270               }
1271
1272               transition.AnimateTo( Property( child, propertyIndex ),
1273                                     animator->targetValue,
1274                                     animator->alphaFunction,
1275                                     TimePeriod( animator->timePeriodDelay,
1276                                                 animator->timePeriodDuration ) );
1277             }
1278           }
1279         }
1280       }
1281     }
1282   }
1283
1284   return transition;
1285 }
1286
1287 bool Control::OnAccessibilityActivated()
1288 {
1289   return false; // Accessibility activation is not handled by default
1290 }
1291
1292 bool Control::OnKeyboardEnter()
1293 {
1294   return false; // Keyboard enter is not handled by default
1295 }
1296
1297 bool Control::OnAccessibilityPan(PanGesture gesture)
1298 {
1299   return false; // Accessibility pan gesture is not handled by default
1300 }
1301
1302 bool Control::OnAccessibilityTouch(const TouchEvent& touchEvent)
1303 {
1304   return false; // Accessibility touch event is not handled by default
1305 }
1306
1307 bool Control::OnAccessibilityValueChange(bool isIncrease)
1308 {
1309   return false; // Accessibility value change action is not handled by default
1310 }
1311
1312 bool Control::OnAccessibilityZoom()
1313 {
1314   return false; // Accessibility zoom action is not handled by default
1315 }
1316
1317 Actor Control::GetNextKeyboardFocusableActor(Actor currentFocusedActor, Toolkit::Control::KeyboardFocus::Direction direction, bool loopEnabled)
1318 {
1319   return Actor();
1320 }
1321
1322 void Control::OnKeyboardFocusChangeCommitted(Actor commitedFocusableActor)
1323 {
1324 }
1325
1326 Toolkit::Control::KeyEventSignalType& Control::KeyEventSignal()
1327 {
1328   return mImpl->mKeyEventSignal;
1329 }
1330
1331 Toolkit::Control::KeyInputFocusSignalType& Control::KeyInputFocusGainedSignal()
1332 {
1333   return mImpl->mKeyInputFocusGainedSignal;
1334 }
1335
1336 Toolkit::Control::KeyInputFocusSignalType& Control::KeyInputFocusLostSignal()
1337 {
1338   return mImpl->mKeyInputFocusLostSignal;
1339 }
1340
1341 bool Control::EmitKeyEventSignal( const KeyEvent& event )
1342 {
1343   // Guard against destruction during signal emission
1344   Dali::Toolkit::Control handle( GetOwner() );
1345
1346   bool consumed = false;
1347
1348   // signals are allocated dynamically when someone connects
1349   if ( !mImpl->mKeyEventSignal.Empty() )
1350   {
1351     consumed = mImpl->mKeyEventSignal.Emit( handle, event );
1352   }
1353
1354   if (!consumed)
1355   {
1356     // Notification for derived classes
1357     consumed = OnKeyEvent(event);
1358   }
1359
1360   return consumed;
1361 }
1362
1363 Control::Control( ControlBehaviour behaviourFlags )
1364 : CustomActorImpl( static_cast< ActorFlags >( behaviourFlags ) ),
1365   mImpl(new Impl(*this))
1366 {
1367   mImpl->mFlags = behaviourFlags;
1368 }
1369
1370 Control::~Control()
1371 {
1372   delete mImpl;
1373 }
1374
1375 void Control::Initialize()
1376 {
1377   // Call deriving classes so initialised before styling is applied to them.
1378   OnInitialize();
1379
1380   if( (mImpl->mFlags & REQUIRES_STYLE_CHANGE_SIGNALS) ||
1381       !(mImpl->mFlags & DISABLE_STYLE_CHANGE_SIGNALS) )
1382   {
1383     Toolkit::StyleManager styleManager = StyleManager::Get();
1384
1385     // if stylemanager is available
1386     if( styleManager )
1387     {
1388       StyleManager& styleManagerImpl = GetImpl( styleManager );
1389
1390       // Register for style changes
1391       styleManagerImpl.ControlStyleChangeSignal().Connect( this, &Control::OnStyleChange );
1392
1393       // Apply the current style
1394       styleManagerImpl.ApplyThemeStyleAtInit( Toolkit::Control( GetOwner() ) );
1395     }
1396   }
1397
1398   if( mImpl->mFlags & REQUIRES_KEYBOARD_NAVIGATION_SUPPORT )
1399   {
1400     SetKeyboardNavigationSupport( true );
1401   }
1402 }
1403
1404 void Control::OnInitialize()
1405 {
1406 }
1407
1408 void Control::OnControlChildAdd( Actor& child )
1409 {
1410 }
1411
1412 void Control::OnControlChildRemove( Actor& child )
1413 {
1414 }
1415
1416 void Control::OnStyleChange( Toolkit::StyleManager styleManager, StyleChange::Type change )
1417 {
1418   // By default the control is only interested in theme (not font) changes
1419   if( styleManager && change == StyleChange::THEME_CHANGE )
1420   {
1421     GetImpl( styleManager ).ApplyThemeStyle( Toolkit::Control( GetOwner() ) );
1422   }
1423   RelayoutRequest();
1424 }
1425
1426 void Control::OnPinch(const PinchGesture& pinch)
1427 {
1428   if( !( mImpl->mStartingPinchScale ) )
1429   {
1430     // lazy allocate
1431     mImpl->mStartingPinchScale = new Vector3;
1432   }
1433
1434   if( pinch.state == Gesture::Started )
1435   {
1436     *( mImpl->mStartingPinchScale ) = Self().GetCurrentScale();
1437   }
1438
1439   Self().SetScale( *( mImpl->mStartingPinchScale ) * pinch.scale );
1440 }
1441
1442 void Control::OnPan( const PanGesture& pan )
1443 {
1444 }
1445
1446 void Control::OnTap(const TapGesture& tap)
1447 {
1448 }
1449
1450 void Control::OnLongPress( const LongPressGesture& longPress )
1451 {
1452 }
1453
1454 void Control::EmitKeyInputFocusSignal( bool focusGained )
1455 {
1456   Dali::Toolkit::Control handle( GetOwner() );
1457
1458   if ( focusGained )
1459   {
1460     // signals are allocated dynamically when someone connects
1461     if ( !mImpl->mKeyInputFocusGainedSignal.Empty() )
1462     {
1463       mImpl->mKeyInputFocusGainedSignal.Emit( handle );
1464     }
1465   }
1466   else
1467   {
1468     // signals are allocated dynamically when someone connects
1469     if ( !mImpl->mKeyInputFocusLostSignal.Empty() )
1470     {
1471       mImpl->mKeyInputFocusLostSignal.Emit( handle );
1472     }
1473   }
1474 }
1475
1476 void Control::OnStageConnection( int depth )
1477 {
1478   DALI_LOG_INFO( gLogFilter, Debug::Verbose, "Control::OnStageConnection number of registered visuals(%d)\n",  mImpl->mVisuals.Size() );
1479
1480   Actor self( Self() );
1481
1482   for(RegisteredVisualContainer::Iterator iter = mImpl->mVisuals.Begin(); iter!= mImpl->mVisuals.End(); iter++)
1483   {
1484     // Check whether the visual is empty and enabled
1485     if( (*iter)->visual && (*iter)->enabled )
1486     {
1487       DALI_LOG_INFO( gLogFilter, Debug::Verbose, "Control::OnStageConnection Setting visual(%d) on stage\n", (*iter)->index );
1488       Toolkit::GetImplementation((*iter)->visual).SetOnStage( self );
1489     }
1490   }
1491
1492   if( mImpl->mVisuals.Empty() && ! self.GetRendererCount() )
1493   {
1494     Property::Value clippingValue = self.GetProperty( Actor::Property::CLIPPING_MODE );
1495     int clippingMode = ClippingMode::DISABLED;
1496     if( clippingValue.Get( clippingMode ) )
1497     {
1498       // Add a transparent background if we do not have any renderers or visuals so we clip our children
1499
1500       if( clippingMode == ClippingMode::CLIP_CHILDREN )
1501       {
1502         // Create a transparent background visual which will also get staged.
1503         SetBackgroundColor( Color::TRANSPARENT );
1504       }
1505     }
1506   }
1507 }
1508
1509 void Control::OnStageDisconnection()
1510 {
1511   for(RegisteredVisualContainer::Iterator iter = mImpl->mVisuals.Begin(); iter!= mImpl->mVisuals.End(); iter++)
1512   {
1513     // Check whether the visual is empty
1514     if( (*iter)->visual )
1515     {
1516       DALI_LOG_INFO( gLogFilter, Debug::Verbose, "Control::OnStageDisconnection Setting visual(%d) off stage\n", (*iter)->index );
1517       Actor self( Self() );
1518       Toolkit::GetImplementation((*iter)->visual).SetOffStage( self );
1519     }
1520   }
1521 }
1522
1523 void Control::OnKeyInputFocusGained()
1524 {
1525   EmitKeyInputFocusSignal( true );
1526 }
1527
1528 void Control::OnKeyInputFocusLost()
1529 {
1530   EmitKeyInputFocusSignal( false );
1531 }
1532
1533 void Control::OnChildAdd(Actor& child)
1534 {
1535   // Notify derived classes.
1536   OnControlChildAdd( child );
1537 }
1538
1539 void Control::OnChildRemove(Actor& child)
1540 {
1541   // Notify derived classes.
1542   OnControlChildRemove( child );
1543 }
1544
1545 void Control::OnPropertySet( Property::Index index, Property::Value propertyValue )
1546 {
1547   Actor self( Self() );
1548   if( index == Actor::Property::CLIPPING_MODE )
1549   {
1550     // Only set the background if we're already on the stage and have no renderers or visuals
1551
1552     if( mImpl->mVisuals.Empty() && ! self.GetRendererCount() && self.OnStage() )
1553     {
1554       ClippingMode::Type clippingMode = ClippingMode::DISABLED;
1555       if( Scripting::GetEnumerationProperty< ClippingMode::Type >( propertyValue, CLIPPING_MODE_TABLE, CLIPPING_MODE_TABLE_COUNT, clippingMode ) )
1556       {
1557         // Add a transparent background if we do not have one so we clip children
1558
1559         if( clippingMode == ClippingMode::CLIP_CHILDREN )
1560         {
1561           SetBackgroundColor( Color::TRANSPARENT );
1562         }
1563       }
1564     }
1565   }
1566 }
1567
1568 void Control::OnSizeSet(const Vector3& targetSize)
1569 {
1570   Toolkit::Visual::Base visual = GetVisual( Toolkit::Control::Property::BACKGROUND );
1571   if( visual )
1572   {
1573     Vector2 size( targetSize );
1574     visual.SetTransformAndSize( Property::Map(), size ); // Send an empty map as we do not want to modify the visual's set transform
1575   }
1576 }
1577
1578 void Control::OnSizeAnimation(Animation& animation, const Vector3& targetSize)
1579 {
1580   // @todo size negotiate background to new size, animate as well?
1581 }
1582
1583 bool Control::OnTouchEvent(const TouchEvent& event)
1584 {
1585   return false; // Do not consume
1586 }
1587
1588 bool Control::OnHoverEvent(const HoverEvent& event)
1589 {
1590   return false; // Do not consume
1591 }
1592
1593 bool Control::OnKeyEvent(const KeyEvent& event)
1594 {
1595   return false; // Do not consume
1596 }
1597
1598 bool Control::OnWheelEvent(const WheelEvent& event)
1599 {
1600   return false; // Do not consume
1601 }
1602
1603 void Control::OnRelayout( const Vector2& size, RelayoutContainer& container )
1604 {
1605   for( unsigned int i = 0, numChildren = Self().GetChildCount(); i < numChildren; ++i )
1606   {
1607     container.Add( Self().GetChildAt( i ), size );
1608   }
1609
1610   Toolkit::Visual::Base visual = GetVisual( Toolkit::Control::Property::BACKGROUND );
1611   if( visual )
1612   {
1613     visual.SetTransformAndSize( Property::Map(), size ); // Send an empty map as we do not want to modify the visual's set transform
1614   }
1615 }
1616
1617 void Control::OnSetResizePolicy( ResizePolicy::Type policy, Dimension::Type dimension )
1618 {
1619 }
1620
1621 Vector3 Control::GetNaturalSize()
1622 {
1623   Toolkit::Visual::Base visual = GetVisual( Toolkit::Control::Property::BACKGROUND );
1624   if( visual )
1625   {
1626     Vector2 naturalSize;
1627     visual.GetNaturalSize( naturalSize );
1628     return Vector3( naturalSize );
1629   }
1630   return Vector3::ZERO;
1631 }
1632
1633 float Control::CalculateChildSize( const Dali::Actor& child, Dimension::Type dimension )
1634 {
1635   return CalculateChildSizeBase( child, dimension );
1636 }
1637
1638 float Control::GetHeightForWidth( float width )
1639 {
1640   return GetHeightForWidthBase( width );
1641 }
1642
1643 float Control::GetWidthForHeight( float height )
1644 {
1645   return GetWidthForHeightBase( height );
1646 }
1647
1648 bool Control::RelayoutDependentOnChildren( Dimension::Type dimension )
1649 {
1650   return RelayoutDependentOnChildrenBase( dimension );
1651 }
1652
1653 void Control::OnCalculateRelayoutSize( Dimension::Type dimension )
1654 {
1655 }
1656
1657 void Control::OnLayoutNegotiated( float size, Dimension::Type dimension )
1658 {
1659 }
1660
1661 void Control::SignalConnected( SlotObserver* slotObserver, CallbackBase* callback )
1662 {
1663   mImpl->SignalConnected( slotObserver, callback );
1664 }
1665
1666 void Control::SignalDisconnected( SlotObserver* slotObserver, CallbackBase* callback )
1667 {
1668   mImpl->SignalDisconnected( slotObserver, callback );
1669 }
1670
1671 Control& GetImplementation( Dali::Toolkit::Control& handle )
1672 {
1673   CustomActorImpl& customInterface = handle.GetImplementation();
1674   // downcast to control
1675   Control& impl = dynamic_cast< Internal::Control& >( customInterface );
1676   return impl;
1677 }
1678
1679 const Control& GetImplementation( const Dali::Toolkit::Control& handle )
1680 {
1681   const CustomActorImpl& customInterface = handle.GetImplementation();
1682   // downcast to control
1683   const Control& impl = dynamic_cast< const Internal::Control& >( customInterface );
1684   return impl;
1685 }
1686
1687 } // namespace Internal
1688
1689 } // namespace Toolkit
1690
1691 } // namespace Dali