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 if(DALI_LIKELY(accessible))
623 auto lastPosition = accessible->GetLastPosition();
624 auto accessibleRect = accessible->GetExtents(Dali::Accessibility::CoordinateType::WINDOW);
625 auto rect = GetShowingGeometry(accessibleRect, accessible);
627 switch(mAccessibilityLastScreenRelativeMoveType)
629 case Dali::Accessibility::ScreenRelativeMoveType::OUTSIDE:
631 if(IsShowingGeometryOnScreen(rect))
633 mAccessibilityLastScreenRelativeMoveType = Dali::Accessibility::ScreenRelativeMoveType::INSIDE;
637 case Dali::Accessibility::ScreenRelativeMoveType::INSIDE:
639 if(rect.width < 0 && !Dali::Equals(accessibleRect.x, lastPosition.x))
641 mAccessibilityLastScreenRelativeMoveType = (accessibleRect.x < lastPosition.x) ? Dali::Accessibility::ScreenRelativeMoveType::OUTGOING_TOP_LEFT : Dali::Accessibility::ScreenRelativeMoveType::OUTGOING_BOTTOM_RIGHT;
643 if(rect.height < 0 && !Dali::Equals(accessibleRect.y, lastPosition.y))
645 mAccessibilityLastScreenRelativeMoveType = (accessibleRect.y < lastPosition.y) ? Dali::Accessibility::ScreenRelativeMoveType::OUTGOING_TOP_LEFT : Dali::Accessibility::ScreenRelativeMoveType::OUTGOING_BOTTOM_RIGHT;
647 // notify AT-clients on outgoing moves only
648 if(mAccessibilityLastScreenRelativeMoveType != Dali::Accessibility::ScreenRelativeMoveType::INSIDE)
650 accessible->EmitMovedOutOfScreen(mAccessibilityLastScreenRelativeMoveType);
654 case Dali::Accessibility::ScreenRelativeMoveType::OUTGOING_TOP_LEFT:
655 case Dali::Accessibility::ScreenRelativeMoveType::OUTGOING_BOTTOM_RIGHT:
657 if(IsShowingGeometryOnScreen(rect))
659 mAccessibilityLastScreenRelativeMoveType = Dali::Accessibility::ScreenRelativeMoveType::INSIDE;
663 mAccessibilityLastScreenRelativeMoveType = Dali::Accessibility::ScreenRelativeMoveType::OUTSIDE;
673 accessible->SetLastPosition(Vector2(accessibleRect.x, accessibleRect.y));
677 void Control::Impl::RegisterAccessibilityPositionPropertyNotification()
679 if(mIsAccessibilityPositionPropertyNotificationSet)
683 // set default value until first move of object is detected
684 mAccessibilityLastScreenRelativeMoveType = Dali::Accessibility::ScreenRelativeMoveType::OUTSIDE;
685 // recalculate mAccessibilityLastScreenRelativeMoveType accordingly to the initial position
686 CheckHighlightedObjectGeometry();
687 mAccessibilityPositionNotification = mControlImpl.Self().AddPropertyNotification(Actor::Property::WORLD_POSITION, StepCondition(1.0f, 1.0f));
688 mAccessibilityPositionNotification.SetNotifyMode(PropertyNotification::NOTIFY_ON_CHANGED);
689 mAccessibilityPositionNotification.NotifySignal().Connect(this, [this](PropertyNotification&) { CheckHighlightedObjectGeometry(); });
690 mIsAccessibilityPositionPropertyNotificationSet = true;
693 void Control::Impl::UnregisterAccessibilityPositionPropertyNotification()
695 mControlImpl.Self().RemovePropertyNotification(mAccessibilityPositionNotification);
696 mIsAccessibilityPositionPropertyNotificationSet = false;
699 // Gesture Detection Methods
700 void Control::Impl::PinchDetected(Actor actor, const PinchGesture& pinch)
702 mControlImpl.OnPinch(pinch);
705 void Control::Impl::PanDetected(Actor actor, const PanGesture& pan)
707 mControlImpl.OnPan(pan);
710 void Control::Impl::TapDetected(Actor actor, const TapGesture& tap)
712 mControlImpl.OnTap(tap);
715 void Control::Impl::LongPressDetected(Actor actor, const LongPressGesture& longPress)
717 mControlImpl.OnLongPress(longPress);
720 void Control::Impl::RegisterVisual(Property::Index index, Toolkit::Visual::Base& visual)
722 RegisterVisual(index, visual, VisualState::ENABLED, DepthIndexValue::NOT_SET);
725 void Control::Impl::RegisterVisual(Property::Index index, Toolkit::Visual::Base& visual, int depthIndex)
727 RegisterVisual(index, visual, VisualState::ENABLED, DepthIndexValue::SET, depthIndex);
730 void Control::Impl::RegisterVisual(Property::Index index, Toolkit::Visual::Base& visual, bool enabled)
732 RegisterVisual(index, visual, (enabled ? VisualState::ENABLED : VisualState::DISABLED), DepthIndexValue::NOT_SET);
735 void Control::Impl::RegisterVisual(Property::Index index, Toolkit::Visual::Base& visual, bool enabled, int depthIndex)
737 RegisterVisual(index, visual, (enabled ? VisualState::ENABLED : VisualState::DISABLED), DepthIndexValue::SET, depthIndex);
740 void Control::Impl::RegisterVisual(Property::Index index, Toolkit::Visual::Base& visual, VisualState::Type enabled, DepthIndexValue::Type depthIndexValueSet, int depthIndex)
742 DALI_ASSERT_ALWAYS(Stage::IsCoreThread() && "Core is not installed. Might call this API from worker thread?");
744 DALI_LOG_INFO(gLogFilter, Debug::Concise, "RegisterVisual:%d \n", index);
746 bool visualReplaced(false);
747 Actor self = mControlImpl.Self();
749 // Set the depth index, if not set by caller this will be either the current visual depth, max depth of all visuals
751 int requiredDepthIndex = visual.GetDepthIndex();
753 if(depthIndexValueSet == DepthIndexValue::SET)
755 requiredDepthIndex = depthIndex;
758 // Visual replacement, existing visual should only be removed from stage when replacement ready.
759 if(!mVisuals.Empty())
761 RegisteredVisualContainer::Iterator registeredVisualsiter;
762 // Check if visual (index) is already registered, this is the current visual.
763 if(FindVisual(index, mVisuals, registeredVisualsiter))
765 Toolkit::Visual::Base& currentRegisteredVisual = (*registeredVisualsiter)->visual;
766 if(currentRegisteredVisual)
768 // Store current visual depth index as may need to set the replacement visual to same depth
769 const int currentDepthIndex = (*registeredVisualsiter)->visual.GetDepthIndex();
771 // No longer required to know if the replaced visual's resources are ready
772 StopObservingVisual(currentRegisteredVisual);
774 // If control staged and visual enabled then visuals will be swapped once ready
775 if(self.GetProperty<bool>(Actor::Property::CONNECTED_TO_SCENE) && enabled)
777 // Check if visual is currently in the process of being replaced ( is in removal container )
778 RegisteredVisualContainer::Iterator visualQueuedForRemoval;
779 if(FindVisual(index, mRemoveVisuals, visualQueuedForRemoval))
781 // Visual with same index is already in removal container so current visual pending
782 // Only the the last requested visual will be displayed so remove current visual which is staged but not ready.
783 Toolkit::GetImplementation(currentRegisteredVisual).SetOffScene(self);
784 mVisuals.Erase(registeredVisualsiter);
788 // current visual not already in removal container so add now.
789 DALI_LOG_INFO(gLogFilter, Debug::Verbose, "RegisterVisual Move current registered visual to removal Queue: %d \n", index);
790 MoveVisual(registeredVisualsiter, mVisuals, mRemoveVisuals);
795 // Control not staged or visual disabled so can just erase from registered visuals and new visual will be added later.
796 mVisuals.Erase(registeredVisualsiter);
799 // 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
800 if((depthIndexValueSet == DepthIndexValue::NOT_SET) &&
801 (visual.GetDepthIndex() == 0))
803 requiredDepthIndex = currentDepthIndex;
807 visualReplaced = true;
811 // If not set, set the name of the visual to the same name as the control's property.
812 // ( If the control has been type registered )
813 if(visual.GetName().empty())
815 // returns empty string if index is not found as long as index is not -1
816 std::string visualName = self.GetPropertyName(index);
817 if(!visualName.empty())
819 DALI_LOG_INFO(gLogFilter, Debug::Concise, "Setting visual name for property %d to %s\n", index, visualName.c_str());
820 visual.SetName(visualName);
824 if(!visualReplaced) // New registration entry
826 // 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
827 if((depthIndexValueSet == DepthIndexValue::NOT_SET) &&
828 (mVisuals.Size() > 0) &&
829 (visual.GetDepthIndex() == 0))
831 int maxDepthIndex = std::numeric_limits<int>::min();
833 RegisteredVisualContainer::ConstIterator iter;
834 const RegisteredVisualContainer::ConstIterator endIter = mVisuals.End();
835 for(iter = mVisuals.Begin(); iter != endIter; iter++)
837 const int visualDepthIndex = (*iter)->visual.GetDepthIndex();
838 if(visualDepthIndex > maxDepthIndex)
840 maxDepthIndex = visualDepthIndex;
843 ++maxDepthIndex; // Add one to the current maximum depth index so that our added visual appears on top
844 requiredDepthIndex = std::max(0, maxDepthIndex); // Start at zero if maxDepth index belongs to a background
850 // Set determined depth index
851 visual.SetDepthIndex(requiredDepthIndex);
853 // Monitor when the visual resources are ready
854 StartObservingVisual(visual);
856 DALI_LOG_INFO(gLogFilter, Debug::Concise, "New Visual registration index[%d] depth[%d]\n", index, requiredDepthIndex);
857 RegisteredVisual* newRegisteredVisual = new RegisteredVisual(index, visual, (enabled == VisualState::ENABLED ? true : false), (visualReplaced && enabled));
858 mVisuals.PushBack(newRegisteredVisual);
860 Internal::Visual::Base& visualImpl = Toolkit::GetImplementation(visual);
861 // Put on stage if enabled and the control is already on the stage
862 if((enabled == VisualState::ENABLED) && self.GetProperty<bool>(Actor::Property::CONNECTED_TO_SCENE))
864 visualImpl.SetOnScene(self);
866 else if(enabled && visualImpl.IsResourceReady()) // When not being staged, check if visual already 'ResourceReady' before it was Registered. ( Resource may have been loaded already )
868 ResourceReady(visualImpl);
872 DALI_LOG_INFO(gLogFilter, Debug::Verbose, "Control::RegisterVisual() Registered %s(%d), enabled:%s\n", visual.GetName().c_str(), index, enabled ? "true" : "false");
875 void Control::Impl::UnregisterVisual(Property::Index index)
877 DALI_ASSERT_ALWAYS(Stage::IsCoreThread() && "Core is not installed. Might call this API from worker thread?");
879 RegisteredVisualContainer::Iterator iter;
880 if(FindVisual(index, mVisuals, iter))
882 // stop observing visual
883 StopObservingVisual((*iter)->visual);
885 Actor self(mControlImpl.Self());
886 Toolkit::GetImplementation((*iter)->visual).SetOffScene(self);
887 (*iter)->visual.Reset();
888 mVisuals.Erase(iter);
891 if(FindVisual(index, mRemoveVisuals, iter))
893 Actor self(mControlImpl.Self());
894 Toolkit::GetImplementation((*iter)->visual).SetOffScene(self);
895 (*iter)->pending = false;
897 // Discard removed visual. It will be destroyed at next Idle time.
898 DiscardVisual(iter, mRemoveVisuals);
902 Toolkit::Visual::Base Control::Impl::GetVisual(Property::Index index) const
904 RegisteredVisualContainer::Iterator iter;
905 if(FindVisual(index, mVisuals, iter))
907 return (*iter)->visual;
910 return Toolkit::Visual::Base();
913 void Control::Impl::EnableVisual(Property::Index index, bool enable)
915 DALI_LOG_INFO(gLogFilter, Debug::General, "Control::EnableVisual(%d, %s)\n", index, enable ? "T" : "F");
917 RegisteredVisualContainer::Iterator iter;
918 if(FindVisual(index, mVisuals, iter))
920 if((*iter)->enabled == enable)
922 DALI_LOG_INFO(gLogFilter, Debug::Verbose, "Control::EnableVisual Visual %s(%d) already %s\n", (*iter)->visual.GetName().c_str(), index, enable ? "enabled" : "disabled");
926 (*iter)->enabled = enable;
927 Actor parentActor = mControlImpl.Self();
928 if(mControlImpl.Self().GetProperty<bool>(Actor::Property::CONNECTED_TO_SCENE)) // If control not on Scene then Visual will be added when SceneConnection is called.
932 DALI_LOG_INFO(gLogFilter, Debug::Verbose, "Control::EnableVisual Setting %s(%d) on stage \n", (*iter)->visual.GetName().c_str(), index);
933 Toolkit::GetImplementation((*iter)->visual).SetOnScene(parentActor);
937 DALI_LOG_INFO(gLogFilter, Debug::Verbose, "Control::EnableVisual Setting %s(%d) off stage \n", (*iter)->visual.GetName().c_str(), index);
938 Toolkit::GetImplementation((*iter)->visual).SetOffScene(parentActor); // No need to call if control not staged.
944 DALI_LOG_WARNING("Control::EnableVisual(%d, %s) FAILED - NO SUCH VISUAL\n", index, enable ? "T" : "F");
948 bool Control::Impl::IsVisualEnabled(Property::Index index) const
950 RegisteredVisualContainer::Iterator iter;
951 if(FindVisual(index, mVisuals, iter))
953 return (*iter)->enabled;
958 void Control::Impl::EnableReadyTransitionOverriden(Toolkit::Visual::Base& visual, bool enable)
960 DALI_LOG_INFO(gLogFilter, Debug::General, "Control::EnableReadyTransitionOverriden(%p, %s)\n", visual, enable ? "T" : "F");
962 RegisteredVisualContainer::Iterator iter;
963 if(FindVisual(visual, mVisuals, iter))
965 if((*iter)->overideReadyTransition == enable)
967 DALI_LOG_INFO(gLogFilter, Debug::Verbose, "Control::EnableReadyTransitionOverriden Visual %s(%p) already %s\n", (*iter)->visual.GetName().c_str(), visual, enable ? "enabled" : "disabled");
971 (*iter)->overideReadyTransition = enable;
975 void Control::Impl::StopObservingVisual(Toolkit::Visual::Base& visual)
977 Internal::Visual::Base& visualImpl = Toolkit::GetImplementation(visual);
979 // Stop observing the visual
980 visualImpl.RemoveEventObserver(*this);
983 void Control::Impl::StartObservingVisual(Toolkit::Visual::Base& visual)
985 Internal::Visual::Base& visualImpl = Toolkit::GetImplementation(visual);
987 // start observing the visual for events
988 visualImpl.AddEventObserver(*this);
991 void Control::Impl::ResourceReady()
993 DALI_ASSERT_ALWAYS(Stage::IsCoreThread() && "Core is not installed. Might call this API from worker thread?");
995 // Emit signal if all enabled visuals registered by the control are ready or there are no visuals.
996 if(IsResourceReady())
998 EmitResourceReadySignal();
1002 // Called by a Visual when it's resource is ready
1003 void Control::Impl::ResourceReady(Visual::Base& object)
1005 DALI_LOG_INFO(gLogFilter, Debug::Verbose, "Control::Impl::ResourceReady() replacements pending[%d]\n", mRemoveVisuals.Count());
1007 Actor self = mControlImpl.Self();
1009 RegisteredVisualContainer::Iterator registeredIter;
1011 // A resource is ready, find resource in the registered visuals container and get its index
1012 if(!FindVisual(object, mVisuals, registeredIter))
1017 RegisteredVisualContainer::Iterator visualToRemoveIter;
1018 // Find visual with the same index in the removal container
1019 // Set if off stage as it's replacement is now ready.
1020 // Remove if from removal list as now removed from stage.
1021 // Set Pending flag on the ready visual to false as now ready.
1022 if(FindVisual((*registeredIter)->index, mRemoveVisuals, visualToRemoveIter))
1024 (*registeredIter)->pending = false;
1025 if(!((*visualToRemoveIter)->overideReadyTransition))
1027 Toolkit::GetImplementation((*visualToRemoveIter)->visual).SetOffScene(self);
1030 // Discard removed visual. It will be destroyed at next Idle time.
1031 DiscardVisual(visualToRemoveIter, mRemoveVisuals);
1034 // A visual is ready so control may need relayouting if staged
1035 RelayoutRequest(object);
1037 // Called by a Visual when it's resource is ready
1038 if(((*registeredIter)->enabled))
1044 void Control::Impl::NotifyVisualEvent(Visual::Base& object, Property::Index signalId)
1046 for(auto registeredIter = mVisuals.Begin(), end = mVisuals.End(); registeredIter != end; ++registeredIter)
1048 Internal::Visual::Base& registeredVisualImpl = Toolkit::GetImplementation((*registeredIter)->visual);
1049 if(&object == ®isteredVisualImpl)
1051 Dali::Toolkit::Control handle(mControlImpl.GetOwner());
1052 mVisualEventSignal.Emit(handle, (*registeredIter)->index, signalId);
1058 void Control::Impl::RelayoutRequest(Visual::Base& object)
1060 if(mControlImpl.Self().GetProperty<bool>(Actor::Property::CONNECTED_TO_SCENE))
1062 mControlImpl.RelayoutRequest();
1066 bool Control::Impl::IsResourceReady() const
1068 // Iterate through and check all the enabled visuals are ready
1069 for(auto visualIter = mVisuals.Begin();
1070 visualIter != mVisuals.End();
1073 const Toolkit::Visual::Base visual = (*visualIter)->visual;
1074 const Internal::Visual::Base& visualImpl = Toolkit::GetImplementation(visual);
1076 // one of the enabled visuals is not ready
1077 if(!visualImpl.IsResourceReady() && (*visualIter)->enabled)
1085 Toolkit::Visual::ResourceStatus Control::Impl::GetVisualResourceStatus(Property::Index index) const
1087 RegisteredVisualContainer::Iterator iter;
1088 if(FindVisual(index, mVisuals, iter))
1090 const Toolkit::Visual::Base visual = (*iter)->visual;
1091 const Internal::Visual::Base& visualImpl = Toolkit::GetImplementation(visual);
1092 return visualImpl.GetResourceStatus();
1095 return Toolkit::Visual::ResourceStatus::PREPARING;
1098 void Control::Impl::AddTransitions(Dali::Animation& animation,
1099 const Toolkit::TransitionData& handle,
1100 bool createAnimation)
1102 // Setup a Transition from TransitionData.
1103 const Internal::TransitionData& transitionData = Toolkit::GetImplementation(handle);
1104 TransitionData::Iterator end = transitionData.End();
1105 for(TransitionData::Iterator iter = transitionData.Begin();
1109 TransitionData::Animator* animator = (*iter);
1111 Toolkit::Visual::Base visual = GetVisualByName(mVisuals, animator->objectName);
1115 #if defined(DEBUG_ENABLED)
1116 Dali::TypeInfo typeInfo;
1117 ControlWrapper* controlWrapperImpl = dynamic_cast<ControlWrapper*>(&mControlImpl);
1118 if(controlWrapperImpl)
1120 typeInfo = controlWrapperImpl->GetTypeInfo();
1123 DALI_LOG_INFO(gLogFilter, Debug::Concise, "CreateTransition: Found %s visual for %s\n", visual.GetName().c_str(), typeInfo ? typeInfo.GetName().c_str() : "Unknown");
1125 Internal::Visual::Base& visualImpl = Toolkit::GetImplementation(visual);
1126 visualImpl.AnimateProperty(animation, *animator);
1130 DALI_LOG_INFO(gLogFilter, Debug::Concise, "CreateTransition: Could not find visual. Trying actors");
1131 // Otherwise, try any actor children of control (Including the control)
1132 Actor child = mControlImpl.Self().FindChildByName(animator->objectName);
1135 Property::Index propertyIndex = child.GetPropertyIndex(animator->propertyKey);
1136 if(propertyIndex != Property::INVALID_INDEX)
1138 if(animator->animate == false)
1140 if(animator->targetValue.GetType() != Property::NONE)
1142 child.SetProperty(propertyIndex, animator->targetValue);
1145 else // animate the property
1147 if(animator->initialValue.GetType() != Property::NONE)
1149 child.SetProperty(propertyIndex, animator->initialValue);
1152 if(createAnimation && !animation)
1154 animation = Dali::Animation::New(0.1f);
1157 animation.AnimateTo(Property(child, propertyIndex),
1158 animator->targetValue,
1159 animator->alphaFunction,
1160 TimePeriod(animator->timePeriodDelay,
1161 animator->timePeriodDuration));
1169 Dali::Animation Control::Impl::CreateTransition(const Toolkit::TransitionData& transitionData)
1171 Dali::Animation transition;
1173 if(transitionData.Count() > 0)
1175 AddTransitions(transition, transitionData, true);
1180 void Control::Impl::DoAction(Dali::Property::Index visualIndex, Dali::Property::Index actionId, const Dali::Property::Value attributes)
1182 RegisteredVisualContainer::Iterator iter;
1183 if(FindVisual(visualIndex, mVisuals, iter))
1185 Toolkit::GetImplementation((*iter)->visual).DoAction(actionId, attributes);
1189 void Control::Impl::DoActionExtension(Dali::Property::Index visualIndex, Dali::Property::Index actionId, Dali::Any attributes)
1191 RegisteredVisualContainer::Iterator iter;
1192 if(FindVisual(visualIndex, mVisuals, iter))
1194 Toolkit::GetImplementation((*iter)->visual).DoActionExtension(actionId, attributes);
1198 void Control::Impl::AppendAccessibilityAttribute(const std::string& key, const std::string value)
1200 Property::Value* checkedValue = mAccessibilityAttributes.Find(key);
1203 mAccessibilityAttributes[key] = Property::Value(value);
1207 mAccessibilityAttributes.Insert(key, value);
1211 void Control::Impl::SetProperty(BaseObject* object, Property::Index index, const Property::Value& value)
1213 DALI_ASSERT_ALWAYS(Stage::IsCoreThread() && "Core is not installed. Might call this API from worker thread?");
1215 Toolkit::Control control = Toolkit::Control::DownCast(BaseHandle(object));
1219 Control& controlImpl(GetImplementation(control));
1223 case Toolkit::Control::Property::STYLE_NAME:
1225 controlImpl.SetStyleName(value.Get<std::string>());
1229 case Toolkit::DevelControl::Property::STATE:
1231 bool withTransitions = true;
1232 const Property::Value* valuePtr = &value;
1233 const Property::Map* map = value.GetMap();
1236 Property::Value* value2 = map->Find("withTransitions");
1239 withTransitions = value2->Get<bool>();
1242 valuePtr = map->Find("state");
1247 Toolkit::DevelControl::State state(controlImpl.mImpl->mState);
1248 if(Scripting::GetEnumerationProperty<Toolkit::DevelControl::State>(*valuePtr, ControlStateTable, ControlStateTableCount, state))
1250 controlImpl.mImpl->SetState(state, withTransitions);
1256 case Toolkit::DevelControl::Property::SUB_STATE:
1258 std::string subState;
1259 if(value.Get(subState))
1261 controlImpl.mImpl->SetSubState(subState);
1266 case Toolkit::DevelControl::Property::LEFT_FOCUSABLE_ACTOR_ID:
1269 if(value.Get(focusId))
1271 controlImpl.mImpl->mLeftFocusableActorId = focusId;
1276 case Toolkit::DevelControl::Property::RIGHT_FOCUSABLE_ACTOR_ID:
1279 if(value.Get(focusId))
1281 controlImpl.mImpl->mRightFocusableActorId = focusId;
1286 case Toolkit::DevelControl::Property::UP_FOCUSABLE_ACTOR_ID:
1289 if(value.Get(focusId))
1291 controlImpl.mImpl->mUpFocusableActorId = focusId;
1296 case Toolkit::DevelControl::Property::DOWN_FOCUSABLE_ACTOR_ID:
1299 if(value.Get(focusId))
1301 controlImpl.mImpl->mDownFocusableActorId = focusId;
1306 case Toolkit::Control::Property::KEY_INPUT_FOCUS:
1308 if(value.Get<bool>())
1310 controlImpl.SetKeyInputFocus();
1314 controlImpl.ClearKeyInputFocus();
1319 case Toolkit::Control::Property::BACKGROUND:
1323 const Property::Map* map = value.GetMap();
1324 if(map && !map->Empty())
1326 controlImpl.SetBackground(*map);
1328 else if(value.Get(url))
1330 // don't know the size to load
1331 Toolkit::Visual::Base visual = Toolkit::VisualFactory::Get().CreateVisual(url, ImageDimensions());
1334 controlImpl.mImpl->RegisterVisual(Toolkit::Control::Property::BACKGROUND, visual, DepthIndex::BACKGROUND);
1337 else if(value.Get(color))
1339 controlImpl.SetBackgroundColor(color);
1343 // The background is an empty property map, so we should clear the background
1344 controlImpl.ClearBackground();
1349 case Toolkit::Control::Property::MARGIN:
1352 if(value.Get(margin))
1354 controlImpl.mImpl->SetMargin(margin);
1359 case Toolkit::Control::Property::PADDING:
1362 if(value.Get(padding))
1364 controlImpl.mImpl->SetPadding(padding);
1369 case Toolkit::DevelControl::Property::TOOLTIP:
1371 TooltipPtr& tooltipPtr = controlImpl.mImpl->mTooltip;
1374 tooltipPtr = Tooltip::New(control);
1376 tooltipPtr->SetProperties(value);
1380 case Toolkit::DevelControl::Property::SHADOW:
1382 const Property::Map* map = value.GetMap();
1383 if(map && !map->Empty())
1385 controlImpl.mImpl->SetShadow(*map);
1389 // The shadow is an empty property map, so we should clear the shadow
1390 controlImpl.mImpl->ClearShadow();
1395 case Toolkit::DevelControl::Property::ACCESSIBILITY_NAME:
1400 controlImpl.mImpl->mAccessibilityName = name;
1405 case Toolkit::DevelControl::Property::ACCESSIBILITY_DESCRIPTION:
1410 controlImpl.mImpl->mAccessibilityDescription = text;
1415 case Toolkit::DevelControl::Property::ACCESSIBILITY_TRANSLATION_DOMAIN:
1420 controlImpl.mImpl->mAccessibilityTranslationDomain = text;
1425 case Toolkit::DevelControl::Property::ACCESSIBILITY_ROLE:
1427 Dali::Accessibility::Role role;
1430 controlImpl.mImpl->mAccessibilityRole = role;
1435 case Toolkit::DevelControl::Property::ACCESSIBILITY_HIGHLIGHTABLE:
1438 if(value.Get(highlightable))
1440 controlImpl.mImpl->mAccessibilityHighlightable = highlightable;
1445 case Toolkit::DevelControl::Property::ACCESSIBILITY_ATTRIBUTES:
1447 const Property::Map* map = value.GetMap();
1448 if(map && !map->Empty())
1450 controlImpl.mImpl->mAccessibilityAttributes = *map;
1455 case Toolkit::DevelControl::Property::DISPATCH_KEY_EVENTS:
1458 if(value.Get(dispatch))
1460 controlImpl.mImpl->mDispatchKeyEvents = dispatch;
1465 case Toolkit::DevelControl::Property::ACCESSIBILITY_HIDDEN:
1468 if(value.Get(hidden))
1470 controlImpl.mImpl->mAccessibilityHidden = hidden;
1472 auto* accessible = controlImpl.GetAccessibleObject();
1473 if(DALI_LIKELY(accessible))
1475 auto* parent = dynamic_cast<Dali::Accessibility::ActorAccessible*>(accessible->GetParent());
1478 parent->OnChildrenChanged();
1484 case Toolkit::DevelControl::Property::CLOCKWISE_FOCUSABLE_ACTOR_ID:
1487 if(value.Get(focusId))
1489 controlImpl.mImpl->mClockwiseFocusableActorId = focusId;
1493 case Toolkit::DevelControl::Property::COUNTER_CLOCKWISE_FOCUSABLE_ACTOR_ID:
1496 if(value.Get(focusId))
1498 controlImpl.mImpl->mCounterClockwiseFocusableActorId = focusId;
1503 case Toolkit::DevelControl::Property::AUTOMATION_ID:
1505 std::string automationId;
1506 if(value.Get(automationId))
1508 controlImpl.mImpl->mAutomationId = automationId;
1516 Property::Value Control::Impl::GetProperty(BaseObject* object, Property::Index index)
1518 DALI_ASSERT_ALWAYS(Stage::IsCoreThread() && "Core is not installed. Might call this API from worker thread?");
1520 Property::Value value;
1522 Toolkit::Control control = Toolkit::Control::DownCast(BaseHandle(object));
1526 Control& controlImpl(GetImplementation(control));
1530 case Toolkit::Control::Property::STYLE_NAME:
1532 value = controlImpl.GetStyleName();
1536 case Toolkit::DevelControl::Property::STATE:
1538 value = controlImpl.mImpl->mState;
1542 case Toolkit::DevelControl::Property::SUB_STATE:
1544 value = controlImpl.mImpl->mSubStateName;
1548 case Toolkit::DevelControl::Property::LEFT_FOCUSABLE_ACTOR_ID:
1550 value = controlImpl.mImpl->mLeftFocusableActorId;
1554 case Toolkit::DevelControl::Property::RIGHT_FOCUSABLE_ACTOR_ID:
1556 value = controlImpl.mImpl->mRightFocusableActorId;
1560 case Toolkit::DevelControl::Property::UP_FOCUSABLE_ACTOR_ID:
1562 value = controlImpl.mImpl->mUpFocusableActorId;
1566 case Toolkit::DevelControl::Property::DOWN_FOCUSABLE_ACTOR_ID:
1568 value = controlImpl.mImpl->mDownFocusableActorId;
1572 case Toolkit::Control::Property::KEY_INPUT_FOCUS:
1574 value = controlImpl.HasKeyInputFocus();
1578 case Toolkit::Control::Property::BACKGROUND:
1581 Toolkit::Visual::Base visual = controlImpl.mImpl->GetVisual(Toolkit::Control::Property::BACKGROUND);
1584 visual.CreatePropertyMap(map);
1591 case Toolkit::Control::Property::MARGIN:
1593 value = controlImpl.mImpl->GetMargin();
1597 case Toolkit::Control::Property::PADDING:
1599 value = controlImpl.mImpl->GetPadding();
1603 case Toolkit::DevelControl::Property::TOOLTIP:
1606 if(controlImpl.mImpl->mTooltip)
1608 controlImpl.mImpl->mTooltip->CreatePropertyMap(map);
1614 case Toolkit::DevelControl::Property::SHADOW:
1617 Toolkit::Visual::Base visual = controlImpl.mImpl->GetVisual(Toolkit::DevelControl::Property::SHADOW);
1620 visual.CreatePropertyMap(map);
1627 case Toolkit::DevelControl::Property::ACCESSIBILITY_NAME:
1629 value = controlImpl.mImpl->mAccessibilityName;
1633 case Toolkit::DevelControl::Property::ACCESSIBILITY_DESCRIPTION:
1635 value = controlImpl.mImpl->mAccessibilityDescription;
1639 case Toolkit::DevelControl::Property::ACCESSIBILITY_TRANSLATION_DOMAIN:
1641 value = controlImpl.mImpl->mAccessibilityTranslationDomain;
1645 case Toolkit::DevelControl::Property::ACCESSIBILITY_ROLE:
1647 value = Property::Value(controlImpl.mImpl->mAccessibilityRole);
1651 case Toolkit::DevelControl::Property::ACCESSIBILITY_HIGHLIGHTABLE:
1653 value = controlImpl.mImpl->mAccessibilityHighlightable;
1657 case Toolkit::DevelControl::Property::ACCESSIBILITY_ATTRIBUTES:
1659 value = controlImpl.mImpl->mAccessibilityAttributes;
1663 case Toolkit::DevelControl::Property::DISPATCH_KEY_EVENTS:
1665 value = controlImpl.mImpl->mDispatchKeyEvents;
1669 case Toolkit::DevelControl::Property::ACCESSIBILITY_HIDDEN:
1671 value = controlImpl.mImpl->mAccessibilityHidden;
1675 case Toolkit::DevelControl::Property::CLOCKWISE_FOCUSABLE_ACTOR_ID:
1677 value = controlImpl.mImpl->mClockwiseFocusableActorId;
1681 case Toolkit::DevelControl::Property::COUNTER_CLOCKWISE_FOCUSABLE_ACTOR_ID:
1683 value = controlImpl.mImpl->mCounterClockwiseFocusableActorId;
1687 case Toolkit::DevelControl::Property::AUTOMATION_ID:
1689 value = controlImpl.mImpl->mAutomationId;
1698 void Control::Impl::RemoveAccessibilityAttribute(const std::string& key)
1700 Property::Value* value = mAccessibilityAttributes.Find(key);
1703 mAccessibilityAttributes[key] = Property::Value();
1707 void Control::Impl::ClearAccessibilityAttributes()
1709 mAccessibilityAttributes.Clear();
1712 void Control::Impl::SetAccessibilityReadingInfoType(const Dali::Accessibility::ReadingInfoTypes types)
1714 std::string value{};
1715 if(types[Dali::Accessibility::ReadingInfoType::NAME])
1717 value += READING_INFO_TYPE_NAME;
1719 if(types[Dali::Accessibility::ReadingInfoType::ROLE])
1723 value += READING_INFO_TYPE_SEPARATOR;
1725 value += READING_INFO_TYPE_ROLE;
1727 if(types[Dali::Accessibility::ReadingInfoType::DESCRIPTION])
1731 value += READING_INFO_TYPE_SEPARATOR;
1733 value += READING_INFO_TYPE_DESCRIPTION;
1735 if(types[Dali::Accessibility::ReadingInfoType::STATE])
1739 value += READING_INFO_TYPE_SEPARATOR;
1741 value += READING_INFO_TYPE_STATE;
1743 AppendAccessibilityAttribute(READING_INFO_TYPE_ATTRIBUTE_NAME, value);
1746 Dali::Accessibility::ReadingInfoTypes Control::Impl::GetAccessibilityReadingInfoType() const
1748 std::string value{};
1749 auto place = mAccessibilityAttributes.Find(READING_INFO_TYPE_ATTRIBUTE_NAME);
1756 Dali::Accessibility::ReadingInfoTypes types;
1757 types[Dali::Accessibility::ReadingInfoType::NAME] = true;
1758 types[Dali::Accessibility::ReadingInfoType::ROLE] = true;
1759 types[Dali::Accessibility::ReadingInfoType::DESCRIPTION] = true;
1760 types[Dali::Accessibility::ReadingInfoType::STATE] = true;
1769 Dali::Accessibility::ReadingInfoTypes types;
1771 if(value.find(READING_INFO_TYPE_NAME) != std::string::npos)
1773 types[Dali::Accessibility::ReadingInfoType::NAME] = true;
1775 if(value.find(READING_INFO_TYPE_ROLE) != std::string::npos)
1777 types[Dali::Accessibility::ReadingInfoType::ROLE] = true;
1779 if(value.find(READING_INFO_TYPE_DESCRIPTION) != std::string::npos)
1781 types[Dali::Accessibility::ReadingInfoType::DESCRIPTION] = true;
1783 if(value.find(READING_INFO_TYPE_STATE) != std::string::npos)
1785 types[Dali::Accessibility::ReadingInfoType::STATE] = true;
1791 void Control::Impl::CopyInstancedProperties(RegisteredVisualContainer& visuals, Dictionary<Property::Map>& instancedProperties)
1793 for(RegisteredVisualContainer::Iterator iter = visuals.Begin(); iter != visuals.End(); iter++)
1797 Property::Map instanceMap;
1798 Toolkit::GetImplementation((*iter)->visual).CreateInstancePropertyMap(instanceMap);
1799 instancedProperties.Add((*iter)->visual.GetName(), instanceMap);
1804 void Control::Impl::RemoveVisual(RegisteredVisualContainer& visuals, const std::string& visualName)
1806 Actor self(mControlImpl.Self());
1808 for(RegisteredVisualContainer::Iterator visualIter = visuals.Begin();
1809 visualIter != visuals.End();
1812 Toolkit::Visual::Base visual = (*visualIter)->visual;
1813 if(visual && visual.GetName() == visualName)
1815 Toolkit::GetImplementation(visual).SetOffScene(self);
1816 (*visualIter)->visual.Reset();
1817 visuals.Erase(visualIter);
1823 void Control::Impl::RemoveVisuals(RegisteredVisualContainer& visuals, DictionaryKeys& removeVisuals)
1825 Actor self(mControlImpl.Self());
1826 for(DictionaryKeys::iterator iter = removeVisuals.begin(); iter != removeVisuals.end(); ++iter)
1828 const std::string visualName = *iter;
1829 RemoveVisual(visuals, visualName);
1833 void Control::Impl::RecreateChangedVisuals(Dictionary<Property::Map>& stateVisualsToChange,
1834 Dictionary<Property::Map>& instancedProperties)
1836 Dali::CustomActor handle(mControlImpl.GetOwner());
1837 for(Dictionary<Property::Map>::iterator iter = stateVisualsToChange.Begin();
1838 iter != stateVisualsToChange.End();
1841 const std::string& visualName = (*iter).key;
1842 const Property::Map& toMap = (*iter).entry;
1844 Actor self = mControlImpl.Self();
1845 RegisteredVisualContainer::Iterator registeredVisualsiter;
1846 // Check if visual (visualName) is already registered, this is the current visual.
1847 if(FindVisual(visualName, mVisuals, registeredVisualsiter))
1849 Toolkit::Visual::Base& visual = (*registeredVisualsiter)->visual;
1852 // No longer required to know if the replaced visual's resources are ready
1853 StopObservingVisual(visual);
1855 // If control staged then visuals will be swapped once ready
1856 if(self.GetProperty<bool>(Actor::Property::CONNECTED_TO_SCENE))
1858 // Check if visual is currently in the process of being replaced ( is in removal container )
1859 RegisteredVisualContainer::Iterator visualQueuedForRemoval;
1860 if(FindVisual(visualName, mRemoveVisuals, visualQueuedForRemoval))
1862 // Visual with same visual name is already in removal container so current visual pending
1863 // Only the the last requested visual will be displayed so remove current visual which is staged but not ready.
1864 Toolkit::GetImplementation(visual).SetOffScene(self);
1865 (*registeredVisualsiter)->visual.Reset();
1866 mVisuals.Erase(registeredVisualsiter);
1870 // current visual not already in removal container so add now.
1871 DALI_LOG_INFO(gLogFilter, Debug::Verbose, "RegisterVisual Move current registered visual to removal Queue: %s \n", visualName.c_str());
1872 MoveVisual(registeredVisualsiter, mVisuals, mRemoveVisuals);
1877 // Control not staged or visual disabled so can just erase from registered visuals and new visual will be added later.
1878 (*registeredVisualsiter)->visual.Reset();
1879 mVisuals.Erase(registeredVisualsiter);
1883 const Property::Map* instancedMap = instancedProperties.FindConst(visualName);
1884 Style::ApplyVisual(handle, visualName, toMap, instancedMap);
1889 void Control::Impl::ReplaceStateVisualsAndProperties(const StylePtr oldState, const StylePtr newState, const std::string& subState)
1891 DALI_ASSERT_ALWAYS(Stage::IsCoreThread() && "Core is not installed. Might call this API from worker thread?");
1893 // Collect all old visual names
1894 DictionaryKeys stateVisualsToRemove;
1897 oldState->visuals.GetKeys(stateVisualsToRemove);
1898 if(!subState.empty())
1900 const StylePtr* oldSubState = oldState->subStates.FindConst(subState);
1903 DictionaryKeys subStateVisualsToRemove;
1904 (*oldSubState)->visuals.GetKeys(subStateVisualsToRemove);
1905 Merge(stateVisualsToRemove, subStateVisualsToRemove);
1910 // Collect all new visual properties
1911 Dictionary<Property::Map> stateVisualsToAdd;
1914 stateVisualsToAdd = newState->visuals;
1915 if(!subState.empty())
1917 const StylePtr* newSubState = newState->subStates.FindConst(subState);
1920 stateVisualsToAdd.Merge((*newSubState)->visuals);
1925 // If a name is in both add/remove, move it to change list.
1926 Dictionary<Property::Map> stateVisualsToChange;
1927 FindChangableVisuals(stateVisualsToAdd, stateVisualsToChange, stateVisualsToRemove);
1929 // Copy instanced properties (e.g. text label) of current visuals
1930 Dictionary<Property::Map> instancedProperties;
1931 CopyInstancedProperties(mVisuals, instancedProperties);
1933 // For each visual in remove list, remove from mVisuals
1934 RemoveVisuals(mVisuals, stateVisualsToRemove);
1936 // For each visual in add list, create and add to mVisuals
1937 Dali::CustomActor handle(mControlImpl.GetOwner());
1938 Style::ApplyVisuals(handle, stateVisualsToAdd, instancedProperties);
1940 // For each visual in change list, if it requires a new visual,
1941 // remove old visual, create and add to mVisuals
1942 RecreateChangedVisuals(stateVisualsToChange, instancedProperties);
1945 void Control::Impl::SetState(DevelControl::State newState, bool withTransitions)
1947 DevelControl::State oldState = mState;
1948 Dali::CustomActor handle(mControlImpl.GetOwner());
1949 DALI_LOG_INFO(gLogFilter, Debug::Concise, "Control::Impl::SetState: %s\n", (mState == DevelControl::NORMAL ? "NORMAL" : (mState == DevelControl::FOCUSED ? "FOCUSED" : (mState == DevelControl::DISABLED ? "DISABLED" : "NONE"))));
1951 if(mState != newState)
1953 // If mState was Disabled, and new state is Focused, should probably
1954 // store that fact, e.g. in another property that FocusManager can access.
1957 // Trigger state change and transitions
1958 // Apply new style, if stylemanager is available
1959 Toolkit::StyleManager styleManager = Toolkit::StyleManager::Get();
1962 const StylePtr stylePtr = GetImpl(styleManager).GetRecordedStyle(Toolkit::Control(mControlImpl.GetOwner()));
1966 std::string oldStateName = Scripting::GetEnumerationName<Toolkit::DevelControl::State>(oldState, ControlStateTable, ControlStateTableCount);
1967 std::string newStateName = Scripting::GetEnumerationName<Toolkit::DevelControl::State>(newState, ControlStateTable, ControlStateTableCount);
1969 const StylePtr* newStateStyle = stylePtr->subStates.Find(newStateName);
1970 const StylePtr* oldStateStyle = stylePtr->subStates.Find(oldStateName);
1971 if(oldStateStyle && newStateStyle)
1973 // Only change if both state styles exist
1974 ReplaceStateVisualsAndProperties(*oldStateStyle, *newStateStyle, mSubStateName);
1981 void Control::Impl::SetSubState(const std::string& subStateName, bool withTransitions)
1983 if(mSubStateName != subStateName)
1985 // Get existing sub-state visuals, and unregister them
1986 Dali::CustomActor handle(mControlImpl.GetOwner());
1988 Toolkit::StyleManager styleManager = Toolkit::StyleManager::Get();
1991 const StylePtr stylePtr = GetImpl(styleManager).GetRecordedStyle(Toolkit::Control(mControlImpl.GetOwner()));
1995 std::string stateName = Scripting::GetEnumerationName<Toolkit::DevelControl::State>(mState, ControlStateTable, ControlStateTableCount);
1997 const StylePtr* state = stylePtr->subStates.Find(stateName);
2000 StylePtr stateStyle(*state);
2002 const StylePtr* newStateStyle = stateStyle->subStates.Find(subStateName);
2003 const StylePtr* oldStateStyle = stateStyle->subStates.Find(mSubStateName);
2004 if(oldStateStyle && newStateStyle)
2007 ReplaceStateVisualsAndProperties(*oldStateStyle, *newStateStyle, empty);
2013 mSubStateName = subStateName;
2017 void Control::Impl::OnSceneDisconnection()
2019 Actor self = mControlImpl.Self();
2021 // Any visuals set for replacement but not yet ready should still be registered.
2022 // Reason: If a request was made to register a new visual but the control removed from scene before visual was ready
2023 // then when this control appears back on stage it should use that new visual.
2025 // Iterate through all registered visuals and set off scene
2026 SetVisualsOffScene(mVisuals, self);
2028 // Visuals pending replacement can now be taken out of the removal list and set off scene
2029 // Iterate through all replacement visuals and add to a move queue then set off scene
2031 if(!mRemoveVisuals.Empty())
2033 std::reverse(mRemoveVisuals.Begin(), mRemoveVisuals.End());
2035 while(!mRemoveVisuals.Empty())
2037 auto removalIter = mRemoveVisuals.End() - 1u;
2038 Toolkit::GetImplementation((*removalIter)->visual).SetOffScene(self);
2040 // Discard removed visual. It will be destroyed at next Idle time.
2041 DiscardVisual(removalIter, mRemoveVisuals);
2045 for(auto replacedIter = mVisuals.Begin(), end = mVisuals.End(); replacedIter != end; replacedIter++)
2047 (*replacedIter)->pending = false;
2051 void Control::Impl::SetMargin(Extents margin)
2053 mControlImpl.mImpl->mMargin = margin;
2055 // Trigger a size negotiation request that may be needed when setting a margin.
2056 mControlImpl.RelayoutRequest();
2059 Extents Control::Impl::GetMargin() const
2061 return mControlImpl.mImpl->mMargin;
2064 void Control::Impl::SetPadding(Extents padding)
2066 mControlImpl.mImpl->mPadding = padding;
2068 // Trigger a size negotiation request that may be needed when setting a padding.
2069 mControlImpl.RelayoutRequest();
2072 Extents Control::Impl::GetPadding() const
2074 return mControlImpl.mImpl->mPadding;
2077 void Control::Impl::SetInputMethodContext(InputMethodContext& inputMethodContext)
2079 mInputMethodContext = inputMethodContext;
2082 bool Control::Impl::FilterKeyEvent(const KeyEvent& event)
2084 bool consumed(false);
2086 if(mInputMethodContext)
2088 consumed = mInputMethodContext.FilterEventKey(event);
2093 DevelControl::VisualEventSignalType& Control::Impl::VisualEventSignal()
2095 return mVisualEventSignal;
2098 void Control::Impl::SetShadow(const Property::Map& map)
2100 Toolkit::Visual::Base visual = Toolkit::VisualFactory::Get().CreateVisual(map);
2101 visual.SetName("shadow");
2105 mControlImpl.mImpl->RegisterVisual(Toolkit::DevelControl::Property::SHADOW, visual, DepthIndex::BACKGROUND_EFFECT);
2107 mControlImpl.RelayoutRequest();
2111 void Control::Impl::ClearShadow()
2113 mControlImpl.mImpl->UnregisterVisual(Toolkit::DevelControl::Property::SHADOW);
2115 // Trigger a size negotiation request that may be needed when unregistering a visual.
2116 mControlImpl.RelayoutRequest();
2119 Dali::Property Control::Impl::GetVisualProperty(Dali::Property::Index index, Dali::Property::Key visualPropertyKey)
2121 Toolkit::Visual::Base visual = GetVisualByIndex(mVisuals, index);
2124 Internal::Visual::Base& visualImpl = Toolkit::GetImplementation(visual);
2125 return visualImpl.GetPropertyObject(std::move(visualPropertyKey));
2129 return Dali::Property(handle, Property::INVALID_INDEX);
2132 void Control::Impl::CreateTransitions(std::vector<std::pair<Dali::Property::Index, Dali::Property::Map>>& sourceProperties,
2133 std::vector<std::pair<Dali::Property::Index, Dali::Property::Map>>& destinationProperties,
2134 Dali::Toolkit::Control source,
2135 Dali::Toolkit::Control destination)
2137 // Retrieves background properties to be transitioned.
2138 Dali::Property::Map backgroundSourcePropertyMap, backgroundDestinationPropertyMap;
2139 mControlImpl.MakeVisualTransition(backgroundSourcePropertyMap, backgroundDestinationPropertyMap, source, destination, Toolkit::Control::Property::BACKGROUND);
2140 if(backgroundSourcePropertyMap.Count() > 0)
2142 sourceProperties.push_back(std::pair<Dali::Property::Index, Dali::Property::Map>(Toolkit::Control::Property::BACKGROUND, backgroundSourcePropertyMap));
2143 destinationProperties.push_back(std::pair<Dali::Property::Index, Dali::Property::Map>(Toolkit::Control::Property::BACKGROUND, backgroundDestinationPropertyMap));
2146 // Retrieves shadow properties to be transitioned.
2147 Dali::Property::Map shadowSourcePropertyMap, shadowDestinationPropertyMap;
2148 mControlImpl.MakeVisualTransition(shadowSourcePropertyMap, shadowDestinationPropertyMap, source, destination, Toolkit::DevelControl::Property::SHADOW);
2149 if(shadowSourcePropertyMap.Count() > 0)
2151 sourceProperties.push_back(std::pair<Dali::Property::Index, Dali::Property::Map>(Toolkit::DevelControl::Property::SHADOW, shadowSourcePropertyMap));
2152 destinationProperties.push_back(std::pair<Dali::Property::Index, Dali::Property::Map>(Toolkit::DevelControl::Property::SHADOW, shadowDestinationPropertyMap));
2155 // Retrieves transition from inherited class.
2156 mControlImpl.OnCreateTransitions(sourceProperties, destinationProperties, source, destination);
2159 void Control::Impl::UpdateVisualProperties(const std::vector<std::pair<Dali::Property::Index, Dali::Property::Map>>& properties)
2161 for(auto&& data : properties)
2163 if(data.first == Toolkit::Control::Property::BACKGROUND)
2165 DoAction(Toolkit::Control::Property::BACKGROUND, DevelVisual::Action::UPDATE_PROPERTY, data.second);
2167 else if(data.first == Toolkit::DevelControl::Property::SHADOW)
2169 DoAction(Toolkit::DevelControl::Property::SHADOW, DevelVisual::Action::UPDATE_PROPERTY, data.second);
2172 mControlImpl.OnUpdateVisualProperties(properties);
2175 void Control::Impl::EmitResourceReadySignal()
2177 if(!mIsEmittingResourceReadySignal)
2179 // Guard against calls to emit the signal during the callback
2180 mIsEmittingResourceReadySignal = true;
2182 // If the signal handler changes visual, it may become ready during this call & therefore this method will
2183 // get called again recursively. If so, mIdleCallbackRegistered is set below, and we act on it after that secondary
2184 // invocation has completed by notifying in an Idle callback to prevent further recursion.
2185 Dali::Toolkit::Control handle(mControlImpl.GetOwner());
2186 mResourceReadySignal.Emit(handle);
2188 mIsEmittingResourceReadySignal = false;
2192 if(!mIdleCallbackRegistered)
2194 mIdleCallbackRegistered = true;
2196 // Add idler to emit the signal again
2199 // The callback manager takes the ownership of the callback object.
2200 mIdleCallback = MakeCallback(this, &Control::Impl::OnIdleCallback);
2201 Adaptor::Get().AddIdle(mIdleCallback, true);
2207 bool Control::Impl::OnIdleCallback()
2210 mIdleCallbackRegistered = false;
2212 // A visual is ready so control may need relayouting if staged
2213 if(mControlImpl.Self().GetProperty<bool>(Actor::Property::CONNECTED_TO_SCENE))
2215 mControlImpl.RelayoutRequest();
2218 EmitResourceReadySignal();
2220 if(!mIdleCallbackRegistered)
2222 // Set the pointer to null as the callback manager deletes the callback after execute it.
2223 mIdleCallback = nullptr;
2226 // Repeat idle if mIdleCallbackRegistered become true one more time.
2227 return mIdleCallbackRegistered;
2230 Toolkit::DevelControl::ControlAccessible* Control::Impl::GetAccessibleObject()
2232 if(mAccessibleCreatable && !mAccessibleObject)
2234 mAccessibleObject.reset(mControlImpl.CreateAccessibleObject());
2237 return mAccessibleObject.get();
2240 bool Control::Impl::IsAccessibleCreated() const
2242 return !!mAccessibleObject;
2245 void Control::Impl::EnableCreateAccessible(bool enable)
2247 mAccessibleCreatable = enable;
2250 bool Control::Impl::IsCreateAccessibleEnabled() const
2252 return mAccessibleCreatable;
2255 } // namespace Internal
2257 } // namespace Toolkit