2 * Copyright (c) 2022 Samsung Electronics Co., Ltd.
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
8 * http://www.apache.org/licenses/LICENSE-2.0
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.
19 #include "control-data-impl.h"
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>
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>
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 = "|";
68 extern const Dali::Scripting::StringEnum ControlStateTable[];
69 extern const unsigned int ControlStateTableCount;
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},
77 const unsigned int ControlStateTableCount = sizeof(ControlStateTable) / sizeof(ControlStateTable[0]);
81 #if defined(DEBUG_ENABLED)
82 Debug::Filter* gLogFilter = Debug::Filter::New(Debug::NoLogging, false, "LOG_CONTROL_VISUALS");
86 void Remove(Dictionary<T>& keyValues, const std::string& name)
88 keyValues.Remove(name);
91 void Remove(DictionaryKeys& keys, const std::string& name)
93 DictionaryKeys::iterator iter = std::find(keys.begin(), keys.end(), name);
94 if(iter != keys.end())
101 * Finds visual in given array, returning true if found along with the iterator for that visual as a out parameter
103 bool FindVisual(Property::Index targetIndex, const RegisteredVisualContainer& visuals, RegisteredVisualContainer::Iterator& iter)
105 for(iter = visuals.Begin(); iter != visuals.End(); iter++)
107 if((*iter)->index == targetIndex)
116 * Finds visual in given array, returning true if found along with the iterator for that visual as a out parameter
118 bool FindVisual(std::string visualName, const RegisteredVisualContainer& visuals, RegisteredVisualContainer::Iterator& iter)
120 for(iter = visuals.Begin(); iter != visuals.End(); iter++)
122 Toolkit::Visual::Base visual = (*iter)->visual;
123 if(visual && visual.GetName() == visualName)
131 void FindChangableVisuals(Dictionary<Property::Map>& stateVisualsToAdd,
132 Dictionary<Property::Map>& stateVisualsToChange,
133 DictionaryKeys& stateVisualsToRemove)
135 DictionaryKeys copyOfStateVisualsToRemove = stateVisualsToRemove;
137 for(DictionaryKeys::iterator iter = copyOfStateVisualsToRemove.begin();
138 iter != copyOfStateVisualsToRemove.end();
141 const std::string& visualName = (*iter);
142 Property::Map* toMap = stateVisualsToAdd.Find(visualName);
145 stateVisualsToChange.Add(visualName, *toMap);
146 stateVisualsToAdd.Remove(visualName);
147 Remove(stateVisualsToRemove, visualName);
152 Toolkit::Visual::Base GetVisualByName(
153 const RegisteredVisualContainer& visuals,
154 const std::string& visualName)
156 Toolkit::Visual::Base visualHandle;
158 RegisteredVisualContainer::Iterator iter;
159 for(iter = visuals.Begin(); iter != visuals.End(); iter++)
161 Toolkit::Visual::Base visual = (*iter)->visual;
162 if(visual && visual.GetName() == visualName)
164 visualHandle = visual;
171 Toolkit::Visual::Base GetVisualByIndex(
172 const RegisteredVisualContainer& visuals,
173 Property::Index index)
175 Toolkit::Visual::Base visualHandle;
177 RegisteredVisualContainer::Iterator iter;
178 for(iter = visuals.Begin(); iter != visuals.End(); iter++)
180 if((*iter)->index == index)
182 visualHandle = (*iter)->visual;
190 * Move visual from source to destination container
192 void MoveVisual(RegisteredVisualContainer::Iterator sourceIter, RegisteredVisualContainer& source, RegisteredVisualContainer& destination)
194 Toolkit::Visual::Base visual = (*sourceIter)->visual;
197 RegisteredVisual* rv = source.Release(sourceIter);
198 destination.PushBack(rv);
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
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";
216 static bool DoAction(BaseObject* object, const std::string& actionName, const Property::Map& attributes)
220 Dali::BaseHandle handle(object);
222 Toolkit::Control control = Toolkit::Control::DownCast(handle);
224 DALI_ASSERT_ALWAYS(control);
226 if(0 == strcmp(actionName.c_str(), ACTION_ACCESSIBILITY_ACTIVATED) || actionName == "activate")
228 // if cast succeeds there is an implementation so no need to check
229 if(!DevelControl::AccessibilityActivateSignal(control).Empty())
231 DevelControl::AccessibilityActivateSignal(control).Emit();
235 ret = Internal::GetImplementation(control).OnAccessibilityActivated();
238 else if(0 == strcmp(actionName.c_str(), ACTION_ACCESSIBILITY_READING_SKIPPED))
240 // if cast succeeds there is an implementation so no need to check
241 if(!DevelControl::AccessibilityReadingSkippedSignal(control).Empty())
243 DevelControl::AccessibilityReadingSkippedSignal(control).Emit();
246 else if(0 == strcmp(actionName.c_str(), ACTION_ACCESSIBILITY_READING_PAUSED))
248 // if cast succeeds there is an implementation so no need to check
249 if(!DevelControl::AccessibilityReadingPausedSignal(control).Empty())
251 DevelControl::AccessibilityReadingPausedSignal(control).Emit();
254 else if(0 == strcmp(actionName.c_str(), ACTION_ACCESSIBILITY_READING_RESUMED))
256 // if cast succeeds there is an implementation so no need to check
257 if(!DevelControl::AccessibilityReadingResumedSignal(control).Empty())
259 DevelControl::AccessibilityReadingResumedSignal(control).Emit();
262 else if(0 == strcmp(actionName.c_str(), ACTION_ACCESSIBILITY_READING_CANCELLED))
264 // if cast succeeds there is an implementation so no need to check
265 if(!DevelControl::AccessibilityReadingCancelledSignal(control).Empty())
267 DevelControl::AccessibilityReadingCancelledSignal(control).Emit();
270 else if(0 == strcmp(actionName.c_str(), ACTION_ACCESSIBILITY_READING_STOPPED))
272 // if cast succeeds there is an implementation so no need to check
273 if(!DevelControl::AccessibilityReadingStoppedSignal(control).Empty())
275 DevelControl::AccessibilityReadingStoppedSignal(control).Emit();
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.
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)
306 Dali::BaseHandle handle(object);
308 bool connected(false);
309 Toolkit::Control control = Toolkit::Control::DownCast(handle);
312 Internal::Control& controlImpl(Internal::GetImplementation(control));
315 if(0 == strcmp(signalName.c_str(), SIGNAL_KEY_EVENT))
317 controlImpl.KeyEventSignal().Connect(tracker, functor);
319 else if(0 == strcmp(signalName.c_str(), SIGNAL_KEY_INPUT_FOCUS_GAINED))
321 controlImpl.KeyInputFocusGainedSignal().Connect(tracker, functor);
323 else if(0 == strcmp(signalName.c_str(), SIGNAL_KEY_INPUT_FOCUS_LOST))
325 controlImpl.KeyInputFocusLostSignal().Connect(tracker, functor);
327 else if(0 == strcmp(signalName.c_str(), SIGNAL_TAPPED))
329 controlImpl.EnableGestureDetection(GestureType::TAP);
330 controlImpl.GetTapGestureDetector().DetectedSignal().Connect(tracker, functor);
332 else if(0 == strcmp(signalName.c_str(), SIGNAL_PANNED))
334 controlImpl.EnableGestureDetection(GestureType::PAN);
335 controlImpl.GetPanGestureDetector().DetectedSignal().Connect(tracker, functor);
337 else if(0 == strcmp(signalName.c_str(), SIGNAL_PINCHED))
339 controlImpl.EnableGestureDetection(GestureType::PINCH);
340 controlImpl.GetPinchGestureDetector().DetectedSignal().Connect(tracker, functor);
342 else if(0 == strcmp(signalName.c_str(), SIGNAL_LONG_PRESSED))
344 controlImpl.EnableGestureDetection(GestureType::LONG_PRESS);
345 controlImpl.GetLongPressGestureDetector().DetectedSignal().Connect(tracker, functor);
347 else if(0 == strcmp(signalName.c_str(), SIGNAL_GET_NAME))
349 DevelControl::AccessibilityGetNameSignal(control).Connect(tracker, functor);
351 else if(0 == strcmp(signalName.c_str(), SIGNAL_GET_DESCRIPTION))
353 DevelControl::AccessibilityGetDescriptionSignal(control).Connect(tracker, functor);
355 else if(0 == strcmp(signalName.c_str(), SIGNAL_DO_GESTURE))
357 DevelControl::AccessibilityDoGestureSignal(control).Connect(tracker, functor);
364 * Creates control through type registry
368 return Internal::Control::New();
370 // Setup signals and actions using the type-registry.
371 DALI_TYPE_REGISTRATION_BEGIN(Control, CustomActor, Create);
373 // Note: Properties are registered separately below.
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);
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);
394 DALI_TYPE_REGISTRATION_END()
397 * @brief Iterate through given container and setOffScene any visual found
399 * @param[in] container Container of visuals
400 * @param[in] parent Parent actor to remove visuals from
402 void SetVisualsOffScene(const RegisteredVisualContainer& container, Actor parent)
404 for(auto iter = container.Begin(), end = container.End(); iter != end; iter++)
408 DALI_LOG_INFO(gLogFilter, Debug::Verbose, "Control::SetOffScene Setting visual(%d) off stage\n", (*iter)->index);
409 Toolkit::GetImplementation((*iter)->visual).SetOffScene(parent);
414 Dali::Rect<> GetShowingGeometry(Dali::Rect<> rect, Dali::Toolkit::DevelControl::ControlAccessible* accessible)
417 Vector2 currentPosition;
418 auto parent = dynamic_cast<Toolkit::DevelControl::ControlAccessible*>(accessible->GetParent());
422 parentRect = parent->GetExtents(Dali::Accessibility::CoordinateType::WINDOW);
424 currentPosition.x = rect.x;
425 currentPosition.y = rect.y;
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;
432 if(rect.width < 0 || rect.height < 0)
437 parent = dynamic_cast<Toolkit::DevelControl::ControlAccessible*>(parent->GetParent());
443 static bool IsShowingGeometryOnScreen(Dali::Rect<> rect)
445 return rect.width > 0 && rect.height > 0;
448 Dali::Accessibility::Accessible* ExternalAccessibleGetter(Dali::Actor actor)
450 auto control = Toolkit::Control::DownCast(actor);
456 auto& controlImpl = Toolkit::Internal::GetImplementation(control);
458 return controlImpl.GetAccessibleObject();
461 } // unnamed namespace
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);
491 Control::Impl::Impl(Control& controlImpl)
492 : mControlImpl(controlImpl),
493 mState(Toolkit::DevelControl::NORMAL),
495 mLeftFocusableActorId(-1),
496 mRightFocusableActorId(-1),
497 mUpFocusableActorId(-1),
498 mDownFocusableActorId(-1),
499 mClockwiseFocusableActorId(-1),
500 mCounterClockwiseFocusableActorId(-1),
502 mBackgroundColor(Color::TRANSPARENT),
503 mStartingPinchScale(nullptr),
505 mPadding(0, 0, 0, 0),
507 mKeyInputFocusGainedSignal(),
508 mKeyInputFocusLostSignal(),
509 mResourceReadySignal(),
510 mVisualEventSignal(),
511 mAccessibilityGetNameSignal(),
512 mAccessibilityGetDescriptionSignal(),
513 mAccessibilityDoGestureSignal(),
514 mPinchGestureDetector(),
515 mPanGestureDetector(),
516 mTapGestureDetector(),
517 mLongPressGestureDetector(),
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)
528 Dali::Accessibility::Accessible::RegisterExternalAccessibleGetter(&ExternalAccessibleGetter);
531 Control::Impl::~Impl()
533 for(auto&& iter : mVisuals)
535 StopObservingVisual(iter->visual);
538 for(auto&& iter : mRemoveVisuals)
540 StopObservingVisual(iter->visual);
543 // All gesture detectors will be destroyed so no need to disconnect.
544 delete mStartingPinchScale;
546 if(mIdleCallback && Adaptor::IsAvailable())
548 // Removes the callback from the callback manager in case the control is destroyed before the callback is executed.
549 Adaptor::Get().RemoveIdle(mIdleCallback);
553 Control::Impl& Control::Impl::Get(Internal::Control& internalControl)
555 return *internalControl.mImpl;
558 const Control::Impl& Control::Impl::Get(const Internal::Control& internalControl)
560 return *internalControl.mImpl;
563 void Control::Impl::CheckHighlightedObjectGeometry()
565 auto accessible = GetAccessibleObject();
566 auto lastPosition = accessible->GetLastPosition();
567 auto accessibleRect = accessible->GetExtents(Dali::Accessibility::CoordinateType::WINDOW);
568 auto rect = GetShowingGeometry(accessibleRect, accessible);
570 switch(mAccessibilityLastScreenRelativeMoveType)
572 case Dali::Accessibility::ScreenRelativeMoveType::OUTSIDE:
574 if(IsShowingGeometryOnScreen(rect))
576 mAccessibilityLastScreenRelativeMoveType = Dali::Accessibility::ScreenRelativeMoveType::INSIDE;
580 case Dali::Accessibility::ScreenRelativeMoveType::INSIDE:
582 if(rect.width < 0 && accessibleRect.x != lastPosition.x)
584 mAccessibilityLastScreenRelativeMoveType = (accessibleRect.x < lastPosition.x) ? Dali::Accessibility::ScreenRelativeMoveType::OUTGOING_TOP_LEFT : Dali::Accessibility::ScreenRelativeMoveType::OUTGOING_BOTTOM_RIGHT;
586 if(rect.height < 0 && accessibleRect.y != lastPosition.y)
588 mAccessibilityLastScreenRelativeMoveType = (accessibleRect.y < lastPosition.y) ? Dali::Accessibility::ScreenRelativeMoveType::OUTGOING_TOP_LEFT : Dali::Accessibility::ScreenRelativeMoveType::OUTGOING_BOTTOM_RIGHT;
590 // notify AT-clients on outgoing moves only
591 if(mAccessibilityLastScreenRelativeMoveType != Dali::Accessibility::ScreenRelativeMoveType::INSIDE)
593 accessible->EmitMovedOutOfScreen(mAccessibilityLastScreenRelativeMoveType);
597 case Dali::Accessibility::ScreenRelativeMoveType::OUTGOING_TOP_LEFT:
598 case Dali::Accessibility::ScreenRelativeMoveType::OUTGOING_BOTTOM_RIGHT:
600 if(IsShowingGeometryOnScreen(rect))
602 mAccessibilityLastScreenRelativeMoveType = Dali::Accessibility::ScreenRelativeMoveType::INSIDE;
606 mAccessibilityLastScreenRelativeMoveType = Dali::Accessibility::ScreenRelativeMoveType::OUTSIDE;
616 accessible->SetLastPosition(Vector2(accessibleRect.x, accessibleRect.y));
619 void Control::Impl::RegisterAccessibilityPositionPropertyNotification()
621 if(mIsAccessibilityPositionPropertyNotificationSet)
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;
635 void Control::Impl::UnregisterAccessibilityPositionPropertyNotification()
637 mControlImpl.Self().RemovePropertyNotification(mAccessibilityPositionNotification);
638 mIsAccessibilityPositionPropertyNotificationSet = false;
641 // Gesture Detection Methods
642 void Control::Impl::PinchDetected(Actor actor, const PinchGesture& pinch)
644 mControlImpl.OnPinch(pinch);
647 void Control::Impl::PanDetected(Actor actor, const PanGesture& pan)
649 mControlImpl.OnPan(pan);
652 void Control::Impl::TapDetected(Actor actor, const TapGesture& tap)
654 mControlImpl.OnTap(tap);
657 void Control::Impl::LongPressDetected(Actor actor, const LongPressGesture& longPress)
659 mControlImpl.OnLongPress(longPress);
662 void Control::Impl::RegisterVisual(Property::Index index, Toolkit::Visual::Base& visual)
664 RegisterVisual(index, visual, VisualState::ENABLED, DepthIndexValue::NOT_SET);
667 void Control::Impl::RegisterVisual(Property::Index index, Toolkit::Visual::Base& visual, int depthIndex)
669 RegisterVisual(index, visual, VisualState::ENABLED, DepthIndexValue::SET, depthIndex);
672 void Control::Impl::RegisterVisual(Property::Index index, Toolkit::Visual::Base& visual, bool enabled)
674 RegisterVisual(index, visual, (enabled ? VisualState::ENABLED : VisualState::DISABLED), DepthIndexValue::NOT_SET);
677 void Control::Impl::RegisterVisual(Property::Index index, Toolkit::Visual::Base& visual, bool enabled, int depthIndex)
679 RegisterVisual(index, visual, (enabled ? VisualState::ENABLED : VisualState::DISABLED), DepthIndexValue::SET, depthIndex);
682 void Control::Impl::RegisterVisual(Property::Index index, Toolkit::Visual::Base& visual, VisualState::Type enabled, DepthIndexValue::Type depthIndexValueSet, int depthIndex)
684 DALI_LOG_INFO(gLogFilter, Debug::Concise, "RegisterVisual:%d \n", index);
686 bool visualReplaced(false);
687 Actor self = mControlImpl.Self();
689 // Set the depth index, if not set by caller this will be either the current visual depth, max depth of all visuals
691 int requiredDepthIndex = visual.GetDepthIndex();
693 if(depthIndexValueSet == DepthIndexValue::SET)
695 requiredDepthIndex = depthIndex;
698 // Visual replacement, existing visual should only be removed from stage when replacement ready.
699 if(!mVisuals.Empty())
701 RegisteredVisualContainer::Iterator registeredVisualsiter;
702 // Check if visual (index) is already registered, this is the current visual.
703 if(FindVisual(index, mVisuals, registeredVisualsiter))
705 Toolkit::Visual::Base& currentRegisteredVisual = (*registeredVisualsiter)->visual;
706 if(currentRegisteredVisual)
708 // Store current visual depth index as may need to set the replacement visual to same depth
709 const int currentDepthIndex = (*registeredVisualsiter)->visual.GetDepthIndex();
711 // No longer required to know if the replaced visual's resources are ready
712 StopObservingVisual(currentRegisteredVisual);
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)
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))
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);
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);
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);
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))
743 requiredDepthIndex = currentDepthIndex;
747 visualReplaced = true;
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())
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())
759 DALI_LOG_INFO(gLogFilter, Debug::Concise, "Setting visual name for property %d to %s\n", index, visualName.c_str());
760 visual.SetName(visualName);
764 if(!visualReplaced) // New registration entry
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))
771 int maxDepthIndex = std::numeric_limits<int>::min();
773 RegisteredVisualContainer::ConstIterator iter;
774 const RegisteredVisualContainer::ConstIterator endIter = mVisuals.End();
775 for(iter = mVisuals.Begin(); iter != endIter; iter++)
777 const int visualDepthIndex = (*iter)->visual.GetDepthIndex();
778 if(visualDepthIndex > maxDepthIndex)
780 maxDepthIndex = visualDepthIndex;
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
790 // Set determined depth index
791 visual.SetDepthIndex(requiredDepthIndex);
793 // Monitor when the visual resources are ready
794 StartObservingVisual(visual);
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);
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))
804 visualImpl.SetOnScene(self);
806 else if(visualImpl.IsResourceReady()) // When not being staged, check if visual already 'ResourceReady' before it was Registered. ( Resource may have been loaded already )
808 ResourceReady(visualImpl);
812 DALI_LOG_INFO(gLogFilter, Debug::Verbose, "Control::RegisterVisual() Registered %s(%d), enabled:%s\n", visual.GetName().c_str(), index, enabled ? "true" : "false");
815 void Control::Impl::UnregisterVisual(Property::Index index)
817 RegisteredVisualContainer::Iterator iter;
818 if(FindVisual(index, mVisuals, iter))
820 // stop observing visual
821 StopObservingVisual((*iter)->visual);
823 Actor self(mControlImpl.Self());
824 Toolkit::GetImplementation((*iter)->visual).SetOffScene(self);
825 (*iter)->visual.Reset();
826 mVisuals.Erase(iter);
829 if(FindVisual(index, mRemoveVisuals, iter))
831 Actor self(mControlImpl.Self());
832 Toolkit::GetImplementation((*iter)->visual).SetOffScene(self);
833 (*iter)->pending = false;
834 (*iter)->visual.Reset();
835 mRemoveVisuals.Erase(iter);
839 Toolkit::Visual::Base Control::Impl::GetVisual(Property::Index index) const
841 RegisteredVisualContainer::Iterator iter;
842 if(FindVisual(index, mVisuals, iter))
844 return (*iter)->visual;
847 return Toolkit::Visual::Base();
850 void Control::Impl::EnableVisual(Property::Index index, bool enable)
852 DALI_LOG_INFO(gLogFilter, Debug::General, "Control::EnableVisual(%d, %s)\n", index, enable ? "T" : "F");
854 RegisteredVisualContainer::Iterator iter;
855 if(FindVisual(index, mVisuals, iter))
857 if((*iter)->enabled == enable)
859 DALI_LOG_INFO(gLogFilter, Debug::Verbose, "Control::EnableVisual Visual %s(%d) already %s\n", (*iter)->visual.GetName().c_str(), index, enable ? "enabled" : "disabled");
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.
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);
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.
881 DALI_LOG_WARNING("Control::EnableVisual(%d, %s) FAILED - NO SUCH VISUAL\n", index, enable ? "T" : "F");
885 bool Control::Impl::IsVisualEnabled(Property::Index index) const
887 RegisteredVisualContainer::Iterator iter;
888 if(FindVisual(index, mVisuals, iter))
890 return (*iter)->enabled;
895 void Control::Impl::StopObservingVisual(Toolkit::Visual::Base& visual)
897 Internal::Visual::Base& visualImpl = Toolkit::GetImplementation(visual);
899 // Stop observing the visual
900 visualImpl.RemoveEventObserver(*this);
903 void Control::Impl::StartObservingVisual(Toolkit::Visual::Base& visual)
905 Internal::Visual::Base& visualImpl = Toolkit::GetImplementation(visual);
907 // start observing the visual for events
908 visualImpl.AddEventObserver(*this);
911 // Called by a Visual when it's resource is ready
912 void Control::Impl::ResourceReady(Visual::Base& object)
914 DALI_LOG_INFO(gLogFilter, Debug::Verbose, "Control::Impl::ResourceReady() replacements pending[%d]\n", mRemoveVisuals.Count());
916 Actor self = mControlImpl.Self();
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)
921 Internal::Visual::Base& registeredVisualImpl = Toolkit::GetImplementation((*registeredIter)->visual);
923 if(&object == ®isteredVisualImpl)
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))
932 (*registeredIter)->pending = false;
933 Toolkit::GetImplementation((*visualToRemoveIter)->visual).SetOffScene(self);
934 mRemoveVisuals.Erase(visualToRemoveIter);
940 // A visual is ready so control may need relayouting if staged
941 if(self.GetProperty<bool>(Actor::Property::CONNECTED_TO_SCENE))
943 mControlImpl.RelayoutRequest();
946 // Emit signal if all enabled visuals registered by the control are ready.
947 if(IsResourceReady())
950 mNeedToEmitResourceReady = false;
952 EmitResourceReadySignal();
956 void Control::Impl::NotifyVisualEvent(Visual::Base& object, Property::Index signalId)
958 for(auto registeredIter = mVisuals.Begin(), end = mVisuals.End(); registeredIter != end; ++registeredIter)
960 Internal::Visual::Base& registeredVisualImpl = Toolkit::GetImplementation((*registeredIter)->visual);
961 if(&object == ®isteredVisualImpl)
963 Dali::Toolkit::Control handle(mControlImpl.GetOwner());
964 mVisualEventSignal.Emit(handle, (*registeredIter)->index, signalId);
970 void Control::Impl::RelayoutRequest(Visual::Base& object)
972 mControlImpl.RelayoutRequest();
975 bool Control::Impl::IsResourceReady() const
977 // Iterate through and check all the enabled visuals are ready
978 for(auto visualIter = mVisuals.Begin();
979 visualIter != mVisuals.End();
982 const Toolkit::Visual::Base visual = (*visualIter)->visual;
983 const Internal::Visual::Base& visualImpl = Toolkit::GetImplementation(visual);
985 // one of the enabled visuals is not ready
986 if(!visualImpl.IsResourceReady() && (*visualIter)->enabled)
994 Toolkit::Visual::ResourceStatus Control::Impl::GetVisualResourceStatus(Property::Index index) const
996 RegisteredVisualContainer::Iterator iter;
997 if(FindVisual(index, mVisuals, iter))
999 const Toolkit::Visual::Base visual = (*iter)->visual;
1000 const Internal::Visual::Base& visualImpl = Toolkit::GetImplementation(visual);
1001 return visualImpl.GetResourceStatus();
1004 return Toolkit::Visual::ResourceStatus::PREPARING;
1007 void Control::Impl::AddTransitions(Dali::Animation& animation,
1008 const Toolkit::TransitionData& handle,
1009 bool createAnimation)
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();
1018 TransitionData::Animator* animator = (*iter);
1020 Toolkit::Visual::Base visual = GetVisualByName(mVisuals, animator->objectName);
1024 #if defined(DEBUG_ENABLED)
1025 Dali::TypeInfo typeInfo;
1026 ControlWrapper* controlWrapperImpl = dynamic_cast<ControlWrapper*>(&mControlImpl);
1027 if(controlWrapperImpl)
1029 typeInfo = controlWrapperImpl->GetTypeInfo();
1032 DALI_LOG_INFO(gLogFilter, Debug::Concise, "CreateTransition: Found %s visual for %s\n", visual.GetName().c_str(), typeInfo ? typeInfo.GetName().c_str() : "Unknown");
1034 Internal::Visual::Base& visualImpl = Toolkit::GetImplementation(visual);
1035 visualImpl.AnimateProperty(animation, *animator);
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);
1044 Property::Index propertyIndex = child.GetPropertyIndex(animator->propertyKey);
1045 if(propertyIndex != Property::INVALID_INDEX)
1047 if(animator->animate == false)
1049 if(animator->targetValue.GetType() != Property::NONE)
1051 child.SetProperty(propertyIndex, animator->targetValue);
1054 else // animate the property
1056 if(animator->initialValue.GetType() != Property::NONE)
1058 child.SetProperty(propertyIndex, animator->initialValue);
1061 if(createAnimation && !animation)
1063 animation = Dali::Animation::New(0.1f);
1066 animation.AnimateTo(Property(child, propertyIndex),
1067 animator->targetValue,
1068 animator->alphaFunction,
1069 TimePeriod(animator->timePeriodDelay,
1070 animator->timePeriodDuration));
1078 Dali::Animation Control::Impl::CreateTransition(const Toolkit::TransitionData& transitionData)
1080 Dali::Animation transition;
1082 if(transitionData.Count() > 0)
1084 AddTransitions(transition, transitionData, true);
1089 void Control::Impl::DoAction(Dali::Property::Index visualIndex, Dali::Property::Index actionId, const Dali::Property::Value attributes)
1091 RegisteredVisualContainer::Iterator iter;
1092 if(FindVisual(visualIndex, mVisuals, iter))
1094 Toolkit::GetImplementation((*iter)->visual).DoAction(actionId, attributes);
1098 void Control::Impl::AppendAccessibilityAttribute(const std::string& key, const std::string value)
1100 Property::Value* checkedValue = mAccessibilityAttributes.Find(key);
1103 mAccessibilityAttributes[key] = Property::Value(value);
1107 mAccessibilityAttributes.Insert(key, value);
1111 void Control::Impl::SetProperty(BaseObject* object, Property::Index index, const Property::Value& value)
1113 Toolkit::Control control = Toolkit::Control::DownCast(BaseHandle(object));
1117 Control& controlImpl(GetImplementation(control));
1121 case Toolkit::Control::Property::STYLE_NAME:
1123 controlImpl.SetStyleName(value.Get<std::string>());
1127 case Toolkit::DevelControl::Property::STATE:
1129 bool withTransitions = true;
1130 const Property::Value* valuePtr = &value;
1131 const Property::Map* map = value.GetMap();
1134 Property::Value* value2 = map->Find("withTransitions");
1137 withTransitions = value2->Get<bool>();
1140 valuePtr = map->Find("state");
1145 Toolkit::DevelControl::State state(controlImpl.mImpl->mState);
1146 if(Scripting::GetEnumerationProperty<Toolkit::DevelControl::State>(*valuePtr, ControlStateTable, ControlStateTableCount, state))
1148 controlImpl.mImpl->SetState(state, withTransitions);
1154 case Toolkit::DevelControl::Property::SUB_STATE:
1156 std::string subState;
1157 if(value.Get(subState))
1159 controlImpl.mImpl->SetSubState(subState);
1164 case Toolkit::DevelControl::Property::LEFT_FOCUSABLE_ACTOR_ID:
1167 if(value.Get(focusId))
1169 controlImpl.mImpl->mLeftFocusableActorId = focusId;
1174 case Toolkit::DevelControl::Property::RIGHT_FOCUSABLE_ACTOR_ID:
1177 if(value.Get(focusId))
1179 controlImpl.mImpl->mRightFocusableActorId = focusId;
1184 case Toolkit::DevelControl::Property::UP_FOCUSABLE_ACTOR_ID:
1187 if(value.Get(focusId))
1189 controlImpl.mImpl->mUpFocusableActorId = focusId;
1194 case Toolkit::DevelControl::Property::DOWN_FOCUSABLE_ACTOR_ID:
1197 if(value.Get(focusId))
1199 controlImpl.mImpl->mDownFocusableActorId = focusId;
1204 case Toolkit::Control::Property::KEY_INPUT_FOCUS:
1206 if(value.Get<bool>())
1208 controlImpl.SetKeyInputFocus();
1212 controlImpl.ClearKeyInputFocus();
1217 case Toolkit::Control::Property::BACKGROUND:
1221 const Property::Map* map = value.GetMap();
1222 if(map && !map->Empty())
1224 controlImpl.SetBackground(*map);
1226 else if(value.Get(url))
1228 // don't know the size to load
1229 Toolkit::Visual::Base visual = Toolkit::VisualFactory::Get().CreateVisual(url, ImageDimensions());
1232 controlImpl.mImpl->RegisterVisual(Toolkit::Control::Property::BACKGROUND, visual, DepthIndex::BACKGROUND);
1235 else if(value.Get(color))
1237 controlImpl.SetBackgroundColor(color);
1241 // The background is an empty property map, so we should clear the background
1242 controlImpl.ClearBackground();
1247 case Toolkit::Control::Property::MARGIN:
1250 if(value.Get(margin))
1252 controlImpl.mImpl->SetMargin(margin);
1257 case Toolkit::Control::Property::PADDING:
1260 if(value.Get(padding))
1262 controlImpl.mImpl->SetPadding(padding);
1267 case Toolkit::DevelControl::Property::TOOLTIP:
1269 TooltipPtr& tooltipPtr = controlImpl.mImpl->mTooltip;
1272 tooltipPtr = Tooltip::New(control);
1274 tooltipPtr->SetProperties(value);
1278 case Toolkit::DevelControl::Property::SHADOW:
1280 const Property::Map* map = value.GetMap();
1281 if(map && !map->Empty())
1283 controlImpl.mImpl->SetShadow(*map);
1287 // The shadow is an empty property map, so we should clear the shadow
1288 controlImpl.mImpl->ClearShadow();
1293 case Toolkit::DevelControl::Property::ACCESSIBILITY_NAME:
1298 controlImpl.mImpl->mAccessibilityName = name;
1303 case Toolkit::DevelControl::Property::ACCESSIBILITY_DESCRIPTION:
1308 controlImpl.mImpl->mAccessibilityDescription = text;
1313 case Toolkit::DevelControl::Property::ACCESSIBILITY_TRANSLATION_DOMAIN:
1318 controlImpl.mImpl->mAccessibilityTranslationDomain = text;
1323 case Toolkit::DevelControl::Property::ACCESSIBILITY_ROLE:
1325 Dali::Accessibility::Role role;
1328 controlImpl.mImpl->mAccessibilityRole = role;
1333 case Toolkit::DevelControl::Property::ACCESSIBILITY_HIGHLIGHTABLE:
1336 if(value.Get(highlightable))
1338 controlImpl.mImpl->mAccessibilityHighlightable = highlightable;
1343 case Toolkit::DevelControl::Property::ACCESSIBILITY_ATTRIBUTES:
1345 const Property::Map* map = value.GetMap();
1346 if(map && !map->Empty())
1348 controlImpl.mImpl->mAccessibilityAttributes = *map;
1353 case Toolkit::DevelControl::Property::DISPATCH_KEY_EVENTS:
1356 if(value.Get(dispatch))
1358 controlImpl.mImpl->mDispatchKeyEvents = dispatch;
1363 case Toolkit::DevelControl::Property::ACCESSIBILITY_HIDDEN:
1366 if(value.Get(hidden))
1368 controlImpl.mImpl->mAccessibilityHidden = hidden;
1370 auto* accessible = controlImpl.GetAccessibleObject();
1371 auto* parent = dynamic_cast<Dali::Accessibility::ActorAccessible*>(accessible->GetParent());
1374 parent->OnChildrenChanged();
1379 case Toolkit::DevelControl::Property::CLOCKWISE_FOCUSABLE_ACTOR_ID:
1382 if(value.Get(focusId))
1384 controlImpl.mImpl->mClockwiseFocusableActorId = focusId;
1388 case Toolkit::DevelControl::Property::COUNTER_CLOCKWISE_FOCUSABLE_ACTOR_ID:
1391 if(value.Get(focusId))
1393 controlImpl.mImpl->mCounterClockwiseFocusableActorId = focusId;
1401 Property::Value Control::Impl::GetProperty(BaseObject* object, Property::Index index)
1403 Property::Value value;
1405 Toolkit::Control control = Toolkit::Control::DownCast(BaseHandle(object));
1409 Control& controlImpl(GetImplementation(control));
1413 case Toolkit::Control::Property::STYLE_NAME:
1415 value = controlImpl.GetStyleName();
1419 case Toolkit::DevelControl::Property::STATE:
1421 value = controlImpl.mImpl->mState;
1425 case Toolkit::DevelControl::Property::SUB_STATE:
1427 value = controlImpl.mImpl->mSubStateName;
1431 case Toolkit::DevelControl::Property::LEFT_FOCUSABLE_ACTOR_ID:
1433 value = controlImpl.mImpl->mLeftFocusableActorId;
1437 case Toolkit::DevelControl::Property::RIGHT_FOCUSABLE_ACTOR_ID:
1439 value = controlImpl.mImpl->mRightFocusableActorId;
1443 case Toolkit::DevelControl::Property::UP_FOCUSABLE_ACTOR_ID:
1445 value = controlImpl.mImpl->mUpFocusableActorId;
1449 case Toolkit::DevelControl::Property::DOWN_FOCUSABLE_ACTOR_ID:
1451 value = controlImpl.mImpl->mDownFocusableActorId;
1455 case Toolkit::Control::Property::KEY_INPUT_FOCUS:
1457 value = controlImpl.HasKeyInputFocus();
1461 case Toolkit::Control::Property::BACKGROUND:
1464 Toolkit::Visual::Base visual = controlImpl.mImpl->GetVisual(Toolkit::Control::Property::BACKGROUND);
1467 visual.CreatePropertyMap(map);
1474 case Toolkit::Control::Property::MARGIN:
1476 value = controlImpl.mImpl->GetMargin();
1480 case Toolkit::Control::Property::PADDING:
1482 value = controlImpl.mImpl->GetPadding();
1486 case Toolkit::DevelControl::Property::TOOLTIP:
1489 if(controlImpl.mImpl->mTooltip)
1491 controlImpl.mImpl->mTooltip->CreatePropertyMap(map);
1497 case Toolkit::DevelControl::Property::SHADOW:
1500 Toolkit::Visual::Base visual = controlImpl.mImpl->GetVisual(Toolkit::DevelControl::Property::SHADOW);
1503 visual.CreatePropertyMap(map);
1510 case Toolkit::DevelControl::Property::ACCESSIBILITY_NAME:
1512 value = controlImpl.mImpl->mAccessibilityName;
1516 case Toolkit::DevelControl::Property::ACCESSIBILITY_DESCRIPTION:
1518 value = controlImpl.mImpl->mAccessibilityDescription;
1522 case Toolkit::DevelControl::Property::ACCESSIBILITY_TRANSLATION_DOMAIN:
1524 value = controlImpl.mImpl->mAccessibilityTranslationDomain;
1528 case Toolkit::DevelControl::Property::ACCESSIBILITY_ROLE:
1530 value = Property::Value(controlImpl.mImpl->mAccessibilityRole);
1534 case Toolkit::DevelControl::Property::ACCESSIBILITY_HIGHLIGHTABLE:
1536 value = controlImpl.mImpl->mAccessibilityHighlightable;
1540 case Toolkit::DevelControl::Property::ACCESSIBILITY_ATTRIBUTES:
1542 value = controlImpl.mImpl->mAccessibilityAttributes;
1546 case Toolkit::DevelControl::Property::DISPATCH_KEY_EVENTS:
1548 value = controlImpl.mImpl->mDispatchKeyEvents;
1552 case Toolkit::DevelControl::Property::ACCESSIBILITY_HIDDEN:
1554 value = controlImpl.mImpl->mAccessibilityHidden;
1558 case Toolkit::DevelControl::Property::CLOCKWISE_FOCUSABLE_ACTOR_ID:
1560 value = controlImpl.mImpl->mClockwiseFocusableActorId;
1564 case Toolkit::DevelControl::Property::COUNTER_CLOCKWISE_FOCUSABLE_ACTOR_ID:
1566 value = controlImpl.mImpl->mCounterClockwiseFocusableActorId;
1575 void Control::Impl::RemoveAccessibilityAttribute(const std::string& key)
1577 Property::Value* value = mAccessibilityAttributes.Find(key);
1580 mAccessibilityAttributes[key] = Property::Value();
1584 void Control::Impl::ClearAccessibilityAttributes()
1586 mAccessibilityAttributes.Clear();
1589 void Control::Impl::SetAccessibilityReadingInfoType(const Dali::Accessibility::ReadingInfoTypes types)
1591 std::string value{};
1592 if(types[Dali::Accessibility::ReadingInfoType::NAME])
1594 value += READING_INFO_TYPE_NAME;
1596 if(types[Dali::Accessibility::ReadingInfoType::ROLE])
1600 value += READING_INFO_TYPE_SEPARATOR;
1602 value += READING_INFO_TYPE_ROLE;
1604 if(types[Dali::Accessibility::ReadingInfoType::DESCRIPTION])
1608 value += READING_INFO_TYPE_SEPARATOR;
1610 value += READING_INFO_TYPE_DESCRIPTION;
1612 if(types[Dali::Accessibility::ReadingInfoType::STATE])
1616 value += READING_INFO_TYPE_SEPARATOR;
1618 value += READING_INFO_TYPE_STATE;
1620 AppendAccessibilityAttribute(READING_INFO_TYPE_ATTRIBUTE_NAME, value);
1623 Dali::Accessibility::ReadingInfoTypes Control::Impl::GetAccessibilityReadingInfoType() const
1625 std::string value{};
1626 auto place = mAccessibilityAttributes.Find(READING_INFO_TYPE_ATTRIBUTE_NAME);
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;
1646 Dali::Accessibility::ReadingInfoTypes types;
1648 if(value.find(READING_INFO_TYPE_NAME) != std::string::npos)
1650 types[Dali::Accessibility::ReadingInfoType::NAME] = true;
1652 if(value.find(READING_INFO_TYPE_ROLE) != std::string::npos)
1654 types[Dali::Accessibility::ReadingInfoType::ROLE] = true;
1656 if(value.find(READING_INFO_TYPE_DESCRIPTION) != std::string::npos)
1658 types[Dali::Accessibility::ReadingInfoType::DESCRIPTION] = true;
1660 if(value.find(READING_INFO_TYPE_STATE) != std::string::npos)
1662 types[Dali::Accessibility::ReadingInfoType::STATE] = true;
1668 void Control::Impl::CopyInstancedProperties(RegisteredVisualContainer& visuals, Dictionary<Property::Map>& instancedProperties)
1670 for(RegisteredVisualContainer::Iterator iter = visuals.Begin(); iter != visuals.End(); iter++)
1674 Property::Map instanceMap;
1675 Toolkit::GetImplementation((*iter)->visual).CreateInstancePropertyMap(instanceMap);
1676 instancedProperties.Add((*iter)->visual.GetName(), instanceMap);
1681 void Control::Impl::RemoveVisual(RegisteredVisualContainer& visuals, const std::string& visualName)
1683 Actor self(mControlImpl.Self());
1685 for(RegisteredVisualContainer::Iterator visualIter = visuals.Begin();
1686 visualIter != visuals.End();
1689 Toolkit::Visual::Base visual = (*visualIter)->visual;
1690 if(visual && visual.GetName() == visualName)
1692 Toolkit::GetImplementation(visual).SetOffScene(self);
1693 (*visualIter)->visual.Reset();
1694 visuals.Erase(visualIter);
1700 void Control::Impl::RemoveVisuals(RegisteredVisualContainer& visuals, DictionaryKeys& removeVisuals)
1702 Actor self(mControlImpl.Self());
1703 for(DictionaryKeys::iterator iter = removeVisuals.begin(); iter != removeVisuals.end(); ++iter)
1705 const std::string visualName = *iter;
1706 RemoveVisual(visuals, visualName);
1710 void Control::Impl::RecreateChangedVisuals(Dictionary<Property::Map>& stateVisualsToChange,
1711 Dictionary<Property::Map>& instancedProperties)
1713 Dali::CustomActor handle(mControlImpl.GetOwner());
1714 for(Dictionary<Property::Map>::iterator iter = stateVisualsToChange.Begin();
1715 iter != stateVisualsToChange.End();
1718 const std::string& visualName = (*iter).key;
1719 const Property::Map& toMap = (*iter).entry;
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))
1726 Toolkit::Visual::Base& visual = (*registeredVisualsiter)->visual;
1729 // No longer required to know if the replaced visual's resources are ready
1730 StopObservingVisual(visual);
1732 // If control staged then visuals will be swapped once ready
1733 if(self.GetProperty<bool>(Actor::Property::CONNECTED_TO_SCENE))
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))
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);
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);
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);
1760 const Property::Map* instancedMap = instancedProperties.FindConst(visualName);
1761 Style::ApplyVisual(handle, visualName, toMap, instancedMap);
1766 void Control::Impl::ReplaceStateVisualsAndProperties(const StylePtr oldState, const StylePtr newState, const std::string& subState)
1768 // Collect all old visual names
1769 DictionaryKeys stateVisualsToRemove;
1772 oldState->visuals.GetKeys(stateVisualsToRemove);
1773 if(!subState.empty())
1775 const StylePtr* oldSubState = oldState->subStates.FindConst(subState);
1778 DictionaryKeys subStateVisualsToRemove;
1779 (*oldSubState)->visuals.GetKeys(subStateVisualsToRemove);
1780 Merge(stateVisualsToRemove, subStateVisualsToRemove);
1785 // Collect all new visual properties
1786 Dictionary<Property::Map> stateVisualsToAdd;
1789 stateVisualsToAdd = newState->visuals;
1790 if(!subState.empty())
1792 const StylePtr* newSubState = newState->subStates.FindConst(subState);
1795 stateVisualsToAdd.Merge((*newSubState)->visuals);
1800 // If a name is in both add/remove, move it to change list.
1801 Dictionary<Property::Map> stateVisualsToChange;
1802 FindChangableVisuals(stateVisualsToAdd, stateVisualsToChange, stateVisualsToRemove);
1804 // Copy instanced properties (e.g. text label) of current visuals
1805 Dictionary<Property::Map> instancedProperties;
1806 CopyInstancedProperties(mVisuals, instancedProperties);
1808 // For each visual in remove list, remove from mVisuals
1809 RemoveVisuals(mVisuals, stateVisualsToRemove);
1811 // For each visual in add list, create and add to mVisuals
1812 Dali::CustomActor handle(mControlImpl.GetOwner());
1813 Style::ApplyVisuals(handle, stateVisualsToAdd, instancedProperties);
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);
1820 void Control::Impl::SetState(DevelControl::State newState, bool withTransitions)
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"))));
1826 if(mState != newState)
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.
1832 // Trigger state change and transitions
1833 // Apply new style, if stylemanager is available
1834 Toolkit::StyleManager styleManager = Toolkit::StyleManager::Get();
1837 const StylePtr stylePtr = GetImpl(styleManager).GetRecordedStyle(Toolkit::Control(mControlImpl.GetOwner()));
1841 std::string oldStateName = Scripting::GetEnumerationName<Toolkit::DevelControl::State>(oldState, ControlStateTable, ControlStateTableCount);
1842 std::string newStateName = Scripting::GetEnumerationName<Toolkit::DevelControl::State>(newState, ControlStateTable, ControlStateTableCount);
1844 const StylePtr* newStateStyle = stylePtr->subStates.Find(newStateName);
1845 const StylePtr* oldStateStyle = stylePtr->subStates.Find(oldStateName);
1846 if(oldStateStyle && newStateStyle)
1848 // Only change if both state styles exist
1849 ReplaceStateVisualsAndProperties(*oldStateStyle, *newStateStyle, mSubStateName);
1856 void Control::Impl::SetSubState(const std::string& subStateName, bool withTransitions)
1858 if(mSubStateName != subStateName)
1860 // Get existing sub-state visuals, and unregister them
1861 Dali::CustomActor handle(mControlImpl.GetOwner());
1863 Toolkit::StyleManager styleManager = Toolkit::StyleManager::Get();
1866 const StylePtr stylePtr = GetImpl(styleManager).GetRecordedStyle(Toolkit::Control(mControlImpl.GetOwner()));
1870 std::string stateName = Scripting::GetEnumerationName<Toolkit::DevelControl::State>(mState, ControlStateTable, ControlStateTableCount);
1872 const StylePtr* state = stylePtr->subStates.Find(stateName);
1875 StylePtr stateStyle(*state);
1877 const StylePtr* newStateStyle = stateStyle->subStates.Find(subStateName);
1878 const StylePtr* oldStateStyle = stateStyle->subStates.Find(mSubStateName);
1879 if(oldStateStyle && newStateStyle)
1882 ReplaceStateVisualsAndProperties(*oldStateStyle, *newStateStyle, empty);
1888 mSubStateName = subStateName;
1892 void Control::Impl::OnSceneDisconnection()
1894 Actor self = mControlImpl.Self();
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.
1900 // Iterate through all registered visuals and set off scene
1901 SetVisualsOffScene(mVisuals, self);
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++)
1907 Toolkit::GetImplementation((*removalIter)->visual).SetOffScene(self);
1910 for(auto replacedIter = mVisuals.Begin(), end = mVisuals.End(); replacedIter != end; replacedIter++)
1912 (*replacedIter)->pending = false;
1915 mRemoveVisuals.Clear();
1918 void Control::Impl::SetMargin(Extents margin)
1920 mControlImpl.mImpl->mMargin = margin;
1922 // Trigger a size negotiation request that may be needed when setting a margin.
1923 mControlImpl.RelayoutRequest();
1926 Extents Control::Impl::GetMargin() const
1928 return mControlImpl.mImpl->mMargin;
1931 void Control::Impl::SetPadding(Extents padding)
1933 mControlImpl.mImpl->mPadding = padding;
1935 // Trigger a size negotiation request that may be needed when setting a padding.
1936 mControlImpl.RelayoutRequest();
1939 Extents Control::Impl::GetPadding() const
1941 return mControlImpl.mImpl->mPadding;
1944 void Control::Impl::SetInputMethodContext(InputMethodContext& inputMethodContext)
1946 mInputMethodContext = inputMethodContext;
1949 bool Control::Impl::FilterKeyEvent(const KeyEvent& event)
1951 bool consumed(false);
1953 if(mInputMethodContext)
1955 consumed = mInputMethodContext.FilterEventKey(event);
1960 DevelControl::VisualEventSignalType& Control::Impl::VisualEventSignal()
1962 return mVisualEventSignal;
1965 void Control::Impl::SetShadow(const Property::Map& map)
1967 Toolkit::Visual::Base visual = Toolkit::VisualFactory::Get().CreateVisual(map);
1968 visual.SetName("shadow");
1972 mControlImpl.mImpl->RegisterVisual(Toolkit::DevelControl::Property::SHADOW, visual, DepthIndex::BACKGROUND_EFFECT);
1974 mControlImpl.RelayoutRequest();
1978 void Control::Impl::ClearShadow()
1980 mControlImpl.mImpl->UnregisterVisual(Toolkit::DevelControl::Property::SHADOW);
1982 // Trigger a size negotiation request that may be needed when unregistering a visual.
1983 mControlImpl.RelayoutRequest();
1986 Dali::Property Control::Impl::GetVisualProperty(Dali::Property::Index index, Dali::Property::Key visualPropertyKey)
1988 Toolkit::Visual::Base visual = GetVisualByIndex(mVisuals, index);
1991 Internal::Visual::Base& visualImpl = Toolkit::GetImplementation(visual);
1992 return visualImpl.GetPropertyObject(visualPropertyKey);
1996 return Dali::Property(handle, Property::INVALID_INDEX);
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)
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)
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));
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)
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));
2022 // Retrieves transition from inherited class.
2023 mControlImpl.OnCreateTransitions(sourceProperties, destinationProperties, source, destination);
2026 void Control::Impl::UpdateVisualProperties(const std::vector<std::pair<Dali::Property::Index, Dali::Property::Map>>& properties)
2028 for(auto&& data : properties)
2030 if(data.first == Toolkit::Control::Property::BACKGROUND)
2032 DoAction(Toolkit::Control::Property::BACKGROUND, DevelVisual::Action::UPDATE_PROPERTY, data.second);
2034 else if(data.first == Toolkit::DevelControl::Property::SHADOW)
2036 DoAction(Toolkit::DevelControl::Property::SHADOW, DevelVisual::Action::UPDATE_PROPERTY, data.second);
2039 mControlImpl.OnUpdateVisualProperties(properties);
2042 void Control::Impl::EmitResourceReadySignal()
2044 if(!mIsEmittingResourceReadySignal)
2046 // Guard against calls to emit the signal during the callback
2047 mIsEmittingResourceReadySignal = true;
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);
2055 if(mNeedToEmitResourceReady)
2057 // Add idler to emit the signal again
2060 // The callback manager takes the ownership of the callback object.
2061 mIdleCallback = MakeCallback(this, &Control::Impl::OnIdleCallback);
2062 Adaptor::Get().AddIdle(mIdleCallback, false);
2066 mIsEmittingResourceReadySignal = false;
2070 mNeedToEmitResourceReady = true;
2074 void Control::Impl::OnIdleCallback()
2076 if(mNeedToEmitResourceReady)
2079 mNeedToEmitResourceReady = false;
2081 // A visual is ready so control may need relayouting if staged
2082 if(mControlImpl.Self().GetProperty<bool>(Actor::Property::CONNECTED_TO_SCENE))
2084 mControlImpl.RelayoutRequest();
2087 EmitResourceReadySignal();
2090 // Set the pointer to null as the callback manager deletes the callback after execute it.
2091 mIdleCallback = nullptr;
2094 Toolkit::DevelControl::ControlAccessible* Control::Impl::GetAccessibleObject()
2096 if(!mAccessibleObject)
2098 mAccessibleObject.reset(mControlImpl.CreateAccessibleObject());
2101 return mAccessibleObject.get();
2104 } // namespace Internal
2106 } // namespace Toolkit