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/components_ng/pattern/navigation/nav_bar_pattern.h"
17 
18 #include <algorithm>
19 
20 #include "base/i18n/localization.h"
21 #include "core/common/container.h"
22 #include "core/components_ng/base/view_abstract.h"
23 #include "core/components_ng/pattern/bubble/bubble_pattern.h"
24 #include "core/components_ng/pattern/button/button_layout_property.h"
25 #include "core/components_ng/pattern/button/button_pattern.h"
26 #include "core/components_ng/pattern/grid/grid_pattern.h"
27 #include "core/components_ng/pattern/image/image_layout_property.h"
28 #include "core/components_ng/pattern/image/image_pattern.h"
29 #include "core/components_ng/pattern/menu/menu_view.h"
30 #include "core/components_ng/pattern/menu/wrapper/menu_wrapper_pattern.h"
31 #include "core/components_ng/pattern/navigation/bar_item_event_hub.h"
32 #include "core/components_ng/pattern/navigation/bar_item_pattern.h"
33 #include "core/components_ng/pattern/navigation/navigation_pattern.h"
34 #include "core/components_ng/pattern/navigation/navigation_title_util.h"
35 #include "core/components_ng/pattern/navigation/navigation_toolbar_util.h"
36 #include "core/components_ng/pattern/navigation/title_bar_pattern.h"
37 #include "core/components_ng/pattern/navigation/tool_bar_node.h"
38 #include "core/components_ng/pattern/text/text_pattern.h"
39 
40 namespace OHOS::Ace::NG {
41 namespace {
42 // titlebar ZINDEX
43 constexpr static int32_t DEFAULT_TITLEBAR_ZINDEX = 2;
44 constexpr float DEFAULT_NAV_BAR_MASK_OPACITY = 0.6f;
BuildMoreItemNodeAction(const RefPtr<FrameNode> & buttonNode,const RefPtr<BarItemNode> & barItemNode,const RefPtr<FrameNode> & barMenuNode,const RefPtr<NavBarNode> & navBarNode)45 void BuildMoreItemNodeAction(const RefPtr<FrameNode>& buttonNode, const RefPtr<BarItemNode>& barItemNode,
46     const RefPtr<FrameNode>& barMenuNode, const RefPtr<NavBarNode>& navBarNode)
47 {
48     auto eventHub = barItemNode->GetEventHub<BarItemEventHub>();
49     CHECK_NULL_VOID(eventHub);
50 
51     auto context = PipelineContext::GetCurrentContext();
52     auto clickCallback = [weakContext = WeakPtr<PipelineContext>(context), id = barItemNode->GetId(),
53                              weakMenu = WeakPtr<FrameNode>(barMenuNode),
54                              weakBarItemNode = WeakPtr<BarItemNode>(barItemNode),
55                              weakNavBarNode = WeakPtr<NavBarNode>(navBarNode)]() {
56         auto context = weakContext.Upgrade();
57         CHECK_NULL_VOID(context);
58 
59         auto overlayManager = context->GetOverlayManager();
60         CHECK_NULL_VOID(overlayManager);
61 
62         auto menu = weakMenu.Upgrade();
63         CHECK_NULL_VOID(menu);
64 
65         auto barItemNode = weakBarItemNode.Upgrade();
66         CHECK_NULL_VOID(barItemNode);
67 
68         auto menuNode = AceType::DynamicCast<FrameNode>(menu->GetChildAtIndex(0));
69         CHECK_NULL_VOID(menuNode);
70 
71         auto menuPattern = menuNode->GetPattern<MenuPattern>();
72         CHECK_NULL_VOID(menuPattern);
73 
74         auto navBarNode = weakNavBarNode.Upgrade();
75         CHECK_NULL_VOID(navBarNode);
76 
77         auto navBarPattern = navBarNode->GetPattern<NavBarPattern>();
78         CHECK_NULL_VOID(navBarPattern);
79 
80         // navigation menu show like select.
81         menuPattern->SetIsSelectMenu(true);
82         OffsetF offset(0.0f, 0.0f);
83         if (AceApplicationInfo::GetInstance().GreatOrEqualTargetAPIVersion(PlatformVersion::VERSION_TWELVE)) {
84             auto symbol = AceType::DynamicCast<FrameNode>(barItemNode->GetChildren().front());
85             CHECK_NULL_VOID(symbol);
86             auto symbolProperty = symbol->GetLayoutProperty<TextLayoutProperty>();
87             CHECK_NULL_VOID(symbolProperty);
88             auto symbolEffectOptions = symbolProperty->GetSymbolEffectOptionsValue(SymbolEffectOptions());
89             symbolEffectOptions.SetEffectType(SymbolEffectType::BOUNCE);
90             symbolEffectOptions.SetIsTxtActive(true);
91             symbolEffectOptions.SetIsTxtActiveSource(0);
92             symbolProperty->UpdateSymbolEffectOptions(symbolEffectOptions);
93             symbol->MarkDirtyNode(PROPERTY_UPDATE_MEASURE_SELF);
94         } else {
95             offset = navBarPattern->GetShowMenuOffset(barItemNode, menuNode);
96         }
97         overlayManager->ShowMenu(id, offset, menu);
98     };
99     eventHub->SetItemAction(clickCallback);
100 
101     auto gestureEventHub = buttonNode->GetOrCreateGestureEventHub();
102     CHECK_NULL_VOID(gestureEventHub);
103     auto callback = [action = clickCallback](GestureEvent& info) {
104         if (info.GetSourceDevice() == SourceType::KEYBOARD) {
105             return;
106         }
107         action();
108     };
109     gestureEventHub->AddClickEvent(AceType::MakeRefPtr<ClickEvent>(callback));
110 }
111 
CreateMenuItems(const int32_t menuNodeId,const std::vector<NG::BarItem> & menuItems,RefPtr<NavBarNode> navBarNode,bool isCreateLandscapeMenu)112 RefPtr<FrameNode> CreateMenuItems(const int32_t menuNodeId, const std::vector<NG::BarItem>& menuItems,
113     RefPtr<NavBarNode> navBarNode, bool isCreateLandscapeMenu)
114 {
115     auto menuNode = FrameNode::GetOrCreateFrameNode(
116         V2::NAVIGATION_MENU_ETS_TAG, menuNodeId, []() { return AceType::MakeRefPtr<LinearLayoutPattern>(false); });
117     CHECK_NULL_RETURN(menuNode, nullptr);
118     menuNode->Clean();
119     menuNode->MarkDirtyNode(PROPERTY_UPDATE_MEASURE);
120     auto rowProperty = menuNode->GetLayoutProperty<LinearLayoutProperty>();
121     CHECK_NULL_RETURN(rowProperty, nullptr);
122     rowProperty->UpdateMainAxisAlign(FlexAlign::SPACE_BETWEEN);
123     auto theme = NavigationGetTheme();
124     auto navBarPattern = AceType::DynamicCast<NavBarPattern>(navBarNode->GetPattern());
125     auto navBarMaxNum = navBarPattern->GetMaxMenuNum();
126     auto mostMenuItemCount =
127         navBarMaxNum < 0 ? theme->GetMostMenuItemCountInBar() : static_cast<uint32_t>(navBarMaxNum);
128     mostMenuItemCount = SystemProperties::GetDeviceOrientation() == DeviceOrientation::LANDSCAPE ? MAX_MENU_NUM_LARGE
129                                                                                                   : mostMenuItemCount;
130     navBarPattern->SetMaxMenuNum(mostMenuItemCount);
131     bool needMoreButton = menuItems.size() > mostMenuItemCount ? true : false;
132 
133     auto frameNode = navBarNode->GetParent();
134     auto navigationGroupNode = AceType::DynamicCast<NavigationGroupNode>(frameNode);
135     CHECK_NULL_RETURN(navigationGroupNode, nullptr);
136     auto hub = navigationGroupNode->GetEventHub<EventHub>();
137     CHECK_NULL_RETURN(hub, nullptr);
138     auto isButtonEnabled = hub->IsEnabled();
139 
140     std::string parentId = navigationGroupNode->GetInspectorId().value_or("");
141     int32_t count = 0;
142     std::vector<OptionParam> params;
143     OptionParam param;
144     for (const auto& menuItem : menuItems) {
145         ++count;
146         if (needMoreButton && (count > static_cast<int32_t>(mostMenuItemCount) - 1)) {
147             param = { menuItem.text.value_or(""), menuItem.icon.value_or(""), menuItem.isEnabled.value_or(true),
148                 menuItem.action, menuItem.iconSymbol.value_or(nullptr) };
149             param.SetSymbolUserDefinedIdealFontSize(theme->GetMenuIconSize());
150             params.push_back(param);
151         } else {
152             auto menuItemNode = NavigationTitleUtil::CreateMenuItemButton(theme);
153             int32_t barItemNodeId = ElementRegister::GetInstance()->MakeUniqueId();
154             auto barItemNode = BarItemNode::GetOrCreateBarItemNode(
155                 V2::BAR_ITEM_ETS_TAG, barItemNodeId, []() { return AceType::MakeRefPtr<BarItemPattern>(); });
156             NavigationTitleUtil::UpdateBarItemNodeWithItem(barItemNode, menuItem, isButtonEnabled);
157             auto barItemLayoutProperty = barItemNode->GetLayoutProperty();
158             CHECK_NULL_RETURN(barItemLayoutProperty, nullptr);
159             barItemLayoutProperty->UpdateMeasureType(MeasureType::MATCH_PARENT);
160 
161             auto iconNode = AceType::DynamicCast<FrameNode>(barItemNode->GetChildren().front());
162             NavigationTitleUtil::InitTitleBarButtonEvent(
163                 menuItemNode, iconNode, false, menuItem, menuItem.isEnabled.value_or(true));
164 
165             // read navigation menu button
166             NavigationTitleUtil::SetAccessibility(menuItemNode, menuItem.text.value_or(""));
167 
168             // set navigation titleBar menu inspectorId
169             std::string menuItemValue = menuItemNode->GetTag() + std::to_string(count);
170             // Field field;
171             NavigationTitleUtil::SetInnerChildId(menuItemNode, NG::NAV_FIELD,
172                 menuNode->GetTag(), menuItemValue, parentId);
173 
174             barItemNode->MountToParent(menuItemNode);
175             barItemNode->MarkModifyDone();
176             menuItemNode->MarkModifyDone();
177             menuNode->AddChild(menuItemNode);
178         }
179     }
180 
181     // build more button
182     if (needMoreButton) {
183         int32_t barItemNodeId = ElementRegister::GetInstance()->MakeUniqueId();
184         auto barItemNode = BarItemNode::GetOrCreateBarItemNode(
185             V2::BAR_ITEM_ETS_TAG, barItemNodeId, []() { return AceType::MakeRefPtr<BarItemPattern>(); });
186         auto barItemLayoutProperty = barItemNode->GetLayoutProperty();
187         CHECK_NULL_RETURN(barItemLayoutProperty, nullptr);
188         barItemLayoutProperty->UpdateMeasureType(MeasureType::MATCH_PARENT);
189         NavigationTitleUtil::BuildMoreIemNode(barItemNode, isButtonEnabled);
190         auto menuItemNode = NavigationTitleUtil::CreateMenuItemButton(theme);
191         MenuParam menuParam;
192         menuParam.isShowInSubWindow = false;
193         auto targetId = barItemNode->GetId();
194         auto targetTag = barItemNode->GetTag();
195         if (AceApplicationInfo::GetInstance().GreatOrEqualTargetAPIVersion(PlatformVersion::VERSION_TWELVE)) {
196             menuParam.placement = Placement::BOTTOM_RIGHT;
197             targetId = menuItemNode->GetId();
198             targetTag = menuItemNode->GetTag();
199         }
200         auto barMenuNode = MenuView::Create(
201             std::move(params), targetId, targetTag, MenuType::NAVIGATION_MENU, menuParam);
202         BuildMoreItemNodeAction(menuItemNode, barItemNode, barMenuNode, navBarNode);
203         auto iconNode = AceType::DynamicCast<FrameNode>(barItemNode->GetChildren().front());
204         NavigationTitleUtil::InitTitleBarButtonEvent(menuItemNode, iconNode, true);
205 
206         // read navigation "more" button
207         std::string message  = Localization::GetInstance()->GetEntryLetters("navigation.more");
208         NavigationTitleUtil::SetAccessibility(menuItemNode, message);
209 
210         // set navigation titleBar "more" button inspectorId
211         NavigationTitleUtil::SetInnerChildId(menuItemNode, NG::NAV_FIELD, menuNode->GetTag(), "More", parentId);
212 
213         barItemNode->MountToParent(menuItemNode);
214         barItemNode->MarkModifyDone();
215         menuItemNode->MarkModifyDone();
216         menuNode->AddChild(menuItemNode);
217         isCreateLandscapeMenu ? navBarNode->SetLandscapeMenuNode(barMenuNode) : navBarNode->SetMenuNode(barMenuNode);
218     }
219 
220     NavigationTitleUtil::InitDragAndLongPressEvent(menuNode, menuItems);
221     return menuNode;
222 }
223 
BuildMenu(const RefPtr<NavBarNode> & navBarNode,const RefPtr<TitleBarNode> & titleBarNode)224 void BuildMenu(const RefPtr<NavBarNode>& navBarNode, const RefPtr<TitleBarNode>& titleBarNode)
225 {
226     if (navBarNode->GetMenuNodeOperationValue(ChildNodeOperation::NONE) == ChildNodeOperation::REPLACE) {
227         titleBarNode->RemoveChild(titleBarNode->GetMenu());
228         titleBarNode->MarkDirtyNode(PROPERTY_UPDATE_MEASURE);
229     }
230     if (navBarNode->GetPrevMenuIsCustomValue(false)) {
231         if (navBarNode->GetMenuNodeOperationValue(ChildNodeOperation::NONE) == ChildNodeOperation::NONE) {
232             return;
233         }
234         titleBarNode->SetMenu(navBarNode->GetMenu());
235         titleBarNode->AddChild(titleBarNode->GetMenu());
236         navBarNode->UpdateMenuNodeOperation(ChildNodeOperation::NONE);
237     } else {
238         navBarNode->UpdateMenuNodeOperation(ChildNodeOperation::NONE);
239         auto navBarPattern = navBarNode->GetPattern<NavBarPattern>();
240         CHECK_NULL_VOID(navBarPattern);
241         auto titleBarMenuItems = navBarPattern->GetTitleBarMenuItems();
242         auto toolBarMenuItems = navBarPattern->GetToolBarMenuItems();
243 
244         if (navBarPattern->HasMenuNodeId()) {
245             auto menuNode = CreateMenuItems(navBarPattern->GetMenuNodeId(), titleBarMenuItems, navBarNode, false);
246             CHECK_NULL_VOID(menuNode);
247             navBarNode->SetMenu(menuNode);
248         }
249 
250         titleBarMenuItems.insert(titleBarMenuItems.end(), toolBarMenuItems.begin(), toolBarMenuItems.end());
251         auto landscapeMenuNode =
252             CreateMenuItems(navBarPattern->GetLandscapeMenuNodeId(), titleBarMenuItems, navBarNode, true);
253         CHECK_NULL_VOID(landscapeMenuNode);
254         navBarNode->SetLandscapeMenu(landscapeMenuNode);
255     }
256 }
257 
BuildTitleBar(const RefPtr<NavBarNode> & navBarNode,const RefPtr<TitleBarNode> & titleBarNode)258 void BuildTitleBar(const RefPtr<NavBarNode>& navBarNode, const RefPtr<TitleBarNode>& titleBarNode)
259 {
260     auto titleBarLayoutProperty = titleBarNode->GetLayoutProperty<TitleBarLayoutProperty>();
261     CHECK_NULL_VOID(titleBarLayoutProperty);
262 
263     // Update back button visibility
264     auto backButtonNode = AceType::DynamicCast<FrameNode>(titleBarNode->GetBackButton());
265     if (backButtonNode) {
266         auto backButtonLayoutProperty = backButtonNode->GetLayoutProperty();
267         CHECK_NULL_VOID(backButtonLayoutProperty);
268         backButtonLayoutProperty->UpdateVisibility(
269             titleBarLayoutProperty->GetHideBackButtonValue(false) ? VisibleType::GONE : VisibleType::VISIBLE);
270     }
271 
272     // update main title
273     auto mainTitleNode = AceType::DynamicCast<FrameNode>(titleBarNode->GetTitle());
274     if (mainTitleNode && !navBarNode->GetPrevTitleIsCustomValue(false)) {
275         auto textLayoutProperty = mainTitleNode->GetLayoutProperty<TextLayoutProperty>();
276         auto theme = NavigationGetTheme();
277         CHECK_NULL_VOID(theme);
278         if (titleBarLayoutProperty->GetTitleModeValue(NavigationTitleMode::FREE) == NavigationTitleMode::MINI) {
279             textLayoutProperty->UpdateFontSize(theme->GetTitleFontSize());
280         } else {
281             textLayoutProperty->UpdateFontSize(theme->GetTitleFontSizeBig());
282         }
283         mainTitleNode->MarkModifyDone();
284     }
285 
286     // update menu
287     BuildMenu(navBarNode, titleBarNode);
288 }
289 } // namespace
290 
MountTitleBar(const RefPtr<FrameNode> & host,bool & needRunTitleBarAnimation)291 void NavBarPattern::MountTitleBar(
292     const RefPtr<FrameNode>& host, bool& needRunTitleBarAnimation)
293 {
294     needRunTitleBarAnimation = false;
295     auto hostNode = AceType::DynamicCast<NavBarNode>(host);
296     CHECK_NULL_VOID(hostNode);
297     auto navBarLayoutProperty = hostNode->GetLayoutProperty<NavBarLayoutProperty>();
298     CHECK_NULL_VOID(navBarLayoutProperty);
299     auto titleBarNode = AceType::DynamicCast<TitleBarNode>(hostNode->GetTitleBarNode());
300     CHECK_NULL_VOID(titleBarNode);
301     auto titleBarLayoutProperty = titleBarNode->GetLayoutProperty<TitleBarLayoutProperty>();
302     CHECK_NULL_VOID(titleBarLayoutProperty);
303     auto navBarPattern = AceType::DynamicCast<NavBarPattern>(hostNode->GetPattern());
304     auto hasCustomMenu = hostNode->GetPrevMenuIsCustomValue(false) && hostNode->GetMenu();
305     // menu is not consume menu, menu item and tool bar menus need all empty
306     auto hideMenu = !hostNode->GetPrevMenuIsCustomValue(false) && navBarPattern->GetTitleBarMenuItems().empty() &&
307                     navBarPattern->GetToolBarMenuItems().empty();
308     if (!titleBarNode->GetTitle() && !titleBarNode->GetSubtitle() && !titleBarNode->GetBackButton() && !hasCustomMenu &&
309         hideMenu) {
310         titleBarLayoutProperty->UpdateVisibility(VisibleType::GONE);
311         return;
312     }
313     titleBarLayoutProperty->UpdateTitleMode(navBarLayoutProperty->GetTitleModeValue(NavigationTitleMode::FREE));
314     titleBarLayoutProperty->UpdateHideBackButton(navBarLayoutProperty->GetHideBackButtonValue(false));
315     BuildTitleBar(hostNode, titleBarNode);
316     bool hideTitleBar = navBarLayoutProperty->GetHideTitleBarValue(false);
317     // At the initial state, animation is not required.
318     if (!currHideTitleBar_.has_value() ||
319         !navBarLayoutProperty->GetIsAnimatedTitleBarValue(false)) {
320         currHideTitleBar_ = hideTitleBar;
321         HideOrShowTitleBarImmediately(hostNode, hideTitleBar);
322         return;
323     }
324     titleBarNode->MarkModifyDone();
325     titleBarNode->MarkDirtyNode();
326 
327     // Animation is needed only when the status changed.
328     needRunTitleBarAnimation = currHideTitleBar_.value() != hideTitleBar;
329     currHideTitleBar_ = hideTitleBar;
330 }
331 
GetShowMenuOffset(const RefPtr<BarItemNode> barItemNode,RefPtr<FrameNode> menuNode)332 OffsetF NavBarPattern::GetShowMenuOffset(const RefPtr<BarItemNode> barItemNode, RefPtr<FrameNode> menuNode)
333 {
334     auto imageNode = barItemNode->GetChildAtIndex(0);
335     CHECK_NULL_RETURN(imageNode, OffsetF(0.0f, 0.0f));
336 
337     auto imageFrameNode = AceType::DynamicCast<FrameNode>(imageNode);
338     CHECK_NULL_RETURN(imageFrameNode, OffsetF(0.0f, 0.0f));
339     auto imgOffset = imageFrameNode->GetOffsetRelativeToWindow();
340     auto imageSize = imageFrameNode->GetGeometryNode()->GetFrameSize();
341 
342     auto menuLayoutProperty = menuNode->GetLayoutProperty<MenuLayoutProperty>();
343     CHECK_NULL_RETURN(menuLayoutProperty, OffsetF(0.0f, 0.0f));
344     menuLayoutProperty->UpdateTargetSize(imageSize);
345 
346     bool isRightToLeft = AceApplicationInfo::GetInstance().IsRightToLeft();
347     if (isRightToLeft) {
348         imgOffset.SetX(imgOffset.GetX() + imageSize.Width());
349     } else {
350         imgOffset.SetX(imgOffset.GetX());
351     }
352     imgOffset.SetY(imgOffset.GetY() + imageSize.Height());
353     return imgOffset;
354 }
355 
OnAttachToFrameNode()356 void NavBarPattern::OnAttachToFrameNode()
357 {
358     auto host = GetHost();
359     CHECK_NULL_VOID(host);
360     auto pipelineContext = PipelineContext::GetCurrentContext();
361     CHECK_NULL_VOID(pipelineContext);
362     pipelineContext->AddWindowSizeChangeCallback(host->GetId());
363 
364     auto theme = NavigationGetTheme();
365     CHECK_NULL_VOID(theme);
366     if (theme && theme->GetNavBarUnfocusEffectEnable()) {
367         pipelineContext->AddWindowFocusChangedCallback(host->GetId());
368     }
369     if (Container::GreatOrEqualAPIVersion(PlatformVersion::VERSION_ELEVEN)) {
370         SafeAreaExpandOpts opts = { .type = SAFE_AREA_TYPE_SYSTEM | SAFE_AREA_TYPE_CUTOUT,
371             .edges = SAFE_AREA_EDGE_ALL };
372         host->GetLayoutProperty()->UpdateSafeAreaExpandOpts(opts);
373     }
374 }
375 
OnCoordScrollStart()376 void NavBarPattern::OnCoordScrollStart()
377 {
378     if (isHideTitlebar_ || titleMode_ != NavigationTitleMode::FREE) {
379         return;
380     }
381     auto hostNode = AceType::DynamicCast<NavBarNode>(GetHost());
382     CHECK_NULL_VOID(hostNode);
383     auto titleNode = AceType::DynamicCast<TitleBarNode>(hostNode->GetTitleBarNode());
384     CHECK_NULL_VOID(titleNode);
385     auto titlePattern = titleNode->GetPattern<TitleBarPattern>();
386     CHECK_NULL_VOID(titlePattern);
387     titlePattern->OnCoordScrollStart();
388 }
389 
OnCoordScrollUpdate(float offset)390 float NavBarPattern::OnCoordScrollUpdate(float offset)
391 {
392     if (isHideTitlebar_ || titleMode_ != NavigationTitleMode::FREE) {
393         return 0.0f;
394     }
395     auto hostNode = AceType::DynamicCast<NavBarNode>(GetHost());
396     CHECK_NULL_RETURN(hostNode, 0.0f);
397     auto titleNode = AceType::DynamicCast<TitleBarNode>(hostNode->GetTitleBarNode());
398     CHECK_NULL_RETURN(titleNode, 0.0f);
399     auto titlePattern = titleNode->GetPattern<TitleBarPattern>();
400     CHECK_NULL_RETURN(titlePattern, 0.0f);
401     return titlePattern->OnCoordScrollUpdate(offset);
402 }
403 
OnCoordScrollEnd()404 void NavBarPattern::OnCoordScrollEnd()
405 {
406     TAG_LOGI(AceLogTag::ACE_NAVIGATION, "OnCoordScroll end");
407     if (titleMode_ != NavigationTitleMode::FREE) {
408         TAG_LOGI(AceLogTag::ACE_NAVIGATION, "titleMode_ is not free");
409         return;
410     }
411     auto hostNode = AceType::DynamicCast<NavBarNode>(GetHost());
412     CHECK_NULL_VOID(hostNode);
413     auto titleNode = AceType::DynamicCast<TitleBarNode>(hostNode->GetTitleBarNode());
414     CHECK_NULL_VOID(titleNode);
415     auto titlePattern = titleNode->GetPattern<TitleBarPattern>();
416     titlePattern->OnCoordScrollEnd();
417 }
418 
OnModifyDone()419 void NavBarPattern::OnModifyDone()
420 {
421     Pattern::OnModifyDone();
422     auto hostNode = AceType::DynamicCast<NavBarNode>(GetHost());
423     CHECK_NULL_VOID(hostNode);
424     auto titleBarNode = AceType::DynamicCast<TitleBarNode>(hostNode->GetTitleBarNode());
425     CHECK_NULL_VOID(titleBarNode);
426     auto titleBarRenderContext = titleBarNode->GetRenderContext();
427     CHECK_NULL_VOID(titleBarRenderContext);
428     // set the titlebar to float on the top
429     titleBarRenderContext->UpdateZIndex(DEFAULT_TITLEBAR_ZINDEX);
430     bool needRunTitleBarAnimation = false;
431     MountTitleBar(hostNode, needRunTitleBarAnimation);
432     bool needRunToolBarAnimation = false;
433     NavigationToolbarUtil::MountToolBar(hostNode, needRunToolBarAnimation);
434     HandleTitleBarAndToolBarAnimation(
435         hostNode, needRunTitleBarAnimation, needRunToolBarAnimation);
436     UpdateHideBarProperty();
437     ExpandContentSafeAreaIfNeeded();
438     auto navBarLayoutProperty = hostNode->GetLayoutProperty<NavBarLayoutProperty>();
439     CHECK_NULL_VOID(navBarLayoutProperty);
440     titleMode_ = navBarLayoutProperty->GetTitleModeValue(NavigationTitleMode::FREE);
441 
442     auto parent = hostNode->GetParent();
443     CHECK_NULL_VOID(parent);
444     titleBarNode->SetInnerParentId(parent->GetInspectorId().value_or(""));
445 }
446 
OnWindowSizeChanged(int32_t width,int32_t height,WindowSizeChangeReason type)447 void NavBarPattern::OnWindowSizeChanged(int32_t width, int32_t height, WindowSizeChangeReason type)
448 {
449     auto navBarNode = AceType::DynamicCast<NavBarNode>(GetHost());
450     CHECK_NULL_VOID(navBarNode);
451     if (preWidth_.has_value() && preWidth_.value() != width) {
452         AbortBarAnimation();
453     }
454     preWidth_ = width;
455     // change menu num in landscape and orientation
456     do {
457         if (navBarNode->GetPrevMenuIsCustomValue(false)) {
458             break;
459         }
460         auto targetNum = SystemProperties::GetDeviceOrientation() == DeviceOrientation::LANDSCAPE ? MAX_MENU_NUM_LARGE
461                                                                                                   : MAX_MENU_NUM_SMALL;
462         if (targetNum == maxMenuNums_) {
463             break;
464         }
465         maxMenuNums_ = targetNum;
466         auto titleBarNode = AceType::DynamicCast<TitleBarNode>(navBarNode->GetTitleBarNode());
467         CHECK_NULL_VOID(titleBarNode);
468         BuildMenu(navBarNode, titleBarNode);
469         titleBarNode->MarkDirtyNode(PROPERTY_UPDATE_MEASURE_SELF_AND_CHILD);
470     } while (0);
471 }
472 
OnDetachFromFrameNode(FrameNode * frameNode)473 void NavBarPattern::OnDetachFromFrameNode(FrameNode* frameNode)
474 {
475     CHECK_NULL_VOID(frameNode);
476     auto pipeline = PipelineContext::GetCurrentContext();
477     CHECK_NULL_VOID(pipeline);
478     pipeline->RemoveWindowSizeChangeCallback(frameNode->GetId());
479 }
480 
WindowFocus(bool isFocus)481 void NavBarPattern::WindowFocus(bool isFocus)
482 {
483     isWindowFocus_ = isFocus;
484     SetNavBarMask(isFocus);
485 }
486 
OnColorConfigurationUpdate()487 void NavBarPattern::OnColorConfigurationUpdate()
488 {
489     SetNavBarMask(isWindowFocus_);
490 }
491 
SetNavBarMask(bool isWindowFocus)492 void NavBarPattern::SetNavBarMask(bool isWindowFocus)
493 {
494     auto theme = NavigationGetTheme();
495     CHECK_NULL_VOID(theme);
496     auto navBarNode = GetHost();
497     CHECK_NULL_VOID(navBarNode);
498     auto parent = navBarNode->GetParent();
499     CHECK_NULL_VOID(parent);
500     auto navigationGroupNode = AceType::DynamicCast<NavigationGroupNode>(parent);
501     CHECK_NULL_VOID(navigationGroupNode);
502     auto pattern = navigationGroupNode->GetPattern();
503     CHECK_NULL_VOID(pattern);
504     auto navigationPattern = AceType::DynamicCast<NavigationPattern>(pattern);
505     if (navigationPattern && navigationPattern->GetNavigationMode() == NavigationMode::SPLIT) {
506         auto renderContext = navBarNode->GetRenderContext();
507         CHECK_NULL_VOID(renderContext);
508         Color maskColor = theme->GetNavBarUnfocusColor().BlendOpacity(DEFAULT_NAV_BAR_MASK_OPACITY);
509         auto maskProperty = AceType::MakeRefPtr<ProgressMaskProperty>();
510         maskProperty->SetColor(isWindowFocus ? Color::TRANSPARENT : maskColor);
511         renderContext->UpdateProgressMask(maskProperty);
512     }
513 }
514 
CanCoordScrollUp(float offset) const515 bool NavBarPattern::CanCoordScrollUp(float offset) const
516 {
517     auto hostNode = AceType::DynamicCast<NavBarNode>(GetHost());
518     CHECK_NULL_RETURN(hostNode, false);
519     auto titleNode = AceType::DynamicCast<TitleBarNode>(hostNode->GetTitleBarNode());
520     CHECK_NULL_RETURN(titleNode, false);
521     auto titlePattern = titleNode->GetPattern<TitleBarPattern>();
522     CHECK_NULL_RETURN(titlePattern, false);
523     return Negative(offset) && !titlePattern->IsCurrentMinTitle();
524 }
525 
GetTitleBarHeightLessThanMaxBarHeight() const526 float NavBarPattern::GetTitleBarHeightLessThanMaxBarHeight() const
527 {
528     auto hostNode = AceType::DynamicCast<NavBarNode>(GetHost());
529     CHECK_NULL_RETURN(hostNode, 0.f);
530     auto titleBarNode = AceType::DynamicCast<TitleBarNode>(hostNode->GetTitleBarNode());
531     CHECK_NULL_RETURN(titleBarNode, 0.f);
532     auto titlePattern = titleBarNode->GetPattern<TitleBarPattern>();
533     CHECK_NULL_RETURN(titlePattern, 0.f);
534     return titlePattern->GetTitleBarHeightLessThanMaxBarHeight();
535 }
536 } // namespace OHOS::Ace::NG
537