X-Git-Url: http://review.tizen.org/git/?a=blobdiff_plain;f=dali-toolkit%2Finternal%2Fcontrols%2Fcontrol%2Fcontrol-data-impl.cpp;h=a837b7775e17ad3abbddb1d350ee9602d6ce46c9;hb=0cb97d2327cef87961e8c5203085294b6a4adfcb;hp=23f9204cd8e02b3dde13ffebbd568398faec6051;hpb=42b12368d0e630722a62c69ffd8dbcef96393d0d;p=platform%2Fcore%2Fuifw%2Fdali-toolkit.git diff --git a/dali-toolkit/internal/controls/control/control-data-impl.cpp b/dali-toolkit/internal/controls/control/control-data-impl.cpp index 23f9204..a837b77 100644 --- a/dali-toolkit/internal/controls/control/control-data-impl.cpp +++ b/dali-toolkit/internal/controls/control/control-data-impl.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2022 Samsung Electronics Co., Ltd. + * Copyright (c) 2023 Samsung Electronics Co., Ltd. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -52,12 +52,12 @@ namespace { -const std::string READING_INFO_TYPE_NAME = "name"; -const std::string READING_INFO_TYPE_ROLE = "role"; -const std::string READING_INFO_TYPE_DESCRIPTION = "description"; -const std::string READING_INFO_TYPE_STATE = "state"; -const std::string READING_INFO_TYPE_ATTRIBUTE_NAME = "reading_info_type"; -const std::string READING_INFO_TYPE_SEPARATOR = "|"; +const char* READING_INFO_TYPE_NAME = "name"; +const char* READING_INFO_TYPE_ROLE = "role"; +const char* READING_INFO_TYPE_DESCRIPTION = "description"; +const char* READING_INFO_TYPE_STATE = "state"; +const char* READING_INFO_TYPE_ATTRIBUTE_NAME = "reading_info_type"; +const char* READING_INFO_TYPE_SEPARATOR = "|"; } // namespace namespace Dali @@ -129,6 +129,38 @@ bool FindVisual(std::string visualName, const RegisteredVisualContainer& visuals return false; } +/** + * Finds visual in given array, returning true if found along with the iterator for that visual as a out parameter + */ +bool FindVisual(const Toolkit::Visual::Base findVisual, const RegisteredVisualContainer& visuals, RegisteredVisualContainer::Iterator& iter) +{ + for(iter = visuals.Begin(); iter != visuals.End(); iter++) + { + Toolkit::Visual::Base visual = (*iter)->visual; + if(visual && visual == findVisual) + { + return true; + } + } + return false; +} + +/** + * Finds internal visual in given array, returning true if found along with the iterator for that visual as a out parameter + */ +bool FindVisual(const Visual::Base& findInternalVisual, const RegisteredVisualContainer& visuals, RegisteredVisualContainer::Iterator& iter) +{ + for(iter = visuals.Begin(); iter != visuals.End(); iter++) + { + Visual::Base& visual = Toolkit::GetImplementation((*iter)->visual); + if((&visual == &findInternalVisual)) + { + return true; + } + } + return false; +} + void FindChangableVisuals(Dictionary& stateVisualsToAdd, Dictionary& stateVisualsToChange, DictionaryKeys& stateVisualsToRemove) @@ -201,6 +233,23 @@ void MoveVisual(RegisteredVisualContainer::Iterator sourceIter, RegisteredVisual } /** + * Discard visual from source to visual factory. + */ +void DiscardVisual(RegisteredVisualContainer::Iterator sourceIter, RegisteredVisualContainer& source) +{ + Toolkit::Visual::Base visual = (*sourceIter)->visual; + if(visual) + { + if(Stage::IsInstalled()) + { + Toolkit::VisualFactory::Get().DiscardVisual(visual); + } + } + + source.Erase(sourceIter); +} + +/** * Performs actions as requested using the action name. * @param[in] object The object on which to perform the action. * @param[in] actionName The action to perform. @@ -524,7 +573,7 @@ Control::Impl::Impl(Control& controlImpl) mIsKeyboardNavigationSupported(false), mIsKeyboardFocusGroup(false), mIsEmittingResourceReadySignal(false), - mNeedToEmitResourceReady(false), + mIdleCallbackRegistered(false), mDispatchKeyEvents(true) { Dali::Accessibility::Accessible::RegisterExternalAccessibleGetter(&ExternalAccessibleGetter); @@ -554,11 +603,15 @@ Control::Impl::~Impl() Control::Impl& Control::Impl::Get(Internal::Control& internalControl) { + DALI_ASSERT_ALWAYS(Stage::IsCoreThread() && "Core is not installed. Might call this API from worker thread?"); + return *internalControl.mImpl; } const Control::Impl& Control::Impl::Get(const Internal::Control& internalControl) { + DALI_ASSERT_ALWAYS(Stage::IsCoreThread() && "Core is not installed. Might call this API from worker thread?"); + return *internalControl.mImpl; } @@ -683,6 +736,8 @@ void Control::Impl::RegisterVisual(Property::Index index, Toolkit::Visual::Base& void Control::Impl::RegisterVisual(Property::Index index, Toolkit::Visual::Base& visual, VisualState::Type enabled, DepthIndexValue::Type depthIndexValueSet, int depthIndex) { + DALI_ASSERT_ALWAYS(Stage::IsCoreThread() && "Core is not installed. Might call this API from worker thread?"); + DALI_LOG_INFO(gLogFilter, Debug::Concise, "RegisterVisual:%d \n", index); bool visualReplaced(false); @@ -805,7 +860,7 @@ void Control::Impl::RegisterVisual(Property::Index index, Toolkit::Visual::Base& { visualImpl.SetOnScene(self); } - else if(visualImpl.IsResourceReady()) // When not being staged, check if visual already 'ResourceReady' before it was Registered. ( Resource may have been loaded already ) + else if(enabled && visualImpl.IsResourceReady()) // When not being staged, check if visual already 'ResourceReady' before it was Registered. ( Resource may have been loaded already ) { ResourceReady(visualImpl); } @@ -816,6 +871,8 @@ void Control::Impl::RegisterVisual(Property::Index index, Toolkit::Visual::Base& void Control::Impl::UnregisterVisual(Property::Index index) { + DALI_ASSERT_ALWAYS(Stage::IsCoreThread() && "Core is not installed. Might call this API from worker thread?"); + RegisteredVisualContainer::Iterator iter; if(FindVisual(index, mVisuals, iter)) { @@ -833,8 +890,9 @@ void Control::Impl::UnregisterVisual(Property::Index index) Actor self(mControlImpl.Self()); Toolkit::GetImplementation((*iter)->visual).SetOffScene(self); (*iter)->pending = false; - (*iter)->visual.Reset(); - mRemoveVisuals.Erase(iter); + + // Discard removed visual. It will be destroyed at next Idle time. + DiscardVisual(iter, mRemoveVisuals); } } @@ -894,6 +952,23 @@ bool Control::Impl::IsVisualEnabled(Property::Index index) const return false; } +void Control::Impl::EnableReadyTransitionOverriden(Toolkit::Visual::Base& visual, bool enable) +{ + DALI_LOG_INFO(gLogFilter, Debug::General, "Control::EnableReadyTransitionOverriden(%p, %s)\n", visual, enable ? "T" : "F"); + + RegisteredVisualContainer::Iterator iter; + if(FindVisual(visual, mVisuals, iter)) + { + if((*iter)->overideReadyTransition == enable) + { + DALI_LOG_INFO(gLogFilter, Debug::Verbose, "Control::EnableReadyTransitionOverriden Visual %s(%p) already %s\n", (*iter)->visual.GetName().c_str(), visual, enable ? "enabled" : "disabled"); + return; + } + + (*iter)->overideReadyTransition = enable; + } +} + void Control::Impl::StopObservingVisual(Toolkit::Visual::Base& visual) { Internal::Visual::Base& visualImpl = Toolkit::GetImplementation(visual); @@ -910,20 +985,13 @@ void Control::Impl::StartObservingVisual(Toolkit::Visual::Base& visual) visualImpl.AddEventObserver(*this); } -void Control::Impl::ResourceReady(bool relayoutRequest) +void Control::Impl::ResourceReady() { - Actor self = mControlImpl.Self(); - // A visual is ready so control may need relayouting if staged - if(relayoutRequest && self.GetProperty(Actor::Property::CONNECTED_TO_SCENE)) - { - mControlImpl.RelayoutRequest(); - } + DALI_ASSERT_ALWAYS(Stage::IsCoreThread() && "Core is not installed. Might call this API from worker thread?"); // Emit signal if all enabled visuals registered by the control are ready or there are no visuals. if(IsResourceReady()) { - // Reset the flag - mNeedToEmitResourceReady = false; EmitResourceReadySignal(); } } @@ -935,30 +1003,39 @@ void Control::Impl::ResourceReady(Visual::Base& object) Actor self = mControlImpl.Self(); + RegisteredVisualContainer::Iterator registeredIter; + // A resource is ready, find resource in the registered visuals container and get its index - for(auto registeredIter = mVisuals.Begin(), end = mVisuals.End(); registeredIter != end; ++registeredIter) + if(!FindVisual(object, mVisuals, registeredIter)) { - Internal::Visual::Base& registeredVisualImpl = Toolkit::GetImplementation((*registeredIter)->visual); + return; + } - if(&object == ®isteredVisualImpl) + RegisteredVisualContainer::Iterator visualToRemoveIter; + // Find visual with the same index in the removal container + // Set if off stage as it's replacement is now ready. + // Remove if from removal list as now removed from stage. + // Set Pending flag on the ready visual to false as now ready. + if(FindVisual((*registeredIter)->index, mRemoveVisuals, visualToRemoveIter)) + { + (*registeredIter)->pending = false; + if(!((*visualToRemoveIter)->overideReadyTransition)) { - RegisteredVisualContainer::Iterator visualToRemoveIter; - // Find visual with the same index in the removal container - // Set if off stage as it's replacement is now ready. - // Remove if from removal list as now removed from stage. - // Set Pending flag on the ready visual to false as now ready. - if(FindVisual((*registeredIter)->index, mRemoveVisuals, visualToRemoveIter)) - { - (*registeredIter)->pending = false; - Toolkit::GetImplementation((*visualToRemoveIter)->visual).SetOffScene(self); - mRemoveVisuals.Erase(visualToRemoveIter); - } - break; + Toolkit::GetImplementation((*visualToRemoveIter)->visual).SetOffScene(self); } + + // Discard removed visual. It will be destroyed at next Idle time. + DiscardVisual(visualToRemoveIter, mRemoveVisuals); } + // A visual is ready so control may need relayouting if staged + RelayoutRequest(object); + // Called by a Visual when it's resource is ready - ResourceReady(true); + if(((*registeredIter)->enabled)) + { + ResourceReady(); + } } void Control::Impl::NotifyVisualEvent(Visual::Base& object, Property::Index signalId) @@ -977,7 +1054,10 @@ void Control::Impl::NotifyVisualEvent(Visual::Base& object, Property::Index sign void Control::Impl::RelayoutRequest(Visual::Base& object) { - mControlImpl.RelayoutRequest(); + if(mControlImpl.Self().GetProperty(Actor::Property::CONNECTED_TO_SCENE)) + { + mControlImpl.RelayoutRequest(); + } } bool Control::Impl::IsResourceReady() const @@ -1127,6 +1207,8 @@ void Control::Impl::AppendAccessibilityAttribute(const std::string& key, const s void Control::Impl::SetProperty(BaseObject* object, Property::Index index, const Property::Value& value) { + DALI_ASSERT_ALWAYS(Stage::IsCoreThread() && "Core is not installed. Might call this API from worker thread?"); + Toolkit::Control control = Toolkit::Control::DownCast(BaseHandle(object)); if(control) @@ -1427,6 +1509,8 @@ void Control::Impl::SetProperty(BaseObject* object, Property::Index index, const Property::Value Control::Impl::GetProperty(BaseObject* object, Property::Index index) { + DALI_ASSERT_ALWAYS(Stage::IsCoreThread() && "Core is not installed. Might call this API from worker thread?"); + Property::Value value; Toolkit::Control control = Toolkit::Control::DownCast(BaseHandle(object)); @@ -1798,6 +1882,8 @@ void Control::Impl::RecreateChangedVisuals(Dictionary& stateVisua void Control::Impl::ReplaceStateVisualsAndProperties(const StylePtr oldState, const StylePtr newState, const std::string& subState) { + DALI_ASSERT_ALWAYS(Stage::IsCoreThread() && "Core is not installed. Might call this API from worker thread?"); + // Collect all old visual names DictionaryKeys stateVisualsToRemove; if(oldState) @@ -1935,17 +2021,25 @@ void Control::Impl::OnSceneDisconnection() // Visuals pending replacement can now be taken out of the removal list and set off scene // Iterate through all replacement visuals and add to a move queue then set off scene - for(auto removalIter = mRemoveVisuals.Begin(), end = mRemoveVisuals.End(); removalIter != end; removalIter++) + + if(!mRemoveVisuals.Empty()) { - Toolkit::GetImplementation((*removalIter)->visual).SetOffScene(self); + std::reverse(mRemoveVisuals.Begin(), mRemoveVisuals.End()); + + while(!mRemoveVisuals.Empty()) + { + auto removalIter = mRemoveVisuals.End() - 1u; + Toolkit::GetImplementation((*removalIter)->visual).SetOffScene(self); + + // Discard removed visual. It will be destroyed at next Idle time. + DiscardVisual(removalIter, mRemoveVisuals); + } } for(auto replacedIter = mVisuals.Begin(), end = mVisuals.End(); replacedIter != end; replacedIter++) { (*replacedIter)->pending = false; } - - mRemoveVisuals.Clear(); } void Control::Impl::SetMargin(Extents margin) @@ -2022,7 +2116,7 @@ Dali::Property Control::Impl::GetVisualProperty(Dali::Property::Index index, Dal if(visual) { Internal::Visual::Base& visualImpl = Toolkit::GetImplementation(visual); - return visualImpl.GetPropertyObject(visualPropertyKey); + return visualImpl.GetPropertyObject(std::move(visualPropertyKey)); } Handle handle; @@ -2080,48 +2174,51 @@ void Control::Impl::EmitResourceReadySignal() 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 + // get called again recursively. If so, mIdleCallbackRegistered 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) + mIsEmittingResourceReadySignal = false; + } + else + { + if(!mIdleCallbackRegistered) { + mIdleCallbackRegistered = true; + // 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); + Adaptor::Get().AddIdle(mIdleCallback, true); } } - - mIsEmittingResourceReadySignal = false; - } - else - { - mNeedToEmitResourceReady = true; } } -void Control::Impl::OnIdleCallback() +bool Control::Impl::OnIdleCallback() { - if(mNeedToEmitResourceReady) + // Reset the flag + mIdleCallbackRegistered = false; + + // A visual is ready so control may need relayouting if staged + if(mControlImpl.Self().GetProperty(Actor::Property::CONNECTED_TO_SCENE)) { - // Reset the flag - mNeedToEmitResourceReady = false; + mControlImpl.RelayoutRequest(); + } - // A visual is ready so control may need relayouting if staged - if(mControlImpl.Self().GetProperty(Actor::Property::CONNECTED_TO_SCENE)) - { - mControlImpl.RelayoutRequest(); - } + EmitResourceReadySignal(); - EmitResourceReadySignal(); + if(!mIdleCallbackRegistered) + { + // Set the pointer to null as the callback manager deletes the callback after execute it. + mIdleCallback = nullptr; } - // Set the pointer to null as the callback manager deletes the callback after execute it. - mIdleCallback = nullptr; + // Repeat idle if mIdleCallbackRegistered become true one more time. + return mIdleCallbackRegistered; } Toolkit::DevelControl::ControlAccessible* Control::Impl::GetAccessibleObject()