2 * Copyright (c) 2023 Samsung Electronics Co., Ltd.
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
8 * http://www.apache.org/licenses/LICENSE-2.0
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
19 #include "control-data-impl.h"
22 #include <dali-toolkit/public-api/controls/control-impl.h>
23 #include <dali-toolkit/public-api/controls/control.h>
24 #include <dali-toolkit/public-api/dali-toolkit-common.h>
25 #include <dali/devel-api/actors/actor-devel.h>
26 #include <dali/devel-api/adaptor-framework/accessibility.h>
27 #include <dali/devel-api/common/stage.h>
28 #include <dali/devel-api/object/handle-devel.h>
29 #include <dali/devel-api/scripting/enum-helper.h>
30 #include <dali/devel-api/scripting/scripting.h>
31 #include <dali/integration-api/adaptor-framework/adaptor.h>
32 #include <dali/integration-api/debug.h>
33 #include <dali/public-api/math/math-utils.h>
34 #include <dali/public-api/object/object-registry.h>
35 #include <dali/public-api/object/type-registry-helper.h>
40 #include <dali-toolkit/devel-api/asset-manager/asset-manager.h>
41 #include <dali-toolkit/devel-api/controls/control-depth-index-ranges.h>
42 #include <dali-toolkit/devel-api/controls/control-devel.h>
43 #include <dali-toolkit/devel-api/controls/control-wrapper-impl.h>
44 #include <dali-toolkit/devel-api/visuals/visual-actions-devel.h>
45 #include <dali-toolkit/internal/styling/style-manager-impl.h>
46 #include <dali-toolkit/internal/visuals/visual-base-impl.h>
47 #include <dali-toolkit/internal/visuals/visual-string-constants.h>
48 #include <dali-toolkit/public-api/controls/image-view/image-view.h>
49 #include <dali-toolkit/public-api/focus-manager/keyboard-focus-manager.h>
50 #include <dali-toolkit/public-api/visuals/image-visual-properties.h>
51 #include <dali-toolkit/public-api/visuals/visual-properties.h>
55 const char* READING_INFO_TYPE_NAME = "name";
56 const char* READING_INFO_TYPE_ROLE = "role";
57 const char* READING_INFO_TYPE_DESCRIPTION = "description";
58 const char* READING_INFO_TYPE_STATE = "state";
59 const char* READING_INFO_TYPE_ATTRIBUTE_NAME = "reading_info_type";
60 const char* READING_INFO_TYPE_SEPARATOR = "|";
69 extern const Dali::Scripting::StringEnum ControlStateTable[];
70 extern const unsigned int ControlStateTableCount;
72 // Not static or anonymous - shared with other translation units
73 const Scripting::StringEnum ControlStateTable[] = {
74 {"NORMAL", Toolkit::DevelControl::NORMAL},
75 {"FOCUSED", Toolkit::DevelControl::FOCUSED},
76 {"DISABLED", Toolkit::DevelControl::DISABLED},
78 const unsigned int ControlStateTableCount = sizeof(ControlStateTable) / sizeof(ControlStateTable[0]);
82 #if defined(DEBUG_ENABLED)
83 Debug::Filter* gLogFilter = Debug::Filter::New(Debug::NoLogging, false, "LOG_CONTROL_VISUALS");
87 void Remove(Dictionary<T>& keyValues, const std::string& name)
89 keyValues.Remove(name);
92 void Remove(DictionaryKeys& keys, const std::string& name)
94 DictionaryKeys::iterator iter = std::find(keys.begin(), keys.end(), name);
95 if(iter != keys.end())
102 * Finds visual in given array, returning true if found along with the iterator for that visual as a out parameter
104 bool FindVisual(Property::Index targetIndex, const RegisteredVisualContainer& visuals, RegisteredVisualContainer::Iterator& iter)
106 for(iter = visuals.Begin(); iter != visuals.End(); iter++)
108 if((*iter)->index == targetIndex)
117 * Finds visual in given array, returning true if found along with the iterator for that visual as a out parameter
119 bool FindVisual(std::string visualName, const RegisteredVisualContainer& visuals, RegisteredVisualContainer::Iterator& iter)
121 for(iter = visuals.Begin(); iter != visuals.End(); iter++)
123 Toolkit::Visual::Base visual = (*iter)->visual;
124 if(visual && visual.GetName() == visualName)
133 * Finds visual in given array, returning true if found along with the iterator for that visual as a out parameter
135 bool FindVisual(const Toolkit::Visual::Base findVisual, const RegisteredVisualContainer& visuals, RegisteredVisualContainer::Iterator& iter)
137 for(iter = visuals.Begin(); iter != visuals.End(); iter++)
139 Toolkit::Visual::Base visual = (*iter)->visual;
140 if(visual && visual == findVisual)
149 * Finds internal visual in given array, returning true if found along with the iterator for that visual as a out parameter
151 bool FindVisual(const Visual::Base& findInternalVisual, const RegisteredVisualContainer& visuals, RegisteredVisualContainer::Iterator& iter)
153 for(iter = visuals.Begin(); iter != visuals.End(); iter++)
155 Visual::Base& visual = Toolkit::GetImplementation((*iter)->visual);
156 if((&visual == &findInternalVisual))
164 void FindChangableVisuals(Dictionary<Property::Map>& stateVisualsToAdd,
165 Dictionary<Property::Map>& stateVisualsToChange,
166 DictionaryKeys& stateVisualsToRemove)
168 DictionaryKeys copyOfStateVisualsToRemove = stateVisualsToRemove;
170 for(DictionaryKeys::iterator iter = copyOfStateVisualsToRemove.begin();
171 iter != copyOfStateVisualsToRemove.end();
174 const std::string& visualName = (*iter);
175 Property::Map* toMap = stateVisualsToAdd.Find(visualName);
178 stateVisualsToChange.Add(visualName, *toMap);
179 stateVisualsToAdd.Remove(visualName);
180 Remove(stateVisualsToRemove, visualName);
185 Toolkit::Visual::Base GetVisualByName(
186 const RegisteredVisualContainer& visuals,
187 const std::string& visualName)
189 Toolkit::Visual::Base visualHandle;
191 RegisteredVisualContainer::Iterator iter;
192 for(iter = visuals.Begin(); iter != visuals.End(); iter++)
194 Toolkit::Visual::Base visual = (*iter)->visual;
195 if(visual && visual.GetName() == visualName)
197 visualHandle = visual;
204 Toolkit::Visual::Base GetVisualByIndex(
205 const RegisteredVisualContainer& visuals,
206 Property::Index index)
208 Toolkit::Visual::Base visualHandle;
210 RegisteredVisualContainer::Iterator iter;
211 for(iter = visuals.Begin(); iter != visuals.End(); iter++)
213 if((*iter)->index == index)
215 visualHandle = (*iter)->visual;
223 * Move visual from source to destination container
225 void MoveVisual(RegisteredVisualContainer::Iterator sourceIter, RegisteredVisualContainer& source, RegisteredVisualContainer& destination)
227 Toolkit::Visual::Base visual = (*sourceIter)->visual;
230 RegisteredVisual* rv = source.Release(sourceIter);
231 destination.PushBack(rv);
236 * Discard visual from source to visual factory.
238 void DiscardVisual(RegisteredVisualContainer::Iterator sourceIter, RegisteredVisualContainer& source)
240 Toolkit::Visual::Base visual = (*sourceIter)->visual;
243 if(Stage::IsInstalled())
245 Toolkit::VisualFactory::Get().DiscardVisual(visual);
249 source.Erase(sourceIter);
253 * Performs actions as requested using the action name.
254 * @param[in] object The object on which to perform the action.
255 * @param[in] actionName The action to perform.
256 * @param[in] attributes The attributes with which to perfrom this action.
257 * @return true if action has been accepted by this control
259 const char* ACTION_ACCESSIBILITY_ACTIVATED = "accessibilityActivated";
260 const char* ACTION_ACCESSIBILITY_READING_CANCELLED = "ReadingCancelled";
261 const char* ACTION_ACCESSIBILITY_READING_PAUSED = "ReadingPaused";
262 const char* ACTION_ACCESSIBILITY_READING_RESUMED = "ReadingResumed";
263 const char* ACTION_ACCESSIBILITY_READING_SKIPPED = "ReadingSkipped";
264 const char* ACTION_ACCESSIBILITY_READING_STOPPED = "ReadingStopped";
266 static bool DoAction(BaseObject* object, const std::string& actionName, const Property::Map& attributes)
270 Dali::BaseHandle handle(object);
272 Toolkit::Control control = Toolkit::Control::DownCast(handle);
274 DALI_ASSERT_ALWAYS(control);
276 if(0 == strcmp(actionName.c_str(), ACTION_ACCESSIBILITY_ACTIVATED) || actionName == "activate")
278 // if cast succeeds there is an implementation so no need to check
279 if(!DevelControl::AccessibilityActivateSignal(control).Empty())
281 DevelControl::AccessibilityActivateSignal(control).Emit();
285 ret = Internal::GetImplementation(control).OnAccessibilityActivated();
288 else if(0 == strcmp(actionName.c_str(), ACTION_ACCESSIBILITY_READING_SKIPPED))
290 // if cast succeeds there is an implementation so no need to check
291 if(!DevelControl::AccessibilityReadingSkippedSignal(control).Empty())
293 DevelControl::AccessibilityReadingSkippedSignal(control).Emit();
296 else if(0 == strcmp(actionName.c_str(), ACTION_ACCESSIBILITY_READING_PAUSED))
298 // if cast succeeds there is an implementation so no need to check
299 if(!DevelControl::AccessibilityReadingPausedSignal(control).Empty())
301 DevelControl::AccessibilityReadingPausedSignal(control).Emit();
304 else if(0 == strcmp(actionName.c_str(), ACTION_ACCESSIBILITY_READING_RESUMED))
306 // if cast succeeds there is an implementation so no need to check
307 if(!DevelControl::AccessibilityReadingResumedSignal(control).Empty())
309 DevelControl::AccessibilityReadingResumedSignal(control).Emit();
312 else if(0 == strcmp(actionName.c_str(), ACTION_ACCESSIBILITY_READING_CANCELLED))
314 // if cast succeeds there is an implementation so no need to check
315 if(!DevelControl::AccessibilityReadingCancelledSignal(control).Empty())
317 DevelControl::AccessibilityReadingCancelledSignal(control).Emit();
320 else if(0 == strcmp(actionName.c_str(), ACTION_ACCESSIBILITY_READING_STOPPED))
322 // if cast succeeds there is an implementation so no need to check
323 if(!DevelControl::AccessibilityReadingStoppedSignal(control).Empty())
325 DevelControl::AccessibilityReadingStoppedSignal(control).Emit();
336 * Connects a callback function with the object's signals.
337 * @param[in] object The object providing the signal.
338 * @param[in] tracker Used to disconnect the signal.
339 * @param[in] signalName The signal to connect to.
340 * @param[in] functor A newly allocated FunctorDelegate.
341 * @return True if the signal was connected.
342 * @post If a signal was connected, ownership of functor was passed to CallbackBase. Otherwise the caller is responsible for deleting the unused functor.
344 const char* SIGNAL_KEY_EVENT = "keyEvent";
345 const char* SIGNAL_KEY_INPUT_FOCUS_GAINED = "keyInputFocusGained";
346 const char* SIGNAL_KEY_INPUT_FOCUS_LOST = "keyInputFocusLost";
347 const char* SIGNAL_TAPPED = "tapped";
348 const char* SIGNAL_PANNED = "panned";
349 const char* SIGNAL_PINCHED = "pinched";
350 const char* SIGNAL_LONG_PRESSED = "longPressed";
351 const char* SIGNAL_GET_NAME = "getName";
352 const char* SIGNAL_GET_DESCRIPTION = "getDescription";
353 const char* SIGNAL_DO_GESTURE = "doGesture";
354 static bool DoConnectSignal(BaseObject* object, ConnectionTrackerInterface* tracker, const std::string& signalName, FunctorDelegate* functor)
356 Dali::BaseHandle handle(object);
358 bool connected(false);
359 Toolkit::Control control = Toolkit::Control::DownCast(handle);
362 Internal::Control& controlImpl(Internal::GetImplementation(control));
365 if(0 == strcmp(signalName.c_str(), SIGNAL_KEY_EVENT))
367 controlImpl.KeyEventSignal().Connect(tracker, functor);
369 else if(0 == strcmp(signalName.c_str(), SIGNAL_KEY_INPUT_FOCUS_GAINED))
371 controlImpl.KeyInputFocusGainedSignal().Connect(tracker, functor);
373 else if(0 == strcmp(signalName.c_str(), SIGNAL_KEY_INPUT_FOCUS_LOST))
375 controlImpl.KeyInputFocusLostSignal().Connect(tracker, functor);
377 else if(0 == strcmp(signalName.c_str(), SIGNAL_TAPPED))
379 controlImpl.EnableGestureDetection(GestureType::TAP);
380 controlImpl.GetTapGestureDetector().DetectedSignal().Connect(tracker, functor);
382 else if(0 == strcmp(signalName.c_str(), SIGNAL_PANNED))
384 controlImpl.EnableGestureDetection(GestureType::PAN);
385 controlImpl.GetPanGestureDetector().DetectedSignal().Connect(tracker, functor);
387 else if(0 == strcmp(signalName.c_str(), SIGNAL_PINCHED))
389 controlImpl.EnableGestureDetection(GestureType::PINCH);
390 controlImpl.GetPinchGestureDetector().DetectedSignal().Connect(tracker, functor);
392 else if(0 == strcmp(signalName.c_str(), SIGNAL_LONG_PRESSED))
394 controlImpl.EnableGestureDetection(GestureType::LONG_PRESS);
395 controlImpl.GetLongPressGestureDetector().DetectedSignal().Connect(tracker, functor);
397 else if(0 == strcmp(signalName.c_str(), SIGNAL_GET_NAME))
399 DevelControl::AccessibilityGetNameSignal(control).Connect(tracker, functor);
401 else if(0 == strcmp(signalName.c_str(), SIGNAL_GET_DESCRIPTION))
403 DevelControl::AccessibilityGetDescriptionSignal(control).Connect(tracker, functor);
405 else if(0 == strcmp(signalName.c_str(), SIGNAL_DO_GESTURE))
407 DevelControl::AccessibilityDoGestureSignal(control).Connect(tracker, functor);
414 * Creates control through type registry
418 return Internal::Control::New();
420 // Setup signals and actions using the type-registry.
421 DALI_TYPE_REGISTRATION_BEGIN(Control, CustomActor, Create);
423 // Note: Properties are registered separately below.
425 SignalConnectorType registerSignal1(typeRegistration, SIGNAL_KEY_EVENT, &DoConnectSignal);
426 SignalConnectorType registerSignal2(typeRegistration, SIGNAL_KEY_INPUT_FOCUS_GAINED, &DoConnectSignal);
427 SignalConnectorType registerSignal3(typeRegistration, SIGNAL_KEY_INPUT_FOCUS_LOST, &DoConnectSignal);
428 SignalConnectorType registerSignal4(typeRegistration, SIGNAL_TAPPED, &DoConnectSignal);
429 SignalConnectorType registerSignal5(typeRegistration, SIGNAL_PANNED, &DoConnectSignal);
430 SignalConnectorType registerSignal6(typeRegistration, SIGNAL_PINCHED, &DoConnectSignal);
431 SignalConnectorType registerSignal7(typeRegistration, SIGNAL_LONG_PRESSED, &DoConnectSignal);
432 SignalConnectorType registerSignal8(typeRegistration, SIGNAL_GET_NAME, &DoConnectSignal);
433 SignalConnectorType registerSignal9(typeRegistration, SIGNAL_GET_DESCRIPTION, &DoConnectSignal);
434 SignalConnectorType registerSignal10(typeRegistration, SIGNAL_DO_GESTURE, &DoConnectSignal);
436 TypeAction registerAction1(typeRegistration, "activate", &DoAction);
437 TypeAction registerAction2(typeRegistration, ACTION_ACCESSIBILITY_ACTIVATED, &DoAction);
438 TypeAction registerAction3(typeRegistration, ACTION_ACCESSIBILITY_READING_SKIPPED, &DoAction);
439 TypeAction registerAction4(typeRegistration, ACTION_ACCESSIBILITY_READING_CANCELLED, &DoAction);
440 TypeAction registerAction5(typeRegistration, ACTION_ACCESSIBILITY_READING_STOPPED, &DoAction);
441 TypeAction registerAction6(typeRegistration, ACTION_ACCESSIBILITY_READING_PAUSED, &DoAction);
442 TypeAction registerAction7(typeRegistration, ACTION_ACCESSIBILITY_READING_RESUMED, &DoAction);
444 DALI_TYPE_REGISTRATION_END()
447 * @brief Iterate through given container and setOffScene any visual found
449 * @param[in] container Container of visuals
450 * @param[in] parent Parent actor to remove visuals from
452 void SetVisualsOffScene(const RegisteredVisualContainer& container, Actor parent)
454 for(auto iter = container.Begin(), end = container.End(); iter != end; iter++)
458 DALI_LOG_INFO(gLogFilter, Debug::Verbose, "Control::SetOffScene Setting visual(%d) off stage\n", (*iter)->index);
459 Toolkit::GetImplementation((*iter)->visual).SetOffScene(parent);
464 Dali::Rect<> GetShowingGeometry(Dali::Rect<> rect, Dali::Toolkit::DevelControl::ControlAccessible* accessible)
467 Vector2 currentPosition;
468 auto parent = dynamic_cast<Toolkit::DevelControl::ControlAccessible*>(accessible->GetParent());
472 parentRect = parent->GetExtents(Dali::Accessibility::CoordinateType::WINDOW);
474 currentPosition.x = rect.x;
475 currentPosition.y = rect.y;
477 rect.x = rect.x > parentRect.x ? rect.x : parentRect.x;
478 rect.y = rect.y > parentRect.y ? rect.y : parentRect.y;
479 rect.width = currentPosition.x + rect.width < parentRect.x + parentRect.width ? currentPosition.x + rect.width - rect.x : parentRect.x + parentRect.width - rect.x;
480 rect.height = currentPosition.y + rect.height < parentRect.y + parentRect.height ? currentPosition.y + rect.height - rect.y : parentRect.y + parentRect.height - rect.y;
482 if(rect.width < 0 || rect.height < 0)
487 parent = dynamic_cast<Toolkit::DevelControl::ControlAccessible*>(parent->GetParent());
493 static bool IsShowingGeometryOnScreen(Dali::Rect<> rect)
495 return rect.width > 0 && rect.height > 0;
498 Dali::Accessibility::Accessible* ExternalAccessibleGetter(Dali::Actor actor)
500 auto control = Toolkit::Control::DownCast(actor);
506 auto& controlImpl = Toolkit::Internal::GetImplementation(control);
508 return controlImpl.GetAccessibleObject();
511 } // unnamed namespace
514 // Properties registered without macro to use specific member variables.
515 const PropertyRegistration Control::Impl::PROPERTY_1(typeRegistration, "styleName", Toolkit::Control::Property::STYLE_NAME, Property::STRING, &Control::Impl::SetProperty, &Control::Impl::GetProperty);
516 const PropertyRegistration Control::Impl::PROPERTY_4(typeRegistration, "keyInputFocus", Toolkit::Control::Property::KEY_INPUT_FOCUS, Property::BOOLEAN, &Control::Impl::SetProperty, &Control::Impl::GetProperty);
517 const PropertyRegistration Control::Impl::PROPERTY_5(typeRegistration, "background", Toolkit::Control::Property::BACKGROUND, Property::MAP, &Control::Impl::SetProperty, &Control::Impl::GetProperty);
518 const PropertyRegistration Control::Impl::PROPERTY_6(typeRegistration, "margin", Toolkit::Control::Property::MARGIN, Property::EXTENTS, &Control::Impl::SetProperty, &Control::Impl::GetProperty);
519 const PropertyRegistration Control::Impl::PROPERTY_7(typeRegistration, "padding", Toolkit::Control::Property::PADDING, Property::EXTENTS, &Control::Impl::SetProperty, &Control::Impl::GetProperty);
520 const PropertyRegistration Control::Impl::PROPERTY_8(typeRegistration, "tooltip", Toolkit::DevelControl::Property::TOOLTIP, Property::MAP, &Control::Impl::SetProperty, &Control::Impl::GetProperty);
521 const PropertyRegistration Control::Impl::PROPERTY_9(typeRegistration, "state", Toolkit::DevelControl::Property::STATE, Property::STRING, &Control::Impl::SetProperty, &Control::Impl::GetProperty);
522 const PropertyRegistration Control::Impl::PROPERTY_10(typeRegistration, "subState", Toolkit::DevelControl::Property::SUB_STATE, Property::STRING, &Control::Impl::SetProperty, &Control::Impl::GetProperty);
523 const PropertyRegistration Control::Impl::PROPERTY_11(typeRegistration, "leftFocusableActorId", Toolkit::DevelControl::Property::LEFT_FOCUSABLE_ACTOR_ID, Property::INTEGER, &Control::Impl::SetProperty, &Control::Impl::GetProperty);
524 const PropertyRegistration Control::Impl::PROPERTY_12(typeRegistration, "rightFocusableActorId", Toolkit::DevelControl::Property::RIGHT_FOCUSABLE_ACTOR_ID, Property::INTEGER, &Control::Impl::SetProperty, &Control::Impl::GetProperty);
525 const PropertyRegistration Control::Impl::PROPERTY_13(typeRegistration, "upFocusableActorId", Toolkit::DevelControl::Property::UP_FOCUSABLE_ACTOR_ID, Property::INTEGER, &Control::Impl::SetProperty, &Control::Impl::GetProperty);
526 const PropertyRegistration Control::Impl::PROPERTY_14(typeRegistration, "downFocusableActorId", Toolkit::DevelControl::Property::DOWN_FOCUSABLE_ACTOR_ID, Property::INTEGER, &Control::Impl::SetProperty, &Control::Impl::GetProperty);
527 const PropertyRegistration Control::Impl::PROPERTY_15(typeRegistration, "shadow", Toolkit::DevelControl::Property::SHADOW, Property::MAP, &Control::Impl::SetProperty, &Control::Impl::GetProperty);
528 const PropertyRegistration Control::Impl::PROPERTY_16(typeRegistration, "accessibilityName", Toolkit::DevelControl::Property::ACCESSIBILITY_NAME, Property::STRING, &Control::Impl::SetProperty, &Control::Impl::GetProperty);
529 const PropertyRegistration Control::Impl::PROPERTY_17(typeRegistration, "accessibilityDescription", Toolkit::DevelControl::Property::ACCESSIBILITY_DESCRIPTION, Property::STRING, &Control::Impl::SetProperty, &Control::Impl::GetProperty);
530 const PropertyRegistration Control::Impl::PROPERTY_18(typeRegistration, "accessibilityTranslationDomain", Toolkit::DevelControl::Property::ACCESSIBILITY_TRANSLATION_DOMAIN, Property::STRING, &Control::Impl::SetProperty, &Control::Impl::GetProperty);
531 const PropertyRegistration Control::Impl::PROPERTY_19(typeRegistration, "accessibilityRole", Toolkit::DevelControl::Property::ACCESSIBILITY_ROLE, Property::INTEGER, &Control::Impl::SetProperty, &Control::Impl::GetProperty);
532 const PropertyRegistration Control::Impl::PROPERTY_20(typeRegistration, "accessibilityHighlightable", Toolkit::DevelControl::Property::ACCESSIBILITY_HIGHLIGHTABLE, Property::BOOLEAN, &Control::Impl::SetProperty, &Control::Impl::GetProperty);
533 const PropertyRegistration Control::Impl::PROPERTY_21(typeRegistration, "accessibilityAttributes", Toolkit::DevelControl::Property::ACCESSIBILITY_ATTRIBUTES, Property::MAP, &Control::Impl::SetProperty, &Control::Impl::GetProperty);
534 const PropertyRegistration Control::Impl::PROPERTY_22(typeRegistration, "dispatchKeyEvents", Toolkit::DevelControl::Property::DISPATCH_KEY_EVENTS, Property::BOOLEAN, &Control::Impl::SetProperty, &Control::Impl::GetProperty);
535 const PropertyRegistration Control::Impl::PROPERTY_23(typeRegistration, "accessibilityHidden", Toolkit::DevelControl::Property::ACCESSIBILITY_HIDDEN, Property::BOOLEAN, &Control::Impl::SetProperty, &Control::Impl::GetProperty);
536 const PropertyRegistration Control::Impl::PROPERTY_24(typeRegistration, "clockwiseFocusableActorId", Toolkit::DevelControl::Property::CLOCKWISE_FOCUSABLE_ACTOR_ID, Property::INTEGER, &Control::Impl::SetProperty, &Control::Impl::GetProperty);
537 const PropertyRegistration Control::Impl::PROPERTY_25(typeRegistration, "counterClockwiseFocusableActorId", Toolkit::DevelControl::Property::COUNTER_CLOCKWISE_FOCUSABLE_ACTOR_ID, Property::INTEGER, &Control::Impl::SetProperty, &Control::Impl::GetProperty);
538 const PropertyRegistration Control::Impl::PROPERTY_26(typeRegistration, "automationId", Toolkit::DevelControl::Property::AUTOMATION_ID, Property::STRING, &Control::Impl::SetProperty, &Control::Impl::GetProperty);
542 Control::Impl::Impl(Control& controlImpl)
543 : mControlImpl(controlImpl),
544 mState(Toolkit::DevelControl::NORMAL),
546 mLeftFocusableActorId(-1),
547 mRightFocusableActorId(-1),
548 mUpFocusableActorId(-1),
549 mDownFocusableActorId(-1),
550 mClockwiseFocusableActorId(-1),
551 mCounterClockwiseFocusableActorId(-1),
553 mBackgroundColor(Color::TRANSPARENT),
554 mStartingPinchScale(nullptr),
556 mPadding(0, 0, 0, 0),
558 mKeyInputFocusGainedSignal(),
559 mKeyInputFocusLostSignal(),
560 mResourceReadySignal(),
561 mVisualEventSignal(),
562 mAccessibilityGetNameSignal(),
563 mAccessibilityGetDescriptionSignal(),
564 mAccessibilityDoGestureSignal(),
565 mPinchGestureDetector(),
566 mPanGestureDetector(),
567 mTapGestureDetector(),
568 mLongPressGestureDetector(),
570 mInputMethodContext(),
571 mIdleCallback(nullptr),
572 mFlags(Control::ControlBehaviour(CONTROL_BEHAVIOUR_DEFAULT)),
573 mIsKeyboardNavigationSupported(false),
574 mIsKeyboardFocusGroup(false),
575 mIsEmittingResourceReadySignal(false),
576 mIdleCallbackRegistered(false),
577 mDispatchKeyEvents(true)
579 Dali::Accessibility::Accessible::RegisterExternalAccessibleGetter(&ExternalAccessibleGetter);
582 Control::Impl::~Impl()
584 for(auto&& iter : mVisuals)
586 StopObservingVisual(iter->visual);
589 for(auto&& iter : mRemoveVisuals)
591 StopObservingVisual(iter->visual);
594 // All gesture detectors will be destroyed so no need to disconnect.
595 delete mStartingPinchScale;
597 if(mIdleCallback && Adaptor::IsAvailable())
599 // Removes the callback from the callback manager in case the control is destroyed before the callback is executed.
600 Adaptor::Get().RemoveIdle(mIdleCallback);
604 Control::Impl& Control::Impl::Get(Internal::Control& internalControl)
606 DALI_ASSERT_ALWAYS(Stage::IsCoreThread() && "Core is not installed. Might call this API from worker thread?");
608 return *internalControl.mImpl;
611 const Control::Impl& Control::Impl::Get(const Internal::Control& internalControl)
613 DALI_ASSERT_ALWAYS(Stage::IsCoreThread() && "Core is not installed. Might call this API from worker thread?");
615 return *internalControl.mImpl;
618 void Control::Impl::CheckHighlightedObjectGeometry()
620 auto accessible = GetAccessibleObject();
621 auto lastPosition = accessible->GetLastPosition();
622 auto accessibleRect = accessible->GetExtents(Dali::Accessibility::CoordinateType::WINDOW);
623 auto rect = GetShowingGeometry(accessibleRect, accessible);
625 switch(mAccessibilityLastScreenRelativeMoveType)
627 case Dali::Accessibility::ScreenRelativeMoveType::OUTSIDE:
629 if(IsShowingGeometryOnScreen(rect))
631 mAccessibilityLastScreenRelativeMoveType = Dali::Accessibility::ScreenRelativeMoveType::INSIDE;
635 case Dali::Accessibility::ScreenRelativeMoveType::INSIDE:
637 if(rect.width < 0 && !Dali::Equals(accessibleRect.x, lastPosition.x))
639 mAccessibilityLastScreenRelativeMoveType = (accessibleRect.x < lastPosition.x) ? Dali::Accessibility::ScreenRelativeMoveType::OUTGOING_TOP_LEFT : Dali::Accessibility::ScreenRelativeMoveType::OUTGOING_BOTTOM_RIGHT;
641 if(rect.height < 0 && !Dali::Equals(accessibleRect.y, lastPosition.y))
643 mAccessibilityLastScreenRelativeMoveType = (accessibleRect.y < lastPosition.y) ? Dali::Accessibility::ScreenRelativeMoveType::OUTGOING_TOP_LEFT : Dali::Accessibility::ScreenRelativeMoveType::OUTGOING_BOTTOM_RIGHT;
645 // notify AT-clients on outgoing moves only
646 if(mAccessibilityLastScreenRelativeMoveType != Dali::Accessibility::ScreenRelativeMoveType::INSIDE)
648 accessible->EmitMovedOutOfScreen(mAccessibilityLastScreenRelativeMoveType);
652 case Dali::Accessibility::ScreenRelativeMoveType::OUTGOING_TOP_LEFT:
653 case Dali::Accessibility::ScreenRelativeMoveType::OUTGOING_BOTTOM_RIGHT:
655 if(IsShowingGeometryOnScreen(rect))
657 mAccessibilityLastScreenRelativeMoveType = Dali::Accessibility::ScreenRelativeMoveType::INSIDE;
661 mAccessibilityLastScreenRelativeMoveType = Dali::Accessibility::ScreenRelativeMoveType::OUTSIDE;
671 accessible->SetLastPosition(Vector2(accessibleRect.x, accessibleRect.y));
674 void Control::Impl::RegisterAccessibilityPositionPropertyNotification()
676 if(mIsAccessibilityPositionPropertyNotificationSet)
680 // set default value until first move of object is detected
681 mAccessibilityLastScreenRelativeMoveType = Dali::Accessibility::ScreenRelativeMoveType::OUTSIDE;
682 // recalculate mAccessibilityLastScreenRelativeMoveType accordingly to the initial position
683 CheckHighlightedObjectGeometry();
684 mAccessibilityPositionNotification = mControlImpl.Self().AddPropertyNotification(Actor::Property::WORLD_POSITION, StepCondition(1.0f, 1.0f));
685 mAccessibilityPositionNotification.SetNotifyMode(PropertyNotification::NOTIFY_ON_CHANGED);
686 mAccessibilityPositionNotification.NotifySignal().Connect(this, [this](PropertyNotification&) { CheckHighlightedObjectGeometry(); });
687 mIsAccessibilityPositionPropertyNotificationSet = true;
690 void Control::Impl::UnregisterAccessibilityPositionPropertyNotification()
692 mControlImpl.Self().RemovePropertyNotification(mAccessibilityPositionNotification);
693 mIsAccessibilityPositionPropertyNotificationSet = false;
696 // Gesture Detection Methods
697 void Control::Impl::PinchDetected(Actor actor, const PinchGesture& pinch)
699 mControlImpl.OnPinch(pinch);
702 void Control::Impl::PanDetected(Actor actor, const PanGesture& pan)
704 mControlImpl.OnPan(pan);
707 void Control::Impl::TapDetected(Actor actor, const TapGesture& tap)
709 mControlImpl.OnTap(tap);
712 void Control::Impl::LongPressDetected(Actor actor, const LongPressGesture& longPress)
714 mControlImpl.OnLongPress(longPress);
717 void Control::Impl::RegisterVisual(Property::Index index, Toolkit::Visual::Base& visual)
719 RegisterVisual(index, visual, VisualState::ENABLED, DepthIndexValue::NOT_SET);
722 void Control::Impl::RegisterVisual(Property::Index index, Toolkit::Visual::Base& visual, int depthIndex)
724 RegisterVisual(index, visual, VisualState::ENABLED, DepthIndexValue::SET, depthIndex);
727 void Control::Impl::RegisterVisual(Property::Index index, Toolkit::Visual::Base& visual, bool enabled)
729 RegisterVisual(index, visual, (enabled ? VisualState::ENABLED : VisualState::DISABLED), DepthIndexValue::NOT_SET);
732 void Control::Impl::RegisterVisual(Property::Index index, Toolkit::Visual::Base& visual, bool enabled, int depthIndex)
734 RegisterVisual(index, visual, (enabled ? VisualState::ENABLED : VisualState::DISABLED), DepthIndexValue::SET, depthIndex);
737 void Control::Impl::RegisterVisual(Property::Index index, Toolkit::Visual::Base& visual, VisualState::Type enabled, DepthIndexValue::Type depthIndexValueSet, int depthIndex)
739 DALI_ASSERT_ALWAYS(Stage::IsCoreThread() && "Core is not installed. Might call this API from worker thread?");
741 DALI_LOG_INFO(gLogFilter, Debug::Concise, "RegisterVisual:%d \n", index);
743 bool visualReplaced(false);
744 Actor self = mControlImpl.Self();
746 // Set the depth index, if not set by caller this will be either the current visual depth, max depth of all visuals
748 int requiredDepthIndex = visual.GetDepthIndex();
750 if(depthIndexValueSet == DepthIndexValue::SET)
752 requiredDepthIndex = depthIndex;
755 // Visual replacement, existing visual should only be removed from stage when replacement ready.
756 if(!mVisuals.Empty())
758 RegisteredVisualContainer::Iterator registeredVisualsiter;
759 // Check if visual (index) is already registered, this is the current visual.
760 if(FindVisual(index, mVisuals, registeredVisualsiter))
762 Toolkit::Visual::Base& currentRegisteredVisual = (*registeredVisualsiter)->visual;
763 if(currentRegisteredVisual)
765 // Store current visual depth index as may need to set the replacement visual to same depth
766 const int currentDepthIndex = (*registeredVisualsiter)->visual.GetDepthIndex();
768 // No longer required to know if the replaced visual's resources are ready
769 StopObservingVisual(currentRegisteredVisual);
771 // If control staged and visual enabled then visuals will be swapped once ready
772 if(self.GetProperty<bool>(Actor::Property::CONNECTED_TO_SCENE) && enabled)
774 // Check if visual is currently in the process of being replaced ( is in removal container )
775 RegisteredVisualContainer::Iterator visualQueuedForRemoval;
776 if(FindVisual(index, mRemoveVisuals, visualQueuedForRemoval))
778 // Visual with same index is already in removal container so current visual pending
779 // Only the the last requested visual will be displayed so remove current visual which is staged but not ready.
780 Toolkit::GetImplementation(currentRegisteredVisual).SetOffScene(self);
781 mVisuals.Erase(registeredVisualsiter);
785 // current visual not already in removal container so add now.
786 DALI_LOG_INFO(gLogFilter, Debug::Verbose, "RegisterVisual Move current registered visual to removal Queue: %d \n", index);
787 MoveVisual(registeredVisualsiter, mVisuals, mRemoveVisuals);
792 // Control not staged or visual disabled so can just erase from registered visuals and new visual will be added later.
793 mVisuals.Erase(registeredVisualsiter);
796 // 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
797 if((depthIndexValueSet == DepthIndexValue::NOT_SET) &&
798 (visual.GetDepthIndex() == 0))
800 requiredDepthIndex = currentDepthIndex;
804 visualReplaced = true;
808 // If not set, set the name of the visual to the same name as the control's property.
809 // ( If the control has been type registered )
810 if(visual.GetName().empty())
812 // returns empty string if index is not found as long as index is not -1
813 std::string visualName = self.GetPropertyName(index);
814 if(!visualName.empty())
816 DALI_LOG_INFO(gLogFilter, Debug::Concise, "Setting visual name for property %d to %s\n", index, visualName.c_str());
817 visual.SetName(visualName);
821 if(!visualReplaced) // New registration entry
823 // 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
824 if((depthIndexValueSet == DepthIndexValue::NOT_SET) &&
825 (mVisuals.Size() > 0) &&
826 (visual.GetDepthIndex() == 0))
828 int maxDepthIndex = std::numeric_limits<int>::min();
830 RegisteredVisualContainer::ConstIterator iter;
831 const RegisteredVisualContainer::ConstIterator endIter = mVisuals.End();
832 for(iter = mVisuals.Begin(); iter != endIter; iter++)
834 const int visualDepthIndex = (*iter)->visual.GetDepthIndex();
835 if(visualDepthIndex > maxDepthIndex)
837 maxDepthIndex = visualDepthIndex;
840 ++maxDepthIndex; // Add one to the current maximum depth index so that our added visual appears on top
841 requiredDepthIndex = std::max(0, maxDepthIndex); // Start at zero if maxDepth index belongs to a background
847 // Set determined depth index
848 visual.SetDepthIndex(requiredDepthIndex);
850 // Monitor when the visual resources are ready
851 StartObservingVisual(visual);
853 DALI_LOG_INFO(gLogFilter, Debug::Concise, "New Visual registration index[%d] depth[%d]\n", index, requiredDepthIndex);
854 RegisteredVisual* newRegisteredVisual = new RegisteredVisual(index, visual, (enabled == VisualState::ENABLED ? true : false), (visualReplaced && enabled));
855 mVisuals.PushBack(newRegisteredVisual);
857 Internal::Visual::Base& visualImpl = Toolkit::GetImplementation(visual);
858 // Put on stage if enabled and the control is already on the stage
859 if((enabled == VisualState::ENABLED) && self.GetProperty<bool>(Actor::Property::CONNECTED_TO_SCENE))
861 visualImpl.SetOnScene(self);
863 else if(enabled && visualImpl.IsResourceReady()) // When not being staged, check if visual already 'ResourceReady' before it was Registered. ( Resource may have been loaded already )
865 ResourceReady(visualImpl);
869 DALI_LOG_INFO(gLogFilter, Debug::Verbose, "Control::RegisterVisual() Registered %s(%d), enabled:%s\n", visual.GetName().c_str(), index, enabled ? "true" : "false");
872 void Control::Impl::UnregisterVisual(Property::Index index)
874 DALI_ASSERT_ALWAYS(Stage::IsCoreThread() && "Core is not installed. Might call this API from worker thread?");
876 RegisteredVisualContainer::Iterator iter;
877 if(FindVisual(index, mVisuals, iter))
879 // stop observing visual
880 StopObservingVisual((*iter)->visual);
882 Actor self(mControlImpl.Self());
883 Toolkit::GetImplementation((*iter)->visual).SetOffScene(self);
884 (*iter)->visual.Reset();
885 mVisuals.Erase(iter);
888 if(FindVisual(index, mRemoveVisuals, iter))
890 Actor self(mControlImpl.Self());
891 Toolkit::GetImplementation((*iter)->visual).SetOffScene(self);
892 (*iter)->pending = false;
894 // Discard removed visual. It will be destroyed at next Idle time.
895 DiscardVisual(iter, mRemoveVisuals);
899 Toolkit::Visual::Base Control::Impl::GetVisual(Property::Index index) const
901 RegisteredVisualContainer::Iterator iter;
902 if(FindVisual(index, mVisuals, iter))
904 return (*iter)->visual;
907 return Toolkit::Visual::Base();
910 void Control::Impl::EnableVisual(Property::Index index, bool enable)
912 DALI_LOG_INFO(gLogFilter, Debug::General, "Control::EnableVisual(%d, %s)\n", index, enable ? "T" : "F");
914 RegisteredVisualContainer::Iterator iter;
915 if(FindVisual(index, mVisuals, iter))
917 if((*iter)->enabled == enable)
919 DALI_LOG_INFO(gLogFilter, Debug::Verbose, "Control::EnableVisual Visual %s(%d) already %s\n", (*iter)->visual.GetName().c_str(), index, enable ? "enabled" : "disabled");
923 (*iter)->enabled = enable;
924 Actor parentActor = mControlImpl.Self();
925 if(mControlImpl.Self().GetProperty<bool>(Actor::Property::CONNECTED_TO_SCENE)) // If control not on Scene then Visual will be added when SceneConnection is called.
929 DALI_LOG_INFO(gLogFilter, Debug::Verbose, "Control::EnableVisual Setting %s(%d) on stage \n", (*iter)->visual.GetName().c_str(), index);
930 Toolkit::GetImplementation((*iter)->visual).SetOnScene(parentActor);
934 DALI_LOG_INFO(gLogFilter, Debug::Verbose, "Control::EnableVisual Setting %s(%d) off stage \n", (*iter)->visual.GetName().c_str(), index);
935 Toolkit::GetImplementation((*iter)->visual).SetOffScene(parentActor); // No need to call if control not staged.
941 DALI_LOG_WARNING("Control::EnableVisual(%d, %s) FAILED - NO SUCH VISUAL\n", index, enable ? "T" : "F");
945 bool Control::Impl::IsVisualEnabled(Property::Index index) const
947 RegisteredVisualContainer::Iterator iter;
948 if(FindVisual(index, mVisuals, iter))
950 return (*iter)->enabled;
955 void Control::Impl::EnableReadyTransitionOverriden(Toolkit::Visual::Base& visual, bool enable)
957 DALI_LOG_INFO(gLogFilter, Debug::General, "Control::EnableReadyTransitionOverriden(%p, %s)\n", visual, enable ? "T" : "F");
959 RegisteredVisualContainer::Iterator iter;
960 if(FindVisual(visual, mVisuals, iter))
962 if((*iter)->overideReadyTransition == enable)
964 DALI_LOG_INFO(gLogFilter, Debug::Verbose, "Control::EnableReadyTransitionOverriden Visual %s(%p) already %s\n", (*iter)->visual.GetName().c_str(), visual, enable ? "enabled" : "disabled");
968 (*iter)->overideReadyTransition = enable;
972 void Control::Impl::StopObservingVisual(Toolkit::Visual::Base& visual)
974 Internal::Visual::Base& visualImpl = Toolkit::GetImplementation(visual);
976 // Stop observing the visual
977 visualImpl.RemoveEventObserver(*this);
980 void Control::Impl::StartObservingVisual(Toolkit::Visual::Base& visual)
982 Internal::Visual::Base& visualImpl = Toolkit::GetImplementation(visual);
984 // start observing the visual for events
985 visualImpl.AddEventObserver(*this);
988 void Control::Impl::ResourceReady()
990 DALI_ASSERT_ALWAYS(Stage::IsCoreThread() && "Core is not installed. Might call this API from worker thread?");
992 // Emit signal if all enabled visuals registered by the control are ready or there are no visuals.
993 if(IsResourceReady())
995 EmitResourceReadySignal();
999 // Called by a Visual when it's resource is ready
1000 void Control::Impl::ResourceReady(Visual::Base& object)
1002 DALI_LOG_INFO(gLogFilter, Debug::Verbose, "Control::Impl::ResourceReady() replacements pending[%d]\n", mRemoveVisuals.Count());
1004 Actor self = mControlImpl.Self();
1006 RegisteredVisualContainer::Iterator registeredIter;
1008 // A resource is ready, find resource in the registered visuals container and get its index
1009 if(!FindVisual(object, mVisuals, registeredIter))
1014 RegisteredVisualContainer::Iterator visualToRemoveIter;
1015 // Find visual with the same index in the removal container
1016 // Set if off stage as it's replacement is now ready.
1017 // Remove if from removal list as now removed from stage.
1018 // Set Pending flag on the ready visual to false as now ready.
1019 if(FindVisual((*registeredIter)->index, mRemoveVisuals, visualToRemoveIter))
1021 (*registeredIter)->pending = false;
1022 if(!((*visualToRemoveIter)->overideReadyTransition))
1024 Toolkit::GetImplementation((*visualToRemoveIter)->visual).SetOffScene(self);
1027 // Discard removed visual. It will be destroyed at next Idle time.
1028 DiscardVisual(visualToRemoveIter, mRemoveVisuals);
1031 // A visual is ready so control may need relayouting if staged
1032 RelayoutRequest(object);
1034 // Called by a Visual when it's resource is ready
1035 if(((*registeredIter)->enabled))
1041 void Control::Impl::NotifyVisualEvent(Visual::Base& object, Property::Index signalId)
1043 for(auto registeredIter = mVisuals.Begin(), end = mVisuals.End(); registeredIter != end; ++registeredIter)
1045 Internal::Visual::Base& registeredVisualImpl = Toolkit::GetImplementation((*registeredIter)->visual);
1046 if(&object == ®isteredVisualImpl)
1048 Dali::Toolkit::Control handle(mControlImpl.GetOwner());
1049 mVisualEventSignal.Emit(handle, (*registeredIter)->index, signalId);
1055 void Control::Impl::RelayoutRequest(Visual::Base& object)
1057 if(mControlImpl.Self().GetProperty<bool>(Actor::Property::CONNECTED_TO_SCENE))
1059 mControlImpl.RelayoutRequest();
1063 bool Control::Impl::IsResourceReady() const
1065 // Iterate through and check all the enabled visuals are ready
1066 for(auto visualIter = mVisuals.Begin();
1067 visualIter != mVisuals.End();
1070 const Toolkit::Visual::Base visual = (*visualIter)->visual;
1071 const Internal::Visual::Base& visualImpl = Toolkit::GetImplementation(visual);
1073 // one of the enabled visuals is not ready
1074 if(!visualImpl.IsResourceReady() && (*visualIter)->enabled)
1082 Toolkit::Visual::ResourceStatus Control::Impl::GetVisualResourceStatus(Property::Index index) const
1084 RegisteredVisualContainer::Iterator iter;
1085 if(FindVisual(index, mVisuals, iter))
1087 const Toolkit::Visual::Base visual = (*iter)->visual;
1088 const Internal::Visual::Base& visualImpl = Toolkit::GetImplementation(visual);
1089 return visualImpl.GetResourceStatus();
1092 return Toolkit::Visual::ResourceStatus::PREPARING;
1095 void Control::Impl::AddTransitions(Dali::Animation& animation,
1096 const Toolkit::TransitionData& handle,
1097 bool createAnimation)
1099 // Setup a Transition from TransitionData.
1100 const Internal::TransitionData& transitionData = Toolkit::GetImplementation(handle);
1101 TransitionData::Iterator end = transitionData.End();
1102 for(TransitionData::Iterator iter = transitionData.Begin();
1106 TransitionData::Animator* animator = (*iter);
1108 Toolkit::Visual::Base visual = GetVisualByName(mVisuals, animator->objectName);
1112 #if defined(DEBUG_ENABLED)
1113 Dali::TypeInfo typeInfo;
1114 ControlWrapper* controlWrapperImpl = dynamic_cast<ControlWrapper*>(&mControlImpl);
1115 if(controlWrapperImpl)
1117 typeInfo = controlWrapperImpl->GetTypeInfo();
1120 DALI_LOG_INFO(gLogFilter, Debug::Concise, "CreateTransition: Found %s visual for %s\n", visual.GetName().c_str(), typeInfo ? typeInfo.GetName().c_str() : "Unknown");
1122 Internal::Visual::Base& visualImpl = Toolkit::GetImplementation(visual);
1123 visualImpl.AnimateProperty(animation, *animator);
1127 DALI_LOG_INFO(gLogFilter, Debug::Concise, "CreateTransition: Could not find visual. Trying actors");
1128 // Otherwise, try any actor children of control (Including the control)
1129 Actor child = mControlImpl.Self().FindChildByName(animator->objectName);
1132 Property::Index propertyIndex = child.GetPropertyIndex(animator->propertyKey);
1133 if(propertyIndex != Property::INVALID_INDEX)
1135 if(animator->animate == false)
1137 if(animator->targetValue.GetType() != Property::NONE)
1139 child.SetProperty(propertyIndex, animator->targetValue);
1142 else // animate the property
1144 if(animator->initialValue.GetType() != Property::NONE)
1146 child.SetProperty(propertyIndex, animator->initialValue);
1149 if(createAnimation && !animation)
1151 animation = Dali::Animation::New(0.1f);
1154 animation.AnimateTo(Property(child, propertyIndex),
1155 animator->targetValue,
1156 animator->alphaFunction,
1157 TimePeriod(animator->timePeriodDelay,
1158 animator->timePeriodDuration));
1166 Dali::Animation Control::Impl::CreateTransition(const Toolkit::TransitionData& transitionData)
1168 Dali::Animation transition;
1170 if(transitionData.Count() > 0)
1172 AddTransitions(transition, transitionData, true);
1177 void Control::Impl::DoAction(Dali::Property::Index visualIndex, Dali::Property::Index actionId, const Dali::Property::Value attributes)
1179 RegisteredVisualContainer::Iterator iter;
1180 if(FindVisual(visualIndex, mVisuals, iter))
1182 Toolkit::GetImplementation((*iter)->visual).DoAction(actionId, attributes);
1186 void Control::Impl::DoActionExtension(Dali::Property::Index visualIndex, Dali::Property::Index actionId, Dali::Any attributes)
1188 RegisteredVisualContainer::Iterator iter;
1189 if(FindVisual(visualIndex, mVisuals, iter))
1191 Toolkit::GetImplementation((*iter)->visual).DoActionExtension(actionId, attributes);
1195 void Control::Impl::AppendAccessibilityAttribute(const std::string& key, const std::string value)
1197 Property::Value* checkedValue = mAccessibilityAttributes.Find(key);
1200 mAccessibilityAttributes[key] = Property::Value(value);
1204 mAccessibilityAttributes.Insert(key, value);
1208 void Control::Impl::SetProperty(BaseObject* object, Property::Index index, const Property::Value& value)
1210 DALI_ASSERT_ALWAYS(Stage::IsCoreThread() && "Core is not installed. Might call this API from worker thread?");
1212 Toolkit::Control control = Toolkit::Control::DownCast(BaseHandle(object));
1216 Control& controlImpl(GetImplementation(control));
1220 case Toolkit::Control::Property::STYLE_NAME:
1222 controlImpl.SetStyleName(value.Get<std::string>());
1226 case Toolkit::DevelControl::Property::STATE:
1228 bool withTransitions = true;
1229 const Property::Value* valuePtr = &value;
1230 const Property::Map* map = value.GetMap();
1233 Property::Value* value2 = map->Find("withTransitions");
1236 withTransitions = value2->Get<bool>();
1239 valuePtr = map->Find("state");
1244 Toolkit::DevelControl::State state(controlImpl.mImpl->mState);
1245 if(Scripting::GetEnumerationProperty<Toolkit::DevelControl::State>(*valuePtr, ControlStateTable, ControlStateTableCount, state))
1247 controlImpl.mImpl->SetState(state, withTransitions);
1253 case Toolkit::DevelControl::Property::SUB_STATE:
1255 std::string subState;
1256 if(value.Get(subState))
1258 controlImpl.mImpl->SetSubState(subState);
1263 case Toolkit::DevelControl::Property::LEFT_FOCUSABLE_ACTOR_ID:
1266 if(value.Get(focusId))
1268 controlImpl.mImpl->mLeftFocusableActorId = focusId;
1273 case Toolkit::DevelControl::Property::RIGHT_FOCUSABLE_ACTOR_ID:
1276 if(value.Get(focusId))
1278 controlImpl.mImpl->mRightFocusableActorId = focusId;
1283 case Toolkit::DevelControl::Property::UP_FOCUSABLE_ACTOR_ID:
1286 if(value.Get(focusId))
1288 controlImpl.mImpl->mUpFocusableActorId = focusId;
1293 case Toolkit::DevelControl::Property::DOWN_FOCUSABLE_ACTOR_ID:
1296 if(value.Get(focusId))
1298 controlImpl.mImpl->mDownFocusableActorId = focusId;
1303 case Toolkit::Control::Property::KEY_INPUT_FOCUS:
1305 if(value.Get<bool>())
1307 controlImpl.SetKeyInputFocus();
1311 controlImpl.ClearKeyInputFocus();
1316 case Toolkit::Control::Property::BACKGROUND:
1320 const Property::Map* map = value.GetMap();
1321 if(map && !map->Empty())
1323 controlImpl.SetBackground(*map);
1325 else if(value.Get(url))
1327 // don't know the size to load
1328 Toolkit::Visual::Base visual = Toolkit::VisualFactory::Get().CreateVisual(url, ImageDimensions());
1331 controlImpl.mImpl->RegisterVisual(Toolkit::Control::Property::BACKGROUND, visual, DepthIndex::BACKGROUND);
1334 else if(value.Get(color))
1336 controlImpl.SetBackgroundColor(color);
1340 // The background is an empty property map, so we should clear the background
1341 controlImpl.ClearBackground();
1346 case Toolkit::Control::Property::MARGIN:
1349 if(value.Get(margin))
1351 controlImpl.mImpl->SetMargin(margin);
1356 case Toolkit::Control::Property::PADDING:
1359 if(value.Get(padding))
1361 controlImpl.mImpl->SetPadding(padding);
1366 case Toolkit::DevelControl::Property::TOOLTIP:
1368 TooltipPtr& tooltipPtr = controlImpl.mImpl->mTooltip;
1371 tooltipPtr = Tooltip::New(control);
1373 tooltipPtr->SetProperties(value);
1377 case Toolkit::DevelControl::Property::SHADOW:
1379 const Property::Map* map = value.GetMap();
1380 if(map && !map->Empty())
1382 controlImpl.mImpl->SetShadow(*map);
1386 // The shadow is an empty property map, so we should clear the shadow
1387 controlImpl.mImpl->ClearShadow();
1392 case Toolkit::DevelControl::Property::ACCESSIBILITY_NAME:
1397 controlImpl.mImpl->mAccessibilityName = name;
1402 case Toolkit::DevelControl::Property::ACCESSIBILITY_DESCRIPTION:
1407 controlImpl.mImpl->mAccessibilityDescription = text;
1412 case Toolkit::DevelControl::Property::ACCESSIBILITY_TRANSLATION_DOMAIN:
1417 controlImpl.mImpl->mAccessibilityTranslationDomain = text;
1422 case Toolkit::DevelControl::Property::ACCESSIBILITY_ROLE:
1424 Dali::Accessibility::Role role;
1427 controlImpl.mImpl->mAccessibilityRole = role;
1432 case Toolkit::DevelControl::Property::ACCESSIBILITY_HIGHLIGHTABLE:
1435 if(value.Get(highlightable))
1437 controlImpl.mImpl->mAccessibilityHighlightable = highlightable;
1442 case Toolkit::DevelControl::Property::ACCESSIBILITY_ATTRIBUTES:
1444 const Property::Map* map = value.GetMap();
1445 if(map && !map->Empty())
1447 controlImpl.mImpl->mAccessibilityAttributes = *map;
1452 case Toolkit::DevelControl::Property::DISPATCH_KEY_EVENTS:
1455 if(value.Get(dispatch))
1457 controlImpl.mImpl->mDispatchKeyEvents = dispatch;
1462 case Toolkit::DevelControl::Property::ACCESSIBILITY_HIDDEN:
1465 if(value.Get(hidden))
1467 controlImpl.mImpl->mAccessibilityHidden = hidden;
1469 auto* accessible = controlImpl.GetAccessibleObject();
1470 auto* parent = dynamic_cast<Dali::Accessibility::ActorAccessible*>(accessible->GetParent());
1473 parent->OnChildrenChanged();
1478 case Toolkit::DevelControl::Property::CLOCKWISE_FOCUSABLE_ACTOR_ID:
1481 if(value.Get(focusId))
1483 controlImpl.mImpl->mClockwiseFocusableActorId = focusId;
1487 case Toolkit::DevelControl::Property::COUNTER_CLOCKWISE_FOCUSABLE_ACTOR_ID:
1490 if(value.Get(focusId))
1492 controlImpl.mImpl->mCounterClockwiseFocusableActorId = focusId;
1497 case Toolkit::DevelControl::Property::AUTOMATION_ID:
1499 std::string automationId;
1500 if(value.Get(automationId))
1502 controlImpl.mImpl->mAutomationId = automationId;
1510 Property::Value Control::Impl::GetProperty(BaseObject* object, Property::Index index)
1512 DALI_ASSERT_ALWAYS(Stage::IsCoreThread() && "Core is not installed. Might call this API from worker thread?");
1514 Property::Value value;
1516 Toolkit::Control control = Toolkit::Control::DownCast(BaseHandle(object));
1520 Control& controlImpl(GetImplementation(control));
1524 case Toolkit::Control::Property::STYLE_NAME:
1526 value = controlImpl.GetStyleName();
1530 case Toolkit::DevelControl::Property::STATE:
1532 value = controlImpl.mImpl->mState;
1536 case Toolkit::DevelControl::Property::SUB_STATE:
1538 value = controlImpl.mImpl->mSubStateName;
1542 case Toolkit::DevelControl::Property::LEFT_FOCUSABLE_ACTOR_ID:
1544 value = controlImpl.mImpl->mLeftFocusableActorId;
1548 case Toolkit::DevelControl::Property::RIGHT_FOCUSABLE_ACTOR_ID:
1550 value = controlImpl.mImpl->mRightFocusableActorId;
1554 case Toolkit::DevelControl::Property::UP_FOCUSABLE_ACTOR_ID:
1556 value = controlImpl.mImpl->mUpFocusableActorId;
1560 case Toolkit::DevelControl::Property::DOWN_FOCUSABLE_ACTOR_ID:
1562 value = controlImpl.mImpl->mDownFocusableActorId;
1566 case Toolkit::Control::Property::KEY_INPUT_FOCUS:
1568 value = controlImpl.HasKeyInputFocus();
1572 case Toolkit::Control::Property::BACKGROUND:
1575 Toolkit::Visual::Base visual = controlImpl.mImpl->GetVisual(Toolkit::Control::Property::BACKGROUND);
1578 visual.CreatePropertyMap(map);
1585 case Toolkit::Control::Property::MARGIN:
1587 value = controlImpl.mImpl->GetMargin();
1591 case Toolkit::Control::Property::PADDING:
1593 value = controlImpl.mImpl->GetPadding();
1597 case Toolkit::DevelControl::Property::TOOLTIP:
1600 if(controlImpl.mImpl->mTooltip)
1602 controlImpl.mImpl->mTooltip->CreatePropertyMap(map);
1608 case Toolkit::DevelControl::Property::SHADOW:
1611 Toolkit::Visual::Base visual = controlImpl.mImpl->GetVisual(Toolkit::DevelControl::Property::SHADOW);
1614 visual.CreatePropertyMap(map);
1621 case Toolkit::DevelControl::Property::ACCESSIBILITY_NAME:
1623 value = controlImpl.mImpl->mAccessibilityName;
1627 case Toolkit::DevelControl::Property::ACCESSIBILITY_DESCRIPTION:
1629 value = controlImpl.mImpl->mAccessibilityDescription;
1633 case Toolkit::DevelControl::Property::ACCESSIBILITY_TRANSLATION_DOMAIN:
1635 value = controlImpl.mImpl->mAccessibilityTranslationDomain;
1639 case Toolkit::DevelControl::Property::ACCESSIBILITY_ROLE:
1641 value = Property::Value(controlImpl.mImpl->mAccessibilityRole);
1645 case Toolkit::DevelControl::Property::ACCESSIBILITY_HIGHLIGHTABLE:
1647 value = controlImpl.mImpl->mAccessibilityHighlightable;
1651 case Toolkit::DevelControl::Property::ACCESSIBILITY_ATTRIBUTES:
1653 value = controlImpl.mImpl->mAccessibilityAttributes;
1657 case Toolkit::DevelControl::Property::DISPATCH_KEY_EVENTS:
1659 value = controlImpl.mImpl->mDispatchKeyEvents;
1663 case Toolkit::DevelControl::Property::ACCESSIBILITY_HIDDEN:
1665 value = controlImpl.mImpl->mAccessibilityHidden;
1669 case Toolkit::DevelControl::Property::CLOCKWISE_FOCUSABLE_ACTOR_ID:
1671 value = controlImpl.mImpl->mClockwiseFocusableActorId;
1675 case Toolkit::DevelControl::Property::COUNTER_CLOCKWISE_FOCUSABLE_ACTOR_ID:
1677 value = controlImpl.mImpl->mCounterClockwiseFocusableActorId;
1681 case Toolkit::DevelControl::Property::AUTOMATION_ID:
1683 value = controlImpl.mImpl->mAutomationId;
1692 void Control::Impl::RemoveAccessibilityAttribute(const std::string& key)
1694 Property::Value* value = mAccessibilityAttributes.Find(key);
1697 mAccessibilityAttributes[key] = Property::Value();
1701 void Control::Impl::ClearAccessibilityAttributes()
1703 mAccessibilityAttributes.Clear();
1706 void Control::Impl::SetAccessibilityReadingInfoType(const Dali::Accessibility::ReadingInfoTypes types)
1708 std::string value{};
1709 if(types[Dali::Accessibility::ReadingInfoType::NAME])
1711 value += READING_INFO_TYPE_NAME;
1713 if(types[Dali::Accessibility::ReadingInfoType::ROLE])
1717 value += READING_INFO_TYPE_SEPARATOR;
1719 value += READING_INFO_TYPE_ROLE;
1721 if(types[Dali::Accessibility::ReadingInfoType::DESCRIPTION])
1725 value += READING_INFO_TYPE_SEPARATOR;
1727 value += READING_INFO_TYPE_DESCRIPTION;
1729 if(types[Dali::Accessibility::ReadingInfoType::STATE])
1733 value += READING_INFO_TYPE_SEPARATOR;
1735 value += READING_INFO_TYPE_STATE;
1737 AppendAccessibilityAttribute(READING_INFO_TYPE_ATTRIBUTE_NAME, value);
1740 Dali::Accessibility::ReadingInfoTypes Control::Impl::GetAccessibilityReadingInfoType() const
1742 std::string value{};
1743 auto place = mAccessibilityAttributes.Find(READING_INFO_TYPE_ATTRIBUTE_NAME);
1750 Dali::Accessibility::ReadingInfoTypes types;
1751 types[Dali::Accessibility::ReadingInfoType::NAME] = true;
1752 types[Dali::Accessibility::ReadingInfoType::ROLE] = true;
1753 types[Dali::Accessibility::ReadingInfoType::DESCRIPTION] = true;
1754 types[Dali::Accessibility::ReadingInfoType::STATE] = true;
1763 Dali::Accessibility::ReadingInfoTypes types;
1765 if(value.find(READING_INFO_TYPE_NAME) != std::string::npos)
1767 types[Dali::Accessibility::ReadingInfoType::NAME] = true;
1769 if(value.find(READING_INFO_TYPE_ROLE) != std::string::npos)
1771 types[Dali::Accessibility::ReadingInfoType::ROLE] = true;
1773 if(value.find(READING_INFO_TYPE_DESCRIPTION) != std::string::npos)
1775 types[Dali::Accessibility::ReadingInfoType::DESCRIPTION] = true;
1777 if(value.find(READING_INFO_TYPE_STATE) != std::string::npos)
1779 types[Dali::Accessibility::ReadingInfoType::STATE] = true;
1785 void Control::Impl::CopyInstancedProperties(RegisteredVisualContainer& visuals, Dictionary<Property::Map>& instancedProperties)
1787 for(RegisteredVisualContainer::Iterator iter = visuals.Begin(); iter != visuals.End(); iter++)
1791 Property::Map instanceMap;
1792 Toolkit::GetImplementation((*iter)->visual).CreateInstancePropertyMap(instanceMap);
1793 instancedProperties.Add((*iter)->visual.GetName(), instanceMap);
1798 void Control::Impl::RemoveVisual(RegisteredVisualContainer& visuals, const std::string& visualName)
1800 Actor self(mControlImpl.Self());
1802 for(RegisteredVisualContainer::Iterator visualIter = visuals.Begin();
1803 visualIter != visuals.End();
1806 Toolkit::Visual::Base visual = (*visualIter)->visual;
1807 if(visual && visual.GetName() == visualName)
1809 Toolkit::GetImplementation(visual).SetOffScene(self);
1810 (*visualIter)->visual.Reset();
1811 visuals.Erase(visualIter);
1817 void Control::Impl::RemoveVisuals(RegisteredVisualContainer& visuals, DictionaryKeys& removeVisuals)
1819 Actor self(mControlImpl.Self());
1820 for(DictionaryKeys::iterator iter = removeVisuals.begin(); iter != removeVisuals.end(); ++iter)
1822 const std::string visualName = *iter;
1823 RemoveVisual(visuals, visualName);
1827 void Control::Impl::RecreateChangedVisuals(Dictionary<Property::Map>& stateVisualsToChange,
1828 Dictionary<Property::Map>& instancedProperties)
1830 Dali::CustomActor handle(mControlImpl.GetOwner());
1831 for(Dictionary<Property::Map>::iterator iter = stateVisualsToChange.Begin();
1832 iter != stateVisualsToChange.End();
1835 const std::string& visualName = (*iter).key;
1836 const Property::Map& toMap = (*iter).entry;
1838 Actor self = mControlImpl.Self();
1839 RegisteredVisualContainer::Iterator registeredVisualsiter;
1840 // Check if visual (visualName) is already registered, this is the current visual.
1841 if(FindVisual(visualName, mVisuals, registeredVisualsiter))
1843 Toolkit::Visual::Base& visual = (*registeredVisualsiter)->visual;
1846 // No longer required to know if the replaced visual's resources are ready
1847 StopObservingVisual(visual);
1849 // If control staged then visuals will be swapped once ready
1850 if(self.GetProperty<bool>(Actor::Property::CONNECTED_TO_SCENE))
1852 // Check if visual is currently in the process of being replaced ( is in removal container )
1853 RegisteredVisualContainer::Iterator visualQueuedForRemoval;
1854 if(FindVisual(visualName, mRemoveVisuals, visualQueuedForRemoval))
1856 // Visual with same visual name is already in removal container so current visual pending
1857 // Only the the last requested visual will be displayed so remove current visual which is staged but not ready.
1858 Toolkit::GetImplementation(visual).SetOffScene(self);
1859 (*registeredVisualsiter)->visual.Reset();
1860 mVisuals.Erase(registeredVisualsiter);
1864 // current visual not already in removal container so add now.
1865 DALI_LOG_INFO(gLogFilter, Debug::Verbose, "RegisterVisual Move current registered visual to removal Queue: %s \n", visualName.c_str());
1866 MoveVisual(registeredVisualsiter, mVisuals, mRemoveVisuals);
1871 // Control not staged or visual disabled so can just erase from registered visuals and new visual will be added later.
1872 (*registeredVisualsiter)->visual.Reset();
1873 mVisuals.Erase(registeredVisualsiter);
1877 const Property::Map* instancedMap = instancedProperties.FindConst(visualName);
1878 Style::ApplyVisual(handle, visualName, toMap, instancedMap);
1883 void Control::Impl::ReplaceStateVisualsAndProperties(const StylePtr oldState, const StylePtr newState, const std::string& subState)
1885 DALI_ASSERT_ALWAYS(Stage::IsCoreThread() && "Core is not installed. Might call this API from worker thread?");
1887 // Collect all old visual names
1888 DictionaryKeys stateVisualsToRemove;
1891 oldState->visuals.GetKeys(stateVisualsToRemove);
1892 if(!subState.empty())
1894 const StylePtr* oldSubState = oldState->subStates.FindConst(subState);
1897 DictionaryKeys subStateVisualsToRemove;
1898 (*oldSubState)->visuals.GetKeys(subStateVisualsToRemove);
1899 Merge(stateVisualsToRemove, subStateVisualsToRemove);
1904 // Collect all new visual properties
1905 Dictionary<Property::Map> stateVisualsToAdd;
1908 stateVisualsToAdd = newState->visuals;
1909 if(!subState.empty())
1911 const StylePtr* newSubState = newState->subStates.FindConst(subState);
1914 stateVisualsToAdd.Merge((*newSubState)->visuals);
1919 // If a name is in both add/remove, move it to change list.
1920 Dictionary<Property::Map> stateVisualsToChange;
1921 FindChangableVisuals(stateVisualsToAdd, stateVisualsToChange, stateVisualsToRemove);
1923 // Copy instanced properties (e.g. text label) of current visuals
1924 Dictionary<Property::Map> instancedProperties;
1925 CopyInstancedProperties(mVisuals, instancedProperties);
1927 // For each visual in remove list, remove from mVisuals
1928 RemoveVisuals(mVisuals, stateVisualsToRemove);
1930 // For each visual in add list, create and add to mVisuals
1931 Dali::CustomActor handle(mControlImpl.GetOwner());
1932 Style::ApplyVisuals(handle, stateVisualsToAdd, instancedProperties);
1934 // For each visual in change list, if it requires a new visual,
1935 // remove old visual, create and add to mVisuals
1936 RecreateChangedVisuals(stateVisualsToChange, instancedProperties);
1939 void Control::Impl::SetState(DevelControl::State newState, bool withTransitions)
1941 DevelControl::State oldState = mState;
1942 Dali::CustomActor handle(mControlImpl.GetOwner());
1943 DALI_LOG_INFO(gLogFilter, Debug::Concise, "Control::Impl::SetState: %s\n", (mState == DevelControl::NORMAL ? "NORMAL" : (mState == DevelControl::FOCUSED ? "FOCUSED" : (mState == DevelControl::DISABLED ? "DISABLED" : "NONE"))));
1945 if(mState != newState)
1947 // If mState was Disabled, and new state is Focused, should probably
1948 // store that fact, e.g. in another property that FocusManager can access.
1951 // Trigger state change and transitions
1952 // Apply new style, if stylemanager is available
1953 Toolkit::StyleManager styleManager = Toolkit::StyleManager::Get();
1956 const StylePtr stylePtr = GetImpl(styleManager).GetRecordedStyle(Toolkit::Control(mControlImpl.GetOwner()));
1960 std::string oldStateName = Scripting::GetEnumerationName<Toolkit::DevelControl::State>(oldState, ControlStateTable, ControlStateTableCount);
1961 std::string newStateName = Scripting::GetEnumerationName<Toolkit::DevelControl::State>(newState, ControlStateTable, ControlStateTableCount);
1963 const StylePtr* newStateStyle = stylePtr->subStates.Find(newStateName);
1964 const StylePtr* oldStateStyle = stylePtr->subStates.Find(oldStateName);
1965 if(oldStateStyle && newStateStyle)
1967 // Only change if both state styles exist
1968 ReplaceStateVisualsAndProperties(*oldStateStyle, *newStateStyle, mSubStateName);
1975 void Control::Impl::SetSubState(const std::string& subStateName, bool withTransitions)
1977 if(mSubStateName != subStateName)
1979 // Get existing sub-state visuals, and unregister them
1980 Dali::CustomActor handle(mControlImpl.GetOwner());
1982 Toolkit::StyleManager styleManager = Toolkit::StyleManager::Get();
1985 const StylePtr stylePtr = GetImpl(styleManager).GetRecordedStyle(Toolkit::Control(mControlImpl.GetOwner()));
1989 std::string stateName = Scripting::GetEnumerationName<Toolkit::DevelControl::State>(mState, ControlStateTable, ControlStateTableCount);
1991 const StylePtr* state = stylePtr->subStates.Find(stateName);
1994 StylePtr stateStyle(*state);
1996 const StylePtr* newStateStyle = stateStyle->subStates.Find(subStateName);
1997 const StylePtr* oldStateStyle = stateStyle->subStates.Find(mSubStateName);
1998 if(oldStateStyle && newStateStyle)
2001 ReplaceStateVisualsAndProperties(*oldStateStyle, *newStateStyle, empty);
2007 mSubStateName = subStateName;
2011 void Control::Impl::OnSceneDisconnection()
2013 Actor self = mControlImpl.Self();
2015 // Any visuals set for replacement but not yet ready should still be registered.
2016 // Reason: If a request was made to register a new visual but the control removed from scene before visual was ready
2017 // then when this control appears back on stage it should use that new visual.
2019 // Iterate through all registered visuals and set off scene
2020 SetVisualsOffScene(mVisuals, self);
2022 // Visuals pending replacement can now be taken out of the removal list and set off scene
2023 // Iterate through all replacement visuals and add to a move queue then set off scene
2025 if(!mRemoveVisuals.Empty())
2027 std::reverse(mRemoveVisuals.Begin(), mRemoveVisuals.End());
2029 while(!mRemoveVisuals.Empty())
2031 auto removalIter = mRemoveVisuals.End() - 1u;
2032 Toolkit::GetImplementation((*removalIter)->visual).SetOffScene(self);
2034 // Discard removed visual. It will be destroyed at next Idle time.
2035 DiscardVisual(removalIter, mRemoveVisuals);
2039 for(auto replacedIter = mVisuals.Begin(), end = mVisuals.End(); replacedIter != end; replacedIter++)
2041 (*replacedIter)->pending = false;
2045 void Control::Impl::SetMargin(Extents margin)
2047 mControlImpl.mImpl->mMargin = margin;
2049 // Trigger a size negotiation request that may be needed when setting a margin.
2050 mControlImpl.RelayoutRequest();
2053 Extents Control::Impl::GetMargin() const
2055 return mControlImpl.mImpl->mMargin;
2058 void Control::Impl::SetPadding(Extents padding)
2060 mControlImpl.mImpl->mPadding = padding;
2062 // Trigger a size negotiation request that may be needed when setting a padding.
2063 mControlImpl.RelayoutRequest();
2066 Extents Control::Impl::GetPadding() const
2068 return mControlImpl.mImpl->mPadding;
2071 void Control::Impl::SetInputMethodContext(InputMethodContext& inputMethodContext)
2073 mInputMethodContext = inputMethodContext;
2076 bool Control::Impl::FilterKeyEvent(const KeyEvent& event)
2078 bool consumed(false);
2080 if(mInputMethodContext)
2082 consumed = mInputMethodContext.FilterEventKey(event);
2087 DevelControl::VisualEventSignalType& Control::Impl::VisualEventSignal()
2089 return mVisualEventSignal;
2092 void Control::Impl::SetShadow(const Property::Map& map)
2094 Toolkit::Visual::Base visual = Toolkit::VisualFactory::Get().CreateVisual(map);
2095 visual.SetName("shadow");
2099 mControlImpl.mImpl->RegisterVisual(Toolkit::DevelControl::Property::SHADOW, visual, DepthIndex::BACKGROUND_EFFECT);
2101 mControlImpl.RelayoutRequest();
2105 void Control::Impl::ClearShadow()
2107 mControlImpl.mImpl->UnregisterVisual(Toolkit::DevelControl::Property::SHADOW);
2109 // Trigger a size negotiation request that may be needed when unregistering a visual.
2110 mControlImpl.RelayoutRequest();
2113 Dali::Property Control::Impl::GetVisualProperty(Dali::Property::Index index, Dali::Property::Key visualPropertyKey)
2115 Toolkit::Visual::Base visual = GetVisualByIndex(mVisuals, index);
2118 Internal::Visual::Base& visualImpl = Toolkit::GetImplementation(visual);
2119 return visualImpl.GetPropertyObject(std::move(visualPropertyKey));
2123 return Dali::Property(handle, Property::INVALID_INDEX);
2126 void Control::Impl::CreateTransitions(std::vector<std::pair<Dali::Property::Index, Dali::Property::Map>>& sourceProperties,
2127 std::vector<std::pair<Dali::Property::Index, Dali::Property::Map>>& destinationProperties,
2128 Dali::Toolkit::Control source,
2129 Dali::Toolkit::Control destination)
2131 // Retrieves background properties to be transitioned.
2132 Dali::Property::Map backgroundSourcePropertyMap, backgroundDestinationPropertyMap;
2133 mControlImpl.MakeVisualTransition(backgroundSourcePropertyMap, backgroundDestinationPropertyMap, source, destination, Toolkit::Control::Property::BACKGROUND);
2134 if(backgroundSourcePropertyMap.Count() > 0)
2136 sourceProperties.push_back(std::pair<Dali::Property::Index, Dali::Property::Map>(Toolkit::Control::Property::BACKGROUND, backgroundSourcePropertyMap));
2137 destinationProperties.push_back(std::pair<Dali::Property::Index, Dali::Property::Map>(Toolkit::Control::Property::BACKGROUND, backgroundDestinationPropertyMap));
2140 // Retrieves shadow properties to be transitioned.
2141 Dali::Property::Map shadowSourcePropertyMap, shadowDestinationPropertyMap;
2142 mControlImpl.MakeVisualTransition(shadowSourcePropertyMap, shadowDestinationPropertyMap, source, destination, Toolkit::DevelControl::Property::SHADOW);
2143 if(shadowSourcePropertyMap.Count() > 0)
2145 sourceProperties.push_back(std::pair<Dali::Property::Index, Dali::Property::Map>(Toolkit::DevelControl::Property::SHADOW, shadowSourcePropertyMap));
2146 destinationProperties.push_back(std::pair<Dali::Property::Index, Dali::Property::Map>(Toolkit::DevelControl::Property::SHADOW, shadowDestinationPropertyMap));
2149 // Retrieves transition from inherited class.
2150 mControlImpl.OnCreateTransitions(sourceProperties, destinationProperties, source, destination);
2153 void Control::Impl::UpdateVisualProperties(const std::vector<std::pair<Dali::Property::Index, Dali::Property::Map>>& properties)
2155 for(auto&& data : properties)
2157 if(data.first == Toolkit::Control::Property::BACKGROUND)
2159 DoAction(Toolkit::Control::Property::BACKGROUND, DevelVisual::Action::UPDATE_PROPERTY, data.second);
2161 else if(data.first == Toolkit::DevelControl::Property::SHADOW)
2163 DoAction(Toolkit::DevelControl::Property::SHADOW, DevelVisual::Action::UPDATE_PROPERTY, data.second);
2166 mControlImpl.OnUpdateVisualProperties(properties);
2169 void Control::Impl::EmitResourceReadySignal()
2171 if(!mIsEmittingResourceReadySignal)
2173 // Guard against calls to emit the signal during the callback
2174 mIsEmittingResourceReadySignal = true;
2176 // If the signal handler changes visual, it may become ready during this call & therefore this method will
2177 // get called again recursively. If so, mIdleCallbackRegistered is set below, and we act on it after that secondary
2178 // invocation has completed by notifying in an Idle callback to prevent further recursion.
2179 Dali::Toolkit::Control handle(mControlImpl.GetOwner());
2180 mResourceReadySignal.Emit(handle);
2182 mIsEmittingResourceReadySignal = false;
2186 if(!mIdleCallbackRegistered)
2188 mIdleCallbackRegistered = true;
2190 // Add idler to emit the signal again
2193 // The callback manager takes the ownership of the callback object.
2194 mIdleCallback = MakeCallback(this, &Control::Impl::OnIdleCallback);
2195 Adaptor::Get().AddIdle(mIdleCallback, true);
2201 bool Control::Impl::OnIdleCallback()
2204 mIdleCallbackRegistered = false;
2206 // A visual is ready so control may need relayouting if staged
2207 if(mControlImpl.Self().GetProperty<bool>(Actor::Property::CONNECTED_TO_SCENE))
2209 mControlImpl.RelayoutRequest();
2212 EmitResourceReadySignal();
2214 if(!mIdleCallbackRegistered)
2216 // Set the pointer to null as the callback manager deletes the callback after execute it.
2217 mIdleCallback = nullptr;
2220 // Repeat idle if mIdleCallbackRegistered become true one more time.
2221 return mIdleCallbackRegistered;
2224 Toolkit::DevelControl::ControlAccessible* Control::Impl::GetAccessibleObject()
2226 if(!mAccessibleObject)
2228 mAccessibleObject.reset(mControlImpl.CreateAccessibleObject());
2231 return mAccessibleObject.get();
2234 } // namespace Internal
2236 } // namespace Toolkit