2 * Copyright (c) 2019 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/dali-toolkit-common.h>
23 #include <dali/integration-api/debug.h>
24 #include <dali/devel-api/object/handle-devel.h>
25 #include <dali/devel-api/scripting/enum-helper.h>
26 #include <dali/devel-api/scripting/scripting.h>
27 #include <dali/integration-api/debug.h>
28 #include <dali/public-api/object/type-registry-helper.h>
29 #include <dali/integration-api/adaptor-framework/adaptor.h>
30 #include <dali/devel-api/common/stage.h>
31 #include <dali-toolkit/public-api/controls/control.h>
32 #include <dali/public-api/object/object-registry.h>
33 #include <dali/devel-api/adaptor-framework/accessibility.h>
34 #include <dali-toolkit/public-api/controls/control-impl.h>
35 #include <dali/devel-api/actors/actor-devel.h>
40 #include <dali-toolkit/internal/visuals/visual-base-impl.h>
41 #include <dali-toolkit/public-api/visuals/image-visual-properties.h>
42 #include <dali-toolkit/public-api/visuals/visual-properties.h>
43 #include <dali-toolkit/devel-api/controls/control-depth-index-ranges.h>
44 #include <dali-toolkit/devel-api/controls/control-devel.h>
45 #include <dali-toolkit/devel-api/controls/control-wrapper-impl.h>
46 #include <dali-toolkit/internal/styling/style-manager-impl.h>
47 #include <dali-toolkit/internal/visuals/visual-string-constants.h>
48 #include <dali-toolkit/public-api/focus-manager/keyboard-focus-manager.h>
49 #include <dali-toolkit/public-api/controls/image-view/image-view.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 = "|";
70 extern const Dali::Scripting::StringEnum ControlStateTable[];
71 extern const unsigned int ControlStateTableCount;
74 // Not static or anonymous - shared with other translation units
75 const Scripting::StringEnum ControlStateTable[] = {
76 { "NORMAL", Toolkit::DevelControl::NORMAL },
77 { "FOCUSED", Toolkit::DevelControl::FOCUSED },
78 { "DISABLED", Toolkit::DevelControl::DISABLED },
80 const unsigned int ControlStateTableCount = sizeof( ControlStateTable ) / sizeof( ControlStateTable[0] );
87 #if defined(DEBUG_ENABLED)
88 Debug::Filter* gLogFilter = Debug::Filter::New( Debug::NoLogging, false, "LOG_CONTROL_VISUALS");
93 void Remove( Dictionary<T>& keyValues, const std::string& name )
95 keyValues.Remove(name);
98 void Remove( DictionaryKeys& keys, const std::string& name )
100 DictionaryKeys::iterator iter = std::find( keys.begin(), keys.end(), name );
101 if( iter != keys.end())
108 * Finds visual in given array, returning true if found along with the iterator for that visual as a out parameter
110 bool FindVisual( Property::Index targetIndex, const RegisteredVisualContainer& visuals, RegisteredVisualContainer::Iterator& iter )
112 for ( iter = visuals.Begin(); iter != visuals.End(); iter++ )
114 if ( (*iter)->index == targetIndex )
123 * Finds visual in given array, returning true if found along with the iterator for that visual as a out parameter
125 bool FindVisual( std::string visualName, const RegisteredVisualContainer& visuals, RegisteredVisualContainer::Iterator& iter )
127 for ( iter = visuals.Begin(); iter != visuals.End(); iter++ )
129 Toolkit::Visual::Base visual = (*iter)->visual;
130 if( visual && visual.GetName() == visualName )
138 void FindChangableVisuals( Dictionary<Property::Map>& stateVisualsToAdd,
139 Dictionary<Property::Map>& stateVisualsToChange,
140 DictionaryKeys& stateVisualsToRemove)
142 DictionaryKeys copyOfStateVisualsToRemove = stateVisualsToRemove;
144 for( DictionaryKeys::iterator iter = copyOfStateVisualsToRemove.begin();
145 iter != copyOfStateVisualsToRemove.end(); ++iter )
147 const std::string& visualName = (*iter);
148 Property::Map* toMap = stateVisualsToAdd.Find( visualName );
151 stateVisualsToChange.Add( visualName, *toMap );
152 stateVisualsToAdd.Remove( visualName );
153 Remove( stateVisualsToRemove, visualName );
158 Toolkit::Visual::Base GetVisualByName(
159 const RegisteredVisualContainer& visuals,
160 const std::string& visualName )
162 Toolkit::Visual::Base visualHandle;
164 RegisteredVisualContainer::Iterator iter;
165 for ( iter = visuals.Begin(); iter != visuals.End(); iter++ )
167 Toolkit::Visual::Base visual = (*iter)->visual;
168 if( visual && visual.GetName() == visualName )
170 visualHandle = visual;
177 Toolkit::Visual::Base GetVisualByIndex(
178 const RegisteredVisualContainer& visuals,
179 Property::Index index)
181 Toolkit::Visual::Base visualHandle;
183 RegisteredVisualContainer::Iterator iter;
184 for(iter = visuals.Begin(); iter != visuals.End(); iter++)
186 if((*iter)->index == index)
188 visualHandle = (*iter)->visual;
196 * Move visual from source to destination container
198 void MoveVisual( RegisteredVisualContainer::Iterator sourceIter, RegisteredVisualContainer& source, RegisteredVisualContainer& destination )
200 Toolkit::Visual::Base visual = (*sourceIter)->visual;
203 RegisteredVisual* rv = source.Release( sourceIter );
204 destination.PushBack( rv );
209 * Performs actions as requested using the action name.
210 * @param[in] object The object on which to perform the action.
211 * @param[in] actionName The action to perform.
212 * @param[in] attributes The attributes with which to perfrom this action.
213 * @return true if action has been accepted by this control
215 const char* ACTION_ACCESSIBILITY_ACTIVATED = "accessibilityActivated";
216 const char* ACTION_ACCESSIBILITY_READING_CANCELLED = "ReadingCancelled";
217 const char* ACTION_ACCESSIBILITY_READING_PAUSED = "ReadingPaused";
218 const char* ACTION_ACCESSIBILITY_READING_RESUMED = "ReadingResumed";
219 const char* ACTION_ACCESSIBILITY_READING_SKIPPED = "ReadingSkipped";
220 const char* ACTION_ACCESSIBILITY_READING_STOPPED = "ReadingStopped";
222 static bool DoAction( BaseObject* object, const std::string& actionName, const Property::Map& attributes )
226 Dali::BaseHandle handle( object );
228 Toolkit::Control control = Toolkit::Control::DownCast( handle );
230 DALI_ASSERT_ALWAYS( control );
232 if( 0 == strcmp( actionName.c_str(), ACTION_ACCESSIBILITY_ACTIVATED ) ||
233 actionName == "activate" )
235 // if cast succeeds there is an implementation so no need to check
236 if( !DevelControl::AccessibilityActivateSignal( control ).Empty() )
237 DevelControl::AccessibilityActivateSignal( control ).Emit();
238 else ret = Internal::GetImplementation( control ).OnAccessibilityActivated();
240 else if( 0 == strcmp( actionName.c_str(), ACTION_ACCESSIBILITY_READING_SKIPPED ) )
242 // if cast succeeds there is an implementation so no need to check
243 if( !DevelControl::AccessibilityReadingSkippedSignal( control ).Empty() )
244 DevelControl::AccessibilityReadingSkippedSignal( control ).Emit();
246 else if( 0 == strcmp( actionName.c_str(), ACTION_ACCESSIBILITY_READING_PAUSED ) )
248 // if cast succeeds there is an implementation so no need to check
249 if( !DevelControl::AccessibilityReadingPausedSignal( control ).Empty() )
250 DevelControl::AccessibilityReadingPausedSignal( control ).Emit();
252 else if( 0 == strcmp( actionName.c_str(), ACTION_ACCESSIBILITY_READING_RESUMED ) )
254 // if cast succeeds there is an implementation so no need to check
255 if( !DevelControl::AccessibilityReadingResumedSignal( control ).Empty() )
256 DevelControl::AccessibilityReadingResumedSignal( control ).Emit();
258 else if( 0 == strcmp( actionName.c_str(), ACTION_ACCESSIBILITY_READING_CANCELLED ) )
260 // if cast succeeds there is an implementation so no need to check
261 if( !DevelControl::AccessibilityReadingCancelledSignal( control ).Empty() )
262 DevelControl::AccessibilityReadingCancelledSignal( control ).Emit();
264 else if( 0 == strcmp( actionName.c_str(), ACTION_ACCESSIBILITY_READING_STOPPED ) )
266 // if cast succeeds there is an implementation so no need to check
267 if(!DevelControl::AccessibilityReadingStoppedSignal( control ).Empty())
268 DevelControl::AccessibilityReadingStoppedSignal( control ).Emit();
277 * Connects a callback function with the object's signals.
278 * @param[in] object The object providing the signal.
279 * @param[in] tracker Used to disconnect the signal.
280 * @param[in] signalName The signal to connect to.
281 * @param[in] functor A newly allocated FunctorDelegate.
282 * @return True if the signal was connected.
283 * @post If a signal was connected, ownership of functor was passed to CallbackBase. Otherwise the caller is responsible for deleting the unused functor.
285 const char* SIGNAL_KEY_EVENT = "keyEvent";
286 const char* SIGNAL_KEY_INPUT_FOCUS_GAINED = "keyInputFocusGained";
287 const char* SIGNAL_KEY_INPUT_FOCUS_LOST = "keyInputFocusLost";
288 const char* SIGNAL_TAPPED = "tapped";
289 const char* SIGNAL_PANNED = "panned";
290 const char* SIGNAL_PINCHED = "pinched";
291 const char* SIGNAL_LONG_PRESSED = "longPressed";
292 const char* SIGNAL_GET_NAME = "getName";
293 const char* SIGNAL_GET_DESCRIPTION = "getDescription";
294 const char* SIGNAL_DO_GESTURE = "doGesture";
295 static bool DoConnectSignal( BaseObject* object, ConnectionTrackerInterface* tracker, const std::string& signalName, FunctorDelegate* functor )
297 Dali::BaseHandle handle( object );
299 bool connected( false );
300 Toolkit::Control control = Toolkit::Control::DownCast( handle );
303 Internal::Control& controlImpl( Internal::GetImplementation( control ) );
306 if ( 0 == strcmp( signalName.c_str(), SIGNAL_KEY_EVENT ) )
308 controlImpl.KeyEventSignal().Connect( tracker, functor );
310 else if( 0 == strcmp( signalName.c_str(), SIGNAL_KEY_INPUT_FOCUS_GAINED ) )
312 controlImpl.KeyInputFocusGainedSignal().Connect( tracker, functor );
314 else if( 0 == strcmp( signalName.c_str(), SIGNAL_KEY_INPUT_FOCUS_LOST ) )
316 controlImpl.KeyInputFocusLostSignal().Connect( tracker, functor );
318 else if( 0 == strcmp( signalName.c_str(), SIGNAL_TAPPED ) )
320 controlImpl.EnableGestureDetection( GestureType::TAP );
321 controlImpl.GetTapGestureDetector().DetectedSignal().Connect( tracker, functor );
323 else if( 0 == strcmp( signalName.c_str(), SIGNAL_PANNED ) )
325 controlImpl.EnableGestureDetection( GestureType::PAN );
326 controlImpl.GetPanGestureDetector().DetectedSignal().Connect( tracker, functor );
328 else if( 0 == strcmp( signalName.c_str(), SIGNAL_PINCHED ) )
330 controlImpl.EnableGestureDetection( GestureType::PINCH );
331 controlImpl.GetPinchGestureDetector().DetectedSignal().Connect( tracker, functor );
333 else if( 0 == strcmp( signalName.c_str(), SIGNAL_LONG_PRESSED ) )
335 controlImpl.EnableGestureDetection( GestureType::LONG_PRESS );
336 controlImpl.GetLongPressGestureDetector().DetectedSignal().Connect( tracker, functor );
338 else if( 0 == strcmp( signalName.c_str(), SIGNAL_GET_NAME ) )
340 DevelControl::AccessibilityGetNameSignal( control ).Connect( tracker, functor );
342 else if( 0 == strcmp( signalName.c_str(), SIGNAL_GET_DESCRIPTION ) )
344 DevelControl::AccessibilityGetDescriptionSignal( control ).Connect( tracker, functor );
346 else if( 0 == strcmp( signalName.c_str(), SIGNAL_DO_GESTURE ) )
348 DevelControl::AccessibilityDoGestureSignal( control ).Connect( tracker, functor );
356 * Creates control through type registry
360 return Internal::Control::New();
362 // Setup signals and actions using the type-registry.
363 DALI_TYPE_REGISTRATION_BEGIN( Control, CustomActor, Create );
365 // Note: Properties are registered separately below.
367 SignalConnectorType registerSignal1( typeRegistration, SIGNAL_KEY_EVENT, &DoConnectSignal );
368 SignalConnectorType registerSignal2( typeRegistration, SIGNAL_KEY_INPUT_FOCUS_GAINED, &DoConnectSignal );
369 SignalConnectorType registerSignal3( typeRegistration, SIGNAL_KEY_INPUT_FOCUS_LOST, &DoConnectSignal );
370 SignalConnectorType registerSignal4( typeRegistration, SIGNAL_TAPPED, &DoConnectSignal );
371 SignalConnectorType registerSignal5( typeRegistration, SIGNAL_PANNED, &DoConnectSignal );
372 SignalConnectorType registerSignal6( typeRegistration, SIGNAL_PINCHED, &DoConnectSignal );
373 SignalConnectorType registerSignal7( typeRegistration, SIGNAL_LONG_PRESSED, &DoConnectSignal );
374 SignalConnectorType registerSignal8( typeRegistration, SIGNAL_GET_NAME, &DoConnectSignal );
375 SignalConnectorType registerSignal9( typeRegistration, SIGNAL_GET_DESCRIPTION, &DoConnectSignal );
376 SignalConnectorType registerSignal10( typeRegistration, SIGNAL_DO_GESTURE, &DoConnectSignal );
378 TypeAction registerAction1( typeRegistration, "activate", &DoAction );
379 TypeAction registerAction2( typeRegistration, ACTION_ACCESSIBILITY_ACTIVATED, &DoAction );
380 TypeAction registerAction3( typeRegistration, ACTION_ACCESSIBILITY_READING_SKIPPED, &DoAction );
381 TypeAction registerAction4( typeRegistration, ACTION_ACCESSIBILITY_READING_CANCELLED, &DoAction );
382 TypeAction registerAction5( typeRegistration, ACTION_ACCESSIBILITY_READING_STOPPED, &DoAction );
383 TypeAction registerAction6( typeRegistration, ACTION_ACCESSIBILITY_READING_PAUSED, &DoAction );
384 TypeAction registerAction7( typeRegistration, ACTION_ACCESSIBILITY_READING_RESUMED, &DoAction );
386 DALI_TYPE_REGISTRATION_END()
389 * @brief Iterate through given container and setOffScene any visual found
391 * @param[in] container Container of visuals
392 * @param[in] parent Parent actor to remove visuals from
394 void SetVisualsOffScene( const RegisteredVisualContainer& container, Actor parent )
396 for( auto iter = container.Begin(), end = container.End() ; iter!= end; iter++)
398 if( (*iter)->visual )
400 DALI_LOG_INFO( gLogFilter, Debug::Verbose, "Control::SetOffScene Setting visual(%d) off stage\n", (*iter)->index );
401 Toolkit::GetImplementation((*iter)->visual).SetOffScene( parent );
406 } // unnamed namespace
409 // Properties registered without macro to use specific member variables.
410 const PropertyRegistration Control::Impl::PROPERTY_1( typeRegistration, "styleName", Toolkit::Control::Property::STYLE_NAME, Property::STRING, &Control::Impl::SetProperty, &Control::Impl::GetProperty );
411 const PropertyRegistration Control::Impl::PROPERTY_4( typeRegistration, "keyInputFocus", Toolkit::Control::Property::KEY_INPUT_FOCUS, Property::BOOLEAN, &Control::Impl::SetProperty, &Control::Impl::GetProperty );
412 const PropertyRegistration Control::Impl::PROPERTY_5( typeRegistration, "background", Toolkit::Control::Property::BACKGROUND, Property::MAP, &Control::Impl::SetProperty, &Control::Impl::GetProperty );
413 const PropertyRegistration Control::Impl::PROPERTY_6( typeRegistration, "margin", Toolkit::Control::Property::MARGIN, Property::EXTENTS, &Control::Impl::SetProperty, &Control::Impl::GetProperty );
414 const PropertyRegistration Control::Impl::PROPERTY_7( typeRegistration, "padding", Toolkit::Control::Property::PADDING, Property::EXTENTS, &Control::Impl::SetProperty, &Control::Impl::GetProperty );
415 const PropertyRegistration Control::Impl::PROPERTY_8( typeRegistration, "tooltip", Toolkit::DevelControl::Property::TOOLTIP, Property::MAP, &Control::Impl::SetProperty, &Control::Impl::GetProperty );
416 const PropertyRegistration Control::Impl::PROPERTY_9( typeRegistration, "state", Toolkit::DevelControl::Property::STATE, Property::STRING, &Control::Impl::SetProperty, &Control::Impl::GetProperty );
417 const PropertyRegistration Control::Impl::PROPERTY_10( typeRegistration, "subState", Toolkit::DevelControl::Property::SUB_STATE, Property::STRING, &Control::Impl::SetProperty, &Control::Impl::GetProperty );
418 const PropertyRegistration Control::Impl::PROPERTY_11( typeRegistration, "leftFocusableActorId", Toolkit::DevelControl::Property::LEFT_FOCUSABLE_ACTOR_ID, Property::INTEGER, &Control::Impl::SetProperty, &Control::Impl::GetProperty );
419 const PropertyRegistration Control::Impl::PROPERTY_12( typeRegistration, "rightFocusableActorId", Toolkit::DevelControl::Property::RIGHT_FOCUSABLE_ACTOR_ID,Property::INTEGER, &Control::Impl::SetProperty, &Control::Impl::GetProperty );
420 const PropertyRegistration Control::Impl::PROPERTY_13( typeRegistration, "upFocusableActorId", Toolkit::DevelControl::Property::UP_FOCUSABLE_ACTOR_ID, Property::INTEGER, &Control::Impl::SetProperty, &Control::Impl::GetProperty );
421 const PropertyRegistration Control::Impl::PROPERTY_14( typeRegistration, "downFocusableActorId", Toolkit::DevelControl::Property::DOWN_FOCUSABLE_ACTOR_ID, Property::INTEGER, &Control::Impl::SetProperty, &Control::Impl::GetProperty );
422 const PropertyRegistration Control::Impl::PROPERTY_15( typeRegistration, "shadow", Toolkit::DevelControl::Property::SHADOW, Property::MAP, &Control::Impl::SetProperty, &Control::Impl::GetProperty );
423 const PropertyRegistration Control::Impl::PROPERTY_16( typeRegistration, "accessibilityAttributes", Toolkit::DevelControl::Property::ACCESSIBILITY_ATTRIBUTES, Property::MAP, &Control::Impl::SetProperty, &Control::Impl::GetProperty );
424 const PropertyRegistration Control::Impl::PROPERTY_17( typeRegistration, "accessibilityName", Toolkit::DevelControl::Property::ACCESSIBILITY_NAME, Property::STRING, &Control::Impl::SetProperty, &Control::Impl::GetProperty );
425 const PropertyRegistration Control::Impl::PROPERTY_18( typeRegistration, "accessibilityDescription", Toolkit::DevelControl::Property::ACCESSIBILITY_DESCRIPTION, Property::STRING, &Control::Impl::SetProperty, &Control::Impl::GetProperty );
426 const PropertyRegistration Control::Impl::PROPERTY_19( typeRegistration, "accessibilityTranslationDomain", Toolkit::DevelControl::Property::ACCESSIBILITY_TRANSLATION_DOMAIN, Property::STRING, &Control::Impl::SetProperty, &Control::Impl::GetProperty );
427 const PropertyRegistration Control::Impl::PROPERTY_20( typeRegistration, "accessibilityRole", Toolkit::DevelControl::Property::ACCESSIBILITY_ROLE, Property::INTEGER, &Control::Impl::SetProperty, &Control::Impl::GetProperty );
428 const PropertyRegistration Control::Impl::PROPERTY_21( typeRegistration, "accessibilityHighlightable", Toolkit::DevelControl::Property::ACCESSIBILITY_HIGHLIGHTABLE, Property::BOOLEAN, &Control::Impl::SetProperty, &Control::Impl::GetProperty );
429 const PropertyRegistration Control::Impl::PROPERTY_22( typeRegistration, "accessibilityAnimated", Toolkit::DevelControl::Property::ACCESSIBILITY_ANIMATED, Property::BOOLEAN, &Control::Impl::SetProperty, &Control::Impl::GetProperty );
431 Control::Impl::Impl( Control& controlImpl )
432 : mControlImpl( controlImpl ),
433 mState( Toolkit::DevelControl::NORMAL ),
435 mLeftFocusableActorId( -1 ),
436 mRightFocusableActorId( -1 ),
437 mUpFocusableActorId( -1 ),
438 mDownFocusableActorId( -1 ),
440 mBackgroundColor(Color::TRANSPARENT),
441 mStartingPinchScale(nullptr),
442 mMargin( 0, 0, 0, 0 ),
443 mPadding( 0, 0, 0, 0 ),
445 mKeyInputFocusGainedSignal(),
446 mKeyInputFocusLostSignal(),
447 mResourceReadySignal(),
448 mVisualEventSignal(),
449 mAccessibilityGetNameSignal(),
450 mAccessibilityGetDescriptionSignal(),
451 mAccessibilityDoGestureSignal(),
452 mPinchGestureDetector(),
453 mPanGestureDetector(),
454 mTapGestureDetector(),
455 mLongPressGestureDetector(),
457 mInputMethodContext(),
458 mIdleCallback(nullptr),
460 mAutofillContainer(),
461 mFlags( Control::ControlBehaviour( CONTROL_BEHAVIOUR_DEFAULT ) ),
462 mIsKeyboardNavigationSupported( false ),
463 mIsKeyboardFocusGroup( false ),
464 mIsEmittingResourceReadySignal(false),
465 mNeedToEmitResourceReady(false),
466 mIsAutofillEnabled( false )
468 Dali::Accessibility::Accessible::RegisterControlAccessibilityGetter(
469 []( Dali::Actor actor ) -> Dali::Accessibility::Accessible* {
470 return Control::Impl::GetAccessibilityObject( actor );
473 accessibilityConstructor = []( Dali::Actor actor ) -> std::unique_ptr< Dali::Accessibility::Accessible > {
474 return std::unique_ptr< Dali::Accessibility::Accessible >( new AccessibleImpl( actor,
475 Dali::Accessibility::Role::UNKNOWN ) );
478 size_t len = static_cast<size_t>(Dali::Accessibility::RelationType::MAX_COUNT);
479 mAccessibilityRelations.reserve(len);
480 for (auto i = 0u; i < len; ++i)
482 mAccessibilityRelations.push_back({});
486 Control::Impl::~Impl()
488 for( auto&& iter : mVisuals )
490 StopObservingVisual( iter->visual );
493 for( auto&& iter : mRemoveVisuals )
495 StopObservingVisual( iter->visual );
498 AccessibilityDeregister();
499 // All gesture detectors will be destroyed so no need to disconnect.
500 delete mStartingPinchScale;
502 if(mIdleCallback && Adaptor::IsAvailable())
504 // Removes the callback from the callback manager in case the control is destroyed before the callback is executed.
505 Adaptor::Get().RemoveIdle(mIdleCallback);
509 Control::Impl& Control::Impl::Get( Internal::Control& internalControl )
511 return *internalControl.mImpl;
514 const Control::Impl& Control::Impl::Get( const Internal::Control& internalControl )
516 return *internalControl.mImpl;
519 // Gesture Detection Methods
520 void Control::Impl::PinchDetected(Actor actor, const PinchGesture& pinch)
522 mControlImpl.OnPinch(pinch);
525 void Control::Impl::PanDetected(Actor actor, const PanGesture& pan)
527 mControlImpl.OnPan(pan);
530 void Control::Impl::TapDetected(Actor actor, const TapGesture& tap)
532 mControlImpl.OnTap(tap);
535 void Control::Impl::LongPressDetected(Actor actor, const LongPressGesture& longPress)
537 mControlImpl.OnLongPress(longPress);
540 void Control::Impl::RegisterVisual( Property::Index index, Toolkit::Visual::Base& visual )
542 RegisterVisual( index, visual, VisualState::ENABLED, DepthIndexValue::NOT_SET );
545 void Control::Impl::RegisterVisual( Property::Index index, Toolkit::Visual::Base& visual, int depthIndex )
547 RegisterVisual( index, visual, VisualState::ENABLED, DepthIndexValue::SET, depthIndex );
550 void Control::Impl::RegisterVisual( Property::Index index, Toolkit::Visual::Base& visual, bool enabled )
552 RegisterVisual( index, visual, ( enabled ? VisualState::ENABLED : VisualState::DISABLED ), DepthIndexValue::NOT_SET );
555 void Control::Impl::RegisterVisual( Property::Index index, Toolkit::Visual::Base& visual, bool enabled, int depthIndex )
557 RegisterVisual( index, visual, ( enabled ? VisualState::ENABLED : VisualState::DISABLED ), DepthIndexValue::SET, depthIndex );
560 void Control::Impl::RegisterVisual( Property::Index index, Toolkit::Visual::Base& visual, VisualState::Type enabled, DepthIndexValue::Type depthIndexValueSet, int depthIndex )
562 DALI_LOG_INFO( gLogFilter, Debug::Concise, "RegisterVisual:%d \n", index );
564 bool visualReplaced ( false );
565 Actor self = mControlImpl.Self();
567 // Set the depth index, if not set by caller this will be either the current visual depth, max depth of all visuals
569 int requiredDepthIndex = visual.GetDepthIndex();
571 if( depthIndexValueSet == DepthIndexValue::SET )
573 requiredDepthIndex = depthIndex;
576 // Visual replacement, existing visual should only be removed from stage when replacement ready.
577 if( !mVisuals.Empty() )
579 RegisteredVisualContainer::Iterator registeredVisualsiter;
580 // Check if visual (index) is already registered, this is the current visual.
581 if( FindVisual( index, mVisuals, registeredVisualsiter ) )
583 Toolkit::Visual::Base& currentRegisteredVisual = (*registeredVisualsiter)->visual;
584 if( currentRegisteredVisual )
586 // Store current visual depth index as may need to set the replacement visual to same depth
587 const int currentDepthIndex = (*registeredVisualsiter)->visual.GetDepthIndex();
589 // No longer required to know if the replaced visual's resources are ready
590 StopObservingVisual( currentRegisteredVisual );
592 // If control staged and visual enabled then visuals will be swapped once ready
593 if( self.GetProperty< bool >( Actor::Property::CONNECTED_TO_SCENE ) && enabled )
595 // Check if visual is currently in the process of being replaced ( is in removal container )
596 RegisteredVisualContainer::Iterator visualQueuedForRemoval;
597 if ( FindVisual( index, mRemoveVisuals, visualQueuedForRemoval ) )
599 // Visual with same index is already in removal container so current visual pending
600 // Only the the last requested visual will be displayed so remove current visual which is staged but not ready.
601 Toolkit::GetImplementation( currentRegisteredVisual ).SetOffScene( self );
602 mVisuals.Erase( registeredVisualsiter );
606 // current visual not already in removal container so add now.
607 DALI_LOG_INFO( gLogFilter, Debug::Verbose, "RegisterVisual Move current registered visual to removal Queue: %d \n", index );
608 MoveVisual( registeredVisualsiter, mVisuals, mRemoveVisuals );
613 // Control not staged or visual disabled so can just erase from registered visuals and new visual will be added later.
614 mVisuals.Erase( registeredVisualsiter );
617 // 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
618 if( ( depthIndexValueSet == DepthIndexValue::NOT_SET ) &&
619 ( visual.GetDepthIndex() == 0 ) )
621 requiredDepthIndex = currentDepthIndex;
625 visualReplaced = true;
629 // If not set, set the name of the visual to the same name as the control's property.
630 // ( If the control has been type registered )
631 if( visual.GetName().empty() )
633 // returns empty string if index is not found as long as index is not -1
634 std::string visualName = self.GetPropertyName( index );
635 if( !visualName.empty() )
637 DALI_LOG_INFO( gLogFilter, Debug::Concise, "Setting visual name for property %d to %s\n",
638 index, visualName.c_str() );
639 visual.SetName( visualName );
643 if( !visualReplaced ) // New registration entry
645 // 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
646 if( ( depthIndexValueSet == DepthIndexValue::NOT_SET ) &&
647 ( mVisuals.Size() > 0 ) &&
648 ( visual.GetDepthIndex() == 0 ) )
650 int maxDepthIndex = std::numeric_limits< int >::min();
652 RegisteredVisualContainer::ConstIterator iter;
653 const RegisteredVisualContainer::ConstIterator endIter = mVisuals.End();
654 for ( iter = mVisuals.Begin(); iter != endIter; iter++ )
656 const int visualDepthIndex = (*iter)->visual.GetDepthIndex();
657 if ( visualDepthIndex > maxDepthIndex )
659 maxDepthIndex = visualDepthIndex;
662 ++maxDepthIndex; // Add one to the current maximum depth index so that our added visual appears on top
663 requiredDepthIndex = std::max( 0, maxDepthIndex ); // Start at zero if maxDepth index belongs to a background
669 // Set determined depth index
670 visual.SetDepthIndex( requiredDepthIndex );
672 // Monitor when the visual resources are ready
673 StartObservingVisual( visual );
675 DALI_LOG_INFO( gLogFilter, Debug::Concise, "New Visual registration index[%d] depth[%d]\n", index, requiredDepthIndex );
676 RegisteredVisual* newRegisteredVisual = new RegisteredVisual( index, visual,
677 ( enabled == VisualState::ENABLED ? true : false ),
678 ( visualReplaced && enabled ) ) ;
679 mVisuals.PushBack( newRegisteredVisual );
681 Internal::Visual::Base& visualImpl = Toolkit::GetImplementation( visual );
682 // Put on stage if enabled and the control is already on the stage
683 if( ( enabled == VisualState::ENABLED ) && self.GetProperty< bool >( Actor::Property::CONNECTED_TO_SCENE ) )
685 visualImpl.SetOnScene( self );
687 else if( visualImpl.IsResourceReady() ) // When not being staged, check if visual already 'ResourceReady' before it was Registered. ( Resource may have been loaded already )
689 ResourceReady( visualImpl );
694 DALI_LOG_INFO( gLogFilter, Debug::Verbose, "Control::RegisterVisual() Registered %s(%d), enabled:%s\n", visual.GetName().c_str(), index, enabled?"true":"false" );
697 void Control::Impl::UnregisterVisual( Property::Index index )
699 RegisteredVisualContainer::Iterator iter;
700 if ( FindVisual( index, mVisuals, iter ) )
702 // stop observing visual
703 StopObservingVisual( (*iter)->visual );
705 Actor self( mControlImpl.Self() );
706 Toolkit::GetImplementation((*iter)->visual).SetOffScene( self );
707 (*iter)->visual.Reset();
708 mVisuals.Erase( iter );
711 if( FindVisual( index, mRemoveVisuals, iter ) )
713 Actor self( mControlImpl.Self() );
714 Toolkit::GetImplementation( (*iter)->visual ).SetOffScene( self );
715 (*iter)->pending = false;
716 (*iter)->visual.Reset();
717 mRemoveVisuals.Erase( iter );
721 Toolkit::Visual::Base Control::Impl::GetVisual( Property::Index index ) const
723 RegisteredVisualContainer::Iterator iter;
724 if ( FindVisual( index, mVisuals, iter ) )
726 return (*iter)->visual;
729 return Toolkit::Visual::Base();
732 void Control::Impl::EnableVisual( Property::Index index, bool enable )
734 DALI_LOG_INFO( gLogFilter, Debug::General, "Control::EnableVisual(%d, %s)\n", index, enable?"T":"F");
736 RegisteredVisualContainer::Iterator iter;
737 if ( FindVisual( index, mVisuals, iter ) )
739 if ( (*iter)->enabled == enable )
741 DALI_LOG_INFO( gLogFilter, Debug::Verbose, "Control::EnableVisual Visual %s(%d) already %s\n", (*iter)->visual.GetName().c_str(), index, enable?"enabled":"disabled");
745 (*iter)->enabled = enable;
746 Actor parentActor = mControlImpl.Self();
747 if ( mControlImpl.Self().GetProperty< bool >( Actor::Property::CONNECTED_TO_SCENE ) ) // If control not on Scene then Visual will be added when SceneConnection is called.
751 DALI_LOG_INFO( gLogFilter, Debug::Verbose, "Control::EnableVisual Setting %s(%d) on stage \n", (*iter)->visual.GetName().c_str(), index );
752 Toolkit::GetImplementation((*iter)->visual).SetOnScene( parentActor );
756 DALI_LOG_INFO( gLogFilter, Debug::Verbose, "Control::EnableVisual Setting %s(%d) off stage \n", (*iter)->visual.GetName().c_str(), index );
757 Toolkit::GetImplementation((*iter)->visual).SetOffScene( parentActor ); // No need to call if control not staged.
763 DALI_LOG_WARNING( "Control::EnableVisual(%d, %s) FAILED - NO SUCH VISUAL\n", index, enable?"T":"F" );
767 bool Control::Impl::IsVisualEnabled( Property::Index index ) const
769 RegisteredVisualContainer::Iterator iter;
770 if ( FindVisual( index, mVisuals, iter ) )
772 return (*iter)->enabled;
777 void Control::Impl::StopObservingVisual( Toolkit::Visual::Base& visual )
779 Internal::Visual::Base& visualImpl = Toolkit::GetImplementation( visual );
781 // Stop observing the visual
782 visualImpl.RemoveEventObserver( *this );
785 void Control::Impl::StartObservingVisual( Toolkit::Visual::Base& visual)
787 Internal::Visual::Base& visualImpl = Toolkit::GetImplementation( visual );
789 // start observing the visual for events
790 visualImpl.AddEventObserver( *this );
793 // Called by a Visual when it's resource is ready
794 void Control::Impl::ResourceReady( Visual::Base& object)
796 DALI_LOG_INFO( gLogFilter, Debug::Verbose, "Control::Impl::ResourceReady() replacements pending[%d]\n", mRemoveVisuals.Count() );
798 Actor self = mControlImpl.Self();
800 // A resource is ready, find resource in the registered visuals container and get its index
801 for( auto registeredIter = mVisuals.Begin(), end = mVisuals.End(); registeredIter != end; ++registeredIter )
803 Internal::Visual::Base& registeredVisualImpl = Toolkit::GetImplementation( (*registeredIter)->visual );
805 if( &object == ®isteredVisualImpl )
807 RegisteredVisualContainer::Iterator visualToRemoveIter;
808 // Find visual with the same index in the removal container
809 // Set if off stage as it's replacement is now ready.
810 // Remove if from removal list as now removed from stage.
811 // Set Pending flag on the ready visual to false as now ready.
812 if( FindVisual( (*registeredIter)->index, mRemoveVisuals, visualToRemoveIter ) )
814 (*registeredIter)->pending = false;
815 Toolkit::GetImplementation( (*visualToRemoveIter)->visual ).SetOffScene( self );
816 mRemoveVisuals.Erase( visualToRemoveIter );
822 // A visual is ready so control may need relayouting if staged
823 if ( self.GetProperty< bool >( Actor::Property::CONNECTED_TO_SCENE ) )
825 mControlImpl.RelayoutRequest();
828 // Emit signal if all enabled visuals registered by the control are ready.
829 if( IsResourceReady() )
832 mNeedToEmitResourceReady = false;
834 EmitResourceReadySignal();
838 void Control::Impl::NotifyVisualEvent( Visual::Base& object, Property::Index signalId )
840 for( auto registeredIter = mVisuals.Begin(), end = mVisuals.End(); registeredIter != end; ++registeredIter )
842 Internal::Visual::Base& registeredVisualImpl = Toolkit::GetImplementation( (*registeredIter)->visual );
843 if( &object == ®isteredVisualImpl )
845 Dali::Toolkit::Control handle( mControlImpl.GetOwner() );
846 mVisualEventSignal.Emit( handle, (*registeredIter)->index, signalId );
852 bool Control::Impl::IsResourceReady() const
854 // Iterate through and check all the enabled visuals are ready
855 for( auto visualIter = mVisuals.Begin();
856 visualIter != mVisuals.End(); ++visualIter )
858 const Toolkit::Visual::Base visual = (*visualIter)->visual;
859 const Internal::Visual::Base& visualImpl = Toolkit::GetImplementation( visual );
861 // one of the enabled visuals is not ready
862 if( !visualImpl.IsResourceReady() && (*visualIter)->enabled )
870 Toolkit::Visual::ResourceStatus Control::Impl::GetVisualResourceStatus( Property::Index index ) const
872 RegisteredVisualContainer::Iterator iter;
873 if ( FindVisual( index, mVisuals, iter ) )
875 const Toolkit::Visual::Base visual = (*iter)->visual;
876 const Internal::Visual::Base& visualImpl = Toolkit::GetImplementation( visual );
877 return visualImpl.GetResourceStatus( );
880 return Toolkit::Visual::ResourceStatus::PREPARING;
885 void Control::Impl::AddTransitions( Dali::Animation& animation,
886 const Toolkit::TransitionData& handle,
887 bool createAnimation )
889 // Setup a Transition from TransitionData.
890 const Internal::TransitionData& transitionData = Toolkit::GetImplementation( handle );
891 TransitionData::Iterator end = transitionData.End();
892 for( TransitionData::Iterator iter = transitionData.Begin() ;
893 iter != end; ++iter )
895 TransitionData::Animator* animator = (*iter);
897 Toolkit::Visual::Base visual = GetVisualByName( mVisuals, animator->objectName );
901 #if defined(DEBUG_ENABLED)
902 Dali::TypeInfo typeInfo;
903 ControlWrapper* controlWrapperImpl = dynamic_cast<ControlWrapper*>(&mControlImpl);
904 if( controlWrapperImpl )
906 typeInfo = controlWrapperImpl->GetTypeInfo();
909 DALI_LOG_INFO( gLogFilter, Debug::Concise, "CreateTransition: Found %s visual for %s\n",
910 visual.GetName().c_str(), typeInfo?typeInfo.GetName().c_str():"Unknown" );
912 Internal::Visual::Base& visualImpl = Toolkit::GetImplementation( visual );
913 visualImpl.AnimateProperty( animation, *animator );
917 DALI_LOG_INFO( gLogFilter, Debug::Concise, "CreateTransition: Could not find visual. Trying actors");
918 // Otherwise, try any actor children of control (Including the control)
919 Actor child = mControlImpl.Self().FindChildByName( animator->objectName );
922 Property::Index propertyIndex = child.GetPropertyIndex( animator->propertyKey );
923 if( propertyIndex != Property::INVALID_INDEX )
925 if( animator->animate == false )
927 if( animator->targetValue.GetType() != Property::NONE )
929 child.SetProperty( propertyIndex, animator->targetValue );
932 else // animate the property
934 if( animator->initialValue.GetType() != Property::NONE )
936 child.SetProperty( propertyIndex, animator->initialValue );
939 if( createAnimation && !animation )
941 animation = Dali::Animation::New( 0.1f );
944 animation.AnimateTo( Property( child, propertyIndex ),
945 animator->targetValue,
946 animator->alphaFunction,
947 TimePeriod( animator->timePeriodDelay,
948 animator->timePeriodDuration ) );
956 Dali::Animation Control::Impl::CreateTransition( const Toolkit::TransitionData& transitionData )
958 Dali::Animation transition;
960 if( transitionData.Count() > 0 )
962 AddTransitions( transition, transitionData, true );
969 void Control::Impl::DoAction( Dali::Property::Index visualIndex, Dali::Property::Index actionId, const Dali::Property::Value attributes )
971 RegisteredVisualContainer::Iterator iter;
972 if ( FindVisual( visualIndex, mVisuals, iter ) )
974 Toolkit::GetImplementation((*iter)->visual).DoAction( actionId, attributes );
978 void Control::Impl::AppendAccessibilityAttribute( const std::string& key,
979 const std::string value )
981 Property::Value* val = mAccessibilityAttributes.Find( key );
984 mAccessibilityAttributes[key] = Property::Value( value );
988 mAccessibilityAttributes.Insert( key, value );
992 void Control::Impl::SetProperty( BaseObject* object, Property::Index index, const Property::Value& value )
994 Toolkit::Control control = Toolkit::Control::DownCast( BaseHandle( object ) );
998 Control& controlImpl( GetImplementation( control ) );
1002 case Toolkit::Control::Property::STYLE_NAME:
1004 controlImpl.SetStyleName( value.Get< std::string >() );
1008 case Toolkit::DevelControl::Property::STATE:
1010 bool withTransitions=true;
1011 const Property::Value* valuePtr=&value;
1012 const Property::Map* map = value.GetMap();
1015 Property::Value* value2 = map->Find("withTransitions");
1018 withTransitions = value2->Get<bool>();
1021 valuePtr = map->Find("state");
1026 Toolkit::DevelControl::State state( controlImpl.mImpl->mState );
1027 if( Scripting::GetEnumerationProperty< Toolkit::DevelControl::State >( *valuePtr, ControlStateTable, ControlStateTableCount, state ) )
1029 controlImpl.mImpl->SetState( state, withTransitions );
1035 case Toolkit::DevelControl::Property::SUB_STATE:
1037 std::string subState;
1038 if( value.Get( subState ) )
1040 controlImpl.mImpl->SetSubState( subState );
1045 case Toolkit::DevelControl::Property::LEFT_FOCUSABLE_ACTOR_ID:
1048 if( value.Get( focusId ) )
1050 controlImpl.mImpl->mLeftFocusableActorId = focusId;
1055 case Toolkit::DevelControl::Property::RIGHT_FOCUSABLE_ACTOR_ID:
1058 if( value.Get( focusId ) )
1060 controlImpl.mImpl->mRightFocusableActorId = focusId;
1065 case Toolkit::DevelControl::Property::ACCESSIBILITY_NAME:
1068 if( value.Get( name ) )
1070 controlImpl.mImpl->mAccessibilityName = name;
1071 controlImpl.mImpl->mAccessibilityNameSet = true;
1075 controlImpl.mImpl->mAccessibilityNameSet = false;
1080 case Toolkit::DevelControl::Property::ACCESSIBILITY_DESCRIPTION:
1083 if( value.Get( txt ) )
1085 controlImpl.mImpl->mAccessibilityDescription = txt;
1086 controlImpl.mImpl->mAccessibilityDescriptionSet = true;
1090 controlImpl.mImpl->mAccessibilityDescriptionSet = false;
1095 case Toolkit::DevelControl::Property::ACCESSIBILITY_TRANSLATION_DOMAIN:
1098 if( value.Get( txt ) )
1100 controlImpl.mImpl->mAccessibilityTranslationDomain = txt;
1101 controlImpl.mImpl->mAccessibilityTranslationDomainSet = true;
1105 controlImpl.mImpl->mAccessibilityTranslationDomainSet = false;
1110 case Toolkit::DevelControl::Property::ACCESSIBILITY_HIGHLIGHTABLE:
1113 if( value.Get( highlightable ) )
1115 controlImpl.mImpl->mAccessibilityHighlightable = highlightable;
1116 controlImpl.mImpl->mAccessibilityHighlightableSet = true;
1120 controlImpl.mImpl->mAccessibilityHighlightableSet = false;
1125 case Toolkit::DevelControl::Property::ACCESSIBILITY_ROLE:
1127 Dali::Accessibility::Role val;
1128 if( value.Get( val ) )
1130 controlImpl.mImpl->mAccessibilityRole = val;
1135 case Toolkit::DevelControl::Property::UP_FOCUSABLE_ACTOR_ID:
1138 if( value.Get( focusId ) )
1140 controlImpl.mImpl->mUpFocusableActorId = focusId;
1145 case Toolkit::DevelControl::Property::DOWN_FOCUSABLE_ACTOR_ID:
1148 if( value.Get( focusId ) )
1150 controlImpl.mImpl->mDownFocusableActorId = focusId;
1155 case Toolkit::Control::Property::KEY_INPUT_FOCUS:
1157 if ( value.Get< bool >() )
1159 controlImpl.SetKeyInputFocus();
1163 controlImpl.ClearKeyInputFocus();
1168 case Toolkit::Control::Property::BACKGROUND:
1172 const Property::Map* map = value.GetMap();
1173 if( map && !map->Empty() )
1175 controlImpl.SetBackground( *map );
1177 else if( value.Get( url ) )
1179 // don't know the size to load
1180 Toolkit::Visual::Base visual = Toolkit::VisualFactory::Get().CreateVisual( url, ImageDimensions() );
1183 controlImpl.mImpl->RegisterVisual( Toolkit::Control::Property::BACKGROUND, visual, DepthIndex::BACKGROUND );
1186 else if( value.Get( color ) )
1188 controlImpl.SetBackgroundColor(color);
1192 // The background is an empty property map, so we should clear the background
1193 controlImpl.ClearBackground();
1198 case Toolkit::Control::Property::MARGIN:
1201 if( value.Get( margin ) )
1203 controlImpl.mImpl->SetMargin( margin );
1208 case Toolkit::Control::Property::PADDING:
1211 if( value.Get( padding ) )
1213 controlImpl.mImpl->SetPadding( padding );
1218 case Toolkit::DevelControl::Property::TOOLTIP:
1220 TooltipPtr& tooltipPtr = controlImpl.mImpl->mTooltip;
1223 tooltipPtr = Tooltip::New( control );
1225 tooltipPtr->SetProperties( value );
1229 case Toolkit::DevelControl::Property::SHADOW:
1231 const Property::Map* map = value.GetMap();
1232 if( map && !map->Empty() )
1234 controlImpl.mImpl->SetShadow( *map );
1238 // The shadow is an empty property map, so we should clear the shadow
1239 controlImpl.mImpl->ClearShadow();
1244 case Toolkit::DevelControl::Property::ACCESSIBILITY_ATTRIBUTES:
1246 const Property::Map* map = value.GetMap();
1247 if( map && !map->Empty() )
1249 controlImpl.mImpl->mAccessibilityAttributes = *map;
1254 case Toolkit::DevelControl::Property::ACCESSIBILITY_ANIMATED:
1257 if( value.Get( animated ) )
1259 controlImpl.mImpl->mAccessibilityAnimated = animated;
1267 Property::Value Control::Impl::GetProperty( BaseObject* object, Property::Index index )
1269 Property::Value value;
1271 Toolkit::Control control = Toolkit::Control::DownCast( BaseHandle( object ) );
1275 Control& controlImpl( GetImplementation( control ) );
1279 case Toolkit::Control::Property::STYLE_NAME:
1281 value = controlImpl.GetStyleName();
1285 case Toolkit::DevelControl::Property::STATE:
1287 value = controlImpl.mImpl->mState;
1291 case Toolkit::DevelControl::Property::SUB_STATE:
1293 value = controlImpl.mImpl->mSubStateName;
1297 case Toolkit::DevelControl::Property::LEFT_FOCUSABLE_ACTOR_ID:
1299 value = controlImpl.mImpl->mLeftFocusableActorId;
1303 case Toolkit::DevelControl::Property::RIGHT_FOCUSABLE_ACTOR_ID:
1305 value = controlImpl.mImpl->mRightFocusableActorId;
1309 case Toolkit::DevelControl::Property::ACCESSIBILITY_NAME:
1311 if (controlImpl.mImpl->mAccessibilityNameSet)
1313 value = controlImpl.mImpl->mAccessibilityName;
1318 case Toolkit::DevelControl::Property::ACCESSIBILITY_DESCRIPTION:
1320 if (controlImpl.mImpl->mAccessibilityDescriptionSet)
1322 value = controlImpl.mImpl->mAccessibilityDescription;
1327 case Toolkit::DevelControl::Property::ACCESSIBILITY_TRANSLATION_DOMAIN:
1329 if (controlImpl.mImpl->mAccessibilityTranslationDomainSet)
1331 value = controlImpl.mImpl->mAccessibilityTranslationDomain;
1336 case Toolkit::DevelControl::Property::ACCESSIBILITY_HIGHLIGHTABLE:
1338 if (controlImpl.mImpl->mAccessibilityHighlightableSet)
1340 value = controlImpl.mImpl->mAccessibilityHighlightable;
1345 case Toolkit::DevelControl::Property::ACCESSIBILITY_ROLE:
1347 value = Property::Value(controlImpl.mImpl->mAccessibilityRole);
1351 case Toolkit::DevelControl::Property::UP_FOCUSABLE_ACTOR_ID:
1353 value = controlImpl.mImpl->mUpFocusableActorId;
1357 case Toolkit::DevelControl::Property::DOWN_FOCUSABLE_ACTOR_ID:
1359 value = controlImpl.mImpl->mDownFocusableActorId;
1363 case Toolkit::Control::Property::KEY_INPUT_FOCUS:
1365 value = controlImpl.HasKeyInputFocus();
1369 case Toolkit::Control::Property::BACKGROUND:
1372 Toolkit::Visual::Base visual = controlImpl.mImpl->GetVisual( Toolkit::Control::Property::BACKGROUND );
1375 visual.CreatePropertyMap( map );
1382 case Toolkit::Control::Property::MARGIN:
1384 value = controlImpl.mImpl->GetMargin();
1388 case Toolkit::Control::Property::PADDING:
1390 value = controlImpl.mImpl->GetPadding();
1394 case Toolkit::DevelControl::Property::TOOLTIP:
1397 if( controlImpl.mImpl->mTooltip )
1399 controlImpl.mImpl->mTooltip->CreatePropertyMap( map );
1405 case Toolkit::DevelControl::Property::SHADOW:
1408 Toolkit::Visual::Base visual = controlImpl.mImpl->GetVisual( Toolkit::DevelControl::Property::SHADOW );
1411 visual.CreatePropertyMap( map );
1418 case Toolkit::DevelControl::Property::ACCESSIBILITY_ATTRIBUTES:
1420 value = controlImpl.mImpl->mAccessibilityAttributes;
1424 case Toolkit::DevelControl::Property::ACCESSIBILITY_ANIMATED:
1426 value = controlImpl.mImpl->mAccessibilityAnimated;
1435 void Control::Impl::RemoveAccessibilityAttribute( const std::string& key )
1437 Property::Value* val = mAccessibilityAttributes.Find( key );
1439 mAccessibilityAttributes[key] = Property::Value();
1442 void Control::Impl::ClearAccessibilityAttributes()
1444 mAccessibilityAttributes.Clear();
1447 void Control::Impl::SetAccessibilityReadingInfoType( const Dali::Accessibility::ReadingInfoTypes types )
1450 if ( types[ Dali::Accessibility::ReadingInfoType::NAME ] )
1452 value += READING_INFO_TYPE_NAME;
1454 if ( types[ Dali::Accessibility::ReadingInfoType::ROLE ] )
1456 if( !value.empty() )
1458 value += READING_INFO_TYPE_SEPARATOR;
1460 value += READING_INFO_TYPE_ROLE;
1462 if ( types[ Dali::Accessibility::ReadingInfoType::DESCRIPTION ] )
1464 if( !value.empty() )
1466 value += READING_INFO_TYPE_SEPARATOR;
1468 value += READING_INFO_TYPE_DESCRIPTION;
1470 if ( types[ Dali::Accessibility::ReadingInfoType::STATE ] )
1472 if( !value.empty() )
1474 value += READING_INFO_TYPE_SEPARATOR;
1476 value += READING_INFO_TYPE_STATE;
1478 AppendAccessibilityAttribute( READING_INFO_TYPE_ATTRIBUTE_NAME, value );
1481 Dali::Accessibility::ReadingInfoTypes Control::Impl::GetAccessibilityReadingInfoType() const
1484 auto place = mAccessibilityAttributes.Find( READING_INFO_TYPE_ATTRIBUTE_NAME );
1487 place->Get( value );
1490 if ( value.empty() )
1495 Dali::Accessibility::ReadingInfoTypes types;
1497 if ( value.find( READING_INFO_TYPE_NAME ) != std::string::npos )
1499 types[ Dali::Accessibility::ReadingInfoType::NAME ] = true;
1501 if ( value.find( READING_INFO_TYPE_ROLE ) != std::string::npos )
1503 types[ Dali::Accessibility::ReadingInfoType::ROLE ] = true;
1505 if ( value.find( READING_INFO_TYPE_DESCRIPTION ) != std::string::npos )
1507 types[ Dali::Accessibility::ReadingInfoType::DESCRIPTION ] = true;
1509 if ( value.find( READING_INFO_TYPE_STATE ) != std::string::npos )
1511 types[ Dali::Accessibility::ReadingInfoType::STATE ] = true;
1517 void Control::Impl::CopyInstancedProperties( RegisteredVisualContainer& visuals, Dictionary<Property::Map>& instancedProperties )
1519 for(RegisteredVisualContainer::Iterator iter = visuals.Begin(); iter!= visuals.End(); iter++)
1521 if( (*iter)->visual )
1523 Property::Map instanceMap;
1524 Toolkit::GetImplementation((*iter)->visual).CreateInstancePropertyMap(instanceMap);
1525 instancedProperties.Add( (*iter)->visual.GetName(), instanceMap );
1531 void Control::Impl::RemoveVisual( RegisteredVisualContainer& visuals, const std::string& visualName )
1533 Actor self( mControlImpl.Self() );
1535 for ( RegisteredVisualContainer::Iterator visualIter = visuals.Begin();
1536 visualIter != visuals.End(); ++visualIter )
1538 Toolkit::Visual::Base visual = (*visualIter)->visual;
1539 if( visual && visual.GetName() == visualName )
1541 Toolkit::GetImplementation(visual).SetOffScene( self );
1542 (*visualIter)->visual.Reset();
1543 visuals.Erase( visualIter );
1549 void Control::Impl::RemoveVisuals( RegisteredVisualContainer& visuals, DictionaryKeys& removeVisuals )
1551 Actor self( mControlImpl.Self() );
1552 for( DictionaryKeys::iterator iter = removeVisuals.begin(); iter != removeVisuals.end(); ++iter )
1554 const std::string visualName = *iter;
1555 RemoveVisual( visuals, visualName );
1559 void Control::Impl::RecreateChangedVisuals( Dictionary<Property::Map>& stateVisualsToChange,
1560 Dictionary<Property::Map>& instancedProperties )
1562 Dali::CustomActor handle( mControlImpl.GetOwner() );
1563 for( Dictionary<Property::Map>::iterator iter = stateVisualsToChange.Begin();
1564 iter != stateVisualsToChange.End(); ++iter )
1566 const std::string& visualName = (*iter).key;
1567 const Property::Map& toMap = (*iter).entry;
1569 Actor self = mControlImpl.Self();
1570 RegisteredVisualContainer::Iterator registeredVisualsiter;
1571 // Check if visual (visualName) is already registered, this is the current visual.
1572 if(FindVisual(visualName, mVisuals, registeredVisualsiter))
1574 Toolkit::Visual::Base& visual = (*registeredVisualsiter)->visual;
1577 // No longer required to know if the replaced visual's resources are ready
1578 StopObservingVisual(visual);
1580 // If control staged then visuals will be swapped once ready
1581 if(self.GetProperty<bool>(Actor::Property::CONNECTED_TO_SCENE))
1583 // Check if visual is currently in the process of being replaced ( is in removal container )
1584 RegisteredVisualContainer::Iterator visualQueuedForRemoval;
1585 if(FindVisual(visualName, mRemoveVisuals, visualQueuedForRemoval))
1587 // Visual with same visual name is already in removal container so current visual pending
1588 // Only the the last requested visual will be displayed so remove current visual which is staged but not ready.
1589 Toolkit::GetImplementation(visual).SetOffScene(self);
1590 (*registeredVisualsiter)->visual.Reset();
1591 mVisuals.Erase(registeredVisualsiter);
1595 // current visual not already in removal container so add now.
1596 DALI_LOG_INFO(gLogFilter, Debug::Verbose, "RegisterVisual Move current registered visual to removal Queue: %s \n", visualName.c_str());
1597 MoveVisual(registeredVisualsiter, mVisuals, mRemoveVisuals);
1602 // Control not staged or visual disabled so can just erase from registered visuals and new visual will be added later.
1603 (*registeredVisualsiter)->visual.Reset();
1604 mVisuals.Erase(registeredVisualsiter);
1608 const Property::Map* instancedMap = instancedProperties.FindConst(visualName);
1609 Style::ApplyVisual(handle, visualName, toMap, instancedMap);
1614 void Control::Impl::ReplaceStateVisualsAndProperties( const StylePtr oldState, const StylePtr newState, const std::string& subState )
1616 // Collect all old visual names
1617 DictionaryKeys stateVisualsToRemove;
1620 oldState->visuals.GetKeys( stateVisualsToRemove );
1621 if( ! subState.empty() )
1623 const StylePtr* oldSubState = oldState->subStates.FindConst(subState);
1626 DictionaryKeys subStateVisualsToRemove;
1627 (*oldSubState)->visuals.GetKeys( subStateVisualsToRemove );
1628 Merge( stateVisualsToRemove, subStateVisualsToRemove );
1633 // Collect all new visual properties
1634 Dictionary<Property::Map> stateVisualsToAdd;
1637 stateVisualsToAdd = newState->visuals;
1638 if( ! subState.empty() )
1640 const StylePtr* newSubState = newState->subStates.FindConst(subState);
1643 stateVisualsToAdd.Merge( (*newSubState)->visuals );
1648 // If a name is in both add/remove, move it to change list.
1649 Dictionary<Property::Map> stateVisualsToChange;
1650 FindChangableVisuals( stateVisualsToAdd, stateVisualsToChange, stateVisualsToRemove);
1652 // Copy instanced properties (e.g. text label) of current visuals
1653 Dictionary<Property::Map> instancedProperties;
1654 CopyInstancedProperties( mVisuals, instancedProperties );
1656 // For each visual in remove list, remove from mVisuals
1657 RemoveVisuals( mVisuals, stateVisualsToRemove );
1659 // For each visual in add list, create and add to mVisuals
1660 Dali::CustomActor handle( mControlImpl.GetOwner() );
1661 Style::ApplyVisuals( handle, stateVisualsToAdd, instancedProperties );
1663 // For each visual in change list, if it requires a new visual,
1664 // remove old visual, create and add to mVisuals
1665 RecreateChangedVisuals( stateVisualsToChange, instancedProperties );
1668 void Control::Impl::SetState( DevelControl::State newState, bool withTransitions )
1670 DevelControl::State oldState = mState;
1671 Dali::CustomActor handle( mControlImpl.GetOwner() );
1672 DALI_LOG_INFO(gLogFilter, Debug::Concise, "Control::Impl::SetState: %s\n",
1673 (mState == DevelControl::NORMAL ? "NORMAL" :(
1674 mState == DevelControl::FOCUSED ?"FOCUSED" : (
1675 mState == DevelControl::DISABLED?"DISABLED":"NONE" ))));
1677 if( mState != newState )
1679 // If mState was Disabled, and new state is Focused, should probably
1680 // store that fact, e.g. in another property that FocusManager can access.
1683 // Trigger state change and transitions
1684 // Apply new style, if stylemanager is available
1685 Toolkit::StyleManager styleManager = Toolkit::StyleManager::Get();
1688 const StylePtr stylePtr = GetImpl( styleManager ).GetRecordedStyle( Toolkit::Control( mControlImpl.GetOwner() ) );
1692 std::string oldStateName = Scripting::GetEnumerationName< Toolkit::DevelControl::State >( oldState, ControlStateTable, ControlStateTableCount );
1693 std::string newStateName = Scripting::GetEnumerationName< Toolkit::DevelControl::State >( newState, ControlStateTable, ControlStateTableCount );
1695 const StylePtr* newStateStyle = stylePtr->subStates.Find( newStateName );
1696 const StylePtr* oldStateStyle = stylePtr->subStates.Find( oldStateName );
1697 if( oldStateStyle && newStateStyle )
1699 // Only change if both state styles exist
1700 ReplaceStateVisualsAndProperties( *oldStateStyle, *newStateStyle, mSubStateName );
1707 void Control::Impl::SetSubState( const std::string& subStateName, bool withTransitions )
1709 if( mSubStateName != subStateName )
1711 // Get existing sub-state visuals, and unregister them
1712 Dali::CustomActor handle( mControlImpl.GetOwner() );
1714 Toolkit::StyleManager styleManager = Toolkit::StyleManager::Get();
1717 const StylePtr stylePtr = GetImpl( styleManager ).GetRecordedStyle( Toolkit::Control( mControlImpl.GetOwner() ) );
1721 std::string stateName = Scripting::GetEnumerationName< Toolkit::DevelControl::State >( mState, ControlStateTable, ControlStateTableCount );
1723 const StylePtr* state = stylePtr->subStates.Find( stateName );
1726 StylePtr stateStyle(*state);
1728 const StylePtr* newStateStyle = stateStyle->subStates.Find( subStateName );
1729 const StylePtr* oldStateStyle = stateStyle->subStates.Find( mSubStateName );
1730 if( oldStateStyle && newStateStyle )
1733 ReplaceStateVisualsAndProperties( *oldStateStyle, *newStateStyle, empty );
1739 mSubStateName = subStateName;
1743 void Control::Impl::OnSceneDisconnection()
1745 Actor self = mControlImpl.Self();
1747 // Any visuals set for replacement but not yet ready should still be registered.
1748 // Reason: If a request was made to register a new visual but the control removed from scene before visual was ready
1749 // then when this control appears back on stage it should use that new visual.
1751 // Iterate through all registered visuals and set off scene
1752 SetVisualsOffScene( mVisuals, self );
1754 // Visuals pending replacement can now be taken out of the removal list and set off scene
1755 // Iterate through all replacement visuals and add to a move queue then set off scene
1756 for( auto removalIter = mRemoveVisuals.Begin(), end = mRemoveVisuals.End(); removalIter != end; removalIter++ )
1758 Toolkit::GetImplementation((*removalIter)->visual).SetOffScene( self );
1761 for( auto replacedIter = mVisuals.Begin(), end = mVisuals.End(); replacedIter != end; replacedIter++ )
1763 (*replacedIter)->pending = false;
1766 mRemoveVisuals.Clear();
1769 void Control::Impl::SetMargin( Extents margin )
1771 mControlImpl.mImpl->mMargin = margin;
1773 // Trigger a size negotiation request that may be needed when setting a margin.
1774 mControlImpl.RelayoutRequest();
1777 Extents Control::Impl::GetMargin() const
1779 return mControlImpl.mImpl->mMargin;
1782 void Control::Impl::SetPadding( Extents padding )
1784 mControlImpl.mImpl->mPadding = padding;
1786 // Trigger a size negotiation request that may be needed when setting a padding.
1787 mControlImpl.RelayoutRequest();
1790 Extents Control::Impl::GetPadding() const
1792 return mControlImpl.mImpl->mPadding;
1795 void Control::Impl::SetInputMethodContext( InputMethodContext& inputMethodContext )
1797 mInputMethodContext = inputMethodContext;
1800 bool Control::Impl::FilterKeyEvent( const KeyEvent& event )
1802 bool consumed ( false );
1804 if ( mInputMethodContext )
1806 consumed = mInputMethodContext.FilterEventKey( event );
1811 DevelControl::VisualEventSignalType& Control::Impl::VisualEventSignal()
1813 return mVisualEventSignal;
1816 void Control::Impl::SetShadow( const Property::Map& map )
1818 Toolkit::Visual::Base visual = Toolkit::VisualFactory::Get().CreateVisual( map );
1819 visual.SetName("shadow");
1823 mControlImpl.mImpl->RegisterVisual( Toolkit::DevelControl::Property::SHADOW, visual, DepthIndex::BACKGROUND_EFFECT );
1825 mControlImpl.RelayoutRequest();
1829 void Control::Impl::ClearShadow()
1831 mControlImpl.mImpl->UnregisterVisual( Toolkit::DevelControl::Property::SHADOW );
1833 // Trigger a size negotiation request that may be needed when unregistering a visual.
1834 mControlImpl.RelayoutRequest();
1837 Dali::Property Control::Impl::GetVisualProperty(Dali::Property::Index index, Dali::Property::Key visualPropertyKey)
1839 Toolkit::Visual::Base visual = GetVisualByIndex(mVisuals, index);
1842 Internal::Visual::Base& visualImpl = Toolkit::GetImplementation(visual);
1843 return visualImpl.GetPropertyObject(visualPropertyKey);
1847 return Dali::Property(handle, Property::INVALID_INDEX);
1850 void Control::Impl::EmitResourceReadySignal()
1852 if(!mIsEmittingResourceReadySignal)
1854 // Guard against calls to emit the signal during the callback
1855 mIsEmittingResourceReadySignal = true;
1857 // If the signal handler changes visual, it may become ready during this call & therefore this method will
1858 // get called again recursively. If so, mNeedToEmitResourceReady is set below, and we act on it after that secondary
1859 // invocation has completed by notifying in an Idle callback to prevent further recursion.
1860 Dali::Toolkit::Control handle(mControlImpl.GetOwner());
1861 mResourceReadySignal.Emit(handle);
1863 if(mNeedToEmitResourceReady)
1865 // Add idler to emit the signal again
1868 // The callback manager takes the ownership of the callback object.
1869 mIdleCallback = MakeCallback( this, &Control::Impl::OnIdleCallback);
1870 Adaptor::Get().AddIdle(mIdleCallback, false);
1874 mIsEmittingResourceReadySignal = false;
1878 mNeedToEmitResourceReady = true;
1882 void Control::Impl::OnIdleCallback()
1884 if(mNeedToEmitResourceReady)
1887 mNeedToEmitResourceReady = false;
1889 // A visual is ready so control may need relayouting if staged
1890 if(mControlImpl.Self().GetProperty<bool>(Actor::Property::CONNECTED_TO_SCENE))
1892 mControlImpl.RelayoutRequest();
1895 EmitResourceReadySignal();
1898 // Set the pointer to null as the callback manager deletes the callback after execute it.
1899 mIdleCallback = nullptr;
1902 Dali::Accessibility::Accessible *Control::Impl::GetAccessibilityObject()
1904 if( !accessibilityObject )
1905 accessibilityObject = accessibilityConstructor( mControlImpl.Self() );
1906 return accessibilityObject.get();
1909 Dali::Accessibility::Accessible *Control::Impl::GetAccessibilityObject(Dali::Actor actor)
1913 auto q = Dali::Toolkit::Control::DownCast( actor );
1916 auto q2 = static_cast< Internal::Control* >( &q.GetImplementation() );
1917 return q2->mImpl->GetAccessibilityObject();
1923 Control::Impl::AccessibleImpl::AccessibleImpl(Dali::Actor self, Dali::Accessibility::Role role, bool modal)
1924 : self(self), modal(modal)
1926 auto control = Dali::Toolkit::Control::DownCast(self);
1928 Internal::Control& internalControl = Toolkit::Internal::GetImplementation( control );
1929 Internal::Control::Impl& controlImpl = Internal::Control::Impl::Get( internalControl );
1930 if( controlImpl.mAccessibilityRole == Dali::Accessibility::Role::UNKNOWN )
1931 controlImpl.mAccessibilityRole = role;
1933 self.PropertySetSignal().Connect(&controlImpl, [this, &controlImpl](Dali::Handle &handle, Dali::Property::Index index, Dali::Property::Value value)
1935 if (this->self != Dali::Accessibility::Accessible::GetCurrentlyHighlightedActor())
1940 if (index == DevelControl::Property::ACCESSIBILITY_NAME
1941 || (index == GetNamePropertyIndex() && !controlImpl.mAccessibilityNameSet))
1943 if (controlImpl.mAccessibilityGetNameSignal.Empty())
1945 Emit(Dali::Accessibility::ObjectPropertyChangeEvent::NAME);
1949 if (index == DevelControl::Property::ACCESSIBILITY_DESCRIPTION
1950 || (index == GetDescriptionPropertyIndex() && !controlImpl.mAccessibilityDescriptionSet))
1952 if (controlImpl.mAccessibilityGetDescriptionSignal.Empty())
1954 Emit(Dali::Accessibility::ObjectPropertyChangeEvent::DESCRIPTION);
1960 std::string Control::Impl::AccessibleImpl::GetName()
1962 auto control = Dali::Toolkit::Control::DownCast(self);
1964 Internal::Control& internalControl = Toolkit::Internal::GetImplementation( control );
1965 Internal::Control::Impl& controlImpl = Internal::Control::Impl::Get( internalControl );
1967 if (!controlImpl.mAccessibilityGetNameSignal.Empty()) {
1969 controlImpl.mAccessibilityGetNameSignal.Emit(ret);
1973 if (controlImpl.mAccessibilityNameSet)
1974 return controlImpl.mAccessibilityName;
1976 if (auto raw = GetNameRaw(); !raw.empty())
1979 return self.GetProperty< std::string >( Actor::Property::NAME );
1982 std::string Control::Impl::AccessibleImpl::GetNameRaw()
1987 std::string Control::Impl::AccessibleImpl::GetDescription()
1989 auto control = Dali::Toolkit::Control::DownCast(self);
1991 Internal::Control& internalControl = Toolkit::Internal::GetImplementation( control );
1992 Internal::Control::Impl& controlImpl = Internal::Control::Impl::Get( internalControl );
1994 if (!controlImpl.mAccessibilityGetDescriptionSignal.Empty()) {
1996 controlImpl.mAccessibilityGetDescriptionSignal.Emit(ret);
2000 if (controlImpl.mAccessibilityDescriptionSet)
2001 return controlImpl.mAccessibilityDescription;
2003 return GetDescriptionRaw();
2006 std::string Control::Impl::AccessibleImpl::GetDescriptionRaw()
2011 Dali::Accessibility::Accessible* Control::Impl::AccessibleImpl::GetParent()
2013 return Dali::Accessibility::Accessible::Get( self.GetParent() );
2016 size_t Control::Impl::AccessibleImpl::GetChildCount()
2018 return self.GetChildCount();
2021 Dali::Accessibility::Accessible* Control::Impl::AccessibleImpl::GetChildAtIndex( size_t index )
2023 return Dali::Accessibility::Accessible::Get( self.GetChildAt( static_cast< unsigned int >( index ) ) );
2026 size_t Control::Impl::AccessibleImpl::GetIndexInParent()
2029 auto parent = s.GetParent();
2030 DALI_ASSERT_ALWAYS( parent && "can't call GetIndexInParent on object without parent" );
2031 auto count = parent.GetChildCount();
2032 for( auto i = 0u; i < count; ++i )
2034 auto c = parent.GetChildAt( i );
2038 DALI_ASSERT_ALWAYS( false && "object isn't child of it's parent" );
2039 return static_cast<size_t>(-1);
2042 Dali::Accessibility::Role Control::Impl::AccessibleImpl::GetRole()
2044 return self.GetProperty<Dali::Accessibility::Role>( Toolkit::DevelControl::Property::ACCESSIBILITY_ROLE );
2047 Dali::Accessibility::States Control::Impl::AccessibleImpl::CalculateStates()
2049 Dali::Accessibility::States s;
2050 s[Dali::Accessibility::State::FOCUSABLE] = self.GetProperty< bool >( Actor::Property::KEYBOARD_FOCUSABLE );
2051 s[Dali::Accessibility::State::FOCUSED] = Toolkit::KeyboardFocusManager::Get().GetCurrentFocusActor() == self;
2052 if(self.GetProperty( Toolkit::DevelControl::Property::ACCESSIBILITY_HIGHLIGHTABLE ).GetType() == Property::NONE )
2053 s[Dali::Accessibility::State::HIGHLIGHTABLE] = false;
2055 s[Dali::Accessibility::State::HIGHLIGHTABLE] = self.GetProperty( Toolkit::DevelControl::Property::ACCESSIBILITY_HIGHLIGHTABLE ).Get< bool >();
2056 s[Dali::Accessibility::State::HIGHLIGHTED] = GetCurrentlyHighlightedActor() == self;
2057 s[Dali::Accessibility::State::ENABLED] = true;
2058 s[Dali::Accessibility::State::SENSITIVE] = true;
2059 s[Dali::Accessibility::State::ANIMATED] = self.GetProperty( Toolkit::DevelControl::Property::ACCESSIBILITY_ANIMATED ).Get< bool >();
2060 s[Dali::Accessibility::State::VISIBLE] = true;
2063 s[Dali::Accessibility::State::MODAL] = true;
2065 s[Dali::Accessibility::State::SHOWING] = !self.GetProperty( Dali::DevelActor::Property::CULLED ).Get< bool >()
2066 && self.GetCurrentProperty< bool >( Actor::Property::VISIBLE );
2068 s[Dali::Accessibility::State::DEFUNCT] = !self.GetProperty( Dali::DevelActor::Property::CONNECTED_TO_SCENE ).Get< bool >();
2072 Dali::Accessibility::States Control::Impl::AccessibleImpl::GetStates()
2074 return CalculateStates();
2077 Dali::Accessibility::Attributes Control::Impl::AccessibleImpl::GetAttributes()
2079 std::unordered_map< std::string, std::string > attribute_map;
2080 auto q = Dali::Toolkit::Control::DownCast( self );
2082 q.GetProperty( Dali::Toolkit::DevelControl::Property::ACCESSIBILITY_ATTRIBUTES );
2083 auto z = w.GetMap();
2087 auto map_size = z->Count();
2089 for( unsigned int i = 0; i < map_size; i++ )
2091 auto map_key = z->GetKeyAt( i );
2092 if( map_key.type == Property::Key::STRING )
2094 std::string map_value;
2095 if( z->GetValue( i ).Get( map_value ) )
2097 attribute_map.emplace( std::move( map_key.stringKey ),
2098 std::move( map_value ) );
2104 return attribute_map;
2107 Dali::Accessibility::ComponentLayer Control::Impl::AccessibleImpl::GetLayer()
2109 return Dali::Accessibility::ComponentLayer::WINDOW;
2112 Dali::Rect<> Control::Impl::AccessibleImpl::GetExtents( Dali::Accessibility::CoordType ctype )
2114 Vector2 screenPosition =
2115 self.GetProperty( Dali::DevelActor::Property::SCREEN_POSITION )
2117 auto size = self.GetCurrentProperty< Vector3 >( Actor::Property::SIZE ) * self.GetCurrentProperty< Vector3 >( Actor::Property::WORLD_SCALE );
2118 bool positionUsesAnchorPoint =
2119 self.GetProperty( Dali::DevelActor::Property::POSITION_USES_ANCHOR_POINT )
2121 Vector3 anchorPointOffSet =
2122 size * ( positionUsesAnchorPoint ? self.GetCurrentProperty< Vector3 >( Actor::Property::ANCHOR_POINT )
2123 : AnchorPoint::TOP_LEFT );
2124 Vector2 position = Vector2( screenPosition.x - anchorPointOffSet.x,
2125 screenPosition.y - anchorPointOffSet.y );
2127 return { position.x, position.y, size.x, size.y };
2130 int16_t Control::Impl::AccessibleImpl::GetMdiZOrder() { return 0; }
2131 double Control::Impl::AccessibleImpl::GetAlpha() { return 0; }
2133 bool Control::Impl::AccessibleImpl::GrabFocus()
2135 return Toolkit::KeyboardFocusManager::Get().SetCurrentFocusActor( self );
2138 const char* const FOCUS_BORDER_IMAGE_PATH = DALI_IMAGE_DIR "keyboard_focus.9.png";
2140 static Dali::Actor CreateHighlightIndicatorActor()
2142 // Create the default if it hasn't been set and one that's shared by all the
2143 // keyboard focusable actors const char* const FOCUS_BORDER_IMAGE_PATH =
2144 // DALI_IMAGE_DIR "keyboard_focus.9.png";
2145 auto actor = Toolkit::ImageView::New( FOCUS_BORDER_IMAGE_PATH );
2146 actor.SetResizePolicy( ResizePolicy::FILL_TO_PARENT, Dimension::ALL_DIMENSIONS );
2147 DevelControl::AppendAccessibilityAttribute( actor, "highlight", "" );
2148 actor.SetProperty( Toolkit::DevelControl::Property::ACCESSIBILITY_ANIMATED, true);
2149 actor.SetProperty( Toolkit::DevelControl::Property::ACCESSIBILITY_HIGHLIGHTABLE, false );
2154 bool Control::Impl::AccessibleImpl::GrabHighlight()
2156 auto old = GetCurrentlyHighlightedActor();
2158 if( !Dali::Accessibility::IsUp() )
2164 auto c = dynamic_cast< Dali::Accessibility::Component* >( GetAccessibilityObject( old ) );
2166 c->ClearHighlight();
2168 auto highlight = GetHighlightActor();
2171 highlight = CreateHighlightIndicatorActor();
2172 SetHighlightActor( highlight );
2174 highlight.SetProperty( Actor::Property::PARENT_ORIGIN, ParentOrigin::CENTER );
2175 highlight.SetProperty( Actor::Property::ANCHOR_POINT, AnchorPoint::CENTER );
2176 highlight.SetProperty( Actor::Property::POSITION_Z, 1.0f );
2177 highlight.SetProperty( Actor::Property::POSITION, Vector2( 0.0f, 0.0f ));
2179 EnsureSelfVisible();
2180 self.Add( highlight );
2181 SetCurrentlyHighlightedActor( self );
2182 EmitHighlighted( true );
2189 bool Control::Impl::AccessibleImpl::ClearHighlight()
2191 if( !Dali::Accessibility::IsUp() )
2193 if( GetCurrentlyHighlightedActor() == self )
2195 self.Remove( GetHighlightActor() );
2196 SetCurrentlyHighlightedActor( {} );
2197 EmitHighlighted( false );
2203 std::string Control::Impl::AccessibleImpl::GetActionName( size_t index )
2205 if ( index >= GetActionCount() ) return "";
2206 Dali::TypeInfo type;
2207 self.GetTypeInfo( type );
2208 DALI_ASSERT_ALWAYS( type && "no TypeInfo object" );
2209 return type.GetActionName( index );
2211 std::string Control::Impl::AccessibleImpl::GetLocalizedActionName( size_t index )
2213 // TODO: add localization
2214 return GetActionName( index );
2216 std::string Control::Impl::AccessibleImpl::GetActionDescription( size_t index )
2220 size_t Control::Impl::AccessibleImpl::GetActionCount()
2222 Dali::TypeInfo type;
2223 self.GetTypeInfo( type );
2224 DALI_ASSERT_ALWAYS( type && "no TypeInfo object" );
2225 return type.GetActionCount();
2227 std::string Control::Impl::AccessibleImpl::GetActionKeyBinding( size_t index )
2231 bool Control::Impl::AccessibleImpl::DoAction( size_t index )
2233 std::string actionName = GetActionName( index );
2234 return self.DoAction( actionName, {} );
2236 bool Control::Impl::AccessibleImpl::DoAction(const std::string& name)
2238 return self.DoAction( name, {} );
2241 bool Control::Impl::AccessibleImpl::DoGesture(const Dali::Accessibility::GestureInfo &gestureInfo)
2243 auto control = Dali::Toolkit::Control::DownCast(self);
2245 Internal::Control& internalControl = Toolkit::Internal::GetImplementation( control );
2246 Internal::Control::Impl& controlImpl = Internal::Control::Impl::Get( internalControl );
2248 if (!controlImpl.mAccessibilityDoGestureSignal.Empty()) {
2249 auto ret = std::make_pair(gestureInfo, false);
2250 controlImpl.mAccessibilityDoGestureSignal.Emit(ret);
2257 std::vector<Dali::Accessibility::Relation> Control::Impl::AccessibleImpl::GetRelationSet()
2259 auto control = Dali::Toolkit::Control::DownCast(self);
2261 Internal::Control& internalControl = Toolkit::Internal::GetImplementation( control );
2262 Internal::Control::Impl& controlImpl = Internal::Control::Impl::Get( internalControl );
2264 std::vector<Dali::Accessibility::Relation> ret;
2266 auto &v = controlImpl.mAccessibilityRelations;
2267 for (auto i = 0u; i < v.size(); ++i)
2272 ret.emplace_back( Accessibility::Relation{ static_cast<Accessibility::RelationType>(i), v[i] } );
2278 void Control::Impl::AccessibleImpl::EnsureChildVisible(Actor child)
2282 void Control::Impl::AccessibleImpl::EnsureSelfVisible()
2284 auto parent = dynamic_cast<Control::Impl::AccessibleImpl*>(GetParent());
2287 parent->EnsureChildVisible(self);
2291 Property::Index Control::Impl::AccessibleImpl::GetNamePropertyIndex()
2293 return Actor::Property::NAME;
2296 Property::Index Control::Impl::AccessibleImpl::GetDescriptionPropertyIndex()
2298 return Property::INVALID_INDEX;
2301 void Control::Impl::PositionOrSizeChangedCallback( PropertyNotification &p )
2303 auto self = Dali::Actor::DownCast(p.GetTarget());
2304 if (Dali::Accessibility::IsUp() && !self.GetProperty( Toolkit::DevelControl::Property::ACCESSIBILITY_ANIMATED ).Get< bool >())
2306 auto extents = DevelActor::CalculateScreenExtents( self );
2307 Dali::Accessibility::Accessible::Get( self )->EmitBoundsChanged( extents );
2311 void Control::Impl::CulledChangedCallback( PropertyNotification &p)
2313 if (Dali::Accessibility::IsUp())
2315 auto self = Dali::Actor::DownCast(p.GetTarget());
2316 Dali::Accessibility::Accessible::Get(self)->EmitShowing( !self.GetProperty( DevelActor::Property::CULLED ).Get<bool>() );
2320 void Control::Impl::AccessibilityRegister()
2322 if (!accessibilityNotificationSet)
2324 accessibilityNotificationPosition = mControlImpl.Self().AddPropertyNotification( Actor::Property::POSITION, StepCondition( 0.01f ) );
2325 accessibilityNotificationPosition.SetNotifyMode( PropertyNotification::NOTIFY_ON_CHANGED );
2326 accessibilityNotificationPosition.NotifySignal().Connect( &Control::Impl::PositionOrSizeChangedCallback );
2328 accessibilityNotificationSize = mControlImpl.Self().AddPropertyNotification( Actor::Property::SIZE, StepCondition( 0.01f ) );
2329 accessibilityNotificationSize.SetNotifyMode( PropertyNotification::NOTIFY_ON_CHANGED );
2330 accessibilityNotificationSize.NotifySignal().Connect( &Control::Impl::PositionOrSizeChangedCallback );
2332 accessibilityNotificationCulled = mControlImpl.Self().AddPropertyNotification( DevelActor::Property::CULLED, LessThanCondition( 0.5f ) );
2333 accessibilityNotificationCulled.SetNotifyMode( PropertyNotification::NOTIFY_ON_CHANGED );
2334 accessibilityNotificationCulled.NotifySignal().Connect( &Control::Impl::CulledChangedCallback );
2336 accessibilityNotificationSet = true;
2340 void Control::Impl::AccessibilityDeregister()
2342 if (accessibilityNotificationSet)
2344 accessibilityNotificationPosition = {};
2345 accessibilityNotificationSize = {};
2346 accessibilityNotificationCulled = {};
2347 accessibilityNotificationSet = false;
2351 void Control::Impl::SetAutofillEnabled( bool autofillEnabled )
2353 mIsAutofillEnabled = autofillEnabled;
2356 bool Control::Impl::IsAutofillEnabled()
2358 return mIsAutofillEnabled;
2361 void Control::Impl::SetAutofillItemHandle( Dali::AutofillItem item )
2363 mAutofillItem = item;
2366 Dali::AutofillItem Control::Impl::GetAutofillItemHandle()
2368 return mAutofillItem;
2371 void Control::Impl::SetAutofillContainer( Toolkit::AutofillContainer container )
2373 mAutofillContainer = container;
2376 Toolkit::AutofillContainer Control::Impl::GetAutofillContainer()
2378 return mAutofillContainer;
2381 } // namespace Internal
2383 } // namespace Toolkit