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