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 "frameworks/bridge/declarative_frontend/jsview/js_water_flow.h"
17
18 #include "bridge/declarative_frontend/jsview/js_view_common_def.h"
19 #include "frameworks/bridge/declarative_frontend/jsview/js_interactable_view.h"
20 #include "frameworks/bridge/declarative_frontend/jsview/js_scroller.h"
21 #include "frameworks/bridge/declarative_frontend/view_stack_processor.h"
22 #include "frameworks/core/components_v2/water_flow/water_flow_component.h"
23
24 namespace OHOS::Ace::Framework {
25 namespace {
26 const std::vector<FlexDirection> LAYOUT_DIRECTION = { FlexDirection::ROW, FlexDirection::COLUMN,
27 FlexDirection::ROW_REVERSE, FlexDirection::COLUMN_REVERSE };
28 } // namespace
29
Create(const JSCallbackInfo & args)30 void JSWaterFlow::Create(const JSCallbackInfo& args)
31 {
32 LOGI("Create component: WaterFLow");
33 if (args.Length() > 1) {
34 LOGW("Arg is wrong, it is supposed to have at most one argument");
35 return;
36 }
37
38 // create waterflow component
39 std::list<RefPtr<OHOS::Ace::Component>> componentChildren;
40 auto waterflowComponent = AceType::MakeRefPtr<V2::WaterFlowComponent>(componentChildren);
41 CHECK_NULL_VOID(waterflowComponent);
42
43 if (args.Length() == 1) {
44 if (!args[0]->IsObject()) {
45 LOGE("The arg must be object");
46 return;
47 }
48 JSRef<JSObject> obj = JSRef<JSObject>::Cast(args[0]);
49 auto footerObject = obj->GetProperty("footer");
50 if (footerObject->IsFunction()) {
51 ScopedViewStackProcessor builderViewStackProcessor;
52 auto builderFunc = AceType::MakeRefPtr<JsFunction>(JSRef<JSFunc>::Cast(footerObject));
53 builderFunc->Execute();
54 RefPtr<Component> customComponent = ViewStackProcessor::GetInstance()->Finish();
55 waterflowComponent->SetFooterComponent(customComponent);
56 }
57 auto scroller = obj->GetProperty("scroller");
58 if (scroller->IsObject()) {
59 auto *jsScroller = JSRef<JSObject>::Cast(scroller)->Unwrap<JSScroller>();
60 CHECK_NULL_VOID(jsScroller);
61 auto positionController = AceType::MakeRefPtr<V2::WaterFlowPositionController>();
62 jsScroller->SetController(positionController);
63 waterflowComponent->SetController(positionController);
64 // Init scroll bar proxy.
65 auto proxy = AceType::DynamicCast<ScrollBarProxy>(jsScroller->GetScrollBarProxy());
66 if (!proxy) {
67 proxy = AceType::MakeRefPtr<ScrollBarProxy>();
68 jsScroller->SetScrollBarProxy(proxy);
69 }
70 waterflowComponent->SetScrollBarProxy(proxy);
71 }
72 }
73 ViewStackProcessor::GetInstance()->Push(waterflowComponent);
74 }
75
JSBind(BindingTarget globalObj)76 void JSWaterFlow::JSBind(BindingTarget globalObj)
77 {
78 LOGD("JSWaterFlow:JSBind");
79 JSClass<JSWaterFlow>::Declare("WaterFlow");
80
81 MethodOptions opt = MethodOptions::NONE;
82 JSClass<JSWaterFlow>::StaticMethod("create", &JSWaterFlow::Create, opt);
83 JSClass<JSWaterFlow>::StaticMethod("columnsGap", &JSWaterFlow::SetColumnsGap, opt);
84 JSClass<JSWaterFlow>::StaticMethod("rowsGap", &JSWaterFlow::SetRowsGap, opt);
85 JSClass<JSWaterFlow>::StaticMethod("layoutDirection", &JSWaterFlow::SetLayoutDirection, opt);
86 JSClass<JSWaterFlow>::StaticMethod("columnsTemplate", &JSWaterFlow::SetColumnsTemplate, opt);
87 JSClass<JSWaterFlow>::StaticMethod("itemConstraintSize", &JSWaterFlow::SetItemConstraintSize, opt);
88 JSClass<JSWaterFlow>::StaticMethod("rowsTemplate", &JSWaterFlow::SetRowsTemplate, opt);
89 JSClass<JSWaterFlow>::StaticMethod("onReachStart", &JSWaterFlow::ReachStartCallback);
90 JSClass<JSWaterFlow>::StaticMethod("onReachEnd", &JSWaterFlow::ReachEndCallback);
91 JSClass<JSWaterFlow>::StaticMethod("onClick", &JSInteractableView::JsOnClick);
92 JSClass<JSWaterFlow>::StaticMethod("onTouch", &JSInteractableView::JsOnTouch);
93 JSClass<JSWaterFlow>::StaticMethod("onHover", &JSInteractableView::JsOnHover);
94 JSClass<JSWaterFlow>::StaticMethod("onKeyEvent", &JSInteractableView::JsOnKey);
95 JSClass<JSWaterFlow>::StaticMethod("onDeleteEvent", &JSInteractableView::JsOnDelete);
96 JSClass<JSWaterFlow>::StaticMethod("onAppear", &JSInteractableView::JsOnAppear);
97 JSClass<JSWaterFlow>::StaticMethod("onDisAppear", &JSInteractableView::JsOnDisAppear);
98 JSClass<JSWaterFlow>::StaticMethod("remoteMessage", &JSInteractableView::JsCommonRemoteMessage);
99
100 JSClass<JSWaterFlow>::Inherit<JSContainerBase>();
101 JSClass<JSWaterFlow>::Inherit<JSViewAbstract>();
102 JSClass<JSWaterFlow>::Bind<>(globalObj);
103 }
104
SetColumnsGap(const JSCallbackInfo & info)105 void JSWaterFlow::SetColumnsGap(const JSCallbackInfo& info)
106 {
107 if (info.Length() < 1) {
108 LOGW("Arg is wrong, it is supposed to have at least 1 argument");
109 return;
110 }
111 Dimension colGap;
112 if (!ParseJsDimensionVp(info[0], colGap)) {
113 return;
114 }
115 auto component = ViewStackProcessor::GetInstance()->GetMainComponent();
116 auto waterflow = AceType::DynamicCast<V2::WaterFlowComponent>(component);
117 if (waterflow) {
118 waterflow->SetColumnsGap(colGap);
119 }
120 }
121
SetRowsGap(const JSCallbackInfo & info)122 void JSWaterFlow::SetRowsGap(const JSCallbackInfo& info)
123 {
124 if (info.Length() < 1) {
125 LOGW("Arg is wrong, it is supposed to have at least 1 argument");
126 return;
127 }
128 Dimension rowGap;
129 if (!ParseJsDimensionVp(info[0], rowGap)) {
130 return;
131 }
132 auto component = ViewStackProcessor::GetInstance()->GetMainComponent();
133 auto waterflow = AceType::DynamicCast<V2::WaterFlowComponent>(component);
134 if (waterflow) {
135 waterflow->SetRowsGap(rowGap);
136 }
137 }
138
SetLayoutDirection(int32_t value)139 void JSWaterFlow::SetLayoutDirection(int32_t value)
140 {
141 if (value >= 0 && value < static_cast<int32_t>(LAYOUT_DIRECTION.size())) {
142 auto component = ViewStackProcessor::GetInstance()->GetMainComponent();
143 auto waterflow = AceType::DynamicCast<V2::WaterFlowComponent>(component);
144 if (waterflow) {
145 waterflow->SetLayoutDirection(LAYOUT_DIRECTION[value]);
146 }
147 }
148 }
SetColumnsTemplate(const std::string & value)149 void JSWaterFlow::SetColumnsTemplate(const std::string& value)
150 {
151 auto component = ViewStackProcessor::GetInstance()->GetMainComponent();
152 auto waterflow = AceType::DynamicCast<V2::WaterFlowComponent>(component);
153 if (waterflow) {
154 waterflow->SetColumnsArgs(value);
155 }
156 }
157
SetItemConstraintSize(const JSCallbackInfo & info)158 void JSWaterFlow::SetItemConstraintSize(const JSCallbackInfo& info)
159 {
160 if (info.Length() < 1 || !info[0]->IsObject()) {
161 LOGI("waterflow create error, info is invalid");
162 return;
163 }
164 auto component = ViewStackProcessor::GetInstance()->GetMainComponent();
165 auto waterflow = AceType::DynamicCast<V2::WaterFlowComponent>(component);
166 JSRef<JSObject> sizeObj = JSRef<JSObject>::Cast(info[0]);
167
168 JSRef<JSVal> minWidthValue = sizeObj->GetProperty("minWidth");
169 Dimension minWidth;
170 if (ParseJsDimensionVp(minWidthValue, minWidth)) {
171 waterflow->SetMinWidth(minWidth);
172 }
173
174 JSRef<JSVal> maxWidthValue = sizeObj->GetProperty("maxWidth");
175 Dimension maxWidth;
176 if (ParseJsDimensionVp(maxWidthValue, maxWidth)) {
177 waterflow->SetMaxWidth(maxWidth);
178 }
179
180 JSRef<JSVal> minHeightValue = sizeObj->GetProperty("minHeight");
181 Dimension minHeight;
182 if (ParseJsDimensionVp(minHeightValue, minHeight)) {
183 waterflow->SetMinHeight(minHeight);
184 }
185
186 JSRef<JSVal> maxHeightValue = sizeObj->GetProperty("maxHeight");
187 Dimension maxHeight;
188 if (ParseJsDimensionVp(maxHeightValue, maxHeight)) {
189 waterflow->SetMaxHeight(maxHeight);
190 }
191 }
192
SetRowsTemplate(const std::string & value)193 void JSWaterFlow::SetRowsTemplate(const std::string& value)
194 {
195 auto component = ViewStackProcessor::GetInstance()->GetMainComponent();
196 auto waterflow = AceType::DynamicCast<V2::WaterFlowComponent>(component);
197 if (waterflow) {
198 waterflow->SetRowsArgs(value);
199 }
200 }
201
ReachStartCallback(const JSCallbackInfo & args)202 void JSWaterFlow::ReachStartCallback(const JSCallbackInfo& args)
203 {
204 if (!JSViewBindEvent(&V2::WaterFlowComponent::SetOnReachStart, args)) {
205 LOGW("Failed to bind event");
206 }
207 args.ReturnSelf();
208 }
209
ReachEndCallback(const JSCallbackInfo & args)210 void JSWaterFlow::ReachEndCallback(const JSCallbackInfo& args)
211 {
212 if (!JSViewBindEvent(&V2::WaterFlowComponent::SetOnReachEnd, args)) {
213 LOGW("Failed to bind event");
214 }
215 args.ReturnSelf();
216 }
217 } // namespace OHOS::Ace::Framework
218