1 /*
2  * Copyright (c) 2022 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/components_ng/pattern/list/list_item_model_ng.h"
17 
18 #include "base/memory/referenced.h"
19 #include "base/utils/utils.h"
20 #include "core/components_ng/base/frame_node.h"
21 #include "core/components_ng/base/view_stack_processor.h"
22 #include "core/components_ng/pattern/list/list_item_event_hub.h"
23 #include "core/components_ng/pattern/list/list_item_layout_property.h"
24 #include "core/components_ng/pattern/list/list_item_pattern.h"
25 #include "core/components_ng/pattern/list/list_pattern.h"
26 #include "core/components_ng/pattern/scrollable/scrollable_item.h"
27 #include "core/components_ng/pattern/scrollable/scrollable_item_pool.h"
28 #include "core/components_v2/inspector/inspector_constants.h"
29 
30 namespace OHOS::Ace::NG {
31 
Create(std::function<void (int32_t)> && deepRenderFunc,V2::ListItemStyle listItemStyle)32 void ListItemModelNG::Create(std::function<void(int32_t)>&& deepRenderFunc, V2::ListItemStyle listItemStyle)
33 {
34     auto* stack = ViewStackProcessor::GetInstance();
35     auto nodeId = stack->ClaimNodeId();
36     ACE_LAYOUT_SCOPED_TRACE("Create[%s][self:%d]", V2::LIST_ITEM_ETS_TAG, nodeId);
37     if (deepRenderFunc) {
38         auto deepRender = [nodeId, deepRenderFunc = std::move(deepRenderFunc)]() -> RefPtr<UINode> {
39             CHECK_NULL_RETURN(deepRenderFunc, nullptr);
40             ScopedViewStackProcessor scopedViewStackProcessor;
41             deepRenderFunc(nodeId);
42             return ViewStackProcessor::GetInstance()->Finish();
43         };
44         auto frameNode = ScrollableItemPool::GetInstance().Allocate(V2::LIST_ITEM_ETS_TAG, nodeId,
45             [shallowBuilder = AceType::MakeRefPtr<ShallowBuilder>(std::move(deepRender)), itemStyle = listItemStyle]() {
46                 return AceType::MakeRefPtr<ListItemPattern>(shallowBuilder, itemStyle);
47             });
48         stack->Push(frameNode);
49     } else {
50         auto frameNode = FrameNode::GetOrCreateFrameNode(V2::LIST_ITEM_ETS_TAG, nodeId,
51             [listItemStyle]() { return AceType::MakeRefPtr<ListItemPattern>(nullptr, listItemStyle); });
52         stack->Push(frameNode);
53     }
54 }
55 
Create()56 void ListItemModelNG::Create()
57 {
58     auto* stack = ViewStackProcessor::GetInstance();
59     auto nodeId = stack->ClaimNodeId();
60     auto frameNode = FrameNode::GetOrCreateFrameNode(V2::LIST_ITEM_ETS_TAG, nodeId,
61         []() { return AceType::MakeRefPtr<ListItemPattern>(nullptr, V2::ListItemStyle::NONE); });
62     stack->Push(frameNode);
63 }
64 
OnDidPop()65 void ListItemModelNG::OnDidPop()
66 {
67     auto frameNode = ViewStackProcessor::GetInstance()->GetMainFrameNode();
68     CHECK_NULL_VOID(frameNode);
69     auto pattern = frameNode->GetPattern<ListItemPattern>();
70     CHECK_NULL_VOID(pattern);
71     pattern->OnDidPop();
72 }
73 
CreateFrameNode(int32_t nodeId)74 RefPtr<FrameNode> ListItemModelNG::CreateFrameNode(int32_t nodeId)
75 {
76     auto frameNode = FrameNode::CreateFrameNode(V2::LIST_ITEM_ETS_TAG, nodeId,
77         AceType::MakeRefPtr<ListItemPattern>(nullptr, V2::ListItemStyle::NONE));
78     return frameNode;
79 }
80 
81 // use SetDeleteArea to update builder function
SetSwiperAction(std::function<void ()> && startAction,std::function<void ()> && endAction,OnOffsetChangeFunc && onOffsetChangeFunc,V2::SwipeEdgeEffect edgeEffect)82 void ListItemModelNG::SetSwiperAction(std::function<void()>&& startAction, std::function<void()>&& endAction,
83     OnOffsetChangeFunc&& onOffsetChangeFunc, V2::SwipeEdgeEffect edgeEffect)
84 {
85     auto frameNode = ViewStackProcessor::GetInstance()->GetMainFrameNode();
86     CHECK_NULL_VOID(frameNode);
87     auto pattern = frameNode->GetPattern<ListItemPattern>();
88     CHECK_NULL_VOID(pattern);
89     pattern->SetOffsetChangeCallBack(std::move(onOffsetChangeFunc));
90     ACE_UPDATE_LAYOUT_PROPERTY(ListItemLayoutProperty, EdgeEffect, edgeEffect);
91 }
92 
SetSticky(V2::StickyMode stickyMode)93 void ListItemModelNG::SetSticky(V2::StickyMode stickyMode)
94 {
95     ACE_UPDATE_LAYOUT_PROPERTY(ListItemLayoutProperty, StickyMode, stickyMode);
96 }
97 
SetEditMode(uint32_t editMode)98 void ListItemModelNG::SetEditMode(uint32_t editMode)
99 {
100     ACE_UPDATE_LAYOUT_PROPERTY(ListItemLayoutProperty, EditMode, editMode);
101 }
102 
SetSelectable(bool selectable)103 void ListItemModelNG::SetSelectable(bool selectable)
104 {
105     auto frameNode = ViewStackProcessor::GetInstance()->GetMainFrameNode();
106     CHECK_NULL_VOID(frameNode);
107     auto pattern = frameNode->GetPattern<ListItemPattern>();
108     CHECK_NULL_VOID(pattern);
109     pattern->SetSelectable(selectable);
110 }
111 
SetSelected(bool selected)112 void ListItemModelNG::SetSelected(bool selected)
113 {
114     auto frameNode = ViewStackProcessor::GetInstance()->GetMainFrameNode();
115     CHECK_NULL_VOID(frameNode);
116     auto pattern = frameNode->GetPattern<ListItemPattern>();
117     CHECK_NULL_VOID(pattern);
118     pattern->SetSelected(selected);
119     auto eventHub = frameNode->GetEventHub<ListItemEventHub>();
120     CHECK_NULL_VOID(eventHub);
121     eventHub->SetCurrentUIState(UI_STATE_SELECTED, selected);
122 }
123 
SetSelectChangeEvent(std::function<void (bool)> && changeEvent)124 void ListItemModelNG::SetSelectChangeEvent(std::function<void(bool)>&& changeEvent)
125 {
126     auto frameNode = ViewStackProcessor::GetInstance()->GetMainFrameNode();
127     CHECK_NULL_VOID(frameNode);
128     auto eventHub = frameNode->GetEventHub<ListItemEventHub>();
129     CHECK_NULL_VOID(eventHub);
130     eventHub->SetSelectChangeEvent(std::move(changeEvent));
131 }
132 
SetSelectCallback(OnSelectFunc && selectCallback)133 void ListItemModelNG::SetSelectCallback(OnSelectFunc&& selectCallback)
134 {
135     auto frameNode = ViewStackProcessor::GetInstance()->GetMainFrameNode();
136     CHECK_NULL_VOID(frameNode);
137     auto eventHub = frameNode->GetEventHub<ListItemEventHub>();
138     CHECK_NULL_VOID(eventHub);
139     eventHub->SetOnSelect(std::move(selectCallback));
140 }
141 
SetDeleteArea(std::function<void ()> && builderAction,OnDeleteEvent && onDelete,OnEnterDeleteAreaEvent && onEnterDeleteArea,OnExitDeleteAreaEvent && onExitDeleteArea,OnStateChangedEvent && onStateChange,const Dimension & length,bool isStartArea)142 void ListItemModelNG::SetDeleteArea(std::function<void()>&& builderAction, OnDeleteEvent&& onDelete,
143     OnEnterDeleteAreaEvent&& onEnterDeleteArea, OnExitDeleteAreaEvent&& onExitDeleteArea,
144     OnStateChangedEvent&& onStateChange, const Dimension& length, bool isStartArea)
145 {
146     auto frameNode = ViewStackProcessor::GetInstance()->GetMainFrameNode();
147     CHECK_NULL_VOID(frameNode);
148     auto eventHub = frameNode->GetEventHub<ListItemEventHub>();
149     CHECK_NULL_VOID(eventHub);
150     auto pattern = frameNode->GetPattern<ListItemPattern>();
151     CHECK_NULL_VOID(pattern);
152     if (isStartArea) {
153         RefPtr<NG::UINode> startNode;
154         if (builderAction) {
155             NG::ScopedViewStackProcessor builderViewStackProcessor;
156             builderAction();
157             startNode = NG::ViewStackProcessor::GetInstance()->Finish();
158         }
159         pattern->SetStartNode(startNode);
160         InstallSwiperCallBack(eventHub, std::move(onDelete), std::move(onEnterDeleteArea), std::move(onExitDeleteArea),
161             std::move(onStateChange), isStartArea);
162         ACE_UPDATE_LAYOUT_PROPERTY(ListItemLayoutProperty, StartDeleteAreaDistance, length);
163     } else {
164         RefPtr<NG::UINode> endNode;
165         if (builderAction) {
166             NG::ScopedViewStackProcessor builderViewStackProcessor;
167             builderAction();
168             endNode = NG::ViewStackProcessor::GetInstance()->Finish();
169         }
170         pattern->SetEndNode(endNode);
171         InstallSwiperCallBack(eventHub, std::move(onDelete), std::move(onEnterDeleteArea), std::move(onExitDeleteArea),
172             std::move(onStateChange), isStartArea);
173         ACE_UPDATE_LAYOUT_PROPERTY(ListItemLayoutProperty, EndDeleteAreaDistance, length);
174     }
175 }
176 
InstallSwiperCallBack(RefPtr<ListItemEventHub> eventHub,OnDeleteEvent && onDelete,OnEnterDeleteAreaEvent && onEnterDeleteArea,OnExitDeleteAreaEvent && onExitDeleteArea,OnStateChangedEvent && onStateChange,bool isStartArea)177 void ListItemModelNG::InstallSwiperCallBack(RefPtr<ListItemEventHub> eventHub, OnDeleteEvent&& onDelete,
178     OnEnterDeleteAreaEvent&& onEnterDeleteArea, OnExitDeleteAreaEvent&& onExitDeleteArea,
179     OnStateChangedEvent&& onStateChange, bool isStartArea)
180 {
181     CHECK_NULL_VOID(eventHub);
182     if (isStartArea) {
183         eventHub->SetStartOnDelete(std::move(onDelete));
184         eventHub->SetOnEnterStartDeleteArea(std::move(onEnterDeleteArea));
185         eventHub->SetOnExitStartDeleteArea(std::move(onExitDeleteArea));
186         eventHub->SetStartOnStateChange(std::move(onStateChange));
187     } else {
188         eventHub->SetEndOnDelete(std::move(onDelete));
189         eventHub->SetOnEnterEndDeleteArea(std::move(onEnterDeleteArea));
190         eventHub->SetOnExitEndDeleteArea(std::move(onExitDeleteArea));
191         eventHub->SetEndOnStateChange(std::move(onStateChange));
192     }
193 }
194 
SetSelected(FrameNode * frameNode,bool selected)195 void ListItemModelNG::SetSelected(FrameNode* frameNode, bool selected)
196 {
197     CHECK_NULL_VOID(frameNode);
198     auto pattern = frameNode->GetPattern<ListItemPattern>();
199     CHECK_NULL_VOID(pattern);
200     pattern->SetSelected(selected);
201     auto eventHub = frameNode->GetEventHub<ListItemEventHub>();
202     CHECK_NULL_VOID(eventHub);
203     eventHub->SetCurrentUIState(UI_STATE_SELECTED, selected);
204 }
205 
SetSelectable(FrameNode * frameNode,bool selectable)206 void ListItemModelNG::SetSelectable(FrameNode* frameNode, bool selectable)
207 {
208     CHECK_NULL_VOID(frameNode);
209     auto pattern = frameNode->GetPattern<ListItemPattern>();
210     CHECK_NULL_VOID(pattern);
211     pattern->SetSelectable(selectable);
212 }
213 
SetDeleteArea(FrameNode * frameNode,FrameNode * buildNode,OnDeleteEvent && onDelete,OnEnterDeleteAreaEvent && onEnterDeleteArea,OnExitDeleteAreaEvent && onExitDeleteArea,OnStateChangedEvent && onStateChange,const Dimension & length,bool isStartArea)214 void ListItemModelNG::SetDeleteArea(FrameNode* frameNode, FrameNode* buildNode, OnDeleteEvent&& onDelete,
215     OnEnterDeleteAreaEvent&& onEnterDeleteArea, OnExitDeleteAreaEvent&& onExitDeleteArea,
216     OnStateChangedEvent&& onStateChange, const Dimension& length, bool isStartArea)
217 {
218     CHECK_NULL_VOID(frameNode);
219     auto eventHub = frameNode->GetEventHub<ListItemEventHub>();
220     CHECK_NULL_VOID(eventHub);
221     auto pattern = frameNode->GetPattern<ListItemPattern>();
222     CHECK_NULL_VOID(pattern);
223     if (isStartArea) {
224         const auto startNode = AceType::Claim<UINode>(buildNode);
225         pattern->SetStartNode(startNode);
226 
227         eventHub->SetStartOnDelete(std::move(onDelete));
228         eventHub->SetOnEnterStartDeleteArea(std::move(onEnterDeleteArea));
229         eventHub->SetOnExitStartDeleteArea(std::move(onExitDeleteArea));
230         eventHub->SetStartOnStateChange(std::move(onStateChange));
231         ACE_UPDATE_NODE_LAYOUT_PROPERTY(ListItemLayoutProperty, StartDeleteAreaDistance, length, frameNode);
232     } else {
233         const auto endNode = AceType::Claim<UINode>(buildNode);
234         pattern->SetEndNode(endNode);
235 
236         eventHub->SetEndOnDelete(std::move(onDelete));
237         eventHub->SetOnEnterEndDeleteArea(std::move(onEnterDeleteArea));
238         eventHub->SetOnExitEndDeleteArea(std::move(onExitDeleteArea));
239         eventHub->SetEndOnStateChange(std::move(onStateChange));
240         ACE_UPDATE_NODE_LAYOUT_PROPERTY(ListItemLayoutProperty, EndDeleteAreaDistance, length, frameNode);
241     }
242 }
243 
SetSwiperAction(FrameNode * frameNode,std::function<void ()> && startAction,std::function<void ()> && endAction,OnOffsetChangeFunc && onOffsetChangeFunc,V2::SwipeEdgeEffect edgeEffect)244 void ListItemModelNG::SetSwiperAction(FrameNode* frameNode, std::function<void()>&& startAction,
245     std::function<void()>&& endAction, OnOffsetChangeFunc&& onOffsetChangeFunc, V2::SwipeEdgeEffect edgeEffect)
246 {
247     CHECK_NULL_VOID(frameNode);
248     auto pattern = frameNode->GetPattern<ListItemPattern>();
249     CHECK_NULL_VOID(pattern);
250     pattern->SetOffsetChangeCallBack(std::move(onOffsetChangeFunc));
251     ACE_UPDATE_NODE_LAYOUT_PROPERTY(ListItemLayoutProperty, EdgeEffect, edgeEffect, frameNode);
252 }
253 
SetSelectCallback(FrameNode * frameNode,OnSelectFunc && selectCallback)254 void ListItemModelNG::SetSelectCallback(FrameNode* frameNode, OnSelectFunc&& selectCallback)
255 {
256     CHECK_NULL_VOID(frameNode);
257     auto eventHub = frameNode->GetEventHub<ListItemEventHub>();
258     CHECK_NULL_VOID(eventHub);
259     eventHub->SetOnSelect(std::move(selectCallback));
260 }
261 
262 } // namespace OHOS::Ace::NG
263