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/math/math-utils.h>
34 #include <dali/public-api/object/object-registry.h>
35 #include <dali/public-api/object/type-registry-helper.h>
40 #include <dali-toolkit/devel-api/asset-manager/asset-manager.h>
41 #include <dali-toolkit/devel-api/controls/control-depth-index-ranges.h>
42 #include <dali-toolkit/devel-api/controls/control-devel.h>
43 #include <dali-toolkit/devel-api/controls/control-wrapper-impl.h>
44 #include <dali-toolkit/devel-api/visuals/visual-actions-devel.h>
45 #include <dali-toolkit/internal/styling/style-manager-impl.h>
46 #include <dali-toolkit/internal/visuals/visual-base-impl.h>
47 #include <dali-toolkit/internal/visuals/visual-string-constants.h>
48 #include <dali-toolkit/public-api/controls/image-view/image-view.h>
49 #include <dali-toolkit/public-api/focus-manager/keyboard-focus-manager.h>
50 #include <dali-toolkit/public-api/visuals/image-visual-properties.h>
51 #include <dali-toolkit/public-api/visuals/visual-properties.h>
55 const char* READING_INFO_TYPE_NAME = "name";
56 const char* READING_INFO_TYPE_ROLE = "role";
57 const char* READING_INFO_TYPE_DESCRIPTION = "description";
58 const char* READING_INFO_TYPE_STATE = "state";
59 const char* READING_INFO_TYPE_ATTRIBUTE_NAME = "reading_info_type";
60 const char* READING_INFO_TYPE_SEPARATOR = "|";
69 extern const Dali::Scripting::StringEnum ControlStateTable[];
70 extern const unsigned int ControlStateTableCount;
72 // Not static or anonymous - shared with other translation units
73 const Scripting::StringEnum ControlStateTable[] = {
74 {"NORMAL", Toolkit::DevelControl::NORMAL},
75 {"FOCUSED", Toolkit::DevelControl::FOCUSED},
76 {"DISABLED", Toolkit::DevelControl::DISABLED},
78 const unsigned int ControlStateTableCount = sizeof(ControlStateTable) / sizeof(ControlStateTable[0]);
82 #if defined(DEBUG_ENABLED)
83 Debug::Filter* gLogFilter = Debug::Filter::New(Debug::NoLogging, false, "LOG_CONTROL_VISUALS");
87 void Remove(Dictionary<T>& keyValues, const std::string& name)
89 keyValues.Remove(name);
92 void Remove(DictionaryKeys& keys, const std::string& name)
94 DictionaryKeys::iterator iter = std::find(keys.begin(), keys.end(), name);
95 if(iter != keys.end())
102 * Finds visual in given array, returning true if found along with the iterator for that visual as a out parameter
104 bool FindVisual(Property::Index targetIndex, const RegisteredVisualContainer& visuals, RegisteredVisualContainer::Iterator& iter)
106 for(iter = visuals.Begin(); iter != visuals.End(); iter++)
108 if((*iter)->index == targetIndex)
117 * Finds visual in given array, returning true if found along with the iterator for that visual as a out parameter
119 bool FindVisual(std::string visualName, const RegisteredVisualContainer& visuals, RegisteredVisualContainer::Iterator& iter)
121 for(iter = visuals.Begin(); iter != visuals.End(); iter++)
123 Toolkit::Visual::Base visual = (*iter)->visual;
124 if(visual && visual.GetName() == visualName)
132 void FindChangableVisuals(Dictionary<Property::Map>& stateVisualsToAdd,
133 Dictionary<Property::Map>& stateVisualsToChange,
134 DictionaryKeys& stateVisualsToRemove)
136 DictionaryKeys copyOfStateVisualsToRemove = stateVisualsToRemove;
138 for(DictionaryKeys::iterator iter = copyOfStateVisualsToRemove.begin();
139 iter != copyOfStateVisualsToRemove.end();
142 const std::string& visualName = (*iter);
143 Property::Map* toMap = stateVisualsToAdd.Find(visualName);
146 stateVisualsToChange.Add(visualName, *toMap);
147 stateVisualsToAdd.Remove(visualName);
148 Remove(stateVisualsToRemove, visualName);
153 Toolkit::Visual::Base GetVisualByName(
154 const RegisteredVisualContainer& visuals,
155 const std::string& visualName)
157 Toolkit::Visual::Base visualHandle;
159 RegisteredVisualContainer::Iterator iter;
160 for(iter = visuals.Begin(); iter != visuals.End(); iter++)
162 Toolkit::Visual::Base visual = (*iter)->visual;
163 if(visual && visual.GetName() == visualName)
165 visualHandle = visual;
172 Toolkit::Visual::Base GetVisualByIndex(
173 const RegisteredVisualContainer& visuals,
174 Property::Index index)
176 Toolkit::Visual::Base visualHandle;
178 RegisteredVisualContainer::Iterator iter;
179 for(iter = visuals.Begin(); iter != visuals.End(); iter++)
181 if((*iter)->index == index)
183 visualHandle = (*iter)->visual;
191 * Move visual from source to destination container
193 void MoveVisual(RegisteredVisualContainer::Iterator sourceIter, RegisteredVisualContainer& source, RegisteredVisualContainer& destination)
195 Toolkit::Visual::Base visual = (*sourceIter)->visual;
198 RegisteredVisual* rv = source.Release(sourceIter);
199 destination.PushBack(rv);
204 * Performs actions as requested using the action name.
205 * @param[in] object The object on which to perform the action.
206 * @param[in] actionName The action to perform.
207 * @param[in] attributes The attributes with which to perfrom this action.
208 * @return true if action has been accepted by this control
210 const char* ACTION_ACCESSIBILITY_ACTIVATED = "accessibilityActivated";
211 const char* ACTION_ACCESSIBILITY_READING_CANCELLED = "ReadingCancelled";
212 const char* ACTION_ACCESSIBILITY_READING_PAUSED = "ReadingPaused";
213 const char* ACTION_ACCESSIBILITY_READING_RESUMED = "ReadingResumed";
214 const char* ACTION_ACCESSIBILITY_READING_SKIPPED = "ReadingSkipped";
215 const char* ACTION_ACCESSIBILITY_READING_STOPPED = "ReadingStopped";
217 static bool DoAction(BaseObject* object, const std::string& actionName, const Property::Map& attributes)
221 Dali::BaseHandle handle(object);
223 Toolkit::Control control = Toolkit::Control::DownCast(handle);
225 DALI_ASSERT_ALWAYS(control);
227 if(0 == strcmp(actionName.c_str(), ACTION_ACCESSIBILITY_ACTIVATED) || actionName == "activate")
229 // if cast succeeds there is an implementation so no need to check
230 if(!DevelControl::AccessibilityActivateSignal(control).Empty())
232 DevelControl::AccessibilityActivateSignal(control).Emit();
236 ret = Internal::GetImplementation(control).OnAccessibilityActivated();
239 else if(0 == strcmp(actionName.c_str(), ACTION_ACCESSIBILITY_READING_SKIPPED))
241 // if cast succeeds there is an implementation so no need to check
242 if(!DevelControl::AccessibilityReadingSkippedSignal(control).Empty())
244 DevelControl::AccessibilityReadingSkippedSignal(control).Emit();
247 else if(0 == strcmp(actionName.c_str(), ACTION_ACCESSIBILITY_READING_PAUSED))
249 // if cast succeeds there is an implementation so no need to check
250 if(!DevelControl::AccessibilityReadingPausedSignal(control).Empty())
252 DevelControl::AccessibilityReadingPausedSignal(control).Emit();
255 else if(0 == strcmp(actionName.c_str(), ACTION_ACCESSIBILITY_READING_RESUMED))
257 // if cast succeeds there is an implementation so no need to check
258 if(!DevelControl::AccessibilityReadingResumedSignal(control).Empty())
260 DevelControl::AccessibilityReadingResumedSignal(control).Emit();
263 else if(0 == strcmp(actionName.c_str(), ACTION_ACCESSIBILITY_READING_CANCELLED))
265 // if cast succeeds there is an implementation so no need to check
266 if(!DevelControl::AccessibilityReadingCancelledSignal(control).Empty())
268 DevelControl::AccessibilityReadingCancelledSignal(control).Emit();
271 else if(0 == strcmp(actionName.c_str(), ACTION_ACCESSIBILITY_READING_STOPPED))
273 // if cast succeeds there is an implementation so no need to check
274 if(!DevelControl::AccessibilityReadingStoppedSignal(control).Empty())
276 DevelControl::AccessibilityReadingStoppedSignal(control).Emit();
287 * Connects a callback function with the object's signals.
288 * @param[in] object The object providing the signal.
289 * @param[in] tracker Used to disconnect the signal.
290 * @param[in] signalName The signal to connect to.
291 * @param[in] functor A newly allocated FunctorDelegate.
292 * @return True if the signal was connected.
293 * @post If a signal was connected, ownership of functor was passed to CallbackBase. Otherwise the caller is responsible for deleting the unused functor.
295 const char* SIGNAL_KEY_EVENT = "keyEvent";
296 const char* SIGNAL_KEY_INPUT_FOCUS_GAINED = "keyInputFocusGained";
297 const char* SIGNAL_KEY_INPUT_FOCUS_LOST = "keyInputFocusLost";
298 const char* SIGNAL_TAPPED = "tapped";
299 const char* SIGNAL_PANNED = "panned";
300 const char* SIGNAL_PINCHED = "pinched";
301 const char* SIGNAL_LONG_PRESSED = "longPressed";
302 const char* SIGNAL_GET_NAME = "getName";
303 const char* SIGNAL_GET_DESCRIPTION = "getDescription";
304 const char* SIGNAL_DO_GESTURE = "doGesture";
305 static bool DoConnectSignal(BaseObject* object, ConnectionTrackerInterface* tracker, const std::string& signalName, FunctorDelegate* functor)
307 Dali::BaseHandle handle(object);
309 bool connected(false);
310 Toolkit::Control control = Toolkit::Control::DownCast(handle);
313 Internal::Control& controlImpl(Internal::GetImplementation(control));
316 if(0 == strcmp(signalName.c_str(), SIGNAL_KEY_EVENT))
318 controlImpl.KeyEventSignal().Connect(tracker, functor);
320 else if(0 == strcmp(signalName.c_str(), SIGNAL_KEY_INPUT_FOCUS_GAINED))
322 controlImpl.KeyInputFocusGainedSignal().Connect(tracker, functor);
324 else if(0 == strcmp(signalName.c_str(), SIGNAL_KEY_INPUT_FOCUS_LOST))
326 controlImpl.KeyInputFocusLostSignal().Connect(tracker, functor);
328 else if(0 == strcmp(signalName.c_str(), SIGNAL_TAPPED))
330 controlImpl.EnableGestureDetection(GestureType::TAP);
331 controlImpl.GetTapGestureDetector().DetectedSignal().Connect(tracker, functor);
333 else if(0 == strcmp(signalName.c_str(), SIGNAL_PANNED))
335 controlImpl.EnableGestureDetection(GestureType::PAN);
336 controlImpl.GetPanGestureDetector().DetectedSignal().Connect(tracker, functor);
338 else if(0 == strcmp(signalName.c_str(), SIGNAL_PINCHED))
340 controlImpl.EnableGestureDetection(GestureType::PINCH);
341 controlImpl.GetPinchGestureDetector().DetectedSignal().Connect(tracker, functor);
343 else if(0 == strcmp(signalName.c_str(), SIGNAL_LONG_PRESSED))
345 controlImpl.EnableGestureDetection(GestureType::LONG_PRESS);
346 controlImpl.GetLongPressGestureDetector().DetectedSignal().Connect(tracker, functor);
348 else if(0 == strcmp(signalName.c_str(), SIGNAL_GET_NAME))
350 DevelControl::AccessibilityGetNameSignal(control).Connect(tracker, functor);
352 else if(0 == strcmp(signalName.c_str(), SIGNAL_GET_DESCRIPTION))
354 DevelControl::AccessibilityGetDescriptionSignal(control).Connect(tracker, functor);
356 else if(0 == strcmp(signalName.c_str(), SIGNAL_DO_GESTURE))
358 DevelControl::AccessibilityDoGestureSignal(control).Connect(tracker, functor);
365 * Creates control through type registry
369 return Internal::Control::New();
371 // Setup signals and actions using the type-registry.
372 DALI_TYPE_REGISTRATION_BEGIN(Control, CustomActor, Create);
374 // Note: Properties are registered separately below.
376 SignalConnectorType registerSignal1(typeRegistration, SIGNAL_KEY_EVENT, &DoConnectSignal);
377 SignalConnectorType registerSignal2(typeRegistration, SIGNAL_KEY_INPUT_FOCUS_GAINED, &DoConnectSignal);
378 SignalConnectorType registerSignal3(typeRegistration, SIGNAL_KEY_INPUT_FOCUS_LOST, &DoConnectSignal);
379 SignalConnectorType registerSignal4(typeRegistration, SIGNAL_TAPPED, &DoConnectSignal);
380 SignalConnectorType registerSignal5(typeRegistration, SIGNAL_PANNED, &DoConnectSignal);
381 SignalConnectorType registerSignal6(typeRegistration, SIGNAL_PINCHED, &DoConnectSignal);
382 SignalConnectorType registerSignal7(typeRegistration, SIGNAL_LONG_PRESSED, &DoConnectSignal);
383 SignalConnectorType registerSignal8(typeRegistration, SIGNAL_GET_NAME, &DoConnectSignal);
384 SignalConnectorType registerSignal9(typeRegistration, SIGNAL_GET_DESCRIPTION, &DoConnectSignal);
385 SignalConnectorType registerSignal10(typeRegistration, SIGNAL_DO_GESTURE, &DoConnectSignal);
387 TypeAction registerAction1(typeRegistration, "activate", &DoAction);
388 TypeAction registerAction2(typeRegistration, ACTION_ACCESSIBILITY_ACTIVATED, &DoAction);
389 TypeAction registerAction3(typeRegistration, ACTION_ACCESSIBILITY_READING_SKIPPED, &DoAction);
390 TypeAction registerAction4(typeRegistration, ACTION_ACCESSIBILITY_READING_CANCELLED, &DoAction);
391 TypeAction registerAction5(typeRegistration, ACTION_ACCESSIBILITY_READING_STOPPED, &DoAction);
392 TypeAction registerAction6(typeRegistration, ACTION_ACCESSIBILITY_READING_PAUSED, &DoAction);
393 TypeAction registerAction7(typeRegistration, ACTION_ACCESSIBILITY_READING_RESUMED, &DoAction);
395 DALI_TYPE_REGISTRATION_END()
398 * @brief Iterate through given container and setOffScene any visual found
400 * @param[in] container Container of visuals
401 * @param[in] parent Parent actor to remove visuals from
403 void SetVisualsOffScene(const RegisteredVisualContainer& container, Actor parent)
405 for(auto iter = container.Begin(), end = container.End(); iter != end; iter++)
409 DALI_LOG_INFO(gLogFilter, Debug::Verbose, "Control::SetOffScene Setting visual(%d) off stage\n", (*iter)->index);
410 Toolkit::GetImplementation((*iter)->visual).SetOffScene(parent);
415 Dali::Rect<> GetShowingGeometry(Dali::Rect<> rect, Dali::Toolkit::DevelControl::ControlAccessible* accessible)
418 Vector2 currentPosition;
419 auto parent = dynamic_cast<Toolkit::DevelControl::ControlAccessible*>(accessible->GetParent());
423 parentRect = parent->GetExtents(Dali::Accessibility::CoordinateType::WINDOW);
425 currentPosition.x = rect.x;
426 currentPosition.y = rect.y;
428 rect.x = rect.x > parentRect.x ? rect.x : parentRect.x;
429 rect.y = rect.y > parentRect.y ? rect.y : parentRect.y;
430 rect.width = currentPosition.x + rect.width < parentRect.x + parentRect.width ? currentPosition.x + rect.width - rect.x : parentRect.x + parentRect.width - rect.x;
431 rect.height = currentPosition.y + rect.height < parentRect.y + parentRect.height ? currentPosition.y + rect.height - rect.y : parentRect.y + parentRect.height - rect.y;
433 if(rect.width < 0 || rect.height < 0)
438 parent = dynamic_cast<Toolkit::DevelControl::ControlAccessible*>(parent->GetParent());
444 static bool IsShowingGeometryOnScreen(Dali::Rect<> rect)
446 return rect.width > 0 && rect.height > 0;
449 Dali::Accessibility::Accessible* ExternalAccessibleGetter(Dali::Actor actor)
451 auto control = Toolkit::Control::DownCast(actor);
457 auto& controlImpl = Toolkit::Internal::GetImplementation(control);
459 return controlImpl.GetAccessibleObject();
462 } // unnamed namespace
465 // Properties registered without macro to use specific member variables.
466 const PropertyRegistration Control::Impl::PROPERTY_1(typeRegistration, "styleName", Toolkit::Control::Property::STYLE_NAME, Property::STRING, &Control::Impl::SetProperty, &Control::Impl::GetProperty);
467 const PropertyRegistration Control::Impl::PROPERTY_4(typeRegistration, "keyInputFocus", Toolkit::Control::Property::KEY_INPUT_FOCUS, Property::BOOLEAN, &Control::Impl::SetProperty, &Control::Impl::GetProperty);
468 const PropertyRegistration Control::Impl::PROPERTY_5(typeRegistration, "background", Toolkit::Control::Property::BACKGROUND, Property::MAP, &Control::Impl::SetProperty, &Control::Impl::GetProperty);
469 const PropertyRegistration Control::Impl::PROPERTY_6(typeRegistration, "margin", Toolkit::Control::Property::MARGIN, Property::EXTENTS, &Control::Impl::SetProperty, &Control::Impl::GetProperty);
470 const PropertyRegistration Control::Impl::PROPERTY_7(typeRegistration, "padding", Toolkit::Control::Property::PADDING, Property::EXTENTS, &Control::Impl::SetProperty, &Control::Impl::GetProperty);
471 const PropertyRegistration Control::Impl::PROPERTY_8(typeRegistration, "tooltip", Toolkit::DevelControl::Property::TOOLTIP, Property::MAP, &Control::Impl::SetProperty, &Control::Impl::GetProperty);
472 const PropertyRegistration Control::Impl::PROPERTY_9(typeRegistration, "state", Toolkit::DevelControl::Property::STATE, Property::STRING, &Control::Impl::SetProperty, &Control::Impl::GetProperty);
473 const PropertyRegistration Control::Impl::PROPERTY_10(typeRegistration, "subState", Toolkit::DevelControl::Property::SUB_STATE, Property::STRING, &Control::Impl::SetProperty, &Control::Impl::GetProperty);
474 const PropertyRegistration Control::Impl::PROPERTY_11(typeRegistration, "leftFocusableActorId", Toolkit::DevelControl::Property::LEFT_FOCUSABLE_ACTOR_ID, Property::INTEGER, &Control::Impl::SetProperty, &Control::Impl::GetProperty);
475 const PropertyRegistration Control::Impl::PROPERTY_12(typeRegistration, "rightFocusableActorId", Toolkit::DevelControl::Property::RIGHT_FOCUSABLE_ACTOR_ID, Property::INTEGER, &Control::Impl::SetProperty, &Control::Impl::GetProperty);
476 const PropertyRegistration Control::Impl::PROPERTY_13(typeRegistration, "upFocusableActorId", Toolkit::DevelControl::Property::UP_FOCUSABLE_ACTOR_ID, Property::INTEGER, &Control::Impl::SetProperty, &Control::Impl::GetProperty);
477 const PropertyRegistration Control::Impl::PROPERTY_14(typeRegistration, "downFocusableActorId", Toolkit::DevelControl::Property::DOWN_FOCUSABLE_ACTOR_ID, Property::INTEGER, &Control::Impl::SetProperty, &Control::Impl::GetProperty);
478 const PropertyRegistration Control::Impl::PROPERTY_15(typeRegistration, "shadow", Toolkit::DevelControl::Property::SHADOW, Property::MAP, &Control::Impl::SetProperty, &Control::Impl::GetProperty);
479 const PropertyRegistration Control::Impl::PROPERTY_16(typeRegistration, "accessibilityName", Toolkit::DevelControl::Property::ACCESSIBILITY_NAME, Property::STRING, &Control::Impl::SetProperty, &Control::Impl::GetProperty);
480 const PropertyRegistration Control::Impl::PROPERTY_17(typeRegistration, "accessibilityDescription", Toolkit::DevelControl::Property::ACCESSIBILITY_DESCRIPTION, Property::STRING, &Control::Impl::SetProperty, &Control::Impl::GetProperty);
481 const PropertyRegistration Control::Impl::PROPERTY_18(typeRegistration, "accessibilityTranslationDomain", Toolkit::DevelControl::Property::ACCESSIBILITY_TRANSLATION_DOMAIN, Property::STRING, &Control::Impl::SetProperty, &Control::Impl::GetProperty);
482 const PropertyRegistration Control::Impl::PROPERTY_19(typeRegistration, "accessibilityRole", Toolkit::DevelControl::Property::ACCESSIBILITY_ROLE, Property::INTEGER, &Control::Impl::SetProperty, &Control::Impl::GetProperty);
483 const PropertyRegistration Control::Impl::PROPERTY_20(typeRegistration, "accessibilityHighlightable", Toolkit::DevelControl::Property::ACCESSIBILITY_HIGHLIGHTABLE, Property::BOOLEAN, &Control::Impl::SetProperty, &Control::Impl::GetProperty);
484 const PropertyRegistration Control::Impl::PROPERTY_21(typeRegistration, "accessibilityAttributes", Toolkit::DevelControl::Property::ACCESSIBILITY_ATTRIBUTES, Property::MAP, &Control::Impl::SetProperty, &Control::Impl::GetProperty);
485 const PropertyRegistration Control::Impl::PROPERTY_22(typeRegistration, "dispatchKeyEvents", Toolkit::DevelControl::Property::DISPATCH_KEY_EVENTS, Property::BOOLEAN, &Control::Impl::SetProperty, &Control::Impl::GetProperty);
486 const PropertyRegistration Control::Impl::PROPERTY_23(typeRegistration, "accessibilityHidden", Toolkit::DevelControl::Property::ACCESSIBILITY_HIDDEN, Property::BOOLEAN, &Control::Impl::SetProperty, &Control::Impl::GetProperty);
487 const PropertyRegistration Control::Impl::PROPERTY_24(typeRegistration, "clockwiseFocusableActorId", Toolkit::DevelControl::Property::CLOCKWISE_FOCUSABLE_ACTOR_ID, Property::INTEGER, &Control::Impl::SetProperty, &Control::Impl::GetProperty);
488 const PropertyRegistration Control::Impl::PROPERTY_25(typeRegistration, "counterClockwiseFocusableActorId", Toolkit::DevelControl::Property::COUNTER_CLOCKWISE_FOCUSABLE_ACTOR_ID, Property::INTEGER, &Control::Impl::SetProperty, &Control::Impl::GetProperty);
489 const PropertyRegistration Control::Impl::PROPERTY_26(typeRegistration, "automationId", Toolkit::DevelControl::Property::AUTOMATION_ID, Property::STRING, &Control::Impl::SetProperty, &Control::Impl::GetProperty);
493 Control::Impl::Impl(Control& controlImpl)
494 : mControlImpl(controlImpl),
495 mState(Toolkit::DevelControl::NORMAL),
497 mLeftFocusableActorId(-1),
498 mRightFocusableActorId(-1),
499 mUpFocusableActorId(-1),
500 mDownFocusableActorId(-1),
501 mClockwiseFocusableActorId(-1),
502 mCounterClockwiseFocusableActorId(-1),
504 mBackgroundColor(Color::TRANSPARENT),
505 mStartingPinchScale(nullptr),
507 mPadding(0, 0, 0, 0),
509 mKeyInputFocusGainedSignal(),
510 mKeyInputFocusLostSignal(),
511 mResourceReadySignal(),
512 mVisualEventSignal(),
513 mAccessibilityGetNameSignal(),
514 mAccessibilityGetDescriptionSignal(),
515 mAccessibilityDoGestureSignal(),
516 mPinchGestureDetector(),
517 mPanGestureDetector(),
518 mTapGestureDetector(),
519 mLongPressGestureDetector(),
521 mInputMethodContext(),
522 mIdleCallback(nullptr),
523 mFlags(Control::ControlBehaviour(CONTROL_BEHAVIOUR_DEFAULT)),
524 mIsKeyboardNavigationSupported(false),
525 mIsKeyboardFocusGroup(false),
526 mIsEmittingResourceReadySignal(false),
527 mNeedToEmitResourceReady(false),
528 mDispatchKeyEvents(true)
530 Dali::Accessibility::Accessible::RegisterExternalAccessibleGetter(&ExternalAccessibleGetter);
533 Control::Impl::~Impl()
535 for(auto&& iter : mVisuals)
537 StopObservingVisual(iter->visual);
540 for(auto&& iter : mRemoveVisuals)
542 StopObservingVisual(iter->visual);
545 // All gesture detectors will be destroyed so no need to disconnect.
546 delete mStartingPinchScale;
548 if(mIdleCallback && Adaptor::IsAvailable())
550 // Removes the callback from the callback manager in case the control is destroyed before the callback is executed.
551 Adaptor::Get().RemoveIdle(mIdleCallback);
555 Control::Impl& Control::Impl::Get(Internal::Control& internalControl)
557 return *internalControl.mImpl;
560 const Control::Impl& Control::Impl::Get(const Internal::Control& internalControl)
562 return *internalControl.mImpl;
565 void Control::Impl::CheckHighlightedObjectGeometry()
567 auto accessible = GetAccessibleObject();
568 auto lastPosition = accessible->GetLastPosition();
569 auto accessibleRect = accessible->GetExtents(Dali::Accessibility::CoordinateType::WINDOW);
570 auto rect = GetShowingGeometry(accessibleRect, accessible);
572 switch(mAccessibilityLastScreenRelativeMoveType)
574 case Dali::Accessibility::ScreenRelativeMoveType::OUTSIDE:
576 if(IsShowingGeometryOnScreen(rect))
578 mAccessibilityLastScreenRelativeMoveType = Dali::Accessibility::ScreenRelativeMoveType::INSIDE;
582 case Dali::Accessibility::ScreenRelativeMoveType::INSIDE:
584 if(rect.width < 0 && !Dali::Equals(accessibleRect.x, lastPosition.x))
586 mAccessibilityLastScreenRelativeMoveType = (accessibleRect.x < lastPosition.x) ? Dali::Accessibility::ScreenRelativeMoveType::OUTGOING_TOP_LEFT : Dali::Accessibility::ScreenRelativeMoveType::OUTGOING_BOTTOM_RIGHT;
588 if(rect.height < 0 && !Dali::Equals(accessibleRect.y, lastPosition.y))
590 mAccessibilityLastScreenRelativeMoveType = (accessibleRect.y < lastPosition.y) ? Dali::Accessibility::ScreenRelativeMoveType::OUTGOING_TOP_LEFT : Dali::Accessibility::ScreenRelativeMoveType::OUTGOING_BOTTOM_RIGHT;
592 // notify AT-clients on outgoing moves only
593 if(mAccessibilityLastScreenRelativeMoveType != Dali::Accessibility::ScreenRelativeMoveType::INSIDE)
595 accessible->EmitMovedOutOfScreen(mAccessibilityLastScreenRelativeMoveType);
599 case Dali::Accessibility::ScreenRelativeMoveType::OUTGOING_TOP_LEFT:
600 case Dali::Accessibility::ScreenRelativeMoveType::OUTGOING_BOTTOM_RIGHT:
602 if(IsShowingGeometryOnScreen(rect))
604 mAccessibilityLastScreenRelativeMoveType = Dali::Accessibility::ScreenRelativeMoveType::INSIDE;
608 mAccessibilityLastScreenRelativeMoveType = Dali::Accessibility::ScreenRelativeMoveType::OUTSIDE;
618 accessible->SetLastPosition(Vector2(accessibleRect.x, accessibleRect.y));
621 void Control::Impl::RegisterAccessibilityPositionPropertyNotification()
623 if(mIsAccessibilityPositionPropertyNotificationSet)
627 // set default value until first move of object is detected
628 mAccessibilityLastScreenRelativeMoveType = Dali::Accessibility::ScreenRelativeMoveType::OUTSIDE;
629 // recalculate mAccessibilityLastScreenRelativeMoveType accordingly to the initial position
630 CheckHighlightedObjectGeometry();
631 mAccessibilityPositionNotification = mControlImpl.Self().AddPropertyNotification(Actor::Property::WORLD_POSITION, StepCondition(1.0f, 1.0f));
632 mAccessibilityPositionNotification.SetNotifyMode(PropertyNotification::NOTIFY_ON_CHANGED);
633 mAccessibilityPositionNotification.NotifySignal().Connect(this, [this](PropertyNotification&) { CheckHighlightedObjectGeometry(); });
634 mIsAccessibilityPositionPropertyNotificationSet = true;
637 void Control::Impl::UnregisterAccessibilityPositionPropertyNotification()
639 mControlImpl.Self().RemovePropertyNotification(mAccessibilityPositionNotification);
640 mIsAccessibilityPositionPropertyNotificationSet = false;
643 // Gesture Detection Methods
644 void Control::Impl::PinchDetected(Actor actor, const PinchGesture& pinch)
646 mControlImpl.OnPinch(pinch);
649 void Control::Impl::PanDetected(Actor actor, const PanGesture& pan)
651 mControlImpl.OnPan(pan);
654 void Control::Impl::TapDetected(Actor actor, const TapGesture& tap)
656 mControlImpl.OnTap(tap);
659 void Control::Impl::LongPressDetected(Actor actor, const LongPressGesture& longPress)
661 mControlImpl.OnLongPress(longPress);
664 void Control::Impl::RegisterVisual(Property::Index index, Toolkit::Visual::Base& visual)
666 RegisterVisual(index, visual, VisualState::ENABLED, DepthIndexValue::NOT_SET);
669 void Control::Impl::RegisterVisual(Property::Index index, Toolkit::Visual::Base& visual, int depthIndex)
671 RegisterVisual(index, visual, VisualState::ENABLED, DepthIndexValue::SET, depthIndex);
674 void Control::Impl::RegisterVisual(Property::Index index, Toolkit::Visual::Base& visual, bool enabled)
676 RegisterVisual(index, visual, (enabled ? VisualState::ENABLED : VisualState::DISABLED), DepthIndexValue::NOT_SET);
679 void Control::Impl::RegisterVisual(Property::Index index, Toolkit::Visual::Base& visual, bool enabled, int depthIndex)
681 RegisterVisual(index, visual, (enabled ? VisualState::ENABLED : VisualState::DISABLED), DepthIndexValue::SET, depthIndex);
684 void Control::Impl::RegisterVisual(Property::Index index, Toolkit::Visual::Base& visual, VisualState::Type enabled, DepthIndexValue::Type depthIndexValueSet, int depthIndex)
686 DALI_LOG_INFO(gLogFilter, Debug::Concise, "RegisterVisual:%d \n", index);
688 bool visualReplaced(false);
689 Actor self = mControlImpl.Self();
691 // Set the depth index, if not set by caller this will be either the current visual depth, max depth of all visuals
693 int requiredDepthIndex = visual.GetDepthIndex();
695 if(depthIndexValueSet == DepthIndexValue::SET)
697 requiredDepthIndex = depthIndex;
700 // Visual replacement, existing visual should only be removed from stage when replacement ready.
701 if(!mVisuals.Empty())
703 RegisteredVisualContainer::Iterator registeredVisualsiter;
704 // Check if visual (index) is already registered, this is the current visual.
705 if(FindVisual(index, mVisuals, registeredVisualsiter))
707 Toolkit::Visual::Base& currentRegisteredVisual = (*registeredVisualsiter)->visual;
708 if(currentRegisteredVisual)
710 // Store current visual depth index as may need to set the replacement visual to same depth
711 const int currentDepthIndex = (*registeredVisualsiter)->visual.GetDepthIndex();
713 // No longer required to know if the replaced visual's resources are ready
714 StopObservingVisual(currentRegisteredVisual);
716 // If control staged and visual enabled then visuals will be swapped once ready
717 if(self.GetProperty<bool>(Actor::Property::CONNECTED_TO_SCENE) && enabled)
719 // Check if visual is currently in the process of being replaced ( is in removal container )
720 RegisteredVisualContainer::Iterator visualQueuedForRemoval;
721 if(FindVisual(index, mRemoveVisuals, visualQueuedForRemoval))
723 // Visual with same index is already in removal container so current visual pending
724 // Only the the last requested visual will be displayed so remove current visual which is staged but not ready.
725 Toolkit::GetImplementation(currentRegisteredVisual).SetOffScene(self);
726 mVisuals.Erase(registeredVisualsiter);
730 // current visual not already in removal container so add now.
731 DALI_LOG_INFO(gLogFilter, Debug::Verbose, "RegisterVisual Move current registered visual to removal Queue: %d \n", index);
732 MoveVisual(registeredVisualsiter, mVisuals, mRemoveVisuals);
737 // Control not staged or visual disabled so can just erase from registered visuals and new visual will be added later.
738 mVisuals.Erase(registeredVisualsiter);
741 // 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
742 if((depthIndexValueSet == DepthIndexValue::NOT_SET) &&
743 (visual.GetDepthIndex() == 0))
745 requiredDepthIndex = currentDepthIndex;
749 visualReplaced = true;
753 // If not set, set the name of the visual to the same name as the control's property.
754 // ( If the control has been type registered )
755 if(visual.GetName().empty())
757 // returns empty string if index is not found as long as index is not -1
758 std::string visualName = self.GetPropertyName(index);
759 if(!visualName.empty())
761 DALI_LOG_INFO(gLogFilter, Debug::Concise, "Setting visual name for property %d to %s\n", index, visualName.c_str());
762 visual.SetName(visualName);
766 if(!visualReplaced) // New registration entry
768 // 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
769 if((depthIndexValueSet == DepthIndexValue::NOT_SET) &&
770 (mVisuals.Size() > 0) &&
771 (visual.GetDepthIndex() == 0))
773 int maxDepthIndex = std::numeric_limits<int>::min();
775 RegisteredVisualContainer::ConstIterator iter;
776 const RegisteredVisualContainer::ConstIterator endIter = mVisuals.End();
777 for(iter = mVisuals.Begin(); iter != endIter; iter++)
779 const int visualDepthIndex = (*iter)->visual.GetDepthIndex();
780 if(visualDepthIndex > maxDepthIndex)
782 maxDepthIndex = visualDepthIndex;
785 ++maxDepthIndex; // Add one to the current maximum depth index so that our added visual appears on top
786 requiredDepthIndex = std::max(0, maxDepthIndex); // Start at zero if maxDepth index belongs to a background
792 // Set determined depth index
793 visual.SetDepthIndex(requiredDepthIndex);
795 // Monitor when the visual resources are ready
796 StartObservingVisual(visual);
798 DALI_LOG_INFO(gLogFilter, Debug::Concise, "New Visual registration index[%d] depth[%d]\n", index, requiredDepthIndex);
799 RegisteredVisual* newRegisteredVisual = new RegisteredVisual(index, visual, (enabled == VisualState::ENABLED ? true : false), (visualReplaced && enabled));
800 mVisuals.PushBack(newRegisteredVisual);
802 Internal::Visual::Base& visualImpl = Toolkit::GetImplementation(visual);
803 // Put on stage if enabled and the control is already on the stage
804 if((enabled == VisualState::ENABLED) && self.GetProperty<bool>(Actor::Property::CONNECTED_TO_SCENE))
806 visualImpl.SetOnScene(self);
808 else if(visualImpl.IsResourceReady()) // When not being staged, check if visual already 'ResourceReady' before it was Registered. ( Resource may have been loaded already )
810 ResourceReady(visualImpl);
814 DALI_LOG_INFO(gLogFilter, Debug::Verbose, "Control::RegisterVisual() Registered %s(%d), enabled:%s\n", visual.GetName().c_str(), index, enabled ? "true" : "false");
817 void Control::Impl::UnregisterVisual(Property::Index index)
819 RegisteredVisualContainer::Iterator iter;
820 if(FindVisual(index, mVisuals, iter))
822 // stop observing visual
823 StopObservingVisual((*iter)->visual);
825 Actor self(mControlImpl.Self());
826 Toolkit::GetImplementation((*iter)->visual).SetOffScene(self);
827 (*iter)->visual.Reset();
828 mVisuals.Erase(iter);
831 if(FindVisual(index, mRemoveVisuals, iter))
833 Actor self(mControlImpl.Self());
834 Toolkit::GetImplementation((*iter)->visual).SetOffScene(self);
835 (*iter)->pending = false;
836 (*iter)->visual.Reset();
837 mRemoveVisuals.Erase(iter);
841 Toolkit::Visual::Base Control::Impl::GetVisual(Property::Index index) const
843 RegisteredVisualContainer::Iterator iter;
844 if(FindVisual(index, mVisuals, iter))
846 return (*iter)->visual;
849 return Toolkit::Visual::Base();
852 void Control::Impl::EnableVisual(Property::Index index, bool enable)
854 DALI_LOG_INFO(gLogFilter, Debug::General, "Control::EnableVisual(%d, %s)\n", index, enable ? "T" : "F");
856 RegisteredVisualContainer::Iterator iter;
857 if(FindVisual(index, mVisuals, iter))
859 if((*iter)->enabled == enable)
861 DALI_LOG_INFO(gLogFilter, Debug::Verbose, "Control::EnableVisual Visual %s(%d) already %s\n", (*iter)->visual.GetName().c_str(), index, enable ? "enabled" : "disabled");
865 (*iter)->enabled = enable;
866 Actor parentActor = mControlImpl.Self();
867 if(mControlImpl.Self().GetProperty<bool>(Actor::Property::CONNECTED_TO_SCENE)) // If control not on Scene then Visual will be added when SceneConnection is called.
871 DALI_LOG_INFO(gLogFilter, Debug::Verbose, "Control::EnableVisual Setting %s(%d) on stage \n", (*iter)->visual.GetName().c_str(), index);
872 Toolkit::GetImplementation((*iter)->visual).SetOnScene(parentActor);
876 DALI_LOG_INFO(gLogFilter, Debug::Verbose, "Control::EnableVisual Setting %s(%d) off stage \n", (*iter)->visual.GetName().c_str(), index);
877 Toolkit::GetImplementation((*iter)->visual).SetOffScene(parentActor); // No need to call if control not staged.
883 DALI_LOG_WARNING("Control::EnableVisual(%d, %s) FAILED - NO SUCH VISUAL\n", index, enable ? "T" : "F");
887 bool Control::Impl::IsVisualEnabled(Property::Index index) const
889 RegisteredVisualContainer::Iterator iter;
890 if(FindVisual(index, mVisuals, iter))
892 return (*iter)->enabled;
897 void Control::Impl::StopObservingVisual(Toolkit::Visual::Base& visual)
899 Internal::Visual::Base& visualImpl = Toolkit::GetImplementation(visual);
901 // Stop observing the visual
902 visualImpl.RemoveEventObserver(*this);
905 void Control::Impl::StartObservingVisual(Toolkit::Visual::Base& visual)
907 Internal::Visual::Base& visualImpl = Toolkit::GetImplementation(visual);
909 // start observing the visual for events
910 visualImpl.AddEventObserver(*this);
913 void Control::Impl::ResourceReady(bool relayoutRequest)
915 Actor self = mControlImpl.Self();
916 // A visual is ready so control may need relayouting if staged
917 if(relayoutRequest && self.GetProperty<bool>(Actor::Property::CONNECTED_TO_SCENE))
919 mControlImpl.RelayoutRequest();
922 // Emit signal if all enabled visuals registered by the control are ready or there are no visuals.
923 if(IsResourceReady())
926 mNeedToEmitResourceReady = false;
927 EmitResourceReadySignal();
931 // Called by a Visual when it's resource is ready
932 void Control::Impl::ResourceReady(Visual::Base& object)
934 DALI_LOG_INFO(gLogFilter, Debug::Verbose, "Control::Impl::ResourceReady() replacements pending[%d]\n", mRemoveVisuals.Count());
936 Actor self = mControlImpl.Self();
938 // A resource is ready, find resource in the registered visuals container and get its index
939 for(auto registeredIter = mVisuals.Begin(), end = mVisuals.End(); registeredIter != end; ++registeredIter)
941 Internal::Visual::Base& registeredVisualImpl = Toolkit::GetImplementation((*registeredIter)->visual);
943 if(&object == ®isteredVisualImpl)
945 RegisteredVisualContainer::Iterator visualToRemoveIter;
946 // Find visual with the same index in the removal container
947 // Set if off stage as it's replacement is now ready.
948 // Remove if from removal list as now removed from stage.
949 // Set Pending flag on the ready visual to false as now ready.
950 if(FindVisual((*registeredIter)->index, mRemoveVisuals, visualToRemoveIter))
952 (*registeredIter)->pending = false;
953 Toolkit::GetImplementation((*visualToRemoveIter)->visual).SetOffScene(self);
954 mRemoveVisuals.Erase(visualToRemoveIter);
960 // Called by a Visual when it's resource is ready
964 void Control::Impl::NotifyVisualEvent(Visual::Base& object, Property::Index signalId)
966 for(auto registeredIter = mVisuals.Begin(), end = mVisuals.End(); registeredIter != end; ++registeredIter)
968 Internal::Visual::Base& registeredVisualImpl = Toolkit::GetImplementation((*registeredIter)->visual);
969 if(&object == ®isteredVisualImpl)
971 Dali::Toolkit::Control handle(mControlImpl.GetOwner());
972 mVisualEventSignal.Emit(handle, (*registeredIter)->index, signalId);
978 void Control::Impl::RelayoutRequest(Visual::Base& object)
980 mControlImpl.RelayoutRequest();
983 bool Control::Impl::IsResourceReady() const
985 // Iterate through and check all the enabled visuals are ready
986 for(auto visualIter = mVisuals.Begin();
987 visualIter != mVisuals.End();
990 const Toolkit::Visual::Base visual = (*visualIter)->visual;
991 const Internal::Visual::Base& visualImpl = Toolkit::GetImplementation(visual);
993 // one of the enabled visuals is not ready
994 if(!visualImpl.IsResourceReady() && (*visualIter)->enabled)
1002 Toolkit::Visual::ResourceStatus Control::Impl::GetVisualResourceStatus(Property::Index index) const
1004 RegisteredVisualContainer::Iterator iter;
1005 if(FindVisual(index, mVisuals, iter))
1007 const Toolkit::Visual::Base visual = (*iter)->visual;
1008 const Internal::Visual::Base& visualImpl = Toolkit::GetImplementation(visual);
1009 return visualImpl.GetResourceStatus();
1012 return Toolkit::Visual::ResourceStatus::PREPARING;
1015 void Control::Impl::AddTransitions(Dali::Animation& animation,
1016 const Toolkit::TransitionData& handle,
1017 bool createAnimation)
1019 // Setup a Transition from TransitionData.
1020 const Internal::TransitionData& transitionData = Toolkit::GetImplementation(handle);
1021 TransitionData::Iterator end = transitionData.End();
1022 for(TransitionData::Iterator iter = transitionData.Begin();
1026 TransitionData::Animator* animator = (*iter);
1028 Toolkit::Visual::Base visual = GetVisualByName(mVisuals, animator->objectName);
1032 #if defined(DEBUG_ENABLED)
1033 Dali::TypeInfo typeInfo;
1034 ControlWrapper* controlWrapperImpl = dynamic_cast<ControlWrapper*>(&mControlImpl);
1035 if(controlWrapperImpl)
1037 typeInfo = controlWrapperImpl->GetTypeInfo();
1040 DALI_LOG_INFO(gLogFilter, Debug::Concise, "CreateTransition: Found %s visual for %s\n", visual.GetName().c_str(), typeInfo ? typeInfo.GetName().c_str() : "Unknown");
1042 Internal::Visual::Base& visualImpl = Toolkit::GetImplementation(visual);
1043 visualImpl.AnimateProperty(animation, *animator);
1047 DALI_LOG_INFO(gLogFilter, Debug::Concise, "CreateTransition: Could not find visual. Trying actors");
1048 // Otherwise, try any actor children of control (Including the control)
1049 Actor child = mControlImpl.Self().FindChildByName(animator->objectName);
1052 Property::Index propertyIndex = child.GetPropertyIndex(animator->propertyKey);
1053 if(propertyIndex != Property::INVALID_INDEX)
1055 if(animator->animate == false)
1057 if(animator->targetValue.GetType() != Property::NONE)
1059 child.SetProperty(propertyIndex, animator->targetValue);
1062 else // animate the property
1064 if(animator->initialValue.GetType() != Property::NONE)
1066 child.SetProperty(propertyIndex, animator->initialValue);
1069 if(createAnimation && !animation)
1071 animation = Dali::Animation::New(0.1f);
1074 animation.AnimateTo(Property(child, propertyIndex),
1075 animator->targetValue,
1076 animator->alphaFunction,
1077 TimePeriod(animator->timePeriodDelay,
1078 animator->timePeriodDuration));
1086 Dali::Animation Control::Impl::CreateTransition(const Toolkit::TransitionData& transitionData)
1088 Dali::Animation transition;
1090 if(transitionData.Count() > 0)
1092 AddTransitions(transition, transitionData, true);
1097 void Control::Impl::DoAction(Dali::Property::Index visualIndex, Dali::Property::Index actionId, const Dali::Property::Value attributes)
1099 RegisteredVisualContainer::Iterator iter;
1100 if(FindVisual(visualIndex, mVisuals, iter))
1102 Toolkit::GetImplementation((*iter)->visual).DoAction(actionId, attributes);
1106 void Control::Impl::DoActionExtension(Dali::Property::Index visualIndex, Dali::Property::Index actionId, Dali::Any attributes)
1108 RegisteredVisualContainer::Iterator iter;
1109 if(FindVisual(visualIndex, mVisuals, iter))
1111 Toolkit::GetImplementation((*iter)->visual).DoActionExtension(actionId, attributes);
1115 void Control::Impl::AppendAccessibilityAttribute(const std::string& key, const std::string value)
1117 Property::Value* checkedValue = mAccessibilityAttributes.Find(key);
1120 mAccessibilityAttributes[key] = Property::Value(value);
1124 mAccessibilityAttributes.Insert(key, value);
1128 void Control::Impl::SetProperty(BaseObject* object, Property::Index index, const Property::Value& value)
1130 Toolkit::Control control = Toolkit::Control::DownCast(BaseHandle(object));
1134 Control& controlImpl(GetImplementation(control));
1138 case Toolkit::Control::Property::STYLE_NAME:
1140 controlImpl.SetStyleName(value.Get<std::string>());
1144 case Toolkit::DevelControl::Property::STATE:
1146 bool withTransitions = true;
1147 const Property::Value* valuePtr = &value;
1148 const Property::Map* map = value.GetMap();
1151 Property::Value* value2 = map->Find("withTransitions");
1154 withTransitions = value2->Get<bool>();
1157 valuePtr = map->Find("state");
1162 Toolkit::DevelControl::State state(controlImpl.mImpl->mState);
1163 if(Scripting::GetEnumerationProperty<Toolkit::DevelControl::State>(*valuePtr, ControlStateTable, ControlStateTableCount, state))
1165 controlImpl.mImpl->SetState(state, withTransitions);
1171 case Toolkit::DevelControl::Property::SUB_STATE:
1173 std::string subState;
1174 if(value.Get(subState))
1176 controlImpl.mImpl->SetSubState(subState);
1181 case Toolkit::DevelControl::Property::LEFT_FOCUSABLE_ACTOR_ID:
1184 if(value.Get(focusId))
1186 controlImpl.mImpl->mLeftFocusableActorId = focusId;
1191 case Toolkit::DevelControl::Property::RIGHT_FOCUSABLE_ACTOR_ID:
1194 if(value.Get(focusId))
1196 controlImpl.mImpl->mRightFocusableActorId = focusId;
1201 case Toolkit::DevelControl::Property::UP_FOCUSABLE_ACTOR_ID:
1204 if(value.Get(focusId))
1206 controlImpl.mImpl->mUpFocusableActorId = focusId;
1211 case Toolkit::DevelControl::Property::DOWN_FOCUSABLE_ACTOR_ID:
1214 if(value.Get(focusId))
1216 controlImpl.mImpl->mDownFocusableActorId = focusId;
1221 case Toolkit::Control::Property::KEY_INPUT_FOCUS:
1223 if(value.Get<bool>())
1225 controlImpl.SetKeyInputFocus();
1229 controlImpl.ClearKeyInputFocus();
1234 case Toolkit::Control::Property::BACKGROUND:
1238 const Property::Map* map = value.GetMap();
1239 if(map && !map->Empty())
1241 controlImpl.SetBackground(*map);
1243 else if(value.Get(url))
1245 // don't know the size to load
1246 Toolkit::Visual::Base visual = Toolkit::VisualFactory::Get().CreateVisual(url, ImageDimensions());
1249 controlImpl.mImpl->RegisterVisual(Toolkit::Control::Property::BACKGROUND, visual, DepthIndex::BACKGROUND);
1252 else if(value.Get(color))
1254 controlImpl.SetBackgroundColor(color);
1258 // The background is an empty property map, so we should clear the background
1259 controlImpl.ClearBackground();
1264 case Toolkit::Control::Property::MARGIN:
1267 if(value.Get(margin))
1269 controlImpl.mImpl->SetMargin(margin);
1274 case Toolkit::Control::Property::PADDING:
1277 if(value.Get(padding))
1279 controlImpl.mImpl->SetPadding(padding);
1284 case Toolkit::DevelControl::Property::TOOLTIP:
1286 TooltipPtr& tooltipPtr = controlImpl.mImpl->mTooltip;
1289 tooltipPtr = Tooltip::New(control);
1291 tooltipPtr->SetProperties(value);
1295 case Toolkit::DevelControl::Property::SHADOW:
1297 const Property::Map* map = value.GetMap();
1298 if(map && !map->Empty())
1300 controlImpl.mImpl->SetShadow(*map);
1304 // The shadow is an empty property map, so we should clear the shadow
1305 controlImpl.mImpl->ClearShadow();
1310 case Toolkit::DevelControl::Property::ACCESSIBILITY_NAME:
1315 controlImpl.mImpl->mAccessibilityName = name;
1320 case Toolkit::DevelControl::Property::ACCESSIBILITY_DESCRIPTION:
1325 controlImpl.mImpl->mAccessibilityDescription = text;
1330 case Toolkit::DevelControl::Property::ACCESSIBILITY_TRANSLATION_DOMAIN:
1335 controlImpl.mImpl->mAccessibilityTranslationDomain = text;
1340 case Toolkit::DevelControl::Property::ACCESSIBILITY_ROLE:
1342 Dali::Accessibility::Role role;
1345 controlImpl.mImpl->mAccessibilityRole = role;
1350 case Toolkit::DevelControl::Property::ACCESSIBILITY_HIGHLIGHTABLE:
1353 if(value.Get(highlightable))
1355 controlImpl.mImpl->mAccessibilityHighlightable = highlightable;
1360 case Toolkit::DevelControl::Property::ACCESSIBILITY_ATTRIBUTES:
1362 const Property::Map* map = value.GetMap();
1363 if(map && !map->Empty())
1365 controlImpl.mImpl->mAccessibilityAttributes = *map;
1370 case Toolkit::DevelControl::Property::DISPATCH_KEY_EVENTS:
1373 if(value.Get(dispatch))
1375 controlImpl.mImpl->mDispatchKeyEvents = dispatch;
1380 case Toolkit::DevelControl::Property::ACCESSIBILITY_HIDDEN:
1383 if(value.Get(hidden))
1385 controlImpl.mImpl->mAccessibilityHidden = hidden;
1387 auto* accessible = controlImpl.GetAccessibleObject();
1388 auto* parent = dynamic_cast<Dali::Accessibility::ActorAccessible*>(accessible->GetParent());
1391 parent->OnChildrenChanged();
1396 case Toolkit::DevelControl::Property::CLOCKWISE_FOCUSABLE_ACTOR_ID:
1399 if(value.Get(focusId))
1401 controlImpl.mImpl->mClockwiseFocusableActorId = focusId;
1405 case Toolkit::DevelControl::Property::COUNTER_CLOCKWISE_FOCUSABLE_ACTOR_ID:
1408 if(value.Get(focusId))
1410 controlImpl.mImpl->mCounterClockwiseFocusableActorId = focusId;
1415 case Toolkit::DevelControl::Property::AUTOMATION_ID:
1417 std::string automationId;
1418 if(value.Get(automationId))
1420 controlImpl.mImpl->mAutomationId = automationId;
1428 Property::Value Control::Impl::GetProperty(BaseObject* object, Property::Index index)
1430 Property::Value value;
1432 Toolkit::Control control = Toolkit::Control::DownCast(BaseHandle(object));
1436 Control& controlImpl(GetImplementation(control));
1440 case Toolkit::Control::Property::STYLE_NAME:
1442 value = controlImpl.GetStyleName();
1446 case Toolkit::DevelControl::Property::STATE:
1448 value = controlImpl.mImpl->mState;
1452 case Toolkit::DevelControl::Property::SUB_STATE:
1454 value = controlImpl.mImpl->mSubStateName;
1458 case Toolkit::DevelControl::Property::LEFT_FOCUSABLE_ACTOR_ID:
1460 value = controlImpl.mImpl->mLeftFocusableActorId;
1464 case Toolkit::DevelControl::Property::RIGHT_FOCUSABLE_ACTOR_ID:
1466 value = controlImpl.mImpl->mRightFocusableActorId;
1470 case Toolkit::DevelControl::Property::UP_FOCUSABLE_ACTOR_ID:
1472 value = controlImpl.mImpl->mUpFocusableActorId;
1476 case Toolkit::DevelControl::Property::DOWN_FOCUSABLE_ACTOR_ID:
1478 value = controlImpl.mImpl->mDownFocusableActorId;
1482 case Toolkit::Control::Property::KEY_INPUT_FOCUS:
1484 value = controlImpl.HasKeyInputFocus();
1488 case Toolkit::Control::Property::BACKGROUND:
1491 Toolkit::Visual::Base visual = controlImpl.mImpl->GetVisual(Toolkit::Control::Property::BACKGROUND);
1494 visual.CreatePropertyMap(map);
1501 case Toolkit::Control::Property::MARGIN:
1503 value = controlImpl.mImpl->GetMargin();
1507 case Toolkit::Control::Property::PADDING:
1509 value = controlImpl.mImpl->GetPadding();
1513 case Toolkit::DevelControl::Property::TOOLTIP:
1516 if(controlImpl.mImpl->mTooltip)
1518 controlImpl.mImpl->mTooltip->CreatePropertyMap(map);
1524 case Toolkit::DevelControl::Property::SHADOW:
1527 Toolkit::Visual::Base visual = controlImpl.mImpl->GetVisual(Toolkit::DevelControl::Property::SHADOW);
1530 visual.CreatePropertyMap(map);
1537 case Toolkit::DevelControl::Property::ACCESSIBILITY_NAME:
1539 value = controlImpl.mImpl->mAccessibilityName;
1543 case Toolkit::DevelControl::Property::ACCESSIBILITY_DESCRIPTION:
1545 value = controlImpl.mImpl->mAccessibilityDescription;
1549 case Toolkit::DevelControl::Property::ACCESSIBILITY_TRANSLATION_DOMAIN:
1551 value = controlImpl.mImpl->mAccessibilityTranslationDomain;
1555 case Toolkit::DevelControl::Property::ACCESSIBILITY_ROLE:
1557 value = Property::Value(controlImpl.mImpl->mAccessibilityRole);
1561 case Toolkit::DevelControl::Property::ACCESSIBILITY_HIGHLIGHTABLE:
1563 value = controlImpl.mImpl->mAccessibilityHighlightable;
1567 case Toolkit::DevelControl::Property::ACCESSIBILITY_ATTRIBUTES:
1569 value = controlImpl.mImpl->mAccessibilityAttributes;
1573 case Toolkit::DevelControl::Property::DISPATCH_KEY_EVENTS:
1575 value = controlImpl.mImpl->mDispatchKeyEvents;
1579 case Toolkit::DevelControl::Property::ACCESSIBILITY_HIDDEN:
1581 value = controlImpl.mImpl->mAccessibilityHidden;
1585 case Toolkit::DevelControl::Property::CLOCKWISE_FOCUSABLE_ACTOR_ID:
1587 value = controlImpl.mImpl->mClockwiseFocusableActorId;
1591 case Toolkit::DevelControl::Property::COUNTER_CLOCKWISE_FOCUSABLE_ACTOR_ID:
1593 value = controlImpl.mImpl->mCounterClockwiseFocusableActorId;
1597 case Toolkit::DevelControl::Property::AUTOMATION_ID:
1599 value = controlImpl.mImpl->mAutomationId;
1608 void Control::Impl::RemoveAccessibilityAttribute(const std::string& key)
1610 Property::Value* value = mAccessibilityAttributes.Find(key);
1613 mAccessibilityAttributes[key] = Property::Value();
1617 void Control::Impl::ClearAccessibilityAttributes()
1619 mAccessibilityAttributes.Clear();
1622 void Control::Impl::SetAccessibilityReadingInfoType(const Dali::Accessibility::ReadingInfoTypes types)
1624 std::string value{};
1625 if(types[Dali::Accessibility::ReadingInfoType::NAME])
1627 value += READING_INFO_TYPE_NAME;
1629 if(types[Dali::Accessibility::ReadingInfoType::ROLE])
1633 value += READING_INFO_TYPE_SEPARATOR;
1635 value += READING_INFO_TYPE_ROLE;
1637 if(types[Dali::Accessibility::ReadingInfoType::DESCRIPTION])
1641 value += READING_INFO_TYPE_SEPARATOR;
1643 value += READING_INFO_TYPE_DESCRIPTION;
1645 if(types[Dali::Accessibility::ReadingInfoType::STATE])
1649 value += READING_INFO_TYPE_SEPARATOR;
1651 value += READING_INFO_TYPE_STATE;
1653 AppendAccessibilityAttribute(READING_INFO_TYPE_ATTRIBUTE_NAME, value);
1656 Dali::Accessibility::ReadingInfoTypes Control::Impl::GetAccessibilityReadingInfoType() const
1658 std::string value{};
1659 auto place = mAccessibilityAttributes.Find(READING_INFO_TYPE_ATTRIBUTE_NAME);
1666 Dali::Accessibility::ReadingInfoTypes types;
1667 types[Dali::Accessibility::ReadingInfoType::NAME] = true;
1668 types[Dali::Accessibility::ReadingInfoType::ROLE] = true;
1669 types[Dali::Accessibility::ReadingInfoType::DESCRIPTION] = true;
1670 types[Dali::Accessibility::ReadingInfoType::STATE] = true;
1679 Dali::Accessibility::ReadingInfoTypes types;
1681 if(value.find(READING_INFO_TYPE_NAME) != std::string::npos)
1683 types[Dali::Accessibility::ReadingInfoType::NAME] = true;
1685 if(value.find(READING_INFO_TYPE_ROLE) != std::string::npos)
1687 types[Dali::Accessibility::ReadingInfoType::ROLE] = true;
1689 if(value.find(READING_INFO_TYPE_DESCRIPTION) != std::string::npos)
1691 types[Dali::Accessibility::ReadingInfoType::DESCRIPTION] = true;
1693 if(value.find(READING_INFO_TYPE_STATE) != std::string::npos)
1695 types[Dali::Accessibility::ReadingInfoType::STATE] = true;
1701 void Control::Impl::CopyInstancedProperties(RegisteredVisualContainer& visuals, Dictionary<Property::Map>& instancedProperties)
1703 for(RegisteredVisualContainer::Iterator iter = visuals.Begin(); iter != visuals.End(); iter++)
1707 Property::Map instanceMap;
1708 Toolkit::GetImplementation((*iter)->visual).CreateInstancePropertyMap(instanceMap);
1709 instancedProperties.Add((*iter)->visual.GetName(), instanceMap);
1714 void Control::Impl::RemoveVisual(RegisteredVisualContainer& visuals, const std::string& visualName)
1716 Actor self(mControlImpl.Self());
1718 for(RegisteredVisualContainer::Iterator visualIter = visuals.Begin();
1719 visualIter != visuals.End();
1722 Toolkit::Visual::Base visual = (*visualIter)->visual;
1723 if(visual && visual.GetName() == visualName)
1725 Toolkit::GetImplementation(visual).SetOffScene(self);
1726 (*visualIter)->visual.Reset();
1727 visuals.Erase(visualIter);
1733 void Control::Impl::RemoveVisuals(RegisteredVisualContainer& visuals, DictionaryKeys& removeVisuals)
1735 Actor self(mControlImpl.Self());
1736 for(DictionaryKeys::iterator iter = removeVisuals.begin(); iter != removeVisuals.end(); ++iter)
1738 const std::string visualName = *iter;
1739 RemoveVisual(visuals, visualName);
1743 void Control::Impl::RecreateChangedVisuals(Dictionary<Property::Map>& stateVisualsToChange,
1744 Dictionary<Property::Map>& instancedProperties)
1746 Dali::CustomActor handle(mControlImpl.GetOwner());
1747 for(Dictionary<Property::Map>::iterator iter = stateVisualsToChange.Begin();
1748 iter != stateVisualsToChange.End();
1751 const std::string& visualName = (*iter).key;
1752 const Property::Map& toMap = (*iter).entry;
1754 Actor self = mControlImpl.Self();
1755 RegisteredVisualContainer::Iterator registeredVisualsiter;
1756 // Check if visual (visualName) is already registered, this is the current visual.
1757 if(FindVisual(visualName, mVisuals, registeredVisualsiter))
1759 Toolkit::Visual::Base& visual = (*registeredVisualsiter)->visual;
1762 // No longer required to know if the replaced visual's resources are ready
1763 StopObservingVisual(visual);
1765 // If control staged then visuals will be swapped once ready
1766 if(self.GetProperty<bool>(Actor::Property::CONNECTED_TO_SCENE))
1768 // Check if visual is currently in the process of being replaced ( is in removal container )
1769 RegisteredVisualContainer::Iterator visualQueuedForRemoval;
1770 if(FindVisual(visualName, mRemoveVisuals, visualQueuedForRemoval))
1772 // Visual with same visual name is already in removal container so current visual pending
1773 // Only the the last requested visual will be displayed so remove current visual which is staged but not ready.
1774 Toolkit::GetImplementation(visual).SetOffScene(self);
1775 (*registeredVisualsiter)->visual.Reset();
1776 mVisuals.Erase(registeredVisualsiter);
1780 // current visual not already in removal container so add now.
1781 DALI_LOG_INFO(gLogFilter, Debug::Verbose, "RegisterVisual Move current registered visual to removal Queue: %s \n", visualName.c_str());
1782 MoveVisual(registeredVisualsiter, mVisuals, mRemoveVisuals);
1787 // Control not staged or visual disabled so can just erase from registered visuals and new visual will be added later.
1788 (*registeredVisualsiter)->visual.Reset();
1789 mVisuals.Erase(registeredVisualsiter);
1793 const Property::Map* instancedMap = instancedProperties.FindConst(visualName);
1794 Style::ApplyVisual(handle, visualName, toMap, instancedMap);
1799 void Control::Impl::ReplaceStateVisualsAndProperties(const StylePtr oldState, const StylePtr newState, const std::string& subState)
1801 // Collect all old visual names
1802 DictionaryKeys stateVisualsToRemove;
1805 oldState->visuals.GetKeys(stateVisualsToRemove);
1806 if(!subState.empty())
1808 const StylePtr* oldSubState = oldState->subStates.FindConst(subState);
1811 DictionaryKeys subStateVisualsToRemove;
1812 (*oldSubState)->visuals.GetKeys(subStateVisualsToRemove);
1813 Merge(stateVisualsToRemove, subStateVisualsToRemove);
1818 // Collect all new visual properties
1819 Dictionary<Property::Map> stateVisualsToAdd;
1822 stateVisualsToAdd = newState->visuals;
1823 if(!subState.empty())
1825 const StylePtr* newSubState = newState->subStates.FindConst(subState);
1828 stateVisualsToAdd.Merge((*newSubState)->visuals);
1833 // If a name is in both add/remove, move it to change list.
1834 Dictionary<Property::Map> stateVisualsToChange;
1835 FindChangableVisuals(stateVisualsToAdd, stateVisualsToChange, stateVisualsToRemove);
1837 // Copy instanced properties (e.g. text label) of current visuals
1838 Dictionary<Property::Map> instancedProperties;
1839 CopyInstancedProperties(mVisuals, instancedProperties);
1841 // For each visual in remove list, remove from mVisuals
1842 RemoveVisuals(mVisuals, stateVisualsToRemove);
1844 // For each visual in add list, create and add to mVisuals
1845 Dali::CustomActor handle(mControlImpl.GetOwner());
1846 Style::ApplyVisuals(handle, stateVisualsToAdd, instancedProperties);
1848 // For each visual in change list, if it requires a new visual,
1849 // remove old visual, create and add to mVisuals
1850 RecreateChangedVisuals(stateVisualsToChange, instancedProperties);
1853 void Control::Impl::SetState(DevelControl::State newState, bool withTransitions)
1855 DevelControl::State oldState = mState;
1856 Dali::CustomActor handle(mControlImpl.GetOwner());
1857 DALI_LOG_INFO(gLogFilter, Debug::Concise, "Control::Impl::SetState: %s\n", (mState == DevelControl::NORMAL ? "NORMAL" : (mState == DevelControl::FOCUSED ? "FOCUSED" : (mState == DevelControl::DISABLED ? "DISABLED" : "NONE"))));
1859 if(mState != newState)
1861 // If mState was Disabled, and new state is Focused, should probably
1862 // store that fact, e.g. in another property that FocusManager can access.
1865 // Trigger state change and transitions
1866 // Apply new style, if stylemanager is available
1867 Toolkit::StyleManager styleManager = Toolkit::StyleManager::Get();
1870 const StylePtr stylePtr = GetImpl(styleManager).GetRecordedStyle(Toolkit::Control(mControlImpl.GetOwner()));
1874 std::string oldStateName = Scripting::GetEnumerationName<Toolkit::DevelControl::State>(oldState, ControlStateTable, ControlStateTableCount);
1875 std::string newStateName = Scripting::GetEnumerationName<Toolkit::DevelControl::State>(newState, ControlStateTable, ControlStateTableCount);
1877 const StylePtr* newStateStyle = stylePtr->subStates.Find(newStateName);
1878 const StylePtr* oldStateStyle = stylePtr->subStates.Find(oldStateName);
1879 if(oldStateStyle && newStateStyle)
1881 // Only change if both state styles exist
1882 ReplaceStateVisualsAndProperties(*oldStateStyle, *newStateStyle, mSubStateName);
1889 void Control::Impl::SetSubState(const std::string& subStateName, bool withTransitions)
1891 if(mSubStateName != subStateName)
1893 // Get existing sub-state visuals, and unregister them
1894 Dali::CustomActor handle(mControlImpl.GetOwner());
1896 Toolkit::StyleManager styleManager = Toolkit::StyleManager::Get();
1899 const StylePtr stylePtr = GetImpl(styleManager).GetRecordedStyle(Toolkit::Control(mControlImpl.GetOwner()));
1903 std::string stateName = Scripting::GetEnumerationName<Toolkit::DevelControl::State>(mState, ControlStateTable, ControlStateTableCount);
1905 const StylePtr* state = stylePtr->subStates.Find(stateName);
1908 StylePtr stateStyle(*state);
1910 const StylePtr* newStateStyle = stateStyle->subStates.Find(subStateName);
1911 const StylePtr* oldStateStyle = stateStyle->subStates.Find(mSubStateName);
1912 if(oldStateStyle && newStateStyle)
1915 ReplaceStateVisualsAndProperties(*oldStateStyle, *newStateStyle, empty);
1921 mSubStateName = subStateName;
1925 void Control::Impl::OnSceneDisconnection()
1927 Actor self = mControlImpl.Self();
1929 // Any visuals set for replacement but not yet ready should still be registered.
1930 // Reason: If a request was made to register a new visual but the control removed from scene before visual was ready
1931 // then when this control appears back on stage it should use that new visual.
1933 // Iterate through all registered visuals and set off scene
1934 SetVisualsOffScene(mVisuals, self);
1936 // Visuals pending replacement can now be taken out of the removal list and set off scene
1937 // Iterate through all replacement visuals and add to a move queue then set off scene
1938 for(auto removalIter = mRemoveVisuals.Begin(), end = mRemoveVisuals.End(); removalIter != end; removalIter++)
1940 Toolkit::GetImplementation((*removalIter)->visual).SetOffScene(self);
1943 for(auto replacedIter = mVisuals.Begin(), end = mVisuals.End(); replacedIter != end; replacedIter++)
1945 (*replacedIter)->pending = false;
1948 mRemoveVisuals.Clear();
1951 void Control::Impl::SetMargin(Extents margin)
1953 mControlImpl.mImpl->mMargin = margin;
1955 // Trigger a size negotiation request that may be needed when setting a margin.
1956 mControlImpl.RelayoutRequest();
1959 Extents Control::Impl::GetMargin() const
1961 return mControlImpl.mImpl->mMargin;
1964 void Control::Impl::SetPadding(Extents padding)
1966 mControlImpl.mImpl->mPadding = padding;
1968 // Trigger a size negotiation request that may be needed when setting a padding.
1969 mControlImpl.RelayoutRequest();
1972 Extents Control::Impl::GetPadding() const
1974 return mControlImpl.mImpl->mPadding;
1977 void Control::Impl::SetInputMethodContext(InputMethodContext& inputMethodContext)
1979 mInputMethodContext = inputMethodContext;
1982 bool Control::Impl::FilterKeyEvent(const KeyEvent& event)
1984 bool consumed(false);
1986 if(mInputMethodContext)
1988 consumed = mInputMethodContext.FilterEventKey(event);
1993 DevelControl::VisualEventSignalType& Control::Impl::VisualEventSignal()
1995 return mVisualEventSignal;
1998 void Control::Impl::SetShadow(const Property::Map& map)
2000 Toolkit::Visual::Base visual = Toolkit::VisualFactory::Get().CreateVisual(map);
2001 visual.SetName("shadow");
2005 mControlImpl.mImpl->RegisterVisual(Toolkit::DevelControl::Property::SHADOW, visual, DepthIndex::BACKGROUND_EFFECT);
2007 mControlImpl.RelayoutRequest();
2011 void Control::Impl::ClearShadow()
2013 mControlImpl.mImpl->UnregisterVisual(Toolkit::DevelControl::Property::SHADOW);
2015 // Trigger a size negotiation request that may be needed when unregistering a visual.
2016 mControlImpl.RelayoutRequest();
2019 Dali::Property Control::Impl::GetVisualProperty(Dali::Property::Index index, Dali::Property::Key visualPropertyKey)
2021 Toolkit::Visual::Base visual = GetVisualByIndex(mVisuals, index);
2024 Internal::Visual::Base& visualImpl = Toolkit::GetImplementation(visual);
2025 return visualImpl.GetPropertyObject(visualPropertyKey);
2029 return Dali::Property(handle, Property::INVALID_INDEX);
2032 void Control::Impl::CreateTransitions(std::vector<std::pair<Dali::Property::Index, Dali::Property::Map>>& sourceProperties,
2033 std::vector<std::pair<Dali::Property::Index, Dali::Property::Map>>& destinationProperties,
2034 Dali::Toolkit::Control source,
2035 Dali::Toolkit::Control destination)
2037 // Retrieves background properties to be transitioned.
2038 Dali::Property::Map backgroundSourcePropertyMap, backgroundDestinationPropertyMap;
2039 mControlImpl.MakeVisualTransition(backgroundSourcePropertyMap, backgroundDestinationPropertyMap, source, destination, Toolkit::Control::Property::BACKGROUND);
2040 if(backgroundSourcePropertyMap.Count() > 0)
2042 sourceProperties.push_back(std::pair<Dali::Property::Index, Dali::Property::Map>(Toolkit::Control::Property::BACKGROUND, backgroundSourcePropertyMap));
2043 destinationProperties.push_back(std::pair<Dali::Property::Index, Dali::Property::Map>(Toolkit::Control::Property::BACKGROUND, backgroundDestinationPropertyMap));
2046 // Retrieves shadow properties to be transitioned.
2047 Dali::Property::Map shadowSourcePropertyMap, shadowDestinationPropertyMap;
2048 mControlImpl.MakeVisualTransition(shadowSourcePropertyMap, shadowDestinationPropertyMap, source, destination, Toolkit::DevelControl::Property::SHADOW);
2049 if(shadowSourcePropertyMap.Count() > 0)
2051 sourceProperties.push_back(std::pair<Dali::Property::Index, Dali::Property::Map>(Toolkit::DevelControl::Property::SHADOW, shadowSourcePropertyMap));
2052 destinationProperties.push_back(std::pair<Dali::Property::Index, Dali::Property::Map>(Toolkit::DevelControl::Property::SHADOW, shadowDestinationPropertyMap));
2055 // Retrieves transition from inherited class.
2056 mControlImpl.OnCreateTransitions(sourceProperties, destinationProperties, source, destination);
2059 void Control::Impl::UpdateVisualProperties(const std::vector<std::pair<Dali::Property::Index, Dali::Property::Map>>& properties)
2061 for(auto&& data : properties)
2063 if(data.first == Toolkit::Control::Property::BACKGROUND)
2065 DoAction(Toolkit::Control::Property::BACKGROUND, DevelVisual::Action::UPDATE_PROPERTY, data.second);
2067 else if(data.first == Toolkit::DevelControl::Property::SHADOW)
2069 DoAction(Toolkit::DevelControl::Property::SHADOW, DevelVisual::Action::UPDATE_PROPERTY, data.second);
2072 mControlImpl.OnUpdateVisualProperties(properties);
2075 void Control::Impl::EmitResourceReadySignal()
2077 if(!mIsEmittingResourceReadySignal)
2079 // Guard against calls to emit the signal during the callback
2080 mIsEmittingResourceReadySignal = true;
2082 // If the signal handler changes visual, it may become ready during this call & therefore this method will
2083 // get called again recursively. If so, mNeedToEmitResourceReady is set below, and we act on it after that secondary
2084 // invocation has completed by notifying in an Idle callback to prevent further recursion.
2085 Dali::Toolkit::Control handle(mControlImpl.GetOwner());
2086 mResourceReadySignal.Emit(handle);
2088 if(mNeedToEmitResourceReady)
2090 // Add idler to emit the signal again
2093 // The callback manager takes the ownership of the callback object.
2094 mIdleCallback = MakeCallback(this, &Control::Impl::OnIdleCallback);
2095 Adaptor::Get().AddIdle(mIdleCallback, false);
2099 mIsEmittingResourceReadySignal = false;
2103 mNeedToEmitResourceReady = true;
2107 void Control::Impl::OnIdleCallback()
2109 if(mNeedToEmitResourceReady)
2112 mNeedToEmitResourceReady = false;
2114 // A visual is ready so control may need relayouting if staged
2115 if(mControlImpl.Self().GetProperty<bool>(Actor::Property::CONNECTED_TO_SCENE))
2117 mControlImpl.RelayoutRequest();
2120 EmitResourceReadySignal();
2123 // Set the pointer to null as the callback manager deletes the callback after execute it.
2124 mIdleCallback = nullptr;
2127 Toolkit::DevelControl::ControlAccessible* Control::Impl::GetAccessibleObject()
2129 if(!mAccessibleObject)
2131 mAccessibleObject.reset(mControlImpl.CreateAccessibleObject());
2134 return mAccessibleObject.get();
2137 } // namespace Internal
2139 } // namespace Toolkit