Merge "Add ApplyCustomFragmentPrefix" 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/asset-manager/asset-manager.h>
40 #include <dali-toolkit/devel-api/controls/control-depth-index-ranges.h>
41 #include <dali-toolkit/devel-api/controls/control-devel.h>
42 #include <dali-toolkit/devel-api/controls/control-wrapper-impl.h>
43 #include <dali-toolkit/internal/styling/style-manager-impl.h>
44 #include <dali-toolkit/internal/visuals/visual-base-impl.h>
45 #include <dali-toolkit/internal/visuals/visual-string-constants.h>
46 #include <dali-toolkit/public-api/controls/image-view/image-view.h>
47 #include <dali-toolkit/public-api/focus-manager/keyboard-focus-manager.h>
48 #include <dali-toolkit/public-api/visuals/image-visual-properties.h>
49 #include <dali-toolkit/public-api/visuals/visual-properties.h>
50
51 namespace
52 {
53 const std::string READING_INFO_TYPE_NAME           = "name";
54 const std::string READING_INFO_TYPE_ROLE           = "role";
55 const std::string READING_INFO_TYPE_DESCRIPTION    = "description";
56 const std::string READING_INFO_TYPE_STATE          = "state";
57 const std::string READING_INFO_TYPE_ATTRIBUTE_NAME = "reading_info_type";
58 const std::string READING_INFO_TYPE_SEPARATOR      = "|";
59 } // namespace
60
61 namespace Dali
62 {
63 namespace Toolkit
64 {
65 namespace Internal
66 {
67 extern const Dali::Scripting::StringEnum ControlStateTable[];
68 extern const unsigned int                ControlStateTableCount;
69
70 // Not static or anonymous - shared with other translation units
71 const Scripting::StringEnum ControlStateTable[] = {
72   {"NORMAL", Toolkit::DevelControl::NORMAL},
73   {"FOCUSED", Toolkit::DevelControl::FOCUSED},
74   {"DISABLED", Toolkit::DevelControl::DISABLED},
75 };
76 const unsigned int ControlStateTableCount = sizeof(ControlStateTable) / sizeof(ControlStateTable[0]);
77
78 namespace
79 {
80 #if defined(DEBUG_ENABLED)
81 Debug::Filter* gLogFilter = Debug::Filter::New(Debug::NoLogging, false, "LOG_CONTROL_VISUALS");
82 #endif
83
84 template<typename T>
85 void Remove(Dictionary<T>& keyValues, const std::string& name)
86 {
87   keyValues.Remove(name);
88 }
89
90 void Remove(DictionaryKeys& keys, const std::string& name)
91 {
92   DictionaryKeys::iterator iter = std::find(keys.begin(), keys.end(), name);
93   if(iter != keys.end())
94   {
95     keys.erase(iter);
96   }
97 }
98
99 /**
100  *  Finds visual in given array, returning true if found along with the iterator for that visual as a out parameter
101  */
102 bool FindVisual(Property::Index targetIndex, const RegisteredVisualContainer& visuals, RegisteredVisualContainer::Iterator& iter)
103 {
104   for(iter = visuals.Begin(); iter != visuals.End(); iter++)
105   {
106     if((*iter)->index == targetIndex)
107     {
108       return true;
109     }
110   }
111   return false;
112 }
113
114 /**
115  *  Finds visual in given array, returning true if found along with the iterator for that visual as a out parameter
116  */
117 bool FindVisual(std::string visualName, const RegisteredVisualContainer& visuals, RegisteredVisualContainer::Iterator& iter)
118 {
119   for(iter = visuals.Begin(); iter != visuals.End(); iter++)
120   {
121     Toolkit::Visual::Base visual = (*iter)->visual;
122     if(visual && visual.GetName() == visualName)
123     {
124       return true;
125     }
126   }
127   return false;
128 }
129
130 void FindChangableVisuals(Dictionary<Property::Map>& stateVisualsToAdd,
131                           Dictionary<Property::Map>& stateVisualsToChange,
132                           DictionaryKeys&            stateVisualsToRemove)
133 {
134   DictionaryKeys copyOfStateVisualsToRemove = stateVisualsToRemove;
135
136   for(DictionaryKeys::iterator iter = copyOfStateVisualsToRemove.begin();
137       iter != copyOfStateVisualsToRemove.end();
138       ++iter)
139   {
140     const std::string& visualName = (*iter);
141     Property::Map*     toMap      = stateVisualsToAdd.Find(visualName);
142     if(toMap)
143     {
144       stateVisualsToChange.Add(visualName, *toMap);
145       stateVisualsToAdd.Remove(visualName);
146       Remove(stateVisualsToRemove, visualName);
147     }
148   }
149 }
150
151 Toolkit::Visual::Base GetVisualByName(
152   const RegisteredVisualContainer& visuals,
153   const std::string&               visualName)
154 {
155   Toolkit::Visual::Base visualHandle;
156
157   RegisteredVisualContainer::Iterator iter;
158   for(iter = visuals.Begin(); iter != visuals.End(); iter++)
159   {
160     Toolkit::Visual::Base visual = (*iter)->visual;
161     if(visual && visual.GetName() == visualName)
162     {
163       visualHandle = visual;
164       break;
165     }
166   }
167   return visualHandle;
168 }
169
170 Toolkit::Visual::Base GetVisualByIndex(
171   const RegisteredVisualContainer& visuals,
172   Property::Index                  index)
173 {
174   Toolkit::Visual::Base visualHandle;
175
176   RegisteredVisualContainer::Iterator iter;
177   for(iter = visuals.Begin(); iter != visuals.End(); iter++)
178   {
179     if((*iter)->index == index)
180     {
181       visualHandle = (*iter)->visual;
182       break;
183     }
184   }
185   return visualHandle;
186 }
187
188 /**
189  * Move visual from source to destination container
190  */
191 void MoveVisual(RegisteredVisualContainer::Iterator sourceIter, RegisteredVisualContainer& source, RegisteredVisualContainer& destination)
192 {
193   Toolkit::Visual::Base visual = (*sourceIter)->visual;
194   if(visual)
195   {
196     RegisteredVisual* rv = source.Release(sourceIter);
197     destination.PushBack(rv);
198   }
199 }
200
201 /**
202  * Performs actions as requested using the action name.
203  * @param[in] object The object on which to perform the action.
204  * @param[in] actionName The action to perform.
205  * @param[in] attributes The attributes with which to perfrom this action.
206  * @return true if action has been accepted by this control
207  */
208 const char* ACTION_ACCESSIBILITY_ACTIVATED         = "accessibilityActivated";
209 const char* ACTION_ACCESSIBILITY_READING_CANCELLED = "ReadingCancelled";
210 const char* ACTION_ACCESSIBILITY_READING_PAUSED    = "ReadingPaused";
211 const char* ACTION_ACCESSIBILITY_READING_RESUMED   = "ReadingResumed";
212 const char* ACTION_ACCESSIBILITY_READING_SKIPPED   = "ReadingSkipped";
213 const char* ACTION_ACCESSIBILITY_READING_STOPPED   = "ReadingStopped";
214
215 static bool DoAction(BaseObject* object, const std::string& actionName, const Property::Map& attributes)
216 {
217   bool ret = true;
218
219   Dali::BaseHandle handle(object);
220
221   Toolkit::Control control = Toolkit::Control::DownCast(handle);
222
223   DALI_ASSERT_ALWAYS(control);
224
225   if(0 == strcmp(actionName.c_str(), ACTION_ACCESSIBILITY_ACTIVATED) || actionName == "activate")
226   {
227     // if cast succeeds there is an implementation so no need to check
228     if(!DevelControl::AccessibilityActivateSignal(control).Empty())
229     {
230       DevelControl::AccessibilityActivateSignal(control).Emit();
231     }
232     else
233     {
234       ret = Internal::GetImplementation(control).OnAccessibilityActivated();
235     }
236   }
237   else if(0 == strcmp(actionName.c_str(), ACTION_ACCESSIBILITY_READING_SKIPPED))
238   {
239     // if cast succeeds there is an implementation so no need to check
240     if(!DevelControl::AccessibilityReadingSkippedSignal(control).Empty())
241     {
242       DevelControl::AccessibilityReadingSkippedSignal(control).Emit();
243     }
244   }
245   else if(0 == strcmp(actionName.c_str(), ACTION_ACCESSIBILITY_READING_PAUSED))
246   {
247     // if cast succeeds there is an implementation so no need to check
248     if(!DevelControl::AccessibilityReadingPausedSignal(control).Empty())
249     {
250       DevelControl::AccessibilityReadingPausedSignal(control).Emit();
251     }
252   }
253   else if(0 == strcmp(actionName.c_str(), ACTION_ACCESSIBILITY_READING_RESUMED))
254   {
255     // if cast succeeds there is an implementation so no need to check
256     if(!DevelControl::AccessibilityReadingResumedSignal(control).Empty())
257     {
258       DevelControl::AccessibilityReadingResumedSignal(control).Emit();
259     }
260   }
261   else if(0 == strcmp(actionName.c_str(), ACTION_ACCESSIBILITY_READING_CANCELLED))
262   {
263     // if cast succeeds there is an implementation so no need to check
264     if(!DevelControl::AccessibilityReadingCancelledSignal(control).Empty())
265     {
266       DevelControl::AccessibilityReadingCancelledSignal(control).Emit();
267     }
268   }
269   else if(0 == strcmp(actionName.c_str(), ACTION_ACCESSIBILITY_READING_STOPPED))
270   {
271     // if cast succeeds there is an implementation so no need to check
272     if(!DevelControl::AccessibilityReadingStoppedSignal(control).Empty())
273     {
274       DevelControl::AccessibilityReadingStoppedSignal(control).Emit();
275     }
276   }
277   else
278   {
279     ret = false;
280   }
281   return ret;
282 }
283
284 /**
285  * Connects a callback function with the object's signals.
286  * @param[in] object The object providing the signal.
287  * @param[in] tracker Used to disconnect the signal.
288  * @param[in] signalName The signal to connect to.
289  * @param[in] functor A newly allocated FunctorDelegate.
290  * @return True if the signal was connected.
291  * @post If a signal was connected, ownership of functor was passed to CallbackBase. Otherwise the caller is responsible for deleting the unused functor.
292  */
293 const char* SIGNAL_KEY_EVENT              = "keyEvent";
294 const char* SIGNAL_KEY_INPUT_FOCUS_GAINED = "keyInputFocusGained";
295 const char* SIGNAL_KEY_INPUT_FOCUS_LOST   = "keyInputFocusLost";
296 const char* SIGNAL_TAPPED                 = "tapped";
297 const char* SIGNAL_PANNED                 = "panned";
298 const char* SIGNAL_PINCHED                = "pinched";
299 const char* SIGNAL_LONG_PRESSED           = "longPressed";
300 const char* SIGNAL_GET_NAME               = "getName";
301 const char* SIGNAL_GET_DESCRIPTION        = "getDescription";
302 const char* SIGNAL_DO_GESTURE             = "doGesture";
303 static bool DoConnectSignal(BaseObject* object, ConnectionTrackerInterface* tracker, const std::string& signalName, FunctorDelegate* functor)
304 {
305   Dali::BaseHandle handle(object);
306
307   bool             connected(false);
308   Toolkit::Control control = Toolkit::Control::DownCast(handle);
309   if(control)
310   {
311     Internal::Control& controlImpl(Internal::GetImplementation(control));
312     connected = true;
313
314     if(0 == strcmp(signalName.c_str(), SIGNAL_KEY_EVENT))
315     {
316       controlImpl.KeyEventSignal().Connect(tracker, functor);
317     }
318     else if(0 == strcmp(signalName.c_str(), SIGNAL_KEY_INPUT_FOCUS_GAINED))
319     {
320       controlImpl.KeyInputFocusGainedSignal().Connect(tracker, functor);
321     }
322     else if(0 == strcmp(signalName.c_str(), SIGNAL_KEY_INPUT_FOCUS_LOST))
323     {
324       controlImpl.KeyInputFocusLostSignal().Connect(tracker, functor);
325     }
326     else if(0 == strcmp(signalName.c_str(), SIGNAL_TAPPED))
327     {
328       controlImpl.EnableGestureDetection(GestureType::TAP);
329       controlImpl.GetTapGestureDetector().DetectedSignal().Connect(tracker, functor);
330     }
331     else if(0 == strcmp(signalName.c_str(), SIGNAL_PANNED))
332     {
333       controlImpl.EnableGestureDetection(GestureType::PAN);
334       controlImpl.GetPanGestureDetector().DetectedSignal().Connect(tracker, functor);
335     }
336     else if(0 == strcmp(signalName.c_str(), SIGNAL_PINCHED))
337     {
338       controlImpl.EnableGestureDetection(GestureType::PINCH);
339       controlImpl.GetPinchGestureDetector().DetectedSignal().Connect(tracker, functor);
340     }
341     else if(0 == strcmp(signalName.c_str(), SIGNAL_LONG_PRESSED))
342     {
343       controlImpl.EnableGestureDetection(GestureType::LONG_PRESS);
344       controlImpl.GetLongPressGestureDetector().DetectedSignal().Connect(tracker, functor);
345     }
346     else if(0 == strcmp(signalName.c_str(), SIGNAL_GET_NAME))
347     {
348       DevelControl::AccessibilityGetNameSignal(control).Connect(tracker, functor);
349     }
350     else if(0 == strcmp(signalName.c_str(), SIGNAL_GET_DESCRIPTION))
351     {
352       DevelControl::AccessibilityGetDescriptionSignal(control).Connect(tracker, functor);
353     }
354     else if(0 == strcmp(signalName.c_str(), SIGNAL_DO_GESTURE))
355     {
356       DevelControl::AccessibilityDoGestureSignal(control).Connect(tracker, functor);
357     }
358   }
359   return connected;
360 }
361
362 /**
363  * Creates control through type registry
364  */
365 BaseHandle Create()
366 {
367   return Internal::Control::New();
368 }
369 // Setup signals and actions using the type-registry.
370 DALI_TYPE_REGISTRATION_BEGIN(Control, CustomActor, Create);
371
372 // Note: Properties are registered separately below.
373
374 SignalConnectorType registerSignal1(typeRegistration, SIGNAL_KEY_EVENT, &DoConnectSignal);
375 SignalConnectorType registerSignal2(typeRegistration, SIGNAL_KEY_INPUT_FOCUS_GAINED, &DoConnectSignal);
376 SignalConnectorType registerSignal3(typeRegistration, SIGNAL_KEY_INPUT_FOCUS_LOST, &DoConnectSignal);
377 SignalConnectorType registerSignal4(typeRegistration, SIGNAL_TAPPED, &DoConnectSignal);
378 SignalConnectorType registerSignal5(typeRegistration, SIGNAL_PANNED, &DoConnectSignal);
379 SignalConnectorType registerSignal6(typeRegistration, SIGNAL_PINCHED, &DoConnectSignal);
380 SignalConnectorType registerSignal7(typeRegistration, SIGNAL_LONG_PRESSED, &DoConnectSignal);
381 SignalConnectorType registerSignal8(typeRegistration, SIGNAL_GET_NAME, &DoConnectSignal);
382 SignalConnectorType registerSignal9(typeRegistration, SIGNAL_GET_DESCRIPTION, &DoConnectSignal);
383 SignalConnectorType registerSignal10(typeRegistration, SIGNAL_DO_GESTURE, &DoConnectSignal);
384
385 TypeAction registerAction1(typeRegistration, "activate", &DoAction);
386 TypeAction registerAction2(typeRegistration, ACTION_ACCESSIBILITY_ACTIVATED, &DoAction);
387 TypeAction registerAction3(typeRegistration, ACTION_ACCESSIBILITY_READING_SKIPPED, &DoAction);
388 TypeAction registerAction4(typeRegistration, ACTION_ACCESSIBILITY_READING_CANCELLED, &DoAction);
389 TypeAction registerAction5(typeRegistration, ACTION_ACCESSIBILITY_READING_STOPPED, &DoAction);
390 TypeAction registerAction6(typeRegistration, ACTION_ACCESSIBILITY_READING_PAUSED, &DoAction);
391 TypeAction registerAction7(typeRegistration, ACTION_ACCESSIBILITY_READING_RESUMED, &DoAction);
392
393 DALI_TYPE_REGISTRATION_END()
394
395 /**
396  * @brief Iterate through given container and setOffScene any visual found
397  *
398  * @param[in] container Container of visuals
399  * @param[in] parent Parent actor to remove visuals from
400  */
401 void SetVisualsOffScene(const RegisteredVisualContainer& container, Actor parent)
402 {
403   for(auto iter = container.Begin(), end = container.End(); iter != end; iter++)
404   {
405     if((*iter)->visual)
406     {
407       DALI_LOG_INFO(gLogFilter, Debug::Verbose, "Control::SetOffScene Setting visual(%d) off stage\n", (*iter)->index);
408       Toolkit::GetImplementation((*iter)->visual).SetOffScene(parent);
409     }
410   }
411 }
412
413 } // unnamed namespace
414
415 // clang-format off
416 // Properties registered without macro to use specific member variables.
417 const PropertyRegistration Control::Impl::PROPERTY_1(typeRegistration,  "styleName",                      Toolkit::Control::Property::STYLE_NAME,                            Property::STRING,  &Control::Impl::SetProperty, &Control::Impl::GetProperty);
418 const PropertyRegistration Control::Impl::PROPERTY_4(typeRegistration,  "keyInputFocus",                  Toolkit::Control::Property::KEY_INPUT_FOCUS,                       Property::BOOLEAN, &Control::Impl::SetProperty, &Control::Impl::GetProperty);
419 const PropertyRegistration Control::Impl::PROPERTY_5(typeRegistration,  "background",                     Toolkit::Control::Property::BACKGROUND,                            Property::MAP,     &Control::Impl::SetProperty, &Control::Impl::GetProperty);
420 const PropertyRegistration Control::Impl::PROPERTY_6(typeRegistration,  "margin",                         Toolkit::Control::Property::MARGIN,                                Property::EXTENTS, &Control::Impl::SetProperty, &Control::Impl::GetProperty);
421 const PropertyRegistration Control::Impl::PROPERTY_7(typeRegistration,  "padding",                        Toolkit::Control::Property::PADDING,                               Property::EXTENTS, &Control::Impl::SetProperty, &Control::Impl::GetProperty);
422 const PropertyRegistration Control::Impl::PROPERTY_8(typeRegistration,  "tooltip",                        Toolkit::DevelControl::Property::TOOLTIP,                          Property::MAP,     &Control::Impl::SetProperty, &Control::Impl::GetProperty);
423 const PropertyRegistration Control::Impl::PROPERTY_9(typeRegistration,  "state",                          Toolkit::DevelControl::Property::STATE,                            Property::STRING,  &Control::Impl::SetProperty, &Control::Impl::GetProperty);
424 const PropertyRegistration Control::Impl::PROPERTY_10(typeRegistration, "subState",                       Toolkit::DevelControl::Property::SUB_STATE,                        Property::STRING,  &Control::Impl::SetProperty, &Control::Impl::GetProperty);
425 const PropertyRegistration Control::Impl::PROPERTY_11(typeRegistration, "leftFocusableActorId",           Toolkit::DevelControl::Property::LEFT_FOCUSABLE_ACTOR_ID,          Property::INTEGER, &Control::Impl::SetProperty, &Control::Impl::GetProperty);
426 const PropertyRegistration Control::Impl::PROPERTY_12(typeRegistration, "rightFocusableActorId",          Toolkit::DevelControl::Property::RIGHT_FOCUSABLE_ACTOR_ID,         Property::INTEGER, &Control::Impl::SetProperty, &Control::Impl::GetProperty);
427 const PropertyRegistration Control::Impl::PROPERTY_13(typeRegistration, "upFocusableActorId",             Toolkit::DevelControl::Property::UP_FOCUSABLE_ACTOR_ID,            Property::INTEGER, &Control::Impl::SetProperty, &Control::Impl::GetProperty);
428 const PropertyRegistration Control::Impl::PROPERTY_14(typeRegistration, "downFocusableActorId",           Toolkit::DevelControl::Property::DOWN_FOCUSABLE_ACTOR_ID,          Property::INTEGER, &Control::Impl::SetProperty, &Control::Impl::GetProperty);
429 const PropertyRegistration Control::Impl::PROPERTY_15(typeRegistration, "shadow",                         Toolkit::DevelControl::Property::SHADOW,                           Property::MAP,     &Control::Impl::SetProperty, &Control::Impl::GetProperty);
430 const PropertyRegistration Control::Impl::PROPERTY_16(typeRegistration, "accessibilityName",              Toolkit::DevelControl::Property::ACCESSIBILITY_NAME,               Property::STRING,  &Control::Impl::SetProperty, &Control::Impl::GetProperty);
431 const PropertyRegistration Control::Impl::PROPERTY_17(typeRegistration, "accessibilityDescription",       Toolkit::DevelControl::Property::ACCESSIBILITY_DESCRIPTION,        Property::STRING,  &Control::Impl::SetProperty, &Control::Impl::GetProperty);
432 const PropertyRegistration Control::Impl::PROPERTY_18(typeRegistration, "accessibilityTranslationDomain", Toolkit::DevelControl::Property::ACCESSIBILITY_TRANSLATION_DOMAIN, Property::STRING,  &Control::Impl::SetProperty, &Control::Impl::GetProperty);
433 const PropertyRegistration Control::Impl::PROPERTY_19(typeRegistration, "accessibilityRole",              Toolkit::DevelControl::Property::ACCESSIBILITY_ROLE,               Property::INTEGER, &Control::Impl::SetProperty, &Control::Impl::GetProperty);
434 const PropertyRegistration Control::Impl::PROPERTY_20(typeRegistration, "accessibilityHighlightable",     Toolkit::DevelControl::Property::ACCESSIBILITY_HIGHLIGHTABLE,      Property::BOOLEAN, &Control::Impl::SetProperty, &Control::Impl::GetProperty);
435 const PropertyRegistration Control::Impl::PROPERTY_21(typeRegistration, "accessibilityAttributes",        Toolkit::DevelControl::Property::ACCESSIBILITY_ATTRIBUTES,         Property::MAP,     &Control::Impl::SetProperty, &Control::Impl::GetProperty);
436 // clang-format on
437
438 Control::Impl::Impl(Control& controlImpl)
439 : mControlImpl(controlImpl),
440   mState(Toolkit::DevelControl::NORMAL),
441   mSubStateName(""),
442   mLeftFocusableActorId(-1),
443   mRightFocusableActorId(-1),
444   mUpFocusableActorId(-1),
445   mDownFocusableActorId(-1),
446   mStyleName(""),
447   mBackgroundColor(Color::TRANSPARENT),
448   mStartingPinchScale(nullptr),
449   mMargin(0, 0, 0, 0),
450   mPadding(0, 0, 0, 0),
451   mKeyEventSignal(),
452   mKeyInputFocusGainedSignal(),
453   mKeyInputFocusLostSignal(),
454   mResourceReadySignal(),
455   mVisualEventSignal(),
456   mAccessibilityGetNameSignal(),
457   mAccessibilityGetDescriptionSignal(),
458   mAccessibilityDoGestureSignal(),
459   mPinchGestureDetector(),
460   mPanGestureDetector(),
461   mTapGestureDetector(),
462   mLongPressGestureDetector(),
463   mTooltip(NULL),
464   mInputMethodContext(),
465   mIdleCallback(nullptr),
466   mFlags(Control::ControlBehaviour(CONTROL_BEHAVIOUR_DEFAULT)),
467   mIsKeyboardNavigationSupported(false),
468   mIsKeyboardFocusGroup(false),
469   mIsEmittingResourceReadySignal(false),
470   mNeedToEmitResourceReady(false)
471 {
472   Dali::Accessibility::Accessible::RegisterControlAccessibilityGetter(
473     [](Dali::Actor actor) -> Dali::Accessibility::Accessible* {
474       return Control::Impl::GetAccessibilityObject(actor);
475     });
476
477   mAccessibilityConstructor = [](Dali::Actor actor) -> std::unique_ptr<Dali::Accessibility::Accessible> {
478     return std::unique_ptr<Dali::Accessibility::Accessible>(new DevelControl::AccessibleImpl(actor, Dali::Accessibility::Role::UNKNOWN));
479   };
480
481   size_t length = static_cast<size_t>(Dali::Accessibility::RelationType::MAX_COUNT);
482   mAccessibilityRelations.reserve(length);
483   for(auto i = 0u; i < length; ++i)
484   {
485     mAccessibilityRelations.push_back({});
486   }
487 }
488
489 Control::Impl::~Impl()
490 {
491   for(auto&& iter : mVisuals)
492   {
493     StopObservingVisual(iter->visual);
494   }
495
496   for(auto&& iter : mRemoveVisuals)
497   {
498     StopObservingVisual(iter->visual);
499   }
500
501   // All gesture detectors will be destroyed so no need to disconnect.
502   delete mStartingPinchScale;
503
504   if(mIdleCallback && Adaptor::IsAvailable())
505   {
506     // Removes the callback from the callback manager in case the control is destroyed before the callback is executed.
507     Adaptor::Get().RemoveIdle(mIdleCallback);
508   }
509 }
510
511 Control::Impl& Control::Impl::Get(Internal::Control& internalControl)
512 {
513   return *internalControl.mImpl;
514 }
515
516 const Control::Impl& Control::Impl::Get(const Internal::Control& internalControl)
517 {
518   return *internalControl.mImpl;
519 }
520
521 // Gesture Detection Methods
522 void Control::Impl::PinchDetected(Actor actor, const PinchGesture& pinch)
523 {
524   mControlImpl.OnPinch(pinch);
525 }
526
527 void Control::Impl::PanDetected(Actor actor, const PanGesture& pan)
528 {
529   mControlImpl.OnPan(pan);
530 }
531
532 void Control::Impl::TapDetected(Actor actor, const TapGesture& tap)
533 {
534   mControlImpl.OnTap(tap);
535 }
536
537 void Control::Impl::LongPressDetected(Actor actor, const LongPressGesture& longPress)
538 {
539   mControlImpl.OnLongPress(longPress);
540 }
541
542 void Control::Impl::RegisterVisual(Property::Index index, Toolkit::Visual::Base& visual)
543 {
544   RegisterVisual(index, visual, VisualState::ENABLED, DepthIndexValue::NOT_SET);
545 }
546
547 void Control::Impl::RegisterVisual(Property::Index index, Toolkit::Visual::Base& visual, int depthIndex)
548 {
549   RegisterVisual(index, visual, VisualState::ENABLED, DepthIndexValue::SET, depthIndex);
550 }
551
552 void Control::Impl::RegisterVisual(Property::Index index, Toolkit::Visual::Base& visual, bool enabled)
553 {
554   RegisterVisual(index, visual, (enabled ? VisualState::ENABLED : VisualState::DISABLED), DepthIndexValue::NOT_SET);
555 }
556
557 void Control::Impl::RegisterVisual(Property::Index index, Toolkit::Visual::Base& visual, bool enabled, int depthIndex)
558 {
559   RegisterVisual(index, visual, (enabled ? VisualState::ENABLED : VisualState::DISABLED), DepthIndexValue::SET, depthIndex);
560 }
561
562 void Control::Impl::RegisterVisual(Property::Index index, Toolkit::Visual::Base& visual, VisualState::Type enabled, DepthIndexValue::Type depthIndexValueSet, int depthIndex)
563 {
564   DALI_LOG_INFO(gLogFilter, Debug::Concise, "RegisterVisual:%d \n", index);
565
566   bool  visualReplaced(false);
567   Actor self = mControlImpl.Self();
568
569   // Set the depth index, if not set by caller this will be either the current visual depth, max depth of all visuals
570   // or zero.
571   int requiredDepthIndex = visual.GetDepthIndex();
572
573   if(depthIndexValueSet == DepthIndexValue::SET)
574   {
575     requiredDepthIndex = depthIndex;
576   }
577
578   // Visual replacement, existing visual should only be removed from stage when replacement ready.
579   if(!mVisuals.Empty())
580   {
581     RegisteredVisualContainer::Iterator registeredVisualsiter;
582     // Check if visual (index) is already registered, this is the current visual.
583     if(FindVisual(index, mVisuals, registeredVisualsiter))
584     {
585       Toolkit::Visual::Base& currentRegisteredVisual = (*registeredVisualsiter)->visual;
586       if(currentRegisteredVisual)
587       {
588         // Store current visual depth index as may need to set the replacement visual to same depth
589         const int currentDepthIndex = (*registeredVisualsiter)->visual.GetDepthIndex();
590
591         // No longer required to know if the replaced visual's resources are ready
592         StopObservingVisual(currentRegisteredVisual);
593
594         // If control staged and visual enabled then visuals will be swapped once ready
595         if(self.GetProperty<bool>(Actor::Property::CONNECTED_TO_SCENE) && enabled)
596         {
597           // Check if visual is currently in the process of being replaced ( is in removal container )
598           RegisteredVisualContainer::Iterator visualQueuedForRemoval;
599           if(FindVisual(index, mRemoveVisuals, visualQueuedForRemoval))
600           {
601             // Visual with same index is already in removal container so current visual pending
602             // Only the the last requested visual will be displayed so remove current visual which is staged but not ready.
603             Toolkit::GetImplementation(currentRegisteredVisual).SetOffScene(self);
604             mVisuals.Erase(registeredVisualsiter);
605           }
606           else
607           {
608             // current visual not already in removal container so add now.
609             DALI_LOG_INFO(gLogFilter, Debug::Verbose, "RegisterVisual Move current registered visual to removal Queue: %d \n", index);
610             MoveVisual(registeredVisualsiter, mVisuals, mRemoveVisuals);
611           }
612         }
613         else
614         {
615           // Control not staged or visual disabled so can just erase from registered visuals and new visual will be added later.
616           mVisuals.Erase(registeredVisualsiter);
617         }
618
619         // 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
620         if((depthIndexValueSet == DepthIndexValue::NOT_SET) &&
621            (visual.GetDepthIndex() == 0))
622         {
623           requiredDepthIndex = currentDepthIndex;
624         }
625       }
626
627       visualReplaced = true;
628     }
629   }
630
631   // If not set, set the name of the visual to the same name as the control's property.
632   // ( If the control has been type registered )
633   if(visual.GetName().empty())
634   {
635     // returns empty string if index is not found as long as index is not -1
636     std::string visualName = self.GetPropertyName(index);
637     if(!visualName.empty())
638     {
639       DALI_LOG_INFO(gLogFilter, Debug::Concise, "Setting visual name for property %d to %s\n", index, visualName.c_str());
640       visual.SetName(visualName);
641     }
642   }
643
644   if(!visualReplaced) // New registration entry
645   {
646     // 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
647     if((depthIndexValueSet == DepthIndexValue::NOT_SET) &&
648        (mVisuals.Size() > 0) &&
649        (visual.GetDepthIndex() == 0))
650     {
651       int maxDepthIndex = std::numeric_limits<int>::min();
652
653       RegisteredVisualContainer::ConstIterator       iter;
654       const RegisteredVisualContainer::ConstIterator endIter = mVisuals.End();
655       for(iter = mVisuals.Begin(); iter != endIter; iter++)
656       {
657         const int visualDepthIndex = (*iter)->visual.GetDepthIndex();
658         if(visualDepthIndex > maxDepthIndex)
659         {
660           maxDepthIndex = visualDepthIndex;
661         }
662       }
663       ++maxDepthIndex;                                 // Add one to the current maximum depth index so that our added visual appears on top
664       requiredDepthIndex = std::max(0, maxDepthIndex); // Start at zero if maxDepth index belongs to a background
665     }
666   }
667
668   if(visual)
669   {
670     // Set determined depth index
671     visual.SetDepthIndex(requiredDepthIndex);
672
673     // Monitor when the visual resources are ready
674     StartObservingVisual(visual);
675
676     DALI_LOG_INFO(gLogFilter, Debug::Concise, "New Visual registration index[%d] depth[%d]\n", index, requiredDepthIndex);
677     RegisteredVisual* newRegisteredVisual = new RegisteredVisual(index, visual, (enabled == VisualState::ENABLED ? true : false), (visualReplaced && enabled));
678     mVisuals.PushBack(newRegisteredVisual);
679
680     Internal::Visual::Base& visualImpl = Toolkit::GetImplementation(visual);
681     // Put on stage if enabled and the control is already on the stage
682     if((enabled == VisualState::ENABLED) && self.GetProperty<bool>(Actor::Property::CONNECTED_TO_SCENE))
683     {
684       visualImpl.SetOnScene(self);
685     }
686     else if(visualImpl.IsResourceReady()) // When not being staged, check if visual already 'ResourceReady' before it was Registered. ( Resource may have been loaded already )
687     {
688       ResourceReady(visualImpl);
689     }
690   }
691
692   DALI_LOG_INFO(gLogFilter, Debug::Verbose, "Control::RegisterVisual() Registered %s(%d), enabled:%s\n", visual.GetName().c_str(), index, enabled ? "true" : "false");
693 }
694
695 void Control::Impl::UnregisterVisual(Property::Index index)
696 {
697   RegisteredVisualContainer::Iterator iter;
698   if(FindVisual(index, mVisuals, iter))
699   {
700     // stop observing visual
701     StopObservingVisual((*iter)->visual);
702
703     Actor self(mControlImpl.Self());
704     Toolkit::GetImplementation((*iter)->visual).SetOffScene(self);
705     (*iter)->visual.Reset();
706     mVisuals.Erase(iter);
707   }
708
709   if(FindVisual(index, mRemoveVisuals, iter))
710   {
711     Actor self(mControlImpl.Self());
712     Toolkit::GetImplementation((*iter)->visual).SetOffScene(self);
713     (*iter)->pending = false;
714     (*iter)->visual.Reset();
715     mRemoveVisuals.Erase(iter);
716   }
717 }
718
719 Toolkit::Visual::Base Control::Impl::GetVisual(Property::Index index) const
720 {
721   RegisteredVisualContainer::Iterator iter;
722   if(FindVisual(index, mVisuals, iter))
723   {
724     return (*iter)->visual;
725   }
726
727   return Toolkit::Visual::Base();
728 }
729
730 void Control::Impl::EnableVisual(Property::Index index, bool enable)
731 {
732   DALI_LOG_INFO(gLogFilter, Debug::General, "Control::EnableVisual(%d, %s)\n", index, enable ? "T" : "F");
733
734   RegisteredVisualContainer::Iterator iter;
735   if(FindVisual(index, mVisuals, iter))
736   {
737     if((*iter)->enabled == enable)
738     {
739       DALI_LOG_INFO(gLogFilter, Debug::Verbose, "Control::EnableVisual Visual %s(%d) already %s\n", (*iter)->visual.GetName().c_str(), index, enable ? "enabled" : "disabled");
740       return;
741     }
742
743     (*iter)->enabled  = enable;
744     Actor parentActor = mControlImpl.Self();
745     if(mControlImpl.Self().GetProperty<bool>(Actor::Property::CONNECTED_TO_SCENE)) // If control not on Scene then Visual will be added when SceneConnection is called.
746     {
747       if(enable)
748       {
749         DALI_LOG_INFO(gLogFilter, Debug::Verbose, "Control::EnableVisual Setting %s(%d) on stage \n", (*iter)->visual.GetName().c_str(), index);
750         Toolkit::GetImplementation((*iter)->visual).SetOnScene(parentActor);
751       }
752       else
753       {
754         DALI_LOG_INFO(gLogFilter, Debug::Verbose, "Control::EnableVisual Setting %s(%d) off stage \n", (*iter)->visual.GetName().c_str(), index);
755         Toolkit::GetImplementation((*iter)->visual).SetOffScene(parentActor); // No need to call if control not staged.
756       }
757     }
758   }
759   else
760   {
761     DALI_LOG_WARNING("Control::EnableVisual(%d, %s) FAILED - NO SUCH VISUAL\n", index, enable ? "T" : "F");
762   }
763 }
764
765 bool Control::Impl::IsVisualEnabled(Property::Index index) const
766 {
767   RegisteredVisualContainer::Iterator iter;
768   if(FindVisual(index, mVisuals, iter))
769   {
770     return (*iter)->enabled;
771   }
772   return false;
773 }
774
775 void Control::Impl::StopObservingVisual(Toolkit::Visual::Base& visual)
776 {
777   Internal::Visual::Base& visualImpl = Toolkit::GetImplementation(visual);
778
779   // Stop observing the visual
780   visualImpl.RemoveEventObserver(*this);
781 }
782
783 void Control::Impl::StartObservingVisual(Toolkit::Visual::Base& visual)
784 {
785   Internal::Visual::Base& visualImpl = Toolkit::GetImplementation(visual);
786
787   // start observing the visual for events
788   visualImpl.AddEventObserver(*this);
789 }
790
791 // Called by a Visual when it's resource is ready
792 void Control::Impl::ResourceReady(Visual::Base& object)
793 {
794   DALI_LOG_INFO(gLogFilter, Debug::Verbose, "Control::Impl::ResourceReady() replacements pending[%d]\n", mRemoveVisuals.Count());
795
796   Actor self = mControlImpl.Self();
797
798   // A resource is ready, find resource in the registered visuals container and get its index
799   for(auto registeredIter = mVisuals.Begin(), end = mVisuals.End(); registeredIter != end; ++registeredIter)
800   {
801     Internal::Visual::Base& registeredVisualImpl = Toolkit::GetImplementation((*registeredIter)->visual);
802
803     if(&object == &registeredVisualImpl)
804     {
805       RegisteredVisualContainer::Iterator visualToRemoveIter;
806       // Find visual with the same index in the removal container
807       // Set if off stage as it's replacement is now ready.
808       // Remove if from removal list as now removed from stage.
809       // Set Pending flag on the ready visual to false as now ready.
810       if(FindVisual((*registeredIter)->index, mRemoveVisuals, visualToRemoveIter))
811       {
812         (*registeredIter)->pending = false;
813         Toolkit::GetImplementation((*visualToRemoveIter)->visual).SetOffScene(self);
814         mRemoveVisuals.Erase(visualToRemoveIter);
815       }
816       break;
817     }
818   }
819
820   // A visual is ready so control may need relayouting if staged
821   if(self.GetProperty<bool>(Actor::Property::CONNECTED_TO_SCENE))
822   {
823     mControlImpl.RelayoutRequest();
824   }
825
826   // Emit signal if all enabled visuals registered by the control are ready.
827   if(IsResourceReady())
828   {
829     // Reset the flag
830     mNeedToEmitResourceReady = false;
831
832     EmitResourceReadySignal();
833   }
834 }
835
836 void Control::Impl::NotifyVisualEvent(Visual::Base& object, Property::Index signalId)
837 {
838   for(auto registeredIter = mVisuals.Begin(), end = mVisuals.End(); registeredIter != end; ++registeredIter)
839   {
840     Internal::Visual::Base& registeredVisualImpl = Toolkit::GetImplementation((*registeredIter)->visual);
841     if(&object == &registeredVisualImpl)
842     {
843       Dali::Toolkit::Control handle(mControlImpl.GetOwner());
844       mVisualEventSignal.Emit(handle, (*registeredIter)->index, signalId);
845       break;
846     }
847   }
848 }
849
850 bool Control::Impl::IsResourceReady() const
851 {
852   // Iterate through and check all the enabled visuals are ready
853   for(auto visualIter = mVisuals.Begin();
854       visualIter != mVisuals.End();
855       ++visualIter)
856   {
857     const Toolkit::Visual::Base   visual     = (*visualIter)->visual;
858     const Internal::Visual::Base& visualImpl = Toolkit::GetImplementation(visual);
859
860     // one of the enabled visuals is not ready
861     if(!visualImpl.IsResourceReady() && (*visualIter)->enabled)
862     {
863       return false;
864     }
865   }
866   return true;
867 }
868
869 Toolkit::Visual::ResourceStatus Control::Impl::GetVisualResourceStatus(Property::Index index) const
870 {
871   RegisteredVisualContainer::Iterator iter;
872   if(FindVisual(index, mVisuals, iter))
873   {
874     const Toolkit::Visual::Base   visual     = (*iter)->visual;
875     const Internal::Visual::Base& visualImpl = Toolkit::GetImplementation(visual);
876     return visualImpl.GetResourceStatus();
877   }
878
879   return Toolkit::Visual::ResourceStatus::PREPARING;
880 }
881
882 void Control::Impl::AddTransitions(Dali::Animation&               animation,
883                                    const Toolkit::TransitionData& handle,
884                                    bool                           createAnimation)
885 {
886   // Setup a Transition from TransitionData.
887   const Internal::TransitionData& transitionData = Toolkit::GetImplementation(handle);
888   TransitionData::Iterator        end            = transitionData.End();
889   for(TransitionData::Iterator iter = transitionData.Begin();
890       iter != end;
891       ++iter)
892   {
893     TransitionData::Animator* animator = (*iter);
894
895     Toolkit::Visual::Base visual = GetVisualByName(mVisuals, animator->objectName);
896
897     if(visual)
898     {
899 #if defined(DEBUG_ENABLED)
900       Dali::TypeInfo  typeInfo;
901       ControlWrapper* controlWrapperImpl = dynamic_cast<ControlWrapper*>(&mControlImpl);
902       if(controlWrapperImpl)
903       {
904         typeInfo = controlWrapperImpl->GetTypeInfo();
905       }
906
907       DALI_LOG_INFO(gLogFilter, Debug::Concise, "CreateTransition: Found %s visual for %s\n", visual.GetName().c_str(), typeInfo ? typeInfo.GetName().c_str() : "Unknown");
908 #endif
909       Internal::Visual::Base& visualImpl = Toolkit::GetImplementation(visual);
910       visualImpl.AnimateProperty(animation, *animator);
911     }
912     else
913     {
914       DALI_LOG_INFO(gLogFilter, Debug::Concise, "CreateTransition: Could not find visual. Trying actors");
915       // Otherwise, try any actor children of control (Including the control)
916       Actor child = mControlImpl.Self().FindChildByName(animator->objectName);
917       if(child)
918       {
919         Property::Index propertyIndex = child.GetPropertyIndex(animator->propertyKey);
920         if(propertyIndex != Property::INVALID_INDEX)
921         {
922           if(animator->animate == false)
923           {
924             if(animator->targetValue.GetType() != Property::NONE)
925             {
926               child.SetProperty(propertyIndex, animator->targetValue);
927             }
928           }
929           else // animate the property
930           {
931             if(animator->initialValue.GetType() != Property::NONE)
932             {
933               child.SetProperty(propertyIndex, animator->initialValue);
934             }
935
936             if(createAnimation && !animation)
937             {
938               animation = Dali::Animation::New(0.1f);
939             }
940
941             animation.AnimateTo(Property(child, propertyIndex),
942                                 animator->targetValue,
943                                 animator->alphaFunction,
944                                 TimePeriod(animator->timePeriodDelay,
945                                            animator->timePeriodDuration));
946           }
947         }
948       }
949     }
950   }
951 }
952
953 Dali::Animation Control::Impl::CreateTransition(const Toolkit::TransitionData& transitionData)
954 {
955   Dali::Animation transition;
956
957   if(transitionData.Count() > 0)
958   {
959     AddTransitions(transition, transitionData, true);
960   }
961   return transition;
962 }
963
964 void Control::Impl::DoAction(Dali::Property::Index visualIndex, Dali::Property::Index actionId, const Dali::Property::Value attributes)
965 {
966   RegisteredVisualContainer::Iterator iter;
967   if(FindVisual(visualIndex, mVisuals, iter))
968   {
969     Toolkit::GetImplementation((*iter)->visual).DoAction(actionId, attributes);
970   }
971 }
972
973 void Control::Impl::AppendAccessibilityAttribute(const std::string& key, const std::string value)
974 {
975   Property::Value* checkedValue = mAccessibilityAttributes.Find(key);
976   if(checkedValue)
977   {
978     mAccessibilityAttributes[key] = Property::Value(value);
979   }
980   else
981   {
982     mAccessibilityAttributes.Insert(key, value);
983   }
984 }
985
986 void Control::Impl::SetProperty(BaseObject* object, Property::Index index, const Property::Value& value)
987 {
988   Toolkit::Control control = Toolkit::Control::DownCast(BaseHandle(object));
989
990   if(control)
991   {
992     Control& controlImpl(GetImplementation(control));
993
994     switch(index)
995     {
996       case Toolkit::Control::Property::STYLE_NAME:
997       {
998         controlImpl.SetStyleName(value.Get<std::string>());
999         break;
1000       }
1001
1002       case Toolkit::DevelControl::Property::STATE:
1003       {
1004         bool                   withTransitions = true;
1005         const Property::Value* valuePtr        = &value;
1006         const Property::Map*   map             = value.GetMap();
1007         if(map)
1008         {
1009           Property::Value* value2 = map->Find("withTransitions");
1010           if(value2)
1011           {
1012             withTransitions = value2->Get<bool>();
1013           }
1014
1015           valuePtr = map->Find("state");
1016         }
1017
1018         if(valuePtr)
1019         {
1020           Toolkit::DevelControl::State state(controlImpl.mImpl->mState);
1021           if(Scripting::GetEnumerationProperty<Toolkit::DevelControl::State>(*valuePtr, ControlStateTable, ControlStateTableCount, state))
1022           {
1023             controlImpl.mImpl->SetState(state, withTransitions);
1024           }
1025         }
1026       }
1027       break;
1028
1029       case Toolkit::DevelControl::Property::SUB_STATE:
1030       {
1031         std::string subState;
1032         if(value.Get(subState))
1033         {
1034           controlImpl.mImpl->SetSubState(subState);
1035         }
1036       }
1037       break;
1038
1039       case Toolkit::DevelControl::Property::LEFT_FOCUSABLE_ACTOR_ID:
1040       {
1041         int focusId;
1042         if(value.Get(focusId))
1043         {
1044           controlImpl.mImpl->mLeftFocusableActorId = focusId;
1045         }
1046       }
1047       break;
1048
1049       case Toolkit::DevelControl::Property::RIGHT_FOCUSABLE_ACTOR_ID:
1050       {
1051         int focusId;
1052         if(value.Get(focusId))
1053         {
1054           controlImpl.mImpl->mRightFocusableActorId = focusId;
1055         }
1056       }
1057       break;
1058
1059       case Toolkit::DevelControl::Property::UP_FOCUSABLE_ACTOR_ID:
1060       {
1061         int focusId;
1062         if(value.Get(focusId))
1063         {
1064           controlImpl.mImpl->mUpFocusableActorId = focusId;
1065         }
1066       }
1067       break;
1068
1069       case Toolkit::DevelControl::Property::DOWN_FOCUSABLE_ACTOR_ID:
1070       {
1071         int focusId;
1072         if(value.Get(focusId))
1073         {
1074           controlImpl.mImpl->mDownFocusableActorId = focusId;
1075         }
1076       }
1077       break;
1078
1079       case Toolkit::Control::Property::KEY_INPUT_FOCUS:
1080       {
1081         if(value.Get<bool>())
1082         {
1083           controlImpl.SetKeyInputFocus();
1084         }
1085         else
1086         {
1087           controlImpl.ClearKeyInputFocus();
1088         }
1089         break;
1090       }
1091
1092       case Toolkit::Control::Property::BACKGROUND:
1093       {
1094         std::string          url;
1095         Vector4              color;
1096         const Property::Map* map = value.GetMap();
1097         if(map && !map->Empty())
1098         {
1099           controlImpl.SetBackground(*map);
1100         }
1101         else if(value.Get(url))
1102         {
1103           // don't know the size to load
1104           Toolkit::Visual::Base visual = Toolkit::VisualFactory::Get().CreateVisual(url, ImageDimensions());
1105           if(visual)
1106           {
1107             controlImpl.mImpl->RegisterVisual(Toolkit::Control::Property::BACKGROUND, visual, DepthIndex::BACKGROUND);
1108           }
1109         }
1110         else if(value.Get(color))
1111         {
1112           controlImpl.SetBackgroundColor(color);
1113         }
1114         else
1115         {
1116           // The background is an empty property map, so we should clear the background
1117           controlImpl.ClearBackground();
1118         }
1119         break;
1120       }
1121
1122       case Toolkit::Control::Property::MARGIN:
1123       {
1124         Extents margin;
1125         if(value.Get(margin))
1126         {
1127           controlImpl.mImpl->SetMargin(margin);
1128         }
1129         break;
1130       }
1131
1132       case Toolkit::Control::Property::PADDING:
1133       {
1134         Extents padding;
1135         if(value.Get(padding))
1136         {
1137           controlImpl.mImpl->SetPadding(padding);
1138         }
1139         break;
1140       }
1141
1142       case Toolkit::DevelControl::Property::TOOLTIP:
1143       {
1144         TooltipPtr& tooltipPtr = controlImpl.mImpl->mTooltip;
1145         if(!tooltipPtr)
1146         {
1147           tooltipPtr = Tooltip::New(control);
1148         }
1149         tooltipPtr->SetProperties(value);
1150         break;
1151       }
1152
1153       case Toolkit::DevelControl::Property::SHADOW:
1154       {
1155         const Property::Map* map = value.GetMap();
1156         if(map && !map->Empty())
1157         {
1158           controlImpl.mImpl->SetShadow(*map);
1159         }
1160         else
1161         {
1162           // The shadow is an empty property map, so we should clear the shadow
1163           controlImpl.mImpl->ClearShadow();
1164         }
1165         break;
1166       }
1167
1168       case Toolkit::DevelControl::Property::ACCESSIBILITY_NAME:
1169       {
1170         std::string name;
1171         if(value.Get(name))
1172         {
1173           controlImpl.mImpl->mAccessibilityName    = name;
1174           controlImpl.mImpl->mAccessibilityNameSet = true;
1175         }
1176         else
1177         {
1178           controlImpl.mImpl->mAccessibilityNameSet = false;
1179         }
1180       }
1181       break;
1182
1183       case Toolkit::DevelControl::Property::ACCESSIBILITY_DESCRIPTION:
1184       {
1185         std::string text;
1186         if(value.Get(text))
1187         {
1188           controlImpl.mImpl->mAccessibilityDescription    = text;
1189           controlImpl.mImpl->mAccessibilityDescriptionSet = true;
1190         }
1191         else
1192         {
1193           controlImpl.mImpl->mAccessibilityDescriptionSet = false;
1194         }
1195       }
1196       break;
1197
1198       case Toolkit::DevelControl::Property::ACCESSIBILITY_TRANSLATION_DOMAIN:
1199       {
1200         std::string text;
1201         if(value.Get(text))
1202         {
1203           controlImpl.mImpl->mAccessibilityTranslationDomain    = text;
1204           controlImpl.mImpl->mAccessibilityTranslationDomainSet = true;
1205         }
1206         else
1207         {
1208           controlImpl.mImpl->mAccessibilityTranslationDomainSet = false;
1209         }
1210       }
1211       break;
1212
1213       case Toolkit::DevelControl::Property::ACCESSIBILITY_ROLE:
1214       {
1215         Dali::Accessibility::Role role;
1216         if(value.Get(role))
1217         {
1218           controlImpl.mImpl->mAccessibilityRole = role;
1219         }
1220       }
1221       break;
1222
1223       case Toolkit::DevelControl::Property::ACCESSIBILITY_HIGHLIGHTABLE:
1224       {
1225         bool highlightable;
1226         if(value.Get(highlightable))
1227         {
1228           controlImpl.mImpl->mAccessibilityHighlightable    = highlightable;
1229           controlImpl.mImpl->mAccessibilityHighlightableSet = true;
1230         }
1231         else
1232         {
1233           controlImpl.mImpl->mAccessibilityHighlightableSet = false;
1234         }
1235       }
1236       break;
1237
1238       case Toolkit::DevelControl::Property::ACCESSIBILITY_ATTRIBUTES:
1239       {
1240         const Property::Map* map = value.GetMap();
1241         if(map && !map->Empty())
1242         {
1243           controlImpl.mImpl->mAccessibilityAttributes = *map;
1244         }
1245         break;
1246       }
1247     }
1248   }
1249 }
1250
1251 Property::Value Control::Impl::GetProperty(BaseObject* object, Property::Index index)
1252 {
1253   Property::Value value;
1254
1255   Toolkit::Control control = Toolkit::Control::DownCast(BaseHandle(object));
1256
1257   if(control)
1258   {
1259     Control& controlImpl(GetImplementation(control));
1260
1261     switch(index)
1262     {
1263       case Toolkit::Control::Property::STYLE_NAME:
1264       {
1265         value = controlImpl.GetStyleName();
1266         break;
1267       }
1268
1269       case Toolkit::DevelControl::Property::STATE:
1270       {
1271         value = controlImpl.mImpl->mState;
1272         break;
1273       }
1274
1275       case Toolkit::DevelControl::Property::SUB_STATE:
1276       {
1277         value = controlImpl.mImpl->mSubStateName;
1278         break;
1279       }
1280
1281       case Toolkit::DevelControl::Property::LEFT_FOCUSABLE_ACTOR_ID:
1282       {
1283         value = controlImpl.mImpl->mLeftFocusableActorId;
1284         break;
1285       }
1286
1287       case Toolkit::DevelControl::Property::RIGHT_FOCUSABLE_ACTOR_ID:
1288       {
1289         value = controlImpl.mImpl->mRightFocusableActorId;
1290         break;
1291       }
1292
1293       case Toolkit::DevelControl::Property::UP_FOCUSABLE_ACTOR_ID:
1294       {
1295         value = controlImpl.mImpl->mUpFocusableActorId;
1296         break;
1297       }
1298
1299       case Toolkit::DevelControl::Property::DOWN_FOCUSABLE_ACTOR_ID:
1300       {
1301         value = controlImpl.mImpl->mDownFocusableActorId;
1302         break;
1303       }
1304
1305       case Toolkit::Control::Property::KEY_INPUT_FOCUS:
1306       {
1307         value = controlImpl.HasKeyInputFocus();
1308         break;
1309       }
1310
1311       case Toolkit::Control::Property::BACKGROUND:
1312       {
1313         Property::Map         map;
1314         Toolkit::Visual::Base visual = controlImpl.mImpl->GetVisual(Toolkit::Control::Property::BACKGROUND);
1315         if(visual)
1316         {
1317           visual.CreatePropertyMap(map);
1318         }
1319
1320         value = map;
1321         break;
1322       }
1323
1324       case Toolkit::Control::Property::MARGIN:
1325       {
1326         value = controlImpl.mImpl->GetMargin();
1327         break;
1328       }
1329
1330       case Toolkit::Control::Property::PADDING:
1331       {
1332         value = controlImpl.mImpl->GetPadding();
1333         break;
1334       }
1335
1336       case Toolkit::DevelControl::Property::TOOLTIP:
1337       {
1338         Property::Map map;
1339         if(controlImpl.mImpl->mTooltip)
1340         {
1341           controlImpl.mImpl->mTooltip->CreatePropertyMap(map);
1342         }
1343         value = map;
1344         break;
1345       }
1346
1347       case Toolkit::DevelControl::Property::SHADOW:
1348       {
1349         Property::Map         map;
1350         Toolkit::Visual::Base visual = controlImpl.mImpl->GetVisual(Toolkit::DevelControl::Property::SHADOW);
1351         if(visual)
1352         {
1353           visual.CreatePropertyMap(map);
1354         }
1355
1356         value = map;
1357         break;
1358       }
1359
1360       case Toolkit::DevelControl::Property::ACCESSIBILITY_NAME:
1361       {
1362         if(controlImpl.mImpl->mAccessibilityNameSet)
1363         {
1364           value = controlImpl.mImpl->mAccessibilityName;
1365         }
1366         break;
1367       }
1368
1369       case Toolkit::DevelControl::Property::ACCESSIBILITY_DESCRIPTION:
1370       {
1371         if(controlImpl.mImpl->mAccessibilityDescriptionSet)
1372         {
1373           value = controlImpl.mImpl->mAccessibilityDescription;
1374         }
1375         break;
1376       }
1377
1378       case Toolkit::DevelControl::Property::ACCESSIBILITY_TRANSLATION_DOMAIN:
1379       {
1380         if(controlImpl.mImpl->mAccessibilityTranslationDomainSet)
1381         {
1382           value = controlImpl.mImpl->mAccessibilityTranslationDomain;
1383         }
1384         break;
1385       }
1386
1387       case Toolkit::DevelControl::Property::ACCESSIBILITY_ROLE:
1388       {
1389         value = Property::Value(controlImpl.mImpl->mAccessibilityRole);
1390         break;
1391       }
1392
1393       case Toolkit::DevelControl::Property::ACCESSIBILITY_HIGHLIGHTABLE:
1394       {
1395         if(controlImpl.mImpl->mAccessibilityHighlightableSet)
1396         {
1397           value = controlImpl.mImpl->mAccessibilityHighlightable;
1398         }
1399         break;
1400       }
1401
1402       case Toolkit::DevelControl::Property::ACCESSIBILITY_ATTRIBUTES:
1403       {
1404         value = controlImpl.mImpl->mAccessibilityAttributes;
1405         break;
1406       }
1407     }
1408   }
1409
1410   return value;
1411 }
1412
1413 void Control::Impl::RemoveAccessibilityAttribute(const std::string& key)
1414 {
1415   Property::Value* value = mAccessibilityAttributes.Find(key);
1416   if(value)
1417   {
1418     mAccessibilityAttributes[key] = Property::Value();
1419   }
1420 }
1421
1422 void Control::Impl::ClearAccessibilityAttributes()
1423 {
1424   mAccessibilityAttributes.Clear();
1425 }
1426
1427 void Control::Impl::SetAccessibilityReadingInfoType(const Dali::Accessibility::ReadingInfoTypes types)
1428 {
1429   std::string value{};
1430   if(types[Dali::Accessibility::ReadingInfoType::NAME])
1431   {
1432     value += READING_INFO_TYPE_NAME;
1433   }
1434   if(types[Dali::Accessibility::ReadingInfoType::ROLE])
1435   {
1436     if(!value.empty())
1437     {
1438       value += READING_INFO_TYPE_SEPARATOR;
1439     }
1440     value += READING_INFO_TYPE_ROLE;
1441   }
1442   if(types[Dali::Accessibility::ReadingInfoType::DESCRIPTION])
1443   {
1444     if(!value.empty())
1445     {
1446       value += READING_INFO_TYPE_SEPARATOR;
1447     }
1448     value += READING_INFO_TYPE_DESCRIPTION;
1449   }
1450   if(types[Dali::Accessibility::ReadingInfoType::STATE])
1451   {
1452     if(!value.empty())
1453     {
1454       value += READING_INFO_TYPE_SEPARATOR;
1455     }
1456     value += READING_INFO_TYPE_STATE;
1457   }
1458   AppendAccessibilityAttribute(READING_INFO_TYPE_ATTRIBUTE_NAME, value);
1459 }
1460
1461 Dali::Accessibility::ReadingInfoTypes Control::Impl::GetAccessibilityReadingInfoType() const
1462 {
1463   std::string value{};
1464   auto        place = mAccessibilityAttributes.Find(READING_INFO_TYPE_ATTRIBUTE_NAME);
1465   if(place)
1466   {
1467     place->Get(value);
1468   }
1469   else
1470   {
1471     Dali::Accessibility::ReadingInfoTypes types;
1472     types[Dali::Accessibility::ReadingInfoType::NAME]        = true;
1473     types[Dali::Accessibility::ReadingInfoType::ROLE]        = true;
1474     types[Dali::Accessibility::ReadingInfoType::DESCRIPTION] = true;
1475     types[Dali::Accessibility::ReadingInfoType::STATE]       = true;
1476     return types;
1477   }
1478
1479   if(value.empty())
1480   {
1481     return {};
1482   }
1483
1484   Dali::Accessibility::ReadingInfoTypes types;
1485
1486   if(value.find(READING_INFO_TYPE_NAME) != std::string::npos)
1487   {
1488     types[Dali::Accessibility::ReadingInfoType::NAME] = true;
1489   }
1490   if(value.find(READING_INFO_TYPE_ROLE) != std::string::npos)
1491   {
1492     types[Dali::Accessibility::ReadingInfoType::ROLE] = true;
1493   }
1494   if(value.find(READING_INFO_TYPE_DESCRIPTION) != std::string::npos)
1495   {
1496     types[Dali::Accessibility::ReadingInfoType::DESCRIPTION] = true;
1497   }
1498   if(value.find(READING_INFO_TYPE_STATE) != std::string::npos)
1499   {
1500     types[Dali::Accessibility::ReadingInfoType::STATE] = true;
1501   }
1502
1503   return types;
1504 }
1505
1506 void Control::Impl::CopyInstancedProperties(RegisteredVisualContainer& visuals, Dictionary<Property::Map>& instancedProperties)
1507 {
1508   for(RegisteredVisualContainer::Iterator iter = visuals.Begin(); iter != visuals.End(); iter++)
1509   {
1510     if((*iter)->visual)
1511     {
1512       Property::Map instanceMap;
1513       Toolkit::GetImplementation((*iter)->visual).CreateInstancePropertyMap(instanceMap);
1514       instancedProperties.Add((*iter)->visual.GetName(), instanceMap);
1515     }
1516   }
1517 }
1518
1519 void Control::Impl::RemoveVisual(RegisteredVisualContainer& visuals, const std::string& visualName)
1520 {
1521   Actor self(mControlImpl.Self());
1522
1523   for(RegisteredVisualContainer::Iterator visualIter = visuals.Begin();
1524       visualIter != visuals.End();
1525       ++visualIter)
1526   {
1527     Toolkit::Visual::Base visual = (*visualIter)->visual;
1528     if(visual && visual.GetName() == visualName)
1529     {
1530       Toolkit::GetImplementation(visual).SetOffScene(self);
1531       (*visualIter)->visual.Reset();
1532       visuals.Erase(visualIter);
1533       break;
1534     }
1535   }
1536 }
1537
1538 void Control::Impl::RemoveVisuals(RegisteredVisualContainer& visuals, DictionaryKeys& removeVisuals)
1539 {
1540   Actor self(mControlImpl.Self());
1541   for(DictionaryKeys::iterator iter = removeVisuals.begin(); iter != removeVisuals.end(); ++iter)
1542   {
1543     const std::string visualName = *iter;
1544     RemoveVisual(visuals, visualName);
1545   }
1546 }
1547
1548 void Control::Impl::RecreateChangedVisuals(Dictionary<Property::Map>& stateVisualsToChange,
1549                                            Dictionary<Property::Map>& instancedProperties)
1550 {
1551   Dali::CustomActor handle(mControlImpl.GetOwner());
1552   for(Dictionary<Property::Map>::iterator iter = stateVisualsToChange.Begin();
1553       iter != stateVisualsToChange.End();
1554       ++iter)
1555   {
1556     const std::string&   visualName = (*iter).key;
1557     const Property::Map& toMap      = (*iter).entry;
1558
1559     Actor                               self = mControlImpl.Self();
1560     RegisteredVisualContainer::Iterator registeredVisualsiter;
1561     // Check if visual (visualName) is already registered, this is the current visual.
1562     if(FindVisual(visualName, mVisuals, registeredVisualsiter))
1563     {
1564       Toolkit::Visual::Base& visual = (*registeredVisualsiter)->visual;
1565       if(visual)
1566       {
1567         // No longer required to know if the replaced visual's resources are ready
1568         StopObservingVisual(visual);
1569
1570         // If control staged then visuals will be swapped once ready
1571         if(self.GetProperty<bool>(Actor::Property::CONNECTED_TO_SCENE))
1572         {
1573           // Check if visual is currently in the process of being replaced ( is in removal container )
1574           RegisteredVisualContainer::Iterator visualQueuedForRemoval;
1575           if(FindVisual(visualName, mRemoveVisuals, visualQueuedForRemoval))
1576           {
1577             // Visual with same visual name is already in removal container so current visual pending
1578             // Only the the last requested visual will be displayed so remove current visual which is staged but not ready.
1579             Toolkit::GetImplementation(visual).SetOffScene(self);
1580             (*registeredVisualsiter)->visual.Reset();
1581             mVisuals.Erase(registeredVisualsiter);
1582           }
1583           else
1584           {
1585             // current visual not already in removal container so add now.
1586             DALI_LOG_INFO(gLogFilter, Debug::Verbose, "RegisterVisual Move current registered visual to removal Queue: %s \n", visualName.c_str());
1587             MoveVisual(registeredVisualsiter, mVisuals, mRemoveVisuals);
1588           }
1589         }
1590         else
1591         {
1592           // Control not staged or visual disabled so can just erase from registered visuals and new visual will be added later.
1593           (*registeredVisualsiter)->visual.Reset();
1594           mVisuals.Erase(registeredVisualsiter);
1595         }
1596       }
1597
1598       const Property::Map* instancedMap = instancedProperties.FindConst(visualName);
1599       Style::ApplyVisual(handle, visualName, toMap, instancedMap);
1600     }
1601   }
1602 }
1603
1604 void Control::Impl::ReplaceStateVisualsAndProperties(const StylePtr oldState, const StylePtr newState, const std::string& subState)
1605 {
1606   // Collect all old visual names
1607   DictionaryKeys stateVisualsToRemove;
1608   if(oldState)
1609   {
1610     oldState->visuals.GetKeys(stateVisualsToRemove);
1611     if(!subState.empty())
1612     {
1613       const StylePtr* oldSubState = oldState->subStates.FindConst(subState);
1614       if(oldSubState)
1615       {
1616         DictionaryKeys subStateVisualsToRemove;
1617         (*oldSubState)->visuals.GetKeys(subStateVisualsToRemove);
1618         Merge(stateVisualsToRemove, subStateVisualsToRemove);
1619       }
1620     }
1621   }
1622
1623   // Collect all new visual properties
1624   Dictionary<Property::Map> stateVisualsToAdd;
1625   if(newState)
1626   {
1627     stateVisualsToAdd = newState->visuals;
1628     if(!subState.empty())
1629     {
1630       const StylePtr* newSubState = newState->subStates.FindConst(subState);
1631       if(newSubState)
1632       {
1633         stateVisualsToAdd.Merge((*newSubState)->visuals);
1634       }
1635     }
1636   }
1637
1638   // If a name is in both add/remove, move it to change list.
1639   Dictionary<Property::Map> stateVisualsToChange;
1640   FindChangableVisuals(stateVisualsToAdd, stateVisualsToChange, stateVisualsToRemove);
1641
1642   // Copy instanced properties (e.g. text label) of current visuals
1643   Dictionary<Property::Map> instancedProperties;
1644   CopyInstancedProperties(mVisuals, instancedProperties);
1645
1646   // For each visual in remove list, remove from mVisuals
1647   RemoveVisuals(mVisuals, stateVisualsToRemove);
1648
1649   // For each visual in add list, create and add to mVisuals
1650   Dali::CustomActor handle(mControlImpl.GetOwner());
1651   Style::ApplyVisuals(handle, stateVisualsToAdd, instancedProperties);
1652
1653   // For each visual in change list, if it requires a new visual,
1654   // remove old visual, create and add to mVisuals
1655   RecreateChangedVisuals(stateVisualsToChange, instancedProperties);
1656 }
1657
1658 void Control::Impl::SetState(DevelControl::State newState, bool withTransitions)
1659 {
1660   DevelControl::State oldState = mState;
1661   Dali::CustomActor   handle(mControlImpl.GetOwner());
1662   DALI_LOG_INFO(gLogFilter, Debug::Concise, "Control::Impl::SetState: %s\n", (mState == DevelControl::NORMAL ? "NORMAL" : (mState == DevelControl::FOCUSED ? "FOCUSED" : (mState == DevelControl::DISABLED ? "DISABLED" : "NONE"))));
1663
1664   if(mState != newState)
1665   {
1666     // If mState was Disabled, and new state is Focused, should probably
1667     // store that fact, e.g. in another property that FocusManager can access.
1668     mState = newState;
1669
1670     // Trigger state change and transitions
1671     // Apply new style, if stylemanager is available
1672     Toolkit::StyleManager styleManager = Toolkit::StyleManager::Get();
1673     if(styleManager)
1674     {
1675       const StylePtr stylePtr = GetImpl(styleManager).GetRecordedStyle(Toolkit::Control(mControlImpl.GetOwner()));
1676
1677       if(stylePtr)
1678       {
1679         std::string oldStateName = Scripting::GetEnumerationName<Toolkit::DevelControl::State>(oldState, ControlStateTable, ControlStateTableCount);
1680         std::string newStateName = Scripting::GetEnumerationName<Toolkit::DevelControl::State>(newState, ControlStateTable, ControlStateTableCount);
1681
1682         const StylePtr* newStateStyle = stylePtr->subStates.Find(newStateName);
1683         const StylePtr* oldStateStyle = stylePtr->subStates.Find(oldStateName);
1684         if(oldStateStyle && newStateStyle)
1685         {
1686           // Only change if both state styles exist
1687           ReplaceStateVisualsAndProperties(*oldStateStyle, *newStateStyle, mSubStateName);
1688         }
1689       }
1690     }
1691   }
1692 }
1693
1694 void Control::Impl::SetSubState(const std::string& subStateName, bool withTransitions)
1695 {
1696   if(mSubStateName != subStateName)
1697   {
1698     // Get existing sub-state visuals, and unregister them
1699     Dali::CustomActor handle(mControlImpl.GetOwner());
1700
1701     Toolkit::StyleManager styleManager = Toolkit::StyleManager::Get();
1702     if(styleManager)
1703     {
1704       const StylePtr stylePtr = GetImpl(styleManager).GetRecordedStyle(Toolkit::Control(mControlImpl.GetOwner()));
1705       if(stylePtr)
1706       {
1707         // Stringify state
1708         std::string stateName = Scripting::GetEnumerationName<Toolkit::DevelControl::State>(mState, ControlStateTable, ControlStateTableCount);
1709
1710         const StylePtr* state = stylePtr->subStates.Find(stateName);
1711         if(state)
1712         {
1713           StylePtr stateStyle(*state);
1714
1715           const StylePtr* newStateStyle = stateStyle->subStates.Find(subStateName);
1716           const StylePtr* oldStateStyle = stateStyle->subStates.Find(mSubStateName);
1717           if(oldStateStyle && newStateStyle)
1718           {
1719             std::string empty;
1720             ReplaceStateVisualsAndProperties(*oldStateStyle, *newStateStyle, empty);
1721           }
1722         }
1723       }
1724     }
1725
1726     mSubStateName = subStateName;
1727   }
1728 }
1729
1730 void Control::Impl::OnSceneDisconnection()
1731 {
1732   Actor self = mControlImpl.Self();
1733
1734   // Any visuals set for replacement but not yet ready should still be registered.
1735   // Reason: If a request was made to register a new visual but the control removed from scene before visual was ready
1736   // then when this control appears back on stage it should use that new visual.
1737
1738   // Iterate through all registered visuals and set off scene
1739   SetVisualsOffScene(mVisuals, self);
1740
1741   // Visuals pending replacement can now be taken out of the removal list and set off scene
1742   // Iterate through all replacement visuals and add to a move queue then set off scene
1743   for(auto removalIter = mRemoveVisuals.Begin(), end = mRemoveVisuals.End(); removalIter != end; removalIter++)
1744   {
1745     Toolkit::GetImplementation((*removalIter)->visual).SetOffScene(self);
1746   }
1747
1748   for(auto replacedIter = mVisuals.Begin(), end = mVisuals.End(); replacedIter != end; replacedIter++)
1749   {
1750     (*replacedIter)->pending = false;
1751   }
1752
1753   mRemoveVisuals.Clear();
1754 }
1755
1756 void Control::Impl::SetMargin(Extents margin)
1757 {
1758   mControlImpl.mImpl->mMargin = margin;
1759
1760   // Trigger a size negotiation request that may be needed when setting a margin.
1761   mControlImpl.RelayoutRequest();
1762 }
1763
1764 Extents Control::Impl::GetMargin() const
1765 {
1766   return mControlImpl.mImpl->mMargin;
1767 }
1768
1769 void Control::Impl::SetPadding(Extents padding)
1770 {
1771   mControlImpl.mImpl->mPadding = padding;
1772
1773   // Trigger a size negotiation request that may be needed when setting a padding.
1774   mControlImpl.RelayoutRequest();
1775 }
1776
1777 Extents Control::Impl::GetPadding() const
1778 {
1779   return mControlImpl.mImpl->mPadding;
1780 }
1781
1782 void Control::Impl::SetInputMethodContext(InputMethodContext& inputMethodContext)
1783 {
1784   mInputMethodContext = inputMethodContext;
1785 }
1786
1787 bool Control::Impl::FilterKeyEvent(const KeyEvent& event)
1788 {
1789   bool consumed(false);
1790
1791   if(mInputMethodContext)
1792   {
1793     consumed = mInputMethodContext.FilterEventKey(event);
1794   }
1795   return consumed;
1796 }
1797
1798 DevelControl::VisualEventSignalType& Control::Impl::VisualEventSignal()
1799 {
1800   return mVisualEventSignal;
1801 }
1802
1803 void Control::Impl::SetShadow(const Property::Map& map)
1804 {
1805   Toolkit::Visual::Base visual = Toolkit::VisualFactory::Get().CreateVisual(map);
1806   visual.SetName("shadow");
1807
1808   if(visual)
1809   {
1810     mControlImpl.mImpl->RegisterVisual(Toolkit::DevelControl::Property::SHADOW, visual, DepthIndex::BACKGROUND_EFFECT);
1811
1812     mControlImpl.RelayoutRequest();
1813   }
1814 }
1815
1816 void Control::Impl::ClearShadow()
1817 {
1818   mControlImpl.mImpl->UnregisterVisual(Toolkit::DevelControl::Property::SHADOW);
1819
1820   // Trigger a size negotiation request that may be needed when unregistering a visual.
1821   mControlImpl.RelayoutRequest();
1822 }
1823
1824 Dali::Property Control::Impl::GetVisualProperty(Dali::Property::Index index, Dali::Property::Key visualPropertyKey)
1825 {
1826   Toolkit::Visual::Base visual = GetVisualByIndex(mVisuals, index);
1827   if(visual)
1828   {
1829     Internal::Visual::Base& visualImpl = Toolkit::GetImplementation(visual);
1830     return visualImpl.GetPropertyObject(visualPropertyKey);
1831   }
1832
1833   Handle handle;
1834   return Dali::Property(handle, Property::INVALID_INDEX);
1835 }
1836
1837 void Control::Impl::MakeVisualTransition(Dali::Animation& animation, Dali::Toolkit::Control source, Dali::Property::Index visualIndex, AlphaFunction alphaFunction, TimePeriod timePeriod)
1838 {
1839   Dali::Toolkit::Control sourceHandle      = Dali::Toolkit::Control::DownCast(source);
1840   Property::Map          sourceMap         = sourceHandle.GetProperty<Property::Map>(visualIndex);
1841   Dali::Toolkit::Control destinationHandle = Dali::Toolkit::Control::DownCast(mControlImpl.Self());
1842   Property::Map          destinationMap    = destinationHandle.GetProperty<Property::Map>(visualIndex);
1843
1844   Vector4 mixColor(1.0f, 1.0f, 1.0f, 1.0f);
1845   Vector4 cornerRadius(0.0f, 0.0f, 0.0f, 0.0f);
1846   float   borderlineWidth(0.0f);
1847   Vector4 borderlineColor(0.0f, 0.0f, 0.0f, 1.0f);
1848   float   borderlineOffset(0.0f);
1849
1850   if(!destinationMap.Empty())
1851   {
1852     static auto findValueVector4 = [](const Property::Map& map, Property::Index index, const Vector4& defaultValue = Vector4()) -> Vector4 {
1853       Property::Value* propertyValue = map.Find(index);
1854       if(propertyValue)
1855       {
1856         return propertyValue->Get<Vector4>();
1857       }
1858       return defaultValue;
1859     };
1860
1861     static auto findValueFloat = [](const Property::Map& map, Property::Index index, const float& defaultValue = 0.0f) -> float {
1862       Property::Value* propertyValue = map.Find(index);
1863       if(propertyValue)
1864       {
1865         return propertyValue->Get<float>();
1866       }
1867       return defaultValue;
1868     };
1869
1870     mixColor         = findValueVector4(destinationMap, Dali::Toolkit::Visual::Property::MIX_COLOR, mixColor);
1871     cornerRadius     = findValueVector4(destinationMap, Toolkit::DevelVisual::Property::CORNER_RADIUS, cornerRadius);
1872     borderlineWidth  = findValueFloat(destinationMap, Toolkit::DevelVisual::Property::BORDERLINE_WIDTH, borderlineWidth);
1873     borderlineColor  = findValueVector4(destinationMap, Toolkit::DevelVisual::Property::BORDERLINE_COLOR, borderlineColor);
1874     borderlineOffset = findValueFloat(destinationMap, Toolkit::DevelVisual::Property::BORDERLINE_OFFSET, borderlineOffset);
1875
1876     if(sourceMap.Empty())
1877     {
1878       sourceMap.Insert(Toolkit::Visual::Property::TYPE, Toolkit::Visual::COLOR);
1879       sourceMap.Insert(Dali::Toolkit::Visual::Property::MIX_COLOR, Color::TRANSPARENT);
1880       sourceMap.Insert(Toolkit::DevelVisual::Property::CORNER_RADIUS, cornerRadius);
1881       sourceMap.Insert(Toolkit::DevelVisual::Property::BORDERLINE_WIDTH, borderlineWidth);
1882       sourceMap.Insert(Toolkit::DevelVisual::Property::BORDERLINE_COLOR, borderlineColor);
1883       sourceMap.Insert(Toolkit::DevelVisual::Property::BORDERLINE_OFFSET, borderlineOffset);
1884     }
1885
1886     Vector4 sourceMixColor         = findValueVector4(sourceMap, Dali::Toolkit::Visual::Property::MIX_COLOR, mixColor);
1887     Vector4 sourceCornerRadius     = findValueVector4(sourceMap, Toolkit::DevelVisual::Property::CORNER_RADIUS, cornerRadius);
1888     float   sourceBorderlineWidth  = findValueFloat(sourceMap, Toolkit::DevelVisual::Property::BORDERLINE_WIDTH, borderlineWidth);
1889     Vector4 sourceBorderlineColor  = findValueVector4(sourceMap, Toolkit::DevelVisual::Property::BORDERLINE_COLOR, borderlineColor);
1890     float   sourceBorderlineOffset = findValueFloat(sourceMap, Toolkit::DevelVisual::Property::BORDERLINE_OFFSET, borderlineOffset);
1891
1892     std::vector<Dali::Property>                              properties;
1893     std::vector<std::pair<Property::Value, Property::Value>> values;
1894
1895     if(Vector3(sourceMixColor) != Vector3(mixColor))
1896     {
1897       properties.push_back(GetVisualProperty(visualIndex, Dali::Toolkit::Visual::Property::MIX_COLOR));
1898       values.push_back(std::make_pair(Vector3(sourceMixColor), Vector3(mixColor)));
1899     }
1900
1901     if(std::abs(sourceMixColor.a - mixColor.a) > Math::MACHINE_EPSILON_1)
1902     {
1903       properties.push_back(GetVisualProperty(visualIndex, Dali::Toolkit::Visual::Property::OPACITY));
1904       values.push_back(std::make_pair(sourceMixColor.a, mixColor.a));
1905     }
1906
1907     if(sourceCornerRadius != cornerRadius)
1908     {
1909       properties.push_back(GetVisualProperty(visualIndex, Dali::Toolkit::DevelVisual::Property::CORNER_RADIUS));
1910       values.push_back(std::make_pair(sourceCornerRadius, cornerRadius));
1911     }
1912
1913     if(sourceBorderlineWidth != borderlineWidth)
1914     {
1915       properties.push_back(GetVisualProperty(visualIndex, Dali::Toolkit::DevelVisual::Property::BORDERLINE_WIDTH));
1916       values.push_back(std::make_pair(sourceBorderlineWidth, borderlineWidth));
1917     }
1918
1919     if(sourceBorderlineColor != borderlineColor)
1920     {
1921       properties.push_back(GetVisualProperty(visualIndex, Dali::Toolkit::DevelVisual::Property::BORDERLINE_COLOR));
1922       values.push_back(std::make_pair(sourceBorderlineColor, borderlineColor));
1923     }
1924
1925     if(sourceBorderlineOffset != borderlineOffset)
1926     {
1927       properties.push_back(GetVisualProperty(visualIndex, Dali::Toolkit::DevelVisual::Property::BORDERLINE_OFFSET));
1928       values.push_back(std::make_pair(sourceBorderlineOffset, borderlineOffset));
1929     }
1930
1931     for(uint32_t i = 0; i < properties.size(); ++i)
1932     {
1933       if(timePeriod.delaySeconds > 0.0f)
1934       {
1935         Dali::KeyFrames initialKeyframes = Dali::KeyFrames::New();
1936         initialKeyframes.Add(0.0f, values[i].first);
1937         initialKeyframes.Add(1.0f, values[i].first);
1938         animation.AnimateBetween(properties[i], initialKeyframes, TimePeriod(timePeriod.delaySeconds));
1939       }
1940       Dali::KeyFrames keyframes = Dali::KeyFrames::New();
1941       keyframes.Add(0.0f, values[i].first);
1942       keyframes.Add(1.0f, values[i].second);
1943       animation.AnimateBetween(properties[i], keyframes, alphaFunction, timePeriod);
1944     }
1945   }
1946 }
1947
1948 void Control::Impl::EmitResourceReadySignal()
1949 {
1950   if(!mIsEmittingResourceReadySignal)
1951   {
1952     // Guard against calls to emit the signal during the callback
1953     mIsEmittingResourceReadySignal = true;
1954
1955     // If the signal handler changes visual, it may become ready during this call & therefore this method will
1956     // get called again recursively. If so, mNeedToEmitResourceReady is set below, and we act on it after that secondary
1957     // invocation has completed by notifying in an Idle callback to prevent further recursion.
1958     Dali::Toolkit::Control handle(mControlImpl.GetOwner());
1959     mResourceReadySignal.Emit(handle);
1960
1961     if(mNeedToEmitResourceReady)
1962     {
1963       // Add idler to emit the signal again
1964       if(!mIdleCallback)
1965       {
1966         // The callback manager takes the ownership of the callback object.
1967         mIdleCallback = MakeCallback(this, &Control::Impl::OnIdleCallback);
1968         Adaptor::Get().AddIdle(mIdleCallback, false);
1969       }
1970     }
1971
1972     mIsEmittingResourceReadySignal = false;
1973   }
1974   else
1975   {
1976     mNeedToEmitResourceReady = true;
1977   }
1978 }
1979
1980 void Control::Impl::OnIdleCallback()
1981 {
1982   if(mNeedToEmitResourceReady)
1983   {
1984     // Reset the flag
1985     mNeedToEmitResourceReady = false;
1986
1987     // A visual is ready so control may need relayouting if staged
1988     if(mControlImpl.Self().GetProperty<bool>(Actor::Property::CONNECTED_TO_SCENE))
1989     {
1990       mControlImpl.RelayoutRequest();
1991     }
1992
1993     EmitResourceReadySignal();
1994   }
1995
1996   // Set the pointer to null as the callback manager deletes the callback after execute it.
1997   mIdleCallback = nullptr;
1998 }
1999
2000 Dali::Accessibility::Accessible* Control::Impl::GetAccessibilityObject()
2001 {
2002   if(!mAccessibilityObject)
2003   {
2004     mAccessibilityObject = mAccessibilityConstructor(mControlImpl.Self());
2005   }
2006   return mAccessibilityObject.get();
2007 }
2008
2009 Dali::Accessibility::Accessible* Control::Impl::GetAccessibilityObject(Dali::Actor actor)
2010 {
2011   if(actor)
2012   {
2013     auto control = Dali::Toolkit::Control::DownCast(actor);
2014     if(control)
2015     {
2016       auto controlImpl = static_cast<Internal::Control*>(&control.GetImplementation());
2017       return controlImpl->mImpl->GetAccessibilityObject();
2018     }
2019   }
2020   return nullptr;
2021 }
2022
2023 } // namespace Internal
2024
2025 } // namespace Toolkit
2026
2027 } // namespace Dali