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