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