• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2024 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 <string>
17 
18 #include "base/memory/referenced.h"
19 #include "core/components_ng/syntax/repeat_model_ng.h"
20 #include "bridge/declarative_frontend/jsview/js_repeat.h"
21 #include "bridge/declarative_frontend/jsview/js_view_common_def.h"
22 
23 
24 namespace OHOS::Ace {
GetInstance()25 RepeatModel* RepeatModel::GetInstance()
26 {
27     static NG::RepeatModelNG instance;
28     return &instance;
29 }
30 } // namespace OHOS::Ace
31 
32 
33 namespace OHOS::Ace::Framework {
34 
StartRender()35 void JSRepeat::StartRender()
36 {
37     RepeatModel::GetInstance()->StartRender();
38 }
39 
FinishRender(const JSCallbackInfo & info)40 void JSRepeat::FinishRender(const JSCallbackInfo& info)
41 {
42     std::list<int32_t> removedElmtIds;
43 
44     if ((info.Length() != 1) || !info[0]->IsArray()) {
45         TAG_LOGW(AceLogTag::ACE_REPEAT, "Invalid arguments for Repeat.FinishRender");
46         return;
47     }
48     RepeatModel::GetInstance()->FinishRender(removedElmtIds);
49 
50     if (!removedElmtIds.size()) {
51         return;
52     }
53 
54     // convert list of removed elmtIds: std::list to JSArray<number>
55     JSRef<JSArray> jsArr = JSRef<JSArray>::Cast(info[0]);
56     size_t index = jsArr->Length();
57     for (const auto& rmElmtId : removedElmtIds) {
58         jsArr->SetValueAt(index++, JSRef<JSVal>::Make(ToJSValue(rmElmtId)));
59     }
60 }
61 
62 // signature is
63 // fromIndex: number
MoveChild(const JSCallbackInfo & info)64 void JSRepeat::MoveChild(const JSCallbackInfo& info)
65 {
66     if ((info.Length() != 1) || !info[0]->IsNumber()) {
67         TAG_LOGW(AceLogTag::ACE_REPEAT, "Invalid arguments for Repeat.MoveChild");
68         return;
69     }
70 
71     const auto fromIndex = info[0]->ToNumber<uint32_t>();
72     RepeatModel::GetInstance()->MoveChild(fromIndex);
73 }
74 
75 // signature is
76 // id: string
77 // parentView? : JSView
CreateNewChildStart(const JSCallbackInfo & info)78 void JSRepeat::CreateNewChildStart(const JSCallbackInfo& info)
79 {
80     if ((info.Length() < 1) || !info[0]->IsString()) {
81         TAG_LOGW(AceLogTag::ACE_REPEAT, "Invalid arguments for Repeat.CreateNewChildStart");
82         return;
83     }
84 
85     const auto key = info[0]->ToString();
86     RepeatModel::GetInstance()->CreateNewChildStart(key);
87 }
88 
89 // signature is
90 // id: string
91 // parentView? : JSView
CreateNewChildFinish(const JSCallbackInfo & info)92 void JSRepeat::CreateNewChildFinish(const JSCallbackInfo& info)
93 {
94     if ((info.Length() < 1) || !info[0]->IsString()) {
95         TAG_LOGW(AceLogTag::ACE_REPEAT, "Invalid arguments for Repeat.CreateNewChildFinish");
96         return;
97     }
98 
99     const auto key = info[0]->ToString();
100     RepeatModel::GetInstance()->CreateNewChildFinish(key);
101 }
102 
OnMove(const JSCallbackInfo & info)103 void JSRepeat::OnMove(const JSCallbackInfo& info)
104 {
105     if (info[0]->IsFunction()) {
106         auto context = info.GetExecutionContext();
107         auto onMove = [execCtx = context, func = JSRef<JSFunc>::Cast(info[0])](int32_t from, int32_t to) {
108             auto params = ConvertToJSValues(from, to);
109             func->Call(JSRef<JSObject>(), params.size(), params.data());
110         };
111         RepeatModel::GetInstance()->OnMove(std::move(onMove));
112         if (info.Length() > 1 && info[1]->IsObject()) {
113             JsParseItemDragEventHandler(context, info[1]);
114         } else {
115             RepeatModel::GetInstance()->SetItemDragHandler(nullptr, nullptr, nullptr, nullptr);
116         }
117     } else {
118         RepeatModel::GetInstance()->OnMove(nullptr);
119         RepeatModel::GetInstance()->SetItemDragHandler(nullptr, nullptr, nullptr, nullptr);
120     }
121 }
122 
AfterAddChild()123 void JSRepeat::AfterAddChild()
124 {
125     RepeatModel::GetInstance()->AfterAddChild();
126 }
127 
JsParseItemDragEventHandler(const JsiExecutionContext & context,const JSRef<JSObject> & itemDragEventObj)128 void JSRepeat::JsParseItemDragEventHandler(
129     const JsiExecutionContext& context, const JSRef<JSObject>& itemDragEventObj)
130 {
131     auto onLongPress = itemDragEventObj->GetProperty("onLongPress");
132     std::function<void(int32_t)> onLongPressCallback;
133     if (onLongPress->IsFunction()) {
134         onLongPressCallback = [execCtx = context, func = JSRef<JSFunc>::Cast(onLongPress)](int32_t index) {
135             auto params = ConvertToJSValues(index);
136             func->Call(JSRef<JSObject>(), params.size(), params.data());
137         };
138     }
139 
140     auto onDragStart = itemDragEventObj->GetProperty("onDragStart");
141     std::function<void(int32_t)> onDragStartCallback;
142     if (onDragStart->IsFunction()) {
143         onDragStartCallback = [execCtx = context, func = JSRef<JSFunc>::Cast(onDragStart)](int32_t index) {
144             auto params = ConvertToJSValues(index);
145             func->Call(JSRef<JSObject>(), params.size(), params.data());
146         };
147     }
148 
149     auto onMoveThrough = itemDragEventObj->GetProperty("onMoveThrough");
150     std::function<void(int32_t, int32_t)> onMoveThroughCallback;
151     if (onMoveThrough->IsFunction()) {
152         onMoveThroughCallback = [execCtx = context, func = JSRef<JSFunc>::Cast(onMoveThrough)](
153                                     int32_t from, int32_t to) {
154             auto params = ConvertToJSValues(from, to);
155             func->Call(JSRef<JSObject>(), params.size(), params.data());
156         };
157     }
158 
159     auto onDrop = itemDragEventObj->GetProperty("onDrop");
160     std::function<void(int32_t)> onDropCallback;
161     if (onDrop->IsFunction()) {
162         onDropCallback = [execCtx = context, func = JSRef<JSFunc>::Cast(onDrop)](int32_t index) {
163             auto params = ConvertToJSValues(index);
164             func->Call(JSRef<JSObject>(), params.size(), params.data());
165         };
166     }
167     RepeatModel::GetInstance()->SetItemDragHandler(std::move(onLongPressCallback), std::move(onDragStartCallback),
168         std::move(onMoveThroughCallback), std::move(onDropCallback));
169 }
170 
JSBind(BindingTarget globalObj)171 void JSRepeat::JSBind(BindingTarget globalObj)
172 {
173     JSClass<JSRepeat>::Declare("RepeatNative");
174     JSClass<JSRepeat>::StaticMethod("startRender", &JSRepeat::StartRender);
175     JSClass<JSRepeat>::StaticMethod("finishRender", &JSRepeat::FinishRender);
176     JSClass<JSRepeat>::StaticMethod("moveChild", &JSRepeat::MoveChild);
177     JSClass<JSRepeat>::StaticMethod("createNewChildStart", &JSRepeat::CreateNewChildStart);
178     JSClass<JSRepeat>::StaticMethod("createNewChildFinish", &JSRepeat::CreateNewChildFinish);
179     JSClass<JSRepeat>::StaticMethod("afterAddChild", &JSRepeat::AfterAddChild);
180     JSClass<JSRepeat>::StaticMethod("onMove", &JSRepeat::OnMove);
181     JSClass<JSRepeat>::Bind<>(globalObj);
182 }
183 
184 } // namespace OHOS::Ace::Framework
185