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