• 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 "core/interfaces/native/node/node_adapter_impl.h"
17 
18 #include "core/components_ng/syntax/lazy_for_each_node.h"
19 
20 struct _ArkUINodeAdapter {
21     OHOS::Ace::RefPtr<OHOS::Ace::NG::NativeLazyForEachBuilder> builder;
22     OHOS::Ace::RefPtr<OHOS::Ace::NG::LazyForEachNode> node;
23 };
24 
25 namespace OHOS::Ace::NG {
26 
RegisterDataChangeListener(const RefPtr<V2::DataChangeListener> & listener)27 void NativeLazyForEachBuilder::RegisterDataChangeListener(const RefPtr<V2::DataChangeListener>& listener)
28 {
29     listener_ = RawPtr(listener);
30     if (!receiver_) {
31         return;
32     }
33     ArkUINodeAdapterEvent event { .type = ON_ATTACH_TO_NODE };
34     event.extraParam = reinterpret_cast<intptr_t>(userData_);
35     auto lazyForEachNode = DynamicCast<LazyForEachNode>(listener);
36     if (lazyForEachNode) {
37         auto parent = lazyForEachNode->GetParent();
38         if (parent) {
39             event.handle = reinterpret_cast<ArkUINodeHandle>(RawPtr(parent));
40         }
41     }
42     receiver_(&event);
43 }
44 
UnregisterDataChangeListener(V2::DataChangeListener * listener)45 void NativeLazyForEachBuilder::UnregisterDataChangeListener(V2::DataChangeListener* listener)
46 {
47     listener_ = nullptr;
48     if (!receiver_) {
49         return;
50     }
51     ArkUINodeAdapterEvent event { .type = ON_DETACH_FROM_NODE };
52     event.extraParam = reinterpret_cast<intptr_t>(userData_);
53     receiver_(&event);
54 }
55 
OnGetTotalCount()56 int32_t NativeLazyForEachBuilder::OnGetTotalCount()
57 {
58     return totalCount_;
59 }
60 
OnGetChildByIndex(int32_t index,std::unordered_map<std::string,LazyForEachCacheChild> & cachedItems)61 LazyForEachChild NativeLazyForEachBuilder::OnGetChildByIndex(
62     int32_t index, std::unordered_map<std::string, LazyForEachCacheChild>& cachedItems)
63 {
64     LazyForEachChild child;
65     if (!receiver_) {
66         return child;
67     }
68     ArkUINodeAdapterEvent getIdevent { .index = index, .idSet = false, .type = ON_GET_NODE_ID, .nodeSet = false };
69     getIdevent.extraParam = reinterpret_cast<intptr_t>(userData_);
70     receiver_(&getIdevent);
71     std::string idStr;
72     if (getIdevent.idSet) {
73         idStr = std::to_string(getIdevent.id);
74     } else {
75         idStr = std::to_string(index);
76     }
77     child.first = idStr;
78     const auto& itemIter = cachedItems.find(idStr);
79     if (itemIter != cachedItems.end()) {
80         child.second = itemIter->second.second;
81         cachedItems.erase(itemIter);
82         // For not change C-API receiver
83         if (needUpdateEvent_) {
84             getIdevent.type = ON_UPDATE_NODE;
85             getIdevent.handle = reinterpret_cast<ArkUINodeHandle>(AceType::RawPtr(child.second));
86             if (!getIdevent.idSet) {
87                 getIdevent.id = index;
88             }
89             receiver_(&getIdevent);
90         }
91         FlushDirtyPropertyNodes(child.second);
92         return child;
93     }
94     ArkUINodeAdapterEvent getChildEvent {
95         .index = index, .id = getIdevent.id, .idSet = false, .type = ON_ADD_NODE_TO_ADAPTER, .nodeSet = false
96     };
97     getChildEvent.extraParam = reinterpret_cast<intptr_t>(userData_);
98     receiver_(&getChildEvent);
99     if (getChildEvent.nodeSet) {
100         child.second = Claim(reinterpret_cast<UINode*>(getChildEvent.handle));
101     }
102     FlushDirtyPropertyNodes(child.second);
103     return child;
104 }
105 
FlushDirtyPropertyNodes(const RefPtr<UINode> & node)106 void NativeLazyForEachBuilder::FlushDirtyPropertyNodes(const RefPtr<UINode>& node)
107 {
108     CHECK_NULL_VOID(node);
109     auto context = node->GetContext();
110     CHECK_NULL_VOID(context);
111     context->FlushDirtyPropertyNodes();
112 }
113 
OnItemDeleted(UINode * node,const std::string & key)114 void NativeLazyForEachBuilder::OnItemDeleted(UINode* node, const std::string& key)
115 {
116     if (!receiver_) {
117         return;
118     }
119     ArkUINodeAdapterEvent event {
120         .id = StringUtils::StringToInt(key), .idSet = false, .type = ON_REMOVE_NODE_FROM_ADAPTER, .nodeSet = false
121     };
122     event.extraParam = reinterpret_cast<intptr_t>(userData_);
123     event.handle = reinterpret_cast<ArkUINodeHandle>(node);
124     receiver_(&event);
125 }
126 
GetAllItem(ArkUINodeHandle ** items,ArkUI_Uint32 * size)127 ArkUI_Int32 NativeLazyForEachBuilder::GetAllItem(ArkUINodeHandle** items, ArkUI_Uint32* size)
128 {
129     std::vector<UINode*> childList;
130     GetAllItems(childList);
131     *size = childList.size();
132     *items = new ArkUINodeHandle[*size];
133     for (uint32_t i = 0; i < *size; i++) {
134         (*items)[i] = reinterpret_cast<ArkUINodeHandle>(childList[i]);
135     }
136     return ERROR_CODE_NO_ERROR;
137 }
138 
UINodeAdapter(ArkUINodeAdapterHandle handle)139 UINodeAdapter::UINodeAdapter(ArkUINodeAdapterHandle handle) : handle_(handle)
140 {
141     CHECK_NULL_VOID(handle_);
142     CHECK_NULL_VOID(handle_->builder);
143     handle_->builder->SetUserData(this);
144     handle_->builder->SetReceiver([](ArkUINodeAdapterEvent* event) {
145         CHECK_NULL_VOID(event);
146         auto adapter = reinterpret_cast<UINodeAdapter*>(event->extraParam);
147         if (adapter != nullptr) {
148             adapter->OnEventReceived(event);
149         }
150     });
151     handle_->builder->SetNeedUpdateEvent(true);
152 }
153 
~UINodeAdapter()154 UINodeAdapter::~UINodeAdapter()
155 {
156     if (handle_ != nullptr) {
157         delete handle_;
158         handle_ = nullptr;
159     }
160 }
161 
OnEventReceived(ArkUINodeAdapterEvent * event)162 void UINodeAdapter::OnEventReceived(ArkUINodeAdapterEvent* event)
163 {
164     switch (event->type) {
165         case ON_ATTACH_TO_NODE:
166             if (attachToNodeFunc_) {
167                 attachToNodeFunc_(event->handle);
168             }
169             break;
170         case ON_DETACH_FROM_NODE:
171             if (detachFromNodeFunc_) {
172                 detachFromNodeFunc_();
173             }
174             break;
175         case ON_GET_NODE_ID:
176             if (getChildIdFunc_) {
177                 auto id = getChildIdFunc_(event->index);
178                 event->idSet = true;
179                 event->id = id;
180             }
181             break;
182         case ON_ADD_NODE_TO_ADAPTER:
183             if (createNewChildFunc_) {
184                 auto handle = createNewChildFunc_(event->index);
185                 event->nodeSet = true;
186                 event->handle = handle;
187             }
188             break;
189         case ON_REMOVE_NODE_FROM_ADAPTER:
190             if (disposeChildFunc_) {
191                 disposeChildFunc_(event->handle, event->id);
192             }
193             break;
194         case ON_UPDATE_NODE:
195             if (updateChildFunc_) {
196                 updateChildFunc_(event->handle, event->id);
197             }
198             break;
199         default:
200             break;
201     }
202 }
203 
SetTotalNodeCount(uint32_t count)204 void UINodeAdapter::SetTotalNodeCount(uint32_t count)
205 {
206     CHECK_NULL_VOID(handle_);
207     CHECK_NULL_VOID(handle_->builder);
208     handle_->builder->SetNodeTotalCount(count);
209 }
210 
GetTotalNodeCount() const211 uint32_t UINodeAdapter::GetTotalNodeCount() const
212 {
213     CHECK_NULL_RETURN(handle_, 0);
214     CHECK_NULL_RETURN(handle_->builder, 0);
215     return handle_->builder->GetNodeTotalCount();
216 }
217 
NotifyItemReloaded()218 void UINodeAdapter::NotifyItemReloaded()
219 {
220     CHECK_NULL_VOID(handle_);
221     CHECK_NULL_VOID(handle_->builder);
222     handle_->builder->NotifyItemReloaded();
223 }
224 
NotifyItemChanged(uint32_t start,uint32_t count)225 void UINodeAdapter::NotifyItemChanged(uint32_t start, uint32_t count)
226 {
227     CHECK_NULL_VOID(handle_);
228     CHECK_NULL_VOID(handle_->builder);
229     handle_->builder->NotifyItemChanged(start, count);
230 }
231 
NotifyItemInserted(uint32_t start,uint32_t count)232 void UINodeAdapter::NotifyItemInserted(uint32_t start, uint32_t count)
233 {
234     CHECK_NULL_VOID(handle_);
235     CHECK_NULL_VOID(handle_->builder);
236     handle_->builder->NotifyItemInserted(start, count);
237 }
238 
NotifyItemMoved(uint32_t from,uint32_t to)239 void UINodeAdapter::NotifyItemMoved(uint32_t from, uint32_t to)
240 {
241     CHECK_NULL_VOID(handle_);
242     CHECK_NULL_VOID(handle_->builder);
243     handle_->builder->NotifyItemMoved(from, to);
244 }
245 
NotifyItemRemoved(uint32_t start,uint32_t count)246 void UINodeAdapter::NotifyItemRemoved(uint32_t start, uint32_t count)
247 {
248     CHECK_NULL_VOID(handle_);
249     CHECK_NULL_VOID(handle_->builder);
250     handle_->builder->NotifyItemRemoved(start, count);
251 }
252 
GetAllItems()253 std::vector<ArkUINodeHandle> UINodeAdapter::GetAllItems()
254 {
255     std::vector<ArkUINodeHandle> items;
256     CHECK_NULL_RETURN(handle_, items);
257     CHECK_NULL_RETURN(handle_->builder, items);
258 
259     ArkUINodeHandle* itemArray = nullptr;
260     uint32_t size = 0;
261     handle_->builder->GetAllItem(&itemArray, &size);
262     for (uint32_t i = 0; i < size; i++) {
263         items.push_back(itemArray[i]);
264     }
265     if (itemArray != nullptr) {
266         delete[] itemArray;
267     }
268     return items;
269 }
270 
271 } // namespace OHOS::Ace::NG
272 
273 namespace OHOS::Ace::NodeAdapter {
274 namespace {
275 
Create()276 ArkUINodeAdapterHandle Create()
277 {
278     auto* adapter = new _ArkUINodeAdapter { .builder = AceType::MakeRefPtr<NG::NativeLazyForEachBuilder>() };
279     adapter->builder->SetHostHandle(adapter);
280     return adapter;
281 }
282 
Dispose(ArkUINodeAdapterHandle handle)283 void Dispose(ArkUINodeAdapterHandle handle)
284 {
285     if (!handle) {
286         return;
287     }
288     if (handle->node) {
289         const auto& parent = handle->node->GetParent();
290         if (parent) {
291             parent->RemoveChild(handle->node);
292         }
293     }
294     if (handle->builder) {
295         handle->builder->SetHostHandle(nullptr);
296     }
297     delete handle;
298 }
299 
SetTotalNodeCount(ArkUINodeAdapterHandle handle,ArkUI_Uint32 size)300 ArkUI_Int32 SetTotalNodeCount(ArkUINodeAdapterHandle handle, ArkUI_Uint32 size)
301 {
302     if (handle) {
303         handle->builder->SetNodeTotalCount(size);
304         return ERROR_CODE_NO_ERROR;
305     }
306     return ERROR_CODE_PARAM_INVALID;
307 }
308 
GetTotalNodeCount(ArkUINodeAdapterHandle handle)309 ArkUI_Uint32 GetTotalNodeCount(ArkUINodeAdapterHandle handle)
310 {
311     if (handle) {
312         return handle->builder->GetNodeTotalCount();
313     }
314     return 0;
315 }
316 
RegisterEventReceiver(ArkUINodeAdapterHandle handle,void * userData,void (* receiver)(ArkUINodeAdapterEvent * event))317 ArkUI_Int32 RegisterEventReceiver(
318     ArkUINodeAdapterHandle handle, void* userData, void (*receiver)(ArkUINodeAdapterEvent* event))
319 {
320     if (!handle) {
321         return ERROR_CODE_PARAM_INVALID;
322     }
323     handle->builder->SetUserData(userData);
324     handle->builder->SetReceiver(receiver);
325     return ERROR_CODE_NO_ERROR;
326 }
327 
UnregisterEventReceiver(ArkUINodeAdapterHandle handle)328 void UnregisterEventReceiver(ArkUINodeAdapterHandle handle)
329 {
330     if (!handle) {
331         return;
332     }
333     handle->builder->SetUserData(nullptr);
334     handle->builder->SetReceiver(nullptr);
335 }
336 
NotifyItemReloaded(ArkUINodeAdapterHandle handle)337 ArkUI_Int32 NotifyItemReloaded(ArkUINodeAdapterHandle handle)
338 {
339     if (!handle) {
340         return ERROR_CODE_PARAM_INVALID;
341     }
342     return handle->builder->NotifyItemReloaded();
343 }
344 
NotifyItemChanged(ArkUINodeAdapterHandle handle,ArkUI_Uint32 startPosition,ArkUI_Uint32 itemCount)345 ArkUI_Int32 NotifyItemChanged(ArkUINodeAdapterHandle handle, ArkUI_Uint32 startPosition, ArkUI_Uint32 itemCount)
346 {
347     if (!handle) {
348         return ERROR_CODE_PARAM_INVALID;
349     }
350     return handle->builder->NotifyItemChanged(startPosition, itemCount);
351 }
352 
NotifyItemRemoved(ArkUINodeAdapterHandle handle,ArkUI_Uint32 startPosition,ArkUI_Uint32 itemCount)353 ArkUI_Int32 NotifyItemRemoved(ArkUINodeAdapterHandle handle, ArkUI_Uint32 startPosition, ArkUI_Uint32 itemCount)
354 {
355     if (!handle) {
356         return ERROR_CODE_PARAM_INVALID;
357     }
358     return handle->builder->NotifyItemRemoved(startPosition, itemCount);
359 }
360 
NotifyItemInserted(ArkUINodeAdapterHandle handle,ArkUI_Uint32 startPosition,ArkUI_Uint32 itemCount)361 ArkUI_Int32 NotifyItemInserted(ArkUINodeAdapterHandle handle, ArkUI_Uint32 startPosition, ArkUI_Uint32 itemCount)
362 {
363     if (!handle) {
364         return ERROR_CODE_PARAM_INVALID;
365     }
366     return handle->builder->NotifyItemInserted(startPosition, itemCount);
367 }
368 
NotifyItemMoved(ArkUINodeAdapterHandle handle,ArkUI_Uint32 from,ArkUI_Uint32 to)369 ArkUI_Int32 NotifyItemMoved(ArkUINodeAdapterHandle handle, ArkUI_Uint32 from, ArkUI_Uint32 to)
370 {
371     if (!handle) {
372         return ERROR_CODE_PARAM_INVALID;
373     }
374     return handle->builder->NotifyItemMoved(from, to);
375 }
376 
GetAllItem(ArkUINodeAdapterHandle handle,ArkUINodeHandle ** items,ArkUI_Uint32 * size)377 ArkUI_Int32 GetAllItem(ArkUINodeAdapterHandle handle, ArkUINodeHandle** items, ArkUI_Uint32* size)
378 {
379     if (!handle) {
380         return ERROR_CODE_PARAM_INVALID;
381     }
382     return handle->builder->GetAllItem(items, size);
383 }
384 
AttachHostNode(ArkUINodeAdapterHandle handle,ArkUINodeHandle host)385 void AttachHostNode(ArkUINodeAdapterHandle handle, ArkUINodeHandle host)
386 {
387     CHECK_NULL_VOID(handle);
388     CHECK_NULL_VOID(host);
389     if (!handle->node) {
390         handle->node =
391             NG::LazyForEachNode::CreateLazyForEachNode(ElementRegister::GetInstance()->MakeUniqueId(), handle->builder);
392     }
393     auto* uiNode = reinterpret_cast<NG::UINode*>(host);
394     uiNode->AddChild(handle->node);
395 }
396 
DetachHostNode(ArkUINodeHandle host)397 void DetachHostNode(ArkUINodeHandle host)
398 {
399     CHECK_NULL_VOID(host);
400     auto* uiNode = reinterpret_cast<NG::UINode*>(host);
401     const auto& child = AceType::DynamicCast<NG::LazyForEachNode>(uiNode->GetChildAtIndex(0));
402     CHECK_NULL_VOID(child);
403     uiNode->RemoveChild(child);
404     const auto& builder = AceType::DynamicCast<NG::NativeLazyForEachBuilder>(child->GetBuilder());
405     CHECK_NULL_VOID(builder);
406     auto handle = builder->GetHostHandle();
407     CHECK_NULL_VOID(handle);
408     handle->node = nullptr;
409 }
410 
GetNodeAdapter(ArkUINodeHandle host)411 ArkUINodeAdapterHandle GetNodeAdapter(ArkUINodeHandle host)
412 {
413     CHECK_NULL_RETURN(host, nullptr);
414     auto* uiNode = reinterpret_cast<NG::UINode*>(host);
415     const auto& child = AceType::DynamicCast<NG::LazyForEachNode>(uiNode->GetChildAtIndex(0));
416     CHECK_NULL_RETURN(child, nullptr);
417     const auto& builder = AceType::DynamicCast<NG::NativeLazyForEachBuilder>(child->GetBuilder());
418     CHECK_NULL_RETURN(builder, nullptr);
419     return builder->GetHostHandle();
420 }
421 
422 } // namespace
423 
GetNodeAdapterAPI()424 const ArkUINodeAdapterAPI* GetNodeAdapterAPI()
425 {
426     CHECK_INITIALIZED_FIELDS_BEGIN(); // don't move this line
427     static const ArkUINodeAdapterAPI impl {
428         .create = Create,
429         .dispose = Dispose,
430         .setTotalNodeCount = SetTotalNodeCount,
431         .getTotalNodeCount = GetTotalNodeCount,
432         .registerEventReceiver = RegisterEventReceiver,
433         .unregisterEventReceiver = UnregisterEventReceiver,
434         .notifyItemReloaded = NotifyItemReloaded,
435         .notifyItemChanged = NotifyItemChanged,
436         .notifyItemRemoved = NotifyItemRemoved,
437         .notifyItemInserted = NotifyItemInserted,
438         .notifyItemMoved = NotifyItemMoved,
439         .getAllItem = GetAllItem,
440         .attachHostNode = AttachHostNode,
441         .detachHostNode = DetachHostNode,
442         .getNodeAdapter = GetNodeAdapter
443     };
444     CHECK_INITIALIZED_FIELDS_END(impl, 0, 0, 0); // don't move this line
445     return &impl;
446 }
447 
GetCJUINodeAdapterAPI()448 const CJUINodeAdapterAPI* GetCJUINodeAdapterAPI()
449 {
450     CHECK_INITIALIZED_FIELDS_BEGIN(); // don't move this line
451     static const CJUINodeAdapterAPI impl {
452         .create = Create,
453         .dispose = Dispose,
454         .setTotalNodeCount = SetTotalNodeCount,
455         .getTotalNodeCount = GetTotalNodeCount,
456         .registerEventReceiver = RegisterEventReceiver,
457         .unregisterEventReceiver = UnregisterEventReceiver,
458         .notifyItemReloaded = NotifyItemReloaded,
459         .notifyItemChanged = NotifyItemChanged,
460         .notifyItemRemoved = NotifyItemRemoved,
461         .notifyItemInserted = NotifyItemInserted,
462         .notifyItemMoved = NotifyItemMoved,
463         .getAllItem = GetAllItem,
464         .attachHostNode = AttachHostNode,
465         .detachHostNode = DetachHostNode,
466         .getNodeAdapter = GetNodeAdapter
467     };
468     CHECK_INITIALIZED_FIELDS_END(impl, 0, 0, 0); // don't move this line
469     return &impl;
470 }
471 
472 } // namespace OHOS::Ace::NodeAdapter
473