Add DevelControl::Property::AUTOMATION_ID
[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::AppendAccessibilityAttribute(const std::string& key, const std::string value)
1100 {
1101   Property::Value* checkedValue = mAccessibilityAttributes.Find(key);
1102   if(checkedValue)
1103   {
1104     mAccessibilityAttributes[key] = Property::Value(value);
1105   }
1106   else
1107   {
1108     mAccessibilityAttributes.Insert(key, value);
1109   }
1110 }
1111
1112 void Control::Impl::SetProperty(BaseObject* object, Property::Index index, const Property::Value& value)
1113 {
1114   Toolkit::Control control = Toolkit::Control::DownCast(BaseHandle(object));
1115
1116   if(control)
1117   {
1118     Control& controlImpl(GetImplementation(control));
1119
1120     switch(index)
1121     {
1122       case Toolkit::Control::Property::STYLE_NAME:
1123       {
1124         controlImpl.SetStyleName(value.Get<std::string>());
1125         break;
1126       }
1127
1128       case Toolkit::DevelControl::Property::STATE:
1129       {
1130         bool                   withTransitions = true;
1131         const Property::Value* valuePtr        = &value;
1132         const Property::Map*   map             = value.GetMap();
1133         if(map)
1134         {
1135           Property::Value* value2 = map->Find("withTransitions");
1136           if(value2)
1137           {
1138             withTransitions = value2->Get<bool>();
1139           }
1140
1141           valuePtr = map->Find("state");
1142         }
1143
1144         if(valuePtr)
1145         {
1146           Toolkit::DevelControl::State state(controlImpl.mImpl->mState);
1147           if(Scripting::GetEnumerationProperty<Toolkit::DevelControl::State>(*valuePtr, ControlStateTable, ControlStateTableCount, state))
1148           {
1149             controlImpl.mImpl->SetState(state, withTransitions);
1150           }
1151         }
1152       }
1153       break;
1154
1155       case Toolkit::DevelControl::Property::SUB_STATE:
1156       {
1157         std::string subState;
1158         if(value.Get(subState))
1159         {
1160           controlImpl.mImpl->SetSubState(subState);
1161         }
1162       }
1163       break;
1164
1165       case Toolkit::DevelControl::Property::LEFT_FOCUSABLE_ACTOR_ID:
1166       {
1167         int focusId;
1168         if(value.Get(focusId))
1169         {
1170           controlImpl.mImpl->mLeftFocusableActorId = focusId;
1171         }
1172       }
1173       break;
1174
1175       case Toolkit::DevelControl::Property::RIGHT_FOCUSABLE_ACTOR_ID:
1176       {
1177         int focusId;
1178         if(value.Get(focusId))
1179         {
1180           controlImpl.mImpl->mRightFocusableActorId = focusId;
1181         }
1182       }
1183       break;
1184
1185       case Toolkit::DevelControl::Property::UP_FOCUSABLE_ACTOR_ID:
1186       {
1187         int focusId;
1188         if(value.Get(focusId))
1189         {
1190           controlImpl.mImpl->mUpFocusableActorId = focusId;
1191         }
1192       }
1193       break;
1194
1195       case Toolkit::DevelControl::Property::DOWN_FOCUSABLE_ACTOR_ID:
1196       {
1197         int focusId;
1198         if(value.Get(focusId))
1199         {
1200           controlImpl.mImpl->mDownFocusableActorId = focusId;
1201         }
1202       }
1203       break;
1204
1205       case Toolkit::Control::Property::KEY_INPUT_FOCUS:
1206       {
1207         if(value.Get<bool>())
1208         {
1209           controlImpl.SetKeyInputFocus();
1210         }
1211         else
1212         {
1213           controlImpl.ClearKeyInputFocus();
1214         }
1215         break;
1216       }
1217
1218       case Toolkit::Control::Property::BACKGROUND:
1219       {
1220         std::string          url;
1221         Vector4              color;
1222         const Property::Map* map = value.GetMap();
1223         if(map && !map->Empty())
1224         {
1225           controlImpl.SetBackground(*map);
1226         }
1227         else if(value.Get(url))
1228         {
1229           // don't know the size to load
1230           Toolkit::Visual::Base visual = Toolkit::VisualFactory::Get().CreateVisual(url, ImageDimensions());
1231           if(visual)
1232           {
1233             controlImpl.mImpl->RegisterVisual(Toolkit::Control::Property::BACKGROUND, visual, DepthIndex::BACKGROUND);
1234           }
1235         }
1236         else if(value.Get(color))
1237         {
1238           controlImpl.SetBackgroundColor(color);
1239         }
1240         else
1241         {
1242           // The background is an empty property map, so we should clear the background
1243           controlImpl.ClearBackground();
1244         }
1245         break;
1246       }
1247
1248       case Toolkit::Control::Property::MARGIN:
1249       {
1250         Extents margin;
1251         if(value.Get(margin))
1252         {
1253           controlImpl.mImpl->SetMargin(margin);
1254         }
1255         break;
1256       }
1257
1258       case Toolkit::Control::Property::PADDING:
1259       {
1260         Extents padding;
1261         if(value.Get(padding))
1262         {
1263           controlImpl.mImpl->SetPadding(padding);
1264         }
1265         break;
1266       }
1267
1268       case Toolkit::DevelControl::Property::TOOLTIP:
1269       {
1270         TooltipPtr& tooltipPtr = controlImpl.mImpl->mTooltip;
1271         if(!tooltipPtr)
1272         {
1273           tooltipPtr = Tooltip::New(control);
1274         }
1275         tooltipPtr->SetProperties(value);
1276         break;
1277       }
1278
1279       case Toolkit::DevelControl::Property::SHADOW:
1280       {
1281         const Property::Map* map = value.GetMap();
1282         if(map && !map->Empty())
1283         {
1284           controlImpl.mImpl->SetShadow(*map);
1285         }
1286         else
1287         {
1288           // The shadow is an empty property map, so we should clear the shadow
1289           controlImpl.mImpl->ClearShadow();
1290         }
1291         break;
1292       }
1293
1294       case Toolkit::DevelControl::Property::ACCESSIBILITY_NAME:
1295       {
1296         std::string name;
1297         if(value.Get(name))
1298         {
1299           controlImpl.mImpl->mAccessibilityName = name;
1300         }
1301         break;
1302       }
1303
1304       case Toolkit::DevelControl::Property::ACCESSIBILITY_DESCRIPTION:
1305       {
1306         std::string text;
1307         if(value.Get(text))
1308         {
1309           controlImpl.mImpl->mAccessibilityDescription = text;
1310         }
1311         break;
1312       }
1313
1314       case Toolkit::DevelControl::Property::ACCESSIBILITY_TRANSLATION_DOMAIN:
1315       {
1316         std::string text;
1317         if(value.Get(text))
1318         {
1319           controlImpl.mImpl->mAccessibilityTranslationDomain = text;
1320         }
1321         break;
1322       }
1323
1324       case Toolkit::DevelControl::Property::ACCESSIBILITY_ROLE:
1325       {
1326         Dali::Accessibility::Role role;
1327         if(value.Get(role))
1328         {
1329           controlImpl.mImpl->mAccessibilityRole = role;
1330         }
1331         break;
1332       }
1333
1334       case Toolkit::DevelControl::Property::ACCESSIBILITY_HIGHLIGHTABLE:
1335       {
1336         bool highlightable;
1337         if(value.Get(highlightable))
1338         {
1339           controlImpl.mImpl->mAccessibilityHighlightable = highlightable;
1340         }
1341         break;
1342       }
1343
1344       case Toolkit::DevelControl::Property::ACCESSIBILITY_ATTRIBUTES:
1345       {
1346         const Property::Map* map = value.GetMap();
1347         if(map && !map->Empty())
1348         {
1349           controlImpl.mImpl->mAccessibilityAttributes = *map;
1350         }
1351         break;
1352       }
1353
1354       case Toolkit::DevelControl::Property::DISPATCH_KEY_EVENTS:
1355       {
1356         bool dispatch;
1357         if(value.Get(dispatch))
1358         {
1359           controlImpl.mImpl->mDispatchKeyEvents = dispatch;
1360         }
1361         break;
1362       }
1363
1364       case Toolkit::DevelControl::Property::ACCESSIBILITY_HIDDEN:
1365       {
1366         bool hidden;
1367         if(value.Get(hidden))
1368         {
1369           controlImpl.mImpl->mAccessibilityHidden = hidden;
1370
1371           auto* accessible = controlImpl.GetAccessibleObject();
1372           auto* parent     = dynamic_cast<Dali::Accessibility::ActorAccessible*>(accessible->GetParent());
1373           if(parent)
1374           {
1375             parent->OnChildrenChanged();
1376           }
1377         }
1378         break;
1379       }
1380       case Toolkit::DevelControl::Property::CLOCKWISE_FOCUSABLE_ACTOR_ID:
1381       {
1382         int focusId;
1383         if(value.Get(focusId))
1384         {
1385           controlImpl.mImpl->mClockwiseFocusableActorId = focusId;
1386         }
1387         break;
1388       }
1389       case Toolkit::DevelControl::Property::COUNTER_CLOCKWISE_FOCUSABLE_ACTOR_ID:
1390       {
1391         int focusId;
1392         if(value.Get(focusId))
1393         {
1394           controlImpl.mImpl->mCounterClockwiseFocusableActorId = focusId;
1395         }
1396         break;
1397       }
1398
1399       case Toolkit::DevelControl::Property::AUTOMATION_ID:
1400       {
1401         std::string automationId;
1402         if(value.Get(automationId))
1403         {
1404           controlImpl.mImpl->mAutomationId = automationId;
1405         }
1406         break;
1407       }
1408     }
1409   }
1410 }
1411
1412 Property::Value Control::Impl::GetProperty(BaseObject* object, Property::Index index)
1413 {
1414   Property::Value value;
1415
1416   Toolkit::Control control = Toolkit::Control::DownCast(BaseHandle(object));
1417
1418   if(control)
1419   {
1420     Control& controlImpl(GetImplementation(control));
1421
1422     switch(index)
1423     {
1424       case Toolkit::Control::Property::STYLE_NAME:
1425       {
1426         value = controlImpl.GetStyleName();
1427         break;
1428       }
1429
1430       case Toolkit::DevelControl::Property::STATE:
1431       {
1432         value = controlImpl.mImpl->mState;
1433         break;
1434       }
1435
1436       case Toolkit::DevelControl::Property::SUB_STATE:
1437       {
1438         value = controlImpl.mImpl->mSubStateName;
1439         break;
1440       }
1441
1442       case Toolkit::DevelControl::Property::LEFT_FOCUSABLE_ACTOR_ID:
1443       {
1444         value = controlImpl.mImpl->mLeftFocusableActorId;
1445         break;
1446       }
1447
1448       case Toolkit::DevelControl::Property::RIGHT_FOCUSABLE_ACTOR_ID:
1449       {
1450         value = controlImpl.mImpl->mRightFocusableActorId;
1451         break;
1452       }
1453
1454       case Toolkit::DevelControl::Property::UP_FOCUSABLE_ACTOR_ID:
1455       {
1456         value = controlImpl.mImpl->mUpFocusableActorId;
1457         break;
1458       }
1459
1460       case Toolkit::DevelControl::Property::DOWN_FOCUSABLE_ACTOR_ID:
1461       {
1462         value = controlImpl.mImpl->mDownFocusableActorId;
1463         break;
1464       }
1465
1466       case Toolkit::Control::Property::KEY_INPUT_FOCUS:
1467       {
1468         value = controlImpl.HasKeyInputFocus();
1469         break;
1470       }
1471
1472       case Toolkit::Control::Property::BACKGROUND:
1473       {
1474         Property::Map         map;
1475         Toolkit::Visual::Base visual = controlImpl.mImpl->GetVisual(Toolkit::Control::Property::BACKGROUND);
1476         if(visual)
1477         {
1478           visual.CreatePropertyMap(map);
1479         }
1480
1481         value = map;
1482         break;
1483       }
1484
1485       case Toolkit::Control::Property::MARGIN:
1486       {
1487         value = controlImpl.mImpl->GetMargin();
1488         break;
1489       }
1490
1491       case Toolkit::Control::Property::PADDING:
1492       {
1493         value = controlImpl.mImpl->GetPadding();
1494         break;
1495       }
1496
1497       case Toolkit::DevelControl::Property::TOOLTIP:
1498       {
1499         Property::Map map;
1500         if(controlImpl.mImpl->mTooltip)
1501         {
1502           controlImpl.mImpl->mTooltip->CreatePropertyMap(map);
1503         }
1504         value = map;
1505         break;
1506       }
1507
1508       case Toolkit::DevelControl::Property::SHADOW:
1509       {
1510         Property::Map         map;
1511         Toolkit::Visual::Base visual = controlImpl.mImpl->GetVisual(Toolkit::DevelControl::Property::SHADOW);
1512         if(visual)
1513         {
1514           visual.CreatePropertyMap(map);
1515         }
1516
1517         value = map;
1518         break;
1519       }
1520
1521       case Toolkit::DevelControl::Property::ACCESSIBILITY_NAME:
1522       {
1523         value = controlImpl.mImpl->mAccessibilityName;
1524         break;
1525       }
1526
1527       case Toolkit::DevelControl::Property::ACCESSIBILITY_DESCRIPTION:
1528       {
1529         value = controlImpl.mImpl->mAccessibilityDescription;
1530         break;
1531       }
1532
1533       case Toolkit::DevelControl::Property::ACCESSIBILITY_TRANSLATION_DOMAIN:
1534       {
1535         value = controlImpl.mImpl->mAccessibilityTranslationDomain;
1536         break;
1537       }
1538
1539       case Toolkit::DevelControl::Property::ACCESSIBILITY_ROLE:
1540       {
1541         value = Property::Value(controlImpl.mImpl->mAccessibilityRole);
1542         break;
1543       }
1544
1545       case Toolkit::DevelControl::Property::ACCESSIBILITY_HIGHLIGHTABLE:
1546       {
1547         value = controlImpl.mImpl->mAccessibilityHighlightable;
1548         break;
1549       }
1550
1551       case Toolkit::DevelControl::Property::ACCESSIBILITY_ATTRIBUTES:
1552       {
1553         value = controlImpl.mImpl->mAccessibilityAttributes;
1554         break;
1555       }
1556
1557       case Toolkit::DevelControl::Property::DISPATCH_KEY_EVENTS:
1558       {
1559         value = controlImpl.mImpl->mDispatchKeyEvents;
1560         break;
1561       }
1562
1563       case Toolkit::DevelControl::Property::ACCESSIBILITY_HIDDEN:
1564       {
1565         value = controlImpl.mImpl->mAccessibilityHidden;
1566         break;
1567       }
1568
1569       case Toolkit::DevelControl::Property::CLOCKWISE_FOCUSABLE_ACTOR_ID:
1570       {
1571         value = controlImpl.mImpl->mClockwiseFocusableActorId;
1572         break;
1573       }
1574
1575       case Toolkit::DevelControl::Property::COUNTER_CLOCKWISE_FOCUSABLE_ACTOR_ID:
1576       {
1577         value = controlImpl.mImpl->mCounterClockwiseFocusableActorId;
1578         break;
1579       }
1580
1581       case Toolkit::DevelControl::Property::AUTOMATION_ID:
1582       {
1583         value = controlImpl.mImpl->mAutomationId;
1584         break;
1585       }
1586     }
1587   }
1588
1589   return value;
1590 }
1591
1592 void Control::Impl::RemoveAccessibilityAttribute(const std::string& key)
1593 {
1594   Property::Value* value = mAccessibilityAttributes.Find(key);
1595   if(value)
1596   {
1597     mAccessibilityAttributes[key] = Property::Value();
1598   }
1599 }
1600
1601 void Control::Impl::ClearAccessibilityAttributes()
1602 {
1603   mAccessibilityAttributes.Clear();
1604 }
1605
1606 void Control::Impl::SetAccessibilityReadingInfoType(const Dali::Accessibility::ReadingInfoTypes types)
1607 {
1608   std::string value{};
1609   if(types[Dali::Accessibility::ReadingInfoType::NAME])
1610   {
1611     value += READING_INFO_TYPE_NAME;
1612   }
1613   if(types[Dali::Accessibility::ReadingInfoType::ROLE])
1614   {
1615     if(!value.empty())
1616     {
1617       value += READING_INFO_TYPE_SEPARATOR;
1618     }
1619     value += READING_INFO_TYPE_ROLE;
1620   }
1621   if(types[Dali::Accessibility::ReadingInfoType::DESCRIPTION])
1622   {
1623     if(!value.empty())
1624     {
1625       value += READING_INFO_TYPE_SEPARATOR;
1626     }
1627     value += READING_INFO_TYPE_DESCRIPTION;
1628   }
1629   if(types[Dali::Accessibility::ReadingInfoType::STATE])
1630   {
1631     if(!value.empty())
1632     {
1633       value += READING_INFO_TYPE_SEPARATOR;
1634     }
1635     value += READING_INFO_TYPE_STATE;
1636   }
1637   AppendAccessibilityAttribute(READING_INFO_TYPE_ATTRIBUTE_NAME, value);
1638 }
1639
1640 Dali::Accessibility::ReadingInfoTypes Control::Impl::GetAccessibilityReadingInfoType() const
1641 {
1642   std::string value{};
1643   auto        place = mAccessibilityAttributes.Find(READING_INFO_TYPE_ATTRIBUTE_NAME);
1644   if(place)
1645   {
1646     place->Get(value);
1647   }
1648   else
1649   {
1650     Dali::Accessibility::ReadingInfoTypes types;
1651     types[Dali::Accessibility::ReadingInfoType::NAME]        = true;
1652     types[Dali::Accessibility::ReadingInfoType::ROLE]        = true;
1653     types[Dali::Accessibility::ReadingInfoType::DESCRIPTION] = true;
1654     types[Dali::Accessibility::ReadingInfoType::STATE]       = true;
1655     return types;
1656   }
1657
1658   if(value.empty())
1659   {
1660     return {};
1661   }
1662
1663   Dali::Accessibility::ReadingInfoTypes types;
1664
1665   if(value.find(READING_INFO_TYPE_NAME) != std::string::npos)
1666   {
1667     types[Dali::Accessibility::ReadingInfoType::NAME] = true;
1668   }
1669   if(value.find(READING_INFO_TYPE_ROLE) != std::string::npos)
1670   {
1671     types[Dali::Accessibility::ReadingInfoType::ROLE] = true;
1672   }
1673   if(value.find(READING_INFO_TYPE_DESCRIPTION) != std::string::npos)
1674   {
1675     types[Dali::Accessibility::ReadingInfoType::DESCRIPTION] = true;
1676   }
1677   if(value.find(READING_INFO_TYPE_STATE) != std::string::npos)
1678   {
1679     types[Dali::Accessibility::ReadingInfoType::STATE] = true;
1680   }
1681
1682   return types;
1683 }
1684
1685 void Control::Impl::CopyInstancedProperties(RegisteredVisualContainer& visuals, Dictionary<Property::Map>& instancedProperties)
1686 {
1687   for(RegisteredVisualContainer::Iterator iter = visuals.Begin(); iter != visuals.End(); iter++)
1688   {
1689     if((*iter)->visual)
1690     {
1691       Property::Map instanceMap;
1692       Toolkit::GetImplementation((*iter)->visual).CreateInstancePropertyMap(instanceMap);
1693       instancedProperties.Add((*iter)->visual.GetName(), instanceMap);
1694     }
1695   }
1696 }
1697
1698 void Control::Impl::RemoveVisual(RegisteredVisualContainer& visuals, const std::string& visualName)
1699 {
1700   Actor self(mControlImpl.Self());
1701
1702   for(RegisteredVisualContainer::Iterator visualIter = visuals.Begin();
1703       visualIter != visuals.End();
1704       ++visualIter)
1705   {
1706     Toolkit::Visual::Base visual = (*visualIter)->visual;
1707     if(visual && visual.GetName() == visualName)
1708     {
1709       Toolkit::GetImplementation(visual).SetOffScene(self);
1710       (*visualIter)->visual.Reset();
1711       visuals.Erase(visualIter);
1712       break;
1713     }
1714   }
1715 }
1716
1717 void Control::Impl::RemoveVisuals(RegisteredVisualContainer& visuals, DictionaryKeys& removeVisuals)
1718 {
1719   Actor self(mControlImpl.Self());
1720   for(DictionaryKeys::iterator iter = removeVisuals.begin(); iter != removeVisuals.end(); ++iter)
1721   {
1722     const std::string visualName = *iter;
1723     RemoveVisual(visuals, visualName);
1724   }
1725 }
1726
1727 void Control::Impl::RecreateChangedVisuals(Dictionary<Property::Map>& stateVisualsToChange,
1728                                            Dictionary<Property::Map>& instancedProperties)
1729 {
1730   Dali::CustomActor handle(mControlImpl.GetOwner());
1731   for(Dictionary<Property::Map>::iterator iter = stateVisualsToChange.Begin();
1732       iter != stateVisualsToChange.End();
1733       ++iter)
1734   {
1735     const std::string&   visualName = (*iter).key;
1736     const Property::Map& toMap      = (*iter).entry;
1737
1738     Actor                               self = mControlImpl.Self();
1739     RegisteredVisualContainer::Iterator registeredVisualsiter;
1740     // Check if visual (visualName) is already registered, this is the current visual.
1741     if(FindVisual(visualName, mVisuals, registeredVisualsiter))
1742     {
1743       Toolkit::Visual::Base& visual = (*registeredVisualsiter)->visual;
1744       if(visual)
1745       {
1746         // No longer required to know if the replaced visual's resources are ready
1747         StopObservingVisual(visual);
1748
1749         // If control staged then visuals will be swapped once ready
1750         if(self.GetProperty<bool>(Actor::Property::CONNECTED_TO_SCENE))
1751         {
1752           // Check if visual is currently in the process of being replaced ( is in removal container )
1753           RegisteredVisualContainer::Iterator visualQueuedForRemoval;
1754           if(FindVisual(visualName, mRemoveVisuals, visualQueuedForRemoval))
1755           {
1756             // Visual with same visual name is already in removal container so current visual pending
1757             // Only the the last requested visual will be displayed so remove current visual which is staged but not ready.
1758             Toolkit::GetImplementation(visual).SetOffScene(self);
1759             (*registeredVisualsiter)->visual.Reset();
1760             mVisuals.Erase(registeredVisualsiter);
1761           }
1762           else
1763           {
1764             // current visual not already in removal container so add now.
1765             DALI_LOG_INFO(gLogFilter, Debug::Verbose, "RegisterVisual Move current registered visual to removal Queue: %s \n", visualName.c_str());
1766             MoveVisual(registeredVisualsiter, mVisuals, mRemoveVisuals);
1767           }
1768         }
1769         else
1770         {
1771           // Control not staged or visual disabled so can just erase from registered visuals and new visual will be added later.
1772           (*registeredVisualsiter)->visual.Reset();
1773           mVisuals.Erase(registeredVisualsiter);
1774         }
1775       }
1776
1777       const Property::Map* instancedMap = instancedProperties.FindConst(visualName);
1778       Style::ApplyVisual(handle, visualName, toMap, instancedMap);
1779     }
1780   }
1781 }
1782
1783 void Control::Impl::ReplaceStateVisualsAndProperties(const StylePtr oldState, const StylePtr newState, const std::string& subState)
1784 {
1785   // Collect all old visual names
1786   DictionaryKeys stateVisualsToRemove;
1787   if(oldState)
1788   {
1789     oldState->visuals.GetKeys(stateVisualsToRemove);
1790     if(!subState.empty())
1791     {
1792       const StylePtr* oldSubState = oldState->subStates.FindConst(subState);
1793       if(oldSubState)
1794       {
1795         DictionaryKeys subStateVisualsToRemove;
1796         (*oldSubState)->visuals.GetKeys(subStateVisualsToRemove);
1797         Merge(stateVisualsToRemove, subStateVisualsToRemove);
1798       }
1799     }
1800   }
1801
1802   // Collect all new visual properties
1803   Dictionary<Property::Map> stateVisualsToAdd;
1804   if(newState)
1805   {
1806     stateVisualsToAdd = newState->visuals;
1807     if(!subState.empty())
1808     {
1809       const StylePtr* newSubState = newState->subStates.FindConst(subState);
1810       if(newSubState)
1811       {
1812         stateVisualsToAdd.Merge((*newSubState)->visuals);
1813       }
1814     }
1815   }
1816
1817   // If a name is in both add/remove, move it to change list.
1818   Dictionary<Property::Map> stateVisualsToChange;
1819   FindChangableVisuals(stateVisualsToAdd, stateVisualsToChange, stateVisualsToRemove);
1820
1821   // Copy instanced properties (e.g. text label) of current visuals
1822   Dictionary<Property::Map> instancedProperties;
1823   CopyInstancedProperties(mVisuals, instancedProperties);
1824
1825   // For each visual in remove list, remove from mVisuals
1826   RemoveVisuals(mVisuals, stateVisualsToRemove);
1827
1828   // For each visual in add list, create and add to mVisuals
1829   Dali::CustomActor handle(mControlImpl.GetOwner());
1830   Style::ApplyVisuals(handle, stateVisualsToAdd, instancedProperties);
1831
1832   // For each visual in change list, if it requires a new visual,
1833   // remove old visual, create and add to mVisuals
1834   RecreateChangedVisuals(stateVisualsToChange, instancedProperties);
1835 }
1836
1837 void Control::Impl::SetState(DevelControl::State newState, bool withTransitions)
1838 {
1839   DevelControl::State oldState = mState;
1840   Dali::CustomActor   handle(mControlImpl.GetOwner());
1841   DALI_LOG_INFO(gLogFilter, Debug::Concise, "Control::Impl::SetState: %s\n", (mState == DevelControl::NORMAL ? "NORMAL" : (mState == DevelControl::FOCUSED ? "FOCUSED" : (mState == DevelControl::DISABLED ? "DISABLED" : "NONE"))));
1842
1843   if(mState != newState)
1844   {
1845     // If mState was Disabled, and new state is Focused, should probably
1846     // store that fact, e.g. in another property that FocusManager can access.
1847     mState = newState;
1848
1849     // Trigger state change and transitions
1850     // Apply new style, if stylemanager is available
1851     Toolkit::StyleManager styleManager = Toolkit::StyleManager::Get();
1852     if(styleManager)
1853     {
1854       const StylePtr stylePtr = GetImpl(styleManager).GetRecordedStyle(Toolkit::Control(mControlImpl.GetOwner()));
1855
1856       if(stylePtr)
1857       {
1858         std::string oldStateName = Scripting::GetEnumerationName<Toolkit::DevelControl::State>(oldState, ControlStateTable, ControlStateTableCount);
1859         std::string newStateName = Scripting::GetEnumerationName<Toolkit::DevelControl::State>(newState, ControlStateTable, ControlStateTableCount);
1860
1861         const StylePtr* newStateStyle = stylePtr->subStates.Find(newStateName);
1862         const StylePtr* oldStateStyle = stylePtr->subStates.Find(oldStateName);
1863         if(oldStateStyle && newStateStyle)
1864         {
1865           // Only change if both state styles exist
1866           ReplaceStateVisualsAndProperties(*oldStateStyle, *newStateStyle, mSubStateName);
1867         }
1868       }
1869     }
1870   }
1871 }
1872
1873 void Control::Impl::SetSubState(const std::string& subStateName, bool withTransitions)
1874 {
1875   if(mSubStateName != subStateName)
1876   {
1877     // Get existing sub-state visuals, and unregister them
1878     Dali::CustomActor handle(mControlImpl.GetOwner());
1879
1880     Toolkit::StyleManager styleManager = Toolkit::StyleManager::Get();
1881     if(styleManager)
1882     {
1883       const StylePtr stylePtr = GetImpl(styleManager).GetRecordedStyle(Toolkit::Control(mControlImpl.GetOwner()));
1884       if(stylePtr)
1885       {
1886         // Stringify state
1887         std::string stateName = Scripting::GetEnumerationName<Toolkit::DevelControl::State>(mState, ControlStateTable, ControlStateTableCount);
1888
1889         const StylePtr* state = stylePtr->subStates.Find(stateName);
1890         if(state)
1891         {
1892           StylePtr stateStyle(*state);
1893
1894           const StylePtr* newStateStyle = stateStyle->subStates.Find(subStateName);
1895           const StylePtr* oldStateStyle = stateStyle->subStates.Find(mSubStateName);
1896           if(oldStateStyle && newStateStyle)
1897           {
1898             std::string empty;
1899             ReplaceStateVisualsAndProperties(*oldStateStyle, *newStateStyle, empty);
1900           }
1901         }
1902       }
1903     }
1904
1905     mSubStateName = subStateName;
1906   }
1907 }
1908
1909 void Control::Impl::OnSceneDisconnection()
1910 {
1911   Actor self = mControlImpl.Self();
1912
1913   // Any visuals set for replacement but not yet ready should still be registered.
1914   // Reason: If a request was made to register a new visual but the control removed from scene before visual was ready
1915   // then when this control appears back on stage it should use that new visual.
1916
1917   // Iterate through all registered visuals and set off scene
1918   SetVisualsOffScene(mVisuals, self);
1919
1920   // Visuals pending replacement can now be taken out of the removal list and set off scene
1921   // Iterate through all replacement visuals and add to a move queue then set off scene
1922   for(auto removalIter = mRemoveVisuals.Begin(), end = mRemoveVisuals.End(); removalIter != end; removalIter++)
1923   {
1924     Toolkit::GetImplementation((*removalIter)->visual).SetOffScene(self);
1925   }
1926
1927   for(auto replacedIter = mVisuals.Begin(), end = mVisuals.End(); replacedIter != end; replacedIter++)
1928   {
1929     (*replacedIter)->pending = false;
1930   }
1931
1932   mRemoveVisuals.Clear();
1933 }
1934
1935 void Control::Impl::SetMargin(Extents margin)
1936 {
1937   mControlImpl.mImpl->mMargin = margin;
1938
1939   // Trigger a size negotiation request that may be needed when setting a margin.
1940   mControlImpl.RelayoutRequest();
1941 }
1942
1943 Extents Control::Impl::GetMargin() const
1944 {
1945   return mControlImpl.mImpl->mMargin;
1946 }
1947
1948 void Control::Impl::SetPadding(Extents padding)
1949 {
1950   mControlImpl.mImpl->mPadding = padding;
1951
1952   // Trigger a size negotiation request that may be needed when setting a padding.
1953   mControlImpl.RelayoutRequest();
1954 }
1955
1956 Extents Control::Impl::GetPadding() const
1957 {
1958   return mControlImpl.mImpl->mPadding;
1959 }
1960
1961 void Control::Impl::SetInputMethodContext(InputMethodContext& inputMethodContext)
1962 {
1963   mInputMethodContext = inputMethodContext;
1964 }
1965
1966 bool Control::Impl::FilterKeyEvent(const KeyEvent& event)
1967 {
1968   bool consumed(false);
1969
1970   if(mInputMethodContext)
1971   {
1972     consumed = mInputMethodContext.FilterEventKey(event);
1973   }
1974   return consumed;
1975 }
1976
1977 DevelControl::VisualEventSignalType& Control::Impl::VisualEventSignal()
1978 {
1979   return mVisualEventSignal;
1980 }
1981
1982 void Control::Impl::SetShadow(const Property::Map& map)
1983 {
1984   Toolkit::Visual::Base visual = Toolkit::VisualFactory::Get().CreateVisual(map);
1985   visual.SetName("shadow");
1986
1987   if(visual)
1988   {
1989     mControlImpl.mImpl->RegisterVisual(Toolkit::DevelControl::Property::SHADOW, visual, DepthIndex::BACKGROUND_EFFECT);
1990
1991     mControlImpl.RelayoutRequest();
1992   }
1993 }
1994
1995 void Control::Impl::ClearShadow()
1996 {
1997   mControlImpl.mImpl->UnregisterVisual(Toolkit::DevelControl::Property::SHADOW);
1998
1999   // Trigger a size negotiation request that may be needed when unregistering a visual.
2000   mControlImpl.RelayoutRequest();
2001 }
2002
2003 Dali::Property Control::Impl::GetVisualProperty(Dali::Property::Index index, Dali::Property::Key visualPropertyKey)
2004 {
2005   Toolkit::Visual::Base visual = GetVisualByIndex(mVisuals, index);
2006   if(visual)
2007   {
2008     Internal::Visual::Base& visualImpl = Toolkit::GetImplementation(visual);
2009     return visualImpl.GetPropertyObject(visualPropertyKey);
2010   }
2011
2012   Handle handle;
2013   return Dali::Property(handle, Property::INVALID_INDEX);
2014 }
2015
2016 void Control::Impl::CreateTransitions(std::vector<std::pair<Dali::Property::Index, Dali::Property::Map>>& sourceProperties,
2017                                       std::vector<std::pair<Dali::Property::Index, Dali::Property::Map>>& destinationProperties,
2018                                       Dali::Toolkit::Control                                              source,
2019                                       Dali::Toolkit::Control                                              destination)
2020 {
2021   // Retrieves background properties to be transitioned.
2022   Dali::Property::Map backgroundSourcePropertyMap, backgroundDestinationPropertyMap;
2023   mControlImpl.MakeVisualTransition(backgroundSourcePropertyMap, backgroundDestinationPropertyMap, source, destination, Toolkit::Control::Property::BACKGROUND);
2024   if(backgroundSourcePropertyMap.Count() > 0)
2025   {
2026     sourceProperties.push_back(std::pair<Dali::Property::Index, Dali::Property::Map>(Toolkit::Control::Property::BACKGROUND, backgroundSourcePropertyMap));
2027     destinationProperties.push_back(std::pair<Dali::Property::Index, Dali::Property::Map>(Toolkit::Control::Property::BACKGROUND, backgroundDestinationPropertyMap));
2028   }
2029
2030   // Retrieves shadow properties to be transitioned.
2031   Dali::Property::Map shadowSourcePropertyMap, shadowDestinationPropertyMap;
2032   mControlImpl.MakeVisualTransition(shadowSourcePropertyMap, shadowDestinationPropertyMap, source, destination, Toolkit::DevelControl::Property::SHADOW);
2033   if(shadowSourcePropertyMap.Count() > 0)
2034   {
2035     sourceProperties.push_back(std::pair<Dali::Property::Index, Dali::Property::Map>(Toolkit::DevelControl::Property::SHADOW, shadowSourcePropertyMap));
2036     destinationProperties.push_back(std::pair<Dali::Property::Index, Dali::Property::Map>(Toolkit::DevelControl::Property::SHADOW, shadowDestinationPropertyMap));
2037   }
2038
2039   // Retrieves transition from inherited class.
2040   mControlImpl.OnCreateTransitions(sourceProperties, destinationProperties, source, destination);
2041 }
2042
2043 void Control::Impl::UpdateVisualProperties(const std::vector<std::pair<Dali::Property::Index, Dali::Property::Map>>& properties)
2044 {
2045   for(auto&& data : properties)
2046   {
2047     if(data.first == Toolkit::Control::Property::BACKGROUND)
2048     {
2049       DoAction(Toolkit::Control::Property::BACKGROUND, DevelVisual::Action::UPDATE_PROPERTY, data.second);
2050     }
2051     else if(data.first == Toolkit::DevelControl::Property::SHADOW)
2052     {
2053       DoAction(Toolkit::DevelControl::Property::SHADOW, DevelVisual::Action::UPDATE_PROPERTY, data.second);
2054     }
2055   }
2056   mControlImpl.OnUpdateVisualProperties(properties);
2057 }
2058
2059 void Control::Impl::EmitResourceReadySignal()
2060 {
2061   if(!mIsEmittingResourceReadySignal)
2062   {
2063     // Guard against calls to emit the signal during the callback
2064     mIsEmittingResourceReadySignal = true;
2065
2066     // If the signal handler changes visual, it may become ready during this call & therefore this method will
2067     // get called again recursively. If so, mNeedToEmitResourceReady is set below, and we act on it after that secondary
2068     // invocation has completed by notifying in an Idle callback to prevent further recursion.
2069     Dali::Toolkit::Control handle(mControlImpl.GetOwner());
2070     mResourceReadySignal.Emit(handle);
2071
2072     if(mNeedToEmitResourceReady)
2073     {
2074       // Add idler to emit the signal again
2075       if(!mIdleCallback)
2076       {
2077         // The callback manager takes the ownership of the callback object.
2078         mIdleCallback = MakeCallback(this, &Control::Impl::OnIdleCallback);
2079         Adaptor::Get().AddIdle(mIdleCallback, false);
2080       }
2081     }
2082
2083     mIsEmittingResourceReadySignal = false;
2084   }
2085   else
2086   {
2087     mNeedToEmitResourceReady = true;
2088   }
2089 }
2090
2091 void Control::Impl::OnIdleCallback()
2092 {
2093   if(mNeedToEmitResourceReady)
2094   {
2095     // Reset the flag
2096     mNeedToEmitResourceReady = false;
2097
2098     // A visual is ready so control may need relayouting if staged
2099     if(mControlImpl.Self().GetProperty<bool>(Actor::Property::CONNECTED_TO_SCENE))
2100     {
2101       mControlImpl.RelayoutRequest();
2102     }
2103
2104     EmitResourceReadySignal();
2105   }
2106
2107   // Set the pointer to null as the callback manager deletes the callback after execute it.
2108   mIdleCallback = nullptr;
2109 }
2110
2111 Toolkit::DevelControl::ControlAccessible* Control::Impl::GetAccessibleObject()
2112 {
2113   if(!mAccessibleObject)
2114   {
2115     mAccessibleObject.reset(mControlImpl.CreateAccessibleObject());
2116   }
2117
2118   return mAccessibleObject.get();
2119 }
2120
2121 } // namespace Internal
2122
2123 } // namespace Toolkit
2124
2125 } // namespace Dali