2 * Copyright (c) 2021 Samsung Electronics Co., Ltd.
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
8 * http://www.apache.org/licenses/LICENSE-2.0
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
19 #include "control-data-impl.h"
22 #include <dali-toolkit/public-api/controls/control-impl.h>
23 #include <dali-toolkit/public-api/controls/control.h>
24 #include <dali-toolkit/public-api/dali-toolkit-common.h>
25 #include <dali/devel-api/actors/actor-devel.h>
26 #include <dali/devel-api/adaptor-framework/accessibility.h>
27 #include <dali/devel-api/common/stage.h>
28 #include <dali/devel-api/object/handle-devel.h>
29 #include <dali/devel-api/scripting/enum-helper.h>
30 #include <dali/devel-api/scripting/scripting.h>
31 #include <dali/integration-api/adaptor-framework/adaptor.h>
32 #include <dali/integration-api/debug.h>
33 #include <dali/public-api/object/object-registry.h>
34 #include <dali/public-api/object/type-registry-helper.h>
39 #include <dali-toolkit/devel-api/asset-manager/asset-manager.h>
40 #include <dali-toolkit/devel-api/controls/control-depth-index-ranges.h>
41 #include <dali-toolkit/devel-api/controls/control-devel.h>
42 #include <dali-toolkit/devel-api/controls/control-wrapper-impl.h>
43 #include <dali-toolkit/internal/styling/style-manager-impl.h>
44 #include <dali-toolkit/internal/visuals/visual-base-impl.h>
45 #include <dali-toolkit/internal/visuals/visual-string-constants.h>
46 #include <dali-toolkit/public-api/controls/image-view/image-view.h>
47 #include <dali-toolkit/public-api/focus-manager/keyboard-focus-manager.h>
48 #include <dali-toolkit/public-api/visuals/image-visual-properties.h>
49 #include <dali-toolkit/public-api/visuals/visual-properties.h>
53 const std::string READING_INFO_TYPE_NAME = "name";
54 const std::string READING_INFO_TYPE_ROLE = "role";
55 const std::string READING_INFO_TYPE_DESCRIPTION = "description";
56 const std::string READING_INFO_TYPE_STATE = "state";
57 const std::string READING_INFO_TYPE_ATTRIBUTE_NAME = "reading_info_type";
58 const std::string READING_INFO_TYPE_SEPARATOR = "|";
67 extern const Dali::Scripting::StringEnum ControlStateTable[];
68 extern const unsigned int ControlStateTableCount;
70 // Not static or anonymous - shared with other translation units
71 const Scripting::StringEnum ControlStateTable[] = {
72 {"NORMAL", Toolkit::DevelControl::NORMAL},
73 {"FOCUSED", Toolkit::DevelControl::FOCUSED},
74 {"DISABLED", Toolkit::DevelControl::DISABLED},
76 const unsigned int ControlStateTableCount = sizeof(ControlStateTable) / sizeof(ControlStateTable[0]);
80 #if defined(DEBUG_ENABLED)
81 Debug::Filter* gLogFilter = Debug::Filter::New(Debug::NoLogging, false, "LOG_CONTROL_VISUALS");
85 void Remove(Dictionary<T>& keyValues, const std::string& name)
87 keyValues.Remove(name);
90 void Remove(DictionaryKeys& keys, const std::string& name)
92 DictionaryKeys::iterator iter = std::find(keys.begin(), keys.end(), name);
93 if(iter != keys.end())
100 * Finds visual in given array, returning true if found along with the iterator for that visual as a out parameter
102 bool FindVisual(Property::Index targetIndex, const RegisteredVisualContainer& visuals, RegisteredVisualContainer::Iterator& iter)
104 for(iter = visuals.Begin(); iter != visuals.End(); iter++)
106 if((*iter)->index == targetIndex)
115 * Finds visual in given array, returning true if found along with the iterator for that visual as a out parameter
117 bool FindVisual(std::string visualName, const RegisteredVisualContainer& visuals, RegisteredVisualContainer::Iterator& iter)
119 for(iter = visuals.Begin(); iter != visuals.End(); iter++)
121 Toolkit::Visual::Base visual = (*iter)->visual;
122 if(visual && visual.GetName() == visualName)
130 void FindChangableVisuals(Dictionary<Property::Map>& stateVisualsToAdd,
131 Dictionary<Property::Map>& stateVisualsToChange,
132 DictionaryKeys& stateVisualsToRemove)
134 DictionaryKeys copyOfStateVisualsToRemove = stateVisualsToRemove;
136 for(DictionaryKeys::iterator iter = copyOfStateVisualsToRemove.begin();
137 iter != copyOfStateVisualsToRemove.end();
140 const std::string& visualName = (*iter);
141 Property::Map* toMap = stateVisualsToAdd.Find(visualName);
144 stateVisualsToChange.Add(visualName, *toMap);
145 stateVisualsToAdd.Remove(visualName);
146 Remove(stateVisualsToRemove, visualName);
151 Toolkit::Visual::Base GetVisualByName(
152 const RegisteredVisualContainer& visuals,
153 const std::string& visualName)
155 Toolkit::Visual::Base visualHandle;
157 RegisteredVisualContainer::Iterator iter;
158 for(iter = visuals.Begin(); iter != visuals.End(); iter++)
160 Toolkit::Visual::Base visual = (*iter)->visual;
161 if(visual && visual.GetName() == visualName)
163 visualHandle = visual;
170 Toolkit::Visual::Base GetVisualByIndex(
171 const RegisteredVisualContainer& visuals,
172 Property::Index index)
174 Toolkit::Visual::Base visualHandle;
176 RegisteredVisualContainer::Iterator iter;
177 for(iter = visuals.Begin(); iter != visuals.End(); iter++)
179 if((*iter)->index == index)
181 visualHandle = (*iter)->visual;
189 * Move visual from source to destination container
191 void MoveVisual(RegisteredVisualContainer::Iterator sourceIter, RegisteredVisualContainer& source, RegisteredVisualContainer& destination)
193 Toolkit::Visual::Base visual = (*sourceIter)->visual;
196 RegisteredVisual* rv = source.Release(sourceIter);
197 destination.PushBack(rv);
202 * Performs actions as requested using the action name.
203 * @param[in] object The object on which to perform the action.
204 * @param[in] actionName The action to perform.
205 * @param[in] attributes The attributes with which to perfrom this action.
206 * @return true if action has been accepted by this control
208 const char* ACTION_ACCESSIBILITY_ACTIVATED = "accessibilityActivated";
209 const char* ACTION_ACCESSIBILITY_READING_CANCELLED = "ReadingCancelled";
210 const char* ACTION_ACCESSIBILITY_READING_PAUSED = "ReadingPaused";
211 const char* ACTION_ACCESSIBILITY_READING_RESUMED = "ReadingResumed";
212 const char* ACTION_ACCESSIBILITY_READING_SKIPPED = "ReadingSkipped";
213 const char* ACTION_ACCESSIBILITY_READING_STOPPED = "ReadingStopped";
215 static bool DoAction(BaseObject* object, const std::string& actionName, const Property::Map& attributes)
219 Dali::BaseHandle handle(object);
221 Toolkit::Control control = Toolkit::Control::DownCast(handle);
223 DALI_ASSERT_ALWAYS(control);
225 if(0 == strcmp(actionName.c_str(), ACTION_ACCESSIBILITY_ACTIVATED) ||
226 actionName == "activate")
228 // if cast succeeds there is an implementation so no need to check
229 if(!DevelControl::AccessibilityActivateSignal(control).Empty())
230 DevelControl::AccessibilityActivateSignal(control).Emit();
232 ret = Internal::GetImplementation(control).OnAccessibilityActivated();
234 else if(0 == strcmp(actionName.c_str(), ACTION_ACCESSIBILITY_READING_SKIPPED))
236 // if cast succeeds there is an implementation so no need to check
237 if(!DevelControl::AccessibilityReadingSkippedSignal(control).Empty())
238 DevelControl::AccessibilityReadingSkippedSignal(control).Emit();
240 else if(0 == strcmp(actionName.c_str(), ACTION_ACCESSIBILITY_READING_PAUSED))
242 // if cast succeeds there is an implementation so no need to check
243 if(!DevelControl::AccessibilityReadingPausedSignal(control).Empty())
244 DevelControl::AccessibilityReadingPausedSignal(control).Emit();
246 else if(0 == strcmp(actionName.c_str(), ACTION_ACCESSIBILITY_READING_RESUMED))
248 // if cast succeeds there is an implementation so no need to check
249 if(!DevelControl::AccessibilityReadingResumedSignal(control).Empty())
250 DevelControl::AccessibilityReadingResumedSignal(control).Emit();
252 else if(0 == strcmp(actionName.c_str(), ACTION_ACCESSIBILITY_READING_CANCELLED))
254 // if cast succeeds there is an implementation so no need to check
255 if(!DevelControl::AccessibilityReadingCancelledSignal(control).Empty())
256 DevelControl::AccessibilityReadingCancelledSignal(control).Emit();
258 else if(0 == strcmp(actionName.c_str(), ACTION_ACCESSIBILITY_READING_STOPPED))
260 // if cast succeeds there is an implementation so no need to check
261 if(!DevelControl::AccessibilityReadingStoppedSignal(control).Empty())
262 DevelControl::AccessibilityReadingStoppedSignal(control).Emit();
272 * Connects a callback function with the object's signals.
273 * @param[in] object The object providing the signal.
274 * @param[in] tracker Used to disconnect the signal.
275 * @param[in] signalName The signal to connect to.
276 * @param[in] functor A newly allocated FunctorDelegate.
277 * @return True if the signal was connected.
278 * @post If a signal was connected, ownership of functor was passed to CallbackBase. Otherwise the caller is responsible for deleting the unused functor.
280 const char* SIGNAL_KEY_EVENT = "keyEvent";
281 const char* SIGNAL_KEY_INPUT_FOCUS_GAINED = "keyInputFocusGained";
282 const char* SIGNAL_KEY_INPUT_FOCUS_LOST = "keyInputFocusLost";
283 const char* SIGNAL_TAPPED = "tapped";
284 const char* SIGNAL_PANNED = "panned";
285 const char* SIGNAL_PINCHED = "pinched";
286 const char* SIGNAL_LONG_PRESSED = "longPressed";
287 const char* SIGNAL_GET_NAME = "getName";
288 const char* SIGNAL_GET_DESCRIPTION = "getDescription";
289 const char* SIGNAL_DO_GESTURE = "doGesture";
290 static bool DoConnectSignal(BaseObject* object, ConnectionTrackerInterface* tracker, const std::string& signalName, FunctorDelegate* functor)
292 Dali::BaseHandle handle(object);
294 bool connected(false);
295 Toolkit::Control control = Toolkit::Control::DownCast(handle);
298 Internal::Control& controlImpl(Internal::GetImplementation(control));
301 if(0 == strcmp(signalName.c_str(), SIGNAL_KEY_EVENT))
303 controlImpl.KeyEventSignal().Connect(tracker, functor);
305 else if(0 == strcmp(signalName.c_str(), SIGNAL_KEY_INPUT_FOCUS_GAINED))
307 controlImpl.KeyInputFocusGainedSignal().Connect(tracker, functor);
309 else if(0 == strcmp(signalName.c_str(), SIGNAL_KEY_INPUT_FOCUS_LOST))
311 controlImpl.KeyInputFocusLostSignal().Connect(tracker, functor);
313 else if(0 == strcmp(signalName.c_str(), SIGNAL_TAPPED))
315 controlImpl.EnableGestureDetection(GestureType::TAP);
316 controlImpl.GetTapGestureDetector().DetectedSignal().Connect(tracker, functor);
318 else if(0 == strcmp(signalName.c_str(), SIGNAL_PANNED))
320 controlImpl.EnableGestureDetection(GestureType::PAN);
321 controlImpl.GetPanGestureDetector().DetectedSignal().Connect(tracker, functor);
323 else if(0 == strcmp(signalName.c_str(), SIGNAL_PINCHED))
325 controlImpl.EnableGestureDetection(GestureType::PINCH);
326 controlImpl.GetPinchGestureDetector().DetectedSignal().Connect(tracker, functor);
328 else if(0 == strcmp(signalName.c_str(), SIGNAL_LONG_PRESSED))
330 controlImpl.EnableGestureDetection(GestureType::LONG_PRESS);
331 controlImpl.GetLongPressGestureDetector().DetectedSignal().Connect(tracker, functor);
333 else if(0 == strcmp(signalName.c_str(), SIGNAL_GET_NAME))
335 DevelControl::AccessibilityGetNameSignal(control).Connect(tracker, functor);
337 else if(0 == strcmp(signalName.c_str(), SIGNAL_GET_DESCRIPTION))
339 DevelControl::AccessibilityGetDescriptionSignal(control).Connect(tracker, functor);
341 else if(0 == strcmp(signalName.c_str(), SIGNAL_DO_GESTURE))
343 DevelControl::AccessibilityDoGestureSignal(control).Connect(tracker, functor);
350 * Creates control through type registry
354 return Internal::Control::New();
356 // Setup signals and actions using the type-registry.
357 DALI_TYPE_REGISTRATION_BEGIN(Control, CustomActor, Create);
359 // Note: Properties are registered separately below.
361 SignalConnectorType registerSignal1(typeRegistration, SIGNAL_KEY_EVENT, &DoConnectSignal);
362 SignalConnectorType registerSignal2(typeRegistration, SIGNAL_KEY_INPUT_FOCUS_GAINED, &DoConnectSignal);
363 SignalConnectorType registerSignal3(typeRegistration, SIGNAL_KEY_INPUT_FOCUS_LOST, &DoConnectSignal);
364 SignalConnectorType registerSignal4(typeRegistration, SIGNAL_TAPPED, &DoConnectSignal);
365 SignalConnectorType registerSignal5(typeRegistration, SIGNAL_PANNED, &DoConnectSignal);
366 SignalConnectorType registerSignal6(typeRegistration, SIGNAL_PINCHED, &DoConnectSignal);
367 SignalConnectorType registerSignal7(typeRegistration, SIGNAL_LONG_PRESSED, &DoConnectSignal);
368 SignalConnectorType registerSignal8(typeRegistration, SIGNAL_GET_NAME, &DoConnectSignal);
369 SignalConnectorType registerSignal9(typeRegistration, SIGNAL_GET_DESCRIPTION, &DoConnectSignal);
370 SignalConnectorType registerSignal10(typeRegistration, SIGNAL_DO_GESTURE, &DoConnectSignal);
372 TypeAction registerAction1(typeRegistration, "activate", &DoAction);
373 TypeAction registerAction2(typeRegistration, ACTION_ACCESSIBILITY_ACTIVATED, &DoAction);
374 TypeAction registerAction3(typeRegistration, ACTION_ACCESSIBILITY_READING_SKIPPED, &DoAction);
375 TypeAction registerAction4(typeRegistration, ACTION_ACCESSIBILITY_READING_CANCELLED, &DoAction);
376 TypeAction registerAction5(typeRegistration, ACTION_ACCESSIBILITY_READING_STOPPED, &DoAction);
377 TypeAction registerAction6(typeRegistration, ACTION_ACCESSIBILITY_READING_PAUSED, &DoAction);
378 TypeAction registerAction7(typeRegistration, ACTION_ACCESSIBILITY_READING_RESUMED, &DoAction);
380 DALI_TYPE_REGISTRATION_END()
383 * @brief Iterate through given container and setOffScene any visual found
385 * @param[in] container Container of visuals
386 * @param[in] parent Parent actor to remove visuals from
388 void SetVisualsOffScene(const RegisteredVisualContainer& container, Actor parent)
390 for(auto iter = container.Begin(), end = container.End(); iter != end; iter++)
394 DALI_LOG_INFO(gLogFilter, Debug::Verbose, "Control::SetOffScene Setting visual(%d) off stage\n", (*iter)->index);
395 Toolkit::GetImplementation((*iter)->visual).SetOffScene(parent);
400 } // unnamed namespace
403 // Properties registered without macro to use specific member variables.
404 const PropertyRegistration Control::Impl::PROPERTY_1(typeRegistration, "styleName", Toolkit::Control::Property::STYLE_NAME, Property::STRING, &Control::Impl::SetProperty, &Control::Impl::GetProperty);
405 const PropertyRegistration Control::Impl::PROPERTY_4(typeRegistration, "keyInputFocus", Toolkit::Control::Property::KEY_INPUT_FOCUS, Property::BOOLEAN, &Control::Impl::SetProperty, &Control::Impl::GetProperty);
406 const PropertyRegistration Control::Impl::PROPERTY_5(typeRegistration, "background", Toolkit::Control::Property::BACKGROUND, Property::MAP, &Control::Impl::SetProperty, &Control::Impl::GetProperty);
407 const PropertyRegistration Control::Impl::PROPERTY_6(typeRegistration, "margin", Toolkit::Control::Property::MARGIN, Property::EXTENTS, &Control::Impl::SetProperty, &Control::Impl::GetProperty);
408 const PropertyRegistration Control::Impl::PROPERTY_7(typeRegistration, "padding", Toolkit::Control::Property::PADDING, Property::EXTENTS, &Control::Impl::SetProperty, &Control::Impl::GetProperty);
409 const PropertyRegistration Control::Impl::PROPERTY_8(typeRegistration, "tooltip", Toolkit::DevelControl::Property::TOOLTIP, Property::MAP, &Control::Impl::SetProperty, &Control::Impl::GetProperty);
410 const PropertyRegistration Control::Impl::PROPERTY_9(typeRegistration, "state", Toolkit::DevelControl::Property::STATE, Property::STRING, &Control::Impl::SetProperty, &Control::Impl::GetProperty);
411 const PropertyRegistration Control::Impl::PROPERTY_10(typeRegistration, "subState", Toolkit::DevelControl::Property::SUB_STATE, Property::STRING, &Control::Impl::SetProperty, &Control::Impl::GetProperty);
412 const PropertyRegistration Control::Impl::PROPERTY_11(typeRegistration, "leftFocusableActorId", Toolkit::DevelControl::Property::LEFT_FOCUSABLE_ACTOR_ID, Property::INTEGER, &Control::Impl::SetProperty, &Control::Impl::GetProperty);
413 const PropertyRegistration Control::Impl::PROPERTY_12(typeRegistration, "rightFocusableActorId", Toolkit::DevelControl::Property::RIGHT_FOCUSABLE_ACTOR_ID, Property::INTEGER, &Control::Impl::SetProperty, &Control::Impl::GetProperty);
414 const PropertyRegistration Control::Impl::PROPERTY_13(typeRegistration, "upFocusableActorId", Toolkit::DevelControl::Property::UP_FOCUSABLE_ACTOR_ID, Property::INTEGER, &Control::Impl::SetProperty, &Control::Impl::GetProperty);
415 const PropertyRegistration Control::Impl::PROPERTY_14(typeRegistration, "downFocusableActorId", Toolkit::DevelControl::Property::DOWN_FOCUSABLE_ACTOR_ID, Property::INTEGER, &Control::Impl::SetProperty, &Control::Impl::GetProperty);
416 const PropertyRegistration Control::Impl::PROPERTY_15(typeRegistration, "shadow", Toolkit::DevelControl::Property::SHADOW, Property::MAP, &Control::Impl::SetProperty, &Control::Impl::GetProperty);
417 const PropertyRegistration Control::Impl::PROPERTY_16(typeRegistration, "accessibilityAttributes", Toolkit::DevelControl::Property::ACCESSIBILITY_ATTRIBUTES, Property::MAP, &Control::Impl::SetProperty, &Control::Impl::GetProperty);
418 const PropertyRegistration Control::Impl::PROPERTY_17(typeRegistration, "accessibilityName", Toolkit::DevelControl::Property::ACCESSIBILITY_NAME, Property::STRING, &Control::Impl::SetProperty, &Control::Impl::GetProperty);
419 const PropertyRegistration Control::Impl::PROPERTY_18(typeRegistration, "accessibilityDescription", Toolkit::DevelControl::Property::ACCESSIBILITY_DESCRIPTION, Property::STRING, &Control::Impl::SetProperty, &Control::Impl::GetProperty);
420 const PropertyRegistration Control::Impl::PROPERTY_19(typeRegistration, "accessibilityTranslationDomain", Toolkit::DevelControl::Property::ACCESSIBILITY_TRANSLATION_DOMAIN, Property::STRING, &Control::Impl::SetProperty, &Control::Impl::GetProperty);
421 const PropertyRegistration Control::Impl::PROPERTY_20(typeRegistration, "accessibilityRole", Toolkit::DevelControl::Property::ACCESSIBILITY_ROLE, Property::INTEGER, &Control::Impl::SetProperty, &Control::Impl::GetProperty);
422 const PropertyRegistration Control::Impl::PROPERTY_21(typeRegistration, "accessibilityHighlightable", Toolkit::DevelControl::Property::ACCESSIBILITY_HIGHLIGHTABLE, Property::BOOLEAN, &Control::Impl::SetProperty, &Control::Impl::GetProperty);
423 const PropertyRegistration Control::Impl::PROPERTY_22(typeRegistration, "accessibilityAnimated", Toolkit::DevelControl::Property::ACCESSIBILITY_ANIMATED, Property::BOOLEAN, &Control::Impl::SetProperty, &Control::Impl::GetProperty);
426 Control::Impl::Impl(Control& controlImpl)
427 : mControlImpl(controlImpl),
428 mState(Toolkit::DevelControl::NORMAL),
430 mLeftFocusableActorId(-1),
431 mRightFocusableActorId(-1),
432 mUpFocusableActorId(-1),
433 mDownFocusableActorId(-1),
435 mBackgroundColor(Color::TRANSPARENT),
436 mStartingPinchScale(nullptr),
438 mPadding(0, 0, 0, 0),
440 mKeyInputFocusGainedSignal(),
441 mKeyInputFocusLostSignal(),
442 mResourceReadySignal(),
443 mVisualEventSignal(),
444 mAccessibilityGetNameSignal(),
445 mAccessibilityGetDescriptionSignal(),
446 mAccessibilityDoGestureSignal(),
447 mPinchGestureDetector(),
448 mPanGestureDetector(),
449 mTapGestureDetector(),
450 mLongPressGestureDetector(),
452 mInputMethodContext(),
453 mIdleCallback(nullptr),
454 mFlags(Control::ControlBehaviour(CONTROL_BEHAVIOUR_DEFAULT)),
455 mIsKeyboardNavigationSupported(false),
456 mIsKeyboardFocusGroup(false),
457 mIsEmittingResourceReadySignal(false),
458 mNeedToEmitResourceReady(false)
460 Dali::Accessibility::Accessible::RegisterControlAccessibilityGetter(
461 [](Dali::Actor actor) -> Dali::Accessibility::Accessible* {
462 return Control::Impl::GetAccessibilityObject(actor);
465 accessibilityConstructor = [](Dali::Actor actor) -> std::unique_ptr<Dali::Accessibility::Accessible> {
466 return std::unique_ptr<Dali::Accessibility::Accessible>(new AccessibleImpl(actor,
467 Dali::Accessibility::Role::UNKNOWN));
470 size_t len = static_cast<size_t>(Dali::Accessibility::RelationType::MAX_COUNT);
471 mAccessibilityRelations.reserve(len);
472 for(auto i = 0u; i < len; ++i)
474 mAccessibilityRelations.push_back({});
478 Control::Impl::~Impl()
480 for(auto&& iter : mVisuals)
482 StopObservingVisual(iter->visual);
485 for(auto&& iter : mRemoveVisuals)
487 StopObservingVisual(iter->visual);
490 AccessibilityDeregister();
491 // All gesture detectors will be destroyed so no need to disconnect.
492 delete mStartingPinchScale;
494 if(mIdleCallback && Adaptor::IsAvailable())
496 // Removes the callback from the callback manager in case the control is destroyed before the callback is executed.
497 Adaptor::Get().RemoveIdle(mIdleCallback);
501 Control::Impl& Control::Impl::Get(Internal::Control& internalControl)
503 return *internalControl.mImpl;
506 const Control::Impl& Control::Impl::Get(const Internal::Control& internalControl)
508 return *internalControl.mImpl;
511 // Gesture Detection Methods
512 void Control::Impl::PinchDetected(Actor actor, const PinchGesture& pinch)
514 mControlImpl.OnPinch(pinch);
517 void Control::Impl::PanDetected(Actor actor, const PanGesture& pan)
519 mControlImpl.OnPan(pan);
522 void Control::Impl::TapDetected(Actor actor, const TapGesture& tap)
524 mControlImpl.OnTap(tap);
527 void Control::Impl::LongPressDetected(Actor actor, const LongPressGesture& longPress)
529 mControlImpl.OnLongPress(longPress);
532 void Control::Impl::RegisterVisual(Property::Index index, Toolkit::Visual::Base& visual)
534 RegisterVisual(index, visual, VisualState::ENABLED, DepthIndexValue::NOT_SET);
537 void Control::Impl::RegisterVisual(Property::Index index, Toolkit::Visual::Base& visual, int depthIndex)
539 RegisterVisual(index, visual, VisualState::ENABLED, DepthIndexValue::SET, depthIndex);
542 void Control::Impl::RegisterVisual(Property::Index index, Toolkit::Visual::Base& visual, bool enabled)
544 RegisterVisual(index, visual, (enabled ? VisualState::ENABLED : VisualState::DISABLED), DepthIndexValue::NOT_SET);
547 void Control::Impl::RegisterVisual(Property::Index index, Toolkit::Visual::Base& visual, bool enabled, int depthIndex)
549 RegisterVisual(index, visual, (enabled ? VisualState::ENABLED : VisualState::DISABLED), DepthIndexValue::SET, depthIndex);
552 void Control::Impl::RegisterVisual(Property::Index index, Toolkit::Visual::Base& visual, VisualState::Type enabled, DepthIndexValue::Type depthIndexValueSet, int depthIndex)
554 DALI_LOG_INFO(gLogFilter, Debug::Concise, "RegisterVisual:%d \n", index);
556 bool visualReplaced(false);
557 Actor self = mControlImpl.Self();
559 // Set the depth index, if not set by caller this will be either the current visual depth, max depth of all visuals
561 int requiredDepthIndex = visual.GetDepthIndex();
563 if(depthIndexValueSet == DepthIndexValue::SET)
565 requiredDepthIndex = depthIndex;
568 // Visual replacement, existing visual should only be removed from stage when replacement ready.
569 if(!mVisuals.Empty())
571 RegisteredVisualContainer::Iterator registeredVisualsiter;
572 // Check if visual (index) is already registered, this is the current visual.
573 if(FindVisual(index, mVisuals, registeredVisualsiter))
575 Toolkit::Visual::Base& currentRegisteredVisual = (*registeredVisualsiter)->visual;
576 if(currentRegisteredVisual)
578 // Store current visual depth index as may need to set the replacement visual to same depth
579 const int currentDepthIndex = (*registeredVisualsiter)->visual.GetDepthIndex();
581 // No longer required to know if the replaced visual's resources are ready
582 StopObservingVisual(currentRegisteredVisual);
584 // If control staged and visual enabled then visuals will be swapped once ready
585 if(self.GetProperty<bool>(Actor::Property::CONNECTED_TO_SCENE) && enabled)
587 // Check if visual is currently in the process of being replaced ( is in removal container )
588 RegisteredVisualContainer::Iterator visualQueuedForRemoval;
589 if(FindVisual(index, mRemoveVisuals, visualQueuedForRemoval))
591 // Visual with same index is already in removal container so current visual pending
592 // Only the the last requested visual will be displayed so remove current visual which is staged but not ready.
593 Toolkit::GetImplementation(currentRegisteredVisual).SetOffScene(self);
594 mVisuals.Erase(registeredVisualsiter);
598 // current visual not already in removal container so add now.
599 DALI_LOG_INFO(gLogFilter, Debug::Verbose, "RegisterVisual Move current registered visual to removal Queue: %d \n", index);
600 MoveVisual(registeredVisualsiter, mVisuals, mRemoveVisuals);
605 // Control not staged or visual disabled so can just erase from registered visuals and new visual will be added later.
606 mVisuals.Erase(registeredVisualsiter);
609 // 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
610 if((depthIndexValueSet == DepthIndexValue::NOT_SET) &&
611 (visual.GetDepthIndex() == 0))
613 requiredDepthIndex = currentDepthIndex;
617 visualReplaced = true;
621 // If not set, set the name of the visual to the same name as the control's property.
622 // ( If the control has been type registered )
623 if(visual.GetName().empty())
625 // returns empty string if index is not found as long as index is not -1
626 std::string visualName = self.GetPropertyName(index);
627 if(!visualName.empty())
629 DALI_LOG_INFO(gLogFilter, Debug::Concise, "Setting visual name for property %d to %s\n", index, visualName.c_str());
630 visual.SetName(visualName);
634 if(!visualReplaced) // New registration entry
636 // 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
637 if((depthIndexValueSet == DepthIndexValue::NOT_SET) &&
638 (mVisuals.Size() > 0) &&
639 (visual.GetDepthIndex() == 0))
641 int maxDepthIndex = std::numeric_limits<int>::min();
643 RegisteredVisualContainer::ConstIterator iter;
644 const RegisteredVisualContainer::ConstIterator endIter = mVisuals.End();
645 for(iter = mVisuals.Begin(); iter != endIter; iter++)
647 const int visualDepthIndex = (*iter)->visual.GetDepthIndex();
648 if(visualDepthIndex > maxDepthIndex)
650 maxDepthIndex = visualDepthIndex;
653 ++maxDepthIndex; // Add one to the current maximum depth index so that our added visual appears on top
654 requiredDepthIndex = std::max(0, maxDepthIndex); // Start at zero if maxDepth index belongs to a background
660 // Set determined depth index
661 visual.SetDepthIndex(requiredDepthIndex);
663 // Monitor when the visual resources are ready
664 StartObservingVisual(visual);
666 DALI_LOG_INFO(gLogFilter, Debug::Concise, "New Visual registration index[%d] depth[%d]\n", index, requiredDepthIndex);
667 RegisteredVisual* newRegisteredVisual = new RegisteredVisual(index, visual, (enabled == VisualState::ENABLED ? true : false), (visualReplaced && enabled));
668 mVisuals.PushBack(newRegisteredVisual);
670 Internal::Visual::Base& visualImpl = Toolkit::GetImplementation(visual);
671 // Put on stage if enabled and the control is already on the stage
672 if((enabled == VisualState::ENABLED) && self.GetProperty<bool>(Actor::Property::CONNECTED_TO_SCENE))
674 visualImpl.SetOnScene(self);
676 else if(visualImpl.IsResourceReady()) // When not being staged, check if visual already 'ResourceReady' before it was Registered. ( Resource may have been loaded already )
678 ResourceReady(visualImpl);
682 DALI_LOG_INFO(gLogFilter, Debug::Verbose, "Control::RegisterVisual() Registered %s(%d), enabled:%s\n", visual.GetName().c_str(), index, enabled ? "true" : "false");
685 void Control::Impl::UnregisterVisual(Property::Index index)
687 RegisteredVisualContainer::Iterator iter;
688 if(FindVisual(index, mVisuals, iter))
690 // stop observing visual
691 StopObservingVisual((*iter)->visual);
693 Actor self(mControlImpl.Self());
694 Toolkit::GetImplementation((*iter)->visual).SetOffScene(self);
695 (*iter)->visual.Reset();
696 mVisuals.Erase(iter);
699 if(FindVisual(index, mRemoveVisuals, iter))
701 Actor self(mControlImpl.Self());
702 Toolkit::GetImplementation((*iter)->visual).SetOffScene(self);
703 (*iter)->pending = false;
704 (*iter)->visual.Reset();
705 mRemoveVisuals.Erase(iter);
709 Toolkit::Visual::Base Control::Impl::GetVisual(Property::Index index) const
711 RegisteredVisualContainer::Iterator iter;
712 if(FindVisual(index, mVisuals, iter))
714 return (*iter)->visual;
717 return Toolkit::Visual::Base();
720 void Control::Impl::EnableVisual(Property::Index index, bool enable)
722 DALI_LOG_INFO(gLogFilter, Debug::General, "Control::EnableVisual(%d, %s)\n", index, enable ? "T" : "F");
724 RegisteredVisualContainer::Iterator iter;
725 if(FindVisual(index, mVisuals, iter))
727 if((*iter)->enabled == enable)
729 DALI_LOG_INFO(gLogFilter, Debug::Verbose, "Control::EnableVisual Visual %s(%d) already %s\n", (*iter)->visual.GetName().c_str(), index, enable ? "enabled" : "disabled");
733 (*iter)->enabled = enable;
734 Actor parentActor = mControlImpl.Self();
735 if(mControlImpl.Self().GetProperty<bool>(Actor::Property::CONNECTED_TO_SCENE)) // If control not on Scene then Visual will be added when SceneConnection is called.
739 DALI_LOG_INFO(gLogFilter, Debug::Verbose, "Control::EnableVisual Setting %s(%d) on stage \n", (*iter)->visual.GetName().c_str(), index);
740 Toolkit::GetImplementation((*iter)->visual).SetOnScene(parentActor);
744 DALI_LOG_INFO(gLogFilter, Debug::Verbose, "Control::EnableVisual Setting %s(%d) off stage \n", (*iter)->visual.GetName().c_str(), index);
745 Toolkit::GetImplementation((*iter)->visual).SetOffScene(parentActor); // No need to call if control not staged.
751 DALI_LOG_WARNING("Control::EnableVisual(%d, %s) FAILED - NO SUCH VISUAL\n", index, enable ? "T" : "F");
755 bool Control::Impl::IsVisualEnabled(Property::Index index) const
757 RegisteredVisualContainer::Iterator iter;
758 if(FindVisual(index, mVisuals, iter))
760 return (*iter)->enabled;
765 void Control::Impl::StopObservingVisual(Toolkit::Visual::Base& visual)
767 Internal::Visual::Base& visualImpl = Toolkit::GetImplementation(visual);
769 // Stop observing the visual
770 visualImpl.RemoveEventObserver(*this);
773 void Control::Impl::StartObservingVisual(Toolkit::Visual::Base& visual)
775 Internal::Visual::Base& visualImpl = Toolkit::GetImplementation(visual);
777 // start observing the visual for events
778 visualImpl.AddEventObserver(*this);
781 // Called by a Visual when it's resource is ready
782 void Control::Impl::ResourceReady(Visual::Base& object)
784 DALI_LOG_INFO(gLogFilter, Debug::Verbose, "Control::Impl::ResourceReady() replacements pending[%d]\n", mRemoveVisuals.Count());
786 Actor self = mControlImpl.Self();
788 // A resource is ready, find resource in the registered visuals container and get its index
789 for(auto registeredIter = mVisuals.Begin(), end = mVisuals.End(); registeredIter != end; ++registeredIter)
791 Internal::Visual::Base& registeredVisualImpl = Toolkit::GetImplementation((*registeredIter)->visual);
793 if(&object == ®isteredVisualImpl)
795 RegisteredVisualContainer::Iterator visualToRemoveIter;
796 // Find visual with the same index in the removal container
797 // Set if off stage as it's replacement is now ready.
798 // Remove if from removal list as now removed from stage.
799 // Set Pending flag on the ready visual to false as now ready.
800 if(FindVisual((*registeredIter)->index, mRemoveVisuals, visualToRemoveIter))
802 (*registeredIter)->pending = false;
803 Toolkit::GetImplementation((*visualToRemoveIter)->visual).SetOffScene(self);
804 mRemoveVisuals.Erase(visualToRemoveIter);
810 // A visual is ready so control may need relayouting if staged
811 if(self.GetProperty<bool>(Actor::Property::CONNECTED_TO_SCENE))
813 mControlImpl.RelayoutRequest();
816 // Emit signal if all enabled visuals registered by the control are ready.
817 if(IsResourceReady())
820 mNeedToEmitResourceReady = false;
822 EmitResourceReadySignal();
826 void Control::Impl::NotifyVisualEvent(Visual::Base& object, Property::Index signalId)
828 for(auto registeredIter = mVisuals.Begin(), end = mVisuals.End(); registeredIter != end; ++registeredIter)
830 Internal::Visual::Base& registeredVisualImpl = Toolkit::GetImplementation((*registeredIter)->visual);
831 if(&object == ®isteredVisualImpl)
833 Dali::Toolkit::Control handle(mControlImpl.GetOwner());
834 mVisualEventSignal.Emit(handle, (*registeredIter)->index, signalId);
840 bool Control::Impl::IsResourceReady() const
842 // Iterate through and check all the enabled visuals are ready
843 for(auto visualIter = mVisuals.Begin();
844 visualIter != mVisuals.End();
847 const Toolkit::Visual::Base visual = (*visualIter)->visual;
848 const Internal::Visual::Base& visualImpl = Toolkit::GetImplementation(visual);
850 // one of the enabled visuals is not ready
851 if(!visualImpl.IsResourceReady() && (*visualIter)->enabled)
859 Toolkit::Visual::ResourceStatus Control::Impl::GetVisualResourceStatus(Property::Index index) const
861 RegisteredVisualContainer::Iterator iter;
862 if(FindVisual(index, mVisuals, iter))
864 const Toolkit::Visual::Base visual = (*iter)->visual;
865 const Internal::Visual::Base& visualImpl = Toolkit::GetImplementation(visual);
866 return visualImpl.GetResourceStatus();
869 return Toolkit::Visual::ResourceStatus::PREPARING;
872 void Control::Impl::AddTransitions(Dali::Animation& animation,
873 const Toolkit::TransitionData& handle,
874 bool createAnimation)
876 // Setup a Transition from TransitionData.
877 const Internal::TransitionData& transitionData = Toolkit::GetImplementation(handle);
878 TransitionData::Iterator end = transitionData.End();
879 for(TransitionData::Iterator iter = transitionData.Begin();
883 TransitionData::Animator* animator = (*iter);
885 Toolkit::Visual::Base visual = GetVisualByName(mVisuals, animator->objectName);
889 #if defined(DEBUG_ENABLED)
890 Dali::TypeInfo typeInfo;
891 ControlWrapper* controlWrapperImpl = dynamic_cast<ControlWrapper*>(&mControlImpl);
892 if(controlWrapperImpl)
894 typeInfo = controlWrapperImpl->GetTypeInfo();
897 DALI_LOG_INFO(gLogFilter, Debug::Concise, "CreateTransition: Found %s visual for %s\n", visual.GetName().c_str(), typeInfo ? typeInfo.GetName().c_str() : "Unknown");
899 Internal::Visual::Base& visualImpl = Toolkit::GetImplementation(visual);
900 visualImpl.AnimateProperty(animation, *animator);
904 DALI_LOG_INFO(gLogFilter, Debug::Concise, "CreateTransition: Could not find visual. Trying actors");
905 // Otherwise, try any actor children of control (Including the control)
906 Actor child = mControlImpl.Self().FindChildByName(animator->objectName);
909 Property::Index propertyIndex = child.GetPropertyIndex(animator->propertyKey);
910 if(propertyIndex != Property::INVALID_INDEX)
912 if(animator->animate == false)
914 if(animator->targetValue.GetType() != Property::NONE)
916 child.SetProperty(propertyIndex, animator->targetValue);
919 else // animate the property
921 if(animator->initialValue.GetType() != Property::NONE)
923 child.SetProperty(propertyIndex, animator->initialValue);
926 if(createAnimation && !animation)
928 animation = Dali::Animation::New(0.1f);
931 animation.AnimateTo(Property(child, propertyIndex),
932 animator->targetValue,
933 animator->alphaFunction,
934 TimePeriod(animator->timePeriodDelay,
935 animator->timePeriodDuration));
943 Dali::Animation Control::Impl::CreateTransition(const Toolkit::TransitionData& transitionData)
945 Dali::Animation transition;
947 if(transitionData.Count() > 0)
949 AddTransitions(transition, transitionData, true);
954 void Control::Impl::DoAction(Dali::Property::Index visualIndex, Dali::Property::Index actionId, const Dali::Property::Value attributes)
956 RegisteredVisualContainer::Iterator iter;
957 if(FindVisual(visualIndex, mVisuals, iter))
959 Toolkit::GetImplementation((*iter)->visual).DoAction(actionId, attributes);
963 void Control::Impl::AppendAccessibilityAttribute(const std::string& key,
964 const std::string value)
966 Property::Value* val = mAccessibilityAttributes.Find(key);
969 mAccessibilityAttributes[key] = Property::Value(value);
973 mAccessibilityAttributes.Insert(key, value);
977 void Control::Impl::SetProperty(BaseObject* object, Property::Index index, const Property::Value& value)
979 Toolkit::Control control = Toolkit::Control::DownCast(BaseHandle(object));
983 Control& controlImpl(GetImplementation(control));
987 case Toolkit::Control::Property::STYLE_NAME:
989 controlImpl.SetStyleName(value.Get<std::string>());
993 case Toolkit::DevelControl::Property::STATE:
995 bool withTransitions = true;
996 const Property::Value* valuePtr = &value;
997 const Property::Map* map = value.GetMap();
1000 Property::Value* value2 = map->Find("withTransitions");
1003 withTransitions = value2->Get<bool>();
1006 valuePtr = map->Find("state");
1011 Toolkit::DevelControl::State state(controlImpl.mImpl->mState);
1012 if(Scripting::GetEnumerationProperty<Toolkit::DevelControl::State>(*valuePtr, ControlStateTable, ControlStateTableCount, state))
1014 controlImpl.mImpl->SetState(state, withTransitions);
1020 case Toolkit::DevelControl::Property::SUB_STATE:
1022 std::string subState;
1023 if(value.Get(subState))
1025 controlImpl.mImpl->SetSubState(subState);
1030 case Toolkit::DevelControl::Property::LEFT_FOCUSABLE_ACTOR_ID:
1033 if(value.Get(focusId))
1035 controlImpl.mImpl->mLeftFocusableActorId = focusId;
1040 case Toolkit::DevelControl::Property::RIGHT_FOCUSABLE_ACTOR_ID:
1043 if(value.Get(focusId))
1045 controlImpl.mImpl->mRightFocusableActorId = focusId;
1050 case Toolkit::DevelControl::Property::ACCESSIBILITY_NAME:
1055 controlImpl.mImpl->mAccessibilityName = name;
1056 controlImpl.mImpl->mAccessibilityNameSet = true;
1060 controlImpl.mImpl->mAccessibilityNameSet = false;
1065 case Toolkit::DevelControl::Property::ACCESSIBILITY_DESCRIPTION:
1070 controlImpl.mImpl->mAccessibilityDescription = txt;
1071 controlImpl.mImpl->mAccessibilityDescriptionSet = true;
1075 controlImpl.mImpl->mAccessibilityDescriptionSet = false;
1080 case Toolkit::DevelControl::Property::ACCESSIBILITY_TRANSLATION_DOMAIN:
1085 controlImpl.mImpl->mAccessibilityTranslationDomain = txt;
1086 controlImpl.mImpl->mAccessibilityTranslationDomainSet = true;
1090 controlImpl.mImpl->mAccessibilityTranslationDomainSet = false;
1095 case Toolkit::DevelControl::Property::ACCESSIBILITY_HIGHLIGHTABLE:
1098 if(value.Get(highlightable))
1100 controlImpl.mImpl->mAccessibilityHighlightable = highlightable;
1101 controlImpl.mImpl->mAccessibilityHighlightableSet = true;
1105 controlImpl.mImpl->mAccessibilityHighlightableSet = false;
1110 case Toolkit::DevelControl::Property::ACCESSIBILITY_ROLE:
1112 Dali::Accessibility::Role val;
1115 controlImpl.mImpl->mAccessibilityRole = val;
1120 case Toolkit::DevelControl::Property::UP_FOCUSABLE_ACTOR_ID:
1123 if(value.Get(focusId))
1125 controlImpl.mImpl->mUpFocusableActorId = focusId;
1130 case Toolkit::DevelControl::Property::DOWN_FOCUSABLE_ACTOR_ID:
1133 if(value.Get(focusId))
1135 controlImpl.mImpl->mDownFocusableActorId = focusId;
1140 case Toolkit::Control::Property::KEY_INPUT_FOCUS:
1142 if(value.Get<bool>())
1144 controlImpl.SetKeyInputFocus();
1148 controlImpl.ClearKeyInputFocus();
1153 case Toolkit::Control::Property::BACKGROUND:
1157 const Property::Map* map = value.GetMap();
1158 if(map && !map->Empty())
1160 controlImpl.SetBackground(*map);
1162 else if(value.Get(url))
1164 // don't know the size to load
1165 Toolkit::Visual::Base visual = Toolkit::VisualFactory::Get().CreateVisual(url, ImageDimensions());
1168 controlImpl.mImpl->RegisterVisual(Toolkit::Control::Property::BACKGROUND, visual, DepthIndex::BACKGROUND);
1171 else if(value.Get(color))
1173 controlImpl.SetBackgroundColor(color);
1177 // The background is an empty property map, so we should clear the background
1178 controlImpl.ClearBackground();
1183 case Toolkit::Control::Property::MARGIN:
1186 if(value.Get(margin))
1188 controlImpl.mImpl->SetMargin(margin);
1193 case Toolkit::Control::Property::PADDING:
1196 if(value.Get(padding))
1198 controlImpl.mImpl->SetPadding(padding);
1203 case Toolkit::DevelControl::Property::TOOLTIP:
1205 TooltipPtr& tooltipPtr = controlImpl.mImpl->mTooltip;
1208 tooltipPtr = Tooltip::New(control);
1210 tooltipPtr->SetProperties(value);
1214 case Toolkit::DevelControl::Property::SHADOW:
1216 const Property::Map* map = value.GetMap();
1217 if(map && !map->Empty())
1219 controlImpl.mImpl->SetShadow(*map);
1223 // The shadow is an empty property map, so we should clear the shadow
1224 controlImpl.mImpl->ClearShadow();
1229 case Toolkit::DevelControl::Property::ACCESSIBILITY_ATTRIBUTES:
1231 const Property::Map* map = value.GetMap();
1232 if(map && !map->Empty())
1234 controlImpl.mImpl->mAccessibilityAttributes = *map;
1239 case Toolkit::DevelControl::Property::ACCESSIBILITY_ANIMATED:
1242 if(value.Get(animated))
1244 controlImpl.mImpl->mAccessibilityAnimated = animated;
1252 Property::Value Control::Impl::GetProperty(BaseObject* object, Property::Index index)
1254 Property::Value value;
1256 Toolkit::Control control = Toolkit::Control::DownCast(BaseHandle(object));
1260 Control& controlImpl(GetImplementation(control));
1264 case Toolkit::Control::Property::STYLE_NAME:
1266 value = controlImpl.GetStyleName();
1270 case Toolkit::DevelControl::Property::STATE:
1272 value = controlImpl.mImpl->mState;
1276 case Toolkit::DevelControl::Property::SUB_STATE:
1278 value = controlImpl.mImpl->mSubStateName;
1282 case Toolkit::DevelControl::Property::LEFT_FOCUSABLE_ACTOR_ID:
1284 value = controlImpl.mImpl->mLeftFocusableActorId;
1288 case Toolkit::DevelControl::Property::RIGHT_FOCUSABLE_ACTOR_ID:
1290 value = controlImpl.mImpl->mRightFocusableActorId;
1294 case Toolkit::DevelControl::Property::ACCESSIBILITY_NAME:
1296 if(controlImpl.mImpl->mAccessibilityNameSet)
1298 value = controlImpl.mImpl->mAccessibilityName;
1303 case Toolkit::DevelControl::Property::ACCESSIBILITY_DESCRIPTION:
1305 if(controlImpl.mImpl->mAccessibilityDescriptionSet)
1307 value = controlImpl.mImpl->mAccessibilityDescription;
1312 case Toolkit::DevelControl::Property::ACCESSIBILITY_TRANSLATION_DOMAIN:
1314 if(controlImpl.mImpl->mAccessibilityTranslationDomainSet)
1316 value = controlImpl.mImpl->mAccessibilityTranslationDomain;
1321 case Toolkit::DevelControl::Property::ACCESSIBILITY_HIGHLIGHTABLE:
1323 if(controlImpl.mImpl->mAccessibilityHighlightableSet)
1325 value = controlImpl.mImpl->mAccessibilityHighlightable;
1330 case Toolkit::DevelControl::Property::ACCESSIBILITY_ROLE:
1332 value = Property::Value(controlImpl.mImpl->mAccessibilityRole);
1336 case Toolkit::DevelControl::Property::UP_FOCUSABLE_ACTOR_ID:
1338 value = controlImpl.mImpl->mUpFocusableActorId;
1342 case Toolkit::DevelControl::Property::DOWN_FOCUSABLE_ACTOR_ID:
1344 value = controlImpl.mImpl->mDownFocusableActorId;
1348 case Toolkit::Control::Property::KEY_INPUT_FOCUS:
1350 value = controlImpl.HasKeyInputFocus();
1354 case Toolkit::Control::Property::BACKGROUND:
1357 Toolkit::Visual::Base visual = controlImpl.mImpl->GetVisual(Toolkit::Control::Property::BACKGROUND);
1360 visual.CreatePropertyMap(map);
1367 case Toolkit::Control::Property::MARGIN:
1369 value = controlImpl.mImpl->GetMargin();
1373 case Toolkit::Control::Property::PADDING:
1375 value = controlImpl.mImpl->GetPadding();
1379 case Toolkit::DevelControl::Property::TOOLTIP:
1382 if(controlImpl.mImpl->mTooltip)
1384 controlImpl.mImpl->mTooltip->CreatePropertyMap(map);
1390 case Toolkit::DevelControl::Property::SHADOW:
1393 Toolkit::Visual::Base visual = controlImpl.mImpl->GetVisual(Toolkit::DevelControl::Property::SHADOW);
1396 visual.CreatePropertyMap(map);
1403 case Toolkit::DevelControl::Property::ACCESSIBILITY_ATTRIBUTES:
1405 value = controlImpl.mImpl->mAccessibilityAttributes;
1409 case Toolkit::DevelControl::Property::ACCESSIBILITY_ANIMATED:
1411 value = controlImpl.mImpl->mAccessibilityAnimated;
1420 void Control::Impl::RemoveAccessibilityAttribute(const std::string& key)
1422 Property::Value* val = mAccessibilityAttributes.Find(key);
1424 mAccessibilityAttributes[key] = Property::Value();
1427 void Control::Impl::ClearAccessibilityAttributes()
1429 mAccessibilityAttributes.Clear();
1432 void Control::Impl::SetAccessibilityReadingInfoType(const Dali::Accessibility::ReadingInfoTypes types)
1435 if(types[Dali::Accessibility::ReadingInfoType::NAME])
1437 value += READING_INFO_TYPE_NAME;
1439 if(types[Dali::Accessibility::ReadingInfoType::ROLE])
1443 value += READING_INFO_TYPE_SEPARATOR;
1445 value += READING_INFO_TYPE_ROLE;
1447 if(types[Dali::Accessibility::ReadingInfoType::DESCRIPTION])
1451 value += READING_INFO_TYPE_SEPARATOR;
1453 value += READING_INFO_TYPE_DESCRIPTION;
1455 if(types[Dali::Accessibility::ReadingInfoType::STATE])
1459 value += READING_INFO_TYPE_SEPARATOR;
1461 value += READING_INFO_TYPE_STATE;
1463 AppendAccessibilityAttribute(READING_INFO_TYPE_ATTRIBUTE_NAME, value);
1466 Dali::Accessibility::ReadingInfoTypes Control::Impl::GetAccessibilityReadingInfoType() const
1469 auto place = mAccessibilityAttributes.Find(READING_INFO_TYPE_ATTRIBUTE_NAME);
1480 Dali::Accessibility::ReadingInfoTypes types;
1482 if(value.find(READING_INFO_TYPE_NAME) != std::string::npos)
1484 types[Dali::Accessibility::ReadingInfoType::NAME] = true;
1486 if(value.find(READING_INFO_TYPE_ROLE) != std::string::npos)
1488 types[Dali::Accessibility::ReadingInfoType::ROLE] = true;
1490 if(value.find(READING_INFO_TYPE_DESCRIPTION) != std::string::npos)
1492 types[Dali::Accessibility::ReadingInfoType::DESCRIPTION] = true;
1494 if(value.find(READING_INFO_TYPE_STATE) != std::string::npos)
1496 types[Dali::Accessibility::ReadingInfoType::STATE] = true;
1502 void Control::Impl::CopyInstancedProperties(RegisteredVisualContainer& visuals, Dictionary<Property::Map>& instancedProperties)
1504 for(RegisteredVisualContainer::Iterator iter = visuals.Begin(); iter != visuals.End(); iter++)
1508 Property::Map instanceMap;
1509 Toolkit::GetImplementation((*iter)->visual).CreateInstancePropertyMap(instanceMap);
1510 instancedProperties.Add((*iter)->visual.GetName(), instanceMap);
1515 void Control::Impl::RemoveVisual(RegisteredVisualContainer& visuals, const std::string& visualName)
1517 Actor self(mControlImpl.Self());
1519 for(RegisteredVisualContainer::Iterator visualIter = visuals.Begin();
1520 visualIter != visuals.End();
1523 Toolkit::Visual::Base visual = (*visualIter)->visual;
1524 if(visual && visual.GetName() == visualName)
1526 Toolkit::GetImplementation(visual).SetOffScene(self);
1527 (*visualIter)->visual.Reset();
1528 visuals.Erase(visualIter);
1534 void Control::Impl::RemoveVisuals(RegisteredVisualContainer& visuals, DictionaryKeys& removeVisuals)
1536 Actor self(mControlImpl.Self());
1537 for(DictionaryKeys::iterator iter = removeVisuals.begin(); iter != removeVisuals.end(); ++iter)
1539 const std::string visualName = *iter;
1540 RemoveVisual(visuals, visualName);
1544 void Control::Impl::RecreateChangedVisuals(Dictionary<Property::Map>& stateVisualsToChange,
1545 Dictionary<Property::Map>& instancedProperties)
1547 Dali::CustomActor handle(mControlImpl.GetOwner());
1548 for(Dictionary<Property::Map>::iterator iter = stateVisualsToChange.Begin();
1549 iter != stateVisualsToChange.End();
1552 const std::string& visualName = (*iter).key;
1553 const Property::Map& toMap = (*iter).entry;
1555 Actor self = mControlImpl.Self();
1556 RegisteredVisualContainer::Iterator registeredVisualsiter;
1557 // Check if visual (visualName) is already registered, this is the current visual.
1558 if(FindVisual(visualName, mVisuals, registeredVisualsiter))
1560 Toolkit::Visual::Base& visual = (*registeredVisualsiter)->visual;
1563 // No longer required to know if the replaced visual's resources are ready
1564 StopObservingVisual(visual);
1566 // If control staged then visuals will be swapped once ready
1567 if(self.GetProperty<bool>(Actor::Property::CONNECTED_TO_SCENE))
1569 // Check if visual is currently in the process of being replaced ( is in removal container )
1570 RegisteredVisualContainer::Iterator visualQueuedForRemoval;
1571 if(FindVisual(visualName, mRemoveVisuals, visualQueuedForRemoval))
1573 // Visual with same visual name is already in removal container so current visual pending
1574 // Only the the last requested visual will be displayed so remove current visual which is staged but not ready.
1575 Toolkit::GetImplementation(visual).SetOffScene(self);
1576 (*registeredVisualsiter)->visual.Reset();
1577 mVisuals.Erase(registeredVisualsiter);
1581 // current visual not already in removal container so add now.
1582 DALI_LOG_INFO(gLogFilter, Debug::Verbose, "RegisterVisual Move current registered visual to removal Queue: %s \n", visualName.c_str());
1583 MoveVisual(registeredVisualsiter, mVisuals, mRemoveVisuals);
1588 // Control not staged or visual disabled so can just erase from registered visuals and new visual will be added later.
1589 (*registeredVisualsiter)->visual.Reset();
1590 mVisuals.Erase(registeredVisualsiter);
1594 const Property::Map* instancedMap = instancedProperties.FindConst(visualName);
1595 Style::ApplyVisual(handle, visualName, toMap, instancedMap);
1600 void Control::Impl::ReplaceStateVisualsAndProperties(const StylePtr oldState, const StylePtr newState, const std::string& subState)
1602 // Collect all old visual names
1603 DictionaryKeys stateVisualsToRemove;
1606 oldState->visuals.GetKeys(stateVisualsToRemove);
1607 if(!subState.empty())
1609 const StylePtr* oldSubState = oldState->subStates.FindConst(subState);
1612 DictionaryKeys subStateVisualsToRemove;
1613 (*oldSubState)->visuals.GetKeys(subStateVisualsToRemove);
1614 Merge(stateVisualsToRemove, subStateVisualsToRemove);
1619 // Collect all new visual properties
1620 Dictionary<Property::Map> stateVisualsToAdd;
1623 stateVisualsToAdd = newState->visuals;
1624 if(!subState.empty())
1626 const StylePtr* newSubState = newState->subStates.FindConst(subState);
1629 stateVisualsToAdd.Merge((*newSubState)->visuals);
1634 // If a name is in both add/remove, move it to change list.
1635 Dictionary<Property::Map> stateVisualsToChange;
1636 FindChangableVisuals(stateVisualsToAdd, stateVisualsToChange, stateVisualsToRemove);
1638 // Copy instanced properties (e.g. text label) of current visuals
1639 Dictionary<Property::Map> instancedProperties;
1640 CopyInstancedProperties(mVisuals, instancedProperties);
1642 // For each visual in remove list, remove from mVisuals
1643 RemoveVisuals(mVisuals, stateVisualsToRemove);
1645 // For each visual in add list, create and add to mVisuals
1646 Dali::CustomActor handle(mControlImpl.GetOwner());
1647 Style::ApplyVisuals(handle, stateVisualsToAdd, instancedProperties);
1649 // For each visual in change list, if it requires a new visual,
1650 // remove old visual, create and add to mVisuals
1651 RecreateChangedVisuals(stateVisualsToChange, instancedProperties);
1654 void Control::Impl::SetState(DevelControl::State newState, bool withTransitions)
1656 DevelControl::State oldState = mState;
1657 Dali::CustomActor handle(mControlImpl.GetOwner());
1658 DALI_LOG_INFO(gLogFilter, Debug::Concise, "Control::Impl::SetState: %s\n", (mState == DevelControl::NORMAL ? "NORMAL" : (mState == DevelControl::FOCUSED ? "FOCUSED" : (mState == DevelControl::DISABLED ? "DISABLED" : "NONE"))));
1660 if(mState != newState)
1662 // If mState was Disabled, and new state is Focused, should probably
1663 // store that fact, e.g. in another property that FocusManager can access.
1666 // Trigger state change and transitions
1667 // Apply new style, if stylemanager is available
1668 Toolkit::StyleManager styleManager = Toolkit::StyleManager::Get();
1671 const StylePtr stylePtr = GetImpl(styleManager).GetRecordedStyle(Toolkit::Control(mControlImpl.GetOwner()));
1675 std::string oldStateName = Scripting::GetEnumerationName<Toolkit::DevelControl::State>(oldState, ControlStateTable, ControlStateTableCount);
1676 std::string newStateName = Scripting::GetEnumerationName<Toolkit::DevelControl::State>(newState, ControlStateTable, ControlStateTableCount);
1678 const StylePtr* newStateStyle = stylePtr->subStates.Find(newStateName);
1679 const StylePtr* oldStateStyle = stylePtr->subStates.Find(oldStateName);
1680 if(oldStateStyle && newStateStyle)
1682 // Only change if both state styles exist
1683 ReplaceStateVisualsAndProperties(*oldStateStyle, *newStateStyle, mSubStateName);
1690 void Control::Impl::SetSubState(const std::string& subStateName, bool withTransitions)
1692 if(mSubStateName != subStateName)
1694 // Get existing sub-state visuals, and unregister them
1695 Dali::CustomActor handle(mControlImpl.GetOwner());
1697 Toolkit::StyleManager styleManager = Toolkit::StyleManager::Get();
1700 const StylePtr stylePtr = GetImpl(styleManager).GetRecordedStyle(Toolkit::Control(mControlImpl.GetOwner()));
1704 std::string stateName = Scripting::GetEnumerationName<Toolkit::DevelControl::State>(mState, ControlStateTable, ControlStateTableCount);
1706 const StylePtr* state = stylePtr->subStates.Find(stateName);
1709 StylePtr stateStyle(*state);
1711 const StylePtr* newStateStyle = stateStyle->subStates.Find(subStateName);
1712 const StylePtr* oldStateStyle = stateStyle->subStates.Find(mSubStateName);
1713 if(oldStateStyle && newStateStyle)
1716 ReplaceStateVisualsAndProperties(*oldStateStyle, *newStateStyle, empty);
1722 mSubStateName = subStateName;
1726 void Control::Impl::OnSceneDisconnection()
1728 Actor self = mControlImpl.Self();
1730 // Any visuals set for replacement but not yet ready should still be registered.
1731 // Reason: If a request was made to register a new visual but the control removed from scene before visual was ready
1732 // then when this control appears back on stage it should use that new visual.
1734 // Iterate through all registered visuals and set off scene
1735 SetVisualsOffScene(mVisuals, self);
1737 // Visuals pending replacement can now be taken out of the removal list and set off scene
1738 // Iterate through all replacement visuals and add to a move queue then set off scene
1739 for(auto removalIter = mRemoveVisuals.Begin(), end = mRemoveVisuals.End(); removalIter != end; removalIter++)
1741 Toolkit::GetImplementation((*removalIter)->visual).SetOffScene(self);
1744 for(auto replacedIter = mVisuals.Begin(), end = mVisuals.End(); replacedIter != end; replacedIter++)
1746 (*replacedIter)->pending = false;
1749 mRemoveVisuals.Clear();
1752 void Control::Impl::SetMargin(Extents margin)
1754 mControlImpl.mImpl->mMargin = margin;
1756 // Trigger a size negotiation request that may be needed when setting a margin.
1757 mControlImpl.RelayoutRequest();
1760 Extents Control::Impl::GetMargin() const
1762 return mControlImpl.mImpl->mMargin;
1765 void Control::Impl::SetPadding(Extents padding)
1767 mControlImpl.mImpl->mPadding = padding;
1769 // Trigger a size negotiation request that may be needed when setting a padding.
1770 mControlImpl.RelayoutRequest();
1773 Extents Control::Impl::GetPadding() const
1775 return mControlImpl.mImpl->mPadding;
1778 void Control::Impl::SetInputMethodContext(InputMethodContext& inputMethodContext)
1780 mInputMethodContext = inputMethodContext;
1783 bool Control::Impl::FilterKeyEvent(const KeyEvent& event)
1785 bool consumed(false);
1787 if(mInputMethodContext)
1789 consumed = mInputMethodContext.FilterEventKey(event);
1794 DevelControl::VisualEventSignalType& Control::Impl::VisualEventSignal()
1796 return mVisualEventSignal;
1799 void Control::Impl::SetShadow(const Property::Map& map)
1801 Toolkit::Visual::Base visual = Toolkit::VisualFactory::Get().CreateVisual(map);
1802 visual.SetName("shadow");
1806 mControlImpl.mImpl->RegisterVisual(Toolkit::DevelControl::Property::SHADOW, visual, DepthIndex::BACKGROUND_EFFECT);
1808 mControlImpl.RelayoutRequest();
1812 void Control::Impl::ClearShadow()
1814 mControlImpl.mImpl->UnregisterVisual(Toolkit::DevelControl::Property::SHADOW);
1816 // Trigger a size negotiation request that may be needed when unregistering a visual.
1817 mControlImpl.RelayoutRequest();
1820 Dali::Property Control::Impl::GetVisualProperty(Dali::Property::Index index, Dali::Property::Key visualPropertyKey)
1822 Toolkit::Visual::Base visual = GetVisualByIndex(mVisuals, index);
1825 Internal::Visual::Base& visualImpl = Toolkit::GetImplementation(visual);
1826 return visualImpl.GetPropertyObject(visualPropertyKey);
1830 return Dali::Property(handle, Property::INVALID_INDEX);
1833 void Control::Impl::EmitResourceReadySignal()
1835 if(!mIsEmittingResourceReadySignal)
1837 // Guard against calls to emit the signal during the callback
1838 mIsEmittingResourceReadySignal = true;
1840 // If the signal handler changes visual, it may become ready during this call & therefore this method will
1841 // get called again recursively. If so, mNeedToEmitResourceReady is set below, and we act on it after that secondary
1842 // invocation has completed by notifying in an Idle callback to prevent further recursion.
1843 Dali::Toolkit::Control handle(mControlImpl.GetOwner());
1844 mResourceReadySignal.Emit(handle);
1846 if(mNeedToEmitResourceReady)
1848 // Add idler to emit the signal again
1851 // The callback manager takes the ownership of the callback object.
1852 mIdleCallback = MakeCallback(this, &Control::Impl::OnIdleCallback);
1853 Adaptor::Get().AddIdle(mIdleCallback, false);
1857 mIsEmittingResourceReadySignal = false;
1861 mNeedToEmitResourceReady = true;
1865 void Control::Impl::OnIdleCallback()
1867 if(mNeedToEmitResourceReady)
1870 mNeedToEmitResourceReady = false;
1872 // A visual is ready so control may need relayouting if staged
1873 if(mControlImpl.Self().GetProperty<bool>(Actor::Property::CONNECTED_TO_SCENE))
1875 mControlImpl.RelayoutRequest();
1878 EmitResourceReadySignal();
1881 // Set the pointer to null as the callback manager deletes the callback after execute it.
1882 mIdleCallback = nullptr;
1885 Dali::Accessibility::Accessible* Control::Impl::GetAccessibilityObject()
1887 if(!accessibilityObject)
1888 accessibilityObject = accessibilityConstructor(mControlImpl.Self());
1889 return accessibilityObject.get();
1892 Dali::Accessibility::Accessible* Control::Impl::GetAccessibilityObject(Dali::Actor actor)
1896 auto q = Dali::Toolkit::Control::DownCast(actor);
1899 auto q2 = static_cast<Internal::Control*>(&q.GetImplementation());
1900 return q2->mImpl->GetAccessibilityObject();
1906 Control::Impl::AccessibleImpl::AccessibleImpl(Dali::Actor self, Dali::Accessibility::Role role, bool modal)
1910 auto control = Dali::Toolkit::Control::DownCast(self);
1912 Internal::Control& internalControl = Toolkit::Internal::GetImplementation(control);
1913 Internal::Control::Impl& controlImpl = Internal::Control::Impl::Get(internalControl);
1914 if(controlImpl.mAccessibilityRole == Dali::Accessibility::Role::UNKNOWN)
1915 controlImpl.mAccessibilityRole = role;
1917 self.PropertySetSignal().Connect(&controlImpl, [this, &controlImpl](Dali::Handle& handle, Dali::Property::Index index, Dali::Property::Value value) {
1918 if(this->self != Dali::Accessibility::Accessible::GetCurrentlyHighlightedActor())
1923 if(index == DevelControl::Property::ACCESSIBILITY_NAME || (index == GetNamePropertyIndex() && !controlImpl.mAccessibilityNameSet))
1925 if(controlImpl.mAccessibilityGetNameSignal.Empty())
1927 Emit(Dali::Accessibility::ObjectPropertyChangeEvent::NAME);
1931 if(index == DevelControl::Property::ACCESSIBILITY_DESCRIPTION || (index == GetDescriptionPropertyIndex() && !controlImpl.mAccessibilityDescriptionSet))
1933 if(controlImpl.mAccessibilityGetDescriptionSignal.Empty())
1935 Emit(Dali::Accessibility::ObjectPropertyChangeEvent::DESCRIPTION);
1941 std::string Control::Impl::AccessibleImpl::GetName()
1943 auto control = Dali::Toolkit::Control::DownCast(self);
1945 Internal::Control& internalControl = Toolkit::Internal::GetImplementation(control);
1946 Internal::Control::Impl& controlImpl = Internal::Control::Impl::Get(internalControl);
1948 if(!controlImpl.mAccessibilityGetNameSignal.Empty())
1951 controlImpl.mAccessibilityGetNameSignal.Emit(ret);
1955 if(controlImpl.mAccessibilityNameSet)
1956 return controlImpl.mAccessibilityName;
1958 if(auto raw = GetNameRaw(); !raw.empty())
1961 return self.GetProperty<std::string>(Actor::Property::NAME);
1964 std::string Control::Impl::AccessibleImpl::GetNameRaw()
1969 std::string Control::Impl::AccessibleImpl::GetDescription()
1971 auto control = Dali::Toolkit::Control::DownCast(self);
1973 Internal::Control& internalControl = Toolkit::Internal::GetImplementation(control);
1974 Internal::Control::Impl& controlImpl = Internal::Control::Impl::Get(internalControl);
1976 if(!controlImpl.mAccessibilityGetDescriptionSignal.Empty())
1979 controlImpl.mAccessibilityGetDescriptionSignal.Emit(ret);
1983 if(controlImpl.mAccessibilityDescriptionSet)
1984 return controlImpl.mAccessibilityDescription;
1986 return GetDescriptionRaw();
1989 std::string Control::Impl::AccessibleImpl::GetDescriptionRaw()
1994 Dali::Accessibility::Accessible* Control::Impl::AccessibleImpl::GetParent()
1996 return Dali::Accessibility::Accessible::Get(self.GetParent());
1999 size_t Control::Impl::AccessibleImpl::GetChildCount()
2001 return self.GetChildCount();
2004 Dali::Accessibility::Accessible* Control::Impl::AccessibleImpl::GetChildAtIndex(size_t index)
2006 return Dali::Accessibility::Accessible::Get(self.GetChildAt(static_cast<unsigned int>(index)));
2009 size_t Control::Impl::AccessibleImpl::GetIndexInParent()
2012 auto parent = s.GetParent();
2013 DALI_ASSERT_ALWAYS(parent && "can't call GetIndexInParent on object without parent");
2014 auto count = parent.GetChildCount();
2015 for(auto i = 0u; i < count; ++i)
2017 auto c = parent.GetChildAt(i);
2021 DALI_ASSERT_ALWAYS(false && "object isn't child of it's parent");
2022 return static_cast<size_t>(-1);
2025 Dali::Accessibility::Role Control::Impl::AccessibleImpl::GetRole()
2027 return self.GetProperty<Dali::Accessibility::Role>(Toolkit::DevelControl::Property::ACCESSIBILITY_ROLE);
2030 Dali::Accessibility::States Control::Impl::AccessibleImpl::CalculateStates()
2032 Dali::Accessibility::States s;
2033 s[Dali::Accessibility::State::FOCUSABLE] = self.GetProperty<bool>(Actor::Property::KEYBOARD_FOCUSABLE);
2034 s[Dali::Accessibility::State::FOCUSED] = Toolkit::KeyboardFocusManager::Get().GetCurrentFocusActor() == self;
2035 if(self.GetProperty(Toolkit::DevelControl::Property::ACCESSIBILITY_HIGHLIGHTABLE).GetType() == Property::NONE)
2036 s[Dali::Accessibility::State::HIGHLIGHTABLE] = false;
2038 s[Dali::Accessibility::State::HIGHLIGHTABLE] = self.GetProperty(Toolkit::DevelControl::Property::ACCESSIBILITY_HIGHLIGHTABLE).Get<bool>();
2039 s[Dali::Accessibility::State::HIGHLIGHTED] = GetCurrentlyHighlightedActor() == self;
2040 s[Dali::Accessibility::State::ENABLED] = true;
2041 s[Dali::Accessibility::State::SENSITIVE] = true;
2042 s[Dali::Accessibility::State::ANIMATED] = self.GetProperty(Toolkit::DevelControl::Property::ACCESSIBILITY_ANIMATED).Get<bool>();
2043 s[Dali::Accessibility::State::VISIBLE] = true;
2046 s[Dali::Accessibility::State::MODAL] = true;
2048 s[Dali::Accessibility::State::SHOWING] = !self.GetProperty(Dali::DevelActor::Property::CULLED).Get<bool>() && self.GetCurrentProperty<bool>(Actor::Property::VISIBLE);
2050 s[Dali::Accessibility::State::DEFUNCT] = !self.GetProperty(Dali::DevelActor::Property::CONNECTED_TO_SCENE).Get<bool>();
2054 Dali::Accessibility::States Control::Impl::AccessibleImpl::GetStates()
2056 return CalculateStates();
2059 Dali::Accessibility::Attributes Control::Impl::AccessibleImpl::GetAttributes()
2061 std::unordered_map<std::string, std::string> attribute_map;
2062 auto q = Dali::Toolkit::Control::DownCast(self);
2064 q.GetProperty(Dali::Toolkit::DevelControl::Property::ACCESSIBILITY_ATTRIBUTES);
2065 auto z = w.GetMap();
2069 auto map_size = z->Count();
2071 for(unsigned int i = 0; i < map_size; i++)
2073 auto map_key = z->GetKeyAt(i);
2074 if(map_key.type == Property::Key::STRING)
2076 std::string map_value;
2077 if(z->GetValue(i).Get(map_value))
2079 attribute_map.emplace(std::move(map_key.stringKey),
2080 std::move(map_value));
2086 return attribute_map;
2089 Dali::Accessibility::ComponentLayer Control::Impl::AccessibleImpl::GetLayer()
2091 return Dali::Accessibility::ComponentLayer::WINDOW;
2094 Dali::Rect<> Control::Impl::AccessibleImpl::GetExtents(Dali::Accessibility::CoordType ctype)
2096 Vector2 screenPosition =
2097 self.GetProperty(Dali::DevelActor::Property::SCREEN_POSITION)
2099 auto size = self.GetCurrentProperty<Vector3>(Actor::Property::SIZE) * self.GetCurrentProperty<Vector3>(Actor::Property::WORLD_SCALE);
2100 bool positionUsesAnchorPoint =
2101 self.GetProperty(Dali::DevelActor::Property::POSITION_USES_ANCHOR_POINT)
2103 Vector3 anchorPointOffSet =
2104 size * (positionUsesAnchorPoint ? self.GetCurrentProperty<Vector3>(Actor::Property::ANCHOR_POINT)
2105 : AnchorPoint::TOP_LEFT);
2106 Vector2 position = Vector2(screenPosition.x - anchorPointOffSet.x,
2107 screenPosition.y - anchorPointOffSet.y);
2109 return {position.x, position.y, size.x, size.y};
2112 int16_t Control::Impl::AccessibleImpl::GetMdiZOrder()
2116 double Control::Impl::AccessibleImpl::GetAlpha()
2121 bool Control::Impl::AccessibleImpl::GrabFocus()
2123 return Toolkit::KeyboardFocusManager::Get().SetCurrentFocusActor(self);
2126 static Dali::Actor CreateHighlightIndicatorActor()
2128 std::string focusBorderImagePath(AssetManager::GetDaliImagePath());
2129 focusBorderImagePath += "/keyboard_focus.9.png";
2130 // Create the default if it hasn't been set and one that's shared by all the
2131 // keyboard focusable actors
2132 auto actor = Toolkit::ImageView::New(focusBorderImagePath);
2133 actor.SetResizePolicy(ResizePolicy::FILL_TO_PARENT, Dimension::ALL_DIMENSIONS);
2134 DevelControl::AppendAccessibilityAttribute(actor, "highlight", "");
2135 actor.SetProperty(Toolkit::DevelControl::Property::ACCESSIBILITY_ANIMATED, true);
2136 actor.SetProperty(Toolkit::DevelControl::Property::ACCESSIBILITY_HIGHLIGHTABLE, false);
2141 bool Control::Impl::AccessibleImpl::GrabHighlight()
2143 auto old = GetCurrentlyHighlightedActor();
2145 if(!Dali::Accessibility::IsUp())
2151 auto c = dynamic_cast<Dali::Accessibility::Component*>(GetAccessibilityObject(old));
2153 c->ClearHighlight();
2155 auto highlight = GetHighlightActor();
2158 highlight = CreateHighlightIndicatorActor();
2159 SetHighlightActor(highlight);
2161 highlight.SetProperty(Actor::Property::PARENT_ORIGIN, ParentOrigin::CENTER);
2162 highlight.SetProperty(Actor::Property::ANCHOR_POINT, AnchorPoint::CENTER);
2163 highlight.SetProperty(Actor::Property::POSITION_Z, 1.0f);
2164 highlight.SetProperty(Actor::Property::POSITION, Vector2(0.0f, 0.0f));
2166 EnsureSelfVisible();
2167 self.Add(highlight);
2168 SetCurrentlyHighlightedActor(self);
2169 EmitHighlighted(true);
2174 bool Control::Impl::AccessibleImpl::ClearHighlight()
2176 if(!Dali::Accessibility::IsUp())
2178 if(GetCurrentlyHighlightedActor() == self)
2180 self.Remove(GetHighlightActor());
2181 SetCurrentlyHighlightedActor({});
2182 EmitHighlighted(false);
2188 std::string Control::Impl::AccessibleImpl::GetActionName(size_t index)
2190 if(index >= GetActionCount()) return "";
2191 Dali::TypeInfo type;
2192 self.GetTypeInfo(type);
2193 DALI_ASSERT_ALWAYS(type && "no TypeInfo object");
2194 return type.GetActionName(index);
2196 std::string Control::Impl::AccessibleImpl::GetLocalizedActionName(size_t index)
2198 // TODO: add localization
2199 return GetActionName(index);
2201 std::string Control::Impl::AccessibleImpl::GetActionDescription(size_t index)
2205 size_t Control::Impl::AccessibleImpl::GetActionCount()
2207 Dali::TypeInfo type;
2208 self.GetTypeInfo(type);
2209 DALI_ASSERT_ALWAYS(type && "no TypeInfo object");
2210 return type.GetActionCount();
2212 std::string Control::Impl::AccessibleImpl::GetActionKeyBinding(size_t index)
2216 bool Control::Impl::AccessibleImpl::DoAction(size_t index)
2218 std::string actionName = GetActionName(index);
2219 return self.DoAction(actionName, {});
2221 bool Control::Impl::AccessibleImpl::DoAction(const std::string& name)
2223 return self.DoAction(name, {});
2226 bool Control::Impl::AccessibleImpl::DoGesture(const Dali::Accessibility::GestureInfo& gestureInfo)
2228 auto control = Dali::Toolkit::Control::DownCast(self);
2230 Internal::Control& internalControl = Toolkit::Internal::GetImplementation(control);
2231 Internal::Control::Impl& controlImpl = Internal::Control::Impl::Get(internalControl);
2233 if(!controlImpl.mAccessibilityDoGestureSignal.Empty())
2235 auto ret = std::make_pair(gestureInfo, false);
2236 controlImpl.mAccessibilityDoGestureSignal.Emit(ret);
2243 std::vector<Dali::Accessibility::Relation> Control::Impl::AccessibleImpl::GetRelationSet()
2245 auto control = Dali::Toolkit::Control::DownCast(self);
2247 Internal::Control& internalControl = Toolkit::Internal::GetImplementation(control);
2248 Internal::Control::Impl& controlImpl = Internal::Control::Impl::Get(internalControl);
2250 std::vector<Dali::Accessibility::Relation> ret;
2252 auto& v = controlImpl.mAccessibilityRelations;
2253 for(auto i = 0u; i < v.size(); ++i)
2258 ret.emplace_back(Accessibility::Relation{static_cast<Accessibility::RelationType>(i), v[i]});
2264 void Control::Impl::AccessibleImpl::EnsureChildVisible(Actor child)
2268 void Control::Impl::AccessibleImpl::EnsureSelfVisible()
2270 auto parent = dynamic_cast<Control::Impl::AccessibleImpl*>(GetParent());
2273 parent->EnsureChildVisible(self);
2277 Property::Index Control::Impl::AccessibleImpl::GetNamePropertyIndex()
2279 return Actor::Property::NAME;
2282 Property::Index Control::Impl::AccessibleImpl::GetDescriptionPropertyIndex()
2284 return Property::INVALID_INDEX;
2287 void Control::Impl::PositionOrSizeChangedCallback(PropertyNotification& p)
2289 auto self = Dali::Actor::DownCast(p.GetTarget());
2290 if(Dali::Accessibility::IsUp() && !self.GetProperty(Toolkit::DevelControl::Property::ACCESSIBILITY_ANIMATED).Get<bool>())
2292 auto extents = DevelActor::CalculateScreenExtents(self);
2293 Dali::Accessibility::Accessible::Get(self)->EmitBoundsChanged(extents);
2297 void Control::Impl::CulledChangedCallback(PropertyNotification& p)
2299 if(Dali::Accessibility::IsUp())
2301 auto self = Dali::Actor::DownCast(p.GetTarget());
2302 Dali::Accessibility::Accessible::Get(self)->EmitShowing(!self.GetProperty(DevelActor::Property::CULLED).Get<bool>());
2306 void Control::Impl::AccessibilityRegister()
2308 if(!accessibilityNotificationSet)
2310 accessibilityNotificationPosition = mControlImpl.Self().AddPropertyNotification(Actor::Property::POSITION, StepCondition(0.01f));
2311 accessibilityNotificationPosition.SetNotifyMode(PropertyNotification::NOTIFY_ON_CHANGED);
2312 accessibilityNotificationPosition.NotifySignal().Connect(&Control::Impl::PositionOrSizeChangedCallback);
2314 accessibilityNotificationSize = mControlImpl.Self().AddPropertyNotification(Actor::Property::SIZE, StepCondition(0.01f));
2315 accessibilityNotificationSize.SetNotifyMode(PropertyNotification::NOTIFY_ON_CHANGED);
2316 accessibilityNotificationSize.NotifySignal().Connect(&Control::Impl::PositionOrSizeChangedCallback);
2318 accessibilityNotificationCulled = mControlImpl.Self().AddPropertyNotification(DevelActor::Property::CULLED, LessThanCondition(0.5f));
2319 accessibilityNotificationCulled.SetNotifyMode(PropertyNotification::NOTIFY_ON_CHANGED);
2320 accessibilityNotificationCulled.NotifySignal().Connect(&Control::Impl::CulledChangedCallback);
2322 accessibilityNotificationSet = true;
2326 void Control::Impl::AccessibilityDeregister()
2328 if(accessibilityNotificationSet)
2330 accessibilityNotificationPosition = {};
2331 accessibilityNotificationSize = {};
2332 accessibilityNotificationCulled = {};
2333 accessibilityNotificationSet = false;
2337 } // namespace Internal
2339 } // namespace Toolkit