Merge "Fix text written below cursor bug" 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         break;
1382       }
1383     }
1384   }
1385 }
1386
1387 Property::Value Control::Impl::GetProperty(BaseObject* object, Property::Index index)
1388 {
1389   Property::Value value;
1390
1391   Toolkit::Control control = Toolkit::Control::DownCast(BaseHandle(object));
1392
1393   if(control)
1394   {
1395     Control& controlImpl(GetImplementation(control));
1396
1397     switch(index)
1398     {
1399       case Toolkit::Control::Property::STYLE_NAME:
1400       {
1401         value = controlImpl.GetStyleName();
1402         break;
1403       }
1404
1405       case Toolkit::DevelControl::Property::STATE:
1406       {
1407         value = controlImpl.mImpl->mState;
1408         break;
1409       }
1410
1411       case Toolkit::DevelControl::Property::SUB_STATE:
1412       {
1413         value = controlImpl.mImpl->mSubStateName;
1414         break;
1415       }
1416
1417       case Toolkit::DevelControl::Property::LEFT_FOCUSABLE_ACTOR_ID:
1418       {
1419         value = controlImpl.mImpl->mLeftFocusableActorId;
1420         break;
1421       }
1422
1423       case Toolkit::DevelControl::Property::RIGHT_FOCUSABLE_ACTOR_ID:
1424       {
1425         value = controlImpl.mImpl->mRightFocusableActorId;
1426         break;
1427       }
1428
1429       case Toolkit::DevelControl::Property::UP_FOCUSABLE_ACTOR_ID:
1430       {
1431         value = controlImpl.mImpl->mUpFocusableActorId;
1432         break;
1433       }
1434
1435       case Toolkit::DevelControl::Property::DOWN_FOCUSABLE_ACTOR_ID:
1436       {
1437         value = controlImpl.mImpl->mDownFocusableActorId;
1438         break;
1439       }
1440
1441       case Toolkit::Control::Property::KEY_INPUT_FOCUS:
1442       {
1443         value = controlImpl.HasKeyInputFocus();
1444         break;
1445       }
1446
1447       case Toolkit::Control::Property::BACKGROUND:
1448       {
1449         Property::Map         map;
1450         Toolkit::Visual::Base visual = controlImpl.mImpl->GetVisual(Toolkit::Control::Property::BACKGROUND);
1451         if(visual)
1452         {
1453           visual.CreatePropertyMap(map);
1454         }
1455
1456         value = map;
1457         break;
1458       }
1459
1460       case Toolkit::Control::Property::MARGIN:
1461       {
1462         value = controlImpl.mImpl->GetMargin();
1463         break;
1464       }
1465
1466       case Toolkit::Control::Property::PADDING:
1467       {
1468         value = controlImpl.mImpl->GetPadding();
1469         break;
1470       }
1471
1472       case Toolkit::DevelControl::Property::TOOLTIP:
1473       {
1474         Property::Map map;
1475         if(controlImpl.mImpl->mTooltip)
1476         {
1477           controlImpl.mImpl->mTooltip->CreatePropertyMap(map);
1478         }
1479         value = map;
1480         break;
1481       }
1482
1483       case Toolkit::DevelControl::Property::SHADOW:
1484       {
1485         Property::Map         map;
1486         Toolkit::Visual::Base visual = controlImpl.mImpl->GetVisual(Toolkit::DevelControl::Property::SHADOW);
1487         if(visual)
1488         {
1489           visual.CreatePropertyMap(map);
1490         }
1491
1492         value = map;
1493         break;
1494       }
1495
1496       case Toolkit::DevelControl::Property::ACCESSIBILITY_NAME:
1497       {
1498         if(controlImpl.mImpl->mAccessibilityNameSet)
1499         {
1500           value = controlImpl.mImpl->mAccessibilityName;
1501         }
1502         break;
1503       }
1504
1505       case Toolkit::DevelControl::Property::ACCESSIBILITY_DESCRIPTION:
1506       {
1507         if(controlImpl.mImpl->mAccessibilityDescriptionSet)
1508         {
1509           value = controlImpl.mImpl->mAccessibilityDescription;
1510         }
1511         break;
1512       }
1513
1514       case Toolkit::DevelControl::Property::ACCESSIBILITY_TRANSLATION_DOMAIN:
1515       {
1516         if(controlImpl.mImpl->mAccessibilityTranslationDomainSet)
1517         {
1518           value = controlImpl.mImpl->mAccessibilityTranslationDomain;
1519         }
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         if(controlImpl.mImpl->mAccessibilityHighlightableSet)
1532         {
1533           value = controlImpl.mImpl->mAccessibilityHighlightable;
1534         }
1535         break;
1536       }
1537
1538       case Toolkit::DevelControl::Property::ACCESSIBILITY_ATTRIBUTES:
1539       {
1540         value = controlImpl.mImpl->mAccessibilityAttributes;
1541         break;
1542       }
1543
1544       case Toolkit::DevelControl::Property::DISPATCH_KEY_EVENTS:
1545       {
1546         value = controlImpl.mImpl->mDispatchKeyEvents;
1547         break;
1548       }
1549
1550       case Toolkit::DevelControl::Property::ACCESSIBILITY_HIDDEN:
1551       {
1552         value = controlImpl.mImpl->mAccessibilityHidden;
1553         break;
1554       }
1555     }
1556   }
1557
1558   return value;
1559 }
1560
1561 void Control::Impl::RemoveAccessibilityAttribute(const std::string& key)
1562 {
1563   Property::Value* value = mAccessibilityAttributes.Find(key);
1564   if(value)
1565   {
1566     mAccessibilityAttributes[key] = Property::Value();
1567   }
1568 }
1569
1570 void Control::Impl::ClearAccessibilityAttributes()
1571 {
1572   mAccessibilityAttributes.Clear();
1573 }
1574
1575 void Control::Impl::SetAccessibilityReadingInfoType(const Dali::Accessibility::ReadingInfoTypes types)
1576 {
1577   std::string value{};
1578   if(types[Dali::Accessibility::ReadingInfoType::NAME])
1579   {
1580     value += READING_INFO_TYPE_NAME;
1581   }
1582   if(types[Dali::Accessibility::ReadingInfoType::ROLE])
1583   {
1584     if(!value.empty())
1585     {
1586       value += READING_INFO_TYPE_SEPARATOR;
1587     }
1588     value += READING_INFO_TYPE_ROLE;
1589   }
1590   if(types[Dali::Accessibility::ReadingInfoType::DESCRIPTION])
1591   {
1592     if(!value.empty())
1593     {
1594       value += READING_INFO_TYPE_SEPARATOR;
1595     }
1596     value += READING_INFO_TYPE_DESCRIPTION;
1597   }
1598   if(types[Dali::Accessibility::ReadingInfoType::STATE])
1599   {
1600     if(!value.empty())
1601     {
1602       value += READING_INFO_TYPE_SEPARATOR;
1603     }
1604     value += READING_INFO_TYPE_STATE;
1605   }
1606   AppendAccessibilityAttribute(READING_INFO_TYPE_ATTRIBUTE_NAME, value);
1607 }
1608
1609 Dali::Accessibility::ReadingInfoTypes Control::Impl::GetAccessibilityReadingInfoType() const
1610 {
1611   std::string value{};
1612   auto        place = mAccessibilityAttributes.Find(READING_INFO_TYPE_ATTRIBUTE_NAME);
1613   if(place)
1614   {
1615     place->Get(value);
1616   }
1617   else
1618   {
1619     Dali::Accessibility::ReadingInfoTypes types;
1620     types[Dali::Accessibility::ReadingInfoType::NAME]        = true;
1621     types[Dali::Accessibility::ReadingInfoType::ROLE]        = true;
1622     types[Dali::Accessibility::ReadingInfoType::DESCRIPTION] = true;
1623     types[Dali::Accessibility::ReadingInfoType::STATE]       = true;
1624     return types;
1625   }
1626
1627   if(value.empty())
1628   {
1629     return {};
1630   }
1631
1632   Dali::Accessibility::ReadingInfoTypes types;
1633
1634   if(value.find(READING_INFO_TYPE_NAME) != std::string::npos)
1635   {
1636     types[Dali::Accessibility::ReadingInfoType::NAME] = true;
1637   }
1638   if(value.find(READING_INFO_TYPE_ROLE) != std::string::npos)
1639   {
1640     types[Dali::Accessibility::ReadingInfoType::ROLE] = true;
1641   }
1642   if(value.find(READING_INFO_TYPE_DESCRIPTION) != std::string::npos)
1643   {
1644     types[Dali::Accessibility::ReadingInfoType::DESCRIPTION] = true;
1645   }
1646   if(value.find(READING_INFO_TYPE_STATE) != std::string::npos)
1647   {
1648     types[Dali::Accessibility::ReadingInfoType::STATE] = true;
1649   }
1650
1651   return types;
1652 }
1653
1654 void Control::Impl::CopyInstancedProperties(RegisteredVisualContainer& visuals, Dictionary<Property::Map>& instancedProperties)
1655 {
1656   for(RegisteredVisualContainer::Iterator iter = visuals.Begin(); iter != visuals.End(); iter++)
1657   {
1658     if((*iter)->visual)
1659     {
1660       Property::Map instanceMap;
1661       Toolkit::GetImplementation((*iter)->visual).CreateInstancePropertyMap(instanceMap);
1662       instancedProperties.Add((*iter)->visual.GetName(), instanceMap);
1663     }
1664   }
1665 }
1666
1667 void Control::Impl::RemoveVisual(RegisteredVisualContainer& visuals, const std::string& visualName)
1668 {
1669   Actor self(mControlImpl.Self());
1670
1671   for(RegisteredVisualContainer::Iterator visualIter = visuals.Begin();
1672       visualIter != visuals.End();
1673       ++visualIter)
1674   {
1675     Toolkit::Visual::Base visual = (*visualIter)->visual;
1676     if(visual && visual.GetName() == visualName)
1677     {
1678       Toolkit::GetImplementation(visual).SetOffScene(self);
1679       (*visualIter)->visual.Reset();
1680       visuals.Erase(visualIter);
1681       break;
1682     }
1683   }
1684 }
1685
1686 void Control::Impl::RemoveVisuals(RegisteredVisualContainer& visuals, DictionaryKeys& removeVisuals)
1687 {
1688   Actor self(mControlImpl.Self());
1689   for(DictionaryKeys::iterator iter = removeVisuals.begin(); iter != removeVisuals.end(); ++iter)
1690   {
1691     const std::string visualName = *iter;
1692     RemoveVisual(visuals, visualName);
1693   }
1694 }
1695
1696 void Control::Impl::RecreateChangedVisuals(Dictionary<Property::Map>& stateVisualsToChange,
1697                                            Dictionary<Property::Map>& instancedProperties)
1698 {
1699   Dali::CustomActor handle(mControlImpl.GetOwner());
1700   for(Dictionary<Property::Map>::iterator iter = stateVisualsToChange.Begin();
1701       iter != stateVisualsToChange.End();
1702       ++iter)
1703   {
1704     const std::string&   visualName = (*iter).key;
1705     const Property::Map& toMap      = (*iter).entry;
1706
1707     Actor                               self = mControlImpl.Self();
1708     RegisteredVisualContainer::Iterator registeredVisualsiter;
1709     // Check if visual (visualName) is already registered, this is the current visual.
1710     if(FindVisual(visualName, mVisuals, registeredVisualsiter))
1711     {
1712       Toolkit::Visual::Base& visual = (*registeredVisualsiter)->visual;
1713       if(visual)
1714       {
1715         // No longer required to know if the replaced visual's resources are ready
1716         StopObservingVisual(visual);
1717
1718         // If control staged then visuals will be swapped once ready
1719         if(self.GetProperty<bool>(Actor::Property::CONNECTED_TO_SCENE))
1720         {
1721           // Check if visual is currently in the process of being replaced ( is in removal container )
1722           RegisteredVisualContainer::Iterator visualQueuedForRemoval;
1723           if(FindVisual(visualName, mRemoveVisuals, visualQueuedForRemoval))
1724           {
1725             // Visual with same visual name is already in removal container so current visual pending
1726             // Only the the last requested visual will be displayed so remove current visual which is staged but not ready.
1727             Toolkit::GetImplementation(visual).SetOffScene(self);
1728             (*registeredVisualsiter)->visual.Reset();
1729             mVisuals.Erase(registeredVisualsiter);
1730           }
1731           else
1732           {
1733             // current visual not already in removal container so add now.
1734             DALI_LOG_INFO(gLogFilter, Debug::Verbose, "RegisterVisual Move current registered visual to removal Queue: %s \n", visualName.c_str());
1735             MoveVisual(registeredVisualsiter, mVisuals, mRemoveVisuals);
1736           }
1737         }
1738         else
1739         {
1740           // Control not staged or visual disabled so can just erase from registered visuals and new visual will be added later.
1741           (*registeredVisualsiter)->visual.Reset();
1742           mVisuals.Erase(registeredVisualsiter);
1743         }
1744       }
1745
1746       const Property::Map* instancedMap = instancedProperties.FindConst(visualName);
1747       Style::ApplyVisual(handle, visualName, toMap, instancedMap);
1748     }
1749   }
1750 }
1751
1752 void Control::Impl::ReplaceStateVisualsAndProperties(const StylePtr oldState, const StylePtr newState, const std::string& subState)
1753 {
1754   // Collect all old visual names
1755   DictionaryKeys stateVisualsToRemove;
1756   if(oldState)
1757   {
1758     oldState->visuals.GetKeys(stateVisualsToRemove);
1759     if(!subState.empty())
1760     {
1761       const StylePtr* oldSubState = oldState->subStates.FindConst(subState);
1762       if(oldSubState)
1763       {
1764         DictionaryKeys subStateVisualsToRemove;
1765         (*oldSubState)->visuals.GetKeys(subStateVisualsToRemove);
1766         Merge(stateVisualsToRemove, subStateVisualsToRemove);
1767       }
1768     }
1769   }
1770
1771   // Collect all new visual properties
1772   Dictionary<Property::Map> stateVisualsToAdd;
1773   if(newState)
1774   {
1775     stateVisualsToAdd = newState->visuals;
1776     if(!subState.empty())
1777     {
1778       const StylePtr* newSubState = newState->subStates.FindConst(subState);
1779       if(newSubState)
1780       {
1781         stateVisualsToAdd.Merge((*newSubState)->visuals);
1782       }
1783     }
1784   }
1785
1786   // If a name is in both add/remove, move it to change list.
1787   Dictionary<Property::Map> stateVisualsToChange;
1788   FindChangableVisuals(stateVisualsToAdd, stateVisualsToChange, stateVisualsToRemove);
1789
1790   // Copy instanced properties (e.g. text label) of current visuals
1791   Dictionary<Property::Map> instancedProperties;
1792   CopyInstancedProperties(mVisuals, instancedProperties);
1793
1794   // For each visual in remove list, remove from mVisuals
1795   RemoveVisuals(mVisuals, stateVisualsToRemove);
1796
1797   // For each visual in add list, create and add to mVisuals
1798   Dali::CustomActor handle(mControlImpl.GetOwner());
1799   Style::ApplyVisuals(handle, stateVisualsToAdd, instancedProperties);
1800
1801   // For each visual in change list, if it requires a new visual,
1802   // remove old visual, create and add to mVisuals
1803   RecreateChangedVisuals(stateVisualsToChange, instancedProperties);
1804 }
1805
1806 void Control::Impl::SetState(DevelControl::State newState, bool withTransitions)
1807 {
1808   DevelControl::State oldState = mState;
1809   Dali::CustomActor   handle(mControlImpl.GetOwner());
1810   DALI_LOG_INFO(gLogFilter, Debug::Concise, "Control::Impl::SetState: %s\n", (mState == DevelControl::NORMAL ? "NORMAL" : (mState == DevelControl::FOCUSED ? "FOCUSED" : (mState == DevelControl::DISABLED ? "DISABLED" : "NONE"))));
1811
1812   if(mState != newState)
1813   {
1814     // If mState was Disabled, and new state is Focused, should probably
1815     // store that fact, e.g. in another property that FocusManager can access.
1816     mState = newState;
1817
1818     // Trigger state change and transitions
1819     // Apply new style, if stylemanager is available
1820     Toolkit::StyleManager styleManager = Toolkit::StyleManager::Get();
1821     if(styleManager)
1822     {
1823       const StylePtr stylePtr = GetImpl(styleManager).GetRecordedStyle(Toolkit::Control(mControlImpl.GetOwner()));
1824
1825       if(stylePtr)
1826       {
1827         std::string oldStateName = Scripting::GetEnumerationName<Toolkit::DevelControl::State>(oldState, ControlStateTable, ControlStateTableCount);
1828         std::string newStateName = Scripting::GetEnumerationName<Toolkit::DevelControl::State>(newState, ControlStateTable, ControlStateTableCount);
1829
1830         const StylePtr* newStateStyle = stylePtr->subStates.Find(newStateName);
1831         const StylePtr* oldStateStyle = stylePtr->subStates.Find(oldStateName);
1832         if(oldStateStyle && newStateStyle)
1833         {
1834           // Only change if both state styles exist
1835           ReplaceStateVisualsAndProperties(*oldStateStyle, *newStateStyle, mSubStateName);
1836         }
1837       }
1838     }
1839   }
1840 }
1841
1842 void Control::Impl::SetSubState(const std::string& subStateName, bool withTransitions)
1843 {
1844   if(mSubStateName != subStateName)
1845   {
1846     // Get existing sub-state visuals, and unregister them
1847     Dali::CustomActor handle(mControlImpl.GetOwner());
1848
1849     Toolkit::StyleManager styleManager = Toolkit::StyleManager::Get();
1850     if(styleManager)
1851     {
1852       const StylePtr stylePtr = GetImpl(styleManager).GetRecordedStyle(Toolkit::Control(mControlImpl.GetOwner()));
1853       if(stylePtr)
1854       {
1855         // Stringify state
1856         std::string stateName = Scripting::GetEnumerationName<Toolkit::DevelControl::State>(mState, ControlStateTable, ControlStateTableCount);
1857
1858         const StylePtr* state = stylePtr->subStates.Find(stateName);
1859         if(state)
1860         {
1861           StylePtr stateStyle(*state);
1862
1863           const StylePtr* newStateStyle = stateStyle->subStates.Find(subStateName);
1864           const StylePtr* oldStateStyle = stateStyle->subStates.Find(mSubStateName);
1865           if(oldStateStyle && newStateStyle)
1866           {
1867             std::string empty;
1868             ReplaceStateVisualsAndProperties(*oldStateStyle, *newStateStyle, empty);
1869           }
1870         }
1871       }
1872     }
1873
1874     mSubStateName = subStateName;
1875   }
1876 }
1877
1878 void Control::Impl::OnSceneDisconnection()
1879 {
1880   Actor self = mControlImpl.Self();
1881
1882   // Any visuals set for replacement but not yet ready should still be registered.
1883   // Reason: If a request was made to register a new visual but the control removed from scene before visual was ready
1884   // then when this control appears back on stage it should use that new visual.
1885
1886   // Iterate through all registered visuals and set off scene
1887   SetVisualsOffScene(mVisuals, self);
1888
1889   // Visuals pending replacement can now be taken out of the removal list and set off scene
1890   // Iterate through all replacement visuals and add to a move queue then set off scene
1891   for(auto removalIter = mRemoveVisuals.Begin(), end = mRemoveVisuals.End(); removalIter != end; removalIter++)
1892   {
1893     Toolkit::GetImplementation((*removalIter)->visual).SetOffScene(self);
1894   }
1895
1896   for(auto replacedIter = mVisuals.Begin(), end = mVisuals.End(); replacedIter != end; replacedIter++)
1897   {
1898     (*replacedIter)->pending = false;
1899   }
1900
1901   mRemoveVisuals.Clear();
1902 }
1903
1904 void Control::Impl::SetMargin(Extents margin)
1905 {
1906   mControlImpl.mImpl->mMargin = margin;
1907
1908   // Trigger a size negotiation request that may be needed when setting a margin.
1909   mControlImpl.RelayoutRequest();
1910 }
1911
1912 Extents Control::Impl::GetMargin() const
1913 {
1914   return mControlImpl.mImpl->mMargin;
1915 }
1916
1917 void Control::Impl::SetPadding(Extents padding)
1918 {
1919   mControlImpl.mImpl->mPadding = padding;
1920
1921   // Trigger a size negotiation request that may be needed when setting a padding.
1922   mControlImpl.RelayoutRequest();
1923 }
1924
1925 Extents Control::Impl::GetPadding() const
1926 {
1927   return mControlImpl.mImpl->mPadding;
1928 }
1929
1930 void Control::Impl::SetInputMethodContext(InputMethodContext& inputMethodContext)
1931 {
1932   mInputMethodContext = inputMethodContext;
1933 }
1934
1935 bool Control::Impl::FilterKeyEvent(const KeyEvent& event)
1936 {
1937   bool consumed(false);
1938
1939   if(mInputMethodContext)
1940   {
1941     consumed = mInputMethodContext.FilterEventKey(event);
1942   }
1943   return consumed;
1944 }
1945
1946 DevelControl::VisualEventSignalType& Control::Impl::VisualEventSignal()
1947 {
1948   return mVisualEventSignal;
1949 }
1950
1951 void Control::Impl::SetShadow(const Property::Map& map)
1952 {
1953   Toolkit::Visual::Base visual = Toolkit::VisualFactory::Get().CreateVisual(map);
1954   visual.SetName("shadow");
1955
1956   if(visual)
1957   {
1958     mControlImpl.mImpl->RegisterVisual(Toolkit::DevelControl::Property::SHADOW, visual, DepthIndex::BACKGROUND_EFFECT);
1959
1960     mControlImpl.RelayoutRequest();
1961   }
1962 }
1963
1964 void Control::Impl::ClearShadow()
1965 {
1966   mControlImpl.mImpl->UnregisterVisual(Toolkit::DevelControl::Property::SHADOW);
1967
1968   // Trigger a size negotiation request that may be needed when unregistering a visual.
1969   mControlImpl.RelayoutRequest();
1970 }
1971
1972 Dali::Property Control::Impl::GetVisualProperty(Dali::Property::Index index, Dali::Property::Key visualPropertyKey)
1973 {
1974   Toolkit::Visual::Base visual = GetVisualByIndex(mVisuals, index);
1975   if(visual)
1976   {
1977     Internal::Visual::Base& visualImpl = Toolkit::GetImplementation(visual);
1978     return visualImpl.GetPropertyObject(visualPropertyKey);
1979   }
1980
1981   Handle handle;
1982   return Dali::Property(handle, Property::INVALID_INDEX);
1983 }
1984
1985 void Control::Impl::CreateTransitions(std::vector<std::pair<Dali::Property::Index, Dali::Property::Map>>& sourceProperties,
1986                                       std::vector<std::pair<Dali::Property::Index, Dali::Property::Map>>& destinationProperties,
1987                                       Dali::Toolkit::Control source, Dali::Toolkit::Control destination)
1988 {
1989   // Retrieves background properties to be transitioned.
1990   Dali::Property::Map backgroundSourcePropertyMap, backgroundDestinationPropertyMap;
1991   mControlImpl.MakeVisualTransition(backgroundSourcePropertyMap, backgroundDestinationPropertyMap, source, destination, Toolkit::Control::Property::BACKGROUND);
1992   if(backgroundSourcePropertyMap.Count() > 0)
1993   {
1994     sourceProperties.push_back(std::pair<Dali::Property::Index, Dali::Property::Map>(Toolkit::Control::Property::BACKGROUND, backgroundSourcePropertyMap));
1995     destinationProperties.push_back(std::pair<Dali::Property::Index, Dali::Property::Map>(Toolkit::Control::Property::BACKGROUND, backgroundDestinationPropertyMap));
1996   }
1997
1998   // Retrieves shadow properties to be transitioned.
1999   Dali::Property::Map shadowSourcePropertyMap, shadowDestinationPropertyMap;
2000   mControlImpl.MakeVisualTransition(shadowSourcePropertyMap, shadowDestinationPropertyMap, source, destination, Toolkit::DevelControl::Property::SHADOW);
2001   if(shadowSourcePropertyMap.Count() > 0)
2002   {
2003     sourceProperties.push_back(std::pair<Dali::Property::Index, Dali::Property::Map>(Toolkit::DevelControl::Property::SHADOW, shadowSourcePropertyMap));
2004     destinationProperties.push_back(std::pair<Dali::Property::Index, Dali::Property::Map>(Toolkit::DevelControl::Property::SHADOW, shadowDestinationPropertyMap));
2005   }
2006
2007   // Retrieves transition from inherited class.
2008   mControlImpl.OnCreateTransitions(sourceProperties, destinationProperties, source, destination);
2009 }
2010
2011 void Control::Impl::UpdateVisualProperties(const std::vector<std::pair<Dali::Property::Index, Dali::Property::Map>>& properties)
2012 {
2013   for(auto&& data : properties)
2014   {
2015     if(data.first == Toolkit::Control::Property::BACKGROUND)
2016     {
2017       DoAction(Toolkit::Control::Property::BACKGROUND, DevelVisual::Action::UPDATE_PROPERTY, data.second);
2018     }
2019     else if(data.first == Toolkit::DevelControl::Property::SHADOW)
2020     {
2021       DoAction(Toolkit::DevelControl::Property::SHADOW, DevelVisual::Action::UPDATE_PROPERTY, data.second);
2022     }
2023   }
2024   mControlImpl.OnUpdateVisualProperties(properties);
2025 }
2026
2027 void Control::Impl::EmitResourceReadySignal()
2028 {
2029   if(!mIsEmittingResourceReadySignal)
2030   {
2031     // Guard against calls to emit the signal during the callback
2032     mIsEmittingResourceReadySignal = true;
2033
2034     // If the signal handler changes visual, it may become ready during this call & therefore this method will
2035     // get called again recursively. If so, mNeedToEmitResourceReady is set below, and we act on it after that secondary
2036     // invocation has completed by notifying in an Idle callback to prevent further recursion.
2037     Dali::Toolkit::Control handle(mControlImpl.GetOwner());
2038     mResourceReadySignal.Emit(handle);
2039
2040     if(mNeedToEmitResourceReady)
2041     {
2042       // Add idler to emit the signal again
2043       if(!mIdleCallback)
2044       {
2045         // The callback manager takes the ownership of the callback object.
2046         mIdleCallback = MakeCallback(this, &Control::Impl::OnIdleCallback);
2047         Adaptor::Get().AddIdle(mIdleCallback, false);
2048       }
2049     }
2050
2051     mIsEmittingResourceReadySignal = false;
2052   }
2053   else
2054   {
2055     mNeedToEmitResourceReady = true;
2056   }
2057 }
2058
2059 void Control::Impl::OnIdleCallback()
2060 {
2061   if(mNeedToEmitResourceReady)
2062   {
2063     // Reset the flag
2064     mNeedToEmitResourceReady = false;
2065
2066     // A visual is ready so control may need relayouting if staged
2067     if(mControlImpl.Self().GetProperty<bool>(Actor::Property::CONNECTED_TO_SCENE))
2068     {
2069       mControlImpl.RelayoutRequest();
2070     }
2071
2072     EmitResourceReadySignal();
2073   }
2074
2075   // Set the pointer to null as the callback manager deletes the callback after execute it.
2076   mIdleCallback = nullptr;
2077 }
2078
2079 Dali::Accessibility::Accessible* Control::Impl::GetAccessibilityObject()
2080 {
2081   if(!mAccessibilityObject)
2082   {
2083     mAccessibilityObject = mAccessibilityConstructor(mControlImpl.Self());
2084   }
2085   return mAccessibilityObject.get();
2086 }
2087
2088 Dali::Accessibility::Accessible* Control::Impl::GetAccessibilityObject(Dali::Actor actor)
2089 {
2090   if(actor)
2091   {
2092     auto control = Dali::Toolkit::Control::DownCast(actor);
2093     if(control)
2094     {
2095       auto controlImpl = static_cast<Internal::Control*>(&control.GetImplementation());
2096       return controlImpl->mImpl->GetAccessibilityObject();
2097     }
2098   }
2099   return nullptr;
2100 }
2101
2102 } // namespace Internal
2103
2104 } // namespace Toolkit
2105
2106 } // namespace Dali