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())
108 Toolkit::Visual::Type GetVisualTypeFromMap( const Property::Map& map )
110 Property::Value* typeValue = map.Find( Toolkit::Visual::Property::TYPE, VISUAL_TYPE );
111 Toolkit::Visual::Type type = Toolkit::Visual::IMAGE;
114 Scripting::GetEnumerationProperty( *typeValue, VISUAL_TYPE_TABLE, VISUAL_TYPE_TABLE_COUNT, type );
120 * Finds visual in given array, returning true if found along with the iterator for that visual as a out parameter
122 bool FindVisual( Property::Index targetIndex, const RegisteredVisualContainer& visuals, RegisteredVisualContainer::Iterator& iter )
124 for ( iter = visuals.Begin(); iter != visuals.End(); iter++ )
126 if ( (*iter)->index == targetIndex )
134 void FindChangableVisuals( Dictionary<Property::Map>& stateVisualsToAdd,
135 Dictionary<Property::Map>& stateVisualsToChange,
136 DictionaryKeys& stateVisualsToRemove)
138 DictionaryKeys copyOfStateVisualsToRemove = stateVisualsToRemove;
140 for( DictionaryKeys::iterator iter = copyOfStateVisualsToRemove.begin();
141 iter != copyOfStateVisualsToRemove.end(); ++iter )
143 const std::string& visualName = (*iter);
144 Property::Map* toMap = stateVisualsToAdd.Find( visualName );
147 stateVisualsToChange.Add( visualName, *toMap );
148 stateVisualsToAdd.Remove( visualName );
149 Remove( stateVisualsToRemove, visualName );
154 Toolkit::Visual::Base GetVisualByName(
155 const RegisteredVisualContainer& visuals,
156 const std::string& visualName )
158 Toolkit::Visual::Base visualHandle;
160 RegisteredVisualContainer::Iterator iter;
161 for ( iter = visuals.Begin(); iter != visuals.End(); iter++ )
163 Toolkit::Visual::Base visual = (*iter)->visual;
164 if( visual && visual.GetName() == visualName )
166 visualHandle = visual;
174 * Move visual from source to destination container
176 void MoveVisual( RegisteredVisualContainer::Iterator sourceIter, RegisteredVisualContainer& source, RegisteredVisualContainer& destination )
178 Toolkit::Visual::Base visual = (*sourceIter)->visual;
181 RegisteredVisual* rv = source.Release( sourceIter );
182 destination.PushBack( rv );
187 * Performs actions as requested using the action name.
188 * @param[in] object The object on which to perform the action.
189 * @param[in] actionName The action to perform.
190 * @param[in] attributes The attributes with which to perfrom this action.
191 * @return true if action has been accepted by this control
193 const char* ACTION_ACCESSIBILITY_ACTIVATED = "accessibilityActivated";
194 const char* ACTION_ACCESSIBILITY_READING_CANCELLED = "ReadingCancelled";
195 const char* ACTION_ACCESSIBILITY_READING_PAUSED = "ReadingPaused";
196 const char* ACTION_ACCESSIBILITY_READING_RESUMED = "ReadingResumed";
197 const char* ACTION_ACCESSIBILITY_READING_SKIPPED = "ReadingSkipped";
198 const char* ACTION_ACCESSIBILITY_READING_STOPPED = "ReadingStopped";
200 static bool DoAction( BaseObject* object, const std::string& actionName, const Property::Map& attributes )
204 Dali::BaseHandle handle( object );
206 Toolkit::Control control = Toolkit::Control::DownCast( handle );
208 DALI_ASSERT_ALWAYS( control );
210 if( 0 == strcmp( actionName.c_str(), ACTION_ACCESSIBILITY_ACTIVATED ) ||
211 actionName == "activate" )
213 // if cast succeeds there is an implementation so no need to check
214 if( !DevelControl::AccessibilityActivateSignal( control ).Empty() )
215 DevelControl::AccessibilityActivateSignal( control ).Emit();
216 else ret = Internal::GetImplementation( control ).OnAccessibilityActivated();
218 else if( 0 == strcmp( actionName.c_str(), ACTION_ACCESSIBILITY_READING_SKIPPED ) )
220 // if cast succeeds there is an implementation so no need to check
221 if( !DevelControl::AccessibilityReadingSkippedSignal( control ).Empty() )
222 DevelControl::AccessibilityReadingSkippedSignal( control ).Emit();
224 else if( 0 == strcmp( actionName.c_str(), ACTION_ACCESSIBILITY_READING_PAUSED ) )
226 // if cast succeeds there is an implementation so no need to check
227 if( !DevelControl::AccessibilityReadingPausedSignal( control ).Empty() )
228 DevelControl::AccessibilityReadingPausedSignal( control ).Emit();
230 else if( 0 == strcmp( actionName.c_str(), ACTION_ACCESSIBILITY_READING_RESUMED ) )
232 // if cast succeeds there is an implementation so no need to check
233 if( !DevelControl::AccessibilityReadingResumedSignal( control ).Empty() )
234 DevelControl::AccessibilityReadingResumedSignal( control ).Emit();
236 else if( 0 == strcmp( actionName.c_str(), ACTION_ACCESSIBILITY_READING_CANCELLED ) )
238 // if cast succeeds there is an implementation so no need to check
239 if( !DevelControl::AccessibilityReadingCancelledSignal( control ).Empty() )
240 DevelControl::AccessibilityReadingCancelledSignal( control ).Emit();
242 else if( 0 == strcmp( actionName.c_str(), ACTION_ACCESSIBILITY_READING_STOPPED ) )
244 // if cast succeeds there is an implementation so no need to check
245 if(!DevelControl::AccessibilityReadingStoppedSignal( control ).Empty())
246 DevelControl::AccessibilityReadingStoppedSignal( control ).Emit();
255 * Connects a callback function with the object's signals.
256 * @param[in] object The object providing the signal.
257 * @param[in] tracker Used to disconnect the signal.
258 * @param[in] signalName The signal to connect to.
259 * @param[in] functor A newly allocated FunctorDelegate.
260 * @return True if the signal was connected.
261 * @post If a signal was connected, ownership of functor was passed to CallbackBase. Otherwise the caller is responsible for deleting the unused functor.
263 const char* SIGNAL_KEY_EVENT = "keyEvent";
264 const char* SIGNAL_KEY_INPUT_FOCUS_GAINED = "keyInputFocusGained";
265 const char* SIGNAL_KEY_INPUT_FOCUS_LOST = "keyInputFocusLost";
266 const char* SIGNAL_TAPPED = "tapped";
267 const char* SIGNAL_PANNED = "panned";
268 const char* SIGNAL_PINCHED = "pinched";
269 const char* SIGNAL_LONG_PRESSED = "longPressed";
270 const char* SIGNAL_GET_NAME = "getName";
271 const char* SIGNAL_GET_DESCRIPTION = "getDescription";
272 const char* SIGNAL_DO_GESTURE = "doGesture";
273 static bool DoConnectSignal( BaseObject* object, ConnectionTrackerInterface* tracker, const std::string& signalName, FunctorDelegate* functor )
275 Dali::BaseHandle handle( object );
277 bool connected( false );
278 Toolkit::Control control = Toolkit::Control::DownCast( handle );
281 Internal::Control& controlImpl( Internal::GetImplementation( control ) );
284 if ( 0 == strcmp( signalName.c_str(), SIGNAL_KEY_EVENT ) )
286 controlImpl.KeyEventSignal().Connect( tracker, functor );
288 else if( 0 == strcmp( signalName.c_str(), SIGNAL_KEY_INPUT_FOCUS_GAINED ) )
290 controlImpl.KeyInputFocusGainedSignal().Connect( tracker, functor );
292 else if( 0 == strcmp( signalName.c_str(), SIGNAL_KEY_INPUT_FOCUS_LOST ) )
294 controlImpl.KeyInputFocusLostSignal().Connect( tracker, functor );
296 else if( 0 == strcmp( signalName.c_str(), SIGNAL_TAPPED ) )
298 controlImpl.EnableGestureDetection( GestureType::TAP );
299 controlImpl.GetTapGestureDetector().DetectedSignal().Connect( tracker, functor );
301 else if( 0 == strcmp( signalName.c_str(), SIGNAL_PANNED ) )
303 controlImpl.EnableGestureDetection( GestureType::PAN );
304 controlImpl.GetPanGestureDetector().DetectedSignal().Connect( tracker, functor );
306 else if( 0 == strcmp( signalName.c_str(), SIGNAL_PINCHED ) )
308 controlImpl.EnableGestureDetection( GestureType::PINCH );
309 controlImpl.GetPinchGestureDetector().DetectedSignal().Connect( tracker, functor );
311 else if( 0 == strcmp( signalName.c_str(), SIGNAL_LONG_PRESSED ) )
313 controlImpl.EnableGestureDetection( GestureType::LONG_PRESS );
314 controlImpl.GetLongPressGestureDetector().DetectedSignal().Connect( tracker, functor );
316 else if( 0 == strcmp( signalName.c_str(), SIGNAL_GET_NAME ) )
318 DevelControl::AccessibilityGetNameSignal( control ).Connect( tracker, functor );
320 else if( 0 == strcmp( signalName.c_str(), SIGNAL_GET_DESCRIPTION ) )
322 DevelControl::AccessibilityGetDescriptionSignal( control ).Connect( tracker, functor );
324 else if( 0 == strcmp( signalName.c_str(), SIGNAL_DO_GESTURE ) )
326 DevelControl::AccessibilityDoGestureSignal( control ).Connect( tracker, functor );
334 * Creates control through type registry
338 return Internal::Control::New();
340 // Setup signals and actions using the type-registry.
341 DALI_TYPE_REGISTRATION_BEGIN( Control, CustomActor, Create );
343 // Note: Properties are registered separately below.
345 SignalConnectorType registerSignal1( typeRegistration, SIGNAL_KEY_EVENT, &DoConnectSignal );
346 SignalConnectorType registerSignal2( typeRegistration, SIGNAL_KEY_INPUT_FOCUS_GAINED, &DoConnectSignal );
347 SignalConnectorType registerSignal3( typeRegistration, SIGNAL_KEY_INPUT_FOCUS_LOST, &DoConnectSignal );
348 SignalConnectorType registerSignal4( typeRegistration, SIGNAL_TAPPED, &DoConnectSignal );
349 SignalConnectorType registerSignal5( typeRegistration, SIGNAL_PANNED, &DoConnectSignal );
350 SignalConnectorType registerSignal6( typeRegistration, SIGNAL_PINCHED, &DoConnectSignal );
351 SignalConnectorType registerSignal7( typeRegistration, SIGNAL_LONG_PRESSED, &DoConnectSignal );
352 SignalConnectorType registerSignal8( typeRegistration, SIGNAL_GET_NAME, &DoConnectSignal );
353 SignalConnectorType registerSignal9( typeRegistration, SIGNAL_GET_DESCRIPTION, &DoConnectSignal );
354 SignalConnectorType registerSignal10( typeRegistration, SIGNAL_DO_GESTURE, &DoConnectSignal );
356 TypeAction registerAction1( typeRegistration, "activate", &DoAction );
357 TypeAction registerAction2( typeRegistration, ACTION_ACCESSIBILITY_ACTIVATED, &DoAction );
358 TypeAction registerAction3( typeRegistration, ACTION_ACCESSIBILITY_READING_SKIPPED, &DoAction );
359 TypeAction registerAction4( typeRegistration, ACTION_ACCESSIBILITY_READING_CANCELLED, &DoAction );
360 TypeAction registerAction5( typeRegistration, ACTION_ACCESSIBILITY_READING_STOPPED, &DoAction );
361 TypeAction registerAction6( typeRegistration, ACTION_ACCESSIBILITY_READING_PAUSED, &DoAction );
362 TypeAction registerAction7( typeRegistration, ACTION_ACCESSIBILITY_READING_RESUMED, &DoAction );
364 DALI_TYPE_REGISTRATION_END()
367 * @brief Iterate through given container and setOffScene any visual found
369 * @param[in] container Container of visuals
370 * @param[in] parent Parent actor to remove visuals from
372 void SetVisualsOffScene( const RegisteredVisualContainer& container, Actor parent )
374 for( auto iter = container.Begin(), end = container.End() ; iter!= end; iter++)
376 if( (*iter)->visual )
378 DALI_LOG_INFO( gLogFilter, Debug::Verbose, "Control::SetOffScene Setting visual(%d) off stage\n", (*iter)->index );
379 Toolkit::GetImplementation((*iter)->visual).SetOffScene( parent );
384 } // unnamed namespace
387 // Properties registered without macro to use specific member variables.
388 const PropertyRegistration Control::Impl::PROPERTY_1( typeRegistration, "styleName", Toolkit::Control::Property::STYLE_NAME, Property::STRING, &Control::Impl::SetProperty, &Control::Impl::GetProperty );
389 const PropertyRegistration Control::Impl::PROPERTY_4( typeRegistration, "keyInputFocus", Toolkit::Control::Property::KEY_INPUT_FOCUS, Property::BOOLEAN, &Control::Impl::SetProperty, &Control::Impl::GetProperty );
390 const PropertyRegistration Control::Impl::PROPERTY_5( typeRegistration, "background", Toolkit::Control::Property::BACKGROUND, Property::MAP, &Control::Impl::SetProperty, &Control::Impl::GetProperty );
391 const PropertyRegistration Control::Impl::PROPERTY_6( typeRegistration, "margin", Toolkit::Control::Property::MARGIN, Property::EXTENTS, &Control::Impl::SetProperty, &Control::Impl::GetProperty );
392 const PropertyRegistration Control::Impl::PROPERTY_7( typeRegistration, "padding", Toolkit::Control::Property::PADDING, Property::EXTENTS, &Control::Impl::SetProperty, &Control::Impl::GetProperty );
393 const PropertyRegistration Control::Impl::PROPERTY_8( typeRegistration, "tooltip", Toolkit::DevelControl::Property::TOOLTIP, Property::MAP, &Control::Impl::SetProperty, &Control::Impl::GetProperty );
394 const PropertyRegistration Control::Impl::PROPERTY_9( typeRegistration, "state", Toolkit::DevelControl::Property::STATE, Property::STRING, &Control::Impl::SetProperty, &Control::Impl::GetProperty );
395 const PropertyRegistration Control::Impl::PROPERTY_10( typeRegistration, "subState", Toolkit::DevelControl::Property::SUB_STATE, Property::STRING, &Control::Impl::SetProperty, &Control::Impl::GetProperty );
396 const PropertyRegistration Control::Impl::PROPERTY_11( typeRegistration, "leftFocusableActorId", Toolkit::DevelControl::Property::LEFT_FOCUSABLE_ACTOR_ID, Property::INTEGER, &Control::Impl::SetProperty, &Control::Impl::GetProperty );
397 const PropertyRegistration Control::Impl::PROPERTY_12( typeRegistration, "rightFocusableActorId", Toolkit::DevelControl::Property::RIGHT_FOCUSABLE_ACTOR_ID,Property::INTEGER, &Control::Impl::SetProperty, &Control::Impl::GetProperty );
398 const PropertyRegistration Control::Impl::PROPERTY_13( typeRegistration, "upFocusableActorId", Toolkit::DevelControl::Property::UP_FOCUSABLE_ACTOR_ID, Property::INTEGER, &Control::Impl::SetProperty, &Control::Impl::GetProperty );
399 const PropertyRegistration Control::Impl::PROPERTY_14( typeRegistration, "downFocusableActorId", Toolkit::DevelControl::Property::DOWN_FOCUSABLE_ACTOR_ID, Property::INTEGER, &Control::Impl::SetProperty, &Control::Impl::GetProperty );
400 const PropertyRegistration Control::Impl::PROPERTY_15( typeRegistration, "shadow", Toolkit::DevelControl::Property::SHADOW, Property::MAP, &Control::Impl::SetProperty, &Control::Impl::GetProperty );
401 const PropertyRegistration Control::Impl::PROPERTY_16( typeRegistration, "accessibilityAttributes", Toolkit::DevelControl::Property::ACCESSIBILITY_ATTRIBUTES, Property::MAP, &Control::Impl::SetProperty, &Control::Impl::GetProperty );
402 const PropertyRegistration Control::Impl::PROPERTY_17( typeRegistration, "accessibilityName", Toolkit::DevelControl::Property::ACCESSIBILITY_NAME, Property::STRING, &Control::Impl::SetProperty, &Control::Impl::GetProperty );
403 const PropertyRegistration Control::Impl::PROPERTY_18( typeRegistration, "accessibilityDescription", Toolkit::DevelControl::Property::ACCESSIBILITY_DESCRIPTION, Property::STRING, &Control::Impl::SetProperty, &Control::Impl::GetProperty );
404 const PropertyRegistration Control::Impl::PROPERTY_19( typeRegistration, "accessibilityTranslationDomain", Toolkit::DevelControl::Property::ACCESSIBILITY_TRANSLATION_DOMAIN, Property::STRING, &Control::Impl::SetProperty, &Control::Impl::GetProperty );
405 const PropertyRegistration Control::Impl::PROPERTY_20( typeRegistration, "accessibilityRole", Toolkit::DevelControl::Property::ACCESSIBILITY_ROLE, Property::INTEGER, &Control::Impl::SetProperty, &Control::Impl::GetProperty );
406 const PropertyRegistration Control::Impl::PROPERTY_21( typeRegistration, "accessibilityHighlightable", Toolkit::DevelControl::Property::ACCESSIBILITY_HIGHLIGHTABLE, Property::BOOLEAN, &Control::Impl::SetProperty, &Control::Impl::GetProperty );
407 const PropertyRegistration Control::Impl::PROPERTY_22( typeRegistration, "accessibilityAnimated", Toolkit::DevelControl::Property::ACCESSIBILITY_ANIMATED, Property::BOOLEAN, &Control::Impl::SetProperty, &Control::Impl::GetProperty );
409 Control::Impl::Impl( Control& controlImpl )
410 : mControlImpl( controlImpl ),
411 mState( Toolkit::DevelControl::NORMAL ),
413 mLeftFocusableActorId( -1 ),
414 mRightFocusableActorId( -1 ),
415 mUpFocusableActorId( -1 ),
416 mDownFocusableActorId( -1 ),
418 mBackgroundColor(Color::TRANSPARENT),
419 mStartingPinchScale(nullptr),
420 mMargin( 0, 0, 0, 0 ),
421 mPadding( 0, 0, 0, 0 ),
423 mKeyInputFocusGainedSignal(),
424 mKeyInputFocusLostSignal(),
425 mResourceReadySignal(),
426 mVisualEventSignal(),
427 mAccessibilityGetNameSignal(),
428 mAccessibilityGetDescriptionSignal(),
429 mAccessibilityDoGestureSignal(),
430 mPinchGestureDetector(),
431 mPanGestureDetector(),
432 mTapGestureDetector(),
433 mLongPressGestureDetector(),
435 mInputMethodContext(),
436 mIdleCallback(nullptr),
437 mFlags( Control::ControlBehaviour( CONTROL_BEHAVIOUR_DEFAULT ) ),
438 mIsKeyboardNavigationSupported( false ),
439 mIsKeyboardFocusGroup( false ),
440 mIsEmittingResourceReadySignal(false),
441 mNeedToEmitResourceReady(false)
443 Dali::Accessibility::Accessible::RegisterControlAccessibilityGetter(
444 []( Dali::Actor actor ) -> Dali::Accessibility::Accessible* {
445 return Control::Impl::GetAccessibilityObject( actor );
448 accessibilityConstructor = []( Dali::Actor actor ) -> std::unique_ptr< Dali::Accessibility::Accessible > {
449 return std::unique_ptr< Dali::Accessibility::Accessible >( new AccessibleImpl( actor,
450 Dali::Accessibility::Role::UNKNOWN ) );
453 size_t len = static_cast<size_t>(Dali::Accessibility::RelationType::MAX_COUNT);
454 mAccessibilityRelations.reserve(len);
455 for (auto i = 0u; i < len; ++i)
457 mAccessibilityRelations.push_back({});
461 Control::Impl::~Impl()
463 for( auto&& iter : mVisuals )
465 StopObservingVisual( iter->visual );
468 for( auto&& iter : mRemoveVisuals )
470 StopObservingVisual( iter->visual );
473 AccessibilityDeregister();
474 // All gesture detectors will be destroyed so no need to disconnect.
475 delete mStartingPinchScale;
477 if(mIdleCallback && Adaptor::IsAvailable())
479 // Removes the callback from the callback manager in case the control is destroyed before the callback is executed.
480 Adaptor::Get().RemoveIdle(mIdleCallback);
484 Control::Impl& Control::Impl::Get( Internal::Control& internalControl )
486 return *internalControl.mImpl;
489 const Control::Impl& Control::Impl::Get( const Internal::Control& internalControl )
491 return *internalControl.mImpl;
494 // Gesture Detection Methods
495 void Control::Impl::PinchDetected(Actor actor, const PinchGesture& pinch)
497 mControlImpl.OnPinch(pinch);
500 void Control::Impl::PanDetected(Actor actor, const PanGesture& pan)
502 mControlImpl.OnPan(pan);
505 void Control::Impl::TapDetected(Actor actor, const TapGesture& tap)
507 mControlImpl.OnTap(tap);
510 void Control::Impl::LongPressDetected(Actor actor, const LongPressGesture& longPress)
512 mControlImpl.OnLongPress(longPress);
515 void Control::Impl::RegisterVisual( Property::Index index, Toolkit::Visual::Base& visual )
517 RegisterVisual( index, visual, VisualState::ENABLED, DepthIndexValue::NOT_SET );
520 void Control::Impl::RegisterVisual( Property::Index index, Toolkit::Visual::Base& visual, int depthIndex )
522 RegisterVisual( index, visual, VisualState::ENABLED, DepthIndexValue::SET, depthIndex );
525 void Control::Impl::RegisterVisual( Property::Index index, Toolkit::Visual::Base& visual, bool enabled )
527 RegisterVisual( index, visual, ( enabled ? VisualState::ENABLED : VisualState::DISABLED ), DepthIndexValue::NOT_SET );
530 void Control::Impl::RegisterVisual( Property::Index index, Toolkit::Visual::Base& visual, bool enabled, int depthIndex )
532 RegisterVisual( index, visual, ( enabled ? VisualState::ENABLED : VisualState::DISABLED ), DepthIndexValue::SET, depthIndex );
535 void Control::Impl::RegisterVisual( Property::Index index, Toolkit::Visual::Base& visual, VisualState::Type enabled, DepthIndexValue::Type depthIndexValueSet, int depthIndex )
537 DALI_LOG_INFO( gLogFilter, Debug::Concise, "RegisterVisual:%d \n", index );
539 bool visualReplaced ( false );
540 Actor self = mControlImpl.Self();
542 // Set the depth index, if not set by caller this will be either the current visual depth, max depth of all visuals
544 int requiredDepthIndex = visual.GetDepthIndex();
546 if( depthIndexValueSet == DepthIndexValue::SET )
548 requiredDepthIndex = depthIndex;
551 // Visual replacement, existing visual should only be removed from stage when replacement ready.
552 if( !mVisuals.Empty() )
554 RegisteredVisualContainer::Iterator registeredVisualsiter;
555 // Check if visual (index) is already registered, this is the current visual.
556 if( FindVisual( index, mVisuals, registeredVisualsiter ) )
558 Toolkit::Visual::Base& currentRegisteredVisual = (*registeredVisualsiter)->visual;
559 if( currentRegisteredVisual )
561 // Store current visual depth index as may need to set the replacement visual to same depth
562 const int currentDepthIndex = (*registeredVisualsiter)->visual.GetDepthIndex();
564 // No longer required to know if the replaced visual's resources are ready
565 StopObservingVisual( currentRegisteredVisual );
567 // If control staged and visual enabled then visuals will be swapped once ready
568 if( self.GetProperty< bool >( Actor::Property::CONNECTED_TO_SCENE ) && enabled )
570 // Check if visual is currently in the process of being replaced ( is in removal container )
571 RegisteredVisualContainer::Iterator visualQueuedForRemoval;
572 if ( FindVisual( index, mRemoveVisuals, visualQueuedForRemoval ) )
574 // Visual with same index is already in removal container so current visual pending
575 // Only the the last requested visual will be displayed so remove current visual which is staged but not ready.
576 Toolkit::GetImplementation( currentRegisteredVisual ).SetOffScene( self );
577 mVisuals.Erase( registeredVisualsiter );
581 // current visual not already in removal container so add now.
582 DALI_LOG_INFO( gLogFilter, Debug::Verbose, "RegisterVisual Move current registered visual to removal Queue: %d \n", index );
583 MoveVisual( registeredVisualsiter, mVisuals, mRemoveVisuals );
588 // Control not staged or visual disabled so can just erase from registered visuals and new visual will be added later.
589 mVisuals.Erase( registeredVisualsiter );
592 // 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
593 if( ( depthIndexValueSet == DepthIndexValue::NOT_SET ) &&
594 ( visual.GetDepthIndex() == 0 ) )
596 requiredDepthIndex = currentDepthIndex;
600 visualReplaced = true;
604 // If not set, set the name of the visual to the same name as the control's property.
605 // ( If the control has been type registered )
606 if( visual.GetName().empty() )
608 // returns empty string if index is not found as long as index is not -1
609 std::string visualName = self.GetPropertyName( index );
610 if( !visualName.empty() )
612 DALI_LOG_INFO( gLogFilter, Debug::Concise, "Setting visual name for property %d to %s\n",
613 index, visualName.c_str() );
614 visual.SetName( visualName );
618 if( !visualReplaced ) // New registration entry
620 // 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
621 if( ( depthIndexValueSet == DepthIndexValue::NOT_SET ) &&
622 ( mVisuals.Size() > 0 ) &&
623 ( visual.GetDepthIndex() == 0 ) )
625 int maxDepthIndex = std::numeric_limits< int >::min();
627 RegisteredVisualContainer::ConstIterator iter;
628 const RegisteredVisualContainer::ConstIterator endIter = mVisuals.End();
629 for ( iter = mVisuals.Begin(); iter != endIter; iter++ )
631 const int visualDepthIndex = (*iter)->visual.GetDepthIndex();
632 if ( visualDepthIndex > maxDepthIndex )
634 maxDepthIndex = visualDepthIndex;
637 ++maxDepthIndex; // Add one to the current maximum depth index so that our added visual appears on top
638 requiredDepthIndex = std::max( 0, maxDepthIndex ); // Start at zero if maxDepth index belongs to a background
644 // Set determined depth index
645 visual.SetDepthIndex( requiredDepthIndex );
647 // Monitor when the visual resources are ready
648 StartObservingVisual( visual );
650 DALI_LOG_INFO( gLogFilter, Debug::Concise, "New Visual registration index[%d] depth[%d]\n", index, requiredDepthIndex );
651 RegisteredVisual* newRegisteredVisual = new RegisteredVisual( index, visual,
652 ( enabled == VisualState::ENABLED ? true : false ),
653 ( visualReplaced && enabled ) ) ;
654 mVisuals.PushBack( newRegisteredVisual );
656 Internal::Visual::Base& visualImpl = Toolkit::GetImplementation( visual );
657 // Put on stage if enabled and the control is already on the stage
658 if( ( enabled == VisualState::ENABLED ) && self.GetProperty< bool >( Actor::Property::CONNECTED_TO_SCENE ) )
660 visualImpl.SetOnScene( self );
662 else if( visualImpl.IsResourceReady() ) // When not being staged, check if visual already 'ResourceReady' before it was Registered. ( Resource may have been loaded already )
664 ResourceReady( visualImpl );
669 DALI_LOG_INFO( gLogFilter, Debug::Verbose, "Control::RegisterVisual() Registered %s(%d), enabled:%s\n", visual.GetName().c_str(), index, enabled?"true":"false" );
672 void Control::Impl::UnregisterVisual( Property::Index index )
674 RegisteredVisualContainer::Iterator iter;
675 if ( FindVisual( index, mVisuals, iter ) )
677 // stop observing visual
678 StopObservingVisual( (*iter)->visual );
680 Actor self( mControlImpl.Self() );
681 Toolkit::GetImplementation((*iter)->visual).SetOffScene( self );
682 (*iter)->visual.Reset();
683 mVisuals.Erase( iter );
686 if( FindVisual( index, mRemoveVisuals, iter ) )
688 Actor self( mControlImpl.Self() );
689 Toolkit::GetImplementation( (*iter)->visual ).SetOffScene( self );
690 (*iter)->pending = false;
691 (*iter)->visual.Reset();
692 mRemoveVisuals.Erase( iter );
696 Toolkit::Visual::Base Control::Impl::GetVisual( Property::Index index ) const
698 RegisteredVisualContainer::Iterator iter;
699 if ( FindVisual( index, mVisuals, iter ) )
701 return (*iter)->visual;
704 return Toolkit::Visual::Base();
707 void Control::Impl::EnableVisual( Property::Index index, bool enable )
709 DALI_LOG_INFO( gLogFilter, Debug::General, "Control::EnableVisual(%d, %s)\n", index, enable?"T":"F");
711 RegisteredVisualContainer::Iterator iter;
712 if ( FindVisual( index, mVisuals, iter ) )
714 if ( (*iter)->enabled == enable )
716 DALI_LOG_INFO( gLogFilter, Debug::Verbose, "Control::EnableVisual Visual %s(%d) already %s\n", (*iter)->visual.GetName().c_str(), index, enable?"enabled":"disabled");
720 (*iter)->enabled = enable;
721 Actor parentActor = mControlImpl.Self();
722 if ( mControlImpl.Self().GetProperty< bool >( Actor::Property::CONNECTED_TO_SCENE ) ) // If control not on Scene then Visual will be added when SceneConnection is called.
726 DALI_LOG_INFO( gLogFilter, Debug::Verbose, "Control::EnableVisual Setting %s(%d) on stage \n", (*iter)->visual.GetName().c_str(), index );
727 Toolkit::GetImplementation((*iter)->visual).SetOnScene( parentActor );
731 DALI_LOG_INFO( gLogFilter, Debug::Verbose, "Control::EnableVisual Setting %s(%d) off stage \n", (*iter)->visual.GetName().c_str(), index );
732 Toolkit::GetImplementation((*iter)->visual).SetOffScene( parentActor ); // No need to call if control not staged.
738 DALI_LOG_WARNING( "Control::EnableVisual(%d, %s) FAILED - NO SUCH VISUAL\n", index, enable?"T":"F" );
742 bool Control::Impl::IsVisualEnabled( Property::Index index ) const
744 RegisteredVisualContainer::Iterator iter;
745 if ( FindVisual( index, mVisuals, iter ) )
747 return (*iter)->enabled;
752 void Control::Impl::StopObservingVisual( Toolkit::Visual::Base& visual )
754 Internal::Visual::Base& visualImpl = Toolkit::GetImplementation( visual );
756 // Stop observing the visual
757 visualImpl.RemoveEventObserver( *this );
760 void Control::Impl::StartObservingVisual( Toolkit::Visual::Base& visual)
762 Internal::Visual::Base& visualImpl = Toolkit::GetImplementation( visual );
764 // start observing the visual for events
765 visualImpl.AddEventObserver( *this );
768 // Called by a Visual when it's resource is ready
769 void Control::Impl::ResourceReady( Visual::Base& object)
771 DALI_LOG_INFO( gLogFilter, Debug::Verbose, "Control::Impl::ResourceReady() replacements pending[%d]\n", mRemoveVisuals.Count() );
773 Actor self = mControlImpl.Self();
775 // A resource is ready, find resource in the registered visuals container and get its index
776 for( auto registeredIter = mVisuals.Begin(), end = mVisuals.End(); registeredIter != end; ++registeredIter )
778 Internal::Visual::Base& registeredVisualImpl = Toolkit::GetImplementation( (*registeredIter)->visual );
780 if( &object == ®isteredVisualImpl )
782 RegisteredVisualContainer::Iterator visualToRemoveIter;
783 // Find visual with the same index in the removal container
784 // Set if off stage as it's replacement is now ready.
785 // Remove if from removal list as now removed from stage.
786 // Set Pending flag on the ready visual to false as now ready.
787 if( FindVisual( (*registeredIter)->index, mRemoveVisuals, visualToRemoveIter ) )
789 (*registeredIter)->pending = false;
790 Toolkit::GetImplementation( (*visualToRemoveIter)->visual ).SetOffScene( self );
791 mRemoveVisuals.Erase( visualToRemoveIter );
797 // A visual is ready so control may need relayouting if staged
798 if ( self.GetProperty< bool >( Actor::Property::CONNECTED_TO_SCENE ) )
800 mControlImpl.RelayoutRequest();
803 // Emit signal if all enabled visuals registered by the control are ready.
804 if( IsResourceReady() )
807 mNeedToEmitResourceReady = false;
809 EmitResourceReadySignal();
813 void Control::Impl::NotifyVisualEvent( Visual::Base& object, Property::Index signalId )
815 for( auto registeredIter = mVisuals.Begin(), end = mVisuals.End(); registeredIter != end; ++registeredIter )
817 Internal::Visual::Base& registeredVisualImpl = Toolkit::GetImplementation( (*registeredIter)->visual );
818 if( &object == ®isteredVisualImpl )
820 Dali::Toolkit::Control handle( mControlImpl.GetOwner() );
821 mVisualEventSignal.Emit( handle, (*registeredIter)->index, signalId );
827 bool Control::Impl::IsResourceReady() const
829 // Iterate through and check all the enabled visuals are ready
830 for( auto visualIter = mVisuals.Begin();
831 visualIter != mVisuals.End(); ++visualIter )
833 const Toolkit::Visual::Base visual = (*visualIter)->visual;
834 const Internal::Visual::Base& visualImpl = Toolkit::GetImplementation( visual );
836 // one of the enabled visuals is not ready
837 if( !visualImpl.IsResourceReady() && (*visualIter)->enabled )
845 Toolkit::Visual::ResourceStatus Control::Impl::GetVisualResourceStatus( Property::Index index ) const
847 RegisteredVisualContainer::Iterator iter;
848 if ( FindVisual( index, mVisuals, iter ) )
850 const Toolkit::Visual::Base visual = (*iter)->visual;
851 const Internal::Visual::Base& visualImpl = Toolkit::GetImplementation( visual );
852 return visualImpl.GetResourceStatus( );
855 return Toolkit::Visual::ResourceStatus::PREPARING;
860 void Control::Impl::AddTransitions( Dali::Animation& animation,
861 const Toolkit::TransitionData& handle,
862 bool createAnimation )
864 // Setup a Transition from TransitionData.
865 const Internal::TransitionData& transitionData = Toolkit::GetImplementation( handle );
866 TransitionData::Iterator end = transitionData.End();
867 for( TransitionData::Iterator iter = transitionData.Begin() ;
868 iter != end; ++iter )
870 TransitionData::Animator* animator = (*iter);
872 Toolkit::Visual::Base visual = GetVisualByName( mVisuals, animator->objectName );
876 #if defined(DEBUG_ENABLED)
877 Dali::TypeInfo typeInfo;
878 ControlWrapper* controlWrapperImpl = dynamic_cast<ControlWrapper*>(&mControlImpl);
879 if( controlWrapperImpl )
881 typeInfo = controlWrapperImpl->GetTypeInfo();
884 DALI_LOG_INFO( gLogFilter, Debug::Concise, "CreateTransition: Found %s visual for %s\n",
885 visual.GetName().c_str(), typeInfo?typeInfo.GetName().c_str():"Unknown" );
887 Internal::Visual::Base& visualImpl = Toolkit::GetImplementation( visual );
888 visualImpl.AnimateProperty( animation, *animator );
892 DALI_LOG_INFO( gLogFilter, Debug::Concise, "CreateTransition: Could not find visual. Trying actors");
893 // Otherwise, try any actor children of control (Including the control)
894 Actor child = mControlImpl.Self().FindChildByName( animator->objectName );
897 Property::Index propertyIndex = child.GetPropertyIndex( animator->propertyKey );
898 if( propertyIndex != Property::INVALID_INDEX )
900 if( animator->animate == false )
902 if( animator->targetValue.GetType() != Property::NONE )
904 child.SetProperty( propertyIndex, animator->targetValue );
907 else // animate the property
909 if( animator->initialValue.GetType() != Property::NONE )
911 child.SetProperty( propertyIndex, animator->initialValue );
914 if( createAnimation && !animation )
916 animation = Dali::Animation::New( 0.1f );
919 animation.AnimateTo( Property( child, propertyIndex ),
920 animator->targetValue,
921 animator->alphaFunction,
922 TimePeriod( animator->timePeriodDelay,
923 animator->timePeriodDuration ) );
931 Dali::Animation Control::Impl::CreateTransition( const Toolkit::TransitionData& transitionData )
933 Dali::Animation transition;
935 if( transitionData.Count() > 0 )
937 AddTransitions( transition, transitionData, true );
944 void Control::Impl::DoAction( Dali::Property::Index visualIndex, Dali::Property::Index actionId, const Dali::Property::Value attributes )
946 RegisteredVisualContainer::Iterator iter;
947 if ( FindVisual( visualIndex, mVisuals, iter ) )
949 Toolkit::GetImplementation((*iter)->visual).DoAction( actionId, attributes );
953 void Control::Impl::AppendAccessibilityAttribute( const std::string& key,
954 const std::string value )
956 Property::Value* val = mAccessibilityAttributes.Find( key );
959 mAccessibilityAttributes[key] = Property::Value( value );
963 mAccessibilityAttributes.Insert( key, value );
967 void Control::Impl::SetProperty( BaseObject* object, Property::Index index, const Property::Value& value )
969 Toolkit::Control control = Toolkit::Control::DownCast( BaseHandle( object ) );
973 Control& controlImpl( GetImplementation( control ) );
977 case Toolkit::Control::Property::STYLE_NAME:
979 controlImpl.SetStyleName( value.Get< std::string >() );
983 case Toolkit::DevelControl::Property::STATE:
985 bool withTransitions=true;
986 const Property::Value* valuePtr=&value;
987 const Property::Map* map = value.GetMap();
990 Property::Value* value2 = map->Find("withTransitions");
993 withTransitions = value2->Get<bool>();
996 valuePtr = map->Find("state");
1001 Toolkit::DevelControl::State state( controlImpl.mImpl->mState );
1002 if( Scripting::GetEnumerationProperty< Toolkit::DevelControl::State >( *valuePtr, ControlStateTable, ControlStateTableCount, state ) )
1004 controlImpl.mImpl->SetState( state, withTransitions );
1010 case Toolkit::DevelControl::Property::SUB_STATE:
1012 std::string subState;
1013 if( value.Get( subState ) )
1015 controlImpl.mImpl->SetSubState( subState );
1020 case Toolkit::DevelControl::Property::LEFT_FOCUSABLE_ACTOR_ID:
1023 if( value.Get( focusId ) )
1025 controlImpl.mImpl->mLeftFocusableActorId = focusId;
1030 case Toolkit::DevelControl::Property::RIGHT_FOCUSABLE_ACTOR_ID:
1033 if( value.Get( focusId ) )
1035 controlImpl.mImpl->mRightFocusableActorId = focusId;
1040 case Toolkit::DevelControl::Property::ACCESSIBILITY_NAME:
1043 if( value.Get( name ) )
1045 controlImpl.mImpl->mAccessibilityName = name;
1046 controlImpl.mImpl->mAccessibilityNameSet = true;
1050 controlImpl.mImpl->mAccessibilityNameSet = false;
1055 case Toolkit::DevelControl::Property::ACCESSIBILITY_DESCRIPTION:
1058 if( value.Get( txt ) )
1060 controlImpl.mImpl->mAccessibilityDescription = txt;
1061 controlImpl.mImpl->mAccessibilityDescriptionSet = true;
1065 controlImpl.mImpl->mAccessibilityDescriptionSet = false;
1070 case Toolkit::DevelControl::Property::ACCESSIBILITY_TRANSLATION_DOMAIN:
1073 if( value.Get( txt ) )
1075 controlImpl.mImpl->mAccessibilityTranslationDomain = txt;
1076 controlImpl.mImpl->mAccessibilityTranslationDomainSet = true;
1080 controlImpl.mImpl->mAccessibilityTranslationDomainSet = false;
1085 case Toolkit::DevelControl::Property::ACCESSIBILITY_HIGHLIGHTABLE:
1088 if( value.Get( highlightable ) )
1090 controlImpl.mImpl->mAccessibilityHighlightable = highlightable;
1091 controlImpl.mImpl->mAccessibilityHighlightableSet = true;
1095 controlImpl.mImpl->mAccessibilityHighlightableSet = false;
1100 case Toolkit::DevelControl::Property::ACCESSIBILITY_ROLE:
1102 Dali::Accessibility::Role val;
1103 if( value.Get( val ) )
1105 controlImpl.mImpl->mAccessibilityRole = val;
1110 case Toolkit::DevelControl::Property::UP_FOCUSABLE_ACTOR_ID:
1113 if( value.Get( focusId ) )
1115 controlImpl.mImpl->mUpFocusableActorId = focusId;
1120 case Toolkit::DevelControl::Property::DOWN_FOCUSABLE_ACTOR_ID:
1123 if( value.Get( focusId ) )
1125 controlImpl.mImpl->mDownFocusableActorId = focusId;
1130 case Toolkit::Control::Property::KEY_INPUT_FOCUS:
1132 if ( value.Get< bool >() )
1134 controlImpl.SetKeyInputFocus();
1138 controlImpl.ClearKeyInputFocus();
1143 case Toolkit::Control::Property::BACKGROUND:
1147 const Property::Map* map = value.GetMap();
1148 if( map && !map->Empty() )
1150 controlImpl.SetBackground( *map );
1152 else if( value.Get( url ) )
1154 // don't know the size to load
1155 Toolkit::Visual::Base visual = Toolkit::VisualFactory::Get().CreateVisual( url, ImageDimensions() );
1158 controlImpl.mImpl->RegisterVisual( Toolkit::Control::Property::BACKGROUND, visual, DepthIndex::BACKGROUND );
1161 else if( value.Get( color ) )
1163 controlImpl.SetBackgroundColor(color);
1167 // The background is an empty property map, so we should clear the background
1168 controlImpl.ClearBackground();
1173 case Toolkit::Control::Property::MARGIN:
1176 if( value.Get( margin ) )
1178 controlImpl.mImpl->SetMargin( margin );
1183 case Toolkit::Control::Property::PADDING:
1186 if( value.Get( padding ) )
1188 controlImpl.mImpl->SetPadding( padding );
1193 case Toolkit::DevelControl::Property::TOOLTIP:
1195 TooltipPtr& tooltipPtr = controlImpl.mImpl->mTooltip;
1198 tooltipPtr = Tooltip::New( control );
1200 tooltipPtr->SetProperties( value );
1204 case Toolkit::DevelControl::Property::SHADOW:
1206 const Property::Map* map = value.GetMap();
1207 if( map && !map->Empty() )
1209 controlImpl.mImpl->SetShadow( *map );
1213 // The shadow is an empty property map, so we should clear the shadow
1214 controlImpl.mImpl->ClearShadow();
1219 case Toolkit::DevelControl::Property::ACCESSIBILITY_ATTRIBUTES:
1221 const Property::Map* map = value.GetMap();
1222 if( map && !map->Empty() )
1224 controlImpl.mImpl->mAccessibilityAttributes = *map;
1229 case Toolkit::DevelControl::Property::ACCESSIBILITY_ANIMATED:
1232 if( value.Get( animated ) )
1234 controlImpl.mImpl->mAccessibilityAnimated = animated;
1242 Property::Value Control::Impl::GetProperty( BaseObject* object, Property::Index index )
1244 Property::Value value;
1246 Toolkit::Control control = Toolkit::Control::DownCast( BaseHandle( object ) );
1250 Control& controlImpl( GetImplementation( control ) );
1254 case Toolkit::Control::Property::STYLE_NAME:
1256 value = controlImpl.GetStyleName();
1260 case Toolkit::DevelControl::Property::STATE:
1262 value = controlImpl.mImpl->mState;
1266 case Toolkit::DevelControl::Property::SUB_STATE:
1268 value = controlImpl.mImpl->mSubStateName;
1272 case Toolkit::DevelControl::Property::LEFT_FOCUSABLE_ACTOR_ID:
1274 value = controlImpl.mImpl->mLeftFocusableActorId;
1278 case Toolkit::DevelControl::Property::RIGHT_FOCUSABLE_ACTOR_ID:
1280 value = controlImpl.mImpl->mRightFocusableActorId;
1284 case Toolkit::DevelControl::Property::ACCESSIBILITY_NAME:
1286 if (controlImpl.mImpl->mAccessibilityNameSet)
1288 value = controlImpl.mImpl->mAccessibilityName;
1293 case Toolkit::DevelControl::Property::ACCESSIBILITY_DESCRIPTION:
1295 if (controlImpl.mImpl->mAccessibilityDescriptionSet)
1297 value = controlImpl.mImpl->mAccessibilityDescription;
1302 case Toolkit::DevelControl::Property::ACCESSIBILITY_TRANSLATION_DOMAIN:
1304 if (controlImpl.mImpl->mAccessibilityTranslationDomainSet)
1306 value = controlImpl.mImpl->mAccessibilityTranslationDomain;
1311 case Toolkit::DevelControl::Property::ACCESSIBILITY_HIGHLIGHTABLE:
1313 if (controlImpl.mImpl->mAccessibilityHighlightableSet)
1315 value = controlImpl.mImpl->mAccessibilityHighlightable;
1320 case Toolkit::DevelControl::Property::ACCESSIBILITY_ROLE:
1322 value = Property::Value(controlImpl.mImpl->mAccessibilityRole);
1326 case Toolkit::DevelControl::Property::UP_FOCUSABLE_ACTOR_ID:
1328 value = controlImpl.mImpl->mUpFocusableActorId;
1332 case Toolkit::DevelControl::Property::DOWN_FOCUSABLE_ACTOR_ID:
1334 value = controlImpl.mImpl->mDownFocusableActorId;
1338 case Toolkit::Control::Property::KEY_INPUT_FOCUS:
1340 value = controlImpl.HasKeyInputFocus();
1344 case Toolkit::Control::Property::BACKGROUND:
1347 Toolkit::Visual::Base visual = controlImpl.mImpl->GetVisual( Toolkit::Control::Property::BACKGROUND );
1350 visual.CreatePropertyMap( map );
1357 case Toolkit::Control::Property::MARGIN:
1359 value = controlImpl.mImpl->GetMargin();
1363 case Toolkit::Control::Property::PADDING:
1365 value = controlImpl.mImpl->GetPadding();
1369 case Toolkit::DevelControl::Property::TOOLTIP:
1372 if( controlImpl.mImpl->mTooltip )
1374 controlImpl.mImpl->mTooltip->CreatePropertyMap( map );
1380 case Toolkit::DevelControl::Property::SHADOW:
1383 Toolkit::Visual::Base visual = controlImpl.mImpl->GetVisual( Toolkit::DevelControl::Property::SHADOW );
1386 visual.CreatePropertyMap( map );
1393 case Toolkit::DevelControl::Property::ACCESSIBILITY_ATTRIBUTES:
1395 value = controlImpl.mImpl->mAccessibilityAttributes;
1399 case Toolkit::DevelControl::Property::ACCESSIBILITY_ANIMATED:
1401 value = controlImpl.mImpl->mAccessibilityAnimated;
1410 void Control::Impl::RemoveAccessibilityAttribute( const std::string& key )
1412 Property::Value* val = mAccessibilityAttributes.Find( key );
1414 mAccessibilityAttributes[key] = Property::Value();
1417 void Control::Impl::ClearAccessibilityAttributes()
1419 mAccessibilityAttributes.Clear();
1422 void Control::Impl::SetAccessibilityReadingInfoType( const Dali::Accessibility::ReadingInfoTypes types )
1425 if ( types[ Dali::Accessibility::ReadingInfoType::NAME ] )
1427 value += READING_INFO_TYPE_NAME;
1429 if ( types[ Dali::Accessibility::ReadingInfoType::ROLE ] )
1431 if( !value.empty() )
1433 value += READING_INFO_TYPE_SEPARATOR;
1435 value += READING_INFO_TYPE_ROLE;
1437 if ( types[ Dali::Accessibility::ReadingInfoType::DESCRIPTION ] )
1439 if( !value.empty() )
1441 value += READING_INFO_TYPE_SEPARATOR;
1443 value += READING_INFO_TYPE_DESCRIPTION;
1445 if ( types[ Dali::Accessibility::ReadingInfoType::STATE ] )
1447 if( !value.empty() )
1449 value += READING_INFO_TYPE_SEPARATOR;
1451 value += READING_INFO_TYPE_STATE;
1453 AppendAccessibilityAttribute( READING_INFO_TYPE_ATTRIBUTE_NAME, value );
1456 Dali::Accessibility::ReadingInfoTypes Control::Impl::GetAccessibilityReadingInfoType() const
1459 auto place = mAccessibilityAttributes.Find( READING_INFO_TYPE_ATTRIBUTE_NAME );
1462 place->Get( value );
1465 if ( value.empty() )
1470 Dali::Accessibility::ReadingInfoTypes types;
1472 if ( value.find( READING_INFO_TYPE_NAME ) != std::string::npos )
1474 types[ Dali::Accessibility::ReadingInfoType::NAME ] = true;
1476 if ( value.find( READING_INFO_TYPE_ROLE ) != std::string::npos )
1478 types[ Dali::Accessibility::ReadingInfoType::ROLE ] = true;
1480 if ( value.find( READING_INFO_TYPE_DESCRIPTION ) != std::string::npos )
1482 types[ Dali::Accessibility::ReadingInfoType::DESCRIPTION ] = true;
1484 if ( value.find( READING_INFO_TYPE_STATE ) != std::string::npos )
1486 types[ Dali::Accessibility::ReadingInfoType::STATE ] = true;
1492 void Control::Impl::CopyInstancedProperties( RegisteredVisualContainer& visuals, Dictionary<Property::Map>& instancedProperties )
1494 for(RegisteredVisualContainer::Iterator iter = visuals.Begin(); iter!= visuals.End(); iter++)
1496 if( (*iter)->visual )
1498 Property::Map instanceMap;
1499 Toolkit::GetImplementation((*iter)->visual).CreateInstancePropertyMap(instanceMap);
1500 instancedProperties.Add( (*iter)->visual.GetName(), instanceMap );
1506 void Control::Impl::RemoveVisual( RegisteredVisualContainer& visuals, const std::string& visualName )
1508 Actor self( mControlImpl.Self() );
1510 for ( RegisteredVisualContainer::Iterator visualIter = visuals.Begin();
1511 visualIter != visuals.End(); ++visualIter )
1513 Toolkit::Visual::Base visual = (*visualIter)->visual;
1514 if( visual && visual.GetName() == visualName )
1516 Toolkit::GetImplementation(visual).SetOffScene( self );
1517 (*visualIter)->visual.Reset();
1518 visuals.Erase( visualIter );
1524 void Control::Impl::RemoveVisuals( RegisteredVisualContainer& visuals, DictionaryKeys& removeVisuals )
1526 Actor self( mControlImpl.Self() );
1527 for( DictionaryKeys::iterator iter = removeVisuals.begin(); iter != removeVisuals.end(); ++iter )
1529 const std::string visualName = *iter;
1530 RemoveVisual( visuals, visualName );
1534 void Control::Impl::RecreateChangedVisuals( Dictionary<Property::Map>& stateVisualsToChange,
1535 Dictionary<Property::Map>& instancedProperties )
1537 Dali::CustomActor handle( mControlImpl.GetOwner() );
1538 for( Dictionary<Property::Map>::iterator iter = stateVisualsToChange.Begin();
1539 iter != stateVisualsToChange.End(); ++iter )
1541 const std::string& visualName = (*iter).key;
1542 const Property::Map& toMap = (*iter).entry;
1544 // is it a candidate for re-creation?
1545 bool recreate = false;
1547 Toolkit::Visual::Base visual = GetVisualByName( mVisuals, visualName );
1550 Property::Map fromMap;
1551 visual.CreatePropertyMap( fromMap );
1553 Toolkit::Visual::Type fromType = GetVisualTypeFromMap( fromMap );
1554 Toolkit::Visual::Type toType = GetVisualTypeFromMap( toMap );
1556 if( fromType != toType )
1562 if( fromType == Toolkit::Visual::IMAGE || fromType == Toolkit::Visual::N_PATCH
1563 || fromType == Toolkit::Visual::SVG || fromType == Toolkit::Visual::ANIMATED_IMAGE )
1565 Property::Value* fromUrl = fromMap.Find( Toolkit::ImageVisual::Property::URL, IMAGE_URL_NAME );
1566 Property::Value* toUrl = toMap.Find( Toolkit::ImageVisual::Property::URL, IMAGE_URL_NAME );
1568 if( fromUrl && toUrl )
1570 std::string fromUrlString;
1571 std::string toUrlString;
1572 fromUrl->Get(fromUrlString);
1573 toUrl->Get(toUrlString);
1575 if( fromUrlString != toUrlString )
1583 const Property::Map* instancedMap = instancedProperties.FindConst( visualName );
1584 if( recreate || instancedMap )
1586 RemoveVisual( mVisuals, visualName );
1587 Style::ApplyVisual( handle, visualName, toMap, instancedMap );
1591 // @todo check to see if we can apply toMap without recreating the visual
1592 // e.g. by setting only animatable properties
1593 // For now, recreate all visuals, but merge in instance data.
1594 RemoveVisual( mVisuals, visualName );
1595 Style::ApplyVisual( handle, visualName, toMap, instancedMap );
1601 void Control::Impl::ReplaceStateVisualsAndProperties( const StylePtr oldState, const StylePtr newState, const std::string& subState )
1603 // Collect all old visual names
1604 DictionaryKeys stateVisualsToRemove;
1607 oldState->visuals.GetKeys( stateVisualsToRemove );
1608 if( ! subState.empty() )
1610 const StylePtr* oldSubState = oldState->subStates.FindConst(subState);
1613 DictionaryKeys subStateVisualsToRemove;
1614 (*oldSubState)->visuals.GetKeys( subStateVisualsToRemove );
1615 Merge( stateVisualsToRemove, subStateVisualsToRemove );
1620 // Collect all new visual properties
1621 Dictionary<Property::Map> stateVisualsToAdd;
1624 stateVisualsToAdd = newState->visuals;
1625 if( ! subState.empty() )
1627 const StylePtr* newSubState = newState->subStates.FindConst(subState);
1630 stateVisualsToAdd.Merge( (*newSubState)->visuals );
1635 // If a name is in both add/remove, move it to change list.
1636 Dictionary<Property::Map> stateVisualsToChange;
1637 FindChangableVisuals( stateVisualsToAdd, stateVisualsToChange, stateVisualsToRemove);
1639 // Copy instanced properties (e.g. text label) of current visuals
1640 Dictionary<Property::Map> instancedProperties;
1641 CopyInstancedProperties( mVisuals, instancedProperties );
1643 // For each visual in remove list, remove from mVisuals
1644 RemoveVisuals( mVisuals, stateVisualsToRemove );
1646 // For each visual in add list, create and add to mVisuals
1647 Dali::CustomActor handle( mControlImpl.GetOwner() );
1648 Style::ApplyVisuals( handle, stateVisualsToAdd, instancedProperties );
1650 // For each visual in change list, if it requires a new visual,
1651 // remove old visual, create and add to mVisuals
1652 RecreateChangedVisuals( stateVisualsToChange, instancedProperties );
1655 void Control::Impl::SetState( DevelControl::State newState, bool withTransitions )
1657 DevelControl::State oldState = mState;
1658 Dali::CustomActor handle( mControlImpl.GetOwner() );
1659 DALI_LOG_INFO(gLogFilter, Debug::Concise, "Control::Impl::SetState: %s\n",
1660 (mState == DevelControl::NORMAL ? "NORMAL" :(
1661 mState == DevelControl::FOCUSED ?"FOCUSED" : (
1662 mState == DevelControl::DISABLED?"DISABLED":"NONE" ))));
1664 if( mState != newState )
1666 // If mState was Disabled, and new state is Focused, should probably
1667 // store that fact, e.g. in another property that FocusManager can access.
1670 // Trigger state change and transitions
1671 // Apply new style, if stylemanager is available
1672 Toolkit::StyleManager styleManager = Toolkit::StyleManager::Get();
1675 const StylePtr stylePtr = GetImpl( styleManager ).GetRecordedStyle( Toolkit::Control( mControlImpl.GetOwner() ) );
1679 std::string oldStateName = Scripting::GetEnumerationName< Toolkit::DevelControl::State >( oldState, ControlStateTable, ControlStateTableCount );
1680 std::string newStateName = Scripting::GetEnumerationName< Toolkit::DevelControl::State >( newState, ControlStateTable, ControlStateTableCount );
1682 const StylePtr* newStateStyle = stylePtr->subStates.Find( newStateName );
1683 const StylePtr* oldStateStyle = stylePtr->subStates.Find( oldStateName );
1684 if( oldStateStyle && newStateStyle )
1686 // Only change if both state styles exist
1687 ReplaceStateVisualsAndProperties( *oldStateStyle, *newStateStyle, mSubStateName );
1694 void Control::Impl::SetSubState( const std::string& subStateName, bool withTransitions )
1696 if( mSubStateName != subStateName )
1698 // Get existing sub-state visuals, and unregister them
1699 Dali::CustomActor handle( mControlImpl.GetOwner() );
1701 Toolkit::StyleManager styleManager = Toolkit::StyleManager::Get();
1704 const StylePtr stylePtr = GetImpl( styleManager ).GetRecordedStyle( Toolkit::Control( mControlImpl.GetOwner() ) );
1708 std::string stateName = Scripting::GetEnumerationName< Toolkit::DevelControl::State >( mState, ControlStateTable, ControlStateTableCount );
1710 const StylePtr* state = stylePtr->subStates.Find( stateName );
1713 StylePtr stateStyle(*state);
1715 const StylePtr* newStateStyle = stateStyle->subStates.Find( subStateName );
1716 const StylePtr* oldStateStyle = stateStyle->subStates.Find( mSubStateName );
1717 if( oldStateStyle && newStateStyle )
1720 ReplaceStateVisualsAndProperties( *oldStateStyle, *newStateStyle, empty );
1726 mSubStateName = subStateName;
1730 void Control::Impl::OnSceneDisconnection()
1732 Actor self = mControlImpl.Self();
1734 // Any visuals set for replacement but not yet ready should still be registered.
1735 // Reason: If a request was made to register a new visual but the control removed from scene before visual was ready
1736 // then when this control appears back on stage it should use that new visual.
1738 // Iterate through all registered visuals and set off scene
1739 SetVisualsOffScene( mVisuals, self );
1741 // Visuals pending replacement can now be taken out of the removal list and set off scene
1742 // Iterate through all replacement visuals and add to a move queue then set off scene
1743 for( auto removalIter = mRemoveVisuals.Begin(), end = mRemoveVisuals.End(); removalIter != end; removalIter++ )
1745 Toolkit::GetImplementation((*removalIter)->visual).SetOffScene( self );
1748 for( auto replacedIter = mVisuals.Begin(), end = mVisuals.End(); replacedIter != end; replacedIter++ )
1750 (*replacedIter)->pending = false;
1753 mRemoveVisuals.Clear();
1756 void Control::Impl::SetMargin( Extents margin )
1758 mControlImpl.mImpl->mMargin = margin;
1760 // Trigger a size negotiation request that may be needed when setting a margin.
1761 mControlImpl.RelayoutRequest();
1764 Extents Control::Impl::GetMargin() const
1766 return mControlImpl.mImpl->mMargin;
1769 void Control::Impl::SetPadding( Extents padding )
1771 mControlImpl.mImpl->mPadding = padding;
1773 // Trigger a size negotiation request that may be needed when setting a padding.
1774 mControlImpl.RelayoutRequest();
1777 Extents Control::Impl::GetPadding() const
1779 return mControlImpl.mImpl->mPadding;
1782 void Control::Impl::SetInputMethodContext( InputMethodContext& inputMethodContext )
1784 mInputMethodContext = inputMethodContext;
1787 bool Control::Impl::FilterKeyEvent( const KeyEvent& event )
1789 bool consumed ( false );
1791 if ( mInputMethodContext )
1793 consumed = mInputMethodContext.FilterEventKey( event );
1798 DevelControl::VisualEventSignalType& Control::Impl::VisualEventSignal()
1800 return mVisualEventSignal;
1803 void Control::Impl::SetShadow( const Property::Map& map )
1805 Toolkit::Visual::Base visual = Toolkit::VisualFactory::Get().CreateVisual( map );
1806 visual.SetName("shadow");
1810 mControlImpl.mImpl->RegisterVisual( Toolkit::DevelControl::Property::SHADOW, visual, DepthIndex::BACKGROUND_EFFECT );
1812 mControlImpl.RelayoutRequest();
1816 void Control::Impl::ClearShadow()
1818 mControlImpl.mImpl->UnregisterVisual( Toolkit::DevelControl::Property::SHADOW );
1820 // Trigger a size negotiation request that may be needed when unregistering a visual.
1821 mControlImpl.RelayoutRequest();
1824 void Control::Impl::EmitResourceReadySignal()
1826 if(!mIsEmittingResourceReadySignal)
1828 // Guard against calls to emit the signal during the callback
1829 mIsEmittingResourceReadySignal = true;
1831 // If the signal handler changes visual, it may become ready during this call & therefore this method will
1832 // get called again recursively. If so, mNeedToEmitResourceReady is set below, and we act on it after that secondary
1833 // invocation has completed by notifying in an Idle callback to prevent further recursion.
1834 Dali::Toolkit::Control handle(mControlImpl.GetOwner());
1835 mResourceReadySignal.Emit(handle);
1837 if(mNeedToEmitResourceReady)
1839 // Add idler to emit the signal again
1842 // The callback manager takes the ownership of the callback object.
1843 mIdleCallback = MakeCallback( this, &Control::Impl::OnIdleCallback);
1844 Adaptor::Get().AddIdle(mIdleCallback, false);
1848 mIsEmittingResourceReadySignal = false;
1852 mNeedToEmitResourceReady = true;
1856 void Control::Impl::OnIdleCallback()
1858 if(mNeedToEmitResourceReady)
1861 mNeedToEmitResourceReady = false;
1863 // A visual is ready so control may need relayouting if staged
1864 if(mControlImpl.Self().GetProperty<bool>(Actor::Property::CONNECTED_TO_SCENE))
1866 mControlImpl.RelayoutRequest();
1869 EmitResourceReadySignal();
1872 // Set the pointer to null as the callback manager deletes the callback after execute it.
1873 mIdleCallback = nullptr;
1876 Dali::Accessibility::Accessible *Control::Impl::GetAccessibilityObject()
1878 if( !accessibilityObject )
1879 accessibilityObject = accessibilityConstructor( mControlImpl.Self() );
1880 return accessibilityObject.get();
1883 Dali::Accessibility::Accessible *Control::Impl::GetAccessibilityObject(Dali::Actor actor)
1887 auto q = Dali::Toolkit::Control::DownCast( actor );
1890 auto q2 = static_cast< Internal::Control* >( &q.GetImplementation() );
1891 return q2->mImpl->GetAccessibilityObject();
1897 Control::Impl::AccessibleImpl::AccessibleImpl(Dali::Actor self, Dali::Accessibility::Role role, bool modal)
1898 : self(self), modal(modal)
1900 auto control = Dali::Toolkit::Control::DownCast(self);
1902 Internal::Control& internalControl = Toolkit::Internal::GetImplementation( control );
1903 Internal::Control::Impl& controlImpl = Internal::Control::Impl::Get( internalControl );
1904 if( controlImpl.mAccessibilityRole == Dali::Accessibility::Role::UNKNOWN )
1905 controlImpl.mAccessibilityRole = role;
1907 self.PropertySetSignal().Connect(&controlImpl, [this, &controlImpl](Dali::Handle &handle, Dali::Property::Index index, Dali::Property::Value value)
1909 if (this->self != Dali::Accessibility::Accessible::GetCurrentlyHighlightedActor())
1914 if (index == DevelControl::Property::ACCESSIBILITY_NAME
1915 || (index == GetNamePropertyIndex() && !controlImpl.mAccessibilityNameSet))
1917 if (controlImpl.mAccessibilityGetNameSignal.Empty())
1919 Emit(Dali::Accessibility::ObjectPropertyChangeEvent::NAME);
1923 if (index == DevelControl::Property::ACCESSIBILITY_DESCRIPTION
1924 || (index == GetDescriptionPropertyIndex() && !controlImpl.mAccessibilityDescriptionSet))
1926 if (controlImpl.mAccessibilityGetDescriptionSignal.Empty())
1928 Emit(Dali::Accessibility::ObjectPropertyChangeEvent::DESCRIPTION);
1934 std::string Control::Impl::AccessibleImpl::GetName()
1936 auto control = Dali::Toolkit::Control::DownCast(self);
1938 Internal::Control& internalControl = Toolkit::Internal::GetImplementation( control );
1939 Internal::Control::Impl& controlImpl = Internal::Control::Impl::Get( internalControl );
1941 if (!controlImpl.mAccessibilityGetNameSignal.Empty()) {
1943 controlImpl.mAccessibilityGetNameSignal.Emit(ret);
1947 if (controlImpl.mAccessibilityNameSet)
1948 return controlImpl.mAccessibilityName;
1950 if (auto raw = GetNameRaw(); !raw.empty())
1953 return self.GetProperty< std::string >( Actor::Property::NAME );
1956 std::string Control::Impl::AccessibleImpl::GetNameRaw()
1961 std::string Control::Impl::AccessibleImpl::GetDescription()
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.mAccessibilityGetDescriptionSignal.Empty()) {
1970 controlImpl.mAccessibilityGetDescriptionSignal.Emit(ret);
1974 if (controlImpl.mAccessibilityDescriptionSet)
1975 return controlImpl.mAccessibilityDescription;
1977 return GetDescriptionRaw();
1980 std::string Control::Impl::AccessibleImpl::GetDescriptionRaw()
1985 Dali::Accessibility::Accessible* Control::Impl::AccessibleImpl::GetParent()
1987 return Dali::Accessibility::Accessible::Get( self.GetParent() );
1990 size_t Control::Impl::AccessibleImpl::GetChildCount()
1992 return self.GetChildCount();
1995 Dali::Accessibility::Accessible* Control::Impl::AccessibleImpl::GetChildAtIndex( size_t index )
1997 return Dali::Accessibility::Accessible::Get( self.GetChildAt( static_cast< unsigned int >( index ) ) );
2000 size_t Control::Impl::AccessibleImpl::GetIndexInParent()
2003 auto parent = s.GetParent();
2004 DALI_ASSERT_ALWAYS( parent && "can't call GetIndexInParent on object without parent" );
2005 auto count = parent.GetChildCount();
2006 for( auto i = 0u; i < count; ++i )
2008 auto c = parent.GetChildAt( i );
2012 DALI_ASSERT_ALWAYS( false && "object isn't child of it's parent" );
2013 return static_cast<size_t>(-1);
2016 Dali::Accessibility::Role Control::Impl::AccessibleImpl::GetRole()
2018 return self.GetProperty<Dali::Accessibility::Role>( Toolkit::DevelControl::Property::ACCESSIBILITY_ROLE );
2021 Dali::Accessibility::States Control::Impl::AccessibleImpl::CalculateStates()
2023 Dali::Accessibility::States s;
2024 s[Dali::Accessibility::State::FOCUSABLE] = self.GetProperty< bool >( Actor::Property::KEYBOARD_FOCUSABLE );
2025 s[Dali::Accessibility::State::FOCUSED] = Toolkit::KeyboardFocusManager::Get().GetCurrentFocusActor() == self;
2026 if(self.GetProperty( Toolkit::DevelControl::Property::ACCESSIBILITY_HIGHLIGHTABLE ).GetType() == Property::NONE )
2027 s[Dali::Accessibility::State::HIGHLIGHTABLE] = false;
2029 s[Dali::Accessibility::State::HIGHLIGHTABLE] = self.GetProperty( Toolkit::DevelControl::Property::ACCESSIBILITY_HIGHLIGHTABLE ).Get< bool >();
2030 s[Dali::Accessibility::State::HIGHLIGHTED] = GetCurrentlyHighlightedActor() == self;
2031 s[Dali::Accessibility::State::ENABLED] = true;
2032 s[Dali::Accessibility::State::SENSITIVE] = true;
2033 s[Dali::Accessibility::State::ANIMATED] = self.GetProperty( Toolkit::DevelControl::Property::ACCESSIBILITY_ANIMATED ).Get< bool >();
2034 s[Dali::Accessibility::State::VISIBLE] = true;
2037 s[Dali::Accessibility::State::MODAL] = true;
2039 s[Dali::Accessibility::State::SHOWING] = !self.GetProperty( Dali::DevelActor::Property::CULLED ).Get< bool >()
2040 && self.GetCurrentProperty< bool >( Actor::Property::VISIBLE );
2042 s[Dali::Accessibility::State::DEFUNCT] = !self.GetProperty( Dali::DevelActor::Property::CONNECTED_TO_SCENE ).Get< bool >();
2046 Dali::Accessibility::States Control::Impl::AccessibleImpl::GetStates()
2048 return CalculateStates();
2051 Dali::Accessibility::Attributes Control::Impl::AccessibleImpl::GetAttributes()
2053 std::unordered_map< std::string, std::string > attribute_map;
2054 auto q = Dali::Toolkit::Control::DownCast( self );
2056 q.GetProperty( Dali::Toolkit::DevelControl::Property::ACCESSIBILITY_ATTRIBUTES );
2057 auto z = w.GetMap();
2061 auto map_size = z->Count();
2063 for( unsigned int i = 0; i < map_size; i++ )
2065 auto map_key = z->GetKeyAt( i );
2066 if( map_key.type == Property::Key::STRING )
2068 std::string map_value;
2069 if( z->GetValue( i ).Get( map_value ) )
2071 attribute_map.emplace( std::move( map_key.stringKey ),
2072 std::move( map_value ) );
2078 return attribute_map;
2081 Dali::Accessibility::ComponentLayer Control::Impl::AccessibleImpl::GetLayer()
2083 return Dali::Accessibility::ComponentLayer::WINDOW;
2086 Dali::Rect<> Control::Impl::AccessibleImpl::GetExtents( Dali::Accessibility::CoordType ctype )
2088 Vector2 screenPosition =
2089 self.GetProperty( Dali::DevelActor::Property::SCREEN_POSITION )
2091 auto size = self.GetCurrentProperty< Vector3 >( Actor::Property::SIZE ) * self.GetCurrentProperty< Vector3 >( Actor::Property::WORLD_SCALE );
2092 bool positionUsesAnchorPoint =
2093 self.GetProperty( Dali::DevelActor::Property::POSITION_USES_ANCHOR_POINT )
2095 Vector3 anchorPointOffSet =
2096 size * ( positionUsesAnchorPoint ? self.GetCurrentProperty< Vector3 >( Actor::Property::ANCHOR_POINT )
2097 : AnchorPoint::TOP_LEFT );
2098 Vector2 position = Vector2( screenPosition.x - anchorPointOffSet.x,
2099 screenPosition.y - anchorPointOffSet.y );
2101 return { position.x, position.y, size.x, size.y };
2104 int16_t Control::Impl::AccessibleImpl::GetMdiZOrder() { return 0; }
2105 double Control::Impl::AccessibleImpl::GetAlpha() { return 0; }
2107 bool Control::Impl::AccessibleImpl::GrabFocus()
2109 return Toolkit::KeyboardFocusManager::Get().SetCurrentFocusActor( self );
2112 static Dali::Actor CreateHighlightIndicatorActor()
2114 std::string focusBorderImagePath(AssetManager::GetDaliImagePath());
2115 focusBorderImagePath += "/keyboard_focus.9.png";
2116 // Create the default if it hasn't been set and one that's shared by all the
2117 // keyboard focusable actors
2118 auto actor = Toolkit::ImageView::New( focusBorderImagePath );
2119 actor.SetResizePolicy( ResizePolicy::FILL_TO_PARENT, Dimension::ALL_DIMENSIONS );
2120 DevelControl::AppendAccessibilityAttribute( actor, "highlight", "" );
2121 actor.SetProperty( Toolkit::DevelControl::Property::ACCESSIBILITY_ANIMATED, true);
2122 actor.SetProperty( Toolkit::DevelControl::Property::ACCESSIBILITY_HIGHLIGHTABLE, false );
2127 bool Control::Impl::AccessibleImpl::GrabHighlight()
2129 auto old = GetCurrentlyHighlightedActor();
2131 if( !Dali::Accessibility::IsUp() )
2137 auto c = dynamic_cast< Dali::Accessibility::Component* >( GetAccessibilityObject( old ) );
2139 c->ClearHighlight();
2141 auto highlight = GetHighlightActor();
2144 highlight = CreateHighlightIndicatorActor();
2145 SetHighlightActor( highlight );
2147 highlight.SetProperty( Actor::Property::PARENT_ORIGIN, ParentOrigin::CENTER );
2148 highlight.SetProperty( Actor::Property::ANCHOR_POINT, AnchorPoint::CENTER );
2149 highlight.SetProperty( Actor::Property::POSITION_Z, 1.0f );
2150 highlight.SetProperty( Actor::Property::POSITION, Vector2( 0.0f, 0.0f ));
2152 EnsureSelfVisible();
2153 self.Add( highlight );
2154 SetCurrentlyHighlightedActor( self );
2155 EmitHighlighted( true );
2162 bool Control::Impl::AccessibleImpl::ClearHighlight()
2164 if( !Dali::Accessibility::IsUp() )
2166 if( GetCurrentlyHighlightedActor() == self )
2168 self.Remove( GetHighlightActor() );
2169 SetCurrentlyHighlightedActor( {} );
2170 EmitHighlighted( false );
2176 std::string Control::Impl::AccessibleImpl::GetActionName( size_t index )
2178 if ( index >= GetActionCount() ) return "";
2179 Dali::TypeInfo type;
2180 self.GetTypeInfo( type );
2181 DALI_ASSERT_ALWAYS( type && "no TypeInfo object" );
2182 return type.GetActionName( index );
2184 std::string Control::Impl::AccessibleImpl::GetLocalizedActionName( size_t index )
2186 // TODO: add localization
2187 return GetActionName( index );
2189 std::string Control::Impl::AccessibleImpl::GetActionDescription( size_t index )
2193 size_t Control::Impl::AccessibleImpl::GetActionCount()
2195 Dali::TypeInfo type;
2196 self.GetTypeInfo( type );
2197 DALI_ASSERT_ALWAYS( type && "no TypeInfo object" );
2198 return type.GetActionCount();
2200 std::string Control::Impl::AccessibleImpl::GetActionKeyBinding( size_t index )
2204 bool Control::Impl::AccessibleImpl::DoAction( size_t index )
2206 std::string actionName = GetActionName( index );
2207 return self.DoAction( actionName, {} );
2209 bool Control::Impl::AccessibleImpl::DoAction(const std::string& name)
2211 return self.DoAction( name, {} );
2214 bool Control::Impl::AccessibleImpl::DoGesture(const Dali::Accessibility::GestureInfo &gestureInfo)
2216 auto control = Dali::Toolkit::Control::DownCast(self);
2218 Internal::Control& internalControl = Toolkit::Internal::GetImplementation( control );
2219 Internal::Control::Impl& controlImpl = Internal::Control::Impl::Get( internalControl );
2221 if (!controlImpl.mAccessibilityDoGestureSignal.Empty()) {
2222 auto ret = std::make_pair(gestureInfo, false);
2223 controlImpl.mAccessibilityDoGestureSignal.Emit(ret);
2230 std::vector<Dali::Accessibility::Relation> Control::Impl::AccessibleImpl::GetRelationSet()
2232 auto control = Dali::Toolkit::Control::DownCast(self);
2234 Internal::Control& internalControl = Toolkit::Internal::GetImplementation( control );
2235 Internal::Control::Impl& controlImpl = Internal::Control::Impl::Get( internalControl );
2237 std::vector<Dali::Accessibility::Relation> ret;
2239 auto &v = controlImpl.mAccessibilityRelations;
2240 for (auto i = 0u; i < v.size(); ++i)
2245 ret.emplace_back( Accessibility::Relation{ static_cast<Accessibility::RelationType>(i), v[i] } );
2251 void Control::Impl::AccessibleImpl::EnsureChildVisible(Actor child)
2255 void Control::Impl::AccessibleImpl::EnsureSelfVisible()
2257 auto parent = dynamic_cast<Control::Impl::AccessibleImpl*>(GetParent());
2260 parent->EnsureChildVisible(self);
2264 Property::Index Control::Impl::AccessibleImpl::GetNamePropertyIndex()
2266 return Actor::Property::NAME;
2269 Property::Index Control::Impl::AccessibleImpl::GetDescriptionPropertyIndex()
2271 return Property::INVALID_INDEX;
2274 void Control::Impl::PositionOrSizeChangedCallback( PropertyNotification &p )
2276 auto self = Dali::Actor::DownCast(p.GetTarget());
2277 if (Dali::Accessibility::IsUp() && !self.GetProperty( Toolkit::DevelControl::Property::ACCESSIBILITY_ANIMATED ).Get< bool >())
2279 auto extents = DevelActor::CalculateScreenExtents( self );
2280 Dali::Accessibility::Accessible::Get( self )->EmitBoundsChanged( extents );
2284 void Control::Impl::CulledChangedCallback( PropertyNotification &p)
2286 if (Dali::Accessibility::IsUp())
2288 auto self = Dali::Actor::DownCast(p.GetTarget());
2289 Dali::Accessibility::Accessible::Get(self)->EmitShowing( !self.GetProperty( DevelActor::Property::CULLED ).Get<bool>() );
2293 void Control::Impl::AccessibilityRegister()
2295 if (!accessibilityNotificationSet)
2297 accessibilityNotificationPosition = mControlImpl.Self().AddPropertyNotification( Actor::Property::POSITION, StepCondition( 0.01f ) );
2298 accessibilityNotificationPosition.SetNotifyMode( PropertyNotification::NOTIFY_ON_CHANGED );
2299 accessibilityNotificationPosition.NotifySignal().Connect( &Control::Impl::PositionOrSizeChangedCallback );
2301 accessibilityNotificationSize = mControlImpl.Self().AddPropertyNotification( Actor::Property::SIZE, StepCondition( 0.01f ) );
2302 accessibilityNotificationSize.SetNotifyMode( PropertyNotification::NOTIFY_ON_CHANGED );
2303 accessibilityNotificationSize.NotifySignal().Connect( &Control::Impl::PositionOrSizeChangedCallback );
2305 accessibilityNotificationCulled = mControlImpl.Self().AddPropertyNotification( DevelActor::Property::CULLED, LessThanCondition( 0.5f ) );
2306 accessibilityNotificationCulled.SetNotifyMode( PropertyNotification::NOTIFY_ON_CHANGED );
2307 accessibilityNotificationCulled.NotifySignal().Connect( &Control::Impl::CulledChangedCallback );
2309 accessibilityNotificationSet = true;
2313 void Control::Impl::AccessibilityDeregister()
2315 if (accessibilityNotificationSet)
2317 accessibilityNotificationPosition = {};
2318 accessibilityNotificationSize = {};
2319 accessibilityNotificationCulled = {};
2320 accessibilityNotificationSet = false;
2324 } // namespace Internal
2326 } // namespace Toolkit