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