2 * Copyright (c) 2021 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/visuals/visual-actions-devel.h>
40 #include <dali-toolkit/devel-api/asset-manager/asset-manager.h>
41 #include <dali-toolkit/devel-api/controls/control-depth-index-ranges.h>
42 #include <dali-toolkit/devel-api/controls/control-devel.h>
43 #include <dali-toolkit/devel-api/controls/control-wrapper-impl.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 } // unnamed namespace
451 // Properties registered without macro to use specific member variables.
452 const PropertyRegistration Control::Impl::PROPERTY_1(typeRegistration, "styleName", Toolkit::Control::Property::STYLE_NAME, Property::STRING, &Control::Impl::SetProperty, &Control::Impl::GetProperty);
453 const PropertyRegistration Control::Impl::PROPERTY_4(typeRegistration, "keyInputFocus", Toolkit::Control::Property::KEY_INPUT_FOCUS, Property::BOOLEAN, &Control::Impl::SetProperty, &Control::Impl::GetProperty);
454 const PropertyRegistration Control::Impl::PROPERTY_5(typeRegistration, "background", Toolkit::Control::Property::BACKGROUND, Property::MAP, &Control::Impl::SetProperty, &Control::Impl::GetProperty);
455 const PropertyRegistration Control::Impl::PROPERTY_6(typeRegistration, "margin", Toolkit::Control::Property::MARGIN, Property::EXTENTS, &Control::Impl::SetProperty, &Control::Impl::GetProperty);
456 const PropertyRegistration Control::Impl::PROPERTY_7(typeRegistration, "padding", Toolkit::Control::Property::PADDING, Property::EXTENTS, &Control::Impl::SetProperty, &Control::Impl::GetProperty);
457 const PropertyRegistration Control::Impl::PROPERTY_8(typeRegistration, "tooltip", Toolkit::DevelControl::Property::TOOLTIP, Property::MAP, &Control::Impl::SetProperty, &Control::Impl::GetProperty);
458 const PropertyRegistration Control::Impl::PROPERTY_9(typeRegistration, "state", Toolkit::DevelControl::Property::STATE, Property::STRING, &Control::Impl::SetProperty, &Control::Impl::GetProperty);
459 const PropertyRegistration Control::Impl::PROPERTY_10(typeRegistration, "subState", Toolkit::DevelControl::Property::SUB_STATE, Property::STRING, &Control::Impl::SetProperty, &Control::Impl::GetProperty);
460 const PropertyRegistration Control::Impl::PROPERTY_11(typeRegistration, "leftFocusableActorId", Toolkit::DevelControl::Property::LEFT_FOCUSABLE_ACTOR_ID, Property::INTEGER, &Control::Impl::SetProperty, &Control::Impl::GetProperty);
461 const PropertyRegistration Control::Impl::PROPERTY_12(typeRegistration, "rightFocusableActorId", Toolkit::DevelControl::Property::RIGHT_FOCUSABLE_ACTOR_ID, Property::INTEGER, &Control::Impl::SetProperty, &Control::Impl::GetProperty);
462 const PropertyRegistration Control::Impl::PROPERTY_13(typeRegistration, "upFocusableActorId", Toolkit::DevelControl::Property::UP_FOCUSABLE_ACTOR_ID, Property::INTEGER, &Control::Impl::SetProperty, &Control::Impl::GetProperty);
463 const PropertyRegistration Control::Impl::PROPERTY_14(typeRegistration, "downFocusableActorId", Toolkit::DevelControl::Property::DOWN_FOCUSABLE_ACTOR_ID, Property::INTEGER, &Control::Impl::SetProperty, &Control::Impl::GetProperty);
464 const PropertyRegistration Control::Impl::PROPERTY_15(typeRegistration, "shadow", Toolkit::DevelControl::Property::SHADOW, Property::MAP, &Control::Impl::SetProperty, &Control::Impl::GetProperty);
465 const PropertyRegistration Control::Impl::PROPERTY_16(typeRegistration, "accessibilityName", Toolkit::DevelControl::Property::ACCESSIBILITY_NAME, Property::STRING, &Control::Impl::SetProperty, &Control::Impl::GetProperty);
466 const PropertyRegistration Control::Impl::PROPERTY_17(typeRegistration, "accessibilityDescription", Toolkit::DevelControl::Property::ACCESSIBILITY_DESCRIPTION, Property::STRING, &Control::Impl::SetProperty, &Control::Impl::GetProperty);
467 const PropertyRegistration Control::Impl::PROPERTY_18(typeRegistration, "accessibilityTranslationDomain", Toolkit::DevelControl::Property::ACCESSIBILITY_TRANSLATION_DOMAIN, Property::STRING, &Control::Impl::SetProperty, &Control::Impl::GetProperty);
468 const PropertyRegistration Control::Impl::PROPERTY_19(typeRegistration, "accessibilityRole", Toolkit::DevelControl::Property::ACCESSIBILITY_ROLE, Property::INTEGER, &Control::Impl::SetProperty, &Control::Impl::GetProperty);
469 const PropertyRegistration Control::Impl::PROPERTY_20(typeRegistration, "accessibilityHighlightable", Toolkit::DevelControl::Property::ACCESSIBILITY_HIGHLIGHTABLE, Property::BOOLEAN, &Control::Impl::SetProperty, &Control::Impl::GetProperty);
470 const PropertyRegistration Control::Impl::PROPERTY_21(typeRegistration, "accessibilityAttributes", Toolkit::DevelControl::Property::ACCESSIBILITY_ATTRIBUTES, Property::MAP, &Control::Impl::SetProperty, &Control::Impl::GetProperty);
471 const PropertyRegistration Control::Impl::PROPERTY_22(typeRegistration, "dispatchKeyEvents", Toolkit::DevelControl::Property::DISPATCH_KEY_EVENTS, Property::BOOLEAN, &Control::Impl::SetProperty, &Control::Impl::GetProperty);
472 const PropertyRegistration Control::Impl::PROPERTY_23(typeRegistration, "accessibilityHidden", Toolkit::DevelControl::Property::ACCESSIBILITY_HIDDEN, Property::BOOLEAN, &Control::Impl::SetProperty, &Control::Impl::GetProperty);
476 Control::Impl::Impl(Control& controlImpl)
477 : mControlImpl(controlImpl),
478 mState(Toolkit::DevelControl::NORMAL),
480 mLeftFocusableActorId(-1),
481 mRightFocusableActorId(-1),
482 mUpFocusableActorId(-1),
483 mDownFocusableActorId(-1),
485 mBackgroundColor(Color::TRANSPARENT),
486 mStartingPinchScale(nullptr),
488 mPadding(0, 0, 0, 0),
490 mKeyInputFocusGainedSignal(),
491 mKeyInputFocusLostSignal(),
492 mResourceReadySignal(),
493 mVisualEventSignal(),
494 mAccessibilityGetNameSignal(),
495 mAccessibilityGetDescriptionSignal(),
496 mAccessibilityDoGestureSignal(),
497 mPinchGestureDetector(),
498 mPanGestureDetector(),
499 mTapGestureDetector(),
500 mLongPressGestureDetector(),
502 mInputMethodContext(),
503 mIdleCallback(nullptr),
504 mFlags(Control::ControlBehaviour(CONTROL_BEHAVIOUR_DEFAULT)),
505 mIsKeyboardNavigationSupported(false),
506 mIsKeyboardFocusGroup(false),
507 mIsEmittingResourceReadySignal(false),
508 mNeedToEmitResourceReady(false),
509 mDispatchKeyEvents(true)
511 Dali::Accessibility::Accessible::RegisterExternalAccessibleGetter(
512 [](Dali::Actor actor) -> Dali::Accessibility::Accessible* {
513 return Control::Impl::GetAccessibilityObject(actor);
516 mAccessibilityConstructor = [](Dali::Actor actor) -> std::unique_ptr<Dali::Accessibility::Accessible> {
517 return std::unique_ptr<Dali::Accessibility::Accessible>(new DevelControl::ControlAccessible(actor, Dali::Accessibility::Role::UNKNOWN));
521 Control::Impl::~Impl()
523 for(auto&& iter : mVisuals)
525 StopObservingVisual(iter->visual);
528 for(auto&& iter : mRemoveVisuals)
530 StopObservingVisual(iter->visual);
533 // All gesture detectors will be destroyed so no need to disconnect.
534 delete mStartingPinchScale;
536 if(mIdleCallback && Adaptor::IsAvailable())
538 // Removes the callback from the callback manager in case the control is destroyed before the callback is executed.
539 Adaptor::Get().RemoveIdle(mIdleCallback);
543 Control::Impl& Control::Impl::Get(Internal::Control& internalControl)
545 return *internalControl.mImpl;
548 const Control::Impl& Control::Impl::Get(const Internal::Control& internalControl)
550 return *internalControl.mImpl;
553 void Control::Impl::CheckHighlightedObjectGeometry()
555 auto accessible = dynamic_cast<Dali::Toolkit::DevelControl::ControlAccessible*>(mAccessibilityObject.get());
558 DALI_LOG_ERROR("accessible is not a pointer to a DevelControl::ControlAccessible type");
562 auto lastPosition = accessible->GetLastPosition();
563 auto accessibleRect = accessible->GetExtents(Dali::Accessibility::CoordinateType::WINDOW);
564 auto rect = GetShowingGeometry(accessibleRect, accessible);
566 switch(mAccessibilityLastScreenRelativeMoveType)
568 case Dali::Accessibility::ScreenRelativeMoveType::OUTSIDE:
570 if(IsShowingGeometryOnScreen(rect))
572 mAccessibilityLastScreenRelativeMoveType = Dali::Accessibility::ScreenRelativeMoveType::INSIDE;
576 case Dali::Accessibility::ScreenRelativeMoveType::INSIDE:
578 if(rect.width < 0 && accessibleRect.x != lastPosition.x)
580 mAccessibilityLastScreenRelativeMoveType = (accessibleRect.x < lastPosition.x) ? Dali::Accessibility::ScreenRelativeMoveType::OUTGOING_TOP_LEFT : Dali::Accessibility::ScreenRelativeMoveType::OUTGOING_BOTTOM_RIGHT;
582 if(rect.height < 0 && accessibleRect.y != lastPosition.y)
584 mAccessibilityLastScreenRelativeMoveType = (accessibleRect.y < lastPosition.y) ? Dali::Accessibility::ScreenRelativeMoveType::OUTGOING_TOP_LEFT : Dali::Accessibility::ScreenRelativeMoveType::OUTGOING_BOTTOM_RIGHT;
586 // notify AT-clients on outgoing moves only
587 if(mAccessibilityLastScreenRelativeMoveType != Dali::Accessibility::ScreenRelativeMoveType::INSIDE)
589 mAccessibilityObject.get()->EmitMovedOutOfScreen(mAccessibilityLastScreenRelativeMoveType);
593 case Dali::Accessibility::ScreenRelativeMoveType::OUTGOING_TOP_LEFT:
594 case Dali::Accessibility::ScreenRelativeMoveType::OUTGOING_BOTTOM_RIGHT:
596 if(IsShowingGeometryOnScreen(rect))
598 mAccessibilityLastScreenRelativeMoveType = Dali::Accessibility::ScreenRelativeMoveType::INSIDE;
602 mAccessibilityLastScreenRelativeMoveType = Dali::Accessibility::ScreenRelativeMoveType::OUTSIDE;
612 accessible->SetLastPosition(Vector2(accessibleRect.x, accessibleRect.y));
615 void Control::Impl::RegisterAccessibilityPositionPropertyNotification()
617 if(mIsAccessibilityPositionPropertyNotificationSet)
621 // set default value until first move of object is detected
622 mAccessibilityLastScreenRelativeMoveType = Dali::Accessibility::ScreenRelativeMoveType::OUTSIDE;
623 // recalculate mAccessibilityLastScreenRelativeMoveType accordingly to the initial position
624 CheckHighlightedObjectGeometry();
625 mAccessibilityPositionNotification = mControlImpl.Self().AddPropertyNotification(Actor::Property::WORLD_POSITION, StepCondition(1.0f, 1.0f));
626 mAccessibilityPositionNotification.SetNotifyMode(PropertyNotification::NOTIFY_ON_CHANGED);
627 mAccessibilityPositionNotification.NotifySignal().Connect(this, [this](PropertyNotification&){ CheckHighlightedObjectGeometry(); });
628 mIsAccessibilityPositionPropertyNotificationSet = true;
631 void Control::Impl::UnregisterAccessibilityPositionPropertyNotification()
633 mControlImpl.Self().RemovePropertyNotification(mAccessibilityPositionNotification);
634 mIsAccessibilityPositionPropertyNotificationSet = false;
637 // Gesture Detection Methods
638 void Control::Impl::PinchDetected(Actor actor, const PinchGesture& pinch)
640 mControlImpl.OnPinch(pinch);
643 void Control::Impl::PanDetected(Actor actor, const PanGesture& pan)
645 mControlImpl.OnPan(pan);
648 void Control::Impl::TapDetected(Actor actor, const TapGesture& tap)
650 mControlImpl.OnTap(tap);
653 void Control::Impl::LongPressDetected(Actor actor, const LongPressGesture& longPress)
655 mControlImpl.OnLongPress(longPress);
658 void Control::Impl::RegisterVisual(Property::Index index, Toolkit::Visual::Base& visual)
660 RegisterVisual(index, visual, VisualState::ENABLED, DepthIndexValue::NOT_SET);
663 void Control::Impl::RegisterVisual(Property::Index index, Toolkit::Visual::Base& visual, int depthIndex)
665 RegisterVisual(index, visual, VisualState::ENABLED, DepthIndexValue::SET, depthIndex);
668 void Control::Impl::RegisterVisual(Property::Index index, Toolkit::Visual::Base& visual, bool enabled)
670 RegisterVisual(index, visual, (enabled ? VisualState::ENABLED : VisualState::DISABLED), DepthIndexValue::NOT_SET);
673 void Control::Impl::RegisterVisual(Property::Index index, Toolkit::Visual::Base& visual, bool enabled, int depthIndex)
675 RegisterVisual(index, visual, (enabled ? VisualState::ENABLED : VisualState::DISABLED), DepthIndexValue::SET, depthIndex);
678 void Control::Impl::RegisterVisual(Property::Index index, Toolkit::Visual::Base& visual, VisualState::Type enabled, DepthIndexValue::Type depthIndexValueSet, int depthIndex)
680 DALI_LOG_INFO(gLogFilter, Debug::Concise, "RegisterVisual:%d \n", index);
682 bool visualReplaced(false);
683 Actor self = mControlImpl.Self();
685 // Set the depth index, if not set by caller this will be either the current visual depth, max depth of all visuals
687 int requiredDepthIndex = visual.GetDepthIndex();
689 if(depthIndexValueSet == DepthIndexValue::SET)
691 requiredDepthIndex = depthIndex;
694 // Visual replacement, existing visual should only be removed from stage when replacement ready.
695 if(!mVisuals.Empty())
697 RegisteredVisualContainer::Iterator registeredVisualsiter;
698 // Check if visual (index) is already registered, this is the current visual.
699 if(FindVisual(index, mVisuals, registeredVisualsiter))
701 Toolkit::Visual::Base& currentRegisteredVisual = (*registeredVisualsiter)->visual;
702 if(currentRegisteredVisual)
704 // Store current visual depth index as may need to set the replacement visual to same depth
705 const int currentDepthIndex = (*registeredVisualsiter)->visual.GetDepthIndex();
707 // No longer required to know if the replaced visual's resources are ready
708 StopObservingVisual(currentRegisteredVisual);
710 // If control staged and visual enabled then visuals will be swapped once ready
711 if(self.GetProperty<bool>(Actor::Property::CONNECTED_TO_SCENE) && enabled)
713 // Check if visual is currently in the process of being replaced ( is in removal container )
714 RegisteredVisualContainer::Iterator visualQueuedForRemoval;
715 if(FindVisual(index, mRemoveVisuals, visualQueuedForRemoval))
717 // Visual with same index is already in removal container so current visual pending
718 // Only the the last requested visual will be displayed so remove current visual which is staged but not ready.
719 Toolkit::GetImplementation(currentRegisteredVisual).SetOffScene(self);
720 mVisuals.Erase(registeredVisualsiter);
724 // current visual not already in removal container so add now.
725 DALI_LOG_INFO(gLogFilter, Debug::Verbose, "RegisterVisual Move current registered visual to removal Queue: %d \n", index);
726 MoveVisual(registeredVisualsiter, mVisuals, mRemoveVisuals);
731 // Control not staged or visual disabled so can just erase from registered visuals and new visual will be added later.
732 mVisuals.Erase(registeredVisualsiter);
735 // 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
736 if((depthIndexValueSet == DepthIndexValue::NOT_SET) &&
737 (visual.GetDepthIndex() == 0))
739 requiredDepthIndex = currentDepthIndex;
743 visualReplaced = true;
747 // If not set, set the name of the visual to the same name as the control's property.
748 // ( If the control has been type registered )
749 if(visual.GetName().empty())
751 // returns empty string if index is not found as long as index is not -1
752 std::string visualName = self.GetPropertyName(index);
753 if(!visualName.empty())
755 DALI_LOG_INFO(gLogFilter, Debug::Concise, "Setting visual name for property %d to %s\n", index, visualName.c_str());
756 visual.SetName(visualName);
760 if(!visualReplaced) // New registration entry
762 // 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
763 if((depthIndexValueSet == DepthIndexValue::NOT_SET) &&
764 (mVisuals.Size() > 0) &&
765 (visual.GetDepthIndex() == 0))
767 int maxDepthIndex = std::numeric_limits<int>::min();
769 RegisteredVisualContainer::ConstIterator iter;
770 const RegisteredVisualContainer::ConstIterator endIter = mVisuals.End();
771 for(iter = mVisuals.Begin(); iter != endIter; iter++)
773 const int visualDepthIndex = (*iter)->visual.GetDepthIndex();
774 if(visualDepthIndex > maxDepthIndex)
776 maxDepthIndex = visualDepthIndex;
779 ++maxDepthIndex; // Add one to the current maximum depth index so that our added visual appears on top
780 requiredDepthIndex = std::max(0, maxDepthIndex); // Start at zero if maxDepth index belongs to a background
786 // Set determined depth index
787 visual.SetDepthIndex(requiredDepthIndex);
789 // Monitor when the visual resources are ready
790 StartObservingVisual(visual);
792 DALI_LOG_INFO(gLogFilter, Debug::Concise, "New Visual registration index[%d] depth[%d]\n", index, requiredDepthIndex);
793 RegisteredVisual* newRegisteredVisual = new RegisteredVisual(index, visual, (enabled == VisualState::ENABLED ? true : false), (visualReplaced && enabled));
794 mVisuals.PushBack(newRegisteredVisual);
796 Internal::Visual::Base& visualImpl = Toolkit::GetImplementation(visual);
797 // Put on stage if enabled and the control is already on the stage
798 if((enabled == VisualState::ENABLED) && self.GetProperty<bool>(Actor::Property::CONNECTED_TO_SCENE))
800 visualImpl.SetOnScene(self);
802 else if(visualImpl.IsResourceReady()) // When not being staged, check if visual already 'ResourceReady' before it was Registered. ( Resource may have been loaded already )
804 ResourceReady(visualImpl);
808 DALI_LOG_INFO(gLogFilter, Debug::Verbose, "Control::RegisterVisual() Registered %s(%d), enabled:%s\n", visual.GetName().c_str(), index, enabled ? "true" : "false");
811 void Control::Impl::UnregisterVisual(Property::Index index)
813 RegisteredVisualContainer::Iterator iter;
814 if(FindVisual(index, mVisuals, iter))
816 // stop observing visual
817 StopObservingVisual((*iter)->visual);
819 Actor self(mControlImpl.Self());
820 Toolkit::GetImplementation((*iter)->visual).SetOffScene(self);
821 (*iter)->visual.Reset();
822 mVisuals.Erase(iter);
825 if(FindVisual(index, mRemoveVisuals, iter))
827 Actor self(mControlImpl.Self());
828 Toolkit::GetImplementation((*iter)->visual).SetOffScene(self);
829 (*iter)->pending = false;
830 (*iter)->visual.Reset();
831 mRemoveVisuals.Erase(iter);
835 Toolkit::Visual::Base Control::Impl::GetVisual(Property::Index index) const
837 RegisteredVisualContainer::Iterator iter;
838 if(FindVisual(index, mVisuals, iter))
840 return (*iter)->visual;
843 return Toolkit::Visual::Base();
846 void Control::Impl::EnableVisual(Property::Index index, bool enable)
848 DALI_LOG_INFO(gLogFilter, Debug::General, "Control::EnableVisual(%d, %s)\n", index, enable ? "T" : "F");
850 RegisteredVisualContainer::Iterator iter;
851 if(FindVisual(index, mVisuals, iter))
853 if((*iter)->enabled == enable)
855 DALI_LOG_INFO(gLogFilter, Debug::Verbose, "Control::EnableVisual Visual %s(%d) already %s\n", (*iter)->visual.GetName().c_str(), index, enable ? "enabled" : "disabled");
859 (*iter)->enabled = enable;
860 Actor parentActor = mControlImpl.Self();
861 if(mControlImpl.Self().GetProperty<bool>(Actor::Property::CONNECTED_TO_SCENE)) // If control not on Scene then Visual will be added when SceneConnection is called.
865 DALI_LOG_INFO(gLogFilter, Debug::Verbose, "Control::EnableVisual Setting %s(%d) on stage \n", (*iter)->visual.GetName().c_str(), index);
866 Toolkit::GetImplementation((*iter)->visual).SetOnScene(parentActor);
870 DALI_LOG_INFO(gLogFilter, Debug::Verbose, "Control::EnableVisual Setting %s(%d) off stage \n", (*iter)->visual.GetName().c_str(), index);
871 Toolkit::GetImplementation((*iter)->visual).SetOffScene(parentActor); // No need to call if control not staged.
877 DALI_LOG_WARNING("Control::EnableVisual(%d, %s) FAILED - NO SUCH VISUAL\n", index, enable ? "T" : "F");
881 bool Control::Impl::IsVisualEnabled(Property::Index index) const
883 RegisteredVisualContainer::Iterator iter;
884 if(FindVisual(index, mVisuals, iter))
886 return (*iter)->enabled;
891 void Control::Impl::StopObservingVisual(Toolkit::Visual::Base& visual)
893 Internal::Visual::Base& visualImpl = Toolkit::GetImplementation(visual);
895 // Stop observing the visual
896 visualImpl.RemoveEventObserver(*this);
899 void Control::Impl::StartObservingVisual(Toolkit::Visual::Base& visual)
901 Internal::Visual::Base& visualImpl = Toolkit::GetImplementation(visual);
903 // start observing the visual for events
904 visualImpl.AddEventObserver(*this);
907 // Called by a Visual when it's resource is ready
908 void Control::Impl::ResourceReady(Visual::Base& object)
910 DALI_LOG_INFO(gLogFilter, Debug::Verbose, "Control::Impl::ResourceReady() replacements pending[%d]\n", mRemoveVisuals.Count());
912 Actor self = mControlImpl.Self();
914 // A resource is ready, find resource in the registered visuals container and get its index
915 for(auto registeredIter = mVisuals.Begin(), end = mVisuals.End(); registeredIter != end; ++registeredIter)
917 Internal::Visual::Base& registeredVisualImpl = Toolkit::GetImplementation((*registeredIter)->visual);
919 if(&object == ®isteredVisualImpl)
921 RegisteredVisualContainer::Iterator visualToRemoveIter;
922 // Find visual with the same index in the removal container
923 // Set if off stage as it's replacement is now ready.
924 // Remove if from removal list as now removed from stage.
925 // Set Pending flag on the ready visual to false as now ready.
926 if(FindVisual((*registeredIter)->index, mRemoveVisuals, visualToRemoveIter))
928 (*registeredIter)->pending = false;
929 Toolkit::GetImplementation((*visualToRemoveIter)->visual).SetOffScene(self);
930 mRemoveVisuals.Erase(visualToRemoveIter);
936 // A visual is ready so control may need relayouting if staged
937 if(self.GetProperty<bool>(Actor::Property::CONNECTED_TO_SCENE))
939 mControlImpl.RelayoutRequest();
942 // Emit signal if all enabled visuals registered by the control are ready.
943 if(IsResourceReady())
946 mNeedToEmitResourceReady = false;
948 EmitResourceReadySignal();
952 void Control::Impl::NotifyVisualEvent(Visual::Base& object, Property::Index signalId)
954 for(auto registeredIter = mVisuals.Begin(), end = mVisuals.End(); registeredIter != end; ++registeredIter)
956 Internal::Visual::Base& registeredVisualImpl = Toolkit::GetImplementation((*registeredIter)->visual);
957 if(&object == ®isteredVisualImpl)
959 Dali::Toolkit::Control handle(mControlImpl.GetOwner());
960 mVisualEventSignal.Emit(handle, (*registeredIter)->index, signalId);
966 bool Control::Impl::IsResourceReady() const
968 // Iterate through and check all the enabled visuals are ready
969 for(auto visualIter = mVisuals.Begin();
970 visualIter != mVisuals.End();
973 const Toolkit::Visual::Base visual = (*visualIter)->visual;
974 const Internal::Visual::Base& visualImpl = Toolkit::GetImplementation(visual);
976 // one of the enabled visuals is not ready
977 if(!visualImpl.IsResourceReady() && (*visualIter)->enabled)
985 Toolkit::Visual::ResourceStatus Control::Impl::GetVisualResourceStatus(Property::Index index) const
987 RegisteredVisualContainer::Iterator iter;
988 if(FindVisual(index, mVisuals, iter))
990 const Toolkit::Visual::Base visual = (*iter)->visual;
991 const Internal::Visual::Base& visualImpl = Toolkit::GetImplementation(visual);
992 return visualImpl.GetResourceStatus();
995 return Toolkit::Visual::ResourceStatus::PREPARING;
998 void Control::Impl::AddTransitions(Dali::Animation& animation,
999 const Toolkit::TransitionData& handle,
1000 bool createAnimation)
1002 // Setup a Transition from TransitionData.
1003 const Internal::TransitionData& transitionData = Toolkit::GetImplementation(handle);
1004 TransitionData::Iterator end = transitionData.End();
1005 for(TransitionData::Iterator iter = transitionData.Begin();
1009 TransitionData::Animator* animator = (*iter);
1011 Toolkit::Visual::Base visual = GetVisualByName(mVisuals, animator->objectName);
1015 #if defined(DEBUG_ENABLED)
1016 Dali::TypeInfo typeInfo;
1017 ControlWrapper* controlWrapperImpl = dynamic_cast<ControlWrapper*>(&mControlImpl);
1018 if(controlWrapperImpl)
1020 typeInfo = controlWrapperImpl->GetTypeInfo();
1023 DALI_LOG_INFO(gLogFilter, Debug::Concise, "CreateTransition: Found %s visual for %s\n", visual.GetName().c_str(), typeInfo ? typeInfo.GetName().c_str() : "Unknown");
1025 Internal::Visual::Base& visualImpl = Toolkit::GetImplementation(visual);
1026 visualImpl.AnimateProperty(animation, *animator);
1030 DALI_LOG_INFO(gLogFilter, Debug::Concise, "CreateTransition: Could not find visual. Trying actors");
1031 // Otherwise, try any actor children of control (Including the control)
1032 Actor child = mControlImpl.Self().FindChildByName(animator->objectName);
1035 Property::Index propertyIndex = child.GetPropertyIndex(animator->propertyKey);
1036 if(propertyIndex != Property::INVALID_INDEX)
1038 if(animator->animate == false)
1040 if(animator->targetValue.GetType() != Property::NONE)
1042 child.SetProperty(propertyIndex, animator->targetValue);
1045 else // animate the property
1047 if(animator->initialValue.GetType() != Property::NONE)
1049 child.SetProperty(propertyIndex, animator->initialValue);
1052 if(createAnimation && !animation)
1054 animation = Dali::Animation::New(0.1f);
1057 animation.AnimateTo(Property(child, propertyIndex),
1058 animator->targetValue,
1059 animator->alphaFunction,
1060 TimePeriod(animator->timePeriodDelay,
1061 animator->timePeriodDuration));
1069 Dali::Animation Control::Impl::CreateTransition(const Toolkit::TransitionData& transitionData)
1071 Dali::Animation transition;
1073 if(transitionData.Count() > 0)
1075 AddTransitions(transition, transitionData, true);
1080 void Control::Impl::DoAction(Dali::Property::Index visualIndex, Dali::Property::Index actionId, const Dali::Property::Value attributes)
1082 RegisteredVisualContainer::Iterator iter;
1083 if(FindVisual(visualIndex, mVisuals, iter))
1085 Toolkit::GetImplementation((*iter)->visual).DoAction(actionId, attributes);
1089 void Control::Impl::AppendAccessibilityAttribute(const std::string& key, const std::string value)
1091 Property::Value* checkedValue = mAccessibilityAttributes.Find(key);
1094 mAccessibilityAttributes[key] = Property::Value(value);
1098 mAccessibilityAttributes.Insert(key, value);
1102 void Control::Impl::SetProperty(BaseObject* object, Property::Index index, const Property::Value& value)
1104 Toolkit::Control control = Toolkit::Control::DownCast(BaseHandle(object));
1108 Control& controlImpl(GetImplementation(control));
1112 case Toolkit::Control::Property::STYLE_NAME:
1114 controlImpl.SetStyleName(value.Get<std::string>());
1118 case Toolkit::DevelControl::Property::STATE:
1120 bool withTransitions = true;
1121 const Property::Value* valuePtr = &value;
1122 const Property::Map* map = value.GetMap();
1125 Property::Value* value2 = map->Find("withTransitions");
1128 withTransitions = value2->Get<bool>();
1131 valuePtr = map->Find("state");
1136 Toolkit::DevelControl::State state(controlImpl.mImpl->mState);
1137 if(Scripting::GetEnumerationProperty<Toolkit::DevelControl::State>(*valuePtr, ControlStateTable, ControlStateTableCount, state))
1139 controlImpl.mImpl->SetState(state, withTransitions);
1145 case Toolkit::DevelControl::Property::SUB_STATE:
1147 std::string subState;
1148 if(value.Get(subState))
1150 controlImpl.mImpl->SetSubState(subState);
1155 case Toolkit::DevelControl::Property::LEFT_FOCUSABLE_ACTOR_ID:
1158 if(value.Get(focusId))
1160 controlImpl.mImpl->mLeftFocusableActorId = focusId;
1165 case Toolkit::DevelControl::Property::RIGHT_FOCUSABLE_ACTOR_ID:
1168 if(value.Get(focusId))
1170 controlImpl.mImpl->mRightFocusableActorId = focusId;
1175 case Toolkit::DevelControl::Property::UP_FOCUSABLE_ACTOR_ID:
1178 if(value.Get(focusId))
1180 controlImpl.mImpl->mUpFocusableActorId = focusId;
1185 case Toolkit::DevelControl::Property::DOWN_FOCUSABLE_ACTOR_ID:
1188 if(value.Get(focusId))
1190 controlImpl.mImpl->mDownFocusableActorId = focusId;
1195 case Toolkit::Control::Property::KEY_INPUT_FOCUS:
1197 if(value.Get<bool>())
1199 controlImpl.SetKeyInputFocus();
1203 controlImpl.ClearKeyInputFocus();
1208 case Toolkit::Control::Property::BACKGROUND:
1212 const Property::Map* map = value.GetMap();
1213 if(map && !map->Empty())
1215 controlImpl.SetBackground(*map);
1217 else if(value.Get(url))
1219 // don't know the size to load
1220 Toolkit::Visual::Base visual = Toolkit::VisualFactory::Get().CreateVisual(url, ImageDimensions());
1223 controlImpl.mImpl->RegisterVisual(Toolkit::Control::Property::BACKGROUND, visual, DepthIndex::BACKGROUND);
1226 else if(value.Get(color))
1228 controlImpl.SetBackgroundColor(color);
1232 // The background is an empty property map, so we should clear the background
1233 controlImpl.ClearBackground();
1238 case Toolkit::Control::Property::MARGIN:
1241 if(value.Get(margin))
1243 controlImpl.mImpl->SetMargin(margin);
1248 case Toolkit::Control::Property::PADDING:
1251 if(value.Get(padding))
1253 controlImpl.mImpl->SetPadding(padding);
1258 case Toolkit::DevelControl::Property::TOOLTIP:
1260 TooltipPtr& tooltipPtr = controlImpl.mImpl->mTooltip;
1263 tooltipPtr = Tooltip::New(control);
1265 tooltipPtr->SetProperties(value);
1269 case Toolkit::DevelControl::Property::SHADOW:
1271 const Property::Map* map = value.GetMap();
1272 if(map && !map->Empty())
1274 controlImpl.mImpl->SetShadow(*map);
1278 // The shadow is an empty property map, so we should clear the shadow
1279 controlImpl.mImpl->ClearShadow();
1284 case Toolkit::DevelControl::Property::ACCESSIBILITY_NAME:
1289 controlImpl.mImpl->mAccessibilityName = name;
1290 controlImpl.mImpl->mAccessibilityNameSet = true;
1294 controlImpl.mImpl->mAccessibilityNameSet = false;
1299 case Toolkit::DevelControl::Property::ACCESSIBILITY_DESCRIPTION:
1304 controlImpl.mImpl->mAccessibilityDescription = text;
1305 controlImpl.mImpl->mAccessibilityDescriptionSet = true;
1309 controlImpl.mImpl->mAccessibilityDescriptionSet = false;
1314 case Toolkit::DevelControl::Property::ACCESSIBILITY_TRANSLATION_DOMAIN:
1319 controlImpl.mImpl->mAccessibilityTranslationDomain = text;
1320 controlImpl.mImpl->mAccessibilityTranslationDomainSet = true;
1324 controlImpl.mImpl->mAccessibilityTranslationDomainSet = false;
1329 case Toolkit::DevelControl::Property::ACCESSIBILITY_ROLE:
1331 Dali::Accessibility::Role role;
1334 controlImpl.mImpl->mAccessibilityRole = role;
1339 case Toolkit::DevelControl::Property::ACCESSIBILITY_HIGHLIGHTABLE:
1342 if(value.Get(highlightable))
1344 controlImpl.mImpl->mAccessibilityHighlightable = highlightable;
1345 controlImpl.mImpl->mAccessibilityHighlightableSet = true;
1349 controlImpl.mImpl->mAccessibilityHighlightableSet = false;
1354 case Toolkit::DevelControl::Property::ACCESSIBILITY_ATTRIBUTES:
1356 const Property::Map* map = value.GetMap();
1357 if(map && !map->Empty())
1359 controlImpl.mImpl->mAccessibilityAttributes = *map;
1364 case Toolkit::DevelControl::Property::DISPATCH_KEY_EVENTS:
1367 if(value.Get(dispatch))
1369 controlImpl.mImpl->mDispatchKeyEvents = dispatch;
1374 case Toolkit::DevelControl::Property::ACCESSIBILITY_HIDDEN:
1377 if(value.Get(hidden))
1379 controlImpl.mImpl->mAccessibilityHidden = hidden;
1381 auto* accessible = controlImpl.mImpl->GetAccessibilityObject();
1382 auto* parent = dynamic_cast<Dali::Accessibility::ActorAccessible*>(accessible->GetParent());
1385 parent->OnChildrenChanged();
1394 Property::Value Control::Impl::GetProperty(BaseObject* object, Property::Index index)
1396 Property::Value value;
1398 Toolkit::Control control = Toolkit::Control::DownCast(BaseHandle(object));
1402 Control& controlImpl(GetImplementation(control));
1406 case Toolkit::Control::Property::STYLE_NAME:
1408 value = controlImpl.GetStyleName();
1412 case Toolkit::DevelControl::Property::STATE:
1414 value = controlImpl.mImpl->mState;
1418 case Toolkit::DevelControl::Property::SUB_STATE:
1420 value = controlImpl.mImpl->mSubStateName;
1424 case Toolkit::DevelControl::Property::LEFT_FOCUSABLE_ACTOR_ID:
1426 value = controlImpl.mImpl->mLeftFocusableActorId;
1430 case Toolkit::DevelControl::Property::RIGHT_FOCUSABLE_ACTOR_ID:
1432 value = controlImpl.mImpl->mRightFocusableActorId;
1436 case Toolkit::DevelControl::Property::UP_FOCUSABLE_ACTOR_ID:
1438 value = controlImpl.mImpl->mUpFocusableActorId;
1442 case Toolkit::DevelControl::Property::DOWN_FOCUSABLE_ACTOR_ID:
1444 value = controlImpl.mImpl->mDownFocusableActorId;
1448 case Toolkit::Control::Property::KEY_INPUT_FOCUS:
1450 value = controlImpl.HasKeyInputFocus();
1454 case Toolkit::Control::Property::BACKGROUND:
1457 Toolkit::Visual::Base visual = controlImpl.mImpl->GetVisual(Toolkit::Control::Property::BACKGROUND);
1460 visual.CreatePropertyMap(map);
1467 case Toolkit::Control::Property::MARGIN:
1469 value = controlImpl.mImpl->GetMargin();
1473 case Toolkit::Control::Property::PADDING:
1475 value = controlImpl.mImpl->GetPadding();
1479 case Toolkit::DevelControl::Property::TOOLTIP:
1482 if(controlImpl.mImpl->mTooltip)
1484 controlImpl.mImpl->mTooltip->CreatePropertyMap(map);
1490 case Toolkit::DevelControl::Property::SHADOW:
1493 Toolkit::Visual::Base visual = controlImpl.mImpl->GetVisual(Toolkit::DevelControl::Property::SHADOW);
1496 visual.CreatePropertyMap(map);
1503 case Toolkit::DevelControl::Property::ACCESSIBILITY_NAME:
1505 if(controlImpl.mImpl->mAccessibilityNameSet)
1507 value = controlImpl.mImpl->mAccessibilityName;
1512 case Toolkit::DevelControl::Property::ACCESSIBILITY_DESCRIPTION:
1514 if(controlImpl.mImpl->mAccessibilityDescriptionSet)
1516 value = controlImpl.mImpl->mAccessibilityDescription;
1521 case Toolkit::DevelControl::Property::ACCESSIBILITY_TRANSLATION_DOMAIN:
1523 if(controlImpl.mImpl->mAccessibilityTranslationDomainSet)
1525 value = controlImpl.mImpl->mAccessibilityTranslationDomain;
1530 case Toolkit::DevelControl::Property::ACCESSIBILITY_ROLE:
1532 value = Property::Value(controlImpl.mImpl->mAccessibilityRole);
1536 case Toolkit::DevelControl::Property::ACCESSIBILITY_HIGHLIGHTABLE:
1538 if(controlImpl.mImpl->mAccessibilityHighlightableSet)
1540 value = controlImpl.mImpl->mAccessibilityHighlightable;
1545 case Toolkit::DevelControl::Property::ACCESSIBILITY_ATTRIBUTES:
1547 value = controlImpl.mImpl->mAccessibilityAttributes;
1551 case Toolkit::DevelControl::Property::DISPATCH_KEY_EVENTS:
1553 value = controlImpl.mImpl->mDispatchKeyEvents;
1557 case Toolkit::DevelControl::Property::ACCESSIBILITY_HIDDEN:
1559 value = controlImpl.mImpl->mAccessibilityHidden;
1568 void Control::Impl::RemoveAccessibilityAttribute(const std::string& key)
1570 Property::Value* value = mAccessibilityAttributes.Find(key);
1573 mAccessibilityAttributes[key] = Property::Value();
1577 void Control::Impl::ClearAccessibilityAttributes()
1579 mAccessibilityAttributes.Clear();
1582 void Control::Impl::SetAccessibilityReadingInfoType(const Dali::Accessibility::ReadingInfoTypes types)
1584 std::string value{};
1585 if(types[Dali::Accessibility::ReadingInfoType::NAME])
1587 value += READING_INFO_TYPE_NAME;
1589 if(types[Dali::Accessibility::ReadingInfoType::ROLE])
1593 value += READING_INFO_TYPE_SEPARATOR;
1595 value += READING_INFO_TYPE_ROLE;
1597 if(types[Dali::Accessibility::ReadingInfoType::DESCRIPTION])
1601 value += READING_INFO_TYPE_SEPARATOR;
1603 value += READING_INFO_TYPE_DESCRIPTION;
1605 if(types[Dali::Accessibility::ReadingInfoType::STATE])
1609 value += READING_INFO_TYPE_SEPARATOR;
1611 value += READING_INFO_TYPE_STATE;
1613 AppendAccessibilityAttribute(READING_INFO_TYPE_ATTRIBUTE_NAME, value);
1616 Dali::Accessibility::ReadingInfoTypes Control::Impl::GetAccessibilityReadingInfoType() const
1618 std::string value{};
1619 auto place = mAccessibilityAttributes.Find(READING_INFO_TYPE_ATTRIBUTE_NAME);
1626 Dali::Accessibility::ReadingInfoTypes types;
1627 types[Dali::Accessibility::ReadingInfoType::NAME] = true;
1628 types[Dali::Accessibility::ReadingInfoType::ROLE] = true;
1629 types[Dali::Accessibility::ReadingInfoType::DESCRIPTION] = true;
1630 types[Dali::Accessibility::ReadingInfoType::STATE] = true;
1639 Dali::Accessibility::ReadingInfoTypes types;
1641 if(value.find(READING_INFO_TYPE_NAME) != std::string::npos)
1643 types[Dali::Accessibility::ReadingInfoType::NAME] = true;
1645 if(value.find(READING_INFO_TYPE_ROLE) != std::string::npos)
1647 types[Dali::Accessibility::ReadingInfoType::ROLE] = true;
1649 if(value.find(READING_INFO_TYPE_DESCRIPTION) != std::string::npos)
1651 types[Dali::Accessibility::ReadingInfoType::DESCRIPTION] = true;
1653 if(value.find(READING_INFO_TYPE_STATE) != std::string::npos)
1655 types[Dali::Accessibility::ReadingInfoType::STATE] = true;
1661 void Control::Impl::CopyInstancedProperties(RegisteredVisualContainer& visuals, Dictionary<Property::Map>& instancedProperties)
1663 for(RegisteredVisualContainer::Iterator iter = visuals.Begin(); iter != visuals.End(); iter++)
1667 Property::Map instanceMap;
1668 Toolkit::GetImplementation((*iter)->visual).CreateInstancePropertyMap(instanceMap);
1669 instancedProperties.Add((*iter)->visual.GetName(), instanceMap);
1674 void Control::Impl::RemoveVisual(RegisteredVisualContainer& visuals, const std::string& visualName)
1676 Actor self(mControlImpl.Self());
1678 for(RegisteredVisualContainer::Iterator visualIter = visuals.Begin();
1679 visualIter != visuals.End();
1682 Toolkit::Visual::Base visual = (*visualIter)->visual;
1683 if(visual && visual.GetName() == visualName)
1685 Toolkit::GetImplementation(visual).SetOffScene(self);
1686 (*visualIter)->visual.Reset();
1687 visuals.Erase(visualIter);
1693 void Control::Impl::RemoveVisuals(RegisteredVisualContainer& visuals, DictionaryKeys& removeVisuals)
1695 Actor self(mControlImpl.Self());
1696 for(DictionaryKeys::iterator iter = removeVisuals.begin(); iter != removeVisuals.end(); ++iter)
1698 const std::string visualName = *iter;
1699 RemoveVisual(visuals, visualName);
1703 void Control::Impl::RecreateChangedVisuals(Dictionary<Property::Map>& stateVisualsToChange,
1704 Dictionary<Property::Map>& instancedProperties)
1706 Dali::CustomActor handle(mControlImpl.GetOwner());
1707 for(Dictionary<Property::Map>::iterator iter = stateVisualsToChange.Begin();
1708 iter != stateVisualsToChange.End();
1711 const std::string& visualName = (*iter).key;
1712 const Property::Map& toMap = (*iter).entry;
1714 Actor self = mControlImpl.Self();
1715 RegisteredVisualContainer::Iterator registeredVisualsiter;
1716 // Check if visual (visualName) is already registered, this is the current visual.
1717 if(FindVisual(visualName, mVisuals, registeredVisualsiter))
1719 Toolkit::Visual::Base& visual = (*registeredVisualsiter)->visual;
1722 // No longer required to know if the replaced visual's resources are ready
1723 StopObservingVisual(visual);
1725 // If control staged then visuals will be swapped once ready
1726 if(self.GetProperty<bool>(Actor::Property::CONNECTED_TO_SCENE))
1728 // Check if visual is currently in the process of being replaced ( is in removal container )
1729 RegisteredVisualContainer::Iterator visualQueuedForRemoval;
1730 if(FindVisual(visualName, mRemoveVisuals, visualQueuedForRemoval))
1732 // Visual with same visual name is already in removal container so current visual pending
1733 // Only the the last requested visual will be displayed so remove current visual which is staged but not ready.
1734 Toolkit::GetImplementation(visual).SetOffScene(self);
1735 (*registeredVisualsiter)->visual.Reset();
1736 mVisuals.Erase(registeredVisualsiter);
1740 // current visual not already in removal container so add now.
1741 DALI_LOG_INFO(gLogFilter, Debug::Verbose, "RegisterVisual Move current registered visual to removal Queue: %s \n", visualName.c_str());
1742 MoveVisual(registeredVisualsiter, mVisuals, mRemoveVisuals);
1747 // Control not staged or visual disabled so can just erase from registered visuals and new visual will be added later.
1748 (*registeredVisualsiter)->visual.Reset();
1749 mVisuals.Erase(registeredVisualsiter);
1753 const Property::Map* instancedMap = instancedProperties.FindConst(visualName);
1754 Style::ApplyVisual(handle, visualName, toMap, instancedMap);
1759 void Control::Impl::ReplaceStateVisualsAndProperties(const StylePtr oldState, const StylePtr newState, const std::string& subState)
1761 // Collect all old visual names
1762 DictionaryKeys stateVisualsToRemove;
1765 oldState->visuals.GetKeys(stateVisualsToRemove);
1766 if(!subState.empty())
1768 const StylePtr* oldSubState = oldState->subStates.FindConst(subState);
1771 DictionaryKeys subStateVisualsToRemove;
1772 (*oldSubState)->visuals.GetKeys(subStateVisualsToRemove);
1773 Merge(stateVisualsToRemove, subStateVisualsToRemove);
1778 // Collect all new visual properties
1779 Dictionary<Property::Map> stateVisualsToAdd;
1782 stateVisualsToAdd = newState->visuals;
1783 if(!subState.empty())
1785 const StylePtr* newSubState = newState->subStates.FindConst(subState);
1788 stateVisualsToAdd.Merge((*newSubState)->visuals);
1793 // If a name is in both add/remove, move it to change list.
1794 Dictionary<Property::Map> stateVisualsToChange;
1795 FindChangableVisuals(stateVisualsToAdd, stateVisualsToChange, stateVisualsToRemove);
1797 // Copy instanced properties (e.g. text label) of current visuals
1798 Dictionary<Property::Map> instancedProperties;
1799 CopyInstancedProperties(mVisuals, instancedProperties);
1801 // For each visual in remove list, remove from mVisuals
1802 RemoveVisuals(mVisuals, stateVisualsToRemove);
1804 // For each visual in add list, create and add to mVisuals
1805 Dali::CustomActor handle(mControlImpl.GetOwner());
1806 Style::ApplyVisuals(handle, stateVisualsToAdd, instancedProperties);
1808 // For each visual in change list, if it requires a new visual,
1809 // remove old visual, create and add to mVisuals
1810 RecreateChangedVisuals(stateVisualsToChange, instancedProperties);
1813 void Control::Impl::SetState(DevelControl::State newState, bool withTransitions)
1815 DevelControl::State oldState = mState;
1816 Dali::CustomActor handle(mControlImpl.GetOwner());
1817 DALI_LOG_INFO(gLogFilter, Debug::Concise, "Control::Impl::SetState: %s\n", (mState == DevelControl::NORMAL ? "NORMAL" : (mState == DevelControl::FOCUSED ? "FOCUSED" : (mState == DevelControl::DISABLED ? "DISABLED" : "NONE"))));
1819 if(mState != newState)
1821 // If mState was Disabled, and new state is Focused, should probably
1822 // store that fact, e.g. in another property that FocusManager can access.
1825 // Trigger state change and transitions
1826 // Apply new style, if stylemanager is available
1827 Toolkit::StyleManager styleManager = Toolkit::StyleManager::Get();
1830 const StylePtr stylePtr = GetImpl(styleManager).GetRecordedStyle(Toolkit::Control(mControlImpl.GetOwner()));
1834 std::string oldStateName = Scripting::GetEnumerationName<Toolkit::DevelControl::State>(oldState, ControlStateTable, ControlStateTableCount);
1835 std::string newStateName = Scripting::GetEnumerationName<Toolkit::DevelControl::State>(newState, ControlStateTable, ControlStateTableCount);
1837 const StylePtr* newStateStyle = stylePtr->subStates.Find(newStateName);
1838 const StylePtr* oldStateStyle = stylePtr->subStates.Find(oldStateName);
1839 if(oldStateStyle && newStateStyle)
1841 // Only change if both state styles exist
1842 ReplaceStateVisualsAndProperties(*oldStateStyle, *newStateStyle, mSubStateName);
1849 void Control::Impl::SetSubState(const std::string& subStateName, bool withTransitions)
1851 if(mSubStateName != subStateName)
1853 // Get existing sub-state visuals, and unregister them
1854 Dali::CustomActor handle(mControlImpl.GetOwner());
1856 Toolkit::StyleManager styleManager = Toolkit::StyleManager::Get();
1859 const StylePtr stylePtr = GetImpl(styleManager).GetRecordedStyle(Toolkit::Control(mControlImpl.GetOwner()));
1863 std::string stateName = Scripting::GetEnumerationName<Toolkit::DevelControl::State>(mState, ControlStateTable, ControlStateTableCount);
1865 const StylePtr* state = stylePtr->subStates.Find(stateName);
1868 StylePtr stateStyle(*state);
1870 const StylePtr* newStateStyle = stateStyle->subStates.Find(subStateName);
1871 const StylePtr* oldStateStyle = stateStyle->subStates.Find(mSubStateName);
1872 if(oldStateStyle && newStateStyle)
1875 ReplaceStateVisualsAndProperties(*oldStateStyle, *newStateStyle, empty);
1881 mSubStateName = subStateName;
1885 void Control::Impl::OnSceneDisconnection()
1887 Actor self = mControlImpl.Self();
1889 // Any visuals set for replacement but not yet ready should still be registered.
1890 // Reason: If a request was made to register a new visual but the control removed from scene before visual was ready
1891 // then when this control appears back on stage it should use that new visual.
1893 // Iterate through all registered visuals and set off scene
1894 SetVisualsOffScene(mVisuals, self);
1896 // Visuals pending replacement can now be taken out of the removal list and set off scene
1897 // Iterate through all replacement visuals and add to a move queue then set off scene
1898 for(auto removalIter = mRemoveVisuals.Begin(), end = mRemoveVisuals.End(); removalIter != end; removalIter++)
1900 Toolkit::GetImplementation((*removalIter)->visual).SetOffScene(self);
1903 for(auto replacedIter = mVisuals.Begin(), end = mVisuals.End(); replacedIter != end; replacedIter++)
1905 (*replacedIter)->pending = false;
1908 mRemoveVisuals.Clear();
1911 void Control::Impl::SetMargin(Extents margin)
1913 mControlImpl.mImpl->mMargin = margin;
1915 // Trigger a size negotiation request that may be needed when setting a margin.
1916 mControlImpl.RelayoutRequest();
1919 Extents Control::Impl::GetMargin() const
1921 return mControlImpl.mImpl->mMargin;
1924 void Control::Impl::SetPadding(Extents padding)
1926 mControlImpl.mImpl->mPadding = padding;
1928 // Trigger a size negotiation request that may be needed when setting a padding.
1929 mControlImpl.RelayoutRequest();
1932 Extents Control::Impl::GetPadding() const
1934 return mControlImpl.mImpl->mPadding;
1937 void Control::Impl::SetInputMethodContext(InputMethodContext& inputMethodContext)
1939 mInputMethodContext = inputMethodContext;
1942 bool Control::Impl::FilterKeyEvent(const KeyEvent& event)
1944 bool consumed(false);
1946 if(mInputMethodContext)
1948 consumed = mInputMethodContext.FilterEventKey(event);
1953 DevelControl::VisualEventSignalType& Control::Impl::VisualEventSignal()
1955 return mVisualEventSignal;
1958 void Control::Impl::SetShadow(const Property::Map& map)
1960 Toolkit::Visual::Base visual = Toolkit::VisualFactory::Get().CreateVisual(map);
1961 visual.SetName("shadow");
1965 mControlImpl.mImpl->RegisterVisual(Toolkit::DevelControl::Property::SHADOW, visual, DepthIndex::BACKGROUND_EFFECT);
1967 mControlImpl.RelayoutRequest();
1971 void Control::Impl::ClearShadow()
1973 mControlImpl.mImpl->UnregisterVisual(Toolkit::DevelControl::Property::SHADOW);
1975 // Trigger a size negotiation request that may be needed when unregistering a visual.
1976 mControlImpl.RelayoutRequest();
1979 Dali::Property Control::Impl::GetVisualProperty(Dali::Property::Index index, Dali::Property::Key visualPropertyKey)
1981 Toolkit::Visual::Base visual = GetVisualByIndex(mVisuals, index);
1984 Internal::Visual::Base& visualImpl = Toolkit::GetImplementation(visual);
1985 return visualImpl.GetPropertyObject(visualPropertyKey);
1989 return Dali::Property(handle, Property::INVALID_INDEX);
1992 void Control::Impl::CreateTransitions(std::vector<std::pair<Dali::Property::Index, Dali::Property::Map>>& sourceProperties,
1993 std::vector<std::pair<Dali::Property::Index, Dali::Property::Map>>& destinationProperties,
1994 Dali::Toolkit::Control source, Dali::Toolkit::Control destination)
1996 // Retrieves background properties to be transitioned.
1997 Dali::Property::Map backgroundSourcePropertyMap, backgroundDestinationPropertyMap;
1998 mControlImpl.MakeVisualTransition(backgroundSourcePropertyMap, backgroundDestinationPropertyMap, source, destination, Toolkit::Control::Property::BACKGROUND);
1999 if(backgroundSourcePropertyMap.Count() > 0)
2001 sourceProperties.push_back(std::pair<Dali::Property::Index, Dali::Property::Map>(Toolkit::Control::Property::BACKGROUND, backgroundSourcePropertyMap));
2002 destinationProperties.push_back(std::pair<Dali::Property::Index, Dali::Property::Map>(Toolkit::Control::Property::BACKGROUND, backgroundDestinationPropertyMap));
2005 // Retrieves shadow properties to be transitioned.
2006 Dali::Property::Map shadowSourcePropertyMap, shadowDestinationPropertyMap;
2007 mControlImpl.MakeVisualTransition(shadowSourcePropertyMap, shadowDestinationPropertyMap, source, destination, Toolkit::DevelControl::Property::SHADOW);
2008 if(shadowSourcePropertyMap.Count() > 0)
2010 sourceProperties.push_back(std::pair<Dali::Property::Index, Dali::Property::Map>(Toolkit::DevelControl::Property::SHADOW, shadowSourcePropertyMap));
2011 destinationProperties.push_back(std::pair<Dali::Property::Index, Dali::Property::Map>(Toolkit::DevelControl::Property::SHADOW, shadowDestinationPropertyMap));
2014 // Retrieves transition from inherited class.
2015 mControlImpl.OnCreateTransitions(sourceProperties, destinationProperties, source, destination);
2018 void Control::Impl::UpdateVisualProperties(const std::vector<std::pair<Dali::Property::Index, Dali::Property::Map>>& properties)
2020 for(auto&& data : properties)
2022 if(data.first == Toolkit::Control::Property::BACKGROUND)
2024 DoAction(Toolkit::Control::Property::BACKGROUND, DevelVisual::Action::UPDATE_PROPERTY, data.second);
2026 else if(data.first == Toolkit::DevelControl::Property::SHADOW)
2028 DoAction(Toolkit::DevelControl::Property::SHADOW, DevelVisual::Action::UPDATE_PROPERTY, data.second);
2031 mControlImpl.OnUpdateVisualProperties(properties);
2034 void Control::Impl::EmitResourceReadySignal()
2036 if(!mIsEmittingResourceReadySignal)
2038 // Guard against calls to emit the signal during the callback
2039 mIsEmittingResourceReadySignal = true;
2041 // If the signal handler changes visual, it may become ready during this call & therefore this method will
2042 // get called again recursively. If so, mNeedToEmitResourceReady is set below, and we act on it after that secondary
2043 // invocation has completed by notifying in an Idle callback to prevent further recursion.
2044 Dali::Toolkit::Control handle(mControlImpl.GetOwner());
2045 mResourceReadySignal.Emit(handle);
2047 if(mNeedToEmitResourceReady)
2049 // Add idler to emit the signal again
2052 // The callback manager takes the ownership of the callback object.
2053 mIdleCallback = MakeCallback(this, &Control::Impl::OnIdleCallback);
2054 Adaptor::Get().AddIdle(mIdleCallback, false);
2058 mIsEmittingResourceReadySignal = false;
2062 mNeedToEmitResourceReady = true;
2066 void Control::Impl::OnIdleCallback()
2068 if(mNeedToEmitResourceReady)
2071 mNeedToEmitResourceReady = false;
2073 // A visual is ready so control may need relayouting if staged
2074 if(mControlImpl.Self().GetProperty<bool>(Actor::Property::CONNECTED_TO_SCENE))
2076 mControlImpl.RelayoutRequest();
2079 EmitResourceReadySignal();
2082 // Set the pointer to null as the callback manager deletes the callback after execute it.
2083 mIdleCallback = nullptr;
2086 Dali::Accessibility::Accessible* Control::Impl::GetAccessibilityObject()
2088 if(!mAccessibilityObject)
2090 mAccessibilityObject = mAccessibilityConstructor(mControlImpl.Self());
2092 return mAccessibilityObject.get();
2095 Dali::Accessibility::Accessible* Control::Impl::GetAccessibilityObject(Dali::Actor actor)
2099 auto control = Dali::Toolkit::Control::DownCast(actor);
2102 auto controlImpl = static_cast<Internal::Control*>(&control.GetImplementation());
2103 return controlImpl->mImpl->GetAccessibilityObject();
2109 } // namespace Internal
2111 } // namespace Toolkit