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