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);
425 Control::Impl::Impl(Control& controlImpl)
426 : mControlImpl(controlImpl),
427 mState(Toolkit::DevelControl::NORMAL),
429 mLeftFocusableActorId(-1),
430 mRightFocusableActorId(-1),
431 mUpFocusableActorId(-1),
432 mDownFocusableActorId(-1),
434 mBackgroundColor(Color::TRANSPARENT),
435 mStartingPinchScale(nullptr),
437 mPadding(0, 0, 0, 0),
439 mKeyInputFocusGainedSignal(),
440 mKeyInputFocusLostSignal(),
441 mResourceReadySignal(),
442 mVisualEventSignal(),
443 mAccessibilityGetNameSignal(),
444 mAccessibilityGetDescriptionSignal(),
445 mAccessibilityDoGestureSignal(),
446 mPinchGestureDetector(),
447 mPanGestureDetector(),
448 mTapGestureDetector(),
449 mLongPressGestureDetector(),
451 mInputMethodContext(),
452 mIdleCallback(nullptr),
453 mFlags(Control::ControlBehaviour(CONTROL_BEHAVIOUR_DEFAULT)),
454 mIsKeyboardNavigationSupported(false),
455 mIsKeyboardFocusGroup(false),
456 mIsEmittingResourceReadySignal(false),
457 mNeedToEmitResourceReady(false)
459 Dali::Accessibility::Accessible::RegisterControlAccessibilityGetter(
460 [](Dali::Actor actor) -> Dali::Accessibility::Accessible* {
461 return Control::Impl::GetAccessibilityObject(actor);
464 accessibilityConstructor = [](Dali::Actor actor) -> std::unique_ptr<Dali::Accessibility::Accessible> {
465 return std::unique_ptr<Dali::Accessibility::Accessible>(new DevelControl::AccessibleImpl(actor,
466 Dali::Accessibility::Role::UNKNOWN));
469 size_t len = static_cast<size_t>(Dali::Accessibility::RelationType::MAX_COUNT);
470 mAccessibilityRelations.reserve(len);
471 for(auto i = 0u; i < len; ++i)
473 mAccessibilityRelations.push_back({});
477 Control::Impl::~Impl()
479 for(auto&& iter : mVisuals)
481 StopObservingVisual(iter->visual);
484 for(auto&& iter : mRemoveVisuals)
486 StopObservingVisual(iter->visual);
489 // All gesture detectors will be destroyed so no need to disconnect.
490 delete mStartingPinchScale;
492 if(mIdleCallback && Adaptor::IsAvailable())
494 // Removes the callback from the callback manager in case the control is destroyed before the callback is executed.
495 Adaptor::Get().RemoveIdle(mIdleCallback);
499 Control::Impl& Control::Impl::Get(Internal::Control& internalControl)
501 return *internalControl.mImpl;
504 const Control::Impl& Control::Impl::Get(const Internal::Control& internalControl)
506 return *internalControl.mImpl;
509 // Gesture Detection Methods
510 void Control::Impl::PinchDetected(Actor actor, const PinchGesture& pinch)
512 mControlImpl.OnPinch(pinch);
515 void Control::Impl::PanDetected(Actor actor, const PanGesture& pan)
517 mControlImpl.OnPan(pan);
520 void Control::Impl::TapDetected(Actor actor, const TapGesture& tap)
522 mControlImpl.OnTap(tap);
525 void Control::Impl::LongPressDetected(Actor actor, const LongPressGesture& longPress)
527 mControlImpl.OnLongPress(longPress);
530 void Control::Impl::RegisterVisual(Property::Index index, Toolkit::Visual::Base& visual)
532 RegisterVisual(index, visual, VisualState::ENABLED, DepthIndexValue::NOT_SET);
535 void Control::Impl::RegisterVisual(Property::Index index, Toolkit::Visual::Base& visual, int depthIndex)
537 RegisterVisual(index, visual, VisualState::ENABLED, DepthIndexValue::SET, depthIndex);
540 void Control::Impl::RegisterVisual(Property::Index index, Toolkit::Visual::Base& visual, bool enabled)
542 RegisterVisual(index, visual, (enabled ? VisualState::ENABLED : VisualState::DISABLED), DepthIndexValue::NOT_SET);
545 void Control::Impl::RegisterVisual(Property::Index index, Toolkit::Visual::Base& visual, bool enabled, int depthIndex)
547 RegisterVisual(index, visual, (enabled ? VisualState::ENABLED : VisualState::DISABLED), DepthIndexValue::SET, depthIndex);
550 void Control::Impl::RegisterVisual(Property::Index index, Toolkit::Visual::Base& visual, VisualState::Type enabled, DepthIndexValue::Type depthIndexValueSet, int depthIndex)
552 DALI_LOG_INFO(gLogFilter, Debug::Concise, "RegisterVisual:%d \n", index);
554 bool visualReplaced(false);
555 Actor self = mControlImpl.Self();
557 // Set the depth index, if not set by caller this will be either the current visual depth, max depth of all visuals
559 int requiredDepthIndex = visual.GetDepthIndex();
561 if(depthIndexValueSet == DepthIndexValue::SET)
563 requiredDepthIndex = depthIndex;
566 // Visual replacement, existing visual should only be removed from stage when replacement ready.
567 if(!mVisuals.Empty())
569 RegisteredVisualContainer::Iterator registeredVisualsiter;
570 // Check if visual (index) is already registered, this is the current visual.
571 if(FindVisual(index, mVisuals, registeredVisualsiter))
573 Toolkit::Visual::Base& currentRegisteredVisual = (*registeredVisualsiter)->visual;
574 if(currentRegisteredVisual)
576 // Store current visual depth index as may need to set the replacement visual to same depth
577 const int currentDepthIndex = (*registeredVisualsiter)->visual.GetDepthIndex();
579 // No longer required to know if the replaced visual's resources are ready
580 StopObservingVisual(currentRegisteredVisual);
582 // If control staged and visual enabled then visuals will be swapped once ready
583 if(self.GetProperty<bool>(Actor::Property::CONNECTED_TO_SCENE) && enabled)
585 // Check if visual is currently in the process of being replaced ( is in removal container )
586 RegisteredVisualContainer::Iterator visualQueuedForRemoval;
587 if(FindVisual(index, mRemoveVisuals, visualQueuedForRemoval))
589 // Visual with same index is already in removal container so current visual pending
590 // Only the the last requested visual will be displayed so remove current visual which is staged but not ready.
591 Toolkit::GetImplementation(currentRegisteredVisual).SetOffScene(self);
592 mVisuals.Erase(registeredVisualsiter);
596 // current visual not already in removal container so add now.
597 DALI_LOG_INFO(gLogFilter, Debug::Verbose, "RegisterVisual Move current registered visual to removal Queue: %d \n", index);
598 MoveVisual(registeredVisualsiter, mVisuals, mRemoveVisuals);
603 // Control not staged or visual disabled so can just erase from registered visuals and new visual will be added later.
604 mVisuals.Erase(registeredVisualsiter);
607 // 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
608 if((depthIndexValueSet == DepthIndexValue::NOT_SET) &&
609 (visual.GetDepthIndex() == 0))
611 requiredDepthIndex = currentDepthIndex;
615 visualReplaced = true;
619 // If not set, set the name of the visual to the same name as the control's property.
620 // ( If the control has been type registered )
621 if(visual.GetName().empty())
623 // returns empty string if index is not found as long as index is not -1
624 std::string visualName = self.GetPropertyName(index);
625 if(!visualName.empty())
627 DALI_LOG_INFO(gLogFilter, Debug::Concise, "Setting visual name for property %d to %s\n", index, visualName.c_str());
628 visual.SetName(visualName);
632 if(!visualReplaced) // New registration entry
634 // 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
635 if((depthIndexValueSet == DepthIndexValue::NOT_SET) &&
636 (mVisuals.Size() > 0) &&
637 (visual.GetDepthIndex() == 0))
639 int maxDepthIndex = std::numeric_limits<int>::min();
641 RegisteredVisualContainer::ConstIterator iter;
642 const RegisteredVisualContainer::ConstIterator endIter = mVisuals.End();
643 for(iter = mVisuals.Begin(); iter != endIter; iter++)
645 const int visualDepthIndex = (*iter)->visual.GetDepthIndex();
646 if(visualDepthIndex > maxDepthIndex)
648 maxDepthIndex = visualDepthIndex;
651 ++maxDepthIndex; // Add one to the current maximum depth index so that our added visual appears on top
652 requiredDepthIndex = std::max(0, maxDepthIndex); // Start at zero if maxDepth index belongs to a background
658 // Set determined depth index
659 visual.SetDepthIndex(requiredDepthIndex);
661 // Monitor when the visual resources are ready
662 StartObservingVisual(visual);
664 DALI_LOG_INFO(gLogFilter, Debug::Concise, "New Visual registration index[%d] depth[%d]\n", index, requiredDepthIndex);
665 RegisteredVisual* newRegisteredVisual = new RegisteredVisual(index, visual, (enabled == VisualState::ENABLED ? true : false), (visualReplaced && enabled));
666 mVisuals.PushBack(newRegisteredVisual);
668 Internal::Visual::Base& visualImpl = Toolkit::GetImplementation(visual);
669 // Put on stage if enabled and the control is already on the stage
670 if((enabled == VisualState::ENABLED) && self.GetProperty<bool>(Actor::Property::CONNECTED_TO_SCENE))
672 visualImpl.SetOnScene(self);
674 else if(visualImpl.IsResourceReady()) // When not being staged, check if visual already 'ResourceReady' before it was Registered. ( Resource may have been loaded already )
676 ResourceReady(visualImpl);
680 DALI_LOG_INFO(gLogFilter, Debug::Verbose, "Control::RegisterVisual() Registered %s(%d), enabled:%s\n", visual.GetName().c_str(), index, enabled ? "true" : "false");
683 void Control::Impl::UnregisterVisual(Property::Index index)
685 RegisteredVisualContainer::Iterator iter;
686 if(FindVisual(index, mVisuals, iter))
688 // stop observing visual
689 StopObservingVisual((*iter)->visual);
691 Actor self(mControlImpl.Self());
692 Toolkit::GetImplementation((*iter)->visual).SetOffScene(self);
693 (*iter)->visual.Reset();
694 mVisuals.Erase(iter);
697 if(FindVisual(index, mRemoveVisuals, iter))
699 Actor self(mControlImpl.Self());
700 Toolkit::GetImplementation((*iter)->visual).SetOffScene(self);
701 (*iter)->pending = false;
702 (*iter)->visual.Reset();
703 mRemoveVisuals.Erase(iter);
707 Toolkit::Visual::Base Control::Impl::GetVisual(Property::Index index) const
709 RegisteredVisualContainer::Iterator iter;
710 if(FindVisual(index, mVisuals, iter))
712 return (*iter)->visual;
715 return Toolkit::Visual::Base();
718 void Control::Impl::EnableVisual(Property::Index index, bool enable)
720 DALI_LOG_INFO(gLogFilter, Debug::General, "Control::EnableVisual(%d, %s)\n", index, enable ? "T" : "F");
722 RegisteredVisualContainer::Iterator iter;
723 if(FindVisual(index, mVisuals, iter))
725 if((*iter)->enabled == enable)
727 DALI_LOG_INFO(gLogFilter, Debug::Verbose, "Control::EnableVisual Visual %s(%d) already %s\n", (*iter)->visual.GetName().c_str(), index, enable ? "enabled" : "disabled");
731 (*iter)->enabled = enable;
732 Actor parentActor = mControlImpl.Self();
733 if(mControlImpl.Self().GetProperty<bool>(Actor::Property::CONNECTED_TO_SCENE)) // If control not on Scene then Visual will be added when SceneConnection is called.
737 DALI_LOG_INFO(gLogFilter, Debug::Verbose, "Control::EnableVisual Setting %s(%d) on stage \n", (*iter)->visual.GetName().c_str(), index);
738 Toolkit::GetImplementation((*iter)->visual).SetOnScene(parentActor);
742 DALI_LOG_INFO(gLogFilter, Debug::Verbose, "Control::EnableVisual Setting %s(%d) off stage \n", (*iter)->visual.GetName().c_str(), index);
743 Toolkit::GetImplementation((*iter)->visual).SetOffScene(parentActor); // No need to call if control not staged.
749 DALI_LOG_WARNING("Control::EnableVisual(%d, %s) FAILED - NO SUCH VISUAL\n", index, enable ? "T" : "F");
753 bool Control::Impl::IsVisualEnabled(Property::Index index) const
755 RegisteredVisualContainer::Iterator iter;
756 if(FindVisual(index, mVisuals, iter))
758 return (*iter)->enabled;
763 void Control::Impl::StopObservingVisual(Toolkit::Visual::Base& visual)
765 Internal::Visual::Base& visualImpl = Toolkit::GetImplementation(visual);
767 // Stop observing the visual
768 visualImpl.RemoveEventObserver(*this);
771 void Control::Impl::StartObservingVisual(Toolkit::Visual::Base& visual)
773 Internal::Visual::Base& visualImpl = Toolkit::GetImplementation(visual);
775 // start observing the visual for events
776 visualImpl.AddEventObserver(*this);
779 // Called by a Visual when it's resource is ready
780 void Control::Impl::ResourceReady(Visual::Base& object)
782 DALI_LOG_INFO(gLogFilter, Debug::Verbose, "Control::Impl::ResourceReady() replacements pending[%d]\n", mRemoveVisuals.Count());
784 Actor self = mControlImpl.Self();
786 // A resource is ready, find resource in the registered visuals container and get its index
787 for(auto registeredIter = mVisuals.Begin(), end = mVisuals.End(); registeredIter != end; ++registeredIter)
789 Internal::Visual::Base& registeredVisualImpl = Toolkit::GetImplementation((*registeredIter)->visual);
791 if(&object == ®isteredVisualImpl)
793 RegisteredVisualContainer::Iterator visualToRemoveIter;
794 // Find visual with the same index in the removal container
795 // Set if off stage as it's replacement is now ready.
796 // Remove if from removal list as now removed from stage.
797 // Set Pending flag on the ready visual to false as now ready.
798 if(FindVisual((*registeredIter)->index, mRemoveVisuals, visualToRemoveIter))
800 (*registeredIter)->pending = false;
801 Toolkit::GetImplementation((*visualToRemoveIter)->visual).SetOffScene(self);
802 mRemoveVisuals.Erase(visualToRemoveIter);
808 // A visual is ready so control may need relayouting if staged
809 if(self.GetProperty<bool>(Actor::Property::CONNECTED_TO_SCENE))
811 mControlImpl.RelayoutRequest();
814 // Emit signal if all enabled visuals registered by the control are ready.
815 if(IsResourceReady())
818 mNeedToEmitResourceReady = false;
820 EmitResourceReadySignal();
824 void Control::Impl::NotifyVisualEvent(Visual::Base& object, Property::Index signalId)
826 for(auto registeredIter = mVisuals.Begin(), end = mVisuals.End(); registeredIter != end; ++registeredIter)
828 Internal::Visual::Base& registeredVisualImpl = Toolkit::GetImplementation((*registeredIter)->visual);
829 if(&object == ®isteredVisualImpl)
831 Dali::Toolkit::Control handle(mControlImpl.GetOwner());
832 mVisualEventSignal.Emit(handle, (*registeredIter)->index, signalId);
838 bool Control::Impl::IsResourceReady() const
840 // Iterate through and check all the enabled visuals are ready
841 for(auto visualIter = mVisuals.Begin();
842 visualIter != mVisuals.End();
845 const Toolkit::Visual::Base visual = (*visualIter)->visual;
846 const Internal::Visual::Base& visualImpl = Toolkit::GetImplementation(visual);
848 // one of the enabled visuals is not ready
849 if(!visualImpl.IsResourceReady() && (*visualIter)->enabled)
857 Toolkit::Visual::ResourceStatus Control::Impl::GetVisualResourceStatus(Property::Index index) const
859 RegisteredVisualContainer::Iterator iter;
860 if(FindVisual(index, mVisuals, iter))
862 const Toolkit::Visual::Base visual = (*iter)->visual;
863 const Internal::Visual::Base& visualImpl = Toolkit::GetImplementation(visual);
864 return visualImpl.GetResourceStatus();
867 return Toolkit::Visual::ResourceStatus::PREPARING;
870 void Control::Impl::AddTransitions(Dali::Animation& animation,
871 const Toolkit::TransitionData& handle,
872 bool createAnimation)
874 // Setup a Transition from TransitionData.
875 const Internal::TransitionData& transitionData = Toolkit::GetImplementation(handle);
876 TransitionData::Iterator end = transitionData.End();
877 for(TransitionData::Iterator iter = transitionData.Begin();
881 TransitionData::Animator* animator = (*iter);
883 Toolkit::Visual::Base visual = GetVisualByName(mVisuals, animator->objectName);
887 #if defined(DEBUG_ENABLED)
888 Dali::TypeInfo typeInfo;
889 ControlWrapper* controlWrapperImpl = dynamic_cast<ControlWrapper*>(&mControlImpl);
890 if(controlWrapperImpl)
892 typeInfo = controlWrapperImpl->GetTypeInfo();
895 DALI_LOG_INFO(gLogFilter, Debug::Concise, "CreateTransition: Found %s visual for %s\n", visual.GetName().c_str(), typeInfo ? typeInfo.GetName().c_str() : "Unknown");
897 Internal::Visual::Base& visualImpl = Toolkit::GetImplementation(visual);
898 visualImpl.AnimateProperty(animation, *animator);
902 DALI_LOG_INFO(gLogFilter, Debug::Concise, "CreateTransition: Could not find visual. Trying actors");
903 // Otherwise, try any actor children of control (Including the control)
904 Actor child = mControlImpl.Self().FindChildByName(animator->objectName);
907 Property::Index propertyIndex = child.GetPropertyIndex(animator->propertyKey);
908 if(propertyIndex != Property::INVALID_INDEX)
910 if(animator->animate == false)
912 if(animator->targetValue.GetType() != Property::NONE)
914 child.SetProperty(propertyIndex, animator->targetValue);
917 else // animate the property
919 if(animator->initialValue.GetType() != Property::NONE)
921 child.SetProperty(propertyIndex, animator->initialValue);
924 if(createAnimation && !animation)
926 animation = Dali::Animation::New(0.1f);
929 animation.AnimateTo(Property(child, propertyIndex),
930 animator->targetValue,
931 animator->alphaFunction,
932 TimePeriod(animator->timePeriodDelay,
933 animator->timePeriodDuration));
941 Dali::Animation Control::Impl::CreateTransition(const Toolkit::TransitionData& transitionData)
943 Dali::Animation transition;
945 if(transitionData.Count() > 0)
947 AddTransitions(transition, transitionData, true);
952 void Control::Impl::DoAction(Dali::Property::Index visualIndex, Dali::Property::Index actionId, const Dali::Property::Value attributes)
954 RegisteredVisualContainer::Iterator iter;
955 if(FindVisual(visualIndex, mVisuals, iter))
957 Toolkit::GetImplementation((*iter)->visual).DoAction(actionId, attributes);
961 void Control::Impl::AppendAccessibilityAttribute(const std::string& key,
962 const std::string value)
964 Property::Value* val = mAccessibilityAttributes.Find(key);
967 mAccessibilityAttributes[key] = Property::Value(value);
971 mAccessibilityAttributes.Insert(key, value);
975 void Control::Impl::SetProperty(BaseObject* object, Property::Index index, const Property::Value& value)
977 Toolkit::Control control = Toolkit::Control::DownCast(BaseHandle(object));
981 Control& controlImpl(GetImplementation(control));
985 case Toolkit::Control::Property::STYLE_NAME:
987 controlImpl.SetStyleName(value.Get<std::string>());
991 case Toolkit::DevelControl::Property::STATE:
993 bool withTransitions = true;
994 const Property::Value* valuePtr = &value;
995 const Property::Map* map = value.GetMap();
998 Property::Value* value2 = map->Find("withTransitions");
1001 withTransitions = value2->Get<bool>();
1004 valuePtr = map->Find("state");
1009 Toolkit::DevelControl::State state(controlImpl.mImpl->mState);
1010 if(Scripting::GetEnumerationProperty<Toolkit::DevelControl::State>(*valuePtr, ControlStateTable, ControlStateTableCount, state))
1012 controlImpl.mImpl->SetState(state, withTransitions);
1018 case Toolkit::DevelControl::Property::SUB_STATE:
1020 std::string subState;
1021 if(value.Get(subState))
1023 controlImpl.mImpl->SetSubState(subState);
1028 case Toolkit::DevelControl::Property::LEFT_FOCUSABLE_ACTOR_ID:
1031 if(value.Get(focusId))
1033 controlImpl.mImpl->mLeftFocusableActorId = focusId;
1038 case Toolkit::DevelControl::Property::RIGHT_FOCUSABLE_ACTOR_ID:
1041 if(value.Get(focusId))
1043 controlImpl.mImpl->mRightFocusableActorId = focusId;
1048 case Toolkit::DevelControl::Property::ACCESSIBILITY_NAME:
1053 controlImpl.mImpl->mAccessibilityName = name;
1054 controlImpl.mImpl->mAccessibilityNameSet = true;
1058 controlImpl.mImpl->mAccessibilityNameSet = false;
1063 case Toolkit::DevelControl::Property::ACCESSIBILITY_DESCRIPTION:
1068 controlImpl.mImpl->mAccessibilityDescription = txt;
1069 controlImpl.mImpl->mAccessibilityDescriptionSet = true;
1073 controlImpl.mImpl->mAccessibilityDescriptionSet = false;
1078 case Toolkit::DevelControl::Property::ACCESSIBILITY_TRANSLATION_DOMAIN:
1083 controlImpl.mImpl->mAccessibilityTranslationDomain = txt;
1084 controlImpl.mImpl->mAccessibilityTranslationDomainSet = true;
1088 controlImpl.mImpl->mAccessibilityTranslationDomainSet = false;
1093 case Toolkit::DevelControl::Property::ACCESSIBILITY_HIGHLIGHTABLE:
1096 if(value.Get(highlightable))
1098 controlImpl.mImpl->mAccessibilityHighlightable = highlightable;
1099 controlImpl.mImpl->mAccessibilityHighlightableSet = true;
1103 controlImpl.mImpl->mAccessibilityHighlightableSet = false;
1108 case Toolkit::DevelControl::Property::ACCESSIBILITY_ROLE:
1110 Dali::Accessibility::Role val;
1113 controlImpl.mImpl->mAccessibilityRole = val;
1118 case Toolkit::DevelControl::Property::UP_FOCUSABLE_ACTOR_ID:
1121 if(value.Get(focusId))
1123 controlImpl.mImpl->mUpFocusableActorId = focusId;
1128 case Toolkit::DevelControl::Property::DOWN_FOCUSABLE_ACTOR_ID:
1131 if(value.Get(focusId))
1133 controlImpl.mImpl->mDownFocusableActorId = focusId;
1138 case Toolkit::Control::Property::KEY_INPUT_FOCUS:
1140 if(value.Get<bool>())
1142 controlImpl.SetKeyInputFocus();
1146 controlImpl.ClearKeyInputFocus();
1151 case Toolkit::Control::Property::BACKGROUND:
1155 const Property::Map* map = value.GetMap();
1156 if(map && !map->Empty())
1158 controlImpl.SetBackground(*map);
1160 else if(value.Get(url))
1162 // don't know the size to load
1163 Toolkit::Visual::Base visual = Toolkit::VisualFactory::Get().CreateVisual(url, ImageDimensions());
1166 controlImpl.mImpl->RegisterVisual(Toolkit::Control::Property::BACKGROUND, visual, DepthIndex::BACKGROUND);
1169 else if(value.Get(color))
1171 controlImpl.SetBackgroundColor(color);
1175 // The background is an empty property map, so we should clear the background
1176 controlImpl.ClearBackground();
1181 case Toolkit::Control::Property::MARGIN:
1184 if(value.Get(margin))
1186 controlImpl.mImpl->SetMargin(margin);
1191 case Toolkit::Control::Property::PADDING:
1194 if(value.Get(padding))
1196 controlImpl.mImpl->SetPadding(padding);
1201 case Toolkit::DevelControl::Property::TOOLTIP:
1203 TooltipPtr& tooltipPtr = controlImpl.mImpl->mTooltip;
1206 tooltipPtr = Tooltip::New(control);
1208 tooltipPtr->SetProperties(value);
1212 case Toolkit::DevelControl::Property::SHADOW:
1214 const Property::Map* map = value.GetMap();
1215 if(map && !map->Empty())
1217 controlImpl.mImpl->SetShadow(*map);
1221 // The shadow is an empty property map, so we should clear the shadow
1222 controlImpl.mImpl->ClearShadow();
1227 case Toolkit::DevelControl::Property::ACCESSIBILITY_ATTRIBUTES:
1229 const Property::Map* map = value.GetMap();
1230 if(map && !map->Empty())
1232 controlImpl.mImpl->mAccessibilityAttributes = *map;
1240 Property::Value Control::Impl::GetProperty(BaseObject* object, Property::Index index)
1242 Property::Value value;
1244 Toolkit::Control control = Toolkit::Control::DownCast(BaseHandle(object));
1248 Control& controlImpl(GetImplementation(control));
1252 case Toolkit::Control::Property::STYLE_NAME:
1254 value = controlImpl.GetStyleName();
1258 case Toolkit::DevelControl::Property::STATE:
1260 value = controlImpl.mImpl->mState;
1264 case Toolkit::DevelControl::Property::SUB_STATE:
1266 value = controlImpl.mImpl->mSubStateName;
1270 case Toolkit::DevelControl::Property::LEFT_FOCUSABLE_ACTOR_ID:
1272 value = controlImpl.mImpl->mLeftFocusableActorId;
1276 case Toolkit::DevelControl::Property::RIGHT_FOCUSABLE_ACTOR_ID:
1278 value = controlImpl.mImpl->mRightFocusableActorId;
1282 case Toolkit::DevelControl::Property::ACCESSIBILITY_NAME:
1284 if(controlImpl.mImpl->mAccessibilityNameSet)
1286 value = controlImpl.mImpl->mAccessibilityName;
1291 case Toolkit::DevelControl::Property::ACCESSIBILITY_DESCRIPTION:
1293 if(controlImpl.mImpl->mAccessibilityDescriptionSet)
1295 value = controlImpl.mImpl->mAccessibilityDescription;
1300 case Toolkit::DevelControl::Property::ACCESSIBILITY_TRANSLATION_DOMAIN:
1302 if(controlImpl.mImpl->mAccessibilityTranslationDomainSet)
1304 value = controlImpl.mImpl->mAccessibilityTranslationDomain;
1309 case Toolkit::DevelControl::Property::ACCESSIBILITY_HIGHLIGHTABLE:
1311 if(controlImpl.mImpl->mAccessibilityHighlightableSet)
1313 value = controlImpl.mImpl->mAccessibilityHighlightable;
1318 case Toolkit::DevelControl::Property::ACCESSIBILITY_ROLE:
1320 value = Property::Value(controlImpl.mImpl->mAccessibilityRole);
1324 case Toolkit::DevelControl::Property::UP_FOCUSABLE_ACTOR_ID:
1326 value = controlImpl.mImpl->mUpFocusableActorId;
1330 case Toolkit::DevelControl::Property::DOWN_FOCUSABLE_ACTOR_ID:
1332 value = controlImpl.mImpl->mDownFocusableActorId;
1336 case Toolkit::Control::Property::KEY_INPUT_FOCUS:
1338 value = controlImpl.HasKeyInputFocus();
1342 case Toolkit::Control::Property::BACKGROUND:
1345 Toolkit::Visual::Base visual = controlImpl.mImpl->GetVisual(Toolkit::Control::Property::BACKGROUND);
1348 visual.CreatePropertyMap(map);
1355 case Toolkit::Control::Property::MARGIN:
1357 value = controlImpl.mImpl->GetMargin();
1361 case Toolkit::Control::Property::PADDING:
1363 value = controlImpl.mImpl->GetPadding();
1367 case Toolkit::DevelControl::Property::TOOLTIP:
1370 if(controlImpl.mImpl->mTooltip)
1372 controlImpl.mImpl->mTooltip->CreatePropertyMap(map);
1378 case Toolkit::DevelControl::Property::SHADOW:
1381 Toolkit::Visual::Base visual = controlImpl.mImpl->GetVisual(Toolkit::DevelControl::Property::SHADOW);
1384 visual.CreatePropertyMap(map);
1391 case Toolkit::DevelControl::Property::ACCESSIBILITY_ATTRIBUTES:
1393 value = controlImpl.mImpl->mAccessibilityAttributes;
1402 void Control::Impl::RemoveAccessibilityAttribute(const std::string& key)
1404 Property::Value* val = mAccessibilityAttributes.Find(key);
1406 mAccessibilityAttributes[key] = Property::Value();
1409 void Control::Impl::ClearAccessibilityAttributes()
1411 mAccessibilityAttributes.Clear();
1414 void Control::Impl::SetAccessibilityReadingInfoType(const Dali::Accessibility::ReadingInfoTypes types)
1417 if(types[Dali::Accessibility::ReadingInfoType::NAME])
1419 value += READING_INFO_TYPE_NAME;
1421 if(types[Dali::Accessibility::ReadingInfoType::ROLE])
1425 value += READING_INFO_TYPE_SEPARATOR;
1427 value += READING_INFO_TYPE_ROLE;
1429 if(types[Dali::Accessibility::ReadingInfoType::DESCRIPTION])
1433 value += READING_INFO_TYPE_SEPARATOR;
1435 value += READING_INFO_TYPE_DESCRIPTION;
1437 if(types[Dali::Accessibility::ReadingInfoType::STATE])
1441 value += READING_INFO_TYPE_SEPARATOR;
1443 value += READING_INFO_TYPE_STATE;
1445 AppendAccessibilityAttribute(READING_INFO_TYPE_ATTRIBUTE_NAME, value);
1448 Dali::Accessibility::ReadingInfoTypes Control::Impl::GetAccessibilityReadingInfoType() const
1451 auto place = mAccessibilityAttributes.Find(READING_INFO_TYPE_ATTRIBUTE_NAME);
1458 Dali::Accessibility::ReadingInfoTypes types;
1459 types[Dali::Accessibility::ReadingInfoType::NAME] = true;
1460 types[Dali::Accessibility::ReadingInfoType::ROLE] = true;
1461 types[Dali::Accessibility::ReadingInfoType::DESCRIPTION] = true;
1462 types[Dali::Accessibility::ReadingInfoType::STATE] = true;
1471 Dali::Accessibility::ReadingInfoTypes types;
1473 if(value.find(READING_INFO_TYPE_NAME) != std::string::npos)
1475 types[Dali::Accessibility::ReadingInfoType::NAME] = true;
1477 if(value.find(READING_INFO_TYPE_ROLE) != std::string::npos)
1479 types[Dali::Accessibility::ReadingInfoType::ROLE] = true;
1481 if(value.find(READING_INFO_TYPE_DESCRIPTION) != std::string::npos)
1483 types[Dali::Accessibility::ReadingInfoType::DESCRIPTION] = true;
1485 if(value.find(READING_INFO_TYPE_STATE) != std::string::npos)
1487 types[Dali::Accessibility::ReadingInfoType::STATE] = true;
1493 void Control::Impl::CopyInstancedProperties(RegisteredVisualContainer& visuals, Dictionary<Property::Map>& instancedProperties)
1495 for(RegisteredVisualContainer::Iterator iter = visuals.Begin(); iter != visuals.End(); iter++)
1499 Property::Map instanceMap;
1500 Toolkit::GetImplementation((*iter)->visual).CreateInstancePropertyMap(instanceMap);
1501 instancedProperties.Add((*iter)->visual.GetName(), instanceMap);
1506 void Control::Impl::RemoveVisual(RegisteredVisualContainer& visuals, const std::string& visualName)
1508 Actor self(mControlImpl.Self());
1510 for(RegisteredVisualContainer::Iterator visualIter = visuals.Begin();
1511 visualIter != visuals.End();
1514 Toolkit::Visual::Base visual = (*visualIter)->visual;
1515 if(visual && visual.GetName() == visualName)
1517 Toolkit::GetImplementation(visual).SetOffScene(self);
1518 (*visualIter)->visual.Reset();
1519 visuals.Erase(visualIter);
1525 void Control::Impl::RemoveVisuals(RegisteredVisualContainer& visuals, DictionaryKeys& removeVisuals)
1527 Actor self(mControlImpl.Self());
1528 for(DictionaryKeys::iterator iter = removeVisuals.begin(); iter != removeVisuals.end(); ++iter)
1530 const std::string visualName = *iter;
1531 RemoveVisual(visuals, visualName);
1535 void Control::Impl::RecreateChangedVisuals(Dictionary<Property::Map>& stateVisualsToChange,
1536 Dictionary<Property::Map>& instancedProperties)
1538 Dali::CustomActor handle(mControlImpl.GetOwner());
1539 for(Dictionary<Property::Map>::iterator iter = stateVisualsToChange.Begin();
1540 iter != stateVisualsToChange.End();
1543 const std::string& visualName = (*iter).key;
1544 const Property::Map& toMap = (*iter).entry;
1546 Actor self = mControlImpl.Self();
1547 RegisteredVisualContainer::Iterator registeredVisualsiter;
1548 // Check if visual (visualName) is already registered, this is the current visual.
1549 if(FindVisual(visualName, mVisuals, registeredVisualsiter))
1551 Toolkit::Visual::Base& visual = (*registeredVisualsiter)->visual;
1554 // No longer required to know if the replaced visual's resources are ready
1555 StopObservingVisual(visual);
1557 // If control staged then visuals will be swapped once ready
1558 if(self.GetProperty<bool>(Actor::Property::CONNECTED_TO_SCENE))
1560 // Check if visual is currently in the process of being replaced ( is in removal container )
1561 RegisteredVisualContainer::Iterator visualQueuedForRemoval;
1562 if(FindVisual(visualName, mRemoveVisuals, visualQueuedForRemoval))
1564 // Visual with same visual name is already in removal container so current visual pending
1565 // Only the the last requested visual will be displayed so remove current visual which is staged but not ready.
1566 Toolkit::GetImplementation(visual).SetOffScene(self);
1567 (*registeredVisualsiter)->visual.Reset();
1568 mVisuals.Erase(registeredVisualsiter);
1572 // current visual not already in removal container so add now.
1573 DALI_LOG_INFO(gLogFilter, Debug::Verbose, "RegisterVisual Move current registered visual to removal Queue: %s \n", visualName.c_str());
1574 MoveVisual(registeredVisualsiter, mVisuals, mRemoveVisuals);
1579 // Control not staged or visual disabled so can just erase from registered visuals and new visual will be added later.
1580 (*registeredVisualsiter)->visual.Reset();
1581 mVisuals.Erase(registeredVisualsiter);
1585 const Property::Map* instancedMap = instancedProperties.FindConst(visualName);
1586 Style::ApplyVisual(handle, visualName, toMap, instancedMap);
1591 void Control::Impl::ReplaceStateVisualsAndProperties(const StylePtr oldState, const StylePtr newState, const std::string& subState)
1593 // Collect all old visual names
1594 DictionaryKeys stateVisualsToRemove;
1597 oldState->visuals.GetKeys(stateVisualsToRemove);
1598 if(!subState.empty())
1600 const StylePtr* oldSubState = oldState->subStates.FindConst(subState);
1603 DictionaryKeys subStateVisualsToRemove;
1604 (*oldSubState)->visuals.GetKeys(subStateVisualsToRemove);
1605 Merge(stateVisualsToRemove, subStateVisualsToRemove);
1610 // Collect all new visual properties
1611 Dictionary<Property::Map> stateVisualsToAdd;
1614 stateVisualsToAdd = newState->visuals;
1615 if(!subState.empty())
1617 const StylePtr* newSubState = newState->subStates.FindConst(subState);
1620 stateVisualsToAdd.Merge((*newSubState)->visuals);
1625 // If a name is in both add/remove, move it to change list.
1626 Dictionary<Property::Map> stateVisualsToChange;
1627 FindChangableVisuals(stateVisualsToAdd, stateVisualsToChange, stateVisualsToRemove);
1629 // Copy instanced properties (e.g. text label) of current visuals
1630 Dictionary<Property::Map> instancedProperties;
1631 CopyInstancedProperties(mVisuals, instancedProperties);
1633 // For each visual in remove list, remove from mVisuals
1634 RemoveVisuals(mVisuals, stateVisualsToRemove);
1636 // For each visual in add list, create and add to mVisuals
1637 Dali::CustomActor handle(mControlImpl.GetOwner());
1638 Style::ApplyVisuals(handle, stateVisualsToAdd, instancedProperties);
1640 // For each visual in change list, if it requires a new visual,
1641 // remove old visual, create and add to mVisuals
1642 RecreateChangedVisuals(stateVisualsToChange, instancedProperties);
1645 void Control::Impl::SetState(DevelControl::State newState, bool withTransitions)
1647 DevelControl::State oldState = mState;
1648 Dali::CustomActor handle(mControlImpl.GetOwner());
1649 DALI_LOG_INFO(gLogFilter, Debug::Concise, "Control::Impl::SetState: %s\n", (mState == DevelControl::NORMAL ? "NORMAL" : (mState == DevelControl::FOCUSED ? "FOCUSED" : (mState == DevelControl::DISABLED ? "DISABLED" : "NONE"))));
1651 if(mState != newState)
1653 // If mState was Disabled, and new state is Focused, should probably
1654 // store that fact, e.g. in another property that FocusManager can access.
1657 // Trigger state change and transitions
1658 // Apply new style, if stylemanager is available
1659 Toolkit::StyleManager styleManager = Toolkit::StyleManager::Get();
1662 const StylePtr stylePtr = GetImpl(styleManager).GetRecordedStyle(Toolkit::Control(mControlImpl.GetOwner()));
1666 std::string oldStateName = Scripting::GetEnumerationName<Toolkit::DevelControl::State>(oldState, ControlStateTable, ControlStateTableCount);
1667 std::string newStateName = Scripting::GetEnumerationName<Toolkit::DevelControl::State>(newState, ControlStateTable, ControlStateTableCount);
1669 const StylePtr* newStateStyle = stylePtr->subStates.Find(newStateName);
1670 const StylePtr* oldStateStyle = stylePtr->subStates.Find(oldStateName);
1671 if(oldStateStyle && newStateStyle)
1673 // Only change if both state styles exist
1674 ReplaceStateVisualsAndProperties(*oldStateStyle, *newStateStyle, mSubStateName);
1681 void Control::Impl::SetSubState(const std::string& subStateName, bool withTransitions)
1683 if(mSubStateName != subStateName)
1685 // Get existing sub-state visuals, and unregister them
1686 Dali::CustomActor handle(mControlImpl.GetOwner());
1688 Toolkit::StyleManager styleManager = Toolkit::StyleManager::Get();
1691 const StylePtr stylePtr = GetImpl(styleManager).GetRecordedStyle(Toolkit::Control(mControlImpl.GetOwner()));
1695 std::string stateName = Scripting::GetEnumerationName<Toolkit::DevelControl::State>(mState, ControlStateTable, ControlStateTableCount);
1697 const StylePtr* state = stylePtr->subStates.Find(stateName);
1700 StylePtr stateStyle(*state);
1702 const StylePtr* newStateStyle = stateStyle->subStates.Find(subStateName);
1703 const StylePtr* oldStateStyle = stateStyle->subStates.Find(mSubStateName);
1704 if(oldStateStyle && newStateStyle)
1707 ReplaceStateVisualsAndProperties(*oldStateStyle, *newStateStyle, empty);
1713 mSubStateName = subStateName;
1717 void Control::Impl::OnSceneDisconnection()
1719 Actor self = mControlImpl.Self();
1721 // Any visuals set for replacement but not yet ready should still be registered.
1722 // Reason: If a request was made to register a new visual but the control removed from scene before visual was ready
1723 // then when this control appears back on stage it should use that new visual.
1725 // Iterate through all registered visuals and set off scene
1726 SetVisualsOffScene(mVisuals, self);
1728 // Visuals pending replacement can now be taken out of the removal list and set off scene
1729 // Iterate through all replacement visuals and add to a move queue then set off scene
1730 for(auto removalIter = mRemoveVisuals.Begin(), end = mRemoveVisuals.End(); removalIter != end; removalIter++)
1732 Toolkit::GetImplementation((*removalIter)->visual).SetOffScene(self);
1735 for(auto replacedIter = mVisuals.Begin(), end = mVisuals.End(); replacedIter != end; replacedIter++)
1737 (*replacedIter)->pending = false;
1740 mRemoveVisuals.Clear();
1743 void Control::Impl::SetMargin(Extents margin)
1745 mControlImpl.mImpl->mMargin = margin;
1747 // Trigger a size negotiation request that may be needed when setting a margin.
1748 mControlImpl.RelayoutRequest();
1751 Extents Control::Impl::GetMargin() const
1753 return mControlImpl.mImpl->mMargin;
1756 void Control::Impl::SetPadding(Extents padding)
1758 mControlImpl.mImpl->mPadding = padding;
1760 // Trigger a size negotiation request that may be needed when setting a padding.
1761 mControlImpl.RelayoutRequest();
1764 Extents Control::Impl::GetPadding() const
1766 return mControlImpl.mImpl->mPadding;
1769 void Control::Impl::SetInputMethodContext(InputMethodContext& inputMethodContext)
1771 mInputMethodContext = inputMethodContext;
1774 bool Control::Impl::FilterKeyEvent(const KeyEvent& event)
1776 bool consumed(false);
1778 if(mInputMethodContext)
1780 consumed = mInputMethodContext.FilterEventKey(event);
1785 DevelControl::VisualEventSignalType& Control::Impl::VisualEventSignal()
1787 return mVisualEventSignal;
1790 void Control::Impl::SetShadow(const Property::Map& map)
1792 Toolkit::Visual::Base visual = Toolkit::VisualFactory::Get().CreateVisual(map);
1793 visual.SetName("shadow");
1797 mControlImpl.mImpl->RegisterVisual(Toolkit::DevelControl::Property::SHADOW, visual, DepthIndex::BACKGROUND_EFFECT);
1799 mControlImpl.RelayoutRequest();
1803 void Control::Impl::ClearShadow()
1805 mControlImpl.mImpl->UnregisterVisual(Toolkit::DevelControl::Property::SHADOW);
1807 // Trigger a size negotiation request that may be needed when unregistering a visual.
1808 mControlImpl.RelayoutRequest();
1811 Dali::Property Control::Impl::GetVisualProperty(Dali::Property::Index index, Dali::Property::Key visualPropertyKey)
1813 Toolkit::Visual::Base visual = GetVisualByIndex(mVisuals, index);
1816 Internal::Visual::Base& visualImpl = Toolkit::GetImplementation(visual);
1817 return visualImpl.GetPropertyObject(visualPropertyKey);
1821 return Dali::Property(handle, Property::INVALID_INDEX);
1824 void Control::Impl::MakeVisualTransition(Dali::Animation& animation, Dali::Toolkit::Control source, Dali::Property::Index visualIndex, AlphaFunction alphaFunction, TimePeriod timePeriod)
1826 Dali::Toolkit::Control sourceHandle = Dali::Toolkit::Control::DownCast(source);
1827 Property::Map sourceMap = sourceHandle.GetProperty<Property::Map>(visualIndex);
1828 Dali::Toolkit::Control destinationHandle = Dali::Toolkit::Control::DownCast(mControlImpl.Self());
1829 Property::Map destinationMap = destinationHandle.GetProperty<Property::Map>(visualIndex);
1831 Vector4 mixColor(1.0f, 1.0f, 1.0f, 1.0f);
1832 Vector4 cornerRadius(0.0f, 0.0f, 0.0f, 0.0f);
1834 if(!destinationMap.Empty())
1836 mixColor = destinationMap.Find(Dali::Toolkit::Visual::Property::MIX_COLOR)->Get<Vector4>();
1837 cornerRadius = destinationMap.Find(Toolkit::DevelVisual::Property::CORNER_RADIUS)->Get<Vector4>();
1839 if(sourceMap.Empty())
1841 sourceMap.Insert(Toolkit::Visual::Property::TYPE, Toolkit::Visual::COLOR);
1842 sourceMap.Insert(Dali::Toolkit::Visual::Property::MIX_COLOR, Color::TRANSPARENT);
1843 sourceMap.Insert(Toolkit::DevelVisual::Property::CORNER_RADIUS, cornerRadius);
1846 Vector4 sourceMixColor = sourceMap.Find(Dali::Toolkit::Visual::Property::MIX_COLOR)->Get<Vector4>();
1847 Vector4 sourceCornerRadius = sourceMap.Find(Toolkit::DevelVisual::Property::CORNER_RADIUS)->Get<Vector4>();
1849 std::vector<Dali::Property> properties;
1850 std::vector<std::pair<Property::Value, Property::Value>> values;
1852 if(Vector3(sourceMixColor) != Vector3(mixColor))
1854 properties.push_back(GetVisualProperty(visualIndex, Dali::Toolkit::Visual::Property::MIX_COLOR));
1855 values.push_back(std::make_pair(Vector3(sourceMixColor), Vector3(mixColor)));
1858 if(std::abs(sourceMixColor.a - mixColor.a) > Math::MACHINE_EPSILON_1)
1860 properties.push_back(GetVisualProperty(visualIndex, Dali::Toolkit::Visual::Property::OPACITY));
1861 values.push_back(std::make_pair(sourceMixColor.a, mixColor.a));
1864 if(sourceCornerRadius != cornerRadius)
1866 properties.push_back(GetVisualProperty(visualIndex, Dali::Toolkit::DevelVisual::Property::CORNER_RADIUS));
1867 values.push_back(std::make_pair(sourceCornerRadius, cornerRadius));
1870 for(uint32_t i = 0; i < properties.size(); ++i)
1872 if(timePeriod.delaySeconds > 0.0f)
1874 Dali::KeyFrames initialKeyframes = Dali::KeyFrames::New();
1875 initialKeyframes.Add(0.0f, values[i].first);
1876 initialKeyframes.Add(1.0f, values[i].first);
1877 animation.AnimateBetween(properties[i], initialKeyframes, TimePeriod(timePeriod.delaySeconds));
1879 Dali::KeyFrames keyframes = Dali::KeyFrames::New();
1880 keyframes.Add(0.0f, values[i].first);
1881 keyframes.Add(1.0f, values[i].second);
1882 animation.AnimateBetween(properties[i], keyframes, alphaFunction, timePeriod);
1887 void Control::Impl::EmitResourceReadySignal()
1889 if(!mIsEmittingResourceReadySignal)
1891 // Guard against calls to emit the signal during the callback
1892 mIsEmittingResourceReadySignal = true;
1894 // If the signal handler changes visual, it may become ready during this call & therefore this method will
1895 // get called again recursively. If so, mNeedToEmitResourceReady is set below, and we act on it after that secondary
1896 // invocation has completed by notifying in an Idle callback to prevent further recursion.
1897 Dali::Toolkit::Control handle(mControlImpl.GetOwner());
1898 mResourceReadySignal.Emit(handle);
1900 if(mNeedToEmitResourceReady)
1902 // Add idler to emit the signal again
1905 // The callback manager takes the ownership of the callback object.
1906 mIdleCallback = MakeCallback(this, &Control::Impl::OnIdleCallback);
1907 Adaptor::Get().AddIdle(mIdleCallback, false);
1911 mIsEmittingResourceReadySignal = false;
1915 mNeedToEmitResourceReady = true;
1919 void Control::Impl::OnIdleCallback()
1921 if(mNeedToEmitResourceReady)
1924 mNeedToEmitResourceReady = false;
1926 // A visual is ready so control may need relayouting if staged
1927 if(mControlImpl.Self().GetProperty<bool>(Actor::Property::CONNECTED_TO_SCENE))
1929 mControlImpl.RelayoutRequest();
1932 EmitResourceReadySignal();
1935 // Set the pointer to null as the callback manager deletes the callback after execute it.
1936 mIdleCallback = nullptr;
1939 Dali::Accessibility::Accessible* Control::Impl::GetAccessibilityObject()
1941 if(!accessibilityObject)
1942 accessibilityObject = accessibilityConstructor(mControlImpl.Self());
1943 return accessibilityObject.get();
1946 Dali::Accessibility::Accessible* Control::Impl::GetAccessibilityObject(Dali::Actor actor)
1950 auto q = Dali::Toolkit::Control::DownCast(actor);
1953 auto q2 = static_cast<Internal::Control*>(&q.GetImplementation());
1954 return q2->mImpl->GetAccessibilityObject();
1960 } // namespace Internal
1962 } // namespace Toolkit