1 /*
2  * Copyright (c) 2022-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 #ifndef FOUNDATION_ACE_FRAMEWORKS_CORE_COMPONENTS_NG_PATTERNS_LIST_LIST_ITEM_PATTERN_H
17 #define FOUNDATION_ACE_FRAMEWORKS_CORE_COMPONENTS_NG_PATTERNS_LIST_LIST_ITEM_PATTERN_H
18 
19 #include "base/memory/referenced.h"
20 #include "base/utils/noncopyable.h"
21 #include "base/utils/utils.h"
22 #include "core/components/list/list_item_theme.h"
23 #include "core/components_ng/pattern/list/list_item_accessibility_property.h"
24 #include "core/components_ng/pattern/list/list_item_drag_manager.h"
25 #include "core/components_ng/pattern/list/list_item_event_hub.h"
26 #include "core/components_ng/pattern/list/list_item_layout_property.h"
27 #include "core/components_ng/pattern/list/list_layout_property.h"
28 #include "core/components_ng/pattern/pattern.h"
29 #include "core/components_ng/syntax/shallow_builder.h"
30 #include "core/pipeline_ng/ui_task_scheduler.h"
31 
32 namespace OHOS::Ace::NG {
33 class InspectorFilter;
34 
35 enum class ListItemSwipeIndex {
36     SWIPER_END = -1,
37     ITEM_CHILD = 0,
38     SWIPER_START = 1,
39     SWIPER_ACTION = 2,
40 };
41 
42 class ACE_EXPORT ListItemPattern : public Pattern {
43     DECLARE_ACE_TYPE(ListItemPattern, Pattern);
44 
45 public:
ListItemPattern(const RefPtr<ShallowBuilder> & shallowBuilder)46     explicit ListItemPattern(const RefPtr<ShallowBuilder>& shallowBuilder) : shallowBuilder_(shallowBuilder) {}
ListItemPattern(const RefPtr<ShallowBuilder> & shallowBuilder,V2::ListItemStyle listItemStyle)47     explicit ListItemPattern(const RefPtr<ShallowBuilder>& shallowBuilder, V2::ListItemStyle listItemStyle)
48         : shallowBuilder_(shallowBuilder), listItemStyle_(listItemStyle)
49     {}
50     ~ListItemPattern() override = default;
51 
IsAtomicNode()52     bool IsAtomicNode() const override
53     {
54         return false;
55     }
56 
BeforeCreateLayoutWrapper()57     void BeforeCreateLayoutWrapper() override
58     {
59         if (shallowBuilder_ && !shallowBuilder_->IsExecuteDeepRenderDone()) {
60             shallowBuilder_->ExecuteDeepRender();
61             shallowBuilder_.Reset();
62         }
63     }
64 
65     bool RenderCustomChild(int64_t deadline) override;
66 
GetFocusPattern()67     FocusPattern GetFocusPattern() const override
68     {
69         if (listItemStyle_ == V2::ListItemStyle::CARD) {
70             auto pipelineContext = PipelineBase::GetCurrentContext();
71             CHECK_NULL_RETURN(pipelineContext, FocusPattern());
72             auto listItemTheme = pipelineContext->GetTheme<ListItemTheme>();
73             CHECK_NULL_RETURN(listItemTheme, FocusPattern());
74             FocusPaintParam paintParam;
75             paintParam.SetPaintColor(listItemTheme->GetItemFocusBorderColor());
76             paintParam.SetPaintWidth(listItemTheme->GetItemFocusBorderWidth());
77             return { FocusType::SCOPE, true, FocusStyleType::INNER_BORDER, paintParam };
78         }
79         return { FocusType::SCOPE, true };
80     }
81 
CreateLayoutProperty()82     RefPtr<LayoutProperty> CreateLayoutProperty() override
83     {
84         return MakeRefPtr<ListItemLayoutProperty>();
85     }
86 
87     RefPtr<LayoutAlgorithm> CreateLayoutAlgorithm() override;
88     bool OnDirtyLayoutWrapperSwap(const RefPtr<LayoutWrapper>& dirty, const DirtySwapConfig& config) override;
89 
CreateEventHub()90     RefPtr<EventHub> CreateEventHub() override
91     {
92         return MakeRefPtr<ListItemEventHub>();
93     }
94 
95     void ToJsonValue(std::unique_ptr<JsonValue>& json, const InspectorFilter& filter) const override;
96 
97     void SetStartNode(const RefPtr<NG::UINode>& startNode);
98 
99     void SetEndNode(const RefPtr<NG::UINode>& endNode);
100 
101     SizeF GetContentSize() const;
102 
103     void HandleDragStart(const GestureEvent& info);
104     void HandleDragUpdate(const GestureEvent& info);
105     void HandleDragEnd(const GestureEvent& info);
106 
107     V2::SwipeEdgeEffect GetEdgeEffect();
108     void MarkDirtyNode();
109     void UpdatePostion(float delta);
110     void DumpAdvanceInfo() override;
111 
HasStartNode()112     bool HasStartNode() const
113     {
114         return startNodeIndex_ >= 0;
115     }
116 
HasEndNode()117     bool HasEndNode() const
118     {
119         return endNodeIndex_ >= 0;
120     }
121 
122     void OnDidPop();
123 
GetSwiperIndex()124     ListItemSwipeIndex GetSwiperIndex()
125     {
126         return swiperIndex_;
127     }
128 
129     RefPtr<FrameNode> GetListFrameNode() const;
130 
131     RefPtr<FrameNode> GetParentFrameNode() const;
132 
133     Axis GetAxis() const;
134 
135     void ChangeAxis(Axis axis);
136 
137     void SetSwiperItemForList();
138 
139     void ResetSwipeStatus(bool calledByUser = false);
140 
141     static float CalculateFriction(float gamma);
142 
143     void MarkIsSelected(bool isSelected);
144 
IsSelected()145     bool IsSelected() const
146     {
147         return isSelected_;
148     }
149 
SetSelected(bool selected)150     void SetSelected(bool selected)
151     {
152         isSelected_ = selected;
153     }
154 
Selectable()155     bool Selectable() const
156     {
157         return selectable_;
158     }
159 
SetSelectable(bool selectable)160     void SetSelectable(bool selectable)
161     {
162         selectable_ = selectable;
163         if (!selectable) {
164             MarkIsSelected(false);
165         }
166     }
167 
GetIndexInList()168     int32_t GetIndexInList() const
169     {
170         return indexInList_;
171     }
172 
SetIndexInList(int32_t index)173     void SetIndexInList(int32_t index)
174     {
175         indexInList_ = index;
176     }
177 
GetIndexInListItemGroup()178     int32_t GetIndexInListItemGroup() const
179     {
180         return indexInListItemGroup_;
181     }
182 
SetIndexInListItemGroup(int32_t index)183     void SetIndexInListItemGroup(int32_t index)
184     {
185         indexInListItemGroup_ = index;
186     }
187 
CreateAccessibilityProperty()188     RefPtr<AccessibilityProperty> CreateAccessibilityProperty() override
189     {
190         return MakeRefPtr<ListItemAccessibilityProperty>();
191     }
192 
GetListItemStyle()193     V2::ListItemStyle GetListItemStyle()
194     {
195         return listItemStyle_;
196     }
197 
198     void SetOffsetChangeCallBack(OnOffsetChangeFunc&& offsetChangeCallback);
199 
200     void CloseSwipeAction(OnFinishFunc&& onFinishCallback);
201 
FireOnFinshEvent()202     void FireOnFinshEvent() const
203     {
204         if (onFinishEvent_) {
205             onFinishEvent_();
206         }
207     }
208 
209     bool GetLayouted() const;
210     float GetEstimateHeight(float estimateHeight, Axis axis) const;
211     bool ClickJudge(const PointF& localPoint);
212 
InitDragManager(RefPtr<ForEachBaseNode> forEach)213     void InitDragManager(RefPtr<ForEachBaseNode> forEach)
214     {
215         if (!dragManager_) {
216             dragManager_ = MakeRefPtr<ListItemDragManager>(GetHost(), forEach);
217             dragManager_->InitDragDropEvent();
218         }
219     }
DeInitDragManager()220     void DeInitDragManager()
221     {
222         if (dragManager_) {
223             dragManager_->DeInitDragDropEvent();
224             dragManager_ = nullptr;
225         }
226     }
227 
228 protected:
229     void OnModifyDone() override;
230 
IsNeedInitClickEventRecorder()231     bool IsNeedInitClickEventRecorder() const override
232     {
233         return true;
234     }
235 
236 private:
237     void InitSwiperAction(bool axisChanged);
238     float GetFriction();
239     void ChangeDeleteAreaStage();
240     void StartSpringMotion(float start, float end, float velocity, bool isCloseAllSwipeActions = false);
241     void OnAttachToFrameNode() override;
242     void SetListItemDefaultAttributes(const RefPtr<FrameNode>& listItemNode);
243     void OnColorConfigurationUpdate() override;
244     void InitListItemCardStyleForList();
245     void UpdateListItemAlignToCenter();
246     Color GetBlendGgColor();
247     void InitHoverEvent();
248     void HandleHoverEvent(bool isHover, const RefPtr<NG::FrameNode>& itemNode);
249     void InitPressEvent();
250     void HandlePressEvent(bool isPressed, const RefPtr<NG::FrameNode>& itemNode);
251     void InitDisableEvent();
252     void SetAccessibilityAction();
253     void DoDeleteAnimation(bool isRightDelete);
254     void FireSwipeActionOffsetChange(float oldOffset, float newOffset);
255     void FireSwipeActionStateChange(ListItemSwipeIndex newSwiperIndex);
256     void UpdateClickJudgeCallback();
257     bool ClickJudgeVertical(const SizeF& size, double xOffset, double yOffset);
ResetNodeSize()258     void ResetNodeSize()
259     {
260         startNodeSize_ = 0.0f;
261         endNodeSize_ = 0.0f;
262     }
263     bool IsRTLAndVertical() const;
264     void OnDetachFromMainTree() override;
265 
266     RefPtr<ShallowBuilder> shallowBuilder_;
267     V2::ListItemStyle listItemStyle_ = V2::ListItemStyle::NONE;
268 
269     int32_t indexInList_ = 0;
270     int32_t indexInListItemGroup_ = -1;
271 
272     // swiperAction
273     int32_t startNodeIndex_ = -1;
274     int32_t endNodeIndex_ = -1;
275     int32_t childNodeIndex_ = 0;
276 
277     float curOffset_ = 0.0f;
278     float startNodeSize_ = 0.0f;
279     float endNodeSize_ = 0.0f;
280     Axis axis_ = Axis::NONE;
281     ListItemSwipeIndex swiperIndex_ = ListItemSwipeIndex::ITEM_CHILD;
282     SwipeActionState swipeActionState_ = SwipeActionState::COLLAPSED;
283     float startDeleteAreaDistance_ = 0.0f;
284     float endDeleteAreaDistance_ = 0.0f;
285     bool hasStartDeleteArea_ = false;
286     bool hasEndDeleteArea_ = false;
287     bool inStartDeleteArea_ = false;
288     bool inEndDeleteArea_ = false;
289 
290     RefPtr<PanEvent> panEvent_;
291     RefPtr<Animator> springController_;
292     RefPtr<SpringMotion> springMotion_;
293 
294     // selectable
295     bool selectable_ = true;
296     bool isSelected_ = false;
297 
298     // drag sort
299     RefPtr<ListItemDragManager> dragManager_;
300 
301     RefPtr<InputEvent> hoverEvent_;
302     RefPtr<TouchEventImpl> touchListener_;
303     bool isHover_ = false;
304     bool isPressed_ = false;
305     std::optional<double> enableOpacity_;
306     OnFinishFunc onFinishEvent_;
307     bool isLayouted_ = false;
308     bool springMotionTraceFlag_ = false;
309     bool isDragging_ = false;
310 
311     ACE_DISALLOW_COPY_AND_MOVE(ListItemPattern);
312 };
313 } // namespace OHOS::Ace::NG
314 
315 #endif // FOUNDATION_ACE_FRAMEWORKS_CORE_COMPONENTS_NG_PATTERNS_LIST_LIST_ITEM_PATTERN_H
316