• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2022-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_SWITCH_SWITCH_PAINT_METHOD_H
17 #define FOUNDATION_ACE_FRAMEWORKS_CORE_COMPONENTS_NG_PATTERN_SWITCH_SWITCH_PAINT_METHOD_H
18 
19 #include "core/components/checkable/checkable_theme.h"
20 #include "core/components_ng/pattern/toggle/switch_modifier.h"
21 #include "core/components_ng/pattern/toggle/switch_paint_property.h"
22 #include "core/components_ng/render/canvas_image.h"
23 #include "core/components_ng/render/node_paint_method.h"
24 #include "core/components_ng/render/paint_wrapper.h"
25 #include "core/components_ng/render/render_context.h"
26 #include "core/pipeline_ng/pipeline_context.h"
27 
28 namespace OHOS::Ace::NG {
29 namespace {
30 constexpr float SWITCH_ERROR_RADIUS = -1.0f;
31 constexpr double NUM_TWO = 2.0;
32 } // namespace
33 class ACE_EXPORT SwitchPaintMethod : public NodePaintMethod {
34     DECLARE_ACE_TYPE(SwitchPaintMethod, NodePaintMethod);
35 public:
36     SwitchPaintMethod() = default;
37 
38     ~SwitchPaintMethod() override = default;
39 
GetContentModifier(PaintWrapper * paintWrapper)40     RefPtr<Modifier> GetContentModifier(PaintWrapper* paintWrapper) override
41     {
42         if (!switchModifier_) {
43             auto paintProperty = DynamicCast<SwitchPaintProperty>(paintWrapper->GetPaintProperty());
44             CHECK_NULL_RETURN(paintProperty, nullptr);
45             auto size = paintWrapper->GetContentSize();
46             auto offset = paintWrapper->GetContentOffset();
47             bool isRtl = direction_ == TextDirection::AUTO ? AceApplicationInfo::GetInstance().IsRightToLeft()
48                                                            : direction_ == TextDirection::RTL;
49             auto pointOffset = isSelect_ ^ isRtl ? size.Width() - size.Height() : 0.0f;
50             auto renderContext = paintWrapper->GetRenderContext();
51             CHECK_NULL_RETURN(renderContext, nullptr);
52             auto host = renderContext->GetHost();
53             CHECK_NULL_RETURN(host, nullptr);
54             auto pipeline = host->GetContext();
55             CHECK_NULL_RETURN(pipeline, nullptr);
56             auto themeScopeId = GetThemeScopeId(paintWrapper);
57             auto switchTheme = pipeline->GetTheme<SwitchTheme>(themeScopeId);
58             CHECK_NULL_RETURN(switchTheme, nullptr);
59             auto boardColor = isSelect_ ? paintProperty->GetSelectedColorValue(switchTheme->GetActiveColor())
60                                         : switchTheme->GetInactivePointColor();
61             auto pointColor = paintProperty->GetSwitchPointColorValue(switchTheme->GetPointColor());
62             switchModifier_ = AceType::MakeRefPtr<SwitchModifier>(
63                 size, offset, pointOffset, isSelect_, boardColor, pointColor, dragOffsetX_);
64             switchModifier_->InitializeParam(themeScopeId);
65         }
66         return switchModifier_;
67     }
68 
UpdateBoundsRect(PaintWrapper * paintWrapper,float pointRadius,double actualTrackRadius)69     void UpdateBoundsRect(PaintWrapper* paintWrapper, float pointRadius, double actualTrackRadius)
70     {
71         CHECK_NULL_VOID(switchModifier_);
72         auto size = paintWrapper->GetContentSize();
73         auto offset = paintWrapper->GetContentOffset();
74         auto pipeline = PipelineBase::GetCurrentContext();
75         CHECK_NULL_VOID(pipeline);
76         auto switchTheme = pipeline->GetTheme<SwitchTheme>();
77         auto horizontalPadding = switchTheme->GetHotZoneHorizontalPadding().ConvertToPx();
78         auto verticalPadding = switchTheme->GetHotZoneVerticalPadding().ConvertToPx();
79         auto actualGap = radiusGap_.ConvertToPx() * size.Height() /
80                         (switchTheme->GetHeight().ConvertToPx() - verticalPadding * 2);
81         auto horizontalIncrement = 0.0;
82         auto verticalIncrement = 0.0;
83         auto actualPointRadius = pointRadius == SWITCH_ERROR_RADIUS ? size.Height() / NUM_TWO - actualGap : pointRadius;
84         if (GreatOrEqual(size.Width(), size.Height())) {
85             horizontalIncrement =
86                 (actualPointRadius * NUM_TWO > size.Height()) ? (actualPointRadius - size.Height() / NUM_TWO) : 0.0;
87             verticalIncrement =
88                 (actualPointRadius * NUM_TWO > size.Height()) ? (actualPointRadius - size.Height() / NUM_TWO) : 0.0;
89         } else {
90             horizontalIncrement =
91                 (actualPointRadius > actualTrackRadius) ? (actualPointRadius - actualTrackRadius) : 0.0;
92             verticalIncrement =
93                 (actualPointRadius * NUM_TWO > size.Height()) ? (actualPointRadius - size.Height() / NUM_TWO) : 0.0;
94         }
95         horizontalPadding += horizontalIncrement;
96         verticalPadding += verticalIncrement;
97         float boundsRectOriginX = offset.GetX() - horizontalPadding;
98         float boundsRectOriginY = offset.GetY() - verticalPadding;
99         float boundsRectWidth = size.Width() + 2 * horizontalPadding;
100         float boundsRectHeight = size.Height() + 2 * verticalPadding;
101         RectF boundsRect(boundsRectOriginX, boundsRectOriginY, boundsRectWidth, boundsRectHeight);
102         switchModifier_->SetBoundsRect(boundsRect);
103     }
104 
UpdateModifierColor(PaintWrapper * paintWrapper)105     void UpdateModifierColor(PaintWrapper* paintWrapper)
106     {
107         auto paintProperty = DynamicCast<SwitchPaintProperty>(paintWrapper->GetPaintProperty());
108         CHECK_NULL_VOID(paintProperty);
109         auto renderContext = paintWrapper->GetRenderContext();
110         CHECK_NULL_VOID(renderContext);
111         auto host = renderContext->GetHost();
112         CHECK_NULL_VOID(host);
113         auto pipeline = host->GetContext();
114         CHECK_NULL_VOID(pipeline);
115         auto switchTheme = pipeline->GetTheme<SwitchTheme>(GetThemeScopeId(paintWrapper));
116         CHECK_NULL_VOID(switchTheme);
117         if (paintProperty->HasUnselectedColor()) {
118             switchModifier_->SetInactiveColor(paintProperty->GetUnselectedColor().value());
119         }
120         if (paintProperty->HasSelectedColor()) {
121             switchModifier_->SetUserActiveColor(paintProperty->GetSelectedColor().value());
122         } else {
123             switchModifier_->SetUserActiveColor(switchTheme->GetActiveColor());
124         }
125         if (paintProperty->HasSwitchPointColor()) {
126             switchModifier_->SetPointColor(paintProperty->GetSwitchPointColor().value());
127         } else {
128             switchModifier_->SetPointColor(switchTheme->GetPointColor());
129         }
130     }
131 
UpdateContentModifier(PaintWrapper * paintWrapper)132     void UpdateContentModifier(PaintWrapper* paintWrapper) override
133     {
134         CHECK_NULL_VOID(switchModifier_);
135         switchModifier_->SetUseContentModifier(useContentModifier_);
136         UpdateModifierColor(paintWrapper);
137         auto paintProperty = DynamicCast<SwitchPaintProperty>(paintWrapper->GetPaintProperty());
138         CHECK_NULL_VOID(paintProperty);
139         auto pointRadius = SWITCH_ERROR_RADIUS;
140         if (paintProperty->HasPointRadius()) {
141             pointRadius = paintProperty->GetPointRadius().value().ConvertToPx();
142         }
143         switchModifier_->SetPointRadius(pointRadius);
144         auto trackRadius = SWITCH_ERROR_RADIUS;
145         if (paintProperty->HasTrackBorderRadius()) {
146             trackRadius = paintProperty->GetTrackBorderRadius().value().ConvertToPx();
147         }
148         switchModifier_->SetTrackRadius(trackRadius);
149         auto size = paintWrapper->GetContentSize();
150         auto offset = paintWrapper->GetContentOffset();
151         switchModifier_->SetSize(size);
152         switchModifier_->SetOffset(offset);
153         switchModifier_->SetIsSelect(isSelect_);
154         switchModifier_->SetDirection(direction_);
155         switchModifier_->SetTouchHoverAnimationType(touchHoverType_);
156         switchModifier_->SetDragOffsetX(dragOffsetX_);
157         switchModifier_->SetIsDragEvent(isDragEvent_);
158         switchModifier_->SetShowHoverEffect(showHoverEffect_);
159         auto actualTrackRadius = 0.0;
160         if (GreatOrEqual(trackRadius, 0.0) && LessOrEqual(trackRadius, std::min(size.Width(), size.Height()) / 2.0)) {
161             // 2.0f is used to calculate half of the width.
162             actualTrackRadius = trackRadius;
163         } else {
164             actualTrackRadius = size.Width() / 2.0; // 2.0f is used to calculate half of the width.
165         }
166         switchModifier_->SetActualTrackRadius(actualTrackRadius);
167         auto renderContext = paintWrapper->GetRenderContext();
168         CHECK_NULL_VOID(renderContext);
169         switchModifier_->UpdateAnimatableProperty(renderContext->GetHost());
170         UpdateBoundsRect(paintWrapper, pointRadius, actualTrackRadius);
171         paintWrapper->FlushContentModifier();
172     }
173 
SetHotZoneOffset(OffsetF & hotZoneOffset)174     void SetHotZoneOffset(OffsetF& hotZoneOffset)
175     {
176         hotZoneOffset_ = hotZoneOffset;
177     }
178 
SetHotZoneSize(SizeF & hotZoneSize)179     void SetHotZoneSize(SizeF& hotZoneSize)
180     {
181         hotZoneSize_ = hotZoneSize;
182     }
183 
SetHoverPercent(float hoverPercent)184     void SetHoverPercent(float hoverPercent)
185     {
186         hoverPercent_ = hoverPercent;
187     }
188 
SetDragOffsetX(float dragOffsetX)189     void SetDragOffsetX(float dragOffsetX)
190     {
191         dragOffsetX_ = dragOffsetX;
192     }
193 
SetIsSelect(bool isSelect)194     void SetIsSelect(bool isSelect)
195     {
196         isSelect_ = isSelect;
197     }
198 
SetIsHover(bool isHover)199     void SetIsHover(bool isHover)
200     {
201         isHover_ = isHover;
202     }
203 
SetTouchHoverAnimationType(const TouchHoverAnimationType touchHoverType)204     void SetTouchHoverAnimationType(const TouchHoverAnimationType touchHoverType)
205     {
206         touchHoverType_ = touchHoverType;
207     }
208 
SetIsDragEvent(bool isDragEvent)209     void SetIsDragEvent(bool isDragEvent)
210     {
211         isDragEvent_ = isDragEvent;
212     }
213 
SetShowHoverEffect(bool showHoverEffect)214     void SetShowHoverEffect(bool showHoverEffect)
215     {
216         showHoverEffect_ = showHoverEffect;
217     }
218 
SetDirection(TextDirection direction)219     void SetDirection(TextDirection direction)
220     {
221         direction_ = direction;
222     }
223 
SetUseContentModifier(bool useContentModifier)224     void SetUseContentModifier(bool useContentModifier)
225     {
226         useContentModifier_ = useContentModifier;
227     }
228 
GetSwitchModifier()229     RefPtr<SwitchModifier> GetSwitchModifier()
230     {
231         return switchModifier_;
232     }
233 
234 private:
235     float dragOffsetX_ = 0.0f;
236     float hoverPercent_ = 0.0f;
237     const Dimension radiusGap_ = 2.0_vp;
238     bool isSelect_ = true;
239     Color clickEffectColor_ = Color::WHITE;
240     Color hoverColor_ = Color::WHITE;
241     Color focusColor_ = Color::WHITE;
242     Dimension hoverRadius_ = 8.0_vp;
243     bool showHoverEffect_ = true;
244     bool useContentModifier_ = false;
245 
246     bool isHover_ = false;
247     OffsetF hotZoneOffset_;
248     SizeF hotZoneSize_;
249     TouchHoverAnimationType touchHoverType_ = TouchHoverAnimationType::NONE;
250     TextDirection direction_ = TextDirection::AUTO;
251     bool isDragEvent_ = false;
252 
253     RefPtr<SwitchModifier> switchModifier_;
254 
255     ACE_DISALLOW_COPY_AND_MOVE(SwitchPaintMethod);
256 
257     int32_t GetThemeScopeId(PaintWrapper* paintWrapper) const;
258 };
259 } // namespace OHOS::Ace::NG
260 
261 #endif // FOUNDATION_ACE_FRAMEWORKS_CORE_COMPONENTS_NG_PATTERN_SWITCH_SWITCH_PAINT_METHOD_H
262