• 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 #include "core/components_ng/pattern/checkboxgroup/checkboxgroup_modifier.h"
17 
18 #include "core/components_ng/render/drawing_prop_convertor.h"
19 
20 namespace OHOS::Ace::NG {
21 namespace {
22 constexpr uint8_t ENABLED_ALPHA = 255;
23 constexpr uint8_t DISABLED_ALPHA = 102;
24 constexpr float CHECK_MARK_START_X_POSITION = 0.25f;
25 constexpr float CHECK_MARK_START_Y_POSITION = 0.49f;
26 constexpr float CHECK_MARK_MIDDLE_X_POSITION = 0.44f;
27 constexpr float CHECK_MARK_MIDDLE_Y_POSITION = 0.68f;
28 constexpr float CHECK_MARK_END_X_POSITION = 0.76f;
29 constexpr float CHECK_MARK_END_Y_POSITION = 0.33f;
30 constexpr float CHECK_MARK_PART_START_X_POSITION = 0.20f;
31 constexpr float CHECK_MARK_PART_END_Y_POSITION = 0.80f;
32 constexpr float CHECK_MARK_PART_Y_POSITION = 0.50f;
33 constexpr float CHECKBOX_GROUP_DOUBLE_RATIO = 2.0f;
34 constexpr float CHECKBOX_GROUP_LENGTH_ZERO = 0.0f;
35 } // namespace
36 
CheckBoxGroupModifier(const Parameters & parameters)37 CheckBoxGroupModifier::CheckBoxGroupModifier(const Parameters& parameters)
38 {
39     activeColor_ = AceType::MakeRefPtr<AnimatablePropertyColor>(LinearColor(parameters.activeColor));
40     pointColor_ = AceType::MakeRefPtr<AnimatablePropertyColor>(LinearColor(parameters.pointColor));
41     inactiveColor_ = AceType::MakeRefPtr<AnimatablePropertyColor>(LinearColor(parameters.inactiveColor));
42     checkMarkPaintSize_ = AceType::MakeRefPtr<AnimatablePropertyFloat>(parameters.checkMarkPaintSize);
43     checkStroke_ = AceType::MakeRefPtr<AnimatablePropertyFloat>(parameters.checkStroke);
44     enabled_ = AceType::MakeRefPtr<PropertyBool>(true);
45     uiStatus_ = AceType::MakeRefPtr<PropertyInt>(static_cast<int>(parameters.uiStatus));
46     status_ = AceType::MakeRefPtr<PropertyInt>(static_cast<int>(UIStatus::UNSELECTED));
47     offset_ = AceType::MakeRefPtr<PropertyOffsetF>(OffsetF());
48     size_ = AceType::MakeRefPtr<PropertySizeF>(SizeF());
49     animateTouchHoverColor_ = AceType::MakeRefPtr<AnimatablePropertyColor>(LinearColor(Color::TRANSPARENT));
50     inactivePointColor_ = AceType::MakeRefPtr<PropertyColor>(parameters.inactivePointColor);
51 
52     borderWidth_ = parameters.borderWidth;
53     borderRadius_ = parameters.borderRadius;
54     shadowColor_ = parameters.shadowColor;
55     clickEffectColor_ = parameters.clickEffectColor;
56     hoverColor_ = parameters.hoverColor;
57     hoverRadius_ = parameters.hoverRadius;
58     hotZoneHorizontalPadding_ = parameters.hotZoneHorizontalPadding;
59     defaultPaddingSize_ = parameters.defaultPaddingSize;
60     hoverPaddingSize_ = parameters.hoverPaddingSize;
61     showCircleDial_ = parameters.showCircleDial;
62     hotZoneVerticalPadding_ = parameters.hotZoneVerticalPadding;
63     shadowWidth_ = parameters.shadowWidth;
64     hoverDuration_ = parameters.hoverDuration;
65     hoverToTouchDuration_ = parameters.hoverToTouchDuration;
66     checkBoxGroupShape_ = AceType::MakeRefPtr<PropertyInt>(static_cast<int32_t>(CheckBoxStyle::CIRCULAR_STYLE));
67     if (Container::GreatOrEqualAPITargetVersion(PlatformVersion::VERSION_TWELVE)) {
68         checkBoxGroupStyle_ = CheckBoxStyle::CIRCULAR_STYLE;
69     } else {
70         checkBoxGroupStyle_ = CheckBoxStyle::SQUARE_STYLE;
71     }
72     AttachProperty(activeColor_);
73     AttachProperty(pointColor_);
74     AttachProperty(inactiveColor_);
75     AttachProperty(inactivePointColor_);
76     AttachProperty(checkMarkPaintSize_);
77     AttachProperty(checkStroke_);
78     AttachProperty(enabled_);
79     AttachProperty(uiStatus_);
80     AttachProperty(status_);
81     AttachProperty(offset_);
82     AttachProperty(size_);
83     AttachProperty(animateTouchHoverColor_);
84     AttachProperty(checkBoxGroupShape_);
85 }
86 
PaintCheckBox(DrawingContext & context,const OffsetF & paintOffset,const SizeF & contentSize) const87 void CheckBoxGroupModifier::PaintCheckBox(
88     DrawingContext& context, const OffsetF& paintOffset, const SizeF& contentSize) const
89 {
90     auto& canvas = context.canvas;
91     auto color = activeColor_;
92 
93     RSPen pen;
94     RSBrush brush;
95     pen.SetWidth(borderWidth_);
96     pen.SetAntiAlias(true);
97     DrawTouchAndHoverBoard(canvas, contentSize, paintOffset);
98     RSPen shadowPen = RSPen(pen);
99     shadowPen.SetColor(ToRSColor(shadowColor_));
100     if (static_cast<CheckBoxGroupPaintProperty::SelectStatus>(status_->Get()) ==
101         CheckBoxGroupPaintProperty::SelectStatus::PART) {
102         PaintCheckBoxGroupPartStatus(canvas, paintOffset, brush, pen, contentSize);
103         return;
104     }
105     if (static_cast<UIStatus>(uiStatus_->Get()) == UIStatus::OFF_TO_ON ||
106         static_cast<UIStatus>(uiStatus_->Get()) == UIStatus::PART_TO_ON) {
107         brush.SetColor(ToRSColor(color->Get()));
108         brush.SetAntiAlias(true);
109         pen.SetColor(ToRSColor(pointColor_->Get()));
110         if (!enabled_->Get()) {
111             brush.SetColor(ToRSColor(color->Get().BlendOpacity(static_cast<float>(DISABLED_ALPHA) / ENABLED_ALPHA)));
112         }
113         DrawActiveBorder(canvas, paintOffset, brush, contentSize);
114         DrawCheck(canvas, paintOffset, pen, shadowPen, contentSize);
115     } else {
116         brush.SetColor(ToRSColor(inactivePointColor_->Get()));
117         pen.SetColor(ToRSColor(inactiveColor_->Get()));
118         if (!enabled_->Get()) {
119             brush.SetColor(
120                 ToRSColor(inactivePointColor_->Get().BlendOpacity(static_cast<float>(DISABLED_ALPHA) / ENABLED_ALPHA)));
121             pen.SetColor(
122                 ToRSColor(inactiveColor_->Get().BlendOpacity(static_cast<float>(DISABLED_ALPHA) / ENABLED_ALPHA)));
123         }
124         DrawUnselectedBorder(canvas, paintOffset, brush, contentSize);
125         DrawUnselected(canvas, paintOffset, pen, contentSize);
126     }
127 }
128 
PaintCheckBoxGroupPartStatus(RSCanvas & canvas,const OffsetF & paintOffset,RSBrush & brush,RSPen & pen,const SizeF & paintSize) const129 void CheckBoxGroupModifier::PaintCheckBoxGroupPartStatus(
130     RSCanvas& canvas, const OffsetF& paintOffset, RSBrush& brush, RSPen& pen, const SizeF& paintSize) const
131 {
132     auto color = activeColor_;
133     brush.SetColor(ToRSColor(color->Get()));
134     brush.SetAntiAlias(true);
135     pen.SetColor(ToRSColor(pointColor_->Get()));
136     if (!enabled_->Get()) {
137         brush.SetColor(ToRSColor(color->Get().BlendOpacity(static_cast<float>(DISABLED_ALPHA) / ENABLED_ALPHA)));
138     }
139     DrawActiveBorder(canvas, paintOffset, brush, paintSize);
140     DrawPart(canvas, paintOffset, pen, paintSize);
141 }
142 
DrawCheck(RSCanvas & canvas,const OffsetF & origin,RSPen & pen,RSPen & shadowPen,const SizeF & paintSize) const143 void CheckBoxGroupModifier::DrawCheck(
144     RSCanvas& canvas, const OffsetF& origin, RSPen& pen, RSPen& shadowPen, const SizeF& paintSize) const
145 {
146     if (checkMarkPaintSize_->Get() == CHECKBOX_GROUP_LENGTH_ZERO || checkStroke_->Get() == CHECKBOX_GROUP_LENGTH_ZERO) {
147         return;
148     }
149 #ifndef USE_ROSEN_DRAWING
150     RSPath path;
151 #else
152     RSRecordingPath path;
153 #endif
154     float originX = origin.GetX();
155     float originY = origin.GetY();
156     float strokeSize = checkMarkPaintSize_->Get();
157     const Offset start = Offset(strokeSize * CHECK_MARK_START_X_POSITION, strokeSize * CHECK_MARK_START_Y_POSITION);
158     const Offset middle = Offset(strokeSize * CHECK_MARK_MIDDLE_X_POSITION, strokeSize * CHECK_MARK_MIDDLE_Y_POSITION);
159     const Offset end = Offset(strokeSize * CHECK_MARK_END_X_POSITION, strokeSize * CHECK_MARK_END_Y_POSITION);
160     path.MoveTo(originX + start.GetX() + (paintSize.Width() - strokeSize) / CHECKBOX_GROUP_DOUBLE_RATIO,
161         originY + start.GetY() + (paintSize.Height() - strokeSize) / CHECKBOX_GROUP_DOUBLE_RATIO);
162     path.LineTo(originX + middle.GetX() + (paintSize.Width() - strokeSize) / CHECKBOX_GROUP_DOUBLE_RATIO,
163         originY + middle.GetY() + (paintSize.Height() - strokeSize) / CHECKBOX_GROUP_DOUBLE_RATIO);
164     path.MoveTo(originX + middle.GetX() + (paintSize.Width() - strokeSize) / CHECKBOX_GROUP_DOUBLE_RATIO,
165         originY + middle.GetY() + (paintSize.Height() - strokeSize) / CHECKBOX_GROUP_DOUBLE_RATIO);
166     path.LineTo(originX + end.GetX() + (paintSize.Width() - strokeSize) / CHECKBOX_GROUP_DOUBLE_RATIO,
167         originY + end.GetY() + (paintSize.Height() - strokeSize) / CHECKBOX_GROUP_DOUBLE_RATIO);
168     shadowPen.SetCapStyle(RSPen::CapStyle::ROUND_CAP);
169     shadowPen.SetWidth(checkStroke_->Get() + shadowWidth_.ConvertToPx() * CHECKBOX_GROUP_DOUBLE_RATIO);
170     pen.SetWidth(checkStroke_->Get());
171     pen.SetCapStyle(RSPen::CapStyle::ROUND_CAP);
172     canvas.AttachPen(shadowPen);
173     canvas.DrawPath(path);
174     canvas.AttachPen(pen);
175     canvas.DrawPath(path);
176 #ifdef USE_ROSEN_DRAWING
177     canvas.DetachPen();
178 #endif
179 }
180 
DrawUnselected(RSCanvas & canvas,const OffsetF & origin,RSPen & pen,const SizeF & paintSize) const181 void CheckBoxGroupModifier::DrawUnselected(
182     RSCanvas& canvas, const OffsetF& origin, RSPen& pen, const SizeF& paintSize) const
183 {
184     float originX = origin.GetX() + borderWidth_ / CHECKBOX_GROUP_DOUBLE_RATIO;
185     float originY = origin.GetY() + borderWidth_ / CHECKBOX_GROUP_DOUBLE_RATIO;
186     float endX = originX + paintSize.Width() - borderWidth_;
187     float endY = originY + paintSize.Height() - borderWidth_;
188     RSRect rect(originX, originY, endX, endY);
189     auto rrect = RSRoundRect(rect, borderRadius_, borderRadius_);
190     canvas.AttachPen(pen);
191     DrawRectOrCircle(canvas, rrect);
192 #ifdef USE_ROSEN_DRAWING
193     canvas.DetachPen();
194 #endif
195 }
196 
DrawActiveBorder(RSCanvas & canvas,const OffsetF & paintOffset,RSBrush & brush,const SizeF & paintSize) const197 void CheckBoxGroupModifier::DrawActiveBorder(
198     RSCanvas& canvas, const OffsetF& paintOffset, RSBrush& brush, const SizeF& paintSize) const
199 {
200     float originX = paintOffset.GetX();
201     float originY = paintOffset.GetY();
202     float endX = originX + paintSize.Width();
203     float endY = originY + paintSize.Height();
204     RSRect rect(originX, originY, endX, endY);
205     auto rrect = RSRoundRect(rect, borderRadius_, borderRadius_);
206     canvas.AttachBrush(brush);
207     DrawRectOrCircle(canvas, rrect);
208     canvas.DetachBrush();
209 }
210 
DrawUnselectedBorder(RSCanvas & canvas,const OffsetF & paintOffset,RSBrush & brush,const SizeF & paintSize) const211 void CheckBoxGroupModifier::DrawUnselectedBorder(
212     RSCanvas& canvas, const OffsetF& paintOffset, RSBrush& brush, const SizeF& paintSize) const
213 {
214     float originX = paintOffset.GetX() + borderWidth_;
215     float originY = paintOffset.GetY() + borderWidth_;
216     float endX = originX + paintSize.Width() - CHECKBOX_GROUP_DOUBLE_RATIO * borderWidth_;
217     float endY = originY + paintSize.Height() - CHECKBOX_GROUP_DOUBLE_RATIO * borderWidth_;
218     RSRect rect(originX, originY, endX, endY);
219     auto rrect = RSRoundRect(rect, borderRadius_, borderRadius_);
220     canvas.AttachBrush(brush);
221     DrawRectOrCircle(canvas, rrect);
222 #ifdef USE_ROSEN_DRAWING
223     canvas.DetachBrush();
224 #endif
225 }
226 
DrawPart(RSCanvas & canvas,const OffsetF & origin,RSPen & pen,const SizeF & paintSize) const227 void CheckBoxGroupModifier::DrawPart(RSCanvas& canvas, const OffsetF& origin, RSPen& pen, const SizeF& paintSize) const
228 {
229     if (checkMarkPaintSize_->Get() == CHECKBOX_GROUP_LENGTH_ZERO || checkStroke_->Get() == CHECKBOX_GROUP_LENGTH_ZERO) {
230         return;
231     }
232 #ifndef USE_ROSEN_DRAWING
233     RSPath path;
234 #else
235     RSRecordingPath path;
236 #endif
237     RSPen shadowPen;
238     float originX = origin.GetX();
239     float originY = origin.GetY();
240     const Offset start = Offset(checkMarkPaintSize_->Get() * CHECK_MARK_PART_START_X_POSITION,
241         checkMarkPaintSize_->Get() * CHECK_MARK_PART_Y_POSITION);
242     const Offset end = Offset(checkMarkPaintSize_->Get() * CHECK_MARK_PART_END_Y_POSITION,
243         checkMarkPaintSize_->Get() * CHECK_MARK_PART_Y_POSITION);
244     path.MoveTo(originX + start.GetX() + (paintSize.Width() - checkMarkPaintSize_->Get()) / CHECKBOX_GROUP_DOUBLE_RATIO,
245         originY + start.GetY() + (paintSize.Height() - checkMarkPaintSize_->Get()) / CHECKBOX_GROUP_DOUBLE_RATIO);
246     path.LineTo(originX + end.GetX() + (paintSize.Width() - checkMarkPaintSize_->Get()) / CHECKBOX_GROUP_DOUBLE_RATIO,
247         originY + end.GetY() + (paintSize.Height() - checkMarkPaintSize_->Get()) / CHECKBOX_GROUP_DOUBLE_RATIO);
248     shadowPen.SetColor(ToRSColor(shadowColor_));
249     shadowPen.SetCapStyle(RSPen::CapStyle::ROUND_CAP);
250     shadowPen.SetWidth(checkStroke_->Get() + shadowWidth_.ConvertToPx() * CHECKBOX_GROUP_DOUBLE_RATIO);
251     canvas.AttachPen(shadowPen);
252     canvas.DrawPath(path);
253     pen.SetWidth(checkStroke_->Get());
254     pen.SetCapStyle(RSPen::CapStyle::ROUND_CAP);
255     canvas.AttachPen(pen);
256     canvas.DrawPath(path);
257 #ifdef USE_ROSEN_DRAWING
258     canvas.DetachPen();
259 #endif
260 }
261 
DrawTouchAndHoverBoard(RSCanvas & canvas,const SizeF & size,const OffsetF & offset) const262 void CheckBoxGroupModifier::DrawTouchAndHoverBoard(RSCanvas& canvas, const SizeF& size, const OffsetF& offset) const
263 {
264     if (HoverEffectType::NONE == hoverEffectType_) {
265         return;
266     }
267     RSBrush brush;
268     brush.SetColor(ToRSColor(animateTouchHoverColor_->Get()));
269     brush.SetAntiAlias(true);
270     float originX;
271     float originY;
272     float endX;
273     float endY;
274     auto paddingPx = (showCircleDial_ ? hoverPaddingSize_.ConvertToPx() : defaultPaddingSize_.ConvertToPx());
275     if (Container::GreatOrEqualAPITargetVersion(PlatformVersion::VERSION_TWELVE)) {
276         originX = offset.GetX() - paddingPx;
277         originY = offset.GetY() - paddingPx;
278         endX = size.Width() + originX +
279             CHECKBOX_GROUP_DOUBLE_RATIO * paddingPx;
280         endY = size.Height() + originY +
281             CHECKBOX_GROUP_DOUBLE_RATIO * paddingPx;
282     } else {
283         originX = offset.GetX() - hotZoneHorizontalPadding_.ConvertToPx();
284         originY = offset.GetY() - hotZoneVerticalPadding_.ConvertToPx();
285         endX = size.Width() + originX + CHECKBOX_GROUP_DOUBLE_RATIO * hotZoneHorizontalPadding_.ConvertToPx();
286         endY = size.Height() + originY + CHECKBOX_GROUP_DOUBLE_RATIO * hotZoneVerticalPadding_.ConvertToPx();
287     }
288     auto rrect = RSRoundRect({ originX, originY, endX, endY }, hoverRadius_.ConvertToPx(), hoverRadius_.ConvertToPx());
289     canvas.AttachBrush(brush);
290     DrawRectOrCircle(canvas, rrect);
291 #ifdef USE_ROSEN_DRAWING
292     canvas.DetachBrush();
293 #endif
294 }
295 
DrawRectOrCircle(RSCanvas & canvas,const RSRoundRect & rrect) const296 void CheckBoxGroupModifier::DrawRectOrCircle(RSCanvas& canvas, const RSRoundRect& rrect) const
297 {
298     if (CheckBoxStyle::SQUARE_STYLE == checkBoxGroupStyle_) {
299         canvas.DrawRoundRect(rrect);
300     } else {
301         RSScalar halfDenominator = 2.0f;
302         RSRect rect = rrect.GetRect();
303         RSScalar x = (rect.GetLeft() + rect.GetRight()) / halfDenominator;
304         RSScalar y = (rect.GetTop() + rect.GetBottom()) / halfDenominator;
305         RSPoint centerPt(x, y);
306         RSScalar radius = std::min(rect.GetWidth(), rect.GetHeight()) / halfDenominator;
307         canvas.DrawCircle(centerPt, radius);
308     }
309 }
310 } // namespace OHOS::Ace::NG
311