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 * 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();
723 if(mAccessibilityGetNameSignal.Empty())
725 if(index == DevelControl::Property::ACCESSIBILITY_NAME || (mAccessibilityName.empty() && index == accessible->GetNamePropertyIndex()))
727 accessible->Emit(Dali::Accessibility::ObjectPropertyChangeEvent::NAME);
731 if(mAccessibilityGetDescriptionSignal.Empty())
733 if(index == DevelControl::Property::ACCESSIBILITY_DESCRIPTION || (mAccessibilityDescription.empty() && index == accessible->GetDescriptionPropertyIndex()))
735 accessible->Emit(Dali::Accessibility::ObjectPropertyChangeEvent::DESCRIPTION);
740 // Gesture Detection Methods
741 void Control::Impl::PinchDetected(Actor actor, const PinchGesture& pinch)
743 mControlImpl.OnPinch(pinch);
746 void Control::Impl::PanDetected(Actor actor, const PanGesture& pan)
748 mControlImpl.OnPan(pan);
751 void Control::Impl::TapDetected(Actor actor, const TapGesture& tap)
753 mControlImpl.OnTap(tap);
756 void Control::Impl::LongPressDetected(Actor actor, const LongPressGesture& longPress)
758 mControlImpl.OnLongPress(longPress);
761 void Control::Impl::RegisterVisual(Property::Index index, Toolkit::Visual::Base& visual)
763 RegisterVisual(index, visual, VisualState::ENABLED, DepthIndexValue::NOT_SET);
766 void Control::Impl::RegisterVisual(Property::Index index, Toolkit::Visual::Base& visual, int depthIndex)
768 RegisterVisual(index, visual, VisualState::ENABLED, DepthIndexValue::SET, depthIndex);
771 void Control::Impl::RegisterVisual(Property::Index index, Toolkit::Visual::Base& visual, bool enabled)
773 RegisterVisual(index, visual, (enabled ? VisualState::ENABLED : VisualState::DISABLED), DepthIndexValue::NOT_SET);
776 void Control::Impl::RegisterVisual(Property::Index index, Toolkit::Visual::Base& visual, bool enabled, int depthIndex)
778 RegisterVisual(index, visual, (enabled ? VisualState::ENABLED : VisualState::DISABLED), DepthIndexValue::SET, depthIndex);
781 void Control::Impl::RegisterVisual(Property::Index index, Toolkit::Visual::Base& visual, VisualState::Type enabled, DepthIndexValue::Type depthIndexValueSet, int depthIndex)
783 DALI_ASSERT_ALWAYS(Stage::IsCoreThread() && "Core is not installed. Might call this API from worker thread?");
785 DALI_LOG_INFO(gLogFilter, Debug::Concise, "RegisterVisual:%d \n", index);
787 bool visualReplaced(false);
788 Actor self = mControlImpl.Self();
790 // Set the depth index, if not set by caller this will be either the current visual depth, max depth of all visuals
792 int requiredDepthIndex = visual.GetDepthIndex();
794 if(depthIndexValueSet == DepthIndexValue::SET)
796 requiredDepthIndex = depthIndex;
799 // Visual replacement, existing visual should only be removed from stage when replacement ready.
800 if(!mVisuals.Empty())
802 RegisteredVisualContainer::Iterator registeredVisualsiter;
803 // Check if visual (index) is already registered, this is the current visual.
804 if(FindVisual(index, mVisuals, registeredVisualsiter))
806 Toolkit::Visual::Base& currentRegisteredVisual = (*registeredVisualsiter)->visual;
807 if(currentRegisteredVisual)
809 // Store current visual depth index as may need to set the replacement visual to same depth
810 const int currentDepthIndex = (*registeredVisualsiter)->visual.GetDepthIndex();
812 // No longer required to know if the replaced visual's resources are ready
813 StopObservingVisual(currentRegisteredVisual);
815 // If control staged and visual enabled then visuals will be swapped once ready
816 if(self.GetProperty<bool>(Actor::Property::CONNECTED_TO_SCENE) && enabled)
818 // Check if visual is currently in the process of being replaced ( is in removal container )
819 RegisteredVisualContainer::Iterator visualQueuedForRemoval;
820 if(FindVisual(index, mRemoveVisuals, visualQueuedForRemoval))
822 // Visual with same index is already in removal container so current visual pending
823 // Only the the last requested visual will be displayed so remove current visual which is staged but not ready.
824 Toolkit::GetImplementation(currentRegisteredVisual).SetOffScene(self);
825 mVisuals.Erase(registeredVisualsiter);
829 // current visual not already in removal container so add now.
830 DALI_LOG_INFO(gLogFilter, Debug::Verbose, "RegisterVisual Move current registered visual to removal Queue: %d \n", index);
831 MoveVisual(registeredVisualsiter, mVisuals, mRemoveVisuals);
836 // Control not staged or visual disabled so can just erase from registered visuals and new visual will be added later.
837 mVisuals.Erase(registeredVisualsiter);
840 // 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
841 if((depthIndexValueSet == DepthIndexValue::NOT_SET) &&
842 (visual.GetDepthIndex() == 0))
844 requiredDepthIndex = currentDepthIndex;
848 visualReplaced = true;
852 // If not set, set the name of the visual to the same name as the control's property.
853 // ( If the control has been type registered )
854 if(visual.GetName().empty())
856 // returns empty string if index is not found as long as index is not -1
857 std::string visualName = self.GetPropertyName(index);
858 if(!visualName.empty())
860 DALI_LOG_INFO(gLogFilter, Debug::Concise, "Setting visual name for property %d to %s\n", index, visualName.c_str());
861 visual.SetName(visualName);
865 if(!visualReplaced) // New registration entry
867 // 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
868 if((depthIndexValueSet == DepthIndexValue::NOT_SET) &&
869 (mVisuals.Size() > 0) &&
870 (visual.GetDepthIndex() == 0))
872 int maxDepthIndex = std::numeric_limits<int>::min();
874 RegisteredVisualContainer::ConstIterator iter;
875 const RegisteredVisualContainer::ConstIterator endIter = mVisuals.End();
876 for(iter = mVisuals.Begin(); iter != endIter; iter++)
878 const int visualDepthIndex = (*iter)->visual.GetDepthIndex();
879 if(visualDepthIndex > maxDepthIndex)
881 maxDepthIndex = visualDepthIndex;
884 ++maxDepthIndex; // Add one to the current maximum depth index so that our added visual appears on top
885 requiredDepthIndex = std::max(0, maxDepthIndex); // Start at zero if maxDepth index belongs to a background
891 // Set determined depth index
892 visual.SetDepthIndex(requiredDepthIndex);
894 // Monitor when the visual resources are ready
895 StartObservingVisual(visual);
897 DALI_LOG_INFO(gLogFilter, Debug::Concise, "New Visual registration index[%d] depth[%d]\n", index, requiredDepthIndex);
898 RegisteredVisual* newRegisteredVisual = new RegisteredVisual(index, visual, (enabled == VisualState::ENABLED ? true : false), (visualReplaced && enabled));
899 mVisuals.PushBack(newRegisteredVisual);
901 Internal::Visual::Base& visualImpl = Toolkit::GetImplementation(visual);
902 // Put on stage if enabled and the control is already on the stage
903 if((enabled == VisualState::ENABLED) && self.GetProperty<bool>(Actor::Property::CONNECTED_TO_SCENE))
905 visualImpl.SetOnScene(self);
907 else if(enabled && visualImpl.IsResourceReady()) // When not being staged, check if visual already 'ResourceReady' before it was Registered. ( Resource may have been loaded already )
909 ResourceReady(visualImpl);
913 DALI_LOG_INFO(gLogFilter, Debug::Verbose, "Control::RegisterVisual() Registered %s(%d), enabled:%s\n", visual.GetName().c_str(), index, enabled ? "true" : "false");
916 void Control::Impl::UnregisterVisual(Property::Index index)
918 DALI_ASSERT_ALWAYS(Stage::IsCoreThread() && "Core is not installed. Might call this API from worker thread?");
920 RegisteredVisualContainer::Iterator iter;
921 if(FindVisual(index, mVisuals, iter))
923 // stop observing visual
924 StopObservingVisual((*iter)->visual);
926 Actor self(mControlImpl.Self());
927 Toolkit::GetImplementation((*iter)->visual).SetOffScene(self);
928 (*iter)->visual.Reset();
929 mVisuals.Erase(iter);
932 if(FindVisual(index, mRemoveVisuals, iter))
934 Actor self(mControlImpl.Self());
935 Toolkit::GetImplementation((*iter)->visual).SetOffScene(self);
936 (*iter)->pending = false;
938 // Discard removed visual. It will be destroyed at next Idle time.
939 DiscardVisual(iter, mRemoveVisuals);
943 Toolkit::Visual::Base Control::Impl::GetVisual(Property::Index index) const
945 RegisteredVisualContainer::Iterator iter;
946 if(FindVisual(index, mVisuals, iter))
948 return (*iter)->visual;
951 return Toolkit::Visual::Base();
954 void Control::Impl::EnableVisual(Property::Index index, bool enable)
956 DALI_LOG_INFO(gLogFilter, Debug::General, "Control::EnableVisual(%d, %s)\n", index, enable ? "T" : "F");
958 RegisteredVisualContainer::Iterator iter;
959 if(FindVisual(index, mVisuals, iter))
961 if((*iter)->enabled == enable)
963 DALI_LOG_INFO(gLogFilter, Debug::Verbose, "Control::EnableVisual Visual %s(%d) already %s\n", (*iter)->visual.GetName().c_str(), index, enable ? "enabled" : "disabled");
967 (*iter)->enabled = enable;
968 Actor parentActor = mControlImpl.Self();
969 if(mControlImpl.Self().GetProperty<bool>(Actor::Property::CONNECTED_TO_SCENE)) // If control not on Scene then Visual will be added when SceneConnection is called.
973 DALI_LOG_INFO(gLogFilter, Debug::Verbose, "Control::EnableVisual Setting %s(%d) on stage \n", (*iter)->visual.GetName().c_str(), index);
974 Toolkit::GetImplementation((*iter)->visual).SetOnScene(parentActor);
978 DALI_LOG_INFO(gLogFilter, Debug::Verbose, "Control::EnableVisual Setting %s(%d) off stage \n", (*iter)->visual.GetName().c_str(), index);
979 Toolkit::GetImplementation((*iter)->visual).SetOffScene(parentActor); // No need to call if control not staged.
985 DALI_LOG_WARNING("Control::EnableVisual(%d, %s) FAILED - NO SUCH VISUAL\n", index, enable ? "T" : "F");
989 bool Control::Impl::IsVisualEnabled(Property::Index index) const
991 RegisteredVisualContainer::Iterator iter;
992 if(FindVisual(index, mVisuals, iter))
994 return (*iter)->enabled;
999 void Control::Impl::EnableReadyTransitionOverriden(Toolkit::Visual::Base& visual, bool enable)
1001 DALI_LOG_INFO(gLogFilter, Debug::General, "Control::EnableReadyTransitionOverriden(%p, %s)\n", visual, enable ? "T" : "F");
1003 RegisteredVisualContainer::Iterator iter;
1004 if(FindVisual(visual, mVisuals, iter))
1006 if((*iter)->overideReadyTransition == enable)
1008 DALI_LOG_INFO(gLogFilter, Debug::Verbose, "Control::EnableReadyTransitionOverriden Visual %s(%p) already %s\n", (*iter)->visual.GetName().c_str(), visual, enable ? "enabled" : "disabled");
1012 (*iter)->overideReadyTransition = enable;
1016 void Control::Impl::StopObservingVisual(Toolkit::Visual::Base& visual)
1018 Internal::Visual::Base& visualImpl = Toolkit::GetImplementation(visual);
1020 // Stop observing the visual
1021 visualImpl.RemoveEventObserver(*this);
1024 void Control::Impl::StartObservingVisual(Toolkit::Visual::Base& visual)
1026 Internal::Visual::Base& visualImpl = Toolkit::GetImplementation(visual);
1028 // start observing the visual for events
1029 visualImpl.AddEventObserver(*this);
1032 void Control::Impl::ResourceReady()
1034 DALI_ASSERT_ALWAYS(Stage::IsCoreThread() && "Core is not installed. Might call this API from worker thread?");
1036 // Emit signal if all enabled visuals registered by the control are ready or there are no visuals.
1037 if(IsResourceReady())
1039 EmitResourceReadySignal();
1043 // Called by a Visual when it's resource is ready
1044 void Control::Impl::ResourceReady(Visual::Base& object)
1046 DALI_LOG_INFO(gLogFilter, Debug::Verbose, "Control::Impl::ResourceReady() replacements pending[%d]\n", mRemoveVisuals.Count());
1048 Actor self = mControlImpl.Self();
1050 RegisteredVisualContainer::Iterator registeredIter;
1052 // A resource is ready, find resource in the registered visuals container and get its index
1053 if(!FindVisual(object, mVisuals, registeredIter))
1058 RegisteredVisualContainer::Iterator visualToRemoveIter;
1059 // Find visual with the same index in the removal container
1060 // Set if off stage as it's replacement is now ready.
1061 // Remove if from removal list as now removed from stage.
1062 // Set Pending flag on the ready visual to false as now ready.
1063 if(FindVisual((*registeredIter)->index, mRemoveVisuals, visualToRemoveIter))
1065 (*registeredIter)->pending = false;
1066 if(!((*visualToRemoveIter)->overideReadyTransition))
1068 Toolkit::GetImplementation((*visualToRemoveIter)->visual).SetOffScene(self);
1071 // Discard removed visual. It will be destroyed at next Idle time.
1072 DiscardVisual(visualToRemoveIter, mRemoveVisuals);
1075 // A visual is ready so control may need relayouting if staged
1076 RelayoutRequest(object);
1078 // Called by a Visual when it's resource is ready
1079 if(((*registeredIter)->enabled))
1085 void Control::Impl::NotifyVisualEvent(Visual::Base& object, Property::Index signalId)
1087 for(auto registeredIter = mVisuals.Begin(), end = mVisuals.End(); registeredIter != end; ++registeredIter)
1089 Internal::Visual::Base& registeredVisualImpl = Toolkit::GetImplementation((*registeredIter)->visual);
1090 if(&object == ®isteredVisualImpl)
1092 Dali::Toolkit::Control handle(mControlImpl.GetOwner());
1093 mVisualEventSignal.Emit(handle, (*registeredIter)->index, signalId);
1099 void Control::Impl::RelayoutRequest(Visual::Base& object)
1101 if(mControlImpl.Self().GetProperty<bool>(Actor::Property::CONNECTED_TO_SCENE))
1103 mControlImpl.RelayoutRequest();
1107 bool Control::Impl::IsResourceReady() const
1109 // Iterate through and check all the enabled visuals are ready
1110 for(auto visualIter = mVisuals.Begin();
1111 visualIter != mVisuals.End();
1114 const Toolkit::Visual::Base visual = (*visualIter)->visual;
1115 const Internal::Visual::Base& visualImpl = Toolkit::GetImplementation(visual);
1117 // one of the enabled visuals is not ready
1118 if(!visualImpl.IsResourceReady() && (*visualIter)->enabled)
1126 Toolkit::Visual::ResourceStatus Control::Impl::GetVisualResourceStatus(Property::Index index) const
1128 RegisteredVisualContainer::Iterator iter;
1129 if(FindVisual(index, mVisuals, iter))
1131 const Toolkit::Visual::Base visual = (*iter)->visual;
1132 const Internal::Visual::Base& visualImpl = Toolkit::GetImplementation(visual);
1133 return visualImpl.GetResourceStatus();
1136 return Toolkit::Visual::ResourceStatus::PREPARING;
1139 void Control::Impl::AddTransitions(Dali::Animation& animation,
1140 const Toolkit::TransitionData& handle,
1141 bool createAnimation)
1143 // Setup a Transition from TransitionData.
1144 const Internal::TransitionData& transitionData = Toolkit::GetImplementation(handle);
1145 TransitionData::Iterator end = transitionData.End();
1146 for(TransitionData::Iterator iter = transitionData.Begin();
1150 TransitionData::Animator* animator = (*iter);
1152 Toolkit::Visual::Base visual = GetVisualByName(mVisuals, animator->objectName);
1156 #if defined(DEBUG_ENABLED)
1157 Dali::TypeInfo typeInfo;
1158 ControlWrapper* controlWrapperImpl = dynamic_cast<ControlWrapper*>(&mControlImpl);
1159 if(controlWrapperImpl)
1161 typeInfo = controlWrapperImpl->GetTypeInfo();
1164 DALI_LOG_INFO(gLogFilter, Debug::Concise, "CreateTransition: Found %s visual for %s\n", visual.GetName().c_str(), typeInfo ? typeInfo.GetName().c_str() : "Unknown");
1166 Internal::Visual::Base& visualImpl = Toolkit::GetImplementation(visual);
1167 visualImpl.AnimateProperty(animation, *animator);
1171 DALI_LOG_INFO(gLogFilter, Debug::Concise, "CreateTransition: Could not find visual. Trying actors");
1172 // Otherwise, try any actor children of control (Including the control)
1173 Actor child = mControlImpl.Self().FindChildByName(animator->objectName);
1176 Property::Index propertyIndex = child.GetPropertyIndex(animator->propertyKey);
1177 if(propertyIndex != Property::INVALID_INDEX)
1179 if(animator->animate == false)
1181 if(animator->targetValue.GetType() != Property::NONE)
1183 child.SetProperty(propertyIndex, animator->targetValue);
1186 else // animate the property
1188 if(animator->initialValue.GetType() != Property::NONE)
1190 child.SetProperty(propertyIndex, animator->initialValue);
1193 if(createAnimation && !animation)
1195 animation = Dali::Animation::New(0.1f);
1198 animation.AnimateTo(Property(child, propertyIndex),
1199 animator->targetValue,
1200 animator->alphaFunction,
1201 TimePeriod(animator->timePeriodDelay,
1202 animator->timePeriodDuration));
1210 Dali::Animation Control::Impl::CreateTransition(const Toolkit::TransitionData& transitionData)
1212 Dali::Animation transition;
1214 if(transitionData.Count() > 0)
1216 AddTransitions(transition, transitionData, true);
1221 void Control::Impl::DoAction(Dali::Property::Index visualIndex, Dali::Property::Index actionId, const Dali::Property::Value attributes)
1223 RegisteredVisualContainer::Iterator iter;
1224 if(FindVisual(visualIndex, mVisuals, iter))
1226 Toolkit::GetImplementation((*iter)->visual).DoAction(actionId, attributes);
1230 void Control::Impl::DoActionExtension(Dali::Property::Index visualIndex, Dali::Property::Index actionId, Dali::Any attributes)
1232 RegisteredVisualContainer::Iterator iter;
1233 if(FindVisual(visualIndex, mVisuals, iter))
1235 Toolkit::GetImplementation((*iter)->visual).DoActionExtension(actionId, attributes);
1239 void Control::Impl::AppendAccessibilityAttribute(const std::string& key, const std::string value)
1241 Property::Value* checkedValue = mAccessibilityAttributes.Find(key);
1244 mAccessibilityAttributes[key] = Property::Value(value);
1248 mAccessibilityAttributes.Insert(key, value);
1252 void Control::Impl::SetProperty(BaseObject* object, Property::Index index, const Property::Value& value)
1254 DALI_ASSERT_ALWAYS(Stage::IsCoreThread() && "Core is not installed. Might call this API from worker thread?");
1256 Toolkit::Control control = Toolkit::Control::DownCast(BaseHandle(object));
1260 Control& controlImpl(GetImplementation(control));
1264 case Toolkit::Control::Property::STYLE_NAME:
1266 controlImpl.SetStyleName(value.Get<std::string>());
1270 case Toolkit::DevelControl::Property::STATE:
1272 bool withTransitions = true;
1273 const Property::Value* valuePtr = &value;
1274 const Property::Map* map = value.GetMap();
1277 Property::Value* value2 = map->Find("withTransitions");
1280 withTransitions = value2->Get<bool>();
1283 valuePtr = map->Find("state");
1288 Toolkit::DevelControl::State state(controlImpl.mImpl->mState);
1289 if(Scripting::GetEnumerationProperty<Toolkit::DevelControl::State>(*valuePtr, ControlStateTable, ControlStateTableCount, state))
1291 controlImpl.mImpl->SetState(state, withTransitions);
1297 case Toolkit::DevelControl::Property::SUB_STATE:
1299 std::string subState;
1300 if(value.Get(subState))
1302 controlImpl.mImpl->SetSubState(subState);
1307 case Toolkit::DevelControl::Property::LEFT_FOCUSABLE_ACTOR_ID:
1310 if(value.Get(focusId))
1312 controlImpl.mImpl->mLeftFocusableActorId = focusId;
1317 case Toolkit::DevelControl::Property::RIGHT_FOCUSABLE_ACTOR_ID:
1320 if(value.Get(focusId))
1322 controlImpl.mImpl->mRightFocusableActorId = focusId;
1327 case Toolkit::DevelControl::Property::UP_FOCUSABLE_ACTOR_ID:
1330 if(value.Get(focusId))
1332 controlImpl.mImpl->mUpFocusableActorId = focusId;
1337 case Toolkit::DevelControl::Property::DOWN_FOCUSABLE_ACTOR_ID:
1340 if(value.Get(focusId))
1342 controlImpl.mImpl->mDownFocusableActorId = focusId;
1347 case Toolkit::Control::Property::KEY_INPUT_FOCUS:
1349 if(value.Get<bool>())
1351 controlImpl.SetKeyInputFocus();
1355 controlImpl.ClearKeyInputFocus();
1360 case Toolkit::Control::Property::BACKGROUND:
1364 const Property::Map* map = value.GetMap();
1365 if(map && !map->Empty())
1367 controlImpl.SetBackground(*map);
1369 else if(value.Get(url))
1371 // don't know the size to load
1372 Toolkit::Visual::Base visual = Toolkit::VisualFactory::Get().CreateVisual(url, ImageDimensions());
1375 controlImpl.mImpl->RegisterVisual(Toolkit::Control::Property::BACKGROUND, visual, DepthIndex::BACKGROUND);
1378 else if(value.Get(color))
1380 controlImpl.SetBackgroundColor(color);
1384 // The background is an empty property map, so we should clear the background
1385 controlImpl.ClearBackground();
1390 case Toolkit::Control::Property::MARGIN:
1393 if(value.Get(margin))
1395 controlImpl.mImpl->SetMargin(margin);
1400 case Toolkit::Control::Property::PADDING:
1403 if(value.Get(padding))
1405 controlImpl.mImpl->SetPadding(padding);
1410 case Toolkit::DevelControl::Property::TOOLTIP:
1412 TooltipPtr& tooltipPtr = controlImpl.mImpl->mTooltip;
1415 tooltipPtr = Tooltip::New(control);
1417 tooltipPtr->SetProperties(value);
1421 case Toolkit::DevelControl::Property::SHADOW:
1423 const Property::Map* map = value.GetMap();
1424 if(map && !map->Empty())
1426 controlImpl.mImpl->SetShadow(*map);
1430 // The shadow is an empty property map, so we should clear the shadow
1431 controlImpl.mImpl->ClearShadow();
1436 case Toolkit::DevelControl::Property::ACCESSIBILITY_NAME:
1441 controlImpl.mImpl->mAccessibilityName = name;
1446 case Toolkit::DevelControl::Property::ACCESSIBILITY_DESCRIPTION:
1451 controlImpl.mImpl->mAccessibilityDescription = text;
1456 case Toolkit::DevelControl::Property::ACCESSIBILITY_TRANSLATION_DOMAIN:
1461 controlImpl.mImpl->mAccessibilityTranslationDomain = text;
1466 case Toolkit::DevelControl::Property::ACCESSIBILITY_ROLE:
1468 Dali::Accessibility::Role role;
1471 controlImpl.mImpl->mAccessibilityRole = role;
1476 case Toolkit::DevelControl::Property::ACCESSIBILITY_HIGHLIGHTABLE:
1479 if(value.Get(highlightable))
1481 controlImpl.mImpl->mAccessibilityHighlightable = highlightable;
1486 case Toolkit::DevelControl::Property::ACCESSIBILITY_ATTRIBUTES:
1488 const Property::Map* map = value.GetMap();
1489 if(map && !map->Empty())
1491 controlImpl.mImpl->mAccessibilityAttributes = *map;
1496 case Toolkit::DevelControl::Property::DISPATCH_KEY_EVENTS:
1499 if(value.Get(dispatch))
1501 controlImpl.mImpl->mDispatchKeyEvents = dispatch;
1506 case Toolkit::DevelControl::Property::ACCESSIBILITY_HIDDEN:
1509 if(value.Get(hidden))
1511 controlImpl.mImpl->mAccessibilityHidden = hidden;
1513 auto* accessible = controlImpl.GetAccessibleObject();
1514 if(DALI_LIKELY(accessible))
1516 auto* parent = dynamic_cast<Dali::Accessibility::ActorAccessible*>(accessible->GetParent());
1519 parent->OnChildrenChanged();
1525 case Toolkit::DevelControl::Property::CLOCKWISE_FOCUSABLE_ACTOR_ID:
1528 if(value.Get(focusId))
1530 controlImpl.mImpl->mClockwiseFocusableActorId = focusId;
1534 case Toolkit::DevelControl::Property::COUNTER_CLOCKWISE_FOCUSABLE_ACTOR_ID:
1537 if(value.Get(focusId))
1539 controlImpl.mImpl->mCounterClockwiseFocusableActorId = focusId;
1544 case Toolkit::DevelControl::Property::AUTOMATION_ID:
1546 std::string automationId;
1547 if(value.Get(automationId))
1549 controlImpl.mImpl->mAutomationId = automationId;
1557 Property::Value Control::Impl::GetProperty(BaseObject* object, Property::Index index)
1559 DALI_ASSERT_ALWAYS(Stage::IsCoreThread() && "Core is not installed. Might call this API from worker thread?");
1561 Property::Value value;
1563 Toolkit::Control control = Toolkit::Control::DownCast(BaseHandle(object));
1567 Control& controlImpl(GetImplementation(control));
1571 case Toolkit::Control::Property::STYLE_NAME:
1573 value = controlImpl.GetStyleName();
1577 case Toolkit::DevelControl::Property::STATE:
1579 value = controlImpl.mImpl->mState;
1583 case Toolkit::DevelControl::Property::SUB_STATE:
1585 value = controlImpl.mImpl->mSubStateName;
1589 case Toolkit::DevelControl::Property::LEFT_FOCUSABLE_ACTOR_ID:
1591 value = controlImpl.mImpl->mLeftFocusableActorId;
1595 case Toolkit::DevelControl::Property::RIGHT_FOCUSABLE_ACTOR_ID:
1597 value = controlImpl.mImpl->mRightFocusableActorId;
1601 case Toolkit::DevelControl::Property::UP_FOCUSABLE_ACTOR_ID:
1603 value = controlImpl.mImpl->mUpFocusableActorId;
1607 case Toolkit::DevelControl::Property::DOWN_FOCUSABLE_ACTOR_ID:
1609 value = controlImpl.mImpl->mDownFocusableActorId;
1613 case Toolkit::Control::Property::KEY_INPUT_FOCUS:
1615 value = controlImpl.HasKeyInputFocus();
1619 case Toolkit::Control::Property::BACKGROUND:
1622 Toolkit::Visual::Base visual = controlImpl.mImpl->GetVisual(Toolkit::Control::Property::BACKGROUND);
1625 visual.CreatePropertyMap(map);
1632 case Toolkit::Control::Property::MARGIN:
1634 value = controlImpl.mImpl->GetMargin();
1638 case Toolkit::Control::Property::PADDING:
1640 value = controlImpl.mImpl->GetPadding();
1644 case Toolkit::DevelControl::Property::TOOLTIP:
1647 if(controlImpl.mImpl->mTooltip)
1649 controlImpl.mImpl->mTooltip->CreatePropertyMap(map);
1655 case Toolkit::DevelControl::Property::SHADOW:
1658 Toolkit::Visual::Base visual = controlImpl.mImpl->GetVisual(Toolkit::DevelControl::Property::SHADOW);
1661 visual.CreatePropertyMap(map);
1668 case Toolkit::DevelControl::Property::ACCESSIBILITY_NAME:
1670 value = controlImpl.mImpl->mAccessibilityName;
1674 case Toolkit::DevelControl::Property::ACCESSIBILITY_DESCRIPTION:
1676 value = controlImpl.mImpl->mAccessibilityDescription;
1680 case Toolkit::DevelControl::Property::ACCESSIBILITY_TRANSLATION_DOMAIN:
1682 value = controlImpl.mImpl->mAccessibilityTranslationDomain;
1686 case Toolkit::DevelControl::Property::ACCESSIBILITY_ROLE:
1688 value = Property::Value(controlImpl.mImpl->mAccessibilityRole);
1692 case Toolkit::DevelControl::Property::ACCESSIBILITY_HIGHLIGHTABLE:
1694 value = controlImpl.mImpl->mAccessibilityHighlightable;
1698 case Toolkit::DevelControl::Property::ACCESSIBILITY_ATTRIBUTES:
1700 value = controlImpl.mImpl->mAccessibilityAttributes;
1704 case Toolkit::DevelControl::Property::DISPATCH_KEY_EVENTS:
1706 value = controlImpl.mImpl->mDispatchKeyEvents;
1710 case Toolkit::DevelControl::Property::ACCESSIBILITY_HIDDEN:
1712 value = controlImpl.mImpl->mAccessibilityHidden;
1716 case Toolkit::DevelControl::Property::CLOCKWISE_FOCUSABLE_ACTOR_ID:
1718 value = controlImpl.mImpl->mClockwiseFocusableActorId;
1722 case Toolkit::DevelControl::Property::COUNTER_CLOCKWISE_FOCUSABLE_ACTOR_ID:
1724 value = controlImpl.mImpl->mCounterClockwiseFocusableActorId;
1728 case Toolkit::DevelControl::Property::AUTOMATION_ID:
1730 value = controlImpl.mImpl->mAutomationId;
1739 void Control::Impl::RemoveAccessibilityAttribute(const std::string& key)
1741 Property::Value* value = mAccessibilityAttributes.Find(key);
1744 mAccessibilityAttributes[key] = Property::Value();
1748 void Control::Impl::ClearAccessibilityAttributes()
1750 mAccessibilityAttributes.Clear();
1753 void Control::Impl::SetAccessibilityReadingInfoType(const Dali::Accessibility::ReadingInfoTypes types)
1755 std::string value{};
1756 if(types[Dali::Accessibility::ReadingInfoType::NAME])
1758 value += READING_INFO_TYPE_NAME;
1760 if(types[Dali::Accessibility::ReadingInfoType::ROLE])
1764 value += READING_INFO_TYPE_SEPARATOR;
1766 value += READING_INFO_TYPE_ROLE;
1768 if(types[Dali::Accessibility::ReadingInfoType::DESCRIPTION])
1772 value += READING_INFO_TYPE_SEPARATOR;
1774 value += READING_INFO_TYPE_DESCRIPTION;
1776 if(types[Dali::Accessibility::ReadingInfoType::STATE])
1780 value += READING_INFO_TYPE_SEPARATOR;
1782 value += READING_INFO_TYPE_STATE;
1784 AppendAccessibilityAttribute(READING_INFO_TYPE_ATTRIBUTE_NAME, value);
1787 Dali::Accessibility::ReadingInfoTypes Control::Impl::GetAccessibilityReadingInfoType() const
1789 std::string value{};
1790 auto place = mAccessibilityAttributes.Find(READING_INFO_TYPE_ATTRIBUTE_NAME);
1797 Dali::Accessibility::ReadingInfoTypes types;
1798 types[Dali::Accessibility::ReadingInfoType::NAME] = true;
1799 types[Dali::Accessibility::ReadingInfoType::ROLE] = true;
1800 types[Dali::Accessibility::ReadingInfoType::DESCRIPTION] = true;
1801 types[Dali::Accessibility::ReadingInfoType::STATE] = true;
1810 Dali::Accessibility::ReadingInfoTypes types;
1812 if(value.find(READING_INFO_TYPE_NAME) != std::string::npos)
1814 types[Dali::Accessibility::ReadingInfoType::NAME] = true;
1816 if(value.find(READING_INFO_TYPE_ROLE) != std::string::npos)
1818 types[Dali::Accessibility::ReadingInfoType::ROLE] = true;
1820 if(value.find(READING_INFO_TYPE_DESCRIPTION) != std::string::npos)
1822 types[Dali::Accessibility::ReadingInfoType::DESCRIPTION] = true;
1824 if(value.find(READING_INFO_TYPE_STATE) != std::string::npos)
1826 types[Dali::Accessibility::ReadingInfoType::STATE] = true;
1832 void Control::Impl::CopyInstancedProperties(RegisteredVisualContainer& visuals, Dictionary<Property::Map>& instancedProperties)
1834 for(RegisteredVisualContainer::Iterator iter = visuals.Begin(); iter != visuals.End(); iter++)
1838 Property::Map instanceMap;
1839 Toolkit::GetImplementation((*iter)->visual).CreateInstancePropertyMap(instanceMap);
1840 instancedProperties.Add((*iter)->visual.GetName(), instanceMap);
1845 void Control::Impl::RemoveVisual(RegisteredVisualContainer& visuals, const std::string& visualName)
1847 Actor self(mControlImpl.Self());
1849 for(RegisteredVisualContainer::Iterator visualIter = visuals.Begin();
1850 visualIter != visuals.End();
1853 Toolkit::Visual::Base visual = (*visualIter)->visual;
1854 if(visual && visual.GetName() == visualName)
1856 Toolkit::GetImplementation(visual).SetOffScene(self);
1857 (*visualIter)->visual.Reset();
1858 visuals.Erase(visualIter);
1864 void Control::Impl::RemoveVisuals(RegisteredVisualContainer& visuals, DictionaryKeys& removeVisuals)
1866 Actor self(mControlImpl.Self());
1867 for(DictionaryKeys::iterator iter = removeVisuals.begin(); iter != removeVisuals.end(); ++iter)
1869 const std::string visualName = *iter;
1870 RemoveVisual(visuals, visualName);
1874 void Control::Impl::RecreateChangedVisuals(Dictionary<Property::Map>& stateVisualsToChange,
1875 Dictionary<Property::Map>& instancedProperties)
1877 Dali::CustomActor handle(mControlImpl.GetOwner());
1878 for(Dictionary<Property::Map>::iterator iter = stateVisualsToChange.Begin();
1879 iter != stateVisualsToChange.End();
1882 const std::string& visualName = (*iter).key;
1883 const Property::Map& toMap = (*iter).entry;
1885 Actor self = mControlImpl.Self();
1886 RegisteredVisualContainer::Iterator registeredVisualsiter;
1887 // Check if visual (visualName) is already registered, this is the current visual.
1888 if(FindVisual(visualName, mVisuals, registeredVisualsiter))
1890 Toolkit::Visual::Base& visual = (*registeredVisualsiter)->visual;
1893 // No longer required to know if the replaced visual's resources are ready
1894 StopObservingVisual(visual);
1896 // If control staged then visuals will be swapped once ready
1897 if(self.GetProperty<bool>(Actor::Property::CONNECTED_TO_SCENE))
1899 // Check if visual is currently in the process of being replaced ( is in removal container )
1900 RegisteredVisualContainer::Iterator visualQueuedForRemoval;
1901 if(FindVisual(visualName, mRemoveVisuals, visualQueuedForRemoval))
1903 // Visual with same visual name is already in removal container so current visual pending
1904 // Only the the last requested visual will be displayed so remove current visual which is staged but not ready.
1905 Toolkit::GetImplementation(visual).SetOffScene(self);
1906 (*registeredVisualsiter)->visual.Reset();
1907 mVisuals.Erase(registeredVisualsiter);
1911 // current visual not already in removal container so add now.
1912 DALI_LOG_INFO(gLogFilter, Debug::Verbose, "RegisterVisual Move current registered visual to removal Queue: %s \n", visualName.c_str());
1913 MoveVisual(registeredVisualsiter, mVisuals, mRemoveVisuals);
1918 // Control not staged or visual disabled so can just erase from registered visuals and new visual will be added later.
1919 (*registeredVisualsiter)->visual.Reset();
1920 mVisuals.Erase(registeredVisualsiter);
1924 const Property::Map* instancedMap = instancedProperties.FindConst(visualName);
1925 Style::ApplyVisual(handle, visualName, toMap, instancedMap);
1930 void Control::Impl::ReplaceStateVisualsAndProperties(const StylePtr oldState, const StylePtr newState, const std::string& subState)
1932 DALI_ASSERT_ALWAYS(Stage::IsCoreThread() && "Core is not installed. Might call this API from worker thread?");
1934 // Collect all old visual names
1935 DictionaryKeys stateVisualsToRemove;
1938 oldState->visuals.GetKeys(stateVisualsToRemove);
1939 if(!subState.empty())
1941 const StylePtr* oldSubState = oldState->subStates.FindConst(subState);
1944 DictionaryKeys subStateVisualsToRemove;
1945 (*oldSubState)->visuals.GetKeys(subStateVisualsToRemove);
1946 Merge(stateVisualsToRemove, subStateVisualsToRemove);
1951 // Collect all new visual properties
1952 Dictionary<Property::Map> stateVisualsToAdd;
1955 stateVisualsToAdd = newState->visuals;
1956 if(!subState.empty())
1958 const StylePtr* newSubState = newState->subStates.FindConst(subState);
1961 stateVisualsToAdd.Merge((*newSubState)->visuals);
1966 // If a name is in both add/remove, move it to change list.
1967 Dictionary<Property::Map> stateVisualsToChange;
1968 FindChangableVisuals(stateVisualsToAdd, stateVisualsToChange, stateVisualsToRemove);
1970 // Copy instanced properties (e.g. text label) of current visuals
1971 Dictionary<Property::Map> instancedProperties;
1972 CopyInstancedProperties(mVisuals, instancedProperties);
1974 // For each visual in remove list, remove from mVisuals
1975 RemoveVisuals(mVisuals, stateVisualsToRemove);
1977 // For each visual in add list, create and add to mVisuals
1978 Dali::CustomActor handle(mControlImpl.GetOwner());
1979 Style::ApplyVisuals(handle, stateVisualsToAdd, instancedProperties);
1981 // For each visual in change list, if it requires a new visual,
1982 // remove old visual, create and add to mVisuals
1983 RecreateChangedVisuals(stateVisualsToChange, instancedProperties);
1986 void Control::Impl::SetState(DevelControl::State newState, bool withTransitions)
1988 DevelControl::State oldState = mState;
1989 Dali::CustomActor handle(mControlImpl.GetOwner());
1990 DALI_LOG_INFO(gLogFilter, Debug::Concise, "Control::Impl::SetState: %s\n", (mState == DevelControl::NORMAL ? "NORMAL" : (mState == DevelControl::FOCUSED ? "FOCUSED" : (mState == DevelControl::DISABLED ? "DISABLED" : "NONE"))));
1992 if(mState != newState)
1994 // If mState was Disabled, and new state is Focused, should probably
1995 // store that fact, e.g. in another property that FocusManager can access.
1998 // Trigger state change and transitions
1999 // Apply new style, if stylemanager is available
2000 Toolkit::StyleManager styleManager = Toolkit::StyleManager::Get();
2003 const StylePtr stylePtr = GetImpl(styleManager).GetRecordedStyle(Toolkit::Control(mControlImpl.GetOwner()));
2007 std::string oldStateName = Scripting::GetEnumerationName<Toolkit::DevelControl::State>(oldState, ControlStateTable, ControlStateTableCount);
2008 std::string newStateName = Scripting::GetEnumerationName<Toolkit::DevelControl::State>(newState, ControlStateTable, ControlStateTableCount);
2010 const StylePtr* newStateStyle = stylePtr->subStates.Find(newStateName);
2011 const StylePtr* oldStateStyle = stylePtr->subStates.Find(oldStateName);
2012 if(oldStateStyle && newStateStyle)
2014 // Only change if both state styles exist
2015 ReplaceStateVisualsAndProperties(*oldStateStyle, *newStateStyle, mSubStateName);
2022 void Control::Impl::SetSubState(const std::string& subStateName, bool withTransitions)
2024 if(mSubStateName != subStateName)
2026 // Get existing sub-state visuals, and unregister them
2027 Dali::CustomActor handle(mControlImpl.GetOwner());
2029 Toolkit::StyleManager styleManager = Toolkit::StyleManager::Get();
2032 const StylePtr stylePtr = GetImpl(styleManager).GetRecordedStyle(Toolkit::Control(mControlImpl.GetOwner()));
2036 std::string stateName = Scripting::GetEnumerationName<Toolkit::DevelControl::State>(mState, ControlStateTable, ControlStateTableCount);
2038 const StylePtr* state = stylePtr->subStates.Find(stateName);
2041 StylePtr stateStyle(*state);
2043 const StylePtr* newStateStyle = stateStyle->subStates.Find(subStateName);
2044 const StylePtr* oldStateStyle = stateStyle->subStates.Find(mSubStateName);
2045 if(oldStateStyle && newStateStyle)
2048 ReplaceStateVisualsAndProperties(*oldStateStyle, *newStateStyle, empty);
2054 mSubStateName = subStateName;
2058 void Control::Impl::OnSceneDisconnection()
2060 Actor self = mControlImpl.Self();
2062 // Any visuals set for replacement but not yet ready should still be registered.
2063 // Reason: If a request was made to register a new visual but the control removed from scene before visual was ready
2064 // then when this control appears back on stage it should use that new visual.
2066 // Iterate through all registered visuals and set off scene
2067 SetVisualsOffScene(mVisuals, self);
2069 // Visuals pending replacement can now be taken out of the removal list and set off scene
2070 // Iterate through all replacement visuals and add to a move queue then set off scene
2072 if(!mRemoveVisuals.Empty())
2074 std::reverse(mRemoveVisuals.Begin(), mRemoveVisuals.End());
2076 while(!mRemoveVisuals.Empty())
2078 auto removalIter = mRemoveVisuals.End() - 1u;
2079 Toolkit::GetImplementation((*removalIter)->visual).SetOffScene(self);
2081 // Discard removed visual. It will be destroyed at next Idle time.
2082 DiscardVisual(removalIter, mRemoveVisuals);
2086 for(auto replacedIter = mVisuals.Begin(), end = mVisuals.End(); replacedIter != end; replacedIter++)
2088 (*replacedIter)->pending = false;
2092 void Control::Impl::SetMargin(Extents margin)
2094 mControlImpl.mImpl->mMargin = margin;
2096 // Trigger a size negotiation request that may be needed when setting a margin.
2097 mControlImpl.RelayoutRequest();
2100 Extents Control::Impl::GetMargin() const
2102 return mControlImpl.mImpl->mMargin;
2105 void Control::Impl::SetPadding(Extents padding)
2107 mControlImpl.mImpl->mPadding = padding;
2109 // Trigger a size negotiation request that may be needed when setting a padding.
2110 mControlImpl.RelayoutRequest();
2113 Extents Control::Impl::GetPadding() const
2115 return mControlImpl.mImpl->mPadding;
2118 void Control::Impl::SetInputMethodContext(InputMethodContext& inputMethodContext)
2120 mInputMethodContext = inputMethodContext;
2123 bool Control::Impl::FilterKeyEvent(const KeyEvent& event)
2125 bool consumed(false);
2127 if(mInputMethodContext)
2129 consumed = mInputMethodContext.FilterEventKey(event);
2134 DevelControl::VisualEventSignalType& Control::Impl::VisualEventSignal()
2136 return mVisualEventSignal;
2139 void Control::Impl::SetShadow(const Property::Map& map)
2141 Toolkit::Visual::Base visual = Toolkit::VisualFactory::Get().CreateVisual(map);
2142 visual.SetName("shadow");
2146 mControlImpl.mImpl->RegisterVisual(Toolkit::DevelControl::Property::SHADOW, visual, DepthIndex::BACKGROUND_EFFECT);
2148 mControlImpl.RelayoutRequest();
2152 void Control::Impl::ClearShadow()
2154 mControlImpl.mImpl->UnregisterVisual(Toolkit::DevelControl::Property::SHADOW);
2156 // Trigger a size negotiation request that may be needed when unregistering a visual.
2157 mControlImpl.RelayoutRequest();
2160 Dali::Property Control::Impl::GetVisualProperty(Dali::Property::Index index, Dali::Property::Key visualPropertyKey)
2162 Toolkit::Visual::Base visual = GetVisualByIndex(mVisuals, index);
2165 Internal::Visual::Base& visualImpl = Toolkit::GetImplementation(visual);
2166 return visualImpl.GetPropertyObject(std::move(visualPropertyKey));
2170 return Dali::Property(handle, Property::INVALID_INDEX);
2173 void Control::Impl::CreateTransitions(std::vector<std::pair<Dali::Property::Index, Dali::Property::Map>>& sourceProperties,
2174 std::vector<std::pair<Dali::Property::Index, Dali::Property::Map>>& destinationProperties,
2175 Dali::Toolkit::Control source,
2176 Dali::Toolkit::Control destination)
2178 // Retrieves background properties to be transitioned.
2179 Dali::Property::Map backgroundSourcePropertyMap, backgroundDestinationPropertyMap;
2180 mControlImpl.MakeVisualTransition(backgroundSourcePropertyMap, backgroundDestinationPropertyMap, source, destination, Toolkit::Control::Property::BACKGROUND);
2181 if(backgroundSourcePropertyMap.Count() > 0)
2183 sourceProperties.push_back(std::pair<Dali::Property::Index, Dali::Property::Map>(Toolkit::Control::Property::BACKGROUND, backgroundSourcePropertyMap));
2184 destinationProperties.push_back(std::pair<Dali::Property::Index, Dali::Property::Map>(Toolkit::Control::Property::BACKGROUND, backgroundDestinationPropertyMap));
2187 // Retrieves shadow properties to be transitioned.
2188 Dali::Property::Map shadowSourcePropertyMap, shadowDestinationPropertyMap;
2189 mControlImpl.MakeVisualTransition(shadowSourcePropertyMap, shadowDestinationPropertyMap, source, destination, Toolkit::DevelControl::Property::SHADOW);
2190 if(shadowSourcePropertyMap.Count() > 0)
2192 sourceProperties.push_back(std::pair<Dali::Property::Index, Dali::Property::Map>(Toolkit::DevelControl::Property::SHADOW, shadowSourcePropertyMap));
2193 destinationProperties.push_back(std::pair<Dali::Property::Index, Dali::Property::Map>(Toolkit::DevelControl::Property::SHADOW, shadowDestinationPropertyMap));
2196 // Retrieves transition from inherited class.
2197 mControlImpl.OnCreateTransitions(sourceProperties, destinationProperties, source, destination);
2200 void Control::Impl::UpdateVisualProperties(const std::vector<std::pair<Dali::Property::Index, Dali::Property::Map>>& properties)
2202 for(auto&& data : properties)
2204 if(data.first == Toolkit::Control::Property::BACKGROUND)
2206 DoAction(Toolkit::Control::Property::BACKGROUND, DevelVisual::Action::UPDATE_PROPERTY, data.second);
2208 else if(data.first == Toolkit::DevelControl::Property::SHADOW)
2210 DoAction(Toolkit::DevelControl::Property::SHADOW, DevelVisual::Action::UPDATE_PROPERTY, data.second);
2213 mControlImpl.OnUpdateVisualProperties(properties);
2216 void Control::Impl::EmitResourceReadySignal()
2218 if(!mIsEmittingResourceReadySignal)
2220 // Guard against calls to emit the signal during the callback
2221 mIsEmittingResourceReadySignal = true;
2223 // If the signal handler changes visual, it may become ready during this call & therefore this method will
2224 // get called again recursively. If so, mIdleCallbackRegistered is set below, and we act on it after that secondary
2225 // invocation has completed by notifying in an Idle callback to prevent further recursion.
2226 Dali::Toolkit::Control handle(mControlImpl.GetOwner());
2227 mResourceReadySignal.Emit(handle);
2229 mIsEmittingResourceReadySignal = false;
2233 if(!mIdleCallbackRegistered)
2235 mIdleCallbackRegistered = true;
2237 // Add idler to emit the signal again
2240 // The callback manager takes the ownership of the callback object.
2241 mIdleCallback = MakeCallback(this, &Control::Impl::OnIdleCallback);
2242 Adaptor::Get().AddIdle(mIdleCallback, true);
2248 bool Control::Impl::OnIdleCallback()
2251 mIdleCallbackRegistered = false;
2253 // A visual is ready so control may need relayouting if staged
2254 if(mControlImpl.Self().GetProperty<bool>(Actor::Property::CONNECTED_TO_SCENE))
2256 mControlImpl.RelayoutRequest();
2259 EmitResourceReadySignal();
2261 if(!mIdleCallbackRegistered)
2263 // Set the pointer to null as the callback manager deletes the callback after execute it.
2264 mIdleCallback = nullptr;
2267 // Repeat idle if mIdleCallbackRegistered become true one more time.
2268 return mIdleCallbackRegistered;
2271 Toolkit::DevelControl::ControlAccessible* Control::Impl::GetAccessibleObject()
2273 if(mAccessibleCreatable && !mAccessibleObject)
2275 mAccessibleObject.reset(mControlImpl.CreateAccessibleObject());
2278 return mAccessibleObject.get();
2281 bool Control::Impl::IsAccessibleCreated() const
2283 return !!mAccessibleObject;
2286 void Control::Impl::EnableCreateAccessible(bool enable)
2288 mAccessibleCreatable = enable;
2291 bool Control::Impl::IsCreateAccessibleEnabled() const
2293 return mAccessibleCreatable;
2296 } // namespace Internal
2298 } // namespace Toolkit