• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 #include "core/components_ng/pattern/grid/grid_event_hub.h"
17 
18 #include "core/components_ng/pattern/grid/grid_item_pattern.h"
19 #include "core/components_ng/render/adapter/component_snapshot.h"
20 
21 namespace OHOS::Ace::NG {
22 #if defined(PIXEL_MAP_SUPPORTED)
23 constexpr int32_t CREATE_PIXELMAP_TIME = 80;
24 #endif
25 
InitItemDragEvent(const RefPtr<GestureEventHub> & gestureHub)26 void GridEventHub::InitItemDragEvent(const RefPtr<GestureEventHub>& gestureHub)
27 {
28     auto actionStartTask = [weak = WeakClaim(this)](const GestureEvent& info) {
29         auto eventHub = weak.Upgrade();
30         if (eventHub) {
31             eventHub->HandleOnItemDragStart(info);
32         }
33     };
34 
35     auto actionUpdateTask = [weak = WeakClaim(this)](const GestureEvent& info) {
36         auto eventHub = weak.Upgrade();
37         if (eventHub) {
38             eventHub->HandleOnItemDragUpdate(info);
39         }
40     };
41 
42     auto actionEndTask = [weak = WeakClaim(this)](const GestureEvent& info) {
43         auto eventHub = weak.Upgrade();
44         if (eventHub) {
45             eventHub->HandleOnItemDragEnd(info);
46         }
47     };
48 
49     auto actionCancelTask = [weak = WeakClaim(this)]() {
50         auto eventHub = weak.Upgrade();
51         if (eventHub) {
52             eventHub->HandleOnItemDragCancel();
53         }
54     };
55 
56     auto dragEvent = MakeRefPtr<DragEvent>(
57         std::move(actionStartTask), std::move(actionUpdateTask), std::move(actionEndTask), std::move(actionCancelTask));
58     gestureHub->SetDragEvent(dragEvent, { PanDirection::ALL }, DEFAULT_PAN_FINGER, DEFAULT_PAN_DISTANCE);
59 }
60 
CheckPostionInGrid(float x,float y)61 bool GridEventHub::CheckPostionInGrid(float x, float y)
62 {
63     auto host = GetFrameNode();
64     CHECK_NULL_RETURN(host, false);
65     auto size = host->GetRenderContext()->GetPaintRectWithTransform();
66     size.SetOffset(host->GetTransformRelativeOffset());
67     return size.IsInRegion(PointF(x, y));
68 }
69 
GetInsertPosition(float x,float y)70 int32_t GridEventHub::GetInsertPosition(float x, float y)
71 {
72     if (!CheckPostionInGrid(x, y)) {
73         return -1;
74     }
75 
76     auto host = GetFrameNode();
77     CHECK_NULL_RETURN(host, -1);
78     auto pattern = AceType::DynamicCast<GridPattern>(host->GetPattern());
79     CHECK_NULL_RETURN(pattern, -1);
80     auto itemFrameNode = host->FindChildByPositionWithoutChildTransform(x, y);
81     if (itemFrameNode) {
82         RefPtr<GridItemLayoutProperty> itemLayoutProperty = itemFrameNode->GetLayoutProperty<GridItemLayoutProperty>();
83         CHECK_NULL_RETURN(itemLayoutProperty, 0);
84         auto mainIndex = itemLayoutProperty->GetMainIndex().value_or(-1);
85         auto crossIndex = itemLayoutProperty->GetCrossIndex().value_or(-1);
86         return mainIndex * pattern->GetCrossCount() + crossIndex;
87     }
88 
89     // on virtual grid item dragged in this grid
90     if (pattern->GetGridLayoutInfo().currentRect_.IsInRegion(PointF(x, y))) {
91         return pattern->GetOriginalIndex();
92     }
93 
94     // in grid, but not on any grid item
95     return pattern->GetChildrenCount();
96 }
97 
GetFrameNodeChildSize()98 int GridEventHub::GetFrameNodeChildSize()
99 {
100     auto host = GetFrameNode();
101     CHECK_NULL_RETURN(host, 0);
102     auto pattern = host->GetPattern<GridPattern>();
103     CHECK_NULL_RETURN(pattern, 0);
104     return pattern->GetChildrenCount();
105 }
106 
GetGridItemIndex(const RefPtr<FrameNode> & frameNode)107 int32_t GridEventHub::GetGridItemIndex(const RefPtr<FrameNode>& frameNode)
108 {
109     CHECK_NULL_RETURN(frameNode, 0);
110     auto gridFrameNode = GetFrameNode();
111     CHECK_NULL_RETURN(gridFrameNode, 0);
112     auto gridPattern = gridFrameNode->GetPattern<GridPattern>();
113     CHECK_NULL_RETURN(gridPattern, 0);
114     RefPtr<GridItemPattern> itemPattern = frameNode->GetPattern<GridItemPattern>();
115     CHECK_NULL_RETURN(itemPattern, 0);
116     auto itemProperty = frameNode->GetLayoutProperty<GridItemLayoutProperty>();
117     CHECK_NULL_RETURN(itemProperty, 0);
118 
119     auto gridLayoutInfo = gridPattern->GetGridLayoutInfo();
120     auto mainIndex = itemProperty->GetMainIndex().value_or(-1);
121     auto crossIndex = itemProperty->GetCrossIndex().value_or(-1);
122     auto crossIndexIterator = gridLayoutInfo.gridMatrix_.find(mainIndex);
123     if (crossIndexIterator != gridLayoutInfo.gridMatrix_.end()) {
124         auto crossIndexMap = crossIndexIterator->second;
125 
126         auto indexIterator = crossIndexMap.find(crossIndex);
127         if (indexIterator != crossIndexMap.end()) {
128             return indexIterator->second;
129         }
130     }
131 
132     return 0;
133 }
134 
GetEditable() const135 bool GridEventHub::GetEditable() const
136 {
137     auto host = GetFrameNode();
138     CHECK_NULL_RETURN(host, false);
139     auto layoutProperty = host->GetLayoutProperty<GridLayoutProperty>();
140     CHECK_NULL_RETURN(layoutProperty, false);
141     return layoutProperty->GetEditable().value_or(false);
142 }
143 
HandleOnItemDragStart(const GestureEvent & info)144 void GridEventHub::HandleOnItemDragStart(const GestureEvent& info)
145 {
146     if (!GetEditable()) {
147         return;
148     }
149 
150     auto host = GetFrameNode();
151     CHECK_NULL_VOID(host);
152     auto pipeline = host->GetContext();
153     CHECK_NULL_VOID(pipeline);
154 
155     auto globalX = static_cast<float>(info.GetGlobalPoint().GetX());
156     auto globalY = static_cast<float>(info.GetGlobalPoint().GetY());
157 
158     auto gridItem = host->FindChildByPositionWithoutChildTransform(globalX, globalY);
159     CHECK_NULL_VOID(gridItem);
160     draggedIndex_ = GetGridItemIndex(gridItem);
161 
162     OHOS::Ace::ItemDragInfo itemDragInfo;
163     itemDragInfo.SetX(globalX);
164     itemDragInfo.SetY(globalY);
165     auto customNode = FireOnItemDragStart(itemDragInfo, draggedIndex_);
166     CHECK_NULL_VOID(customNode);
167     auto dragDropManager = pipeline->GetDragDropManager();
168     CHECK_NULL_VOID(dragDropManager);
169     dragDropManager->SetDraggingPointer(info.GetPointerId());
170     dragDropManager->SetDraggingPressedState(true);
171     dragDropManager->SetDragStartPoint(info.GetGlobalPoint().GetX(), info.GetGlobalPoint().GetY());
172 #if defined(PIXEL_MAP_SUPPORTED)
173     auto callback = [id = Container::CurrentId(), pipeline, info, host, gridItem, weak = WeakClaim(this)](
174                         std::shared_ptr<Media::PixelMap> mediaPixelMap, int32_t /*arg*/,
175                         const std::function<void()>& finishCallback) {
176         ContainerScope scope(id);
177         if (!mediaPixelMap) {
178             TAG_LOGE(AceLogTag::ACE_DRAG, "gridItem drag start failed, custom component screenshot is empty.");
179             return;
180         }
181         CHECK_NULL_VOID(pipeline);
182         auto taskScheduler = pipeline->GetTaskExecutor();
183         CHECK_NULL_VOID(taskScheduler);
184         taskScheduler->PostTask(
185             [finishCallback]() {
186                 if (finishCallback) {
187                     finishCallback();
188                 }
189             },
190             TaskExecutor::TaskType::UI, "ArkUIGridItemDragRemoveCustomNode");
191         auto pixelMap = PixelMap::CreatePixelMap(reinterpret_cast<void*>(&mediaPixelMap));
192         CHECK_NULL_VOID(pixelMap);
193         taskScheduler->PostTask(
194             [weak, pipeline, info, pixelMap, host, gridItem]() {
195                 auto eventHub = weak.Upgrade();
196                 CHECK_NULL_VOID(eventHub);
197                 auto manager = pipeline->GetDragDropManager();
198                 CHECK_NULL_VOID(manager);
199                 eventHub->dragDropProxy_ = manager->CreateAndShowItemDragOverlay(pixelMap, info, eventHub);
200                 CHECK_NULL_VOID(eventHub->dragDropProxy_);
201                 eventHub->dragDropProxy_->OnItemDragStart(info, host);
202                 gridItem->GetLayoutProperty()->UpdateVisibility(VisibleType::INVISIBLE);
203                 eventHub->draggingItem_ = gridItem;
204                 if (!manager->IsDraggingPressed(info.GetPointerId())) {
205                     eventHub->HandleOnItemDragEnd(info);
206                 }
207             },
208             TaskExecutor::TaskType::UI, "ArkUIGridItemDragStart");
209     };
210     SnapshotParam param;
211     if (auto pixmap = ComponentSnapshot::CreateSync(customNode, param); pixmap) {
212         callback(pixmap, 0, nullptr);
213         return;
214     }
215     param.delay = CREATE_PIXELMAP_TIME;
216     NG::ComponentSnapshot::Create(customNode, std::move(callback), true, param);
217 #else
218     auto manager = pipeline->GetDragDropManager();
219     CHECK_NULL_VOID(manager);
220     dragDropProxy_ = manager->CreateAndShowItemDragOverlay(customNode, info, AceType::Claim(this));
221     CHECK_NULL_VOID(dragDropProxy_);
222     dragDropProxy_->OnItemDragStart(info, host);
223     gridItem->GetLayoutProperty()->UpdateVisibility(VisibleType::INVISIBLE);
224     draggingItem_ = gridItem;
225     if (!manager->IsDraggingPressed(info.GetPointerId())) {
226         HandleOnItemDragEnd(info);
227     }
228 #endif
229 }
230 
HandleOnItemDragUpdate(const GestureEvent & info)231 void GridEventHub::HandleOnItemDragUpdate(const GestureEvent& info)
232 {
233     if (!GetEditable()) {
234         return;
235     }
236 
237     CHECK_NULL_VOID(dragDropProxy_);
238     dragDropProxy_->OnItemDragMove(info, draggedIndex_, DragType::GRID);
239 }
240 
HandleOnItemDragEnd(const GestureEvent & info)241 void GridEventHub::HandleOnItemDragEnd(const GestureEvent& info)
242 {
243     CHECK_NULL_VOID(dragDropProxy_);
244     if (GetEditable()) {
245         dragDropProxy_->OnItemDragEnd(info, draggedIndex_, DragType::GRID);
246     } else {
247         dragDropProxy_->onItemDragCancel();
248     }
249     dragDropProxy_->DestroyDragWindow();
250     dragDropProxy_ = nullptr;
251     draggedIndex_ = 0;
252     if (draggingItem_) {
253         draggingItem_->GetLayoutProperty()->UpdateVisibility(VisibleType::VISIBLE);
254         draggingItem_ = nullptr;
255     }
256 
257     auto host = GetFrameNode();
258     CHECK_NULL_VOID(host);
259     auto pattern = AceType::DynamicCast<GridPattern>(host->GetPattern());
260     CHECK_NULL_VOID(pattern);
261     pattern->ClearDragState();
262 }
263 
HandleOnItemDragCancel()264 void GridEventHub::HandleOnItemDragCancel()
265 {
266     CHECK_NULL_VOID(dragDropProxy_);
267     dragDropProxy_->onItemDragCancel();
268     dragDropProxy_->DestroyDragWindow();
269     dragDropProxy_ = nullptr;
270     draggedIndex_ = 0;
271     if (draggingItem_) {
272         draggingItem_->GetLayoutProperty()->UpdateVisibility(VisibleType::VISIBLE);
273         draggingItem_ = nullptr;
274     }
275 
276     auto host = GetFrameNode();
277     CHECK_NULL_VOID(host);
278     auto pattern = AceType::DynamicCast<GridPattern>(host->GetPattern());
279     CHECK_NULL_VOID(pattern);
280     pattern->ClearDragState();
281 }
282 
FireOnItemDragEnter(const ItemDragInfo & dragInfo)283 void GridEventHub::FireOnItemDragEnter(const ItemDragInfo& dragInfo)
284 {
285     if (onItemDragEnter_) {
286         onItemDragEnter_(dragInfo);
287     }
288 }
289 
FireOnItemDragLeave(const ItemDragInfo & dragInfo,int32_t itemIndex)290 void GridEventHub::FireOnItemDragLeave(const ItemDragInfo& dragInfo, int32_t itemIndex)
291 {
292     if (itemIndex == -1) {
293         auto host = GetFrameNode();
294         CHECK_NULL_VOID(host);
295         auto pattern = AceType::DynamicCast<GridPattern>(host->GetPattern());
296         CHECK_NULL_VOID(pattern);
297         auto insertIndex = pattern->GetChildrenCount();
298         MoveItems(itemIndex, insertIndex);
299         pattern->ClearDragState();
300     }
301 
302     if (onItemDragLeave_) {
303         onItemDragLeave_(dragInfo, itemIndex);
304     }
305 }
306 
FireOnItemDrop(const ItemDragInfo & dragInfo,int32_t itemIndex,int32_t insertIndex,bool isSuccess)307 bool GridEventHub::FireOnItemDrop(const ItemDragInfo& dragInfo, int32_t itemIndex, int32_t insertIndex, bool isSuccess)
308 {
309     TAG_LOGI(AceLogTag::ACE_GRID, "itemIndex:%{public}d, insertIndex:%{public}d", itemIndex, insertIndex);
310     auto host = GetFrameNode();
311     CHECK_NULL_RETURN(host, false);
312     auto pattern = AceType::DynamicCast<GridPattern>(host->GetPattern());
313     CHECK_NULL_RETURN(pattern, false);
314     if (pattern->SupportAnimation()) {
315         insertIndex = (itemIndex == -1 || insertIndex == -1) ? insertIndex : pattern->GetOriginalIndex();
316         pattern->ClearDragState();
317     }
318 
319     if (onItemDrop_) {
320         onItemDrop_(dragInfo, itemIndex, insertIndex, isSuccess);
321         host->ChildrenUpdatedFrom(0);
322         return true;
323     }
324     host->ChildrenUpdatedFrom(0);
325     return false;
326 }
327 
FireOnItemDragMove(const ItemDragInfo & dragInfo,int32_t itemIndex,int32_t insertIndex) const328 void GridEventHub::FireOnItemDragMove(const ItemDragInfo& dragInfo, int32_t itemIndex, int32_t insertIndex) const
329 {
330     MoveItems(itemIndex, insertIndex);
331 
332     if (onItemDragMove_) {
333         auto host = GetFrameNode();
334         CHECK_NULL_VOID(host);
335         auto pattern = AceType::DynamicCast<GridPattern>(host->GetPattern());
336         CHECK_NULL_VOID(pattern);
337         if (pattern->SupportAnimation()) {
338             insertIndex = (itemIndex == -1 || insertIndex == -1) ? insertIndex : pattern->GetOriginalIndex();
339         }
340         onItemDragMove_(dragInfo, itemIndex, insertIndex);
341     }
342 }
343 
MoveItems(int32_t itemIndex,int32_t insertIndex) const344 void GridEventHub::MoveItems(int32_t itemIndex, int32_t insertIndex) const
345 {
346     auto host = GetFrameNode();
347     CHECK_NULL_VOID(host);
348     auto pattern = AceType::DynamicCast<GridPattern>(host->GetPattern());
349     CHECK_NULL_VOID(pattern);
350     if (!pattern->SupportAnimation()) {
351         return;
352     }
353     constexpr float ANIMATION_CURVE_VELOCITY = 0.0f;    // The move animation spring curve velocity is 0.0
354     constexpr float ANIMATION_CURVE_MASS = 1.0f;        // The move animation spring curve mass is 1.0
355     constexpr float ANIMATION_CURVE_STIFFNESS = 400.0f; // The move animation spring curve stiffness is 110.0
356     constexpr float ANIMATION_CURVE_DAMPING = 38.0f;    // The move animation spring curve damping is 17.0
357     AnimationOption option;
358     constexpr int32_t duration = 400;
359     option.SetDuration(duration);
360     auto curve = MakeRefPtr<SpringCurve>(
361         ANIMATION_CURVE_VELOCITY, ANIMATION_CURVE_MASS, ANIMATION_CURVE_STIFFNESS, ANIMATION_CURVE_DAMPING);
362     option.SetCurve(curve);
363     auto context = host->GetContextRefPtr();
364     CHECK_NULL_VOID(context);
365     AnimationUtils::Animate(
366         option, [pattern, itemIndex, insertIndex]() { pattern->MoveItems(itemIndex, insertIndex); }, nullptr,
367         nullptr, context);
368 }
369 } // namespace OHOS::Ace::NG