Implement Visual control logic for NUI 54/309754/25
authorEunki, Hong <eunkiki.hong@samsung.com>
Tue, 16 Apr 2024 07:41:58 +0000 (16:41 +0900)
committerEunki, Hong <eunkiki.hong@samsung.com>
Mon, 3 Jun 2024 08:33:31 +0000 (17:33 +0900)
Let we implement NUI specific Visual policy.

1. Let we allow to set visual as BaseHandle class.
2. Allow to change the property of visual
 - Previous implements only able to change the PropertyMap.
   This concept is not matched with C# standard coding rule.
   Thus, we need to make a class, that keep whole properties at C# side.
3. Allow to change the order of rendering order.
 - For limitation ; We allow this visual only used between Background and Contents.
4. Do not allow to make AnimatedImageVisual if we don't use Animated flags

Change-Id: I47940c91ed853b83235119e16221aea1b27087c5
Signed-off-by: Eunki, Hong <eunkiki.hong@samsung.com>
dali-csharp-binder/common/visual-objects/visual-object-impl.cpp [new file with mode: 0644]
dali-csharp-binder/common/visual-objects/visual-object-impl.h [new file with mode: 0644]
dali-csharp-binder/common/visual-objects/visual-object.cpp [new file with mode: 0644]
dali-csharp-binder/common/visual-objects/visual-object.h [new file with mode: 0644]
dali-csharp-binder/common/visual-objects/visual-objects-container-impl.cpp [new file with mode: 0644]
dali-csharp-binder/common/visual-objects/visual-objects-container-impl.h [new file with mode: 0644]
dali-csharp-binder/common/visual-objects/visual-objects-container.cpp [new file with mode: 0644]
dali-csharp-binder/common/visual-objects/visual-objects-container.h [new file with mode: 0644]
dali-csharp-binder/file.list

