2 * Copyright (c) 2024 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 * Discard visual from source to visual factory.
238 void DiscardVisual(RegisteredVisualContainer::Iterator sourceIter, RegisteredVisualContainer& source)
240 Toolkit::Visual::Base visual = (*sourceIter)->visual;
243 if(Stage::IsInstalled())
245 Toolkit::VisualFactory::Get().DiscardVisual(visual);
249 source.Erase(sourceIter);
253 * Performs actions as requested using the action name.
254 * @param[in] object The object on which to perform the action.
255 * @param[in] actionName The action to perform.
256 * @param[in] attributes The attributes with which to perfrom this action.
257 * @return true if action has been accepted by this control
259 const char* ACTION_ACCESSIBILITY_ACTIVATED = "accessibilityActivated";
260 const char* ACTION_ACCESSIBILITY_READING_CANCELLED = "ReadingCancelled";
261 const char* ACTION_ACCESSIBILITY_READING_PAUSED = "ReadingPaused";
262 const char* ACTION_ACCESSIBILITY_READING_RESUMED = "ReadingResumed";
263 const char* ACTION_ACCESSIBILITY_READING_SKIPPED = "ReadingSkipped";
264 const char* ACTION_ACCESSIBILITY_READING_STOPPED = "ReadingStopped";
266 static bool DoAction(BaseObject* object, const std::string& actionName, const Property::Map& attributes)
270 Dali::BaseHandle handle(object);
272 Toolkit::Control control = Toolkit::Control::DownCast(handle);
274 DALI_ASSERT_ALWAYS(control);
276 if(0 == strcmp(actionName.c_str(), ACTION_ACCESSIBILITY_ACTIVATED) || actionName == "activate")
278 // if cast succeeds there is an implementation so no need to check
279 if(!DevelControl::AccessibilityActivateSignal(control).Empty())
281 DevelControl::AccessibilityActivateSignal(control).Emit();
285 ret = Internal::GetImplementation(control).OnAccessibilityActivated();
288 else if(0 == strcmp(actionName.c_str(), ACTION_ACCESSIBILITY_READING_SKIPPED))
290 // if cast succeeds there is an implementation so no need to check
291 if(!DevelControl::AccessibilityReadingSkippedSignal(control).Empty())
293 DevelControl::AccessibilityReadingSkippedSignal(control).Emit();
296 else if(0 == strcmp(actionName.c_str(), ACTION_ACCESSIBILITY_READING_PAUSED))
298 // if cast succeeds there is an implementation so no need to check
299 if(!DevelControl::AccessibilityReadingPausedSignal(control).Empty())
301 DevelControl::AccessibilityReadingPausedSignal(control).Emit();
304 else if(0 == strcmp(actionName.c_str(), ACTION_ACCESSIBILITY_READING_RESUMED))
306 // if cast succeeds there is an implementation so no need to check
307 if(!DevelControl::AccessibilityReadingResumedSignal(control).Empty())
309 DevelControl::AccessibilityReadingResumedSignal(control).Emit();
312 else if(0 == strcmp(actionName.c_str(), ACTION_ACCESSIBILITY_READING_CANCELLED))
314 // if cast succeeds there is an implementation so no need to check
315 if(!DevelControl::AccessibilityReadingCancelledSignal(control).Empty())
317 DevelControl::AccessibilityReadingCancelledSignal(control).Emit();
320 else if(0 == strcmp(actionName.c_str(), ACTION_ACCESSIBILITY_READING_STOPPED))
322 // if cast succeeds there is an implementation so no need to check
323 if(!DevelControl::AccessibilityReadingStoppedSignal(control).Empty())
325 DevelControl::AccessibilityReadingStoppedSignal(control).Emit();
336 * Connects a callback function with the object's signals.
337 * @param[in] object The object providing the signal.
338 * @param[in] tracker Used to disconnect the signal.
339 * @param[in] signalName The signal to connect to.
340 * @param[in] functor A newly allocated FunctorDelegate.
341 * @return True if the signal was connected.
342 * @post If a signal was connected, ownership of functor was passed to CallbackBase. Otherwise the caller is responsible for deleting the unused functor.
344 const char* SIGNAL_KEY_EVENT = "keyEvent";
345 const char* SIGNAL_KEY_INPUT_FOCUS_GAINED = "keyInputFocusGained";
346 const char* SIGNAL_KEY_INPUT_FOCUS_LOST = "keyInputFocusLost";
347 const char* SIGNAL_TAPPED = "tapped";
348 const char* SIGNAL_PANNED = "panned";
349 const char* SIGNAL_PINCHED = "pinched";
350 const char* SIGNAL_LONG_PRESSED = "longPressed";
351 const char* SIGNAL_GET_NAME = "getName";
352 const char* SIGNAL_GET_DESCRIPTION = "getDescription";
353 const char* SIGNAL_DO_GESTURE = "doGesture";
354 static bool DoConnectSignal(BaseObject* object, ConnectionTrackerInterface* tracker, const std::string& signalName, FunctorDelegate* functor)
356 Dali::BaseHandle handle(object);
358 bool connected(false);
359 Toolkit::Control control = Toolkit::Control::DownCast(handle);
362 Internal::Control& controlImpl(Internal::GetImplementation(control));
365 if(0 == strcmp(signalName.c_str(), SIGNAL_KEY_EVENT))
367 controlImpl.KeyEventSignal().Connect(tracker, functor);
369 else if(0 == strcmp(signalName.c_str(), SIGNAL_KEY_INPUT_FOCUS_GAINED))
371 controlImpl.KeyInputFocusGainedSignal().Connect(tracker, functor);
373 else if(0 == strcmp(signalName.c_str(), SIGNAL_KEY_INPUT_FOCUS_LOST))
375 controlImpl.KeyInputFocusLostSignal().Connect(tracker, functor);
377 else if(0 == strcmp(signalName.c_str(), SIGNAL_TAPPED))
379 controlImpl.EnableGestureDetection(GestureType::TAP);
380 controlImpl.GetTapGestureDetector().DetectedSignal().Connect(tracker, functor);
382 else if(0 == strcmp(signalName.c_str(), SIGNAL_PANNED))
384 controlImpl.EnableGestureDetection(GestureType::PAN);
385 controlImpl.GetPanGestureDetector().DetectedSignal().Connect(tracker, functor);
387 else if(0 == strcmp(signalName.c_str(), SIGNAL_PINCHED))
389 controlImpl.EnableGestureDetection(GestureType::PINCH);
390 controlImpl.GetPinchGestureDetector().DetectedSignal().Connect(tracker, functor);
392 else if(0 == strcmp(signalName.c_str(), SIGNAL_LONG_PRESSED))
394 controlImpl.EnableGestureDetection(GestureType::LONG_PRESS);
395 controlImpl.GetLongPressGestureDetector().DetectedSignal().Connect(tracker, functor);
397 else if(0 == strcmp(signalName.c_str(), SIGNAL_GET_NAME))
399 DevelControl::AccessibilityGetNameSignal(control).Connect(tracker, functor);
401 else if(0 == strcmp(signalName.c_str(), SIGNAL_GET_DESCRIPTION))
403 DevelControl::AccessibilityGetDescriptionSignal(control).Connect(tracker, functor);
405 else if(0 == strcmp(signalName.c_str(), SIGNAL_DO_GESTURE))
407 DevelControl::AccessibilityDoGestureSignal(control).Connect(tracker, functor);
414 * Creates control through type registry
418 return Internal::Control::New();
420 // Setup signals and actions using the type-registry.
421 DALI_TYPE_REGISTRATION_BEGIN(Control, CustomActor, Create);
423 // Note: Properties are registered separately below.
425 SignalConnectorType registerSignal1(typeRegistration, SIGNAL_KEY_EVENT, &DoConnectSignal);
426 SignalConnectorType registerSignal2(typeRegistration, SIGNAL_KEY_INPUT_FOCUS_GAINED, &DoConnectSignal);
427 SignalConnectorType registerSignal3(typeRegistration, SIGNAL_KEY_INPUT_FOCUS_LOST, &DoConnectSignal);
428 SignalConnectorType registerSignal4(typeRegistration, SIGNAL_TAPPED, &DoConnectSignal);
429 SignalConnectorType registerSignal5(typeRegistration, SIGNAL_PANNED, &DoConnectSignal);
430 SignalConnectorType registerSignal6(typeRegistration, SIGNAL_PINCHED, &DoConnectSignal);
431 SignalConnectorType registerSignal7(typeRegistration, SIGNAL_LONG_PRESSED, &DoConnectSignal);
432 SignalConnectorType registerSignal8(typeRegistration, SIGNAL_GET_NAME, &DoConnectSignal);
433 SignalConnectorType registerSignal9(typeRegistration, SIGNAL_GET_DESCRIPTION, &DoConnectSignal);
434 SignalConnectorType registerSignal10(typeRegistration, SIGNAL_DO_GESTURE, &DoConnectSignal);
436 TypeAction registerAction1(typeRegistration, "activate", &DoAction);
437 TypeAction registerAction2(typeRegistration, ACTION_ACCESSIBILITY_ACTIVATED, &DoAction);
438 TypeAction registerAction3(typeRegistration, ACTION_ACCESSIBILITY_READING_SKIPPED, &DoAction);
439 TypeAction registerAction4(typeRegistration, ACTION_ACCESSIBILITY_READING_CANCELLED, &DoAction);
440 TypeAction registerAction5(typeRegistration, ACTION_ACCESSIBILITY_READING_STOPPED, &DoAction);
441 TypeAction registerAction6(typeRegistration, ACTION_ACCESSIBILITY_READING_PAUSED, &DoAction);
442 TypeAction registerAction7(typeRegistration, ACTION_ACCESSIBILITY_READING_RESUMED, &DoAction);
444 DALI_TYPE_REGISTRATION_END()
447 * @brief Iterate through given container and setOffScene any visual found
449 * @param[in] container Container of visuals
450 * @param[in] parent Parent actor to remove visuals from
452 void SetVisualsOffScene(const RegisteredVisualContainer& container, Actor parent)
454 for(auto iter = container.Begin(), end = container.End(); iter != end; iter++)
458 DALI_LOG_INFO(gLogFilter, Debug::Verbose, "Control::SetOffScene Setting visual(%d) off stage\n", (*iter)->index);
459 Toolkit::GetImplementation((*iter)->visual).SetOffScene(parent);
464 Dali::Rect<> GetShowingGeometry(Dali::Rect<> rect, Dali::Toolkit::DevelControl::ControlAccessible* accessible)
467 Vector2 currentPosition;
468 auto parent = dynamic_cast<Toolkit::DevelControl::ControlAccessible*>(accessible->GetParent());
472 parentRect = parent->GetExtents(Dali::Accessibility::CoordinateType::WINDOW);
474 currentPosition.x = rect.x;
475 currentPosition.y = rect.y;
477 rect.x = rect.x > parentRect.x ? rect.x : parentRect.x;
478 rect.y = rect.y > parentRect.y ? rect.y : parentRect.y;
479 rect.width = currentPosition.x + rect.width < parentRect.x + parentRect.width ? currentPosition.x + rect.width - rect.x : parentRect.x + parentRect.width - rect.x;
480 rect.height = currentPosition.y + rect.height < parentRect.y + parentRect.height ? currentPosition.y + rect.height - rect.y : parentRect.y + parentRect.height - rect.y;
482 if(rect.width < 0 || rect.height < 0)
487 parent = dynamic_cast<Toolkit::DevelControl::ControlAccessible*>(parent->GetParent());
493 static bool IsShowingGeometryOnScreen(Dali::Rect<> rect)
495 return rect.width > 0 && rect.height > 0;
498 Dali::Accessibility::Accessible* ExternalAccessibleGetter(Dali::Actor actor)
500 auto control = Toolkit::Control::DownCast(actor);
506 auto& controlImpl = Toolkit::Internal::GetImplementation(control);
508 return controlImpl.GetAccessibleObject();
511 } // unnamed namespace
514 // Properties registered without macro to use specific member variables.
515 const PropertyRegistration Control::Impl::PROPERTY_1(typeRegistration, "styleName", Toolkit::Control::Property::STYLE_NAME, Property::STRING, &Control::Impl::SetProperty, &Control::Impl::GetProperty);
516 const PropertyRegistration Control::Impl::PROPERTY_4(typeRegistration, "keyInputFocus", Toolkit::Control::Property::KEY_INPUT_FOCUS, Property::BOOLEAN, &Control::Impl::SetProperty, &Control::Impl::GetProperty);
517 const PropertyRegistration Control::Impl::PROPERTY_5(typeRegistration, "background", Toolkit::Control::Property::BACKGROUND, Property::MAP, &Control::Impl::SetProperty, &Control::Impl::GetProperty);
518 const PropertyRegistration Control::Impl::PROPERTY_6(typeRegistration, "margin", Toolkit::Control::Property::MARGIN, Property::EXTENTS, &Control::Impl::SetProperty, &Control::Impl::GetProperty);
519 const PropertyRegistration Control::Impl::PROPERTY_7(typeRegistration, "padding", Toolkit::Control::Property::PADDING, Property::EXTENTS, &Control::Impl::SetProperty, &Control::Impl::GetProperty);
520 const PropertyRegistration Control::Impl::PROPERTY_8(typeRegistration, "tooltip", Toolkit::DevelControl::Property::TOOLTIP, Property::MAP, &Control::Impl::SetProperty, &Control::Impl::GetProperty);
521 const PropertyRegistration Control::Impl::PROPERTY_9(typeRegistration, "state", Toolkit::DevelControl::Property::STATE, Property::STRING, &Control::Impl::SetProperty, &Control::Impl::GetProperty);
522 const PropertyRegistration Control::Impl::PROPERTY_10(typeRegistration, "subState", Toolkit::DevelControl::Property::SUB_STATE, Property::STRING, &Control::Impl::SetProperty, &Control::Impl::GetProperty);
523 const PropertyRegistration Control::Impl::PROPERTY_11(typeRegistration, "leftFocusableActorId", Toolkit::DevelControl::Property::LEFT_FOCUSABLE_ACTOR_ID, Property::INTEGER, &Control::Impl::SetProperty, &Control::Impl::GetProperty);
524 const PropertyRegistration Control::Impl::PROPERTY_12(typeRegistration, "rightFocusableActorId", Toolkit::DevelControl::Property::RIGHT_FOCUSABLE_ACTOR_ID, Property::INTEGER, &Control::Impl::SetProperty, &Control::Impl::GetProperty);
525 const PropertyRegistration Control::Impl::PROPERTY_13(typeRegistration, "upFocusableActorId", Toolkit::DevelControl::Property::UP_FOCUSABLE_ACTOR_ID, Property::INTEGER, &Control::Impl::SetProperty, &Control::Impl::GetProperty);
526 const PropertyRegistration Control::Impl::PROPERTY_14(typeRegistration, "downFocusableActorId", Toolkit::DevelControl::Property::DOWN_FOCUSABLE_ACTOR_ID, Property::INTEGER, &Control::Impl::SetProperty, &Control::Impl::GetProperty);
527 const PropertyRegistration Control::Impl::PROPERTY_15(typeRegistration, "shadow", Toolkit::DevelControl::Property::SHADOW, Property::MAP, &Control::Impl::SetProperty, &Control::Impl::GetProperty);
528 const PropertyRegistration Control::Impl::PROPERTY_16(typeRegistration, "accessibilityName", Toolkit::DevelControl::Property::ACCESSIBILITY_NAME, Property::STRING, &Control::Impl::SetProperty, &Control::Impl::GetProperty);
529 const PropertyRegistration Control::Impl::PROPERTY_17(typeRegistration, "accessibilityDescription", Toolkit::DevelControl::Property::ACCESSIBILITY_DESCRIPTION, Property::STRING, &Control::Impl::SetProperty, &Control::Impl::GetProperty);
530 const PropertyRegistration Control::Impl::PROPERTY_18(typeRegistration, "accessibilityTranslationDomain", Toolkit::DevelControl::Property::ACCESSIBILITY_TRANSLATION_DOMAIN, Property::STRING, &Control::Impl::SetProperty, &Control::Impl::GetProperty);
531 const PropertyRegistration Control::Impl::PROPERTY_19(typeRegistration, "accessibilityRole", Toolkit::DevelControl::Property::ACCESSIBILITY_ROLE, Property::INTEGER, &Control::Impl::SetProperty, &Control::Impl::GetProperty);
532 const PropertyRegistration Control::Impl::PROPERTY_20(typeRegistration, "accessibilityHighlightable", Toolkit::DevelControl::Property::ACCESSIBILITY_HIGHLIGHTABLE, Property::BOOLEAN, &Control::Impl::SetProperty, &Control::Impl::GetProperty);
533 const PropertyRegistration Control::Impl::PROPERTY_21(typeRegistration, "accessibilityAttributes", Toolkit::DevelControl::Property::ACCESSIBILITY_ATTRIBUTES, Property::MAP, &Control::Impl::SetProperty, &Control::Impl::GetProperty);
534 const PropertyRegistration Control::Impl::PROPERTY_22(typeRegistration, "dispatchKeyEvents", Toolkit::DevelControl::Property::DISPATCH_KEY_EVENTS, Property::BOOLEAN, &Control::Impl::SetProperty, &Control::Impl::GetProperty);
535 const PropertyRegistration Control::Impl::PROPERTY_23(typeRegistration, "accessibilityHidden", Toolkit::DevelControl::Property::ACCESSIBILITY_HIDDEN, Property::BOOLEAN, &Control::Impl::SetProperty, &Control::Impl::GetProperty);
536 const PropertyRegistration Control::Impl::PROPERTY_24(typeRegistration, "clockwiseFocusableActorId", Toolkit::DevelControl::Property::CLOCKWISE_FOCUSABLE_ACTOR_ID, Property::INTEGER, &Control::Impl::SetProperty, &Control::Impl::GetProperty);
537 const PropertyRegistration Control::Impl::PROPERTY_25(typeRegistration, "counterClockwiseFocusableActorId", Toolkit::DevelControl::Property::COUNTER_CLOCKWISE_FOCUSABLE_ACTOR_ID, Property::INTEGER, &Control::Impl::SetProperty, &Control::Impl::GetProperty);
538 const PropertyRegistration Control::Impl::PROPERTY_26(typeRegistration, "automationId", Toolkit::DevelControl::Property::AUTOMATION_ID, Property::STRING, &Control::Impl::SetProperty, &Control::Impl::GetProperty);
542 Control::Impl::Impl(Control& controlImpl)
543 : mControlImpl(controlImpl),
544 mState(Toolkit::DevelControl::NORMAL),
546 mLeftFocusableActorId(-1),
547 mRightFocusableActorId(-1),
548 mUpFocusableActorId(-1),
549 mDownFocusableActorId(-1),
550 mClockwiseFocusableActorId(-1),
551 mCounterClockwiseFocusableActorId(-1),
553 mBackgroundColor(Color::TRANSPARENT),
554 mStartingPinchScale(nullptr),
556 mPadding(0, 0, 0, 0),
558 mKeyInputFocusGainedSignal(),
559 mKeyInputFocusLostSignal(),
560 mResourceReadySignal(),
561 mVisualEventSignal(),
562 mAccessibilityGetNameSignal(),
563 mAccessibilityGetDescriptionSignal(),
564 mAccessibilityDoGestureSignal(),
565 mPinchGestureDetector(),
566 mPanGestureDetector(),
567 mTapGestureDetector(),
568 mLongPressGestureDetector(),
570 mInputMethodContext(),
571 mIdleCallback(nullptr),
572 mFlags(Control::ControlBehaviour(CONTROL_BEHAVIOUR_DEFAULT)),
573 mIsKeyboardNavigationSupported(false),
574 mIsKeyboardFocusGroup(false),
575 mIsEmittingResourceReadySignal(false),
576 mIdleCallbackRegistered(false),
577 mDispatchKeyEvents(true)
579 Dali::Accessibility::Accessible::RegisterExternalAccessibleGetter(&ExternalAccessibleGetter);
582 Control::Impl::~Impl()
584 for(auto&& iter : mVisuals)
586 StopObservingVisual(iter->visual);
589 for(auto&& iter : mRemoveVisuals)
591 StopObservingVisual(iter->visual);
594 // All gesture detectors will be destroyed so no need to disconnect.
595 delete mStartingPinchScale;
597 if(mIdleCallback && Adaptor::IsAvailable())
599 // Removes the callback from the callback manager in case the control is destroyed before the callback is executed.
600 Adaptor::Get().RemoveIdle(mIdleCallback);
604 Control::Impl& Control::Impl::Get(Internal::Control& internalControl)
606 DALI_ASSERT_ALWAYS(Stage::IsCoreThread() && "Core is not installed. Might call this API from worker thread?");
608 return *internalControl.mImpl;
611 const Control::Impl& Control::Impl::Get(const Internal::Control& internalControl)
613 DALI_ASSERT_ALWAYS(Stage::IsCoreThread() && "Core is not installed. Might call this API from worker thread?");
615 return *internalControl.mImpl;
618 void Control::Impl::CheckHighlightedObjectGeometry()
620 auto accessible = GetAccessibleObject();
621 if(DALI_LIKELY(accessible))
623 auto lastPosition = accessible->GetLastPosition();
624 auto accessibleRect = accessible->GetExtents(Dali::Accessibility::CoordinateType::WINDOW);
625 auto rect = GetShowingGeometry(accessibleRect, accessible);
627 switch(mAccessibilityLastScreenRelativeMoveType)
629 case Dali::Accessibility::ScreenRelativeMoveType::OUTSIDE:
631 if(IsShowingGeometryOnScreen(rect))
633 mAccessibilityLastScreenRelativeMoveType = Dali::Accessibility::ScreenRelativeMoveType::INSIDE;
637 case Dali::Accessibility::ScreenRelativeMoveType::INSIDE:
639 if(rect.width < 0 && !Dali::Equals(accessibleRect.x, lastPosition.x))
641 mAccessibilityLastScreenRelativeMoveType = (accessibleRect.x < lastPosition.x) ? Dali::Accessibility::ScreenRelativeMoveType::OUTGOING_TOP_LEFT : Dali::Accessibility::ScreenRelativeMoveType::OUTGOING_BOTTOM_RIGHT;
643 if(rect.height < 0 && !Dali::Equals(accessibleRect.y, lastPosition.y))
645 mAccessibilityLastScreenRelativeMoveType = (accessibleRect.y < lastPosition.y) ? Dali::Accessibility::ScreenRelativeMoveType::OUTGOING_TOP_LEFT : Dali::Accessibility::ScreenRelativeMoveType::OUTGOING_BOTTOM_RIGHT;
647 // notify AT-clients on outgoing moves only
648 if(mAccessibilityLastScreenRelativeMoveType != Dali::Accessibility::ScreenRelativeMoveType::INSIDE)
650 accessible->EmitMovedOutOfScreen(mAccessibilityLastScreenRelativeMoveType);
654 case Dali::Accessibility::ScreenRelativeMoveType::OUTGOING_TOP_LEFT:
655 case Dali::Accessibility::ScreenRelativeMoveType::OUTGOING_BOTTOM_RIGHT:
657 if(IsShowingGeometryOnScreen(rect))
659 mAccessibilityLastScreenRelativeMoveType = Dali::Accessibility::ScreenRelativeMoveType::INSIDE;
663 mAccessibilityLastScreenRelativeMoveType = Dali::Accessibility::ScreenRelativeMoveType::OUTSIDE;
673 accessible->SetLastPosition(Vector2(accessibleRect.x, accessibleRect.y));
677 void Control::Impl::RegisterAccessibilityPositionPropertyNotification()
679 if(mIsAccessibilityPositionPropertyNotificationSet)
683 // set default value until first move of object is detected
684 mAccessibilityLastScreenRelativeMoveType = Dali::Accessibility::ScreenRelativeMoveType::OUTSIDE;
685 // recalculate mAccessibilityLastScreenRelativeMoveType accordingly to the initial position
686 CheckHighlightedObjectGeometry();
687 mAccessibilityPositionNotification = mControlImpl.Self().AddPropertyNotification(Actor::Property::WORLD_POSITION, StepCondition(1.0f, 1.0f));
688 mAccessibilityPositionNotification.SetNotifyMode(PropertyNotification::NOTIFY_ON_CHANGED);
689 mAccessibilityPositionNotification.NotifySignal().Connect(this, [this](PropertyNotification&) { CheckHighlightedObjectGeometry(); });
690 mIsAccessibilityPositionPropertyNotificationSet = true;
693 void Control::Impl::UnregisterAccessibilityPositionPropertyNotification()
695 mControlImpl.Self().RemovePropertyNotification(mAccessibilityPositionNotification);
696 mIsAccessibilityPositionPropertyNotificationSet = false;
699 void Control::Impl::RegisterAccessibilityPropertySetSignal()
701 if(mIsAccessibilityPropertySetSignalRegistered)
705 mControlImpl.Self().PropertySetSignal().Connect(this, &Control::Impl::OnAccessibilityPropertySet);
706 mIsAccessibilityPropertySetSignalRegistered = true;
709 void Control::Impl::UnregisterAccessibilityPropertySetSignal()
711 if(!mIsAccessibilityPropertySetSignalRegistered)
715 mControlImpl.Self().PropertySetSignal().Disconnect(this, &Control::Impl::OnAccessibilityPropertySet);
716 mIsAccessibilityPropertySetSignalRegistered = false;
719 void Control::Impl::OnAccessibilityPropertySet(Dali::Handle& handle, Dali::Property::Index index, const Dali::Property::Value& value)
721 auto* accessible = GetAccessibleObject();
722 if(DALI_LIKELY(accessible))
724 if(mAccessibilityGetNameSignal.Empty())
726 if(index == DevelControl::Property::ACCESSIBILITY_NAME || (mAccessibilityName.empty() && index == accessible->GetNamePropertyIndex()))
728 accessible->Emit(Dali::Accessibility::ObjectPropertyChangeEvent::NAME);
732 if(mAccessibilityGetDescriptionSignal.Empty())
734 if(index == DevelControl::Property::ACCESSIBILITY_DESCRIPTION || (mAccessibilityDescription.empty() && index == accessible->GetDescriptionPropertyIndex()))
736 accessible->Emit(Dali::Accessibility::ObjectPropertyChangeEvent::DESCRIPTION);
742 // Gesture Detection Methods
743 void Control::Impl::PinchDetected(Actor actor, const PinchGesture& pinch)
745 mControlImpl.OnPinch(pinch);
748 void Control::Impl::PanDetected(Actor actor, const PanGesture& pan)
750 mControlImpl.OnPan(pan);
753 void Control::Impl::TapDetected(Actor actor, const TapGesture& tap)
755 mControlImpl.OnTap(tap);
758 void Control::Impl::LongPressDetected(Actor actor, const LongPressGesture& longPress)
760 mControlImpl.OnLongPress(longPress);
763 void Control::Impl::RegisterVisual(Property::Index index, Toolkit::Visual::Base& visual)
765 RegisterVisual(index, visual, VisualState::ENABLED, DepthIndexValue::NOT_SET);
768 void Control::Impl::RegisterVisual(Property::Index index, Toolkit::Visual::Base& visual, int depthIndex)
770 RegisterVisual(index, visual, VisualState::ENABLED, DepthIndexValue::SET, depthIndex);
773 void Control::Impl::RegisterVisual(Property::Index index, Toolkit::Visual::Base& visual, bool enabled)
775 RegisterVisual(index, visual, (enabled ? VisualState::ENABLED : VisualState::DISABLED), DepthIndexValue::NOT_SET);
778 void Control::Impl::RegisterVisual(Property::Index index, Toolkit::Visual::Base& visual, bool enabled, int depthIndex)
780 RegisterVisual(index, visual, (enabled ? VisualState::ENABLED : VisualState::DISABLED), DepthIndexValue::SET, depthIndex);
783 void Control::Impl::RegisterVisual(Property::Index index, Toolkit::Visual::Base& visual, VisualState::Type enabled, DepthIndexValue::Type depthIndexValueSet, int depthIndex)
785 DALI_ASSERT_ALWAYS(Stage::IsCoreThread() && "Core is not installed. Might call this API from worker thread?");
787 DALI_LOG_INFO(gLogFilter, Debug::Concise, "RegisterVisual:%d \n", index);
789 bool visualReplaced(false);
790 Actor self = mControlImpl.Self();
792 // Set the depth index, if not set by caller this will be either the current visual depth, max depth of all visuals
794 int requiredDepthIndex = visual.GetDepthIndex();
796 if(depthIndexValueSet == DepthIndexValue::SET)
798 requiredDepthIndex = depthIndex;
801 // Visual replacement, existing visual should only be removed from stage when replacement ready.
802 if(!mVisuals.Empty())
804 RegisteredVisualContainer::Iterator registeredVisualsiter;
805 // Check if visual (index) is already registered, this is the current visual.
806 if(FindVisual(index, mVisuals, registeredVisualsiter))
808 Toolkit::Visual::Base& currentRegisteredVisual = (*registeredVisualsiter)->visual;
809 if(currentRegisteredVisual)
811 // Store current visual depth index as may need to set the replacement visual to same depth
812 const int currentDepthIndex = (*registeredVisualsiter)->visual.GetDepthIndex();
814 // No longer required to know if the replaced visual's resources are ready
815 StopObservingVisual(currentRegisteredVisual);
817 // If control staged and visual enabled then visuals will be swapped once ready
818 if(self.GetProperty<bool>(Actor::Property::CONNECTED_TO_SCENE) && enabled)
820 // Check if visual is currently in the process of being replaced ( is in removal container )
821 RegisteredVisualContainer::Iterator visualQueuedForRemoval;
822 if(FindVisual(index, mRemoveVisuals, visualQueuedForRemoval))
824 // Visual with same index is already in removal container so current visual pending
825 // Only the the last requested visual will be displayed so remove current visual which is staged but not ready.
826 Toolkit::GetImplementation(currentRegisteredVisual).SetOffScene(self);
827 mVisuals.Erase(registeredVisualsiter);
831 // current visual not already in removal container so add now.
832 DALI_LOG_INFO(gLogFilter, Debug::Verbose, "RegisterVisual Move current registered visual to removal Queue: %d \n", index);
833 MoveVisual(registeredVisualsiter, mVisuals, mRemoveVisuals);
838 // Control not staged or visual disabled so can just erase from registered visuals and new visual will be added later.
839 mVisuals.Erase(registeredVisualsiter);
842 // 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
843 if((depthIndexValueSet == DepthIndexValue::NOT_SET) &&
844 (visual.GetDepthIndex() == 0))
846 requiredDepthIndex = currentDepthIndex;
850 visualReplaced = true;
854 // If not set, set the name of the visual to the same name as the control's property.
855 // ( If the control has been type registered )
856 if(visual.GetName().empty())
858 // returns empty string if index is not found as long as index is not -1
859 std::string visualName = self.GetPropertyName(index);
860 if(!visualName.empty())
862 DALI_LOG_INFO(gLogFilter, Debug::Concise, "Setting visual name for property %d to %s\n", index, visualName.c_str());
863 visual.SetName(visualName);
867 if(!visualReplaced) // New registration entry
869 // 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
870 if((depthIndexValueSet == DepthIndexValue::NOT_SET) &&
871 (mVisuals.Size() > 0) &&
872 (visual.GetDepthIndex() == 0))
874 int maxDepthIndex = std::numeric_limits<int>::min();
876 RegisteredVisualContainer::ConstIterator iter;
877 const RegisteredVisualContainer::ConstIterator endIter = mVisuals.End();
878 for(iter = mVisuals.Begin(); iter != endIter; iter++)
880 const int visualDepthIndex = (*iter)->visual.GetDepthIndex();
881 if(visualDepthIndex > maxDepthIndex)
883 maxDepthIndex = visualDepthIndex;
886 ++maxDepthIndex; // Add one to the current maximum depth index so that our added visual appears on top
887 requiredDepthIndex = std::max(0, maxDepthIndex); // Start at zero if maxDepth index belongs to a background
893 // Set determined depth index
894 visual.SetDepthIndex(requiredDepthIndex);
896 // Monitor when the visual resources are ready
897 StartObservingVisual(visual);
899 DALI_LOG_INFO(gLogFilter, Debug::Concise, "New Visual registration index[%d] depth[%d]\n", index, requiredDepthIndex);
900 RegisteredVisual* newRegisteredVisual = new RegisteredVisual(index, visual, (enabled == VisualState::ENABLED ? true : false), (visualReplaced && enabled));
901 mVisuals.PushBack(newRegisteredVisual);
903 Internal::Visual::Base& visualImpl = Toolkit::GetImplementation(visual);
904 // Put on stage if enabled and the control is already on the stage
905 if((enabled == VisualState::ENABLED) && self.GetProperty<bool>(Actor::Property::CONNECTED_TO_SCENE))
907 visualImpl.SetOnScene(self);
909 else if(enabled && visualImpl.IsResourceReady()) // When not being staged, check if visual already 'ResourceReady' before it was Registered. ( Resource may have been loaded already )
911 ResourceReady(visualImpl);
915 DALI_LOG_INFO(gLogFilter, Debug::Verbose, "Control::RegisterVisual() Registered %s(%d), enabled:%s\n", visual.GetName().c_str(), index, enabled ? "true" : "false");
918 void Control::Impl::UnregisterVisual(Property::Index index)
920 DALI_ASSERT_ALWAYS(Stage::IsCoreThread() && "Core is not installed. Might call this API from worker thread?");
922 RegisteredVisualContainer::Iterator iter;
923 if(FindVisual(index, mVisuals, iter))
925 // stop observing visual
926 StopObservingVisual((*iter)->visual);
928 Actor self(mControlImpl.Self());
929 Toolkit::GetImplementation((*iter)->visual).SetOffScene(self);
930 (*iter)->visual.Reset();
931 mVisuals.Erase(iter);
934 if(FindVisual(index, mRemoveVisuals, iter))
936 Actor self(mControlImpl.Self());
937 Toolkit::GetImplementation((*iter)->visual).SetOffScene(self);
938 (*iter)->pending = false;
940 // Discard removed visual. It will be destroyed at next Idle time.
941 DiscardVisual(iter, mRemoveVisuals);
945 Toolkit::Visual::Base Control::Impl::GetVisual(Property::Index index) const
947 RegisteredVisualContainer::Iterator iter;
948 if(FindVisual(index, mVisuals, iter))
950 return (*iter)->visual;
953 return Toolkit::Visual::Base();
956 void Control::Impl::EnableVisual(Property::Index index, bool enable)
958 DALI_LOG_INFO(gLogFilter, Debug::General, "Control::EnableVisual(%d, %s)\n", index, enable ? "T" : "F");
960 RegisteredVisualContainer::Iterator iter;
961 if(FindVisual(index, mVisuals, iter))
963 if((*iter)->enabled == enable)
965 DALI_LOG_INFO(gLogFilter, Debug::Verbose, "Control::EnableVisual Visual %s(%d) already %s\n", (*iter)->visual.GetName().c_str(), index, enable ? "enabled" : "disabled");
969 (*iter)->enabled = enable;
970 Actor parentActor = mControlImpl.Self();
971 if(mControlImpl.Self().GetProperty<bool>(Actor::Property::CONNECTED_TO_SCENE)) // If control not on Scene then Visual will be added when SceneConnection is called.
975 DALI_LOG_INFO(gLogFilter, Debug::Verbose, "Control::EnableVisual Setting %s(%d) on stage \n", (*iter)->visual.GetName().c_str(), index);
976 Toolkit::GetImplementation((*iter)->visual).SetOnScene(parentActor);
980 DALI_LOG_INFO(gLogFilter, Debug::Verbose, "Control::EnableVisual Setting %s(%d) off stage \n", (*iter)->visual.GetName().c_str(), index);
981 Toolkit::GetImplementation((*iter)->visual).SetOffScene(parentActor); // No need to call if control not staged.
987 DALI_LOG_WARNING("Control::EnableVisual(%d, %s) FAILED - NO SUCH VISUAL\n", index, enable ? "T" : "F");
991 bool Control::Impl::IsVisualEnabled(Property::Index index) const
993 RegisteredVisualContainer::Iterator iter;
994 if(FindVisual(index, mVisuals, iter))
996 return (*iter)->enabled;
1001 void Control::Impl::EnableReadyTransitionOverriden(Toolkit::Visual::Base& visual, bool enable)
1003 DALI_LOG_INFO(gLogFilter, Debug::General, "Control::EnableReadyTransitionOverriden(%p, %s)\n", visual, enable ? "T" : "F");
1005 RegisteredVisualContainer::Iterator iter;
1006 if(FindVisual(visual, mVisuals, iter))
1008 if((*iter)->overideReadyTransition == enable)
1010 DALI_LOG_INFO(gLogFilter, Debug::Verbose, "Control::EnableReadyTransitionOverriden Visual %s(%p) already %s\n", (*iter)->visual.GetName().c_str(), visual, enable ? "enabled" : "disabled");
1014 (*iter)->overideReadyTransition = enable;
1018 void Control::Impl::StopObservingVisual(Toolkit::Visual::Base& visual)
1020 Internal::Visual::Base& visualImpl = Toolkit::GetImplementation(visual);
1022 // Stop observing the visual
1023 visualImpl.RemoveEventObserver(*this);
1026 void Control::Impl::StartObservingVisual(Toolkit::Visual::Base& visual)
1028 Internal::Visual::Base& visualImpl = Toolkit::GetImplementation(visual);
1030 // start observing the visual for events
1031 visualImpl.AddEventObserver(*this);
1034 void Control::Impl::ResourceReady()
1036 DALI_ASSERT_ALWAYS(Stage::IsCoreThread() && "Core is not installed. Might call this API from worker thread?");
1038 // Emit signal if all enabled visuals registered by the control are ready or there are no visuals.
1039 if(IsResourceReady())
1041 EmitResourceReadySignal();
1045 // Called by a Visual when it's resource is ready
1046 void Control::Impl::ResourceReady(Visual::Base& object)
1048 DALI_LOG_INFO(gLogFilter, Debug::Verbose, "Control::Impl::ResourceReady() replacements pending[%d]\n", mRemoveVisuals.Count());
1050 Actor self = mControlImpl.Self();
1052 RegisteredVisualContainer::Iterator registeredIter;
1054 // A resource is ready, find resource in the registered visuals container and get its index
1055 if(!FindVisual(object, mVisuals, registeredIter))
1060 RegisteredVisualContainer::Iterator visualToRemoveIter;
1061 // Find visual with the same index in the removal container
1062 // Set if off stage as it's replacement is now ready.
1063 // Remove if from removal list as now removed from stage.
1064 // Set Pending flag on the ready visual to false as now ready.
1065 if(FindVisual((*registeredIter)->index, mRemoveVisuals, visualToRemoveIter))
1067 (*registeredIter)->pending = false;
1068 if(!((*visualToRemoveIter)->overideReadyTransition))
1070 Toolkit::GetImplementation((*visualToRemoveIter)->visual).SetOffScene(self);
1073 // Discard removed visual. It will be destroyed at next Idle time.
1074 DiscardVisual(visualToRemoveIter, mRemoveVisuals);
1077 // A visual is ready so control may need relayouting if staged
1078 RelayoutRequest(object);
1080 // Called by a Visual when it's resource is ready
1081 if(((*registeredIter)->enabled))
1087 void Control::Impl::NotifyVisualEvent(Visual::Base& object, Property::Index signalId)
1089 for(auto registeredIter = mVisuals.Begin(), end = mVisuals.End(); registeredIter != end; ++registeredIter)
1091 Internal::Visual::Base& registeredVisualImpl = Toolkit::GetImplementation((*registeredIter)->visual);
1092 if(&object == ®isteredVisualImpl)
1094 Dali::Toolkit::Control handle(mControlImpl.GetOwner());
1095 mVisualEventSignal.Emit(handle, (*registeredIter)->index, signalId);
1101 void Control::Impl::RelayoutRequest(Visual::Base& object)
1103 if(mControlImpl.Self().GetProperty<bool>(Actor::Property::CONNECTED_TO_SCENE))
1105 mControlImpl.RelayoutRequest();
1109 bool Control::Impl::IsResourceReady() const
1111 // Iterate through and check all the enabled visuals are ready
1112 for(auto visualIter = mVisuals.Begin();
1113 visualIter != mVisuals.End();
1116 const Toolkit::Visual::Base visual = (*visualIter)->visual;
1117 const Internal::Visual::Base& visualImpl = Toolkit::GetImplementation(visual);
1119 // one of the enabled visuals is not ready
1120 if(!visualImpl.IsResourceReady() && (*visualIter)->enabled)
1128 Toolkit::Visual::ResourceStatus Control::Impl::GetVisualResourceStatus(Property::Index index) const
1130 RegisteredVisualContainer::Iterator iter;
1131 if(FindVisual(index, mVisuals, iter))
1133 const Toolkit::Visual::Base visual = (*iter)->visual;
1134 const Internal::Visual::Base& visualImpl = Toolkit::GetImplementation(visual);
1135 return visualImpl.GetResourceStatus();
1138 return Toolkit::Visual::ResourceStatus::PREPARING;
1141 void Control::Impl::AddTransitions(Dali::Animation& animation,
1142 const Toolkit::TransitionData& handle,
1143 bool createAnimation)
1145 // Setup a Transition from TransitionData.
1146 const Internal::TransitionData& transitionData = Toolkit::GetImplementation(handle);
1147 TransitionData::Iterator end = transitionData.End();
1148 for(TransitionData::Iterator iter = transitionData.Begin();
1152 TransitionData::Animator* animator = (*iter);
1154 Toolkit::Visual::Base visual = GetVisualByName(mVisuals, animator->objectName);
1158 #if defined(DEBUG_ENABLED)
1159 Dali::TypeInfo typeInfo;
1160 ControlWrapper* controlWrapperImpl = dynamic_cast<ControlWrapper*>(&mControlImpl);
1161 if(controlWrapperImpl)
1163 typeInfo = controlWrapperImpl->GetTypeInfo();
1166 DALI_LOG_INFO(gLogFilter, Debug::Concise, "CreateTransition: Found %s visual for %s\n", visual.GetName().c_str(), typeInfo ? typeInfo.GetName().c_str() : "Unknown");
1168 Internal::Visual::Base& visualImpl = Toolkit::GetImplementation(visual);
1169 visualImpl.AnimateProperty(animation, *animator);
1173 DALI_LOG_INFO(gLogFilter, Debug::Concise, "CreateTransition: Could not find visual. Trying actors");
1174 // Otherwise, try any actor children of control (Including the control)
1175 Actor child = mControlImpl.Self().FindChildByName(animator->objectName);
1178 Property::Index propertyIndex = child.GetPropertyIndex(animator->propertyKey);
1179 if(propertyIndex != Property::INVALID_INDEX)
1181 if(animator->animate == false)
1183 if(animator->targetValue.GetType() != Property::NONE)
1185 child.SetProperty(propertyIndex, animator->targetValue);
1188 else // animate the property
1190 if(animator->initialValue.GetType() != Property::NONE)
1192 child.SetProperty(propertyIndex, animator->initialValue);
1195 if(createAnimation && !animation)
1197 animation = Dali::Animation::New(0.1f);
1200 animation.AnimateTo(Property(child, propertyIndex),
1201 animator->targetValue,
1202 animator->alphaFunction,
1203 TimePeriod(animator->timePeriodDelay,
1204 animator->timePeriodDuration));
1212 Dali::Animation Control::Impl::CreateTransition(const Toolkit::TransitionData& transitionData)
1214 Dali::Animation transition;
1216 if(transitionData.Count() > 0)
1218 AddTransitions(transition, transitionData, true);
1223 void Control::Impl::DoAction(Dali::Property::Index visualIndex, Dali::Property::Index actionId, const Dali::Property::Value attributes)
1225 RegisteredVisualContainer::Iterator iter;
1226 if(FindVisual(visualIndex, mVisuals, iter))
1228 Toolkit::GetImplementation((*iter)->visual).DoAction(actionId, attributes);
1232 void Control::Impl::DoActionExtension(Dali::Property::Index visualIndex, Dali::Property::Index actionId, Dali::Any attributes)
1234 RegisteredVisualContainer::Iterator iter;
1235 if(FindVisual(visualIndex, mVisuals, iter))
1237 Toolkit::GetImplementation((*iter)->visual).DoActionExtension(actionId, attributes);
1241 void Control::Impl::AppendAccessibilityAttribute(const std::string& key, const std::string value)
1243 Property::Value* checkedValue = mAccessibilityAttributes.Find(key);
1246 mAccessibilityAttributes[key] = Property::Value(value);
1250 mAccessibilityAttributes.Insert(key, value);
1254 void Control::Impl::SetProperty(BaseObject* object, Property::Index index, const Property::Value& value)
1256 DALI_ASSERT_ALWAYS(Stage::IsCoreThread() && "Core is not installed. Might call this API from worker thread?");
1258 Toolkit::Control control = Toolkit::Control::DownCast(BaseHandle(object));
1262 Control& controlImpl(GetImplementation(control));
1266 case Toolkit::Control::Property::STYLE_NAME:
1268 controlImpl.SetStyleName(value.Get<std::string>());
1272 case Toolkit::DevelControl::Property::STATE:
1274 bool withTransitions = true;
1275 const Property::Value* valuePtr = &value;
1276 const Property::Map* map = value.GetMap();
1279 Property::Value* value2 = map->Find("withTransitions");
1282 withTransitions = value2->Get<bool>();
1285 valuePtr = map->Find("state");
1290 Toolkit::DevelControl::State state(controlImpl.mImpl->mState);
1291 if(Scripting::GetEnumerationProperty<Toolkit::DevelControl::State>(*valuePtr, ControlStateTable, ControlStateTableCount, state))
1293 controlImpl.mImpl->SetState(state, withTransitions);
1299 case Toolkit::DevelControl::Property::SUB_STATE:
1301 std::string subState;
1302 if(value.Get(subState))
1304 controlImpl.mImpl->SetSubState(subState);
1309 case Toolkit::DevelControl::Property::LEFT_FOCUSABLE_ACTOR_ID:
1312 if(value.Get(focusId))
1314 controlImpl.mImpl->mLeftFocusableActorId = focusId;
1319 case Toolkit::DevelControl::Property::RIGHT_FOCUSABLE_ACTOR_ID:
1322 if(value.Get(focusId))
1324 controlImpl.mImpl->mRightFocusableActorId = focusId;
1329 case Toolkit::DevelControl::Property::UP_FOCUSABLE_ACTOR_ID:
1332 if(value.Get(focusId))
1334 controlImpl.mImpl->mUpFocusableActorId = focusId;
1339 case Toolkit::DevelControl::Property::DOWN_FOCUSABLE_ACTOR_ID:
1342 if(value.Get(focusId))
1344 controlImpl.mImpl->mDownFocusableActorId = focusId;
1349 case Toolkit::Control::Property::KEY_INPUT_FOCUS:
1351 if(value.Get<bool>())
1353 controlImpl.SetKeyInputFocus();
1357 controlImpl.ClearKeyInputFocus();
1362 case Toolkit::Control::Property::BACKGROUND:
1366 const Property::Map* map = value.GetMap();
1367 if(map && !map->Empty())
1369 controlImpl.SetBackground(*map);
1371 else if(value.Get(url))
1373 // don't know the size to load
1374 Toolkit::Visual::Base visual = Toolkit::VisualFactory::Get().CreateVisual(url, ImageDimensions());
1377 controlImpl.mImpl->RegisterVisual(Toolkit::Control::Property::BACKGROUND, visual, DepthIndex::BACKGROUND);
1380 else if(value.Get(color))
1382 controlImpl.SetBackgroundColor(color);
1386 // The background is an empty property map, so we should clear the background
1387 controlImpl.ClearBackground();
1392 case Toolkit::Control::Property::MARGIN:
1395 if(value.Get(margin))
1397 controlImpl.mImpl->SetMargin(margin);
1402 case Toolkit::Control::Property::PADDING:
1405 if(value.Get(padding))
1407 controlImpl.mImpl->SetPadding(padding);
1412 case Toolkit::DevelControl::Property::TOOLTIP:
1414 TooltipPtr& tooltipPtr = controlImpl.mImpl->mTooltip;
1417 tooltipPtr = Tooltip::New(control);
1419 tooltipPtr->SetProperties(value);
1423 case Toolkit::DevelControl::Property::SHADOW:
1425 const Property::Map* map = value.GetMap();
1426 if(map && !map->Empty())
1428 controlImpl.mImpl->SetShadow(*map);
1432 // The shadow is an empty property map, so we should clear the shadow
1433 controlImpl.mImpl->ClearShadow();
1438 case Toolkit::DevelControl::Property::ACCESSIBILITY_NAME:
1443 controlImpl.mImpl->mAccessibilityName = name;
1448 case Toolkit::DevelControl::Property::ACCESSIBILITY_DESCRIPTION:
1453 controlImpl.mImpl->mAccessibilityDescription = text;
1458 case Toolkit::DevelControl::Property::ACCESSIBILITY_TRANSLATION_DOMAIN:
1463 controlImpl.mImpl->mAccessibilityTranslationDomain = text;
1468 case Toolkit::DevelControl::Property::ACCESSIBILITY_ROLE:
1470 Dali::Accessibility::Role role;
1473 controlImpl.mImpl->mAccessibilityRole = role;
1478 case Toolkit::DevelControl::Property::ACCESSIBILITY_HIGHLIGHTABLE:
1481 if(value.Get(highlightable))
1483 controlImpl.mImpl->mAccessibilityHighlightable = highlightable;
1488 case Toolkit::DevelControl::Property::ACCESSIBILITY_ATTRIBUTES:
1490 const Property::Map* map = value.GetMap();
1491 if(map && !map->Empty())
1493 controlImpl.mImpl->mAccessibilityAttributes = *map;
1498 case Toolkit::DevelControl::Property::DISPATCH_KEY_EVENTS:
1501 if(value.Get(dispatch))
1503 controlImpl.mImpl->mDispatchKeyEvents = dispatch;
1508 case Toolkit::DevelControl::Property::ACCESSIBILITY_HIDDEN:
1511 if(value.Get(hidden))
1513 controlImpl.mImpl->mAccessibilityHidden = hidden;
1515 auto* accessible = controlImpl.GetAccessibleObject();
1516 if(DALI_LIKELY(accessible))
1518 auto* parent = dynamic_cast<Dali::Accessibility::ActorAccessible*>(accessible->GetParent());
1521 parent->OnChildrenChanged();
1527 case Toolkit::DevelControl::Property::CLOCKWISE_FOCUSABLE_ACTOR_ID:
1530 if(value.Get(focusId))
1532 controlImpl.mImpl->mClockwiseFocusableActorId = focusId;
1536 case Toolkit::DevelControl::Property::COUNTER_CLOCKWISE_FOCUSABLE_ACTOR_ID:
1539 if(value.Get(focusId))
1541 controlImpl.mImpl->mCounterClockwiseFocusableActorId = focusId;
1546 case Toolkit::DevelControl::Property::AUTOMATION_ID:
1548 std::string automationId;
1549 if(value.Get(automationId))
1551 controlImpl.mImpl->mAutomationId = automationId;
1559 Property::Value Control::Impl::GetProperty(BaseObject* object, Property::Index index)
1561 DALI_ASSERT_ALWAYS(Stage::IsCoreThread() && "Core is not installed. Might call this API from worker thread?");
1563 Property::Value value;
1565 Toolkit::Control control = Toolkit::Control::DownCast(BaseHandle(object));
1569 Control& controlImpl(GetImplementation(control));
1573 case Toolkit::Control::Property::STYLE_NAME:
1575 value = controlImpl.GetStyleName();
1579 case Toolkit::DevelControl::Property::STATE:
1581 value = controlImpl.mImpl->mState;
1585 case Toolkit::DevelControl::Property::SUB_STATE:
1587 value = controlImpl.mImpl->mSubStateName;
1591 case Toolkit::DevelControl::Property::LEFT_FOCUSABLE_ACTOR_ID:
1593 value = controlImpl.mImpl->mLeftFocusableActorId;
1597 case Toolkit::DevelControl::Property::RIGHT_FOCUSABLE_ACTOR_ID:
1599 value = controlImpl.mImpl->mRightFocusableActorId;
1603 case Toolkit::DevelControl::Property::UP_FOCUSABLE_ACTOR_ID:
1605 value = controlImpl.mImpl->mUpFocusableActorId;
1609 case Toolkit::DevelControl::Property::DOWN_FOCUSABLE_ACTOR_ID:
1611 value = controlImpl.mImpl->mDownFocusableActorId;
1615 case Toolkit::Control::Property::KEY_INPUT_FOCUS:
1617 value = controlImpl.HasKeyInputFocus();
1621 case Toolkit::Control::Property::BACKGROUND:
1624 Toolkit::Visual::Base visual = controlImpl.mImpl->GetVisual(Toolkit::Control::Property::BACKGROUND);
1627 visual.CreatePropertyMap(map);
1634 case Toolkit::Control::Property::MARGIN:
1636 value = controlImpl.mImpl->GetMargin();
1640 case Toolkit::Control::Property::PADDING:
1642 value = controlImpl.mImpl->GetPadding();
1646 case Toolkit::DevelControl::Property::TOOLTIP:
1649 if(controlImpl.mImpl->mTooltip)
1651 controlImpl.mImpl->mTooltip->CreatePropertyMap(map);
1657 case Toolkit::DevelControl::Property::SHADOW:
1660 Toolkit::Visual::Base visual = controlImpl.mImpl->GetVisual(Toolkit::DevelControl::Property::SHADOW);
1663 visual.CreatePropertyMap(map);
1670 case Toolkit::DevelControl::Property::ACCESSIBILITY_NAME:
1672 value = controlImpl.mImpl->mAccessibilityName;
1676 case Toolkit::DevelControl::Property::ACCESSIBILITY_DESCRIPTION:
1678 value = controlImpl.mImpl->mAccessibilityDescription;
1682 case Toolkit::DevelControl::Property::ACCESSIBILITY_TRANSLATION_DOMAIN:
1684 value = controlImpl.mImpl->mAccessibilityTranslationDomain;
1688 case Toolkit::DevelControl::Property::ACCESSIBILITY_ROLE:
1690 value = Property::Value(controlImpl.mImpl->mAccessibilityRole);
1694 case Toolkit::DevelControl::Property::ACCESSIBILITY_HIGHLIGHTABLE:
1696 value = controlImpl.mImpl->mAccessibilityHighlightable;
1700 case Toolkit::DevelControl::Property::ACCESSIBILITY_ATTRIBUTES:
1702 value = controlImpl.mImpl->mAccessibilityAttributes;
1706 case Toolkit::DevelControl::Property::DISPATCH_KEY_EVENTS:
1708 value = controlImpl.mImpl->mDispatchKeyEvents;
1712 case Toolkit::DevelControl::Property::ACCESSIBILITY_HIDDEN:
1714 value = controlImpl.mImpl->mAccessibilityHidden;
1718 case Toolkit::DevelControl::Property::CLOCKWISE_FOCUSABLE_ACTOR_ID:
1720 value = controlImpl.mImpl->mClockwiseFocusableActorId;
1724 case Toolkit::DevelControl::Property::COUNTER_CLOCKWISE_FOCUSABLE_ACTOR_ID:
1726 value = controlImpl.mImpl->mCounterClockwiseFocusableActorId;
1730 case Toolkit::DevelControl::Property::AUTOMATION_ID:
1732 value = controlImpl.mImpl->mAutomationId;
1741 void Control::Impl::RemoveAccessibilityAttribute(const std::string& key)
1743 Property::Value* value = mAccessibilityAttributes.Find(key);
1746 mAccessibilityAttributes[key] = Property::Value();
1750 void Control::Impl::ClearAccessibilityAttributes()
1752 mAccessibilityAttributes.Clear();
1755 void Control::Impl::SetAccessibilityReadingInfoType(const Dali::Accessibility::ReadingInfoTypes types)
1757 std::string value{};
1758 if(types[Dali::Accessibility::ReadingInfoType::NAME])
1760 value += READING_INFO_TYPE_NAME;
1762 if(types[Dali::Accessibility::ReadingInfoType::ROLE])
1766 value += READING_INFO_TYPE_SEPARATOR;
1768 value += READING_INFO_TYPE_ROLE;
1770 if(types[Dali::Accessibility::ReadingInfoType::DESCRIPTION])
1774 value += READING_INFO_TYPE_SEPARATOR;
1776 value += READING_INFO_TYPE_DESCRIPTION;
1778 if(types[Dali::Accessibility::ReadingInfoType::STATE])
1782 value += READING_INFO_TYPE_SEPARATOR;
1784 value += READING_INFO_TYPE_STATE;
1786 AppendAccessibilityAttribute(READING_INFO_TYPE_ATTRIBUTE_NAME, value);
1789 Dali::Accessibility::ReadingInfoTypes Control::Impl::GetAccessibilityReadingInfoType() const
1791 std::string value{};
1792 auto place = mAccessibilityAttributes.Find(READING_INFO_TYPE_ATTRIBUTE_NAME);
1799 Dali::Accessibility::ReadingInfoTypes types;
1800 types[Dali::Accessibility::ReadingInfoType::NAME] = true;
1801 types[Dali::Accessibility::ReadingInfoType::ROLE] = true;
1802 types[Dali::Accessibility::ReadingInfoType::DESCRIPTION] = true;
1803 types[Dali::Accessibility::ReadingInfoType::STATE] = true;
1812 Dali::Accessibility::ReadingInfoTypes types;
1814 if(value.find(READING_INFO_TYPE_NAME) != std::string::npos)
1816 types[Dali::Accessibility::ReadingInfoType::NAME] = true;
1818 if(value.find(READING_INFO_TYPE_ROLE) != std::string::npos)
1820 types[Dali::Accessibility::ReadingInfoType::ROLE] = true;
1822 if(value.find(READING_INFO_TYPE_DESCRIPTION) != std::string::npos)
1824 types[Dali::Accessibility::ReadingInfoType::DESCRIPTION] = true;
1826 if(value.find(READING_INFO_TYPE_STATE) != std::string::npos)
1828 types[Dali::Accessibility::ReadingInfoType::STATE] = true;
1834 void Control::Impl::CopyInstancedProperties(RegisteredVisualContainer& visuals, Dictionary<Property::Map>& instancedProperties)
1836 for(RegisteredVisualContainer::Iterator iter = visuals.Begin(); iter != visuals.End(); iter++)
1840 Property::Map instanceMap;
1841 Toolkit::GetImplementation((*iter)->visual).CreateInstancePropertyMap(instanceMap);
1842 instancedProperties.Add((*iter)->visual.GetName(), instanceMap);
1847 void Control::Impl::RemoveVisual(RegisteredVisualContainer& visuals, const std::string& visualName)
1849 Actor self(mControlImpl.Self());
1851 for(RegisteredVisualContainer::Iterator visualIter = visuals.Begin();
1852 visualIter != visuals.End();
1855 Toolkit::Visual::Base visual = (*visualIter)->visual;
1856 if(visual && visual.GetName() == visualName)
1858 Toolkit::GetImplementation(visual).SetOffScene(self);
1859 (*visualIter)->visual.Reset();
1860 visuals.Erase(visualIter);
1866 void Control::Impl::RemoveVisuals(RegisteredVisualContainer& visuals, DictionaryKeys& removeVisuals)
1868 Actor self(mControlImpl.Self());
1869 for(DictionaryKeys::iterator iter = removeVisuals.begin(); iter != removeVisuals.end(); ++iter)
1871 const std::string visualName = *iter;
1872 RemoveVisual(visuals, visualName);
1876 void Control::Impl::RecreateChangedVisuals(Dictionary<Property::Map>& stateVisualsToChange,
1877 Dictionary<Property::Map>& instancedProperties)
1879 Dali::CustomActor handle(mControlImpl.GetOwner());
1880 for(Dictionary<Property::Map>::iterator iter = stateVisualsToChange.Begin();
1881 iter != stateVisualsToChange.End();
1884 const std::string& visualName = (*iter).key;
1885 const Property::Map& toMap = (*iter).entry;
1887 Actor self = mControlImpl.Self();
1888 RegisteredVisualContainer::Iterator registeredVisualsiter;
1889 // Check if visual (visualName) is already registered, this is the current visual.
1890 if(FindVisual(visualName, mVisuals, registeredVisualsiter))
1892 Toolkit::Visual::Base& visual = (*registeredVisualsiter)->visual;
1895 // No longer required to know if the replaced visual's resources are ready
1896 StopObservingVisual(visual);
1898 // If control staged then visuals will be swapped once ready
1899 if(self.GetProperty<bool>(Actor::Property::CONNECTED_TO_SCENE))
1901 // Check if visual is currently in the process of being replaced ( is in removal container )
1902 RegisteredVisualContainer::Iterator visualQueuedForRemoval;
1903 if(FindVisual(visualName, mRemoveVisuals, visualQueuedForRemoval))
1905 // Visual with same visual name is already in removal container so current visual pending
1906 // Only the the last requested visual will be displayed so remove current visual which is staged but not ready.
1907 Toolkit::GetImplementation(visual).SetOffScene(self);
1908 (*registeredVisualsiter)->visual.Reset();
1909 mVisuals.Erase(registeredVisualsiter);
1913 // current visual not already in removal container so add now.
1914 DALI_LOG_INFO(gLogFilter, Debug::Verbose, "RegisterVisual Move current registered visual to removal Queue: %s \n", visualName.c_str());
1915 MoveVisual(registeredVisualsiter, mVisuals, mRemoveVisuals);
1920 // Control not staged or visual disabled so can just erase from registered visuals and new visual will be added later.
1921 (*registeredVisualsiter)->visual.Reset();
1922 mVisuals.Erase(registeredVisualsiter);
1926 const Property::Map* instancedMap = instancedProperties.FindConst(visualName);
1927 Style::ApplyVisual(handle, visualName, toMap, instancedMap);
1932 void Control::Impl::ReplaceStateVisualsAndProperties(const StylePtr oldState, const StylePtr newState, const std::string& subState)
1934 DALI_ASSERT_ALWAYS(Stage::IsCoreThread() && "Core is not installed. Might call this API from worker thread?");
1936 // Collect all old visual names
1937 DictionaryKeys stateVisualsToRemove;
1940 oldState->visuals.GetKeys(stateVisualsToRemove);
1941 if(!subState.empty())
1943 const StylePtr* oldSubState = oldState->subStates.FindConst(subState);
1946 DictionaryKeys subStateVisualsToRemove;
1947 (*oldSubState)->visuals.GetKeys(subStateVisualsToRemove);
1948 Merge(stateVisualsToRemove, subStateVisualsToRemove);
1953 // Collect all new visual properties
1954 Dictionary<Property::Map> stateVisualsToAdd;
1957 stateVisualsToAdd = newState->visuals;
1958 if(!subState.empty())
1960 const StylePtr* newSubState = newState->subStates.FindConst(subState);
1963 stateVisualsToAdd.Merge((*newSubState)->visuals);
1968 // If a name is in both add/remove, move it to change list.
1969 Dictionary<Property::Map> stateVisualsToChange;
1970 FindChangableVisuals(stateVisualsToAdd, stateVisualsToChange, stateVisualsToRemove);
1972 // Copy instanced properties (e.g. text label) of current visuals
1973 Dictionary<Property::Map> instancedProperties;
1974 CopyInstancedProperties(mVisuals, instancedProperties);
1976 // For each visual in remove list, remove from mVisuals
1977 RemoveVisuals(mVisuals, stateVisualsToRemove);
1979 // For each visual in add list, create and add to mVisuals
1980 Dali::CustomActor handle(mControlImpl.GetOwner());
1981 Style::ApplyVisuals(handle, stateVisualsToAdd, instancedProperties);
1983 // For each visual in change list, if it requires a new visual,
1984 // remove old visual, create and add to mVisuals
1985 RecreateChangedVisuals(stateVisualsToChange, instancedProperties);
1988 void Control::Impl::SetState(DevelControl::State newState, bool withTransitions)
1990 DevelControl::State oldState = mState;
1991 Dali::CustomActor handle(mControlImpl.GetOwner());
1992 DALI_LOG_INFO(gLogFilter, Debug::Concise, "Control::Impl::SetState: %s\n", (mState == DevelControl::NORMAL ? "NORMAL" : (mState == DevelControl::FOCUSED ? "FOCUSED" : (mState == DevelControl::DISABLED ? "DISABLED" : "NONE"))));
1994 if(mState != newState)
1996 // If mState was Disabled, and new state is Focused, should probably
1997 // store that fact, e.g. in another property that FocusManager can access.
2000 // Trigger state change and transitions
2001 // Apply new style, if stylemanager is available
2002 Toolkit::StyleManager styleManager = Toolkit::StyleManager::Get();
2005 const StylePtr stylePtr = GetImpl(styleManager).GetRecordedStyle(Toolkit::Control(mControlImpl.GetOwner()));
2009 std::string oldStateName = Scripting::GetEnumerationName<Toolkit::DevelControl::State>(oldState, ControlStateTable, ControlStateTableCount);
2010 std::string newStateName = Scripting::GetEnumerationName<Toolkit::DevelControl::State>(newState, ControlStateTable, ControlStateTableCount);
2012 const StylePtr* newStateStyle = stylePtr->subStates.Find(newStateName);
2013 const StylePtr* oldStateStyle = stylePtr->subStates.Find(oldStateName);
2014 if(oldStateStyle && newStateStyle)
2016 // Only change if both state styles exist
2017 ReplaceStateVisualsAndProperties(*oldStateStyle, *newStateStyle, mSubStateName);
2024 void Control::Impl::SetSubState(const std::string& subStateName, bool withTransitions)
2026 if(mSubStateName != subStateName)
2028 // Get existing sub-state visuals, and unregister them
2029 Dali::CustomActor handle(mControlImpl.GetOwner());
2031 Toolkit::StyleManager styleManager = Toolkit::StyleManager::Get();
2034 const StylePtr stylePtr = GetImpl(styleManager).GetRecordedStyle(Toolkit::Control(mControlImpl.GetOwner()));
2038 std::string stateName = Scripting::GetEnumerationName<Toolkit::DevelControl::State>(mState, ControlStateTable, ControlStateTableCount);
2040 const StylePtr* state = stylePtr->subStates.Find(stateName);
2043 StylePtr stateStyle(*state);
2045 const StylePtr* newStateStyle = stateStyle->subStates.Find(subStateName);
2046 const StylePtr* oldStateStyle = stateStyle->subStates.Find(mSubStateName);
2047 if(oldStateStyle && newStateStyle)
2050 ReplaceStateVisualsAndProperties(*oldStateStyle, *newStateStyle, empty);
2056 mSubStateName = subStateName;
2060 void Control::Impl::OnSceneDisconnection()
2062 Actor self = mControlImpl.Self();
2064 // Any visuals set for replacement but not yet ready should still be registered.
2065 // Reason: If a request was made to register a new visual but the control removed from scene before visual was ready
2066 // then when this control appears back on stage it should use that new visual.
2068 // Iterate through all registered visuals and set off scene
2069 SetVisualsOffScene(mVisuals, self);
2071 // Visuals pending replacement can now be taken out of the removal list and set off scene
2072 // Iterate through all replacement visuals and add to a move queue then set off scene
2074 if(!mRemoveVisuals.Empty())
2076 std::reverse(mRemoveVisuals.Begin(), mRemoveVisuals.End());
2078 while(!mRemoveVisuals.Empty())
2080 auto removalIter = mRemoveVisuals.End() - 1u;
2081 Toolkit::GetImplementation((*removalIter)->visual).SetOffScene(self);
2083 // Discard removed visual. It will be destroyed at next Idle time.
2084 DiscardVisual(removalIter, mRemoveVisuals);
2088 for(auto replacedIter = mVisuals.Begin(), end = mVisuals.End(); replacedIter != end; replacedIter++)
2090 (*replacedIter)->pending = false;
2094 void Control::Impl::SetMargin(Extents margin)
2096 mControlImpl.mImpl->mMargin = margin;
2098 // Trigger a size negotiation request that may be needed when setting a margin.
2099 mControlImpl.RelayoutRequest();
2102 Extents Control::Impl::GetMargin() const
2104 return mControlImpl.mImpl->mMargin;
2107 void Control::Impl::SetPadding(Extents padding)
2109 mControlImpl.mImpl->mPadding = padding;
2111 // Trigger a size negotiation request that may be needed when setting a padding.
2112 mControlImpl.RelayoutRequest();
2115 Extents Control::Impl::GetPadding() const
2117 return mControlImpl.mImpl->mPadding;
2120 void Control::Impl::SetInputMethodContext(InputMethodContext& inputMethodContext)
2122 mInputMethodContext = inputMethodContext;
2125 bool Control::Impl::FilterKeyEvent(const KeyEvent& event)
2127 bool consumed(false);
2129 if(mInputMethodContext)
2131 consumed = mInputMethodContext.FilterEventKey(event);
2136 DevelControl::VisualEventSignalType& Control::Impl::VisualEventSignal()
2138 return mVisualEventSignal;
2141 void Control::Impl::SetShadow(const Property::Map& map)
2143 Toolkit::Visual::Base visual = Toolkit::VisualFactory::Get().CreateVisual(map);
2144 visual.SetName("shadow");
2148 mControlImpl.mImpl->RegisterVisual(Toolkit::DevelControl::Property::SHADOW, visual, DepthIndex::BACKGROUND_EFFECT);
2150 mControlImpl.RelayoutRequest();
2154 void Control::Impl::ClearShadow()
2156 mControlImpl.mImpl->UnregisterVisual(Toolkit::DevelControl::Property::SHADOW);
2158 // Trigger a size negotiation request that may be needed when unregistering a visual.
2159 mControlImpl.RelayoutRequest();
2162 Dali::Property Control::Impl::GetVisualProperty(Dali::Property::Index index, Dali::Property::Key visualPropertyKey)
2164 Toolkit::Visual::Base visual = GetVisualByIndex(mVisuals, index);
2167 Internal::Visual::Base& visualImpl = Toolkit::GetImplementation(visual);
2168 return visualImpl.GetPropertyObject(std::move(visualPropertyKey));
2172 return Dali::Property(handle, Property::INVALID_INDEX);
2175 void Control::Impl::CreateTransitions(std::vector<std::pair<Dali::Property::Index, Dali::Property::Map>>& sourceProperties,
2176 std::vector<std::pair<Dali::Property::Index, Dali::Property::Map>>& destinationProperties,
2177 Dali::Toolkit::Control source,
2178 Dali::Toolkit::Control destination)
2180 // Retrieves background properties to be transitioned.
2181 Dali::Property::Map backgroundSourcePropertyMap, backgroundDestinationPropertyMap;
2182 mControlImpl.MakeVisualTransition(backgroundSourcePropertyMap, backgroundDestinationPropertyMap, source, destination, Toolkit::Control::Property::BACKGROUND);
2183 if(backgroundSourcePropertyMap.Count() > 0)
2185 sourceProperties.push_back(std::pair<Dali::Property::Index, Dali::Property::Map>(Toolkit::Control::Property::BACKGROUND, backgroundSourcePropertyMap));
2186 destinationProperties.push_back(std::pair<Dali::Property::Index, Dali::Property::Map>(Toolkit::Control::Property::BACKGROUND, backgroundDestinationPropertyMap));
2189 // Retrieves shadow properties to be transitioned.
2190 Dali::Property::Map shadowSourcePropertyMap, shadowDestinationPropertyMap;
2191 mControlImpl.MakeVisualTransition(shadowSourcePropertyMap, shadowDestinationPropertyMap, source, destination, Toolkit::DevelControl::Property::SHADOW);
2192 if(shadowSourcePropertyMap.Count() > 0)
2194 sourceProperties.push_back(std::pair<Dali::Property::Index, Dali::Property::Map>(Toolkit::DevelControl::Property::SHADOW, shadowSourcePropertyMap));
2195 destinationProperties.push_back(std::pair<Dali::Property::Index, Dali::Property::Map>(Toolkit::DevelControl::Property::SHADOW, shadowDestinationPropertyMap));
2198 // Retrieves transition from inherited class.
2199 mControlImpl.OnCreateTransitions(sourceProperties, destinationProperties, source, destination);
2202 void Control::Impl::UpdateVisualProperties(const std::vector<std::pair<Dali::Property::Index, Dali::Property::Map>>& properties)
2204 for(auto&& data : properties)
2206 if(data.first == Toolkit::Control::Property::BACKGROUND)
2208 DoAction(Toolkit::Control::Property::BACKGROUND, DevelVisual::Action::UPDATE_PROPERTY, data.second);
2210 else if(data.first == Toolkit::DevelControl::Property::SHADOW)
2212 DoAction(Toolkit::DevelControl::Property::SHADOW, DevelVisual::Action::UPDATE_PROPERTY, data.second);
2215 mControlImpl.OnUpdateVisualProperties(properties);
2218 void Control::Impl::EmitResourceReadySignal()
2220 if(!mIsEmittingResourceReadySignal)
2222 // Guard against calls to emit the signal during the callback
2223 mIsEmittingResourceReadySignal = true;
2225 // If the signal handler changes visual, it may become ready during this call & therefore this method will
2226 // get called again recursively. If so, mIdleCallbackRegistered is set below, and we act on it after that secondary
2227 // invocation has completed by notifying in an Idle callback to prevent further recursion.
2228 Dali::Toolkit::Control handle(mControlImpl.GetOwner());
2229 mResourceReadySignal.Emit(handle);
2231 mIsEmittingResourceReadySignal = false;
2235 if(!mIdleCallbackRegistered)
2237 mIdleCallbackRegistered = true;
2239 // Add idler to emit the signal again
2242 // The callback manager takes the ownership of the callback object.
2243 mIdleCallback = MakeCallback(this, &Control::Impl::OnIdleCallback);
2244 if(DALI_UNLIKELY(!Adaptor::Get().AddIdle(mIdleCallback, true)))
2246 DALI_LOG_ERROR("Fail to add idle callback for control resource ready. Skip this callback.\n");
2247 mIdleCallback = nullptr;
2248 mIdleCallbackRegistered = false;
2255 bool Control::Impl::OnIdleCallback()
2258 mIdleCallbackRegistered = false;
2260 // A visual is ready so control may need relayouting if staged
2261 if(mControlImpl.Self().GetProperty<bool>(Actor::Property::CONNECTED_TO_SCENE))
2263 mControlImpl.RelayoutRequest();
2266 EmitResourceReadySignal();
2268 if(!mIdleCallbackRegistered)
2270 // Set the pointer to null as the callback manager deletes the callback after execute it.
2271 mIdleCallback = nullptr;
2274 // Repeat idle if mIdleCallbackRegistered become true one more time.
2275 return mIdleCallbackRegistered;
2278 Toolkit::DevelControl::ControlAccessible* Control::Impl::GetAccessibleObject()
2280 if(mAccessibleCreatable && !mAccessibleObject)
2282 mAccessibleObject.reset(mControlImpl.CreateAccessibleObject());
2285 return mAccessibleObject.get();
2288 bool Control::Impl::IsAccessibleCreated() const
2290 return !!mAccessibleObject;
2293 void Control::Impl::EnableCreateAccessible(bool enable)
2295 mAccessibleCreatable = enable;
2298 bool Control::Impl::IsCreateAccessibleEnabled() const
2300 return mAccessibleCreatable;
2303 } // namespace Internal
2305 } // namespace Toolkit