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());
553 auto lastPosition = accessibleImpl->GetLastPosition();
554 auto accessibleRect = accessibleImpl->GetExtents(Dali::Accessibility::CoordinateType::WINDOW);
556 if(lastPosition.x == accessibleRect.x && lastPosition.y == accessibleRect.y)
561 auto rect = GetShowingGeometry(accessibleRect, accessibleImpl);
563 // MoveOuted is sent already, no need to send it again
564 if(mAccessibilityMovedOutOfScreenDirection != Dali::Accessibility::MovedOutOfScreenType::NONE)
566 if(rect.width > 0 && rect.height > 0)
568 // flick next does not use MoveOuted - ScrollToSelf makes object show, so reset for sending MoveOuted next
569 mAccessibilityMovedOutOfScreenDirection = Dali::Accessibility::MovedOutOfScreenType::NONE;
576 mAccessibilityMovedOutOfScreenDirection = (accessibleRect.x < lastPosition.x) ? Dali::Accessibility::MovedOutOfScreenType::TOP_LEFT : Dali::Accessibility::MovedOutOfScreenType::BOTTOM_RIGHT;
581 mAccessibilityMovedOutOfScreenDirection = (accessibleRect.y < lastPosition.y) ? Dali::Accessibility::MovedOutOfScreenType::TOP_LEFT : Dali::Accessibility::MovedOutOfScreenType::BOTTOM_RIGHT;
584 if(mAccessibilityMovedOutOfScreenDirection != Dali::Accessibility::MovedOutOfScreenType::NONE)
586 mAccessibilityObject.get()->EmitMovedOutOfScreen(mAccessibilityMovedOutOfScreenDirection);
587 accessibleImpl->SetLastPosition(Vector2(0.0f, 0.0f));
591 accessibleImpl->SetLastPosition(Vector2(accessibleRect.x, accessibleRect.y));
594 void Control::Impl::RegisterAccessibilityPositionPropertyNotification()
596 if(mIsAccessibilityPositionPropertyNotificationSet)
601 mAccessibilityMovedOutOfScreenDirection = Dali::Accessibility::MovedOutOfScreenType::NONE;
602 mAccessibilityPositionNotification = mControlImpl.Self().AddPropertyNotification(Actor::Property::WORLD_POSITION, StepCondition(1.0f, 1.0f));
603 mAccessibilityPositionNotification.SetNotifyMode(PropertyNotification::NOTIFY_ON_CHANGED);
604 mAccessibilityPositionNotification.NotifySignal().Connect(this, &Control::Impl::CheckHighlightedObjectGeometry);
605 mIsAccessibilityPositionPropertyNotificationSet = true;
608 void Control::Impl::UnregisterAccessibilityPositionPropertyNotification()
610 mControlImpl.Self().RemovePropertyNotification(mAccessibilityPositionNotification);
611 mIsAccessibilityPositionPropertyNotificationSet = false;
614 // Gesture Detection Methods
615 void Control::Impl::PinchDetected(Actor actor, const PinchGesture& pinch)
617 mControlImpl.OnPinch(pinch);
620 void Control::Impl::PanDetected(Actor actor, const PanGesture& pan)
622 mControlImpl.OnPan(pan);
625 void Control::Impl::TapDetected(Actor actor, const TapGesture& tap)
627 mControlImpl.OnTap(tap);
630 void Control::Impl::LongPressDetected(Actor actor, const LongPressGesture& longPress)
632 mControlImpl.OnLongPress(longPress);
635 void Control::Impl::RegisterVisual(Property::Index index, Toolkit::Visual::Base& visual)
637 RegisterVisual(index, visual, VisualState::ENABLED, DepthIndexValue::NOT_SET);
640 void Control::Impl::RegisterVisual(Property::Index index, Toolkit::Visual::Base& visual, int depthIndex)
642 RegisterVisual(index, visual, VisualState::ENABLED, DepthIndexValue::SET, depthIndex);
645 void Control::Impl::RegisterVisual(Property::Index index, Toolkit::Visual::Base& visual, bool enabled)
647 RegisterVisual(index, visual, (enabled ? VisualState::ENABLED : VisualState::DISABLED), DepthIndexValue::NOT_SET);
650 void Control::Impl::RegisterVisual(Property::Index index, Toolkit::Visual::Base& visual, bool enabled, int depthIndex)
652 RegisterVisual(index, visual, (enabled ? VisualState::ENABLED : VisualState::DISABLED), DepthIndexValue::SET, depthIndex);
655 void Control::Impl::RegisterVisual(Property::Index index, Toolkit::Visual::Base& visual, VisualState::Type enabled, DepthIndexValue::Type depthIndexValueSet, int depthIndex)
657 DALI_LOG_INFO(gLogFilter, Debug::Concise, "RegisterVisual:%d \n", index);
659 bool visualReplaced(false);
660 Actor self = mControlImpl.Self();
662 // Set the depth index, if not set by caller this will be either the current visual depth, max depth of all visuals
664 int requiredDepthIndex = visual.GetDepthIndex();
666 if(depthIndexValueSet == DepthIndexValue::SET)
668 requiredDepthIndex = depthIndex;
671 // Visual replacement, existing visual should only be removed from stage when replacement ready.
672 if(!mVisuals.Empty())
674 RegisteredVisualContainer::Iterator registeredVisualsiter;
675 // Check if visual (index) is already registered, this is the current visual.
676 if(FindVisual(index, mVisuals, registeredVisualsiter))
678 Toolkit::Visual::Base& currentRegisteredVisual = (*registeredVisualsiter)->visual;
679 if(currentRegisteredVisual)
681 // Store current visual depth index as may need to set the replacement visual to same depth
682 const int currentDepthIndex = (*registeredVisualsiter)->visual.GetDepthIndex();
684 // No longer required to know if the replaced visual's resources are ready
685 StopObservingVisual(currentRegisteredVisual);
687 // If control staged and visual enabled then visuals will be swapped once ready
688 if(self.GetProperty<bool>(Actor::Property::CONNECTED_TO_SCENE) && enabled)
690 // Check if visual is currently in the process of being replaced ( is in removal container )
691 RegisteredVisualContainer::Iterator visualQueuedForRemoval;
692 if(FindVisual(index, mRemoveVisuals, visualQueuedForRemoval))
694 // Visual with same index is already in removal container so current visual pending
695 // Only the the last requested visual will be displayed so remove current visual which is staged but not ready.
696 Toolkit::GetImplementation(currentRegisteredVisual).SetOffScene(self);
697 mVisuals.Erase(registeredVisualsiter);
701 // current visual not already in removal container so add now.
702 DALI_LOG_INFO(gLogFilter, Debug::Verbose, "RegisterVisual Move current registered visual to removal Queue: %d \n", index);
703 MoveVisual(registeredVisualsiter, mVisuals, mRemoveVisuals);
708 // Control not staged or visual disabled so can just erase from registered visuals and new visual will be added later.
709 mVisuals.Erase(registeredVisualsiter);
712 // 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
713 if((depthIndexValueSet == DepthIndexValue::NOT_SET) &&
714 (visual.GetDepthIndex() == 0))
716 requiredDepthIndex = currentDepthIndex;
720 visualReplaced = true;
724 // If not set, set the name of the visual to the same name as the control's property.
725 // ( If the control has been type registered )
726 if(visual.GetName().empty())
728 // returns empty string if index is not found as long as index is not -1
729 std::string visualName = self.GetPropertyName(index);
730 if(!visualName.empty())
732 DALI_LOG_INFO(gLogFilter, Debug::Concise, "Setting visual name for property %d to %s\n", index, visualName.c_str());
733 visual.SetName(visualName);
737 if(!visualReplaced) // New registration entry
739 // 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
740 if((depthIndexValueSet == DepthIndexValue::NOT_SET) &&
741 (mVisuals.Size() > 0) &&
742 (visual.GetDepthIndex() == 0))
744 int maxDepthIndex = std::numeric_limits<int>::min();
746 RegisteredVisualContainer::ConstIterator iter;
747 const RegisteredVisualContainer::ConstIterator endIter = mVisuals.End();
748 for(iter = mVisuals.Begin(); iter != endIter; iter++)
750 const int visualDepthIndex = (*iter)->visual.GetDepthIndex();
751 if(visualDepthIndex > maxDepthIndex)
753 maxDepthIndex = visualDepthIndex;
756 ++maxDepthIndex; // Add one to the current maximum depth index so that our added visual appears on top
757 requiredDepthIndex = std::max(0, maxDepthIndex); // Start at zero if maxDepth index belongs to a background
763 // Set determined depth index
764 visual.SetDepthIndex(requiredDepthIndex);
766 // Monitor when the visual resources are ready
767 StartObservingVisual(visual);
769 DALI_LOG_INFO(gLogFilter, Debug::Concise, "New Visual registration index[%d] depth[%d]\n", index, requiredDepthIndex);
770 RegisteredVisual* newRegisteredVisual = new RegisteredVisual(index, visual, (enabled == VisualState::ENABLED ? true : false), (visualReplaced && enabled));
771 mVisuals.PushBack(newRegisteredVisual);
773 Internal::Visual::Base& visualImpl = Toolkit::GetImplementation(visual);
774 // Put on stage if enabled and the control is already on the stage
775 if((enabled == VisualState::ENABLED) && self.GetProperty<bool>(Actor::Property::CONNECTED_TO_SCENE))
777 visualImpl.SetOnScene(self);
779 else if(visualImpl.IsResourceReady()) // When not being staged, check if visual already 'ResourceReady' before it was Registered. ( Resource may have been loaded already )
781 ResourceReady(visualImpl);
785 DALI_LOG_INFO(gLogFilter, Debug::Verbose, "Control::RegisterVisual() Registered %s(%d), enabled:%s\n", visual.GetName().c_str(), index, enabled ? "true" : "false");
788 void Control::Impl::UnregisterVisual(Property::Index index)
790 RegisteredVisualContainer::Iterator iter;
791 if(FindVisual(index, mVisuals, iter))
793 // stop observing visual
794 StopObservingVisual((*iter)->visual);
796 Actor self(mControlImpl.Self());
797 Toolkit::GetImplementation((*iter)->visual).SetOffScene(self);
798 (*iter)->visual.Reset();
799 mVisuals.Erase(iter);
802 if(FindVisual(index, mRemoveVisuals, iter))
804 Actor self(mControlImpl.Self());
805 Toolkit::GetImplementation((*iter)->visual).SetOffScene(self);
806 (*iter)->pending = false;
807 (*iter)->visual.Reset();
808 mRemoveVisuals.Erase(iter);
812 Toolkit::Visual::Base Control::Impl::GetVisual(Property::Index index) const
814 RegisteredVisualContainer::Iterator iter;
815 if(FindVisual(index, mVisuals, iter))
817 return (*iter)->visual;
820 return Toolkit::Visual::Base();
823 void Control::Impl::EnableVisual(Property::Index index, bool enable)
825 DALI_LOG_INFO(gLogFilter, Debug::General, "Control::EnableVisual(%d, %s)\n", index, enable ? "T" : "F");
827 RegisteredVisualContainer::Iterator iter;
828 if(FindVisual(index, mVisuals, iter))
830 if((*iter)->enabled == enable)
832 DALI_LOG_INFO(gLogFilter, Debug::Verbose, "Control::EnableVisual Visual %s(%d) already %s\n", (*iter)->visual.GetName().c_str(), index, enable ? "enabled" : "disabled");
836 (*iter)->enabled = enable;
837 Actor parentActor = mControlImpl.Self();
838 if(mControlImpl.Self().GetProperty<bool>(Actor::Property::CONNECTED_TO_SCENE)) // If control not on Scene then Visual will be added when SceneConnection is called.
842 DALI_LOG_INFO(gLogFilter, Debug::Verbose, "Control::EnableVisual Setting %s(%d) on stage \n", (*iter)->visual.GetName().c_str(), index);
843 Toolkit::GetImplementation((*iter)->visual).SetOnScene(parentActor);
847 DALI_LOG_INFO(gLogFilter, Debug::Verbose, "Control::EnableVisual Setting %s(%d) off stage \n", (*iter)->visual.GetName().c_str(), index);
848 Toolkit::GetImplementation((*iter)->visual).SetOffScene(parentActor); // No need to call if control not staged.
854 DALI_LOG_WARNING("Control::EnableVisual(%d, %s) FAILED - NO SUCH VISUAL\n", index, enable ? "T" : "F");
858 bool Control::Impl::IsVisualEnabled(Property::Index index) const
860 RegisteredVisualContainer::Iterator iter;
861 if(FindVisual(index, mVisuals, iter))
863 return (*iter)->enabled;
868 void Control::Impl::StopObservingVisual(Toolkit::Visual::Base& visual)
870 Internal::Visual::Base& visualImpl = Toolkit::GetImplementation(visual);
872 // Stop observing the visual
873 visualImpl.RemoveEventObserver(*this);
876 void Control::Impl::StartObservingVisual(Toolkit::Visual::Base& visual)
878 Internal::Visual::Base& visualImpl = Toolkit::GetImplementation(visual);
880 // start observing the visual for events
881 visualImpl.AddEventObserver(*this);
884 // Called by a Visual when it's resource is ready
885 void Control::Impl::ResourceReady(Visual::Base& object)
887 DALI_LOG_INFO(gLogFilter, Debug::Verbose, "Control::Impl::ResourceReady() replacements pending[%d]\n", mRemoveVisuals.Count());
889 Actor self = mControlImpl.Self();
891 // A resource is ready, find resource in the registered visuals container and get its index
892 for(auto registeredIter = mVisuals.Begin(), end = mVisuals.End(); registeredIter != end; ++registeredIter)
894 Internal::Visual::Base& registeredVisualImpl = Toolkit::GetImplementation((*registeredIter)->visual);
896 if(&object == ®isteredVisualImpl)
898 RegisteredVisualContainer::Iterator visualToRemoveIter;
899 // Find visual with the same index in the removal container
900 // Set if off stage as it's replacement is now ready.
901 // Remove if from removal list as now removed from stage.
902 // Set Pending flag on the ready visual to false as now ready.
903 if(FindVisual((*registeredIter)->index, mRemoveVisuals, visualToRemoveIter))
905 (*registeredIter)->pending = false;
906 Toolkit::GetImplementation((*visualToRemoveIter)->visual).SetOffScene(self);
907 mRemoveVisuals.Erase(visualToRemoveIter);
913 // A visual is ready so control may need relayouting if staged
914 if(self.GetProperty<bool>(Actor::Property::CONNECTED_TO_SCENE))
916 mControlImpl.RelayoutRequest();
919 // Emit signal if all enabled visuals registered by the control are ready.
920 if(IsResourceReady())
923 mNeedToEmitResourceReady = false;
925 EmitResourceReadySignal();
929 void Control::Impl::NotifyVisualEvent(Visual::Base& object, Property::Index signalId)
931 for(auto registeredIter = mVisuals.Begin(), end = mVisuals.End(); registeredIter != end; ++registeredIter)
933 Internal::Visual::Base& registeredVisualImpl = Toolkit::GetImplementation((*registeredIter)->visual);
934 if(&object == ®isteredVisualImpl)
936 Dali::Toolkit::Control handle(mControlImpl.GetOwner());
937 mVisualEventSignal.Emit(handle, (*registeredIter)->index, signalId);
943 bool Control::Impl::IsResourceReady() const
945 // Iterate through and check all the enabled visuals are ready
946 for(auto visualIter = mVisuals.Begin();
947 visualIter != mVisuals.End();
950 const Toolkit::Visual::Base visual = (*visualIter)->visual;
951 const Internal::Visual::Base& visualImpl = Toolkit::GetImplementation(visual);
953 // one of the enabled visuals is not ready
954 if(!visualImpl.IsResourceReady() && (*visualIter)->enabled)
962 Toolkit::Visual::ResourceStatus Control::Impl::GetVisualResourceStatus(Property::Index index) const
964 RegisteredVisualContainer::Iterator iter;
965 if(FindVisual(index, mVisuals, iter))
967 const Toolkit::Visual::Base visual = (*iter)->visual;
968 const Internal::Visual::Base& visualImpl = Toolkit::GetImplementation(visual);
969 return visualImpl.GetResourceStatus();
972 return Toolkit::Visual::ResourceStatus::PREPARING;
975 void Control::Impl::AddTransitions(Dali::Animation& animation,
976 const Toolkit::TransitionData& handle,
977 bool createAnimation)
979 // Setup a Transition from TransitionData.
980 const Internal::TransitionData& transitionData = Toolkit::GetImplementation(handle);
981 TransitionData::Iterator end = transitionData.End();
982 for(TransitionData::Iterator iter = transitionData.Begin();
986 TransitionData::Animator* animator = (*iter);
988 Toolkit::Visual::Base visual = GetVisualByName(mVisuals, animator->objectName);
992 #if defined(DEBUG_ENABLED)
993 Dali::TypeInfo typeInfo;
994 ControlWrapper* controlWrapperImpl = dynamic_cast<ControlWrapper*>(&mControlImpl);
995 if(controlWrapperImpl)
997 typeInfo = controlWrapperImpl->GetTypeInfo();
1000 DALI_LOG_INFO(gLogFilter, Debug::Concise, "CreateTransition: Found %s visual for %s\n", visual.GetName().c_str(), typeInfo ? typeInfo.GetName().c_str() : "Unknown");
1002 Internal::Visual::Base& visualImpl = Toolkit::GetImplementation(visual);
1003 visualImpl.AnimateProperty(animation, *animator);
1007 DALI_LOG_INFO(gLogFilter, Debug::Concise, "CreateTransition: Could not find visual. Trying actors");
1008 // Otherwise, try any actor children of control (Including the control)
1009 Actor child = mControlImpl.Self().FindChildByName(animator->objectName);
1012 Property::Index propertyIndex = child.GetPropertyIndex(animator->propertyKey);
1013 if(propertyIndex != Property::INVALID_INDEX)
1015 if(animator->animate == false)
1017 if(animator->targetValue.GetType() != Property::NONE)
1019 child.SetProperty(propertyIndex, animator->targetValue);
1022 else // animate the property
1024 if(animator->initialValue.GetType() != Property::NONE)
1026 child.SetProperty(propertyIndex, animator->initialValue);
1029 if(createAnimation && !animation)
1031 animation = Dali::Animation::New(0.1f);
1034 animation.AnimateTo(Property(child, propertyIndex),
1035 animator->targetValue,
1036 animator->alphaFunction,
1037 TimePeriod(animator->timePeriodDelay,
1038 animator->timePeriodDuration));
1046 Dali::Animation Control::Impl::CreateTransition(const Toolkit::TransitionData& transitionData)
1048 Dali::Animation transition;
1050 if(transitionData.Count() > 0)
1052 AddTransitions(transition, transitionData, true);
1057 void Control::Impl::DoAction(Dali::Property::Index visualIndex, Dali::Property::Index actionId, const Dali::Property::Value attributes)
1059 RegisteredVisualContainer::Iterator iter;
1060 if(FindVisual(visualIndex, mVisuals, iter))
1062 Toolkit::GetImplementation((*iter)->visual).DoAction(actionId, attributes);
1066 void Control::Impl::AppendAccessibilityAttribute(const std::string& key, const std::string value)
1068 Property::Value* checkedValue = mAccessibilityAttributes.Find(key);
1071 mAccessibilityAttributes[key] = Property::Value(value);
1075 mAccessibilityAttributes.Insert(key, value);
1079 void Control::Impl::SetProperty(BaseObject* object, Property::Index index, const Property::Value& value)
1081 Toolkit::Control control = Toolkit::Control::DownCast(BaseHandle(object));
1085 Control& controlImpl(GetImplementation(control));
1089 case Toolkit::Control::Property::STYLE_NAME:
1091 controlImpl.SetStyleName(value.Get<std::string>());
1095 case Toolkit::DevelControl::Property::STATE:
1097 bool withTransitions = true;
1098 const Property::Value* valuePtr = &value;
1099 const Property::Map* map = value.GetMap();
1102 Property::Value* value2 = map->Find("withTransitions");
1105 withTransitions = value2->Get<bool>();
1108 valuePtr = map->Find("state");
1113 Toolkit::DevelControl::State state(controlImpl.mImpl->mState);
1114 if(Scripting::GetEnumerationProperty<Toolkit::DevelControl::State>(*valuePtr, ControlStateTable, ControlStateTableCount, state))
1116 controlImpl.mImpl->SetState(state, withTransitions);
1122 case Toolkit::DevelControl::Property::SUB_STATE:
1124 std::string subState;
1125 if(value.Get(subState))
1127 controlImpl.mImpl->SetSubState(subState);
1132 case Toolkit::DevelControl::Property::LEFT_FOCUSABLE_ACTOR_ID:
1135 if(value.Get(focusId))
1137 controlImpl.mImpl->mLeftFocusableActorId = focusId;
1142 case Toolkit::DevelControl::Property::RIGHT_FOCUSABLE_ACTOR_ID:
1145 if(value.Get(focusId))
1147 controlImpl.mImpl->mRightFocusableActorId = focusId;
1152 case Toolkit::DevelControl::Property::UP_FOCUSABLE_ACTOR_ID:
1155 if(value.Get(focusId))
1157 controlImpl.mImpl->mUpFocusableActorId = focusId;
1162 case Toolkit::DevelControl::Property::DOWN_FOCUSABLE_ACTOR_ID:
1165 if(value.Get(focusId))
1167 controlImpl.mImpl->mDownFocusableActorId = focusId;
1172 case Toolkit::Control::Property::KEY_INPUT_FOCUS:
1174 if(value.Get<bool>())
1176 controlImpl.SetKeyInputFocus();
1180 controlImpl.ClearKeyInputFocus();
1185 case Toolkit::Control::Property::BACKGROUND:
1189 const Property::Map* map = value.GetMap();
1190 if(map && !map->Empty())
1192 controlImpl.SetBackground(*map);
1194 else if(value.Get(url))
1196 // don't know the size to load
1197 Toolkit::Visual::Base visual = Toolkit::VisualFactory::Get().CreateVisual(url, ImageDimensions());
1200 controlImpl.mImpl->RegisterVisual(Toolkit::Control::Property::BACKGROUND, visual, DepthIndex::BACKGROUND);
1203 else if(value.Get(color))
1205 controlImpl.SetBackgroundColor(color);
1209 // The background is an empty property map, so we should clear the background
1210 controlImpl.ClearBackground();
1215 case Toolkit::Control::Property::MARGIN:
1218 if(value.Get(margin))
1220 controlImpl.mImpl->SetMargin(margin);
1225 case Toolkit::Control::Property::PADDING:
1228 if(value.Get(padding))
1230 controlImpl.mImpl->SetPadding(padding);
1235 case Toolkit::DevelControl::Property::TOOLTIP:
1237 TooltipPtr& tooltipPtr = controlImpl.mImpl->mTooltip;
1240 tooltipPtr = Tooltip::New(control);
1242 tooltipPtr->SetProperties(value);
1246 case Toolkit::DevelControl::Property::SHADOW:
1248 const Property::Map* map = value.GetMap();
1249 if(map && !map->Empty())
1251 controlImpl.mImpl->SetShadow(*map);
1255 // The shadow is an empty property map, so we should clear the shadow
1256 controlImpl.mImpl->ClearShadow();
1261 case Toolkit::DevelControl::Property::ACCESSIBILITY_NAME:
1266 controlImpl.mImpl->mAccessibilityName = name;
1267 controlImpl.mImpl->mAccessibilityNameSet = true;
1271 controlImpl.mImpl->mAccessibilityNameSet = false;
1276 case Toolkit::DevelControl::Property::ACCESSIBILITY_DESCRIPTION:
1281 controlImpl.mImpl->mAccessibilityDescription = text;
1282 controlImpl.mImpl->mAccessibilityDescriptionSet = true;
1286 controlImpl.mImpl->mAccessibilityDescriptionSet = false;
1291 case Toolkit::DevelControl::Property::ACCESSIBILITY_TRANSLATION_DOMAIN:
1296 controlImpl.mImpl->mAccessibilityTranslationDomain = text;
1297 controlImpl.mImpl->mAccessibilityTranslationDomainSet = true;
1301 controlImpl.mImpl->mAccessibilityTranslationDomainSet = false;
1306 case Toolkit::DevelControl::Property::ACCESSIBILITY_ROLE:
1308 Dali::Accessibility::Role role;
1311 controlImpl.mImpl->mAccessibilityRole = role;
1316 case Toolkit::DevelControl::Property::ACCESSIBILITY_HIGHLIGHTABLE:
1319 if(value.Get(highlightable))
1321 controlImpl.mImpl->mAccessibilityHighlightable = highlightable;
1322 controlImpl.mImpl->mAccessibilityHighlightableSet = true;
1326 controlImpl.mImpl->mAccessibilityHighlightableSet = false;
1331 case Toolkit::DevelControl::Property::ACCESSIBILITY_ATTRIBUTES:
1333 const Property::Map* map = value.GetMap();
1334 if(map && !map->Empty())
1336 controlImpl.mImpl->mAccessibilityAttributes = *map;
1344 Property::Value Control::Impl::GetProperty(BaseObject* object, Property::Index index)
1346 Property::Value value;
1348 Toolkit::Control control = Toolkit::Control::DownCast(BaseHandle(object));
1352 Control& controlImpl(GetImplementation(control));
1356 case Toolkit::Control::Property::STYLE_NAME:
1358 value = controlImpl.GetStyleName();
1362 case Toolkit::DevelControl::Property::STATE:
1364 value = controlImpl.mImpl->mState;
1368 case Toolkit::DevelControl::Property::SUB_STATE:
1370 value = controlImpl.mImpl->mSubStateName;
1374 case Toolkit::DevelControl::Property::LEFT_FOCUSABLE_ACTOR_ID:
1376 value = controlImpl.mImpl->mLeftFocusableActorId;
1380 case Toolkit::DevelControl::Property::RIGHT_FOCUSABLE_ACTOR_ID:
1382 value = controlImpl.mImpl->mRightFocusableActorId;
1386 case Toolkit::DevelControl::Property::UP_FOCUSABLE_ACTOR_ID:
1388 value = controlImpl.mImpl->mUpFocusableActorId;
1392 case Toolkit::DevelControl::Property::DOWN_FOCUSABLE_ACTOR_ID:
1394 value = controlImpl.mImpl->mDownFocusableActorId;
1398 case Toolkit::Control::Property::KEY_INPUT_FOCUS:
1400 value = controlImpl.HasKeyInputFocus();
1404 case Toolkit::Control::Property::BACKGROUND:
1407 Toolkit::Visual::Base visual = controlImpl.mImpl->GetVisual(Toolkit::Control::Property::BACKGROUND);
1410 visual.CreatePropertyMap(map);
1417 case Toolkit::Control::Property::MARGIN:
1419 value = controlImpl.mImpl->GetMargin();
1423 case Toolkit::Control::Property::PADDING:
1425 value = controlImpl.mImpl->GetPadding();
1429 case Toolkit::DevelControl::Property::TOOLTIP:
1432 if(controlImpl.mImpl->mTooltip)
1434 controlImpl.mImpl->mTooltip->CreatePropertyMap(map);
1440 case Toolkit::DevelControl::Property::SHADOW:
1443 Toolkit::Visual::Base visual = controlImpl.mImpl->GetVisual(Toolkit::DevelControl::Property::SHADOW);
1446 visual.CreatePropertyMap(map);
1453 case Toolkit::DevelControl::Property::ACCESSIBILITY_NAME:
1455 if(controlImpl.mImpl->mAccessibilityNameSet)
1457 value = controlImpl.mImpl->mAccessibilityName;
1462 case Toolkit::DevelControl::Property::ACCESSIBILITY_DESCRIPTION:
1464 if(controlImpl.mImpl->mAccessibilityDescriptionSet)
1466 value = controlImpl.mImpl->mAccessibilityDescription;
1471 case Toolkit::DevelControl::Property::ACCESSIBILITY_TRANSLATION_DOMAIN:
1473 if(controlImpl.mImpl->mAccessibilityTranslationDomainSet)
1475 value = controlImpl.mImpl->mAccessibilityTranslationDomain;
1480 case Toolkit::DevelControl::Property::ACCESSIBILITY_ROLE:
1482 value = Property::Value(controlImpl.mImpl->mAccessibilityRole);
1486 case Toolkit::DevelControl::Property::ACCESSIBILITY_HIGHLIGHTABLE:
1488 if(controlImpl.mImpl->mAccessibilityHighlightableSet)
1490 value = controlImpl.mImpl->mAccessibilityHighlightable;
1495 case Toolkit::DevelControl::Property::ACCESSIBILITY_ATTRIBUTES:
1497 value = controlImpl.mImpl->mAccessibilityAttributes;
1506 void Control::Impl::RemoveAccessibilityAttribute(const std::string& key)
1508 Property::Value* value = mAccessibilityAttributes.Find(key);
1511 mAccessibilityAttributes[key] = Property::Value();
1515 void Control::Impl::ClearAccessibilityAttributes()
1517 mAccessibilityAttributes.Clear();
1520 void Control::Impl::SetAccessibilityReadingInfoType(const Dali::Accessibility::ReadingInfoTypes types)
1522 std::string value{};
1523 if(types[Dali::Accessibility::ReadingInfoType::NAME])
1525 value += READING_INFO_TYPE_NAME;
1527 if(types[Dali::Accessibility::ReadingInfoType::ROLE])
1531 value += READING_INFO_TYPE_SEPARATOR;
1533 value += READING_INFO_TYPE_ROLE;
1535 if(types[Dali::Accessibility::ReadingInfoType::DESCRIPTION])
1539 value += READING_INFO_TYPE_SEPARATOR;
1541 value += READING_INFO_TYPE_DESCRIPTION;
1543 if(types[Dali::Accessibility::ReadingInfoType::STATE])
1547 value += READING_INFO_TYPE_SEPARATOR;
1549 value += READING_INFO_TYPE_STATE;
1551 AppendAccessibilityAttribute(READING_INFO_TYPE_ATTRIBUTE_NAME, value);
1554 Dali::Accessibility::ReadingInfoTypes Control::Impl::GetAccessibilityReadingInfoType() const
1556 std::string value{};
1557 auto place = mAccessibilityAttributes.Find(READING_INFO_TYPE_ATTRIBUTE_NAME);
1564 Dali::Accessibility::ReadingInfoTypes types;
1565 types[Dali::Accessibility::ReadingInfoType::NAME] = true;
1566 types[Dali::Accessibility::ReadingInfoType::ROLE] = true;
1567 types[Dali::Accessibility::ReadingInfoType::DESCRIPTION] = true;
1568 types[Dali::Accessibility::ReadingInfoType::STATE] = true;
1577 Dali::Accessibility::ReadingInfoTypes types;
1579 if(value.find(READING_INFO_TYPE_NAME) != std::string::npos)
1581 types[Dali::Accessibility::ReadingInfoType::NAME] = true;
1583 if(value.find(READING_INFO_TYPE_ROLE) != std::string::npos)
1585 types[Dali::Accessibility::ReadingInfoType::ROLE] = true;
1587 if(value.find(READING_INFO_TYPE_DESCRIPTION) != std::string::npos)
1589 types[Dali::Accessibility::ReadingInfoType::DESCRIPTION] = true;
1591 if(value.find(READING_INFO_TYPE_STATE) != std::string::npos)
1593 types[Dali::Accessibility::ReadingInfoType::STATE] = true;
1599 void Control::Impl::CopyInstancedProperties(RegisteredVisualContainer& visuals, Dictionary<Property::Map>& instancedProperties)
1601 for(RegisteredVisualContainer::Iterator iter = visuals.Begin(); iter != visuals.End(); iter++)
1605 Property::Map instanceMap;
1606 Toolkit::GetImplementation((*iter)->visual).CreateInstancePropertyMap(instanceMap);
1607 instancedProperties.Add((*iter)->visual.GetName(), instanceMap);
1612 void Control::Impl::RemoveVisual(RegisteredVisualContainer& visuals, const std::string& visualName)
1614 Actor self(mControlImpl.Self());
1616 for(RegisteredVisualContainer::Iterator visualIter = visuals.Begin();
1617 visualIter != visuals.End();
1620 Toolkit::Visual::Base visual = (*visualIter)->visual;
1621 if(visual && visual.GetName() == visualName)
1623 Toolkit::GetImplementation(visual).SetOffScene(self);
1624 (*visualIter)->visual.Reset();
1625 visuals.Erase(visualIter);
1631 void Control::Impl::RemoveVisuals(RegisteredVisualContainer& visuals, DictionaryKeys& removeVisuals)
1633 Actor self(mControlImpl.Self());
1634 for(DictionaryKeys::iterator iter = removeVisuals.begin(); iter != removeVisuals.end(); ++iter)
1636 const std::string visualName = *iter;
1637 RemoveVisual(visuals, visualName);
1641 void Control::Impl::RecreateChangedVisuals(Dictionary<Property::Map>& stateVisualsToChange,
1642 Dictionary<Property::Map>& instancedProperties)
1644 Dali::CustomActor handle(mControlImpl.GetOwner());
1645 for(Dictionary<Property::Map>::iterator iter = stateVisualsToChange.Begin();
1646 iter != stateVisualsToChange.End();
1649 const std::string& visualName = (*iter).key;
1650 const Property::Map& toMap = (*iter).entry;
1652 Actor self = mControlImpl.Self();
1653 RegisteredVisualContainer::Iterator registeredVisualsiter;
1654 // Check if visual (visualName) is already registered, this is the current visual.
1655 if(FindVisual(visualName, mVisuals, registeredVisualsiter))
1657 Toolkit::Visual::Base& visual = (*registeredVisualsiter)->visual;
1660 // No longer required to know if the replaced visual's resources are ready
1661 StopObservingVisual(visual);
1663 // If control staged then visuals will be swapped once ready
1664 if(self.GetProperty<bool>(Actor::Property::CONNECTED_TO_SCENE))
1666 // Check if visual is currently in the process of being replaced ( is in removal container )
1667 RegisteredVisualContainer::Iterator visualQueuedForRemoval;
1668 if(FindVisual(visualName, mRemoveVisuals, visualQueuedForRemoval))
1670 // Visual with same visual name is already in removal container so current visual pending
1671 // Only the the last requested visual will be displayed so remove current visual which is staged but not ready.
1672 Toolkit::GetImplementation(visual).SetOffScene(self);
1673 (*registeredVisualsiter)->visual.Reset();
1674 mVisuals.Erase(registeredVisualsiter);
1678 // current visual not already in removal container so add now.
1679 DALI_LOG_INFO(gLogFilter, Debug::Verbose, "RegisterVisual Move current registered visual to removal Queue: %s \n", visualName.c_str());
1680 MoveVisual(registeredVisualsiter, mVisuals, mRemoveVisuals);
1685 // Control not staged or visual disabled so can just erase from registered visuals and new visual will be added later.
1686 (*registeredVisualsiter)->visual.Reset();
1687 mVisuals.Erase(registeredVisualsiter);
1691 const Property::Map* instancedMap = instancedProperties.FindConst(visualName);
1692 Style::ApplyVisual(handle, visualName, toMap, instancedMap);
1697 void Control::Impl::ReplaceStateVisualsAndProperties(const StylePtr oldState, const StylePtr newState, const std::string& subState)
1699 // Collect all old visual names
1700 DictionaryKeys stateVisualsToRemove;
1703 oldState->visuals.GetKeys(stateVisualsToRemove);
1704 if(!subState.empty())
1706 const StylePtr* oldSubState = oldState->subStates.FindConst(subState);
1709 DictionaryKeys subStateVisualsToRemove;
1710 (*oldSubState)->visuals.GetKeys(subStateVisualsToRemove);
1711 Merge(stateVisualsToRemove, subStateVisualsToRemove);
1716 // Collect all new visual properties
1717 Dictionary<Property::Map> stateVisualsToAdd;
1720 stateVisualsToAdd = newState->visuals;
1721 if(!subState.empty())
1723 const StylePtr* newSubState = newState->subStates.FindConst(subState);
1726 stateVisualsToAdd.Merge((*newSubState)->visuals);
1731 // If a name is in both add/remove, move it to change list.
1732 Dictionary<Property::Map> stateVisualsToChange;
1733 FindChangableVisuals(stateVisualsToAdd, stateVisualsToChange, stateVisualsToRemove);
1735 // Copy instanced properties (e.g. text label) of current visuals
1736 Dictionary<Property::Map> instancedProperties;
1737 CopyInstancedProperties(mVisuals, instancedProperties);
1739 // For each visual in remove list, remove from mVisuals
1740 RemoveVisuals(mVisuals, stateVisualsToRemove);
1742 // For each visual in add list, create and add to mVisuals
1743 Dali::CustomActor handle(mControlImpl.GetOwner());
1744 Style::ApplyVisuals(handle, stateVisualsToAdd, instancedProperties);
1746 // For each visual in change list, if it requires a new visual,
1747 // remove old visual, create and add to mVisuals
1748 RecreateChangedVisuals(stateVisualsToChange, instancedProperties);
1751 void Control::Impl::SetState(DevelControl::State newState, bool withTransitions)
1753 DevelControl::State oldState = mState;
1754 Dali::CustomActor handle(mControlImpl.GetOwner());
1755 DALI_LOG_INFO(gLogFilter, Debug::Concise, "Control::Impl::SetState: %s\n", (mState == DevelControl::NORMAL ? "NORMAL" : (mState == DevelControl::FOCUSED ? "FOCUSED" : (mState == DevelControl::DISABLED ? "DISABLED" : "NONE"))));
1757 if(mState != newState)
1759 // If mState was Disabled, and new state is Focused, should probably
1760 // store that fact, e.g. in another property that FocusManager can access.
1763 // Trigger state change and transitions
1764 // Apply new style, if stylemanager is available
1765 Toolkit::StyleManager styleManager = Toolkit::StyleManager::Get();
1768 const StylePtr stylePtr = GetImpl(styleManager).GetRecordedStyle(Toolkit::Control(mControlImpl.GetOwner()));
1772 std::string oldStateName = Scripting::GetEnumerationName<Toolkit::DevelControl::State>(oldState, ControlStateTable, ControlStateTableCount);
1773 std::string newStateName = Scripting::GetEnumerationName<Toolkit::DevelControl::State>(newState, ControlStateTable, ControlStateTableCount);
1775 const StylePtr* newStateStyle = stylePtr->subStates.Find(newStateName);
1776 const StylePtr* oldStateStyle = stylePtr->subStates.Find(oldStateName);
1777 if(oldStateStyle && newStateStyle)
1779 // Only change if both state styles exist
1780 ReplaceStateVisualsAndProperties(*oldStateStyle, *newStateStyle, mSubStateName);
1787 void Control::Impl::SetSubState(const std::string& subStateName, bool withTransitions)
1789 if(mSubStateName != subStateName)
1791 // Get existing sub-state visuals, and unregister them
1792 Dali::CustomActor handle(mControlImpl.GetOwner());
1794 Toolkit::StyleManager styleManager = Toolkit::StyleManager::Get();
1797 const StylePtr stylePtr = GetImpl(styleManager).GetRecordedStyle(Toolkit::Control(mControlImpl.GetOwner()));
1801 std::string stateName = Scripting::GetEnumerationName<Toolkit::DevelControl::State>(mState, ControlStateTable, ControlStateTableCount);
1803 const StylePtr* state = stylePtr->subStates.Find(stateName);
1806 StylePtr stateStyle(*state);
1808 const StylePtr* newStateStyle = stateStyle->subStates.Find(subStateName);
1809 const StylePtr* oldStateStyle = stateStyle->subStates.Find(mSubStateName);
1810 if(oldStateStyle && newStateStyle)
1813 ReplaceStateVisualsAndProperties(*oldStateStyle, *newStateStyle, empty);
1819 mSubStateName = subStateName;
1823 void Control::Impl::OnSceneDisconnection()
1825 Actor self = mControlImpl.Self();
1827 // Any visuals set for replacement but not yet ready should still be registered.
1828 // Reason: If a request was made to register a new visual but the control removed from scene before visual was ready
1829 // then when this control appears back on stage it should use that new visual.
1831 // Iterate through all registered visuals and set off scene
1832 SetVisualsOffScene(mVisuals, self);
1834 // Visuals pending replacement can now be taken out of the removal list and set off scene
1835 // Iterate through all replacement visuals and add to a move queue then set off scene
1836 for(auto removalIter = mRemoveVisuals.Begin(), end = mRemoveVisuals.End(); removalIter != end; removalIter++)
1838 Toolkit::GetImplementation((*removalIter)->visual).SetOffScene(self);
1841 for(auto replacedIter = mVisuals.Begin(), end = mVisuals.End(); replacedIter != end; replacedIter++)
1843 (*replacedIter)->pending = false;
1846 mRemoveVisuals.Clear();
1849 void Control::Impl::SetMargin(Extents margin)
1851 mControlImpl.mImpl->mMargin = margin;
1853 // Trigger a size negotiation request that may be needed when setting a margin.
1854 mControlImpl.RelayoutRequest();
1857 Extents Control::Impl::GetMargin() const
1859 return mControlImpl.mImpl->mMargin;
1862 void Control::Impl::SetPadding(Extents padding)
1864 mControlImpl.mImpl->mPadding = padding;
1866 // Trigger a size negotiation request that may be needed when setting a padding.
1867 mControlImpl.RelayoutRequest();
1870 Extents Control::Impl::GetPadding() const
1872 return mControlImpl.mImpl->mPadding;
1875 void Control::Impl::SetInputMethodContext(InputMethodContext& inputMethodContext)
1877 mInputMethodContext = inputMethodContext;
1880 bool Control::Impl::FilterKeyEvent(const KeyEvent& event)
1882 bool consumed(false);
1884 if(mInputMethodContext)
1886 consumed = mInputMethodContext.FilterEventKey(event);
1891 DevelControl::VisualEventSignalType& Control::Impl::VisualEventSignal()
1893 return mVisualEventSignal;
1896 void Control::Impl::SetShadow(const Property::Map& map)
1898 Toolkit::Visual::Base visual = Toolkit::VisualFactory::Get().CreateVisual(map);
1899 visual.SetName("shadow");
1903 mControlImpl.mImpl->RegisterVisual(Toolkit::DevelControl::Property::SHADOW, visual, DepthIndex::BACKGROUND_EFFECT);
1905 mControlImpl.RelayoutRequest();
1909 void Control::Impl::ClearShadow()
1911 mControlImpl.mImpl->UnregisterVisual(Toolkit::DevelControl::Property::SHADOW);
1913 // Trigger a size negotiation request that may be needed when unregistering a visual.
1914 mControlImpl.RelayoutRequest();
1917 Dali::Property Control::Impl::GetVisualProperty(Dali::Property::Index index, Dali::Property::Key visualPropertyKey)
1919 Toolkit::Visual::Base visual = GetVisualByIndex(mVisuals, index);
1922 Internal::Visual::Base& visualImpl = Toolkit::GetImplementation(visual);
1923 return visualImpl.GetPropertyObject(visualPropertyKey);
1927 return Dali::Property(handle, Property::INVALID_INDEX);
1930 void Control::Impl::MakeVisualTransition(Dali::Animation& animation, Dali::Toolkit::Control source, Dali::Property::Index visualIndex, AlphaFunction alphaFunction, TimePeriod timePeriod)
1932 Dali::Toolkit::Control sourceHandle = Dali::Toolkit::Control::DownCast(source);
1933 Property::Map sourceMap = sourceHandle.GetProperty<Property::Map>(visualIndex);
1934 Dali::Toolkit::Control destinationHandle = Dali::Toolkit::Control::DownCast(mControlImpl.Self());
1935 Property::Map destinationMap = destinationHandle.GetProperty<Property::Map>(visualIndex);
1937 Vector4 mixColor(1.0f, 1.0f, 1.0f, 1.0f);
1938 Vector4 cornerRadius(0.0f, 0.0f, 0.0f, 0.0f);
1939 float borderlineWidth(0.0f);
1940 Vector4 borderlineColor(0.0f, 0.0f, 0.0f, 1.0f);
1941 float borderlineOffset(0.0f);
1943 if(!destinationMap.Empty())
1945 static auto findValueVector4 = [](const Property::Map& map, Property::Index index, const Vector4& defaultValue = Vector4()) -> Vector4 {
1946 Property::Value* propertyValue = map.Find(index);
1949 return propertyValue->Get<Vector4>();
1951 return defaultValue;
1954 static auto findValueFloat = [](const Property::Map& map, Property::Index index, const float& defaultValue = 0.0f) -> float {
1955 Property::Value* propertyValue = map.Find(index);
1958 return propertyValue->Get<float>();
1960 return defaultValue;
1963 mixColor = findValueVector4(destinationMap, Dali::Toolkit::Visual::Property::MIX_COLOR, mixColor);
1964 cornerRadius = findValueVector4(destinationMap, Toolkit::DevelVisual::Property::CORNER_RADIUS, cornerRadius);
1965 borderlineWidth = findValueFloat(destinationMap, Toolkit::DevelVisual::Property::BORDERLINE_WIDTH, borderlineWidth);
1966 borderlineColor = findValueVector4(destinationMap, Toolkit::DevelVisual::Property::BORDERLINE_COLOR, borderlineColor);
1967 borderlineOffset = findValueFloat(destinationMap, Toolkit::DevelVisual::Property::BORDERLINE_OFFSET, borderlineOffset);
1969 if(sourceMap.Empty())
1971 sourceMap.Insert(Toolkit::Visual::Property::TYPE, Toolkit::Visual::COLOR);
1972 sourceMap.Insert(Dali::Toolkit::Visual::Property::MIX_COLOR, Color::TRANSPARENT);
1973 sourceMap.Insert(Toolkit::DevelVisual::Property::CORNER_RADIUS, cornerRadius);
1974 sourceMap.Insert(Toolkit::DevelVisual::Property::BORDERLINE_WIDTH, borderlineWidth);
1975 sourceMap.Insert(Toolkit::DevelVisual::Property::BORDERLINE_COLOR, borderlineColor);
1976 sourceMap.Insert(Toolkit::DevelVisual::Property::BORDERLINE_OFFSET, borderlineOffset);
1979 Vector4 sourceMixColor = findValueVector4(sourceMap, Dali::Toolkit::Visual::Property::MIX_COLOR, mixColor);
1980 Vector4 sourceCornerRadius = findValueVector4(sourceMap, Toolkit::DevelVisual::Property::CORNER_RADIUS, cornerRadius);
1981 float sourceBorderlineWidth = findValueFloat(sourceMap, Toolkit::DevelVisual::Property::BORDERLINE_WIDTH, borderlineWidth);
1982 Vector4 sourceBorderlineColor = findValueVector4(sourceMap, Toolkit::DevelVisual::Property::BORDERLINE_COLOR, borderlineColor);
1983 float sourceBorderlineOffset = findValueFloat(sourceMap, Toolkit::DevelVisual::Property::BORDERLINE_OFFSET, borderlineOffset);
1985 std::vector<Dali::Property> properties;
1986 std::vector<std::pair<Property::Value, Property::Value>> values;
1988 if(Vector3(sourceMixColor) != Vector3(mixColor))
1990 properties.push_back(GetVisualProperty(visualIndex, Dali::Toolkit::Visual::Property::MIX_COLOR));
1991 values.push_back(std::make_pair(Vector3(sourceMixColor), Vector3(mixColor)));
1994 if(std::abs(sourceMixColor.a - mixColor.a) > Math::MACHINE_EPSILON_1)
1996 properties.push_back(GetVisualProperty(visualIndex, Dali::Toolkit::Visual::Property::OPACITY));
1997 values.push_back(std::make_pair(sourceMixColor.a, mixColor.a));
2000 if(sourceCornerRadius != cornerRadius)
2002 properties.push_back(GetVisualProperty(visualIndex, Dali::Toolkit::DevelVisual::Property::CORNER_RADIUS));
2003 values.push_back(std::make_pair(sourceCornerRadius, cornerRadius));
2006 if(sourceBorderlineWidth != borderlineWidth)
2008 properties.push_back(GetVisualProperty(visualIndex, Dali::Toolkit::DevelVisual::Property::BORDERLINE_WIDTH));
2009 values.push_back(std::make_pair(sourceBorderlineWidth, borderlineWidth));
2012 if(sourceBorderlineColor != borderlineColor)
2014 properties.push_back(GetVisualProperty(visualIndex, Dali::Toolkit::DevelVisual::Property::BORDERLINE_COLOR));
2015 values.push_back(std::make_pair(sourceBorderlineColor, borderlineColor));
2018 if(sourceBorderlineOffset != borderlineOffset)
2020 properties.push_back(GetVisualProperty(visualIndex, Dali::Toolkit::DevelVisual::Property::BORDERLINE_OFFSET));
2021 values.push_back(std::make_pair(sourceBorderlineOffset, borderlineOffset));
2024 for(uint32_t i = 0; i < properties.size(); ++i)
2026 if(timePeriod.delaySeconds > 0.0f)
2028 Dali::KeyFrames initialKeyframes = Dali::KeyFrames::New();
2029 initialKeyframes.Add(0.0f, values[i].first);
2030 initialKeyframes.Add(1.0f, values[i].first);
2031 animation.AnimateBetween(properties[i], initialKeyframes, TimePeriod(timePeriod.delaySeconds));
2033 Dali::KeyFrames keyframes = Dali::KeyFrames::New();
2034 keyframes.Add(0.0f, values[i].first);
2035 keyframes.Add(1.0f, values[i].second);
2036 animation.AnimateBetween(properties[i], keyframes, alphaFunction, timePeriod);
2041 void Control::Impl::EmitResourceReadySignal()
2043 if(!mIsEmittingResourceReadySignal)
2045 // Guard against calls to emit the signal during the callback
2046 mIsEmittingResourceReadySignal = true;
2048 // If the signal handler changes visual, it may become ready during this call & therefore this method will
2049 // get called again recursively. If so, mNeedToEmitResourceReady is set below, and we act on it after that secondary
2050 // invocation has completed by notifying in an Idle callback to prevent further recursion.
2051 Dali::Toolkit::Control handle(mControlImpl.GetOwner());
2052 mResourceReadySignal.Emit(handle);
2054 if(mNeedToEmitResourceReady)
2056 // Add idler to emit the signal again
2059 // The callback manager takes the ownership of the callback object.
2060 mIdleCallback = MakeCallback(this, &Control::Impl::OnIdleCallback);
2061 Adaptor::Get().AddIdle(mIdleCallback, false);
2065 mIsEmittingResourceReadySignal = false;
2069 mNeedToEmitResourceReady = true;
2073 void Control::Impl::OnIdleCallback()
2075 if(mNeedToEmitResourceReady)
2078 mNeedToEmitResourceReady = false;
2080 // A visual is ready so control may need relayouting if staged
2081 if(mControlImpl.Self().GetProperty<bool>(Actor::Property::CONNECTED_TO_SCENE))
2083 mControlImpl.RelayoutRequest();
2086 EmitResourceReadySignal();
2089 // Set the pointer to null as the callback manager deletes the callback after execute it.
2090 mIdleCallback = nullptr;
2093 Dali::Accessibility::Accessible* Control::Impl::GetAccessibilityObject()
2095 if(!mAccessibilityObject)
2097 mAccessibilityObject = mAccessibilityConstructor(mControlImpl.Self());
2099 return mAccessibilityObject.get();
2102 Dali::Accessibility::Accessible* Control::Impl::GetAccessibilityObject(Dali::Actor actor)
2106 auto control = Dali::Toolkit::Control::DownCast(actor);
2109 auto controlImpl = static_cast<Internal::Control*>(&control.GetImplementation());
2110 return controlImpl->mImpl->GetAccessibilityObject();
2116 } // namespace Internal
2118 } // namespace Toolkit