• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2024 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 #include "core/components_ng/manager/drag_drop/utils/drag_animation_helper.h"
16 
17 #include "core/components_ng/manager/drag_drop/drag_drop_func_wrapper.h"
18 #include "core/components_ng/manager/drag_drop/drag_drop_controller_func_wrapper.h"
19 #include "core/components_ng/pattern/image/image_pattern.h"
20 #include "core/components_ng/pattern/menu/menu_theme.h"
21 #include "core/components_ng/pattern/menu/preview/menu_preview_pattern.h"
22 #include "core/components_ng/pattern/stack/stack_pattern.h"
23 #include "core/components_ng/pattern/text/text_pattern.h"
24 
25 namespace OHOS::Ace::NG {
26 namespace {
27 constexpr int32_t BEFORE_LIFTING_TIME = 650;
28 constexpr int32_t IMAGE_SHOW_TIME = 50;
29 constexpr int32_t PIXELMAP_ANIMATION_DURATION = 300;
30 constexpr int32_t BADGE_ANIMATION_DURATION = 200;
31 constexpr int32_t BADGE_ANIMATION_DELAY = 100;
32 constexpr int32_t NODE_RESET_DURATION = 200;
33 constexpr float DEFAULT_ANIMATION_SCALE = 0.95f;
34 constexpr float GATHER_SPRING_RESPONSE = 0.304f;
35 constexpr float GATHER_SPRING_DAMPING_FRACTION = 0.97f;
36 constexpr float GRID_MOVE_SCALE = 0.2f;
37 constexpr float LIST_MOVE_SCALE = 0.2f;
38 constexpr float EULER_NUMBER = 2.71828f;
39 constexpr float GATHER_OFFSET_RADIUS = 0.1f;
40 constexpr float PIXELMAP_DRAG_SCALE_MULTIPLE = 1.05f;
41 constexpr float BADGE_ANIMATION_SCALE = 1.0f;
42 constexpr Dimension BADGE_RELATIVE_OFFSET = 8.0_vp;
43 constexpr Dimension BADGE_DEFAULT_SIZE = 24.0_vp;
44 constexpr Dimension BADGE_TEXT_FONT_SIZE = 14.0_fp;
45 const Color BADGE_TEXT_FONT_COLOR = Color::FromString("#ffffffff");
46 const Color BADGE_BACKGROUND_COLOR = Color::FromString("#ff007dff");
47 constexpr float DEFAULT_INTERPOLATING_SPRING_VELOCITY = 10.0f;
48 constexpr float DEFAULT_INTERPOLATING_SPRING_MASS = 1.0f;
49 constexpr float DEFAULT_INTERPOLATING_SPRING_STIFFNESS = 410.0f;
50 constexpr float DEFAULT_INTERPOLATING_SPRING_DAMPING = 38.0f;
51 constexpr float DEFAULT_GRAYED = 0.4f;
52 constexpr float HALF_DIVIDE = 2.0f;
53 const RefPtr<InterpolatingSpring> DRAG_START_ANIMATION_CURVE =
54     AceType::MakeRefPtr<InterpolatingSpring>(0.0f, 0.0f, 380.0f, 34.0f);
55 const RefPtr<InterpolatingSpring> DRAG_END_ANIMATION_CURVE =
56     AceType::MakeRefPtr<InterpolatingSpring>(0.0f, 0.0f, 228.0f, 29.0f);
57 const RefPtr<Curve> DRAG_CONTROL_ANIMATION_CURVE =
58     AceType::MakeRefPtr<ResponsiveSpringMotion>(0.347f, 0.99f, 0.0f);
59 }
60 
CalcDistanceBeforeLifting(bool isGrid,CalcResult & calcResult,OffsetF gatherNodeCenter,const std::vector<GatherNodeChildInfo> & gatherNodeChildrenInfo)61 void DragAnimationHelper::CalcDistanceBeforeLifting(bool isGrid, CalcResult& calcResult, OffsetF gatherNodeCenter,
62     const std::vector<GatherNodeChildInfo>& gatherNodeChildrenInfo)
63 {
64     for (const auto& child : gatherNodeChildrenInfo) {
65         auto imageNode = child.imageNode.Upgrade();
66         CHECK_NULL_VOID(imageNode);
67         auto width = child.width;
68         auto height = child.height;
69         OffsetF curPos = {child.offset.GetX() + child.halfWidth, child.offset.GetY() + child.halfHeight};
70         float dis = sqrt(pow(gatherNodeCenter.GetX() - curPos.GetX(), 2) +
71             pow(gatherNodeCenter.GetY() - curPos.GetY(), 2));
72         calcResult.maxDistance = std::max(calcResult.maxDistance, dis);
73         calcResult.minDistance = calcResult.minDistance < 0 ? dis : std::min(calcResult.minDistance, dis);
74         if (isGrid) {
75             calcResult.maxTranslation = calcResult.maxTranslation < 0 ? std::min(width, height) :
76                 std::min(calcResult.maxTranslation, std::min(width, height));
77         } else {
78             calcResult.maxTranslation = calcResult.maxTranslation < 0 ? height :
79                 std::min(calcResult.maxTranslation, height);
80         }
81     }
82     calcResult.maxTranslation *= isGrid ? GRID_MOVE_SCALE : LIST_MOVE_SCALE;
83 }
84 
CalcOffsetToTarget(OffsetF curPos,OffsetF targetPos,CalcResult & calcResult)85 OffsetF DragAnimationHelper::CalcOffsetToTarget(OffsetF curPos, OffsetF targetPos, CalcResult& calcResult)
86 {
87     if (NearZero(calcResult.maxDistance) || NearZero(calcResult.minDistance) || calcResult.maxTranslation < 0) {
88         return { 0.0f, 0.0f };
89     }
90 
91     float xDis = targetPos.GetX() - curPos.GetX();
92     float yDis = targetPos.GetY() - curPos.GetY();
93     float dis = sqrt(pow(xDis, 2) + pow(yDis, 2));
94     if (NearZero(dis)) {
95         return { 0.0f, 0.0f };
96     }
97     auto trans = calcResult.maxTranslation * pow(EULER_NUMBER, -(dis - calcResult.minDistance) /
98         calcResult.maxDistance * GATHER_OFFSET_RADIUS);
99     float x = xDis * trans / dis;
100     float y = yDis * trans / dis;
101     return { x, y };
102 }
103 
PlayGatherNodeTranslateAnimation(const RefPtr<FrameNode> & frameNode,const RefPtr<OverlayManager> & overlayManager)104 void DragAnimationHelper::PlayGatherNodeTranslateAnimation(const RefPtr<FrameNode>& frameNode,
105     const RefPtr<OverlayManager>& overlayManager)
106 {
107     CHECK_NULL_VOID(overlayManager);
108     CHECK_NULL_VOID(frameNode);
109     AnimationOption option;
110     option.SetDuration(BEFORE_LIFTING_TIME);
111     option.SetCurve(Curves::SHARP);
112     auto gatherNodeCenter = DragDropFuncWrapper::GetPaintRectCenterToScreen(frameNode);
113     auto gatherNodeChildrenInfo = overlayManager->GetGatherNodeChildrenInfo();
114 
115     bool isGrid = frameNode->GetTag() == V2::GRID_ITEM_ETS_TAG;
116     CalcResult calcResult = { 0.0f, -1.0f, -1.0f };
117     CalcDistanceBeforeLifting(isGrid, calcResult, gatherNodeCenter, gatherNodeChildrenInfo);
118     AnimationUtils::Animate(
119         option,
120         [gatherNodeCenter, gatherNodeChildrenInfo, calcResult]() mutable {
121             for (const auto& child : gatherNodeChildrenInfo) {
122                 auto imageNode = child.imageNode.Upgrade();
123                 auto curPos = child.offset + OffsetF(child.halfWidth, child.halfHeight);
124                 auto offset = CalcOffsetToTarget(curPos, gatherNodeCenter, calcResult);
125                 offset += child.offset;
126                 DragDropFuncWrapper::UpdateNodePositionToScreen(imageNode, offset);
127             }
128         });
129 }
130 
PlayGatherNodeOpacityAnimation(const RefPtr<OverlayManager> & overlayManager)131 void DragAnimationHelper::PlayGatherNodeOpacityAnimation(const RefPtr<OverlayManager>& overlayManager)
132 {
133     CHECK_NULL_VOID(overlayManager);
134     auto gatherNodeChildrenInfo = overlayManager->GetGatherNodeChildrenInfo();
135 
136     AnimationOption opacityOption;
137     opacityOption.SetDuration(IMAGE_SHOW_TIME);
138     opacityOption.SetCurve(AceType::MakeRefPtr<CubicCurve>(0.0f, 0.0f, 1.0f, 1.0f));
139 
140     for (const auto& child : gatherNodeChildrenInfo) {
141         auto imageNode = child.imageNode.Upgrade();
142         CHECK_NULL_VOID(imageNode);
143         auto imageContext = imageNode->GetRenderContext();
144         CHECK_NULL_VOID(imageContext);
145         imageContext->OpacityAnimation(opacityOption, 0.0f, 1.0f);
146     }
147 }
148 
PlayGatherAnimationBeforeLifting(const RefPtr<DragEventActuator> & actuator)149 void DragAnimationHelper::PlayGatherAnimationBeforeLifting(const RefPtr<DragEventActuator>& actuator)
150 {
151     TAG_LOGI(AceLogTag::ACE_DRAG, "Play gather animation before lifting");
152     CHECK_NULL_VOID(actuator);
153     if (!actuator->IsNeedGather()) {
154         return;
155     }
156     auto pipeline = PipelineContext::GetCurrentContextSafelyWithCheck();
157     CHECK_NULL_VOID(pipeline);
158     auto manager = pipeline->GetOverlayManager();
159     CHECK_NULL_VOID(manager);
160     auto frameNode = actuator->GetFrameNode();
161     CHECK_NULL_VOID(frameNode);
162     auto gatherNode = actuator->GetGatherNode();
163     CHECK_NULL_VOID(gatherNode);
164     auto imageContext = gatherNode->GetRenderContext();
165     CHECK_NULL_VOID(imageContext);
166     imageContext->UpdatePosition(OffsetT<Dimension>(Dimension(0.0f), Dimension(0.0f)));
167     auto gatherNodeChildrenInfo = actuator->GetGatherNodeChildrenInfo();
168     DragEventActuator::MountGatherNode(manager, frameNode, gatherNode, gatherNodeChildrenInfo);
169     actuator->ClearGatherNodeChildrenInfo();
170     actuator->InitGatherNodesPosition(gatherNodeChildrenInfo);
171     pipeline->FlushSyncGeometryNodeTasks();
172     manager->SetIsGatherWithMenu(false);
173     PlayGatherNodeOpacityAnimation(manager);
174     PlayGatherNodeTranslateAnimation(frameNode, manager);
175 }
176 
PlayNodeAnimationBeforeLifting(const RefPtr<FrameNode> & frameNode)177 void DragAnimationHelper::PlayNodeAnimationBeforeLifting(const RefPtr<FrameNode>& frameNode)
178 {
179     CHECK_NULL_VOID(frameNode);
180     auto previewOptions = frameNode->GetDragPreviewOption();
181     if (!previewOptions.defaultAnimationBeforeLifting) {
182         return;
183     }
184     AnimationOption option;
185     option.SetDuration(BEFORE_LIFTING_TIME);
186     auto springCurve = AceType::MakeRefPtr<InterpolatingSpring>(DEFAULT_INTERPOLATING_SPRING_VELOCITY,
187         DEFAULT_INTERPOLATING_SPRING_MASS, DEFAULT_INTERPOLATING_SPRING_STIFFNESS,
188         DEFAULT_INTERPOLATING_SPRING_DAMPING);
189     option.SetCurve(springCurve);
190     auto renderContext = frameNode->GetRenderContext();
191     CHECK_NULL_VOID(renderContext);
192     renderContext->UpdateTransformScale({ 1.0f, 1.0f });
193 
194     AnimationUtils::Animate(
195         option,
196         [renderContext]() mutable {
197             CHECK_NULL_VOID(renderContext);
198             renderContext->UpdateTransformScale({ DEFAULT_ANIMATION_SCALE, DEFAULT_ANIMATION_SCALE });
199         });
200 }
201 
PlayNodeResetAnimation(const RefPtr<DragEventActuator> & actuator)202 void DragAnimationHelper::PlayNodeResetAnimation(const RefPtr<DragEventActuator>& actuator)
203 {
204     CHECK_NULL_VOID(actuator);
205     auto frameNode = actuator->GetFrameNode();
206     CHECK_NULL_VOID(frameNode);
207     bool defaultAnimationBeforeLifting = frameNode->GetDragPreviewOption().defaultAnimationBeforeLifting;
208     if (!defaultAnimationBeforeLifting) {
209         return;
210     }
211     auto frameContext = frameNode->GetRenderContext();
212     CHECK_NULL_VOID(frameContext);
213     auto layoutProperty = frameNode->GetLayoutProperty();
214     if (layoutProperty) {
215         layoutProperty->UpdateVisibility(VisibleType::VISIBLE);
216     }
217     AnimationOption option;
218     option.SetDuration(PIXELMAP_ANIMATION_DURATION);
219     const RefPtr<Curve> curve = AceType::MakeRefPtr<ResponsiveSpringMotion>(0.33f, 0.67f, 1.0f);
220     option.SetCurve(curve);
221     AnimationUtils::Animate(
222         option,
223         [frameContext]() mutable {
224             frameContext->UpdateTransformScale({ 1.0f, 1.0f });
225         },
226         option.GetOnFinishEvent());
227 }
228 
PlayGatherAnimation(const RefPtr<FrameNode> & frameNode,const RefPtr<OverlayManager> & overlayManager)229 void DragAnimationHelper::PlayGatherAnimation(const RefPtr<FrameNode>& frameNode,
230     const RefPtr<OverlayManager>& overlayManager)
231 {
232     TAG_LOGI(AceLogTag::ACE_DRAG, "Play gather animation");
233     CHECK_NULL_VOID(frameNode);
234     auto gatherNodeCenter = DragDropFuncWrapper::GetPaintRectCenter(frameNode);
235     CHECK_NULL_VOID(overlayManager);
236     auto gatherNodeChildrenInfo = overlayManager->GetGatherNodeChildrenInfo();
237     BorderRadiusProperty borderRadius;
238     borderRadius.SetRadius(0.0_vp);
239     borderRadius.multiValued = false;
240     for (const auto& child : gatherNodeChildrenInfo) {
241         auto imageNode = child.imageNode.Upgrade();
242         CHECK_NULL_VOID(imageNode);
243         auto imageContext = imageNode->GetRenderContext();
244         CHECK_NULL_VOID(imageContext);
245         imageContext->UpdateBorderRadius(borderRadius);
246     }
247 
248     AnimationOption option;
249     option.SetDuration(PIXELMAP_ANIMATION_DURATION);
250     const RefPtr<Curve> curve = AceType::MakeRefPtr<ResponsiveSpringMotion>(GATHER_SPRING_RESPONSE,
251         GATHER_SPRING_DAMPING_FRACTION, 0.0f);
252     option.SetCurve(curve);
253     auto geometryNode = frameNode->GetGeometryNode();
254     CHECK_NULL_VOID(geometryNode);
255     auto frameNodeSize = geometryNode->GetFrameSize();
256     auto renderContext = frameNode->GetRenderContext();
257     CHECK_NULL_VOID(renderContext);
258     GatherAnimationInfo gatherAnimationInfo = { PIXELMAP_DRAG_SCALE_MULTIPLE, frameNodeSize.Width(),
259         frameNodeSize.Height(), gatherNodeCenter, renderContext->GetBorderRadius() };
260     AnimationUtils::Animate(
261         option,
262         [weakOverlayManager = AceType::WeakClaim(AceType::RawPtr(overlayManager)), gatherAnimationInfo,
263             weak = AceType::WeakClaim(AceType::RawPtr(frameNode))]() {
264             auto overlayManager = weakOverlayManager.Upgrade();
265             auto frameNode = weak.Upgrade();
266             DragDropManager::UpdateGatherNodeAttr(overlayManager, gatherAnimationInfo);
267             DragDropManager::UpdateGatherNodePosition(overlayManager, frameNode);
268         },
269         option.GetOnFinishEvent());
270 }
271 
ShowBadgeAnimation(const RefPtr<FrameNode> & textNode)272 void DragAnimationHelper::ShowBadgeAnimation(const RefPtr<FrameNode>& textNode)
273 {
274     auto pipelineContext = PipelineContext::GetCurrentContextSafelyWithCheck();
275     CHECK_NULL_VOID(pipelineContext);
276     auto dragDropManager = pipelineContext->GetDragDropManager();
277     CHECK_NULL_VOID(dragDropManager);
278     CHECK_NULL_VOID(textNode);
279     auto textNodeContext = textNode->GetRenderContext();
280     CHECK_NULL_VOID(textNodeContext);
281     textNodeContext->SetVisible(true);
282     auto windowScale = dragDropManager->GetWindowScale();
283     auto badgeScale = GreatNotEqual(windowScale, 0.0f) ? BADGE_ANIMATION_SCALE / windowScale : BADGE_ANIMATION_SCALE;
284     if (!dragDropManager->IsShowBadgeAnimation()) {
285         textNodeContext->UpdateTransformScale({ badgeScale, badgeScale });
286         return;
287     }
288     textNodeContext->UpdateTransformScale({ 0.0f, 0.0f });
289     RefPtr<Curve> interpolatingSpring = AceType::MakeRefPtr<InterpolatingSpring>(0.0f, 1.0f, 628.0f, 40.0f);
290     CHECK_NULL_VOID(interpolatingSpring);
291     AnimationOption textOption;
292     textOption.SetDuration(BADGE_ANIMATION_DURATION);
293     textOption.SetCurve(interpolatingSpring);
294     textOption.SetDelay(BADGE_ANIMATION_DELAY);
295     AnimationUtils::Animate(
296         textOption,
297         [textNodeContext, badgeScale]() mutable {
298             textNodeContext->UpdateTransformScale({ badgeScale, badgeScale });
299         },
300         textOption.GetOnFinishEvent());
301 
302     dragDropManager->SetIsShowBadgeAnimation(false);
303 }
304 
CalcBadgeTextOffset(const RefPtr<MenuPattern> & menuPattern,const RefPtr<FrameNode> & imageNode,const RefPtr<PipelineBase> & context,int32_t badgeLength)305 OffsetF DragAnimationHelper::CalcBadgeTextOffset(const RefPtr<MenuPattern>& menuPattern,
306     const RefPtr<FrameNode>& imageNode, const RefPtr<PipelineBase>& context, int32_t badgeLength)
307 {
308     CHECK_NULL_RETURN(imageNode, OffsetF());
309     CHECK_NULL_RETURN(menuPattern, OffsetF());
310     auto offset = imageNode->GetPaintRectOffset();
311     auto width = imageNode->GetGeometryNode()->GetFrameSize().Width();
312     auto scaleAfter = menuPattern->GetPreviewAfterAnimationScale();
313     auto menuTheme = context->GetTheme<NG::MenuTheme>();
314     CHECK_NULL_RETURN(menuTheme, OffsetF());
315     auto previewAfterAnimationScale =
316         LessNotEqual(scaleAfter, 0.0) ? menuTheme->GetPreviewAfterAnimationScale() : scaleAfter;
317     double textOffsetX = offset.GetX() + width * previewAfterAnimationScale -
318         BADGE_RELATIVE_OFFSET.ConvertToPx() - (BADGE_RELATIVE_OFFSET.ConvertToPx() * badgeLength);
319     double textOffsetY = offset.GetY() - BADGE_RELATIVE_OFFSET.ConvertToPx();
320     return OffsetF(textOffsetX, textOffsetY);
321 }
322 
CalcBadgeTextPosition(const RefPtr<MenuPattern> & menuPattern,const RefPtr<OverlayManager> & manager,const RefPtr<FrameNode> & imageNode,const RefPtr<FrameNode> & textNode)323 void DragAnimationHelper::CalcBadgeTextPosition(const RefPtr<MenuPattern>& menuPattern,
324     const RefPtr<OverlayManager>& manager, const RefPtr<FrameNode>& imageNode, const RefPtr<FrameNode>& textNode)
325 {
326     CHECK_NULL_VOID(manager);
327     CHECK_NULL_VOID(textNode);
328     CHECK_NULL_VOID(menuPattern);
329     auto pipelineContext = PipelineContext::GetCurrentContextSafelyWithCheck();
330     CHECK_NULL_VOID(pipelineContext);
331     auto dragDropManager = pipelineContext->GetDragDropManager();
332     CHECK_NULL_VOID(dragDropManager);
333     auto frameNode = FrameNode::GetFrameNode(menuPattern->GetTargetTag(), menuPattern->GetTargetId());
334     CHECK_NULL_VOID(frameNode);
335     auto badgeNumber = frameNode->GetDragPreviewOption().GetCustomerBadgeNumber();
336     auto childSize = badgeNumber.has_value() ? static_cast<size_t>(badgeNumber.value()) :
337                                         manager->GetGatherNodeChildrenInfo().size() + 1;
338     TAG_LOGI(AceLogTag::ACE_DRAG, "Badge node number %{public}d, children count %{public}d",
339         badgeNumber.value_or(-1), static_cast<int32_t>(manager->GetGatherNodeChildrenInfo().size()));
340     auto badgeLength = std::to_string(childSize).size();
341     UpdateBadgeLayoutAndRenderContext(textNode, badgeLength, childSize);
342     auto textRenderContext = textNode->GetRenderContext();
343     CHECK_NULL_VOID(textRenderContext);
344     auto offset = CalcBadgeTextOffset(menuPattern, imageNode, pipelineContext, badgeLength);
345     textRenderContext->UpdatePosition(OffsetT<Dimension>(Dimension(offset.GetX()), Dimension(offset.GetY())));
346     textNode->MarkDirtyNode(NG::PROPERTY_UPDATE_MEASURE);
347     textNode->MarkModifyDone();
348     textNode->SetLayoutDirtyMarked(true);
349     textNode->SetActive(true);
350     auto context = textNode->GetContext();
351     if (context) {
352         context->FlushUITaskWithSingleDirtyNode(textNode);
353     }
354     pipelineContext->FlushSyncGeometryNodeTasks();
355 }
356 
UpdateBadgeLayoutAndRenderContext(const RefPtr<FrameNode> & textNode,int32_t badgeLength,int32_t childSize)357 void DragAnimationHelper::UpdateBadgeLayoutAndRenderContext(
358     const RefPtr<FrameNode>& textNode, int32_t badgeLength, int32_t childSize)
359 {
360     if (childSize <= 1) {
361         return;
362     }
363     CHECK_NULL_VOID(textNode);
364     auto textLayoutProperty = textNode->GetLayoutProperty<TextLayoutProperty>();
365     CHECK_NULL_VOID(textLayoutProperty);
366     textLayoutProperty->UpdateContent(std::to_string(childSize));
367     textLayoutProperty->UpdateMaxLines(1);
368     textLayoutProperty->UpdateFontWeight(FontWeight::MEDIUM);
369     textLayoutProperty->UpdateTextColor(BADGE_TEXT_FONT_COLOR);
370     textLayoutProperty->UpdateFontSize(BADGE_TEXT_FONT_SIZE);
371     textLayoutProperty->UpdateTextAlign(TextAlign::CENTER);
372     int64_t textWidth = BADGE_DEFAULT_SIZE.ConvertToPx() + (BADGE_RELATIVE_OFFSET.ConvertToPx() * (badgeLength - 1));
373     auto textSize = CalcSize(NG::CalcLength(textWidth), NG::CalcLength(BADGE_DEFAULT_SIZE.ConvertToPx()));
374     textLayoutProperty->UpdateUserDefinedIdealSize(textSize);
375 
376     auto textRenderContext = textNode->GetRenderContext();
377     CHECK_NULL_VOID(textRenderContext);
378     textRenderContext->SetVisible(true);
379     textRenderContext->UpdateBackgroundColor(BADGE_BACKGROUND_COLOR);
380     BorderRadiusProperty borderRadius;
381     borderRadius.SetRadius(BADGE_DEFAULT_SIZE);
382     textRenderContext->UpdateBorderRadius(borderRadius);
383 }
384 
UpdateGatherNodeToTop()385 void DragAnimationHelper::UpdateGatherNodeToTop()
386 {
387     auto mainPipeline = PipelineContext::GetMainPipelineContext();
388     CHECK_NULL_VOID(mainPipeline);
389     auto manager = mainPipeline->GetOverlayManager();
390     CHECK_NULL_VOID(manager);
391     manager->UpdateGatherNodeToTop();
392 }
393 
ShowGatherAnimationWithMenu(const RefPtr<FrameNode> & menuWrapperNode)394 void DragAnimationHelper::ShowGatherAnimationWithMenu(const RefPtr<FrameNode>& menuWrapperNode)
395 {
396     auto mainPipeline = PipelineContext::GetMainPipelineContext();
397     CHECK_NULL_VOID(mainPipeline);
398     auto manager = mainPipeline->GetOverlayManager();
399     CHECK_NULL_VOID(manager);
400     manager->SetIsGatherWithMenu(true);
401 
402     mainPipeline->AddAfterRenderTask([weakWrapperNode = AceType::WeakClaim(AceType::RawPtr(menuWrapperNode)),
403         weakManager = AceType::WeakClaim(AceType::RawPtr(manager))]() {
404         auto menuWrapperNode = weakWrapperNode.Upgrade();
405         CHECK_NULL_VOID(menuWrapperNode);
406         auto menuWrapperPattern = menuWrapperNode->GetPattern<MenuWrapperPattern>();
407         CHECK_NULL_VOID(menuWrapperPattern);
408         auto manager = weakManager.Upgrade();
409         auto textNode = menuWrapperPattern->GetBadgeNode();
410         auto imageNode = menuWrapperPattern->GetPreview();
411         auto menuNode = menuWrapperPattern->GetMenu();
412         CHECK_NULL_VOID(menuNode);
413         auto menuPattern = menuNode->GetPattern<MenuPattern>();
414         DragAnimationHelper::PlayGatherAnimation(imageNode, manager);
415         DragAnimationHelper::CalcBadgeTextPosition(menuPattern, manager, imageNode, textNode);
416         DragAnimationHelper::ShowBadgeAnimation(textNode);
417     });
418 }
419 
SetPreOpacity(const RefPtr<FrameNode> & preNode)420 void DragAnimationHelper::SetPreOpacity(const RefPtr<FrameNode>& preNode)
421 {
422     auto grayedOpacity = preNode->GetPreGrayedOpacity();
423     DoGrayedAnimation(preNode, grayedOpacity, DRAG_END_ANIMATION_CURVE);
424 }
425 
DoDragStartGrayedAnimation(const RefPtr<FrameNode> & frameNode)426 void DragAnimationHelper::DoDragStartGrayedAnimation(const RefPtr<FrameNode>& frameNode)
427 {
428     CHECK_NULL_VOID(frameNode);
429     auto renderContext = frameNode->GetRenderContext();
430     CHECK_NULL_VOID(renderContext);
431     float opacity = 1.0f;
432     if (renderContext->HasOpacity()) {
433         opacity = renderContext->GetOpacityValue();
434         frameNode->SetPreGrayedOpacity(opacity);
435     }
436     DoGrayedAnimation(frameNode, opacity * DEFAULT_GRAYED, DRAG_START_ANIMATION_CURVE);
437 }
438 
DoGrayedAnimation(const RefPtr<FrameNode> & frameNode,float opacity,RefPtr<InterpolatingSpring> cure)439 void DragAnimationHelper::DoGrayedAnimation(
440     const RefPtr<FrameNode>& frameNode, float opacity, RefPtr<InterpolatingSpring> cure)
441 {
442     CHECK_NULL_VOID(frameNode);
443     auto frameTag = frameNode->GetTag();
444     auto gestureHub = frameNode->GetOrCreateGestureEventHub();
445     CHECK_NULL_VOID(gestureHub);
446     if (gestureHub->IsTextCategoryComponent(frameTag)) {
447         return;
448     }
449     AnimationOption option;
450     option.SetCurve(cure);
451     AnimationUtils::Animate(
452         option, [frameNode, opacity]() { ACE_UPDATE_NODE_RENDER_CONTEXT(Opacity, opacity, frameNode); },
453         option.GetOnFinishEvent());
454 }
455 
CreateImageNode(const RefPtr<PixelMap> & pixelMap)456 RefPtr<FrameNode> DragAnimationHelper::CreateImageNode(const RefPtr<PixelMap>& pixelMap)
457 {
458     CHECK_NULL_RETURN(pixelMap, nullptr);
459     auto width = pixelMap->GetWidth();
460     auto height = pixelMap->GetHeight();
461     auto imageNode = FrameNode::GetOrCreateFrameNode(V2::IMAGE_ETS_TAG,
462         ElementRegister::GetInstance()->MakeUniqueId(), []() { return AceType::MakeRefPtr<ImagePattern>(); });
463     CHECK_NULL_RETURN(imageNode, nullptr);
464     auto renderProps = imageNode->GetPaintProperty<ImageRenderProperty>();
465     CHECK_NULL_RETURN(renderProps, nullptr);
466     renderProps->UpdateImageInterpolation(ImageInterpolation::HIGH);
467     renderProps->UpdateNeedBorderRadius(false);
468     auto props = imageNode->GetLayoutProperty<ImageLayoutProperty>();
469     CHECK_NULL_RETURN(props, nullptr);
470     props->UpdateAutoResize(false);
471     props->UpdateImageSourceInfo(ImageSourceInfo(pixelMap));
472     auto targetSize = CalcSize(NG::CalcLength(width), NG::CalcLength(height));
473     props->UpdateUserDefinedIdealSize(targetSize);
474     auto imageContext = imageNode->GetRenderContext();
475     CHECK_NULL_RETURN(imageContext, nullptr);
476     Vector5F rotate = Vector5F(0.0f, 0.0f, 1.0f, 0.0f, 0.0f);
477     imageContext->UpdateTransformRotate(rotate);
478     imageContext->UpdateClipEdge(true);
479     imageContext->UpdateBorderRadius(BorderRadiusProperty(Dimension()));
480     imageContext->UpdateOpacity(1.0f);
481     auto imagePattern = imageNode->GetPattern<ImagePattern>();
482     if (imagePattern) {
483         imagePattern->SetSyncLoad(true);
484     }
485     ClickEffectInfo clickEffectInfo;
486     clickEffectInfo.level = ClickEffectLevel::LIGHT;
487     clickEffectInfo.scaleNumber = DEFAULT_ANIMATION_SCALE;
488     imageContext->UpdateClickEffectLevel(clickEffectInfo);
489     return imageNode;
490 }
491 
CreateGatherNode(const RefPtr<FrameNode> & frameNode,std::vector<GatherNodeChildInfo> & gatherNodeInfo)492 RefPtr<FrameNode> DragAnimationHelper::CreateGatherNode(const RefPtr<FrameNode>& frameNode,
493     std::vector<GatherNodeChildInfo>& gatherNodeInfo)
494 {
495     CHECK_NULL_RETURN(frameNode, nullptr);
496     auto parentNode = DragDropFuncWrapper::FindItemParentNode(frameNode);
497     CHECK_NULL_RETURN(parentNode, nullptr);
498     auto scrollPattern = parentNode->GetPattern<ScrollablePattern>();
499     CHECK_NULL_RETURN(scrollPattern, nullptr);
500     auto children = scrollPattern->GetVisibleSelectedItems();
501     if (children.empty()) {
502         return nullptr;
503     }
504 
505     auto stackNode = FrameNode::GetOrCreateFrameNode(V2::STACK_ETS_TAG, ElementRegister::GetInstance()->MakeUniqueId(),
506         []() { return AceType::MakeRefPtr<StackPattern>(); });
507     CHECK_NULL_RETURN(stackNode, nullptr);
508     auto geometryNode = stackNode->GetGeometryNode();
509     CHECK_NULL_RETURN(geometryNode, nullptr);
510     geometryNode->SetFrameOffset({0.0f, 0.0f});
511     gatherNodeInfo.clear();
512     for (auto iter = children.rbegin(); iter != children.rend(); iter++) {
513         auto itemFrameNode = (*iter);
514         if (itemFrameNode == frameNode) {
515             continue;
516         }
517         GatherNodeChildInfo gatherNodeChildInfo;
518         auto imageNode = CreateGatherImageNode(itemFrameNode, gatherNodeChildInfo);
519         CHECK_NULL_RETURN(imageNode, nullptr);
520         stackNode->AddChild(imageNode);
521         gatherNodeInfo.push_back(gatherNodeChildInfo);
522     }
523     TAG_LOGI(AceLogTag::ACE_DRAG, "Create gather node success, count %{public}d",
524         static_cast<int32_t>(children.size()));
525     return stackNode;
526 }
527 
GetOrCreateGatherNode(const RefPtr<NG::OverlayManager> & overlayManager,const RefPtr<DragEventActuator> & actuator,std::vector<GatherNodeChildInfo> & info)528 RefPtr<FrameNode> DragAnimationHelper::GetOrCreateGatherNode(const RefPtr<NG::OverlayManager>& overlayManager,
529     const RefPtr<DragEventActuator>& actuator, std::vector<GatherNodeChildInfo>& info)
530 {
531     CHECK_NULL_RETURN(actuator, nullptr);
532     if (!actuator->IsNeedGather()) {
533         return nullptr;
534     }
535     auto frameNode = actuator->GetFrameNode();
536     CHECK_NULL_RETURN(frameNode, nullptr);
537     auto previewOptions = frameNode->GetDragPreviewOption();
538     if (!previewOptions.isMultiSelectionEnabled) {
539         return nullptr;
540     }
541     CHECK_NULL_RETURN(overlayManager, nullptr);
542     auto gatherNode = overlayManager->GetGatherNode();
543     if (!gatherNode) {
544         gatherNode = CreateGatherNode(frameNode, info);
545         if (gatherNode) {
546             MarkDirtyNode(gatherNode);
547         }
548         return gatherNode;
549     } else {
550         info = overlayManager->GetGatherNodeChildrenInfo();
551         overlayManager->RemoveGatherNode();
552     }
553     return gatherNode;
554 }
555 
CreateGatherImageNode(const RefPtr<FrameNode> & frameNode,GatherNodeChildInfo & gatherNodeChildInfo)556 RefPtr<FrameNode> DragAnimationHelper::CreateGatherImageNode(const RefPtr<FrameNode>& frameNode,
557     GatherNodeChildInfo& gatherNodeChildInfo)
558 {
559     CHECK_NULL_RETURN(frameNode, nullptr);
560     auto pixelMap = DragDropFuncWrapper::GetGatherNodePreviewPixelMap(frameNode);
561     CHECK_NULL_RETURN(pixelMap, nullptr);
562     int32_t width = pixelMap->GetWidth();
563     int32_t height = pixelMap->GetHeight();
564     auto offset = DragDropFuncWrapper::GetPaintRectCenter(frameNode) - OffsetF(width / 2.0f, height / 2.0f);
565     auto imageNode = CreateImageNode(pixelMap);
566     CHECK_NULL_RETURN(imageNode, nullptr);
567     auto imageContext = imageNode->GetRenderContext();
568     CHECK_NULL_RETURN(imageContext, nullptr);
569     imageContext->UpdatePosition(OffsetT<Dimension>(Dimension(offset.GetX()), Dimension(offset.GetY())));
570 
571     gatherNodeChildInfo = { imageNode,
572         offset + DragDropFuncWrapper::GetCurrentWindowOffset(frameNode->GetContextRefPtr()), width, height,
573         width / 2.0f, height / 2.0f, WeakPtr<FrameNode>(frameNode) };
574     return imageNode;
575 }
576 
MountGatherNode(const RefPtr<OverlayManager> & overlayManager,const RefPtr<FrameNode> & frameNode,const RefPtr<FrameNode> & gatherNode,const std::vector<GatherNodeChildInfo> & gatherNodeInfo)577 void DragAnimationHelper::MountGatherNode(const RefPtr<OverlayManager>& overlayManager,
578     const RefPtr<FrameNode>& frameNode, const RefPtr<FrameNode>& gatherNode,
579     const std::vector<GatherNodeChildInfo>& gatherNodeInfo)
580 {
581     if (!overlayManager || !frameNode || !gatherNode) {
582         return;
583     }
584     TAG_LOGI(AceLogTag::ACE_DRAG, "Mount gather node");
585     auto container = Container::Current();
586     if (container && container->IsScenceBoardWindow()) {
587         auto windowScene = overlayManager->FindWindowScene(frameNode);
588         overlayManager->MountGatherNodeToWindowScene(gatherNode, gatherNodeInfo, windowScene);
589     } else {
590         overlayManager->MountGatherNodeToRootNode(gatherNode, gatherNodeInfo);
591     }
592 }
593 
MarkDirtyNode(const RefPtr<FrameNode> & frameNode)594 void DragAnimationHelper::MarkDirtyNode(const RefPtr<FrameNode>& frameNode)
595 {
596     CHECK_NULL_VOID(frameNode);
597     frameNode->MarkModifyDone();
598     frameNode->SetLayoutDirtyMarked(true);
599     auto context = frameNode->GetContext();
600     if (context) {
601         context->FlushUITaskWithSingleDirtyNode(frameNode);
602     }
603 
604     auto children = frameNode->GetChildren();
605     for (const auto& child : children) {
606         CHECK_NULL_VOID(child);
607         auto imageNode = AceType::DynamicCast<FrameNode>(child);
608         CHECK_NULL_VOID(imageNode);
609         MarkDirtyNode(imageNode);
610     }
611 }
612 
InitGatherNodeAttr(const RefPtr<FrameNode> & gatherNode,const std::vector<GatherNodeChildInfo> & gatherNodeInfo)613 void DragAnimationHelper::InitGatherNodeAttr(const RefPtr<FrameNode>& gatherNode,
614     const std::vector<GatherNodeChildInfo>& gatherNodeInfo)
615 {
616     CHECK_NULL_VOID(gatherNode);
617     auto renderContext = gatherNode->GetRenderContext();
618     if (renderContext) {
619         renderContext->UpdatePosition(OffsetT<Dimension>(Dimension(0.0f), Dimension(0.0f)));
620     }
621     for (auto childInfo : gatherNodeInfo) {
622         auto imageNode = childInfo.imageNode.Upgrade();
623         DragDropFuncWrapper::UpdateNodePositionToScreen(imageNode, childInfo.offset);
624     }
625 }
626 
ShowGatherNodeAnimation(const RefPtr<FrameNode> & frameNode)627 bool DragAnimationHelper::ShowGatherNodeAnimation(const RefPtr<FrameNode>& frameNode)
628 {
629     TAG_LOGI(AceLogTag::ACE_DRAG, "Show gather node animation");
630     CHECK_NULL_RETURN(frameNode, false);
631     auto pipeline = frameNode->GetContextRefPtr();
632     CHECK_NULL_RETURN(pipeline, false);
633     auto manager = pipeline->GetOverlayManager();
634     CHECK_NULL_RETURN(manager, false);
635 
636     if (manager->GetHasGatherNode()) {
637         TAG_LOGW(AceLogTag::ACE_DRAG, "Not need create gather node, already have");
638         return false;
639     }
640 
641     //create gather node
642     std::vector<GatherNodeChildInfo> gatherNodeInfo;
643     auto gatherNode = CreateGatherNode(frameNode, gatherNodeInfo);
644     CHECK_NULL_RETURN(gatherNode, false);
645     MountGatherNode(manager, frameNode, gatherNode, gatherNodeInfo);
646     InitGatherNodeAttr(gatherNode, gatherNodeInfo);
647     AddDragNodeCopy(manager, frameNode, gatherNode);
648     MarkDirtyNode(gatherNode);
649 
650     pipeline->FlushPipelineImmediately();
651     manager->SetIsGatherWithMenu(false);
652 
653     //do gather animation before lifting
654     PlayGatherNodeOpacityAnimation(manager);
655     PlayGatherNodeTranslateAnimation(frameNode, manager);
656     ShowDragNodeCopyAnimation(manager, frameNode);
657     return true;
658 }
659 
AddDragNodeCopy(const RefPtr<OverlayManager> & overlayManager,const RefPtr<FrameNode> & frameNode,const RefPtr<FrameNode> & gatherNode)660 void DragAnimationHelper::AddDragNodeCopy(const RefPtr<OverlayManager>& overlayManager,
661     const RefPtr<FrameNode>& frameNode, const RefPtr<FrameNode>& gatherNode)
662 {
663     CHECK_NULL_VOID(frameNode);
664     CHECK_NULL_VOID(gatherNode);
665     CHECK_NULL_VOID(overlayManager);
666     //create frameNode copy
667     auto renderContext = frameNode->GetRenderContext();
668     CHECK_NULL_VOID(renderContext);
669     auto pixelMap = renderContext->GetThumbnailPixelMap(true, false);
670     CHECK_NULL_VOID(pixelMap);
671     auto dragNodeCopy = CreateImageNode(pixelMap);
672     CHECK_NULL_VOID(dragNodeCopy);
673 
674     //mount to gatherNode
675     gatherNode->AddChild(dragNodeCopy);
676     overlayManager->SetDragNodeCopy(dragNodeCopy);
677 
678     //update position
679     int32_t width = pixelMap->GetWidth();
680     int32_t height = pixelMap->GetHeight();
681     auto offset = DragDropFuncWrapper::GetPaintRectCenter(frameNode) -
682         OffsetF(width / HALF_DIVIDE, height / HALF_DIVIDE);
683     DragDropFuncWrapper::UpdateNodePositionToWindow(dragNodeCopy, offset);
684     auto copyNodeRenderContext = dragNodeCopy->GetRenderContext();
685     CHECK_NULL_VOID(copyNodeRenderContext);
686     copyNodeRenderContext->UpdateTransformScale({ 1.0f, 1.0f });
687 }
688 
ShowDragNodeCopyAnimation(const RefPtr<OverlayManager> & overlayManager,const RefPtr<FrameNode> & frameNode)689 void DragAnimationHelper::ShowDragNodeCopyAnimation(const RefPtr<OverlayManager>& overlayManager,
690     const RefPtr<FrameNode>& frameNode)
691 {
692     CHECK_NULL_VOID(frameNode);
693     CHECK_NULL_VOID(overlayManager);
694     auto dragNodeCopy = overlayManager->GetDragNodeCopy();
695     CHECK_NULL_VOID(dragNodeCopy);
696     auto previewOptions = frameNode->GetDragPreviewOption();
697     if (!previewOptions.defaultAnimationBeforeLifting) {
698         return;
699     }
700     auto layoutProperty = frameNode->GetLayoutProperty();
701     if (layoutProperty) {
702         layoutProperty->UpdateVisibility(VisibleType::INVISIBLE);
703     }
704     auto renderContext = dragNodeCopy->GetRenderContext();
705     AnimationOption option;
706     option.SetDuration(BEFORE_LIFTING_TIME);
707     auto springCurve = AceType::MakeRefPtr<InterpolatingSpring>(DEFAULT_INTERPOLATING_SPRING_VELOCITY,
708         DEFAULT_INTERPOLATING_SPRING_MASS, DEFAULT_INTERPOLATING_SPRING_STIFFNESS,
709         DEFAULT_INTERPOLATING_SPRING_DAMPING);
710     option.SetCurve(springCurve);
711     AnimationUtils::Animate(
712         option,
713         [renderContext]() mutable {
714             CHECK_NULL_VOID(renderContext);
715             renderContext->UpdateTransformScale({ DEFAULT_ANIMATION_SCALE, DEFAULT_ANIMATION_SCALE });
716         },
717         option.GetOnFinishEvent()
718     );
719 }
720 
HideDragNodeCopyWithAnimation(const RefPtr<OverlayManager> & overlayManager,const RefPtr<FrameNode> & frameNode)721 void DragAnimationHelper::HideDragNodeCopyWithAnimation(const RefPtr<OverlayManager>& overlayManager,
722     const RefPtr<FrameNode>& frameNode)
723 {
724     CHECK_NULL_VOID(frameNode);
725     CHECK_NULL_VOID(overlayManager);
726     auto dragNodeCopy = overlayManager->GetDragNodeCopy();
727     auto defaultAnimation = frameNode->GetDragPreviewOption().defaultAnimationBeforeLifting;
728     if (!dragNodeCopy) {
729         auto layoutProperty = frameNode->GetLayoutProperty();
730         if (layoutProperty && defaultAnimation) {
731             layoutProperty->UpdateVisibility(VisibleType::VISIBLE);
732         }
733         return;
734     }
735     auto renderContext = dragNodeCopy->GetRenderContext();
736     CHECK_NULL_VOID(renderContext);
737     AnimationOption option;
738     option.SetDuration(NODE_RESET_DURATION);
739     option.SetCurve(Curves::SHARP);
740     option.SetOnFinishEvent([renderContext, weak = AceType::WeakClaim(AceType::RawPtr(frameNode)),
741         defaultAnimation]() {
742         auto frameNode = weak.Upgrade();
743         if (frameNode) {
744             auto layoutProperty = frameNode->GetLayoutProperty();
745             if (layoutProperty && defaultAnimation) {
746                 layoutProperty->UpdateVisibility(VisibleType::VISIBLE);
747             }
748         }
749         if (renderContext) {
750             renderContext->UpdateOpacity(0.0f);
751         }
752     });
753 
754     AnimationUtils::Animate(
755         option,
756         [renderContext]() mutable {
757             CHECK_NULL_VOID(renderContext);
758             renderContext->UpdateTransformScale({ 1.0, 1.0f });
759         },
760         option.GetOnFinishEvent()
761     );
762 }
763 
HideDragNodeCopy(const RefPtr<OverlayManager> & overlayManager)764 void DragAnimationHelper::HideDragNodeCopy(const RefPtr<OverlayManager>& overlayManager)
765 {
766     CHECK_NULL_VOID(overlayManager);
767     auto dragNodeCopy = overlayManager->GetDragNodeCopy();
768     CHECK_NULL_VOID(dragNodeCopy);
769     auto renderContext = dragNodeCopy->GetRenderContext();
770     CHECK_NULL_VOID(renderContext);
771     renderContext->UpdateOpacity(0.0f);
772 }
773 
UpdateBadgeTextNodePosition(const RefPtr<FrameNode> & frameNode,const RefPtr<FrameNode> & textNode,int32_t childSize,float previewScale,OffsetF previewOffset)774 void DragAnimationHelper::UpdateBadgeTextNodePosition(const RefPtr<FrameNode>& frameNode,
775     const RefPtr<FrameNode>& textNode, int32_t childSize, float previewScale, OffsetF previewOffset)
776 {
777     if (childSize <= 1) {
778         return;
779     }
780     CHECK_NULL_VOID(frameNode);
781     CHECK_NULL_VOID(textNode);
782     auto textRenderContext = textNode->GetRenderContext();
783     CHECK_NULL_VOID(textRenderContext);
784     auto pixelMap = frameNode->GetDragPixelMap();
785     CHECK_NULL_VOID(pixelMap);
786     auto width = pixelMap->GetWidth();
787     auto height = pixelMap->GetHeight();
788     auto offset = previewOffset.NonOffset()
789                       ? DragDropFuncWrapper::GetFrameNodeOffsetToWindow(textNode, frameNode, width, height)
790                       : previewOffset;
791     auto badgeLength = std::to_string(childSize).size();
792     double textOffsetX = offset.GetX() + width * (previewScale + 1) / 2 - BADGE_RELATIVE_OFFSET.ConvertToPx() -
793                          (BADGE_RELATIVE_OFFSET.ConvertToPx() * badgeLength);
794     double textOffsetY = offset.GetY() - height * (previewScale - 1) / 2 - BADGE_RELATIVE_OFFSET.ConvertToPx();
795     textRenderContext->UpdateTransformTranslate({ 0.0f, 0.0f, 0.0f });
796     textRenderContext->UpdatePosition(OffsetT<Dimension>(Dimension(textOffsetX), Dimension(textOffsetY)));
797 }
798 
CreateBadgeTextNode(int32_t childSize)799 RefPtr<FrameNode> DragAnimationHelper::CreateBadgeTextNode(int32_t childSize)
800 {
801     if (childSize <= 1) {
802         return nullptr;
803     }
804     auto textNode = FrameNode::GetOrCreateFrameNode(V2::TEXT_ETS_TAG, ElementRegister::GetInstance()->MakeUniqueId(),
805         []() { return AceType::MakeRefPtr<TextPattern>(); });
806     CHECK_NULL_RETURN(textNode, nullptr);
807     auto badgeLength = std::to_string(childSize).size();
808     DragAnimationHelper::UpdateBadgeLayoutAndRenderContext(textNode, badgeLength, childSize);
809 
810     textNode->MarkDirtyNode(NG::PROPERTY_UPDATE_MEASURE);
811     textNode->MarkModifyDone();
812     textNode->SetLayoutDirtyMarked(true);
813     textNode->SetActive(true);
814     return textNode;
815 }
816 
ShowPreviewBadgeAnimation(const RefPtr<GestureEventHub> & gestureHub,const RefPtr<OverlayManager> & manager)817 void DragAnimationHelper::ShowPreviewBadgeAnimation(
818     const RefPtr<GestureEventHub>& gestureHub, const RefPtr<OverlayManager>& manager)
819 {
820     CHECK_NULL_VOID(gestureHub);
821     auto frameNode = gestureHub->GetFrameNode();
822     CHECK_NULL_VOID(frameNode);
823     auto dragPreviewOptions = frameNode->GetDragPreviewOption();
824     auto badgeNumber = dragPreviewOptions.GetCustomerBadgeNumber();
825     int32_t childSize = badgeNumber.has_value() ? badgeNumber.value()
826                                                 : static_cast<int32_t>(manager->GetGatherNodeChildrenInfo().size()) + 1;
827     auto textNode = DragAnimationHelper::CreateBadgeTextNode(childSize);
828     CHECK_NULL_VOID(textNode);
829     auto column = manager->GetPixelMapNode();
830     CHECK_NULL_VOID(column);
831     column->AddChild(textNode);
832 
833     DragAnimationHelper::UpdateBadgeTextNodePosition(frameNode, textNode, childSize, PIXELMAP_DRAG_SCALE_MULTIPLE);
834     DragAnimationHelper::ShowBadgeAnimation(textNode);
835 }
836 
837 // update ImageNode default attr before floating
SetImageNodeInitAttr(const RefPtr<FrameNode> & frameNode,const RefPtr<FrameNode> & imageNode)838 void DragAnimationHelper::SetImageNodeInitAttr(const RefPtr<FrameNode>& frameNode, const RefPtr<FrameNode>& imageNode)
839 {
840     CHECK_NULL_VOID(imageNode);
841     CHECK_NULL_VOID(frameNode);
842     auto imageContext = imageNode->GetRenderContext();
843     CHECK_NULL_VOID(imageContext);
844     auto dragPreviewOption = frameNode->GetDragPreviewOption();
845 
846     // update default scale
847     imageContext->UpdateTransformScale({ 1.0f, 1.0f });
848 
849     // update shadow
850     auto shadow = Shadow::CreateShadow(ShadowStyle::None);
851     if (dragPreviewOption.options.shadow.has_value()) {
852         shadow = dragPreviewOption.options.shadow.value();
853         shadow.SetColor(Color(0x00000000));
854     }
855     imageContext->UpdateBackShadow(shadow);
856 
857     // update radius
858     auto borderRadius = DragDropFuncWrapper::GetDragFrameNodeBorderRadius(frameNode);
859     imageContext->UpdateBorderRadius(borderRadius);
860 
861     // update opacity
862     imageContext->UpdateOpacity(1.0f);
863 }
864 
SetImageNodeFinishAttr(const RefPtr<FrameNode> & frameNode,const RefPtr<FrameNode> & imageNode)865 void DragAnimationHelper::SetImageNodeFinishAttr(const RefPtr<FrameNode>& frameNode, const RefPtr<FrameNode>& imageNode)
866 {
867     CHECK_NULL_VOID(imageNode);
868     CHECK_NULL_VOID(frameNode);
869     auto imageContext = imageNode->GetRenderContext();
870     CHECK_NULL_VOID(imageContext);
871     auto dragPreviewOption = frameNode->GetDragPreviewOption();
872     if (dragPreviewOption.options.shadow.has_value() && !dragPreviewOption.options.shadow->GetIsFilled()) {
873         imageContext->UpdateBackShadow(dragPreviewOption.options.shadow.value());
874     }
875 }
876 
PreLayout(const RefPtr<FrameNode> & imageNode)877 void DragAnimationHelper::PreLayout(const RefPtr<FrameNode>& imageNode)
878 {
879     CHECK_NULL_VOID(imageNode);
880     auto subwindowContext = imageNode->GetContext();
881     if (subwindowContext) {
882         subwindowContext->FlushSyncGeometryNodeTasks();
883         subwindowContext->PreLayout(subwindowContext->GetTimeFromExternalTimer(), 0);
884     }
885 }
886 
SetNodeVisible(const RefPtr<FrameNode> & frameNode,bool visible)887 void DragAnimationHelper::SetNodeVisible(const RefPtr<FrameNode>& frameNode, bool visible)
888 {
889     CHECK_NULL_VOID(frameNode);
890     auto renderContext = frameNode->GetRenderContext();
891     CHECK_NULL_VOID(renderContext);
892     renderContext->SetVisible(visible);
893 }
894 
DragStartAnimation(const Offset & newOffset,const RefPtr<OverlayManager> & overlayManager,const OffsetF & gatherNodeCenter,Point point,int32_t containerId)895 void DragAnimationHelper::DragStartAnimation(const Offset& newOffset, const RefPtr<OverlayManager>& overlayManager,
896     const OffsetF& gatherNodeCenter, Point point, int32_t containerId)
897 {
898     auto pipelineContext = PipelineContext::GetCurrentContextSafelyWithCheck();
899     CHECK_NULL_VOID(pipelineContext);
900     auto dragDropManager = pipelineContext->GetDragDropManager();
901     CHECK_NULL_VOID(dragDropManager);
902     AnimationOption option;
903     constexpr int32_t animateDuration = 300;
904     option.SetCurve(DRAG_CONTROL_ANIMATION_CURVE);
905     option.SetDuration(animateDuration);
906     option.SetOnFinishEvent([weakManager = AceType::WeakClaim(AceType::RawPtr(dragDropManager)), containerId]() {
907        auto dragDropManager = weakManager.Upgrade();
908        dragDropManager->SetStartAnimation(true);
909        if (dragDropManager && !dragDropManager->IsPullMoveReceivedForCurrentDrag()) {
910            DragControllerFuncWrapper::TransDragWindowToDragFwk(containerId);
911        }
912     });
913     auto imageNode = dragDropManager->GetDragPreviewInfo().imageNode;
914     CHECK_NULL_VOID(imageNode);
915     auto renderContext = imageNode->GetRenderContext();
916     CHECK_NULL_VOID(renderContext);
917     AnimationUtils::Animate(
918         option,
919         [renderContext, info = dragDropManager->GetDragPreviewInfo(), newOffset, overlayManager,
920             dragDropManager, gatherNodeCenter]() {
921                 CHECK_NULL_VOID(renderContext);
922                 renderContext->UpdateTransformScale({ info.scale, info.scale });
923                 renderContext->UpdateTransformTranslate({ newOffset.GetX(), newOffset.GetY(), 0.0f });
924                 GatherAnimationInfo gatherAnimationInfo = { info.scale, info.width, info.height,
925                     gatherNodeCenter, renderContext->GetBorderRadius() };
926                 dragDropManager->UpdateGatherNodeAttr(overlayManager, gatherAnimationInfo);
927                 dragDropManager->UpdateTextNodePosition(info.textNode, newOffset);
928         },
929         option.GetOnFinishEvent());
930 }
931 
CreatePreviewNode(const RefPtr<FrameNode> & frameNode,RefPtr<FrameNode> & imageNode,float dragPreviewScale,const PreparedInfoForDrag & data)932 void DragAnimationHelper::CreatePreviewNode(const RefPtr<FrameNode>& frameNode, RefPtr<FrameNode>& imageNode,
933     float dragPreviewScale, const PreparedInfoForDrag& data)
934 {
935     CHECK_NULL_VOID(frameNode);
936     auto pixelMap = frameNode->GetDragPixelMap();
937     CHECK_NULL_VOID(pixelMap);
938     auto center = DragDropFuncWrapper::GetPaintRectCenter(frameNode);
939     auto frameOffset = OffsetF(0, 0);
940     imageNode = FrameNode::GetOrCreateFrameNode(V2::IMAGE_ETS_TAG, ElementRegister::GetInstance()->MakeUniqueId(),
941         []() { return AceType::MakeRefPtr<ImagePattern>(); });
942     CHECK_NULL_VOID(imageNode);
943     imageNode->SetDragPreviewOptions(frameNode->GetDragPreviewOption());
944 
945     auto renderProps = imageNode->GetPaintProperty<ImageRenderProperty>();
946     CHECK_NULL_VOID(renderProps);
947     renderProps->UpdateImageInterpolation(ImageInterpolation::HIGH);
948     auto props = imageNode->GetLayoutProperty<ImageLayoutProperty>();
949     props->UpdateAutoResize(false);
950     props->UpdateImageSourceInfo(ImageSourceInfo(pixelMap));
951     auto targetSize = CalcSize(NG::CalcLength(pixelMap->GetWidth()), NG::CalcLength(pixelMap->GetHeight()));
952     props->UpdateUserDefinedIdealSize(targetSize);
953 
954     auto imagePattern = imageNode->GetPattern<ImagePattern>();
955     CHECK_NULL_VOID(imagePattern);
956     imagePattern->SetSyncLoad(true);
957 
958     if (frameNode->GetDragPreviewOption().sizeChangeEffect == DraggingSizeChangeEffect::DEFAULT || !data.isMenuShow) {
959         frameOffset =
960             OffsetF(center.GetX() - (pixelMap->GetWidth() / 2.0f), center.GetY() - (pixelMap->GetHeight() / 2.0f));
961         DragEventActuator::UpdatePreviewPositionAndScale(imageNode, frameOffset, dragPreviewScale);
962         UpdatePreview(frameNode, imageNode, imageNode);
963     }
964     if ((frameNode->GetDragPreviewOption().sizeChangeEffect == DraggingSizeChangeEffect::SIZE_TRANSITION ||
965             frameNode->GetDragPreviewOption().sizeChangeEffect == DraggingSizeChangeEffect::SIZE_CONTENT_TRANSITION) &&
966         data.isMenuShow) {
967         frameOffset = OffsetF(center.GetX() - (data.menuPreviewRect.Width() / 2.0f),
968             center.GetY() - (data.menuPreviewRect.Height() / 2.0f));
969         CHECK_NULL_VOID(data.relativeContainerNode);
970         auto relativeContainerRenderContext = data.relativeContainerNode->GetRenderContext();
971         CHECK_NULL_VOID(relativeContainerRenderContext);
972         relativeContainerRenderContext->UpdatePosition(
973             OffsetT<Dimension>(Dimension(frameOffset.GetX()), Dimension(frameOffset.GetY())));
974         data.relativeContainerNode->SetDragPreviewOptions(frameNode->GetDragPreviewOption());
975         UpdatePreview(frameNode, imageNode, data.relativeContainerNode);
976     }
977 }
978 
UpdatePreview(const RefPtr<FrameNode> & frameNode,const RefPtr<FrameNode> & imageNode,const RefPtr<FrameNode> & dragNode)979 void DragAnimationHelper::UpdatePreview(
980     const RefPtr<FrameNode>& frameNode, const RefPtr<FrameNode>& imageNode, const RefPtr<FrameNode>& dragNode)
981 {
982     CHECK_NULL_VOID(frameNode);
983     CHECK_NULL_VOID(imageNode);
984     CHECK_NULL_VOID(dragNode);
985     DragEventActuator::UpdatePreviewAttr(frameNode, imageNode);
986 }
987 
MountPixelMap(const RefPtr<OverlayManager> & manager,const RefPtr<GestureEventHub> & gestureHub,const PreparedInfoForDrag & data,bool isDragPixelMap)988 void DragAnimationHelper::MountPixelMap(const RefPtr<OverlayManager>& manager,
989     const RefPtr<GestureEventHub>& gestureHub, const PreparedInfoForDrag& data, bool isDragPixelMap)
990 {
991     CHECK_NULL_VOID(manager);
992     CHECK_NULL_VOID(data.imageNode);
993     CHECK_NULL_VOID(gestureHub);
994     auto columnNode = FrameNode::CreateFrameNode(V2::COLUMN_ETS_TAG, ElementRegister::GetInstance()->MakeUniqueId(),
995         AceType::MakeRefPtr<LinearLayoutPattern>(true));
996     CHECK_NULL_VOID(columnNode);
997     if (data.imageNode->GetDragPreviewOption().sizeChangeEffect == DraggingSizeChangeEffect::DEFAULT ||
998         !data.isMenuShow) {
999         columnNode->AddChild(data.imageNode);
1000         if (data.textNode) {
1001             columnNode->AddChild(data.textNode);
1002         }
1003     }
1004     if ((data.imageNode->GetDragPreviewOption().sizeChangeEffect ==
1005             DraggingSizeChangeEffect::SIZE_TRANSITION ||
1006         data.imageNode->GetDragPreviewOption().sizeChangeEffect ==
1007         DraggingSizeChangeEffect::SIZE_CONTENT_TRANSITION)&& data.isMenuShow) {
1008         MountPixelMapSizeContentTransition(data, columnNode);
1009     }
1010     auto hub = columnNode->GetOrCreateGestureEventHub();
1011     CHECK_NULL_VOID(hub);
1012     hub->SetPixelMap(gestureHub->GetPixelMap());
1013     auto container = Container::Current();
1014     if (container && container->IsScenceBoardWindow()) {
1015         auto frameNode = gestureHub->GetFrameNode();
1016         CHECK_NULL_VOID(frameNode);
1017         auto windowScene = manager->FindWindowScene(frameNode);
1018         manager->MountPixelMapToWindowScene(columnNode, windowScene, isDragPixelMap);
1019     } else {
1020         manager->MountPixelMapToRootNode(columnNode, isDragPixelMap);
1021     }
1022     DragEventActuator::SetPreviewDefaultAnimateProperty(data.imageNode);
1023     columnNode->MarkDirtyNode(NG::PROPERTY_UPDATE_MEASURE);
1024     columnNode->MarkModifyDone();
1025     columnNode->SetActive(true);
1026     auto renderContext = columnNode->GetRenderContext();
1027     if (renderContext) {
1028         renderContext->MarkUiFirstNode(false);
1029         renderContext->UpdatePosition(OffsetT<Dimension>(Dimension(0.0f), Dimension(0.0f)));
1030     }
1031     MarkDirtyNode(columnNode);
1032 
1033     if (!isDragPixelMap) {
1034         auto pipeline = PipelineBase::GetCurrentContextSafelyWithCheck();
1035         CHECK_NULL_VOID(pipeline);
1036         pipeline->FlushSyncGeometryNodeTasks();
1037     }
1038 }
1039 
MountPixelMapSizeContentTransition(const PreparedInfoForDrag & data,const RefPtr<FrameNode> & columnNode)1040 void DragAnimationHelper::MountPixelMapSizeContentTransition(
1041     const PreparedInfoForDrag& data, const RefPtr<FrameNode>& columnNode)
1042 {
1043     CHECK_NULL_VOID(data.imageNode);
1044     CHECK_NULL_VOID(data.relativeContainerNode);
1045     CHECK_NULL_VOID(columnNode);
1046     auto stackFrameNode = FrameNode::GetOrCreateFrameNode(V2::STACK_ETS_TAG,
1047         ElementRegister::GetInstance()->MakeUniqueId(), []() { return AceType::MakeRefPtr<StackPattern>(); });
1048     auto stackLayoutProperty = stackFrameNode->GetLayoutProperty();
1049     CHECK_NULL_VOID(stackLayoutProperty);
1050     stackLayoutProperty->UpdateUserDefinedIdealSize({ CalcLength(data.menuPreviewRect.Width(), DimensionUnit::PX),
1051         CalcLength(data.menuPreviewRect.Height(), DimensionUnit::PX) });
1052     stackLayoutProperty->UpdateAlignRules(
1053         { { AlignDirection::TOP, { .anchor = "__container__", .vertical = VerticalAlign::TOP } },
1054             { AlignDirection::RIGHT, { .anchor = "__container__", .horizontal = HorizontalAlign::END } } });
1055     auto stackContext = stackFrameNode->GetContext();
1056     CHECK_NULL_VOID(stackContext);
1057     auto renderContext = stackFrameNode->GetRenderContext();
1058     CHECK_NULL_VOID(renderContext);
1059     renderContext->UpdateClipEdge(true);
1060     renderContext->UpdateBorderRadius(data.borderRadius);
1061     columnNode->AddChild(data.relativeContainerNode);
1062     data.relativeContainerNode->AddChild(stackFrameNode);
1063     stackFrameNode->AddChild(data.imageNode);
1064     auto dragPreviewLayoutProperty = data.imageNode->GetLayoutProperty();
1065     CHECK_NULL_VOID(dragPreviewLayoutProperty);
1066     dragPreviewLayoutProperty->UpdateUserDefinedIdealSize(
1067         { CalcLength(0.0, DimensionUnit::AUTO), CalcLength(0.0, DimensionUnit::AUTO) });
1068     dragPreviewLayoutProperty->UpdateMeasureType(MeasureType::MATCH_PARENT);
1069     CreateAndMountMenuPreviewNode(data, stackFrameNode);
1070     if (data.textNode) {
1071         auto textRow = FrameNode::CreateFrameNode(V2::ROW_ETS_TAG, ElementRegister::GetInstance()->MakeUniqueId(),
1072             AceType::MakeRefPtr<LinearLayoutPattern>(false));
1073         textRow->AddChild(data.textNode);
1074         auto textRowLayoutProperty = textRow->GetLayoutProperty();
1075         CHECK_NULL_VOID(textRowLayoutProperty);
1076         auto textRowRenderContext = textRow->GetRenderContext();
1077         CHECK_NULL_VOID(textRowRenderContext);
1078         textRowRenderContext->UpdateOffset(OffsetT<Dimension>(
1079             Dimension(BADGE_RELATIVE_OFFSET.ConvertToPx()), Dimension(-BADGE_RELATIVE_OFFSET.ConvertToPx())));
1080         textRowLayoutProperty->UpdateAlignRules(
1081             { { AlignDirection::TOP, { .anchor = "__container__", .vertical = VerticalAlign::TOP } },
1082                 { AlignDirection::RIGHT, { .anchor = "__container__", .horizontal = HorizontalAlign::END } } });
1083 
1084         data.relativeContainerNode->AddChild(textRow);
1085     }
1086 }
1087 
CreateAndMountMenuPreviewNode(const PreparedInfoForDrag & data,const RefPtr<FrameNode> & stackFrameNode)1088 void DragAnimationHelper::CreateAndMountMenuPreviewNode(
1089     const PreparedInfoForDrag& data, const RefPtr<FrameNode>& stackFrameNode)
1090 {
1091     CHECK_NULL_VOID(data.imageNode);
1092     CHECK_NULL_VOID(data.menuPreviewNode);
1093     if (data.imageNode->GetDragPreviewOption().sizeChangeEffect == DraggingSizeChangeEffect::SIZE_CONTENT_TRANSITION) {
1094         auto menuPreviewImageNode = FrameNode::GetOrCreateFrameNode(V2::IMAGE_ETS_TAG,
1095             ElementRegister::GetInstance()->MakeUniqueId(), []() { return AceType::MakeRefPtr<ImagePattern>(); });
1096         CHECK_NULL_VOID(menuPreviewImageNode);
1097         auto menuPreviewImageNodeLayoutProperty = menuPreviewImageNode->GetLayoutProperty<ImageLayoutProperty>();
1098         CHECK_NULL_VOID(menuPreviewImageNodeLayoutProperty);
1099         auto menuPreviewRenderContext = data.menuPreviewNode->GetRenderContext();
1100         CHECK_NULL_VOID(menuPreviewRenderContext);
1101         auto menuPreviewPixelMap = menuPreviewRenderContext->GetThumbnailPixelMap(true);
1102         menuPreviewImageNodeLayoutProperty->UpdateImageSourceInfo(ImageSourceInfo(menuPreviewPixelMap));
1103         auto menuPreviewImagePattern = menuPreviewImageNode->GetPattern<ImagePattern>();
1104         CHECK_NULL_VOID(menuPreviewImagePattern);
1105         menuPreviewImagePattern->SetSyncLoad(true);
1106         menuPreviewImageNodeLayoutProperty->UpdateUserDefinedIdealSize(
1107             { CalcLength(0.0, DimensionUnit::AUTO), CalcLength(0.0, DimensionUnit::AUTO) });
1108         menuPreviewImageNodeLayoutProperty->UpdateMeasureType(MeasureType::MATCH_PARENT);
1109         menuPreviewImageNodeLayoutProperty->UpdateImageFit(ImageFit::COVER);
1110         auto menuPreviewImageRenderContext = menuPreviewImageNode->GetRenderContext();
1111         CHECK_NULL_VOID(menuPreviewImageRenderContext);
1112         menuPreviewImageRenderContext->UpdateOpacity(1.0f);
1113         stackFrameNode->AddChild(menuPreviewImageNode);
1114         auto dragPreviewRenderContext = data.imageNode->GetRenderContext();
1115         CHECK_NULL_VOID(dragPreviewRenderContext);
1116         dragPreviewRenderContext->UpdateOpacity(0.0f);
1117     }
1118 }
1119 } // namespace OHOS::Ace::NG
1120