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