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