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 mNeedToEmitResourceReady(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())
968 mNeedToEmitResourceReady = false;
969 EmitResourceReadySignal();
973 // Called by a Visual when it's resource is ready
974 void Control::Impl::ResourceReady(Visual::Base& object)
976 DALI_LOG_INFO(gLogFilter, Debug::Verbose, "Control::Impl::ResourceReady() replacements pending[%d]\n", mRemoveVisuals.Count());
978 Actor self = mControlImpl.Self();
980 RegisteredVisualContainer::Iterator registeredIter;
982 // A resource is ready, find resource in the registered visuals container and get its index
983 if(!FindVisual(object, mVisuals, registeredIter))
988 RegisteredVisualContainer::Iterator visualToRemoveIter;
989 // Find visual with the same index in the removal container
990 // Set if off stage as it's replacement is now ready.
991 // Remove if from removal list as now removed from stage.
992 // Set Pending flag on the ready visual to false as now ready.
993 if(FindVisual((*registeredIter)->index, mRemoveVisuals, visualToRemoveIter))
995 (*registeredIter)->pending = false;
996 if(!((*visualToRemoveIter)->overideReadyTransition))
998 Toolkit::GetImplementation((*visualToRemoveIter)->visual).SetOffScene(self);
1000 mRemoveVisuals.Erase(visualToRemoveIter);
1003 // A visual is ready so control may need relayouting if staged
1004 RelayoutRequest(object);
1006 // Called by a Visual when it's resource is ready
1007 if(((*registeredIter)->enabled))
1013 void Control::Impl::NotifyVisualEvent(Visual::Base& object, Property::Index signalId)
1015 for(auto registeredIter = mVisuals.Begin(), end = mVisuals.End(); registeredIter != end; ++registeredIter)
1017 Internal::Visual::Base& registeredVisualImpl = Toolkit::GetImplementation((*registeredIter)->visual);
1018 if(&object == ®isteredVisualImpl)
1020 Dali::Toolkit::Control handle(mControlImpl.GetOwner());
1021 mVisualEventSignal.Emit(handle, (*registeredIter)->index, signalId);
1027 void Control::Impl::RelayoutRequest(Visual::Base& object)
1029 if(mControlImpl.Self().GetProperty<bool>(Actor::Property::CONNECTED_TO_SCENE))
1031 mControlImpl.RelayoutRequest();
1035 bool Control::Impl::IsResourceReady() const
1037 // Iterate through and check all the enabled visuals are ready
1038 for(auto visualIter = mVisuals.Begin();
1039 visualIter != mVisuals.End();
1042 const Toolkit::Visual::Base visual = (*visualIter)->visual;
1043 const Internal::Visual::Base& visualImpl = Toolkit::GetImplementation(visual);
1045 // one of the enabled visuals is not ready
1046 if(!visualImpl.IsResourceReady() && (*visualIter)->enabled)
1054 Toolkit::Visual::ResourceStatus Control::Impl::GetVisualResourceStatus(Property::Index index) const
1056 RegisteredVisualContainer::Iterator iter;
1057 if(FindVisual(index, mVisuals, iter))
1059 const Toolkit::Visual::Base visual = (*iter)->visual;
1060 const Internal::Visual::Base& visualImpl = Toolkit::GetImplementation(visual);
1061 return visualImpl.GetResourceStatus();
1064 return Toolkit::Visual::ResourceStatus::PREPARING;
1067 void Control::Impl::AddTransitions(Dali::Animation& animation,
1068 const Toolkit::TransitionData& handle,
1069 bool createAnimation)
1071 // Setup a Transition from TransitionData.
1072 const Internal::TransitionData& transitionData = Toolkit::GetImplementation(handle);
1073 TransitionData::Iterator end = transitionData.End();
1074 for(TransitionData::Iterator iter = transitionData.Begin();
1078 TransitionData::Animator* animator = (*iter);
1080 Toolkit::Visual::Base visual = GetVisualByName(mVisuals, animator->objectName);
1084 #if defined(DEBUG_ENABLED)
1085 Dali::TypeInfo typeInfo;
1086 ControlWrapper* controlWrapperImpl = dynamic_cast<ControlWrapper*>(&mControlImpl);
1087 if(controlWrapperImpl)
1089 typeInfo = controlWrapperImpl->GetTypeInfo();
1092 DALI_LOG_INFO(gLogFilter, Debug::Concise, "CreateTransition: Found %s visual for %s\n", visual.GetName().c_str(), typeInfo ? typeInfo.GetName().c_str() : "Unknown");
1094 Internal::Visual::Base& visualImpl = Toolkit::GetImplementation(visual);
1095 visualImpl.AnimateProperty(animation, *animator);
1099 DALI_LOG_INFO(gLogFilter, Debug::Concise, "CreateTransition: Could not find visual. Trying actors");
1100 // Otherwise, try any actor children of control (Including the control)
1101 Actor child = mControlImpl.Self().FindChildByName(animator->objectName);
1104 Property::Index propertyIndex = child.GetPropertyIndex(animator->propertyKey);
1105 if(propertyIndex != Property::INVALID_INDEX)
1107 if(animator->animate == false)
1109 if(animator->targetValue.GetType() != Property::NONE)
1111 child.SetProperty(propertyIndex, animator->targetValue);
1114 else // animate the property
1116 if(animator->initialValue.GetType() != Property::NONE)
1118 child.SetProperty(propertyIndex, animator->initialValue);
1121 if(createAnimation && !animation)
1123 animation = Dali::Animation::New(0.1f);
1126 animation.AnimateTo(Property(child, propertyIndex),
1127 animator->targetValue,
1128 animator->alphaFunction,
1129 TimePeriod(animator->timePeriodDelay,
1130 animator->timePeriodDuration));
1138 Dali::Animation Control::Impl::CreateTransition(const Toolkit::TransitionData& transitionData)
1140 Dali::Animation transition;
1142 if(transitionData.Count() > 0)
1144 AddTransitions(transition, transitionData, true);
1149 void Control::Impl::DoAction(Dali::Property::Index visualIndex, Dali::Property::Index actionId, const Dali::Property::Value attributes)
1151 RegisteredVisualContainer::Iterator iter;
1152 if(FindVisual(visualIndex, mVisuals, iter))
1154 Toolkit::GetImplementation((*iter)->visual).DoAction(actionId, attributes);
1158 void Control::Impl::DoActionExtension(Dali::Property::Index visualIndex, Dali::Property::Index actionId, Dali::Any attributes)
1160 RegisteredVisualContainer::Iterator iter;
1161 if(FindVisual(visualIndex, mVisuals, iter))
1163 Toolkit::GetImplementation((*iter)->visual).DoActionExtension(actionId, attributes);
1167 void Control::Impl::AppendAccessibilityAttribute(const std::string& key, const std::string value)
1169 Property::Value* checkedValue = mAccessibilityAttributes.Find(key);
1172 mAccessibilityAttributes[key] = Property::Value(value);
1176 mAccessibilityAttributes.Insert(key, value);
1180 void Control::Impl::SetProperty(BaseObject* object, Property::Index index, const Property::Value& value)
1182 Toolkit::Control control = Toolkit::Control::DownCast(BaseHandle(object));
1186 Control& controlImpl(GetImplementation(control));
1190 case Toolkit::Control::Property::STYLE_NAME:
1192 controlImpl.SetStyleName(value.Get<std::string>());
1196 case Toolkit::DevelControl::Property::STATE:
1198 bool withTransitions = true;
1199 const Property::Value* valuePtr = &value;
1200 const Property::Map* map = value.GetMap();
1203 Property::Value* value2 = map->Find("withTransitions");
1206 withTransitions = value2->Get<bool>();
1209 valuePtr = map->Find("state");
1214 Toolkit::DevelControl::State state(controlImpl.mImpl->mState);
1215 if(Scripting::GetEnumerationProperty<Toolkit::DevelControl::State>(*valuePtr, ControlStateTable, ControlStateTableCount, state))
1217 controlImpl.mImpl->SetState(state, withTransitions);
1223 case Toolkit::DevelControl::Property::SUB_STATE:
1225 std::string subState;
1226 if(value.Get(subState))
1228 controlImpl.mImpl->SetSubState(subState);
1233 case Toolkit::DevelControl::Property::LEFT_FOCUSABLE_ACTOR_ID:
1236 if(value.Get(focusId))
1238 controlImpl.mImpl->mLeftFocusableActorId = focusId;
1243 case Toolkit::DevelControl::Property::RIGHT_FOCUSABLE_ACTOR_ID:
1246 if(value.Get(focusId))
1248 controlImpl.mImpl->mRightFocusableActorId = focusId;
1253 case Toolkit::DevelControl::Property::UP_FOCUSABLE_ACTOR_ID:
1256 if(value.Get(focusId))
1258 controlImpl.mImpl->mUpFocusableActorId = focusId;
1263 case Toolkit::DevelControl::Property::DOWN_FOCUSABLE_ACTOR_ID:
1266 if(value.Get(focusId))
1268 controlImpl.mImpl->mDownFocusableActorId = focusId;
1273 case Toolkit::Control::Property::KEY_INPUT_FOCUS:
1275 if(value.Get<bool>())
1277 controlImpl.SetKeyInputFocus();
1281 controlImpl.ClearKeyInputFocus();
1286 case Toolkit::Control::Property::BACKGROUND:
1290 const Property::Map* map = value.GetMap();
1291 if(map && !map->Empty())
1293 controlImpl.SetBackground(*map);
1295 else if(value.Get(url))
1297 // don't know the size to load
1298 Toolkit::Visual::Base visual = Toolkit::VisualFactory::Get().CreateVisual(url, ImageDimensions());
1301 controlImpl.mImpl->RegisterVisual(Toolkit::Control::Property::BACKGROUND, visual, DepthIndex::BACKGROUND);
1304 else if(value.Get(color))
1306 controlImpl.SetBackgroundColor(color);
1310 // The background is an empty property map, so we should clear the background
1311 controlImpl.ClearBackground();
1316 case Toolkit::Control::Property::MARGIN:
1319 if(value.Get(margin))
1321 controlImpl.mImpl->SetMargin(margin);
1326 case Toolkit::Control::Property::PADDING:
1329 if(value.Get(padding))
1331 controlImpl.mImpl->SetPadding(padding);
1336 case Toolkit::DevelControl::Property::TOOLTIP:
1338 TooltipPtr& tooltipPtr = controlImpl.mImpl->mTooltip;
1341 tooltipPtr = Tooltip::New(control);
1343 tooltipPtr->SetProperties(value);
1347 case Toolkit::DevelControl::Property::SHADOW:
1349 const Property::Map* map = value.GetMap();
1350 if(map && !map->Empty())
1352 controlImpl.mImpl->SetShadow(*map);
1356 // The shadow is an empty property map, so we should clear the shadow
1357 controlImpl.mImpl->ClearShadow();
1362 case Toolkit::DevelControl::Property::ACCESSIBILITY_NAME:
1367 controlImpl.mImpl->mAccessibilityName = name;
1372 case Toolkit::DevelControl::Property::ACCESSIBILITY_DESCRIPTION:
1377 controlImpl.mImpl->mAccessibilityDescription = text;
1382 case Toolkit::DevelControl::Property::ACCESSIBILITY_TRANSLATION_DOMAIN:
1387 controlImpl.mImpl->mAccessibilityTranslationDomain = text;
1392 case Toolkit::DevelControl::Property::ACCESSIBILITY_ROLE:
1394 Dali::Accessibility::Role role;
1397 controlImpl.mImpl->mAccessibilityRole = role;
1402 case Toolkit::DevelControl::Property::ACCESSIBILITY_HIGHLIGHTABLE:
1405 if(value.Get(highlightable))
1407 controlImpl.mImpl->mAccessibilityHighlightable = highlightable;
1412 case Toolkit::DevelControl::Property::ACCESSIBILITY_ATTRIBUTES:
1414 const Property::Map* map = value.GetMap();
1415 if(map && !map->Empty())
1417 controlImpl.mImpl->mAccessibilityAttributes = *map;
1422 case Toolkit::DevelControl::Property::DISPATCH_KEY_EVENTS:
1425 if(value.Get(dispatch))
1427 controlImpl.mImpl->mDispatchKeyEvents = dispatch;
1432 case Toolkit::DevelControl::Property::ACCESSIBILITY_HIDDEN:
1435 if(value.Get(hidden))
1437 controlImpl.mImpl->mAccessibilityHidden = hidden;
1439 auto* accessible = controlImpl.GetAccessibleObject();
1440 auto* parent = dynamic_cast<Dali::Accessibility::ActorAccessible*>(accessible->GetParent());
1443 parent->OnChildrenChanged();
1448 case Toolkit::DevelControl::Property::CLOCKWISE_FOCUSABLE_ACTOR_ID:
1451 if(value.Get(focusId))
1453 controlImpl.mImpl->mClockwiseFocusableActorId = focusId;
1457 case Toolkit::DevelControl::Property::COUNTER_CLOCKWISE_FOCUSABLE_ACTOR_ID:
1460 if(value.Get(focusId))
1462 controlImpl.mImpl->mCounterClockwiseFocusableActorId = focusId;
1467 case Toolkit::DevelControl::Property::AUTOMATION_ID:
1469 std::string automationId;
1470 if(value.Get(automationId))
1472 controlImpl.mImpl->mAutomationId = automationId;
1480 Property::Value Control::Impl::GetProperty(BaseObject* object, Property::Index index)
1482 Property::Value value;
1484 Toolkit::Control control = Toolkit::Control::DownCast(BaseHandle(object));
1488 Control& controlImpl(GetImplementation(control));
1492 case Toolkit::Control::Property::STYLE_NAME:
1494 value = controlImpl.GetStyleName();
1498 case Toolkit::DevelControl::Property::STATE:
1500 value = controlImpl.mImpl->mState;
1504 case Toolkit::DevelControl::Property::SUB_STATE:
1506 value = controlImpl.mImpl->mSubStateName;
1510 case Toolkit::DevelControl::Property::LEFT_FOCUSABLE_ACTOR_ID:
1512 value = controlImpl.mImpl->mLeftFocusableActorId;
1516 case Toolkit::DevelControl::Property::RIGHT_FOCUSABLE_ACTOR_ID:
1518 value = controlImpl.mImpl->mRightFocusableActorId;
1522 case Toolkit::DevelControl::Property::UP_FOCUSABLE_ACTOR_ID:
1524 value = controlImpl.mImpl->mUpFocusableActorId;
1528 case Toolkit::DevelControl::Property::DOWN_FOCUSABLE_ACTOR_ID:
1530 value = controlImpl.mImpl->mDownFocusableActorId;
1534 case Toolkit::Control::Property::KEY_INPUT_FOCUS:
1536 value = controlImpl.HasKeyInputFocus();
1540 case Toolkit::Control::Property::BACKGROUND:
1543 Toolkit::Visual::Base visual = controlImpl.mImpl->GetVisual(Toolkit::Control::Property::BACKGROUND);
1546 visual.CreatePropertyMap(map);
1553 case Toolkit::Control::Property::MARGIN:
1555 value = controlImpl.mImpl->GetMargin();
1559 case Toolkit::Control::Property::PADDING:
1561 value = controlImpl.mImpl->GetPadding();
1565 case Toolkit::DevelControl::Property::TOOLTIP:
1568 if(controlImpl.mImpl->mTooltip)
1570 controlImpl.mImpl->mTooltip->CreatePropertyMap(map);
1576 case Toolkit::DevelControl::Property::SHADOW:
1579 Toolkit::Visual::Base visual = controlImpl.mImpl->GetVisual(Toolkit::DevelControl::Property::SHADOW);
1582 visual.CreatePropertyMap(map);
1589 case Toolkit::DevelControl::Property::ACCESSIBILITY_NAME:
1591 value = controlImpl.mImpl->mAccessibilityName;
1595 case Toolkit::DevelControl::Property::ACCESSIBILITY_DESCRIPTION:
1597 value = controlImpl.mImpl->mAccessibilityDescription;
1601 case Toolkit::DevelControl::Property::ACCESSIBILITY_TRANSLATION_DOMAIN:
1603 value = controlImpl.mImpl->mAccessibilityTranslationDomain;
1607 case Toolkit::DevelControl::Property::ACCESSIBILITY_ROLE:
1609 value = Property::Value(controlImpl.mImpl->mAccessibilityRole);
1613 case Toolkit::DevelControl::Property::ACCESSIBILITY_HIGHLIGHTABLE:
1615 value = controlImpl.mImpl->mAccessibilityHighlightable;
1619 case Toolkit::DevelControl::Property::ACCESSIBILITY_ATTRIBUTES:
1621 value = controlImpl.mImpl->mAccessibilityAttributes;
1625 case Toolkit::DevelControl::Property::DISPATCH_KEY_EVENTS:
1627 value = controlImpl.mImpl->mDispatchKeyEvents;
1631 case Toolkit::DevelControl::Property::ACCESSIBILITY_HIDDEN:
1633 value = controlImpl.mImpl->mAccessibilityHidden;
1637 case Toolkit::DevelControl::Property::CLOCKWISE_FOCUSABLE_ACTOR_ID:
1639 value = controlImpl.mImpl->mClockwiseFocusableActorId;
1643 case Toolkit::DevelControl::Property::COUNTER_CLOCKWISE_FOCUSABLE_ACTOR_ID:
1645 value = controlImpl.mImpl->mCounterClockwiseFocusableActorId;
1649 case Toolkit::DevelControl::Property::AUTOMATION_ID:
1651 value = controlImpl.mImpl->mAutomationId;
1660 void Control::Impl::RemoveAccessibilityAttribute(const std::string& key)
1662 Property::Value* value = mAccessibilityAttributes.Find(key);
1665 mAccessibilityAttributes[key] = Property::Value();
1669 void Control::Impl::ClearAccessibilityAttributes()
1671 mAccessibilityAttributes.Clear();
1674 void Control::Impl::SetAccessibilityReadingInfoType(const Dali::Accessibility::ReadingInfoTypes types)
1676 std::string value{};
1677 if(types[Dali::Accessibility::ReadingInfoType::NAME])
1679 value += READING_INFO_TYPE_NAME;
1681 if(types[Dali::Accessibility::ReadingInfoType::ROLE])
1685 value += READING_INFO_TYPE_SEPARATOR;
1687 value += READING_INFO_TYPE_ROLE;
1689 if(types[Dali::Accessibility::ReadingInfoType::DESCRIPTION])
1693 value += READING_INFO_TYPE_SEPARATOR;
1695 value += READING_INFO_TYPE_DESCRIPTION;
1697 if(types[Dali::Accessibility::ReadingInfoType::STATE])
1701 value += READING_INFO_TYPE_SEPARATOR;
1703 value += READING_INFO_TYPE_STATE;
1705 AppendAccessibilityAttribute(READING_INFO_TYPE_ATTRIBUTE_NAME, value);
1708 Dali::Accessibility::ReadingInfoTypes Control::Impl::GetAccessibilityReadingInfoType() const
1710 std::string value{};
1711 auto place = mAccessibilityAttributes.Find(READING_INFO_TYPE_ATTRIBUTE_NAME);
1718 Dali::Accessibility::ReadingInfoTypes types;
1719 types[Dali::Accessibility::ReadingInfoType::NAME] = true;
1720 types[Dali::Accessibility::ReadingInfoType::ROLE] = true;
1721 types[Dali::Accessibility::ReadingInfoType::DESCRIPTION] = true;
1722 types[Dali::Accessibility::ReadingInfoType::STATE] = true;
1731 Dali::Accessibility::ReadingInfoTypes types;
1733 if(value.find(READING_INFO_TYPE_NAME) != std::string::npos)
1735 types[Dali::Accessibility::ReadingInfoType::NAME] = true;
1737 if(value.find(READING_INFO_TYPE_ROLE) != std::string::npos)
1739 types[Dali::Accessibility::ReadingInfoType::ROLE] = true;
1741 if(value.find(READING_INFO_TYPE_DESCRIPTION) != std::string::npos)
1743 types[Dali::Accessibility::ReadingInfoType::DESCRIPTION] = true;
1745 if(value.find(READING_INFO_TYPE_STATE) != std::string::npos)
1747 types[Dali::Accessibility::ReadingInfoType::STATE] = true;
1753 void Control::Impl::CopyInstancedProperties(RegisteredVisualContainer& visuals, Dictionary<Property::Map>& instancedProperties)
1755 for(RegisteredVisualContainer::Iterator iter = visuals.Begin(); iter != visuals.End(); iter++)
1759 Property::Map instanceMap;
1760 Toolkit::GetImplementation((*iter)->visual).CreateInstancePropertyMap(instanceMap);
1761 instancedProperties.Add((*iter)->visual.GetName(), instanceMap);
1766 void Control::Impl::RemoveVisual(RegisteredVisualContainer& visuals, const std::string& visualName)
1768 Actor self(mControlImpl.Self());
1770 for(RegisteredVisualContainer::Iterator visualIter = visuals.Begin();
1771 visualIter != visuals.End();
1774 Toolkit::Visual::Base visual = (*visualIter)->visual;
1775 if(visual && visual.GetName() == visualName)
1777 Toolkit::GetImplementation(visual).SetOffScene(self);
1778 (*visualIter)->visual.Reset();
1779 visuals.Erase(visualIter);
1785 void Control::Impl::RemoveVisuals(RegisteredVisualContainer& visuals, DictionaryKeys& removeVisuals)
1787 Actor self(mControlImpl.Self());
1788 for(DictionaryKeys::iterator iter = removeVisuals.begin(); iter != removeVisuals.end(); ++iter)
1790 const std::string visualName = *iter;
1791 RemoveVisual(visuals, visualName);
1795 void Control::Impl::RecreateChangedVisuals(Dictionary<Property::Map>& stateVisualsToChange,
1796 Dictionary<Property::Map>& instancedProperties)
1798 Dali::CustomActor handle(mControlImpl.GetOwner());
1799 for(Dictionary<Property::Map>::iterator iter = stateVisualsToChange.Begin();
1800 iter != stateVisualsToChange.End();
1803 const std::string& visualName = (*iter).key;
1804 const Property::Map& toMap = (*iter).entry;
1806 Actor self = mControlImpl.Self();
1807 RegisteredVisualContainer::Iterator registeredVisualsiter;
1808 // Check if visual (visualName) is already registered, this is the current visual.
1809 if(FindVisual(visualName, mVisuals, registeredVisualsiter))
1811 Toolkit::Visual::Base& visual = (*registeredVisualsiter)->visual;
1814 // No longer required to know if the replaced visual's resources are ready
1815 StopObservingVisual(visual);
1817 // If control staged then visuals will be swapped once ready
1818 if(self.GetProperty<bool>(Actor::Property::CONNECTED_TO_SCENE))
1820 // Check if visual is currently in the process of being replaced ( is in removal container )
1821 RegisteredVisualContainer::Iterator visualQueuedForRemoval;
1822 if(FindVisual(visualName, mRemoveVisuals, visualQueuedForRemoval))
1824 // Visual with same visual name is already in removal container so current visual pending
1825 // Only the the last requested visual will be displayed so remove current visual which is staged but not ready.
1826 Toolkit::GetImplementation(visual).SetOffScene(self);
1827 (*registeredVisualsiter)->visual.Reset();
1828 mVisuals.Erase(registeredVisualsiter);
1832 // current visual not already in removal container so add now.
1833 DALI_LOG_INFO(gLogFilter, Debug::Verbose, "RegisterVisual Move current registered visual to removal Queue: %s \n", visualName.c_str());
1834 MoveVisual(registeredVisualsiter, mVisuals, mRemoveVisuals);
1839 // Control not staged or visual disabled so can just erase from registered visuals and new visual will be added later.
1840 (*registeredVisualsiter)->visual.Reset();
1841 mVisuals.Erase(registeredVisualsiter);
1845 const Property::Map* instancedMap = instancedProperties.FindConst(visualName);
1846 Style::ApplyVisual(handle, visualName, toMap, instancedMap);
1851 void Control::Impl::ReplaceStateVisualsAndProperties(const StylePtr oldState, const StylePtr newState, const std::string& subState)
1853 // Collect all old visual names
1854 DictionaryKeys stateVisualsToRemove;
1857 oldState->visuals.GetKeys(stateVisualsToRemove);
1858 if(!subState.empty())
1860 const StylePtr* oldSubState = oldState->subStates.FindConst(subState);
1863 DictionaryKeys subStateVisualsToRemove;
1864 (*oldSubState)->visuals.GetKeys(subStateVisualsToRemove);
1865 Merge(stateVisualsToRemove, subStateVisualsToRemove);
1870 // Collect all new visual properties
1871 Dictionary<Property::Map> stateVisualsToAdd;
1874 stateVisualsToAdd = newState->visuals;
1875 if(!subState.empty())
1877 const StylePtr* newSubState = newState->subStates.FindConst(subState);
1880 stateVisualsToAdd.Merge((*newSubState)->visuals);
1885 // If a name is in both add/remove, move it to change list.
1886 Dictionary<Property::Map> stateVisualsToChange;
1887 FindChangableVisuals(stateVisualsToAdd, stateVisualsToChange, stateVisualsToRemove);
1889 // Copy instanced properties (e.g. text label) of current visuals
1890 Dictionary<Property::Map> instancedProperties;
1891 CopyInstancedProperties(mVisuals, instancedProperties);
1893 // For each visual in remove list, remove from mVisuals
1894 RemoveVisuals(mVisuals, stateVisualsToRemove);
1896 // For each visual in add list, create and add to mVisuals
1897 Dali::CustomActor handle(mControlImpl.GetOwner());
1898 Style::ApplyVisuals(handle, stateVisualsToAdd, instancedProperties);
1900 // For each visual in change list, if it requires a new visual,
1901 // remove old visual, create and add to mVisuals
1902 RecreateChangedVisuals(stateVisualsToChange, instancedProperties);
1905 void Control::Impl::SetState(DevelControl::State newState, bool withTransitions)
1907 DevelControl::State oldState = mState;
1908 Dali::CustomActor handle(mControlImpl.GetOwner());
1909 DALI_LOG_INFO(gLogFilter, Debug::Concise, "Control::Impl::SetState: %s\n", (mState == DevelControl::NORMAL ? "NORMAL" : (mState == DevelControl::FOCUSED ? "FOCUSED" : (mState == DevelControl::DISABLED ? "DISABLED" : "NONE"))));
1911 if(mState != newState)
1913 // If mState was Disabled, and new state is Focused, should probably
1914 // store that fact, e.g. in another property that FocusManager can access.
1917 // Trigger state change and transitions
1918 // Apply new style, if stylemanager is available
1919 Toolkit::StyleManager styleManager = Toolkit::StyleManager::Get();
1922 const StylePtr stylePtr = GetImpl(styleManager).GetRecordedStyle(Toolkit::Control(mControlImpl.GetOwner()));
1926 std::string oldStateName = Scripting::GetEnumerationName<Toolkit::DevelControl::State>(oldState, ControlStateTable, ControlStateTableCount);
1927 std::string newStateName = Scripting::GetEnumerationName<Toolkit::DevelControl::State>(newState, ControlStateTable, ControlStateTableCount);
1929 const StylePtr* newStateStyle = stylePtr->subStates.Find(newStateName);
1930 const StylePtr* oldStateStyle = stylePtr->subStates.Find(oldStateName);
1931 if(oldStateStyle && newStateStyle)
1933 // Only change if both state styles exist
1934 ReplaceStateVisualsAndProperties(*oldStateStyle, *newStateStyle, mSubStateName);
1941 void Control::Impl::SetSubState(const std::string& subStateName, bool withTransitions)
1943 if(mSubStateName != subStateName)
1945 // Get existing sub-state visuals, and unregister them
1946 Dali::CustomActor handle(mControlImpl.GetOwner());
1948 Toolkit::StyleManager styleManager = Toolkit::StyleManager::Get();
1951 const StylePtr stylePtr = GetImpl(styleManager).GetRecordedStyle(Toolkit::Control(mControlImpl.GetOwner()));
1955 std::string stateName = Scripting::GetEnumerationName<Toolkit::DevelControl::State>(mState, ControlStateTable, ControlStateTableCount);
1957 const StylePtr* state = stylePtr->subStates.Find(stateName);
1960 StylePtr stateStyle(*state);
1962 const StylePtr* newStateStyle = stateStyle->subStates.Find(subStateName);
1963 const StylePtr* oldStateStyle = stateStyle->subStates.Find(mSubStateName);
1964 if(oldStateStyle && newStateStyle)
1967 ReplaceStateVisualsAndProperties(*oldStateStyle, *newStateStyle, empty);
1973 mSubStateName = subStateName;
1977 void Control::Impl::OnSceneDisconnection()
1979 Actor self = mControlImpl.Self();
1981 // Any visuals set for replacement but not yet ready should still be registered.
1982 // Reason: If a request was made to register a new visual but the control removed from scene before visual was ready
1983 // then when this control appears back on stage it should use that new visual.
1985 // Iterate through all registered visuals and set off scene
1986 SetVisualsOffScene(mVisuals, self);
1988 // Visuals pending replacement can now be taken out of the removal list and set off scene
1989 // Iterate through all replacement visuals and add to a move queue then set off scene
1990 for(auto removalIter = mRemoveVisuals.Begin(), end = mRemoveVisuals.End(); removalIter != end; removalIter++)
1992 Toolkit::GetImplementation((*removalIter)->visual).SetOffScene(self);
1995 for(auto replacedIter = mVisuals.Begin(), end = mVisuals.End(); replacedIter != end; replacedIter++)
1997 (*replacedIter)->pending = false;
2000 mRemoveVisuals.Clear();
2003 void Control::Impl::SetMargin(Extents margin)
2005 mControlImpl.mImpl->mMargin = margin;
2007 // Trigger a size negotiation request that may be needed when setting a margin.
2008 mControlImpl.RelayoutRequest();
2011 Extents Control::Impl::GetMargin() const
2013 return mControlImpl.mImpl->mMargin;
2016 void Control::Impl::SetPadding(Extents padding)
2018 mControlImpl.mImpl->mPadding = padding;
2020 // Trigger a size negotiation request that may be needed when setting a padding.
2021 mControlImpl.RelayoutRequest();
2024 Extents Control::Impl::GetPadding() const
2026 return mControlImpl.mImpl->mPadding;
2029 void Control::Impl::SetInputMethodContext(InputMethodContext& inputMethodContext)
2031 mInputMethodContext = inputMethodContext;
2034 bool Control::Impl::FilterKeyEvent(const KeyEvent& event)
2036 bool consumed(false);
2038 if(mInputMethodContext)
2040 consumed = mInputMethodContext.FilterEventKey(event);
2045 DevelControl::VisualEventSignalType& Control::Impl::VisualEventSignal()
2047 return mVisualEventSignal;
2050 void Control::Impl::SetShadow(const Property::Map& map)
2052 Toolkit::Visual::Base visual = Toolkit::VisualFactory::Get().CreateVisual(map);
2053 visual.SetName("shadow");
2057 mControlImpl.mImpl->RegisterVisual(Toolkit::DevelControl::Property::SHADOW, visual, DepthIndex::BACKGROUND_EFFECT);
2059 mControlImpl.RelayoutRequest();
2063 void Control::Impl::ClearShadow()
2065 mControlImpl.mImpl->UnregisterVisual(Toolkit::DevelControl::Property::SHADOW);
2067 // Trigger a size negotiation request that may be needed when unregistering a visual.
2068 mControlImpl.RelayoutRequest();
2071 Dali::Property Control::Impl::GetVisualProperty(Dali::Property::Index index, Dali::Property::Key visualPropertyKey)
2073 Toolkit::Visual::Base visual = GetVisualByIndex(mVisuals, index);
2076 Internal::Visual::Base& visualImpl = Toolkit::GetImplementation(visual);
2077 return visualImpl.GetPropertyObject(visualPropertyKey);
2081 return Dali::Property(handle, Property::INVALID_INDEX);
2084 void Control::Impl::CreateTransitions(std::vector<std::pair<Dali::Property::Index, Dali::Property::Map>>& sourceProperties,
2085 std::vector<std::pair<Dali::Property::Index, Dali::Property::Map>>& destinationProperties,
2086 Dali::Toolkit::Control source,
2087 Dali::Toolkit::Control destination)
2089 // Retrieves background properties to be transitioned.
2090 Dali::Property::Map backgroundSourcePropertyMap, backgroundDestinationPropertyMap;
2091 mControlImpl.MakeVisualTransition(backgroundSourcePropertyMap, backgroundDestinationPropertyMap, source, destination, Toolkit::Control::Property::BACKGROUND);
2092 if(backgroundSourcePropertyMap.Count() > 0)
2094 sourceProperties.push_back(std::pair<Dali::Property::Index, Dali::Property::Map>(Toolkit::Control::Property::BACKGROUND, backgroundSourcePropertyMap));
2095 destinationProperties.push_back(std::pair<Dali::Property::Index, Dali::Property::Map>(Toolkit::Control::Property::BACKGROUND, backgroundDestinationPropertyMap));
2098 // Retrieves shadow properties to be transitioned.
2099 Dali::Property::Map shadowSourcePropertyMap, shadowDestinationPropertyMap;
2100 mControlImpl.MakeVisualTransition(shadowSourcePropertyMap, shadowDestinationPropertyMap, source, destination, Toolkit::DevelControl::Property::SHADOW);
2101 if(shadowSourcePropertyMap.Count() > 0)
2103 sourceProperties.push_back(std::pair<Dali::Property::Index, Dali::Property::Map>(Toolkit::DevelControl::Property::SHADOW, shadowSourcePropertyMap));
2104 destinationProperties.push_back(std::pair<Dali::Property::Index, Dali::Property::Map>(Toolkit::DevelControl::Property::SHADOW, shadowDestinationPropertyMap));
2107 // Retrieves transition from inherited class.
2108 mControlImpl.OnCreateTransitions(sourceProperties, destinationProperties, source, destination);
2111 void Control::Impl::UpdateVisualProperties(const std::vector<std::pair<Dali::Property::Index, Dali::Property::Map>>& properties)
2113 for(auto&& data : properties)
2115 if(data.first == Toolkit::Control::Property::BACKGROUND)
2117 DoAction(Toolkit::Control::Property::BACKGROUND, DevelVisual::Action::UPDATE_PROPERTY, data.second);
2119 else if(data.first == Toolkit::DevelControl::Property::SHADOW)
2121 DoAction(Toolkit::DevelControl::Property::SHADOW, DevelVisual::Action::UPDATE_PROPERTY, data.second);
2124 mControlImpl.OnUpdateVisualProperties(properties);
2127 void Control::Impl::EmitResourceReadySignal()
2129 if(!mIsEmittingResourceReadySignal)
2131 // Guard against calls to emit the signal during the callback
2132 mIsEmittingResourceReadySignal = true;
2134 // If the signal handler changes visual, it may become ready during this call & therefore this method will
2135 // get called again recursively. If so, mNeedToEmitResourceReady is set below, and we act on it after that secondary
2136 // invocation has completed by notifying in an Idle callback to prevent further recursion.
2137 Dali::Toolkit::Control handle(mControlImpl.GetOwner());
2138 mResourceReadySignal.Emit(handle);
2140 if(mNeedToEmitResourceReady)
2142 // Add idler to emit the signal again
2145 // The callback manager takes the ownership of the callback object.
2146 mIdleCallback = MakeCallback(this, &Control::Impl::OnIdleCallback);
2147 Adaptor::Get().AddIdle(mIdleCallback, false);
2151 mIsEmittingResourceReadySignal = false;
2155 mNeedToEmitResourceReady = true;
2159 void Control::Impl::OnIdleCallback()
2161 if(mNeedToEmitResourceReady)
2164 mNeedToEmitResourceReady = false;
2166 // A visual is ready so control may need relayouting if staged
2167 if(mControlImpl.Self().GetProperty<bool>(Actor::Property::CONNECTED_TO_SCENE))
2169 mControlImpl.RelayoutRequest();
2172 EmitResourceReadySignal();
2175 // Set the pointer to null as the callback manager deletes the callback after execute it.
2176 mIdleCallback = nullptr;
2179 Toolkit::DevelControl::ControlAccessible* Control::Impl::GetAccessibleObject()
2181 if(!mAccessibleObject)
2183 mAccessibleObject.reset(mControlImpl.CreateAccessibleObject());
2186 return mAccessibleObject.get();
2189 } // namespace Internal
2191 } // namespace Toolkit