From: Eunki, Hong Date: Mon, 21 Apr 2025 10:23:52 +0000 (+0900) Subject: Support InnerShadow and Borderline for control X-Git-Tag: dali_2.4.17~8^2 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=refs%2Fchanges%2F06%2F323006%2F7;p=platform%2Fcore%2Fuifw%2Fdali-toolkit.git Support InnerShadow and Borderline for control Let we define new properties for INNER_SHADOW and BORDERLINE. We should make rendering order as SHADOW - BACKGROUND - (CONTENT) - INNER_SHADOW - BORDERLINE. So make INNER_SHADOW and BORDERLINE depth index as DECORATOIN reltive range. Also, make BORDERLINE_WIDTH animatable properties to make we control BORDERLINE visual easier, and make it animatable. Change-Id: I1c8b4be1b0d98399105015c966395ae064c5b726 Signed-off-by: Eunki, Hong --- diff --git a/automated-tests/src/dali-toolkit/utc-Dali-Control.cpp b/automated-tests/src/dali-toolkit/utc-Dali-Control.cpp index 46ce1c0e6e..181f32917c 100644 --- a/automated-tests/src/dali-toolkit/utc-Dali-Control.cpp +++ b/automated-tests/src/dali-toolkit/utc-Dali-Control.cpp @@ -27,6 +27,7 @@ #include #include #include +#include #include #include @@ -719,6 +720,42 @@ int UtcDaliControlShadowProperties(void) END_TEST; } +int UtcDaliControlInnerShadowProperties(void) +{ + ToolkitTestApplication application; + Control control = Control::New(); + + DALI_TEST_CHECK(control.GetProperty(DevelControl::Property::INNER_SHADOW).Get().Empty()); + + Property::Map imageMap; + imageMap[Toolkit::Visual::Property::TYPE] = Visual::IMAGE; + imageMap[ImageVisual::Property::URL] = "TestImage"; + control.SetProperty(DevelControl::Property::INNER_SHADOW, imageMap); + Property::Value propValue = control.GetProperty(DevelControl::Property::INNER_SHADOW); + Property::Map* resultMap = propValue.GetMap(); + DALI_TEST_CHECK(resultMap->Find(Toolkit::Visual::Property::TYPE)); + DALI_TEST_EQUALS(resultMap->Find(Toolkit::Visual::Property::TYPE)->Get(), (int)Visual::IMAGE, TEST_LOCATION); + DALI_TEST_CHECK(resultMap->Find(ImageVisual::Property::URL)); + DALI_TEST_EQUALS(resultMap->Find(ImageVisual::Property::URL)->Get(), "TestImage", TEST_LOCATION); + + Property::Map colorMap; + colorMap[Visual::Property::TYPE] = Visual::COLOR; + colorMap[ColorVisual::Property::MIX_COLOR] = Color::CYAN; + control.SetProperty(DevelControl::Property::INNER_SHADOW, colorMap); + propValue = control.GetProperty(DevelControl::Property::INNER_SHADOW); + resultMap = propValue.GetMap(); + DALI_TEST_CHECK(resultMap->Find(Toolkit::Visual::Property::TYPE)); + DALI_TEST_EQUALS(resultMap->Find(Toolkit::Visual::Property::TYPE)->Get(), (int)Visual::COLOR, TEST_LOCATION); + DALI_TEST_CHECK(resultMap->Find(ColorVisual::Property::MIX_COLOR)); + DALI_TEST_EQUALS(resultMap->Find(ColorVisual::Property::MIX_COLOR)->Get(), Color::CYAN, TEST_LOCATION); + + Property::Map emptyMap; + control.SetProperty(DevelControl::Property::INNER_SHADOW, emptyMap); + DALI_TEST_CHECK(control.GetProperty(DevelControl::Property::INNER_SHADOW).Get().Empty()); + + END_TEST; +} + int UtcDaliControlKeyProperties(void) { ToolkitTestApplication application; @@ -1609,6 +1646,8 @@ int UtcDaliControlNewWithDisableVisuals(void) // Check Background or Shadow with property map skipped control.SetProperty(Control::Property::BACKGROUND, propertyMap); control.SetProperty(DevelControl::Property::SHADOW, propertyMap); + control.SetProperty(DevelControl::Property::INNER_SHADOW, propertyMap); + control.SetProperty(DevelControl::Property::BORDERLINE, propertyMap); application.SendNotification(); application.Render(); @@ -1672,3 +1711,186 @@ int UtcDaliControlCornerRadius(void) END_TEST; } + +int UtcDaliControlBorderline(void) +{ + ToolkitTestApplication application; + + Control control = Control::New(); + control.SetProperty(Actor::Property::SIZE, Vector2(100.0f, 100.0f)); + control.SetProperty(Actor::Property::ANCHOR_POINT, AnchorPoint::TOP_LEFT); + + application.GetScene().Add(control); + + float borderlineWidth = 10.0f; + Vector4 borderlineColor = Color::BLUE; + float borderlineOffset = 0.2f; + + control.SetProperty(DevelControl::Property::BORDERLINE_WIDTH, borderlineWidth); + control.SetProperty(DevelControl::Property::BORDERLINE_COLOR, borderlineColor); + control.SetProperty(DevelControl::Property::BORDERLINE_OFFSET, borderlineOffset); + + application.SendNotification(); + application.Render(); + + float retrievedFloat; + Vector4 retrievedVector; + DALI_TEST_CHECK(control.GetProperty(DevelControl::Property::BORDERLINE_WIDTH).Get(retrievedFloat)); + DALI_TEST_EQUALS(retrievedFloat, borderlineWidth, TEST_LOCATION); + DALI_TEST_CHECK(control.GetProperty(DevelControl::Property::BORDERLINE_COLOR).Get(retrievedVector)); + DALI_TEST_EQUALS(retrievedVector, borderlineColor, TEST_LOCATION); + DALI_TEST_CHECK(control.GetProperty(DevelControl::Property::BORDERLINE_OFFSET).Get(retrievedFloat)); + DALI_TEST_EQUALS(retrievedFloat, borderlineOffset, TEST_LOCATION); + + Property::Map retrievedMap; + + tet_printf("Check BORDERLINE visual has not corner radius value yet.\n"); + + Property::Value value = control.GetProperty(DevelControl::Property::BORDERLINE); + DALI_TEST_CHECK(value.GetMap()); + retrievedMap = *(value.GetMap()); + + Property::Value* valuePtr = retrievedMap.Find(DevelVisual::Property::CORNER_RADIUS); + if(valuePtr) + { + DALI_TEST_CHECK(valuePtr->Get(retrievedVector)); + DALI_TEST_EQUALS(retrievedVector, Vector4::ZERO, TEST_LOCATION); + } + + valuePtr = retrievedMap.Find(DevelVisual::Property::BORDERLINE_WIDTH); + DALI_TEST_CHECK(valuePtr); + DALI_TEST_CHECK(valuePtr->Get(retrievedFloat)); + DALI_TEST_EQUALS(retrievedFloat, borderlineWidth, TEST_LOCATION); + valuePtr = retrievedMap.Find(DevelVisual::Property::BORDERLINE_COLOR); + DALI_TEST_CHECK(valuePtr); + DALI_TEST_CHECK(valuePtr->Get(retrievedVector)); + DALI_TEST_EQUALS(retrievedVector, borderlineColor, TEST_LOCATION); + valuePtr = retrievedMap.Find(DevelVisual::Property::BORDERLINE_OFFSET); + DALI_TEST_CHECK(valuePtr); + DALI_TEST_CHECK(valuePtr->Get(retrievedFloat)); + DALI_TEST_EQUALS(retrievedFloat, borderlineOffset, TEST_LOCATION); + + tet_printf("Set corner radius. Check BORDERLINE visual has corner radius value now.\n"); + Vector4 radius = Vector4(0.5f, 0.5f, 0.5f, 0.5f); + Vector4 squreness = Vector4(0.3f, 0.3f, 0.3f, 0.3f); + control.SetProperty(DevelControl::Property::CORNER_RADIUS, radius); + control.SetProperty(DevelControl::Property::CORNER_RADIUS_POLICY, Toolkit::Visual::Transform::Policy::Type::RELATIVE); + control.SetProperty(DevelControl::Property::CORNER_SQUARENESS, squreness); + + value = control.GetProperty(DevelControl::Property::BORDERLINE); + DALI_TEST_CHECK(value.GetMap()); + retrievedMap = *(value.GetMap()); + + int retrievedInteger; + valuePtr = retrievedMap.Find(DevelVisual::Property::CORNER_RADIUS); + DALI_TEST_CHECK(valuePtr); + DALI_TEST_CHECK(valuePtr->Get(retrievedVector)); + DALI_TEST_EQUALS(retrievedVector, radius, TEST_LOCATION); + valuePtr = retrievedMap.Find(DevelVisual::Property::CORNER_RADIUS_POLICY); + DALI_TEST_CHECK(valuePtr); + DALI_TEST_CHECK(valuePtr->Get(retrievedInteger)); + DALI_TEST_EQUALS(retrievedInteger, (int)Toolkit::Visual::Transform::Policy::Type::RELATIVE, TEST_LOCATION); + valuePtr = retrievedMap.Find(DevelVisual::Property::CORNER_SQUARENESS); + DALI_TEST_CHECK(valuePtr); + DALI_TEST_CHECK(valuePtr->Get(retrievedVector)); + DALI_TEST_EQUALS(retrievedVector, squreness, TEST_LOCATION); + + valuePtr = retrievedMap.Find(DevelVisual::Property::BORDERLINE_WIDTH); + DALI_TEST_CHECK(valuePtr); + DALI_TEST_CHECK(valuePtr->Get(retrievedFloat)); + DALI_TEST_EQUALS(retrievedFloat, borderlineWidth, TEST_LOCATION); + valuePtr = retrievedMap.Find(DevelVisual::Property::BORDERLINE_COLOR); + DALI_TEST_CHECK(valuePtr); + DALI_TEST_CHECK(valuePtr->Get(retrievedVector)); + DALI_TEST_EQUALS(retrievedVector, borderlineColor, TEST_LOCATION); + valuePtr = retrievedMap.Find(DevelVisual::Property::BORDERLINE_OFFSET); + DALI_TEST_CHECK(valuePtr); + DALI_TEST_CHECK(valuePtr->Get(retrievedFloat)); + DALI_TEST_EQUALS(retrievedFloat, borderlineOffset, TEST_LOCATION); + + tet_printf("Change borderline value. Check BORDERLINE visual.\n"); + borderlineWidth = 20.0f; + borderlineColor = Color::RED; + borderlineOffset = -1.0f; + + control.SetProperty(DevelControl::Property::BORDERLINE_WIDTH, borderlineWidth); + control.SetProperty(DevelControl::Property::BORDERLINE_COLOR, borderlineColor); + control.SetProperty(DevelControl::Property::BORDERLINE_OFFSET, borderlineOffset); + + value = control.GetProperty(DevelControl::Property::BORDERLINE); + DALI_TEST_CHECK(value.GetMap()); + retrievedMap = *(value.GetMap()); + + valuePtr = retrievedMap.Find(DevelVisual::Property::CORNER_RADIUS); + DALI_TEST_CHECK(valuePtr); + DALI_TEST_CHECK(valuePtr->Get(retrievedVector)); + DALI_TEST_EQUALS(retrievedVector, radius, TEST_LOCATION); + valuePtr = retrievedMap.Find(DevelVisual::Property::CORNER_RADIUS_POLICY); + DALI_TEST_CHECK(valuePtr); + DALI_TEST_CHECK(valuePtr->Get(retrievedInteger)); + DALI_TEST_EQUALS(retrievedInteger, (int)Toolkit::Visual::Transform::Policy::Type::RELATIVE, TEST_LOCATION); + valuePtr = retrievedMap.Find(DevelVisual::Property::CORNER_SQUARENESS); + DALI_TEST_CHECK(valuePtr); + DALI_TEST_CHECK(valuePtr->Get(retrievedVector)); + DALI_TEST_EQUALS(retrievedVector, squreness, TEST_LOCATION); + + valuePtr = retrievedMap.Find(DevelVisual::Property::BORDERLINE_WIDTH); + DALI_TEST_CHECK(valuePtr); + DALI_TEST_CHECK(valuePtr->Get(retrievedFloat)); + DALI_TEST_EQUALS(retrievedFloat, borderlineWidth, TEST_LOCATION); + valuePtr = retrievedMap.Find(DevelVisual::Property::BORDERLINE_COLOR); + DALI_TEST_CHECK(valuePtr); + DALI_TEST_CHECK(valuePtr->Get(retrievedVector)); + DALI_TEST_EQUALS(retrievedVector, borderlineColor, TEST_LOCATION); + valuePtr = retrievedMap.Find(DevelVisual::Property::BORDERLINE_OFFSET); + DALI_TEST_CHECK(valuePtr); + DALI_TEST_CHECK(valuePtr->Get(retrievedFloat)); + DALI_TEST_EQUALS(retrievedFloat, borderlineOffset, TEST_LOCATION); + + tet_printf("Set borderline property forcibly!\n"); + borderlineWidth = 30.0f; + borderlineColor = Color::GREEN; + borderlineOffset = -0.3f; + // Just re-use retrieved map, to reduce duplicated property settings. + retrievedMap[DevelVisual::Property::CORNER_RADIUS] = Vector4(10.f, 20.f, 30.f, 40.f); + retrievedMap[DevelVisual::Property::CORNER_RADIUS_POLICY] = (int)Toolkit::Visual::Transform::Policy::Type::ABSOLUTE; + retrievedMap[DevelVisual::Property::CORNER_SQUARENESS] = Vector4(0.7f, 0.6f, 0.5f, 0.4f); + retrievedMap[DevelVisual::Property::BORDERLINE_WIDTH] = borderlineWidth; + retrievedMap[DevelVisual::Property::BORDERLINE_COLOR] = borderlineColor; + retrievedMap[DevelVisual::Property::BORDERLINE_OFFSET] = borderlineOffset; + + control.SetProperty(DevelControl::Property::BORDERLINE, retrievedMap); + + value = control.GetProperty(DevelControl::Property::BORDERLINE); + DALI_TEST_CHECK(value.GetMap()); + retrievedMap = *(value.GetMap()); + + // Check we are using Control's corner radius feature instead it's own. + valuePtr = retrievedMap.Find(DevelVisual::Property::CORNER_RADIUS); + DALI_TEST_CHECK(valuePtr); + DALI_TEST_CHECK(valuePtr->Get(retrievedVector)); + DALI_TEST_EQUALS(retrievedVector, radius, TEST_LOCATION); + valuePtr = retrievedMap.Find(DevelVisual::Property::CORNER_RADIUS_POLICY); + DALI_TEST_CHECK(valuePtr); + DALI_TEST_CHECK(valuePtr->Get(retrievedInteger)); + DALI_TEST_EQUALS(retrievedInteger, (int)Toolkit::Visual::Transform::Policy::Type::RELATIVE, TEST_LOCATION); + valuePtr = retrievedMap.Find(DevelVisual::Property::CORNER_SQUARENESS); + DALI_TEST_CHECK(valuePtr); + DALI_TEST_CHECK(valuePtr->Get(retrievedVector)); + DALI_TEST_EQUALS(retrievedVector, squreness, TEST_LOCATION); + + valuePtr = retrievedMap.Find(DevelVisual::Property::BORDERLINE_WIDTH); + DALI_TEST_CHECK(valuePtr); + DALI_TEST_CHECK(valuePtr->Get(retrievedFloat)); + DALI_TEST_EQUALS(retrievedFloat, borderlineWidth, TEST_LOCATION); + valuePtr = retrievedMap.Find(DevelVisual::Property::BORDERLINE_COLOR); + DALI_TEST_CHECK(valuePtr); + DALI_TEST_CHECK(valuePtr->Get(retrievedVector)); + DALI_TEST_EQUALS(retrievedVector, borderlineColor, TEST_LOCATION); + valuePtr = retrievedMap.Find(DevelVisual::Property::BORDERLINE_OFFSET); + DALI_TEST_CHECK(valuePtr); + DALI_TEST_CHECK(valuePtr->Get(retrievedFloat)); + DALI_TEST_EQUALS(retrievedFloat, borderlineOffset, TEST_LOCATION); + + END_TEST; +} diff --git a/dali-toolkit/devel-api/controls/control-devel.h b/dali-toolkit/devel-api/controls/control-devel.h index b8764b629b..3de84cab4b 100644 --- a/dali-toolkit/devel-api/controls/control-devel.h +++ b/dali-toolkit/devel-api/controls/control-devel.h @@ -265,6 +265,18 @@ enum */ OFFSCREEN_RENDERING, + /** + * @brief The inner shadow of the control. The visual will use DepthIndex::Ranges::DECORATION - 2 + * @details Name "innerShadow", type Property::MAP. + */ + INNER_SHADOW, + + /** + * @brief The inset borderline of the control. The visual will use DepthIndex::Ranges::DECORATION - 1 + * @details Name "borderline", type Property::MAP. + */ + BORDERLINE, + /** * @brief The radius for the rounded corners of the control. * @details Name "viewCornerRadius", type Property::VECTOR4 @@ -293,6 +305,30 @@ enum * @note It will not create UniformMap internally. So this property don't be used at Render phase. */ CORNER_SQUARENESS, + + /** + * @brief The width for the borderline of the control. It will update borderline visual + * @details Name "viewBorderlineWidth", type Property::FLOAT. + * @see Dali::Toolkit::DevelVisual::Property::Type::BORDERLINE_WIDTH + * @note It will not create UniformMap internally. So this property don't be used at Render phase. + */ + BORDERLINE_WIDTH, + + /** + * @brief The color for the borderline of the control. It will update borderline visual + * @details Name "viewBorderlineColor", type Property::VECTOR4 + * @see Dali::Toolkit::DevelVisual::Property::Type::BORDERLINE_COLOR + * @note It will not create UniformMap internally. So this property don't be used at Render phase. + */ + BORDERLINE_COLOR, + + /** + * @brief The offset for the borderline of the control. It will update borderline visual + * @details Name "viewBorderlineOffset", type Property::FLOAT. + * @see Dali::Toolkit::DevelVisual::Property::Type::BORDERLINE_OFFSET + * @note It will not create UniformMap internally. So this property don't be used at Render phase. + */ + BORDERLINE_OFFSET, }; } // namespace Property diff --git a/dali-toolkit/internal/controls/control/control-data-impl.cpp b/dali-toolkit/internal/controls/control/control-data-impl.cpp index d4f81737d5..041f2944f3 100644 --- a/dali-toolkit/internal/controls/control/control-data-impl.cpp +++ b/dali-toolkit/internal/controls/control/control-data-impl.cpp @@ -49,6 +49,8 @@ #include #include #include +#include +#include #include @@ -94,6 +96,9 @@ constexpr const char* ACTION_ACCESSIBILITY_READING_RESUMED = "ReadingResumed"; constexpr const char* ACTION_ACCESSIBILITY_READING_SKIPPED = "ReadingSkipped"; constexpr const char* ACTION_ACCESSIBILITY_READING_STOPPED = "ReadingStopped"; +constexpr int INNER_SHADOW_DEPTH_INDEX = DepthIndex::DECORATION - 2; +constexpr int BORDERLINE_DEPTH_INDEX = DepthIndex::DECORATION - 1; + bool PerformAccessibilityAction(Toolkit::Control control, const std::string& actionName, const Property::Map& attributes) { using Dali::Accessibility::ActionType; @@ -375,10 +380,15 @@ const PropertyRegistration Control::Impl::PROPERTY_28(typeRegistration, "accessi const PropertyRegistration Control::Impl::PROPERTY_29(typeRegistration, "accessibilityStates", Toolkit::DevelControl::Property::ACCESSIBILITY_STATES, Property::INTEGER, &Control::Impl::SetProperty, &Control::Impl::GetProperty); const PropertyRegistration Control::Impl::PROPERTY_30(typeRegistration, "accessibilityIsModal", Toolkit::DevelControl::Property::ACCESSIBILITY_IS_MODAL, Property::BOOLEAN, &Control::Impl::SetProperty, &Control::Impl::GetProperty); const PropertyRegistration Control::Impl::PROPERTY_31(typeRegistration, "offScreenRendering", Toolkit::DevelControl::Property::OFFSCREEN_RENDERING, Property::INTEGER, &Control::Impl::SetProperty, &Control::Impl::GetProperty); +const PropertyRegistration Control::Impl::PROPERTY_32(typeRegistration, "innerShadow", Toolkit::DevelControl::Property::INNER_SHADOW, Property::MAP, &Control::Impl::SetProperty, &Control::Impl::GetProperty); +const PropertyRegistration Control::Impl::PROPERTY_33(typeRegistration, "borderline", Toolkit::DevelControl::Property::BORDERLINE, Property::MAP, &Control::Impl::SetProperty, &Control::Impl::GetProperty); const AnimatablePropertyRegistration Control::Impl::ANIMATABLE_PROPERTY_1(typeRegistration, "viewCornerRadius", Toolkit::DevelControl::Property::CORNER_RADIUS, Property::VECTOR4, &Control::Impl::SetProperty, &Control::Impl::GetProperty); const AnimatablePropertyRegistration Control::Impl::ANIMATABLE_PROPERTY_2(typeRegistration, "viewCornerRadiusPolicy", Toolkit::DevelControl::Property::CORNER_RADIUS_POLICY, Property::INTEGER, &Control::Impl::SetProperty, &Control::Impl::GetProperty); ///< Make animatable, for constarint-input const AnimatablePropertyRegistration Control::Impl::ANIMATABLE_PROPERTY_3(typeRegistration, "viewCornerSquareness", Toolkit::DevelControl::Property::CORNER_SQUARENESS, Property::VECTOR4, &Control::Impl::SetProperty, &Control::Impl::GetProperty); +const AnimatablePropertyRegistration Control::Impl::ANIMATABLE_PROPERTY_4(typeRegistration, "viewBorderlineWidth", Toolkit::DevelControl::Property::BORDERLINE_WIDTH, Property::FLOAT, &Control::Impl::SetProperty, &Control::Impl::GetProperty); +const AnimatablePropertyRegistration Control::Impl::ANIMATABLE_PROPERTY_5(typeRegistration, "viewBorderlineColor", Toolkit::DevelControl::Property::BORDERLINE_COLOR, Property::VECTOR4, &Control::Impl::SetProperty, &Control::Impl::GetProperty); +const AnimatablePropertyRegistration Control::Impl::ANIMATABLE_PROPERTY_6(typeRegistration, "viewBorderlineOffset", Toolkit::DevelControl::Property::BORDERLINE_OFFSET, Property::FLOAT, &Control::Impl::SetProperty, &Control::Impl::GetProperty); // clang-format on @@ -396,9 +406,6 @@ Control::Impl::Impl(Control& controlImpl) mCounterClockwiseFocusableActorId(-1), mStyleName(""), mBackgroundColor(Color::TRANSPARENT), - mCornerRadius(Vector4::ZERO), - mCornerRadiusPolicy(Toolkit::Visual::Transform::Policy::Type::ABSOLUTE), - mCornerSquareness(Vector4::ZERO), mRenderEffect(nullptr), mStartingPinchScale(nullptr), mMargin(0, 0, 0, 0), @@ -412,6 +419,7 @@ Control::Impl::Impl(Control& controlImpl) mPanGestureDetector(), mTapGestureDetector(), mLongPressGestureDetector(), + mDecorationData{nullptr}, mOffScreenRenderingImpl(nullptr), mOffScreenRenderingType(DevelControl::OffScreenRenderingType::NONE), mTooltip(NULL), @@ -610,9 +618,9 @@ void Control::Impl::EnableCornerPropertiesOverridden(Toolkit::Visual::Base& visu if(DALI_LIKELY(mVisualData)) { Property::Map map; - map[Toolkit::DevelVisual::Property::CORNER_RADIUS] = mCornerRadius; - map[Toolkit::DevelVisual::Property::CORNER_RADIUS_POLICY] = mCornerRadiusPolicy; - map[Toolkit::DevelVisual::Property::CORNER_SQUARENESS] = mCornerSquareness; + map[Toolkit::DevelVisual::Property::CORNER_RADIUS] = DecorationData::GetCornerRadius(mDecorationData); + map[Toolkit::DevelVisual::Property::CORNER_RADIUS_POLICY] = DecorationData::GetCornerRadiusPolicy(mDecorationData); + map[Toolkit::DevelVisual::Property::CORNER_SQUARENESS] = DecorationData::GetCornerSquareness(mDecorationData); mVisualData->EnableCornerPropertiesOverridden(visual, enable, map); } @@ -1092,12 +1100,46 @@ void Control::Impl::SetProperty(BaseObject* object, Property::Index index, const break; } + case Toolkit::DevelControl::Property::INNER_SHADOW: + { + const Property::Map* map = value.GetMap(); + if(map && !map->Empty()) + { + controlImpl.mImpl->SetInnerShadow(*map); + } + else + { + // The shadow is an empty property map, so we should clear the inner shadow + controlImpl.mImpl->ClearInnerShadow(); + } + break; + } + + case Toolkit::DevelControl::Property::BORDERLINE: + { + const Property::Map* map = value.GetMap(); + if(map && !map->Empty()) + { + controlImpl.mImpl->SetBorderline(*map, true); + } + else + { + // The shadow is an empty property map, so we should clear the inner shadow + controlImpl.mImpl->ClearBorderline(); + } + break; + } + case Toolkit::DevelControl::Property::CORNER_RADIUS: { Vector4 radius; if(value.Get(radius)) { - controlImpl.mImpl->SetCornerRadius(radius, controlImpl.mImpl->mCornerRadiusPolicy, controlImpl.mImpl->mCornerSquareness); + if(DecorationData::GetCornerRadius(controlImpl.mImpl->mDecorationData) != radius) + { + DecorationData::SetCornerRadius(controlImpl.mImpl->mDecorationData, radius); + controlImpl.mImpl->UpdateCornerRadius(); + } } break; } @@ -1107,9 +1149,11 @@ void Control::Impl::SetProperty(BaseObject* object, Property::Index index, const int policy; if(value.Get(policy)) { - controlImpl.mImpl->SetCornerRadius(controlImpl.mImpl->mCornerRadius, - static_cast(policy), - controlImpl.mImpl->mCornerSquareness); + if(DecorationData::GetCornerRadiusPolicy(controlImpl.mImpl->mDecorationData) != policy) + { + DecorationData::SetCornerRadiusPolicy(controlImpl.mImpl->mDecorationData, policy); + controlImpl.mImpl->UpdateCornerRadius(); + } } break; } @@ -1119,7 +1163,53 @@ void Control::Impl::SetProperty(BaseObject* object, Property::Index index, const Vector4 squareness; if(value.Get(squareness)) { - controlImpl.mImpl->SetCornerRadius(controlImpl.mImpl->mCornerRadius, controlImpl.mImpl->mCornerRadiusPolicy, squareness); + if(DecorationData::GetCornerSquareness(controlImpl.mImpl->mDecorationData) != squareness) + { + DecorationData::SetCornerSquareness(controlImpl.mImpl->mDecorationData, squareness); + controlImpl.mImpl->UpdateCornerRadius(); + } + } + break; + } + + case Toolkit::DevelControl::Property::BORDERLINE_WIDTH: + { + float width; + if(value.Get(width)) + { + if(DecorationData::GetBorderlineWidth(controlImpl.mImpl->mDecorationData) != width) + { + DecorationData::SetBorderlineWidth(controlImpl.mImpl->mDecorationData, width); + controlImpl.mImpl->UpdateBorderline(); + } + } + break; + } + + case Toolkit::DevelControl::Property::BORDERLINE_COLOR: + { + Vector4 color; + if(value.Get(color)) + { + if(DecorationData::GetBorderlineColor(controlImpl.mImpl->mDecorationData) != color) + { + DecorationData::SetBorderlineColor(controlImpl.mImpl->mDecorationData, color); + controlImpl.mImpl->UpdateBorderline(); + } + } + break; + } + + case Toolkit::DevelControl::Property::BORDERLINE_OFFSET: + { + float offset; + if(value.Get(offset)) + { + if(DecorationData::GetBorderlineOffset(controlImpl.mImpl->mDecorationData) != offset) + { + DecorationData::SetBorderlineOffset(controlImpl.mImpl->mDecorationData, offset); + controlImpl.mImpl->UpdateBorderline(); + } } break; } @@ -1336,21 +1426,73 @@ Property::Value Control::Impl::GetProperty(BaseObject* object, Property::Index i break; } + case Toolkit::DevelControl::Property::INNER_SHADOW: + { + Property::Map map; + + if(DALI_LIKELY(controlImpl.mImpl->mVisualData)) + { + Toolkit::Visual::Base visual = controlImpl.mImpl->mVisualData->GetVisual(Toolkit::DevelControl::Property::INNER_SHADOW); + if(visual) + { + visual.CreatePropertyMap(map); + } + } + + value = map; + break; + } + + case Toolkit::DevelControl::Property::BORDERLINE: + { + Property::Map map; + + if(DALI_LIKELY(controlImpl.mImpl->mVisualData)) + { + Toolkit::Visual::Base visual = controlImpl.mImpl->mVisualData->GetVisual(Toolkit::DevelControl::Property::BORDERLINE); + if(visual) + { + visual.CreatePropertyMap(map); + } + } + + value = map; + break; + } + case Toolkit::DevelControl::Property::CORNER_RADIUS: { - value = controlImpl.mImpl->mCornerRadius; + value = DecorationData::GetCornerRadius(controlImpl.mImpl->mDecorationData); break; } case Toolkit::DevelControl::Property::CORNER_RADIUS_POLICY: { - value = static_cast(controlImpl.mImpl->mCornerRadiusPolicy); + value = DecorationData::GetCornerRadiusPolicy(controlImpl.mImpl->mDecorationData); break; } case Toolkit::DevelControl::Property::CORNER_SQUARENESS: { - value = controlImpl.mImpl->mCornerSquareness; + value = DecorationData::GetCornerSquareness(controlImpl.mImpl->mDecorationData); + break; + } + + case Toolkit::DevelControl::Property::BORDERLINE_WIDTH: + { + value = DecorationData::GetBorderlineWidth(controlImpl.mImpl->mDecorationData); + break; + } + + case Toolkit::DevelControl::Property::BORDERLINE_COLOR: + { + value = DecorationData::GetBorderlineColor(controlImpl.mImpl->mDecorationData); + break; + } + + case Toolkit::DevelControl::Property::BORDERLINE_OFFSET: + { + value = DecorationData::GetBorderlineOffset(controlImpl.mImpl->mDecorationData); break; } } @@ -1591,6 +1733,71 @@ void Control::Impl::ClearShadow() } } +void Control::Impl::SetInnerShadow(const Property::Map& map) +{ + if(DALI_LIKELY(mVisualData)) + { + Toolkit::Visual::Base visual = Toolkit::VisualFactory::Get().CreateVisual(map); + visual.SetName("innerShadow"); + + if(visual) + { + mVisualData->RegisterVisual(Toolkit::DevelControl::Property::INNER_SHADOW, visual, INNER_SHADOW_DEPTH_INDEX); + EnableCornerPropertiesOverridden(visual, true); + + mControlImpl.RelayoutRequest(); + } + } +} + +void Control::Impl::ClearInnerShadow() +{ + if(DALI_LIKELY(mVisualData)) + { + mVisualData->UnregisterVisual(Toolkit::DevelControl::Property::INNER_SHADOW); + + // Trigger a size negotiation request that may be needed when unregistering a visual. + mControlImpl.RelayoutRequest(); + } +} + +void Control::Impl::SetBorderline(const Property::Map& map, bool forciblyCreate) +{ + if(DALI_LIKELY(mVisualData)) + { + if(!forciblyCreate) + { + Toolkit::Internal::Visual::Base* previousVisualImplPtr = mVisualData->GetVisualImplPtr(Toolkit::DevelControl::Property::BORDERLINE); + if(previousVisualImplPtr) + { + previousVisualImplPtr->DoAction(Toolkit::DevelVisual::Action::UPDATE_PROPERTY, map); + return; + } + } + Toolkit::Visual::Base visual = Toolkit::VisualFactory::Get().CreateVisual(map); + visual.SetName("borderline"); + + if(visual) + { + mVisualData->RegisterVisual(Toolkit::DevelControl::Property::BORDERLINE, visual, BORDERLINE_DEPTH_INDEX); + EnableCornerPropertiesOverridden(visual, true); + + mControlImpl.RelayoutRequest(); + } + } +} + +void Control::Impl::ClearBorderline() +{ + if(DALI_LIKELY(mVisualData)) + { + mVisualData->UnregisterVisual(Toolkit::DevelControl::Property::BORDERLINE); + + // 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) { if(DALI_LIKELY(mVisualData)) @@ -1751,21 +1958,12 @@ void Control::Impl::SetOffScreenRendering(int32_t offScreenRenderingType) mOffScreenRenderingType = newType; } -void Control::Impl::SetCornerRadius(Vector4 radius, Toolkit::Visual::Transform::Policy::Type policy, Vector4 squareness) +void Control::Impl::UpdateCornerRadius() { - if(radius == mCornerRadius && policy == mCornerRadiusPolicy && squareness == mCornerSquareness) - { - return; - } - - mCornerRadius = radius; - mCornerRadiusPolicy = policy; - mCornerSquareness = squareness; - Property::Map map; - map[Toolkit::DevelVisual::Property::CORNER_RADIUS] = radius; - map[Toolkit::DevelVisual::Property::CORNER_RADIUS_POLICY] = policy; - map[Toolkit::DevelVisual::Property::CORNER_SQUARENESS] = squareness; + map[Toolkit::DevelVisual::Property::CORNER_RADIUS] = DecorationData::GetCornerRadius(mDecorationData); + map[Toolkit::DevelVisual::Property::CORNER_RADIUS_POLICY] = DecorationData::GetCornerRadiusPolicy(mDecorationData); + map[Toolkit::DevelVisual::Property::CORNER_SQUARENESS] = DecorationData::GetCornerSquareness(mDecorationData); RegisteredVisualContainer& visuals = mVisualData->mVisuals; for(auto it = visuals.begin(); it != visuals.end(); it++) @@ -1787,6 +1985,18 @@ void Control::Impl::SetCornerRadius(Vector4 radius, Toolkit::Visual::Transform:: } } +void Control::Impl::UpdateBorderline() +{ + Property::Map map; + map[Toolkit::Visual::Property::TYPE] = Toolkit::Visual::Type::COLOR; + map[Toolkit::ColorVisual::Property::MIX_COLOR] = Color::TRANSPARENT; + map[Toolkit::DevelVisual::Property::BORDERLINE_WIDTH] = DecorationData::GetBorderlineWidth(mDecorationData); + map[Toolkit::DevelVisual::Property::BORDERLINE_COLOR] = DecorationData::GetBorderlineColor(mDecorationData); + map[Toolkit::DevelVisual::Property::BORDERLINE_OFFSET] = DecorationData::GetBorderlineOffset(mDecorationData); + + SetBorderline(map, false); +} + void Control::Impl::Process(bool postProcessor) { if(DALI_LIKELY(mVisualData)) diff --git a/dali-toolkit/internal/controls/control/control-data-impl.h b/dali-toolkit/internal/controls/control/control-data-impl.h index a832860b2a..2ee794ea81 100644 --- a/dali-toolkit/internal/controls/control/control-data-impl.h +++ b/dali-toolkit/internal/controls/control/control-data-impl.h @@ -27,6 +27,7 @@ // INTERNAL INCLUDES #include +#include #include #include #include @@ -357,6 +358,29 @@ public: */ void ClearShadow(); + /** + * @brief Sets the inner shadow with a property map. + * @param[in] map The inner shadow property map + */ + void SetInnerShadow(const Property::Map& map); + + /** + * @brief Clear the inner shadow. + */ + void ClearInnerShadow(); + + /** + * @brief Sets the borderline with a property map. + * @param[in] map The borderline property map + * @param[in] forciblyCreate Create new visual forcibly, False if we only need to update properties. + */ + void SetBorderline(const Property::Map& map, bool forciblyCreate); + + /** + * @brief Clear the borderline. + */ + void ClearBorderline(); + /** * @copydoc DevelControl::GetVisualProperty() */ @@ -490,12 +514,14 @@ private: void SetOffScreenRendering(int32_t offScreenRenderingType); /** - * Set corner radius to this control. - * @param[in] radius Corner radius property value - * @param[in] policy Corner radius policy. Default value is ABSOLUTE. - * @param[in] squareness Corner squareness property value + * Notify to this control's corner radius changed. */ - void SetCornerRadius(Vector4 radius, Toolkit::Visual::Transform::Policy::Type policy, Vector4 squareness); + void UpdateCornerRadius(); + + /** + * Notify to this control's borderline changed. + */ + void UpdateBorderline(); public: Control& mControlImpl; @@ -514,9 +540,6 @@ public: std::string mStyleName; Vector4 mBackgroundColor; ///< The color of the background visual - Vector4 mCornerRadius; ///< The corner radius of this control - Toolkit::Visual::Transform::Policy::Type mCornerRadiusPolicy; ///< The corner radius policy of this control - Vector4 mCornerSquareness; ///< The corner squareness of this control RenderEffectImplPtr mRenderEffect; ///< The render effect on this control Vector3* mStartingPinchScale; ///< The scale when a pinch gesture starts, TODO: consider removing this Extents mMargin; ///< The margin values @@ -533,6 +556,9 @@ public: TapGestureDetector mTapGestureDetector; LongPressGestureDetector mLongPressGestureDetector; + // Decoration data (CornerRadius, Borderline) + DecorationData* mDecorationData; + // Off screen rendering context std::unique_ptr mOffScreenRenderingImpl; DevelControl::OffScreenRenderingType mOffScreenRenderingType; @@ -583,10 +609,15 @@ public: static const PropertyRegistration PROPERTY_29; static const PropertyRegistration PROPERTY_30; static const PropertyRegistration PROPERTY_31; + static const PropertyRegistration PROPERTY_32; + static const PropertyRegistration PROPERTY_33; static const AnimatablePropertyRegistration ANIMATABLE_PROPERTY_1; static const AnimatablePropertyRegistration ANIMATABLE_PROPERTY_2; static const AnimatablePropertyRegistration ANIMATABLE_PROPERTY_3; + static const AnimatablePropertyRegistration ANIMATABLE_PROPERTY_4; + static const AnimatablePropertyRegistration ANIMATABLE_PROPERTY_5; + static const AnimatablePropertyRegistration ANIMATABLE_PROPERTY_6; }; } // namespace Internal diff --git a/dali-toolkit/internal/controls/control/control-decoration-data.h b/dali-toolkit/internal/controls/control/control-decoration-data.h new file mode 100644 index 0000000000..88554b1632 --- /dev/null +++ b/dali-toolkit/internal/controls/control/control-decoration-data.h @@ -0,0 +1,119 @@ +#ifndef DALI_TOOLKIT_CONTROL_DECORATION_DATA_H +#define DALI_TOOLKIT_CONTROL_DECORATION_DATA_H + +/* + * Copyright (c) 2025 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 + +// INTERNAL INCLUDES +#include + +namespace Dali::Toolkit::Internal +{ +struct DecorationData +{ + // Default constructor + DecorationData() + : mBorderlineColor(Color::BLACK), + mCornerRadius(Vector4::ZERO), + mCornerSquareness(Vector4::ZERO), + mBorderlineWidth(0.0f), + mBorderlineOffset(0.0f), + mCornerRadiusPolicy(static_cast(Toolkit::Visual::Transform::Policy::ABSOLUTE)) + { + } + Vector4 mBorderlineColor; + Vector4 mCornerRadius; + Vector4 mCornerSquareness; + float mBorderlineWidth; + float mBorderlineOffset; + int mCornerRadiusPolicy; + + /** + * @brief Helper API to reduce duplicated codes. + * + * Keep these API as inline function due to the performance. + */ + static DecorationData* EnsureDecorationData(DecorationData*& data) + { + if(data == nullptr) + { + data = new DecorationData(); + } + return data; + } + + static float GetBorderlineWidth(const DecorationData* const data) + { + return data ? data->mBorderlineWidth : 0.0f; + } + static void SetBorderlineWidth(DecorationData*& data, float value) + { + EnsureDecorationData(data)->mBorderlineWidth = value; + } + + static Vector4 GetBorderlineColor(const DecorationData* const data) + { + return data ? data->mBorderlineColor : Color::BLACK; + } + static void SetBorderlineColor(DecorationData*& data, Vector4 value) + { + EnsureDecorationData(data)->mBorderlineColor = value; + } + + static float GetBorderlineOffset(const DecorationData* const data) + { + return data ? data->mBorderlineOffset : 0.0f; + } + static void SetBorderlineOffset(DecorationData*& data, float value) + { + EnsureDecorationData(data)->mBorderlineOffset = value; + } + + static Vector4 GetCornerRadius(const DecorationData* const data) + { + return data ? data->mCornerRadius : Vector4::ZERO; + } + static void SetCornerRadius(DecorationData*& data, Vector4 value) + { + EnsureDecorationData(data)->mCornerRadius = value; + } + + static int GetCornerRadiusPolicy(const DecorationData* const data) + { + return data ? data->mCornerRadiusPolicy : static_cast(Toolkit::Visual::Transform::Policy::ABSOLUTE); + } + static void SetCornerRadiusPolicy(DecorationData*& data, int value) + { + EnsureDecorationData(data)->mCornerRadiusPolicy = value; + } + + static Vector4 GetCornerSquareness(const DecorationData* const data) + { + return data ? data->mCornerSquareness : Vector4::ZERO; + } + static void SetCornerSquareness(DecorationData*& data, Vector4 value) + { + EnsureDecorationData(data)->mCornerSquareness = value; + } +}; + +} // namespace Dali::Toolkit::Internal + +#endif // DALI_TOOLKIT_CONTROL_DECORATION_DATA_H diff --git a/dali-toolkit/internal/visuals/visual-base-data-impl.h b/dali-toolkit/internal/visuals/visual-base-data-impl.h index 2e0edd602e..affff43aa9 100644 --- a/dali-toolkit/internal/visuals/visual-base-data-impl.h +++ b/dali-toolkit/internal/visuals/visual-base-data-impl.h @@ -24,6 +24,7 @@ // INTERNAL INCLUDES #include +#include #include #include #include @@ -114,26 +115,6 @@ struct Base::Impl Toolkit::Align::Type mAnchorPoint; }; - struct DecorationData - { - // Default constructor - DecorationData() - : mBorderlineColor(Color::BLACK), - mCornerRadius(Vector4::ZERO), - mCornerSquareness(Vector4::ZERO), - mBorderlineWidth(0.0f), - mBorderlineOffset(0.0f), - mCornerRadiusPolicy(static_cast(Toolkit::Visual::Transform::Policy::ABSOLUTE)) - { - } - Vector4 mBorderlineColor; - Vector4 mCornerRadius; - Vector4 mCornerSquareness; - float mBorderlineWidth; - float mBorderlineOffset; - int mCornerRadiusPolicy; - }; - /** * @brief Set the uniform properties onto the renderer. * And Register visual transform uniforms if neccessary. @@ -147,23 +128,14 @@ struct Base::Impl } } - DecorationData* EnsureDecorationData() - { - if(mDecorationData == nullptr) - { - mDecorationData = new DecorationData(); - } - return mDecorationData; - } - /** * @brief Get decoration data value : borderline width * * Keep these API as inline function due to the performance. */ - float GetBorderlineWidth() + float GetBorderlineWidth() const { - return mDecorationData ? mDecorationData->mBorderlineWidth : 0.0f; + return DecorationData::GetBorderlineWidth(mDecorationData); } /** @@ -173,7 +145,7 @@ struct Base::Impl */ void SetBorderlineWidth(float value) { - EnsureDecorationData()->mBorderlineWidth = value; + DecorationData::SetBorderlineWidth(mDecorationData, value); } /** @@ -181,9 +153,9 @@ struct Base::Impl * * Keep these API as inline function due to the performance. */ - Vector4 GetBorderlineColor() + Vector4 GetBorderlineColor() const { - return mDecorationData ? mDecorationData->mBorderlineColor : Color::BLACK; + return DecorationData::GetBorderlineColor(mDecorationData); } /** @@ -193,7 +165,7 @@ struct Base::Impl */ void SetBorderlineColor(Vector4 value) { - EnsureDecorationData()->mBorderlineColor = value; + DecorationData::SetBorderlineColor(mDecorationData, value); } /** @@ -201,9 +173,9 @@ struct Base::Impl * * Keep these API as inline function due to the performance. */ - float GetBorderlineOffset() + float GetBorderlineOffset() const { - return mDecorationData ? mDecorationData->mBorderlineOffset : 0.0f; + return DecorationData::GetBorderlineOffset(mDecorationData); } /** @@ -213,7 +185,7 @@ struct Base::Impl */ void SetBorderlineOffset(float value) { - EnsureDecorationData()->mBorderlineOffset = value; + DecorationData::SetBorderlineOffset(mDecorationData, value); } /** @@ -221,9 +193,9 @@ struct Base::Impl * * Keep these API as inline function due to the performance. */ - Vector4 GetCornerRadius() + Vector4 GetCornerRadius() const { - return mDecorationData ? mDecorationData->mCornerRadius : Vector4::ZERO; + return DecorationData::GetCornerRadius(mDecorationData); } /** @@ -233,7 +205,7 @@ struct Base::Impl */ void SetCornerRadius(Vector4 value) { - EnsureDecorationData()->mCornerRadius = value; + DecorationData::SetCornerRadius(mDecorationData, value); } /** @@ -241,9 +213,9 @@ struct Base::Impl * * Keep these API as inline function due to the performance. */ - int GetCornerRadiusPolicy() + int GetCornerRadiusPolicy() const { - return mDecorationData ? mDecorationData->mCornerRadiusPolicy : static_cast(Toolkit::Visual::Transform::Policy::ABSOLUTE); + return DecorationData::GetCornerRadiusPolicy(mDecorationData); } /** @@ -253,7 +225,7 @@ struct Base::Impl */ void SetCornerRadiusPolicy(int value) { - EnsureDecorationData()->mCornerRadiusPolicy = value; + DecorationData::SetCornerRadiusPolicy(mDecorationData, value); } /** @@ -261,9 +233,9 @@ struct Base::Impl * * Keep these API as inline function due to the performance. */ - Vector4 GetCornerSquareness() + Vector4 GetCornerSquareness() const { - return mDecorationData ? mDecorationData->mCornerSquareness : Vector4::ZERO; + return DecorationData::GetCornerSquareness(mDecorationData); } /** @@ -273,7 +245,7 @@ struct Base::Impl */ void SetCornerSquareness(Vector4 value) { - EnsureDecorationData()->mCornerSquareness = value; + DecorationData::SetCornerSquareness(mDecorationData, value); } VisualRenderer mRenderer;