2 * Copyright (c) 2021 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/object/object-registry.h>
34 #include <dali/public-api/object/type-registry-helper.h>
39 #include <dali-toolkit/devel-api/asset-manager/asset-manager.h>
40 #include <dali-toolkit/devel-api/controls/control-depth-index-ranges.h>
41 #include <dali-toolkit/devel-api/controls/control-devel.h>
42 #include <dali-toolkit/devel-api/controls/control-wrapper-impl.h>
43 #include <dali-toolkit/internal/styling/style-manager-impl.h>
44 #include <dali-toolkit/internal/visuals/visual-base-impl.h>
45 #include <dali-toolkit/internal/visuals/visual-string-constants.h>
46 #include <dali-toolkit/public-api/controls/image-view/image-view.h>
47 #include <dali-toolkit/public-api/focus-manager/keyboard-focus-manager.h>
48 #include <dali-toolkit/public-api/visuals/image-visual-properties.h>
49 #include <dali-toolkit/public-api/visuals/visual-properties.h>
53 const std::string READING_INFO_TYPE_NAME = "name";
54 const std::string READING_INFO_TYPE_ROLE = "role";
55 const std::string READING_INFO_TYPE_DESCRIPTION = "description";
56 const std::string READING_INFO_TYPE_STATE = "state";
57 const std::string READING_INFO_TYPE_ATTRIBUTE_NAME = "reading_info_type";
58 const std::string READING_INFO_TYPE_SEPARATOR = "|";
67 extern const Dali::Scripting::StringEnum ControlStateTable[];
68 extern const unsigned int ControlStateTableCount;
70 // Not static or anonymous - shared with other translation units
71 const Scripting::StringEnum ControlStateTable[] = {
72 {"NORMAL", Toolkit::DevelControl::NORMAL},
73 {"FOCUSED", Toolkit::DevelControl::FOCUSED},
74 {"DISABLED", Toolkit::DevelControl::DISABLED},
76 const unsigned int ControlStateTableCount = sizeof(ControlStateTable) / sizeof(ControlStateTable[0]);
80 #if defined(DEBUG_ENABLED)
81 Debug::Filter* gLogFilter = Debug::Filter::New(Debug::NoLogging, false, "LOG_CONTROL_VISUALS");
85 void Remove(Dictionary<T>& keyValues, const std::string& name)
87 keyValues.Remove(name);
90 void Remove(DictionaryKeys& keys, const std::string& name)
92 DictionaryKeys::iterator iter = std::find(keys.begin(), keys.end(), name);
93 if(iter != keys.end())
100 * Finds visual in given array, returning true if found along with the iterator for that visual as a out parameter
102 bool FindVisual(Property::Index targetIndex, const RegisteredVisualContainer& visuals, RegisteredVisualContainer::Iterator& iter)
104 for(iter = visuals.Begin(); iter != visuals.End(); iter++)
106 if((*iter)->index == targetIndex)
115 * Finds visual in given array, returning true if found along with the iterator for that visual as a out parameter
117 bool FindVisual(std::string visualName, const RegisteredVisualContainer& visuals, RegisteredVisualContainer::Iterator& iter)
119 for(iter = visuals.Begin(); iter != visuals.End(); iter++)
121 Toolkit::Visual::Base visual = (*iter)->visual;
122 if(visual && visual.GetName() == visualName)
130 void FindChangableVisuals(Dictionary<Property::Map>& stateVisualsToAdd,
131 Dictionary<Property::Map>& stateVisualsToChange,
132 DictionaryKeys& stateVisualsToRemove)
134 DictionaryKeys copyOfStateVisualsToRemove = stateVisualsToRemove;
136 for(DictionaryKeys::iterator iter = copyOfStateVisualsToRemove.begin();
137 iter != copyOfStateVisualsToRemove.end();
140 const std::string& visualName = (*iter);
141 Property::Map* toMap = stateVisualsToAdd.Find(visualName);
144 stateVisualsToChange.Add(visualName, *toMap);
145 stateVisualsToAdd.Remove(visualName);
146 Remove(stateVisualsToRemove, visualName);
151 Toolkit::Visual::Base GetVisualByName(
152 const RegisteredVisualContainer& visuals,
153 const std::string& visualName)
155 Toolkit::Visual::Base visualHandle;
157 RegisteredVisualContainer::Iterator iter;
158 for(iter = visuals.Begin(); iter != visuals.End(); iter++)
160 Toolkit::Visual::Base visual = (*iter)->visual;
161 if(visual && visual.GetName() == visualName)
163 visualHandle = visual;
170 Toolkit::Visual::Base GetVisualByIndex(
171 const RegisteredVisualContainer& visuals,
172 Property::Index index)
174 Toolkit::Visual::Base visualHandle;
176 RegisteredVisualContainer::Iterator iter;
177 for(iter = visuals.Begin(); iter != visuals.End(); iter++)
179 if((*iter)->index == index)
181 visualHandle = (*iter)->visual;
189 * Move visual from source to destination container
191 void MoveVisual(RegisteredVisualContainer::Iterator sourceIter, RegisteredVisualContainer& source, RegisteredVisualContainer& destination)
193 Toolkit::Visual::Base visual = (*sourceIter)->visual;
196 RegisteredVisual* rv = source.Release(sourceIter);
197 destination.PushBack(rv);
202 * Performs actions as requested using the action name.
203 * @param[in] object The object on which to perform the action.
204 * @param[in] actionName The action to perform.
205 * @param[in] attributes The attributes with which to perfrom this action.
206 * @return true if action has been accepted by this control
208 const char* ACTION_ACCESSIBILITY_ACTIVATED = "accessibilityActivated";
209 const char* ACTION_ACCESSIBILITY_READING_CANCELLED = "ReadingCancelled";
210 const char* ACTION_ACCESSIBILITY_READING_PAUSED = "ReadingPaused";
211 const char* ACTION_ACCESSIBILITY_READING_RESUMED = "ReadingResumed";
212 const char* ACTION_ACCESSIBILITY_READING_SKIPPED = "ReadingSkipped";
213 const char* ACTION_ACCESSIBILITY_READING_STOPPED = "ReadingStopped";
215 static bool DoAction(BaseObject* object, const std::string& actionName, const Property::Map& attributes)
219 Dali::BaseHandle handle(object);
221 Toolkit::Control control = Toolkit::Control::DownCast(handle);
223 DALI_ASSERT_ALWAYS(control);
225 if(0 == strcmp(actionName.c_str(), ACTION_ACCESSIBILITY_ACTIVATED) || actionName == "activate")
227 // if cast succeeds there is an implementation so no need to check
228 if(!DevelControl::AccessibilityActivateSignal(control).Empty())
230 DevelControl::AccessibilityActivateSignal(control).Emit();
234 ret = Internal::GetImplementation(control).OnAccessibilityActivated();
237 else if(0 == strcmp(actionName.c_str(), ACTION_ACCESSIBILITY_READING_SKIPPED))
239 // if cast succeeds there is an implementation so no need to check
240 if(!DevelControl::AccessibilityReadingSkippedSignal(control).Empty())
242 DevelControl::AccessibilityReadingSkippedSignal(control).Emit();
245 else if(0 == strcmp(actionName.c_str(), ACTION_ACCESSIBILITY_READING_PAUSED))
247 // if cast succeeds there is an implementation so no need to check
248 if(!DevelControl::AccessibilityReadingPausedSignal(control).Empty())
250 DevelControl::AccessibilityReadingPausedSignal(control).Emit();
253 else if(0 == strcmp(actionName.c_str(), ACTION_ACCESSIBILITY_READING_RESUMED))
255 // if cast succeeds there is an implementation so no need to check
256 if(!DevelControl::AccessibilityReadingResumedSignal(control).Empty())
258 DevelControl::AccessibilityReadingResumedSignal(control).Emit();
261 else if(0 == strcmp(actionName.c_str(), ACTION_ACCESSIBILITY_READING_CANCELLED))
263 // if cast succeeds there is an implementation so no need to check
264 if(!DevelControl::AccessibilityReadingCancelledSignal(control).Empty())
266 DevelControl::AccessibilityReadingCancelledSignal(control).Emit();
269 else if(0 == strcmp(actionName.c_str(), ACTION_ACCESSIBILITY_READING_STOPPED))
271 // if cast succeeds there is an implementation so no need to check
272 if(!DevelControl::AccessibilityReadingStoppedSignal(control).Empty())
274 DevelControl::AccessibilityReadingStoppedSignal(control).Emit();
285 * Connects a callback function with the object's signals.
286 * @param[in] object The object providing the signal.
287 * @param[in] tracker Used to disconnect the signal.
288 * @param[in] signalName The signal to connect to.
289 * @param[in] functor A newly allocated FunctorDelegate.
290 * @return True if the signal was connected.
291 * @post If a signal was connected, ownership of functor was passed to CallbackBase. Otherwise the caller is responsible for deleting the unused functor.
293 const char* SIGNAL_KEY_EVENT = "keyEvent";
294 const char* SIGNAL_KEY_INPUT_FOCUS_GAINED = "keyInputFocusGained";
295 const char* SIGNAL_KEY_INPUT_FOCUS_LOST = "keyInputFocusLost";
296 const char* SIGNAL_TAPPED = "tapped";
297 const char* SIGNAL_PANNED = "panned";
298 const char* SIGNAL_PINCHED = "pinched";
299 const char* SIGNAL_LONG_PRESSED = "longPressed";
300 const char* SIGNAL_GET_NAME = "getName";
301 const char* SIGNAL_GET_DESCRIPTION = "getDescription";
302 const char* SIGNAL_DO_GESTURE = "doGesture";
303 static bool DoConnectSignal(BaseObject* object, ConnectionTrackerInterface* tracker, const std::string& signalName, FunctorDelegate* functor)
305 Dali::BaseHandle handle(object);
307 bool connected(false);
308 Toolkit::Control control = Toolkit::Control::DownCast(handle);
311 Internal::Control& controlImpl(Internal::GetImplementation(control));
314 if(0 == strcmp(signalName.c_str(), SIGNAL_KEY_EVENT))
316 controlImpl.KeyEventSignal().Connect(tracker, functor);
318 else if(0 == strcmp(signalName.c_str(), SIGNAL_KEY_INPUT_FOCUS_GAINED))
320 controlImpl.KeyInputFocusGainedSignal().Connect(tracker, functor);
322 else if(0 == strcmp(signalName.c_str(), SIGNAL_KEY_INPUT_FOCUS_LOST))
324 controlImpl.KeyInputFocusLostSignal().Connect(tracker, functor);
326 else if(0 == strcmp(signalName.c_str(), SIGNAL_TAPPED))
328 controlImpl.EnableGestureDetection(GestureType::TAP);
329 controlImpl.GetTapGestureDetector().DetectedSignal().Connect(tracker, functor);
331 else if(0 == strcmp(signalName.c_str(), SIGNAL_PANNED))
333 controlImpl.EnableGestureDetection(GestureType::PAN);
334 controlImpl.GetPanGestureDetector().DetectedSignal().Connect(tracker, functor);
336 else if(0 == strcmp(signalName.c_str(), SIGNAL_PINCHED))
338 controlImpl.EnableGestureDetection(GestureType::PINCH);
339 controlImpl.GetPinchGestureDetector().DetectedSignal().Connect(tracker, functor);
341 else if(0 == strcmp(signalName.c_str(), SIGNAL_LONG_PRESSED))
343 controlImpl.EnableGestureDetection(GestureType::LONG_PRESS);
344 controlImpl.GetLongPressGestureDetector().DetectedSignal().Connect(tracker, functor);
346 else if(0 == strcmp(signalName.c_str(), SIGNAL_GET_NAME))
348 DevelControl::AccessibilityGetNameSignal(control).Connect(tracker, functor);
350 else if(0 == strcmp(signalName.c_str(), SIGNAL_GET_DESCRIPTION))
352 DevelControl::AccessibilityGetDescriptionSignal(control).Connect(tracker, functor);
354 else if(0 == strcmp(signalName.c_str(), SIGNAL_DO_GESTURE))
356 DevelControl::AccessibilityDoGestureSignal(control).Connect(tracker, functor);
363 * Creates control through type registry
367 return Internal::Control::New();
369 // Setup signals and actions using the type-registry.
370 DALI_TYPE_REGISTRATION_BEGIN(Control, CustomActor, Create);
372 // Note: Properties are registered separately below.
374 SignalConnectorType registerSignal1(typeRegistration, SIGNAL_KEY_EVENT, &DoConnectSignal);
375 SignalConnectorType registerSignal2(typeRegistration, SIGNAL_KEY_INPUT_FOCUS_GAINED, &DoConnectSignal);
376 SignalConnectorType registerSignal3(typeRegistration, SIGNAL_KEY_INPUT_FOCUS_LOST, &DoConnectSignal);
377 SignalConnectorType registerSignal4(typeRegistration, SIGNAL_TAPPED, &DoConnectSignal);
378 SignalConnectorType registerSignal5(typeRegistration, SIGNAL_PANNED, &DoConnectSignal);
379 SignalConnectorType registerSignal6(typeRegistration, SIGNAL_PINCHED, &DoConnectSignal);
380 SignalConnectorType registerSignal7(typeRegistration, SIGNAL_LONG_PRESSED, &DoConnectSignal);
381 SignalConnectorType registerSignal8(typeRegistration, SIGNAL_GET_NAME, &DoConnectSignal);
382 SignalConnectorType registerSignal9(typeRegistration, SIGNAL_GET_DESCRIPTION, &DoConnectSignal);
383 SignalConnectorType registerSignal10(typeRegistration, SIGNAL_DO_GESTURE, &DoConnectSignal);
385 TypeAction registerAction1(typeRegistration, "activate", &DoAction);
386 TypeAction registerAction2(typeRegistration, ACTION_ACCESSIBILITY_ACTIVATED, &DoAction);
387 TypeAction registerAction3(typeRegistration, ACTION_ACCESSIBILITY_READING_SKIPPED, &DoAction);
388 TypeAction registerAction4(typeRegistration, ACTION_ACCESSIBILITY_READING_CANCELLED, &DoAction);
389 TypeAction registerAction5(typeRegistration, ACTION_ACCESSIBILITY_READING_STOPPED, &DoAction);
390 TypeAction registerAction6(typeRegistration, ACTION_ACCESSIBILITY_READING_PAUSED, &DoAction);
391 TypeAction registerAction7(typeRegistration, ACTION_ACCESSIBILITY_READING_RESUMED, &DoAction);
393 DALI_TYPE_REGISTRATION_END()
396 * @brief Iterate through given container and setOffScene any visual found
398 * @param[in] container Container of visuals
399 * @param[in] parent Parent actor to remove visuals from
401 void SetVisualsOffScene(const RegisteredVisualContainer& container, Actor parent)
403 for(auto iter = container.Begin(), end = container.End(); iter != end; iter++)
407 DALI_LOG_INFO(gLogFilter, Debug::Verbose, "Control::SetOffScene Setting visual(%d) off stage\n", (*iter)->index);
408 Toolkit::GetImplementation((*iter)->visual).SetOffScene(parent);
413 Dali::Rect<> GetShowingGeometry(Dali::Rect<> rect, Dali::Toolkit::DevelControl::AccessibleImpl* accessibleImpl)
416 Vector2 currentPosition;
417 auto parent = dynamic_cast<Toolkit::DevelControl::AccessibleImpl*>(accessibleImpl->GetParent());
421 parentRect = parent->GetExtents(Dali::Accessibility::CoordinateType::WINDOW);
423 currentPosition.x = rect.x;
424 currentPosition.y = rect.y;
426 rect.x = rect.x > parentRect.x ? rect.x : parentRect.x;
427 rect.y = rect.y > parentRect.y ? rect.y : parentRect.y;
428 rect.width = currentPosition.x + rect.width < parentRect.x + parentRect.width ? currentPosition.x + rect.width - rect.x : parentRect.x + parentRect.width - rect.x;
429 rect.height = currentPosition.y + rect.height < parentRect.y + parentRect.height ? currentPosition.y + rect.height - rect.y : parentRect.y + parentRect.height - rect.y;
431 if(rect.width < 0 || rect.height < 0)
436 parent = dynamic_cast<Toolkit::DevelControl::AccessibleImpl*>(parent->GetParent());
442 } // unnamed namespace
445 // Properties registered without macro to use specific member variables.
446 const PropertyRegistration Control::Impl::PROPERTY_1(typeRegistration, "styleName", Toolkit::Control::Property::STYLE_NAME, Property::STRING, &Control::Impl::SetProperty, &Control::Impl::GetProperty);
447 const PropertyRegistration Control::Impl::PROPERTY_4(typeRegistration, "keyInputFocus", Toolkit::Control::Property::KEY_INPUT_FOCUS, Property::BOOLEAN, &Control::Impl::SetProperty, &Control::Impl::GetProperty);
448 const PropertyRegistration Control::Impl::PROPERTY_5(typeRegistration, "background", Toolkit::Control::Property::BACKGROUND, Property::MAP, &Control::Impl::SetProperty, &Control::Impl::GetProperty);
449 const PropertyRegistration Control::Impl::PROPERTY_6(typeRegistration, "margin", Toolkit::Control::Property::MARGIN, Property::EXTENTS, &Control::Impl::SetProperty, &Control::Impl::GetProperty);
450 const PropertyRegistration Control::Impl::PROPERTY_7(typeRegistration, "padding", Toolkit::Control::Property::PADDING, Property::EXTENTS, &Control::Impl::SetProperty, &Control::Impl::GetProperty);
451 const PropertyRegistration Control::Impl::PROPERTY_8(typeRegistration, "tooltip", Toolkit::DevelControl::Property::TOOLTIP, Property::MAP, &Control::Impl::SetProperty, &Control::Impl::GetProperty);
452 const PropertyRegistration Control::Impl::PROPERTY_9(typeRegistration, "state", Toolkit::DevelControl::Property::STATE, Property::STRING, &Control::Impl::SetProperty, &Control::Impl::GetProperty);
453 const PropertyRegistration Control::Impl::PROPERTY_10(typeRegistration, "subState", Toolkit::DevelControl::Property::SUB_STATE, Property::STRING, &Control::Impl::SetProperty, &Control::Impl::GetProperty);
454 const PropertyRegistration Control::Impl::PROPERTY_11(typeRegistration, "leftFocusableActorId", Toolkit::DevelControl::Property::LEFT_FOCUSABLE_ACTOR_ID, Property::INTEGER, &Control::Impl::SetProperty, &Control::Impl::GetProperty);
455 const PropertyRegistration Control::Impl::PROPERTY_12(typeRegistration, "rightFocusableActorId", Toolkit::DevelControl::Property::RIGHT_FOCUSABLE_ACTOR_ID, Property::INTEGER, &Control::Impl::SetProperty, &Control::Impl::GetProperty);
456 const PropertyRegistration Control::Impl::PROPERTY_13(typeRegistration, "upFocusableActorId", Toolkit::DevelControl::Property::UP_FOCUSABLE_ACTOR_ID, Property::INTEGER, &Control::Impl::SetProperty, &Control::Impl::GetProperty);
457 const PropertyRegistration Control::Impl::PROPERTY_14(typeRegistration, "downFocusableActorId", Toolkit::DevelControl::Property::DOWN_FOCUSABLE_ACTOR_ID, Property::INTEGER, &Control::Impl::SetProperty, &Control::Impl::GetProperty);
458 const PropertyRegistration Control::Impl::PROPERTY_15(typeRegistration, "shadow", Toolkit::DevelControl::Property::SHADOW, Property::MAP, &Control::Impl::SetProperty, &Control::Impl::GetProperty);
459 const PropertyRegistration Control::Impl::PROPERTY_16(typeRegistration, "accessibilityName", Toolkit::DevelControl::Property::ACCESSIBILITY_NAME, Property::STRING, &Control::Impl::SetProperty, &Control::Impl::GetProperty);
460 const PropertyRegistration Control::Impl::PROPERTY_17(typeRegistration, "accessibilityDescription", Toolkit::DevelControl::Property::ACCESSIBILITY_DESCRIPTION, Property::STRING, &Control::Impl::SetProperty, &Control::Impl::GetProperty);
461 const PropertyRegistration Control::Impl::PROPERTY_18(typeRegistration, "accessibilityTranslationDomain", Toolkit::DevelControl::Property::ACCESSIBILITY_TRANSLATION_DOMAIN, Property::STRING, &Control::Impl::SetProperty, &Control::Impl::GetProperty);
462 const PropertyRegistration Control::Impl::PROPERTY_19(typeRegistration, "accessibilityRole", Toolkit::DevelControl::Property::ACCESSIBILITY_ROLE, Property::INTEGER, &Control::Impl::SetProperty, &Control::Impl::GetProperty);
463 const PropertyRegistration Control::Impl::PROPERTY_20(typeRegistration, "accessibilityHighlightable", Toolkit::DevelControl::Property::ACCESSIBILITY_HIGHLIGHTABLE, Property::BOOLEAN, &Control::Impl::SetProperty, &Control::Impl::GetProperty);
464 const PropertyRegistration Control::Impl::PROPERTY_21(typeRegistration, "accessibilityAttributes", Toolkit::DevelControl::Property::ACCESSIBILITY_ATTRIBUTES, Property::MAP, &Control::Impl::SetProperty, &Control::Impl::GetProperty);
467 Control::Impl::Impl(Control& controlImpl)
468 : mControlImpl(controlImpl),
469 mState(Toolkit::DevelControl::NORMAL),
471 mLeftFocusableActorId(-1),
472 mRightFocusableActorId(-1),
473 mUpFocusableActorId(-1),
474 mDownFocusableActorId(-1),
476 mBackgroundColor(Color::TRANSPARENT),
477 mStartingPinchScale(nullptr),
479 mPadding(0, 0, 0, 0),
481 mKeyInputFocusGainedSignal(),
482 mKeyInputFocusLostSignal(),
483 mResourceReadySignal(),
484 mVisualEventSignal(),
485 mAccessibilityGetNameSignal(),
486 mAccessibilityGetDescriptionSignal(),
487 mAccessibilityDoGestureSignal(),
488 mPinchGestureDetector(),
489 mPanGestureDetector(),
490 mTapGestureDetector(),
491 mLongPressGestureDetector(),
493 mInputMethodContext(),
494 mIdleCallback(nullptr),
495 mFlags(Control::ControlBehaviour(CONTROL_BEHAVIOUR_DEFAULT)),
496 mIsKeyboardNavigationSupported(false),
497 mIsKeyboardFocusGroup(false),
498 mIsEmittingResourceReadySignal(false),
499 mNeedToEmitResourceReady(false)
501 Dali::Accessibility::Accessible::RegisterControlAccessibilityGetter(
502 [](Dali::Actor actor) -> Dali::Accessibility::Accessible* {
503 return Control::Impl::GetAccessibilityObject(actor);
506 mAccessibilityConstructor = [](Dali::Actor actor) -> std::unique_ptr<Dali::Accessibility::Accessible> {
507 return std::unique_ptr<Dali::Accessibility::Accessible>(new DevelControl::AccessibleImpl(actor, Dali::Accessibility::Role::UNKNOWN));
510 size_t length = static_cast<size_t>(Dali::Accessibility::RelationType::MAX_COUNT);
511 mAccessibilityRelations.reserve(length);
512 for(auto i = 0u; i < length; ++i)
514 mAccessibilityRelations.push_back({});
518 Control::Impl::~Impl()
520 for(auto&& iter : mVisuals)
522 StopObservingVisual(iter->visual);
525 for(auto&& iter : mRemoveVisuals)
527 StopObservingVisual(iter->visual);
530 // All gesture detectors will be destroyed so no need to disconnect.
531 delete mStartingPinchScale;
533 if(mIdleCallback && Adaptor::IsAvailable())
535 // Removes the callback from the callback manager in case the control is destroyed before the callback is executed.
536 Adaptor::Get().RemoveIdle(mIdleCallback);
540 Control::Impl& Control::Impl::Get(Internal::Control& internalControl)
542 return *internalControl.mImpl;
545 const Control::Impl& Control::Impl::Get(const Internal::Control& internalControl)
547 return *internalControl.mImpl;
550 void Control::Impl::CheckHighlightedObjectGeometry(PropertyNotification& propertyNotification)
552 auto accessibleImpl = dynamic_cast<Dali::Toolkit::DevelControl::AccessibleImpl*>(mAccessibilityObject.get());
555 DALI_LOG_ERROR("accessibleImpl is not a pointer to a DevelControl::AccessibleImpl type");
559 auto lastPosition = accessibleImpl->GetLastPosition();
560 auto accessibleRect = accessibleImpl->GetExtents(Dali::Accessibility::CoordinateType::WINDOW);
562 if(lastPosition.x == accessibleRect.x && lastPosition.y == accessibleRect.y)
567 auto rect = GetShowingGeometry(accessibleRect, accessibleImpl);
569 // MoveOuted is sent already, no need to send it again
570 if(mAccessibilityMovedOutOfScreenDirection != Dali::Accessibility::MovedOutOfScreenType::NONE)
572 if(rect.width > 0 && rect.height > 0)
574 // flick next does not use MoveOuted - ScrollToSelf makes object show, so reset for sending MoveOuted next
575 mAccessibilityMovedOutOfScreenDirection = Dali::Accessibility::MovedOutOfScreenType::NONE;
582 mAccessibilityMovedOutOfScreenDirection = (accessibleRect.x < lastPosition.x) ? Dali::Accessibility::MovedOutOfScreenType::TOP_LEFT : Dali::Accessibility::MovedOutOfScreenType::BOTTOM_RIGHT;
587 mAccessibilityMovedOutOfScreenDirection = (accessibleRect.y < lastPosition.y) ? Dali::Accessibility::MovedOutOfScreenType::TOP_LEFT : Dali::Accessibility::MovedOutOfScreenType::BOTTOM_RIGHT;
590 if(mAccessibilityMovedOutOfScreenDirection != Dali::Accessibility::MovedOutOfScreenType::NONE)
592 mAccessibilityObject.get()->EmitMovedOutOfScreen(mAccessibilityMovedOutOfScreenDirection);
593 accessibleImpl->SetLastPosition(Vector2(0.0f, 0.0f));
597 accessibleImpl->SetLastPosition(Vector2(accessibleRect.x, accessibleRect.y));
600 void Control::Impl::RegisterAccessibilityPositionPropertyNotification()
602 if(mIsAccessibilityPositionPropertyNotificationSet)
607 mAccessibilityMovedOutOfScreenDirection = Dali::Accessibility::MovedOutOfScreenType::NONE;
608 mAccessibilityPositionNotification = mControlImpl.Self().AddPropertyNotification(Actor::Property::WORLD_POSITION, StepCondition(1.0f, 1.0f));
609 mAccessibilityPositionNotification.SetNotifyMode(PropertyNotification::NOTIFY_ON_CHANGED);
610 mAccessibilityPositionNotification.NotifySignal().Connect(this, &Control::Impl::CheckHighlightedObjectGeometry);
611 mIsAccessibilityPositionPropertyNotificationSet = true;
614 void Control::Impl::UnregisterAccessibilityPositionPropertyNotification()
616 mControlImpl.Self().RemovePropertyNotification(mAccessibilityPositionNotification);
617 mIsAccessibilityPositionPropertyNotificationSet = false;
620 // Gesture Detection Methods
621 void Control::Impl::PinchDetected(Actor actor, const PinchGesture& pinch)
623 mControlImpl.OnPinch(pinch);
626 void Control::Impl::PanDetected(Actor actor, const PanGesture& pan)
628 mControlImpl.OnPan(pan);
631 void Control::Impl::TapDetected(Actor actor, const TapGesture& tap)
633 mControlImpl.OnTap(tap);
636 void Control::Impl::LongPressDetected(Actor actor, const LongPressGesture& longPress)
638 mControlImpl.OnLongPress(longPress);
641 void Control::Impl::RegisterVisual(Property::Index index, Toolkit::Visual::Base& visual)
643 RegisterVisual(index, visual, VisualState::ENABLED, DepthIndexValue::NOT_SET);
646 void Control::Impl::RegisterVisual(Property::Index index, Toolkit::Visual::Base& visual, int depthIndex)
648 RegisterVisual(index, visual, VisualState::ENABLED, DepthIndexValue::SET, depthIndex);
651 void Control::Impl::RegisterVisual(Property::Index index, Toolkit::Visual::Base& visual, bool enabled)
653 RegisterVisual(index, visual, (enabled ? VisualState::ENABLED : VisualState::DISABLED), DepthIndexValue::NOT_SET);
656 void Control::Impl::RegisterVisual(Property::Index index, Toolkit::Visual::Base& visual, bool enabled, int depthIndex)
658 RegisterVisual(index, visual, (enabled ? VisualState::ENABLED : VisualState::DISABLED), DepthIndexValue::SET, depthIndex);
661 void Control::Impl::RegisterVisual(Property::Index index, Toolkit::Visual::Base& visual, VisualState::Type enabled, DepthIndexValue::Type depthIndexValueSet, int depthIndex)
663 DALI_LOG_INFO(gLogFilter, Debug::Concise, "RegisterVisual:%d \n", index);
665 bool visualReplaced(false);
666 Actor self = mControlImpl.Self();
668 // Set the depth index, if not set by caller this will be either the current visual depth, max depth of all visuals
670 int requiredDepthIndex = visual.GetDepthIndex();
672 if(depthIndexValueSet == DepthIndexValue::SET)
674 requiredDepthIndex = depthIndex;
677 // Visual replacement, existing visual should only be removed from stage when replacement ready.
678 if(!mVisuals.Empty())
680 RegisteredVisualContainer::Iterator registeredVisualsiter;
681 // Check if visual (index) is already registered, this is the current visual.
682 if(FindVisual(index, mVisuals, registeredVisualsiter))
684 Toolkit::Visual::Base& currentRegisteredVisual = (*registeredVisualsiter)->visual;
685 if(currentRegisteredVisual)
687 // Store current visual depth index as may need to set the replacement visual to same depth
688 const int currentDepthIndex = (*registeredVisualsiter)->visual.GetDepthIndex();
690 // No longer required to know if the replaced visual's resources are ready
691 StopObservingVisual(currentRegisteredVisual);
693 // If control staged and visual enabled then visuals will be swapped once ready
694 if(self.GetProperty<bool>(Actor::Property::CONNECTED_TO_SCENE) && enabled)
696 // Check if visual is currently in the process of being replaced ( is in removal container )
697 RegisteredVisualContainer::Iterator visualQueuedForRemoval;
698 if(FindVisual(index, mRemoveVisuals, visualQueuedForRemoval))
700 // Visual with same index is already in removal container so current visual pending
701 // Only the the last requested visual will be displayed so remove current visual which is staged but not ready.
702 Toolkit::GetImplementation(currentRegisteredVisual).SetOffScene(self);
703 mVisuals.Erase(registeredVisualsiter);
707 // current visual not already in removal container so add now.
708 DALI_LOG_INFO(gLogFilter, Debug::Verbose, "RegisterVisual Move current registered visual to removal Queue: %d \n", index);
709 MoveVisual(registeredVisualsiter, mVisuals, mRemoveVisuals);
714 // Control not staged or visual disabled so can just erase from registered visuals and new visual will be added later.
715 mVisuals.Erase(registeredVisualsiter);
718 // 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
719 if((depthIndexValueSet == DepthIndexValue::NOT_SET) &&
720 (visual.GetDepthIndex() == 0))
722 requiredDepthIndex = currentDepthIndex;
726 visualReplaced = true;
730 // If not set, set the name of the visual to the same name as the control's property.
731 // ( If the control has been type registered )
732 if(visual.GetName().empty())
734 // returns empty string if index is not found as long as index is not -1
735 std::string visualName = self.GetPropertyName(index);
736 if(!visualName.empty())
738 DALI_LOG_INFO(gLogFilter, Debug::Concise, "Setting visual name for property %d to %s\n", index, visualName.c_str());
739 visual.SetName(visualName);
743 if(!visualReplaced) // New registration entry
745 // 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
746 if((depthIndexValueSet == DepthIndexValue::NOT_SET) &&
747 (mVisuals.Size() > 0) &&
748 (visual.GetDepthIndex() == 0))
750 int maxDepthIndex = std::numeric_limits<int>::min();
752 RegisteredVisualContainer::ConstIterator iter;
753 const RegisteredVisualContainer::ConstIterator endIter = mVisuals.End();
754 for(iter = mVisuals.Begin(); iter != endIter; iter++)
756 const int visualDepthIndex = (*iter)->visual.GetDepthIndex();
757 if(visualDepthIndex > maxDepthIndex)
759 maxDepthIndex = visualDepthIndex;
762 ++maxDepthIndex; // Add one to the current maximum depth index so that our added visual appears on top
763 requiredDepthIndex = std::max(0, maxDepthIndex); // Start at zero if maxDepth index belongs to a background
769 // Set determined depth index
770 visual.SetDepthIndex(requiredDepthIndex);
772 // Monitor when the visual resources are ready
773 StartObservingVisual(visual);
775 DALI_LOG_INFO(gLogFilter, Debug::Concise, "New Visual registration index[%d] depth[%d]\n", index, requiredDepthIndex);
776 RegisteredVisual* newRegisteredVisual = new RegisteredVisual(index, visual, (enabled == VisualState::ENABLED ? true : false), (visualReplaced && enabled));
777 mVisuals.PushBack(newRegisteredVisual);
779 Internal::Visual::Base& visualImpl = Toolkit::GetImplementation(visual);
780 // Put on stage if enabled and the control is already on the stage
781 if((enabled == VisualState::ENABLED) && self.GetProperty<bool>(Actor::Property::CONNECTED_TO_SCENE))
783 visualImpl.SetOnScene(self);
785 else if(visualImpl.IsResourceReady()) // When not being staged, check if visual already 'ResourceReady' before it was Registered. ( Resource may have been loaded already )
787 ResourceReady(visualImpl);
791 DALI_LOG_INFO(gLogFilter, Debug::Verbose, "Control::RegisterVisual() Registered %s(%d), enabled:%s\n", visual.GetName().c_str(), index, enabled ? "true" : "false");
794 void Control::Impl::UnregisterVisual(Property::Index index)
796 RegisteredVisualContainer::Iterator iter;
797 if(FindVisual(index, mVisuals, iter))
799 // stop observing visual
800 StopObservingVisual((*iter)->visual);
802 Actor self(mControlImpl.Self());
803 Toolkit::GetImplementation((*iter)->visual).SetOffScene(self);
804 (*iter)->visual.Reset();
805 mVisuals.Erase(iter);
808 if(FindVisual(index, mRemoveVisuals, iter))
810 Actor self(mControlImpl.Self());
811 Toolkit::GetImplementation((*iter)->visual).SetOffScene(self);
812 (*iter)->pending = false;
813 (*iter)->visual.Reset();
814 mRemoveVisuals.Erase(iter);
818 Toolkit::Visual::Base Control::Impl::GetVisual(Property::Index index) const
820 RegisteredVisualContainer::Iterator iter;
821 if(FindVisual(index, mVisuals, iter))
823 return (*iter)->visual;
826 return Toolkit::Visual::Base();
829 void Control::Impl::EnableVisual(Property::Index index, bool enable)
831 DALI_LOG_INFO(gLogFilter, Debug::General, "Control::EnableVisual(%d, %s)\n", index, enable ? "T" : "F");
833 RegisteredVisualContainer::Iterator iter;
834 if(FindVisual(index, mVisuals, iter))
836 if((*iter)->enabled == enable)
838 DALI_LOG_INFO(gLogFilter, Debug::Verbose, "Control::EnableVisual Visual %s(%d) already %s\n", (*iter)->visual.GetName().c_str(), index, enable ? "enabled" : "disabled");
842 (*iter)->enabled = enable;
843 Actor parentActor = mControlImpl.Self();
844 if(mControlImpl.Self().GetProperty<bool>(Actor::Property::CONNECTED_TO_SCENE)) // If control not on Scene then Visual will be added when SceneConnection is called.
848 DALI_LOG_INFO(gLogFilter, Debug::Verbose, "Control::EnableVisual Setting %s(%d) on stage \n", (*iter)->visual.GetName().c_str(), index);
849 Toolkit::GetImplementation((*iter)->visual).SetOnScene(parentActor);
853 DALI_LOG_INFO(gLogFilter, Debug::Verbose, "Control::EnableVisual Setting %s(%d) off stage \n", (*iter)->visual.GetName().c_str(), index);
854 Toolkit::GetImplementation((*iter)->visual).SetOffScene(parentActor); // No need to call if control not staged.
860 DALI_LOG_WARNING("Control::EnableVisual(%d, %s) FAILED - NO SUCH VISUAL\n", index, enable ? "T" : "F");
864 bool Control::Impl::IsVisualEnabled(Property::Index index) const
866 RegisteredVisualContainer::Iterator iter;
867 if(FindVisual(index, mVisuals, iter))
869 return (*iter)->enabled;
874 void Control::Impl::StopObservingVisual(Toolkit::Visual::Base& visual)
876 Internal::Visual::Base& visualImpl = Toolkit::GetImplementation(visual);
878 // Stop observing the visual
879 visualImpl.RemoveEventObserver(*this);
882 void Control::Impl::StartObservingVisual(Toolkit::Visual::Base& visual)
884 Internal::Visual::Base& visualImpl = Toolkit::GetImplementation(visual);
886 // start observing the visual for events
887 visualImpl.AddEventObserver(*this);
890 // Called by a Visual when it's resource is ready
891 void Control::Impl::ResourceReady(Visual::Base& object)
893 DALI_LOG_INFO(gLogFilter, Debug::Verbose, "Control::Impl::ResourceReady() replacements pending[%d]\n", mRemoveVisuals.Count());
895 Actor self = mControlImpl.Self();
897 // A resource is ready, find resource in the registered visuals container and get its index
898 for(auto registeredIter = mVisuals.Begin(), end = mVisuals.End(); registeredIter != end; ++registeredIter)
900 Internal::Visual::Base& registeredVisualImpl = Toolkit::GetImplementation((*registeredIter)->visual);
902 if(&object == ®isteredVisualImpl)
904 RegisteredVisualContainer::Iterator visualToRemoveIter;
905 // Find visual with the same index in the removal container
906 // Set if off stage as it's replacement is now ready.
907 // Remove if from removal list as now removed from stage.
908 // Set Pending flag on the ready visual to false as now ready.
909 if(FindVisual((*registeredIter)->index, mRemoveVisuals, visualToRemoveIter))
911 (*registeredIter)->pending = false;
912 Toolkit::GetImplementation((*visualToRemoveIter)->visual).SetOffScene(self);
913 mRemoveVisuals.Erase(visualToRemoveIter);
919 // A visual is ready so control may need relayouting if staged
920 if(self.GetProperty<bool>(Actor::Property::CONNECTED_TO_SCENE))
922 mControlImpl.RelayoutRequest();
925 // Emit signal if all enabled visuals registered by the control are ready.
926 if(IsResourceReady())
929 mNeedToEmitResourceReady = false;
931 EmitResourceReadySignal();
935 void Control::Impl::NotifyVisualEvent(Visual::Base& object, Property::Index signalId)
937 for(auto registeredIter = mVisuals.Begin(), end = mVisuals.End(); registeredIter != end; ++registeredIter)
939 Internal::Visual::Base& registeredVisualImpl = Toolkit::GetImplementation((*registeredIter)->visual);
940 if(&object == ®isteredVisualImpl)
942 Dali::Toolkit::Control handle(mControlImpl.GetOwner());
943 mVisualEventSignal.Emit(handle, (*registeredIter)->index, signalId);
949 bool Control::Impl::IsResourceReady() const
951 // Iterate through and check all the enabled visuals are ready
952 for(auto visualIter = mVisuals.Begin();
953 visualIter != mVisuals.End();
956 const Toolkit::Visual::Base visual = (*visualIter)->visual;
957 const Internal::Visual::Base& visualImpl = Toolkit::GetImplementation(visual);
959 // one of the enabled visuals is not ready
960 if(!visualImpl.IsResourceReady() && (*visualIter)->enabled)
968 Toolkit::Visual::ResourceStatus Control::Impl::GetVisualResourceStatus(Property::Index index) const
970 RegisteredVisualContainer::Iterator iter;
971 if(FindVisual(index, mVisuals, iter))
973 const Toolkit::Visual::Base visual = (*iter)->visual;
974 const Internal::Visual::Base& visualImpl = Toolkit::GetImplementation(visual);
975 return visualImpl.GetResourceStatus();
978 return Toolkit::Visual::ResourceStatus::PREPARING;
981 void Control::Impl::AddTransitions(Dali::Animation& animation,
982 const Toolkit::TransitionData& handle,
983 bool createAnimation)
985 // Setup a Transition from TransitionData.
986 const Internal::TransitionData& transitionData = Toolkit::GetImplementation(handle);
987 TransitionData::Iterator end = transitionData.End();
988 for(TransitionData::Iterator iter = transitionData.Begin();
992 TransitionData::Animator* animator = (*iter);
994 Toolkit::Visual::Base visual = GetVisualByName(mVisuals, animator->objectName);
998 #if defined(DEBUG_ENABLED)
999 Dali::TypeInfo typeInfo;
1000 ControlWrapper* controlWrapperImpl = dynamic_cast<ControlWrapper*>(&mControlImpl);
1001 if(controlWrapperImpl)
1003 typeInfo = controlWrapperImpl->GetTypeInfo();
1006 DALI_LOG_INFO(gLogFilter, Debug::Concise, "CreateTransition: Found %s visual for %s\n", visual.GetName().c_str(), typeInfo ? typeInfo.GetName().c_str() : "Unknown");
1008 Internal::Visual::Base& visualImpl = Toolkit::GetImplementation(visual);
1009 visualImpl.AnimateProperty(animation, *animator);
1013 DALI_LOG_INFO(gLogFilter, Debug::Concise, "CreateTransition: Could not find visual. Trying actors");
1014 // Otherwise, try any actor children of control (Including the control)
1015 Actor child = mControlImpl.Self().FindChildByName(animator->objectName);
1018 Property::Index propertyIndex = child.GetPropertyIndex(animator->propertyKey);
1019 if(propertyIndex != Property::INVALID_INDEX)
1021 if(animator->animate == false)
1023 if(animator->targetValue.GetType() != Property::NONE)
1025 child.SetProperty(propertyIndex, animator->targetValue);
1028 else // animate the property
1030 if(animator->initialValue.GetType() != Property::NONE)
1032 child.SetProperty(propertyIndex, animator->initialValue);
1035 if(createAnimation && !animation)
1037 animation = Dali::Animation::New(0.1f);
1040 animation.AnimateTo(Property(child, propertyIndex),
1041 animator->targetValue,
1042 animator->alphaFunction,
1043 TimePeriod(animator->timePeriodDelay,
1044 animator->timePeriodDuration));
1052 Dali::Animation Control::Impl::CreateTransition(const Toolkit::TransitionData& transitionData)
1054 Dali::Animation transition;
1056 if(transitionData.Count() > 0)
1058 AddTransitions(transition, transitionData, true);
1063 void Control::Impl::DoAction(Dali::Property::Index visualIndex, Dali::Property::Index actionId, const Dali::Property::Value attributes)
1065 RegisteredVisualContainer::Iterator iter;
1066 if(FindVisual(visualIndex, mVisuals, iter))
1068 Toolkit::GetImplementation((*iter)->visual).DoAction(actionId, attributes);
1072 void Control::Impl::AppendAccessibilityAttribute(const std::string& key, const std::string value)
1074 Property::Value* checkedValue = mAccessibilityAttributes.Find(key);
1077 mAccessibilityAttributes[key] = Property::Value(value);
1081 mAccessibilityAttributes.Insert(key, value);
1085 void Control::Impl::SetProperty(BaseObject* object, Property::Index index, const Property::Value& value)
1087 Toolkit::Control control = Toolkit::Control::DownCast(BaseHandle(object));
1091 Control& controlImpl(GetImplementation(control));
1095 case Toolkit::Control::Property::STYLE_NAME:
1097 controlImpl.SetStyleName(value.Get<std::string>());
1101 case Toolkit::DevelControl::Property::STATE:
1103 bool withTransitions = true;
1104 const Property::Value* valuePtr = &value;
1105 const Property::Map* map = value.GetMap();
1108 Property::Value* value2 = map->Find("withTransitions");
1111 withTransitions = value2->Get<bool>();
1114 valuePtr = map->Find("state");
1119 Toolkit::DevelControl::State state(controlImpl.mImpl->mState);
1120 if(Scripting::GetEnumerationProperty<Toolkit::DevelControl::State>(*valuePtr, ControlStateTable, ControlStateTableCount, state))
1122 controlImpl.mImpl->SetState(state, withTransitions);
1128 case Toolkit::DevelControl::Property::SUB_STATE:
1130 std::string subState;
1131 if(value.Get(subState))
1133 controlImpl.mImpl->SetSubState(subState);
1138 case Toolkit::DevelControl::Property::LEFT_FOCUSABLE_ACTOR_ID:
1141 if(value.Get(focusId))
1143 controlImpl.mImpl->mLeftFocusableActorId = focusId;
1148 case Toolkit::DevelControl::Property::RIGHT_FOCUSABLE_ACTOR_ID:
1151 if(value.Get(focusId))
1153 controlImpl.mImpl->mRightFocusableActorId = focusId;
1158 case Toolkit::DevelControl::Property::UP_FOCUSABLE_ACTOR_ID:
1161 if(value.Get(focusId))
1163 controlImpl.mImpl->mUpFocusableActorId = focusId;
1168 case Toolkit::DevelControl::Property::DOWN_FOCUSABLE_ACTOR_ID:
1171 if(value.Get(focusId))
1173 controlImpl.mImpl->mDownFocusableActorId = focusId;
1178 case Toolkit::Control::Property::KEY_INPUT_FOCUS:
1180 if(value.Get<bool>())
1182 controlImpl.SetKeyInputFocus();
1186 controlImpl.ClearKeyInputFocus();
1191 case Toolkit::Control::Property::BACKGROUND:
1195 const Property::Map* map = value.GetMap();
1196 if(map && !map->Empty())
1198 controlImpl.SetBackground(*map);
1200 else if(value.Get(url))
1202 // don't know the size to load
1203 Toolkit::Visual::Base visual = Toolkit::VisualFactory::Get().CreateVisual(url, ImageDimensions());
1206 controlImpl.mImpl->RegisterVisual(Toolkit::Control::Property::BACKGROUND, visual, DepthIndex::BACKGROUND);
1209 else if(value.Get(color))
1211 controlImpl.SetBackgroundColor(color);
1215 // The background is an empty property map, so we should clear the background
1216 controlImpl.ClearBackground();
1221 case Toolkit::Control::Property::MARGIN:
1224 if(value.Get(margin))
1226 controlImpl.mImpl->SetMargin(margin);
1231 case Toolkit::Control::Property::PADDING:
1234 if(value.Get(padding))
1236 controlImpl.mImpl->SetPadding(padding);
1241 case Toolkit::DevelControl::Property::TOOLTIP:
1243 TooltipPtr& tooltipPtr = controlImpl.mImpl->mTooltip;
1246 tooltipPtr = Tooltip::New(control);
1248 tooltipPtr->SetProperties(value);
1252 case Toolkit::DevelControl::Property::SHADOW:
1254 const Property::Map* map = value.GetMap();
1255 if(map && !map->Empty())
1257 controlImpl.mImpl->SetShadow(*map);
1261 // The shadow is an empty property map, so we should clear the shadow
1262 controlImpl.mImpl->ClearShadow();
1267 case Toolkit::DevelControl::Property::ACCESSIBILITY_NAME:
1272 controlImpl.mImpl->mAccessibilityName = name;
1273 controlImpl.mImpl->mAccessibilityNameSet = true;
1277 controlImpl.mImpl->mAccessibilityNameSet = false;
1282 case Toolkit::DevelControl::Property::ACCESSIBILITY_DESCRIPTION:
1287 controlImpl.mImpl->mAccessibilityDescription = text;
1288 controlImpl.mImpl->mAccessibilityDescriptionSet = true;
1292 controlImpl.mImpl->mAccessibilityDescriptionSet = false;
1297 case Toolkit::DevelControl::Property::ACCESSIBILITY_TRANSLATION_DOMAIN:
1302 controlImpl.mImpl->mAccessibilityTranslationDomain = text;
1303 controlImpl.mImpl->mAccessibilityTranslationDomainSet = true;
1307 controlImpl.mImpl->mAccessibilityTranslationDomainSet = false;
1312 case Toolkit::DevelControl::Property::ACCESSIBILITY_ROLE:
1314 Dali::Accessibility::Role role;
1317 controlImpl.mImpl->mAccessibilityRole = role;
1322 case Toolkit::DevelControl::Property::ACCESSIBILITY_HIGHLIGHTABLE:
1325 if(value.Get(highlightable))
1327 controlImpl.mImpl->mAccessibilityHighlightable = highlightable;
1328 controlImpl.mImpl->mAccessibilityHighlightableSet = true;
1332 controlImpl.mImpl->mAccessibilityHighlightableSet = false;
1337 case Toolkit::DevelControl::Property::ACCESSIBILITY_ATTRIBUTES:
1339 const Property::Map* map = value.GetMap();
1340 if(map && !map->Empty())
1342 controlImpl.mImpl->mAccessibilityAttributes = *map;
1350 Property::Value Control::Impl::GetProperty(BaseObject* object, Property::Index index)
1352 Property::Value value;
1354 Toolkit::Control control = Toolkit::Control::DownCast(BaseHandle(object));
1358 Control& controlImpl(GetImplementation(control));
1362 case Toolkit::Control::Property::STYLE_NAME:
1364 value = controlImpl.GetStyleName();
1368 case Toolkit::DevelControl::Property::STATE:
1370 value = controlImpl.mImpl->mState;
1374 case Toolkit::DevelControl::Property::SUB_STATE:
1376 value = controlImpl.mImpl->mSubStateName;
1380 case Toolkit::DevelControl::Property::LEFT_FOCUSABLE_ACTOR_ID:
1382 value = controlImpl.mImpl->mLeftFocusableActorId;
1386 case Toolkit::DevelControl::Property::RIGHT_FOCUSABLE_ACTOR_ID:
1388 value = controlImpl.mImpl->mRightFocusableActorId;
1392 case Toolkit::DevelControl::Property::UP_FOCUSABLE_ACTOR_ID:
1394 value = controlImpl.mImpl->mUpFocusableActorId;
1398 case Toolkit::DevelControl::Property::DOWN_FOCUSABLE_ACTOR_ID:
1400 value = controlImpl.mImpl->mDownFocusableActorId;
1404 case Toolkit::Control::Property::KEY_INPUT_FOCUS:
1406 value = controlImpl.HasKeyInputFocus();
1410 case Toolkit::Control::Property::BACKGROUND:
1413 Toolkit::Visual::Base visual = controlImpl.mImpl->GetVisual(Toolkit::Control::Property::BACKGROUND);
1416 visual.CreatePropertyMap(map);
1423 case Toolkit::Control::Property::MARGIN:
1425 value = controlImpl.mImpl->GetMargin();
1429 case Toolkit::Control::Property::PADDING:
1431 value = controlImpl.mImpl->GetPadding();
1435 case Toolkit::DevelControl::Property::TOOLTIP:
1438 if(controlImpl.mImpl->mTooltip)
1440 controlImpl.mImpl->mTooltip->CreatePropertyMap(map);
1446 case Toolkit::DevelControl::Property::SHADOW:
1449 Toolkit::Visual::Base visual = controlImpl.mImpl->GetVisual(Toolkit::DevelControl::Property::SHADOW);
1452 visual.CreatePropertyMap(map);
1459 case Toolkit::DevelControl::Property::ACCESSIBILITY_NAME:
1461 if(controlImpl.mImpl->mAccessibilityNameSet)
1463 value = controlImpl.mImpl->mAccessibilityName;
1468 case Toolkit::DevelControl::Property::ACCESSIBILITY_DESCRIPTION:
1470 if(controlImpl.mImpl->mAccessibilityDescriptionSet)
1472 value = controlImpl.mImpl->mAccessibilityDescription;
1477 case Toolkit::DevelControl::Property::ACCESSIBILITY_TRANSLATION_DOMAIN:
1479 if(controlImpl.mImpl->mAccessibilityTranslationDomainSet)
1481 value = controlImpl.mImpl->mAccessibilityTranslationDomain;
1486 case Toolkit::DevelControl::Property::ACCESSIBILITY_ROLE:
1488 value = Property::Value(controlImpl.mImpl->mAccessibilityRole);
1492 case Toolkit::DevelControl::Property::ACCESSIBILITY_HIGHLIGHTABLE:
1494 if(controlImpl.mImpl->mAccessibilityHighlightableSet)
1496 value = controlImpl.mImpl->mAccessibilityHighlightable;
1501 case Toolkit::DevelControl::Property::ACCESSIBILITY_ATTRIBUTES:
1503 value = controlImpl.mImpl->mAccessibilityAttributes;
1512 void Control::Impl::RemoveAccessibilityAttribute(const std::string& key)
1514 Property::Value* value = mAccessibilityAttributes.Find(key);
1517 mAccessibilityAttributes[key] = Property::Value();
1521 void Control::Impl::ClearAccessibilityAttributes()
1523 mAccessibilityAttributes.Clear();
1526 void Control::Impl::SetAccessibilityReadingInfoType(const Dali::Accessibility::ReadingInfoTypes types)
1528 std::string value{};
1529 if(types[Dali::Accessibility::ReadingInfoType::NAME])
1531 value += READING_INFO_TYPE_NAME;
1533 if(types[Dali::Accessibility::ReadingInfoType::ROLE])
1537 value += READING_INFO_TYPE_SEPARATOR;
1539 value += READING_INFO_TYPE_ROLE;
1541 if(types[Dali::Accessibility::ReadingInfoType::DESCRIPTION])
1545 value += READING_INFO_TYPE_SEPARATOR;
1547 value += READING_INFO_TYPE_DESCRIPTION;
1549 if(types[Dali::Accessibility::ReadingInfoType::STATE])
1553 value += READING_INFO_TYPE_SEPARATOR;
1555 value += READING_INFO_TYPE_STATE;
1557 AppendAccessibilityAttribute(READING_INFO_TYPE_ATTRIBUTE_NAME, value);
1560 Dali::Accessibility::ReadingInfoTypes Control::Impl::GetAccessibilityReadingInfoType() const
1562 std::string value{};
1563 auto place = mAccessibilityAttributes.Find(READING_INFO_TYPE_ATTRIBUTE_NAME);
1570 Dali::Accessibility::ReadingInfoTypes types;
1571 types[Dali::Accessibility::ReadingInfoType::NAME] = true;
1572 types[Dali::Accessibility::ReadingInfoType::ROLE] = true;
1573 types[Dali::Accessibility::ReadingInfoType::DESCRIPTION] = true;
1574 types[Dali::Accessibility::ReadingInfoType::STATE] = true;
1583 Dali::Accessibility::ReadingInfoTypes types;
1585 if(value.find(READING_INFO_TYPE_NAME) != std::string::npos)
1587 types[Dali::Accessibility::ReadingInfoType::NAME] = true;
1589 if(value.find(READING_INFO_TYPE_ROLE) != std::string::npos)
1591 types[Dali::Accessibility::ReadingInfoType::ROLE] = true;
1593 if(value.find(READING_INFO_TYPE_DESCRIPTION) != std::string::npos)
1595 types[Dali::Accessibility::ReadingInfoType::DESCRIPTION] = true;
1597 if(value.find(READING_INFO_TYPE_STATE) != std::string::npos)
1599 types[Dali::Accessibility::ReadingInfoType::STATE] = true;
1605 void Control::Impl::CopyInstancedProperties(RegisteredVisualContainer& visuals, Dictionary<Property::Map>& instancedProperties)
1607 for(RegisteredVisualContainer::Iterator iter = visuals.Begin(); iter != visuals.End(); iter++)
1611 Property::Map instanceMap;
1612 Toolkit::GetImplementation((*iter)->visual).CreateInstancePropertyMap(instanceMap);
1613 instancedProperties.Add((*iter)->visual.GetName(), instanceMap);
1618 void Control::Impl::RemoveVisual(RegisteredVisualContainer& visuals, const std::string& visualName)
1620 Actor self(mControlImpl.Self());
1622 for(RegisteredVisualContainer::Iterator visualIter = visuals.Begin();
1623 visualIter != visuals.End();
1626 Toolkit::Visual::Base visual = (*visualIter)->visual;
1627 if(visual && visual.GetName() == visualName)
1629 Toolkit::GetImplementation(visual).SetOffScene(self);
1630 (*visualIter)->visual.Reset();
1631 visuals.Erase(visualIter);
1637 void Control::Impl::RemoveVisuals(RegisteredVisualContainer& visuals, DictionaryKeys& removeVisuals)
1639 Actor self(mControlImpl.Self());
1640 for(DictionaryKeys::iterator iter = removeVisuals.begin(); iter != removeVisuals.end(); ++iter)
1642 const std::string visualName = *iter;
1643 RemoveVisual(visuals, visualName);
1647 void Control::Impl::RecreateChangedVisuals(Dictionary<Property::Map>& stateVisualsToChange,
1648 Dictionary<Property::Map>& instancedProperties)
1650 Dali::CustomActor handle(mControlImpl.GetOwner());
1651 for(Dictionary<Property::Map>::iterator iter = stateVisualsToChange.Begin();
1652 iter != stateVisualsToChange.End();
1655 const std::string& visualName = (*iter).key;
1656 const Property::Map& toMap = (*iter).entry;
1658 Actor self = mControlImpl.Self();
1659 RegisteredVisualContainer::Iterator registeredVisualsiter;
1660 // Check if visual (visualName) is already registered, this is the current visual.
1661 if(FindVisual(visualName, mVisuals, registeredVisualsiter))
1663 Toolkit::Visual::Base& visual = (*registeredVisualsiter)->visual;
1666 // No longer required to know if the replaced visual's resources are ready
1667 StopObservingVisual(visual);
1669 // If control staged then visuals will be swapped once ready
1670 if(self.GetProperty<bool>(Actor::Property::CONNECTED_TO_SCENE))
1672 // Check if visual is currently in the process of being replaced ( is in removal container )
1673 RegisteredVisualContainer::Iterator visualQueuedForRemoval;
1674 if(FindVisual(visualName, mRemoveVisuals, visualQueuedForRemoval))
1676 // Visual with same visual name is already in removal container so current visual pending
1677 // Only the the last requested visual will be displayed so remove current visual which is staged but not ready.
1678 Toolkit::GetImplementation(visual).SetOffScene(self);
1679 (*registeredVisualsiter)->visual.Reset();
1680 mVisuals.Erase(registeredVisualsiter);
1684 // current visual not already in removal container so add now.
1685 DALI_LOG_INFO(gLogFilter, Debug::Verbose, "RegisterVisual Move current registered visual to removal Queue: %s \n", visualName.c_str());
1686 MoveVisual(registeredVisualsiter, mVisuals, mRemoveVisuals);
1691 // Control not staged or visual disabled so can just erase from registered visuals and new visual will be added later.
1692 (*registeredVisualsiter)->visual.Reset();
1693 mVisuals.Erase(registeredVisualsiter);
1697 const Property::Map* instancedMap = instancedProperties.FindConst(visualName);
1698 Style::ApplyVisual(handle, visualName, toMap, instancedMap);
1703 void Control::Impl::ReplaceStateVisualsAndProperties(const StylePtr oldState, const StylePtr newState, const std::string& subState)
1705 // Collect all old visual names
1706 DictionaryKeys stateVisualsToRemove;
1709 oldState->visuals.GetKeys(stateVisualsToRemove);
1710 if(!subState.empty())
1712 const StylePtr* oldSubState = oldState->subStates.FindConst(subState);
1715 DictionaryKeys subStateVisualsToRemove;
1716 (*oldSubState)->visuals.GetKeys(subStateVisualsToRemove);
1717 Merge(stateVisualsToRemove, subStateVisualsToRemove);
1722 // Collect all new visual properties
1723 Dictionary<Property::Map> stateVisualsToAdd;
1726 stateVisualsToAdd = newState->visuals;
1727 if(!subState.empty())
1729 const StylePtr* newSubState = newState->subStates.FindConst(subState);
1732 stateVisualsToAdd.Merge((*newSubState)->visuals);
1737 // If a name is in both add/remove, move it to change list.
1738 Dictionary<Property::Map> stateVisualsToChange;
1739 FindChangableVisuals(stateVisualsToAdd, stateVisualsToChange, stateVisualsToRemove);
1741 // Copy instanced properties (e.g. text label) of current visuals
1742 Dictionary<Property::Map> instancedProperties;
1743 CopyInstancedProperties(mVisuals, instancedProperties);
1745 // For each visual in remove list, remove from mVisuals
1746 RemoveVisuals(mVisuals, stateVisualsToRemove);
1748 // For each visual in add list, create and add to mVisuals
1749 Dali::CustomActor handle(mControlImpl.GetOwner());
1750 Style::ApplyVisuals(handle, stateVisualsToAdd, instancedProperties);
1752 // For each visual in change list, if it requires a new visual,
1753 // remove old visual, create and add to mVisuals
1754 RecreateChangedVisuals(stateVisualsToChange, instancedProperties);
1757 void Control::Impl::SetState(DevelControl::State newState, bool withTransitions)
1759 DevelControl::State oldState = mState;
1760 Dali::CustomActor handle(mControlImpl.GetOwner());
1761 DALI_LOG_INFO(gLogFilter, Debug::Concise, "Control::Impl::SetState: %s\n", (mState == DevelControl::NORMAL ? "NORMAL" : (mState == DevelControl::FOCUSED ? "FOCUSED" : (mState == DevelControl::DISABLED ? "DISABLED" : "NONE"))));
1763 if(mState != newState)
1765 // If mState was Disabled, and new state is Focused, should probably
1766 // store that fact, e.g. in another property that FocusManager can access.
1769 // Trigger state change and transitions
1770 // Apply new style, if stylemanager is available
1771 Toolkit::StyleManager styleManager = Toolkit::StyleManager::Get();
1774 const StylePtr stylePtr = GetImpl(styleManager).GetRecordedStyle(Toolkit::Control(mControlImpl.GetOwner()));
1778 std::string oldStateName = Scripting::GetEnumerationName<Toolkit::DevelControl::State>(oldState, ControlStateTable, ControlStateTableCount);
1779 std::string newStateName = Scripting::GetEnumerationName<Toolkit::DevelControl::State>(newState, ControlStateTable, ControlStateTableCount);
1781 const StylePtr* newStateStyle = stylePtr->subStates.Find(newStateName);
1782 const StylePtr* oldStateStyle = stylePtr->subStates.Find(oldStateName);
1783 if(oldStateStyle && newStateStyle)
1785 // Only change if both state styles exist
1786 ReplaceStateVisualsAndProperties(*oldStateStyle, *newStateStyle, mSubStateName);
1793 void Control::Impl::SetSubState(const std::string& subStateName, bool withTransitions)
1795 if(mSubStateName != subStateName)
1797 // Get existing sub-state visuals, and unregister them
1798 Dali::CustomActor handle(mControlImpl.GetOwner());
1800 Toolkit::StyleManager styleManager = Toolkit::StyleManager::Get();
1803 const StylePtr stylePtr = GetImpl(styleManager).GetRecordedStyle(Toolkit::Control(mControlImpl.GetOwner()));
1807 std::string stateName = Scripting::GetEnumerationName<Toolkit::DevelControl::State>(mState, ControlStateTable, ControlStateTableCount);
1809 const StylePtr* state = stylePtr->subStates.Find(stateName);
1812 StylePtr stateStyle(*state);
1814 const StylePtr* newStateStyle = stateStyle->subStates.Find(subStateName);
1815 const StylePtr* oldStateStyle = stateStyle->subStates.Find(mSubStateName);
1816 if(oldStateStyle && newStateStyle)
1819 ReplaceStateVisualsAndProperties(*oldStateStyle, *newStateStyle, empty);
1825 mSubStateName = subStateName;
1829 void Control::Impl::OnSceneDisconnection()
1831 Actor self = mControlImpl.Self();
1833 // Any visuals set for replacement but not yet ready should still be registered.
1834 // Reason: If a request was made to register a new visual but the control removed from scene before visual was ready
1835 // then when this control appears back on stage it should use that new visual.
1837 // Iterate through all registered visuals and set off scene
1838 SetVisualsOffScene(mVisuals, self);
1840 // Visuals pending replacement can now be taken out of the removal list and set off scene
1841 // Iterate through all replacement visuals and add to a move queue then set off scene
1842 for(auto removalIter = mRemoveVisuals.Begin(), end = mRemoveVisuals.End(); removalIter != end; removalIter++)
1844 Toolkit::GetImplementation((*removalIter)->visual).SetOffScene(self);
1847 for(auto replacedIter = mVisuals.Begin(), end = mVisuals.End(); replacedIter != end; replacedIter++)
1849 (*replacedIter)->pending = false;
1852 mRemoveVisuals.Clear();
1855 void Control::Impl::SetMargin(Extents margin)
1857 mControlImpl.mImpl->mMargin = margin;
1859 // Trigger a size negotiation request that may be needed when setting a margin.
1860 mControlImpl.RelayoutRequest();
1863 Extents Control::Impl::GetMargin() const
1865 return mControlImpl.mImpl->mMargin;
1868 void Control::Impl::SetPadding(Extents padding)
1870 mControlImpl.mImpl->mPadding = padding;
1872 // Trigger a size negotiation request that may be needed when setting a padding.
1873 mControlImpl.RelayoutRequest();
1876 Extents Control::Impl::GetPadding() const
1878 return mControlImpl.mImpl->mPadding;
1881 void Control::Impl::SetInputMethodContext(InputMethodContext& inputMethodContext)
1883 mInputMethodContext = inputMethodContext;
1886 bool Control::Impl::FilterKeyEvent(const KeyEvent& event)
1888 bool consumed(false);
1890 if(mInputMethodContext)
1892 consumed = mInputMethodContext.FilterEventKey(event);
1897 DevelControl::VisualEventSignalType& Control::Impl::VisualEventSignal()
1899 return mVisualEventSignal;
1902 void Control::Impl::SetShadow(const Property::Map& map)
1904 Toolkit::Visual::Base visual = Toolkit::VisualFactory::Get().CreateVisual(map);
1905 visual.SetName("shadow");
1909 mControlImpl.mImpl->RegisterVisual(Toolkit::DevelControl::Property::SHADOW, visual, DepthIndex::BACKGROUND_EFFECT);
1911 mControlImpl.RelayoutRequest();
1915 void Control::Impl::ClearShadow()
1917 mControlImpl.mImpl->UnregisterVisual(Toolkit::DevelControl::Property::SHADOW);
1919 // Trigger a size negotiation request that may be needed when unregistering a visual.
1920 mControlImpl.RelayoutRequest();
1923 Dali::Property Control::Impl::GetVisualProperty(Dali::Property::Index index, Dali::Property::Key visualPropertyKey)
1925 Toolkit::Visual::Base visual = GetVisualByIndex(mVisuals, index);
1928 Internal::Visual::Base& visualImpl = Toolkit::GetImplementation(visual);
1929 return visualImpl.GetPropertyObject(visualPropertyKey);
1933 return Dali::Property(handle, Property::INVALID_INDEX);
1936 void Control::Impl::MakeVisualTransition(Dali::Animation& animation, Dali::Toolkit::Control source, Dali::Property::Index visualIndex, AlphaFunction alphaFunction, TimePeriod timePeriod)
1938 Dali::Toolkit::Control sourceHandle = Dali::Toolkit::Control::DownCast(source);
1939 Property::Map sourceMap = sourceHandle.GetProperty<Property::Map>(visualIndex);
1940 Dali::Toolkit::Control destinationHandle = Dali::Toolkit::Control::DownCast(mControlImpl.Self());
1941 Property::Map destinationMap = destinationHandle.GetProperty<Property::Map>(visualIndex);
1943 Vector4 mixColor(1.0f, 1.0f, 1.0f, 1.0f);
1944 Vector4 cornerRadius(0.0f, 0.0f, 0.0f, 0.0f);
1945 float borderlineWidth(0.0f);
1946 Vector4 borderlineColor(0.0f, 0.0f, 0.0f, 1.0f);
1947 float borderlineOffset(0.0f);
1949 if(!destinationMap.Empty())
1951 static auto findValueVector4 = [](const Property::Map& map, Property::Index index, const Vector4& defaultValue = Vector4()) -> Vector4 {
1952 Property::Value* propertyValue = map.Find(index);
1955 return propertyValue->Get<Vector4>();
1957 return defaultValue;
1960 static auto findValueFloat = [](const Property::Map& map, Property::Index index, const float& defaultValue = 0.0f) -> float {
1961 Property::Value* propertyValue = map.Find(index);
1964 return propertyValue->Get<float>();
1966 return defaultValue;
1969 mixColor = findValueVector4(destinationMap, Dali::Toolkit::Visual::Property::MIX_COLOR, mixColor);
1970 cornerRadius = findValueVector4(destinationMap, Toolkit::DevelVisual::Property::CORNER_RADIUS, cornerRadius);
1971 borderlineWidth = findValueFloat(destinationMap, Toolkit::DevelVisual::Property::BORDERLINE_WIDTH, borderlineWidth);
1972 borderlineColor = findValueVector4(destinationMap, Toolkit::DevelVisual::Property::BORDERLINE_COLOR, borderlineColor);
1973 borderlineOffset = findValueFloat(destinationMap, Toolkit::DevelVisual::Property::BORDERLINE_OFFSET, borderlineOffset);
1975 if(sourceMap.Empty())
1977 sourceMap.Insert(Toolkit::Visual::Property::TYPE, Toolkit::Visual::COLOR);
1978 sourceMap.Insert(Dali::Toolkit::Visual::Property::MIX_COLOR, Color::TRANSPARENT);
1979 sourceMap.Insert(Toolkit::DevelVisual::Property::CORNER_RADIUS, cornerRadius);
1980 sourceMap.Insert(Toolkit::DevelVisual::Property::BORDERLINE_WIDTH, borderlineWidth);
1981 sourceMap.Insert(Toolkit::DevelVisual::Property::BORDERLINE_COLOR, borderlineColor);
1982 sourceMap.Insert(Toolkit::DevelVisual::Property::BORDERLINE_OFFSET, borderlineOffset);
1985 Vector4 sourceMixColor = findValueVector4(sourceMap, Dali::Toolkit::Visual::Property::MIX_COLOR, mixColor);
1986 Vector4 sourceCornerRadius = findValueVector4(sourceMap, Toolkit::DevelVisual::Property::CORNER_RADIUS, cornerRadius);
1987 float sourceBorderlineWidth = findValueFloat(sourceMap, Toolkit::DevelVisual::Property::BORDERLINE_WIDTH, borderlineWidth);
1988 Vector4 sourceBorderlineColor = findValueVector4(sourceMap, Toolkit::DevelVisual::Property::BORDERLINE_COLOR, borderlineColor);
1989 float sourceBorderlineOffset = findValueFloat(sourceMap, Toolkit::DevelVisual::Property::BORDERLINE_OFFSET, borderlineOffset);
1991 std::vector<Dali::Property> properties;
1992 std::vector<std::pair<Property::Value, Property::Value>> values;
1994 if(Vector3(sourceMixColor) != Vector3(mixColor))
1996 properties.push_back(GetVisualProperty(visualIndex, Dali::Toolkit::Visual::Property::MIX_COLOR));
1997 values.push_back(std::make_pair(Vector3(sourceMixColor), Vector3(mixColor)));
2000 if(std::abs(sourceMixColor.a - mixColor.a) > Math::MACHINE_EPSILON_1)
2002 properties.push_back(GetVisualProperty(visualIndex, Dali::Toolkit::Visual::Property::OPACITY));
2003 values.push_back(std::make_pair(sourceMixColor.a, mixColor.a));
2006 if(sourceCornerRadius != cornerRadius)
2008 properties.push_back(GetVisualProperty(visualIndex, Dali::Toolkit::DevelVisual::Property::CORNER_RADIUS));
2009 values.push_back(std::make_pair(sourceCornerRadius, cornerRadius));
2012 if(sourceBorderlineWidth != borderlineWidth)
2014 properties.push_back(GetVisualProperty(visualIndex, Dali::Toolkit::DevelVisual::Property::BORDERLINE_WIDTH));
2015 values.push_back(std::make_pair(sourceBorderlineWidth, borderlineWidth));
2018 if(sourceBorderlineColor != borderlineColor)
2020 properties.push_back(GetVisualProperty(visualIndex, Dali::Toolkit::DevelVisual::Property::BORDERLINE_COLOR));
2021 values.push_back(std::make_pair(sourceBorderlineColor, borderlineColor));
2024 if(sourceBorderlineOffset != borderlineOffset)
2026 properties.push_back(GetVisualProperty(visualIndex, Dali::Toolkit::DevelVisual::Property::BORDERLINE_OFFSET));
2027 values.push_back(std::make_pair(sourceBorderlineOffset, borderlineOffset));
2030 for(uint32_t i = 0; i < properties.size(); ++i)
2032 if(timePeriod.delaySeconds > 0.0f)
2034 Dali::KeyFrames initialKeyframes = Dali::KeyFrames::New();
2035 initialKeyframes.Add(0.0f, values[i].first);
2036 initialKeyframes.Add(1.0f, values[i].first);
2037 animation.AnimateBetween(properties[i], initialKeyframes, TimePeriod(timePeriod.delaySeconds));
2039 Dali::KeyFrames keyframes = Dali::KeyFrames::New();
2040 keyframes.Add(0.0f, values[i].first);
2041 keyframes.Add(1.0f, values[i].second);
2042 animation.AnimateBetween(properties[i], keyframes, alphaFunction, timePeriod);
2047 void Control::Impl::EmitResourceReadySignal()
2049 if(!mIsEmittingResourceReadySignal)
2051 // Guard against calls to emit the signal during the callback
2052 mIsEmittingResourceReadySignal = true;
2054 // If the signal handler changes visual, it may become ready during this call & therefore this method will
2055 // get called again recursively. If so, mNeedToEmitResourceReady is set below, and we act on it after that secondary
2056 // invocation has completed by notifying in an Idle callback to prevent further recursion.
2057 Dali::Toolkit::Control handle(mControlImpl.GetOwner());
2058 mResourceReadySignal.Emit(handle);
2060 if(mNeedToEmitResourceReady)
2062 // Add idler to emit the signal again
2065 // The callback manager takes the ownership of the callback object.
2066 mIdleCallback = MakeCallback(this, &Control::Impl::OnIdleCallback);
2067 Adaptor::Get().AddIdle(mIdleCallback, false);
2071 mIsEmittingResourceReadySignal = false;
2075 mNeedToEmitResourceReady = true;
2079 void Control::Impl::OnIdleCallback()
2081 if(mNeedToEmitResourceReady)
2084 mNeedToEmitResourceReady = false;
2086 // A visual is ready so control may need relayouting if staged
2087 if(mControlImpl.Self().GetProperty<bool>(Actor::Property::CONNECTED_TO_SCENE))
2089 mControlImpl.RelayoutRequest();
2092 EmitResourceReadySignal();
2095 // Set the pointer to null as the callback manager deletes the callback after execute it.
2096 mIdleCallback = nullptr;
2099 Dali::Accessibility::Accessible* Control::Impl::GetAccessibilityObject()
2101 if(!mAccessibilityObject)
2103 mAccessibilityObject = mAccessibilityConstructor(mControlImpl.Self());
2105 return mAccessibilityObject.get();
2108 Dali::Accessibility::Accessible* Control::Impl::GetAccessibilityObject(Dali::Actor actor)
2112 auto control = Dali::Toolkit::Control::DownCast(actor);
2115 auto controlImpl = static_cast<Internal::Control*>(&control.GetImplementation());
2116 return controlImpl->mImpl->GetAccessibilityObject();
2122 } // namespace Internal
2124 } // namespace Toolkit