[dali_2.3.41] Merge branch 'devel/master'
[platform/core/uifw/dali-toolkit.git] / dali-toolkit / internal / controls / control / control-data-impl.cpp
1 /*
2  * Copyright (c) 2024 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/math/math-utils.h>
34 #include <dali/public-api/object/object-registry.h>
35 #include <dali/public-api/object/type-registry-helper.h>
36 #include <cstring>
37 #include <limits>
38
39 // INTERNAL INCLUDES
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/devel-api/visuals/visual-actions-devel.h>
45 #include <dali-toolkit/internal/styling/style-manager-impl.h>
46 #include <dali-toolkit/internal/visuals/visual-base-impl.h>
47 #include <dali-toolkit/internal/visuals/visual-string-constants.h>
48 #include <dali-toolkit/public-api/align-enumerations.h>
49 #include <dali-toolkit/public-api/controls/image-view/image-view.h>
50 #include <dali-toolkit/public-api/focus-manager/keyboard-focus-manager.h>
51 #include <dali-toolkit/public-api/visuals/image-visual-properties.h>
52 #include <dali-toolkit/public-api/visuals/visual-properties.h>
53
54 namespace
55 {
56 const char* READING_INFO_TYPE_NAME           = "name";
57 const char* READING_INFO_TYPE_ROLE           = "role";
58 const char* READING_INFO_TYPE_DESCRIPTION    = "description";
59 const char* READING_INFO_TYPE_STATE          = "state";
60 const char* READING_INFO_TYPE_ATTRIBUTE_NAME = "reading_info_type";
61 const char* READING_INFO_TYPE_SEPARATOR      = "|";
62 } // namespace
63
64 namespace Dali
65 {
66 namespace Toolkit
67 {
68 namespace Internal
69 {
70 extern const Dali::Scripting::StringEnum ControlStateTable[];
71 extern const unsigned int                ControlStateTableCount;
72
73 // Not static or anonymous - shared with other translation units
74 const Scripting::StringEnum ControlStateTable[] = {
75   {"NORMAL", Toolkit::DevelControl::NORMAL},
76   {"FOCUSED", Toolkit::DevelControl::FOCUSED},
77   {"DISABLED", Toolkit::DevelControl::DISABLED},
78 };
79 const unsigned int ControlStateTableCount = sizeof(ControlStateTable) / sizeof(ControlStateTable[0]);
80 const Vector4      FULL_TEXTURE_RECT(0.f, 0.f, 1.f, 1.f);
81
82 namespace
83 {
84 #if defined(DEBUG_ENABLED)
85 Debug::Filter* gLogFilter = Debug::Filter::New(Debug::NoLogging, false, "LOG_CONTROL_VISUALS");
86 #endif
87
88 template<typename T>
89 void Remove(Dictionary<T>& keyValues, const std::string& name)
90 {
91   keyValues.Remove(name);
92 }
93
94 void Remove(DictionaryKeys& keys, const std::string& name)
95 {
96   DictionaryKeys::iterator iter = std::find(keys.begin(), keys.end(), name);
97   if(iter != keys.end())
98   {
99     keys.erase(iter);
100   }
101 }
102
103 /**
104  *  Finds visual in given array, returning true if found along with the iterator for that visual as a out parameter
105  */
106 bool FindVisual(Property::Index targetIndex, const RegisteredVisualContainer& visuals, RegisteredVisualContainer::Iterator& iter)
107 {
108   for(iter = visuals.Begin(); iter != visuals.End(); iter++)
109   {
110     if((*iter)->index == targetIndex)
111     {
112       return true;
113     }
114   }
115   return false;
116 }
117
118 /**
119  *  Finds visual in given array, returning true if found along with the iterator for that visual as a out parameter
120  */
121 bool FindVisual(std::string visualName, const RegisteredVisualContainer& visuals, RegisteredVisualContainer::Iterator& iter)
122 {
123   for(iter = visuals.Begin(); iter != visuals.End(); iter++)
124   {
125     Toolkit::Visual::Base visual = (*iter)->visual;
126     if(visual && visual.GetName() == visualName)
127     {
128       return true;
129     }
130   }
131   return false;
132 }
133
134 /**
135  *  Finds visual in given array, returning true if found along with the iterator for that visual as a out parameter
136  */
137 bool FindVisual(const Toolkit::Visual::Base findVisual, const RegisteredVisualContainer& visuals, RegisteredVisualContainer::Iterator& iter)
138 {
139   for(iter = visuals.Begin(); iter != visuals.End(); iter++)
140   {
141     Toolkit::Visual::Base visual = (*iter)->visual;
142     if(visual && visual == findVisual)
143     {
144       return true;
145     }
146   }
147   return false;
148 }
149
150 /**
151  *  Finds internal visual in given array, returning true if found along with the iterator for that visual as a out parameter
152  */
153 bool FindVisual(const Visual::Base& findInternalVisual, const RegisteredVisualContainer& visuals, RegisteredVisualContainer::Iterator& iter)
154 {
155   for(iter = visuals.Begin(); iter != visuals.End(); iter++)
156   {
157     Visual::Base& visual = Toolkit::GetImplementation((*iter)->visual);
158     if((&visual == &findInternalVisual))
159     {
160       return true;
161     }
162   }
163   return false;
164 }
165
166 void FindChangableVisuals(Dictionary<Property::Map>& stateVisualsToAdd,
167                           Dictionary<Property::Map>& stateVisualsToChange,
168                           DictionaryKeys&            stateVisualsToRemove)
169 {
170   DictionaryKeys copyOfStateVisualsToRemove = stateVisualsToRemove;
171
172   for(DictionaryKeys::iterator iter = copyOfStateVisualsToRemove.begin();
173       iter != copyOfStateVisualsToRemove.end();
174       ++iter)
175   {
176     const std::string& visualName = (*iter);
177     Property::Map*     toMap      = stateVisualsToAdd.Find(visualName);
178     if(toMap)
179     {
180       stateVisualsToChange.Add(visualName, *toMap);
181       stateVisualsToAdd.Remove(visualName);
182       Remove(stateVisualsToRemove, visualName);
183     }
184   }
185 }
186
187 Toolkit::Visual::Base GetVisualByName(
188   const RegisteredVisualContainer& visuals,
189   const std::string&               visualName)
190 {
191   Toolkit::Visual::Base visualHandle;
192
193   RegisteredVisualContainer::Iterator iter;
194   for(iter = visuals.Begin(); iter != visuals.End(); iter++)
195   {
196     Toolkit::Visual::Base visual = (*iter)->visual;
197     if(visual && visual.GetName() == visualName)
198     {
199       visualHandle = visual;
200       break;
201     }
202   }
203   return visualHandle;
204 }
205
206 Toolkit::Visual::Base GetVisualByIndex(
207   const RegisteredVisualContainer& visuals,
208   Property::Index                  index)
209 {
210   Toolkit::Visual::Base visualHandle;
211
212   RegisteredVisualContainer::Iterator iter;
213   for(iter = visuals.Begin(); iter != visuals.End(); iter++)
214   {
215     if((*iter)->index == index)
216     {
217       visualHandle = (*iter)->visual;
218       break;
219     }
220   }
221   return visualHandle;
222 }
223
224 /**
225  * Move visual from source to destination container
226  */
227 void MoveVisual(RegisteredVisualContainer::Iterator sourceIter, RegisteredVisualContainer& source, RegisteredVisualContainer& destination)
228 {
229   Toolkit::Visual::Base visual = (*sourceIter)->visual;
230   if(visual)
231   {
232     RegisteredVisual* rv = source.Release(sourceIter);
233     destination.PushBack(rv);
234   }
235 }
236
237 /**
238  * Discard visual from source to visual factory.
239  */
240 void DiscardVisual(RegisteredVisualContainer::Iterator sourceIter, RegisteredVisualContainer& source)
241 {
242   Toolkit::Visual::Base visual = (*sourceIter)->visual;
243   if(visual)
244   {
245     if(DALI_LIKELY(Dali::Adaptor::IsAvailable()))
246     {
247       Toolkit::VisualFactory::Get().DiscardVisual(visual);
248     }
249   }
250
251   source.Erase(sourceIter);
252 }
253
254 /**
255  * Performs actions as requested using the action name.
256  * @param[in] object The object on which to perform the action.
257  * @param[in] actionName The action to perform.
258  * @param[in] attributes The attributes with which to perfrom this action.
259  * @return true if action has been accepted by this control
260  */
261 constexpr const char* ACTION_ACCESSIBILITY_ACTIVATE  = "activate";
262 constexpr const char* ACTION_ACCESSIBILITY_ESCAPE    = "escape";
263 constexpr const char* ACTION_ACCESSIBILITY_INCREMENT = "increment";
264 constexpr const char* ACTION_ACCESSIBILITY_DECREMENT = "decrement";
265
266 // Legacy actions
267 constexpr const char* ACTION_ACCESSIBILITY_READING_CANCELLED = "ReadingCancelled";
268 constexpr const char* ACTION_ACCESSIBILITY_READING_PAUSED    = "ReadingPaused";
269 constexpr const char* ACTION_ACCESSIBILITY_READING_RESUMED   = "ReadingResumed";
270 constexpr const char* ACTION_ACCESSIBILITY_READING_SKIPPED   = "ReadingSkipped";
271 constexpr const char* ACTION_ACCESSIBILITY_READING_STOPPED   = "ReadingStopped";
272
273 bool PerformAccessibilityAction(Toolkit::Control control, const std::string& actionName, const Property::Map& attributes)
274 {
275   using Dali::Accessibility::ActionType;
276   DALI_ASSERT_DEBUG(control);
277   DALI_ASSERT_DEBUG(!DevelControl::AccessibilityActionSignal(control).Empty());
278
279   ActionType action = ActionType::MAX_COUNT;
280   if(actionName == ACTION_ACCESSIBILITY_ACTIVATE)
281   {
282     action = ActionType::ACTIVATE;
283   }
284   else if(actionName == ACTION_ACCESSIBILITY_ESCAPE)
285   {
286     action = ActionType::ESCAPE;
287   }
288   else if(actionName == ACTION_ACCESSIBILITY_INCREMENT)
289   {
290     action = ActionType::INCREMENT;
291   }
292   else if(actionName == ACTION_ACCESSIBILITY_DECREMENT)
293   {
294     action = ActionType::DECREMENT;
295   }
296
297   if(action != ActionType::MAX_COUNT)
298   {
299     bool success = DevelControl::AccessibilityActionSignal(control).Emit({action, Dali::Actor{}});
300     DALI_LOG_INFO(gLogFilter, Debug::Verbose, "Performed AccessibilityAction: %s, success : %d\n", actionName.c_str(), success);
301     return success;
302   }
303
304   return false;
305 }
306
307 bool PerformLegacyAccessibilityAction(Toolkit::Control control, const std::string& actionName)
308 {
309   bool ret = true;
310   if(0 == strcmp(actionName.c_str(), ACTION_ACCESSIBILITY_ACTIVATE))
311   {
312     // if cast succeeds there is an implementation so no need to check
313     if(!DevelControl::AccessibilityActivateSignal(control).Empty())
314     {
315       DevelControl::AccessibilityActivateSignal(control).Emit();
316     }
317     else
318     {
319       ret = Internal::GetImplementation(control).OnAccessibilityActivated();
320     }
321   }
322   else if(0 == strcmp(actionName.c_str(), ACTION_ACCESSIBILITY_READING_SKIPPED))
323   {
324     // if cast succeeds there is an implementation so no need to check
325     if(!DevelControl::AccessibilityReadingSkippedSignal(control).Empty())
326     {
327       DevelControl::AccessibilityReadingSkippedSignal(control).Emit();
328     }
329   }
330   else if(0 == strcmp(actionName.c_str(), ACTION_ACCESSIBILITY_READING_PAUSED))
331   {
332     // if cast succeeds there is an implementation so no need to check
333     if(!DevelControl::AccessibilityReadingPausedSignal(control).Empty())
334     {
335       DevelControl::AccessibilityReadingPausedSignal(control).Emit();
336     }
337   }
338   else if(0 == strcmp(actionName.c_str(), ACTION_ACCESSIBILITY_READING_RESUMED))
339   {
340     // if cast succeeds there is an implementation so no need to check
341     if(!DevelControl::AccessibilityReadingResumedSignal(control).Empty())
342     {
343       DevelControl::AccessibilityReadingResumedSignal(control).Emit();
344     }
345   }
346   else if(0 == strcmp(actionName.c_str(), ACTION_ACCESSIBILITY_READING_CANCELLED))
347   {
348     // if cast succeeds there is an implementation so no need to check
349     if(!DevelControl::AccessibilityReadingCancelledSignal(control).Empty())
350     {
351       DevelControl::AccessibilityReadingCancelledSignal(control).Emit();
352     }
353   }
354   else if(0 == strcmp(actionName.c_str(), ACTION_ACCESSIBILITY_READING_STOPPED))
355   {
356     // if cast succeeds there is an implementation so no need to check
357     if(!DevelControl::AccessibilityReadingStoppedSignal(control).Empty())
358     {
359       DevelControl::AccessibilityReadingStoppedSignal(control).Emit();
360     }
361   }
362   else
363   {
364     ret = false;
365   }
366
367   if(ret)
368   {
369     DALI_LOG_INFO(gLogFilter, Debug::Verbose, "Performed Legacy AccessibilityAction: %s\n", actionName.c_str());
370   }
371   return ret;
372 }
373
374 bool DoAccessibilityAction(BaseObject* object, const std::string& actionName, const Property::Map& attributes)
375 {
376   Dali::BaseHandle handle(object);
377
378   Toolkit::Control control = Toolkit::Control::DownCast(handle);
379
380   DALI_ASSERT_ALWAYS(control);
381
382   if(!DevelControl::AccessibilityActionSignal(control).Empty())
383   {
384     return PerformAccessibilityAction(control, actionName, attributes);
385   }
386
387   // Fall back to legacy action is no ActionSignal is connected
388   return PerformLegacyAccessibilityAction(control, actionName);
389 }
390
391 bool DoLegacyAccessibilityAction(BaseObject* object, const std::string& actionName, const Property::Map& attributes)
392 {
393   Dali::BaseHandle handle(object);
394
395   Toolkit::Control control = Toolkit::Control::DownCast(handle);
396
397   DALI_ASSERT_ALWAYS(control);
398
399   return PerformLegacyAccessibilityAction(control, actionName);
400 }
401
402 /**
403  * Connects a callback function with the object's signals.
404  * @param[in] object The object providing the signal.
405  * @param[in] tracker Used to disconnect the signal.
406  * @param[in] signalName The signal to connect to.
407  * @param[in] functor A newly allocated FunctorDelegate.
408  * @return True if the signal was connected.
409  * @post If a signal was connected, ownership of functor was passed to CallbackBase. Otherwise the caller is responsible for deleting the unused functor.
410  */
411 const char* SIGNAL_KEY_EVENT              = "keyEvent";
412 const char* SIGNAL_KEY_INPUT_FOCUS_GAINED = "keyInputFocusGained";
413 const char* SIGNAL_KEY_INPUT_FOCUS_LOST   = "keyInputFocusLost";
414 const char* SIGNAL_TAPPED                 = "tapped";
415 const char* SIGNAL_PANNED                 = "panned";
416 const char* SIGNAL_PINCHED                = "pinched";
417 const char* SIGNAL_LONG_PRESSED           = "longPressed";
418 const char* SIGNAL_GET_NAME               = "getName";
419 const char* SIGNAL_GET_DESCRIPTION        = "getDescription";
420 const char* SIGNAL_DO_GESTURE             = "doGesture";
421 static bool DoConnectSignal(BaseObject* object, ConnectionTrackerInterface* tracker, const std::string& signalName, FunctorDelegate* functor)
422 {
423   Dali::BaseHandle handle(object);
424
425   bool             connected(false);
426   Toolkit::Control control = Toolkit::Control::DownCast(handle);
427   if(control)
428   {
429     Internal::Control& controlImpl(Internal::GetImplementation(control));
430     connected = true;
431
432     if(0 == strcmp(signalName.c_str(), SIGNAL_KEY_EVENT))
433     {
434       controlImpl.KeyEventSignal().Connect(tracker, functor);
435     }
436     else if(0 == strcmp(signalName.c_str(), SIGNAL_KEY_INPUT_FOCUS_GAINED))
437     {
438       controlImpl.KeyInputFocusGainedSignal().Connect(tracker, functor);
439     }
440     else if(0 == strcmp(signalName.c_str(), SIGNAL_KEY_INPUT_FOCUS_LOST))
441     {
442       controlImpl.KeyInputFocusLostSignal().Connect(tracker, functor);
443     }
444     else if(0 == strcmp(signalName.c_str(), SIGNAL_TAPPED))
445     {
446       controlImpl.EnableGestureDetection(GestureType::TAP);
447       controlImpl.GetTapGestureDetector().DetectedSignal().Connect(tracker, functor);
448     }
449     else if(0 == strcmp(signalName.c_str(), SIGNAL_PANNED))
450     {
451       controlImpl.EnableGestureDetection(GestureType::PAN);
452       controlImpl.GetPanGestureDetector().DetectedSignal().Connect(tracker, functor);
453     }
454     else if(0 == strcmp(signalName.c_str(), SIGNAL_PINCHED))
455     {
456       controlImpl.EnableGestureDetection(GestureType::PINCH);
457       controlImpl.GetPinchGestureDetector().DetectedSignal().Connect(tracker, functor);
458     }
459     else if(0 == strcmp(signalName.c_str(), SIGNAL_LONG_PRESSED))
460     {
461       controlImpl.EnableGestureDetection(GestureType::LONG_PRESS);
462       controlImpl.GetLongPressGestureDetector().DetectedSignal().Connect(tracker, functor);
463     }
464     else if(0 == strcmp(signalName.c_str(), SIGNAL_GET_NAME))
465     {
466       DevelControl::AccessibilityGetNameSignal(control).Connect(tracker, functor);
467     }
468     else if(0 == strcmp(signalName.c_str(), SIGNAL_GET_DESCRIPTION))
469     {
470       DevelControl::AccessibilityGetDescriptionSignal(control).Connect(tracker, functor);
471     }
472     else if(0 == strcmp(signalName.c_str(), SIGNAL_DO_GESTURE))
473     {
474       DevelControl::AccessibilityDoGestureSignal(control).Connect(tracker, functor);
475     }
476   }
477   return connected;
478 }
479
480 /**
481  * Creates control through type registry
482  */
483 BaseHandle Create()
484 {
485   return Internal::Control::New();
486 }
487 // Setup signals and actions using the type-registry.
488 DALI_TYPE_REGISTRATION_BEGIN(Control, CustomActor, Create);
489
490 // Note: Properties are registered separately below.
491
492 SignalConnectorType registerSignal1(typeRegistration, SIGNAL_KEY_EVENT, &DoConnectSignal);
493 SignalConnectorType registerSignal2(typeRegistration, SIGNAL_KEY_INPUT_FOCUS_GAINED, &DoConnectSignal);
494 SignalConnectorType registerSignal3(typeRegistration, SIGNAL_KEY_INPUT_FOCUS_LOST, &DoConnectSignal);
495 SignalConnectorType registerSignal4(typeRegistration, SIGNAL_TAPPED, &DoConnectSignal);
496 SignalConnectorType registerSignal5(typeRegistration, SIGNAL_PANNED, &DoConnectSignal);
497 SignalConnectorType registerSignal6(typeRegistration, SIGNAL_PINCHED, &DoConnectSignal);
498 SignalConnectorType registerSignal7(typeRegistration, SIGNAL_LONG_PRESSED, &DoConnectSignal);
499 SignalConnectorType registerSignal8(typeRegistration, SIGNAL_GET_NAME, &DoConnectSignal);
500 SignalConnectorType registerSignal9(typeRegistration, SIGNAL_GET_DESCRIPTION, &DoConnectSignal);
501 SignalConnectorType registerSignal10(typeRegistration, SIGNAL_DO_GESTURE, &DoConnectSignal);
502
503 // === Accessibility Actions === START
504 TypeAction registerAction1(typeRegistration, ACTION_ACCESSIBILITY_ACTIVATE, &DoAccessibilityAction);
505 TypeAction registerAction2(typeRegistration, ACTION_ACCESSIBILITY_ESCAPE, &DoAccessibilityAction);
506 TypeAction registerAction3(typeRegistration, ACTION_ACCESSIBILITY_INCREMENT, &DoAccessibilityAction);
507 TypeAction registerAction4(typeRegistration, ACTION_ACCESSIBILITY_DECREMENT, &DoAccessibilityAction);
508 // === Accessibility Actions === END
509
510 // === Legacy Accessibility Actions === START
511 TypeAction registerAction5(typeRegistration, ACTION_ACCESSIBILITY_READING_SKIPPED, &DoLegacyAccessibilityAction);
512 TypeAction registerAction6(typeRegistration, ACTION_ACCESSIBILITY_READING_CANCELLED, &DoLegacyAccessibilityAction);
513 TypeAction registerAction7(typeRegistration, ACTION_ACCESSIBILITY_READING_STOPPED, &DoLegacyAccessibilityAction);
514 TypeAction registerAction8(typeRegistration, ACTION_ACCESSIBILITY_READING_PAUSED, &DoLegacyAccessibilityAction);
515 TypeAction registerAction9(typeRegistration, ACTION_ACCESSIBILITY_READING_RESUMED, &DoLegacyAccessibilityAction);
516 // === Legacy Accessibility Actions === END
517
518 DALI_TYPE_REGISTRATION_END()
519
520 /**
521  * @brief Iterate through given container and setOffScene any visual found
522  *
523  * @param[in] container Container of visuals
524  * @param[in] parent Parent actor to remove visuals from
525  */
526 void SetVisualsOffScene(const RegisteredVisualContainer& container, Actor parent)
527 {
528   for(auto iter = container.Begin(), end = container.End(); iter != end; iter++)
529   {
530     if((*iter)->visual)
531     {
532       DALI_LOG_INFO(gLogFilter, Debug::Verbose, "Control::SetOffScene Setting visual(%d) off stage\n", (*iter)->index);
533       Toolkit::GetImplementation((*iter)->visual).SetOffScene(parent);
534     }
535   }
536 }
537
538 Dali::Rect<> GetShowingGeometry(Dali::Rect<> rect, Dali::Toolkit::DevelControl::ControlAccessible* accessible)
539 {
540   Rect<>  parentRect;
541   Vector2 currentPosition;
542   auto    parent = dynamic_cast<Toolkit::DevelControl::ControlAccessible*>(accessible->GetParent());
543
544   while(parent)
545   {
546     parentRect = parent->GetExtents(Dali::Accessibility::CoordinateType::WINDOW);
547
548     currentPosition.x = rect.x;
549     currentPosition.y = rect.y;
550
551     rect.x      = rect.x > parentRect.x ? rect.x : parentRect.x;
552     rect.y      = rect.y > parentRect.y ? rect.y : parentRect.y;
553     rect.width  = currentPosition.x + rect.width < parentRect.x + parentRect.width ? currentPosition.x + rect.width - rect.x : parentRect.x + parentRect.width - rect.x;
554     rect.height = currentPosition.y + rect.height < parentRect.y + parentRect.height ? currentPosition.y + rect.height - rect.y : parentRect.y + parentRect.height - rect.y;
555
556     if(rect.width < 0 || rect.height < 0)
557     {
558       return rect;
559     }
560
561     parent = dynamic_cast<Toolkit::DevelControl::ControlAccessible*>(parent->GetParent());
562   }
563
564   return rect;
565 }
566
567 static bool IsShowingGeometryOnScreen(Dali::Rect<> rect)
568 {
569   return rect.width > 0 && rect.height > 0;
570 }
571
572 } // unnamed namespace
573
574 // clang-format off
575 // Properties registered without macro to use specific member variables.
576 const PropertyRegistration Control::Impl::PROPERTY_1(typeRegistration,  "styleName",                      Toolkit::Control::Property::STYLE_NAME,                            Property::STRING,  &Control::Impl::SetProperty, &Control::Impl::GetProperty);
577 const PropertyRegistration Control::Impl::PROPERTY_4(typeRegistration,  "keyInputFocus",                  Toolkit::Control::Property::KEY_INPUT_FOCUS,                       Property::BOOLEAN, &Control::Impl::SetProperty, &Control::Impl::GetProperty);
578 const PropertyRegistration Control::Impl::PROPERTY_5(typeRegistration,  "background",                     Toolkit::Control::Property::BACKGROUND,                            Property::MAP,     &Control::Impl::SetProperty, &Control::Impl::GetProperty);
579 const PropertyRegistration Control::Impl::PROPERTY_6(typeRegistration,  "margin",                         Toolkit::Control::Property::MARGIN,                                Property::EXTENTS, &Control::Impl::SetProperty, &Control::Impl::GetProperty);
580 const PropertyRegistration Control::Impl::PROPERTY_7(typeRegistration,  "padding",                        Toolkit::Control::Property::PADDING,                               Property::EXTENTS, &Control::Impl::SetProperty, &Control::Impl::GetProperty);
581 const PropertyRegistration Control::Impl::PROPERTY_8(typeRegistration,  "tooltip",                        Toolkit::DevelControl::Property::TOOLTIP,                          Property::MAP,     &Control::Impl::SetProperty, &Control::Impl::GetProperty);
582 const PropertyRegistration Control::Impl::PROPERTY_9(typeRegistration,  "state",                          Toolkit::DevelControl::Property::STATE,                            Property::STRING,  &Control::Impl::SetProperty, &Control::Impl::GetProperty);
583 const PropertyRegistration Control::Impl::PROPERTY_10(typeRegistration, "subState",                       Toolkit::DevelControl::Property::SUB_STATE,                        Property::STRING,  &Control::Impl::SetProperty, &Control::Impl::GetProperty);
584 const PropertyRegistration Control::Impl::PROPERTY_11(typeRegistration, "leftFocusableActorId",           Toolkit::DevelControl::Property::LEFT_FOCUSABLE_ACTOR_ID,          Property::INTEGER, &Control::Impl::SetProperty, &Control::Impl::GetProperty);
585 const PropertyRegistration Control::Impl::PROPERTY_12(typeRegistration, "rightFocusableActorId",          Toolkit::DevelControl::Property::RIGHT_FOCUSABLE_ACTOR_ID,         Property::INTEGER, &Control::Impl::SetProperty, &Control::Impl::GetProperty);
586 const PropertyRegistration Control::Impl::PROPERTY_13(typeRegistration, "upFocusableActorId",             Toolkit::DevelControl::Property::UP_FOCUSABLE_ACTOR_ID,            Property::INTEGER, &Control::Impl::SetProperty, &Control::Impl::GetProperty);
587 const PropertyRegistration Control::Impl::PROPERTY_14(typeRegistration, "downFocusableActorId",           Toolkit::DevelControl::Property::DOWN_FOCUSABLE_ACTOR_ID,          Property::INTEGER, &Control::Impl::SetProperty, &Control::Impl::GetProperty);
588 const PropertyRegistration Control::Impl::PROPERTY_15(typeRegistration, "shadow",                         Toolkit::DevelControl::Property::SHADOW,                           Property::MAP,     &Control::Impl::SetProperty, &Control::Impl::GetProperty);
589 const PropertyRegistration Control::Impl::PROPERTY_16(typeRegistration, "accessibilityName",              Toolkit::DevelControl::Property::ACCESSIBILITY_NAME,               Property::STRING,  &Control::Impl::SetProperty, &Control::Impl::GetProperty);
590 const PropertyRegistration Control::Impl::PROPERTY_17(typeRegistration, "accessibilityDescription",       Toolkit::DevelControl::Property::ACCESSIBILITY_DESCRIPTION,        Property::STRING,  &Control::Impl::SetProperty, &Control::Impl::GetProperty);
591 const PropertyRegistration Control::Impl::PROPERTY_18(typeRegistration, "accessibilityTranslationDomain", Toolkit::DevelControl::Property::ACCESSIBILITY_TRANSLATION_DOMAIN, Property::STRING,  &Control::Impl::SetProperty, &Control::Impl::GetProperty);
592 const PropertyRegistration Control::Impl::PROPERTY_19(typeRegistration, "accessibilityRole",              Toolkit::DevelControl::Property::ACCESSIBILITY_ROLE,               Property::INTEGER, &Control::Impl::SetProperty, &Control::Impl::GetProperty);
593 const PropertyRegistration Control::Impl::PROPERTY_20(typeRegistration, "accessibilityHighlightable",     Toolkit::DevelControl::Property::ACCESSIBILITY_HIGHLIGHTABLE,      Property::BOOLEAN, &Control::Impl::SetProperty, &Control::Impl::GetProperty);
594 const PropertyRegistration Control::Impl::PROPERTY_21(typeRegistration, "accessibilityAttributes",        Toolkit::DevelControl::Property::ACCESSIBILITY_ATTRIBUTES,         Property::MAP,     &Control::Impl::SetProperty, &Control::Impl::GetProperty);
595 const PropertyRegistration Control::Impl::PROPERTY_22(typeRegistration, "dispatchKeyEvents",              Toolkit::DevelControl::Property::DISPATCH_KEY_EVENTS,              Property::BOOLEAN, &Control::Impl::SetProperty, &Control::Impl::GetProperty);
596 const PropertyRegistration Control::Impl::PROPERTY_23(typeRegistration, "accessibilityHidden",            Toolkit::DevelControl::Property::ACCESSIBILITY_HIDDEN,             Property::BOOLEAN, &Control::Impl::SetProperty, &Control::Impl::GetProperty);
597 const PropertyRegistration Control::Impl::PROPERTY_24(typeRegistration, "clockwiseFocusableActorId",      Toolkit::DevelControl::Property::CLOCKWISE_FOCUSABLE_ACTOR_ID,     Property::INTEGER, &Control::Impl::SetProperty, &Control::Impl::GetProperty);
598 const PropertyRegistration Control::Impl::PROPERTY_25(typeRegistration, "counterClockwiseFocusableActorId", Toolkit::DevelControl::Property::COUNTER_CLOCKWISE_FOCUSABLE_ACTOR_ID, Property::INTEGER, &Control::Impl::SetProperty, &Control::Impl::GetProperty);
599 const PropertyRegistration Control::Impl::PROPERTY_26(typeRegistration, "automationId",                   Toolkit::DevelControl::Property::AUTOMATION_ID,                    Property::STRING,  &Control::Impl::SetProperty, &Control::Impl::GetProperty);
600 const PropertyRegistration Control::Impl::PROPERTY_27(typeRegistration, "accessibilityValue",             Toolkit::DevelControl::Property::ACCESSIBILITY_VALUE,              Property::STRING,  &Control::Impl::SetProperty, &Control::Impl::GetProperty);
601 const PropertyRegistration Control::Impl::PROPERTY_28(typeRegistration, "accessibilityScrollable",        Toolkit::DevelControl::Property::ACCESSIBILITY_SCROLLABLE,         Property::BOOLEAN, &Control::Impl::SetProperty, &Control::Impl::GetProperty);
602 const PropertyRegistration Control::Impl::PROPERTY_29(typeRegistration, "accessibilityStates",            Toolkit::DevelControl::Property::ACCESSIBILITY_STATES,             Property::INTEGER, &Control::Impl::SetProperty, &Control::Impl::GetProperty);
603 const PropertyRegistration Control::Impl::PROPERTY_30(typeRegistration, "accessibilityIsModal",           Toolkit::DevelControl::Property::ACCESSIBILITY_IS_MODAL,           Property::BOOLEAN, &Control::Impl::SetProperty, &Control::Impl::GetProperty);
604
605 // clang-format on
606
607 Control::Impl::Impl(Control& controlImpl)
608 : mControlImpl(controlImpl),
609   mState(Toolkit::DevelControl::NORMAL),
610   mSubStateName(""),
611   mLeftFocusableActorId(-1),
612   mRightFocusableActorId(-1),
613   mUpFocusableActorId(-1),
614   mDownFocusableActorId(-1),
615   mClockwiseFocusableActorId(-1),
616   mCounterClockwiseFocusableActorId(-1),
617   mStyleName(""),
618   mBackgroundColor(Color::TRANSPARENT),
619   mStartingPinchScale(nullptr),
620   mMargin(0, 0, 0, 0),
621   mPadding(0, 0, 0, 0),
622   mSize(0, 0),
623   mKeyEventSignal(),
624   mKeyInputFocusGainedSignal(),
625   mKeyInputFocusLostSignal(),
626   mResourceReadySignal(),
627   mVisualEventSignal(),
628   mAccessibilityGetNameSignal(),
629   mAccessibilityGetDescriptionSignal(),
630   mAccessibilityDoGestureSignal(),
631   mPinchGestureDetector(),
632   mPanGestureDetector(),
633   mTapGestureDetector(),
634   mLongPressGestureDetector(),
635   mTooltip(NULL),
636   mInputMethodContext(),
637   mIdleCallback(nullptr),
638   mFlags(Control::ControlBehaviour(CONTROL_BEHAVIOUR_DEFAULT)),
639   mIsKeyboardNavigationSupported(false),
640   mIsKeyboardFocusGroup(false),
641   mIsEmittingResourceReadySignal(false),
642   mIdleCallbackRegistered(false),
643   mDispatchKeyEvents(true),
644   mProcessorRegistered(false)
645 {
646   Accessibility::Accessible::RegisterExternalAccessibleGetter([](Dali::Actor actor) -> std::pair<std::shared_ptr<Accessibility::Accessible>, bool> {
647     auto control = Toolkit::Control::DownCast(actor);
648     if(!control)
649     {
650       return {nullptr, true};
651     }
652
653     auto& controlImpl = Toolkit::Internal::GetImplementation(control);
654     if(controlImpl.mImpl->IsCreateAccessibleEnabled())
655     {
656       return {std::shared_ptr<DevelControl::ControlAccessible>(controlImpl.CreateAccessibleObject()), true};
657     }
658
659     return {nullptr, false};
660   });
661   mAccessibilityProps.states[DevelControl::AccessibilityState::ENABLED] = true;
662 }
663
664 Control::Impl::~Impl()
665 {
666   while(!mVisuals.Empty())
667   {
668     auto iter = mVisuals.End() - 1u;
669     StopObservingVisual((*iter)->visual);
670
671     // Discard removed visual. It will be destroyed at next Idle time.
672     DiscardVisual(iter, mVisuals);
673   }
674
675   while(!mRemoveVisuals.Empty())
676   {
677     auto removalIter = mRemoveVisuals.End() - 1u;
678     StopObservingVisual((*removalIter)->visual);
679
680     // Discard removed visual. It will be destroyed at next Idle time.
681     DiscardVisual(removalIter, mRemoveVisuals);
682   }
683
684   // All gesture detectors will be destroyed so no need to disconnect.
685   delete mStartingPinchScale;
686
687   if(mProcessorRegistered && Adaptor::IsAvailable())
688   {
689     // Unregister the processor from the adaptor
690     Adaptor::Get().UnregisterProcessorOnce(*this, true);
691   }
692
693   if(mIdleCallback && Adaptor::IsAvailable())
694   {
695     // Removes the callback from the callback manager in case the control is destroyed before the callback is executed.
696     Adaptor::Get().RemoveIdle(mIdleCallback);
697   }
698 }
699
700 Control::Impl& Control::Impl::Get(Internal::Control& internalControl)
701 {
702   DALI_ASSERT_ALWAYS(Stage::IsCoreThread() && "Core is not installed. Might call this API from worker thread?");
703
704   return *internalControl.mImpl;
705 }
706
707 const Control::Impl& Control::Impl::Get(const Internal::Control& internalControl)
708 {
709   DALI_ASSERT_ALWAYS(Stage::IsCoreThread() && "Core is not installed. Might call this API from worker thread?");
710
711   return *internalControl.mImpl;
712 }
713
714 void Control::Impl::CheckHighlightedObjectGeometry()
715 {
716   auto accessible = GetAccessibleObject();
717   if(DALI_LIKELY(accessible))
718   {
719     auto lastPosition   = accessible->GetLastPosition();
720     auto accessibleRect = accessible->GetExtents(Dali::Accessibility::CoordinateType::WINDOW);
721     auto rect           = GetShowingGeometry(accessibleRect, accessible.get());
722
723     switch(mAccessibilityLastScreenRelativeMoveType)
724     {
725       case Dali::Accessibility::ScreenRelativeMoveType::OUTSIDE:
726       {
727         if(IsShowingGeometryOnScreen(rect))
728         {
729           mAccessibilityLastScreenRelativeMoveType = Dali::Accessibility::ScreenRelativeMoveType::INSIDE;
730         }
731         break;
732       }
733       case Dali::Accessibility::ScreenRelativeMoveType::INSIDE:
734       {
735         if(rect.width < 0 && !Dali::Equals(accessibleRect.x, lastPosition.x))
736         {
737           mAccessibilityLastScreenRelativeMoveType = (accessibleRect.x < lastPosition.x) ? Dali::Accessibility::ScreenRelativeMoveType::OUTGOING_TOP_LEFT : Dali::Accessibility::ScreenRelativeMoveType::OUTGOING_BOTTOM_RIGHT;
738         }
739         if(rect.height < 0 && !Dali::Equals(accessibleRect.y, lastPosition.y))
740         {
741           mAccessibilityLastScreenRelativeMoveType = (accessibleRect.y < lastPosition.y) ? Dali::Accessibility::ScreenRelativeMoveType::OUTGOING_TOP_LEFT : Dali::Accessibility::ScreenRelativeMoveType::OUTGOING_BOTTOM_RIGHT;
742         }
743         // notify AT-clients on outgoing moves only
744         if(mAccessibilityLastScreenRelativeMoveType != Dali::Accessibility::ScreenRelativeMoveType::INSIDE)
745         {
746           accessible->EmitMovedOutOfScreen(mAccessibilityLastScreenRelativeMoveType);
747         }
748         break;
749       }
750       case Dali::Accessibility::ScreenRelativeMoveType::OUTGOING_TOP_LEFT:
751       case Dali::Accessibility::ScreenRelativeMoveType::OUTGOING_BOTTOM_RIGHT:
752       {
753         if(IsShowingGeometryOnScreen(rect))
754         {
755           mAccessibilityLastScreenRelativeMoveType = Dali::Accessibility::ScreenRelativeMoveType::INSIDE;
756         }
757         else
758         {
759           mAccessibilityLastScreenRelativeMoveType = Dali::Accessibility::ScreenRelativeMoveType::OUTSIDE;
760         }
761         break;
762       }
763       default:
764       {
765         break;
766       }
767     }
768
769     accessible->SetLastPosition(Vector2(accessibleRect.x, accessibleRect.y));
770   }
771 }
772
773 void Control::Impl::RegisterAccessibilityPositionPropertyNotification()
774 {
775   if(mIsAccessibilityPositionPropertyNotificationSet)
776   {
777     return;
778   }
779   // set default value until first move of object is detected
780   mAccessibilityLastScreenRelativeMoveType = Dali::Accessibility::ScreenRelativeMoveType::OUTSIDE;
781   // recalculate mAccessibilityLastScreenRelativeMoveType accordingly to the initial position
782   CheckHighlightedObjectGeometry();
783   mAccessibilityPositionNotification = mControlImpl.Self().AddPropertyNotification(Actor::Property::WORLD_POSITION, StepCondition(1.0f, 1.0f));
784   mAccessibilityPositionNotification.SetNotifyMode(PropertyNotification::NOTIFY_ON_CHANGED);
785   mAccessibilityPositionNotification.NotifySignal().Connect(this, [this](PropertyNotification&) { CheckHighlightedObjectGeometry(); });
786   mIsAccessibilityPositionPropertyNotificationSet = true;
787 }
788
789 void Control::Impl::UnregisterAccessibilityPositionPropertyNotification()
790 {
791   mControlImpl.Self().RemovePropertyNotification(mAccessibilityPositionNotification);
792   mIsAccessibilityPositionPropertyNotificationSet = false;
793 }
794
795 void Control::Impl::RegisterAccessibilityPropertySetSignal()
796 {
797   if(mIsAccessibilityPropertySetSignalRegistered)
798   {
799     return;
800   }
801   mControlImpl.Self().PropertySetSignal().Connect(this, &Control::Impl::OnAccessibilityPropertySet);
802   mIsAccessibilityPropertySetSignalRegistered = true;
803 }
804
805 void Control::Impl::UnregisterAccessibilityPropertySetSignal()
806 {
807   if(!mIsAccessibilityPropertySetSignalRegistered)
808   {
809     return;
810   }
811   mControlImpl.Self().PropertySetSignal().Disconnect(this, &Control::Impl::OnAccessibilityPropertySet);
812   mIsAccessibilityPropertySetSignalRegistered = false;
813 }
814
815 void Control::Impl::OnAccessibilityPropertySet(Dali::Handle& handle, Dali::Property::Index index, const Dali::Property::Value& value)
816 {
817   auto accessible = GetAccessibleObject();
818   if(DALI_LIKELY(accessible))
819   {
820     if(mAccessibilityGetNameSignal.Empty())
821     {
822       if(index == DevelControl::Property::ACCESSIBILITY_NAME || (mAccessibilityProps.name.empty() && index == accessible->GetNamePropertyIndex()))
823       {
824         accessible->Emit(Dali::Accessibility::ObjectPropertyChangeEvent::NAME);
825         return;
826       }
827     }
828
829     if(mAccessibilityGetDescriptionSignal.Empty())
830     {
831       if(index == DevelControl::Property::ACCESSIBILITY_DESCRIPTION || (mAccessibilityProps.description.empty() && index == accessible->GetDescriptionPropertyIndex()))
832       {
833         accessible->Emit(Dali::Accessibility::ObjectPropertyChangeEvent::DESCRIPTION);
834         return;
835       }
836     }
837
838     if(index == DevelControl::Property::ACCESSIBILITY_VALUE)
839     {
840       accessible->Emit(Dali::Accessibility::ObjectPropertyChangeEvent::VALUE);
841       return;
842     }
843
844     if(index == DevelControl::Property::ACCESSIBILITY_STATES)
845     {
846       accessible->OnStatePropertySet(mAccessibilityProps.states);
847       return;
848     }
849   }
850 }
851
852 // Gesture Detection Methods
853 void Control::Impl::PinchDetected(Actor actor, const PinchGesture& pinch)
854 {
855   mControlImpl.OnPinch(pinch);
856 }
857
858 void Control::Impl::PanDetected(Actor actor, const PanGesture& pan)
859 {
860   mControlImpl.OnPan(pan);
861 }
862
863 void Control::Impl::TapDetected(Actor actor, const TapGesture& tap)
864 {
865   mControlImpl.OnTap(tap);
866 }
867
868 void Control::Impl::LongPressDetected(Actor actor, const LongPressGesture& longPress)
869 {
870   mControlImpl.OnLongPress(longPress);
871 }
872
873 void Control::Impl::RegisterVisual(Property::Index index, Toolkit::Visual::Base& visual)
874 {
875   RegisterVisual(index, visual, VisualState::ENABLED, DepthIndexValue::NOT_SET);
876 }
877
878 void Control::Impl::RegisterVisual(Property::Index index, Toolkit::Visual::Base& visual, int depthIndex)
879 {
880   RegisterVisual(index, visual, VisualState::ENABLED, DepthIndexValue::SET, depthIndex);
881 }
882
883 void Control::Impl::RegisterVisual(Property::Index index, Toolkit::Visual::Base& visual, bool enabled)
884 {
885   RegisterVisual(index, visual, (enabled ? VisualState::ENABLED : VisualState::DISABLED), DepthIndexValue::NOT_SET);
886 }
887
888 void Control::Impl::RegisterVisual(Property::Index index, Toolkit::Visual::Base& visual, bool enabled, int depthIndex)
889 {
890   RegisterVisual(index, visual, (enabled ? VisualState::ENABLED : VisualState::DISABLED), DepthIndexValue::SET, depthIndex);
891 }
892
893 void Control::Impl::RegisterVisual(Property::Index index, Toolkit::Visual::Base& visual, VisualState::Type enabled, DepthIndexValue::Type depthIndexValueSet, int depthIndex)
894 {
895   DALI_ASSERT_ALWAYS(Stage::IsCoreThread() && "Core is not installed. Might call this API from worker thread?");
896
897   DALI_LOG_INFO(gLogFilter, Debug::Concise, "RegisterVisual:%d \n", index);
898
899   bool  visualReplaced(false);
900   Actor self = mControlImpl.Self();
901
902   // Set the depth index, if not set by caller this will be either the current visual depth, max depth of all visuals
903   // or zero.
904   int requiredDepthIndex = visual.GetDepthIndex();
905
906   if(depthIndexValueSet == DepthIndexValue::SET)
907   {
908     requiredDepthIndex = depthIndex;
909   }
910
911   // Change the depth index value automatically if the visual has DepthIndex to AUTO_INDEX
912   // or if RegisterVisual set DepthIndex to AUTO_INDEX.
913   const bool requiredDepthIndexChanged = (requiredDepthIndex == DepthIndex::AUTO_INDEX);
914
915   // Visual replacement, existing visual should only be removed from stage when replacement ready.
916   if(!mVisuals.Empty())
917   {
918     RegisteredVisualContainer::Iterator registeredVisualsiter;
919     // Check if visual (index) is already registered, this is the current visual.
920     if(FindVisual(index, mVisuals, registeredVisualsiter))
921     {
922       Toolkit::Visual::Base& currentRegisteredVisual = (*registeredVisualsiter)->visual;
923       if(currentRegisteredVisual)
924       {
925         // Store current visual depth index as may need to set the replacement visual to same depth
926         const int currentDepthIndex = (*registeredVisualsiter)->visual.GetDepthIndex();
927
928         // No longer required to know if the replaced visual's resources are ready
929         StopObservingVisual(currentRegisteredVisual);
930
931         // If control staged and visual enabled then visuals will be swapped once ready
932         if(self.GetProperty<bool>(Actor::Property::CONNECTED_TO_SCENE) && enabled)
933         {
934           // Check if visual is currently in the process of being replaced ( is in removal container )
935           RegisteredVisualContainer::Iterator visualQueuedForRemoval;
936           if(FindVisual(index, mRemoveVisuals, visualQueuedForRemoval))
937           {
938             // Visual with same index is already in removal container so current visual pending
939             // Only the the last requested visual will be displayed so remove current visual which is staged but not ready.
940             Toolkit::GetImplementation(currentRegisteredVisual).SetOffScene(self);
941             mVisuals.Erase(registeredVisualsiter);
942           }
943           else
944           {
945             // current visual not already in removal container so add now.
946             DALI_LOG_INFO(gLogFilter, Debug::Verbose, "RegisterVisual Move current registered visual to removal Queue: %d \n", index);
947             MoveVisual(registeredVisualsiter, mVisuals, mRemoveVisuals);
948           }
949         }
950         else
951         {
952           // Control not staged or visual disabled so can just erase from registered visuals and new visual will be added later.
953           mVisuals.Erase(registeredVisualsiter);
954         }
955
956         // If the visual have a depth index as AUTO_INDEX and the new visual does not have a depth index applied to it, then use the previously set depth-index for this index
957         if(requiredDepthIndexChanged)
958         {
959           requiredDepthIndex = currentDepthIndex;
960           DALI_LOG_INFO(gLogFilter, Debug::Verbose, "Use replaced visual index. VisualDepthIndex AUTO_INDEX set as: %d\n", requiredDepthIndex);
961         }
962       }
963
964       visualReplaced = true;
965     }
966   }
967
968   // If not set, set the name of the visual to the same name as the control's property.
969   // ( If the control has been type registered )
970   if(visual.GetName().empty())
971   {
972     // returns empty string if index is not found as long as index is not -1
973     std::string visualName = self.GetPropertyName(index);
974     if(!visualName.empty())
975     {
976       DALI_LOG_INFO(gLogFilter, Debug::Concise, "Setting visual name for property %d to %s\n", index, visualName.c_str());
977       visual.SetName(visualName);
978     }
979   }
980
981   if(!visualReplaced) // New registration entry
982   {
983     // If we have more than one visual and the visual have a depth index as AUTO_INDEX, then set it to be the highest
984     if((mVisuals.Size() > 0) && requiredDepthIndexChanged)
985     {
986       int maxDepthIndex = static_cast<int>(DepthIndex::CONTENT) - 1; // Start at DepthIndex::CONTENT if maxDepth index belongs to a background or no visuals have been added yet.
987
988       RegisteredVisualContainer::ConstIterator       iter;
989       const RegisteredVisualContainer::ConstIterator endIter = mVisuals.End();
990       for(iter = mVisuals.Begin(); iter != endIter; iter++)
991       {
992         const int visualDepthIndex = (*iter)->visual.GetDepthIndex();
993         if(visualDepthIndex > maxDepthIndex)
994         {
995           maxDepthIndex = visualDepthIndex;
996         }
997       }
998       requiredDepthIndex = ++maxDepthIndex; // Add one to the current maximum depth index so that our added visual appears on top.
999       DALI_LOG_INFO(gLogFilter, Debug::Verbose, "Use top of all visuals. VisualDepthIndex AUTO_INDEX set as: %d\n", requiredDepthIndex);
1000     }
1001   }
1002
1003   if(visual)
1004   {
1005     // If required depth index still DepthIndex::AUTO_INDEX, Make it as DepthIndex::CONTENT now
1006     if(requiredDepthIndex == static_cast<int>(DepthIndex::AUTO_INDEX))
1007     {
1008       requiredDepthIndex = static_cast<int>(DepthIndex::CONTENT);
1009       DALI_LOG_INFO(gLogFilter, Debug::Verbose, "Some strange cases. VisualDepthIndex AUTO_INDEX set as: %d\n", requiredDepthIndex);
1010     }
1011
1012     // Set determined depth index
1013     visual.SetDepthIndex(requiredDepthIndex);
1014
1015     // Monitor when the visual resources are ready
1016     StartObservingVisual(visual);
1017
1018     DALI_LOG_INFO(gLogFilter, Debug::Concise, "New Visual registration index[%d] depth[%d]\n", index, requiredDepthIndex);
1019     RegisteredVisual* newRegisteredVisual = new RegisteredVisual(index, visual, (enabled == VisualState::ENABLED ? true : false), (visualReplaced && enabled));
1020     mVisuals.PushBack(newRegisteredVisual);
1021
1022     Internal::Visual::Base& visualImpl = Toolkit::GetImplementation(visual);
1023     // Put on stage if enabled and the control is already on the stage
1024     if((enabled == VisualState::ENABLED) && self.GetProperty<bool>(Actor::Property::CONNECTED_TO_SCENE))
1025     {
1026       visualImpl.SetOnScene(self);
1027     }
1028     else if(enabled && visualImpl.IsResourceReady()) // When not being staged, check if visual already 'ResourceReady' before it was Registered. ( Resource may have been loaded already )
1029     {
1030       ResourceReady(visualImpl);
1031     }
1032   }
1033
1034   DALI_LOG_INFO(gLogFilter, Debug::Verbose, "Control::RegisterVisual() Registered %s(%d), enabled:%s\n", visual.GetName().c_str(), index, enabled ? "true" : "false");
1035 }
1036
1037 void Control::Impl::UnregisterVisual(Property::Index index)
1038 {
1039   DALI_ASSERT_ALWAYS(Stage::IsCoreThread() && "Core is not installed. Might call this API from worker thread?");
1040
1041   RegisteredVisualContainer::Iterator iter;
1042   if(FindVisual(index, mVisuals, iter))
1043   {
1044     // stop observing visual
1045     StopObservingVisual((*iter)->visual);
1046
1047     Actor self(mControlImpl.Self());
1048     Toolkit::GetImplementation((*iter)->visual).SetOffScene(self);
1049     (*iter)->visual.Reset();
1050     mVisuals.Erase(iter);
1051   }
1052
1053   if(FindVisual(index, mRemoveVisuals, iter))
1054   {
1055     Actor self(mControlImpl.Self());
1056     Toolkit::GetImplementation((*iter)->visual).SetOffScene(self);
1057     (*iter)->pending = false;
1058
1059     // Discard removed visual. It will be destroyed at next Idle time.
1060     DiscardVisual(iter, mRemoveVisuals);
1061   }
1062 }
1063
1064 Toolkit::Visual::Base Control::Impl::GetVisual(Property::Index index) const
1065 {
1066   RegisteredVisualContainer::Iterator iter;
1067   if(FindVisual(index, mVisuals, iter))
1068   {
1069     return (*iter)->visual;
1070   }
1071
1072   return Toolkit::Visual::Base();
1073 }
1074
1075 void Control::Impl::EnableVisual(Property::Index index, bool enable)
1076 {
1077   DALI_LOG_INFO(gLogFilter, Debug::General, "Control::EnableVisual(%d, %s)\n", index, enable ? "T" : "F");
1078
1079   RegisteredVisualContainer::Iterator iter;
1080   if(FindVisual(index, mVisuals, iter))
1081   {
1082     if((*iter)->enabled == enable)
1083     {
1084       DALI_LOG_INFO(gLogFilter, Debug::Verbose, "Control::EnableVisual Visual %s(%d) already %s\n", (*iter)->visual.GetName().c_str(), index, enable ? "enabled" : "disabled");
1085       return;
1086     }
1087
1088     (*iter)->enabled  = enable;
1089     Actor parentActor = mControlImpl.Self();
1090     if(mControlImpl.Self().GetProperty<bool>(Actor::Property::CONNECTED_TO_SCENE)) // If control not on Scene then Visual will be added when SceneConnection is called.
1091     {
1092       if(enable)
1093       {
1094         DALI_LOG_INFO(gLogFilter, Debug::Verbose, "Control::EnableVisual Setting %s(%d) on stage \n", (*iter)->visual.GetName().c_str(), index);
1095         Toolkit::GetImplementation((*iter)->visual).SetOnScene(parentActor);
1096       }
1097       else
1098       {
1099         DALI_LOG_INFO(gLogFilter, Debug::Verbose, "Control::EnableVisual Setting %s(%d) off stage \n", (*iter)->visual.GetName().c_str(), index);
1100         Toolkit::GetImplementation((*iter)->visual).SetOffScene(parentActor); // No need to call if control not staged.
1101       }
1102     }
1103   }
1104   else
1105   {
1106     DALI_LOG_WARNING("Control::EnableVisual(%d, %s) FAILED - NO SUCH VISUAL\n", index, enable ? "T" : "F");
1107   }
1108 }
1109
1110 bool Control::Impl::IsVisualEnabled(Property::Index index) const
1111 {
1112   RegisteredVisualContainer::Iterator iter;
1113   if(FindVisual(index, mVisuals, iter))
1114   {
1115     return (*iter)->enabled;
1116   }
1117   return false;
1118 }
1119
1120 void Control::Impl::EnableReadyTransitionOverriden(Toolkit::Visual::Base& visual, bool enable)
1121 {
1122   DALI_LOG_INFO(gLogFilter, Debug::General, "Control::EnableReadyTransitionOverriden(%p, %s)\n", visual, enable ? "T" : "F");
1123
1124   RegisteredVisualContainer::Iterator iter;
1125   if(FindVisual(visual, mVisuals, iter))
1126   {
1127     if((*iter)->overideReadyTransition == enable)
1128     {
1129       DALI_LOG_INFO(gLogFilter, Debug::Verbose, "Control::EnableReadyTransitionOverriden Visual %s(%p) already %s\n", (*iter)->visual.GetName().c_str(), visual, enable ? "enabled" : "disabled");
1130       return;
1131     }
1132
1133     (*iter)->overideReadyTransition = enable;
1134   }
1135 }
1136
1137 void Control::Impl::StopObservingVisual(Toolkit::Visual::Base& visual)
1138 {
1139   Internal::Visual::Base& visualImpl = Toolkit::GetImplementation(visual);
1140
1141   // Stop observing the visual
1142   visualImpl.RemoveEventObserver(*this);
1143 }
1144
1145 void Control::Impl::StartObservingVisual(Toolkit::Visual::Base& visual)
1146 {
1147   Internal::Visual::Base& visualImpl = Toolkit::GetImplementation(visual);
1148
1149   // start observing the visual for events
1150   visualImpl.AddEventObserver(*this);
1151 }
1152
1153 void Control::Impl::ResourceReady()
1154 {
1155   DALI_ASSERT_ALWAYS(Stage::IsCoreThread() && "Core is not installed. Might call this API from worker thread?");
1156
1157   // Emit signal if all enabled visuals registered by the control are ready or there are no visuals.
1158   if(IsResourceReady())
1159   {
1160     EmitResourceReadySignal();
1161   }
1162 }
1163
1164 // Called by a Visual when it's resource is ready
1165 void Control::Impl::ResourceReady(Visual::Base& object)
1166 {
1167   DALI_LOG_INFO(gLogFilter, Debug::Verbose, "Control::Impl::ResourceReady() replacements pending[%d]\n", mRemoveVisuals.Count());
1168
1169   Actor self = mControlImpl.Self();
1170
1171   RegisteredVisualContainer::Iterator registeredIter;
1172
1173   // A resource is ready, find resource in the registered visuals container and get its index
1174   if(!FindVisual(object, mVisuals, registeredIter))
1175   {
1176     return;
1177   }
1178
1179   RegisteredVisualContainer::Iterator visualToRemoveIter;
1180   // Find visual with the same index in the removal container
1181   // Set if off stage as it's replacement is now ready.
1182   // Remove if from removal list as now removed from stage.
1183   // Set Pending flag on the ready visual to false as now ready.
1184   if(FindVisual((*registeredIter)->index, mRemoveVisuals, visualToRemoveIter))
1185   {
1186     (*registeredIter)->pending = false;
1187     if(!((*visualToRemoveIter)->overideReadyTransition))
1188     {
1189       Toolkit::GetImplementation((*visualToRemoveIter)->visual).SetOffScene(self);
1190     }
1191
1192     // Discard removed visual. It will be destroyed at next Idle time.
1193     DiscardVisual(visualToRemoveIter, mRemoveVisuals);
1194   }
1195
1196   // A visual is ready so control may need relayouting if staged
1197   RelayoutRequest(object);
1198
1199   // Called by a Visual when it's resource is ready
1200   if(((*registeredIter)->enabled))
1201   {
1202     ResourceReady();
1203   }
1204 }
1205
1206 void Control::Impl::NotifyVisualEvent(Visual::Base& object, Property::Index signalId)
1207 {
1208   for(auto registeredIter = mVisuals.Begin(), end = mVisuals.End(); registeredIter != end; ++registeredIter)
1209   {
1210     Internal::Visual::Base& registeredVisualImpl = Toolkit::GetImplementation((*registeredIter)->visual);
1211     if(&object == &registeredVisualImpl)
1212     {
1213       Dali::Toolkit::Control handle(mControlImpl.GetOwner());
1214       mVisualEventSignal.Emit(handle, (*registeredIter)->index, signalId);
1215       break;
1216     }
1217   }
1218 }
1219
1220 void Control::Impl::RelayoutRequest(Visual::Base& object)
1221 {
1222   if(mControlImpl.Self().GetProperty<bool>(Actor::Property::CONNECTED_TO_SCENE))
1223   {
1224     mControlImpl.RelayoutRequest();
1225   }
1226 }
1227
1228 bool Control::Impl::IsResourceReady() const
1229 {
1230   // Iterate through and check all the enabled visuals are ready
1231   for(auto visualIter = mVisuals.Begin();
1232       visualIter != mVisuals.End();
1233       ++visualIter)
1234   {
1235     const Toolkit::Visual::Base   visual     = (*visualIter)->visual;
1236     const Internal::Visual::Base& visualImpl = Toolkit::GetImplementation(visual);
1237
1238     // one of the enabled visuals is not ready
1239     if(!visualImpl.IsResourceReady() && (*visualIter)->enabled)
1240     {
1241       return false;
1242     }
1243   }
1244   return true;
1245 }
1246
1247 Toolkit::Visual::ResourceStatus Control::Impl::GetVisualResourceStatus(Property::Index index) const
1248 {
1249   RegisteredVisualContainer::Iterator iter;
1250   if(FindVisual(index, mVisuals, iter))
1251   {
1252     const Toolkit::Visual::Base   visual     = (*iter)->visual;
1253     const Internal::Visual::Base& visualImpl = Toolkit::GetImplementation(visual);
1254     return visualImpl.GetResourceStatus();
1255   }
1256
1257   return Toolkit::Visual::ResourceStatus::PREPARING;
1258 }
1259
1260 void Control::Impl::AddTransitions(Dali::Animation&               animation,
1261                                    const Toolkit::TransitionData& handle,
1262                                    bool                           createAnimation)
1263 {
1264   // Setup a Transition from TransitionData.
1265   const Internal::TransitionData& transitionData = Toolkit::GetImplementation(handle);
1266   TransitionData::Iterator        end            = transitionData.End();
1267   for(TransitionData::Iterator iter = transitionData.Begin();
1268       iter != end;
1269       ++iter)
1270   {
1271     TransitionData::Animator* animator = (*iter);
1272
1273     Toolkit::Visual::Base visual = GetVisualByName(mVisuals, animator->objectName);
1274     if(visual)
1275     {
1276 #if defined(DEBUG_ENABLED)
1277       Dali::TypeInfo  typeInfo;
1278       ControlWrapper* controlWrapperImpl = dynamic_cast<ControlWrapper*>(&mControlImpl);
1279       if(controlWrapperImpl)
1280       {
1281         typeInfo = controlWrapperImpl->GetTypeInfo();
1282       }
1283
1284       DALI_LOG_INFO(gLogFilter, Debug::Concise, "CreateTransition: Found %s visual for %s\n", visual.GetName().c_str(), typeInfo ? typeInfo.GetName().c_str() : "Unknown");
1285 #endif
1286       Internal::Visual::Base& visualImpl = Toolkit::GetImplementation(visual);
1287       visualImpl.AnimateProperty(animation, *animator);
1288     }
1289     else
1290     {
1291       DALI_LOG_INFO(gLogFilter, Debug::Concise, "CreateTransition: Could not find visual. Trying actors");
1292       // Otherwise, try any actor children of control (Including the control)
1293       Actor child = mControlImpl.Self().FindChildByName(animator->objectName);
1294       if(child)
1295       {
1296         Property::Index propertyIndex = child.GetPropertyIndex(animator->propertyKey);
1297         if(propertyIndex != Property::INVALID_INDEX)
1298         {
1299           if(animator->animate == false)
1300           {
1301             if(animator->targetValue.GetType() != Property::NONE)
1302             {
1303               child.SetProperty(propertyIndex, animator->targetValue);
1304             }
1305           }
1306           else // animate the property
1307           {
1308             if(animator->initialValue.GetType() != Property::NONE)
1309             {
1310               child.SetProperty(propertyIndex, animator->initialValue);
1311             }
1312
1313             if(createAnimation && !animation)
1314             {
1315               animation = Dali::Animation::New(0.1f);
1316             }
1317
1318             animation.AnimateTo(Property(child, propertyIndex),
1319                                 animator->targetValue,
1320                                 animator->alphaFunction,
1321                                 TimePeriod(animator->timePeriodDelay,
1322                                            animator->timePeriodDuration));
1323           }
1324         }
1325       }
1326     }
1327   }
1328 }
1329
1330 Dali::Animation Control::Impl::CreateTransition(const Toolkit::TransitionData& transitionData)
1331 {
1332   Dali::Animation transition;
1333
1334   if(transitionData.Count() > 0)
1335   {
1336     AddTransitions(transition, transitionData, true);
1337   }
1338   return transition;
1339 }
1340
1341 void Control::Impl::DoAction(Dali::Property::Index visualIndex, Dali::Property::Index actionId, const Dali::Property::Value attributes)
1342 {
1343   RegisteredVisualContainer::Iterator iter;
1344   if(FindVisual(visualIndex, mVisuals, iter))
1345   {
1346     Toolkit::GetImplementation((*iter)->visual).DoAction(actionId, attributes);
1347   }
1348 }
1349
1350 void Control::Impl::DoActionExtension(Dali::Property::Index visualIndex, Dali::Property::Index actionId, Dali::Any attributes)
1351 {
1352   RegisteredVisualContainer::Iterator iter;
1353   if(FindVisual(visualIndex, mVisuals, iter))
1354   {
1355     Toolkit::GetImplementation((*iter)->visual).DoActionExtension(actionId, attributes);
1356   }
1357 }
1358
1359 void Control::Impl::AppendAccessibilityAttribute(const std::string& key, const std::string value)
1360 {
1361   Property::Value* checkedValue = mAccessibilityProps.extraAttributes.Find(key);
1362   if(checkedValue)
1363   {
1364     mAccessibilityProps.extraAttributes[key] = Property::Value(value);
1365   }
1366   else
1367   {
1368     mAccessibilityProps.extraAttributes.Insert(key, value);
1369   }
1370 }
1371
1372 void Control::Impl::SetProperty(BaseObject* object, Property::Index index, const Property::Value& value)
1373 {
1374   DALI_ASSERT_ALWAYS(Stage::IsCoreThread() && "Core is not installed. Might call this API from worker thread?");
1375
1376   Toolkit::Control control = Toolkit::Control::DownCast(BaseHandle(object));
1377
1378   if(control)
1379   {
1380     Control& controlImpl(GetImplementation(control));
1381
1382     switch(index)
1383     {
1384       case Toolkit::Control::Property::STYLE_NAME:
1385       {
1386         controlImpl.SetStyleName(value.Get<std::string>());
1387         break;
1388       }
1389
1390       case Toolkit::DevelControl::Property::STATE:
1391       {
1392         bool                   withTransitions = true;
1393         const Property::Value* valuePtr        = &value;
1394         const Property::Map*   map             = value.GetMap();
1395         if(map)
1396         {
1397           Property::Value* value2 = map->Find("withTransitions");
1398           if(value2)
1399           {
1400             withTransitions = value2->Get<bool>();
1401           }
1402
1403           valuePtr = map->Find("state");
1404         }
1405
1406         if(valuePtr)
1407         {
1408           Toolkit::DevelControl::State state(controlImpl.mImpl->mState);
1409           if(Scripting::GetEnumerationProperty<Toolkit::DevelControl::State>(*valuePtr, ControlStateTable, ControlStateTableCount, state))
1410           {
1411             controlImpl.mImpl->SetState(state, withTransitions);
1412           }
1413         }
1414       }
1415       break;
1416
1417       case Toolkit::DevelControl::Property::SUB_STATE:
1418       {
1419         std::string subState;
1420         if(value.Get(subState))
1421         {
1422           controlImpl.mImpl->SetSubState(subState);
1423         }
1424       }
1425       break;
1426
1427       case Toolkit::DevelControl::Property::LEFT_FOCUSABLE_ACTOR_ID:
1428       {
1429         int focusId;
1430         if(value.Get(focusId))
1431         {
1432           controlImpl.mImpl->mLeftFocusableActorId = focusId;
1433         }
1434       }
1435       break;
1436
1437       case Toolkit::DevelControl::Property::RIGHT_FOCUSABLE_ACTOR_ID:
1438       {
1439         int focusId;
1440         if(value.Get(focusId))
1441         {
1442           controlImpl.mImpl->mRightFocusableActorId = focusId;
1443         }
1444       }
1445       break;
1446
1447       case Toolkit::DevelControl::Property::UP_FOCUSABLE_ACTOR_ID:
1448       {
1449         int focusId;
1450         if(value.Get(focusId))
1451         {
1452           controlImpl.mImpl->mUpFocusableActorId = focusId;
1453         }
1454       }
1455       break;
1456
1457       case Toolkit::DevelControl::Property::DOWN_FOCUSABLE_ACTOR_ID:
1458       {
1459         int focusId;
1460         if(value.Get(focusId))
1461         {
1462           controlImpl.mImpl->mDownFocusableActorId = focusId;
1463         }
1464       }
1465       break;
1466
1467       case Toolkit::Control::Property::KEY_INPUT_FOCUS:
1468       {
1469         if(value.Get<bool>())
1470         {
1471           controlImpl.SetKeyInputFocus();
1472         }
1473         else
1474         {
1475           controlImpl.ClearKeyInputFocus();
1476         }
1477         break;
1478       }
1479
1480       case Toolkit::Control::Property::BACKGROUND:
1481       {
1482         std::string          url;
1483         Vector4              color;
1484         const Property::Map* map = value.GetMap();
1485         if(map && !map->Empty())
1486         {
1487           controlImpl.SetBackground(*map);
1488         }
1489         else if(value.Get(url))
1490         {
1491           // don't know the size to load
1492           Toolkit::Visual::Base visual = Toolkit::VisualFactory::Get().CreateVisual(url, ImageDimensions());
1493           if(visual)
1494           {
1495             controlImpl.mImpl->RegisterVisual(Toolkit::Control::Property::BACKGROUND, visual, DepthIndex::BACKGROUND);
1496           }
1497         }
1498         else if(value.Get(color))
1499         {
1500           controlImpl.SetBackgroundColor(color);
1501         }
1502         else
1503         {
1504           // The background is an empty property map, so we should clear the background
1505           controlImpl.ClearBackground();
1506         }
1507         break;
1508       }
1509
1510       case Toolkit::Control::Property::MARGIN:
1511       {
1512         Extents margin;
1513         if(value.Get(margin))
1514         {
1515           controlImpl.mImpl->SetMargin(margin);
1516         }
1517         break;
1518       }
1519
1520       case Toolkit::Control::Property::PADDING:
1521       {
1522         Extents padding;
1523         if(value.Get(padding))
1524         {
1525           controlImpl.mImpl->SetPadding(padding);
1526         }
1527         break;
1528       }
1529
1530       case Toolkit::DevelControl::Property::TOOLTIP:
1531       {
1532         TooltipPtr& tooltipPtr = controlImpl.mImpl->mTooltip;
1533         if(!tooltipPtr)
1534         {
1535           tooltipPtr = Tooltip::New(control);
1536         }
1537         tooltipPtr->SetProperties(value);
1538         break;
1539       }
1540
1541       case Toolkit::DevelControl::Property::SHADOW:
1542       {
1543         const Property::Map* map = value.GetMap();
1544         if(map && !map->Empty())
1545         {
1546           controlImpl.mImpl->SetShadow(*map);
1547         }
1548         else
1549         {
1550           // The shadow is an empty property map, so we should clear the shadow
1551           controlImpl.mImpl->ClearShadow();
1552         }
1553         break;
1554       }
1555
1556       case Toolkit::DevelControl::Property::ACCESSIBILITY_NAME:
1557       {
1558         std::string name;
1559         if(value.Get(name))
1560         {
1561           controlImpl.mImpl->mAccessibilityProps.name = std::move(name);
1562         }
1563         break;
1564       }
1565
1566       case Toolkit::DevelControl::Property::ACCESSIBILITY_DESCRIPTION:
1567       {
1568         std::string text;
1569         if(value.Get(text))
1570         {
1571           controlImpl.mImpl->mAccessibilityProps.description = std::move(text);
1572         }
1573         break;
1574       }
1575
1576       case Toolkit::DevelControl::Property::ACCESSIBILITY_ROLE:
1577       {
1578         int32_t role;
1579         if(value.Get(role))
1580         {
1581           controlImpl.mImpl->mAccessibilityProps.role = role;
1582         }
1583         break;
1584       }
1585
1586       case Toolkit::DevelControl::Property::ACCESSIBILITY_HIGHLIGHTABLE:
1587       {
1588         bool highlightable;
1589         if(value.Get(highlightable))
1590         {
1591           controlImpl.mImpl->mAccessibilityProps.isHighlightable = highlightable;
1592         }
1593         break;
1594       }
1595
1596       case Toolkit::DevelControl::Property::ACCESSIBILITY_ATTRIBUTES:
1597       {
1598         const Property::Map* map = value.GetMap();
1599         if(map && !map->Empty())
1600         {
1601           controlImpl.mImpl->mAccessibilityProps.extraAttributes = *map;
1602         }
1603         break;
1604       }
1605
1606       case Toolkit::DevelControl::Property::DISPATCH_KEY_EVENTS:
1607       {
1608         bool dispatch;
1609         if(value.Get(dispatch))
1610         {
1611           controlImpl.mImpl->mDispatchKeyEvents = dispatch;
1612         }
1613         break;
1614       }
1615
1616       case Toolkit::DevelControl::Property::ACCESSIBILITY_HIDDEN:
1617       {
1618         bool hidden;
1619         if(value.Get(hidden))
1620         {
1621           controlImpl.mImpl->mAccessibilityProps.isHidden = hidden;
1622
1623           auto accessible = controlImpl.GetAccessibleObject();
1624           if(DALI_LIKELY(accessible))
1625           {
1626             auto* parent = dynamic_cast<Dali::Accessibility::ActorAccessible*>(accessible->GetParent());
1627             if(parent)
1628             {
1629               parent->OnChildrenChanged();
1630             }
1631           }
1632         }
1633         break;
1634       }
1635       case Toolkit::DevelControl::Property::CLOCKWISE_FOCUSABLE_ACTOR_ID:
1636       {
1637         int focusId;
1638         if(value.Get(focusId))
1639         {
1640           controlImpl.mImpl->mClockwiseFocusableActorId = focusId;
1641         }
1642         break;
1643       }
1644       case Toolkit::DevelControl::Property::COUNTER_CLOCKWISE_FOCUSABLE_ACTOR_ID:
1645       {
1646         int focusId;
1647         if(value.Get(focusId))
1648         {
1649           controlImpl.mImpl->mCounterClockwiseFocusableActorId = focusId;
1650         }
1651         break;
1652       }
1653
1654       case Toolkit::DevelControl::Property::AUTOMATION_ID:
1655       {
1656         std::string automationId;
1657         if(value.Get(automationId))
1658         {
1659           controlImpl.mImpl->mAccessibilityProps.automationId = std::move(automationId);
1660         }
1661         break;
1662       }
1663
1664       case Toolkit::DevelControl::Property::ACCESSIBILITY_VALUE:
1665       {
1666         std::string accessibilityValue;
1667         if(value.Get(accessibilityValue))
1668         {
1669           controlImpl.mImpl->mAccessibilityProps.value = std::move(accessibilityValue);
1670         }
1671         break;
1672       }
1673
1674       case Toolkit::DevelControl::Property::ACCESSIBILITY_SCROLLABLE:
1675       {
1676         bool isScrollable;
1677         if(value.Get(isScrollable))
1678         {
1679           controlImpl.mImpl->mAccessibilityProps.isScrollable = isScrollable;
1680         }
1681         break;
1682       }
1683
1684       case Toolkit::DevelControl::Property::ACCESSIBILITY_STATES:
1685       {
1686         int32_t states;
1687         if(value.Get(states))
1688         {
1689           controlImpl.mImpl->mAccessibilityProps.states = Toolkit::DevelControl::AccessibilityStates{static_cast<uint32_t>(states)};
1690         }
1691         break;
1692       }
1693
1694       case Toolkit::DevelControl::Property::ACCESSIBILITY_IS_MODAL:
1695       {
1696         bool isModal;
1697         if(value.Get(isModal))
1698         {
1699           controlImpl.mImpl->mAccessibilityProps.isModal = isModal;
1700         }
1701         break;
1702       }
1703     }
1704   }
1705 }
1706
1707 Property::Value Control::Impl::GetProperty(BaseObject* object, Property::Index index)
1708 {
1709   DALI_ASSERT_ALWAYS(Stage::IsCoreThread() && "Core is not installed. Might call this API from worker thread?");
1710
1711   Property::Value value;
1712
1713   Toolkit::Control control = Toolkit::Control::DownCast(BaseHandle(object));
1714
1715   if(control)
1716   {
1717     Control& controlImpl(GetImplementation(control));
1718
1719     switch(index)
1720     {
1721       case Toolkit::Control::Property::STYLE_NAME:
1722       {
1723         value = controlImpl.GetStyleName();
1724         break;
1725       }
1726
1727       case Toolkit::DevelControl::Property::STATE:
1728       {
1729         value = controlImpl.mImpl->mState;
1730         break;
1731       }
1732
1733       case Toolkit::DevelControl::Property::SUB_STATE:
1734       {
1735         value = controlImpl.mImpl->mSubStateName;
1736         break;
1737       }
1738
1739       case Toolkit::DevelControl::Property::LEFT_FOCUSABLE_ACTOR_ID:
1740       {
1741         value = controlImpl.mImpl->mLeftFocusableActorId;
1742         break;
1743       }
1744
1745       case Toolkit::DevelControl::Property::RIGHT_FOCUSABLE_ACTOR_ID:
1746       {
1747         value = controlImpl.mImpl->mRightFocusableActorId;
1748         break;
1749       }
1750
1751       case Toolkit::DevelControl::Property::UP_FOCUSABLE_ACTOR_ID:
1752       {
1753         value = controlImpl.mImpl->mUpFocusableActorId;
1754         break;
1755       }
1756
1757       case Toolkit::DevelControl::Property::DOWN_FOCUSABLE_ACTOR_ID:
1758       {
1759         value = controlImpl.mImpl->mDownFocusableActorId;
1760         break;
1761       }
1762
1763       case Toolkit::Control::Property::KEY_INPUT_FOCUS:
1764       {
1765         value = controlImpl.HasKeyInputFocus();
1766         break;
1767       }
1768
1769       case Toolkit::Control::Property::BACKGROUND:
1770       {
1771         Property::Map         map;
1772         Toolkit::Visual::Base visual = controlImpl.mImpl->GetVisual(Toolkit::Control::Property::BACKGROUND);
1773         if(visual)
1774         {
1775           visual.CreatePropertyMap(map);
1776         }
1777
1778         value = map;
1779         break;
1780       }
1781
1782       case Toolkit::Control::Property::MARGIN:
1783       {
1784         value = controlImpl.mImpl->GetMargin();
1785         break;
1786       }
1787
1788       case Toolkit::Control::Property::PADDING:
1789       {
1790         value = controlImpl.mImpl->GetPadding();
1791         break;
1792       }
1793
1794       case Toolkit::DevelControl::Property::TOOLTIP:
1795       {
1796         Property::Map map;
1797         if(controlImpl.mImpl->mTooltip)
1798         {
1799           controlImpl.mImpl->mTooltip->CreatePropertyMap(map);
1800         }
1801         value = map;
1802         break;
1803       }
1804
1805       case Toolkit::DevelControl::Property::SHADOW:
1806       {
1807         Property::Map         map;
1808         Toolkit::Visual::Base visual = controlImpl.mImpl->GetVisual(Toolkit::DevelControl::Property::SHADOW);
1809         if(visual)
1810         {
1811           visual.CreatePropertyMap(map);
1812         }
1813
1814         value = map;
1815         break;
1816       }
1817
1818       case Toolkit::DevelControl::Property::ACCESSIBILITY_NAME:
1819       {
1820         value = controlImpl.mImpl->mAccessibilityProps.name;
1821         break;
1822       }
1823
1824       case Toolkit::DevelControl::Property::ACCESSIBILITY_DESCRIPTION:
1825       {
1826         value = controlImpl.mImpl->mAccessibilityProps.description;
1827         break;
1828       }
1829
1830       case Toolkit::DevelControl::Property::ACCESSIBILITY_ROLE:
1831       {
1832         value = controlImpl.mImpl->mAccessibilityProps.role;
1833         break;
1834       }
1835
1836       case Toolkit::DevelControl::Property::ACCESSIBILITY_HIGHLIGHTABLE:
1837       {
1838         value = controlImpl.mImpl->mAccessibilityProps.isHighlightable;
1839         break;
1840       }
1841
1842       case Toolkit::DevelControl::Property::ACCESSIBILITY_ATTRIBUTES:
1843       {
1844         value = controlImpl.mImpl->mAccessibilityProps.extraAttributes;
1845         break;
1846       }
1847
1848       case Toolkit::DevelControl::Property::DISPATCH_KEY_EVENTS:
1849       {
1850         value = controlImpl.mImpl->mDispatchKeyEvents;
1851         break;
1852       }
1853
1854       case Toolkit::DevelControl::Property::ACCESSIBILITY_HIDDEN:
1855       {
1856         value = controlImpl.mImpl->mAccessibilityProps.isHidden;
1857         break;
1858       }
1859
1860       case Toolkit::DevelControl::Property::CLOCKWISE_FOCUSABLE_ACTOR_ID:
1861       {
1862         value = controlImpl.mImpl->mClockwiseFocusableActorId;
1863         break;
1864       }
1865
1866       case Toolkit::DevelControl::Property::COUNTER_CLOCKWISE_FOCUSABLE_ACTOR_ID:
1867       {
1868         value = controlImpl.mImpl->mCounterClockwiseFocusableActorId;
1869         break;
1870       }
1871
1872       case Toolkit::DevelControl::Property::AUTOMATION_ID:
1873       {
1874         value = controlImpl.mImpl->mAccessibilityProps.automationId;
1875         break;
1876       }
1877
1878       case Toolkit::DevelControl::Property::ACCESSIBILITY_VALUE:
1879       {
1880         value = controlImpl.mImpl->mAccessibilityProps.value;
1881         break;
1882       }
1883
1884       case Toolkit::DevelControl::Property::ACCESSIBILITY_SCROLLABLE:
1885       {
1886         value = controlImpl.mImpl->mAccessibilityProps.isScrollable;
1887         break;
1888       }
1889
1890       case Toolkit::DevelControl::Property::ACCESSIBILITY_STATES:
1891       {
1892         value = static_cast<int32_t>(controlImpl.mImpl->mAccessibilityProps.states.GetRawData32());
1893         break;
1894       }
1895
1896       case Toolkit::DevelControl::Property::ACCESSIBILITY_IS_MODAL:
1897       {
1898         value = controlImpl.mImpl->mAccessibilityProps.isModal;
1899         break;
1900       }
1901     }
1902   }
1903
1904   return value;
1905 }
1906
1907 void Control::Impl::RemoveAccessibilityAttribute(const std::string& key)
1908 {
1909   Property::Value* value = mAccessibilityProps.extraAttributes.Find(key);
1910   if(value)
1911   {
1912     mAccessibilityProps.extraAttributes[key] = Property::Value();
1913   }
1914 }
1915
1916 void Control::Impl::ClearAccessibilityAttributes()
1917 {
1918   mAccessibilityProps.extraAttributes.Clear();
1919 }
1920
1921 void Control::Impl::SetAccessibilityReadingInfoType(const Dali::Accessibility::ReadingInfoTypes types)
1922 {
1923   std::string value{};
1924   if(types[Dali::Accessibility::ReadingInfoType::NAME])
1925   {
1926     value += READING_INFO_TYPE_NAME;
1927   }
1928   if(types[Dali::Accessibility::ReadingInfoType::ROLE])
1929   {
1930     if(!value.empty())
1931     {
1932       value += READING_INFO_TYPE_SEPARATOR;
1933     }
1934     value += READING_INFO_TYPE_ROLE;
1935   }
1936   if(types[Dali::Accessibility::ReadingInfoType::DESCRIPTION])
1937   {
1938     if(!value.empty())
1939     {
1940       value += READING_INFO_TYPE_SEPARATOR;
1941     }
1942     value += READING_INFO_TYPE_DESCRIPTION;
1943   }
1944   if(types[Dali::Accessibility::ReadingInfoType::STATE])
1945   {
1946     if(!value.empty())
1947     {
1948       value += READING_INFO_TYPE_SEPARATOR;
1949     }
1950     value += READING_INFO_TYPE_STATE;
1951   }
1952   AppendAccessibilityAttribute(READING_INFO_TYPE_ATTRIBUTE_NAME, value);
1953 }
1954
1955 Dali::Accessibility::ReadingInfoTypes Control::Impl::GetAccessibilityReadingInfoType() const
1956 {
1957   std::string value{};
1958   auto        place = mAccessibilityProps.extraAttributes.Find(READING_INFO_TYPE_ATTRIBUTE_NAME);
1959   if(place)
1960   {
1961     place->Get(value);
1962   }
1963   else
1964   {
1965     Dali::Accessibility::ReadingInfoTypes types;
1966     types[Dali::Accessibility::ReadingInfoType::NAME]        = true;
1967     types[Dali::Accessibility::ReadingInfoType::ROLE]        = true;
1968     types[Dali::Accessibility::ReadingInfoType::DESCRIPTION] = true;
1969     types[Dali::Accessibility::ReadingInfoType::STATE]       = true;
1970     return types;
1971   }
1972
1973   if(value.empty())
1974   {
1975     return {};
1976   }
1977
1978   Dali::Accessibility::ReadingInfoTypes types;
1979
1980   if(value.find(READING_INFO_TYPE_NAME) != std::string::npos)
1981   {
1982     types[Dali::Accessibility::ReadingInfoType::NAME] = true;
1983   }
1984   if(value.find(READING_INFO_TYPE_ROLE) != std::string::npos)
1985   {
1986     types[Dali::Accessibility::ReadingInfoType::ROLE] = true;
1987   }
1988   if(value.find(READING_INFO_TYPE_DESCRIPTION) != std::string::npos)
1989   {
1990     types[Dali::Accessibility::ReadingInfoType::DESCRIPTION] = true;
1991   }
1992   if(value.find(READING_INFO_TYPE_STATE) != std::string::npos)
1993   {
1994     types[Dali::Accessibility::ReadingInfoType::STATE] = true;
1995   }
1996
1997   return types;
1998 }
1999
2000 void Control::Impl::CopyInstancedProperties(RegisteredVisualContainer& visuals, Dictionary<Property::Map>& instancedProperties)
2001 {
2002   for(RegisteredVisualContainer::Iterator iter = visuals.Begin(); iter != visuals.End(); iter++)
2003   {
2004     if((*iter)->visual)
2005     {
2006       Property::Map instanceMap;
2007       Toolkit::GetImplementation((*iter)->visual).CreateInstancePropertyMap(instanceMap);
2008       instancedProperties.Add((*iter)->visual.GetName(), instanceMap);
2009     }
2010   }
2011 }
2012
2013 void Control::Impl::RemoveVisual(RegisteredVisualContainer& visuals, const std::string& visualName)
2014 {
2015   Actor self(mControlImpl.Self());
2016
2017   for(RegisteredVisualContainer::Iterator visualIter = visuals.Begin();
2018       visualIter != visuals.End();
2019       ++visualIter)
2020   {
2021     Toolkit::Visual::Base visual = (*visualIter)->visual;
2022     if(visual && visual.GetName() == visualName)
2023     {
2024       Toolkit::GetImplementation(visual).SetOffScene(self);
2025       (*visualIter)->visual.Reset();
2026       visuals.Erase(visualIter);
2027       break;
2028     }
2029   }
2030 }
2031
2032 void Control::Impl::RemoveVisuals(RegisteredVisualContainer& visuals, DictionaryKeys& removeVisuals)
2033 {
2034   Actor self(mControlImpl.Self());
2035   for(DictionaryKeys::iterator iter = removeVisuals.begin(); iter != removeVisuals.end(); ++iter)
2036   {
2037     const std::string visualName = *iter;
2038     RemoveVisual(visuals, visualName);
2039   }
2040 }
2041
2042 void Control::Impl::RecreateChangedVisuals(Dictionary<Property::Map>& stateVisualsToChange,
2043                                            Dictionary<Property::Map>& instancedProperties)
2044 {
2045   Dali::CustomActor handle(mControlImpl.GetOwner());
2046   for(Dictionary<Property::Map>::iterator iter = stateVisualsToChange.Begin();
2047       iter != stateVisualsToChange.End();
2048       ++iter)
2049   {
2050     const std::string&   visualName = (*iter).key;
2051     const Property::Map& toMap      = (*iter).entry;
2052
2053     Actor                               self = mControlImpl.Self();
2054     RegisteredVisualContainer::Iterator registeredVisualsiter;
2055     // Check if visual (visualName) is already registered, this is the current visual.
2056     if(FindVisual(visualName, mVisuals, registeredVisualsiter))
2057     {
2058       Toolkit::Visual::Base& visual = (*registeredVisualsiter)->visual;
2059       if(visual)
2060       {
2061         // No longer required to know if the replaced visual's resources are ready
2062         StopObservingVisual(visual);
2063
2064         // If control staged then visuals will be swapped once ready
2065         if(self.GetProperty<bool>(Actor::Property::CONNECTED_TO_SCENE))
2066         {
2067           // Check if visual is currently in the process of being replaced ( is in removal container )
2068           RegisteredVisualContainer::Iterator visualQueuedForRemoval;
2069           if(FindVisual(visualName, mRemoveVisuals, visualQueuedForRemoval))
2070           {
2071             // Visual with same visual name is already in removal container so current visual pending
2072             // Only the the last requested visual will be displayed so remove current visual which is staged but not ready.
2073             Toolkit::GetImplementation(visual).SetOffScene(self);
2074             (*registeredVisualsiter)->visual.Reset();
2075             mVisuals.Erase(registeredVisualsiter);
2076           }
2077           else
2078           {
2079             // current visual not already in removal container so add now.
2080             DALI_LOG_INFO(gLogFilter, Debug::Verbose, "RegisterVisual Move current registered visual to removal Queue: %s \n", visualName.c_str());
2081             MoveVisual(registeredVisualsiter, mVisuals, mRemoveVisuals);
2082           }
2083         }
2084         else
2085         {
2086           // Control not staged or visual disabled so can just erase from registered visuals and new visual will be added later.
2087           (*registeredVisualsiter)->visual.Reset();
2088           mVisuals.Erase(registeredVisualsiter);
2089         }
2090       }
2091
2092       const Property::Map* instancedMap = instancedProperties.FindConst(visualName);
2093       Style::ApplyVisual(handle, visualName, toMap, instancedMap);
2094     }
2095   }
2096 }
2097
2098 void Control::Impl::ReplaceStateVisualsAndProperties(const StylePtr oldState, const StylePtr newState, const std::string& subState)
2099 {
2100   DALI_ASSERT_ALWAYS(Stage::IsCoreThread() && "Core is not installed. Might call this API from worker thread?");
2101
2102   // Collect all old visual names
2103   DictionaryKeys stateVisualsToRemove;
2104   if(oldState)
2105   {
2106     oldState->visuals.GetKeys(stateVisualsToRemove);
2107     if(!subState.empty())
2108     {
2109       const StylePtr* oldSubState = oldState->subStates.FindConst(subState);
2110       if(oldSubState)
2111       {
2112         DictionaryKeys subStateVisualsToRemove;
2113         (*oldSubState)->visuals.GetKeys(subStateVisualsToRemove);
2114         Merge(stateVisualsToRemove, subStateVisualsToRemove);
2115       }
2116     }
2117   }
2118
2119   // Collect all new visual properties
2120   Dictionary<Property::Map> stateVisualsToAdd;
2121   if(newState)
2122   {
2123     stateVisualsToAdd = newState->visuals;
2124     if(!subState.empty())
2125     {
2126       const StylePtr* newSubState = newState->subStates.FindConst(subState);
2127       if(newSubState)
2128       {
2129         stateVisualsToAdd.Merge((*newSubState)->visuals);
2130       }
2131     }
2132   }
2133
2134   // If a name is in both add/remove, move it to change list.
2135   Dictionary<Property::Map> stateVisualsToChange;
2136   FindChangableVisuals(stateVisualsToAdd, stateVisualsToChange, stateVisualsToRemove);
2137
2138   // Copy instanced properties (e.g. text label) of current visuals
2139   Dictionary<Property::Map> instancedProperties;
2140   CopyInstancedProperties(mVisuals, instancedProperties);
2141
2142   // For each visual in remove list, remove from mVisuals
2143   RemoveVisuals(mVisuals, stateVisualsToRemove);
2144
2145   // For each visual in add list, create and add to mVisuals
2146   Dali::CustomActor handle(mControlImpl.GetOwner());
2147   Style::ApplyVisuals(handle, stateVisualsToAdd, instancedProperties);
2148
2149   // For each visual in change list, if it requires a new visual,
2150   // remove old visual, create and add to mVisuals
2151   RecreateChangedVisuals(stateVisualsToChange, instancedProperties);
2152 }
2153
2154 void Control::Impl::SetState(DevelControl::State newState, bool withTransitions)
2155 {
2156   DevelControl::State oldState = mState;
2157   Dali::CustomActor   handle(mControlImpl.GetOwner());
2158   DALI_LOG_INFO(gLogFilter, Debug::Concise, "Control::Impl::SetState: %s\n", (mState == DevelControl::NORMAL ? "NORMAL" : (mState == DevelControl::FOCUSED ? "FOCUSED" : (mState == DevelControl::DISABLED ? "DISABLED" : "NONE"))));
2159
2160   if(mState != newState)
2161   {
2162     // If mState was Disabled, and new state is Focused, should probably
2163     // store that fact, e.g. in another property that FocusManager can access.
2164     mState = newState;
2165
2166     // Trigger state change and transitions
2167     // Apply new style, if stylemanager is available
2168     Toolkit::StyleManager styleManager = Toolkit::StyleManager::Get();
2169     if(styleManager)
2170     {
2171       const StylePtr stylePtr = GetImpl(styleManager).GetRecordedStyle(Toolkit::Control(mControlImpl.GetOwner()));
2172
2173       if(stylePtr)
2174       {
2175         std::string oldStateName = Scripting::GetEnumerationName<Toolkit::DevelControl::State>(oldState, ControlStateTable, ControlStateTableCount);
2176         std::string newStateName = Scripting::GetEnumerationName<Toolkit::DevelControl::State>(newState, ControlStateTable, ControlStateTableCount);
2177
2178         const StylePtr* newStateStyle = stylePtr->subStates.Find(newStateName);
2179         const StylePtr* oldStateStyle = stylePtr->subStates.Find(oldStateName);
2180         if(oldStateStyle && newStateStyle)
2181         {
2182           // Only change if both state styles exist
2183           ReplaceStateVisualsAndProperties(*oldStateStyle, *newStateStyle, mSubStateName);
2184         }
2185       }
2186     }
2187   }
2188 }
2189
2190 void Control::Impl::SetSubState(const std::string& subStateName, bool withTransitions)
2191 {
2192   if(mSubStateName != subStateName)
2193   {
2194     // Get existing sub-state visuals, and unregister them
2195     Dali::CustomActor handle(mControlImpl.GetOwner());
2196
2197     Toolkit::StyleManager styleManager = Toolkit::StyleManager::Get();
2198     if(styleManager)
2199     {
2200       const StylePtr stylePtr = GetImpl(styleManager).GetRecordedStyle(Toolkit::Control(mControlImpl.GetOwner()));
2201       if(stylePtr)
2202       {
2203         // Stringify state
2204         std::string stateName = Scripting::GetEnumerationName<Toolkit::DevelControl::State>(mState, ControlStateTable, ControlStateTableCount);
2205
2206         const StylePtr* state = stylePtr->subStates.Find(stateName);
2207         if(state)
2208         {
2209           StylePtr stateStyle(*state);
2210
2211           const StylePtr* newStateStyle = stateStyle->subStates.Find(subStateName);
2212           const StylePtr* oldStateStyle = stateStyle->subStates.Find(mSubStateName);
2213           if(oldStateStyle && newStateStyle)
2214           {
2215             std::string empty;
2216             ReplaceStateVisualsAndProperties(*oldStateStyle, *newStateStyle, empty);
2217           }
2218         }
2219       }
2220     }
2221
2222     mSubStateName = subStateName;
2223   }
2224 }
2225
2226 void Control::Impl::OnSceneDisconnection()
2227 {
2228   Actor self = mControlImpl.Self();
2229
2230   // Any visuals set for replacement but not yet ready should still be registered.
2231   // Reason: If a request was made to register a new visual but the control removed from scene before visual was ready
2232   // then when this control appears back on stage it should use that new visual.
2233
2234   // Iterate through all registered visuals and set off scene
2235   SetVisualsOffScene(mVisuals, self);
2236
2237   // Visuals pending replacement can now be taken out of the removal list and set off scene
2238   // Iterate through all replacement visuals and add to a move queue then set off scene
2239
2240   if(!mRemoveVisuals.Empty())
2241   {
2242     std::reverse(mRemoveVisuals.Begin(), mRemoveVisuals.End());
2243
2244     while(!mRemoveVisuals.Empty())
2245     {
2246       auto removalIter = mRemoveVisuals.End() - 1u;
2247       Toolkit::GetImplementation((*removalIter)->visual).SetOffScene(self);
2248
2249       // Discard removed visual. It will be destroyed at next Idle time.
2250       DiscardVisual(removalIter, mRemoveVisuals);
2251     }
2252   }
2253
2254   for(auto replacedIter = mVisuals.Begin(), end = mVisuals.End(); replacedIter != end; replacedIter++)
2255   {
2256     (*replacedIter)->pending = false;
2257   }
2258 }
2259
2260 void Control::Impl::SetMargin(Extents margin)
2261 {
2262   mControlImpl.mImpl->mMargin = margin;
2263
2264   // Trigger a size negotiation request that may be needed when setting a margin.
2265   mControlImpl.RelayoutRequest();
2266 }
2267
2268 Extents Control::Impl::GetMargin() const
2269 {
2270   return mControlImpl.mImpl->mMargin;
2271 }
2272
2273 void Control::Impl::SetPadding(Extents padding)
2274 {
2275   mControlImpl.mImpl->mPadding = padding;
2276
2277   // Trigger a size negotiation request that may be needed when setting a padding.
2278   mControlImpl.RelayoutRequest();
2279 }
2280
2281 Extents Control::Impl::GetPadding() const
2282 {
2283   return mControlImpl.mImpl->mPadding;
2284 }
2285
2286 void Control::Impl::SetInputMethodContext(InputMethodContext& inputMethodContext)
2287 {
2288   mInputMethodContext = inputMethodContext;
2289 }
2290
2291 bool Control::Impl::FilterKeyEvent(const KeyEvent& event)
2292 {
2293   bool consumed(false);
2294
2295   if(mInputMethodContext)
2296   {
2297     consumed = mInputMethodContext.FilterEventKey(event);
2298   }
2299   return consumed;
2300 }
2301
2302 DevelControl::VisualEventSignalType& Control::Impl::VisualEventSignal()
2303 {
2304   return mVisualEventSignal;
2305 }
2306
2307 void Control::Impl::SetShadow(const Property::Map& map)
2308 {
2309   Toolkit::Visual::Base visual = Toolkit::VisualFactory::Get().CreateVisual(map);
2310   visual.SetName("shadow");
2311
2312   if(visual)
2313   {
2314     mControlImpl.mImpl->RegisterVisual(Toolkit::DevelControl::Property::SHADOW, visual, DepthIndex::BACKGROUND_EFFECT);
2315
2316     mControlImpl.RelayoutRequest();
2317   }
2318 }
2319
2320 void Control::Impl::ClearShadow()
2321 {
2322   mControlImpl.mImpl->UnregisterVisual(Toolkit::DevelControl::Property::SHADOW);
2323
2324   // Trigger a size negotiation request that may be needed when unregistering a visual.
2325   mControlImpl.RelayoutRequest();
2326 }
2327
2328 Dali::Property Control::Impl::GetVisualProperty(Dali::Property::Index index, Dali::Property::Key visualPropertyKey)
2329 {
2330   Toolkit::Visual::Base visual = GetVisualByIndex(mVisuals, index);
2331   if(visual)
2332   {
2333     Internal::Visual::Base& visualImpl = Toolkit::GetImplementation(visual);
2334     return visualImpl.GetPropertyObject(std::move(visualPropertyKey));
2335   }
2336
2337   Handle handle;
2338   return Dali::Property(handle, Property::INVALID_INDEX);
2339 }
2340
2341 void Control::Impl::CreateTransitions(std::vector<std::pair<Dali::Property::Index, Dali::Property::Map>>& sourceProperties,
2342                                       std::vector<std::pair<Dali::Property::Index, Dali::Property::Map>>& destinationProperties,
2343                                       Dali::Toolkit::Control                                              source,
2344                                       Dali::Toolkit::Control                                              destination)
2345 {
2346   // Retrieves background properties to be transitioned.
2347   Dali::Property::Map backgroundSourcePropertyMap, backgroundDestinationPropertyMap;
2348   mControlImpl.MakeVisualTransition(backgroundSourcePropertyMap, backgroundDestinationPropertyMap, source, destination, Toolkit::Control::Property::BACKGROUND);
2349   if(backgroundSourcePropertyMap.Count() > 0)
2350   {
2351     sourceProperties.push_back(std::pair<Dali::Property::Index, Dali::Property::Map>(Toolkit::Control::Property::BACKGROUND, backgroundSourcePropertyMap));
2352     destinationProperties.push_back(std::pair<Dali::Property::Index, Dali::Property::Map>(Toolkit::Control::Property::BACKGROUND, backgroundDestinationPropertyMap));
2353   }
2354
2355   // Retrieves shadow properties to be transitioned.
2356   Dali::Property::Map shadowSourcePropertyMap, shadowDestinationPropertyMap;
2357   mControlImpl.MakeVisualTransition(shadowSourcePropertyMap, shadowDestinationPropertyMap, source, destination, Toolkit::DevelControl::Property::SHADOW);
2358   if(shadowSourcePropertyMap.Count() > 0)
2359   {
2360     sourceProperties.push_back(std::pair<Dali::Property::Index, Dali::Property::Map>(Toolkit::DevelControl::Property::SHADOW, shadowSourcePropertyMap));
2361     destinationProperties.push_back(std::pair<Dali::Property::Index, Dali::Property::Map>(Toolkit::DevelControl::Property::SHADOW, shadowDestinationPropertyMap));
2362   }
2363
2364   // Retrieves transition from inherited class.
2365   mControlImpl.OnCreateTransitions(sourceProperties, destinationProperties, source, destination);
2366 }
2367
2368 void Control::Impl::UpdateVisualProperties(const std::vector<std::pair<Dali::Property::Index, Dali::Property::Map>>& properties)
2369 {
2370   for(auto&& data : properties)
2371   {
2372     if(data.first == Toolkit::Control::Property::BACKGROUND)
2373     {
2374       DoAction(Toolkit::Control::Property::BACKGROUND, DevelVisual::Action::UPDATE_PROPERTY, data.second);
2375     }
2376     else if(data.first == Toolkit::DevelControl::Property::SHADOW)
2377     {
2378       DoAction(Toolkit::DevelControl::Property::SHADOW, DevelVisual::Action::UPDATE_PROPERTY, data.second);
2379     }
2380   }
2381   mControlImpl.OnUpdateVisualProperties(properties);
2382 }
2383
2384 void Control::Impl::EmitResourceReadySignal()
2385 {
2386   if(DALI_LIKELY(Dali::Adaptor::IsAvailable())) ///< Avoid resource ready callback during shutting down
2387   {
2388     if(!mIsEmittingResourceReadySignal)
2389     {
2390       // Guard against calls to emit the signal during the callback
2391       mIsEmittingResourceReadySignal = true;
2392
2393       // If the signal handler changes visual, it may become ready during this call & therefore this method will
2394       // get called again recursively. If so, mIdleCallbackRegistered is set below, and we act on it after that secondary
2395       // invocation has completed by notifying in an Idle callback to prevent further recursion.
2396       Dali::Toolkit::Control handle(mControlImpl.GetOwner());
2397       mResourceReadySignal.Emit(handle);
2398
2399       mIsEmittingResourceReadySignal = false;
2400     }
2401     else
2402     {
2403       if(!mIdleCallbackRegistered)
2404       {
2405         mIdleCallbackRegistered = true;
2406
2407         // Add idler to emit the signal again
2408         if(!mIdleCallback)
2409         {
2410           // The callback manager takes the ownership of the callback object.
2411           mIdleCallback = MakeCallback(this, &Control::Impl::OnIdleCallback);
2412           if(DALI_UNLIKELY(!Adaptor::Get().AddIdle(mIdleCallback, true)))
2413           {
2414             DALI_LOG_ERROR("Fail to add idle callback for control resource ready. Skip this callback.\n");
2415             mIdleCallback           = nullptr;
2416             mIdleCallbackRegistered = false;
2417           }
2418         }
2419       }
2420     }
2421   }
2422 }
2423
2424 bool Control::Impl::OnIdleCallback()
2425 {
2426   // Reset the flag
2427   mIdleCallbackRegistered = false;
2428
2429   // A visual is ready so control may need relayouting if staged
2430   if(mControlImpl.Self().GetProperty<bool>(Actor::Property::CONNECTED_TO_SCENE))
2431   {
2432     mControlImpl.RelayoutRequest();
2433   }
2434
2435   EmitResourceReadySignal();
2436
2437   if(!mIdleCallbackRegistered)
2438   {
2439     // Set the pointer to null as the callback manager deletes the callback after execute it.
2440     mIdleCallback = nullptr;
2441   }
2442
2443   // Repeat idle if mIdleCallbackRegistered become true one more time.
2444   return mIdleCallbackRegistered;
2445 }
2446
2447 std::shared_ptr<Toolkit::DevelControl::ControlAccessible> Control::Impl::GetAccessibleObject()
2448 {
2449   return std::dynamic_pointer_cast<DevelControl::ControlAccessible>(Accessibility::Accessible::GetOwningPtr(mControlImpl.Self()));
2450 }
2451
2452 bool Control::Impl::IsAccessibleCreated() const
2453 {
2454   return !!Accessibility::Bridge::GetCurrentBridge()->GetAccessible(mControlImpl.Self());
2455 }
2456
2457 void Control::Impl::EnableCreateAccessible(bool enable)
2458 {
2459   mAccessibleCreatable = enable;
2460 }
2461
2462 bool Control::Impl::IsCreateAccessibleEnabled() const
2463 {
2464   return mAccessibleCreatable;
2465 }
2466
2467 void Control::Impl::ApplyFittingMode(const Vector2& size)
2468 {
2469   Actor self = mControlImpl.Self();
2470   for(RegisteredVisualContainer::Iterator iter = mVisuals.Begin(); iter != mVisuals.End(); iter++)
2471   {
2472     // Check whether the visual is empty and enabled
2473     if((*iter)->visual && (*iter)->enabled)
2474     {
2475       Internal::Visual::Base& visualImpl = Toolkit::GetImplementation((*iter)->visual);
2476
2477       // If the current visual is using the transform property map, fittingMode will not be applied.
2478       if(visualImpl.IsIgnoreFittingMode())
2479       {
2480         continue;
2481       }
2482
2483       Visual::FittingMode fittingMode  = visualImpl.GetFittingMode();
2484       Property::Map       transformMap = Property::Map();
2485
2486       // If the fittingMode is DONT_CARE, we don't need to apply fittingMode, just Set empty transformMap
2487       if(fittingMode == Visual::FittingMode::DONT_CARE)
2488       {
2489         if(visualImpl.GetType() != Toolkit::Visual::Type::TEXT)
2490         {
2491           ((*iter)->visual).SetTransformAndSize(transformMap, size);
2492         }
2493         continue;
2494       }
2495
2496       Extents padding = self.GetProperty<Extents>(Toolkit::Control::Property::PADDING);
2497
2498       bool zeroPadding = (padding == Extents());
2499
2500       Dali::LayoutDirection::Type layoutDirection = static_cast<Dali::LayoutDirection::Type>(
2501         self.GetProperty(Dali::Actor::Property::LAYOUT_DIRECTION).Get<int>());
2502       if(Dali::LayoutDirection::RIGHT_TO_LEFT == layoutDirection)
2503       {
2504         std::swap(padding.start, padding.end);
2505       }
2506
2507       // remove padding from the size to know how much is left for the visual
2508       Vector2 finalSize   = size - Vector2(padding.start + padding.end, padding.top + padding.bottom);
2509       Vector2 finalOffset = Vector2(padding.start, padding.top);
2510
2511       // Reset PIXEL_AREA after using OVER_FIT_KEEP_ASPECT_RATIO
2512       if(visualImpl.IsPixelAreaSetForFittingMode())
2513       {
2514         visualImpl.SetPixelAreaForFittingMode(FULL_TEXTURE_RECT);
2515       }
2516
2517       if((!zeroPadding) || // If padding is not zero
2518          (fittingMode != Visual::FittingMode::FILL))
2519       {
2520         visualImpl.SetTransformMapUsageForFittingMode(true);
2521
2522         Vector2 naturalSize;
2523         // NaturalSize will not be used for FILL fitting mode, which is default.
2524         // Skip GetNaturalSize
2525         if(fittingMode != Visual::FittingMode::FILL)
2526         {
2527           ((*iter)->visual).GetNaturalSize(naturalSize);
2528         }
2529
2530         // If FittingMode use FIT_WIDTH or FIT_HEIGTH, it need to change proper fittingMode
2531         if(fittingMode == Visual::FittingMode::FIT_WIDTH || fittingMode == Visual::FittingMode::FIT_HEIGHT)
2532         {
2533           const float widthRatio  = !Dali::EqualsZero(naturalSize.width) ? (finalSize.width / naturalSize.width) : 0.0f;
2534           const float heightRatio = !Dali::EqualsZero(naturalSize.height) ? (finalSize.height / naturalSize.height) : 0.0f;
2535           if(widthRatio < heightRatio)
2536           {
2537             // Final size has taller form than natural size.
2538             fittingMode = (fittingMode == Visual::FittingMode::FIT_WIDTH) ? Visual::FittingMode::FIT_KEEP_ASPECT_RATIO : Visual::FittingMode::OVER_FIT_KEEP_ASPECT_RATIO;
2539           }
2540           else
2541           {
2542             // Final size has wider form than natural size.
2543             fittingMode = (fittingMode == Visual::FittingMode::FIT_WIDTH) ? Visual::FittingMode::OVER_FIT_KEEP_ASPECT_RATIO : Visual::FittingMode::FIT_KEEP_ASPECT_RATIO;
2544           }
2545         }
2546
2547         // Calculate size for fittingMode
2548         switch(fittingMode)
2549         {
2550           case Visual::FittingMode::FIT_KEEP_ASPECT_RATIO:
2551           {
2552             auto availableVisualSize = finalSize;
2553
2554             // scale to fit the padded area
2555             finalSize = naturalSize * std::min((!Dali::EqualsZero(naturalSize.width) ? (availableVisualSize.width / naturalSize.width) : 0),
2556                                                (!Dali::EqualsZero(naturalSize.height) ? (availableVisualSize.height / naturalSize.height) : 0));
2557
2558             // calculate final offset within the padded area
2559             finalOffset += (availableVisualSize - finalSize) * .5f;
2560
2561             // populate the transform map
2562             transformMap.Add(Toolkit::Visual::Transform::Property::OFFSET, finalOffset)
2563               .Add(Toolkit::Visual::Transform::Property::SIZE, finalSize);
2564             break;
2565           }
2566           case Visual::FittingMode::OVER_FIT_KEEP_ASPECT_RATIO:
2567           {
2568             auto availableVisualSize = finalSize;
2569             finalSize                = naturalSize * std::max((!Dali::EqualsZero(naturalSize.width) ? (availableVisualSize.width / naturalSize.width) : 0.0f),
2570                                                (!Dali::EqualsZero(naturalSize.height) ? (availableVisualSize.height / naturalSize.height) : 0.0f));
2571
2572             auto originalOffset = finalOffset;
2573
2574             if(!visualImpl.IsPixelAreaSetForFittingMode() && !Dali::EqualsZero(finalSize.width) && !Dali::EqualsZero(finalSize.height))
2575             {
2576               float   x           = abs((availableVisualSize.width - finalSize.width) / finalSize.width) * .5f;
2577               float   y           = abs((availableVisualSize.height - finalSize.height) / finalSize.height) * .5f;
2578               float   widthRatio  = 1.f - abs((availableVisualSize.width - finalSize.width) / finalSize.width);
2579               float   heightRatio = 1.f - abs((availableVisualSize.height - finalSize.height) / finalSize.height);
2580               Vector4 pixelArea   = Vector4(x, y, widthRatio, heightRatio);
2581               visualImpl.SetPixelAreaForFittingMode(pixelArea);
2582             }
2583
2584             // populate the transform map
2585             transformMap.Add(Toolkit::Visual::Transform::Property::OFFSET, originalOffset)
2586               .Add(Toolkit::Visual::Transform::Property::SIZE, availableVisualSize);
2587             break;
2588           }
2589           case Visual::FittingMode::CENTER:
2590           {
2591             auto availableVisualSize = finalSize;
2592             if(availableVisualSize.width > naturalSize.width && availableVisualSize.height > naturalSize.height)
2593             {
2594               finalSize = naturalSize;
2595             }
2596             else
2597             {
2598               finalSize = naturalSize * std::min((!Dali::EqualsZero(naturalSize.width) ? (availableVisualSize.width / naturalSize.width) : 0.0f),
2599                                                  (!Dali::EqualsZero(naturalSize.height) ? (availableVisualSize.height / naturalSize.height) : 0.0f));
2600             }
2601
2602             finalOffset += (availableVisualSize - finalSize) * .5f;
2603
2604             // populate the transform map
2605             transformMap.Add(Toolkit::Visual::Transform::Property::OFFSET, finalOffset)
2606               .Add(Toolkit::Visual::Transform::Property::SIZE, finalSize);
2607             break;
2608           }
2609           case Visual::FittingMode::FILL:
2610           {
2611             transformMap.Add(Toolkit::Visual::Transform::Property::OFFSET, finalOffset)
2612               .Add(Toolkit::Visual::Transform::Property::SIZE, finalSize);
2613             break;
2614           }
2615           case Visual::FittingMode::FIT_WIDTH:
2616           case Visual::FittingMode::FIT_HEIGHT:
2617           case Visual::FittingMode::DONT_CARE:
2618           {
2619             // This FittingMode already converted
2620             break;
2621           }
2622         }
2623
2624         // Set extra value for applying transformMap
2625         transformMap.Add(Toolkit::Visual::Transform::Property::OFFSET_POLICY,
2626                          Vector2(Toolkit::Visual::Transform::Policy::ABSOLUTE, Toolkit::Visual::Transform::Policy::ABSOLUTE))
2627           .Add(Toolkit::Visual::Transform::Property::ORIGIN, Toolkit::Align::TOP_BEGIN)
2628           .Add(Toolkit::Visual::Transform::Property::ANCHOR_POINT, Toolkit::Align::TOP_BEGIN)
2629           .Add(Toolkit::Visual::Transform::Property::SIZE_POLICY,
2630                Vector2(Toolkit::Visual::Transform::Policy::ABSOLUTE, Toolkit::Visual::Transform::Policy::ABSOLUTE));
2631       }
2632       else if(visualImpl.IsTransformMapSetForFittingMode() && zeroPadding) // Reset offset to zero only if padding applied previously
2633       {
2634         visualImpl.SetTransformMapUsageForFittingMode(false);
2635
2636         // Reset the transform map
2637         transformMap.Add(Toolkit::Visual::Transform::Property::OFFSET, Vector2::ZERO)
2638           .Add(Toolkit::Visual::Transform::Property::OFFSET_POLICY,
2639                Vector2(Toolkit::Visual::Transform::Policy::RELATIVE, Toolkit::Visual::Transform::Policy::RELATIVE))
2640           .Add(Toolkit::Visual::Transform::Property::SIZE, Vector2::ONE)
2641           .Add(Toolkit::Visual::Transform::Property::SIZE_POLICY,
2642                Vector2(Toolkit::Visual::Transform::Policy::RELATIVE, Toolkit::Visual::Transform::Policy::RELATIVE));
2643       }
2644
2645       ((*iter)->visual).SetTransformAndSize(transformMap, size);
2646     }
2647   }
2648 }
2649
2650 void Control::Impl::RegisterProcessorOnce()
2651 {
2652   if(!mProcessorRegistered)
2653   {
2654     Adaptor::Get().RegisterProcessorOnce(*this, true);
2655     mProcessorRegistered = true;
2656   }
2657 }
2658
2659 void Control::Impl::Process(bool postProcessor)
2660 {
2661   // Call ApplyFittingMode
2662   ApplyFittingMode(mSize);
2663   mProcessorRegistered = false;
2664 }
2665
2666 } // namespace Internal
2667
2668 } // namespace Toolkit
2669
2670 } // namespace Dali