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);
475 Control::Impl::Impl(Control& controlImpl)
476 : mControlImpl(controlImpl),
477 mState(Toolkit::DevelControl::NORMAL),
479 mLeftFocusableActorId(-1),
480 mRightFocusableActorId(-1),
481 mUpFocusableActorId(-1),
482 mDownFocusableActorId(-1),
484 mBackgroundColor(Color::TRANSPARENT),
485 mStartingPinchScale(nullptr),
487 mPadding(0, 0, 0, 0),
489 mKeyInputFocusGainedSignal(),
490 mKeyInputFocusLostSignal(),
491 mResourceReadySignal(),
492 mVisualEventSignal(),
493 mAccessibilityGetNameSignal(),
494 mAccessibilityGetDescriptionSignal(),
495 mAccessibilityDoGestureSignal(),
496 mPinchGestureDetector(),
497 mPanGestureDetector(),
498 mTapGestureDetector(),
499 mLongPressGestureDetector(),
501 mInputMethodContext(),
502 mIdleCallback(nullptr),
503 mFlags(Control::ControlBehaviour(CONTROL_BEHAVIOUR_DEFAULT)),
504 mIsKeyboardNavigationSupported(false),
505 mIsKeyboardFocusGroup(false),
506 mIsEmittingResourceReadySignal(false),
507 mNeedToEmitResourceReady(false),
508 mDispatchKeyEvents(true)
510 Dali::Accessibility::Accessible::RegisterExternalAccessibleGetter(
511 [](Dali::Actor actor) -> Dali::Accessibility::Accessible* {
512 return Control::Impl::GetAccessibilityObject(actor);
515 mAccessibilityConstructor = [](Dali::Actor actor) -> std::unique_ptr<Dali::Accessibility::Accessible> {
516 return std::unique_ptr<Dali::Accessibility::Accessible>(new DevelControl::ControlAccessible(actor, Dali::Accessibility::Role::UNKNOWN));
520 Control::Impl::~Impl()
522 for(auto&& iter : mVisuals)
524 StopObservingVisual(iter->visual);
527 for(auto&& iter : mRemoveVisuals)
529 StopObservingVisual(iter->visual);
532 // All gesture detectors will be destroyed so no need to disconnect.
533 delete mStartingPinchScale;
535 if(mIdleCallback && Adaptor::IsAvailable())
537 // Removes the callback from the callback manager in case the control is destroyed before the callback is executed.
538 Adaptor::Get().RemoveIdle(mIdleCallback);
542 Control::Impl& Control::Impl::Get(Internal::Control& internalControl)
544 return *internalControl.mImpl;
547 const Control::Impl& Control::Impl::Get(const Internal::Control& internalControl)
549 return *internalControl.mImpl;
552 void Control::Impl::CheckHighlightedObjectGeometry()
554 auto accessible = dynamic_cast<Dali::Toolkit::DevelControl::ControlAccessible*>(mAccessibilityObject.get());
557 DALI_LOG_ERROR("accessible is not a pointer to a DevelControl::ControlAccessible type");
561 auto lastPosition = accessible->GetLastPosition();
562 auto accessibleRect = accessible->GetExtents(Dali::Accessibility::CoordinateType::WINDOW);
563 auto rect = GetShowingGeometry(accessibleRect, accessible);
565 switch(mAccessibilityLastScreenRelativeMoveType)
567 case Dali::Accessibility::ScreenRelativeMoveType::OUTSIDE:
569 if(IsShowingGeometryOnScreen(rect))
571 mAccessibilityLastScreenRelativeMoveType = Dali::Accessibility::ScreenRelativeMoveType::INSIDE;
575 case Dali::Accessibility::ScreenRelativeMoveType::INSIDE:
577 if(rect.width < 0 && accessibleRect.x != lastPosition.x)
579 mAccessibilityLastScreenRelativeMoveType = (accessibleRect.x < lastPosition.x) ? Dali::Accessibility::ScreenRelativeMoveType::OUTGOING_TOP_LEFT : Dali::Accessibility::ScreenRelativeMoveType::OUTGOING_BOTTOM_RIGHT;
581 if(rect.height < 0 && accessibleRect.y != lastPosition.y)
583 mAccessibilityLastScreenRelativeMoveType = (accessibleRect.y < lastPosition.y) ? Dali::Accessibility::ScreenRelativeMoveType::OUTGOING_TOP_LEFT : Dali::Accessibility::ScreenRelativeMoveType::OUTGOING_BOTTOM_RIGHT;
585 // notify AT-clients on outgoing moves only
586 if(mAccessibilityLastScreenRelativeMoveType != Dali::Accessibility::ScreenRelativeMoveType::INSIDE)
588 mAccessibilityObject.get()->EmitMovedOutOfScreen(mAccessibilityLastScreenRelativeMoveType);
592 case Dali::Accessibility::ScreenRelativeMoveType::OUTGOING_TOP_LEFT:
593 case Dali::Accessibility::ScreenRelativeMoveType::OUTGOING_BOTTOM_RIGHT:
595 if(IsShowingGeometryOnScreen(rect))
597 mAccessibilityLastScreenRelativeMoveType = Dali::Accessibility::ScreenRelativeMoveType::INSIDE;
601 mAccessibilityLastScreenRelativeMoveType = Dali::Accessibility::ScreenRelativeMoveType::OUTSIDE;
611 accessible->SetLastPosition(Vector2(accessibleRect.x, accessibleRect.y));
614 void Control::Impl::RegisterAccessibilityPositionPropertyNotification()
616 if(mIsAccessibilityPositionPropertyNotificationSet)
620 // set default value until first move of object is detected
621 mAccessibilityLastScreenRelativeMoveType = Dali::Accessibility::ScreenRelativeMoveType::OUTSIDE;
622 // recalculate mAccessibilityLastScreenRelativeMoveType accordingly to the initial position
623 CheckHighlightedObjectGeometry();
624 mAccessibilityPositionNotification = mControlImpl.Self().AddPropertyNotification(Actor::Property::WORLD_POSITION, StepCondition(1.0f, 1.0f));
625 mAccessibilityPositionNotification.SetNotifyMode(PropertyNotification::NOTIFY_ON_CHANGED);
626 mAccessibilityPositionNotification.NotifySignal().Connect(this, [this](PropertyNotification&){ CheckHighlightedObjectGeometry(); });
627 mIsAccessibilityPositionPropertyNotificationSet = true;
630 void Control::Impl::UnregisterAccessibilityPositionPropertyNotification()
632 mControlImpl.Self().RemovePropertyNotification(mAccessibilityPositionNotification);
633 mIsAccessibilityPositionPropertyNotificationSet = false;
636 // Gesture Detection Methods
637 void Control::Impl::PinchDetected(Actor actor, const PinchGesture& pinch)
639 mControlImpl.OnPinch(pinch);
642 void Control::Impl::PanDetected(Actor actor, const PanGesture& pan)
644 mControlImpl.OnPan(pan);
647 void Control::Impl::TapDetected(Actor actor, const TapGesture& tap)
649 mControlImpl.OnTap(tap);
652 void Control::Impl::LongPressDetected(Actor actor, const LongPressGesture& longPress)
654 mControlImpl.OnLongPress(longPress);
657 void Control::Impl::RegisterVisual(Property::Index index, Toolkit::Visual::Base& visual)
659 RegisterVisual(index, visual, VisualState::ENABLED, DepthIndexValue::NOT_SET);
662 void Control::Impl::RegisterVisual(Property::Index index, Toolkit::Visual::Base& visual, int depthIndex)
664 RegisterVisual(index, visual, VisualState::ENABLED, DepthIndexValue::SET, depthIndex);
667 void Control::Impl::RegisterVisual(Property::Index index, Toolkit::Visual::Base& visual, bool enabled)
669 RegisterVisual(index, visual, (enabled ? VisualState::ENABLED : VisualState::DISABLED), DepthIndexValue::NOT_SET);
672 void Control::Impl::RegisterVisual(Property::Index index, Toolkit::Visual::Base& visual, bool enabled, int depthIndex)
674 RegisterVisual(index, visual, (enabled ? VisualState::ENABLED : VisualState::DISABLED), DepthIndexValue::SET, depthIndex);
677 void Control::Impl::RegisterVisual(Property::Index index, Toolkit::Visual::Base& visual, VisualState::Type enabled, DepthIndexValue::Type depthIndexValueSet, int depthIndex)
679 DALI_LOG_INFO(gLogFilter, Debug::Concise, "RegisterVisual:%d \n", index);
681 bool visualReplaced(false);
682 Actor self = mControlImpl.Self();
684 // Set the depth index, if not set by caller this will be either the current visual depth, max depth of all visuals
686 int requiredDepthIndex = visual.GetDepthIndex();
688 if(depthIndexValueSet == DepthIndexValue::SET)
690 requiredDepthIndex = depthIndex;
693 // Visual replacement, existing visual should only be removed from stage when replacement ready.
694 if(!mVisuals.Empty())
696 RegisteredVisualContainer::Iterator registeredVisualsiter;
697 // Check if visual (index) is already registered, this is the current visual.
698 if(FindVisual(index, mVisuals, registeredVisualsiter))
700 Toolkit::Visual::Base& currentRegisteredVisual = (*registeredVisualsiter)->visual;
701 if(currentRegisteredVisual)
703 // Store current visual depth index as may need to set the replacement visual to same depth
704 const int currentDepthIndex = (*registeredVisualsiter)->visual.GetDepthIndex();
706 // No longer required to know if the replaced visual's resources are ready
707 StopObservingVisual(currentRegisteredVisual);
709 // If control staged and visual enabled then visuals will be swapped once ready
710 if(self.GetProperty<bool>(Actor::Property::CONNECTED_TO_SCENE) && enabled)
712 // Check if visual is currently in the process of being replaced ( is in removal container )
713 RegisteredVisualContainer::Iterator visualQueuedForRemoval;
714 if(FindVisual(index, mRemoveVisuals, visualQueuedForRemoval))
716 // Visual with same index is already in removal container so current visual pending
717 // Only the the last requested visual will be displayed so remove current visual which is staged but not ready.
718 Toolkit::GetImplementation(currentRegisteredVisual).SetOffScene(self);
719 mVisuals.Erase(registeredVisualsiter);
723 // current visual not already in removal container so add now.
724 DALI_LOG_INFO(gLogFilter, Debug::Verbose, "RegisterVisual Move current registered visual to removal Queue: %d \n", index);
725 MoveVisual(registeredVisualsiter, mVisuals, mRemoveVisuals);
730 // Control not staged or visual disabled so can just erase from registered visuals and new visual will be added later.
731 mVisuals.Erase(registeredVisualsiter);
734 // 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
735 if((depthIndexValueSet == DepthIndexValue::NOT_SET) &&
736 (visual.GetDepthIndex() == 0))
738 requiredDepthIndex = currentDepthIndex;
742 visualReplaced = true;
746 // If not set, set the name of the visual to the same name as the control's property.
747 // ( If the control has been type registered )
748 if(visual.GetName().empty())
750 // returns empty string if index is not found as long as index is not -1
751 std::string visualName = self.GetPropertyName(index);
752 if(!visualName.empty())
754 DALI_LOG_INFO(gLogFilter, Debug::Concise, "Setting visual name for property %d to %s\n", index, visualName.c_str());
755 visual.SetName(visualName);
759 if(!visualReplaced) // New registration entry
761 // 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
762 if((depthIndexValueSet == DepthIndexValue::NOT_SET) &&
763 (mVisuals.Size() > 0) &&
764 (visual.GetDepthIndex() == 0))
766 int maxDepthIndex = std::numeric_limits<int>::min();
768 RegisteredVisualContainer::ConstIterator iter;
769 const RegisteredVisualContainer::ConstIterator endIter = mVisuals.End();
770 for(iter = mVisuals.Begin(); iter != endIter; iter++)
772 const int visualDepthIndex = (*iter)->visual.GetDepthIndex();
773 if(visualDepthIndex > maxDepthIndex)
775 maxDepthIndex = visualDepthIndex;
778 ++maxDepthIndex; // Add one to the current maximum depth index so that our added visual appears on top
779 requiredDepthIndex = std::max(0, maxDepthIndex); // Start at zero if maxDepth index belongs to a background
785 // Set determined depth index
786 visual.SetDepthIndex(requiredDepthIndex);
788 // Monitor when the visual resources are ready
789 StartObservingVisual(visual);
791 DALI_LOG_INFO(gLogFilter, Debug::Concise, "New Visual registration index[%d] depth[%d]\n", index, requiredDepthIndex);
792 RegisteredVisual* newRegisteredVisual = new RegisteredVisual(index, visual, (enabled == VisualState::ENABLED ? true : false), (visualReplaced && enabled));
793 mVisuals.PushBack(newRegisteredVisual);
795 Internal::Visual::Base& visualImpl = Toolkit::GetImplementation(visual);
796 // Put on stage if enabled and the control is already on the stage
797 if((enabled == VisualState::ENABLED) && self.GetProperty<bool>(Actor::Property::CONNECTED_TO_SCENE))
799 visualImpl.SetOnScene(self);
801 else if(visualImpl.IsResourceReady()) // When not being staged, check if visual already 'ResourceReady' before it was Registered. ( Resource may have been loaded already )
803 ResourceReady(visualImpl);
807 DALI_LOG_INFO(gLogFilter, Debug::Verbose, "Control::RegisterVisual() Registered %s(%d), enabled:%s\n", visual.GetName().c_str(), index, enabled ? "true" : "false");
810 void Control::Impl::UnregisterVisual(Property::Index index)
812 RegisteredVisualContainer::Iterator iter;
813 if(FindVisual(index, mVisuals, iter))
815 // stop observing visual
816 StopObservingVisual((*iter)->visual);
818 Actor self(mControlImpl.Self());
819 Toolkit::GetImplementation((*iter)->visual).SetOffScene(self);
820 (*iter)->visual.Reset();
821 mVisuals.Erase(iter);
824 if(FindVisual(index, mRemoveVisuals, iter))
826 Actor self(mControlImpl.Self());
827 Toolkit::GetImplementation((*iter)->visual).SetOffScene(self);
828 (*iter)->pending = false;
829 (*iter)->visual.Reset();
830 mRemoveVisuals.Erase(iter);
834 Toolkit::Visual::Base Control::Impl::GetVisual(Property::Index index) const
836 RegisteredVisualContainer::Iterator iter;
837 if(FindVisual(index, mVisuals, iter))
839 return (*iter)->visual;
842 return Toolkit::Visual::Base();
845 void Control::Impl::EnableVisual(Property::Index index, bool enable)
847 DALI_LOG_INFO(gLogFilter, Debug::General, "Control::EnableVisual(%d, %s)\n", index, enable ? "T" : "F");
849 RegisteredVisualContainer::Iterator iter;
850 if(FindVisual(index, mVisuals, iter))
852 if((*iter)->enabled == enable)
854 DALI_LOG_INFO(gLogFilter, Debug::Verbose, "Control::EnableVisual Visual %s(%d) already %s\n", (*iter)->visual.GetName().c_str(), index, enable ? "enabled" : "disabled");
858 (*iter)->enabled = enable;
859 Actor parentActor = mControlImpl.Self();
860 if(mControlImpl.Self().GetProperty<bool>(Actor::Property::CONNECTED_TO_SCENE)) // If control not on Scene then Visual will be added when SceneConnection is called.
864 DALI_LOG_INFO(gLogFilter, Debug::Verbose, "Control::EnableVisual Setting %s(%d) on stage \n", (*iter)->visual.GetName().c_str(), index);
865 Toolkit::GetImplementation((*iter)->visual).SetOnScene(parentActor);
869 DALI_LOG_INFO(gLogFilter, Debug::Verbose, "Control::EnableVisual Setting %s(%d) off stage \n", (*iter)->visual.GetName().c_str(), index);
870 Toolkit::GetImplementation((*iter)->visual).SetOffScene(parentActor); // No need to call if control not staged.
876 DALI_LOG_WARNING("Control::EnableVisual(%d, %s) FAILED - NO SUCH VISUAL\n", index, enable ? "T" : "F");
880 bool Control::Impl::IsVisualEnabled(Property::Index index) const
882 RegisteredVisualContainer::Iterator iter;
883 if(FindVisual(index, mVisuals, iter))
885 return (*iter)->enabled;
890 void Control::Impl::StopObservingVisual(Toolkit::Visual::Base& visual)
892 Internal::Visual::Base& visualImpl = Toolkit::GetImplementation(visual);
894 // Stop observing the visual
895 visualImpl.RemoveEventObserver(*this);
898 void Control::Impl::StartObservingVisual(Toolkit::Visual::Base& visual)
900 Internal::Visual::Base& visualImpl = Toolkit::GetImplementation(visual);
902 // start observing the visual for events
903 visualImpl.AddEventObserver(*this);
906 // Called by a Visual when it's resource is ready
907 void Control::Impl::ResourceReady(Visual::Base& object)
909 DALI_LOG_INFO(gLogFilter, Debug::Verbose, "Control::Impl::ResourceReady() replacements pending[%d]\n", mRemoveVisuals.Count());
911 Actor self = mControlImpl.Self();
913 // A resource is ready, find resource in the registered visuals container and get its index
914 for(auto registeredIter = mVisuals.Begin(), end = mVisuals.End(); registeredIter != end; ++registeredIter)
916 Internal::Visual::Base& registeredVisualImpl = Toolkit::GetImplementation((*registeredIter)->visual);
918 if(&object == ®isteredVisualImpl)
920 RegisteredVisualContainer::Iterator visualToRemoveIter;
921 // Find visual with the same index in the removal container
922 // Set if off stage as it's replacement is now ready.
923 // Remove if from removal list as now removed from stage.
924 // Set Pending flag on the ready visual to false as now ready.
925 if(FindVisual((*registeredIter)->index, mRemoveVisuals, visualToRemoveIter))
927 (*registeredIter)->pending = false;
928 Toolkit::GetImplementation((*visualToRemoveIter)->visual).SetOffScene(self);
929 mRemoveVisuals.Erase(visualToRemoveIter);
935 // A visual is ready so control may need relayouting if staged
936 if(self.GetProperty<bool>(Actor::Property::CONNECTED_TO_SCENE))
938 mControlImpl.RelayoutRequest();
941 // Emit signal if all enabled visuals registered by the control are ready.
942 if(IsResourceReady())
945 mNeedToEmitResourceReady = false;
947 EmitResourceReadySignal();
951 void Control::Impl::NotifyVisualEvent(Visual::Base& object, Property::Index signalId)
953 for(auto registeredIter = mVisuals.Begin(), end = mVisuals.End(); registeredIter != end; ++registeredIter)
955 Internal::Visual::Base& registeredVisualImpl = Toolkit::GetImplementation((*registeredIter)->visual);
956 if(&object == ®isteredVisualImpl)
958 Dali::Toolkit::Control handle(mControlImpl.GetOwner());
959 mVisualEventSignal.Emit(handle, (*registeredIter)->index, signalId);
965 bool Control::Impl::IsResourceReady() const
967 // Iterate through and check all the enabled visuals are ready
968 for(auto visualIter = mVisuals.Begin();
969 visualIter != mVisuals.End();
972 const Toolkit::Visual::Base visual = (*visualIter)->visual;
973 const Internal::Visual::Base& visualImpl = Toolkit::GetImplementation(visual);
975 // one of the enabled visuals is not ready
976 if(!visualImpl.IsResourceReady() && (*visualIter)->enabled)
984 Toolkit::Visual::ResourceStatus Control::Impl::GetVisualResourceStatus(Property::Index index) const
986 RegisteredVisualContainer::Iterator iter;
987 if(FindVisual(index, mVisuals, iter))
989 const Toolkit::Visual::Base visual = (*iter)->visual;
990 const Internal::Visual::Base& visualImpl = Toolkit::GetImplementation(visual);
991 return visualImpl.GetResourceStatus();
994 return Toolkit::Visual::ResourceStatus::PREPARING;
997 void Control::Impl::AddTransitions(Dali::Animation& animation,
998 const Toolkit::TransitionData& handle,
999 bool createAnimation)
1001 // Setup a Transition from TransitionData.
1002 const Internal::TransitionData& transitionData = Toolkit::GetImplementation(handle);
1003 TransitionData::Iterator end = transitionData.End();
1004 for(TransitionData::Iterator iter = transitionData.Begin();
1008 TransitionData::Animator* animator = (*iter);
1010 Toolkit::Visual::Base visual = GetVisualByName(mVisuals, animator->objectName);
1014 #if defined(DEBUG_ENABLED)
1015 Dali::TypeInfo typeInfo;
1016 ControlWrapper* controlWrapperImpl = dynamic_cast<ControlWrapper*>(&mControlImpl);
1017 if(controlWrapperImpl)
1019 typeInfo = controlWrapperImpl->GetTypeInfo();
1022 DALI_LOG_INFO(gLogFilter, Debug::Concise, "CreateTransition: Found %s visual for %s\n", visual.GetName().c_str(), typeInfo ? typeInfo.GetName().c_str() : "Unknown");
1024 Internal::Visual::Base& visualImpl = Toolkit::GetImplementation(visual);
1025 visualImpl.AnimateProperty(animation, *animator);
1029 DALI_LOG_INFO(gLogFilter, Debug::Concise, "CreateTransition: Could not find visual. Trying actors");
1030 // Otherwise, try any actor children of control (Including the control)
1031 Actor child = mControlImpl.Self().FindChildByName(animator->objectName);
1034 Property::Index propertyIndex = child.GetPropertyIndex(animator->propertyKey);
1035 if(propertyIndex != Property::INVALID_INDEX)
1037 if(animator->animate == false)
1039 if(animator->targetValue.GetType() != Property::NONE)
1041 child.SetProperty(propertyIndex, animator->targetValue);
1044 else // animate the property
1046 if(animator->initialValue.GetType() != Property::NONE)
1048 child.SetProperty(propertyIndex, animator->initialValue);
1051 if(createAnimation && !animation)
1053 animation = Dali::Animation::New(0.1f);
1056 animation.AnimateTo(Property(child, propertyIndex),
1057 animator->targetValue,
1058 animator->alphaFunction,
1059 TimePeriod(animator->timePeriodDelay,
1060 animator->timePeriodDuration));
1068 Dali::Animation Control::Impl::CreateTransition(const Toolkit::TransitionData& transitionData)
1070 Dali::Animation transition;
1072 if(transitionData.Count() > 0)
1074 AddTransitions(transition, transitionData, true);
1079 void Control::Impl::DoAction(Dali::Property::Index visualIndex, Dali::Property::Index actionId, const Dali::Property::Value attributes)
1081 RegisteredVisualContainer::Iterator iter;
1082 if(FindVisual(visualIndex, mVisuals, iter))
1084 Toolkit::GetImplementation((*iter)->visual).DoAction(actionId, attributes);
1088 void Control::Impl::AppendAccessibilityAttribute(const std::string& key, const std::string value)
1090 Property::Value* checkedValue = mAccessibilityAttributes.Find(key);
1093 mAccessibilityAttributes[key] = Property::Value(value);
1097 mAccessibilityAttributes.Insert(key, value);
1101 void Control::Impl::SetProperty(BaseObject* object, Property::Index index, const Property::Value& value)
1103 Toolkit::Control control = Toolkit::Control::DownCast(BaseHandle(object));
1107 Control& controlImpl(GetImplementation(control));
1111 case Toolkit::Control::Property::STYLE_NAME:
1113 controlImpl.SetStyleName(value.Get<std::string>());
1117 case Toolkit::DevelControl::Property::STATE:
1119 bool withTransitions = true;
1120 const Property::Value* valuePtr = &value;
1121 const Property::Map* map = value.GetMap();
1124 Property::Value* value2 = map->Find("withTransitions");
1127 withTransitions = value2->Get<bool>();
1130 valuePtr = map->Find("state");
1135 Toolkit::DevelControl::State state(controlImpl.mImpl->mState);
1136 if(Scripting::GetEnumerationProperty<Toolkit::DevelControl::State>(*valuePtr, ControlStateTable, ControlStateTableCount, state))
1138 controlImpl.mImpl->SetState(state, withTransitions);
1144 case Toolkit::DevelControl::Property::SUB_STATE:
1146 std::string subState;
1147 if(value.Get(subState))
1149 controlImpl.mImpl->SetSubState(subState);
1154 case Toolkit::DevelControl::Property::LEFT_FOCUSABLE_ACTOR_ID:
1157 if(value.Get(focusId))
1159 controlImpl.mImpl->mLeftFocusableActorId = focusId;
1164 case Toolkit::DevelControl::Property::RIGHT_FOCUSABLE_ACTOR_ID:
1167 if(value.Get(focusId))
1169 controlImpl.mImpl->mRightFocusableActorId = focusId;
1174 case Toolkit::DevelControl::Property::UP_FOCUSABLE_ACTOR_ID:
1177 if(value.Get(focusId))
1179 controlImpl.mImpl->mUpFocusableActorId = focusId;
1184 case Toolkit::DevelControl::Property::DOWN_FOCUSABLE_ACTOR_ID:
1187 if(value.Get(focusId))
1189 controlImpl.mImpl->mDownFocusableActorId = focusId;
1194 case Toolkit::Control::Property::KEY_INPUT_FOCUS:
1196 if(value.Get<bool>())
1198 controlImpl.SetKeyInputFocus();
1202 controlImpl.ClearKeyInputFocus();
1207 case Toolkit::Control::Property::BACKGROUND:
1211 const Property::Map* map = value.GetMap();
1212 if(map && !map->Empty())
1214 controlImpl.SetBackground(*map);
1216 else if(value.Get(url))
1218 // don't know the size to load
1219 Toolkit::Visual::Base visual = Toolkit::VisualFactory::Get().CreateVisual(url, ImageDimensions());
1222 controlImpl.mImpl->RegisterVisual(Toolkit::Control::Property::BACKGROUND, visual, DepthIndex::BACKGROUND);
1225 else if(value.Get(color))
1227 controlImpl.SetBackgroundColor(color);
1231 // The background is an empty property map, so we should clear the background
1232 controlImpl.ClearBackground();
1237 case Toolkit::Control::Property::MARGIN:
1240 if(value.Get(margin))
1242 controlImpl.mImpl->SetMargin(margin);
1247 case Toolkit::Control::Property::PADDING:
1250 if(value.Get(padding))
1252 controlImpl.mImpl->SetPadding(padding);
1257 case Toolkit::DevelControl::Property::TOOLTIP:
1259 TooltipPtr& tooltipPtr = controlImpl.mImpl->mTooltip;
1262 tooltipPtr = Tooltip::New(control);
1264 tooltipPtr->SetProperties(value);
1268 case Toolkit::DevelControl::Property::SHADOW:
1270 const Property::Map* map = value.GetMap();
1271 if(map && !map->Empty())
1273 controlImpl.mImpl->SetShadow(*map);
1277 // The shadow is an empty property map, so we should clear the shadow
1278 controlImpl.mImpl->ClearShadow();
1283 case Toolkit::DevelControl::Property::ACCESSIBILITY_NAME:
1288 controlImpl.mImpl->mAccessibilityName = name;
1289 controlImpl.mImpl->mAccessibilityNameSet = true;
1293 controlImpl.mImpl->mAccessibilityNameSet = false;
1298 case Toolkit::DevelControl::Property::ACCESSIBILITY_DESCRIPTION:
1303 controlImpl.mImpl->mAccessibilityDescription = text;
1304 controlImpl.mImpl->mAccessibilityDescriptionSet = true;
1308 controlImpl.mImpl->mAccessibilityDescriptionSet = false;
1313 case Toolkit::DevelControl::Property::ACCESSIBILITY_TRANSLATION_DOMAIN:
1318 controlImpl.mImpl->mAccessibilityTranslationDomain = text;
1319 controlImpl.mImpl->mAccessibilityTranslationDomainSet = true;
1323 controlImpl.mImpl->mAccessibilityTranslationDomainSet = false;
1328 case Toolkit::DevelControl::Property::ACCESSIBILITY_ROLE:
1330 Dali::Accessibility::Role role;
1333 controlImpl.mImpl->mAccessibilityRole = role;
1338 case Toolkit::DevelControl::Property::ACCESSIBILITY_HIGHLIGHTABLE:
1341 if(value.Get(highlightable))
1343 controlImpl.mImpl->mAccessibilityHighlightable = highlightable;
1344 controlImpl.mImpl->mAccessibilityHighlightableSet = true;
1348 controlImpl.mImpl->mAccessibilityHighlightableSet = false;
1353 case Toolkit::DevelControl::Property::ACCESSIBILITY_ATTRIBUTES:
1355 const Property::Map* map = value.GetMap();
1356 if(map && !map->Empty())
1358 controlImpl.mImpl->mAccessibilityAttributes = *map;
1363 case Toolkit::DevelControl::Property::DISPATCH_KEY_EVENTS:
1366 if(value.Get(dispatch))
1368 controlImpl.mImpl->mDispatchKeyEvents = dispatch;
1376 Property::Value Control::Impl::GetProperty(BaseObject* object, Property::Index index)
1378 Property::Value value;
1380 Toolkit::Control control = Toolkit::Control::DownCast(BaseHandle(object));
1384 Control& controlImpl(GetImplementation(control));
1388 case Toolkit::Control::Property::STYLE_NAME:
1390 value = controlImpl.GetStyleName();
1394 case Toolkit::DevelControl::Property::STATE:
1396 value = controlImpl.mImpl->mState;
1400 case Toolkit::DevelControl::Property::SUB_STATE:
1402 value = controlImpl.mImpl->mSubStateName;
1406 case Toolkit::DevelControl::Property::LEFT_FOCUSABLE_ACTOR_ID:
1408 value = controlImpl.mImpl->mLeftFocusableActorId;
1412 case Toolkit::DevelControl::Property::RIGHT_FOCUSABLE_ACTOR_ID:
1414 value = controlImpl.mImpl->mRightFocusableActorId;
1418 case Toolkit::DevelControl::Property::UP_FOCUSABLE_ACTOR_ID:
1420 value = controlImpl.mImpl->mUpFocusableActorId;
1424 case Toolkit::DevelControl::Property::DOWN_FOCUSABLE_ACTOR_ID:
1426 value = controlImpl.mImpl->mDownFocusableActorId;
1430 case Toolkit::Control::Property::KEY_INPUT_FOCUS:
1432 value = controlImpl.HasKeyInputFocus();
1436 case Toolkit::Control::Property::BACKGROUND:
1439 Toolkit::Visual::Base visual = controlImpl.mImpl->GetVisual(Toolkit::Control::Property::BACKGROUND);
1442 visual.CreatePropertyMap(map);
1449 case Toolkit::Control::Property::MARGIN:
1451 value = controlImpl.mImpl->GetMargin();
1455 case Toolkit::Control::Property::PADDING:
1457 value = controlImpl.mImpl->GetPadding();
1461 case Toolkit::DevelControl::Property::TOOLTIP:
1464 if(controlImpl.mImpl->mTooltip)
1466 controlImpl.mImpl->mTooltip->CreatePropertyMap(map);
1472 case Toolkit::DevelControl::Property::SHADOW:
1475 Toolkit::Visual::Base visual = controlImpl.mImpl->GetVisual(Toolkit::DevelControl::Property::SHADOW);
1478 visual.CreatePropertyMap(map);
1485 case Toolkit::DevelControl::Property::ACCESSIBILITY_NAME:
1487 if(controlImpl.mImpl->mAccessibilityNameSet)
1489 value = controlImpl.mImpl->mAccessibilityName;
1494 case Toolkit::DevelControl::Property::ACCESSIBILITY_DESCRIPTION:
1496 if(controlImpl.mImpl->mAccessibilityDescriptionSet)
1498 value = controlImpl.mImpl->mAccessibilityDescription;
1503 case Toolkit::DevelControl::Property::ACCESSIBILITY_TRANSLATION_DOMAIN:
1505 if(controlImpl.mImpl->mAccessibilityTranslationDomainSet)
1507 value = controlImpl.mImpl->mAccessibilityTranslationDomain;
1512 case Toolkit::DevelControl::Property::ACCESSIBILITY_ROLE:
1514 value = Property::Value(controlImpl.mImpl->mAccessibilityRole);
1518 case Toolkit::DevelControl::Property::ACCESSIBILITY_HIGHLIGHTABLE:
1520 if(controlImpl.mImpl->mAccessibilityHighlightableSet)
1522 value = controlImpl.mImpl->mAccessibilityHighlightable;
1527 case Toolkit::DevelControl::Property::ACCESSIBILITY_ATTRIBUTES:
1529 value = controlImpl.mImpl->mAccessibilityAttributes;
1532 case Toolkit::DevelControl::Property::DISPATCH_KEY_EVENTS:
1534 value = controlImpl.mImpl->mDispatchKeyEvents;
1543 void Control::Impl::RemoveAccessibilityAttribute(const std::string& key)
1545 Property::Value* value = mAccessibilityAttributes.Find(key);
1548 mAccessibilityAttributes[key] = Property::Value();
1552 void Control::Impl::ClearAccessibilityAttributes()
1554 mAccessibilityAttributes.Clear();
1557 void Control::Impl::SetAccessibilityReadingInfoType(const Dali::Accessibility::ReadingInfoTypes types)
1559 std::string value{};
1560 if(types[Dali::Accessibility::ReadingInfoType::NAME])
1562 value += READING_INFO_TYPE_NAME;
1564 if(types[Dali::Accessibility::ReadingInfoType::ROLE])
1568 value += READING_INFO_TYPE_SEPARATOR;
1570 value += READING_INFO_TYPE_ROLE;
1572 if(types[Dali::Accessibility::ReadingInfoType::DESCRIPTION])
1576 value += READING_INFO_TYPE_SEPARATOR;
1578 value += READING_INFO_TYPE_DESCRIPTION;
1580 if(types[Dali::Accessibility::ReadingInfoType::STATE])
1584 value += READING_INFO_TYPE_SEPARATOR;
1586 value += READING_INFO_TYPE_STATE;
1588 AppendAccessibilityAttribute(READING_INFO_TYPE_ATTRIBUTE_NAME, value);
1591 Dali::Accessibility::ReadingInfoTypes Control::Impl::GetAccessibilityReadingInfoType() const
1593 std::string value{};
1594 auto place = mAccessibilityAttributes.Find(READING_INFO_TYPE_ATTRIBUTE_NAME);
1601 Dali::Accessibility::ReadingInfoTypes types;
1602 types[Dali::Accessibility::ReadingInfoType::NAME] = true;
1603 types[Dali::Accessibility::ReadingInfoType::ROLE] = true;
1604 types[Dali::Accessibility::ReadingInfoType::DESCRIPTION] = true;
1605 types[Dali::Accessibility::ReadingInfoType::STATE] = true;
1614 Dali::Accessibility::ReadingInfoTypes types;
1616 if(value.find(READING_INFO_TYPE_NAME) != std::string::npos)
1618 types[Dali::Accessibility::ReadingInfoType::NAME] = true;
1620 if(value.find(READING_INFO_TYPE_ROLE) != std::string::npos)
1622 types[Dali::Accessibility::ReadingInfoType::ROLE] = true;
1624 if(value.find(READING_INFO_TYPE_DESCRIPTION) != std::string::npos)
1626 types[Dali::Accessibility::ReadingInfoType::DESCRIPTION] = true;
1628 if(value.find(READING_INFO_TYPE_STATE) != std::string::npos)
1630 types[Dali::Accessibility::ReadingInfoType::STATE] = true;
1636 void Control::Impl::CopyInstancedProperties(RegisteredVisualContainer& visuals, Dictionary<Property::Map>& instancedProperties)
1638 for(RegisteredVisualContainer::Iterator iter = visuals.Begin(); iter != visuals.End(); iter++)
1642 Property::Map instanceMap;
1643 Toolkit::GetImplementation((*iter)->visual).CreateInstancePropertyMap(instanceMap);
1644 instancedProperties.Add((*iter)->visual.GetName(), instanceMap);
1649 void Control::Impl::RemoveVisual(RegisteredVisualContainer& visuals, const std::string& visualName)
1651 Actor self(mControlImpl.Self());
1653 for(RegisteredVisualContainer::Iterator visualIter = visuals.Begin();
1654 visualIter != visuals.End();
1657 Toolkit::Visual::Base visual = (*visualIter)->visual;
1658 if(visual && visual.GetName() == visualName)
1660 Toolkit::GetImplementation(visual).SetOffScene(self);
1661 (*visualIter)->visual.Reset();
1662 visuals.Erase(visualIter);
1668 void Control::Impl::RemoveVisuals(RegisteredVisualContainer& visuals, DictionaryKeys& removeVisuals)
1670 Actor self(mControlImpl.Self());
1671 for(DictionaryKeys::iterator iter = removeVisuals.begin(); iter != removeVisuals.end(); ++iter)
1673 const std::string visualName = *iter;
1674 RemoveVisual(visuals, visualName);
1678 void Control::Impl::RecreateChangedVisuals(Dictionary<Property::Map>& stateVisualsToChange,
1679 Dictionary<Property::Map>& instancedProperties)
1681 Dali::CustomActor handle(mControlImpl.GetOwner());
1682 for(Dictionary<Property::Map>::iterator iter = stateVisualsToChange.Begin();
1683 iter != stateVisualsToChange.End();
1686 const std::string& visualName = (*iter).key;
1687 const Property::Map& toMap = (*iter).entry;
1689 Actor self = mControlImpl.Self();
1690 RegisteredVisualContainer::Iterator registeredVisualsiter;
1691 // Check if visual (visualName) is already registered, this is the current visual.
1692 if(FindVisual(visualName, mVisuals, registeredVisualsiter))
1694 Toolkit::Visual::Base& visual = (*registeredVisualsiter)->visual;
1697 // No longer required to know if the replaced visual's resources are ready
1698 StopObservingVisual(visual);
1700 // If control staged then visuals will be swapped once ready
1701 if(self.GetProperty<bool>(Actor::Property::CONNECTED_TO_SCENE))
1703 // Check if visual is currently in the process of being replaced ( is in removal container )
1704 RegisteredVisualContainer::Iterator visualQueuedForRemoval;
1705 if(FindVisual(visualName, mRemoveVisuals, visualQueuedForRemoval))
1707 // Visual with same visual name is already in removal container so current visual pending
1708 // Only the the last requested visual will be displayed so remove current visual which is staged but not ready.
1709 Toolkit::GetImplementation(visual).SetOffScene(self);
1710 (*registeredVisualsiter)->visual.Reset();
1711 mVisuals.Erase(registeredVisualsiter);
1715 // current visual not already in removal container so add now.
1716 DALI_LOG_INFO(gLogFilter, Debug::Verbose, "RegisterVisual Move current registered visual to removal Queue: %s \n", visualName.c_str());
1717 MoveVisual(registeredVisualsiter, mVisuals, mRemoveVisuals);
1722 // Control not staged or visual disabled so can just erase from registered visuals and new visual will be added later.
1723 (*registeredVisualsiter)->visual.Reset();
1724 mVisuals.Erase(registeredVisualsiter);
1728 const Property::Map* instancedMap = instancedProperties.FindConst(visualName);
1729 Style::ApplyVisual(handle, visualName, toMap, instancedMap);
1734 void Control::Impl::ReplaceStateVisualsAndProperties(const StylePtr oldState, const StylePtr newState, const std::string& subState)
1736 // Collect all old visual names
1737 DictionaryKeys stateVisualsToRemove;
1740 oldState->visuals.GetKeys(stateVisualsToRemove);
1741 if(!subState.empty())
1743 const StylePtr* oldSubState = oldState->subStates.FindConst(subState);
1746 DictionaryKeys subStateVisualsToRemove;
1747 (*oldSubState)->visuals.GetKeys(subStateVisualsToRemove);
1748 Merge(stateVisualsToRemove, subStateVisualsToRemove);
1753 // Collect all new visual properties
1754 Dictionary<Property::Map> stateVisualsToAdd;
1757 stateVisualsToAdd = newState->visuals;
1758 if(!subState.empty())
1760 const StylePtr* newSubState = newState->subStates.FindConst(subState);
1763 stateVisualsToAdd.Merge((*newSubState)->visuals);
1768 // If a name is in both add/remove, move it to change list.
1769 Dictionary<Property::Map> stateVisualsToChange;
1770 FindChangableVisuals(stateVisualsToAdd, stateVisualsToChange, stateVisualsToRemove);
1772 // Copy instanced properties (e.g. text label) of current visuals
1773 Dictionary<Property::Map> instancedProperties;
1774 CopyInstancedProperties(mVisuals, instancedProperties);
1776 // For each visual in remove list, remove from mVisuals
1777 RemoveVisuals(mVisuals, stateVisualsToRemove);
1779 // For each visual in add list, create and add to mVisuals
1780 Dali::CustomActor handle(mControlImpl.GetOwner());
1781 Style::ApplyVisuals(handle, stateVisualsToAdd, instancedProperties);
1783 // For each visual in change list, if it requires a new visual,
1784 // remove old visual, create and add to mVisuals
1785 RecreateChangedVisuals(stateVisualsToChange, instancedProperties);
1788 void Control::Impl::SetState(DevelControl::State newState, bool withTransitions)
1790 DevelControl::State oldState = mState;
1791 Dali::CustomActor handle(mControlImpl.GetOwner());
1792 DALI_LOG_INFO(gLogFilter, Debug::Concise, "Control::Impl::SetState: %s\n", (mState == DevelControl::NORMAL ? "NORMAL" : (mState == DevelControl::FOCUSED ? "FOCUSED" : (mState == DevelControl::DISABLED ? "DISABLED" : "NONE"))));
1794 if(mState != newState)
1796 // If mState was Disabled, and new state is Focused, should probably
1797 // store that fact, e.g. in another property that FocusManager can access.
1800 // Trigger state change and transitions
1801 // Apply new style, if stylemanager is available
1802 Toolkit::StyleManager styleManager = Toolkit::StyleManager::Get();
1805 const StylePtr stylePtr = GetImpl(styleManager).GetRecordedStyle(Toolkit::Control(mControlImpl.GetOwner()));
1809 std::string oldStateName = Scripting::GetEnumerationName<Toolkit::DevelControl::State>(oldState, ControlStateTable, ControlStateTableCount);
1810 std::string newStateName = Scripting::GetEnumerationName<Toolkit::DevelControl::State>(newState, ControlStateTable, ControlStateTableCount);
1812 const StylePtr* newStateStyle = stylePtr->subStates.Find(newStateName);
1813 const StylePtr* oldStateStyle = stylePtr->subStates.Find(oldStateName);
1814 if(oldStateStyle && newStateStyle)
1816 // Only change if both state styles exist
1817 ReplaceStateVisualsAndProperties(*oldStateStyle, *newStateStyle, mSubStateName);
1824 void Control::Impl::SetSubState(const std::string& subStateName, bool withTransitions)
1826 if(mSubStateName != subStateName)
1828 // Get existing sub-state visuals, and unregister them
1829 Dali::CustomActor handle(mControlImpl.GetOwner());
1831 Toolkit::StyleManager styleManager = Toolkit::StyleManager::Get();
1834 const StylePtr stylePtr = GetImpl(styleManager).GetRecordedStyle(Toolkit::Control(mControlImpl.GetOwner()));
1838 std::string stateName = Scripting::GetEnumerationName<Toolkit::DevelControl::State>(mState, ControlStateTable, ControlStateTableCount);
1840 const StylePtr* state = stylePtr->subStates.Find(stateName);
1843 StylePtr stateStyle(*state);
1845 const StylePtr* newStateStyle = stateStyle->subStates.Find(subStateName);
1846 const StylePtr* oldStateStyle = stateStyle->subStates.Find(mSubStateName);
1847 if(oldStateStyle && newStateStyle)
1850 ReplaceStateVisualsAndProperties(*oldStateStyle, *newStateStyle, empty);
1856 mSubStateName = subStateName;
1860 void Control::Impl::OnSceneDisconnection()
1862 Actor self = mControlImpl.Self();
1864 // Any visuals set for replacement but not yet ready should still be registered.
1865 // Reason: If a request was made to register a new visual but the control removed from scene before visual was ready
1866 // then when this control appears back on stage it should use that new visual.
1868 // Iterate through all registered visuals and set off scene
1869 SetVisualsOffScene(mVisuals, self);
1871 // Visuals pending replacement can now be taken out of the removal list and set off scene
1872 // Iterate through all replacement visuals and add to a move queue then set off scene
1873 for(auto removalIter = mRemoveVisuals.Begin(), end = mRemoveVisuals.End(); removalIter != end; removalIter++)
1875 Toolkit::GetImplementation((*removalIter)->visual).SetOffScene(self);
1878 for(auto replacedIter = mVisuals.Begin(), end = mVisuals.End(); replacedIter != end; replacedIter++)
1880 (*replacedIter)->pending = false;
1883 mRemoveVisuals.Clear();
1886 void Control::Impl::SetMargin(Extents margin)
1888 mControlImpl.mImpl->mMargin = margin;
1890 // Trigger a size negotiation request that may be needed when setting a margin.
1891 mControlImpl.RelayoutRequest();
1894 Extents Control::Impl::GetMargin() const
1896 return mControlImpl.mImpl->mMargin;
1899 void Control::Impl::SetPadding(Extents padding)
1901 mControlImpl.mImpl->mPadding = padding;
1903 // Trigger a size negotiation request that may be needed when setting a padding.
1904 mControlImpl.RelayoutRequest();
1907 Extents Control::Impl::GetPadding() const
1909 return mControlImpl.mImpl->mPadding;
1912 void Control::Impl::SetInputMethodContext(InputMethodContext& inputMethodContext)
1914 mInputMethodContext = inputMethodContext;
1917 bool Control::Impl::FilterKeyEvent(const KeyEvent& event)
1919 bool consumed(false);
1921 if(mInputMethodContext)
1923 consumed = mInputMethodContext.FilterEventKey(event);
1928 DevelControl::VisualEventSignalType& Control::Impl::VisualEventSignal()
1930 return mVisualEventSignal;
1933 void Control::Impl::SetShadow(const Property::Map& map)
1935 Toolkit::Visual::Base visual = Toolkit::VisualFactory::Get().CreateVisual(map);
1936 visual.SetName("shadow");
1940 mControlImpl.mImpl->RegisterVisual(Toolkit::DevelControl::Property::SHADOW, visual, DepthIndex::BACKGROUND_EFFECT);
1942 mControlImpl.RelayoutRequest();
1946 void Control::Impl::ClearShadow()
1948 mControlImpl.mImpl->UnregisterVisual(Toolkit::DevelControl::Property::SHADOW);
1950 // Trigger a size negotiation request that may be needed when unregistering a visual.
1951 mControlImpl.RelayoutRequest();
1954 Dali::Property Control::Impl::GetVisualProperty(Dali::Property::Index index, Dali::Property::Key visualPropertyKey)
1956 Toolkit::Visual::Base visual = GetVisualByIndex(mVisuals, index);
1959 Internal::Visual::Base& visualImpl = Toolkit::GetImplementation(visual);
1960 return visualImpl.GetPropertyObject(visualPropertyKey);
1964 return Dali::Property(handle, Property::INVALID_INDEX);
1967 void Control::Impl::CreateTransitions(std::vector<std::pair<Dali::Property::Index, Dali::Property::Map>>& sourceProperties,
1968 std::vector<std::pair<Dali::Property::Index, Dali::Property::Map>>& destinationProperties,
1969 Dali::Toolkit::Control source, Dali::Toolkit::Control destination)
1971 // Retrieves background properties to be transitioned.
1972 Dali::Property::Map backgroundSourcePropertyMap, backgroundDestinationPropertyMap;
1973 mControlImpl.MakeVisualTransition(backgroundSourcePropertyMap, backgroundDestinationPropertyMap, source, destination, Toolkit::Control::Property::BACKGROUND);
1974 if(backgroundSourcePropertyMap.Count() > 0)
1976 sourceProperties.push_back(std::pair<Dali::Property::Index, Dali::Property::Map>(Toolkit::Control::Property::BACKGROUND, backgroundSourcePropertyMap));
1977 destinationProperties.push_back(std::pair<Dali::Property::Index, Dali::Property::Map>(Toolkit::Control::Property::BACKGROUND, backgroundDestinationPropertyMap));
1980 // Retrieves shadow properties to be transitioned.
1981 Dali::Property::Map shadowSourcePropertyMap, shadowDestinationPropertyMap;
1982 mControlImpl.MakeVisualTransition(shadowSourcePropertyMap, shadowDestinationPropertyMap, source, destination, Toolkit::DevelControl::Property::SHADOW);
1983 if(shadowSourcePropertyMap.Count() > 0)
1985 sourceProperties.push_back(std::pair<Dali::Property::Index, Dali::Property::Map>(Toolkit::DevelControl::Property::SHADOW, shadowSourcePropertyMap));
1986 destinationProperties.push_back(std::pair<Dali::Property::Index, Dali::Property::Map>(Toolkit::DevelControl::Property::SHADOW, shadowDestinationPropertyMap));
1989 // Retrieves transition from inherited class.
1990 mControlImpl.OnCreateTransitions(sourceProperties, destinationProperties, source, destination);
1993 void Control::Impl::UpdateVisualProperties(const std::vector<std::pair<Dali::Property::Index, Dali::Property::Map>>& properties)
1995 for(auto&& data : properties)
1997 if(data.first == Toolkit::Control::Property::BACKGROUND)
1999 DoAction(Toolkit::Control::Property::BACKGROUND, DevelVisual::Action::UPDATE_PROPERTY, data.second);
2001 else if(data.first == Toolkit::DevelControl::Property::SHADOW)
2003 DoAction(Toolkit::DevelControl::Property::SHADOW, DevelVisual::Action::UPDATE_PROPERTY, data.second);
2006 mControlImpl.OnUpdateVisualProperties(properties);
2009 void Control::Impl::EmitResourceReadySignal()
2011 if(!mIsEmittingResourceReadySignal)
2013 // Guard against calls to emit the signal during the callback
2014 mIsEmittingResourceReadySignal = true;
2016 // If the signal handler changes visual, it may become ready during this call & therefore this method will
2017 // get called again recursively. If so, mNeedToEmitResourceReady is set below, and we act on it after that secondary
2018 // invocation has completed by notifying in an Idle callback to prevent further recursion.
2019 Dali::Toolkit::Control handle(mControlImpl.GetOwner());
2020 mResourceReadySignal.Emit(handle);
2022 if(mNeedToEmitResourceReady)
2024 // Add idler to emit the signal again
2027 // The callback manager takes the ownership of the callback object.
2028 mIdleCallback = MakeCallback(this, &Control::Impl::OnIdleCallback);
2029 Adaptor::Get().AddIdle(mIdleCallback, false);
2033 mIsEmittingResourceReadySignal = false;
2037 mNeedToEmitResourceReady = true;
2041 void Control::Impl::OnIdleCallback()
2043 if(mNeedToEmitResourceReady)
2046 mNeedToEmitResourceReady = false;
2048 // A visual is ready so control may need relayouting if staged
2049 if(mControlImpl.Self().GetProperty<bool>(Actor::Property::CONNECTED_TO_SCENE))
2051 mControlImpl.RelayoutRequest();
2054 EmitResourceReadySignal();
2057 // Set the pointer to null as the callback manager deletes the callback after execute it.
2058 mIdleCallback = nullptr;
2061 Dali::Accessibility::Accessible* Control::Impl::GetAccessibilityObject()
2063 if(!mAccessibilityObject)
2065 mAccessibilityObject = mAccessibilityConstructor(mControlImpl.Self());
2067 return mAccessibilityObject.get();
2070 Dali::Accessibility::Accessible* Control::Impl::GetAccessibilityObject(Dali::Actor actor)
2074 auto control = Dali::Toolkit::Control::DownCast(actor);
2077 auto controlImpl = static_cast<Internal::Control*>(&control.GetImplementation());
2078 return controlImpl->mImpl->GetAccessibilityObject();
2084 } // namespace Internal
2086 } // namespace Toolkit