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);
473 const PropertyRegistration Control::Impl::PROPERTY_24(typeRegistration, "clockwiseFocusableActorId", Toolkit::DevelControl::Property::CLOCKWISE_FOCUSABLE_ACTOR_ID, Property::INTEGER, &Control::Impl::SetProperty, &Control::Impl::GetProperty);
474 const PropertyRegistration Control::Impl::PROPERTY_25(typeRegistration, "counterClockwiseFocusableActorId", Toolkit::DevelControl::Property::COUNTER_CLOCKWISE_FOCUSABLE_ACTOR_ID, Property::INTEGER, &Control::Impl::SetProperty, &Control::Impl::GetProperty);
478 Control::Impl::Impl(Control& controlImpl)
479 : mControlImpl(controlImpl),
480 mState(Toolkit::DevelControl::NORMAL),
482 mLeftFocusableActorId(-1),
483 mRightFocusableActorId(-1),
484 mUpFocusableActorId(-1),
485 mDownFocusableActorId(-1),
486 mClockwiseFocusableActorId(-1),
487 mCounterClockwiseFocusableActorId(-1),
489 mBackgroundColor(Color::TRANSPARENT),
490 mStartingPinchScale(nullptr),
492 mPadding(0, 0, 0, 0),
494 mKeyInputFocusGainedSignal(),
495 mKeyInputFocusLostSignal(),
496 mResourceReadySignal(),
497 mVisualEventSignal(),
498 mAccessibilityGetNameSignal(),
499 mAccessibilityGetDescriptionSignal(),
500 mAccessibilityDoGestureSignal(),
501 mPinchGestureDetector(),
502 mPanGestureDetector(),
503 mTapGestureDetector(),
504 mLongPressGestureDetector(),
506 mInputMethodContext(),
507 mIdleCallback(nullptr),
508 mFlags(Control::ControlBehaviour(CONTROL_BEHAVIOUR_DEFAULT)),
509 mIsKeyboardNavigationSupported(false),
510 mIsKeyboardFocusGroup(false),
511 mIsEmittingResourceReadySignal(false),
512 mNeedToEmitResourceReady(false),
513 mDispatchKeyEvents(true)
515 Dali::Accessibility::Accessible::RegisterExternalAccessibleGetter(
516 [](Dali::Actor actor) -> Dali::Accessibility::Accessible* {
517 return Control::Impl::GetAccessibilityObject(actor);
520 mAccessibilityConstructor = [](Dali::Actor actor) -> std::unique_ptr<Dali::Accessibility::Accessible> {
521 return std::unique_ptr<Dali::Accessibility::Accessible>(new DevelControl::ControlAccessible(actor, Dali::Accessibility::Role::UNKNOWN));
525 Control::Impl::~Impl()
527 for(auto&& iter : mVisuals)
529 StopObservingVisual(iter->visual);
532 for(auto&& iter : mRemoveVisuals)
534 StopObservingVisual(iter->visual);
537 // All gesture detectors will be destroyed so no need to disconnect.
538 delete mStartingPinchScale;
540 if(mIdleCallback && Adaptor::IsAvailable())
542 // Removes the callback from the callback manager in case the control is destroyed before the callback is executed.
543 Adaptor::Get().RemoveIdle(mIdleCallback);
547 Control::Impl& Control::Impl::Get(Internal::Control& internalControl)
549 return *internalControl.mImpl;
552 const Control::Impl& Control::Impl::Get(const Internal::Control& internalControl)
554 return *internalControl.mImpl;
557 void Control::Impl::CheckHighlightedObjectGeometry()
559 auto accessible = dynamic_cast<Dali::Toolkit::DevelControl::ControlAccessible*>(mAccessibilityObject.get());
562 DALI_LOG_ERROR("accessible is not a pointer to a DevelControl::ControlAccessible type");
566 auto lastPosition = accessible->GetLastPosition();
567 auto accessibleRect = accessible->GetExtents(Dali::Accessibility::CoordinateType::WINDOW);
568 auto rect = GetShowingGeometry(accessibleRect, accessible);
570 switch(mAccessibilityLastScreenRelativeMoveType)
572 case Dali::Accessibility::ScreenRelativeMoveType::OUTSIDE:
574 if(IsShowingGeometryOnScreen(rect))
576 mAccessibilityLastScreenRelativeMoveType = Dali::Accessibility::ScreenRelativeMoveType::INSIDE;
580 case Dali::Accessibility::ScreenRelativeMoveType::INSIDE:
582 if(rect.width < 0 && accessibleRect.x != lastPosition.x)
584 mAccessibilityLastScreenRelativeMoveType = (accessibleRect.x < lastPosition.x) ? Dali::Accessibility::ScreenRelativeMoveType::OUTGOING_TOP_LEFT : Dali::Accessibility::ScreenRelativeMoveType::OUTGOING_BOTTOM_RIGHT;
586 if(rect.height < 0 && accessibleRect.y != lastPosition.y)
588 mAccessibilityLastScreenRelativeMoveType = (accessibleRect.y < lastPosition.y) ? Dali::Accessibility::ScreenRelativeMoveType::OUTGOING_TOP_LEFT : Dali::Accessibility::ScreenRelativeMoveType::OUTGOING_BOTTOM_RIGHT;
590 // notify AT-clients on outgoing moves only
591 if(mAccessibilityLastScreenRelativeMoveType != Dali::Accessibility::ScreenRelativeMoveType::INSIDE)
593 mAccessibilityObject.get()->EmitMovedOutOfScreen(mAccessibilityLastScreenRelativeMoveType);
597 case Dali::Accessibility::ScreenRelativeMoveType::OUTGOING_TOP_LEFT:
598 case Dali::Accessibility::ScreenRelativeMoveType::OUTGOING_BOTTOM_RIGHT:
600 if(IsShowingGeometryOnScreen(rect))
602 mAccessibilityLastScreenRelativeMoveType = Dali::Accessibility::ScreenRelativeMoveType::INSIDE;
606 mAccessibilityLastScreenRelativeMoveType = Dali::Accessibility::ScreenRelativeMoveType::OUTSIDE;
616 accessible->SetLastPosition(Vector2(accessibleRect.x, accessibleRect.y));
619 void Control::Impl::RegisterAccessibilityPositionPropertyNotification()
621 if(mIsAccessibilityPositionPropertyNotificationSet)
625 // set default value until first move of object is detected
626 mAccessibilityLastScreenRelativeMoveType = Dali::Accessibility::ScreenRelativeMoveType::OUTSIDE;
627 // recalculate mAccessibilityLastScreenRelativeMoveType accordingly to the initial position
628 CheckHighlightedObjectGeometry();
629 mAccessibilityPositionNotification = mControlImpl.Self().AddPropertyNotification(Actor::Property::WORLD_POSITION, StepCondition(1.0f, 1.0f));
630 mAccessibilityPositionNotification.SetNotifyMode(PropertyNotification::NOTIFY_ON_CHANGED);
631 mAccessibilityPositionNotification.NotifySignal().Connect(this, [this](PropertyNotification&){ CheckHighlightedObjectGeometry(); });
632 mIsAccessibilityPositionPropertyNotificationSet = true;
635 void Control::Impl::UnregisterAccessibilityPositionPropertyNotification()
637 mControlImpl.Self().RemovePropertyNotification(mAccessibilityPositionNotification);
638 mIsAccessibilityPositionPropertyNotificationSet = false;
641 // Gesture Detection Methods
642 void Control::Impl::PinchDetected(Actor actor, const PinchGesture& pinch)
644 mControlImpl.OnPinch(pinch);
647 void Control::Impl::PanDetected(Actor actor, const PanGesture& pan)
649 mControlImpl.OnPan(pan);
652 void Control::Impl::TapDetected(Actor actor, const TapGesture& tap)
654 mControlImpl.OnTap(tap);
657 void Control::Impl::LongPressDetected(Actor actor, const LongPressGesture& longPress)
659 mControlImpl.OnLongPress(longPress);
662 void Control::Impl::RegisterVisual(Property::Index index, Toolkit::Visual::Base& visual)
664 RegisterVisual(index, visual, VisualState::ENABLED, DepthIndexValue::NOT_SET);
667 void Control::Impl::RegisterVisual(Property::Index index, Toolkit::Visual::Base& visual, int depthIndex)
669 RegisterVisual(index, visual, VisualState::ENABLED, DepthIndexValue::SET, depthIndex);
672 void Control::Impl::RegisterVisual(Property::Index index, Toolkit::Visual::Base& visual, bool enabled)
674 RegisterVisual(index, visual, (enabled ? VisualState::ENABLED : VisualState::DISABLED), DepthIndexValue::NOT_SET);
677 void Control::Impl::RegisterVisual(Property::Index index, Toolkit::Visual::Base& visual, bool enabled, int depthIndex)
679 RegisterVisual(index, visual, (enabled ? VisualState::ENABLED : VisualState::DISABLED), DepthIndexValue::SET, depthIndex);
682 void Control::Impl::RegisterVisual(Property::Index index, Toolkit::Visual::Base& visual, VisualState::Type enabled, DepthIndexValue::Type depthIndexValueSet, int depthIndex)
684 DALI_LOG_INFO(gLogFilter, Debug::Concise, "RegisterVisual:%d \n", index);
686 bool visualReplaced(false);
687 Actor self = mControlImpl.Self();
689 // Set the depth index, if not set by caller this will be either the current visual depth, max depth of all visuals
691 int requiredDepthIndex = visual.GetDepthIndex();
693 if(depthIndexValueSet == DepthIndexValue::SET)
695 requiredDepthIndex = depthIndex;
698 // Visual replacement, existing visual should only be removed from stage when replacement ready.
699 if(!mVisuals.Empty())
701 RegisteredVisualContainer::Iterator registeredVisualsiter;
702 // Check if visual (index) is already registered, this is the current visual.
703 if(FindVisual(index, mVisuals, registeredVisualsiter))
705 Toolkit::Visual::Base& currentRegisteredVisual = (*registeredVisualsiter)->visual;
706 if(currentRegisteredVisual)
708 // Store current visual depth index as may need to set the replacement visual to same depth
709 const int currentDepthIndex = (*registeredVisualsiter)->visual.GetDepthIndex();
711 // No longer required to know if the replaced visual's resources are ready
712 StopObservingVisual(currentRegisteredVisual);
714 // If control staged and visual enabled then visuals will be swapped once ready
715 if(self.GetProperty<bool>(Actor::Property::CONNECTED_TO_SCENE) && enabled)
717 // Check if visual is currently in the process of being replaced ( is in removal container )
718 RegisteredVisualContainer::Iterator visualQueuedForRemoval;
719 if(FindVisual(index, mRemoveVisuals, visualQueuedForRemoval))
721 // Visual with same index is already in removal container so current visual pending
722 // Only the the last requested visual will be displayed so remove current visual which is staged but not ready.
723 Toolkit::GetImplementation(currentRegisteredVisual).SetOffScene(self);
724 mVisuals.Erase(registeredVisualsiter);
728 // current visual not already in removal container so add now.
729 DALI_LOG_INFO(gLogFilter, Debug::Verbose, "RegisterVisual Move current registered visual to removal Queue: %d \n", index);
730 MoveVisual(registeredVisualsiter, mVisuals, mRemoveVisuals);
735 // Control not staged or visual disabled so can just erase from registered visuals and new visual will be added later.
736 mVisuals.Erase(registeredVisualsiter);
739 // If we've not set the depth-index value and the new visual does not have a depth index applied to it, then use the previously set depth-index for this index
740 if((depthIndexValueSet == DepthIndexValue::NOT_SET) &&
741 (visual.GetDepthIndex() == 0))
743 requiredDepthIndex = currentDepthIndex;
747 visualReplaced = true;
751 // If not set, set the name of the visual to the same name as the control's property.
752 // ( If the control has been type registered )
753 if(visual.GetName().empty())
755 // returns empty string if index is not found as long as index is not -1
756 std::string visualName = self.GetPropertyName(index);
757 if(!visualName.empty())
759 DALI_LOG_INFO(gLogFilter, Debug::Concise, "Setting visual name for property %d to %s\n", index, visualName.c_str());
760 visual.SetName(visualName);
764 if(!visualReplaced) // New registration entry
766 // If we've not set the depth-index value, we have more than one visual and the visual does not have a depth index, then set it to be the highest
767 if((depthIndexValueSet == DepthIndexValue::NOT_SET) &&
768 (mVisuals.Size() > 0) &&
769 (visual.GetDepthIndex() == 0))
771 int maxDepthIndex = std::numeric_limits<int>::min();
773 RegisteredVisualContainer::ConstIterator iter;
774 const RegisteredVisualContainer::ConstIterator endIter = mVisuals.End();
775 for(iter = mVisuals.Begin(); iter != endIter; iter++)
777 const int visualDepthIndex = (*iter)->visual.GetDepthIndex();
778 if(visualDepthIndex > maxDepthIndex)
780 maxDepthIndex = visualDepthIndex;
783 ++maxDepthIndex; // Add one to the current maximum depth index so that our added visual appears on top
784 requiredDepthIndex = std::max(0, maxDepthIndex); // Start at zero if maxDepth index belongs to a background
790 // Set determined depth index
791 visual.SetDepthIndex(requiredDepthIndex);
793 // Monitor when the visual resources are ready
794 StartObservingVisual(visual);
796 DALI_LOG_INFO(gLogFilter, Debug::Concise, "New Visual registration index[%d] depth[%d]\n", index, requiredDepthIndex);
797 RegisteredVisual* newRegisteredVisual = new RegisteredVisual(index, visual, (enabled == VisualState::ENABLED ? true : false), (visualReplaced && enabled));
798 mVisuals.PushBack(newRegisteredVisual);
800 Internal::Visual::Base& visualImpl = Toolkit::GetImplementation(visual);
801 // Put on stage if enabled and the control is already on the stage
802 if((enabled == VisualState::ENABLED) && self.GetProperty<bool>(Actor::Property::CONNECTED_TO_SCENE))
804 visualImpl.SetOnScene(self);
806 else if(visualImpl.IsResourceReady()) // When not being staged, check if visual already 'ResourceReady' before it was Registered. ( Resource may have been loaded already )
808 ResourceReady(visualImpl);
812 DALI_LOG_INFO(gLogFilter, Debug::Verbose, "Control::RegisterVisual() Registered %s(%d), enabled:%s\n", visual.GetName().c_str(), index, enabled ? "true" : "false");
815 void Control::Impl::UnregisterVisual(Property::Index index)
817 RegisteredVisualContainer::Iterator iter;
818 if(FindVisual(index, mVisuals, iter))
820 // stop observing visual
821 StopObservingVisual((*iter)->visual);
823 Actor self(mControlImpl.Self());
824 Toolkit::GetImplementation((*iter)->visual).SetOffScene(self);
825 (*iter)->visual.Reset();
826 mVisuals.Erase(iter);
829 if(FindVisual(index, mRemoveVisuals, iter))
831 Actor self(mControlImpl.Self());
832 Toolkit::GetImplementation((*iter)->visual).SetOffScene(self);
833 (*iter)->pending = false;
834 (*iter)->visual.Reset();
835 mRemoveVisuals.Erase(iter);
839 Toolkit::Visual::Base Control::Impl::GetVisual(Property::Index index) const
841 RegisteredVisualContainer::Iterator iter;
842 if(FindVisual(index, mVisuals, iter))
844 return (*iter)->visual;
847 return Toolkit::Visual::Base();
850 void Control::Impl::EnableVisual(Property::Index index, bool enable)
852 DALI_LOG_INFO(gLogFilter, Debug::General, "Control::EnableVisual(%d, %s)\n", index, enable ? "T" : "F");
854 RegisteredVisualContainer::Iterator iter;
855 if(FindVisual(index, mVisuals, iter))
857 if((*iter)->enabled == enable)
859 DALI_LOG_INFO(gLogFilter, Debug::Verbose, "Control::EnableVisual Visual %s(%d) already %s\n", (*iter)->visual.GetName().c_str(), index, enable ? "enabled" : "disabled");
863 (*iter)->enabled = enable;
864 Actor parentActor = mControlImpl.Self();
865 if(mControlImpl.Self().GetProperty<bool>(Actor::Property::CONNECTED_TO_SCENE)) // If control not on Scene then Visual will be added when SceneConnection is called.
869 DALI_LOG_INFO(gLogFilter, Debug::Verbose, "Control::EnableVisual Setting %s(%d) on stage \n", (*iter)->visual.GetName().c_str(), index);
870 Toolkit::GetImplementation((*iter)->visual).SetOnScene(parentActor);
874 DALI_LOG_INFO(gLogFilter, Debug::Verbose, "Control::EnableVisual Setting %s(%d) off stage \n", (*iter)->visual.GetName().c_str(), index);
875 Toolkit::GetImplementation((*iter)->visual).SetOffScene(parentActor); // No need to call if control not staged.
881 DALI_LOG_WARNING("Control::EnableVisual(%d, %s) FAILED - NO SUCH VISUAL\n", index, enable ? "T" : "F");
885 bool Control::Impl::IsVisualEnabled(Property::Index index) const
887 RegisteredVisualContainer::Iterator iter;
888 if(FindVisual(index, mVisuals, iter))
890 return (*iter)->enabled;
895 void Control::Impl::StopObservingVisual(Toolkit::Visual::Base& visual)
897 Internal::Visual::Base& visualImpl = Toolkit::GetImplementation(visual);
899 // Stop observing the visual
900 visualImpl.RemoveEventObserver(*this);
903 void Control::Impl::StartObservingVisual(Toolkit::Visual::Base& visual)
905 Internal::Visual::Base& visualImpl = Toolkit::GetImplementation(visual);
907 // start observing the visual for events
908 visualImpl.AddEventObserver(*this);
911 // Called by a Visual when it's resource is ready
912 void Control::Impl::ResourceReady(Visual::Base& object)
914 DALI_LOG_INFO(gLogFilter, Debug::Verbose, "Control::Impl::ResourceReady() replacements pending[%d]\n", mRemoveVisuals.Count());
916 Actor self = mControlImpl.Self();
918 // A resource is ready, find resource in the registered visuals container and get its index
919 for(auto registeredIter = mVisuals.Begin(), end = mVisuals.End(); registeredIter != end; ++registeredIter)
921 Internal::Visual::Base& registeredVisualImpl = Toolkit::GetImplementation((*registeredIter)->visual);
923 if(&object == ®isteredVisualImpl)
925 RegisteredVisualContainer::Iterator visualToRemoveIter;
926 // Find visual with the same index in the removal container
927 // Set if off stage as it's replacement is now ready.
928 // Remove if from removal list as now removed from stage.
929 // Set Pending flag on the ready visual to false as now ready.
930 if(FindVisual((*registeredIter)->index, mRemoveVisuals, visualToRemoveIter))
932 (*registeredIter)->pending = false;
933 Toolkit::GetImplementation((*visualToRemoveIter)->visual).SetOffScene(self);
934 mRemoveVisuals.Erase(visualToRemoveIter);
940 // A visual is ready so control may need relayouting if staged
941 if(self.GetProperty<bool>(Actor::Property::CONNECTED_TO_SCENE))
943 mControlImpl.RelayoutRequest();
946 // Emit signal if all enabled visuals registered by the control are ready.
947 if(IsResourceReady())
950 mNeedToEmitResourceReady = false;
952 EmitResourceReadySignal();
956 void Control::Impl::NotifyVisualEvent(Visual::Base& object, Property::Index signalId)
958 for(auto registeredIter = mVisuals.Begin(), end = mVisuals.End(); registeredIter != end; ++registeredIter)
960 Internal::Visual::Base& registeredVisualImpl = Toolkit::GetImplementation((*registeredIter)->visual);
961 if(&object == ®isteredVisualImpl)
963 Dali::Toolkit::Control handle(mControlImpl.GetOwner());
964 mVisualEventSignal.Emit(handle, (*registeredIter)->index, signalId);
970 bool Control::Impl::IsResourceReady() const
972 // Iterate through and check all the enabled visuals are ready
973 for(auto visualIter = mVisuals.Begin();
974 visualIter != mVisuals.End();
977 const Toolkit::Visual::Base visual = (*visualIter)->visual;
978 const Internal::Visual::Base& visualImpl = Toolkit::GetImplementation(visual);
980 // one of the enabled visuals is not ready
981 if(!visualImpl.IsResourceReady() && (*visualIter)->enabled)
989 Toolkit::Visual::ResourceStatus Control::Impl::GetVisualResourceStatus(Property::Index index) const
991 RegisteredVisualContainer::Iterator iter;
992 if(FindVisual(index, mVisuals, iter))
994 const Toolkit::Visual::Base visual = (*iter)->visual;
995 const Internal::Visual::Base& visualImpl = Toolkit::GetImplementation(visual);
996 return visualImpl.GetResourceStatus();
999 return Toolkit::Visual::ResourceStatus::PREPARING;
1002 void Control::Impl::AddTransitions(Dali::Animation& animation,
1003 const Toolkit::TransitionData& handle,
1004 bool createAnimation)
1006 // Setup a Transition from TransitionData.
1007 const Internal::TransitionData& transitionData = Toolkit::GetImplementation(handle);
1008 TransitionData::Iterator end = transitionData.End();
1009 for(TransitionData::Iterator iter = transitionData.Begin();
1013 TransitionData::Animator* animator = (*iter);
1015 Toolkit::Visual::Base visual = GetVisualByName(mVisuals, animator->objectName);
1019 #if defined(DEBUG_ENABLED)
1020 Dali::TypeInfo typeInfo;
1021 ControlWrapper* controlWrapperImpl = dynamic_cast<ControlWrapper*>(&mControlImpl);
1022 if(controlWrapperImpl)
1024 typeInfo = controlWrapperImpl->GetTypeInfo();
1027 DALI_LOG_INFO(gLogFilter, Debug::Concise, "CreateTransition: Found %s visual for %s\n", visual.GetName().c_str(), typeInfo ? typeInfo.GetName().c_str() : "Unknown");
1029 Internal::Visual::Base& visualImpl = Toolkit::GetImplementation(visual);
1030 visualImpl.AnimateProperty(animation, *animator);
1034 DALI_LOG_INFO(gLogFilter, Debug::Concise, "CreateTransition: Could not find visual. Trying actors");
1035 // Otherwise, try any actor children of control (Including the control)
1036 Actor child = mControlImpl.Self().FindChildByName(animator->objectName);
1039 Property::Index propertyIndex = child.GetPropertyIndex(animator->propertyKey);
1040 if(propertyIndex != Property::INVALID_INDEX)
1042 if(animator->animate == false)
1044 if(animator->targetValue.GetType() != Property::NONE)
1046 child.SetProperty(propertyIndex, animator->targetValue);
1049 else // animate the property
1051 if(animator->initialValue.GetType() != Property::NONE)
1053 child.SetProperty(propertyIndex, animator->initialValue);
1056 if(createAnimation && !animation)
1058 animation = Dali::Animation::New(0.1f);
1061 animation.AnimateTo(Property(child, propertyIndex),
1062 animator->targetValue,
1063 animator->alphaFunction,
1064 TimePeriod(animator->timePeriodDelay,
1065 animator->timePeriodDuration));
1073 Dali::Animation Control::Impl::CreateTransition(const Toolkit::TransitionData& transitionData)
1075 Dali::Animation transition;
1077 if(transitionData.Count() > 0)
1079 AddTransitions(transition, transitionData, true);
1084 void Control::Impl::DoAction(Dali::Property::Index visualIndex, Dali::Property::Index actionId, const Dali::Property::Value attributes)
1086 RegisteredVisualContainer::Iterator iter;
1087 if(FindVisual(visualIndex, mVisuals, iter))
1089 Toolkit::GetImplementation((*iter)->visual).DoAction(actionId, attributes);
1093 void Control::Impl::AppendAccessibilityAttribute(const std::string& key, const std::string value)
1095 Property::Value* checkedValue = mAccessibilityAttributes.Find(key);
1098 mAccessibilityAttributes[key] = Property::Value(value);
1102 mAccessibilityAttributes.Insert(key, value);
1106 void Control::Impl::SetProperty(BaseObject* object, Property::Index index, const Property::Value& value)
1108 Toolkit::Control control = Toolkit::Control::DownCast(BaseHandle(object));
1112 Control& controlImpl(GetImplementation(control));
1116 case Toolkit::Control::Property::STYLE_NAME:
1118 controlImpl.SetStyleName(value.Get<std::string>());
1122 case Toolkit::DevelControl::Property::STATE:
1124 bool withTransitions = true;
1125 const Property::Value* valuePtr = &value;
1126 const Property::Map* map = value.GetMap();
1129 Property::Value* value2 = map->Find("withTransitions");
1132 withTransitions = value2->Get<bool>();
1135 valuePtr = map->Find("state");
1140 Toolkit::DevelControl::State state(controlImpl.mImpl->mState);
1141 if(Scripting::GetEnumerationProperty<Toolkit::DevelControl::State>(*valuePtr, ControlStateTable, ControlStateTableCount, state))
1143 controlImpl.mImpl->SetState(state, withTransitions);
1149 case Toolkit::DevelControl::Property::SUB_STATE:
1151 std::string subState;
1152 if(value.Get(subState))
1154 controlImpl.mImpl->SetSubState(subState);
1159 case Toolkit::DevelControl::Property::LEFT_FOCUSABLE_ACTOR_ID:
1162 if(value.Get(focusId))
1164 controlImpl.mImpl->mLeftFocusableActorId = focusId;
1169 case Toolkit::DevelControl::Property::RIGHT_FOCUSABLE_ACTOR_ID:
1172 if(value.Get(focusId))
1174 controlImpl.mImpl->mRightFocusableActorId = focusId;
1179 case Toolkit::DevelControl::Property::UP_FOCUSABLE_ACTOR_ID:
1182 if(value.Get(focusId))
1184 controlImpl.mImpl->mUpFocusableActorId = focusId;
1189 case Toolkit::DevelControl::Property::DOWN_FOCUSABLE_ACTOR_ID:
1192 if(value.Get(focusId))
1194 controlImpl.mImpl->mDownFocusableActorId = focusId;
1199 case Toolkit::Control::Property::KEY_INPUT_FOCUS:
1201 if(value.Get<bool>())
1203 controlImpl.SetKeyInputFocus();
1207 controlImpl.ClearKeyInputFocus();
1212 case Toolkit::Control::Property::BACKGROUND:
1216 const Property::Map* map = value.GetMap();
1217 if(map && !map->Empty())
1219 controlImpl.SetBackground(*map);
1221 else if(value.Get(url))
1223 // don't know the size to load
1224 Toolkit::Visual::Base visual = Toolkit::VisualFactory::Get().CreateVisual(url, ImageDimensions());
1227 controlImpl.mImpl->RegisterVisual(Toolkit::Control::Property::BACKGROUND, visual, DepthIndex::BACKGROUND);
1230 else if(value.Get(color))
1232 controlImpl.SetBackgroundColor(color);
1236 // The background is an empty property map, so we should clear the background
1237 controlImpl.ClearBackground();
1242 case Toolkit::Control::Property::MARGIN:
1245 if(value.Get(margin))
1247 controlImpl.mImpl->SetMargin(margin);
1252 case Toolkit::Control::Property::PADDING:
1255 if(value.Get(padding))
1257 controlImpl.mImpl->SetPadding(padding);
1262 case Toolkit::DevelControl::Property::TOOLTIP:
1264 TooltipPtr& tooltipPtr = controlImpl.mImpl->mTooltip;
1267 tooltipPtr = Tooltip::New(control);
1269 tooltipPtr->SetProperties(value);
1273 case Toolkit::DevelControl::Property::SHADOW:
1275 const Property::Map* map = value.GetMap();
1276 if(map && !map->Empty())
1278 controlImpl.mImpl->SetShadow(*map);
1282 // The shadow is an empty property map, so we should clear the shadow
1283 controlImpl.mImpl->ClearShadow();
1288 case Toolkit::DevelControl::Property::ACCESSIBILITY_NAME:
1293 controlImpl.mImpl->mAccessibilityName = name;
1298 case Toolkit::DevelControl::Property::ACCESSIBILITY_DESCRIPTION:
1303 controlImpl.mImpl->mAccessibilityDescription = text;
1308 case Toolkit::DevelControl::Property::ACCESSIBILITY_TRANSLATION_DOMAIN:
1313 controlImpl.mImpl->mAccessibilityTranslationDomain = text;
1318 case Toolkit::DevelControl::Property::ACCESSIBILITY_ROLE:
1320 Dali::Accessibility::Role role;
1323 controlImpl.mImpl->mAccessibilityRole = role;
1328 case Toolkit::DevelControl::Property::ACCESSIBILITY_HIGHLIGHTABLE:
1331 if(value.Get(highlightable))
1333 controlImpl.mImpl->mAccessibilityHighlightable = highlightable;
1338 case Toolkit::DevelControl::Property::ACCESSIBILITY_ATTRIBUTES:
1340 const Property::Map* map = value.GetMap();
1341 if(map && !map->Empty())
1343 controlImpl.mImpl->mAccessibilityAttributes = *map;
1348 case Toolkit::DevelControl::Property::DISPATCH_KEY_EVENTS:
1351 if(value.Get(dispatch))
1353 controlImpl.mImpl->mDispatchKeyEvents = dispatch;
1358 case Toolkit::DevelControl::Property::ACCESSIBILITY_HIDDEN:
1361 if(value.Get(hidden))
1363 controlImpl.mImpl->mAccessibilityHidden = hidden;
1365 auto* accessible = controlImpl.mImpl->GetAccessibilityObject();
1366 auto* parent = dynamic_cast<Dali::Accessibility::ActorAccessible*>(accessible->GetParent());
1369 parent->OnChildrenChanged();
1374 case Toolkit::DevelControl::Property::CLOCKWISE_FOCUSABLE_ACTOR_ID:
1377 if(value.Get(focusId))
1379 controlImpl.mImpl->mClockwiseFocusableActorId = focusId;
1383 case Toolkit::DevelControl::Property::COUNTER_CLOCKWISE_FOCUSABLE_ACTOR_ID:
1386 if(value.Get(focusId))
1388 controlImpl.mImpl->mCounterClockwiseFocusableActorId = focusId;
1396 Property::Value Control::Impl::GetProperty(BaseObject* object, Property::Index index)
1398 Property::Value value;
1400 Toolkit::Control control = Toolkit::Control::DownCast(BaseHandle(object));
1404 Control& controlImpl(GetImplementation(control));
1408 case Toolkit::Control::Property::STYLE_NAME:
1410 value = controlImpl.GetStyleName();
1414 case Toolkit::DevelControl::Property::STATE:
1416 value = controlImpl.mImpl->mState;
1420 case Toolkit::DevelControl::Property::SUB_STATE:
1422 value = controlImpl.mImpl->mSubStateName;
1426 case Toolkit::DevelControl::Property::LEFT_FOCUSABLE_ACTOR_ID:
1428 value = controlImpl.mImpl->mLeftFocusableActorId;
1432 case Toolkit::DevelControl::Property::RIGHT_FOCUSABLE_ACTOR_ID:
1434 value = controlImpl.mImpl->mRightFocusableActorId;
1438 case Toolkit::DevelControl::Property::UP_FOCUSABLE_ACTOR_ID:
1440 value = controlImpl.mImpl->mUpFocusableActorId;
1444 case Toolkit::DevelControl::Property::DOWN_FOCUSABLE_ACTOR_ID:
1446 value = controlImpl.mImpl->mDownFocusableActorId;
1450 case Toolkit::Control::Property::KEY_INPUT_FOCUS:
1452 value = controlImpl.HasKeyInputFocus();
1456 case Toolkit::Control::Property::BACKGROUND:
1459 Toolkit::Visual::Base visual = controlImpl.mImpl->GetVisual(Toolkit::Control::Property::BACKGROUND);
1462 visual.CreatePropertyMap(map);
1469 case Toolkit::Control::Property::MARGIN:
1471 value = controlImpl.mImpl->GetMargin();
1475 case Toolkit::Control::Property::PADDING:
1477 value = controlImpl.mImpl->GetPadding();
1481 case Toolkit::DevelControl::Property::TOOLTIP:
1484 if(controlImpl.mImpl->mTooltip)
1486 controlImpl.mImpl->mTooltip->CreatePropertyMap(map);
1492 case Toolkit::DevelControl::Property::SHADOW:
1495 Toolkit::Visual::Base visual = controlImpl.mImpl->GetVisual(Toolkit::DevelControl::Property::SHADOW);
1498 visual.CreatePropertyMap(map);
1505 case Toolkit::DevelControl::Property::ACCESSIBILITY_NAME:
1507 value = controlImpl.mImpl->mAccessibilityName;
1511 case Toolkit::DevelControl::Property::ACCESSIBILITY_DESCRIPTION:
1513 value = controlImpl.mImpl->mAccessibilityDescription;
1517 case Toolkit::DevelControl::Property::ACCESSIBILITY_TRANSLATION_DOMAIN:
1519 value = controlImpl.mImpl->mAccessibilityTranslationDomain;
1523 case Toolkit::DevelControl::Property::ACCESSIBILITY_ROLE:
1525 value = Property::Value(controlImpl.mImpl->mAccessibilityRole);
1529 case Toolkit::DevelControl::Property::ACCESSIBILITY_HIGHLIGHTABLE:
1531 value = controlImpl.mImpl->mAccessibilityHighlightable;
1535 case Toolkit::DevelControl::Property::ACCESSIBILITY_ATTRIBUTES:
1537 value = controlImpl.mImpl->mAccessibilityAttributes;
1541 case Toolkit::DevelControl::Property::DISPATCH_KEY_EVENTS:
1543 value = controlImpl.mImpl->mDispatchKeyEvents;
1547 case Toolkit::DevelControl::Property::ACCESSIBILITY_HIDDEN:
1549 value = controlImpl.mImpl->mAccessibilityHidden;
1553 case Toolkit::DevelControl::Property::CLOCKWISE_FOCUSABLE_ACTOR_ID:
1555 value = controlImpl.mImpl->mClockwiseFocusableActorId;
1559 case Toolkit::DevelControl::Property::COUNTER_CLOCKWISE_FOCUSABLE_ACTOR_ID:
1561 value = controlImpl.mImpl->mCounterClockwiseFocusableActorId;
1570 void Control::Impl::RemoveAccessibilityAttribute(const std::string& key)
1572 Property::Value* value = mAccessibilityAttributes.Find(key);
1575 mAccessibilityAttributes[key] = Property::Value();
1579 void Control::Impl::ClearAccessibilityAttributes()
1581 mAccessibilityAttributes.Clear();
1584 void Control::Impl::SetAccessibilityReadingInfoType(const Dali::Accessibility::ReadingInfoTypes types)
1586 std::string value{};
1587 if(types[Dali::Accessibility::ReadingInfoType::NAME])
1589 value += READING_INFO_TYPE_NAME;
1591 if(types[Dali::Accessibility::ReadingInfoType::ROLE])
1595 value += READING_INFO_TYPE_SEPARATOR;
1597 value += READING_INFO_TYPE_ROLE;
1599 if(types[Dali::Accessibility::ReadingInfoType::DESCRIPTION])
1603 value += READING_INFO_TYPE_SEPARATOR;
1605 value += READING_INFO_TYPE_DESCRIPTION;
1607 if(types[Dali::Accessibility::ReadingInfoType::STATE])
1611 value += READING_INFO_TYPE_SEPARATOR;
1613 value += READING_INFO_TYPE_STATE;
1615 AppendAccessibilityAttribute(READING_INFO_TYPE_ATTRIBUTE_NAME, value);
1618 Dali::Accessibility::ReadingInfoTypes Control::Impl::GetAccessibilityReadingInfoType() const
1620 std::string value{};
1621 auto place = mAccessibilityAttributes.Find(READING_INFO_TYPE_ATTRIBUTE_NAME);
1628 Dali::Accessibility::ReadingInfoTypes types;
1629 types[Dali::Accessibility::ReadingInfoType::NAME] = true;
1630 types[Dali::Accessibility::ReadingInfoType::ROLE] = true;
1631 types[Dali::Accessibility::ReadingInfoType::DESCRIPTION] = true;
1632 types[Dali::Accessibility::ReadingInfoType::STATE] = true;
1641 Dali::Accessibility::ReadingInfoTypes types;
1643 if(value.find(READING_INFO_TYPE_NAME) != std::string::npos)
1645 types[Dali::Accessibility::ReadingInfoType::NAME] = true;
1647 if(value.find(READING_INFO_TYPE_ROLE) != std::string::npos)
1649 types[Dali::Accessibility::ReadingInfoType::ROLE] = true;
1651 if(value.find(READING_INFO_TYPE_DESCRIPTION) != std::string::npos)
1653 types[Dali::Accessibility::ReadingInfoType::DESCRIPTION] = true;
1655 if(value.find(READING_INFO_TYPE_STATE) != std::string::npos)
1657 types[Dali::Accessibility::ReadingInfoType::STATE] = true;
1663 void Control::Impl::CopyInstancedProperties(RegisteredVisualContainer& visuals, Dictionary<Property::Map>& instancedProperties)
1665 for(RegisteredVisualContainer::Iterator iter = visuals.Begin(); iter != visuals.End(); iter++)
1669 Property::Map instanceMap;
1670 Toolkit::GetImplementation((*iter)->visual).CreateInstancePropertyMap(instanceMap);
1671 instancedProperties.Add((*iter)->visual.GetName(), instanceMap);
1676 void Control::Impl::RemoveVisual(RegisteredVisualContainer& visuals, const std::string& visualName)
1678 Actor self(mControlImpl.Self());
1680 for(RegisteredVisualContainer::Iterator visualIter = visuals.Begin();
1681 visualIter != visuals.End();
1684 Toolkit::Visual::Base visual = (*visualIter)->visual;
1685 if(visual && visual.GetName() == visualName)
1687 Toolkit::GetImplementation(visual).SetOffScene(self);
1688 (*visualIter)->visual.Reset();
1689 visuals.Erase(visualIter);
1695 void Control::Impl::RemoveVisuals(RegisteredVisualContainer& visuals, DictionaryKeys& removeVisuals)
1697 Actor self(mControlImpl.Self());
1698 for(DictionaryKeys::iterator iter = removeVisuals.begin(); iter != removeVisuals.end(); ++iter)
1700 const std::string visualName = *iter;
1701 RemoveVisual(visuals, visualName);
1705 void Control::Impl::RecreateChangedVisuals(Dictionary<Property::Map>& stateVisualsToChange,
1706 Dictionary<Property::Map>& instancedProperties)
1708 Dali::CustomActor handle(mControlImpl.GetOwner());
1709 for(Dictionary<Property::Map>::iterator iter = stateVisualsToChange.Begin();
1710 iter != stateVisualsToChange.End();
1713 const std::string& visualName = (*iter).key;
1714 const Property::Map& toMap = (*iter).entry;
1716 Actor self = mControlImpl.Self();
1717 RegisteredVisualContainer::Iterator registeredVisualsiter;
1718 // Check if visual (visualName) is already registered, this is the current visual.
1719 if(FindVisual(visualName, mVisuals, registeredVisualsiter))
1721 Toolkit::Visual::Base& visual = (*registeredVisualsiter)->visual;
1724 // No longer required to know if the replaced visual's resources are ready
1725 StopObservingVisual(visual);
1727 // If control staged then visuals will be swapped once ready
1728 if(self.GetProperty<bool>(Actor::Property::CONNECTED_TO_SCENE))
1730 // Check if visual is currently in the process of being replaced ( is in removal container )
1731 RegisteredVisualContainer::Iterator visualQueuedForRemoval;
1732 if(FindVisual(visualName, mRemoveVisuals, visualQueuedForRemoval))
1734 // Visual with same visual name is already in removal container so current visual pending
1735 // Only the the last requested visual will be displayed so remove current visual which is staged but not ready.
1736 Toolkit::GetImplementation(visual).SetOffScene(self);
1737 (*registeredVisualsiter)->visual.Reset();
1738 mVisuals.Erase(registeredVisualsiter);
1742 // current visual not already in removal container so add now.
1743 DALI_LOG_INFO(gLogFilter, Debug::Verbose, "RegisterVisual Move current registered visual to removal Queue: %s \n", visualName.c_str());
1744 MoveVisual(registeredVisualsiter, mVisuals, mRemoveVisuals);
1749 // Control not staged or visual disabled so can just erase from registered visuals and new visual will be added later.
1750 (*registeredVisualsiter)->visual.Reset();
1751 mVisuals.Erase(registeredVisualsiter);
1755 const Property::Map* instancedMap = instancedProperties.FindConst(visualName);
1756 Style::ApplyVisual(handle, visualName, toMap, instancedMap);
1761 void Control::Impl::ReplaceStateVisualsAndProperties(const StylePtr oldState, const StylePtr newState, const std::string& subState)
1763 // Collect all old visual names
1764 DictionaryKeys stateVisualsToRemove;
1767 oldState->visuals.GetKeys(stateVisualsToRemove);
1768 if(!subState.empty())
1770 const StylePtr* oldSubState = oldState->subStates.FindConst(subState);
1773 DictionaryKeys subStateVisualsToRemove;
1774 (*oldSubState)->visuals.GetKeys(subStateVisualsToRemove);
1775 Merge(stateVisualsToRemove, subStateVisualsToRemove);
1780 // Collect all new visual properties
1781 Dictionary<Property::Map> stateVisualsToAdd;
1784 stateVisualsToAdd = newState->visuals;
1785 if(!subState.empty())
1787 const StylePtr* newSubState = newState->subStates.FindConst(subState);
1790 stateVisualsToAdd.Merge((*newSubState)->visuals);
1795 // If a name is in both add/remove, move it to change list.
1796 Dictionary<Property::Map> stateVisualsToChange;
1797 FindChangableVisuals(stateVisualsToAdd, stateVisualsToChange, stateVisualsToRemove);
1799 // Copy instanced properties (e.g. text label) of current visuals
1800 Dictionary<Property::Map> instancedProperties;
1801 CopyInstancedProperties(mVisuals, instancedProperties);
1803 // For each visual in remove list, remove from mVisuals
1804 RemoveVisuals(mVisuals, stateVisualsToRemove);
1806 // For each visual in add list, create and add to mVisuals
1807 Dali::CustomActor handle(mControlImpl.GetOwner());
1808 Style::ApplyVisuals(handle, stateVisualsToAdd, instancedProperties);
1810 // For each visual in change list, if it requires a new visual,
1811 // remove old visual, create and add to mVisuals
1812 RecreateChangedVisuals(stateVisualsToChange, instancedProperties);
1815 void Control::Impl::SetState(DevelControl::State newState, bool withTransitions)
1817 DevelControl::State oldState = mState;
1818 Dali::CustomActor handle(mControlImpl.GetOwner());
1819 DALI_LOG_INFO(gLogFilter, Debug::Concise, "Control::Impl::SetState: %s\n", (mState == DevelControl::NORMAL ? "NORMAL" : (mState == DevelControl::FOCUSED ? "FOCUSED" : (mState == DevelControl::DISABLED ? "DISABLED" : "NONE"))));
1821 if(mState != newState)
1823 // If mState was Disabled, and new state is Focused, should probably
1824 // store that fact, e.g. in another property that FocusManager can access.
1827 // Trigger state change and transitions
1828 // Apply new style, if stylemanager is available
1829 Toolkit::StyleManager styleManager = Toolkit::StyleManager::Get();
1832 const StylePtr stylePtr = GetImpl(styleManager).GetRecordedStyle(Toolkit::Control(mControlImpl.GetOwner()));
1836 std::string oldStateName = Scripting::GetEnumerationName<Toolkit::DevelControl::State>(oldState, ControlStateTable, ControlStateTableCount);
1837 std::string newStateName = Scripting::GetEnumerationName<Toolkit::DevelControl::State>(newState, ControlStateTable, ControlStateTableCount);
1839 const StylePtr* newStateStyle = stylePtr->subStates.Find(newStateName);
1840 const StylePtr* oldStateStyle = stylePtr->subStates.Find(oldStateName);
1841 if(oldStateStyle && newStateStyle)
1843 // Only change if both state styles exist
1844 ReplaceStateVisualsAndProperties(*oldStateStyle, *newStateStyle, mSubStateName);
1851 void Control::Impl::SetSubState(const std::string& subStateName, bool withTransitions)
1853 if(mSubStateName != subStateName)
1855 // Get existing sub-state visuals, and unregister them
1856 Dali::CustomActor handle(mControlImpl.GetOwner());
1858 Toolkit::StyleManager styleManager = Toolkit::StyleManager::Get();
1861 const StylePtr stylePtr = GetImpl(styleManager).GetRecordedStyle(Toolkit::Control(mControlImpl.GetOwner()));
1865 std::string stateName = Scripting::GetEnumerationName<Toolkit::DevelControl::State>(mState, ControlStateTable, ControlStateTableCount);
1867 const StylePtr* state = stylePtr->subStates.Find(stateName);
1870 StylePtr stateStyle(*state);
1872 const StylePtr* newStateStyle = stateStyle->subStates.Find(subStateName);
1873 const StylePtr* oldStateStyle = stateStyle->subStates.Find(mSubStateName);
1874 if(oldStateStyle && newStateStyle)
1877 ReplaceStateVisualsAndProperties(*oldStateStyle, *newStateStyle, empty);
1883 mSubStateName = subStateName;
1887 void Control::Impl::OnSceneDisconnection()
1889 Actor self = mControlImpl.Self();
1891 // Any visuals set for replacement but not yet ready should still be registered.
1892 // Reason: If a request was made to register a new visual but the control removed from scene before visual was ready
1893 // then when this control appears back on stage it should use that new visual.
1895 // Iterate through all registered visuals and set off scene
1896 SetVisualsOffScene(mVisuals, self);
1898 // Visuals pending replacement can now be taken out of the removal list and set off scene
1899 // Iterate through all replacement visuals and add to a move queue then set off scene
1900 for(auto removalIter = mRemoveVisuals.Begin(), end = mRemoveVisuals.End(); removalIter != end; removalIter++)
1902 Toolkit::GetImplementation((*removalIter)->visual).SetOffScene(self);
1905 for(auto replacedIter = mVisuals.Begin(), end = mVisuals.End(); replacedIter != end; replacedIter++)
1907 (*replacedIter)->pending = false;
1910 mRemoveVisuals.Clear();
1913 void Control::Impl::SetMargin(Extents margin)
1915 mControlImpl.mImpl->mMargin = margin;
1917 // Trigger a size negotiation request that may be needed when setting a margin.
1918 mControlImpl.RelayoutRequest();
1921 Extents Control::Impl::GetMargin() const
1923 return mControlImpl.mImpl->mMargin;
1926 void Control::Impl::SetPadding(Extents padding)
1928 mControlImpl.mImpl->mPadding = padding;
1930 // Trigger a size negotiation request that may be needed when setting a padding.
1931 mControlImpl.RelayoutRequest();
1934 Extents Control::Impl::GetPadding() const
1936 return mControlImpl.mImpl->mPadding;
1939 void Control::Impl::SetInputMethodContext(InputMethodContext& inputMethodContext)
1941 mInputMethodContext = inputMethodContext;
1944 bool Control::Impl::FilterKeyEvent(const KeyEvent& event)
1946 bool consumed(false);
1948 if(mInputMethodContext)
1950 consumed = mInputMethodContext.FilterEventKey(event);
1955 DevelControl::VisualEventSignalType& Control::Impl::VisualEventSignal()
1957 return mVisualEventSignal;
1960 void Control::Impl::SetShadow(const Property::Map& map)
1962 Toolkit::Visual::Base visual = Toolkit::VisualFactory::Get().CreateVisual(map);
1963 visual.SetName("shadow");
1967 mControlImpl.mImpl->RegisterVisual(Toolkit::DevelControl::Property::SHADOW, visual, DepthIndex::BACKGROUND_EFFECT);
1969 mControlImpl.RelayoutRequest();
1973 void Control::Impl::ClearShadow()
1975 mControlImpl.mImpl->UnregisterVisual(Toolkit::DevelControl::Property::SHADOW);
1977 // Trigger a size negotiation request that may be needed when unregistering a visual.
1978 mControlImpl.RelayoutRequest();
1981 Dali::Property Control::Impl::GetVisualProperty(Dali::Property::Index index, Dali::Property::Key visualPropertyKey)
1983 Toolkit::Visual::Base visual = GetVisualByIndex(mVisuals, index);
1986 Internal::Visual::Base& visualImpl = Toolkit::GetImplementation(visual);
1987 return visualImpl.GetPropertyObject(visualPropertyKey);
1991 return Dali::Property(handle, Property::INVALID_INDEX);
1994 void Control::Impl::CreateTransitions(std::vector<std::pair<Dali::Property::Index, Dali::Property::Map>>& sourceProperties,
1995 std::vector<std::pair<Dali::Property::Index, Dali::Property::Map>>& destinationProperties,
1996 Dali::Toolkit::Control source, Dali::Toolkit::Control destination)
1998 // Retrieves background properties to be transitioned.
1999 Dali::Property::Map backgroundSourcePropertyMap, backgroundDestinationPropertyMap;
2000 mControlImpl.MakeVisualTransition(backgroundSourcePropertyMap, backgroundDestinationPropertyMap, source, destination, Toolkit::Control::Property::BACKGROUND);
2001 if(backgroundSourcePropertyMap.Count() > 0)
2003 sourceProperties.push_back(std::pair<Dali::Property::Index, Dali::Property::Map>(Toolkit::Control::Property::BACKGROUND, backgroundSourcePropertyMap));
2004 destinationProperties.push_back(std::pair<Dali::Property::Index, Dali::Property::Map>(Toolkit::Control::Property::BACKGROUND, backgroundDestinationPropertyMap));
2007 // Retrieves shadow properties to be transitioned.
2008 Dali::Property::Map shadowSourcePropertyMap, shadowDestinationPropertyMap;
2009 mControlImpl.MakeVisualTransition(shadowSourcePropertyMap, shadowDestinationPropertyMap, source, destination, Toolkit::DevelControl::Property::SHADOW);
2010 if(shadowSourcePropertyMap.Count() > 0)
2012 sourceProperties.push_back(std::pair<Dali::Property::Index, Dali::Property::Map>(Toolkit::DevelControl::Property::SHADOW, shadowSourcePropertyMap));
2013 destinationProperties.push_back(std::pair<Dali::Property::Index, Dali::Property::Map>(Toolkit::DevelControl::Property::SHADOW, shadowDestinationPropertyMap));
2016 // Retrieves transition from inherited class.
2017 mControlImpl.OnCreateTransitions(sourceProperties, destinationProperties, source, destination);
2020 void Control::Impl::UpdateVisualProperties(const std::vector<std::pair<Dali::Property::Index, Dali::Property::Map>>& properties)
2022 for(auto&& data : properties)
2024 if(data.first == Toolkit::Control::Property::BACKGROUND)
2026 DoAction(Toolkit::Control::Property::BACKGROUND, DevelVisual::Action::UPDATE_PROPERTY, data.second);
2028 else if(data.first == Toolkit::DevelControl::Property::SHADOW)
2030 DoAction(Toolkit::DevelControl::Property::SHADOW, DevelVisual::Action::UPDATE_PROPERTY, data.second);
2033 mControlImpl.OnUpdateVisualProperties(properties);
2036 void Control::Impl::EmitResourceReadySignal()
2038 if(!mIsEmittingResourceReadySignal)
2040 // Guard against calls to emit the signal during the callback
2041 mIsEmittingResourceReadySignal = true;
2043 // If the signal handler changes visual, it may become ready during this call & therefore this method will
2044 // get called again recursively. If so, mNeedToEmitResourceReady is set below, and we act on it after that secondary
2045 // invocation has completed by notifying in an Idle callback to prevent further recursion.
2046 Dali::Toolkit::Control handle(mControlImpl.GetOwner());
2047 mResourceReadySignal.Emit(handle);
2049 if(mNeedToEmitResourceReady)
2051 // Add idler to emit the signal again
2054 // The callback manager takes the ownership of the callback object.
2055 mIdleCallback = MakeCallback(this, &Control::Impl::OnIdleCallback);
2056 Adaptor::Get().AddIdle(mIdleCallback, false);
2060 mIsEmittingResourceReadySignal = false;
2064 mNeedToEmitResourceReady = true;
2068 void Control::Impl::OnIdleCallback()
2070 if(mNeedToEmitResourceReady)
2073 mNeedToEmitResourceReady = false;
2075 // A visual is ready so control may need relayouting if staged
2076 if(mControlImpl.Self().GetProperty<bool>(Actor::Property::CONNECTED_TO_SCENE))
2078 mControlImpl.RelayoutRequest();
2081 EmitResourceReadySignal();
2084 // Set the pointer to null as the callback manager deletes the callback after execute it.
2085 mIdleCallback = nullptr;
2088 Dali::Accessibility::Accessible* Control::Impl::GetAccessibilityObject()
2090 if(!mAccessibilityObject)
2092 mAccessibilityObject = mAccessibilityConstructor(mControlImpl.Self());
2094 return mAccessibilityObject.get();
2097 Dali::Accessibility::Accessible* Control::Impl::GetAccessibilityObject(Dali::Actor actor)
2101 auto control = Dali::Toolkit::Control::DownCast(actor);
2104 auto controlImpl = static_cast<Internal::Control*>(&control.GetImplementation());
2105 return controlImpl->mImpl->GetAccessibilityObject();
2111 } // namespace Internal
2113 } // namespace Toolkit