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 DALI_ASSERT_ALWAYS(Stage::IsCoreThread() && "Core is not installed. Might call this API from worker thread?");
591 return *internalControl.mImpl;
594 const Control::Impl& Control::Impl::Get(const Internal::Control& internalControl)
596 DALI_ASSERT_ALWAYS(Stage::IsCoreThread() && "Core is not installed. Might call this API from worker thread?");
598 return *internalControl.mImpl;
601 void Control::Impl::CheckHighlightedObjectGeometry()
603 auto accessible = GetAccessibleObject();
604 auto lastPosition = accessible->GetLastPosition();
605 auto accessibleRect = accessible->GetExtents(Dali::Accessibility::CoordinateType::WINDOW);
606 auto rect = GetShowingGeometry(accessibleRect, accessible);
608 switch(mAccessibilityLastScreenRelativeMoveType)
610 case Dali::Accessibility::ScreenRelativeMoveType::OUTSIDE:
612 if(IsShowingGeometryOnScreen(rect))
614 mAccessibilityLastScreenRelativeMoveType = Dali::Accessibility::ScreenRelativeMoveType::INSIDE;
618 case Dali::Accessibility::ScreenRelativeMoveType::INSIDE:
620 if(rect.width < 0 && !Dali::Equals(accessibleRect.x, lastPosition.x))
622 mAccessibilityLastScreenRelativeMoveType = (accessibleRect.x < lastPosition.x) ? Dali::Accessibility::ScreenRelativeMoveType::OUTGOING_TOP_LEFT : Dali::Accessibility::ScreenRelativeMoveType::OUTGOING_BOTTOM_RIGHT;
624 if(rect.height < 0 && !Dali::Equals(accessibleRect.y, lastPosition.y))
626 mAccessibilityLastScreenRelativeMoveType = (accessibleRect.y < lastPosition.y) ? Dali::Accessibility::ScreenRelativeMoveType::OUTGOING_TOP_LEFT : Dali::Accessibility::ScreenRelativeMoveType::OUTGOING_BOTTOM_RIGHT;
628 // notify AT-clients on outgoing moves only
629 if(mAccessibilityLastScreenRelativeMoveType != Dali::Accessibility::ScreenRelativeMoveType::INSIDE)
631 accessible->EmitMovedOutOfScreen(mAccessibilityLastScreenRelativeMoveType);
635 case Dali::Accessibility::ScreenRelativeMoveType::OUTGOING_TOP_LEFT:
636 case Dali::Accessibility::ScreenRelativeMoveType::OUTGOING_BOTTOM_RIGHT:
638 if(IsShowingGeometryOnScreen(rect))
640 mAccessibilityLastScreenRelativeMoveType = Dali::Accessibility::ScreenRelativeMoveType::INSIDE;
644 mAccessibilityLastScreenRelativeMoveType = Dali::Accessibility::ScreenRelativeMoveType::OUTSIDE;
654 accessible->SetLastPosition(Vector2(accessibleRect.x, accessibleRect.y));
657 void Control::Impl::RegisterAccessibilityPositionPropertyNotification()
659 if(mIsAccessibilityPositionPropertyNotificationSet)
663 // set default value until first move of object is detected
664 mAccessibilityLastScreenRelativeMoveType = Dali::Accessibility::ScreenRelativeMoveType::OUTSIDE;
665 // recalculate mAccessibilityLastScreenRelativeMoveType accordingly to the initial position
666 CheckHighlightedObjectGeometry();
667 mAccessibilityPositionNotification = mControlImpl.Self().AddPropertyNotification(Actor::Property::WORLD_POSITION, StepCondition(1.0f, 1.0f));
668 mAccessibilityPositionNotification.SetNotifyMode(PropertyNotification::NOTIFY_ON_CHANGED);
669 mAccessibilityPositionNotification.NotifySignal().Connect(this, [this](PropertyNotification&) { CheckHighlightedObjectGeometry(); });
670 mIsAccessibilityPositionPropertyNotificationSet = true;
673 void Control::Impl::UnregisterAccessibilityPositionPropertyNotification()
675 mControlImpl.Self().RemovePropertyNotification(mAccessibilityPositionNotification);
676 mIsAccessibilityPositionPropertyNotificationSet = false;
679 // Gesture Detection Methods
680 void Control::Impl::PinchDetected(Actor actor, const PinchGesture& pinch)
682 mControlImpl.OnPinch(pinch);
685 void Control::Impl::PanDetected(Actor actor, const PanGesture& pan)
687 mControlImpl.OnPan(pan);
690 void Control::Impl::TapDetected(Actor actor, const TapGesture& tap)
692 mControlImpl.OnTap(tap);
695 void Control::Impl::LongPressDetected(Actor actor, const LongPressGesture& longPress)
697 mControlImpl.OnLongPress(longPress);
700 void Control::Impl::RegisterVisual(Property::Index index, Toolkit::Visual::Base& visual)
702 RegisterVisual(index, visual, VisualState::ENABLED, DepthIndexValue::NOT_SET);
705 void Control::Impl::RegisterVisual(Property::Index index, Toolkit::Visual::Base& visual, int depthIndex)
707 RegisterVisual(index, visual, VisualState::ENABLED, DepthIndexValue::SET, depthIndex);
710 void Control::Impl::RegisterVisual(Property::Index index, Toolkit::Visual::Base& visual, bool enabled)
712 RegisterVisual(index, visual, (enabled ? VisualState::ENABLED : VisualState::DISABLED), DepthIndexValue::NOT_SET);
715 void Control::Impl::RegisterVisual(Property::Index index, Toolkit::Visual::Base& visual, bool enabled, int depthIndex)
717 RegisterVisual(index, visual, (enabled ? VisualState::ENABLED : VisualState::DISABLED), DepthIndexValue::SET, depthIndex);
720 void Control::Impl::RegisterVisual(Property::Index index, Toolkit::Visual::Base& visual, VisualState::Type enabled, DepthIndexValue::Type depthIndexValueSet, int depthIndex)
722 DALI_ASSERT_ALWAYS(Stage::IsCoreThread() && "Core is not installed. Might call this API from worker thread?");
724 DALI_LOG_INFO(gLogFilter, Debug::Concise, "RegisterVisual:%d \n", index);
726 bool visualReplaced(false);
727 Actor self = mControlImpl.Self();
729 // Set the depth index, if not set by caller this will be either the current visual depth, max depth of all visuals
731 int requiredDepthIndex = visual.GetDepthIndex();
733 if(depthIndexValueSet == DepthIndexValue::SET)
735 requiredDepthIndex = depthIndex;
738 // Visual replacement, existing visual should only be removed from stage when replacement ready.
739 if(!mVisuals.Empty())
741 RegisteredVisualContainer::Iterator registeredVisualsiter;
742 // Check if visual (index) is already registered, this is the current visual.
743 if(FindVisual(index, mVisuals, registeredVisualsiter))
745 Toolkit::Visual::Base& currentRegisteredVisual = (*registeredVisualsiter)->visual;
746 if(currentRegisteredVisual)
748 // Store current visual depth index as may need to set the replacement visual to same depth
749 const int currentDepthIndex = (*registeredVisualsiter)->visual.GetDepthIndex();
751 // No longer required to know if the replaced visual's resources are ready
752 StopObservingVisual(currentRegisteredVisual);
754 // If control staged and visual enabled then visuals will be swapped once ready
755 if(self.GetProperty<bool>(Actor::Property::CONNECTED_TO_SCENE) && enabled)
757 // Check if visual is currently in the process of being replaced ( is in removal container )
758 RegisteredVisualContainer::Iterator visualQueuedForRemoval;
759 if(FindVisual(index, mRemoveVisuals, visualQueuedForRemoval))
761 // Visual with same index is already in removal container so current visual pending
762 // Only the the last requested visual will be displayed so remove current visual which is staged but not ready.
763 Toolkit::GetImplementation(currentRegisteredVisual).SetOffScene(self);
764 mVisuals.Erase(registeredVisualsiter);
768 // current visual not already in removal container so add now.
769 DALI_LOG_INFO(gLogFilter, Debug::Verbose, "RegisterVisual Move current registered visual to removal Queue: %d \n", index);
770 MoveVisual(registeredVisualsiter, mVisuals, mRemoveVisuals);
775 // Control not staged or visual disabled so can just erase from registered visuals and new visual will be added later.
776 mVisuals.Erase(registeredVisualsiter);
779 // 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
780 if((depthIndexValueSet == DepthIndexValue::NOT_SET) &&
781 (visual.GetDepthIndex() == 0))
783 requiredDepthIndex = currentDepthIndex;
787 visualReplaced = true;
791 // If not set, set the name of the visual to the same name as the control's property.
792 // ( If the control has been type registered )
793 if(visual.GetName().empty())
795 // returns empty string if index is not found as long as index is not -1
796 std::string visualName = self.GetPropertyName(index);
797 if(!visualName.empty())
799 DALI_LOG_INFO(gLogFilter, Debug::Concise, "Setting visual name for property %d to %s\n", index, visualName.c_str());
800 visual.SetName(visualName);
804 if(!visualReplaced) // New registration entry
806 // 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
807 if((depthIndexValueSet == DepthIndexValue::NOT_SET) &&
808 (mVisuals.Size() > 0) &&
809 (visual.GetDepthIndex() == 0))
811 int maxDepthIndex = std::numeric_limits<int>::min();
813 RegisteredVisualContainer::ConstIterator iter;
814 const RegisteredVisualContainer::ConstIterator endIter = mVisuals.End();
815 for(iter = mVisuals.Begin(); iter != endIter; iter++)
817 const int visualDepthIndex = (*iter)->visual.GetDepthIndex();
818 if(visualDepthIndex > maxDepthIndex)
820 maxDepthIndex = visualDepthIndex;
823 ++maxDepthIndex; // Add one to the current maximum depth index so that our added visual appears on top
824 requiredDepthIndex = std::max(0, maxDepthIndex); // Start at zero if maxDepth index belongs to a background
830 // Set determined depth index
831 visual.SetDepthIndex(requiredDepthIndex);
833 // Monitor when the visual resources are ready
834 StartObservingVisual(visual);
836 DALI_LOG_INFO(gLogFilter, Debug::Concise, "New Visual registration index[%d] depth[%d]\n", index, requiredDepthIndex);
837 RegisteredVisual* newRegisteredVisual = new RegisteredVisual(index, visual, (enabled == VisualState::ENABLED ? true : false), (visualReplaced && enabled));
838 mVisuals.PushBack(newRegisteredVisual);
840 Internal::Visual::Base& visualImpl = Toolkit::GetImplementation(visual);
841 // Put on stage if enabled and the control is already on the stage
842 if((enabled == VisualState::ENABLED) && self.GetProperty<bool>(Actor::Property::CONNECTED_TO_SCENE))
844 visualImpl.SetOnScene(self);
846 else if(enabled && visualImpl.IsResourceReady()) // When not being staged, check if visual already 'ResourceReady' before it was Registered. ( Resource may have been loaded already )
848 ResourceReady(visualImpl);
852 DALI_LOG_INFO(gLogFilter, Debug::Verbose, "Control::RegisterVisual() Registered %s(%d), enabled:%s\n", visual.GetName().c_str(), index, enabled ? "true" : "false");
855 void Control::Impl::UnregisterVisual(Property::Index index)
857 DALI_ASSERT_ALWAYS(Stage::IsCoreThread() && "Core is not installed. Might call this API from worker thread?");
859 RegisteredVisualContainer::Iterator iter;
860 if(FindVisual(index, mVisuals, iter))
862 // stop observing visual
863 StopObservingVisual((*iter)->visual);
865 Actor self(mControlImpl.Self());
866 Toolkit::GetImplementation((*iter)->visual).SetOffScene(self);
867 (*iter)->visual.Reset();
868 mVisuals.Erase(iter);
871 if(FindVisual(index, mRemoveVisuals, iter))
873 Actor self(mControlImpl.Self());
874 Toolkit::GetImplementation((*iter)->visual).SetOffScene(self);
875 (*iter)->pending = false;
876 (*iter)->visual.Reset();
877 mRemoveVisuals.Erase(iter);
881 Toolkit::Visual::Base Control::Impl::GetVisual(Property::Index index) const
883 RegisteredVisualContainer::Iterator iter;
884 if(FindVisual(index, mVisuals, iter))
886 return (*iter)->visual;
889 return Toolkit::Visual::Base();
892 void Control::Impl::EnableVisual(Property::Index index, bool enable)
894 DALI_LOG_INFO(gLogFilter, Debug::General, "Control::EnableVisual(%d, %s)\n", index, enable ? "T" : "F");
896 RegisteredVisualContainer::Iterator iter;
897 if(FindVisual(index, mVisuals, iter))
899 if((*iter)->enabled == enable)
901 DALI_LOG_INFO(gLogFilter, Debug::Verbose, "Control::EnableVisual Visual %s(%d) already %s\n", (*iter)->visual.GetName().c_str(), index, enable ? "enabled" : "disabled");
905 (*iter)->enabled = enable;
906 Actor parentActor = mControlImpl.Self();
907 if(mControlImpl.Self().GetProperty<bool>(Actor::Property::CONNECTED_TO_SCENE)) // If control not on Scene then Visual will be added when SceneConnection is called.
911 DALI_LOG_INFO(gLogFilter, Debug::Verbose, "Control::EnableVisual Setting %s(%d) on stage \n", (*iter)->visual.GetName().c_str(), index);
912 Toolkit::GetImplementation((*iter)->visual).SetOnScene(parentActor);
916 DALI_LOG_INFO(gLogFilter, Debug::Verbose, "Control::EnableVisual Setting %s(%d) off stage \n", (*iter)->visual.GetName().c_str(), index);
917 Toolkit::GetImplementation((*iter)->visual).SetOffScene(parentActor); // No need to call if control not staged.
923 DALI_LOG_WARNING("Control::EnableVisual(%d, %s) FAILED - NO SUCH VISUAL\n", index, enable ? "T" : "F");
927 bool Control::Impl::IsVisualEnabled(Property::Index index) const
929 RegisteredVisualContainer::Iterator iter;
930 if(FindVisual(index, mVisuals, iter))
932 return (*iter)->enabled;
937 void Control::Impl::EnableReadyTransitionOverriden(Toolkit::Visual::Base& visual, bool enable)
939 DALI_LOG_INFO(gLogFilter, Debug::General, "Control::EnableReadyTransitionOverriden(%p, %s)\n", visual, enable ? "T" : "F");
941 RegisteredVisualContainer::Iterator iter;
942 if(FindVisual(visual, mVisuals, iter))
944 if((*iter)->overideReadyTransition == enable)
946 DALI_LOG_INFO(gLogFilter, Debug::Verbose, "Control::EnableReadyTransitionOverriden Visual %s(%p) already %s\n", (*iter)->visual.GetName().c_str(), visual, enable ? "enabled" : "disabled");
950 (*iter)->overideReadyTransition = enable;
954 void Control::Impl::StopObservingVisual(Toolkit::Visual::Base& visual)
956 Internal::Visual::Base& visualImpl = Toolkit::GetImplementation(visual);
958 // Stop observing the visual
959 visualImpl.RemoveEventObserver(*this);
962 void Control::Impl::StartObservingVisual(Toolkit::Visual::Base& visual)
964 Internal::Visual::Base& visualImpl = Toolkit::GetImplementation(visual);
966 // start observing the visual for events
967 visualImpl.AddEventObserver(*this);
970 void Control::Impl::ResourceReady()
972 DALI_ASSERT_ALWAYS(Stage::IsCoreThread() && "Core is not installed. Might call this API from worker thread?");
974 // Emit signal if all enabled visuals registered by the control are ready or there are no visuals.
975 if(IsResourceReady())
977 EmitResourceReadySignal();
981 // Called by a Visual when it's resource is ready
982 void Control::Impl::ResourceReady(Visual::Base& object)
984 DALI_LOG_INFO(gLogFilter, Debug::Verbose, "Control::Impl::ResourceReady() replacements pending[%d]\n", mRemoveVisuals.Count());
986 Actor self = mControlImpl.Self();
988 RegisteredVisualContainer::Iterator registeredIter;
990 // A resource is ready, find resource in the registered visuals container and get its index
991 if(!FindVisual(object, mVisuals, registeredIter))
996 RegisteredVisualContainer::Iterator visualToRemoveIter;
997 // Find visual with the same index in the removal container
998 // Set if off stage as it's replacement is now ready.
999 // Remove if from removal list as now removed from stage.
1000 // Set Pending flag on the ready visual to false as now ready.
1001 if(FindVisual((*registeredIter)->index, mRemoveVisuals, visualToRemoveIter))
1003 (*registeredIter)->pending = false;
1004 if(!((*visualToRemoveIter)->overideReadyTransition))
1006 Toolkit::GetImplementation((*visualToRemoveIter)->visual).SetOffScene(self);
1008 mRemoveVisuals.Erase(visualToRemoveIter);
1011 // A visual is ready so control may need relayouting if staged
1012 RelayoutRequest(object);
1014 // Called by a Visual when it's resource is ready
1015 if(((*registeredIter)->enabled))
1021 void Control::Impl::NotifyVisualEvent(Visual::Base& object, Property::Index signalId)
1023 for(auto registeredIter = mVisuals.Begin(), end = mVisuals.End(); registeredIter != end; ++registeredIter)
1025 Internal::Visual::Base& registeredVisualImpl = Toolkit::GetImplementation((*registeredIter)->visual);
1026 if(&object == ®isteredVisualImpl)
1028 Dali::Toolkit::Control handle(mControlImpl.GetOwner());
1029 mVisualEventSignal.Emit(handle, (*registeredIter)->index, signalId);
1035 void Control::Impl::RelayoutRequest(Visual::Base& object)
1037 if(mControlImpl.Self().GetProperty<bool>(Actor::Property::CONNECTED_TO_SCENE))
1039 mControlImpl.RelayoutRequest();
1043 bool Control::Impl::IsResourceReady() const
1045 // Iterate through and check all the enabled visuals are ready
1046 for(auto visualIter = mVisuals.Begin();
1047 visualIter != mVisuals.End();
1050 const Toolkit::Visual::Base visual = (*visualIter)->visual;
1051 const Internal::Visual::Base& visualImpl = Toolkit::GetImplementation(visual);
1053 // one of the enabled visuals is not ready
1054 if(!visualImpl.IsResourceReady() && (*visualIter)->enabled)
1062 Toolkit::Visual::ResourceStatus Control::Impl::GetVisualResourceStatus(Property::Index index) const
1064 RegisteredVisualContainer::Iterator iter;
1065 if(FindVisual(index, mVisuals, iter))
1067 const Toolkit::Visual::Base visual = (*iter)->visual;
1068 const Internal::Visual::Base& visualImpl = Toolkit::GetImplementation(visual);
1069 return visualImpl.GetResourceStatus();
1072 return Toolkit::Visual::ResourceStatus::PREPARING;
1075 void Control::Impl::AddTransitions(Dali::Animation& animation,
1076 const Toolkit::TransitionData& handle,
1077 bool createAnimation)
1079 // Setup a Transition from TransitionData.
1080 const Internal::TransitionData& transitionData = Toolkit::GetImplementation(handle);
1081 TransitionData::Iterator end = transitionData.End();
1082 for(TransitionData::Iterator iter = transitionData.Begin();
1086 TransitionData::Animator* animator = (*iter);
1088 Toolkit::Visual::Base visual = GetVisualByName(mVisuals, animator->objectName);
1092 #if defined(DEBUG_ENABLED)
1093 Dali::TypeInfo typeInfo;
1094 ControlWrapper* controlWrapperImpl = dynamic_cast<ControlWrapper*>(&mControlImpl);
1095 if(controlWrapperImpl)
1097 typeInfo = controlWrapperImpl->GetTypeInfo();
1100 DALI_LOG_INFO(gLogFilter, Debug::Concise, "CreateTransition: Found %s visual for %s\n", visual.GetName().c_str(), typeInfo ? typeInfo.GetName().c_str() : "Unknown");
1102 Internal::Visual::Base& visualImpl = Toolkit::GetImplementation(visual);
1103 visualImpl.AnimateProperty(animation, *animator);
1107 DALI_LOG_INFO(gLogFilter, Debug::Concise, "CreateTransition: Could not find visual. Trying actors");
1108 // Otherwise, try any actor children of control (Including the control)
1109 Actor child = mControlImpl.Self().FindChildByName(animator->objectName);
1112 Property::Index propertyIndex = child.GetPropertyIndex(animator->propertyKey);
1113 if(propertyIndex != Property::INVALID_INDEX)
1115 if(animator->animate == false)
1117 if(animator->targetValue.GetType() != Property::NONE)
1119 child.SetProperty(propertyIndex, animator->targetValue);
1122 else // animate the property
1124 if(animator->initialValue.GetType() != Property::NONE)
1126 child.SetProperty(propertyIndex, animator->initialValue);
1129 if(createAnimation && !animation)
1131 animation = Dali::Animation::New(0.1f);
1134 animation.AnimateTo(Property(child, propertyIndex),
1135 animator->targetValue,
1136 animator->alphaFunction,
1137 TimePeriod(animator->timePeriodDelay,
1138 animator->timePeriodDuration));
1146 Dali::Animation Control::Impl::CreateTransition(const Toolkit::TransitionData& transitionData)
1148 Dali::Animation transition;
1150 if(transitionData.Count() > 0)
1152 AddTransitions(transition, transitionData, true);
1157 void Control::Impl::DoAction(Dali::Property::Index visualIndex, Dali::Property::Index actionId, const Dali::Property::Value attributes)
1159 RegisteredVisualContainer::Iterator iter;
1160 if(FindVisual(visualIndex, mVisuals, iter))
1162 Toolkit::GetImplementation((*iter)->visual).DoAction(actionId, attributes);
1166 void Control::Impl::DoActionExtension(Dali::Property::Index visualIndex, Dali::Property::Index actionId, Dali::Any attributes)
1168 RegisteredVisualContainer::Iterator iter;
1169 if(FindVisual(visualIndex, mVisuals, iter))
1171 Toolkit::GetImplementation((*iter)->visual).DoActionExtension(actionId, attributes);
1175 void Control::Impl::AppendAccessibilityAttribute(const std::string& key, const std::string value)
1177 Property::Value* checkedValue = mAccessibilityAttributes.Find(key);
1180 mAccessibilityAttributes[key] = Property::Value(value);
1184 mAccessibilityAttributes.Insert(key, value);
1188 void Control::Impl::SetProperty(BaseObject* object, Property::Index index, const Property::Value& value)
1190 DALI_ASSERT_ALWAYS(Stage::IsCoreThread() && "Core is not installed. Might call this API from worker thread?");
1192 Toolkit::Control control = Toolkit::Control::DownCast(BaseHandle(object));
1196 Control& controlImpl(GetImplementation(control));
1200 case Toolkit::Control::Property::STYLE_NAME:
1202 controlImpl.SetStyleName(value.Get<std::string>());
1206 case Toolkit::DevelControl::Property::STATE:
1208 bool withTransitions = true;
1209 const Property::Value* valuePtr = &value;
1210 const Property::Map* map = value.GetMap();
1213 Property::Value* value2 = map->Find("withTransitions");
1216 withTransitions = value2->Get<bool>();
1219 valuePtr = map->Find("state");
1224 Toolkit::DevelControl::State state(controlImpl.mImpl->mState);
1225 if(Scripting::GetEnumerationProperty<Toolkit::DevelControl::State>(*valuePtr, ControlStateTable, ControlStateTableCount, state))
1227 controlImpl.mImpl->SetState(state, withTransitions);
1233 case Toolkit::DevelControl::Property::SUB_STATE:
1235 std::string subState;
1236 if(value.Get(subState))
1238 controlImpl.mImpl->SetSubState(subState);
1243 case Toolkit::DevelControl::Property::LEFT_FOCUSABLE_ACTOR_ID:
1246 if(value.Get(focusId))
1248 controlImpl.mImpl->mLeftFocusableActorId = focusId;
1253 case Toolkit::DevelControl::Property::RIGHT_FOCUSABLE_ACTOR_ID:
1256 if(value.Get(focusId))
1258 controlImpl.mImpl->mRightFocusableActorId = focusId;
1263 case Toolkit::DevelControl::Property::UP_FOCUSABLE_ACTOR_ID:
1266 if(value.Get(focusId))
1268 controlImpl.mImpl->mUpFocusableActorId = focusId;
1273 case Toolkit::DevelControl::Property::DOWN_FOCUSABLE_ACTOR_ID:
1276 if(value.Get(focusId))
1278 controlImpl.mImpl->mDownFocusableActorId = focusId;
1283 case Toolkit::Control::Property::KEY_INPUT_FOCUS:
1285 if(value.Get<bool>())
1287 controlImpl.SetKeyInputFocus();
1291 controlImpl.ClearKeyInputFocus();
1296 case Toolkit::Control::Property::BACKGROUND:
1300 const Property::Map* map = value.GetMap();
1301 if(map && !map->Empty())
1303 controlImpl.SetBackground(*map);
1305 else if(value.Get(url))
1307 // don't know the size to load
1308 Toolkit::Visual::Base visual = Toolkit::VisualFactory::Get().CreateVisual(url, ImageDimensions());
1311 controlImpl.mImpl->RegisterVisual(Toolkit::Control::Property::BACKGROUND, visual, DepthIndex::BACKGROUND);
1314 else if(value.Get(color))
1316 controlImpl.SetBackgroundColor(color);
1320 // The background is an empty property map, so we should clear the background
1321 controlImpl.ClearBackground();
1326 case Toolkit::Control::Property::MARGIN:
1329 if(value.Get(margin))
1331 controlImpl.mImpl->SetMargin(margin);
1336 case Toolkit::Control::Property::PADDING:
1339 if(value.Get(padding))
1341 controlImpl.mImpl->SetPadding(padding);
1346 case Toolkit::DevelControl::Property::TOOLTIP:
1348 TooltipPtr& tooltipPtr = controlImpl.mImpl->mTooltip;
1351 tooltipPtr = Tooltip::New(control);
1353 tooltipPtr->SetProperties(value);
1357 case Toolkit::DevelControl::Property::SHADOW:
1359 const Property::Map* map = value.GetMap();
1360 if(map && !map->Empty())
1362 controlImpl.mImpl->SetShadow(*map);
1366 // The shadow is an empty property map, so we should clear the shadow
1367 controlImpl.mImpl->ClearShadow();
1372 case Toolkit::DevelControl::Property::ACCESSIBILITY_NAME:
1377 controlImpl.mImpl->mAccessibilityName = name;
1382 case Toolkit::DevelControl::Property::ACCESSIBILITY_DESCRIPTION:
1387 controlImpl.mImpl->mAccessibilityDescription = text;
1392 case Toolkit::DevelControl::Property::ACCESSIBILITY_TRANSLATION_DOMAIN:
1397 controlImpl.mImpl->mAccessibilityTranslationDomain = text;
1402 case Toolkit::DevelControl::Property::ACCESSIBILITY_ROLE:
1404 Dali::Accessibility::Role role;
1407 controlImpl.mImpl->mAccessibilityRole = role;
1412 case Toolkit::DevelControl::Property::ACCESSIBILITY_HIGHLIGHTABLE:
1415 if(value.Get(highlightable))
1417 controlImpl.mImpl->mAccessibilityHighlightable = highlightable;
1422 case Toolkit::DevelControl::Property::ACCESSIBILITY_ATTRIBUTES:
1424 const Property::Map* map = value.GetMap();
1425 if(map && !map->Empty())
1427 controlImpl.mImpl->mAccessibilityAttributes = *map;
1432 case Toolkit::DevelControl::Property::DISPATCH_KEY_EVENTS:
1435 if(value.Get(dispatch))
1437 controlImpl.mImpl->mDispatchKeyEvents = dispatch;
1442 case Toolkit::DevelControl::Property::ACCESSIBILITY_HIDDEN:
1445 if(value.Get(hidden))
1447 controlImpl.mImpl->mAccessibilityHidden = hidden;
1449 auto* accessible = controlImpl.GetAccessibleObject();
1450 auto* parent = dynamic_cast<Dali::Accessibility::ActorAccessible*>(accessible->GetParent());
1453 parent->OnChildrenChanged();
1458 case Toolkit::DevelControl::Property::CLOCKWISE_FOCUSABLE_ACTOR_ID:
1461 if(value.Get(focusId))
1463 controlImpl.mImpl->mClockwiseFocusableActorId = focusId;
1467 case Toolkit::DevelControl::Property::COUNTER_CLOCKWISE_FOCUSABLE_ACTOR_ID:
1470 if(value.Get(focusId))
1472 controlImpl.mImpl->mCounterClockwiseFocusableActorId = focusId;
1477 case Toolkit::DevelControl::Property::AUTOMATION_ID:
1479 std::string automationId;
1480 if(value.Get(automationId))
1482 controlImpl.mImpl->mAutomationId = automationId;
1490 Property::Value Control::Impl::GetProperty(BaseObject* object, Property::Index index)
1492 DALI_ASSERT_ALWAYS(Stage::IsCoreThread() && "Core is not installed. Might call this API from worker thread?");
1494 Property::Value value;
1496 Toolkit::Control control = Toolkit::Control::DownCast(BaseHandle(object));
1500 Control& controlImpl(GetImplementation(control));
1504 case Toolkit::Control::Property::STYLE_NAME:
1506 value = controlImpl.GetStyleName();
1510 case Toolkit::DevelControl::Property::STATE:
1512 value = controlImpl.mImpl->mState;
1516 case Toolkit::DevelControl::Property::SUB_STATE:
1518 value = controlImpl.mImpl->mSubStateName;
1522 case Toolkit::DevelControl::Property::LEFT_FOCUSABLE_ACTOR_ID:
1524 value = controlImpl.mImpl->mLeftFocusableActorId;
1528 case Toolkit::DevelControl::Property::RIGHT_FOCUSABLE_ACTOR_ID:
1530 value = controlImpl.mImpl->mRightFocusableActorId;
1534 case Toolkit::DevelControl::Property::UP_FOCUSABLE_ACTOR_ID:
1536 value = controlImpl.mImpl->mUpFocusableActorId;
1540 case Toolkit::DevelControl::Property::DOWN_FOCUSABLE_ACTOR_ID:
1542 value = controlImpl.mImpl->mDownFocusableActorId;
1546 case Toolkit::Control::Property::KEY_INPUT_FOCUS:
1548 value = controlImpl.HasKeyInputFocus();
1552 case Toolkit::Control::Property::BACKGROUND:
1555 Toolkit::Visual::Base visual = controlImpl.mImpl->GetVisual(Toolkit::Control::Property::BACKGROUND);
1558 visual.CreatePropertyMap(map);
1565 case Toolkit::Control::Property::MARGIN:
1567 value = controlImpl.mImpl->GetMargin();
1571 case Toolkit::Control::Property::PADDING:
1573 value = controlImpl.mImpl->GetPadding();
1577 case Toolkit::DevelControl::Property::TOOLTIP:
1580 if(controlImpl.mImpl->mTooltip)
1582 controlImpl.mImpl->mTooltip->CreatePropertyMap(map);
1588 case Toolkit::DevelControl::Property::SHADOW:
1591 Toolkit::Visual::Base visual = controlImpl.mImpl->GetVisual(Toolkit::DevelControl::Property::SHADOW);
1594 visual.CreatePropertyMap(map);
1601 case Toolkit::DevelControl::Property::ACCESSIBILITY_NAME:
1603 value = controlImpl.mImpl->mAccessibilityName;
1607 case Toolkit::DevelControl::Property::ACCESSIBILITY_DESCRIPTION:
1609 value = controlImpl.mImpl->mAccessibilityDescription;
1613 case Toolkit::DevelControl::Property::ACCESSIBILITY_TRANSLATION_DOMAIN:
1615 value = controlImpl.mImpl->mAccessibilityTranslationDomain;
1619 case Toolkit::DevelControl::Property::ACCESSIBILITY_ROLE:
1621 value = Property::Value(controlImpl.mImpl->mAccessibilityRole);
1625 case Toolkit::DevelControl::Property::ACCESSIBILITY_HIGHLIGHTABLE:
1627 value = controlImpl.mImpl->mAccessibilityHighlightable;
1631 case Toolkit::DevelControl::Property::ACCESSIBILITY_ATTRIBUTES:
1633 value = controlImpl.mImpl->mAccessibilityAttributes;
1637 case Toolkit::DevelControl::Property::DISPATCH_KEY_EVENTS:
1639 value = controlImpl.mImpl->mDispatchKeyEvents;
1643 case Toolkit::DevelControl::Property::ACCESSIBILITY_HIDDEN:
1645 value = controlImpl.mImpl->mAccessibilityHidden;
1649 case Toolkit::DevelControl::Property::CLOCKWISE_FOCUSABLE_ACTOR_ID:
1651 value = controlImpl.mImpl->mClockwiseFocusableActorId;
1655 case Toolkit::DevelControl::Property::COUNTER_CLOCKWISE_FOCUSABLE_ACTOR_ID:
1657 value = controlImpl.mImpl->mCounterClockwiseFocusableActorId;
1661 case Toolkit::DevelControl::Property::AUTOMATION_ID:
1663 value = controlImpl.mImpl->mAutomationId;
1672 void Control::Impl::RemoveAccessibilityAttribute(const std::string& key)
1674 Property::Value* value = mAccessibilityAttributes.Find(key);
1677 mAccessibilityAttributes[key] = Property::Value();
1681 void Control::Impl::ClearAccessibilityAttributes()
1683 mAccessibilityAttributes.Clear();
1686 void Control::Impl::SetAccessibilityReadingInfoType(const Dali::Accessibility::ReadingInfoTypes types)
1688 std::string value{};
1689 if(types[Dali::Accessibility::ReadingInfoType::NAME])
1691 value += READING_INFO_TYPE_NAME;
1693 if(types[Dali::Accessibility::ReadingInfoType::ROLE])
1697 value += READING_INFO_TYPE_SEPARATOR;
1699 value += READING_INFO_TYPE_ROLE;
1701 if(types[Dali::Accessibility::ReadingInfoType::DESCRIPTION])
1705 value += READING_INFO_TYPE_SEPARATOR;
1707 value += READING_INFO_TYPE_DESCRIPTION;
1709 if(types[Dali::Accessibility::ReadingInfoType::STATE])
1713 value += READING_INFO_TYPE_SEPARATOR;
1715 value += READING_INFO_TYPE_STATE;
1717 AppendAccessibilityAttribute(READING_INFO_TYPE_ATTRIBUTE_NAME, value);
1720 Dali::Accessibility::ReadingInfoTypes Control::Impl::GetAccessibilityReadingInfoType() const
1722 std::string value{};
1723 auto place = mAccessibilityAttributes.Find(READING_INFO_TYPE_ATTRIBUTE_NAME);
1730 Dali::Accessibility::ReadingInfoTypes types;
1731 types[Dali::Accessibility::ReadingInfoType::NAME] = true;
1732 types[Dali::Accessibility::ReadingInfoType::ROLE] = true;
1733 types[Dali::Accessibility::ReadingInfoType::DESCRIPTION] = true;
1734 types[Dali::Accessibility::ReadingInfoType::STATE] = true;
1743 Dali::Accessibility::ReadingInfoTypes types;
1745 if(value.find(READING_INFO_TYPE_NAME) != std::string::npos)
1747 types[Dali::Accessibility::ReadingInfoType::NAME] = true;
1749 if(value.find(READING_INFO_TYPE_ROLE) != std::string::npos)
1751 types[Dali::Accessibility::ReadingInfoType::ROLE] = true;
1753 if(value.find(READING_INFO_TYPE_DESCRIPTION) != std::string::npos)
1755 types[Dali::Accessibility::ReadingInfoType::DESCRIPTION] = true;
1757 if(value.find(READING_INFO_TYPE_STATE) != std::string::npos)
1759 types[Dali::Accessibility::ReadingInfoType::STATE] = true;
1765 void Control::Impl::CopyInstancedProperties(RegisteredVisualContainer& visuals, Dictionary<Property::Map>& instancedProperties)
1767 for(RegisteredVisualContainer::Iterator iter = visuals.Begin(); iter != visuals.End(); iter++)
1771 Property::Map instanceMap;
1772 Toolkit::GetImplementation((*iter)->visual).CreateInstancePropertyMap(instanceMap);
1773 instancedProperties.Add((*iter)->visual.GetName(), instanceMap);
1778 void Control::Impl::RemoveVisual(RegisteredVisualContainer& visuals, const std::string& visualName)
1780 Actor self(mControlImpl.Self());
1782 for(RegisteredVisualContainer::Iterator visualIter = visuals.Begin();
1783 visualIter != visuals.End();
1786 Toolkit::Visual::Base visual = (*visualIter)->visual;
1787 if(visual && visual.GetName() == visualName)
1789 Toolkit::GetImplementation(visual).SetOffScene(self);
1790 (*visualIter)->visual.Reset();
1791 visuals.Erase(visualIter);
1797 void Control::Impl::RemoveVisuals(RegisteredVisualContainer& visuals, DictionaryKeys& removeVisuals)
1799 Actor self(mControlImpl.Self());
1800 for(DictionaryKeys::iterator iter = removeVisuals.begin(); iter != removeVisuals.end(); ++iter)
1802 const std::string visualName = *iter;
1803 RemoveVisual(visuals, visualName);
1807 void Control::Impl::RecreateChangedVisuals(Dictionary<Property::Map>& stateVisualsToChange,
1808 Dictionary<Property::Map>& instancedProperties)
1810 Dali::CustomActor handle(mControlImpl.GetOwner());
1811 for(Dictionary<Property::Map>::iterator iter = stateVisualsToChange.Begin();
1812 iter != stateVisualsToChange.End();
1815 const std::string& visualName = (*iter).key;
1816 const Property::Map& toMap = (*iter).entry;
1818 Actor self = mControlImpl.Self();
1819 RegisteredVisualContainer::Iterator registeredVisualsiter;
1820 // Check if visual (visualName) is already registered, this is the current visual.
1821 if(FindVisual(visualName, mVisuals, registeredVisualsiter))
1823 Toolkit::Visual::Base& visual = (*registeredVisualsiter)->visual;
1826 // No longer required to know if the replaced visual's resources are ready
1827 StopObservingVisual(visual);
1829 // If control staged then visuals will be swapped once ready
1830 if(self.GetProperty<bool>(Actor::Property::CONNECTED_TO_SCENE))
1832 // Check if visual is currently in the process of being replaced ( is in removal container )
1833 RegisteredVisualContainer::Iterator visualQueuedForRemoval;
1834 if(FindVisual(visualName, mRemoveVisuals, visualQueuedForRemoval))
1836 // Visual with same visual name is already in removal container so current visual pending
1837 // Only the the last requested visual will be displayed so remove current visual which is staged but not ready.
1838 Toolkit::GetImplementation(visual).SetOffScene(self);
1839 (*registeredVisualsiter)->visual.Reset();
1840 mVisuals.Erase(registeredVisualsiter);
1844 // current visual not already in removal container so add now.
1845 DALI_LOG_INFO(gLogFilter, Debug::Verbose, "RegisterVisual Move current registered visual to removal Queue: %s \n", visualName.c_str());
1846 MoveVisual(registeredVisualsiter, mVisuals, mRemoveVisuals);
1851 // Control not staged or visual disabled so can just erase from registered visuals and new visual will be added later.
1852 (*registeredVisualsiter)->visual.Reset();
1853 mVisuals.Erase(registeredVisualsiter);
1857 const Property::Map* instancedMap = instancedProperties.FindConst(visualName);
1858 Style::ApplyVisual(handle, visualName, toMap, instancedMap);
1863 void Control::Impl::ReplaceStateVisualsAndProperties(const StylePtr oldState, const StylePtr newState, const std::string& subState)
1865 DALI_ASSERT_ALWAYS(Stage::IsCoreThread() && "Core is not installed. Might call this API from worker thread?");
1867 // Collect all old visual names
1868 DictionaryKeys stateVisualsToRemove;
1871 oldState->visuals.GetKeys(stateVisualsToRemove);
1872 if(!subState.empty())
1874 const StylePtr* oldSubState = oldState->subStates.FindConst(subState);
1877 DictionaryKeys subStateVisualsToRemove;
1878 (*oldSubState)->visuals.GetKeys(subStateVisualsToRemove);
1879 Merge(stateVisualsToRemove, subStateVisualsToRemove);
1884 // Collect all new visual properties
1885 Dictionary<Property::Map> stateVisualsToAdd;
1888 stateVisualsToAdd = newState->visuals;
1889 if(!subState.empty())
1891 const StylePtr* newSubState = newState->subStates.FindConst(subState);
1894 stateVisualsToAdd.Merge((*newSubState)->visuals);
1899 // If a name is in both add/remove, move it to change list.
1900 Dictionary<Property::Map> stateVisualsToChange;
1901 FindChangableVisuals(stateVisualsToAdd, stateVisualsToChange, stateVisualsToRemove);
1903 // Copy instanced properties (e.g. text label) of current visuals
1904 Dictionary<Property::Map> instancedProperties;
1905 CopyInstancedProperties(mVisuals, instancedProperties);
1907 // For each visual in remove list, remove from mVisuals
1908 RemoveVisuals(mVisuals, stateVisualsToRemove);
1910 // For each visual in add list, create and add to mVisuals
1911 Dali::CustomActor handle(mControlImpl.GetOwner());
1912 Style::ApplyVisuals(handle, stateVisualsToAdd, instancedProperties);
1914 // For each visual in change list, if it requires a new visual,
1915 // remove old visual, create and add to mVisuals
1916 RecreateChangedVisuals(stateVisualsToChange, instancedProperties);
1919 void Control::Impl::SetState(DevelControl::State newState, bool withTransitions)
1921 DevelControl::State oldState = mState;
1922 Dali::CustomActor handle(mControlImpl.GetOwner());
1923 DALI_LOG_INFO(gLogFilter, Debug::Concise, "Control::Impl::SetState: %s\n", (mState == DevelControl::NORMAL ? "NORMAL" : (mState == DevelControl::FOCUSED ? "FOCUSED" : (mState == DevelControl::DISABLED ? "DISABLED" : "NONE"))));
1925 if(mState != newState)
1927 // If mState was Disabled, and new state is Focused, should probably
1928 // store that fact, e.g. in another property that FocusManager can access.
1931 // Trigger state change and transitions
1932 // Apply new style, if stylemanager is available
1933 Toolkit::StyleManager styleManager = Toolkit::StyleManager::Get();
1936 const StylePtr stylePtr = GetImpl(styleManager).GetRecordedStyle(Toolkit::Control(mControlImpl.GetOwner()));
1940 std::string oldStateName = Scripting::GetEnumerationName<Toolkit::DevelControl::State>(oldState, ControlStateTable, ControlStateTableCount);
1941 std::string newStateName = Scripting::GetEnumerationName<Toolkit::DevelControl::State>(newState, ControlStateTable, ControlStateTableCount);
1943 const StylePtr* newStateStyle = stylePtr->subStates.Find(newStateName);
1944 const StylePtr* oldStateStyle = stylePtr->subStates.Find(oldStateName);
1945 if(oldStateStyle && newStateStyle)
1947 // Only change if both state styles exist
1948 ReplaceStateVisualsAndProperties(*oldStateStyle, *newStateStyle, mSubStateName);
1955 void Control::Impl::SetSubState(const std::string& subStateName, bool withTransitions)
1957 if(mSubStateName != subStateName)
1959 // Get existing sub-state visuals, and unregister them
1960 Dali::CustomActor handle(mControlImpl.GetOwner());
1962 Toolkit::StyleManager styleManager = Toolkit::StyleManager::Get();
1965 const StylePtr stylePtr = GetImpl(styleManager).GetRecordedStyle(Toolkit::Control(mControlImpl.GetOwner()));
1969 std::string stateName = Scripting::GetEnumerationName<Toolkit::DevelControl::State>(mState, ControlStateTable, ControlStateTableCount);
1971 const StylePtr* state = stylePtr->subStates.Find(stateName);
1974 StylePtr stateStyle(*state);
1976 const StylePtr* newStateStyle = stateStyle->subStates.Find(subStateName);
1977 const StylePtr* oldStateStyle = stateStyle->subStates.Find(mSubStateName);
1978 if(oldStateStyle && newStateStyle)
1981 ReplaceStateVisualsAndProperties(*oldStateStyle, *newStateStyle, empty);
1987 mSubStateName = subStateName;
1991 void Control::Impl::OnSceneDisconnection()
1993 Actor self = mControlImpl.Self();
1995 // Any visuals set for replacement but not yet ready should still be registered.
1996 // Reason: If a request was made to register a new visual but the control removed from scene before visual was ready
1997 // then when this control appears back on stage it should use that new visual.
1999 // Iterate through all registered visuals and set off scene
2000 SetVisualsOffScene(mVisuals, self);
2002 // Visuals pending replacement can now be taken out of the removal list and set off scene
2003 // Iterate through all replacement visuals and add to a move queue then set off scene
2004 for(auto removalIter = mRemoveVisuals.Begin(), end = mRemoveVisuals.End(); removalIter != end; removalIter++)
2006 Toolkit::GetImplementation((*removalIter)->visual).SetOffScene(self);
2009 for(auto replacedIter = mVisuals.Begin(), end = mVisuals.End(); replacedIter != end; replacedIter++)
2011 (*replacedIter)->pending = false;
2014 mRemoveVisuals.Clear();
2017 void Control::Impl::SetMargin(Extents margin)
2019 mControlImpl.mImpl->mMargin = margin;
2021 // Trigger a size negotiation request that may be needed when setting a margin.
2022 mControlImpl.RelayoutRequest();
2025 Extents Control::Impl::GetMargin() const
2027 return mControlImpl.mImpl->mMargin;
2030 void Control::Impl::SetPadding(Extents padding)
2032 mControlImpl.mImpl->mPadding = padding;
2034 // Trigger a size negotiation request that may be needed when setting a padding.
2035 mControlImpl.RelayoutRequest();
2038 Extents Control::Impl::GetPadding() const
2040 return mControlImpl.mImpl->mPadding;
2043 void Control::Impl::SetInputMethodContext(InputMethodContext& inputMethodContext)
2045 mInputMethodContext = inputMethodContext;
2048 bool Control::Impl::FilterKeyEvent(const KeyEvent& event)
2050 bool consumed(false);
2052 if(mInputMethodContext)
2054 consumed = mInputMethodContext.FilterEventKey(event);
2059 DevelControl::VisualEventSignalType& Control::Impl::VisualEventSignal()
2061 return mVisualEventSignal;
2064 void Control::Impl::SetShadow(const Property::Map& map)
2066 Toolkit::Visual::Base visual = Toolkit::VisualFactory::Get().CreateVisual(map);
2067 visual.SetName("shadow");
2071 mControlImpl.mImpl->RegisterVisual(Toolkit::DevelControl::Property::SHADOW, visual, DepthIndex::BACKGROUND_EFFECT);
2073 mControlImpl.RelayoutRequest();
2077 void Control::Impl::ClearShadow()
2079 mControlImpl.mImpl->UnregisterVisual(Toolkit::DevelControl::Property::SHADOW);
2081 // Trigger a size negotiation request that may be needed when unregistering a visual.
2082 mControlImpl.RelayoutRequest();
2085 Dali::Property Control::Impl::GetVisualProperty(Dali::Property::Index index, Dali::Property::Key visualPropertyKey)
2087 Toolkit::Visual::Base visual = GetVisualByIndex(mVisuals, index);
2090 Internal::Visual::Base& visualImpl = Toolkit::GetImplementation(visual);
2091 return visualImpl.GetPropertyObject(visualPropertyKey);
2095 return Dali::Property(handle, Property::INVALID_INDEX);
2098 void Control::Impl::CreateTransitions(std::vector<std::pair<Dali::Property::Index, Dali::Property::Map>>& sourceProperties,
2099 std::vector<std::pair<Dali::Property::Index, Dali::Property::Map>>& destinationProperties,
2100 Dali::Toolkit::Control source,
2101 Dali::Toolkit::Control destination)
2103 // Retrieves background properties to be transitioned.
2104 Dali::Property::Map backgroundSourcePropertyMap, backgroundDestinationPropertyMap;
2105 mControlImpl.MakeVisualTransition(backgroundSourcePropertyMap, backgroundDestinationPropertyMap, source, destination, Toolkit::Control::Property::BACKGROUND);
2106 if(backgroundSourcePropertyMap.Count() > 0)
2108 sourceProperties.push_back(std::pair<Dali::Property::Index, Dali::Property::Map>(Toolkit::Control::Property::BACKGROUND, backgroundSourcePropertyMap));
2109 destinationProperties.push_back(std::pair<Dali::Property::Index, Dali::Property::Map>(Toolkit::Control::Property::BACKGROUND, backgroundDestinationPropertyMap));
2112 // Retrieves shadow properties to be transitioned.
2113 Dali::Property::Map shadowSourcePropertyMap, shadowDestinationPropertyMap;
2114 mControlImpl.MakeVisualTransition(shadowSourcePropertyMap, shadowDestinationPropertyMap, source, destination, Toolkit::DevelControl::Property::SHADOW);
2115 if(shadowSourcePropertyMap.Count() > 0)
2117 sourceProperties.push_back(std::pair<Dali::Property::Index, Dali::Property::Map>(Toolkit::DevelControl::Property::SHADOW, shadowSourcePropertyMap));
2118 destinationProperties.push_back(std::pair<Dali::Property::Index, Dali::Property::Map>(Toolkit::DevelControl::Property::SHADOW, shadowDestinationPropertyMap));
2121 // Retrieves transition from inherited class.
2122 mControlImpl.OnCreateTransitions(sourceProperties, destinationProperties, source, destination);
2125 void Control::Impl::UpdateVisualProperties(const std::vector<std::pair<Dali::Property::Index, Dali::Property::Map>>& properties)
2127 for(auto&& data : properties)
2129 if(data.first == Toolkit::Control::Property::BACKGROUND)
2131 DoAction(Toolkit::Control::Property::BACKGROUND, DevelVisual::Action::UPDATE_PROPERTY, data.second);
2133 else if(data.first == Toolkit::DevelControl::Property::SHADOW)
2135 DoAction(Toolkit::DevelControl::Property::SHADOW, DevelVisual::Action::UPDATE_PROPERTY, data.second);
2138 mControlImpl.OnUpdateVisualProperties(properties);
2141 void Control::Impl::EmitResourceReadySignal()
2143 if(!mIsEmittingResourceReadySignal)
2145 // Guard against calls to emit the signal during the callback
2146 mIsEmittingResourceReadySignal = true;
2148 // If the signal handler changes visual, it may become ready during this call & therefore this method will
2149 // get called again recursively. If so, mIdleCallbackRegistered is set below, and we act on it after that secondary
2150 // invocation has completed by notifying in an Idle callback to prevent further recursion.
2151 Dali::Toolkit::Control handle(mControlImpl.GetOwner());
2152 mResourceReadySignal.Emit(handle);
2154 mIsEmittingResourceReadySignal = false;
2158 if(!mIdleCallbackRegistered)
2160 mIdleCallbackRegistered = true;
2162 // Add idler to emit the signal again
2165 // The callback manager takes the ownership of the callback object.
2166 mIdleCallback = MakeCallback(this, &Control::Impl::OnIdleCallback);
2167 Adaptor::Get().AddIdle(mIdleCallback, true);
2173 bool Control::Impl::OnIdleCallback()
2176 mIdleCallbackRegistered = false;
2178 // A visual is ready so control may need relayouting if staged
2179 if(mControlImpl.Self().GetProperty<bool>(Actor::Property::CONNECTED_TO_SCENE))
2181 mControlImpl.RelayoutRequest();
2184 EmitResourceReadySignal();
2186 if(!mIdleCallbackRegistered)
2188 // Set the pointer to null as the callback manager deletes the callback after execute it.
2189 mIdleCallback = nullptr;
2192 // Repeat idle if mIdleCallbackRegistered become true one more time.
2193 return mIdleCallbackRegistered;
2196 Toolkit::DevelControl::ControlAccessible* Control::Impl::GetAccessibleObject()
2198 if(!mAccessibleObject)
2200 mAccessibleObject.reset(mControlImpl.CreateAccessibleObject());
2203 return mAccessibleObject.get();
2206 } // namespace Internal
2208 } // namespace Toolkit