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