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