• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2021 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/common/properties/scroll_bar.h"
17 
18 #include "core/animation/curve_animation.h"
19 
20 namespace OHOS::Ace {
21 
InBarRegion(const Point & point) const22 bool ScrollBar::InBarRegion(const Point& point) const
23 {
24     if (NeedScrollBar() && shapeMode_ == ShapeMode::RECT) {
25         return touchRegion_.IsInRegion(point);
26     }
27     return false;
28 }
29 
UpdateScrollBarRegion(const Offset & offset,const Size & size,const Offset & lastOffset,double estimatedHeight)30 void ScrollBar::UpdateScrollBarRegion(
31     const Offset& offset, const Size& size, const Offset& lastOffset, double estimatedHeight)
32 {
33     if (!NearZero(estimatedHeight)) {
34         SetBarRegion(offset, size);
35         SetTrickRegion(offset, size, lastOffset, estimatedHeight);
36     }
37 }
38 
SetBarRegion(const Offset & offset,const Size & size)39 void ScrollBar::SetBarRegion(const Offset& offset, const Size& size)
40 {
41     double normalWidth = NormalizeToPx(normalWidth_);
42     if (shapeMode_ == ShapeMode::RECT) {
43         double height = std::max(size.Height() - NormalizeToPx(reservedHeight_), 0.0);
44         if (positionMode_ == PositionMode::LEFT) {
45             barRect_ = Rect(0.0, 0.0, normalWidth, height) + offset;
46         } else {
47             barRect_ = Rect(size.Width() - normalWidth - NormalizeToPx(padding_.Right()), 0.0,
48                 normalWidth, height) + offset;
49         }
50     }
51 }
52 
SetTrickRegion(const Offset & offset,const Size & size,const Offset & lastOffset,double estimatedHeight)53 void ScrollBar::SetTrickRegion(const Offset& offset, const Size& size, const Offset& lastOffset, double estimatedHeight)
54 {
55     if (shapeMode_ == ShapeMode::RECT) {
56         double height = size.Height();
57         double barRegionHeight = std::max(height - NormalizeToPx(reservedHeight_), 0.0);
58         double activeHeight = barRegionHeight * height / estimatedHeight - outBoundary_;
59         if (!NearEqual(height, estimatedHeight)) {
60             double width = size.Width();
61             if (!NearZero(outBoundary_)) {
62                 activeHeight = std::max(
63                     std::max(activeHeight, NormalizeToPx(minHeight_) - outBoundary_), NormalizeToPx(minDynamicHeight_));
64             } else {
65                 activeHeight = std::max(activeHeight, NormalizeToPx(minHeight_));
66             }
67             double lastOffsetY = std::max(lastOffset.GetY(), 0.0);
68             double activeOffsetY = (height - activeHeight) * lastOffsetY / (estimatedHeight - height);
69             activeOffsetY = std::min(activeOffsetY, barRegionHeight - activeHeight);
70             double normalWidth = NormalizeToPx(normalWidth_);
71             if (positionMode_ == PositionMode::LEFT) {
72                 activeRect_ = Rect(-NormalizeToPx(position_), activeOffsetY, normalWidth, activeHeight) + offset;
73                 touchRegion_ = activeRect_ + Size(NormalizeToPx(touchWidth_), 0);
74             } else {
75                 double x = width - normalWidth - NormalizeToPx(padding_.Right()) + NormalizeToPx(position_);
76                 activeRect_ = Rect(x, activeOffsetY, normalWidth, activeHeight) + offset;
77                 // Update the hot region
78                 touchRegion_ =
79                     activeRect_ -
80                     Offset(NormalizeToPx(touchWidth_) - NormalizeToPx(normalWidth_) - NormalizeToPx(padding_.Right()),
81                         0.0) +
82                     Size(NormalizeToPx(touchWidth_) - NormalizeToPx(normalWidth_), 0);
83             }
84         }
85     } else {
86         double diameter = std::min(size.Width(), size.Height());
87         if (!NearEqual(estimatedHeight, diameter)) {
88             double maxAngle = bottomAngle_ - topAngle_;
89             trickSweepAngle_ = std::max(diameter * maxAngle / estimatedHeight, minAngle_);
90             double lastOffsetY = std::max(lastOffset.GetY(), 0.0);
91             double trickStartAngle = (maxAngle - trickSweepAngle_) * lastOffsetY / (estimatedHeight - diameter);
92             trickStartAngle = std::clamp(0.0, trickStartAngle, maxAngle) - maxAngle * FACTOR_HALF;
93             if (positionMode_ == PositionMode::LEFT) {
94                 if (trickStartAngle > 0.0) {
95                     trickStartAngle_ = STRAIGHT_ANGLE - trickStartAngle;
96                 } else {
97                     trickStartAngle_ = -(trickStartAngle + STRAIGHT_ANGLE);
98                 }
99                 trickSweepAngle_ = -trickSweepAngle_;
100             } else {
101                 trickStartAngle_ = trickStartAngle;
102             }
103         }
104     }
105 }
106 
NeedScrollBar() const107 bool ScrollBar::NeedScrollBar() const
108 {
109     return displayMode_ == DisplayMode::AUTO || displayMode_ == DisplayMode::ON;
110 }
111 
NeedPaint() const112 bool ScrollBar::NeedPaint() const
113 {
114     return NeedScrollBar() && isScrollable_;
115 }
116 
GetNormalWidthToPx() const117 double ScrollBar::GetNormalWidthToPx() const
118 {
119     return NormalizeToPx(normalWidth_);
120 }
121 
InitScrollBar(const WeakPtr<RenderNode> & scroll,const WeakPtr<PipelineContext> & context)122 void ScrollBar::InitScrollBar(const WeakPtr<RenderNode>& scroll, const WeakPtr<PipelineContext>& context)
123 {
124     pipelineContext_ = context;
125     if (NeedScrollBar()) {
126         if (!barController_) {
127             barController_ = AceType::MakeRefPtr<ScrollBarController>();
128         }
129         barController_->Initialize(context);
130         barController_->SetScrollNode(scroll);
131         barController_->SetActiveWidth(activeWidth_);
132         barController_->SetInactiveWidth(inactiveWidth_);
133     }
134 }
135 
NormalizeToPx(const Dimension & dimension) const136 double ScrollBar::NormalizeToPx(const Dimension& dimension) const
137 {
138     auto pipelineContext = pipelineContext_.Upgrade();
139     if (!pipelineContext) {
140         LOGE("NormalizeToPx failed");
141         return 0.0;
142     }
143     return pipelineContext->NormalizeToPx(dimension);
144 }
145 
SetCallBack(const ScrollBarPositionCallback & callback,const ScrollBarEndCallback & barEndCallback,const ScrollBarEventCallback & scrollEndCallback)146 void ScrollBar::SetCallBack(const ScrollBarPositionCallback& callback, const ScrollBarEndCallback& barEndCallback,
147     const ScrollBarEventCallback& scrollEndCallback)
148 {
149     if (barController_) {
150         barController_->SetCallback(callback);
151         barController_->SetBarEndCallback(barEndCallback);
152         barController_->SetScrollEndCallback(scrollEndCallback);
153         barController_->SetTouchDownCallback([weakScrollBar = AceType::WeakClaim(this)](double value) {
154             auto scrollBar = weakScrollBar.Upgrade();
155             if (!scrollBar) {
156                 LOGE("scrollBar is released");
157                 return;
158             }
159             // value is normalized before animation
160             scrollBar->normalWidth_ = Dimension(value, DimensionUnit::PX);
161         });
162         barController_->SetTouchUpCallback([weakScrollBar = AceType::WeakClaim(this)](double value) {
163             auto scrollBar = weakScrollBar.Upgrade();
164             if (!scrollBar) {
165                 LOGE("scrollBar is released");
166                 return;
167             }
168             // value is normalized before animation
169             scrollBar->normalWidth_ = Dimension(value, DimensionUnit::PX);
170         });
171     }
172 }
173 
HandleScrollBarEnd()174 void ScrollBar::HandleScrollBarEnd()
175 {
176     if (displayMode_ == DisplayMode::AUTO) {
177         barController_->HandleScrollBarEnd();
178     }
179 }
180 
AddScrollBarController(const Offset & coordinateOffset,TouchTestResult & result)181 void ScrollBar::AddScrollBarController(const Offset& coordinateOffset, TouchTestResult& result)
182 {
183     if (barController_) {
184         barController_->SetCoordinateOffset(coordinateOffset);
185         result.emplace_back(barController_);
186     }
187 }
188 
SetActive(bool isActive)189 void ScrollBar::SetActive(bool isActive)
190 {
191     if (barController_) {
192         barController_->SetActive(isActive);
193     }
194 }
195 
IsActive() const196 bool ScrollBar::IsActive() const
197 {
198     if (barController_) {
199         return barController_->IsActive();
200     }
201     return false;
202 }
203 
SetUndisplay()204 void ScrollBar::SetUndisplay()
205 {
206     displayMode_ = DisplayMode::OFF;
207 }
208 
GetRootSize() const209 Size ScrollBar::GetRootSize() const
210 {
211     auto context = pipelineContext_.Upgrade();
212     if (context) {
213         auto rootHeight = context->GetRootHeight();
214         auto rootWidth = context->GetRootWidth();
215         return Size(rootWidth, rootHeight);
216     } else {
217         return Size();
218     }
219 }
220 
Reset()221 void ScrollBar::Reset()
222 {
223     if (barController_) {
224         barController_->Reset();
225     }
226 }
227 
228 } // namespace OHOS::Ace