+DevelControl::VisualEventSignalType& Control::Impl::VisualEventSignal()
+{
+ return mVisualEventSignal;
+}
+
+void Control::Impl::SetShadow( const Property::Map& map )
+{
+ Toolkit::Visual::Base visual = Toolkit::VisualFactory::Get().CreateVisual( map );
+ visual.SetName("shadow");
+
+ if( visual )
+ {
+ mControlImpl.mImpl->RegisterVisual( Toolkit::DevelControl::Property::SHADOW, visual, DepthIndex::BACKGROUND_EFFECT );
+
+ mControlImpl.RelayoutRequest();
+ }
+}
+
+void Control::Impl::ClearShadow()
+{
+ mControlImpl.mImpl->UnregisterVisual( Toolkit::DevelControl::Property::SHADOW );
+
+ // Trigger a size negotiation request that may be needed when unregistering a visual.
+ mControlImpl.RelayoutRequest();
+}
+
+Dali::Property Control::Impl::GetVisualProperty(Dali::Property::Index index, Dali::Property::Key visualPropertyKey)
+{
+ Toolkit::Visual::Base visual = GetVisualByIndex(mVisuals, index);
+ if(visual)
+ {
+ Internal::Visual::Base& visualImpl = Toolkit::GetImplementation(visual);
+ return visualImpl.GetPropertyObject(visualPropertyKey);
+ }
+
+ Handle handle;
+ return Dali::Property(handle, Property::INVALID_INDEX);
+}
+
+void Control::Impl::EmitResourceReadySignal()
+{
+ if(!mIsEmittingResourceReadySignal)
+ {
+ // Guard against calls to emit the signal during the callback
+ mIsEmittingResourceReadySignal = true;
+
+ // If the signal handler changes visual, it may become ready during this call & therefore this method will
+ // get called again recursively. If so, mNeedToEmitResourceReady is set below, and we act on it after that secondary
+ // invocation has completed by notifying in an Idle callback to prevent further recursion.
+ Dali::Toolkit::Control handle(mControlImpl.GetOwner());
+ mResourceReadySignal.Emit(handle);
+
+ if(mNeedToEmitResourceReady)
+ {
+ // Add idler to emit the signal again
+ if(!mIdleCallback)
+ {
+ // The callback manager takes the ownership of the callback object.
+ mIdleCallback = MakeCallback( this, &Control::Impl::OnIdleCallback);
+ Adaptor::Get().AddIdle(mIdleCallback, false);
+ }
+ }
+
+ mIsEmittingResourceReadySignal = false;
+ }
+ else
+ {
+ mNeedToEmitResourceReady = true;
+ }
+}
+
+void Control::Impl::OnIdleCallback()
+{
+ if(mNeedToEmitResourceReady)
+ {
+ // Reset the flag
+ mNeedToEmitResourceReady = false;
+
+ // A visual is ready so control may need relayouting if staged
+ if(mControlImpl.Self().GetProperty<bool>(Actor::Property::CONNECTED_TO_SCENE))
+ {
+ mControlImpl.RelayoutRequest();
+ }
+
+ EmitResourceReadySignal();
+ }
+
+ // Set the pointer to null as the callback manager deletes the callback after execute it.
+ mIdleCallback = nullptr;
+}
+
+Dali::Accessibility::Accessible *Control::Impl::GetAccessibilityObject()
+{
+ if( !accessibilityObject )
+ accessibilityObject = accessibilityConstructor( mControlImpl.Self() );
+ return accessibilityObject.get();
+}
+
+Dali::Accessibility::Accessible *Control::Impl::GetAccessibilityObject(Dali::Actor actor)
+{
+ if( actor )
+ {
+ auto q = Dali::Toolkit::Control::DownCast( actor );
+ if( q )
+ {
+ auto q2 = static_cast< Internal::Control* >( &q.GetImplementation() );
+ return q2->mImpl->GetAccessibilityObject();
+ }
+ }
+ return nullptr;
+}
+
+Control::Impl::AccessibleImpl::AccessibleImpl(Dali::Actor self, Dali::Accessibility::Role role, bool modal)
+ : self(self), modal(modal)
+{
+ auto control = Dali::Toolkit::Control::DownCast(self);
+
+ Internal::Control& internalControl = Toolkit::Internal::GetImplementation( control );
+ Internal::Control::Impl& controlImpl = Internal::Control::Impl::Get( internalControl );
+ if( controlImpl.mAccessibilityRole == Dali::Accessibility::Role::UNKNOWN )
+ controlImpl.mAccessibilityRole = role;
+
+ self.PropertySetSignal().Connect(&controlImpl, [this, &controlImpl](Dali::Handle &handle, Dali::Property::Index index, Dali::Property::Value value)
+ {
+ if (this->self != Dali::Accessibility::Accessible::GetCurrentlyHighlightedActor())
+ {
+ return;
+ }
+
+ if (index == DevelControl::Property::ACCESSIBILITY_NAME
+ || (index == GetNamePropertyIndex() && !controlImpl.mAccessibilityNameSet))
+ {
+ if (controlImpl.mAccessibilityGetNameSignal.Empty())
+ {
+ Emit(Dali::Accessibility::ObjectPropertyChangeEvent::NAME);
+ }
+ }
+
+ if (index == DevelControl::Property::ACCESSIBILITY_DESCRIPTION
+ || (index == GetDescriptionPropertyIndex() && !controlImpl.mAccessibilityDescriptionSet))
+ {
+ if (controlImpl.mAccessibilityGetDescriptionSignal.Empty())
+ {
+ Emit(Dali::Accessibility::ObjectPropertyChangeEvent::DESCRIPTION);
+ }
+ }
+ });
+}
+
+std::string Control::Impl::AccessibleImpl::GetName()
+{
+ auto control = Dali::Toolkit::Control::DownCast(self);
+
+ Internal::Control& internalControl = Toolkit::Internal::GetImplementation( control );
+ Internal::Control::Impl& controlImpl = Internal::Control::Impl::Get( internalControl );
+
+ if (!controlImpl.mAccessibilityGetNameSignal.Empty()) {
+ std::string ret;
+ controlImpl.mAccessibilityGetNameSignal.Emit(ret);
+ return ret;
+ }
+
+ if (controlImpl.mAccessibilityNameSet)
+ return controlImpl.mAccessibilityName;
+
+ if (auto raw = GetNameRaw(); !raw.empty())
+ return raw;
+
+ return self.GetProperty< std::string >( Actor::Property::NAME );
+}
+
+std::string Control::Impl::AccessibleImpl::GetNameRaw()
+{
+ return {};
+}
+
+std::string Control::Impl::AccessibleImpl::GetDescription()
+{
+ auto control = Dali::Toolkit::Control::DownCast(self);
+
+ Internal::Control& internalControl = Toolkit::Internal::GetImplementation( control );
+ Internal::Control::Impl& controlImpl = Internal::Control::Impl::Get( internalControl );
+
+ if (!controlImpl.mAccessibilityGetDescriptionSignal.Empty()) {
+ std::string ret;
+ controlImpl.mAccessibilityGetDescriptionSignal.Emit(ret);
+ return ret;
+ }
+
+ if (controlImpl.mAccessibilityDescriptionSet)
+ return controlImpl.mAccessibilityDescription;
+
+ return GetDescriptionRaw();
+}
+
+std::string Control::Impl::AccessibleImpl::GetDescriptionRaw()
+{
+ return "";
+}
+
+Dali::Accessibility::Accessible* Control::Impl::AccessibleImpl::GetParent()
+{
+ return Dali::Accessibility::Accessible::Get( self.GetParent() );
+}
+
+size_t Control::Impl::AccessibleImpl::GetChildCount()
+{
+ return self.GetChildCount();
+}
+
+Dali::Accessibility::Accessible* Control::Impl::AccessibleImpl::GetChildAtIndex( size_t index )
+{
+ return Dali::Accessibility::Accessible::Get( self.GetChildAt( static_cast< unsigned int >( index ) ) );
+}
+
+size_t Control::Impl::AccessibleImpl::GetIndexInParent()
+{
+ auto s = self;
+ auto parent = s.GetParent();
+ DALI_ASSERT_ALWAYS( parent && "can't call GetIndexInParent on object without parent" );
+ auto count = parent.GetChildCount();
+ for( auto i = 0u; i < count; ++i )
+ {
+ auto c = parent.GetChildAt( i );
+ if( c == s )
+ return i;
+ }
+ DALI_ASSERT_ALWAYS( false && "object isn't child of it's parent" );
+ return static_cast<size_t>(-1);
+}
+
+Dali::Accessibility::Role Control::Impl::AccessibleImpl::GetRole()
+{
+ return self.GetProperty<Dali::Accessibility::Role>( Toolkit::DevelControl::Property::ACCESSIBILITY_ROLE );
+}
+
+Dali::Accessibility::States Control::Impl::AccessibleImpl::CalculateStates()
+{
+ Dali::Accessibility::States s;
+ s[Dali::Accessibility::State::FOCUSABLE] = self.GetProperty< bool >( Actor::Property::KEYBOARD_FOCUSABLE );
+ s[Dali::Accessibility::State::FOCUSED] = Toolkit::KeyboardFocusManager::Get().GetCurrentFocusActor() == self;
+ if(self.GetProperty( Toolkit::DevelControl::Property::ACCESSIBILITY_HIGHLIGHTABLE ).GetType() == Property::NONE )
+ s[Dali::Accessibility::State::HIGHLIGHTABLE] = false;
+ else
+ s[Dali::Accessibility::State::HIGHLIGHTABLE] = self.GetProperty( Toolkit::DevelControl::Property::ACCESSIBILITY_HIGHLIGHTABLE ).Get< bool >();
+ s[Dali::Accessibility::State::HIGHLIGHTED] = GetCurrentlyHighlightedActor() == self;
+ s[Dali::Accessibility::State::ENABLED] = true;
+ s[Dali::Accessibility::State::SENSITIVE] = true;
+ s[Dali::Accessibility::State::ANIMATED] = self.GetProperty( Toolkit::DevelControl::Property::ACCESSIBILITY_ANIMATED ).Get< bool >();
+ s[Dali::Accessibility::State::VISIBLE] = true;
+ if( modal )
+ {
+ s[Dali::Accessibility::State::MODAL] = true;
+ }
+ s[Dali::Accessibility::State::SHOWING] = !self.GetProperty( Dali::DevelActor::Property::CULLED ).Get< bool >()
+ && self.GetCurrentProperty< bool >( Actor::Property::VISIBLE );
+
+ s[Dali::Accessibility::State::DEFUNCT] = !self.GetProperty( Dali::DevelActor::Property::CONNECTED_TO_SCENE ).Get< bool >();
+ return s;
+}
+
+Dali::Accessibility::States Control::Impl::AccessibleImpl::GetStates()
+{
+ return CalculateStates();
+}
+
+Dali::Accessibility::Attributes Control::Impl::AccessibleImpl::GetAttributes()
+{
+ std::unordered_map< std::string, std::string > attribute_map;
+ auto q = Dali::Toolkit::Control::DownCast( self );
+ auto w =
+ q.GetProperty( Dali::Toolkit::DevelControl::Property::ACCESSIBILITY_ATTRIBUTES );
+ auto z = w.GetMap();
+
+ if( z )
+ {
+ auto map_size = z->Count();
+
+ for( unsigned int i = 0; i < map_size; i++ )
+ {
+ auto map_key = z->GetKeyAt( i );
+ if( map_key.type == Property::Key::STRING )
+ {
+ std::string map_value;
+ if( z->GetValue( i ).Get( map_value ) )
+ {
+ attribute_map.emplace( std::move( map_key.stringKey ),
+ std::move( map_value ) );
+ }
+ }
+ }
+ }
+
+ return attribute_map;
+}
+
+Dali::Accessibility::ComponentLayer Control::Impl::AccessibleImpl::GetLayer()
+{
+ return Dali::Accessibility::ComponentLayer::WINDOW;
+}
+
+Dali::Rect<> Control::Impl::AccessibleImpl::GetExtents( Dali::Accessibility::CoordType ctype )
+{
+ Vector2 screenPosition =
+ self.GetProperty( Dali::DevelActor::Property::SCREEN_POSITION )
+ .Get< Vector2 >();
+ auto size = self.GetCurrentProperty< Vector3 >( Actor::Property::SIZE ) * self.GetCurrentProperty< Vector3 >( Actor::Property::WORLD_SCALE );
+ bool positionUsesAnchorPoint =
+ self.GetProperty( Dali::DevelActor::Property::POSITION_USES_ANCHOR_POINT )
+ .Get< bool >();
+ Vector3 anchorPointOffSet =
+ size * ( positionUsesAnchorPoint ? self.GetCurrentProperty< Vector3 >( Actor::Property::ANCHOR_POINT )
+ : AnchorPoint::TOP_LEFT );
+ Vector2 position = Vector2( screenPosition.x - anchorPointOffSet.x,
+ screenPosition.y - anchorPointOffSet.y );
+
+ return { position.x, position.y, size.x, size.y };
+}
+
+int16_t Control::Impl::AccessibleImpl::GetMdiZOrder() { return 0; }
+double Control::Impl::AccessibleImpl::GetAlpha() { return 0; }
+
+bool Control::Impl::AccessibleImpl::GrabFocus()