1 /*
2 * Copyright (c) 2021-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 "bridge/declarative_frontend/jsview/js_grid.h"
17 #if !defined(PREVIEW) && defined(OHOS_PLATFORM)
18 #include "interfaces/inner_api/ui_session/ui_session_manager.h"
19 #endif
20
21 #include "base/log/ace_scoring_log.h"
22 #include "base/utils/utils.h"
23 #include "bridge/declarative_frontend/engine/functions/js_drag_function.h"
24 #include "bridge/declarative_frontend/jsview/js_interactable_view.h"
25 #include "bridge/declarative_frontend/jsview/js_scrollable.h"
26 #include "bridge/declarative_frontend/jsview/js_scroller.h"
27 #include "bridge/declarative_frontend/jsview/js_view_common_def.h"
28 #include "bridge/declarative_frontend/jsview/models/grid_model_impl.h"
29 #include "core/common/ace_application_info.h"
30 #include "core/common/container.h"
31 #include "core/components_ng/base/view_stack_processor.h"
32 #include "core/components_ng/pattern/grid/grid_model_ng.h"
33
34 namespace OHOS::Ace {
35
36 std::unique_ptr<GridModel> GridModel::instance_ = nullptr;
37 std::mutex GridModel::mutex_;
38
GetInstance()39 GridModel* GridModel::GetInstance()
40 {
41 if (!instance_) {
42 std::lock_guard<std::mutex> lock(mutex_);
43 if (!instance_) {
44 #ifdef NG_BUILD
45 instance_.reset(new NG::GridModelNG());
46 #else
47 if (Container::IsCurrentUseNewPipeline()) {
48 instance_.reset(new NG::GridModelNG());
49 } else {
50 instance_.reset(new Framework::GridModelImpl());
51 }
52 #endif
53 }
54 }
55 return instance_.get();
56 }
57
58 } // namespace OHOS::Ace
59
60 namespace OHOS::Ace::Framework {
61 namespace {
62 const std::vector<DisplayMode> DISPLAY_MODE = { DisplayMode::OFF, DisplayMode::AUTO, DisplayMode::ON };
63 const std::vector<EdgeEffect> EDGE_EFFECT = { EdgeEffect::SPRING, EdgeEffect::FADE, EdgeEffect::NONE };
64 const std::vector<FlexDirection> LAYOUT_DIRECTION = { FlexDirection::ROW, FlexDirection::COLUMN,
65 FlexDirection::ROW_REVERSE, FlexDirection::COLUMN_REVERSE };
66 const size_t GRID_ITEM_SIZE_RESULT_LENGTH = 2;
67 const size_t GRID_ITEM_RECT_RESULT_LENGTH = 4;
68
ParseGridItemSize(const JSRef<JSVal> & value,GridItemSize & gridItemSize)69 void ParseGridItemSize(const JSRef<JSVal>& value, GridItemSize& gridItemSize)
70 {
71 if (value->IsArray()) {
72 JSRef<JSArray> array = JSRef<JSArray>::Cast(value);
73 auto length = array->Length();
74 if (length != GRID_ITEM_SIZE_RESULT_LENGTH) {
75 return;
76 }
77 JSRef<JSVal> rows = array->GetValueAt(0);
78 if (rows->IsNumber()) {
79 gridItemSize.rows = rows->ToNumber<int32_t>();
80 }
81 JSRef<JSVal> columns = array->GetValueAt(1);
82 if (columns->IsNumber()) {
83 gridItemSize.columns = columns->ToNumber<int32_t>();
84 }
85 }
86 }
87
ParseGridItemRect(const JSRef<JSVal> & value,GridItemRect & gridItemRect)88 void ParseGridItemRect(const JSRef<JSVal>& value, GridItemRect& gridItemRect)
89 {
90 if (value->IsArray()) {
91 JSRef<JSArray> array = JSRef<JSArray>::Cast(value);
92 auto length = array->Length();
93 if (length != GRID_ITEM_RECT_RESULT_LENGTH) {
94 return;
95 }
96 JSRef<JSVal> rowStart = array->GetValueAt(GridItemRect::ROW_START);
97 if (rowStart->IsNumber()) {
98 gridItemRect.rowStart = rowStart->ToNumber<int32_t>();
99 }
100 JSRef<JSVal> rowSpan = array->GetValueAt(GridItemRect::ROW_SPAN);
101 if (rowSpan->IsNumber()) {
102 gridItemRect.rowSpan = rowSpan->ToNumber<int32_t>();
103 }
104 JSRef<JSVal> columnStart = array->GetValueAt(GridItemRect::COLUMN_START);
105 if (columnStart->IsNumber()) {
106 gridItemRect.columnStart = columnStart->ToNumber<int32_t>();
107 }
108 JSRef<JSVal> columnSpan = array->GetValueAt(GridItemRect::COLUMN_SPAN);
109 if (columnSpan->IsNumber()) {
110 gridItemRect.columnSpan = columnSpan->ToNumber<int32_t>();
111 }
112 }
113 }
114
ParseGetGridItemSize(const JSCallbackInfo & info,JSRef<JSObject> & obj,GridLayoutOptions & option)115 void ParseGetGridItemSize(const JSCallbackInfo& info, JSRef<JSObject>& obj, GridLayoutOptions& option)
116 {
117 auto getSizeByIndex = obj->GetProperty("onGetIrregularSizeByIndex");
118 if (getSizeByIndex->IsFunction()) {
119 auto onGetIrregularSizeByIndex = [execCtx = info.GetExecutionContext(),
120 func = AceType::MakeRefPtr<JsFunction>(JSRef<JSObject>(),
121 JSRef<JSFunc>::Cast(getSizeByIndex))](int32_t index) {
122 JAVASCRIPT_EXECUTION_SCOPE(execCtx);
123 GridItemSize gridItemSize;
124 JSRef<JSVal> itemIndex = JSRef<JSVal>::Make(ToJSValue(index));
125 auto result = func->ExecuteJS(1, &itemIndex);
126 if (!result->IsArray()) {
127 return gridItemSize;
128 }
129 ParseGridItemSize(result, gridItemSize);
130 return gridItemSize;
131 };
132 option.getSizeByIndex = std::move(onGetIrregularSizeByIndex);
133 }
134 }
135
ParseGetGridItemRect(const JSCallbackInfo & info,JSRef<JSObject> & obj,GridLayoutOptions & option)136 void ParseGetGridItemRect(const JSCallbackInfo& info, JSRef<JSObject>& obj, GridLayoutOptions& option)
137 {
138 auto getRectByIndex = obj->GetProperty("onGetRectByIndex");
139 if (getRectByIndex->IsFunction()) {
140 auto onGetRectByIndex = [execCtx = info.GetExecutionContext(),
141 func = AceType::MakeRefPtr<JsFunction>(
142 JSRef<JSObject>(), JSRef<JSFunc>::Cast(getRectByIndex))](int32_t index) {
143 JAVASCRIPT_EXECUTION_SCOPE(execCtx);
144 GridItemRect gridItemRect;
145 JSRef<JSVal> itemIndex = JSRef<JSVal>::Make(ToJSValue(index));
146 auto result = func->ExecuteJS(1, &itemIndex);
147 if (!result->IsArray()) {
148 return gridItemRect;
149 }
150 ParseGridItemRect(result, gridItemRect);
151 return gridItemRect;
152 };
153 option.getRectByIndex = std::move(onGetRectByIndex);
154 }
155 }
156
SetGridLayoutOptions(const JSCallbackInfo & info)157 void SetGridLayoutOptions(const JSCallbackInfo& info)
158 {
159 if (!(info.Length() > 1 && info[1]->IsObject())) {
160 return;
161 }
162 GridLayoutOptions option;
163 auto obj = JSRef<JSObject>::Cast(info[1]);
164 auto value = obj->GetProperty("regularSize");
165 ParseGridItemSize(value, option.regularSize);
166
167 // only support regularSize(1, 1)
168 option.regularSize.rows = 1;
169 option.regularSize.columns = 1;
170
171 auto indexes = obj->GetProperty("irregularIndexes");
172 if (indexes->IsArray()) {
173 JSRef<JSArray> array = JSRef<JSArray>::Cast(indexes);
174 auto length = array->Length();
175 for (size_t i = 0; i < length; i++) {
176 JSRef<JSVal> index = array->GetValueAt(i);
177 if (!index->IsNumber()) {
178 continue;
179 }
180 auto indexNum = index->ToNumber<int32_t>();
181 if (indexNum >= 0) {
182 option.irregularIndexes.emplace(indexNum);
183 }
184 }
185 }
186
187 ParseGetGridItemSize(info, obj, option);
188 ParseGetGridItemRect(info, obj, option);
189
190 GridModel::GetInstance()->SetLayoutOptions(option);
191 }
192
JsOnScrollToIndex(const JSCallbackInfo & info)193 void JsOnScrollToIndex(const JSCallbackInfo& info)
194 {
195 if (!info[0]->IsFunction()) {
196 return;
197 }
198
199 auto onScrollIndex = [execCtx = info.GetExecutionContext(), func = JSRef<JSFunc>::Cast(info[0])](
200 const BaseEventInfo* event) {
201 JAVASCRIPT_EXECUTION_SCOPE(execCtx);
202 const auto* eventInfo = TypeInfoHelper::DynamicCast<V2::GridEventInfo>(event);
203 if (!eventInfo) {
204 return;
205 }
206 auto params = ConvertToJSValues(eventInfo->GetScrollIndex());
207 func->Call(JSRef<JSObject>(), static_cast<int>(params.size()), params.data());
208 };
209 GridModel::GetInstance()->SetOnScrollToIndex(std::move(onScrollIndex));
210 }
211 } // namespace
212
Create(const JSCallbackInfo & info)213 void JSGrid::Create(const JSCallbackInfo& info)
214 {
215 RefPtr<ScrollControllerBase> positionController;
216 RefPtr<ScrollProxy> scrollBarProxy;
217 if (info.Length() > 0 && info[0]->IsObject()) {
218 JSScroller* jsScroller = JSRef<JSObject>::Cast(info[0])->Unwrap<JSScroller>();
219 if (jsScroller) {
220 jsScroller->SetInstanceId(Container::CurrentId());
221 positionController = GridModel::GetInstance()->CreatePositionController();
222 jsScroller->SetController(positionController);
223
224 // Init scroll bar proxy.
225 scrollBarProxy = jsScroller->GetScrollBarProxy();
226 if (!scrollBarProxy) {
227 scrollBarProxy = GridModel::GetInstance()->CreateScrollBarProxy();
228 jsScroller->SetScrollBarProxy(scrollBarProxy);
229 }
230 }
231 }
232 GridModel::GetInstance()->Create(positionController, scrollBarProxy);
233
234 SetGridLayoutOptions(info);
235 }
236
PopGrid(const JSCallbackInfo &)237 void JSGrid::PopGrid(const JSCallbackInfo& /* info */)
238 {
239 GridModel::GetInstance()->Pop();
240 }
241
UseProxy(const JSCallbackInfo & args)242 void JSGrid::UseProxy(const JSCallbackInfo& args)
243 {
244 #ifdef NG_BUILD
245 args.SetReturnValue(JSRef<JSVal>::Make(ToJSValue(false)));
246 #else
247 auto parentGrid = ViewStackProcessor::GetInstance()->GetTopGrid();
248
249 // return true if code path for GridElement and its children will rely on
250 // ElementProxy. Only in this case shallow render functionality can be used
251 // see also GridLayoutComponent::CreateElement() and GridItemElementProxy class
252 args.SetReturnValue(JSRef<JSVal>::Make(ToJSValue(parentGrid ? !parentGrid->UseNonProxiedCodePath() : false)));
253 #endif
254 }
255
SetColumnsTemplate(const std::string & value)256 void JSGrid::SetColumnsTemplate(const std::string& value)
257 {
258 GridModel::GetInstance()->SetColumnsTemplate(value);
259 }
260
SetRowsTemplate(const std::string & value)261 void JSGrid::SetRowsTemplate(const std::string& value)
262 {
263 GridModel::GetInstance()->SetRowsTemplate(value);
264 }
265
SetColumnsGap(const JSCallbackInfo & info)266 void JSGrid::SetColumnsGap(const JSCallbackInfo& info)
267 {
268 if (info.Length() < 1) {
269 return;
270 }
271 CalcDimension colGap;
272
273 if (!ParseJsDimensionVp(info[0], colGap) || colGap.Value() < 0) {
274 colGap.SetValue(0.0);
275 }
276
277 GridModel::GetInstance()->SetColumnsGap(colGap);
278 }
279
SetRowsGap(const JSCallbackInfo & info)280 void JSGrid::SetRowsGap(const JSCallbackInfo& info)
281 {
282 if (info.Length() < 1) {
283 return;
284 }
285 CalcDimension rowGap;
286
287 if (!ParseJsDimensionVp(info[0], rowGap) || rowGap.Value() < 0) {
288 rowGap.SetValue(0.0);
289 }
290
291 GridModel::GetInstance()->SetRowsGap(rowGap);
292 }
293
JsGridHeight(const JSCallbackInfo & info)294 void JSGrid::JsGridHeight(const JSCallbackInfo& info)
295 {
296 if (info.Length() < 1) {
297 return;
298 }
299
300 CalcDimension value;
301 if (!ParseJsDimensionVp(info[0], value)) {
302 return;
303 }
304 if (LessNotEqual(value.Value(), 0.0)) {
305 value.SetValue(0.0);
306 }
307 GridModel::GetInstance()->SetGridHeight(value);
308 }
309
JsOnScrollBarUpdate(const JSCallbackInfo & info)310 void JSGrid::JsOnScrollBarUpdate(const JSCallbackInfo& info)
311 {
312 if (!info[0]->IsFunction()) {
313 return;
314 }
315 auto onScrollBarUpdate = [execCtx = info.GetExecutionContext(),
316 func = AceType::MakeRefPtr<JsFunction>(JSRef<JSObject>(),
317 JSRef<JSFunc>::Cast(info[0]))](int32_t index, const Dimension& offset) {
318 JSRef<JSVal> itemIndex = JSRef<JSVal>::Make(ToJSValue(index));
319 JSRef<JSVal> itemOffset = ConvertToJSValue(offset);
320 JSRef<JSVal> params[2] = { itemIndex, itemOffset };
321 auto result = func->ExecuteJS(2, params);
322 if (result->IsObject()) {
323 JSRef<JSObject> obj = JSRef<JSObject>::Cast(result);
324
325 Dimension totalOffset_;
326 Dimension totalLength_;
327 if (!ConvertFromJSValue(obj->GetProperty("totalOffset"), totalOffset_) ||
328 !ConvertFromJSValue(obj->GetProperty("totalLength"), totalLength_)) {
329 return std::pair<float, float>(0, 0);
330 } else {
331 return std::pair<float, float>(totalOffset_.ConvertToPx(), totalLength_.ConvertToPx());
332 }
333 }
334 return std::pair<float, float>(0, 0);
335 };
336 GridModel::GetInstance()->SetOnScrollBarUpdate(std::move(onScrollBarUpdate));
337 }
338
SetScrollEnabled(const JSCallbackInfo & args)339 void JSGrid::SetScrollEnabled(const JSCallbackInfo& args)
340 {
341 GridModel::GetInstance()->SetScrollEnabled(args[0]->IsBoolean() ? args[0]->ToBoolean() : true);
342 }
343
JSBind(BindingTarget globalObj)344 void JSGrid::JSBind(BindingTarget globalObj)
345 {
346 JSClass<JSGrid>::Declare("Grid");
347
348 MethodOptions opt = MethodOptions::NONE;
349 JSClass<JSGrid>::StaticMethod("create", &JSGrid::Create, opt);
350 JSClass<JSGrid>::StaticMethod("pop", &JSGrid::PopGrid, opt);
351 JSClass<JSGrid>::StaticMethod("willUseProxy", &JSGrid::UseProxy, opt);
352 JSClass<JSGrid>::StaticMethod("columnsTemplate", &JSGrid::SetColumnsTemplate, opt);
353 JSClass<JSGrid>::StaticMethod("rowsTemplate", &JSGrid::SetRowsTemplate, opt);
354 JSClass<JSGrid>::StaticMethod("columnsGap", &JSGrid::SetColumnsGap, opt);
355 JSClass<JSGrid>::StaticMethod("rowsGap", &JSGrid::SetRowsGap, opt);
356 JSClass<JSGrid>::StaticMethod("onClick", &JSInteractableView::JsOnClick);
357 JSClass<JSGrid>::StaticMethod("onAttach", &JSInteractableView::JsOnAttach);
358 JSClass<JSGrid>::StaticMethod("onAppear", &JSInteractableView::JsOnAppear);
359 JSClass<JSGrid>::StaticMethod("onDetach", &JSInteractableView::JsOnDetach);
360 JSClass<JSGrid>::StaticMethod("onDisAppear", &JSInteractableView::JsOnDisAppear);
361 JSClass<JSGrid>::StaticMethod("onTouch", &JSInteractableView::JsOnTouch);
362 JSClass<JSGrid>::StaticMethod("onHover", &JSInteractableView::JsOnHover);
363 JSClass<JSGrid>::StaticMethod("onKeyEvent", &JSInteractableView::JsOnKey);
364 JSClass<JSGrid>::StaticMethod("onDeleteEvent", &JSInteractableView::JsOnDelete);
365 JSClass<JSGrid>::StaticMethod("scrollBar", &JSGrid::SetScrollBar, opt);
366 JSClass<JSGrid>::StaticMethod("scrollBarWidth", &JSGrid::SetScrollBarWidth, opt);
367 JSClass<JSGrid>::StaticMethod("scrollBarColor", &JSGrid::SetScrollBarColor, opt);
368 JSClass<JSGrid>::StaticMethod("clip", &JSScrollable::JsClip);
369
370 JSClass<JSGrid>::StaticMethod("onScrollBarUpdate", &JSGrid::JsOnScrollBarUpdate);
371 JSClass<JSGrid>::StaticMethod("cachedCount", &JSGrid::SetCachedCount);
372 JSClass<JSGrid>::StaticMethod("editMode", &JSGrid::SetEditMode, opt);
373 JSClass<JSGrid>::StaticMethod("multiSelectable", &JSGrid::SetMultiSelectable, opt);
374 JSClass<JSGrid>::StaticMethod("maxCount", &JSGrid::SetMaxCount, opt);
375 JSClass<JSGrid>::StaticMethod("minCount", &JSGrid::SetMinCount, opt);
376 JSClass<JSGrid>::StaticMethod("cellLength", &JSGrid::CellLength, opt);
377 JSClass<JSGrid>::StaticMethod("layoutDirection", &JSGrid::SetLayoutDirection, opt);
378 JSClass<JSGrid>::StaticMethod("dragAnimation", &JSGrid::SetDragAnimation, opt);
379 JSClass<JSGrid>::StaticMethod("edgeEffect", &JSGrid::SetEdgeEffect, opt);
380 JSClass<JSGrid>::StaticMethod("direction", &JSGrid::SetDirection, opt);
381 JSClass<JSGrid>::StaticMethod("supportAnimation", &JSGrid::SetSupportAnimation, opt);
382 JSClass<JSGrid>::StaticMethod("onItemDragEnter", &JSGrid::JsOnGridDragEnter);
383 JSClass<JSGrid>::StaticMethod("onItemDragMove", &JSGrid::JsOnGridDragMove);
384 JSClass<JSGrid>::StaticMethod("onItemDragLeave", &JSGrid::JsOnGridDragLeave);
385 JSClass<JSGrid>::StaticMethod("onItemDragStart", &JSGrid::JsOnGridDragStart);
386 JSClass<JSGrid>::StaticMethod("height", &JSGrid::JsGridHeight);
387 JSClass<JSGrid>::StaticMethod("onItemDrop", &JSGrid::JsOnGridDrop);
388 JSClass<JSGrid>::StaticMethod("remoteMessage", &JSInteractableView::JsCommonRemoteMessage);
389 JSClass<JSGrid>::StaticMethod("nestedScroll", &JSGrid::SetNestedScroll);
390 JSClass<JSGrid>::StaticMethod("enableScrollInteraction", &JSGrid::SetScrollEnabled);
391 JSClass<JSGrid>::StaticMethod("friction", &JSGrid::SetFriction);
392 JSClass<JSGrid>::StaticMethod("alignItems", &JSGrid::SetAlignItems);
393
394 JSClass<JSGrid>::StaticMethod("onScroll", &JSGrid::JsOnScroll);
395 JSClass<JSGrid>::StaticMethod("onReachStart", &JSGrid::JsOnReachStart);
396 JSClass<JSGrid>::StaticMethod("onReachEnd", &JSGrid::JsOnReachEnd);
397 JSClass<JSGrid>::StaticMethod("onScrollStart", &JSGrid::JsOnScrollStart);
398 JSClass<JSGrid>::StaticMethod("onScrollStop", &JSGrid::JsOnScrollStop);
399 JSClass<JSGrid>::StaticMethod("onScrollIndex", &JSGrid::JsOnScrollIndex);
400 JSClass<JSGrid>::StaticMethod("onScrollFrameBegin", &JSGrid::JsOnScrollFrameBegin);
401
402 JSClass<JSGrid>::InheritAndBind<JSScrollableBase>(globalObj);
403 }
404
SetScrollBar(const JSCallbackInfo & info)405 void JSGrid::SetScrollBar(const JSCallbackInfo& info)
406 {
407 auto displayMode = JSScrollable::ParseDisplayMode(info, GridModel::GetInstance()->GetDisplayMode());
408 GridModel::GetInstance()->SetScrollBarMode(displayMode);
409 }
410
SetScrollBarColor(const JSCallbackInfo & info)411 void JSGrid::SetScrollBarColor(const JSCallbackInfo& info)
412 {
413 auto scrollBarColor = JSScrollable::ParseBarColor(info);
414 if (!scrollBarColor.empty()) {
415 GridModel::GetInstance()->SetScrollBarColor(scrollBarColor);
416 }
417 }
418
SetScrollBarWidth(const JSCallbackInfo & scrollWidth)419 void JSGrid::SetScrollBarWidth(const JSCallbackInfo& scrollWidth)
420 {
421 auto scrollBarWidth = JSScrollable::ParseBarWidth(scrollWidth);
422 if (!scrollBarWidth.empty()) {
423 GridModel::GetInstance()->SetScrollBarWidth(scrollBarWidth);
424 }
425 }
426
SetCachedCount(const JSCallbackInfo & info)427 void JSGrid::SetCachedCount(const JSCallbackInfo& info)
428 {
429 int32_t cachedCount = 1;
430 auto jsValue = info[0];
431
432 if (!jsValue->IsUndefined() && jsValue->IsNumber()) {
433 cachedCount = jsValue->ToNumber<int32_t>();
434 if (cachedCount < 0) {
435 cachedCount = 1;
436 }
437 }
438 bool show = false;
439 if (info.Length() > 1) {
440 show = info[1]->ToBoolean();
441 }
442 GridModel::GetInstance()->SetCachedCount(cachedCount, show);
443 }
444
SetEditMode(const JSCallbackInfo & info)445 void JSGrid::SetEditMode(const JSCallbackInfo& info)
446 {
447 // undefined means false to EditMode
448 bool editMode = false;
449 if (!info[0]->IsUndefined() && info[0]->IsBoolean()) {
450 ParseJsBool(info[0], editMode);
451 }
452 GridModel::GetInstance()->SetEditable(editMode);
453 }
454
SetMaxCount(const JSCallbackInfo & info)455 void JSGrid::SetMaxCount(const JSCallbackInfo& info)
456 {
457 int32_t maxCount = Infinity<int32_t>();
458 if (!info[0]->IsUndefined() && info[0]->IsNumber()) {
459 ParseJsInt32(info[0], maxCount);
460 if (maxCount < 1) {
461 maxCount = Infinity<int32_t>();
462 }
463 }
464 GridModel::GetInstance()->SetMaxCount(maxCount);
465 }
466
SetMinCount(const JSCallbackInfo & info)467 void JSGrid::SetMinCount(const JSCallbackInfo& info)
468 {
469 int32_t minCount = 1;
470 if (!info[0]->IsUndefined() && info[0]->IsNumber()) {
471 ParseJsInt32(info[0], minCount);
472 if (minCount < 1) {
473 minCount = 1;
474 }
475 }
476 GridModel::GetInstance()->SetMinCount(minCount);
477 }
478
CellLength(int32_t cellLength)479 void JSGrid::CellLength(int32_t cellLength)
480 {
481 GridModel::GetInstance()->SetCellLength(cellLength);
482 }
483
SetSupportAnimation(bool supportAnimation)484 void JSGrid::SetSupportAnimation(bool supportAnimation)
485 {
486 GridModel::GetInstance()->SetSupportAnimation(supportAnimation);
487 }
488
SetDragAnimation(bool value)489 void JSGrid::SetDragAnimation(bool value)
490 {
491 GridModel::GetInstance()->SetSupportDragAnimation(value);
492 }
493
SetEdgeEffect(const JSCallbackInfo & info)494 void JSGrid::SetEdgeEffect(const JSCallbackInfo& info)
495 {
496 auto edgeEffect = EdgeEffect::NONE;
497 if (info.Length() > 0) {
498 edgeEffect = JSScrollable::ParseEdgeEffect(info[0], EdgeEffect::NONE);
499 }
500 auto alwaysEnabled = false;
501 if (info.Length() > 1) {
502 alwaysEnabled = JSScrollable::ParseAlwaysEnable(info[1], false);
503 }
504 GridModel::GetInstance()->SetEdgeEffect(edgeEffect, alwaysEnabled);
505 }
506
SetLayoutDirection(int32_t value)507 void JSGrid::SetLayoutDirection(int32_t value)
508 {
509 if (value < 0 || value >= static_cast<int32_t>(LAYOUT_DIRECTION.size())) {
510 return;
511 }
512 GridModel::GetInstance()->SetLayoutDirection(LAYOUT_DIRECTION[value]);
513 }
514
SetDirection(const std::string & dir)515 void JSGrid::SetDirection(const std::string& dir)
516 {
517 TextDirection direction;
518 if (dir == "Ltr") {
519 direction = TextDirection::LTR;
520 } else if (dir == "Rtl") {
521 direction = TextDirection::RTL;
522 } else {
523 direction = TextDirection::AUTO;
524 }
525 GridModel::GetInstance()->SetIsRTL(direction);
526 }
527
JsOnGridDragEnter(const JSCallbackInfo & info)528 void JSGrid::JsOnGridDragEnter(const JSCallbackInfo& info)
529 {
530 if (!info[0]->IsFunction()) {
531 return;
532 }
533
534 RefPtr<JsDragFunction> jsOnDragEnterFunc = AceType::MakeRefPtr<JsDragFunction>(JSRef<JSFunc>::Cast(info[0]));
535 auto onItemDragEnter = [execCtx = info.GetExecutionContext(), func = std::move(jsOnDragEnterFunc)](
536 const ItemDragInfo& dragInfo) {
537 JAVASCRIPT_EXECUTION_SCOPE_WITH_CHECK(execCtx);
538 ACE_SCORING_EVENT("Grid.onItemDragEnter");
539 func->ItemDragEnterExecute(dragInfo);
540 };
541 GridModel::GetInstance()->SetOnItemDragEnter(std::move(onItemDragEnter));
542 }
543
JsOnGridDragMove(const JSCallbackInfo & info)544 void JSGrid::JsOnGridDragMove(const JSCallbackInfo& info)
545 {
546 if (!info[0]->IsFunction()) {
547 return;
548 }
549
550 RefPtr<JsDragFunction> jsOnDragMoveFunc = AceType::MakeRefPtr<JsDragFunction>(JSRef<JSFunc>::Cast(info[0]));
551 auto onItemDragMove = [execCtx = info.GetExecutionContext(), func = std::move(jsOnDragMoveFunc)](
552 const ItemDragInfo& dragInfo, int32_t itemIndex, int32_t insertIndex) {
553 JAVASCRIPT_EXECUTION_SCOPE_WITH_CHECK(execCtx);
554 ACE_SCORING_EVENT("Grid.onItemDragMove");
555 func->ItemDragMoveExecute(dragInfo, itemIndex, insertIndex);
556 };
557 GridModel::GetInstance()->SetOnItemDragMove(std::move(onItemDragMove));
558 }
559
JsOnGridDragLeave(const JSCallbackInfo & info)560 void JSGrid::JsOnGridDragLeave(const JSCallbackInfo& info)
561 {
562 if (!info[0]->IsFunction()) {
563 return;
564 }
565
566 RefPtr<JsDragFunction> jsOnDragLeaveFunc = AceType::MakeRefPtr<JsDragFunction>(JSRef<JSFunc>::Cast(info[0]));
567 auto onItemDragLeave = [execCtx = info.GetExecutionContext(), func = std::move(jsOnDragLeaveFunc)](
568 const ItemDragInfo& dragInfo, int32_t itemIndex) {
569 JAVASCRIPT_EXECUTION_SCOPE_WITH_CHECK(execCtx);
570 ACE_SCORING_EVENT("Grid.onItemDragLeave");
571 func->ItemDragLeaveExecute(dragInfo, itemIndex);
572 };
573 GridModel::GetInstance()->SetOnItemDragLeave(std::move(onItemDragLeave));
574 }
575
JsOnGridDragStart(const JSCallbackInfo & info)576 void JSGrid::JsOnGridDragStart(const JSCallbackInfo& info)
577 {
578 if (!info[0]->IsFunction()) {
579 return;
580 }
581
582 auto jsOnDragFunc = AceType::MakeRefPtr<JsDragFunction>(JSRef<JSFunc>::Cast(info[0]));
583 WeakPtr<NG::FrameNode> targetNode = AceType::WeakClaim(NG::ViewStackProcessor::GetInstance()->GetMainFrameNode());
584 auto onItemDragStart = [execCtx = info.GetExecutionContext(), func = std::move(jsOnDragFunc), node = targetNode](
585 const ItemDragInfo& dragInfo, int32_t itemIndex) {
586 JAVASCRIPT_EXECUTION_SCOPE_WITH_CHECK(execCtx);
587 ACE_SCORING_EVENT("Grid.onItemDragStart");
588 auto ret = func->ItemDragStartExecute(dragInfo, itemIndex);
589 if (!ret->IsObject()) {
590 return;
591 }
592
593 auto builderObj = JSRef<JSObject>::Cast(ret);
594 auto builder = builderObj->GetProperty("builder");
595 if (!builder->IsFunction()) {
596 return;
597 }
598 auto builderFunc = AceType::MakeRefPtr<JsFunction>(JSRef<JSFunc>::Cast(builder));
599 CHECK_NULL_VOID(builderFunc);
600 PipelineContext::SetCallBackNode(node);
601 builderFunc->Execute();
602 };
603 GridModel::GetInstance()->SetOnItemDragStart(std::move(onItemDragStart));
604 }
605
JsOnGridDrop(const JSCallbackInfo & info)606 void JSGrid::JsOnGridDrop(const JSCallbackInfo& info)
607 {
608 if (!info[0]->IsFunction()) {
609 return;
610 }
611
612 RefPtr<JsDragFunction> jsOnDropFunc = AceType::MakeRefPtr<JsDragFunction>(JSRef<JSFunc>::Cast(info[0]));
613 auto onItemDrop = [execCtx = info.GetExecutionContext(), func = std::move(jsOnDropFunc)](
614 const ItemDragInfo& dragInfo, int32_t itemIndex, int32_t insertIndex, bool isSuccess) {
615 JAVASCRIPT_EXECUTION_SCOPE_WITH_CHECK(execCtx);
616 ACE_SCORING_EVENT("Grid.onItemDrop");
617 func->ItemDropExecute(dragInfo, itemIndex, insertIndex, isSuccess);
618 #if !defined(PREVIEW) && defined(OHOS_PLATFORM)
619 UiSessionManager::GetInstance().ReportComponentChangeEvent("event", "Grid.onItemDrop");
620 #endif
621 };
622 GridModel::GetInstance()->SetOnItemDrop(std::move(onItemDrop));
623 }
624
SetMultiSelectable(bool multiSelectable)625 void JSGrid::SetMultiSelectable(bool multiSelectable)
626 {
627 GridModel::GetInstance()->SetMultiSelectable(multiSelectable);
628 }
629
SetNestedScroll(const JSCallbackInfo & args)630 void JSGrid::SetNestedScroll(const JSCallbackInfo& args)
631 {
632 NestedScrollOptions nestedOpt = {
633 .forward = NestedScrollMode::SELF_ONLY,
634 .backward = NestedScrollMode::SELF_ONLY,
635 };
636 if (args.Length() < 1 || !args[0]->IsObject()) {
637 GridModel::GetInstance()->SetNestedScroll(nestedOpt);
638 return;
639 }
640 JSRef<JSObject> obj = JSRef<JSObject>::Cast(args[0]);
641 int32_t froward = 0;
642 JSViewAbstract::ParseJsInt32(obj->GetProperty("scrollForward"), froward);
643 if (froward < static_cast<int32_t>(NestedScrollMode::SELF_ONLY) ||
644 froward > static_cast<int32_t>(NestedScrollMode::PARALLEL)) {
645 froward = 0;
646 }
647 int32_t backward = 0;
648 JSViewAbstract::ParseJsInt32(obj->GetProperty("scrollBackward"), backward);
649 if (backward < static_cast<int32_t>(NestedScrollMode::SELF_ONLY) ||
650 backward > static_cast<int32_t>(NestedScrollMode::PARALLEL)) {
651 backward = 0;
652 }
653 nestedOpt.forward = static_cast<NestedScrollMode>(froward);
654 nestedOpt.backward = static_cast<NestedScrollMode>(backward);
655 GridModel::GetInstance()->SetNestedScroll(nestedOpt);
656 args.ReturnSelf();
657 }
658
SetFriction(const JSCallbackInfo & info)659 void JSGrid::SetFriction(const JSCallbackInfo& info)
660 {
661 double friction = -1.0;
662 if (!JSViewAbstract::ParseJsDouble(info[0], friction)) {
663 friction = -1.0;
664 }
665 GridModel::GetInstance()->SetFriction(friction);
666 }
667
SetAlignItems(const JSCallbackInfo & info)668 void JSGrid::SetAlignItems(const JSCallbackInfo& info)
669 {
670 if (info.Length() < 1) {
671 GridModel::GetInstance()->SetAlignItems(GridItemAlignment::DEFAULT);
672 return;
673 }
674
675 if (info[0]->IsNumber()) {
676 auto itemAlign = static_cast<GridItemAlignment>(info[0]->ToNumber<int32_t>());
677 if (itemAlign < GridItemAlignment::DEFAULT || itemAlign > GridItemAlignment::STRETCH) {
678 itemAlign = GridItemAlignment::DEFAULT;
679 }
680 GridModel::GetInstance()->SetAlignItems(itemAlign);
681 } else {
682 GridModel::GetInstance()->SetAlignItems(GridItemAlignment::DEFAULT);
683 }
684 }
685
JsOnScroll(const JSCallbackInfo & args)686 void JSGrid::JsOnScroll(const JSCallbackInfo& args)
687 {
688 if (args[0]->IsFunction()) {
689 auto onScroll = [execCtx = args.GetExecutionContext(), func = JSRef<JSFunc>::Cast(args[0])](
690 const CalcDimension& scrollOffset, const ScrollState& scrollState) {
691 auto params = ConvertToJSValues(scrollOffset, scrollState);
692 func->Call(JSRef<JSObject>(), params.size(), params.data());
693 return;
694 };
695 GridModel::GetInstance()->SetOnScroll(std::move(onScroll));
696 }
697 args.ReturnSelf();
698 }
699
JsOnScrollStart(const JSCallbackInfo & args)700 void JSGrid::JsOnScrollStart(const JSCallbackInfo& args)
701 {
702 if (args[0]->IsFunction()) {
703 auto onScrollStart = [execCtx = args.GetExecutionContext(), func = JSRef<JSFunc>::Cast(args[0])]() {
704 func->Call(JSRef<JSObject>());
705 return;
706 };
707 GridModel::GetInstance()->SetOnScrollStart(std::move(onScrollStart));
708 }
709 args.ReturnSelf();
710 }
711
JsOnScrollStop(const JSCallbackInfo & args)712 void JSGrid::JsOnScrollStop(const JSCallbackInfo& args)
713 {
714 if (args[0]->IsFunction()) {
715 auto onScrollStop = [execCtx = args.GetExecutionContext(), func = JSRef<JSFunc>::Cast(args[0])]() {
716 func->Call(JSRef<JSObject>());
717 #if !defined(PREVIEW) && defined(OHOS_PLATFORM)
718 UiSessionManager::GetInstance().ReportComponentChangeEvent("event", "Grid.onScrollStop");
719 #endif
720 return;
721 };
722 GridModel::GetInstance()->SetOnScrollStop(std::move(onScrollStop));
723 }
724 args.ReturnSelf();
725 }
726
JsOnScrollIndex(const JSCallbackInfo & args)727 void JSGrid::JsOnScrollIndex(const JSCallbackInfo& args)
728 {
729 if (Container::LessThanAPIVersion(PlatformVersion::VERSION_TEN)) {
730 JsOnScrollToIndex(args);
731 return;
732 }
733
734 if (args[0]->IsFunction()) {
735 auto onScrollIndex = [execCtx = args.GetExecutionContext(), func = JSRef<JSFunc>::Cast(args[0])](
736 const int32_t first, const int32_t last) {
737 JAVASCRIPT_EXECUTION_SCOPE_WITH_CHECK(execCtx);
738 auto params = ConvertToJSValues(first, last);
739 func->Call(JSRef<JSObject>(), params.size(), params.data());
740 return;
741 };
742 GridModel::GetInstance()->SetOnScrollIndex(std::move(onScrollIndex));
743 }
744 args.ReturnSelf();
745 }
746
JsOnScrollFrameBegin(const JSCallbackInfo & args)747 void JSGrid::JsOnScrollFrameBegin(const JSCallbackInfo& args)
748 {
749 if (args[0]->IsFunction()) {
750 auto onScrollBegin = [execCtx = args.GetExecutionContext(), func = JSRef<JSFunc>::Cast(args[0])](
751 const Dimension& offset, const ScrollState& state) -> ScrollFrameResult {
752 ScrollFrameResult scrollRes { .offset = offset };
753 JAVASCRIPT_EXECUTION_SCOPE_WITH_CHECK(execCtx, scrollRes);
754 auto params = ConvertToJSValues(offset, state);
755 auto result = func->Call(JSRef<JSObject>(), params.size(), params.data());
756 if (result.IsEmpty()) {
757 return scrollRes;
758 }
759
760 if (!result->IsObject()) {
761 return scrollRes;
762 }
763
764 auto resObj = JSRef<JSObject>::Cast(result);
765 auto dxRemainValue = resObj->GetProperty("offsetRemain");
766 if (dxRemainValue->IsNumber()) {
767 scrollRes.offset = Dimension(dxRemainValue->ToNumber<float>(), DimensionUnit::VP);
768 }
769 return scrollRes;
770 };
771 GridModel::GetInstance()->SetOnScrollFrameBegin(std::move(onScrollBegin));
772 }
773 }
774
JsOnReachStart(const JSCallbackInfo & args)775 void JSGrid::JsOnReachStart(const JSCallbackInfo& args)
776 {
777 if (args[0]->IsFunction()) {
778 auto onReachStart = [execCtx = args.GetExecutionContext(), func = JSRef<JSFunc>::Cast(args[0])]() {
779 func->Call(JSRef<JSObject>());
780 #if !defined(PREVIEW) && defined(OHOS_PLATFORM)
781 UiSessionManager::GetInstance().ReportComponentChangeEvent("event", "Grid.onReachStart");
782 #endif
783 return;
784 };
785 GridModel::GetInstance()->SetOnReachStart(std::move(onReachStart));
786 }
787 args.ReturnSelf();
788 }
789
JsOnReachEnd(const JSCallbackInfo & args)790 void JSGrid::JsOnReachEnd(const JSCallbackInfo& args)
791 {
792 if (args[0]->IsFunction()) {
793 auto onReachEnd = [execCtx = args.GetExecutionContext(), func = JSRef<JSFunc>::Cast(args[0])]() {
794 func->Call(JSRef<JSObject>());
795 #if !defined(PREVIEW) && defined(OHOS_PLATFORM)
796 UiSessionManager::GetInstance().ReportComponentChangeEvent("event", "Grid.onReachEnd");
797 #endif
798 return;
799 };
800 GridModel::GetInstance()->SetOnReachEnd(std::move(onReachEnd));
801 }
802 args.ReturnSelf();
803 }
804
805 } // namespace OHOS::Ace::Framework
806