2 * Copyright (c) 2022 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)
148 void FindChangableVisuals(Dictionary<Property::Map>& stateVisualsToAdd,
149 Dictionary<Property::Map>& stateVisualsToChange,
150 DictionaryKeys& stateVisualsToRemove)
152 DictionaryKeys copyOfStateVisualsToRemove = stateVisualsToRemove;
154 for(DictionaryKeys::iterator iter = copyOfStateVisualsToRemove.begin();
155 iter != copyOfStateVisualsToRemove.end();
158 const std::string& visualName = (*iter);
159 Property::Map* toMap = stateVisualsToAdd.Find(visualName);
162 stateVisualsToChange.Add(visualName, *toMap);
163 stateVisualsToAdd.Remove(visualName);
164 Remove(stateVisualsToRemove, visualName);
169 Toolkit::Visual::Base GetVisualByName(
170 const RegisteredVisualContainer& visuals,
171 const std::string& visualName)
173 Toolkit::Visual::Base visualHandle;
175 RegisteredVisualContainer::Iterator iter;
176 for(iter = visuals.Begin(); iter != visuals.End(); iter++)
178 Toolkit::Visual::Base visual = (*iter)->visual;
179 if(visual && visual.GetName() == visualName)
181 visualHandle = visual;
188 Toolkit::Visual::Base GetVisualByIndex(
189 const RegisteredVisualContainer& visuals,
190 Property::Index index)
192 Toolkit::Visual::Base visualHandle;
194 RegisteredVisualContainer::Iterator iter;
195 for(iter = visuals.Begin(); iter != visuals.End(); iter++)
197 if((*iter)->index == index)
199 visualHandle = (*iter)->visual;
207 * Move visual from source to destination container
209 void MoveVisual(RegisteredVisualContainer::Iterator sourceIter, RegisteredVisualContainer& source, RegisteredVisualContainer& destination)
211 Toolkit::Visual::Base visual = (*sourceIter)->visual;
214 RegisteredVisual* rv = source.Release(sourceIter);
215 destination.PushBack(rv);
220 * Performs actions as requested using the action name.
221 * @param[in] object The object on which to perform the action.
222 * @param[in] actionName The action to perform.
223 * @param[in] attributes The attributes with which to perfrom this action.
224 * @return true if action has been accepted by this control
226 const char* ACTION_ACCESSIBILITY_ACTIVATED = "accessibilityActivated";
227 const char* ACTION_ACCESSIBILITY_READING_CANCELLED = "ReadingCancelled";
228 const char* ACTION_ACCESSIBILITY_READING_PAUSED = "ReadingPaused";
229 const char* ACTION_ACCESSIBILITY_READING_RESUMED = "ReadingResumed";
230 const char* ACTION_ACCESSIBILITY_READING_SKIPPED = "ReadingSkipped";
231 const char* ACTION_ACCESSIBILITY_READING_STOPPED = "ReadingStopped";
233 static bool DoAction(BaseObject* object, const std::string& actionName, const Property::Map& attributes)
237 Dali::BaseHandle handle(object);
239 Toolkit::Control control = Toolkit::Control::DownCast(handle);
241 DALI_ASSERT_ALWAYS(control);
243 if(0 == strcmp(actionName.c_str(), ACTION_ACCESSIBILITY_ACTIVATED) || actionName == "activate")
245 // if cast succeeds there is an implementation so no need to check
246 if(!DevelControl::AccessibilityActivateSignal(control).Empty())
248 DevelControl::AccessibilityActivateSignal(control).Emit();
252 ret = Internal::GetImplementation(control).OnAccessibilityActivated();
255 else if(0 == strcmp(actionName.c_str(), ACTION_ACCESSIBILITY_READING_SKIPPED))
257 // if cast succeeds there is an implementation so no need to check
258 if(!DevelControl::AccessibilityReadingSkippedSignal(control).Empty())
260 DevelControl::AccessibilityReadingSkippedSignal(control).Emit();
263 else if(0 == strcmp(actionName.c_str(), ACTION_ACCESSIBILITY_READING_PAUSED))
265 // if cast succeeds there is an implementation so no need to check
266 if(!DevelControl::AccessibilityReadingPausedSignal(control).Empty())
268 DevelControl::AccessibilityReadingPausedSignal(control).Emit();
271 else if(0 == strcmp(actionName.c_str(), ACTION_ACCESSIBILITY_READING_RESUMED))
273 // if cast succeeds there is an implementation so no need to check
274 if(!DevelControl::AccessibilityReadingResumedSignal(control).Empty())
276 DevelControl::AccessibilityReadingResumedSignal(control).Emit();
279 else if(0 == strcmp(actionName.c_str(), ACTION_ACCESSIBILITY_READING_CANCELLED))
281 // if cast succeeds there is an implementation so no need to check
282 if(!DevelControl::AccessibilityReadingCancelledSignal(control).Empty())
284 DevelControl::AccessibilityReadingCancelledSignal(control).Emit();
287 else if(0 == strcmp(actionName.c_str(), ACTION_ACCESSIBILITY_READING_STOPPED))
289 // if cast succeeds there is an implementation so no need to check
290 if(!DevelControl::AccessibilityReadingStoppedSignal(control).Empty())
292 DevelControl::AccessibilityReadingStoppedSignal(control).Emit();
303 * Connects a callback function with the object's signals.
304 * @param[in] object The object providing the signal.
305 * @param[in] tracker Used to disconnect the signal.
306 * @param[in] signalName The signal to connect to.
307 * @param[in] functor A newly allocated FunctorDelegate.
308 * @return True if the signal was connected.
309 * @post If a signal was connected, ownership of functor was passed to CallbackBase. Otherwise the caller is responsible for deleting the unused functor.
311 const char* SIGNAL_KEY_EVENT = "keyEvent";
312 const char* SIGNAL_KEY_INPUT_FOCUS_GAINED = "keyInputFocusGained";
313 const char* SIGNAL_KEY_INPUT_FOCUS_LOST = "keyInputFocusLost";
314 const char* SIGNAL_TAPPED = "tapped";
315 const char* SIGNAL_PANNED = "panned";
316 const char* SIGNAL_PINCHED = "pinched";
317 const char* SIGNAL_LONG_PRESSED = "longPressed";
318 const char* SIGNAL_GET_NAME = "getName";
319 const char* SIGNAL_GET_DESCRIPTION = "getDescription";
320 const char* SIGNAL_DO_GESTURE = "doGesture";
321 static bool DoConnectSignal(BaseObject* object, ConnectionTrackerInterface* tracker, const std::string& signalName, FunctorDelegate* functor)
323 Dali::BaseHandle handle(object);
325 bool connected(false);
326 Toolkit::Control control = Toolkit::Control::DownCast(handle);
329 Internal::Control& controlImpl(Internal::GetImplementation(control));
332 if(0 == strcmp(signalName.c_str(), SIGNAL_KEY_EVENT))
334 controlImpl.KeyEventSignal().Connect(tracker, functor);
336 else if(0 == strcmp(signalName.c_str(), SIGNAL_KEY_INPUT_FOCUS_GAINED))
338 controlImpl.KeyInputFocusGainedSignal().Connect(tracker, functor);
340 else if(0 == strcmp(signalName.c_str(), SIGNAL_KEY_INPUT_FOCUS_LOST))
342 controlImpl.KeyInputFocusLostSignal().Connect(tracker, functor);
344 else if(0 == strcmp(signalName.c_str(), SIGNAL_TAPPED))
346 controlImpl.EnableGestureDetection(GestureType::TAP);
347 controlImpl.GetTapGestureDetector().DetectedSignal().Connect(tracker, functor);
349 else if(0 == strcmp(signalName.c_str(), SIGNAL_PANNED))
351 controlImpl.EnableGestureDetection(GestureType::PAN);
352 controlImpl.GetPanGestureDetector().DetectedSignal().Connect(tracker, functor);
354 else if(0 == strcmp(signalName.c_str(), SIGNAL_PINCHED))
356 controlImpl.EnableGestureDetection(GestureType::PINCH);
357 controlImpl.GetPinchGestureDetector().DetectedSignal().Connect(tracker, functor);
359 else if(0 == strcmp(signalName.c_str(), SIGNAL_LONG_PRESSED))
361 controlImpl.EnableGestureDetection(GestureType::LONG_PRESS);
362 controlImpl.GetLongPressGestureDetector().DetectedSignal().Connect(tracker, functor);
364 else if(0 == strcmp(signalName.c_str(), SIGNAL_GET_NAME))
366 DevelControl::AccessibilityGetNameSignal(control).Connect(tracker, functor);
368 else if(0 == strcmp(signalName.c_str(), SIGNAL_GET_DESCRIPTION))
370 DevelControl::AccessibilityGetDescriptionSignal(control).Connect(tracker, functor);
372 else if(0 == strcmp(signalName.c_str(), SIGNAL_DO_GESTURE))
374 DevelControl::AccessibilityDoGestureSignal(control).Connect(tracker, functor);
381 * Creates control through type registry
385 return Internal::Control::New();
387 // Setup signals and actions using the type-registry.
388 DALI_TYPE_REGISTRATION_BEGIN(Control, CustomActor, Create);
390 // Note: Properties are registered separately below.
392 SignalConnectorType registerSignal1(typeRegistration, SIGNAL_KEY_EVENT, &DoConnectSignal);
393 SignalConnectorType registerSignal2(typeRegistration, SIGNAL_KEY_INPUT_FOCUS_GAINED, &DoConnectSignal);
394 SignalConnectorType registerSignal3(typeRegistration, SIGNAL_KEY_INPUT_FOCUS_LOST, &DoConnectSignal);
395 SignalConnectorType registerSignal4(typeRegistration, SIGNAL_TAPPED, &DoConnectSignal);
396 SignalConnectorType registerSignal5(typeRegistration, SIGNAL_PANNED, &DoConnectSignal);
397 SignalConnectorType registerSignal6(typeRegistration, SIGNAL_PINCHED, &DoConnectSignal);
398 SignalConnectorType registerSignal7(typeRegistration, SIGNAL_LONG_PRESSED, &DoConnectSignal);
399 SignalConnectorType registerSignal8(typeRegistration, SIGNAL_GET_NAME, &DoConnectSignal);
400 SignalConnectorType registerSignal9(typeRegistration, SIGNAL_GET_DESCRIPTION, &DoConnectSignal);
401 SignalConnectorType registerSignal10(typeRegistration, SIGNAL_DO_GESTURE, &DoConnectSignal);
403 TypeAction registerAction1(typeRegistration, "activate", &DoAction);
404 TypeAction registerAction2(typeRegistration, ACTION_ACCESSIBILITY_ACTIVATED, &DoAction);
405 TypeAction registerAction3(typeRegistration, ACTION_ACCESSIBILITY_READING_SKIPPED, &DoAction);
406 TypeAction registerAction4(typeRegistration, ACTION_ACCESSIBILITY_READING_CANCELLED, &DoAction);
407 TypeAction registerAction5(typeRegistration, ACTION_ACCESSIBILITY_READING_STOPPED, &DoAction);
408 TypeAction registerAction6(typeRegistration, ACTION_ACCESSIBILITY_READING_PAUSED, &DoAction);
409 TypeAction registerAction7(typeRegistration, ACTION_ACCESSIBILITY_READING_RESUMED, &DoAction);
411 DALI_TYPE_REGISTRATION_END()
414 * @brief Iterate through given container and setOffScene any visual found
416 * @param[in] container Container of visuals
417 * @param[in] parent Parent actor to remove visuals from
419 void SetVisualsOffScene(const RegisteredVisualContainer& container, Actor parent)
421 for(auto iter = container.Begin(), end = container.End(); iter != end; iter++)
425 DALI_LOG_INFO(gLogFilter, Debug::Verbose, "Control::SetOffScene Setting visual(%d) off stage\n", (*iter)->index);
426 Toolkit::GetImplementation((*iter)->visual).SetOffScene(parent);
431 Dali::Rect<> GetShowingGeometry(Dali::Rect<> rect, Dali::Toolkit::DevelControl::ControlAccessible* accessible)
434 Vector2 currentPosition;
435 auto parent = dynamic_cast<Toolkit::DevelControl::ControlAccessible*>(accessible->GetParent());
439 parentRect = parent->GetExtents(Dali::Accessibility::CoordinateType::WINDOW);
441 currentPosition.x = rect.x;
442 currentPosition.y = rect.y;
444 rect.x = rect.x > parentRect.x ? rect.x : parentRect.x;
445 rect.y = rect.y > parentRect.y ? rect.y : parentRect.y;
446 rect.width = currentPosition.x + rect.width < parentRect.x + parentRect.width ? currentPosition.x + rect.width - rect.x : parentRect.x + parentRect.width - rect.x;
447 rect.height = currentPosition.y + rect.height < parentRect.y + parentRect.height ? currentPosition.y + rect.height - rect.y : parentRect.y + parentRect.height - rect.y;
449 if(rect.width < 0 || rect.height < 0)
454 parent = dynamic_cast<Toolkit::DevelControl::ControlAccessible*>(parent->GetParent());
460 static bool IsShowingGeometryOnScreen(Dali::Rect<> rect)
462 return rect.width > 0 && rect.height > 0;
465 Dali::Accessibility::Accessible* ExternalAccessibleGetter(Dali::Actor actor)
467 auto control = Toolkit::Control::DownCast(actor);
473 auto& controlImpl = Toolkit::Internal::GetImplementation(control);
475 return controlImpl.GetAccessibleObject();
478 } // unnamed namespace
481 // Properties registered without macro to use specific member variables.
482 const PropertyRegistration Control::Impl::PROPERTY_1(typeRegistration, "styleName", Toolkit::Control::Property::STYLE_NAME, Property::STRING, &Control::Impl::SetProperty, &Control::Impl::GetProperty);
483 const PropertyRegistration Control::Impl::PROPERTY_4(typeRegistration, "keyInputFocus", Toolkit::Control::Property::KEY_INPUT_FOCUS, Property::BOOLEAN, &Control::Impl::SetProperty, &Control::Impl::GetProperty);
484 const PropertyRegistration Control::Impl::PROPERTY_5(typeRegistration, "background", Toolkit::Control::Property::BACKGROUND, Property::MAP, &Control::Impl::SetProperty, &Control::Impl::GetProperty);
485 const PropertyRegistration Control::Impl::PROPERTY_6(typeRegistration, "margin", Toolkit::Control::Property::MARGIN, Property::EXTENTS, &Control::Impl::SetProperty, &Control::Impl::GetProperty);
486 const PropertyRegistration Control::Impl::PROPERTY_7(typeRegistration, "padding", Toolkit::Control::Property::PADDING, Property::EXTENTS, &Control::Impl::SetProperty, &Control::Impl::GetProperty);
487 const PropertyRegistration Control::Impl::PROPERTY_8(typeRegistration, "tooltip", Toolkit::DevelControl::Property::TOOLTIP, Property::MAP, &Control::Impl::SetProperty, &Control::Impl::GetProperty);
488 const PropertyRegistration Control::Impl::PROPERTY_9(typeRegistration, "state", Toolkit::DevelControl::Property::STATE, Property::STRING, &Control::Impl::SetProperty, &Control::Impl::GetProperty);
489 const PropertyRegistration Control::Impl::PROPERTY_10(typeRegistration, "subState", Toolkit::DevelControl::Property::SUB_STATE, Property::STRING, &Control::Impl::SetProperty, &Control::Impl::GetProperty);
490 const PropertyRegistration Control::Impl::PROPERTY_11(typeRegistration, "leftFocusableActorId", Toolkit::DevelControl::Property::LEFT_FOCUSABLE_ACTOR_ID, Property::INTEGER, &Control::Impl::SetProperty, &Control::Impl::GetProperty);
491 const PropertyRegistration Control::Impl::PROPERTY_12(typeRegistration, "rightFocusableActorId", Toolkit::DevelControl::Property::RIGHT_FOCUSABLE_ACTOR_ID, Property::INTEGER, &Control::Impl::SetProperty, &Control::Impl::GetProperty);
492 const PropertyRegistration Control::Impl::PROPERTY_13(typeRegistration, "upFocusableActorId", Toolkit::DevelControl::Property::UP_FOCUSABLE_ACTOR_ID, Property::INTEGER, &Control::Impl::SetProperty, &Control::Impl::GetProperty);
493 const PropertyRegistration Control::Impl::PROPERTY_14(typeRegistration, "downFocusableActorId", Toolkit::DevelControl::Property::DOWN_FOCUSABLE_ACTOR_ID, Property::INTEGER, &Control::Impl::SetProperty, &Control::Impl::GetProperty);
494 const PropertyRegistration Control::Impl::PROPERTY_15(typeRegistration, "shadow", Toolkit::DevelControl::Property::SHADOW, Property::MAP, &Control::Impl::SetProperty, &Control::Impl::GetProperty);
495 const PropertyRegistration Control::Impl::PROPERTY_16(typeRegistration, "accessibilityName", Toolkit::DevelControl::Property::ACCESSIBILITY_NAME, Property::STRING, &Control::Impl::SetProperty, &Control::Impl::GetProperty);
496 const PropertyRegistration Control::Impl::PROPERTY_17(typeRegistration, "accessibilityDescription", Toolkit::DevelControl::Property::ACCESSIBILITY_DESCRIPTION, Property::STRING, &Control::Impl::SetProperty, &Control::Impl::GetProperty);
497 const PropertyRegistration Control::Impl::PROPERTY_18(typeRegistration, "accessibilityTranslationDomain", Toolkit::DevelControl::Property::ACCESSIBILITY_TRANSLATION_DOMAIN, Property::STRING, &Control::Impl::SetProperty, &Control::Impl::GetProperty);
498 const PropertyRegistration Control::Impl::PROPERTY_19(typeRegistration, "accessibilityRole", Toolkit::DevelControl::Property::ACCESSIBILITY_ROLE, Property::INTEGER, &Control::Impl::SetProperty, &Control::Impl::GetProperty);
499 const PropertyRegistration Control::Impl::PROPERTY_20(typeRegistration, "accessibilityHighlightable", Toolkit::DevelControl::Property::ACCESSIBILITY_HIGHLIGHTABLE, Property::BOOLEAN, &Control::Impl::SetProperty, &Control::Impl::GetProperty);
500 const PropertyRegistration Control::Impl::PROPERTY_21(typeRegistration, "accessibilityAttributes", Toolkit::DevelControl::Property::ACCESSIBILITY_ATTRIBUTES, Property::MAP, &Control::Impl::SetProperty, &Control::Impl::GetProperty);
501 const PropertyRegistration Control::Impl::PROPERTY_22(typeRegistration, "dispatchKeyEvents", Toolkit::DevelControl::Property::DISPATCH_KEY_EVENTS, Property::BOOLEAN, &Control::Impl::SetProperty, &Control::Impl::GetProperty);
502 const PropertyRegistration Control::Impl::PROPERTY_23(typeRegistration, "accessibilityHidden", Toolkit::DevelControl::Property::ACCESSIBILITY_HIDDEN, Property::BOOLEAN, &Control::Impl::SetProperty, &Control::Impl::GetProperty);
503 const PropertyRegistration Control::Impl::PROPERTY_24(typeRegistration, "clockwiseFocusableActorId", Toolkit::DevelControl::Property::CLOCKWISE_FOCUSABLE_ACTOR_ID, Property::INTEGER, &Control::Impl::SetProperty, &Control::Impl::GetProperty);
504 const PropertyRegistration Control::Impl::PROPERTY_25(typeRegistration, "counterClockwiseFocusableActorId", Toolkit::DevelControl::Property::COUNTER_CLOCKWISE_FOCUSABLE_ACTOR_ID, Property::INTEGER, &Control::Impl::SetProperty, &Control::Impl::GetProperty);
505 const PropertyRegistration Control::Impl::PROPERTY_26(typeRegistration, "automationId", Toolkit::DevelControl::Property::AUTOMATION_ID, Property::STRING, &Control::Impl::SetProperty, &Control::Impl::GetProperty);
509 Control::Impl::Impl(Control& controlImpl)
510 : mControlImpl(controlImpl),
511 mState(Toolkit::DevelControl::NORMAL),
513 mLeftFocusableActorId(-1),
514 mRightFocusableActorId(-1),
515 mUpFocusableActorId(-1),
516 mDownFocusableActorId(-1),
517 mClockwiseFocusableActorId(-1),
518 mCounterClockwiseFocusableActorId(-1),
520 mBackgroundColor(Color::TRANSPARENT),
521 mStartingPinchScale(nullptr),
523 mPadding(0, 0, 0, 0),
525 mKeyInputFocusGainedSignal(),
526 mKeyInputFocusLostSignal(),
527 mResourceReadySignal(),
528 mVisualEventSignal(),
529 mAccessibilityGetNameSignal(),
530 mAccessibilityGetDescriptionSignal(),
531 mAccessibilityDoGestureSignal(),
532 mPinchGestureDetector(),
533 mPanGestureDetector(),
534 mTapGestureDetector(),
535 mLongPressGestureDetector(),
537 mInputMethodContext(),
538 mIdleCallback(nullptr),
539 mFlags(Control::ControlBehaviour(CONTROL_BEHAVIOUR_DEFAULT)),
540 mIsKeyboardNavigationSupported(false),
541 mIsKeyboardFocusGroup(false),
542 mIsEmittingResourceReadySignal(false),
543 mNeedToEmitResourceReady(false),
544 mDispatchKeyEvents(true)
546 Dali::Accessibility::Accessible::RegisterExternalAccessibleGetter(&ExternalAccessibleGetter);
549 Control::Impl::~Impl()
551 for(auto&& iter : mVisuals)
553 StopObservingVisual(iter->visual);
556 for(auto&& iter : mRemoveVisuals)
558 StopObservingVisual(iter->visual);
561 // All gesture detectors will be destroyed so no need to disconnect.
562 delete mStartingPinchScale;
564 if(mIdleCallback && Adaptor::IsAvailable())
566 // Removes the callback from the callback manager in case the control is destroyed before the callback is executed.
567 Adaptor::Get().RemoveIdle(mIdleCallback);
571 Control::Impl& Control::Impl::Get(Internal::Control& internalControl)
573 return *internalControl.mImpl;
576 const Control::Impl& Control::Impl::Get(const Internal::Control& internalControl)
578 return *internalControl.mImpl;
581 void Control::Impl::CheckHighlightedObjectGeometry()
583 auto accessible = GetAccessibleObject();
584 auto lastPosition = accessible->GetLastPosition();
585 auto accessibleRect = accessible->GetExtents(Dali::Accessibility::CoordinateType::WINDOW);
586 auto rect = GetShowingGeometry(accessibleRect, accessible);
588 switch(mAccessibilityLastScreenRelativeMoveType)
590 case Dali::Accessibility::ScreenRelativeMoveType::OUTSIDE:
592 if(IsShowingGeometryOnScreen(rect))
594 mAccessibilityLastScreenRelativeMoveType = Dali::Accessibility::ScreenRelativeMoveType::INSIDE;
598 case Dali::Accessibility::ScreenRelativeMoveType::INSIDE:
600 if(rect.width < 0 && !Dali::Equals(accessibleRect.x, lastPosition.x))
602 mAccessibilityLastScreenRelativeMoveType = (accessibleRect.x < lastPosition.x) ? Dali::Accessibility::ScreenRelativeMoveType::OUTGOING_TOP_LEFT : Dali::Accessibility::ScreenRelativeMoveType::OUTGOING_BOTTOM_RIGHT;
604 if(rect.height < 0 && !Dali::Equals(accessibleRect.y, lastPosition.y))
606 mAccessibilityLastScreenRelativeMoveType = (accessibleRect.y < lastPosition.y) ? Dali::Accessibility::ScreenRelativeMoveType::OUTGOING_TOP_LEFT : Dali::Accessibility::ScreenRelativeMoveType::OUTGOING_BOTTOM_RIGHT;
608 // notify AT-clients on outgoing moves only
609 if(mAccessibilityLastScreenRelativeMoveType != Dali::Accessibility::ScreenRelativeMoveType::INSIDE)
611 accessible->EmitMovedOutOfScreen(mAccessibilityLastScreenRelativeMoveType);
615 case Dali::Accessibility::ScreenRelativeMoveType::OUTGOING_TOP_LEFT:
616 case Dali::Accessibility::ScreenRelativeMoveType::OUTGOING_BOTTOM_RIGHT:
618 if(IsShowingGeometryOnScreen(rect))
620 mAccessibilityLastScreenRelativeMoveType = Dali::Accessibility::ScreenRelativeMoveType::INSIDE;
624 mAccessibilityLastScreenRelativeMoveType = Dali::Accessibility::ScreenRelativeMoveType::OUTSIDE;
634 accessible->SetLastPosition(Vector2(accessibleRect.x, accessibleRect.y));
637 void Control::Impl::RegisterAccessibilityPositionPropertyNotification()
639 if(mIsAccessibilityPositionPropertyNotificationSet)
643 // set default value until first move of object is detected
644 mAccessibilityLastScreenRelativeMoveType = Dali::Accessibility::ScreenRelativeMoveType::OUTSIDE;
645 // recalculate mAccessibilityLastScreenRelativeMoveType accordingly to the initial position
646 CheckHighlightedObjectGeometry();
647 mAccessibilityPositionNotification = mControlImpl.Self().AddPropertyNotification(Actor::Property::WORLD_POSITION, StepCondition(1.0f, 1.0f));
648 mAccessibilityPositionNotification.SetNotifyMode(PropertyNotification::NOTIFY_ON_CHANGED);
649 mAccessibilityPositionNotification.NotifySignal().Connect(this, [this](PropertyNotification&) { CheckHighlightedObjectGeometry(); });
650 mIsAccessibilityPositionPropertyNotificationSet = true;
653 void Control::Impl::UnregisterAccessibilityPositionPropertyNotification()
655 mControlImpl.Self().RemovePropertyNotification(mAccessibilityPositionNotification);
656 mIsAccessibilityPositionPropertyNotificationSet = false;
659 // Gesture Detection Methods
660 void Control::Impl::PinchDetected(Actor actor, const PinchGesture& pinch)
662 mControlImpl.OnPinch(pinch);
665 void Control::Impl::PanDetected(Actor actor, const PanGesture& pan)
667 mControlImpl.OnPan(pan);
670 void Control::Impl::TapDetected(Actor actor, const TapGesture& tap)
672 mControlImpl.OnTap(tap);
675 void Control::Impl::LongPressDetected(Actor actor, const LongPressGesture& longPress)
677 mControlImpl.OnLongPress(longPress);
680 void Control::Impl::RegisterVisual(Property::Index index, Toolkit::Visual::Base& visual)
682 RegisterVisual(index, visual, VisualState::ENABLED, DepthIndexValue::NOT_SET);
685 void Control::Impl::RegisterVisual(Property::Index index, Toolkit::Visual::Base& visual, int depthIndex)
687 RegisterVisual(index, visual, VisualState::ENABLED, DepthIndexValue::SET, depthIndex);
690 void Control::Impl::RegisterVisual(Property::Index index, Toolkit::Visual::Base& visual, bool enabled)
692 RegisterVisual(index, visual, (enabled ? VisualState::ENABLED : VisualState::DISABLED), DepthIndexValue::NOT_SET);
695 void Control::Impl::RegisterVisual(Property::Index index, Toolkit::Visual::Base& visual, bool enabled, int depthIndex)
697 RegisterVisual(index, visual, (enabled ? VisualState::ENABLED : VisualState::DISABLED), DepthIndexValue::SET, depthIndex);
700 void Control::Impl::RegisterVisual(Property::Index index, Toolkit::Visual::Base& visual, VisualState::Type enabled, DepthIndexValue::Type depthIndexValueSet, int depthIndex)
702 DALI_LOG_INFO(gLogFilter, Debug::Concise, "RegisterVisual:%d \n", index);
704 bool visualReplaced(false);
705 Actor self = mControlImpl.Self();
707 // Set the depth index, if not set by caller this will be either the current visual depth, max depth of all visuals
709 int requiredDepthIndex = visual.GetDepthIndex();
711 if(depthIndexValueSet == DepthIndexValue::SET)
713 requiredDepthIndex = depthIndex;
716 // Visual replacement, existing visual should only be removed from stage when replacement ready.
717 if(!mVisuals.Empty())
719 RegisteredVisualContainer::Iterator registeredVisualsiter;
720 // Check if visual (index) is already registered, this is the current visual.
721 if(FindVisual(index, mVisuals, registeredVisualsiter))
723 Toolkit::Visual::Base& currentRegisteredVisual = (*registeredVisualsiter)->visual;
724 if(currentRegisteredVisual)
726 // Store current visual depth index as may need to set the replacement visual to same depth
727 const int currentDepthIndex = (*registeredVisualsiter)->visual.GetDepthIndex();
729 // No longer required to know if the replaced visual's resources are ready
730 StopObservingVisual(currentRegisteredVisual);
732 // If control staged and visual enabled then visuals will be swapped once ready
733 if(self.GetProperty<bool>(Actor::Property::CONNECTED_TO_SCENE) && enabled)
735 // Check if visual is currently in the process of being replaced ( is in removal container )
736 RegisteredVisualContainer::Iterator visualQueuedForRemoval;
737 if(FindVisual(index, mRemoveVisuals, visualQueuedForRemoval))
739 // Visual with same index is already in removal container so current visual pending
740 // Only the the last requested visual will be displayed so remove current visual which is staged but not ready.
741 Toolkit::GetImplementation(currentRegisteredVisual).SetOffScene(self);
742 mVisuals.Erase(registeredVisualsiter);
746 // current visual not already in removal container so add now.
747 DALI_LOG_INFO(gLogFilter, Debug::Verbose, "RegisterVisual Move current registered visual to removal Queue: %d \n", index);
748 MoveVisual(registeredVisualsiter, mVisuals, mRemoveVisuals);
753 // Control not staged or visual disabled so can just erase from registered visuals and new visual will be added later.
754 mVisuals.Erase(registeredVisualsiter);
757 // 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
758 if((depthIndexValueSet == DepthIndexValue::NOT_SET) &&
759 (visual.GetDepthIndex() == 0))
761 requiredDepthIndex = currentDepthIndex;
765 visualReplaced = true;
769 // If not set, set the name of the visual to the same name as the control's property.
770 // ( If the control has been type registered )
771 if(visual.GetName().empty())
773 // returns empty string if index is not found as long as index is not -1
774 std::string visualName = self.GetPropertyName(index);
775 if(!visualName.empty())
777 DALI_LOG_INFO(gLogFilter, Debug::Concise, "Setting visual name for property %d to %s\n", index, visualName.c_str());
778 visual.SetName(visualName);
782 if(!visualReplaced) // New registration entry
784 // 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
785 if((depthIndexValueSet == DepthIndexValue::NOT_SET) &&
786 (mVisuals.Size() > 0) &&
787 (visual.GetDepthIndex() == 0))
789 int maxDepthIndex = std::numeric_limits<int>::min();
791 RegisteredVisualContainer::ConstIterator iter;
792 const RegisteredVisualContainer::ConstIterator endIter = mVisuals.End();
793 for(iter = mVisuals.Begin(); iter != endIter; iter++)
795 const int visualDepthIndex = (*iter)->visual.GetDepthIndex();
796 if(visualDepthIndex > maxDepthIndex)
798 maxDepthIndex = visualDepthIndex;
801 ++maxDepthIndex; // Add one to the current maximum depth index so that our added visual appears on top
802 requiredDepthIndex = std::max(0, maxDepthIndex); // Start at zero if maxDepth index belongs to a background
808 // Set determined depth index
809 visual.SetDepthIndex(requiredDepthIndex);
811 // Monitor when the visual resources are ready
812 StartObservingVisual(visual);
814 DALI_LOG_INFO(gLogFilter, Debug::Concise, "New Visual registration index[%d] depth[%d]\n", index, requiredDepthIndex);
815 RegisteredVisual* newRegisteredVisual = new RegisteredVisual(index, visual, (enabled == VisualState::ENABLED ? true : false), (visualReplaced && enabled));
816 mVisuals.PushBack(newRegisteredVisual);
818 Internal::Visual::Base& visualImpl = Toolkit::GetImplementation(visual);
819 // Put on stage if enabled and the control is already on the stage
820 if((enabled == VisualState::ENABLED) && self.GetProperty<bool>(Actor::Property::CONNECTED_TO_SCENE))
822 visualImpl.SetOnScene(self);
824 else if(visualImpl.IsResourceReady()) // When not being staged, check if visual already 'ResourceReady' before it was Registered. ( Resource may have been loaded already )
826 ResourceReady(visualImpl);
830 DALI_LOG_INFO(gLogFilter, Debug::Verbose, "Control::RegisterVisual() Registered %s(%d), enabled:%s\n", visual.GetName().c_str(), index, enabled ? "true" : "false");
833 void Control::Impl::UnregisterVisual(Property::Index index)
835 RegisteredVisualContainer::Iterator iter;
836 if(FindVisual(index, mVisuals, iter))
838 // stop observing visual
839 StopObservingVisual((*iter)->visual);
841 Actor self(mControlImpl.Self());
842 Toolkit::GetImplementation((*iter)->visual).SetOffScene(self);
843 (*iter)->visual.Reset();
844 mVisuals.Erase(iter);
847 if(FindVisual(index, mRemoveVisuals, iter))
849 Actor self(mControlImpl.Self());
850 Toolkit::GetImplementation((*iter)->visual).SetOffScene(self);
851 (*iter)->pending = false;
852 (*iter)->visual.Reset();
853 mRemoveVisuals.Erase(iter);
857 Toolkit::Visual::Base Control::Impl::GetVisual(Property::Index index) const
859 RegisteredVisualContainer::Iterator iter;
860 if(FindVisual(index, mVisuals, iter))
862 return (*iter)->visual;
865 return Toolkit::Visual::Base();
868 void Control::Impl::EnableVisual(Property::Index index, bool enable)
870 DALI_LOG_INFO(gLogFilter, Debug::General, "Control::EnableVisual(%d, %s)\n", index, enable ? "T" : "F");
872 RegisteredVisualContainer::Iterator iter;
873 if(FindVisual(index, mVisuals, iter))
875 if((*iter)->enabled == enable)
877 DALI_LOG_INFO(gLogFilter, Debug::Verbose, "Control::EnableVisual Visual %s(%d) already %s\n", (*iter)->visual.GetName().c_str(), index, enable ? "enabled" : "disabled");
881 (*iter)->enabled = enable;
882 Actor parentActor = mControlImpl.Self();
883 if(mControlImpl.Self().GetProperty<bool>(Actor::Property::CONNECTED_TO_SCENE)) // If control not on Scene then Visual will be added when SceneConnection is called.
887 DALI_LOG_INFO(gLogFilter, Debug::Verbose, "Control::EnableVisual Setting %s(%d) on stage \n", (*iter)->visual.GetName().c_str(), index);
888 Toolkit::GetImplementation((*iter)->visual).SetOnScene(parentActor);
892 DALI_LOG_INFO(gLogFilter, Debug::Verbose, "Control::EnableVisual Setting %s(%d) off stage \n", (*iter)->visual.GetName().c_str(), index);
893 Toolkit::GetImplementation((*iter)->visual).SetOffScene(parentActor); // No need to call if control not staged.
899 DALI_LOG_WARNING("Control::EnableVisual(%d, %s) FAILED - NO SUCH VISUAL\n", index, enable ? "T" : "F");
903 bool Control::Impl::IsVisualEnabled(Property::Index index) const
905 RegisteredVisualContainer::Iterator iter;
906 if(FindVisual(index, mVisuals, iter))
908 return (*iter)->enabled;
913 void Control::Impl::EnableReadyTransitionOverriden(Toolkit::Visual::Base& visual, bool enable)
915 DALI_LOG_INFO(gLogFilter, Debug::General, "Control::EnableReadyTransitionOverriden(%p, %s)\n", visual, enable ? "T" : "F");
917 RegisteredVisualContainer::Iterator iter;
918 if(FindVisual(visual, mVisuals, iter))
920 if((*iter)->overideReadyTransition == enable)
922 DALI_LOG_INFO(gLogFilter, Debug::Verbose, "Control::EnableReadyTransitionOverriden Visual %s(%p) already %s\n", (*iter)->visual.GetName().c_str(), visual, enable ? "enabled" : "disabled");
926 (*iter)->overideReadyTransition = enable;
930 void Control::Impl::StopObservingVisual(Toolkit::Visual::Base& visual)
932 Internal::Visual::Base& visualImpl = Toolkit::GetImplementation(visual);
934 // Stop observing the visual
935 visualImpl.RemoveEventObserver(*this);
938 void Control::Impl::StartObservingVisual(Toolkit::Visual::Base& visual)
940 Internal::Visual::Base& visualImpl = Toolkit::GetImplementation(visual);
942 // start observing the visual for events
943 visualImpl.AddEventObserver(*this);
946 void Control::Impl::ResourceReady(bool relayoutRequest)
948 Actor self = mControlImpl.Self();
949 // A visual is ready so control may need relayouting if staged
950 if(relayoutRequest && self.GetProperty<bool>(Actor::Property::CONNECTED_TO_SCENE))
952 mControlImpl.RelayoutRequest();
955 // Emit signal if all enabled visuals registered by the control are ready or there are no visuals.
956 if(IsResourceReady())
959 mNeedToEmitResourceReady = false;
960 EmitResourceReadySignal();
964 // Called by a Visual when it's resource is ready
965 void Control::Impl::ResourceReady(Visual::Base& object)
967 DALI_LOG_INFO(gLogFilter, Debug::Verbose, "Control::Impl::ResourceReady() replacements pending[%d]\n", mRemoveVisuals.Count());
969 Actor self = mControlImpl.Self();
971 // A resource is ready, find resource in the registered visuals container and get its index
972 for(auto registeredIter = mVisuals.Begin(), end = mVisuals.End(); registeredIter != end; ++registeredIter)
974 Internal::Visual::Base& registeredVisualImpl = Toolkit::GetImplementation((*registeredIter)->visual);
976 if(&object == ®isteredVisualImpl)
978 RegisteredVisualContainer::Iterator visualToRemoveIter;
979 // Find visual with the same index in the removal container
980 // Set if off stage as it's replacement is now ready.
981 // Remove if from removal list as now removed from stage.
982 // Set Pending flag on the ready visual to false as now ready.
983 if(FindVisual((*registeredIter)->index, mRemoveVisuals, visualToRemoveIter))
985 (*registeredIter)->pending = false;
986 if(!((*visualToRemoveIter)->overideReadyTransition))
988 Toolkit::GetImplementation((*visualToRemoveIter)->visual).SetOffScene(self);
990 mRemoveVisuals.Erase(visualToRemoveIter);
996 // Called by a Visual when it's resource is ready
1000 void Control::Impl::NotifyVisualEvent(Visual::Base& object, Property::Index signalId)
1002 for(auto registeredIter = mVisuals.Begin(), end = mVisuals.End(); registeredIter != end; ++registeredIter)
1004 Internal::Visual::Base& registeredVisualImpl = Toolkit::GetImplementation((*registeredIter)->visual);
1005 if(&object == ®isteredVisualImpl)
1007 Dali::Toolkit::Control handle(mControlImpl.GetOwner());
1008 mVisualEventSignal.Emit(handle, (*registeredIter)->index, signalId);
1014 void Control::Impl::RelayoutRequest(Visual::Base& object)
1016 mControlImpl.RelayoutRequest();
1019 bool Control::Impl::IsResourceReady() const
1021 // Iterate through and check all the enabled visuals are ready
1022 for(auto visualIter = mVisuals.Begin();
1023 visualIter != mVisuals.End();
1026 const Toolkit::Visual::Base visual = (*visualIter)->visual;
1027 const Internal::Visual::Base& visualImpl = Toolkit::GetImplementation(visual);
1029 // one of the enabled visuals is not ready
1030 if(!visualImpl.IsResourceReady() && (*visualIter)->enabled)
1038 Toolkit::Visual::ResourceStatus Control::Impl::GetVisualResourceStatus(Property::Index index) const
1040 RegisteredVisualContainer::Iterator iter;
1041 if(FindVisual(index, mVisuals, iter))
1043 const Toolkit::Visual::Base visual = (*iter)->visual;
1044 const Internal::Visual::Base& visualImpl = Toolkit::GetImplementation(visual);
1045 return visualImpl.GetResourceStatus();
1048 return Toolkit::Visual::ResourceStatus::PREPARING;
1051 void Control::Impl::AddTransitions(Dali::Animation& animation,
1052 const Toolkit::TransitionData& handle,
1053 bool createAnimation)
1055 // Setup a Transition from TransitionData.
1056 const Internal::TransitionData& transitionData = Toolkit::GetImplementation(handle);
1057 TransitionData::Iterator end = transitionData.End();
1058 for(TransitionData::Iterator iter = transitionData.Begin();
1062 TransitionData::Animator* animator = (*iter);
1064 Toolkit::Visual::Base visual = GetVisualByName(mVisuals, animator->objectName);
1068 #if defined(DEBUG_ENABLED)
1069 Dali::TypeInfo typeInfo;
1070 ControlWrapper* controlWrapperImpl = dynamic_cast<ControlWrapper*>(&mControlImpl);
1071 if(controlWrapperImpl)
1073 typeInfo = controlWrapperImpl->GetTypeInfo();
1076 DALI_LOG_INFO(gLogFilter, Debug::Concise, "CreateTransition: Found %s visual for %s\n", visual.GetName().c_str(), typeInfo ? typeInfo.GetName().c_str() : "Unknown");
1078 Internal::Visual::Base& visualImpl = Toolkit::GetImplementation(visual);
1079 visualImpl.AnimateProperty(animation, *animator);
1083 DALI_LOG_INFO(gLogFilter, Debug::Concise, "CreateTransition: Could not find visual. Trying actors");
1084 // Otherwise, try any actor children of control (Including the control)
1085 Actor child = mControlImpl.Self().FindChildByName(animator->objectName);
1088 Property::Index propertyIndex = child.GetPropertyIndex(animator->propertyKey);
1089 if(propertyIndex != Property::INVALID_INDEX)
1091 if(animator->animate == false)
1093 if(animator->targetValue.GetType() != Property::NONE)
1095 child.SetProperty(propertyIndex, animator->targetValue);
1098 else // animate the property
1100 if(animator->initialValue.GetType() != Property::NONE)
1102 child.SetProperty(propertyIndex, animator->initialValue);
1105 if(createAnimation && !animation)
1107 animation = Dali::Animation::New(0.1f);
1110 animation.AnimateTo(Property(child, propertyIndex),
1111 animator->targetValue,
1112 animator->alphaFunction,
1113 TimePeriod(animator->timePeriodDelay,
1114 animator->timePeriodDuration));
1122 Dali::Animation Control::Impl::CreateTransition(const Toolkit::TransitionData& transitionData)
1124 Dali::Animation transition;
1126 if(transitionData.Count() > 0)
1128 AddTransitions(transition, transitionData, true);
1133 void Control::Impl::DoAction(Dali::Property::Index visualIndex, Dali::Property::Index actionId, const Dali::Property::Value attributes)
1135 RegisteredVisualContainer::Iterator iter;
1136 if(FindVisual(visualIndex, mVisuals, iter))
1138 Toolkit::GetImplementation((*iter)->visual).DoAction(actionId, attributes);
1142 void Control::Impl::DoActionExtension(Dali::Property::Index visualIndex, Dali::Property::Index actionId, Dali::Any attributes)
1144 RegisteredVisualContainer::Iterator iter;
1145 if(FindVisual(visualIndex, mVisuals, iter))
1147 Toolkit::GetImplementation((*iter)->visual).DoActionExtension(actionId, attributes);
1151 void Control::Impl::AppendAccessibilityAttribute(const std::string& key, const std::string value)
1153 Property::Value* checkedValue = mAccessibilityAttributes.Find(key);
1156 mAccessibilityAttributes[key] = Property::Value(value);
1160 mAccessibilityAttributes.Insert(key, value);
1164 void Control::Impl::SetProperty(BaseObject* object, Property::Index index, const Property::Value& value)
1166 Toolkit::Control control = Toolkit::Control::DownCast(BaseHandle(object));
1170 Control& controlImpl(GetImplementation(control));
1174 case Toolkit::Control::Property::STYLE_NAME:
1176 controlImpl.SetStyleName(value.Get<std::string>());
1180 case Toolkit::DevelControl::Property::STATE:
1182 bool withTransitions = true;
1183 const Property::Value* valuePtr = &value;
1184 const Property::Map* map = value.GetMap();
1187 Property::Value* value2 = map->Find("withTransitions");
1190 withTransitions = value2->Get<bool>();
1193 valuePtr = map->Find("state");
1198 Toolkit::DevelControl::State state(controlImpl.mImpl->mState);
1199 if(Scripting::GetEnumerationProperty<Toolkit::DevelControl::State>(*valuePtr, ControlStateTable, ControlStateTableCount, state))
1201 controlImpl.mImpl->SetState(state, withTransitions);
1207 case Toolkit::DevelControl::Property::SUB_STATE:
1209 std::string subState;
1210 if(value.Get(subState))
1212 controlImpl.mImpl->SetSubState(subState);
1217 case Toolkit::DevelControl::Property::LEFT_FOCUSABLE_ACTOR_ID:
1220 if(value.Get(focusId))
1222 controlImpl.mImpl->mLeftFocusableActorId = focusId;
1227 case Toolkit::DevelControl::Property::RIGHT_FOCUSABLE_ACTOR_ID:
1230 if(value.Get(focusId))
1232 controlImpl.mImpl->mRightFocusableActorId = focusId;
1237 case Toolkit::DevelControl::Property::UP_FOCUSABLE_ACTOR_ID:
1240 if(value.Get(focusId))
1242 controlImpl.mImpl->mUpFocusableActorId = focusId;
1247 case Toolkit::DevelControl::Property::DOWN_FOCUSABLE_ACTOR_ID:
1250 if(value.Get(focusId))
1252 controlImpl.mImpl->mDownFocusableActorId = focusId;
1257 case Toolkit::Control::Property::KEY_INPUT_FOCUS:
1259 if(value.Get<bool>())
1261 controlImpl.SetKeyInputFocus();
1265 controlImpl.ClearKeyInputFocus();
1270 case Toolkit::Control::Property::BACKGROUND:
1274 const Property::Map* map = value.GetMap();
1275 if(map && !map->Empty())
1277 controlImpl.SetBackground(*map);
1279 else if(value.Get(url))
1281 // don't know the size to load
1282 Toolkit::Visual::Base visual = Toolkit::VisualFactory::Get().CreateVisual(url, ImageDimensions());
1285 controlImpl.mImpl->RegisterVisual(Toolkit::Control::Property::BACKGROUND, visual, DepthIndex::BACKGROUND);
1288 else if(value.Get(color))
1290 controlImpl.SetBackgroundColor(color);
1294 // The background is an empty property map, so we should clear the background
1295 controlImpl.ClearBackground();
1300 case Toolkit::Control::Property::MARGIN:
1303 if(value.Get(margin))
1305 controlImpl.mImpl->SetMargin(margin);
1310 case Toolkit::Control::Property::PADDING:
1313 if(value.Get(padding))
1315 controlImpl.mImpl->SetPadding(padding);
1320 case Toolkit::DevelControl::Property::TOOLTIP:
1322 TooltipPtr& tooltipPtr = controlImpl.mImpl->mTooltip;
1325 tooltipPtr = Tooltip::New(control);
1327 tooltipPtr->SetProperties(value);
1331 case Toolkit::DevelControl::Property::SHADOW:
1333 const Property::Map* map = value.GetMap();
1334 if(map && !map->Empty())
1336 controlImpl.mImpl->SetShadow(*map);
1340 // The shadow is an empty property map, so we should clear the shadow
1341 controlImpl.mImpl->ClearShadow();
1346 case Toolkit::DevelControl::Property::ACCESSIBILITY_NAME:
1351 controlImpl.mImpl->mAccessibilityName = name;
1356 case Toolkit::DevelControl::Property::ACCESSIBILITY_DESCRIPTION:
1361 controlImpl.mImpl->mAccessibilityDescription = text;
1366 case Toolkit::DevelControl::Property::ACCESSIBILITY_TRANSLATION_DOMAIN:
1371 controlImpl.mImpl->mAccessibilityTranslationDomain = text;
1376 case Toolkit::DevelControl::Property::ACCESSIBILITY_ROLE:
1378 Dali::Accessibility::Role role;
1381 controlImpl.mImpl->mAccessibilityRole = role;
1386 case Toolkit::DevelControl::Property::ACCESSIBILITY_HIGHLIGHTABLE:
1389 if(value.Get(highlightable))
1391 controlImpl.mImpl->mAccessibilityHighlightable = highlightable;
1396 case Toolkit::DevelControl::Property::ACCESSIBILITY_ATTRIBUTES:
1398 const Property::Map* map = value.GetMap();
1399 if(map && !map->Empty())
1401 controlImpl.mImpl->mAccessibilityAttributes = *map;
1406 case Toolkit::DevelControl::Property::DISPATCH_KEY_EVENTS:
1409 if(value.Get(dispatch))
1411 controlImpl.mImpl->mDispatchKeyEvents = dispatch;
1416 case Toolkit::DevelControl::Property::ACCESSIBILITY_HIDDEN:
1419 if(value.Get(hidden))
1421 controlImpl.mImpl->mAccessibilityHidden = hidden;
1423 auto* accessible = controlImpl.GetAccessibleObject();
1424 auto* parent = dynamic_cast<Dali::Accessibility::ActorAccessible*>(accessible->GetParent());
1427 parent->OnChildrenChanged();
1432 case Toolkit::DevelControl::Property::CLOCKWISE_FOCUSABLE_ACTOR_ID:
1435 if(value.Get(focusId))
1437 controlImpl.mImpl->mClockwiseFocusableActorId = focusId;
1441 case Toolkit::DevelControl::Property::COUNTER_CLOCKWISE_FOCUSABLE_ACTOR_ID:
1444 if(value.Get(focusId))
1446 controlImpl.mImpl->mCounterClockwiseFocusableActorId = focusId;
1451 case Toolkit::DevelControl::Property::AUTOMATION_ID:
1453 std::string automationId;
1454 if(value.Get(automationId))
1456 controlImpl.mImpl->mAutomationId = automationId;
1464 Property::Value Control::Impl::GetProperty(BaseObject* object, Property::Index index)
1466 Property::Value value;
1468 Toolkit::Control control = Toolkit::Control::DownCast(BaseHandle(object));
1472 Control& controlImpl(GetImplementation(control));
1476 case Toolkit::Control::Property::STYLE_NAME:
1478 value = controlImpl.GetStyleName();
1482 case Toolkit::DevelControl::Property::STATE:
1484 value = controlImpl.mImpl->mState;
1488 case Toolkit::DevelControl::Property::SUB_STATE:
1490 value = controlImpl.mImpl->mSubStateName;
1494 case Toolkit::DevelControl::Property::LEFT_FOCUSABLE_ACTOR_ID:
1496 value = controlImpl.mImpl->mLeftFocusableActorId;
1500 case Toolkit::DevelControl::Property::RIGHT_FOCUSABLE_ACTOR_ID:
1502 value = controlImpl.mImpl->mRightFocusableActorId;
1506 case Toolkit::DevelControl::Property::UP_FOCUSABLE_ACTOR_ID:
1508 value = controlImpl.mImpl->mUpFocusableActorId;
1512 case Toolkit::DevelControl::Property::DOWN_FOCUSABLE_ACTOR_ID:
1514 value = controlImpl.mImpl->mDownFocusableActorId;
1518 case Toolkit::Control::Property::KEY_INPUT_FOCUS:
1520 value = controlImpl.HasKeyInputFocus();
1524 case Toolkit::Control::Property::BACKGROUND:
1527 Toolkit::Visual::Base visual = controlImpl.mImpl->GetVisual(Toolkit::Control::Property::BACKGROUND);
1530 visual.CreatePropertyMap(map);
1537 case Toolkit::Control::Property::MARGIN:
1539 value = controlImpl.mImpl->GetMargin();
1543 case Toolkit::Control::Property::PADDING:
1545 value = controlImpl.mImpl->GetPadding();
1549 case Toolkit::DevelControl::Property::TOOLTIP:
1552 if(controlImpl.mImpl->mTooltip)
1554 controlImpl.mImpl->mTooltip->CreatePropertyMap(map);
1560 case Toolkit::DevelControl::Property::SHADOW:
1563 Toolkit::Visual::Base visual = controlImpl.mImpl->GetVisual(Toolkit::DevelControl::Property::SHADOW);
1566 visual.CreatePropertyMap(map);
1573 case Toolkit::DevelControl::Property::ACCESSIBILITY_NAME:
1575 value = controlImpl.mImpl->mAccessibilityName;
1579 case Toolkit::DevelControl::Property::ACCESSIBILITY_DESCRIPTION:
1581 value = controlImpl.mImpl->mAccessibilityDescription;
1585 case Toolkit::DevelControl::Property::ACCESSIBILITY_TRANSLATION_DOMAIN:
1587 value = controlImpl.mImpl->mAccessibilityTranslationDomain;
1591 case Toolkit::DevelControl::Property::ACCESSIBILITY_ROLE:
1593 value = Property::Value(controlImpl.mImpl->mAccessibilityRole);
1597 case Toolkit::DevelControl::Property::ACCESSIBILITY_HIGHLIGHTABLE:
1599 value = controlImpl.mImpl->mAccessibilityHighlightable;
1603 case Toolkit::DevelControl::Property::ACCESSIBILITY_ATTRIBUTES:
1605 value = controlImpl.mImpl->mAccessibilityAttributes;
1609 case Toolkit::DevelControl::Property::DISPATCH_KEY_EVENTS:
1611 value = controlImpl.mImpl->mDispatchKeyEvents;
1615 case Toolkit::DevelControl::Property::ACCESSIBILITY_HIDDEN:
1617 value = controlImpl.mImpl->mAccessibilityHidden;
1621 case Toolkit::DevelControl::Property::CLOCKWISE_FOCUSABLE_ACTOR_ID:
1623 value = controlImpl.mImpl->mClockwiseFocusableActorId;
1627 case Toolkit::DevelControl::Property::COUNTER_CLOCKWISE_FOCUSABLE_ACTOR_ID:
1629 value = controlImpl.mImpl->mCounterClockwiseFocusableActorId;
1633 case Toolkit::DevelControl::Property::AUTOMATION_ID:
1635 value = controlImpl.mImpl->mAutomationId;
1644 void Control::Impl::RemoveAccessibilityAttribute(const std::string& key)
1646 Property::Value* value = mAccessibilityAttributes.Find(key);
1649 mAccessibilityAttributes[key] = Property::Value();
1653 void Control::Impl::ClearAccessibilityAttributes()
1655 mAccessibilityAttributes.Clear();
1658 void Control::Impl::SetAccessibilityReadingInfoType(const Dali::Accessibility::ReadingInfoTypes types)
1660 std::string value{};
1661 if(types[Dali::Accessibility::ReadingInfoType::NAME])
1663 value += READING_INFO_TYPE_NAME;
1665 if(types[Dali::Accessibility::ReadingInfoType::ROLE])
1669 value += READING_INFO_TYPE_SEPARATOR;
1671 value += READING_INFO_TYPE_ROLE;
1673 if(types[Dali::Accessibility::ReadingInfoType::DESCRIPTION])
1677 value += READING_INFO_TYPE_SEPARATOR;
1679 value += READING_INFO_TYPE_DESCRIPTION;
1681 if(types[Dali::Accessibility::ReadingInfoType::STATE])
1685 value += READING_INFO_TYPE_SEPARATOR;
1687 value += READING_INFO_TYPE_STATE;
1689 AppendAccessibilityAttribute(READING_INFO_TYPE_ATTRIBUTE_NAME, value);
1692 Dali::Accessibility::ReadingInfoTypes Control::Impl::GetAccessibilityReadingInfoType() const
1694 std::string value{};
1695 auto place = mAccessibilityAttributes.Find(READING_INFO_TYPE_ATTRIBUTE_NAME);
1702 Dali::Accessibility::ReadingInfoTypes types;
1703 types[Dali::Accessibility::ReadingInfoType::NAME] = true;
1704 types[Dali::Accessibility::ReadingInfoType::ROLE] = true;
1705 types[Dali::Accessibility::ReadingInfoType::DESCRIPTION] = true;
1706 types[Dali::Accessibility::ReadingInfoType::STATE] = true;
1715 Dali::Accessibility::ReadingInfoTypes types;
1717 if(value.find(READING_INFO_TYPE_NAME) != std::string::npos)
1719 types[Dali::Accessibility::ReadingInfoType::NAME] = true;
1721 if(value.find(READING_INFO_TYPE_ROLE) != std::string::npos)
1723 types[Dali::Accessibility::ReadingInfoType::ROLE] = true;
1725 if(value.find(READING_INFO_TYPE_DESCRIPTION) != std::string::npos)
1727 types[Dali::Accessibility::ReadingInfoType::DESCRIPTION] = true;
1729 if(value.find(READING_INFO_TYPE_STATE) != std::string::npos)
1731 types[Dali::Accessibility::ReadingInfoType::STATE] = true;
1737 void Control::Impl::CopyInstancedProperties(RegisteredVisualContainer& visuals, Dictionary<Property::Map>& instancedProperties)
1739 for(RegisteredVisualContainer::Iterator iter = visuals.Begin(); iter != visuals.End(); iter++)
1743 Property::Map instanceMap;
1744 Toolkit::GetImplementation((*iter)->visual).CreateInstancePropertyMap(instanceMap);
1745 instancedProperties.Add((*iter)->visual.GetName(), instanceMap);
1750 void Control::Impl::RemoveVisual(RegisteredVisualContainer& visuals, const std::string& visualName)
1752 Actor self(mControlImpl.Self());
1754 for(RegisteredVisualContainer::Iterator visualIter = visuals.Begin();
1755 visualIter != visuals.End();
1758 Toolkit::Visual::Base visual = (*visualIter)->visual;
1759 if(visual && visual.GetName() == visualName)
1761 Toolkit::GetImplementation(visual).SetOffScene(self);
1762 (*visualIter)->visual.Reset();
1763 visuals.Erase(visualIter);
1769 void Control::Impl::RemoveVisuals(RegisteredVisualContainer& visuals, DictionaryKeys& removeVisuals)
1771 Actor self(mControlImpl.Self());
1772 for(DictionaryKeys::iterator iter = removeVisuals.begin(); iter != removeVisuals.end(); ++iter)
1774 const std::string visualName = *iter;
1775 RemoveVisual(visuals, visualName);
1779 void Control::Impl::RecreateChangedVisuals(Dictionary<Property::Map>& stateVisualsToChange,
1780 Dictionary<Property::Map>& instancedProperties)
1782 Dali::CustomActor handle(mControlImpl.GetOwner());
1783 for(Dictionary<Property::Map>::iterator iter = stateVisualsToChange.Begin();
1784 iter != stateVisualsToChange.End();
1787 const std::string& visualName = (*iter).key;
1788 const Property::Map& toMap = (*iter).entry;
1790 Actor self = mControlImpl.Self();
1791 RegisteredVisualContainer::Iterator registeredVisualsiter;
1792 // Check if visual (visualName) is already registered, this is the current visual.
1793 if(FindVisual(visualName, mVisuals, registeredVisualsiter))
1795 Toolkit::Visual::Base& visual = (*registeredVisualsiter)->visual;
1798 // No longer required to know if the replaced visual's resources are ready
1799 StopObservingVisual(visual);
1801 // If control staged then visuals will be swapped once ready
1802 if(self.GetProperty<bool>(Actor::Property::CONNECTED_TO_SCENE))
1804 // Check if visual is currently in the process of being replaced ( is in removal container )
1805 RegisteredVisualContainer::Iterator visualQueuedForRemoval;
1806 if(FindVisual(visualName, mRemoveVisuals, visualQueuedForRemoval))
1808 // Visual with same visual name is already in removal container so current visual pending
1809 // Only the the last requested visual will be displayed so remove current visual which is staged but not ready.
1810 Toolkit::GetImplementation(visual).SetOffScene(self);
1811 (*registeredVisualsiter)->visual.Reset();
1812 mVisuals.Erase(registeredVisualsiter);
1816 // current visual not already in removal container so add now.
1817 DALI_LOG_INFO(gLogFilter, Debug::Verbose, "RegisterVisual Move current registered visual to removal Queue: %s \n", visualName.c_str());
1818 MoveVisual(registeredVisualsiter, mVisuals, mRemoveVisuals);
1823 // Control not staged or visual disabled so can just erase from registered visuals and new visual will be added later.
1824 (*registeredVisualsiter)->visual.Reset();
1825 mVisuals.Erase(registeredVisualsiter);
1829 const Property::Map* instancedMap = instancedProperties.FindConst(visualName);
1830 Style::ApplyVisual(handle, visualName, toMap, instancedMap);
1835 void Control::Impl::ReplaceStateVisualsAndProperties(const StylePtr oldState, const StylePtr newState, const std::string& subState)
1837 // Collect all old visual names
1838 DictionaryKeys stateVisualsToRemove;
1841 oldState->visuals.GetKeys(stateVisualsToRemove);
1842 if(!subState.empty())
1844 const StylePtr* oldSubState = oldState->subStates.FindConst(subState);
1847 DictionaryKeys subStateVisualsToRemove;
1848 (*oldSubState)->visuals.GetKeys(subStateVisualsToRemove);
1849 Merge(stateVisualsToRemove, subStateVisualsToRemove);
1854 // Collect all new visual properties
1855 Dictionary<Property::Map> stateVisualsToAdd;
1858 stateVisualsToAdd = newState->visuals;
1859 if(!subState.empty())
1861 const StylePtr* newSubState = newState->subStates.FindConst(subState);
1864 stateVisualsToAdd.Merge((*newSubState)->visuals);
1869 // If a name is in both add/remove, move it to change list.
1870 Dictionary<Property::Map> stateVisualsToChange;
1871 FindChangableVisuals(stateVisualsToAdd, stateVisualsToChange, stateVisualsToRemove);
1873 // Copy instanced properties (e.g. text label) of current visuals
1874 Dictionary<Property::Map> instancedProperties;
1875 CopyInstancedProperties(mVisuals, instancedProperties);
1877 // For each visual in remove list, remove from mVisuals
1878 RemoveVisuals(mVisuals, stateVisualsToRemove);
1880 // For each visual in add list, create and add to mVisuals
1881 Dali::CustomActor handle(mControlImpl.GetOwner());
1882 Style::ApplyVisuals(handle, stateVisualsToAdd, instancedProperties);
1884 // For each visual in change list, if it requires a new visual,
1885 // remove old visual, create and add to mVisuals
1886 RecreateChangedVisuals(stateVisualsToChange, instancedProperties);
1889 void Control::Impl::SetState(DevelControl::State newState, bool withTransitions)
1891 DevelControl::State oldState = mState;
1892 Dali::CustomActor handle(mControlImpl.GetOwner());
1893 DALI_LOG_INFO(gLogFilter, Debug::Concise, "Control::Impl::SetState: %s\n", (mState == DevelControl::NORMAL ? "NORMAL" : (mState == DevelControl::FOCUSED ? "FOCUSED" : (mState == DevelControl::DISABLED ? "DISABLED" : "NONE"))));
1895 if(mState != newState)
1897 // If mState was Disabled, and new state is Focused, should probably
1898 // store that fact, e.g. in another property that FocusManager can access.
1901 // Trigger state change and transitions
1902 // Apply new style, if stylemanager is available
1903 Toolkit::StyleManager styleManager = Toolkit::StyleManager::Get();
1906 const StylePtr stylePtr = GetImpl(styleManager).GetRecordedStyle(Toolkit::Control(mControlImpl.GetOwner()));
1910 std::string oldStateName = Scripting::GetEnumerationName<Toolkit::DevelControl::State>(oldState, ControlStateTable, ControlStateTableCount);
1911 std::string newStateName = Scripting::GetEnumerationName<Toolkit::DevelControl::State>(newState, ControlStateTable, ControlStateTableCount);
1913 const StylePtr* newStateStyle = stylePtr->subStates.Find(newStateName);
1914 const StylePtr* oldStateStyle = stylePtr->subStates.Find(oldStateName);
1915 if(oldStateStyle && newStateStyle)
1917 // Only change if both state styles exist
1918 ReplaceStateVisualsAndProperties(*oldStateStyle, *newStateStyle, mSubStateName);
1925 void Control::Impl::SetSubState(const std::string& subStateName, bool withTransitions)
1927 if(mSubStateName != subStateName)
1929 // Get existing sub-state visuals, and unregister them
1930 Dali::CustomActor handle(mControlImpl.GetOwner());
1932 Toolkit::StyleManager styleManager = Toolkit::StyleManager::Get();
1935 const StylePtr stylePtr = GetImpl(styleManager).GetRecordedStyle(Toolkit::Control(mControlImpl.GetOwner()));
1939 std::string stateName = Scripting::GetEnumerationName<Toolkit::DevelControl::State>(mState, ControlStateTable, ControlStateTableCount);
1941 const StylePtr* state = stylePtr->subStates.Find(stateName);
1944 StylePtr stateStyle(*state);
1946 const StylePtr* newStateStyle = stateStyle->subStates.Find(subStateName);
1947 const StylePtr* oldStateStyle = stateStyle->subStates.Find(mSubStateName);
1948 if(oldStateStyle && newStateStyle)
1951 ReplaceStateVisualsAndProperties(*oldStateStyle, *newStateStyle, empty);
1957 mSubStateName = subStateName;
1961 void Control::Impl::OnSceneDisconnection()
1963 Actor self = mControlImpl.Self();
1965 // Any visuals set for replacement but not yet ready should still be registered.
1966 // Reason: If a request was made to register a new visual but the control removed from scene before visual was ready
1967 // then when this control appears back on stage it should use that new visual.
1969 // Iterate through all registered visuals and set off scene
1970 SetVisualsOffScene(mVisuals, self);
1972 // Visuals pending replacement can now be taken out of the removal list and set off scene
1973 // Iterate through all replacement visuals and add to a move queue then set off scene
1974 for(auto removalIter = mRemoveVisuals.Begin(), end = mRemoveVisuals.End(); removalIter != end; removalIter++)
1976 Toolkit::GetImplementation((*removalIter)->visual).SetOffScene(self);
1979 for(auto replacedIter = mVisuals.Begin(), end = mVisuals.End(); replacedIter != end; replacedIter++)
1981 (*replacedIter)->pending = false;
1984 mRemoveVisuals.Clear();
1987 void Control::Impl::SetMargin(Extents margin)
1989 mControlImpl.mImpl->mMargin = margin;
1991 // Trigger a size negotiation request that may be needed when setting a margin.
1992 mControlImpl.RelayoutRequest();
1995 Extents Control::Impl::GetMargin() const
1997 return mControlImpl.mImpl->mMargin;
2000 void Control::Impl::SetPadding(Extents padding)
2002 mControlImpl.mImpl->mPadding = padding;
2004 // Trigger a size negotiation request that may be needed when setting a padding.
2005 mControlImpl.RelayoutRequest();
2008 Extents Control::Impl::GetPadding() const
2010 return mControlImpl.mImpl->mPadding;
2013 void Control::Impl::SetInputMethodContext(InputMethodContext& inputMethodContext)
2015 mInputMethodContext = inputMethodContext;
2018 bool Control::Impl::FilterKeyEvent(const KeyEvent& event)
2020 bool consumed(false);
2022 if(mInputMethodContext)
2024 consumed = mInputMethodContext.FilterEventKey(event);
2029 DevelControl::VisualEventSignalType& Control::Impl::VisualEventSignal()
2031 return mVisualEventSignal;
2034 void Control::Impl::SetShadow(const Property::Map& map)
2036 Toolkit::Visual::Base visual = Toolkit::VisualFactory::Get().CreateVisual(map);
2037 visual.SetName("shadow");
2041 mControlImpl.mImpl->RegisterVisual(Toolkit::DevelControl::Property::SHADOW, visual, DepthIndex::BACKGROUND_EFFECT);
2043 mControlImpl.RelayoutRequest();
2047 void Control::Impl::ClearShadow()
2049 mControlImpl.mImpl->UnregisterVisual(Toolkit::DevelControl::Property::SHADOW);
2051 // Trigger a size negotiation request that may be needed when unregistering a visual.
2052 mControlImpl.RelayoutRequest();
2055 Dali::Property Control::Impl::GetVisualProperty(Dali::Property::Index index, Dali::Property::Key visualPropertyKey)
2057 Toolkit::Visual::Base visual = GetVisualByIndex(mVisuals, index);
2060 Internal::Visual::Base& visualImpl = Toolkit::GetImplementation(visual);
2061 return visualImpl.GetPropertyObject(visualPropertyKey);
2065 return Dali::Property(handle, Property::INVALID_INDEX);
2068 void Control::Impl::CreateTransitions(std::vector<std::pair<Dali::Property::Index, Dali::Property::Map>>& sourceProperties,
2069 std::vector<std::pair<Dali::Property::Index, Dali::Property::Map>>& destinationProperties,
2070 Dali::Toolkit::Control source,
2071 Dali::Toolkit::Control destination)
2073 // Retrieves background properties to be transitioned.
2074 Dali::Property::Map backgroundSourcePropertyMap, backgroundDestinationPropertyMap;
2075 mControlImpl.MakeVisualTransition(backgroundSourcePropertyMap, backgroundDestinationPropertyMap, source, destination, Toolkit::Control::Property::BACKGROUND);
2076 if(backgroundSourcePropertyMap.Count() > 0)
2078 sourceProperties.push_back(std::pair<Dali::Property::Index, Dali::Property::Map>(Toolkit::Control::Property::BACKGROUND, backgroundSourcePropertyMap));
2079 destinationProperties.push_back(std::pair<Dali::Property::Index, Dali::Property::Map>(Toolkit::Control::Property::BACKGROUND, backgroundDestinationPropertyMap));
2082 // Retrieves shadow properties to be transitioned.
2083 Dali::Property::Map shadowSourcePropertyMap, shadowDestinationPropertyMap;
2084 mControlImpl.MakeVisualTransition(shadowSourcePropertyMap, shadowDestinationPropertyMap, source, destination, Toolkit::DevelControl::Property::SHADOW);
2085 if(shadowSourcePropertyMap.Count() > 0)
2087 sourceProperties.push_back(std::pair<Dali::Property::Index, Dali::Property::Map>(Toolkit::DevelControl::Property::SHADOW, shadowSourcePropertyMap));
2088 destinationProperties.push_back(std::pair<Dali::Property::Index, Dali::Property::Map>(Toolkit::DevelControl::Property::SHADOW, shadowDestinationPropertyMap));
2091 // Retrieves transition from inherited class.
2092 mControlImpl.OnCreateTransitions(sourceProperties, destinationProperties, source, destination);
2095 void Control::Impl::UpdateVisualProperties(const std::vector<std::pair<Dali::Property::Index, Dali::Property::Map>>& properties)
2097 for(auto&& data : properties)
2099 if(data.first == Toolkit::Control::Property::BACKGROUND)
2101 DoAction(Toolkit::Control::Property::BACKGROUND, DevelVisual::Action::UPDATE_PROPERTY, data.second);
2103 else if(data.first == Toolkit::DevelControl::Property::SHADOW)
2105 DoAction(Toolkit::DevelControl::Property::SHADOW, DevelVisual::Action::UPDATE_PROPERTY, data.second);
2108 mControlImpl.OnUpdateVisualProperties(properties);
2111 void Control::Impl::EmitResourceReadySignal()
2113 if(!mIsEmittingResourceReadySignal)
2115 // Guard against calls to emit the signal during the callback
2116 mIsEmittingResourceReadySignal = true;
2118 // If the signal handler changes visual, it may become ready during this call & therefore this method will
2119 // get called again recursively. If so, mNeedToEmitResourceReady is set below, and we act on it after that secondary
2120 // invocation has completed by notifying in an Idle callback to prevent further recursion.
2121 Dali::Toolkit::Control handle(mControlImpl.GetOwner());
2122 mResourceReadySignal.Emit(handle);
2124 if(mNeedToEmitResourceReady)
2126 // Add idler to emit the signal again
2129 // The callback manager takes the ownership of the callback object.
2130 mIdleCallback = MakeCallback(this, &Control::Impl::OnIdleCallback);
2131 Adaptor::Get().AddIdle(mIdleCallback, false);
2135 mIsEmittingResourceReadySignal = false;
2139 mNeedToEmitResourceReady = true;
2143 void Control::Impl::OnIdleCallback()
2145 if(mNeedToEmitResourceReady)
2148 mNeedToEmitResourceReady = false;
2150 // A visual is ready so control may need relayouting if staged
2151 if(mControlImpl.Self().GetProperty<bool>(Actor::Property::CONNECTED_TO_SCENE))
2153 mControlImpl.RelayoutRequest();
2156 EmitResourceReadySignal();
2159 // Set the pointer to null as the callback manager deletes the callback after execute it.
2160 mIdleCallback = nullptr;
2163 Toolkit::DevelControl::ControlAccessible* Control::Impl::GetAccessibleObject()
2165 if(!mAccessibleObject)
2167 mAccessibleObject.reset(mControlImpl.CreateAccessibleObject());
2170 return mAccessibleObject.get();
2173 } // namespace Internal
2175 } // namespace Toolkit