• 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/scroll/inner/scroll_bar_overlay_modifier.h"
17 
18 #include "base/geometry/ng/offset_t.h"
19 #include "base/utils/utils.h"
20 #include "core/components_ng/base/modifier.h"
21 #include "core/components_ng/render/drawing.h"
22 #include "core/components_ng/render/drawing_prop_convertor.h"
23 
24 namespace OHOS::Ace::NG {
25 namespace {
26 constexpr double FULL_ALPHA = 255.0;
27 constexpr float HALF = 0.5f;
28 constexpr int32_t BAR_END_DURATION = 400;        // 400ms
29 constexpr int32_t BAR_APPEAR_DURATION = 100;     // 100ms
30 constexpr int32_t BAR_GROW_DURATION = 150;       // 150ms, scroll bar width expands from 4dp to 8dp
31 constexpr int32_t BAR_SHRINK_DURATION = 250;     // 250ms, scroll bar width shrinks from 8dp to 4dp
32 } // namespace
33 
ScrollBarOverlayModifier(const OffsetF & fgOffset,const OffsetF & bgOffset,const SizeF & fgSize,const SizeF & bgSize)34 ScrollBarOverlayModifier::ScrollBarOverlayModifier(
35     const OffsetF& fgOffset, const OffsetF& bgOffset, const SizeF& fgSize, const SizeF& bgSize)
36 {
37     fgOffset_ = AceType::MakeRefPtr<AnimatablePropertyOffsetF>(fgOffset);
38     AttachProperty(fgOffset_);
39     fgSize_ = AceType::MakeRefPtr<AnimatablePropertySizeF>(fgSize);
40     AttachProperty(fgSize_);
41     bgOffset_ = AceType::MakeRefPtr<AnimatablePropertyOffsetF>(bgOffset);
42     AttachProperty(bgOffset_);
43     bgSize_ = AceType::MakeRefPtr<AnimatablePropertySizeF>(bgSize);
44     AttachProperty(bgSize_);
45 
46     opacity_ = AceType::MakeRefPtr<AnimatablePropertyUint8>(UINT8_MAX);
47     AttachProperty(opacity_);
48     fgColor_ = AceType::MakeRefPtr<PropertyColor>(Color());
49     AttachProperty(fgColor_);
50     bgColor_ = AceType::MakeRefPtr<PropertyColor>(Color());
51     AttachProperty(bgColor_);
52 }
53 
onDraw(DrawingContext & drawingContext)54 void ScrollBarOverlayModifier::onDraw(DrawingContext& drawingContext)
55 {
56     CHECK_NULL_VOID_NOLOG(opacity_);
57     CHECK_NULL_VOID_NOLOG(fgOffset_);
58     CHECK_NULL_VOID_NOLOG(fgSize_);
59     CHECK_NULL_VOID_NOLOG(bgOffset_);
60     CHECK_NULL_VOID_NOLOG(bgSize_);
61     CHECK_NULL_VOID_NOLOG(fgColor_);
62     CHECK_NULL_VOID_NOLOG(bgColor_);
63 
64     auto fgSize = fgSize_->Get();
65     auto bgSize = bgSize_->Get();
66     auto fgOffset = fgOffset_->Get();
67     auto bgOffset = bgOffset_->Get();
68     if (!NearZero(fgSize.Height()) && !NearZero(bgSize.Height())) {
69         auto& canvas = drawingContext.canvas;
70         RSBrush brush;
71         brush.SetBlendMode(RSBlendMode::SRC_OVER);
72         brush.SetAntiAlias(true);
73         RSRect bgRect(
74             bgOffset.GetX(), bgOffset.GetY(), bgOffset.GetX() + bgSize.Width(), bgOffset.GetY() + bgSize.Height());
75         RSColor bgColor = ToRSColor(bgColor_->Get());
76         brush.SetColor(bgColor);
77         double filletRadius = bgRect.GetWidth() * HALF;
78         canvas.AttachBrush(brush);
79         canvas.DrawRoundRect({ bgRect, filletRadius, filletRadius });
80         canvas.DetachBrush();
81 
82         RSRect fgRect(
83             fgOffset.GetX(), fgOffset.GetY(), fgOffset.GetX() + fgSize.Width(), fgOffset.GetY() + fgSize.Height());
84         RSColor fgColor = ToRSColor(fgColor_->Get().BlendOpacity(opacity_->Get() / FULL_ALPHA));
85         brush.SetColor(fgColor);
86         canvas.AttachBrush(brush);
87         canvas.DrawRoundRect({ fgRect, filletRadius, filletRadius });
88     }
89 }
90 
StartOpacityAnimation(OpacityAnimationType opacityAnimationType)91 void ScrollBarOverlayModifier::StartOpacityAnimation(OpacityAnimationType opacityAnimationType)
92 {
93     CHECK_NULL_VOID_NOLOG(opacity_);
94     if (opacityAnimationType == OpacityAnimationType::NONE) {
95         return;
96     }
97     if (opacityAnimationType != opacityAnimatingType_) {
98         StopBarOpacityAnimation();
99     } else {
100         return;
101     }
102     AnimationOption option;
103     option.SetCurve(Curves::SHARP);
104     if (opacityAnimationType == OpacityAnimationType::DISAPPEAR) {
105         option.SetDuration(BAR_END_DURATION);
106     } else if (opacityAnimationType == OpacityAnimationType::APPEAR) {
107         option.SetDuration(BAR_APPEAR_DURATION);
108     }
109     opacityAnimatingType_ = opacityAnimationType;
110     opacityAnimation_ = AnimationUtils::StartAnimation(
111         option,
112         [&]() {
113             if (opacityAnimatingType_ == OpacityAnimationType::DISAPPEAR) {
114                 opacity_->Set(0);
115             } else if (opacityAnimatingType_ == OpacityAnimationType::APPEAR) {
116                 opacity_->Set(UINT8_MAX);
117             }
118         },
119         [weak = WeakClaim(this)]() {
120             auto modifier = weak.Upgrade();
121             CHECK_NULL_VOID_NOLOG(modifier);
122             modifier->SetOpacityAnimatingType(OpacityAnimationType::NONE);
123         });
124 }
125 
StopBarOpacityAnimation()126 void ScrollBarOverlayModifier::StopBarOpacityAnimation()
127 {
128     if (opacityAnimation_) {
129         AnimationUtils::StopAnimation(opacityAnimation_);
130     }
131 }
132 
SetOffset(const OffsetF & fgOffset,const OffsetF & bgOffset)133 void ScrollBarOverlayModifier::SetOffset(const OffsetF& fgOffset, const OffsetF& bgOffset)
134 {
135     CHECK_NULL_VOID_NOLOG(fgOffset_);
136     CHECK_NULL_VOID_NOLOG(bgOffset_);
137     fgOffset_->Set(fgOffset);
138     bgOffset_->Set(bgOffset);
139 }
140 
SetSize(const SizeF & fgSize,const SizeF & bgSize)141 void ScrollBarOverlayModifier::SetSize(const SizeF& fgSize, const SizeF& bgSize)
142 {
143     CHECK_NULL_VOID(fgSize_);
144     CHECK_NULL_VOID(bgSize_);
145     fgSize_->Set(fgSize);
146     bgSize_->Set(bgSize);
147 }
148 
SetRect(const Rect & fgRect,const Rect & bgRect)149 void ScrollBarOverlayModifier::SetRect(const Rect& fgRect, const Rect& bgRect)
150 {
151     SetOffset(OffsetF(fgRect.Left(), fgRect.Top()), OffsetF(bgRect.Left(), bgRect.Top()));
152     SetSize(SizeF(fgRect.Width(), fgRect.Height()), SizeF(bgRect.Width(), bgRect.Height()));
153 }
154 
StartHoverAnimation(const SizeF & fgSize,const SizeF & bgSize,const OffsetF & fgOffset,const OffsetF & bgOffset,HoverAnimationType hoverAnimationType)155 void ScrollBarOverlayModifier::StartHoverAnimation(const SizeF& fgSize, const SizeF& bgSize, const OffsetF& fgOffset,
156     const OffsetF& bgOffset, HoverAnimationType hoverAnimationType)
157 {
158     CHECK_NULL_VOID_NOLOG(fgSize_);
159     CHECK_NULL_VOID_NOLOG(bgSize_);
160     CHECK_NULL_VOID_NOLOG(fgOffset_);
161     CHECK_NULL_VOID_NOLOG(bgOffset_);
162     if (hoverAnimationType == HoverAnimationType::NONE) {
163         if (hoverAnimatingType_ == HoverAnimationType::NONE) {
164             fgSize_->Set(fgSize);
165             bgSize_->Set(bgSize);
166             fgOffset_->Set(fgOffset);
167             bgOffset_->Set(bgOffset);
168         }
169         return;
170     }
171     if (hoverAnimationType != hoverAnimatingType_) {
172         StopBarHoverAnimation();
173     }
174     AnimationOption option;
175     option.SetCurve(Curves::SHARP);
176     hoverAnimatingType_ = hoverAnimationType;
177     if (hoverAnimatingType_ == HoverAnimationType::GROW) {
178         option.SetDuration(BAR_GROW_DURATION);
179     } else if (hoverAnimatingType_ == HoverAnimationType::SHRINK) {
180         option.SetDuration(BAR_SHRINK_DURATION);
181     }
182 
183     hoverAnimation_ = AnimationUtils::StartAnimation(
184         option,
185         [&]() {
186             fgSize_->Set(fgSize);
187             bgSize_->Set(bgSize);
188             fgOffset_->Set(fgOffset);
189             bgOffset_->Set(bgOffset);
190         },
191         [weak = WeakClaim(this)]() {
192             auto modifier = weak.Upgrade();
193             CHECK_NULL_VOID_NOLOG(modifier);
194             modifier->SetHoverAnimatingType(HoverAnimationType::NONE);
195         });
196 }
197 
StopBarHoverAnimation()198 void ScrollBarOverlayModifier::StopBarHoverAnimation()
199 {
200     if (hoverAnimation_) {
201         AnimationUtils::StopAnimation(hoverAnimation_);
202     }
203 }
204 
SetFgColor(Color fgColor)205 void ScrollBarOverlayModifier::SetFgColor(Color fgColor)
206 {
207     CHECK_NULL_VOID_NOLOG(fgColor_);
208     fgColor_->Set(fgColor);
209 }
210 
SetBgColor(Color bgColor)211 void ScrollBarOverlayModifier::SetBgColor(Color bgColor)
212 {
213     CHECK_NULL_VOID_NOLOG(bgColor_);
214     bgColor_->Set(bgColor);
215 }
216 } // namespace OHOS::Ace::NG