2 * Copyright (c) 2024 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/math/math-utils.h>
34 #include <dali/public-api/object/object-registry.h>
35 #include <dali/public-api/object/type-registry-helper.h>
40 #include <dali-toolkit/devel-api/asset-manager/asset-manager.h>
41 #include <dali-toolkit/devel-api/controls/control-depth-index-ranges.h>
42 #include <dali-toolkit/devel-api/controls/control-devel.h>
43 #include <dali-toolkit/devel-api/controls/control-wrapper-impl.h>
44 #include <dali-toolkit/devel-api/visuals/visual-actions-devel.h>
45 #include <dali-toolkit/internal/styling/style-manager-impl.h>
46 #include <dali-toolkit/internal/visuals/visual-base-impl.h>
47 #include <dali-toolkit/internal/visuals/visual-string-constants.h>
48 #include <dali-toolkit/public-api/align-enumerations.h>
49 #include <dali-toolkit/public-api/controls/image-view/image-view.h>
50 #include <dali-toolkit/public-api/focus-manager/keyboard-focus-manager.h>
51 #include <dali-toolkit/public-api/visuals/image-visual-properties.h>
52 #include <dali-toolkit/public-api/visuals/visual-properties.h>
56 const char* READING_INFO_TYPE_NAME = "name";
57 const char* READING_INFO_TYPE_ROLE = "role";
58 const char* READING_INFO_TYPE_DESCRIPTION = "description";
59 const char* READING_INFO_TYPE_STATE = "state";
60 const char* READING_INFO_TYPE_ATTRIBUTE_NAME = "reading_info_type";
61 const char* READING_INFO_TYPE_SEPARATOR = "|";
70 extern const Dali::Scripting::StringEnum ControlStateTable[];
71 extern const unsigned int ControlStateTableCount;
73 // Not static or anonymous - shared with other translation units
74 const Scripting::StringEnum ControlStateTable[] = {
75 {"NORMAL", Toolkit::DevelControl::NORMAL},
76 {"FOCUSED", Toolkit::DevelControl::FOCUSED},
77 {"DISABLED", Toolkit::DevelControl::DISABLED},
79 const unsigned int ControlStateTableCount = sizeof(ControlStateTable) / sizeof(ControlStateTable[0]);
80 const Vector4 FULL_TEXTURE_RECT(0.f, 0.f, 1.f, 1.f);
84 #if defined(DEBUG_ENABLED)
85 Debug::Filter* gLogFilter = Debug::Filter::New(Debug::NoLogging, false, "LOG_CONTROL_VISUALS");
89 void Remove(Dictionary<T>& keyValues, const std::string& name)
91 keyValues.Remove(name);
94 void Remove(DictionaryKeys& keys, const std::string& name)
96 DictionaryKeys::iterator iter = std::find(keys.begin(), keys.end(), name);
97 if(iter != keys.end())
104 * Finds visual in given array, returning true if found along with the iterator for that visual as a out parameter
106 bool FindVisual(Property::Index targetIndex, const RegisteredVisualContainer& visuals, RegisteredVisualContainer::Iterator& iter)
108 for(iter = visuals.Begin(); iter != visuals.End(); iter++)
110 if((*iter)->index == targetIndex)
119 * Finds visual in given array, returning true if found along with the iterator for that visual as a out parameter
121 bool FindVisual(std::string visualName, const RegisteredVisualContainer& visuals, RegisteredVisualContainer::Iterator& iter)
123 for(iter = visuals.Begin(); iter != visuals.End(); iter++)
125 Toolkit::Visual::Base visual = (*iter)->visual;
126 if(visual && visual.GetName() == visualName)
135 * Finds visual in given array, returning true if found along with the iterator for that visual as a out parameter
137 bool FindVisual(const Toolkit::Visual::Base findVisual, const RegisteredVisualContainer& visuals, RegisteredVisualContainer::Iterator& iter)
139 for(iter = visuals.Begin(); iter != visuals.End(); iter++)
141 Toolkit::Visual::Base visual = (*iter)->visual;
142 if(visual && visual == findVisual)
151 * Finds internal visual in given array, returning true if found along with the iterator for that visual as a out parameter
153 bool FindVisual(const Visual::Base& findInternalVisual, const RegisteredVisualContainer& visuals, RegisteredVisualContainer::Iterator& iter)
155 for(iter = visuals.Begin(); iter != visuals.End(); iter++)
157 Visual::Base& visual = Toolkit::GetImplementation((*iter)->visual);
158 if((&visual == &findInternalVisual))
166 void FindChangableVisuals(Dictionary<Property::Map>& stateVisualsToAdd,
167 Dictionary<Property::Map>& stateVisualsToChange,
168 DictionaryKeys& stateVisualsToRemove)
170 DictionaryKeys copyOfStateVisualsToRemove = stateVisualsToRemove;
172 for(DictionaryKeys::iterator iter = copyOfStateVisualsToRemove.begin();
173 iter != copyOfStateVisualsToRemove.end();
176 const std::string& visualName = (*iter);
177 Property::Map* toMap = stateVisualsToAdd.Find(visualName);
180 stateVisualsToChange.Add(visualName, *toMap);
181 stateVisualsToAdd.Remove(visualName);
182 Remove(stateVisualsToRemove, visualName);
187 Toolkit::Visual::Base GetVisualByName(
188 const RegisteredVisualContainer& visuals,
189 const std::string& visualName)
191 Toolkit::Visual::Base visualHandle;
193 RegisteredVisualContainer::Iterator iter;
194 for(iter = visuals.Begin(); iter != visuals.End(); iter++)
196 Toolkit::Visual::Base visual = (*iter)->visual;
197 if(visual && visual.GetName() == visualName)
199 visualHandle = visual;
206 Toolkit::Visual::Base GetVisualByIndex(
207 const RegisteredVisualContainer& visuals,
208 Property::Index index)
210 Toolkit::Visual::Base visualHandle;
212 RegisteredVisualContainer::Iterator iter;
213 for(iter = visuals.Begin(); iter != visuals.End(); iter++)
215 if((*iter)->index == index)
217 visualHandle = (*iter)->visual;
225 * Move visual from source to destination container
227 void MoveVisual(RegisteredVisualContainer::Iterator sourceIter, RegisteredVisualContainer& source, RegisteredVisualContainer& destination)
229 Toolkit::Visual::Base visual = (*sourceIter)->visual;
232 RegisteredVisual* rv = source.Release(sourceIter);
233 destination.PushBack(rv);
238 * Discard visual from source to visual factory.
240 void DiscardVisual(RegisteredVisualContainer::Iterator sourceIter, RegisteredVisualContainer& source)
242 Toolkit::Visual::Base visual = (*sourceIter)->visual;
245 if(DALI_LIKELY(Dali::Adaptor::IsAvailable()))
247 Toolkit::VisualFactory::Get().DiscardVisual(visual);
251 source.Erase(sourceIter);
255 * Performs actions as requested using the action name.
256 * @param[in] object The object on which to perform the action.
257 * @param[in] actionName The action to perform.
258 * @param[in] attributes The attributes with which to perfrom this action.
259 * @return true if action has been accepted by this control
261 constexpr const char* ACTION_ACCESSIBILITY_ACTIVATE = "activate";
262 constexpr const char* ACTION_ACCESSIBILITY_ESCAPE = "escape";
263 constexpr const char* ACTION_ACCESSIBILITY_INCREMENT = "increment";
264 constexpr const char* ACTION_ACCESSIBILITY_DECREMENT = "decrement";
267 constexpr const char* ACTION_ACCESSIBILITY_READING_CANCELLED = "ReadingCancelled";
268 constexpr const char* ACTION_ACCESSIBILITY_READING_PAUSED = "ReadingPaused";
269 constexpr const char* ACTION_ACCESSIBILITY_READING_RESUMED = "ReadingResumed";
270 constexpr const char* ACTION_ACCESSIBILITY_READING_SKIPPED = "ReadingSkipped";
271 constexpr const char* ACTION_ACCESSIBILITY_READING_STOPPED = "ReadingStopped";
273 bool PerformAccessibilityAction(Toolkit::Control control, const std::string& actionName, const Property::Map& attributes)
275 using Dali::Accessibility::ActionType;
276 DALI_ASSERT_DEBUG(control);
277 DALI_ASSERT_DEBUG(!DevelControl::AccessibilityActionSignal(control).Empty());
279 ActionType action = ActionType::MAX_COUNT;
280 if(actionName == ACTION_ACCESSIBILITY_ACTIVATE)
282 action = ActionType::ACTIVATE;
284 else if(actionName == ACTION_ACCESSIBILITY_ESCAPE)
286 action = ActionType::ESCAPE;
288 else if(actionName == ACTION_ACCESSIBILITY_INCREMENT)
290 action = ActionType::INCREMENT;
292 else if(actionName == ACTION_ACCESSIBILITY_DECREMENT)
294 action = ActionType::DECREMENT;
297 if(action != ActionType::MAX_COUNT)
299 bool success = DevelControl::AccessibilityActionSignal(control).Emit({action, Dali::Actor{}});
300 DALI_LOG_INFO(gLogFilter, Debug::Verbose, "Performed AccessibilityAction: %s, success : %d\n", actionName.c_str(), success);
307 bool PerformLegacyAccessibilityAction(Toolkit::Control control, const std::string& actionName)
310 if(0 == strcmp(actionName.c_str(), ACTION_ACCESSIBILITY_ACTIVATE))
312 // if cast succeeds there is an implementation so no need to check
313 if(!DevelControl::AccessibilityActivateSignal(control).Empty())
315 DevelControl::AccessibilityActivateSignal(control).Emit();
319 ret = Internal::GetImplementation(control).OnAccessibilityActivated();
322 else if(0 == strcmp(actionName.c_str(), ACTION_ACCESSIBILITY_READING_SKIPPED))
324 // if cast succeeds there is an implementation so no need to check
325 if(!DevelControl::AccessibilityReadingSkippedSignal(control).Empty())
327 DevelControl::AccessibilityReadingSkippedSignal(control).Emit();
330 else if(0 == strcmp(actionName.c_str(), ACTION_ACCESSIBILITY_READING_PAUSED))
332 // if cast succeeds there is an implementation so no need to check
333 if(!DevelControl::AccessibilityReadingPausedSignal(control).Empty())
335 DevelControl::AccessibilityReadingPausedSignal(control).Emit();
338 else if(0 == strcmp(actionName.c_str(), ACTION_ACCESSIBILITY_READING_RESUMED))
340 // if cast succeeds there is an implementation so no need to check
341 if(!DevelControl::AccessibilityReadingResumedSignal(control).Empty())
343 DevelControl::AccessibilityReadingResumedSignal(control).Emit();
346 else if(0 == strcmp(actionName.c_str(), ACTION_ACCESSIBILITY_READING_CANCELLED))
348 // if cast succeeds there is an implementation so no need to check
349 if(!DevelControl::AccessibilityReadingCancelledSignal(control).Empty())
351 DevelControl::AccessibilityReadingCancelledSignal(control).Emit();
354 else if(0 == strcmp(actionName.c_str(), ACTION_ACCESSIBILITY_READING_STOPPED))
356 // if cast succeeds there is an implementation so no need to check
357 if(!DevelControl::AccessibilityReadingStoppedSignal(control).Empty())
359 DevelControl::AccessibilityReadingStoppedSignal(control).Emit();
369 DALI_LOG_INFO(gLogFilter, Debug::Verbose, "Performed Legacy AccessibilityAction: %s\n", actionName.c_str());
374 bool DoAccessibilityAction(BaseObject* object, const std::string& actionName, const Property::Map& attributes)
376 Dali::BaseHandle handle(object);
378 Toolkit::Control control = Toolkit::Control::DownCast(handle);
380 DALI_ASSERT_ALWAYS(control);
382 if(!DevelControl::AccessibilityActionSignal(control).Empty())
384 return PerformAccessibilityAction(control, actionName, attributes);
387 // Fall back to legacy action is no ActionSignal is connected
388 return PerformLegacyAccessibilityAction(control, actionName);
391 bool DoLegacyAccessibilityAction(BaseObject* object, const std::string& actionName, const Property::Map& attributes)
393 Dali::BaseHandle handle(object);
395 Toolkit::Control control = Toolkit::Control::DownCast(handle);
397 DALI_ASSERT_ALWAYS(control);
399 return PerformLegacyAccessibilityAction(control, actionName);
403 * Connects a callback function with the object's signals.
404 * @param[in] object The object providing the signal.
405 * @param[in] tracker Used to disconnect the signal.
406 * @param[in] signalName The signal to connect to.
407 * @param[in] functor A newly allocated FunctorDelegate.
408 * @return True if the signal was connected.
409 * @post If a signal was connected, ownership of functor was passed to CallbackBase. Otherwise the caller is responsible for deleting the unused functor.
411 const char* SIGNAL_KEY_EVENT = "keyEvent";
412 const char* SIGNAL_KEY_INPUT_FOCUS_GAINED = "keyInputFocusGained";
413 const char* SIGNAL_KEY_INPUT_FOCUS_LOST = "keyInputFocusLost";
414 const char* SIGNAL_TAPPED = "tapped";
415 const char* SIGNAL_PANNED = "panned";
416 const char* SIGNAL_PINCHED = "pinched";
417 const char* SIGNAL_LONG_PRESSED = "longPressed";
418 const char* SIGNAL_GET_NAME = "getName";
419 const char* SIGNAL_GET_DESCRIPTION = "getDescription";
420 const char* SIGNAL_DO_GESTURE = "doGesture";
421 static bool DoConnectSignal(BaseObject* object, ConnectionTrackerInterface* tracker, const std::string& signalName, FunctorDelegate* functor)
423 Dali::BaseHandle handle(object);
425 bool connected(false);
426 Toolkit::Control control = Toolkit::Control::DownCast(handle);
429 Internal::Control& controlImpl(Internal::GetImplementation(control));
432 if(0 == strcmp(signalName.c_str(), SIGNAL_KEY_EVENT))
434 controlImpl.KeyEventSignal().Connect(tracker, functor);
436 else if(0 == strcmp(signalName.c_str(), SIGNAL_KEY_INPUT_FOCUS_GAINED))
438 controlImpl.KeyInputFocusGainedSignal().Connect(tracker, functor);
440 else if(0 == strcmp(signalName.c_str(), SIGNAL_KEY_INPUT_FOCUS_LOST))
442 controlImpl.KeyInputFocusLostSignal().Connect(tracker, functor);
444 else if(0 == strcmp(signalName.c_str(), SIGNAL_TAPPED))
446 controlImpl.EnableGestureDetection(GestureType::TAP);
447 controlImpl.GetTapGestureDetector().DetectedSignal().Connect(tracker, functor);
449 else if(0 == strcmp(signalName.c_str(), SIGNAL_PANNED))
451 controlImpl.EnableGestureDetection(GestureType::PAN);
452 controlImpl.GetPanGestureDetector().DetectedSignal().Connect(tracker, functor);
454 else if(0 == strcmp(signalName.c_str(), SIGNAL_PINCHED))
456 controlImpl.EnableGestureDetection(GestureType::PINCH);
457 controlImpl.GetPinchGestureDetector().DetectedSignal().Connect(tracker, functor);
459 else if(0 == strcmp(signalName.c_str(), SIGNAL_LONG_PRESSED))
461 controlImpl.EnableGestureDetection(GestureType::LONG_PRESS);
462 controlImpl.GetLongPressGestureDetector().DetectedSignal().Connect(tracker, functor);
464 else if(0 == strcmp(signalName.c_str(), SIGNAL_GET_NAME))
466 DevelControl::AccessibilityGetNameSignal(control).Connect(tracker, functor);
468 else if(0 == strcmp(signalName.c_str(), SIGNAL_GET_DESCRIPTION))
470 DevelControl::AccessibilityGetDescriptionSignal(control).Connect(tracker, functor);
472 else if(0 == strcmp(signalName.c_str(), SIGNAL_DO_GESTURE))
474 DevelControl::AccessibilityDoGestureSignal(control).Connect(tracker, functor);
481 * Creates control through type registry
485 return Internal::Control::New();
487 // Setup signals and actions using the type-registry.
488 DALI_TYPE_REGISTRATION_BEGIN(Control, CustomActor, Create);
490 // Note: Properties are registered separately below.
492 SignalConnectorType registerSignal1(typeRegistration, SIGNAL_KEY_EVENT, &DoConnectSignal);
493 SignalConnectorType registerSignal2(typeRegistration, SIGNAL_KEY_INPUT_FOCUS_GAINED, &DoConnectSignal);
494 SignalConnectorType registerSignal3(typeRegistration, SIGNAL_KEY_INPUT_FOCUS_LOST, &DoConnectSignal);
495 SignalConnectorType registerSignal4(typeRegistration, SIGNAL_TAPPED, &DoConnectSignal);
496 SignalConnectorType registerSignal5(typeRegistration, SIGNAL_PANNED, &DoConnectSignal);
497 SignalConnectorType registerSignal6(typeRegistration, SIGNAL_PINCHED, &DoConnectSignal);
498 SignalConnectorType registerSignal7(typeRegistration, SIGNAL_LONG_PRESSED, &DoConnectSignal);
499 SignalConnectorType registerSignal8(typeRegistration, SIGNAL_GET_NAME, &DoConnectSignal);
500 SignalConnectorType registerSignal9(typeRegistration, SIGNAL_GET_DESCRIPTION, &DoConnectSignal);
501 SignalConnectorType registerSignal10(typeRegistration, SIGNAL_DO_GESTURE, &DoConnectSignal);
503 // === Accessibility Actions === START
504 TypeAction registerAction1(typeRegistration, ACTION_ACCESSIBILITY_ACTIVATE, &DoAccessibilityAction);
505 TypeAction registerAction2(typeRegistration, ACTION_ACCESSIBILITY_ESCAPE, &DoAccessibilityAction);
506 TypeAction registerAction3(typeRegistration, ACTION_ACCESSIBILITY_INCREMENT, &DoAccessibilityAction);
507 TypeAction registerAction4(typeRegistration, ACTION_ACCESSIBILITY_DECREMENT, &DoAccessibilityAction);
508 // === Accessibility Actions === END
510 // === Legacy Accessibility Actions === START
511 TypeAction registerAction5(typeRegistration, ACTION_ACCESSIBILITY_READING_SKIPPED, &DoLegacyAccessibilityAction);
512 TypeAction registerAction6(typeRegistration, ACTION_ACCESSIBILITY_READING_CANCELLED, &DoLegacyAccessibilityAction);
513 TypeAction registerAction7(typeRegistration, ACTION_ACCESSIBILITY_READING_STOPPED, &DoLegacyAccessibilityAction);
514 TypeAction registerAction8(typeRegistration, ACTION_ACCESSIBILITY_READING_PAUSED, &DoLegacyAccessibilityAction);
515 TypeAction registerAction9(typeRegistration, ACTION_ACCESSIBILITY_READING_RESUMED, &DoLegacyAccessibilityAction);
516 // === Legacy Accessibility Actions === END
518 DALI_TYPE_REGISTRATION_END()
521 * @brief Iterate through given container and setOffScene any visual found
523 * @param[in] container Container of visuals
524 * @param[in] parent Parent actor to remove visuals from
526 void SetVisualsOffScene(const RegisteredVisualContainer& container, Actor parent)
528 for(auto iter = container.Begin(), end = container.End(); iter != end; iter++)
532 DALI_LOG_INFO(gLogFilter, Debug::Verbose, "Control::SetOffScene Setting visual(%d) off stage\n", (*iter)->index);
533 Toolkit::GetImplementation((*iter)->visual).SetOffScene(parent);
538 Dali::Rect<> GetShowingGeometry(Dali::Rect<> rect, Dali::Toolkit::DevelControl::ControlAccessible* accessible)
541 Vector2 currentPosition;
542 auto parent = dynamic_cast<Toolkit::DevelControl::ControlAccessible*>(accessible->GetParent());
546 parentRect = parent->GetExtents(Dali::Accessibility::CoordinateType::WINDOW);
548 currentPosition.x = rect.x;
549 currentPosition.y = rect.y;
551 rect.x = rect.x > parentRect.x ? rect.x : parentRect.x;
552 rect.y = rect.y > parentRect.y ? rect.y : parentRect.y;
553 rect.width = currentPosition.x + rect.width < parentRect.x + parentRect.width ? currentPosition.x + rect.width - rect.x : parentRect.x + parentRect.width - rect.x;
554 rect.height = currentPosition.y + rect.height < parentRect.y + parentRect.height ? currentPosition.y + rect.height - rect.y : parentRect.y + parentRect.height - rect.y;
556 if(rect.width < 0 || rect.height < 0)
561 parent = dynamic_cast<Toolkit::DevelControl::ControlAccessible*>(parent->GetParent());
567 static bool IsShowingGeometryOnScreen(Dali::Rect<> rect)
569 return rect.width > 0 && rect.height > 0;
572 } // unnamed namespace
575 // Properties registered without macro to use specific member variables.
576 const PropertyRegistration Control::Impl::PROPERTY_1(typeRegistration, "styleName", Toolkit::Control::Property::STYLE_NAME, Property::STRING, &Control::Impl::SetProperty, &Control::Impl::GetProperty);
577 const PropertyRegistration Control::Impl::PROPERTY_4(typeRegistration, "keyInputFocus", Toolkit::Control::Property::KEY_INPUT_FOCUS, Property::BOOLEAN, &Control::Impl::SetProperty, &Control::Impl::GetProperty);
578 const PropertyRegistration Control::Impl::PROPERTY_5(typeRegistration, "background", Toolkit::Control::Property::BACKGROUND, Property::MAP, &Control::Impl::SetProperty, &Control::Impl::GetProperty);
579 const PropertyRegistration Control::Impl::PROPERTY_6(typeRegistration, "margin", Toolkit::Control::Property::MARGIN, Property::EXTENTS, &Control::Impl::SetProperty, &Control::Impl::GetProperty);
580 const PropertyRegistration Control::Impl::PROPERTY_7(typeRegistration, "padding", Toolkit::Control::Property::PADDING, Property::EXTENTS, &Control::Impl::SetProperty, &Control::Impl::GetProperty);
581 const PropertyRegistration Control::Impl::PROPERTY_8(typeRegistration, "tooltip", Toolkit::DevelControl::Property::TOOLTIP, Property::MAP, &Control::Impl::SetProperty, &Control::Impl::GetProperty);
582 const PropertyRegistration Control::Impl::PROPERTY_9(typeRegistration, "state", Toolkit::DevelControl::Property::STATE, Property::STRING, &Control::Impl::SetProperty, &Control::Impl::GetProperty);
583 const PropertyRegistration Control::Impl::PROPERTY_10(typeRegistration, "subState", Toolkit::DevelControl::Property::SUB_STATE, Property::STRING, &Control::Impl::SetProperty, &Control::Impl::GetProperty);
584 const PropertyRegistration Control::Impl::PROPERTY_11(typeRegistration, "leftFocusableActorId", Toolkit::DevelControl::Property::LEFT_FOCUSABLE_ACTOR_ID, Property::INTEGER, &Control::Impl::SetProperty, &Control::Impl::GetProperty);
585 const PropertyRegistration Control::Impl::PROPERTY_12(typeRegistration, "rightFocusableActorId", Toolkit::DevelControl::Property::RIGHT_FOCUSABLE_ACTOR_ID, Property::INTEGER, &Control::Impl::SetProperty, &Control::Impl::GetProperty);
586 const PropertyRegistration Control::Impl::PROPERTY_13(typeRegistration, "upFocusableActorId", Toolkit::DevelControl::Property::UP_FOCUSABLE_ACTOR_ID, Property::INTEGER, &Control::Impl::SetProperty, &Control::Impl::GetProperty);
587 const PropertyRegistration Control::Impl::PROPERTY_14(typeRegistration, "downFocusableActorId", Toolkit::DevelControl::Property::DOWN_FOCUSABLE_ACTOR_ID, Property::INTEGER, &Control::Impl::SetProperty, &Control::Impl::GetProperty);
588 const PropertyRegistration Control::Impl::PROPERTY_15(typeRegistration, "shadow", Toolkit::DevelControl::Property::SHADOW, Property::MAP, &Control::Impl::SetProperty, &Control::Impl::GetProperty);
589 const PropertyRegistration Control::Impl::PROPERTY_16(typeRegistration, "accessibilityName", Toolkit::DevelControl::Property::ACCESSIBILITY_NAME, Property::STRING, &Control::Impl::SetProperty, &Control::Impl::GetProperty);
590 const PropertyRegistration Control::Impl::PROPERTY_17(typeRegistration, "accessibilityDescription", Toolkit::DevelControl::Property::ACCESSIBILITY_DESCRIPTION, Property::STRING, &Control::Impl::SetProperty, &Control::Impl::GetProperty);
591 const PropertyRegistration Control::Impl::PROPERTY_18(typeRegistration, "accessibilityTranslationDomain", Toolkit::DevelControl::Property::ACCESSIBILITY_TRANSLATION_DOMAIN, Property::STRING, &Control::Impl::SetProperty, &Control::Impl::GetProperty);
592 const PropertyRegistration Control::Impl::PROPERTY_19(typeRegistration, "accessibilityRole", Toolkit::DevelControl::Property::ACCESSIBILITY_ROLE, Property::INTEGER, &Control::Impl::SetProperty, &Control::Impl::GetProperty);
593 const PropertyRegistration Control::Impl::PROPERTY_20(typeRegistration, "accessibilityHighlightable", Toolkit::DevelControl::Property::ACCESSIBILITY_HIGHLIGHTABLE, Property::BOOLEAN, &Control::Impl::SetProperty, &Control::Impl::GetProperty);
594 const PropertyRegistration Control::Impl::PROPERTY_21(typeRegistration, "accessibilityAttributes", Toolkit::DevelControl::Property::ACCESSIBILITY_ATTRIBUTES, Property::MAP, &Control::Impl::SetProperty, &Control::Impl::GetProperty);
595 const PropertyRegistration Control::Impl::PROPERTY_22(typeRegistration, "dispatchKeyEvents", Toolkit::DevelControl::Property::DISPATCH_KEY_EVENTS, Property::BOOLEAN, &Control::Impl::SetProperty, &Control::Impl::GetProperty);
596 const PropertyRegistration Control::Impl::PROPERTY_23(typeRegistration, "accessibilityHidden", Toolkit::DevelControl::Property::ACCESSIBILITY_HIDDEN, Property::BOOLEAN, &Control::Impl::SetProperty, &Control::Impl::GetProperty);
597 const PropertyRegistration Control::Impl::PROPERTY_24(typeRegistration, "clockwiseFocusableActorId", Toolkit::DevelControl::Property::CLOCKWISE_FOCUSABLE_ACTOR_ID, Property::INTEGER, &Control::Impl::SetProperty, &Control::Impl::GetProperty);
598 const PropertyRegistration Control::Impl::PROPERTY_25(typeRegistration, "counterClockwiseFocusableActorId", Toolkit::DevelControl::Property::COUNTER_CLOCKWISE_FOCUSABLE_ACTOR_ID, Property::INTEGER, &Control::Impl::SetProperty, &Control::Impl::GetProperty);
599 const PropertyRegistration Control::Impl::PROPERTY_26(typeRegistration, "automationId", Toolkit::DevelControl::Property::AUTOMATION_ID, Property::STRING, &Control::Impl::SetProperty, &Control::Impl::GetProperty);
600 const PropertyRegistration Control::Impl::PROPERTY_27(typeRegistration, "accessibilityValue", Toolkit::DevelControl::Property::ACCESSIBILITY_VALUE, Property::STRING, &Control::Impl::SetProperty, &Control::Impl::GetProperty);
601 const PropertyRegistration Control::Impl::PROPERTY_28(typeRegistration, "accessibilityScrollable", Toolkit::DevelControl::Property::ACCESSIBILITY_SCROLLABLE, Property::BOOLEAN, &Control::Impl::SetProperty, &Control::Impl::GetProperty);
602 const PropertyRegistration Control::Impl::PROPERTY_29(typeRegistration, "accessibilityStates", Toolkit::DevelControl::Property::ACCESSIBILITY_STATES, Property::INTEGER, &Control::Impl::SetProperty, &Control::Impl::GetProperty);
603 const PropertyRegistration Control::Impl::PROPERTY_30(typeRegistration, "accessibilityIsModal", Toolkit::DevelControl::Property::ACCESSIBILITY_IS_MODAL, Property::BOOLEAN, &Control::Impl::SetProperty, &Control::Impl::GetProperty);
607 Control::Impl::Impl(Control& controlImpl)
608 : mControlImpl(controlImpl),
609 mState(Toolkit::DevelControl::NORMAL),
611 mLeftFocusableActorId(-1),
612 mRightFocusableActorId(-1),
613 mUpFocusableActorId(-1),
614 mDownFocusableActorId(-1),
615 mClockwiseFocusableActorId(-1),
616 mCounterClockwiseFocusableActorId(-1),
618 mBackgroundColor(Color::TRANSPARENT),
619 mStartingPinchScale(nullptr),
621 mPadding(0, 0, 0, 0),
624 mKeyInputFocusGainedSignal(),
625 mKeyInputFocusLostSignal(),
626 mResourceReadySignal(),
627 mVisualEventSignal(),
628 mAccessibilityGetNameSignal(),
629 mAccessibilityGetDescriptionSignal(),
630 mAccessibilityDoGestureSignal(),
631 mPinchGestureDetector(),
632 mPanGestureDetector(),
633 mTapGestureDetector(),
634 mLongPressGestureDetector(),
636 mInputMethodContext(),
637 mIdleCallback(nullptr),
638 mFlags(Control::ControlBehaviour(CONTROL_BEHAVIOUR_DEFAULT)),
639 mIsKeyboardNavigationSupported(false),
640 mIsKeyboardFocusGroup(false),
641 mIsEmittingResourceReadySignal(false),
642 mIdleCallbackRegistered(false),
643 mDispatchKeyEvents(true),
644 mProcessorRegistered(false)
646 Accessibility::Accessible::RegisterExternalAccessibleGetter([](Dali::Actor actor) -> std::pair<std::shared_ptr<Accessibility::Accessible>, bool> {
647 auto control = Toolkit::Control::DownCast(actor);
650 return {nullptr, true};
653 auto& controlImpl = Toolkit::Internal::GetImplementation(control);
654 if(controlImpl.mImpl->IsCreateAccessibleEnabled())
656 return {std::shared_ptr<DevelControl::ControlAccessible>(controlImpl.CreateAccessibleObject()), true};
659 return {nullptr, false};
661 mAccessibilityProps.states[DevelControl::AccessibilityState::ENABLED] = true;
664 Control::Impl::~Impl()
666 while(!mVisuals.Empty())
668 auto iter = mVisuals.End() - 1u;
669 StopObservingVisual((*iter)->visual);
671 // Discard removed visual. It will be destroyed at next Idle time.
672 DiscardVisual(iter, mVisuals);
675 while(!mRemoveVisuals.Empty())
677 auto removalIter = mRemoveVisuals.End() - 1u;
678 StopObservingVisual((*removalIter)->visual);
680 // Discard removed visual. It will be destroyed at next Idle time.
681 DiscardVisual(removalIter, mRemoveVisuals);
684 // All gesture detectors will be destroyed so no need to disconnect.
685 delete mStartingPinchScale;
687 if(mProcessorRegistered && Adaptor::IsAvailable())
689 // Unregister the processor from the adaptor
690 Adaptor::Get().UnregisterProcessorOnce(*this, true);
693 if(mIdleCallback && Adaptor::IsAvailable())
695 // Removes the callback from the callback manager in case the control is destroyed before the callback is executed.
696 Adaptor::Get().RemoveIdle(mIdleCallback);
700 Control::Impl& Control::Impl::Get(Internal::Control& internalControl)
702 DALI_ASSERT_ALWAYS(Stage::IsCoreThread() && "Core is not installed. Might call this API from worker thread?");
704 return *internalControl.mImpl;
707 const Control::Impl& Control::Impl::Get(const Internal::Control& internalControl)
709 DALI_ASSERT_ALWAYS(Stage::IsCoreThread() && "Core is not installed. Might call this API from worker thread?");
711 return *internalControl.mImpl;
714 void Control::Impl::CheckHighlightedObjectGeometry()
716 auto accessible = GetAccessibleObject();
717 if(DALI_LIKELY(accessible))
719 auto lastPosition = accessible->GetLastPosition();
720 auto accessibleRect = accessible->GetExtents(Dali::Accessibility::CoordinateType::WINDOW);
721 auto rect = GetShowingGeometry(accessibleRect, accessible.get());
723 switch(mAccessibilityLastScreenRelativeMoveType)
725 case Dali::Accessibility::ScreenRelativeMoveType::OUTSIDE:
727 if(IsShowingGeometryOnScreen(rect))
729 mAccessibilityLastScreenRelativeMoveType = Dali::Accessibility::ScreenRelativeMoveType::INSIDE;
733 case Dali::Accessibility::ScreenRelativeMoveType::INSIDE:
735 if(rect.width < 0 && !Dali::Equals(accessibleRect.x, lastPosition.x))
737 mAccessibilityLastScreenRelativeMoveType = (accessibleRect.x < lastPosition.x) ? Dali::Accessibility::ScreenRelativeMoveType::OUTGOING_TOP_LEFT : Dali::Accessibility::ScreenRelativeMoveType::OUTGOING_BOTTOM_RIGHT;
739 if(rect.height < 0 && !Dali::Equals(accessibleRect.y, lastPosition.y))
741 mAccessibilityLastScreenRelativeMoveType = (accessibleRect.y < lastPosition.y) ? Dali::Accessibility::ScreenRelativeMoveType::OUTGOING_TOP_LEFT : Dali::Accessibility::ScreenRelativeMoveType::OUTGOING_BOTTOM_RIGHT;
743 // notify AT-clients on outgoing moves only
744 if(mAccessibilityLastScreenRelativeMoveType != Dali::Accessibility::ScreenRelativeMoveType::INSIDE)
746 accessible->EmitMovedOutOfScreen(mAccessibilityLastScreenRelativeMoveType);
750 case Dali::Accessibility::ScreenRelativeMoveType::OUTGOING_TOP_LEFT:
751 case Dali::Accessibility::ScreenRelativeMoveType::OUTGOING_BOTTOM_RIGHT:
753 if(IsShowingGeometryOnScreen(rect))
755 mAccessibilityLastScreenRelativeMoveType = Dali::Accessibility::ScreenRelativeMoveType::INSIDE;
759 mAccessibilityLastScreenRelativeMoveType = Dali::Accessibility::ScreenRelativeMoveType::OUTSIDE;
769 accessible->SetLastPosition(Vector2(accessibleRect.x, accessibleRect.y));
773 void Control::Impl::RegisterAccessibilityPositionPropertyNotification()
775 if(mIsAccessibilityPositionPropertyNotificationSet)
779 // set default value until first move of object is detected
780 mAccessibilityLastScreenRelativeMoveType = Dali::Accessibility::ScreenRelativeMoveType::OUTSIDE;
781 // recalculate mAccessibilityLastScreenRelativeMoveType accordingly to the initial position
782 CheckHighlightedObjectGeometry();
783 mAccessibilityPositionNotification = mControlImpl.Self().AddPropertyNotification(Actor::Property::WORLD_POSITION, StepCondition(1.0f, 1.0f));
784 mAccessibilityPositionNotification.SetNotifyMode(PropertyNotification::NOTIFY_ON_CHANGED);
785 mAccessibilityPositionNotification.NotifySignal().Connect(this, [this](PropertyNotification&) { CheckHighlightedObjectGeometry(); });
786 mIsAccessibilityPositionPropertyNotificationSet = true;
789 void Control::Impl::UnregisterAccessibilityPositionPropertyNotification()
791 mControlImpl.Self().RemovePropertyNotification(mAccessibilityPositionNotification);
792 mIsAccessibilityPositionPropertyNotificationSet = false;
795 void Control::Impl::RegisterAccessibilityPropertySetSignal()
797 if(mIsAccessibilityPropertySetSignalRegistered)
801 mControlImpl.Self().PropertySetSignal().Connect(this, &Control::Impl::OnAccessibilityPropertySet);
802 mIsAccessibilityPropertySetSignalRegistered = true;
805 void Control::Impl::UnregisterAccessibilityPropertySetSignal()
807 if(!mIsAccessibilityPropertySetSignalRegistered)
811 mControlImpl.Self().PropertySetSignal().Disconnect(this, &Control::Impl::OnAccessibilityPropertySet);
812 mIsAccessibilityPropertySetSignalRegistered = false;
815 void Control::Impl::OnAccessibilityPropertySet(Dali::Handle& handle, Dali::Property::Index index, const Dali::Property::Value& value)
817 auto accessible = GetAccessibleObject();
818 if(DALI_LIKELY(accessible))
820 if(mAccessibilityGetNameSignal.Empty())
822 if(index == DevelControl::Property::ACCESSIBILITY_NAME || (mAccessibilityProps.name.empty() && index == accessible->GetNamePropertyIndex()))
824 accessible->Emit(Dali::Accessibility::ObjectPropertyChangeEvent::NAME);
829 if(mAccessibilityGetDescriptionSignal.Empty())
831 if(index == DevelControl::Property::ACCESSIBILITY_DESCRIPTION || (mAccessibilityProps.description.empty() && index == accessible->GetDescriptionPropertyIndex()))
833 accessible->Emit(Dali::Accessibility::ObjectPropertyChangeEvent::DESCRIPTION);
838 if(index == DevelControl::Property::ACCESSIBILITY_VALUE)
840 accessible->Emit(Dali::Accessibility::ObjectPropertyChangeEvent::VALUE);
844 if(index == DevelControl::Property::ACCESSIBILITY_STATES)
846 accessible->OnStatePropertySet(mAccessibilityProps.states);
852 // Gesture Detection Methods
853 void Control::Impl::PinchDetected(Actor actor, const PinchGesture& pinch)
855 mControlImpl.OnPinch(pinch);
858 void Control::Impl::PanDetected(Actor actor, const PanGesture& pan)
860 mControlImpl.OnPan(pan);
863 void Control::Impl::TapDetected(Actor actor, const TapGesture& tap)
865 mControlImpl.OnTap(tap);
868 void Control::Impl::LongPressDetected(Actor actor, const LongPressGesture& longPress)
870 mControlImpl.OnLongPress(longPress);
873 void Control::Impl::RegisterVisual(Property::Index index, Toolkit::Visual::Base& visual)
875 RegisterVisual(index, visual, VisualState::ENABLED, DepthIndexValue::NOT_SET);
878 void Control::Impl::RegisterVisual(Property::Index index, Toolkit::Visual::Base& visual, int depthIndex)
880 RegisterVisual(index, visual, VisualState::ENABLED, DepthIndexValue::SET, depthIndex);
883 void Control::Impl::RegisterVisual(Property::Index index, Toolkit::Visual::Base& visual, bool enabled)
885 RegisterVisual(index, visual, (enabled ? VisualState::ENABLED : VisualState::DISABLED), DepthIndexValue::NOT_SET);
888 void Control::Impl::RegisterVisual(Property::Index index, Toolkit::Visual::Base& visual, bool enabled, int depthIndex)
890 RegisterVisual(index, visual, (enabled ? VisualState::ENABLED : VisualState::DISABLED), DepthIndexValue::SET, depthIndex);
893 void Control::Impl::RegisterVisual(Property::Index index, Toolkit::Visual::Base& visual, VisualState::Type enabled, DepthIndexValue::Type depthIndexValueSet, int depthIndex)
895 DALI_ASSERT_ALWAYS(Stage::IsCoreThread() && "Core is not installed. Might call this API from worker thread?");
897 DALI_LOG_INFO(gLogFilter, Debug::Concise, "RegisterVisual:%d \n", index);
899 bool visualReplaced(false);
900 Actor self = mControlImpl.Self();
902 // Set the depth index, if not set by caller this will be either the current visual depth, max depth of all visuals
904 int requiredDepthIndex = visual.GetDepthIndex();
906 if(depthIndexValueSet == DepthIndexValue::SET)
908 requiredDepthIndex = depthIndex;
911 // Change the depth index value automatically if the visual has DepthIndex to AUTO_INDEX
912 // or if RegisterVisual set DepthIndex to AUTO_INDEX.
913 const bool requiredDepthIndexChanged = (requiredDepthIndex == DepthIndex::AUTO_INDEX);
915 // Visual replacement, existing visual should only be removed from stage when replacement ready.
916 if(!mVisuals.Empty())
918 RegisteredVisualContainer::Iterator registeredVisualsiter;
919 // Check if visual (index) is already registered, this is the current visual.
920 if(FindVisual(index, mVisuals, registeredVisualsiter))
922 Toolkit::Visual::Base& currentRegisteredVisual = (*registeredVisualsiter)->visual;
923 if(currentRegisteredVisual)
925 // Store current visual depth index as may need to set the replacement visual to same depth
926 const int currentDepthIndex = (*registeredVisualsiter)->visual.GetDepthIndex();
928 // No longer required to know if the replaced visual's resources are ready
929 StopObservingVisual(currentRegisteredVisual);
931 // If control staged and visual enabled then visuals will be swapped once ready
932 if(self.GetProperty<bool>(Actor::Property::CONNECTED_TO_SCENE) && enabled)
934 // Check if visual is currently in the process of being replaced ( is in removal container )
935 RegisteredVisualContainer::Iterator visualQueuedForRemoval;
936 if(FindVisual(index, mRemoveVisuals, visualQueuedForRemoval))
938 // Visual with same index is already in removal container so current visual pending
939 // Only the the last requested visual will be displayed so remove current visual which is staged but not ready.
940 Toolkit::GetImplementation(currentRegisteredVisual).SetOffScene(self);
941 mVisuals.Erase(registeredVisualsiter);
945 // current visual not already in removal container so add now.
946 DALI_LOG_INFO(gLogFilter, Debug::Verbose, "RegisterVisual Move current registered visual to removal Queue: %d \n", index);
947 MoveVisual(registeredVisualsiter, mVisuals, mRemoveVisuals);
952 // Control not staged or visual disabled so can just erase from registered visuals and new visual will be added later.
953 mVisuals.Erase(registeredVisualsiter);
956 // If the visual have a depth index as AUTO_INDEX and the new visual does not have a depth index applied to it, then use the previously set depth-index for this index
957 if(requiredDepthIndexChanged)
959 requiredDepthIndex = currentDepthIndex;
960 DALI_LOG_INFO(gLogFilter, Debug::Verbose, "Use replaced visual index. VisualDepthIndex AUTO_INDEX set as: %d\n", requiredDepthIndex);
964 visualReplaced = true;
968 // If not set, set the name of the visual to the same name as the control's property.
969 // ( If the control has been type registered )
970 if(visual.GetName().empty())
972 // returns empty string if index is not found as long as index is not -1
973 std::string visualName = self.GetPropertyName(index);
974 if(!visualName.empty())
976 DALI_LOG_INFO(gLogFilter, Debug::Concise, "Setting visual name for property %d to %s\n", index, visualName.c_str());
977 visual.SetName(visualName);
981 if(!visualReplaced) // New registration entry
983 // If we have more than one visual and the visual have a depth index as AUTO_INDEX, then set it to be the highest
984 if((mVisuals.Size() > 0) && requiredDepthIndexChanged)
986 int maxDepthIndex = static_cast<int>(DepthIndex::CONTENT) - 1; // Start at DepthIndex::CONTENT if maxDepth index belongs to a background or no visuals have been added yet.
988 RegisteredVisualContainer::ConstIterator iter;
989 const RegisteredVisualContainer::ConstIterator endIter = mVisuals.End();
990 for(iter = mVisuals.Begin(); iter != endIter; iter++)
992 const int visualDepthIndex = (*iter)->visual.GetDepthIndex();
993 if(visualDepthIndex > maxDepthIndex)
995 maxDepthIndex = visualDepthIndex;
998 requiredDepthIndex = ++maxDepthIndex; // Add one to the current maximum depth index so that our added visual appears on top.
999 DALI_LOG_INFO(gLogFilter, Debug::Verbose, "Use top of all visuals. VisualDepthIndex AUTO_INDEX set as: %d\n", requiredDepthIndex);
1005 // If required depth index still DepthIndex::AUTO_INDEX, Make it as DepthIndex::CONTENT now
1006 if(requiredDepthIndex == static_cast<int>(DepthIndex::AUTO_INDEX))
1008 requiredDepthIndex = static_cast<int>(DepthIndex::CONTENT);
1009 DALI_LOG_INFO(gLogFilter, Debug::Verbose, "Some strange cases. VisualDepthIndex AUTO_INDEX set as: %d\n", requiredDepthIndex);
1012 // Set determined depth index
1013 visual.SetDepthIndex(requiredDepthIndex);
1015 // Monitor when the visual resources are ready
1016 StartObservingVisual(visual);
1018 DALI_LOG_INFO(gLogFilter, Debug::Concise, "New Visual registration index[%d] depth[%d]\n", index, requiredDepthIndex);
1019 RegisteredVisual* newRegisteredVisual = new RegisteredVisual(index, visual, (enabled == VisualState::ENABLED ? true : false), (visualReplaced && enabled));
1020 mVisuals.PushBack(newRegisteredVisual);
1022 Internal::Visual::Base& visualImpl = Toolkit::GetImplementation(visual);
1023 // Put on stage if enabled and the control is already on the stage
1024 if((enabled == VisualState::ENABLED) && self.GetProperty<bool>(Actor::Property::CONNECTED_TO_SCENE))
1026 visualImpl.SetOnScene(self);
1028 else if(enabled && visualImpl.IsResourceReady()) // When not being staged, check if visual already 'ResourceReady' before it was Registered. ( Resource may have been loaded already )
1030 ResourceReady(visualImpl);
1034 DALI_LOG_INFO(gLogFilter, Debug::Verbose, "Control::RegisterVisual() Registered %s(%d), enabled:%s\n", visual.GetName().c_str(), index, enabled ? "true" : "false");
1037 void Control::Impl::UnregisterVisual(Property::Index index)
1039 DALI_ASSERT_ALWAYS(Stage::IsCoreThread() && "Core is not installed. Might call this API from worker thread?");
1041 RegisteredVisualContainer::Iterator iter;
1042 if(FindVisual(index, mVisuals, iter))
1044 // stop observing visual
1045 StopObservingVisual((*iter)->visual);
1047 Actor self(mControlImpl.Self());
1048 Toolkit::GetImplementation((*iter)->visual).SetOffScene(self);
1049 (*iter)->visual.Reset();
1050 mVisuals.Erase(iter);
1053 if(FindVisual(index, mRemoveVisuals, iter))
1055 Actor self(mControlImpl.Self());
1056 Toolkit::GetImplementation((*iter)->visual).SetOffScene(self);
1057 (*iter)->pending = false;
1059 // Discard removed visual. It will be destroyed at next Idle time.
1060 DiscardVisual(iter, mRemoveVisuals);
1064 Toolkit::Visual::Base Control::Impl::GetVisual(Property::Index index) const
1066 RegisteredVisualContainer::Iterator iter;
1067 if(FindVisual(index, mVisuals, iter))
1069 return (*iter)->visual;
1072 return Toolkit::Visual::Base();
1075 void Control::Impl::EnableVisual(Property::Index index, bool enable)
1077 DALI_LOG_INFO(gLogFilter, Debug::General, "Control::EnableVisual(%d, %s)\n", index, enable ? "T" : "F");
1079 RegisteredVisualContainer::Iterator iter;
1080 if(FindVisual(index, mVisuals, iter))
1082 if((*iter)->enabled == enable)
1084 DALI_LOG_INFO(gLogFilter, Debug::Verbose, "Control::EnableVisual Visual %s(%d) already %s\n", (*iter)->visual.GetName().c_str(), index, enable ? "enabled" : "disabled");
1088 (*iter)->enabled = enable;
1089 Actor parentActor = mControlImpl.Self();
1090 if(mControlImpl.Self().GetProperty<bool>(Actor::Property::CONNECTED_TO_SCENE)) // If control not on Scene then Visual will be added when SceneConnection is called.
1094 DALI_LOG_INFO(gLogFilter, Debug::Verbose, "Control::EnableVisual Setting %s(%d) on stage \n", (*iter)->visual.GetName().c_str(), index);
1095 Toolkit::GetImplementation((*iter)->visual).SetOnScene(parentActor);
1099 DALI_LOG_INFO(gLogFilter, Debug::Verbose, "Control::EnableVisual Setting %s(%d) off stage \n", (*iter)->visual.GetName().c_str(), index);
1100 Toolkit::GetImplementation((*iter)->visual).SetOffScene(parentActor); // No need to call if control not staged.
1106 DALI_LOG_WARNING("Control::EnableVisual(%d, %s) FAILED - NO SUCH VISUAL\n", index, enable ? "T" : "F");
1110 bool Control::Impl::IsVisualEnabled(Property::Index index) const
1112 RegisteredVisualContainer::Iterator iter;
1113 if(FindVisual(index, mVisuals, iter))
1115 return (*iter)->enabled;
1120 void Control::Impl::EnableReadyTransitionOverriden(Toolkit::Visual::Base& visual, bool enable)
1122 DALI_LOG_INFO(gLogFilter, Debug::General, "Control::EnableReadyTransitionOverriden(%p, %s)\n", visual, enable ? "T" : "F");
1124 RegisteredVisualContainer::Iterator iter;
1125 if(FindVisual(visual, mVisuals, iter))
1127 if((*iter)->overideReadyTransition == enable)
1129 DALI_LOG_INFO(gLogFilter, Debug::Verbose, "Control::EnableReadyTransitionOverriden Visual %s(%p) already %s\n", (*iter)->visual.GetName().c_str(), visual, enable ? "enabled" : "disabled");
1133 (*iter)->overideReadyTransition = enable;
1137 void Control::Impl::StopObservingVisual(Toolkit::Visual::Base& visual)
1139 Internal::Visual::Base& visualImpl = Toolkit::GetImplementation(visual);
1141 // Stop observing the visual
1142 visualImpl.RemoveEventObserver(*this);
1145 void Control::Impl::StartObservingVisual(Toolkit::Visual::Base& visual)
1147 Internal::Visual::Base& visualImpl = Toolkit::GetImplementation(visual);
1149 // start observing the visual for events
1150 visualImpl.AddEventObserver(*this);
1153 void Control::Impl::ResourceReady()
1155 DALI_ASSERT_ALWAYS(Stage::IsCoreThread() && "Core is not installed. Might call this API from worker thread?");
1157 // Emit signal if all enabled visuals registered by the control are ready or there are no visuals.
1158 if(IsResourceReady())
1160 EmitResourceReadySignal();
1164 // Called by a Visual when it's resource is ready
1165 void Control::Impl::ResourceReady(Visual::Base& object)
1167 DALI_LOG_INFO(gLogFilter, Debug::Verbose, "Control::Impl::ResourceReady() replacements pending[%d]\n", mRemoveVisuals.Count());
1169 Actor self = mControlImpl.Self();
1171 RegisteredVisualContainer::Iterator registeredIter;
1173 // A resource is ready, find resource in the registered visuals container and get its index
1174 if(!FindVisual(object, mVisuals, registeredIter))
1179 RegisteredVisualContainer::Iterator visualToRemoveIter;
1180 // Find visual with the same index in the removal container
1181 // Set if off stage as it's replacement is now ready.
1182 // Remove if from removal list as now removed from stage.
1183 // Set Pending flag on the ready visual to false as now ready.
1184 if(FindVisual((*registeredIter)->index, mRemoveVisuals, visualToRemoveIter))
1186 (*registeredIter)->pending = false;
1187 if(!((*visualToRemoveIter)->overideReadyTransition))
1189 Toolkit::GetImplementation((*visualToRemoveIter)->visual).SetOffScene(self);
1192 // Discard removed visual. It will be destroyed at next Idle time.
1193 DiscardVisual(visualToRemoveIter, mRemoveVisuals);
1196 // A visual is ready so control may need relayouting if staged
1197 RelayoutRequest(object);
1199 // Called by a Visual when it's resource is ready
1200 if(((*registeredIter)->enabled))
1206 void Control::Impl::NotifyVisualEvent(Visual::Base& object, Property::Index signalId)
1208 for(auto registeredIter = mVisuals.Begin(), end = mVisuals.End(); registeredIter != end; ++registeredIter)
1210 Internal::Visual::Base& registeredVisualImpl = Toolkit::GetImplementation((*registeredIter)->visual);
1211 if(&object == ®isteredVisualImpl)
1213 Dali::Toolkit::Control handle(mControlImpl.GetOwner());
1214 mVisualEventSignal.Emit(handle, (*registeredIter)->index, signalId);
1220 void Control::Impl::RelayoutRequest(Visual::Base& object)
1222 if(mControlImpl.Self().GetProperty<bool>(Actor::Property::CONNECTED_TO_SCENE))
1224 mControlImpl.RelayoutRequest();
1228 bool Control::Impl::IsResourceReady() const
1230 // Iterate through and check all the enabled visuals are ready
1231 for(auto visualIter = mVisuals.Begin();
1232 visualIter != mVisuals.End();
1235 const Toolkit::Visual::Base visual = (*visualIter)->visual;
1236 const Internal::Visual::Base& visualImpl = Toolkit::GetImplementation(visual);
1238 // one of the enabled visuals is not ready
1239 if(!visualImpl.IsResourceReady() && (*visualIter)->enabled)
1247 Toolkit::Visual::ResourceStatus Control::Impl::GetVisualResourceStatus(Property::Index index) const
1249 RegisteredVisualContainer::Iterator iter;
1250 if(FindVisual(index, mVisuals, iter))
1252 const Toolkit::Visual::Base visual = (*iter)->visual;
1253 const Internal::Visual::Base& visualImpl = Toolkit::GetImplementation(visual);
1254 return visualImpl.GetResourceStatus();
1257 return Toolkit::Visual::ResourceStatus::PREPARING;
1260 void Control::Impl::AddTransitions(Dali::Animation& animation,
1261 const Toolkit::TransitionData& handle,
1262 bool createAnimation)
1264 // Setup a Transition from TransitionData.
1265 const Internal::TransitionData& transitionData = Toolkit::GetImplementation(handle);
1266 TransitionData::Iterator end = transitionData.End();
1267 for(TransitionData::Iterator iter = transitionData.Begin();
1271 TransitionData::Animator* animator = (*iter);
1273 Toolkit::Visual::Base visual = GetVisualByName(mVisuals, animator->objectName);
1276 #if defined(DEBUG_ENABLED)
1277 Dali::TypeInfo typeInfo;
1278 ControlWrapper* controlWrapperImpl = dynamic_cast<ControlWrapper*>(&mControlImpl);
1279 if(controlWrapperImpl)
1281 typeInfo = controlWrapperImpl->GetTypeInfo();
1284 DALI_LOG_INFO(gLogFilter, Debug::Concise, "CreateTransition: Found %s visual for %s\n", visual.GetName().c_str(), typeInfo ? typeInfo.GetName().c_str() : "Unknown");
1286 Internal::Visual::Base& visualImpl = Toolkit::GetImplementation(visual);
1287 visualImpl.AnimateProperty(animation, *animator);
1291 DALI_LOG_INFO(gLogFilter, Debug::Concise, "CreateTransition: Could not find visual. Trying actors");
1292 // Otherwise, try any actor children of control (Including the control)
1293 Actor child = mControlImpl.Self().FindChildByName(animator->objectName);
1296 Property::Index propertyIndex = child.GetPropertyIndex(animator->propertyKey);
1297 if(propertyIndex != Property::INVALID_INDEX)
1299 if(animator->animate == false)
1301 if(animator->targetValue.GetType() != Property::NONE)
1303 child.SetProperty(propertyIndex, animator->targetValue);
1306 else // animate the property
1308 if(animator->initialValue.GetType() != Property::NONE)
1310 child.SetProperty(propertyIndex, animator->initialValue);
1313 if(createAnimation && !animation)
1315 animation = Dali::Animation::New(0.1f);
1318 animation.AnimateTo(Property(child, propertyIndex),
1319 animator->targetValue,
1320 animator->alphaFunction,
1321 TimePeriod(animator->timePeriodDelay,
1322 animator->timePeriodDuration));
1330 Dali::Animation Control::Impl::CreateTransition(const Toolkit::TransitionData& transitionData)
1332 Dali::Animation transition;
1334 if(transitionData.Count() > 0)
1336 AddTransitions(transition, transitionData, true);
1341 void Control::Impl::DoAction(Dali::Property::Index visualIndex, Dali::Property::Index actionId, const Dali::Property::Value attributes)
1343 RegisteredVisualContainer::Iterator iter;
1344 if(FindVisual(visualIndex, mVisuals, iter))
1346 Toolkit::GetImplementation((*iter)->visual).DoAction(actionId, attributes);
1350 void Control::Impl::DoActionExtension(Dali::Property::Index visualIndex, Dali::Property::Index actionId, Dali::Any attributes)
1352 RegisteredVisualContainer::Iterator iter;
1353 if(FindVisual(visualIndex, mVisuals, iter))
1355 Toolkit::GetImplementation((*iter)->visual).DoActionExtension(actionId, attributes);
1359 void Control::Impl::AppendAccessibilityAttribute(const std::string& key, const std::string value)
1361 Property::Value* checkedValue = mAccessibilityProps.extraAttributes.Find(key);
1364 mAccessibilityProps.extraAttributes[key] = Property::Value(value);
1368 mAccessibilityProps.extraAttributes.Insert(key, value);
1372 void Control::Impl::SetProperty(BaseObject* object, Property::Index index, const Property::Value& value)
1374 DALI_ASSERT_ALWAYS(Stage::IsCoreThread() && "Core is not installed. Might call this API from worker thread?");
1376 Toolkit::Control control = Toolkit::Control::DownCast(BaseHandle(object));
1380 Control& controlImpl(GetImplementation(control));
1384 case Toolkit::Control::Property::STYLE_NAME:
1386 controlImpl.SetStyleName(value.Get<std::string>());
1390 case Toolkit::DevelControl::Property::STATE:
1392 bool withTransitions = true;
1393 const Property::Value* valuePtr = &value;
1394 const Property::Map* map = value.GetMap();
1397 Property::Value* value2 = map->Find("withTransitions");
1400 withTransitions = value2->Get<bool>();
1403 valuePtr = map->Find("state");
1408 Toolkit::DevelControl::State state(controlImpl.mImpl->mState);
1409 if(Scripting::GetEnumerationProperty<Toolkit::DevelControl::State>(*valuePtr, ControlStateTable, ControlStateTableCount, state))
1411 controlImpl.mImpl->SetState(state, withTransitions);
1417 case Toolkit::DevelControl::Property::SUB_STATE:
1419 std::string subState;
1420 if(value.Get(subState))
1422 controlImpl.mImpl->SetSubState(subState);
1427 case Toolkit::DevelControl::Property::LEFT_FOCUSABLE_ACTOR_ID:
1430 if(value.Get(focusId))
1432 controlImpl.mImpl->mLeftFocusableActorId = focusId;
1437 case Toolkit::DevelControl::Property::RIGHT_FOCUSABLE_ACTOR_ID:
1440 if(value.Get(focusId))
1442 controlImpl.mImpl->mRightFocusableActorId = focusId;
1447 case Toolkit::DevelControl::Property::UP_FOCUSABLE_ACTOR_ID:
1450 if(value.Get(focusId))
1452 controlImpl.mImpl->mUpFocusableActorId = focusId;
1457 case Toolkit::DevelControl::Property::DOWN_FOCUSABLE_ACTOR_ID:
1460 if(value.Get(focusId))
1462 controlImpl.mImpl->mDownFocusableActorId = focusId;
1467 case Toolkit::Control::Property::KEY_INPUT_FOCUS:
1469 if(value.Get<bool>())
1471 controlImpl.SetKeyInputFocus();
1475 controlImpl.ClearKeyInputFocus();
1480 case Toolkit::Control::Property::BACKGROUND:
1484 const Property::Map* map = value.GetMap();
1485 if(map && !map->Empty())
1487 controlImpl.SetBackground(*map);
1489 else if(value.Get(url))
1491 // don't know the size to load
1492 Toolkit::Visual::Base visual = Toolkit::VisualFactory::Get().CreateVisual(url, ImageDimensions());
1495 controlImpl.mImpl->RegisterVisual(Toolkit::Control::Property::BACKGROUND, visual, DepthIndex::BACKGROUND);
1498 else if(value.Get(color))
1500 controlImpl.SetBackgroundColor(color);
1504 // The background is an empty property map, so we should clear the background
1505 controlImpl.ClearBackground();
1510 case Toolkit::Control::Property::MARGIN:
1513 if(value.Get(margin))
1515 controlImpl.mImpl->SetMargin(margin);
1520 case Toolkit::Control::Property::PADDING:
1523 if(value.Get(padding))
1525 controlImpl.mImpl->SetPadding(padding);
1530 case Toolkit::DevelControl::Property::TOOLTIP:
1532 TooltipPtr& tooltipPtr = controlImpl.mImpl->mTooltip;
1535 tooltipPtr = Tooltip::New(control);
1537 tooltipPtr->SetProperties(value);
1541 case Toolkit::DevelControl::Property::SHADOW:
1543 const Property::Map* map = value.GetMap();
1544 if(map && !map->Empty())
1546 controlImpl.mImpl->SetShadow(*map);
1550 // The shadow is an empty property map, so we should clear the shadow
1551 controlImpl.mImpl->ClearShadow();
1556 case Toolkit::DevelControl::Property::ACCESSIBILITY_NAME:
1561 controlImpl.mImpl->mAccessibilityProps.name = std::move(name);
1566 case Toolkit::DevelControl::Property::ACCESSIBILITY_DESCRIPTION:
1571 controlImpl.mImpl->mAccessibilityProps.description = std::move(text);
1576 case Toolkit::DevelControl::Property::ACCESSIBILITY_ROLE:
1581 controlImpl.mImpl->mAccessibilityProps.role = role;
1586 case Toolkit::DevelControl::Property::ACCESSIBILITY_HIGHLIGHTABLE:
1589 if(value.Get(highlightable))
1591 controlImpl.mImpl->mAccessibilityProps.isHighlightable = highlightable;
1596 case Toolkit::DevelControl::Property::ACCESSIBILITY_ATTRIBUTES:
1598 const Property::Map* map = value.GetMap();
1599 if(map && !map->Empty())
1601 controlImpl.mImpl->mAccessibilityProps.extraAttributes = *map;
1606 case Toolkit::DevelControl::Property::DISPATCH_KEY_EVENTS:
1609 if(value.Get(dispatch))
1611 controlImpl.mImpl->mDispatchKeyEvents = dispatch;
1616 case Toolkit::DevelControl::Property::ACCESSIBILITY_HIDDEN:
1619 if(value.Get(hidden))
1621 controlImpl.mImpl->mAccessibilityProps.isHidden = hidden;
1623 auto accessible = controlImpl.GetAccessibleObject();
1624 if(DALI_LIKELY(accessible))
1626 auto* parent = dynamic_cast<Dali::Accessibility::ActorAccessible*>(accessible->GetParent());
1629 parent->OnChildrenChanged();
1635 case Toolkit::DevelControl::Property::CLOCKWISE_FOCUSABLE_ACTOR_ID:
1638 if(value.Get(focusId))
1640 controlImpl.mImpl->mClockwiseFocusableActorId = focusId;
1644 case Toolkit::DevelControl::Property::COUNTER_CLOCKWISE_FOCUSABLE_ACTOR_ID:
1647 if(value.Get(focusId))
1649 controlImpl.mImpl->mCounterClockwiseFocusableActorId = focusId;
1654 case Toolkit::DevelControl::Property::AUTOMATION_ID:
1656 std::string automationId;
1657 if(value.Get(automationId))
1659 controlImpl.mImpl->mAccessibilityProps.automationId = std::move(automationId);
1664 case Toolkit::DevelControl::Property::ACCESSIBILITY_VALUE:
1666 std::string accessibilityValue;
1667 if(value.Get(accessibilityValue))
1669 controlImpl.mImpl->mAccessibilityProps.value = std::move(accessibilityValue);
1674 case Toolkit::DevelControl::Property::ACCESSIBILITY_SCROLLABLE:
1677 if(value.Get(isScrollable))
1679 controlImpl.mImpl->mAccessibilityProps.isScrollable = isScrollable;
1684 case Toolkit::DevelControl::Property::ACCESSIBILITY_STATES:
1687 if(value.Get(states))
1689 controlImpl.mImpl->mAccessibilityProps.states = Toolkit::DevelControl::AccessibilityStates{static_cast<uint32_t>(states)};
1694 case Toolkit::DevelControl::Property::ACCESSIBILITY_IS_MODAL:
1697 if(value.Get(isModal))
1699 controlImpl.mImpl->mAccessibilityProps.isModal = isModal;
1707 Property::Value Control::Impl::GetProperty(BaseObject* object, Property::Index index)
1709 DALI_ASSERT_ALWAYS(Stage::IsCoreThread() && "Core is not installed. Might call this API from worker thread?");
1711 Property::Value value;
1713 Toolkit::Control control = Toolkit::Control::DownCast(BaseHandle(object));
1717 Control& controlImpl(GetImplementation(control));
1721 case Toolkit::Control::Property::STYLE_NAME:
1723 value = controlImpl.GetStyleName();
1727 case Toolkit::DevelControl::Property::STATE:
1729 value = controlImpl.mImpl->mState;
1733 case Toolkit::DevelControl::Property::SUB_STATE:
1735 value = controlImpl.mImpl->mSubStateName;
1739 case Toolkit::DevelControl::Property::LEFT_FOCUSABLE_ACTOR_ID:
1741 value = controlImpl.mImpl->mLeftFocusableActorId;
1745 case Toolkit::DevelControl::Property::RIGHT_FOCUSABLE_ACTOR_ID:
1747 value = controlImpl.mImpl->mRightFocusableActorId;
1751 case Toolkit::DevelControl::Property::UP_FOCUSABLE_ACTOR_ID:
1753 value = controlImpl.mImpl->mUpFocusableActorId;
1757 case Toolkit::DevelControl::Property::DOWN_FOCUSABLE_ACTOR_ID:
1759 value = controlImpl.mImpl->mDownFocusableActorId;
1763 case Toolkit::Control::Property::KEY_INPUT_FOCUS:
1765 value = controlImpl.HasKeyInputFocus();
1769 case Toolkit::Control::Property::BACKGROUND:
1772 Toolkit::Visual::Base visual = controlImpl.mImpl->GetVisual(Toolkit::Control::Property::BACKGROUND);
1775 visual.CreatePropertyMap(map);
1782 case Toolkit::Control::Property::MARGIN:
1784 value = controlImpl.mImpl->GetMargin();
1788 case Toolkit::Control::Property::PADDING:
1790 value = controlImpl.mImpl->GetPadding();
1794 case Toolkit::DevelControl::Property::TOOLTIP:
1797 if(controlImpl.mImpl->mTooltip)
1799 controlImpl.mImpl->mTooltip->CreatePropertyMap(map);
1805 case Toolkit::DevelControl::Property::SHADOW:
1808 Toolkit::Visual::Base visual = controlImpl.mImpl->GetVisual(Toolkit::DevelControl::Property::SHADOW);
1811 visual.CreatePropertyMap(map);
1818 case Toolkit::DevelControl::Property::ACCESSIBILITY_NAME:
1820 value = controlImpl.mImpl->mAccessibilityProps.name;
1824 case Toolkit::DevelControl::Property::ACCESSIBILITY_DESCRIPTION:
1826 value = controlImpl.mImpl->mAccessibilityProps.description;
1830 case Toolkit::DevelControl::Property::ACCESSIBILITY_ROLE:
1832 value = controlImpl.mImpl->mAccessibilityProps.role;
1836 case Toolkit::DevelControl::Property::ACCESSIBILITY_HIGHLIGHTABLE:
1838 value = controlImpl.mImpl->mAccessibilityProps.isHighlightable;
1842 case Toolkit::DevelControl::Property::ACCESSIBILITY_ATTRIBUTES:
1844 value = controlImpl.mImpl->mAccessibilityProps.extraAttributes;
1848 case Toolkit::DevelControl::Property::DISPATCH_KEY_EVENTS:
1850 value = controlImpl.mImpl->mDispatchKeyEvents;
1854 case Toolkit::DevelControl::Property::ACCESSIBILITY_HIDDEN:
1856 value = controlImpl.mImpl->mAccessibilityProps.isHidden;
1860 case Toolkit::DevelControl::Property::CLOCKWISE_FOCUSABLE_ACTOR_ID:
1862 value = controlImpl.mImpl->mClockwiseFocusableActorId;
1866 case Toolkit::DevelControl::Property::COUNTER_CLOCKWISE_FOCUSABLE_ACTOR_ID:
1868 value = controlImpl.mImpl->mCounterClockwiseFocusableActorId;
1872 case Toolkit::DevelControl::Property::AUTOMATION_ID:
1874 value = controlImpl.mImpl->mAccessibilityProps.automationId;
1878 case Toolkit::DevelControl::Property::ACCESSIBILITY_VALUE:
1880 value = controlImpl.mImpl->mAccessibilityProps.value;
1884 case Toolkit::DevelControl::Property::ACCESSIBILITY_SCROLLABLE:
1886 value = controlImpl.mImpl->mAccessibilityProps.isScrollable;
1890 case Toolkit::DevelControl::Property::ACCESSIBILITY_STATES:
1892 value = static_cast<int32_t>(controlImpl.mImpl->mAccessibilityProps.states.GetRawData32());
1896 case Toolkit::DevelControl::Property::ACCESSIBILITY_IS_MODAL:
1898 value = controlImpl.mImpl->mAccessibilityProps.isModal;
1907 void Control::Impl::RemoveAccessibilityAttribute(const std::string& key)
1909 Property::Value* value = mAccessibilityProps.extraAttributes.Find(key);
1912 mAccessibilityProps.extraAttributes[key] = Property::Value();
1916 void Control::Impl::ClearAccessibilityAttributes()
1918 mAccessibilityProps.extraAttributes.Clear();
1921 void Control::Impl::SetAccessibilityReadingInfoType(const Dali::Accessibility::ReadingInfoTypes types)
1923 std::string value{};
1924 if(types[Dali::Accessibility::ReadingInfoType::NAME])
1926 value += READING_INFO_TYPE_NAME;
1928 if(types[Dali::Accessibility::ReadingInfoType::ROLE])
1932 value += READING_INFO_TYPE_SEPARATOR;
1934 value += READING_INFO_TYPE_ROLE;
1936 if(types[Dali::Accessibility::ReadingInfoType::DESCRIPTION])
1940 value += READING_INFO_TYPE_SEPARATOR;
1942 value += READING_INFO_TYPE_DESCRIPTION;
1944 if(types[Dali::Accessibility::ReadingInfoType::STATE])
1948 value += READING_INFO_TYPE_SEPARATOR;
1950 value += READING_INFO_TYPE_STATE;
1952 AppendAccessibilityAttribute(READING_INFO_TYPE_ATTRIBUTE_NAME, value);
1955 Dali::Accessibility::ReadingInfoTypes Control::Impl::GetAccessibilityReadingInfoType() const
1957 std::string value{};
1958 auto place = mAccessibilityProps.extraAttributes.Find(READING_INFO_TYPE_ATTRIBUTE_NAME);
1965 Dali::Accessibility::ReadingInfoTypes types;
1966 types[Dali::Accessibility::ReadingInfoType::NAME] = true;
1967 types[Dali::Accessibility::ReadingInfoType::ROLE] = true;
1968 types[Dali::Accessibility::ReadingInfoType::DESCRIPTION] = true;
1969 types[Dali::Accessibility::ReadingInfoType::STATE] = true;
1978 Dali::Accessibility::ReadingInfoTypes types;
1980 if(value.find(READING_INFO_TYPE_NAME) != std::string::npos)
1982 types[Dali::Accessibility::ReadingInfoType::NAME] = true;
1984 if(value.find(READING_INFO_TYPE_ROLE) != std::string::npos)
1986 types[Dali::Accessibility::ReadingInfoType::ROLE] = true;
1988 if(value.find(READING_INFO_TYPE_DESCRIPTION) != std::string::npos)
1990 types[Dali::Accessibility::ReadingInfoType::DESCRIPTION] = true;
1992 if(value.find(READING_INFO_TYPE_STATE) != std::string::npos)
1994 types[Dali::Accessibility::ReadingInfoType::STATE] = true;
2000 void Control::Impl::CopyInstancedProperties(RegisteredVisualContainer& visuals, Dictionary<Property::Map>& instancedProperties)
2002 for(RegisteredVisualContainer::Iterator iter = visuals.Begin(); iter != visuals.End(); iter++)
2006 Property::Map instanceMap;
2007 Toolkit::GetImplementation((*iter)->visual).CreateInstancePropertyMap(instanceMap);
2008 instancedProperties.Add((*iter)->visual.GetName(), instanceMap);
2013 void Control::Impl::RemoveVisual(RegisteredVisualContainer& visuals, const std::string& visualName)
2015 Actor self(mControlImpl.Self());
2017 for(RegisteredVisualContainer::Iterator visualIter = visuals.Begin();
2018 visualIter != visuals.End();
2021 Toolkit::Visual::Base visual = (*visualIter)->visual;
2022 if(visual && visual.GetName() == visualName)
2024 Toolkit::GetImplementation(visual).SetOffScene(self);
2025 (*visualIter)->visual.Reset();
2026 visuals.Erase(visualIter);
2032 void Control::Impl::RemoveVisuals(RegisteredVisualContainer& visuals, DictionaryKeys& removeVisuals)
2034 Actor self(mControlImpl.Self());
2035 for(DictionaryKeys::iterator iter = removeVisuals.begin(); iter != removeVisuals.end(); ++iter)
2037 const std::string visualName = *iter;
2038 RemoveVisual(visuals, visualName);
2042 void Control::Impl::RecreateChangedVisuals(Dictionary<Property::Map>& stateVisualsToChange,
2043 Dictionary<Property::Map>& instancedProperties)
2045 Dali::CustomActor handle(mControlImpl.GetOwner());
2046 for(Dictionary<Property::Map>::iterator iter = stateVisualsToChange.Begin();
2047 iter != stateVisualsToChange.End();
2050 const std::string& visualName = (*iter).key;
2051 const Property::Map& toMap = (*iter).entry;
2053 Actor self = mControlImpl.Self();
2054 RegisteredVisualContainer::Iterator registeredVisualsiter;
2055 // Check if visual (visualName) is already registered, this is the current visual.
2056 if(FindVisual(visualName, mVisuals, registeredVisualsiter))
2058 Toolkit::Visual::Base& visual = (*registeredVisualsiter)->visual;
2061 // No longer required to know if the replaced visual's resources are ready
2062 StopObservingVisual(visual);
2064 // If control staged then visuals will be swapped once ready
2065 if(self.GetProperty<bool>(Actor::Property::CONNECTED_TO_SCENE))
2067 // Check if visual is currently in the process of being replaced ( is in removal container )
2068 RegisteredVisualContainer::Iterator visualQueuedForRemoval;
2069 if(FindVisual(visualName, mRemoveVisuals, visualQueuedForRemoval))
2071 // Visual with same visual name is already in removal container so current visual pending
2072 // Only the the last requested visual will be displayed so remove current visual which is staged but not ready.
2073 Toolkit::GetImplementation(visual).SetOffScene(self);
2074 (*registeredVisualsiter)->visual.Reset();
2075 mVisuals.Erase(registeredVisualsiter);
2079 // current visual not already in removal container so add now.
2080 DALI_LOG_INFO(gLogFilter, Debug::Verbose, "RegisterVisual Move current registered visual to removal Queue: %s \n", visualName.c_str());
2081 MoveVisual(registeredVisualsiter, mVisuals, mRemoveVisuals);
2086 // Control not staged or visual disabled so can just erase from registered visuals and new visual will be added later.
2087 (*registeredVisualsiter)->visual.Reset();
2088 mVisuals.Erase(registeredVisualsiter);
2092 const Property::Map* instancedMap = instancedProperties.FindConst(visualName);
2093 Style::ApplyVisual(handle, visualName, toMap, instancedMap);
2098 void Control::Impl::ReplaceStateVisualsAndProperties(const StylePtr oldState, const StylePtr newState, const std::string& subState)
2100 DALI_ASSERT_ALWAYS(Stage::IsCoreThread() && "Core is not installed. Might call this API from worker thread?");
2102 // Collect all old visual names
2103 DictionaryKeys stateVisualsToRemove;
2106 oldState->visuals.GetKeys(stateVisualsToRemove);
2107 if(!subState.empty())
2109 const StylePtr* oldSubState = oldState->subStates.FindConst(subState);
2112 DictionaryKeys subStateVisualsToRemove;
2113 (*oldSubState)->visuals.GetKeys(subStateVisualsToRemove);
2114 Merge(stateVisualsToRemove, subStateVisualsToRemove);
2119 // Collect all new visual properties
2120 Dictionary<Property::Map> stateVisualsToAdd;
2123 stateVisualsToAdd = newState->visuals;
2124 if(!subState.empty())
2126 const StylePtr* newSubState = newState->subStates.FindConst(subState);
2129 stateVisualsToAdd.Merge((*newSubState)->visuals);
2134 // If a name is in both add/remove, move it to change list.
2135 Dictionary<Property::Map> stateVisualsToChange;
2136 FindChangableVisuals(stateVisualsToAdd, stateVisualsToChange, stateVisualsToRemove);
2138 // Copy instanced properties (e.g. text label) of current visuals
2139 Dictionary<Property::Map> instancedProperties;
2140 CopyInstancedProperties(mVisuals, instancedProperties);
2142 // For each visual in remove list, remove from mVisuals
2143 RemoveVisuals(mVisuals, stateVisualsToRemove);
2145 // For each visual in add list, create and add to mVisuals
2146 Dali::CustomActor handle(mControlImpl.GetOwner());
2147 Style::ApplyVisuals(handle, stateVisualsToAdd, instancedProperties);
2149 // For each visual in change list, if it requires a new visual,
2150 // remove old visual, create and add to mVisuals
2151 RecreateChangedVisuals(stateVisualsToChange, instancedProperties);
2154 void Control::Impl::SetState(DevelControl::State newState, bool withTransitions)
2156 DevelControl::State oldState = mState;
2157 Dali::CustomActor handle(mControlImpl.GetOwner());
2158 DALI_LOG_INFO(gLogFilter, Debug::Concise, "Control::Impl::SetState: %s\n", (mState == DevelControl::NORMAL ? "NORMAL" : (mState == DevelControl::FOCUSED ? "FOCUSED" : (mState == DevelControl::DISABLED ? "DISABLED" : "NONE"))));
2160 if(mState != newState)
2162 // If mState was Disabled, and new state is Focused, should probably
2163 // store that fact, e.g. in another property that FocusManager can access.
2166 // Trigger state change and transitions
2167 // Apply new style, if stylemanager is available
2168 Toolkit::StyleManager styleManager = Toolkit::StyleManager::Get();
2171 const StylePtr stylePtr = GetImpl(styleManager).GetRecordedStyle(Toolkit::Control(mControlImpl.GetOwner()));
2175 std::string oldStateName = Scripting::GetEnumerationName<Toolkit::DevelControl::State>(oldState, ControlStateTable, ControlStateTableCount);
2176 std::string newStateName = Scripting::GetEnumerationName<Toolkit::DevelControl::State>(newState, ControlStateTable, ControlStateTableCount);
2178 const StylePtr* newStateStyle = stylePtr->subStates.Find(newStateName);
2179 const StylePtr* oldStateStyle = stylePtr->subStates.Find(oldStateName);
2180 if(oldStateStyle && newStateStyle)
2182 // Only change if both state styles exist
2183 ReplaceStateVisualsAndProperties(*oldStateStyle, *newStateStyle, mSubStateName);
2190 void Control::Impl::SetSubState(const std::string& subStateName, bool withTransitions)
2192 if(mSubStateName != subStateName)
2194 // Get existing sub-state visuals, and unregister them
2195 Dali::CustomActor handle(mControlImpl.GetOwner());
2197 Toolkit::StyleManager styleManager = Toolkit::StyleManager::Get();
2200 const StylePtr stylePtr = GetImpl(styleManager).GetRecordedStyle(Toolkit::Control(mControlImpl.GetOwner()));
2204 std::string stateName = Scripting::GetEnumerationName<Toolkit::DevelControl::State>(mState, ControlStateTable, ControlStateTableCount);
2206 const StylePtr* state = stylePtr->subStates.Find(stateName);
2209 StylePtr stateStyle(*state);
2211 const StylePtr* newStateStyle = stateStyle->subStates.Find(subStateName);
2212 const StylePtr* oldStateStyle = stateStyle->subStates.Find(mSubStateName);
2213 if(oldStateStyle && newStateStyle)
2216 ReplaceStateVisualsAndProperties(*oldStateStyle, *newStateStyle, empty);
2222 mSubStateName = subStateName;
2226 void Control::Impl::OnSceneDisconnection()
2228 Actor self = mControlImpl.Self();
2230 // Any visuals set for replacement but not yet ready should still be registered.
2231 // Reason: If a request was made to register a new visual but the control removed from scene before visual was ready
2232 // then when this control appears back on stage it should use that new visual.
2234 // Iterate through all registered visuals and set off scene
2235 SetVisualsOffScene(mVisuals, self);
2237 // Visuals pending replacement can now be taken out of the removal list and set off scene
2238 // Iterate through all replacement visuals and add to a move queue then set off scene
2240 if(!mRemoveVisuals.Empty())
2242 std::reverse(mRemoveVisuals.Begin(), mRemoveVisuals.End());
2244 while(!mRemoveVisuals.Empty())
2246 auto removalIter = mRemoveVisuals.End() - 1u;
2247 Toolkit::GetImplementation((*removalIter)->visual).SetOffScene(self);
2249 // Discard removed visual. It will be destroyed at next Idle time.
2250 DiscardVisual(removalIter, mRemoveVisuals);
2254 for(auto replacedIter = mVisuals.Begin(), end = mVisuals.End(); replacedIter != end; replacedIter++)
2256 (*replacedIter)->pending = false;
2260 void Control::Impl::SetMargin(Extents margin)
2262 mControlImpl.mImpl->mMargin = margin;
2264 // Trigger a size negotiation request that may be needed when setting a margin.
2265 mControlImpl.RelayoutRequest();
2268 Extents Control::Impl::GetMargin() const
2270 return mControlImpl.mImpl->mMargin;
2273 void Control::Impl::SetPadding(Extents padding)
2275 mControlImpl.mImpl->mPadding = padding;
2277 // Trigger a size negotiation request that may be needed when setting a padding.
2278 mControlImpl.RelayoutRequest();
2281 Extents Control::Impl::GetPadding() const
2283 return mControlImpl.mImpl->mPadding;
2286 void Control::Impl::SetInputMethodContext(InputMethodContext& inputMethodContext)
2288 mInputMethodContext = inputMethodContext;
2291 bool Control::Impl::FilterKeyEvent(const KeyEvent& event)
2293 bool consumed(false);
2295 if(mInputMethodContext)
2297 consumed = mInputMethodContext.FilterEventKey(event);
2302 DevelControl::VisualEventSignalType& Control::Impl::VisualEventSignal()
2304 return mVisualEventSignal;
2307 void Control::Impl::SetShadow(const Property::Map& map)
2309 Toolkit::Visual::Base visual = Toolkit::VisualFactory::Get().CreateVisual(map);
2310 visual.SetName("shadow");
2314 mControlImpl.mImpl->RegisterVisual(Toolkit::DevelControl::Property::SHADOW, visual, DepthIndex::BACKGROUND_EFFECT);
2316 mControlImpl.RelayoutRequest();
2320 void Control::Impl::ClearShadow()
2322 mControlImpl.mImpl->UnregisterVisual(Toolkit::DevelControl::Property::SHADOW);
2324 // Trigger a size negotiation request that may be needed when unregistering a visual.
2325 mControlImpl.RelayoutRequest();
2328 Dali::Property Control::Impl::GetVisualProperty(Dali::Property::Index index, Dali::Property::Key visualPropertyKey)
2330 Toolkit::Visual::Base visual = GetVisualByIndex(mVisuals, index);
2333 Internal::Visual::Base& visualImpl = Toolkit::GetImplementation(visual);
2334 return visualImpl.GetPropertyObject(std::move(visualPropertyKey));
2338 return Dali::Property(handle, Property::INVALID_INDEX);
2341 void Control::Impl::CreateTransitions(std::vector<std::pair<Dali::Property::Index, Dali::Property::Map>>& sourceProperties,
2342 std::vector<std::pair<Dali::Property::Index, Dali::Property::Map>>& destinationProperties,
2343 Dali::Toolkit::Control source,
2344 Dali::Toolkit::Control destination)
2346 // Retrieves background properties to be transitioned.
2347 Dali::Property::Map backgroundSourcePropertyMap, backgroundDestinationPropertyMap;
2348 mControlImpl.MakeVisualTransition(backgroundSourcePropertyMap, backgroundDestinationPropertyMap, source, destination, Toolkit::Control::Property::BACKGROUND);
2349 if(backgroundSourcePropertyMap.Count() > 0)
2351 sourceProperties.push_back(std::pair<Dali::Property::Index, Dali::Property::Map>(Toolkit::Control::Property::BACKGROUND, backgroundSourcePropertyMap));
2352 destinationProperties.push_back(std::pair<Dali::Property::Index, Dali::Property::Map>(Toolkit::Control::Property::BACKGROUND, backgroundDestinationPropertyMap));
2355 // Retrieves shadow properties to be transitioned.
2356 Dali::Property::Map shadowSourcePropertyMap, shadowDestinationPropertyMap;
2357 mControlImpl.MakeVisualTransition(shadowSourcePropertyMap, shadowDestinationPropertyMap, source, destination, Toolkit::DevelControl::Property::SHADOW);
2358 if(shadowSourcePropertyMap.Count() > 0)
2360 sourceProperties.push_back(std::pair<Dali::Property::Index, Dali::Property::Map>(Toolkit::DevelControl::Property::SHADOW, shadowSourcePropertyMap));
2361 destinationProperties.push_back(std::pair<Dali::Property::Index, Dali::Property::Map>(Toolkit::DevelControl::Property::SHADOW, shadowDestinationPropertyMap));
2364 // Retrieves transition from inherited class.
2365 mControlImpl.OnCreateTransitions(sourceProperties, destinationProperties, source, destination);
2368 void Control::Impl::UpdateVisualProperties(const std::vector<std::pair<Dali::Property::Index, Dali::Property::Map>>& properties)
2370 for(auto&& data : properties)
2372 if(data.first == Toolkit::Control::Property::BACKGROUND)
2374 DoAction(Toolkit::Control::Property::BACKGROUND, DevelVisual::Action::UPDATE_PROPERTY, data.second);
2376 else if(data.first == Toolkit::DevelControl::Property::SHADOW)
2378 DoAction(Toolkit::DevelControl::Property::SHADOW, DevelVisual::Action::UPDATE_PROPERTY, data.second);
2381 mControlImpl.OnUpdateVisualProperties(properties);
2384 void Control::Impl::EmitResourceReadySignal()
2386 if(DALI_LIKELY(Dali::Adaptor::IsAvailable())) ///< Avoid resource ready callback during shutting down
2388 if(!mIsEmittingResourceReadySignal)
2390 // Guard against calls to emit the signal during the callback
2391 mIsEmittingResourceReadySignal = true;
2393 // If the signal handler changes visual, it may become ready during this call & therefore this method will
2394 // get called again recursively. If so, mIdleCallbackRegistered is set below, and we act on it after that secondary
2395 // invocation has completed by notifying in an Idle callback to prevent further recursion.
2396 Dali::Toolkit::Control handle(mControlImpl.GetOwner());
2397 mResourceReadySignal.Emit(handle);
2399 mIsEmittingResourceReadySignal = false;
2403 if(!mIdleCallbackRegistered)
2405 mIdleCallbackRegistered = true;
2407 // Add idler to emit the signal again
2410 // The callback manager takes the ownership of the callback object.
2411 mIdleCallback = MakeCallback(this, &Control::Impl::OnIdleCallback);
2412 if(DALI_UNLIKELY(!Adaptor::Get().AddIdle(mIdleCallback, true)))
2414 DALI_LOG_ERROR("Fail to add idle callback for control resource ready. Skip this callback.\n");
2415 mIdleCallback = nullptr;
2416 mIdleCallbackRegistered = false;
2424 bool Control::Impl::OnIdleCallback()
2427 mIdleCallbackRegistered = false;
2429 // A visual is ready so control may need relayouting if staged
2430 if(mControlImpl.Self().GetProperty<bool>(Actor::Property::CONNECTED_TO_SCENE))
2432 mControlImpl.RelayoutRequest();
2435 EmitResourceReadySignal();
2437 if(!mIdleCallbackRegistered)
2439 // Set the pointer to null as the callback manager deletes the callback after execute it.
2440 mIdleCallback = nullptr;
2443 // Repeat idle if mIdleCallbackRegistered become true one more time.
2444 return mIdleCallbackRegistered;
2447 std::shared_ptr<Toolkit::DevelControl::ControlAccessible> Control::Impl::GetAccessibleObject()
2449 return std::dynamic_pointer_cast<DevelControl::ControlAccessible>(Accessibility::Accessible::GetOwningPtr(mControlImpl.Self()));
2452 bool Control::Impl::IsAccessibleCreated() const
2454 return !!Accessibility::Bridge::GetCurrentBridge()->GetAccessible(mControlImpl.Self());
2457 void Control::Impl::EnableCreateAccessible(bool enable)
2459 mAccessibleCreatable = enable;
2462 bool Control::Impl::IsCreateAccessibleEnabled() const
2464 return mAccessibleCreatable;
2467 void Control::Impl::ApplyFittingMode(const Vector2& size)
2469 Actor self = mControlImpl.Self();
2470 for(RegisteredVisualContainer::Iterator iter = mVisuals.Begin(); iter != mVisuals.End(); iter++)
2472 // Check whether the visual is empty and enabled
2473 if((*iter)->visual && (*iter)->enabled)
2475 Internal::Visual::Base& visualImpl = Toolkit::GetImplementation((*iter)->visual);
2477 // If the current visual is using the transform property map, fittingMode will not be applied.
2478 if(visualImpl.IsIgnoreFittingMode())
2483 Visual::FittingMode fittingMode = visualImpl.GetFittingMode();
2484 Property::Map transformMap = Property::Map();
2486 // If the fittingMode is DONT_CARE, we don't need to apply fittingMode, just Set empty transformMap
2487 if(fittingMode == Visual::FittingMode::DONT_CARE)
2489 if(visualImpl.GetType() != Toolkit::Visual::Type::TEXT)
2491 ((*iter)->visual).SetTransformAndSize(transformMap, size);
2496 Extents padding = self.GetProperty<Extents>(Toolkit::Control::Property::PADDING);
2498 bool zeroPadding = (padding == Extents());
2500 Dali::LayoutDirection::Type layoutDirection = static_cast<Dali::LayoutDirection::Type>(
2501 self.GetProperty(Dali::Actor::Property::LAYOUT_DIRECTION).Get<int>());
2502 if(Dali::LayoutDirection::RIGHT_TO_LEFT == layoutDirection)
2504 std::swap(padding.start, padding.end);
2507 // remove padding from the size to know how much is left for the visual
2508 Vector2 finalSize = size - Vector2(padding.start + padding.end, padding.top + padding.bottom);
2509 Vector2 finalOffset = Vector2(padding.start, padding.top);
2511 // Reset PIXEL_AREA after using OVER_FIT_KEEP_ASPECT_RATIO
2512 if(visualImpl.IsPixelAreaSetForFittingMode())
2514 visualImpl.SetPixelAreaForFittingMode(FULL_TEXTURE_RECT);
2517 if((!zeroPadding) || // If padding is not zero
2518 (fittingMode != Visual::FittingMode::FILL))
2520 visualImpl.SetTransformMapUsageForFittingMode(true);
2522 Vector2 naturalSize;
2523 // NaturalSize will not be used for FILL fitting mode, which is default.
2524 // Skip GetNaturalSize
2525 if(fittingMode != Visual::FittingMode::FILL)
2527 ((*iter)->visual).GetNaturalSize(naturalSize);
2530 // If FittingMode use FIT_WIDTH or FIT_HEIGTH, it need to change proper fittingMode
2531 if(fittingMode == Visual::FittingMode::FIT_WIDTH || fittingMode == Visual::FittingMode::FIT_HEIGHT)
2533 const float widthRatio = !Dali::EqualsZero(naturalSize.width) ? (finalSize.width / naturalSize.width) : 0.0f;
2534 const float heightRatio = !Dali::EqualsZero(naturalSize.height) ? (finalSize.height / naturalSize.height) : 0.0f;
2535 if(widthRatio < heightRatio)
2537 // Final size has taller form than natural size.
2538 fittingMode = (fittingMode == Visual::FittingMode::FIT_WIDTH) ? Visual::FittingMode::FIT_KEEP_ASPECT_RATIO : Visual::FittingMode::OVER_FIT_KEEP_ASPECT_RATIO;
2542 // Final size has wider form than natural size.
2543 fittingMode = (fittingMode == Visual::FittingMode::FIT_WIDTH) ? Visual::FittingMode::OVER_FIT_KEEP_ASPECT_RATIO : Visual::FittingMode::FIT_KEEP_ASPECT_RATIO;
2547 // Calculate size for fittingMode
2550 case Visual::FittingMode::FIT_KEEP_ASPECT_RATIO:
2552 auto availableVisualSize = finalSize;
2554 // scale to fit the padded area
2555 finalSize = naturalSize * std::min((!Dali::EqualsZero(naturalSize.width) ? (availableVisualSize.width / naturalSize.width) : 0),
2556 (!Dali::EqualsZero(naturalSize.height) ? (availableVisualSize.height / naturalSize.height) : 0));
2558 // calculate final offset within the padded area
2559 finalOffset += (availableVisualSize - finalSize) * .5f;
2561 // populate the transform map
2562 transformMap.Add(Toolkit::Visual::Transform::Property::OFFSET, finalOffset)
2563 .Add(Toolkit::Visual::Transform::Property::SIZE, finalSize);
2566 case Visual::FittingMode::OVER_FIT_KEEP_ASPECT_RATIO:
2568 auto availableVisualSize = finalSize;
2569 finalSize = naturalSize * std::max((!Dali::EqualsZero(naturalSize.width) ? (availableVisualSize.width / naturalSize.width) : 0.0f),
2570 (!Dali::EqualsZero(naturalSize.height) ? (availableVisualSize.height / naturalSize.height) : 0.0f));
2572 auto originalOffset = finalOffset;
2574 if(!visualImpl.IsPixelAreaSetForFittingMode() && !Dali::EqualsZero(finalSize.width) && !Dali::EqualsZero(finalSize.height))
2576 float x = abs((availableVisualSize.width - finalSize.width) / finalSize.width) * .5f;
2577 float y = abs((availableVisualSize.height - finalSize.height) / finalSize.height) * .5f;
2578 float widthRatio = 1.f - abs((availableVisualSize.width - finalSize.width) / finalSize.width);
2579 float heightRatio = 1.f - abs((availableVisualSize.height - finalSize.height) / finalSize.height);
2580 Vector4 pixelArea = Vector4(x, y, widthRatio, heightRatio);
2581 visualImpl.SetPixelAreaForFittingMode(pixelArea);
2584 // populate the transform map
2585 transformMap.Add(Toolkit::Visual::Transform::Property::OFFSET, originalOffset)
2586 .Add(Toolkit::Visual::Transform::Property::SIZE, availableVisualSize);
2589 case Visual::FittingMode::CENTER:
2591 auto availableVisualSize = finalSize;
2592 if(availableVisualSize.width > naturalSize.width && availableVisualSize.height > naturalSize.height)
2594 finalSize = naturalSize;
2598 finalSize = naturalSize * std::min((!Dali::EqualsZero(naturalSize.width) ? (availableVisualSize.width / naturalSize.width) : 0.0f),
2599 (!Dali::EqualsZero(naturalSize.height) ? (availableVisualSize.height / naturalSize.height) : 0.0f));
2602 finalOffset += (availableVisualSize - finalSize) * .5f;
2604 // populate the transform map
2605 transformMap.Add(Toolkit::Visual::Transform::Property::OFFSET, finalOffset)
2606 .Add(Toolkit::Visual::Transform::Property::SIZE, finalSize);
2609 case Visual::FittingMode::FILL:
2611 transformMap.Add(Toolkit::Visual::Transform::Property::OFFSET, finalOffset)
2612 .Add(Toolkit::Visual::Transform::Property::SIZE, finalSize);
2615 case Visual::FittingMode::FIT_WIDTH:
2616 case Visual::FittingMode::FIT_HEIGHT:
2617 case Visual::FittingMode::DONT_CARE:
2619 // This FittingMode already converted
2624 // Set extra value for applying transformMap
2625 transformMap.Add(Toolkit::Visual::Transform::Property::OFFSET_POLICY,
2626 Vector2(Toolkit::Visual::Transform::Policy::ABSOLUTE, Toolkit::Visual::Transform::Policy::ABSOLUTE))
2627 .Add(Toolkit::Visual::Transform::Property::ORIGIN, Toolkit::Align::TOP_BEGIN)
2628 .Add(Toolkit::Visual::Transform::Property::ANCHOR_POINT, Toolkit::Align::TOP_BEGIN)
2629 .Add(Toolkit::Visual::Transform::Property::SIZE_POLICY,
2630 Vector2(Toolkit::Visual::Transform::Policy::ABSOLUTE, Toolkit::Visual::Transform::Policy::ABSOLUTE));
2632 else if(visualImpl.IsTransformMapSetForFittingMode() && zeroPadding) // Reset offset to zero only if padding applied previously
2634 visualImpl.SetTransformMapUsageForFittingMode(false);
2636 // Reset the transform map
2637 transformMap.Add(Toolkit::Visual::Transform::Property::OFFSET, Vector2::ZERO)
2638 .Add(Toolkit::Visual::Transform::Property::OFFSET_POLICY,
2639 Vector2(Toolkit::Visual::Transform::Policy::RELATIVE, Toolkit::Visual::Transform::Policy::RELATIVE))
2640 .Add(Toolkit::Visual::Transform::Property::SIZE, Vector2::ONE)
2641 .Add(Toolkit::Visual::Transform::Property::SIZE_POLICY,
2642 Vector2(Toolkit::Visual::Transform::Policy::RELATIVE, Toolkit::Visual::Transform::Policy::RELATIVE));
2645 ((*iter)->visual).SetTransformAndSize(transformMap, size);
2650 void Control::Impl::RegisterProcessorOnce()
2652 if(!mProcessorRegistered)
2654 Adaptor::Get().RegisterProcessorOnce(*this, true);
2655 mProcessorRegistered = true;
2659 void Control::Impl::Process(bool postProcessor)
2661 // Call ApplyFittingMode
2662 ApplyFittingMode(mSize);
2663 mProcessorRegistered = false;
2666 } // namespace Internal
2668 } // namespace Toolkit