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);
488 const PropertyRegistration Control::Impl::PROPERTY_26(typeRegistration, "automationId", Toolkit::DevelControl::Property::AUTOMATION_ID, Property::STRING, &Control::Impl::SetProperty, &Control::Impl::GetProperty);
492 Control::Impl::Impl(Control& controlImpl)
493 : mControlImpl(controlImpl),
494 mState(Toolkit::DevelControl::NORMAL),
496 mLeftFocusableActorId(-1),
497 mRightFocusableActorId(-1),
498 mUpFocusableActorId(-1),
499 mDownFocusableActorId(-1),
500 mClockwiseFocusableActorId(-1),
501 mCounterClockwiseFocusableActorId(-1),
503 mBackgroundColor(Color::TRANSPARENT),
504 mStartingPinchScale(nullptr),
506 mPadding(0, 0, 0, 0),
508 mKeyInputFocusGainedSignal(),
509 mKeyInputFocusLostSignal(),
510 mResourceReadySignal(),
511 mVisualEventSignal(),
512 mAccessibilityGetNameSignal(),
513 mAccessibilityGetDescriptionSignal(),
514 mAccessibilityDoGestureSignal(),
515 mPinchGestureDetector(),
516 mPanGestureDetector(),
517 mTapGestureDetector(),
518 mLongPressGestureDetector(),
520 mInputMethodContext(),
521 mIdleCallback(nullptr),
522 mFlags(Control::ControlBehaviour(CONTROL_BEHAVIOUR_DEFAULT)),
523 mIsKeyboardNavigationSupported(false),
524 mIsKeyboardFocusGroup(false),
525 mIsEmittingResourceReadySignal(false),
526 mNeedToEmitResourceReady(false),
527 mDispatchKeyEvents(true)
529 Dali::Accessibility::Accessible::RegisterExternalAccessibleGetter(&ExternalAccessibleGetter);
532 Control::Impl::~Impl()
534 for(auto&& iter : mVisuals)
536 StopObservingVisual(iter->visual);
539 for(auto&& iter : mRemoveVisuals)
541 StopObservingVisual(iter->visual);
544 // All gesture detectors will be destroyed so no need to disconnect.
545 delete mStartingPinchScale;
547 if(mIdleCallback && Adaptor::IsAvailable())
549 // Removes the callback from the callback manager in case the control is destroyed before the callback is executed.
550 Adaptor::Get().RemoveIdle(mIdleCallback);
554 Control::Impl& Control::Impl::Get(Internal::Control& internalControl)
556 return *internalControl.mImpl;
559 const Control::Impl& Control::Impl::Get(const Internal::Control& internalControl)
561 return *internalControl.mImpl;
564 void Control::Impl::CheckHighlightedObjectGeometry()
566 auto accessible = GetAccessibleObject();
567 auto lastPosition = accessible->GetLastPosition();
568 auto accessibleRect = accessible->GetExtents(Dali::Accessibility::CoordinateType::WINDOW);
569 auto rect = GetShowingGeometry(accessibleRect, accessible);
571 switch(mAccessibilityLastScreenRelativeMoveType)
573 case Dali::Accessibility::ScreenRelativeMoveType::OUTSIDE:
575 if(IsShowingGeometryOnScreen(rect))
577 mAccessibilityLastScreenRelativeMoveType = Dali::Accessibility::ScreenRelativeMoveType::INSIDE;
581 case Dali::Accessibility::ScreenRelativeMoveType::INSIDE:
583 if(rect.width < 0 && accessibleRect.x != lastPosition.x)
585 mAccessibilityLastScreenRelativeMoveType = (accessibleRect.x < lastPosition.x) ? Dali::Accessibility::ScreenRelativeMoveType::OUTGOING_TOP_LEFT : Dali::Accessibility::ScreenRelativeMoveType::OUTGOING_BOTTOM_RIGHT;
587 if(rect.height < 0 && accessibleRect.y != lastPosition.y)
589 mAccessibilityLastScreenRelativeMoveType = (accessibleRect.y < lastPosition.y) ? Dali::Accessibility::ScreenRelativeMoveType::OUTGOING_TOP_LEFT : Dali::Accessibility::ScreenRelativeMoveType::OUTGOING_BOTTOM_RIGHT;
591 // notify AT-clients on outgoing moves only
592 if(mAccessibilityLastScreenRelativeMoveType != Dali::Accessibility::ScreenRelativeMoveType::INSIDE)
594 accessible->EmitMovedOutOfScreen(mAccessibilityLastScreenRelativeMoveType);
598 case Dali::Accessibility::ScreenRelativeMoveType::OUTGOING_TOP_LEFT:
599 case Dali::Accessibility::ScreenRelativeMoveType::OUTGOING_BOTTOM_RIGHT:
601 if(IsShowingGeometryOnScreen(rect))
603 mAccessibilityLastScreenRelativeMoveType = Dali::Accessibility::ScreenRelativeMoveType::INSIDE;
607 mAccessibilityLastScreenRelativeMoveType = Dali::Accessibility::ScreenRelativeMoveType::OUTSIDE;
617 accessible->SetLastPosition(Vector2(accessibleRect.x, accessibleRect.y));
620 void Control::Impl::RegisterAccessibilityPositionPropertyNotification()
622 if(mIsAccessibilityPositionPropertyNotificationSet)
626 // set default value until first move of object is detected
627 mAccessibilityLastScreenRelativeMoveType = Dali::Accessibility::ScreenRelativeMoveType::OUTSIDE;
628 // recalculate mAccessibilityLastScreenRelativeMoveType accordingly to the initial position
629 CheckHighlightedObjectGeometry();
630 mAccessibilityPositionNotification = mControlImpl.Self().AddPropertyNotification(Actor::Property::WORLD_POSITION, StepCondition(1.0f, 1.0f));
631 mAccessibilityPositionNotification.SetNotifyMode(PropertyNotification::NOTIFY_ON_CHANGED);
632 mAccessibilityPositionNotification.NotifySignal().Connect(this, [this](PropertyNotification&) { CheckHighlightedObjectGeometry(); });
633 mIsAccessibilityPositionPropertyNotificationSet = true;
636 void Control::Impl::UnregisterAccessibilityPositionPropertyNotification()
638 mControlImpl.Self().RemovePropertyNotification(mAccessibilityPositionNotification);
639 mIsAccessibilityPositionPropertyNotificationSet = false;
642 // Gesture Detection Methods
643 void Control::Impl::PinchDetected(Actor actor, const PinchGesture& pinch)
645 mControlImpl.OnPinch(pinch);
648 void Control::Impl::PanDetected(Actor actor, const PanGesture& pan)
650 mControlImpl.OnPan(pan);
653 void Control::Impl::TapDetected(Actor actor, const TapGesture& tap)
655 mControlImpl.OnTap(tap);
658 void Control::Impl::LongPressDetected(Actor actor, const LongPressGesture& longPress)
660 mControlImpl.OnLongPress(longPress);
663 void Control::Impl::RegisterVisual(Property::Index index, Toolkit::Visual::Base& visual)
665 RegisterVisual(index, visual, VisualState::ENABLED, DepthIndexValue::NOT_SET);
668 void Control::Impl::RegisterVisual(Property::Index index, Toolkit::Visual::Base& visual, int depthIndex)
670 RegisterVisual(index, visual, VisualState::ENABLED, DepthIndexValue::SET, depthIndex);
673 void Control::Impl::RegisterVisual(Property::Index index, Toolkit::Visual::Base& visual, bool enabled)
675 RegisterVisual(index, visual, (enabled ? VisualState::ENABLED : VisualState::DISABLED), DepthIndexValue::NOT_SET);
678 void Control::Impl::RegisterVisual(Property::Index index, Toolkit::Visual::Base& visual, bool enabled, int depthIndex)
680 RegisterVisual(index, visual, (enabled ? VisualState::ENABLED : VisualState::DISABLED), DepthIndexValue::SET, depthIndex);
683 void Control::Impl::RegisterVisual(Property::Index index, Toolkit::Visual::Base& visual, VisualState::Type enabled, DepthIndexValue::Type depthIndexValueSet, int depthIndex)
685 DALI_LOG_INFO(gLogFilter, Debug::Concise, "RegisterVisual:%d \n", index);
687 bool visualReplaced(false);
688 Actor self = mControlImpl.Self();
690 // Set the depth index, if not set by caller this will be either the current visual depth, max depth of all visuals
692 int requiredDepthIndex = visual.GetDepthIndex();
694 if(depthIndexValueSet == DepthIndexValue::SET)
696 requiredDepthIndex = depthIndex;
699 // Visual replacement, existing visual should only be removed from stage when replacement ready.
700 if(!mVisuals.Empty())
702 RegisteredVisualContainer::Iterator registeredVisualsiter;
703 // Check if visual (index) is already registered, this is the current visual.
704 if(FindVisual(index, mVisuals, registeredVisualsiter))
706 Toolkit::Visual::Base& currentRegisteredVisual = (*registeredVisualsiter)->visual;
707 if(currentRegisteredVisual)
709 // Store current visual depth index as may need to set the replacement visual to same depth
710 const int currentDepthIndex = (*registeredVisualsiter)->visual.GetDepthIndex();
712 // No longer required to know if the replaced visual's resources are ready
713 StopObservingVisual(currentRegisteredVisual);
715 // If control staged and visual enabled then visuals will be swapped once ready
716 if(self.GetProperty<bool>(Actor::Property::CONNECTED_TO_SCENE) && enabled)
718 // Check if visual is currently in the process of being replaced ( is in removal container )
719 RegisteredVisualContainer::Iterator visualQueuedForRemoval;
720 if(FindVisual(index, mRemoveVisuals, visualQueuedForRemoval))
722 // Visual with same index is already in removal container so current visual pending
723 // Only the the last requested visual will be displayed so remove current visual which is staged but not ready.
724 Toolkit::GetImplementation(currentRegisteredVisual).SetOffScene(self);
725 mVisuals.Erase(registeredVisualsiter);
729 // current visual not already in removal container so add now.
730 DALI_LOG_INFO(gLogFilter, Debug::Verbose, "RegisterVisual Move current registered visual to removal Queue: %d \n", index);
731 MoveVisual(registeredVisualsiter, mVisuals, mRemoveVisuals);
736 // Control not staged or visual disabled so can just erase from registered visuals and new visual will be added later.
737 mVisuals.Erase(registeredVisualsiter);
740 // 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
741 if((depthIndexValueSet == DepthIndexValue::NOT_SET) &&
742 (visual.GetDepthIndex() == 0))
744 requiredDepthIndex = currentDepthIndex;
748 visualReplaced = true;
752 // If not set, set the name of the visual to the same name as the control's property.
753 // ( If the control has been type registered )
754 if(visual.GetName().empty())
756 // returns empty string if index is not found as long as index is not -1
757 std::string visualName = self.GetPropertyName(index);
758 if(!visualName.empty())
760 DALI_LOG_INFO(gLogFilter, Debug::Concise, "Setting visual name for property %d to %s\n", index, visualName.c_str());
761 visual.SetName(visualName);
765 if(!visualReplaced) // New registration entry
767 // 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
768 if((depthIndexValueSet == DepthIndexValue::NOT_SET) &&
769 (mVisuals.Size() > 0) &&
770 (visual.GetDepthIndex() == 0))
772 int maxDepthIndex = std::numeric_limits<int>::min();
774 RegisteredVisualContainer::ConstIterator iter;
775 const RegisteredVisualContainer::ConstIterator endIter = mVisuals.End();
776 for(iter = mVisuals.Begin(); iter != endIter; iter++)
778 const int visualDepthIndex = (*iter)->visual.GetDepthIndex();
779 if(visualDepthIndex > maxDepthIndex)
781 maxDepthIndex = visualDepthIndex;
784 ++maxDepthIndex; // Add one to the current maximum depth index so that our added visual appears on top
785 requiredDepthIndex = std::max(0, maxDepthIndex); // Start at zero if maxDepth index belongs to a background
791 // Set determined depth index
792 visual.SetDepthIndex(requiredDepthIndex);
794 // Monitor when the visual resources are ready
795 StartObservingVisual(visual);
797 DALI_LOG_INFO(gLogFilter, Debug::Concise, "New Visual registration index[%d] depth[%d]\n", index, requiredDepthIndex);
798 RegisteredVisual* newRegisteredVisual = new RegisteredVisual(index, visual, (enabled == VisualState::ENABLED ? true : false), (visualReplaced && enabled));
799 mVisuals.PushBack(newRegisteredVisual);
801 Internal::Visual::Base& visualImpl = Toolkit::GetImplementation(visual);
802 // Put on stage if enabled and the control is already on the stage
803 if((enabled == VisualState::ENABLED) && self.GetProperty<bool>(Actor::Property::CONNECTED_TO_SCENE))
805 visualImpl.SetOnScene(self);
807 else if(visualImpl.IsResourceReady()) // When not being staged, check if visual already 'ResourceReady' before it was Registered. ( Resource may have been loaded already )
809 ResourceReady(visualImpl);
813 DALI_LOG_INFO(gLogFilter, Debug::Verbose, "Control::RegisterVisual() Registered %s(%d), enabled:%s\n", visual.GetName().c_str(), index, enabled ? "true" : "false");
816 void Control::Impl::UnregisterVisual(Property::Index index)
818 RegisteredVisualContainer::Iterator iter;
819 if(FindVisual(index, mVisuals, iter))
821 // stop observing visual
822 StopObservingVisual((*iter)->visual);
824 Actor self(mControlImpl.Self());
825 Toolkit::GetImplementation((*iter)->visual).SetOffScene(self);
826 (*iter)->visual.Reset();
827 mVisuals.Erase(iter);
830 if(FindVisual(index, mRemoveVisuals, iter))
832 Actor self(mControlImpl.Self());
833 Toolkit::GetImplementation((*iter)->visual).SetOffScene(self);
834 (*iter)->pending = false;
835 (*iter)->visual.Reset();
836 mRemoveVisuals.Erase(iter);
840 Toolkit::Visual::Base Control::Impl::GetVisual(Property::Index index) const
842 RegisteredVisualContainer::Iterator iter;
843 if(FindVisual(index, mVisuals, iter))
845 return (*iter)->visual;
848 return Toolkit::Visual::Base();
851 void Control::Impl::EnableVisual(Property::Index index, bool enable)
853 DALI_LOG_INFO(gLogFilter, Debug::General, "Control::EnableVisual(%d, %s)\n", index, enable ? "T" : "F");
855 RegisteredVisualContainer::Iterator iter;
856 if(FindVisual(index, mVisuals, iter))
858 if((*iter)->enabled == enable)
860 DALI_LOG_INFO(gLogFilter, Debug::Verbose, "Control::EnableVisual Visual %s(%d) already %s\n", (*iter)->visual.GetName().c_str(), index, enable ? "enabled" : "disabled");
864 (*iter)->enabled = enable;
865 Actor parentActor = mControlImpl.Self();
866 if(mControlImpl.Self().GetProperty<bool>(Actor::Property::CONNECTED_TO_SCENE)) // If control not on Scene then Visual will be added when SceneConnection is called.
870 DALI_LOG_INFO(gLogFilter, Debug::Verbose, "Control::EnableVisual Setting %s(%d) on stage \n", (*iter)->visual.GetName().c_str(), index);
871 Toolkit::GetImplementation((*iter)->visual).SetOnScene(parentActor);
875 DALI_LOG_INFO(gLogFilter, Debug::Verbose, "Control::EnableVisual Setting %s(%d) off stage \n", (*iter)->visual.GetName().c_str(), index);
876 Toolkit::GetImplementation((*iter)->visual).SetOffScene(parentActor); // No need to call if control not staged.
882 DALI_LOG_WARNING("Control::EnableVisual(%d, %s) FAILED - NO SUCH VISUAL\n", index, enable ? "T" : "F");
886 bool Control::Impl::IsVisualEnabled(Property::Index index) const
888 RegisteredVisualContainer::Iterator iter;
889 if(FindVisual(index, mVisuals, iter))
891 return (*iter)->enabled;
896 void Control::Impl::StopObservingVisual(Toolkit::Visual::Base& visual)
898 Internal::Visual::Base& visualImpl = Toolkit::GetImplementation(visual);
900 // Stop observing the visual
901 visualImpl.RemoveEventObserver(*this);
904 void Control::Impl::StartObservingVisual(Toolkit::Visual::Base& visual)
906 Internal::Visual::Base& visualImpl = Toolkit::GetImplementation(visual);
908 // start observing the visual for events
909 visualImpl.AddEventObserver(*this);
912 void Control::Impl::ResourceReady(bool relayoutRequest)
914 Actor self = mControlImpl.Self();
915 // A visual is ready so control may need relayouting if staged
916 if(relayoutRequest && self.GetProperty<bool>(Actor::Property::CONNECTED_TO_SCENE))
918 mControlImpl.RelayoutRequest();
921 // Emit signal if all enabled visuals registered by the control are ready or there are no visuals.
922 if(IsResourceReady())
925 mNeedToEmitResourceReady = false;
926 EmitResourceReadySignal();
930 // Called by a Visual when it's resource is ready
931 void Control::Impl::ResourceReady(Visual::Base& object)
933 DALI_LOG_INFO(gLogFilter, Debug::Verbose, "Control::Impl::ResourceReady() replacements pending[%d]\n", mRemoveVisuals.Count());
935 Actor self = mControlImpl.Self();
937 // A resource is ready, find resource in the registered visuals container and get its index
938 for(auto registeredIter = mVisuals.Begin(), end = mVisuals.End(); registeredIter != end; ++registeredIter)
940 Internal::Visual::Base& registeredVisualImpl = Toolkit::GetImplementation((*registeredIter)->visual);
942 if(&object == ®isteredVisualImpl)
944 RegisteredVisualContainer::Iterator visualToRemoveIter;
945 // Find visual with the same index in the removal container
946 // Set if off stage as it's replacement is now ready.
947 // Remove if from removal list as now removed from stage.
948 // Set Pending flag on the ready visual to false as now ready.
949 if(FindVisual((*registeredIter)->index, mRemoveVisuals, visualToRemoveIter))
951 (*registeredIter)->pending = false;
952 Toolkit::GetImplementation((*visualToRemoveIter)->visual).SetOffScene(self);
953 mRemoveVisuals.Erase(visualToRemoveIter);
959 // Called by a Visual when it's resource is ready
963 void Control::Impl::NotifyVisualEvent(Visual::Base& object, Property::Index signalId)
965 for(auto registeredIter = mVisuals.Begin(), end = mVisuals.End(); registeredIter != end; ++registeredIter)
967 Internal::Visual::Base& registeredVisualImpl = Toolkit::GetImplementation((*registeredIter)->visual);
968 if(&object == ®isteredVisualImpl)
970 Dali::Toolkit::Control handle(mControlImpl.GetOwner());
971 mVisualEventSignal.Emit(handle, (*registeredIter)->index, signalId);
977 void Control::Impl::RelayoutRequest(Visual::Base& object)
979 mControlImpl.RelayoutRequest();
982 bool Control::Impl::IsResourceReady() const
984 // Iterate through and check all the enabled visuals are ready
985 for(auto visualIter = mVisuals.Begin();
986 visualIter != mVisuals.End();
989 const Toolkit::Visual::Base visual = (*visualIter)->visual;
990 const Internal::Visual::Base& visualImpl = Toolkit::GetImplementation(visual);
992 // one of the enabled visuals is not ready
993 if(!visualImpl.IsResourceReady() && (*visualIter)->enabled)
1001 Toolkit::Visual::ResourceStatus Control::Impl::GetVisualResourceStatus(Property::Index index) const
1003 RegisteredVisualContainer::Iterator iter;
1004 if(FindVisual(index, mVisuals, iter))
1006 const Toolkit::Visual::Base visual = (*iter)->visual;
1007 const Internal::Visual::Base& visualImpl = Toolkit::GetImplementation(visual);
1008 return visualImpl.GetResourceStatus();
1011 return Toolkit::Visual::ResourceStatus::PREPARING;
1014 void Control::Impl::AddTransitions(Dali::Animation& animation,
1015 const Toolkit::TransitionData& handle,
1016 bool createAnimation)
1018 // Setup a Transition from TransitionData.
1019 const Internal::TransitionData& transitionData = Toolkit::GetImplementation(handle);
1020 TransitionData::Iterator end = transitionData.End();
1021 for(TransitionData::Iterator iter = transitionData.Begin();
1025 TransitionData::Animator* animator = (*iter);
1027 Toolkit::Visual::Base visual = GetVisualByName(mVisuals, animator->objectName);
1031 #if defined(DEBUG_ENABLED)
1032 Dali::TypeInfo typeInfo;
1033 ControlWrapper* controlWrapperImpl = dynamic_cast<ControlWrapper*>(&mControlImpl);
1034 if(controlWrapperImpl)
1036 typeInfo = controlWrapperImpl->GetTypeInfo();
1039 DALI_LOG_INFO(gLogFilter, Debug::Concise, "CreateTransition: Found %s visual for %s\n", visual.GetName().c_str(), typeInfo ? typeInfo.GetName().c_str() : "Unknown");
1041 Internal::Visual::Base& visualImpl = Toolkit::GetImplementation(visual);
1042 visualImpl.AnimateProperty(animation, *animator);
1046 DALI_LOG_INFO(gLogFilter, Debug::Concise, "CreateTransition: Could not find visual. Trying actors");
1047 // Otherwise, try any actor children of control (Including the control)
1048 Actor child = mControlImpl.Self().FindChildByName(animator->objectName);
1051 Property::Index propertyIndex = child.GetPropertyIndex(animator->propertyKey);
1052 if(propertyIndex != Property::INVALID_INDEX)
1054 if(animator->animate == false)
1056 if(animator->targetValue.GetType() != Property::NONE)
1058 child.SetProperty(propertyIndex, animator->targetValue);
1061 else // animate the property
1063 if(animator->initialValue.GetType() != Property::NONE)
1065 child.SetProperty(propertyIndex, animator->initialValue);
1068 if(createAnimation && !animation)
1070 animation = Dali::Animation::New(0.1f);
1073 animation.AnimateTo(Property(child, propertyIndex),
1074 animator->targetValue,
1075 animator->alphaFunction,
1076 TimePeriod(animator->timePeriodDelay,
1077 animator->timePeriodDuration));
1085 Dali::Animation Control::Impl::CreateTransition(const Toolkit::TransitionData& transitionData)
1087 Dali::Animation transition;
1089 if(transitionData.Count() > 0)
1091 AddTransitions(transition, transitionData, true);
1096 void Control::Impl::DoAction(Dali::Property::Index visualIndex, Dali::Property::Index actionId, const Dali::Property::Value attributes)
1098 RegisteredVisualContainer::Iterator iter;
1099 if(FindVisual(visualIndex, mVisuals, iter))
1101 Toolkit::GetImplementation((*iter)->visual).DoAction(actionId, attributes);
1105 void Control::Impl::DoActionExtension(Dali::Property::Index visualIndex, Dali::Property::Index actionId, Dali::Any attributes)
1107 RegisteredVisualContainer::Iterator iter;
1108 if(FindVisual(visualIndex, mVisuals, iter))
1110 Toolkit::GetImplementation((*iter)->visual).DoActionExtension(actionId, attributes);
1114 void Control::Impl::AppendAccessibilityAttribute(const std::string& key, const std::string value)
1116 Property::Value* checkedValue = mAccessibilityAttributes.Find(key);
1119 mAccessibilityAttributes[key] = Property::Value(value);
1123 mAccessibilityAttributes.Insert(key, value);
1127 void Control::Impl::SetProperty(BaseObject* object, Property::Index index, const Property::Value& value)
1129 Toolkit::Control control = Toolkit::Control::DownCast(BaseHandle(object));
1133 Control& controlImpl(GetImplementation(control));
1137 case Toolkit::Control::Property::STYLE_NAME:
1139 controlImpl.SetStyleName(value.Get<std::string>());
1143 case Toolkit::DevelControl::Property::STATE:
1145 bool withTransitions = true;
1146 const Property::Value* valuePtr = &value;
1147 const Property::Map* map = value.GetMap();
1150 Property::Value* value2 = map->Find("withTransitions");
1153 withTransitions = value2->Get<bool>();
1156 valuePtr = map->Find("state");
1161 Toolkit::DevelControl::State state(controlImpl.mImpl->mState);
1162 if(Scripting::GetEnumerationProperty<Toolkit::DevelControl::State>(*valuePtr, ControlStateTable, ControlStateTableCount, state))
1164 controlImpl.mImpl->SetState(state, withTransitions);
1170 case Toolkit::DevelControl::Property::SUB_STATE:
1172 std::string subState;
1173 if(value.Get(subState))
1175 controlImpl.mImpl->SetSubState(subState);
1180 case Toolkit::DevelControl::Property::LEFT_FOCUSABLE_ACTOR_ID:
1183 if(value.Get(focusId))
1185 controlImpl.mImpl->mLeftFocusableActorId = focusId;
1190 case Toolkit::DevelControl::Property::RIGHT_FOCUSABLE_ACTOR_ID:
1193 if(value.Get(focusId))
1195 controlImpl.mImpl->mRightFocusableActorId = focusId;
1200 case Toolkit::DevelControl::Property::UP_FOCUSABLE_ACTOR_ID:
1203 if(value.Get(focusId))
1205 controlImpl.mImpl->mUpFocusableActorId = focusId;
1210 case Toolkit::DevelControl::Property::DOWN_FOCUSABLE_ACTOR_ID:
1213 if(value.Get(focusId))
1215 controlImpl.mImpl->mDownFocusableActorId = focusId;
1220 case Toolkit::Control::Property::KEY_INPUT_FOCUS:
1222 if(value.Get<bool>())
1224 controlImpl.SetKeyInputFocus();
1228 controlImpl.ClearKeyInputFocus();
1233 case Toolkit::Control::Property::BACKGROUND:
1237 const Property::Map* map = value.GetMap();
1238 if(map && !map->Empty())
1240 controlImpl.SetBackground(*map);
1242 else if(value.Get(url))
1244 // don't know the size to load
1245 Toolkit::Visual::Base visual = Toolkit::VisualFactory::Get().CreateVisual(url, ImageDimensions());
1248 controlImpl.mImpl->RegisterVisual(Toolkit::Control::Property::BACKGROUND, visual, DepthIndex::BACKGROUND);
1251 else if(value.Get(color))
1253 controlImpl.SetBackgroundColor(color);
1257 // The background is an empty property map, so we should clear the background
1258 controlImpl.ClearBackground();
1263 case Toolkit::Control::Property::MARGIN:
1266 if(value.Get(margin))
1268 controlImpl.mImpl->SetMargin(margin);
1273 case Toolkit::Control::Property::PADDING:
1276 if(value.Get(padding))
1278 controlImpl.mImpl->SetPadding(padding);
1283 case Toolkit::DevelControl::Property::TOOLTIP:
1285 TooltipPtr& tooltipPtr = controlImpl.mImpl->mTooltip;
1288 tooltipPtr = Tooltip::New(control);
1290 tooltipPtr->SetProperties(value);
1294 case Toolkit::DevelControl::Property::SHADOW:
1296 const Property::Map* map = value.GetMap();
1297 if(map && !map->Empty())
1299 controlImpl.mImpl->SetShadow(*map);
1303 // The shadow is an empty property map, so we should clear the shadow
1304 controlImpl.mImpl->ClearShadow();
1309 case Toolkit::DevelControl::Property::ACCESSIBILITY_NAME:
1314 controlImpl.mImpl->mAccessibilityName = name;
1319 case Toolkit::DevelControl::Property::ACCESSIBILITY_DESCRIPTION:
1324 controlImpl.mImpl->mAccessibilityDescription = text;
1329 case Toolkit::DevelControl::Property::ACCESSIBILITY_TRANSLATION_DOMAIN:
1334 controlImpl.mImpl->mAccessibilityTranslationDomain = text;
1339 case Toolkit::DevelControl::Property::ACCESSIBILITY_ROLE:
1341 Dali::Accessibility::Role role;
1344 controlImpl.mImpl->mAccessibilityRole = role;
1349 case Toolkit::DevelControl::Property::ACCESSIBILITY_HIGHLIGHTABLE:
1352 if(value.Get(highlightable))
1354 controlImpl.mImpl->mAccessibilityHighlightable = highlightable;
1359 case Toolkit::DevelControl::Property::ACCESSIBILITY_ATTRIBUTES:
1361 const Property::Map* map = value.GetMap();
1362 if(map && !map->Empty())
1364 controlImpl.mImpl->mAccessibilityAttributes = *map;
1369 case Toolkit::DevelControl::Property::DISPATCH_KEY_EVENTS:
1372 if(value.Get(dispatch))
1374 controlImpl.mImpl->mDispatchKeyEvents = dispatch;
1379 case Toolkit::DevelControl::Property::ACCESSIBILITY_HIDDEN:
1382 if(value.Get(hidden))
1384 controlImpl.mImpl->mAccessibilityHidden = hidden;
1386 auto* accessible = controlImpl.GetAccessibleObject();
1387 auto* parent = dynamic_cast<Dali::Accessibility::ActorAccessible*>(accessible->GetParent());
1390 parent->OnChildrenChanged();
1395 case Toolkit::DevelControl::Property::CLOCKWISE_FOCUSABLE_ACTOR_ID:
1398 if(value.Get(focusId))
1400 controlImpl.mImpl->mClockwiseFocusableActorId = focusId;
1404 case Toolkit::DevelControl::Property::COUNTER_CLOCKWISE_FOCUSABLE_ACTOR_ID:
1407 if(value.Get(focusId))
1409 controlImpl.mImpl->mCounterClockwiseFocusableActorId = focusId;
1414 case Toolkit::DevelControl::Property::AUTOMATION_ID:
1416 std::string automationId;
1417 if(value.Get(automationId))
1419 controlImpl.mImpl->mAutomationId = automationId;
1427 Property::Value Control::Impl::GetProperty(BaseObject* object, Property::Index index)
1429 Property::Value value;
1431 Toolkit::Control control = Toolkit::Control::DownCast(BaseHandle(object));
1435 Control& controlImpl(GetImplementation(control));
1439 case Toolkit::Control::Property::STYLE_NAME:
1441 value = controlImpl.GetStyleName();
1445 case Toolkit::DevelControl::Property::STATE:
1447 value = controlImpl.mImpl->mState;
1451 case Toolkit::DevelControl::Property::SUB_STATE:
1453 value = controlImpl.mImpl->mSubStateName;
1457 case Toolkit::DevelControl::Property::LEFT_FOCUSABLE_ACTOR_ID:
1459 value = controlImpl.mImpl->mLeftFocusableActorId;
1463 case Toolkit::DevelControl::Property::RIGHT_FOCUSABLE_ACTOR_ID:
1465 value = controlImpl.mImpl->mRightFocusableActorId;
1469 case Toolkit::DevelControl::Property::UP_FOCUSABLE_ACTOR_ID:
1471 value = controlImpl.mImpl->mUpFocusableActorId;
1475 case Toolkit::DevelControl::Property::DOWN_FOCUSABLE_ACTOR_ID:
1477 value = controlImpl.mImpl->mDownFocusableActorId;
1481 case Toolkit::Control::Property::KEY_INPUT_FOCUS:
1483 value = controlImpl.HasKeyInputFocus();
1487 case Toolkit::Control::Property::BACKGROUND:
1490 Toolkit::Visual::Base visual = controlImpl.mImpl->GetVisual(Toolkit::Control::Property::BACKGROUND);
1493 visual.CreatePropertyMap(map);
1500 case Toolkit::Control::Property::MARGIN:
1502 value = controlImpl.mImpl->GetMargin();
1506 case Toolkit::Control::Property::PADDING:
1508 value = controlImpl.mImpl->GetPadding();
1512 case Toolkit::DevelControl::Property::TOOLTIP:
1515 if(controlImpl.mImpl->mTooltip)
1517 controlImpl.mImpl->mTooltip->CreatePropertyMap(map);
1523 case Toolkit::DevelControl::Property::SHADOW:
1526 Toolkit::Visual::Base visual = controlImpl.mImpl->GetVisual(Toolkit::DevelControl::Property::SHADOW);
1529 visual.CreatePropertyMap(map);
1536 case Toolkit::DevelControl::Property::ACCESSIBILITY_NAME:
1538 value = controlImpl.mImpl->mAccessibilityName;
1542 case Toolkit::DevelControl::Property::ACCESSIBILITY_DESCRIPTION:
1544 value = controlImpl.mImpl->mAccessibilityDescription;
1548 case Toolkit::DevelControl::Property::ACCESSIBILITY_TRANSLATION_DOMAIN:
1550 value = controlImpl.mImpl->mAccessibilityTranslationDomain;
1554 case Toolkit::DevelControl::Property::ACCESSIBILITY_ROLE:
1556 value = Property::Value(controlImpl.mImpl->mAccessibilityRole);
1560 case Toolkit::DevelControl::Property::ACCESSIBILITY_HIGHLIGHTABLE:
1562 value = controlImpl.mImpl->mAccessibilityHighlightable;
1566 case Toolkit::DevelControl::Property::ACCESSIBILITY_ATTRIBUTES:
1568 value = controlImpl.mImpl->mAccessibilityAttributes;
1572 case Toolkit::DevelControl::Property::DISPATCH_KEY_EVENTS:
1574 value = controlImpl.mImpl->mDispatchKeyEvents;
1578 case Toolkit::DevelControl::Property::ACCESSIBILITY_HIDDEN:
1580 value = controlImpl.mImpl->mAccessibilityHidden;
1584 case Toolkit::DevelControl::Property::CLOCKWISE_FOCUSABLE_ACTOR_ID:
1586 value = controlImpl.mImpl->mClockwiseFocusableActorId;
1590 case Toolkit::DevelControl::Property::COUNTER_CLOCKWISE_FOCUSABLE_ACTOR_ID:
1592 value = controlImpl.mImpl->mCounterClockwiseFocusableActorId;
1596 case Toolkit::DevelControl::Property::AUTOMATION_ID:
1598 value = controlImpl.mImpl->mAutomationId;
1607 void Control::Impl::RemoveAccessibilityAttribute(const std::string& key)
1609 Property::Value* value = mAccessibilityAttributes.Find(key);
1612 mAccessibilityAttributes[key] = Property::Value();
1616 void Control::Impl::ClearAccessibilityAttributes()
1618 mAccessibilityAttributes.Clear();
1621 void Control::Impl::SetAccessibilityReadingInfoType(const Dali::Accessibility::ReadingInfoTypes types)
1623 std::string value{};
1624 if(types[Dali::Accessibility::ReadingInfoType::NAME])
1626 value += READING_INFO_TYPE_NAME;
1628 if(types[Dali::Accessibility::ReadingInfoType::ROLE])
1632 value += READING_INFO_TYPE_SEPARATOR;
1634 value += READING_INFO_TYPE_ROLE;
1636 if(types[Dali::Accessibility::ReadingInfoType::DESCRIPTION])
1640 value += READING_INFO_TYPE_SEPARATOR;
1642 value += READING_INFO_TYPE_DESCRIPTION;
1644 if(types[Dali::Accessibility::ReadingInfoType::STATE])
1648 value += READING_INFO_TYPE_SEPARATOR;
1650 value += READING_INFO_TYPE_STATE;
1652 AppendAccessibilityAttribute(READING_INFO_TYPE_ATTRIBUTE_NAME, value);
1655 Dali::Accessibility::ReadingInfoTypes Control::Impl::GetAccessibilityReadingInfoType() const
1657 std::string value{};
1658 auto place = mAccessibilityAttributes.Find(READING_INFO_TYPE_ATTRIBUTE_NAME);
1665 Dali::Accessibility::ReadingInfoTypes types;
1666 types[Dali::Accessibility::ReadingInfoType::NAME] = true;
1667 types[Dali::Accessibility::ReadingInfoType::ROLE] = true;
1668 types[Dali::Accessibility::ReadingInfoType::DESCRIPTION] = true;
1669 types[Dali::Accessibility::ReadingInfoType::STATE] = true;
1678 Dali::Accessibility::ReadingInfoTypes types;
1680 if(value.find(READING_INFO_TYPE_NAME) != std::string::npos)
1682 types[Dali::Accessibility::ReadingInfoType::NAME] = true;
1684 if(value.find(READING_INFO_TYPE_ROLE) != std::string::npos)
1686 types[Dali::Accessibility::ReadingInfoType::ROLE] = true;
1688 if(value.find(READING_INFO_TYPE_DESCRIPTION) != std::string::npos)
1690 types[Dali::Accessibility::ReadingInfoType::DESCRIPTION] = true;
1692 if(value.find(READING_INFO_TYPE_STATE) != std::string::npos)
1694 types[Dali::Accessibility::ReadingInfoType::STATE] = true;
1700 void Control::Impl::CopyInstancedProperties(RegisteredVisualContainer& visuals, Dictionary<Property::Map>& instancedProperties)
1702 for(RegisteredVisualContainer::Iterator iter = visuals.Begin(); iter != visuals.End(); iter++)
1706 Property::Map instanceMap;
1707 Toolkit::GetImplementation((*iter)->visual).CreateInstancePropertyMap(instanceMap);
1708 instancedProperties.Add((*iter)->visual.GetName(), instanceMap);
1713 void Control::Impl::RemoveVisual(RegisteredVisualContainer& visuals, const std::string& visualName)
1715 Actor self(mControlImpl.Self());
1717 for(RegisteredVisualContainer::Iterator visualIter = visuals.Begin();
1718 visualIter != visuals.End();
1721 Toolkit::Visual::Base visual = (*visualIter)->visual;
1722 if(visual && visual.GetName() == visualName)
1724 Toolkit::GetImplementation(visual).SetOffScene(self);
1725 (*visualIter)->visual.Reset();
1726 visuals.Erase(visualIter);
1732 void Control::Impl::RemoveVisuals(RegisteredVisualContainer& visuals, DictionaryKeys& removeVisuals)
1734 Actor self(mControlImpl.Self());
1735 for(DictionaryKeys::iterator iter = removeVisuals.begin(); iter != removeVisuals.end(); ++iter)
1737 const std::string visualName = *iter;
1738 RemoveVisual(visuals, visualName);
1742 void Control::Impl::RecreateChangedVisuals(Dictionary<Property::Map>& stateVisualsToChange,
1743 Dictionary<Property::Map>& instancedProperties)
1745 Dali::CustomActor handle(mControlImpl.GetOwner());
1746 for(Dictionary<Property::Map>::iterator iter = stateVisualsToChange.Begin();
1747 iter != stateVisualsToChange.End();
1750 const std::string& visualName = (*iter).key;
1751 const Property::Map& toMap = (*iter).entry;
1753 Actor self = mControlImpl.Self();
1754 RegisteredVisualContainer::Iterator registeredVisualsiter;
1755 // Check if visual (visualName) is already registered, this is the current visual.
1756 if(FindVisual(visualName, mVisuals, registeredVisualsiter))
1758 Toolkit::Visual::Base& visual = (*registeredVisualsiter)->visual;
1761 // No longer required to know if the replaced visual's resources are ready
1762 StopObservingVisual(visual);
1764 // If control staged then visuals will be swapped once ready
1765 if(self.GetProperty<bool>(Actor::Property::CONNECTED_TO_SCENE))
1767 // Check if visual is currently in the process of being replaced ( is in removal container )
1768 RegisteredVisualContainer::Iterator visualQueuedForRemoval;
1769 if(FindVisual(visualName, mRemoveVisuals, visualQueuedForRemoval))
1771 // Visual with same visual name is already in removal container so current visual pending
1772 // Only the the last requested visual will be displayed so remove current visual which is staged but not ready.
1773 Toolkit::GetImplementation(visual).SetOffScene(self);
1774 (*registeredVisualsiter)->visual.Reset();
1775 mVisuals.Erase(registeredVisualsiter);
1779 // current visual not already in removal container so add now.
1780 DALI_LOG_INFO(gLogFilter, Debug::Verbose, "RegisterVisual Move current registered visual to removal Queue: %s \n", visualName.c_str());
1781 MoveVisual(registeredVisualsiter, mVisuals, mRemoveVisuals);
1786 // Control not staged or visual disabled so can just erase from registered visuals and new visual will be added later.
1787 (*registeredVisualsiter)->visual.Reset();
1788 mVisuals.Erase(registeredVisualsiter);
1792 const Property::Map* instancedMap = instancedProperties.FindConst(visualName);
1793 Style::ApplyVisual(handle, visualName, toMap, instancedMap);
1798 void Control::Impl::ReplaceStateVisualsAndProperties(const StylePtr oldState, const StylePtr newState, const std::string& subState)
1800 // Collect all old visual names
1801 DictionaryKeys stateVisualsToRemove;
1804 oldState->visuals.GetKeys(stateVisualsToRemove);
1805 if(!subState.empty())
1807 const StylePtr* oldSubState = oldState->subStates.FindConst(subState);
1810 DictionaryKeys subStateVisualsToRemove;
1811 (*oldSubState)->visuals.GetKeys(subStateVisualsToRemove);
1812 Merge(stateVisualsToRemove, subStateVisualsToRemove);
1817 // Collect all new visual properties
1818 Dictionary<Property::Map> stateVisualsToAdd;
1821 stateVisualsToAdd = newState->visuals;
1822 if(!subState.empty())
1824 const StylePtr* newSubState = newState->subStates.FindConst(subState);
1827 stateVisualsToAdd.Merge((*newSubState)->visuals);
1832 // If a name is in both add/remove, move it to change list.
1833 Dictionary<Property::Map> stateVisualsToChange;
1834 FindChangableVisuals(stateVisualsToAdd, stateVisualsToChange, stateVisualsToRemove);
1836 // Copy instanced properties (e.g. text label) of current visuals
1837 Dictionary<Property::Map> instancedProperties;
1838 CopyInstancedProperties(mVisuals, instancedProperties);
1840 // For each visual in remove list, remove from mVisuals
1841 RemoveVisuals(mVisuals, stateVisualsToRemove);
1843 // For each visual in add list, create and add to mVisuals
1844 Dali::CustomActor handle(mControlImpl.GetOwner());
1845 Style::ApplyVisuals(handle, stateVisualsToAdd, instancedProperties);
1847 // For each visual in change list, if it requires a new visual,
1848 // remove old visual, create and add to mVisuals
1849 RecreateChangedVisuals(stateVisualsToChange, instancedProperties);
1852 void Control::Impl::SetState(DevelControl::State newState, bool withTransitions)
1854 DevelControl::State oldState = mState;
1855 Dali::CustomActor handle(mControlImpl.GetOwner());
1856 DALI_LOG_INFO(gLogFilter, Debug::Concise, "Control::Impl::SetState: %s\n", (mState == DevelControl::NORMAL ? "NORMAL" : (mState == DevelControl::FOCUSED ? "FOCUSED" : (mState == DevelControl::DISABLED ? "DISABLED" : "NONE"))));
1858 if(mState != newState)
1860 // If mState was Disabled, and new state is Focused, should probably
1861 // store that fact, e.g. in another property that FocusManager can access.
1864 // Trigger state change and transitions
1865 // Apply new style, if stylemanager is available
1866 Toolkit::StyleManager styleManager = Toolkit::StyleManager::Get();
1869 const StylePtr stylePtr = GetImpl(styleManager).GetRecordedStyle(Toolkit::Control(mControlImpl.GetOwner()));
1873 std::string oldStateName = Scripting::GetEnumerationName<Toolkit::DevelControl::State>(oldState, ControlStateTable, ControlStateTableCount);
1874 std::string newStateName = Scripting::GetEnumerationName<Toolkit::DevelControl::State>(newState, ControlStateTable, ControlStateTableCount);
1876 const StylePtr* newStateStyle = stylePtr->subStates.Find(newStateName);
1877 const StylePtr* oldStateStyle = stylePtr->subStates.Find(oldStateName);
1878 if(oldStateStyle && newStateStyle)
1880 // Only change if both state styles exist
1881 ReplaceStateVisualsAndProperties(*oldStateStyle, *newStateStyle, mSubStateName);
1888 void Control::Impl::SetSubState(const std::string& subStateName, bool withTransitions)
1890 if(mSubStateName != subStateName)
1892 // Get existing sub-state visuals, and unregister them
1893 Dali::CustomActor handle(mControlImpl.GetOwner());
1895 Toolkit::StyleManager styleManager = Toolkit::StyleManager::Get();
1898 const StylePtr stylePtr = GetImpl(styleManager).GetRecordedStyle(Toolkit::Control(mControlImpl.GetOwner()));
1902 std::string stateName = Scripting::GetEnumerationName<Toolkit::DevelControl::State>(mState, ControlStateTable, ControlStateTableCount);
1904 const StylePtr* state = stylePtr->subStates.Find(stateName);
1907 StylePtr stateStyle(*state);
1909 const StylePtr* newStateStyle = stateStyle->subStates.Find(subStateName);
1910 const StylePtr* oldStateStyle = stateStyle->subStates.Find(mSubStateName);
1911 if(oldStateStyle && newStateStyle)
1914 ReplaceStateVisualsAndProperties(*oldStateStyle, *newStateStyle, empty);
1920 mSubStateName = subStateName;
1924 void Control::Impl::OnSceneDisconnection()
1926 Actor self = mControlImpl.Self();
1928 // Any visuals set for replacement but not yet ready should still be registered.
1929 // Reason: If a request was made to register a new visual but the control removed from scene before visual was ready
1930 // then when this control appears back on stage it should use that new visual.
1932 // Iterate through all registered visuals and set off scene
1933 SetVisualsOffScene(mVisuals, self);
1935 // Visuals pending replacement can now be taken out of the removal list and set off scene
1936 // Iterate through all replacement visuals and add to a move queue then set off scene
1937 for(auto removalIter = mRemoveVisuals.Begin(), end = mRemoveVisuals.End(); removalIter != end; removalIter++)
1939 Toolkit::GetImplementation((*removalIter)->visual).SetOffScene(self);
1942 for(auto replacedIter = mVisuals.Begin(), end = mVisuals.End(); replacedIter != end; replacedIter++)
1944 (*replacedIter)->pending = false;
1947 mRemoveVisuals.Clear();
1950 void Control::Impl::SetMargin(Extents margin)
1952 mControlImpl.mImpl->mMargin = margin;
1954 // Trigger a size negotiation request that may be needed when setting a margin.
1955 mControlImpl.RelayoutRequest();
1958 Extents Control::Impl::GetMargin() const
1960 return mControlImpl.mImpl->mMargin;
1963 void Control::Impl::SetPadding(Extents padding)
1965 mControlImpl.mImpl->mPadding = padding;
1967 // Trigger a size negotiation request that may be needed when setting a padding.
1968 mControlImpl.RelayoutRequest();
1971 Extents Control::Impl::GetPadding() const
1973 return mControlImpl.mImpl->mPadding;
1976 void Control::Impl::SetInputMethodContext(InputMethodContext& inputMethodContext)
1978 mInputMethodContext = inputMethodContext;
1981 bool Control::Impl::FilterKeyEvent(const KeyEvent& event)
1983 bool consumed(false);
1985 if(mInputMethodContext)
1987 consumed = mInputMethodContext.FilterEventKey(event);
1992 DevelControl::VisualEventSignalType& Control::Impl::VisualEventSignal()
1994 return mVisualEventSignal;
1997 void Control::Impl::SetShadow(const Property::Map& map)
1999 Toolkit::Visual::Base visual = Toolkit::VisualFactory::Get().CreateVisual(map);
2000 visual.SetName("shadow");
2004 mControlImpl.mImpl->RegisterVisual(Toolkit::DevelControl::Property::SHADOW, visual, DepthIndex::BACKGROUND_EFFECT);
2006 mControlImpl.RelayoutRequest();
2010 void Control::Impl::ClearShadow()
2012 mControlImpl.mImpl->UnregisterVisual(Toolkit::DevelControl::Property::SHADOW);
2014 // Trigger a size negotiation request that may be needed when unregistering a visual.
2015 mControlImpl.RelayoutRequest();
2018 Dali::Property Control::Impl::GetVisualProperty(Dali::Property::Index index, Dali::Property::Key visualPropertyKey)
2020 Toolkit::Visual::Base visual = GetVisualByIndex(mVisuals, index);
2023 Internal::Visual::Base& visualImpl = Toolkit::GetImplementation(visual);
2024 return visualImpl.GetPropertyObject(visualPropertyKey);
2028 return Dali::Property(handle, Property::INVALID_INDEX);
2031 void Control::Impl::CreateTransitions(std::vector<std::pair<Dali::Property::Index, Dali::Property::Map>>& sourceProperties,
2032 std::vector<std::pair<Dali::Property::Index, Dali::Property::Map>>& destinationProperties,
2033 Dali::Toolkit::Control source,
2034 Dali::Toolkit::Control destination)
2036 // Retrieves background properties to be transitioned.
2037 Dali::Property::Map backgroundSourcePropertyMap, backgroundDestinationPropertyMap;
2038 mControlImpl.MakeVisualTransition(backgroundSourcePropertyMap, backgroundDestinationPropertyMap, source, destination, Toolkit::Control::Property::BACKGROUND);
2039 if(backgroundSourcePropertyMap.Count() > 0)
2041 sourceProperties.push_back(std::pair<Dali::Property::Index, Dali::Property::Map>(Toolkit::Control::Property::BACKGROUND, backgroundSourcePropertyMap));
2042 destinationProperties.push_back(std::pair<Dali::Property::Index, Dali::Property::Map>(Toolkit::Control::Property::BACKGROUND, backgroundDestinationPropertyMap));
2045 // Retrieves shadow properties to be transitioned.
2046 Dali::Property::Map shadowSourcePropertyMap, shadowDestinationPropertyMap;
2047 mControlImpl.MakeVisualTransition(shadowSourcePropertyMap, shadowDestinationPropertyMap, source, destination, Toolkit::DevelControl::Property::SHADOW);
2048 if(shadowSourcePropertyMap.Count() > 0)
2050 sourceProperties.push_back(std::pair<Dali::Property::Index, Dali::Property::Map>(Toolkit::DevelControl::Property::SHADOW, shadowSourcePropertyMap));
2051 destinationProperties.push_back(std::pair<Dali::Property::Index, Dali::Property::Map>(Toolkit::DevelControl::Property::SHADOW, shadowDestinationPropertyMap));
2054 // Retrieves transition from inherited class.
2055 mControlImpl.OnCreateTransitions(sourceProperties, destinationProperties, source, destination);
2058 void Control::Impl::UpdateVisualProperties(const std::vector<std::pair<Dali::Property::Index, Dali::Property::Map>>& properties)
2060 for(auto&& data : properties)
2062 if(data.first == Toolkit::Control::Property::BACKGROUND)
2064 DoAction(Toolkit::Control::Property::BACKGROUND, DevelVisual::Action::UPDATE_PROPERTY, data.second);
2066 else if(data.first == Toolkit::DevelControl::Property::SHADOW)
2068 DoAction(Toolkit::DevelControl::Property::SHADOW, DevelVisual::Action::UPDATE_PROPERTY, data.second);
2071 mControlImpl.OnUpdateVisualProperties(properties);
2074 void Control::Impl::EmitResourceReadySignal()
2076 if(!mIsEmittingResourceReadySignal)
2078 // Guard against calls to emit the signal during the callback
2079 mIsEmittingResourceReadySignal = true;
2081 // If the signal handler changes visual, it may become ready during this call & therefore this method will
2082 // get called again recursively. If so, mNeedToEmitResourceReady is set below, and we act on it after that secondary
2083 // invocation has completed by notifying in an Idle callback to prevent further recursion.
2084 Dali::Toolkit::Control handle(mControlImpl.GetOwner());
2085 mResourceReadySignal.Emit(handle);
2087 if(mNeedToEmitResourceReady)
2089 // Add idler to emit the signal again
2092 // The callback manager takes the ownership of the callback object.
2093 mIdleCallback = MakeCallback(this, &Control::Impl::OnIdleCallback);
2094 Adaptor::Get().AddIdle(mIdleCallback, false);
2098 mIsEmittingResourceReadySignal = false;
2102 mNeedToEmitResourceReady = true;
2106 void Control::Impl::OnIdleCallback()
2108 if(mNeedToEmitResourceReady)
2111 mNeedToEmitResourceReady = false;
2113 // A visual is ready so control may need relayouting if staged
2114 if(mControlImpl.Self().GetProperty<bool>(Actor::Property::CONNECTED_TO_SCENE))
2116 mControlImpl.RelayoutRequest();
2119 EmitResourceReadySignal();
2122 // Set the pointer to null as the callback manager deletes the callback after execute it.
2123 mIdleCallback = nullptr;
2126 Toolkit::DevelControl::ControlAccessible* Control::Impl::GetAccessibleObject()
2128 if(!mAccessibleObject)
2130 mAccessibleObject.reset(mControlImpl.CreateAccessibleObject());
2133 return mAccessibleObject.get();
2136 } // namespace Internal
2138 } // namespace Toolkit