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