2 * Copyright (c) 2023 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)
133 * Finds visual in given array, returning true if found along with the iterator for that visual as a out parameter
135 bool FindVisual(const Toolkit::Visual::Base findVisual, const RegisteredVisualContainer& visuals, RegisteredVisualContainer::Iterator& iter)
137 for(iter = visuals.Begin(); iter != visuals.End(); iter++)
139 Toolkit::Visual::Base visual = (*iter)->visual;
140 if(visual && visual == findVisual)
149 * Finds internal visual in given array, returning true if found along with the iterator for that visual as a out parameter
151 bool FindVisual(const Visual::Base& findInternalVisual, const RegisteredVisualContainer& visuals, RegisteredVisualContainer::Iterator& iter)
153 for(iter = visuals.Begin(); iter != visuals.End(); iter++)
155 Visual::Base& visual = Toolkit::GetImplementation((*iter)->visual);
156 if((&visual == &findInternalVisual))
164 void FindChangableVisuals(Dictionary<Property::Map>& stateVisualsToAdd,
165 Dictionary<Property::Map>& stateVisualsToChange,
166 DictionaryKeys& stateVisualsToRemove)
168 DictionaryKeys copyOfStateVisualsToRemove = stateVisualsToRemove;
170 for(DictionaryKeys::iterator iter = copyOfStateVisualsToRemove.begin();
171 iter != copyOfStateVisualsToRemove.end();
174 const std::string& visualName = (*iter);
175 Property::Map* toMap = stateVisualsToAdd.Find(visualName);
178 stateVisualsToChange.Add(visualName, *toMap);
179 stateVisualsToAdd.Remove(visualName);
180 Remove(stateVisualsToRemove, visualName);
185 Toolkit::Visual::Base GetVisualByName(
186 const RegisteredVisualContainer& visuals,
187 const std::string& visualName)
189 Toolkit::Visual::Base visualHandle;
191 RegisteredVisualContainer::Iterator iter;
192 for(iter = visuals.Begin(); iter != visuals.End(); iter++)
194 Toolkit::Visual::Base visual = (*iter)->visual;
195 if(visual && visual.GetName() == visualName)
197 visualHandle = visual;
204 Toolkit::Visual::Base GetVisualByIndex(
205 const RegisteredVisualContainer& visuals,
206 Property::Index index)
208 Toolkit::Visual::Base visualHandle;
210 RegisteredVisualContainer::Iterator iter;
211 for(iter = visuals.Begin(); iter != visuals.End(); iter++)
213 if((*iter)->index == index)
215 visualHandle = (*iter)->visual;
223 * Move visual from source to destination container
225 void MoveVisual(RegisteredVisualContainer::Iterator sourceIter, RegisteredVisualContainer& source, RegisteredVisualContainer& destination)
227 Toolkit::Visual::Base visual = (*sourceIter)->visual;
230 RegisteredVisual* rv = source.Release(sourceIter);
231 destination.PushBack(rv);
236 * Performs actions as requested using the action name.
237 * @param[in] object The object on which to perform the action.
238 * @param[in] actionName The action to perform.
239 * @param[in] attributes The attributes with which to perfrom this action.
240 * @return true if action has been accepted by this control
242 const char* ACTION_ACCESSIBILITY_ACTIVATED = "accessibilityActivated";
243 const char* ACTION_ACCESSIBILITY_READING_CANCELLED = "ReadingCancelled";
244 const char* ACTION_ACCESSIBILITY_READING_PAUSED = "ReadingPaused";
245 const char* ACTION_ACCESSIBILITY_READING_RESUMED = "ReadingResumed";
246 const char* ACTION_ACCESSIBILITY_READING_SKIPPED = "ReadingSkipped";
247 const char* ACTION_ACCESSIBILITY_READING_STOPPED = "ReadingStopped";
249 static bool DoAction(BaseObject* object, const std::string& actionName, const Property::Map& attributes)
253 Dali::BaseHandle handle(object);
255 Toolkit::Control control = Toolkit::Control::DownCast(handle);
257 DALI_ASSERT_ALWAYS(control);
259 if(0 == strcmp(actionName.c_str(), ACTION_ACCESSIBILITY_ACTIVATED) || actionName == "activate")
261 // if cast succeeds there is an implementation so no need to check
262 if(!DevelControl::AccessibilityActivateSignal(control).Empty())
264 DevelControl::AccessibilityActivateSignal(control).Emit();
268 ret = Internal::GetImplementation(control).OnAccessibilityActivated();
271 else if(0 == strcmp(actionName.c_str(), ACTION_ACCESSIBILITY_READING_SKIPPED))
273 // if cast succeeds there is an implementation so no need to check
274 if(!DevelControl::AccessibilityReadingSkippedSignal(control).Empty())
276 DevelControl::AccessibilityReadingSkippedSignal(control).Emit();
279 else if(0 == strcmp(actionName.c_str(), ACTION_ACCESSIBILITY_READING_PAUSED))
281 // if cast succeeds there is an implementation so no need to check
282 if(!DevelControl::AccessibilityReadingPausedSignal(control).Empty())
284 DevelControl::AccessibilityReadingPausedSignal(control).Emit();
287 else if(0 == strcmp(actionName.c_str(), ACTION_ACCESSIBILITY_READING_RESUMED))
289 // if cast succeeds there is an implementation so no need to check
290 if(!DevelControl::AccessibilityReadingResumedSignal(control).Empty())
292 DevelControl::AccessibilityReadingResumedSignal(control).Emit();
295 else if(0 == strcmp(actionName.c_str(), ACTION_ACCESSIBILITY_READING_CANCELLED))
297 // if cast succeeds there is an implementation so no need to check
298 if(!DevelControl::AccessibilityReadingCancelledSignal(control).Empty())
300 DevelControl::AccessibilityReadingCancelledSignal(control).Emit();
303 else if(0 == strcmp(actionName.c_str(), ACTION_ACCESSIBILITY_READING_STOPPED))
305 // if cast succeeds there is an implementation so no need to check
306 if(!DevelControl::AccessibilityReadingStoppedSignal(control).Empty())
308 DevelControl::AccessibilityReadingStoppedSignal(control).Emit();
319 * Connects a callback function with the object's signals.
320 * @param[in] object The object providing the signal.
321 * @param[in] tracker Used to disconnect the signal.
322 * @param[in] signalName The signal to connect to.
323 * @param[in] functor A newly allocated FunctorDelegate.
324 * @return True if the signal was connected.
325 * @post If a signal was connected, ownership of functor was passed to CallbackBase. Otherwise the caller is responsible for deleting the unused functor.
327 const char* SIGNAL_KEY_EVENT = "keyEvent";
328 const char* SIGNAL_KEY_INPUT_FOCUS_GAINED = "keyInputFocusGained";
329 const char* SIGNAL_KEY_INPUT_FOCUS_LOST = "keyInputFocusLost";
330 const char* SIGNAL_TAPPED = "tapped";
331 const char* SIGNAL_PANNED = "panned";
332 const char* SIGNAL_PINCHED = "pinched";
333 const char* SIGNAL_LONG_PRESSED = "longPressed";
334 const char* SIGNAL_GET_NAME = "getName";
335 const char* SIGNAL_GET_DESCRIPTION = "getDescription";
336 const char* SIGNAL_DO_GESTURE = "doGesture";
337 static bool DoConnectSignal(BaseObject* object, ConnectionTrackerInterface* tracker, const std::string& signalName, FunctorDelegate* functor)
339 Dali::BaseHandle handle(object);
341 bool connected(false);
342 Toolkit::Control control = Toolkit::Control::DownCast(handle);
345 Internal::Control& controlImpl(Internal::GetImplementation(control));
348 if(0 == strcmp(signalName.c_str(), SIGNAL_KEY_EVENT))
350 controlImpl.KeyEventSignal().Connect(tracker, functor);
352 else if(0 == strcmp(signalName.c_str(), SIGNAL_KEY_INPUT_FOCUS_GAINED))
354 controlImpl.KeyInputFocusGainedSignal().Connect(tracker, functor);
356 else if(0 == strcmp(signalName.c_str(), SIGNAL_KEY_INPUT_FOCUS_LOST))
358 controlImpl.KeyInputFocusLostSignal().Connect(tracker, functor);
360 else if(0 == strcmp(signalName.c_str(), SIGNAL_TAPPED))
362 controlImpl.EnableGestureDetection(GestureType::TAP);
363 controlImpl.GetTapGestureDetector().DetectedSignal().Connect(tracker, functor);
365 else if(0 == strcmp(signalName.c_str(), SIGNAL_PANNED))
367 controlImpl.EnableGestureDetection(GestureType::PAN);
368 controlImpl.GetPanGestureDetector().DetectedSignal().Connect(tracker, functor);
370 else if(0 == strcmp(signalName.c_str(), SIGNAL_PINCHED))
372 controlImpl.EnableGestureDetection(GestureType::PINCH);
373 controlImpl.GetPinchGestureDetector().DetectedSignal().Connect(tracker, functor);
375 else if(0 == strcmp(signalName.c_str(), SIGNAL_LONG_PRESSED))
377 controlImpl.EnableGestureDetection(GestureType::LONG_PRESS);
378 controlImpl.GetLongPressGestureDetector().DetectedSignal().Connect(tracker, functor);
380 else if(0 == strcmp(signalName.c_str(), SIGNAL_GET_NAME))
382 DevelControl::AccessibilityGetNameSignal(control).Connect(tracker, functor);
384 else if(0 == strcmp(signalName.c_str(), SIGNAL_GET_DESCRIPTION))
386 DevelControl::AccessibilityGetDescriptionSignal(control).Connect(tracker, functor);
388 else if(0 == strcmp(signalName.c_str(), SIGNAL_DO_GESTURE))
390 DevelControl::AccessibilityDoGestureSignal(control).Connect(tracker, functor);
397 * Creates control through type registry
401 return Internal::Control::New();
403 // Setup signals and actions using the type-registry.
404 DALI_TYPE_REGISTRATION_BEGIN(Control, CustomActor, Create);
406 // Note: Properties are registered separately below.
408 SignalConnectorType registerSignal1(typeRegistration, SIGNAL_KEY_EVENT, &DoConnectSignal);
409 SignalConnectorType registerSignal2(typeRegistration, SIGNAL_KEY_INPUT_FOCUS_GAINED, &DoConnectSignal);
410 SignalConnectorType registerSignal3(typeRegistration, SIGNAL_KEY_INPUT_FOCUS_LOST, &DoConnectSignal);
411 SignalConnectorType registerSignal4(typeRegistration, SIGNAL_TAPPED, &DoConnectSignal);
412 SignalConnectorType registerSignal5(typeRegistration, SIGNAL_PANNED, &DoConnectSignal);
413 SignalConnectorType registerSignal6(typeRegistration, SIGNAL_PINCHED, &DoConnectSignal);
414 SignalConnectorType registerSignal7(typeRegistration, SIGNAL_LONG_PRESSED, &DoConnectSignal);
415 SignalConnectorType registerSignal8(typeRegistration, SIGNAL_GET_NAME, &DoConnectSignal);
416 SignalConnectorType registerSignal9(typeRegistration, SIGNAL_GET_DESCRIPTION, &DoConnectSignal);
417 SignalConnectorType registerSignal10(typeRegistration, SIGNAL_DO_GESTURE, &DoConnectSignal);
419 TypeAction registerAction1(typeRegistration, "activate", &DoAction);
420 TypeAction registerAction2(typeRegistration, ACTION_ACCESSIBILITY_ACTIVATED, &DoAction);
421 TypeAction registerAction3(typeRegistration, ACTION_ACCESSIBILITY_READING_SKIPPED, &DoAction);
422 TypeAction registerAction4(typeRegistration, ACTION_ACCESSIBILITY_READING_CANCELLED, &DoAction);
423 TypeAction registerAction5(typeRegistration, ACTION_ACCESSIBILITY_READING_STOPPED, &DoAction);
424 TypeAction registerAction6(typeRegistration, ACTION_ACCESSIBILITY_READING_PAUSED, &DoAction);
425 TypeAction registerAction7(typeRegistration, ACTION_ACCESSIBILITY_READING_RESUMED, &DoAction);
427 DALI_TYPE_REGISTRATION_END()
430 * @brief Iterate through given container and setOffScene any visual found
432 * @param[in] container Container of visuals
433 * @param[in] parent Parent actor to remove visuals from
435 void SetVisualsOffScene(const RegisteredVisualContainer& container, Actor parent)
437 for(auto iter = container.Begin(), end = container.End(); iter != end; iter++)
441 DALI_LOG_INFO(gLogFilter, Debug::Verbose, "Control::SetOffScene Setting visual(%d) off stage\n", (*iter)->index);
442 Toolkit::GetImplementation((*iter)->visual).SetOffScene(parent);
447 Dali::Rect<> GetShowingGeometry(Dali::Rect<> rect, Dali::Toolkit::DevelControl::ControlAccessible* accessible)
450 Vector2 currentPosition;
451 auto parent = dynamic_cast<Toolkit::DevelControl::ControlAccessible*>(accessible->GetParent());
455 parentRect = parent->GetExtents(Dali::Accessibility::CoordinateType::WINDOW);
457 currentPosition.x = rect.x;
458 currentPosition.y = rect.y;
460 rect.x = rect.x > parentRect.x ? rect.x : parentRect.x;
461 rect.y = rect.y > parentRect.y ? rect.y : parentRect.y;
462 rect.width = currentPosition.x + rect.width < parentRect.x + parentRect.width ? currentPosition.x + rect.width - rect.x : parentRect.x + parentRect.width - rect.x;
463 rect.height = currentPosition.y + rect.height < parentRect.y + parentRect.height ? currentPosition.y + rect.height - rect.y : parentRect.y + parentRect.height - rect.y;
465 if(rect.width < 0 || rect.height < 0)
470 parent = dynamic_cast<Toolkit::DevelControl::ControlAccessible*>(parent->GetParent());
476 static bool IsShowingGeometryOnScreen(Dali::Rect<> rect)
478 return rect.width > 0 && rect.height > 0;
481 Dali::Accessibility::Accessible* ExternalAccessibleGetter(Dali::Actor actor)
483 auto control = Toolkit::Control::DownCast(actor);
489 auto& controlImpl = Toolkit::Internal::GetImplementation(control);
491 return controlImpl.GetAccessibleObject();
494 } // unnamed namespace
497 // Properties registered without macro to use specific member variables.
498 const PropertyRegistration Control::Impl::PROPERTY_1(typeRegistration, "styleName", Toolkit::Control::Property::STYLE_NAME, Property::STRING, &Control::Impl::SetProperty, &Control::Impl::GetProperty);
499 const PropertyRegistration Control::Impl::PROPERTY_4(typeRegistration, "keyInputFocus", Toolkit::Control::Property::KEY_INPUT_FOCUS, Property::BOOLEAN, &Control::Impl::SetProperty, &Control::Impl::GetProperty);
500 const PropertyRegistration Control::Impl::PROPERTY_5(typeRegistration, "background", Toolkit::Control::Property::BACKGROUND, Property::MAP, &Control::Impl::SetProperty, &Control::Impl::GetProperty);
501 const PropertyRegistration Control::Impl::PROPERTY_6(typeRegistration, "margin", Toolkit::Control::Property::MARGIN, Property::EXTENTS, &Control::Impl::SetProperty, &Control::Impl::GetProperty);
502 const PropertyRegistration Control::Impl::PROPERTY_7(typeRegistration, "padding", Toolkit::Control::Property::PADDING, Property::EXTENTS, &Control::Impl::SetProperty, &Control::Impl::GetProperty);
503 const PropertyRegistration Control::Impl::PROPERTY_8(typeRegistration, "tooltip", Toolkit::DevelControl::Property::TOOLTIP, Property::MAP, &Control::Impl::SetProperty, &Control::Impl::GetProperty);
504 const PropertyRegistration Control::Impl::PROPERTY_9(typeRegistration, "state", Toolkit::DevelControl::Property::STATE, Property::STRING, &Control::Impl::SetProperty, &Control::Impl::GetProperty);
505 const PropertyRegistration Control::Impl::PROPERTY_10(typeRegistration, "subState", Toolkit::DevelControl::Property::SUB_STATE, Property::STRING, &Control::Impl::SetProperty, &Control::Impl::GetProperty);
506 const PropertyRegistration Control::Impl::PROPERTY_11(typeRegistration, "leftFocusableActorId", Toolkit::DevelControl::Property::LEFT_FOCUSABLE_ACTOR_ID, Property::INTEGER, &Control::Impl::SetProperty, &Control::Impl::GetProperty);
507 const PropertyRegistration Control::Impl::PROPERTY_12(typeRegistration, "rightFocusableActorId", Toolkit::DevelControl::Property::RIGHT_FOCUSABLE_ACTOR_ID, Property::INTEGER, &Control::Impl::SetProperty, &Control::Impl::GetProperty);
508 const PropertyRegistration Control::Impl::PROPERTY_13(typeRegistration, "upFocusableActorId", Toolkit::DevelControl::Property::UP_FOCUSABLE_ACTOR_ID, Property::INTEGER, &Control::Impl::SetProperty, &Control::Impl::GetProperty);
509 const PropertyRegistration Control::Impl::PROPERTY_14(typeRegistration, "downFocusableActorId", Toolkit::DevelControl::Property::DOWN_FOCUSABLE_ACTOR_ID, Property::INTEGER, &Control::Impl::SetProperty, &Control::Impl::GetProperty);
510 const PropertyRegistration Control::Impl::PROPERTY_15(typeRegistration, "shadow", Toolkit::DevelControl::Property::SHADOW, Property::MAP, &Control::Impl::SetProperty, &Control::Impl::GetProperty);
511 const PropertyRegistration Control::Impl::PROPERTY_16(typeRegistration, "accessibilityName", Toolkit::DevelControl::Property::ACCESSIBILITY_NAME, Property::STRING, &Control::Impl::SetProperty, &Control::Impl::GetProperty);
512 const PropertyRegistration Control::Impl::PROPERTY_17(typeRegistration, "accessibilityDescription", Toolkit::DevelControl::Property::ACCESSIBILITY_DESCRIPTION, Property::STRING, &Control::Impl::SetProperty, &Control::Impl::GetProperty);
513 const PropertyRegistration Control::Impl::PROPERTY_18(typeRegistration, "accessibilityTranslationDomain", Toolkit::DevelControl::Property::ACCESSIBILITY_TRANSLATION_DOMAIN, Property::STRING, &Control::Impl::SetProperty, &Control::Impl::GetProperty);
514 const PropertyRegistration Control::Impl::PROPERTY_19(typeRegistration, "accessibilityRole", Toolkit::DevelControl::Property::ACCESSIBILITY_ROLE, Property::INTEGER, &Control::Impl::SetProperty, &Control::Impl::GetProperty);
515 const PropertyRegistration Control::Impl::PROPERTY_20(typeRegistration, "accessibilityHighlightable", Toolkit::DevelControl::Property::ACCESSIBILITY_HIGHLIGHTABLE, Property::BOOLEAN, &Control::Impl::SetProperty, &Control::Impl::GetProperty);
516 const PropertyRegistration Control::Impl::PROPERTY_21(typeRegistration, "accessibilityAttributes", Toolkit::DevelControl::Property::ACCESSIBILITY_ATTRIBUTES, Property::MAP, &Control::Impl::SetProperty, &Control::Impl::GetProperty);
517 const PropertyRegistration Control::Impl::PROPERTY_22(typeRegistration, "dispatchKeyEvents", Toolkit::DevelControl::Property::DISPATCH_KEY_EVENTS, Property::BOOLEAN, &Control::Impl::SetProperty, &Control::Impl::GetProperty);
518 const PropertyRegistration Control::Impl::PROPERTY_23(typeRegistration, "accessibilityHidden", Toolkit::DevelControl::Property::ACCESSIBILITY_HIDDEN, Property::BOOLEAN, &Control::Impl::SetProperty, &Control::Impl::GetProperty);
519 const PropertyRegistration Control::Impl::PROPERTY_24(typeRegistration, "clockwiseFocusableActorId", Toolkit::DevelControl::Property::CLOCKWISE_FOCUSABLE_ACTOR_ID, Property::INTEGER, &Control::Impl::SetProperty, &Control::Impl::GetProperty);
520 const PropertyRegistration Control::Impl::PROPERTY_25(typeRegistration, "counterClockwiseFocusableActorId", Toolkit::DevelControl::Property::COUNTER_CLOCKWISE_FOCUSABLE_ACTOR_ID, Property::INTEGER, &Control::Impl::SetProperty, &Control::Impl::GetProperty);
521 const PropertyRegistration Control::Impl::PROPERTY_26(typeRegistration, "automationId", Toolkit::DevelControl::Property::AUTOMATION_ID, Property::STRING, &Control::Impl::SetProperty, &Control::Impl::GetProperty);
525 Control::Impl::Impl(Control& controlImpl)
526 : mControlImpl(controlImpl),
527 mState(Toolkit::DevelControl::NORMAL),
529 mLeftFocusableActorId(-1),
530 mRightFocusableActorId(-1),
531 mUpFocusableActorId(-1),
532 mDownFocusableActorId(-1),
533 mClockwiseFocusableActorId(-1),
534 mCounterClockwiseFocusableActorId(-1),
536 mBackgroundColor(Color::TRANSPARENT),
537 mStartingPinchScale(nullptr),
539 mPadding(0, 0, 0, 0),
541 mKeyInputFocusGainedSignal(),
542 mKeyInputFocusLostSignal(),
543 mResourceReadySignal(),
544 mVisualEventSignal(),
545 mAccessibilityGetNameSignal(),
546 mAccessibilityGetDescriptionSignal(),
547 mAccessibilityDoGestureSignal(),
548 mPinchGestureDetector(),
549 mPanGestureDetector(),
550 mTapGestureDetector(),
551 mLongPressGestureDetector(),
553 mInputMethodContext(),
554 mIdleCallback(nullptr),
555 mFlags(Control::ControlBehaviour(CONTROL_BEHAVIOUR_DEFAULT)),
556 mIsKeyboardNavigationSupported(false),
557 mIsKeyboardFocusGroup(false),
558 mIsEmittingResourceReadySignal(false),
559 mIdleCallbackRegistered(false),
560 mDispatchKeyEvents(true)
562 Dali::Accessibility::Accessible::RegisterExternalAccessibleGetter(&ExternalAccessibleGetter);
565 Control::Impl::~Impl()
567 for(auto&& iter : mVisuals)
569 StopObservingVisual(iter->visual);
572 for(auto&& iter : mRemoveVisuals)
574 StopObservingVisual(iter->visual);
577 // All gesture detectors will be destroyed so no need to disconnect.
578 delete mStartingPinchScale;
580 if(mIdleCallback && Adaptor::IsAvailable())
582 // Removes the callback from the callback manager in case the control is destroyed before the callback is executed.
583 Adaptor::Get().RemoveIdle(mIdleCallback);
587 Control::Impl& Control::Impl::Get(Internal::Control& internalControl)
589 return *internalControl.mImpl;
592 const Control::Impl& Control::Impl::Get(const Internal::Control& internalControl)
594 return *internalControl.mImpl;
597 void Control::Impl::CheckHighlightedObjectGeometry()
599 auto accessible = GetAccessibleObject();
600 auto lastPosition = accessible->GetLastPosition();
601 auto accessibleRect = accessible->GetExtents(Dali::Accessibility::CoordinateType::WINDOW);
602 auto rect = GetShowingGeometry(accessibleRect, accessible);
604 switch(mAccessibilityLastScreenRelativeMoveType)
606 case Dali::Accessibility::ScreenRelativeMoveType::OUTSIDE:
608 if(IsShowingGeometryOnScreen(rect))
610 mAccessibilityLastScreenRelativeMoveType = Dali::Accessibility::ScreenRelativeMoveType::INSIDE;
614 case Dali::Accessibility::ScreenRelativeMoveType::INSIDE:
616 if(rect.width < 0 && !Dali::Equals(accessibleRect.x, lastPosition.x))
618 mAccessibilityLastScreenRelativeMoveType = (accessibleRect.x < lastPosition.x) ? Dali::Accessibility::ScreenRelativeMoveType::OUTGOING_TOP_LEFT : Dali::Accessibility::ScreenRelativeMoveType::OUTGOING_BOTTOM_RIGHT;
620 if(rect.height < 0 && !Dali::Equals(accessibleRect.y, lastPosition.y))
622 mAccessibilityLastScreenRelativeMoveType = (accessibleRect.y < lastPosition.y) ? Dali::Accessibility::ScreenRelativeMoveType::OUTGOING_TOP_LEFT : Dali::Accessibility::ScreenRelativeMoveType::OUTGOING_BOTTOM_RIGHT;
624 // notify AT-clients on outgoing moves only
625 if(mAccessibilityLastScreenRelativeMoveType != Dali::Accessibility::ScreenRelativeMoveType::INSIDE)
627 accessible->EmitMovedOutOfScreen(mAccessibilityLastScreenRelativeMoveType);
631 case Dali::Accessibility::ScreenRelativeMoveType::OUTGOING_TOP_LEFT:
632 case Dali::Accessibility::ScreenRelativeMoveType::OUTGOING_BOTTOM_RIGHT:
634 if(IsShowingGeometryOnScreen(rect))
636 mAccessibilityLastScreenRelativeMoveType = Dali::Accessibility::ScreenRelativeMoveType::INSIDE;
640 mAccessibilityLastScreenRelativeMoveType = Dali::Accessibility::ScreenRelativeMoveType::OUTSIDE;
650 accessible->SetLastPosition(Vector2(accessibleRect.x, accessibleRect.y));
653 void Control::Impl::RegisterAccessibilityPositionPropertyNotification()
655 if(mIsAccessibilityPositionPropertyNotificationSet)
659 // set default value until first move of object is detected
660 mAccessibilityLastScreenRelativeMoveType = Dali::Accessibility::ScreenRelativeMoveType::OUTSIDE;
661 // recalculate mAccessibilityLastScreenRelativeMoveType accordingly to the initial position
662 CheckHighlightedObjectGeometry();
663 mAccessibilityPositionNotification = mControlImpl.Self().AddPropertyNotification(Actor::Property::WORLD_POSITION, StepCondition(1.0f, 1.0f));
664 mAccessibilityPositionNotification.SetNotifyMode(PropertyNotification::NOTIFY_ON_CHANGED);
665 mAccessibilityPositionNotification.NotifySignal().Connect(this, [this](PropertyNotification&) { CheckHighlightedObjectGeometry(); });
666 mIsAccessibilityPositionPropertyNotificationSet = true;
669 void Control::Impl::UnregisterAccessibilityPositionPropertyNotification()
671 mControlImpl.Self().RemovePropertyNotification(mAccessibilityPositionNotification);
672 mIsAccessibilityPositionPropertyNotificationSet = false;
675 // Gesture Detection Methods
676 void Control::Impl::PinchDetected(Actor actor, const PinchGesture& pinch)
678 mControlImpl.OnPinch(pinch);
681 void Control::Impl::PanDetected(Actor actor, const PanGesture& pan)
683 mControlImpl.OnPan(pan);
686 void Control::Impl::TapDetected(Actor actor, const TapGesture& tap)
688 mControlImpl.OnTap(tap);
691 void Control::Impl::LongPressDetected(Actor actor, const LongPressGesture& longPress)
693 mControlImpl.OnLongPress(longPress);
696 void Control::Impl::RegisterVisual(Property::Index index, Toolkit::Visual::Base& visual)
698 RegisterVisual(index, visual, VisualState::ENABLED, DepthIndexValue::NOT_SET);
701 void Control::Impl::RegisterVisual(Property::Index index, Toolkit::Visual::Base& visual, int depthIndex)
703 RegisterVisual(index, visual, VisualState::ENABLED, DepthIndexValue::SET, depthIndex);
706 void Control::Impl::RegisterVisual(Property::Index index, Toolkit::Visual::Base& visual, bool enabled)
708 RegisterVisual(index, visual, (enabled ? VisualState::ENABLED : VisualState::DISABLED), DepthIndexValue::NOT_SET);
711 void Control::Impl::RegisterVisual(Property::Index index, Toolkit::Visual::Base& visual, bool enabled, int depthIndex)
713 RegisterVisual(index, visual, (enabled ? VisualState::ENABLED : VisualState::DISABLED), DepthIndexValue::SET, depthIndex);
716 void Control::Impl::RegisterVisual(Property::Index index, Toolkit::Visual::Base& visual, VisualState::Type enabled, DepthIndexValue::Type depthIndexValueSet, int depthIndex)
718 DALI_LOG_INFO(gLogFilter, Debug::Concise, "RegisterVisual:%d \n", index);
720 bool visualReplaced(false);
721 Actor self = mControlImpl.Self();
723 // Set the depth index, if not set by caller this will be either the current visual depth, max depth of all visuals
725 int requiredDepthIndex = visual.GetDepthIndex();
727 if(depthIndexValueSet == DepthIndexValue::SET)
729 requiredDepthIndex = depthIndex;
732 // Visual replacement, existing visual should only be removed from stage when replacement ready.
733 if(!mVisuals.Empty())
735 RegisteredVisualContainer::Iterator registeredVisualsiter;
736 // Check if visual (index) is already registered, this is the current visual.
737 if(FindVisual(index, mVisuals, registeredVisualsiter))
739 Toolkit::Visual::Base& currentRegisteredVisual = (*registeredVisualsiter)->visual;
740 if(currentRegisteredVisual)
742 // Store current visual depth index as may need to set the replacement visual to same depth
743 const int currentDepthIndex = (*registeredVisualsiter)->visual.GetDepthIndex();
745 // No longer required to know if the replaced visual's resources are ready
746 StopObservingVisual(currentRegisteredVisual);
748 // If control staged and visual enabled then visuals will be swapped once ready
749 if(self.GetProperty<bool>(Actor::Property::CONNECTED_TO_SCENE) && enabled)
751 // Check if visual is currently in the process of being replaced ( is in removal container )
752 RegisteredVisualContainer::Iterator visualQueuedForRemoval;
753 if(FindVisual(index, mRemoveVisuals, visualQueuedForRemoval))
755 // Visual with same index is already in removal container so current visual pending
756 // Only the the last requested visual will be displayed so remove current visual which is staged but not ready.
757 Toolkit::GetImplementation(currentRegisteredVisual).SetOffScene(self);
758 mVisuals.Erase(registeredVisualsiter);
762 // current visual not already in removal container so add now.
763 DALI_LOG_INFO(gLogFilter, Debug::Verbose, "RegisterVisual Move current registered visual to removal Queue: %d \n", index);
764 MoveVisual(registeredVisualsiter, mVisuals, mRemoveVisuals);
769 // Control not staged or visual disabled so can just erase from registered visuals and new visual will be added later.
770 mVisuals.Erase(registeredVisualsiter);
773 // 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
774 if((depthIndexValueSet == DepthIndexValue::NOT_SET) &&
775 (visual.GetDepthIndex() == 0))
777 requiredDepthIndex = currentDepthIndex;
781 visualReplaced = true;
785 // If not set, set the name of the visual to the same name as the control's property.
786 // ( If the control has been type registered )
787 if(visual.GetName().empty())
789 // returns empty string if index is not found as long as index is not -1
790 std::string visualName = self.GetPropertyName(index);
791 if(!visualName.empty())
793 DALI_LOG_INFO(gLogFilter, Debug::Concise, "Setting visual name for property %d to %s\n", index, visualName.c_str());
794 visual.SetName(visualName);
798 if(!visualReplaced) // New registration entry
800 // 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
801 if((depthIndexValueSet == DepthIndexValue::NOT_SET) &&
802 (mVisuals.Size() > 0) &&
803 (visual.GetDepthIndex() == 0))
805 int maxDepthIndex = std::numeric_limits<int>::min();
807 RegisteredVisualContainer::ConstIterator iter;
808 const RegisteredVisualContainer::ConstIterator endIter = mVisuals.End();
809 for(iter = mVisuals.Begin(); iter != endIter; iter++)
811 const int visualDepthIndex = (*iter)->visual.GetDepthIndex();
812 if(visualDepthIndex > maxDepthIndex)
814 maxDepthIndex = visualDepthIndex;
817 ++maxDepthIndex; // Add one to the current maximum depth index so that our added visual appears on top
818 requiredDepthIndex = std::max(0, maxDepthIndex); // Start at zero if maxDepth index belongs to a background
824 // Set determined depth index
825 visual.SetDepthIndex(requiredDepthIndex);
827 // Monitor when the visual resources are ready
828 StartObservingVisual(visual);
830 DALI_LOG_INFO(gLogFilter, Debug::Concise, "New Visual registration index[%d] depth[%d]\n", index, requiredDepthIndex);
831 RegisteredVisual* newRegisteredVisual = new RegisteredVisual(index, visual, (enabled == VisualState::ENABLED ? true : false), (visualReplaced && enabled));
832 mVisuals.PushBack(newRegisteredVisual);
834 Internal::Visual::Base& visualImpl = Toolkit::GetImplementation(visual);
835 // Put on stage if enabled and the control is already on the stage
836 if((enabled == VisualState::ENABLED) && self.GetProperty<bool>(Actor::Property::CONNECTED_TO_SCENE))
838 visualImpl.SetOnScene(self);
840 else if(enabled && visualImpl.IsResourceReady()) // When not being staged, check if visual already 'ResourceReady' before it was Registered. ( Resource may have been loaded already )
842 ResourceReady(visualImpl);
846 DALI_LOG_INFO(gLogFilter, Debug::Verbose, "Control::RegisterVisual() Registered %s(%d), enabled:%s\n", visual.GetName().c_str(), index, enabled ? "true" : "false");
849 void Control::Impl::UnregisterVisual(Property::Index index)
851 RegisteredVisualContainer::Iterator iter;
852 if(FindVisual(index, mVisuals, iter))
854 // stop observing visual
855 StopObservingVisual((*iter)->visual);
857 Actor self(mControlImpl.Self());
858 Toolkit::GetImplementation((*iter)->visual).SetOffScene(self);
859 (*iter)->visual.Reset();
860 mVisuals.Erase(iter);
863 if(FindVisual(index, mRemoveVisuals, iter))
865 Actor self(mControlImpl.Self());
866 Toolkit::GetImplementation((*iter)->visual).SetOffScene(self);
867 (*iter)->pending = false;
868 (*iter)->visual.Reset();
869 mRemoveVisuals.Erase(iter);
873 Toolkit::Visual::Base Control::Impl::GetVisual(Property::Index index) const
875 RegisteredVisualContainer::Iterator iter;
876 if(FindVisual(index, mVisuals, iter))
878 return (*iter)->visual;
881 return Toolkit::Visual::Base();
884 void Control::Impl::EnableVisual(Property::Index index, bool enable)
886 DALI_LOG_INFO(gLogFilter, Debug::General, "Control::EnableVisual(%d, %s)\n", index, enable ? "T" : "F");
888 RegisteredVisualContainer::Iterator iter;
889 if(FindVisual(index, mVisuals, iter))
891 if((*iter)->enabled == enable)
893 DALI_LOG_INFO(gLogFilter, Debug::Verbose, "Control::EnableVisual Visual %s(%d) already %s\n", (*iter)->visual.GetName().c_str(), index, enable ? "enabled" : "disabled");
897 (*iter)->enabled = enable;
898 Actor parentActor = mControlImpl.Self();
899 if(mControlImpl.Self().GetProperty<bool>(Actor::Property::CONNECTED_TO_SCENE)) // If control not on Scene then Visual will be added when SceneConnection is called.
903 DALI_LOG_INFO(gLogFilter, Debug::Verbose, "Control::EnableVisual Setting %s(%d) on stage \n", (*iter)->visual.GetName().c_str(), index);
904 Toolkit::GetImplementation((*iter)->visual).SetOnScene(parentActor);
908 DALI_LOG_INFO(gLogFilter, Debug::Verbose, "Control::EnableVisual Setting %s(%d) off stage \n", (*iter)->visual.GetName().c_str(), index);
909 Toolkit::GetImplementation((*iter)->visual).SetOffScene(parentActor); // No need to call if control not staged.
915 DALI_LOG_WARNING("Control::EnableVisual(%d, %s) FAILED - NO SUCH VISUAL\n", index, enable ? "T" : "F");
919 bool Control::Impl::IsVisualEnabled(Property::Index index) const
921 RegisteredVisualContainer::Iterator iter;
922 if(FindVisual(index, mVisuals, iter))
924 return (*iter)->enabled;
929 void Control::Impl::EnableReadyTransitionOverriden(Toolkit::Visual::Base& visual, bool enable)
931 DALI_LOG_INFO(gLogFilter, Debug::General, "Control::EnableReadyTransitionOverriden(%p, %s)\n", visual, enable ? "T" : "F");
933 RegisteredVisualContainer::Iterator iter;
934 if(FindVisual(visual, mVisuals, iter))
936 if((*iter)->overideReadyTransition == enable)
938 DALI_LOG_INFO(gLogFilter, Debug::Verbose, "Control::EnableReadyTransitionOverriden Visual %s(%p) already %s\n", (*iter)->visual.GetName().c_str(), visual, enable ? "enabled" : "disabled");
942 (*iter)->overideReadyTransition = enable;
946 void Control::Impl::StopObservingVisual(Toolkit::Visual::Base& visual)
948 Internal::Visual::Base& visualImpl = Toolkit::GetImplementation(visual);
950 // Stop observing the visual
951 visualImpl.RemoveEventObserver(*this);
954 void Control::Impl::StartObservingVisual(Toolkit::Visual::Base& visual)
956 Internal::Visual::Base& visualImpl = Toolkit::GetImplementation(visual);
958 // start observing the visual for events
959 visualImpl.AddEventObserver(*this);
962 void Control::Impl::ResourceReady()
964 // Emit signal if all enabled visuals registered by the control are ready or there are no visuals.
965 if(IsResourceReady())
967 EmitResourceReadySignal();
971 // Called by a Visual when it's resource is ready
972 void Control::Impl::ResourceReady(Visual::Base& object)
974 DALI_LOG_INFO(gLogFilter, Debug::Verbose, "Control::Impl::ResourceReady() replacements pending[%d]\n", mRemoveVisuals.Count());
976 Actor self = mControlImpl.Self();
978 RegisteredVisualContainer::Iterator registeredIter;
980 // A resource is ready, find resource in the registered visuals container and get its index
981 if(!FindVisual(object, mVisuals, registeredIter))
986 RegisteredVisualContainer::Iterator visualToRemoveIter;
987 // Find visual with the same index in the removal container
988 // Set if off stage as it's replacement is now ready.
989 // Remove if from removal list as now removed from stage.
990 // Set Pending flag on the ready visual to false as now ready.
991 if(FindVisual((*registeredIter)->index, mRemoveVisuals, visualToRemoveIter))
993 (*registeredIter)->pending = false;
994 if(!((*visualToRemoveIter)->overideReadyTransition))
996 Toolkit::GetImplementation((*visualToRemoveIter)->visual).SetOffScene(self);
998 mRemoveVisuals.Erase(visualToRemoveIter);
1001 // A visual is ready so control may need relayouting if staged
1002 RelayoutRequest(object);
1004 // Called by a Visual when it's resource is ready
1005 if(((*registeredIter)->enabled))
1011 void Control::Impl::NotifyVisualEvent(Visual::Base& object, Property::Index signalId)
1013 for(auto registeredIter = mVisuals.Begin(), end = mVisuals.End(); registeredIter != end; ++registeredIter)
1015 Internal::Visual::Base& registeredVisualImpl = Toolkit::GetImplementation((*registeredIter)->visual);
1016 if(&object == ®isteredVisualImpl)
1018 Dali::Toolkit::Control handle(mControlImpl.GetOwner());
1019 mVisualEventSignal.Emit(handle, (*registeredIter)->index, signalId);
1025 void Control::Impl::RelayoutRequest(Visual::Base& object)
1027 if(mControlImpl.Self().GetProperty<bool>(Actor::Property::CONNECTED_TO_SCENE))
1029 mControlImpl.RelayoutRequest();
1033 bool Control::Impl::IsResourceReady() const
1035 // Iterate through and check all the enabled visuals are ready
1036 for(auto visualIter = mVisuals.Begin();
1037 visualIter != mVisuals.End();
1040 const Toolkit::Visual::Base visual = (*visualIter)->visual;
1041 const Internal::Visual::Base& visualImpl = Toolkit::GetImplementation(visual);
1043 // one of the enabled visuals is not ready
1044 if(!visualImpl.IsResourceReady() && (*visualIter)->enabled)
1052 Toolkit::Visual::ResourceStatus Control::Impl::GetVisualResourceStatus(Property::Index index) const
1054 RegisteredVisualContainer::Iterator iter;
1055 if(FindVisual(index, mVisuals, iter))
1057 const Toolkit::Visual::Base visual = (*iter)->visual;
1058 const Internal::Visual::Base& visualImpl = Toolkit::GetImplementation(visual);
1059 return visualImpl.GetResourceStatus();
1062 return Toolkit::Visual::ResourceStatus::PREPARING;
1065 void Control::Impl::AddTransitions(Dali::Animation& animation,
1066 const Toolkit::TransitionData& handle,
1067 bool createAnimation)
1069 // Setup a Transition from TransitionData.
1070 const Internal::TransitionData& transitionData = Toolkit::GetImplementation(handle);
1071 TransitionData::Iterator end = transitionData.End();
1072 for(TransitionData::Iterator iter = transitionData.Begin();
1076 TransitionData::Animator* animator = (*iter);
1078 Toolkit::Visual::Base visual = GetVisualByName(mVisuals, animator->objectName);
1082 #if defined(DEBUG_ENABLED)
1083 Dali::TypeInfo typeInfo;
1084 ControlWrapper* controlWrapperImpl = dynamic_cast<ControlWrapper*>(&mControlImpl);
1085 if(controlWrapperImpl)
1087 typeInfo = controlWrapperImpl->GetTypeInfo();
1090 DALI_LOG_INFO(gLogFilter, Debug::Concise, "CreateTransition: Found %s visual for %s\n", visual.GetName().c_str(), typeInfo ? typeInfo.GetName().c_str() : "Unknown");
1092 Internal::Visual::Base& visualImpl = Toolkit::GetImplementation(visual);
1093 visualImpl.AnimateProperty(animation, *animator);
1097 DALI_LOG_INFO(gLogFilter, Debug::Concise, "CreateTransition: Could not find visual. Trying actors");
1098 // Otherwise, try any actor children of control (Including the control)
1099 Actor child = mControlImpl.Self().FindChildByName(animator->objectName);
1102 Property::Index propertyIndex = child.GetPropertyIndex(animator->propertyKey);
1103 if(propertyIndex != Property::INVALID_INDEX)
1105 if(animator->animate == false)
1107 if(animator->targetValue.GetType() != Property::NONE)
1109 child.SetProperty(propertyIndex, animator->targetValue);
1112 else // animate the property
1114 if(animator->initialValue.GetType() != Property::NONE)
1116 child.SetProperty(propertyIndex, animator->initialValue);
1119 if(createAnimation && !animation)
1121 animation = Dali::Animation::New(0.1f);
1124 animation.AnimateTo(Property(child, propertyIndex),
1125 animator->targetValue,
1126 animator->alphaFunction,
1127 TimePeriod(animator->timePeriodDelay,
1128 animator->timePeriodDuration));
1136 Dali::Animation Control::Impl::CreateTransition(const Toolkit::TransitionData& transitionData)
1138 Dali::Animation transition;
1140 if(transitionData.Count() > 0)
1142 AddTransitions(transition, transitionData, true);
1147 void Control::Impl::DoAction(Dali::Property::Index visualIndex, Dali::Property::Index actionId, const Dali::Property::Value attributes)
1149 RegisteredVisualContainer::Iterator iter;
1150 if(FindVisual(visualIndex, mVisuals, iter))
1152 Toolkit::GetImplementation((*iter)->visual).DoAction(actionId, attributes);
1156 void Control::Impl::DoActionExtension(Dali::Property::Index visualIndex, Dali::Property::Index actionId, Dali::Any attributes)
1158 RegisteredVisualContainer::Iterator iter;
1159 if(FindVisual(visualIndex, mVisuals, iter))
1161 Toolkit::GetImplementation((*iter)->visual).DoActionExtension(actionId, attributes);
1165 void Control::Impl::AppendAccessibilityAttribute(const std::string& key, const std::string value)
1167 Property::Value* checkedValue = mAccessibilityAttributes.Find(key);
1170 mAccessibilityAttributes[key] = Property::Value(value);
1174 mAccessibilityAttributes.Insert(key, value);
1178 void Control::Impl::SetProperty(BaseObject* object, Property::Index index, const Property::Value& value)
1180 Toolkit::Control control = Toolkit::Control::DownCast(BaseHandle(object));
1184 Control& controlImpl(GetImplementation(control));
1188 case Toolkit::Control::Property::STYLE_NAME:
1190 controlImpl.SetStyleName(value.Get<std::string>());
1194 case Toolkit::DevelControl::Property::STATE:
1196 bool withTransitions = true;
1197 const Property::Value* valuePtr = &value;
1198 const Property::Map* map = value.GetMap();
1201 Property::Value* value2 = map->Find("withTransitions");
1204 withTransitions = value2->Get<bool>();
1207 valuePtr = map->Find("state");
1212 Toolkit::DevelControl::State state(controlImpl.mImpl->mState);
1213 if(Scripting::GetEnumerationProperty<Toolkit::DevelControl::State>(*valuePtr, ControlStateTable, ControlStateTableCount, state))
1215 controlImpl.mImpl->SetState(state, withTransitions);
1221 case Toolkit::DevelControl::Property::SUB_STATE:
1223 std::string subState;
1224 if(value.Get(subState))
1226 controlImpl.mImpl->SetSubState(subState);
1231 case Toolkit::DevelControl::Property::LEFT_FOCUSABLE_ACTOR_ID:
1234 if(value.Get(focusId))
1236 controlImpl.mImpl->mLeftFocusableActorId = focusId;
1241 case Toolkit::DevelControl::Property::RIGHT_FOCUSABLE_ACTOR_ID:
1244 if(value.Get(focusId))
1246 controlImpl.mImpl->mRightFocusableActorId = focusId;
1251 case Toolkit::DevelControl::Property::UP_FOCUSABLE_ACTOR_ID:
1254 if(value.Get(focusId))
1256 controlImpl.mImpl->mUpFocusableActorId = focusId;
1261 case Toolkit::DevelControl::Property::DOWN_FOCUSABLE_ACTOR_ID:
1264 if(value.Get(focusId))
1266 controlImpl.mImpl->mDownFocusableActorId = focusId;
1271 case Toolkit::Control::Property::KEY_INPUT_FOCUS:
1273 if(value.Get<bool>())
1275 controlImpl.SetKeyInputFocus();
1279 controlImpl.ClearKeyInputFocus();
1284 case Toolkit::Control::Property::BACKGROUND:
1288 const Property::Map* map = value.GetMap();
1289 if(map && !map->Empty())
1291 controlImpl.SetBackground(*map);
1293 else if(value.Get(url))
1295 // don't know the size to load
1296 Toolkit::Visual::Base visual = Toolkit::VisualFactory::Get().CreateVisual(url, ImageDimensions());
1299 controlImpl.mImpl->RegisterVisual(Toolkit::Control::Property::BACKGROUND, visual, DepthIndex::BACKGROUND);
1302 else if(value.Get(color))
1304 controlImpl.SetBackgroundColor(color);
1308 // The background is an empty property map, so we should clear the background
1309 controlImpl.ClearBackground();
1314 case Toolkit::Control::Property::MARGIN:
1317 if(value.Get(margin))
1319 controlImpl.mImpl->SetMargin(margin);
1324 case Toolkit::Control::Property::PADDING:
1327 if(value.Get(padding))
1329 controlImpl.mImpl->SetPadding(padding);
1334 case Toolkit::DevelControl::Property::TOOLTIP:
1336 TooltipPtr& tooltipPtr = controlImpl.mImpl->mTooltip;
1339 tooltipPtr = Tooltip::New(control);
1341 tooltipPtr->SetProperties(value);
1345 case Toolkit::DevelControl::Property::SHADOW:
1347 const Property::Map* map = value.GetMap();
1348 if(map && !map->Empty())
1350 controlImpl.mImpl->SetShadow(*map);
1354 // The shadow is an empty property map, so we should clear the shadow
1355 controlImpl.mImpl->ClearShadow();
1360 case Toolkit::DevelControl::Property::ACCESSIBILITY_NAME:
1365 controlImpl.mImpl->mAccessibilityName = name;
1370 case Toolkit::DevelControl::Property::ACCESSIBILITY_DESCRIPTION:
1375 controlImpl.mImpl->mAccessibilityDescription = text;
1380 case Toolkit::DevelControl::Property::ACCESSIBILITY_TRANSLATION_DOMAIN:
1385 controlImpl.mImpl->mAccessibilityTranslationDomain = text;
1390 case Toolkit::DevelControl::Property::ACCESSIBILITY_ROLE:
1392 Dali::Accessibility::Role role;
1395 controlImpl.mImpl->mAccessibilityRole = role;
1400 case Toolkit::DevelControl::Property::ACCESSIBILITY_HIGHLIGHTABLE:
1403 if(value.Get(highlightable))
1405 controlImpl.mImpl->mAccessibilityHighlightable = highlightable;
1410 case Toolkit::DevelControl::Property::ACCESSIBILITY_ATTRIBUTES:
1412 const Property::Map* map = value.GetMap();
1413 if(map && !map->Empty())
1415 controlImpl.mImpl->mAccessibilityAttributes = *map;
1420 case Toolkit::DevelControl::Property::DISPATCH_KEY_EVENTS:
1423 if(value.Get(dispatch))
1425 controlImpl.mImpl->mDispatchKeyEvents = dispatch;
1430 case Toolkit::DevelControl::Property::ACCESSIBILITY_HIDDEN:
1433 if(value.Get(hidden))
1435 controlImpl.mImpl->mAccessibilityHidden = hidden;
1437 auto* accessible = controlImpl.GetAccessibleObject();
1438 auto* parent = dynamic_cast<Dali::Accessibility::ActorAccessible*>(accessible->GetParent());
1441 parent->OnChildrenChanged();
1446 case Toolkit::DevelControl::Property::CLOCKWISE_FOCUSABLE_ACTOR_ID:
1449 if(value.Get(focusId))
1451 controlImpl.mImpl->mClockwiseFocusableActorId = focusId;
1455 case Toolkit::DevelControl::Property::COUNTER_CLOCKWISE_FOCUSABLE_ACTOR_ID:
1458 if(value.Get(focusId))
1460 controlImpl.mImpl->mCounterClockwiseFocusableActorId = focusId;
1465 case Toolkit::DevelControl::Property::AUTOMATION_ID:
1467 std::string automationId;
1468 if(value.Get(automationId))
1470 controlImpl.mImpl->mAutomationId = automationId;
1478 Property::Value Control::Impl::GetProperty(BaseObject* object, Property::Index index)
1480 Property::Value value;
1482 Toolkit::Control control = Toolkit::Control::DownCast(BaseHandle(object));
1486 Control& controlImpl(GetImplementation(control));
1490 case Toolkit::Control::Property::STYLE_NAME:
1492 value = controlImpl.GetStyleName();
1496 case Toolkit::DevelControl::Property::STATE:
1498 value = controlImpl.mImpl->mState;
1502 case Toolkit::DevelControl::Property::SUB_STATE:
1504 value = controlImpl.mImpl->mSubStateName;
1508 case Toolkit::DevelControl::Property::LEFT_FOCUSABLE_ACTOR_ID:
1510 value = controlImpl.mImpl->mLeftFocusableActorId;
1514 case Toolkit::DevelControl::Property::RIGHT_FOCUSABLE_ACTOR_ID:
1516 value = controlImpl.mImpl->mRightFocusableActorId;
1520 case Toolkit::DevelControl::Property::UP_FOCUSABLE_ACTOR_ID:
1522 value = controlImpl.mImpl->mUpFocusableActorId;
1526 case Toolkit::DevelControl::Property::DOWN_FOCUSABLE_ACTOR_ID:
1528 value = controlImpl.mImpl->mDownFocusableActorId;
1532 case Toolkit::Control::Property::KEY_INPUT_FOCUS:
1534 value = controlImpl.HasKeyInputFocus();
1538 case Toolkit::Control::Property::BACKGROUND:
1541 Toolkit::Visual::Base visual = controlImpl.mImpl->GetVisual(Toolkit::Control::Property::BACKGROUND);
1544 visual.CreatePropertyMap(map);
1551 case Toolkit::Control::Property::MARGIN:
1553 value = controlImpl.mImpl->GetMargin();
1557 case Toolkit::Control::Property::PADDING:
1559 value = controlImpl.mImpl->GetPadding();
1563 case Toolkit::DevelControl::Property::TOOLTIP:
1566 if(controlImpl.mImpl->mTooltip)
1568 controlImpl.mImpl->mTooltip->CreatePropertyMap(map);
1574 case Toolkit::DevelControl::Property::SHADOW:
1577 Toolkit::Visual::Base visual = controlImpl.mImpl->GetVisual(Toolkit::DevelControl::Property::SHADOW);
1580 visual.CreatePropertyMap(map);
1587 case Toolkit::DevelControl::Property::ACCESSIBILITY_NAME:
1589 value = controlImpl.mImpl->mAccessibilityName;
1593 case Toolkit::DevelControl::Property::ACCESSIBILITY_DESCRIPTION:
1595 value = controlImpl.mImpl->mAccessibilityDescription;
1599 case Toolkit::DevelControl::Property::ACCESSIBILITY_TRANSLATION_DOMAIN:
1601 value = controlImpl.mImpl->mAccessibilityTranslationDomain;
1605 case Toolkit::DevelControl::Property::ACCESSIBILITY_ROLE:
1607 value = Property::Value(controlImpl.mImpl->mAccessibilityRole);
1611 case Toolkit::DevelControl::Property::ACCESSIBILITY_HIGHLIGHTABLE:
1613 value = controlImpl.mImpl->mAccessibilityHighlightable;
1617 case Toolkit::DevelControl::Property::ACCESSIBILITY_ATTRIBUTES:
1619 value = controlImpl.mImpl->mAccessibilityAttributes;
1623 case Toolkit::DevelControl::Property::DISPATCH_KEY_EVENTS:
1625 value = controlImpl.mImpl->mDispatchKeyEvents;
1629 case Toolkit::DevelControl::Property::ACCESSIBILITY_HIDDEN:
1631 value = controlImpl.mImpl->mAccessibilityHidden;
1635 case Toolkit::DevelControl::Property::CLOCKWISE_FOCUSABLE_ACTOR_ID:
1637 value = controlImpl.mImpl->mClockwiseFocusableActorId;
1641 case Toolkit::DevelControl::Property::COUNTER_CLOCKWISE_FOCUSABLE_ACTOR_ID:
1643 value = controlImpl.mImpl->mCounterClockwiseFocusableActorId;
1647 case Toolkit::DevelControl::Property::AUTOMATION_ID:
1649 value = controlImpl.mImpl->mAutomationId;
1658 void Control::Impl::RemoveAccessibilityAttribute(const std::string& key)
1660 Property::Value* value = mAccessibilityAttributes.Find(key);
1663 mAccessibilityAttributes[key] = Property::Value();
1667 void Control::Impl::ClearAccessibilityAttributes()
1669 mAccessibilityAttributes.Clear();
1672 void Control::Impl::SetAccessibilityReadingInfoType(const Dali::Accessibility::ReadingInfoTypes types)
1674 std::string value{};
1675 if(types[Dali::Accessibility::ReadingInfoType::NAME])
1677 value += READING_INFO_TYPE_NAME;
1679 if(types[Dali::Accessibility::ReadingInfoType::ROLE])
1683 value += READING_INFO_TYPE_SEPARATOR;
1685 value += READING_INFO_TYPE_ROLE;
1687 if(types[Dali::Accessibility::ReadingInfoType::DESCRIPTION])
1691 value += READING_INFO_TYPE_SEPARATOR;
1693 value += READING_INFO_TYPE_DESCRIPTION;
1695 if(types[Dali::Accessibility::ReadingInfoType::STATE])
1699 value += READING_INFO_TYPE_SEPARATOR;
1701 value += READING_INFO_TYPE_STATE;
1703 AppendAccessibilityAttribute(READING_INFO_TYPE_ATTRIBUTE_NAME, value);
1706 Dali::Accessibility::ReadingInfoTypes Control::Impl::GetAccessibilityReadingInfoType() const
1708 std::string value{};
1709 auto place = mAccessibilityAttributes.Find(READING_INFO_TYPE_ATTRIBUTE_NAME);
1716 Dali::Accessibility::ReadingInfoTypes types;
1717 types[Dali::Accessibility::ReadingInfoType::NAME] = true;
1718 types[Dali::Accessibility::ReadingInfoType::ROLE] = true;
1719 types[Dali::Accessibility::ReadingInfoType::DESCRIPTION] = true;
1720 types[Dali::Accessibility::ReadingInfoType::STATE] = true;
1729 Dali::Accessibility::ReadingInfoTypes types;
1731 if(value.find(READING_INFO_TYPE_NAME) != std::string::npos)
1733 types[Dali::Accessibility::ReadingInfoType::NAME] = true;
1735 if(value.find(READING_INFO_TYPE_ROLE) != std::string::npos)
1737 types[Dali::Accessibility::ReadingInfoType::ROLE] = true;
1739 if(value.find(READING_INFO_TYPE_DESCRIPTION) != std::string::npos)
1741 types[Dali::Accessibility::ReadingInfoType::DESCRIPTION] = true;
1743 if(value.find(READING_INFO_TYPE_STATE) != std::string::npos)
1745 types[Dali::Accessibility::ReadingInfoType::STATE] = true;
1751 void Control::Impl::CopyInstancedProperties(RegisteredVisualContainer& visuals, Dictionary<Property::Map>& instancedProperties)
1753 for(RegisteredVisualContainer::Iterator iter = visuals.Begin(); iter != visuals.End(); iter++)
1757 Property::Map instanceMap;
1758 Toolkit::GetImplementation((*iter)->visual).CreateInstancePropertyMap(instanceMap);
1759 instancedProperties.Add((*iter)->visual.GetName(), instanceMap);
1764 void Control::Impl::RemoveVisual(RegisteredVisualContainer& visuals, const std::string& visualName)
1766 Actor self(mControlImpl.Self());
1768 for(RegisteredVisualContainer::Iterator visualIter = visuals.Begin();
1769 visualIter != visuals.End();
1772 Toolkit::Visual::Base visual = (*visualIter)->visual;
1773 if(visual && visual.GetName() == visualName)
1775 Toolkit::GetImplementation(visual).SetOffScene(self);
1776 (*visualIter)->visual.Reset();
1777 visuals.Erase(visualIter);
1783 void Control::Impl::RemoveVisuals(RegisteredVisualContainer& visuals, DictionaryKeys& removeVisuals)
1785 Actor self(mControlImpl.Self());
1786 for(DictionaryKeys::iterator iter = removeVisuals.begin(); iter != removeVisuals.end(); ++iter)
1788 const std::string visualName = *iter;
1789 RemoveVisual(visuals, visualName);
1793 void Control::Impl::RecreateChangedVisuals(Dictionary<Property::Map>& stateVisualsToChange,
1794 Dictionary<Property::Map>& instancedProperties)
1796 Dali::CustomActor handle(mControlImpl.GetOwner());
1797 for(Dictionary<Property::Map>::iterator iter = stateVisualsToChange.Begin();
1798 iter != stateVisualsToChange.End();
1801 const std::string& visualName = (*iter).key;
1802 const Property::Map& toMap = (*iter).entry;
1804 Actor self = mControlImpl.Self();
1805 RegisteredVisualContainer::Iterator registeredVisualsiter;
1806 // Check if visual (visualName) is already registered, this is the current visual.
1807 if(FindVisual(visualName, mVisuals, registeredVisualsiter))
1809 Toolkit::Visual::Base& visual = (*registeredVisualsiter)->visual;
1812 // No longer required to know if the replaced visual's resources are ready
1813 StopObservingVisual(visual);
1815 // If control staged then visuals will be swapped once ready
1816 if(self.GetProperty<bool>(Actor::Property::CONNECTED_TO_SCENE))
1818 // Check if visual is currently in the process of being replaced ( is in removal container )
1819 RegisteredVisualContainer::Iterator visualQueuedForRemoval;
1820 if(FindVisual(visualName, mRemoveVisuals, visualQueuedForRemoval))
1822 // Visual with same visual name is already in removal container so current visual pending
1823 // Only the the last requested visual will be displayed so remove current visual which is staged but not ready.
1824 Toolkit::GetImplementation(visual).SetOffScene(self);
1825 (*registeredVisualsiter)->visual.Reset();
1826 mVisuals.Erase(registeredVisualsiter);
1830 // current visual not already in removal container so add now.
1831 DALI_LOG_INFO(gLogFilter, Debug::Verbose, "RegisterVisual Move current registered visual to removal Queue: %s \n", visualName.c_str());
1832 MoveVisual(registeredVisualsiter, mVisuals, mRemoveVisuals);
1837 // Control not staged or visual disabled so can just erase from registered visuals and new visual will be added later.
1838 (*registeredVisualsiter)->visual.Reset();
1839 mVisuals.Erase(registeredVisualsiter);
1843 const Property::Map* instancedMap = instancedProperties.FindConst(visualName);
1844 Style::ApplyVisual(handle, visualName, toMap, instancedMap);
1849 void Control::Impl::ReplaceStateVisualsAndProperties(const StylePtr oldState, const StylePtr newState, const std::string& subState)
1851 // Collect all old visual names
1852 DictionaryKeys stateVisualsToRemove;
1855 oldState->visuals.GetKeys(stateVisualsToRemove);
1856 if(!subState.empty())
1858 const StylePtr* oldSubState = oldState->subStates.FindConst(subState);
1861 DictionaryKeys subStateVisualsToRemove;
1862 (*oldSubState)->visuals.GetKeys(subStateVisualsToRemove);
1863 Merge(stateVisualsToRemove, subStateVisualsToRemove);
1868 // Collect all new visual properties
1869 Dictionary<Property::Map> stateVisualsToAdd;
1872 stateVisualsToAdd = newState->visuals;
1873 if(!subState.empty())
1875 const StylePtr* newSubState = newState->subStates.FindConst(subState);
1878 stateVisualsToAdd.Merge((*newSubState)->visuals);
1883 // If a name is in both add/remove, move it to change list.
1884 Dictionary<Property::Map> stateVisualsToChange;
1885 FindChangableVisuals(stateVisualsToAdd, stateVisualsToChange, stateVisualsToRemove);
1887 // Copy instanced properties (e.g. text label) of current visuals
1888 Dictionary<Property::Map> instancedProperties;
1889 CopyInstancedProperties(mVisuals, instancedProperties);
1891 // For each visual in remove list, remove from mVisuals
1892 RemoveVisuals(mVisuals, stateVisualsToRemove);
1894 // For each visual in add list, create and add to mVisuals
1895 Dali::CustomActor handle(mControlImpl.GetOwner());
1896 Style::ApplyVisuals(handle, stateVisualsToAdd, instancedProperties);
1898 // For each visual in change list, if it requires a new visual,
1899 // remove old visual, create and add to mVisuals
1900 RecreateChangedVisuals(stateVisualsToChange, instancedProperties);
1903 void Control::Impl::SetState(DevelControl::State newState, bool withTransitions)
1905 DevelControl::State oldState = mState;
1906 Dali::CustomActor handle(mControlImpl.GetOwner());
1907 DALI_LOG_INFO(gLogFilter, Debug::Concise, "Control::Impl::SetState: %s\n", (mState == DevelControl::NORMAL ? "NORMAL" : (mState == DevelControl::FOCUSED ? "FOCUSED" : (mState == DevelControl::DISABLED ? "DISABLED" : "NONE"))));
1909 if(mState != newState)
1911 // If mState was Disabled, and new state is Focused, should probably
1912 // store that fact, e.g. in another property that FocusManager can access.
1915 // Trigger state change and transitions
1916 // Apply new style, if stylemanager is available
1917 Toolkit::StyleManager styleManager = Toolkit::StyleManager::Get();
1920 const StylePtr stylePtr = GetImpl(styleManager).GetRecordedStyle(Toolkit::Control(mControlImpl.GetOwner()));
1924 std::string oldStateName = Scripting::GetEnumerationName<Toolkit::DevelControl::State>(oldState, ControlStateTable, ControlStateTableCount);
1925 std::string newStateName = Scripting::GetEnumerationName<Toolkit::DevelControl::State>(newState, ControlStateTable, ControlStateTableCount);
1927 const StylePtr* newStateStyle = stylePtr->subStates.Find(newStateName);
1928 const StylePtr* oldStateStyle = stylePtr->subStates.Find(oldStateName);
1929 if(oldStateStyle && newStateStyle)
1931 // Only change if both state styles exist
1932 ReplaceStateVisualsAndProperties(*oldStateStyle, *newStateStyle, mSubStateName);
1939 void Control::Impl::SetSubState(const std::string& subStateName, bool withTransitions)
1941 if(mSubStateName != subStateName)
1943 // Get existing sub-state visuals, and unregister them
1944 Dali::CustomActor handle(mControlImpl.GetOwner());
1946 Toolkit::StyleManager styleManager = Toolkit::StyleManager::Get();
1949 const StylePtr stylePtr = GetImpl(styleManager).GetRecordedStyle(Toolkit::Control(mControlImpl.GetOwner()));
1953 std::string stateName = Scripting::GetEnumerationName<Toolkit::DevelControl::State>(mState, ControlStateTable, ControlStateTableCount);
1955 const StylePtr* state = stylePtr->subStates.Find(stateName);
1958 StylePtr stateStyle(*state);
1960 const StylePtr* newStateStyle = stateStyle->subStates.Find(subStateName);
1961 const StylePtr* oldStateStyle = stateStyle->subStates.Find(mSubStateName);
1962 if(oldStateStyle && newStateStyle)
1965 ReplaceStateVisualsAndProperties(*oldStateStyle, *newStateStyle, empty);
1971 mSubStateName = subStateName;
1975 void Control::Impl::OnSceneDisconnection()
1977 Actor self = mControlImpl.Self();
1979 // Any visuals set for replacement but not yet ready should still be registered.
1980 // Reason: If a request was made to register a new visual but the control removed from scene before visual was ready
1981 // then when this control appears back on stage it should use that new visual.
1983 // Iterate through all registered visuals and set off scene
1984 SetVisualsOffScene(mVisuals, self);
1986 // Visuals pending replacement can now be taken out of the removal list and set off scene
1987 // Iterate through all replacement visuals and add to a move queue then set off scene
1988 for(auto removalIter = mRemoveVisuals.Begin(), end = mRemoveVisuals.End(); removalIter != end; removalIter++)
1990 Toolkit::GetImplementation((*removalIter)->visual).SetOffScene(self);
1993 for(auto replacedIter = mVisuals.Begin(), end = mVisuals.End(); replacedIter != end; replacedIter++)
1995 (*replacedIter)->pending = false;
1998 mRemoveVisuals.Clear();
2001 void Control::Impl::SetMargin(Extents margin)
2003 mControlImpl.mImpl->mMargin = margin;
2005 // Trigger a size negotiation request that may be needed when setting a margin.
2006 mControlImpl.RelayoutRequest();
2009 Extents Control::Impl::GetMargin() const
2011 return mControlImpl.mImpl->mMargin;
2014 void Control::Impl::SetPadding(Extents padding)
2016 mControlImpl.mImpl->mPadding = padding;
2018 // Trigger a size negotiation request that may be needed when setting a padding.
2019 mControlImpl.RelayoutRequest();
2022 Extents Control::Impl::GetPadding() const
2024 return mControlImpl.mImpl->mPadding;
2027 void Control::Impl::SetInputMethodContext(InputMethodContext& inputMethodContext)
2029 mInputMethodContext = inputMethodContext;
2032 bool Control::Impl::FilterKeyEvent(const KeyEvent& event)
2034 bool consumed(false);
2036 if(mInputMethodContext)
2038 consumed = mInputMethodContext.FilterEventKey(event);
2043 DevelControl::VisualEventSignalType& Control::Impl::VisualEventSignal()
2045 return mVisualEventSignal;
2048 void Control::Impl::SetShadow(const Property::Map& map)
2050 Toolkit::Visual::Base visual = Toolkit::VisualFactory::Get().CreateVisual(map);
2051 visual.SetName("shadow");
2055 mControlImpl.mImpl->RegisterVisual(Toolkit::DevelControl::Property::SHADOW, visual, DepthIndex::BACKGROUND_EFFECT);
2057 mControlImpl.RelayoutRequest();
2061 void Control::Impl::ClearShadow()
2063 mControlImpl.mImpl->UnregisterVisual(Toolkit::DevelControl::Property::SHADOW);
2065 // Trigger a size negotiation request that may be needed when unregistering a visual.
2066 mControlImpl.RelayoutRequest();
2069 Dali::Property Control::Impl::GetVisualProperty(Dali::Property::Index index, Dali::Property::Key visualPropertyKey)
2071 Toolkit::Visual::Base visual = GetVisualByIndex(mVisuals, index);
2074 Internal::Visual::Base& visualImpl = Toolkit::GetImplementation(visual);
2075 return visualImpl.GetPropertyObject(visualPropertyKey);
2079 return Dali::Property(handle, Property::INVALID_INDEX);
2082 void Control::Impl::CreateTransitions(std::vector<std::pair<Dali::Property::Index, Dali::Property::Map>>& sourceProperties,
2083 std::vector<std::pair<Dali::Property::Index, Dali::Property::Map>>& destinationProperties,
2084 Dali::Toolkit::Control source,
2085 Dali::Toolkit::Control destination)
2087 // Retrieves background properties to be transitioned.
2088 Dali::Property::Map backgroundSourcePropertyMap, backgroundDestinationPropertyMap;
2089 mControlImpl.MakeVisualTransition(backgroundSourcePropertyMap, backgroundDestinationPropertyMap, source, destination, Toolkit::Control::Property::BACKGROUND);
2090 if(backgroundSourcePropertyMap.Count() > 0)
2092 sourceProperties.push_back(std::pair<Dali::Property::Index, Dali::Property::Map>(Toolkit::Control::Property::BACKGROUND, backgroundSourcePropertyMap));
2093 destinationProperties.push_back(std::pair<Dali::Property::Index, Dali::Property::Map>(Toolkit::Control::Property::BACKGROUND, backgroundDestinationPropertyMap));
2096 // Retrieves shadow properties to be transitioned.
2097 Dali::Property::Map shadowSourcePropertyMap, shadowDestinationPropertyMap;
2098 mControlImpl.MakeVisualTransition(shadowSourcePropertyMap, shadowDestinationPropertyMap, source, destination, Toolkit::DevelControl::Property::SHADOW);
2099 if(shadowSourcePropertyMap.Count() > 0)
2101 sourceProperties.push_back(std::pair<Dali::Property::Index, Dali::Property::Map>(Toolkit::DevelControl::Property::SHADOW, shadowSourcePropertyMap));
2102 destinationProperties.push_back(std::pair<Dali::Property::Index, Dali::Property::Map>(Toolkit::DevelControl::Property::SHADOW, shadowDestinationPropertyMap));
2105 // Retrieves transition from inherited class.
2106 mControlImpl.OnCreateTransitions(sourceProperties, destinationProperties, source, destination);
2109 void Control::Impl::UpdateVisualProperties(const std::vector<std::pair<Dali::Property::Index, Dali::Property::Map>>& properties)
2111 for(auto&& data : properties)
2113 if(data.first == Toolkit::Control::Property::BACKGROUND)
2115 DoAction(Toolkit::Control::Property::BACKGROUND, DevelVisual::Action::UPDATE_PROPERTY, data.second);
2117 else if(data.first == Toolkit::DevelControl::Property::SHADOW)
2119 DoAction(Toolkit::DevelControl::Property::SHADOW, DevelVisual::Action::UPDATE_PROPERTY, data.second);
2122 mControlImpl.OnUpdateVisualProperties(properties);
2125 void Control::Impl::EmitResourceReadySignal()
2127 if(!mIsEmittingResourceReadySignal)
2129 // Guard against calls to emit the signal during the callback
2130 mIsEmittingResourceReadySignal = true;
2132 // If the signal handler changes visual, it may become ready during this call & therefore this method will
2133 // get called again recursively. If so, mIdleCallbackRegistered is set below, and we act on it after that secondary
2134 // invocation has completed by notifying in an Idle callback to prevent further recursion.
2135 Dali::Toolkit::Control handle(mControlImpl.GetOwner());
2136 mResourceReadySignal.Emit(handle);
2138 mIsEmittingResourceReadySignal = false;
2142 if(!mIdleCallbackRegistered)
2144 mIdleCallbackRegistered = true;
2146 // Add idler to emit the signal again
2149 // The callback manager takes the ownership of the callback object.
2150 mIdleCallback = MakeCallback(this, &Control::Impl::OnIdleCallback);
2151 Adaptor::Get().AddIdle(mIdleCallback, true);
2157 bool Control::Impl::OnIdleCallback()
2160 mIdleCallbackRegistered = false;
2162 // A visual is ready so control may need relayouting if staged
2163 if(mControlImpl.Self().GetProperty<bool>(Actor::Property::CONNECTED_TO_SCENE))
2165 mControlImpl.RelayoutRequest();
2168 EmitResourceReadySignal();
2170 if(!mIdleCallbackRegistered)
2172 // Set the pointer to null as the callback manager deletes the callback after execute it.
2173 mIdleCallback = nullptr;
2176 // Repeat idle if mIdleCallbackRegistered become true one more time.
2177 return mIdleCallbackRegistered;
2180 Toolkit::DevelControl::ControlAccessible* Control::Impl::GetAccessibleObject()
2182 if(!mAccessibleObject)
2184 mAccessibleObject.reset(mControlImpl.CreateAccessibleObject());
2187 return mAccessibleObject.get();
2190 } // namespace Internal
2192 } // namespace Toolkit