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_PATTERNS_SWIPER_INDICATOR_SWIPER_INDICATOR_MODIFIER_H
17 #define FOUNDATION_ACE_FRAMEWORKS_CORE_COMPONENTS_NG_PATTERNS_SWIPER_INDICATOR_SWIPER_INDICATOR_MODIFIER_H
18 
19 #include <optional>
20 
21 #include "core/components/swiper/swiper_indicator_theme.h"
22 #include "core/components_ng/base/modifier.h"
23 #include "core/components_ng/render/animation_utils.h"
24 #include "core/components_ng/render/drawing_prop_convertor.h"
25 
26 namespace OHOS::Ace::NG {
27 constexpr int32_t ITEM_SIZE = 4;
28 constexpr float INIT_SIZE_RATE = 1.0f;
29 
30 enum class TouchBottomType {
31     NONE = 0,
32     START,
33     END,
34 };
35 
36 enum class TouchBottomAnimationStage {
37     STAGE_NONE,
38     STAGE_SHRINKT_TO_BLACK_POINT,
39     STAGE_EXPAND_TO_LONG_POINT,
40 };
41 
42 class DotIndicatorModifier : public ContentModifier {
43     DECLARE_ACE_TYPE(DotIndicatorModifier, ContentModifier);
44 public:
DotIndicatorModifier()45     DotIndicatorModifier()
46         : backgroundColor_(AceType::MakeRefPtr<AnimatablePropertyColor>(LinearColor::TRANSPARENT)),
47           vectorBlackPointCenterX_(AceType::MakeRefPtr<AnimatablePropertyVectorFloat>(LinearVector<float>(0))),
48           longPointLeftCenterX_(AceType::MakeRefPtr<AnimatablePropertyFloat>(0)),
49           longPointRightCenterX_(AceType::MakeRefPtr<AnimatablePropertyFloat>(0)),
50           normalToHoverPointDilateRatio_(AceType::MakeRefPtr<AnimatablePropertyFloat>(1)),
51           hoverToNormalPointDilateRatio_(AceType::MakeRefPtr<AnimatablePropertyFloat>(1)),
52           longPointDilateRatio_(AceType::MakeRefPtr<AnimatablePropertyFloat>(1)),
53           indicatorPadding_(AceType::MakeRefPtr<AnimatablePropertyFloat>(0)),
54           indicatorMargin_(AceType::MakeRefPtr<AnimatablePropertyOffsetF>(OffsetF(0, 0))),
55           itemHalfSizes_(AceType::MakeRefPtr<AnimatablePropertyVectorFloat>(LinearVector<float>(ITEM_SIZE))),
56           backgroundWidthDilateRatio_(AceType::MakeRefPtr<AnimatablePropertyFloat>(1)),
57           backgroundHeightDilateRatio_(AceType::MakeRefPtr<AnimatablePropertyFloat>(1)),
58           unselectedColor_(AceType::MakeRefPtr<PropertyColor>(Color::TRANSPARENT)),
59           selectedColor_(AceType::MakeRefPtr<AnimatablePropertyColor>(LinearColor::TRANSPARENT)),
60           touchBottomPointColor_(AceType::MakeRefPtr<AnimatablePropertyColor>(LinearColor::TRANSPARENT))
61     {
62         AttachProperty(vectorBlackPointCenterX_);
63         AttachProperty(longPointLeftCenterX_);
64         AttachProperty(longPointRightCenterX_);
65         AttachProperty(normalToHoverPointDilateRatio_);
66         AttachProperty(hoverToNormalPointDilateRatio_);
67         AttachProperty(longPointDilateRatio_);
68         AttachProperty(backgroundColor_);
69         AttachProperty(indicatorPadding_);
70         AttachProperty(indicatorMargin_);
71         AttachProperty(itemHalfSizes_);
72         AttachProperty(unselectedColor_);
73         AttachProperty(selectedColor_);
74         AttachProperty(backgroundWidthDilateRatio_);
75         AttachProperty(backgroundHeightDilateRatio_);
76         AttachProperty(touchBottomPointColor_);
77     }
78     ~DotIndicatorModifier() override = default;
79 
80     struct ContentProperty {
81         Color backgroundColor = Color::TRANSPARENT;
82         LinearVector<float> vectorBlackPointCenterX;
83         LinearVector<float> unselectedIndicatorWidth;
84         LinearVector<float> unselectedIndicatorHeight;
85         LinearVector<float> itemHalfSizes = {};
86         float longPointLeftCenterX = 0;
87         float longPointRightCenterX = 0;
88         float normalToHoverPointDilateRatio = 1;
89         float hoverToNormalPointDilateRatio = 1;
90         float longPointDilateRatio = 0;
91         float indicatorPadding = 0;
92         OffsetF indicatorMargin = { 0, 0 };
93         float theFirstPointMove = 0;
94         float theSecondPointMove = 0;
95         float theThirdPointMove = 0;
96         float fourthPointMove = 0;
97         float fifthPointMove = 0;
98         float sixthPointMove = 0;
99         float seventhPointMove = 0;
100         float eighthPointMove = 0;
101         float ninthPointMove = 0;
102         float newPointMove = 0;
103         float leftSecondPointSizeRate = INIT_SIZE_RATE;
104         float leftThirdPointSizeRate = INIT_SIZE_RATE;
105         float rightSecondPointSizeRate = INIT_SIZE_RATE;
106         float rightFirstPointSizeRate = INIT_SIZE_RATE;
107         uint8_t firstPointOpacity = 0;
108         uint8_t newPointOpacity = 0;
109     };
110 
111     void onDraw(DrawingContext& context) override;
112     // paint
113     virtual void PaintContent(DrawingContext& context, ContentProperty& contentProperty);
114     void PaintUnselectedIndicator(RSCanvas& canvas, const OffsetF& center,
115         const LinearVector<float>& itemHalfSizes,
116         bool currentIndexFlag, const LinearColor& indicatorColor);
117     void PaintSelectedIndicator(RSCanvas& canvas, const OffsetF& leftCenter,
118         const OffsetF& rightCenter, const LinearVector<float>& itemHalfSizes);
119     void PaintMask(DrawingContext& context);
120     void PaintBackground(DrawingContext& context, const ContentProperty& contentProperty);
121     virtual LinearVector<float> GetItemHalfSizes(size_t index, ContentProperty& contentProperty);
122     // Update property
123     void UpdateShrinkPaintProperty(const OffsetF& margin, const LinearVector<float>& normalItemHalfSizes,
124         const LinearVector<float>& vectorBlackPointCenterX, const std::pair<float, float>& longPointCenterX);
125     void UpdateDilatePaintProperty(const LinearVector<float>& hoverItemHalfSizes,
126         const LinearVector<float>& vectorBlackPointCenterX, const std::pair<float, float>& longPointCenterX);
127     void UpdateBackgroundColor(const Color& backgroundColor);
128 
129     void UpdateNormalPaintProperty(const OffsetF& margin, const LinearVector<float>& normalItemHalfSizes,
130         const LinearVector<float>& vectorBlackPointCenterX, const std::pair<float, float>& longPointCenterX);
131     void UpdateHoverPaintProperty(const LinearVector<float>& hoverItemHalfSizes,
132         const LinearVector<float>& vectorBlackPointCenterX, const std::pair<float, float>& longPointCenterX);
133     void UpdatePressPaintProperty(const LinearVector<float>& hoverItemHalfSizes,
134         const LinearVector<float>& vectorBlackPointCenterX, const std::pair<float, float>& longPointCenterX);
135     // Update
136     void UpdateNormalToHoverPaintProperty(const LinearVector<float>& hoverItemHalfSizes,
137         const LinearVector<float>& vectorBlackPointCenterX, const std::pair<float, float>& longPointCenterX);
138     void UpdateHoverToNormalPaintProperty(const OffsetF& margin, const LinearVector<float>& normalItemHalfSizes,
139         const LinearVector<float>& vectorBlackPointCenterX, const std::pair<float, float>& longPointCenterX);
140     void UpdateNormalToPressPaintProperty(const LinearVector<float>& hoverItemHalfSizes,
141         const LinearVector<float>& vectorBlackPointCenterX, const std::pair<float, float>& longPointCenterX);
142     void UpdatePressToNormalPaintProperty(const OffsetF& margin, const LinearVector<float>& normalItemHalfSizes,
143         const LinearVector<float>& vectorBlackPointCenterX, const std::pair<float, float>& longPointCenterX);
144     void UpdateHoverAndPressConversionPaintProperty();
145 
146     // Point dilate ratio
147     void UpdateNormalToHoverPointDilateRatio();
148     void UpdateHoverToNormalPointDilateRatio();
149     void UpdateLongPointDilateRatio();
150 
151     void UpdateAllPointCenterXAnimation(GestureState gestureState, const LinearVector<float>& vectorBlackPointCenterX,
152         const std::pair<float, float>& longPointCenterX);
153 
154     // Touch bottom animation
155     void UpdateTouchBottomAnimation(TouchBottomType touchBottomType, const LinearVector<float>& vectorBlackPointCenterX,
156         const std::pair<float, float>& longPointCenterX, float touchBottomRate);
157 
SetAxis(Axis axis)158     void SetAxis(Axis axis)
159     {
160         axis_ = axis;
161     }
162 
SetUnselectedColor(const Color & unselectedColor)163     void SetUnselectedColor(const Color& unselectedColor)
164     {
165         if (unselectedColor_) {
166             unselectedColor_->Set(unselectedColor);
167         }
168     }
169 
SetSelectedColor(const Color & selectedColor)170     void SetSelectedColor(const Color& selectedColor)
171     {
172         if (selectedColor_ && isSelectedColorAnimEnd_) {
173             selectedColor_->Set(LinearColor(selectedColor));
174         }
175         if (touchBottomPointColor_ && isSelectedColorAnimEnd_) {
176             touchBottomPointColor_->Set(LinearColor(selectedColor));
177         }
178     }
179 
SetCurrentIndex(int32_t index)180     void SetCurrentIndex(int32_t index)
181     {
182         currentIndex_ = index;
183     }
184 
SetNormalToHoverIndex(const std::optional<int32_t> & normalToHoverIndex)185     void SetNormalToHoverIndex(const std::optional<int32_t>& normalToHoverIndex)
186     {
187         normalToHoverIndex_ = normalToHoverIndex;
188     }
189 
SetHoverToNormalIndex(const std::optional<int32_t> & hoverToNormalIndex)190     void SetHoverToNormalIndex(const std::optional<int32_t>& hoverToNormalIndex)
191     {
192         hoverToNormalIndex_ = hoverToNormalIndex;
193     }
194 
GetNormalToHoverIndex()195     std::optional<int32_t> GetNormalToHoverIndex()
196     {
197         return normalToHoverIndex_;
198     }
199 
GetHoverToNormalIndex()200     std::optional<int32_t> GetHoverToNormalIndex()
201     {
202         return hoverToNormalIndex_;
203     }
204 
SetIndicatorMask(bool indicatorMask)205     void SetIndicatorMask(bool indicatorMask)
206     {
207         indicatorMask_ = indicatorMask;
208     }
209 
SetOffset(const OffsetF & offset)210     void SetOffset(const OffsetF& offset)
211     {
212         offset_ = offset;
213     }
214 
SetCenterY(const float & centerY)215     void SetCenterY(const float& centerY)
216     {
217         centerY_ = centerY;
218     }
219 
SetIsHover(bool isHover)220     void SetIsHover(bool isHover)
221     {
222         isHover_ = isHover;
223     }
224 
GetIsHover()225     bool GetIsHover() const
226     {
227         return isHover_;
228     }
229 
SetIsPressed(bool isPressed)230     void SetIsPressed(bool isPressed)
231     {
232         isPressed_ = isPressed;
233     }
234 
GetIsPressed()235     bool GetIsPressed() const
236     {
237         return isPressed_;
238     }
239 
SetLongPointIsHover(bool isHover)240     void SetLongPointIsHover(bool isHover)
241     {
242         longPointIsHover_ = isHover;
243     }
244 
GetLongPointIsHover()245     bool GetLongPointIsHover() const
246     {
247         return longPointIsHover_;
248     }
249 
SetItemWidth(const float itemWidth)250     void SetItemWidth(const float itemWidth)
251     {
252         itemWidth_ = itemWidth;
253     }
254 
SetItemHeight(const float itemHeight)255     void SetItemHeight(const float itemHeight)
256     {
257         itemHeight_ = itemHeight;
258     }
259 
SetSelectedItemWidth(const float selectedItemWidth)260     void SetSelectedItemWidth(const float selectedItemWidth)
261     {
262         selectedItemWidth_ = selectedItemWidth;
263     }
264 
SetSelectedItemHeight(const float selectedItemHeight)265     void SetSelectedItemHeight(const float selectedItemHeight)
266     {
267         selectedItemHeight_ = selectedItemHeight;
268     }
269 
SetIsIndicatorCustomSize(bool isCustomSize)270     void SetIsIndicatorCustomSize(bool isCustomSize)
271     {
272         isCustomSize_ = isCustomSize;
273     }
274 
SetAnimationDuration(int32_t duration)275     void SetAnimationDuration(int32_t duration)
276     {
277         animationDuration_ = duration;
278     }
279 
UpdateVectorBlackPointCenterX(const LinearVector<float> & value)280     inline void UpdateVectorBlackPointCenterX(const LinearVector<float>& value)
281     {
282         vectorBlackPointCenterX_->Set(value);
283     }
284 
GetLongPointCenterX()285     std::pair<float, float> GetLongPointCenterX()
286     {
287         return { longPointLeftCenterX_->Get(), longPointRightCenterX_->Get() };
288     }
289 
290     void PlayIndicatorAnimation(const LinearVector<float>& vectorBlackPointCenterX,
291         const std::vector<std::pair<float, float>>& longPointCenterX, GestureState gestureState,
292         TouchBottomTypeLoop touchBottomTypeLoop);
293     virtual void StopAnimation(bool ifImmediately = false);
SetLongPointHeadCurve(RefPtr<Curve> curve,float motionVelocity)294     void SetLongPointHeadCurve(RefPtr<Curve> curve, float motionVelocity)
295     {
296         headCurve_ = curve;
297         motionVelocity_ = motionVelocity;
298     }
299 
SetIsOverlong(bool isOverlong)300     void SetIsOverlong(bool isOverlong)
301     {
302         isOverlong_ = isOverlong;
303     }
304 
305 protected:
GetSwiperIndicatorTheme()306     static RefPtr<OHOS::Ace::SwiperIndicatorTheme> GetSwiperIndicatorTheme()
307     {
308         auto pipelineContext = PipelineBase::GetCurrentContext();
309         CHECK_NULL_RETURN(pipelineContext, nullptr);
310         auto swiperTheme = pipelineContext->GetTheme<SwiperIndicatorTheme>();
311         CHECK_NULL_RETURN(swiperTheme, nullptr);
312         return swiperTheme;
313     }
314 
315     void PlayBlackPointsAnimation(const LinearVector<float>& vectorBlackPointCenterX);
316     void PlayLongPointAnimation(const std::vector<std::pair<float, float>>& longPointCenterX, GestureState gestureState,
317         TouchBottomTypeLoop touchBottomTypeLoop, const LinearVector<float>& vectorBlackPointCenterX,
318         bool isNormal = true);
319     void PlayTouchBottomAnimation(const std::vector<std::pair<float, float>>& longPointCenterX,
320         TouchBottomTypeLoop touchBottomTypeLoop, const LinearVector<float>& vectorBlackPointCenterX);
321     void PlayOpacityAnimation();
322     std::pair<float, float> GetTouchBottomCenterX(ContentProperty& contentProperty);
323     int32_t GetLoopTranslateDuration() const;
324     int32_t GetLoopOpacityDuration() const;
325     float CalculateMinimumAmplitudeRatio(
326         const std::vector<std::pair<float, float>>& longPointCenterX, GestureState gestureState) const;
327 
328     RefPtr<AnimatablePropertyColor> backgroundColor_;
329     RefPtr<AnimatablePropertyVectorFloat> vectorBlackPointCenterX_;
330     RefPtr<AnimatablePropertyFloat> longPointLeftCenterX_;
331     RefPtr<AnimatablePropertyFloat> longPointRightCenterX_;
332     RefPtr<AnimatablePropertyFloat> normalToHoverPointDilateRatio_;
333     RefPtr<AnimatablePropertyFloat> hoverToNormalPointDilateRatio_;
334     RefPtr<AnimatablePropertyFloat> longPointDilateRatio_;
335     RefPtr<AnimatablePropertyFloat> indicatorPadding_;
336     RefPtr<AnimatablePropertyOffsetF> indicatorMargin_;
337     RefPtr<AnimatablePropertyVectorFloat> itemHalfSizes_;
338     RefPtr<AnimatablePropertyFloat> backgroundWidthDilateRatio_;
339     RefPtr<AnimatablePropertyFloat> backgroundHeightDilateRatio_;
340 
341     RefPtr<Curve> headCurve_;
342     float motionVelocity_ = 0;
343 
344     float centerY_ = 0;
345     Axis axis_ = Axis::HORIZONTAL;
346     RefPtr<PropertyColor> unselectedColor_;
347     RefPtr<AnimatablePropertyColor> selectedColor_;
348     bool isSelectedColorAnimEnd_ = true;
349     RefPtr<AnimatablePropertyColor> touchBottomPointColor_;
350     bool isTouchBottomLoop_ = false;
351     bool ifNeedFinishCallback_ = false;
352     TouchBottomAnimationStage animationState_ = TouchBottomAnimationStage::STAGE_NONE;
353     std::optional<int32_t> normalToHoverIndex_ = std::nullopt;
354     std::optional<int32_t> hoverToNormalIndex_ = std::nullopt;
355     bool longPointIsHover_ = false;
356     bool isHover_ = false;
357     bool isPressed_ = false;
358     bool longPointLeftAnimEnd_ = true;
359     bool longPointRightAnimEnd_ = true;
360 
361     bool indicatorMask_ = false;
362     bool isCustomSize_ = false;
363     int32_t currentIndex_ = 0;
364     int32_t animationDuration_ = 0;
365     OffsetF offset_;
366     float itemWidth_ = 0.0f;
367     float itemHeight_ = 0.0f;
368     float selectedItemWidth_ = 0.0f;
369     float selectedItemHeight_ = 0.0f;
370     TouchBottomType touchBottomType_ = TouchBottomType::NONE;
371     bool isOverlong_ = false;
372     ACE_DISALLOW_COPY_AND_MOVE(DotIndicatorModifier);
373 };
374 } // namespace OHOS::Ace::NG
375 
376 #endif // FOUNDATION_ACE_FRAMEWORKS_CORE_COMPONENTS_NG_PATTERNS_SWIPER_INDICATOR_SWIPER_INDICATOR_MODIFIER_H
377