• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2022-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 "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/jsview/models/water_flow_model_impl.h"
22 #include "frameworks/bridge/declarative_frontend/view_stack_processor.h"
23 #include "frameworks/core/components_ng/pattern/waterflow/water_flow_model_ng.h"
24 
25 namespace OHOS::Ace {
26 std::unique_ptr<WaterFlowModel> WaterFlowModel::instance_ = nullptr;
27 
GetInstance()28 WaterFlowModel* WaterFlowModel::GetInstance()
29 {
30     if (!instance_) {
31 #ifdef NG_BUILD
32         instance_.reset(new NG::WaterFlowModelNG());
33 #else
34         if (Container::IsCurrentUseNewPipeline()) {
35             instance_.reset(new NG::WaterFlowModelNG());
36         } else {
37             instance_.reset(new Framework::WaterFlowModelImpl());
38         }
39 #endif
40     }
41     return instance_.get();
42 }
43 } // namespace OHOS::Ace
44 namespace OHOS::Ace::Framework {
45 namespace {
46 const std::vector<FlexDirection> LAYOUT_DIRECTION = { FlexDirection::ROW, FlexDirection::COLUMN,
47     FlexDirection::ROW_REVERSE, FlexDirection::COLUMN_REVERSE };
48 } // namespace
49 
Create(const JSCallbackInfo & args)50 void JSWaterFlow::Create(const JSCallbackInfo& args)
51 {
52     LOGI("Create component: WaterFLow");
53     if (args.Length() > 1) {
54         LOGW("Arg is wrong, it is supposed to have at most one argument");
55         return;
56     }
57 
58     WaterFlowModel::GetInstance()->Create();
59 
60     if (args.Length() == 1) {
61         if (!args[0]->IsObject()) {
62             LOGE("The arg must be object");
63             return;
64         }
65         JSRef<JSObject> obj = JSRef<JSObject>::Cast(args[0]);
66         auto footerObject = obj->GetProperty("footer");
67         if (footerObject->IsFunction()) {
68             auto builderFunc = AceType::MakeRefPtr<JsFunction>(JSRef<JSFunc>::Cast(footerObject));
69             auto footerAction = [builderFunc]() { builderFunc->Execute(); };
70             WaterFlowModel::GetInstance()->SetFooter(footerAction);
71         }
72         auto scroller = obj->GetProperty("scroller");
73         if (scroller->IsObject()) {
74             auto* jsScroller = JSRef<JSObject>::Cast(scroller)->Unwrap<JSScroller>();
75             CHECK_NULL_VOID(jsScroller);
76             auto positionController = WaterFlowModel::GetInstance()->CreateScrollController();
77             jsScroller->SetController(positionController);
78 
79             // Init scroll bar proxy.
80             auto proxy = jsScroller->GetScrollBarProxy();
81             if (!proxy) {
82                 proxy = WaterFlowModel::GetInstance()->CreateScrollBarProxy();
83                 jsScroller->SetScrollBarProxy(proxy);
84             }
85             WaterFlowModel::GetInstance()->SetScroller(positionController, proxy);
86         }
87     }
88 }
89 
JSBind(BindingTarget globalObj)90 void JSWaterFlow::JSBind(BindingTarget globalObj)
91 {
92     LOGD("JSWaterFlow:JSBind");
93     JSClass<JSWaterFlow>::Declare("WaterFlow");
94 
95     MethodOptions opt = MethodOptions::NONE;
96     JSClass<JSWaterFlow>::StaticMethod("create", &JSWaterFlow::Create, opt);
97     JSClass<JSWaterFlow>::StaticMethod("columnsGap", &JSWaterFlow::SetColumnsGap, opt);
98     JSClass<JSWaterFlow>::StaticMethod("rowsGap", &JSWaterFlow::SetRowsGap, opt);
99     JSClass<JSWaterFlow>::StaticMethod("layoutDirection", &JSWaterFlow::SetLayoutDirection, opt);
100     JSClass<JSWaterFlow>::StaticMethod("columnsTemplate", &JSWaterFlow::SetColumnsTemplate, opt);
101     JSClass<JSWaterFlow>::StaticMethod("itemConstraintSize", &JSWaterFlow::SetItemConstraintSize, opt);
102     JSClass<JSWaterFlow>::StaticMethod("rowsTemplate", &JSWaterFlow::SetRowsTemplate, opt);
103     JSClass<JSWaterFlow>::StaticMethod("onReachStart", &JSWaterFlow::ReachStartCallback);
104     JSClass<JSWaterFlow>::StaticMethod("onReachEnd", &JSWaterFlow::ReachEndCallback);
105     JSClass<JSWaterFlow>::StaticMethod("onClick", &JSInteractableView::JsOnClick);
106     JSClass<JSWaterFlow>::StaticMethod("onTouch", &JSInteractableView::JsOnTouch);
107     JSClass<JSWaterFlow>::StaticMethod("onHover", &JSInteractableView::JsOnHover);
108     JSClass<JSWaterFlow>::StaticMethod("onKeyEvent", &JSInteractableView::JsOnKey);
109     JSClass<JSWaterFlow>::StaticMethod("onDeleteEvent", &JSInteractableView::JsOnDelete);
110     JSClass<JSWaterFlow>::StaticMethod("onAppear", &JSInteractableView::JsOnAppear);
111     JSClass<JSWaterFlow>::StaticMethod("onDisAppear", &JSInteractableView::JsOnDisAppear);
112     JSClass<JSWaterFlow>::StaticMethod("remoteMessage", &JSInteractableView::JsCommonRemoteMessage);
113 
114     JSClass<JSWaterFlow>::Inherit<JSContainerBase>();
115     JSClass<JSWaterFlow>::Inherit<JSViewAbstract>();
116     JSClass<JSWaterFlow>::Bind<>(globalObj);
117 }
118 
SetColumnsGap(const JSCallbackInfo & info)119 void JSWaterFlow::SetColumnsGap(const JSCallbackInfo& info)
120 {
121     if (info.Length() < 1) {
122         LOGW("Arg is wrong, it is supposed to have at least 1 argument");
123         return;
124     }
125     Dimension colGap;
126     if (!ParseJsDimensionVp(info[0], colGap) || colGap.Value() < 0) {
127         colGap.SetValue(0.0);
128     }
129     WaterFlowModel::GetInstance()->SetColumnsGap(colGap);
130 }
131 
SetRowsGap(const JSCallbackInfo & info)132 void JSWaterFlow::SetRowsGap(const JSCallbackInfo& info)
133 {
134     if (info.Length() < 1) {
135         LOGW("Arg is wrong, it is supposed to have at least 1 argument");
136         return;
137     }
138     Dimension rowGap;
139     if (!ParseJsDimensionVp(info[0], rowGap) || rowGap.Value() < 0) {
140         rowGap.SetValue(0.0);
141     }
142     WaterFlowModel::GetInstance()->SetRowsGap(rowGap);
143 }
144 
SetLayoutDirection(const JSCallbackInfo & info)145 void JSWaterFlow::SetLayoutDirection(const JSCallbackInfo& info)
146 {
147     if (info.Length() < 1) {
148         LOGE("The arg is wrong, it is supposed to have at least 1 arguments");
149         return;
150     }
151     auto value = static_cast<int32_t>(FlexDirection::COLUMN);
152     auto jsValue = info[0];
153     if (!jsValue->IsUndefined()) {
154         ParseJsInteger<int32_t>(jsValue, value);
155     }
156     if (value >= 0 && value < static_cast<int32_t>(LAYOUT_DIRECTION.size())) {
157         WaterFlowModel::GetInstance()->SetLayoutDirection(LAYOUT_DIRECTION[value]);
158     } else {
159         WaterFlowModel::GetInstance()->SetLayoutDirection(FlexDirection::COLUMN);
160     }
161 }
162 
SetColumnsTemplate(const std::string & value)163 void JSWaterFlow::SetColumnsTemplate(const std::string& value)
164 {
165     WaterFlowModel::GetInstance()->SetColumnsTemplate(value);
166 }
167 
SetItemConstraintSize(const JSCallbackInfo & info)168 void JSWaterFlow::SetItemConstraintSize(const JSCallbackInfo& info)
169 {
170     if (info.Length() < 1 || !info[0]->IsObject()) {
171         LOGI("waterflow create error, info is invalid");
172         return;
173     }
174 
175     JSRef<JSObject> sizeObj = JSRef<JSObject>::Cast(info[0]);
176 
177     JSRef<JSVal> minWidthValue = sizeObj->GetProperty("minWidth");
178     Dimension minWidth;
179     if (ParseJsDimensionVp(minWidthValue, minWidth)) {
180         WaterFlowModel::GetInstance()->SetItemMinWidth(minWidth);
181     }
182 
183     JSRef<JSVal> maxWidthValue = sizeObj->GetProperty("maxWidth");
184     Dimension maxWidth;
185     if (ParseJsDimensionVp(maxWidthValue, maxWidth)) {
186         WaterFlowModel::GetInstance()->SetItemMaxWidth(maxWidth);
187     }
188 
189     JSRef<JSVal> minHeightValue = sizeObj->GetProperty("minHeight");
190     Dimension minHeight;
191     if (ParseJsDimensionVp(minHeightValue, minHeight)) {
192         WaterFlowModel::GetInstance()->SetItemMinHeight(minHeight);
193     }
194 
195     JSRef<JSVal> maxHeightValue = sizeObj->GetProperty("maxHeight");
196     Dimension maxHeight;
197     if (ParseJsDimensionVp(maxHeightValue, maxHeight)) {
198         WaterFlowModel::GetInstance()->SetItemMaxHeight(maxHeight);
199     }
200 }
201 
SetRowsTemplate(const std::string & value)202 void JSWaterFlow::SetRowsTemplate(const std::string& value)
203 {
204     WaterFlowModel::GetInstance()->SetRowsTemplate(value);
205 }
206 
ReachStartCallback(const JSCallbackInfo & args)207 void JSWaterFlow::ReachStartCallback(const JSCallbackInfo& args)
208 {
209     if (args[0]->IsFunction()) {
210         auto onReachStart = [execCtx = args.GetExecutionContext(), func = JSRef<JSFunc>::Cast(args[0])]() {
211             func->Call(JSRef<JSObject>());
212             return;
213         };
214         WaterFlowModel::GetInstance()->SetOnReachStart(std::move(onReachStart));
215     }
216     args.ReturnSelf();
217 }
218 
ReachEndCallback(const JSCallbackInfo & args)219 void JSWaterFlow::ReachEndCallback(const JSCallbackInfo& args)
220 {
221     if (args[0]->IsFunction()) {
222         auto onReachEnd = [execCtx = args.GetExecutionContext(), func = JSRef<JSFunc>::Cast(args[0])]() {
223             func->Call(JSRef<JSObject>());
224             return;
225         };
226         WaterFlowModel::GetInstance()->SetOnReachEnd(std::move(onReachEnd));
227     }
228     args.ReturnSelf();
229 }
230 } // namespace OHOS::Ace::Framework
231