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