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