[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, "reservedProperty01",     Toolkit::Control::Property::RESERVED_PROPERTY_01,         Property::VECTOR4, &Control::Impl::SetProperty, &Control::Impl::GetProperty );
302 const PropertyRegistration Control::Impl::PROPERTY_3( typeRegistration, "reservedProperty02",     Toolkit::Control::Property::RESERVED_PROPERTY_02,         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 const PropertyRegistration Control::Impl::PROPERTY_15( typeRegistration, "shadow",                Toolkit::DevelControl::Property::SHADOW,                  Property::MAP,     &Control::Impl::SetProperty, &Control::Impl::GetProperty );
315
316 Control::Impl::Impl( Control& controlImpl )
317 : mControlImpl( controlImpl ),
318   mState( Toolkit::DevelControl::NORMAL ),
319   mSubStateName(""),
320   mLeftFocusableActorId( -1 ),
321   mRightFocusableActorId( -1 ),
322   mUpFocusableActorId( -1 ),
323   mDownFocusableActorId( -1 ),
324   mStyleName(""),
325   mBackgroundColor(Color::TRANSPARENT),
326   mStartingPinchScale( NULL ),
327   mMargin( 0, 0, 0, 0 ),
328   mPadding( 0, 0, 0, 0 ),
329   mKeyEventSignal(),
330   mKeyInputFocusGainedSignal(),
331   mKeyInputFocusLostSignal(),
332   mResourceReadySignal(),
333   mVisualEventSignal(),
334   mPinchGestureDetector(),
335   mPanGestureDetector(),
336   mTapGestureDetector(),
337   mLongPressGestureDetector(),
338   mTooltip( NULL ),
339   mInputMethodContext(),
340   mAutofillItem(),
341   mAutofillContainer(),
342   mFlags( Control::ControlBehaviour( CONTROL_BEHAVIOUR_DEFAULT ) ),
343   mIsKeyboardNavigationSupported( false ),
344   mIsKeyboardFocusGroup( false ),
345   mIsAutofillEnabled( false )
346 {
347 }
348
349 Control::Impl::~Impl()
350 {
351   // All gesture detectors will be destroyed so no need to disconnect.
352   delete mStartingPinchScale;
353 }
354
355 Control::Impl& Control::Impl::Get( Internal::Control& internalControl )
356 {
357   return *internalControl.mImpl;
358 }
359
360 const Control::Impl& Control::Impl::Get( const Internal::Control& internalControl )
361 {
362   return *internalControl.mImpl;
363 }
364
365 // Gesture Detection Methods
366 void Control::Impl::PinchDetected(Actor actor, const PinchGesture& pinch)
367 {
368   mControlImpl.OnPinch(pinch);
369 }
370
371 void Control::Impl::PanDetected(Actor actor, const PanGesture& pan)
372 {
373   mControlImpl.OnPan(pan);
374 }
375
376 void Control::Impl::TapDetected(Actor actor, const TapGesture& tap)
377 {
378   mControlImpl.OnTap(tap);
379 }
380
381 void Control::Impl::LongPressDetected(Actor actor, const LongPressGesture& longPress)
382 {
383   mControlImpl.OnLongPress(longPress);
384 }
385
386 void Control::Impl::RegisterVisual( Property::Index index, Toolkit::Visual::Base& visual )
387 {
388   RegisterVisual( index, visual, VisualState::ENABLED, DepthIndexValue::NOT_SET );
389 }
390
391 void Control::Impl::RegisterVisual( Property::Index index, Toolkit::Visual::Base& visual, int depthIndex )
392 {
393   RegisterVisual( index, visual, VisualState::ENABLED, DepthIndexValue::SET, depthIndex );
394 }
395
396 void Control::Impl::RegisterVisual( Property::Index index, Toolkit::Visual::Base& visual, bool enabled )
397 {
398   RegisterVisual( index, visual, ( enabled ? VisualState::ENABLED : VisualState::DISABLED ), DepthIndexValue::NOT_SET );
399 }
400
401 void Control::Impl::RegisterVisual( Property::Index index, Toolkit::Visual::Base& visual, bool enabled, int depthIndex )
402 {
403   RegisterVisual( index, visual, ( enabled ? VisualState::ENABLED : VisualState::DISABLED ), DepthIndexValue::SET, depthIndex );
404 }
405
406 void Control::Impl::RegisterVisual( Property::Index index, Toolkit::Visual::Base& visual, VisualState::Type enabled, DepthIndexValue::Type depthIndexValueSet, int depthIndex )
407 {
408   DALI_LOG_INFO( gLogFilter, Debug::Concise, "RegisterVisual:%d \n", index );
409
410   bool visualReplaced ( false );
411   Actor self = mControlImpl.Self();
412
413   // Set the depth index, if not set by caller this will be either the current visual depth, max depth of all visuals
414   // or zero.
415   int requiredDepthIndex = visual.GetDepthIndex();
416
417   if( depthIndexValueSet == DepthIndexValue::SET )
418   {
419     requiredDepthIndex = depthIndex;
420   }
421
422   // Visual replacement, existing visual should only be removed from stage when replacement ready.
423   if( !mVisuals.Empty() )
424   {
425     RegisteredVisualContainer::Iterator registeredVisualsiter;
426     // Check if visual (index) is already registered, this is the current visual.
427     if( FindVisual( index, mVisuals, registeredVisualsiter ) )
428     {
429       Toolkit::Visual::Base& currentRegisteredVisual = (*registeredVisualsiter)->visual;
430       if( currentRegisteredVisual )
431       {
432         // Store current visual depth index as may need to set the replacement visual to same depth
433         const int currentDepthIndex = (*registeredVisualsiter)->visual.GetDepthIndex();
434
435         // No longer required to know if the replaced visual's resources are ready
436         StopObservingVisual( currentRegisteredVisual );
437
438         // If control staged and visual enabled then visuals will be swapped once ready
439         if(  self.OnStage() && enabled )
440         {
441           // Check if visual is currently in the process of being replaced ( is in removal container )
442           RegisteredVisualContainer::Iterator visualQueuedForRemoval;
443           if ( FindVisual( index, mRemoveVisuals, visualQueuedForRemoval ) )
444           {
445             // Visual with same index is already in removal container so current visual pending
446             // Only the the last requested visual will be displayed so remove current visual which is staged but not ready.
447             Toolkit::GetImplementation( currentRegisteredVisual ).SetOffStage( self );
448             mVisuals.Erase( registeredVisualsiter );
449           }
450           else
451           {
452             // current visual not already in removal container so add now.
453             DALI_LOG_INFO( gLogFilter, Debug::Verbose, "RegisterVisual Move current registered visual to removal Queue: %d \n", index );
454             MoveVisual( registeredVisualsiter, mVisuals, mRemoveVisuals );
455           }
456         }
457         else
458         {
459           // Control not staged or visual disabled so can just erase from registered visuals and new visual will be added later.
460           mVisuals.Erase( registeredVisualsiter );
461         }
462
463         // 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
464         if( ( depthIndexValueSet == DepthIndexValue::NOT_SET ) &&
465             ( visual.GetDepthIndex() == 0 ) )
466         {
467           requiredDepthIndex = currentDepthIndex;
468         }
469       }
470
471       visualReplaced = true;
472     }
473   }
474
475   // If not set, set the name of the visual to the same name as the control's property.
476   // ( If the control has been type registered )
477   if( visual.GetName().empty() )
478   {
479     // returns empty string if index is not found as long as index is not -1
480     std::string visualName = self.GetPropertyName( index );
481     if( !visualName.empty() )
482     {
483       DALI_LOG_INFO( gLogFilter, Debug::Concise, "Setting visual name for property %d to %s\n",
484                      index, visualName.c_str() );
485       visual.SetName( visualName );
486     }
487   }
488
489   if( !visualReplaced ) // New registration entry
490   {
491     // 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
492     if( ( depthIndexValueSet == DepthIndexValue::NOT_SET ) &&
493         ( mVisuals.Size() > 0 ) &&
494         ( visual.GetDepthIndex() == 0 ) )
495     {
496       int maxDepthIndex = std::numeric_limits< int >::min();
497
498       RegisteredVisualContainer::ConstIterator iter;
499       const RegisteredVisualContainer::ConstIterator endIter = mVisuals.End();
500       for ( iter = mVisuals.Begin(); iter != endIter; iter++ )
501       {
502         const int visualDepthIndex = (*iter)->visual.GetDepthIndex();
503         if ( visualDepthIndex > maxDepthIndex )
504         {
505           maxDepthIndex = visualDepthIndex;
506         }
507       }
508       ++maxDepthIndex; // Add one to the current maximum depth index so that our added visual appears on top
509       requiredDepthIndex = std::max( 0, maxDepthIndex ); // Start at zero if maxDepth index belongs to a background
510     }
511   }
512
513   if( visual )
514   {
515     // Set determined depth index
516     visual.SetDepthIndex( requiredDepthIndex );
517
518     // Monitor when the visual resources are ready
519     StartObservingVisual( visual );
520
521     DALI_LOG_INFO( gLogFilter, Debug::Concise, "New Visual registration index[%d] depth[%d]\n", index, requiredDepthIndex );
522     RegisteredVisual* newRegisteredVisual  = new RegisteredVisual( index, visual,
523                                              ( enabled == VisualState::ENABLED ? true : false ),
524                                              ( visualReplaced && enabled ) ) ;
525     mVisuals.PushBack( newRegisteredVisual );
526
527     Internal::Visual::Base& visualImpl = Toolkit::GetImplementation( visual );
528     // Put on stage if enabled and the control is already on the stage
529     if( ( enabled == VisualState::ENABLED ) && self.OnStage() )
530     {
531       visualImpl.SetOnStage( self );
532     }
533     else if( visualImpl.IsResourceReady() ) // When not being staged, check if visual already 'ResourceReady' before it was Registered. ( Resource may have been loaded already )
534     {
535       ResourceReady( visualImpl );
536     }
537
538   }
539
540   DALI_LOG_INFO( gLogFilter, Debug::Verbose, "Control::RegisterVisual() Registered %s(%d), enabled:%s\n",  visual.GetName().c_str(), index, enabled?"true":"false" );
541 }
542
543 void Control::Impl::UnregisterVisual( Property::Index index )
544 {
545   RegisteredVisualContainer::Iterator iter;
546   if ( FindVisual( index, mVisuals, iter ) )
547   {
548     // stop observing visual
549     StopObservingVisual( (*iter)->visual );
550
551     Actor self( mControlImpl.Self() );
552     Toolkit::GetImplementation((*iter)->visual).SetOffStage( self );
553     (*iter)->visual.Reset();
554     mVisuals.Erase( iter );
555   }
556
557   if( FindVisual( index, mRemoveVisuals, iter ) )
558   {
559     Actor self( mControlImpl.Self() );
560     Toolkit::GetImplementation( (*iter)->visual ).SetOffStage( self );
561     (*iter)->pending = false;
562     (*iter)->visual.Reset();
563     mRemoveVisuals.Erase( iter );
564   }
565 }
566
567 Toolkit::Visual::Base Control::Impl::GetVisual( Property::Index index ) const
568 {
569   RegisteredVisualContainer::Iterator iter;
570   if ( FindVisual( index, mVisuals, iter ) )
571   {
572     return (*iter)->visual;
573   }
574
575   return Toolkit::Visual::Base();
576 }
577
578 void Control::Impl::EnableVisual( Property::Index index, bool enable )
579 {
580   DALI_LOG_INFO( gLogFilter, Debug::General, "Control::EnableVisual(%d, %s)\n", index, enable?"T":"F");
581
582   RegisteredVisualContainer::Iterator iter;
583   if ( FindVisual( index, mVisuals, iter ) )
584   {
585     if (  (*iter)->enabled == enable )
586     {
587       DALI_LOG_INFO( gLogFilter, Debug::Verbose, "Control::EnableVisual Visual %s(%d) already %s\n", (*iter)->visual.GetName().c_str(), index, enable?"enabled":"disabled");
588       return;
589     }
590
591     (*iter)->enabled = enable;
592     Actor parentActor = mControlImpl.Self();
593     if ( mControlImpl.Self().OnStage() ) // If control not on Stage then Visual will be added when StageConnection is called.
594     {
595       if ( enable )
596       {
597         DALI_LOG_INFO( gLogFilter, Debug::Verbose, "Control::EnableVisual Setting %s(%d) on stage \n", (*iter)->visual.GetName().c_str(), index );
598         Toolkit::GetImplementation((*iter)->visual).SetOnStage( parentActor );
599       }
600       else
601       {
602         DALI_LOG_INFO( gLogFilter, Debug::Verbose, "Control::EnableVisual Setting %s(%d) off stage \n", (*iter)->visual.GetName().c_str(), index );
603         Toolkit::GetImplementation((*iter)->visual).SetOffStage( parentActor );  // No need to call if control not staged.
604       }
605     }
606   }
607   else
608   {
609     DALI_LOG_WARNING( "Control::EnableVisual(%d, %s) FAILED - NO SUCH VISUAL\n", index, enable?"T":"F" );
610   }
611 }
612
613 bool Control::Impl::IsVisualEnabled( Property::Index index ) const
614 {
615   RegisteredVisualContainer::Iterator iter;
616   if ( FindVisual( index, mVisuals, iter ) )
617   {
618     return (*iter)->enabled;
619   }
620   return false;
621 }
622
623 void Control::Impl::StopObservingVisual( Toolkit::Visual::Base& visual )
624 {
625   Internal::Visual::Base& visualImpl = Toolkit::GetImplementation( visual );
626
627   // Stop observing the visual
628   visualImpl.RemoveEventObserver( *this );
629 }
630
631 void Control::Impl::StartObservingVisual( Toolkit::Visual::Base& visual)
632 {
633   Internal::Visual::Base& visualImpl = Toolkit::GetImplementation( visual );
634
635   // start observing the visual for events
636   visualImpl.AddEventObserver( *this );
637 }
638
639 // Called by a Visual when it's resource is ready
640 void Control::Impl::ResourceReady( Visual::Base& object)
641 {
642   DALI_LOG_INFO( gLogFilter, Debug::Verbose, "Control::Impl::ResourceReady() replacements pending[%d]\n", mRemoveVisuals.Count() );
643
644   Actor self = mControlImpl.Self();
645
646   // A resource is ready, find resource in the registered visuals container and get its index
647   for( auto registeredIter = mVisuals.Begin(),  end = mVisuals.End(); registeredIter != end; ++registeredIter )
648   {
649     Internal::Visual::Base& registeredVisualImpl = Toolkit::GetImplementation( (*registeredIter)->visual );
650
651     if( &object == &registeredVisualImpl )
652     {
653       RegisteredVisualContainer::Iterator visualToRemoveIter;
654       // Find visual with the same index in the removal container
655       // Set if off stage as it's replacement is now ready.
656       // Remove if from removal list as now removed from stage.
657       // Set Pending flag on the ready visual to false as now ready.
658       if( FindVisual( (*registeredIter)->index, mRemoveVisuals, visualToRemoveIter ) )
659       {
660         (*registeredIter)->pending = false;
661         Toolkit::GetImplementation( (*visualToRemoveIter)->visual ).SetOffStage( self );
662         mRemoveVisuals.Erase( visualToRemoveIter );
663       }
664       break;
665     }
666   }
667
668   // A visual is ready so control may need relayouting if staged
669   if ( self.OnStage() )
670   {
671     mControlImpl.RelayoutRequest();
672   }
673
674   // Emit signal if all enabled visuals registered by the control are ready.
675   if( IsResourceReady() )
676   {
677     Dali::Toolkit::Control handle( mControlImpl.GetOwner() );
678     mResourceReadySignal.Emit( handle );
679   }
680 }
681
682 void Control::Impl::NotifyVisualEvent( Visual::Base& object, Property::Index signalId )
683 {
684   for( auto registeredIter = mVisuals.Begin(),  end = mVisuals.End(); registeredIter != end; ++registeredIter )
685   {
686     Internal::Visual::Base& registeredVisualImpl = Toolkit::GetImplementation( (*registeredIter)->visual );
687     if( &object == &registeredVisualImpl )
688     {
689       Dali::Toolkit::Control handle( mControlImpl.GetOwner() );
690       mVisualEventSignal.Emit( handle, (*registeredIter)->index, signalId );
691       break;
692     }
693   }
694 }
695
696 bool Control::Impl::IsResourceReady() const
697 {
698   // Iterate through and check all the enabled visuals are ready
699   for( auto visualIter = mVisuals.Begin();
700          visualIter != mVisuals.End(); ++visualIter )
701   {
702     const Toolkit::Visual::Base visual = (*visualIter)->visual;
703     const Internal::Visual::Base& visualImpl = Toolkit::GetImplementation( visual );
704
705     // one of the enabled visuals is not ready
706     if( !visualImpl.IsResourceReady() && (*visualIter)->enabled )
707     {
708       return false;
709     }
710   }
711   return true;
712 }
713
714 Toolkit::Visual::ResourceStatus Control::Impl::GetVisualResourceStatus( Property::Index index ) const
715 {
716   RegisteredVisualContainer::Iterator iter;
717   if ( FindVisual( index, mVisuals, iter ) )
718   {
719     const Toolkit::Visual::Base visual = (*iter)->visual;
720     const Internal::Visual::Base& visualImpl = Toolkit::GetImplementation( visual );
721     return visualImpl.GetResourceStatus( );
722   }
723
724   return Toolkit::Visual::ResourceStatus::PREPARING;
725 }
726
727
728
729 void Control::Impl::AddTransitions( Dali::Animation& animation,
730                                     const Toolkit::TransitionData& handle,
731                                     bool createAnimation )
732 {
733   // Setup a Transition from TransitionData.
734   const Internal::TransitionData& transitionData = Toolkit::GetImplementation( handle );
735   TransitionData::Iterator end = transitionData.End();
736   for( TransitionData::Iterator iter = transitionData.Begin() ;
737        iter != end; ++iter )
738   {
739     TransitionData::Animator* animator = (*iter);
740
741     Toolkit::Visual::Base visual = GetVisualByName( mVisuals, animator->objectName );
742
743     if( visual )
744     {
745 #if defined(DEBUG_ENABLED)
746       Dali::TypeInfo typeInfo;
747       ControlWrapper* controlWrapperImpl = dynamic_cast<ControlWrapper*>(&mControlImpl);
748       if( controlWrapperImpl )
749       {
750         typeInfo = controlWrapperImpl->GetTypeInfo();
751       }
752
753       DALI_LOG_INFO( gLogFilter, Debug::Concise, "CreateTransition: Found %s visual for %s\n",
754                      visual.GetName().c_str(), typeInfo?typeInfo.GetName().c_str():"Unknown" );
755 #endif
756       Internal::Visual::Base& visualImpl = Toolkit::GetImplementation( visual );
757       visualImpl.AnimateProperty( animation, *animator );
758     }
759     else
760     {
761       DALI_LOG_INFO( gLogFilter, Debug::Concise, "CreateTransition: Could not find visual. Trying actors");
762       // Otherwise, try any actor children of control (Including the control)
763       Actor child = mControlImpl.Self().FindChildByName( animator->objectName );
764       if( child )
765       {
766         Property::Index propertyIndex = DevelHandle::GetPropertyIndex( child, animator->propertyKey );
767         if( propertyIndex != Property::INVALID_INDEX )
768         {
769           if( animator->animate == false )
770           {
771             if( animator->targetValue.GetType() != Property::NONE )
772             {
773               child.SetProperty( propertyIndex, animator->targetValue );
774             }
775           }
776           else // animate the property
777           {
778             if( animator->initialValue.GetType() != Property::NONE )
779             {
780               child.SetProperty( propertyIndex, animator->initialValue );
781             }
782
783             if( createAnimation && !animation )
784             {
785               animation = Dali::Animation::New( 0.1f );
786             }
787
788             animation.AnimateTo( Property( child, propertyIndex ),
789                                  animator->targetValue,
790                                  animator->alphaFunction,
791                                  TimePeriod( animator->timePeriodDelay,
792                                              animator->timePeriodDuration ) );
793           }
794         }
795       }
796     }
797   }
798 }
799
800 Dali::Animation Control::Impl::CreateTransition( const Toolkit::TransitionData& transitionData )
801 {
802   Dali::Animation transition;
803
804   if( transitionData.Count() > 0 )
805   {
806     AddTransitions( transition, transitionData, true );
807   }
808   return transition;
809 }
810
811
812
813 void Control::Impl::DoAction( Dali::Property::Index visualIndex, Dali::Property::Index actionId, const Dali::Property::Value attributes )
814 {
815   RegisteredVisualContainer::Iterator iter;
816   if ( FindVisual( visualIndex, mVisuals, iter ) )
817   {
818     Toolkit::GetImplementation((*iter)->visual).DoAction( actionId, attributes );
819   }
820 }
821
822 void Control::Impl::SetProperty( BaseObject* object, Property::Index index, const Property::Value& value )
823 {
824   Toolkit::Control control = Toolkit::Control::DownCast( BaseHandle( object ) );
825
826   if ( control )
827   {
828     Control& controlImpl( GetImplementation( control ) );
829
830     switch ( index )
831     {
832       case Toolkit::Control::Property::STYLE_NAME:
833       {
834         controlImpl.SetStyleName( value.Get< std::string >() );
835         break;
836       }
837
838       case Toolkit::DevelControl::Property::STATE:
839       {
840         bool withTransitions=true;
841         const Property::Value* valuePtr=&value;
842         Property::Map* map = value.GetMap();
843         if(map)
844         {
845           Property::Value* value2 = map->Find("withTransitions");
846           if( value2 )
847           {
848             withTransitions = value2->Get<bool>();
849           }
850
851           valuePtr = map->Find("state");
852         }
853
854         if( valuePtr )
855         {
856           Toolkit::DevelControl::State state( controlImpl.mImpl->mState );
857           if( Scripting::GetEnumerationProperty< Toolkit::DevelControl::State >( *valuePtr, ControlStateTable, ControlStateTableCount, state ) )
858           {
859             controlImpl.mImpl->SetState( state, withTransitions );
860           }
861         }
862       }
863       break;
864
865       case Toolkit::DevelControl::Property::SUB_STATE:
866       {
867         std::string subState;
868         if( value.Get( subState ) )
869         {
870           controlImpl.mImpl->SetSubState( subState );
871         }
872       }
873       break;
874
875       case Toolkit::DevelControl::Property::LEFT_FOCUSABLE_ACTOR_ID:
876       {
877         int focusId;
878         if( value.Get( focusId ) )
879         {
880           controlImpl.mImpl->mLeftFocusableActorId = focusId;
881         }
882       }
883       break;
884
885       case Toolkit::DevelControl::Property::RIGHT_FOCUSABLE_ACTOR_ID:
886       {
887         int focusId;
888         if( value.Get( focusId ) )
889         {
890           controlImpl.mImpl->mRightFocusableActorId = focusId;
891         }
892       }
893       break;
894
895       case Toolkit::DevelControl::Property::UP_FOCUSABLE_ACTOR_ID:
896       {
897         int focusId;
898         if( value.Get( focusId ) )
899         {
900           controlImpl.mImpl->mUpFocusableActorId = focusId;
901         }
902       }
903       break;
904
905       case Toolkit::DevelControl::Property::DOWN_FOCUSABLE_ACTOR_ID:
906       {
907         int focusId;
908         if( value.Get( focusId ) )
909         {
910           controlImpl.mImpl->mDownFocusableActorId = focusId;
911         }
912       }
913       break;
914
915       case Toolkit::Control::Property::KEY_INPUT_FOCUS:
916       {
917         if ( value.Get< bool >() )
918         {
919           controlImpl.SetKeyInputFocus();
920         }
921         else
922         {
923           controlImpl.ClearKeyInputFocus();
924         }
925         break;
926       }
927
928       case Toolkit::Control::Property::BACKGROUND:
929       {
930         std::string url;
931         Vector4 color;
932         const Property::Map* map = value.GetMap();
933         if( map && !map->Empty() )
934         {
935           controlImpl.SetBackground( *map );
936         }
937         else if( value.Get( url ) )
938         {
939           // don't know the size to load
940           Toolkit::Visual::Base visual = Toolkit::VisualFactory::Get().CreateVisual( url, ImageDimensions() );
941           if( visual )
942           {
943             controlImpl.mImpl->RegisterVisual( Toolkit::Control::Property::BACKGROUND, visual, DepthIndex::BACKGROUND );
944           }
945         }
946         else if( value.Get( color ) )
947         {
948           controlImpl.SetBackgroundColor(color);
949         }
950         else
951         {
952           // The background is an empty property map, so we should clear the background
953           controlImpl.ClearBackground();
954         }
955         break;
956       }
957
958       case Toolkit::Control::Property::MARGIN:
959       {
960         Extents margin;
961         if( value.Get( margin ) )
962         {
963           controlImpl.mImpl->SetMargin( margin );
964         }
965         break;
966       }
967
968       case Toolkit::Control::Property::PADDING:
969       {
970         Extents padding;
971         if( value.Get( padding ) )
972         {
973           controlImpl.mImpl->SetPadding( padding );
974         }
975         break;
976       }
977
978       case Toolkit::DevelControl::Property::TOOLTIP:
979       {
980         TooltipPtr& tooltipPtr = controlImpl.mImpl->mTooltip;
981         if( ! tooltipPtr )
982         {
983           tooltipPtr = Tooltip::New( control );
984         }
985         tooltipPtr->SetProperties( value );
986         break;
987       }
988
989       case Toolkit::DevelControl::Property::SHADOW:
990       {
991         const Property::Map* map = value.GetMap();
992         if( map && !map->Empty() )
993         {
994           controlImpl.mImpl->SetShadow( *map );
995         }
996         else
997         {
998           // The shadow is an empty property map, so we should clear the shadow
999           controlImpl.mImpl->ClearShadow();
1000         }
1001         break;
1002       }
1003
1004     }
1005   }
1006 }
1007
1008 Property::Value Control::Impl::GetProperty( BaseObject* object, Property::Index index )
1009 {
1010   Property::Value value;
1011
1012   Toolkit::Control control = Toolkit::Control::DownCast( BaseHandle( object ) );
1013
1014   if ( control )
1015   {
1016     Control& controlImpl( GetImplementation( control ) );
1017
1018     switch ( index )
1019     {
1020       case Toolkit::Control::Property::STYLE_NAME:
1021       {
1022         value = controlImpl.GetStyleName();
1023         break;
1024       }
1025
1026       case Toolkit::DevelControl::Property::STATE:
1027       {
1028         value = controlImpl.mImpl->mState;
1029         break;
1030       }
1031
1032       case Toolkit::DevelControl::Property::SUB_STATE:
1033       {
1034         value = controlImpl.mImpl->mSubStateName;
1035         break;
1036       }
1037
1038       case Toolkit::DevelControl::Property::LEFT_FOCUSABLE_ACTOR_ID:
1039       {
1040         value = controlImpl.mImpl->mLeftFocusableActorId;
1041         break;
1042       }
1043
1044       case Toolkit::DevelControl::Property::RIGHT_FOCUSABLE_ACTOR_ID:
1045       {
1046         value = controlImpl.mImpl->mRightFocusableActorId;
1047         break;
1048       }
1049
1050       case Toolkit::DevelControl::Property::UP_FOCUSABLE_ACTOR_ID:
1051       {
1052         value = controlImpl.mImpl->mUpFocusableActorId;
1053         break;
1054       }
1055
1056       case Toolkit::DevelControl::Property::DOWN_FOCUSABLE_ACTOR_ID:
1057       {
1058         value = controlImpl.mImpl->mDownFocusableActorId;
1059         break;
1060       }
1061
1062       case Toolkit::Control::Property::KEY_INPUT_FOCUS:
1063       {
1064         value = controlImpl.HasKeyInputFocus();
1065         break;
1066       }
1067
1068       case Toolkit::Control::Property::BACKGROUND:
1069       {
1070         Property::Map map;
1071         Toolkit::Visual::Base visual = controlImpl.mImpl->GetVisual( Toolkit::Control::Property::BACKGROUND );
1072         if( visual )
1073         {
1074           visual.CreatePropertyMap( map );
1075         }
1076
1077         value = map;
1078         break;
1079       }
1080
1081       case Toolkit::Control::Property::MARGIN:
1082       {
1083         value = controlImpl.mImpl->GetMargin();
1084         break;
1085       }
1086
1087       case Toolkit::Control::Property::PADDING:
1088       {
1089         value = controlImpl.mImpl->GetPadding();
1090         break;
1091       }
1092
1093       case Toolkit::DevelControl::Property::TOOLTIP:
1094       {
1095         Property::Map map;
1096         if( controlImpl.mImpl->mTooltip )
1097         {
1098           controlImpl.mImpl->mTooltip->CreatePropertyMap( map );
1099         }
1100         value = map;
1101         break;
1102       }
1103
1104       case Toolkit::DevelControl::Property::SHADOW:
1105       {
1106         Property::Map map;
1107         Toolkit::Visual::Base visual = controlImpl.mImpl->GetVisual( Toolkit::DevelControl::Property::SHADOW );
1108         if( visual )
1109         {
1110           visual.CreatePropertyMap( map );
1111         }
1112
1113         value = map;
1114         break;
1115       }
1116     }
1117   }
1118
1119   return value;
1120 }
1121
1122
1123 void  Control::Impl::CopyInstancedProperties( RegisteredVisualContainer& visuals, Dictionary<Property::Map>& instancedProperties )
1124 {
1125   for(RegisteredVisualContainer::Iterator iter = visuals.Begin(); iter!= visuals.End(); iter++)
1126   {
1127     if( (*iter)->visual )
1128     {
1129       Property::Map instanceMap;
1130       Toolkit::GetImplementation((*iter)->visual).CreateInstancePropertyMap(instanceMap);
1131       instancedProperties.Add( (*iter)->visual.GetName(), instanceMap );
1132     }
1133   }
1134 }
1135
1136
1137 void Control::Impl::RemoveVisual( RegisteredVisualContainer& visuals, const std::string& visualName )
1138 {
1139   Actor self( mControlImpl.Self() );
1140
1141   for ( RegisteredVisualContainer::Iterator visualIter = visuals.Begin();
1142         visualIter != visuals.End(); ++visualIter )
1143   {
1144     Toolkit::Visual::Base visual = (*visualIter)->visual;
1145     if( visual && visual.GetName() == visualName )
1146     {
1147       Toolkit::GetImplementation(visual).SetOffStage( self );
1148       (*visualIter)->visual.Reset();
1149       visuals.Erase( visualIter );
1150       break;
1151     }
1152   }
1153 }
1154
1155 void Control::Impl::RemoveVisuals( RegisteredVisualContainer& visuals, DictionaryKeys& removeVisuals )
1156 {
1157   Actor self( mControlImpl.Self() );
1158   for( DictionaryKeys::iterator iter = removeVisuals.begin(); iter != removeVisuals.end(); ++iter )
1159   {
1160     const std::string visualName = *iter;
1161     RemoveVisual( visuals, visualName );
1162   }
1163 }
1164
1165 void Control::Impl::RecreateChangedVisuals( Dictionary<Property::Map>& stateVisualsToChange,
1166                              Dictionary<Property::Map>& instancedProperties )
1167 {
1168   Dali::CustomActor handle( mControlImpl.GetOwner() );
1169   for( Dictionary<Property::Map>::iterator iter = stateVisualsToChange.Begin();
1170        iter != stateVisualsToChange.End(); ++iter )
1171   {
1172     const std::string& visualName = (*iter).key;
1173     const Property::Map& toMap = (*iter).entry;
1174
1175     // is it a candidate for re-creation?
1176     bool recreate = false;
1177
1178     Toolkit::Visual::Base visual = GetVisualByName( mVisuals, visualName );
1179     if( visual )
1180     {
1181       Property::Map fromMap;
1182       visual.CreatePropertyMap( fromMap );
1183
1184       Toolkit::Visual::Type fromType = GetVisualTypeFromMap( fromMap );
1185       Toolkit::Visual::Type toType = GetVisualTypeFromMap( toMap );
1186
1187       if( fromType != toType )
1188       {
1189         recreate = true;
1190       }
1191       else
1192       {
1193         if( fromType == Toolkit::Visual::IMAGE || fromType == Toolkit::Visual::N_PATCH
1194             || fromType == Toolkit::Visual::SVG || fromType == Toolkit::Visual::ANIMATED_IMAGE )
1195         {
1196           Property::Value* fromUrl = fromMap.Find( Toolkit::ImageVisual::Property::URL, IMAGE_URL_NAME );
1197           Property::Value* toUrl = toMap.Find( Toolkit::ImageVisual::Property::URL, IMAGE_URL_NAME );
1198
1199           if( fromUrl && toUrl )
1200           {
1201             std::string fromUrlString;
1202             std::string toUrlString;
1203             fromUrl->Get(fromUrlString);
1204             toUrl->Get(toUrlString);
1205
1206             if( fromUrlString != toUrlString )
1207             {
1208               recreate = true;
1209             }
1210           }
1211         }
1212       }
1213
1214       const Property::Map* instancedMap = instancedProperties.FindConst( visualName );
1215       if( recreate || instancedMap )
1216       {
1217         RemoveVisual( mVisuals, visualName );
1218         Style::ApplyVisual( handle, visualName, toMap, instancedMap );
1219       }
1220       else
1221       {
1222         // @todo check to see if we can apply toMap without recreating the visual
1223         // e.g. by setting only animatable properties
1224         // For now, recreate all visuals, but merge in instance data.
1225         RemoveVisual( mVisuals, visualName );
1226         Style::ApplyVisual( handle, visualName, toMap, instancedMap );
1227       }
1228     }
1229   }
1230 }
1231
1232 void Control::Impl::ReplaceStateVisualsAndProperties( const StylePtr oldState, const StylePtr newState, const std::string& subState )
1233 {
1234   // Collect all old visual names
1235   DictionaryKeys stateVisualsToRemove;
1236   if( oldState )
1237   {
1238     oldState->visuals.GetKeys( stateVisualsToRemove );
1239     if( ! subState.empty() )
1240     {
1241       const StylePtr* oldSubState = oldState->subStates.FindConst(subState);
1242       if( oldSubState )
1243       {
1244         DictionaryKeys subStateVisualsToRemove;
1245         (*oldSubState)->visuals.GetKeys( subStateVisualsToRemove );
1246         Merge( stateVisualsToRemove, subStateVisualsToRemove );
1247       }
1248     }
1249   }
1250
1251   // Collect all new visual properties
1252   Dictionary<Property::Map> stateVisualsToAdd;
1253   if( newState )
1254   {
1255     stateVisualsToAdd = newState->visuals;
1256     if( ! subState.empty() )
1257     {
1258       const StylePtr* newSubState = newState->subStates.FindConst(subState);
1259       if( newSubState )
1260       {
1261         stateVisualsToAdd.Merge( (*newSubState)->visuals );
1262       }
1263     }
1264   }
1265
1266   // If a name is in both add/remove, move it to change list.
1267   Dictionary<Property::Map> stateVisualsToChange;
1268   FindChangableVisuals( stateVisualsToAdd, stateVisualsToChange, stateVisualsToRemove);
1269
1270   // Copy instanced properties (e.g. text label) of current visuals
1271   Dictionary<Property::Map> instancedProperties;
1272   CopyInstancedProperties( mVisuals, instancedProperties );
1273
1274   // For each visual in remove list, remove from mVisuals
1275   RemoveVisuals( mVisuals, stateVisualsToRemove );
1276
1277   // For each visual in add list, create and add to mVisuals
1278   Dali::CustomActor handle( mControlImpl.GetOwner() );
1279   Style::ApplyVisuals( handle, stateVisualsToAdd, instancedProperties );
1280
1281   // For each visual in change list, if it requires a new visual,
1282   // remove old visual, create and add to mVisuals
1283   RecreateChangedVisuals( stateVisualsToChange, instancedProperties );
1284 }
1285
1286 void Control::Impl::SetState( DevelControl::State newState, bool withTransitions )
1287 {
1288   DevelControl::State oldState = mState;
1289   Dali::CustomActor handle( mControlImpl.GetOwner() );
1290   DALI_LOG_INFO(gLogFilter, Debug::Concise, "Control::Impl::SetState: %s\n",
1291                 (mState == DevelControl::NORMAL ? "NORMAL" :(
1292                   mState == DevelControl::FOCUSED ?"FOCUSED" : (
1293                     mState == DevelControl::DISABLED?"DISABLED":"NONE" ))));
1294
1295   if( mState != newState )
1296   {
1297     // If mState was Disabled, and new state is Focused, should probably
1298     // store that fact, e.g. in another property that FocusManager can access.
1299     mState = newState;
1300
1301     // Trigger state change and transitions
1302     // Apply new style, if stylemanager is available
1303     Toolkit::StyleManager styleManager = Toolkit::StyleManager::Get();
1304     if( styleManager )
1305     {
1306       const StylePtr stylePtr = GetImpl( styleManager ).GetRecordedStyle( Toolkit::Control( mControlImpl.GetOwner() ) );
1307
1308       if( stylePtr )
1309       {
1310         std::string oldStateName = Scripting::GetEnumerationName< Toolkit::DevelControl::State >( oldState, ControlStateTable, ControlStateTableCount );
1311         std::string newStateName = Scripting::GetEnumerationName< Toolkit::DevelControl::State >( newState, ControlStateTable, ControlStateTableCount );
1312
1313         const StylePtr* newStateStyle = stylePtr->subStates.Find( newStateName );
1314         const StylePtr* oldStateStyle = stylePtr->subStates.Find( oldStateName );
1315         if( oldStateStyle && newStateStyle )
1316         {
1317           // Only change if both state styles exist
1318           ReplaceStateVisualsAndProperties( *oldStateStyle, *newStateStyle, mSubStateName );
1319         }
1320       }
1321     }
1322   }
1323 }
1324
1325 void Control::Impl::SetSubState( const std::string& subStateName, bool withTransitions )
1326 {
1327   if( mSubStateName != subStateName )
1328   {
1329     // Get existing sub-state visuals, and unregister them
1330     Dali::CustomActor handle( mControlImpl.GetOwner() );
1331
1332     Toolkit::StyleManager styleManager = Toolkit::StyleManager::Get();
1333     if( styleManager )
1334     {
1335       const StylePtr stylePtr = GetImpl( styleManager ).GetRecordedStyle( Toolkit::Control( mControlImpl.GetOwner() ) );
1336       if( stylePtr )
1337       {
1338         // Stringify state
1339         std::string stateName = Scripting::GetEnumerationName< Toolkit::DevelControl::State >( mState, ControlStateTable, ControlStateTableCount );
1340
1341         const StylePtr* state = stylePtr->subStates.Find( stateName );
1342         if( state )
1343         {
1344           StylePtr stateStyle(*state);
1345
1346           const StylePtr* newStateStyle = stateStyle->subStates.Find( subStateName );
1347           const StylePtr* oldStateStyle = stateStyle->subStates.Find( mSubStateName );
1348           if( oldStateStyle && newStateStyle )
1349           {
1350             std::string empty;
1351             ReplaceStateVisualsAndProperties( *oldStateStyle, *newStateStyle, empty );
1352           }
1353         }
1354       }
1355     }
1356
1357     mSubStateName = subStateName;
1358   }
1359 }
1360
1361 void Control::Impl::OnStageDisconnection()
1362 {
1363   Actor self = mControlImpl.Self();
1364
1365   // Any visuals set for replacement but not yet ready should still be registered.
1366   // Reason: If a request was made to register a new visual but the control removed from stage before visual was ready
1367   // then when this control appears back on stage it should use that new visual.
1368
1369   // Iterate through all registered visuals and set off stage
1370   SetVisualsOffStage( mVisuals, self );
1371
1372   // Visuals pending replacement can now be taken out of the removal list and set off stage
1373   // Iterate through all replacement visuals and add to a move queue then set off stage
1374   for( auto removalIter = mRemoveVisuals.Begin(), end = mRemoveVisuals.End(); removalIter != end; removalIter++ )
1375   {
1376     Toolkit::GetImplementation((*removalIter)->visual).SetOffStage( self );
1377   }
1378
1379   for( auto replacedIter = mVisuals.Begin(), end = mVisuals.End(); replacedIter != end; replacedIter++ )
1380   {
1381     (*replacedIter)->pending = false;
1382   }
1383
1384   mRemoveVisuals.Clear();
1385 }
1386
1387 void Control::Impl::SetMargin( Extents margin )
1388 {
1389   mControlImpl.mImpl->mMargin = margin;
1390
1391   // Trigger a size negotiation request that may be needed when setting a margin.
1392   mControlImpl.RelayoutRequest();
1393 }
1394
1395 Extents Control::Impl::GetMargin() const
1396 {
1397   return mControlImpl.mImpl->mMargin;
1398 }
1399
1400 void Control::Impl::SetPadding( Extents padding )
1401 {
1402   mControlImpl.mImpl->mPadding = padding;
1403
1404   // Trigger a size negotiation request that may be needed when setting a padding.
1405   mControlImpl.RelayoutRequest();
1406 }
1407
1408 Extents Control::Impl::GetPadding() const
1409 {
1410   return mControlImpl.mImpl->mPadding;
1411 }
1412
1413 void Control::Impl::SetInputMethodContext( InputMethodContext& inputMethodContext )
1414 {
1415   mInputMethodContext = inputMethodContext;
1416 }
1417
1418 bool Control::Impl::FilterKeyEvent( const KeyEvent& event )
1419 {
1420   bool consumed ( false );
1421
1422   if ( mInputMethodContext )
1423   {
1424     consumed = mInputMethodContext.FilterEventKey( event );
1425   }
1426   return consumed;
1427 }
1428
1429 DevelControl::VisualEventSignalType& Control::Impl::VisualEventSignal()
1430 {
1431   return mVisualEventSignal;
1432 }
1433
1434 void Control::Impl::SetShadow( const Property::Map& map )
1435 {
1436   Toolkit::Visual::Base visual = Toolkit::VisualFactory::Get().CreateVisual( map );
1437   visual.SetName("shadow");
1438
1439   if( visual )
1440   {
1441     mControlImpl.mImpl->RegisterVisual( Toolkit::DevelControl::Property::SHADOW, visual, DepthIndex::BACKGROUND_EFFECT );
1442
1443     mControlImpl.RelayoutRequest();
1444   }
1445 }
1446
1447 void Control::Impl::ClearShadow()
1448 {
1449    mControlImpl.mImpl->UnregisterVisual( Toolkit::DevelControl::Property::SHADOW );
1450
1451    // Trigger a size negotiation request that may be needed when unregistering a visual.
1452    mControlImpl.RelayoutRequest();
1453 }
1454
1455 void Control::Impl::SetAutofillEnabled( bool autofillEnabled )
1456 {
1457   mIsAutofillEnabled = autofillEnabled;
1458 }
1459
1460 bool Control::Impl::IsAutofillEnabled()
1461 {
1462   return mIsAutofillEnabled;
1463 }
1464
1465 void Control::Impl::SetAutofillItemHandle( Dali::AutofillItem item )
1466 {
1467   mAutofillItem = item;
1468 }
1469
1470 Dali::AutofillItem Control::Impl::GetAutofillItemHandle()
1471 {
1472   return mAutofillItem;
1473 }
1474
1475 void Control::Impl::SetAutofillContainer( Toolkit::AutofillContainer container )
1476 {
1477   mAutofillContainer = container;
1478 }
1479
1480 Toolkit::AutofillContainer Control::Impl::GetAutofillContainer()
1481 {
1482   return mAutofillContainer;
1483 }
1484
1485 } // namespace Internal
1486
1487 } // namespace Toolkit
1488
1489 } // namespace Dali