diff --git a/dali-csharp-binder/common/visual-objects/visual-object-impl.cpp b/dali-csharp-binder/common/visual-objects/visual-object-impl.cpp
new file mode 100644 (file)
index 0000000..8f54d61
--- /dev/null
@@ -0,0 +1,280 @@
+/*
+ * 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 <dali-csharp-binder/common/visual-objects/visual-object-impl.h>
+
+// EXTERNAL INCLUDES
+#include <dali-toolkit/devel-api/controls/control-depth-index-ranges.h>
+#include <dali-toolkit/devel-api/visual-factory/visual-factory.h>
+#include <dali/integration-api/adaptor-framework/adaptor.h>
+#include <dali/integration-api/debug.h>
+
+// INTERNAL
+#include <dali-csharp-binder/common/visual-objects/visual-object.h>
+#include <dali-csharp-binder/common/visual-objects/visual-objects-container-impl.h>
+#include <dali-csharp-binder/common/visual-objects/visual-objects-container.h>
+
+namespace Dali::Internal
+{
+VisualObjectPtr VisualObject::New()
+{
+  VisualObjectPtr visualObject(new VisualObject());
+  return visualObject;
+}
+
+///< Public API
+
+void VisualObject::DetachFromContainer()
+{
+  if(auto container = mContainer.GetHandle())
+  {
+    container.RemoveVisualObject(Dali::VisualObject(this));
+  }
+  DetachFromContainerInternal();
+}
+
+Dali::VisualObjectsContainer VisualObject::GetContainer()
+{
+  return mContainer.GetHandle();
+}
+
+void VisualObject::CreateVisual(const Dali::Property::Map& map)
+{
+  if(Dali::Adaptor::IsAvailable())
+  {
+    auto visualFactory = Dali::Toolkit::VisualFactory::Get();
+    if(visualFactory)
+    {
+      if(!map.Empty())
+      {
+        mVisual = visualFactory.CreateVisual(map, Dali::Toolkit::VisualFactory::CreationOptions::IMAGE_VISUAL_LOAD_STATIC_IMAGES_ONLY);
+      }
+      else
+      {
+        // Special behavior, if map is empty, unregister the visual.
+        mVisual.Reset();
+      }
+    }
+
+    // Replace as newly created visual now.
+    if(auto container = mContainer.GetHandle())
+    {
+      GetImplementation(container).ReplaceVisualObject(*this);
+    }
+  }
+}
+
+void VisualObject::RetrieveVisualPropertyMap(Dali::Property::Map& map) const
+{
+  if(mVisual)
+  {
+    mVisual.CreatePropertyMap(map);
+  }
+}
+
+void VisualObject::DoAction(Dali::Property::Index actionId, const Dali::Property::Value& attributes)
+{
+  if(mVisual)
+  {
+    mVisual.DoAction(actionId, attributes);
+  }
+}
+
+/// Sibling Order Change API
+
+void VisualObject::SetSiblingOrder(uint32_t siblingOrder)
+{
+  auto container = mContainer.GetHandle();
+  if(container && mSiblingOrder != siblingOrder)
+  {
+    GetImplementation(container).ChangeSiblingOrder(mSiblingOrder, siblingOrder);
+  }
+}
+
+uint32_t VisualObject::GetSiblingOrder() const
+{
+  // If we are not in container, return 0.
+  if(!mContainer.GetHandle())
+  {
+    return 0u;
+  }
+  return mSiblingOrder;
+}
+
+void VisualObject::Raise()
+{
+  auto container = mContainer.GetHandle();
+  if(container)
+  {
+    if(mSiblingOrder + 1u < container.GetVisualObjectsCount())
+    {
+      SetSiblingOrder(mSiblingOrder + 1u);
+    }
+  }
+}
+
+void VisualObject::Lower()
+{
+  auto container = mContainer.GetHandle();
+  if(container)
+  {
+    if(mSiblingOrder > 0u)
+    {
+      SetSiblingOrder(mSiblingOrder - 1u);
+    }
+  }
+}
+
+void VisualObject::RaiseToTop()
+{
+  auto container = mContainer.GetHandle();
+  if(container && container.GetVisualObjectsCount() > 0u)
+  {
+    SetSiblingOrder(container.GetVisualObjectsCount() - 1u);
+  }
+}
+
+void VisualObject::LowerToBottom()
+{
+  auto container = mContainer.GetHandle();
+  if(container)
+  {
+    SetSiblingOrder(0u);
+  }
+}
+
+void VisualObject::RaiseAbove(Dali::Internal::VisualObject& target)
+{
+  auto container = mContainer.GetHandle();
+  // Check whether target and this is in the same container.
+  if(container && container == target.GetContainer())
+  {
+    uint32_t fromIndex = mSiblingOrder;
+    uint32_t toIndex   = target.GetSiblingOrder();
+
+    // Change sibling order only if fromIndex is less than toIndex.
+    // Note : target's sibling order will be updated automatically.
+    if(fromIndex < toIndex)
+    {
+      SetSiblingOrder(toIndex);
+    }
+  }
+}
+
+void VisualObject::LowerBelow(Dali::Internal::VisualObject& target)
+{
+  auto container = mContainer.GetHandle();
+  // Check whether target and this is in the same container.
+  if(container && container == target.GetContainer())
+  {
+    uint32_t fromIndex = mSiblingOrder;
+    uint32_t toIndex   = target.GetSiblingOrder();
+
+    // Change sibling order only if fromIndex is greater than toIndex.
+    // Note : target's sibling order will be updated automatically.
+    if(fromIndex > toIndex)
+    {
+      SetSiblingOrder(toIndex);
+    }
+  }
+}
+
+// Private and internal
+
+void VisualObject::AttachToContainerInternal(Dali::VisualObjectsContainer container)
+{
+  mContainer = WeakHandle(container);
+  mRangeType = container.GetContainerRangeType();
+}
+
+void VisualObject::DetachFromContainerInternal()
+{
+  mContainer.Reset();
+  mSiblingOrder     = 0u;
+  mVisualPropertyId = INVALID_VISUAL_PROPERTY_ID;
+}
+
+void VisualObject::SetSiblingOrderInternal(uint32_t siblingOrder)
+{
+  mSiblingOrder = siblingOrder;
+  if(mVisual)
+  {
+    mVisual.SetDepthIndex(GetDepthIndex());
+  }
+}
+
+int32_t VisualObject::GetDepthIndex() const
+{
+  int32_t baseDepthIndex = 0;
+  switch(mRangeType)
+  {
+    case Dali::VisualObjectsContainer::ContainerRangeType::BACKGROUND_EFFECT:
+    {
+      baseDepthIndex = Dali::Toolkit::DepthIndex::Ranges::MINIMUM_DEPTH_INDEX + 1;
+      break;
+    }
+    case Dali::VisualObjectsContainer::ContainerRangeType::BACKGROUND:
+    {
+      baseDepthIndex = Dali::Toolkit::DepthIndex::Ranges::BACKGROUND_EFFECT + 1;
+      break;
+    }
+    case Dali::VisualObjectsContainer::ContainerRangeType::CONTENT:
+    {
+      baseDepthIndex = Dali::Toolkit::DepthIndex::Ranges::BACKGROUND + 1;
+      break;
+    }
+    case Dali::VisualObjectsContainer::ContainerRangeType::DECORATION:
+    {
+      baseDepthIndex = Dali::Toolkit::DepthIndex::Ranges::CONTENT + 4; /* Give some gap from CONTENT. */
+      break;
+    }
+    case Dali::VisualObjectsContainer::ContainerRangeType::FOREGROUND_EFFECT:
+    {
+      baseDepthIndex = Dali::Toolkit::DepthIndex::Ranges::DECORATION + 1;
+      break;
+    }
+  }
+  return baseDepthIndex + static_cast<int32_t>(mSiblingOrder);
+}
+
+VisualObject::VisualObject()
+: mContainer(),
+  mVisual(),
+  mSiblingOrder(0u),
+  mVisualPropertyId(VisualObject::INVALID_VISUAL_PROPERTY_ID)
+{
+}
+
+VisualObject::~VisualObject()
+{
+  if(DALI_LIKELY(Dali::Adaptor::IsAvailable()))
+  {
+    DetachFromContainerInternal();
+
+    if(mVisual)
+    {
+      auto visualFactory = Dali::Toolkit::VisualFactory::Get();
+      if(visualFactory)
+      {
+        visualFactory.DiscardVisual(std::move(mVisual));
+      }
+    }
+  }
+}
+
+} // namespace Dali::Internal
\ No newline at end of file
diff --git a/dali-csharp-binder/common/visual-objects/visual-object-impl.h b/dali-csharp-binder/common/visual-objects/visual-object-impl.h
new file mode 100644 (file)
index 0000000..954cdb1
--- /dev/null
@@ -0,0 +1,230 @@
+#ifndef CSHARP_VISUAL_OBJECT_IMPL_H
+#define CSHARP_VISUAL_OBJECT_IMPL_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.
+ *
+ */
+
+// EXTERNAL INCLUDES
+#include <dali-toolkit/devel-api/visual-factory/visual-base.h>
+#include <dali/public-api/common/dali-common.h>
+#include <dali/public-api/common/intrusive-ptr.h>
+#include <dali/public-api/object/base-object.h>
+#include <dali/public-api/object/property-map.h>
+#include <dali/public-api/object/weak-handle.h>
+#include <limits>
+
+// INTERNAL INCLUDES
+#include <dali-csharp-binder/common/visual-objects/visual-object.h>
+#include <dali-csharp-binder/common/visual-objects/visual-objects-container.h>
+
+namespace Dali
+{
+namespace Internal
+{
+class VisualObject;
+using VisualObjectPtr = Dali::IntrusivePtr<VisualObject>;
+
+class VisualObject : public Dali::BaseObject
+{
+public:
+  using VisualPropertyId                                       = uint32_t;
+  static constexpr VisualPropertyId INVALID_VISUAL_PROPERTY_ID = std::numeric_limits<VisualPropertyId>::max();
+
+  /**
+   * @brief Creates a VisualObject object.
+   *
+   * @SINCE_2_3.27
+   * @return The newly created visual object.
+   */
+  static VisualObjectPtr New();
+
+public: ///< Public API
+  /**
+   * @copydoc Dali::VisualObject::DetachFromContainer()
+   */
+  void DetachFromContainer();
+
+  /**
+   * @copydoc Dali::VisualObject::GetContainer()
+   */
+  Dali::VisualObjectsContainer GetContainer();
+
+  /**
+   * @copydoc Dali::VisualObject::CreateVisual()
+   */
+  void CreateVisual(const Dali::Property::Map& map);
+
+  /**
+   * @copydoc Dali::VisualObject::RetrieveVisualProperty()
+   */
+  void RetrieveVisualPropertyMap(Dali::Property::Map& map) const;
+
+  /**
+   * @copydoc Dali::VisualObject::DoAction()
+   */
+  void DoAction(Dali::Property::Index actionId, const Dali::Property::Value& attributes);
+
+  /// Sibling Order Change API
+
+  /**
+   * @copydoc Dali::VisualObject::SetSiblingOrder()
+   */
+  void SetSiblingOrder(uint32_t siblingOrder);
+
+  /**
+   * @copydoc Dali::VisualObject::GetSiblingOrder()
+   */
+  uint32_t GetSiblingOrder() const;
+
+  /**
+   * @copydoc Dali::VisualObject::Raise()
+   */
+  void Raise();
+
+  /**
+   * @copydoc Dali::VisualObject::Lower()
+   */
+  void Lower();
+
+  /**
+   * @copydoc Dali::VisualObject::RaiseToTop()
+   */
+  void RaiseToTop();
+
+  /**
+   * @copydoc Dali::VisualObject::LowerToBottom()
+   */
+  void LowerToBottom();
+
+  /**
+   * @copydoc Dali::VisualObject::RaiseAbove()
+   */
+  void RaiseAbove(Dali::Internal::VisualObject& target);
+
+  /**
+   * @copydoc Dali::VisualObject::LowerBelow()
+   */
+  void LowerBelow(Dali::Internal::VisualObject& target);
+
+public: ///< Called from Internal::VisualObjectsContainer
+  /**
+   * @brief Set the container who contain this visual object.
+   * @note It should be called only from Internal::VisualObject or Internal::VisualObjectsContainer.
+   *
+   * @param[in] container VisualObjectsContainer who contain this visual object. Or empty container if visual object is not in container.
+   */
+  void AttachToContainerInternal(Dali::VisualObjectsContainer container);
+
+  /**
+   * @brief Detach from container without change the container.
+   * @note It should be called only from Internal::VisualObject or Internal::VisualObjectsContainer.
+   */
+  void DetachFromContainerInternal();
+
+  /**
+   * @brief Set the sibling order without change the container.
+   * @note It should be called only from Internal::VisualObject or Internal::VisualObjectsContainer.
+   *
+   * @param[in] siblingOrder The sibling order inside of the container.
+   */
+  void SetSiblingOrderInternal(uint32_t siblingOrder);
+
+  /**
+   * @brief Get the depth index of visual, depend by sibling order.
+   * @note It should be called only from Internal::VisualObject or Internal::VisualObjectsContainer.
+   *
+   * @return The depth index of visual.
+   */
+  int32_t GetDepthIndex() const;
+
+  /**
+   * @brief Get the Visual::Base object what this object hold.
+   * @note It should be called only from Internal::VisualObject or Internal::VisualObjectsContainer.
+   *
+   * @return Latest created Visual::Base object created by VisualObject::CreateVisual();
+   */
+  Dali::Toolkit::Visual::Base GetVisual()
+  {
+    return mVisual;
+  }
+
+  /**
+   * @brief Set the unique id of visual what it registered into control.
+   *
+   * @param[in] visualPropertyId The id of visual property registered.
+   */
+  void SetVisualPropertyId(VisualPropertyId visualPropertyId)
+  {
+    mVisualPropertyId = visualPropertyId;
+  }
+
+  /**
+   * @brief Get the unique id of visual what it registered into control.
+   *
+   * @return The id of visual property registered
+   */
+  VisualPropertyId GetVisualPropertyId() const
+  {
+    return mVisualPropertyId;
+  }
+
+public:
+  /**
+   * @brief Constructor - creates a VisualObject.
+   */
+  VisualObject();
+
+  /**
+   * @brief Destructor.
+   */
+  ~VisualObject() override;
+
+private:
+  Dali::WeakHandle<Dali::VisualObjectsContainer> mContainer;
+
+  Dali::Toolkit::Visual::Base mVisual;
+
+  Dali::VisualObjectsContainer::ContainerRangeType mRangeType{Dali::VisualObjectsContainer::ContainerRangeType::CONTENT};
+
+  uint32_t mSiblingOrder{0u};
+  uint32_t mVisualPropertyId{INVALID_VISUAL_PROPERTY_ID};
+};
+} // namespace Internal
+
+// Helpers for api forwarding methods
+
+inline static Internal::VisualObject& GetImplementation(Dali::VisualObject& handle)
+{
+  DALI_ASSERT_ALWAYS(handle && "VisualObject handle is empty.");
+
+  Dali::BaseObject& object = handle.GetBaseObject();
+
+  return static_cast<Internal::VisualObject&>(object);
+}
+
+inline static const Internal::VisualObject& GetImplementation(const Dali::VisualObject& handle)
+{
+  DALI_ASSERT_ALWAYS(handle && "VisualObject handle is empty.");
+
+  const Dali::BaseObject& object = handle.GetBaseObject();
+
+  return static_cast<const Internal::VisualObject&>(object);
+}
+
+} // namespace Dali
+
+#endif // CSHARP_VISUAL_OBJECT_IMPL_H
\ No newline at end of file
diff --git a/dali-csharp-binder/common/visual-objects/visual-object.cpp b/dali-csharp-binder/common/visual-objects/visual-object.cpp
new file mode 100644 (file)
index 0000000..60d3c9c
--- /dev/null
@@ -0,0 +1,357 @@
+/*
+ * 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 <dali-csharp-binder/common/visual-objects/visual-object.h>
+
+// EXTERNAL INCLUDES
+#include <dali-toolkit/devel-api/visuals/visual-actions-devel.h>
+#include <dali/integration-api/debug.h>
+
+// INTERNAL INCLUDES
+#include <dali-csharp-binder/common/common.h>
+#include <dali-csharp-binder/common/visual-objects/visual-object-impl.h>
+
+namespace Dali
+{
+VisualObject::VisualObject(Dali::Internal::VisualObject* object)
+: BaseHandle(object)
+{
+}
+
+VisualObject VisualObject::New()
+{
+  Internal::VisualObjectPtr internal = Internal::VisualObject::New();
+  return VisualObject(internal.Get());
+}
+
+///< Public API
+
+void VisualObject::DetachFromContainer()
+{
+  GetImplementation(*this).DetachFromContainer();
+}
+
+Dali::VisualObjectsContainer VisualObject::GetContainer()
+{
+  return GetImplementation(*this).GetContainer();
+}
+
+void VisualObject::CreateVisual(const Dali::Property::Map& map)
+{
+  GetImplementation(*this).CreateVisual(map);
+}
+
+void VisualObject::DoAction(Dali::Property::Index actionId, const Dali::Property::Value& attributes)
+{
+  GetImplementation(*this).DoAction(actionId, attributes);
+}
+
+void VisualObject::RetrieveVisualPropertyMap(Dali::Property::Map& map) const
+{
+  GetImplementation(*this).RetrieveVisualPropertyMap(map);
+}
+
+/// Sibling Order Change API
+
+void VisualObject::SetSiblingOrder(uint32_t siblingOrder)
+{
+  GetImplementation(*this).SetSiblingOrder(siblingOrder);
+}
+
+uint32_t VisualObject::GetSiblingOrder() const
+{
+  return GetImplementation(*this).GetSiblingOrder();
+}
+
+void VisualObject::Raise()
+{
+  GetImplementation(*this).Raise();
+}
+
+void VisualObject::Lower()
+{
+  GetImplementation(*this).Lower();
+}
+
+void VisualObject::RaiseToTop()
+{
+  GetImplementation(*this).RaiseToTop();
+}
+
+void VisualObject::LowerToBottom()
+{
+  GetImplementation(*this).LowerToBottom();
+}
+
+void VisualObject::RaiseAbove(Dali::VisualObject target)
+{
+  GetImplementation(*this).RaiseAbove(GetImplementation(target));
+}
+
+void VisualObject::LowerBelow(Dali::VisualObject target)
+{
+  GetImplementation(*this).LowerBelow(GetImplementation(target));
+}
+
+} // namespace Dali
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+SWIGEXPORT void* SWIGSTDCALL CSharp_Dali_new_VisualObject__SWIG_0()
+{
+  Dali::VisualObject* result = 0;
+
+  try_catch(([&]() {
+    result = (Dali::VisualObject*)new Dali::VisualObject();
+  }));
+
+  return (void*)result;
+}
+
+SWIGEXPORT void* SWIGSTDCALL CSharp_Dali_VisualObject_New()
+{
+  void*              jresult = 0;
+  Dali::VisualObject result;
+
+  try_catch(([&]() {
+    result = Dali::VisualObject::New();
+  }));
+
+  jresult = new Dali::VisualObject((const Dali::VisualObject&)result);
+  return jresult;
+}
+
+SWIGEXPORT void SWIGSTDCALL CSharp_Dali_delete_VisualObject(void* nuiVisualObject)
+{
+  Dali::VisualObject* visualObject = (Dali::VisualObject*)0;
+
+  visualObject = (Dali::VisualObject*)nuiVisualObject;
+  try_catch(([&]() {
+    delete visualObject;
+  }));
+}
+
+SWIGEXPORT void SWIGSTDCALL CSharp_Dali_VisualObject_DetachFromContainer(void* nuiVisualObject)
+{
+  Dali::VisualObject* visualObject = (Dali::VisualObject*)0;
+
+  GUARD_ON_NULL_RET(nuiVisualObject);
+
+  visualObject = (Dali::VisualObject*)nuiVisualObject;
+  try_catch(([&]() {
+    visualObject->DetachFromContainer();
+  }));
+}
+
+SWIGEXPORT void* SWIGSTDCALL CSharp_Dali_VisualObject_GetContainer(void* nuiVisualObject)
+{
+  void*                        jresult      = 0;
+  Dali::VisualObject*          visualObject = (Dali::VisualObject*)0;
+  Dali::VisualObjectsContainer result;
+
+  GUARD_ON_NULL_RET0(nuiVisualObject);
+
+  visualObject = (Dali::VisualObject*)nuiVisualObject;
+  try_catch(([&]() {
+    result = visualObject->GetContainer();
+  }));
+
+  jresult = new Dali::VisualObjectsContainer((const Dali::VisualObjectsContainer&)result);
+  return jresult;
+}
+
+SWIGEXPORT void SWIGSTDCALL CSharp_Dali_VisualObject_CreateVisual(void* nuiVisualObject, void* nuiPropertyMap)
+{
+  Dali::VisualObject* visualObject = (Dali::VisualObject*)0;
+  Dali::Property::Map propertyMap;
+
+  GUARD_ON_NULL_RET(nuiVisualObject);
+
+  // We allow to set null for nuiPropertyMap.
+
+  visualObject = (Dali::VisualObject*)nuiVisualObject;
+  propertyMap  = nuiPropertyMap ? *((const Dali::Property::Map*)nuiPropertyMap) : Dali::Property::Map();
+  try_catch(([&]() {
+    visualObject->CreateVisual(propertyMap);
+  }));
+}
+
+SWIGEXPORT void SWIGSTDCALL CSharp_Dali_VisualObject_RetrieveVisualPropertyMap(void* nuiVisualObject, void* nuiPropertyMap)
+{
+  const Dali::VisualObject* visualObject = (const Dali::VisualObject*)0;
+  Dali::Property::Map*      propertyMap  = (Dali::Property::Map*)0;
+
+  GUARD_ON_NULL_RET(nuiVisualObject);
+  GUARD_ON_NULL_RET(nuiPropertyMap);
+
+  visualObject = (const Dali::VisualObject*)nuiVisualObject;
+  propertyMap  = (Dali::Property::Map*)nuiPropertyMap;
+  try_catch(([&]() {
+    visualObject->RetrieveVisualPropertyMap(*propertyMap);
+  }));
+}
+
+SWIGEXPORT void SWIGSTDCALL CSharp_Dali_VisualObject_DoAction_UpdatePropertyMap(void* nuiVisualObject, void* nuiPropertyMap)
+{
+  Dali::VisualObject*  visualObject = (Dali::VisualObject*)0;
+  Dali::Property::Map* propertyMap  = (Dali::Property::Map*)0;
+
+  GUARD_ON_NULL_RET(nuiVisualObject);
+  GUARD_ON_NULL_RET(nuiPropertyMap);
+
+  visualObject = (Dali::VisualObject*)nuiVisualObject;
+  propertyMap  = (Dali::Property::Map*)nuiPropertyMap;
+  try_catch(([&]() {
+    visualObject->DoAction(Dali::Toolkit::DevelVisual::Action::UPDATE_PROPERTY, *propertyMap);
+  }));
+}
+
+SWIGEXPORT void SWIGSTDCALL CSharp_Dali_VisualObject_DoActionWithEmptyAttributes(void* nuiVisualObject, int actionId)
+{
+  Dali::VisualObject* visualObject = (Dali::VisualObject*)0;
+
+  GUARD_ON_NULL_RET(nuiVisualObject);
+
+  visualObject = (Dali::VisualObject*)nuiVisualObject;
+  try_catch(([&]() {
+    visualObject->DoAction(actionId, Dali::Property::Value());
+  }));
+}
+
+SWIGEXPORT void SWIGSTDCALL CSharp_Dali_VisualObject_DoActionWithSingleIntAttributes(void* nuiVisualObject, int actionId, int actionValue)
+{
+  Dali::VisualObject* visualObject = (Dali::VisualObject*)0;
+
+  GUARD_ON_NULL_RET(nuiVisualObject);
+
+  visualObject = (Dali::VisualObject*)nuiVisualObject;
+  try_catch(([&]() {
+    visualObject->DoAction(actionId, Dali::Property::Value(actionValue));
+  }));
+}
+
+SWIGEXPORT void SWIGSTDCALL CSharp_Dali_VisualObject_SetSiblingOrder(void* nuiVisualObject, uint32_t index)
+{
+  Dali::VisualObject* visualObject = (Dali::VisualObject*)0;
+
+  GUARD_ON_NULL_RET(nuiVisualObject);
+
+  visualObject = (Dali::VisualObject*)nuiVisualObject;
+  try_catch(([&]() {
+    visualObject->SetSiblingOrder(index);
+  }));
+}
+
+SWIGEXPORT uint32_t SWIGSTDCALL CSharp_Dali_VisualObject_GetSiblingOrder(void* nuiVisualObject)
+{
+  const Dali::VisualObject* visualObject = (const Dali::VisualObject*)0;
+  uint32_t                  result       = 0u;
+
+  GUARD_ON_NULL_RET0(nuiVisualObject);
+
+  visualObject = (const Dali::VisualObject*)nuiVisualObject;
+  try_catch(([&]() {
+    result = visualObject->GetSiblingOrder();
+  }));
+
+  return result;
+}
+
+SWIGEXPORT void SWIGSTDCALL CSharp_Dali_VisualObject_Raise(void* nuiVisualObject)
+{
+  Dali::VisualObject* visualObject = (Dali::VisualObject*)0;
+
+  GUARD_ON_NULL_RET(nuiVisualObject);
+
+  visualObject = (Dali::VisualObject*)nuiVisualObject;
+  try_catch(([&]() {
+    visualObject->Raise();
+  }));
+}
+
+SWIGEXPORT void SWIGSTDCALL CSharp_Dali_VisualObject_Lower(void* nuiVisualObject)
+{
+  Dali::VisualObject* visualObject = (Dali::VisualObject*)0;
+
+  GUARD_ON_NULL_RET(nuiVisualObject);
+
+  visualObject = (Dali::VisualObject*)nuiVisualObject;
+  try_catch(([&]() {
+    visualObject->Lower();
+  }));
+}
+
+SWIGEXPORT void SWIGSTDCALL CSharp_Dali_VisualObject_RaiseToTop(void* nuiVisualObject)
+{
+  Dali::VisualObject* visualObject = (Dali::VisualObject*)0;
+
+  GUARD_ON_NULL_RET(nuiVisualObject);
+
+  visualObject = (Dali::VisualObject*)nuiVisualObject;
+  try_catch(([&]() {
+    visualObject->RaiseToTop();
+  }));
+}
+
+SWIGEXPORT void SWIGSTDCALL CSharp_Dali_VisualObject_LowerToBottom(void* nuiVisualObject)
+{
+  Dali::VisualObject* visualObject = (Dali::VisualObject*)0;
+
+  GUARD_ON_NULL_RET(nuiVisualObject);
+
+  visualObject = (Dali::VisualObject*)nuiVisualObject;
+  try_catch(([&]() {
+    visualObject->LowerToBottom();
+  }));
+}
+
+SWIGEXPORT void SWIGSTDCALL CSharp_Dali_VisualObject_RaiseAbove(void* nuiVisualObject, void* nuiTargetVisualObject)
+{
+  Dali::VisualObject* visualObject       = (Dali::VisualObject*)0;
+  Dali::VisualObject* targetVisualObject = (Dali::VisualObject*)0;
+
+  GUARD_ON_NULL_RET(nuiVisualObject);
+  GUARD_ON_NULL_RET(nuiTargetVisualObject);
+
+  visualObject       = (Dali::VisualObject*)nuiVisualObject;
+  targetVisualObject = (Dali::VisualObject*)nuiTargetVisualObject;
+  try_catch(([&]() {
+    visualObject->RaiseAbove(*targetVisualObject);
+  }));
+}
+
+SWIGEXPORT void SWIGSTDCALL CSharp_Dali_VisualObject_LowerBelow(void* nuiVisualObject, void* nuiTargetVisualObject)
+{
+  Dali::VisualObject* visualObject       = (Dali::VisualObject*)0;
+  Dali::VisualObject* targetVisualObject = (Dali::VisualObject*)0;
+
+  GUARD_ON_NULL_RET(nuiVisualObject);
+  GUARD_ON_NULL_RET(nuiTargetVisualObject);
+
+  visualObject       = (Dali::VisualObject*)nuiVisualObject;
+  targetVisualObject = (Dali::VisualObject*)nuiTargetVisualObject;
+  try_catch(([&]() {
+    visualObject->LowerBelow(*targetVisualObject);
+  }));
+}
+
+#ifdef __cplusplus
+}
+#endif
\ No newline at end of file
diff --git a/dali-csharp-binder/common/visual-objects/visual-object.h b/dali-csharp-binder/common/visual-objects/visual-object.h
new file mode 100644 (file)
index 0000000..a06c98d
--- /dev/null
@@ -0,0 +1,228 @@
+#ifndef CSHARP_VISUAL_OBJECT_H
+#define CSHARP_VISUAL_OBJECT_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.
+ *
+ */
+
+// EXTERNAL INCLUDES
+#include <dali/public-api/object/base-handle.h>
+
+// INTERNAL INCLUDES
+#include <dali-csharp-binder/common/visual-objects/visual-objects-container.h>
+
+namespace Dali
+{
+namespace Internal
+{
+class VisualObject;
+}
+/**
+ * @brief VisualObject is a owner of Visual::Base.
+ * It will be used when we want to Attach / Detach from control,
+ * and change rendering order for C# specific policy.
+ *
+ * VisualObject could be added to only one VisualObjectsContainer.
+ * If user try to add VisualObject to another VisualObjectsContainer,
+ * it will be removed from previous container and added to new container.
+ *
+ * @code
+ *
+ * TextLabel textLabel = TextLabel::New("Hello World");
+ * textLabel.SetBackgroundColor(Color::RED);
+ *
+ * VisualObjectsContainer container = VisualObjectsContainer.New(textLabel);
+ *
+ * VisualObject visualObject1 = VisualObject.New();
+ * VisualObject visualObject2 = VisualObject.New();
+ * VisualObject visualObject3 = VisualObject.New();
+ * container.AddVisualObject(visualObject1);
+ * container.AddVisualObject(visualObject2);
+ * container.AddVisualObject(visualObject3);
+ *
+ * // Current textLabel will show RED background and text.
+ *
+ * visualObject1.CreateVisual(TRANSLUCENT_BLUE_COLOR_PROPERTY_MAP);
+ *
+ * // textLabel will show text, translucent blue, and red (top to bottom)
+ *
+ * visualObject3.CreateVisual(SOME_IMAGE_PROPERTY_MAP);
+ *
+ * // textLabel will show text, some image, translucent blue, and red (top to bottom)
+ *
+ * visualObject2.CreateVisual(GREEN_BORDER_PROPERTY_MAP);
+ *
+ * // textLabel will show text, some image, green border, translucent blue, and red (top to bottom)
+ *
+ * visualObject2.RaiseToTop();
+ *
+ * // textLabel will show text, green border, some image, translucent blue, and red (top to bottom)
+ *
+ * @endcode
+ *
+ * @SINCE_2_3.27
+ */
+class VisualObject : public Dali::BaseHandle
+{
+public:
+  /**
+   * @brief Creates a VisualObject object.
+   *
+   * @SINCE_2_3.27
+   * @return The newly created visual object.
+   */
+  static VisualObject New();
+
+public: ///< Public API
+  /**
+   * @brief Detach from the Container. Now container will be empty handle.
+   *
+   * @SINCE_2_3.27
+   */
+  void DetachFromContainer();
+
+  /**
+   * @brief Get the Container who contain this visual object.
+   *
+   * @SINCE_2_3.27
+   * @return VisualObjectsContainer who contain this visual object. Or empty container if visual object is not in container.
+   */
+  Dali::VisualObjectsContainer GetContainer();
+
+  /**
+   * @brief Create Visual with Property::Map.
+   * @note It will remove previous visual.
+   *
+   * @SINCE_2_3.27
+   * @param[in] map The Creation information of the visual.
+   */
+  void CreateVisual(const Dali::Property::Map& map);
+
+  /**
+   * @brief Get the visual property map.
+   *
+   * @SINCE_2_3.27
+   * @param[out] map The visual property map.
+   */
+  void RetrieveVisualPropertyMap(Dali::Property::Map& map) const;
+
+  /**
+   * @brief Perform an action on a visual registered to this control.
+   * Visuals will have actions, this API is used to perform one of these actions with the given attributes.
+   * @note If visual is not been registered to the control, action should be ignored.
+   *
+   * @SINCE_2_3.27
+   * @param[in] actionId The action to perform.  See Visual to find supported actions.
+   * @param[in] attributes Optional attributes for the action.
+   */
+  void DoAction(Dali::Property::Index actionId, const Dali::Property::Value& attributes);
+
+  /// Sibling Order Change API
+
+  /**
+   * @brief Set the sibling order of the visual object inside of the container.
+   * @note It will change other VisualObject's sibling order to keep the order.
+   *
+   * @SINCE_2_3.27
+   * @param[in] siblingOrder The sibling order inside of the container.
+   */
+  void SetSiblingOrder(uint32_t siblingOrder);
+
+  /**
+   * @brief Get the sibling order of the visual object inside of the container.
+   *
+   * @SINCE_2_3.27
+   * @return The sibling order inside of the container. Or 0 if visual object is not in container.
+   */
+  uint32_t GetSiblingOrder() const;
+
+  /**
+   * @brief Raise the visual object above the next sibling visual object.
+   *
+   * @SINCE_2_3.27
+   * @pre The VisualObject has been initialized.
+   * @pre The VisualObject has been parented.
+   */
+  void Raise();
+
+  /**
+   * @brief Lower the visual object below the previous sibling visual object.
+   *
+   * @SINCE_2_3.27
+   * @pre The VisualObject has been initialized.
+   * @pre The VisualObject has been parented.
+   */
+  void Lower();
+
+  /**
+   * @brief Raise visual object above all other sibling visual objects.
+   *
+   * @SINCE_2_3.27
+   * @pre The VisualObject has been initialized.
+   * @pre The VisualObject has been parented.
+   */
+  void RaiseToTop();
+
+  /**
+   * @brief Lower visual object to the bottom of all other sibling visual objects.
+   *
+   * @SINCE_2_3.27
+   * @pre The VisualObject has been initialized.
+   * @pre The VisualObject has been parented.
+   */
+  void LowerToBottom();
+
+  /**
+   * @brief Raises the visual object above the target visual object.
+   *
+   * @SINCE_2_3.27
+   * @param[in] target The target visual object
+   * @pre The VisualObject has been initialized.
+   * @pre The VisualObject has been parented.
+   * @pre The target visual object is a sibling.
+   */
+  void RaiseAbove(VisualObject target);
+
+  /**
+   * @brief Lower the visual object to below the target visual object.
+   *
+   * @SINCE_2_3.27
+   * @param[in] target The target visual object
+   * @pre The VisualObject has been initialized.
+   * @pre The VisualObject has been parented.
+   * @pre The target visual object is a sibling.
+   */
+  void LowerBelow(VisualObject target);
+
+public:
+  VisualObject()                           = default;
+  ~VisualObject()                          = default;
+  VisualObject(const VisualObject& handle) = default;
+  VisualObject& operator=(const VisualObject& rhs) = default;
+  VisualObject(VisualObject&& rhs) noexcept        = default;
+  VisualObject& operator=(VisualObject&& rhs) noexcept = default;
+
+public:
+  /**
+   * @brief This constructor is used by Dali New() methods.
+   *
+   * @param[in] object A pointer to a newly allocated Dali resource
+   */
+  VisualObject(Dali::Internal::VisualObject* object);
+};
+} // namespace Dali
+
+#endif // CSHARP_VISUAL_OBJECT_H
\ No newline at end of file
diff --git a/dali-csharp-binder/common/visual-objects/visual-objects-container-impl.cpp b/dali-csharp-binder/common/visual-objects/visual-objects-container-impl.cpp
new file mode 100644 (file)
index 0000000..5129638
--- /dev/null
@@ -0,0 +1,273 @@
+/*
+ * 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 <dali-csharp-binder/common/visual-objects/visual-objects-container-impl.h>
+
+// EXTERNAL INCLUDES
+#include <dali-toolkit/devel-api/controls/control-depth-index-ranges.h>
+#include <dali-toolkit/devel-api/controls/control-devel.h>
+#include <dali-toolkit/public-api/controls/control-impl.h>
+#include <dali-toolkit/public-api/controls/control.h>
+#include <dali/integration-api/adaptor-framework/adaptor.h>
+#include <dali/integration-api/debug.h>
+
+// INTERNAL INCLUDES
+#include <dali-csharp-binder/common/visual-objects/visual-object-impl.h>
+#include <dali-csharp-binder/common/visual-objects/visual-object.h>
+
+namespace Dali::Internal
+{
+namespace
+{
+constexpr std::string_view VISUAL_OBJECT_PROPERTY_NAME_PREFIX("VisualObject");
+
+constexpr uint32_t MAXIMUM_VISUAL_OBJECTS_COUNT = (Dali::Toolkit::DepthIndex::Ranges::CONTENT - Dali::Toolkit::DepthIndex::Ranges::BACKGROUND - 1u - 3u /* Placeholder + Transition + RenderEffect */);
+} // namespace
+VisualObjectsContainerPtr VisualObjectsContainer::New(Dali::Toolkit::Control control, Dali::VisualObjectsContainer::ContainerRangeType rangeType)
+{
+  VisualObjectsContainerPtr container(new VisualObjectsContainer(control, rangeType));
+  return container;
+}
+
+///< Public API
+
+Dali::Toolkit::Control VisualObjectsContainer::GetOwner() const
+{
+  return mControl.GetHandle();
+}
+
+Dali::VisualObjectsContainer::ContainerRangeType VisualObjectsContainer::GetContainerRangeType() const
+{
+  return mRangeType;
+}
+
+uint32_t VisualObjectsContainer::GetVisualObjectsCount() const
+{
+  return static_cast<uint32_t>(mVisualObjects.size());
+}
+
+Dali::VisualObject VisualObjectsContainer::GetVisualObjectAt(uint32_t index) const
+{
+  DALI_ASSERT_ALWAYS(index < mVisualObjects.size() && "Visual object index out of bounds");
+  return mVisualObjects[index];
+}
+
+bool VisualObjectsContainer::AddVisualObject(Dali::VisualObject visualObject)
+{
+  if(visualObject)
+  {
+    if(DALI_UNLIKELY(!Dali::Adaptor::IsAvailable()))
+    {
+      DALI_LOG_ERROR("Application is terminated, or worker thread call this API. Add VisualObject failed.\n");
+      return false;
+    }
+
+    Dali::VisualObjectsContainer self(this); // Keep reference for safety
+
+    auto oldContainer = visualObject.GetContainer();
+
+    // Skip below logic if visual object is already in this container.
+    if(self != oldContainer)
+    {
+      if(mVisualObjects.size() >= MAXIMUM_VISUAL_OBJECTS_COUNT)
+      {
+        DALI_LOG_ERROR("Visual objects container is full. Add VisualObject failed.\n");
+        return false;
+      }
+
+      if(oldContainer)
+      {
+        visualObject.DetachFromContainer();
+      }
+
+      // Add to this container.
+      auto& visualObjectImpl = GetImplementation(visualObject);
+      visualObjectImpl.AttachToContainerInternal(self);
+      visualObjectImpl.SetSiblingOrderInternal(mVisualObjects.size());
+
+      ReplaceVisualObject(visualObjectImpl);
+
+      mVisualObjects.push_back(visualObject);
+      return true;
+    }
+  }
+  return false;
+}
+
+void VisualObjectsContainer::RemoveVisualObject(Dali::VisualObject visualObject)
+{
+  if(visualObject)
+  {
+    if(DALI_UNLIKELY(!Dali::Adaptor::IsAvailable()))
+    {
+      return;
+    }
+
+    Dali::VisualObjectsContainer self(this); // Keep reference for safety
+
+    auto iter = std::find(mVisualObjects.begin(), mVisualObjects.end(), visualObject);
+    if(iter != mVisualObjects.end())
+    {
+      // Shift down other visual objects sibling order
+      uint32_t siblingOrder = visualObject.GetSiblingOrder();
+      for(auto jter = iter + 1; jter != mVisualObjects.end(); ++jter)
+      {
+        GetImplementation(*jter).SetSiblingOrderInternal(siblingOrder++);
+      }
+      mVisualObjects.erase(iter);
+
+      auto& visualObjectImpl = GetImplementation(visualObject);
+      UnregisterVisualObject(visualObjectImpl);
+      visualObjectImpl.DetachFromContainerInternal();
+    }
+  }
+}
+
+void VisualObjectsContainer::ChangeSiblingOrder(uint32_t fromIndex, uint32_t toIndex)
+{
+  DALI_ASSERT_ALWAYS(fromIndex < mVisualObjects.size() && "fromIndex is out of bounds");
+  DALI_ASSERT_ALWAYS(toIndex < mVisualObjects.size() && "toIndex is out of bounds");
+  if(fromIndex != toIndex)
+  {
+    // Keep reference of visual object.
+    Dali::VisualObject visualObject = mVisualObjects[fromIndex];
+
+    if(fromIndex < toIndex)
+    {
+      for(uint32_t i = fromIndex; i != toIndex; ++i)
+      {
+        GetImplementation(mVisualObjects[i + 1]).SetSiblingOrderInternal(i);
+        mVisualObjects[i] = mVisualObjects[i + 1];
+      }
+    }
+    else if(fromIndex > toIndex)
+    {
+      for(uint32_t i = fromIndex; i != toIndex; --i)
+      {
+        GetImplementation(mVisualObjects[i - 1]).SetSiblingOrderInternal(i);
+        mVisualObjects[i] = mVisualObjects[i - 1];
+      }
+    }
+    GetImplementation(visualObject).SetSiblingOrderInternal(toIndex);
+    mVisualObjects[toIndex] = visualObject;
+  }
+}
+
+// Private and internal
+
+void VisualObjectsContainer::ReplaceVisualObject(Dali::Internal::VisualObject& visualObjectImpl)
+{
+  if(DALI_LIKELY(Dali::Adaptor::IsAvailable()))
+  {
+    Dali::Toolkit::Control control = mControl.GetHandle();
+    if(control)
+    {
+      VisualObject::VisualPropertyId propertyId = visualObjectImpl.GetVisualPropertyId();
+
+      Property::Index index = Property::INVALID_INDEX;
+
+      if(propertyId == VisualObject::INVALID_VISUAL_PROPERTY_ID)
+      {
+        // Add dummy index to converter, and get unique id.
+        propertyId = mVisualIndexConverter.Add(static_cast<uint32_t>(Property::INVALID_INDEX));
+
+        // Register new property to control using propertyId
+        {
+          std::ostringstream oss;
+          oss << VISUAL_OBJECT_PROPERTY_NAME_PREFIX << "_" << static_cast<int>(mRangeType) << "_" << propertyId;
+          index = control.RegisterProperty(oss.str(), Property::Value(oss.str()), Property::AccessMode::READ_WRITE);
+        }
+
+        // Change as valid index now.
+        mVisualIndexConverter[propertyId] = static_cast<uint32_t>(index);
+
+        visualObjectImpl.SetVisualPropertyId(propertyId);
+      }
+      else
+      {
+        index = mVisualIndexConverter[propertyId];
+      }
+
+      if(index != Property::INVALID_INDEX)
+      {
+        // Replace visual.
+        auto visualBase = visualObjectImpl.GetVisual();
+        if(visualBase)
+        {
+          // Register the visual to the control.
+          Dali::Toolkit::DevelControl::RegisterVisual(Dali::Toolkit::Internal::GetImplementation(control), index, visualBase, static_cast<int>(visualObjectImpl.GetDepthIndex()));
+        }
+        else
+        {
+          // Unregister the visual from the control.
+          Dali::Toolkit::DevelControl::UnregisterVisual(Dali::Toolkit::Internal::GetImplementation(control), index);
+        }
+      }
+    }
+  }
+}
+
+void VisualObjectsContainer::UnregisterVisualObject(Dali::Internal::VisualObject& visualObjectImpl)
+{
+  if(DALI_LIKELY(Dali::Adaptor::IsAvailable()))
+  {
+    Dali::Toolkit::Control control = mControl.GetHandle();
+    if(control)
+    {
+      VisualObject::VisualPropertyId propertyId = visualObjectImpl.GetVisualPropertyId();
+
+      DALI_ASSERT_ALWAYS(propertyId != VisualObject::INVALID_VISUAL_PROPERTY_ID && "VisualObject is not registered before!");
+
+      Property::Index index = static_cast<Property::Index>(mVisualIndexConverter[propertyId]);
+      if(index != Property::INVALID_INDEX)
+      {
+        Dali::Toolkit::DevelControl::UnregisterVisual(Dali::Toolkit::Internal::GetImplementation(control), index);
+      }
+      mVisualIndexConverter.Remove(propertyId);
+
+      visualObjectImpl.SetVisualPropertyId(VisualObject::INVALID_VISUAL_PROPERTY_ID);
+    }
+  }
+}
+
+VisualObjectsContainer::VisualObjectsContainer(Dali::Toolkit::Control control, Dali::VisualObjectsContainer::ContainerRangeType rangeType)
+: BaseObject(),
+  mVisualObjects(),
+  mControl(control),
+  mRangeType(rangeType),
+  mVisualIndexConverter()
+{
+}
+
+VisualObjectsContainer::~VisualObjectsContainer()
+{
+  if(DALI_LIKELY(Dali::Adaptor::IsAvailable()))
+  {
+    // Detach visual objects without touch the containers.
+    for(auto&& visualObject : mVisualObjects)
+    {
+      auto& visualObjectImpl = GetImplementation(visualObject);
+
+      UnregisterVisualObject(visualObjectImpl);
+      visualObjectImpl.DetachFromContainerInternal();
+    }
+    mVisualObjects.clear();
+  }
+}
+
+} // namespace Dali::Internal
\ No newline at end of file
diff --git a/dali-csharp-binder/common/visual-objects/visual-objects-container-impl.h b/dali-csharp-binder/common/visual-objects/visual-objects-container-impl.h
new file mode 100644 (file)
index 0000000..aa4292d
--- /dev/null
@@ -0,0 +1,154 @@
+#ifndef CSHARP_VISUAL_OBJECTS_CONTAINER_IMPL_H
+#define CSHARP_VISUAL_OBJECTS_CONTAINER_IMPL_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.
+ *
+ */
+
+// EXTERNAL INCLUDES
+#include <dali-toolkit/devel-api/visual-factory/visual-base.h>
+#include <dali-toolkit/public-api/controls/control.h>
+#include <dali/devel-api/common/free-list.h>
+#include <dali/public-api/common/dali-common.h>
+#include <dali/public-api/common/intrusive-ptr.h>
+#include <dali/public-api/common/vector-wrapper.h>
+#include <dali/public-api/object/base-object.h>
+#include <dali/public-api/object/weak-handle.h>
+
+// INTERNAL INCLUDES
+#include <dali-csharp-binder/common/visual-objects/visual-object.h>
+
+namespace Dali
+{
+namespace Internal
+{
+class VisualObjectsContainer;
+using VisualObjectsContainerPtr = Dali::IntrusivePtr<VisualObjectsContainer>;
+
+class VisualObjectsContainer : public Dali::BaseObject
+{
+public:
+  /**
+   * @brief Creates a VisualObjectsContainer object.
+   *
+   * @SINCE_2_3.27
+   * @param[in] control The control that owns this VisualObjectsContainer.
+   * @param[in] rangeType The range type of this VisualObjectsContainer.
+   * @return The newly created visual object container.
+   */
+  static VisualObjectsContainerPtr New(Dali::Toolkit::Control control, Dali::VisualObjectsContainer::ContainerRangeType rangeType);
+
+public: ///< Public API
+  /**
+   * @copydoc Dali::VisualObjectsContainer::GetOwner()
+   */
+  Dali::Toolkit::Control GetOwner() const;
+
+  /**
+   * @copydoc Dali::VisualObjectsContainer::GetContainerRangeType()
+   */
+  Dali::VisualObjectsContainer::ContainerRangeType GetContainerRangeType() const;
+
+  /**
+   * @copydoc Dali::VisualObjectsContainer::GetVisualObjectsCount()
+   */
+  uint32_t GetVisualObjectsCount() const;
+
+  /**
+   * @copydoc Dali::VisualObjectsContainer::GetVisualObjectAt()
+   */
+  Dali::VisualObject GetVisualObjectAt(uint32_t index) const;
+
+  /**
+   * @copydoc Dali::VisualObjectsContainer::AddVisualObject()
+   */
+  bool AddVisualObject(Dali::VisualObject visualObject);
+
+  /**
+   * @copydoc Dali::VisualObjectsContainer::RemoveVisualObject()
+   */
+  void RemoveVisualObject(Dali::VisualObject visualObject);
+
+public: ///< Called from Internal::VisualObject
+  /**
+   * @brief Replace visual object's visual into the control.
+   * If the visual object is already registered, it will be replaced.
+   * If VisualObject doesn't have visual yet, it will unregister visual.
+   *
+   * @param[in] visualObjectImpl visual object implements.
+   */
+  void ReplaceVisualObject(Dali::Internal::VisualObject& visualObjectImpl);
+
+  /**
+   * @copydoc Dali::VisualObjectsContainer::ChangeSiblingOrder()
+   */
+  void ChangeSiblingOrder(uint32_t fromIndex, uint32_t toIndex);
+
+private:
+  /**
+   * @brief Unregister visual object's visual from the control.
+   *
+   * @param[in] visualObjectImpl visual object implements.
+   */
+  void UnregisterVisualObject(Dali::Internal::VisualObject& visualObjectImpl);
+
+public:
+  /**
+   * @brief Constructor - creates a VisualObjectsContainer.
+   *
+   * @param[in] control The control that owns this VisualObjectsContainer.
+   * @param[in] rangeType The range type of this VisualObjectsContainer.
+   */
+  VisualObjectsContainer(Dali::Toolkit::Control control, Dali::VisualObjectsContainer::ContainerRangeType rangeType);
+
+  /**
+   * @brief Destructor.
+   */
+  ~VisualObjectsContainer() override;
+
+private:
+  std::vector<Dali::VisualObject>          mVisualObjects;
+  Dali::WeakHandle<Dali::Toolkit::Control> mControl;
+
+  const Dali::VisualObjectsContainer::ContainerRangeType mRangeType;
+
+  Dali::FreeList mVisualIndexConverter; ///< Convert from virtual visual index of VisualObject to actual visual index of mControl.
+};
+} // namespace Internal
+
+// Helpers for api forwarding methods
+
+inline static Internal::VisualObjectsContainer& GetImplementation(Dali::VisualObjectsContainer& handle)
+{
+  DALI_ASSERT_ALWAYS(handle && "VisualObjectsContainer handle is empty.");
+
+  Dali::BaseObject& object = handle.GetBaseObject();
+
+  return static_cast<Internal::VisualObjectsContainer&>(object);
+}
+
+inline static const Internal::VisualObjectsContainer& GetImplementation(const Dali::VisualObjectsContainer& handle)
+{
+  DALI_ASSERT_ALWAYS(handle && "VisualObjectsContainer handle is empty.");
+
+  const Dali::BaseObject& object = handle.GetBaseObject();
+
+  return static_cast<const Internal::VisualObjectsContainer&>(object);
+}
+
+} // namespace Dali
+
+#endif // CSHARP_VISUAL_OBJECTS_CONTAINER_IMPL_H
\ No newline at end of file
diff --git a/dali-csharp-binder/common/visual-objects/visual-objects-container.cpp b/dali-csharp-binder/common/visual-objects/visual-objects-container.cpp
new file mode 100644 (file)
index 0000000..3a3c3e8
--- /dev/null
@@ -0,0 +1,249 @@
+/*
+ * 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 <dali-csharp-binder/common/visual-objects/visual-objects-container.h>
+
+// EXTERNAL INCLUDES
+#include <dali/integration-api/debug.h>
+
+// INTERNAL INCLUDES
+#include <dali-csharp-binder/common/common.h>
+#include <dali-csharp-binder/common/visual-objects/visual-object.h>
+#include <dali-csharp-binder/common/visual-objects/visual-objects-container-impl.h>
+
+namespace Dali
+{
+VisualObjectsContainer::VisualObjectsContainer(Dali::Internal::VisualObjectsContainer* object)
+: BaseHandle(object)
+{
+}
+
+VisualObjectsContainer VisualObjectsContainer::New(Dali::Toolkit::Control control, VisualObjectsContainer::ContainerRangeType rangeType)
+{
+  Internal::VisualObjectsContainerPtr internal = Internal::VisualObjectsContainer::New(control, rangeType);
+  return VisualObjectsContainer(internal.Get());
+}
+
+VisualObjectsContainer VisualObjectsContainer::DownCast(BaseHandle handle)
+{
+  return VisualObjectsContainer(dynamic_cast<Dali::Internal::VisualObjectsContainer*>(handle.GetObjectPtr()));
+}
+
+///< Public API
+
+Dali::Toolkit::Control VisualObjectsContainer::GetOwner() const
+{
+  return GetImplementation(*this).GetOwner();
+}
+
+VisualObjectsContainer::ContainerRangeType VisualObjectsContainer::GetContainerRangeType() const
+{
+  return GetImplementation(*this).GetContainerRangeType();
+}
+
+uint32_t VisualObjectsContainer::GetVisualObjectsCount() const
+{
+  return GetImplementation(*this).GetVisualObjectsCount();
+}
+
+Dali::VisualObject VisualObjectsContainer::GetVisualObjectAt(uint32_t index) const
+{
+  return GetImplementation(*this).GetVisualObjectAt(index);
+}
+
+bool VisualObjectsContainer::AddVisualObject(Dali::VisualObject visualObject)
+{
+  return GetImplementation(*this).AddVisualObject(visualObject);
+}
+
+void VisualObjectsContainer::RemoveVisualObject(Dali::VisualObject visualObject)
+{
+  GetImplementation(*this).RemoveVisualObject(visualObject);
+}
+
+} // namespace Dali
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+SWIGEXPORT int SWIGSTDCALL CSharp_Dali_VisualObjectsContainer_ContainerRangeTypeBackgroundEffectGet()
+{
+  return static_cast<int>(Dali::VisualObjectsContainer::ContainerRangeType::BACKGROUND_EFFECT);
+}
+
+SWIGEXPORT int SWIGSTDCALL CSharp_Dali_VisualObjectsContainer_ContainerRangeTypeBackgroundGet()
+{
+  return static_cast<int>(Dali::VisualObjectsContainer::ContainerRangeType::BACKGROUND);
+}
+
+SWIGEXPORT int SWIGSTDCALL CSharp_Dali_VisualObjectsContainer_ContainerRangeTypeContentGet()
+{
+  return static_cast<int>(Dali::VisualObjectsContainer::ContainerRangeType::CONTENT);
+}
+
+SWIGEXPORT int SWIGSTDCALL CSharp_Dali_VisualObjectsContainer_ContainerRangeTypeDecorationGet()
+{
+  return static_cast<int>(Dali::VisualObjectsContainer::ContainerRangeType::DECORATION);
+}
+
+SWIGEXPORT int SWIGSTDCALL CSharp_Dali_VisualObjectsContainer_ContainerRangeTypeForegroundEffectGet()
+{
+  return static_cast<int>(Dali::VisualObjectsContainer::ContainerRangeType::FOREGROUND_EFFECT);
+}
+
+SWIGEXPORT void* SWIGSTDCALL CSharp_Dali_new_VisualObjectsContainer__SWIG_0()
+{
+  Dali::VisualObjectsContainer* result = 0;
+
+  try_catch(([&]() {
+    result = (Dali::VisualObjectsContainer*)new Dali::VisualObjectsContainer();
+  }));
+
+  return (void*)result;
+}
+
+SWIGEXPORT void* SWIGSTDCALL CSharp_Dali_VisualObjectsContainer_New(void* nuiView, int rangeType)
+{
+  void*                        jresult = 0;
+  Dali::VisualObjectsContainer result;
+
+  GUARD_ON_NULL_RET0(nuiView);
+
+  try_catch(([&]() {
+    auto handle  = (Dali::BaseHandle*)nuiView;
+    auto control = Dali::Toolkit::Control::DownCast(*handle);
+    if(control)
+    {
+      result = Dali::VisualObjectsContainer::New(control, static_cast<Dali::VisualObjectsContainer::ContainerRangeType>(rangeType));
+    }
+  }));
+
+  jresult = new Dali::VisualObjectsContainer((const Dali::VisualObjectsContainer&)result);
+  return jresult;
+}
+
+SWIGEXPORT void SWIGSTDCALL CSharp_Dali_delete_VisualObjectsContainer(void* nuiVisualObjectsContainer)
+{
+  Dali::VisualObjectsContainer* arg1 = (Dali::VisualObjectsContainer*)0;
+
+  arg1 = (Dali::VisualObjectsContainer*)nuiVisualObjectsContainer;
+  try_catch(([&]() {
+    delete arg1;
+  }));
+}
+
+SWIGEXPORT void* SWIGSTDCALL CSharp_Dali_VisualObjectsContainer_GetOwner(void* nuiVisualObjectsContainer)
+{
+  void*                               jresult   = 0;
+  const Dali::VisualObjectsContainer* container = (const Dali::VisualObjectsContainer*)0;
+  Dali::Toolkit::Control              result;
+
+  GUARD_ON_NULL_RET0(nuiVisualObjectsContainer);
+
+  container = (const Dali::VisualObjectsContainer*)nuiVisualObjectsContainer;
+  try_catch(([&]() {
+    result = container->GetOwner();
+  }));
+
+  jresult = new Dali::Toolkit::Control((const Dali::Toolkit::Control&)result);
+  return jresult;
+}
+
+SWIGEXPORT int SWIGSTDCALL CSharp_Dali_VisualObjectsContainer_GetContainerRangeType(void* nuiVisualObjectsContainer)
+{
+  const Dali::VisualObjectsContainer*              container = (const Dali::VisualObjectsContainer*)0;
+  Dali::VisualObjectsContainer::ContainerRangeType result    = Dali::VisualObjectsContainer::ContainerRangeType::CONTENT;
+
+  GUARD_ON_NULL_RET0(nuiVisualObjectsContainer);
+
+  container = (const Dali::VisualObjectsContainer*)nuiVisualObjectsContainer;
+  try_catch(([&]() {
+    result = container->GetContainerRangeType();
+  }));
+
+  return static_cast<int>(result);
+}
+
+SWIGEXPORT uint32_t SWIGSTDCALL CSharp_Dali_VisualObjectsContainer_GetVisualObjectsCount(void* nuiVisualObjectsContainer)
+{
+  const Dali::VisualObjectsContainer* container = (const Dali::VisualObjectsContainer*)0;
+  uint32_t                            result    = 0u;
+
+  GUARD_ON_NULL_RET0(nuiVisualObjectsContainer);
+
+  container = (const Dali::VisualObjectsContainer*)nuiVisualObjectsContainer;
+  try_catch(([&]() {
+    result = container->GetVisualObjectsCount();
+  }));
+
+  return result;
+}
+
+SWIGEXPORT void* SWIGSTDCALL CSharp_Dali_VisualObjectsContainer_GetVisualObjectAt(void* nuiVisualObjectsContainer, uint32_t index)
+{
+  void*                               jresult   = 0;
+  const Dali::VisualObjectsContainer* container = (const Dali::VisualObjectsContainer*)0;
+  Dali::VisualObject                  result;
+
+  GUARD_ON_NULL_RET0(nuiVisualObjectsContainer);
+
+  container = (const Dali::VisualObjectsContainer*)nuiVisualObjectsContainer;
+  try_catch(([&]() {
+    result = container->GetVisualObjectAt(index);
+  }));
+
+  jresult = new Dali::VisualObject((const Dali::VisualObject&)result);
+  return jresult;
+}
+
+SWIGEXPORT bool SWIGSTDCALL CSharp_Dali_VisualObjectsContainer_AddVisualObject(void* nuiVisualObjectsContainer, void* nuiVisualObject)
+{
+  Dali::VisualObjectsContainer* container    = (Dali::VisualObjectsContainer*)0;
+  Dali::VisualObject*           visualObject = (Dali::VisualObject*)0;
+  bool                          result       = false;
+
+  GUARD_ON_NULL_RET0(nuiVisualObjectsContainer);
+  GUARD_ON_NULL_RET0(nuiVisualObject);
+
+  container    = (Dali::VisualObjectsContainer*)nuiVisualObjectsContainer;
+  visualObject = (Dali::VisualObject*)nuiVisualObject;
+  try_catch(([&]() {
+    result = container->AddVisualObject(*visualObject);
+  }));
+  return result;
+}
+
+SWIGEXPORT void SWIGSTDCALL CSharp_Dali_VisualObjectsContainer_RemoveVisualObject(void* nuiVisualObjectsContainer, void* nuiVisualObject)
+{
+  Dali::VisualObjectsContainer* container    = (Dali::VisualObjectsContainer*)0;
+  Dali::VisualObject*           visualObject = (Dali::VisualObject*)0;
+
+  GUARD_ON_NULL_RET(nuiVisualObjectsContainer);
+  GUARD_ON_NULL_RET(nuiVisualObject);
+
+  container    = (Dali::VisualObjectsContainer*)nuiVisualObjectsContainer;
+  visualObject = (Dali::VisualObject*)nuiVisualObject;
+  try_catch(([&]() {
+    container->RemoveVisualObject(*visualObject);
+  }));
+}
+
+#ifdef __cplusplus
+}
+#endif
\ No newline at end of file
diff --git a/dali-csharp-binder/common/visual-objects/visual-objects-container.h b/dali-csharp-binder/common/visual-objects/visual-objects-container.h
new file mode 100644 (file)
index 0000000..c6503d7
--- /dev/null
@@ -0,0 +1,164 @@
+#ifndef CSHARP_VISUAL_OBJECTS_CONTAINER_H
+#define CSHARP_VISUAL_OBJECTS_CONTAINER_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.
+ *
+ */
+
+// EXTERNAL INCLUDES
+#include <dali-toolkit/public-api/controls/control.h>
+#include <dali/public-api/object/base-handle.h>
+
+namespace Dali
+{
+namespace Internal
+{
+class VisualObjectsContainer;
+}
+
+class VisualObject;
+
+/**
+ * @brief VisualObjectsContainer is a container for visual objects for C# specific policy.
+ *
+ * For each VisualObjectContainer, there is a corresponding control.
+ * Each control can has only one VisualObjectsContainer per each ContainerRangeType.
+ *
+ * It is used to manage visual objects properties to owned control;
+ * e.g. SiblingOrder of visual objects to DepthIndex of visual.
+ *
+ * To avoid the collision between Dali toolkit logic and C# specific policy,
+ * there is some limitation of visual object counts per each ContainerRangeType.
+ *
+ * For example, if ContainerRangeType is ContainerRangeType::CONTENT,
+ * it will use visual object's depth index only between
+ * Dali::Toolkit::DepthIndex::Ranges::BACKGROUND and Dali::Toolkit::DepthIndex::Ranges::CONTENT.
+ * If user try to add over the Dali::Toolkit::DepthIndex::Ranges::CONTENT, it will be ignored.
+ *
+ * @SINCE_2_3.27
+ */
+class VisualObjectsContainer : public Dali::BaseHandle
+{
+public:
+  /**
+   * @brief Enumeration for the visual objects container range.
+   * It will be used when we determine the visual's depth index.
+   *
+   * @SINCE_2_3.27
+   */
+  enum class ContainerRangeType
+  {
+    BACKGROUND_EFFECT, ///< The visual object exist under Dali::Toolkit::DepthIndex::Ranges::BACKGROUND_EFFECT
+    BACKGROUND,        ///< The visual object exist between Dali::Toolkit::DepthIndex::Ranges::BACKGROUND_EFFECT and Dali::Toolkit::DepthIndex::Ranges::BACKGROUND
+    CONTENT,           ///< The visual object exist between Dali::Toolkit::DepthIndex::Ranges::BACKGROUND and Dali::Toolkit::DepthIndex::Ranges::CONTENT
+    DECORATION,        ///< The visual object exist between Dali::Toolkit::DepthIndex::Ranges::CONTENT and Dali::Toolkit::DepthIndex::Ranges::DECORATION
+    FOREGROUND_EFFECT, ///< The visual object exist between Dali::Toolkit::DepthIndex::Ranges::DECORATION and Dali::Toolkit::DepthIndex::Ranges::FOREGROUND_EFFECT
+  };
+
+  /**
+   * @brief Creates a VisualObjectsContainer object.
+   *
+   * @SINCE_2_3.27
+   * @param[in] control The control that owns this VisualObjectsContainer.
+   * @param[in] rangeType The range type of this VisualObjectsContainer.
+   * @return The newly created visual objects container
+   * @post The control should not create another VisualObjectsContainer for each rangeType.
+   */
+  static VisualObjectsContainer New(Dali::Toolkit::Control control, ContainerRangeType rangeType = ContainerRangeType::CONTENT);
+
+public: ///< Public API
+  /**
+   * @brief Adds a visual object to the container.
+   *
+   * @SINCE_2_3.27
+   * @return The owner of this container, or empty handle if owner is invalid.
+   */
+  Dali::Toolkit::Control GetOwner() const;
+
+  /**
+   * @brief Gets the range type of VisualObjectsContainer.
+   *
+   * @SINCE_2_3.27
+   * @return The range type of VisualObjectsContainer.
+   */
+  ContainerRangeType GetContainerRangeType() const;
+
+  /**
+   * @brief Gets the number of visual objects in the container.
+   *
+   * @SINCE_2_3.27
+   * @return The number of visual objects in the container.
+   */
+  uint32_t GetVisualObjectsCount() const;
+
+  /**
+   * @brief Get the visual objects from the container.
+   * @note If index is out of range, will throw exception.
+   *
+   * @SINCE_2_3.27
+   * @param[in] index The index of the visual object to get.
+   * @return The visual object at the given index.
+   */
+  Dali::VisualObject GetVisualObjectAt(uint32_t index) const;
+
+  /**
+   * @brief Adds a visual object to the container.
+   * Added visual object will be placed top of other visuals.
+   * If the container cannot add more than maxium count of objects
+   * or the visual object is already added, It will be ignored.
+   *
+   * @SINCE_2_3.27
+   * @param[in] visualObject The visual object to be added.
+   * @return True if the visual object is added successfully.
+   */
+  bool AddVisualObject(Dali::VisualObject visualObject);
+
+  /**
+   * @brief Removes a visual object from the container.
+   * All other visual objects will be shifted down.
+   *
+   * @SINCE_2_3.27
+   * @param[in] visualObject The visual object to be added.
+   */
+  void RemoveVisualObject(Dali::VisualObject visualObject);
+
+public:
+  VisualObjectsContainer()                                     = default;
+  ~VisualObjectsContainer()                                    = default;
+  VisualObjectsContainer(const VisualObjectsContainer& handle) = default;
+  VisualObjectsContainer& operator=(const VisualObjectsContainer& rhs) = default;
+  VisualObjectsContainer(VisualObjectsContainer&& rhs) noexcept        = default;
+  VisualObjectsContainer& operator=(VisualObjectsContainer&& rhs) noexcept = default;
+
+  /**
+   * @brief Downcasts a handle to VisualObjectsContainer handle.
+   *
+   * @param[in] handle Handle to an object
+   * @return A handle to a VisualObjectsContainer or an uninitialized handle
+   */
+  static VisualObjectsContainer DownCast(BaseHandle handle);
+
+public:
+  /**
+   * @brief This constructor is used by Dali New() methods.
+   *
+   * @param[in] object A pointer to a newly allocated Dali resource
+   */
+  VisualObjectsContainer(Dali::Internal::VisualObjectsContainer* object);
+};
+} // namespace Dali
+
+#endif // CSHARP_VISUAL_OBJECTS_CONTAINER_H
\ No newline at end of file
index 7a9e931..6fbca92 100755 (executable)
@@ -7,6 +7,11 @@ SET( dali_csharp_binder_dir ${CMAKE_CURRENT_SOURCE_DIR}/../../dali-csharp-binder
 
 # module: csharp-binder, backend: common - ubuntu,mobile,tv,ivi,tizen-wearable,common
 SET( dali_csharp_binder_common_src_files
+  ${dali_csharp_binder_dir}/common/visual-objects/visual-object-impl.cpp
+  ${dali_csharp_binder_dir}/common/visual-objects/visual-object.cpp
+  ${dali_csharp_binder_dir}/common/visual-objects/visual-objects-container-impl.cpp
+  ${dali_csharp_binder_dir}/common/visual-objects/visual-objects-container.cpp
+
   ${dali_csharp_binder_dir}/common/common.cpp
   ${dali_csharp_binder_dir}/common/dali-wrap.cpp
   ${dali_csharp_binder_dir}/common/callbackbase-wrap.cpp