• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2024 Huawei Device Co., Ltd.
3  * Licensed under the Apache License, Version 2.0 (the "License");
4  * you may not use this file except in compliance with the License.
5  * You may obtain a copy of the License at
6  *
7  *     http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software
10  * distributed under the License is distributed on an "AS IS" BASIS,
11  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12  * See the License for the specific language governing permissions and
13  * limitations under the License.
14  */
15 
16 #include "core/components_ng/pattern/navigation/navigation_title_util.h"
17 
18 #include <algorithm>
19 
20 #include "base/i18n/localization.h"
21 #include "core/common/ace_application_info.h"
22 #include "core/common/agingadapation/aging_adapation_dialog_theme.h"
23 #include "core/common/agingadapation/aging_adapation_dialog_util.h"
24 #include "core/common/container.h"
25 #include "core/components_ng/base/view_abstract.h"
26 #include "core/components_ng/pattern/bubble/bubble_pattern.h"
27 #include "core/components_ng/pattern/button/button_layout_property.h"
28 #include "core/components_ng/pattern/button/button_pattern.h"
29 #include "core/components_ng/pattern/grid/grid_pattern.h"
30 #include "core/components_ng/pattern/image/image_layout_property.h"
31 #include "core/components_ng/pattern/image/image_pattern.h"
32 #include "core/components_ng/pattern/menu/menu_view.h"
33 #include "core/components_ng/pattern/menu/wrapper/menu_wrapper_pattern.h"
34 #include "core/components_ng/pattern/navigation/bar_item_event_hub.h"
35 #include "core/components_ng/pattern/navigation/bar_item_pattern.h"
36 #include "core/components_ng/pattern/navigation/nav_bar_pattern.h"
37 #include "core/components_ng/pattern/navigation/navdestination_node_base.h"
38 #include "core/components_ng/pattern/navigation/navdestination_pattern_base.h"
39 #include "core/components_ng/pattern/navigation/navigation_pattern.h"
40 #include "core/components_ng/pattern/navigation/title_bar_node.h"
41 #include "core/components_ng/pattern/navigation/title_bar_pattern.h"
42 #include "core/components_ng/pattern/navigation/tool_bar_node.h"
43 #include "core/components_ng/pattern/text/text_pattern.h"
44 
45 namespace OHOS::Ace::NG {
46 namespace {
47 constexpr Dimension TITLEBAR_VERTICAL_PADDING = 56.0_vp;
48 constexpr int32_t TITLEBAR_OPACITY_ANIMATION_DURATION = 120;
49 const RefPtr<CubicCurve> TITLEBAR_OPACITY_ANIMATION_CURVE = AceType::MakeRefPtr<CubicCurve>(0.4, 0.0, 0.4, 1.0);
50 }
BuildMoreButton(bool isButtonEnabled,const RefPtr<NavigationBarTheme> & theme,const RefPtr<NavDestinationNodeBase> & nodeBase,const RefPtr<FrameNode> & menuNode,std::vector<OptionParam> && params,const std::string & field,const std::string & parentId,bool isCreateLandscapeMenu)51 bool NavigationTitleUtil::BuildMoreButton(bool isButtonEnabled, const RefPtr<NavigationBarTheme>& theme,
52     const RefPtr<NavDestinationNodeBase>& nodeBase, const RefPtr<FrameNode>& menuNode,
53     std::vector<OptionParam>&& params, const std::string& field, const std::string& parentId,
54     bool isCreateLandscapeMenu)
55 {
56     auto barItemNode = CreateBarItemNode(isButtonEnabled);
57     CHECK_NULL_RETURN(barItemNode, false);
58     auto menuItemNode = CreateMenuItemButton(theme);
59     CHECK_NULL_RETURN(menuItemNode, false);
60     MenuParam menuParam;
61     menuParam.isShowInSubWindow = false;
62     menuParam.placement = Placement::BOTTOM_RIGHT;
63     auto barMenuNode = MenuView::Create(
64         std::move(params), menuItemNode->GetId(), menuItemNode->GetTag(), MenuType::NAVIGATION_MENU, menuParam);
65     BuildMoreItemNodeAction(menuItemNode, barItemNode, barMenuNode);
66     auto iconNode = AceType::DynamicCast<FrameNode>(barItemNode->GetChildren().front());
67     InitTitleBarButtonEvent(menuItemNode, iconNode, true);
68 
69     // read navdestination "more" button
70     std::string message = Localization::GetInstance()->GetEntryLetters("navigation.more");
71     SetAccessibility(menuItemNode, message);
72 
73     // set navdestination titleBar "more" button inspectorId
74     SetInnerChildId(menuItemNode, field, menuNode->GetTag(), "More", parentId);
75 
76     barItemNode->MountToParent(menuItemNode);
77     barItemNode->MarkModifyDone();
78     menuItemNode->MarkModifyDone();
79     CHECK_NULL_RETURN(menuNode, false);
80     menuNode->AddChild(menuItemNode);
81     CHECK_NULL_RETURN(nodeBase, false);
82     if (isCreateLandscapeMenu) {
83         nodeBase->SetLandscapeMenuNode(barMenuNode);
84     } else {
85         nodeBase->SetMenuNode(barMenuNode);
86     }
87     return true;
88 }
89 
CreateMenuItems(const int32_t menuNodeId,const std::vector<NG::BarItem> & menuItems,const RefPtr<NavDestinationNodeBase> & navDestinationNodeBase,bool isButtonEnabled,const std::string & field,const std::string & parentId,bool isCreateLandscapeMenu)90 RefPtr<FrameNode> NavigationTitleUtil::CreateMenuItems(const int32_t menuNodeId,
91     const std::vector<NG::BarItem>& menuItems, const RefPtr<NavDestinationNodeBase>& navDestinationNodeBase,
92     bool isButtonEnabled, const std::string& field, const std::string& parentId, bool isCreateLandscapeMenu)
93 {
94     auto menuNode = FrameNode::GetOrCreateFrameNode(
95         V2::NAVIGATION_MENU_ETS_TAG, menuNodeId, []() { return AceType::MakeRefPtr<LinearLayoutPattern>(false); });
96     CHECK_NULL_RETURN(menuNode, nullptr);
97     menuNode->Clean();
98     menuNode->MarkDirtyNode(PROPERTY_UPDATE_MEASURE);
99     auto rowProperty = menuNode->GetLayoutProperty<LinearLayoutProperty>();
100     CHECK_NULL_RETURN(rowProperty, nullptr);
101     rowProperty->UpdateMainAxisAlign(FlexAlign::SPACE_BETWEEN);
102     auto theme = NavigationGetTheme();
103     CHECK_NULL_RETURN(theme, nullptr);
104     auto mostMenuItemCount = GetOrInitMaxMenuNums(theme, navDestinationNodeBase);
105     bool needMoreButton = menuItems.size() > mostMenuItemCount ? true : false;
106 
107     int32_t count = 0;
108     std::vector<OptionParam> params;
109     OptionParam param;
110     for (const auto& menuItem : menuItems) {
111         ++count;
112         if (needMoreButton && (count > static_cast<int32_t>(mostMenuItemCount) - 1)) {
113             param = { menuItem.text.value_or(""), menuItem.icon.value_or(""), menuItem.isEnabled.value_or(true),
114                 menuItem.action, menuItem.iconSymbol.value_or(nullptr) };
115             param.SetSymbolUserDefinedIdealFontSize(theme->GetMenuIconSize());
116             params.push_back(param);
117         } else {
118             auto menuItemNode = CreateMenuItemNode(theme, menuItem, isButtonEnabled);
119             CHECK_NULL_RETURN(menuItemNode, nullptr);
120 
121             // set titleBar menuitem inspectorId
122             std::string menuItemId = menuItemNode->GetTag() + std::to_string(count);
123             NavigationTitleUtil::SetInnerChildId(menuItemNode, field, menuNode->GetTag(), menuItemId, parentId);
124 
125             // read menu button
126             SetAccessibility(menuItemNode, menuItem.text.value_or(""));
127             menuNode->AddChild(menuItemNode);
128         }
129     }
130 
131     // build more button
132     if (needMoreButton) {
133         bool buildMoreButtonResult = BuildMoreButton(isButtonEnabled, theme, navDestinationNodeBase,
134             menuNode, std::move(params), field, parentId, isCreateLandscapeMenu);
135         if (!buildMoreButtonResult) {
136             TAG_LOGI(AceLogTag::ACE_NAVIGATION, "build more button node failed");
137             return nullptr;
138         }
139     }
140     InitDragAndLongPressEvent(menuNode, menuItems);
141     return menuNode;
142 }
143 
GetOrInitMaxMenuNums(const RefPtr<NavigationBarTheme> & theme,const RefPtr<NavDestinationNodeBase> & navDestinationNodeBase)144 uint32_t NavigationTitleUtil::GetOrInitMaxMenuNums(
145     const RefPtr<NavigationBarTheme>& theme, const RefPtr<NavDestinationNodeBase>& navDestinationNodeBase)
146 {
147     auto patternBase = navDestinationNodeBase->GetPattern<NavDestinationPatternBase>();
148     CHECK_NULL_RETURN(patternBase, 0);
149     auto navDesMaxNum = patternBase->GetMaxMenuNum();
150     auto mostMenuItemCount =
151         navDesMaxNum < 0 ? theme->GetMostMenuItemCountInBar() : static_cast<uint32_t>(navDesMaxNum);
152     mostMenuItemCount = SystemProperties::GetDeviceOrientation() == DeviceOrientation::LANDSCAPE ? MAX_MENU_NUM_LARGE
153                                                                                                  : mostMenuItemCount;
154     patternBase->SetMaxMenuNum(mostMenuItemCount);
155     return mostMenuItemCount;
156 }
157 
BuildMoreItemNodeAction(const RefPtr<FrameNode> & buttonNode,const RefPtr<BarItemNode> & barItemNode,const RefPtr<FrameNode> & barMenuNode)158 void NavigationTitleUtil::BuildMoreItemNodeAction(const RefPtr<FrameNode>& buttonNode,
159     const RefPtr<BarItemNode>& barItemNode, const RefPtr<FrameNode>& barMenuNode)
160 {
161     auto eventHub = barItemNode->GetEventHub<BarItemEventHub>();
162     CHECK_NULL_VOID(eventHub);
163 
164     auto context = PipelineContext::GetCurrentContext();
165     auto clickCallback = [weakContext = WeakPtr<PipelineContext>(context), id = barItemNode->GetId(),
166                              weakMenu = WeakPtr<FrameNode>(barMenuNode)]() {
167         auto context = weakContext.Upgrade();
168         CHECK_NULL_VOID(context);
169 
170         auto overlayManager = context->GetOverlayManager();
171         CHECK_NULL_VOID(overlayManager);
172 
173         auto menu = weakMenu.Upgrade();
174         CHECK_NULL_VOID(menu);
175         overlayManager->ShowMenu(id, OffsetF(0.0f, 0.0f), menu);
176     };
177     eventHub->SetItemAction(clickCallback);
178 
179     auto gestureEventHub = buttonNode->GetOrCreateGestureEventHub();
180     CHECK_NULL_VOID(gestureEventHub);
181     auto callback = [action = clickCallback](GestureEvent& info) {
182         if (info.GetSourceDevice() == SourceType::KEYBOARD) {
183             return;
184         }
185         action();
186     };
187     gestureEventHub->AddClickEvent(AceType::MakeRefPtr<ClickEvent>(callback));
188 }
189 
CreateMenuItemNode(const RefPtr<NavigationBarTheme> & theme,const BarItem & menuItem,bool isButtonEnabled)190 RefPtr<FrameNode> NavigationTitleUtil::CreateMenuItemNode(
191     const RefPtr<NavigationBarTheme>& theme, const BarItem& menuItem, bool isButtonEnabled)
192 {
193     auto menuItemNode = CreateMenuItemButton(theme);
194     CHECK_NULL_RETURN(menuItemNode, nullptr);
195 
196     int32_t barItemNodeId = ElementRegister::GetInstance()->MakeUniqueId();
197     auto barItemNode = BarItemNode::GetOrCreateBarItemNode(
198         V2::BAR_ITEM_ETS_TAG, barItemNodeId, []() { return AceType::MakeRefPtr<BarItemPattern>(); });
199     UpdateBarItemNodeWithItem(barItemNode, menuItem, isButtonEnabled);
200     auto iconNode = AceType::DynamicCast<FrameNode>(barItemNode->GetChildren().front());
201     InitTitleBarButtonEvent(menuItemNode, iconNode, false, menuItem, menuItem.isEnabled.value_or(true));
202     auto barItemLayoutProperty = barItemNode->GetLayoutProperty();
203     CHECK_NULL_RETURN(barItemLayoutProperty, nullptr);
204     barItemLayoutProperty->UpdateMeasureType(MeasureType::MATCH_PARENT);
205 
206     barItemNode->MountToParent(menuItemNode);
207     barItemNode->MarkModifyDone();
208     menuItemNode->MarkModifyDone();
209     return menuItemNode;
210 }
211 
CreateMenuItemButton(const RefPtr<NavigationBarTheme> & theme)212 RefPtr<FrameNode> NavigationTitleUtil::CreateMenuItemButton(const RefPtr<NavigationBarTheme>& theme)
213 {
214     auto buttonPattern = AceType::MakeRefPtr<NG::ButtonPattern>();
215     CHECK_NULL_RETURN(buttonPattern, nullptr);
216     buttonPattern->setComponentButtonType(ComponentButtonType::NAVIGATION);
217     if (AceApplicationInfo::GetInstance().GreatOrEqualTargetAPIVersion(PlatformVersion::VERSION_TWELVE)) {
218         buttonPattern->SetBlendColor(theme->GetBackgroundPressedColor(), theme->GetBackgroundHoverColor());
219         buttonPattern->SetFocusBorderColor(theme->GetBackgroundFocusOutlineColor());
220         buttonPattern->SetFocusBorderWidth(theme->GetBackgroundFocusOutlineWeight());
221     } else {
222         buttonPattern->SetFocusBorderColor(theme->GetToolBarItemFocusColor());
223         buttonPattern->SetFocusBorderWidth(theme->GetToolBarItemFocusBorderWidth());
224     }
225     auto menuItemNode = FrameNode::CreateFrameNode(
226         V2::MENU_ITEM_ETS_TAG, ElementRegister::GetInstance()->MakeUniqueId(), buttonPattern);
227     CHECK_NULL_RETURN(menuItemNode, nullptr);
228     auto focusHub = menuItemNode->GetOrCreateFocusHub();
229     CHECK_NULL_RETURN(focusHub, nullptr);
230     focusHub->SetFocusDependence(FocusDependence::SELF);
231     auto menuItemLayoutProperty = menuItemNode->GetLayoutProperty<ButtonLayoutProperty>();
232     CHECK_NULL_RETURN(menuItemLayoutProperty, nullptr);
233     menuItemLayoutProperty->UpdateType(ButtonType::NORMAL);
234     auto renderContext = menuItemNode->GetRenderContext();
235     CHECK_NULL_RETURN(renderContext, nullptr);
236     if (AceApplicationInfo::GetInstance().GreatOrEqualTargetAPIVersion(PlatformVersion::VERSION_TWELVE)) {
237         auto iconBackgroundWidth = theme->GetIconBackgroundWidth();
238         auto iconBackgroundHeight = theme->GetIconBackgroundHeight();
239         menuItemLayoutProperty->UpdateUserDefinedIdealSize(
240             CalcSize(CalcLength(iconBackgroundWidth), CalcLength(iconBackgroundHeight)));
241         menuItemLayoutProperty->UpdateBorderRadius(BorderRadiusProperty(theme->GetCornerRadius()));
242         renderContext->UpdateBackgroundColor(theme->GetCompBackgroundColor());
243         PaddingProperty padding;
244         padding.SetEdges(CalcLength(MENU_BUTTON_PADDING));
245         menuItemLayoutProperty->UpdatePadding(padding);
246         MarginProperty margin;
247         margin.right = CalcLength(theme->GetCompPadding());
248         margin.end = CalcLength(theme->GetCompPadding());
249         menuItemLayoutProperty->UpdateMargin(margin);
250     } else {
251         menuItemLayoutProperty->UpdateUserDefinedIdealSize(
252             CalcSize(CalcLength(BACK_BUTTON_SIZE), CalcLength(BACK_BUTTON_SIZE)));
253         menuItemLayoutProperty->UpdateBorderRadius(BorderRadiusProperty(BUTTON_RADIUS_SIZE));
254         renderContext->UpdateBackgroundColor(Color::TRANSPARENT);
255         PaddingProperty padding;
256         padding.SetEdges(CalcLength(BUTTON_PADDING));
257         menuItemLayoutProperty->UpdatePadding(padding);
258     }
259     return menuItemNode;
260 }
261 
CreateBarItemTextNode(const std::string & text)262 RefPtr<FrameNode> NavigationTitleUtil::CreateBarItemTextNode(const std::string& text)
263 {
264     int32_t nodeId = ElementRegister::GetInstance()->MakeUniqueId();
265     auto textNode = FrameNode::CreateFrameNode(V2::TEXT_ETS_TAG, nodeId, AceType::MakeRefPtr<TextPattern>());
266     auto textLayoutProperty = textNode->GetLayoutProperty<TextLayoutProperty>();
267     CHECK_NULL_RETURN(textLayoutProperty, nullptr);
268     textLayoutProperty->UpdateContent(text);
269     textLayoutProperty->UpdateFontSize(TEXT_FONT_SIZE);
270     textLayoutProperty->UpdateTextColor(TEXT_COLOR);
271     textLayoutProperty->UpdateTextAlign(TextAlign::CENTER);
272     return textNode;
273 }
274 
UpdateSymbolEffect(RefPtr<TextLayoutProperty> symbolProperty,bool isActive)275 void UpdateSymbolEffect(RefPtr<TextLayoutProperty> symbolProperty, bool isActive)
276 {
277     CHECK_NULL_VOID(symbolProperty);
278     auto symbolEffectOptions = SymbolEffectOptions(SymbolEffectType::BOUNCE);
279     symbolEffectOptions.SetIsTxtActive(isActive);
280     symbolEffectOptions.SetIsTxtActiveSource(0);
281     symbolProperty->UpdateSymbolEffectOptions(symbolEffectOptions);
282 }
283 
CreateBarItemIconNode(const BarItem & barItem,const bool isButtonEnabled)284 RefPtr<FrameNode> NavigationTitleUtil::CreateBarItemIconNode(const BarItem& barItem, const bool isButtonEnabled)
285 {
286     auto theme = NavigationGetTheme();
287     CHECK_NULL_RETURN(theme, nullptr);
288 
289     Color iconColor = theme->GetMenuIconColor();
290     double iconOpacity = theme->GetAlphaDisabled();
291     auto iconWidth = theme->GetMenuIconSize();
292     auto iconHeight = theme->GetMenuIconSize();
293     if (AceApplicationInfo::GetInstance().GreatOrEqualTargetAPIVersion(PlatformVersion::VERSION_TWELVE)) {
294         iconColor = theme->GetIconColor();
295         iconOpacity = theme->GetIconDisableAlpha();
296         iconWidth = theme->GetIconWidth();
297         iconHeight = theme->GetIconHeight();
298     }
299 
300     if (barItem.iconSymbol.has_value() && barItem.iconSymbol.value() != nullptr) {
301         auto iconNode = FrameNode::GetOrCreateFrameNode(V2::SYMBOL_ETS_TAG,
302             ElementRegister::GetInstance()->MakeUniqueId(), []() { return AceType::MakeRefPtr<TextPattern>(); });
303         CHECK_NULL_RETURN(iconNode, nullptr);
304         auto symbolProperty = iconNode->GetLayoutProperty<TextLayoutProperty>();
305         CHECK_NULL_RETURN(symbolProperty, nullptr);
306         if (isButtonEnabled) {
307             symbolProperty->UpdateSymbolColorList({ iconColor });
308         } else {
309             symbolProperty->UpdateSymbolColorList({ iconColor.BlendOpacity(iconOpacity) });
310         }
311         barItem.iconSymbol.value()(AccessibilityManager::WeakClaim(AccessibilityManager::RawPtr(iconNode)));
312         UpdateSymbolEffect(symbolProperty, false);
313         symbolProperty->UpdateFontSize(iconWidth);
314         iconNode->MarkModifyDone();
315         return iconNode;
316     }
317     int32_t nodeId = ElementRegister::GetInstance()->MakeUniqueId();
318     ImageSourceInfo info(barItem.icon.value());
319     auto iconNode = FrameNode::CreateFrameNode(V2::IMAGE_ETS_TAG, nodeId, AceType::MakeRefPtr<ImagePattern>());
320     auto imageLayoutProperty = iconNode->GetLayoutProperty<ImageLayoutProperty>();
321     CHECK_NULL_RETURN(imageLayoutProperty, nullptr);
322     if (isButtonEnabled) {
323         info.SetFillColor(iconColor);
324     } else {
325         info.SetFillColor(iconColor.BlendOpacity(iconOpacity));
326     }
327     imageLayoutProperty->UpdateImageSourceInfo(info);
328     imageLayoutProperty->UpdateUserDefinedIdealSize(CalcSize(CalcLength(iconWidth), CalcLength(iconHeight)));
329     iconNode->MarkModifyDone();
330     return iconNode;
331 }
332 
InitTitleBarButtonEvent(const RefPtr<FrameNode> & buttonNode,const RefPtr<FrameNode> & iconNode,bool isMoreButton,const BarItem & menuItem,bool isButtonEnabled)333 void NavigationTitleUtil::InitTitleBarButtonEvent(const RefPtr<FrameNode>& buttonNode,
334     const RefPtr<FrameNode>& iconNode, bool isMoreButton, const BarItem& menuItem, bool isButtonEnabled)
335 {
336     auto eventHub = buttonNode->GetOrCreateInputEventHub();
337     CHECK_NULL_VOID(eventHub);
338 
339     if (isMoreButton) {
340         auto hoverTask = [weakTargetNode = WeakPtr<FrameNode>(buttonNode)](bool isHover) {
341             auto targetNode = weakTargetNode.Upgrade();
342             CHECK_NULL_VOID(targetNode);
343             auto popupParam = AceType::MakeRefPtr<PopupParam>();
344             popupParam->SetMessage(Localization::GetInstance()->GetEntryLetters("common.more"));
345             popupParam->SetIsShow(isHover);
346             popupParam->SetBlockEvent(false);
347             ViewAbstract::BindPopup(popupParam, targetNode, nullptr);
348         };
349         eventHub->AddOnHoverEvent(AceType::MakeRefPtr<InputEvent>(std::move(hoverTask)));
350         return;
351     }
352 
353     if (menuItem.action) {
354         auto gestureEventHub = buttonNode->GetOrCreateGestureEventHub();
355         CHECK_NULL_VOID(gestureEventHub);
356         auto clickCallback = [action = menuItem.action, weakNode = WeakPtr<FrameNode>(iconNode)](GestureEvent& info) {
357             if (info.GetSourceDevice() == SourceType::KEYBOARD) {
358                 return;
359             }
360             if (action) {
361                 action();
362             }
363             auto symbol = weakNode.Upgrade();
364             CHECK_NULL_VOID(symbol);
365             if (symbol->GetTag() == V2::SYMBOL_ETS_TAG) {
366                 auto symbolProperty = symbol->GetLayoutProperty<TextLayoutProperty>();
367                 CHECK_NULL_VOID(symbolProperty);
368                 auto symbolEffectOptions = symbolProperty->GetSymbolEffectOptionsValue(SymbolEffectOptions());
369                 symbolEffectOptions.SetEffectType(SymbolEffectType::BOUNCE);
370                 symbolEffectOptions.SetIsTxtActive(true);
371                 symbolEffectOptions.SetIsTxtActiveSource(0);
372                 symbolProperty->UpdateSymbolEffectOptions(symbolEffectOptions);
373                 symbol->MarkDirtyNode(PROPERTY_UPDATE_MEASURE_SELF);
374             }
375         };
376         gestureEventHub->AddClickEvent(AceType::MakeRefPtr<ClickEvent>(clickCallback));
377     }
378 
379     auto buttonEvent = buttonNode->GetEventHub<ButtonEventHub>();
380     CHECK_NULL_VOID(buttonEvent);
381     buttonEvent->SetEnabled(isButtonEnabled);
382     auto focusHub = buttonNode->GetFocusHub();
383     CHECK_NULL_VOID(focusHub);
384     focusHub->SetEnabled(isButtonEnabled);
385 }
386 
UpdateBarItemNodeWithItem(const RefPtr<BarItemNode> & barItemNode,const BarItem & barItem,const bool isButtonEnabled)387 void NavigationTitleUtil::UpdateBarItemNodeWithItem(
388     const RefPtr<BarItemNode>& barItemNode, const BarItem& barItem, const bool isButtonEnabled)
389 {
390     if (Container::LessThanAPIVersion(PlatformVersion::VERSION_TEN) && barItem.text.has_value() &&
391         !barItem.text.value().empty()) {
392         auto textNode = CreateBarItemTextNode(barItem.text.value());
393         barItemNode->SetTextNode(textNode);
394         barItemNode->AddChild(textNode);
395     }
396     if ((barItem.icon.has_value()) || (barItem.iconSymbol.has_value() && barItem.iconSymbol.value() != nullptr)) {
397         auto iconNode = CreateBarItemIconNode(barItem, isButtonEnabled);
398         barItemNode->SetIconNode(iconNode);
399         barItemNode->AddChild(iconNode);
400     }
401     if (barItem.action) {
402         auto eventHub = barItemNode->GetEventHub<BarItemEventHub>();
403         CHECK_NULL_VOID(eventHub);
404         eventHub->SetItemAction(barItem.action);
405     }
406     auto barItemPattern = barItemNode->GetPattern<BarItemPattern>();
407     barItemNode->MarkModifyDone();
408 }
409 
BuildImageMoreItemNode(const RefPtr<BarItemNode> & barItemNode,bool isButtonEnabled)410 void BuildImageMoreItemNode(const RefPtr<BarItemNode>& barItemNode, bool isButtonEnabled)
411 {
412     int32_t imageNodeId = ElementRegister::GetInstance()->MakeUniqueId();
413     auto imageNode = FrameNode::CreateFrameNode(V2::IMAGE_ETS_TAG, imageNodeId, AceType::MakeRefPtr<ImagePattern>());
414     auto imageLayoutProperty = imageNode->GetLayoutProperty<ImageLayoutProperty>();
415     CHECK_NULL_VOID(imageLayoutProperty);
416     auto theme = NavigationGetTheme();
417     CHECK_NULL_VOID(theme);
418 
419     auto info = ImageSourceInfo("");
420     info.SetResourceId(theme->GetMoreResourceId());
421     if (isButtonEnabled) {
422         info.SetFillColor(theme->GetMenuIconColor());
423     } else {
424         info.SetFillColor(theme->GetMenuIconColor().BlendOpacity(theme->GetAlphaDisabled()));
425     }
426 
427     imageLayoutProperty->UpdateImageSourceInfo(info);
428     auto iconSize = theme->GetMenuIconSize();
429     imageLayoutProperty->UpdateUserDefinedIdealSize(CalcSize(CalcLength(iconSize), CalcLength(iconSize)));
430     imageNode->MarkModifyDone();
431 
432     barItemNode->SetIsMoreItemNode(true);
433     barItemNode->SetIconNode(imageNode);
434     barItemNode->AddChild(imageNode);
435     barItemNode->MarkModifyDone();
436 }
437 
BuildSymbolMoreItemNode(const RefPtr<BarItemNode> & barItemNode,bool isButtonEnabled)438 void BuildSymbolMoreItemNode(const RefPtr<BarItemNode>& barItemNode, bool isButtonEnabled)
439 {
440     auto theme = NavigationGetTheme();
441     CHECK_NULL_VOID(theme);
442     auto iconSize = theme->GetMenuIconSize();
443     auto symbolNode = FrameNode::GetOrCreateFrameNode(V2::SYMBOL_ETS_TAG,
444         ElementRegister::GetInstance()->MakeUniqueId(), []() { return AceType::MakeRefPtr<TextPattern>(); });
445     CHECK_NULL_VOID(symbolNode);
446     auto symbolProperty = symbolNode->GetLayoutProperty<TextLayoutProperty>();
447     CHECK_NULL_VOID(symbolProperty);
448     symbolProperty->UpdateSymbolSourceInfo(SymbolSourceInfo(theme->GetMoreSymbolId()));
449     symbolProperty->UpdateFontSize(iconSize);
450     if (isButtonEnabled) {
451         symbolProperty->UpdateSymbolColorList({ theme->GetMenuIconColor() });
452     } else {
453         symbolProperty->UpdateSymbolColorList({ theme->GetMenuIconColor().BlendOpacity(theme->GetAlphaDisabled()) });
454     }
455     symbolNode->MarkModifyDone();
456     barItemNode->SetIsMoreItemNode(true);
457     barItemNode->SetIconNode(symbolNode);
458     barItemNode->AddChild(symbolNode);
459     barItemNode->MarkModifyDone();
460 }
461 
BuildMoreIemNode(const RefPtr<BarItemNode> & barItemNode,bool isButtonEnabled)462 void NavigationTitleUtil::BuildMoreIemNode(const RefPtr<BarItemNode>& barItemNode, bool isButtonEnabled)
463 {
464     if (AceApplicationInfo::GetInstance().GreatOrEqualTargetAPIVersion(PlatformVersion::VERSION_TWELVE) &&
465         SystemProperties::IsNeedSymbol()) {
466         BuildSymbolMoreItemNode(barItemNode, isButtonEnabled);
467     } else {
468         BuildImageMoreItemNode(barItemNode, isButtonEnabled);
469     }
470 }
471 
CreateBarItemNode(bool isButtonEnabled)472 RefPtr<BarItemNode> NavigationTitleUtil::CreateBarItemNode(bool isButtonEnabled)
473 {
474     int32_t barItemNodeId = ElementRegister::GetInstance()->MakeUniqueId();
475     auto barItemNode = BarItemNode::GetOrCreateBarItemNode(
476         V2::BAR_ITEM_ETS_TAG, barItemNodeId, []() { return AceType::MakeRefPtr<BarItemPattern>(); });
477     auto barItemLayoutProperty = barItemNode->GetLayoutProperty();
478     CHECK_NULL_RETURN(barItemLayoutProperty, nullptr);
479     barItemLayoutProperty->UpdateMeasureType(MeasureType::MATCH_PARENT);
480     BuildMoreIemNode(barItemNode, isButtonEnabled);
481     return barItemNode;
482 }
483 
HandleLongPress(const GestureEvent & info,const RefPtr<FrameNode> & menuNode,const std::vector<NG::BarItem> & menuItems)484 void NavigationTitleUtil::HandleLongPress(
485     const GestureEvent& info, const RefPtr<FrameNode>& menuNode, const std::vector<NG::BarItem>& menuItems)
486 {
487     CHECK_NULL_VOID(menuNode);
488     auto context = PipelineBase::GetCurrentContext();
489     CHECK_NULL_VOID(context);
490     auto dialogTheme = context->GetTheme<AgingAdapationDialogTheme>();
491     CHECK_NULL_VOID(dialogTheme);
492     float scale = context->GetFontScale();
493     if (LessNotEqual(scale, dialogTheme->GetBigFontSizeScale())) {
494         TAG_LOGI(AceLogTag::ACE_NAVIGATION,
495             "The current system font scale is %{public}f; dialogTheme font scale is %{public}f", scale,
496             dialogTheme->GetBigFontSizeScale());
497         return;
498     }
499     auto menuItemNode = menuNode->FindChildByPosition(info.GetGlobalLocation().GetX(), info.GetGlobalLocation().GetY());
500     CHECK_NULL_VOID(menuItemNode);
501     auto index = menuNode->GetChildIndex(menuItemNode);
502     auto dialogNode = CreatePopupDialogNode(menuItemNode, menuItems, index);
503     CHECK_NULL_VOID(dialogNode);
504     auto titleBarNode = menuNode->GetParentFrameNode();
505     CHECK_NULL_VOID(titleBarNode);
506     auto titleBarPattern = titleBarNode->GetPattern<TitleBarPattern>();
507     CHECK_NULL_VOID(titleBarPattern);
508     if (titleBarPattern->GetLargeFontPopUpDialogNode() != nullptr) {
509         HandleLongPressActionEnd(menuNode);
510     }
511     titleBarPattern->SetLargeFontPopUpDialogNode(dialogNode);
512 }
513 
HandleLongPressActionEnd(const RefPtr<FrameNode> & targetNode)514 void NavigationTitleUtil::HandleLongPressActionEnd(const RefPtr<FrameNode>& targetNode)
515 {
516     CHECK_NULL_VOID(targetNode);
517     auto titleBarNode = targetNode->GetParentFrameNode();
518     CHECK_NULL_VOID(titleBarNode);
519     auto titleBarPattern = titleBarNode->GetPattern<TitleBarPattern>();
520     CHECK_NULL_VOID(titleBarPattern);
521     auto dialogNode = titleBarPattern->GetLargeFontPopUpDialogNode();
522     CHECK_NULL_VOID(dialogNode);
523     auto pipeline = PipelineContext::GetCurrentContext();
524     CHECK_NULL_VOID(pipeline);
525     auto overlayManager = pipeline->GetOverlayManager();
526     CHECK_NULL_VOID(overlayManager);
527     overlayManager->CloseDialog(dialogNode);
528     titleBarPattern->SetLargeFontPopUpDialogNode(nullptr);
529 }
530 
InitDragAndLongPressEvent(const RefPtr<FrameNode> & menuNode,const std::vector<NG::BarItem> & menuItems)531 void NavigationTitleUtil::InitDragAndLongPressEvent(
532     const RefPtr<FrameNode>& menuNode, const std::vector<NG::BarItem>& menuItems)
533 {
534     CHECK_NULL_VOID(menuNode);
535     auto pipeline = menuNode->GetContext();
536     CHECK_NULL_VOID(pipeline);
537     if (LessNotEqual(pipeline->GetFontScale(), AgingAdapationDialogUtil::GetDialogBigFontSizeScale())) {
538         return;
539     }
540 
541     auto gestureHub = menuNode->GetOrCreateGestureEventHub();
542     CHECK_NULL_VOID(gestureHub);
543     InitDragEvent(gestureHub, menuNode, menuItems);
544     InitLongPressEvent(gestureHub, menuNode, menuItems);
545     auto accessibilityProperty = menuNode->GetAccessibilityProperty<NG::AccessibilityProperty>();
546     CHECK_NULL_VOID(accessibilityProperty);
547     accessibilityProperty->SetAccessibilityLevel(AccessibilityProperty::Level::NO_STR);
548 }
549 
CreatePopupDialogNode(const RefPtr<FrameNode> targetNode,const std::vector<NG::BarItem> & menuItems,int32_t index)550 RefPtr<FrameNode> NavigationTitleUtil::CreatePopupDialogNode(
551     const RefPtr<FrameNode> targetNode, const std::vector<NG::BarItem>& menuItems, int32_t index)
552 {
553     CHECK_NULL_RETURN(targetNode, nullptr);
554     RefPtr<BarItemNode> barItemNode = AceType::DynamicCast<BarItemNode>(targetNode->GetFirstChild());
555     CHECK_NULL_RETURN(barItemNode, nullptr);
556     auto accessibilityProperty = targetNode->GetAccessibilityProperty<AccessibilityProperty>();
557     CHECK_NULL_RETURN(accessibilityProperty, nullptr);
558     ImageSourceInfo imageSourceInfo;
559     std::string message;
560     RefPtr<FrameNode> dialogNode;
561     if (barItemNode->IsMoreItemNode()) {
562         auto theme = NavigationGetTheme();
563         CHECK_NULL_RETURN(theme, nullptr);
564         message = Localization::GetInstance()->GetEntryLetters("common.more");
565         if (message.empty()) {
566             message = accessibilityProperty->GetAccessibilityText();
567         }
568         if (AceApplicationInfo::GetInstance().GreatOrEqualTargetAPIVersion(PlatformVersion::VERSION_TWELVE)) {
569             auto symbolNode = AceType::DynamicCast<FrameNode>(barItemNode->GetFirstChild());
570             CHECK_NULL_RETURN(symbolNode, nullptr);
571             dialogNode = AgingAdapationDialogUtil::ShowLongPressDialog(message, symbolNode);
572             return dialogNode;
573         }
574         imageSourceInfo.SetResourceId(theme->GetMoreResourceId());
575         dialogNode = AgingAdapationDialogUtil::ShowLongPressDialog(message, imageSourceInfo);
576         return dialogNode;
577     }
578     if (index < 0 || index >= static_cast<int32_t>(menuItems.size())) {
579         return nullptr;
580     }
581     auto menuItem = menuItems.at(index);
582     if (menuItem.text.has_value() && !menuItem.text.value().empty()) {
583         message = menuItem.text.value();
584     } else {
585         message = accessibilityProperty->GetAccessibilityText();
586     }
587     if (menuItem.iconSymbol.has_value() && menuItem.iconSymbol.value() != nullptr) {
588         return CreateSymbolDialog(message, barItemNode);
589     }
590     if (menuItem.icon.has_value() && !menuItem.icon.value().empty()) {
591         imageSourceInfo = ImageSourceInfo(menuItem.icon.value());
592     }
593     dialogNode = AgingAdapationDialogUtil::ShowLongPressDialog(message, imageSourceInfo);
594     return dialogNode;
595 }
596 
CreateSymbolDialog(const std::string & message,const RefPtr<FrameNode> & targetNode)597 RefPtr<FrameNode> NavigationTitleUtil::CreateSymbolDialog(
598     const std::string& message, const RefPtr<FrameNode>& targetNode)
599 {
600     auto barItemNode = AceType::DynamicCast<BarItemNode>(targetNode);
601     CHECK_NULL_RETURN(barItemNode, nullptr);
602     auto iconNode = AceType::DynamicCast<FrameNode>(barItemNode->GetIconNode());
603     CHECK_NULL_RETURN(iconNode, nullptr);
604     return AgingAdapationDialogUtil::ShowLongPressDialog(message, iconNode);
605 }
606 
SetAccessibility(const RefPtr<FrameNode> & node,const std::string & message)607 void NavigationTitleUtil::SetAccessibility(const RefPtr<FrameNode>& node, const std::string& message)
608 {
609     CHECK_NULL_VOID(node);
610     auto accessibilityProperty = node->GetAccessibilityProperty<NG::AccessibilityProperty>();
611     CHECK_NULL_VOID(accessibilityProperty);
612     accessibilityProperty->SetAccessibilityText(message);
613     accessibilityProperty->SetAccessibilityGroup(true);
614 }
615 
GetTitleString(const RefPtr<TitleBarNode> & titleBarNode,bool isCustom)616 std::string NavigationTitleUtil::GetTitleString(const RefPtr<TitleBarNode>& titleBarNode, bool isCustom)
617 {
618     if (isCustom) {
619         return "";
620     }
621     CHECK_NULL_RETURN(titleBarNode, "");
622     auto title = AceType::DynamicCast<FrameNode>(titleBarNode->GetTitle());
623     CHECK_NULL_RETURN(title, "");
624     if (title->GetTag() != V2::TEXT_ETS_TAG) {
625         return "";
626     }
627     auto textLayoutProperty = title->GetLayoutProperty<TextLayoutProperty>();
628     CHECK_NULL_RETURN(textLayoutProperty, "");
629     return textLayoutProperty->GetContentValue("");
630 }
631 
GetSubtitleString(const RefPtr<TitleBarNode> & titleBarNode)632 std::string NavigationTitleUtil::GetSubtitleString(const RefPtr<TitleBarNode>& titleBarNode)
633 {
634     CHECK_NULL_RETURN(titleBarNode, "");
635     auto subtitle = AceType::DynamicCast<FrameNode>(titleBarNode->GetSubtitle());
636     CHECK_NULL_RETURN(subtitle, "");
637     if (subtitle->GetTag() != V2::TEXT_ETS_TAG) {
638         return "";
639     }
640     auto textLayoutProperty = subtitle->GetLayoutProperty<TextLayoutProperty>();
641     CHECK_NULL_RETURN(textLayoutProperty, "");
642     return textLayoutProperty->GetContentValue("");
643 }
644 
InitDragEvent(const RefPtr<GestureEventHub> & gestureHub,const RefPtr<FrameNode> & menuNode,const std::vector<NG::BarItem> & menuItems)645 void NavigationTitleUtil::InitDragEvent(const RefPtr<GestureEventHub>& gestureHub, const RefPtr<FrameNode>& menuNode,
646     const std::vector<NG::BarItem>& menuItems)
647 {
648     auto actionUpdateTask = [weakMenuNode = WeakPtr<FrameNode>(menuNode), menuItems](const GestureEvent& info) {
649         auto menuNode = weakMenuNode.Upgrade();
650         CHECK_NULL_VOID(menuNode);
651         auto menuItemNode =
652             menuNode->FindChildByPosition(info.GetGlobalLocation().GetX(), info.GetGlobalLocation().GetY());
653         CHECK_NULL_VOID(menuItemNode);
654         auto index = menuNode->GetChildIndex(menuItemNode);
655         auto totalCount = menuNode->TotalChildCount();
656         auto titleBarNode = menuNode->GetParentFrameNode();
657         CHECK_NULL_VOID(titleBarNode);
658         auto titleBarPattern = titleBarNode->GetPattern<TitleBarPattern>();
659         CHECK_NULL_VOID(titleBarPattern);
660         auto dialogNode = titleBarPattern->GetLargeFontPopUpDialogNode();
661         if (dialogNode && index >= 0 && index < totalCount) {
662             if (!titleBarPattern->GetMoveIndex().has_value()) {
663                 titleBarPattern->SetMoveIndex(index);
664             }
665 
666             if (titleBarPattern->GetMoveIndex().value() != index) {
667                 HandleLongPressActionEnd(menuNode);
668                 titleBarPattern->SetMoveIndex(index);
669                 titleBarPattern->SetLargeFontPopUpDialogNode(CreatePopupDialogNode(menuItemNode, menuItems, index));
670             }
671         }
672     };
673 
674     auto dragEvent = AceType::MakeRefPtr<DragEvent>(nullptr, std::move(actionUpdateTask), nullptr, nullptr);
675     PanDirection panDirection = { .type = PanDirection::ALL };
676     gestureHub->SetDragEvent(dragEvent, panDirection, DEFAULT_PAN_FINGER, DEFAULT_PAN_DISTANCE);
677 }
678 
InitLongPressEvent(const RefPtr<GestureEventHub> & gestureHub,const RefPtr<FrameNode> & menuNode,const std::vector<NG::BarItem> & menuItems)679 void NavigationTitleUtil::InitLongPressEvent(const RefPtr<GestureEventHub>& gestureHub,
680     const RefPtr<FrameNode>& menuNode, const std::vector<NG::BarItem>& menuItems)
681 {
682     auto longPressCallback = [weakTargetNode = WeakPtr<FrameNode>(menuNode), menuItems](GestureEvent& info) {
683         auto menuNode = weakTargetNode.Upgrade();
684         NavigationTitleUtil::HandleLongPress(info, menuNode, menuItems);
685     };
686     auto longPressEvent = AceType::MakeRefPtr<LongPressEvent>(std::move(longPressCallback));
687     gestureHub->SetLongPressEvent(longPressEvent);
688 
689     auto longPressRecognizer = gestureHub->GetLongPressRecognizer();
690     CHECK_NULL_VOID(longPressRecognizer);
691 
692     auto longPressEndCallback = [weakTargetNode = WeakPtr<FrameNode>(menuNode)](GestureEvent& info) {
693         auto menuNode = weakTargetNode.Upgrade();
694         NavigationTitleUtil::HandleLongPressActionEnd(menuNode);
695     };
696     longPressRecognizer->SetOnActionEnd(longPressEndCallback);
697 }
698 
CreateOrUpdateMainTitle(const RefPtr<TitleBarNode> & titleBarNode,const NG::NavigationTitleInfo & titleInfo,bool ignoreMainTitle)699 void NavigationTitleUtil::CreateOrUpdateMainTitle(const RefPtr<TitleBarNode>& titleBarNode,
700     const NG::NavigationTitleInfo& titleInfo, bool ignoreMainTitle)
701 {
702     CHECK_NULL_VOID(titleBarNode);
703     if (ignoreMainTitle) {
704         return;
705     }
706     auto mainTitle = AceType::DynamicCast<FrameNode>(titleBarNode->GetTitle());
707     if (!titleInfo.hasMainTitle) {
708         // remove main title if any.
709         titleBarNode->RemoveChild(mainTitle);
710         titleBarNode->SetTitle(nullptr);
711         return;
712     }
713 
714     if (mainTitle) {
715         // update main title
716         auto textLayoutProperty = mainTitle->GetLayoutProperty<TextLayoutProperty>();
717         CHECK_NULL_VOID(textLayoutProperty);
718         textLayoutProperty->UpdateMaxLines(titleInfo.hasSubTitle ? 1 : TITLEBAR_MAX_LINES);
719         textLayoutProperty->UpdateContent(titleInfo.title);
720         return;
721     }
722     // create and init main title
723     mainTitle = FrameNode::CreateFrameNode(
724         V2::TEXT_ETS_TAG, ElementRegister::GetInstance()->MakeUniqueId(), AceType::MakeRefPtr<TextPattern>());
725     auto textLayoutProperty = mainTitle->GetLayoutProperty<TextLayoutProperty>();
726     CHECK_NULL_VOID(textLayoutProperty);
727     textLayoutProperty->UpdateContent(titleInfo.title);
728     auto titleBarPattern = titleBarNode->GetPattern<TitleBarPattern>();
729     CHECK_NULL_VOID(titleBarPattern);
730     titleBarPattern->SetNeedResetMainTitleProperty(true);
731     titleBarNode->SetTitle(mainTitle);
732     titleBarNode->AddChild(mainTitle);
733 }
734 
CreateOrUpdateSubtitle(const RefPtr<TitleBarNode> & titleBarNode,const NG::NavigationTitleInfo & titleInfo)735 void NavigationTitleUtil::CreateOrUpdateSubtitle(const RefPtr<TitleBarNode>& titleBarNode,
736     const NG::NavigationTitleInfo& titleInfo)
737 {
738     CHECK_NULL_VOID(titleBarNode);
739     auto subTitle = AceType::DynamicCast<FrameNode>(titleBarNode->GetSubtitle());
740     if (!titleInfo.hasSubTitle) {
741         // remove subtitle if any.
742         titleBarNode->RemoveChild(subTitle);
743         titleBarNode->SetSubtitle(nullptr);
744         return;
745     }
746     if (subTitle) {
747         // update subtitle
748         auto textLayoutProperty = subTitle->GetLayoutProperty<TextLayoutProperty>();
749         CHECK_NULL_VOID(textLayoutProperty);
750         textLayoutProperty->UpdateContent(titleInfo.subtitle);
751         auto renderContext = subTitle->GetRenderContext();
752         CHECK_NULL_VOID(renderContext);
753         renderContext->UpdateOpacity(1.0);
754         return;
755     }
756     // create and init subtitle
757     subTitle = FrameNode::CreateFrameNode(
758         V2::TEXT_ETS_TAG, ElementRegister::GetInstance()->MakeUniqueId(), AceType::MakeRefPtr<TextPattern>());
759     auto textLayoutProperty = subTitle->GetLayoutProperty<TextLayoutProperty>();
760     CHECK_NULL_VOID(textLayoutProperty);
761     textLayoutProperty->UpdateContent(titleInfo.subtitle);
762     auto titleBarPattern = titleBarNode->GetPattern<TitleBarPattern>();
763     CHECK_NULL_VOID(titleBarPattern);
764     titleBarPattern->SetNeedResetSubTitleProperty(true);
765     titleBarNode->SetSubtitle(subTitle);
766     titleBarNode->AddChild(subTitle);
767 }
768 
CreateOrUpdateDestinationMainTitle(const RefPtr<TitleBarNode> & titleBarNode,const NG::NavigationTitleInfo & titleInfo)769 void NavigationTitleUtil::CreateOrUpdateDestinationMainTitle(const RefPtr<TitleBarNode>& titleBarNode,
770     const NG::NavigationTitleInfo& titleInfo)
771 {
772     CHECK_NULL_VOID(titleBarNode);
773     auto mainTitle = AceType::DynamicCast<FrameNode>(titleBarNode->GetTitle());
774     if (!titleInfo.hasMainTitle) {
775         // remove main title if any.
776         titleBarNode->RemoveChild(mainTitle);
777         titleBarNode->SetTitle(nullptr);
778         return;
779     }
780     if (mainTitle) {
781         // update main title
782         auto textLayoutProperty = mainTitle->GetLayoutProperty<TextLayoutProperty>();
783         CHECK_NULL_VOID(textLayoutProperty);
784         textLayoutProperty->UpdateMaxLines(titleInfo.hasSubTitle ? 1 : TITLEBAR_MAX_LINES);
785         if (AceApplicationInfo::GetInstance().GreatOrEqualTargetAPIVersion(PlatformVersion::VERSION_TWELVE)) {
786             textLayoutProperty->UpdateHeightAdaptivePolicy(titleInfo.hasSubTitle ?
787             TextHeightAdaptivePolicy::MAX_LINES_FIRST : TextHeightAdaptivePolicy::MIN_FONT_SIZE_FIRST);
788         }
789         textLayoutProperty->UpdateContent(titleInfo.title);
790         textLayoutProperty->UpdateMaxFontScale(STANDARD_FONT_SCALE);
791         return;
792     }
793     // create and init main title
794     mainTitle = FrameNode::CreateFrameNode(
795         V2::TEXT_ETS_TAG, ElementRegister::GetInstance()->MakeUniqueId(), AceType::MakeRefPtr<TextPattern>());
796     auto textLayoutProperty = mainTitle->GetLayoutProperty<TextLayoutProperty>();
797     CHECK_NULL_VOID(textLayoutProperty);
798     textLayoutProperty->UpdateContent(titleInfo.title);
799     auto titleBarPattern = titleBarNode->GetPattern<TitleBarPattern>();
800     CHECK_NULL_VOID(titleBarPattern);
801     titleBarPattern->SetNeedResetMainTitleProperty(true);
802     titleBarNode->SetTitle(mainTitle);
803     titleBarNode->AddChild(mainTitle);
804 }
805 
CreateOrUpdateDestinationSubtitle(const RefPtr<TitleBarNode> & titleBarNode,const NG::NavigationTitleInfo & titleInfo)806 void NavigationTitleUtil::CreateOrUpdateDestinationSubtitle(const RefPtr<TitleBarNode>& titleBarNode,
807     const NG::NavigationTitleInfo& titleInfo)
808 {
809     CHECK_NULL_VOID(titleBarNode);
810     auto subTitle = AceType::DynamicCast<FrameNode>(titleBarNode->GetSubtitle());
811     if (!titleInfo.hasSubTitle) {
812         // remove subtitle if any.
813         titleBarNode->RemoveChild(subTitle);
814         titleBarNode->SetSubtitle(nullptr);
815         return;
816     }
817     if (subTitle) {
818         // update subtitle
819         auto textLayoutProperty = subTitle->GetLayoutProperty<TextLayoutProperty>();
820         CHECK_NULL_VOID(textLayoutProperty);
821         textLayoutProperty->UpdateContent(titleInfo.subtitle);
822         textLayoutProperty->UpdateMaxFontScale(STANDARD_FONT_SCALE);
823         return;
824     }
825     // create and init subtitle
826     subTitle = FrameNode::CreateFrameNode(
827         V2::TEXT_ETS_TAG, ElementRegister::GetInstance()->MakeUniqueId(), AceType::MakeRefPtr<TextPattern>());
828     auto textLayoutProperty = subTitle->GetLayoutProperty<TextLayoutProperty>();
829     CHECK_NULL_VOID(textLayoutProperty);
830     textLayoutProperty->UpdateContent(titleInfo.subtitle);
831     auto titleBarPattern = titleBarNode->GetPattern<TitleBarPattern>();
832     CHECK_NULL_VOID(titleBarPattern);
833     titleBarPattern->SetNeedResetSubTitleProperty(true);
834     titleBarNode->SetSubtitle(subTitle);
835     titleBarNode->AddChild(subTitle);
836 }
837 
FoldStatusChangedAnimation(const RefPtr<FrameNode> & host)838 void NavigationTitleUtil::FoldStatusChangedAnimation(const RefPtr<FrameNode>& host)
839 {
840     CHECK_NULL_VOID(host);
841     auto pipelineContext = host->GetContext();
842     CHECK_NULL_VOID(pipelineContext);
843     auto titleBar = AceType::DynamicCast<TitleBarNode>(host);
844     CHECK_NULL_VOID(titleBar);
845     auto pattern = titleBar->GetPattern<TitleBarPattern>();
846     CHECK_NULL_VOID(pattern);
847 
848     if (!pipelineContext->IsHoverModeChange() || !IsNeedHoverModeAction(titleBar)) {
849         // Since only expanded to hover or hover to expanded need this animation.
850         return;
851     }
852 
853     AnimationOption option;
854     option.SetCurve(TITLEBAR_OPACITY_ANIMATION_CURVE);
855     auto renderNodeContext = host->GetRenderContext();
856     CHECK_NULL_VOID(renderNodeContext);
857     option.SetDuration(TITLEBAR_OPACITY_ANIMATION_DURATION);
858     renderNodeContext->UpdateOpacity(1.0f);
859     option.SetOnFinishEvent([weakRenderNodeContext = WeakPtr<RenderContext>(renderNodeContext),
860                                 weakHost = WeakPtr<FrameNode>(host)]() {
861         auto host = weakHost.Upgrade();
862         CHECK_NULL_VOID(host);
863         auto renderContext = weakRenderNodeContext.Upgrade();
864         CHECK_NULL_VOID(renderContext);
865         AnimationOption finishOption;
866         finishOption.SetDuration(TITLEBAR_OPACITY_ANIMATION_DURATION);
867         finishOption.SetCurve(TITLEBAR_OPACITY_ANIMATION_CURVE);
868         auto parent = AceType::DynamicCast<FrameNode>(host->GetParent());
869         CHECK_NULL_VOID(parent);
870         parent->MarkDirtyNode(PROPERTY_UPDATE_LAYOUT);
871         AnimationUtils::Animate(
872             finishOption, [weakRenderNodeContext = WeakPtr<RenderContext>(renderContext)]() {
873                 auto renderNodeContext = weakRenderNodeContext.Upgrade();
874                 CHECK_NULL_VOID(renderNodeContext);
875                 renderNodeContext->UpdateOpacity(1.0f);
876             });
877     });
878     AnimationUtils::Animate(
879         option,
880         [weakRenderNodeContext = WeakPtr<RenderContext>(renderNodeContext)]() {
881             auto renderContext = weakRenderNodeContext.Upgrade();
882             CHECK_NULL_VOID(renderContext);
883             renderContext->UpdateOpacity(0.0f);
884         },
885         option.GetOnFinishEvent());
886 }
887 
IsNeedHoverModeAction(const RefPtr<TitleBarNode> & titleBarNode)888 bool NavigationTitleUtil::IsNeedHoverModeAction(const RefPtr<TitleBarNode>& titleBarNode)
889 {
890     CHECK_NULL_RETURN(titleBarNode, false);
891     auto pattern = titleBarNode->GetPattern<TitleBarPattern>();
892     CHECK_NULL_RETURN(pattern, false);
893     auto options = pattern->GetTitleBarOptions();
894     auto titleBarLayoutProperty = titleBarNode->GetLayoutProperty<TitleBarLayoutProperty>();
895     CHECK_NULL_RETURN(titleBarLayoutProperty, false);
896     auto parentType = titleBarLayoutProperty->GetTitleBarParentTypeValue(TitleBarParentType::NAVBAR);
897     if (parentType == TitleBarParentType::NAVBAR &&
898         titleBarLayoutProperty->GetTitleModeValue(NavigationTitleMode::MINI) == NavigationTitleMode::FREE) {
899         return false;
900     }
901     if (!options.enableHoverMode || options.brOptions.barStyle == NG::BarStyle::STANDARD) {
902         return false;
903     }
904     RefPtr<NavigationGroupNode> navigationGroupNode;
905     if (parentType == TitleBarParentType::NAVBAR) {
906         auto navBarNode = AceType::DynamicCast<NavBarNode>(titleBarNode->GetParent());
907         CHECK_NULL_RETURN(navBarNode, false);
908         navigationGroupNode = AceType::DynamicCast<NavigationGroupNode>(navBarNode->GetParent());
909     } else {
910         auto navDestination = AceType::DynamicCast<NavDestinationGroupNode>(titleBarNode->GetParent());
911         CHECK_NULL_RETURN(navDestination, false);
912         auto navDestinationPattern = navDestination->GetPattern<NavDestinationPattern>();
913         CHECK_NULL_RETURN(navDestinationPattern, false);
914         navigationGroupNode = AceType::DynamicCast<NavigationGroupNode>(navDestinationPattern->GetNavigationNode());
915     }
916     CHECK_NULL_RETURN(navigationGroupNode, false);
917     auto navigationPattern = AceType::DynamicCast<NavigationPattern>(navigationGroupNode->GetPattern());
918     CHECK_NULL_RETURN(navigationPattern, false);
919     auto pageNode = navigationPattern->GetNavBasePageNode();
920     CHECK_NULL_RETURN(pageNode, false);
921     auto foldCreaseRects = pattern->GetFoldCreaseRects();
922     auto parentNode = AceType::DynamicCast<FrameNode>(titleBarNode->GetParent());
923     CHECK_NULL_RETURN(parentNode, false);
924     bool isParentFullPage = pageNode->GetGeometryNode()->GetFrameSize().Height()
925         == parentNode->GetGeometryNode()->GetFrameSize().Height();
926     return !foldCreaseRects.empty() && isParentFullPage;
927 }
928 
CalculateTitlebarOffset(const RefPtr<UINode> & titleBarNode)929 float NavigationTitleUtil::CalculateTitlebarOffset(const RefPtr<UINode>& titleBarNode)
930 {
931     CHECK_NULL_RETURN(titleBarNode, 0.0f);
932     auto titleBar = AceType::DynamicCast<TitleBarNode>(titleBarNode);
933     CHECK_NULL_RETURN(titleBar, 0.0f);
934     if (!IsNeedHoverModeAction(titleBar)) {
935         return 0.0f;
936     }
937     auto pattern = titleBar->GetPattern<TitleBarPattern>();
938     CHECK_NULL_RETURN(pattern, false);
939     auto foldCreaseRects = pattern->GetFoldCreaseRects();
940     auto pipelineContext = titleBar->GetContext();
941     CHECK_NULL_RETURN(pipelineContext, 0.0f);
942     if (!pipelineContext->IsHalfFoldHoverStatus()) {
943         return 0.0f;
944     }
945     auto safeArea = pipelineContext->GetSafeAreaWithoutProcess();
946     auto length = safeArea.top_.Length();
947     auto foldCrease = foldCreaseRects.front();
948 
949     // offsetY = The Y of the foldCrease + Adapt vertical displacement of hover state - the height of the status bar.
950     return foldCrease.GetOffset().GetY() + TITLEBAR_VERTICAL_PADDING.ConvertToPx() - length;
951 }
952 
IsTitleBarHasOffsetY(const RefPtr<FrameNode> & titleBarNode)953 bool NavigationTitleUtil::IsTitleBarHasOffsetY(const RefPtr<FrameNode>& titleBarNode)
954 {
955     return titleBarNode && titleBarNode->IsVisible() && !NearZero(CalculateTitlebarOffset(titleBarNode));
956 }
957 
UpdateTitleOrToolBarTranslateYAndOpacity(const RefPtr<NavDestinationNodeBase> & nodeBase,const RefPtr<FrameNode> & barNode,float translate,bool isTitle)958 void NavigationTitleUtil::UpdateTitleOrToolBarTranslateYAndOpacity(const RefPtr<NavDestinationNodeBase>& nodeBase,
959     const RefPtr<FrameNode>& barNode, float translate, bool isTitle)
960 {
961     CHECK_NULL_VOID(nodeBase);
962     CHECK_NULL_VOID(barNode);
963     auto renderContext = barNode->GetRenderContext();
964     CHECK_NULL_VOID(renderContext);
965     auto option = renderContext->GetTransformTranslateValue(TranslateOptions(0.0f, 0.0f, 0.0f));
966     option.y = CalcDimension(translate, DimensionUnit::PX);
967     renderContext->UpdateTransformTranslate(option);
968     auto barHeight = renderContext->GetPaintRectWithoutTransform().Height();
969     float opacity = 1.0f;
970     if (!NearZero(barHeight)) {
971         opacity = 1.0f - std::clamp(std::abs(translate) / barHeight, 0.0f, 1.0f);
972     }
973     renderContext->UpdateOpacity(opacity);
974     if (isTitle) {
975         return;
976     }
977     auto divider = AceType::DynamicCast<FrameNode>(nodeBase->GetToolBarDividerNode());
978     CHECK_NULL_VOID(divider);
979     auto dividerRenderContext = divider->GetRenderContext();
980     CHECK_NULL_VOID(dividerRenderContext);
981     dividerRenderContext->UpdateTransformTranslate(option);
982     dividerRenderContext->UpdateOpacity(opacity);
983 }
984 } // namespace OHOS::Ace::NG
985