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