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