1 /*
2 * Copyright (c) 2022 Huawei Device Co., Ltd.
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 * http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15
16 #include "core/common/container.h"
17 #include "core/components_ng/pattern/linear_layout/linear_layout_pattern.h"
18 #include "core/components_ng/pattern/navigation/navigation_title_util.h"
19 #include "core/components_ng/pattern/navigation/navigation_transition_proxy.h"
20 #include "core/components_ng/pattern/navrouter/navdestination_group_node.h"
21 #include "core/components_ng/pattern/navrouter/navdestination_context.h"
22 #include "core/components_ng/pattern/navrouter/navdestination_layout_property.h"
23 #include "core/components_ng/pattern/navrouter/navdestination_pattern.h"
24 #include "core/components_ng/pattern/text/text_layout_property.h"
25 #include "core/components_v2/inspector/inspector_constants.h"
26 #include "core/components_ng/pattern/text/text_pattern.h"
27
28 namespace OHOS::Ace::NG {
29 constexpr double HALF = 0.5;
30 constexpr float CONTENT_OFFSET_PERCENT = 0.2f;
31 constexpr float TITLE_OFFSET_PERCENT = 0.02f;
32 constexpr float REMOVE_CLIP_SIZE = 10000.0f;
33 constexpr int32_t MAX_RENDER_GROUP_TEXT_NODE_COUNT = 50;
34 constexpr int32_t OPACITY_TITLE_OUT_DELAY = 17;
35 constexpr int32_t OPACITY_TITLE_IN_DELAY = 33;
36 constexpr int32_t OPACITY_TITLE_DURATION = 150;
37 constexpr int32_t OPACITY_BACKBUTTON_IN_DELAY = 150;
38 constexpr int32_t OPACITY_BACKBUTTON_IN_DURATION = 200;
39 constexpr int32_t OPACITY_BACKBUTTON_OUT_DURATION = 67;
40 constexpr float MAX_RENDER_GROUP_TEXT_NODE_HEIGHT = 150.0f;
41
~NavDestinationGroupNode()42 NavDestinationGroupNode::~NavDestinationGroupNode()
43 {
44 if (contentNode_) {
45 contentNode_->Clean();
46 }
47 ReleaseTextNodeList();
48 }
49
GetOrCreateGroupNode(const std::string & tag,int32_t nodeId,const std::function<RefPtr<Pattern> (void)> & patternCreator)50 RefPtr<NavDestinationGroupNode> NavDestinationGroupNode::GetOrCreateGroupNode(
51 const std::string& tag, int32_t nodeId, const std::function<RefPtr<Pattern>(void)>& patternCreator)
52 {
53 auto frameNode = GetFrameNode(tag, nodeId);
54 CHECK_NULL_RETURN(!frameNode, AceType::DynamicCast<NavDestinationGroupNode>(frameNode));
55 auto pattern = patternCreator ? patternCreator() : MakeRefPtr<Pattern>();
56 auto navDestinationNode = AceType::MakeRefPtr<NavDestinationGroupNode>(tag, nodeId, pattern);
57 navDestinationNode->InitializePatternAndContext();
58 ElementRegister::GetInstance()->AddUINode(navDestinationNode);
59 return navDestinationNode;
60 }
61
IsNeedContentTransition()62 bool NavDestinationGroupNode::IsNeedContentTransition()
63 {
64 if (systemTransitionType_ == NavigationSystemTransitionType::DEFAULT) {
65 return true;
66 }
67 return (systemTransitionType_ & NavigationSystemTransitionType::CONTENT) != NavigationSystemTransitionType::NONE;
68 }
69
TransitionContentInValid()70 bool NavDestinationGroupNode::TransitionContentInValid()
71 {
72 return (systemTransitionType_ & NavigationSystemTransitionType::CONTENT) == NavigationSystemTransitionType::NONE
73 && mode_ == NavDestinationMode::STANDARD;
74 }
75
IsNeedTitleTransition()76 bool NavDestinationGroupNode::IsNeedTitleTransition()
77 {
78 if (systemTransitionType_ == NavigationSystemTransitionType::DEFAULT) {
79 return true;
80 }
81 if (mode_ == NavDestinationMode::STANDARD) {
82 return (systemTransitionType_ & NavigationSystemTransitionType::TITLE) != NavigationSystemTransitionType::NONE;
83 }
84 return (systemTransitionType_ & NavigationSystemTransitionType::CONTENT) != NavigationSystemTransitionType::NONE;
85 }
86
AddChildToGroup(const RefPtr<UINode> & child,int32_t slot)87 void NavDestinationGroupNode::AddChildToGroup(const RefPtr<UINode>& child, int32_t slot)
88 {
89 auto pattern = AceType::DynamicCast<Pattern>(GetPattern());
90 CHECK_NULL_VOID(pattern);
91 auto contentNode = GetContentNode();
92 if (!contentNode) {
93 auto nodeId = ElementRegister::GetInstance()->MakeUniqueId();
94 ACE_LAYOUT_SCOPED_TRACE("Create[%s][self:%d]", V2::NAVDESTINATION_CONTENT_ETS_TAG, nodeId);
95 contentNode = FrameNode::GetOrCreateFrameNode(V2::NAVDESTINATION_CONTENT_ETS_TAG, nodeId,
96 []() { return AceType::MakeRefPtr<LinearLayoutPattern>(true); });
97 SetContentNode(contentNode);
98 AddChild(contentNode);
99
100 if (Container::GreatOrEqualAPIVersion(PlatformVersion::VERSION_ELEVEN)) {
101 auto navdestinationContentNode = AceType::DynamicCast<FrameNode>(contentNode);
102 SafeAreaExpandOpts opts = { .type = SAFE_AREA_TYPE_SYSTEM | SAFE_AREA_TYPE_CUTOUT,
103 .edges = SAFE_AREA_EDGE_ALL };
104 navdestinationContentNode->GetLayoutProperty()->UpdateSafeAreaExpandOpts(opts);
105 }
106 }
107 contentNode->AddChild(child, slot);
108 }
109
DeleteChildFromGroup(int32_t slot)110 void NavDestinationGroupNode::DeleteChildFromGroup(int32_t slot)
111 {
112 auto navDestination = GetContentNode();
113 CHECK_NULL_VOID(navDestination);
114 navDestination->RemoveChildAtIndex(slot);
115 }
116
OnAttachToMainTree(bool recursive)117 void NavDestinationGroupNode::OnAttachToMainTree(bool recursive)
118 {
119 if (!UseOffscreenProcess()) {
120 ProcessShallowBuilder();
121 }
122 FrameNode::OnAttachToMainTree(recursive);
123 }
124
OnOffscreenProcess(bool recursive)125 void NavDestinationGroupNode::OnOffscreenProcess(bool recursive)
126 {
127 ProcessShallowBuilder();
128 FrameNode::OnOffscreenProcess(recursive);
129 }
130
ProcessShallowBuilder()131 void NavDestinationGroupNode::ProcessShallowBuilder()
132 {
133 if (isCacheNode_) {
134 return;
135 }
136
137 TAG_LOGD(AceLogTag::ACE_NAVIGATION, "render navDestination content");
138 auto navDestinationPattern = GetPattern<NavDestinationPattern>();
139 CHECK_NULL_VOID(navDestinationPattern);
140 auto shallowBuilder = navDestinationPattern->GetShallowBuilder();
141 if (shallowBuilder && !shallowBuilder->IsExecuteDeepRenderDone()) {
142 auto eventHub = GetEventHub<NavDestinationEventHub>();
143 if (eventHub) {
144 auto ctx = navDestinationPattern->GetNavDestinationContext();
145 eventHub->FireOnReady(ctx);
146 }
147 shallowBuilder->ExecuteDeepRender();
148 GetLayoutProperty()->UpdatePropertyChangeFlag(PROPERTY_UPDATE_MEASURE);
149 AceType::DynamicCast<FrameNode>(contentNode_)
150 ->GetLayoutProperty()
151 ->UpdatePropertyChangeFlag(PROPERTY_UPDATE_MEASURE);
152 }
153 }
154
GetNavDestinationCustomNode()155 RefPtr<CustomNodeBase> NavDestinationGroupNode::GetNavDestinationCustomNode()
156 {
157 return customNode_.Upgrade();
158 }
159
SetNavDestinationMode(NavDestinationMode mode)160 void NavDestinationGroupNode::SetNavDestinationMode(NavDestinationMode mode)
161 {
162 mode_ = mode;
163 auto pattern = GetPattern<NavDestinationPattern>();
164 CHECK_NULL_VOID(pattern);
165 auto context = pattern->GetNavDestinationContext();
166 CHECK_NULL_VOID(context);
167 context->SetMode(mode);
168 }
169
ToJsonValue(std::unique_ptr<JsonValue> & json,const InspectorFilter & filter) const170 void NavDestinationGroupNode::ToJsonValue(std::unique_ptr<JsonValue>& json, const InspectorFilter& filter) const
171 {
172 FrameNode::ToJsonValue(json, filter);
173 /* no fixed attr below, just return */
174 if (filter.IsFastFilter()) {
175 return;
176 }
177 auto titleBarNode = DynamicCast<TitleBarNode>(titleBarNode_);
178 if (titleBarNode) {
179 std::string title = NavigationTitleUtil::GetTitleString(titleBarNode, GetPrevTitleIsCustomValue(false));
180 std::string subtitle = NavigationTitleUtil::GetSubtitleString(titleBarNode);
181 json->PutExtAttr("title", title.c_str(), filter);
182 json->PutExtAttr("subtitle", subtitle.c_str(), filter);
183 }
184 json->PutExtAttr("mode", mode_ == NavDestinationMode::DIALOG
185 ? "NavDestinationMode::DIALOG"
186 : "NavDestinationMode::STANDARD", filter);
187 }
188
InitSystemTransitionPush(bool transitionIn)189 void NavDestinationGroupNode::InitSystemTransitionPush(bool transitionIn)
190 {
191 auto titleBarNode = AceType::DynamicCast<FrameNode>(GetTitleBarNode());
192 float isRTL = GetLanguageDirection();
193 bool needContentAnimation = IsNeedContentTransition();
194 bool needTitleAnimation = IsNeedTitleTransition();
195 if (transitionIn) {
196 SetIsOnAnimation(true);
197 SetTransitionType(PageTransitionType::ENTER_PUSH);
198 auto frameSize = GetGeometryNode()->GetFrameSize();
199 if (needContentAnimation) {
200 if (AceApplicationInfo::GetInstance().IsRightToLeft()) {
201 GetRenderContext()->ClipWithRRect(
202 RectF(0.0f, 0.0f, frameSize.Width() * HALF, REMOVE_CLIP_SIZE), RadiusF(EdgeF(0.0f, 0.0f)));
203 } else {
204 GetRenderContext()->ClipWithRRect(
205 RectF(frameSize.Width() * HALF, 0.0f, frameSize.Width(), REMOVE_CLIP_SIZE),
206 RadiusF(EdgeF(0.0f, 0.0f)));
207 }
208 GetRenderContext()->UpdateTranslateInXY({ frameSize.Width() * HALF * isRTL, 0.0f });
209 }
210 if (titleBarNode && needTitleAnimation) {
211 titleBarNode->GetRenderContext()->UpdateTranslateInXY({ frameSize.Width() * HALF * isRTL, 0.0f });
212 }
213 return;
214 }
215 SetTransitionType(PageTransitionType::EXIT_PUSH);
216 SetIsOnAnimation(true);
217 GetRenderContext()->RemoveClipWithRRect();
218 if (needContentAnimation) {
219 GetRenderContext()->UpdateTranslateInXY({ 0.0f, 0.0f });
220 }
221 if (NeedRemoveInPush()) {
222 GetEventHub<EventHub>()->SetEnabledInternal(false);
223 }
224 if (titleBarNode && needTitleAnimation) {
225 titleBarNode->GetRenderContext()->UpdateTranslateInXY({ 0.0f, 0.0f });
226 }
227 }
228
StartSystemTransitionPush(bool transitionIn)229 void NavDestinationGroupNode::StartSystemTransitionPush(bool transitionIn)
230 {
231 auto titleBarNode = AceType::DynamicCast<FrameNode>(GetTitleBarNode());
232 auto frameSize = GetGeometryNode()->GetFrameSize();
233 float isRTL = GetLanguageDirection();
234 bool needContentAnimation = IsNeedContentTransition();
235 bool needTitleAnimation = IsNeedTitleTransition();
236 if (transitionIn) {
237 if (needContentAnimation) {
238 GetRenderContext()->ClipWithRRect(
239 RectF(0.0f, 0.0f, frameSize.Width(), REMOVE_CLIP_SIZE), RadiusF(EdgeF(0.0f, 0.0f)));
240 GetRenderContext()->UpdateTranslateInXY({ 0.0f, 0.0f });
241 }
242 if (titleBarNode && needTitleAnimation) {
243 titleBarNode->GetRenderContext()->UpdateTranslateInXY({ 0.0f, 0.0f });
244 }
245 return;
246 }
247 if (needContentAnimation) {
248 GetRenderContext()->UpdateTranslateInXY(
249 { -frameSize.Width() * CONTENT_OFFSET_PERCENT * isRTL, 0.0f });
250 }
251 if (titleBarNode && needTitleAnimation) {
252 titleBarNode->GetRenderContext()->UpdateTranslateInXY(
253 { frameSize.Width() * TITLE_OFFSET_PERCENT * isRTL, 0.0f });
254 }
255 }
256
SystemTransitionPushCallback(bool transitionIn)257 void NavDestinationGroupNode::SystemTransitionPushCallback(bool transitionIn)
258 {
259 if (transitionIn) {
260 if (GetTransitionType() != PageTransitionType::ENTER_PUSH) {
261 TAG_LOGW(AceLogTag::ACE_NAVIGATION, "curNode has another transition");
262 return;
263 }
264 GetRenderContext()->RemoveClipWithRRect();
265 SetIsOnAnimation(false);
266 return;
267 }
268 SetIsOnAnimation(false);
269 if (IsNeedContentTransition()) {
270 GetRenderContext()->UpdateTranslateInXY({ 0.0f, 0.0f });
271 }
272 GetRenderContext()->SetActualForegroundColor(Color::TRANSPARENT);
273 auto navDestinationPattern = GetPattern<NavDestinationPattern>();
274 auto navigation = AceType::DynamicCast<NavigationGroupNode>(navDestinationPattern->GetNavigationNode());
275 CHECK_NULL_VOID(navigation);
276 bool isInvisible = IsNodeInvisible(navigation);
277 if (GetTransitionType() == PageTransitionType::EXIT_PUSH && isInvisible) {
278 GetLayoutProperty()->UpdateVisibility(VisibleType::INVISIBLE);
279 SetJSViewActive(false);
280 }
281 auto titleBarNode = AceType::DynamicCast<FrameNode>(GetTitleBarNode());
282 if (titleBarNode && IsNeedTitleTransition()) {
283 titleBarNode->GetRenderContext()->UpdateTranslateInXY({ 0.0f, 0.0f });
284 }
285 }
286
InitSystemTransitionPop(bool isTransitionIn)287 void NavDestinationGroupNode::InitSystemTransitionPop(bool isTransitionIn)
288 {
289 auto frameSize = GetGeometryNode()->GetFrameSize();
290 auto titleBarNode = AceType::DynamicCast<FrameNode>(GetTitleBarNode());
291 float isRTL = GetLanguageDirection();
292 bool needContentAnimation = IsNeedContentTransition();
293 bool needTitleAnimation = IsNeedTitleTransition();
294 if (isTransitionIn) {
295 SetTransitionType(PageTransitionType::ENTER_POP);
296 GetRenderContext()->RemoveClipWithRRect();
297 if (needContentAnimation) {
298 GetRenderContext()->UpdateTranslateInXY({ -frameSize.Width() * CONTENT_OFFSET_PERCENT * isRTL, 0.0f });
299 }
300 if (titleBarNode && needTitleAnimation) {
301 titleBarNode->GetRenderContext()->UpdateTranslateInXY(
302 { frameSize.Width() * TITLE_OFFSET_PERCENT * isRTL, 0.0f });
303 }
304 return;
305 }
306 SetIsOnAnimation(true);
307 SetTransitionType(PageTransitionType::EXIT_POP);
308 GetEventHub<EventHub>()->SetEnabledInternal(false);
309 if (needContentAnimation) {
310 GetRenderContext()->ClipWithRRect(RectF(0.0f, 0.0f, frameSize.Width(), REMOVE_CLIP_SIZE),
311 RadiusF(EdgeF(0.0f, 0.0f)));
312 GetRenderContext()->UpdateTranslateInXY({ 0.0f, 0.0f });
313 }
314 if (titleBarNode && needTitleAnimation) {
315 titleBarNode->GetRenderContext()->UpdateTranslateInXY({ 0.0f, 0.0f });
316 }
317 }
318
StartSystemTransitionPop(bool transitionIn)319 void NavDestinationGroupNode::StartSystemTransitionPop(bool transitionIn)
320 {
321 auto titleBarNode = AceType::DynamicCast<FrameNode>(GetTitleBarNode());
322 bool needContentAnimation = IsNeedContentTransition();
323 bool needTitleAnimation = IsNeedTitleTransition();
324 if (transitionIn) {
325 if (needContentAnimation) {
326 GetRenderContext()->UpdateTranslateInXY({ 0.0f, 0.0f });
327 }
328 if (titleBarNode && needTitleAnimation) {
329 titleBarNode->GetRenderContext()->UpdateTranslateInXY({ 0.0f, 0.0f });
330 }
331 return;
332 }
333 auto frameSize = GetGeometryNode()->GetFrameSize();
334 float isRTL = GetLanguageDirection();
335 if (needContentAnimation) {
336 if (AceApplicationInfo::GetInstance().IsRightToLeft()) {
337 GetRenderContext()->ClipWithRRect(
338 RectF(0.0f, 0.0f, frameSize.Width() * HALF, REMOVE_CLIP_SIZE), RadiusF(EdgeF(0.0f, 0.0f)));
339 } else {
340 GetRenderContext()->ClipWithRRect(
341 RectF(frameSize.Width() * HALF, 0.0f, frameSize.Width(), REMOVE_CLIP_SIZE),
342 RadiusF(EdgeF(0.0f, 0.0f)));
343 }
344 GetRenderContext()->UpdateTranslateInXY({ frameSize.Width() * HALF * isRTL, 0.0f });
345 }
346 if (titleBarNode && needTitleAnimation) {
347 titleBarNode->GetRenderContext()->UpdateTranslateInXY({ frameSize.Width() * HALF * isRTL, 0.0f });
348 }
349 }
350
SystemTransitionPopCallback()351 bool NavDestinationGroupNode::SystemTransitionPopCallback()
352 {
353 if (GetTransitionType() != PageTransitionType::EXIT_POP) {
354 // has another transition, just return
355 TAG_LOGW(AceLogTag::ACE_NAVIGATION, "preNavDesNode has another transition");
356 return false;
357 }
358 auto preNavDesPattern = GetPattern<NavDestinationPattern>();
359 CHECK_NULL_RETURN(preNavDesPattern, false);
360
361 // NavRouter will restore the preNavDesNode and needs to set the initial state after the animation ends.
362 auto shallowBuilder = preNavDesPattern->GetShallowBuilder();
363 if (shallowBuilder && !IsCacheNode()) {
364 shallowBuilder->MarkIsExecuteDeepRenderDone(false);
365 }
366 if (!IsCacheNode() && GetContentNode()) {
367 GetContentNode()->Clean();
368 }
369 SetIsOnAnimation(false);
370 GetEventHub<EventHub>()->SetEnabledInternal(true);
371 GetRenderContext()->RemoveClipWithRRect();
372 if (IsNeedContentTransition()) {
373 GetRenderContext()->UpdateTranslateInXY({ 0.0f, 0.0f });
374 }
375 auto preTitleNode = AceType::DynamicCast<FrameNode>(GetTitleBarNode());
376 if (preTitleNode && IsNeedTitleTransition()) {
377 preTitleNode->GetRenderContext()->UpdateTranslateInXY({ 0.0f, 0.0f });
378 preTitleNode->GetRenderContext()->SetOpacity(1.0);
379 auto titleBarNode = AceType::DynamicCast<TitleBarNode>(preTitleNode);
380 CHECK_NULL_RETURN(titleBarNode, true);
381 auto preBackIcon = AceType::DynamicCast<FrameNode>(titleBarNode->GetBackButton());
382 if (preBackIcon) {
383 preBackIcon->GetRenderContext()->SetOpacity(1.0);
384 }
385 }
386 return true;
387 }
388
InitDialogTransition(bool isZeroY)389 void NavDestinationGroupNode::InitDialogTransition(bool isZeroY)
390 {
391 if (systemTransitionType_ == NavigationSystemTransitionType::NONE
392 || systemTransitionType_ == NavigationSystemTransitionType::TITLE) {
393 return;
394 }
395 auto contentNode = AceType::DynamicCast<FrameNode>(GetContentNode());
396 CHECK_NULL_VOID(contentNode);
397 auto context = contentNode->GetRenderContext();
398 CHECK_NULL_VOID(context);
399 if (isZeroY) {
400 context->UpdateTransformTranslate({ 0.0f, 0.0f, 0.0f });
401 return;
402 }
403 context->UpdateTransformTranslate({ 0.0f,
404 contentNode->GetGeometryNode()->GetFrameSize().Height(), 0.0f });
405 }
406
UpdateTextNodeListAsRenderGroup(bool isPopPage,const RefPtr<NavigationTransitionProxy> & proxy)407 void NavDestinationGroupNode::UpdateTextNodeListAsRenderGroup(
408 bool isPopPage, const RefPtr<NavigationTransitionProxy>& proxy)
409 {
410 if (isPopPage) {
411 CollectTextNodeAsRenderGroup(isPopPage);
412 } else {
413 CHECK_NULL_VOID(proxy);
414 auto pipeline = PipelineContext::GetCurrentContext();
415 CHECK_NULL_VOID(pipeline);
416 pipeline->AddAfterLayoutTask([weakNavDestiniation = WeakClaim(this),
417 weakProxy = WeakPtr<NavigationTransitionProxy>(proxy)] () {
418 auto navDestination = weakNavDestiniation.Upgrade();
419 CHECK_NULL_VOID(navDestination);
420 auto proxy = weakProxy.Upgrade();
421 if (proxy && proxy->GetIsFinished()) {
422 return;
423 }
424 navDestination->CollectTextNodeAsRenderGroup(false);
425 });
426 pipeline->RequestFrame();
427 }
428 }
429
CollectTextNodeAsRenderGroup(bool isPopPage)430 void NavDestinationGroupNode::CollectTextNodeAsRenderGroup(bool isPopPage)
431 {
432 ReleaseTextNodeList();
433 std::queue<RefPtr<UINode>> childrenLoopQueue;
434 childrenLoopQueue.push(contentNode_);
435
436 // only the first 50 text nodes will be marked, avoid too much time for traversal
437 // and off-screen drawing at first few frames
438 int32_t remainTextNodeNeedRenderGroup = MAX_RENDER_GROUP_TEXT_NODE_COUNT;
439 while (!childrenLoopQueue.empty() && remainTextNodeNeedRenderGroup > 0) {
440 auto currentNode = childrenLoopQueue.front();
441 childrenLoopQueue.pop();
442 CHECK_NULL_CONTINUE(currentNode);
443 for (auto& child : currentNode->GetChildren()) {
444 if (remainTextNodeNeedRenderGroup <= 0) {
445 break;
446 }
447 CHECK_NULL_CONTINUE(child);
448 childrenLoopQueue.push(child);
449 auto frameNode = AceType::DynamicCast<FrameNode>(child);
450 if (!frameNode || (frameNode->GetTag() != V2::TEXT_ETS_TAG)) {
451 continue;
452 }
453 auto layoutProperty = frameNode->GetLayoutProperty<TextLayoutProperty>();
454 if (!layoutProperty ||
455 (layoutProperty->GetTextOverflowValue(TextOverflow::CLIP) == TextOverflow::MARQUEE)) {
456 continue;
457 }
458 auto& renderContext = frameNode->GetRenderContext();
459 if (!renderContext || renderContext->GetRenderGroupValue(false)) {
460 continue;
461 }
462 renderContext->SetMarkNodeGroup(isPopPage ||
463 (renderContext->GetPaintRectWithoutTransform().Height() < MAX_RENDER_GROUP_TEXT_NODE_HEIGHT));
464 textNodeList_.emplace_back(WeakPtr<UINode>(child));
465 --remainTextNodeNeedRenderGroup;
466 auto pattern = AceType::DynamicCast<TextPattern>(frameNode->GetPattern());
467 CHECK_NULL_CONTINUE(pattern);
468 pattern->RegisterAfterLayoutCallback([weakRenderContext = WeakPtr<RenderContext>(renderContext)]() {
469 auto renderContext = weakRenderContext.Upgrade();
470 if (renderContext && !(renderContext->GetRenderGroupValue(false))) {
471 renderContext->SetMarkNodeGroup(
472 renderContext->GetPaintRectWithoutTransform().Height() < MAX_RENDER_GROUP_TEXT_NODE_HEIGHT);
473 }
474 });
475 }
476 }
477 }
478
ReleaseTextNodeList()479 void NavDestinationGroupNode::ReleaseTextNodeList()
480 {
481 for (auto& child : textNodeList_) {
482 auto textNode = AceType::DynamicCast<FrameNode>(child.Upgrade());
483 if (!textNode) {
484 continue;
485 }
486 auto pattern = AceType::DynamicCast<TextPattern>(textNode->GetPattern());
487 if (pattern) {
488 pattern->UnRegisterAfterLayoutCallback();
489 }
490 auto renderContext = textNode->GetRenderContext();
491 if (renderContext) {
492 renderContext->SetMarkNodeGroup(renderContext->GetRenderGroupValue(false));
493 }
494 }
495 textNodeList_.clear();
496 }
497
CleanContent()498 void NavDestinationGroupNode::CleanContent()
499 {
500 // cacheNode is cached for pip info, and is no need to clean when clean content node
501 if (IsCacheNode()) {
502 return;
503 }
504 auto pattern = GetPattern<NavDestinationPattern>();
505 CHECK_NULL_VOID(pattern);
506 auto shallowBuilder = pattern->GetShallowBuilder();
507 if (shallowBuilder) {
508 shallowBuilder->MarkIsExecuteDeepRenderDone(false);
509 }
510 if (GetContentNode()) {
511 GetContentNode()->Clean(false, true);
512 }
513 }
514
IsNodeInvisible(const RefPtr<FrameNode> & node)515 bool NavDestinationGroupNode::IsNodeInvisible(const RefPtr<FrameNode>& node)
516 {
517 auto navigaiton = DynamicCast<NavigationGroupNode>(node);
518 CHECK_NULL_RETURN(navigaiton, false);
519 int32_t lastStandardIndex = navigaiton->GetLastStandardIndex();
520 bool isInvisible = index_ < lastStandardIndex;
521 return isInvisible;
522 }
523
TitleOpacityAnimation(bool isTransitionIn)524 std::shared_ptr<AnimationUtils::Animation> NavDestinationGroupNode::TitleOpacityAnimation(bool isTransitionIn)
525 {
526 if (!IsNeedTitleTransition()) {
527 return nullptr;
528 }
529 CHECK_NULL_RETURN(GetTitleBarNode(), nullptr);
530 auto titleNode = AceType::DynamicCast<TitleBarNode>(GetTitleBarNode());
531 CHECK_NULL_RETURN(titleNode, nullptr);
532 auto titleRenderContext = titleNode->GetRenderContext();
533 CHECK_NULL_RETURN(titleRenderContext, nullptr);
534 AnimationOption opacityOption;
535 opacityOption.SetCurve(Curves::SHARP);
536 opacityOption.SetDuration(OPACITY_TITLE_DURATION);
537 if (isTransitionIn) {
538 opacityOption.SetDelay(OPACITY_TITLE_IN_DELAY);
539 titleRenderContext->SetOpacity(0.0f);
540 return AnimationUtils::StartAnimation(opacityOption,
541 [weakRender = WeakPtr<RenderContext>(titleRenderContext)]() {
542 auto renderContext = weakRender.Upgrade();
543 CHECK_NULL_VOID(renderContext);
544 renderContext->SetOpacity(1.0f);
545 });
546 }
547 // recover after transition animation.
548 opacityOption.SetDelay(OPACITY_TITLE_OUT_DELAY);
549 titleRenderContext->SetOpacity(1.0f);
550 return AnimationUtils::StartAnimation(opacityOption,
551 [weakRender = WeakPtr<RenderContext>(titleRenderContext)]() {
552 auto renderContext = weakRender.Upgrade();
553 CHECK_NULL_VOID(renderContext);
554 renderContext->SetOpacity(0.0f);
555 });
556 }
557
BackButtonAnimation(bool isTransitionIn)558 std::shared_ptr<AnimationUtils::Animation> NavDestinationGroupNode::BackButtonAnimation(bool isTransitionIn)
559 {
560 if (!IsNeedTitleTransition()) {
561 return nullptr;
562 }
563 auto titleNode = AceType::DynamicCast<TitleBarNode>(GetTitleBarNode());
564 CHECK_NULL_RETURN(titleNode, nullptr);
565 auto backButtonNode = AceType::DynamicCast<FrameNode>(titleNode->GetBackButton());
566 CHECK_NULL_RETURN(backButtonNode, nullptr);
567 AnimationOption transitionOption;
568 transitionOption.SetCurve(Curves::SHARP);
569 auto backButtonNodeContext = backButtonNode->GetRenderContext();
570 CHECK_NULL_RETURN(backButtonNodeContext, nullptr);
571 if (isTransitionIn) {
572 transitionOption.SetDelay(OPACITY_BACKBUTTON_IN_DELAY);
573 transitionOption.SetDuration(OPACITY_BACKBUTTON_IN_DURATION);
574 backButtonNodeContext->SetOpacity(0.0f);
575 return AnimationUtils::StartAnimation(transitionOption,
576 [weakRender = WeakPtr<RenderContext>(backButtonNodeContext)]() {
577 auto renderContext = weakRender.Upgrade();
578 CHECK_NULL_VOID(renderContext);
579 renderContext->SetOpacity(1.0f);
580 });
581 }
582 transitionOption.SetDuration(OPACITY_BACKBUTTON_OUT_DURATION);
583 backButtonNodeContext->SetOpacity(1.0f);
584 return AnimationUtils::StartAnimation(transitionOption,
585 [weakRender = WeakPtr<RenderContext>(backButtonNodeContext)]() {
586 auto renderContext = weakRender.Upgrade();
587 CHECK_NULL_VOID(renderContext);
588 renderContext->SetOpacity(0.0f);
589 });
590 }
591 } // namespace OHOS::Ace::NG
592