5b638e814388bfec8453134963f6987c9f153c60
[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
489 // clang-format on
490
491 Control::Impl::Impl(Control& controlImpl)
492 : mControlImpl(controlImpl),
493   mState(Toolkit::DevelControl::NORMAL),
494   mSubStateName(""),
495   mLeftFocusableActorId(-1),
496   mRightFocusableActorId(-1),
497   mUpFocusableActorId(-1),
498   mDownFocusableActorId(-1),
499   mClockwiseFocusableActorId(-1),
500   mCounterClockwiseFocusableActorId(-1),
501   mStyleName(""),
502   mBackgroundColor(Color::TRANSPARENT),
503   mStartingPinchScale(nullptr),
504   mMargin(0, 0, 0, 0),
505   mPadding(0, 0, 0, 0),
506   mKeyEventSignal(),
507   mKeyInputFocusGainedSignal(),
508   mKeyInputFocusLostSignal(),
509   mResourceReadySignal(),
510   mVisualEventSignal(),
511   mAccessibilityGetNameSignal(),
512   mAccessibilityGetDescriptionSignal(),
513   mAccessibilityDoGestureSignal(),
514   mPinchGestureDetector(),
515   mPanGestureDetector(),
516   mTapGestureDetector(),
517   mLongPressGestureDetector(),
518   mTooltip(NULL),
519   mInputMethodContext(),
520   mIdleCallback(nullptr),
521   mFlags(Control::ControlBehaviour(CONTROL_BEHAVIOUR_DEFAULT)),
522   mIsKeyboardNavigationSupported(false),
523   mIsKeyboardFocusGroup(false),
524   mIsEmittingResourceReadySignal(false),
525   mNeedToEmitResourceReady(false),
526   mDispatchKeyEvents(true)
527 {
528   Dali::Accessibility::Accessible::RegisterExternalAccessibleGetter(&ExternalAccessibleGetter);
529 }
530
531 Control::Impl::~Impl()
532 {
533   for(auto&& iter : mVisuals)
534   {
535     StopObservingVisual(iter->visual);
536   }
537
538   for(auto&& iter : mRemoveVisuals)
539   {
540     StopObservingVisual(iter->visual);
541   }
542
543   // All gesture detectors will be destroyed so no need to disconnect.
544   delete mStartingPinchScale;
545
546   if(mIdleCallback && Adaptor::IsAvailable())
547   {
548     // Removes the callback from the callback manager in case the control is destroyed before the callback is executed.
549     Adaptor::Get().RemoveIdle(mIdleCallback);
550   }
551 }
552
553 Control::Impl& Control::Impl::Get(Internal::Control& internalControl)
554 {
555   return *internalControl.mImpl;
556 }
557
558 const Control::Impl& Control::Impl::Get(const Internal::Control& internalControl)
559 {
560   return *internalControl.mImpl;
561 }
562
563 void Control::Impl::CheckHighlightedObjectGeometry()
564 {
565   auto accessible     = GetAccessibleObject();
566   auto lastPosition   = accessible->GetLastPosition();
567   auto accessibleRect = accessible->GetExtents(Dali::Accessibility::CoordinateType::WINDOW);
568   auto rect           = GetShowingGeometry(accessibleRect, accessible);
569
570   switch(mAccessibilityLastScreenRelativeMoveType)
571   {
572     case Dali::Accessibility::ScreenRelativeMoveType::OUTSIDE:
573     {
574       if(IsShowingGeometryOnScreen(rect))
575       {
576         mAccessibilityLastScreenRelativeMoveType = Dali::Accessibility::ScreenRelativeMoveType::INSIDE;
577       }
578       break;
579     }
580     case Dali::Accessibility::ScreenRelativeMoveType::INSIDE:
581     {
582       if(rect.width < 0 && accessibleRect.x != lastPosition.x)
583       {
584         mAccessibilityLastScreenRelativeMoveType = (accessibleRect.x < lastPosition.x) ? Dali::Accessibility::ScreenRelativeMoveType::OUTGOING_TOP_LEFT : Dali::Accessibility::ScreenRelativeMoveType::OUTGOING_BOTTOM_RIGHT;
585       }
586       if(rect.height < 0 && accessibleRect.y != lastPosition.y)
587       {
588         mAccessibilityLastScreenRelativeMoveType = (accessibleRect.y < lastPosition.y) ? Dali::Accessibility::ScreenRelativeMoveType::OUTGOING_TOP_LEFT : Dali::Accessibility::ScreenRelativeMoveType::OUTGOING_BOTTOM_RIGHT;
589       }
590       // notify AT-clients on outgoing moves only
591       if(mAccessibilityLastScreenRelativeMoveType != Dali::Accessibility::ScreenRelativeMoveType::INSIDE)
592       {
593         accessible->EmitMovedOutOfScreen(mAccessibilityLastScreenRelativeMoveType);
594       }
595       break;
596     }
597     case Dali::Accessibility::ScreenRelativeMoveType::OUTGOING_TOP_LEFT:
598     case Dali::Accessibility::ScreenRelativeMoveType::OUTGOING_BOTTOM_RIGHT:
599     {
600       if(IsShowingGeometryOnScreen(rect))
601       {
602         mAccessibilityLastScreenRelativeMoveType = Dali::Accessibility::ScreenRelativeMoveType::INSIDE;
603       }
604       else
605       {
606         mAccessibilityLastScreenRelativeMoveType = Dali::Accessibility::ScreenRelativeMoveType::OUTSIDE;
607       }
608       break;
609     }
610     default:
611     {
612       break;
613     }
614   }
615
616   accessible->SetLastPosition(Vector2(accessibleRect.x, accessibleRect.y));
617 }
618
619 void Control::Impl::RegisterAccessibilityPositionPropertyNotification()
620 {
621   if(mIsAccessibilityPositionPropertyNotificationSet)
622   {
623     return;
624   }
625   // set default value until first move of object is detected
626   mAccessibilityLastScreenRelativeMoveType = Dali::Accessibility::ScreenRelativeMoveType::OUTSIDE;
627   // recalculate mAccessibilityLastScreenRelativeMoveType accordingly to the initial position
628   CheckHighlightedObjectGeometry();
629   mAccessibilityPositionNotification = mControlImpl.Self().AddPropertyNotification(Actor::Property::WORLD_POSITION, StepCondition(1.0f, 1.0f));
630   mAccessibilityPositionNotification.SetNotifyMode(PropertyNotification::NOTIFY_ON_CHANGED);
631   mAccessibilityPositionNotification.NotifySignal().Connect(this, [this](PropertyNotification&) { CheckHighlightedObjectGeometry(); });
632   mIsAccessibilityPositionPropertyNotificationSet = true;
633 }
634
635 void Control::Impl::UnregisterAccessibilityPositionPropertyNotification()
636 {
637   mControlImpl.Self().RemovePropertyNotification(mAccessibilityPositionNotification);
638   mIsAccessibilityPositionPropertyNotificationSet = false;
639 }
640
641 // Gesture Detection Methods
642 void Control::Impl::PinchDetected(Actor actor, const PinchGesture& pinch)
643 {
644   mControlImpl.OnPinch(pinch);
645 }
646
647 void Control::Impl::PanDetected(Actor actor, const PanGesture& pan)
648 {
649   mControlImpl.OnPan(pan);
650 }
651
652 void Control::Impl::TapDetected(Actor actor, const TapGesture& tap)
653 {
654   mControlImpl.OnTap(tap);
655 }
656
657 void Control::Impl::LongPressDetected(Actor actor, const LongPressGesture& longPress)
658 {
659   mControlImpl.OnLongPress(longPress);
660 }
661
662 void Control::Impl::RegisterVisual(Property::Index index, Toolkit::Visual::Base& visual)
663 {
664   RegisterVisual(index, visual, VisualState::ENABLED, DepthIndexValue::NOT_SET);
665 }
666
667 void Control::Impl::RegisterVisual(Property::Index index, Toolkit::Visual::Base& visual, int depthIndex)
668 {
669   RegisterVisual(index, visual, VisualState::ENABLED, DepthIndexValue::SET, depthIndex);
670 }
671
672 void Control::Impl::RegisterVisual(Property::Index index, Toolkit::Visual::Base& visual, bool enabled)
673 {
674   RegisterVisual(index, visual, (enabled ? VisualState::ENABLED : VisualState::DISABLED), DepthIndexValue::NOT_SET);
675 }
676
677 void Control::Impl::RegisterVisual(Property::Index index, Toolkit::Visual::Base& visual, bool enabled, int depthIndex)
678 {
679   RegisterVisual(index, visual, (enabled ? VisualState::ENABLED : VisualState::DISABLED), DepthIndexValue::SET, depthIndex);
680 }
681
682 void Control::Impl::RegisterVisual(Property::Index index, Toolkit::Visual::Base& visual, VisualState::Type enabled, DepthIndexValue::Type depthIndexValueSet, int depthIndex)
683 {
684   DALI_LOG_INFO(gLogFilter, Debug::Concise, "RegisterVisual:%d \n", index);
685
686   bool  visualReplaced(false);
687   Actor self = mControlImpl.Self();
688
689   // Set the depth index, if not set by caller this will be either the current visual depth, max depth of all visuals
690   // or zero.
691   int requiredDepthIndex = visual.GetDepthIndex();
692
693   if(depthIndexValueSet == DepthIndexValue::SET)
694   {
695     requiredDepthIndex = depthIndex;
696   }
697
698   // Visual replacement, existing visual should only be removed from stage when replacement ready.
699   if(!mVisuals.Empty())
700   {
701     RegisteredVisualContainer::Iterator registeredVisualsiter;
702     // Check if visual (index) is already registered, this is the current visual.
703     if(FindVisual(index, mVisuals, registeredVisualsiter))
704     {
705       Toolkit::Visual::Base& currentRegisteredVisual = (*registeredVisualsiter)->visual;
706       if(currentRegisteredVisual)
707       {
708         // Store current visual depth index as may need to set the replacement visual to same depth
709         const int currentDepthIndex = (*registeredVisualsiter)->visual.GetDepthIndex();
710
711         // No longer required to know if the replaced visual's resources are ready
712         StopObservingVisual(currentRegisteredVisual);
713
714         // If control staged and visual enabled then visuals will be swapped once ready
715         if(self.GetProperty<bool>(Actor::Property::CONNECTED_TO_SCENE) && enabled)
716         {
717           // Check if visual is currently in the process of being replaced ( is in removal container )
718           RegisteredVisualContainer::Iterator visualQueuedForRemoval;
719           if(FindVisual(index, mRemoveVisuals, visualQueuedForRemoval))
720           {
721             // Visual with same index is already in removal container so current visual pending
722             // Only the the last requested visual will be displayed so remove current visual which is staged but not ready.
723             Toolkit::GetImplementation(currentRegisteredVisual).SetOffScene(self);
724             mVisuals.Erase(registeredVisualsiter);
725           }
726           else
727           {
728             // current visual not already in removal container so add now.
729             DALI_LOG_INFO(gLogFilter, Debug::Verbose, "RegisterVisual Move current registered visual to removal Queue: %d \n", index);
730             MoveVisual(registeredVisualsiter, mVisuals, mRemoveVisuals);
731           }
732         }
733         else
734         {
735           // Control not staged or visual disabled so can just erase from registered visuals and new visual will be added later.
736           mVisuals.Erase(registeredVisualsiter);
737         }
738
739         // 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
740         if((depthIndexValueSet == DepthIndexValue::NOT_SET) &&
741            (visual.GetDepthIndex() == 0))
742         {
743           requiredDepthIndex = currentDepthIndex;
744         }
745       }
746
747       visualReplaced = true;
748     }
749   }
750
751   // If not set, set the name of the visual to the same name as the control's property.
752   // ( If the control has been type registered )
753   if(visual.GetName().empty())
754   {
755     // returns empty string if index is not found as long as index is not -1
756     std::string visualName = self.GetPropertyName(index);
757     if(!visualName.empty())
758     {
759       DALI_LOG_INFO(gLogFilter, Debug::Concise, "Setting visual name for property %d to %s\n", index, visualName.c_str());
760       visual.SetName(visualName);
761     }
762   }
763
764   if(!visualReplaced) // New registration entry
765   {
766     // 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
767     if((depthIndexValueSet == DepthIndexValue::NOT_SET) &&
768        (mVisuals.Size() > 0) &&
769        (visual.GetDepthIndex() == 0))
770     {
771       int maxDepthIndex = std::numeric_limits<int>::min();
772
773       RegisteredVisualContainer::ConstIterator       iter;
774       const RegisteredVisualContainer::ConstIterator endIter = mVisuals.End();
775       for(iter = mVisuals.Begin(); iter != endIter; iter++)
776       {
777         const int visualDepthIndex = (*iter)->visual.GetDepthIndex();
778         if(visualDepthIndex > maxDepthIndex)
779         {
780           maxDepthIndex = visualDepthIndex;
781         }
782       }
783       ++maxDepthIndex;                                 // Add one to the current maximum depth index so that our added visual appears on top
784       requiredDepthIndex = std::max(0, maxDepthIndex); // Start at zero if maxDepth index belongs to a background
785     }
786   }
787
788   if(visual)
789   {
790     // Set determined depth index
791     visual.SetDepthIndex(requiredDepthIndex);
792
793     // Monitor when the visual resources are ready
794     StartObservingVisual(visual);
795
796     DALI_LOG_INFO(gLogFilter, Debug::Concise, "New Visual registration index[%d] depth[%d]\n", index, requiredDepthIndex);
797     RegisteredVisual* newRegisteredVisual = new RegisteredVisual(index, visual, (enabled == VisualState::ENABLED ? true : false), (visualReplaced && enabled));
798     mVisuals.PushBack(newRegisteredVisual);
799
800     Internal::Visual::Base& visualImpl = Toolkit::GetImplementation(visual);
801     // Put on stage if enabled and the control is already on the stage
802     if((enabled == VisualState::ENABLED) && self.GetProperty<bool>(Actor::Property::CONNECTED_TO_SCENE))
803     {
804       visualImpl.SetOnScene(self);
805     }
806     else if(visualImpl.IsResourceReady()) // When not being staged, check if visual already 'ResourceReady' before it was Registered. ( Resource may have been loaded already )
807     {
808       ResourceReady(visualImpl);
809     }
810   }
811
812   DALI_LOG_INFO(gLogFilter, Debug::Verbose, "Control::RegisterVisual() Registered %s(%d), enabled:%s\n", visual.GetName().c_str(), index, enabled ? "true" : "false");
813 }
814
815 void Control::Impl::UnregisterVisual(Property::Index index)
816 {
817   RegisteredVisualContainer::Iterator iter;
818   if(FindVisual(index, mVisuals, iter))
819   {
820     // stop observing visual
821     StopObservingVisual((*iter)->visual);
822
823     Actor self(mControlImpl.Self());
824     Toolkit::GetImplementation((*iter)->visual).SetOffScene(self);
825     (*iter)->visual.Reset();
826     mVisuals.Erase(iter);
827   }
828
829   if(FindVisual(index, mRemoveVisuals, iter))
830   {
831     Actor self(mControlImpl.Self());
832     Toolkit::GetImplementation((*iter)->visual).SetOffScene(self);
833     (*iter)->pending = false;
834     (*iter)->visual.Reset();
835     mRemoveVisuals.Erase(iter);
836   }
837 }
838
839 Toolkit::Visual::Base Control::Impl::GetVisual(Property::Index index) const
840 {
841   RegisteredVisualContainer::Iterator iter;
842   if(FindVisual(index, mVisuals, iter))
843   {
844     return (*iter)->visual;
845   }
846
847   return Toolkit::Visual::Base();
848 }
849
850 void Control::Impl::EnableVisual(Property::Index index, bool enable)
851 {
852   DALI_LOG_INFO(gLogFilter, Debug::General, "Control::EnableVisual(%d, %s)\n", index, enable ? "T" : "F");
853
854   RegisteredVisualContainer::Iterator iter;
855   if(FindVisual(index, mVisuals, iter))
856   {
857     if((*iter)->enabled == enable)
858     {
859       DALI_LOG_INFO(gLogFilter, Debug::Verbose, "Control::EnableVisual Visual %s(%d) already %s\n", (*iter)->visual.GetName().c_str(), index, enable ? "enabled" : "disabled");
860       return;
861     }
862
863     (*iter)->enabled  = enable;
864     Actor parentActor = mControlImpl.Self();
865     if(mControlImpl.Self().GetProperty<bool>(Actor::Property::CONNECTED_TO_SCENE)) // If control not on Scene then Visual will be added when SceneConnection is called.
866     {
867       if(enable)
868       {
869         DALI_LOG_INFO(gLogFilter, Debug::Verbose, "Control::EnableVisual Setting %s(%d) on stage \n", (*iter)->visual.GetName().c_str(), index);
870         Toolkit::GetImplementation((*iter)->visual).SetOnScene(parentActor);
871       }
872       else
873       {
874         DALI_LOG_INFO(gLogFilter, Debug::Verbose, "Control::EnableVisual Setting %s(%d) off stage \n", (*iter)->visual.GetName().c_str(), index);
875         Toolkit::GetImplementation((*iter)->visual).SetOffScene(parentActor); // No need to call if control not staged.
876       }
877     }
878   }
879   else
880   {
881     DALI_LOG_WARNING("Control::EnableVisual(%d, %s) FAILED - NO SUCH VISUAL\n", index, enable ? "T" : "F");
882   }
883 }
884
885 bool Control::Impl::IsVisualEnabled(Property::Index index) const
886 {
887   RegisteredVisualContainer::Iterator iter;
888   if(FindVisual(index, mVisuals, iter))
889   {
890     return (*iter)->enabled;
891   }
892   return false;
893 }
894
895 void Control::Impl::StopObservingVisual(Toolkit::Visual::Base& visual)
896 {
897   Internal::Visual::Base& visualImpl = Toolkit::GetImplementation(visual);
898
899   // Stop observing the visual
900   visualImpl.RemoveEventObserver(*this);
901 }
902
903 void Control::Impl::StartObservingVisual(Toolkit::Visual::Base& visual)
904 {
905   Internal::Visual::Base& visualImpl = Toolkit::GetImplementation(visual);
906
907   // start observing the visual for events
908   visualImpl.AddEventObserver(*this);
909 }
910
911 // Called by a Visual when it's resource is ready
912 void Control::Impl::ResourceReady(Visual::Base& object)
913 {
914   DALI_LOG_INFO(gLogFilter, Debug::Verbose, "Control::Impl::ResourceReady() replacements pending[%d]\n", mRemoveVisuals.Count());
915
916   Actor self = mControlImpl.Self();
917
918   // A resource is ready, find resource in the registered visuals container and get its index
919   for(auto registeredIter = mVisuals.Begin(), end = mVisuals.End(); registeredIter != end; ++registeredIter)
920   {
921     Internal::Visual::Base& registeredVisualImpl = Toolkit::GetImplementation((*registeredIter)->visual);
922
923     if(&object == &registeredVisualImpl)
924     {
925       RegisteredVisualContainer::Iterator visualToRemoveIter;
926       // Find visual with the same index in the removal container
927       // Set if off stage as it's replacement is now ready.
928       // Remove if from removal list as now removed from stage.
929       // Set Pending flag on the ready visual to false as now ready.
930       if(FindVisual((*registeredIter)->index, mRemoveVisuals, visualToRemoveIter))
931       {
932         (*registeredIter)->pending = false;
933         Toolkit::GetImplementation((*visualToRemoveIter)->visual).SetOffScene(self);
934         mRemoveVisuals.Erase(visualToRemoveIter);
935       }
936       break;
937     }
938   }
939
940   // A visual is ready so control may need relayouting if staged
941   if(self.GetProperty<bool>(Actor::Property::CONNECTED_TO_SCENE))
942   {
943     mControlImpl.RelayoutRequest();
944   }
945
946   // Emit signal if all enabled visuals registered by the control are ready.
947   if(IsResourceReady())
948   {
949     // Reset the flag
950     mNeedToEmitResourceReady = false;
951
952     EmitResourceReadySignal();
953   }
954 }
955
956 void Control::Impl::NotifyVisualEvent(Visual::Base& object, Property::Index signalId)
957 {
958   for(auto registeredIter = mVisuals.Begin(), end = mVisuals.End(); registeredIter != end; ++registeredIter)
959   {
960     Internal::Visual::Base& registeredVisualImpl = Toolkit::GetImplementation((*registeredIter)->visual);
961     if(&object == &registeredVisualImpl)
962     {
963       Dali::Toolkit::Control handle(mControlImpl.GetOwner());
964       mVisualEventSignal.Emit(handle, (*registeredIter)->index, signalId);
965       break;
966     }
967   }
968 }
969
970 void Control::Impl::RelayoutRequest(Visual::Base& object)
971 {
972   mControlImpl.RelayoutRequest();
973 }
974
975 bool Control::Impl::IsResourceReady() const
976 {
977   // Iterate through and check all the enabled visuals are ready
978   for(auto visualIter = mVisuals.Begin();
979       visualIter != mVisuals.End();
980       ++visualIter)
981   {
982     const Toolkit::Visual::Base   visual     = (*visualIter)->visual;
983     const Internal::Visual::Base& visualImpl = Toolkit::GetImplementation(visual);
984
985     // one of the enabled visuals is not ready
986     if(!visualImpl.IsResourceReady() && (*visualIter)->enabled)
987     {
988       return false;
989     }
990   }
991   return true;
992 }
993
994 Toolkit::Visual::ResourceStatus Control::Impl::GetVisualResourceStatus(Property::Index index) const
995 {
996   RegisteredVisualContainer::Iterator iter;
997   if(FindVisual(index, mVisuals, iter))
998   {
999     const Toolkit::Visual::Base   visual     = (*iter)->visual;
1000     const Internal::Visual::Base& visualImpl = Toolkit::GetImplementation(visual);
1001     return visualImpl.GetResourceStatus();
1002   }
1003
1004   return Toolkit::Visual::ResourceStatus::PREPARING;
1005 }
1006
1007 void Control::Impl::AddTransitions(Dali::Animation&               animation,
1008                                    const Toolkit::TransitionData& handle,
1009                                    bool                           createAnimation)
1010 {
1011   // Setup a Transition from TransitionData.
1012   const Internal::TransitionData& transitionData = Toolkit::GetImplementation(handle);
1013   TransitionData::Iterator        end            = transitionData.End();
1014   for(TransitionData::Iterator iter = transitionData.Begin();
1015       iter != end;
1016       ++iter)
1017   {
1018     TransitionData::Animator* animator = (*iter);
1019
1020     Toolkit::Visual::Base visual = GetVisualByName(mVisuals, animator->objectName);
1021
1022     if(visual)
1023     {
1024 #if defined(DEBUG_ENABLED)
1025       Dali::TypeInfo  typeInfo;
1026       ControlWrapper* controlWrapperImpl = dynamic_cast<ControlWrapper*>(&mControlImpl);
1027       if(controlWrapperImpl)
1028       {
1029         typeInfo = controlWrapperImpl->GetTypeInfo();
1030       }
1031
1032       DALI_LOG_INFO(gLogFilter, Debug::Concise, "CreateTransition: Found %s visual for %s\n", visual.GetName().c_str(), typeInfo ? typeInfo.GetName().c_str() : "Unknown");
1033 #endif
1034       Internal::Visual::Base& visualImpl = Toolkit::GetImplementation(visual);
1035       visualImpl.AnimateProperty(animation, *animator);
1036     }
1037     else
1038     {
1039       DALI_LOG_INFO(gLogFilter, Debug::Concise, "CreateTransition: Could not find visual. Trying actors");
1040       // Otherwise, try any actor children of control (Including the control)
1041       Actor child = mControlImpl.Self().FindChildByName(animator->objectName);
1042       if(child)
1043       {
1044         Property::Index propertyIndex = child.GetPropertyIndex(animator->propertyKey);
1045         if(propertyIndex != Property::INVALID_INDEX)
1046         {
1047           if(animator->animate == false)
1048           {
1049             if(animator->targetValue.GetType() != Property::NONE)
1050             {
1051               child.SetProperty(propertyIndex, animator->targetValue);
1052             }
1053           }
1054           else // animate the property
1055           {
1056             if(animator->initialValue.GetType() != Property::NONE)
1057             {
1058               child.SetProperty(propertyIndex, animator->initialValue);
1059             }
1060
1061             if(createAnimation && !animation)
1062             {
1063               animation = Dali::Animation::New(0.1f);
1064             }
1065
1066             animation.AnimateTo(Property(child, propertyIndex),
1067                                 animator->targetValue,
1068                                 animator->alphaFunction,
1069                                 TimePeriod(animator->timePeriodDelay,
1070                                            animator->timePeriodDuration));
1071           }
1072         }
1073       }
1074     }
1075   }
1076 }
1077
1078 Dali::Animation Control::Impl::CreateTransition(const Toolkit::TransitionData& transitionData)
1079 {
1080   Dali::Animation transition;
1081
1082   if(transitionData.Count() > 0)
1083   {
1084     AddTransitions(transition, transitionData, true);
1085   }
1086   return transition;
1087 }
1088
1089 void Control::Impl::DoAction(Dali::Property::Index visualIndex, Dali::Property::Index actionId, const Dali::Property::Value attributes)
1090 {
1091   RegisteredVisualContainer::Iterator iter;
1092   if(FindVisual(visualIndex, mVisuals, iter))
1093   {
1094     Toolkit::GetImplementation((*iter)->visual).DoAction(actionId, attributes);
1095   }
1096 }
1097
1098 void Control::Impl::DoActionExtension(Dali::Property::Index visualIndex, Dali::Property::Index actionId, Dali::Any attributes)
1099 {
1100   RegisteredVisualContainer::Iterator iter;
1101   if(FindVisual(visualIndex, mVisuals, iter))
1102   {
1103     Toolkit::GetImplementation((*iter)->visual).DoActionExtension(actionId, attributes);
1104   }
1105 }
1106
1107 void Control::Impl::AppendAccessibilityAttribute(const std::string& key, const std::string value)
1108 {
1109   Property::Value* checkedValue = mAccessibilityAttributes.Find(key);
1110   if(checkedValue)
1111   {
1112     mAccessibilityAttributes[key] = Property::Value(value);
1113   }
1114   else
1115   {
1116     mAccessibilityAttributes.Insert(key, value);
1117   }
1118 }
1119
1120 void Control::Impl::SetProperty(BaseObject* object, Property::Index index, const Property::Value& value)
1121 {
1122   Toolkit::Control control = Toolkit::Control::DownCast(BaseHandle(object));
1123
1124   if(control)
1125   {
1126     Control& controlImpl(GetImplementation(control));
1127
1128     switch(index)
1129     {
1130       case Toolkit::Control::Property::STYLE_NAME:
1131       {
1132         controlImpl.SetStyleName(value.Get<std::string>());
1133         break;
1134       }
1135
1136       case Toolkit::DevelControl::Property::STATE:
1137       {
1138         bool                   withTransitions = true;
1139         const Property::Value* valuePtr        = &value;
1140         const Property::Map*   map             = value.GetMap();
1141         if(map)
1142         {
1143           Property::Value* value2 = map->Find("withTransitions");
1144           if(value2)
1145           {
1146             withTransitions = value2->Get<bool>();
1147           }
1148
1149           valuePtr = map->Find("state");
1150         }
1151
1152         if(valuePtr)
1153         {
1154           Toolkit::DevelControl::State state(controlImpl.mImpl->mState);
1155           if(Scripting::GetEnumerationProperty<Toolkit::DevelControl::State>(*valuePtr, ControlStateTable, ControlStateTableCount, state))
1156           {
1157             controlImpl.mImpl->SetState(state, withTransitions);
1158           }
1159         }
1160       }
1161       break;
1162
1163       case Toolkit::DevelControl::Property::SUB_STATE:
1164       {
1165         std::string subState;
1166         if(value.Get(subState))
1167         {
1168           controlImpl.mImpl->SetSubState(subState);
1169         }
1170       }
1171       break;
1172
1173       case Toolkit::DevelControl::Property::LEFT_FOCUSABLE_ACTOR_ID:
1174       {
1175         int focusId;
1176         if(value.Get(focusId))
1177         {
1178           controlImpl.mImpl->mLeftFocusableActorId = focusId;
1179         }
1180       }
1181       break;
1182
1183       case Toolkit::DevelControl::Property::RIGHT_FOCUSABLE_ACTOR_ID:
1184       {
1185         int focusId;
1186         if(value.Get(focusId))
1187         {
1188           controlImpl.mImpl->mRightFocusableActorId = focusId;
1189         }
1190       }
1191       break;
1192
1193       case Toolkit::DevelControl::Property::UP_FOCUSABLE_ACTOR_ID:
1194       {
1195         int focusId;
1196         if(value.Get(focusId))
1197         {
1198           controlImpl.mImpl->mUpFocusableActorId = focusId;
1199         }
1200       }
1201       break;
1202
1203       case Toolkit::DevelControl::Property::DOWN_FOCUSABLE_ACTOR_ID:
1204       {
1205         int focusId;
1206         if(value.Get(focusId))
1207         {
1208           controlImpl.mImpl->mDownFocusableActorId = focusId;
1209         }
1210       }
1211       break;
1212
1213       case Toolkit::Control::Property::KEY_INPUT_FOCUS:
1214       {
1215         if(value.Get<bool>())
1216         {
1217           controlImpl.SetKeyInputFocus();
1218         }
1219         else
1220         {
1221           controlImpl.ClearKeyInputFocus();
1222         }
1223         break;
1224       }
1225
1226       case Toolkit::Control::Property::BACKGROUND:
1227       {
1228         std::string          url;
1229         Vector4              color;
1230         const Property::Map* map = value.GetMap();
1231         if(map && !map->Empty())
1232         {
1233           controlImpl.SetBackground(*map);
1234         }
1235         else if(value.Get(url))
1236         {
1237           // don't know the size to load
1238           Toolkit::Visual::Base visual = Toolkit::VisualFactory::Get().CreateVisual(url, ImageDimensions());
1239           if(visual)
1240           {
1241             controlImpl.mImpl->RegisterVisual(Toolkit::Control::Property::BACKGROUND, visual, DepthIndex::BACKGROUND);
1242           }
1243         }
1244         else if(value.Get(color))
1245         {
1246           controlImpl.SetBackgroundColor(color);
1247         }
1248         else
1249         {
1250           // The background is an empty property map, so we should clear the background
1251           controlImpl.ClearBackground();
1252         }
1253         break;
1254       }
1255
1256       case Toolkit::Control::Property::MARGIN:
1257       {
1258         Extents margin;
1259         if(value.Get(margin))
1260         {
1261           controlImpl.mImpl->SetMargin(margin);
1262         }
1263         break;
1264       }
1265
1266       case Toolkit::Control::Property::PADDING:
1267       {
1268         Extents padding;
1269         if(value.Get(padding))
1270         {
1271           controlImpl.mImpl->SetPadding(padding);
1272         }
1273         break;
1274       }
1275
1276       case Toolkit::DevelControl::Property::TOOLTIP:
1277       {
1278         TooltipPtr& tooltipPtr = controlImpl.mImpl->mTooltip;
1279         if(!tooltipPtr)
1280         {
1281           tooltipPtr = Tooltip::New(control);
1282         }
1283         tooltipPtr->SetProperties(value);
1284         break;
1285       }
1286
1287       case Toolkit::DevelControl::Property::SHADOW:
1288       {
1289         const Property::Map* map = value.GetMap();
1290         if(map && !map->Empty())
1291         {
1292           controlImpl.mImpl->SetShadow(*map);
1293         }
1294         else
1295         {
1296           // The shadow is an empty property map, so we should clear the shadow
1297           controlImpl.mImpl->ClearShadow();
1298         }
1299         break;
1300       }
1301
1302       case Toolkit::DevelControl::Property::ACCESSIBILITY_NAME:
1303       {
1304         std::string name;
1305         if(value.Get(name))
1306         {
1307           controlImpl.mImpl->mAccessibilityName = name;
1308         }
1309         break;
1310       }
1311
1312       case Toolkit::DevelControl::Property::ACCESSIBILITY_DESCRIPTION:
1313       {
1314         std::string text;
1315         if(value.Get(text))
1316         {
1317           controlImpl.mImpl->mAccessibilityDescription = text;
1318         }
1319         break;
1320       }
1321
1322       case Toolkit::DevelControl::Property::ACCESSIBILITY_TRANSLATION_DOMAIN:
1323       {
1324         std::string text;
1325         if(value.Get(text))
1326         {
1327           controlImpl.mImpl->mAccessibilityTranslationDomain = text;
1328         }
1329         break;
1330       }
1331
1332       case Toolkit::DevelControl::Property::ACCESSIBILITY_ROLE:
1333       {
1334         Dali::Accessibility::Role role;
1335         if(value.Get(role))
1336         {
1337           controlImpl.mImpl->mAccessibilityRole = role;
1338         }
1339         break;
1340       }
1341
1342       case Toolkit::DevelControl::Property::ACCESSIBILITY_HIGHLIGHTABLE:
1343       {
1344         bool highlightable;
1345         if(value.Get(highlightable))
1346         {
1347           controlImpl.mImpl->mAccessibilityHighlightable = highlightable;
1348         }
1349         break;
1350       }
1351
1352       case Toolkit::DevelControl::Property::ACCESSIBILITY_ATTRIBUTES:
1353       {
1354         const Property::Map* map = value.GetMap();
1355         if(map && !map->Empty())
1356         {
1357           controlImpl.mImpl->mAccessibilityAttributes = *map;
1358         }
1359         break;
1360       }
1361
1362       case Toolkit::DevelControl::Property::DISPATCH_KEY_EVENTS:
1363       {
1364         bool dispatch;
1365         if(value.Get(dispatch))
1366         {
1367           controlImpl.mImpl->mDispatchKeyEvents = dispatch;
1368         }
1369         break;
1370       }
1371
1372       case Toolkit::DevelControl::Property::ACCESSIBILITY_HIDDEN:
1373       {
1374         bool hidden;
1375         if(value.Get(hidden))
1376         {
1377           controlImpl.mImpl->mAccessibilityHidden = hidden;
1378
1379           auto* accessible = controlImpl.GetAccessibleObject();
1380           auto* parent     = dynamic_cast<Dali::Accessibility::ActorAccessible*>(accessible->GetParent());
1381           if(parent)
1382           {
1383             parent->OnChildrenChanged();
1384           }
1385         }
1386         break;
1387       }
1388       case Toolkit::DevelControl::Property::CLOCKWISE_FOCUSABLE_ACTOR_ID:
1389       {
1390         int focusId;
1391         if(value.Get(focusId))
1392         {
1393           controlImpl.mImpl->mClockwiseFocusableActorId = focusId;
1394         }
1395         break;
1396       }
1397       case Toolkit::DevelControl::Property::COUNTER_CLOCKWISE_FOCUSABLE_ACTOR_ID:
1398       {
1399         int focusId;
1400         if(value.Get(focusId))
1401         {
1402           controlImpl.mImpl->mCounterClockwiseFocusableActorId = focusId;
1403         }
1404         break;
1405       }
1406     }
1407   }
1408 }
1409
1410 Property::Value Control::Impl::GetProperty(BaseObject* object, Property::Index index)
1411 {
1412   Property::Value value;
1413
1414   Toolkit::Control control = Toolkit::Control::DownCast(BaseHandle(object));
1415
1416   if(control)
1417   {
1418     Control& controlImpl(GetImplementation(control));
1419
1420     switch(index)
1421     {
1422       case Toolkit::Control::Property::STYLE_NAME:
1423       {
1424         value = controlImpl.GetStyleName();
1425         break;
1426       }
1427
1428       case Toolkit::DevelControl::Property::STATE:
1429       {
1430         value = controlImpl.mImpl->mState;
1431         break;
1432       }
1433
1434       case Toolkit::DevelControl::Property::SUB_STATE:
1435       {
1436         value = controlImpl.mImpl->mSubStateName;
1437         break;
1438       }
1439
1440       case Toolkit::DevelControl::Property::LEFT_FOCUSABLE_ACTOR_ID:
1441       {
1442         value = controlImpl.mImpl->mLeftFocusableActorId;
1443         break;
1444       }
1445
1446       case Toolkit::DevelControl::Property::RIGHT_FOCUSABLE_ACTOR_ID:
1447       {
1448         value = controlImpl.mImpl->mRightFocusableActorId;
1449         break;
1450       }
1451
1452       case Toolkit::DevelControl::Property::UP_FOCUSABLE_ACTOR_ID:
1453       {
1454         value = controlImpl.mImpl->mUpFocusableActorId;
1455         break;
1456       }
1457
1458       case Toolkit::DevelControl::Property::DOWN_FOCUSABLE_ACTOR_ID:
1459       {
1460         value = controlImpl.mImpl->mDownFocusableActorId;
1461         break;
1462       }
1463
1464       case Toolkit::Control::Property::KEY_INPUT_FOCUS:
1465       {
1466         value = controlImpl.HasKeyInputFocus();
1467         break;
1468       }
1469
1470       case Toolkit::Control::Property::BACKGROUND:
1471       {
1472         Property::Map         map;
1473         Toolkit::Visual::Base visual = controlImpl.mImpl->GetVisual(Toolkit::Control::Property::BACKGROUND);
1474         if(visual)
1475         {
1476           visual.CreatePropertyMap(map);
1477         }
1478
1479         value = map;
1480         break;
1481       }
1482
1483       case Toolkit::Control::Property::MARGIN:
1484       {
1485         value = controlImpl.mImpl->GetMargin();
1486         break;
1487       }
1488
1489       case Toolkit::Control::Property::PADDING:
1490       {
1491         value = controlImpl.mImpl->GetPadding();
1492         break;
1493       }
1494
1495       case Toolkit::DevelControl::Property::TOOLTIP:
1496       {
1497         Property::Map map;
1498         if(controlImpl.mImpl->mTooltip)
1499         {
1500           controlImpl.mImpl->mTooltip->CreatePropertyMap(map);
1501         }
1502         value = map;
1503         break;
1504       }
1505
1506       case Toolkit::DevelControl::Property::SHADOW:
1507       {
1508         Property::Map         map;
1509         Toolkit::Visual::Base visual = controlImpl.mImpl->GetVisual(Toolkit::DevelControl::Property::SHADOW);
1510         if(visual)
1511         {
1512           visual.CreatePropertyMap(map);
1513         }
1514
1515         value = map;
1516         break;
1517       }
1518
1519       case Toolkit::DevelControl::Property::ACCESSIBILITY_NAME:
1520       {
1521         value = controlImpl.mImpl->mAccessibilityName;
1522         break;
1523       }
1524
1525       case Toolkit::DevelControl::Property::ACCESSIBILITY_DESCRIPTION:
1526       {
1527         value = controlImpl.mImpl->mAccessibilityDescription;
1528         break;
1529       }
1530
1531       case Toolkit::DevelControl::Property::ACCESSIBILITY_TRANSLATION_DOMAIN:
1532       {
1533         value = controlImpl.mImpl->mAccessibilityTranslationDomain;
1534         break;
1535       }
1536
1537       case Toolkit::DevelControl::Property::ACCESSIBILITY_ROLE:
1538       {
1539         value = Property::Value(controlImpl.mImpl->mAccessibilityRole);
1540         break;
1541       }
1542
1543       case Toolkit::DevelControl::Property::ACCESSIBILITY_HIGHLIGHTABLE:
1544       {
1545         value = controlImpl.mImpl->mAccessibilityHighlightable;
1546         break;
1547       }
1548
1549       case Toolkit::DevelControl::Property::ACCESSIBILITY_ATTRIBUTES:
1550       {
1551         value = controlImpl.mImpl->mAccessibilityAttributes;
1552         break;
1553       }
1554
1555       case Toolkit::DevelControl::Property::DISPATCH_KEY_EVENTS:
1556       {
1557         value = controlImpl.mImpl->mDispatchKeyEvents;
1558         break;
1559       }
1560
1561       case Toolkit::DevelControl::Property::ACCESSIBILITY_HIDDEN:
1562       {
1563         value = controlImpl.mImpl->mAccessibilityHidden;
1564         break;
1565       }
1566
1567       case Toolkit::DevelControl::Property::CLOCKWISE_FOCUSABLE_ACTOR_ID:
1568       {
1569         value = controlImpl.mImpl->mClockwiseFocusableActorId;
1570         break;
1571       }
1572
1573       case Toolkit::DevelControl::Property::COUNTER_CLOCKWISE_FOCUSABLE_ACTOR_ID:
1574       {
1575         value = controlImpl.mImpl->mCounterClockwiseFocusableActorId;
1576         break;
1577       }
1578     }
1579   }
1580
1581   return value;
1582 }
1583
1584 void Control::Impl::RemoveAccessibilityAttribute(const std::string& key)
1585 {
1586   Property::Value* value = mAccessibilityAttributes.Find(key);
1587   if(value)
1588   {
1589     mAccessibilityAttributes[key] = Property::Value();
1590   }
1591 }
1592
1593 void Control::Impl::ClearAccessibilityAttributes()
1594 {
1595   mAccessibilityAttributes.Clear();
1596 }
1597
1598 void Control::Impl::SetAccessibilityReadingInfoType(const Dali::Accessibility::ReadingInfoTypes types)
1599 {
1600   std::string value{};
1601   if(types[Dali::Accessibility::ReadingInfoType::NAME])
1602   {
1603     value += READING_INFO_TYPE_NAME;
1604   }
1605   if(types[Dali::Accessibility::ReadingInfoType::ROLE])
1606   {
1607     if(!value.empty())
1608     {
1609       value += READING_INFO_TYPE_SEPARATOR;
1610     }
1611     value += READING_INFO_TYPE_ROLE;
1612   }
1613   if(types[Dali::Accessibility::ReadingInfoType::DESCRIPTION])
1614   {
1615     if(!value.empty())
1616     {
1617       value += READING_INFO_TYPE_SEPARATOR;
1618     }
1619     value += READING_INFO_TYPE_DESCRIPTION;
1620   }
1621   if(types[Dali::Accessibility::ReadingInfoType::STATE])
1622   {
1623     if(!value.empty())
1624     {
1625       value += READING_INFO_TYPE_SEPARATOR;
1626     }
1627     value += READING_INFO_TYPE_STATE;
1628   }
1629   AppendAccessibilityAttribute(READING_INFO_TYPE_ATTRIBUTE_NAME, value);
1630 }
1631
1632 Dali::Accessibility::ReadingInfoTypes Control::Impl::GetAccessibilityReadingInfoType() const
1633 {
1634   std::string value{};
1635   auto        place = mAccessibilityAttributes.Find(READING_INFO_TYPE_ATTRIBUTE_NAME);
1636   if(place)
1637   {
1638     place->Get(value);
1639   }
1640   else
1641   {
1642     Dali::Accessibility::ReadingInfoTypes types;
1643     types[Dali::Accessibility::ReadingInfoType::NAME]        = true;
1644     types[Dali::Accessibility::ReadingInfoType::ROLE]        = true;
1645     types[Dali::Accessibility::ReadingInfoType::DESCRIPTION] = true;
1646     types[Dali::Accessibility::ReadingInfoType::STATE]       = true;
1647     return types;
1648   }
1649
1650   if(value.empty())
1651   {
1652     return {};
1653   }
1654
1655   Dali::Accessibility::ReadingInfoTypes types;
1656
1657   if(value.find(READING_INFO_TYPE_NAME) != std::string::npos)
1658   {
1659     types[Dali::Accessibility::ReadingInfoType::NAME] = true;
1660   }
1661   if(value.find(READING_INFO_TYPE_ROLE) != std::string::npos)
1662   {
1663     types[Dali::Accessibility::ReadingInfoType::ROLE] = true;
1664   }
1665   if(value.find(READING_INFO_TYPE_DESCRIPTION) != std::string::npos)
1666   {
1667     types[Dali::Accessibility::ReadingInfoType::DESCRIPTION] = true;
1668   }
1669   if(value.find(READING_INFO_TYPE_STATE) != std::string::npos)
1670   {
1671     types[Dali::Accessibility::ReadingInfoType::STATE] = true;
1672   }
1673
1674   return types;
1675 }
1676
1677 void Control::Impl::CopyInstancedProperties(RegisteredVisualContainer& visuals, Dictionary<Property::Map>& instancedProperties)
1678 {
1679   for(RegisteredVisualContainer::Iterator iter = visuals.Begin(); iter != visuals.End(); iter++)
1680   {
1681     if((*iter)->visual)
1682     {
1683       Property::Map instanceMap;
1684       Toolkit::GetImplementation((*iter)->visual).CreateInstancePropertyMap(instanceMap);
1685       instancedProperties.Add((*iter)->visual.GetName(), instanceMap);
1686     }
1687   }
1688 }
1689
1690 void Control::Impl::RemoveVisual(RegisteredVisualContainer& visuals, const std::string& visualName)
1691 {
1692   Actor self(mControlImpl.Self());
1693
1694   for(RegisteredVisualContainer::Iterator visualIter = visuals.Begin();
1695       visualIter != visuals.End();
1696       ++visualIter)
1697   {
1698     Toolkit::Visual::Base visual = (*visualIter)->visual;
1699     if(visual && visual.GetName() == visualName)
1700     {
1701       Toolkit::GetImplementation(visual).SetOffScene(self);
1702       (*visualIter)->visual.Reset();
1703       visuals.Erase(visualIter);
1704       break;
1705     }
1706   }
1707 }
1708
1709 void Control::Impl::RemoveVisuals(RegisteredVisualContainer& visuals, DictionaryKeys& removeVisuals)
1710 {
1711   Actor self(mControlImpl.Self());
1712   for(DictionaryKeys::iterator iter = removeVisuals.begin(); iter != removeVisuals.end(); ++iter)
1713   {
1714     const std::string visualName = *iter;
1715     RemoveVisual(visuals, visualName);
1716   }
1717 }
1718
1719 void Control::Impl::RecreateChangedVisuals(Dictionary<Property::Map>& stateVisualsToChange,
1720                                            Dictionary<Property::Map>& instancedProperties)
1721 {
1722   Dali::CustomActor handle(mControlImpl.GetOwner());
1723   for(Dictionary<Property::Map>::iterator iter = stateVisualsToChange.Begin();
1724       iter != stateVisualsToChange.End();
1725       ++iter)
1726   {
1727     const std::string&   visualName = (*iter).key;
1728     const Property::Map& toMap      = (*iter).entry;
1729
1730     Actor                               self = mControlImpl.Self();
1731     RegisteredVisualContainer::Iterator registeredVisualsiter;
1732     // Check if visual (visualName) is already registered, this is the current visual.
1733     if(FindVisual(visualName, mVisuals, registeredVisualsiter))
1734     {
1735       Toolkit::Visual::Base& visual = (*registeredVisualsiter)->visual;
1736       if(visual)
1737       {
1738         // No longer required to know if the replaced visual's resources are ready
1739         StopObservingVisual(visual);
1740
1741         // If control staged then visuals will be swapped once ready
1742         if(self.GetProperty<bool>(Actor::Property::CONNECTED_TO_SCENE))
1743         {
1744           // Check if visual is currently in the process of being replaced ( is in removal container )
1745           RegisteredVisualContainer::Iterator visualQueuedForRemoval;
1746           if(FindVisual(visualName, mRemoveVisuals, visualQueuedForRemoval))
1747           {
1748             // Visual with same visual name is already in removal container so current visual pending
1749             // Only the the last requested visual will be displayed so remove current visual which is staged but not ready.
1750             Toolkit::GetImplementation(visual).SetOffScene(self);
1751             (*registeredVisualsiter)->visual.Reset();
1752             mVisuals.Erase(registeredVisualsiter);
1753           }
1754           else
1755           {
1756             // current visual not already in removal container so add now.
1757             DALI_LOG_INFO(gLogFilter, Debug::Verbose, "RegisterVisual Move current registered visual to removal Queue: %s \n", visualName.c_str());
1758             MoveVisual(registeredVisualsiter, mVisuals, mRemoveVisuals);
1759           }
1760         }
1761         else
1762         {
1763           // Control not staged or visual disabled so can just erase from registered visuals and new visual will be added later.
1764           (*registeredVisualsiter)->visual.Reset();
1765           mVisuals.Erase(registeredVisualsiter);
1766         }
1767       }
1768
1769       const Property::Map* instancedMap = instancedProperties.FindConst(visualName);
1770       Style::ApplyVisual(handle, visualName, toMap, instancedMap);
1771     }
1772   }
1773 }
1774
1775 void Control::Impl::ReplaceStateVisualsAndProperties(const StylePtr oldState, const StylePtr newState, const std::string& subState)
1776 {
1777   // Collect all old visual names
1778   DictionaryKeys stateVisualsToRemove;
1779   if(oldState)
1780   {
1781     oldState->visuals.GetKeys(stateVisualsToRemove);
1782     if(!subState.empty())
1783     {
1784       const StylePtr* oldSubState = oldState->subStates.FindConst(subState);
1785       if(oldSubState)
1786       {
1787         DictionaryKeys subStateVisualsToRemove;
1788         (*oldSubState)->visuals.GetKeys(subStateVisualsToRemove);
1789         Merge(stateVisualsToRemove, subStateVisualsToRemove);
1790       }
1791     }
1792   }
1793
1794   // Collect all new visual properties
1795   Dictionary<Property::Map> stateVisualsToAdd;
1796   if(newState)
1797   {
1798     stateVisualsToAdd = newState->visuals;
1799     if(!subState.empty())
1800     {
1801       const StylePtr* newSubState = newState->subStates.FindConst(subState);
1802       if(newSubState)
1803       {
1804         stateVisualsToAdd.Merge((*newSubState)->visuals);
1805       }
1806     }
1807   }
1808
1809   // If a name is in both add/remove, move it to change list.
1810   Dictionary<Property::Map> stateVisualsToChange;
1811   FindChangableVisuals(stateVisualsToAdd, stateVisualsToChange, stateVisualsToRemove);
1812
1813   // Copy instanced properties (e.g. text label) of current visuals
1814   Dictionary<Property::Map> instancedProperties;
1815   CopyInstancedProperties(mVisuals, instancedProperties);
1816
1817   // For each visual in remove list, remove from mVisuals
1818   RemoveVisuals(mVisuals, stateVisualsToRemove);
1819
1820   // For each visual in add list, create and add to mVisuals
1821   Dali::CustomActor handle(mControlImpl.GetOwner());
1822   Style::ApplyVisuals(handle, stateVisualsToAdd, instancedProperties);
1823
1824   // For each visual in change list, if it requires a new visual,
1825   // remove old visual, create and add to mVisuals
1826   RecreateChangedVisuals(stateVisualsToChange, instancedProperties);
1827 }
1828
1829 void Control::Impl::SetState(DevelControl::State newState, bool withTransitions)
1830 {
1831   DevelControl::State oldState = mState;
1832   Dali::CustomActor   handle(mControlImpl.GetOwner());
1833   DALI_LOG_INFO(gLogFilter, Debug::Concise, "Control::Impl::SetState: %s\n", (mState == DevelControl::NORMAL ? "NORMAL" : (mState == DevelControl::FOCUSED ? "FOCUSED" : (mState == DevelControl::DISABLED ? "DISABLED" : "NONE"))));
1834
1835   if(mState != newState)
1836   {
1837     // If mState was Disabled, and new state is Focused, should probably
1838     // store that fact, e.g. in another property that FocusManager can access.
1839     mState = newState;
1840
1841     // Trigger state change and transitions
1842     // Apply new style, if stylemanager is available
1843     Toolkit::StyleManager styleManager = Toolkit::StyleManager::Get();
1844     if(styleManager)
1845     {
1846       const StylePtr stylePtr = GetImpl(styleManager).GetRecordedStyle(Toolkit::Control(mControlImpl.GetOwner()));
1847
1848       if(stylePtr)
1849       {
1850         std::string oldStateName = Scripting::GetEnumerationName<Toolkit::DevelControl::State>(oldState, ControlStateTable, ControlStateTableCount);
1851         std::string newStateName = Scripting::GetEnumerationName<Toolkit::DevelControl::State>(newState, ControlStateTable, ControlStateTableCount);
1852
1853         const StylePtr* newStateStyle = stylePtr->subStates.Find(newStateName);
1854         const StylePtr* oldStateStyle = stylePtr->subStates.Find(oldStateName);
1855         if(oldStateStyle && newStateStyle)
1856         {
1857           // Only change if both state styles exist
1858           ReplaceStateVisualsAndProperties(*oldStateStyle, *newStateStyle, mSubStateName);
1859         }
1860       }
1861     }
1862   }
1863 }
1864
1865 void Control::Impl::SetSubState(const std::string& subStateName, bool withTransitions)
1866 {
1867   if(mSubStateName != subStateName)
1868   {
1869     // Get existing sub-state visuals, and unregister them
1870     Dali::CustomActor handle(mControlImpl.GetOwner());
1871
1872     Toolkit::StyleManager styleManager = Toolkit::StyleManager::Get();
1873     if(styleManager)
1874     {
1875       const StylePtr stylePtr = GetImpl(styleManager).GetRecordedStyle(Toolkit::Control(mControlImpl.GetOwner()));
1876       if(stylePtr)
1877       {
1878         // Stringify state
1879         std::string stateName = Scripting::GetEnumerationName<Toolkit::DevelControl::State>(mState, ControlStateTable, ControlStateTableCount);
1880
1881         const StylePtr* state = stylePtr->subStates.Find(stateName);
1882         if(state)
1883         {
1884           StylePtr stateStyle(*state);
1885
1886           const StylePtr* newStateStyle = stateStyle->subStates.Find(subStateName);
1887           const StylePtr* oldStateStyle = stateStyle->subStates.Find(mSubStateName);
1888           if(oldStateStyle && newStateStyle)
1889           {
1890             std::string empty;
1891             ReplaceStateVisualsAndProperties(*oldStateStyle, *newStateStyle, empty);
1892           }
1893         }
1894       }
1895     }
1896
1897     mSubStateName = subStateName;
1898   }
1899 }
1900
1901 void Control::Impl::OnSceneDisconnection()
1902 {
1903   Actor self = mControlImpl.Self();
1904
1905   // Any visuals set for replacement but not yet ready should still be registered.
1906   // Reason: If a request was made to register a new visual but the control removed from scene before visual was ready
1907   // then when this control appears back on stage it should use that new visual.
1908
1909   // Iterate through all registered visuals and set off scene
1910   SetVisualsOffScene(mVisuals, self);
1911
1912   // Visuals pending replacement can now be taken out of the removal list and set off scene
1913   // Iterate through all replacement visuals and add to a move queue then set off scene
1914   for(auto removalIter = mRemoveVisuals.Begin(), end = mRemoveVisuals.End(); removalIter != end; removalIter++)
1915   {
1916     Toolkit::GetImplementation((*removalIter)->visual).SetOffScene(self);
1917   }
1918
1919   for(auto replacedIter = mVisuals.Begin(), end = mVisuals.End(); replacedIter != end; replacedIter++)
1920   {
1921     (*replacedIter)->pending = false;
1922   }
1923
1924   mRemoveVisuals.Clear();
1925 }
1926
1927 void Control::Impl::SetMargin(Extents margin)
1928 {
1929   mControlImpl.mImpl->mMargin = margin;
1930
1931   // Trigger a size negotiation request that may be needed when setting a margin.
1932   mControlImpl.RelayoutRequest();
1933 }
1934
1935 Extents Control::Impl::GetMargin() const
1936 {
1937   return mControlImpl.mImpl->mMargin;
1938 }
1939
1940 void Control::Impl::SetPadding(Extents padding)
1941 {
1942   mControlImpl.mImpl->mPadding = padding;
1943
1944   // Trigger a size negotiation request that may be needed when setting a padding.
1945   mControlImpl.RelayoutRequest();
1946 }
1947
1948 Extents Control::Impl::GetPadding() const
1949 {
1950   return mControlImpl.mImpl->mPadding;
1951 }
1952
1953 void Control::Impl::SetInputMethodContext(InputMethodContext& inputMethodContext)
1954 {
1955   mInputMethodContext = inputMethodContext;
1956 }
1957
1958 bool Control::Impl::FilterKeyEvent(const KeyEvent& event)
1959 {
1960   bool consumed(false);
1961
1962   if(mInputMethodContext)
1963   {
1964     consumed = mInputMethodContext.FilterEventKey(event);
1965   }
1966   return consumed;
1967 }
1968
1969 DevelControl::VisualEventSignalType& Control::Impl::VisualEventSignal()
1970 {
1971   return mVisualEventSignal;
1972 }
1973
1974 void Control::Impl::SetShadow(const Property::Map& map)
1975 {
1976   Toolkit::Visual::Base visual = Toolkit::VisualFactory::Get().CreateVisual(map);
1977   visual.SetName("shadow");
1978
1979   if(visual)
1980   {
1981     mControlImpl.mImpl->RegisterVisual(Toolkit::DevelControl::Property::SHADOW, visual, DepthIndex::BACKGROUND_EFFECT);
1982
1983     mControlImpl.RelayoutRequest();
1984   }
1985 }
1986
1987 void Control::Impl::ClearShadow()
1988 {
1989   mControlImpl.mImpl->UnregisterVisual(Toolkit::DevelControl::Property::SHADOW);
1990
1991   // Trigger a size negotiation request that may be needed when unregistering a visual.
1992   mControlImpl.RelayoutRequest();
1993 }
1994
1995 Dali::Property Control::Impl::GetVisualProperty(Dali::Property::Index index, Dali::Property::Key visualPropertyKey)
1996 {
1997   Toolkit::Visual::Base visual = GetVisualByIndex(mVisuals, index);
1998   if(visual)
1999   {
2000     Internal::Visual::Base& visualImpl = Toolkit::GetImplementation(visual);
2001     return visualImpl.GetPropertyObject(visualPropertyKey);
2002   }
2003
2004   Handle handle;
2005   return Dali::Property(handle, Property::INVALID_INDEX);
2006 }
2007
2008 void Control::Impl::CreateTransitions(std::vector<std::pair<Dali::Property::Index, Dali::Property::Map>>& sourceProperties,
2009                                       std::vector<std::pair<Dali::Property::Index, Dali::Property::Map>>& destinationProperties,
2010                                       Dali::Toolkit::Control                                              source,
2011                                       Dali::Toolkit::Control                                              destination)
2012 {
2013   // Retrieves background properties to be transitioned.
2014   Dali::Property::Map backgroundSourcePropertyMap, backgroundDestinationPropertyMap;
2015   mControlImpl.MakeVisualTransition(backgroundSourcePropertyMap, backgroundDestinationPropertyMap, source, destination, Toolkit::Control::Property::BACKGROUND);
2016   if(backgroundSourcePropertyMap.Count() > 0)
2017   {
2018     sourceProperties.push_back(std::pair<Dali::Property::Index, Dali::Property::Map>(Toolkit::Control::Property::BACKGROUND, backgroundSourcePropertyMap));
2019     destinationProperties.push_back(std::pair<Dali::Property::Index, Dali::Property::Map>(Toolkit::Control::Property::BACKGROUND, backgroundDestinationPropertyMap));
2020   }
2021
2022   // Retrieves shadow properties to be transitioned.
2023   Dali::Property::Map shadowSourcePropertyMap, shadowDestinationPropertyMap;
2024   mControlImpl.MakeVisualTransition(shadowSourcePropertyMap, shadowDestinationPropertyMap, source, destination, Toolkit::DevelControl::Property::SHADOW);
2025   if(shadowSourcePropertyMap.Count() > 0)
2026   {
2027     sourceProperties.push_back(std::pair<Dali::Property::Index, Dali::Property::Map>(Toolkit::DevelControl::Property::SHADOW, shadowSourcePropertyMap));
2028     destinationProperties.push_back(std::pair<Dali::Property::Index, Dali::Property::Map>(Toolkit::DevelControl::Property::SHADOW, shadowDestinationPropertyMap));
2029   }
2030
2031   // Retrieves transition from inherited class.
2032   mControlImpl.OnCreateTransitions(sourceProperties, destinationProperties, source, destination);
2033 }
2034
2035 void Control::Impl::UpdateVisualProperties(const std::vector<std::pair<Dali::Property::Index, Dali::Property::Map>>& properties)
2036 {
2037   for(auto&& data : properties)
2038   {
2039     if(data.first == Toolkit::Control::Property::BACKGROUND)
2040     {
2041       DoAction(Toolkit::Control::Property::BACKGROUND, DevelVisual::Action::UPDATE_PROPERTY, data.second);
2042     }
2043     else if(data.first == Toolkit::DevelControl::Property::SHADOW)
2044     {
2045       DoAction(Toolkit::DevelControl::Property::SHADOW, DevelVisual::Action::UPDATE_PROPERTY, data.second);
2046     }
2047   }
2048   mControlImpl.OnUpdateVisualProperties(properties);
2049 }
2050
2051 void Control::Impl::EmitResourceReadySignal()
2052 {
2053   if(!mIsEmittingResourceReadySignal)
2054   {
2055     // Guard against calls to emit the signal during the callback
2056     mIsEmittingResourceReadySignal = true;
2057
2058     // If the signal handler changes visual, it may become ready during this call & therefore this method will
2059     // get called again recursively. If so, mNeedToEmitResourceReady is set below, and we act on it after that secondary
2060     // invocation has completed by notifying in an Idle callback to prevent further recursion.
2061     Dali::Toolkit::Control handle(mControlImpl.GetOwner());
2062     mResourceReadySignal.Emit(handle);
2063
2064     if(mNeedToEmitResourceReady)
2065     {
2066       // Add idler to emit the signal again
2067       if(!mIdleCallback)
2068       {
2069         // The callback manager takes the ownership of the callback object.
2070         mIdleCallback = MakeCallback(this, &Control::Impl::OnIdleCallback);
2071         Adaptor::Get().AddIdle(mIdleCallback, false);
2072       }
2073     }
2074
2075     mIsEmittingResourceReadySignal = false;
2076   }
2077   else
2078   {
2079     mNeedToEmitResourceReady = true;
2080   }
2081 }
2082
2083 void Control::Impl::OnIdleCallback()
2084 {
2085   if(mNeedToEmitResourceReady)
2086   {
2087     // Reset the flag
2088     mNeedToEmitResourceReady = false;
2089
2090     // A visual is ready so control may need relayouting if staged
2091     if(mControlImpl.Self().GetProperty<bool>(Actor::Property::CONNECTED_TO_SCENE))
2092     {
2093       mControlImpl.RelayoutRequest();
2094     }
2095
2096     EmitResourceReadySignal();
2097   }
2098
2099   // Set the pointer to null as the callback manager deletes the callback after execute it.
2100   mIdleCallback = nullptr;
2101 }
2102
2103 Toolkit::DevelControl::ControlAccessible* Control::Impl::GetAccessibleObject()
2104 {
2105   if(!mAccessibleObject)
2106   {
2107     mAccessibleObject.reset(mControlImpl.CreateAccessibleObject());
2108   }
2109
2110   return mAccessibleObject.get();
2111 }
2112
2113 } // namespace Internal
2114
2115 } // namespace Toolkit
2116
2117 } // namespace Dali