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 DevelControl::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 // All gesture detectors will be destroyed so no need to disconnect.
491 delete mStartingPinchScale;
493 if(mIdleCallback && Adaptor::IsAvailable())
495 // Removes the callback from the callback manager in case the control is destroyed before the callback is executed.
496 Adaptor::Get().RemoveIdle(mIdleCallback);
500 Control::Impl& Control::Impl::Get(Internal::Control& internalControl)
502 return *internalControl.mImpl;
505 const Control::Impl& Control::Impl::Get(const Internal::Control& internalControl)
507 return *internalControl.mImpl;
510 // Gesture Detection Methods
511 void Control::Impl::PinchDetected(Actor actor, const PinchGesture& pinch)
513 mControlImpl.OnPinch(pinch);
516 void Control::Impl::PanDetected(Actor actor, const PanGesture& pan)
518 mControlImpl.OnPan(pan);
521 void Control::Impl::TapDetected(Actor actor, const TapGesture& tap)
523 mControlImpl.OnTap(tap);
526 void Control::Impl::LongPressDetected(Actor actor, const LongPressGesture& longPress)
528 mControlImpl.OnLongPress(longPress);
531 void Control::Impl::RegisterVisual(Property::Index index, Toolkit::Visual::Base& visual)
533 RegisterVisual(index, visual, VisualState::ENABLED, DepthIndexValue::NOT_SET);
536 void Control::Impl::RegisterVisual(Property::Index index, Toolkit::Visual::Base& visual, int depthIndex)
538 RegisterVisual(index, visual, VisualState::ENABLED, DepthIndexValue::SET, depthIndex);
541 void Control::Impl::RegisterVisual(Property::Index index, Toolkit::Visual::Base& visual, bool enabled)
543 RegisterVisual(index, visual, (enabled ? VisualState::ENABLED : VisualState::DISABLED), DepthIndexValue::NOT_SET);
546 void Control::Impl::RegisterVisual(Property::Index index, Toolkit::Visual::Base& visual, bool enabled, int depthIndex)
548 RegisterVisual(index, visual, (enabled ? VisualState::ENABLED : VisualState::DISABLED), DepthIndexValue::SET, depthIndex);
551 void Control::Impl::RegisterVisual(Property::Index index, Toolkit::Visual::Base& visual, VisualState::Type enabled, DepthIndexValue::Type depthIndexValueSet, int depthIndex)
553 DALI_LOG_INFO(gLogFilter, Debug::Concise, "RegisterVisual:%d \n", index);
555 bool visualReplaced(false);
556 Actor self = mControlImpl.Self();
558 // Set the depth index, if not set by caller this will be either the current visual depth, max depth of all visuals
560 int requiredDepthIndex = visual.GetDepthIndex();
562 if(depthIndexValueSet == DepthIndexValue::SET)
564 requiredDepthIndex = depthIndex;
567 // Visual replacement, existing visual should only be removed from stage when replacement ready.
568 if(!mVisuals.Empty())
570 RegisteredVisualContainer::Iterator registeredVisualsiter;
571 // Check if visual (index) is already registered, this is the current visual.
572 if(FindVisual(index, mVisuals, registeredVisualsiter))
574 Toolkit::Visual::Base& currentRegisteredVisual = (*registeredVisualsiter)->visual;
575 if(currentRegisteredVisual)
577 // Store current visual depth index as may need to set the replacement visual to same depth
578 const int currentDepthIndex = (*registeredVisualsiter)->visual.GetDepthIndex();
580 // No longer required to know if the replaced visual's resources are ready
581 StopObservingVisual(currentRegisteredVisual);
583 // If control staged and visual enabled then visuals will be swapped once ready
584 if(self.GetProperty<bool>(Actor::Property::CONNECTED_TO_SCENE) && enabled)
586 // Check if visual is currently in the process of being replaced ( is in removal container )
587 RegisteredVisualContainer::Iterator visualQueuedForRemoval;
588 if(FindVisual(index, mRemoveVisuals, visualQueuedForRemoval))
590 // Visual with same index is already in removal container so current visual pending
591 // Only the the last requested visual will be displayed so remove current visual which is staged but not ready.
592 Toolkit::GetImplementation(currentRegisteredVisual).SetOffScene(self);
593 mVisuals.Erase(registeredVisualsiter);
597 // current visual not already in removal container so add now.
598 DALI_LOG_INFO(gLogFilter, Debug::Verbose, "RegisterVisual Move current registered visual to removal Queue: %d \n", index);
599 MoveVisual(registeredVisualsiter, mVisuals, mRemoveVisuals);
604 // Control not staged or visual disabled so can just erase from registered visuals and new visual will be added later.
605 mVisuals.Erase(registeredVisualsiter);
608 // 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
609 if((depthIndexValueSet == DepthIndexValue::NOT_SET) &&
610 (visual.GetDepthIndex() == 0))
612 requiredDepthIndex = currentDepthIndex;
616 visualReplaced = true;
620 // If not set, set the name of the visual to the same name as the control's property.
621 // ( If the control has been type registered )
622 if(visual.GetName().empty())
624 // returns empty string if index is not found as long as index is not -1
625 std::string visualName = self.GetPropertyName(index);
626 if(!visualName.empty())
628 DALI_LOG_INFO(gLogFilter, Debug::Concise, "Setting visual name for property %d to %s\n", index, visualName.c_str());
629 visual.SetName(visualName);
633 if(!visualReplaced) // New registration entry
635 // 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
636 if((depthIndexValueSet == DepthIndexValue::NOT_SET) &&
637 (mVisuals.Size() > 0) &&
638 (visual.GetDepthIndex() == 0))
640 int maxDepthIndex = std::numeric_limits<int>::min();
642 RegisteredVisualContainer::ConstIterator iter;
643 const RegisteredVisualContainer::ConstIterator endIter = mVisuals.End();
644 for(iter = mVisuals.Begin(); iter != endIter; iter++)
646 const int visualDepthIndex = (*iter)->visual.GetDepthIndex();
647 if(visualDepthIndex > maxDepthIndex)
649 maxDepthIndex = visualDepthIndex;
652 ++maxDepthIndex; // Add one to the current maximum depth index so that our added visual appears on top
653 requiredDepthIndex = std::max(0, maxDepthIndex); // Start at zero if maxDepth index belongs to a background
659 // Set determined depth index
660 visual.SetDepthIndex(requiredDepthIndex);
662 // Monitor when the visual resources are ready
663 StartObservingVisual(visual);
665 DALI_LOG_INFO(gLogFilter, Debug::Concise, "New Visual registration index[%d] depth[%d]\n", index, requiredDepthIndex);
666 RegisteredVisual* newRegisteredVisual = new RegisteredVisual(index, visual, (enabled == VisualState::ENABLED ? true : false), (visualReplaced && enabled));
667 mVisuals.PushBack(newRegisteredVisual);
669 Internal::Visual::Base& visualImpl = Toolkit::GetImplementation(visual);
670 // Put on stage if enabled and the control is already on the stage
671 if((enabled == VisualState::ENABLED) && self.GetProperty<bool>(Actor::Property::CONNECTED_TO_SCENE))
673 visualImpl.SetOnScene(self);
675 else if(visualImpl.IsResourceReady()) // When not being staged, check if visual already 'ResourceReady' before it was Registered. ( Resource may have been loaded already )
677 ResourceReady(visualImpl);
681 DALI_LOG_INFO(gLogFilter, Debug::Verbose, "Control::RegisterVisual() Registered %s(%d), enabled:%s\n", visual.GetName().c_str(), index, enabled ? "true" : "false");
684 void Control::Impl::UnregisterVisual(Property::Index index)
686 RegisteredVisualContainer::Iterator iter;
687 if(FindVisual(index, mVisuals, iter))
689 // stop observing visual
690 StopObservingVisual((*iter)->visual);
692 Actor self(mControlImpl.Self());
693 Toolkit::GetImplementation((*iter)->visual).SetOffScene(self);
694 (*iter)->visual.Reset();
695 mVisuals.Erase(iter);
698 if(FindVisual(index, mRemoveVisuals, iter))
700 Actor self(mControlImpl.Self());
701 Toolkit::GetImplementation((*iter)->visual).SetOffScene(self);
702 (*iter)->pending = false;
703 (*iter)->visual.Reset();
704 mRemoveVisuals.Erase(iter);
708 Toolkit::Visual::Base Control::Impl::GetVisual(Property::Index index) const
710 RegisteredVisualContainer::Iterator iter;
711 if(FindVisual(index, mVisuals, iter))
713 return (*iter)->visual;
716 return Toolkit::Visual::Base();
719 void Control::Impl::EnableVisual(Property::Index index, bool enable)
721 DALI_LOG_INFO(gLogFilter, Debug::General, "Control::EnableVisual(%d, %s)\n", index, enable ? "T" : "F");
723 RegisteredVisualContainer::Iterator iter;
724 if(FindVisual(index, mVisuals, iter))
726 if((*iter)->enabled == enable)
728 DALI_LOG_INFO(gLogFilter, Debug::Verbose, "Control::EnableVisual Visual %s(%d) already %s\n", (*iter)->visual.GetName().c_str(), index, enable ? "enabled" : "disabled");
732 (*iter)->enabled = enable;
733 Actor parentActor = mControlImpl.Self();
734 if(mControlImpl.Self().GetProperty<bool>(Actor::Property::CONNECTED_TO_SCENE)) // If control not on Scene then Visual will be added when SceneConnection is called.
738 DALI_LOG_INFO(gLogFilter, Debug::Verbose, "Control::EnableVisual Setting %s(%d) on stage \n", (*iter)->visual.GetName().c_str(), index);
739 Toolkit::GetImplementation((*iter)->visual).SetOnScene(parentActor);
743 DALI_LOG_INFO(gLogFilter, Debug::Verbose, "Control::EnableVisual Setting %s(%d) off stage \n", (*iter)->visual.GetName().c_str(), index);
744 Toolkit::GetImplementation((*iter)->visual).SetOffScene(parentActor); // No need to call if control not staged.
750 DALI_LOG_WARNING("Control::EnableVisual(%d, %s) FAILED - NO SUCH VISUAL\n", index, enable ? "T" : "F");
754 bool Control::Impl::IsVisualEnabled(Property::Index index) const
756 RegisteredVisualContainer::Iterator iter;
757 if(FindVisual(index, mVisuals, iter))
759 return (*iter)->enabled;
764 void Control::Impl::StopObservingVisual(Toolkit::Visual::Base& visual)
766 Internal::Visual::Base& visualImpl = Toolkit::GetImplementation(visual);
768 // Stop observing the visual
769 visualImpl.RemoveEventObserver(*this);
772 void Control::Impl::StartObservingVisual(Toolkit::Visual::Base& visual)
774 Internal::Visual::Base& visualImpl = Toolkit::GetImplementation(visual);
776 // start observing the visual for events
777 visualImpl.AddEventObserver(*this);
780 // Called by a Visual when it's resource is ready
781 void Control::Impl::ResourceReady(Visual::Base& object)
783 DALI_LOG_INFO(gLogFilter, Debug::Verbose, "Control::Impl::ResourceReady() replacements pending[%d]\n", mRemoveVisuals.Count());
785 Actor self = mControlImpl.Self();
787 // A resource is ready, find resource in the registered visuals container and get its index
788 for(auto registeredIter = mVisuals.Begin(), end = mVisuals.End(); registeredIter != end; ++registeredIter)
790 Internal::Visual::Base& registeredVisualImpl = Toolkit::GetImplementation((*registeredIter)->visual);
792 if(&object == ®isteredVisualImpl)
794 RegisteredVisualContainer::Iterator visualToRemoveIter;
795 // Find visual with the same index in the removal container
796 // Set if off stage as it's replacement is now ready.
797 // Remove if from removal list as now removed from stage.
798 // Set Pending flag on the ready visual to false as now ready.
799 if(FindVisual((*registeredIter)->index, mRemoveVisuals, visualToRemoveIter))
801 (*registeredIter)->pending = false;
802 Toolkit::GetImplementation((*visualToRemoveIter)->visual).SetOffScene(self);
803 mRemoveVisuals.Erase(visualToRemoveIter);
809 // A visual is ready so control may need relayouting if staged
810 if(self.GetProperty<bool>(Actor::Property::CONNECTED_TO_SCENE))
812 mControlImpl.RelayoutRequest();
815 // Emit signal if all enabled visuals registered by the control are ready.
816 if(IsResourceReady())
819 mNeedToEmitResourceReady = false;
821 EmitResourceReadySignal();
825 void Control::Impl::NotifyVisualEvent(Visual::Base& object, Property::Index signalId)
827 for(auto registeredIter = mVisuals.Begin(), end = mVisuals.End(); registeredIter != end; ++registeredIter)
829 Internal::Visual::Base& registeredVisualImpl = Toolkit::GetImplementation((*registeredIter)->visual);
830 if(&object == ®isteredVisualImpl)
832 Dali::Toolkit::Control handle(mControlImpl.GetOwner());
833 mVisualEventSignal.Emit(handle, (*registeredIter)->index, signalId);
839 bool Control::Impl::IsResourceReady() const
841 // Iterate through and check all the enabled visuals are ready
842 for(auto visualIter = mVisuals.Begin();
843 visualIter != mVisuals.End();
846 const Toolkit::Visual::Base visual = (*visualIter)->visual;
847 const Internal::Visual::Base& visualImpl = Toolkit::GetImplementation(visual);
849 // one of the enabled visuals is not ready
850 if(!visualImpl.IsResourceReady() && (*visualIter)->enabled)
858 Toolkit::Visual::ResourceStatus Control::Impl::GetVisualResourceStatus(Property::Index index) const
860 RegisteredVisualContainer::Iterator iter;
861 if(FindVisual(index, mVisuals, iter))
863 const Toolkit::Visual::Base visual = (*iter)->visual;
864 const Internal::Visual::Base& visualImpl = Toolkit::GetImplementation(visual);
865 return visualImpl.GetResourceStatus();
868 return Toolkit::Visual::ResourceStatus::PREPARING;
871 void Control::Impl::AddTransitions(Dali::Animation& animation,
872 const Toolkit::TransitionData& handle,
873 bool createAnimation)
875 // Setup a Transition from TransitionData.
876 const Internal::TransitionData& transitionData = Toolkit::GetImplementation(handle);
877 TransitionData::Iterator end = transitionData.End();
878 for(TransitionData::Iterator iter = transitionData.Begin();
882 TransitionData::Animator* animator = (*iter);
884 Toolkit::Visual::Base visual = GetVisualByName(mVisuals, animator->objectName);
888 #if defined(DEBUG_ENABLED)
889 Dali::TypeInfo typeInfo;
890 ControlWrapper* controlWrapperImpl = dynamic_cast<ControlWrapper*>(&mControlImpl);
891 if(controlWrapperImpl)
893 typeInfo = controlWrapperImpl->GetTypeInfo();
896 DALI_LOG_INFO(gLogFilter, Debug::Concise, "CreateTransition: Found %s visual for %s\n", visual.GetName().c_str(), typeInfo ? typeInfo.GetName().c_str() : "Unknown");
898 Internal::Visual::Base& visualImpl = Toolkit::GetImplementation(visual);
899 visualImpl.AnimateProperty(animation, *animator);
903 DALI_LOG_INFO(gLogFilter, Debug::Concise, "CreateTransition: Could not find visual. Trying actors");
904 // Otherwise, try any actor children of control (Including the control)
905 Actor child = mControlImpl.Self().FindChildByName(animator->objectName);
908 Property::Index propertyIndex = child.GetPropertyIndex(animator->propertyKey);
909 if(propertyIndex != Property::INVALID_INDEX)
911 if(animator->animate == false)
913 if(animator->targetValue.GetType() != Property::NONE)
915 child.SetProperty(propertyIndex, animator->targetValue);
918 else // animate the property
920 if(animator->initialValue.GetType() != Property::NONE)
922 child.SetProperty(propertyIndex, animator->initialValue);
925 if(createAnimation && !animation)
927 animation = Dali::Animation::New(0.1f);
930 animation.AnimateTo(Property(child, propertyIndex),
931 animator->targetValue,
932 animator->alphaFunction,
933 TimePeriod(animator->timePeriodDelay,
934 animator->timePeriodDuration));
942 Dali::Animation Control::Impl::CreateTransition(const Toolkit::TransitionData& transitionData)
944 Dali::Animation transition;
946 if(transitionData.Count() > 0)
948 AddTransitions(transition, transitionData, true);
953 void Control::Impl::DoAction(Dali::Property::Index visualIndex, Dali::Property::Index actionId, const Dali::Property::Value attributes)
955 RegisteredVisualContainer::Iterator iter;
956 if(FindVisual(visualIndex, mVisuals, iter))
958 Toolkit::GetImplementation((*iter)->visual).DoAction(actionId, attributes);
962 void Control::Impl::AppendAccessibilityAttribute(const std::string& key,
963 const std::string value)
965 Property::Value* val = mAccessibilityAttributes.Find(key);
968 mAccessibilityAttributes[key] = Property::Value(value);
972 mAccessibilityAttributes.Insert(key, value);
976 void Control::Impl::SetProperty(BaseObject* object, Property::Index index, const Property::Value& value)
978 Toolkit::Control control = Toolkit::Control::DownCast(BaseHandle(object));
982 Control& controlImpl(GetImplementation(control));
986 case Toolkit::Control::Property::STYLE_NAME:
988 controlImpl.SetStyleName(value.Get<std::string>());
992 case Toolkit::DevelControl::Property::STATE:
994 bool withTransitions = true;
995 const Property::Value* valuePtr = &value;
996 const Property::Map* map = value.GetMap();
999 Property::Value* value2 = map->Find("withTransitions");
1002 withTransitions = value2->Get<bool>();
1005 valuePtr = map->Find("state");
1010 Toolkit::DevelControl::State state(controlImpl.mImpl->mState);
1011 if(Scripting::GetEnumerationProperty<Toolkit::DevelControl::State>(*valuePtr, ControlStateTable, ControlStateTableCount, state))
1013 controlImpl.mImpl->SetState(state, withTransitions);
1019 case Toolkit::DevelControl::Property::SUB_STATE:
1021 std::string subState;
1022 if(value.Get(subState))
1024 controlImpl.mImpl->SetSubState(subState);
1029 case Toolkit::DevelControl::Property::LEFT_FOCUSABLE_ACTOR_ID:
1032 if(value.Get(focusId))
1034 controlImpl.mImpl->mLeftFocusableActorId = focusId;
1039 case Toolkit::DevelControl::Property::RIGHT_FOCUSABLE_ACTOR_ID:
1042 if(value.Get(focusId))
1044 controlImpl.mImpl->mRightFocusableActorId = focusId;
1049 case Toolkit::DevelControl::Property::ACCESSIBILITY_NAME:
1054 controlImpl.mImpl->mAccessibilityName = name;
1055 controlImpl.mImpl->mAccessibilityNameSet = true;
1059 controlImpl.mImpl->mAccessibilityNameSet = false;
1064 case Toolkit::DevelControl::Property::ACCESSIBILITY_DESCRIPTION:
1069 controlImpl.mImpl->mAccessibilityDescription = txt;
1070 controlImpl.mImpl->mAccessibilityDescriptionSet = true;
1074 controlImpl.mImpl->mAccessibilityDescriptionSet = false;
1079 case Toolkit::DevelControl::Property::ACCESSIBILITY_TRANSLATION_DOMAIN:
1084 controlImpl.mImpl->mAccessibilityTranslationDomain = txt;
1085 controlImpl.mImpl->mAccessibilityTranslationDomainSet = true;
1089 controlImpl.mImpl->mAccessibilityTranslationDomainSet = false;
1094 case Toolkit::DevelControl::Property::ACCESSIBILITY_HIGHLIGHTABLE:
1097 if(value.Get(highlightable))
1099 controlImpl.mImpl->mAccessibilityHighlightable = highlightable;
1100 controlImpl.mImpl->mAccessibilityHighlightableSet = true;
1104 controlImpl.mImpl->mAccessibilityHighlightableSet = false;
1109 case Toolkit::DevelControl::Property::ACCESSIBILITY_ROLE:
1111 Dali::Accessibility::Role val;
1114 controlImpl.mImpl->mAccessibilityRole = val;
1119 case Toolkit::DevelControl::Property::UP_FOCUSABLE_ACTOR_ID:
1122 if(value.Get(focusId))
1124 controlImpl.mImpl->mUpFocusableActorId = focusId;
1129 case Toolkit::DevelControl::Property::DOWN_FOCUSABLE_ACTOR_ID:
1132 if(value.Get(focusId))
1134 controlImpl.mImpl->mDownFocusableActorId = focusId;
1139 case Toolkit::Control::Property::KEY_INPUT_FOCUS:
1141 if(value.Get<bool>())
1143 controlImpl.SetKeyInputFocus();
1147 controlImpl.ClearKeyInputFocus();
1152 case Toolkit::Control::Property::BACKGROUND:
1156 const Property::Map* map = value.GetMap();
1157 if(map && !map->Empty())
1159 controlImpl.SetBackground(*map);
1161 else if(value.Get(url))
1163 // don't know the size to load
1164 Toolkit::Visual::Base visual = Toolkit::VisualFactory::Get().CreateVisual(url, ImageDimensions());
1167 controlImpl.mImpl->RegisterVisual(Toolkit::Control::Property::BACKGROUND, visual, DepthIndex::BACKGROUND);
1170 else if(value.Get(color))
1172 controlImpl.SetBackgroundColor(color);
1176 // The background is an empty property map, so we should clear the background
1177 controlImpl.ClearBackground();
1182 case Toolkit::Control::Property::MARGIN:
1185 if(value.Get(margin))
1187 controlImpl.mImpl->SetMargin(margin);
1192 case Toolkit::Control::Property::PADDING:
1195 if(value.Get(padding))
1197 controlImpl.mImpl->SetPadding(padding);
1202 case Toolkit::DevelControl::Property::TOOLTIP:
1204 TooltipPtr& tooltipPtr = controlImpl.mImpl->mTooltip;
1207 tooltipPtr = Tooltip::New(control);
1209 tooltipPtr->SetProperties(value);
1213 case Toolkit::DevelControl::Property::SHADOW:
1215 const Property::Map* map = value.GetMap();
1216 if(map && !map->Empty())
1218 controlImpl.mImpl->SetShadow(*map);
1222 // The shadow is an empty property map, so we should clear the shadow
1223 controlImpl.mImpl->ClearShadow();
1228 case Toolkit::DevelControl::Property::ACCESSIBILITY_ATTRIBUTES:
1230 const Property::Map* map = value.GetMap();
1231 if(map && !map->Empty())
1233 controlImpl.mImpl->mAccessibilityAttributes = *map;
1238 case Toolkit::DevelControl::Property::ACCESSIBILITY_ANIMATED:
1241 if(value.Get(animated))
1243 controlImpl.mImpl->mAccessibilityAnimated = animated;
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::ACCESSIBILITY_NAME:
1295 if(controlImpl.mImpl->mAccessibilityNameSet)
1297 value = controlImpl.mImpl->mAccessibilityName;
1302 case Toolkit::DevelControl::Property::ACCESSIBILITY_DESCRIPTION:
1304 if(controlImpl.mImpl->mAccessibilityDescriptionSet)
1306 value = controlImpl.mImpl->mAccessibilityDescription;
1311 case Toolkit::DevelControl::Property::ACCESSIBILITY_TRANSLATION_DOMAIN:
1313 if(controlImpl.mImpl->mAccessibilityTranslationDomainSet)
1315 value = controlImpl.mImpl->mAccessibilityTranslationDomain;
1320 case Toolkit::DevelControl::Property::ACCESSIBILITY_HIGHLIGHTABLE:
1322 if(controlImpl.mImpl->mAccessibilityHighlightableSet)
1324 value = controlImpl.mImpl->mAccessibilityHighlightable;
1329 case Toolkit::DevelControl::Property::ACCESSIBILITY_ROLE:
1331 value = Property::Value(controlImpl.mImpl->mAccessibilityRole);
1335 case Toolkit::DevelControl::Property::UP_FOCUSABLE_ACTOR_ID:
1337 value = controlImpl.mImpl->mUpFocusableActorId;
1341 case Toolkit::DevelControl::Property::DOWN_FOCUSABLE_ACTOR_ID:
1343 value = controlImpl.mImpl->mDownFocusableActorId;
1347 case Toolkit::Control::Property::KEY_INPUT_FOCUS:
1349 value = controlImpl.HasKeyInputFocus();
1353 case Toolkit::Control::Property::BACKGROUND:
1356 Toolkit::Visual::Base visual = controlImpl.mImpl->GetVisual(Toolkit::Control::Property::BACKGROUND);
1359 visual.CreatePropertyMap(map);
1366 case Toolkit::Control::Property::MARGIN:
1368 value = controlImpl.mImpl->GetMargin();
1372 case Toolkit::Control::Property::PADDING:
1374 value = controlImpl.mImpl->GetPadding();
1378 case Toolkit::DevelControl::Property::TOOLTIP:
1381 if(controlImpl.mImpl->mTooltip)
1383 controlImpl.mImpl->mTooltip->CreatePropertyMap(map);
1389 case Toolkit::DevelControl::Property::SHADOW:
1392 Toolkit::Visual::Base visual = controlImpl.mImpl->GetVisual(Toolkit::DevelControl::Property::SHADOW);
1395 visual.CreatePropertyMap(map);
1402 case Toolkit::DevelControl::Property::ACCESSIBILITY_ATTRIBUTES:
1404 value = controlImpl.mImpl->mAccessibilityAttributes;
1408 case Toolkit::DevelControl::Property::ACCESSIBILITY_ANIMATED:
1410 value = controlImpl.mImpl->mAccessibilityAnimated;
1419 void Control::Impl::RemoveAccessibilityAttribute(const std::string& key)
1421 Property::Value* val = mAccessibilityAttributes.Find(key);
1423 mAccessibilityAttributes[key] = Property::Value();
1426 void Control::Impl::ClearAccessibilityAttributes()
1428 mAccessibilityAttributes.Clear();
1431 void Control::Impl::SetAccessibilityReadingInfoType(const Dali::Accessibility::ReadingInfoTypes types)
1434 if(types[Dali::Accessibility::ReadingInfoType::NAME])
1436 value += READING_INFO_TYPE_NAME;
1438 if(types[Dali::Accessibility::ReadingInfoType::ROLE])
1442 value += READING_INFO_TYPE_SEPARATOR;
1444 value += READING_INFO_TYPE_ROLE;
1446 if(types[Dali::Accessibility::ReadingInfoType::DESCRIPTION])
1450 value += READING_INFO_TYPE_SEPARATOR;
1452 value += READING_INFO_TYPE_DESCRIPTION;
1454 if(types[Dali::Accessibility::ReadingInfoType::STATE])
1458 value += READING_INFO_TYPE_SEPARATOR;
1460 value += READING_INFO_TYPE_STATE;
1462 AppendAccessibilityAttribute(READING_INFO_TYPE_ATTRIBUTE_NAME, value);
1465 Dali::Accessibility::ReadingInfoTypes Control::Impl::GetAccessibilityReadingInfoType() const
1468 auto place = mAccessibilityAttributes.Find(READING_INFO_TYPE_ATTRIBUTE_NAME);
1475 Dali::Accessibility::ReadingInfoTypes types;
1476 types[Dali::Accessibility::ReadingInfoType::NAME] = true;
1477 types[Dali::Accessibility::ReadingInfoType::ROLE] = true;
1478 types[Dali::Accessibility::ReadingInfoType::DESCRIPTION] = true;
1479 types[Dali::Accessibility::ReadingInfoType::STATE] = true;
1488 Dali::Accessibility::ReadingInfoTypes types;
1490 if(value.find(READING_INFO_TYPE_NAME) != std::string::npos)
1492 types[Dali::Accessibility::ReadingInfoType::NAME] = true;
1494 if(value.find(READING_INFO_TYPE_ROLE) != std::string::npos)
1496 types[Dali::Accessibility::ReadingInfoType::ROLE] = true;
1498 if(value.find(READING_INFO_TYPE_DESCRIPTION) != std::string::npos)
1500 types[Dali::Accessibility::ReadingInfoType::DESCRIPTION] = true;
1502 if(value.find(READING_INFO_TYPE_STATE) != std::string::npos)
1504 types[Dali::Accessibility::ReadingInfoType::STATE] = true;
1510 void Control::Impl::CopyInstancedProperties(RegisteredVisualContainer& visuals, Dictionary<Property::Map>& instancedProperties)
1512 for(RegisteredVisualContainer::Iterator iter = visuals.Begin(); iter != visuals.End(); iter++)
1516 Property::Map instanceMap;
1517 Toolkit::GetImplementation((*iter)->visual).CreateInstancePropertyMap(instanceMap);
1518 instancedProperties.Add((*iter)->visual.GetName(), instanceMap);
1523 void Control::Impl::RemoveVisual(RegisteredVisualContainer& visuals, const std::string& visualName)
1525 Actor self(mControlImpl.Self());
1527 for(RegisteredVisualContainer::Iterator visualIter = visuals.Begin();
1528 visualIter != visuals.End();
1531 Toolkit::Visual::Base visual = (*visualIter)->visual;
1532 if(visual && visual.GetName() == visualName)
1534 Toolkit::GetImplementation(visual).SetOffScene(self);
1535 (*visualIter)->visual.Reset();
1536 visuals.Erase(visualIter);
1542 void Control::Impl::RemoveVisuals(RegisteredVisualContainer& visuals, DictionaryKeys& removeVisuals)
1544 Actor self(mControlImpl.Self());
1545 for(DictionaryKeys::iterator iter = removeVisuals.begin(); iter != removeVisuals.end(); ++iter)
1547 const std::string visualName = *iter;
1548 RemoveVisual(visuals, visualName);
1552 void Control::Impl::RecreateChangedVisuals(Dictionary<Property::Map>& stateVisualsToChange,
1553 Dictionary<Property::Map>& instancedProperties)
1555 Dali::CustomActor handle(mControlImpl.GetOwner());
1556 for(Dictionary<Property::Map>::iterator iter = stateVisualsToChange.Begin();
1557 iter != stateVisualsToChange.End();
1560 const std::string& visualName = (*iter).key;
1561 const Property::Map& toMap = (*iter).entry;
1563 Actor self = mControlImpl.Self();
1564 RegisteredVisualContainer::Iterator registeredVisualsiter;
1565 // Check if visual (visualName) is already registered, this is the current visual.
1566 if(FindVisual(visualName, mVisuals, registeredVisualsiter))
1568 Toolkit::Visual::Base& visual = (*registeredVisualsiter)->visual;
1571 // No longer required to know if the replaced visual's resources are ready
1572 StopObservingVisual(visual);
1574 // If control staged then visuals will be swapped once ready
1575 if(self.GetProperty<bool>(Actor::Property::CONNECTED_TO_SCENE))
1577 // Check if visual is currently in the process of being replaced ( is in removal container )
1578 RegisteredVisualContainer::Iterator visualQueuedForRemoval;
1579 if(FindVisual(visualName, mRemoveVisuals, visualQueuedForRemoval))
1581 // Visual with same visual name is already in removal container so current visual pending
1582 // Only the the last requested visual will be displayed so remove current visual which is staged but not ready.
1583 Toolkit::GetImplementation(visual).SetOffScene(self);
1584 (*registeredVisualsiter)->visual.Reset();
1585 mVisuals.Erase(registeredVisualsiter);
1589 // current visual not already in removal container so add now.
1590 DALI_LOG_INFO(gLogFilter, Debug::Verbose, "RegisterVisual Move current registered visual to removal Queue: %s \n", visualName.c_str());
1591 MoveVisual(registeredVisualsiter, mVisuals, mRemoveVisuals);
1596 // Control not staged or visual disabled so can just erase from registered visuals and new visual will be added later.
1597 (*registeredVisualsiter)->visual.Reset();
1598 mVisuals.Erase(registeredVisualsiter);
1602 const Property::Map* instancedMap = instancedProperties.FindConst(visualName);
1603 Style::ApplyVisual(handle, visualName, toMap, instancedMap);
1608 void Control::Impl::ReplaceStateVisualsAndProperties(const StylePtr oldState, const StylePtr newState, const std::string& subState)
1610 // Collect all old visual names
1611 DictionaryKeys stateVisualsToRemove;
1614 oldState->visuals.GetKeys(stateVisualsToRemove);
1615 if(!subState.empty())
1617 const StylePtr* oldSubState = oldState->subStates.FindConst(subState);
1620 DictionaryKeys subStateVisualsToRemove;
1621 (*oldSubState)->visuals.GetKeys(subStateVisualsToRemove);
1622 Merge(stateVisualsToRemove, subStateVisualsToRemove);
1627 // Collect all new visual properties
1628 Dictionary<Property::Map> stateVisualsToAdd;
1631 stateVisualsToAdd = newState->visuals;
1632 if(!subState.empty())
1634 const StylePtr* newSubState = newState->subStates.FindConst(subState);
1637 stateVisualsToAdd.Merge((*newSubState)->visuals);
1642 // If a name is in both add/remove, move it to change list.
1643 Dictionary<Property::Map> stateVisualsToChange;
1644 FindChangableVisuals(stateVisualsToAdd, stateVisualsToChange, stateVisualsToRemove);
1646 // Copy instanced properties (e.g. text label) of current visuals
1647 Dictionary<Property::Map> instancedProperties;
1648 CopyInstancedProperties(mVisuals, instancedProperties);
1650 // For each visual in remove list, remove from mVisuals
1651 RemoveVisuals(mVisuals, stateVisualsToRemove);
1653 // For each visual in add list, create and add to mVisuals
1654 Dali::CustomActor handle(mControlImpl.GetOwner());
1655 Style::ApplyVisuals(handle, stateVisualsToAdd, instancedProperties);
1657 // For each visual in change list, if it requires a new visual,
1658 // remove old visual, create and add to mVisuals
1659 RecreateChangedVisuals(stateVisualsToChange, instancedProperties);
1662 void Control::Impl::SetState(DevelControl::State newState, bool withTransitions)
1664 DevelControl::State oldState = mState;
1665 Dali::CustomActor handle(mControlImpl.GetOwner());
1666 DALI_LOG_INFO(gLogFilter, Debug::Concise, "Control::Impl::SetState: %s\n", (mState == DevelControl::NORMAL ? "NORMAL" : (mState == DevelControl::FOCUSED ? "FOCUSED" : (mState == DevelControl::DISABLED ? "DISABLED" : "NONE"))));
1668 if(mState != newState)
1670 // If mState was Disabled, and new state is Focused, should probably
1671 // store that fact, e.g. in another property that FocusManager can access.
1674 // Trigger state change and transitions
1675 // Apply new style, if stylemanager is available
1676 Toolkit::StyleManager styleManager = Toolkit::StyleManager::Get();
1679 const StylePtr stylePtr = GetImpl(styleManager).GetRecordedStyle(Toolkit::Control(mControlImpl.GetOwner()));
1683 std::string oldStateName = Scripting::GetEnumerationName<Toolkit::DevelControl::State>(oldState, ControlStateTable, ControlStateTableCount);
1684 std::string newStateName = Scripting::GetEnumerationName<Toolkit::DevelControl::State>(newState, ControlStateTable, ControlStateTableCount);
1686 const StylePtr* newStateStyle = stylePtr->subStates.Find(newStateName);
1687 const StylePtr* oldStateStyle = stylePtr->subStates.Find(oldStateName);
1688 if(oldStateStyle && newStateStyle)
1690 // Only change if both state styles exist
1691 ReplaceStateVisualsAndProperties(*oldStateStyle, *newStateStyle, mSubStateName);
1698 void Control::Impl::SetSubState(const std::string& subStateName, bool withTransitions)
1700 if(mSubStateName != subStateName)
1702 // Get existing sub-state visuals, and unregister them
1703 Dali::CustomActor handle(mControlImpl.GetOwner());
1705 Toolkit::StyleManager styleManager = Toolkit::StyleManager::Get();
1708 const StylePtr stylePtr = GetImpl(styleManager).GetRecordedStyle(Toolkit::Control(mControlImpl.GetOwner()));
1712 std::string stateName = Scripting::GetEnumerationName<Toolkit::DevelControl::State>(mState, ControlStateTable, ControlStateTableCount);
1714 const StylePtr* state = stylePtr->subStates.Find(stateName);
1717 StylePtr stateStyle(*state);
1719 const StylePtr* newStateStyle = stateStyle->subStates.Find(subStateName);
1720 const StylePtr* oldStateStyle = stateStyle->subStates.Find(mSubStateName);
1721 if(oldStateStyle && newStateStyle)
1724 ReplaceStateVisualsAndProperties(*oldStateStyle, *newStateStyle, empty);
1730 mSubStateName = subStateName;
1734 void Control::Impl::OnSceneDisconnection()
1736 Actor self = mControlImpl.Self();
1738 // Any visuals set for replacement but not yet ready should still be registered.
1739 // Reason: If a request was made to register a new visual but the control removed from scene before visual was ready
1740 // then when this control appears back on stage it should use that new visual.
1742 // Iterate through all registered visuals and set off scene
1743 SetVisualsOffScene(mVisuals, self);
1745 // Visuals pending replacement can now be taken out of the removal list and set off scene
1746 // Iterate through all replacement visuals and add to a move queue then set off scene
1747 for(auto removalIter = mRemoveVisuals.Begin(), end = mRemoveVisuals.End(); removalIter != end; removalIter++)
1749 Toolkit::GetImplementation((*removalIter)->visual).SetOffScene(self);
1752 for(auto replacedIter = mVisuals.Begin(), end = mVisuals.End(); replacedIter != end; replacedIter++)
1754 (*replacedIter)->pending = false;
1757 mRemoveVisuals.Clear();
1760 void Control::Impl::SetMargin(Extents margin)
1762 mControlImpl.mImpl->mMargin = margin;
1764 // Trigger a size negotiation request that may be needed when setting a margin.
1765 mControlImpl.RelayoutRequest();
1768 Extents Control::Impl::GetMargin() const
1770 return mControlImpl.mImpl->mMargin;
1773 void Control::Impl::SetPadding(Extents padding)
1775 mControlImpl.mImpl->mPadding = padding;
1777 // Trigger a size negotiation request that may be needed when setting a padding.
1778 mControlImpl.RelayoutRequest();
1781 Extents Control::Impl::GetPadding() const
1783 return mControlImpl.mImpl->mPadding;
1786 void Control::Impl::SetInputMethodContext(InputMethodContext& inputMethodContext)
1788 mInputMethodContext = inputMethodContext;
1791 bool Control::Impl::FilterKeyEvent(const KeyEvent& event)
1793 bool consumed(false);
1795 if(mInputMethodContext)
1797 consumed = mInputMethodContext.FilterEventKey(event);
1802 DevelControl::VisualEventSignalType& Control::Impl::VisualEventSignal()
1804 return mVisualEventSignal;
1807 void Control::Impl::SetShadow(const Property::Map& map)
1809 Toolkit::Visual::Base visual = Toolkit::VisualFactory::Get().CreateVisual(map);
1810 visual.SetName("shadow");
1814 mControlImpl.mImpl->RegisterVisual(Toolkit::DevelControl::Property::SHADOW, visual, DepthIndex::BACKGROUND_EFFECT);
1816 mControlImpl.RelayoutRequest();
1820 void Control::Impl::ClearShadow()
1822 mControlImpl.mImpl->UnregisterVisual(Toolkit::DevelControl::Property::SHADOW);
1824 // Trigger a size negotiation request that may be needed when unregistering a visual.
1825 mControlImpl.RelayoutRequest();
1828 Dali::Property Control::Impl::GetVisualProperty(Dali::Property::Index index, Dali::Property::Key visualPropertyKey)
1830 Toolkit::Visual::Base visual = GetVisualByIndex(mVisuals, index);
1833 Internal::Visual::Base& visualImpl = Toolkit::GetImplementation(visual);
1834 return visualImpl.GetPropertyObject(visualPropertyKey);
1838 return Dali::Property(handle, Property::INVALID_INDEX);
1841 void Control::Impl::EmitResourceReadySignal()
1843 if(!mIsEmittingResourceReadySignal)
1845 // Guard against calls to emit the signal during the callback
1846 mIsEmittingResourceReadySignal = true;
1848 // If the signal handler changes visual, it may become ready during this call & therefore this method will
1849 // get called again recursively. If so, mNeedToEmitResourceReady is set below, and we act on it after that secondary
1850 // invocation has completed by notifying in an Idle callback to prevent further recursion.
1851 Dali::Toolkit::Control handle(mControlImpl.GetOwner());
1852 mResourceReadySignal.Emit(handle);
1854 if(mNeedToEmitResourceReady)
1856 // Add idler to emit the signal again
1859 // The callback manager takes the ownership of the callback object.
1860 mIdleCallback = MakeCallback(this, &Control::Impl::OnIdleCallback);
1861 Adaptor::Get().AddIdle(mIdleCallback, false);
1865 mIsEmittingResourceReadySignal = false;
1869 mNeedToEmitResourceReady = true;
1873 void Control::Impl::OnIdleCallback()
1875 if(mNeedToEmitResourceReady)
1878 mNeedToEmitResourceReady = false;
1880 // A visual is ready so control may need relayouting if staged
1881 if(mControlImpl.Self().GetProperty<bool>(Actor::Property::CONNECTED_TO_SCENE))
1883 mControlImpl.RelayoutRequest();
1886 EmitResourceReadySignal();
1889 // Set the pointer to null as the callback manager deletes the callback after execute it.
1890 mIdleCallback = nullptr;
1893 Dali::Accessibility::Accessible* Control::Impl::GetAccessibilityObject()
1895 if(!accessibilityObject)
1896 accessibilityObject = accessibilityConstructor(mControlImpl.Self());
1897 return accessibilityObject.get();
1900 Dali::Accessibility::Accessible* Control::Impl::GetAccessibilityObject(Dali::Actor actor)
1904 auto q = Dali::Toolkit::Control::DownCast(actor);
1907 auto q2 = static_cast<Internal::Control*>(&q.GetImplementation());
1908 return q2->mImpl->GetAccessibilityObject();
1914 void Control::Impl::PositionOrSizeChangedCallback(PropertyNotification& p)
1916 auto self = Dali::Actor::DownCast(p.GetTarget());
1917 if(Dali::Accessibility::IsUp() && !self.GetProperty(Toolkit::DevelControl::Property::ACCESSIBILITY_ANIMATED).Get<bool>())
1919 auto extents = DevelActor::CalculateScreenExtents(self);
1920 Dali::Accessibility::Accessible::Get(self)->EmitBoundsChanged(extents);
1924 void Control::Impl::CulledChangedCallback(PropertyNotification& p)
1926 if(Dali::Accessibility::IsUp())
1928 auto self = Dali::Actor::DownCast(p.GetTarget());
1929 Dali::Accessibility::Accessible::Get(self)->EmitShowing(!self.GetProperty(DevelActor::Property::CULLED).Get<bool>());
1933 void Control::Impl::AccessibilityRegister()
1935 if(!accessibilityNotificationSet)
1937 accessibilityNotificationPosition = mControlImpl.Self().AddPropertyNotification(Actor::Property::POSITION, StepCondition(0.01f));
1938 accessibilityNotificationPosition.SetNotifyMode(PropertyNotification::NOTIFY_ON_CHANGED);
1939 accessibilityNotificationPosition.NotifySignal().Connect(&Control::Impl::PositionOrSizeChangedCallback);
1941 accessibilityNotificationSize = mControlImpl.Self().AddPropertyNotification(Actor::Property::SIZE, StepCondition(0.01f));
1942 accessibilityNotificationSize.SetNotifyMode(PropertyNotification::NOTIFY_ON_CHANGED);
1943 accessibilityNotificationSize.NotifySignal().Connect(&Control::Impl::PositionOrSizeChangedCallback);
1945 accessibilityNotificationCulled = mControlImpl.Self().AddPropertyNotification(DevelActor::Property::CULLED, LessThanCondition(0.5f));
1946 accessibilityNotificationCulled.SetNotifyMode(PropertyNotification::NOTIFY_ON_CHANGED);
1947 accessibilityNotificationCulled.NotifySignal().Connect(&Control::Impl::CulledChangedCallback);
1949 accessibilityNotificationSet = true;
1953 void Control::Impl::AccessibilityDeregister(bool remove)
1955 if(accessibilityNotificationSet)
1957 accessibilityNotificationPosition.NotifySignal().Disconnect(&Control::Impl::PositionOrSizeChangedCallback);
1960 mControlImpl.Self().RemovePropertyNotification(accessibilityNotificationPosition);
1962 accessibilityNotificationPosition.Reset();
1963 accessibilityNotificationPosition = {};
1965 accessibilityNotificationSize.NotifySignal().Disconnect(&Control::Impl::PositionOrSizeChangedCallback);
1968 mControlImpl.Self().RemovePropertyNotification(accessibilityNotificationSize);
1970 accessibilityNotificationSize.Reset();
1971 accessibilityNotificationSize = {};
1973 accessibilityNotificationCulled.NotifySignal().Disconnect(&Control::Impl::CulledChangedCallback);
1976 mControlImpl.Self().RemovePropertyNotification(accessibilityNotificationCulled);
1978 accessibilityNotificationCulled.Reset();
1979 accessibilityNotificationCulled = {};
1980 accessibilityNotificationSet = false;
1984 } // namespace Internal
1986 } // namespace Toolkit