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>
50 #include <dali-toolkit/devel-api/asset-manager/asset-manager.h>
54 const std::string READING_INFO_TYPE_NAME = "name";
55 const std::string READING_INFO_TYPE_ROLE = "role";
56 const std::string READING_INFO_TYPE_DESCRIPTION = "description";
57 const std::string READING_INFO_TYPE_STATE = "state";
58 const std::string READING_INFO_TYPE_ATTRIBUTE_NAME = "reading_info_type";
59 const std::string READING_INFO_TYPE_SEPARATOR = "|";
71 extern const Dali::Scripting::StringEnum ControlStateTable[];
72 extern const unsigned int ControlStateTableCount;
75 // Not static or anonymous - shared with other translation units
76 const Scripting::StringEnum ControlStateTable[] = {
77 { "NORMAL", Toolkit::DevelControl::NORMAL },
78 { "FOCUSED", Toolkit::DevelControl::FOCUSED },
79 { "DISABLED", Toolkit::DevelControl::DISABLED },
81 const unsigned int ControlStateTableCount = sizeof( ControlStateTable ) / sizeof( ControlStateTable[0] );
88 #if defined(DEBUG_ENABLED)
89 Debug::Filter* gLogFilter = Debug::Filter::New( Debug::NoLogging, false, "LOG_CONTROL_VISUALS");
94 void Remove( Dictionary<T>& keyValues, const std::string& name )
96 keyValues.Remove(name);
99 void Remove( DictionaryKeys& keys, const std::string& name )
101 DictionaryKeys::iterator iter = std::find( keys.begin(), keys.end(), name );
102 if( iter != keys.end())
109 * Finds visual in given array, returning true if found along with the iterator for that visual as a out parameter
111 bool FindVisual( Property::Index targetIndex, const RegisteredVisualContainer& visuals, RegisteredVisualContainer::Iterator& iter )
113 for ( iter = visuals.Begin(); iter != visuals.End(); iter++ )
115 if ( (*iter)->index == targetIndex )
124 * Finds visual in given array, returning true if found along with the iterator for that visual as a out parameter
126 bool FindVisual( std::string visualName, const RegisteredVisualContainer& visuals, RegisteredVisualContainer::Iterator& iter )
128 for ( iter = visuals.Begin(); iter != visuals.End(); iter++ )
130 Toolkit::Visual::Base visual = (*iter)->visual;
131 if( visual && visual.GetName() == visualName )
139 void FindChangableVisuals( Dictionary<Property::Map>& stateVisualsToAdd,
140 Dictionary<Property::Map>& stateVisualsToChange,
141 DictionaryKeys& stateVisualsToRemove)
143 DictionaryKeys copyOfStateVisualsToRemove = stateVisualsToRemove;
145 for( DictionaryKeys::iterator iter = copyOfStateVisualsToRemove.begin();
146 iter != copyOfStateVisualsToRemove.end(); ++iter )
148 const std::string& visualName = (*iter);
149 Property::Map* toMap = stateVisualsToAdd.Find( visualName );
152 stateVisualsToChange.Add( visualName, *toMap );
153 stateVisualsToAdd.Remove( visualName );
154 Remove( stateVisualsToRemove, visualName );
159 Toolkit::Visual::Base GetVisualByName(
160 const RegisteredVisualContainer& visuals,
161 const std::string& visualName )
163 Toolkit::Visual::Base visualHandle;
165 RegisteredVisualContainer::Iterator iter;
166 for ( iter = visuals.Begin(); iter != visuals.End(); iter++ )
168 Toolkit::Visual::Base visual = (*iter)->visual;
169 if( visual && visual.GetName() == visualName )
171 visualHandle = visual;
178 Toolkit::Visual::Base GetVisualByIndex(
179 const RegisteredVisualContainer& visuals,
180 Property::Index index)
182 Toolkit::Visual::Base visualHandle;
184 RegisteredVisualContainer::Iterator iter;
185 for(iter = visuals.Begin(); iter != visuals.End(); iter++)
187 if((*iter)->index == index)
189 visualHandle = (*iter)->visual;
197 * Move visual from source to destination container
199 void MoveVisual( RegisteredVisualContainer::Iterator sourceIter, RegisteredVisualContainer& source, RegisteredVisualContainer& destination )
201 Toolkit::Visual::Base visual = (*sourceIter)->visual;
204 RegisteredVisual* rv = source.Release( sourceIter );
205 destination.PushBack( rv );
210 * Performs actions as requested using the action name.
211 * @param[in] object The object on which to perform the action.
212 * @param[in] actionName The action to perform.
213 * @param[in] attributes The attributes with which to perfrom this action.
214 * @return true if action has been accepted by this control
216 const char* ACTION_ACCESSIBILITY_ACTIVATED = "accessibilityActivated";
217 const char* ACTION_ACCESSIBILITY_READING_CANCELLED = "ReadingCancelled";
218 const char* ACTION_ACCESSIBILITY_READING_PAUSED = "ReadingPaused";
219 const char* ACTION_ACCESSIBILITY_READING_RESUMED = "ReadingResumed";
220 const char* ACTION_ACCESSIBILITY_READING_SKIPPED = "ReadingSkipped";
221 const char* ACTION_ACCESSIBILITY_READING_STOPPED = "ReadingStopped";
223 static bool DoAction( BaseObject* object, const std::string& actionName, const Property::Map& attributes )
227 Dali::BaseHandle handle( object );
229 Toolkit::Control control = Toolkit::Control::DownCast( handle );
231 DALI_ASSERT_ALWAYS( control );
233 if( 0 == strcmp( actionName.c_str(), ACTION_ACCESSIBILITY_ACTIVATED ) ||
234 actionName == "activate" )
236 // if cast succeeds there is an implementation so no need to check
237 if( !DevelControl::AccessibilityActivateSignal( control ).Empty() )
238 DevelControl::AccessibilityActivateSignal( control ).Emit();
239 else ret = Internal::GetImplementation( control ).OnAccessibilityActivated();
241 else if( 0 == strcmp( actionName.c_str(), ACTION_ACCESSIBILITY_READING_SKIPPED ) )
243 // if cast succeeds there is an implementation so no need to check
244 if( !DevelControl::AccessibilityReadingSkippedSignal( control ).Empty() )
245 DevelControl::AccessibilityReadingSkippedSignal( control ).Emit();
247 else if( 0 == strcmp( actionName.c_str(), ACTION_ACCESSIBILITY_READING_PAUSED ) )
249 // if cast succeeds there is an implementation so no need to check
250 if( !DevelControl::AccessibilityReadingPausedSignal( control ).Empty() )
251 DevelControl::AccessibilityReadingPausedSignal( control ).Emit();
253 else if( 0 == strcmp( actionName.c_str(), ACTION_ACCESSIBILITY_READING_RESUMED ) )
255 // if cast succeeds there is an implementation so no need to check
256 if( !DevelControl::AccessibilityReadingResumedSignal( control ).Empty() )
257 DevelControl::AccessibilityReadingResumedSignal( control ).Emit();
259 else if( 0 == strcmp( actionName.c_str(), ACTION_ACCESSIBILITY_READING_CANCELLED ) )
261 // if cast succeeds there is an implementation so no need to check
262 if( !DevelControl::AccessibilityReadingCancelledSignal( control ).Empty() )
263 DevelControl::AccessibilityReadingCancelledSignal( control ).Emit();
265 else if( 0 == strcmp( actionName.c_str(), ACTION_ACCESSIBILITY_READING_STOPPED ) )
267 // if cast succeeds there is an implementation so no need to check
268 if(!DevelControl::AccessibilityReadingStoppedSignal( control ).Empty())
269 DevelControl::AccessibilityReadingStoppedSignal( control ).Emit();
278 * Connects a callback function with the object's signals.
279 * @param[in] object The object providing the signal.
280 * @param[in] tracker Used to disconnect the signal.
281 * @param[in] signalName The signal to connect to.
282 * @param[in] functor A newly allocated FunctorDelegate.
283 * @return True if the signal was connected.
284 * @post If a signal was connected, ownership of functor was passed to CallbackBase. Otherwise the caller is responsible for deleting the unused functor.
286 const char* SIGNAL_KEY_EVENT = "keyEvent";
287 const char* SIGNAL_KEY_INPUT_FOCUS_GAINED = "keyInputFocusGained";
288 const char* SIGNAL_KEY_INPUT_FOCUS_LOST = "keyInputFocusLost";
289 const char* SIGNAL_TAPPED = "tapped";
290 const char* SIGNAL_PANNED = "panned";
291 const char* SIGNAL_PINCHED = "pinched";
292 const char* SIGNAL_LONG_PRESSED = "longPressed";
293 const char* SIGNAL_GET_NAME = "getName";
294 const char* SIGNAL_GET_DESCRIPTION = "getDescription";
295 const char* SIGNAL_DO_GESTURE = "doGesture";
296 static bool DoConnectSignal( BaseObject* object, ConnectionTrackerInterface* tracker, const std::string& signalName, FunctorDelegate* functor )
298 Dali::BaseHandle handle( object );
300 bool connected( false );
301 Toolkit::Control control = Toolkit::Control::DownCast( handle );
304 Internal::Control& controlImpl( Internal::GetImplementation( control ) );
307 if ( 0 == strcmp( signalName.c_str(), SIGNAL_KEY_EVENT ) )
309 controlImpl.KeyEventSignal().Connect( tracker, functor );
311 else if( 0 == strcmp( signalName.c_str(), SIGNAL_KEY_INPUT_FOCUS_GAINED ) )
313 controlImpl.KeyInputFocusGainedSignal().Connect( tracker, functor );
315 else if( 0 == strcmp( signalName.c_str(), SIGNAL_KEY_INPUT_FOCUS_LOST ) )
317 controlImpl.KeyInputFocusLostSignal().Connect( tracker, functor );
319 else if( 0 == strcmp( signalName.c_str(), SIGNAL_TAPPED ) )
321 controlImpl.EnableGestureDetection( GestureType::TAP );
322 controlImpl.GetTapGestureDetector().DetectedSignal().Connect( tracker, functor );
324 else if( 0 == strcmp( signalName.c_str(), SIGNAL_PANNED ) )
326 controlImpl.EnableGestureDetection( GestureType::PAN );
327 controlImpl.GetPanGestureDetector().DetectedSignal().Connect( tracker, functor );
329 else if( 0 == strcmp( signalName.c_str(), SIGNAL_PINCHED ) )
331 controlImpl.EnableGestureDetection( GestureType::PINCH );
332 controlImpl.GetPinchGestureDetector().DetectedSignal().Connect( tracker, functor );
334 else if( 0 == strcmp( signalName.c_str(), SIGNAL_LONG_PRESSED ) )
336 controlImpl.EnableGestureDetection( GestureType::LONG_PRESS );
337 controlImpl.GetLongPressGestureDetector().DetectedSignal().Connect( tracker, functor );
339 else if( 0 == strcmp( signalName.c_str(), SIGNAL_GET_NAME ) )
341 DevelControl::AccessibilityGetNameSignal( control ).Connect( tracker, functor );
343 else if( 0 == strcmp( signalName.c_str(), SIGNAL_GET_DESCRIPTION ) )
345 DevelControl::AccessibilityGetDescriptionSignal( control ).Connect( tracker, functor );
347 else if( 0 == strcmp( signalName.c_str(), SIGNAL_DO_GESTURE ) )
349 DevelControl::AccessibilityDoGestureSignal( control ).Connect( tracker, functor );
357 * Creates control through type registry
361 return Internal::Control::New();
363 // Setup signals and actions using the type-registry.
364 DALI_TYPE_REGISTRATION_BEGIN( Control, CustomActor, Create );
366 // Note: Properties are registered separately below.
368 SignalConnectorType registerSignal1( typeRegistration, SIGNAL_KEY_EVENT, &DoConnectSignal );
369 SignalConnectorType registerSignal2( typeRegistration, SIGNAL_KEY_INPUT_FOCUS_GAINED, &DoConnectSignal );
370 SignalConnectorType registerSignal3( typeRegistration, SIGNAL_KEY_INPUT_FOCUS_LOST, &DoConnectSignal );
371 SignalConnectorType registerSignal4( typeRegistration, SIGNAL_TAPPED, &DoConnectSignal );
372 SignalConnectorType registerSignal5( typeRegistration, SIGNAL_PANNED, &DoConnectSignal );
373 SignalConnectorType registerSignal6( typeRegistration, SIGNAL_PINCHED, &DoConnectSignal );
374 SignalConnectorType registerSignal7( typeRegistration, SIGNAL_LONG_PRESSED, &DoConnectSignal );
375 SignalConnectorType registerSignal8( typeRegistration, SIGNAL_GET_NAME, &DoConnectSignal );
376 SignalConnectorType registerSignal9( typeRegistration, SIGNAL_GET_DESCRIPTION, &DoConnectSignal );
377 SignalConnectorType registerSignal10( typeRegistration, SIGNAL_DO_GESTURE, &DoConnectSignal );
379 TypeAction registerAction1( typeRegistration, "activate", &DoAction );
380 TypeAction registerAction2( typeRegistration, ACTION_ACCESSIBILITY_ACTIVATED, &DoAction );
381 TypeAction registerAction3( typeRegistration, ACTION_ACCESSIBILITY_READING_SKIPPED, &DoAction );
382 TypeAction registerAction4( typeRegistration, ACTION_ACCESSIBILITY_READING_CANCELLED, &DoAction );
383 TypeAction registerAction5( typeRegistration, ACTION_ACCESSIBILITY_READING_STOPPED, &DoAction );
384 TypeAction registerAction6( typeRegistration, ACTION_ACCESSIBILITY_READING_PAUSED, &DoAction );
385 TypeAction registerAction7( typeRegistration, ACTION_ACCESSIBILITY_READING_RESUMED, &DoAction );
387 DALI_TYPE_REGISTRATION_END()
390 * @brief Iterate through given container and setOffScene any visual found
392 * @param[in] container Container of visuals
393 * @param[in] parent Parent actor to remove visuals from
395 void SetVisualsOffScene( const RegisteredVisualContainer& container, Actor parent )
397 for( auto iter = container.Begin(), end = container.End() ; iter!= end; iter++)
399 if( (*iter)->visual )
401 DALI_LOG_INFO( gLogFilter, Debug::Verbose, "Control::SetOffScene Setting visual(%d) off stage\n", (*iter)->index );
402 Toolkit::GetImplementation((*iter)->visual).SetOffScene( parent );
407 } // unnamed namespace
410 // Properties registered without macro to use specific member variables.
411 const PropertyRegistration Control::Impl::PROPERTY_1( typeRegistration, "styleName", Toolkit::Control::Property::STYLE_NAME, Property::STRING, &Control::Impl::SetProperty, &Control::Impl::GetProperty );
412 const PropertyRegistration Control::Impl::PROPERTY_4( typeRegistration, "keyInputFocus", Toolkit::Control::Property::KEY_INPUT_FOCUS, Property::BOOLEAN, &Control::Impl::SetProperty, &Control::Impl::GetProperty );
413 const PropertyRegistration Control::Impl::PROPERTY_5( typeRegistration, "background", Toolkit::Control::Property::BACKGROUND, Property::MAP, &Control::Impl::SetProperty, &Control::Impl::GetProperty );
414 const PropertyRegistration Control::Impl::PROPERTY_6( typeRegistration, "margin", Toolkit::Control::Property::MARGIN, Property::EXTENTS, &Control::Impl::SetProperty, &Control::Impl::GetProperty );
415 const PropertyRegistration Control::Impl::PROPERTY_7( typeRegistration, "padding", Toolkit::Control::Property::PADDING, Property::EXTENTS, &Control::Impl::SetProperty, &Control::Impl::GetProperty );
416 const PropertyRegistration Control::Impl::PROPERTY_8( typeRegistration, "tooltip", Toolkit::DevelControl::Property::TOOLTIP, Property::MAP, &Control::Impl::SetProperty, &Control::Impl::GetProperty );
417 const PropertyRegistration Control::Impl::PROPERTY_9( typeRegistration, "state", Toolkit::DevelControl::Property::STATE, Property::STRING, &Control::Impl::SetProperty, &Control::Impl::GetProperty );
418 const PropertyRegistration Control::Impl::PROPERTY_10( typeRegistration, "subState", Toolkit::DevelControl::Property::SUB_STATE, Property::STRING, &Control::Impl::SetProperty, &Control::Impl::GetProperty );
419 const PropertyRegistration Control::Impl::PROPERTY_11( typeRegistration, "leftFocusableActorId", Toolkit::DevelControl::Property::LEFT_FOCUSABLE_ACTOR_ID, Property::INTEGER, &Control::Impl::SetProperty, &Control::Impl::GetProperty );
420 const PropertyRegistration Control::Impl::PROPERTY_12( typeRegistration, "rightFocusableActorId", Toolkit::DevelControl::Property::RIGHT_FOCUSABLE_ACTOR_ID,Property::INTEGER, &Control::Impl::SetProperty, &Control::Impl::GetProperty );
421 const PropertyRegistration Control::Impl::PROPERTY_13( typeRegistration, "upFocusableActorId", Toolkit::DevelControl::Property::UP_FOCUSABLE_ACTOR_ID, Property::INTEGER, &Control::Impl::SetProperty, &Control::Impl::GetProperty );
422 const PropertyRegistration Control::Impl::PROPERTY_14( typeRegistration, "downFocusableActorId", Toolkit::DevelControl::Property::DOWN_FOCUSABLE_ACTOR_ID, Property::INTEGER, &Control::Impl::SetProperty, &Control::Impl::GetProperty );
423 const PropertyRegistration Control::Impl::PROPERTY_15( typeRegistration, "shadow", Toolkit::DevelControl::Property::SHADOW, Property::MAP, &Control::Impl::SetProperty, &Control::Impl::GetProperty );
424 const PropertyRegistration Control::Impl::PROPERTY_16( typeRegistration, "accessibilityAttributes", Toolkit::DevelControl::Property::ACCESSIBILITY_ATTRIBUTES, Property::MAP, &Control::Impl::SetProperty, &Control::Impl::GetProperty );
425 const PropertyRegistration Control::Impl::PROPERTY_17( typeRegistration, "accessibilityName", Toolkit::DevelControl::Property::ACCESSIBILITY_NAME, Property::STRING, &Control::Impl::SetProperty, &Control::Impl::GetProperty );
426 const PropertyRegistration Control::Impl::PROPERTY_18( typeRegistration, "accessibilityDescription", Toolkit::DevelControl::Property::ACCESSIBILITY_DESCRIPTION, Property::STRING, &Control::Impl::SetProperty, &Control::Impl::GetProperty );
427 const PropertyRegistration Control::Impl::PROPERTY_19( typeRegistration, "accessibilityTranslationDomain", Toolkit::DevelControl::Property::ACCESSIBILITY_TRANSLATION_DOMAIN, Property::STRING, &Control::Impl::SetProperty, &Control::Impl::GetProperty );
428 const PropertyRegistration Control::Impl::PROPERTY_20( typeRegistration, "accessibilityRole", Toolkit::DevelControl::Property::ACCESSIBILITY_ROLE, Property::INTEGER, &Control::Impl::SetProperty, &Control::Impl::GetProperty );
429 const PropertyRegistration Control::Impl::PROPERTY_21( typeRegistration, "accessibilityHighlightable", Toolkit::DevelControl::Property::ACCESSIBILITY_HIGHLIGHTABLE, Property::BOOLEAN, &Control::Impl::SetProperty, &Control::Impl::GetProperty );
430 const PropertyRegistration Control::Impl::PROPERTY_22( typeRegistration, "accessibilityAnimated", Toolkit::DevelControl::Property::ACCESSIBILITY_ANIMATED, Property::BOOLEAN, &Control::Impl::SetProperty, &Control::Impl::GetProperty );
432 Control::Impl::Impl( Control& controlImpl )
433 : mControlImpl( controlImpl ),
434 mState( Toolkit::DevelControl::NORMAL ),
436 mLeftFocusableActorId( -1 ),
437 mRightFocusableActorId( -1 ),
438 mUpFocusableActorId( -1 ),
439 mDownFocusableActorId( -1 ),
441 mBackgroundColor(Color::TRANSPARENT),
442 mStartingPinchScale(nullptr),
443 mMargin( 0, 0, 0, 0 ),
444 mPadding( 0, 0, 0, 0 ),
446 mKeyInputFocusGainedSignal(),
447 mKeyInputFocusLostSignal(),
448 mResourceReadySignal(),
449 mVisualEventSignal(),
450 mAccessibilityGetNameSignal(),
451 mAccessibilityGetDescriptionSignal(),
452 mAccessibilityDoGestureSignal(),
453 mPinchGestureDetector(),
454 mPanGestureDetector(),
455 mTapGestureDetector(),
456 mLongPressGestureDetector(),
458 mInputMethodContext(),
459 mIdleCallback(nullptr),
460 mFlags( Control::ControlBehaviour( CONTROL_BEHAVIOUR_DEFAULT ) ),
461 mIsKeyboardNavigationSupported( false ),
462 mIsKeyboardFocusGroup( false ),
463 mIsEmittingResourceReadySignal(false),
464 mNeedToEmitResourceReady(false)
466 Dali::Accessibility::Accessible::RegisterControlAccessibilityGetter(
467 []( Dali::Actor actor ) -> Dali::Accessibility::Accessible* {
468 return Control::Impl::GetAccessibilityObject( actor );
471 accessibilityConstructor = []( Dali::Actor actor ) -> std::unique_ptr< Dali::Accessibility::Accessible > {
472 return std::unique_ptr< Dali::Accessibility::Accessible >( new AccessibleImpl( actor,
473 Dali::Accessibility::Role::UNKNOWN ) );
476 size_t len = static_cast<size_t>(Dali::Accessibility::RelationType::MAX_COUNT);
477 mAccessibilityRelations.reserve(len);
478 for (auto i = 0u; i < len; ++i)
480 mAccessibilityRelations.push_back({});
484 Control::Impl::~Impl()
486 for( auto&& iter : mVisuals )
488 StopObservingVisual( iter->visual );
491 for( auto&& iter : mRemoveVisuals )
493 StopObservingVisual( iter->visual );
496 AccessibilityDeregister();
497 // All gesture detectors will be destroyed so no need to disconnect.
498 delete mStartingPinchScale;
500 if(mIdleCallback && Adaptor::IsAvailable())
502 // Removes the callback from the callback manager in case the control is destroyed before the callback is executed.
503 Adaptor::Get().RemoveIdle(mIdleCallback);
507 Control::Impl& Control::Impl::Get( Internal::Control& internalControl )
509 return *internalControl.mImpl;
512 const Control::Impl& Control::Impl::Get( const Internal::Control& internalControl )
514 return *internalControl.mImpl;
517 // Gesture Detection Methods
518 void Control::Impl::PinchDetected(Actor actor, const PinchGesture& pinch)
520 mControlImpl.OnPinch(pinch);
523 void Control::Impl::PanDetected(Actor actor, const PanGesture& pan)
525 mControlImpl.OnPan(pan);
528 void Control::Impl::TapDetected(Actor actor, const TapGesture& tap)
530 mControlImpl.OnTap(tap);
533 void Control::Impl::LongPressDetected(Actor actor, const LongPressGesture& longPress)
535 mControlImpl.OnLongPress(longPress);
538 void Control::Impl::RegisterVisual( Property::Index index, Toolkit::Visual::Base& visual )
540 RegisterVisual( index, visual, VisualState::ENABLED, DepthIndexValue::NOT_SET );
543 void Control::Impl::RegisterVisual( Property::Index index, Toolkit::Visual::Base& visual, int depthIndex )
545 RegisterVisual( index, visual, VisualState::ENABLED, DepthIndexValue::SET, depthIndex );
548 void Control::Impl::RegisterVisual( Property::Index index, Toolkit::Visual::Base& visual, bool enabled )
550 RegisterVisual( index, visual, ( enabled ? VisualState::ENABLED : VisualState::DISABLED ), DepthIndexValue::NOT_SET );
553 void Control::Impl::RegisterVisual( Property::Index index, Toolkit::Visual::Base& visual, bool enabled, int depthIndex )
555 RegisterVisual( index, visual, ( enabled ? VisualState::ENABLED : VisualState::DISABLED ), DepthIndexValue::SET, depthIndex );
558 void Control::Impl::RegisterVisual( Property::Index index, Toolkit::Visual::Base& visual, VisualState::Type enabled, DepthIndexValue::Type depthIndexValueSet, int depthIndex )
560 DALI_LOG_INFO( gLogFilter, Debug::Concise, "RegisterVisual:%d \n", index );
562 bool visualReplaced ( false );
563 Actor self = mControlImpl.Self();
565 // Set the depth index, if not set by caller this will be either the current visual depth, max depth of all visuals
567 int requiredDepthIndex = visual.GetDepthIndex();
569 if( depthIndexValueSet == DepthIndexValue::SET )
571 requiredDepthIndex = depthIndex;
574 // Visual replacement, existing visual should only be removed from stage when replacement ready.
575 if( !mVisuals.Empty() )
577 RegisteredVisualContainer::Iterator registeredVisualsiter;
578 // Check if visual (index) is already registered, this is the current visual.
579 if( FindVisual( index, mVisuals, registeredVisualsiter ) )
581 Toolkit::Visual::Base& currentRegisteredVisual = (*registeredVisualsiter)->visual;
582 if( currentRegisteredVisual )
584 // Store current visual depth index as may need to set the replacement visual to same depth
585 const int currentDepthIndex = (*registeredVisualsiter)->visual.GetDepthIndex();
587 // No longer required to know if the replaced visual's resources are ready
588 StopObservingVisual( currentRegisteredVisual );
590 // If control staged and visual enabled then visuals will be swapped once ready
591 if( self.GetProperty< bool >( Actor::Property::CONNECTED_TO_SCENE ) && enabled )
593 // Check if visual is currently in the process of being replaced ( is in removal container )
594 RegisteredVisualContainer::Iterator visualQueuedForRemoval;
595 if ( FindVisual( index, mRemoveVisuals, visualQueuedForRemoval ) )
597 // Visual with same index is already in removal container so current visual pending
598 // Only the the last requested visual will be displayed so remove current visual which is staged but not ready.
599 Toolkit::GetImplementation( currentRegisteredVisual ).SetOffScene( self );
600 mVisuals.Erase( registeredVisualsiter );
604 // current visual not already in removal container so add now.
605 DALI_LOG_INFO( gLogFilter, Debug::Verbose, "RegisterVisual Move current registered visual to removal Queue: %d \n", index );
606 MoveVisual( registeredVisualsiter, mVisuals, mRemoveVisuals );
611 // Control not staged or visual disabled so can just erase from registered visuals and new visual will be added later.
612 mVisuals.Erase( registeredVisualsiter );
615 // 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
616 if( ( depthIndexValueSet == DepthIndexValue::NOT_SET ) &&
617 ( visual.GetDepthIndex() == 0 ) )
619 requiredDepthIndex = currentDepthIndex;
623 visualReplaced = true;
627 // If not set, set the name of the visual to the same name as the control's property.
628 // ( If the control has been type registered )
629 if( visual.GetName().empty() )
631 // returns empty string if index is not found as long as index is not -1
632 std::string visualName = self.GetPropertyName( index );
633 if( !visualName.empty() )
635 DALI_LOG_INFO( gLogFilter, Debug::Concise, "Setting visual name for property %d to %s\n",
636 index, visualName.c_str() );
637 visual.SetName( visualName );
641 if( !visualReplaced ) // New registration entry
643 // 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
644 if( ( depthIndexValueSet == DepthIndexValue::NOT_SET ) &&
645 ( mVisuals.Size() > 0 ) &&
646 ( visual.GetDepthIndex() == 0 ) )
648 int maxDepthIndex = std::numeric_limits< int >::min();
650 RegisteredVisualContainer::ConstIterator iter;
651 const RegisteredVisualContainer::ConstIterator endIter = mVisuals.End();
652 for ( iter = mVisuals.Begin(); iter != endIter; iter++ )
654 const int visualDepthIndex = (*iter)->visual.GetDepthIndex();
655 if ( visualDepthIndex > maxDepthIndex )
657 maxDepthIndex = visualDepthIndex;
660 ++maxDepthIndex; // Add one to the current maximum depth index so that our added visual appears on top
661 requiredDepthIndex = std::max( 0, maxDepthIndex ); // Start at zero if maxDepth index belongs to a background
667 // Set determined depth index
668 visual.SetDepthIndex( requiredDepthIndex );
670 // Monitor when the visual resources are ready
671 StartObservingVisual( visual );
673 DALI_LOG_INFO( gLogFilter, Debug::Concise, "New Visual registration index[%d] depth[%d]\n", index, requiredDepthIndex );
674 RegisteredVisual* newRegisteredVisual = new RegisteredVisual( index, visual,
675 ( enabled == VisualState::ENABLED ? true : false ),
676 ( visualReplaced && enabled ) ) ;
677 mVisuals.PushBack( newRegisteredVisual );
679 Internal::Visual::Base& visualImpl = Toolkit::GetImplementation( visual );
680 // Put on stage if enabled and the control is already on the stage
681 if( ( enabled == VisualState::ENABLED ) && self.GetProperty< bool >( Actor::Property::CONNECTED_TO_SCENE ) )
683 visualImpl.SetOnScene( self );
685 else if( visualImpl.IsResourceReady() ) // When not being staged, check if visual already 'ResourceReady' before it was Registered. ( Resource may have been loaded already )
687 ResourceReady( visualImpl );
692 DALI_LOG_INFO( gLogFilter, Debug::Verbose, "Control::RegisterVisual() Registered %s(%d), enabled:%s\n", visual.GetName().c_str(), index, enabled?"true":"false" );
695 void Control::Impl::UnregisterVisual( Property::Index index )
697 RegisteredVisualContainer::Iterator iter;
698 if ( FindVisual( index, mVisuals, iter ) )
700 // stop observing visual
701 StopObservingVisual( (*iter)->visual );
703 Actor self( mControlImpl.Self() );
704 Toolkit::GetImplementation((*iter)->visual).SetOffScene( self );
705 (*iter)->visual.Reset();
706 mVisuals.Erase( iter );
709 if( FindVisual( index, mRemoveVisuals, iter ) )
711 Actor self( mControlImpl.Self() );
712 Toolkit::GetImplementation( (*iter)->visual ).SetOffScene( self );
713 (*iter)->pending = false;
714 (*iter)->visual.Reset();
715 mRemoveVisuals.Erase( iter );
719 Toolkit::Visual::Base Control::Impl::GetVisual( Property::Index index ) const
721 RegisteredVisualContainer::Iterator iter;
722 if ( FindVisual( index, mVisuals, iter ) )
724 return (*iter)->visual;
727 return Toolkit::Visual::Base();
730 void Control::Impl::EnableVisual( Property::Index index, bool enable )
732 DALI_LOG_INFO( gLogFilter, Debug::General, "Control::EnableVisual(%d, %s)\n", index, enable?"T":"F");
734 RegisteredVisualContainer::Iterator iter;
735 if ( FindVisual( index, mVisuals, iter ) )
737 if ( (*iter)->enabled == enable )
739 DALI_LOG_INFO( gLogFilter, Debug::Verbose, "Control::EnableVisual Visual %s(%d) already %s\n", (*iter)->visual.GetName().c_str(), index, enable?"enabled":"disabled");
743 (*iter)->enabled = enable;
744 Actor parentActor = mControlImpl.Self();
745 if ( mControlImpl.Self().GetProperty< bool >( Actor::Property::CONNECTED_TO_SCENE ) ) // If control not on Scene then Visual will be added when SceneConnection is called.
749 DALI_LOG_INFO( gLogFilter, Debug::Verbose, "Control::EnableVisual Setting %s(%d) on stage \n", (*iter)->visual.GetName().c_str(), index );
750 Toolkit::GetImplementation((*iter)->visual).SetOnScene( parentActor );
754 DALI_LOG_INFO( gLogFilter, Debug::Verbose, "Control::EnableVisual Setting %s(%d) off stage \n", (*iter)->visual.GetName().c_str(), index );
755 Toolkit::GetImplementation((*iter)->visual).SetOffScene( parentActor ); // No need to call if control not staged.
761 DALI_LOG_WARNING( "Control::EnableVisual(%d, %s) FAILED - NO SUCH VISUAL\n", index, enable?"T":"F" );
765 bool Control::Impl::IsVisualEnabled( Property::Index index ) const
767 RegisteredVisualContainer::Iterator iter;
768 if ( FindVisual( index, mVisuals, iter ) )
770 return (*iter)->enabled;
775 void Control::Impl::StopObservingVisual( Toolkit::Visual::Base& visual )
777 Internal::Visual::Base& visualImpl = Toolkit::GetImplementation( visual );
779 // Stop observing the visual
780 visualImpl.RemoveEventObserver( *this );
783 void Control::Impl::StartObservingVisual( Toolkit::Visual::Base& visual)
785 Internal::Visual::Base& visualImpl = Toolkit::GetImplementation( visual );
787 // start observing the visual for events
788 visualImpl.AddEventObserver( *this );
791 // Called by a Visual when it's resource is ready
792 void Control::Impl::ResourceReady( Visual::Base& object)
794 DALI_LOG_INFO( gLogFilter, Debug::Verbose, "Control::Impl::ResourceReady() replacements pending[%d]\n", mRemoveVisuals.Count() );
796 Actor self = mControlImpl.Self();
798 // A resource is ready, find resource in the registered visuals container and get its index
799 for( auto registeredIter = mVisuals.Begin(), end = mVisuals.End(); registeredIter != end; ++registeredIter )
801 Internal::Visual::Base& registeredVisualImpl = Toolkit::GetImplementation( (*registeredIter)->visual );
803 if( &object == ®isteredVisualImpl )
805 RegisteredVisualContainer::Iterator visualToRemoveIter;
806 // Find visual with the same index in the removal container
807 // Set if off stage as it's replacement is now ready.
808 // Remove if from removal list as now removed from stage.
809 // Set Pending flag on the ready visual to false as now ready.
810 if( FindVisual( (*registeredIter)->index, mRemoveVisuals, visualToRemoveIter ) )
812 (*registeredIter)->pending = false;
813 Toolkit::GetImplementation( (*visualToRemoveIter)->visual ).SetOffScene( self );
814 mRemoveVisuals.Erase( visualToRemoveIter );
820 // A visual is ready so control may need relayouting if staged
821 if ( self.GetProperty< bool >( Actor::Property::CONNECTED_TO_SCENE ) )
823 mControlImpl.RelayoutRequest();
826 // Emit signal if all enabled visuals registered by the control are ready.
827 if( IsResourceReady() )
830 mNeedToEmitResourceReady = false;
832 EmitResourceReadySignal();
836 void Control::Impl::NotifyVisualEvent( Visual::Base& object, Property::Index signalId )
838 for( auto registeredIter = mVisuals.Begin(), end = mVisuals.End(); registeredIter != end; ++registeredIter )
840 Internal::Visual::Base& registeredVisualImpl = Toolkit::GetImplementation( (*registeredIter)->visual );
841 if( &object == ®isteredVisualImpl )
843 Dali::Toolkit::Control handle( mControlImpl.GetOwner() );
844 mVisualEventSignal.Emit( handle, (*registeredIter)->index, signalId );
850 bool Control::Impl::IsResourceReady() const
852 // Iterate through and check all the enabled visuals are ready
853 for( auto visualIter = mVisuals.Begin();
854 visualIter != mVisuals.End(); ++visualIter )
856 const Toolkit::Visual::Base visual = (*visualIter)->visual;
857 const Internal::Visual::Base& visualImpl = Toolkit::GetImplementation( visual );
859 // one of the enabled visuals is not ready
860 if( !visualImpl.IsResourceReady() && (*visualIter)->enabled )
868 Toolkit::Visual::ResourceStatus Control::Impl::GetVisualResourceStatus( Property::Index index ) const
870 RegisteredVisualContainer::Iterator iter;
871 if ( FindVisual( index, mVisuals, iter ) )
873 const Toolkit::Visual::Base visual = (*iter)->visual;
874 const Internal::Visual::Base& visualImpl = Toolkit::GetImplementation( visual );
875 return visualImpl.GetResourceStatus( );
878 return Toolkit::Visual::ResourceStatus::PREPARING;
883 void Control::Impl::AddTransitions( Dali::Animation& animation,
884 const Toolkit::TransitionData& handle,
885 bool createAnimation )
887 // Setup a Transition from TransitionData.
888 const Internal::TransitionData& transitionData = Toolkit::GetImplementation( handle );
889 TransitionData::Iterator end = transitionData.End();
890 for( TransitionData::Iterator iter = transitionData.Begin() ;
891 iter != end; ++iter )
893 TransitionData::Animator* animator = (*iter);
895 Toolkit::Visual::Base visual = GetVisualByName( mVisuals, animator->objectName );
899 #if defined(DEBUG_ENABLED)
900 Dali::TypeInfo typeInfo;
901 ControlWrapper* controlWrapperImpl = dynamic_cast<ControlWrapper*>(&mControlImpl);
902 if( controlWrapperImpl )
904 typeInfo = controlWrapperImpl->GetTypeInfo();
907 DALI_LOG_INFO( gLogFilter, Debug::Concise, "CreateTransition: Found %s visual for %s\n",
908 visual.GetName().c_str(), typeInfo?typeInfo.GetName().c_str():"Unknown" );
910 Internal::Visual::Base& visualImpl = Toolkit::GetImplementation( visual );
911 visualImpl.AnimateProperty( animation, *animator );
915 DALI_LOG_INFO( gLogFilter, Debug::Concise, "CreateTransition: Could not find visual. Trying actors");
916 // Otherwise, try any actor children of control (Including the control)
917 Actor child = mControlImpl.Self().FindChildByName( animator->objectName );
920 Property::Index propertyIndex = child.GetPropertyIndex( animator->propertyKey );
921 if( propertyIndex != Property::INVALID_INDEX )
923 if( animator->animate == false )
925 if( animator->targetValue.GetType() != Property::NONE )
927 child.SetProperty( propertyIndex, animator->targetValue );
930 else // animate the property
932 if( animator->initialValue.GetType() != Property::NONE )
934 child.SetProperty( propertyIndex, animator->initialValue );
937 if( createAnimation && !animation )
939 animation = Dali::Animation::New( 0.1f );
942 animation.AnimateTo( Property( child, propertyIndex ),
943 animator->targetValue,
944 animator->alphaFunction,
945 TimePeriod( animator->timePeriodDelay,
946 animator->timePeriodDuration ) );
954 Dali::Animation Control::Impl::CreateTransition( const Toolkit::TransitionData& transitionData )
956 Dali::Animation transition;
958 if( transitionData.Count() > 0 )
960 AddTransitions( transition, transitionData, true );
967 void Control::Impl::DoAction( Dali::Property::Index visualIndex, Dali::Property::Index actionId, const Dali::Property::Value attributes )
969 RegisteredVisualContainer::Iterator iter;
970 if ( FindVisual( visualIndex, mVisuals, iter ) )
972 Toolkit::GetImplementation((*iter)->visual).DoAction( actionId, attributes );
976 void Control::Impl::AppendAccessibilityAttribute( const std::string& key,
977 const std::string value )
979 Property::Value* val = mAccessibilityAttributes.Find( key );
982 mAccessibilityAttributes[key] = Property::Value( value );
986 mAccessibilityAttributes.Insert( key, value );
990 void Control::Impl::SetProperty( BaseObject* object, Property::Index index, const Property::Value& value )
992 Toolkit::Control control = Toolkit::Control::DownCast( BaseHandle( object ) );
996 Control& controlImpl( GetImplementation( control ) );
1000 case Toolkit::Control::Property::STYLE_NAME:
1002 controlImpl.SetStyleName( value.Get< std::string >() );
1006 case Toolkit::DevelControl::Property::STATE:
1008 bool withTransitions=true;
1009 const Property::Value* valuePtr=&value;
1010 const Property::Map* map = value.GetMap();
1013 Property::Value* value2 = map->Find("withTransitions");
1016 withTransitions = value2->Get<bool>();
1019 valuePtr = map->Find("state");
1024 Toolkit::DevelControl::State state( controlImpl.mImpl->mState );
1025 if( Scripting::GetEnumerationProperty< Toolkit::DevelControl::State >( *valuePtr, ControlStateTable, ControlStateTableCount, state ) )
1027 controlImpl.mImpl->SetState( state, withTransitions );
1033 case Toolkit::DevelControl::Property::SUB_STATE:
1035 std::string subState;
1036 if( value.Get( subState ) )
1038 controlImpl.mImpl->SetSubState( subState );
1043 case Toolkit::DevelControl::Property::LEFT_FOCUSABLE_ACTOR_ID:
1046 if( value.Get( focusId ) )
1048 controlImpl.mImpl->mLeftFocusableActorId = focusId;
1053 case Toolkit::DevelControl::Property::RIGHT_FOCUSABLE_ACTOR_ID:
1056 if( value.Get( focusId ) )
1058 controlImpl.mImpl->mRightFocusableActorId = focusId;
1063 case Toolkit::DevelControl::Property::ACCESSIBILITY_NAME:
1066 if( value.Get( name ) )
1068 controlImpl.mImpl->mAccessibilityName = name;
1069 controlImpl.mImpl->mAccessibilityNameSet = true;
1073 controlImpl.mImpl->mAccessibilityNameSet = false;
1078 case Toolkit::DevelControl::Property::ACCESSIBILITY_DESCRIPTION:
1081 if( value.Get( txt ) )
1083 controlImpl.mImpl->mAccessibilityDescription = txt;
1084 controlImpl.mImpl->mAccessibilityDescriptionSet = true;
1088 controlImpl.mImpl->mAccessibilityDescriptionSet = false;
1093 case Toolkit::DevelControl::Property::ACCESSIBILITY_TRANSLATION_DOMAIN:
1096 if( value.Get( txt ) )
1098 controlImpl.mImpl->mAccessibilityTranslationDomain = txt;
1099 controlImpl.mImpl->mAccessibilityTranslationDomainSet = true;
1103 controlImpl.mImpl->mAccessibilityTranslationDomainSet = false;
1108 case Toolkit::DevelControl::Property::ACCESSIBILITY_HIGHLIGHTABLE:
1111 if( value.Get( highlightable ) )
1113 controlImpl.mImpl->mAccessibilityHighlightable = highlightable;
1114 controlImpl.mImpl->mAccessibilityHighlightableSet = true;
1118 controlImpl.mImpl->mAccessibilityHighlightableSet = false;
1123 case Toolkit::DevelControl::Property::ACCESSIBILITY_ROLE:
1125 Dali::Accessibility::Role val;
1126 if( value.Get( val ) )
1128 controlImpl.mImpl->mAccessibilityRole = val;
1133 case Toolkit::DevelControl::Property::UP_FOCUSABLE_ACTOR_ID:
1136 if( value.Get( focusId ) )
1138 controlImpl.mImpl->mUpFocusableActorId = focusId;
1143 case Toolkit::DevelControl::Property::DOWN_FOCUSABLE_ACTOR_ID:
1146 if( value.Get( focusId ) )
1148 controlImpl.mImpl->mDownFocusableActorId = focusId;
1153 case Toolkit::Control::Property::KEY_INPUT_FOCUS:
1155 if ( value.Get< bool >() )
1157 controlImpl.SetKeyInputFocus();
1161 controlImpl.ClearKeyInputFocus();
1166 case Toolkit::Control::Property::BACKGROUND:
1170 const Property::Map* map = value.GetMap();
1171 if( map && !map->Empty() )
1173 controlImpl.SetBackground( *map );
1175 else if( value.Get( url ) )
1177 // don't know the size to load
1178 Toolkit::Visual::Base visual = Toolkit::VisualFactory::Get().CreateVisual( url, ImageDimensions() );
1181 controlImpl.mImpl->RegisterVisual( Toolkit::Control::Property::BACKGROUND, visual, DepthIndex::BACKGROUND );
1184 else if( value.Get( color ) )
1186 controlImpl.SetBackgroundColor(color);
1190 // The background is an empty property map, so we should clear the background
1191 controlImpl.ClearBackground();
1196 case Toolkit::Control::Property::MARGIN:
1199 if( value.Get( margin ) )
1201 controlImpl.mImpl->SetMargin( margin );
1206 case Toolkit::Control::Property::PADDING:
1209 if( value.Get( padding ) )
1211 controlImpl.mImpl->SetPadding( padding );
1216 case Toolkit::DevelControl::Property::TOOLTIP:
1218 TooltipPtr& tooltipPtr = controlImpl.mImpl->mTooltip;
1221 tooltipPtr = Tooltip::New( control );
1223 tooltipPtr->SetProperties( value );
1227 case Toolkit::DevelControl::Property::SHADOW:
1229 const Property::Map* map = value.GetMap();
1230 if( map && !map->Empty() )
1232 controlImpl.mImpl->SetShadow( *map );
1236 // The shadow is an empty property map, so we should clear the shadow
1237 controlImpl.mImpl->ClearShadow();
1242 case Toolkit::DevelControl::Property::ACCESSIBILITY_ATTRIBUTES:
1244 const Property::Map* map = value.GetMap();
1245 if( map && !map->Empty() )
1247 controlImpl.mImpl->mAccessibilityAttributes = *map;
1252 case Toolkit::DevelControl::Property::ACCESSIBILITY_ANIMATED:
1255 if( value.Get( animated ) )
1257 controlImpl.mImpl->mAccessibilityAnimated = animated;
1265 Property::Value Control::Impl::GetProperty( BaseObject* object, Property::Index index )
1267 Property::Value value;
1269 Toolkit::Control control = Toolkit::Control::DownCast( BaseHandle( object ) );
1273 Control& controlImpl( GetImplementation( control ) );
1277 case Toolkit::Control::Property::STYLE_NAME:
1279 value = controlImpl.GetStyleName();
1283 case Toolkit::DevelControl::Property::STATE:
1285 value = controlImpl.mImpl->mState;
1289 case Toolkit::DevelControl::Property::SUB_STATE:
1291 value = controlImpl.mImpl->mSubStateName;
1295 case Toolkit::DevelControl::Property::LEFT_FOCUSABLE_ACTOR_ID:
1297 value = controlImpl.mImpl->mLeftFocusableActorId;
1301 case Toolkit::DevelControl::Property::RIGHT_FOCUSABLE_ACTOR_ID:
1303 value = controlImpl.mImpl->mRightFocusableActorId;
1307 case Toolkit::DevelControl::Property::ACCESSIBILITY_NAME:
1309 if (controlImpl.mImpl->mAccessibilityNameSet)
1311 value = controlImpl.mImpl->mAccessibilityName;
1316 case Toolkit::DevelControl::Property::ACCESSIBILITY_DESCRIPTION:
1318 if (controlImpl.mImpl->mAccessibilityDescriptionSet)
1320 value = controlImpl.mImpl->mAccessibilityDescription;
1325 case Toolkit::DevelControl::Property::ACCESSIBILITY_TRANSLATION_DOMAIN:
1327 if (controlImpl.mImpl->mAccessibilityTranslationDomainSet)
1329 value = controlImpl.mImpl->mAccessibilityTranslationDomain;
1334 case Toolkit::DevelControl::Property::ACCESSIBILITY_HIGHLIGHTABLE:
1336 if (controlImpl.mImpl->mAccessibilityHighlightableSet)
1338 value = controlImpl.mImpl->mAccessibilityHighlightable;
1343 case Toolkit::DevelControl::Property::ACCESSIBILITY_ROLE:
1345 value = Property::Value(controlImpl.mImpl->mAccessibilityRole);
1349 case Toolkit::DevelControl::Property::UP_FOCUSABLE_ACTOR_ID:
1351 value = controlImpl.mImpl->mUpFocusableActorId;
1355 case Toolkit::DevelControl::Property::DOWN_FOCUSABLE_ACTOR_ID:
1357 value = controlImpl.mImpl->mDownFocusableActorId;
1361 case Toolkit::Control::Property::KEY_INPUT_FOCUS:
1363 value = controlImpl.HasKeyInputFocus();
1367 case Toolkit::Control::Property::BACKGROUND:
1370 Toolkit::Visual::Base visual = controlImpl.mImpl->GetVisual( Toolkit::Control::Property::BACKGROUND );
1373 visual.CreatePropertyMap( map );
1380 case Toolkit::Control::Property::MARGIN:
1382 value = controlImpl.mImpl->GetMargin();
1386 case Toolkit::Control::Property::PADDING:
1388 value = controlImpl.mImpl->GetPadding();
1392 case Toolkit::DevelControl::Property::TOOLTIP:
1395 if( controlImpl.mImpl->mTooltip )
1397 controlImpl.mImpl->mTooltip->CreatePropertyMap( map );
1403 case Toolkit::DevelControl::Property::SHADOW:
1406 Toolkit::Visual::Base visual = controlImpl.mImpl->GetVisual( Toolkit::DevelControl::Property::SHADOW );
1409 visual.CreatePropertyMap( map );
1416 case Toolkit::DevelControl::Property::ACCESSIBILITY_ATTRIBUTES:
1418 value = controlImpl.mImpl->mAccessibilityAttributes;
1422 case Toolkit::DevelControl::Property::ACCESSIBILITY_ANIMATED:
1424 value = controlImpl.mImpl->mAccessibilityAnimated;
1433 void Control::Impl::RemoveAccessibilityAttribute( const std::string& key )
1435 Property::Value* val = mAccessibilityAttributes.Find( key );
1437 mAccessibilityAttributes[key] = Property::Value();
1440 void Control::Impl::ClearAccessibilityAttributes()
1442 mAccessibilityAttributes.Clear();
1445 void Control::Impl::SetAccessibilityReadingInfoType( const Dali::Accessibility::ReadingInfoTypes types )
1448 if ( types[ Dali::Accessibility::ReadingInfoType::NAME ] )
1450 value += READING_INFO_TYPE_NAME;
1452 if ( types[ Dali::Accessibility::ReadingInfoType::ROLE ] )
1454 if( !value.empty() )
1456 value += READING_INFO_TYPE_SEPARATOR;
1458 value += READING_INFO_TYPE_ROLE;
1460 if ( types[ Dali::Accessibility::ReadingInfoType::DESCRIPTION ] )
1462 if( !value.empty() )
1464 value += READING_INFO_TYPE_SEPARATOR;
1466 value += READING_INFO_TYPE_DESCRIPTION;
1468 if ( types[ Dali::Accessibility::ReadingInfoType::STATE ] )
1470 if( !value.empty() )
1472 value += READING_INFO_TYPE_SEPARATOR;
1474 value += READING_INFO_TYPE_STATE;
1476 AppendAccessibilityAttribute( READING_INFO_TYPE_ATTRIBUTE_NAME, value );
1479 Dali::Accessibility::ReadingInfoTypes Control::Impl::GetAccessibilityReadingInfoType() const
1482 auto place = mAccessibilityAttributes.Find( READING_INFO_TYPE_ATTRIBUTE_NAME );
1485 place->Get( value );
1488 if ( value.empty() )
1493 Dali::Accessibility::ReadingInfoTypes types;
1495 if ( value.find( READING_INFO_TYPE_NAME ) != std::string::npos )
1497 types[ Dali::Accessibility::ReadingInfoType::NAME ] = true;
1499 if ( value.find( READING_INFO_TYPE_ROLE ) != std::string::npos )
1501 types[ Dali::Accessibility::ReadingInfoType::ROLE ] = true;
1503 if ( value.find( READING_INFO_TYPE_DESCRIPTION ) != std::string::npos )
1505 types[ Dali::Accessibility::ReadingInfoType::DESCRIPTION ] = true;
1507 if ( value.find( READING_INFO_TYPE_STATE ) != std::string::npos )
1509 types[ Dali::Accessibility::ReadingInfoType::STATE ] = true;
1515 void Control::Impl::CopyInstancedProperties( RegisteredVisualContainer& visuals, Dictionary<Property::Map>& instancedProperties )
1517 for(RegisteredVisualContainer::Iterator iter = visuals.Begin(); iter!= visuals.End(); iter++)
1519 if( (*iter)->visual )
1521 Property::Map instanceMap;
1522 Toolkit::GetImplementation((*iter)->visual).CreateInstancePropertyMap(instanceMap);
1523 instancedProperties.Add( (*iter)->visual.GetName(), instanceMap );
1529 void Control::Impl::RemoveVisual( RegisteredVisualContainer& visuals, const std::string& visualName )
1531 Actor self( mControlImpl.Self() );
1533 for ( RegisteredVisualContainer::Iterator visualIter = visuals.Begin();
1534 visualIter != visuals.End(); ++visualIter )
1536 Toolkit::Visual::Base visual = (*visualIter)->visual;
1537 if( visual && visual.GetName() == visualName )
1539 Toolkit::GetImplementation(visual).SetOffScene( self );
1540 (*visualIter)->visual.Reset();
1541 visuals.Erase( visualIter );
1547 void Control::Impl::RemoveVisuals( RegisteredVisualContainer& visuals, DictionaryKeys& removeVisuals )
1549 Actor self( mControlImpl.Self() );
1550 for( DictionaryKeys::iterator iter = removeVisuals.begin(); iter != removeVisuals.end(); ++iter )
1552 const std::string visualName = *iter;
1553 RemoveVisual( visuals, visualName );
1557 void Control::Impl::RecreateChangedVisuals( Dictionary<Property::Map>& stateVisualsToChange,
1558 Dictionary<Property::Map>& instancedProperties )
1560 Dali::CustomActor handle( mControlImpl.GetOwner() );
1561 for( Dictionary<Property::Map>::iterator iter = stateVisualsToChange.Begin();
1562 iter != stateVisualsToChange.End(); ++iter )
1564 const std::string& visualName = (*iter).key;
1565 const Property::Map& toMap = (*iter).entry;
1567 Actor self = mControlImpl.Self();
1568 RegisteredVisualContainer::Iterator registeredVisualsiter;
1569 // Check if visual (visualName) is already registered, this is the current visual.
1570 if(FindVisual(visualName, mVisuals, registeredVisualsiter))
1572 Toolkit::Visual::Base& visual = (*registeredVisualsiter)->visual;
1575 // No longer required to know if the replaced visual's resources are ready
1576 StopObservingVisual(visual);
1578 // If control staged then visuals will be swapped once ready
1579 if(self.GetProperty<bool>(Actor::Property::CONNECTED_TO_SCENE))
1581 // Check if visual is currently in the process of being replaced ( is in removal container )
1582 RegisteredVisualContainer::Iterator visualQueuedForRemoval;
1583 if(FindVisual(visualName, mRemoveVisuals, visualQueuedForRemoval))
1585 // Visual with same visual name is already in removal container so current visual pending
1586 // Only the the last requested visual will be displayed so remove current visual which is staged but not ready.
1587 Toolkit::GetImplementation(visual).SetOffScene(self);
1588 (*registeredVisualsiter)->visual.Reset();
1589 mVisuals.Erase(registeredVisualsiter);
1593 // current visual not already in removal container so add now.
1594 DALI_LOG_INFO(gLogFilter, Debug::Verbose, "RegisterVisual Move current registered visual to removal Queue: %s \n", visualName.c_str());
1595 MoveVisual(registeredVisualsiter, mVisuals, mRemoveVisuals);
1600 // Control not staged or visual disabled so can just erase from registered visuals and new visual will be added later.
1601 (*registeredVisualsiter)->visual.Reset();
1602 mVisuals.Erase(registeredVisualsiter);
1606 const Property::Map* instancedMap = instancedProperties.FindConst(visualName);
1607 Style::ApplyVisual(handle, visualName, toMap, instancedMap);
1612 void Control::Impl::ReplaceStateVisualsAndProperties( const StylePtr oldState, const StylePtr newState, const std::string& subState )
1614 // Collect all old visual names
1615 DictionaryKeys stateVisualsToRemove;
1618 oldState->visuals.GetKeys( stateVisualsToRemove );
1619 if( ! subState.empty() )
1621 const StylePtr* oldSubState = oldState->subStates.FindConst(subState);
1624 DictionaryKeys subStateVisualsToRemove;
1625 (*oldSubState)->visuals.GetKeys( subStateVisualsToRemove );
1626 Merge( stateVisualsToRemove, subStateVisualsToRemove );
1631 // Collect all new visual properties
1632 Dictionary<Property::Map> stateVisualsToAdd;
1635 stateVisualsToAdd = newState->visuals;
1636 if( ! subState.empty() )
1638 const StylePtr* newSubState = newState->subStates.FindConst(subState);
1641 stateVisualsToAdd.Merge( (*newSubState)->visuals );
1646 // If a name is in both add/remove, move it to change list.
1647 Dictionary<Property::Map> stateVisualsToChange;
1648 FindChangableVisuals( stateVisualsToAdd, stateVisualsToChange, stateVisualsToRemove);
1650 // Copy instanced properties (e.g. text label) of current visuals
1651 Dictionary<Property::Map> instancedProperties;
1652 CopyInstancedProperties( mVisuals, instancedProperties );
1654 // For each visual in remove list, remove from mVisuals
1655 RemoveVisuals( mVisuals, stateVisualsToRemove );
1657 // For each visual in add list, create and add to mVisuals
1658 Dali::CustomActor handle( mControlImpl.GetOwner() );
1659 Style::ApplyVisuals( handle, stateVisualsToAdd, instancedProperties );
1661 // For each visual in change list, if it requires a new visual,
1662 // remove old visual, create and add to mVisuals
1663 RecreateChangedVisuals( stateVisualsToChange, instancedProperties );
1666 void Control::Impl::SetState( DevelControl::State newState, bool withTransitions )
1668 DevelControl::State oldState = mState;
1669 Dali::CustomActor handle( mControlImpl.GetOwner() );
1670 DALI_LOG_INFO(gLogFilter, Debug::Concise, "Control::Impl::SetState: %s\n",
1671 (mState == DevelControl::NORMAL ? "NORMAL" :(
1672 mState == DevelControl::FOCUSED ?"FOCUSED" : (
1673 mState == DevelControl::DISABLED?"DISABLED":"NONE" ))));
1675 if( mState != newState )
1677 // If mState was Disabled, and new state is Focused, should probably
1678 // store that fact, e.g. in another property that FocusManager can access.
1681 // Trigger state change and transitions
1682 // Apply new style, if stylemanager is available
1683 Toolkit::StyleManager styleManager = Toolkit::StyleManager::Get();
1686 const StylePtr stylePtr = GetImpl( styleManager ).GetRecordedStyle( Toolkit::Control( mControlImpl.GetOwner() ) );
1690 std::string oldStateName = Scripting::GetEnumerationName< Toolkit::DevelControl::State >( oldState, ControlStateTable, ControlStateTableCount );
1691 std::string newStateName = Scripting::GetEnumerationName< Toolkit::DevelControl::State >( newState, ControlStateTable, ControlStateTableCount );
1693 const StylePtr* newStateStyle = stylePtr->subStates.Find( newStateName );
1694 const StylePtr* oldStateStyle = stylePtr->subStates.Find( oldStateName );
1695 if( oldStateStyle && newStateStyle )
1697 // Only change if both state styles exist
1698 ReplaceStateVisualsAndProperties( *oldStateStyle, *newStateStyle, mSubStateName );
1705 void Control::Impl::SetSubState( const std::string& subStateName, bool withTransitions )
1707 if( mSubStateName != subStateName )
1709 // Get existing sub-state visuals, and unregister them
1710 Dali::CustomActor handle( mControlImpl.GetOwner() );
1712 Toolkit::StyleManager styleManager = Toolkit::StyleManager::Get();
1715 const StylePtr stylePtr = GetImpl( styleManager ).GetRecordedStyle( Toolkit::Control( mControlImpl.GetOwner() ) );
1719 std::string stateName = Scripting::GetEnumerationName< Toolkit::DevelControl::State >( mState, ControlStateTable, ControlStateTableCount );
1721 const StylePtr* state = stylePtr->subStates.Find( stateName );
1724 StylePtr stateStyle(*state);
1726 const StylePtr* newStateStyle = stateStyle->subStates.Find( subStateName );
1727 const StylePtr* oldStateStyle = stateStyle->subStates.Find( mSubStateName );
1728 if( oldStateStyle && newStateStyle )
1731 ReplaceStateVisualsAndProperties( *oldStateStyle, *newStateStyle, empty );
1737 mSubStateName = subStateName;
1741 void Control::Impl::OnSceneDisconnection()
1743 Actor self = mControlImpl.Self();
1745 // Any visuals set for replacement but not yet ready should still be registered.
1746 // Reason: If a request was made to register a new visual but the control removed from scene before visual was ready
1747 // then when this control appears back on stage it should use that new visual.
1749 // Iterate through all registered visuals and set off scene
1750 SetVisualsOffScene( mVisuals, self );
1752 // Visuals pending replacement can now be taken out of the removal list and set off scene
1753 // Iterate through all replacement visuals and add to a move queue then set off scene
1754 for( auto removalIter = mRemoveVisuals.Begin(), end = mRemoveVisuals.End(); removalIter != end; removalIter++ )
1756 Toolkit::GetImplementation((*removalIter)->visual).SetOffScene( self );
1759 for( auto replacedIter = mVisuals.Begin(), end = mVisuals.End(); replacedIter != end; replacedIter++ )
1761 (*replacedIter)->pending = false;
1764 mRemoveVisuals.Clear();
1767 void Control::Impl::SetMargin( Extents margin )
1769 mControlImpl.mImpl->mMargin = margin;
1771 // Trigger a size negotiation request that may be needed when setting a margin.
1772 mControlImpl.RelayoutRequest();
1775 Extents Control::Impl::GetMargin() const
1777 return mControlImpl.mImpl->mMargin;
1780 void Control::Impl::SetPadding( Extents padding )
1782 mControlImpl.mImpl->mPadding = padding;
1784 // Trigger a size negotiation request that may be needed when setting a padding.
1785 mControlImpl.RelayoutRequest();
1788 Extents Control::Impl::GetPadding() const
1790 return mControlImpl.mImpl->mPadding;
1793 void Control::Impl::SetInputMethodContext( InputMethodContext& inputMethodContext )
1795 mInputMethodContext = inputMethodContext;
1798 bool Control::Impl::FilterKeyEvent( const KeyEvent& event )
1800 bool consumed ( false );
1802 if ( mInputMethodContext )
1804 consumed = mInputMethodContext.FilterEventKey( event );
1809 DevelControl::VisualEventSignalType& Control::Impl::VisualEventSignal()
1811 return mVisualEventSignal;
1814 void Control::Impl::SetShadow( const Property::Map& map )
1816 Toolkit::Visual::Base visual = Toolkit::VisualFactory::Get().CreateVisual( map );
1817 visual.SetName("shadow");
1821 mControlImpl.mImpl->RegisterVisual( Toolkit::DevelControl::Property::SHADOW, visual, DepthIndex::BACKGROUND_EFFECT );
1823 mControlImpl.RelayoutRequest();
1827 void Control::Impl::ClearShadow()
1829 mControlImpl.mImpl->UnregisterVisual( Toolkit::DevelControl::Property::SHADOW );
1831 // Trigger a size negotiation request that may be needed when unregistering a visual.
1832 mControlImpl.RelayoutRequest();
1835 Dali::Property Control::Impl::GetVisualProperty(Dali::Property::Index index, Dali::Property::Key visualPropertyKey)
1837 Toolkit::Visual::Base visual = GetVisualByIndex(mVisuals, index);
1840 Internal::Visual::Base& visualImpl = Toolkit::GetImplementation(visual);
1841 return visualImpl.GetPropertyObject(visualPropertyKey);
1845 return Dali::Property(handle, Property::INVALID_INDEX);
1848 void Control::Impl::EmitResourceReadySignal()
1850 if(!mIsEmittingResourceReadySignal)
1852 // Guard against calls to emit the signal during the callback
1853 mIsEmittingResourceReadySignal = true;
1855 // If the signal handler changes visual, it may become ready during this call & therefore this method will
1856 // get called again recursively. If so, mNeedToEmitResourceReady is set below, and we act on it after that secondary
1857 // invocation has completed by notifying in an Idle callback to prevent further recursion.
1858 Dali::Toolkit::Control handle(mControlImpl.GetOwner());
1859 mResourceReadySignal.Emit(handle);
1861 if(mNeedToEmitResourceReady)
1863 // Add idler to emit the signal again
1866 // The callback manager takes the ownership of the callback object.
1867 mIdleCallback = MakeCallback( this, &Control::Impl::OnIdleCallback);
1868 Adaptor::Get().AddIdle(mIdleCallback, false);
1872 mIsEmittingResourceReadySignal = false;
1876 mNeedToEmitResourceReady = true;
1880 void Control::Impl::OnIdleCallback()
1882 if(mNeedToEmitResourceReady)
1885 mNeedToEmitResourceReady = false;
1887 // A visual is ready so control may need relayouting if staged
1888 if(mControlImpl.Self().GetProperty<bool>(Actor::Property::CONNECTED_TO_SCENE))
1890 mControlImpl.RelayoutRequest();
1893 EmitResourceReadySignal();
1896 // Set the pointer to null as the callback manager deletes the callback after execute it.
1897 mIdleCallback = nullptr;
1900 Dali::Accessibility::Accessible *Control::Impl::GetAccessibilityObject()
1902 if( !accessibilityObject )
1903 accessibilityObject = accessibilityConstructor( mControlImpl.Self() );
1904 return accessibilityObject.get();
1907 Dali::Accessibility::Accessible *Control::Impl::GetAccessibilityObject(Dali::Actor actor)
1911 auto q = Dali::Toolkit::Control::DownCast( actor );
1914 auto q2 = static_cast< Internal::Control* >( &q.GetImplementation() );
1915 return q2->mImpl->GetAccessibilityObject();
1921 Control::Impl::AccessibleImpl::AccessibleImpl(Dali::Actor self, Dali::Accessibility::Role role, bool modal)
1922 : self(self), modal(modal)
1924 auto control = Dali::Toolkit::Control::DownCast(self);
1926 Internal::Control& internalControl = Toolkit::Internal::GetImplementation( control );
1927 Internal::Control::Impl& controlImpl = Internal::Control::Impl::Get( internalControl );
1928 if( controlImpl.mAccessibilityRole == Dali::Accessibility::Role::UNKNOWN )
1929 controlImpl.mAccessibilityRole = role;
1931 self.PropertySetSignal().Connect(&controlImpl, [this, &controlImpl](Dali::Handle &handle, Dali::Property::Index index, Dali::Property::Value value)
1933 if (this->self != Dali::Accessibility::Accessible::GetCurrentlyHighlightedActor())
1938 if (index == DevelControl::Property::ACCESSIBILITY_NAME
1939 || (index == GetNamePropertyIndex() && !controlImpl.mAccessibilityNameSet))
1941 if (controlImpl.mAccessibilityGetNameSignal.Empty())
1943 Emit(Dali::Accessibility::ObjectPropertyChangeEvent::NAME);
1947 if (index == DevelControl::Property::ACCESSIBILITY_DESCRIPTION
1948 || (index == GetDescriptionPropertyIndex() && !controlImpl.mAccessibilityDescriptionSet))
1950 if (controlImpl.mAccessibilityGetDescriptionSignal.Empty())
1952 Emit(Dali::Accessibility::ObjectPropertyChangeEvent::DESCRIPTION);
1958 std::string Control::Impl::AccessibleImpl::GetName()
1960 auto control = Dali::Toolkit::Control::DownCast(self);
1962 Internal::Control& internalControl = Toolkit::Internal::GetImplementation( control );
1963 Internal::Control::Impl& controlImpl = Internal::Control::Impl::Get( internalControl );
1965 if (!controlImpl.mAccessibilityGetNameSignal.Empty()) {
1967 controlImpl.mAccessibilityGetNameSignal.Emit(ret);
1971 if (controlImpl.mAccessibilityNameSet)
1972 return controlImpl.mAccessibilityName;
1974 if (auto raw = GetNameRaw(); !raw.empty())
1977 return self.GetProperty< std::string >( Actor::Property::NAME );
1980 std::string Control::Impl::AccessibleImpl::GetNameRaw()
1985 std::string Control::Impl::AccessibleImpl::GetDescription()
1987 auto control = Dali::Toolkit::Control::DownCast(self);
1989 Internal::Control& internalControl = Toolkit::Internal::GetImplementation( control );
1990 Internal::Control::Impl& controlImpl = Internal::Control::Impl::Get( internalControl );
1992 if (!controlImpl.mAccessibilityGetDescriptionSignal.Empty()) {
1994 controlImpl.mAccessibilityGetDescriptionSignal.Emit(ret);
1998 if (controlImpl.mAccessibilityDescriptionSet)
1999 return controlImpl.mAccessibilityDescription;
2001 return GetDescriptionRaw();
2004 std::string Control::Impl::AccessibleImpl::GetDescriptionRaw()
2009 Dali::Accessibility::Accessible* Control::Impl::AccessibleImpl::GetParent()
2011 return Dali::Accessibility::Accessible::Get( self.GetParent() );
2014 size_t Control::Impl::AccessibleImpl::GetChildCount()
2016 return self.GetChildCount();
2019 Dali::Accessibility::Accessible* Control::Impl::AccessibleImpl::GetChildAtIndex( size_t index )
2021 return Dali::Accessibility::Accessible::Get( self.GetChildAt( static_cast< unsigned int >( index ) ) );
2024 size_t Control::Impl::AccessibleImpl::GetIndexInParent()
2027 auto parent = s.GetParent();
2028 DALI_ASSERT_ALWAYS( parent && "can't call GetIndexInParent on object without parent" );
2029 auto count = parent.GetChildCount();
2030 for( auto i = 0u; i < count; ++i )
2032 auto c = parent.GetChildAt( i );
2036 DALI_ASSERT_ALWAYS( false && "object isn't child of it's parent" );
2037 return static_cast<size_t>(-1);
2040 Dali::Accessibility::Role Control::Impl::AccessibleImpl::GetRole()
2042 return self.GetProperty<Dali::Accessibility::Role>( Toolkit::DevelControl::Property::ACCESSIBILITY_ROLE );
2045 Dali::Accessibility::States Control::Impl::AccessibleImpl::CalculateStates()
2047 Dali::Accessibility::States s;
2048 s[Dali::Accessibility::State::FOCUSABLE] = self.GetProperty< bool >( Actor::Property::KEYBOARD_FOCUSABLE );
2049 s[Dali::Accessibility::State::FOCUSED] = Toolkit::KeyboardFocusManager::Get().GetCurrentFocusActor() == self;
2050 if(self.GetProperty( Toolkit::DevelControl::Property::ACCESSIBILITY_HIGHLIGHTABLE ).GetType() == Property::NONE )
2051 s[Dali::Accessibility::State::HIGHLIGHTABLE] = false;
2053 s[Dali::Accessibility::State::HIGHLIGHTABLE] = self.GetProperty( Toolkit::DevelControl::Property::ACCESSIBILITY_HIGHLIGHTABLE ).Get< bool >();
2054 s[Dali::Accessibility::State::HIGHLIGHTED] = GetCurrentlyHighlightedActor() == self;
2055 s[Dali::Accessibility::State::ENABLED] = true;
2056 s[Dali::Accessibility::State::SENSITIVE] = true;
2057 s[Dali::Accessibility::State::ANIMATED] = self.GetProperty( Toolkit::DevelControl::Property::ACCESSIBILITY_ANIMATED ).Get< bool >();
2058 s[Dali::Accessibility::State::VISIBLE] = true;
2061 s[Dali::Accessibility::State::MODAL] = true;
2063 s[Dali::Accessibility::State::SHOWING] = !self.GetProperty( Dali::DevelActor::Property::CULLED ).Get< bool >()
2064 && self.GetCurrentProperty< bool >( Actor::Property::VISIBLE );
2066 s[Dali::Accessibility::State::DEFUNCT] = !self.GetProperty( Dali::DevelActor::Property::CONNECTED_TO_SCENE ).Get< bool >();
2070 Dali::Accessibility::States Control::Impl::AccessibleImpl::GetStates()
2072 return CalculateStates();
2075 Dali::Accessibility::Attributes Control::Impl::AccessibleImpl::GetAttributes()
2077 std::unordered_map< std::string, std::string > attribute_map;
2078 auto q = Dali::Toolkit::Control::DownCast( self );
2080 q.GetProperty( Dali::Toolkit::DevelControl::Property::ACCESSIBILITY_ATTRIBUTES );
2081 auto z = w.GetMap();
2085 auto map_size = z->Count();
2087 for( unsigned int i = 0; i < map_size; i++ )
2089 auto map_key = z->GetKeyAt( i );
2090 if( map_key.type == Property::Key::STRING )
2092 std::string map_value;
2093 if( z->GetValue( i ).Get( map_value ) )
2095 attribute_map.emplace( std::move( map_key.stringKey ),
2096 std::move( map_value ) );
2102 return attribute_map;
2105 Dali::Accessibility::ComponentLayer Control::Impl::AccessibleImpl::GetLayer()
2107 return Dali::Accessibility::ComponentLayer::WINDOW;
2110 Dali::Rect<> Control::Impl::AccessibleImpl::GetExtents( Dali::Accessibility::CoordType ctype )
2112 Vector2 screenPosition =
2113 self.GetProperty( Dali::DevelActor::Property::SCREEN_POSITION )
2115 auto size = self.GetCurrentProperty< Vector3 >( Actor::Property::SIZE ) * self.GetCurrentProperty< Vector3 >( Actor::Property::WORLD_SCALE );
2116 bool positionUsesAnchorPoint =
2117 self.GetProperty( Dali::DevelActor::Property::POSITION_USES_ANCHOR_POINT )
2119 Vector3 anchorPointOffSet =
2120 size * ( positionUsesAnchorPoint ? self.GetCurrentProperty< Vector3 >( Actor::Property::ANCHOR_POINT )
2121 : AnchorPoint::TOP_LEFT );
2122 Vector2 position = Vector2( screenPosition.x - anchorPointOffSet.x,
2123 screenPosition.y - anchorPointOffSet.y );
2125 return { position.x, position.y, size.x, size.y };
2128 int16_t Control::Impl::AccessibleImpl::GetMdiZOrder() { return 0; }
2129 double Control::Impl::AccessibleImpl::GetAlpha() { return 0; }
2131 bool Control::Impl::AccessibleImpl::GrabFocus()
2133 return Toolkit::KeyboardFocusManager::Get().SetCurrentFocusActor( self );
2136 static Dali::Actor CreateHighlightIndicatorActor()
2138 std::string focusBorderImagePath(AssetManager::GetDaliImagePath());
2139 focusBorderImagePath += "/keyboard_focus.9.png";
2140 // Create the default if it hasn't been set and one that's shared by all the
2141 // keyboard focusable actors
2142 auto actor = Toolkit::ImageView::New( focusBorderImagePath );
2143 actor.SetResizePolicy( ResizePolicy::FILL_TO_PARENT, Dimension::ALL_DIMENSIONS );
2144 DevelControl::AppendAccessibilityAttribute( actor, "highlight", "" );
2145 actor.SetProperty( Toolkit::DevelControl::Property::ACCESSIBILITY_ANIMATED, true);
2146 actor.SetProperty( Toolkit::DevelControl::Property::ACCESSIBILITY_HIGHLIGHTABLE, false );
2151 bool Control::Impl::AccessibleImpl::GrabHighlight()
2153 auto old = GetCurrentlyHighlightedActor();
2155 if( !Dali::Accessibility::IsUp() )
2161 auto c = dynamic_cast< Dali::Accessibility::Component* >( GetAccessibilityObject( old ) );
2163 c->ClearHighlight();
2165 auto highlight = GetHighlightActor();
2168 highlight = CreateHighlightIndicatorActor();
2169 SetHighlightActor( highlight );
2171 highlight.SetProperty( Actor::Property::PARENT_ORIGIN, ParentOrigin::CENTER );
2172 highlight.SetProperty( Actor::Property::ANCHOR_POINT, AnchorPoint::CENTER );
2173 highlight.SetProperty( Actor::Property::POSITION_Z, 1.0f );
2174 highlight.SetProperty( Actor::Property::POSITION, Vector2( 0.0f, 0.0f ));
2176 EnsureSelfVisible();
2177 self.Add( highlight );
2178 SetCurrentlyHighlightedActor( self );
2179 EmitHighlighted( true );
2186 bool Control::Impl::AccessibleImpl::ClearHighlight()
2188 if( !Dali::Accessibility::IsUp() )
2190 if( GetCurrentlyHighlightedActor() == self )
2192 self.Remove( GetHighlightActor() );
2193 SetCurrentlyHighlightedActor( {} );
2194 EmitHighlighted( false );
2200 std::string Control::Impl::AccessibleImpl::GetActionName( size_t index )
2202 if ( index >= GetActionCount() ) return "";
2203 Dali::TypeInfo type;
2204 self.GetTypeInfo( type );
2205 DALI_ASSERT_ALWAYS( type && "no TypeInfo object" );
2206 return type.GetActionName( index );
2208 std::string Control::Impl::AccessibleImpl::GetLocalizedActionName( size_t index )
2210 // TODO: add localization
2211 return GetActionName( index );
2213 std::string Control::Impl::AccessibleImpl::GetActionDescription( size_t index )
2217 size_t Control::Impl::AccessibleImpl::GetActionCount()
2219 Dali::TypeInfo type;
2220 self.GetTypeInfo( type );
2221 DALI_ASSERT_ALWAYS( type && "no TypeInfo object" );
2222 return type.GetActionCount();
2224 std::string Control::Impl::AccessibleImpl::GetActionKeyBinding( size_t index )
2228 bool Control::Impl::AccessibleImpl::DoAction( size_t index )
2230 std::string actionName = GetActionName( index );
2231 return self.DoAction( actionName, {} );
2233 bool Control::Impl::AccessibleImpl::DoAction(const std::string& name)
2235 return self.DoAction( name, {} );
2238 bool Control::Impl::AccessibleImpl::DoGesture(const Dali::Accessibility::GestureInfo &gestureInfo)
2240 auto control = Dali::Toolkit::Control::DownCast(self);
2242 Internal::Control& internalControl = Toolkit::Internal::GetImplementation( control );
2243 Internal::Control::Impl& controlImpl = Internal::Control::Impl::Get( internalControl );
2245 if (!controlImpl.mAccessibilityDoGestureSignal.Empty()) {
2246 auto ret = std::make_pair(gestureInfo, false);
2247 controlImpl.mAccessibilityDoGestureSignal.Emit(ret);
2254 std::vector<Dali::Accessibility::Relation> Control::Impl::AccessibleImpl::GetRelationSet()
2256 auto control = Dali::Toolkit::Control::DownCast(self);
2258 Internal::Control& internalControl = Toolkit::Internal::GetImplementation( control );
2259 Internal::Control::Impl& controlImpl = Internal::Control::Impl::Get( internalControl );
2261 std::vector<Dali::Accessibility::Relation> ret;
2263 auto &v = controlImpl.mAccessibilityRelations;
2264 for (auto i = 0u; i < v.size(); ++i)
2269 ret.emplace_back( Accessibility::Relation{ static_cast<Accessibility::RelationType>(i), v[i] } );
2275 void Control::Impl::AccessibleImpl::EnsureChildVisible(Actor child)
2279 void Control::Impl::AccessibleImpl::EnsureSelfVisible()
2281 auto parent = dynamic_cast<Control::Impl::AccessibleImpl*>(GetParent());
2284 parent->EnsureChildVisible(self);
2288 Property::Index Control::Impl::AccessibleImpl::GetNamePropertyIndex()
2290 return Actor::Property::NAME;
2293 Property::Index Control::Impl::AccessibleImpl::GetDescriptionPropertyIndex()
2295 return Property::INVALID_INDEX;
2298 void Control::Impl::PositionOrSizeChangedCallback( PropertyNotification &p )
2300 auto self = Dali::Actor::DownCast(p.GetTarget());
2301 if (Dali::Accessibility::IsUp() && !self.GetProperty( Toolkit::DevelControl::Property::ACCESSIBILITY_ANIMATED ).Get< bool >())
2303 auto extents = DevelActor::CalculateScreenExtents( self );
2304 Dali::Accessibility::Accessible::Get( self )->EmitBoundsChanged( extents );
2308 void Control::Impl::CulledChangedCallback( PropertyNotification &p)
2310 if (Dali::Accessibility::IsUp())
2312 auto self = Dali::Actor::DownCast(p.GetTarget());
2313 Dali::Accessibility::Accessible::Get(self)->EmitShowing( !self.GetProperty( DevelActor::Property::CULLED ).Get<bool>() );
2317 void Control::Impl::AccessibilityRegister()
2319 if (!accessibilityNotificationSet)
2321 accessibilityNotificationPosition = mControlImpl.Self().AddPropertyNotification( Actor::Property::POSITION, StepCondition( 0.01f ) );
2322 accessibilityNotificationPosition.SetNotifyMode( PropertyNotification::NOTIFY_ON_CHANGED );
2323 accessibilityNotificationPosition.NotifySignal().Connect( &Control::Impl::PositionOrSizeChangedCallback );
2325 accessibilityNotificationSize = mControlImpl.Self().AddPropertyNotification( Actor::Property::SIZE, StepCondition( 0.01f ) );
2326 accessibilityNotificationSize.SetNotifyMode( PropertyNotification::NOTIFY_ON_CHANGED );
2327 accessibilityNotificationSize.NotifySignal().Connect( &Control::Impl::PositionOrSizeChangedCallback );
2329 accessibilityNotificationCulled = mControlImpl.Self().AddPropertyNotification( DevelActor::Property::CULLED, LessThanCondition( 0.5f ) );
2330 accessibilityNotificationCulled.SetNotifyMode( PropertyNotification::NOTIFY_ON_CHANGED );
2331 accessibilityNotificationCulled.NotifySignal().Connect( &Control::Impl::CulledChangedCallback );
2333 accessibilityNotificationSet = true;
2337 void Control::Impl::AccessibilityDeregister()
2339 if (accessibilityNotificationSet)
2341 accessibilityNotificationPosition = {};
2342 accessibilityNotificationSize = {};
2343 accessibilityNotificationCulled = {};
2344 accessibilityNotificationSet = false;
2348 } // namespace Internal
2350 } // namespace Toolkit