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