1 /*
2  * Copyright (c) 2023 Huawei Device Co., Ltd.
3  * Licensed under the Apache License, Version 2.0 (the "License");
4  * you may not use this file except in compliance with the License.
5  * You may obtain a copy of the License at
6  *
7  *     http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software
10  * distributed under the License is distributed on an "AS IS" BASIS,
11  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12  * See the License for the specific language governing permissions and
13  * limitations under the License.
14  */
15 
16 #ifndef FOUNDATION_ACE_FRAMEWORKS_CORE_COMPONENTS_NG_PATTERN_SLIDER_SLIDER_CONTENT_MODIFIER_H
17 #define FOUNDATION_ACE_FRAMEWORKS_CORE_COMPONENTS_NG_PATTERN_SLIDER_SLIDER_CONTENT_MODIFIER_H
18 
19 #include "base/memory/referenced.h"
20 #include "base/utils/utils.h"
21 #include "core/components/common/properties/animation_option.h"
22 #include "core/components/slider/slider_theme.h"
23 #include "core/components_ng/base/modifier.h"
24 #include "core/components_ng/pattern/slider/slider_paint_property.h"
25 #include "core/components_ng/render/animation_utils.h"
26 #include "core/components_ng/render/drawing.h"
27 #include "core/pipeline/pipeline_base.h"
28 
29 namespace OHOS::Ace::NG {
30 enum class SliderStatus : uint32_t {
31     DEFAULT,
32     CLICK,
33     MOVE,
34 };
35 class SliderContentModifier : public ContentModifier {
36     DECLARE_ACE_TYPE(SliderContentModifier, ContentModifier);
37 
38 public:
39     struct Parameters {
40         float trackThickness = 0.0f;
41         SizeF blockSize;
42         float stepRatio = 0.0f;
43         float hotCircleShadowWidth = 0.0f;
44         bool mouseHoverFlag_ = false;
45         bool mousePressedFlag_ = false;
46         PointF selectStart;
47         PointF selectEnd;
48         PointF backStart;
49         PointF backEnd;
50         PointF circleCenter;
51         Color selectColor;
52         Gradient trackBackgroundColor;
53         Color blockColor;
54     };
55 
56     explicit SliderContentModifier(const Parameters& parameters, std::function<void(float)> updateImageCenterX,
57         std::function<void(float)> updateImageCenterY);
58     ~SliderContentModifier() override = default;
59 
60     void onDraw(DrawingContext& context) override;
61 
62     void DrawBackground(DrawingContext& context);
63     void DrawStep(DrawingContext& context);
64     void DrawSelect(DrawingContext& context);
65     void DrawDefaultBlock(DrawingContext& context);
66     void DrawHoverOrPress(DrawingContext& context);
67     void DrawShadow(DrawingContext& context);
68 
UpdateThemeColor()69     void UpdateThemeColor()
70     {
71         auto pipeline = PipelineBase::GetCurrentContext();
72         CHECK_NULL_VOID(pipeline);
73         auto sliderTheme = pipeline->GetTheme<SliderTheme>();
74         CHECK_NULL_VOID(sliderTheme);
75         blockOuterEdgeColor_ = sliderTheme->GetBlockOuterEdgeColor();
76         blockShadowColor_ = sliderTheme->GetBlockShadowColor();
77     }
78 
79     void UpdateData(const Parameters& parameters);
80     void JudgeNeedAnimate(bool reverse);
81 
SetTrackThickness(float trackThickness)82     void SetTrackThickness(float trackThickness)
83     {
84         if (trackThickness_) {
85             trackThickness_->Set(trackThickness);
86         }
87     }
88 
SetTrackBackgroundColor(const Gradient & color)89     void SetTrackBackgroundColor(const Gradient& color)
90     {
91         CHECK_NULL_VOID(trackBackgroundColor_);
92         trackBackgroundColor_->Set(GradientArithmetic(color));
93     }
94 
SetSelectColor(Color color)95     void SetSelectColor(Color color)
96     {
97         if (selectColor_) {
98             selectColor_->Set(LinearColor(color));
99         }
100     }
101 
SetBlockColor(Color color)102     void SetBlockColor(Color color)
103     {
104         if (blockColor_) {
105             blockColor_->Set(LinearColor(color));
106         }
107     }
108 
109     void SetBoardColor();
110 
SetBackgroundSize(const PointF & start,const PointF & end)111     void SetBackgroundSize(const PointF& start, const PointF& end)
112     {
113         if (backStart_) {
114             backStart_->Set(start - PointF());
115         }
116         if (backEnd_) {
117             backEnd_->Set(end - PointF());
118         }
119     }
120 
121     void SetSelectSize(const PointF& start, const PointF& end);
122 
123     void SetCircleCenter(const PointF& center);
124 
SetStepRatio(float stepRatio)125     void SetStepRatio(float stepRatio)
126     {
127         if (stepRatio_) {
128             stepRatio_->Set(stepRatio);
129         }
130     }
131 
SetAnimatorStatus(SliderStatus status)132     void SetAnimatorStatus(SliderStatus status)
133     {
134         animatorStatus_ = status;
135     }
136 
SetSliderMode(SliderModelNG::SliderMode sliderMode)137     void SetSliderMode(SliderModelNG::SliderMode sliderMode)
138     {
139         if (sliderMode_) {
140             sliderMode_->Set(static_cast<int>(sliderMode));
141         }
142     }
143 
SetTrackBorderRadius(float trackBorderRadius)144     void SetTrackBorderRadius(float trackBorderRadius)
145     {
146         if (trackBorderRadius_) {
147             trackBorderRadius_->Set(trackBorderRadius);
148         }
149     }
150 
SetSelectedBorderRadius(float selectedBorderRadius)151     void SetSelectedBorderRadius(float selectedBorderRadius)
152     {
153         if (selectedBorderRadius_) {
154             selectedBorderRadius_->Set(selectedBorderRadius);
155         }
156     }
157 
SetStepSize(float stepSize)158     void SetStepSize(float stepSize)
159     {
160         if (stepSize_) {
161             stepSize_->Set(stepSize);
162         }
163     }
164 
SetStepColor(const Color & stepColor)165     void SetStepColor(const Color& stepColor)
166     {
167         if (stepColor_) {
168             stepColor_->Set(LinearColor(stepColor));
169         }
170     }
171 
SetShowSteps(bool showSteps)172     void SetShowSteps(bool showSteps)
173     {
174         if (isShowStep_) {
175             isShowStep_->Set(showSteps);
176         }
177     }
178 
SetSliderInteractionMode(SliderModelNG::SliderInteraction mode)179     void SetSliderInteractionMode(SliderModelNG::SliderInteraction mode)
180     {
181         if (sliderInteractionMode_) {
182             sliderInteractionMode_->Set(static_cast<int>(mode));
183         }
184     }
185 
SetMinResponsiveDistance(float minResponse)186     void SetMinResponsiveDistance(float minResponse)
187     {
188         if (minResponse_) {
189             minResponse_->Set(minResponse);
190         }
191     }
192 
SetBlockType(SliderModelNG::BlockStyleType type)193     void SetBlockType(SliderModelNG::BlockStyleType type)
194     {
195         if (blockType_) {
196             blockType_->Set(static_cast<int>(type));
197         }
198     }
199 
SetBlockSize(const SizeF & blockSize)200     void SetBlockSize(const SizeF& blockSize)
201     {
202         if (blockSize_) {
203             blockSize_->Set(blockSize);
204         }
205     }
206 
SetBlockBorderColor(const Color & blockBorderColor)207     void SetBlockBorderColor(const Color& blockBorderColor)
208     {
209         if (blockBorderColor_) {
210             blockBorderColor_->Set(LinearColor(blockBorderColor));
211         }
212     }
213 
SetBlockBorderWidth(float blockBorderWidth)214     void SetBlockBorderWidth(float blockBorderWidth)
215     {
216         if (blockBorderWidth_) {
217             blockBorderWidth_->Set(blockBorderWidth);
218         }
219     }
220 
221     void SetBlockShape(const RefPtr<BasicShape>& shape);
222 
SetDirection(Axis axis)223     void SetDirection(Axis axis)
224     {
225         if (directionAxis_) {
226             directionAxis_->Set(static_cast<int>(axis));
227         }
228     }
229 
GetBlockCenter()230     PointF GetBlockCenter()
231     {
232         auto blockCenterX = blockCenterX_->Get();
233         auto blockCenterY = blockCenterY_->Get();
234         auto backStart = backStart_->Get();
235         auto backEnd = backEnd_->Get();
236         if (static_cast<Axis>(directionAxis_->Get()) == Axis::HORIZONTAL) {
237             blockCenterX = std::clamp(blockCenterX, backStart.GetX(), backEnd.GetX());
238         } else {
239             blockCenterY = std::clamp(blockCenterY, backStart.GetY(), backEnd.GetY());
240         }
241         return { blockCenterX, blockCenterY };
242     }
243 
GetTrackThickness()244     float GetTrackThickness() const
245     {
246         return trackThickness_->Get();
247     }
248 
GetBlockSize()249     SizeF GetBlockSize() const
250     {
251         return blockSize_->Get();
252     }
253 
SetVisible(bool isVisible)254     void SetVisible(bool isVisible)
255     {
256         CHECK_NULL_VOID(isVisible_ != isVisible);
257         isVisible_ = isVisible;
258     }
259 
GetVisible()260     bool GetVisible() const
261     {
262         return isVisible_;
263     }
264 
265     void UpdateContentDirtyRect(const SizeF& frameSize);
266 
SetUseContentModifier(bool useContentModifier)267     void SetUseContentModifier(bool useContentModifier)
268     {
269         if (useContentModifier_) {
270             useContentModifier_->Set(useContentModifier);
271         }
272     }
273 
GetStepPointVec()274     const std::vector<PointF>& GetStepPointVec() const
275     {
276         return stepPointVec_;
277     }
278 
279 private:
280     void InitializeShapeProperty();
281     RSRect GetTrackRect();
282     std::vector<GradientColor> GetTrackBackgroundColor() const;
283     Gradient SortGradientColorsByOffset(const Gradient& gradient) const;
284 
285     void DrawBlock(DrawingContext& context);
286     void DrawBlockShape(DrawingContext& context);
287     void DrawBlockShapeCircle(DrawingContext& context, RefPtr<Circle>& circle);
288     void DrawBlockShapeEllipse(DrawingContext& context, RefPtr<Ellipse>& ellipse);
289     void DrawBlockShapePath(DrawingContext& context, RefPtr<Path>& path);
290     void DrawBlockShapeRect(DrawingContext& context, RefPtr<ShapeRect>& rect);
291     void SetShapeRectRadius(RSRoundRect& roundRect, float borderWidth);
292     void SetBlockClip(DrawingContext& context);
293     void StopSelectAnimation();
294     void StopCircleCenterAnimation();
295 
296 private:
297     std::function<void(float)> updateImageCenterX_;
298     std::function<void(float)> updateImageCenterY_;
299 
300     // animatable property
301     RefPtr<AnimatablePropertyOffsetF> selectStart_;
302     RefPtr<AnimatablePropertyOffsetF> selectEnd_;
303     RefPtr<AnimatablePropertyOffsetF> backStart_;
304     RefPtr<AnimatablePropertyOffsetF> backEnd_;
305     RefPtr<AnimatablePropertyFloat> blockCenterX_;
306     RefPtr<AnimatablePropertyFloat> blockCenterY_;
307     RefPtr<AnimatablePropertyFloat> trackThickness_;
308     RefPtr<AnimatablePropertyVectorColor> trackBackgroundColor_;
309     RefPtr<AnimatablePropertyColor> selectColor_;
310     RefPtr<AnimatablePropertyColor> blockColor_;
311     RefPtr<AnimatablePropertyColor> boardColor_;
312 
313     RefPtr<AnimatablePropertyFloat> trackBorderRadius_;
314     RefPtr<AnimatablePropertyFloat> selectedBorderRadius_;
315     RefPtr<AnimatablePropertyFloat> stepSize_;
316     RefPtr<AnimatablePropertyColor> stepColor_;
317     RefPtr<AnimatablePropertySizeF> blockSize_;
318     RefPtr<AnimatablePropertyColor> blockBorderColor_;
319     RefPtr<AnimatablePropertyFloat> blockBorderWidth_;
320     RefPtr<AnimatablePropertyFloat> shapeWidth_;
321     RefPtr<AnimatablePropertyFloat> shapeHeight_;
322     RefPtr<AnimatablePropertyFloat> circleRadius_;
323     RefPtr<AnimatablePropertyFloat> ellipseRadiusX_;
324     RefPtr<AnimatablePropertyFloat> ellipseRadiusY_;
325     RefPtr<AnimatablePropertyFloat> rectTopLeftRadiusX_;
326     RefPtr<AnimatablePropertyFloat> rectTopLeftRadiusY_;
327     RefPtr<AnimatablePropertyFloat> rectTopRightRadiusX_;
328     RefPtr<AnimatablePropertyFloat> rectTopRightRadiusY_;
329     RefPtr<AnimatablePropertyFloat> rectBottomLeftRadiusX_;
330     RefPtr<AnimatablePropertyFloat> rectBottomLeftRadiusY_;
331     RefPtr<AnimatablePropertyFloat> rectBottomRightRadiusX_;
332     RefPtr<AnimatablePropertyFloat> rectBottomRightRadiusY_;
333     // non-animatable property
334     RefPtr<PropertyFloat> stepRatio_;
335     RefPtr<PropertyInt> sliderMode_;
336     RefPtr<PropertyInt> directionAxis_;
337     RefPtr<PropertyBool> isShowStep_;
338     RefPtr<PropertyInt> sliderInteractionMode_;
339     RefPtr<PropertyFloat> minResponse_;
340     RefPtr<PropertyInt> blockType_;
341     RefPtr<PropertyBool> useContentModifier_;
342 
343     // others
344     struct MarkerPenAndPath {
345         RSPen pen;
346         RSBrush brush;
347         RSPath path;
348     } markerPenAndPath;
349 
350     OffsetF targetSelectEnd_;
351     PointF targetCenter_;
352     bool isVisible_ = true;
353     bool mouseHoverFlag_ = false;
354     bool mousePressedFlag_ = false;
355     bool reverse_ = false;
356     SliderStatus animatorStatus_ = SliderStatus::DEFAULT; // Translate Animation on-off
357     float hotCircleShadowWidth_ = 0.0f;
358     Color blockOuterEdgeColor_;
359     Color blockShadowColor_;
360     RefPtr<BasicShape> shape_;
361     std::vector<PointF> stepPointVec_;
362     ACE_DISALLOW_COPY_AND_MOVE(SliderContentModifier);
363 };
364 
365 } // namespace OHOS::Ace::NG
366 #endif // FOUNDATION_ACE_FRAMEWORKS_CORE_COMPONENTS_NG_PATTERN_SLIDER_SLIDER_CONTENT_MODIFIER_H
367