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