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_event_hub.h"
17
18 #include "base/utils/utils.h"
19 #include "core/components_ng/base/frame_node.h"
20 #include "core/components_ng/pattern/list/list_item_pattern.h"
21 #include "core/components_ng/pattern/list/list_layout_property.h"
22 #include "core/components_ng/pattern/list/list_pattern.h"
23 #include "core/components_ng/render/adapter/component_snapshot.h"
24 #include "core/pipeline_ng/pipeline_context.h"
25
26 namespace OHOS::Ace::NG {
27 #if defined(PIXEL_MAP_SUPPORTED)
28 constexpr int32_t CREATE_PIXELMAP_TIME = 80;
29 #endif
30
InitItemDragEvent(const RefPtr<GestureEventHub> & gestureHub)31 void ListEventHub::InitItemDragEvent(const RefPtr<GestureEventHub>& gestureHub)
32 {
33 auto actionStartTask = [weak = WeakClaim(this)](const GestureEvent& info) {
34 auto eventHub = weak.Upgrade();
35 CHECK_NULL_VOID(eventHub);
36 eventHub->HandleOnItemDragStart(info);
37 };
38
39 auto actionUpdateTask = [weak = WeakClaim(this)](const GestureEvent& info) {
40 auto eventHub = weak.Upgrade();
41 CHECK_NULL_VOID(eventHub);
42 eventHub->HandleOnItemDragUpdate(info);
43 };
44
45 auto actionEndTask = [weak = WeakClaim(this)](const GestureEvent& info) {
46 auto eventHub = weak.Upgrade();
47 CHECK_NULL_VOID(eventHub);
48 eventHub->HandleOnItemDragEnd(info);
49 };
50
51 auto actionCancelTask = [weak = WeakClaim(this)]() {
52 auto eventHub = weak.Upgrade();
53 CHECK_NULL_VOID(eventHub);
54 eventHub->HandleOnItemDragCancel();
55 };
56
57 auto dragEvent = MakeRefPtr<DragEvent>(
58 std::move(actionStartTask), std::move(actionUpdateTask), std::move(actionEndTask), std::move(actionCancelTask));
59 gestureHub->SetDragEvent(dragEvent, { PanDirection::ALL }, DEFAULT_PAN_FINGER, DEFAULT_PAN_DISTANCE);
60 }
61
OnItemDragStart(const GestureEvent & info,const DragDropInfo & dragDropInfo)62 void ListEventHub::OnItemDragStart(const GestureEvent& info, const DragDropInfo& dragDropInfo)
63 {
64 auto pipeline = PipelineContext::GetCurrentContext();
65 CHECK_NULL_VOID(pipeline);
66 auto manager = pipeline->GetDragDropManager();
67 CHECK_NULL_VOID(manager);
68 if (dragDropInfo.pixelMap) {
69 dragDropProxy_ = manager->CreateAndShowDragWindow(dragDropInfo.pixelMap, info);
70 } else if (dragDropInfo.customNode) {
71 dragDropProxy_ = manager->CreateAndShowDragWindow(dragDropInfo.customNode, info);
72 }
73 CHECK_NULL_VOID(dragDropProxy_);
74 dragDropProxy_->OnItemDragStart(info, GetFrameNode());
75 if (!manager->IsDraggingPressed(info.GetPointerId())) {
76 HandleOnItemDragEnd(info);
77 }
78 }
79
HandleOnItemDragStart(const GestureEvent & info)80 void ListEventHub::HandleOnItemDragStart(const GestureEvent& info)
81 {
82 auto host = GetFrameNode();
83 CHECK_NULL_VOID(host);
84 auto pipeline = host->GetContext();
85 CHECK_NULL_VOID(pipeline);
86
87 auto globalX = static_cast<float>(info.GetGlobalPoint().GetX());
88 auto globalY = static_cast<float>(info.GetGlobalPoint().GetY());
89
90 draggedIndex_ = GetListItemIndexByPosition(globalX, globalY, true);
91 if (draggedIndex_ == -1) {
92 return;
93 }
94
95 OHOS::Ace::ItemDragInfo itemDragInfo;
96 itemDragInfo.SetX(globalX);
97 itemDragInfo.SetY(globalY);
98 auto customNode = FireOnItemDragStart(itemDragInfo, draggedIndex_);
99 CHECK_NULL_VOID(customNode);
100 auto dragDropManager = pipeline->GetDragDropManager();
101 CHECK_NULL_VOID(dragDropManager);
102 dragDropManager->SetDraggingPointer(info.GetPointerId());
103 dragDropManager->SetDraggingPressedState(true);
104 #if defined(PIXEL_MAP_SUPPORTED)
105 auto callback = [weakHost = WeakClaim(RawPtr(host)), info, weak = WeakClaim(this)](
106 std::shared_ptr<Media::PixelMap> mediaPixelMap, int32_t /*arg*/,
107 const std::function<void()>& /*unused*/) {
108 auto host = weakHost.Upgrade();
109 CHECK_NULL_VOID(host);
110 ContainerScope scope(host->GetInstanceId());
111 if (!mediaPixelMap) {
112 TAG_LOGE(AceLogTag::ACE_DRAG, "listItem drag start failed, custom component screenshot is empty.");
113 return;
114 }
115 auto pipeline = PipelineContext::GetCurrentContext();
116 CHECK_NULL_VOID(pipeline);
117 DragDropInfo dragDropInfo;
118 dragDropInfo.pixelMap = PixelMap::CreatePixelMap(reinterpret_cast<void*>(&mediaPixelMap));
119 auto taskScheduler = pipeline->GetTaskExecutor();
120 CHECK_NULL_VOID(taskScheduler);
121 taskScheduler->PostTask(
122 [weak, info, dragDropInfo]() {
123 auto eventHub = weak.Upgrade();
124 CHECK_NULL_VOID(eventHub);
125 eventHub->OnItemDragStart(info, dragDropInfo);
126 },
127 TaskExecutor::TaskType::UI, "ArkUIListItemDragStart");
128 };
129 NG::ComponentSnapshot::Create(customNode, std::move(callback), true,
130 SnapshotParam(CREATE_PIXELMAP_TIME));
131 #else
132 DragDropInfo dragDropInfo;
133 dragDropInfo.customNode = customNode;
134 OnItemDragStart(info, dragDropInfo);
135 #endif
136 }
137
HandleOnItemDragUpdate(const GestureEvent & info)138 void ListEventHub::HandleOnItemDragUpdate(const GestureEvent& info)
139 {
140 CHECK_NULL_VOID(dragDropProxy_);
141 dragDropProxy_->OnItemDragMove(info, draggedIndex_, DragType::LIST);
142 }
143
HandleOnItemDragEnd(const GestureEvent & info)144 void ListEventHub::HandleOnItemDragEnd(const GestureEvent& info)
145 {
146 CHECK_NULL_VOID(dragDropProxy_);
147 dragDropProxy_->OnItemDragEnd(info, draggedIndex_, DragType::LIST);
148 dragDropProxy_->DestroyDragWindow();
149 dragDropProxy_ = nullptr;
150 draggedIndex_ = 0;
151 }
152
HandleOnItemDragCancel()153 void ListEventHub::HandleOnItemDragCancel()
154 {
155 CHECK_NULL_VOID(dragDropProxy_);
156 dragDropProxy_->onItemDragCancel();
157 dragDropProxy_->DestroyDragWindow();
158 dragDropProxy_ = nullptr;
159 draggedIndex_ = 0;
160 }
161
GetListItemIndexByPosition(float x,float y,bool strict)162 int32_t ListEventHub::GetListItemIndexByPosition(float x, float y, bool strict)
163 {
164 auto listNode = GetFrameNode();
165 CHECK_NULL_RETURN(listNode, 0);
166
167 if (strict) {
168 auto itemFrameNode = listNode->FindChildByPositionWithoutChildTransform(x, y);
169 CHECK_NULL_RETURN(itemFrameNode, -1);
170 RefPtr<ListItemPattern> itemPattern = itemFrameNode->GetPattern<ListItemPattern>();
171 CHECK_NULL_RETURN(itemPattern, -1);
172 return itemPattern->GetIndexInList();
173 }
174
175 auto listPattern = listNode->GetPattern<ListPattern>();
176 CHECK_NULL_RETURN(listPattern, 0);
177 return listPattern->GetItemIndexByPosition(x, y);
178 }
179 } // namespace OHOS::Ace::NG
180