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),
461 mAutofillContainer(),
462 mFlags( Control::ControlBehaviour( CONTROL_BEHAVIOUR_DEFAULT ) ),
463 mIsKeyboardNavigationSupported( false ),
464 mIsKeyboardFocusGroup( false ),
465 mIsEmittingResourceReadySignal(false),
466 mNeedToEmitResourceReady(false),
467 mIsAutofillEnabled( false )
469 Dali::Accessibility::Accessible::RegisterControlAccessibilityGetter(
470 []( Dali::Actor actor ) -> Dali::Accessibility::Accessible* {
471 return Control::Impl::GetAccessibilityObject( actor );
474 accessibilityConstructor = []( Dali::Actor actor ) -> std::unique_ptr< Dali::Accessibility::Accessible > {
475 return std::unique_ptr< Dali::Accessibility::Accessible >( new AccessibleImpl( actor,
476 Dali::Accessibility::Role::UNKNOWN ) );
479 size_t len = static_cast<size_t>(Dali::Accessibility::RelationType::MAX_COUNT);
480 mAccessibilityRelations.reserve(len);
481 for (auto i = 0u; i < len; ++i)
483 mAccessibilityRelations.push_back({});
487 Control::Impl::~Impl()
489 for( auto&& iter : mVisuals )
491 StopObservingVisual( iter->visual );
494 for( auto&& iter : mRemoveVisuals )
496 StopObservingVisual( iter->visual );
499 AccessibilityDeregister();
500 // All gesture detectors will be destroyed so no need to disconnect.
501 delete mStartingPinchScale;
503 if(mIdleCallback && Adaptor::IsAvailable())
505 // Removes the callback from the callback manager in case the control is destroyed before the callback is executed.
506 Adaptor::Get().RemoveIdle(mIdleCallback);
510 Control::Impl& Control::Impl::Get( Internal::Control& internalControl )
512 return *internalControl.mImpl;
515 const Control::Impl& Control::Impl::Get( const Internal::Control& internalControl )
517 return *internalControl.mImpl;
520 // Gesture Detection Methods
521 void Control::Impl::PinchDetected(Actor actor, const PinchGesture& pinch)
523 mControlImpl.OnPinch(pinch);
526 void Control::Impl::PanDetected(Actor actor, const PanGesture& pan)
528 mControlImpl.OnPan(pan);
531 void Control::Impl::TapDetected(Actor actor, const TapGesture& tap)
533 mControlImpl.OnTap(tap);
536 void Control::Impl::LongPressDetected(Actor actor, const LongPressGesture& longPress)
538 mControlImpl.OnLongPress(longPress);
541 void Control::Impl::RegisterVisual( Property::Index index, Toolkit::Visual::Base& visual )
543 RegisterVisual( index, visual, VisualState::ENABLED, DepthIndexValue::NOT_SET );
546 void Control::Impl::RegisterVisual( Property::Index index, Toolkit::Visual::Base& visual, int depthIndex )
548 RegisterVisual( index, visual, VisualState::ENABLED, DepthIndexValue::SET, depthIndex );
551 void Control::Impl::RegisterVisual( Property::Index index, Toolkit::Visual::Base& visual, bool enabled )
553 RegisterVisual( index, visual, ( enabled ? VisualState::ENABLED : VisualState::DISABLED ), DepthIndexValue::NOT_SET );
556 void Control::Impl::RegisterVisual( Property::Index index, Toolkit::Visual::Base& visual, bool enabled, int depthIndex )
558 RegisterVisual( index, visual, ( enabled ? VisualState::ENABLED : VisualState::DISABLED ), DepthIndexValue::SET, depthIndex );
561 void Control::Impl::RegisterVisual( Property::Index index, Toolkit::Visual::Base& visual, VisualState::Type enabled, DepthIndexValue::Type depthIndexValueSet, int depthIndex )
563 DALI_LOG_INFO( gLogFilter, Debug::Concise, "RegisterVisual:%d \n", index );
565 bool visualReplaced ( false );
566 Actor self = mControlImpl.Self();
568 // Set the depth index, if not set by caller this will be either the current visual depth, max depth of all visuals
570 int requiredDepthIndex = visual.GetDepthIndex();
572 if( depthIndexValueSet == DepthIndexValue::SET )
574 requiredDepthIndex = depthIndex;
577 // Visual replacement, existing visual should only be removed from stage when replacement ready.
578 if( !mVisuals.Empty() )
580 RegisteredVisualContainer::Iterator registeredVisualsiter;
581 // Check if visual (index) is already registered, this is the current visual.
582 if( FindVisual( index, mVisuals, registeredVisualsiter ) )
584 Toolkit::Visual::Base& currentRegisteredVisual = (*registeredVisualsiter)->visual;
585 if( currentRegisteredVisual )
587 // Store current visual depth index as may need to set the replacement visual to same depth
588 const int currentDepthIndex = (*registeredVisualsiter)->visual.GetDepthIndex();
590 // No longer required to know if the replaced visual's resources are ready
591 StopObservingVisual( currentRegisteredVisual );
593 // If control staged and visual enabled then visuals will be swapped once ready
594 if( self.GetProperty< bool >( Actor::Property::CONNECTED_TO_SCENE ) && enabled )
596 // Check if visual is currently in the process of being replaced ( is in removal container )
597 RegisteredVisualContainer::Iterator visualQueuedForRemoval;
598 if ( FindVisual( index, mRemoveVisuals, visualQueuedForRemoval ) )
600 // Visual with same index is already in removal container so current visual pending
601 // Only the the last requested visual will be displayed so remove current visual which is staged but not ready.
602 Toolkit::GetImplementation( currentRegisteredVisual ).SetOffScene( self );
603 mVisuals.Erase( registeredVisualsiter );
607 // current visual not already in removal container so add now.
608 DALI_LOG_INFO( gLogFilter, Debug::Verbose, "RegisterVisual Move current registered visual to removal Queue: %d \n", index );
609 MoveVisual( registeredVisualsiter, mVisuals, mRemoveVisuals );
614 // Control not staged or visual disabled so can just erase from registered visuals and new visual will be added later.
615 mVisuals.Erase( registeredVisualsiter );
618 // 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
619 if( ( depthIndexValueSet == DepthIndexValue::NOT_SET ) &&
620 ( visual.GetDepthIndex() == 0 ) )
622 requiredDepthIndex = currentDepthIndex;
626 visualReplaced = true;
630 // If not set, set the name of the visual to the same name as the control's property.
631 // ( If the control has been type registered )
632 if( visual.GetName().empty() )
634 // returns empty string if index is not found as long as index is not -1
635 std::string visualName = self.GetPropertyName( index );
636 if( !visualName.empty() )
638 DALI_LOG_INFO( gLogFilter, Debug::Concise, "Setting visual name for property %d to %s\n",
639 index, visualName.c_str() );
640 visual.SetName( visualName );
644 if( !visualReplaced ) // New registration entry
646 // 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
647 if( ( depthIndexValueSet == DepthIndexValue::NOT_SET ) &&
648 ( mVisuals.Size() > 0 ) &&
649 ( visual.GetDepthIndex() == 0 ) )
651 int maxDepthIndex = std::numeric_limits< int >::min();
653 RegisteredVisualContainer::ConstIterator iter;
654 const RegisteredVisualContainer::ConstIterator endIter = mVisuals.End();
655 for ( iter = mVisuals.Begin(); iter != endIter; iter++ )
657 const int visualDepthIndex = (*iter)->visual.GetDepthIndex();
658 if ( visualDepthIndex > maxDepthIndex )
660 maxDepthIndex = visualDepthIndex;
663 ++maxDepthIndex; // Add one to the current maximum depth index so that our added visual appears on top
664 requiredDepthIndex = std::max( 0, maxDepthIndex ); // Start at zero if maxDepth index belongs to a background
670 // Set determined depth index
671 visual.SetDepthIndex( requiredDepthIndex );
673 // Monitor when the visual resources are ready
674 StartObservingVisual( visual );
676 DALI_LOG_INFO( gLogFilter, Debug::Concise, "New Visual registration index[%d] depth[%d]\n", index, requiredDepthIndex );
677 RegisteredVisual* newRegisteredVisual = new RegisteredVisual( index, visual,
678 ( enabled == VisualState::ENABLED ? true : false ),
679 ( visualReplaced && enabled ) ) ;
680 mVisuals.PushBack( newRegisteredVisual );
682 Internal::Visual::Base& visualImpl = Toolkit::GetImplementation( visual );
683 // Put on stage if enabled and the control is already on the stage
684 if( ( enabled == VisualState::ENABLED ) && self.GetProperty< bool >( Actor::Property::CONNECTED_TO_SCENE ) )
686 visualImpl.SetOnScene( self );
688 else if( visualImpl.IsResourceReady() ) // When not being staged, check if visual already 'ResourceReady' before it was Registered. ( Resource may have been loaded already )
690 ResourceReady( visualImpl );
695 DALI_LOG_INFO( gLogFilter, Debug::Verbose, "Control::RegisterVisual() Registered %s(%d), enabled:%s\n", visual.GetName().c_str(), index, enabled?"true":"false" );
698 void Control::Impl::UnregisterVisual( Property::Index index )
700 RegisteredVisualContainer::Iterator iter;
701 if ( FindVisual( index, mVisuals, iter ) )
703 // stop observing visual
704 StopObservingVisual( (*iter)->visual );
706 Actor self( mControlImpl.Self() );
707 Toolkit::GetImplementation((*iter)->visual).SetOffScene( self );
708 (*iter)->visual.Reset();
709 mVisuals.Erase( iter );
712 if( FindVisual( index, mRemoveVisuals, iter ) )
714 Actor self( mControlImpl.Self() );
715 Toolkit::GetImplementation( (*iter)->visual ).SetOffScene( self );
716 (*iter)->pending = false;
717 (*iter)->visual.Reset();
718 mRemoveVisuals.Erase( iter );
722 Toolkit::Visual::Base Control::Impl::GetVisual( Property::Index index ) const
724 RegisteredVisualContainer::Iterator iter;
725 if ( FindVisual( index, mVisuals, iter ) )
727 return (*iter)->visual;
730 return Toolkit::Visual::Base();
733 void Control::Impl::EnableVisual( Property::Index index, bool enable )
735 DALI_LOG_INFO( gLogFilter, Debug::General, "Control::EnableVisual(%d, %s)\n", index, enable?"T":"F");
737 RegisteredVisualContainer::Iterator iter;
738 if ( FindVisual( index, mVisuals, iter ) )
740 if ( (*iter)->enabled == enable )
742 DALI_LOG_INFO( gLogFilter, Debug::Verbose, "Control::EnableVisual Visual %s(%d) already %s\n", (*iter)->visual.GetName().c_str(), index, enable?"enabled":"disabled");
746 (*iter)->enabled = enable;
747 Actor parentActor = mControlImpl.Self();
748 if ( mControlImpl.Self().GetProperty< bool >( Actor::Property::CONNECTED_TO_SCENE ) ) // If control not on Scene then Visual will be added when SceneConnection is called.
752 DALI_LOG_INFO( gLogFilter, Debug::Verbose, "Control::EnableVisual Setting %s(%d) on stage \n", (*iter)->visual.GetName().c_str(), index );
753 Toolkit::GetImplementation((*iter)->visual).SetOnScene( parentActor );
757 DALI_LOG_INFO( gLogFilter, Debug::Verbose, "Control::EnableVisual Setting %s(%d) off stage \n", (*iter)->visual.GetName().c_str(), index );
758 Toolkit::GetImplementation((*iter)->visual).SetOffScene( parentActor ); // No need to call if control not staged.
764 DALI_LOG_WARNING( "Control::EnableVisual(%d, %s) FAILED - NO SUCH VISUAL\n", index, enable?"T":"F" );
768 bool Control::Impl::IsVisualEnabled( Property::Index index ) const
770 RegisteredVisualContainer::Iterator iter;
771 if ( FindVisual( index, mVisuals, iter ) )
773 return (*iter)->enabled;
778 void Control::Impl::StopObservingVisual( Toolkit::Visual::Base& visual )
780 Internal::Visual::Base& visualImpl = Toolkit::GetImplementation( visual );
782 // Stop observing the visual
783 visualImpl.RemoveEventObserver( *this );
786 void Control::Impl::StartObservingVisual( Toolkit::Visual::Base& visual)
788 Internal::Visual::Base& visualImpl = Toolkit::GetImplementation( visual );
790 // start observing the visual for events
791 visualImpl.AddEventObserver( *this );
794 // Called by a Visual when it's resource is ready
795 void Control::Impl::ResourceReady( Visual::Base& object)
797 DALI_LOG_INFO( gLogFilter, Debug::Verbose, "Control::Impl::ResourceReady() replacements pending[%d]\n", mRemoveVisuals.Count() );
799 Actor self = mControlImpl.Self();
801 // A resource is ready, find resource in the registered visuals container and get its index
802 for( auto registeredIter = mVisuals.Begin(), end = mVisuals.End(); registeredIter != end; ++registeredIter )
804 Internal::Visual::Base& registeredVisualImpl = Toolkit::GetImplementation( (*registeredIter)->visual );
806 if( &object == ®isteredVisualImpl )
808 RegisteredVisualContainer::Iterator visualToRemoveIter;
809 // Find visual with the same index in the removal container
810 // Set if off stage as it's replacement is now ready.
811 // Remove if from removal list as now removed from stage.
812 // Set Pending flag on the ready visual to false as now ready.
813 if( FindVisual( (*registeredIter)->index, mRemoveVisuals, visualToRemoveIter ) )
815 (*registeredIter)->pending = false;
816 Toolkit::GetImplementation( (*visualToRemoveIter)->visual ).SetOffScene( self );
817 mRemoveVisuals.Erase( visualToRemoveIter );
823 // A visual is ready so control may need relayouting if staged
824 if ( self.GetProperty< bool >( Actor::Property::CONNECTED_TO_SCENE ) )
826 mControlImpl.RelayoutRequest();
829 // Emit signal if all enabled visuals registered by the control are ready.
830 if( IsResourceReady() )
833 mNeedToEmitResourceReady = false;
835 EmitResourceReadySignal();
839 void Control::Impl::NotifyVisualEvent( Visual::Base& object, Property::Index signalId )
841 for( auto registeredIter = mVisuals.Begin(), end = mVisuals.End(); registeredIter != end; ++registeredIter )
843 Internal::Visual::Base& registeredVisualImpl = Toolkit::GetImplementation( (*registeredIter)->visual );
844 if( &object == ®isteredVisualImpl )
846 Dali::Toolkit::Control handle( mControlImpl.GetOwner() );
847 mVisualEventSignal.Emit( handle, (*registeredIter)->index, signalId );
853 bool Control::Impl::IsResourceReady() const
855 // Iterate through and check all the enabled visuals are ready
856 for( auto visualIter = mVisuals.Begin();
857 visualIter != mVisuals.End(); ++visualIter )
859 const Toolkit::Visual::Base visual = (*visualIter)->visual;
860 const Internal::Visual::Base& visualImpl = Toolkit::GetImplementation( visual );
862 // one of the enabled visuals is not ready
863 if( !visualImpl.IsResourceReady() && (*visualIter)->enabled )
871 Toolkit::Visual::ResourceStatus Control::Impl::GetVisualResourceStatus( Property::Index index ) const
873 RegisteredVisualContainer::Iterator iter;
874 if ( FindVisual( index, mVisuals, iter ) )
876 const Toolkit::Visual::Base visual = (*iter)->visual;
877 const Internal::Visual::Base& visualImpl = Toolkit::GetImplementation( visual );
878 return visualImpl.GetResourceStatus( );
881 return Toolkit::Visual::ResourceStatus::PREPARING;
886 void Control::Impl::AddTransitions( Dali::Animation& animation,
887 const Toolkit::TransitionData& handle,
888 bool createAnimation )
890 // Setup a Transition from TransitionData.
891 const Internal::TransitionData& transitionData = Toolkit::GetImplementation( handle );
892 TransitionData::Iterator end = transitionData.End();
893 for( TransitionData::Iterator iter = transitionData.Begin() ;
894 iter != end; ++iter )
896 TransitionData::Animator* animator = (*iter);
898 Toolkit::Visual::Base visual = GetVisualByName( mVisuals, animator->objectName );
902 #if defined(DEBUG_ENABLED)
903 Dali::TypeInfo typeInfo;
904 ControlWrapper* controlWrapperImpl = dynamic_cast<ControlWrapper*>(&mControlImpl);
905 if( controlWrapperImpl )
907 typeInfo = controlWrapperImpl->GetTypeInfo();
910 DALI_LOG_INFO( gLogFilter, Debug::Concise, "CreateTransition: Found %s visual for %s\n",
911 visual.GetName().c_str(), typeInfo?typeInfo.GetName().c_str():"Unknown" );
913 Internal::Visual::Base& visualImpl = Toolkit::GetImplementation( visual );
914 visualImpl.AnimateProperty( animation, *animator );
918 DALI_LOG_INFO( gLogFilter, Debug::Concise, "CreateTransition: Could not find visual. Trying actors");
919 // Otherwise, try any actor children of control (Including the control)
920 Actor child = mControlImpl.Self().FindChildByName( animator->objectName );
923 Property::Index propertyIndex = child.GetPropertyIndex( animator->propertyKey );
924 if( propertyIndex != Property::INVALID_INDEX )
926 if( animator->animate == false )
928 if( animator->targetValue.GetType() != Property::NONE )
930 child.SetProperty( propertyIndex, animator->targetValue );
933 else // animate the property
935 if( animator->initialValue.GetType() != Property::NONE )
937 child.SetProperty( propertyIndex, animator->initialValue );
940 if( createAnimation && !animation )
942 animation = Dali::Animation::New( 0.1f );
945 animation.AnimateTo( Property( child, propertyIndex ),
946 animator->targetValue,
947 animator->alphaFunction,
948 TimePeriod( animator->timePeriodDelay,
949 animator->timePeriodDuration ) );
957 Dali::Animation Control::Impl::CreateTransition( const Toolkit::TransitionData& transitionData )
959 Dali::Animation transition;
961 if( transitionData.Count() > 0 )
963 AddTransitions( transition, transitionData, true );
970 void Control::Impl::DoAction( Dali::Property::Index visualIndex, Dali::Property::Index actionId, const Dali::Property::Value attributes )
972 RegisteredVisualContainer::Iterator iter;
973 if ( FindVisual( visualIndex, mVisuals, iter ) )
975 Toolkit::GetImplementation((*iter)->visual).DoAction( actionId, attributes );
979 void Control::Impl::AppendAccessibilityAttribute( const std::string& key,
980 const std::string value )
982 Property::Value* val = mAccessibilityAttributes.Find( key );
985 mAccessibilityAttributes[key] = Property::Value( value );
989 mAccessibilityAttributes.Insert( key, value );
993 void Control::Impl::SetProperty( BaseObject* object, Property::Index index, const Property::Value& value )
995 Toolkit::Control control = Toolkit::Control::DownCast( BaseHandle( object ) );
999 Control& controlImpl( GetImplementation( control ) );
1003 case Toolkit::Control::Property::STYLE_NAME:
1005 controlImpl.SetStyleName( value.Get< std::string >() );
1009 case Toolkit::DevelControl::Property::STATE:
1011 bool withTransitions=true;
1012 const Property::Value* valuePtr=&value;
1013 const Property::Map* map = value.GetMap();
1016 Property::Value* value2 = map->Find("withTransitions");
1019 withTransitions = value2->Get<bool>();
1022 valuePtr = map->Find("state");
1027 Toolkit::DevelControl::State state( controlImpl.mImpl->mState );
1028 if( Scripting::GetEnumerationProperty< Toolkit::DevelControl::State >( *valuePtr, ControlStateTable, ControlStateTableCount, state ) )
1030 controlImpl.mImpl->SetState( state, withTransitions );
1036 case Toolkit::DevelControl::Property::SUB_STATE:
1038 std::string subState;
1039 if( value.Get( subState ) )
1041 controlImpl.mImpl->SetSubState( subState );
1046 case Toolkit::DevelControl::Property::LEFT_FOCUSABLE_ACTOR_ID:
1049 if( value.Get( focusId ) )
1051 controlImpl.mImpl->mLeftFocusableActorId = focusId;
1056 case Toolkit::DevelControl::Property::RIGHT_FOCUSABLE_ACTOR_ID:
1059 if( value.Get( focusId ) )
1061 controlImpl.mImpl->mRightFocusableActorId = focusId;
1066 case Toolkit::DevelControl::Property::ACCESSIBILITY_NAME:
1069 if( value.Get( name ) )
1071 controlImpl.mImpl->mAccessibilityName = name;
1072 controlImpl.mImpl->mAccessibilityNameSet = true;
1076 controlImpl.mImpl->mAccessibilityNameSet = false;
1081 case Toolkit::DevelControl::Property::ACCESSIBILITY_DESCRIPTION:
1084 if( value.Get( txt ) )
1086 controlImpl.mImpl->mAccessibilityDescription = txt;
1087 controlImpl.mImpl->mAccessibilityDescriptionSet = true;
1091 controlImpl.mImpl->mAccessibilityDescriptionSet = false;
1096 case Toolkit::DevelControl::Property::ACCESSIBILITY_TRANSLATION_DOMAIN:
1099 if( value.Get( txt ) )
1101 controlImpl.mImpl->mAccessibilityTranslationDomain = txt;
1102 controlImpl.mImpl->mAccessibilityTranslationDomainSet = true;
1106 controlImpl.mImpl->mAccessibilityTranslationDomainSet = false;
1111 case Toolkit::DevelControl::Property::ACCESSIBILITY_HIGHLIGHTABLE:
1114 if( value.Get( highlightable ) )
1116 controlImpl.mImpl->mAccessibilityHighlightable = highlightable;
1117 controlImpl.mImpl->mAccessibilityHighlightableSet = true;
1121 controlImpl.mImpl->mAccessibilityHighlightableSet = false;
1126 case Toolkit::DevelControl::Property::ACCESSIBILITY_ROLE:
1128 Dali::Accessibility::Role val;
1129 if( value.Get( val ) )
1131 controlImpl.mImpl->mAccessibilityRole = val;
1136 case Toolkit::DevelControl::Property::UP_FOCUSABLE_ACTOR_ID:
1139 if( value.Get( focusId ) )
1141 controlImpl.mImpl->mUpFocusableActorId = focusId;
1146 case Toolkit::DevelControl::Property::DOWN_FOCUSABLE_ACTOR_ID:
1149 if( value.Get( focusId ) )
1151 controlImpl.mImpl->mDownFocusableActorId = focusId;
1156 case Toolkit::Control::Property::KEY_INPUT_FOCUS:
1158 if ( value.Get< bool >() )
1160 controlImpl.SetKeyInputFocus();
1164 controlImpl.ClearKeyInputFocus();
1169 case Toolkit::Control::Property::BACKGROUND:
1173 const Property::Map* map = value.GetMap();
1174 if( map && !map->Empty() )
1176 controlImpl.SetBackground( *map );
1178 else if( value.Get( url ) )
1180 // don't know the size to load
1181 Toolkit::Visual::Base visual = Toolkit::VisualFactory::Get().CreateVisual( url, ImageDimensions() );
1184 controlImpl.mImpl->RegisterVisual( Toolkit::Control::Property::BACKGROUND, visual, DepthIndex::BACKGROUND );
1187 else if( value.Get( color ) )
1189 controlImpl.SetBackgroundColor(color);
1193 // The background is an empty property map, so we should clear the background
1194 controlImpl.ClearBackground();
1199 case Toolkit::Control::Property::MARGIN:
1202 if( value.Get( margin ) )
1204 controlImpl.mImpl->SetMargin( margin );
1209 case Toolkit::Control::Property::PADDING:
1212 if( value.Get( padding ) )
1214 controlImpl.mImpl->SetPadding( padding );
1219 case Toolkit::DevelControl::Property::TOOLTIP:
1221 TooltipPtr& tooltipPtr = controlImpl.mImpl->mTooltip;
1224 tooltipPtr = Tooltip::New( control );
1226 tooltipPtr->SetProperties( value );
1230 case Toolkit::DevelControl::Property::SHADOW:
1232 const Property::Map* map = value.GetMap();
1233 if( map && !map->Empty() )
1235 controlImpl.mImpl->SetShadow( *map );
1239 // The shadow is an empty property map, so we should clear the shadow
1240 controlImpl.mImpl->ClearShadow();
1245 case Toolkit::DevelControl::Property::ACCESSIBILITY_ATTRIBUTES:
1247 const Property::Map* map = value.GetMap();
1248 if( map && !map->Empty() )
1250 controlImpl.mImpl->mAccessibilityAttributes = *map;
1255 case Toolkit::DevelControl::Property::ACCESSIBILITY_ANIMATED:
1258 if( value.Get( animated ) )
1260 controlImpl.mImpl->mAccessibilityAnimated = animated;
1268 Property::Value Control::Impl::GetProperty( BaseObject* object, Property::Index index )
1270 Property::Value value;
1272 Toolkit::Control control = Toolkit::Control::DownCast( BaseHandle( object ) );
1276 Control& controlImpl( GetImplementation( control ) );
1280 case Toolkit::Control::Property::STYLE_NAME:
1282 value = controlImpl.GetStyleName();
1286 case Toolkit::DevelControl::Property::STATE:
1288 value = controlImpl.mImpl->mState;
1292 case Toolkit::DevelControl::Property::SUB_STATE:
1294 value = controlImpl.mImpl->mSubStateName;
1298 case Toolkit::DevelControl::Property::LEFT_FOCUSABLE_ACTOR_ID:
1300 value = controlImpl.mImpl->mLeftFocusableActorId;
1304 case Toolkit::DevelControl::Property::RIGHT_FOCUSABLE_ACTOR_ID:
1306 value = controlImpl.mImpl->mRightFocusableActorId;
1310 case Toolkit::DevelControl::Property::ACCESSIBILITY_NAME:
1312 if (controlImpl.mImpl->mAccessibilityNameSet)
1314 value = controlImpl.mImpl->mAccessibilityName;
1319 case Toolkit::DevelControl::Property::ACCESSIBILITY_DESCRIPTION:
1321 if (controlImpl.mImpl->mAccessibilityDescriptionSet)
1323 value = controlImpl.mImpl->mAccessibilityDescription;
1328 case Toolkit::DevelControl::Property::ACCESSIBILITY_TRANSLATION_DOMAIN:
1330 if (controlImpl.mImpl->mAccessibilityTranslationDomainSet)
1332 value = controlImpl.mImpl->mAccessibilityTranslationDomain;
1337 case Toolkit::DevelControl::Property::ACCESSIBILITY_HIGHLIGHTABLE:
1339 if (controlImpl.mImpl->mAccessibilityHighlightableSet)
1341 value = controlImpl.mImpl->mAccessibilityHighlightable;
1346 case Toolkit::DevelControl::Property::ACCESSIBILITY_ROLE:
1348 value = Property::Value(controlImpl.mImpl->mAccessibilityRole);
1352 case Toolkit::DevelControl::Property::UP_FOCUSABLE_ACTOR_ID:
1354 value = controlImpl.mImpl->mUpFocusableActorId;
1358 case Toolkit::DevelControl::Property::DOWN_FOCUSABLE_ACTOR_ID:
1360 value = controlImpl.mImpl->mDownFocusableActorId;
1364 case Toolkit::Control::Property::KEY_INPUT_FOCUS:
1366 value = controlImpl.HasKeyInputFocus();
1370 case Toolkit::Control::Property::BACKGROUND:
1373 Toolkit::Visual::Base visual = controlImpl.mImpl->GetVisual( Toolkit::Control::Property::BACKGROUND );
1376 visual.CreatePropertyMap( map );
1383 case Toolkit::Control::Property::MARGIN:
1385 value = controlImpl.mImpl->GetMargin();
1389 case Toolkit::Control::Property::PADDING:
1391 value = controlImpl.mImpl->GetPadding();
1395 case Toolkit::DevelControl::Property::TOOLTIP:
1398 if( controlImpl.mImpl->mTooltip )
1400 controlImpl.mImpl->mTooltip->CreatePropertyMap( map );
1406 case Toolkit::DevelControl::Property::SHADOW:
1409 Toolkit::Visual::Base visual = controlImpl.mImpl->GetVisual( Toolkit::DevelControl::Property::SHADOW );
1412 visual.CreatePropertyMap( map );
1419 case Toolkit::DevelControl::Property::ACCESSIBILITY_ATTRIBUTES:
1421 value = controlImpl.mImpl->mAccessibilityAttributes;
1425 case Toolkit::DevelControl::Property::ACCESSIBILITY_ANIMATED:
1427 value = controlImpl.mImpl->mAccessibilityAnimated;
1436 void Control::Impl::RemoveAccessibilityAttribute( const std::string& key )
1438 Property::Value* val = mAccessibilityAttributes.Find( key );
1440 mAccessibilityAttributes[key] = Property::Value();
1443 void Control::Impl::ClearAccessibilityAttributes()
1445 mAccessibilityAttributes.Clear();
1448 void Control::Impl::SetAccessibilityReadingInfoType( const Dali::Accessibility::ReadingInfoTypes types )
1451 if ( types[ Dali::Accessibility::ReadingInfoType::NAME ] )
1453 value += READING_INFO_TYPE_NAME;
1455 if ( types[ Dali::Accessibility::ReadingInfoType::ROLE ] )
1457 if( !value.empty() )
1459 value += READING_INFO_TYPE_SEPARATOR;
1461 value += READING_INFO_TYPE_ROLE;
1463 if ( types[ Dali::Accessibility::ReadingInfoType::DESCRIPTION ] )
1465 if( !value.empty() )
1467 value += READING_INFO_TYPE_SEPARATOR;
1469 value += READING_INFO_TYPE_DESCRIPTION;
1471 if ( types[ Dali::Accessibility::ReadingInfoType::STATE ] )
1473 if( !value.empty() )
1475 value += READING_INFO_TYPE_SEPARATOR;
1477 value += READING_INFO_TYPE_STATE;
1479 AppendAccessibilityAttribute( READING_INFO_TYPE_ATTRIBUTE_NAME, value );
1482 Dali::Accessibility::ReadingInfoTypes Control::Impl::GetAccessibilityReadingInfoType() const
1485 auto place = mAccessibilityAttributes.Find( READING_INFO_TYPE_ATTRIBUTE_NAME );
1488 place->Get( value );
1491 if ( value.empty() )
1496 Dali::Accessibility::ReadingInfoTypes types;
1498 if ( value.find( READING_INFO_TYPE_NAME ) != std::string::npos )
1500 types[ Dali::Accessibility::ReadingInfoType::NAME ] = true;
1502 if ( value.find( READING_INFO_TYPE_ROLE ) != std::string::npos )
1504 types[ Dali::Accessibility::ReadingInfoType::ROLE ] = true;
1506 if ( value.find( READING_INFO_TYPE_DESCRIPTION ) != std::string::npos )
1508 types[ Dali::Accessibility::ReadingInfoType::DESCRIPTION ] = true;
1510 if ( value.find( READING_INFO_TYPE_STATE ) != std::string::npos )
1512 types[ Dali::Accessibility::ReadingInfoType::STATE ] = true;
1518 void Control::Impl::CopyInstancedProperties( RegisteredVisualContainer& visuals, Dictionary<Property::Map>& instancedProperties )
1520 for(RegisteredVisualContainer::Iterator iter = visuals.Begin(); iter!= visuals.End(); iter++)
1522 if( (*iter)->visual )
1524 Property::Map instanceMap;
1525 Toolkit::GetImplementation((*iter)->visual).CreateInstancePropertyMap(instanceMap);
1526 instancedProperties.Add( (*iter)->visual.GetName(), instanceMap );
1532 void Control::Impl::RemoveVisual( RegisteredVisualContainer& visuals, const std::string& visualName )
1534 Actor self( mControlImpl.Self() );
1536 for ( RegisteredVisualContainer::Iterator visualIter = visuals.Begin();
1537 visualIter != visuals.End(); ++visualIter )
1539 Toolkit::Visual::Base visual = (*visualIter)->visual;
1540 if( visual && visual.GetName() == visualName )
1542 Toolkit::GetImplementation(visual).SetOffScene( self );
1543 (*visualIter)->visual.Reset();
1544 visuals.Erase( visualIter );
1550 void Control::Impl::RemoveVisuals( RegisteredVisualContainer& visuals, DictionaryKeys& removeVisuals )
1552 Actor self( mControlImpl.Self() );
1553 for( DictionaryKeys::iterator iter = removeVisuals.begin(); iter != removeVisuals.end(); ++iter )
1555 const std::string visualName = *iter;
1556 RemoveVisual( visuals, visualName );
1560 void Control::Impl::RecreateChangedVisuals( Dictionary<Property::Map>& stateVisualsToChange,
1561 Dictionary<Property::Map>& instancedProperties )
1563 Dali::CustomActor handle( mControlImpl.GetOwner() );
1564 for( Dictionary<Property::Map>::iterator iter = stateVisualsToChange.Begin();
1565 iter != stateVisualsToChange.End(); ++iter )
1567 const std::string& visualName = (*iter).key;
1568 const Property::Map& toMap = (*iter).entry;
1570 Actor self = mControlImpl.Self();
1571 RegisteredVisualContainer::Iterator registeredVisualsiter;
1572 // Check if visual (visualName) is already registered, this is the current visual.
1573 if(FindVisual(visualName, mVisuals, registeredVisualsiter))
1575 Toolkit::Visual::Base& visual = (*registeredVisualsiter)->visual;
1578 // No longer required to know if the replaced visual's resources are ready
1579 StopObservingVisual(visual);
1581 // If control staged then visuals will be swapped once ready
1582 if(self.GetProperty<bool>(Actor::Property::CONNECTED_TO_SCENE))
1584 // Check if visual is currently in the process of being replaced ( is in removal container )
1585 RegisteredVisualContainer::Iterator visualQueuedForRemoval;
1586 if(FindVisual(visualName, mRemoveVisuals, visualQueuedForRemoval))
1588 // Visual with same visual name is already in removal container so current visual pending
1589 // Only the the last requested visual will be displayed so remove current visual which is staged but not ready.
1590 Toolkit::GetImplementation(visual).SetOffScene(self);
1591 (*registeredVisualsiter)->visual.Reset();
1592 mVisuals.Erase(registeredVisualsiter);
1596 // current visual not already in removal container so add now.
1597 DALI_LOG_INFO(gLogFilter, Debug::Verbose, "RegisterVisual Move current registered visual to removal Queue: %s \n", visualName.c_str());
1598 MoveVisual(registeredVisualsiter, mVisuals, mRemoveVisuals);
1603 // Control not staged or visual disabled so can just erase from registered visuals and new visual will be added later.
1604 (*registeredVisualsiter)->visual.Reset();
1605 mVisuals.Erase(registeredVisualsiter);
1609 const Property::Map* instancedMap = instancedProperties.FindConst(visualName);
1610 Style::ApplyVisual(handle, visualName, toMap, instancedMap);
1615 void Control::Impl::ReplaceStateVisualsAndProperties( const StylePtr oldState, const StylePtr newState, const std::string& subState )
1617 // Collect all old visual names
1618 DictionaryKeys stateVisualsToRemove;
1621 oldState->visuals.GetKeys( stateVisualsToRemove );
1622 if( ! subState.empty() )
1624 const StylePtr* oldSubState = oldState->subStates.FindConst(subState);
1627 DictionaryKeys subStateVisualsToRemove;
1628 (*oldSubState)->visuals.GetKeys( subStateVisualsToRemove );
1629 Merge( stateVisualsToRemove, subStateVisualsToRemove );
1634 // Collect all new visual properties
1635 Dictionary<Property::Map> stateVisualsToAdd;
1638 stateVisualsToAdd = newState->visuals;
1639 if( ! subState.empty() )
1641 const StylePtr* newSubState = newState->subStates.FindConst(subState);
1644 stateVisualsToAdd.Merge( (*newSubState)->visuals );
1649 // If a name is in both add/remove, move it to change list.
1650 Dictionary<Property::Map> stateVisualsToChange;
1651 FindChangableVisuals( stateVisualsToAdd, stateVisualsToChange, stateVisualsToRemove);
1653 // Copy instanced properties (e.g. text label) of current visuals
1654 Dictionary<Property::Map> instancedProperties;
1655 CopyInstancedProperties( mVisuals, instancedProperties );
1657 // For each visual in remove list, remove from mVisuals
1658 RemoveVisuals( mVisuals, stateVisualsToRemove );
1660 // For each visual in add list, create and add to mVisuals
1661 Dali::CustomActor handle( mControlImpl.GetOwner() );
1662 Style::ApplyVisuals( handle, stateVisualsToAdd, instancedProperties );
1664 // For each visual in change list, if it requires a new visual,
1665 // remove old visual, create and add to mVisuals
1666 RecreateChangedVisuals( stateVisualsToChange, instancedProperties );
1669 void Control::Impl::SetState( DevelControl::State newState, bool withTransitions )
1671 DevelControl::State oldState = mState;
1672 Dali::CustomActor handle( mControlImpl.GetOwner() );
1673 DALI_LOG_INFO(gLogFilter, Debug::Concise, "Control::Impl::SetState: %s\n",
1674 (mState == DevelControl::NORMAL ? "NORMAL" :(
1675 mState == DevelControl::FOCUSED ?"FOCUSED" : (
1676 mState == DevelControl::DISABLED?"DISABLED":"NONE" ))));
1678 if( mState != newState )
1680 // If mState was Disabled, and new state is Focused, should probably
1681 // store that fact, e.g. in another property that FocusManager can access.
1684 // Trigger state change and transitions
1685 // Apply new style, if stylemanager is available
1686 Toolkit::StyleManager styleManager = Toolkit::StyleManager::Get();
1689 const StylePtr stylePtr = GetImpl( styleManager ).GetRecordedStyle( Toolkit::Control( mControlImpl.GetOwner() ) );
1693 std::string oldStateName = Scripting::GetEnumerationName< Toolkit::DevelControl::State >( oldState, ControlStateTable, ControlStateTableCount );
1694 std::string newStateName = Scripting::GetEnumerationName< Toolkit::DevelControl::State >( newState, ControlStateTable, ControlStateTableCount );
1696 const StylePtr* newStateStyle = stylePtr->subStates.Find( newStateName );
1697 const StylePtr* oldStateStyle = stylePtr->subStates.Find( oldStateName );
1698 if( oldStateStyle && newStateStyle )
1700 // Only change if both state styles exist
1701 ReplaceStateVisualsAndProperties( *oldStateStyle, *newStateStyle, mSubStateName );
1708 void Control::Impl::SetSubState( const std::string& subStateName, bool withTransitions )
1710 if( mSubStateName != subStateName )
1712 // Get existing sub-state visuals, and unregister them
1713 Dali::CustomActor handle( mControlImpl.GetOwner() );
1715 Toolkit::StyleManager styleManager = Toolkit::StyleManager::Get();
1718 const StylePtr stylePtr = GetImpl( styleManager ).GetRecordedStyle( Toolkit::Control( mControlImpl.GetOwner() ) );
1722 std::string stateName = Scripting::GetEnumerationName< Toolkit::DevelControl::State >( mState, ControlStateTable, ControlStateTableCount );
1724 const StylePtr* state = stylePtr->subStates.Find( stateName );
1727 StylePtr stateStyle(*state);
1729 const StylePtr* newStateStyle = stateStyle->subStates.Find( subStateName );
1730 const StylePtr* oldStateStyle = stateStyle->subStates.Find( mSubStateName );
1731 if( oldStateStyle && newStateStyle )
1734 ReplaceStateVisualsAndProperties( *oldStateStyle, *newStateStyle, empty );
1740 mSubStateName = subStateName;
1744 void Control::Impl::OnSceneDisconnection()
1746 Actor self = mControlImpl.Self();
1748 // Any visuals set for replacement but not yet ready should still be registered.
1749 // Reason: If a request was made to register a new visual but the control removed from scene before visual was ready
1750 // then when this control appears back on stage it should use that new visual.
1752 // Iterate through all registered visuals and set off scene
1753 SetVisualsOffScene( mVisuals, self );
1755 // Visuals pending replacement can now be taken out of the removal list and set off scene
1756 // Iterate through all replacement visuals and add to a move queue then set off scene
1757 for( auto removalIter = mRemoveVisuals.Begin(), end = mRemoveVisuals.End(); removalIter != end; removalIter++ )
1759 Toolkit::GetImplementation((*removalIter)->visual).SetOffScene( self );
1762 for( auto replacedIter = mVisuals.Begin(), end = mVisuals.End(); replacedIter != end; replacedIter++ )
1764 (*replacedIter)->pending = false;
1767 mRemoveVisuals.Clear();
1770 void Control::Impl::SetMargin( Extents margin )
1772 mControlImpl.mImpl->mMargin = margin;
1774 // Trigger a size negotiation request that may be needed when setting a margin.
1775 mControlImpl.RelayoutRequest();
1778 Extents Control::Impl::GetMargin() const
1780 return mControlImpl.mImpl->mMargin;
1783 void Control::Impl::SetPadding( Extents padding )
1785 mControlImpl.mImpl->mPadding = padding;
1787 // Trigger a size negotiation request that may be needed when setting a padding.
1788 mControlImpl.RelayoutRequest();
1791 Extents Control::Impl::GetPadding() const
1793 return mControlImpl.mImpl->mPadding;
1796 void Control::Impl::SetInputMethodContext( InputMethodContext& inputMethodContext )
1798 mInputMethodContext = inputMethodContext;
1801 bool Control::Impl::FilterKeyEvent( const KeyEvent& event )
1803 bool consumed ( false );
1805 if ( mInputMethodContext )
1807 consumed = mInputMethodContext.FilterEventKey( event );
1812 DevelControl::VisualEventSignalType& Control::Impl::VisualEventSignal()
1814 return mVisualEventSignal;
1817 void Control::Impl::SetShadow( const Property::Map& map )
1819 Toolkit::Visual::Base visual = Toolkit::VisualFactory::Get().CreateVisual( map );
1820 visual.SetName("shadow");
1824 mControlImpl.mImpl->RegisterVisual( Toolkit::DevelControl::Property::SHADOW, visual, DepthIndex::BACKGROUND_EFFECT );
1826 mControlImpl.RelayoutRequest();
1830 void Control::Impl::ClearShadow()
1832 mControlImpl.mImpl->UnregisterVisual( Toolkit::DevelControl::Property::SHADOW );
1834 // Trigger a size negotiation request that may be needed when unregistering a visual.
1835 mControlImpl.RelayoutRequest();
1838 Dali::Property Control::Impl::GetVisualProperty(Dali::Property::Index index, Dali::Property::Key visualPropertyKey)
1840 Toolkit::Visual::Base visual = GetVisualByIndex(mVisuals, index);
1843 Internal::Visual::Base& visualImpl = Toolkit::GetImplementation(visual);
1844 return visualImpl.GetPropertyObject(visualPropertyKey);
1848 return Dali::Property(handle, Property::INVALID_INDEX);
1851 void Control::Impl::EmitResourceReadySignal()
1853 if(!mIsEmittingResourceReadySignal)
1855 // Guard against calls to emit the signal during the callback
1856 mIsEmittingResourceReadySignal = true;
1858 // If the signal handler changes visual, it may become ready during this call & therefore this method will
1859 // get called again recursively. If so, mNeedToEmitResourceReady is set below, and we act on it after that secondary
1860 // invocation has completed by notifying in an Idle callback to prevent further recursion.
1861 Dali::Toolkit::Control handle(mControlImpl.GetOwner());
1862 mResourceReadySignal.Emit(handle);
1864 if(mNeedToEmitResourceReady)
1866 // Add idler to emit the signal again
1869 // The callback manager takes the ownership of the callback object.
1870 mIdleCallback = MakeCallback( this, &Control::Impl::OnIdleCallback);
1871 Adaptor::Get().AddIdle(mIdleCallback, false);
1875 mIsEmittingResourceReadySignal = false;
1879 mNeedToEmitResourceReady = true;
1883 void Control::Impl::OnIdleCallback()
1885 if(mNeedToEmitResourceReady)
1888 mNeedToEmitResourceReady = false;
1890 // A visual is ready so control may need relayouting if staged
1891 if(mControlImpl.Self().GetProperty<bool>(Actor::Property::CONNECTED_TO_SCENE))
1893 mControlImpl.RelayoutRequest();
1896 EmitResourceReadySignal();
1899 // Set the pointer to null as the callback manager deletes the callback after execute it.
1900 mIdleCallback = nullptr;
1903 Dali::Accessibility::Accessible *Control::Impl::GetAccessibilityObject()
1905 if( !accessibilityObject )
1906 accessibilityObject = accessibilityConstructor( mControlImpl.Self() );
1907 return accessibilityObject.get();
1910 Dali::Accessibility::Accessible *Control::Impl::GetAccessibilityObject(Dali::Actor actor)
1914 auto q = Dali::Toolkit::Control::DownCast( actor );
1917 auto q2 = static_cast< Internal::Control* >( &q.GetImplementation() );
1918 return q2->mImpl->GetAccessibilityObject();
1924 Control::Impl::AccessibleImpl::AccessibleImpl(Dali::Actor self, Dali::Accessibility::Role role, bool modal)
1925 : self(self), modal(modal)
1927 auto control = Dali::Toolkit::Control::DownCast(self);
1929 Internal::Control& internalControl = Toolkit::Internal::GetImplementation( control );
1930 Internal::Control::Impl& controlImpl = Internal::Control::Impl::Get( internalControl );
1931 if( controlImpl.mAccessibilityRole == Dali::Accessibility::Role::UNKNOWN )
1932 controlImpl.mAccessibilityRole = role;
1934 self.PropertySetSignal().Connect(&controlImpl, [this, &controlImpl](Dali::Handle &handle, Dali::Property::Index index, Dali::Property::Value value)
1936 if (this->self != Dali::Accessibility::Accessible::GetCurrentlyHighlightedActor())
1941 if (index == DevelControl::Property::ACCESSIBILITY_NAME
1942 || (index == GetNamePropertyIndex() && !controlImpl.mAccessibilityNameSet))
1944 if (controlImpl.mAccessibilityGetNameSignal.Empty())
1946 Emit(Dali::Accessibility::ObjectPropertyChangeEvent::NAME);
1950 if (index == DevelControl::Property::ACCESSIBILITY_DESCRIPTION
1951 || (index == GetDescriptionPropertyIndex() && !controlImpl.mAccessibilityDescriptionSet))
1953 if (controlImpl.mAccessibilityGetDescriptionSignal.Empty())
1955 Emit(Dali::Accessibility::ObjectPropertyChangeEvent::DESCRIPTION);
1961 std::string Control::Impl::AccessibleImpl::GetName()
1963 auto control = Dali::Toolkit::Control::DownCast(self);
1965 Internal::Control& internalControl = Toolkit::Internal::GetImplementation( control );
1966 Internal::Control::Impl& controlImpl = Internal::Control::Impl::Get( internalControl );
1968 if (!controlImpl.mAccessibilityGetNameSignal.Empty()) {
1970 controlImpl.mAccessibilityGetNameSignal.Emit(ret);
1974 if (controlImpl.mAccessibilityNameSet)
1975 return controlImpl.mAccessibilityName;
1977 if (auto raw = GetNameRaw(); !raw.empty())
1980 return self.GetProperty< std::string >( Actor::Property::NAME );
1983 std::string Control::Impl::AccessibleImpl::GetNameRaw()
1988 std::string Control::Impl::AccessibleImpl::GetDescription()
1990 auto control = Dali::Toolkit::Control::DownCast(self);
1992 Internal::Control& internalControl = Toolkit::Internal::GetImplementation( control );
1993 Internal::Control::Impl& controlImpl = Internal::Control::Impl::Get( internalControl );
1995 if (!controlImpl.mAccessibilityGetDescriptionSignal.Empty()) {
1997 controlImpl.mAccessibilityGetDescriptionSignal.Emit(ret);
2001 if (controlImpl.mAccessibilityDescriptionSet)
2002 return controlImpl.mAccessibilityDescription;
2004 return GetDescriptionRaw();
2007 std::string Control::Impl::AccessibleImpl::GetDescriptionRaw()
2012 Dali::Accessibility::Accessible* Control::Impl::AccessibleImpl::GetParent()
2014 return Dali::Accessibility::Accessible::Get( self.GetParent() );
2017 size_t Control::Impl::AccessibleImpl::GetChildCount()
2019 return self.GetChildCount();
2022 Dali::Accessibility::Accessible* Control::Impl::AccessibleImpl::GetChildAtIndex( size_t index )
2024 return Dali::Accessibility::Accessible::Get( self.GetChildAt( static_cast< unsigned int >( index ) ) );
2027 size_t Control::Impl::AccessibleImpl::GetIndexInParent()
2030 auto parent = s.GetParent();
2031 DALI_ASSERT_ALWAYS( parent && "can't call GetIndexInParent on object without parent" );
2032 auto count = parent.GetChildCount();
2033 for( auto i = 0u; i < count; ++i )
2035 auto c = parent.GetChildAt( i );
2039 DALI_ASSERT_ALWAYS( false && "object isn't child of it's parent" );
2040 return static_cast<size_t>(-1);
2043 Dali::Accessibility::Role Control::Impl::AccessibleImpl::GetRole()
2045 return self.GetProperty<Dali::Accessibility::Role>( Toolkit::DevelControl::Property::ACCESSIBILITY_ROLE );
2048 Dali::Accessibility::States Control::Impl::AccessibleImpl::CalculateStates()
2050 Dali::Accessibility::States s;
2051 s[Dali::Accessibility::State::FOCUSABLE] = self.GetProperty< bool >( Actor::Property::KEYBOARD_FOCUSABLE );
2052 s[Dali::Accessibility::State::FOCUSED] = Toolkit::KeyboardFocusManager::Get().GetCurrentFocusActor() == self;
2053 if(self.GetProperty( Toolkit::DevelControl::Property::ACCESSIBILITY_HIGHLIGHTABLE ).GetType() == Property::NONE )
2054 s[Dali::Accessibility::State::HIGHLIGHTABLE] = false;
2056 s[Dali::Accessibility::State::HIGHLIGHTABLE] = self.GetProperty( Toolkit::DevelControl::Property::ACCESSIBILITY_HIGHLIGHTABLE ).Get< bool >();
2057 s[Dali::Accessibility::State::HIGHLIGHTED] = GetCurrentlyHighlightedActor() == self;
2058 s[Dali::Accessibility::State::ENABLED] = true;
2059 s[Dali::Accessibility::State::SENSITIVE] = true;
2060 s[Dali::Accessibility::State::ANIMATED] = self.GetProperty( Toolkit::DevelControl::Property::ACCESSIBILITY_ANIMATED ).Get< bool >();
2061 s[Dali::Accessibility::State::VISIBLE] = true;
2064 s[Dali::Accessibility::State::MODAL] = true;
2066 s[Dali::Accessibility::State::SHOWING] = !self.GetProperty( Dali::DevelActor::Property::CULLED ).Get< bool >()
2067 && self.GetCurrentProperty< bool >( Actor::Property::VISIBLE );
2069 s[Dali::Accessibility::State::DEFUNCT] = !self.GetProperty( Dali::DevelActor::Property::CONNECTED_TO_SCENE ).Get< bool >();
2073 Dali::Accessibility::States Control::Impl::AccessibleImpl::GetStates()
2075 return CalculateStates();
2078 Dali::Accessibility::Attributes Control::Impl::AccessibleImpl::GetAttributes()
2080 std::unordered_map< std::string, std::string > attribute_map;
2081 auto q = Dali::Toolkit::Control::DownCast( self );
2083 q.GetProperty( Dali::Toolkit::DevelControl::Property::ACCESSIBILITY_ATTRIBUTES );
2084 auto z = w.GetMap();
2088 auto map_size = z->Count();
2090 for( unsigned int i = 0; i < map_size; i++ )
2092 auto map_key = z->GetKeyAt( i );
2093 if( map_key.type == Property::Key::STRING )
2095 std::string map_value;
2096 if( z->GetValue( i ).Get( map_value ) )
2098 attribute_map.emplace( std::move( map_key.stringKey ),
2099 std::move( map_value ) );
2105 return attribute_map;
2108 Dali::Accessibility::ComponentLayer Control::Impl::AccessibleImpl::GetLayer()
2110 return Dali::Accessibility::ComponentLayer::WINDOW;
2113 Dali::Rect<> Control::Impl::AccessibleImpl::GetExtents( Dali::Accessibility::CoordType ctype )
2115 Vector2 screenPosition =
2116 self.GetProperty( Dali::DevelActor::Property::SCREEN_POSITION )
2118 auto size = self.GetCurrentProperty< Vector3 >( Actor::Property::SIZE ) * self.GetCurrentProperty< Vector3 >( Actor::Property::WORLD_SCALE );
2119 bool positionUsesAnchorPoint =
2120 self.GetProperty( Dali::DevelActor::Property::POSITION_USES_ANCHOR_POINT )
2122 Vector3 anchorPointOffSet =
2123 size * ( positionUsesAnchorPoint ? self.GetCurrentProperty< Vector3 >( Actor::Property::ANCHOR_POINT )
2124 : AnchorPoint::TOP_LEFT );
2125 Vector2 position = Vector2( screenPosition.x - anchorPointOffSet.x,
2126 screenPosition.y - anchorPointOffSet.y );
2128 return { position.x, position.y, size.x, size.y };
2131 int16_t Control::Impl::AccessibleImpl::GetMdiZOrder() { return 0; }
2132 double Control::Impl::AccessibleImpl::GetAlpha() { return 0; }
2134 bool Control::Impl::AccessibleImpl::GrabFocus()
2136 return Toolkit::KeyboardFocusManager::Get().SetCurrentFocusActor( self );
2139 static Dali::Actor CreateHighlightIndicatorActor()
2141 std::string focusBorderImagePath(AssetManager::GetDaliImagePath());
2142 focusBorderImagePath += "/keyboard_focus.9.png";
2143 // Create the default if it hasn't been set and one that's shared by all the
2144 // keyboard focusable actors
2145 auto actor = Toolkit::ImageView::New( focusBorderImagePath );
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