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