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