// INTERNAL INCLUDES
#include <dali-toolkit/devel-api/asset-manager/asset-manager.h>
-#include <dali-toolkit/internal/controls/control/control-data-impl.h>
+#include <dali-toolkit/internal/controls/control/control-accessibility-data.h>
#include <dali-toolkit/internal/visuals/image/image-visual.h>
#include <dali-toolkit/public-api/controls/control-impl.h>
#include <dali-toolkit/public-api/controls/control.h>
Internal::Control::Impl& controlImpl = Internal::Control::Impl::Get(internalControl);
std::string name;
- if(!controlImpl.mAccessibilityGetNameSignal.Empty())
+ if(!controlImpl.mAccessibilityData->mAccessibilityGetNameSignal.Empty())
{
- controlImpl.mAccessibilityGetNameSignal.Emit(name);
+ controlImpl.mAccessibilityData->mAccessibilityGetNameSignal.Emit(name);
}
- else if(!controlImpl.mAccessibilityProps.name.empty())
+ else if(!controlImpl.mAccessibilityData->mAccessibilityProps.name.empty())
{
- name = controlImpl.mAccessibilityProps.name;
+ name = controlImpl.mAccessibilityData->mAccessibilityProps.name;
}
else if(auto raw = GetNameRaw(); !raw.empty())
{
Internal::Control::Impl& controlImpl = Internal::Control::Impl::Get(internalControl);
std::string description;
- if(!controlImpl.mAccessibilityGetDescriptionSignal.Empty())
+ if(!controlImpl.mAccessibilityData->mAccessibilityGetDescriptionSignal.Empty())
{
- controlImpl.mAccessibilityGetDescriptionSignal.Emit(description);
+ controlImpl.mAccessibilityData->mAccessibilityGetDescriptionSignal.Emit(description);
}
- else if(!controlImpl.mAccessibilityProps.description.empty())
+ else if(!controlImpl.mAccessibilityData->mAccessibilityProps.description.empty())
{
- description = controlImpl.mAccessibilityProps.description;
+ description = controlImpl.mAccessibilityData->mAccessibilityProps.description;
}
else
{
Internal::Control::Impl& controlImpl = Internal::Control::Impl::Get(internalControl);
// Apply states
- const auto& props = controlImpl.mAccessibilityProps;
+ const auto& props = controlImpl.mAccessibilityData->mAccessibilityProps;
states[State::ENABLED] = props.states[AccessibilityState::ENABLED];
states[State::SELECTED] = props.states[AccessibilityState::SELECTED];
states[State::CHECKED] = props.states[AccessibilityState::CHECKED];
Internal::Control& internalControl = Toolkit::Internal::GetImplementation(control);
Internal::Control::Impl& controlImpl = Internal::Control::Impl::Get(internalControl);
- return controlImpl.mAccessibilityProps.isHidden;
+ return controlImpl.mAccessibilityData->mAccessibilityProps.isHidden;
}
bool ControlAccessible::GrabFocus()
auto control = Dali::Toolkit::Control::DownCast(Self());
Internal::Control& internalControl = Toolkit::Internal::GetImplementation(control);
Internal::Control::Impl& controlImpl = Internal::Control::Impl::Get(internalControl);
- controlImpl.RegisterAccessibilityPositionPropertyNotification();
+ controlImpl.mAccessibilityData->RegisterAccessibilityPositionPropertyNotification();
}
void ControlAccessible::UnregisterPositionPropertyNotification()
auto control = Dali::Toolkit::Control::DownCast(Self());
Internal::Control& internalControl = Toolkit::Internal::GetImplementation(control);
Internal::Control::Impl& controlImpl = Internal::Control::Impl::Get(internalControl);
- controlImpl.UnregisterAccessibilityPositionPropertyNotification();
+ controlImpl.mAccessibilityData->UnregisterAccessibilityPositionPropertyNotification();
}
void ControlAccessible::RegisterPropertySetSignal()
auto control = Dali::Toolkit::Control::DownCast(Self());
Internal::Control& internalControl = Toolkit::Internal::GetImplementation(control);
Internal::Control::Impl& controlImpl = Internal::Control::Impl::Get(internalControl);
- controlImpl.RegisterAccessibilityPropertySetSignal();
+ controlImpl.mAccessibilityData->RegisterAccessibilityPropertySetSignal();
- mStatesSnapshot = controlImpl.mAccessibilityProps.states;
+ mStatesSnapshot = controlImpl.mAccessibilityData->mAccessibilityProps.states;
}
void ControlAccessible::UnregisterPropertySetSignal()
auto control = Dali::Toolkit::Control::DownCast(Self());
Internal::Control& internalControl = Toolkit::Internal::GetImplementation(control);
Internal::Control::Impl& controlImpl = Internal::Control::Impl::Get(internalControl);
- controlImpl.UnregisterAccessibilityPropertySetSignal();
+ controlImpl.mAccessibilityData->UnregisterAccessibilityPropertySetSignal();
mStatesSnapshot = {};
}
Internal::Control& internalControl = Toolkit::Internal::GetImplementation(control);
Internal::Control::Impl& controlImpl = Internal::Control::Impl::Get(internalControl);
- if(!controlImpl.mAccessibilityDoGestureSignal.Empty())
+ if(!controlImpl.mAccessibilityData->mAccessibilityDoGestureSignal.Empty())
{
auto ret = std::make_pair(gestureInfo, false);
- controlImpl.mAccessibilityDoGestureSignal.Emit(ret);
+ controlImpl.mAccessibilityData->mAccessibilityDoGestureSignal.Emit(ret);
return ret.second;
}
// INTERNAL INCLUDES
#include <dali-toolkit/devel-api/visual-factory/transition-data.h>
-#include <dali-toolkit/internal/controls/control/control-data-impl.h>
+#include <dali-toolkit/internal/controls/control/control-accessibility-data.h>
#include <dali-toolkit/public-api/controls/control-impl.h>
#include <dali-toolkit/public-api/controls/control.h>
Toolkit::DevelControl::AccessibilityActivateSignalType& AccessibilityActivateSignal(Toolkit::Control control)
{
- return GetControlImplementation(control).mAccessibilityActivateSignal;
+ return GetControlImplementation(control).mAccessibilityData->mAccessibilityActivateSignal;
}
Toolkit::DevelControl::AccessibilityReadingSkippedSignalType& AccessibilityReadingSkippedSignal(Toolkit::Control control)
{
- return GetControlImplementation(control).mAccessibilityReadingSkippedSignal;
+ return GetControlImplementation(control).mAccessibilityData->mAccessibilityReadingSkippedSignal;
}
Toolkit::DevelControl::AccessibilityReadingPausedSignalType& AccessibilityReadingPausedSignal(Toolkit::Control control)
{
- return GetControlImplementation(control).mAccessibilityReadingPausedSignal;
+ return GetControlImplementation(control).mAccessibilityData->mAccessibilityReadingPausedSignal;
}
Toolkit::DevelControl::AccessibilityReadingResumedSignalType& AccessibilityReadingResumedSignal(Toolkit::Control control)
{
- return GetControlImplementation(control).mAccessibilityReadingResumedSignal;
+ return GetControlImplementation(control).mAccessibilityData->mAccessibilityReadingResumedSignal;
}
Toolkit::DevelControl::AccessibilityReadingCancelledSignalType& AccessibilityReadingCancelledSignal(Toolkit::Control control)
{
- return GetControlImplementation(control).mAccessibilityReadingCancelledSignal;
+ return GetControlImplementation(control).mAccessibilityData->mAccessibilityReadingCancelledSignal;
}
Toolkit::DevelControl::AccessibilityReadingStoppedSignalType& AccessibilityReadingStoppedSignal(Toolkit::Control control)
{
- return GetControlImplementation(control).mAccessibilityReadingStoppedSignal;
+ return GetControlImplementation(control).mAccessibilityData->mAccessibilityReadingStoppedSignal;
}
Toolkit::DevelControl::AccessibilityGetNameSignalType& AccessibilityGetNameSignal(Toolkit::Control control)
{
- return GetControlImplementation(control).mAccessibilityGetNameSignal;
+ return GetControlImplementation(control).mAccessibilityData->mAccessibilityGetNameSignal;
}
Toolkit::DevelControl::AccessibilityGetDescriptionSignalType& AccessibilityGetDescriptionSignal(Toolkit::Control control)
{
- return GetControlImplementation(control).mAccessibilityGetDescriptionSignal;
+ return GetControlImplementation(control).mAccessibilityData->mAccessibilityGetDescriptionSignal;
}
Toolkit::DevelControl::AccessibilityDoGestureSignalType& AccessibilityDoGestureSignal(Toolkit::Control control)
{
- return GetControlImplementation(control).mAccessibilityDoGestureSignal;
+ return GetControlImplementation(control).mAccessibilityData->mAccessibilityDoGestureSignal;
}
Toolkit::DevelControl::AccessibilityActionSignalType& AccessibilityActionSignal(Toolkit::Control control)
{
- return GetControlImplementation(control).mAccessibilityActionSignal;
+ return GetControlImplementation(control).mAccessibilityData->mAccessibilityActionSignal;
}
void AppendAccessibilityRelation(Toolkit::Control control, Dali::Actor destination, Dali::Accessibility::RelationType relation)
{
if(auto destinationAccessible = Accessibility::Accessible::Get(destination))
{
- GetControlImplementation(control).mAccessibilityProps.relations[relation].insert(destinationAccessible);
+ GetControlImplementation(control).mAccessibilityData->mAccessibilityProps.relations[relation].insert(destinationAccessible);
}
}
{
if(auto destinationAccessible = Accessibility::Accessible::Get(destination))
{
- auto& relations = GetControlImplementation(control).mAccessibilityProps.relations;
+ auto& relations = GetControlImplementation(control).mAccessibilityData->mAccessibilityProps.relations;
relations[relation].erase(destinationAccessible);
std::vector<Accessibility::Relation> GetAccessibilityRelations(Toolkit::Control control)
{
- const auto& relations = GetControlImplementation(control).mAccessibilityProps.relations;
+ const auto& relations = GetControlImplementation(control).mAccessibilityData->mAccessibilityProps.relations;
std::vector<Accessibility::Relation> result;
for(auto& relation : relations)
void ClearAccessibilityRelations(Toolkit::Control control)
{
- GetControlImplementation(control).mAccessibilityProps.relations.clear();
+ GetControlImplementation(control).mAccessibilityData->mAccessibilityProps.relations.clear();
}
void AppendAccessibilityAttribute(Toolkit::Control control, const std::string& key, const std::string& value)
--- /dev/null
+/*
+ * Copyright (c) 2024 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.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+// CLASS HEADER
+#include "control-accessibility-data.h"
+
+// INTERNAL INCLUDES
+#include <dali/integration-api/debug.h>
+#include <dali/public-api/object/type-registry-helper.h>
+
+namespace Dali
+{
+namespace Toolkit
+{
+namespace Internal
+{
+namespace
+{
+static constexpr const char* READING_INFO_TYPE_NAME = "name";
+static constexpr const char* READING_INFO_TYPE_ATTRIBUTE_NAME = "reading_info_type";
+static constexpr const char* READING_INFO_TYPE_ROLE = "role";
+static constexpr const char* READING_INFO_TYPE_DESCRIPTION = "description";
+static constexpr const char* READING_INFO_TYPE_STATE = "state";
+static constexpr const char* READING_INFO_TYPE_SEPARATOR = "|";
+
+Dali::Rect<> GetShowingGeometry(Dali::Rect<> rect, Dali::Toolkit::DevelControl::ControlAccessible* accessible)
+{
+ Rect<> parentRect;
+ Vector2 currentPosition;
+ auto parent = dynamic_cast<Toolkit::DevelControl::ControlAccessible*>(accessible->GetParent());
+
+ while(parent)
+ {
+ parentRect = parent->GetExtents(Dali::Accessibility::CoordinateType::WINDOW);
+
+ currentPosition.x = rect.x;
+ currentPosition.y = rect.y;
+
+ rect.x = rect.x > parentRect.x ? rect.x : parentRect.x;
+ rect.y = rect.y > parentRect.y ? rect.y : parentRect.y;
+ rect.width = currentPosition.x + rect.width < parentRect.x + parentRect.width ? currentPosition.x + rect.width - rect.x : parentRect.x + parentRect.width - rect.x;
+ rect.height = currentPosition.y + rect.height < parentRect.y + parentRect.height ? currentPosition.y + rect.height - rect.y : parentRect.y + parentRect.height - rect.y;
+
+ if(rect.width < 0 || rect.height < 0)
+ {
+ return rect;
+ }
+
+ parent = dynamic_cast<Toolkit::DevelControl::ControlAccessible*>(parent->GetParent());
+ }
+
+ return rect;
+}
+static bool IsShowingGeometryOnScreen(Dali::Rect<> rect)
+{
+ return rect.width > 0 && rect.height > 0;
+}
+} // unnamed namespace
+
+Control::Impl::AccessibilityData::AccessibilityData(Control& controlImpl)
+: mAccessibilityGetNameSignal(),
+ mAccessibilityGetDescriptionSignal(),
+ mAccessibilityDoGestureSignal(),
+ mControlImpl(controlImpl),
+ mIsAccessibilityPositionPropertyNotificationSet(false),
+ mIsAccessibilityPropertySetSignalRegistered(false),
+ mAccessibleCreatable(true)
+{
+ Accessibility::Accessible::RegisterExternalAccessibleGetter([](Dali::Actor actor) -> std::pair<std::shared_ptr<Accessibility::Accessible>, bool> {
+ auto control = Toolkit::Control::DownCast(actor);
+ if(!control)
+ {
+ return {nullptr, true};
+ }
+
+ auto& controlImpl = Toolkit::Internal::GetImplementation(control);
+ if(controlImpl.mImpl->IsCreateAccessibleEnabled())
+ {
+ return {std::shared_ptr<DevelControl::ControlAccessible>(controlImpl.CreateAccessibleObject()), true};
+ }
+
+ return {nullptr, false};
+ });
+ mAccessibilityProps.states[DevelControl::AccessibilityState::ENABLED] = true;
+}
+
+void Control::Impl::AccessibilityData::AppendAccessibilityAttribute(const std::string& key, const std::string value)
+{
+ Property::Value* checkedValue = mAccessibilityProps.extraAttributes.Find(key);
+ if(checkedValue)
+ {
+ mAccessibilityProps.extraAttributes[key] = Property::Value(value);
+ }
+ else
+ {
+ mAccessibilityProps.extraAttributes.Insert(key, value);
+ }
+}
+
+void Control::Impl::AccessibilityData::CheckHighlightedObjectGeometry()
+{
+ auto accessible = GetAccessibleObject();
+ if(DALI_LIKELY(accessible))
+ {
+ auto lastPosition = accessible->GetLastPosition();
+ auto accessibleRect = accessible->GetExtents(Dali::Accessibility::CoordinateType::WINDOW);
+ auto rect = GetShowingGeometry(accessibleRect, accessible.get());
+
+ switch(mAccessibilityLastScreenRelativeMoveType)
+ {
+ case Dali::Accessibility::ScreenRelativeMoveType::OUTSIDE:
+ {
+ if(IsShowingGeometryOnScreen(rect))
+ {
+ mAccessibilityLastScreenRelativeMoveType = Dali::Accessibility::ScreenRelativeMoveType::INSIDE;
+ }
+ break;
+ }
+ case Dali::Accessibility::ScreenRelativeMoveType::INSIDE:
+ {
+ if(rect.width < 0 && !Dali::Equals(accessibleRect.x, lastPosition.x))
+ {
+ mAccessibilityLastScreenRelativeMoveType = (accessibleRect.x < lastPosition.x) ? Dali::Accessibility::ScreenRelativeMoveType::OUTGOING_TOP_LEFT : Dali::Accessibility::ScreenRelativeMoveType::OUTGOING_BOTTOM_RIGHT;
+ }
+ if(rect.height < 0 && !Dali::Equals(accessibleRect.y, lastPosition.y))
+ {
+ mAccessibilityLastScreenRelativeMoveType = (accessibleRect.y < lastPosition.y) ? Dali::Accessibility::ScreenRelativeMoveType::OUTGOING_TOP_LEFT : Dali::Accessibility::ScreenRelativeMoveType::OUTGOING_BOTTOM_RIGHT;
+ }
+ // notify AT-clients on outgoing moves only
+ if(mAccessibilityLastScreenRelativeMoveType != Dali::Accessibility::ScreenRelativeMoveType::INSIDE)
+ {
+ accessible->EmitMovedOutOfScreen(mAccessibilityLastScreenRelativeMoveType);
+ }
+ break;
+ }
+ case Dali::Accessibility::ScreenRelativeMoveType::OUTGOING_TOP_LEFT:
+ case Dali::Accessibility::ScreenRelativeMoveType::OUTGOING_BOTTOM_RIGHT:
+ {
+ if(IsShowingGeometryOnScreen(rect))
+ {
+ mAccessibilityLastScreenRelativeMoveType = Dali::Accessibility::ScreenRelativeMoveType::INSIDE;
+ }
+ else
+ {
+ mAccessibilityLastScreenRelativeMoveType = Dali::Accessibility::ScreenRelativeMoveType::OUTSIDE;
+ }
+ break;
+ }
+ default:
+ {
+ break;
+ }
+ }
+
+ accessible->SetLastPosition(Vector2(accessibleRect.x, accessibleRect.y));
+ }
+}
+
+void Control::Impl::AccessibilityData::RegisterAccessibilityPositionPropertyNotification()
+{
+ if(mIsAccessibilityPositionPropertyNotificationSet)
+ {
+ return;
+ }
+ // set default value until first move of object is detected
+ mAccessibilityLastScreenRelativeMoveType = Dali::Accessibility::ScreenRelativeMoveType::OUTSIDE;
+ // recalculate mAccessibilityLastScreenRelativeMoveType accordingly to the initial position
+ CheckHighlightedObjectGeometry();
+ mAccessibilityPositionNotification = mControlImpl.Self().AddPropertyNotification(Actor::Property::WORLD_POSITION, StepCondition(1.0f, 1.0f));
+ mAccessibilityPositionNotification.SetNotifyMode(PropertyNotification::NOTIFY_ON_CHANGED);
+ mAccessibilityPositionNotification.NotifySignal().Connect(this, [this](PropertyNotification&) { CheckHighlightedObjectGeometry(); });
+ mIsAccessibilityPositionPropertyNotificationSet = true;
+}
+
+void Control::Impl::AccessibilityData::UnregisterAccessibilityPositionPropertyNotification()
+{
+ mControlImpl.Self().RemovePropertyNotification(mAccessibilityPositionNotification);
+ mIsAccessibilityPositionPropertyNotificationSet = false;
+}
+
+void Control::Impl::AccessibilityData::RegisterAccessibilityPropertySetSignal()
+{
+ if(mIsAccessibilityPropertySetSignalRegistered)
+ {
+ return;
+ }
+ mControlImpl.Self().PropertySetSignal().Connect(this, &Control::Impl::AccessibilityData::OnAccessibilityPropertySet);
+ mIsAccessibilityPropertySetSignalRegistered = true;
+}
+
+void Control::Impl::AccessibilityData::UnregisterAccessibilityPropertySetSignal()
+{
+ if(!mIsAccessibilityPropertySetSignalRegistered)
+ {
+ return;
+ }
+ mControlImpl.Self().PropertySetSignal().Disconnect(this, &Control::Impl::AccessibilityData::OnAccessibilityPropertySet);
+ mIsAccessibilityPropertySetSignalRegistered = false;
+}
+
+void Control::Impl::AccessibilityData::OnAccessibilityPropertySet(Dali::Handle& handle, Dali::Property::Index index, const Dali::Property::Value& value)
+{
+ auto accessible = GetAccessibleObject();
+ if(DALI_LIKELY(accessible))
+ {
+ if(mAccessibilityGetNameSignal.Empty())
+ {
+ if(index == DevelControl::Property::ACCESSIBILITY_NAME || (mAccessibilityProps.name.empty() && index == accessible->GetNamePropertyIndex()))
+ {
+ accessible->Emit(Dali::Accessibility::ObjectPropertyChangeEvent::NAME);
+ return;
+ }
+ }
+
+ if(mAccessibilityGetDescriptionSignal.Empty())
+ {
+ if(index == DevelControl::Property::ACCESSIBILITY_DESCRIPTION || (mAccessibilityProps.description.empty() && index == accessible->GetDescriptionPropertyIndex()))
+ {
+ accessible->Emit(Dali::Accessibility::ObjectPropertyChangeEvent::DESCRIPTION);
+ return;
+ }
+ }
+
+ if(index == DevelControl::Property::ACCESSIBILITY_VALUE)
+ {
+ accessible->Emit(Dali::Accessibility::ObjectPropertyChangeEvent::VALUE);
+ return;
+ }
+
+ if(index == DevelControl::Property::ACCESSIBILITY_STATES)
+ {
+ accessible->OnStatePropertySet(mAccessibilityProps.states);
+ return;
+ }
+ }
+}
+
+Dali::Accessibility::ReadingInfoTypes Control::Impl::AccessibilityData::GetAccessibilityReadingInfoType() const
+{
+ std::string value{};
+ auto place = mAccessibilityProps.extraAttributes.Find(READING_INFO_TYPE_ATTRIBUTE_NAME);
+ if(place)
+ {
+ place->Get(value);
+ }
+ else
+ {
+ Dali::Accessibility::ReadingInfoTypes types;
+ types[Dali::Accessibility::ReadingInfoType::NAME] = true;
+ types[Dali::Accessibility::ReadingInfoType::ROLE] = true;
+ types[Dali::Accessibility::ReadingInfoType::DESCRIPTION] = true;
+ types[Dali::Accessibility::ReadingInfoType::STATE] = true;
+ return types;
+ }
+
+ if(value.empty())
+ {
+ return {};
+ }
+
+ Dali::Accessibility::ReadingInfoTypes types;
+
+ if(value.find(READING_INFO_TYPE_NAME) != std::string::npos)
+ {
+ types[Dali::Accessibility::ReadingInfoType::NAME] = true;
+ }
+ if(value.find(READING_INFO_TYPE_ROLE) != std::string::npos)
+ {
+ types[Dali::Accessibility::ReadingInfoType::ROLE] = true;
+ }
+ if(value.find(READING_INFO_TYPE_DESCRIPTION) != std::string::npos)
+ {
+ types[Dali::Accessibility::ReadingInfoType::DESCRIPTION] = true;
+ }
+ if(value.find(READING_INFO_TYPE_STATE) != std::string::npos)
+ {
+ types[Dali::Accessibility::ReadingInfoType::STATE] = true;
+ }
+
+ return types;
+}
+
+void Control::Impl::AccessibilityData::RemoveAccessibilityAttribute(const std::string& key)
+{
+ Property::Value* value = mAccessibilityProps.extraAttributes.Find(key);
+ if(value)
+ {
+ mAccessibilityProps.extraAttributes[key] = Property::Value();
+ }
+}
+
+void Control::Impl::AccessibilityData::ClearAccessibilityAttributes()
+{
+ mAccessibilityProps.extraAttributes.Clear();
+}
+
+void Control::Impl::AccessibilityData::SetAccessibilityReadingInfoType(const Dali::Accessibility::ReadingInfoTypes types)
+{
+ std::string value{};
+ if(types[Dali::Accessibility::ReadingInfoType::NAME])
+ {
+ value += READING_INFO_TYPE_NAME;
+ }
+ if(types[Dali::Accessibility::ReadingInfoType::ROLE])
+ {
+ if(!value.empty())
+ {
+ value += READING_INFO_TYPE_SEPARATOR;
+ }
+ value += READING_INFO_TYPE_ROLE;
+ }
+ if(types[Dali::Accessibility::ReadingInfoType::DESCRIPTION])
+ {
+ if(!value.empty())
+ {
+ value += READING_INFO_TYPE_SEPARATOR;
+ }
+ value += READING_INFO_TYPE_DESCRIPTION;
+ }
+ if(types[Dali::Accessibility::ReadingInfoType::STATE])
+ {
+ if(!value.empty())
+ {
+ value += READING_INFO_TYPE_SEPARATOR;
+ }
+ value += READING_INFO_TYPE_STATE;
+ }
+ AppendAccessibilityAttribute(READING_INFO_TYPE_ATTRIBUTE_NAME, value);
+}
+
+std::shared_ptr<Toolkit::DevelControl::ControlAccessible> Control::Impl::AccessibilityData::GetAccessibleObject()
+{
+ return std::dynamic_pointer_cast<DevelControl::ControlAccessible>(Accessibility::Accessible::GetOwningPtr(mControlImpl.Self()));
+}
+
+bool Control::Impl::AccessibilityData::IsAccessibleCreated() const
+{
+ return !!Accessibility::Bridge::GetCurrentBridge()->GetAccessible(mControlImpl.Self());
+}
+
+void Control::Impl::AccessibilityData::EnableCreateAccessible(bool enable)
+{
+ mAccessibleCreatable = enable;
+}
+
+bool Control::Impl::AccessibilityData::IsCreateAccessibleEnabled() const
+{
+ return mAccessibleCreatable;
+}
+
+} // namespace Internal
+} // namespace Toolkit
+} // namespace Dali
--- /dev/null
+#ifndef DALI_TOOLKIT_CONTROL_ACCESSIBILITY_DATA_H
+#define DALI_TOOLKIT_CONTROL_ACCESSIBILITY_DATA_H
+
+/*
+ * Copyright (c) 2024 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.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+// INTERNAL INCLUDES
+#include <dali-toolkit/devel-api/controls/control-devel.h>
+#include <dali-toolkit/internal/controls/control/control-data-impl.h>
+
+namespace Dali
+{
+namespace Toolkit
+{
+namespace Internal
+{
+// private inner class
+class Control::Impl::AccessibilityData : public ConnectionTracker
+{
+ friend class Toolkit::DevelControl::ControlAccessible;
+
+public:
+ // Constructor
+ AccessibilityData(Control& controlImpl);
+
+ /**
+ * @copydoc Dali::Toolkit::Internal::Control::Impl::AppendAccessibilityAttribute()
+ */
+ void AppendAccessibilityAttribute(const std::string& key, const std::string value);
+
+ /**
+ * @copydoc Dali::Toolkit::Internal::Control::Impl::RemoveAccessibilityAttribute()
+ */
+ void RemoveAccessibilityAttribute(const std::string& key);
+
+ /**
+ * @copydoc Dali::Toolkit::Internal::Control::Impl::ClearAccessibilityAttributes()
+ */
+ void ClearAccessibilityAttributes();
+
+ /**
+ * @copydoc Dali::Toolkit::Internal::Control::Impl::SetAccessibilityReadingInfoType()
+ */
+ void SetAccessibilityReadingInfoType(const Dali::Accessibility::ReadingInfoTypes types);
+
+ /**
+ * @copydoc Dali::Toolkit::Internal::Control::Impl::GetAccessibilityReadingInfoType()
+ */
+ Dali::Accessibility::ReadingInfoTypes GetAccessibilityReadingInfoType() const;
+
+ /**
+ * @copydoc Dali::Toolkit::Internal::Control::Impl::CheckHighlightedObjectGeometry()
+ */
+ void CheckHighlightedObjectGeometry();
+
+ /**
+ * @copydoc Dali::Toolkit::Internal::Control::Impl::RegisterAccessibilityPositionPropertyNotification()
+ */
+ void RegisterAccessibilityPositionPropertyNotification();
+
+ /**
+ * @copydoc Dali::Toolkit::Internal::Control::Impl::UnregisterAccessibilityPositionPropertyNotification()
+ */
+ void UnregisterAccessibilityPositionPropertyNotification();
+
+ /**
+ * @copydoc Dali::Toolkit::Internal::Control::Impl::RegisterAccessibilityPropertySetSignal()
+ */
+ void RegisterAccessibilityPropertySetSignal();
+
+ /**
+ * @copydoc Dali::Toolkit::Internal::Control::Impl::UnregisterAccessibilityPropertySetSignal()
+ */
+ void UnregisterAccessibilityPropertySetSignal();
+
+ /**
+ * @copydoc Dali::Toolkit::Internal::Control::Impl::OnAccessibilityPropertySet()
+ */
+ void OnAccessibilityPropertySet(Dali::Handle& handle, Dali::Property::Index index, const Dali::Property::Value& value);
+
+ /**
+ * @copydoc Dali::Toolkit::Internal::Control::Impl::GetAccessibleObject()
+ */
+ std::shared_ptr<Toolkit::DevelControl::ControlAccessible> GetAccessibleObject();
+
+ /**
+ * @copydoc Dali::Toolkit::Internal::Control::Impl::IsAccessibleCreated()
+ */
+ bool IsAccessibleCreated() const;
+
+ /**
+ * @copydoc Dali::Toolkit::Internal::Control::Impl::EnableCreateAccessible()
+ */
+ void EnableCreateAccessible(bool enable);
+
+ /**
+ * @copydoc Dali::Toolkit::Internal::Control::Impl::IsCreateAccessibleEnabled()
+ */
+ bool IsCreateAccessibleEnabled() const;
+
+public:
+ Toolkit::DevelControl::AccessibilityActivateSignalType mAccessibilityActivateSignal;
+ Toolkit::DevelControl::AccessibilityReadingSkippedSignalType mAccessibilityReadingSkippedSignal;
+ Toolkit::DevelControl::AccessibilityReadingPausedSignalType mAccessibilityReadingPausedSignal;
+ Toolkit::DevelControl::AccessibilityReadingResumedSignalType mAccessibilityReadingResumedSignal;
+ Toolkit::DevelControl::AccessibilityReadingCancelledSignalType mAccessibilityReadingCancelledSignal;
+ Toolkit::DevelControl::AccessibilityReadingStoppedSignalType mAccessibilityReadingStoppedSignal;
+
+ Toolkit::DevelControl::AccessibilityGetNameSignalType mAccessibilityGetNameSignal;
+ Toolkit::DevelControl::AccessibilityGetDescriptionSignalType mAccessibilityGetDescriptionSignal;
+ Toolkit::DevelControl::AccessibilityDoGestureSignalType mAccessibilityDoGestureSignal;
+
+ Toolkit::DevelControl::AccessibilityActionSignalType mAccessibilityActionSignal;
+
+ struct AccessibilityProps
+ {
+ std::string name{};
+ std::string description{};
+ std::string value{};
+ std::string automationId{};
+ int32_t role{static_cast<int32_t>(DevelControl::AccessibilityRole::NONE)};
+ DevelControl::AccessibilityStates states{};
+ std::map<Dali::Accessibility::RelationType, std::set<Accessibility::Accessible*>> relations;
+ Property::Map extraAttributes{};
+ TriStateProperty isHighlightable{TriStateProperty::AUTO};
+ bool isHidden{false};
+ bool isScrollable{false};
+ bool isModal{false};
+ } mAccessibilityProps;
+
+private:
+ // Accessibility - notification for highlighted object to check if it is showing.
+ Dali::PropertyNotification mAccessibilityPositionNotification;
+ Dali::Accessibility::ScreenRelativeMoveType mAccessibilityLastScreenRelativeMoveType{Accessibility::ScreenRelativeMoveType::OUTSIDE};
+
+ Control& mControlImpl;
+
+ bool mIsAccessibilityPositionPropertyNotificationSet : 1;
+ bool mIsAccessibilityPropertySetSignalRegistered : 1;
+ bool mAccessibleCreatable : 1;
+};
+} // namespace Internal
+} // namespace Toolkit
+} // namespace Dali
+#endif // DALI_TOOLKIT_CONTROL_ACCESSIBILITY_DATA_H
// CLASS HEADER
#include "control-data-impl.h"
+#include "control-accessibility-data.h"
+#include "control-visual-data.h"
// EXTERNAL INCLUDES
#include <dali-toolkit/public-api/controls/control-impl.h>
#include <dali-toolkit/devel-api/controls/control-depth-index-ranges.h>
#include <dali-toolkit/devel-api/controls/control-devel.h>
#include <dali-toolkit/devel-api/controls/control-wrapper-impl.h>
-#include <dali-toolkit/devel-api/visuals/visual-actions-devel.h>
+#include <dali-toolkit/devel-api/visual-factory/visual-factory.h>
#include <dali-toolkit/internal/styling/style-manager-impl.h>
+#include <dali-toolkit/internal/visuals/transition-data-impl.h>
#include <dali-toolkit/internal/visuals/visual-base-impl.h>
-#include <dali-toolkit/internal/visuals/visual-string-constants.h>
-#include <dali-toolkit/public-api/align-enumerations.h>
#include <dali-toolkit/public-api/controls/image-view/image-view.h>
#include <dali-toolkit/public-api/focus-manager/keyboard-focus-manager.h>
-#include <dali-toolkit/public-api/visuals/image-visual-properties.h>
-#include <dali-toolkit/public-api/visuals/visual-properties.h>
-
-namespace
-{
-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
{
{"DISABLED", Toolkit::DevelControl::DISABLED},
};
const unsigned int ControlStateTableCount = sizeof(ControlStateTable) / sizeof(ControlStateTable[0]);
-const Vector4 FULL_TEXTURE_RECT(0.f, 0.f, 1.f, 1.f);
namespace
{
#if defined(DEBUG_ENABLED)
-Debug::Filter* gLogFilter = Debug::Filter::New(Debug::NoLogging, false, "LOG_CONTROL_VISUALS");
+Debug::Filter* gLogFilter = Debug::Filter::New(Debug::NoLogging, false, "LOG_CONTROL_DATA");
#endif
-template<typename T>
-void Remove(Dictionary<T>& keyValues, const std::string& name)
-{
- keyValues.Remove(name);
-}
-
-void Remove(DictionaryKeys& keys, const std::string& name)
-{
- DictionaryKeys::iterator iter = std::find(keys.begin(), keys.end(), name);
- if(iter != keys.end())
- {
- keys.erase(iter);
- }
-}
-
-/**
- * Finds visual in given array, returning true if found along with the iterator for that visual as a out parameter
- */
-bool FindVisual(Property::Index targetIndex, const RegisteredVisualContainer& visuals, RegisteredVisualContainer::Iterator& iter)
-{
- for(iter = visuals.Begin(); iter != visuals.End(); iter++)
- {
- if((*iter)->index == targetIndex)
- {
- return true;
- }
- }
- return false;
-}
-
-/**
- * Finds visual in given array, returning true if found along with the iterator for that visual as a out parameter
- */
-bool FindVisual(std::string visualName, const RegisteredVisualContainer& visuals, RegisteredVisualContainer::Iterator& iter)
-{
- for(iter = visuals.Begin(); iter != visuals.End(); iter++)
- {
- Toolkit::Visual::Base visual = (*iter)->visual;
- if(visual && visual.GetName() == visualName)
- {
- return true;
- }
- }
- 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<Property::Map>& stateVisualsToAdd,
- Dictionary<Property::Map>& stateVisualsToChange,
- DictionaryKeys& stateVisualsToRemove)
-{
- DictionaryKeys copyOfStateVisualsToRemove = stateVisualsToRemove;
-
- for(DictionaryKeys::iterator iter = copyOfStateVisualsToRemove.begin();
- iter != copyOfStateVisualsToRemove.end();
- ++iter)
- {
- const std::string& visualName = (*iter);
- Property::Map* toMap = stateVisualsToAdd.Find(visualName);
- if(toMap)
- {
- stateVisualsToChange.Add(visualName, *toMap);
- stateVisualsToAdd.Remove(visualName);
- Remove(stateVisualsToRemove, visualName);
- }
- }
-}
-
-Toolkit::Visual::Base GetVisualByName(
- const RegisteredVisualContainer& visuals,
- const std::string& visualName)
-{
- Toolkit::Visual::Base visualHandle;
-
- RegisteredVisualContainer::Iterator iter;
- for(iter = visuals.Begin(); iter != visuals.End(); iter++)
- {
- Toolkit::Visual::Base visual = (*iter)->visual;
- if(visual && visual.GetName() == visualName)
- {
- visualHandle = visual;
- break;
- }
- }
- return visualHandle;
-}
-
-Toolkit::Visual::Base GetVisualByIndex(
- const RegisteredVisualContainer& visuals,
- Property::Index index)
-{
- Toolkit::Visual::Base visualHandle;
-
- RegisteredVisualContainer::Iterator iter;
- for(iter = visuals.Begin(); iter != visuals.End(); iter++)
- {
- if((*iter)->index == index)
- {
- visualHandle = (*iter)->visual;
- break;
- }
- }
- return visualHandle;
-}
-
-/**
- * Move visual from source to destination container
- */
-void MoveVisual(RegisteredVisualContainer::Iterator sourceIter, RegisteredVisualContainer& source, RegisteredVisualContainer& destination)
-{
- Toolkit::Visual::Base visual = (*sourceIter)->visual;
- if(visual)
- {
- RegisteredVisual* rv = source.Release(sourceIter);
- destination.PushBack(rv);
- }
-}
-
-/**
- * Discard visual from source to visual factory.
- */
-void DiscardVisual(RegisteredVisualContainer::Iterator sourceIter, RegisteredVisualContainer& source)
-{
- Toolkit::Visual::Base visual = (*sourceIter)->visual;
- if(visual)
- {
- if(DALI_LIKELY(Dali::Adaptor::IsAvailable()))
- {
- 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.
return PerformLegacyAccessibilityAction(control, actionName);
}
-/**
- * Connects a callback function with the object's signals.
- * @param[in] object The object providing the signal.
- * @param[in] tracker Used to disconnect the signal.
- * @param[in] signalName The signal to connect to.
- * @param[in] functor A newly allocated FunctorDelegate.
- * @return True if the signal was connected.
- * @post If a signal was connected, ownership of functor was passed to CallbackBase. Otherwise the caller is responsible for deleting the unused functor.
- */
const char* SIGNAL_KEY_EVENT = "keyEvent";
const char* SIGNAL_KEY_INPUT_FOCUS_GAINED = "keyInputFocusGained";
const char* SIGNAL_KEY_INPUT_FOCUS_LOST = "keyInputFocusLost";
const char* SIGNAL_GET_NAME = "getName";
const char* SIGNAL_GET_DESCRIPTION = "getDescription";
const char* SIGNAL_DO_GESTURE = "doGesture";
+
+/**
+ * Connects a callback function with the object's signals.
+ * @param[in] object The object providing the signal.
+ * @param[in] tracker Used to disconnect the signal.
+ * @param[in] signalName The signal to connect to.
+ * @param[in] functor A newly allocated FunctorDelegate.
+ * @return True if the signal was connected.
+ * @post If a signal was connected, ownership of functor was passed to CallbackBase. Otherwise the caller is responsible for deleting the unused functor.
+ */
static bool DoConnectSignal(BaseObject* object, ConnectionTrackerInterface* tracker, const std::string& signalName, FunctorDelegate* functor)
{
Dali::BaseHandle handle(object);
DALI_TYPE_REGISTRATION_END()
-/**
- * @brief Iterate through given container and setOffScene any visual found
- *
- * @param[in] container Container of visuals
- * @param[in] parent Parent actor to remove visuals from
- */
-void SetVisualsOffScene(const RegisteredVisualContainer& container, Actor parent)
-{
- for(auto iter = container.Begin(), end = container.End(); iter != end; iter++)
- {
- if((*iter)->visual)
- {
- DALI_LOG_INFO(gLogFilter, Debug::Verbose, "Control::SetOffScene Setting visual(%d) off stage\n", (*iter)->index);
- Toolkit::GetImplementation((*iter)->visual).SetOffScene(parent);
- }
- }
-}
-
-Dali::Rect<> GetShowingGeometry(Dali::Rect<> rect, Dali::Toolkit::DevelControl::ControlAccessible* accessible)
-{
- Rect<> parentRect;
- Vector2 currentPosition;
- auto parent = dynamic_cast<Toolkit::DevelControl::ControlAccessible*>(accessible->GetParent());
-
- while(parent)
- {
- parentRect = parent->GetExtents(Dali::Accessibility::CoordinateType::WINDOW);
-
- currentPosition.x = rect.x;
- currentPosition.y = rect.y;
-
- rect.x = rect.x > parentRect.x ? rect.x : parentRect.x;
- rect.y = rect.y > parentRect.y ? rect.y : parentRect.y;
- rect.width = currentPosition.x + rect.width < parentRect.x + parentRect.width ? currentPosition.x + rect.width - rect.x : parentRect.x + parentRect.width - rect.x;
- rect.height = currentPosition.y + rect.height < parentRect.y + parentRect.height ? currentPosition.y + rect.height - rect.y : parentRect.y + parentRect.height - rect.y;
-
- if(rect.width < 0 || rect.height < 0)
- {
- return rect;
- }
-
- parent = dynamic_cast<Toolkit::DevelControl::ControlAccessible*>(parent->GetParent());
- }
-
- return rect;
-}
-
-static bool IsShowingGeometryOnScreen(Dali::Rect<> rect)
-{
- return rect.width > 0 && rect.height > 0;
-}
-
} // unnamed namespace
// clang-format off
: mControlImpl(controlImpl),
mState(Toolkit::DevelControl::NORMAL),
mSubStateName(""),
+ mAccessibilityData(nullptr),
+ mVisualData(nullptr),
mLeftFocusableActorId(-1),
mRightFocusableActorId(-1),
mUpFocusableActorId(-1),
mKeyInputFocusGainedSignal(),
mKeyInputFocusLostSignal(),
mResourceReadySignal(),
- mVisualEventSignal(),
- mAccessibilityGetNameSignal(),
- mAccessibilityGetDescriptionSignal(),
- mAccessibilityDoGestureSignal(),
mPinchGestureDetector(),
mPanGestureDetector(),
mTapGestureDetector(),
mDispatchKeyEvents(true),
mProcessorRegistered(false)
{
- Accessibility::Accessible::RegisterExternalAccessibleGetter([](Dali::Actor actor) -> std::pair<std::shared_ptr<Accessibility::Accessible>, bool> {
- auto control = Toolkit::Control::DownCast(actor);
- if(!control)
- {
- return {nullptr, true};
- }
-
- auto& controlImpl = Toolkit::Internal::GetImplementation(control);
- if(controlImpl.mImpl->IsCreateAccessibleEnabled())
- {
- return {std::shared_ptr<DevelControl::ControlAccessible>(controlImpl.CreateAccessibleObject()), true};
- }
-
- return {nullptr, false};
- });
- mAccessibilityProps.states[DevelControl::AccessibilityState::ENABLED] = true;
+ mAccessibilityData = new AccessibilityData(mControlImpl);
+ mVisualData = new VisualData(*this);
}
Control::Impl::~Impl()
{
- while(!mVisuals.Empty())
- {
- auto iter = mVisuals.End() - 1u;
- StopObservingVisual((*iter)->visual);
-
- // Discard removed visual. It will be destroyed at next Idle time.
- DiscardVisual(iter, mVisuals);
- }
-
- while(!mRemoveVisuals.Empty())
- {
- auto removalIter = mRemoveVisuals.End() - 1u;
- StopObservingVisual((*removalIter)->visual);
-
- // Discard removed visual. It will be destroyed at next Idle time.
- DiscardVisual(removalIter, mRemoveVisuals);
- }
+ mVisualData->ClearVisuals();
// All gesture detectors will be destroyed so no need to disconnect.
delete mStartingPinchScale;
// Removes the callback from the callback manager in case the control is destroyed before the callback is executed.
Adaptor::Get().RemoveIdle(mIdleCallback);
}
+
+ delete mAccessibilityData;
+ delete mVisualData;
}
Control::Impl& Control::Impl::Get(Internal::Control& internalControl)
return *internalControl.mImpl;
}
-void Control::Impl::CheckHighlightedObjectGeometry()
+// Gesture Detection Methods
+void Control::Impl::PinchDetected(Actor actor, const PinchGesture& pinch)
{
- auto accessible = GetAccessibleObject();
- if(DALI_LIKELY(accessible))
- {
- auto lastPosition = accessible->GetLastPosition();
- auto accessibleRect = accessible->GetExtents(Dali::Accessibility::CoordinateType::WINDOW);
- auto rect = GetShowingGeometry(accessibleRect, accessible.get());
-
- switch(mAccessibilityLastScreenRelativeMoveType)
- {
- case Dali::Accessibility::ScreenRelativeMoveType::OUTSIDE:
- {
- if(IsShowingGeometryOnScreen(rect))
- {
- mAccessibilityLastScreenRelativeMoveType = Dali::Accessibility::ScreenRelativeMoveType::INSIDE;
- }
- break;
- }
- case Dali::Accessibility::ScreenRelativeMoveType::INSIDE:
- {
- if(rect.width < 0 && !Dali::Equals(accessibleRect.x, lastPosition.x))
- {
- mAccessibilityLastScreenRelativeMoveType = (accessibleRect.x < lastPosition.x) ? Dali::Accessibility::ScreenRelativeMoveType::OUTGOING_TOP_LEFT : Dali::Accessibility::ScreenRelativeMoveType::OUTGOING_BOTTOM_RIGHT;
- }
- if(rect.height < 0 && !Dali::Equals(accessibleRect.y, lastPosition.y))
- {
- mAccessibilityLastScreenRelativeMoveType = (accessibleRect.y < lastPosition.y) ? Dali::Accessibility::ScreenRelativeMoveType::OUTGOING_TOP_LEFT : Dali::Accessibility::ScreenRelativeMoveType::OUTGOING_BOTTOM_RIGHT;
- }
- // notify AT-clients on outgoing moves only
- if(mAccessibilityLastScreenRelativeMoveType != Dali::Accessibility::ScreenRelativeMoveType::INSIDE)
- {
- accessible->EmitMovedOutOfScreen(mAccessibilityLastScreenRelativeMoveType);
- }
- break;
- }
- case Dali::Accessibility::ScreenRelativeMoveType::OUTGOING_TOP_LEFT:
- case Dali::Accessibility::ScreenRelativeMoveType::OUTGOING_BOTTOM_RIGHT:
- {
- if(IsShowingGeometryOnScreen(rect))
- {
- mAccessibilityLastScreenRelativeMoveType = Dali::Accessibility::ScreenRelativeMoveType::INSIDE;
- }
- else
- {
- mAccessibilityLastScreenRelativeMoveType = Dali::Accessibility::ScreenRelativeMoveType::OUTSIDE;
- }
- break;
- }
- default:
- {
- break;
- }
- }
-
- accessible->SetLastPosition(Vector2(accessibleRect.x, accessibleRect.y));
- }
+ mControlImpl.OnPinch(pinch);
}
-void Control::Impl::RegisterAccessibilityPositionPropertyNotification()
+void Control::Impl::PanDetected(Actor actor, const PanGesture& pan)
{
- if(mIsAccessibilityPositionPropertyNotificationSet)
- {
- return;
- }
- // set default value until first move of object is detected
- mAccessibilityLastScreenRelativeMoveType = Dali::Accessibility::ScreenRelativeMoveType::OUTSIDE;
- // recalculate mAccessibilityLastScreenRelativeMoveType accordingly to the initial position
- CheckHighlightedObjectGeometry();
- mAccessibilityPositionNotification = mControlImpl.Self().AddPropertyNotification(Actor::Property::WORLD_POSITION, StepCondition(1.0f, 1.0f));
- mAccessibilityPositionNotification.SetNotifyMode(PropertyNotification::NOTIFY_ON_CHANGED);
- mAccessibilityPositionNotification.NotifySignal().Connect(this, [this](PropertyNotification&) { CheckHighlightedObjectGeometry(); });
- mIsAccessibilityPositionPropertyNotificationSet = true;
+ mControlImpl.OnPan(pan);
}
-void Control::Impl::UnregisterAccessibilityPositionPropertyNotification()
+void Control::Impl::TapDetected(Actor actor, const TapGesture& tap)
{
- mControlImpl.Self().RemovePropertyNotification(mAccessibilityPositionNotification);
- mIsAccessibilityPositionPropertyNotificationSet = false;
+ mControlImpl.OnTap(tap);
}
-void Control::Impl::RegisterAccessibilityPropertySetSignal()
+void Control::Impl::LongPressDetected(Actor actor, const LongPressGesture& longPress)
{
- if(mIsAccessibilityPropertySetSignalRegistered)
- {
- return;
- }
- mControlImpl.Self().PropertySetSignal().Connect(this, &Control::Impl::OnAccessibilityPropertySet);
- mIsAccessibilityPropertySetSignalRegistered = true;
+ mControlImpl.OnLongPress(longPress);
}
-void Control::Impl::UnregisterAccessibilityPropertySetSignal()
+void Control::Impl::ResourceReady()
{
- if(!mIsAccessibilityPropertySetSignalRegistered)
+ 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(mVisualData->IsResourceReady())
{
- return;
+ EmitResourceReadySignal();
}
- mControlImpl.Self().PropertySetSignal().Disconnect(this, &Control::Impl::OnAccessibilityPropertySet);
- mIsAccessibilityPropertySetSignalRegistered = false;
}
-void Control::Impl::OnAccessibilityPropertySet(Dali::Handle& handle, Dali::Property::Index index, const Dali::Property::Value& value)
+void Control::Impl::RegisterVisual(Property::Index index, Toolkit::Visual::Base& visual)
{
- auto accessible = GetAccessibleObject();
- if(DALI_LIKELY(accessible))
- {
- if(mAccessibilityGetNameSignal.Empty())
- {
- if(index == DevelControl::Property::ACCESSIBILITY_NAME || (mAccessibilityProps.name.empty() && index == accessible->GetNamePropertyIndex()))
- {
- accessible->Emit(Dali::Accessibility::ObjectPropertyChangeEvent::NAME);
- return;
- }
- }
-
- if(mAccessibilityGetDescriptionSignal.Empty())
- {
- if(index == DevelControl::Property::ACCESSIBILITY_DESCRIPTION || (mAccessibilityProps.description.empty() && index == accessible->GetDescriptionPropertyIndex()))
- {
- accessible->Emit(Dali::Accessibility::ObjectPropertyChangeEvent::DESCRIPTION);
- return;
- }
- }
-
- if(index == DevelControl::Property::ACCESSIBILITY_VALUE)
- {
- accessible->Emit(Dali::Accessibility::ObjectPropertyChangeEvent::VALUE);
- return;
- }
+ mVisualData->RegisterVisual(index, visual);
+}
- if(index == DevelControl::Property::ACCESSIBILITY_STATES)
- {
- accessible->OnStatePropertySet(mAccessibilityProps.states);
- return;
- }
- }
+void Control::Impl::RegisterVisual(Property::Index index, Toolkit::Visual::Base& visual, int depthIndex)
+{
+ mVisualData->RegisterVisual(index, visual, depthIndex);
}
-// Gesture Detection Methods
-void Control::Impl::PinchDetected(Actor actor, const PinchGesture& pinch)
+void Control::Impl::RegisterVisual(Property::Index index, Toolkit::Visual::Base& visual, bool enabled)
{
- mControlImpl.OnPinch(pinch);
+ mVisualData->RegisterVisual(index, visual, enabled);
}
-void Control::Impl::PanDetected(Actor actor, const PanGesture& pan)
+void Control::Impl::RegisterVisual(Property::Index index, Toolkit::Visual::Base& visual, bool enabled, int depthIndex)
{
- mControlImpl.OnPan(pan);
+ mVisualData->RegisterVisual(index, visual, enabled, depthIndex);
}
-void Control::Impl::TapDetected(Actor actor, const TapGesture& tap)
+void Control::Impl::UnregisterVisual(Property::Index index)
{
- mControlImpl.OnTap(tap);
+ mVisualData->UnregisterVisual(index);
}
-void Control::Impl::LongPressDetected(Actor actor, const LongPressGesture& longPress)
+Toolkit::Visual::Base Control::Impl::GetVisual(Property::Index index) const
{
- mControlImpl.OnLongPress(longPress);
+ return mVisualData->GetVisual(index);
}
-void Control::Impl::RegisterVisual(Property::Index index, Toolkit::Visual::Base& visual)
+bool Control::Impl::IsResourceReady() const
{
- RegisterVisual(index, visual, VisualState::ENABLED, DepthIndexValue::NOT_SET);
+ return mVisualData->IsResourceReady();
}
-void Control::Impl::RegisterVisual(Property::Index index, Toolkit::Visual::Base& visual, int depthIndex)
+void Control::Impl::OnSceneDisconnection()
{
- RegisterVisual(index, visual, VisualState::ENABLED, DepthIndexValue::SET, depthIndex);
+ Actor self = mControlImpl.Self();
+ mVisualData->ClearScene(self);
}
-void Control::Impl::RegisterVisual(Property::Index index, Toolkit::Visual::Base& visual, bool enabled)
+void Control::Impl::EnableReadyTransitionOverriden(Toolkit::Visual::Base& visual, bool enable)
{
- RegisterVisual(index, visual, (enabled ? VisualState::ENABLED : VisualState::DISABLED), DepthIndexValue::NOT_SET);
+ mVisualData->EnableReadyTransitionOverriden(visual, enable);
}
-void Control::Impl::RegisterVisual(Property::Index index, Toolkit::Visual::Base& visual, bool enabled, int depthIndex)
+void Control::Impl::EnableVisual(Property::Index index, bool enable)
{
- RegisterVisual(index, visual, (enabled ? VisualState::ENABLED : VisualState::DISABLED), DepthIndexValue::SET, depthIndex);
+ mVisualData->EnableVisual(index, enable);
}
-void Control::Impl::RegisterVisual(Property::Index index, Toolkit::Visual::Base& visual, VisualState::Type enabled, DepthIndexValue::Type depthIndexValueSet, int depthIndex)
+bool Control::Impl::IsVisualEnabled(Property::Index index) const
{
- 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);
- Actor self = mControlImpl.Self();
-
- // Set the depth index, if not set by caller this will be either the current visual depth, max depth of all visuals
- // or zero.
- int requiredDepthIndex = visual.GetDepthIndex();
-
- if(depthIndexValueSet == DepthIndexValue::SET)
- {
- requiredDepthIndex = depthIndex;
- }
-
- // Change the depth index value automatically if the visual has DepthIndex to AUTO_INDEX
- // or if RegisterVisual set DepthIndex to AUTO_INDEX.
- const bool requiredDepthIndexChanged = (requiredDepthIndex == DepthIndex::AUTO_INDEX);
-
- // Visual replacement, existing visual should only be removed from stage when replacement ready.
- if(!mVisuals.Empty())
- {
- RegisteredVisualContainer::Iterator registeredVisualsiter;
- // Check if visual (index) is already registered, this is the current visual.
- if(FindVisual(index, mVisuals, registeredVisualsiter))
- {
- Toolkit::Visual::Base& currentRegisteredVisual = (*registeredVisualsiter)->visual;
- if(currentRegisteredVisual)
- {
- // Store current visual depth index as may need to set the replacement visual to same depth
- const int currentDepthIndex = (*registeredVisualsiter)->visual.GetDepthIndex();
-
- // No longer required to know if the replaced visual's resources are ready
- StopObservingVisual(currentRegisteredVisual);
-
- // If control staged and visual enabled then visuals will be swapped once ready
- if(self.GetProperty<bool>(Actor::Property::CONNECTED_TO_SCENE) && enabled)
- {
- // Check if visual is currently in the process of being replaced ( is in removal container )
- RegisteredVisualContainer::Iterator visualQueuedForRemoval;
- if(FindVisual(index, mRemoveVisuals, visualQueuedForRemoval))
- {
- // Visual with same index is already in removal container so current visual pending
- // Only the the last requested visual will be displayed so remove current visual which is staged but not ready.
- Toolkit::GetImplementation(currentRegisteredVisual).SetOffScene(self);
- mVisuals.Erase(registeredVisualsiter);
- }
- else
- {
- // current visual not already in removal container so add now.
- DALI_LOG_INFO(gLogFilter, Debug::Verbose, "RegisterVisual Move current registered visual to removal Queue: %d \n", index);
- MoveVisual(registeredVisualsiter, mVisuals, mRemoveVisuals);
- }
- }
- else
- {
- // Control not staged or visual disabled so can just erase from registered visuals and new visual will be added later.
- mVisuals.Erase(registeredVisualsiter);
- }
-
- // If the visual have a depth index as AUTO_INDEX and the new visual does not have a depth index applied to it, then use the previously set depth-index for this index
- if(requiredDepthIndexChanged)
- {
- requiredDepthIndex = currentDepthIndex;
- DALI_LOG_INFO(gLogFilter, Debug::Verbose, "Use replaced visual index. VisualDepthIndex AUTO_INDEX set as: %d\n", requiredDepthIndex);
- }
- }
-
- visualReplaced = true;
- }
- }
-
- // If not set, set the name of the visual to the same name as the control's property.
- // ( If the control has been type registered )
- if(visual.GetName().empty())
- {
- // returns empty string if index is not found as long as index is not -1
- std::string visualName = self.GetPropertyName(index);
- if(!visualName.empty())
- {
- DALI_LOG_INFO(gLogFilter, Debug::Concise, "Setting visual name for property %d to %s\n", index, visualName.c_str());
- visual.SetName(visualName);
- }
- }
-
- if(!visualReplaced) // New registration entry
- {
- // If we have more than one visual and the visual have a depth index as AUTO_INDEX, then set it to be the highest
- if((mVisuals.Size() > 0) && requiredDepthIndexChanged)
- {
- int maxDepthIndex = static_cast<int>(DepthIndex::CONTENT) - 1; // Start at DepthIndex::CONTENT if maxDepth index belongs to a background or no visuals have been added yet.
-
- RegisteredVisualContainer::ConstIterator iter;
- const RegisteredVisualContainer::ConstIterator endIter = mVisuals.End();
- for(iter = mVisuals.Begin(); iter != endIter; iter++)
- {
- const int visualDepthIndex = (*iter)->visual.GetDepthIndex();
- if(visualDepthIndex > maxDepthIndex)
- {
- maxDepthIndex = visualDepthIndex;
- }
- }
- requiredDepthIndex = ++maxDepthIndex; // Add one to the current maximum depth index so that our added visual appears on top.
- DALI_LOG_INFO(gLogFilter, Debug::Verbose, "Use top of all visuals. VisualDepthIndex AUTO_INDEX set as: %d\n", requiredDepthIndex);
- }
- }
-
- if(visual)
- {
- // If required depth index still DepthIndex::AUTO_INDEX, Make it as DepthIndex::CONTENT now
- if(requiredDepthIndex == static_cast<int>(DepthIndex::AUTO_INDEX))
- {
- requiredDepthIndex = static_cast<int>(DepthIndex::CONTENT);
- DALI_LOG_INFO(gLogFilter, Debug::Verbose, "Some strange cases. VisualDepthIndex AUTO_INDEX set as: %d\n", requiredDepthIndex);
- }
-
- // Set determined depth index
- visual.SetDepthIndex(requiredDepthIndex);
-
- // Monitor when the visual resources are ready
- StartObservingVisual(visual);
-
- DALI_LOG_INFO(gLogFilter, Debug::Concise, "New Visual registration index[%d] depth[%d]\n", index, requiredDepthIndex);
- RegisteredVisual* newRegisteredVisual = new RegisteredVisual(index, visual, (enabled == VisualState::ENABLED ? true : false), (visualReplaced && enabled));
- mVisuals.PushBack(newRegisteredVisual);
-
- Internal::Visual::Base& visualImpl = Toolkit::GetImplementation(visual);
- // Put on stage if enabled and the control is already on the stage
- if((enabled == VisualState::ENABLED) && self.GetProperty<bool>(Actor::Property::CONNECTED_TO_SCENE))
- {
- visualImpl.SetOnScene(self);
- }
- 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);
- }
- }
-
- DALI_LOG_INFO(gLogFilter, Debug::Verbose, "Control::RegisterVisual() Registered %s(%d), enabled:%s\n", visual.GetName().c_str(), index, enabled ? "true" : "false");
-}
-
-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))
- {
- // stop observing visual
- StopObservingVisual((*iter)->visual);
-
- Actor self(mControlImpl.Self());
- Toolkit::GetImplementation((*iter)->visual).SetOffScene(self);
- (*iter)->visual.Reset();
- mVisuals.Erase(iter);
- }
-
- if(FindVisual(index, mRemoveVisuals, iter))
- {
- Actor self(mControlImpl.Self());
- Toolkit::GetImplementation((*iter)->visual).SetOffScene(self);
- (*iter)->pending = false;
-
- // Discard removed visual. It will be destroyed at next Idle time.
- DiscardVisual(iter, mRemoveVisuals);
- }
-}
-
-Toolkit::Visual::Base Control::Impl::GetVisual(Property::Index index) const
-{
- RegisteredVisualContainer::Iterator iter;
- if(FindVisual(index, mVisuals, iter))
- {
- return (*iter)->visual;
- }
-
- return Toolkit::Visual::Base();
-}
-
-void Control::Impl::EnableVisual(Property::Index index, bool enable)
-{
- DALI_LOG_INFO(gLogFilter, Debug::General, "Control::EnableVisual(%d, %s)\n", index, enable ? "T" : "F");
-
- RegisteredVisualContainer::Iterator iter;
- if(FindVisual(index, mVisuals, iter))
- {
- if((*iter)->enabled == enable)
- {
- DALI_LOG_INFO(gLogFilter, Debug::Verbose, "Control::EnableVisual Visual %s(%d) already %s\n", (*iter)->visual.GetName().c_str(), index, enable ? "enabled" : "disabled");
- return;
- }
-
- (*iter)->enabled = enable;
- Actor parentActor = mControlImpl.Self();
- if(mControlImpl.Self().GetProperty<bool>(Actor::Property::CONNECTED_TO_SCENE)) // If control not on Scene then Visual will be added when SceneConnection is called.
- {
- if(enable)
- {
- DALI_LOG_INFO(gLogFilter, Debug::Verbose, "Control::EnableVisual Setting %s(%d) on stage \n", (*iter)->visual.GetName().c_str(), index);
- Toolkit::GetImplementation((*iter)->visual).SetOnScene(parentActor);
- }
- else
- {
- DALI_LOG_INFO(gLogFilter, Debug::Verbose, "Control::EnableVisual Setting %s(%d) off stage \n", (*iter)->visual.GetName().c_str(), index);
- Toolkit::GetImplementation((*iter)->visual).SetOffScene(parentActor); // No need to call if control not staged.
- }
- }
- }
- else
- {
- DALI_LOG_WARNING("Control::EnableVisual(%d, %s) FAILED - NO SUCH VISUAL\n", index, enable ? "T" : "F");
- }
-}
-
-bool Control::Impl::IsVisualEnabled(Property::Index index) const
-{
- RegisteredVisualContainer::Iterator iter;
- if(FindVisual(index, mVisuals, iter))
- {
- return (*iter)->enabled;
- }
- 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);
-
- // Stop observing the visual
- visualImpl.RemoveEventObserver(*this);
-}
-
-void Control::Impl::StartObservingVisual(Toolkit::Visual::Base& visual)
-{
- Internal::Visual::Base& visualImpl = Toolkit::GetImplementation(visual);
-
- // start observing the visual for events
- visualImpl.AddEventObserver(*this);
-}
-
-void Control::Impl::ResourceReady()
-{
- 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())
- {
- EmitResourceReadySignal();
- }
-}
-
-// Called by a Visual when it's resource is ready
-void Control::Impl::ResourceReady(Visual::Base& object)
-{
- DALI_LOG_INFO(gLogFilter, Debug::Verbose, "Control::Impl::ResourceReady() replacements pending[%d]\n", mRemoveVisuals.Count());
-
- Actor self = mControlImpl.Self();
-
- RegisteredVisualContainer::Iterator registeredIter;
-
- // A resource is ready, find resource in the registered visuals container and get its index
- if(!FindVisual(object, mVisuals, registeredIter))
- {
- return;
- }
-
- 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))
- {
- 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
- if(((*registeredIter)->enabled))
- {
- ResourceReady();
- }
-}
-
-void Control::Impl::NotifyVisualEvent(Visual::Base& object, Property::Index signalId)
-{
- for(auto registeredIter = mVisuals.Begin(), end = mVisuals.End(); registeredIter != end; ++registeredIter)
- {
- Internal::Visual::Base& registeredVisualImpl = Toolkit::GetImplementation((*registeredIter)->visual);
- if(&object == ®isteredVisualImpl)
- {
- Dali::Toolkit::Control handle(mControlImpl.GetOwner());
- mVisualEventSignal.Emit(handle, (*registeredIter)->index, signalId);
- break;
- }
- }
-}
-
-void Control::Impl::RelayoutRequest(Visual::Base& object)
-{
- if(mControlImpl.Self().GetProperty<bool>(Actor::Property::CONNECTED_TO_SCENE))
- {
- mControlImpl.RelayoutRequest();
- }
-}
-
-bool Control::Impl::IsResourceReady() const
-{
- // Iterate through and check all the enabled visuals are ready
- for(auto visualIter = mVisuals.Begin();
- visualIter != mVisuals.End();
- ++visualIter)
- {
- const Toolkit::Visual::Base visual = (*visualIter)->visual;
- const Internal::Visual::Base& visualImpl = Toolkit::GetImplementation(visual);
-
- // one of the enabled visuals is not ready
- if(!visualImpl.IsResourceReady() && (*visualIter)->enabled)
- {
- return false;
- }
- }
- return true;
-}
+ return mVisualData->IsVisualEnabled(index);
+}
Toolkit::Visual::ResourceStatus Control::Impl::GetVisualResourceStatus(Property::Index index) const
{
- RegisteredVisualContainer::Iterator iter;
- if(FindVisual(index, mVisuals, iter))
- {
- const Toolkit::Visual::Base visual = (*iter)->visual;
- const Internal::Visual::Base& visualImpl = Toolkit::GetImplementation(visual);
- return visualImpl.GetResourceStatus();
- }
-
- return Toolkit::Visual::ResourceStatus::PREPARING;
+ return mVisualData->GetVisualResourceStatus(index);
}
void Control::Impl::AddTransitions(Dali::Animation& animation,
{
TransitionData::Animator* animator = (*iter);
- Toolkit::Visual::Base visual = GetVisualByName(mVisuals, animator->objectName);
+ Toolkit::Visual::Base visual = mVisualData->GetVisual(animator->objectName);
if(visual)
{
#if defined(DEBUG_ENABLED)
}
}
-Dali::Animation Control::Impl::CreateTransition(const Toolkit::TransitionData& transitionData)
-{
- Dali::Animation transition;
-
- if(transitionData.Count() > 0)
- {
- AddTransitions(transition, transitionData, true);
- }
- return transition;
-}
-
void Control::Impl::DoAction(Dali::Property::Index visualIndex, Dali::Property::Index actionId, const Dali::Property::Value attributes)
{
- RegisteredVisualContainer::Iterator iter;
- if(FindVisual(visualIndex, mVisuals, iter))
- {
- Toolkit::GetImplementation((*iter)->visual).DoAction(actionId, attributes);
- }
+ mVisualData->DoAction(visualIndex, actionId, attributes);
}
void Control::Impl::DoActionExtension(Dali::Property::Index visualIndex, Dali::Property::Index actionId, Dali::Any attributes)
{
- RegisteredVisualContainer::Iterator iter;
- if(FindVisual(visualIndex, mVisuals, iter))
- {
- Toolkit::GetImplementation((*iter)->visual).DoActionExtension(actionId, attributes);
- }
+ mVisualData->DoActionExtension(visualIndex, actionId, attributes);
}
-void Control::Impl::AppendAccessibilityAttribute(const std::string& key, const std::string value)
+Dali::Animation Control::Impl::CreateTransition(const Toolkit::TransitionData& transitionData)
{
- Property::Value* checkedValue = mAccessibilityProps.extraAttributes.Find(key);
- if(checkedValue)
- {
- mAccessibilityProps.extraAttributes[key] = Property::Value(value);
- }
- else
+ Dali::Animation transition;
+
+ if(transitionData.Count() > 0)
{
- mAccessibilityProps.extraAttributes.Insert(key, value);
+ AddTransitions(transition, transitionData, true);
}
+ return transition;
}
void Control::Impl::SetProperty(BaseObject* object, Property::Index index, const Property::Value& value)
Toolkit::Visual::Base visual = Toolkit::VisualFactory::Get().CreateVisual(url, ImageDimensions());
if(visual)
{
- controlImpl.mImpl->RegisterVisual(Toolkit::Control::Property::BACKGROUND, visual, DepthIndex::BACKGROUND);
+ controlImpl.mImpl->mVisualData->RegisterVisual(Toolkit::Control::Property::BACKGROUND, visual, DepthIndex::BACKGROUND);
}
}
else if(value.Get(color))
std::string name;
if(value.Get(name))
{
- controlImpl.mImpl->mAccessibilityProps.name = std::move(name);
+ controlImpl.mImpl->mAccessibilityData->mAccessibilityProps.name = std::move(name);
}
break;
}
std::string text;
if(value.Get(text))
{
- controlImpl.mImpl->mAccessibilityProps.description = std::move(text);
+ controlImpl.mImpl->mAccessibilityData->mAccessibilityProps.description = std::move(text);
}
break;
}
int32_t role;
if(value.Get(role))
{
- controlImpl.mImpl->mAccessibilityProps.role = role;
+ controlImpl.mImpl->mAccessibilityData->mAccessibilityProps.role = role;
}
break;
}
bool highlightable;
if(value.Get(highlightable))
{
- controlImpl.mImpl->mAccessibilityProps.isHighlightable = highlightable ? TriStateProperty::TRUE : TriStateProperty::FALSE;
+ controlImpl.mImpl->mAccessibilityData->mAccessibilityProps.isHighlightable = highlightable ? TriStateProperty::TRUE : TriStateProperty::FALSE;
}
break;
}
const Property::Map* map = value.GetMap();
if(map && !map->Empty())
{
- controlImpl.mImpl->mAccessibilityProps.extraAttributes = *map;
+ controlImpl.mImpl->mAccessibilityData->mAccessibilityProps.extraAttributes = *map;
}
break;
}
bool hidden;
if(value.Get(hidden))
{
- controlImpl.mImpl->mAccessibilityProps.isHidden = hidden;
+ controlImpl.mImpl->mAccessibilityData->mAccessibilityProps.isHidden = hidden;
auto accessible = controlImpl.GetAccessibleObject();
if(DALI_LIKELY(accessible))
std::string automationId;
if(value.Get(automationId))
{
- controlImpl.mImpl->mAccessibilityProps.automationId = std::move(automationId);
+ controlImpl.mImpl->mAccessibilityData->mAccessibilityProps.automationId = std::move(automationId);
}
break;
}
std::string accessibilityValue;
if(value.Get(accessibilityValue))
{
- controlImpl.mImpl->mAccessibilityProps.value = std::move(accessibilityValue);
+ controlImpl.mImpl->mAccessibilityData->mAccessibilityProps.value = std::move(accessibilityValue);
}
break;
}
bool isScrollable;
if(value.Get(isScrollable))
{
- controlImpl.mImpl->mAccessibilityProps.isScrollable = isScrollable;
+ controlImpl.mImpl->mAccessibilityData->mAccessibilityProps.isScrollable = isScrollable;
}
break;
}
int32_t states;
if(value.Get(states))
{
- controlImpl.mImpl->mAccessibilityProps.states = Toolkit::DevelControl::AccessibilityStates{static_cast<uint32_t>(states)};
+ controlImpl.mImpl->mAccessibilityData->mAccessibilityProps.states = Toolkit::DevelControl::AccessibilityStates{static_cast<uint32_t>(states)};
}
break;
}
bool isModal;
if(value.Get(isModal))
{
- controlImpl.mImpl->mAccessibilityProps.isModal = isModal;
+ controlImpl.mImpl->mAccessibilityData->mAccessibilityProps.isModal = isModal;
}
break;
}
case Toolkit::Control::Property::BACKGROUND:
{
Property::Map map;
- Toolkit::Visual::Base visual = controlImpl.mImpl->GetVisual(Toolkit::Control::Property::BACKGROUND);
+ Toolkit::Visual::Base visual = controlImpl.mImpl->mVisualData->GetVisual(Toolkit::Control::Property::BACKGROUND);
if(visual)
{
visual.CreatePropertyMap(map);
case Toolkit::DevelControl::Property::SHADOW:
{
Property::Map map;
- Toolkit::Visual::Base visual = controlImpl.mImpl->GetVisual(Toolkit::DevelControl::Property::SHADOW);
+ Toolkit::Visual::Base visual = controlImpl.mImpl->mVisualData->GetVisual(Toolkit::DevelControl::Property::SHADOW);
if(visual)
{
visual.CreatePropertyMap(map);
case Toolkit::DevelControl::Property::ACCESSIBILITY_NAME:
{
- value = controlImpl.mImpl->mAccessibilityProps.name;
+ value = controlImpl.mImpl->mAccessibilityData->mAccessibilityProps.name;
break;
}
case Toolkit::DevelControl::Property::ACCESSIBILITY_DESCRIPTION:
{
- value = controlImpl.mImpl->mAccessibilityProps.description;
+ value = controlImpl.mImpl->mAccessibilityData->mAccessibilityProps.description;
break;
}
case Toolkit::DevelControl::Property::ACCESSIBILITY_ROLE:
{
- value = controlImpl.mImpl->mAccessibilityProps.role;
+ value = controlImpl.mImpl->mAccessibilityData->mAccessibilityProps.role;
break;
}
case Toolkit::DevelControl::Property::ACCESSIBILITY_HIGHLIGHTABLE:
{
- value = controlImpl.mImpl->mAccessibilityProps.isHighlightable == TriStateProperty::TRUE ? true : false;
+ value = controlImpl.mImpl->mAccessibilityData->mAccessibilityProps.isHighlightable == TriStateProperty::TRUE ? true : false;
break;
}
case Toolkit::DevelControl::Property::ACCESSIBILITY_ATTRIBUTES:
{
- value = controlImpl.mImpl->mAccessibilityProps.extraAttributes;
+ value = controlImpl.mImpl->mAccessibilityData->mAccessibilityProps.extraAttributes;
break;
}
case Toolkit::DevelControl::Property::ACCESSIBILITY_HIDDEN:
{
- value = controlImpl.mImpl->mAccessibilityProps.isHidden;
+ value = controlImpl.mImpl->mAccessibilityData->mAccessibilityProps.isHidden;
break;
}
case Toolkit::DevelControl::Property::AUTOMATION_ID:
{
- value = controlImpl.mImpl->mAccessibilityProps.automationId;
+ value = controlImpl.mImpl->mAccessibilityData->mAccessibilityProps.automationId;
break;
}
case Toolkit::DevelControl::Property::ACCESSIBILITY_VALUE:
{
- value = controlImpl.mImpl->mAccessibilityProps.value;
+ value = controlImpl.mImpl->mAccessibilityData->mAccessibilityProps.value;
break;
}
case Toolkit::DevelControl::Property::ACCESSIBILITY_SCROLLABLE:
{
- value = controlImpl.mImpl->mAccessibilityProps.isScrollable;
+ value = controlImpl.mImpl->mAccessibilityData->mAccessibilityProps.isScrollable;
break;
}
case Toolkit::DevelControl::Property::ACCESSIBILITY_STATES:
{
- value = static_cast<int32_t>(controlImpl.mImpl->mAccessibilityProps.states.GetRawData32());
+ value = static_cast<int32_t>(controlImpl.mImpl->mAccessibilityData->mAccessibilityProps.states.GetRawData32());
break;
}
case Toolkit::DevelControl::Property::ACCESSIBILITY_IS_MODAL:
{
- value = controlImpl.mImpl->mAccessibilityProps.isModal;
+ value = controlImpl.mImpl->mAccessibilityData->mAccessibilityProps.isModal;
break;
}
}
return value;
}
-void Control::Impl::RemoveAccessibilityAttribute(const std::string& key)
-{
- Property::Value* value = mAccessibilityProps.extraAttributes.Find(key);
- if(value)
- {
- mAccessibilityProps.extraAttributes[key] = Property::Value();
- }
-}
-
-void Control::Impl::ClearAccessibilityAttributes()
-{
- mAccessibilityProps.extraAttributes.Clear();
-}
-
-void Control::Impl::SetAccessibilityReadingInfoType(const Dali::Accessibility::ReadingInfoTypes types)
-{
- std::string value{};
- if(types[Dali::Accessibility::ReadingInfoType::NAME])
- {
- value += READING_INFO_TYPE_NAME;
- }
- if(types[Dali::Accessibility::ReadingInfoType::ROLE])
- {
- if(!value.empty())
- {
- value += READING_INFO_TYPE_SEPARATOR;
- }
- value += READING_INFO_TYPE_ROLE;
- }
- if(types[Dali::Accessibility::ReadingInfoType::DESCRIPTION])
- {
- if(!value.empty())
- {
- value += READING_INFO_TYPE_SEPARATOR;
- }
- value += READING_INFO_TYPE_DESCRIPTION;
- }
- if(types[Dali::Accessibility::ReadingInfoType::STATE])
- {
- if(!value.empty())
- {
- value += READING_INFO_TYPE_SEPARATOR;
- }
- value += READING_INFO_TYPE_STATE;
- }
- AppendAccessibilityAttribute(READING_INFO_TYPE_ATTRIBUTE_NAME, value);
-}
-
-Dali::Accessibility::ReadingInfoTypes Control::Impl::GetAccessibilityReadingInfoType() const
-{
- std::string value{};
- auto place = mAccessibilityProps.extraAttributes.Find(READING_INFO_TYPE_ATTRIBUTE_NAME);
- if(place)
- {
- place->Get(value);
- }
- else
- {
- Dali::Accessibility::ReadingInfoTypes types;
- types[Dali::Accessibility::ReadingInfoType::NAME] = true;
- types[Dali::Accessibility::ReadingInfoType::ROLE] = true;
- types[Dali::Accessibility::ReadingInfoType::DESCRIPTION] = true;
- types[Dali::Accessibility::ReadingInfoType::STATE] = true;
- return types;
- }
-
- if(value.empty())
- {
- return {};
- }
-
- Dali::Accessibility::ReadingInfoTypes types;
-
- if(value.find(READING_INFO_TYPE_NAME) != std::string::npos)
- {
- types[Dali::Accessibility::ReadingInfoType::NAME] = true;
- }
- if(value.find(READING_INFO_TYPE_ROLE) != std::string::npos)
- {
- types[Dali::Accessibility::ReadingInfoType::ROLE] = true;
- }
- if(value.find(READING_INFO_TYPE_DESCRIPTION) != std::string::npos)
- {
- types[Dali::Accessibility::ReadingInfoType::DESCRIPTION] = true;
- }
- if(value.find(READING_INFO_TYPE_STATE) != std::string::npos)
- {
- types[Dali::Accessibility::ReadingInfoType::STATE] = true;
- }
-
- return types;
-}
-
-void Control::Impl::CopyInstancedProperties(RegisteredVisualContainer& visuals, Dictionary<Property::Map>& instancedProperties)
-{
- for(RegisteredVisualContainer::Iterator iter = visuals.Begin(); iter != visuals.End(); iter++)
- {
- if((*iter)->visual)
- {
- Property::Map instanceMap;
- Toolkit::GetImplementation((*iter)->visual).CreateInstancePropertyMap(instanceMap);
- instancedProperties.Add((*iter)->visual.GetName(), instanceMap);
- }
- }
-}
-
-void Control::Impl::RemoveVisual(RegisteredVisualContainer& visuals, const std::string& visualName)
-{
- Actor self(mControlImpl.Self());
-
- for(RegisteredVisualContainer::Iterator visualIter = visuals.Begin();
- visualIter != visuals.End();
- ++visualIter)
- {
- Toolkit::Visual::Base visual = (*visualIter)->visual;
- if(visual && visual.GetName() == visualName)
- {
- Toolkit::GetImplementation(visual).SetOffScene(self);
- (*visualIter)->visual.Reset();
- visuals.Erase(visualIter);
- break;
- }
- }
-}
-
-void Control::Impl::RemoveVisuals(RegisteredVisualContainer& visuals, DictionaryKeys& removeVisuals)
-{
- Actor self(mControlImpl.Self());
- for(DictionaryKeys::iterator iter = removeVisuals.begin(); iter != removeVisuals.end(); ++iter)
- {
- const std::string visualName = *iter;
- RemoveVisual(visuals, visualName);
- }
-}
-
-void Control::Impl::RecreateChangedVisuals(Dictionary<Property::Map>& stateVisualsToChange,
- Dictionary<Property::Map>& instancedProperties)
-{
- Dali::CustomActor handle(mControlImpl.GetOwner());
- for(Dictionary<Property::Map>::iterator iter = stateVisualsToChange.Begin();
- iter != stateVisualsToChange.End();
- ++iter)
- {
- const std::string& visualName = (*iter).key;
- const Property::Map& toMap = (*iter).entry;
-
- Actor self = mControlImpl.Self();
- RegisteredVisualContainer::Iterator registeredVisualsiter;
- // Check if visual (visualName) is already registered, this is the current visual.
- if(FindVisual(visualName, mVisuals, registeredVisualsiter))
- {
- Toolkit::Visual::Base& visual = (*registeredVisualsiter)->visual;
- if(visual)
- {
- // No longer required to know if the replaced visual's resources are ready
- StopObservingVisual(visual);
-
- // If control staged then visuals will be swapped once ready
- if(self.GetProperty<bool>(Actor::Property::CONNECTED_TO_SCENE))
- {
- // Check if visual is currently in the process of being replaced ( is in removal container )
- RegisteredVisualContainer::Iterator visualQueuedForRemoval;
- if(FindVisual(visualName, mRemoveVisuals, visualQueuedForRemoval))
- {
- // Visual with same visual name is already in removal container so current visual pending
- // Only the the last requested visual will be displayed so remove current visual which is staged but not ready.
- Toolkit::GetImplementation(visual).SetOffScene(self);
- (*registeredVisualsiter)->visual.Reset();
- mVisuals.Erase(registeredVisualsiter);
- }
- else
- {
- // current visual not already in removal container so add now.
- DALI_LOG_INFO(gLogFilter, Debug::Verbose, "RegisterVisual Move current registered visual to removal Queue: %s \n", visualName.c_str());
- MoveVisual(registeredVisualsiter, mVisuals, mRemoveVisuals);
- }
- }
- else
- {
- // Control not staged or visual disabled so can just erase from registered visuals and new visual will be added later.
- (*registeredVisualsiter)->visual.Reset();
- mVisuals.Erase(registeredVisualsiter);
- }
- }
-
- const Property::Map* instancedMap = instancedProperties.FindConst(visualName);
- Style::ApplyVisual(handle, visualName, toMap, instancedMap);
- }
- }
-}
-
-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)
- {
- oldState->visuals.GetKeys(stateVisualsToRemove);
- if(!subState.empty())
- {
- const StylePtr* oldSubState = oldState->subStates.FindConst(subState);
- if(oldSubState)
- {
- DictionaryKeys subStateVisualsToRemove;
- (*oldSubState)->visuals.GetKeys(subStateVisualsToRemove);
- Merge(stateVisualsToRemove, subStateVisualsToRemove);
- }
- }
- }
-
- // Collect all new visual properties
- Dictionary<Property::Map> stateVisualsToAdd;
- if(newState)
- {
- stateVisualsToAdd = newState->visuals;
- if(!subState.empty())
- {
- const StylePtr* newSubState = newState->subStates.FindConst(subState);
- if(newSubState)
- {
- stateVisualsToAdd.Merge((*newSubState)->visuals);
- }
- }
- }
-
- // If a name is in both add/remove, move it to change list.
- Dictionary<Property::Map> stateVisualsToChange;
- FindChangableVisuals(stateVisualsToAdd, stateVisualsToChange, stateVisualsToRemove);
-
- // Copy instanced properties (e.g. text label) of current visuals
- Dictionary<Property::Map> instancedProperties;
- CopyInstancedProperties(mVisuals, instancedProperties);
-
- // For each visual in remove list, remove from mVisuals
- RemoveVisuals(mVisuals, stateVisualsToRemove);
-
- // For each visual in add list, create and add to mVisuals
- Dali::CustomActor handle(mControlImpl.GetOwner());
- Style::ApplyVisuals(handle, stateVisualsToAdd, instancedProperties);
-
- // For each visual in change list, if it requires a new visual,
- // remove old visual, create and add to mVisuals
- RecreateChangedVisuals(stateVisualsToChange, instancedProperties);
-}
-
void Control::Impl::SetState(DevelControl::State newState, bool withTransitions)
{
DevelControl::State oldState = mState;
if(oldStateStyle && newStateStyle)
{
// Only change if both state styles exist
- ReplaceStateVisualsAndProperties(*oldStateStyle, *newStateStyle, mSubStateName);
+ mVisualData->ReplaceStateVisualsAndProperties(*oldStateStyle, *newStateStyle, mSubStateName);
}
}
}
if(oldStateStyle && newStateStyle)
{
std::string empty;
- ReplaceStateVisualsAndProperties(*oldStateStyle, *newStateStyle, empty);
+ mVisualData->ReplaceStateVisualsAndProperties(*oldStateStyle, *newStateStyle, empty);
}
}
}
}
}
-void Control::Impl::OnSceneDisconnection()
-{
- Actor self = mControlImpl.Self();
-
- // Any visuals set for replacement but not yet ready should still be registered.
- // Reason: If a request was made to register a new visual but the control removed from scene before visual was ready
- // then when this control appears back on stage it should use that new visual.
-
- // Iterate through all registered visuals and set off scene
- SetVisualsOffScene(mVisuals, self);
-
- // 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
-
- if(!mRemoveVisuals.Empty())
- {
- 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;
- }
-}
-
void Control::Impl::SetMargin(Extents margin)
{
mControlImpl.mImpl->mMargin = margin;
return mControlImpl.mImpl->mPadding;
}
+DevelControl::VisualEventSignalType& Control::Impl::VisualEventSignal()
+{
+ return mVisualData->VisualEventSignal();
+}
+
void Control::Impl::SetInputMethodContext(InputMethodContext& inputMethodContext)
{
mInputMethodContext = inputMethodContext;
return consumed;
}
-DevelControl::VisualEventSignalType& Control::Impl::VisualEventSignal()
+void Control::Impl::AppendAccessibilityAttribute(const std::string& key, const std::string value)
+{
+ mAccessibilityData->AppendAccessibilityAttribute(key, value);
+}
+
+void Control::Impl::RemoveAccessibilityAttribute(const std::string& key)
+{
+ mAccessibilityData->RemoveAccessibilityAttribute(key);
+}
+
+void Control::Impl::ClearAccessibilityAttributes()
{
- return mVisualEventSignal;
+ mAccessibilityData->ClearAccessibilityAttributes();
+}
+
+void Control::Impl::SetAccessibilityReadingInfoType(const Dali::Accessibility::ReadingInfoTypes types)
+{
+ mAccessibilityData->SetAccessibilityReadingInfoType(types);
+}
+
+Dali::Accessibility::ReadingInfoTypes Control::Impl::GetAccessibilityReadingInfoType() const
+{
+ return mAccessibilityData->GetAccessibilityReadingInfoType();
+}
+
+void Control::Impl::CheckHighlightedObjectGeometry()
+{
+ mAccessibilityData->CheckHighlightedObjectGeometry();
+}
+
+void Control::Impl::RegisterAccessibilityPositionPropertyNotification()
+{
+ mAccessibilityData->RegisterAccessibilityPositionPropertyNotification();
+}
+
+void Control::Impl::UnregisterAccessibilityPositionPropertyNotification()
+{
+ mAccessibilityData->UnregisterAccessibilityPositionPropertyNotification();
+}
+
+void Control::Impl::RegisterAccessibilityPropertySetSignal()
+{
+ mAccessibilityData->RegisterAccessibilityPropertySetSignal();
+}
+
+void Control::Impl::UnregisterAccessibilityPropertySetSignal()
+{
+ mAccessibilityData->UnregisterAccessibilityPropertySetSignal();
+}
+
+void Control::Impl::OnAccessibilityPropertySet(Dali::Handle& handle, Dali::Property::Index index, const Dali::Property::Value& value)
+{
+ mAccessibilityData->OnAccessibilityPropertySet(handle, index, value);
+}
+
+bool Control::Impl::IsAccessibleCreated() const
+{
+ return mAccessibilityData->IsAccessibleCreated();
+}
+
+void Control::Impl::EnableCreateAccessible(bool enable)
+{
+ mAccessibilityData->EnableCreateAccessible(enable);
+}
+
+bool Control::Impl::IsCreateAccessibleEnabled() const
+{
+ return mAccessibilityData->IsCreateAccessibleEnabled();
+}
+
+void Control::Impl::ApplyFittingMode(const Vector2& size)
+{
+ mVisualData->ApplyFittingMode(size);
}
void Control::Impl::SetShadow(const Property::Map& map)
if(visual)
{
- mControlImpl.mImpl->RegisterVisual(Toolkit::DevelControl::Property::SHADOW, visual, DepthIndex::BACKGROUND_EFFECT);
+ mControlImpl.mImpl->mVisualData->RegisterVisual(Toolkit::DevelControl::Property::SHADOW, visual, DepthIndex::BACKGROUND_EFFECT);
mControlImpl.RelayoutRequest();
}
void Control::Impl::ClearShadow()
{
- mControlImpl.mImpl->UnregisterVisual(Toolkit::DevelControl::Property::SHADOW);
+ mControlImpl.mImpl->mVisualData->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(std::move(visualPropertyKey));
- }
-
- Handle handle;
- return Dali::Property(handle, Property::INVALID_INDEX);
+ return mVisualData->GetVisualProperty(index, visualPropertyKey);
}
void Control::Impl::CreateTransitions(std::vector<std::pair<Dali::Property::Index, Dali::Property::Map>>& sourceProperties,
void Control::Impl::UpdateVisualProperties(const std::vector<std::pair<Dali::Property::Index, Dali::Property::Map>>& properties)
{
- for(auto&& data : properties)
- {
- if(data.first == Toolkit::Control::Property::BACKGROUND)
- {
- DoAction(Toolkit::Control::Property::BACKGROUND, DevelVisual::Action::UPDATE_PROPERTY, data.second);
- }
- else if(data.first == Toolkit::DevelControl::Property::SHADOW)
- {
- DoAction(Toolkit::DevelControl::Property::SHADOW, DevelVisual::Action::UPDATE_PROPERTY, data.second);
- }
- }
- mControlImpl.OnUpdateVisualProperties(properties);
+ mVisualData->UpdateVisualProperties(properties);
}
void Control::Impl::EmitResourceReadySignal()
std::shared_ptr<Toolkit::DevelControl::ControlAccessible> Control::Impl::GetAccessibleObject()
{
- return std::dynamic_pointer_cast<DevelControl::ControlAccessible>(Accessibility::Accessible::GetOwningPtr(mControlImpl.Self()));
-}
-
-bool Control::Impl::IsAccessibleCreated() const
-{
- return !!Accessibility::Bridge::GetCurrentBridge()->GetAccessible(mControlImpl.Self());
-}
-
-void Control::Impl::EnableCreateAccessible(bool enable)
-{
- mAccessibleCreatable = enable;
-}
-
-bool Control::Impl::IsCreateAccessibleEnabled() const
-{
- return mAccessibleCreatable;
-}
-
-void Control::Impl::ApplyFittingMode(const Vector2& size)
-{
- Actor self = mControlImpl.Self();
- for(RegisteredVisualContainer::Iterator iter = mVisuals.Begin(); iter != mVisuals.End(); iter++)
- {
- // Check whether the visual is empty and enabled
- if((*iter)->visual && (*iter)->enabled)
- {
- Internal::Visual::Base& visualImpl = Toolkit::GetImplementation((*iter)->visual);
-
- // If the current visual is using the transform property map, fittingMode will not be applied.
- if(visualImpl.IsIgnoreFittingMode())
- {
- continue;
- }
-
- Visual::FittingMode fittingMode = visualImpl.GetFittingMode();
- Property::Map transformMap = Property::Map();
-
- // If the fittingMode is DONT_CARE, we don't need to apply fittingMode, just Set empty transformMap
- if(fittingMode == Visual::FittingMode::DONT_CARE)
- {
- if(visualImpl.GetType() != Toolkit::Visual::Type::TEXT)
- {
- ((*iter)->visual).SetTransformAndSize(transformMap, size);
- }
- continue;
- }
-
- Extents padding = self.GetProperty<Extents>(Toolkit::Control::Property::PADDING);
-
- bool zeroPadding = (padding == Extents());
-
- Dali::LayoutDirection::Type layoutDirection = static_cast<Dali::LayoutDirection::Type>(
- self.GetProperty(Dali::Actor::Property::LAYOUT_DIRECTION).Get<int>());
- if(Dali::LayoutDirection::RIGHT_TO_LEFT == layoutDirection)
- {
- std::swap(padding.start, padding.end);
- }
-
- // remove padding from the size to know how much is left for the visual
- Vector2 finalSize = size - Vector2(padding.start + padding.end, padding.top + padding.bottom);
- Vector2 finalOffset = Vector2(padding.start, padding.top);
-
- // Reset PIXEL_AREA after using OVER_FIT_KEEP_ASPECT_RATIO
- if(visualImpl.IsPixelAreaSetForFittingMode())
- {
- visualImpl.SetPixelAreaForFittingMode(FULL_TEXTURE_RECT);
- }
-
- if((!zeroPadding) || // If padding is not zero
- (fittingMode != Visual::FittingMode::FILL))
- {
- visualImpl.SetTransformMapUsageForFittingMode(true);
-
- Vector2 naturalSize;
- // NaturalSize will not be used for FILL fitting mode, which is default.
- // Skip GetNaturalSize
- if(fittingMode != Visual::FittingMode::FILL)
- {
- ((*iter)->visual).GetNaturalSize(naturalSize);
- }
-
- // If FittingMode use FIT_WIDTH or FIT_HEIGTH, it need to change proper fittingMode
- if(fittingMode == Visual::FittingMode::FIT_WIDTH || fittingMode == Visual::FittingMode::FIT_HEIGHT)
- {
- const float widthRatio = !Dali::EqualsZero(naturalSize.width) ? (finalSize.width / naturalSize.width) : 0.0f;
- const float heightRatio = !Dali::EqualsZero(naturalSize.height) ? (finalSize.height / naturalSize.height) : 0.0f;
- if(widthRatio < heightRatio)
- {
- // Final size has taller form than natural size.
- fittingMode = (fittingMode == Visual::FittingMode::FIT_WIDTH) ? Visual::FittingMode::FIT_KEEP_ASPECT_RATIO : Visual::FittingMode::OVER_FIT_KEEP_ASPECT_RATIO;
- }
- else
- {
- // Final size has wider form than natural size.
- fittingMode = (fittingMode == Visual::FittingMode::FIT_WIDTH) ? Visual::FittingMode::OVER_FIT_KEEP_ASPECT_RATIO : Visual::FittingMode::FIT_KEEP_ASPECT_RATIO;
- }
- }
-
- // Calculate size for fittingMode
- switch(fittingMode)
- {
- case Visual::FittingMode::FIT_KEEP_ASPECT_RATIO:
- {
- auto availableVisualSize = finalSize;
-
- // scale to fit the padded area
- finalSize = naturalSize * std::min((!Dali::EqualsZero(naturalSize.width) ? (availableVisualSize.width / naturalSize.width) : 0),
- (!Dali::EqualsZero(naturalSize.height) ? (availableVisualSize.height / naturalSize.height) : 0));
-
- // calculate final offset within the padded area
- finalOffset += (availableVisualSize - finalSize) * .5f;
-
- // populate the transform map
- transformMap.Add(Toolkit::Visual::Transform::Property::OFFSET, finalOffset)
- .Add(Toolkit::Visual::Transform::Property::SIZE, finalSize);
- break;
- }
- case Visual::FittingMode::OVER_FIT_KEEP_ASPECT_RATIO:
- {
- auto availableVisualSize = finalSize;
- finalSize = naturalSize * std::max((!Dali::EqualsZero(naturalSize.width) ? (availableVisualSize.width / naturalSize.width) : 0.0f),
- (!Dali::EqualsZero(naturalSize.height) ? (availableVisualSize.height / naturalSize.height) : 0.0f));
-
- auto originalOffset = finalOffset;
-
- if(!visualImpl.IsPixelAreaSetForFittingMode() && !Dali::EqualsZero(finalSize.width) && !Dali::EqualsZero(finalSize.height))
- {
- float x = abs((availableVisualSize.width - finalSize.width) / finalSize.width) * .5f;
- float y = abs((availableVisualSize.height - finalSize.height) / finalSize.height) * .5f;
- float widthRatio = 1.f - abs((availableVisualSize.width - finalSize.width) / finalSize.width);
- float heightRatio = 1.f - abs((availableVisualSize.height - finalSize.height) / finalSize.height);
- Vector4 pixelArea = Vector4(x, y, widthRatio, heightRatio);
- visualImpl.SetPixelAreaForFittingMode(pixelArea);
- }
-
- // populate the transform map
- transformMap.Add(Toolkit::Visual::Transform::Property::OFFSET, originalOffset)
- .Add(Toolkit::Visual::Transform::Property::SIZE, availableVisualSize);
- break;
- }
- case Visual::FittingMode::CENTER:
- {
- auto availableVisualSize = finalSize;
- if(availableVisualSize.width > naturalSize.width && availableVisualSize.height > naturalSize.height)
- {
- finalSize = naturalSize;
- }
- else
- {
- finalSize = naturalSize * std::min((!Dali::EqualsZero(naturalSize.width) ? (availableVisualSize.width / naturalSize.width) : 0.0f),
- (!Dali::EqualsZero(naturalSize.height) ? (availableVisualSize.height / naturalSize.height) : 0.0f));
- }
-
- finalOffset += (availableVisualSize - finalSize) * .5f;
-
- // populate the transform map
- transformMap.Add(Toolkit::Visual::Transform::Property::OFFSET, finalOffset)
- .Add(Toolkit::Visual::Transform::Property::SIZE, finalSize);
- break;
- }
- case Visual::FittingMode::FILL:
- {
- transformMap.Add(Toolkit::Visual::Transform::Property::OFFSET, finalOffset)
- .Add(Toolkit::Visual::Transform::Property::SIZE, finalSize);
- break;
- }
- case Visual::FittingMode::FIT_WIDTH:
- case Visual::FittingMode::FIT_HEIGHT:
- case Visual::FittingMode::DONT_CARE:
- {
- // This FittingMode already converted
- break;
- }
- }
-
- // Set extra value for applying transformMap
- transformMap.Add(Toolkit::Visual::Transform::Property::OFFSET_POLICY,
- Vector2(Toolkit::Visual::Transform::Policy::ABSOLUTE, Toolkit::Visual::Transform::Policy::ABSOLUTE))
- .Add(Toolkit::Visual::Transform::Property::ORIGIN, Toolkit::Align::TOP_BEGIN)
- .Add(Toolkit::Visual::Transform::Property::ANCHOR_POINT, Toolkit::Align::TOP_BEGIN)
- .Add(Toolkit::Visual::Transform::Property::SIZE_POLICY,
- Vector2(Toolkit::Visual::Transform::Policy::ABSOLUTE, Toolkit::Visual::Transform::Policy::ABSOLUTE));
- }
- else if(visualImpl.IsTransformMapSetForFittingMode() && zeroPadding) // Reset offset to zero only if padding applied previously
- {
- visualImpl.SetTransformMapUsageForFittingMode(false);
-
- // Reset the transform map
- transformMap.Add(Toolkit::Visual::Transform::Property::OFFSET, Vector2::ZERO)
- .Add(Toolkit::Visual::Transform::Property::OFFSET_POLICY,
- Vector2(Toolkit::Visual::Transform::Policy::RELATIVE, Toolkit::Visual::Transform::Policy::RELATIVE))
- .Add(Toolkit::Visual::Transform::Property::SIZE, Vector2::ONE)
- .Add(Toolkit::Visual::Transform::Property::SIZE_POLICY,
- Vector2(Toolkit::Visual::Transform::Policy::RELATIVE, Toolkit::Visual::Transform::Policy::RELATIVE));
- }
-
- ((*iter)->visual).SetTransformAndSize(transformMap, size);
- }
- }
+ return mAccessibilityData->GetAccessibleObject();
}
void Control::Impl::RegisterProcessorOnce()
void Control::Impl::Process(bool postProcessor)
{
// Call ApplyFittingMode
- ApplyFittingMode(mSize);
+ mVisualData->ApplyFittingMode(mSize);
mProcessorRegistered = false;
}
#include <string>
// INTERNAL INCLUDES
-#include <dali-toolkit/devel-api/controls/control-depth-index-ranges.h>
#include <dali-toolkit/devel-api/controls/control-devel.h>
-#include <dali-toolkit/devel-api/visual-factory/visual-base.h>
-#include <dali-toolkit/internal/builder/dictionary.h>
-#include <dali-toolkit/internal/builder/style.h>
#include <dali-toolkit/internal/controls/tooltip/tooltip.h>
-#include <dali-toolkit/internal/visuals/visual-event-observer.h>
#include <dali-toolkit/public-api/controls/control-impl.h>
#include <dali-toolkit/public-api/controls/render-effects/render-effect.h>
-#include <dali-toolkit/public-api/visuals/visual-properties.h>
-#include <dali/devel-api/common/owner-container.h>
#include <dali/integration-api/debug.h>
#include <map>
#include <memory>
{
namespace Internal
{
-/**
- * Struct used to store Visual within the control, index is a unique key for each visual.
- */
-struct RegisteredVisual
-{
- Property::Index index;
- Toolkit::Visual::Base visual;
- bool enabled : 1;
- bool pending : 1;
- bool overideReadyTransition : 1;
-
- RegisteredVisual(Property::Index aIndex, Toolkit::Visual::Base& aVisual, bool aEnabled, bool aPendingReplacement)
- : index(aIndex),
- visual(aVisual),
- enabled(aEnabled),
- pending(aPendingReplacement),
- overideReadyTransition(false)
- {
- }
-};
-
-typedef Dali::OwnerContainer<RegisteredVisual*> RegisteredVisualContainer;
-
enum class TriStateProperty
{
AUTO = 0,
/**
* @brief Holds the Implementation for the internal control class
*/
-class Control::Impl : public ConnectionTracker, public Visual::EventObserver, public Integration::Processor
+class Control::Impl : public ConnectionTracker, public Integration::Processor
{
- friend class Toolkit::DevelControl::ControlAccessible;
+private:
+ class AccessibilityData;
+ class VisualData;
public:
/**
*/
void ResourceReady();
- /**
- * @brief Called when a resource is ready.
- * @param[in] object The visual whose resources are ready
- * @note Overriding method in Visual::EventObserver.
- */
- void ResourceReady(Visual::Base& object) override;
-
- /**
- * @brief Called when an event occurs.
- * @param[in] object The visual whose events occur
- * @param[in] signalId The signal to emit. See Visual to find supported signals
- * @note Overriding method in Visual::EventObserver.
- */
- void NotifyVisualEvent(Visual::Base& object, Property::Index signalId) override;
-
- /**
- * @brief Called when the visual needs relayout request.
- * @param[in] object The visual who requests relayout
- */
- void RelayoutRequest(Visual::Base& object) override;
-
/**
* @copydoc Dali::Toolkit::DevelControl::RegisterVisual()
*/
*/
Toolkit::Visual::Base GetVisual(Property::Index index) const;
- /**
- * @copydoc Dali::Toolkit::DevelControl::EnableVisual()
- */
- void EnableVisual(Property::Index index, bool enable);
-
- /**
- * @copydoc Dali::Toolkit::DevelControl::IsVisualEnabled()
- */
- bool IsVisualEnabled(Property::Index index) const;
-
/**
* @brief Sets the given visual to be ready transition
*
void EnableReadyTransitionOverriden(Toolkit::Visual::Base& visual, bool enable);
/**
- * @brief Stops observing the given visual.
- * @param[in] visual The visual to stop observing
+ * @copydoc Dali::Toolkit::DevelControl::EnableVisual()
*/
- void StopObservingVisual(Toolkit::Visual::Base& visual);
+ void EnableVisual(Property::Index index, bool enable);
/**
- * @brief Starts observing the given visual.
- * @param[in] visual The visual to start observing
+ * @copydoc Dali::Toolkit::DevelControl::IsVisualEnabled()
*/
- void StartObservingVisual(Toolkit::Visual::Base& visual);
+ bool IsVisualEnabled(Property::Index index) const;
/**
* @copydoc Dali::Toolkit::DevelControl::GetVisualResourceStatus()
*/
void SetSubState(const std::string& subStateName, bool withTransitions = true);
- /**
- * @brief Replaces visuals and properties from the old state to the new state.
- * @param[in] oldState The old state
- * @param[in] newState The new state
- * @param[in] subState The current sub state
- */
- void ReplaceStateVisualsAndProperties(const StylePtr oldState, const StylePtr newState, const std::string& subState);
-
- /**
- * @brief Removes a visual from the control's container.
- * @param[in] visuals The container of visuals
- * @param[in] visualName The name of the visual to remove
- */
- void RemoveVisual(RegisteredVisualContainer& visuals, const std::string& visualName);
-
- /**
- * @brief Removes several visuals from the control's container.
- * @param[in] visuals The container of visuals
- * @param[in] removeVisuals The visuals to remove
- */
- void RemoveVisuals(RegisteredVisualContainer& visuals, DictionaryKeys& removeVisuals);
-
- /**
- * @brief Copies the visual properties that are specific to the control instance into the instancedProperties container.
- * @param[in] visuals The control's visual container
- * @param[out] instancedProperties The instanced properties are added to this container
- */
- void CopyInstancedProperties(RegisteredVisualContainer& visuals, Dictionary<Property::Map>& instancedProperties);
-
- /**
- * @brief On state change, ensures visuals are moved or created appropriately.
- *
- * Go through the list of visuals that are common to both states.
- * If they are different types, or are both image types with different
- * URLs, then the existing visual needs moving and the new visual needs creating
- *
- * @param[in] stateVisualsToChange The visuals to change
- * @param[in] instancedProperties The instanced properties @see CopyInstancedProperties
- */
- void RecreateChangedVisuals(Dictionary<Property::Map>& stateVisualsToChange, Dictionary<Property::Map>& instancedProperties);
-
/**
* @brief Whether the resource is ready
* @return True if the resource is read.
/**
* @brief Retrieves source and destination visual properties for the Transition of this Control.
- * The properties of this Control will be transitioned from the propeties of source Control to that of destination control.
+ * The properties of this Control will be transitioned from the properties of source Control to that of destination Control.
* If a property value is different between source and destination Control,
* the property information of each Control will be included in sourceProperties and destinationProperties.
*
}
private:
- /**
- * Used as an alternative to boolean so that it is obvious whether a visual is enabled/disabled.
- */
- struct VisualState
- {
- enum Type
- {
- DISABLED = 0, ///< Visual disabled.
- ENABLED = 1 ///< Visual enabled.
- };
- };
-
- /**
- * Used as an alternative to boolean so that it is obvious whether a visual's depth value has been set or not by the caller.
- */
- struct DepthIndexValue
- {
- enum Type
- {
- NOT_SET = 0, ///< Visual depth value not set by caller.
- SET = 1 ///< Visual depth value set by caller.
- };
- };
-
- /**
- * @brief Adds the visual to the list of registered visuals.
- * @param[in] index The Property index of the visual, used to reference visual
- * @param[in,out] visual The visual to register, which can be altered in this function
- * @param[in] enabled false if derived class wants to control when visual is set on stage
- * @param[in] depthIndexValueSet Set to true if the depthIndex has actually been set manually
- * @param[in] depthIndex The visual's depth-index is set to this. If the depth-index is set to DepthIndex::Ranges::AUTO_INDEX,
- * the actual depth-index of visual will be determind automatically (Use previous visuals depth-index, or placed on top of all other visuals.)
- * Otherwise, the visual's depth-index is set to clamped value, between DepthIndex::Ranges::MINIMUM_DEPTH_INDEX and DepthIndex::Ranges::MAXIMUM_DEPTH_INDEX.
- *
- * @note Registering a visual with an index that already has a registered visual will replace it. The replacement will
- * occur once the replacement visual is ready (loaded).
- */
- void RegisterVisual(Property::Index index, Toolkit::Visual::Base& visual, VisualState::Type enabled, DepthIndexValue::Type depthIndexValueSet, int depthIndex = static_cast<int>(Toolkit::DepthIndex::AUTO_INDEX));
-
/**
* @brief Emits the resource ready signal.
*/
void EmitResourceReadySignal();
-
/**
* @brief Callbacks called on idle.
*
DevelControl::State mState;
std::string mSubStateName;
+ AccessibilityData* mAccessibilityData;
+ VisualData* mVisualData;
+
int mLeftFocusableActorId; ///< Actor ID of Left focusable control.
int mRightFocusableActorId; ///< Actor ID of Right focusable control.
int mUpFocusableActorId; ///< Actor ID of Up focusable control.
int mClockwiseFocusableActorId; ///< Actor ID of Clockwise focusable control.
int mCounterClockwiseFocusableActorId; ///< Actor ID of Counter clockwise focusable control.
- RegisteredVisualContainer mVisuals; ///< Stores visuals needed by the control, non trivial type so std::vector used.
std::string mStyleName;
Vector4 mBackgroundColor; ///< The color of the background visual
RenderEffect mRenderEffect; ///< The render effect on this control
Toolkit::Control::KeyInputFocusSignalType mKeyInputFocusGainedSignal;
Toolkit::Control::KeyInputFocusSignalType mKeyInputFocusLostSignal;
Toolkit::Control::ResourceReadySignalType mResourceReadySignal;
- DevelControl::VisualEventSignalType mVisualEventSignal;
-
- // Accessibility
- Toolkit::DevelControl::AccessibilityActivateSignalType mAccessibilityActivateSignal;
- Toolkit::DevelControl::AccessibilityReadingSkippedSignalType mAccessibilityReadingSkippedSignal;
- Toolkit::DevelControl::AccessibilityReadingPausedSignalType mAccessibilityReadingPausedSignal;
- Toolkit::DevelControl::AccessibilityReadingResumedSignalType mAccessibilityReadingResumedSignal;
- Toolkit::DevelControl::AccessibilityReadingCancelledSignalType mAccessibilityReadingCancelledSignal;
- Toolkit::DevelControl::AccessibilityReadingStoppedSignalType mAccessibilityReadingStoppedSignal;
-
- Toolkit::DevelControl::AccessibilityGetNameSignalType mAccessibilityGetNameSignal;
- Toolkit::DevelControl::AccessibilityGetDescriptionSignalType mAccessibilityGetDescriptionSignal;
- Toolkit::DevelControl::AccessibilityDoGestureSignalType mAccessibilityDoGestureSignal;
-
- Toolkit::DevelControl::AccessibilityActionSignalType mAccessibilityActionSignal;
-
- struct AccessibilityProps
- {
- std::string name{};
- std::string description{};
- std::string value{};
- std::string automationId{};
- int32_t role{static_cast<int32_t>(DevelControl::AccessibilityRole::NONE)};
- DevelControl::AccessibilityStates states{};
- std::map<Dali::Accessibility::RelationType, std::set<Accessibility::Accessible*>> relations;
- Property::Map extraAttributes{};
- TriStateProperty isHighlightable{TriStateProperty::AUTO};
- bool isHidden{false};
- bool isScrollable{false};
- bool isModal{false};
- } mAccessibilityProps;
-
- bool mAccessibleCreatable = true;
// Gesture Detection
PinchGestureDetector mPinchGestureDetector;
bool mDispatchKeyEvents : 1; ///< Whether the actor emits key event signals
bool mProcessorRegistered : 1; ///< Whether the processor is registered.
- RegisteredVisualContainer mRemoveVisuals; ///< List of visuals that are being replaced by another visual once ready
-
// Properties - these need to be members of Internal::Control::Impl as they access private methods/data of Internal::Control and Internal::Control::Impl.
static const PropertyRegistration PROPERTY_1;
static const PropertyRegistration PROPERTY_2;
static const PropertyRegistration PROPERTY_28;
static const PropertyRegistration PROPERTY_29;
static const PropertyRegistration PROPERTY_30;
-
-private:
- // Accessibility - notification for highlighted object to check if it is showing.
- bool mIsAccessibilityPositionPropertyNotificationSet{false};
- bool mIsAccessibilityPropertySetSignalRegistered{false};
- Dali::PropertyNotification mAccessibilityPositionNotification;
- Dali::Accessibility::ScreenRelativeMoveType mAccessibilityLastScreenRelativeMoveType{Accessibility::ScreenRelativeMoveType::OUTSIDE};
};
} // namespace Internal
/*
- * Copyright (c) 2021 Samsung Electronics Co., Ltd.
+ * Copyright (c) 2024 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.
#include <dali-toolkit/internal/controls/control/control-data-impl.h>
#include <dali-toolkit/internal/controls/control/control-debug.h>
+#include <dali-toolkit/internal/controls/control/control-visual-data.h>
#include <dali-toolkit/internal/visuals/visual-base-impl.h>
#include <dali-toolkit/public-api/controls/control-impl.h>
#include <dali/integration-api/debug.h>
}
oss << "\"id\":\"" << control.Self().GetProperty<int>(Actor::Property::ID) << "\",\n";
oss << "\"registeredVisuals\":\n"
- << controlData.mVisuals << ",\n";
+ << controlData.mVisualData->mVisuals << ",\n";
oss << "\"removeVisuals\":\n"
- << controlData.mRemoveVisuals << ",\n";
+ << controlData.mVisualData->mRemoveVisuals << ",\n";
oss << "\"rendererCount\":" << control.Self().GetRendererCount() << ",\n";
oss << "\"properties\":\n{\n";
DumpProperties(oss, control.Self()) << "}\n";
--- /dev/null
+/*
+ * Copyright (c) 2024 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.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+// CLASS HEADER
+#include "control-visual-data.h"
+
+// EXTERNAL INCLUDES
+#include <dali/devel-api/common/stage.h>
+#include <dali/integration-api/adaptor-framework/adaptor.h>
+
+// INTERNAL INCLUDES
+#include <dali-toolkit/devel-api/visuals/visual-actions-devel.h>
+#include <dali-toolkit/internal/visuals/visual-base-impl.h>
+#include <dali-toolkit/internal/visuals/visual-string-constants.h>
+#include <dali-toolkit/public-api/align-enumerations.h>
+#include <dali-toolkit/public-api/visuals/image-visual-properties.h>
+#include <dali-toolkit/public-api/visuals/visual-properties.h>
+
+namespace Dali
+{
+namespace Toolkit
+{
+namespace Internal
+{
+namespace
+{
+const Vector4 FULL_TEXTURE_RECT(0.f, 0.f, 1.f, 1.f);
+
+#if defined(DEBUG_ENABLED)
+Debug::Filter* gLogFilter = Debug::Filter::New(Debug::NoLogging, false, "LOG_CONTROL_VISUALS");
+#endif
+
+template<typename T>
+void Remove(Dictionary<T>& keyValues, const std::string& name)
+{
+ keyValues.Remove(name);
+}
+
+void Remove(DictionaryKeys& keys, const std::string& name)
+{
+ DictionaryKeys::iterator iter = std::find(keys.begin(), keys.end(), name);
+ if(iter != keys.end())
+ {
+ keys.erase(iter);
+ }
+}
+
+/**
+ * Finds visual in given array, returning true if found along with the iterator for that visual as a out parameter
+ */
+bool FindVisual(Property::Index targetIndex, const RegisteredVisualContainer& visuals, RegisteredVisualContainer::Iterator& iter)
+{
+ for(iter = visuals.Begin(); iter != visuals.End(); iter++)
+ {
+ if((*iter)->index == targetIndex)
+ {
+ return true;
+ }
+ }
+ return false;
+}
+
+/**
+ * Finds visual in given array, returning true if found along with the iterator for that visual as a out parameter
+ */
+bool FindVisual(std::string visualName, const RegisteredVisualContainer& visuals, RegisteredVisualContainer::Iterator& iter)
+{
+ for(iter = visuals.Begin(); iter != visuals.End(); iter++)
+ {
+ Toolkit::Visual::Base visual = (*iter)->visual;
+ if(visual && visual.GetName() == visualName)
+ {
+ return true;
+ }
+ }
+ 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<Property::Map>& stateVisualsToAdd,
+ Dictionary<Property::Map>& stateVisualsToChange,
+ DictionaryKeys& stateVisualsToRemove)
+{
+ DictionaryKeys copyOfStateVisualsToRemove = stateVisualsToRemove;
+
+ for(DictionaryKeys::iterator iter = copyOfStateVisualsToRemove.begin();
+ iter != copyOfStateVisualsToRemove.end();
+ ++iter)
+ {
+ const std::string& visualName = (*iter);
+ Property::Map* toMap = stateVisualsToAdd.Find(visualName);
+ if(toMap)
+ {
+ stateVisualsToChange.Add(visualName, *toMap);
+ stateVisualsToAdd.Remove(visualName);
+ Remove(stateVisualsToRemove, visualName);
+ }
+ }
+}
+
+Toolkit::Visual::Base GetVisualByName(
+ const RegisteredVisualContainer& visuals,
+ const std::string& visualName)
+{
+ Toolkit::Visual::Base visualHandle;
+
+ RegisteredVisualContainer::Iterator iter;
+ for(iter = visuals.Begin(); iter != visuals.End(); iter++)
+ {
+ Toolkit::Visual::Base visual = (*iter)->visual;
+ if(visual && visual.GetName() == visualName)
+ {
+ visualHandle = visual;
+ break;
+ }
+ }
+ return visualHandle;
+}
+
+Toolkit::Visual::Base GetVisualByIndex(
+ const RegisteredVisualContainer& visuals,
+ Property::Index index)
+{
+ Toolkit::Visual::Base visualHandle;
+
+ RegisteredVisualContainer::Iterator iter;
+ for(iter = visuals.Begin(); iter != visuals.End(); iter++)
+ {
+ if((*iter)->index == index)
+ {
+ visualHandle = (*iter)->visual;
+ break;
+ }
+ }
+ return visualHandle;
+}
+
+/**
+ * Move visual from source to destination container
+ */
+void MoveVisual(RegisteredVisualContainer::Iterator sourceIter, RegisteredVisualContainer& source, RegisteredVisualContainer& destination)
+{
+ Toolkit::Visual::Base visual = (*sourceIter)->visual;
+ if(visual)
+ {
+ RegisteredVisual* rv = source.Release(sourceIter);
+ destination.PushBack(rv);
+ }
+}
+
+/**
+ * Discard visual from source to visual factory.
+ */
+void DiscardVisual(RegisteredVisualContainer::Iterator sourceIter, RegisteredVisualContainer& source)
+{
+ Toolkit::Visual::Base visual = (*sourceIter)->visual;
+ if(visual)
+ {
+ if(DALI_LIKELY(Dali::Adaptor::IsAvailable()))
+ {
+ Toolkit::VisualFactory::Get().DiscardVisual(visual);
+ }
+ }
+
+ source.Erase(sourceIter);
+}
+
+/**
+ * @brief Iterate through given container and setOffScene any visual found
+ *
+ * @param[in] container Container of visuals
+ * @param[in] parent Parent actor to remove visuals from
+ */
+void SetVisualsOffScene(const RegisteredVisualContainer& container, Actor parent)
+{
+ for(auto iter = container.Begin(), end = container.End(); iter != end; iter++)
+ {
+ if((*iter)->visual)
+ {
+ DALI_LOG_INFO(gLogFilter, Debug::Verbose, "Control::SetOffScene Setting visual(%d) off stage\n", (*iter)->index);
+ Toolkit::GetImplementation((*iter)->visual).SetOffScene(parent);
+ }
+ }
+}
+} // unnamed namespace
+
+Control::Impl::VisualData::VisualData(Control::Impl& outer)
+: mVisualEventSignal(),
+ mOuter(outer)
+{
+}
+
+Control::Impl::VisualData::~VisualData()
+{
+}
+
+void Control::Impl::VisualData::ClearScene(Actor parent)
+{
+ SetVisualsOffScene(mVisuals, parent);
+
+ if(!mRemoveVisuals.Empty())
+ {
+ std::reverse(mRemoveVisuals.Begin(), mRemoveVisuals.End());
+
+ while(!mRemoveVisuals.Empty())
+ {
+ auto removalIter = mRemoveVisuals.End() - 1u;
+ Toolkit::GetImplementation((*removalIter)->visual).SetOffScene(parent);
+
+ // 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;
+ }
+}
+
+// Called by a Visual when it's resource is ready
+void Control::Impl::VisualData::ResourceReady(Visual::Base& object)
+{
+ DALI_LOG_INFO(gLogFilter, Debug::Verbose, "Control::Impl::VisualData::ResourceReady() replacements pending[%d]\n", mRemoveVisuals.Count());
+
+ Actor self = mOuter.mControlImpl.Self();
+
+ RegisteredVisualContainer::Iterator registeredIter;
+
+ // A resource is ready, find resource in the registered visuals container and get its index
+ if(!FindVisual(object, mVisuals, registeredIter))
+ {
+ return;
+ }
+
+ 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))
+ {
+ 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
+ if(((*registeredIter)->enabled))
+ {
+ mOuter.ResourceReady();
+ }
+}
+
+void Control::Impl::VisualData::NotifyVisualEvent(Visual::Base& object, Property::Index signalId)
+{
+ for(auto registeredIter = mVisuals.Begin(), end = mVisuals.End(); registeredIter != end; ++registeredIter)
+ {
+ Internal::Visual::Base& registeredVisualImpl = Toolkit::GetImplementation((*registeredIter)->visual);
+ if(&object == ®isteredVisualImpl)
+ {
+ Dali::Toolkit::Control handle(mOuter.mControlImpl.GetOwner());
+ mVisualEventSignal.Emit(handle, (*registeredIter)->index, signalId);
+ break;
+ }
+ }
+}
+
+void Control::Impl::VisualData::RelayoutRequest(Visual::Base& object)
+{
+ if(mOuter.mControlImpl.Self().GetProperty<bool>(Actor::Property::CONNECTED_TO_SCENE))
+ {
+ mOuter.mControlImpl.RelayoutRequest();
+ }
+}
+
+bool Control::Impl::VisualData::IsResourceReady() const
+{
+ // Iterate through and check all the enabled visuals are ready
+ for(auto visualIter = mVisuals.Begin();
+ visualIter != mVisuals.End();
+ ++visualIter)
+ {
+ const Toolkit::Visual::Base visual = (*visualIter)->visual;
+ const Internal::Visual::Base& visualImpl = Toolkit::GetImplementation(visual);
+
+ // one of the enabled visuals is not ready
+ if(!visualImpl.IsResourceReady() && (*visualIter)->enabled)
+ {
+ return false;
+ }
+ }
+ return true;
+}
+
+Toolkit::Visual::ResourceStatus Control::Impl::VisualData::GetVisualResourceStatus(Property::Index index) const
+{
+ RegisteredVisualContainer::Iterator iter;
+ if(FindVisual(index, mVisuals, iter))
+ {
+ const Toolkit::Visual::Base visual = (*iter)->visual;
+ const Internal::Visual::Base& visualImpl = Toolkit::GetImplementation(visual);
+ return visualImpl.GetResourceStatus();
+ }
+
+ return Toolkit::Visual::ResourceStatus::PREPARING;
+}
+
+void Control::Impl::VisualData::CopyInstancedProperties(RegisteredVisualContainer& visuals, Dictionary<Property::Map>& instancedProperties)
+{
+ for(RegisteredVisualContainer::Iterator iter = visuals.Begin(); iter != visuals.End(); iter++)
+ {
+ if((*iter)->visual)
+ {
+ Property::Map instanceMap;
+ Toolkit::GetImplementation((*iter)->visual).CreateInstancePropertyMap(instanceMap);
+ instancedProperties.Add((*iter)->visual.GetName(), instanceMap);
+ }
+ }
+}
+
+void Control::Impl::VisualData::RegisterVisual(Property::Index index, Toolkit::Visual::Base& visual)
+{
+ RegisterVisual(index, visual, VisualState::ENABLED, DepthIndexValue::NOT_SET);
+}
+
+void Control::Impl::VisualData::RegisterVisual(Property::Index index, Toolkit::Visual::Base& visual, int depthIndex)
+{
+ RegisterVisual(index, visual, VisualState::ENABLED, DepthIndexValue::SET, depthIndex);
+}
+
+void Control::Impl::VisualData::RegisterVisual(Property::Index index, Toolkit::Visual::Base& visual, bool enabled)
+{
+ RegisterVisual(index, visual, (enabled ? VisualState::ENABLED : VisualState::DISABLED), DepthIndexValue::NOT_SET);
+}
+
+void Control::Impl::VisualData::RegisterVisual(Property::Index index, Toolkit::Visual::Base& visual, bool enabled, int depthIndex)
+{
+ RegisterVisual(index, visual, (enabled ? VisualState::ENABLED : VisualState::DISABLED), DepthIndexValue::SET, depthIndex);
+}
+
+void Control::Impl::VisualData::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);
+ Actor self = mOuter.mControlImpl.Self();
+
+ // Set the depth index, if not set by caller this will be either the current visual depth, max depth of all visuals
+ // or zero.
+ int requiredDepthIndex = visual.GetDepthIndex();
+
+ if(depthIndexValueSet == DepthIndexValue::SET)
+ {
+ requiredDepthIndex = depthIndex;
+ }
+
+ // Change the depth index value automatically if the visual has DepthIndex to AUTO_INDEX
+ // or if RegisterVisual set DepthIndex to AUTO_INDEX.
+ const bool requiredDepthIndexChanged = (requiredDepthIndex == DepthIndex::AUTO_INDEX);
+
+ // Visual replacement, existing visual should only be removed from stage when replacement ready.
+ if(!mVisuals.Empty())
+ {
+ RegisteredVisualContainer::Iterator registeredVisualsiter;
+ // Check if visual (index) is already registered, this is the current visual.
+ if(FindVisual(index, mVisuals, registeredVisualsiter))
+ {
+ Toolkit::Visual::Base& currentRegisteredVisual = (*registeredVisualsiter)->visual;
+ if(currentRegisteredVisual)
+ {
+ // Store current visual depth index as may need to set the replacement visual to same depth
+ const int currentDepthIndex = (*registeredVisualsiter)->visual.GetDepthIndex();
+
+ // No longer required to know if the replaced visual's resources are ready
+ StopObservingVisual(currentRegisteredVisual);
+
+ // If control staged and visual enabled then visuals will be swapped once ready
+ if(self.GetProperty<bool>(Actor::Property::CONNECTED_TO_SCENE) && enabled)
+ {
+ // Check if visual is currently in the process of being replaced ( is in removal container )
+ RegisteredVisualContainer::Iterator visualQueuedForRemoval;
+ if(FindVisual(index, mRemoveVisuals, visualQueuedForRemoval))
+ {
+ // Visual with same index is already in removal container so current visual pending
+ // Only the the last requested visual will be displayed so remove current visual which is staged but not ready.
+ Toolkit::GetImplementation(currentRegisteredVisual).SetOffScene(self);
+ mVisuals.Erase(registeredVisualsiter);
+ }
+ else
+ {
+ // current visual not already in removal container so add now.
+ DALI_LOG_INFO(gLogFilter, Debug::Verbose, "RegisterVisual Move current registered visual to removal Queue: %d \n", index);
+ MoveVisual(registeredVisualsiter, mVisuals, mRemoveVisuals);
+ }
+ }
+ else
+ {
+ // Control not staged or visual disabled so can just erase from registered visuals and new visual will be added later.
+ mVisuals.Erase(registeredVisualsiter);
+ }
+
+ // If the visual have a depth index as AUTO_INDEX and the new visual does not have a depth index applied to it, then use the previously set depth-index for this index
+ if(requiredDepthIndexChanged)
+ {
+ requiredDepthIndex = currentDepthIndex;
+ DALI_LOG_INFO(gLogFilter, Debug::Verbose, "Use replaced visual index. VisualDepthIndex AUTO_INDEX set as: %d\n", requiredDepthIndex);
+ }
+ }
+
+ visualReplaced = true;
+ }
+ }
+
+ // If not set, set the name of the visual to the same name as the control's property.
+ // ( If the control has been type registered )
+ if(visual.GetName().empty())
+ {
+ // returns empty string if index is not found as long as index is not -1
+ std::string visualName = self.GetPropertyName(index);
+ if(!visualName.empty())
+ {
+ DALI_LOG_INFO(gLogFilter, Debug::Concise, "Setting visual name for property %d to %s\n", index, visualName.c_str());
+ visual.SetName(visualName);
+ }
+ }
+
+ if(!visualReplaced) // New registration entry
+ {
+ // If we have more than one visual and the visual have a depth index as AUTO_INDEX, then set it to be the highest
+ if((mVisuals.Size() > 0) && requiredDepthIndexChanged)
+ {
+ int maxDepthIndex = static_cast<int>(DepthIndex::CONTENT) - 1; // Start at DepthIndex::CONTENT if maxDepth index belongs to a background or no visuals have been added yet.
+
+ RegisteredVisualContainer::ConstIterator iter;
+ const RegisteredVisualContainer::ConstIterator endIter = mVisuals.End();
+ for(iter = mVisuals.Begin(); iter != endIter; iter++)
+ {
+ const int visualDepthIndex = (*iter)->visual.GetDepthIndex();
+ if(visualDepthIndex > maxDepthIndex)
+ {
+ maxDepthIndex = visualDepthIndex;
+ }
+ }
+ requiredDepthIndex = ++maxDepthIndex; // Add one to the current maximum depth index so that our added visual appears on top.
+ DALI_LOG_INFO(gLogFilter, Debug::Verbose, "Use top of all visuals. VisualDepthIndex AUTO_INDEX set as: %d\n", requiredDepthIndex);
+ }
+ }
+
+ if(visual)
+ {
+ // If required depth index still DepthIndex::AUTO_INDEX, Make it as DepthIndex::CONTENT now
+ if(requiredDepthIndex == static_cast<int>(DepthIndex::AUTO_INDEX))
+ {
+ requiredDepthIndex = static_cast<int>(DepthIndex::CONTENT);
+ DALI_LOG_INFO(gLogFilter, Debug::Verbose, "Some strange cases. VisualDepthIndex AUTO_INDEX set as: %d\n", requiredDepthIndex);
+ }
+
+ // Set determined depth index
+ visual.SetDepthIndex(requiredDepthIndex);
+
+ // Monitor when the visual resources are ready
+ StartObservingVisual(visual);
+
+ DALI_LOG_INFO(gLogFilter, Debug::Concise, "New Visual registration index[%d] depth[%d]\n", index, requiredDepthIndex);
+ RegisteredVisual* newRegisteredVisual = new RegisteredVisual(index, visual, (enabled == VisualState::ENABLED ? true : false), (visualReplaced && enabled));
+ mVisuals.PushBack(newRegisteredVisual);
+
+ Internal::Visual::Base& visualImpl = Toolkit::GetImplementation(visual);
+ // Put on stage if enabled and the control is already on the stage
+ if((enabled == VisualState::ENABLED) && self.GetProperty<bool>(Actor::Property::CONNECTED_TO_SCENE))
+ {
+ visualImpl.SetOnScene(self);
+ }
+ 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);
+ }
+ }
+
+ DALI_LOG_INFO(gLogFilter, Debug::Verbose, "Control::RegisterVisual() Registered %s(%d), enabled:%s\n", visual.GetName().c_str(), index, enabled ? "true" : "false");
+}
+
+void Control::Impl::VisualData::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))
+ {
+ // stop observing visual
+ StopObservingVisual((*iter)->visual);
+
+ Actor self(mOuter.mControlImpl.Self());
+ Toolkit::GetImplementation((*iter)->visual).SetOffScene(self);
+ (*iter)->visual.Reset();
+ mVisuals.Erase(iter);
+ }
+
+ if(FindVisual(index, mRemoveVisuals, iter))
+ {
+ Actor self(mOuter.mControlImpl.Self());
+ Toolkit::GetImplementation((*iter)->visual).SetOffScene(self);
+ (*iter)->pending = false;
+
+ // Discard removed visual. It will be destroyed at next Idle time.
+ DiscardVisual(iter, mRemoveVisuals);
+ }
+}
+
+Toolkit::Visual::Base Control::Impl::VisualData::GetVisual(Property::Index index) const
+{
+ RegisteredVisualContainer::Iterator iter;
+ if(FindVisual(index, mVisuals, iter))
+ {
+ return (*iter)->visual;
+ }
+
+ return Toolkit::Visual::Base();
+}
+
+Toolkit::Visual::Base Control::Impl::VisualData::GetVisual(const std::string& name) const
+{
+ return GetVisualByName(mVisuals, name);
+}
+
+void Control::Impl::VisualData::EnableVisual(Property::Index index, bool enable)
+{
+ DALI_LOG_INFO(gLogFilter, Debug::General, "Control::EnableVisual(%d, %s)\n", index, enable ? "T" : "F");
+
+ RegisteredVisualContainer::Iterator iter;
+ if(FindVisual(index, mVisuals, iter))
+ {
+ if((*iter)->enabled == enable)
+ {
+ DALI_LOG_INFO(gLogFilter, Debug::Verbose, "Control::EnableVisual Visual %s(%d) already %s\n", (*iter)->visual.GetName().c_str(), index, enable ? "enabled" : "disabled");
+ return;
+ }
+
+ (*iter)->enabled = enable;
+ Actor parentActor = mOuter.mControlImpl.Self();
+ if(mOuter.mControlImpl.Self().GetProperty<bool>(Actor::Property::CONNECTED_TO_SCENE)) // If control not on Scene then Visual will be added when SceneConnection is called.
+ {
+ if(enable)
+ {
+ DALI_LOG_INFO(gLogFilter, Debug::Verbose, "Control::EnableVisual Setting %s(%d) on stage \n", (*iter)->visual.GetName().c_str(), index);
+ Toolkit::GetImplementation((*iter)->visual).SetOnScene(parentActor);
+ }
+ else
+ {
+ DALI_LOG_INFO(gLogFilter, Debug::Verbose, "Control::EnableVisual Setting %s(%d) off stage \n", (*iter)->visual.GetName().c_str(), index);
+ Toolkit::GetImplementation((*iter)->visual).SetOffScene(parentActor); // No need to call if control not staged.
+ }
+ }
+ }
+ else
+ {
+ DALI_LOG_WARNING("Control::EnableVisual(%d, %s) FAILED - NO SUCH VISUAL\n", index, enable ? "T" : "F");
+ }
+}
+
+void Control::Impl::VisualData::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;
+ }
+}
+
+bool Control::Impl::VisualData::IsVisualEnabled(Property::Index index) const
+{
+ RegisteredVisualContainer::Iterator iter;
+ if(FindVisual(index, mVisuals, iter))
+ {
+ return (*iter)->enabled;
+ }
+ return false;
+}
+
+void Control::Impl::VisualData::RemoveVisual(RegisteredVisualContainer& visuals, const std::string& visualName)
+{
+ Actor self(mOuter.mControlImpl.Self());
+
+ for(RegisteredVisualContainer::Iterator visualIter = visuals.Begin();
+ visualIter != visuals.End();
+ ++visualIter)
+ {
+ Toolkit::Visual::Base visual = (*visualIter)->visual;
+ if(visual && visual.GetName() == visualName)
+ {
+ Toolkit::GetImplementation(visual).SetOffScene(self);
+ (*visualIter)->visual.Reset();
+ visuals.Erase(visualIter);
+ break;
+ }
+ }
+}
+
+void Control::Impl::VisualData::RemoveVisuals(RegisteredVisualContainer& visuals, DictionaryKeys& removeVisuals)
+{
+ Actor self(mOuter.mControlImpl.Self());
+ for(DictionaryKeys::iterator iter = removeVisuals.begin(); iter != removeVisuals.end(); ++iter)
+ {
+ const std::string visualName = *iter;
+ RemoveVisual(visuals, visualName);
+ }
+}
+
+void Control::Impl::VisualData::RecreateChangedVisuals(Dictionary<Property::Map>& stateVisualsToChange,
+ Dictionary<Property::Map>& instancedProperties)
+{
+ Dali::CustomActor handle(mOuter.mControlImpl.GetOwner());
+ for(Dictionary<Property::Map>::iterator iter = stateVisualsToChange.Begin();
+ iter != stateVisualsToChange.End();
+ ++iter)
+ {
+ const std::string& visualName = (*iter).key;
+ const Property::Map& toMap = (*iter).entry;
+
+ Actor self = mOuter.mControlImpl.Self();
+ RegisteredVisualContainer::Iterator registeredVisualsiter;
+ // Check if visual (visualName) is already registered, this is the current visual.
+ if(FindVisual(visualName, mVisuals, registeredVisualsiter))
+ {
+ Toolkit::Visual::Base& visual = (*registeredVisualsiter)->visual;
+ if(visual)
+ {
+ // No longer required to know if the replaced visual's resources are ready
+ StopObservingVisual(visual);
+
+ // If control staged then visuals will be swapped once ready
+ if(self.GetProperty<bool>(Actor::Property::CONNECTED_TO_SCENE))
+ {
+ // Check if visual is currently in the process of being replaced ( is in removal container )
+ RegisteredVisualContainer::Iterator visualQueuedForRemoval;
+ if(FindVisual(visualName, mRemoveVisuals, visualQueuedForRemoval))
+ {
+ // Visual with same visual name is already in removal container so current visual pending
+ // Only the the last requested visual will be displayed so remove current visual which is staged but not ready.
+ Toolkit::GetImplementation(visual).SetOffScene(self);
+ (*registeredVisualsiter)->visual.Reset();
+ mVisuals.Erase(registeredVisualsiter);
+ }
+ else
+ {
+ // current visual not already in removal container so add now.
+ DALI_LOG_INFO(gLogFilter, Debug::Verbose, "RegisterVisual Move current registered visual to removal Queue: %s \n", visualName.c_str());
+ MoveVisual(registeredVisualsiter, mVisuals, mRemoveVisuals);
+ }
+ }
+ else
+ {
+ // Control not staged or visual disabled so can just erase from registered visuals and new visual will be added later.
+ (*registeredVisualsiter)->visual.Reset();
+ mVisuals.Erase(registeredVisualsiter);
+ }
+ }
+
+ const Property::Map* instancedMap = instancedProperties.FindConst(visualName);
+ Style::ApplyVisual(handle, visualName, toMap, instancedMap);
+ }
+ }
+}
+
+void Control::Impl::VisualData::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)
+ {
+ oldState->visuals.GetKeys(stateVisualsToRemove);
+ if(!subState.empty())
+ {
+ const StylePtr* oldSubState = oldState->subStates.FindConst(subState);
+ if(oldSubState)
+ {
+ DictionaryKeys subStateVisualsToRemove;
+ (*oldSubState)->visuals.GetKeys(subStateVisualsToRemove);
+ Merge(stateVisualsToRemove, subStateVisualsToRemove);
+ }
+ }
+ }
+
+ // Collect all new visual properties
+ Dictionary<Property::Map> stateVisualsToAdd;
+ if(newState)
+ {
+ stateVisualsToAdd = newState->visuals;
+ if(!subState.empty())
+ {
+ const StylePtr* newSubState = newState->subStates.FindConst(subState);
+ if(newSubState)
+ {
+ stateVisualsToAdd.Merge((*newSubState)->visuals);
+ }
+ }
+ }
+
+ // If a name is in both add/remove, move it to change list.
+ Dictionary<Property::Map> stateVisualsToChange;
+ FindChangableVisuals(stateVisualsToAdd, stateVisualsToChange, stateVisualsToRemove);
+
+ // Copy instanced properties (e.g. text label) of current visuals
+ Dictionary<Property::Map> instancedProperties;
+ CopyInstancedProperties(mVisuals, instancedProperties);
+
+ // For each visual in remove list, remove from mVisuals
+ RemoveVisuals(mVisuals, stateVisualsToRemove);
+
+ // For each visual in add list, create and add to mVisuals
+ Dali::CustomActor handle(mOuter.mControlImpl.GetOwner());
+ Style::ApplyVisuals(handle, stateVisualsToAdd, instancedProperties);
+
+ // For each visual in change list, if it requires a new visual,
+ // remove old visual, create and add to mVisuals
+ RecreateChangedVisuals(stateVisualsToChange, instancedProperties);
+}
+
+DevelControl::VisualEventSignalType& Control::Impl::VisualData::VisualEventSignal()
+{
+ return mVisualEventSignal;
+}
+
+void Control::Impl::VisualData::DoAction(Dali::Property::Index visualIndex, Dali::Property::Index actionId, const Dali::Property::Value attributes)
+{
+ RegisteredVisualContainer::Iterator iter;
+ if(FindVisual(visualIndex, mVisuals, iter))
+ {
+ Toolkit::GetImplementation((*iter)->visual).DoAction(actionId, attributes);
+ }
+}
+
+void Control::Impl::VisualData::DoActionExtension(Dali::Property::Index visualIndex, Dali::Property::Index actionId, Dali::Any attributes)
+{
+ RegisteredVisualContainer::Iterator iter;
+ if(FindVisual(visualIndex, mVisuals, iter))
+ {
+ Toolkit::GetImplementation((*iter)->visual).DoActionExtension(actionId, attributes);
+ }
+}
+
+void Control::Impl::VisualData::ClearVisuals()
+{
+ while(!mVisuals.Empty())
+ {
+ auto iter = mVisuals.End() - 1u;
+ StopObservingVisual((*iter)->visual);
+
+ // Discard removed visual. It will be destroyed at next Idle time.
+ DiscardVisual(iter, mVisuals);
+ }
+
+ while(!mRemoveVisuals.Empty())
+ {
+ auto removalIter = mRemoveVisuals.End() - 1u;
+ StopObservingVisual((*removalIter)->visual);
+
+ // Discard removed visual. It will be destroyed at next Idle time.
+ DiscardVisual(removalIter, mRemoveVisuals);
+ }
+}
+
+Dali::Property Control::Impl::VisualData::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(std::move(visualPropertyKey));
+ }
+
+ Handle handle;
+ return Dali::Property(handle, Property::INVALID_INDEX);
+}
+
+void Control::Impl::VisualData::StopObservingVisual(Toolkit::Visual::Base& visual)
+{
+ Internal::Visual::Base& visualImpl = Toolkit::GetImplementation(visual);
+
+ // Stop observing the visual
+ visualImpl.RemoveEventObserver(*this);
+}
+
+void Control::Impl::VisualData::StartObservingVisual(Toolkit::Visual::Base& visual)
+{
+ Internal::Visual::Base& visualImpl = Toolkit::GetImplementation(visual);
+
+ // start observing the visual for events
+ visualImpl.AddEventObserver(*this);
+}
+
+void Control::Impl::VisualData::UpdateVisualProperties(const std::vector<std::pair<Dali::Property::Index, Dali::Property::Map>>& properties)
+{
+ for(auto&& data : properties)
+ {
+ if(data.first == Toolkit::Control::Property::BACKGROUND)
+ {
+ DoAction(Toolkit::Control::Property::BACKGROUND, DevelVisual::Action::UPDATE_PROPERTY, data.second);
+ }
+ else if(data.first == Toolkit::DevelControl::Property::SHADOW)
+ {
+ DoAction(Toolkit::DevelControl::Property::SHADOW, DevelVisual::Action::UPDATE_PROPERTY, data.second);
+ }
+ }
+ mOuter.mControlImpl.OnUpdateVisualProperties(properties);
+}
+
+void Control::Impl::VisualData::ApplyFittingMode(const Vector2& size)
+{
+ Actor self = mOuter.mControlImpl.Self();
+ for(RegisteredVisualContainer::Iterator iter = mVisuals.Begin(); iter != mVisuals.End(); iter++)
+ {
+ // Check whether the visual is empty and enabled
+ if((*iter)->visual && (*iter)->enabled)
+ {
+ Internal::Visual::Base& visualImpl = Toolkit::GetImplementation((*iter)->visual);
+
+ // If the current visual is using the transform property map, fittingMode will not be applied.
+ if(visualImpl.IsIgnoreFittingMode())
+ {
+ continue;
+ }
+
+ Visual::FittingMode fittingMode = visualImpl.GetFittingMode();
+ Property::Map transformMap = Property::Map();
+
+ // If the fittingMode is DONT_CARE, we don't need to apply fittingMode, just Set empty transformMap
+ if(fittingMode == Visual::FittingMode::DONT_CARE)
+ {
+ if(visualImpl.GetType() != Toolkit::Visual::Type::TEXT)
+ {
+ ((*iter)->visual).SetTransformAndSize(transformMap, size);
+ }
+ continue;
+ }
+
+ Extents padding = self.GetProperty<Extents>(Toolkit::Control::Property::PADDING);
+
+ bool zeroPadding = (padding == Extents());
+
+ Dali::LayoutDirection::Type layoutDirection = static_cast<Dali::LayoutDirection::Type>(
+ self.GetProperty(Dali::Actor::Property::LAYOUT_DIRECTION).Get<int>());
+ if(Dali::LayoutDirection::RIGHT_TO_LEFT == layoutDirection)
+ {
+ std::swap(padding.start, padding.end);
+ }
+
+ // remove padding from the size to know how much is left for the visual
+ Vector2 finalSize = size - Vector2(padding.start + padding.end, padding.top + padding.bottom);
+ Vector2 finalOffset = Vector2(padding.start, padding.top);
+
+ // Reset PIXEL_AREA after using OVER_FIT_KEEP_ASPECT_RATIO
+ if(visualImpl.IsPixelAreaSetForFittingMode())
+ {
+ visualImpl.SetPixelAreaForFittingMode(FULL_TEXTURE_RECT);
+ }
+
+ if((!zeroPadding) || // If padding is not zero
+ (fittingMode != Visual::FittingMode::FILL))
+ {
+ visualImpl.SetTransformMapUsageForFittingMode(true);
+
+ Vector2 naturalSize;
+ // NaturalSize will not be used for FILL fitting mode, which is default.
+ // Skip GetNaturalSize
+ if(fittingMode != Visual::FittingMode::FILL)
+ {
+ ((*iter)->visual).GetNaturalSize(naturalSize);
+ }
+
+ // If FittingMode use FIT_WIDTH or FIT_HEIGTH, it need to change proper fittingMode
+ if(fittingMode == Visual::FittingMode::FIT_WIDTH || fittingMode == Visual::FittingMode::FIT_HEIGHT)
+ {
+ const float widthRatio = !Dali::EqualsZero(naturalSize.width) ? (finalSize.width / naturalSize.width) : 0.0f;
+ const float heightRatio = !Dali::EqualsZero(naturalSize.height) ? (finalSize.height / naturalSize.height) : 0.0f;
+ if(widthRatio < heightRatio)
+ {
+ // Final size has taller form than natural size.
+ fittingMode = (fittingMode == Visual::FittingMode::FIT_WIDTH) ? Visual::FittingMode::FIT_KEEP_ASPECT_RATIO : Visual::FittingMode::OVER_FIT_KEEP_ASPECT_RATIO;
+ }
+ else
+ {
+ // Final size has wider form than natural size.
+ fittingMode = (fittingMode == Visual::FittingMode::FIT_WIDTH) ? Visual::FittingMode::OVER_FIT_KEEP_ASPECT_RATIO : Visual::FittingMode::FIT_KEEP_ASPECT_RATIO;
+ }
+ }
+
+ // Calculate size for fittingMode
+ switch(fittingMode)
+ {
+ case Visual::FittingMode::FIT_KEEP_ASPECT_RATIO:
+ {
+ auto availableVisualSize = finalSize;
+
+ // scale to fit the padded area
+ finalSize = naturalSize * std::min((!Dali::EqualsZero(naturalSize.width) ? (availableVisualSize.width / naturalSize.width) : 0),
+ (!Dali::EqualsZero(naturalSize.height) ? (availableVisualSize.height / naturalSize.height) : 0));
+
+ // calculate final offset within the padded area
+ finalOffset += (availableVisualSize - finalSize) * .5f;
+
+ // populate the transform map
+ transformMap.Add(Toolkit::Visual::Transform::Property::OFFSET, finalOffset)
+ .Add(Toolkit::Visual::Transform::Property::SIZE, finalSize);
+ break;
+ }
+ case Visual::FittingMode::OVER_FIT_KEEP_ASPECT_RATIO:
+ {
+ auto availableVisualSize = finalSize;
+ finalSize = naturalSize * std::max((!Dali::EqualsZero(naturalSize.width) ? (availableVisualSize.width / naturalSize.width) : 0.0f),
+ (!Dali::EqualsZero(naturalSize.height) ? (availableVisualSize.height / naturalSize.height) : 0.0f));
+
+ auto originalOffset = finalOffset;
+
+ if(!visualImpl.IsPixelAreaSetForFittingMode() && !Dali::EqualsZero(finalSize.width) && !Dali::EqualsZero(finalSize.height))
+ {
+ float x = abs((availableVisualSize.width - finalSize.width) / finalSize.width) * .5f;
+ float y = abs((availableVisualSize.height - finalSize.height) / finalSize.height) * .5f;
+ float widthRatio = 1.f - abs((availableVisualSize.width - finalSize.width) / finalSize.width);
+ float heightRatio = 1.f - abs((availableVisualSize.height - finalSize.height) / finalSize.height);
+ Vector4 pixelArea = Vector4(x, y, widthRatio, heightRatio);
+ visualImpl.SetPixelAreaForFittingMode(pixelArea);
+ }
+
+ // populate the transform map
+ transformMap.Add(Toolkit::Visual::Transform::Property::OFFSET, originalOffset)
+ .Add(Toolkit::Visual::Transform::Property::SIZE, availableVisualSize);
+ break;
+ }
+ case Visual::FittingMode::CENTER:
+ {
+ auto availableVisualSize = finalSize;
+ if(availableVisualSize.width > naturalSize.width && availableVisualSize.height > naturalSize.height)
+ {
+ finalSize = naturalSize;
+ }
+ else
+ {
+ finalSize = naturalSize * std::min((!Dali::EqualsZero(naturalSize.width) ? (availableVisualSize.width / naturalSize.width) : 0.0f),
+ (!Dali::EqualsZero(naturalSize.height) ? (availableVisualSize.height / naturalSize.height) : 0.0f));
+ }
+
+ finalOffset += (availableVisualSize - finalSize) * .5f;
+
+ // populate the transform map
+ transformMap.Add(Toolkit::Visual::Transform::Property::OFFSET, finalOffset)
+ .Add(Toolkit::Visual::Transform::Property::SIZE, finalSize);
+ break;
+ }
+ case Visual::FittingMode::FILL:
+ {
+ transformMap.Add(Toolkit::Visual::Transform::Property::OFFSET, finalOffset)
+ .Add(Toolkit::Visual::Transform::Property::SIZE, finalSize);
+ break;
+ }
+ case Visual::FittingMode::FIT_WIDTH:
+ case Visual::FittingMode::FIT_HEIGHT:
+ case Visual::FittingMode::DONT_CARE:
+ {
+ // This FittingMode already converted
+ break;
+ }
+ }
+
+ // Set extra value for applying transformMap
+ transformMap.Add(Toolkit::Visual::Transform::Property::OFFSET_POLICY,
+ Vector2(Toolkit::Visual::Transform::Policy::ABSOLUTE, Toolkit::Visual::Transform::Policy::ABSOLUTE))
+ .Add(Toolkit::Visual::Transform::Property::ORIGIN, Toolkit::Align::TOP_BEGIN)
+ .Add(Toolkit::Visual::Transform::Property::ANCHOR_POINT, Toolkit::Align::TOP_BEGIN)
+ .Add(Toolkit::Visual::Transform::Property::SIZE_POLICY,
+ Vector2(Toolkit::Visual::Transform::Policy::ABSOLUTE, Toolkit::Visual::Transform::Policy::ABSOLUTE));
+ }
+ else if(visualImpl.IsTransformMapSetForFittingMode() && zeroPadding) // Reset offset to zero only if padding applied previously
+ {
+ visualImpl.SetTransformMapUsageForFittingMode(false);
+
+ // Reset the transform map
+ transformMap.Add(Toolkit::Visual::Transform::Property::OFFSET, Vector2::ZERO)
+ .Add(Toolkit::Visual::Transform::Property::OFFSET_POLICY,
+ Vector2(Toolkit::Visual::Transform::Policy::RELATIVE, Toolkit::Visual::Transform::Policy::RELATIVE))
+ .Add(Toolkit::Visual::Transform::Property::SIZE, Vector2::ONE)
+ .Add(Toolkit::Visual::Transform::Property::SIZE_POLICY,
+ Vector2(Toolkit::Visual::Transform::Policy::RELATIVE, Toolkit::Visual::Transform::Policy::RELATIVE));
+ }
+
+ ((*iter)->visual).SetTransformAndSize(transformMap, size);
+ }
+ }
+}
+
+} // namespace Internal
+} // namespace Toolkit
+} // namespace Dali
--- /dev/null
+#ifndef DALI_TOOLKIT_CONTROL_DATA_VISUAL_DATA_H
+#define DALI_TOOLKIT_CONTROL_DATA_VISUAL_DATA_H
+
+/*
+ * Copyright (c) 2024 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.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+// INTERNAL INCLUDES
+#include <dali-toolkit/devel-api/controls/control-depth-index-ranges.h>
+#include <dali-toolkit/devel-api/controls/control-devel.h>
+#include <dali-toolkit/devel-api/visual-factory/visual-base.h>
+#include <dali-toolkit/internal/builder/dictionary.h>
+#include <dali-toolkit/internal/builder/style.h>
+#include <dali-toolkit/internal/visuals/visual-event-observer.h>
+#include <dali-toolkit/public-api/visuals/visual-properties.h>
+#include <dali/devel-api/common/owner-container.h>
+
+#include <dali-toolkit/internal/controls/control/control-data-impl.h>
+
+namespace Dali
+{
+namespace Toolkit
+{
+namespace Internal
+{
+/**
+ * @brief Struct used to store Visual within the control, index is a unique key for each visual.
+ */
+struct RegisteredVisual
+{
+ Property::Index index;
+ Toolkit::Visual::Base visual;
+ bool enabled : 1;
+ bool pending : 1;
+ bool overideReadyTransition : 1;
+
+ RegisteredVisual(Property::Index aIndex, Toolkit::Visual::Base& aVisual, bool aEnabled, bool aPendingReplacement)
+ : index(aIndex),
+ visual(aVisual),
+ enabled(aEnabled),
+ pending(aPendingReplacement),
+ overideReadyTransition(false)
+ {
+ }
+};
+
+typedef Dali::OwnerContainer<RegisteredVisual*> RegisteredVisualContainer;
+
+// private inner class
+class Control::Impl::VisualData : public Visual::EventObserver
+{
+public:
+ // Constructor
+ VisualData(Control::Impl& outer);
+
+ // Destructor
+ ~VisualData();
+
+ /**
+ * @brief Called when a resource is ready.
+ * @param[in] object The visual whose resources are ready
+ * @note Overriding method in Visual::EventObserver.
+ */
+ void ResourceReady(Visual::Base& object) override;
+
+ /**
+ * @brief Called when an event occurs.
+ * @param[in] object The visual whose events occur
+ * @param[in] signalId The signal to emit. See Visual to find supported signals
+ * @note Overriding method in Visual::EventObserver.
+ */
+ void NotifyVisualEvent(Visual::Base& object, Property::Index signalId) override;
+
+ /**
+ * @brief Called when the visual needs relayout request.
+ * @param[in] object The visual who requests relayout
+ */
+ void RelayoutRequest(Visual::Base& object) override;
+
+ /**
+ * @copydoc Dali::Toolkit::Internal::Control::Impl::IsResourceReady()
+ */
+ bool IsResourceReady() const;
+
+ /**
+ * @copydoc Dali::Toolkit::Internal::Control::Impl::EnableReadyTransitionOverriden()
+ */
+ void EnableReadyTransitionOverriden(Toolkit::Visual::Base& visual, bool enable);
+
+ /**
+ * @copydoc Dali::Toolkit::Internal::Control::Impl::GetVisualResourceStatus()
+ */
+ Toolkit::Visual::ResourceStatus GetVisualResourceStatus(Property::Index index) const;
+
+ /**
+ * @brief Copies the visual properties that are specific to the control instance into the instancedProperties container.
+ * @param[in] visuals The control's visual container
+ * @param[out] instancedProperties The instanced properties are added to this container
+ */
+ void CopyInstancedProperties(RegisteredVisualContainer& visuals, Dictionary<Property::Map>& instancedProperties);
+
+ /**
+ * @copydoc Dali::Toolkit::Internal::Control::Impl::RegisterVisual()
+ */
+ void RegisterVisual(Property::Index index, Toolkit::Visual::Base& visual);
+
+ /**
+ * @copydoc Dali::Toolkit::Internal::Control::Impl::RegisterVisual()
+ */
+ void RegisterVisual(Property::Index index, Toolkit::Visual::Base& visual, int depthIndex);
+
+ /**
+ * @copydoc Dali::Toolkit::Internal::Control::Impl::RegisterVisual()
+ */
+ void RegisterVisual(Property::Index index, Toolkit::Visual::Base& visual, bool enabled);
+
+ /**
+ * @copydoc Dali::Toolkit::Internal::Control::Impl::RegisterVisual()
+ */
+ void RegisterVisual(Property::Index index, Toolkit::Visual::Base& visual, bool enabled, int depthIndex);
+
+ /**
+ * @copydoc Dali::Toolkit::Internal::Control::Impl::UnregisterVisual()
+ */
+ void UnregisterVisual(Property::Index index);
+
+ /**
+ * @copydoc Dali::Toolkit::Internal::Control::Impl::GetVisual()
+ */
+ Toolkit::Visual::Base GetVisual(Property::Index index) const;
+
+ /**
+ * @brief Get visual by its name
+ * @param[in] name Name of visual
+ */
+ Toolkit::Visual::Base GetVisual(const std::string& name) const;
+
+ /**
+ * @copydoc Dali::Toolkit::Internal::Control::Impl::GetVisualProperty()
+ */
+ Dali::Property GetVisualProperty(Dali::Property::Index index, Dali::Property::Key visualPropertyKey);
+
+ /**
+ * @copydoc Dali::Toolkit::Internal::Control::Impl::EnableVisual()
+ */
+ void EnableVisual(Property::Index index, bool enable);
+
+ /**
+ * @copydoc Dali::Toolkit::Internal::Control::Impl::IsVisualEnabled()
+ */
+ bool IsVisualEnabled(Property::Index index) const;
+
+ /**
+ * @brief Removes a visual from the control's container.
+ * @param[in] visuals The container of visuals
+ * @param[in] visualName The name of the visual to remove
+ */
+ void RemoveVisual(RegisteredVisualContainer& visuals, const std::string& visualName);
+
+ /**
+ * @brief Removes several visuals from the control's container.
+ * @param[in] visuals The container of visuals
+ * @param[in] removeVisuals The visuals to remove
+ */
+ void RemoveVisuals(RegisteredVisualContainer& visuals, DictionaryKeys& removeVisuals);
+
+ /**
+ * @brief On state change, ensures visuals are moved or created appropriately.
+ *
+ * Go through the list of visuals that are common to both states.
+ * If they are different types, or are both image types with different
+ * URLs, then the existing visual needs moving and the new visual needs creating
+ *
+ * @param[in] stateVisualsToChange The visuals to change
+ * @param[in] instancedProperties The instanced properties @see CopyInstancedProperties
+ */
+ void RecreateChangedVisuals(Dictionary<Property::Map>& stateVisualsToChange, Dictionary<Property::Map>& instancedProperties);
+
+ /**
+ * @brief Replaces visuals and properties from the old state to the new state.
+ * @param[in] oldState The old state
+ * @param[in] newState The new state
+ * @param[in] subState The current sub state
+ */
+ void ReplaceStateVisualsAndProperties(const StylePtr oldState, const StylePtr newState, const std::string& subState);
+
+ /**
+ * @copydoc Dali::Toolkit::Internal::Control::Impl::DoAction()
+ */
+ void DoAction(Dali::Property::Index visualIndex, Dali::Property::Index actionId, const Dali::Property::Value attributes);
+
+ /**
+ * @copydoc Dali::Toolkit::Internal::Control::Impl::DoActionExtension()
+ */
+ void DoActionExtension(Dali::Property::Index visualIndex, Dali::Property::Index actionId, Dali::Any attributes);
+
+ /**
+ * @copydoc Dali::Toolkit::Internal::Control::Impl::VisualEventSignal()
+ */
+ DevelControl::VisualEventSignalType& VisualEventSignal();
+
+ /**
+ * @brief Any visuals set for replacement but not yet ready should still be registered.
+ * Reason: If a request was made to register a new visual but the control removed from scene before visual was ready
+ * then when this control appears back on stage it should use that new visual.
+ *
+ * After all registered visuals are set off scene,
+ * visuals pending replacement can 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.
+ *
+ * @param[in] parent Parent actor to remove visuals from
+ */
+ void ClearScene(Actor parent);
+
+ /**
+ * @brief Clear visuals.
+ */
+ void ClearVisuals();
+
+ /**
+ * @copydoc Dali::Toolkit::Internal::Control::Impl::ApplyFittingMode()
+ */
+ void ApplyFittingMode(const Vector2& size);
+
+ /**
+ * @brief Stops observing the given visual.
+ * @param[in] visual The visual to stop observing
+ */
+ void StopObservingVisual(Toolkit::Visual::Base& visual);
+
+ /**
+ * @brief Starts observing the given visual.
+ * @param[in] visual The visual to start observing
+ */
+ void StartObservingVisual(Toolkit::Visual::Base& visual);
+
+ /**
+ * @copydoc Dali::Toolkit::Internal::Control::Impl::UpdateVisualProperties()
+ */
+ void UpdateVisualProperties(const std::vector<std::pair<Dali::Property::Index, Dali::Property::Map>>& properties);
+
+private:
+ /**
+ * Used as an alternative to boolean so that it is obvious whether a visual is enabled/disabled.
+ */
+ struct VisualState
+ {
+ enum Type
+ {
+ DISABLED = 0, ///< Visual disabled.
+ ENABLED = 1 ///< Visual enabled.
+ };
+ };
+
+ /**
+ * Used as an alternative to boolean so that it is obvious whether a visual's depth value has been set or not by the caller.
+ */
+ struct DepthIndexValue
+ {
+ enum Type
+ {
+ NOT_SET = 0, ///< Visual depth value not set by caller.
+ SET = 1 ///< Visual depth value set by caller.
+ };
+ };
+
+ /**
+ * @brief Adds the visual to the list of registered visuals.
+ * @param[in] index The Property index of the visual, used to reference visual
+ * @param[in,out] visual The visual to register, which can be altered in this function
+ * @param[in] enabled false if derived class wants to control when visual is set on stage
+ * @param[in] depthIndexValueSet Set to true if the depthIndex has actually been set manually
+ * @param[in] depthIndex The visual's depth-index is set to this. If the depth-index is set to DepthIndex::Ranges::AUTO_INDEX,
+ * the actual depth-index of visual will be determind automatically (Use previous visuals depth-index, or placed on top of all other visuals.)
+ * Otherwise, the visual's depth-index is set to clamped value, between DepthIndex::Ranges::MINIMUM_DEPTH_INDEX and DepthIndex::Ranges::MAXIMUM_DEPTH_INDEX.
+ *
+ * @note Registering a visual with an index that already has a registered visual will replace it. The replacement will
+ * occur once the replacement visual is ready (loaded).
+ */
+ void RegisterVisual(Property::Index index, Toolkit::Visual::Base& visual, VisualState::Type enabled, DepthIndexValue::Type depthIndexValueSet, int depthIndex = static_cast<int>(Toolkit::DepthIndex::AUTO_INDEX));
+
+public:
+ RegisteredVisualContainer mVisuals; ///< Stores visuals needed by the control, non trivial type so std::vector used.
+ DevelControl::VisualEventSignalType mVisualEventSignal;
+ RegisteredVisualContainer mRemoveVisuals; ///< List of visuals that are being replaced by another visual once ready
+private:
+ Control::Impl& mOuter;
+};
+} // namespace Internal
+} // namespace Toolkit
+} // namespace Dali
+#endif // DALI_TOOLKIT_CONTROL_DATA_VISUAL_DATA_H
${toolkit_src_dir}/controls/canvas-view/canvas-view-impl.cpp
${toolkit_src_dir}/controls/canvas-view/canvas-view-rasterize-task.cpp
${toolkit_src_dir}/controls/control/control-data-impl.cpp
+ ${toolkit_src_dir}/controls/control/control-accessibility-data.cpp
+ ${toolkit_src_dir}/controls/control/control-visual-data.cpp
${toolkit_src_dir}/controls/control/control-debug.cpp
${toolkit_src_dir}/controls/control/control-renderers.cpp
${toolkit_src_dir}/controls/effects-view/effects-view-impl.cpp
#include <dali-toolkit/devel-api/visuals/color-visual-properties-devel.h>
#include <dali-toolkit/devel-api/visuals/visual-actions-devel.h>
#include <dali-toolkit/internal/controls/control/control-data-impl.h>
+#include <dali-toolkit/internal/controls/control/control-visual-data.h>
#include <dali-toolkit/internal/controls/render-effects/render-effect-impl.h>
#include <dali-toolkit/internal/styling/style-manager-impl.h>
#include <dali-toolkit/internal/visuals/color/color-visual.h>
{
Internal::Control::Impl& controlDataImpl = Internal::Control::Impl::Get(controlImpl);
- if(clippingMode == ClippingMode::CLIP_CHILDREN && controlDataImpl.mVisuals.Empty() && self.GetRendererCount() == 0u)
+ if(clippingMode == ClippingMode::CLIP_CHILDREN && controlDataImpl.mVisualData->mVisuals.Empty() && self.GetRendererCount() == 0u)
{
controlImpl.SetBackgroundColor(Color::TRANSPARENT);
}
void Control::OnSceneConnection(int depth)
{
- DALI_LOG_INFO(gLogFilter, Debug::Verbose, "Control::OnSceneConnection number of registered visuals(%d)\n", mImpl->mVisuals.Size());
+ DALI_LOG_INFO(gLogFilter, Debug::Verbose, "Control::OnSceneConnection number of registered visuals(%d)\n", mImpl->mVisualData->mVisuals.Size());
Actor self(Self());
- for(RegisteredVisualContainer::Iterator iter = mImpl->mVisuals.Begin(); iter != mImpl->mVisuals.End(); iter++)
+ for(RegisteredVisualContainer::Iterator iter = mImpl->mVisualData->mVisuals.Begin(); iter != mImpl->mVisualData->mVisuals.End(); iter++)
{
// Check whether the visual is empty and enabled
if((*iter)->visual && (*iter)->enabled)