Merge "fix ellipsis not working issue when the given width is too narrow" into devel...
[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 <dali/integration-api/adaptor-framework/adaptor.h>
30 #include <dali/devel-api/common/stage.h>
31 #include <dali-toolkit/public-api/controls/control.h>
32 #include <dali/public-api/object/object-registry.h>
33 #include <dali/devel-api/adaptor-framework/accessibility.h>
34 #include <dali-toolkit/public-api/controls/control-impl.h>
35 #include <dali/devel-api/actors/actor-devel.h>
36 #include <cstring>
37 #include <limits>
38
39 // INTERNAL INCLUDES
40 #include <dali-toolkit/internal/visuals/visual-base-impl.h>
41 #include <dali-toolkit/public-api/visuals/image-visual-properties.h>
42 #include <dali-toolkit/public-api/visuals/visual-properties.h>
43 #include <dali-toolkit/devel-api/controls/control-depth-index-ranges.h>
44 #include <dali-toolkit/devel-api/controls/control-devel.h>
45 #include <dali-toolkit/devel-api/controls/control-wrapper-impl.h>
46 #include <dali-toolkit/internal/styling/style-manager-impl.h>
47 #include <dali-toolkit/internal/visuals/visual-string-constants.h>
48 #include <dali-toolkit/public-api/focus-manager/keyboard-focus-manager.h>
49 #include <dali-toolkit/public-api/controls/image-view/image-view.h>
50 #include <dali-toolkit/devel-api/asset-manager/asset-manager.h>
51
52 namespace
53 {
54   const std::string READING_INFO_TYPE_NAME = "name";
55   const std::string READING_INFO_TYPE_ROLE = "role";
56   const std::string READING_INFO_TYPE_DESCRIPTION = "description";
57   const std::string READING_INFO_TYPE_STATE = "state";
58   const std::string READING_INFO_TYPE_ATTRIBUTE_NAME = "reading_info_type";
59   const std::string READING_INFO_TYPE_SEPARATOR = "|";
60 }
61
62 namespace Dali
63 {
64
65 namespace Toolkit
66 {
67
68 namespace Internal
69 {
70
71 extern const Dali::Scripting::StringEnum ControlStateTable[];
72 extern const unsigned int ControlStateTableCount;
73
74
75 // Not static or anonymous - shared with other translation units
76 const Scripting::StringEnum ControlStateTable[] = {
77   { "NORMAL",   Toolkit::DevelControl::NORMAL   },
78   { "FOCUSED",  Toolkit::DevelControl::FOCUSED  },
79   { "DISABLED", Toolkit::DevelControl::DISABLED },
80 };
81 const unsigned int ControlStateTableCount = sizeof( ControlStateTable ) / sizeof( ControlStateTable[0] );
82
83
84
85 namespace
86 {
87
88 #if defined(DEBUG_ENABLED)
89 Debug::Filter* gLogFilter = Debug::Filter::New( Debug::NoLogging, false, "LOG_CONTROL_VISUALS");
90 #endif
91
92
93 template<typename T>
94 void Remove( Dictionary<T>& keyValues, const std::string& name )
95 {
96   keyValues.Remove(name);
97 }
98
99 void Remove( DictionaryKeys& keys, const std::string& name )
100 {
101   DictionaryKeys::iterator iter = std::find( keys.begin(), keys.end(), name );
102   if( iter != keys.end())
103   {
104     keys.erase(iter);
105   }
106 }
107
108 /**
109  *  Finds visual in given array, returning true if found along with the iterator for that visual as a out parameter
110  */
111 bool FindVisual( Property::Index targetIndex, const RegisteredVisualContainer& visuals, RegisteredVisualContainer::Iterator& iter )
112 {
113   for ( iter = visuals.Begin(); iter != visuals.End(); iter++ )
114   {
115     if ( (*iter)->index ==  targetIndex )
116     {
117       return true;
118     }
119   }
120   return false;
121 }
122
123 /**
124  *  Finds visual in given array, returning true if found along with the iterator for that visual as a out parameter
125  */
126 bool FindVisual( std::string visualName, const RegisteredVisualContainer& visuals, RegisteredVisualContainer::Iterator& iter )
127 {
128   for ( iter = visuals.Begin(); iter != visuals.End(); iter++ )
129   {
130     Toolkit::Visual::Base visual = (*iter)->visual;
131     if( visual && visual.GetName() == visualName )
132     {
133       return true;
134     }
135   }
136   return false;
137 }
138
139 void FindChangableVisuals( Dictionary<Property::Map>& stateVisualsToAdd,
140                            Dictionary<Property::Map>& stateVisualsToChange,
141                            DictionaryKeys& stateVisualsToRemove)
142 {
143   DictionaryKeys copyOfStateVisualsToRemove = stateVisualsToRemove;
144
145   for( DictionaryKeys::iterator iter = copyOfStateVisualsToRemove.begin();
146        iter != copyOfStateVisualsToRemove.end(); ++iter )
147   {
148     const std::string& visualName = (*iter);
149     Property::Map* toMap = stateVisualsToAdd.Find( visualName );
150     if( toMap )
151     {
152       stateVisualsToChange.Add( visualName, *toMap );
153       stateVisualsToAdd.Remove( visualName );
154       Remove( stateVisualsToRemove, visualName );
155     }
156   }
157 }
158
159 Toolkit::Visual::Base GetVisualByName(
160   const RegisteredVisualContainer& visuals,
161   const std::string& visualName )
162 {
163   Toolkit::Visual::Base visualHandle;
164
165   RegisteredVisualContainer::Iterator iter;
166   for ( iter = visuals.Begin(); iter != visuals.End(); iter++ )
167   {
168     Toolkit::Visual::Base visual = (*iter)->visual;
169     if( visual && visual.GetName() == visualName )
170     {
171       visualHandle = visual;
172       break;
173     }
174   }
175   return visualHandle;
176 }
177
178 Toolkit::Visual::Base GetVisualByIndex(
179   const RegisteredVisualContainer& visuals,
180   Property::Index                  index)
181 {
182   Toolkit::Visual::Base visualHandle;
183
184   RegisteredVisualContainer::Iterator iter;
185   for(iter = visuals.Begin(); iter != visuals.End(); iter++)
186   {
187     if((*iter)->index == index)
188     {
189       visualHandle = (*iter)->visual;
190       break;
191     }
192   }
193   return visualHandle;
194 }
195
196 /**
197  * Move visual from source to destination container
198  */
199 void MoveVisual( RegisteredVisualContainer::Iterator sourceIter, RegisteredVisualContainer& source, RegisteredVisualContainer& destination )
200 {
201    Toolkit::Visual::Base visual = (*sourceIter)->visual;
202    if( visual )
203    {
204      RegisteredVisual* rv = source.Release( sourceIter );
205      destination.PushBack( rv );
206    }
207 }
208
209 /**
210  * Performs actions as requested using the action name.
211  * @param[in] object The object on which to perform the action.
212  * @param[in] actionName The action to perform.
213  * @param[in] attributes The attributes with which to perfrom this action.
214  * @return true if action has been accepted by this control
215  */
216 const char* ACTION_ACCESSIBILITY_ACTIVATED         = "accessibilityActivated";
217 const char* ACTION_ACCESSIBILITY_READING_CANCELLED = "ReadingCancelled";
218 const char* ACTION_ACCESSIBILITY_READING_PAUSED    = "ReadingPaused";
219 const char* ACTION_ACCESSIBILITY_READING_RESUMED   = "ReadingResumed";
220 const char* ACTION_ACCESSIBILITY_READING_SKIPPED   = "ReadingSkipped";
221 const char* ACTION_ACCESSIBILITY_READING_STOPPED   = "ReadingStopped";
222
223 static bool DoAction( BaseObject* object, const std::string& actionName, const Property::Map& attributes )
224 {
225   bool ret = true;
226
227   Dali::BaseHandle handle( object );
228
229   Toolkit::Control control = Toolkit::Control::DownCast( handle );
230
231   DALI_ASSERT_ALWAYS( control );
232
233   if( 0 == strcmp( actionName.c_str(), ACTION_ACCESSIBILITY_ACTIVATED ) ||
234      actionName == "activate" )
235   {
236     // if cast succeeds there is an implementation so no need to check
237     if( !DevelControl::AccessibilityActivateSignal( control ).Empty() )
238       DevelControl::AccessibilityActivateSignal( control ).Emit();
239     else ret = Internal::GetImplementation( control ).OnAccessibilityActivated();
240   }
241   else if( 0 == strcmp( actionName.c_str(), ACTION_ACCESSIBILITY_READING_SKIPPED ) )
242   {
243     // if cast succeeds there is an implementation so no need to check
244     if( !DevelControl::AccessibilityReadingSkippedSignal( control ).Empty() )
245       DevelControl::AccessibilityReadingSkippedSignal( control ).Emit();
246   }
247   else if( 0 == strcmp( actionName.c_str(), ACTION_ACCESSIBILITY_READING_PAUSED ) )
248   {
249     // if cast succeeds there is an implementation so no need to check
250     if( !DevelControl::AccessibilityReadingPausedSignal( control ).Empty() )
251       DevelControl::AccessibilityReadingPausedSignal( control ).Emit();
252   }
253   else if( 0 == strcmp( actionName.c_str(), ACTION_ACCESSIBILITY_READING_RESUMED ) )
254   {
255     // if cast succeeds there is an implementation so no need to check
256     if( !DevelControl::AccessibilityReadingResumedSignal( control ).Empty() )
257       DevelControl::AccessibilityReadingResumedSignal( control ).Emit();
258   }
259   else if( 0 == strcmp( actionName.c_str(), ACTION_ACCESSIBILITY_READING_CANCELLED ) )
260   {
261     // if cast succeeds there is an implementation so no need to check
262     if( !DevelControl::AccessibilityReadingCancelledSignal( control ).Empty() )
263       DevelControl::AccessibilityReadingCancelledSignal( control ).Emit();
264   }
265   else if( 0 == strcmp( actionName.c_str(), ACTION_ACCESSIBILITY_READING_STOPPED ) )
266   {
267     // if cast succeeds there is an implementation so no need to check
268     if(!DevelControl::AccessibilityReadingStoppedSignal( control ).Empty())
269       DevelControl::AccessibilityReadingStoppedSignal( control ).Emit();
270   } else
271   {
272     ret = false;
273   }
274   return ret;
275 }
276
277 /**
278  * Connects a callback function with the object's signals.
279  * @param[in] object The object providing the signal.
280  * @param[in] tracker Used to disconnect the signal.
281  * @param[in] signalName The signal to connect to.
282  * @param[in] functor A newly allocated FunctorDelegate.
283  * @return True if the signal was connected.
284  * @post If a signal was connected, ownership of functor was passed to CallbackBase. Otherwise the caller is responsible for deleting the unused functor.
285  */
286 const char* SIGNAL_KEY_EVENT = "keyEvent";
287 const char* SIGNAL_KEY_INPUT_FOCUS_GAINED = "keyInputFocusGained";
288 const char* SIGNAL_KEY_INPUT_FOCUS_LOST = "keyInputFocusLost";
289 const char* SIGNAL_TAPPED = "tapped";
290 const char* SIGNAL_PANNED = "panned";
291 const char* SIGNAL_PINCHED = "pinched";
292 const char* SIGNAL_LONG_PRESSED = "longPressed";
293 const char* SIGNAL_GET_NAME = "getName";
294 const char* SIGNAL_GET_DESCRIPTION = "getDescription";
295 const char* SIGNAL_DO_GESTURE = "doGesture";
296 static bool DoConnectSignal( BaseObject* object, ConnectionTrackerInterface* tracker, const std::string& signalName, FunctorDelegate* functor )
297 {
298   Dali::BaseHandle handle( object );
299
300   bool connected( false );
301   Toolkit::Control control = Toolkit::Control::DownCast( handle );
302   if ( control )
303   {
304     Internal::Control& controlImpl( Internal::GetImplementation( control ) );
305     connected = true;
306
307     if ( 0 == strcmp( signalName.c_str(), SIGNAL_KEY_EVENT ) )
308     {
309       controlImpl.KeyEventSignal().Connect( tracker, functor );
310     }
311     else if( 0 == strcmp( signalName.c_str(), SIGNAL_KEY_INPUT_FOCUS_GAINED ) )
312     {
313       controlImpl.KeyInputFocusGainedSignal().Connect( tracker, functor );
314     }
315     else if( 0 == strcmp( signalName.c_str(), SIGNAL_KEY_INPUT_FOCUS_LOST ) )
316     {
317       controlImpl.KeyInputFocusLostSignal().Connect( tracker, functor );
318     }
319     else if( 0 == strcmp( signalName.c_str(), SIGNAL_TAPPED ) )
320     {
321       controlImpl.EnableGestureDetection( GestureType::TAP );
322       controlImpl.GetTapGestureDetector().DetectedSignal().Connect( tracker, functor );
323     }
324     else if( 0 == strcmp( signalName.c_str(), SIGNAL_PANNED ) )
325     {
326       controlImpl.EnableGestureDetection( GestureType::PAN );
327       controlImpl.GetPanGestureDetector().DetectedSignal().Connect( tracker, functor );
328     }
329     else if( 0 == strcmp( signalName.c_str(), SIGNAL_PINCHED ) )
330     {
331       controlImpl.EnableGestureDetection( GestureType::PINCH );
332       controlImpl.GetPinchGestureDetector().DetectedSignal().Connect( tracker, functor );
333     }
334     else if( 0 == strcmp( signalName.c_str(), SIGNAL_LONG_PRESSED ) )
335     {
336       controlImpl.EnableGestureDetection( GestureType::LONG_PRESS );
337       controlImpl.GetLongPressGestureDetector().DetectedSignal().Connect( tracker, functor );
338     }
339     else if( 0 == strcmp( signalName.c_str(), SIGNAL_GET_NAME ) )
340     {
341       DevelControl::AccessibilityGetNameSignal( control ).Connect( tracker, functor );
342     }
343     else if( 0 == strcmp( signalName.c_str(), SIGNAL_GET_DESCRIPTION ) )
344     {
345       DevelControl::AccessibilityGetDescriptionSignal( control ).Connect( tracker, functor );
346     }
347     else if( 0 == strcmp( signalName.c_str(), SIGNAL_DO_GESTURE ) )
348     {
349       DevelControl::AccessibilityDoGestureSignal( control ).Connect( tracker, functor );
350     }
351
352   }
353   return connected;
354 }
355
356 /**
357  * Creates control through type registry
358  */
359 BaseHandle Create()
360 {
361   return Internal::Control::New();
362 }
363 // Setup signals and actions using the type-registry.
364 DALI_TYPE_REGISTRATION_BEGIN( Control, CustomActor, Create );
365
366 // Note: Properties are registered separately below.
367
368 SignalConnectorType registerSignal1( typeRegistration, SIGNAL_KEY_EVENT, &DoConnectSignal );
369 SignalConnectorType registerSignal2( typeRegistration, SIGNAL_KEY_INPUT_FOCUS_GAINED, &DoConnectSignal );
370 SignalConnectorType registerSignal3( typeRegistration, SIGNAL_KEY_INPUT_FOCUS_LOST, &DoConnectSignal );
371 SignalConnectorType registerSignal4( typeRegistration, SIGNAL_TAPPED, &DoConnectSignal );
372 SignalConnectorType registerSignal5( typeRegistration, SIGNAL_PANNED, &DoConnectSignal );
373 SignalConnectorType registerSignal6( typeRegistration, SIGNAL_PINCHED, &DoConnectSignal );
374 SignalConnectorType registerSignal7( typeRegistration, SIGNAL_LONG_PRESSED, &DoConnectSignal );
375 SignalConnectorType registerSignal8( typeRegistration, SIGNAL_GET_NAME, &DoConnectSignal );
376 SignalConnectorType registerSignal9( typeRegistration, SIGNAL_GET_DESCRIPTION, &DoConnectSignal );
377 SignalConnectorType registerSignal10( typeRegistration, SIGNAL_DO_GESTURE, &DoConnectSignal );
378
379 TypeAction registerAction1( typeRegistration, "activate", &DoAction );
380 TypeAction registerAction2( typeRegistration, ACTION_ACCESSIBILITY_ACTIVATED, &DoAction );
381 TypeAction registerAction3( typeRegistration, ACTION_ACCESSIBILITY_READING_SKIPPED, &DoAction );
382 TypeAction registerAction4( typeRegistration, ACTION_ACCESSIBILITY_READING_CANCELLED, &DoAction );
383 TypeAction registerAction5( typeRegistration, ACTION_ACCESSIBILITY_READING_STOPPED, &DoAction );
384 TypeAction registerAction6( typeRegistration, ACTION_ACCESSIBILITY_READING_PAUSED, &DoAction );
385 TypeAction registerAction7( typeRegistration, ACTION_ACCESSIBILITY_READING_RESUMED, &DoAction );
386
387 DALI_TYPE_REGISTRATION_END()
388
389 /**
390  * @brief Iterate through given container and setOffScene any visual found
391  *
392  * @param[in] container Container of visuals
393  * @param[in] parent Parent actor to remove visuals from
394  */
395 void SetVisualsOffScene( const RegisteredVisualContainer& container, Actor parent )
396 {
397   for( auto iter = container.Begin(), end = container.End() ; iter!= end; iter++)
398   {
399     if( (*iter)->visual )
400     {
401       DALI_LOG_INFO( gLogFilter, Debug::Verbose, "Control::SetOffScene Setting visual(%d) off stage\n", (*iter)->index );
402       Toolkit::GetImplementation((*iter)->visual).SetOffScene( parent );
403     }
404   }
405 }
406
407 } // unnamed namespace
408
409
410 // Properties registered without macro to use specific member variables.
411 const PropertyRegistration Control::Impl::PROPERTY_1( typeRegistration, "styleName",              Toolkit::Control::Property::STYLE_NAME,                   Property::STRING,  &Control::Impl::SetProperty, &Control::Impl::GetProperty );
412 const PropertyRegistration Control::Impl::PROPERTY_4( typeRegistration, "keyInputFocus",          Toolkit::Control::Property::KEY_INPUT_FOCUS,              Property::BOOLEAN, &Control::Impl::SetProperty, &Control::Impl::GetProperty );
413 const PropertyRegistration Control::Impl::PROPERTY_5( typeRegistration, "background",             Toolkit::Control::Property::BACKGROUND,                   Property::MAP,     &Control::Impl::SetProperty, &Control::Impl::GetProperty );
414 const PropertyRegistration Control::Impl::PROPERTY_6( typeRegistration, "margin",                 Toolkit::Control::Property::MARGIN,                       Property::EXTENTS, &Control::Impl::SetProperty, &Control::Impl::GetProperty );
415 const PropertyRegistration Control::Impl::PROPERTY_7( typeRegistration, "padding",                Toolkit::Control::Property::PADDING,                      Property::EXTENTS, &Control::Impl::SetProperty, &Control::Impl::GetProperty );
416 const PropertyRegistration Control::Impl::PROPERTY_8( typeRegistration, "tooltip",                Toolkit::DevelControl::Property::TOOLTIP,                 Property::MAP,     &Control::Impl::SetProperty, &Control::Impl::GetProperty );
417 const PropertyRegistration Control::Impl::PROPERTY_9( typeRegistration, "state",                  Toolkit::DevelControl::Property::STATE,                   Property::STRING,  &Control::Impl::SetProperty, &Control::Impl::GetProperty );
418 const PropertyRegistration Control::Impl::PROPERTY_10( typeRegistration, "subState",               Toolkit::DevelControl::Property::SUB_STATE,               Property::STRING,  &Control::Impl::SetProperty, &Control::Impl::GetProperty );
419 const PropertyRegistration Control::Impl::PROPERTY_11( typeRegistration, "leftFocusableActorId",   Toolkit::DevelControl::Property::LEFT_FOCUSABLE_ACTOR_ID, Property::INTEGER, &Control::Impl::SetProperty, &Control::Impl::GetProperty );
420 const PropertyRegistration Control::Impl::PROPERTY_12( typeRegistration, "rightFocusableActorId", Toolkit::DevelControl::Property::RIGHT_FOCUSABLE_ACTOR_ID,Property::INTEGER, &Control::Impl::SetProperty, &Control::Impl::GetProperty );
421 const PropertyRegistration Control::Impl::PROPERTY_13( typeRegistration, "upFocusableActorId",    Toolkit::DevelControl::Property::UP_FOCUSABLE_ACTOR_ID,   Property::INTEGER, &Control::Impl::SetProperty, &Control::Impl::GetProperty );
422 const PropertyRegistration Control::Impl::PROPERTY_14( typeRegistration, "downFocusableActorId",  Toolkit::DevelControl::Property::DOWN_FOCUSABLE_ACTOR_ID, Property::INTEGER, &Control::Impl::SetProperty, &Control::Impl::GetProperty );
423 const PropertyRegistration Control::Impl::PROPERTY_15( typeRegistration, "shadow",                Toolkit::DevelControl::Property::SHADOW,                  Property::MAP,     &Control::Impl::SetProperty, &Control::Impl::GetProperty );
424 const PropertyRegistration Control::Impl::PROPERTY_16( typeRegistration, "accessibilityAttributes",         Toolkit::DevelControl::Property::ACCESSIBILITY_ATTRIBUTES,         Property::MAP,     &Control::Impl::SetProperty, &Control::Impl::GetProperty );
425 const PropertyRegistration Control::Impl::PROPERTY_17( typeRegistration, "accessibilityName",              Toolkit::DevelControl::Property::ACCESSIBILITY_NAME,               Property::STRING,  &Control::Impl::SetProperty, &Control::Impl::GetProperty );
426 const PropertyRegistration Control::Impl::PROPERTY_18( typeRegistration, "accessibilityDescription",       Toolkit::DevelControl::Property::ACCESSIBILITY_DESCRIPTION,         Property::STRING,  &Control::Impl::SetProperty, &Control::Impl::GetProperty );
427 const PropertyRegistration Control::Impl::PROPERTY_19( typeRegistration, "accessibilityTranslationDomain", Toolkit::DevelControl::Property::ACCESSIBILITY_TRANSLATION_DOMAIN, Property::STRING,  &Control::Impl::SetProperty, &Control::Impl::GetProperty );
428 const PropertyRegistration Control::Impl::PROPERTY_20( typeRegistration, "accessibilityRole",              Toolkit::DevelControl::Property::ACCESSIBILITY_ROLE,               Property::INTEGER, &Control::Impl::SetProperty, &Control::Impl::GetProperty );
429 const PropertyRegistration Control::Impl::PROPERTY_21( typeRegistration, "accessibilityHighlightable",     Toolkit::DevelControl::Property::ACCESSIBILITY_HIGHLIGHTABLE,      Property::BOOLEAN, &Control::Impl::SetProperty, &Control::Impl::GetProperty );
430 const PropertyRegistration Control::Impl::PROPERTY_22( typeRegistration, "accessibilityAnimated",          Toolkit::DevelControl::Property::ACCESSIBILITY_ANIMATED,      Property::BOOLEAN, &Control::Impl::SetProperty, &Control::Impl::GetProperty );
431
432 Control::Impl::Impl( Control& controlImpl )
433 : mControlImpl( controlImpl ),
434   mState( Toolkit::DevelControl::NORMAL ),
435   mSubStateName(""),
436   mLeftFocusableActorId( -1 ),
437   mRightFocusableActorId( -1 ),
438   mUpFocusableActorId( -1 ),
439   mDownFocusableActorId( -1 ),
440   mStyleName(""),
441   mBackgroundColor(Color::TRANSPARENT),
442   mStartingPinchScale(nullptr),
443   mMargin( 0, 0, 0, 0 ),
444   mPadding( 0, 0, 0, 0 ),
445   mKeyEventSignal(),
446   mKeyInputFocusGainedSignal(),
447   mKeyInputFocusLostSignal(),
448   mResourceReadySignal(),
449   mVisualEventSignal(),
450   mAccessibilityGetNameSignal(),
451   mAccessibilityGetDescriptionSignal(),
452   mAccessibilityDoGestureSignal(),
453   mPinchGestureDetector(),
454   mPanGestureDetector(),
455   mTapGestureDetector(),
456   mLongPressGestureDetector(),
457   mTooltip( NULL ),
458   mInputMethodContext(),
459   mIdleCallback(nullptr),
460   mFlags( Control::ControlBehaviour( CONTROL_BEHAVIOUR_DEFAULT ) ),
461   mIsKeyboardNavigationSupported( false ),
462   mIsKeyboardFocusGroup( false ),
463   mIsEmittingResourceReadySignal(false),
464   mNeedToEmitResourceReady(false)
465 {
466   Dali::Accessibility::Accessible::RegisterControlAccessibilityGetter(
467       []( Dali::Actor actor ) -> Dali::Accessibility::Accessible* {
468         return Control::Impl::GetAccessibilityObject( actor );
469       } );
470
471   accessibilityConstructor =  []( Dali::Actor actor ) -> std::unique_ptr< Dali::Accessibility::Accessible > {
472         return std::unique_ptr< Dali::Accessibility::Accessible >( new AccessibleImpl( actor,
473                                 Dali::Accessibility::Role::UNKNOWN ) );
474       };
475
476   size_t len = static_cast<size_t>(Dali::Accessibility::RelationType::MAX_COUNT);
477   mAccessibilityRelations.reserve(len);
478   for (auto i = 0u; i < len; ++i)
479   {
480     mAccessibilityRelations.push_back({});
481   }
482 }
483
484 Control::Impl::~Impl()
485 {
486   for( auto&& iter : mVisuals )
487   {
488     StopObservingVisual( iter->visual );
489   }
490
491   for( auto&& iter : mRemoveVisuals )
492   {
493     StopObservingVisual( iter->visual );
494   }
495
496   AccessibilityDeregister();
497   // All gesture detectors will be destroyed so no need to disconnect.
498   delete mStartingPinchScale;
499
500   if(mIdleCallback && Adaptor::IsAvailable())
501   {
502     // Removes the callback from the callback manager in case the control is destroyed before the callback is executed.
503     Adaptor::Get().RemoveIdle(mIdleCallback);
504   }
505 }
506
507 Control::Impl& Control::Impl::Get( Internal::Control& internalControl )
508 {
509   return *internalControl.mImpl;
510 }
511
512 const Control::Impl& Control::Impl::Get( const Internal::Control& internalControl )
513 {
514   return *internalControl.mImpl;
515 }
516
517 // Gesture Detection Methods
518 void Control::Impl::PinchDetected(Actor actor, const PinchGesture& pinch)
519 {
520   mControlImpl.OnPinch(pinch);
521 }
522
523 void Control::Impl::PanDetected(Actor actor, const PanGesture& pan)
524 {
525   mControlImpl.OnPan(pan);
526 }
527
528 void Control::Impl::TapDetected(Actor actor, const TapGesture& tap)
529 {
530   mControlImpl.OnTap(tap);
531 }
532
533 void Control::Impl::LongPressDetected(Actor actor, const LongPressGesture& longPress)
534 {
535   mControlImpl.OnLongPress(longPress);
536 }
537
538 void Control::Impl::RegisterVisual( Property::Index index, Toolkit::Visual::Base& visual )
539 {
540   RegisterVisual( index, visual, VisualState::ENABLED, DepthIndexValue::NOT_SET );
541 }
542
543 void Control::Impl::RegisterVisual( Property::Index index, Toolkit::Visual::Base& visual, int depthIndex )
544 {
545   RegisterVisual( index, visual, VisualState::ENABLED, DepthIndexValue::SET, depthIndex );
546 }
547
548 void Control::Impl::RegisterVisual( Property::Index index, Toolkit::Visual::Base& visual, bool enabled )
549 {
550   RegisterVisual( index, visual, ( enabled ? VisualState::ENABLED : VisualState::DISABLED ), DepthIndexValue::NOT_SET );
551 }
552
553 void Control::Impl::RegisterVisual( Property::Index index, Toolkit::Visual::Base& visual, bool enabled, int depthIndex )
554 {
555   RegisterVisual( index, visual, ( enabled ? VisualState::ENABLED : VisualState::DISABLED ), DepthIndexValue::SET, depthIndex );
556 }
557
558 void Control::Impl::RegisterVisual( Property::Index index, Toolkit::Visual::Base& visual, VisualState::Type enabled, DepthIndexValue::Type depthIndexValueSet, int depthIndex )
559 {
560   DALI_LOG_INFO( gLogFilter, Debug::Concise, "RegisterVisual:%d \n", index );
561
562   bool visualReplaced ( false );
563   Actor self = mControlImpl.Self();
564
565   // Set the depth index, if not set by caller this will be either the current visual depth, max depth of all visuals
566   // or zero.
567   int requiredDepthIndex = visual.GetDepthIndex();
568
569   if( depthIndexValueSet == DepthIndexValue::SET )
570   {
571     requiredDepthIndex = depthIndex;
572   }
573
574   // Visual replacement, existing visual should only be removed from stage when replacement ready.
575   if( !mVisuals.Empty() )
576   {
577     RegisteredVisualContainer::Iterator registeredVisualsiter;
578     // Check if visual (index) is already registered, this is the current visual.
579     if( FindVisual( index, mVisuals, registeredVisualsiter ) )
580     {
581       Toolkit::Visual::Base& currentRegisteredVisual = (*registeredVisualsiter)->visual;
582       if( currentRegisteredVisual )
583       {
584         // Store current visual depth index as may need to set the replacement visual to same depth
585         const int currentDepthIndex = (*registeredVisualsiter)->visual.GetDepthIndex();
586
587         // No longer required to know if the replaced visual's resources are ready
588         StopObservingVisual( currentRegisteredVisual );
589
590         // If control staged and visual enabled then visuals will be swapped once ready
591         if(  self.GetProperty< bool >( Actor::Property::CONNECTED_TO_SCENE ) && enabled )
592         {
593           // Check if visual is currently in the process of being replaced ( is in removal container )
594           RegisteredVisualContainer::Iterator visualQueuedForRemoval;
595           if ( FindVisual( index, mRemoveVisuals, visualQueuedForRemoval ) )
596           {
597             // Visual with same index is already in removal container so current visual pending
598             // Only the the last requested visual will be displayed so remove current visual which is staged but not ready.
599             Toolkit::GetImplementation( currentRegisteredVisual ).SetOffScene( self );
600             mVisuals.Erase( registeredVisualsiter );
601           }
602           else
603           {
604             // current visual not already in removal container so add now.
605             DALI_LOG_INFO( gLogFilter, Debug::Verbose, "RegisterVisual Move current registered visual to removal Queue: %d \n", index );
606             MoveVisual( registeredVisualsiter, mVisuals, mRemoveVisuals );
607           }
608         }
609         else
610         {
611           // Control not staged or visual disabled so can just erase from registered visuals and new visual will be added later.
612           mVisuals.Erase( registeredVisualsiter );
613         }
614
615         // 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
616         if( ( depthIndexValueSet == DepthIndexValue::NOT_SET ) &&
617             ( visual.GetDepthIndex() == 0 ) )
618         {
619           requiredDepthIndex = currentDepthIndex;
620         }
621       }
622
623       visualReplaced = true;
624     }
625   }
626
627   // If not set, set the name of the visual to the same name as the control's property.
628   // ( If the control has been type registered )
629   if( visual.GetName().empty() )
630   {
631     // returns empty string if index is not found as long as index is not -1
632     std::string visualName = self.GetPropertyName( index );
633     if( !visualName.empty() )
634     {
635       DALI_LOG_INFO( gLogFilter, Debug::Concise, "Setting visual name for property %d to %s\n",
636                      index, visualName.c_str() );
637       visual.SetName( visualName );
638     }
639   }
640
641   if( !visualReplaced ) // New registration entry
642   {
643     // 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
644     if( ( depthIndexValueSet == DepthIndexValue::NOT_SET ) &&
645         ( mVisuals.Size() > 0 ) &&
646         ( visual.GetDepthIndex() == 0 ) )
647     {
648       int maxDepthIndex = std::numeric_limits< int >::min();
649
650       RegisteredVisualContainer::ConstIterator iter;
651       const RegisteredVisualContainer::ConstIterator endIter = mVisuals.End();
652       for ( iter = mVisuals.Begin(); iter != endIter; iter++ )
653       {
654         const int visualDepthIndex = (*iter)->visual.GetDepthIndex();
655         if ( visualDepthIndex > maxDepthIndex )
656         {
657           maxDepthIndex = visualDepthIndex;
658         }
659       }
660       ++maxDepthIndex; // Add one to the current maximum depth index so that our added visual appears on top
661       requiredDepthIndex = std::max( 0, maxDepthIndex ); // Start at zero if maxDepth index belongs to a background
662     }
663   }
664
665   if( visual )
666   {
667     // Set determined depth index
668     visual.SetDepthIndex( requiredDepthIndex );
669
670     // Monitor when the visual resources are ready
671     StartObservingVisual( visual );
672
673     DALI_LOG_INFO( gLogFilter, Debug::Concise, "New Visual registration index[%d] depth[%d]\n", index, requiredDepthIndex );
674     RegisteredVisual* newRegisteredVisual  = new RegisteredVisual( index, visual,
675                                              ( enabled == VisualState::ENABLED ? true : false ),
676                                              ( visualReplaced && enabled ) ) ;
677     mVisuals.PushBack( newRegisteredVisual );
678
679     Internal::Visual::Base& visualImpl = Toolkit::GetImplementation( visual );
680     // Put on stage if enabled and the control is already on the stage
681     if( ( enabled == VisualState::ENABLED ) && self.GetProperty< bool >( Actor::Property::CONNECTED_TO_SCENE ) )
682     {
683       visualImpl.SetOnScene( self );
684     }
685     else if( visualImpl.IsResourceReady() ) // When not being staged, check if visual already 'ResourceReady' before it was Registered. ( Resource may have been loaded already )
686     {
687       ResourceReady( visualImpl );
688     }
689
690   }
691
692   DALI_LOG_INFO( gLogFilter, Debug::Verbose, "Control::RegisterVisual() Registered %s(%d), enabled:%s\n",  visual.GetName().c_str(), index, enabled?"true":"false" );
693 }
694
695 void Control::Impl::UnregisterVisual( Property::Index index )
696 {
697   RegisteredVisualContainer::Iterator iter;
698   if ( FindVisual( index, mVisuals, iter ) )
699   {
700     // stop observing visual
701     StopObservingVisual( (*iter)->visual );
702
703     Actor self( mControlImpl.Self() );
704     Toolkit::GetImplementation((*iter)->visual).SetOffScene( self );
705     (*iter)->visual.Reset();
706     mVisuals.Erase( iter );
707   }
708
709   if( FindVisual( index, mRemoveVisuals, iter ) )
710   {
711     Actor self( mControlImpl.Self() );
712     Toolkit::GetImplementation( (*iter)->visual ).SetOffScene( self );
713     (*iter)->pending = false;
714     (*iter)->visual.Reset();
715     mRemoveVisuals.Erase( iter );
716   }
717 }
718
719 Toolkit::Visual::Base Control::Impl::GetVisual( Property::Index index ) const
720 {
721   RegisteredVisualContainer::Iterator iter;
722   if ( FindVisual( index, mVisuals, iter ) )
723   {
724     return (*iter)->visual;
725   }
726
727   return Toolkit::Visual::Base();
728 }
729
730 void Control::Impl::EnableVisual( Property::Index index, bool enable )
731 {
732   DALI_LOG_INFO( gLogFilter, Debug::General, "Control::EnableVisual(%d, %s)\n", index, enable?"T":"F");
733
734   RegisteredVisualContainer::Iterator iter;
735   if ( FindVisual( index, mVisuals, iter ) )
736   {
737     if (  (*iter)->enabled == enable )
738     {
739       DALI_LOG_INFO( gLogFilter, Debug::Verbose, "Control::EnableVisual Visual %s(%d) already %s\n", (*iter)->visual.GetName().c_str(), index, enable?"enabled":"disabled");
740       return;
741     }
742
743     (*iter)->enabled = enable;
744     Actor parentActor = mControlImpl.Self();
745     if ( mControlImpl.Self().GetProperty< bool >( Actor::Property::CONNECTED_TO_SCENE ) ) // If control not on Scene then Visual will be added when SceneConnection is called.
746     {
747       if ( enable )
748       {
749         DALI_LOG_INFO( gLogFilter, Debug::Verbose, "Control::EnableVisual Setting %s(%d) on stage \n", (*iter)->visual.GetName().c_str(), index );
750         Toolkit::GetImplementation((*iter)->visual).SetOnScene( parentActor );
751       }
752       else
753       {
754         DALI_LOG_INFO( gLogFilter, Debug::Verbose, "Control::EnableVisual Setting %s(%d) off stage \n", (*iter)->visual.GetName().c_str(), index );
755         Toolkit::GetImplementation((*iter)->visual).SetOffScene( parentActor );  // No need to call if control not staged.
756       }
757     }
758   }
759   else
760   {
761     DALI_LOG_WARNING( "Control::EnableVisual(%d, %s) FAILED - NO SUCH VISUAL\n", index, enable?"T":"F" );
762   }
763 }
764
765 bool Control::Impl::IsVisualEnabled( Property::Index index ) const
766 {
767   RegisteredVisualContainer::Iterator iter;
768   if ( FindVisual( index, mVisuals, iter ) )
769   {
770     return (*iter)->enabled;
771   }
772   return false;
773 }
774
775 void Control::Impl::StopObservingVisual( Toolkit::Visual::Base& visual )
776 {
777   Internal::Visual::Base& visualImpl = Toolkit::GetImplementation( visual );
778
779   // Stop observing the visual
780   visualImpl.RemoveEventObserver( *this );
781 }
782
783 void Control::Impl::StartObservingVisual( Toolkit::Visual::Base& visual)
784 {
785   Internal::Visual::Base& visualImpl = Toolkit::GetImplementation( visual );
786
787   // start observing the visual for events
788   visualImpl.AddEventObserver( *this );
789 }
790
791 // Called by a Visual when it's resource is ready
792 void Control::Impl::ResourceReady( Visual::Base& object)
793 {
794   DALI_LOG_INFO( gLogFilter, Debug::Verbose, "Control::Impl::ResourceReady() replacements pending[%d]\n", mRemoveVisuals.Count() );
795
796   Actor self = mControlImpl.Self();
797
798   // A resource is ready, find resource in the registered visuals container and get its index
799   for( auto registeredIter = mVisuals.Begin(),  end = mVisuals.End(); registeredIter != end; ++registeredIter )
800   {
801     Internal::Visual::Base& registeredVisualImpl = Toolkit::GetImplementation( (*registeredIter)->visual );
802
803     if( &object == &registeredVisualImpl )
804     {
805       RegisteredVisualContainer::Iterator visualToRemoveIter;
806       // Find visual with the same index in the removal container
807       // Set if off stage as it's replacement is now ready.
808       // Remove if from removal list as now removed from stage.
809       // Set Pending flag on the ready visual to false as now ready.
810       if( FindVisual( (*registeredIter)->index, mRemoveVisuals, visualToRemoveIter ) )
811       {
812         (*registeredIter)->pending = false;
813         Toolkit::GetImplementation( (*visualToRemoveIter)->visual ).SetOffScene( self );
814         mRemoveVisuals.Erase( visualToRemoveIter );
815       }
816       break;
817     }
818   }
819
820   // A visual is ready so control may need relayouting if staged
821   if ( self.GetProperty< bool >( Actor::Property::CONNECTED_TO_SCENE ) )
822   {
823     mControlImpl.RelayoutRequest();
824   }
825
826   // Emit signal if all enabled visuals registered by the control are ready.
827   if( IsResourceReady() )
828   {
829     // Reset the flag
830     mNeedToEmitResourceReady = false;
831
832     EmitResourceReadySignal();
833   }
834 }
835
836 void Control::Impl::NotifyVisualEvent( Visual::Base& object, Property::Index signalId )
837 {
838   for( auto registeredIter = mVisuals.Begin(),  end = mVisuals.End(); registeredIter != end; ++registeredIter )
839   {
840     Internal::Visual::Base& registeredVisualImpl = Toolkit::GetImplementation( (*registeredIter)->visual );
841     if( &object == &registeredVisualImpl )
842     {
843       Dali::Toolkit::Control handle( mControlImpl.GetOwner() );
844       mVisualEventSignal.Emit( handle, (*registeredIter)->index, signalId );
845       break;
846     }
847   }
848 }
849
850 bool Control::Impl::IsResourceReady() const
851 {
852   // Iterate through and check all the enabled visuals are ready
853   for( auto visualIter = mVisuals.Begin();
854          visualIter != mVisuals.End(); ++visualIter )
855   {
856     const Toolkit::Visual::Base visual = (*visualIter)->visual;
857     const Internal::Visual::Base& visualImpl = Toolkit::GetImplementation( visual );
858
859     // one of the enabled visuals is not ready
860     if( !visualImpl.IsResourceReady() && (*visualIter)->enabled )
861     {
862       return false;
863     }
864   }
865   return true;
866 }
867
868 Toolkit::Visual::ResourceStatus Control::Impl::GetVisualResourceStatus( Property::Index index ) const
869 {
870   RegisteredVisualContainer::Iterator iter;
871   if ( FindVisual( index, mVisuals, iter ) )
872   {
873     const Toolkit::Visual::Base visual = (*iter)->visual;
874     const Internal::Visual::Base& visualImpl = Toolkit::GetImplementation( visual );
875     return visualImpl.GetResourceStatus( );
876   }
877
878   return Toolkit::Visual::ResourceStatus::PREPARING;
879 }
880
881
882
883 void Control::Impl::AddTransitions( Dali::Animation& animation,
884                                     const Toolkit::TransitionData& handle,
885                                     bool createAnimation )
886 {
887   // Setup a Transition from TransitionData.
888   const Internal::TransitionData& transitionData = Toolkit::GetImplementation( handle );
889   TransitionData::Iterator end = transitionData.End();
890   for( TransitionData::Iterator iter = transitionData.Begin() ;
891        iter != end; ++iter )
892   {
893     TransitionData::Animator* animator = (*iter);
894
895     Toolkit::Visual::Base visual = GetVisualByName( mVisuals, animator->objectName );
896
897     if( visual )
898     {
899 #if defined(DEBUG_ENABLED)
900       Dali::TypeInfo typeInfo;
901       ControlWrapper* controlWrapperImpl = dynamic_cast<ControlWrapper*>(&mControlImpl);
902       if( controlWrapperImpl )
903       {
904         typeInfo = controlWrapperImpl->GetTypeInfo();
905       }
906
907       DALI_LOG_INFO( gLogFilter, Debug::Concise, "CreateTransition: Found %s visual for %s\n",
908                      visual.GetName().c_str(), typeInfo?typeInfo.GetName().c_str():"Unknown" );
909 #endif
910       Internal::Visual::Base& visualImpl = Toolkit::GetImplementation( visual );
911       visualImpl.AnimateProperty( animation, *animator );
912     }
913     else
914     {
915       DALI_LOG_INFO( gLogFilter, Debug::Concise, "CreateTransition: Could not find visual. Trying actors");
916       // Otherwise, try any actor children of control (Including the control)
917       Actor child = mControlImpl.Self().FindChildByName( animator->objectName );
918       if( child )
919       {
920         Property::Index propertyIndex = child.GetPropertyIndex( animator->propertyKey );
921         if( propertyIndex != Property::INVALID_INDEX )
922         {
923           if( animator->animate == false )
924           {
925             if( animator->targetValue.GetType() != Property::NONE )
926             {
927               child.SetProperty( propertyIndex, animator->targetValue );
928             }
929           }
930           else // animate the property
931           {
932             if( animator->initialValue.GetType() != Property::NONE )
933             {
934               child.SetProperty( propertyIndex, animator->initialValue );
935             }
936
937             if( createAnimation && !animation )
938             {
939               animation = Dali::Animation::New( 0.1f );
940             }
941
942             animation.AnimateTo( Property( child, propertyIndex ),
943                                  animator->targetValue,
944                                  animator->alphaFunction,
945                                  TimePeriod( animator->timePeriodDelay,
946                                              animator->timePeriodDuration ) );
947           }
948         }
949       }
950     }
951   }
952 }
953
954 Dali::Animation Control::Impl::CreateTransition( const Toolkit::TransitionData& transitionData )
955 {
956   Dali::Animation transition;
957
958   if( transitionData.Count() > 0 )
959   {
960     AddTransitions( transition, transitionData, true );
961   }
962   return transition;
963 }
964
965
966
967 void Control::Impl::DoAction( Dali::Property::Index visualIndex, Dali::Property::Index actionId, const Dali::Property::Value attributes )
968 {
969   RegisteredVisualContainer::Iterator iter;
970   if ( FindVisual( visualIndex, mVisuals, iter ) )
971   {
972     Toolkit::GetImplementation((*iter)->visual).DoAction( actionId, attributes );
973   }
974 }
975
976 void Control::Impl::AppendAccessibilityAttribute( const std::string& key,
977                                                const std::string value )
978 {
979   Property::Value* val = mAccessibilityAttributes.Find( key );
980   if( val )
981   {
982     mAccessibilityAttributes[key] = Property::Value( value );
983   }
984   else
985   {
986     mAccessibilityAttributes.Insert( key, value );
987   }
988 }
989
990 void Control::Impl::SetProperty( BaseObject* object, Property::Index index, const Property::Value& value )
991 {
992   Toolkit::Control control = Toolkit::Control::DownCast( BaseHandle( object ) );
993
994   if ( control )
995   {
996     Control& controlImpl( GetImplementation( control ) );
997
998     switch ( index )
999     {
1000       case Toolkit::Control::Property::STYLE_NAME:
1001       {
1002         controlImpl.SetStyleName( value.Get< std::string >() );
1003         break;
1004       }
1005
1006       case Toolkit::DevelControl::Property::STATE:
1007       {
1008         bool withTransitions=true;
1009         const Property::Value* valuePtr=&value;
1010         const Property::Map* map = value.GetMap();
1011         if(map)
1012         {
1013           Property::Value* value2 = map->Find("withTransitions");
1014           if( value2 )
1015           {
1016             withTransitions = value2->Get<bool>();
1017           }
1018
1019           valuePtr = map->Find("state");
1020         }
1021
1022         if( valuePtr )
1023         {
1024           Toolkit::DevelControl::State state( controlImpl.mImpl->mState );
1025           if( Scripting::GetEnumerationProperty< Toolkit::DevelControl::State >( *valuePtr, ControlStateTable, ControlStateTableCount, state ) )
1026           {
1027             controlImpl.mImpl->SetState( state, withTransitions );
1028           }
1029         }
1030       }
1031       break;
1032
1033       case Toolkit::DevelControl::Property::SUB_STATE:
1034       {
1035         std::string subState;
1036         if( value.Get( subState ) )
1037         {
1038           controlImpl.mImpl->SetSubState( subState );
1039         }
1040       }
1041       break;
1042
1043       case Toolkit::DevelControl::Property::LEFT_FOCUSABLE_ACTOR_ID:
1044       {
1045         int focusId;
1046         if( value.Get( focusId ) )
1047         {
1048           controlImpl.mImpl->mLeftFocusableActorId = focusId;
1049         }
1050       }
1051       break;
1052
1053       case Toolkit::DevelControl::Property::RIGHT_FOCUSABLE_ACTOR_ID:
1054       {
1055         int focusId;
1056         if( value.Get( focusId ) )
1057         {
1058           controlImpl.mImpl->mRightFocusableActorId = focusId;
1059         }
1060       }
1061       break;
1062
1063       case Toolkit::DevelControl::Property::ACCESSIBILITY_NAME:
1064       {
1065         std::string name;
1066         if( value.Get( name ) )
1067         {
1068           controlImpl.mImpl->mAccessibilityName = name;
1069           controlImpl.mImpl->mAccessibilityNameSet = true;
1070         }
1071         else
1072         {
1073           controlImpl.mImpl->mAccessibilityNameSet = false;
1074         }
1075       }
1076       break;
1077
1078       case Toolkit::DevelControl::Property::ACCESSIBILITY_DESCRIPTION:
1079       {
1080         std::string txt;
1081         if( value.Get( txt ) )
1082         {
1083           controlImpl.mImpl->mAccessibilityDescription = txt;
1084           controlImpl.mImpl->mAccessibilityDescriptionSet = true;
1085         }
1086         else
1087         {
1088           controlImpl.mImpl->mAccessibilityDescriptionSet = false;
1089         }
1090       }
1091       break;
1092
1093       case Toolkit::DevelControl::Property::ACCESSIBILITY_TRANSLATION_DOMAIN:
1094       {
1095         std::string txt;
1096         if( value.Get( txt ) )
1097         {
1098           controlImpl.mImpl->mAccessibilityTranslationDomain = txt;
1099           controlImpl.mImpl->mAccessibilityTranslationDomainSet = true;
1100         }
1101         else
1102         {
1103           controlImpl.mImpl->mAccessibilityTranslationDomainSet = false;
1104         }
1105       }
1106       break;
1107
1108       case Toolkit::DevelControl::Property::ACCESSIBILITY_HIGHLIGHTABLE:
1109       {
1110         bool highlightable;
1111         if( value.Get( highlightable ) )
1112         {
1113           controlImpl.mImpl->mAccessibilityHighlightable = highlightable;
1114           controlImpl.mImpl->mAccessibilityHighlightableSet = true;
1115         }
1116         else
1117         {
1118           controlImpl.mImpl->mAccessibilityHighlightableSet = false;
1119         }
1120       }
1121       break;
1122
1123       case Toolkit::DevelControl::Property::ACCESSIBILITY_ROLE:
1124       {
1125         Dali::Accessibility::Role val;
1126         if( value.Get( val ) )
1127         {
1128           controlImpl.mImpl->mAccessibilityRole = val;
1129         }
1130       }
1131       break;
1132
1133       case Toolkit::DevelControl::Property::UP_FOCUSABLE_ACTOR_ID:
1134       {
1135         int focusId;
1136         if( value.Get( focusId ) )
1137         {
1138           controlImpl.mImpl->mUpFocusableActorId = focusId;
1139         }
1140       }
1141       break;
1142
1143       case Toolkit::DevelControl::Property::DOWN_FOCUSABLE_ACTOR_ID:
1144       {
1145         int focusId;
1146         if( value.Get( focusId ) )
1147         {
1148           controlImpl.mImpl->mDownFocusableActorId = focusId;
1149         }
1150       }
1151       break;
1152
1153       case Toolkit::Control::Property::KEY_INPUT_FOCUS:
1154       {
1155         if ( value.Get< bool >() )
1156         {
1157           controlImpl.SetKeyInputFocus();
1158         }
1159         else
1160         {
1161           controlImpl.ClearKeyInputFocus();
1162         }
1163         break;
1164       }
1165
1166       case Toolkit::Control::Property::BACKGROUND:
1167       {
1168         std::string url;
1169         Vector4 color;
1170         const Property::Map* map = value.GetMap();
1171         if( map && !map->Empty() )
1172         {
1173           controlImpl.SetBackground( *map );
1174         }
1175         else if( value.Get( url ) )
1176         {
1177           // don't know the size to load
1178           Toolkit::Visual::Base visual = Toolkit::VisualFactory::Get().CreateVisual( url, ImageDimensions() );
1179           if( visual )
1180           {
1181             controlImpl.mImpl->RegisterVisual( Toolkit::Control::Property::BACKGROUND, visual, DepthIndex::BACKGROUND );
1182           }
1183         }
1184         else if( value.Get( color ) )
1185         {
1186           controlImpl.SetBackgroundColor(color);
1187         }
1188         else
1189         {
1190           // The background is an empty property map, so we should clear the background
1191           controlImpl.ClearBackground();
1192         }
1193         break;
1194       }
1195
1196       case Toolkit::Control::Property::MARGIN:
1197       {
1198         Extents margin;
1199         if( value.Get( margin ) )
1200         {
1201           controlImpl.mImpl->SetMargin( margin );
1202         }
1203         break;
1204       }
1205
1206       case Toolkit::Control::Property::PADDING:
1207       {
1208         Extents padding;
1209         if( value.Get( padding ) )
1210         {
1211           controlImpl.mImpl->SetPadding( padding );
1212         }
1213         break;
1214       }
1215
1216       case Toolkit::DevelControl::Property::TOOLTIP:
1217       {
1218         TooltipPtr& tooltipPtr = controlImpl.mImpl->mTooltip;
1219         if( ! tooltipPtr )
1220         {
1221           tooltipPtr = Tooltip::New( control );
1222         }
1223         tooltipPtr->SetProperties( value );
1224         break;
1225       }
1226
1227       case Toolkit::DevelControl::Property::SHADOW:
1228       {
1229         const Property::Map* map = value.GetMap();
1230         if( map && !map->Empty() )
1231         {
1232           controlImpl.mImpl->SetShadow( *map );
1233         }
1234         else
1235         {
1236           // The shadow is an empty property map, so we should clear the shadow
1237           controlImpl.mImpl->ClearShadow();
1238         }
1239         break;
1240       }
1241
1242       case Toolkit::DevelControl::Property::ACCESSIBILITY_ATTRIBUTES:
1243       {
1244         const Property::Map* map = value.GetMap();
1245         if( map && !map->Empty() )
1246         {
1247           controlImpl.mImpl->mAccessibilityAttributes = *map;
1248         }
1249         break;
1250       }
1251
1252       case Toolkit::DevelControl::Property::ACCESSIBILITY_ANIMATED:
1253       {
1254         bool animated;
1255         if( value.Get( animated ) )
1256         {
1257           controlImpl.mImpl->mAccessibilityAnimated = animated;
1258         }
1259         break;
1260       }
1261     }
1262   }
1263 }
1264
1265 Property::Value Control::Impl::GetProperty( BaseObject* object, Property::Index index )
1266 {
1267   Property::Value value;
1268
1269   Toolkit::Control control = Toolkit::Control::DownCast( BaseHandle( object ) );
1270
1271   if ( control )
1272   {
1273     Control& controlImpl( GetImplementation( control ) );
1274
1275     switch ( index )
1276     {
1277       case Toolkit::Control::Property::STYLE_NAME:
1278       {
1279         value = controlImpl.GetStyleName();
1280         break;
1281       }
1282
1283       case Toolkit::DevelControl::Property::STATE:
1284       {
1285         value = controlImpl.mImpl->mState;
1286         break;
1287       }
1288
1289       case Toolkit::DevelControl::Property::SUB_STATE:
1290       {
1291         value = controlImpl.mImpl->mSubStateName;
1292         break;
1293       }
1294
1295       case Toolkit::DevelControl::Property::LEFT_FOCUSABLE_ACTOR_ID:
1296       {
1297         value = controlImpl.mImpl->mLeftFocusableActorId;
1298         break;
1299       }
1300
1301       case Toolkit::DevelControl::Property::RIGHT_FOCUSABLE_ACTOR_ID:
1302       {
1303         value = controlImpl.mImpl->mRightFocusableActorId;
1304         break;
1305       }
1306
1307       case Toolkit::DevelControl::Property::ACCESSIBILITY_NAME:
1308       {
1309         if (controlImpl.mImpl->mAccessibilityNameSet)
1310         {
1311           value = controlImpl.mImpl->mAccessibilityName;
1312         }
1313         break;
1314       }
1315
1316       case Toolkit::DevelControl::Property::ACCESSIBILITY_DESCRIPTION:
1317       {
1318         if (controlImpl.mImpl->mAccessibilityDescriptionSet)
1319         {
1320           value = controlImpl.mImpl->mAccessibilityDescription;
1321         }
1322         break;
1323       }
1324
1325       case Toolkit::DevelControl::Property::ACCESSIBILITY_TRANSLATION_DOMAIN:
1326       {
1327         if (controlImpl.mImpl->mAccessibilityTranslationDomainSet)
1328         {
1329           value = controlImpl.mImpl->mAccessibilityTranslationDomain;
1330         }
1331         break;
1332       }
1333
1334       case Toolkit::DevelControl::Property::ACCESSIBILITY_HIGHLIGHTABLE:
1335       {
1336         if (controlImpl.mImpl->mAccessibilityHighlightableSet)
1337         {
1338           value = controlImpl.mImpl->mAccessibilityHighlightable;
1339         }
1340         break;
1341       }
1342
1343       case Toolkit::DevelControl::Property::ACCESSIBILITY_ROLE:
1344       {
1345         value = Property::Value(controlImpl.mImpl->mAccessibilityRole);
1346         break;
1347       }
1348
1349       case Toolkit::DevelControl::Property::UP_FOCUSABLE_ACTOR_ID:
1350       {
1351         value = controlImpl.mImpl->mUpFocusableActorId;
1352         break;
1353       }
1354
1355       case Toolkit::DevelControl::Property::DOWN_FOCUSABLE_ACTOR_ID:
1356       {
1357         value = controlImpl.mImpl->mDownFocusableActorId;
1358         break;
1359       }
1360
1361       case Toolkit::Control::Property::KEY_INPUT_FOCUS:
1362       {
1363         value = controlImpl.HasKeyInputFocus();
1364         break;
1365       }
1366
1367       case Toolkit::Control::Property::BACKGROUND:
1368       {
1369         Property::Map map;
1370         Toolkit::Visual::Base visual = controlImpl.mImpl->GetVisual( Toolkit::Control::Property::BACKGROUND );
1371         if( visual )
1372         {
1373           visual.CreatePropertyMap( map );
1374         }
1375
1376         value = map;
1377         break;
1378       }
1379
1380       case Toolkit::Control::Property::MARGIN:
1381       {
1382         value = controlImpl.mImpl->GetMargin();
1383         break;
1384       }
1385
1386       case Toolkit::Control::Property::PADDING:
1387       {
1388         value = controlImpl.mImpl->GetPadding();
1389         break;
1390       }
1391
1392       case Toolkit::DevelControl::Property::TOOLTIP:
1393       {
1394         Property::Map map;
1395         if( controlImpl.mImpl->mTooltip )
1396         {
1397           controlImpl.mImpl->mTooltip->CreatePropertyMap( map );
1398         }
1399         value = map;
1400         break;
1401       }
1402
1403       case Toolkit::DevelControl::Property::SHADOW:
1404       {
1405         Property::Map map;
1406         Toolkit::Visual::Base visual = controlImpl.mImpl->GetVisual( Toolkit::DevelControl::Property::SHADOW );
1407         if( visual )
1408         {
1409           visual.CreatePropertyMap( map );
1410         }
1411
1412         value = map;
1413         break;
1414       }
1415
1416       case Toolkit::DevelControl::Property::ACCESSIBILITY_ATTRIBUTES:
1417       {
1418         value = controlImpl.mImpl->mAccessibilityAttributes;
1419         break;
1420       }
1421
1422       case Toolkit::DevelControl::Property::ACCESSIBILITY_ANIMATED:
1423       {
1424         value = controlImpl.mImpl->mAccessibilityAnimated;
1425         break;
1426       }
1427     }
1428   }
1429
1430   return value;
1431 }
1432
1433 void Control::Impl::RemoveAccessibilityAttribute( const std::string& key )
1434 {
1435   Property::Value* val = mAccessibilityAttributes.Find( key );
1436   if( val )
1437     mAccessibilityAttributes[key] = Property::Value();
1438 }
1439
1440 void Control::Impl::ClearAccessibilityAttributes()
1441 {
1442   mAccessibilityAttributes.Clear();
1443 }
1444
1445 void Control::Impl::SetAccessibilityReadingInfoType( const Dali::Accessibility::ReadingInfoTypes types )
1446 {
1447   std::string value;
1448   if ( types[ Dali::Accessibility::ReadingInfoType::NAME ] )
1449   {
1450     value += READING_INFO_TYPE_NAME;
1451   }
1452   if ( types[ Dali::Accessibility::ReadingInfoType::ROLE ] )
1453   {
1454     if( !value.empty() )
1455     {
1456       value += READING_INFO_TYPE_SEPARATOR;
1457     }
1458     value += READING_INFO_TYPE_ROLE;
1459   }
1460   if ( types[ Dali::Accessibility::ReadingInfoType::DESCRIPTION ] )
1461   {
1462     if( !value.empty() )
1463     {
1464       value += READING_INFO_TYPE_SEPARATOR;
1465     }
1466     value += READING_INFO_TYPE_DESCRIPTION;
1467   }
1468   if ( types[ Dali::Accessibility::ReadingInfoType::STATE ] )
1469   {
1470     if( !value.empty() )
1471     {
1472       value += READING_INFO_TYPE_SEPARATOR;
1473     }
1474     value += READING_INFO_TYPE_STATE;
1475   }
1476   AppendAccessibilityAttribute( READING_INFO_TYPE_ATTRIBUTE_NAME, value );
1477 }
1478
1479 Dali::Accessibility::ReadingInfoTypes Control::Impl::GetAccessibilityReadingInfoType() const
1480 {
1481   std::string value;
1482   auto place = mAccessibilityAttributes.Find( READING_INFO_TYPE_ATTRIBUTE_NAME );
1483   if( place )
1484   {
1485     place->Get( value );
1486   }
1487
1488   if ( value.empty() )
1489   {
1490     return {};
1491   }
1492
1493   Dali::Accessibility::ReadingInfoTypes types;
1494
1495   if ( value.find( READING_INFO_TYPE_NAME ) != std::string::npos )
1496   {
1497     types[ Dali::Accessibility::ReadingInfoType::NAME ] = true;
1498   }
1499   if ( value.find( READING_INFO_TYPE_ROLE ) != std::string::npos )
1500   {
1501     types[ Dali::Accessibility::ReadingInfoType::ROLE ] = true;
1502   }
1503   if ( value.find( READING_INFO_TYPE_DESCRIPTION ) != std::string::npos )
1504   {
1505     types[ Dali::Accessibility::ReadingInfoType::DESCRIPTION ] = true;
1506   }
1507   if ( value.find( READING_INFO_TYPE_STATE ) != std::string::npos )
1508   {
1509     types[ Dali::Accessibility::ReadingInfoType::STATE ] = true;
1510   }
1511
1512   return types;
1513 }
1514
1515 void  Control::Impl::CopyInstancedProperties( RegisteredVisualContainer& visuals, Dictionary<Property::Map>& instancedProperties )
1516 {
1517   for(RegisteredVisualContainer::Iterator iter = visuals.Begin(); iter!= visuals.End(); iter++)
1518   {
1519     if( (*iter)->visual )
1520     {
1521       Property::Map instanceMap;
1522       Toolkit::GetImplementation((*iter)->visual).CreateInstancePropertyMap(instanceMap);
1523       instancedProperties.Add( (*iter)->visual.GetName(), instanceMap );
1524     }
1525   }
1526 }
1527
1528
1529 void Control::Impl::RemoveVisual( RegisteredVisualContainer& visuals, const std::string& visualName )
1530 {
1531   Actor self( mControlImpl.Self() );
1532
1533   for ( RegisteredVisualContainer::Iterator visualIter = visuals.Begin();
1534         visualIter != visuals.End(); ++visualIter )
1535   {
1536     Toolkit::Visual::Base visual = (*visualIter)->visual;
1537     if( visual && visual.GetName() == visualName )
1538     {
1539       Toolkit::GetImplementation(visual).SetOffScene( self );
1540       (*visualIter)->visual.Reset();
1541       visuals.Erase( visualIter );
1542       break;
1543     }
1544   }
1545 }
1546
1547 void Control::Impl::RemoveVisuals( RegisteredVisualContainer& visuals, DictionaryKeys& removeVisuals )
1548 {
1549   Actor self( mControlImpl.Self() );
1550   for( DictionaryKeys::iterator iter = removeVisuals.begin(); iter != removeVisuals.end(); ++iter )
1551   {
1552     const std::string visualName = *iter;
1553     RemoveVisual( visuals, visualName );
1554   }
1555 }
1556
1557 void Control::Impl::RecreateChangedVisuals( Dictionary<Property::Map>& stateVisualsToChange,
1558                              Dictionary<Property::Map>& instancedProperties )
1559 {
1560   Dali::CustomActor handle( mControlImpl.GetOwner() );
1561   for( Dictionary<Property::Map>::iterator iter = stateVisualsToChange.Begin();
1562        iter != stateVisualsToChange.End(); ++iter )
1563   {
1564     const std::string& visualName = (*iter).key;
1565     const Property::Map& toMap = (*iter).entry;
1566
1567     Actor self = mControlImpl.Self();
1568     RegisteredVisualContainer::Iterator registeredVisualsiter;
1569     // Check if visual (visualName) is already registered, this is the current visual.
1570     if(FindVisual(visualName, mVisuals, registeredVisualsiter))
1571     {
1572       Toolkit::Visual::Base& visual = (*registeredVisualsiter)->visual;
1573       if(visual)
1574       {
1575         // No longer required to know if the replaced visual's resources are ready
1576         StopObservingVisual(visual);
1577
1578         // If control staged then visuals will be swapped once ready
1579         if(self.GetProperty<bool>(Actor::Property::CONNECTED_TO_SCENE))
1580         {
1581           // Check if visual is currently in the process of being replaced ( is in removal container )
1582           RegisteredVisualContainer::Iterator visualQueuedForRemoval;
1583           if(FindVisual(visualName, mRemoveVisuals, visualQueuedForRemoval))
1584           {
1585             // Visual with same visual name is already in removal container so current visual pending
1586             // Only the the last requested visual will be displayed so remove current visual which is staged but not ready.
1587             Toolkit::GetImplementation(visual).SetOffScene(self);
1588             (*registeredVisualsiter)->visual.Reset();
1589             mVisuals.Erase(registeredVisualsiter);
1590           }
1591           else
1592           {
1593             // current visual not already in removal container so add now.
1594             DALI_LOG_INFO(gLogFilter, Debug::Verbose, "RegisterVisual Move current registered visual to removal Queue: %s \n", visualName.c_str());
1595             MoveVisual(registeredVisualsiter, mVisuals, mRemoveVisuals);
1596           }
1597         }
1598         else
1599         {
1600           // Control not staged or visual disabled so can just erase from registered visuals and new visual will be added later.
1601           (*registeredVisualsiter)->visual.Reset();
1602           mVisuals.Erase(registeredVisualsiter);
1603         }
1604       }
1605
1606       const Property::Map* instancedMap = instancedProperties.FindConst(visualName);
1607       Style::ApplyVisual(handle, visualName, toMap, instancedMap);
1608     }
1609   }
1610 }
1611
1612 void Control::Impl::ReplaceStateVisualsAndProperties( const StylePtr oldState, const StylePtr newState, const std::string& subState )
1613 {
1614   // Collect all old visual names
1615   DictionaryKeys stateVisualsToRemove;
1616   if( oldState )
1617   {
1618     oldState->visuals.GetKeys( stateVisualsToRemove );
1619     if( ! subState.empty() )
1620     {
1621       const StylePtr* oldSubState = oldState->subStates.FindConst(subState);
1622       if( oldSubState )
1623       {
1624         DictionaryKeys subStateVisualsToRemove;
1625         (*oldSubState)->visuals.GetKeys( subStateVisualsToRemove );
1626         Merge( stateVisualsToRemove, subStateVisualsToRemove );
1627       }
1628     }
1629   }
1630
1631   // Collect all new visual properties
1632   Dictionary<Property::Map> stateVisualsToAdd;
1633   if( newState )
1634   {
1635     stateVisualsToAdd = newState->visuals;
1636     if( ! subState.empty() )
1637     {
1638       const StylePtr* newSubState = newState->subStates.FindConst(subState);
1639       if( newSubState )
1640       {
1641         stateVisualsToAdd.Merge( (*newSubState)->visuals );
1642       }
1643     }
1644   }
1645
1646   // If a name is in both add/remove, move it to change list.
1647   Dictionary<Property::Map> stateVisualsToChange;
1648   FindChangableVisuals( stateVisualsToAdd, stateVisualsToChange, stateVisualsToRemove);
1649
1650   // Copy instanced properties (e.g. text label) of current visuals
1651   Dictionary<Property::Map> instancedProperties;
1652   CopyInstancedProperties( mVisuals, instancedProperties );
1653
1654   // For each visual in remove list, remove from mVisuals
1655   RemoveVisuals( mVisuals, stateVisualsToRemove );
1656
1657   // For each visual in add list, create and add to mVisuals
1658   Dali::CustomActor handle( mControlImpl.GetOwner() );
1659   Style::ApplyVisuals( handle, stateVisualsToAdd, instancedProperties );
1660
1661   // For each visual in change list, if it requires a new visual,
1662   // remove old visual, create and add to mVisuals
1663   RecreateChangedVisuals( stateVisualsToChange, instancedProperties );
1664 }
1665
1666 void Control::Impl::SetState( DevelControl::State newState, bool withTransitions )
1667 {
1668   DevelControl::State oldState = mState;
1669   Dali::CustomActor handle( mControlImpl.GetOwner() );
1670   DALI_LOG_INFO(gLogFilter, Debug::Concise, "Control::Impl::SetState: %s\n",
1671                 (mState == DevelControl::NORMAL ? "NORMAL" :(
1672                   mState == DevelControl::FOCUSED ?"FOCUSED" : (
1673                     mState == DevelControl::DISABLED?"DISABLED":"NONE" ))));
1674
1675   if( mState != newState )
1676   {
1677     // If mState was Disabled, and new state is Focused, should probably
1678     // store that fact, e.g. in another property that FocusManager can access.
1679     mState = newState;
1680
1681     // Trigger state change and transitions
1682     // Apply new style, if stylemanager is available
1683     Toolkit::StyleManager styleManager = Toolkit::StyleManager::Get();
1684     if( styleManager )
1685     {
1686       const StylePtr stylePtr = GetImpl( styleManager ).GetRecordedStyle( Toolkit::Control( mControlImpl.GetOwner() ) );
1687
1688       if( stylePtr )
1689       {
1690         std::string oldStateName = Scripting::GetEnumerationName< Toolkit::DevelControl::State >( oldState, ControlStateTable, ControlStateTableCount );
1691         std::string newStateName = Scripting::GetEnumerationName< Toolkit::DevelControl::State >( newState, ControlStateTable, ControlStateTableCount );
1692
1693         const StylePtr* newStateStyle = stylePtr->subStates.Find( newStateName );
1694         const StylePtr* oldStateStyle = stylePtr->subStates.Find( oldStateName );
1695         if( oldStateStyle && newStateStyle )
1696         {
1697           // Only change if both state styles exist
1698           ReplaceStateVisualsAndProperties( *oldStateStyle, *newStateStyle, mSubStateName );
1699         }
1700       }
1701     }
1702   }
1703 }
1704
1705 void Control::Impl::SetSubState( const std::string& subStateName, bool withTransitions )
1706 {
1707   if( mSubStateName != subStateName )
1708   {
1709     // Get existing sub-state visuals, and unregister them
1710     Dali::CustomActor handle( mControlImpl.GetOwner() );
1711
1712     Toolkit::StyleManager styleManager = Toolkit::StyleManager::Get();
1713     if( styleManager )
1714     {
1715       const StylePtr stylePtr = GetImpl( styleManager ).GetRecordedStyle( Toolkit::Control( mControlImpl.GetOwner() ) );
1716       if( stylePtr )
1717       {
1718         // Stringify state
1719         std::string stateName = Scripting::GetEnumerationName< Toolkit::DevelControl::State >( mState, ControlStateTable, ControlStateTableCount );
1720
1721         const StylePtr* state = stylePtr->subStates.Find( stateName );
1722         if( state )
1723         {
1724           StylePtr stateStyle(*state);
1725
1726           const StylePtr* newStateStyle = stateStyle->subStates.Find( subStateName );
1727           const StylePtr* oldStateStyle = stateStyle->subStates.Find( mSubStateName );
1728           if( oldStateStyle && newStateStyle )
1729           {
1730             std::string empty;
1731             ReplaceStateVisualsAndProperties( *oldStateStyle, *newStateStyle, empty );
1732           }
1733         }
1734       }
1735     }
1736
1737     mSubStateName = subStateName;
1738   }
1739 }
1740
1741 void Control::Impl::OnSceneDisconnection()
1742 {
1743   Actor self = mControlImpl.Self();
1744
1745   // Any visuals set for replacement but not yet ready should still be registered.
1746   // Reason: If a request was made to register a new visual but the control removed from scene before visual was ready
1747   // then when this control appears back on stage it should use that new visual.
1748
1749   // Iterate through all registered visuals and set off scene
1750   SetVisualsOffScene( mVisuals, self );
1751
1752   // Visuals pending replacement can now be taken out of the removal list and set off scene
1753   // Iterate through all replacement visuals and add to a move queue then set off scene
1754   for( auto removalIter = mRemoveVisuals.Begin(), end = mRemoveVisuals.End(); removalIter != end; removalIter++ )
1755   {
1756     Toolkit::GetImplementation((*removalIter)->visual).SetOffScene( self );
1757   }
1758
1759   for( auto replacedIter = mVisuals.Begin(), end = mVisuals.End(); replacedIter != end; replacedIter++ )
1760   {
1761     (*replacedIter)->pending = false;
1762   }
1763
1764   mRemoveVisuals.Clear();
1765 }
1766
1767 void Control::Impl::SetMargin( Extents margin )
1768 {
1769   mControlImpl.mImpl->mMargin = margin;
1770
1771   // Trigger a size negotiation request that may be needed when setting a margin.
1772   mControlImpl.RelayoutRequest();
1773 }
1774
1775 Extents Control::Impl::GetMargin() const
1776 {
1777   return mControlImpl.mImpl->mMargin;
1778 }
1779
1780 void Control::Impl::SetPadding( Extents padding )
1781 {
1782   mControlImpl.mImpl->mPadding = padding;
1783
1784   // Trigger a size negotiation request that may be needed when setting a padding.
1785   mControlImpl.RelayoutRequest();
1786 }
1787
1788 Extents Control::Impl::GetPadding() const
1789 {
1790   return mControlImpl.mImpl->mPadding;
1791 }
1792
1793 void Control::Impl::SetInputMethodContext( InputMethodContext& inputMethodContext )
1794 {
1795   mInputMethodContext = inputMethodContext;
1796 }
1797
1798 bool Control::Impl::FilterKeyEvent( const KeyEvent& event )
1799 {
1800   bool consumed ( false );
1801
1802   if ( mInputMethodContext )
1803   {
1804     consumed = mInputMethodContext.FilterEventKey( event );
1805   }
1806   return consumed;
1807 }
1808
1809 DevelControl::VisualEventSignalType& Control::Impl::VisualEventSignal()
1810 {
1811   return mVisualEventSignal;
1812 }
1813
1814 void Control::Impl::SetShadow( const Property::Map& map )
1815 {
1816   Toolkit::Visual::Base visual = Toolkit::VisualFactory::Get().CreateVisual( map );
1817   visual.SetName("shadow");
1818
1819   if( visual )
1820   {
1821     mControlImpl.mImpl->RegisterVisual( Toolkit::DevelControl::Property::SHADOW, visual, DepthIndex::BACKGROUND_EFFECT );
1822
1823     mControlImpl.RelayoutRequest();
1824   }
1825 }
1826
1827 void Control::Impl::ClearShadow()
1828 {
1829    mControlImpl.mImpl->UnregisterVisual( Toolkit::DevelControl::Property::SHADOW );
1830
1831    // Trigger a size negotiation request that may be needed when unregistering a visual.
1832    mControlImpl.RelayoutRequest();
1833 }
1834
1835 Dali::Property Control::Impl::GetVisualProperty(Dali::Property::Index index, Dali::Property::Key visualPropertyKey)
1836 {
1837   Toolkit::Visual::Base visual = GetVisualByIndex(mVisuals, index);
1838   if(visual)
1839   {
1840     Internal::Visual::Base& visualImpl = Toolkit::GetImplementation(visual);
1841     return visualImpl.GetPropertyObject(visualPropertyKey);
1842   }
1843
1844   Handle handle;
1845   return Dali::Property(handle, Property::INVALID_INDEX);
1846 }
1847
1848 void Control::Impl::EmitResourceReadySignal()
1849 {
1850   if(!mIsEmittingResourceReadySignal)
1851   {
1852     // Guard against calls to emit the signal during the callback
1853     mIsEmittingResourceReadySignal = true;
1854
1855     // If the signal handler changes visual, it may become ready during this call & therefore this method will
1856     // get called again recursively. If so, mNeedToEmitResourceReady is set below, and we act on it after that secondary
1857     // invocation has completed by notifying in an Idle callback to prevent further recursion.
1858     Dali::Toolkit::Control handle(mControlImpl.GetOwner());
1859     mResourceReadySignal.Emit(handle);
1860
1861     if(mNeedToEmitResourceReady)
1862     {
1863       // Add idler to emit the signal again
1864       if(!mIdleCallback)
1865       {
1866         // The callback manager takes the ownership of the callback object.
1867         mIdleCallback = MakeCallback( this, &Control::Impl::OnIdleCallback);
1868         Adaptor::Get().AddIdle(mIdleCallback, false);
1869       }
1870     }
1871
1872     mIsEmittingResourceReadySignal = false;
1873   }
1874   else
1875   {
1876     mNeedToEmitResourceReady = true;
1877   }
1878 }
1879
1880 void Control::Impl::OnIdleCallback()
1881 {
1882   if(mNeedToEmitResourceReady)
1883   {
1884     // Reset the flag
1885     mNeedToEmitResourceReady = false;
1886
1887     // A visual is ready so control may need relayouting if staged
1888     if(mControlImpl.Self().GetProperty<bool>(Actor::Property::CONNECTED_TO_SCENE))
1889     {
1890       mControlImpl.RelayoutRequest();
1891     }
1892
1893     EmitResourceReadySignal();
1894   }
1895
1896   // Set the pointer to null as the callback manager deletes the callback after execute it.
1897   mIdleCallback = nullptr;
1898 }
1899
1900 Dali::Accessibility::Accessible *Control::Impl::GetAccessibilityObject()
1901 {
1902   if( !accessibilityObject )
1903     accessibilityObject = accessibilityConstructor( mControlImpl.Self() );
1904   return accessibilityObject.get();
1905 }
1906
1907 Dali::Accessibility::Accessible *Control::Impl::GetAccessibilityObject(Dali::Actor actor)
1908 {
1909   if( actor )
1910   {
1911     auto q = Dali::Toolkit::Control::DownCast( actor );
1912     if( q )
1913     {
1914       auto q2 = static_cast< Internal::Control* >( &q.GetImplementation() );
1915       return q2->mImpl->GetAccessibilityObject();
1916     }
1917   }
1918   return nullptr;
1919 }
1920
1921 Control::Impl::AccessibleImpl::AccessibleImpl(Dali::Actor self, Dali::Accessibility::Role role, bool modal)
1922   : self(self), modal(modal)
1923 {
1924   auto control = Dali::Toolkit::Control::DownCast(self);
1925
1926   Internal::Control& internalControl = Toolkit::Internal::GetImplementation( control );
1927   Internal::Control::Impl& controlImpl = Internal::Control::Impl::Get( internalControl );
1928   if( controlImpl.mAccessibilityRole == Dali::Accessibility::Role::UNKNOWN )
1929     controlImpl.mAccessibilityRole = role;
1930
1931   self.PropertySetSignal().Connect(&controlImpl, [this, &controlImpl](Dali::Handle &handle, Dali::Property::Index index, Dali::Property::Value value)
1932   {
1933     if (this->self != Dali::Accessibility::Accessible::GetCurrentlyHighlightedActor())
1934     {
1935       return;
1936     }
1937
1938     if (index == DevelControl::Property::ACCESSIBILITY_NAME
1939       || (index == GetNamePropertyIndex() && !controlImpl.mAccessibilityNameSet))
1940     {
1941       if (controlImpl.mAccessibilityGetNameSignal.Empty())
1942       {
1943         Emit(Dali::Accessibility::ObjectPropertyChangeEvent::NAME);
1944       }
1945     }
1946
1947     if (index == DevelControl::Property::ACCESSIBILITY_DESCRIPTION
1948       || (index == GetDescriptionPropertyIndex() && !controlImpl.mAccessibilityDescriptionSet))
1949     {
1950       if (controlImpl.mAccessibilityGetDescriptionSignal.Empty())
1951       {
1952         Emit(Dali::Accessibility::ObjectPropertyChangeEvent::DESCRIPTION);
1953       }
1954     }
1955   });
1956 }
1957
1958 std::string Control::Impl::AccessibleImpl::GetName()
1959 {
1960   auto control = Dali::Toolkit::Control::DownCast(self);
1961
1962   Internal::Control& internalControl = Toolkit::Internal::GetImplementation( control );
1963   Internal::Control::Impl& controlImpl = Internal::Control::Impl::Get( internalControl );
1964
1965   if (!controlImpl.mAccessibilityGetNameSignal.Empty()) {
1966       std::string ret;
1967       controlImpl.mAccessibilityGetNameSignal.Emit(ret);
1968       return ret;
1969   }
1970
1971   if (controlImpl.mAccessibilityNameSet)
1972     return controlImpl.mAccessibilityName;
1973
1974   if (auto raw = GetNameRaw(); !raw.empty())
1975     return raw;
1976
1977   return self.GetProperty< std::string >( Actor::Property::NAME );
1978 }
1979
1980 std::string Control::Impl::AccessibleImpl::GetNameRaw()
1981 {
1982   return {};
1983 }
1984
1985 std::string Control::Impl::AccessibleImpl::GetDescription()
1986 {
1987   auto control = Dali::Toolkit::Control::DownCast(self);
1988
1989   Internal::Control& internalControl = Toolkit::Internal::GetImplementation( control );
1990   Internal::Control::Impl& controlImpl = Internal::Control::Impl::Get( internalControl );
1991
1992   if (!controlImpl.mAccessibilityGetDescriptionSignal.Empty()) {
1993       std::string ret;
1994       controlImpl.mAccessibilityGetDescriptionSignal.Emit(ret);
1995       return ret;
1996   }
1997
1998   if (controlImpl.mAccessibilityDescriptionSet)
1999     return controlImpl.mAccessibilityDescription;
2000
2001   return GetDescriptionRaw();
2002 }
2003
2004 std::string Control::Impl::AccessibleImpl::GetDescriptionRaw()
2005 {
2006   return "";
2007 }
2008
2009 Dali::Accessibility::Accessible* Control::Impl::AccessibleImpl::GetParent()
2010 {
2011   return Dali::Accessibility::Accessible::Get( self.GetParent() );
2012 }
2013
2014 size_t Control::Impl::AccessibleImpl::GetChildCount()
2015 {
2016   return self.GetChildCount();
2017 }
2018
2019 Dali::Accessibility::Accessible* Control::Impl::AccessibleImpl::GetChildAtIndex( size_t index )
2020 {
2021   return Dali::Accessibility::Accessible::Get( self.GetChildAt( static_cast< unsigned int >( index ) ) );
2022 }
2023
2024 size_t Control::Impl::AccessibleImpl::GetIndexInParent()
2025 {
2026   auto s = self;
2027   auto parent = s.GetParent();
2028   DALI_ASSERT_ALWAYS( parent && "can't call GetIndexInParent on object without parent" );
2029   auto count = parent.GetChildCount();
2030   for( auto i = 0u; i < count; ++i )
2031   {
2032     auto c = parent.GetChildAt( i );
2033     if( c == s )
2034       return i;
2035   }
2036   DALI_ASSERT_ALWAYS( false && "object isn't child of it's parent" );
2037   return static_cast<size_t>(-1);
2038 }
2039
2040 Dali::Accessibility::Role Control::Impl::AccessibleImpl::GetRole()
2041 {
2042   return self.GetProperty<Dali::Accessibility::Role>( Toolkit::DevelControl::Property::ACCESSIBILITY_ROLE );
2043 }
2044
2045 Dali::Accessibility::States Control::Impl::AccessibleImpl::CalculateStates()
2046 {
2047   Dali::Accessibility::States s;
2048   s[Dali::Accessibility::State::FOCUSABLE] = self.GetProperty< bool >( Actor::Property::KEYBOARD_FOCUSABLE );
2049   s[Dali::Accessibility::State::FOCUSED] = Toolkit::KeyboardFocusManager::Get().GetCurrentFocusActor() == self;
2050   if(self.GetProperty( Toolkit::DevelControl::Property::ACCESSIBILITY_HIGHLIGHTABLE ).GetType() == Property::NONE )
2051     s[Dali::Accessibility::State::HIGHLIGHTABLE] = false;
2052   else
2053     s[Dali::Accessibility::State::HIGHLIGHTABLE] = self.GetProperty( Toolkit::DevelControl::Property::ACCESSIBILITY_HIGHLIGHTABLE ).Get< bool >();
2054   s[Dali::Accessibility::State::HIGHLIGHTED] = GetCurrentlyHighlightedActor() == self;
2055   s[Dali::Accessibility::State::ENABLED] = true;
2056   s[Dali::Accessibility::State::SENSITIVE] = true;
2057   s[Dali::Accessibility::State::ANIMATED] = self.GetProperty( Toolkit::DevelControl::Property::ACCESSIBILITY_ANIMATED ).Get< bool >();
2058   s[Dali::Accessibility::State::VISIBLE] = true;
2059   if( modal )
2060   {
2061     s[Dali::Accessibility::State::MODAL] = true;
2062   }
2063   s[Dali::Accessibility::State::SHOWING] = !self.GetProperty( Dali::DevelActor::Property::CULLED ).Get< bool >()
2064                                          && self.GetCurrentProperty< bool >( Actor::Property::VISIBLE );
2065
2066   s[Dali::Accessibility::State::DEFUNCT] = !self.GetProperty( Dali::DevelActor::Property::CONNECTED_TO_SCENE ).Get< bool >();
2067   return s;
2068 }
2069
2070 Dali::Accessibility::States Control::Impl::AccessibleImpl::GetStates()
2071 {
2072   return CalculateStates();
2073 }
2074
2075 Dali::Accessibility::Attributes Control::Impl::AccessibleImpl::GetAttributes()
2076 {
2077   std::unordered_map< std::string, std::string > attribute_map;
2078   auto q = Dali::Toolkit::Control::DownCast( self );
2079   auto w =
2080       q.GetProperty( Dali::Toolkit::DevelControl::Property::ACCESSIBILITY_ATTRIBUTES );
2081   auto z = w.GetMap();
2082
2083   if( z )
2084   {
2085     auto map_size = z->Count();
2086
2087     for( unsigned int i = 0; i < map_size; i++ )
2088     {
2089       auto map_key = z->GetKeyAt( i );
2090       if( map_key.type == Property::Key::STRING )
2091       {
2092         std::string map_value;
2093         if( z->GetValue( i ).Get( map_value ) )
2094         {
2095           attribute_map.emplace( std::move( map_key.stringKey ),
2096                                  std::move( map_value ) );
2097         }
2098       }
2099     }
2100   }
2101
2102   return attribute_map;
2103 }
2104
2105 Dali::Accessibility::ComponentLayer Control::Impl::AccessibleImpl::GetLayer()
2106 {
2107   return Dali::Accessibility::ComponentLayer::WINDOW;
2108 }
2109
2110 Dali::Rect<> Control::Impl::AccessibleImpl::GetExtents( Dali::Accessibility::CoordType ctype )
2111 {
2112   Vector2 screenPosition =
2113       self.GetProperty( Dali::DevelActor::Property::SCREEN_POSITION )
2114           .Get< Vector2 >();
2115   auto size = self.GetCurrentProperty< Vector3 >( Actor::Property::SIZE ) * self.GetCurrentProperty< Vector3 >( Actor::Property::WORLD_SCALE );
2116   bool positionUsesAnchorPoint =
2117       self.GetProperty( Dali::DevelActor::Property::POSITION_USES_ANCHOR_POINT )
2118           .Get< bool >();
2119   Vector3 anchorPointOffSet =
2120       size * ( positionUsesAnchorPoint ? self.GetCurrentProperty< Vector3 >( Actor::Property::ANCHOR_POINT )
2121                                        : AnchorPoint::TOP_LEFT );
2122   Vector2 position = Vector2( screenPosition.x - anchorPointOffSet.x,
2123                               screenPosition.y - anchorPointOffSet.y );
2124
2125   return { position.x, position.y, size.x, size.y };
2126 }
2127
2128 int16_t Control::Impl::AccessibleImpl::GetMdiZOrder() { return 0; }
2129 double Control::Impl::AccessibleImpl::GetAlpha() { return 0; }
2130
2131 bool Control::Impl::AccessibleImpl::GrabFocus()
2132 {
2133   return Toolkit::KeyboardFocusManager::Get().SetCurrentFocusActor( self );
2134 }
2135
2136 static Dali::Actor CreateHighlightIndicatorActor()
2137 {
2138   std::string focusBorderImagePath(AssetManager::GetDaliImagePath());
2139   focusBorderImagePath += "/keyboard_focus.9.png";
2140   // Create the default if it hasn't been set and one that's shared by all the
2141   // keyboard focusable actors
2142   auto actor = Toolkit::ImageView::New( focusBorderImagePath );
2143   actor.SetResizePolicy( ResizePolicy::FILL_TO_PARENT, Dimension::ALL_DIMENSIONS );
2144   DevelControl::AppendAccessibilityAttribute( actor, "highlight", "" );
2145   actor.SetProperty( Toolkit::DevelControl::Property::ACCESSIBILITY_ANIMATED, true);
2146   actor.SetProperty( Toolkit::DevelControl::Property::ACCESSIBILITY_HIGHLIGHTABLE, false );
2147
2148   return actor;
2149 }
2150
2151 bool Control::Impl::AccessibleImpl::GrabHighlight()
2152 {
2153   auto old = GetCurrentlyHighlightedActor();
2154
2155   if( !Dali::Accessibility::IsUp() )
2156       return false;
2157   if( self == old )
2158     return true;
2159   if( old )
2160   {
2161     auto c = dynamic_cast< Dali::Accessibility::Component* >( GetAccessibilityObject( old ) );
2162     if( c )
2163       c->ClearHighlight();
2164   }
2165   auto highlight = GetHighlightActor();
2166   if ( !highlight )
2167   {
2168     highlight = CreateHighlightIndicatorActor();
2169     SetHighlightActor( highlight );
2170   }
2171   highlight.SetProperty( Actor::Property::PARENT_ORIGIN, ParentOrigin::CENTER );
2172   highlight.SetProperty( Actor::Property::ANCHOR_POINT, AnchorPoint::CENTER );
2173   highlight.SetProperty( Actor::Property::POSITION_Z, 1.0f );
2174   highlight.SetProperty( Actor::Property::POSITION, Vector2( 0.0f, 0.0f ));
2175
2176   EnsureSelfVisible();
2177   self.Add( highlight );
2178   SetCurrentlyHighlightedActor( self );
2179   EmitHighlighted( true );
2180
2181   return true;
2182 }
2183
2184
2185
2186 bool Control::Impl::AccessibleImpl::ClearHighlight()
2187 {
2188   if( !Dali::Accessibility::IsUp() )
2189     return false;
2190   if( GetCurrentlyHighlightedActor() == self )
2191   {
2192     self.Remove( GetHighlightActor() );
2193     SetCurrentlyHighlightedActor( {} );
2194     EmitHighlighted( false );
2195     return true;
2196   }
2197   return false;
2198 }
2199
2200 std::string Control::Impl::AccessibleImpl::GetActionName( size_t index )
2201 {
2202   if ( index >= GetActionCount() ) return "";
2203   Dali::TypeInfo type;
2204   self.GetTypeInfo( type );
2205   DALI_ASSERT_ALWAYS( type && "no TypeInfo object" );
2206   return type.GetActionName( index );
2207 }
2208 std::string Control::Impl::AccessibleImpl::GetLocalizedActionName( size_t index )
2209 {
2210   // TODO: add localization
2211   return GetActionName( index );
2212 }
2213 std::string Control::Impl::AccessibleImpl::GetActionDescription( size_t index )
2214 {
2215   return "";
2216 }
2217 size_t Control::Impl::AccessibleImpl::GetActionCount()
2218 {
2219   Dali::TypeInfo type;
2220   self.GetTypeInfo( type );
2221   DALI_ASSERT_ALWAYS( type && "no TypeInfo object" );
2222   return type.GetActionCount();
2223 }
2224 std::string Control::Impl::AccessibleImpl::GetActionKeyBinding( size_t index )
2225 {
2226   return "";
2227 }
2228 bool Control::Impl::AccessibleImpl::DoAction( size_t index )
2229 {
2230   std::string actionName = GetActionName( index );
2231   return self.DoAction( actionName, {} );
2232 }
2233 bool Control::Impl::AccessibleImpl::DoAction(const std::string& name)
2234 {
2235   return self.DoAction( name, {} );
2236 }
2237
2238 bool Control::Impl::AccessibleImpl::DoGesture(const Dali::Accessibility::GestureInfo &gestureInfo)
2239 {
2240   auto control = Dali::Toolkit::Control::DownCast(self);
2241
2242   Internal::Control& internalControl = Toolkit::Internal::GetImplementation( control );
2243   Internal::Control::Impl& controlImpl = Internal::Control::Impl::Get( internalControl );
2244
2245   if (!controlImpl.mAccessibilityDoGestureSignal.Empty()) {
2246       auto ret = std::make_pair(gestureInfo, false);
2247       controlImpl.mAccessibilityDoGestureSignal.Emit(ret);
2248       return ret.second;
2249   }
2250
2251   return false;
2252 }
2253
2254 std::vector<Dali::Accessibility::Relation> Control::Impl::AccessibleImpl::GetRelationSet()
2255 {
2256   auto control = Dali::Toolkit::Control::DownCast(self);
2257
2258   Internal::Control& internalControl = Toolkit::Internal::GetImplementation( control );
2259   Internal::Control::Impl& controlImpl = Internal::Control::Impl::Get( internalControl );
2260
2261   std::vector<Dali::Accessibility::Relation> ret;
2262
2263   auto &v = controlImpl.mAccessibilityRelations;
2264   for (auto i = 0u; i < v.size(); ++i)
2265   {
2266     if ( v[i].empty() )
2267       continue;
2268
2269     ret.emplace_back( Accessibility::Relation{ static_cast<Accessibility::RelationType>(i), v[i] } );
2270   }
2271
2272   return ret;
2273 }
2274
2275 void Control::Impl::AccessibleImpl::EnsureChildVisible(Actor child)
2276 {
2277 }
2278
2279 void Control::Impl::AccessibleImpl::EnsureSelfVisible()
2280 {
2281   auto parent = dynamic_cast<Control::Impl::AccessibleImpl*>(GetParent());
2282   if (parent)
2283   {
2284     parent->EnsureChildVisible(self);
2285   }
2286 }
2287
2288 Property::Index Control::Impl::AccessibleImpl::GetNamePropertyIndex()
2289 {
2290   return Actor::Property::NAME;
2291 }
2292
2293 Property::Index Control::Impl::AccessibleImpl::GetDescriptionPropertyIndex()
2294 {
2295   return Property::INVALID_INDEX;
2296 }
2297
2298 void Control::Impl::PositionOrSizeChangedCallback( PropertyNotification &p )
2299 {
2300   auto self = Dali::Actor::DownCast(p.GetTarget());
2301   if (Dali::Accessibility::IsUp() && !self.GetProperty( Toolkit::DevelControl::Property::ACCESSIBILITY_ANIMATED ).Get< bool >())
2302   {
2303     auto extents = DevelActor::CalculateScreenExtents( self );
2304     Dali::Accessibility::Accessible::Get( self )->EmitBoundsChanged( extents );
2305   }
2306 }
2307
2308 void Control::Impl::CulledChangedCallback( PropertyNotification &p)
2309 {
2310   if (Dali::Accessibility::IsUp())
2311   {
2312     auto self = Dali::Actor::DownCast(p.GetTarget());
2313     Dali::Accessibility::Accessible::Get(self)->EmitShowing( !self.GetProperty( DevelActor::Property::CULLED ).Get<bool>() );
2314   }
2315 }
2316
2317 void Control::Impl::AccessibilityRegister()
2318 {
2319   if (!accessibilityNotificationSet)
2320   {
2321     accessibilityNotificationPosition = mControlImpl.Self().AddPropertyNotification( Actor::Property::POSITION, StepCondition( 0.01f ) );
2322     accessibilityNotificationPosition.SetNotifyMode( PropertyNotification::NOTIFY_ON_CHANGED );
2323     accessibilityNotificationPosition.NotifySignal().Connect( &Control::Impl::PositionOrSizeChangedCallback );
2324
2325     accessibilityNotificationSize = mControlImpl.Self().AddPropertyNotification( Actor::Property::SIZE, StepCondition( 0.01f ) );
2326     accessibilityNotificationSize.SetNotifyMode( PropertyNotification::NOTIFY_ON_CHANGED );
2327     accessibilityNotificationSize.NotifySignal().Connect( &Control::Impl::PositionOrSizeChangedCallback );
2328
2329     accessibilityNotificationCulled = mControlImpl.Self().AddPropertyNotification( DevelActor::Property::CULLED, LessThanCondition( 0.5f ) );
2330     accessibilityNotificationCulled.SetNotifyMode( PropertyNotification::NOTIFY_ON_CHANGED );
2331     accessibilityNotificationCulled.NotifySignal().Connect( &Control::Impl::CulledChangedCallback );
2332
2333     accessibilityNotificationSet = true;
2334   }
2335 }
2336
2337 void Control::Impl::AccessibilityDeregister()
2338 {
2339   if (accessibilityNotificationSet)
2340   {
2341     accessibilityNotificationPosition = {};
2342     accessibilityNotificationSize = {};
2343     accessibilityNotificationCulled = {};
2344     accessibilityNotificationSet = false;
2345   }
2346 }
2347
2348 } // namespace Internal
2349
2350 } // namespace Toolkit
2351
2352 } // namespace Dali