• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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