• 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 #if defined(PIXEL_MAP_SUPPORTED)
172     auto callback = [id = Container::CurrentId(), pipeline, info, host, gridItem, weak = WeakClaim(this)](
173                         std::shared_ptr<Media::PixelMap> mediaPixelMap, int32_t /*arg*/,
174                         const std::function<void()>& finishCallback) {
175         ContainerScope scope(id);
176         if (!mediaPixelMap) {
177             TAG_LOGE(AceLogTag::ACE_DRAG, "gridItem drag start failed, custom component screenshot is empty.");
178             return;
179         }
180         CHECK_NULL_VOID(pipeline);
181         auto taskScheduler = pipeline->GetTaskExecutor();
182         CHECK_NULL_VOID(taskScheduler);
183         taskScheduler->PostTask(
184             [finishCallback]() {
185                 if (finishCallback) {
186                     finishCallback();
187                 }
188             },
189             TaskExecutor::TaskType::UI, "ArkUIGridItemDragRemoveCustomNode");
190         auto pixelMap = PixelMap::CreatePixelMap(reinterpret_cast<void*>(&mediaPixelMap));
191         CHECK_NULL_VOID(pixelMap);
192         taskScheduler->PostTask(
193             [weak, pipeline, info, pixelMap, host, gridItem]() {
194                 auto eventHub = weak.Upgrade();
195                 CHECK_NULL_VOID(eventHub);
196                 auto manager = pipeline->GetDragDropManager();
197                 CHECK_NULL_VOID(manager);
198                 eventHub->dragDropProxy_ = manager->CreateAndShowItemDragOverlay(pixelMap, info, eventHub);
199                 CHECK_NULL_VOID(eventHub->dragDropProxy_);
200                 eventHub->dragDropProxy_->OnItemDragStart(info, host);
201                 gridItem->GetLayoutProperty()->UpdateVisibility(VisibleType::INVISIBLE);
202                 eventHub->draggingItem_ = gridItem;
203                 if (!manager->IsDraggingPressed(info.GetPointerId())) {
204                     eventHub->HandleOnItemDragEnd(info);
205                 }
206             },
207             TaskExecutor::TaskType::UI, "ArkUIGridItemDragStart");
208     };
209     SnapshotParam param;
210     if (auto pixmap = ComponentSnapshot::CreateSync(customNode, param); pixmap) {
211         callback(pixmap, 0, nullptr);
212         return;
213     }
214     param.delay = CREATE_PIXELMAP_TIME;
215     NG::ComponentSnapshot::Create(customNode, std::move(callback), true, param);
216 #else
217     auto manager = pipeline->GetDragDropManager();
218     CHECK_NULL_VOID(manager);
219     dragDropProxy_ = manager->CreateAndShowItemDragOverlay(customNode, info, AceType::Claim(this));
220     CHECK_NULL_VOID(dragDropProxy_);
221     dragDropProxy_->OnItemDragStart(info, host);
222     gridItem->GetLayoutProperty()->UpdateVisibility(VisibleType::INVISIBLE);
223     draggingItem_ = gridItem;
224     if (!manager->IsDraggingPressed(info.GetPointerId())) {
225         HandleOnItemDragEnd(info);
226     }
227 #endif
228 }
229 
HandleOnItemDragUpdate(const GestureEvent & info)230 void GridEventHub::HandleOnItemDragUpdate(const GestureEvent& info)
231 {
232     if (!GetEditable()) {
233         return;
234     }
235 
236     CHECK_NULL_VOID(dragDropProxy_);
237     dragDropProxy_->OnItemDragMove(info, draggedIndex_, DragType::GRID);
238 }
239 
HandleOnItemDragEnd(const GestureEvent & info)240 void GridEventHub::HandleOnItemDragEnd(const GestureEvent& info)
241 {
242     CHECK_NULL_VOID(dragDropProxy_);
243     if (GetEditable()) {
244         dragDropProxy_->OnItemDragEnd(info, draggedIndex_, DragType::GRID);
245     } else {
246         dragDropProxy_->onItemDragCancel();
247     }
248     dragDropProxy_->DestroyDragWindow();
249     dragDropProxy_ = nullptr;
250     draggedIndex_ = 0;
251     if (draggingItem_) {
252         draggingItem_->GetLayoutProperty()->UpdateVisibility(VisibleType::VISIBLE);
253         draggingItem_ = nullptr;
254     }
255 
256     auto host = GetFrameNode();
257     CHECK_NULL_VOID(host);
258     auto pattern = AceType::DynamicCast<GridPattern>(host->GetPattern());
259     CHECK_NULL_VOID(pattern);
260     pattern->ClearDragState();
261 }
262 
HandleOnItemDragCancel()263 void GridEventHub::HandleOnItemDragCancel()
264 {
265     CHECK_NULL_VOID(dragDropProxy_);
266     dragDropProxy_->onItemDragCancel();
267     dragDropProxy_->DestroyDragWindow();
268     dragDropProxy_ = nullptr;
269     draggedIndex_ = 0;
270     if (draggingItem_) {
271         draggingItem_->GetLayoutProperty()->UpdateVisibility(VisibleType::VISIBLE);
272         draggingItem_ = nullptr;
273     }
274 
275     auto host = GetFrameNode();
276     CHECK_NULL_VOID(host);
277     auto pattern = AceType::DynamicCast<GridPattern>(host->GetPattern());
278     CHECK_NULL_VOID(pattern);
279     pattern->ClearDragState();
280 }
281 
FireOnItemDragEnter(const ItemDragInfo & dragInfo)282 void GridEventHub::FireOnItemDragEnter(const ItemDragInfo& dragInfo)
283 {
284     if (onItemDragEnter_) {
285         onItemDragEnter_(dragInfo);
286     }
287 }
288 
FireOnItemDragLeave(const ItemDragInfo & dragInfo,int32_t itemIndex)289 void GridEventHub::FireOnItemDragLeave(const ItemDragInfo& dragInfo, int32_t itemIndex)
290 {
291     if (itemIndex == -1) {
292         auto host = GetFrameNode();
293         CHECK_NULL_VOID(host);
294         auto pattern = AceType::DynamicCast<GridPattern>(host->GetPattern());
295         CHECK_NULL_VOID(pattern);
296         auto insertIndex = pattern->GetChildrenCount();
297         MoveItems(itemIndex, insertIndex);
298         pattern->ClearDragState();
299     }
300 
301     if (onItemDragLeave_) {
302         onItemDragLeave_(dragInfo, itemIndex);
303     }
304 }
305 
FireOnItemDrop(const ItemDragInfo & dragInfo,int32_t itemIndex,int32_t insertIndex,bool isSuccess)306 bool GridEventHub::FireOnItemDrop(const ItemDragInfo& dragInfo, int32_t itemIndex, int32_t insertIndex, bool isSuccess)
307 {
308     TAG_LOGI(AceLogTag::ACE_GRID, "itemIndex:%{public}d, insertIndex:%{public}d", itemIndex, insertIndex);
309     auto host = GetFrameNode();
310     CHECK_NULL_RETURN(host, false);
311     auto pattern = AceType::DynamicCast<GridPattern>(host->GetPattern());
312     CHECK_NULL_RETURN(pattern, false);
313     if (pattern->SupportAnimation()) {
314         insertIndex = (itemIndex == -1 || insertIndex == -1) ? insertIndex : pattern->GetOriginalIndex();
315         pattern->ClearDragState();
316     }
317 
318     if (onItemDrop_) {
319         onItemDrop_(dragInfo, itemIndex, insertIndex, isSuccess);
320         host->ChildrenUpdatedFrom(0);
321         return true;
322     }
323     host->ChildrenUpdatedFrom(0);
324     return false;
325 }
326 
FireOnItemDragMove(const ItemDragInfo & dragInfo,int32_t itemIndex,int32_t insertIndex) const327 void GridEventHub::FireOnItemDragMove(const ItemDragInfo& dragInfo, int32_t itemIndex, int32_t insertIndex) const
328 {
329     MoveItems(itemIndex, insertIndex);
330 
331     if (onItemDragMove_) {
332         auto host = GetFrameNode();
333         CHECK_NULL_VOID(host);
334         auto pattern = AceType::DynamicCast<GridPattern>(host->GetPattern());
335         CHECK_NULL_VOID(pattern);
336         if (pattern->SupportAnimation()) {
337             insertIndex = (itemIndex == -1 || insertIndex == -1) ? insertIndex : pattern->GetOriginalIndex();
338         }
339         onItemDragMove_(dragInfo, itemIndex, insertIndex);
340     }
341 }
342 
MoveItems(int32_t itemIndex,int32_t insertIndex) const343 void GridEventHub::MoveItems(int32_t itemIndex, int32_t insertIndex) const
344 {
345     auto host = GetFrameNode();
346     CHECK_NULL_VOID(host);
347     auto pattern = AceType::DynamicCast<GridPattern>(host->GetPattern());
348     CHECK_NULL_VOID(pattern);
349     if (!pattern->SupportAnimation()) {
350         return;
351     }
352     constexpr float ANIMATION_CURVE_VELOCITY = 0.0f;    // The move animation spring curve velocity is 0.0
353     constexpr float ANIMATION_CURVE_MASS = 1.0f;        // The move animation spring curve mass is 1.0
354     constexpr float ANIMATION_CURVE_STIFFNESS = 400.0f; // The move animation spring curve stiffness is 110.0
355     constexpr float ANIMATION_CURVE_DAMPING = 38.0f;    // The move animation spring curve damping is 17.0
356     AnimationOption option;
357     constexpr int32_t duration = 400;
358     option.SetDuration(duration);
359     auto curve = MakeRefPtr<SpringCurve>(
360         ANIMATION_CURVE_VELOCITY, ANIMATION_CURVE_MASS, ANIMATION_CURVE_STIFFNESS, ANIMATION_CURVE_DAMPING);
361     option.SetCurve(curve);
362     AnimationUtils::Animate(
363         option, [pattern, itemIndex, insertIndex]() { pattern->MoveItems(itemIndex, insertIndex); }, nullptr);
364 }
365 } // namespace OHOS::Ace::NG