[Tizen] Add AutofillContainer class and autofill implementation
[platform/core/uifw/dali-toolkit.git] / dali-toolkit / internal / controls / control / control-data-impl.cpp
1 /*
2  * Copyright (c) 2019 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 "control-data-impl.h"
20
21 // EXTERNAL INCLUDES
22 #include <dali-toolkit/public-api/dali-toolkit-common.h>
23 #include <dali/integration-api/debug.h>
24 #include <dali/devel-api/object/handle-devel.h>
25 #include <dali/devel-api/scripting/enum-helper.h>
26 #include <dali/devel-api/scripting/scripting.h>
27 #include <dali/integration-api/debug.h>
28 #include <dali/public-api/object/type-registry-helper.h>
29 #include <cstring>
30 #include <limits>
31
32 // INTERNAL INCLUDES
33 #include <dali-toolkit/internal/visuals/visual-base-impl.h>
34 #include <dali-toolkit/public-api/visuals/image-visual-properties.h>
35 #include <dali-toolkit/public-api/visuals/visual-properties.h>
36 #include <dali-toolkit/devel-api/controls/control-depth-index-ranges.h>
37 #include <dali-toolkit/devel-api/controls/control-devel.h>
38 #include <dali-toolkit/devel-api/controls/control-wrapper-impl.h>
39 #include <dali-toolkit/internal/styling/style-manager-impl.h>
40 #include <dali-toolkit/internal/visuals/visual-string-constants.h>
41
42 namespace Dali
43 {
44
45 namespace Toolkit
46 {
47
48 namespace Internal
49 {
50
51 extern const Dali::Scripting::StringEnum ControlStateTable[];
52 extern const unsigned int ControlStateTableCount;
53
54
55 // Not static or anonymous - shared with other translation units
56 const Scripting::StringEnum ControlStateTable[] = {
57   { "NORMAL",   Toolkit::DevelControl::NORMAL   },
58   { "FOCUSED",  Toolkit::DevelControl::FOCUSED  },
59   { "DISABLED", Toolkit::DevelControl::DISABLED },
60 };
61 const unsigned int ControlStateTableCount = sizeof( ControlStateTable ) / sizeof( ControlStateTable[0] );
62
63
64
65 namespace
66 {
67
68 #if defined(DEBUG_ENABLED)
69 Debug::Filter* gLogFilter = Debug::Filter::New( Debug::NoLogging, false, "LOG_CONTROL_VISUALS");
70 #endif
71
72
73 template<typename T>
74 void Remove( Dictionary<T>& keyValues, const std::string& name )
75 {
76   keyValues.Remove(name);
77 }
78
79 void Remove( DictionaryKeys& keys, const std::string& name )
80 {
81   DictionaryKeys::iterator iter = std::find( keys.begin(), keys.end(), name );
82   if( iter != keys.end())
83   {
84     keys.erase(iter);
85   }
86 }
87
88 Toolkit::Visual::Type GetVisualTypeFromMap( const Property::Map& map )
89 {
90   Property::Value* typeValue = map.Find( Toolkit::Visual::Property::TYPE, VISUAL_TYPE  );
91   Toolkit::Visual::Type type = Toolkit::Visual::IMAGE;
92   if( typeValue )
93   {
94     Scripting::GetEnumerationProperty( *typeValue, VISUAL_TYPE_TABLE, VISUAL_TYPE_TABLE_COUNT, type );
95   }
96   return type;
97 }
98
99 /**
100  *  Finds visual in given array, returning true if found along with the iterator for that visual as a out parameter
101  */
102 bool FindVisual( Property::Index targetIndex, const RegisteredVisualContainer& visuals, RegisteredVisualContainer::Iterator& iter )
103 {
104   for ( iter = visuals.Begin(); iter != visuals.End(); iter++ )
105   {
106     if ( (*iter)->index ==  targetIndex )
107     {
108       return true;
109     }
110   }
111   return false;
112 }
113
114 void FindChangableVisuals( Dictionary<Property::Map>& stateVisualsToAdd,
115                            Dictionary<Property::Map>& stateVisualsToChange,
116                            DictionaryKeys& stateVisualsToRemove)
117 {
118   DictionaryKeys copyOfStateVisualsToRemove = stateVisualsToRemove;
119
120   for( DictionaryKeys::iterator iter = copyOfStateVisualsToRemove.begin();
121        iter != copyOfStateVisualsToRemove.end(); ++iter )
122   {
123     const std::string& visualName = (*iter);
124     Property::Map* toMap = stateVisualsToAdd.Find( visualName );
125     if( toMap )
126     {
127       stateVisualsToChange.Add( visualName, *toMap );
128       stateVisualsToAdd.Remove( visualName );
129       Remove( stateVisualsToRemove, visualName );
130     }
131   }
132 }
133
134 Toolkit::Visual::Base GetVisualByName(
135   const RegisteredVisualContainer& visuals,
136   const std::string& visualName )
137 {
138   Toolkit::Visual::Base visualHandle;
139
140   RegisteredVisualContainer::Iterator iter;
141   for ( iter = visuals.Begin(); iter != visuals.End(); iter++ )
142   {
143     Toolkit::Visual::Base visual = (*iter)->visual;
144     if( visual && visual.GetName() == visualName )
145     {
146       visualHandle = visual;
147       break;
148     }
149   }
150   return visualHandle;
151 }
152
153 /**
154  * Move visual from source to destination container
155  */
156 void MoveVisual( RegisteredVisualContainer::Iterator sourceIter, RegisteredVisualContainer& source, RegisteredVisualContainer& destination )
157 {
158    Toolkit::Visual::Base visual = (*sourceIter)->visual;
159    if( visual )
160    {
161      RegisteredVisual* rv = source.Release( sourceIter );
162      destination.PushBack( rv );
163    }
164 }
165
166 /**
167  * Performs actions as requested using the action name.
168  * @param[in] object The object on which to perform the action.
169  * @param[in] actionName The action to perform.
170  * @param[in] attributes The attributes with which to perfrom this action.
171  * @return true if action has been accepted by this control
172  */
173 const char* ACTION_ACCESSIBILITY_ACTIVATED = "accessibilityActivated";
174 static bool DoAction( BaseObject* object, const std::string& actionName, const Property::Map& attributes )
175 {
176   bool ret = false;
177
178   if( object && ( 0 == strcmp( actionName.c_str(), ACTION_ACCESSIBILITY_ACTIVATED ) ) )
179   {
180     Toolkit::Control control = Toolkit::Control::DownCast( BaseHandle( object ) );
181     if( control )
182     {
183       // if cast succeeds there is an implementation so no need to check
184       ret = Internal::GetImplementation( control ).OnAccessibilityActivated();
185     }
186   }
187
188   return ret;
189 }
190
191 /**
192  * Connects a callback function with the object's signals.
193  * @param[in] object The object providing the signal.
194  * @param[in] tracker Used to disconnect the signal.
195  * @param[in] signalName The signal to connect to.
196  * @param[in] functor A newly allocated FunctorDelegate.
197  * @return True if the signal was connected.
198  * @post If a signal was connected, ownership of functor was passed to CallbackBase. Otherwise the caller is responsible for deleting the unused functor.
199  */
200 const char* SIGNAL_KEY_EVENT = "keyEvent";
201 const char* SIGNAL_KEY_INPUT_FOCUS_GAINED = "keyInputFocusGained";
202 const char* SIGNAL_KEY_INPUT_FOCUS_LOST = "keyInputFocusLost";
203 const char* SIGNAL_TAPPED = "tapped";
204 const char* SIGNAL_PANNED = "panned";
205 const char* SIGNAL_PINCHED = "pinched";
206 const char* SIGNAL_LONG_PRESSED = "longPressed";
207 static bool DoConnectSignal( BaseObject* object, ConnectionTrackerInterface* tracker, const std::string& signalName, FunctorDelegate* functor )
208 {
209   Dali::BaseHandle handle( object );
210
211   bool connected( false );
212   Toolkit::Control control = Toolkit::Control::DownCast( handle );
213   if ( control )
214   {
215     Internal::Control& controlImpl( Internal::GetImplementation( control ) );
216     connected = true;
217
218     if ( 0 == strcmp( signalName.c_str(), SIGNAL_KEY_EVENT ) )
219     {
220       controlImpl.KeyEventSignal().Connect( tracker, functor );
221     }
222     else if( 0 == strcmp( signalName.c_str(), SIGNAL_KEY_INPUT_FOCUS_GAINED ) )
223     {
224       controlImpl.KeyInputFocusGainedSignal().Connect( tracker, functor );
225     }
226     else if( 0 == strcmp( signalName.c_str(), SIGNAL_KEY_INPUT_FOCUS_LOST ) )
227     {
228       controlImpl.KeyInputFocusLostSignal().Connect( tracker, functor );
229     }
230     else if( 0 == strcmp( signalName.c_str(), SIGNAL_TAPPED ) )
231     {
232       controlImpl.EnableGestureDetection( Gesture::Tap );
233       controlImpl.GetTapGestureDetector().DetectedSignal().Connect( tracker, functor );
234     }
235     else if( 0 == strcmp( signalName.c_str(), SIGNAL_PANNED ) )
236     {
237       controlImpl.EnableGestureDetection( Gesture::Pan );
238       controlImpl.GetPanGestureDetector().DetectedSignal().Connect( tracker, functor );
239     }
240     else if( 0 == strcmp( signalName.c_str(), SIGNAL_PINCHED ) )
241     {
242       controlImpl.EnableGestureDetection( Gesture::Pinch );
243       controlImpl.GetPinchGestureDetector().DetectedSignal().Connect( tracker, functor );
244     }
245     else if( 0 == strcmp( signalName.c_str(), SIGNAL_LONG_PRESSED ) )
246     {
247       controlImpl.EnableGestureDetection( Gesture::LongPress );
248       controlImpl.GetLongPressGestureDetector().DetectedSignal().Connect( tracker, functor );
249     }
250   }
251   return connected;
252 }
253
254 /**
255  * Creates control through type registry
256  */
257 BaseHandle Create()
258 {
259   return Internal::Control::New();
260 }
261 // Setup signals and actions using the type-registry.
262 DALI_TYPE_REGISTRATION_BEGIN( Control, CustomActor, Create );
263
264 // Note: Properties are registered separately below.
265
266 SignalConnectorType registerSignal1( typeRegistration, SIGNAL_KEY_EVENT, &DoConnectSignal );
267 SignalConnectorType registerSignal2( typeRegistration, SIGNAL_KEY_INPUT_FOCUS_GAINED, &DoConnectSignal );
268 SignalConnectorType registerSignal3( typeRegistration, SIGNAL_KEY_INPUT_FOCUS_LOST, &DoConnectSignal );
269 SignalConnectorType registerSignal4( typeRegistration, SIGNAL_TAPPED, &DoConnectSignal );
270 SignalConnectorType registerSignal5( typeRegistration, SIGNAL_PANNED, &DoConnectSignal );
271 SignalConnectorType registerSignal6( typeRegistration, SIGNAL_PINCHED, &DoConnectSignal );
272 SignalConnectorType registerSignal7( typeRegistration, SIGNAL_LONG_PRESSED, &DoConnectSignal );
273
274 TypeAction registerAction( typeRegistration, ACTION_ACCESSIBILITY_ACTIVATED, &DoAction );
275
276 DALI_TYPE_REGISTRATION_END()
277
278 /**
279  * @brief Iterate through given container and setOffStage any visual found
280  *
281  * @param[in] container Container of visuals
282  * @param[in] parent Parent actor to remove visuals from
283  */
284 void SetVisualsOffStage( const RegisteredVisualContainer& container, Actor parent )
285 {
286   for( auto iter = container.Begin(), end = container.End() ; iter!= end; iter++)
287   {
288     if( (*iter)->visual )
289     {
290       DALI_LOG_INFO( gLogFilter, Debug::Verbose, "Control::SetOffStage Setting visual(%d) off stage\n", (*iter)->index );
291       Toolkit::GetImplementation((*iter)->visual).SetOffStage( parent );
292     }
293   }
294 }
295
296 } // unnamed namespace
297
298
299 // Properties registered without macro to use specific member variables.
300 const PropertyRegistration Control::Impl::PROPERTY_1( typeRegistration, "styleName",              Toolkit::Control::Property::STYLE_NAME,                   Property::STRING,  &Control::Impl::SetProperty, &Control::Impl::GetProperty );
301 const PropertyRegistration Control::Impl::PROPERTY_2( typeRegistration, "backgroundColor",        Toolkit::Control::Property::BACKGROUND_COLOR,             Property::VECTOR4, &Control::Impl::SetProperty, &Control::Impl::GetProperty );
302 const PropertyRegistration Control::Impl::PROPERTY_3( typeRegistration, "backgroundImage",        Toolkit::Control::Property::BACKGROUND_IMAGE,             Property::MAP,     &Control::Impl::SetProperty, &Control::Impl::GetProperty );
303 const PropertyRegistration Control::Impl::PROPERTY_4( typeRegistration, "keyInputFocus",          Toolkit::Control::Property::KEY_INPUT_FOCUS,              Property::BOOLEAN, &Control::Impl::SetProperty, &Control::Impl::GetProperty );
304 const PropertyRegistration Control::Impl::PROPERTY_5( typeRegistration, "background",             Toolkit::Control::Property::BACKGROUND,                   Property::MAP,     &Control::Impl::SetProperty, &Control::Impl::GetProperty );
305 const PropertyRegistration Control::Impl::PROPERTY_6( typeRegistration, "margin",                 Toolkit::Control::Property::MARGIN,                       Property::EXTENTS, &Control::Impl::SetProperty, &Control::Impl::GetProperty );
306 const PropertyRegistration Control::Impl::PROPERTY_7( typeRegistration, "padding",                Toolkit::Control::Property::PADDING,                      Property::EXTENTS, &Control::Impl::SetProperty, &Control::Impl::GetProperty );
307 const PropertyRegistration Control::Impl::PROPERTY_8( typeRegistration, "tooltip",                Toolkit::DevelControl::Property::TOOLTIP,                 Property::MAP,     &Control::Impl::SetProperty, &Control::Impl::GetProperty );
308 const PropertyRegistration Control::Impl::PROPERTY_9( typeRegistration, "state",                  Toolkit::DevelControl::Property::STATE,                   Property::STRING,  &Control::Impl::SetProperty, &Control::Impl::GetProperty );
309 const PropertyRegistration Control::Impl::PROPERTY_10( typeRegistration, "subState",               Toolkit::DevelControl::Property::SUB_STATE,               Property::STRING,  &Control::Impl::SetProperty, &Control::Impl::GetProperty );
310 const PropertyRegistration Control::Impl::PROPERTY_11( typeRegistration, "leftFocusableActorId",   Toolkit::DevelControl::Property::LEFT_FOCUSABLE_ACTOR_ID, Property::INTEGER, &Control::Impl::SetProperty, &Control::Impl::GetProperty );
311 const PropertyRegistration Control::Impl::PROPERTY_12( typeRegistration, "rightFocusableActorId", Toolkit::DevelControl::Property::RIGHT_FOCUSABLE_ACTOR_ID,Property::INTEGER, &Control::Impl::SetProperty, &Control::Impl::GetProperty );
312 const PropertyRegistration Control::Impl::PROPERTY_13( typeRegistration, "upFocusableActorId",    Toolkit::DevelControl::Property::UP_FOCUSABLE_ACTOR_ID,   Property::INTEGER, &Control::Impl::SetProperty, &Control::Impl::GetProperty );
313 const PropertyRegistration Control::Impl::PROPERTY_14( typeRegistration, "downFocusableActorId",  Toolkit::DevelControl::Property::DOWN_FOCUSABLE_ACTOR_ID, Property::INTEGER, &Control::Impl::SetProperty, &Control::Impl::GetProperty );
314
315 Control::Impl::Impl( Control& controlImpl )
316 : mControlImpl( controlImpl ),
317   mState( Toolkit::DevelControl::NORMAL ),
318   mSubStateName(""),
319   mLeftFocusableActorId( -1 ),
320   mRightFocusableActorId( -1 ),
321   mUpFocusableActorId( -1 ),
322   mDownFocusableActorId( -1 ),
323   mStyleName(""),
324   mBackgroundColor(Color::TRANSPARENT),
325   mStartingPinchScale( NULL ),
326   mMargin( 0, 0, 0, 0 ),
327   mPadding( 0, 0, 0, 0 ),
328   mKeyEventSignal(),
329   mKeyInputFocusGainedSignal(),
330   mKeyInputFocusLostSignal(),
331   mResourceReadySignal(),
332   mVisualEventSignal(),
333   mPinchGestureDetector(),
334   mPanGestureDetector(),
335   mTapGestureDetector(),
336   mLongPressGestureDetector(),
337   mTooltip( NULL ),
338   mInputMethodContext(),
339   mAutofillItem(),
340   mAutofillContainer(),
341   mFlags( Control::ControlBehaviour( CONTROL_BEHAVIOUR_DEFAULT ) ),
342   mIsKeyboardNavigationSupported( false ),
343   mIsKeyboardFocusGroup( false ),
344   mIsAutofillEnabled( false )
345 {
346 }
347
348 Control::Impl::~Impl()
349 {
350   // All gesture detectors will be destroyed so no need to disconnect.
351   delete mStartingPinchScale;
352 }
353
354 Control::Impl& Control::Impl::Get( Internal::Control& internalControl )
355 {
356   return *internalControl.mImpl;
357 }
358
359 const Control::Impl& Control::Impl::Get( const Internal::Control& internalControl )
360 {
361   return *internalControl.mImpl;
362 }
363
364 // Gesture Detection Methods
365 void Control::Impl::PinchDetected(Actor actor, const PinchGesture& pinch)
366 {
367   mControlImpl.OnPinch(pinch);
368 }
369
370 void Control::Impl::PanDetected(Actor actor, const PanGesture& pan)
371 {
372   mControlImpl.OnPan(pan);
373 }
374
375 void Control::Impl::TapDetected(Actor actor, const TapGesture& tap)
376 {
377   mControlImpl.OnTap(tap);
378 }
379
380 void Control::Impl::LongPressDetected(Actor actor, const LongPressGesture& longPress)
381 {
382   mControlImpl.OnLongPress(longPress);
383 }
384
385 void Control::Impl::RegisterVisual( Property::Index index, Toolkit::Visual::Base& visual )
386 {
387   RegisterVisual( index, visual, VisualState::ENABLED, DepthIndexValue::NOT_SET );
388 }
389
390 void Control::Impl::RegisterVisual( Property::Index index, Toolkit::Visual::Base& visual, int depthIndex )
391 {
392   RegisterVisual( index, visual, VisualState::ENABLED, DepthIndexValue::SET, depthIndex );
393 }
394
395 void Control::Impl::RegisterVisual( Property::Index index, Toolkit::Visual::Base& visual, bool enabled )
396 {
397   RegisterVisual( index, visual, ( enabled ? VisualState::ENABLED : VisualState::DISABLED ), DepthIndexValue::NOT_SET );
398 }
399
400 void Control::Impl::RegisterVisual( Property::Index index, Toolkit::Visual::Base& visual, bool enabled, int depthIndex )
401 {
402   RegisterVisual( index, visual, ( enabled ? VisualState::ENABLED : VisualState::DISABLED ), DepthIndexValue::SET, depthIndex );
403 }
404
405 void Control::Impl::RegisterVisual( Property::Index index, Toolkit::Visual::Base& visual, VisualState::Type enabled, DepthIndexValue::Type depthIndexValueSet, int depthIndex )
406 {
407   DALI_LOG_INFO( gLogFilter, Debug::Concise, "RegisterVisual:%d \n", index );
408
409   bool visualReplaced ( false );
410   Actor self = mControlImpl.Self();
411
412   // Set the depth index, if not set by caller this will be either the current visual depth, max depth of all visuals
413   // or zero.
414   int requiredDepthIndex = visual.GetDepthIndex();
415
416   if( depthIndexValueSet == DepthIndexValue::SET )
417   {
418     requiredDepthIndex = depthIndex;
419   }
420
421   // Visual replacement, existing visual should only be removed from stage when replacement ready.
422   if( !mVisuals.Empty() )
423   {
424     RegisteredVisualContainer::Iterator registeredVisualsiter;
425     // Check if visual (index) is already registered, this is the current visual.
426     if( FindVisual( index, mVisuals, registeredVisualsiter ) )
427     {
428       Toolkit::Visual::Base& currentRegisteredVisual = (*registeredVisualsiter)->visual;
429       if( currentRegisteredVisual )
430       {
431         // Store current visual depth index as may need to set the replacement visual to same depth
432         const int currentDepthIndex = (*registeredVisualsiter)->visual.GetDepthIndex();
433
434         // No longer required to know if the replaced visual's resources are ready
435         StopObservingVisual( currentRegisteredVisual );
436
437         // If control staged and visual enabled then visuals will be swapped once ready
438         if(  self.OnStage() && enabled )
439         {
440           // Check if visual is currently in the process of being replaced ( is in removal container )
441           RegisteredVisualContainer::Iterator visualQueuedForRemoval;
442           if ( FindVisual( index, mRemoveVisuals, visualQueuedForRemoval ) )
443           {
444             // Visual with same index is already in removal container so current visual pending
445             // Only the the last requested visual will be displayed so remove current visual which is staged but not ready.
446             Toolkit::GetImplementation( currentRegisteredVisual ).SetOffStage( self );
447             mVisuals.Erase( registeredVisualsiter );
448           }
449           else
450           {
451             // current visual not already in removal container so add now.
452             DALI_LOG_INFO( gLogFilter, Debug::Verbose, "RegisterVisual Move current registered visual to removal Queue: %d \n", index );
453             MoveVisual( registeredVisualsiter, mVisuals, mRemoveVisuals );
454           }
455         }
456         else
457         {
458           // Control not staged or visual disabled so can just erase from registered visuals and new visual will be added later.
459           mVisuals.Erase( registeredVisualsiter );
460         }
461
462         // If we've not set the depth-index value and the new visual does not have a depth index applied to it, then use the previously set depth-index for this index
463         if( ( depthIndexValueSet == DepthIndexValue::NOT_SET ) &&
464             ( visual.GetDepthIndex() == 0 ) )
465         {
466           requiredDepthIndex = currentDepthIndex;
467         }
468       }
469
470       visualReplaced = true;
471     }
472   }
473
474   // If not set, set the name of the visual to the same name as the control's property.
475   // ( If the control has been type registered )
476   if( visual.GetName().empty() )
477   {
478     // returns empty string if index is not found as long as index is not -1
479     std::string visualName = self.GetPropertyName( index );
480     if( !visualName.empty() )
481     {
482       DALI_LOG_INFO( gLogFilter, Debug::Concise, "Setting visual name for property %d to %s\n",
483                      index, visualName.c_str() );
484       visual.SetName( visualName );
485     }
486   }
487
488   if( !visualReplaced ) // New registration entry
489   {
490     // If we've not set the depth-index value, we have more than one visual and the visual does not have a depth index, then set it to be the highest
491     if( ( depthIndexValueSet == DepthIndexValue::NOT_SET ) &&
492         ( mVisuals.Size() > 0 ) &&
493         ( visual.GetDepthIndex() == 0 ) )
494     {
495       int maxDepthIndex = std::numeric_limits< int >::min();
496
497       RegisteredVisualContainer::ConstIterator iter;
498       const RegisteredVisualContainer::ConstIterator endIter = mVisuals.End();
499       for ( iter = mVisuals.Begin(); iter != endIter; iter++ )
500       {
501         const int visualDepthIndex = (*iter)->visual.GetDepthIndex();
502         if ( visualDepthIndex > maxDepthIndex )
503         {
504           maxDepthIndex = visualDepthIndex;
505         }
506       }
507       ++maxDepthIndex; // Add one to the current maximum depth index so that our added visual appears on top
508       requiredDepthIndex = std::max( 0, maxDepthIndex ); // Start at zero if maxDepth index belongs to a background
509     }
510   }
511
512   if( visual )
513   {
514     // Set determined depth index
515     visual.SetDepthIndex( requiredDepthIndex );
516
517     // Monitor when the visual resources are ready
518     StartObservingVisual( visual );
519
520     DALI_LOG_INFO( gLogFilter, Debug::Concise, "New Visual registration index[%d] depth[%d]\n", index, requiredDepthIndex );
521     RegisteredVisual* newRegisteredVisual  = new RegisteredVisual( index, visual,
522                                              ( enabled == VisualState::ENABLED ? true : false ),
523                                              ( visualReplaced && enabled ) ) ;
524     mVisuals.PushBack( newRegisteredVisual );
525
526     Internal::Visual::Base& visualImpl = Toolkit::GetImplementation( visual );
527     // Put on stage if enabled and the control is already on the stage
528     if( ( enabled == VisualState::ENABLED ) && self.OnStage() )
529     {
530       visualImpl.SetOnStage( self );
531     }
532     else if( visualImpl.IsResourceReady() ) // When not being staged, check if visual already 'ResourceReady' before it was Registered. ( Resource may have been loaded already )
533     {
534       ResourceReady( visualImpl );
535     }
536
537   }
538
539   DALI_LOG_INFO( gLogFilter, Debug::Verbose, "Control::RegisterVisual() Registered %s(%d), enabled:%s\n",  visual.GetName().c_str(), index, enabled?"true":"false" );
540 }
541
542 void Control::Impl::UnregisterVisual( Property::Index index )
543 {
544   RegisteredVisualContainer::Iterator iter;
545   if ( FindVisual( index, mVisuals, iter ) )
546   {
547     // stop observing visual
548     StopObservingVisual( (*iter)->visual );
549
550     Actor self( mControlImpl.Self() );
551     Toolkit::GetImplementation((*iter)->visual).SetOffStage( self );
552     (*iter)->visual.Reset();
553     mVisuals.Erase( iter );
554   }
555
556   if( FindVisual( index, mRemoveVisuals, iter ) )
557   {
558     Actor self( mControlImpl.Self() );
559     Toolkit::GetImplementation( (*iter)->visual ).SetOffStage( self );
560     (*iter)->pending = false;
561     (*iter)->visual.Reset();
562     mRemoveVisuals.Erase( iter );
563   }
564 }
565
566 Toolkit::Visual::Base Control::Impl::GetVisual( Property::Index index ) const
567 {
568   RegisteredVisualContainer::Iterator iter;
569   if ( FindVisual( index, mVisuals, iter ) )
570   {
571     return (*iter)->visual;
572   }
573
574   return Toolkit::Visual::Base();
575 }
576
577 void Control::Impl::EnableVisual( Property::Index index, bool enable )
578 {
579   DALI_LOG_INFO( gLogFilter, Debug::General, "Control::EnableVisual(%d, %s)\n", index, enable?"T":"F");
580
581   RegisteredVisualContainer::Iterator iter;
582   if ( FindVisual( index, mVisuals, iter ) )
583   {
584     if (  (*iter)->enabled == enable )
585     {
586       DALI_LOG_INFO( gLogFilter, Debug::Verbose, "Control::EnableVisual Visual %s(%d) already %s\n", (*iter)->visual.GetName().c_str(), index, enable?"enabled":"disabled");
587       return;
588     }
589
590     (*iter)->enabled = enable;
591     Actor parentActor = mControlImpl.Self();
592     if ( mControlImpl.Self().OnStage() ) // If control not on Stage then Visual will be added when StageConnection is called.
593     {
594       if ( enable )
595       {
596         DALI_LOG_INFO( gLogFilter, Debug::Verbose, "Control::EnableVisual Setting %s(%d) on stage \n", (*iter)->visual.GetName().c_str(), index );
597         Toolkit::GetImplementation((*iter)->visual).SetOnStage( parentActor );
598       }
599       else
600       {
601         DALI_LOG_INFO( gLogFilter, Debug::Verbose, "Control::EnableVisual Setting %s(%d) off stage \n", (*iter)->visual.GetName().c_str(), index );
602         Toolkit::GetImplementation((*iter)->visual).SetOffStage( parentActor );  // No need to call if control not staged.
603       }
604     }
605   }
606   else
607   {
608     DALI_LOG_WARNING( "Control::EnableVisual(%d, %s) FAILED - NO SUCH VISUAL\n", index, enable?"T":"F" );
609   }
610 }
611
612 bool Control::Impl::IsVisualEnabled( Property::Index index ) const
613 {
614   RegisteredVisualContainer::Iterator iter;
615   if ( FindVisual( index, mVisuals, iter ) )
616   {
617     return (*iter)->enabled;
618   }
619   return false;
620 }
621
622 void Control::Impl::StopObservingVisual( Toolkit::Visual::Base& visual )
623 {
624   Internal::Visual::Base& visualImpl = Toolkit::GetImplementation( visual );
625
626   // Stop observing the visual
627   visualImpl.RemoveEventObserver( *this );
628 }
629
630 void Control::Impl::StartObservingVisual( Toolkit::Visual::Base& visual)
631 {
632   Internal::Visual::Base& visualImpl = Toolkit::GetImplementation( visual );
633
634   // start observing the visual for events
635   visualImpl.AddEventObserver( *this );
636 }
637
638 // Called by a Visual when it's resource is ready
639 void Control::Impl::ResourceReady( Visual::Base& object)
640 {
641   DALI_LOG_INFO( gLogFilter, Debug::Verbose, "Control::Impl::ResourceReady() replacements pending[%d]\n", mRemoveVisuals.Count() );
642
643   Actor self = mControlImpl.Self();
644
645   // A resource is ready, find resource in the registered visuals container and get its index
646   for( auto registeredIter = mVisuals.Begin(),  end = mVisuals.End(); registeredIter != end; ++registeredIter )
647   {
648     Internal::Visual::Base& registeredVisualImpl = Toolkit::GetImplementation( (*registeredIter)->visual );
649
650     if( &object == &registeredVisualImpl )
651     {
652       RegisteredVisualContainer::Iterator visualToRemoveIter;
653       // Find visual with the same index in the removal container
654       // Set if off stage as it's replacement is now ready.
655       // Remove if from removal list as now removed from stage.
656       // Set Pending flag on the ready visual to false as now ready.
657       if( FindVisual( (*registeredIter)->index, mRemoveVisuals, visualToRemoveIter ) )
658       {
659         (*registeredIter)->pending = false;
660         Toolkit::GetImplementation( (*visualToRemoveIter)->visual ).SetOffStage( self );
661         mRemoveVisuals.Erase( visualToRemoveIter );
662       }
663       break;
664     }
665   }
666
667   // A visual is ready so control may need relayouting if staged
668   if ( self.OnStage() )
669   {
670     mControlImpl.RelayoutRequest();
671   }
672
673   // Emit signal if all enabled visuals registered by the control are ready.
674   if( IsResourceReady() )
675   {
676     Dali::Toolkit::Control handle( mControlImpl.GetOwner() );
677     mResourceReadySignal.Emit( handle );
678   }
679 }
680
681 void Control::Impl::NotifyVisualEvent( Visual::Base& object, Property::Index signalId )
682 {
683   for( auto registeredIter = mVisuals.Begin(),  end = mVisuals.End(); registeredIter != end; ++registeredIter )
684   {
685     Internal::Visual::Base& registeredVisualImpl = Toolkit::GetImplementation( (*registeredIter)->visual );
686     if( &object == &registeredVisualImpl )
687     {
688       Dali::Toolkit::Control handle( mControlImpl.GetOwner() );
689       mVisualEventSignal.Emit( handle, (*registeredIter)->index, signalId );
690       break;
691     }
692   }
693 }
694
695 bool Control::Impl::IsResourceReady() const
696 {
697   // Iterate through and check all the enabled visuals are ready
698   for( auto visualIter = mVisuals.Begin();
699          visualIter != mVisuals.End(); ++visualIter )
700   {
701     const Toolkit::Visual::Base visual = (*visualIter)->visual;
702     const Internal::Visual::Base& visualImpl = Toolkit::GetImplementation( visual );
703
704     // one of the enabled visuals is not ready
705     if( !visualImpl.IsResourceReady() && (*visualIter)->enabled )
706     {
707       return false;
708     }
709   }
710   return true;
711 }
712
713 Toolkit::Visual::ResourceStatus Control::Impl::GetVisualResourceStatus( Property::Index index ) const
714 {
715   RegisteredVisualContainer::Iterator iter;
716   if ( FindVisual( index, mVisuals, iter ) )
717   {
718     const Toolkit::Visual::Base visual = (*iter)->visual;
719     const Internal::Visual::Base& visualImpl = Toolkit::GetImplementation( visual );
720     return visualImpl.GetResourceStatus( );
721   }
722
723   return Toolkit::Visual::ResourceStatus::PREPARING;
724 }
725
726
727
728 void Control::Impl::AddTransitions( Dali::Animation& animation,
729                                     const Toolkit::TransitionData& handle,
730                                     bool createAnimation )
731 {
732   // Setup a Transition from TransitionData.
733   const Internal::TransitionData& transitionData = Toolkit::GetImplementation( handle );
734   TransitionData::Iterator end = transitionData.End();
735   for( TransitionData::Iterator iter = transitionData.Begin() ;
736        iter != end; ++iter )
737   {
738     TransitionData::Animator* animator = (*iter);
739
740     Toolkit::Visual::Base visual = GetVisualByName( mVisuals, animator->objectName );
741
742     if( visual )
743     {
744 #if defined(DEBUG_ENABLED)
745       Dali::TypeInfo typeInfo;
746       ControlWrapper* controlWrapperImpl = dynamic_cast<ControlWrapper*>(&mControlImpl);
747       if( controlWrapperImpl )
748       {
749         typeInfo = controlWrapperImpl->GetTypeInfo();
750       }
751
752       DALI_LOG_INFO( gLogFilter, Debug::Concise, "CreateTransition: Found %s visual for %s\n",
753                      visual.GetName().c_str(), typeInfo?typeInfo.GetName().c_str():"Unknown" );
754 #endif
755       Internal::Visual::Base& visualImpl = Toolkit::GetImplementation( visual );
756       visualImpl.AnimateProperty( animation, *animator );
757     }
758     else
759     {
760       DALI_LOG_INFO( gLogFilter, Debug::Concise, "CreateTransition: Could not find visual. Trying actors");
761       // Otherwise, try any actor children of control (Including the control)
762       Actor child = mControlImpl.Self().FindChildByName( animator->objectName );
763       if( child )
764       {
765         Property::Index propertyIndex = DevelHandle::GetPropertyIndex( child, animator->propertyKey );
766         if( propertyIndex != Property::INVALID_INDEX )
767         {
768           if( animator->animate == false )
769           {
770             if( animator->targetValue.GetType() != Property::NONE )
771             {
772               child.SetProperty( propertyIndex, animator->targetValue );
773             }
774           }
775           else // animate the property
776           {
777             if( animator->initialValue.GetType() != Property::NONE )
778             {
779               child.SetProperty( propertyIndex, animator->initialValue );
780             }
781
782             if( createAnimation && !animation )
783             {
784               animation = Dali::Animation::New( 0.1f );
785             }
786
787             animation.AnimateTo( Property( child, propertyIndex ),
788                                  animator->targetValue,
789                                  animator->alphaFunction,
790                                  TimePeriod( animator->timePeriodDelay,
791                                              animator->timePeriodDuration ) );
792           }
793         }
794       }
795     }
796   }
797 }
798
799 Dali::Animation Control::Impl::CreateTransition( const Toolkit::TransitionData& transitionData )
800 {
801   Dali::Animation transition;
802
803   if( transitionData.Count() > 0 )
804   {
805     AddTransitions( transition, transitionData, true );
806   }
807   return transition;
808 }
809
810
811
812 void Control::Impl::DoAction( Dali::Property::Index visualIndex, Dali::Property::Index actionId, const Dali::Property::Value attributes )
813 {
814   RegisteredVisualContainer::Iterator iter;
815   if ( FindVisual( visualIndex, mVisuals, iter ) )
816   {
817     Toolkit::GetImplementation((*iter)->visual).DoAction( actionId, attributes );
818   }
819 }
820
821 void Control::Impl::SetProperty( BaseObject* object, Property::Index index, const Property::Value& value )
822 {
823   Toolkit::Control control = Toolkit::Control::DownCast( BaseHandle( object ) );
824
825   if ( control )
826   {
827     Control& controlImpl( GetImplementation( control ) );
828
829     switch ( index )
830     {
831       case Toolkit::Control::Property::STYLE_NAME:
832       {
833         controlImpl.SetStyleName( value.Get< std::string >() );
834         break;
835       }
836
837       case Toolkit::DevelControl::Property::STATE:
838       {
839         bool withTransitions=true;
840         const Property::Value* valuePtr=&value;
841         Property::Map* map = value.GetMap();
842         if(map)
843         {
844           Property::Value* value2 = map->Find("withTransitions");
845           if( value2 )
846           {
847             withTransitions = value2->Get<bool>();
848           }
849
850           valuePtr = map->Find("state");
851         }
852
853         if( valuePtr )
854         {
855           Toolkit::DevelControl::State state( controlImpl.mImpl->mState );
856           if( Scripting::GetEnumerationProperty< Toolkit::DevelControl::State >( *valuePtr, ControlStateTable, ControlStateTableCount, state ) )
857           {
858             controlImpl.mImpl->SetState( state, withTransitions );
859           }
860         }
861       }
862       break;
863
864       case Toolkit::DevelControl::Property::SUB_STATE:
865       {
866         std::string subState;
867         if( value.Get( subState ) )
868         {
869           controlImpl.mImpl->SetSubState( subState );
870         }
871       }
872       break;
873
874       case Toolkit::DevelControl::Property::LEFT_FOCUSABLE_ACTOR_ID:
875       {
876         int focusId;
877         if( value.Get( focusId ) )
878         {
879           controlImpl.mImpl->mLeftFocusableActorId = focusId;
880         }
881       }
882       break;
883
884       case Toolkit::DevelControl::Property::RIGHT_FOCUSABLE_ACTOR_ID:
885       {
886         int focusId;
887         if( value.Get( focusId ) )
888         {
889           controlImpl.mImpl->mRightFocusableActorId = focusId;
890         }
891       }
892       break;
893
894       case Toolkit::DevelControl::Property::UP_FOCUSABLE_ACTOR_ID:
895       {
896         int focusId;
897         if( value.Get( focusId ) )
898         {
899           controlImpl.mImpl->mUpFocusableActorId = focusId;
900         }
901       }
902       break;
903
904       case Toolkit::DevelControl::Property::DOWN_FOCUSABLE_ACTOR_ID:
905       {
906         int focusId;
907         if( value.Get( focusId ) )
908         {
909           controlImpl.mImpl->mDownFocusableActorId = focusId;
910         }
911       }
912       break;
913
914       case Toolkit::Control::Property::BACKGROUND_COLOR:
915       {
916         DALI_LOG_WARNING( "BACKGROUND_COLOR property is deprecated. Use BACKGROUND property instead\n" );
917         controlImpl.SetBackgroundColor( value.Get< Vector4 >() );
918         break;
919       }
920
921       case Toolkit::Control::Property::BACKGROUND_IMAGE:
922       {
923         DALI_LOG_WARNING( "BACKGROUND_IMAGE property is deprecated. Use BACKGROUND property instead\n" );
924         Image image = Scripting::NewImage( value );
925         if ( image )
926         {
927           controlImpl.SetBackgroundImage( image );
928         }
929         else
930         {
931           // An empty image means the background is no longer required
932           controlImpl.ClearBackground();
933         }
934         break;
935       }
936
937       case Toolkit::Control::Property::KEY_INPUT_FOCUS:
938       {
939         if ( value.Get< bool >() )
940         {
941           controlImpl.SetKeyInputFocus();
942         }
943         else
944         {
945           controlImpl.ClearKeyInputFocus();
946         }
947         break;
948       }
949
950       case Toolkit::Control::Property::BACKGROUND:
951       {
952         std::string url;
953         Vector4 color;
954         const Property::Map* map = value.GetMap();
955         if( map && !map->Empty() )
956         {
957           controlImpl.SetBackground( *map );
958         }
959         else if( value.Get( url ) )
960         {
961           // don't know the size to load
962           Toolkit::Visual::Base visual = Toolkit::VisualFactory::Get().CreateVisual( url, ImageDimensions() );
963           if( visual )
964           {
965             controlImpl.mImpl->RegisterVisual( Toolkit::Control::Property::BACKGROUND, visual, DepthIndex::BACKGROUND );
966           }
967         }
968         else if( value.Get( color ) )
969         {
970           controlImpl.SetBackgroundColor(color);
971         }
972         else
973         {
974           // The background is an empty property map, so we should clear the background
975           controlImpl.ClearBackground();
976         }
977         break;
978       }
979
980       case Toolkit::Control::Property::MARGIN:
981       {
982         Extents margin;
983         if( value.Get( margin ) )
984         {
985           controlImpl.mImpl->SetMargin( margin );
986         }
987         break;
988       }
989
990       case Toolkit::Control::Property::PADDING:
991       {
992         Extents padding;
993         if( value.Get( padding ) )
994         {
995           controlImpl.mImpl->SetPadding( padding );
996         }
997         break;
998       }
999
1000       case Toolkit::DevelControl::Property::TOOLTIP:
1001       {
1002         TooltipPtr& tooltipPtr = controlImpl.mImpl->mTooltip;
1003         if( ! tooltipPtr )
1004         {
1005           tooltipPtr = Tooltip::New( control );
1006         }
1007         tooltipPtr->SetProperties( value );
1008         break;
1009       }
1010
1011     }
1012   }
1013 }
1014
1015 Property::Value Control::Impl::GetProperty( BaseObject* object, Property::Index index )
1016 {
1017   Property::Value value;
1018
1019   Toolkit::Control control = Toolkit::Control::DownCast( BaseHandle( object ) );
1020
1021   if ( control )
1022   {
1023     Control& controlImpl( GetImplementation( control ) );
1024
1025     switch ( index )
1026     {
1027       case Toolkit::Control::Property::STYLE_NAME:
1028       {
1029         value = controlImpl.GetStyleName();
1030         break;
1031       }
1032
1033       case Toolkit::DevelControl::Property::STATE:
1034       {
1035         value = controlImpl.mImpl->mState;
1036         break;
1037       }
1038
1039       case Toolkit::DevelControl::Property::SUB_STATE:
1040       {
1041         value = controlImpl.mImpl->mSubStateName;
1042         break;
1043       }
1044
1045       case Toolkit::DevelControl::Property::LEFT_FOCUSABLE_ACTOR_ID:
1046       {
1047         value = controlImpl.mImpl->mLeftFocusableActorId;
1048         break;
1049       }
1050
1051       case Toolkit::DevelControl::Property::RIGHT_FOCUSABLE_ACTOR_ID:
1052       {
1053         value = controlImpl.mImpl->mRightFocusableActorId;
1054         break;
1055       }
1056
1057       case Toolkit::DevelControl::Property::UP_FOCUSABLE_ACTOR_ID:
1058       {
1059         value = controlImpl.mImpl->mUpFocusableActorId;
1060         break;
1061       }
1062
1063       case Toolkit::DevelControl::Property::DOWN_FOCUSABLE_ACTOR_ID:
1064       {
1065         value = controlImpl.mImpl->mDownFocusableActorId;
1066         break;
1067       }
1068
1069       case Toolkit::Control::Property::BACKGROUND_COLOR:
1070       {
1071         DALI_LOG_WARNING( "BACKGROUND_COLOR property is deprecated. Use BACKGROUND property instead\n" );
1072         value = controlImpl.GetBackgroundColor();
1073         break;
1074       }
1075
1076       case Toolkit::Control::Property::BACKGROUND_IMAGE:
1077       {
1078         DALI_LOG_WARNING( "BACKGROUND_IMAGE property is deprecated. Use BACKGROUND property instead\n" );
1079         Property::Map map;
1080         Toolkit::Visual::Base visual = controlImpl.mImpl->GetVisual( Toolkit::Control::Property::BACKGROUND );
1081         if( visual )
1082         {
1083           visual.CreatePropertyMap( map );
1084         }
1085         value = map;
1086         break;
1087       }
1088
1089       case Toolkit::Control::Property::KEY_INPUT_FOCUS:
1090       {
1091         value = controlImpl.HasKeyInputFocus();
1092         break;
1093       }
1094
1095       case Toolkit::Control::Property::BACKGROUND:
1096       {
1097         Property::Map map;
1098         Toolkit::Visual::Base visual = controlImpl.mImpl->GetVisual( Toolkit::Control::Property::BACKGROUND );
1099         if( visual )
1100         {
1101           visual.CreatePropertyMap( map );
1102         }
1103
1104         value = map;
1105         break;
1106       }
1107
1108       case Toolkit::Control::Property::MARGIN:
1109       {
1110         value = controlImpl.mImpl->GetMargin();
1111         break;
1112       }
1113
1114       case Toolkit::Control::Property::PADDING:
1115       {
1116         value = controlImpl.mImpl->GetPadding();
1117         break;
1118       }
1119
1120       case Toolkit::DevelControl::Property::TOOLTIP:
1121       {
1122         Property::Map map;
1123         if( controlImpl.mImpl->mTooltip )
1124         {
1125           controlImpl.mImpl->mTooltip->CreatePropertyMap( map );
1126         }
1127         value = map;
1128         break;
1129       }
1130     }
1131   }
1132
1133   return value;
1134 }
1135
1136
1137 void  Control::Impl::CopyInstancedProperties( RegisteredVisualContainer& visuals, Dictionary<Property::Map>& instancedProperties )
1138 {
1139   for(RegisteredVisualContainer::Iterator iter = visuals.Begin(); iter!= visuals.End(); iter++)
1140   {
1141     if( (*iter)->visual )
1142     {
1143       Property::Map instanceMap;
1144       Toolkit::GetImplementation((*iter)->visual).CreateInstancePropertyMap(instanceMap);
1145       instancedProperties.Add( (*iter)->visual.GetName(), instanceMap );
1146     }
1147   }
1148 }
1149
1150
1151 void Control::Impl::RemoveVisual( RegisteredVisualContainer& visuals, const std::string& visualName )
1152 {
1153   Actor self( mControlImpl.Self() );
1154
1155   for ( RegisteredVisualContainer::Iterator visualIter = visuals.Begin();
1156         visualIter != visuals.End(); ++visualIter )
1157   {
1158     Toolkit::Visual::Base visual = (*visualIter)->visual;
1159     if( visual && visual.GetName() == visualName )
1160     {
1161       Toolkit::GetImplementation(visual).SetOffStage( self );
1162       (*visualIter)->visual.Reset();
1163       visuals.Erase( visualIter );
1164       break;
1165     }
1166   }
1167 }
1168
1169 void Control::Impl::RemoveVisuals( RegisteredVisualContainer& visuals, DictionaryKeys& removeVisuals )
1170 {
1171   Actor self( mControlImpl.Self() );
1172   for( DictionaryKeys::iterator iter = removeVisuals.begin(); iter != removeVisuals.end(); ++iter )
1173   {
1174     const std::string visualName = *iter;
1175     RemoveVisual( visuals, visualName );
1176   }
1177 }
1178
1179 void Control::Impl::RecreateChangedVisuals( Dictionary<Property::Map>& stateVisualsToChange,
1180                              Dictionary<Property::Map>& instancedProperties )
1181 {
1182   Dali::CustomActor handle( mControlImpl.GetOwner() );
1183   for( Dictionary<Property::Map>::iterator iter = stateVisualsToChange.Begin();
1184        iter != stateVisualsToChange.End(); ++iter )
1185   {
1186     const std::string& visualName = (*iter).key;
1187     const Property::Map& toMap = (*iter).entry;
1188
1189     // is it a candidate for re-creation?
1190     bool recreate = false;
1191
1192     Toolkit::Visual::Base visual = GetVisualByName( mVisuals, visualName );
1193     if( visual )
1194     {
1195       Property::Map fromMap;
1196       visual.CreatePropertyMap( fromMap );
1197
1198       Toolkit::Visual::Type fromType = GetVisualTypeFromMap( fromMap );
1199       Toolkit::Visual::Type toType = GetVisualTypeFromMap( toMap );
1200
1201       if( fromType != toType )
1202       {
1203         recreate = true;
1204       }
1205       else
1206       {
1207         if( fromType == Toolkit::Visual::IMAGE || fromType == Toolkit::Visual::N_PATCH
1208             || fromType == Toolkit::Visual::SVG || fromType == Toolkit::Visual::ANIMATED_IMAGE )
1209         {
1210           Property::Value* fromUrl = fromMap.Find( Toolkit::ImageVisual::Property::URL, IMAGE_URL_NAME );
1211           Property::Value* toUrl = toMap.Find( Toolkit::ImageVisual::Property::URL, IMAGE_URL_NAME );
1212
1213           if( fromUrl && toUrl )
1214           {
1215             std::string fromUrlString;
1216             std::string toUrlString;
1217             fromUrl->Get(fromUrlString);
1218             toUrl->Get(toUrlString);
1219
1220             if( fromUrlString != toUrlString )
1221             {
1222               recreate = true;
1223             }
1224           }
1225         }
1226       }
1227
1228       const Property::Map* instancedMap = instancedProperties.FindConst( visualName );
1229       if( recreate || instancedMap )
1230       {
1231         RemoveVisual( mVisuals, visualName );
1232         Style::ApplyVisual( handle, visualName, toMap, instancedMap );
1233       }
1234       else
1235       {
1236         // @todo check to see if we can apply toMap without recreating the visual
1237         // e.g. by setting only animatable properties
1238         // For now, recreate all visuals, but merge in instance data.
1239         RemoveVisual( mVisuals, visualName );
1240         Style::ApplyVisual( handle, visualName, toMap, instancedMap );
1241       }
1242     }
1243   }
1244 }
1245
1246 void Control::Impl::ReplaceStateVisualsAndProperties( const StylePtr oldState, const StylePtr newState, const std::string& subState )
1247 {
1248   // Collect all old visual names
1249   DictionaryKeys stateVisualsToRemove;
1250   if( oldState )
1251   {
1252     oldState->visuals.GetKeys( stateVisualsToRemove );
1253     if( ! subState.empty() )
1254     {
1255       const StylePtr* oldSubState = oldState->subStates.FindConst(subState);
1256       if( oldSubState )
1257       {
1258         DictionaryKeys subStateVisualsToRemove;
1259         (*oldSubState)->visuals.GetKeys( subStateVisualsToRemove );
1260         Merge( stateVisualsToRemove, subStateVisualsToRemove );
1261       }
1262     }
1263   }
1264
1265   // Collect all new visual properties
1266   Dictionary<Property::Map> stateVisualsToAdd;
1267   if( newState )
1268   {
1269     stateVisualsToAdd = newState->visuals;
1270     if( ! subState.empty() )
1271     {
1272       const StylePtr* newSubState = newState->subStates.FindConst(subState);
1273       if( newSubState )
1274       {
1275         stateVisualsToAdd.Merge( (*newSubState)->visuals );
1276       }
1277     }
1278   }
1279
1280   // If a name is in both add/remove, move it to change list.
1281   Dictionary<Property::Map> stateVisualsToChange;
1282   FindChangableVisuals( stateVisualsToAdd, stateVisualsToChange, stateVisualsToRemove);
1283
1284   // Copy instanced properties (e.g. text label) of current visuals
1285   Dictionary<Property::Map> instancedProperties;
1286   CopyInstancedProperties( mVisuals, instancedProperties );
1287
1288   // For each visual in remove list, remove from mVisuals
1289   RemoveVisuals( mVisuals, stateVisualsToRemove );
1290
1291   // For each visual in add list, create and add to mVisuals
1292   Dali::CustomActor handle( mControlImpl.GetOwner() );
1293   Style::ApplyVisuals( handle, stateVisualsToAdd, instancedProperties );
1294
1295   // For each visual in change list, if it requires a new visual,
1296   // remove old visual, create and add to mVisuals
1297   RecreateChangedVisuals( stateVisualsToChange, instancedProperties );
1298 }
1299
1300 void Control::Impl::SetState( DevelControl::State newState, bool withTransitions )
1301 {
1302   DevelControl::State oldState = mState;
1303   Dali::CustomActor handle( mControlImpl.GetOwner() );
1304   DALI_LOG_INFO(gLogFilter, Debug::Concise, "Control::Impl::SetState: %s\n",
1305                 (mState == DevelControl::NORMAL ? "NORMAL" :(
1306                   mState == DevelControl::FOCUSED ?"FOCUSED" : (
1307                     mState == DevelControl::DISABLED?"DISABLED":"NONE" ))));
1308
1309   if( mState != newState )
1310   {
1311     // If mState was Disabled, and new state is Focused, should probably
1312     // store that fact, e.g. in another property that FocusManager can access.
1313     mState = newState;
1314
1315     // Trigger state change and transitions
1316     // Apply new style, if stylemanager is available
1317     Toolkit::StyleManager styleManager = Toolkit::StyleManager::Get();
1318     if( styleManager )
1319     {
1320       const StylePtr stylePtr = GetImpl( styleManager ).GetRecordedStyle( Toolkit::Control( mControlImpl.GetOwner() ) );
1321
1322       if( stylePtr )
1323       {
1324         std::string oldStateName = Scripting::GetEnumerationName< Toolkit::DevelControl::State >( oldState, ControlStateTable, ControlStateTableCount );
1325         std::string newStateName = Scripting::GetEnumerationName< Toolkit::DevelControl::State >( newState, ControlStateTable, ControlStateTableCount );
1326
1327         const StylePtr* newStateStyle = stylePtr->subStates.Find( newStateName );
1328         const StylePtr* oldStateStyle = stylePtr->subStates.Find( oldStateName );
1329         if( oldStateStyle && newStateStyle )
1330         {
1331           // Only change if both state styles exist
1332           ReplaceStateVisualsAndProperties( *oldStateStyle, *newStateStyle, mSubStateName );
1333         }
1334       }
1335     }
1336   }
1337 }
1338
1339 void Control::Impl::SetSubState( const std::string& subStateName, bool withTransitions )
1340 {
1341   if( mSubStateName != subStateName )
1342   {
1343     // Get existing sub-state visuals, and unregister them
1344     Dali::CustomActor handle( mControlImpl.GetOwner() );
1345
1346     Toolkit::StyleManager styleManager = Toolkit::StyleManager::Get();
1347     if( styleManager )
1348     {
1349       const StylePtr stylePtr = GetImpl( styleManager ).GetRecordedStyle( Toolkit::Control( mControlImpl.GetOwner() ) );
1350       if( stylePtr )
1351       {
1352         // Stringify state
1353         std::string stateName = Scripting::GetEnumerationName< Toolkit::DevelControl::State >( mState, ControlStateTable, ControlStateTableCount );
1354
1355         const StylePtr* state = stylePtr->subStates.Find( stateName );
1356         if( state )
1357         {
1358           StylePtr stateStyle(*state);
1359
1360           const StylePtr* newStateStyle = stateStyle->subStates.Find( subStateName );
1361           const StylePtr* oldStateStyle = stateStyle->subStates.Find( mSubStateName );
1362           if( oldStateStyle && newStateStyle )
1363           {
1364             std::string empty;
1365             ReplaceStateVisualsAndProperties( *oldStateStyle, *newStateStyle, empty );
1366           }
1367         }
1368       }
1369     }
1370
1371     mSubStateName = subStateName;
1372   }
1373 }
1374
1375 void Control::Impl::OnStageDisconnection()
1376 {
1377   Actor self = mControlImpl.Self();
1378
1379   // Any visuals set for replacement but not yet ready should still be registered.
1380   // Reason: If a request was made to register a new visual but the control removed from stage before visual was ready
1381   // then when this control appears back on stage it should use that new visual.
1382
1383   // Iterate through all registered visuals and set off stage
1384   SetVisualsOffStage( mVisuals, self );
1385
1386   // Visuals pending replacement can now be taken out of the removal list and set off stage
1387   // Iterate through all replacement visuals and add to a move queue then set off stage
1388   for( auto removalIter = mRemoveVisuals.Begin(), end = mRemoveVisuals.End(); removalIter != end; removalIter++ )
1389   {
1390     Toolkit::GetImplementation((*removalIter)->visual).SetOffStage( self );
1391   }
1392
1393   for( auto replacedIter = mVisuals.Begin(), end = mVisuals.End(); replacedIter != end; replacedIter++ )
1394   {
1395     (*replacedIter)->pending = false;
1396   }
1397
1398   mRemoveVisuals.Clear();
1399 }
1400
1401 void Control::Impl::SetMargin( Extents margin )
1402 {
1403   mControlImpl.mImpl->mMargin = margin;
1404
1405   // Trigger a size negotiation request that may be needed when setting a margin.
1406   mControlImpl.RelayoutRequest();
1407 }
1408
1409 Extents Control::Impl::GetMargin() const
1410 {
1411   return mControlImpl.mImpl->mMargin;
1412 }
1413
1414 void Control::Impl::SetPadding( Extents padding )
1415 {
1416   mControlImpl.mImpl->mPadding = padding;
1417
1418   // Trigger a size negotiation request that may be needed when setting a padding.
1419   mControlImpl.RelayoutRequest();
1420 }
1421
1422 Extents Control::Impl::GetPadding() const
1423 {
1424   return mControlImpl.mImpl->mPadding;
1425 }
1426
1427 void Control::Impl::SetInputMethodContext( InputMethodContext& inputMethodContext )
1428 {
1429   mInputMethodContext = inputMethodContext;
1430 }
1431
1432 bool Control::Impl::FilterKeyEvent( const KeyEvent& event )
1433 {
1434   bool consumed ( false );
1435
1436   if ( mInputMethodContext )
1437   {
1438     consumed = mInputMethodContext.FilterEventKey( event );
1439   }
1440   return consumed;
1441 }
1442
1443 DevelControl::VisualEventSignalType& Control::Impl::VisualEventSignal()
1444 {
1445   return mVisualEventSignal;
1446 }
1447
1448 void Control::Impl::SetAutofillEnabled( bool autofillEnabled )
1449 {
1450   mIsAutofillEnabled = autofillEnabled;
1451 }
1452
1453 bool Control::Impl::IsAutofillEnabled()
1454 {
1455   return mIsAutofillEnabled;
1456 }
1457
1458 void Control::Impl::SetAutofillItemHandle( Dali::AutofillItem item )
1459 {
1460   mAutofillItem = item;
1461 }
1462
1463 Dali::AutofillItem Control::Impl::GetAutofillItemHandle()
1464 {
1465   return mAutofillItem;
1466 }
1467
1468 void Control::Impl::SetAutofillContainer( Toolkit::AutofillContainer container )
1469 {
1470   mAutofillContainer = container;
1471 }
1472
1473 Toolkit::AutofillContainer Control::Impl::GetAutofillContainer()
1474 {
1475   return mAutofillContainer;
1476 }
1477
1478 } // namespace Internal
1479
1480 } // namespace Toolkit
1481
1482 } // namespace Dali