• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2022-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 
16 #include "core/components_ng/pattern/navrouter/navdestination_pattern.h"
17 
18 #include "base/log/dump_log.h"
19 #include "core/common/agingadapation/aging_adapation_dialog_theme.h"
20 #include "core/common/agingadapation/aging_adapation_dialog_util.h"
21 #include "core/components/theme/app_theme.h"
22 #include "core/components_ng/pattern/navigation/navigation_pattern.h"
23 #include "core/components_ng/pattern/navigation/navigation_title_util.h"
24 #include "core/components_ng/pattern/navigation/navigation_toolbar_util.h"
25 #include "core/components_ng/pattern/navigation/title_bar_pattern.h"
26 
27 namespace OHOS::Ace::NG {
28 namespace {
29 std::atomic<uint64_t> g_navDestinationPatternNextAutoGenId = 0;
30 // titlebar ZINDEX
31 constexpr static int32_t DEFAULT_TITLEBAR_ZINDEX = 2;
32 constexpr float TRANSLATE_THRESHOLD = 26.0f;
33 const auto TRANSLATE_CURVE = AceType::MakeRefPtr<InterpolatingSpring>(0.0f, 1.0f, 228.0f, 30.0f);
34 
BuildMenu(const RefPtr<NavDestinationGroupNode> & navDestinationGroupNode,const RefPtr<TitleBarNode> & titleBarNode)35 void BuildMenu(const RefPtr<NavDestinationGroupNode>& navDestinationGroupNode, const RefPtr<TitleBarNode>& titleBarNode)
36 {
37     if (navDestinationGroupNode->GetMenuNodeOperationValue(ChildNodeOperation::NONE) == ChildNodeOperation::REPLACE) {
38         titleBarNode->RemoveChild(titleBarNode->GetMenu());
39         titleBarNode->MarkDirtyNode(PROPERTY_UPDATE_MEASURE);
40     }
41     if (navDestinationGroupNode->GetPrevMenuIsCustomValue(false)) {
42         if (navDestinationGroupNode->GetMenuNodeOperationValue(ChildNodeOperation::NONE) == ChildNodeOperation::NONE) {
43             return;
44         }
45         titleBarNode->SetMenu(navDestinationGroupNode->GetMenu());
46         titleBarNode->AddChild(titleBarNode->GetMenu());
47         titleBarNode->MarkDirtyNode(PROPERTY_UPDATE_MEASURE);
48         navDestinationGroupNode->UpdateMenuNodeOperation(ChildNodeOperation::NONE);
49     } else {
50         navDestinationGroupNode->UpdateMenuNodeOperation(ChildNodeOperation::NONE);
51         auto navDestinationPattern = navDestinationGroupNode->GetPattern<NavDestinationPattern>();
52         CHECK_NULL_VOID(navDestinationPattern);
53         auto titleBarMenuItems = navDestinationPattern->GetTitleBarMenuItems();
54         auto toolBarMenuItems = navDestinationPattern->GetToolBarMenuItems();
55 
56         bool isButtonEnabled = false;
57         auto hub = navDestinationGroupNode->GetEventHub<EventHub>();
58         if (hub) {
59             isButtonEnabled = hub->IsEnabled();
60         }
61         if (navDestinationPattern->HasMenuNodeId()) {
62             auto menuNode = NavigationTitleUtil::CreateMenuItems(navDestinationPattern->GetMenuNodeId(),
63                 titleBarMenuItems, navDestinationGroupNode, isButtonEnabled, DES_FIELD,
64                 titleBarNode->GetInnerParentId(), false);
65             CHECK_NULL_VOID(menuNode);
66             navDestinationGroupNode->SetMenu(menuNode);
67         }
68 
69         titleBarMenuItems.insert(titleBarMenuItems.end(), toolBarMenuItems.begin(), toolBarMenuItems.end());
70         auto landscapeMenuNode = NavigationTitleUtil::CreateMenuItems(navDestinationPattern->GetLandscapeMenuNodeId(),
71             titleBarMenuItems, navDestinationGroupNode, isButtonEnabled, DES_FIELD, titleBarNode->GetInnerParentId(),
72             true);
73         CHECK_NULL_VOID(landscapeMenuNode);
74         navDestinationGroupNode->SetLandscapeMenu(landscapeMenuNode);
75     }
76 }
77 
GetTitleOrToolBarTranslateAndHeight(const RefPtr<FrameNode> & barNode,float & translate,float & height)78 bool GetTitleOrToolBarTranslateAndHeight(const RefPtr<FrameNode>& barNode, float& translate, float& height)
79 {
80     CHECK_NULL_RETURN(barNode, false);
81     auto renderContext = barNode->GetRenderContext();
82     CHECK_NULL_RETURN(renderContext, false);
83     auto options = renderContext->GetTransformTranslateValue(TranslateOptions(0.0f, 0.0f, 0.0f));
84     translate = options.y.ConvertToPx();
85     height = renderContext->GetPaintRectWithoutTransform().Height();
86     return true;
87 }
88 }
89 
NavDestinationPattern(const RefPtr<ShallowBuilder> & shallowBuilder)90 NavDestinationPattern::NavDestinationPattern(const RefPtr<ShallowBuilder>& shallowBuilder)
91     : shallowBuilder_(shallowBuilder)
92 {
93     navDestinationId_ = g_navDestinationPatternNextAutoGenId.fetch_add(1);
94 }
95 
NavDestinationPattern()96 NavDestinationPattern::NavDestinationPattern()
97 {
98     navDestinationId_ = g_navDestinationPatternNextAutoGenId.fetch_add(1);
99 }
100 
~NavDestinationPattern()101 NavDestinationPattern::~NavDestinationPattern()
102 {
103     customNode_ = nullptr;
104     if (scrollableProcessor_) {
105         scrollableProcessor_->UnbindAllScrollers();
106     }
107 }
108 
OnActive()109 void NavDestinationPattern::OnActive()
110 {
111     Pattern::OnActive();
112     auto hostNode = AceType::DynamicCast<NavDestinationGroupNode>(GetHost());
113     CHECK_NULL_VOID(hostNode);
114     auto navDestinationContext = hostNode->GetRenderContext();
115     CHECK_NULL_VOID(navDestinationContext);
116     auto navDestinationLayoutProperty = hostNode->GetLayoutProperty<NavDestinationLayoutProperty>();
117     CHECK_NULL_VOID(navDestinationLayoutProperty);
118     auto titleBarNode = AceType::DynamicCast<TitleBarNode>(hostNode->GetTitleBarNode());
119     CHECK_NULL_VOID(titleBarNode);
120     auto titleBarLayoutProperty = titleBarNode->GetLayoutProperty<TitleBarLayoutProperty>();
121     CHECK_NULL_VOID(titleBarLayoutProperty);
122     if (navDestinationLayoutProperty->GetHideTitleBar().value_or(false)) {
123         titleBarLayoutProperty->UpdateVisibility(VisibleType::GONE);
124     } else {
125         titleBarLayoutProperty->UpdateVisibility(VisibleType::VISIBLE);
126     }
127     titleBarNode->MarkModifyDone();
128 }
129 
OnModifyDone()130 void NavDestinationPattern::OnModifyDone()
131 {
132     Pattern::OnModifyDone();
133     auto hostNode = AceType::DynamicCast<NavDestinationGroupNode>(GetHost());
134     CHECK_NULL_VOID(hostNode);
135     auto titleBarNode = AceType::DynamicCast<TitleBarNode>(hostNode->GetTitleBarNode());
136     CHECK_NULL_VOID(titleBarNode);
137     auto titleBarRenderContext = titleBarNode->GetRenderContext();
138     CHECK_NULL_VOID(titleBarRenderContext);
139     titleBarNode->SetInnerParentId(hostNode->GetInspectorId().value_or(""));
140     // set the titlebar to float on the top
141     titleBarRenderContext->UpdateZIndex(DEFAULT_TITLEBAR_ZINDEX);
142     auto navDestinationLayoutProperty = hostNode->GetLayoutProperty<NavDestinationLayoutProperty>();
143     CHECK_NULL_VOID(navDestinationLayoutProperty);
144     UpdateHideBarProperty();
145     ExpandContentSafeAreaIfNeeded();
146     UpdateNameIfNeeded(hostNode);
147     UpdateBackgroundColorIfNeeded(hostNode);
148     bool needRunTitleBarAnimation = false;
149     MountTitleBar(hostNode, needRunTitleBarAnimation);
150     bool needRunToolBarAnimation = false;
151     NavigationToolbarUtil::MountToolBar(hostNode, needRunToolBarAnimation);
152     HandleTitleBarAndToolBarAnimation(hostNode, needRunTitleBarAnimation, needRunToolBarAnimation);
153     auto pipeline = hostNode->GetContext();
154     CHECK_NULL_VOID(pipeline);
155     if (GreatOrEqual(pipeline->GetFontScale(), AgingAdapationDialogUtil::GetDialogBigFontSizeScale())) {
156         auto titleBarPattern = titleBarNode->GetPattern<TitleBarPattern>();
157         CHECK_NULL_VOID(titleBarPattern);
158         auto backButtonNode = AceType::DynamicCast<FrameNode>(titleBarNode->GetBackButton());
159         CHECK_NULL_VOID(backButtonNode);
160         titleBarPattern->InitBackButtonLongPressEvent(backButtonNode);
161     }
162     if (scrollableProcessor_) {
163         scrollableProcessor_->UpdateBindingRelation();
164     }
165     auto renderContext = hostNode->GetRenderContext();
166     CHECK_NULL_VOID(renderContext);
167     hostNode->UpdateUserSetOpacity(renderContext->GetOpacity().value_or(1.0f));
168 }
169 
OnLanguageConfigurationUpdate()170 void NavDestinationPattern::OnLanguageConfigurationUpdate()
171 {
172     if (isRightToLeft_ == AceApplicationInfo::GetInstance().IsRightToLeft()) {
173         return;
174     }
175     isRightToLeft_ = AceApplicationInfo::GetInstance().IsRightToLeft();
176     auto hostNode = AceType::DynamicCast<NavDestinationGroupNode>(GetHost());
177     CHECK_NULL_VOID(hostNode);
178     auto titleBarNode = AceType::DynamicCast<TitleBarNode>(hostNode->GetTitleBarNode());
179     CHECK_NULL_VOID(titleBarNode);
180     titleBarNode->MarkDirtyNode(PROPERTY_UPDATE_LAYOUT);
181     auto backButtonUINode = titleBarNode->GetBackButton();
182     auto backButtonNode = AceType::DynamicCast<FrameNode>(backButtonUINode);
183     CHECK_NULL_VOID(backButtonNode);
184     auto imageNode = backButtonNode->GetFirstChild();
185     CHECK_NULL_VOID(imageNode);
186     imageNode->MarkDirtyNode(PROPERTY_UPDATE_RENDER);
187 }
188 
UpdateNameIfNeeded(RefPtr<NavDestinationGroupNode> & hostNode)189 void NavDestinationPattern::UpdateNameIfNeeded(RefPtr<NavDestinationGroupNode>& hostNode)
190 {
191     if (!name_.empty()) {
192         return;
193     }
194     CHECK_NULL_VOID(hostNode);
195     if (hostNode->GetInspectorId().has_value()) {
196         name_ = hostNode->GetInspectorIdValue();
197     } else {
198         name_ = std::to_string(hostNode->GetId());
199     }
200     auto pathInfo = GetNavPathInfo();
201     if (pathInfo) {
202         pathInfo->SetName(name_);
203     }
204 }
205 
UpdateBackgroundColorIfNeeded(RefPtr<NavDestinationGroupNode> & hostNode)206 void NavDestinationPattern::UpdateBackgroundColorIfNeeded(RefPtr<NavDestinationGroupNode>& hostNode)
207 {
208     auto renderContext = hostNode->GetRenderContext();
209     CHECK_NULL_VOID(renderContext);
210     if (IsUserDefinedBgColor()) {
211         TAG_LOGI(AceLogTag::ACE_NAVIGATION, "User defined Background color: %{public}s",
212             renderContext->GetBackgroundColor()->ColorToString().c_str());
213         return;
214     }
215     if (hostNode->GetNavDestinationMode() == NavDestinationMode::DIALOG) {
216         renderContext->UpdateBackgroundColor(Color::TRANSPARENT);
217         TAG_LOGI(AceLogTag::ACE_NAVIGATION, "Set dialog background color: %{public}s",
218             renderContext->GetBackgroundColor()->ColorToString().c_str());
219         return;
220     }
221     auto pipelineContext = PipelineContext::GetCurrentContext();
222     if (!pipelineContext) {
223         return;
224     }
225     auto theme = pipelineContext->GetTheme<AppTheme>();
226     if (!theme) {
227         return;
228     }
229     renderContext->UpdateBackgroundColor(theme->GetBackgroundColor());
230     TAG_LOGI(AceLogTag::ACE_NAVIGATION, "Default background color: %{public}s",
231         renderContext->GetBackgroundColor()->ColorToString().c_str());
232 }
233 
MountTitleBar(RefPtr<NavDestinationGroupNode> & hostNode,bool & needRunTitleBarAnimation)234 void NavDestinationPattern::MountTitleBar(
235     RefPtr<NavDestinationGroupNode>& hostNode, bool& needRunTitleBarAnimation)
236 {
237     needRunTitleBarAnimation = false;
238     auto navDestinationLayoutProperty = hostNode->GetLayoutProperty<NavDestinationLayoutProperty>();
239     CHECK_NULL_VOID(navDestinationLayoutProperty);
240     auto titleBarNode = AceType::DynamicCast<TitleBarNode>(hostNode->GetTitleBarNode());
241     CHECK_NULL_VOID(titleBarNode);
242     auto titleBarLayoutProperty = titleBarNode->GetLayoutProperty<TitleBarLayoutProperty>();
243     CHECK_NULL_VOID(titleBarLayoutProperty);
244 
245     auto backButtonNode = AceType::DynamicCast<FrameNode>(titleBarNode->GetBackButton());
246     if (backButtonNode) {
247         auto backButtonLayoutProperty = backButtonNode->GetLayoutProperty();
248         CHECK_NULL_VOID(backButtonLayoutProperty);
249         backButtonLayoutProperty->UpdateVisibility(
250             navDestinationLayoutProperty->GetHideBackButtonValue(false) ? VisibleType::GONE : VisibleType::VISIBLE);
251     }
252     if (navDestinationLayoutProperty->HasNoPixMap()) {
253         if (navDestinationLayoutProperty->HasImageSource()) {
254             titleBarLayoutProperty->UpdateImageSource(navDestinationLayoutProperty->GetImageSourceValue());
255         }
256         if (navDestinationLayoutProperty->HasPixelMap()) {
257             titleBarLayoutProperty->UpdatePixelMap(navDestinationLayoutProperty->GetPixelMapValue());
258         }
259         titleBarLayoutProperty->UpdateNoPixMap(navDestinationLayoutProperty->GetNoPixMapValue());
260     }
261     bool hideTitleBar = navDestinationLayoutProperty->GetHideTitleBarValue(false);
262     BuildMenu(hostNode, titleBarNode);
263 
264     auto navDesIndex = hostNode->GetIndex();
265     if (navDesIndex == 0) {
266         navDestinationLayoutProperty->UpdatePropertyChangeFlag(PROPERTY_UPDATE_MEASURE);
267         titleBarLayoutProperty->UpdatePropertyChangeFlag(PROPERTY_UPDATE_MEASURE);
268     }
269 
270     if (currHideTitleBar_.has_value() && currHideTitleBar_.value() != hideTitleBar && hideTitleBar) {
271         /**
272          * we need reset translate&opacity of titleBar when state change from show to hide. @sa EnableTitleBarSwipe
273          */
274         NavigationTitleUtil::UpdateTitleOrToolBarTranslateYAndOpacity(hostNode, titleBarNode, 0.0f, true);
275     }
276     // At the initial state, animation is not required.
277     if (!currHideTitleBar_.has_value() || !navDestinationLayoutProperty->GetIsAnimatedTitleBarValue(false)) {
278         currHideTitleBar_ = hideTitleBar;
279         HideOrShowTitleBarImmediately(hostNode, hideTitleBar);
280         return;
281     }
282 
283     titleBarNode->MarkModifyDone();
284     titleBarNode->MarkDirtyNode(PROPERTY_UPDATE_MEASURE_SELF_AND_CHILD);
285 
286     // Animation is needed only when the status changed.
287     needRunTitleBarAnimation = currHideTitleBar_.value() != hideTitleBar;
288     currHideTitleBar_ = hideTitleBar;
289 }
290 
GetBackButtonState()291 bool NavDestinationPattern::GetBackButtonState()
292 {
293     auto hostNode = AceType::DynamicCast<NavDestinationGroupNode>(GetHost());
294     CHECK_NULL_RETURN(hostNode, false);
295     auto navDestinationLayoutProperty = hostNode->GetLayoutProperty<NavDestinationLayoutProperty>();
296     CHECK_NULL_RETURN(navDestinationLayoutProperty, false);
297 
298     auto translateState = navDestinationLayoutProperty->GetTitleBarTranslateStateValue(BarTranslateState::NONE);
299     if (navDestinationLayoutProperty->GetHideTitleBarValue(false) && translateState == BarTranslateState::NONE) {
300         return false;
301     }
302     // get navigation node
303     auto parent = AceType::DynamicCast<FrameNode>(hostNode->GetParent());
304     RefPtr<NavigationGroupNode> navigationNode;
305     while (parent && !parent->IsRootNode()) {
306         navigationNode = AceType::DynamicCast<NavigationGroupNode>(parent);
307         if (navigationNode) {
308             break;
309         }
310         parent = AceType::DynamicCast<FrameNode>(parent->GetParent());
311     }
312     if (!navigationNode) {
313         TAG_LOGW(AceLogTag::ACE_NAVIGATION, "can't find navigation node");
314         return false;
315     }
316     auto navigationLayoutProperty = navigationNode->GetLayoutProperty<NavigationLayoutProperty>();
317     CHECK_NULL_RETURN(navigationLayoutProperty, false);
318     auto pattern = navigationNode->GetPattern<NavigationPattern>();
319     auto stack = pattern->GetNavigationStack();
320     auto index = stack->FindIndex(name_, customNode_, true);
321     bool showBackButton = true;
322     auto titleBarNode = AceType::DynamicCast<TitleBarNode>(hostNode->GetTitleBarNode());
323     if (navDestinationLayoutProperty->GetHideBackButtonValue(false)) {
324         showBackButton = false;
325     }
326     if (index == 0 && (pattern->GetNavigationMode() == NavigationMode::SPLIT ||
327         navigationLayoutProperty->GetHideNavBarValue(false))) {
328         showBackButton = false;
329     }
330     auto isCustomTitle = hostNode->GetPrevTitleIsCustomValue(false);
331     if (isCustomTitle) {
332         return showBackButton;
333     }
334     auto titleBarPattern = titleBarNode->GetPattern<TitleBarPattern>();
335     CHECK_NULL_RETURN(titleBarPattern, showBackButton);
336     if (titleBarPattern->IsFontSizeSettedByDeveloper()) {
337         return showBackButton;
338     }
339     auto titleNode = AceType::DynamicCast<FrameNode>(titleBarNode->GetTitle());
340     CHECK_NULL_RETURN(titleNode, showBackButton);
341     auto theme = NavigationGetTheme();
342     CHECK_NULL_RETURN(theme, showBackButton);
343     auto textLayoutProperty = titleNode->GetLayoutProperty<TextLayoutProperty>();
344     auto currentFontSize = textLayoutProperty->GetAdaptMaxFontSizeValue(Dimension(0.0, DimensionUnit::FP));
345     auto targetFontSize = showBackButton ? theme->GetTitleFontSizeMin() : theme->GetTitleFontSize();
346     if (targetFontSize == currentFontSize) {
347         return showBackButton;
348     }
349     textLayoutProperty->UpdateAdaptMaxFontSize(targetFontSize);
350     textLayoutProperty->UpdatePropertyChangeFlag(PROPERTY_UPDATE_MEASURE);
351     return showBackButton;
352 }
353 
OnAttachToFrameNode()354 void NavDestinationPattern::OnAttachToFrameNode()
355 {
356     auto host = GetHost();
357     CHECK_NULL_VOID(host);
358     if (Container::GreatOrEqualAPIVersion(PlatformVersion::VERSION_ELEVEN)) {
359         SafeAreaExpandOpts opts = { .type = SAFE_AREA_TYPE_SYSTEM | SAFE_AREA_TYPE_CUTOUT,
360             .edges = SAFE_AREA_EDGE_ALL };
361         host->GetLayoutProperty()->UpdateSafeAreaExpandOpts(opts);
362     }
363     isRightToLeft_ = AceApplicationInfo::GetInstance().IsRightToLeft();
364     auto id = host->GetId();
365     auto pipeline = host->GetContext();
366     CHECK_NULL_VOID(pipeline);
367 
368     pipeline->AddWindowStateChangedCallback(id);
369     pipeline->AddWindowSizeChangeCallback(id);
370     pipeline->GetMemoryManager()->AddRecyclePageNode(host);
371 }
372 
OnDetachFromFrameNode(FrameNode * frameNode)373 void NavDestinationPattern::OnDetachFromFrameNode(FrameNode* frameNode)
374 {
375     CHECK_NULL_VOID(frameNode);
376     auto id = frameNode->GetId();
377     auto pipeline = frameNode->GetContext();
378     CHECK_NULL_VOID(pipeline);
379     pipeline->RemoveWindowStateChangedCallback(id);
380     pipeline->RemoveWindowSizeChangeCallback(id);
381     pipeline->GetMemoryManager()->RemoveRecyclePageNode(id);
382 }
383 
DumpInfo()384 void NavDestinationPattern::DumpInfo()
385 {
386     DumpLog::GetInstance().AddDesc(std::string("name: ").append(name_));
387 }
388 
OverlayOnBackPressed()389 bool NavDestinationPattern::OverlayOnBackPressed()
390 {
391     CHECK_NULL_RETURN(overlayManager_, false);
392     if (overlayManager_->IsCurrentNodeProcessRemoveOverlay(GetHost(), false)) {
393         return overlayManager_->RemoveOverlay(true);
394     }
395     return false;
396 }
397 
NeedIgnoreKeyboard()398 bool NavDestinationPattern::NeedIgnoreKeyboard()
399 {
400     auto layoutProperty = GetLayoutProperty<NavDestinationLayoutProperty>();
401     CHECK_NULL_RETURN(layoutProperty, false);
402     auto& opts = layoutProperty->GetSafeAreaExpandOpts();
403     if (opts && (opts->type & SAFE_AREA_TYPE_KEYBOARD) && (opts->edges & SAFE_AREA_EDGE_BOTTOM)) {
404         return true;
405     }
406     return false;
407 }
408 
OnFontScaleConfigurationUpdate()409 void NavDestinationPattern::OnFontScaleConfigurationUpdate()
410 {
411     auto hostNode = AceType::DynamicCast<NavDestinationGroupNode>(GetHost());
412     CHECK_NULL_VOID(hostNode);
413     auto pipeline = hostNode->GetContext();
414     CHECK_NULL_VOID(pipeline);
415     auto titleBarUINode = hostNode->GetTitleBarNode();
416     auto titleBarNode = AceType::DynamicCast<TitleBarNode>(titleBarUINode);
417     CHECK_NULL_VOID(titleBarNode);
418     auto backButtonNode = AceType::DynamicCast<FrameNode>(titleBarNode->GetBackButton());
419     CHECK_NULL_VOID(backButtonNode);
420     if (LessNotEqual(pipeline->GetFontScale(), AgingAdapationDialogUtil::GetDialogBigFontSizeScale())) {
421         auto gestureHub = backButtonNode->GetOrCreateGestureEventHub();
422         CHECK_NULL_VOID(gestureHub);
423         gestureHub->SetLongPressEvent(nullptr);
424         auto longPressRecognizer = gestureHub->GetLongPressRecognizer();
425         CHECK_NULL_VOID(longPressRecognizer);
426         longPressRecognizer->SetOnActionEnd(nullptr);
427         return;
428     }
429     auto titleBarPattern = titleBarNode->GetPattern<TitleBarPattern>();
430     CHECK_NULL_VOID(titleBarPattern);
431     titleBarPattern->InitBackButtonLongPressEvent(backButtonNode);
432 }
433 
SetSystemBarStyle(const RefPtr<SystemBarStyle> & style)434 void NavDestinationPattern::SetSystemBarStyle(const RefPtr<SystemBarStyle>& style)
435 {
436     auto host = GetHost();
437     CHECK_NULL_VOID(host);
438     auto pipeline = host->GetContext();
439     CHECK_NULL_VOID(pipeline);
440     auto windowManager = pipeline->GetWindowManager();
441     CHECK_NULL_VOID(windowManager);
442     if (!backupStyle_.has_value()) {
443         backupStyle_ = windowManager->GetSystemBarStyle();
444     }
445     currStyle_ = style;
446     auto navigationNode = AceType::DynamicCast<NavigationGroupNode>(navigationNode_.Upgrade());
447     CHECK_NULL_VOID(navigationNode);
448     auto navigationPattern = navigationNode->GetPattern<NavigationPattern>();
449     if (navigationPattern->IsFullPageNavigation() && navigationPattern->IsTopNavDestination(host)) {
450         if (currStyle_.value() != nullptr) {
451             windowManager->SetSystemBarStyle(currStyle_.value());
452         } else {
453             navigationPattern->TryRestoreSystemBarStyle(windowManager);
454         }
455     }
456 }
457 
GetTitlebarZIndex() const458 int32_t NavDestinationPattern::GetTitlebarZIndex() const
459 {
460     return DEFAULT_TITLEBAR_ZINDEX;
461 }
462 
OnWindowHide()463 void NavDestinationPattern::OnWindowHide()
464 {
465     CHECK_NULL_VOID(navDestinationContext_);
466     auto navPathInfo = navDestinationContext_->GetNavPathInfo();
467     CHECK_NULL_VOID(navPathInfo);
468     if (!navPathInfo->GetIsEntry()) {
469         return;
470     }
471     TAG_LOGI(AceLogTag::ACE_NAVIGATION, "window lifecycle change to hide, clear navDestination entry tag");
472     navPathInfo->SetIsEntry(false);
473     auto stack = GetNavigationStack().Upgrade();
474     CHECK_NULL_VOID(stack);
475     auto index = navDestinationContext_->GetIndex();
476     stack->SetIsEntryByIndex(index, false);
477 }
478 
DumpInfo(std::unique_ptr<JsonValue> & json)479 void NavDestinationPattern::DumpInfo(std::unique_ptr<JsonValue>& json)
480 {
481     json->Put("name", name_.c_str());
482 }
483 
OnWindowSizeChanged(int32_t width,int32_t height,WindowSizeChangeReason type)484 void NavDestinationPattern::OnWindowSizeChanged(int32_t width, int32_t height, WindowSizeChangeReason type)
485 {
486     auto navDestinationGroupNode = AceType::DynamicCast<NavDestinationGroupNode>(GetHost());
487     CHECK_NULL_VOID(navDestinationGroupNode);
488     if (preWidth_.has_value() && preWidth_.value() != width) {
489         AbortBarAnimation();
490     }
491     preWidth_ = width;
492     // change menu num in landscape and orientation
493     do {
494         if (navDestinationGroupNode->GetPrevMenuIsCustomValue(false)) {
495             break;
496         }
497         auto targetNum = SystemProperties::GetDeviceOrientation() == DeviceOrientation::LANDSCAPE ? MAX_MENU_NUM_LARGE
498                                                                                                   : MAX_MENU_NUM_SMALL;
499         if (targetNum == maxMenuNums_) {
500             break;
501         }
502         maxMenuNums_ = targetNum;
503         auto titleBarNode = AceType::DynamicCast<TitleBarNode>(navDestinationGroupNode->GetTitleBarNode());
504         CHECK_NULL_VOID(titleBarNode);
505         BuildMenu(navDestinationGroupNode, titleBarNode);
506         titleBarNode->MarkDirtyNode(PROPERTY_UPDATE_MEASURE_SELF_AND_CHILD);
507     } while (0);
508     if (type == WindowSizeChangeReason::ROTATION) {
509         CloseLongPressDialog();
510     }
511 }
512 
CloseLongPressDialog()513 void NavDestinationPattern::CloseLongPressDialog()
514 {
515     auto navDestinationGroupNode = AceType::DynamicCast<NavDestinationGroupNode>(GetHost());
516     CHECK_NULL_VOID(navDestinationGroupNode);
517     auto pipeline = navDestinationGroupNode->GetContext();
518     CHECK_NULL_VOID(pipeline);
519     auto overlayManager = pipeline->GetOverlayManager();
520     CHECK_NULL_VOID(overlayManager);
521 
522     auto titleBarNode = AceType::DynamicCast<TitleBarNode>(navDestinationGroupNode->GetTitleBarNode());
523     CHECK_NULL_VOID(titleBarNode);
524     auto titleBarPattern = titleBarNode->GetPattern<TitleBarPattern>();
525     CHECK_NULL_VOID(titleBarPattern);
526     auto backButtonDialogNode = titleBarPattern->GetBackButtonDialogNode();
527     if (backButtonDialogNode) {
528         overlayManager->CloseDialog(backButtonDialogNode);
529         titleBarPattern->SetBackButtonDialogNode(nullptr);
530     }
531     auto menuItemDialogNode = titleBarPattern->GetLargeFontPopUpDialogNode();
532     if (menuItemDialogNode) {
533         overlayManager->CloseDialog(menuItemDialogNode);
534         titleBarPattern->SetLargeFontPopUpDialogNode(nullptr);
535     }
536 }
537 
UpdateTitleAndToolBarHiddenOffset(float offset)538 void NavDestinationPattern::UpdateTitleAndToolBarHiddenOffset(float offset)
539 {
540     CancelShowTitleAndToolBarTask();
541     auto nodeBase = AceType::DynamicCast<NavDestinationNodeBase>(GetHost());
542     CHECK_NULL_VOID(nodeBase);
543     if (EnableTitleBarSwipe(nodeBase)) {
544         auto titleBarNode = AceType::DynamicCast<TitleBarNode>(nodeBase->GetTitleBarNode());
545         UpdateBarHiddenOffset(nodeBase, titleBarNode, offset, true);
546     }
547     if (EnableToolBarSwipe(nodeBase)) {
548         auto toolBarNode = AceType::DynamicCast<NavToolbarNode>(nodeBase->GetToolBarNode());
549         UpdateBarHiddenOffset(nodeBase, toolBarNode, offset, false);
550     }
551 }
552 
CancelShowTitleAndToolBarTask()553 void NavDestinationPattern::CancelShowTitleAndToolBarTask()
554 {
555     if (titleBarSwipeContext_.showBarTask) {
556         titleBarSwipeContext_.showBarTask.Cancel();
557         titleBarSwipeContext_.showBarTask.Reset(nullptr);
558     }
559     if (toolBarSwipeContext_.showBarTask) {
560         toolBarSwipeContext_.showBarTask.Cancel();
561         toolBarSwipeContext_.showBarTask.Reset(nullptr);
562     }
563 }
564 
ResetTitleAndToolBarState()565 void NavDestinationPattern::ResetTitleAndToolBarState()
566 {
567     auto nodeBase = AceType::DynamicCast<NavDestinationNodeBase>(GetHost());
568     CHECK_NULL_VOID(nodeBase);
569     if (EnableTitleBarSwipe(nodeBase)) {
570         auto titleBarNode = AceType::DynamicCast<TitleBarNode>(nodeBase->GetTitleBarNode());
571         ResetBarState(nodeBase, titleBarNode, true);
572     }
573     if (EnableToolBarSwipe(nodeBase)) {
574         auto toolBarNode = AceType::DynamicCast<NavToolbarNode>(nodeBase->GetToolBarNode());
575         ResetBarState(nodeBase, toolBarNode, false);
576     }
577 }
578 
ResetBarState(const RefPtr<NavDestinationNodeBase> & nodeBase,const RefPtr<FrameNode> & barNode,bool isTitle)579 void NavDestinationPattern::ResetBarState(const RefPtr<NavDestinationNodeBase>& nodeBase,
580     const RefPtr<FrameNode>& barNode, bool isTitle)
581 {
582     CHECK_NULL_VOID(nodeBase);
583     CHECK_NULL_VOID(barNode);
584     auto& ctx = GetSwipeContext(isTitle);
585     if (ctx.isBarHiding || ctx.isBarShowing) {
586         return;
587     }
588 
589     float translate = 0.0f;
590     float barHeight = 0.0f;
591     if (!GetTitleOrToolBarTranslateAndHeight(barNode, translate, barHeight) || NearZero(barHeight)) {
592         return;
593     }
594 
595     auto threshold = Dimension(TRANSLATE_THRESHOLD, DimensionUnit::VP).ConvertToPx();
596     float halfBarHeight = barHeight / 2.0f;
597     if (GreatOrEqual(threshold, halfBarHeight)) {
598         threshold = halfBarHeight;
599     }
600     float showAreaHeight = barHeight - std::abs(translate);
601     if (GreatNotEqual(showAreaHeight, 0.0f) && LessNotEqual(showAreaHeight, threshold)) {
602         /**
603          * Scroll to show a small portion of the titleBar&toolBar,
604          * but the height of shownArea is less than the threshold,
605          * it needs to be restored to the hidden state.
606          */
607         StartHideOrShowBarInner(nodeBase, barHeight, translate, isTitle, true);
608     } else if (GreatOrEqual(showAreaHeight, barHeight - threshold) && LessNotEqual(showAreaHeight, barHeight)) {
609         /**
610          * Scroll to hide a small portion of the titleBar&toolBar,
611          * but the height of hiddenArea is less than the threshold,
612          * it needs to be restored to the shown state.
613          */
614         StartHideOrShowBarInner(nodeBase, barHeight, translate, isTitle, false);
615     }
616 }
617 
EnableTitleBarSwipe(const RefPtr<NavDestinationNodeBase> & nodeBase)618 bool NavDestinationPattern::EnableTitleBarSwipe(const RefPtr<NavDestinationNodeBase>& nodeBase)
619 {
620     CHECK_NULL_RETURN(nodeBase, false);
621     auto property = nodeBase->GetLayoutProperty<NavDestinationLayoutPropertyBase>();
622     CHECK_NULL_RETURN(property, false);
623     return !property->GetHideTitleBarValue(false);
624 }
625 
EnableToolBarSwipe(const RefPtr<NavDestinationNodeBase> & nodeBase)626 bool NavDestinationPattern::EnableToolBarSwipe(const RefPtr<NavDestinationNodeBase>& nodeBase)
627 {
628     CHECK_NULL_RETURN(nodeBase, false);
629     auto property = nodeBase->GetLayoutProperty<NavDestinationLayoutPropertyBase>();
630     CHECK_NULL_RETURN(property, false);
631     return !property->GetHideToolBarValue(false);
632 }
633 
UpdateBarHiddenOffset(const RefPtr<NavDestinationNodeBase> & nodeBase,const RefPtr<FrameNode> & barNode,float offset,bool isTitle)634 void NavDestinationPattern::UpdateBarHiddenOffset(
635     const RefPtr<NavDestinationNodeBase>& nodeBase, const RefPtr<FrameNode>& barNode, float offset, bool isTitle)
636 {
637     CHECK_NULL_VOID(nodeBase);
638     CHECK_NULL_VOID(barNode);
639     auto& ctx = GetSwipeContext(isTitle);
640     if (ctx.isBarShowing || ctx.isBarHiding) {
641         return;
642     }
643 
644     float preTranslate = 0.0f;
645     float barHeight = 0.0f;
646     if (!GetTitleOrToolBarTranslateAndHeight(barNode, preTranslate, barHeight) || NearZero(barHeight)) {
647         return;
648     }
649 
650     float newTranslate = 0.0f;
651     if (isTitle) {
652         newTranslate = std::clamp(preTranslate - offset, -barHeight, 0.0f);
653     } else {
654         newTranslate = std::clamp(preTranslate + offset, 0.0f, barHeight);
655     }
656     NavigationTitleUtil::UpdateTitleOrToolBarTranslateYAndOpacity(nodeBase, barNode, newTranslate, isTitle);
657 
658     auto threshold = Dimension(TRANSLATE_THRESHOLD, DimensionUnit::VP).ConvertToPx();
659     float halfBarHeight = barHeight / 2.0f;
660     if (GreatOrEqual(threshold, halfBarHeight)) {
661         threshold = halfBarHeight;
662     }
663     if (Positive(offset) && LessNotEqual(std::abs(preTranslate), threshold) &&
664         GreatOrEqual(std::abs(newTranslate), threshold)) {
665         // When the scrolling up distance exceeds the threshold, it is necessary to start the hide animation.
666         StartHideOrShowBarInner(nodeBase, barHeight, newTranslate, isTitle, true);
667     } else if (Negative(offset) && LessNotEqual(barHeight - std::abs(preTranslate), threshold) &&
668         GreatOrEqual(barHeight - std::abs(newTranslate), threshold)) {
669         // When the scrolling down distance exceeds the threshold, it is necessary to start the show animation.
670         StartHideOrShowBarInner(nodeBase, barHeight, newTranslate, isTitle, false);
671     }
672 }
673 
ShowTitleAndToolBar()674 void NavDestinationPattern::ShowTitleAndToolBar()
675 {
676     auto nodeBase = AceType::DynamicCast<NavDestinationNodeBase>(GetHost());
677     CHECK_NULL_VOID(nodeBase);
678     if (EnableTitleBarSwipe(nodeBase)) {
679         auto titleBarNode = AceType::DynamicCast<TitleBarNode>(nodeBase->GetTitleBarNode());
680         float translate = 0.0f;
681         float barHeight = 0.0f;
682         if (GetTitleOrToolBarTranslateAndHeight(titleBarNode, translate, barHeight)) {
683             if (titleBarSwipeContext_.showBarTask) {
684                 titleBarSwipeContext_.showBarTask.Cancel();
685                 titleBarSwipeContext_.showBarTask.Reset(nullptr);
686             }
687             StopHideBarIfNeeded(translate, true);
688             StartHideOrShowBarInner(nodeBase, barHeight, translate, true, false);
689         }
690     }
691     if (EnableToolBarSwipe(nodeBase)) {
692         auto toolBarNode = AceType::DynamicCast<NavToolbarNode>(nodeBase->GetToolBarNode());
693         float translate = 0.0f;
694         float barHeight = 0.0f;
695         if (GetTitleOrToolBarTranslateAndHeight(toolBarNode, translate, barHeight)) {
696             if (toolBarSwipeContext_.showBarTask) {
697                 toolBarSwipeContext_.showBarTask.Cancel();
698                 toolBarSwipeContext_.showBarTask.Reset(nullptr);
699             }
700             StopHideBarIfNeeded(translate, false);
701             StartHideOrShowBarInner(nodeBase, barHeight, translate, false, false);
702         }
703     }
704 }
705 
StartHideOrShowBarInner(const RefPtr<NavDestinationNodeBase> & nodeBase,float barHeight,float curTranslate,bool isTitle,bool isHide)706 void NavDestinationPattern::StartHideOrShowBarInner(
707     const RefPtr<NavDestinationNodeBase>& nodeBase, float barHeight, float curTranslate, bool isTitle, bool isHide)
708 {
709     CHECK_NULL_VOID(nodeBase);
710     auto barNode = GetBarNode(nodeBase, isTitle);
711     CHECK_NULL_VOID(barNode);
712 
713     auto propertyCallback = [weak = WeakClaim(this), barHeight, isTitle, isHide]() {
714         auto pattern = weak.Upgrade();
715         CHECK_NULL_VOID(pattern);
716         auto nodeBase = AceType::DynamicCast<NavDestinationNodeBase>(pattern->GetHost());
717         CHECK_NULL_VOID(nodeBase);
718         auto barNode = pattern->GetBarNode(nodeBase, isTitle);
719         CHECK_NULL_VOID(barNode);
720         float translate = isHide ? (isTitle ? -barHeight : barHeight) : 0.0f;
721         NavigationTitleUtil::UpdateTitleOrToolBarTranslateYAndOpacity(nodeBase, barNode, translate, isTitle);
722     };
723     auto finishCallback = [weak = WeakClaim(this), isTitle, isHide]() {
724         auto pattern = weak.Upgrade();
725         CHECK_NULL_VOID(pattern);
726         auto nodeBase = AceType::DynamicCast<NavDestinationNodeBase>(pattern->GetHost());
727         CHECK_NULL_VOID(nodeBase);
728         auto barNode = pattern->GetBarNode(nodeBase, isTitle);
729         CHECK_NULL_VOID(barNode);
730         auto& ctx = pattern->GetSwipeContext(isTitle);
731         if (isHide) {
732             ctx.isBarHiding = false;
733         } else {
734             ctx.isBarShowing = false;
735         }
736     };
737     AnimationOption option;
738     option.SetCurve(TRANSLATE_CURVE);
739     auto& ctx = GetSwipeContext(isTitle);
740     if (isHide) {
741         ctx.isBarHiding = true;
742     } else {
743         ctx.isBarShowing = true;
744     }
745     NavigationTitleUtil::UpdateTitleOrToolBarTranslateYAndOpacity(nodeBase, barNode, curTranslate, isTitle);
746     AnimationUtils::Animate(option, propertyCallback, finishCallback);
747 }
748 
StopHideBarIfNeeded(float curTranslate,bool isTitle)749 void NavDestinationPattern::StopHideBarIfNeeded(float curTranslate, bool isTitle)
750 {
751     auto& ctx = GetSwipeContext(isTitle);
752     if (!ctx.isBarHiding) {
753         return;
754     }
755 
756     auto propertyCallback = [weak = WeakClaim(this), isTitle, curTranslate]() {
757         auto pattern = weak.Upgrade();
758         CHECK_NULL_VOID(pattern);
759         auto nodeBase = AceType::DynamicCast<NavDestinationNodeBase>(pattern->GetHost());
760         CHECK_NULL_VOID(nodeBase);
761         auto barNode = pattern->GetBarNode(nodeBase, isTitle);
762         CHECK_NULL_VOID(barNode);
763         NavigationTitleUtil::UpdateTitleOrToolBarTranslateYAndOpacity(nodeBase, barNode, curTranslate, isTitle);
764     };
765     AnimationOption option;
766     option.SetDuration(0);
767     option.SetCurve(Curves::LINEAR);
768     AnimationUtils::Animate(option, propertyCallback);
769     ctx.isBarHiding = false;
770 }
771 
GetBarNode(const RefPtr<NavDestinationNodeBase> & nodeBase,bool isTitle)772 RefPtr<FrameNode> NavDestinationPattern::GetBarNode(const RefPtr<NavDestinationNodeBase>& nodeBase, bool isTitle)
773 {
774     CHECK_NULL_RETURN(nodeBase, nullptr);
775     return isTitle ? AceType::DynamicCast<FrameNode>(nodeBase->GetTitleBarNode())
776                    : AceType::DynamicCast<FrameNode>(nodeBase->GetToolBarNode());
777 }
778 
OnCoordScrollStart()779 void NavDestinationPattern::OnCoordScrollStart()
780 {
781     auto navDestinationGroupNode = AceType::DynamicCast<NavDestinationGroupNode>(GetHost());
782     CHECK_NULL_VOID(navDestinationGroupNode);
783     auto navDestinationEventHub = navDestinationGroupNode->GetEventHub<NavDestinationEventHub>();
784     CHECK_NULL_VOID(navDestinationEventHub);
785     navDestinationEventHub->FireOnCoordScrollStartAction();
786 }
787 
OnCoordScrollUpdate(float offset,float currentOffset)788 float NavDestinationPattern::OnCoordScrollUpdate(float offset, float currentOffset)
789 {
790     auto navDestinationGroupNode = AceType::DynamicCast<NavDestinationGroupNode>(GetHost());
791     CHECK_NULL_RETURN(navDestinationGroupNode, 0.0f);
792     auto navDestinationEventHub = navDestinationGroupNode->GetEventHub<NavDestinationEventHub>();
793     CHECK_NULL_RETURN(navDestinationEventHub, 0.0f);
794     navDestinationEventHub->FireOnCoordScrollUpdateAction(currentOffset);
795     return 0.0f;
796 }
797 
OnCoordScrollEnd()798 void NavDestinationPattern::OnCoordScrollEnd()
799 {
800     auto navDestinationGroupNode = AceType::DynamicCast<NavDestinationGroupNode>(GetHost());
801     CHECK_NULL_VOID(navDestinationGroupNode);
802     auto navDestinationEventHub = navDestinationGroupNode->GetEventHub<NavDestinationEventHub>();
803     CHECK_NULL_VOID(navDestinationEventHub);
804     navDestinationEventHub->FireOnCoordScrollEndAction();
805 }
806 } // namespace OHOS::Ace::NG
807