• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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_SWITCH_SWITCH_MODIFIER_H
17 #define FOUNDATION_ACE_FRAMEWORKS_CORE_COMPONENTS_NG_PATTERNS_SWITCH_SWITCH_MODIFIER_H
18 
19 #include <algorithm>
20 #include <vector>
21 
22 #include "base/geometry/ng/offset_t.h"
23 #include "core/animation/spring_curve.h"
24 #include "core/common/container.h"
25 #include "core/components_ng/base/modifier.h"
26 #include "core/components_ng/pattern/radio/radio_modifier.h"
27 #include "core/components_ng/pattern/toggle/switch_paint_property.h"
28 #include "core/components_ng/property/property.h"
29 #include "core/components_ng/render/animation_utils.h"
30 #include "core/components_ng/render/canvas_image.h"
31 #include "core/components_ng/render/drawing_forward.h"
32 #include "core/components_ng/render/paint_wrapper.h"
33 namespace OHOS::Ace::NG {
34 class SwitchModifier : public ContentModifier {
35     DECLARE_ACE_TYPE(SwitchModifier, ContentModifier);
36 
37 public:
38     SwitchModifier(const SizeF& size, const OffsetF& offset, float pointOffset, bool isSelect,
39         const Color& boardColor, const Color& pointColor, float dragOffsetX);
40     ~SwitchModifier() override = default;
41 
onDraw(DrawingContext & context)42     void onDraw(DrawingContext& context) override
43     {
44         if (useContentModifier_->Get()) {
45             return;
46         }
47         RSCanvas& canvas = context.canvas;
48         PaintSwitch(canvas, offset_->Get(), size_->Get());
49     }
50 
UpdateAnimatableProperty()51     void UpdateAnimatableProperty()
52     {
53         SetSwitchBoardColor();
54         if (!actualSize_.IsPositive()) {
55             return;
56         }
57         bool isRtl = direction_ == TextDirection::AUTO ? AceApplicationInfo::GetInstance().IsRightToLeft()
58                                                        : direction_ == TextDirection::RTL;
59         auto offsetNotRtl = GreatOrEqual(actualSize_.Width(), actualSize_.Height())
60                                 ? (isSelect_->Get() ? actualSize_.Width() - actualSize_.Height() : 0.0f)
61                                 : (isSelect_->Get() ? actualSize_.Width() - actualTrackRadius_ : actualTrackRadius_);
62         auto offsetIsRtl = GreatOrEqual(actualSize_.Width(), actualSize_.Height())
63                                ? (isSelect_->Get() ? 0.0f : actualSize_.Width() - actualSize_.Height())
64                                : (isSelect_->Get() ? actualTrackRadius_ : actualSize_.Width() - actualTrackRadius_);
65         if (!isCancelAnimation_ || !isFocusOrBlur_) {
66             AnimationOption colorOption = AnimationOption();
67             colorOption.SetDuration(colorAnimationDuration_);
68             colorOption.SetCurve(Curves::FAST_OUT_SLOW_IN);
69             AnimationUtils::Animate(colorOption, [&]() {
70                 animatableBoardColor_->Set(isSelect_->Get() ?
71                     LinearColor(userActiveColor_) : LinearColor(inactiveColor_));
72             });
73         }
74         AnimationOption pointOption = AnimationOption();
75         pointOption.SetDuration(pointAnimationDuration_);
76         pointOption.SetCurve(Curves::FAST_OUT_SLOW_IN);
77         float newPointOffset = 0.0f;
78         if (!isDragEvent_) {
79             if (isRtl) {
80                 newPointOffset = offsetIsRtl;
81             } else {
82                 newPointOffset = offsetNotRtl;
83             }
84         } else {
85             if (GreatOrEqual(actualSize_.Width(), actualSize_.Height())) {
86                 newPointOffset = std::clamp(
87                     dragOffsetX_->Get() - offset_->Get().GetX(), 0.0f, actualSize_.Width() - actualSize_.Height());
88             } else {
89                 newPointOffset = std::clamp(dragOffsetX_->Get() - offset_->Get().GetX(), actualTrackRadius_,
90                     actualSize_.Width() - actualTrackRadius_);
91             }
92         }
93         AnimationUtils::Animate(pointOption, [&]() { pointOffset_->Set(newPointOffset); });
94     }
95 
SetSwitchBoardColor()96     void SetSwitchBoardColor()
97     {
98         switch (touchHoverType_) {
99             case TouchHoverAnimationType::HOVER:
100                 SetBoardColor(LinearColor(hoverColor_), hoverDuration_, Curves::FRICTION);
101                 break;
102             case TouchHoverAnimationType::PRESS_TO_HOVER:
103                 SetBoardColor(LinearColor(hoverColor_), hoverToTouchDuration_, Curves::SHARP);
104                 break;
105             case TouchHoverAnimationType::NONE:
106                 SetBoardColor(LinearColor(hoverColor_.BlendOpacity(0)), hoverDuration_, Curves::FRICTION);
107                 break;
108             case TouchHoverAnimationType::HOVER_TO_PRESS:
109                 SetBoardColor(LinearColor(clickEffectColor_), hoverToTouchDuration_, Curves::SHARP);
110                 break;
111             case TouchHoverAnimationType::PRESS:
112                 SetBoardColor(LinearColor(clickEffectColor_), hoverDuration_, Curves::FRICTION);
113                 break;
114             default:
115                 break;
116         }
117     }
118 
SetBoardColor(LinearColor color,int32_t duratuion,const RefPtr<CubicCurve> & curve)119     void SetBoardColor(LinearColor color, int32_t duratuion, const RefPtr<CubicCurve>& curve)
120     {
121         if (animateTouchHoverColor_) {
122             AnimationOption option = AnimationOption();
123             option.SetDuration(duratuion);
124             option.SetCurve(curve);
125             AnimationUtils::Animate(option, [&]() { animateTouchHoverColor_->Set(color); });
126         }
127     }
128 
SetBoardColor(Color color)129     void SetBoardColor(Color color)
130     {
131         if (animatableBoardColor_) {
132             animatableBoardColor_->Set(LinearColor(color));
133         }
134     }
135 
136     void InitializeParam(int32_t themeScopeId);
137     void PaintSwitch(RSCanvas& canvas, const OffsetF& contentOffset, const SizeF& contentSize);
138     float GetSwitchWidth(const SizeF& contentSize) const;
139     float CalcActualWidth(float width, float height, double actualGap, double defaultWidthGap);
140     void DrawFocusBoard(RSCanvas& canvas, const OffsetF& offset);
141     void DrawRectCircle(RSCanvas& canvas, const OffsetF& contentOffset,
142         const SizeF& contentSize, const double& actualGap);
143 
SetUserActiveColor(const Color & color)144     void SetUserActiveColor(const Color& color)
145     {
146         userActiveColor_ = color;
147         animatableBoardColor_->Set(isSelect_->Get() ? LinearColor(userActiveColor_) : LinearColor(inactiveColor_));
148     }
149 
SetPointColor(const Color & color)150     void SetPointColor(const Color& color)
151     {
152         hasPointColor_ = true;
153         animatePointColor_->Set(LinearColor(color));
154     }
155 
SetIsHover(bool isHover)156     void SetIsHover(bool isHover)
157     {
158         if (isHover_) {
159             isHover_->Set(isHover);
160         }
161     }
162 
SetIsSelect(bool isSelect)163     void SetIsSelect(bool isSelect)
164     {
165         if (isSelect_) {
166             isSelect_->Set(isSelect);
167         }
168     }
169 
SetIsFocused(bool isFocused)170     void SetIsFocused(bool isFocused)
171     {
172         if (isFocused_) {
173             isFocused_->Set(isFocused);
174         }
175     }
176 
SetIsOn(bool isOn)177     void SetIsOn(bool isOn)
178     {
179         if (isOn_) {
180             isOn_->Set(isOn);
181         }
182     }
183 
SetFocusPointColor(Color color)184     void SetFocusPointColor(Color color)
185     {
186         pointColor_ = color;
187     }
188 
SetHotZoneOffset(OffsetF & hotZoneOffset)189     void SetHotZoneOffset(OffsetF& hotZoneOffset)
190     {
191         hotZoneOffset_ = hotZoneOffset;
192     }
193 
SetHotZoneSize(SizeF & hotZoneSize)194     void SetHotZoneSize(SizeF& hotZoneSize)
195     {
196         hotZoneSize_ = hotZoneSize;
197     }
198 
SetOffset(OffsetF & offset)199     void SetOffset(OffsetF& offset)
200     {
201         if (offset_) {
202             offset_->Set(offset);
203         }
204     }
205 
SetUseContentModifier(bool useContentModifier)206     void SetUseContentModifier(bool useContentModifier)
207     {
208         if (useContentModifier_) {
209             useContentModifier_->Set(useContentModifier);
210         }
211     }
212 
SetSize(SizeF & size)213     void SetSize(SizeF& size)
214     {
215         actualSize_ = size;
216         if (size_) {
217             size_->Set(size);
218         }
219     }
220 
SetDragOffsetX(float dragOffsetX)221     void SetDragOffsetX(float dragOffsetX)
222     {
223         if (dragOffsetX_) {
224             dragOffsetX_->Set(dragOffsetX);
225         }
226     }
227 
SetPointOffset(float pointOffset)228     void SetPointOffset(float pointOffset)
229     {
230         if (pointOffset_) {
231             pointOffset_->Set(pointOffset);
232         }
233     }
234 
SetTouchHoverAnimationType(const TouchHoverAnimationType touchHoverType)235     void SetTouchHoverAnimationType(const TouchHoverAnimationType touchHoverType)
236     {
237         touchHoverType_ = touchHoverType;
238     }
239 
SetIsDragEvent(bool isDragEvent)240     void SetIsDragEvent(bool isDragEvent)
241     {
242         isDragEvent_ = isDragEvent;
243     }
244 
SetShowHoverEffect(bool showHoverEffect)245     void SetShowHoverEffect(bool showHoverEffect)
246     {
247         showHoverEffect_ = showHoverEffect;
248     }
249 
SetDirection(TextDirection direction)250     void SetDirection(TextDirection direction)
251     {
252         if (direction_ != direction) {
253             direction_ = direction;
254             isFirstCreated_ = true;
255         }
256     }
257 
SetPointRadius(float pointRadius)258     void SetPointRadius(float pointRadius)
259     {
260         animatePointRadius_->Set(pointRadius);
261     }
262 
GetPointRadius()263     float GetPointRadius()
264     {
265         return pointRadius_;
266     }
267 
SetInactiveColor(const Color & color)268     void SetInactiveColor(const Color& color)
269     {
270         inactiveColor_ = color;
271     }
272 
SetTrackRadius(float borderRadius)273     void SetTrackRadius(float borderRadius)
274     {
275         animateTrackRadius_->Set(borderRadius);
276     }
277 
GetTrackRadius()278     float GetTrackRadius()
279     {
280         return actualTrackRadius_;
281     }
282 
SetActualTrackRadius(float borderRadius)283     void SetActualTrackRadius(float borderRadius)
284     {
285         actualTrackRadius_ = borderRadius;
286     }
287 
SetIsFocusOrBlur(bool isFocusOrBlur)288     void SetIsFocusOrBlur(bool isFocusOrBlur)
289     {
290         isFocusOrBlur_ = isFocusOrBlur;
291     }
292 
293 private:
294     float actualWidth_ = 0.0f;
295     float actualHeight_ = 0.0f;
296     float pointRadius_ = 0.0f;
297     const Dimension radiusGap_ = 2.0_vp;
298     Color clickEffectColor_;
299     Color hoverColor_;
300     Color activeColor_;
301     Color inactiveColor_;
302     Color userActiveColor_;
303     Color pointColorUnchecked_;
304     Color pointColor_;
305     Color focusBoardColor_;
306     Dimension hoverRadius_ = 8.0_vp;
307     Dimension focusRadius_ = 8.0_vp;
308     bool isUseDiffPointColor_ = false;
309     bool isCancelAnimation_ = false;
310     float hoverDuration_ = 0.0f;
311     float hoverToTouchDuration_ = 0.0f;
312     float touchDuration_ = 0.0f;
313     float colorAnimationDuration_ = 0.0f;
314     float pointAnimationDuration_ = 0.0f;
315     bool isDragEvent_ = false;
316     bool isFirstCreated_ = true;
317     bool showHoverEffect_ = true;
318     bool isFocusOrBlur_ = false;
319     float actualTrackRadius_ = 0.0f;
320 
321     OffsetF hotZoneOffset_;
322     SizeF hotZoneSize_;
323     SizeF actualSize_;
324     TouchHoverAnimationType touchHoverType_ = TouchHoverAnimationType::NONE;
325     TextDirection direction_ = TextDirection::AUTO;
326 
327     RefPtr<AnimatablePropertyColor> animatableBoardColor_;
328     RefPtr<AnimatablePropertyColor> animateTouchHoverColor_;
329     RefPtr<AnimatablePropertyColor> animatePointColor_;
330     RefPtr<AnimatablePropertyFloat> pointOffset_;
331     RefPtr<PropertyFloat> dragOffsetX_;
332     RefPtr<PropertyBool> isSelect_;
333     RefPtr<PropertyBool> isHover_;
334     RefPtr<PropertyBool> isFocused_;
335     RefPtr<PropertyBool> isOn_;
336     bool hasPointColor_ = false;
337     RefPtr<AnimatablePropertyOffsetF> offset_;
338     RefPtr<AnimatablePropertySizeF> size_;
339     RefPtr<PropertyBool> useContentModifier_;
340     RefPtr<PropertyFloat> animatePointRadius_;
341     RefPtr<PropertyFloat> animateTrackRadius_;
342 
343     ACE_DISALLOW_COPY_AND_MOVE(SwitchModifier);
344 };
345 } // namespace OHOS::Ace::NG
346 
347 #endif // FOUNDATION_ACE_FRAMEWORKS_CORE_COMPONENTS_NG_PATTERNS_SWITCH_SWITCH_MODIFIER_H
348