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 "bridge/declarative_frontend/jsview/js_scroll.h"
17
18 #include "bridge/declarative_frontend/jsview/js_scroller.h"
19 #include "bridge/declarative_frontend/jsview/js_view_common_def.h"
20 #include "bridge/declarative_frontend/view_stack_processor.h"
21 #include "core/components/scroll/scroll_component.h"
22
23 namespace OHOS::Ace::Framework {
24 namespace {
25 const std::vector<DisplayMode> DISPLAY_MODE = {DisplayMode::OFF, DisplayMode::AUTO, DisplayMode::ON};
26 }
Create(const JSCallbackInfo & info)27 void JSScroll::Create(const JSCallbackInfo& info)
28 {
29 RefPtr<Component> child;
30 auto scrollComponent = AceType::MakeRefPtr<OHOS::Ace::ScrollComponent>(child);
31 if (info.Length() > 0 && info[0]->IsObject()) {
32 JSScroller* jsScroller = JSRef<JSObject>::Cast(info[0])->Unwrap<JSScroller>();
33 if (jsScroller) {
34 auto positionController = AceType::MakeRefPtr<ScrollPositionController>();
35 jsScroller->SetController(positionController);
36 scrollComponent->SetScrollPositionController(positionController);
37
38 // Init scroll bar proxy.
39 auto proxy = jsScroller->GetScrollBarProxy();
40 if (!proxy) {
41 proxy = AceType::MakeRefPtr<ScrollBarProxy>();
42 jsScroller->SetScrollBarProxy(proxy);
43 }
44 scrollComponent->SetScrollBarProxy(proxy);
45 }
46 } else {
47 auto positionController = AceType::MakeRefPtr<ScrollPositionController>();
48 scrollComponent->SetScrollPositionController(positionController);
49 }
50 // init scroll bar
51 std::pair<bool, Color> barColor;
52 barColor.first = false;
53 std::pair<bool, Dimension> barWidth;
54 barWidth.first = false;
55 scrollComponent->InitScrollBar(GetTheme<ScrollBarTheme>(), barColor, barWidth, EdgeEffect::NONE);
56 ViewStackProcessor::GetInstance()->Push(scrollComponent);
57 }
58
SetScrollable(int32_t value)59 void JSScroll::SetScrollable(int32_t value)
60 {
61 if (value >= 0 && value < 4) {
62 auto component = ViewStackProcessor::GetInstance()->GetMainComponent();
63 auto scrollComponent = AceType::DynamicCast<ScrollComponent>(component);
64 if (scrollComponent) {
65 scrollComponent->SetAxisDirection((Axis)value);
66 }
67 } else {
68 LOGE("invalid value for SetScrollable");
69 }
70 }
71
OnScrollCallback(const JSCallbackInfo & args)72 void JSScroll::OnScrollCallback(const JSCallbackInfo& args)
73 {
74 if (args[0]->IsFunction()) {
75 auto onScroll = EventMarker(
76 [execCtx = args.GetExecutionContext(), func = JSRef<JSFunc>::Cast(args[0])](const BaseEventInfo* info) {
77 JAVASCRIPT_EXECUTION_SCOPE_WITH_CHECK(execCtx);
78 auto eventInfo = TypeInfoHelper::DynamicCast<ScrollEventInfo>(info);
79 if (!eventInfo) {
80 return;
81 }
82 auto params = ConvertToJSValues(eventInfo->GetScrollX(), eventInfo->GetScrollY());
83 func->Call(JSRef<JSObject>(), params.size(), params.data());
84 });
85 auto scrollComponent =
86 AceType::DynamicCast<ScrollComponent>(ViewStackProcessor::GetInstance()->GetMainComponent());
87 if (scrollComponent) {
88 if (!scrollComponent->GetScrollPositionController()) {
89 scrollComponent->SetScrollPositionController(AceType::MakeRefPtr<ScrollPositionController>());
90 }
91 scrollComponent->SetOnScroll(onScroll);
92 }
93 }
94 args.SetReturnValue(args.This());
95 }
96
OnScrollEdgeCallback(const JSCallbackInfo & args)97 void JSScroll::OnScrollEdgeCallback(const JSCallbackInfo& args)
98 {
99 if (args[0]->IsFunction()) {
100 auto onScroll = EventMarker(
101 [execCtx = args.GetExecutionContext(), func = JSRef<JSFunc>::Cast(args[0])](const BaseEventInfo* info) {
102 JAVASCRIPT_EXECUTION_SCOPE_WITH_CHECK(execCtx);
103 auto eventInfo = TypeInfoHelper::DynamicCast<ScrollEventInfo>(info);
104 if (!eventInfo) {
105 return;
106 }
107 auto param = ConvertToJSValue(static_cast<int32_t>(eventInfo->GetType()));
108 func->Call(JSRef<JSObject>(), 1, ¶m);
109 });
110 auto scrollComponent =
111 AceType::DynamicCast<ScrollComponent>(ViewStackProcessor::GetInstance()->GetMainComponent());
112 if (scrollComponent) {
113 if (!scrollComponent->GetScrollPositionController()) {
114 scrollComponent->SetScrollPositionController(AceType::MakeRefPtr<ScrollPositionController>());
115 }
116 scrollComponent->SetOnScrollEdge(onScroll);
117 }
118 }
119 args.SetReturnValue(args.This());
120 }
121
OnScrollEndCallback(const JSCallbackInfo & args)122 void JSScroll::OnScrollEndCallback(const JSCallbackInfo& args)
123 {
124 if (args[0]->IsFunction()) {
125 auto onScrollStop = EventMarker(
126 [execCtx = args.GetExecutionContext(), func = JSRef<JSFunc>::Cast(args[0])](const BaseEventInfo* info) {
127 JAVASCRIPT_EXECUTION_SCOPE_WITH_CHECK(execCtx);
128 func->Call(JSRef<JSObject>(), 0, nullptr);
129 });
130 auto scrollComponent =
131 AceType::DynamicCast<ScrollComponent>(ViewStackProcessor::GetInstance()->GetMainComponent());
132 if (scrollComponent) {
133 if (!scrollComponent->GetScrollPositionController()) {
134 scrollComponent->SetScrollPositionController(AceType::MakeRefPtr<ScrollPositionController>());
135 }
136 scrollComponent->SetOnScrollEnd(onScrollStop);
137 }
138 }
139 args.SetReturnValue(args.This());
140 }
141
JSBind(BindingTarget globalObj)142 void JSScroll::JSBind(BindingTarget globalObj)
143 {
144 JSClass<JSScroll>::Declare("Scroll");
145 MethodOptions opt = MethodOptions::NONE;
146 JSClass<JSScroll>::StaticMethod("create", &JSScroll::Create, opt);
147 JSClass<JSScroll>::StaticMethod("scrollable", &JSScroll::SetScrollable, opt);
148 JSClass<JSScroll>::StaticMethod("onScroll", &JSScroll::OnScrollCallback, opt);
149 JSClass<JSScroll>::StaticMethod("onScrollEdge", &JSScroll::OnScrollEdgeCallback, opt);
150 JSClass<JSScroll>::StaticMethod("onScrollEnd", &JSScroll::OnScrollEndCallback, opt);
151 JSClass<JSScroll>::StaticMethod("onClick", &JSInteractableView::JsOnClick);
152 JSClass<JSScroll>::StaticMethod("onTouch", &JSInteractableView::JsOnTouch);
153 JSClass<JSScroll>::StaticMethod("onHover", &JSInteractableView::JsOnHover);
154 JSClass<JSScroll>::StaticMethod("onKeyEvent", &JSInteractableView::JsOnKey);
155 JSClass<JSScroll>::StaticMethod("onDeleteEvent", &JSInteractableView::JsOnDelete);
156 JSClass<JSScroll>::StaticMethod("onAppear", &JSInteractableView::JsOnAppear);
157 JSClass<JSScroll>::StaticMethod("onDisAppear", &JSInteractableView::JsOnDisAppear);
158 JSClass<JSScroll>::StaticMethod("edgeEffect", &JSScroll::SetEdgeEffect, opt);
159 JSClass<JSScroll>::StaticMethod("scrollBar", &JSScroll::SetScrollBar, opt);
160 JSClass<JSScroll>::StaticMethod("scrollBarColor", &JSScroll::SetScrollBarColor, opt);
161 JSClass<JSScroll>::StaticMethod("scrollBarWidth", &JSScroll::SetScrollBarWidth, opt);
162 JSClass<JSScroll>::StaticMethod("remoteMessage", &JSInteractableView::JsCommonRemoteMessage);
163 JSClass<JSScroll>::Inherit<JSContainerBase>();
164 JSClass<JSScroll>::Inherit<JSViewAbstract>();
165 JSClass<JSScroll>::Bind<>(globalObj);
166 }
167
SetScrollBar(int displayMode)168 void JSScroll::SetScrollBar(int displayMode)
169 {
170 auto scrollComponent = AceType::DynamicCast<ScrollComponent>(ViewStackProcessor::GetInstance()->GetMainComponent());
171 if (!scrollComponent) {
172 return;
173 }
174 if (displayMode >= 0 && displayMode < static_cast<int32_t>(DISPLAY_MODE.size())) {
175 scrollComponent->SetDisplayMode(DISPLAY_MODE[displayMode]);
176 }
177 }
178
SetScrollBarWidth(const std::string & scrollBarWidth)179 void JSScroll::SetScrollBarWidth(const std::string& scrollBarWidth)
180 {
181 auto scrollComponent = AceType::DynamicCast<ScrollComponent>(ViewStackProcessor::GetInstance()->GetMainComponent());
182 if (!scrollComponent || scrollBarWidth.empty()) {
183 return;
184 }
185 scrollComponent->SetScrollBarWidth(StringUtils::StringToDimension(scrollBarWidth));
186 }
187
SetScrollBarColor(const std::string & scrollBarColor)188 void JSScroll::SetScrollBarColor(const std::string& scrollBarColor)
189 {
190 auto scrollComponent = AceType::DynamicCast<ScrollComponent>(ViewStackProcessor::GetInstance()->GetMainComponent());
191 if (!scrollComponent || scrollBarColor.empty()) {
192 return;
193 }
194 scrollComponent->SetScrollBarColor(Color::FromString(scrollBarColor));
195 }
196
SetEdgeEffect(int edgeEffect)197 void JSScroll::SetEdgeEffect(int edgeEffect)
198 {
199 auto scrollComponent = AceType::DynamicCast<ScrollComponent>(ViewStackProcessor::GetInstance()->GetMainComponent());
200 if (!scrollComponent) {
201 return;
202 }
203 RefPtr<ScrollEdgeEffect> scrollEdgeEffect;
204 if (edgeEffect == 0) {
205 scrollEdgeEffect = AceType::MakeRefPtr<ScrollSpringEffect>();
206 } else if (edgeEffect == 1) {
207 scrollEdgeEffect = AceType::MakeRefPtr<ScrollFadeEffect>(Color::GRAY);
208 } else {
209 scrollEdgeEffect = AceType::MakeRefPtr<ScrollEdgeEffect>(EdgeEffect::NONE);
210 }
211 scrollComponent->SetScrollEffect(scrollEdgeEffect);
212 }
213
214 } // namespace OHOS::Ace::Framework
215