2 * Copyright (c) 2021 Samsung Electronics Co., Ltd.
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
8 * http://www.apache.org/licenses/LICENSE-2.0
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
19 #include "control-data-impl.h"
22 #include <dali-toolkit/public-api/controls/control-impl.h>
23 #include <dali-toolkit/public-api/controls/control.h>
24 #include <dali-toolkit/public-api/dali-toolkit-common.h>
25 #include <dali/devel-api/actors/actor-devel.h>
26 #include <dali/devel-api/adaptor-framework/accessibility.h>
27 #include <dali/devel-api/common/stage.h>
28 #include <dali/devel-api/object/handle-devel.h>
29 #include <dali/devel-api/scripting/enum-helper.h>
30 #include <dali/devel-api/scripting/scripting.h>
31 #include <dali/integration-api/adaptor-framework/adaptor.h>
32 #include <dali/integration-api/debug.h>
33 #include <dali/public-api/object/object-registry.h>
34 #include <dali/public-api/object/type-registry-helper.h>
39 #include <dali-toolkit/devel-api/asset-manager/asset-manager.h>
40 #include <dali-toolkit/devel-api/controls/control-depth-index-ranges.h>
41 #include <dali-toolkit/devel-api/controls/control-devel.h>
42 #include <dali-toolkit/devel-api/controls/control-wrapper-impl.h>
43 #include <dali-toolkit/internal/styling/style-manager-impl.h>
44 #include <dali-toolkit/internal/visuals/visual-base-impl.h>
45 #include <dali-toolkit/internal/visuals/visual-string-constants.h>
46 #include <dali-toolkit/public-api/controls/image-view/image-view.h>
47 #include <dali-toolkit/public-api/focus-manager/keyboard-focus-manager.h>
48 #include <dali-toolkit/public-api/visuals/image-visual-properties.h>
49 #include <dali-toolkit/public-api/visuals/visual-properties.h>
53 const std::string READING_INFO_TYPE_NAME = "name";
54 const std::string READING_INFO_TYPE_ROLE = "role";
55 const std::string READING_INFO_TYPE_DESCRIPTION = "description";
56 const std::string READING_INFO_TYPE_STATE = "state";
57 const std::string READING_INFO_TYPE_ATTRIBUTE_NAME = "reading_info_type";
58 const std::string READING_INFO_TYPE_SEPARATOR = "|";
67 extern const Dali::Scripting::StringEnum ControlStateTable[];
68 extern const unsigned int ControlStateTableCount;
70 // Not static or anonymous - shared with other translation units
71 const Scripting::StringEnum ControlStateTable[] = {
72 {"NORMAL", Toolkit::DevelControl::NORMAL},
73 {"FOCUSED", Toolkit::DevelControl::FOCUSED},
74 {"DISABLED", Toolkit::DevelControl::DISABLED},
76 const unsigned int ControlStateTableCount = sizeof(ControlStateTable) / sizeof(ControlStateTable[0]);
80 #if defined(DEBUG_ENABLED)
81 Debug::Filter* gLogFilter = Debug::Filter::New(Debug::NoLogging, false, "LOG_CONTROL_VISUALS");
85 void Remove(Dictionary<T>& keyValues, const std::string& name)
87 keyValues.Remove(name);
90 void Remove(DictionaryKeys& keys, const std::string& name)
92 DictionaryKeys::iterator iter = std::find(keys.begin(), keys.end(), name);
93 if(iter != keys.end())
100 * Finds visual in given array, returning true if found along with the iterator for that visual as a out parameter
102 bool FindVisual(Property::Index targetIndex, const RegisteredVisualContainer& visuals, RegisteredVisualContainer::Iterator& iter)
104 for(iter = visuals.Begin(); iter != visuals.End(); iter++)
106 if((*iter)->index == targetIndex)
115 * Finds visual in given array, returning true if found along with the iterator for that visual as a out parameter
117 bool FindVisual(std::string visualName, const RegisteredVisualContainer& visuals, RegisteredVisualContainer::Iterator& iter)
119 for(iter = visuals.Begin(); iter != visuals.End(); iter++)
121 Toolkit::Visual::Base visual = (*iter)->visual;
122 if(visual && visual.GetName() == visualName)
130 void FindChangableVisuals(Dictionary<Property::Map>& stateVisualsToAdd,
131 Dictionary<Property::Map>& stateVisualsToChange,
132 DictionaryKeys& stateVisualsToRemove)
134 DictionaryKeys copyOfStateVisualsToRemove = stateVisualsToRemove;
136 for(DictionaryKeys::iterator iter = copyOfStateVisualsToRemove.begin();
137 iter != copyOfStateVisualsToRemove.end();
140 const std::string& visualName = (*iter);
141 Property::Map* toMap = stateVisualsToAdd.Find(visualName);
144 stateVisualsToChange.Add(visualName, *toMap);
145 stateVisualsToAdd.Remove(visualName);
146 Remove(stateVisualsToRemove, visualName);
151 Toolkit::Visual::Base GetVisualByName(
152 const RegisteredVisualContainer& visuals,
153 const std::string& visualName)
155 Toolkit::Visual::Base visualHandle;
157 RegisteredVisualContainer::Iterator iter;
158 for(iter = visuals.Begin(); iter != visuals.End(); iter++)
160 Toolkit::Visual::Base visual = (*iter)->visual;
161 if(visual && visual.GetName() == visualName)
163 visualHandle = visual;
170 Toolkit::Visual::Base GetVisualByIndex(
171 const RegisteredVisualContainer& visuals,
172 Property::Index index)
174 Toolkit::Visual::Base visualHandle;
176 RegisteredVisualContainer::Iterator iter;
177 for(iter = visuals.Begin(); iter != visuals.End(); iter++)
179 if((*iter)->index == index)
181 visualHandle = (*iter)->visual;
189 * Move visual from source to destination container
191 void MoveVisual(RegisteredVisualContainer::Iterator sourceIter, RegisteredVisualContainer& source, RegisteredVisualContainer& destination)
193 Toolkit::Visual::Base visual = (*sourceIter)->visual;
196 RegisteredVisual* rv = source.Release(sourceIter);
197 destination.PushBack(rv);
202 * Performs actions as requested using the action name.
203 * @param[in] object The object on which to perform the action.
204 * @param[in] actionName The action to perform.
205 * @param[in] attributes The attributes with which to perfrom this action.
206 * @return true if action has been accepted by this control
208 const char* ACTION_ACCESSIBILITY_ACTIVATED = "accessibilityActivated";
209 const char* ACTION_ACCESSIBILITY_READING_CANCELLED = "ReadingCancelled";
210 const char* ACTION_ACCESSIBILITY_READING_PAUSED = "ReadingPaused";
211 const char* ACTION_ACCESSIBILITY_READING_RESUMED = "ReadingResumed";
212 const char* ACTION_ACCESSIBILITY_READING_SKIPPED = "ReadingSkipped";
213 const char* ACTION_ACCESSIBILITY_READING_STOPPED = "ReadingStopped";
215 static bool DoAction(BaseObject* object, const std::string& actionName, const Property::Map& attributes)
219 Dali::BaseHandle handle(object);
221 Toolkit::Control control = Toolkit::Control::DownCast(handle);
223 DALI_ASSERT_ALWAYS(control);
225 if(0 == strcmp(actionName.c_str(), ACTION_ACCESSIBILITY_ACTIVATED) || actionName == "activate")
227 // if cast succeeds there is an implementation so no need to check
228 if(!DevelControl::AccessibilityActivateSignal(control).Empty())
230 DevelControl::AccessibilityActivateSignal(control).Emit();
234 ret = Internal::GetImplementation(control).OnAccessibilityActivated();
237 else if(0 == strcmp(actionName.c_str(), ACTION_ACCESSIBILITY_READING_SKIPPED))
239 // if cast succeeds there is an implementation so no need to check
240 if(!DevelControl::AccessibilityReadingSkippedSignal(control).Empty())
242 DevelControl::AccessibilityReadingSkippedSignal(control).Emit();
245 else if(0 == strcmp(actionName.c_str(), ACTION_ACCESSIBILITY_READING_PAUSED))
247 // if cast succeeds there is an implementation so no need to check
248 if(!DevelControl::AccessibilityReadingPausedSignal(control).Empty())
250 DevelControl::AccessibilityReadingPausedSignal(control).Emit();
253 else if(0 == strcmp(actionName.c_str(), ACTION_ACCESSIBILITY_READING_RESUMED))
255 // if cast succeeds there is an implementation so no need to check
256 if(!DevelControl::AccessibilityReadingResumedSignal(control).Empty())
258 DevelControl::AccessibilityReadingResumedSignal(control).Emit();
261 else if(0 == strcmp(actionName.c_str(), ACTION_ACCESSIBILITY_READING_CANCELLED))
263 // if cast succeeds there is an implementation so no need to check
264 if(!DevelControl::AccessibilityReadingCancelledSignal(control).Empty())
266 DevelControl::AccessibilityReadingCancelledSignal(control).Emit();
269 else if(0 == strcmp(actionName.c_str(), ACTION_ACCESSIBILITY_READING_STOPPED))
271 // if cast succeeds there is an implementation so no need to check
272 if(!DevelControl::AccessibilityReadingStoppedSignal(control).Empty())
274 DevelControl::AccessibilityReadingStoppedSignal(control).Emit();
285 * Connects a callback function with the object's signals.
286 * @param[in] object The object providing the signal.
287 * @param[in] tracker Used to disconnect the signal.
288 * @param[in] signalName The signal to connect to.
289 * @param[in] functor A newly allocated FunctorDelegate.
290 * @return True if the signal was connected.
291 * @post If a signal was connected, ownership of functor was passed to CallbackBase. Otherwise the caller is responsible for deleting the unused functor.
293 const char* SIGNAL_KEY_EVENT = "keyEvent";
294 const char* SIGNAL_KEY_INPUT_FOCUS_GAINED = "keyInputFocusGained";
295 const char* SIGNAL_KEY_INPUT_FOCUS_LOST = "keyInputFocusLost";
296 const char* SIGNAL_TAPPED = "tapped";
297 const char* SIGNAL_PANNED = "panned";
298 const char* SIGNAL_PINCHED = "pinched";
299 const char* SIGNAL_LONG_PRESSED = "longPressed";
300 const char* SIGNAL_GET_NAME = "getName";
301 const char* SIGNAL_GET_DESCRIPTION = "getDescription";
302 const char* SIGNAL_DO_GESTURE = "doGesture";
303 static bool DoConnectSignal(BaseObject* object, ConnectionTrackerInterface* tracker, const std::string& signalName, FunctorDelegate* functor)
305 Dali::BaseHandle handle(object);
307 bool connected(false);
308 Toolkit::Control control = Toolkit::Control::DownCast(handle);
311 Internal::Control& controlImpl(Internal::GetImplementation(control));
314 if(0 == strcmp(signalName.c_str(), SIGNAL_KEY_EVENT))
316 controlImpl.KeyEventSignal().Connect(tracker, functor);
318 else if(0 == strcmp(signalName.c_str(), SIGNAL_KEY_INPUT_FOCUS_GAINED))
320 controlImpl.KeyInputFocusGainedSignal().Connect(tracker, functor);
322 else if(0 == strcmp(signalName.c_str(), SIGNAL_KEY_INPUT_FOCUS_LOST))
324 controlImpl.KeyInputFocusLostSignal().Connect(tracker, functor);
326 else if(0 == strcmp(signalName.c_str(), SIGNAL_TAPPED))
328 controlImpl.EnableGestureDetection(GestureType::TAP);
329 controlImpl.GetTapGestureDetector().DetectedSignal().Connect(tracker, functor);
331 else if(0 == strcmp(signalName.c_str(), SIGNAL_PANNED))
333 controlImpl.EnableGestureDetection(GestureType::PAN);
334 controlImpl.GetPanGestureDetector().DetectedSignal().Connect(tracker, functor);
336 else if(0 == strcmp(signalName.c_str(), SIGNAL_PINCHED))
338 controlImpl.EnableGestureDetection(GestureType::PINCH);
339 controlImpl.GetPinchGestureDetector().DetectedSignal().Connect(tracker, functor);
341 else if(0 == strcmp(signalName.c_str(), SIGNAL_LONG_PRESSED))
343 controlImpl.EnableGestureDetection(GestureType::LONG_PRESS);
344 controlImpl.GetLongPressGestureDetector().DetectedSignal().Connect(tracker, functor);
346 else if(0 == strcmp(signalName.c_str(), SIGNAL_GET_NAME))
348 DevelControl::AccessibilityGetNameSignal(control).Connect(tracker, functor);
350 else if(0 == strcmp(signalName.c_str(), SIGNAL_GET_DESCRIPTION))
352 DevelControl::AccessibilityGetDescriptionSignal(control).Connect(tracker, functor);
354 else if(0 == strcmp(signalName.c_str(), SIGNAL_DO_GESTURE))
356 DevelControl::AccessibilityDoGestureSignal(control).Connect(tracker, functor);
363 * Creates control through type registry
367 return Internal::Control::New();
369 // Setup signals and actions using the type-registry.
370 DALI_TYPE_REGISTRATION_BEGIN(Control, CustomActor, Create);
372 // Note: Properties are registered separately below.
374 SignalConnectorType registerSignal1(typeRegistration, SIGNAL_KEY_EVENT, &DoConnectSignal);
375 SignalConnectorType registerSignal2(typeRegistration, SIGNAL_KEY_INPUT_FOCUS_GAINED, &DoConnectSignal);
376 SignalConnectorType registerSignal3(typeRegistration, SIGNAL_KEY_INPUT_FOCUS_LOST, &DoConnectSignal);
377 SignalConnectorType registerSignal4(typeRegistration, SIGNAL_TAPPED, &DoConnectSignal);
378 SignalConnectorType registerSignal5(typeRegistration, SIGNAL_PANNED, &DoConnectSignal);
379 SignalConnectorType registerSignal6(typeRegistration, SIGNAL_PINCHED, &DoConnectSignal);
380 SignalConnectorType registerSignal7(typeRegistration, SIGNAL_LONG_PRESSED, &DoConnectSignal);
381 SignalConnectorType registerSignal8(typeRegistration, SIGNAL_GET_NAME, &DoConnectSignal);
382 SignalConnectorType registerSignal9(typeRegistration, SIGNAL_GET_DESCRIPTION, &DoConnectSignal);
383 SignalConnectorType registerSignal10(typeRegistration, SIGNAL_DO_GESTURE, &DoConnectSignal);
385 TypeAction registerAction1(typeRegistration, "activate", &DoAction);
386 TypeAction registerAction2(typeRegistration, ACTION_ACCESSIBILITY_ACTIVATED, &DoAction);
387 TypeAction registerAction3(typeRegistration, ACTION_ACCESSIBILITY_READING_SKIPPED, &DoAction);
388 TypeAction registerAction4(typeRegistration, ACTION_ACCESSIBILITY_READING_CANCELLED, &DoAction);
389 TypeAction registerAction5(typeRegistration, ACTION_ACCESSIBILITY_READING_STOPPED, &DoAction);
390 TypeAction registerAction6(typeRegistration, ACTION_ACCESSIBILITY_READING_PAUSED, &DoAction);
391 TypeAction registerAction7(typeRegistration, ACTION_ACCESSIBILITY_READING_RESUMED, &DoAction);
393 DALI_TYPE_REGISTRATION_END()
396 * @brief Iterate through given container and setOffScene any visual found
398 * @param[in] container Container of visuals
399 * @param[in] parent Parent actor to remove visuals from
401 void SetVisualsOffScene(const RegisteredVisualContainer& container, Actor parent)
403 for(auto iter = container.Begin(), end = container.End(); iter != end; iter++)
407 DALI_LOG_INFO(gLogFilter, Debug::Verbose, "Control::SetOffScene Setting visual(%d) off stage\n", (*iter)->index);
408 Toolkit::GetImplementation((*iter)->visual).SetOffScene(parent);
413 } // unnamed namespace
416 // Properties registered without macro to use specific member variables.
417 const PropertyRegistration Control::Impl::PROPERTY_1(typeRegistration, "styleName", Toolkit::Control::Property::STYLE_NAME, Property::STRING, &Control::Impl::SetProperty, &Control::Impl::GetProperty);
418 const PropertyRegistration Control::Impl::PROPERTY_4(typeRegistration, "keyInputFocus", Toolkit::Control::Property::KEY_INPUT_FOCUS, Property::BOOLEAN, &Control::Impl::SetProperty, &Control::Impl::GetProperty);
419 const PropertyRegistration Control::Impl::PROPERTY_5(typeRegistration, "background", Toolkit::Control::Property::BACKGROUND, Property::MAP, &Control::Impl::SetProperty, &Control::Impl::GetProperty);
420 const PropertyRegistration Control::Impl::PROPERTY_6(typeRegistration, "margin", Toolkit::Control::Property::MARGIN, Property::EXTENTS, &Control::Impl::SetProperty, &Control::Impl::GetProperty);
421 const PropertyRegistration Control::Impl::PROPERTY_7(typeRegistration, "padding", Toolkit::Control::Property::PADDING, Property::EXTENTS, &Control::Impl::SetProperty, &Control::Impl::GetProperty);
422 const PropertyRegistration Control::Impl::PROPERTY_8(typeRegistration, "tooltip", Toolkit::DevelControl::Property::TOOLTIP, Property::MAP, &Control::Impl::SetProperty, &Control::Impl::GetProperty);
423 const PropertyRegistration Control::Impl::PROPERTY_9(typeRegistration, "state", Toolkit::DevelControl::Property::STATE, Property::STRING, &Control::Impl::SetProperty, &Control::Impl::GetProperty);
424 const PropertyRegistration Control::Impl::PROPERTY_10(typeRegistration, "subState", Toolkit::DevelControl::Property::SUB_STATE, Property::STRING, &Control::Impl::SetProperty, &Control::Impl::GetProperty);
425 const PropertyRegistration Control::Impl::PROPERTY_11(typeRegistration, "leftFocusableActorId", Toolkit::DevelControl::Property::LEFT_FOCUSABLE_ACTOR_ID, Property::INTEGER, &Control::Impl::SetProperty, &Control::Impl::GetProperty);
426 const PropertyRegistration Control::Impl::PROPERTY_12(typeRegistration, "rightFocusableActorId", Toolkit::DevelControl::Property::RIGHT_FOCUSABLE_ACTOR_ID, Property::INTEGER, &Control::Impl::SetProperty, &Control::Impl::GetProperty);
427 const PropertyRegistration Control::Impl::PROPERTY_13(typeRegistration, "upFocusableActorId", Toolkit::DevelControl::Property::UP_FOCUSABLE_ACTOR_ID, Property::INTEGER, &Control::Impl::SetProperty, &Control::Impl::GetProperty);
428 const PropertyRegistration Control::Impl::PROPERTY_14(typeRegistration, "downFocusableActorId", Toolkit::DevelControl::Property::DOWN_FOCUSABLE_ACTOR_ID, Property::INTEGER, &Control::Impl::SetProperty, &Control::Impl::GetProperty);
429 const PropertyRegistration Control::Impl::PROPERTY_15(typeRegistration, "shadow", Toolkit::DevelControl::Property::SHADOW, Property::MAP, &Control::Impl::SetProperty, &Control::Impl::GetProperty);
430 const PropertyRegistration Control::Impl::PROPERTY_16(typeRegistration, "accessibilityName", Toolkit::DevelControl::Property::ACCESSIBILITY_NAME, Property::STRING, &Control::Impl::SetProperty, &Control::Impl::GetProperty);
431 const PropertyRegistration Control::Impl::PROPERTY_17(typeRegistration, "accessibilityDescription", Toolkit::DevelControl::Property::ACCESSIBILITY_DESCRIPTION, Property::STRING, &Control::Impl::SetProperty, &Control::Impl::GetProperty);
432 const PropertyRegistration Control::Impl::PROPERTY_18(typeRegistration, "accessibilityTranslationDomain", Toolkit::DevelControl::Property::ACCESSIBILITY_TRANSLATION_DOMAIN, Property::STRING, &Control::Impl::SetProperty, &Control::Impl::GetProperty);
433 const PropertyRegistration Control::Impl::PROPERTY_19(typeRegistration, "accessibilityRole", Toolkit::DevelControl::Property::ACCESSIBILITY_ROLE, Property::INTEGER, &Control::Impl::SetProperty, &Control::Impl::GetProperty);
434 const PropertyRegistration Control::Impl::PROPERTY_20(typeRegistration, "accessibilityHighlightable", Toolkit::DevelControl::Property::ACCESSIBILITY_HIGHLIGHTABLE, Property::BOOLEAN, &Control::Impl::SetProperty, &Control::Impl::GetProperty);
435 const PropertyRegistration Control::Impl::PROPERTY_21(typeRegistration, "accessibilityAttributes", Toolkit::DevelControl::Property::ACCESSIBILITY_ATTRIBUTES, Property::MAP, &Control::Impl::SetProperty, &Control::Impl::GetProperty);
438 Control::Impl::Impl(Control& controlImpl)
439 : mControlImpl(controlImpl),
440 mState(Toolkit::DevelControl::NORMAL),
442 mLeftFocusableActorId(-1),
443 mRightFocusableActorId(-1),
444 mUpFocusableActorId(-1),
445 mDownFocusableActorId(-1),
447 mBackgroundColor(Color::TRANSPARENT),
448 mStartingPinchScale(nullptr),
450 mPadding(0, 0, 0, 0),
452 mKeyInputFocusGainedSignal(),
453 mKeyInputFocusLostSignal(),
454 mResourceReadySignal(),
455 mVisualEventSignal(),
456 mAccessibilityGetNameSignal(),
457 mAccessibilityGetDescriptionSignal(),
458 mAccessibilityDoGestureSignal(),
459 mPinchGestureDetector(),
460 mPanGestureDetector(),
461 mTapGestureDetector(),
462 mLongPressGestureDetector(),
464 mInputMethodContext(),
465 mIdleCallback(nullptr),
466 mFlags(Control::ControlBehaviour(CONTROL_BEHAVIOUR_DEFAULT)),
467 mIsKeyboardNavigationSupported(false),
468 mIsKeyboardFocusGroup(false),
469 mIsEmittingResourceReadySignal(false),
470 mNeedToEmitResourceReady(false)
472 Dali::Accessibility::Accessible::RegisterControlAccessibilityGetter(
473 [](Dali::Actor actor) -> Dali::Accessibility::Accessible* {
474 return Control::Impl::GetAccessibilityObject(actor);
477 mAccessibilityConstructor = [](Dali::Actor actor) -> std::unique_ptr<Dali::Accessibility::Accessible> {
478 return std::unique_ptr<Dali::Accessibility::Accessible>(new DevelControl::AccessibleImpl(actor, Dali::Accessibility::Role::UNKNOWN));
481 size_t length = static_cast<size_t>(Dali::Accessibility::RelationType::MAX_COUNT);
482 mAccessibilityRelations.reserve(length);
483 for(auto i = 0u; i < length; ++i)
485 mAccessibilityRelations.push_back({});
489 Control::Impl::~Impl()
491 for(auto&& iter : mVisuals)
493 StopObservingVisual(iter->visual);
496 for(auto&& iter : mRemoveVisuals)
498 StopObservingVisual(iter->visual);
501 // All gesture detectors will be destroyed so no need to disconnect.
502 delete mStartingPinchScale;
504 if(mIdleCallback && Adaptor::IsAvailable())
506 // Removes the callback from the callback manager in case the control is destroyed before the callback is executed.
507 Adaptor::Get().RemoveIdle(mIdleCallback);
511 Control::Impl& Control::Impl::Get(Internal::Control& internalControl)
513 return *internalControl.mImpl;
516 const Control::Impl& Control::Impl::Get(const Internal::Control& internalControl)
518 return *internalControl.mImpl;
521 // Gesture Detection Methods
522 void Control::Impl::PinchDetected(Actor actor, const PinchGesture& pinch)
524 mControlImpl.OnPinch(pinch);
527 void Control::Impl::PanDetected(Actor actor, const PanGesture& pan)
529 mControlImpl.OnPan(pan);
532 void Control::Impl::TapDetected(Actor actor, const TapGesture& tap)
534 mControlImpl.OnTap(tap);
537 void Control::Impl::LongPressDetected(Actor actor, const LongPressGesture& longPress)
539 mControlImpl.OnLongPress(longPress);
542 void Control::Impl::RegisterVisual(Property::Index index, Toolkit::Visual::Base& visual)
544 RegisterVisual(index, visual, VisualState::ENABLED, DepthIndexValue::NOT_SET);
547 void Control::Impl::RegisterVisual(Property::Index index, Toolkit::Visual::Base& visual, int depthIndex)
549 RegisterVisual(index, visual, VisualState::ENABLED, DepthIndexValue::SET, depthIndex);
552 void Control::Impl::RegisterVisual(Property::Index index, Toolkit::Visual::Base& visual, bool enabled)
554 RegisterVisual(index, visual, (enabled ? VisualState::ENABLED : VisualState::DISABLED), DepthIndexValue::NOT_SET);
557 void Control::Impl::RegisterVisual(Property::Index index, Toolkit::Visual::Base& visual, bool enabled, int depthIndex)
559 RegisterVisual(index, visual, (enabled ? VisualState::ENABLED : VisualState::DISABLED), DepthIndexValue::SET, depthIndex);
562 void Control::Impl::RegisterVisual(Property::Index index, Toolkit::Visual::Base& visual, VisualState::Type enabled, DepthIndexValue::Type depthIndexValueSet, int depthIndex)
564 DALI_LOG_INFO(gLogFilter, Debug::Concise, "RegisterVisual:%d \n", index);
566 bool visualReplaced(false);
567 Actor self = mControlImpl.Self();
569 // Set the depth index, if not set by caller this will be either the current visual depth, max depth of all visuals
571 int requiredDepthIndex = visual.GetDepthIndex();
573 if(depthIndexValueSet == DepthIndexValue::SET)
575 requiredDepthIndex = depthIndex;
578 // Visual replacement, existing visual should only be removed from stage when replacement ready.
579 if(!mVisuals.Empty())
581 RegisteredVisualContainer::Iterator registeredVisualsiter;
582 // Check if visual (index) is already registered, this is the current visual.
583 if(FindVisual(index, mVisuals, registeredVisualsiter))
585 Toolkit::Visual::Base& currentRegisteredVisual = (*registeredVisualsiter)->visual;
586 if(currentRegisteredVisual)
588 // Store current visual depth index as may need to set the replacement visual to same depth
589 const int currentDepthIndex = (*registeredVisualsiter)->visual.GetDepthIndex();
591 // No longer required to know if the replaced visual's resources are ready
592 StopObservingVisual(currentRegisteredVisual);
594 // If control staged and visual enabled then visuals will be swapped once ready
595 if(self.GetProperty<bool>(Actor::Property::CONNECTED_TO_SCENE) && enabled)
597 // Check if visual is currently in the process of being replaced ( is in removal container )
598 RegisteredVisualContainer::Iterator visualQueuedForRemoval;
599 if(FindVisual(index, mRemoveVisuals, visualQueuedForRemoval))
601 // Visual with same index is already in removal container so current visual pending
602 // Only the the last requested visual will be displayed so remove current visual which is staged but not ready.
603 Toolkit::GetImplementation(currentRegisteredVisual).SetOffScene(self);
604 mVisuals.Erase(registeredVisualsiter);
608 // current visual not already in removal container so add now.
609 DALI_LOG_INFO(gLogFilter, Debug::Verbose, "RegisterVisual Move current registered visual to removal Queue: %d \n", index);
610 MoveVisual(registeredVisualsiter, mVisuals, mRemoveVisuals);
615 // Control not staged or visual disabled so can just erase from registered visuals and new visual will be added later.
616 mVisuals.Erase(registeredVisualsiter);
619 // 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
620 if((depthIndexValueSet == DepthIndexValue::NOT_SET) &&
621 (visual.GetDepthIndex() == 0))
623 requiredDepthIndex = currentDepthIndex;
627 visualReplaced = true;
631 // If not set, set the name of the visual to the same name as the control's property.
632 // ( If the control has been type registered )
633 if(visual.GetName().empty())
635 // returns empty string if index is not found as long as index is not -1
636 std::string visualName = self.GetPropertyName(index);
637 if(!visualName.empty())
639 DALI_LOG_INFO(gLogFilter, Debug::Concise, "Setting visual name for property %d to %s\n", index, visualName.c_str());
640 visual.SetName(visualName);
644 if(!visualReplaced) // New registration entry
646 // 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
647 if((depthIndexValueSet == DepthIndexValue::NOT_SET) &&
648 (mVisuals.Size() > 0) &&
649 (visual.GetDepthIndex() == 0))
651 int maxDepthIndex = std::numeric_limits<int>::min();
653 RegisteredVisualContainer::ConstIterator iter;
654 const RegisteredVisualContainer::ConstIterator endIter = mVisuals.End();
655 for(iter = mVisuals.Begin(); iter != endIter; iter++)
657 const int visualDepthIndex = (*iter)->visual.GetDepthIndex();
658 if(visualDepthIndex > maxDepthIndex)
660 maxDepthIndex = visualDepthIndex;
663 ++maxDepthIndex; // Add one to the current maximum depth index so that our added visual appears on top
664 requiredDepthIndex = std::max(0, maxDepthIndex); // Start at zero if maxDepth index belongs to a background
670 // Set determined depth index
671 visual.SetDepthIndex(requiredDepthIndex);
673 // Monitor when the visual resources are ready
674 StartObservingVisual(visual);
676 DALI_LOG_INFO(gLogFilter, Debug::Concise, "New Visual registration index[%d] depth[%d]\n", index, requiredDepthIndex);
677 RegisteredVisual* newRegisteredVisual = new RegisteredVisual(index, visual, (enabled == VisualState::ENABLED ? true : false), (visualReplaced && enabled));
678 mVisuals.PushBack(newRegisteredVisual);
680 Internal::Visual::Base& visualImpl = Toolkit::GetImplementation(visual);
681 // Put on stage if enabled and the control is already on the stage
682 if((enabled == VisualState::ENABLED) && self.GetProperty<bool>(Actor::Property::CONNECTED_TO_SCENE))
684 visualImpl.SetOnScene(self);
686 else if(visualImpl.IsResourceReady()) // When not being staged, check if visual already 'ResourceReady' before it was Registered. ( Resource may have been loaded already )
688 ResourceReady(visualImpl);
692 DALI_LOG_INFO(gLogFilter, Debug::Verbose, "Control::RegisterVisual() Registered %s(%d), enabled:%s\n", visual.GetName().c_str(), index, enabled ? "true" : "false");
695 void Control::Impl::UnregisterVisual(Property::Index index)
697 RegisteredVisualContainer::Iterator iter;
698 if(FindVisual(index, mVisuals, iter))
700 // stop observing visual
701 StopObservingVisual((*iter)->visual);
703 Actor self(mControlImpl.Self());
704 Toolkit::GetImplementation((*iter)->visual).SetOffScene(self);
705 (*iter)->visual.Reset();
706 mVisuals.Erase(iter);
709 if(FindVisual(index, mRemoveVisuals, iter))
711 Actor self(mControlImpl.Self());
712 Toolkit::GetImplementation((*iter)->visual).SetOffScene(self);
713 (*iter)->pending = false;
714 (*iter)->visual.Reset();
715 mRemoveVisuals.Erase(iter);
719 Toolkit::Visual::Base Control::Impl::GetVisual(Property::Index index) const
721 RegisteredVisualContainer::Iterator iter;
722 if(FindVisual(index, mVisuals, iter))
724 return (*iter)->visual;
727 return Toolkit::Visual::Base();
730 void Control::Impl::EnableVisual(Property::Index index, bool enable)
732 DALI_LOG_INFO(gLogFilter, Debug::General, "Control::EnableVisual(%d, %s)\n", index, enable ? "T" : "F");
734 RegisteredVisualContainer::Iterator iter;
735 if(FindVisual(index, mVisuals, iter))
737 if((*iter)->enabled == enable)
739 DALI_LOG_INFO(gLogFilter, Debug::Verbose, "Control::EnableVisual Visual %s(%d) already %s\n", (*iter)->visual.GetName().c_str(), index, enable ? "enabled" : "disabled");
743 (*iter)->enabled = enable;
744 Actor parentActor = mControlImpl.Self();
745 if(mControlImpl.Self().GetProperty<bool>(Actor::Property::CONNECTED_TO_SCENE)) // If control not on Scene then Visual will be added when SceneConnection is called.
749 DALI_LOG_INFO(gLogFilter, Debug::Verbose, "Control::EnableVisual Setting %s(%d) on stage \n", (*iter)->visual.GetName().c_str(), index);
750 Toolkit::GetImplementation((*iter)->visual).SetOnScene(parentActor);
754 DALI_LOG_INFO(gLogFilter, Debug::Verbose, "Control::EnableVisual Setting %s(%d) off stage \n", (*iter)->visual.GetName().c_str(), index);
755 Toolkit::GetImplementation((*iter)->visual).SetOffScene(parentActor); // No need to call if control not staged.
761 DALI_LOG_WARNING("Control::EnableVisual(%d, %s) FAILED - NO SUCH VISUAL\n", index, enable ? "T" : "F");
765 bool Control::Impl::IsVisualEnabled(Property::Index index) const
767 RegisteredVisualContainer::Iterator iter;
768 if(FindVisual(index, mVisuals, iter))
770 return (*iter)->enabled;
775 void Control::Impl::StopObservingVisual(Toolkit::Visual::Base& visual)
777 Internal::Visual::Base& visualImpl = Toolkit::GetImplementation(visual);
779 // Stop observing the visual
780 visualImpl.RemoveEventObserver(*this);
783 void Control::Impl::StartObservingVisual(Toolkit::Visual::Base& visual)
785 Internal::Visual::Base& visualImpl = Toolkit::GetImplementation(visual);
787 // start observing the visual for events
788 visualImpl.AddEventObserver(*this);
791 // Called by a Visual when it's resource is ready
792 void Control::Impl::ResourceReady(Visual::Base& object)
794 DALI_LOG_INFO(gLogFilter, Debug::Verbose, "Control::Impl::ResourceReady() replacements pending[%d]\n", mRemoveVisuals.Count());
796 Actor self = mControlImpl.Self();
798 // A resource is ready, find resource in the registered visuals container and get its index
799 for(auto registeredIter = mVisuals.Begin(), end = mVisuals.End(); registeredIter != end; ++registeredIter)
801 Internal::Visual::Base& registeredVisualImpl = Toolkit::GetImplementation((*registeredIter)->visual);
803 if(&object == ®isteredVisualImpl)
805 RegisteredVisualContainer::Iterator visualToRemoveIter;
806 // Find visual with the same index in the removal container
807 // Set if off stage as it's replacement is now ready.
808 // Remove if from removal list as now removed from stage.
809 // Set Pending flag on the ready visual to false as now ready.
810 if(FindVisual((*registeredIter)->index, mRemoveVisuals, visualToRemoveIter))
812 (*registeredIter)->pending = false;
813 Toolkit::GetImplementation((*visualToRemoveIter)->visual).SetOffScene(self);
814 mRemoveVisuals.Erase(visualToRemoveIter);
820 // A visual is ready so control may need relayouting if staged
821 if(self.GetProperty<bool>(Actor::Property::CONNECTED_TO_SCENE))
823 mControlImpl.RelayoutRequest();
826 // Emit signal if all enabled visuals registered by the control are ready.
827 if(IsResourceReady())
830 mNeedToEmitResourceReady = false;
832 EmitResourceReadySignal();
836 void Control::Impl::NotifyVisualEvent(Visual::Base& object, Property::Index signalId)
838 for(auto registeredIter = mVisuals.Begin(), end = mVisuals.End(); registeredIter != end; ++registeredIter)
840 Internal::Visual::Base& registeredVisualImpl = Toolkit::GetImplementation((*registeredIter)->visual);
841 if(&object == ®isteredVisualImpl)
843 Dali::Toolkit::Control handle(mControlImpl.GetOwner());
844 mVisualEventSignal.Emit(handle, (*registeredIter)->index, signalId);
850 bool Control::Impl::IsResourceReady() const
852 // Iterate through and check all the enabled visuals are ready
853 for(auto visualIter = mVisuals.Begin();
854 visualIter != mVisuals.End();
857 const Toolkit::Visual::Base visual = (*visualIter)->visual;
858 const Internal::Visual::Base& visualImpl = Toolkit::GetImplementation(visual);
860 // one of the enabled visuals is not ready
861 if(!visualImpl.IsResourceReady() && (*visualIter)->enabled)
869 Toolkit::Visual::ResourceStatus Control::Impl::GetVisualResourceStatus(Property::Index index) const
871 RegisteredVisualContainer::Iterator iter;
872 if(FindVisual(index, mVisuals, iter))
874 const Toolkit::Visual::Base visual = (*iter)->visual;
875 const Internal::Visual::Base& visualImpl = Toolkit::GetImplementation(visual);
876 return visualImpl.GetResourceStatus();
879 return Toolkit::Visual::ResourceStatus::PREPARING;
882 void Control::Impl::AddTransitions(Dali::Animation& animation,
883 const Toolkit::TransitionData& handle,
884 bool createAnimation)
886 // Setup a Transition from TransitionData.
887 const Internal::TransitionData& transitionData = Toolkit::GetImplementation(handle);
888 TransitionData::Iterator end = transitionData.End();
889 for(TransitionData::Iterator iter = transitionData.Begin();
893 TransitionData::Animator* animator = (*iter);
895 Toolkit::Visual::Base visual = GetVisualByName(mVisuals, animator->objectName);
899 #if defined(DEBUG_ENABLED)
900 Dali::TypeInfo typeInfo;
901 ControlWrapper* controlWrapperImpl = dynamic_cast<ControlWrapper*>(&mControlImpl);
902 if(controlWrapperImpl)
904 typeInfo = controlWrapperImpl->GetTypeInfo();
907 DALI_LOG_INFO(gLogFilter, Debug::Concise, "CreateTransition: Found %s visual for %s\n", visual.GetName().c_str(), typeInfo ? typeInfo.GetName().c_str() : "Unknown");
909 Internal::Visual::Base& visualImpl = Toolkit::GetImplementation(visual);
910 visualImpl.AnimateProperty(animation, *animator);
914 DALI_LOG_INFO(gLogFilter, Debug::Concise, "CreateTransition: Could not find visual. Trying actors");
915 // Otherwise, try any actor children of control (Including the control)
916 Actor child = mControlImpl.Self().FindChildByName(animator->objectName);
919 Property::Index propertyIndex = child.GetPropertyIndex(animator->propertyKey);
920 if(propertyIndex != Property::INVALID_INDEX)
922 if(animator->animate == false)
924 if(animator->targetValue.GetType() != Property::NONE)
926 child.SetProperty(propertyIndex, animator->targetValue);
929 else // animate the property
931 if(animator->initialValue.GetType() != Property::NONE)
933 child.SetProperty(propertyIndex, animator->initialValue);
936 if(createAnimation && !animation)
938 animation = Dali::Animation::New(0.1f);
941 animation.AnimateTo(Property(child, propertyIndex),
942 animator->targetValue,
943 animator->alphaFunction,
944 TimePeriod(animator->timePeriodDelay,
945 animator->timePeriodDuration));
953 Dali::Animation Control::Impl::CreateTransition(const Toolkit::TransitionData& transitionData)
955 Dali::Animation transition;
957 if(transitionData.Count() > 0)
959 AddTransitions(transition, transitionData, true);
964 void Control::Impl::DoAction(Dali::Property::Index visualIndex, Dali::Property::Index actionId, const Dali::Property::Value attributes)
966 RegisteredVisualContainer::Iterator iter;
967 if(FindVisual(visualIndex, mVisuals, iter))
969 Toolkit::GetImplementation((*iter)->visual).DoAction(actionId, attributes);
973 void Control::Impl::AppendAccessibilityAttribute(const std::string& key, const std::string value)
975 Property::Value* checkedValue = mAccessibilityAttributes.Find(key);
978 mAccessibilityAttributes[key] = Property::Value(value);
982 mAccessibilityAttributes.Insert(key, value);
986 void Control::Impl::SetProperty(BaseObject* object, Property::Index index, const Property::Value& value)
988 Toolkit::Control control = Toolkit::Control::DownCast(BaseHandle(object));
992 Control& controlImpl(GetImplementation(control));
996 case Toolkit::Control::Property::STYLE_NAME:
998 controlImpl.SetStyleName(value.Get<std::string>());
1002 case Toolkit::DevelControl::Property::STATE:
1004 bool withTransitions = true;
1005 const Property::Value* valuePtr = &value;
1006 const Property::Map* map = value.GetMap();
1009 Property::Value* value2 = map->Find("withTransitions");
1012 withTransitions = value2->Get<bool>();
1015 valuePtr = map->Find("state");
1020 Toolkit::DevelControl::State state(controlImpl.mImpl->mState);
1021 if(Scripting::GetEnumerationProperty<Toolkit::DevelControl::State>(*valuePtr, ControlStateTable, ControlStateTableCount, state))
1023 controlImpl.mImpl->SetState(state, withTransitions);
1029 case Toolkit::DevelControl::Property::SUB_STATE:
1031 std::string subState;
1032 if(value.Get(subState))
1034 controlImpl.mImpl->SetSubState(subState);
1039 case Toolkit::DevelControl::Property::LEFT_FOCUSABLE_ACTOR_ID:
1042 if(value.Get(focusId))
1044 controlImpl.mImpl->mLeftFocusableActorId = focusId;
1049 case Toolkit::DevelControl::Property::RIGHT_FOCUSABLE_ACTOR_ID:
1052 if(value.Get(focusId))
1054 controlImpl.mImpl->mRightFocusableActorId = focusId;
1059 case Toolkit::DevelControl::Property::UP_FOCUSABLE_ACTOR_ID:
1062 if(value.Get(focusId))
1064 controlImpl.mImpl->mUpFocusableActorId = focusId;
1069 case Toolkit::DevelControl::Property::DOWN_FOCUSABLE_ACTOR_ID:
1072 if(value.Get(focusId))
1074 controlImpl.mImpl->mDownFocusableActorId = focusId;
1079 case Toolkit::Control::Property::KEY_INPUT_FOCUS:
1081 if(value.Get<bool>())
1083 controlImpl.SetKeyInputFocus();
1087 controlImpl.ClearKeyInputFocus();
1092 case Toolkit::Control::Property::BACKGROUND:
1096 const Property::Map* map = value.GetMap();
1097 if(map && !map->Empty())
1099 controlImpl.SetBackground(*map);
1101 else if(value.Get(url))
1103 // don't know the size to load
1104 Toolkit::Visual::Base visual = Toolkit::VisualFactory::Get().CreateVisual(url, ImageDimensions());
1107 controlImpl.mImpl->RegisterVisual(Toolkit::Control::Property::BACKGROUND, visual, DepthIndex::BACKGROUND);
1110 else if(value.Get(color))
1112 controlImpl.SetBackgroundColor(color);
1116 // The background is an empty property map, so we should clear the background
1117 controlImpl.ClearBackground();
1122 case Toolkit::Control::Property::MARGIN:
1125 if(value.Get(margin))
1127 controlImpl.mImpl->SetMargin(margin);
1132 case Toolkit::Control::Property::PADDING:
1135 if(value.Get(padding))
1137 controlImpl.mImpl->SetPadding(padding);
1142 case Toolkit::DevelControl::Property::TOOLTIP:
1144 TooltipPtr& tooltipPtr = controlImpl.mImpl->mTooltip;
1147 tooltipPtr = Tooltip::New(control);
1149 tooltipPtr->SetProperties(value);
1153 case Toolkit::DevelControl::Property::SHADOW:
1155 const Property::Map* map = value.GetMap();
1156 if(map && !map->Empty())
1158 controlImpl.mImpl->SetShadow(*map);
1162 // The shadow is an empty property map, so we should clear the shadow
1163 controlImpl.mImpl->ClearShadow();
1168 case Toolkit::DevelControl::Property::ACCESSIBILITY_NAME:
1173 controlImpl.mImpl->mAccessibilityName = name;
1174 controlImpl.mImpl->mAccessibilityNameSet = true;
1178 controlImpl.mImpl->mAccessibilityNameSet = false;
1183 case Toolkit::DevelControl::Property::ACCESSIBILITY_DESCRIPTION:
1188 controlImpl.mImpl->mAccessibilityDescription = text;
1189 controlImpl.mImpl->mAccessibilityDescriptionSet = true;
1193 controlImpl.mImpl->mAccessibilityDescriptionSet = false;
1198 case Toolkit::DevelControl::Property::ACCESSIBILITY_TRANSLATION_DOMAIN:
1203 controlImpl.mImpl->mAccessibilityTranslationDomain = text;
1204 controlImpl.mImpl->mAccessibilityTranslationDomainSet = true;
1208 controlImpl.mImpl->mAccessibilityTranslationDomainSet = false;
1213 case Toolkit::DevelControl::Property::ACCESSIBILITY_ROLE:
1215 Dali::Accessibility::Role role;
1218 controlImpl.mImpl->mAccessibilityRole = role;
1223 case Toolkit::DevelControl::Property::ACCESSIBILITY_HIGHLIGHTABLE:
1226 if(value.Get(highlightable))
1228 controlImpl.mImpl->mAccessibilityHighlightable = highlightable;
1229 controlImpl.mImpl->mAccessibilityHighlightableSet = true;
1233 controlImpl.mImpl->mAccessibilityHighlightableSet = false;
1238 case Toolkit::DevelControl::Property::ACCESSIBILITY_ATTRIBUTES:
1240 const Property::Map* map = value.GetMap();
1241 if(map && !map->Empty())
1243 controlImpl.mImpl->mAccessibilityAttributes = *map;
1251 Property::Value Control::Impl::GetProperty(BaseObject* object, Property::Index index)
1253 Property::Value value;
1255 Toolkit::Control control = Toolkit::Control::DownCast(BaseHandle(object));
1259 Control& controlImpl(GetImplementation(control));
1263 case Toolkit::Control::Property::STYLE_NAME:
1265 value = controlImpl.GetStyleName();
1269 case Toolkit::DevelControl::Property::STATE:
1271 value = controlImpl.mImpl->mState;
1275 case Toolkit::DevelControl::Property::SUB_STATE:
1277 value = controlImpl.mImpl->mSubStateName;
1281 case Toolkit::DevelControl::Property::LEFT_FOCUSABLE_ACTOR_ID:
1283 value = controlImpl.mImpl->mLeftFocusableActorId;
1287 case Toolkit::DevelControl::Property::RIGHT_FOCUSABLE_ACTOR_ID:
1289 value = controlImpl.mImpl->mRightFocusableActorId;
1293 case Toolkit::DevelControl::Property::UP_FOCUSABLE_ACTOR_ID:
1295 value = controlImpl.mImpl->mUpFocusableActorId;
1299 case Toolkit::DevelControl::Property::DOWN_FOCUSABLE_ACTOR_ID:
1301 value = controlImpl.mImpl->mDownFocusableActorId;
1305 case Toolkit::Control::Property::KEY_INPUT_FOCUS:
1307 value = controlImpl.HasKeyInputFocus();
1311 case Toolkit::Control::Property::BACKGROUND:
1314 Toolkit::Visual::Base visual = controlImpl.mImpl->GetVisual(Toolkit::Control::Property::BACKGROUND);
1317 visual.CreatePropertyMap(map);
1324 case Toolkit::Control::Property::MARGIN:
1326 value = controlImpl.mImpl->GetMargin();
1330 case Toolkit::Control::Property::PADDING:
1332 value = controlImpl.mImpl->GetPadding();
1336 case Toolkit::DevelControl::Property::TOOLTIP:
1339 if(controlImpl.mImpl->mTooltip)
1341 controlImpl.mImpl->mTooltip->CreatePropertyMap(map);
1347 case Toolkit::DevelControl::Property::SHADOW:
1350 Toolkit::Visual::Base visual = controlImpl.mImpl->GetVisual(Toolkit::DevelControl::Property::SHADOW);
1353 visual.CreatePropertyMap(map);
1360 case Toolkit::DevelControl::Property::ACCESSIBILITY_NAME:
1362 if(controlImpl.mImpl->mAccessibilityNameSet)
1364 value = controlImpl.mImpl->mAccessibilityName;
1369 case Toolkit::DevelControl::Property::ACCESSIBILITY_DESCRIPTION:
1371 if(controlImpl.mImpl->mAccessibilityDescriptionSet)
1373 value = controlImpl.mImpl->mAccessibilityDescription;
1378 case Toolkit::DevelControl::Property::ACCESSIBILITY_TRANSLATION_DOMAIN:
1380 if(controlImpl.mImpl->mAccessibilityTranslationDomainSet)
1382 value = controlImpl.mImpl->mAccessibilityTranslationDomain;
1387 case Toolkit::DevelControl::Property::ACCESSIBILITY_ROLE:
1389 value = Property::Value(controlImpl.mImpl->mAccessibilityRole);
1393 case Toolkit::DevelControl::Property::ACCESSIBILITY_HIGHLIGHTABLE:
1395 if(controlImpl.mImpl->mAccessibilityHighlightableSet)
1397 value = controlImpl.mImpl->mAccessibilityHighlightable;
1402 case Toolkit::DevelControl::Property::ACCESSIBILITY_ATTRIBUTES:
1404 value = controlImpl.mImpl->mAccessibilityAttributes;
1413 void Control::Impl::RemoveAccessibilityAttribute(const std::string& key)
1415 Property::Value* value = mAccessibilityAttributes.Find(key);
1418 mAccessibilityAttributes[key] = Property::Value();
1422 void Control::Impl::ClearAccessibilityAttributes()
1424 mAccessibilityAttributes.Clear();
1427 void Control::Impl::SetAccessibilityReadingInfoType(const Dali::Accessibility::ReadingInfoTypes types)
1429 std::string value{};
1430 if(types[Dali::Accessibility::ReadingInfoType::NAME])
1432 value += READING_INFO_TYPE_NAME;
1434 if(types[Dali::Accessibility::ReadingInfoType::ROLE])
1438 value += READING_INFO_TYPE_SEPARATOR;
1440 value += READING_INFO_TYPE_ROLE;
1442 if(types[Dali::Accessibility::ReadingInfoType::DESCRIPTION])
1446 value += READING_INFO_TYPE_SEPARATOR;
1448 value += READING_INFO_TYPE_DESCRIPTION;
1450 if(types[Dali::Accessibility::ReadingInfoType::STATE])
1454 value += READING_INFO_TYPE_SEPARATOR;
1456 value += READING_INFO_TYPE_STATE;
1458 AppendAccessibilityAttribute(READING_INFO_TYPE_ATTRIBUTE_NAME, value);
1461 Dali::Accessibility::ReadingInfoTypes Control::Impl::GetAccessibilityReadingInfoType() const
1463 std::string value{};
1464 auto place = mAccessibilityAttributes.Find(READING_INFO_TYPE_ATTRIBUTE_NAME);
1471 Dali::Accessibility::ReadingInfoTypes types;
1472 types[Dali::Accessibility::ReadingInfoType::NAME] = true;
1473 types[Dali::Accessibility::ReadingInfoType::ROLE] = true;
1474 types[Dali::Accessibility::ReadingInfoType::DESCRIPTION] = true;
1475 types[Dali::Accessibility::ReadingInfoType::STATE] = true;
1484 Dali::Accessibility::ReadingInfoTypes types;
1486 if(value.find(READING_INFO_TYPE_NAME) != std::string::npos)
1488 types[Dali::Accessibility::ReadingInfoType::NAME] = true;
1490 if(value.find(READING_INFO_TYPE_ROLE) != std::string::npos)
1492 types[Dali::Accessibility::ReadingInfoType::ROLE] = true;
1494 if(value.find(READING_INFO_TYPE_DESCRIPTION) != std::string::npos)
1496 types[Dali::Accessibility::ReadingInfoType::DESCRIPTION] = true;
1498 if(value.find(READING_INFO_TYPE_STATE) != std::string::npos)
1500 types[Dali::Accessibility::ReadingInfoType::STATE] = true;
1506 void Control::Impl::CopyInstancedProperties(RegisteredVisualContainer& visuals, Dictionary<Property::Map>& instancedProperties)
1508 for(RegisteredVisualContainer::Iterator iter = visuals.Begin(); iter != visuals.End(); iter++)
1512 Property::Map instanceMap;
1513 Toolkit::GetImplementation((*iter)->visual).CreateInstancePropertyMap(instanceMap);
1514 instancedProperties.Add((*iter)->visual.GetName(), instanceMap);
1519 void Control::Impl::RemoveVisual(RegisteredVisualContainer& visuals, const std::string& visualName)
1521 Actor self(mControlImpl.Self());
1523 for(RegisteredVisualContainer::Iterator visualIter = visuals.Begin();
1524 visualIter != visuals.End();
1527 Toolkit::Visual::Base visual = (*visualIter)->visual;
1528 if(visual && visual.GetName() == visualName)
1530 Toolkit::GetImplementation(visual).SetOffScene(self);
1531 (*visualIter)->visual.Reset();
1532 visuals.Erase(visualIter);
1538 void Control::Impl::RemoveVisuals(RegisteredVisualContainer& visuals, DictionaryKeys& removeVisuals)
1540 Actor self(mControlImpl.Self());
1541 for(DictionaryKeys::iterator iter = removeVisuals.begin(); iter != removeVisuals.end(); ++iter)
1543 const std::string visualName = *iter;
1544 RemoveVisual(visuals, visualName);
1548 void Control::Impl::RecreateChangedVisuals(Dictionary<Property::Map>& stateVisualsToChange,
1549 Dictionary<Property::Map>& instancedProperties)
1551 Dali::CustomActor handle(mControlImpl.GetOwner());
1552 for(Dictionary<Property::Map>::iterator iter = stateVisualsToChange.Begin();
1553 iter != stateVisualsToChange.End();
1556 const std::string& visualName = (*iter).key;
1557 const Property::Map& toMap = (*iter).entry;
1559 Actor self = mControlImpl.Self();
1560 RegisteredVisualContainer::Iterator registeredVisualsiter;
1561 // Check if visual (visualName) is already registered, this is the current visual.
1562 if(FindVisual(visualName, mVisuals, registeredVisualsiter))
1564 Toolkit::Visual::Base& visual = (*registeredVisualsiter)->visual;
1567 // No longer required to know if the replaced visual's resources are ready
1568 StopObservingVisual(visual);
1570 // If control staged then visuals will be swapped once ready
1571 if(self.GetProperty<bool>(Actor::Property::CONNECTED_TO_SCENE))
1573 // Check if visual is currently in the process of being replaced ( is in removal container )
1574 RegisteredVisualContainer::Iterator visualQueuedForRemoval;
1575 if(FindVisual(visualName, mRemoveVisuals, visualQueuedForRemoval))
1577 // Visual with same visual name is already in removal container so current visual pending
1578 // Only the the last requested visual will be displayed so remove current visual which is staged but not ready.
1579 Toolkit::GetImplementation(visual).SetOffScene(self);
1580 (*registeredVisualsiter)->visual.Reset();
1581 mVisuals.Erase(registeredVisualsiter);
1585 // current visual not already in removal container so add now.
1586 DALI_LOG_INFO(gLogFilter, Debug::Verbose, "RegisterVisual Move current registered visual to removal Queue: %s \n", visualName.c_str());
1587 MoveVisual(registeredVisualsiter, mVisuals, mRemoveVisuals);
1592 // Control not staged or visual disabled so can just erase from registered visuals and new visual will be added later.
1593 (*registeredVisualsiter)->visual.Reset();
1594 mVisuals.Erase(registeredVisualsiter);
1598 const Property::Map* instancedMap = instancedProperties.FindConst(visualName);
1599 Style::ApplyVisual(handle, visualName, toMap, instancedMap);
1604 void Control::Impl::ReplaceStateVisualsAndProperties(const StylePtr oldState, const StylePtr newState, const std::string& subState)
1606 // Collect all old visual names
1607 DictionaryKeys stateVisualsToRemove;
1610 oldState->visuals.GetKeys(stateVisualsToRemove);
1611 if(!subState.empty())
1613 const StylePtr* oldSubState = oldState->subStates.FindConst(subState);
1616 DictionaryKeys subStateVisualsToRemove;
1617 (*oldSubState)->visuals.GetKeys(subStateVisualsToRemove);
1618 Merge(stateVisualsToRemove, subStateVisualsToRemove);
1623 // Collect all new visual properties
1624 Dictionary<Property::Map> stateVisualsToAdd;
1627 stateVisualsToAdd = newState->visuals;
1628 if(!subState.empty())
1630 const StylePtr* newSubState = newState->subStates.FindConst(subState);
1633 stateVisualsToAdd.Merge((*newSubState)->visuals);
1638 // If a name is in both add/remove, move it to change list.
1639 Dictionary<Property::Map> stateVisualsToChange;
1640 FindChangableVisuals(stateVisualsToAdd, stateVisualsToChange, stateVisualsToRemove);
1642 // Copy instanced properties (e.g. text label) of current visuals
1643 Dictionary<Property::Map> instancedProperties;
1644 CopyInstancedProperties(mVisuals, instancedProperties);
1646 // For each visual in remove list, remove from mVisuals
1647 RemoveVisuals(mVisuals, stateVisualsToRemove);
1649 // For each visual in add list, create and add to mVisuals
1650 Dali::CustomActor handle(mControlImpl.GetOwner());
1651 Style::ApplyVisuals(handle, stateVisualsToAdd, instancedProperties);
1653 // For each visual in change list, if it requires a new visual,
1654 // remove old visual, create and add to mVisuals
1655 RecreateChangedVisuals(stateVisualsToChange, instancedProperties);
1658 void Control::Impl::SetState(DevelControl::State newState, bool withTransitions)
1660 DevelControl::State oldState = mState;
1661 Dali::CustomActor handle(mControlImpl.GetOwner());
1662 DALI_LOG_INFO(gLogFilter, Debug::Concise, "Control::Impl::SetState: %s\n", (mState == DevelControl::NORMAL ? "NORMAL" : (mState == DevelControl::FOCUSED ? "FOCUSED" : (mState == DevelControl::DISABLED ? "DISABLED" : "NONE"))));
1664 if(mState != newState)
1666 // If mState was Disabled, and new state is Focused, should probably
1667 // store that fact, e.g. in another property that FocusManager can access.
1670 // Trigger state change and transitions
1671 // Apply new style, if stylemanager is available
1672 Toolkit::StyleManager styleManager = Toolkit::StyleManager::Get();
1675 const StylePtr stylePtr = GetImpl(styleManager).GetRecordedStyle(Toolkit::Control(mControlImpl.GetOwner()));
1679 std::string oldStateName = Scripting::GetEnumerationName<Toolkit::DevelControl::State>(oldState, ControlStateTable, ControlStateTableCount);
1680 std::string newStateName = Scripting::GetEnumerationName<Toolkit::DevelControl::State>(newState, ControlStateTable, ControlStateTableCount);
1682 const StylePtr* newStateStyle = stylePtr->subStates.Find(newStateName);
1683 const StylePtr* oldStateStyle = stylePtr->subStates.Find(oldStateName);
1684 if(oldStateStyle && newStateStyle)
1686 // Only change if both state styles exist
1687 ReplaceStateVisualsAndProperties(*oldStateStyle, *newStateStyle, mSubStateName);
1694 void Control::Impl::SetSubState(const std::string& subStateName, bool withTransitions)
1696 if(mSubStateName != subStateName)
1698 // Get existing sub-state visuals, and unregister them
1699 Dali::CustomActor handle(mControlImpl.GetOwner());
1701 Toolkit::StyleManager styleManager = Toolkit::StyleManager::Get();
1704 const StylePtr stylePtr = GetImpl(styleManager).GetRecordedStyle(Toolkit::Control(mControlImpl.GetOwner()));
1708 std::string stateName = Scripting::GetEnumerationName<Toolkit::DevelControl::State>(mState, ControlStateTable, ControlStateTableCount);
1710 const StylePtr* state = stylePtr->subStates.Find(stateName);
1713 StylePtr stateStyle(*state);
1715 const StylePtr* newStateStyle = stateStyle->subStates.Find(subStateName);
1716 const StylePtr* oldStateStyle = stateStyle->subStates.Find(mSubStateName);
1717 if(oldStateStyle && newStateStyle)
1720 ReplaceStateVisualsAndProperties(*oldStateStyle, *newStateStyle, empty);
1726 mSubStateName = subStateName;
1730 void Control::Impl::OnSceneDisconnection()
1732 Actor self = mControlImpl.Self();
1734 // Any visuals set for replacement but not yet ready should still be registered.
1735 // Reason: If a request was made to register a new visual but the control removed from scene before visual was ready
1736 // then when this control appears back on stage it should use that new visual.
1738 // Iterate through all registered visuals and set off scene
1739 SetVisualsOffScene(mVisuals, self);
1741 // Visuals pending replacement can now be taken out of the removal list and set off scene
1742 // Iterate through all replacement visuals and add to a move queue then set off scene
1743 for(auto removalIter = mRemoveVisuals.Begin(), end = mRemoveVisuals.End(); removalIter != end; removalIter++)
1745 Toolkit::GetImplementation((*removalIter)->visual).SetOffScene(self);
1748 for(auto replacedIter = mVisuals.Begin(), end = mVisuals.End(); replacedIter != end; replacedIter++)
1750 (*replacedIter)->pending = false;
1753 mRemoveVisuals.Clear();
1756 void Control::Impl::SetMargin(Extents margin)
1758 mControlImpl.mImpl->mMargin = margin;
1760 // Trigger a size negotiation request that may be needed when setting a margin.
1761 mControlImpl.RelayoutRequest();
1764 Extents Control::Impl::GetMargin() const
1766 return mControlImpl.mImpl->mMargin;
1769 void Control::Impl::SetPadding(Extents padding)
1771 mControlImpl.mImpl->mPadding = padding;
1773 // Trigger a size negotiation request that may be needed when setting a padding.
1774 mControlImpl.RelayoutRequest();
1777 Extents Control::Impl::GetPadding() const
1779 return mControlImpl.mImpl->mPadding;
1782 void Control::Impl::SetInputMethodContext(InputMethodContext& inputMethodContext)
1784 mInputMethodContext = inputMethodContext;
1787 bool Control::Impl::FilterKeyEvent(const KeyEvent& event)
1789 bool consumed(false);
1791 if(mInputMethodContext)
1793 consumed = mInputMethodContext.FilterEventKey(event);
1798 DevelControl::VisualEventSignalType& Control::Impl::VisualEventSignal()
1800 return mVisualEventSignal;
1803 void Control::Impl::SetShadow(const Property::Map& map)
1805 Toolkit::Visual::Base visual = Toolkit::VisualFactory::Get().CreateVisual(map);
1806 visual.SetName("shadow");
1810 mControlImpl.mImpl->RegisterVisual(Toolkit::DevelControl::Property::SHADOW, visual, DepthIndex::BACKGROUND_EFFECT);
1812 mControlImpl.RelayoutRequest();
1816 void Control::Impl::ClearShadow()
1818 mControlImpl.mImpl->UnregisterVisual(Toolkit::DevelControl::Property::SHADOW);
1820 // Trigger a size negotiation request that may be needed when unregistering a visual.
1821 mControlImpl.RelayoutRequest();
1824 Dali::Property Control::Impl::GetVisualProperty(Dali::Property::Index index, Dali::Property::Key visualPropertyKey)
1826 Toolkit::Visual::Base visual = GetVisualByIndex(mVisuals, index);
1829 Internal::Visual::Base& visualImpl = Toolkit::GetImplementation(visual);
1830 return visualImpl.GetPropertyObject(visualPropertyKey);
1834 return Dali::Property(handle, Property::INVALID_INDEX);
1837 void Control::Impl::MakeVisualTransition(Dali::Animation& animation, Dali::Toolkit::Control source, Dali::Property::Index visualIndex, AlphaFunction alphaFunction, TimePeriod timePeriod)
1839 Dali::Toolkit::Control sourceHandle = Dali::Toolkit::Control::DownCast(source);
1840 Property::Map sourceMap = sourceHandle.GetProperty<Property::Map>(visualIndex);
1841 Dali::Toolkit::Control destinationHandle = Dali::Toolkit::Control::DownCast(mControlImpl.Self());
1842 Property::Map destinationMap = destinationHandle.GetProperty<Property::Map>(visualIndex);
1844 Vector4 mixColor(1.0f, 1.0f, 1.0f, 1.0f);
1845 Vector4 cornerRadius(0.0f, 0.0f, 0.0f, 0.0f);
1847 if(!destinationMap.Empty())
1849 static auto findValue = [](const Property::Map& map, Property::Index index) -> Vector4 {
1850 Property::Value* propertyValue = map.Find(index);
1853 return propertyValue->Get<Vector4>();
1858 mixColor = findValue(destinationMap, Dali::Toolkit::Visual::Property::MIX_COLOR);
1859 cornerRadius = findValue(destinationMap, Toolkit::DevelVisual::Property::CORNER_RADIUS);
1861 if(sourceMap.Empty())
1863 sourceMap.Insert(Toolkit::Visual::Property::TYPE, Toolkit::Visual::COLOR);
1864 sourceMap.Insert(Dali::Toolkit::Visual::Property::MIX_COLOR, Color::TRANSPARENT);
1865 sourceMap.Insert(Toolkit::DevelVisual::Property::CORNER_RADIUS, cornerRadius);
1868 Vector4 sourceMixColor = findValue(sourceMap, Dali::Toolkit::Visual::Property::MIX_COLOR);
1869 Vector4 sourceCornerRadius = findValue(sourceMap, Toolkit::DevelVisual::Property::CORNER_RADIUS);
1871 std::vector<Dali::Property> properties;
1872 std::vector<std::pair<Property::Value, Property::Value>> values;
1874 if(Vector3(sourceMixColor) != Vector3(mixColor))
1876 properties.push_back(GetVisualProperty(visualIndex, Dali::Toolkit::Visual::Property::MIX_COLOR));
1877 values.push_back(std::make_pair(Vector3(sourceMixColor), Vector3(mixColor)));
1880 if(std::abs(sourceMixColor.a - mixColor.a) > Math::MACHINE_EPSILON_1)
1882 properties.push_back(GetVisualProperty(visualIndex, Dali::Toolkit::Visual::Property::OPACITY));
1883 values.push_back(std::make_pair(sourceMixColor.a, mixColor.a));
1886 if(sourceCornerRadius != cornerRadius)
1888 properties.push_back(GetVisualProperty(visualIndex, Dali::Toolkit::DevelVisual::Property::CORNER_RADIUS));
1889 values.push_back(std::make_pair(sourceCornerRadius, cornerRadius));
1892 for(uint32_t i = 0; i < properties.size(); ++i)
1894 if(timePeriod.delaySeconds > 0.0f)
1896 Dali::KeyFrames initialKeyframes = Dali::KeyFrames::New();
1897 initialKeyframes.Add(0.0f, values[i].first);
1898 initialKeyframes.Add(1.0f, values[i].first);
1899 animation.AnimateBetween(properties[i], initialKeyframes, TimePeriod(timePeriod.delaySeconds));
1901 Dali::KeyFrames keyframes = Dali::KeyFrames::New();
1902 keyframes.Add(0.0f, values[i].first);
1903 keyframes.Add(1.0f, values[i].second);
1904 animation.AnimateBetween(properties[i], keyframes, alphaFunction, timePeriod);
1909 void Control::Impl::EmitResourceReadySignal()
1911 if(!mIsEmittingResourceReadySignal)
1913 // Guard against calls to emit the signal during the callback
1914 mIsEmittingResourceReadySignal = true;
1916 // If the signal handler changes visual, it may become ready during this call & therefore this method will
1917 // get called again recursively. If so, mNeedToEmitResourceReady is set below, and we act on it after that secondary
1918 // invocation has completed by notifying in an Idle callback to prevent further recursion.
1919 Dali::Toolkit::Control handle(mControlImpl.GetOwner());
1920 mResourceReadySignal.Emit(handle);
1922 if(mNeedToEmitResourceReady)
1924 // Add idler to emit the signal again
1927 // The callback manager takes the ownership of the callback object.
1928 mIdleCallback = MakeCallback(this, &Control::Impl::OnIdleCallback);
1929 Adaptor::Get().AddIdle(mIdleCallback, false);
1933 mIsEmittingResourceReadySignal = false;
1937 mNeedToEmitResourceReady = true;
1941 void Control::Impl::OnIdleCallback()
1943 if(mNeedToEmitResourceReady)
1946 mNeedToEmitResourceReady = false;
1948 // A visual is ready so control may need relayouting if staged
1949 if(mControlImpl.Self().GetProperty<bool>(Actor::Property::CONNECTED_TO_SCENE))
1951 mControlImpl.RelayoutRequest();
1954 EmitResourceReadySignal();
1957 // Set the pointer to null as the callback manager deletes the callback after execute it.
1958 mIdleCallback = nullptr;
1961 Dali::Accessibility::Accessible* Control::Impl::GetAccessibilityObject()
1963 if(!mAccessibilityObject)
1965 mAccessibilityObject = mAccessibilityConstructor(mControlImpl.Self());
1967 return mAccessibilityObject.get();
1970 Dali::Accessibility::Accessible* Control::Impl::GetAccessibilityObject(Dali::Actor actor)
1974 auto control = Dali::Toolkit::Control::DownCast(actor);
1977 auto controlImpl = static_cast<Internal::Control*>(&control.GetImplementation());
1978 return controlImpl->mImpl->GetAccessibilityObject();
1984 } // namespace Internal
1986 } // namespace Toolkit