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