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