2 * Copyright (c) 2022 Samsung Electronics Co., Ltd.
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
8 * http://www.apache.org/licenses/LICENSE-2.0
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
19 #include "control-data-impl.h"
22 #include <dali-toolkit/public-api/controls/control-impl.h>
23 #include <dali-toolkit/public-api/controls/control.h>
24 #include <dali-toolkit/public-api/dali-toolkit-common.h>
25 #include <dali/devel-api/actors/actor-devel.h>
26 #include <dali/devel-api/adaptor-framework/accessibility.h>
27 #include <dali/devel-api/common/stage.h>
28 #include <dali/devel-api/object/handle-devel.h>
29 #include <dali/devel-api/scripting/enum-helper.h>
30 #include <dali/devel-api/scripting/scripting.h>
31 #include <dali/integration-api/adaptor-framework/adaptor.h>
32 #include <dali/integration-api/debug.h>
33 #include <dali/public-api/object/object-registry.h>
34 #include <dali/public-api/object/type-registry-helper.h>
39 #include <dali-toolkit/devel-api/asset-manager/asset-manager.h>
40 #include <dali-toolkit/devel-api/controls/control-depth-index-ranges.h>
41 #include <dali-toolkit/devel-api/controls/control-devel.h>
42 #include <dali-toolkit/devel-api/controls/control-wrapper-impl.h>
43 #include <dali-toolkit/devel-api/visuals/visual-actions-devel.h>
44 #include <dali-toolkit/internal/styling/style-manager-impl.h>
45 #include <dali-toolkit/internal/visuals/visual-base-impl.h>
46 #include <dali-toolkit/internal/visuals/visual-string-constants.h>
47 #include <dali-toolkit/public-api/controls/image-view/image-view.h>
48 #include <dali-toolkit/public-api/focus-manager/keyboard-focus-manager.h>
49 #include <dali-toolkit/public-api/visuals/image-visual-properties.h>
50 #include <dali-toolkit/public-api/visuals/visual-properties.h>
54 const std::string READING_INFO_TYPE_NAME = "name";
55 const std::string READING_INFO_TYPE_ROLE = "role";
56 const std::string READING_INFO_TYPE_DESCRIPTION = "description";
57 const std::string READING_INFO_TYPE_STATE = "state";
58 const std::string READING_INFO_TYPE_ATTRIBUTE_NAME = "reading_info_type";
59 const std::string READING_INFO_TYPE_SEPARATOR = "|";
68 extern const Dali::Scripting::StringEnum ControlStateTable[];
69 extern const unsigned int ControlStateTableCount;
71 // Not static or anonymous - shared with other translation units
72 const Scripting::StringEnum ControlStateTable[] = {
73 {"NORMAL", Toolkit::DevelControl::NORMAL},
74 {"FOCUSED", Toolkit::DevelControl::FOCUSED},
75 {"DISABLED", Toolkit::DevelControl::DISABLED},
77 const unsigned int ControlStateTableCount = sizeof(ControlStateTable) / sizeof(ControlStateTable[0]);
81 #if defined(DEBUG_ENABLED)
82 Debug::Filter* gLogFilter = Debug::Filter::New(Debug::NoLogging, false, "LOG_CONTROL_VISUALS");
86 void Remove(Dictionary<T>& keyValues, const std::string& name)
88 keyValues.Remove(name);
91 void Remove(DictionaryKeys& keys, const std::string& name)
93 DictionaryKeys::iterator iter = std::find(keys.begin(), keys.end(), name);
94 if(iter != keys.end())
101 * Finds visual in given array, returning true if found along with the iterator for that visual as a out parameter
103 bool FindVisual(Property::Index targetIndex, const RegisteredVisualContainer& visuals, RegisteredVisualContainer::Iterator& iter)
105 for(iter = visuals.Begin(); iter != visuals.End(); iter++)
107 if((*iter)->index == targetIndex)
116 * Finds visual in given array, returning true if found along with the iterator for that visual as a out parameter
118 bool FindVisual(std::string visualName, const RegisteredVisualContainer& visuals, RegisteredVisualContainer::Iterator& iter)
120 for(iter = visuals.Begin(); iter != visuals.End(); iter++)
122 Toolkit::Visual::Base visual = (*iter)->visual;
123 if(visual && visual.GetName() == visualName)
131 void FindChangableVisuals(Dictionary<Property::Map>& stateVisualsToAdd,
132 Dictionary<Property::Map>& stateVisualsToChange,
133 DictionaryKeys& stateVisualsToRemove)
135 DictionaryKeys copyOfStateVisualsToRemove = stateVisualsToRemove;
137 for(DictionaryKeys::iterator iter = copyOfStateVisualsToRemove.begin();
138 iter != copyOfStateVisualsToRemove.end();
141 const std::string& visualName = (*iter);
142 Property::Map* toMap = stateVisualsToAdd.Find(visualName);
145 stateVisualsToChange.Add(visualName, *toMap);
146 stateVisualsToAdd.Remove(visualName);
147 Remove(stateVisualsToRemove, visualName);
152 Toolkit::Visual::Base GetVisualByName(
153 const RegisteredVisualContainer& visuals,
154 const std::string& visualName)
156 Toolkit::Visual::Base visualHandle;
158 RegisteredVisualContainer::Iterator iter;
159 for(iter = visuals.Begin(); iter != visuals.End(); iter++)
161 Toolkit::Visual::Base visual = (*iter)->visual;
162 if(visual && visual.GetName() == visualName)
164 visualHandle = visual;
171 Toolkit::Visual::Base GetVisualByIndex(
172 const RegisteredVisualContainer& visuals,
173 Property::Index index)
175 Toolkit::Visual::Base visualHandle;
177 RegisteredVisualContainer::Iterator iter;
178 for(iter = visuals.Begin(); iter != visuals.End(); iter++)
180 if((*iter)->index == index)
182 visualHandle = (*iter)->visual;
190 * Move visual from source to destination container
192 void MoveVisual(RegisteredVisualContainer::Iterator sourceIter, RegisteredVisualContainer& source, RegisteredVisualContainer& destination)
194 Toolkit::Visual::Base visual = (*sourceIter)->visual;
197 RegisteredVisual* rv = source.Release(sourceIter);
198 destination.PushBack(rv);
203 * Performs actions as requested using the action name.
204 * @param[in] object The object on which to perform the action.
205 * @param[in] actionName The action to perform.
206 * @param[in] attributes The attributes with which to perfrom this action.
207 * @return true if action has been accepted by this control
209 const char* ACTION_ACCESSIBILITY_ACTIVATED = "accessibilityActivated";
210 const char* ACTION_ACCESSIBILITY_READING_CANCELLED = "ReadingCancelled";
211 const char* ACTION_ACCESSIBILITY_READING_PAUSED = "ReadingPaused";
212 const char* ACTION_ACCESSIBILITY_READING_RESUMED = "ReadingResumed";
213 const char* ACTION_ACCESSIBILITY_READING_SKIPPED = "ReadingSkipped";
214 const char* ACTION_ACCESSIBILITY_READING_STOPPED = "ReadingStopped";
216 static bool DoAction(BaseObject* object, const std::string& actionName, const Property::Map& attributes)
220 Dali::BaseHandle handle(object);
222 Toolkit::Control control = Toolkit::Control::DownCast(handle);
224 DALI_ASSERT_ALWAYS(control);
226 if(0 == strcmp(actionName.c_str(), ACTION_ACCESSIBILITY_ACTIVATED) || actionName == "activate")
228 // if cast succeeds there is an implementation so no need to check
229 if(!DevelControl::AccessibilityActivateSignal(control).Empty())
231 DevelControl::AccessibilityActivateSignal(control).Emit();
235 ret = Internal::GetImplementation(control).OnAccessibilityActivated();
238 else if(0 == strcmp(actionName.c_str(), ACTION_ACCESSIBILITY_READING_SKIPPED))
240 // if cast succeeds there is an implementation so no need to check
241 if(!DevelControl::AccessibilityReadingSkippedSignal(control).Empty())
243 DevelControl::AccessibilityReadingSkippedSignal(control).Emit();
246 else if(0 == strcmp(actionName.c_str(), ACTION_ACCESSIBILITY_READING_PAUSED))
248 // if cast succeeds there is an implementation so no need to check
249 if(!DevelControl::AccessibilityReadingPausedSignal(control).Empty())
251 DevelControl::AccessibilityReadingPausedSignal(control).Emit();
254 else if(0 == strcmp(actionName.c_str(), ACTION_ACCESSIBILITY_READING_RESUMED))
256 // if cast succeeds there is an implementation so no need to check
257 if(!DevelControl::AccessibilityReadingResumedSignal(control).Empty())
259 DevelControl::AccessibilityReadingResumedSignal(control).Emit();
262 else if(0 == strcmp(actionName.c_str(), ACTION_ACCESSIBILITY_READING_CANCELLED))
264 // if cast succeeds there is an implementation so no need to check
265 if(!DevelControl::AccessibilityReadingCancelledSignal(control).Empty())
267 DevelControl::AccessibilityReadingCancelledSignal(control).Emit();
270 else if(0 == strcmp(actionName.c_str(), ACTION_ACCESSIBILITY_READING_STOPPED))
272 // if cast succeeds there is an implementation so no need to check
273 if(!DevelControl::AccessibilityReadingStoppedSignal(control).Empty())
275 DevelControl::AccessibilityReadingStoppedSignal(control).Emit();
286 * Connects a callback function with the object's signals.
287 * @param[in] object The object providing the signal.
288 * @param[in] tracker Used to disconnect the signal.
289 * @param[in] signalName The signal to connect to.
290 * @param[in] functor A newly allocated FunctorDelegate.
291 * @return True if the signal was connected.
292 * @post If a signal was connected, ownership of functor was passed to CallbackBase. Otherwise the caller is responsible for deleting the unused functor.
294 const char* SIGNAL_KEY_EVENT = "keyEvent";
295 const char* SIGNAL_KEY_INPUT_FOCUS_GAINED = "keyInputFocusGained";
296 const char* SIGNAL_KEY_INPUT_FOCUS_LOST = "keyInputFocusLost";
297 const char* SIGNAL_TAPPED = "tapped";
298 const char* SIGNAL_PANNED = "panned";
299 const char* SIGNAL_PINCHED = "pinched";
300 const char* SIGNAL_LONG_PRESSED = "longPressed";
301 const char* SIGNAL_GET_NAME = "getName";
302 const char* SIGNAL_GET_DESCRIPTION = "getDescription";
303 const char* SIGNAL_DO_GESTURE = "doGesture";
304 static bool DoConnectSignal(BaseObject* object, ConnectionTrackerInterface* tracker, const std::string& signalName, FunctorDelegate* functor)
306 Dali::BaseHandle handle(object);
308 bool connected(false);
309 Toolkit::Control control = Toolkit::Control::DownCast(handle);
312 Internal::Control& controlImpl(Internal::GetImplementation(control));
315 if(0 == strcmp(signalName.c_str(), SIGNAL_KEY_EVENT))
317 controlImpl.KeyEventSignal().Connect(tracker, functor);
319 else if(0 == strcmp(signalName.c_str(), SIGNAL_KEY_INPUT_FOCUS_GAINED))
321 controlImpl.KeyInputFocusGainedSignal().Connect(tracker, functor);
323 else if(0 == strcmp(signalName.c_str(), SIGNAL_KEY_INPUT_FOCUS_LOST))
325 controlImpl.KeyInputFocusLostSignal().Connect(tracker, functor);
327 else if(0 == strcmp(signalName.c_str(), SIGNAL_TAPPED))
329 controlImpl.EnableGestureDetection(GestureType::TAP);
330 controlImpl.GetTapGestureDetector().DetectedSignal().Connect(tracker, functor);
332 else if(0 == strcmp(signalName.c_str(), SIGNAL_PANNED))
334 controlImpl.EnableGestureDetection(GestureType::PAN);
335 controlImpl.GetPanGestureDetector().DetectedSignal().Connect(tracker, functor);
337 else if(0 == strcmp(signalName.c_str(), SIGNAL_PINCHED))
339 controlImpl.EnableGestureDetection(GestureType::PINCH);
340 controlImpl.GetPinchGestureDetector().DetectedSignal().Connect(tracker, functor);
342 else if(0 == strcmp(signalName.c_str(), SIGNAL_LONG_PRESSED))
344 controlImpl.EnableGestureDetection(GestureType::LONG_PRESS);
345 controlImpl.GetLongPressGestureDetector().DetectedSignal().Connect(tracker, functor);
347 else if(0 == strcmp(signalName.c_str(), SIGNAL_GET_NAME))
349 DevelControl::AccessibilityGetNameSignal(control).Connect(tracker, functor);
351 else if(0 == strcmp(signalName.c_str(), SIGNAL_GET_DESCRIPTION))
353 DevelControl::AccessibilityGetDescriptionSignal(control).Connect(tracker, functor);
355 else if(0 == strcmp(signalName.c_str(), SIGNAL_DO_GESTURE))
357 DevelControl::AccessibilityDoGestureSignal(control).Connect(tracker, functor);
364 * Creates control through type registry
368 return Internal::Control::New();
370 // Setup signals and actions using the type-registry.
371 DALI_TYPE_REGISTRATION_BEGIN(Control, CustomActor, Create);
373 // Note: Properties are registered separately below.
375 SignalConnectorType registerSignal1(typeRegistration, SIGNAL_KEY_EVENT, &DoConnectSignal);
376 SignalConnectorType registerSignal2(typeRegistration, SIGNAL_KEY_INPUT_FOCUS_GAINED, &DoConnectSignal);
377 SignalConnectorType registerSignal3(typeRegistration, SIGNAL_KEY_INPUT_FOCUS_LOST, &DoConnectSignal);
378 SignalConnectorType registerSignal4(typeRegistration, SIGNAL_TAPPED, &DoConnectSignal);
379 SignalConnectorType registerSignal5(typeRegistration, SIGNAL_PANNED, &DoConnectSignal);
380 SignalConnectorType registerSignal6(typeRegistration, SIGNAL_PINCHED, &DoConnectSignal);
381 SignalConnectorType registerSignal7(typeRegistration, SIGNAL_LONG_PRESSED, &DoConnectSignal);
382 SignalConnectorType registerSignal8(typeRegistration, SIGNAL_GET_NAME, &DoConnectSignal);
383 SignalConnectorType registerSignal9(typeRegistration, SIGNAL_GET_DESCRIPTION, &DoConnectSignal);
384 SignalConnectorType registerSignal10(typeRegistration, SIGNAL_DO_GESTURE, &DoConnectSignal);
386 TypeAction registerAction1(typeRegistration, "activate", &DoAction);
387 TypeAction registerAction2(typeRegistration, ACTION_ACCESSIBILITY_ACTIVATED, &DoAction);
388 TypeAction registerAction3(typeRegistration, ACTION_ACCESSIBILITY_READING_SKIPPED, &DoAction);
389 TypeAction registerAction4(typeRegistration, ACTION_ACCESSIBILITY_READING_CANCELLED, &DoAction);
390 TypeAction registerAction5(typeRegistration, ACTION_ACCESSIBILITY_READING_STOPPED, &DoAction);
391 TypeAction registerAction6(typeRegistration, ACTION_ACCESSIBILITY_READING_PAUSED, &DoAction);
392 TypeAction registerAction7(typeRegistration, ACTION_ACCESSIBILITY_READING_RESUMED, &DoAction);
394 DALI_TYPE_REGISTRATION_END()
397 * @brief Iterate through given container and setOffScene any visual found
399 * @param[in] container Container of visuals
400 * @param[in] parent Parent actor to remove visuals from
402 void SetVisualsOffScene(const RegisteredVisualContainer& container, Actor parent)
404 for(auto iter = container.Begin(), end = container.End(); iter != end; iter++)
408 DALI_LOG_INFO(gLogFilter, Debug::Verbose, "Control::SetOffScene Setting visual(%d) off stage\n", (*iter)->index);
409 Toolkit::GetImplementation((*iter)->visual).SetOffScene(parent);
414 Dali::Rect<> GetShowingGeometry(Dali::Rect<> rect, Dali::Toolkit::DevelControl::ControlAccessible* accessible)
417 Vector2 currentPosition;
418 auto parent = dynamic_cast<Toolkit::DevelControl::ControlAccessible*>(accessible->GetParent());
422 parentRect = parent->GetExtents(Dali::Accessibility::CoordinateType::WINDOW);
424 currentPosition.x = rect.x;
425 currentPosition.y = rect.y;
427 rect.x = rect.x > parentRect.x ? rect.x : parentRect.x;
428 rect.y = rect.y > parentRect.y ? rect.y : parentRect.y;
429 rect.width = currentPosition.x + rect.width < parentRect.x + parentRect.width ? currentPosition.x + rect.width - rect.x : parentRect.x + parentRect.width - rect.x;
430 rect.height = currentPosition.y + rect.height < parentRect.y + parentRect.height ? currentPosition.y + rect.height - rect.y : parentRect.y + parentRect.height - rect.y;
432 if(rect.width < 0 || rect.height < 0)
437 parent = dynamic_cast<Toolkit::DevelControl::ControlAccessible*>(parent->GetParent());
443 static bool IsShowingGeometryOnScreen(Dali::Rect<> rect)
445 return rect.width > 0 && rect.height > 0;
448 Dali::Accessibility::Accessible* ExternalAccessibleGetter(Dali::Actor actor)
450 auto control = Toolkit::Control::DownCast(actor);
456 auto& controlImpl = Toolkit::Internal::GetImplementation(control);
458 return controlImpl.GetAccessibleObject();
461 } // unnamed namespace
464 // Properties registered without macro to use specific member variables.
465 const PropertyRegistration Control::Impl::PROPERTY_1(typeRegistration, "styleName", Toolkit::Control::Property::STYLE_NAME, Property::STRING, &Control::Impl::SetProperty, &Control::Impl::GetProperty);
466 const PropertyRegistration Control::Impl::PROPERTY_4(typeRegistration, "keyInputFocus", Toolkit::Control::Property::KEY_INPUT_FOCUS, Property::BOOLEAN, &Control::Impl::SetProperty, &Control::Impl::GetProperty);
467 const PropertyRegistration Control::Impl::PROPERTY_5(typeRegistration, "background", Toolkit::Control::Property::BACKGROUND, Property::MAP, &Control::Impl::SetProperty, &Control::Impl::GetProperty);
468 const PropertyRegistration Control::Impl::PROPERTY_6(typeRegistration, "margin", Toolkit::Control::Property::MARGIN, Property::EXTENTS, &Control::Impl::SetProperty, &Control::Impl::GetProperty);
469 const PropertyRegistration Control::Impl::PROPERTY_7(typeRegistration, "padding", Toolkit::Control::Property::PADDING, Property::EXTENTS, &Control::Impl::SetProperty, &Control::Impl::GetProperty);
470 const PropertyRegistration Control::Impl::PROPERTY_8(typeRegistration, "tooltip", Toolkit::DevelControl::Property::TOOLTIP, Property::MAP, &Control::Impl::SetProperty, &Control::Impl::GetProperty);
471 const PropertyRegistration Control::Impl::PROPERTY_9(typeRegistration, "state", Toolkit::DevelControl::Property::STATE, Property::STRING, &Control::Impl::SetProperty, &Control::Impl::GetProperty);
472 const PropertyRegistration Control::Impl::PROPERTY_10(typeRegistration, "subState", Toolkit::DevelControl::Property::SUB_STATE, Property::STRING, &Control::Impl::SetProperty, &Control::Impl::GetProperty);
473 const PropertyRegistration Control::Impl::PROPERTY_11(typeRegistration, "leftFocusableActorId", Toolkit::DevelControl::Property::LEFT_FOCUSABLE_ACTOR_ID, Property::INTEGER, &Control::Impl::SetProperty, &Control::Impl::GetProperty);
474 const PropertyRegistration Control::Impl::PROPERTY_12(typeRegistration, "rightFocusableActorId", Toolkit::DevelControl::Property::RIGHT_FOCUSABLE_ACTOR_ID, Property::INTEGER, &Control::Impl::SetProperty, &Control::Impl::GetProperty);
475 const PropertyRegistration Control::Impl::PROPERTY_13(typeRegistration, "upFocusableActorId", Toolkit::DevelControl::Property::UP_FOCUSABLE_ACTOR_ID, Property::INTEGER, &Control::Impl::SetProperty, &Control::Impl::GetProperty);
476 const PropertyRegistration Control::Impl::PROPERTY_14(typeRegistration, "downFocusableActorId", Toolkit::DevelControl::Property::DOWN_FOCUSABLE_ACTOR_ID, Property::INTEGER, &Control::Impl::SetProperty, &Control::Impl::GetProperty);
477 const PropertyRegistration Control::Impl::PROPERTY_15(typeRegistration, "shadow", Toolkit::DevelControl::Property::SHADOW, Property::MAP, &Control::Impl::SetProperty, &Control::Impl::GetProperty);
478 const PropertyRegistration Control::Impl::PROPERTY_16(typeRegistration, "accessibilityName", Toolkit::DevelControl::Property::ACCESSIBILITY_NAME, Property::STRING, &Control::Impl::SetProperty, &Control::Impl::GetProperty);
479 const PropertyRegistration Control::Impl::PROPERTY_17(typeRegistration, "accessibilityDescription", Toolkit::DevelControl::Property::ACCESSIBILITY_DESCRIPTION, Property::STRING, &Control::Impl::SetProperty, &Control::Impl::GetProperty);
480 const PropertyRegistration Control::Impl::PROPERTY_18(typeRegistration, "accessibilityTranslationDomain", Toolkit::DevelControl::Property::ACCESSIBILITY_TRANSLATION_DOMAIN, Property::STRING, &Control::Impl::SetProperty, &Control::Impl::GetProperty);
481 const PropertyRegistration Control::Impl::PROPERTY_19(typeRegistration, "accessibilityRole", Toolkit::DevelControl::Property::ACCESSIBILITY_ROLE, Property::INTEGER, &Control::Impl::SetProperty, &Control::Impl::GetProperty);
482 const PropertyRegistration Control::Impl::PROPERTY_20(typeRegistration, "accessibilityHighlightable", Toolkit::DevelControl::Property::ACCESSIBILITY_HIGHLIGHTABLE, Property::BOOLEAN, &Control::Impl::SetProperty, &Control::Impl::GetProperty);
483 const PropertyRegistration Control::Impl::PROPERTY_21(typeRegistration, "accessibilityAttributes", Toolkit::DevelControl::Property::ACCESSIBILITY_ATTRIBUTES, Property::MAP, &Control::Impl::SetProperty, &Control::Impl::GetProperty);
484 const PropertyRegistration Control::Impl::PROPERTY_22(typeRegistration, "dispatchKeyEvents", Toolkit::DevelControl::Property::DISPATCH_KEY_EVENTS, Property::BOOLEAN, &Control::Impl::SetProperty, &Control::Impl::GetProperty);
485 const PropertyRegistration Control::Impl::PROPERTY_23(typeRegistration, "accessibilityHidden", Toolkit::DevelControl::Property::ACCESSIBILITY_HIDDEN, Property::BOOLEAN, &Control::Impl::SetProperty, &Control::Impl::GetProperty);
486 const PropertyRegistration Control::Impl::PROPERTY_24(typeRegistration, "clockwiseFocusableActorId", Toolkit::DevelControl::Property::CLOCKWISE_FOCUSABLE_ACTOR_ID, Property::INTEGER, &Control::Impl::SetProperty, &Control::Impl::GetProperty);
487 const PropertyRegistration Control::Impl::PROPERTY_25(typeRegistration, "counterClockwiseFocusableActorId", Toolkit::DevelControl::Property::COUNTER_CLOCKWISE_FOCUSABLE_ACTOR_ID, Property::INTEGER, &Control::Impl::SetProperty, &Control::Impl::GetProperty);
491 Control::Impl::Impl(Control& controlImpl)
492 : mControlImpl(controlImpl),
493 mState(Toolkit::DevelControl::NORMAL),
495 mLeftFocusableActorId(-1),
496 mRightFocusableActorId(-1),
497 mUpFocusableActorId(-1),
498 mDownFocusableActorId(-1),
499 mClockwiseFocusableActorId(-1),
500 mCounterClockwiseFocusableActorId(-1),
502 mBackgroundColor(Color::TRANSPARENT),
503 mStartingPinchScale(nullptr),
505 mPadding(0, 0, 0, 0),
507 mKeyInputFocusGainedSignal(),
508 mKeyInputFocusLostSignal(),
509 mResourceReadySignal(),
510 mVisualEventSignal(),
511 mAccessibilityGetNameSignal(),
512 mAccessibilityGetDescriptionSignal(),
513 mAccessibilityDoGestureSignal(),
514 mPinchGestureDetector(),
515 mPanGestureDetector(),
516 mTapGestureDetector(),
517 mLongPressGestureDetector(),
519 mInputMethodContext(),
520 mIdleCallback(nullptr),
521 mFlags(Control::ControlBehaviour(CONTROL_BEHAVIOUR_DEFAULT)),
522 mIsKeyboardNavigationSupported(false),
523 mIsKeyboardFocusGroup(false),
524 mIsEmittingResourceReadySignal(false),
525 mNeedToEmitResourceReady(false),
526 mDispatchKeyEvents(true)
528 Dali::Accessibility::Accessible::RegisterExternalAccessibleGetter(&ExternalAccessibleGetter);
531 Control::Impl::~Impl()
533 for(auto&& iter : mVisuals)
535 StopObservingVisual(iter->visual);
538 for(auto&& iter : mRemoveVisuals)
540 StopObservingVisual(iter->visual);
543 // All gesture detectors will be destroyed so no need to disconnect.
544 delete mStartingPinchScale;
546 if(mIdleCallback && Adaptor::IsAvailable())
548 // Removes the callback from the callback manager in case the control is destroyed before the callback is executed.
549 Adaptor::Get().RemoveIdle(mIdleCallback);
553 Control::Impl& Control::Impl::Get(Internal::Control& internalControl)
555 return *internalControl.mImpl;
558 const Control::Impl& Control::Impl::Get(const Internal::Control& internalControl)
560 return *internalControl.mImpl;
563 void Control::Impl::CheckHighlightedObjectGeometry()
565 auto accessible = GetAccessibleObject();
566 auto lastPosition = accessible->GetLastPosition();
567 auto accessibleRect = accessible->GetExtents(Dali::Accessibility::CoordinateType::WINDOW);
568 auto rect = GetShowingGeometry(accessibleRect, accessible);
570 switch(mAccessibilityLastScreenRelativeMoveType)
572 case Dali::Accessibility::ScreenRelativeMoveType::OUTSIDE:
574 if(IsShowingGeometryOnScreen(rect))
576 mAccessibilityLastScreenRelativeMoveType = Dali::Accessibility::ScreenRelativeMoveType::INSIDE;
580 case Dali::Accessibility::ScreenRelativeMoveType::INSIDE:
582 if(rect.width < 0 && accessibleRect.x != lastPosition.x)
584 mAccessibilityLastScreenRelativeMoveType = (accessibleRect.x < lastPosition.x) ? Dali::Accessibility::ScreenRelativeMoveType::OUTGOING_TOP_LEFT : Dali::Accessibility::ScreenRelativeMoveType::OUTGOING_BOTTOM_RIGHT;
586 if(rect.height < 0 && accessibleRect.y != lastPosition.y)
588 mAccessibilityLastScreenRelativeMoveType = (accessibleRect.y < lastPosition.y) ? Dali::Accessibility::ScreenRelativeMoveType::OUTGOING_TOP_LEFT : Dali::Accessibility::ScreenRelativeMoveType::OUTGOING_BOTTOM_RIGHT;
590 // notify AT-clients on outgoing moves only
591 if(mAccessibilityLastScreenRelativeMoveType != Dali::Accessibility::ScreenRelativeMoveType::INSIDE)
593 accessible->EmitMovedOutOfScreen(mAccessibilityLastScreenRelativeMoveType);
597 case Dali::Accessibility::ScreenRelativeMoveType::OUTGOING_TOP_LEFT:
598 case Dali::Accessibility::ScreenRelativeMoveType::OUTGOING_BOTTOM_RIGHT:
600 if(IsShowingGeometryOnScreen(rect))
602 mAccessibilityLastScreenRelativeMoveType = Dali::Accessibility::ScreenRelativeMoveType::INSIDE;
606 mAccessibilityLastScreenRelativeMoveType = Dali::Accessibility::ScreenRelativeMoveType::OUTSIDE;
616 accessible->SetLastPosition(Vector2(accessibleRect.x, accessibleRect.y));
619 void Control::Impl::RegisterAccessibilityPositionPropertyNotification()
621 if(mIsAccessibilityPositionPropertyNotificationSet)
625 // set default value until first move of object is detected
626 mAccessibilityLastScreenRelativeMoveType = Dali::Accessibility::ScreenRelativeMoveType::OUTSIDE;
627 // recalculate mAccessibilityLastScreenRelativeMoveType accordingly to the initial position
628 CheckHighlightedObjectGeometry();
629 mAccessibilityPositionNotification = mControlImpl.Self().AddPropertyNotification(Actor::Property::WORLD_POSITION, StepCondition(1.0f, 1.0f));
630 mAccessibilityPositionNotification.SetNotifyMode(PropertyNotification::NOTIFY_ON_CHANGED);
631 mAccessibilityPositionNotification.NotifySignal().Connect(this, [this](PropertyNotification&) { CheckHighlightedObjectGeometry(); });
632 mIsAccessibilityPositionPropertyNotificationSet = true;
635 void Control::Impl::UnregisterAccessibilityPositionPropertyNotification()
637 mControlImpl.Self().RemovePropertyNotification(mAccessibilityPositionNotification);
638 mIsAccessibilityPositionPropertyNotificationSet = false;
641 // Gesture Detection Methods
642 void Control::Impl::PinchDetected(Actor actor, const PinchGesture& pinch)
644 mControlImpl.OnPinch(pinch);
647 void Control::Impl::PanDetected(Actor actor, const PanGesture& pan)
649 mControlImpl.OnPan(pan);
652 void Control::Impl::TapDetected(Actor actor, const TapGesture& tap)
654 mControlImpl.OnTap(tap);
657 void Control::Impl::LongPressDetected(Actor actor, const LongPressGesture& longPress)
659 mControlImpl.OnLongPress(longPress);
662 void Control::Impl::RegisterVisual(Property::Index index, Toolkit::Visual::Base& visual)
664 RegisterVisual(index, visual, VisualState::ENABLED, DepthIndexValue::NOT_SET);
667 void Control::Impl::RegisterVisual(Property::Index index, Toolkit::Visual::Base& visual, int depthIndex)
669 RegisterVisual(index, visual, VisualState::ENABLED, DepthIndexValue::SET, depthIndex);
672 void Control::Impl::RegisterVisual(Property::Index index, Toolkit::Visual::Base& visual, bool enabled)
674 RegisterVisual(index, visual, (enabled ? VisualState::ENABLED : VisualState::DISABLED), DepthIndexValue::NOT_SET);
677 void Control::Impl::RegisterVisual(Property::Index index, Toolkit::Visual::Base& visual, bool enabled, int depthIndex)
679 RegisterVisual(index, visual, (enabled ? VisualState::ENABLED : VisualState::DISABLED), DepthIndexValue::SET, depthIndex);
682 void Control::Impl::RegisterVisual(Property::Index index, Toolkit::Visual::Base& visual, VisualState::Type enabled, DepthIndexValue::Type depthIndexValueSet, int depthIndex)
684 DALI_LOG_INFO(gLogFilter, Debug::Concise, "RegisterVisual:%d \n", index);
686 bool visualReplaced(false);
687 Actor self = mControlImpl.Self();
689 // Set the depth index, if not set by caller this will be either the current visual depth, max depth of all visuals
691 int requiredDepthIndex = visual.GetDepthIndex();
693 if(depthIndexValueSet == DepthIndexValue::SET)
695 requiredDepthIndex = depthIndex;
698 // Visual replacement, existing visual should only be removed from stage when replacement ready.
699 if(!mVisuals.Empty())
701 RegisteredVisualContainer::Iterator registeredVisualsiter;
702 // Check if visual (index) is already registered, this is the current visual.
703 if(FindVisual(index, mVisuals, registeredVisualsiter))
705 Toolkit::Visual::Base& currentRegisteredVisual = (*registeredVisualsiter)->visual;
706 if(currentRegisteredVisual)
708 // Store current visual depth index as may need to set the replacement visual to same depth
709 const int currentDepthIndex = (*registeredVisualsiter)->visual.GetDepthIndex();
711 // No longer required to know if the replaced visual's resources are ready
712 StopObservingVisual(currentRegisteredVisual);
714 // If control staged and visual enabled then visuals will be swapped once ready
715 if(self.GetProperty<bool>(Actor::Property::CONNECTED_TO_SCENE) && enabled)
717 // Check if visual is currently in the process of being replaced ( is in removal container )
718 RegisteredVisualContainer::Iterator visualQueuedForRemoval;
719 if(FindVisual(index, mRemoveVisuals, visualQueuedForRemoval))
721 // Visual with same index is already in removal container so current visual pending
722 // Only the the last requested visual will be displayed so remove current visual which is staged but not ready.
723 Toolkit::GetImplementation(currentRegisteredVisual).SetOffScene(self);
724 mVisuals.Erase(registeredVisualsiter);
728 // current visual not already in removal container so add now.
729 DALI_LOG_INFO(gLogFilter, Debug::Verbose, "RegisterVisual Move current registered visual to removal Queue: %d \n", index);
730 MoveVisual(registeredVisualsiter, mVisuals, mRemoveVisuals);
735 // Control not staged or visual disabled so can just erase from registered visuals and new visual will be added later.
736 mVisuals.Erase(registeredVisualsiter);
739 // If we've not set the depth-index value and the new visual does not have a depth index applied to it, then use the previously set depth-index for this index
740 if((depthIndexValueSet == DepthIndexValue::NOT_SET) &&
741 (visual.GetDepthIndex() == 0))
743 requiredDepthIndex = currentDepthIndex;
747 visualReplaced = true;
751 // If not set, set the name of the visual to the same name as the control's property.
752 // ( If the control has been type registered )
753 if(visual.GetName().empty())
755 // returns empty string if index is not found as long as index is not -1
756 std::string visualName = self.GetPropertyName(index);
757 if(!visualName.empty())
759 DALI_LOG_INFO(gLogFilter, Debug::Concise, "Setting visual name for property %d to %s\n", index, visualName.c_str());
760 visual.SetName(visualName);
764 if(!visualReplaced) // New registration entry
766 // If we've not set the depth-index value, we have more than one visual and the visual does not have a depth index, then set it to be the highest
767 if((depthIndexValueSet == DepthIndexValue::NOT_SET) &&
768 (mVisuals.Size() > 0) &&
769 (visual.GetDepthIndex() == 0))
771 int maxDepthIndex = std::numeric_limits<int>::min();
773 RegisteredVisualContainer::ConstIterator iter;
774 const RegisteredVisualContainer::ConstIterator endIter = mVisuals.End();
775 for(iter = mVisuals.Begin(); iter != endIter; iter++)
777 const int visualDepthIndex = (*iter)->visual.GetDepthIndex();
778 if(visualDepthIndex > maxDepthIndex)
780 maxDepthIndex = visualDepthIndex;
783 ++maxDepthIndex; // Add one to the current maximum depth index so that our added visual appears on top
784 requiredDepthIndex = std::max(0, maxDepthIndex); // Start at zero if maxDepth index belongs to a background
790 // Set determined depth index
791 visual.SetDepthIndex(requiredDepthIndex);
793 // Monitor when the visual resources are ready
794 StartObservingVisual(visual);
796 DALI_LOG_INFO(gLogFilter, Debug::Concise, "New Visual registration index[%d] depth[%d]\n", index, requiredDepthIndex);
797 RegisteredVisual* newRegisteredVisual = new RegisteredVisual(index, visual, (enabled == VisualState::ENABLED ? true : false), (visualReplaced && enabled));
798 mVisuals.PushBack(newRegisteredVisual);
800 Internal::Visual::Base& visualImpl = Toolkit::GetImplementation(visual);
801 // Put on stage if enabled and the control is already on the stage
802 if((enabled == VisualState::ENABLED) && self.GetProperty<bool>(Actor::Property::CONNECTED_TO_SCENE))
804 visualImpl.SetOnScene(self);
806 else if(visualImpl.IsResourceReady()) // When not being staged, check if visual already 'ResourceReady' before it was Registered. ( Resource may have been loaded already )
808 ResourceReady(visualImpl);
812 DALI_LOG_INFO(gLogFilter, Debug::Verbose, "Control::RegisterVisual() Registered %s(%d), enabled:%s\n", visual.GetName().c_str(), index, enabled ? "true" : "false");
815 void Control::Impl::UnregisterVisual(Property::Index index)
817 RegisteredVisualContainer::Iterator iter;
818 if(FindVisual(index, mVisuals, iter))
820 // stop observing visual
821 StopObservingVisual((*iter)->visual);
823 Actor self(mControlImpl.Self());
824 Toolkit::GetImplementation((*iter)->visual).SetOffScene(self);
825 (*iter)->visual.Reset();
826 mVisuals.Erase(iter);
829 if(FindVisual(index, mRemoveVisuals, iter))
831 Actor self(mControlImpl.Self());
832 Toolkit::GetImplementation((*iter)->visual).SetOffScene(self);
833 (*iter)->pending = false;
834 (*iter)->visual.Reset();
835 mRemoveVisuals.Erase(iter);
839 Toolkit::Visual::Base Control::Impl::GetVisual(Property::Index index) const
841 RegisteredVisualContainer::Iterator iter;
842 if(FindVisual(index, mVisuals, iter))
844 return (*iter)->visual;
847 return Toolkit::Visual::Base();
850 void Control::Impl::EnableVisual(Property::Index index, bool enable)
852 DALI_LOG_INFO(gLogFilter, Debug::General, "Control::EnableVisual(%d, %s)\n", index, enable ? "T" : "F");
854 RegisteredVisualContainer::Iterator iter;
855 if(FindVisual(index, mVisuals, iter))
857 if((*iter)->enabled == enable)
859 DALI_LOG_INFO(gLogFilter, Debug::Verbose, "Control::EnableVisual Visual %s(%d) already %s\n", (*iter)->visual.GetName().c_str(), index, enable ? "enabled" : "disabled");
863 (*iter)->enabled = enable;
864 Actor parentActor = mControlImpl.Self();
865 if(mControlImpl.Self().GetProperty<bool>(Actor::Property::CONNECTED_TO_SCENE)) // If control not on Scene then Visual will be added when SceneConnection is called.
869 DALI_LOG_INFO(gLogFilter, Debug::Verbose, "Control::EnableVisual Setting %s(%d) on stage \n", (*iter)->visual.GetName().c_str(), index);
870 Toolkit::GetImplementation((*iter)->visual).SetOnScene(parentActor);
874 DALI_LOG_INFO(gLogFilter, Debug::Verbose, "Control::EnableVisual Setting %s(%d) off stage \n", (*iter)->visual.GetName().c_str(), index);
875 Toolkit::GetImplementation((*iter)->visual).SetOffScene(parentActor); // No need to call if control not staged.
881 DALI_LOG_WARNING("Control::EnableVisual(%d, %s) FAILED - NO SUCH VISUAL\n", index, enable ? "T" : "F");
885 bool Control::Impl::IsVisualEnabled(Property::Index index) const
887 RegisteredVisualContainer::Iterator iter;
888 if(FindVisual(index, mVisuals, iter))
890 return (*iter)->enabled;
895 void Control::Impl::StopObservingVisual(Toolkit::Visual::Base& visual)
897 Internal::Visual::Base& visualImpl = Toolkit::GetImplementation(visual);
899 // Stop observing the visual
900 visualImpl.RemoveEventObserver(*this);
903 void Control::Impl::StartObservingVisual(Toolkit::Visual::Base& visual)
905 Internal::Visual::Base& visualImpl = Toolkit::GetImplementation(visual);
907 // start observing the visual for events
908 visualImpl.AddEventObserver(*this);
911 // Called by a Visual when it's resource is ready
912 void Control::Impl::ResourceReady(Visual::Base& object)
914 DALI_LOG_INFO(gLogFilter, Debug::Verbose, "Control::Impl::ResourceReady() replacements pending[%d]\n", mRemoveVisuals.Count());
916 Actor self = mControlImpl.Self();
918 // A resource is ready, find resource in the registered visuals container and get its index
919 for(auto registeredIter = mVisuals.Begin(), end = mVisuals.End(); registeredIter != end; ++registeredIter)
921 Internal::Visual::Base& registeredVisualImpl = Toolkit::GetImplementation((*registeredIter)->visual);
923 if(&object == ®isteredVisualImpl)
925 RegisteredVisualContainer::Iterator visualToRemoveIter;
926 // Find visual with the same index in the removal container
927 // Set if off stage as it's replacement is now ready.
928 // Remove if from removal list as now removed from stage.
929 // Set Pending flag on the ready visual to false as now ready.
930 if(FindVisual((*registeredIter)->index, mRemoveVisuals, visualToRemoveIter))
932 (*registeredIter)->pending = false;
933 Toolkit::GetImplementation((*visualToRemoveIter)->visual).SetOffScene(self);
934 mRemoveVisuals.Erase(visualToRemoveIter);
940 // A visual is ready so control may need relayouting if staged
941 if(self.GetProperty<bool>(Actor::Property::CONNECTED_TO_SCENE))
943 mControlImpl.RelayoutRequest();
946 // Emit signal if all enabled visuals registered by the control are ready.
947 if(IsResourceReady())
950 mNeedToEmitResourceReady = false;
952 EmitResourceReadySignal();
956 void Control::Impl::NotifyVisualEvent(Visual::Base& object, Property::Index signalId)
958 for(auto registeredIter = mVisuals.Begin(), end = mVisuals.End(); registeredIter != end; ++registeredIter)
960 Internal::Visual::Base& registeredVisualImpl = Toolkit::GetImplementation((*registeredIter)->visual);
961 if(&object == ®isteredVisualImpl)
963 Dali::Toolkit::Control handle(mControlImpl.GetOwner());
964 mVisualEventSignal.Emit(handle, (*registeredIter)->index, signalId);
970 void Control::Impl::RelayoutRequest(Visual::Base& object)
972 mControlImpl.RelayoutRequest();
975 bool Control::Impl::IsResourceReady() const
977 // Iterate through and check all the enabled visuals are ready
978 for(auto visualIter = mVisuals.Begin();
979 visualIter != mVisuals.End();
982 const Toolkit::Visual::Base visual = (*visualIter)->visual;
983 const Internal::Visual::Base& visualImpl = Toolkit::GetImplementation(visual);
985 // one of the enabled visuals is not ready
986 if(!visualImpl.IsResourceReady() && (*visualIter)->enabled)
994 Toolkit::Visual::ResourceStatus Control::Impl::GetVisualResourceStatus(Property::Index index) const
996 RegisteredVisualContainer::Iterator iter;
997 if(FindVisual(index, mVisuals, iter))
999 const Toolkit::Visual::Base visual = (*iter)->visual;
1000 const Internal::Visual::Base& visualImpl = Toolkit::GetImplementation(visual);
1001 return visualImpl.GetResourceStatus();
1004 return Toolkit::Visual::ResourceStatus::PREPARING;
1007 void Control::Impl::AddTransitions(Dali::Animation& animation,
1008 const Toolkit::TransitionData& handle,
1009 bool createAnimation)
1011 // Setup a Transition from TransitionData.
1012 const Internal::TransitionData& transitionData = Toolkit::GetImplementation(handle);
1013 TransitionData::Iterator end = transitionData.End();
1014 for(TransitionData::Iterator iter = transitionData.Begin();
1018 TransitionData::Animator* animator = (*iter);
1020 Toolkit::Visual::Base visual = GetVisualByName(mVisuals, animator->objectName);
1024 #if defined(DEBUG_ENABLED)
1025 Dali::TypeInfo typeInfo;
1026 ControlWrapper* controlWrapperImpl = dynamic_cast<ControlWrapper*>(&mControlImpl);
1027 if(controlWrapperImpl)
1029 typeInfo = controlWrapperImpl->GetTypeInfo();
1032 DALI_LOG_INFO(gLogFilter, Debug::Concise, "CreateTransition: Found %s visual for %s\n", visual.GetName().c_str(), typeInfo ? typeInfo.GetName().c_str() : "Unknown");
1034 Internal::Visual::Base& visualImpl = Toolkit::GetImplementation(visual);
1035 visualImpl.AnimateProperty(animation, *animator);
1039 DALI_LOG_INFO(gLogFilter, Debug::Concise, "CreateTransition: Could not find visual. Trying actors");
1040 // Otherwise, try any actor children of control (Including the control)
1041 Actor child = mControlImpl.Self().FindChildByName(animator->objectName);
1044 Property::Index propertyIndex = child.GetPropertyIndex(animator->propertyKey);
1045 if(propertyIndex != Property::INVALID_INDEX)
1047 if(animator->animate == false)
1049 if(animator->targetValue.GetType() != Property::NONE)
1051 child.SetProperty(propertyIndex, animator->targetValue);
1054 else // animate the property
1056 if(animator->initialValue.GetType() != Property::NONE)
1058 child.SetProperty(propertyIndex, animator->initialValue);
1061 if(createAnimation && !animation)
1063 animation = Dali::Animation::New(0.1f);
1066 animation.AnimateTo(Property(child, propertyIndex),
1067 animator->targetValue,
1068 animator->alphaFunction,
1069 TimePeriod(animator->timePeriodDelay,
1070 animator->timePeriodDuration));
1078 Dali::Animation Control::Impl::CreateTransition(const Toolkit::TransitionData& transitionData)
1080 Dali::Animation transition;
1082 if(transitionData.Count() > 0)
1084 AddTransitions(transition, transitionData, true);
1089 void Control::Impl::DoAction(Dali::Property::Index visualIndex, Dali::Property::Index actionId, const Dali::Property::Value attributes)
1091 RegisteredVisualContainer::Iterator iter;
1092 if(FindVisual(visualIndex, mVisuals, iter))
1094 Toolkit::GetImplementation((*iter)->visual).DoAction(actionId, attributes);
1098 void Control::Impl::DoActionExtension(Dali::Property::Index visualIndex, Dali::Property::Index actionId, Dali::Any attributes)
1100 RegisteredVisualContainer::Iterator iter;
1101 if(FindVisual(visualIndex, mVisuals, iter))
1103 Toolkit::GetImplementation((*iter)->visual).DoActionExtension(actionId, attributes);
1107 void Control::Impl::AppendAccessibilityAttribute(const std::string& key, const std::string value)
1109 Property::Value* checkedValue = mAccessibilityAttributes.Find(key);
1112 mAccessibilityAttributes[key] = Property::Value(value);
1116 mAccessibilityAttributes.Insert(key, value);
1120 void Control::Impl::SetProperty(BaseObject* object, Property::Index index, const Property::Value& value)
1122 Toolkit::Control control = Toolkit::Control::DownCast(BaseHandle(object));
1126 Control& controlImpl(GetImplementation(control));
1130 case Toolkit::Control::Property::STYLE_NAME:
1132 controlImpl.SetStyleName(value.Get<std::string>());
1136 case Toolkit::DevelControl::Property::STATE:
1138 bool withTransitions = true;
1139 const Property::Value* valuePtr = &value;
1140 const Property::Map* map = value.GetMap();
1143 Property::Value* value2 = map->Find("withTransitions");
1146 withTransitions = value2->Get<bool>();
1149 valuePtr = map->Find("state");
1154 Toolkit::DevelControl::State state(controlImpl.mImpl->mState);
1155 if(Scripting::GetEnumerationProperty<Toolkit::DevelControl::State>(*valuePtr, ControlStateTable, ControlStateTableCount, state))
1157 controlImpl.mImpl->SetState(state, withTransitions);
1163 case Toolkit::DevelControl::Property::SUB_STATE:
1165 std::string subState;
1166 if(value.Get(subState))
1168 controlImpl.mImpl->SetSubState(subState);
1173 case Toolkit::DevelControl::Property::LEFT_FOCUSABLE_ACTOR_ID:
1176 if(value.Get(focusId))
1178 controlImpl.mImpl->mLeftFocusableActorId = focusId;
1183 case Toolkit::DevelControl::Property::RIGHT_FOCUSABLE_ACTOR_ID:
1186 if(value.Get(focusId))
1188 controlImpl.mImpl->mRightFocusableActorId = focusId;
1193 case Toolkit::DevelControl::Property::UP_FOCUSABLE_ACTOR_ID:
1196 if(value.Get(focusId))
1198 controlImpl.mImpl->mUpFocusableActorId = focusId;
1203 case Toolkit::DevelControl::Property::DOWN_FOCUSABLE_ACTOR_ID:
1206 if(value.Get(focusId))
1208 controlImpl.mImpl->mDownFocusableActorId = focusId;
1213 case Toolkit::Control::Property::KEY_INPUT_FOCUS:
1215 if(value.Get<bool>())
1217 controlImpl.SetKeyInputFocus();
1221 controlImpl.ClearKeyInputFocus();
1226 case Toolkit::Control::Property::BACKGROUND:
1230 const Property::Map* map = value.GetMap();
1231 if(map && !map->Empty())
1233 controlImpl.SetBackground(*map);
1235 else if(value.Get(url))
1237 // don't know the size to load
1238 Toolkit::Visual::Base visual = Toolkit::VisualFactory::Get().CreateVisual(url, ImageDimensions());
1241 controlImpl.mImpl->RegisterVisual(Toolkit::Control::Property::BACKGROUND, visual, DepthIndex::BACKGROUND);
1244 else if(value.Get(color))
1246 controlImpl.SetBackgroundColor(color);
1250 // The background is an empty property map, so we should clear the background
1251 controlImpl.ClearBackground();
1256 case Toolkit::Control::Property::MARGIN:
1259 if(value.Get(margin))
1261 controlImpl.mImpl->SetMargin(margin);
1266 case Toolkit::Control::Property::PADDING:
1269 if(value.Get(padding))
1271 controlImpl.mImpl->SetPadding(padding);
1276 case Toolkit::DevelControl::Property::TOOLTIP:
1278 TooltipPtr& tooltipPtr = controlImpl.mImpl->mTooltip;
1281 tooltipPtr = Tooltip::New(control);
1283 tooltipPtr->SetProperties(value);
1287 case Toolkit::DevelControl::Property::SHADOW:
1289 const Property::Map* map = value.GetMap();
1290 if(map && !map->Empty())
1292 controlImpl.mImpl->SetShadow(*map);
1296 // The shadow is an empty property map, so we should clear the shadow
1297 controlImpl.mImpl->ClearShadow();
1302 case Toolkit::DevelControl::Property::ACCESSIBILITY_NAME:
1307 controlImpl.mImpl->mAccessibilityName = name;
1312 case Toolkit::DevelControl::Property::ACCESSIBILITY_DESCRIPTION:
1317 controlImpl.mImpl->mAccessibilityDescription = text;
1322 case Toolkit::DevelControl::Property::ACCESSIBILITY_TRANSLATION_DOMAIN:
1327 controlImpl.mImpl->mAccessibilityTranslationDomain = text;
1332 case Toolkit::DevelControl::Property::ACCESSIBILITY_ROLE:
1334 Dali::Accessibility::Role role;
1337 controlImpl.mImpl->mAccessibilityRole = role;
1342 case Toolkit::DevelControl::Property::ACCESSIBILITY_HIGHLIGHTABLE:
1345 if(value.Get(highlightable))
1347 controlImpl.mImpl->mAccessibilityHighlightable = highlightable;
1352 case Toolkit::DevelControl::Property::ACCESSIBILITY_ATTRIBUTES:
1354 const Property::Map* map = value.GetMap();
1355 if(map && !map->Empty())
1357 controlImpl.mImpl->mAccessibilityAttributes = *map;
1362 case Toolkit::DevelControl::Property::DISPATCH_KEY_EVENTS:
1365 if(value.Get(dispatch))
1367 controlImpl.mImpl->mDispatchKeyEvents = dispatch;
1372 case Toolkit::DevelControl::Property::ACCESSIBILITY_HIDDEN:
1375 if(value.Get(hidden))
1377 controlImpl.mImpl->mAccessibilityHidden = hidden;
1379 auto* accessible = controlImpl.GetAccessibleObject();
1380 auto* parent = dynamic_cast<Dali::Accessibility::ActorAccessible*>(accessible->GetParent());
1383 parent->OnChildrenChanged();
1388 case Toolkit::DevelControl::Property::CLOCKWISE_FOCUSABLE_ACTOR_ID:
1391 if(value.Get(focusId))
1393 controlImpl.mImpl->mClockwiseFocusableActorId = focusId;
1397 case Toolkit::DevelControl::Property::COUNTER_CLOCKWISE_FOCUSABLE_ACTOR_ID:
1400 if(value.Get(focusId))
1402 controlImpl.mImpl->mCounterClockwiseFocusableActorId = focusId;
1410 Property::Value Control::Impl::GetProperty(BaseObject* object, Property::Index index)
1412 Property::Value value;
1414 Toolkit::Control control = Toolkit::Control::DownCast(BaseHandle(object));
1418 Control& controlImpl(GetImplementation(control));
1422 case Toolkit::Control::Property::STYLE_NAME:
1424 value = controlImpl.GetStyleName();
1428 case Toolkit::DevelControl::Property::STATE:
1430 value = controlImpl.mImpl->mState;
1434 case Toolkit::DevelControl::Property::SUB_STATE:
1436 value = controlImpl.mImpl->mSubStateName;
1440 case Toolkit::DevelControl::Property::LEFT_FOCUSABLE_ACTOR_ID:
1442 value = controlImpl.mImpl->mLeftFocusableActorId;
1446 case Toolkit::DevelControl::Property::RIGHT_FOCUSABLE_ACTOR_ID:
1448 value = controlImpl.mImpl->mRightFocusableActorId;
1452 case Toolkit::DevelControl::Property::UP_FOCUSABLE_ACTOR_ID:
1454 value = controlImpl.mImpl->mUpFocusableActorId;
1458 case Toolkit::DevelControl::Property::DOWN_FOCUSABLE_ACTOR_ID:
1460 value = controlImpl.mImpl->mDownFocusableActorId;
1464 case Toolkit::Control::Property::KEY_INPUT_FOCUS:
1466 value = controlImpl.HasKeyInputFocus();
1470 case Toolkit::Control::Property::BACKGROUND:
1473 Toolkit::Visual::Base visual = controlImpl.mImpl->GetVisual(Toolkit::Control::Property::BACKGROUND);
1476 visual.CreatePropertyMap(map);
1483 case Toolkit::Control::Property::MARGIN:
1485 value = controlImpl.mImpl->GetMargin();
1489 case Toolkit::Control::Property::PADDING:
1491 value = controlImpl.mImpl->GetPadding();
1495 case Toolkit::DevelControl::Property::TOOLTIP:
1498 if(controlImpl.mImpl->mTooltip)
1500 controlImpl.mImpl->mTooltip->CreatePropertyMap(map);
1506 case Toolkit::DevelControl::Property::SHADOW:
1509 Toolkit::Visual::Base visual = controlImpl.mImpl->GetVisual(Toolkit::DevelControl::Property::SHADOW);
1512 visual.CreatePropertyMap(map);
1519 case Toolkit::DevelControl::Property::ACCESSIBILITY_NAME:
1521 value = controlImpl.mImpl->mAccessibilityName;
1525 case Toolkit::DevelControl::Property::ACCESSIBILITY_DESCRIPTION:
1527 value = controlImpl.mImpl->mAccessibilityDescription;
1531 case Toolkit::DevelControl::Property::ACCESSIBILITY_TRANSLATION_DOMAIN:
1533 value = controlImpl.mImpl->mAccessibilityTranslationDomain;
1537 case Toolkit::DevelControl::Property::ACCESSIBILITY_ROLE:
1539 value = Property::Value(controlImpl.mImpl->mAccessibilityRole);
1543 case Toolkit::DevelControl::Property::ACCESSIBILITY_HIGHLIGHTABLE:
1545 value = controlImpl.mImpl->mAccessibilityHighlightable;
1549 case Toolkit::DevelControl::Property::ACCESSIBILITY_ATTRIBUTES:
1551 value = controlImpl.mImpl->mAccessibilityAttributes;
1555 case Toolkit::DevelControl::Property::DISPATCH_KEY_EVENTS:
1557 value = controlImpl.mImpl->mDispatchKeyEvents;
1561 case Toolkit::DevelControl::Property::ACCESSIBILITY_HIDDEN:
1563 value = controlImpl.mImpl->mAccessibilityHidden;
1567 case Toolkit::DevelControl::Property::CLOCKWISE_FOCUSABLE_ACTOR_ID:
1569 value = controlImpl.mImpl->mClockwiseFocusableActorId;
1573 case Toolkit::DevelControl::Property::COUNTER_CLOCKWISE_FOCUSABLE_ACTOR_ID:
1575 value = controlImpl.mImpl->mCounterClockwiseFocusableActorId;
1584 void Control::Impl::RemoveAccessibilityAttribute(const std::string& key)
1586 Property::Value* value = mAccessibilityAttributes.Find(key);
1589 mAccessibilityAttributes[key] = Property::Value();
1593 void Control::Impl::ClearAccessibilityAttributes()
1595 mAccessibilityAttributes.Clear();
1598 void Control::Impl::SetAccessibilityReadingInfoType(const Dali::Accessibility::ReadingInfoTypes types)
1600 std::string value{};
1601 if(types[Dali::Accessibility::ReadingInfoType::NAME])
1603 value += READING_INFO_TYPE_NAME;
1605 if(types[Dali::Accessibility::ReadingInfoType::ROLE])
1609 value += READING_INFO_TYPE_SEPARATOR;
1611 value += READING_INFO_TYPE_ROLE;
1613 if(types[Dali::Accessibility::ReadingInfoType::DESCRIPTION])
1617 value += READING_INFO_TYPE_SEPARATOR;
1619 value += READING_INFO_TYPE_DESCRIPTION;
1621 if(types[Dali::Accessibility::ReadingInfoType::STATE])
1625 value += READING_INFO_TYPE_SEPARATOR;
1627 value += READING_INFO_TYPE_STATE;
1629 AppendAccessibilityAttribute(READING_INFO_TYPE_ATTRIBUTE_NAME, value);
1632 Dali::Accessibility::ReadingInfoTypes Control::Impl::GetAccessibilityReadingInfoType() const
1634 std::string value{};
1635 auto place = mAccessibilityAttributes.Find(READING_INFO_TYPE_ATTRIBUTE_NAME);
1642 Dali::Accessibility::ReadingInfoTypes types;
1643 types[Dali::Accessibility::ReadingInfoType::NAME] = true;
1644 types[Dali::Accessibility::ReadingInfoType::ROLE] = true;
1645 types[Dali::Accessibility::ReadingInfoType::DESCRIPTION] = true;
1646 types[Dali::Accessibility::ReadingInfoType::STATE] = true;
1655 Dali::Accessibility::ReadingInfoTypes types;
1657 if(value.find(READING_INFO_TYPE_NAME) != std::string::npos)
1659 types[Dali::Accessibility::ReadingInfoType::NAME] = true;
1661 if(value.find(READING_INFO_TYPE_ROLE) != std::string::npos)
1663 types[Dali::Accessibility::ReadingInfoType::ROLE] = true;
1665 if(value.find(READING_INFO_TYPE_DESCRIPTION) != std::string::npos)
1667 types[Dali::Accessibility::ReadingInfoType::DESCRIPTION] = true;
1669 if(value.find(READING_INFO_TYPE_STATE) != std::string::npos)
1671 types[Dali::Accessibility::ReadingInfoType::STATE] = true;
1677 void Control::Impl::CopyInstancedProperties(RegisteredVisualContainer& visuals, Dictionary<Property::Map>& instancedProperties)
1679 for(RegisteredVisualContainer::Iterator iter = visuals.Begin(); iter != visuals.End(); iter++)
1683 Property::Map instanceMap;
1684 Toolkit::GetImplementation((*iter)->visual).CreateInstancePropertyMap(instanceMap);
1685 instancedProperties.Add((*iter)->visual.GetName(), instanceMap);
1690 void Control::Impl::RemoveVisual(RegisteredVisualContainer& visuals, const std::string& visualName)
1692 Actor self(mControlImpl.Self());
1694 for(RegisteredVisualContainer::Iterator visualIter = visuals.Begin();
1695 visualIter != visuals.End();
1698 Toolkit::Visual::Base visual = (*visualIter)->visual;
1699 if(visual && visual.GetName() == visualName)
1701 Toolkit::GetImplementation(visual).SetOffScene(self);
1702 (*visualIter)->visual.Reset();
1703 visuals.Erase(visualIter);
1709 void Control::Impl::RemoveVisuals(RegisteredVisualContainer& visuals, DictionaryKeys& removeVisuals)
1711 Actor self(mControlImpl.Self());
1712 for(DictionaryKeys::iterator iter = removeVisuals.begin(); iter != removeVisuals.end(); ++iter)
1714 const std::string visualName = *iter;
1715 RemoveVisual(visuals, visualName);
1719 void Control::Impl::RecreateChangedVisuals(Dictionary<Property::Map>& stateVisualsToChange,
1720 Dictionary<Property::Map>& instancedProperties)
1722 Dali::CustomActor handle(mControlImpl.GetOwner());
1723 for(Dictionary<Property::Map>::iterator iter = stateVisualsToChange.Begin();
1724 iter != stateVisualsToChange.End();
1727 const std::string& visualName = (*iter).key;
1728 const Property::Map& toMap = (*iter).entry;
1730 Actor self = mControlImpl.Self();
1731 RegisteredVisualContainer::Iterator registeredVisualsiter;
1732 // Check if visual (visualName) is already registered, this is the current visual.
1733 if(FindVisual(visualName, mVisuals, registeredVisualsiter))
1735 Toolkit::Visual::Base& visual = (*registeredVisualsiter)->visual;
1738 // No longer required to know if the replaced visual's resources are ready
1739 StopObservingVisual(visual);
1741 // If control staged then visuals will be swapped once ready
1742 if(self.GetProperty<bool>(Actor::Property::CONNECTED_TO_SCENE))
1744 // Check if visual is currently in the process of being replaced ( is in removal container )
1745 RegisteredVisualContainer::Iterator visualQueuedForRemoval;
1746 if(FindVisual(visualName, mRemoveVisuals, visualQueuedForRemoval))
1748 // Visual with same visual name is already in removal container so current visual pending
1749 // Only the the last requested visual will be displayed so remove current visual which is staged but not ready.
1750 Toolkit::GetImplementation(visual).SetOffScene(self);
1751 (*registeredVisualsiter)->visual.Reset();
1752 mVisuals.Erase(registeredVisualsiter);
1756 // current visual not already in removal container so add now.
1757 DALI_LOG_INFO(gLogFilter, Debug::Verbose, "RegisterVisual Move current registered visual to removal Queue: %s \n", visualName.c_str());
1758 MoveVisual(registeredVisualsiter, mVisuals, mRemoveVisuals);
1763 // Control not staged or visual disabled so can just erase from registered visuals and new visual will be added later.
1764 (*registeredVisualsiter)->visual.Reset();
1765 mVisuals.Erase(registeredVisualsiter);
1769 const Property::Map* instancedMap = instancedProperties.FindConst(visualName);
1770 Style::ApplyVisual(handle, visualName, toMap, instancedMap);
1775 void Control::Impl::ReplaceStateVisualsAndProperties(const StylePtr oldState, const StylePtr newState, const std::string& subState)
1777 // Collect all old visual names
1778 DictionaryKeys stateVisualsToRemove;
1781 oldState->visuals.GetKeys(stateVisualsToRemove);
1782 if(!subState.empty())
1784 const StylePtr* oldSubState = oldState->subStates.FindConst(subState);
1787 DictionaryKeys subStateVisualsToRemove;
1788 (*oldSubState)->visuals.GetKeys(subStateVisualsToRemove);
1789 Merge(stateVisualsToRemove, subStateVisualsToRemove);
1794 // Collect all new visual properties
1795 Dictionary<Property::Map> stateVisualsToAdd;
1798 stateVisualsToAdd = newState->visuals;
1799 if(!subState.empty())
1801 const StylePtr* newSubState = newState->subStates.FindConst(subState);
1804 stateVisualsToAdd.Merge((*newSubState)->visuals);
1809 // If a name is in both add/remove, move it to change list.
1810 Dictionary<Property::Map> stateVisualsToChange;
1811 FindChangableVisuals(stateVisualsToAdd, stateVisualsToChange, stateVisualsToRemove);
1813 // Copy instanced properties (e.g. text label) of current visuals
1814 Dictionary<Property::Map> instancedProperties;
1815 CopyInstancedProperties(mVisuals, instancedProperties);
1817 // For each visual in remove list, remove from mVisuals
1818 RemoveVisuals(mVisuals, stateVisualsToRemove);
1820 // For each visual in add list, create and add to mVisuals
1821 Dali::CustomActor handle(mControlImpl.GetOwner());
1822 Style::ApplyVisuals(handle, stateVisualsToAdd, instancedProperties);
1824 // For each visual in change list, if it requires a new visual,
1825 // remove old visual, create and add to mVisuals
1826 RecreateChangedVisuals(stateVisualsToChange, instancedProperties);
1829 void Control::Impl::SetState(DevelControl::State newState, bool withTransitions)
1831 DevelControl::State oldState = mState;
1832 Dali::CustomActor handle(mControlImpl.GetOwner());
1833 DALI_LOG_INFO(gLogFilter, Debug::Concise, "Control::Impl::SetState: %s\n", (mState == DevelControl::NORMAL ? "NORMAL" : (mState == DevelControl::FOCUSED ? "FOCUSED" : (mState == DevelControl::DISABLED ? "DISABLED" : "NONE"))));
1835 if(mState != newState)
1837 // If mState was Disabled, and new state is Focused, should probably
1838 // store that fact, e.g. in another property that FocusManager can access.
1841 // Trigger state change and transitions
1842 // Apply new style, if stylemanager is available
1843 Toolkit::StyleManager styleManager = Toolkit::StyleManager::Get();
1846 const StylePtr stylePtr = GetImpl(styleManager).GetRecordedStyle(Toolkit::Control(mControlImpl.GetOwner()));
1850 std::string oldStateName = Scripting::GetEnumerationName<Toolkit::DevelControl::State>(oldState, ControlStateTable, ControlStateTableCount);
1851 std::string newStateName = Scripting::GetEnumerationName<Toolkit::DevelControl::State>(newState, ControlStateTable, ControlStateTableCount);
1853 const StylePtr* newStateStyle = stylePtr->subStates.Find(newStateName);
1854 const StylePtr* oldStateStyle = stylePtr->subStates.Find(oldStateName);
1855 if(oldStateStyle && newStateStyle)
1857 // Only change if both state styles exist
1858 ReplaceStateVisualsAndProperties(*oldStateStyle, *newStateStyle, mSubStateName);
1865 void Control::Impl::SetSubState(const std::string& subStateName, bool withTransitions)
1867 if(mSubStateName != subStateName)
1869 // Get existing sub-state visuals, and unregister them
1870 Dali::CustomActor handle(mControlImpl.GetOwner());
1872 Toolkit::StyleManager styleManager = Toolkit::StyleManager::Get();
1875 const StylePtr stylePtr = GetImpl(styleManager).GetRecordedStyle(Toolkit::Control(mControlImpl.GetOwner()));
1879 std::string stateName = Scripting::GetEnumerationName<Toolkit::DevelControl::State>(mState, ControlStateTable, ControlStateTableCount);
1881 const StylePtr* state = stylePtr->subStates.Find(stateName);
1884 StylePtr stateStyle(*state);
1886 const StylePtr* newStateStyle = stateStyle->subStates.Find(subStateName);
1887 const StylePtr* oldStateStyle = stateStyle->subStates.Find(mSubStateName);
1888 if(oldStateStyle && newStateStyle)
1891 ReplaceStateVisualsAndProperties(*oldStateStyle, *newStateStyle, empty);
1897 mSubStateName = subStateName;
1901 void Control::Impl::OnSceneDisconnection()
1903 Actor self = mControlImpl.Self();
1905 // Any visuals set for replacement but not yet ready should still be registered.
1906 // Reason: If a request was made to register a new visual but the control removed from scene before visual was ready
1907 // then when this control appears back on stage it should use that new visual.
1909 // Iterate through all registered visuals and set off scene
1910 SetVisualsOffScene(mVisuals, self);
1912 // Visuals pending replacement can now be taken out of the removal list and set off scene
1913 // Iterate through all replacement visuals and add to a move queue then set off scene
1914 for(auto removalIter = mRemoveVisuals.Begin(), end = mRemoveVisuals.End(); removalIter != end; removalIter++)
1916 Toolkit::GetImplementation((*removalIter)->visual).SetOffScene(self);
1919 for(auto replacedIter = mVisuals.Begin(), end = mVisuals.End(); replacedIter != end; replacedIter++)
1921 (*replacedIter)->pending = false;
1924 mRemoveVisuals.Clear();
1927 void Control::Impl::SetMargin(Extents margin)
1929 mControlImpl.mImpl->mMargin = margin;
1931 // Trigger a size negotiation request that may be needed when setting a margin.
1932 mControlImpl.RelayoutRequest();
1935 Extents Control::Impl::GetMargin() const
1937 return mControlImpl.mImpl->mMargin;
1940 void Control::Impl::SetPadding(Extents padding)
1942 mControlImpl.mImpl->mPadding = padding;
1944 // Trigger a size negotiation request that may be needed when setting a padding.
1945 mControlImpl.RelayoutRequest();
1948 Extents Control::Impl::GetPadding() const
1950 return mControlImpl.mImpl->mPadding;
1953 void Control::Impl::SetInputMethodContext(InputMethodContext& inputMethodContext)
1955 mInputMethodContext = inputMethodContext;
1958 bool Control::Impl::FilterKeyEvent(const KeyEvent& event)
1960 bool consumed(false);
1962 if(mInputMethodContext)
1964 consumed = mInputMethodContext.FilterEventKey(event);
1969 DevelControl::VisualEventSignalType& Control::Impl::VisualEventSignal()
1971 return mVisualEventSignal;
1974 void Control::Impl::SetShadow(const Property::Map& map)
1976 Toolkit::Visual::Base visual = Toolkit::VisualFactory::Get().CreateVisual(map);
1977 visual.SetName("shadow");
1981 mControlImpl.mImpl->RegisterVisual(Toolkit::DevelControl::Property::SHADOW, visual, DepthIndex::BACKGROUND_EFFECT);
1983 mControlImpl.RelayoutRequest();
1987 void Control::Impl::ClearShadow()
1989 mControlImpl.mImpl->UnregisterVisual(Toolkit::DevelControl::Property::SHADOW);
1991 // Trigger a size negotiation request that may be needed when unregistering a visual.
1992 mControlImpl.RelayoutRequest();
1995 Dali::Property Control::Impl::GetVisualProperty(Dali::Property::Index index, Dali::Property::Key visualPropertyKey)
1997 Toolkit::Visual::Base visual = GetVisualByIndex(mVisuals, index);
2000 Internal::Visual::Base& visualImpl = Toolkit::GetImplementation(visual);
2001 return visualImpl.GetPropertyObject(visualPropertyKey);
2005 return Dali::Property(handle, Property::INVALID_INDEX);
2008 void Control::Impl::CreateTransitions(std::vector<std::pair<Dali::Property::Index, Dali::Property::Map>>& sourceProperties,
2009 std::vector<std::pair<Dali::Property::Index, Dali::Property::Map>>& destinationProperties,
2010 Dali::Toolkit::Control source,
2011 Dali::Toolkit::Control destination)
2013 // Retrieves background properties to be transitioned.
2014 Dali::Property::Map backgroundSourcePropertyMap, backgroundDestinationPropertyMap;
2015 mControlImpl.MakeVisualTransition(backgroundSourcePropertyMap, backgroundDestinationPropertyMap, source, destination, Toolkit::Control::Property::BACKGROUND);
2016 if(backgroundSourcePropertyMap.Count() > 0)
2018 sourceProperties.push_back(std::pair<Dali::Property::Index, Dali::Property::Map>(Toolkit::Control::Property::BACKGROUND, backgroundSourcePropertyMap));
2019 destinationProperties.push_back(std::pair<Dali::Property::Index, Dali::Property::Map>(Toolkit::Control::Property::BACKGROUND, backgroundDestinationPropertyMap));
2022 // Retrieves shadow properties to be transitioned.
2023 Dali::Property::Map shadowSourcePropertyMap, shadowDestinationPropertyMap;
2024 mControlImpl.MakeVisualTransition(shadowSourcePropertyMap, shadowDestinationPropertyMap, source, destination, Toolkit::DevelControl::Property::SHADOW);
2025 if(shadowSourcePropertyMap.Count() > 0)
2027 sourceProperties.push_back(std::pair<Dali::Property::Index, Dali::Property::Map>(Toolkit::DevelControl::Property::SHADOW, shadowSourcePropertyMap));
2028 destinationProperties.push_back(std::pair<Dali::Property::Index, Dali::Property::Map>(Toolkit::DevelControl::Property::SHADOW, shadowDestinationPropertyMap));
2031 // Retrieves transition from inherited class.
2032 mControlImpl.OnCreateTransitions(sourceProperties, destinationProperties, source, destination);
2035 void Control::Impl::UpdateVisualProperties(const std::vector<std::pair<Dali::Property::Index, Dali::Property::Map>>& properties)
2037 for(auto&& data : properties)
2039 if(data.first == Toolkit::Control::Property::BACKGROUND)
2041 DoAction(Toolkit::Control::Property::BACKGROUND, DevelVisual::Action::UPDATE_PROPERTY, data.second);
2043 else if(data.first == Toolkit::DevelControl::Property::SHADOW)
2045 DoAction(Toolkit::DevelControl::Property::SHADOW, DevelVisual::Action::UPDATE_PROPERTY, data.second);
2048 mControlImpl.OnUpdateVisualProperties(properties);
2051 void Control::Impl::EmitResourceReadySignal()
2053 if(!mIsEmittingResourceReadySignal)
2055 // Guard against calls to emit the signal during the callback
2056 mIsEmittingResourceReadySignal = true;
2058 // If the signal handler changes visual, it may become ready during this call & therefore this method will
2059 // get called again recursively. If so, mNeedToEmitResourceReady is set below, and we act on it after that secondary
2060 // invocation has completed by notifying in an Idle callback to prevent further recursion.
2061 Dali::Toolkit::Control handle(mControlImpl.GetOwner());
2062 mResourceReadySignal.Emit(handle);
2064 if(mNeedToEmitResourceReady)
2066 // Add idler to emit the signal again
2069 // The callback manager takes the ownership of the callback object.
2070 mIdleCallback = MakeCallback(this, &Control::Impl::OnIdleCallback);
2071 Adaptor::Get().AddIdle(mIdleCallback, false);
2075 mIsEmittingResourceReadySignal = false;
2079 mNeedToEmitResourceReady = true;
2083 void Control::Impl::OnIdleCallback()
2085 if(mNeedToEmitResourceReady)
2088 mNeedToEmitResourceReady = false;
2090 // A visual is ready so control may need relayouting if staged
2091 if(mControlImpl.Self().GetProperty<bool>(Actor::Property::CONNECTED_TO_SCENE))
2093 mControlImpl.RelayoutRequest();
2096 EmitResourceReadySignal();
2099 // Set the pointer to null as the callback manager deletes the callback after execute it.
2100 mIdleCallback = nullptr;
2103 Toolkit::DevelControl::ControlAccessible* Control::Impl::GetAccessibleObject()
2105 if(!mAccessibleObject)
2107 mAccessibleObject.reset(mControlImpl.CreateAccessibleObject());
2110 return mAccessibleObject.get();
2113 } // namespace Internal
2115 } // namespace Toolkit