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 static bool IsShowingGeometryOnScreen(Dali::Rect<> rect)
444 return rect.width > 0 && rect.height > 0;
447 } // unnamed namespace
450 // Properties registered without macro to use specific member variables.
451 const PropertyRegistration Control::Impl::PROPERTY_1(typeRegistration, "styleName", Toolkit::Control::Property::STYLE_NAME, Property::STRING, &Control::Impl::SetProperty, &Control::Impl::GetProperty);
452 const PropertyRegistration Control::Impl::PROPERTY_4(typeRegistration, "keyInputFocus", Toolkit::Control::Property::KEY_INPUT_FOCUS, Property::BOOLEAN, &Control::Impl::SetProperty, &Control::Impl::GetProperty);
453 const PropertyRegistration Control::Impl::PROPERTY_5(typeRegistration, "background", Toolkit::Control::Property::BACKGROUND, Property::MAP, &Control::Impl::SetProperty, &Control::Impl::GetProperty);
454 const PropertyRegistration Control::Impl::PROPERTY_6(typeRegistration, "margin", Toolkit::Control::Property::MARGIN, Property::EXTENTS, &Control::Impl::SetProperty, &Control::Impl::GetProperty);
455 const PropertyRegistration Control::Impl::PROPERTY_7(typeRegistration, "padding", Toolkit::Control::Property::PADDING, Property::EXTENTS, &Control::Impl::SetProperty, &Control::Impl::GetProperty);
456 const PropertyRegistration Control::Impl::PROPERTY_8(typeRegistration, "tooltip", Toolkit::DevelControl::Property::TOOLTIP, Property::MAP, &Control::Impl::SetProperty, &Control::Impl::GetProperty);
457 const PropertyRegistration Control::Impl::PROPERTY_9(typeRegistration, "state", Toolkit::DevelControl::Property::STATE, Property::STRING, &Control::Impl::SetProperty, &Control::Impl::GetProperty);
458 const PropertyRegistration Control::Impl::PROPERTY_10(typeRegistration, "subState", Toolkit::DevelControl::Property::SUB_STATE, Property::STRING, &Control::Impl::SetProperty, &Control::Impl::GetProperty);
459 const PropertyRegistration Control::Impl::PROPERTY_11(typeRegistration, "leftFocusableActorId", Toolkit::DevelControl::Property::LEFT_FOCUSABLE_ACTOR_ID, Property::INTEGER, &Control::Impl::SetProperty, &Control::Impl::GetProperty);
460 const PropertyRegistration Control::Impl::PROPERTY_12(typeRegistration, "rightFocusableActorId", Toolkit::DevelControl::Property::RIGHT_FOCUSABLE_ACTOR_ID, Property::INTEGER, &Control::Impl::SetProperty, &Control::Impl::GetProperty);
461 const PropertyRegistration Control::Impl::PROPERTY_13(typeRegistration, "upFocusableActorId", Toolkit::DevelControl::Property::UP_FOCUSABLE_ACTOR_ID, Property::INTEGER, &Control::Impl::SetProperty, &Control::Impl::GetProperty);
462 const PropertyRegistration Control::Impl::PROPERTY_14(typeRegistration, "downFocusableActorId", Toolkit::DevelControl::Property::DOWN_FOCUSABLE_ACTOR_ID, Property::INTEGER, &Control::Impl::SetProperty, &Control::Impl::GetProperty);
463 const PropertyRegistration Control::Impl::PROPERTY_15(typeRegistration, "shadow", Toolkit::DevelControl::Property::SHADOW, Property::MAP, &Control::Impl::SetProperty, &Control::Impl::GetProperty);
464 const PropertyRegistration Control::Impl::PROPERTY_16(typeRegistration, "accessibilityName", Toolkit::DevelControl::Property::ACCESSIBILITY_NAME, Property::STRING, &Control::Impl::SetProperty, &Control::Impl::GetProperty);
465 const PropertyRegistration Control::Impl::PROPERTY_17(typeRegistration, "accessibilityDescription", Toolkit::DevelControl::Property::ACCESSIBILITY_DESCRIPTION, Property::STRING, &Control::Impl::SetProperty, &Control::Impl::GetProperty);
466 const PropertyRegistration Control::Impl::PROPERTY_18(typeRegistration, "accessibilityTranslationDomain", Toolkit::DevelControl::Property::ACCESSIBILITY_TRANSLATION_DOMAIN, Property::STRING, &Control::Impl::SetProperty, &Control::Impl::GetProperty);
467 const PropertyRegistration Control::Impl::PROPERTY_19(typeRegistration, "accessibilityRole", Toolkit::DevelControl::Property::ACCESSIBILITY_ROLE, Property::INTEGER, &Control::Impl::SetProperty, &Control::Impl::GetProperty);
468 const PropertyRegistration Control::Impl::PROPERTY_20(typeRegistration, "accessibilityHighlightable", Toolkit::DevelControl::Property::ACCESSIBILITY_HIGHLIGHTABLE, Property::BOOLEAN, &Control::Impl::SetProperty, &Control::Impl::GetProperty);
469 const PropertyRegistration Control::Impl::PROPERTY_21(typeRegistration, "accessibilityAttributes", Toolkit::DevelControl::Property::ACCESSIBILITY_ATTRIBUTES, Property::MAP, &Control::Impl::SetProperty, &Control::Impl::GetProperty);
472 Control::Impl::Impl(Control& controlImpl)
473 : mControlImpl(controlImpl),
474 mState(Toolkit::DevelControl::NORMAL),
476 mLeftFocusableActorId(-1),
477 mRightFocusableActorId(-1),
478 mUpFocusableActorId(-1),
479 mDownFocusableActorId(-1),
481 mBackgroundColor(Color::TRANSPARENT),
482 mStartingPinchScale(nullptr),
484 mPadding(0, 0, 0, 0),
486 mKeyInputFocusGainedSignal(),
487 mKeyInputFocusLostSignal(),
488 mResourceReadySignal(),
489 mVisualEventSignal(),
490 mAccessibilityGetNameSignal(),
491 mAccessibilityGetDescriptionSignal(),
492 mAccessibilityDoGestureSignal(),
493 mPinchGestureDetector(),
494 mPanGestureDetector(),
495 mTapGestureDetector(),
496 mLongPressGestureDetector(),
498 mInputMethodContext(),
499 mIdleCallback(nullptr),
500 mFlags(Control::ControlBehaviour(CONTROL_BEHAVIOUR_DEFAULT)),
501 mIsKeyboardNavigationSupported(false),
502 mIsKeyboardFocusGroup(false),
503 mIsEmittingResourceReadySignal(false),
504 mNeedToEmitResourceReady(false)
506 Dali::Accessibility::Accessible::RegisterControlAccessibilityGetter(
507 [](Dali::Actor actor) -> Dali::Accessibility::Accessible* {
508 return Control::Impl::GetAccessibilityObject(actor);
511 mAccessibilityConstructor = [](Dali::Actor actor) -> std::unique_ptr<Dali::Accessibility::Accessible> {
512 return std::unique_ptr<Dali::Accessibility::Accessible>(new DevelControl::AccessibleImpl(actor, Dali::Accessibility::Role::UNKNOWN));
515 size_t length = static_cast<size_t>(Dali::Accessibility::RelationType::MAX_COUNT);
516 mAccessibilityRelations.reserve(length);
517 for(auto i = 0u; i < length; ++i)
519 mAccessibilityRelations.push_back({});
523 Control::Impl::~Impl()
525 for(auto&& iter : mVisuals)
527 StopObservingVisual(iter->visual);
530 for(auto&& iter : mRemoveVisuals)
532 StopObservingVisual(iter->visual);
535 // All gesture detectors will be destroyed so no need to disconnect.
536 delete mStartingPinchScale;
538 if(mIdleCallback && Adaptor::IsAvailable())
540 // Removes the callback from the callback manager in case the control is destroyed before the callback is executed.
541 Adaptor::Get().RemoveIdle(mIdleCallback);
545 Control::Impl& Control::Impl::Get(Internal::Control& internalControl)
547 return *internalControl.mImpl;
550 const Control::Impl& Control::Impl::Get(const Internal::Control& internalControl)
552 return *internalControl.mImpl;
555 void Control::Impl::CheckHighlightedObjectGeometry()
557 auto accessibleImpl = dynamic_cast<Dali::Toolkit::DevelControl::AccessibleImpl*>(mAccessibilityObject.get());
560 DALI_LOG_ERROR("accessibleImpl is not a pointer to a DevelControl::AccessibleImpl type");
564 auto lastPosition = accessibleImpl->GetLastPosition();
565 auto accessibleRect = accessibleImpl->GetExtents(Dali::Accessibility::CoordinateType::WINDOW);
566 auto rect = GetShowingGeometry(accessibleRect, accessibleImpl);
568 switch(mAccessibilityLastScreenRelativeMoveType)
570 case Dali::Accessibility::ScreenRelativeMoveType::OUTSIDE:
572 if(IsShowingGeometryOnScreen(rect))
574 mAccessibilityLastScreenRelativeMoveType = Dali::Accessibility::ScreenRelativeMoveType::INSIDE;
578 case Dali::Accessibility::ScreenRelativeMoveType::INSIDE:
580 if(rect.width < 0 && accessibleRect.x != lastPosition.x)
582 mAccessibilityLastScreenRelativeMoveType = (accessibleRect.x < lastPosition.x) ? Dali::Accessibility::ScreenRelativeMoveType::OUTGOING_TOP_LEFT : Dali::Accessibility::ScreenRelativeMoveType::OUTGOING_BOTTOM_RIGHT;
584 if(rect.height < 0 && accessibleRect.y != lastPosition.y)
586 mAccessibilityLastScreenRelativeMoveType = (accessibleRect.y < lastPosition.y) ? Dali::Accessibility::ScreenRelativeMoveType::OUTGOING_TOP_LEFT : Dali::Accessibility::ScreenRelativeMoveType::OUTGOING_BOTTOM_RIGHT;
588 // notify AT-clients on outgoing moves only
589 if(mAccessibilityLastScreenRelativeMoveType != Dali::Accessibility::ScreenRelativeMoveType::INSIDE)
591 mAccessibilityObject.get()->EmitMovedOutOfScreen(mAccessibilityLastScreenRelativeMoveType);
595 case Dali::Accessibility::ScreenRelativeMoveType::OUTGOING_TOP_LEFT:
596 case Dali::Accessibility::ScreenRelativeMoveType::OUTGOING_BOTTOM_RIGHT:
598 if(IsShowingGeometryOnScreen(rect))
600 mAccessibilityLastScreenRelativeMoveType = Dali::Accessibility::ScreenRelativeMoveType::INSIDE;
604 mAccessibilityLastScreenRelativeMoveType = Dali::Accessibility::ScreenRelativeMoveType::OUTSIDE;
614 accessibleImpl->SetLastPosition(Vector2(accessibleRect.x, accessibleRect.y));
617 void Control::Impl::RegisterAccessibilityPositionPropertyNotification()
619 if(mIsAccessibilityPositionPropertyNotificationSet)
623 // set default value until first move of object is detected
624 mAccessibilityLastScreenRelativeMoveType = Dali::Accessibility::ScreenRelativeMoveType::OUTSIDE;
625 // recalculate mAccessibilityLastScreenRelativeMoveType accordingly to the initial position
626 CheckHighlightedObjectGeometry();
627 mAccessibilityPositionNotification = mControlImpl.Self().AddPropertyNotification(Actor::Property::WORLD_POSITION, StepCondition(1.0f, 1.0f));
628 mAccessibilityPositionNotification.SetNotifyMode(PropertyNotification::NOTIFY_ON_CHANGED);
629 mAccessibilityPositionNotification.NotifySignal().Connect(this, [this](PropertyNotification&){ CheckHighlightedObjectGeometry(); });
630 mIsAccessibilityPositionPropertyNotificationSet = true;
633 void Control::Impl::UnregisterAccessibilityPositionPropertyNotification()
635 mControlImpl.Self().RemovePropertyNotification(mAccessibilityPositionNotification);
636 mIsAccessibilityPositionPropertyNotificationSet = false;
639 // Gesture Detection Methods
640 void Control::Impl::PinchDetected(Actor actor, const PinchGesture& pinch)
642 mControlImpl.OnPinch(pinch);
645 void Control::Impl::PanDetected(Actor actor, const PanGesture& pan)
647 mControlImpl.OnPan(pan);
650 void Control::Impl::TapDetected(Actor actor, const TapGesture& tap)
652 mControlImpl.OnTap(tap);
655 void Control::Impl::LongPressDetected(Actor actor, const LongPressGesture& longPress)
657 mControlImpl.OnLongPress(longPress);
660 void Control::Impl::RegisterVisual(Property::Index index, Toolkit::Visual::Base& visual)
662 RegisterVisual(index, visual, VisualState::ENABLED, DepthIndexValue::NOT_SET);
665 void Control::Impl::RegisterVisual(Property::Index index, Toolkit::Visual::Base& visual, int depthIndex)
667 RegisterVisual(index, visual, VisualState::ENABLED, DepthIndexValue::SET, depthIndex);
670 void Control::Impl::RegisterVisual(Property::Index index, Toolkit::Visual::Base& visual, bool enabled)
672 RegisterVisual(index, visual, (enabled ? VisualState::ENABLED : VisualState::DISABLED), DepthIndexValue::NOT_SET);
675 void Control::Impl::RegisterVisual(Property::Index index, Toolkit::Visual::Base& visual, bool enabled, int depthIndex)
677 RegisterVisual(index, visual, (enabled ? VisualState::ENABLED : VisualState::DISABLED), DepthIndexValue::SET, depthIndex);
680 void Control::Impl::RegisterVisual(Property::Index index, Toolkit::Visual::Base& visual, VisualState::Type enabled, DepthIndexValue::Type depthIndexValueSet, int depthIndex)
682 DALI_LOG_INFO(gLogFilter, Debug::Concise, "RegisterVisual:%d \n", index);
684 bool visualReplaced(false);
685 Actor self = mControlImpl.Self();
687 // Set the depth index, if not set by caller this will be either the current visual depth, max depth of all visuals
689 int requiredDepthIndex = visual.GetDepthIndex();
691 if(depthIndexValueSet == DepthIndexValue::SET)
693 requiredDepthIndex = depthIndex;
696 // Visual replacement, existing visual should only be removed from stage when replacement ready.
697 if(!mVisuals.Empty())
699 RegisteredVisualContainer::Iterator registeredVisualsiter;
700 // Check if visual (index) is already registered, this is the current visual.
701 if(FindVisual(index, mVisuals, registeredVisualsiter))
703 Toolkit::Visual::Base& currentRegisteredVisual = (*registeredVisualsiter)->visual;
704 if(currentRegisteredVisual)
706 // Store current visual depth index as may need to set the replacement visual to same depth
707 const int currentDepthIndex = (*registeredVisualsiter)->visual.GetDepthIndex();
709 // No longer required to know if the replaced visual's resources are ready
710 StopObservingVisual(currentRegisteredVisual);
712 // If control staged and visual enabled then visuals will be swapped once ready
713 if(self.GetProperty<bool>(Actor::Property::CONNECTED_TO_SCENE) && enabled)
715 // Check if visual is currently in the process of being replaced ( is in removal container )
716 RegisteredVisualContainer::Iterator visualQueuedForRemoval;
717 if(FindVisual(index, mRemoveVisuals, visualQueuedForRemoval))
719 // Visual with same index is already in removal container so current visual pending
720 // Only the the last requested visual will be displayed so remove current visual which is staged but not ready.
721 Toolkit::GetImplementation(currentRegisteredVisual).SetOffScene(self);
722 mVisuals.Erase(registeredVisualsiter);
726 // current visual not already in removal container so add now.
727 DALI_LOG_INFO(gLogFilter, Debug::Verbose, "RegisterVisual Move current registered visual to removal Queue: %d \n", index);
728 MoveVisual(registeredVisualsiter, mVisuals, mRemoveVisuals);
733 // Control not staged or visual disabled so can just erase from registered visuals and new visual will be added later.
734 mVisuals.Erase(registeredVisualsiter);
737 // 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
738 if((depthIndexValueSet == DepthIndexValue::NOT_SET) &&
739 (visual.GetDepthIndex() == 0))
741 requiredDepthIndex = currentDepthIndex;
745 visualReplaced = true;
749 // If not set, set the name of the visual to the same name as the control's property.
750 // ( If the control has been type registered )
751 if(visual.GetName().empty())
753 // returns empty string if index is not found as long as index is not -1
754 std::string visualName = self.GetPropertyName(index);
755 if(!visualName.empty())
757 DALI_LOG_INFO(gLogFilter, Debug::Concise, "Setting visual name for property %d to %s\n", index, visualName.c_str());
758 visual.SetName(visualName);
762 if(!visualReplaced) // New registration entry
764 // 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
765 if((depthIndexValueSet == DepthIndexValue::NOT_SET) &&
766 (mVisuals.Size() > 0) &&
767 (visual.GetDepthIndex() == 0))
769 int maxDepthIndex = std::numeric_limits<int>::min();
771 RegisteredVisualContainer::ConstIterator iter;
772 const RegisteredVisualContainer::ConstIterator endIter = mVisuals.End();
773 for(iter = mVisuals.Begin(); iter != endIter; iter++)
775 const int visualDepthIndex = (*iter)->visual.GetDepthIndex();
776 if(visualDepthIndex > maxDepthIndex)
778 maxDepthIndex = visualDepthIndex;
781 ++maxDepthIndex; // Add one to the current maximum depth index so that our added visual appears on top
782 requiredDepthIndex = std::max(0, maxDepthIndex); // Start at zero if maxDepth index belongs to a background
788 // Set determined depth index
789 visual.SetDepthIndex(requiredDepthIndex);
791 // Monitor when the visual resources are ready
792 StartObservingVisual(visual);
794 DALI_LOG_INFO(gLogFilter, Debug::Concise, "New Visual registration index[%d] depth[%d]\n", index, requiredDepthIndex);
795 RegisteredVisual* newRegisteredVisual = new RegisteredVisual(index, visual, (enabled == VisualState::ENABLED ? true : false), (visualReplaced && enabled));
796 mVisuals.PushBack(newRegisteredVisual);
798 Internal::Visual::Base& visualImpl = Toolkit::GetImplementation(visual);
799 // Put on stage if enabled and the control is already on the stage
800 if((enabled == VisualState::ENABLED) && self.GetProperty<bool>(Actor::Property::CONNECTED_TO_SCENE))
802 visualImpl.SetOnScene(self);
804 else if(visualImpl.IsResourceReady()) // When not being staged, check if visual already 'ResourceReady' before it was Registered. ( Resource may have been loaded already )
806 ResourceReady(visualImpl);
810 DALI_LOG_INFO(gLogFilter, Debug::Verbose, "Control::RegisterVisual() Registered %s(%d), enabled:%s\n", visual.GetName().c_str(), index, enabled ? "true" : "false");
813 void Control::Impl::UnregisterVisual(Property::Index index)
815 RegisteredVisualContainer::Iterator iter;
816 if(FindVisual(index, mVisuals, iter))
818 // stop observing visual
819 StopObservingVisual((*iter)->visual);
821 Actor self(mControlImpl.Self());
822 Toolkit::GetImplementation((*iter)->visual).SetOffScene(self);
823 (*iter)->visual.Reset();
824 mVisuals.Erase(iter);
827 if(FindVisual(index, mRemoveVisuals, iter))
829 Actor self(mControlImpl.Self());
830 Toolkit::GetImplementation((*iter)->visual).SetOffScene(self);
831 (*iter)->pending = false;
832 (*iter)->visual.Reset();
833 mRemoveVisuals.Erase(iter);
837 Toolkit::Visual::Base Control::Impl::GetVisual(Property::Index index) const
839 RegisteredVisualContainer::Iterator iter;
840 if(FindVisual(index, mVisuals, iter))
842 return (*iter)->visual;
845 return Toolkit::Visual::Base();
848 void Control::Impl::EnableVisual(Property::Index index, bool enable)
850 DALI_LOG_INFO(gLogFilter, Debug::General, "Control::EnableVisual(%d, %s)\n", index, enable ? "T" : "F");
852 RegisteredVisualContainer::Iterator iter;
853 if(FindVisual(index, mVisuals, iter))
855 if((*iter)->enabled == enable)
857 DALI_LOG_INFO(gLogFilter, Debug::Verbose, "Control::EnableVisual Visual %s(%d) already %s\n", (*iter)->visual.GetName().c_str(), index, enable ? "enabled" : "disabled");
861 (*iter)->enabled = enable;
862 Actor parentActor = mControlImpl.Self();
863 if(mControlImpl.Self().GetProperty<bool>(Actor::Property::CONNECTED_TO_SCENE)) // If control not on Scene then Visual will be added when SceneConnection is called.
867 DALI_LOG_INFO(gLogFilter, Debug::Verbose, "Control::EnableVisual Setting %s(%d) on stage \n", (*iter)->visual.GetName().c_str(), index);
868 Toolkit::GetImplementation((*iter)->visual).SetOnScene(parentActor);
872 DALI_LOG_INFO(gLogFilter, Debug::Verbose, "Control::EnableVisual Setting %s(%d) off stage \n", (*iter)->visual.GetName().c_str(), index);
873 Toolkit::GetImplementation((*iter)->visual).SetOffScene(parentActor); // No need to call if control not staged.
879 DALI_LOG_WARNING("Control::EnableVisual(%d, %s) FAILED - NO SUCH VISUAL\n", index, enable ? "T" : "F");
883 bool Control::Impl::IsVisualEnabled(Property::Index index) const
885 RegisteredVisualContainer::Iterator iter;
886 if(FindVisual(index, mVisuals, iter))
888 return (*iter)->enabled;
893 void Control::Impl::StopObservingVisual(Toolkit::Visual::Base& visual)
895 Internal::Visual::Base& visualImpl = Toolkit::GetImplementation(visual);
897 // Stop observing the visual
898 visualImpl.RemoveEventObserver(*this);
901 void Control::Impl::StartObservingVisual(Toolkit::Visual::Base& visual)
903 Internal::Visual::Base& visualImpl = Toolkit::GetImplementation(visual);
905 // start observing the visual for events
906 visualImpl.AddEventObserver(*this);
909 // Called by a Visual when it's resource is ready
910 void Control::Impl::ResourceReady(Visual::Base& object)
912 DALI_LOG_INFO(gLogFilter, Debug::Verbose, "Control::Impl::ResourceReady() replacements pending[%d]\n", mRemoveVisuals.Count());
914 Actor self = mControlImpl.Self();
916 // A resource is ready, find resource in the registered visuals container and get its index
917 for(auto registeredIter = mVisuals.Begin(), end = mVisuals.End(); registeredIter != end; ++registeredIter)
919 Internal::Visual::Base& registeredVisualImpl = Toolkit::GetImplementation((*registeredIter)->visual);
921 if(&object == ®isteredVisualImpl)
923 RegisteredVisualContainer::Iterator visualToRemoveIter;
924 // Find visual with the same index in the removal container
925 // Set if off stage as it's replacement is now ready.
926 // Remove if from removal list as now removed from stage.
927 // Set Pending flag on the ready visual to false as now ready.
928 if(FindVisual((*registeredIter)->index, mRemoveVisuals, visualToRemoveIter))
930 (*registeredIter)->pending = false;
931 Toolkit::GetImplementation((*visualToRemoveIter)->visual).SetOffScene(self);
932 mRemoveVisuals.Erase(visualToRemoveIter);
938 // A visual is ready so control may need relayouting if staged
939 if(self.GetProperty<bool>(Actor::Property::CONNECTED_TO_SCENE))
941 mControlImpl.RelayoutRequest();
944 // Emit signal if all enabled visuals registered by the control are ready.
945 if(IsResourceReady())
948 mNeedToEmitResourceReady = false;
950 EmitResourceReadySignal();
954 void Control::Impl::NotifyVisualEvent(Visual::Base& object, Property::Index signalId)
956 for(auto registeredIter = mVisuals.Begin(), end = mVisuals.End(); registeredIter != end; ++registeredIter)
958 Internal::Visual::Base& registeredVisualImpl = Toolkit::GetImplementation((*registeredIter)->visual);
959 if(&object == ®isteredVisualImpl)
961 Dali::Toolkit::Control handle(mControlImpl.GetOwner());
962 mVisualEventSignal.Emit(handle, (*registeredIter)->index, signalId);
968 bool Control::Impl::IsResourceReady() const
970 // Iterate through and check all the enabled visuals are ready
971 for(auto visualIter = mVisuals.Begin();
972 visualIter != mVisuals.End();
975 const Toolkit::Visual::Base visual = (*visualIter)->visual;
976 const Internal::Visual::Base& visualImpl = Toolkit::GetImplementation(visual);
978 // one of the enabled visuals is not ready
979 if(!visualImpl.IsResourceReady() && (*visualIter)->enabled)
987 Toolkit::Visual::ResourceStatus Control::Impl::GetVisualResourceStatus(Property::Index index) const
989 RegisteredVisualContainer::Iterator iter;
990 if(FindVisual(index, mVisuals, iter))
992 const Toolkit::Visual::Base visual = (*iter)->visual;
993 const Internal::Visual::Base& visualImpl = Toolkit::GetImplementation(visual);
994 return visualImpl.GetResourceStatus();
997 return Toolkit::Visual::ResourceStatus::PREPARING;
1000 void Control::Impl::AddTransitions(Dali::Animation& animation,
1001 const Toolkit::TransitionData& handle,
1002 bool createAnimation)
1004 // Setup a Transition from TransitionData.
1005 const Internal::TransitionData& transitionData = Toolkit::GetImplementation(handle);
1006 TransitionData::Iterator end = transitionData.End();
1007 for(TransitionData::Iterator iter = transitionData.Begin();
1011 TransitionData::Animator* animator = (*iter);
1013 Toolkit::Visual::Base visual = GetVisualByName(mVisuals, animator->objectName);
1017 #if defined(DEBUG_ENABLED)
1018 Dali::TypeInfo typeInfo;
1019 ControlWrapper* controlWrapperImpl = dynamic_cast<ControlWrapper*>(&mControlImpl);
1020 if(controlWrapperImpl)
1022 typeInfo = controlWrapperImpl->GetTypeInfo();
1025 DALI_LOG_INFO(gLogFilter, Debug::Concise, "CreateTransition: Found %s visual for %s\n", visual.GetName().c_str(), typeInfo ? typeInfo.GetName().c_str() : "Unknown");
1027 Internal::Visual::Base& visualImpl = Toolkit::GetImplementation(visual);
1028 visualImpl.AnimateProperty(animation, *animator);
1032 DALI_LOG_INFO(gLogFilter, Debug::Concise, "CreateTransition: Could not find visual. Trying actors");
1033 // Otherwise, try any actor children of control (Including the control)
1034 Actor child = mControlImpl.Self().FindChildByName(animator->objectName);
1037 Property::Index propertyIndex = child.GetPropertyIndex(animator->propertyKey);
1038 if(propertyIndex != Property::INVALID_INDEX)
1040 if(animator->animate == false)
1042 if(animator->targetValue.GetType() != Property::NONE)
1044 child.SetProperty(propertyIndex, animator->targetValue);
1047 else // animate the property
1049 if(animator->initialValue.GetType() != Property::NONE)
1051 child.SetProperty(propertyIndex, animator->initialValue);
1054 if(createAnimation && !animation)
1056 animation = Dali::Animation::New(0.1f);
1059 animation.AnimateTo(Property(child, propertyIndex),
1060 animator->targetValue,
1061 animator->alphaFunction,
1062 TimePeriod(animator->timePeriodDelay,
1063 animator->timePeriodDuration));
1071 Dali::Animation Control::Impl::CreateTransition(const Toolkit::TransitionData& transitionData)
1073 Dali::Animation transition;
1075 if(transitionData.Count() > 0)
1077 AddTransitions(transition, transitionData, true);
1082 void Control::Impl::DoAction(Dali::Property::Index visualIndex, Dali::Property::Index actionId, const Dali::Property::Value attributes)
1084 RegisteredVisualContainer::Iterator iter;
1085 if(FindVisual(visualIndex, mVisuals, iter))
1087 Toolkit::GetImplementation((*iter)->visual).DoAction(actionId, attributes);
1091 void Control::Impl::AppendAccessibilityAttribute(const std::string& key, const std::string value)
1093 Property::Value* checkedValue = mAccessibilityAttributes.Find(key);
1096 mAccessibilityAttributes[key] = Property::Value(value);
1100 mAccessibilityAttributes.Insert(key, value);
1104 void Control::Impl::SetProperty(BaseObject* object, Property::Index index, const Property::Value& value)
1106 Toolkit::Control control = Toolkit::Control::DownCast(BaseHandle(object));
1110 Control& controlImpl(GetImplementation(control));
1114 case Toolkit::Control::Property::STYLE_NAME:
1116 controlImpl.SetStyleName(value.Get<std::string>());
1120 case Toolkit::DevelControl::Property::STATE:
1122 bool withTransitions = true;
1123 const Property::Value* valuePtr = &value;
1124 const Property::Map* map = value.GetMap();
1127 Property::Value* value2 = map->Find("withTransitions");
1130 withTransitions = value2->Get<bool>();
1133 valuePtr = map->Find("state");
1138 Toolkit::DevelControl::State state(controlImpl.mImpl->mState);
1139 if(Scripting::GetEnumerationProperty<Toolkit::DevelControl::State>(*valuePtr, ControlStateTable, ControlStateTableCount, state))
1141 controlImpl.mImpl->SetState(state, withTransitions);
1147 case Toolkit::DevelControl::Property::SUB_STATE:
1149 std::string subState;
1150 if(value.Get(subState))
1152 controlImpl.mImpl->SetSubState(subState);
1157 case Toolkit::DevelControl::Property::LEFT_FOCUSABLE_ACTOR_ID:
1160 if(value.Get(focusId))
1162 controlImpl.mImpl->mLeftFocusableActorId = focusId;
1167 case Toolkit::DevelControl::Property::RIGHT_FOCUSABLE_ACTOR_ID:
1170 if(value.Get(focusId))
1172 controlImpl.mImpl->mRightFocusableActorId = focusId;
1177 case Toolkit::DevelControl::Property::UP_FOCUSABLE_ACTOR_ID:
1180 if(value.Get(focusId))
1182 controlImpl.mImpl->mUpFocusableActorId = focusId;
1187 case Toolkit::DevelControl::Property::DOWN_FOCUSABLE_ACTOR_ID:
1190 if(value.Get(focusId))
1192 controlImpl.mImpl->mDownFocusableActorId = focusId;
1197 case Toolkit::Control::Property::KEY_INPUT_FOCUS:
1199 if(value.Get<bool>())
1201 controlImpl.SetKeyInputFocus();
1205 controlImpl.ClearKeyInputFocus();
1210 case Toolkit::Control::Property::BACKGROUND:
1214 const Property::Map* map = value.GetMap();
1215 if(map && !map->Empty())
1217 controlImpl.SetBackground(*map);
1219 else if(value.Get(url))
1221 // don't know the size to load
1222 Toolkit::Visual::Base visual = Toolkit::VisualFactory::Get().CreateVisual(url, ImageDimensions());
1225 controlImpl.mImpl->RegisterVisual(Toolkit::Control::Property::BACKGROUND, visual, DepthIndex::BACKGROUND);
1228 else if(value.Get(color))
1230 controlImpl.SetBackgroundColor(color);
1234 // The background is an empty property map, so we should clear the background
1235 controlImpl.ClearBackground();
1240 case Toolkit::Control::Property::MARGIN:
1243 if(value.Get(margin))
1245 controlImpl.mImpl->SetMargin(margin);
1250 case Toolkit::Control::Property::PADDING:
1253 if(value.Get(padding))
1255 controlImpl.mImpl->SetPadding(padding);
1260 case Toolkit::DevelControl::Property::TOOLTIP:
1262 TooltipPtr& tooltipPtr = controlImpl.mImpl->mTooltip;
1265 tooltipPtr = Tooltip::New(control);
1267 tooltipPtr->SetProperties(value);
1271 case Toolkit::DevelControl::Property::SHADOW:
1273 const Property::Map* map = value.GetMap();
1274 if(map && !map->Empty())
1276 controlImpl.mImpl->SetShadow(*map);
1280 // The shadow is an empty property map, so we should clear the shadow
1281 controlImpl.mImpl->ClearShadow();
1286 case Toolkit::DevelControl::Property::ACCESSIBILITY_NAME:
1291 controlImpl.mImpl->mAccessibilityName = name;
1292 controlImpl.mImpl->mAccessibilityNameSet = true;
1296 controlImpl.mImpl->mAccessibilityNameSet = false;
1301 case Toolkit::DevelControl::Property::ACCESSIBILITY_DESCRIPTION:
1306 controlImpl.mImpl->mAccessibilityDescription = text;
1307 controlImpl.mImpl->mAccessibilityDescriptionSet = true;
1311 controlImpl.mImpl->mAccessibilityDescriptionSet = false;
1316 case Toolkit::DevelControl::Property::ACCESSIBILITY_TRANSLATION_DOMAIN:
1321 controlImpl.mImpl->mAccessibilityTranslationDomain = text;
1322 controlImpl.mImpl->mAccessibilityTranslationDomainSet = true;
1326 controlImpl.mImpl->mAccessibilityTranslationDomainSet = false;
1331 case Toolkit::DevelControl::Property::ACCESSIBILITY_ROLE:
1333 Dali::Accessibility::Role role;
1336 controlImpl.mImpl->mAccessibilityRole = role;
1341 case Toolkit::DevelControl::Property::ACCESSIBILITY_HIGHLIGHTABLE:
1344 if(value.Get(highlightable))
1346 controlImpl.mImpl->mAccessibilityHighlightable = highlightable;
1347 controlImpl.mImpl->mAccessibilityHighlightableSet = true;
1351 controlImpl.mImpl->mAccessibilityHighlightableSet = false;
1356 case Toolkit::DevelControl::Property::ACCESSIBILITY_ATTRIBUTES:
1358 const Property::Map* map = value.GetMap();
1359 if(map && !map->Empty())
1361 controlImpl.mImpl->mAccessibilityAttributes = *map;
1369 Property::Value Control::Impl::GetProperty(BaseObject* object, Property::Index index)
1371 Property::Value value;
1373 Toolkit::Control control = Toolkit::Control::DownCast(BaseHandle(object));
1377 Control& controlImpl(GetImplementation(control));
1381 case Toolkit::Control::Property::STYLE_NAME:
1383 value = controlImpl.GetStyleName();
1387 case Toolkit::DevelControl::Property::STATE:
1389 value = controlImpl.mImpl->mState;
1393 case Toolkit::DevelControl::Property::SUB_STATE:
1395 value = controlImpl.mImpl->mSubStateName;
1399 case Toolkit::DevelControl::Property::LEFT_FOCUSABLE_ACTOR_ID:
1401 value = controlImpl.mImpl->mLeftFocusableActorId;
1405 case Toolkit::DevelControl::Property::RIGHT_FOCUSABLE_ACTOR_ID:
1407 value = controlImpl.mImpl->mRightFocusableActorId;
1411 case Toolkit::DevelControl::Property::UP_FOCUSABLE_ACTOR_ID:
1413 value = controlImpl.mImpl->mUpFocusableActorId;
1417 case Toolkit::DevelControl::Property::DOWN_FOCUSABLE_ACTOR_ID:
1419 value = controlImpl.mImpl->mDownFocusableActorId;
1423 case Toolkit::Control::Property::KEY_INPUT_FOCUS:
1425 value = controlImpl.HasKeyInputFocus();
1429 case Toolkit::Control::Property::BACKGROUND:
1432 Toolkit::Visual::Base visual = controlImpl.mImpl->GetVisual(Toolkit::Control::Property::BACKGROUND);
1435 visual.CreatePropertyMap(map);
1442 case Toolkit::Control::Property::MARGIN:
1444 value = controlImpl.mImpl->GetMargin();
1448 case Toolkit::Control::Property::PADDING:
1450 value = controlImpl.mImpl->GetPadding();
1454 case Toolkit::DevelControl::Property::TOOLTIP:
1457 if(controlImpl.mImpl->mTooltip)
1459 controlImpl.mImpl->mTooltip->CreatePropertyMap(map);
1465 case Toolkit::DevelControl::Property::SHADOW:
1468 Toolkit::Visual::Base visual = controlImpl.mImpl->GetVisual(Toolkit::DevelControl::Property::SHADOW);
1471 visual.CreatePropertyMap(map);
1478 case Toolkit::DevelControl::Property::ACCESSIBILITY_NAME:
1480 if(controlImpl.mImpl->mAccessibilityNameSet)
1482 value = controlImpl.mImpl->mAccessibilityName;
1487 case Toolkit::DevelControl::Property::ACCESSIBILITY_DESCRIPTION:
1489 if(controlImpl.mImpl->mAccessibilityDescriptionSet)
1491 value = controlImpl.mImpl->mAccessibilityDescription;
1496 case Toolkit::DevelControl::Property::ACCESSIBILITY_TRANSLATION_DOMAIN:
1498 if(controlImpl.mImpl->mAccessibilityTranslationDomainSet)
1500 value = controlImpl.mImpl->mAccessibilityTranslationDomain;
1505 case Toolkit::DevelControl::Property::ACCESSIBILITY_ROLE:
1507 value = Property::Value(controlImpl.mImpl->mAccessibilityRole);
1511 case Toolkit::DevelControl::Property::ACCESSIBILITY_HIGHLIGHTABLE:
1513 if(controlImpl.mImpl->mAccessibilityHighlightableSet)
1515 value = controlImpl.mImpl->mAccessibilityHighlightable;
1520 case Toolkit::DevelControl::Property::ACCESSIBILITY_ATTRIBUTES:
1522 value = controlImpl.mImpl->mAccessibilityAttributes;
1531 void Control::Impl::RemoveAccessibilityAttribute(const std::string& key)
1533 Property::Value* value = mAccessibilityAttributes.Find(key);
1536 mAccessibilityAttributes[key] = Property::Value();
1540 void Control::Impl::ClearAccessibilityAttributes()
1542 mAccessibilityAttributes.Clear();
1545 void Control::Impl::SetAccessibilityReadingInfoType(const Dali::Accessibility::ReadingInfoTypes types)
1547 std::string value{};
1548 if(types[Dali::Accessibility::ReadingInfoType::NAME])
1550 value += READING_INFO_TYPE_NAME;
1552 if(types[Dali::Accessibility::ReadingInfoType::ROLE])
1556 value += READING_INFO_TYPE_SEPARATOR;
1558 value += READING_INFO_TYPE_ROLE;
1560 if(types[Dali::Accessibility::ReadingInfoType::DESCRIPTION])
1564 value += READING_INFO_TYPE_SEPARATOR;
1566 value += READING_INFO_TYPE_DESCRIPTION;
1568 if(types[Dali::Accessibility::ReadingInfoType::STATE])
1572 value += READING_INFO_TYPE_SEPARATOR;
1574 value += READING_INFO_TYPE_STATE;
1576 AppendAccessibilityAttribute(READING_INFO_TYPE_ATTRIBUTE_NAME, value);
1579 Dali::Accessibility::ReadingInfoTypes Control::Impl::GetAccessibilityReadingInfoType() const
1581 std::string value{};
1582 auto place = mAccessibilityAttributes.Find(READING_INFO_TYPE_ATTRIBUTE_NAME);
1589 Dali::Accessibility::ReadingInfoTypes types;
1590 types[Dali::Accessibility::ReadingInfoType::NAME] = true;
1591 types[Dali::Accessibility::ReadingInfoType::ROLE] = true;
1592 types[Dali::Accessibility::ReadingInfoType::DESCRIPTION] = true;
1593 types[Dali::Accessibility::ReadingInfoType::STATE] = true;
1602 Dali::Accessibility::ReadingInfoTypes types;
1604 if(value.find(READING_INFO_TYPE_NAME) != std::string::npos)
1606 types[Dali::Accessibility::ReadingInfoType::NAME] = true;
1608 if(value.find(READING_INFO_TYPE_ROLE) != std::string::npos)
1610 types[Dali::Accessibility::ReadingInfoType::ROLE] = true;
1612 if(value.find(READING_INFO_TYPE_DESCRIPTION) != std::string::npos)
1614 types[Dali::Accessibility::ReadingInfoType::DESCRIPTION] = true;
1616 if(value.find(READING_INFO_TYPE_STATE) != std::string::npos)
1618 types[Dali::Accessibility::ReadingInfoType::STATE] = true;
1624 void Control::Impl::CopyInstancedProperties(RegisteredVisualContainer& visuals, Dictionary<Property::Map>& instancedProperties)
1626 for(RegisteredVisualContainer::Iterator iter = visuals.Begin(); iter != visuals.End(); iter++)
1630 Property::Map instanceMap;
1631 Toolkit::GetImplementation((*iter)->visual).CreateInstancePropertyMap(instanceMap);
1632 instancedProperties.Add((*iter)->visual.GetName(), instanceMap);
1637 void Control::Impl::RemoveVisual(RegisteredVisualContainer& visuals, const std::string& visualName)
1639 Actor self(mControlImpl.Self());
1641 for(RegisteredVisualContainer::Iterator visualIter = visuals.Begin();
1642 visualIter != visuals.End();
1645 Toolkit::Visual::Base visual = (*visualIter)->visual;
1646 if(visual && visual.GetName() == visualName)
1648 Toolkit::GetImplementation(visual).SetOffScene(self);
1649 (*visualIter)->visual.Reset();
1650 visuals.Erase(visualIter);
1656 void Control::Impl::RemoveVisuals(RegisteredVisualContainer& visuals, DictionaryKeys& removeVisuals)
1658 Actor self(mControlImpl.Self());
1659 for(DictionaryKeys::iterator iter = removeVisuals.begin(); iter != removeVisuals.end(); ++iter)
1661 const std::string visualName = *iter;
1662 RemoveVisual(visuals, visualName);
1666 void Control::Impl::RecreateChangedVisuals(Dictionary<Property::Map>& stateVisualsToChange,
1667 Dictionary<Property::Map>& instancedProperties)
1669 Dali::CustomActor handle(mControlImpl.GetOwner());
1670 for(Dictionary<Property::Map>::iterator iter = stateVisualsToChange.Begin();
1671 iter != stateVisualsToChange.End();
1674 const std::string& visualName = (*iter).key;
1675 const Property::Map& toMap = (*iter).entry;
1677 Actor self = mControlImpl.Self();
1678 RegisteredVisualContainer::Iterator registeredVisualsiter;
1679 // Check if visual (visualName) is already registered, this is the current visual.
1680 if(FindVisual(visualName, mVisuals, registeredVisualsiter))
1682 Toolkit::Visual::Base& visual = (*registeredVisualsiter)->visual;
1685 // No longer required to know if the replaced visual's resources are ready
1686 StopObservingVisual(visual);
1688 // If control staged then visuals will be swapped once ready
1689 if(self.GetProperty<bool>(Actor::Property::CONNECTED_TO_SCENE))
1691 // Check if visual is currently in the process of being replaced ( is in removal container )
1692 RegisteredVisualContainer::Iterator visualQueuedForRemoval;
1693 if(FindVisual(visualName, mRemoveVisuals, visualQueuedForRemoval))
1695 // Visual with same visual name is already in removal container so current visual pending
1696 // Only the the last requested visual will be displayed so remove current visual which is staged but not ready.
1697 Toolkit::GetImplementation(visual).SetOffScene(self);
1698 (*registeredVisualsiter)->visual.Reset();
1699 mVisuals.Erase(registeredVisualsiter);
1703 // current visual not already in removal container so add now.
1704 DALI_LOG_INFO(gLogFilter, Debug::Verbose, "RegisterVisual Move current registered visual to removal Queue: %s \n", visualName.c_str());
1705 MoveVisual(registeredVisualsiter, mVisuals, mRemoveVisuals);
1710 // Control not staged or visual disabled so can just erase from registered visuals and new visual will be added later.
1711 (*registeredVisualsiter)->visual.Reset();
1712 mVisuals.Erase(registeredVisualsiter);
1716 const Property::Map* instancedMap = instancedProperties.FindConst(visualName);
1717 Style::ApplyVisual(handle, visualName, toMap, instancedMap);
1722 void Control::Impl::ReplaceStateVisualsAndProperties(const StylePtr oldState, const StylePtr newState, const std::string& subState)
1724 // Collect all old visual names
1725 DictionaryKeys stateVisualsToRemove;
1728 oldState->visuals.GetKeys(stateVisualsToRemove);
1729 if(!subState.empty())
1731 const StylePtr* oldSubState = oldState->subStates.FindConst(subState);
1734 DictionaryKeys subStateVisualsToRemove;
1735 (*oldSubState)->visuals.GetKeys(subStateVisualsToRemove);
1736 Merge(stateVisualsToRemove, subStateVisualsToRemove);
1741 // Collect all new visual properties
1742 Dictionary<Property::Map> stateVisualsToAdd;
1745 stateVisualsToAdd = newState->visuals;
1746 if(!subState.empty())
1748 const StylePtr* newSubState = newState->subStates.FindConst(subState);
1751 stateVisualsToAdd.Merge((*newSubState)->visuals);
1756 // If a name is in both add/remove, move it to change list.
1757 Dictionary<Property::Map> stateVisualsToChange;
1758 FindChangableVisuals(stateVisualsToAdd, stateVisualsToChange, stateVisualsToRemove);
1760 // Copy instanced properties (e.g. text label) of current visuals
1761 Dictionary<Property::Map> instancedProperties;
1762 CopyInstancedProperties(mVisuals, instancedProperties);
1764 // For each visual in remove list, remove from mVisuals
1765 RemoveVisuals(mVisuals, stateVisualsToRemove);
1767 // For each visual in add list, create and add to mVisuals
1768 Dali::CustomActor handle(mControlImpl.GetOwner());
1769 Style::ApplyVisuals(handle, stateVisualsToAdd, instancedProperties);
1771 // For each visual in change list, if it requires a new visual,
1772 // remove old visual, create and add to mVisuals
1773 RecreateChangedVisuals(stateVisualsToChange, instancedProperties);
1776 void Control::Impl::SetState(DevelControl::State newState, bool withTransitions)
1778 DevelControl::State oldState = mState;
1779 Dali::CustomActor handle(mControlImpl.GetOwner());
1780 DALI_LOG_INFO(gLogFilter, Debug::Concise, "Control::Impl::SetState: %s\n", (mState == DevelControl::NORMAL ? "NORMAL" : (mState == DevelControl::FOCUSED ? "FOCUSED" : (mState == DevelControl::DISABLED ? "DISABLED" : "NONE"))));
1782 if(mState != newState)
1784 // If mState was Disabled, and new state is Focused, should probably
1785 // store that fact, e.g. in another property that FocusManager can access.
1788 // Trigger state change and transitions
1789 // Apply new style, if stylemanager is available
1790 Toolkit::StyleManager styleManager = Toolkit::StyleManager::Get();
1793 const StylePtr stylePtr = GetImpl(styleManager).GetRecordedStyle(Toolkit::Control(mControlImpl.GetOwner()));
1797 std::string oldStateName = Scripting::GetEnumerationName<Toolkit::DevelControl::State>(oldState, ControlStateTable, ControlStateTableCount);
1798 std::string newStateName = Scripting::GetEnumerationName<Toolkit::DevelControl::State>(newState, ControlStateTable, ControlStateTableCount);
1800 const StylePtr* newStateStyle = stylePtr->subStates.Find(newStateName);
1801 const StylePtr* oldStateStyle = stylePtr->subStates.Find(oldStateName);
1802 if(oldStateStyle && newStateStyle)
1804 // Only change if both state styles exist
1805 ReplaceStateVisualsAndProperties(*oldStateStyle, *newStateStyle, mSubStateName);
1812 void Control::Impl::SetSubState(const std::string& subStateName, bool withTransitions)
1814 if(mSubStateName != subStateName)
1816 // Get existing sub-state visuals, and unregister them
1817 Dali::CustomActor handle(mControlImpl.GetOwner());
1819 Toolkit::StyleManager styleManager = Toolkit::StyleManager::Get();
1822 const StylePtr stylePtr = GetImpl(styleManager).GetRecordedStyle(Toolkit::Control(mControlImpl.GetOwner()));
1826 std::string stateName = Scripting::GetEnumerationName<Toolkit::DevelControl::State>(mState, ControlStateTable, ControlStateTableCount);
1828 const StylePtr* state = stylePtr->subStates.Find(stateName);
1831 StylePtr stateStyle(*state);
1833 const StylePtr* newStateStyle = stateStyle->subStates.Find(subStateName);
1834 const StylePtr* oldStateStyle = stateStyle->subStates.Find(mSubStateName);
1835 if(oldStateStyle && newStateStyle)
1838 ReplaceStateVisualsAndProperties(*oldStateStyle, *newStateStyle, empty);
1844 mSubStateName = subStateName;
1848 void Control::Impl::OnSceneDisconnection()
1850 Actor self = mControlImpl.Self();
1852 // Any visuals set for replacement but not yet ready should still be registered.
1853 // Reason: If a request was made to register a new visual but the control removed from scene before visual was ready
1854 // then when this control appears back on stage it should use that new visual.
1856 // Iterate through all registered visuals and set off scene
1857 SetVisualsOffScene(mVisuals, self);
1859 // Visuals pending replacement can now be taken out of the removal list and set off scene
1860 // Iterate through all replacement visuals and add to a move queue then set off scene
1861 for(auto removalIter = mRemoveVisuals.Begin(), end = mRemoveVisuals.End(); removalIter != end; removalIter++)
1863 Toolkit::GetImplementation((*removalIter)->visual).SetOffScene(self);
1866 for(auto replacedIter = mVisuals.Begin(), end = mVisuals.End(); replacedIter != end; replacedIter++)
1868 (*replacedIter)->pending = false;
1871 mRemoveVisuals.Clear();
1874 void Control::Impl::SetMargin(Extents margin)
1876 mControlImpl.mImpl->mMargin = margin;
1878 // Trigger a size negotiation request that may be needed when setting a margin.
1879 mControlImpl.RelayoutRequest();
1882 Extents Control::Impl::GetMargin() const
1884 return mControlImpl.mImpl->mMargin;
1887 void Control::Impl::SetPadding(Extents padding)
1889 mControlImpl.mImpl->mPadding = padding;
1891 // Trigger a size negotiation request that may be needed when setting a padding.
1892 mControlImpl.RelayoutRequest();
1895 Extents Control::Impl::GetPadding() const
1897 return mControlImpl.mImpl->mPadding;
1900 void Control::Impl::SetInputMethodContext(InputMethodContext& inputMethodContext)
1902 mInputMethodContext = inputMethodContext;
1905 bool Control::Impl::FilterKeyEvent(const KeyEvent& event)
1907 bool consumed(false);
1909 if(mInputMethodContext)
1911 consumed = mInputMethodContext.FilterEventKey(event);
1916 DevelControl::VisualEventSignalType& Control::Impl::VisualEventSignal()
1918 return mVisualEventSignal;
1921 void Control::Impl::SetShadow(const Property::Map& map)
1923 Toolkit::Visual::Base visual = Toolkit::VisualFactory::Get().CreateVisual(map);
1924 visual.SetName("shadow");
1928 mControlImpl.mImpl->RegisterVisual(Toolkit::DevelControl::Property::SHADOW, visual, DepthIndex::BACKGROUND_EFFECT);
1930 mControlImpl.RelayoutRequest();
1934 void Control::Impl::ClearShadow()
1936 mControlImpl.mImpl->UnregisterVisual(Toolkit::DevelControl::Property::SHADOW);
1938 // Trigger a size negotiation request that may be needed when unregistering a visual.
1939 mControlImpl.RelayoutRequest();
1942 Dali::Property Control::Impl::GetVisualProperty(Dali::Property::Index index, Dali::Property::Key visualPropertyKey)
1944 Toolkit::Visual::Base visual = GetVisualByIndex(mVisuals, index);
1947 Internal::Visual::Base& visualImpl = Toolkit::GetImplementation(visual);
1948 return visualImpl.GetPropertyObject(visualPropertyKey);
1952 return Dali::Property(handle, Property::INVALID_INDEX);
1955 void Control::Impl::MakeVisualTransition(Dali::Animation& animation, Dali::Toolkit::Control source, Dali::Property::Index visualIndex, AlphaFunction alphaFunction, TimePeriod timePeriod)
1957 Dali::Toolkit::Control sourceHandle = Dali::Toolkit::Control::DownCast(source);
1958 Property::Map sourceMap = sourceHandle.GetProperty<Property::Map>(visualIndex);
1959 Dali::Toolkit::Control destinationHandle = Dali::Toolkit::Control::DownCast(mControlImpl.Self());
1960 Property::Map destinationMap = destinationHandle.GetProperty<Property::Map>(visualIndex);
1962 Vector4 mixColor(1.0f, 1.0f, 1.0f, 1.0f);
1963 Vector4 cornerRadius(0.0f, 0.0f, 0.0f, 0.0f);
1964 float borderlineWidth(0.0f);
1965 Vector4 borderlineColor(0.0f, 0.0f, 0.0f, 1.0f);
1966 float borderlineOffset(0.0f);
1968 if(!destinationMap.Empty())
1970 static auto findValueVector4 = [](const Property::Map& map, Property::Index index, const Vector4& defaultValue = Vector4()) -> Vector4 {
1971 Property::Value* propertyValue = map.Find(index);
1974 return propertyValue->Get<Vector4>();
1976 return defaultValue;
1979 static auto findValueFloat = [](const Property::Map& map, Property::Index index, const float& defaultValue = 0.0f) -> float {
1980 Property::Value* propertyValue = map.Find(index);
1983 return propertyValue->Get<float>();
1985 return defaultValue;
1988 mixColor = findValueVector4(destinationMap, Dali::Toolkit::Visual::Property::MIX_COLOR, mixColor);
1989 cornerRadius = findValueVector4(destinationMap, Toolkit::DevelVisual::Property::CORNER_RADIUS, cornerRadius);
1990 borderlineWidth = findValueFloat(destinationMap, Toolkit::DevelVisual::Property::BORDERLINE_WIDTH, borderlineWidth);
1991 borderlineColor = findValueVector4(destinationMap, Toolkit::DevelVisual::Property::BORDERLINE_COLOR, borderlineColor);
1992 borderlineOffset = findValueFloat(destinationMap, Toolkit::DevelVisual::Property::BORDERLINE_OFFSET, borderlineOffset);
1994 if(sourceMap.Empty())
1996 sourceMap.Insert(Toolkit::Visual::Property::TYPE, Toolkit::Visual::COLOR);
1997 sourceMap.Insert(Dali::Toolkit::Visual::Property::MIX_COLOR, Color::TRANSPARENT);
1998 sourceMap.Insert(Toolkit::DevelVisual::Property::CORNER_RADIUS, cornerRadius);
1999 sourceMap.Insert(Toolkit::DevelVisual::Property::BORDERLINE_WIDTH, borderlineWidth);
2000 sourceMap.Insert(Toolkit::DevelVisual::Property::BORDERLINE_COLOR, borderlineColor);
2001 sourceMap.Insert(Toolkit::DevelVisual::Property::BORDERLINE_OFFSET, borderlineOffset);
2004 Vector4 sourceMixColor = findValueVector4(sourceMap, Dali::Toolkit::Visual::Property::MIX_COLOR, mixColor);
2005 Vector4 sourceCornerRadius = findValueVector4(sourceMap, Toolkit::DevelVisual::Property::CORNER_RADIUS, cornerRadius);
2006 float sourceBorderlineWidth = findValueFloat(sourceMap, Toolkit::DevelVisual::Property::BORDERLINE_WIDTH, borderlineWidth);
2007 Vector4 sourceBorderlineColor = findValueVector4(sourceMap, Toolkit::DevelVisual::Property::BORDERLINE_COLOR, borderlineColor);
2008 float sourceBorderlineOffset = findValueFloat(sourceMap, Toolkit::DevelVisual::Property::BORDERLINE_OFFSET, borderlineOffset);
2010 std::vector<Dali::Property> properties;
2011 std::vector<std::pair<Property::Value, Property::Value>> values;
2013 if(Vector3(sourceMixColor) != Vector3(mixColor))
2015 properties.push_back(GetVisualProperty(visualIndex, Dali::Toolkit::Visual::Property::MIX_COLOR));
2016 values.push_back(std::make_pair(Vector3(sourceMixColor), Vector3(mixColor)));
2019 if(std::abs(sourceMixColor.a - mixColor.a) > Math::MACHINE_EPSILON_1)
2021 properties.push_back(GetVisualProperty(visualIndex, Dali::Toolkit::Visual::Property::OPACITY));
2022 values.push_back(std::make_pair(sourceMixColor.a, mixColor.a));
2025 if(sourceCornerRadius != cornerRadius)
2027 properties.push_back(GetVisualProperty(visualIndex, Dali::Toolkit::DevelVisual::Property::CORNER_RADIUS));
2028 values.push_back(std::make_pair(sourceCornerRadius, cornerRadius));
2031 if(sourceBorderlineWidth != borderlineWidth)
2033 properties.push_back(GetVisualProperty(visualIndex, Dali::Toolkit::DevelVisual::Property::BORDERLINE_WIDTH));
2034 values.push_back(std::make_pair(sourceBorderlineWidth, borderlineWidth));
2037 if(sourceBorderlineColor != borderlineColor)
2039 properties.push_back(GetVisualProperty(visualIndex, Dali::Toolkit::DevelVisual::Property::BORDERLINE_COLOR));
2040 values.push_back(std::make_pair(sourceBorderlineColor, borderlineColor));
2043 if(sourceBorderlineOffset != borderlineOffset)
2045 properties.push_back(GetVisualProperty(visualIndex, Dali::Toolkit::DevelVisual::Property::BORDERLINE_OFFSET));
2046 values.push_back(std::make_pair(sourceBorderlineOffset, borderlineOffset));
2049 for(uint32_t i = 0; i < properties.size(); ++i)
2051 if(timePeriod.delaySeconds > 0.0f)
2053 Dali::KeyFrames initialKeyframes = Dali::KeyFrames::New();
2054 initialKeyframes.Add(0.0f, values[i].first);
2055 initialKeyframes.Add(1.0f, values[i].first);
2056 animation.AnimateBetween(properties[i], initialKeyframes, TimePeriod(timePeriod.delaySeconds));
2058 Dali::KeyFrames keyframes = Dali::KeyFrames::New();
2059 keyframes.Add(0.0f, values[i].first);
2060 keyframes.Add(1.0f, values[i].second);
2061 animation.AnimateBetween(properties[i], keyframes, alphaFunction, timePeriod);
2066 void Control::Impl::EmitResourceReadySignal()
2068 if(!mIsEmittingResourceReadySignal)
2070 // Guard against calls to emit the signal during the callback
2071 mIsEmittingResourceReadySignal = true;
2073 // If the signal handler changes visual, it may become ready during this call & therefore this method will
2074 // get called again recursively. If so, mNeedToEmitResourceReady is set below, and we act on it after that secondary
2075 // invocation has completed by notifying in an Idle callback to prevent further recursion.
2076 Dali::Toolkit::Control handle(mControlImpl.GetOwner());
2077 mResourceReadySignal.Emit(handle);
2079 if(mNeedToEmitResourceReady)
2081 // Add idler to emit the signal again
2084 // The callback manager takes the ownership of the callback object.
2085 mIdleCallback = MakeCallback(this, &Control::Impl::OnIdleCallback);
2086 Adaptor::Get().AddIdle(mIdleCallback, false);
2090 mIsEmittingResourceReadySignal = false;
2094 mNeedToEmitResourceReady = true;
2098 void Control::Impl::OnIdleCallback()
2100 if(mNeedToEmitResourceReady)
2103 mNeedToEmitResourceReady = false;
2105 // A visual is ready so control may need relayouting if staged
2106 if(mControlImpl.Self().GetProperty<bool>(Actor::Property::CONNECTED_TO_SCENE))
2108 mControlImpl.RelayoutRequest();
2111 EmitResourceReadySignal();
2114 // Set the pointer to null as the callback manager deletes the callback after execute it.
2115 mIdleCallback = nullptr;
2118 Dali::Accessibility::Accessible* Control::Impl::GetAccessibilityObject()
2120 if(!mAccessibilityObject)
2122 mAccessibilityObject = mAccessibilityConstructor(mControlImpl.Self());
2124 return mAccessibilityObject.get();
2127 Dali::Accessibility::Accessible* Control::Impl::GetAccessibilityObject(Dali::Actor actor)
2131 auto control = Dali::Toolkit::Control::DownCast(actor);
2134 auto controlImpl = static_cast<Internal::Control*>(&control.GetImplementation());
2135 return controlImpl->mImpl->GetAccessibilityObject();
2141 } // namespace Internal
2143 } // namespace Toolkit