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