1 /*
2  * Copyright (c) 2022 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 "bridge/declarative_frontend/jsview/models/scroll_model_impl.h"
17 
18 #include "base/geometry/dimension.h"
19 #include "base/utils/utils.h"
20 #include "bridge/declarative_frontend/jsview/js_scroller.h"
21 #include "bridge/declarative_frontend/jsview/js_view_common_def.h"
22 #include "bridge/declarative_frontend/view_stack_processor.h"
23 #include "core/components/common/layout/constants.h"
24 #include "core/components/scroll/scroll_component.h"
25 #include "core/components_ng/pattern/scroll/scroll_event_hub.h"
26 
27 namespace OHOS::Ace::Framework {
28 namespace {
29 const std::vector<DisplayMode> DISPLAY_MODE = { DisplayMode::OFF, DisplayMode::AUTO, DisplayMode::ON };
30 } // namespace
31 
Create()32 void ScrollModelImpl::Create()
33 {
34     RefPtr<Component> child;
35     auto scrollComponent = AceType::MakeRefPtr<OHOS::Ace::ScrollComponent>(child);
36     ViewStackProcessor::GetInstance()->ClaimElementId(scrollComponent);
37     auto positionController = AceType::MakeRefPtr<ScrollPositionController>();
38     scrollComponent->SetScrollPositionController(positionController);
39     ViewStackProcessor::GetInstance()->Push(scrollComponent);
40 }
41 
GetOrCreateController()42 RefPtr<ScrollControllerBase> ScrollModelImpl::GetOrCreateController()
43 {
44     auto component = AceType::DynamicCast<ScrollComponent>(ViewStackProcessor::GetInstance()->GetMainComponent());
45     CHECK_NULL_RETURN(component, nullptr);
46     if (!component->GetScrollPositionController()) {
47         component->SetScrollPositionController(AceType::MakeRefPtr<ScrollPositionController>());
48     }
49     return component->GetScrollPositionController();
50 }
51 
CreateScrollBarProxy()52 RefPtr<ScrollProxy> ScrollModelImpl::CreateScrollBarProxy()
53 {
54     return AceType::MakeRefPtr<ScrollBarProxy>();
55 }
56 
SetAxis(Axis axis)57 void ScrollModelImpl::SetAxis(Axis axis)
58 {
59     JSViewSetProperty(&ScrollComponent::SetAxisDirection, axis);
60 }
61 
SetOnScrollBegin(OnScrollBeginEvent && event)62 void ScrollModelImpl::SetOnScrollBegin(OnScrollBeginEvent&& event)
63 {
64     JSViewSetProperty(&ScrollComponent::SetOnScrollBegin, std::move(event));
65 }
66 
SetOnScrollFrameBegin(OnScrollFrameBeginEvent && event)67 void ScrollModelImpl::SetOnScrollFrameBegin(OnScrollFrameBeginEvent&& event)
68 {
69 }
70 
SetOnScroll(NG::ScrollEvent && event)71 void ScrollModelImpl::SetOnScroll(NG::ScrollEvent&& event)
72 {
73     auto onScroll = EventMarker([scrollEvent = std::move(event)](const BaseEventInfo* info) {
74         auto eventInfo = TypeInfoHelper::DynamicCast<ScrollEventInfo>(info);
75         if (!eventInfo || !scrollEvent) {
76             return;
77         }
78         Dimension x(eventInfo->GetScrollX(), DimensionUnit::VP);
79         Dimension y(eventInfo->GetScrollY(), DimensionUnit::VP);
80         scrollEvent(x, y);
81     });
82     JSViewSetProperty(&ScrollComponent::SetOnScroll, std::move(onScroll));
83 }
84 
SetOnScrollEdge(NG::ScrollEdgeEvent && event)85 void ScrollModelImpl::SetOnScrollEdge(NG::ScrollEdgeEvent&& event)
86 {
87     auto onScrollEdge = EventMarker([scrollEvent = std::move(event)](const BaseEventInfo* info) {
88         auto eventInfo = TypeInfoHelper::DynamicCast<ScrollEventInfo>(info);
89         if (!eventInfo || !scrollEvent) {
90             return;
91         }
92         if (eventInfo->GetType() == ScrollEvent::SCROLL_TOP) {
93             scrollEvent(NG::ScrollEdge::TOP);
94         } else if (eventInfo->GetType() == ScrollEvent::SCROLL_BOTTOM) {
95             scrollEvent(NG::ScrollEdge::BOTTOM);
96         } else {
97             LOGW("EventType is not support: %{public}d", static_cast<int32_t>(eventInfo->GetType()));
98         }
99     });
100     JSViewSetProperty(&ScrollComponent::SetOnScrollEdge, std::move(onScrollEdge));
101 }
102 
SetOnScrollEnd(NG::ScrollEndEvent && event)103 void ScrollModelImpl::SetOnScrollEnd(NG::ScrollEndEvent&& event)
104 {
105     auto onScrollEnd = EventMarker([scrollEvent = std::move(event)](const BaseEventInfo* info) {
106         if (scrollEvent) {
107             scrollEvent();
108         }
109     });
110     JSViewSetProperty(&ScrollComponent::SetOnScrollEnd, std::move(onScrollEnd));
111 }
112 
SetScrollBarProxy(const RefPtr<ScrollProxy> & proxy)113 void ScrollModelImpl::SetScrollBarProxy(const RefPtr<ScrollProxy>& proxy)
114 {
115     auto scrollBarProxy = AceType::DynamicCast<ScrollBarProxy>(proxy);
116     JSViewSetProperty(&ScrollComponent::SetScrollBarProxy, scrollBarProxy);
117 }
118 
InitScrollBar(const RefPtr<ScrollBarTheme> & theme,const std::pair<bool,Color> & color,const std::pair<bool,Dimension> & width,EdgeEffect effect)119 void ScrollModelImpl::InitScrollBar(const RefPtr<ScrollBarTheme>& theme, const std::pair<bool, Color>& color,
120     const std::pair<bool, Dimension>& width, EdgeEffect effect)
121 {
122     auto component = AceType::DynamicCast<ScrollComponent>(ViewStackProcessor::GetInstance()->GetMainComponent());
123     CHECK_NULL_VOID(component);
124     component->InitScrollBar(theme, color, width, effect);
125 }
126 
SetDisplayMode(int displayMode)127 void ScrollModelImpl::SetDisplayMode(int displayMode)
128 {
129     if (displayMode >= 0 && displayMode < static_cast<int32_t>(DISPLAY_MODE.size())) {
130         JSViewSetProperty(&ScrollComponent::SetDisplayMode, DISPLAY_MODE[displayMode]);
131     }
132 }
133 
SetScrollBarWidth(const Dimension & dimension)134 void ScrollModelImpl::SetScrollBarWidth(const Dimension& dimension)
135 {
136     JSViewSetProperty(&ScrollComponent::SetScrollBarWidth, dimension);
137 }
138 
SetScrollBarColor(const Color & color)139 void ScrollModelImpl::SetScrollBarColor(const Color& color)
140 {
141     JSViewSetProperty(&ScrollComponent::SetScrollBarColor, color);
142 }
143 
SetEdgeEffect(EdgeEffect edgeEffect,bool alwaysEnabled)144 void ScrollModelImpl::SetEdgeEffect(EdgeEffect edgeEffect, bool alwaysEnabled)
145 {
146     auto scrollComponent = AceType::DynamicCast<ScrollComponent>(ViewStackProcessor::GetInstance()->GetMainComponent());
147     CHECK_NULL_VOID(scrollComponent);
148     RefPtr<ScrollEdgeEffect> scrollEdgeEffect;
149     if (edgeEffect == EdgeEffect::SPRING) {
150         scrollEdgeEffect = AceType::MakeRefPtr<ScrollSpringEffect>();
151     } else if (edgeEffect == EdgeEffect::FADE) {
152         scrollEdgeEffect = AceType::MakeRefPtr<ScrollFadeEffect>(Color::GRAY);
153     } else {
154         scrollEdgeEffect = AceType::MakeRefPtr<ScrollEdgeEffect>(EdgeEffect::NONE);
155     }
156     scrollComponent->SetScrollEffect(scrollEdgeEffect);
157 }
158 
SetHasWidth(bool hasWidth)159 void ScrollModelImpl::SetHasWidth(bool hasWidth)
160 {
161     JSViewSetProperty(&ScrollComponent::SetHasWidth, hasWidth);
162 }
163 
SetHasHeight(bool hasHeight)164 void ScrollModelImpl::SetHasHeight(bool hasHeight)
165 {
166     JSViewSetProperty(&ScrollComponent::SetHasHeight, hasHeight);
167 }
168 
169 } // namespace OHOS::Ace::Framework
170