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_RATING_RATING_MODIFIER_H
17 #define FOUNDATION_ACE_FRAMEWORKS_CORE_COMPONENTS_NG_PATTERN_RATING_RATING_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/rating/rating_theme.h"
23 #include "core/components_ng/base/modifier.h"
24 #include "core/components_ng/render/animation_utils.h"
25 #include "core/image/image_source_info.h"
26 #include "core/pipeline/pipeline_base.h"
27 
28 namespace OHOS::Ace::NG {
29 class RatingModifier : public ContentModifier {
30     DECLARE_ACE_TYPE(RatingModifier, ContentModifier);
31 
32 public:
33     RatingModifier();
34     ~RatingModifier() override = default;
35 
36     enum class RatingAnimationType {
37         NONE = 0,
38         HOVER,
39         HOVERTOPRESS,
40         PRESSTOHOVER,
41         PRESS,
42     };
43 
44     void PaintBoard(DrawingContext& context);
45     void PaintStar(DrawingContext& context);
46     void PaintReverseStar(DrawingContext& context);
47 
48     void onDraw(DrawingContext& context) override;
49 
UpdateCanvasImage(const RefPtr<CanvasImage> & foregroundImageCanvas,const RefPtr<CanvasImage> & secondaryImageCanvas,const RefPtr<CanvasImage> & backgroundImageCanvas,const ImagePaintConfig & foregroundConfig,const ImagePaintConfig & secondaryConfig,const ImagePaintConfig & backgroundConfig)50     void UpdateCanvasImage(const RefPtr<CanvasImage>& foregroundImageCanvas,
51         const RefPtr<CanvasImage>& secondaryImageCanvas, const RefPtr<CanvasImage>& backgroundImageCanvas,
52         const ImagePaintConfig& foregroundConfig, const ImagePaintConfig& secondaryConfig,
53         const ImagePaintConfig& backgroundConfig)
54     {
55         SetNeedDraw(true);
56         foregroundImageCanvas_ = foregroundImageCanvas;
57         secondaryImageCanvas_ = secondaryImageCanvas;
58         backgroundImageCanvas_ = backgroundImageCanvas;
59         foregroundImageCanvas_->SetPaintConfig(foregroundConfig);
60         secondaryImageCanvas_->SetPaintConfig(secondaryConfig);
61         backgroundImageCanvas_->SetPaintConfig(backgroundConfig);
62     }
63 
UpdateImageSourceInfo(const ImageSourceInfo & foreground,const ImageSourceInfo & secondary,const ImageSourceInfo & background)64     void UpdateImageSourceInfo(
65         const ImageSourceInfo& foreground, const ImageSourceInfo& secondary, const ImageSourceInfo& background)
66     {
67         foreground_ = foreground;
68         secondary_ = secondary;
69         background_ = background;
70     }
71 
JudgeImageSourceInfo(const ImageSourceInfo & foreground,const ImageSourceInfo & secondary,const ImageSourceInfo & background,const ImagePaintConfig & foregroundConfig)72     bool JudgeImageSourceInfo(const ImageSourceInfo& foreground, const ImageSourceInfo& secondary,
73         const ImageSourceInfo& background, const ImagePaintConfig& foregroundConfig)
74     {
75         if (foreground_ != foreground) {
76             return true;
77         }
78         if (secondary_ != secondary) {
79             return true;
80         }
81         if (background_ != background) {
82             return true;
83         }
84         CHECK_NULL_RETURN(foregroundImageCanvas_, true);
85         if (foregroundImageCanvas_->GetPaintConfig().dstRect_ != foregroundConfig.dstRect_) {
86             return true;
87         }
88         if (foregroundImageCanvas_->GetPaintConfig().scaleX_ != foregroundConfig.scaleX_ ||
89             foregroundImageCanvas_->GetPaintConfig().scaleY_ != foregroundConfig.scaleY_) {
90             return true;
91         }
92         // No need to update three CanvasImages
93         return false;
94     }
95 
SetNeedDraw(bool flag)96     void SetNeedDraw(bool flag)
97     {
98         if (needDraw_) {
99             needDraw_->Set(flag);
100         }
101     }
102 
SetBoardColor(LinearColor color,int32_t duratuion,const RefPtr<CubicCurve> & curve)103     void SetBoardColor(LinearColor color, int32_t duratuion, const RefPtr<CubicCurve>& curve)
104     {
105         if (boardColor_) {
106             AnimationOption option = AnimationOption();
107             option.SetDuration(duratuion);
108             option.SetCurve(curve);
109             AnimationUtils::Animate(option, [&]() { boardColor_->Set(color); });
110         }
111     }
112 
SetContentOffset(OffsetF contentOffset)113     void SetContentOffset(OffsetF contentOffset)
114     {
115         if (contentOffset_) {
116             contentOffset_->Set(contentOffset);
117         }
118     }
119 
SetContentSize(SizeF contentSize)120     void SetContentSize(SizeF contentSize)
121     {
122         if (contentSize_) {
123             contentSize_->Set(contentSize);
124         }
125     }
126 
SetDrawScore(double drawScore)127     void SetDrawScore(double drawScore)
128     {
129         if (drawScore_) {
130             drawScore_->Set(static_cast<float>(drawScore));
131         }
132     }
133 
SetStepSize(double stepSize)134     void SetStepSize(double stepSize)
135     {
136         if (stepSize_) {
137             stepSize_->Set(static_cast<float>(stepSize));
138         }
139     }
140 
SetTouchStar(int32_t touchStar)141     void SetTouchStar(int32_t touchStar)
142     {
143         if (touchStar < 0 || touchStar >= starNum_->Get() || touchStar_->Get() != touchStar) {
144             SetHoverState(RatingAnimationType::NONE);
145         }
146         if (touchStar_) {
147             touchStar_->Set(touchStar);
148         }
149     }
150 
SetStartNum(int32_t starNum)151     void SetStartNum(int32_t starNum)
152     {
153         if (starNum_) {
154             starNum_->Set(starNum);
155         }
156     }
157 
SetUseContentModifier(bool useContentModifier)158     void SetUseContentModifier(bool useContentModifier)
159     {
160         if (useContentModifier_) {
161             useContentModifier_->Set(useContentModifier);
162         }
163     }
164 
SetHoverState(const RatingAnimationType & state)165     void SetHoverState(const RatingAnimationType& state)
166     {
167         if (state_ == state) {
168             return;
169         }
170         state_ = state;
171         auto pipeline = PipelineBase::GetCurrentContext();
172         CHECK_NULL_VOID(pipeline);
173         auto ratingTheme = pipeline->GetTheme<RatingTheme>();
174         CHECK_NULL_VOID(ratingTheme);
175         auto hoverDuration = static_cast<int32_t>(ratingTheme->GetHoverAnimationDuration());
176         auto pressDuration = static_cast<int32_t>(ratingTheme->GetPressAnimationDuration());
177         switch (state) {
178             case RatingAnimationType::HOVER:
179                 SetBoardColor(LinearColor(ratingTheme->GetHoverColor()), hoverDuration, Curves::FRICTION);
180                 break;
181             case RatingAnimationType::HOVERTOPRESS:
182                 SetBoardColor(LinearColor(ratingTheme->GetPressColor()), pressDuration, Curves::SHARP);
183                 break;
184             case RatingAnimationType::PRESSTOHOVER:
185                 SetBoardColor(LinearColor(ratingTheme->GetHoverColor()), pressDuration, Curves::SHARP);
186                 break;
187             case RatingAnimationType::PRESS:
188                 SetBoardColor(LinearColor(ratingTheme->GetPressColor()), hoverDuration, Curves::SHARP);
189                 break;
190             case RatingAnimationType::NONE:
191                 SetBoardColor(LinearColor(Color::TRANSPARENT), hoverDuration, Curves::FRICTION);
192                 break;
193             default:
194                 break;
195         }
196     }
197 
SetReverse(bool reverse)198     void SetReverse(bool reverse)
199     {
200         if (reverse_) {
201             reverse_->Set(reverse);
202         }
203     }
204 
205 private:
206     // others
207     RatingAnimationType state_ = RatingAnimationType::NONE;
208     RefPtr<CanvasImage> foregroundImageCanvas_;
209     RefPtr<CanvasImage> secondaryImageCanvas_;
210     RefPtr<CanvasImage> backgroundImageCanvas_;
211     ImageSourceInfo foreground_;
212     ImageSourceInfo secondary_;
213     ImageSourceInfo background_;
214     // non-animatable property
215     RefPtr<PropertyBool> needDraw_;
216     RefPtr<PropertyInt> starNum_;
217     RefPtr<PropertyInt> touchStar_;
218     RefPtr<PropertyFloat> drawScore_;
219     RefPtr<PropertyFloat> stepSize_;
220     RefPtr<PropertyBool> useContentModifier_;
221     RefPtr<PropertyOffsetF> contentOffset_;
222     RefPtr<PropertySizeF> contentSize_;
223     // animatable property
224     RefPtr<AnimatablePropertyColor> boardColor_;
225     RefPtr<PropertyBool> reverse_;
226     ACE_DISALLOW_COPY_AND_MOVE(RatingModifier);
227 };
228 } // namespace OHOS::Ace::NG
229 #endif // FOUNDATION_ACE_FRAMEWORKS_CORE_COMPONENTS_NG_PATTERN_RATING_RATING_MODIFIER_H
230