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