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