1 /*
2 * Copyright (c) 2024 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 #include "core/components_ng/pattern/arc_scroll/inner/arc_scroll_bar_overlay_modifier.h"
16 #include "base/geometry/ng/offset_t.h"
17 #include "base/utils/utils.h"
18 #include "core/components_ng/base/modifier.h"
19 #include "core/components_ng/render/drawing.h"
20 #include "core/components_ng/render/drawing_prop_convertor.h"
21 #include "core/pipeline/pipeline_base.h"
22
23 namespace OHOS::Ace::NG {
24 namespace {
25 constexpr double FULL_ALPHA = 255.0;
26 constexpr int32_t BAR_GROW_DURATION = 150; // 150ms, scroll bar width expands from 4dp to 8dp
27 constexpr int32_t BAR_SHRINK_DURATION = 250; // 250ms, scroll bar width shrinks from 8dp to 4dp
28 } // namespace
29
ArcScrollBarOverlayModifier(const OffsetF & barOffset,const SizeF & barSize)30 ArcScrollBarOverlayModifier::ArcScrollBarOverlayModifier(
31 const OffsetF& barOffset, const SizeF& barSize) : ScrollBarOverlayModifier(barOffset, barSize)
32 {
33 strokeWidth_ = AceType::MakeRefPtr<AnimatablePropertyFloat>(0.0);
34 AttachProperty(strokeWidth_);
35 curveRadius_ = AceType::MakeRefPtr<AnimatablePropertyFloat>(0.0);
36 AttachProperty(curveRadius_);
37 curveCenter_ = AceType::MakeRefPtr<AnimatablePropertyOffsetF>(OffsetF());
38 AttachProperty(curveCenter_);
39 startAngle_ = AceType::MakeRefPtr<AnimatablePropertyFloat>(0.0);
40 AttachProperty(startAngle_);
41 sweepAngle_ = AceType::MakeRefPtr<AnimatablePropertyFloat>(0.0);
42 AttachProperty(sweepAngle_);
43 backgroundStartAngle_ = AceType::MakeRefPtr<AnimatablePropertyFloat>(0.0);
44 AttachProperty(backgroundStartAngle_);
45 backgroundSweepAngle_ = AceType::MakeRefPtr<AnimatablePropertyFloat>(0.0);
46 AttachProperty(backgroundSweepAngle_);
47 backgroundStrokeWidth_ = AceType::MakeRefPtr<AnimatablePropertyFloat>(0.0);
48 AttachProperty(backgroundStrokeWidth_);
49 backgroundCurveRadius_ = AceType::MakeRefPtr<AnimatablePropertyFloat>(0.0);
50 AttachProperty(backgroundCurveRadius_);
51 backgroundBarColor_ = AceType::MakeRefPtr<PropertyColor>(Color());
52 AttachProperty(backgroundBarColor_);
53 }
54
StartArcBarAnimation(HoverAnimationType hoverAnimationType,OpacityAnimationType opacityAnimationType,bool needAdaptAnimation,const ArcRound & arcBarRect,const ArcRound & backgroundArcBarRect)55 void ArcScrollBarOverlayModifier::StartArcBarAnimation(HoverAnimationType hoverAnimationType,
56 OpacityAnimationType opacityAnimationType, bool needAdaptAnimation, const ArcRound& arcBarRect,
57 const ArcRound& backgroundArcBarRect)
58 {
59 if (hoverAnimationType == HoverAnimationType::NONE && !needAdaptAnimation) {
60 SetArcRect(arcBarRect);
61 SetBackgroundArcRect(backgroundArcBarRect);
62 } else {
63 StartHoverAnimation(arcBarRect, backgroundArcBarRect, hoverAnimationType);
64 }
65 if (opacityAnimationType != OpacityAnimationType::NONE && GetScrollable()) {
66 StartOpacityAnimation(opacityAnimationType);
67 }
68 }
69
SetBackgroundArcRect(const ArcRound & backgroundArcBarRect)70 void ArcScrollBarOverlayModifier::SetBackgroundArcRect(const ArcRound& backgroundArcBarRect)
71 {
72 backgroundStrokeWidth_->Set(backgroundArcBarRect.GetWidth());
73 backgroundCurveRadius_->Set(backgroundArcBarRect.GetRadius());
74 backgroundStartAngle_->Set(backgroundArcBarRect.GetStartAngle());
75 backgroundSweepAngle_->Set(backgroundArcBarRect.GetSweepAngle());
76 }
77
SetArcRect(const ArcRound & arcBarRect)78 void ArcScrollBarOverlayModifier::SetArcRect(const ArcRound& arcBarRect)
79 {
80 strokeWidth_->Set(arcBarRect.GetWidth());
81 curveRadius_->Set(arcBarRect.GetRadius());
82 SetCurveCenter(arcBarRect.GetCenterPoint());
83 startAngle_->Set(arcBarRect.GetStartAngle());
84 sweepAngle_->Set(arcBarRect.GetSweepAngle());
85 }
86
SetBackgroundBarColor(Color backgroundBarColor)87 void ArcScrollBarOverlayModifier::SetBackgroundBarColor(Color backgroundBarColor)
88 {
89 CHECK_NULL_VOID(backgroundBarColor_);
90 backgroundBarColor_->Set(backgroundBarColor);
91 }
92
SetCurveCenter(Point curveCenter)93 void ArcScrollBarOverlayModifier::SetCurveCenter(Point curveCenter)
94 {
95 CHECK_NULL_VOID(curveCenter_);
96 float x = curveCenter.GetX();
97 float y = curveCenter.GetY();
98 OffsetF temp(x, y);
99 curveCenter_->Set(temp);
100 }
101
StartHoverAnimation(const ArcRound & arcBarRect,const ArcRound & backgroundArcBarRect,HoverAnimationType hoverAnimationType)102 void ArcScrollBarOverlayModifier::StartHoverAnimation(const ArcRound& arcBarRect,
103 const ArcRound& backgroundArcBarRect, HoverAnimationType hoverAnimationType)
104 {
105 if (hoverAnimationType == HoverAnimationType::NONE) {
106 SetArcRect(arcBarRect);
107 SetBackgroundArcRect(backgroundArcBarRect);
108 return;
109 }
110 if (hoverAnimationType != GetHoverAnimatingType()) {
111 StopHoverAnimation();
112 }
113
114 AnimationOption option;
115 option.SetCurve(Curves::SHARP);
116 if (hoverAnimationType == HoverAnimationType::GROW) {
117 option.SetDuration(BAR_GROW_DURATION);
118 } else if (hoverAnimationType == HoverAnimationType::SHRINK) {
119 option.SetDuration(BAR_SHRINK_DURATION);
120 }
121
122 SetHoverAnimatingType(hoverAnimationType);
123 hoverAnimation_ = AnimationUtils::StartAnimation(
124 option,
125 [&]() {
126 SetArcRect(arcBarRect);
127 SetBackgroundArcRect(backgroundArcBarRect);
128 },
129 [weak = WeakClaim(this)]() {
130 auto modifier = weak.Upgrade();
131 CHECK_NULL_VOID(modifier);
132 modifier->SetHoverAnimatingType(HoverAnimationType::NONE);
133 });
134 }
135
onDraw(DrawingContext & drawingContext)136 void ArcScrollBarOverlayModifier::onDraw(DrawingContext& drawingContext)
137 {
138 CHECK_NULL_VOID(strokeWidth_);
139 CHECK_NULL_VOID(curveCenter_);
140 CHECK_NULL_VOID(startAngle_);
141 CHECK_NULL_VOID(sweepAngle_);
142 CHECK_NULL_VOID(curveRadius_);
143
144 CHECK_NULL_VOID(backgroundStartAngle_);
145 CHECK_NULL_VOID(backgroundSweepAngle_);
146 CHECK_NULL_VOID(backgroundStrokeWidth_);
147 CHECK_NULL_VOID(backgroundCurveRadius_);
148 CHECK_NULL_VOID(backgroundBarColor_);
149 DrawBackgroundArc(drawingContext);
150 DrawArc(drawingContext);
151 }
152
DrawArc(DrawingContext & context)153 void ArcScrollBarOverlayModifier::DrawArc(DrawingContext& context)
154 {
155 auto pipeline = PipelineBase::GetCurrentContext();
156 CHECK_NULL_VOID(pipeline);
157 auto strokeWidth = strokeWidth_->Get();
158 auto& canvas = context.canvas;
159 RSPen pen;
160 pen.SetAntiAlias(true);
161 pen.SetWidth(strokeWidth);
162 pen.SetCapStyle(ToRSCapStyle(LineCap::ROUND));
163 auto barOpacity = GetOpacity() / FULL_ALPHA;
164 pen.SetColor(ToRSColor(GetBarColor()->Get().BlendOpacity(barOpacity)));
165 canvas.AttachPen(pen);
166 auto center = curveCenter_->Get();
167 auto radius = curveRadius_->Get();
168 auto startAngle = startAngle_->Get();
169 auto sweepAngle = sweepAngle_->Get();
170 canvas.DrawArc(
171 { center.GetX() - radius, center.GetY() - radius, center.GetX() + radius, center.GetY() + radius },
172 startAngle, sweepAngle);
173 canvas.DetachPen();
174 }
175
DrawBackgroundArc(DrawingContext & context)176 void ArcScrollBarOverlayModifier::DrawBackgroundArc(DrawingContext& context)
177 {
178 CHECK_NULL_VOID(backgroundBarColor_);
179 auto pipeline = PipelineBase::GetCurrentContext();
180 CHECK_NULL_VOID(pipeline);
181 auto& canvas = context.canvas;
182 auto strokeWidth = backgroundStrokeWidth_->Get();
183 RSPen pen;
184 pen.SetAntiAlias(true);
185 pen.SetWidth(strokeWidth);
186 pen.SetCapStyle(ToRSCapStyle(LineCap::ROUND));
187 auto barOpacity = GetOpacity() / FULL_ALPHA;
188 pen.SetColor(ToRSColor(backgroundBarColor_->Get().BlendOpacity(barOpacity)));
189
190 canvas.AttachPen(pen);
191 auto center = curveCenter_->Get();
192 auto radius = backgroundCurveRadius_->Get();
193 auto startAngle = backgroundStartAngle_->Get();
194 auto sweepAngle = backgroundSweepAngle_->Get();
195
196 canvas.DrawArc(
197 { center.GetX() - radius, center.GetY() - radius, center.GetX() + radius, center.GetY() + radius },
198 startAngle, sweepAngle);
199 canvas.DetachPen();
200 }
201 } // namespace OHOS::Ace::NG