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),
455 mAutofillContainer(),
456 mFlags(Control::ControlBehaviour(CONTROL_BEHAVIOUR_DEFAULT)),
457 mIsKeyboardNavigationSupported(false),
458 mIsKeyboardFocusGroup(false),
459 mIsEmittingResourceReadySignal(false),
460 mNeedToEmitResourceReady(false),
461 mIsAutofillEnabled(false)
463 Dali::Accessibility::Accessible::RegisterControlAccessibilityGetter(
464 [](Dali::Actor actor) -> Dali::Accessibility::Accessible* {
465 return Control::Impl::GetAccessibilityObject(actor);
468 accessibilityConstructor = [](Dali::Actor actor) -> std::unique_ptr<Dali::Accessibility::Accessible> {
469 return std::unique_ptr<Dali::Accessibility::Accessible>(new DevelControl::AccessibleImpl(actor,
470 Dali::Accessibility::Role::UNKNOWN));
473 size_t len = static_cast<size_t>(Dali::Accessibility::RelationType::MAX_COUNT);
474 mAccessibilityRelations.reserve(len);
475 for(auto i = 0u; i < len; ++i)
477 mAccessibilityRelations.push_back({});
481 Control::Impl::~Impl()
483 for(auto&& iter : mVisuals)
485 StopObservingVisual(iter->visual);
488 for(auto&& iter : mRemoveVisuals)
490 StopObservingVisual(iter->visual);
493 AccessibilityDeregister(false);
494 // All gesture detectors will be destroyed so no need to disconnect.
495 delete mStartingPinchScale;
497 if(mIdleCallback && Adaptor::IsAvailable())
499 // Removes the callback from the callback manager in case the control is destroyed before the callback is executed.
500 Adaptor::Get().RemoveIdle(mIdleCallback);
504 Control::Impl& Control::Impl::Get(Internal::Control& internalControl)
506 return *internalControl.mImpl;
509 const Control::Impl& Control::Impl::Get(const Internal::Control& internalControl)
511 return *internalControl.mImpl;
514 // Gesture Detection Methods
515 void Control::Impl::PinchDetected(Actor actor, const PinchGesture& pinch)
517 mControlImpl.OnPinch(pinch);
520 void Control::Impl::PanDetected(Actor actor, const PanGesture& pan)
522 mControlImpl.OnPan(pan);
525 void Control::Impl::TapDetected(Actor actor, const TapGesture& tap)
527 mControlImpl.OnTap(tap);
530 void Control::Impl::LongPressDetected(Actor actor, const LongPressGesture& longPress)
532 mControlImpl.OnLongPress(longPress);
535 void Control::Impl::RegisterVisual(Property::Index index, Toolkit::Visual::Base& visual)
537 RegisterVisual(index, visual, VisualState::ENABLED, DepthIndexValue::NOT_SET);
540 void Control::Impl::RegisterVisual(Property::Index index, Toolkit::Visual::Base& visual, int depthIndex)
542 RegisterVisual(index, visual, VisualState::ENABLED, DepthIndexValue::SET, depthIndex);
545 void Control::Impl::RegisterVisual(Property::Index index, Toolkit::Visual::Base& visual, bool enabled)
547 RegisterVisual(index, visual, (enabled ? VisualState::ENABLED : VisualState::DISABLED), DepthIndexValue::NOT_SET);
550 void Control::Impl::RegisterVisual(Property::Index index, Toolkit::Visual::Base& visual, bool enabled, int depthIndex)
552 RegisterVisual(index, visual, (enabled ? VisualState::ENABLED : VisualState::DISABLED), DepthIndexValue::SET, depthIndex);
555 void Control::Impl::RegisterVisual(Property::Index index, Toolkit::Visual::Base& visual, VisualState::Type enabled, DepthIndexValue::Type depthIndexValueSet, int depthIndex)
557 DALI_LOG_INFO(gLogFilter, Debug::Concise, "RegisterVisual:%d \n", index);
559 bool visualReplaced(false);
560 Actor self = mControlImpl.Self();
562 // Set the depth index, if not set by caller this will be either the current visual depth, max depth of all visuals
564 int requiredDepthIndex = visual.GetDepthIndex();
566 if(depthIndexValueSet == DepthIndexValue::SET)
568 requiredDepthIndex = depthIndex;
571 // Visual replacement, existing visual should only be removed from stage when replacement ready.
572 if(!mVisuals.Empty())
574 RegisteredVisualContainer::Iterator registeredVisualsiter;
575 // Check if visual (index) is already registered, this is the current visual.
576 if(FindVisual(index, mVisuals, registeredVisualsiter))
578 Toolkit::Visual::Base& currentRegisteredVisual = (*registeredVisualsiter)->visual;
579 if(currentRegisteredVisual)
581 // Store current visual depth index as may need to set the replacement visual to same depth
582 const int currentDepthIndex = (*registeredVisualsiter)->visual.GetDepthIndex();
584 // No longer required to know if the replaced visual's resources are ready
585 StopObservingVisual(currentRegisteredVisual);
587 // If control staged and visual enabled then visuals will be swapped once ready
588 if(self.GetProperty<bool>(Actor::Property::CONNECTED_TO_SCENE) && enabled)
590 // Check if visual is currently in the process of being replaced ( is in removal container )
591 RegisteredVisualContainer::Iterator visualQueuedForRemoval;
592 if(FindVisual(index, mRemoveVisuals, visualQueuedForRemoval))
594 // Visual with same index is already in removal container so current visual pending
595 // Only the the last requested visual will be displayed so remove current visual which is staged but not ready.
596 Toolkit::GetImplementation(currentRegisteredVisual).SetOffScene(self);
597 mVisuals.Erase(registeredVisualsiter);
601 // current visual not already in removal container so add now.
602 DALI_LOG_INFO(gLogFilter, Debug::Verbose, "RegisterVisual Move current registered visual to removal Queue: %d \n", index);
603 MoveVisual(registeredVisualsiter, mVisuals, mRemoveVisuals);
608 // Control not staged or visual disabled so can just erase from registered visuals and new visual will be added later.
609 mVisuals.Erase(registeredVisualsiter);
612 // 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
613 if((depthIndexValueSet == DepthIndexValue::NOT_SET) &&
614 (visual.GetDepthIndex() == 0))
616 requiredDepthIndex = currentDepthIndex;
620 visualReplaced = true;
624 // If not set, set the name of the visual to the same name as the control's property.
625 // ( If the control has been type registered )
626 if(visual.GetName().empty())
628 // returns empty string if index is not found as long as index is not -1
629 std::string visualName = self.GetPropertyName(index);
630 if(!visualName.empty())
632 DALI_LOG_INFO(gLogFilter, Debug::Concise, "Setting visual name for property %d to %s\n", index, visualName.c_str());
633 visual.SetName(visualName);
637 if(!visualReplaced) // New registration entry
639 // 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
640 if((depthIndexValueSet == DepthIndexValue::NOT_SET) &&
641 (mVisuals.Size() > 0) &&
642 (visual.GetDepthIndex() == 0))
644 int maxDepthIndex = std::numeric_limits<int>::min();
646 RegisteredVisualContainer::ConstIterator iter;
647 const RegisteredVisualContainer::ConstIterator endIter = mVisuals.End();
648 for(iter = mVisuals.Begin(); iter != endIter; iter++)
650 const int visualDepthIndex = (*iter)->visual.GetDepthIndex();
651 if(visualDepthIndex > maxDepthIndex)
653 maxDepthIndex = visualDepthIndex;
656 ++maxDepthIndex; // Add one to the current maximum depth index so that our added visual appears on top
657 requiredDepthIndex = std::max(0, maxDepthIndex); // Start at zero if maxDepth index belongs to a background
663 // Set determined depth index
664 visual.SetDepthIndex(requiredDepthIndex);
666 // Monitor when the visual resources are ready
667 StartObservingVisual(visual);
669 DALI_LOG_INFO(gLogFilter, Debug::Concise, "New Visual registration index[%d] depth[%d]\n", index, requiredDepthIndex);
670 RegisteredVisual* newRegisteredVisual = new RegisteredVisual(index, visual, (enabled == VisualState::ENABLED ? true : false), (visualReplaced && enabled));
671 mVisuals.PushBack(newRegisteredVisual);
673 Internal::Visual::Base& visualImpl = Toolkit::GetImplementation(visual);
674 // Put on stage if enabled and the control is already on the stage
675 if((enabled == VisualState::ENABLED) && self.GetProperty<bool>(Actor::Property::CONNECTED_TO_SCENE))
677 visualImpl.SetOnScene(self);
679 else if(visualImpl.IsResourceReady()) // When not being staged, check if visual already 'ResourceReady' before it was Registered. ( Resource may have been loaded already )
681 ResourceReady(visualImpl);
685 DALI_LOG_INFO(gLogFilter, Debug::Verbose, "Control::RegisterVisual() Registered %s(%d), enabled:%s\n", visual.GetName().c_str(), index, enabled ? "true" : "false");
688 void Control::Impl::UnregisterVisual(Property::Index index)
690 RegisteredVisualContainer::Iterator iter;
691 if(FindVisual(index, mVisuals, iter))
693 // stop observing visual
694 StopObservingVisual((*iter)->visual);
696 Actor self(mControlImpl.Self());
697 Toolkit::GetImplementation((*iter)->visual).SetOffScene(self);
698 (*iter)->visual.Reset();
699 mVisuals.Erase(iter);
702 if(FindVisual(index, mRemoveVisuals, iter))
704 Actor self(mControlImpl.Self());
705 Toolkit::GetImplementation((*iter)->visual).SetOffScene(self);
706 (*iter)->pending = false;
707 (*iter)->visual.Reset();
708 mRemoveVisuals.Erase(iter);
712 Toolkit::Visual::Base Control::Impl::GetVisual(Property::Index index) const
714 RegisteredVisualContainer::Iterator iter;
715 if(FindVisual(index, mVisuals, iter))
717 return (*iter)->visual;
720 return Toolkit::Visual::Base();
723 void Control::Impl::EnableVisual(Property::Index index, bool enable)
725 DALI_LOG_INFO(gLogFilter, Debug::General, "Control::EnableVisual(%d, %s)\n", index, enable ? "T" : "F");
727 RegisteredVisualContainer::Iterator iter;
728 if(FindVisual(index, mVisuals, iter))
730 if((*iter)->enabled == enable)
732 DALI_LOG_INFO(gLogFilter, Debug::Verbose, "Control::EnableVisual Visual %s(%d) already %s\n", (*iter)->visual.GetName().c_str(), index, enable ? "enabled" : "disabled");
736 (*iter)->enabled = enable;
737 Actor parentActor = mControlImpl.Self();
738 if(mControlImpl.Self().GetProperty<bool>(Actor::Property::CONNECTED_TO_SCENE)) // If control not on Scene then Visual will be added when SceneConnection is called.
742 DALI_LOG_INFO(gLogFilter, Debug::Verbose, "Control::EnableVisual Setting %s(%d) on stage \n", (*iter)->visual.GetName().c_str(), index);
743 Toolkit::GetImplementation((*iter)->visual).SetOnScene(parentActor);
747 DALI_LOG_INFO(gLogFilter, Debug::Verbose, "Control::EnableVisual Setting %s(%d) off stage \n", (*iter)->visual.GetName().c_str(), index);
748 Toolkit::GetImplementation((*iter)->visual).SetOffScene(parentActor); // No need to call if control not staged.
754 DALI_LOG_WARNING("Control::EnableVisual(%d, %s) FAILED - NO SUCH VISUAL\n", index, enable ? "T" : "F");
758 bool Control::Impl::IsVisualEnabled(Property::Index index) const
760 RegisteredVisualContainer::Iterator iter;
761 if(FindVisual(index, mVisuals, iter))
763 return (*iter)->enabled;
768 void Control::Impl::StopObservingVisual(Toolkit::Visual::Base& visual)
770 Internal::Visual::Base& visualImpl = Toolkit::GetImplementation(visual);
772 // Stop observing the visual
773 visualImpl.RemoveEventObserver(*this);
776 void Control::Impl::StartObservingVisual(Toolkit::Visual::Base& visual)
778 Internal::Visual::Base& visualImpl = Toolkit::GetImplementation(visual);
780 // start observing the visual for events
781 visualImpl.AddEventObserver(*this);
784 // Called by a Visual when it's resource is ready
785 void Control::Impl::ResourceReady(Visual::Base& object)
787 DALI_LOG_INFO(gLogFilter, Debug::Verbose, "Control::Impl::ResourceReady() replacements pending[%d]\n", mRemoveVisuals.Count());
789 Actor self = mControlImpl.Self();
791 // A resource is ready, find resource in the registered visuals container and get its index
792 for(auto registeredIter = mVisuals.Begin(), end = mVisuals.End(); registeredIter != end; ++registeredIter)
794 Internal::Visual::Base& registeredVisualImpl = Toolkit::GetImplementation((*registeredIter)->visual);
796 if(&object == ®isteredVisualImpl)
798 RegisteredVisualContainer::Iterator visualToRemoveIter;
799 // Find visual with the same index in the removal container
800 // Set if off stage as it's replacement is now ready.
801 // Remove if from removal list as now removed from stage.
802 // Set Pending flag on the ready visual to false as now ready.
803 if(FindVisual((*registeredIter)->index, mRemoveVisuals, visualToRemoveIter))
805 (*registeredIter)->pending = false;
806 Toolkit::GetImplementation((*visualToRemoveIter)->visual).SetOffScene(self);
807 mRemoveVisuals.Erase(visualToRemoveIter);
813 // A visual is ready so control may need relayouting if staged
814 if(self.GetProperty<bool>(Actor::Property::CONNECTED_TO_SCENE))
816 mControlImpl.RelayoutRequest();
819 // Emit signal if all enabled visuals registered by the control are ready.
820 if(IsResourceReady())
823 mNeedToEmitResourceReady = false;
825 EmitResourceReadySignal();
829 void Control::Impl::NotifyVisualEvent(Visual::Base& object, Property::Index signalId)
831 for(auto registeredIter = mVisuals.Begin(), end = mVisuals.End(); registeredIter != end; ++registeredIter)
833 Internal::Visual::Base& registeredVisualImpl = Toolkit::GetImplementation((*registeredIter)->visual);
834 if(&object == ®isteredVisualImpl)
836 Dali::Toolkit::Control handle(mControlImpl.GetOwner());
837 mVisualEventSignal.Emit(handle, (*registeredIter)->index, signalId);
843 bool Control::Impl::IsResourceReady() const
845 // Iterate through and check all the enabled visuals are ready
846 for(auto visualIter = mVisuals.Begin();
847 visualIter != mVisuals.End();
850 const Toolkit::Visual::Base visual = (*visualIter)->visual;
851 const Internal::Visual::Base& visualImpl = Toolkit::GetImplementation(visual);
853 // one of the enabled visuals is not ready
854 if(!visualImpl.IsResourceReady() && (*visualIter)->enabled)
862 Toolkit::Visual::ResourceStatus Control::Impl::GetVisualResourceStatus(Property::Index index) const
864 RegisteredVisualContainer::Iterator iter;
865 if(FindVisual(index, mVisuals, iter))
867 const Toolkit::Visual::Base visual = (*iter)->visual;
868 const Internal::Visual::Base& visualImpl = Toolkit::GetImplementation(visual);
869 return visualImpl.GetResourceStatus();
872 return Toolkit::Visual::ResourceStatus::PREPARING;
875 void Control::Impl::AddTransitions(Dali::Animation& animation,
876 const Toolkit::TransitionData& handle,
877 bool createAnimation)
879 // Setup a Transition from TransitionData.
880 const Internal::TransitionData& transitionData = Toolkit::GetImplementation(handle);
881 TransitionData::Iterator end = transitionData.End();
882 for(TransitionData::Iterator iter = transitionData.Begin();
886 TransitionData::Animator* animator = (*iter);
888 Toolkit::Visual::Base visual = GetVisualByName(mVisuals, animator->objectName);
892 #if defined(DEBUG_ENABLED)
893 Dali::TypeInfo typeInfo;
894 ControlWrapper* controlWrapperImpl = dynamic_cast<ControlWrapper*>(&mControlImpl);
895 if(controlWrapperImpl)
897 typeInfo = controlWrapperImpl->GetTypeInfo();
900 DALI_LOG_INFO(gLogFilter, Debug::Concise, "CreateTransition: Found %s visual for %s\n", visual.GetName().c_str(), typeInfo ? typeInfo.GetName().c_str() : "Unknown");
902 Internal::Visual::Base& visualImpl = Toolkit::GetImplementation(visual);
903 visualImpl.AnimateProperty(animation, *animator);
907 DALI_LOG_INFO(gLogFilter, Debug::Concise, "CreateTransition: Could not find visual. Trying actors");
908 // Otherwise, try any actor children of control (Including the control)
909 Actor child = mControlImpl.Self().FindChildByName(animator->objectName);
912 Property::Index propertyIndex = child.GetPropertyIndex(animator->propertyKey);
913 if(propertyIndex != Property::INVALID_INDEX)
915 if(animator->animate == false)
917 if(animator->targetValue.GetType() != Property::NONE)
919 child.SetProperty(propertyIndex, animator->targetValue);
922 else // animate the property
924 if(animator->initialValue.GetType() != Property::NONE)
926 child.SetProperty(propertyIndex, animator->initialValue);
929 if(createAnimation && !animation)
931 animation = Dali::Animation::New(0.1f);
934 animation.AnimateTo(Property(child, propertyIndex),
935 animator->targetValue,
936 animator->alphaFunction,
937 TimePeriod(animator->timePeriodDelay,
938 animator->timePeriodDuration));
946 Dali::Animation Control::Impl::CreateTransition(const Toolkit::TransitionData& transitionData)
948 Dali::Animation transition;
950 if(transitionData.Count() > 0)
952 AddTransitions(transition, transitionData, true);
957 void Control::Impl::DoAction(Dali::Property::Index visualIndex, Dali::Property::Index actionId, const Dali::Property::Value attributes)
959 RegisteredVisualContainer::Iterator iter;
960 if(FindVisual(visualIndex, mVisuals, iter))
962 Toolkit::GetImplementation((*iter)->visual).DoAction(actionId, attributes);
966 void Control::Impl::AppendAccessibilityAttribute(const std::string& key,
967 const std::string value)
969 Property::Value* val = mAccessibilityAttributes.Find(key);
972 mAccessibilityAttributes[key] = Property::Value(value);
976 mAccessibilityAttributes.Insert(key, value);
980 void Control::Impl::SetProperty(BaseObject* object, Property::Index index, const Property::Value& value)
982 Toolkit::Control control = Toolkit::Control::DownCast(BaseHandle(object));
986 Control& controlImpl(GetImplementation(control));
990 case Toolkit::Control::Property::STYLE_NAME:
992 controlImpl.SetStyleName(value.Get<std::string>());
996 case Toolkit::DevelControl::Property::STATE:
998 bool withTransitions = true;
999 const Property::Value* valuePtr = &value;
1000 const Property::Map* map = value.GetMap();
1003 Property::Value* value2 = map->Find("withTransitions");
1006 withTransitions = value2->Get<bool>();
1009 valuePtr = map->Find("state");
1014 Toolkit::DevelControl::State state(controlImpl.mImpl->mState);
1015 if(Scripting::GetEnumerationProperty<Toolkit::DevelControl::State>(*valuePtr, ControlStateTable, ControlStateTableCount, state))
1017 controlImpl.mImpl->SetState(state, withTransitions);
1023 case Toolkit::DevelControl::Property::SUB_STATE:
1025 std::string subState;
1026 if(value.Get(subState))
1028 controlImpl.mImpl->SetSubState(subState);
1033 case Toolkit::DevelControl::Property::LEFT_FOCUSABLE_ACTOR_ID:
1036 if(value.Get(focusId))
1038 controlImpl.mImpl->mLeftFocusableActorId = focusId;
1043 case Toolkit::DevelControl::Property::RIGHT_FOCUSABLE_ACTOR_ID:
1046 if(value.Get(focusId))
1048 controlImpl.mImpl->mRightFocusableActorId = focusId;
1053 case Toolkit::DevelControl::Property::ACCESSIBILITY_NAME:
1058 controlImpl.mImpl->mAccessibilityName = name;
1059 controlImpl.mImpl->mAccessibilityNameSet = true;
1063 controlImpl.mImpl->mAccessibilityNameSet = false;
1068 case Toolkit::DevelControl::Property::ACCESSIBILITY_DESCRIPTION:
1073 controlImpl.mImpl->mAccessibilityDescription = txt;
1074 controlImpl.mImpl->mAccessibilityDescriptionSet = true;
1078 controlImpl.mImpl->mAccessibilityDescriptionSet = false;
1083 case Toolkit::DevelControl::Property::ACCESSIBILITY_TRANSLATION_DOMAIN:
1088 controlImpl.mImpl->mAccessibilityTranslationDomain = txt;
1089 controlImpl.mImpl->mAccessibilityTranslationDomainSet = true;
1093 controlImpl.mImpl->mAccessibilityTranslationDomainSet = false;
1098 case Toolkit::DevelControl::Property::ACCESSIBILITY_HIGHLIGHTABLE:
1101 if(value.Get(highlightable))
1103 controlImpl.mImpl->mAccessibilityHighlightable = highlightable;
1104 controlImpl.mImpl->mAccessibilityHighlightableSet = true;
1108 controlImpl.mImpl->mAccessibilityHighlightableSet = false;
1113 case Toolkit::DevelControl::Property::ACCESSIBILITY_ROLE:
1115 Dali::Accessibility::Role val;
1118 controlImpl.mImpl->mAccessibilityRole = val;
1123 case Toolkit::DevelControl::Property::UP_FOCUSABLE_ACTOR_ID:
1126 if(value.Get(focusId))
1128 controlImpl.mImpl->mUpFocusableActorId = focusId;
1133 case Toolkit::DevelControl::Property::DOWN_FOCUSABLE_ACTOR_ID:
1136 if(value.Get(focusId))
1138 controlImpl.mImpl->mDownFocusableActorId = focusId;
1143 case Toolkit::Control::Property::KEY_INPUT_FOCUS:
1145 if(value.Get<bool>())
1147 controlImpl.SetKeyInputFocus();
1151 controlImpl.ClearKeyInputFocus();
1156 case Toolkit::Control::Property::BACKGROUND:
1160 const Property::Map* map = value.GetMap();
1161 if(map && !map->Empty())
1163 controlImpl.SetBackground(*map);
1165 else if(value.Get(url))
1167 // don't know the size to load
1168 Toolkit::Visual::Base visual = Toolkit::VisualFactory::Get().CreateVisual(url, ImageDimensions());
1171 controlImpl.mImpl->RegisterVisual(Toolkit::Control::Property::BACKGROUND, visual, DepthIndex::BACKGROUND);
1174 else if(value.Get(color))
1176 controlImpl.SetBackgroundColor(color);
1180 // The background is an empty property map, so we should clear the background
1181 controlImpl.ClearBackground();
1186 case Toolkit::Control::Property::MARGIN:
1189 if(value.Get(margin))
1191 controlImpl.mImpl->SetMargin(margin);
1196 case Toolkit::Control::Property::PADDING:
1199 if(value.Get(padding))
1201 controlImpl.mImpl->SetPadding(padding);
1206 case Toolkit::DevelControl::Property::TOOLTIP:
1208 TooltipPtr& tooltipPtr = controlImpl.mImpl->mTooltip;
1211 tooltipPtr = Tooltip::New(control);
1213 tooltipPtr->SetProperties(value);
1217 case Toolkit::DevelControl::Property::SHADOW:
1219 const Property::Map* map = value.GetMap();
1220 if(map && !map->Empty())
1222 controlImpl.mImpl->SetShadow(*map);
1226 // The shadow is an empty property map, so we should clear the shadow
1227 controlImpl.mImpl->ClearShadow();
1232 case Toolkit::DevelControl::Property::ACCESSIBILITY_ATTRIBUTES:
1234 const Property::Map* map = value.GetMap();
1235 if(map && !map->Empty())
1237 controlImpl.mImpl->mAccessibilityAttributes = *map;
1242 case Toolkit::DevelControl::Property::ACCESSIBILITY_ANIMATED:
1245 if(value.Get(animated))
1247 controlImpl.mImpl->mAccessibilityAnimated = animated;
1255 Property::Value Control::Impl::GetProperty(BaseObject* object, Property::Index index)
1257 Property::Value value;
1259 Toolkit::Control control = Toolkit::Control::DownCast(BaseHandle(object));
1263 Control& controlImpl(GetImplementation(control));
1267 case Toolkit::Control::Property::STYLE_NAME:
1269 value = controlImpl.GetStyleName();
1273 case Toolkit::DevelControl::Property::STATE:
1275 value = controlImpl.mImpl->mState;
1279 case Toolkit::DevelControl::Property::SUB_STATE:
1281 value = controlImpl.mImpl->mSubStateName;
1285 case Toolkit::DevelControl::Property::LEFT_FOCUSABLE_ACTOR_ID:
1287 value = controlImpl.mImpl->mLeftFocusableActorId;
1291 case Toolkit::DevelControl::Property::RIGHT_FOCUSABLE_ACTOR_ID:
1293 value = controlImpl.mImpl->mRightFocusableActorId;
1297 case Toolkit::DevelControl::Property::ACCESSIBILITY_NAME:
1299 if(controlImpl.mImpl->mAccessibilityNameSet)
1301 value = controlImpl.mImpl->mAccessibilityName;
1306 case Toolkit::DevelControl::Property::ACCESSIBILITY_DESCRIPTION:
1308 if(controlImpl.mImpl->mAccessibilityDescriptionSet)
1310 value = controlImpl.mImpl->mAccessibilityDescription;
1315 case Toolkit::DevelControl::Property::ACCESSIBILITY_TRANSLATION_DOMAIN:
1317 if(controlImpl.mImpl->mAccessibilityTranslationDomainSet)
1319 value = controlImpl.mImpl->mAccessibilityTranslationDomain;
1324 case Toolkit::DevelControl::Property::ACCESSIBILITY_HIGHLIGHTABLE:
1326 if(controlImpl.mImpl->mAccessibilityHighlightableSet)
1328 value = controlImpl.mImpl->mAccessibilityHighlightable;
1333 case Toolkit::DevelControl::Property::ACCESSIBILITY_ROLE:
1335 value = Property::Value(controlImpl.mImpl->mAccessibilityRole);
1339 case Toolkit::DevelControl::Property::UP_FOCUSABLE_ACTOR_ID:
1341 value = controlImpl.mImpl->mUpFocusableActorId;
1345 case Toolkit::DevelControl::Property::DOWN_FOCUSABLE_ACTOR_ID:
1347 value = controlImpl.mImpl->mDownFocusableActorId;
1351 case Toolkit::Control::Property::KEY_INPUT_FOCUS:
1353 value = controlImpl.HasKeyInputFocus();
1357 case Toolkit::Control::Property::BACKGROUND:
1360 Toolkit::Visual::Base visual = controlImpl.mImpl->GetVisual(Toolkit::Control::Property::BACKGROUND);
1363 visual.CreatePropertyMap(map);
1370 case Toolkit::Control::Property::MARGIN:
1372 value = controlImpl.mImpl->GetMargin();
1376 case Toolkit::Control::Property::PADDING:
1378 value = controlImpl.mImpl->GetPadding();
1382 case Toolkit::DevelControl::Property::TOOLTIP:
1385 if(controlImpl.mImpl->mTooltip)
1387 controlImpl.mImpl->mTooltip->CreatePropertyMap(map);
1393 case Toolkit::DevelControl::Property::SHADOW:
1396 Toolkit::Visual::Base visual = controlImpl.mImpl->GetVisual(Toolkit::DevelControl::Property::SHADOW);
1399 visual.CreatePropertyMap(map);
1406 case Toolkit::DevelControl::Property::ACCESSIBILITY_ATTRIBUTES:
1408 value = controlImpl.mImpl->mAccessibilityAttributes;
1412 case Toolkit::DevelControl::Property::ACCESSIBILITY_ANIMATED:
1414 value = controlImpl.mImpl->mAccessibilityAnimated;
1423 void Control::Impl::RemoveAccessibilityAttribute(const std::string& key)
1425 Property::Value* val = mAccessibilityAttributes.Find(key);
1427 mAccessibilityAttributes[key] = Property::Value();
1430 void Control::Impl::ClearAccessibilityAttributes()
1432 mAccessibilityAttributes.Clear();
1435 void Control::Impl::SetAccessibilityReadingInfoType(const Dali::Accessibility::ReadingInfoTypes types)
1438 if(types[Dali::Accessibility::ReadingInfoType::NAME])
1440 value += READING_INFO_TYPE_NAME;
1442 if(types[Dali::Accessibility::ReadingInfoType::ROLE])
1446 value += READING_INFO_TYPE_SEPARATOR;
1448 value += READING_INFO_TYPE_ROLE;
1450 if(types[Dali::Accessibility::ReadingInfoType::DESCRIPTION])
1454 value += READING_INFO_TYPE_SEPARATOR;
1456 value += READING_INFO_TYPE_DESCRIPTION;
1458 if(types[Dali::Accessibility::ReadingInfoType::STATE])
1462 value += READING_INFO_TYPE_SEPARATOR;
1464 value += READING_INFO_TYPE_STATE;
1466 AppendAccessibilityAttribute(READING_INFO_TYPE_ATTRIBUTE_NAME, value);
1469 Dali::Accessibility::ReadingInfoTypes Control::Impl::GetAccessibilityReadingInfoType() const
1472 auto place = mAccessibilityAttributes.Find(READING_INFO_TYPE_ATTRIBUTE_NAME);
1479 Dali::Accessibility::ReadingInfoTypes types;
1480 types[Dali::Accessibility::ReadingInfoType::NAME] = true;
1481 types[Dali::Accessibility::ReadingInfoType::ROLE] = true;
1482 types[Dali::Accessibility::ReadingInfoType::DESCRIPTION] = true;
1483 types[Dali::Accessibility::ReadingInfoType::STATE] = true;
1492 Dali::Accessibility::ReadingInfoTypes types;
1494 if(value.find(READING_INFO_TYPE_NAME) != std::string::npos)
1496 types[Dali::Accessibility::ReadingInfoType::NAME] = true;
1498 if(value.find(READING_INFO_TYPE_ROLE) != std::string::npos)
1500 types[Dali::Accessibility::ReadingInfoType::ROLE] = true;
1502 if(value.find(READING_INFO_TYPE_DESCRIPTION) != std::string::npos)
1504 types[Dali::Accessibility::ReadingInfoType::DESCRIPTION] = true;
1506 if(value.find(READING_INFO_TYPE_STATE) != std::string::npos)
1508 types[Dali::Accessibility::ReadingInfoType::STATE] = true;
1514 void Control::Impl::CopyInstancedProperties(RegisteredVisualContainer& visuals, Dictionary<Property::Map>& instancedProperties)
1516 for(RegisteredVisualContainer::Iterator iter = visuals.Begin(); iter != visuals.End(); iter++)
1520 Property::Map instanceMap;
1521 Toolkit::GetImplementation((*iter)->visual).CreateInstancePropertyMap(instanceMap);
1522 instancedProperties.Add((*iter)->visual.GetName(), instanceMap);
1527 void Control::Impl::RemoveVisual(RegisteredVisualContainer& visuals, const std::string& visualName)
1529 Actor self(mControlImpl.Self());
1531 for(RegisteredVisualContainer::Iterator visualIter = visuals.Begin();
1532 visualIter != visuals.End();
1535 Toolkit::Visual::Base visual = (*visualIter)->visual;
1536 if(visual && visual.GetName() == visualName)
1538 Toolkit::GetImplementation(visual).SetOffScene(self);
1539 (*visualIter)->visual.Reset();
1540 visuals.Erase(visualIter);
1546 void Control::Impl::RemoveVisuals(RegisteredVisualContainer& visuals, DictionaryKeys& removeVisuals)
1548 Actor self(mControlImpl.Self());
1549 for(DictionaryKeys::iterator iter = removeVisuals.begin(); iter != removeVisuals.end(); ++iter)
1551 const std::string visualName = *iter;
1552 RemoveVisual(visuals, visualName);
1556 void Control::Impl::RecreateChangedVisuals(Dictionary<Property::Map>& stateVisualsToChange,
1557 Dictionary<Property::Map>& instancedProperties)
1559 Dali::CustomActor handle(mControlImpl.GetOwner());
1560 for(Dictionary<Property::Map>::iterator iter = stateVisualsToChange.Begin();
1561 iter != stateVisualsToChange.End();
1564 const std::string& visualName = (*iter).key;
1565 const Property::Map& toMap = (*iter).entry;
1567 Actor self = mControlImpl.Self();
1568 RegisteredVisualContainer::Iterator registeredVisualsiter;
1569 // Check if visual (visualName) is already registered, this is the current visual.
1570 if(FindVisual(visualName, mVisuals, registeredVisualsiter))
1572 Toolkit::Visual::Base& visual = (*registeredVisualsiter)->visual;
1575 // No longer required to know if the replaced visual's resources are ready
1576 StopObservingVisual(visual);
1578 // If control staged then visuals will be swapped once ready
1579 if(self.GetProperty<bool>(Actor::Property::CONNECTED_TO_SCENE))
1581 // Check if visual is currently in the process of being replaced ( is in removal container )
1582 RegisteredVisualContainer::Iterator visualQueuedForRemoval;
1583 if(FindVisual(visualName, mRemoveVisuals, visualQueuedForRemoval))
1585 // Visual with same visual name is already in removal container so current visual pending
1586 // Only the the last requested visual will be displayed so remove current visual which is staged but not ready.
1587 Toolkit::GetImplementation(visual).SetOffScene(self);
1588 (*registeredVisualsiter)->visual.Reset();
1589 mVisuals.Erase(registeredVisualsiter);
1593 // current visual not already in removal container so add now.
1594 DALI_LOG_INFO(gLogFilter, Debug::Verbose, "RegisterVisual Move current registered visual to removal Queue: %s \n", visualName.c_str());
1595 MoveVisual(registeredVisualsiter, mVisuals, mRemoveVisuals);
1600 // Control not staged or visual disabled so can just erase from registered visuals and new visual will be added later.
1601 (*registeredVisualsiter)->visual.Reset();
1602 mVisuals.Erase(registeredVisualsiter);
1606 const Property::Map* instancedMap = instancedProperties.FindConst(visualName);
1607 Style::ApplyVisual(handle, visualName, toMap, instancedMap);
1612 void Control::Impl::ReplaceStateVisualsAndProperties(const StylePtr oldState, const StylePtr newState, const std::string& subState)
1614 // Collect all old visual names
1615 DictionaryKeys stateVisualsToRemove;
1618 oldState->visuals.GetKeys(stateVisualsToRemove);
1619 if(!subState.empty())
1621 const StylePtr* oldSubState = oldState->subStates.FindConst(subState);
1624 DictionaryKeys subStateVisualsToRemove;
1625 (*oldSubState)->visuals.GetKeys(subStateVisualsToRemove);
1626 Merge(stateVisualsToRemove, subStateVisualsToRemove);
1631 // Collect all new visual properties
1632 Dictionary<Property::Map> stateVisualsToAdd;
1635 stateVisualsToAdd = newState->visuals;
1636 if(!subState.empty())
1638 const StylePtr* newSubState = newState->subStates.FindConst(subState);
1641 stateVisualsToAdd.Merge((*newSubState)->visuals);
1646 // If a name is in both add/remove, move it to change list.
1647 Dictionary<Property::Map> stateVisualsToChange;
1648 FindChangableVisuals(stateVisualsToAdd, stateVisualsToChange, stateVisualsToRemove);
1650 // Copy instanced properties (e.g. text label) of current visuals
1651 Dictionary<Property::Map> instancedProperties;
1652 CopyInstancedProperties(mVisuals, instancedProperties);
1654 // For each visual in remove list, remove from mVisuals
1655 RemoveVisuals(mVisuals, stateVisualsToRemove);
1657 // For each visual in add list, create and add to mVisuals
1658 Dali::CustomActor handle(mControlImpl.GetOwner());
1659 Style::ApplyVisuals(handle, stateVisualsToAdd, instancedProperties);
1661 // For each visual in change list, if it requires a new visual,
1662 // remove old visual, create and add to mVisuals
1663 RecreateChangedVisuals(stateVisualsToChange, instancedProperties);
1666 void Control::Impl::SetState(DevelControl::State newState, bool withTransitions)
1668 DevelControl::State oldState = mState;
1669 Dali::CustomActor handle(mControlImpl.GetOwner());
1670 DALI_LOG_INFO(gLogFilter, Debug::Concise, "Control::Impl::SetState: %s\n", (mState == DevelControl::NORMAL ? "NORMAL" : (mState == DevelControl::FOCUSED ? "FOCUSED" : (mState == DevelControl::DISABLED ? "DISABLED" : "NONE"))));
1672 if(mState != newState)
1674 // If mState was Disabled, and new state is Focused, should probably
1675 // store that fact, e.g. in another property that FocusManager can access.
1678 // Trigger state change and transitions
1679 // Apply new style, if stylemanager is available
1680 Toolkit::StyleManager styleManager = Toolkit::StyleManager::Get();
1683 const StylePtr stylePtr = GetImpl(styleManager).GetRecordedStyle(Toolkit::Control(mControlImpl.GetOwner()));
1687 std::string oldStateName = Scripting::GetEnumerationName<Toolkit::DevelControl::State>(oldState, ControlStateTable, ControlStateTableCount);
1688 std::string newStateName = Scripting::GetEnumerationName<Toolkit::DevelControl::State>(newState, ControlStateTable, ControlStateTableCount);
1690 const StylePtr* newStateStyle = stylePtr->subStates.Find(newStateName);
1691 const StylePtr* oldStateStyle = stylePtr->subStates.Find(oldStateName);
1692 if(oldStateStyle && newStateStyle)
1694 // Only change if both state styles exist
1695 ReplaceStateVisualsAndProperties(*oldStateStyle, *newStateStyle, mSubStateName);
1702 void Control::Impl::SetSubState(const std::string& subStateName, bool withTransitions)
1704 if(mSubStateName != subStateName)
1706 // Get existing sub-state visuals, and unregister them
1707 Dali::CustomActor handle(mControlImpl.GetOwner());
1709 Toolkit::StyleManager styleManager = Toolkit::StyleManager::Get();
1712 const StylePtr stylePtr = GetImpl(styleManager).GetRecordedStyle(Toolkit::Control(mControlImpl.GetOwner()));
1716 std::string stateName = Scripting::GetEnumerationName<Toolkit::DevelControl::State>(mState, ControlStateTable, ControlStateTableCount);
1718 const StylePtr* state = stylePtr->subStates.Find(stateName);
1721 StylePtr stateStyle(*state);
1723 const StylePtr* newStateStyle = stateStyle->subStates.Find(subStateName);
1724 const StylePtr* oldStateStyle = stateStyle->subStates.Find(mSubStateName);
1725 if(oldStateStyle && newStateStyle)
1728 ReplaceStateVisualsAndProperties(*oldStateStyle, *newStateStyle, empty);
1734 mSubStateName = subStateName;
1738 void Control::Impl::OnSceneDisconnection()
1740 Actor self = mControlImpl.Self();
1742 // Any visuals set for replacement but not yet ready should still be registered.
1743 // Reason: If a request was made to register a new visual but the control removed from scene before visual was ready
1744 // then when this control appears back on stage it should use that new visual.
1746 // Iterate through all registered visuals and set off scene
1747 SetVisualsOffScene(mVisuals, self);
1749 // Visuals pending replacement can now be taken out of the removal list and set off scene
1750 // Iterate through all replacement visuals and add to a move queue then set off scene
1751 for(auto removalIter = mRemoveVisuals.Begin(), end = mRemoveVisuals.End(); removalIter != end; removalIter++)
1753 Toolkit::GetImplementation((*removalIter)->visual).SetOffScene(self);
1756 for(auto replacedIter = mVisuals.Begin(), end = mVisuals.End(); replacedIter != end; replacedIter++)
1758 (*replacedIter)->pending = false;
1761 mRemoveVisuals.Clear();
1764 void Control::Impl::SetMargin(Extents margin)
1766 mControlImpl.mImpl->mMargin = margin;
1768 // Trigger a size negotiation request that may be needed when setting a margin.
1769 mControlImpl.RelayoutRequest();
1772 Extents Control::Impl::GetMargin() const
1774 return mControlImpl.mImpl->mMargin;
1777 void Control::Impl::SetPadding(Extents padding)
1779 mControlImpl.mImpl->mPadding = padding;
1781 // Trigger a size negotiation request that may be needed when setting a padding.
1782 mControlImpl.RelayoutRequest();
1785 Extents Control::Impl::GetPadding() const
1787 return mControlImpl.mImpl->mPadding;
1790 void Control::Impl::SetInputMethodContext(InputMethodContext& inputMethodContext)
1792 mInputMethodContext = inputMethodContext;
1795 bool Control::Impl::FilterKeyEvent(const KeyEvent& event)
1797 bool consumed(false);
1799 if(mInputMethodContext)
1801 consumed = mInputMethodContext.FilterEventKey(event);
1806 DevelControl::VisualEventSignalType& Control::Impl::VisualEventSignal()
1808 return mVisualEventSignal;
1811 void Control::Impl::SetShadow(const Property::Map& map)
1813 Toolkit::Visual::Base visual = Toolkit::VisualFactory::Get().CreateVisual(map);
1814 visual.SetName("shadow");
1818 mControlImpl.mImpl->RegisterVisual(Toolkit::DevelControl::Property::SHADOW, visual, DepthIndex::BACKGROUND_EFFECT);
1820 mControlImpl.RelayoutRequest();
1824 void Control::Impl::ClearShadow()
1826 mControlImpl.mImpl->UnregisterVisual(Toolkit::DevelControl::Property::SHADOW);
1828 // Trigger a size negotiation request that may be needed when unregistering a visual.
1829 mControlImpl.RelayoutRequest();
1832 Dali::Property Control::Impl::GetVisualProperty(Dali::Property::Index index, Dali::Property::Key visualPropertyKey)
1834 Toolkit::Visual::Base visual = GetVisualByIndex(mVisuals, index);
1837 Internal::Visual::Base& visualImpl = Toolkit::GetImplementation(visual);
1838 return visualImpl.GetPropertyObject(visualPropertyKey);
1842 return Dali::Property(handle, Property::INVALID_INDEX);
1845 void Control::Impl::EmitResourceReadySignal()
1847 if(!mIsEmittingResourceReadySignal)
1849 // Guard against calls to emit the signal during the callback
1850 mIsEmittingResourceReadySignal = true;
1852 // If the signal handler changes visual, it may become ready during this call & therefore this method will
1853 // get called again recursively. If so, mNeedToEmitResourceReady is set below, and we act on it after that secondary
1854 // invocation has completed by notifying in an Idle callback to prevent further recursion.
1855 Dali::Toolkit::Control handle(mControlImpl.GetOwner());
1856 mResourceReadySignal.Emit(handle);
1858 if(mNeedToEmitResourceReady)
1860 // Add idler to emit the signal again
1863 // The callback manager takes the ownership of the callback object.
1864 mIdleCallback = MakeCallback(this, &Control::Impl::OnIdleCallback);
1865 Adaptor::Get().AddIdle(mIdleCallback, false);
1869 mIsEmittingResourceReadySignal = false;
1873 mNeedToEmitResourceReady = true;
1877 void Control::Impl::OnIdleCallback()
1879 if(mNeedToEmitResourceReady)
1882 mNeedToEmitResourceReady = false;
1884 // A visual is ready so control may need relayouting if staged
1885 if(mControlImpl.Self().GetProperty<bool>(Actor::Property::CONNECTED_TO_SCENE))
1887 mControlImpl.RelayoutRequest();
1890 EmitResourceReadySignal();
1893 // Set the pointer to null as the callback manager deletes the callback after execute it.
1894 mIdleCallback = nullptr;
1897 Dali::Accessibility::Accessible* Control::Impl::GetAccessibilityObject()
1899 if(!accessibilityObject)
1900 accessibilityObject = accessibilityConstructor(mControlImpl.Self());
1901 return accessibilityObject.get();
1904 Dali::Accessibility::Accessible* Control::Impl::GetAccessibilityObject(Dali::Actor actor)
1908 auto q = Dali::Toolkit::Control::DownCast(actor);
1911 auto q2 = static_cast<Internal::Control*>(&q.GetImplementation());
1912 return q2->mImpl->GetAccessibilityObject();
1918 void Control::Impl::PositionOrSizeChangedCallback(PropertyNotification& p)
1920 auto self = Dali::Actor::DownCast(p.GetTarget());
1921 if(Dali::Accessibility::IsUp() && !self.GetProperty(Toolkit::DevelControl::Property::ACCESSIBILITY_ANIMATED).Get<bool>())
1923 auto extents = DevelActor::CalculateScreenExtents(self);
1924 Dali::Accessibility::Accessible::Get(self)->EmitBoundsChanged(extents);
1928 void Control::Impl::CulledChangedCallback(PropertyNotification& p)
1930 if(Dali::Accessibility::IsUp())
1932 auto self = Dali::Actor::DownCast(p.GetTarget());
1933 Dali::Accessibility::Accessible::Get(self)->EmitShowing(!self.GetProperty(DevelActor::Property::CULLED).Get<bool>());
1937 void Control::Impl::AccessibilityRegister()
1939 if(!accessibilityNotificationSet)
1941 accessibilityNotificationPosition = mControlImpl.Self().AddPropertyNotification(Actor::Property::POSITION, StepCondition(0.01f));
1942 accessibilityNotificationPosition.SetNotifyMode(PropertyNotification::NOTIFY_ON_CHANGED);
1943 accessibilityNotificationPosition.NotifySignal().Connect(&Control::Impl::PositionOrSizeChangedCallback);
1945 accessibilityNotificationSize = mControlImpl.Self().AddPropertyNotification(Actor::Property::SIZE, StepCondition(0.01f));
1946 accessibilityNotificationSize.SetNotifyMode(PropertyNotification::NOTIFY_ON_CHANGED);
1947 accessibilityNotificationSize.NotifySignal().Connect(&Control::Impl::PositionOrSizeChangedCallback);
1949 accessibilityNotificationCulled = mControlImpl.Self().AddPropertyNotification(DevelActor::Property::CULLED, LessThanCondition(0.5f));
1950 accessibilityNotificationCulled.SetNotifyMode(PropertyNotification::NOTIFY_ON_CHANGED);
1951 accessibilityNotificationCulled.NotifySignal().Connect(&Control::Impl::CulledChangedCallback);
1953 accessibilityNotificationSet = true;
1957 void Control::Impl::AccessibilityDeregister(bool remove)
1959 if(accessibilityNotificationSet)
1961 accessibilityNotificationPosition.NotifySignal().Disconnect(&Control::Impl::PositionOrSizeChangedCallback);
1964 mControlImpl.Self().RemovePropertyNotification(accessibilityNotificationPosition);
1966 accessibilityNotificationPosition.Reset();
1967 accessibilityNotificationPosition = {};
1969 accessibilityNotificationSize.NotifySignal().Disconnect(&Control::Impl::PositionOrSizeChangedCallback);
1972 mControlImpl.Self().RemovePropertyNotification(accessibilityNotificationSize);
1974 accessibilityNotificationSize.Reset();
1975 accessibilityNotificationSize = {};
1977 accessibilityNotificationCulled.NotifySignal().Disconnect(&Control::Impl::CulledChangedCallback);
1980 mControlImpl.Self().RemovePropertyNotification(accessibilityNotificationCulled);
1982 accessibilityNotificationCulled.Reset();
1983 accessibilityNotificationCulled = {};
1984 accessibilityNotificationSet = false;
1988 void Control::Impl::SetAutofillEnabled( bool autofillEnabled )
1990 mIsAutofillEnabled = autofillEnabled;
1993 bool Control::Impl::IsAutofillEnabled()
1995 return mIsAutofillEnabled;
1998 void Control::Impl::SetAutofillItemHandle( Dali::AutofillItem item )
2000 mAutofillItem = item;
2003 Dali::AutofillItem Control::Impl::GetAutofillItemHandle()
2005 return mAutofillItem;
2008 void Control::Impl::SetAutofillContainer( Toolkit::AutofillContainer container )
2010 mAutofillContainer = container;
2013 Toolkit::AutofillContainer Control::Impl::GetAutofillContainer()
2015 return mAutofillContainer;
2018 } // namespace Internal
2020 } // namespace Toolkit