• 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 "base/i18n/localization.h"
19 #include "base/subwindow/subwindow_manager.h"
20 #include "base/utils/system_properties.h"
21 #include "base/utils/utf_helper.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 constexpr int32_t DEFAULT_ANIMATION_DURATION = 450;
50 const RefPtr<CubicCurve> TITLEBAR_OPACITY_ANIMATION_CURVE = AceType::MakeRefPtr<CubicCurve>(0.4, 0.0, 0.4, 1.0);
51 }
52 
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)53 bool NavigationTitleUtil::BuildMoreButton(bool isButtonEnabled, const RefPtr<NavigationBarTheme>& theme,
54     const RefPtr<NavDestinationNodeBase>& nodeBase, const RefPtr<FrameNode>& menuNode,
55     std::vector<OptionParam>&& params, const std::string& field, const std::string& parentId,
56     bool isCreateLandscapeMenu)
57 {
58     auto barItemNode = CreateBarItemNode(isButtonEnabled, theme);
59     CHECK_NULL_RETURN(barItemNode, false);
60     auto menuItemNode = CreateMenuItemButton(theme);
61     CHECK_NULL_RETURN(menuItemNode, false);
62     CHECK_NULL_RETURN(nodeBase, false);
63     auto navDestinationPattern = nodeBase->GetPattern<NavDestinationPattern>();
64     CHECK_NULL_RETURN(navDestinationPattern, false);
65     MenuParam menuParam;
66     menuParam.isShowInSubWindow = false;
67     menuParam.placement = Placement::BOTTOM_RIGHT;
68     if (SystemProperties::GetDeviceType() == DeviceType::TWO_IN_ONE) {
69         menuParam.isShowInSubWindow = true;
70     }
71     NavigationMenuOptions menuOptions = navDestinationPattern->GetMenuOptions();
72     if (menuOptions.mbOptions.bgOptions.blurStyleOption.has_value()) {
73         menuParam.backgroundBlurStyleOption = menuOptions.mbOptions.bgOptions.blurStyleOption.value();
74     }
75     if (menuOptions.mbOptions.bgOptions.effectOption.has_value()) {
76         menuParam.backgroundEffectOption = menuOptions.mbOptions.bgOptions.effectOption.value();
77     }
78     auto barMenuNode = MenuView::Create(
79         std::move(params), menuItemNode->GetId(), menuItemNode->GetTag(), MenuType::NAVIGATION_MENU, menuParam);
80     BuildMoreItemNodeAction(menuItemNode, barItemNode, barMenuNode, menuParam);
81     auto iconNode = AceType::DynamicCast<FrameNode>(barItemNode->GetChildren().front());
82     InitTitleBarButtonEvent(menuItemNode, iconNode, true);
83 
84     // read navdestination "more" button
85     std::string message = theme ? theme->GetMoreMessage() : "";
86     SetAccessibility(menuItemNode, message);
87 
88     // set navdestination titleBar "more" button inspectorId
89     SetInnerChildId(menuItemNode, field, menuNode->GetTag(), "More", parentId);
90 
91     barItemNode->MountToParent(menuItemNode);
92     barItemNode->MarkModifyDone();
93     menuItemNode->MarkModifyDone();
94     CHECK_NULL_RETURN(menuNode, false);
95     menuNode->AddChild(menuItemNode);
96     if (isCreateLandscapeMenu) {
97         nodeBase->SetLandscapeMenuNode(barMenuNode);
98     } else {
99         nodeBase->SetMenuNode(barMenuNode);
100     }
101     return true;
102 }
103 
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)104 RefPtr<FrameNode> NavigationTitleUtil::CreateMenuItems(const int32_t menuNodeId,
105     const std::vector<NG::BarItem>& menuItems, const RefPtr<NavDestinationNodeBase>& navDestinationNodeBase,
106     bool isButtonEnabled, const std::string& field, const std::string& parentId, bool isCreateLandscapeMenu)
107 {
108     auto menuNode = FrameNode::GetOrCreateFrameNode(
109         V2::NAVIGATION_MENU_ETS_TAG, menuNodeId, []() { return AceType::MakeRefPtr<LinearLayoutPattern>(false); });
110     CHECK_NULL_RETURN(menuNode, nullptr);
111     menuNode->Clean();
112     menuNode->MarkDirtyNode(PROPERTY_UPDATE_MEASURE);
113     auto rowProperty = menuNode->GetLayoutProperty<LinearLayoutProperty>();
114     CHECK_NULL_RETURN(rowProperty, nullptr);
115     rowProperty->UpdateMainAxisAlign(FlexAlign::SPACE_BETWEEN);
116     auto theme = NavigationGetTheme(navDestinationNodeBase->GetThemeScopeId());
117     CHECK_NULL_RETURN(theme, nullptr);
118     auto mostMenuItemCount = GetOrInitMaxMenuNums(theme, navDestinationNodeBase);
119     bool needMoreButton = menuItems.size() > mostMenuItemCount;
120 
121     int32_t count = 0;
122     std::vector<OptionParam> params;
123     OptionParam param;
124     for (const auto& menuItem : menuItems) {
125         ++count;
126         if (needMoreButton && (count > static_cast<int32_t>(mostMenuItemCount) - 1)) {
127             param = { menuItem.text.value_or(""), menuItem.icon.value_or(""), menuItem.isEnabled.value_or(true),
128                 menuItem.action, menuItem.iconSymbol.value_or(nullptr) };
129             param.SetSymbolUserDefinedIdealFontSize(theme->GetMenuIconSize());
130             params.push_back(param);
131         } else {
132             auto menuItemNode = CreateMenuItemNode(theme, menuItem, isButtonEnabled);
133             CHECK_NULL_RETURN(menuItemNode, nullptr);
134 
135             // set titleBar menuitem inspectorId
136             std::string menuItemId = menuItemNode->GetTag() + std::to_string(count);
137             NavigationTitleUtil::SetInnerChildId(menuItemNode, field, menuNode->GetTag(), menuItemId, parentId);
138 
139             // read menu button
140             SetAccessibility(menuItemNode, menuItem.text.value_or(""));
141             menuNode->AddChild(menuItemNode);
142         }
143     }
144 
145     // build more button
146     if (needMoreButton) {
147         bool buildMoreButtonResult = BuildMoreButton(isButtonEnabled, theme, navDestinationNodeBase,
148             menuNode, std::move(params), field, parentId, isCreateLandscapeMenu);
149         if (!buildMoreButtonResult) {
150             TAG_LOGI(AceLogTag::ACE_NAVIGATION, "build more button node failed");
151             return nullptr;
152         }
153     }
154     auto titleBarNode = AceType::DynamicCast<TitleBarNode>(navDestinationNodeBase->GetTitleBarNode());
155     CHECK_NULL_RETURN(titleBarNode, nullptr);
156     auto titleBarPattern = titleBarNode->GetPattern<TitleBarPattern>();
157     CHECK_NULL_RETURN(titleBarPattern, nullptr);
158     titleBarPattern->InitMenuDragAndLongPressEvent(menuNode, menuItems);
159     return menuNode;
160 }
161 
GetOrInitMaxMenuNums(const RefPtr<NavigationBarTheme> & theme,const RefPtr<NavDestinationNodeBase> & navDestinationNodeBase)162 uint32_t NavigationTitleUtil::GetOrInitMaxMenuNums(
163     const RefPtr<NavigationBarTheme>& theme, const RefPtr<NavDestinationNodeBase>& navDestinationNodeBase)
164 {
165     auto patternBase = navDestinationNodeBase->GetPattern<NavDestinationPatternBase>();
166     CHECK_NULL_RETURN(patternBase, 0);
167     auto navDesMaxNum = patternBase->GetMaxMenuNum();
168     auto mostMenuItemCount =
169         navDesMaxNum < 0 ? theme->GetMostMenuItemCountInBar() : static_cast<uint32_t>(navDesMaxNum);
170     mostMenuItemCount = SystemProperties::GetDeviceOrientation() == DeviceOrientation::LANDSCAPE ? MAX_MENU_NUM_LARGE
171                                                                                                  : mostMenuItemCount;
172     patternBase->SetMaxMenuNum(mostMenuItemCount);
173     return mostMenuItemCount;
174 }
175 
BuildMoreItemNodeAction(const RefPtr<FrameNode> & buttonNode,const RefPtr<BarItemNode> & barItemNode,const RefPtr<FrameNode> & barMenuNode,const MenuParam & menuParam)176 void NavigationTitleUtil::BuildMoreItemNodeAction(const RefPtr<FrameNode>& buttonNode,
177     const RefPtr<BarItemNode>& barItemNode, const RefPtr<FrameNode>& barMenuNode, const MenuParam& menuParam)
178 {
179     auto eventHub = barItemNode->GetOrCreateEventHub<BarItemEventHub>();
180     CHECK_NULL_VOID(eventHub);
181 
182     auto context = PipelineContext::GetCurrentContext();
183     auto clickCallback = [weakContext = WeakPtr<PipelineContext>(context),
184                             id = barItemNode->GetId(),
185                             param = menuParam,
186                             weakMenu = WeakPtr<FrameNode>(barMenuNode),
187                             weakBarItemNode = WeakPtr<BarItemNode>(barItemNode)]() {
188         auto context = weakContext.Upgrade();
189         CHECK_NULL_VOID(context);
190 
191         auto overlayManager = context->GetOverlayManager();
192         CHECK_NULL_VOID(overlayManager);
193 
194         auto menu = weakMenu.Upgrade();
195         CHECK_NULL_VOID(menu);
196 
197         auto barItemNode = weakBarItemNode.Upgrade();
198         OffsetF offset(0.0f, 0.0f);
199         if (param.isShowInSubWindow) {
200             auto wrapperPattern = menu->GetPattern<MenuWrapperPattern>();
201             if (wrapperPattern && wrapperPattern->GetMenuStatus() == MenuStatus::ON_HIDE_ANIMATION) {
202                 //if on hide animation, avoid displaying the menu again
203                 return;
204             }
205             SubwindowManager::GetInstance()->ShowMenuNG(menu, param, barItemNode, offset);
206             return;
207         }
208         overlayManager->ShowMenu(id, offset, menu);
209     };
210     eventHub->SetItemAction(clickCallback);
211 
212     auto gestureEventHub = buttonNode->GetOrCreateGestureEventHub();
213     CHECK_NULL_VOID(gestureEventHub);
214     auto callback = [action = clickCallback](GestureEvent& info) {
215         if (info.GetSourceDevice() == SourceType::KEYBOARD) {
216             return;
217         }
218         action();
219     };
220     gestureEventHub->AddClickEvent(AceType::MakeRefPtr<ClickEvent>(callback));
221 }
222 
CreateMenuItemNode(const RefPtr<NavigationBarTheme> & theme,const BarItem & menuItem,bool isButtonEnabled)223 RefPtr<FrameNode> NavigationTitleUtil::CreateMenuItemNode(
224     const RefPtr<NavigationBarTheme>& theme, const BarItem& menuItem, bool isButtonEnabled)
225 {
226     auto menuItemNode = CreateMenuItemButton(theme);
227     CHECK_NULL_RETURN(menuItemNode, nullptr);
228 
229     int32_t barItemNodeId = ElementRegister::GetInstance()->MakeUniqueId();
230     auto barItemNode = BarItemNode::GetOrCreateBarItemNode(
231         V2::BAR_ITEM_ETS_TAG, barItemNodeId, []() { return AceType::MakeRefPtr<BarItemPattern>(); });
232     UpdateBarItemNodeWithItem(barItemNode, menuItem, isButtonEnabled, theme);
233     auto iconNode = AceType::DynamicCast<FrameNode>(barItemNode->GetChildren().front());
234     InitTitleBarButtonEvent(menuItemNode, iconNode, false, menuItem, menuItem.isEnabled.value_or(true));
235     auto barItemLayoutProperty = barItemNode->GetLayoutProperty();
236     CHECK_NULL_RETURN(barItemLayoutProperty, nullptr);
237     barItemLayoutProperty->UpdateMeasureType(MeasureType::MATCH_PARENT);
238 
239     barItemNode->MountToParent(menuItemNode);
240     barItemNode->MarkModifyDone();
241     menuItemNode->MarkModifyDone();
242     return menuItemNode;
243 }
244 
CreateMenuItemButton(const RefPtr<NavigationBarTheme> & theme)245 RefPtr<FrameNode> NavigationTitleUtil::CreateMenuItemButton(const RefPtr<NavigationBarTheme>& theme)
246 {
247     auto buttonPattern = AceType::MakeRefPtr<NG::ButtonPattern>();
248     CHECK_NULL_RETURN(buttonPattern, nullptr);
249     buttonPattern->setComponentButtonType(ComponentButtonType::NAVIGATION);
250     if (AceApplicationInfo::GetInstance().GreatOrEqualTargetAPIVersion(PlatformVersion::VERSION_TWELVE)) {
251         buttonPattern->SetBlendColor(theme->GetBackgroundPressedColor(), theme->GetBackgroundHoverColor());
252         buttonPattern->SetFocusBorderColor(theme->GetBackgroundFocusOutlineColor());
253         buttonPattern->SetFocusBorderWidth(theme->GetBackgroundFocusOutlineWeight());
254     } else {
255         buttonPattern->SetFocusBorderColor(theme->GetToolBarItemFocusColor());
256         buttonPattern->SetFocusBorderWidth(theme->GetToolBarItemFocusBorderWidth());
257     }
258     auto menuItemNode = FrameNode::CreateFrameNode(
259         V2::MENU_ITEM_ETS_TAG, ElementRegister::GetInstance()->MakeUniqueId(), buttonPattern);
260     CHECK_NULL_RETURN(menuItemNode, nullptr);
261     auto focusHub = menuItemNode->GetOrCreateFocusHub();
262     CHECK_NULL_RETURN(focusHub, nullptr);
263     focusHub->SetFocusDependence(FocusDependence::SELF);
264     auto menuItemLayoutProperty = menuItemNode->GetLayoutProperty<ButtonLayoutProperty>();
265     CHECK_NULL_RETURN(menuItemLayoutProperty, nullptr);
266     menuItemLayoutProperty->UpdateType(ButtonType::NORMAL);
267     auto renderContext = menuItemNode->GetRenderContext();
268     CHECK_NULL_RETURN(renderContext, nullptr);
269     if (AceApplicationInfo::GetInstance().GreatOrEqualTargetAPIVersion(PlatformVersion::VERSION_TWELVE)) {
270         auto iconBackgroundWidth = theme->GetIconBackgroundWidth();
271         auto iconBackgroundHeight = theme->GetIconBackgroundHeight();
272         menuItemLayoutProperty->UpdateUserDefinedIdealSize(
273             CalcSize(CalcLength(iconBackgroundWidth), CalcLength(iconBackgroundHeight)));
274         menuItemLayoutProperty->UpdateBorderRadius(BorderRadiusProperty(theme->GetCornerRadius()));
275         renderContext->UpdateBackgroundColor(theme->GetCompBackgroundColor());
276         PaddingProperty padding;
277         padding.SetEdges(CalcLength(MENU_BUTTON_PADDING));
278         menuItemLayoutProperty->UpdatePadding(padding);
279         MarginProperty margin;
280         margin.right = CalcLength(theme->GetCompPadding());
281         margin.end = CalcLength(theme->GetCompPadding());
282         menuItemLayoutProperty->UpdateMargin(margin);
283     } else {
284         menuItemLayoutProperty->UpdateUserDefinedIdealSize(
285             CalcSize(CalcLength(BACK_BUTTON_SIZE), CalcLength(BACK_BUTTON_SIZE)));
286         menuItemLayoutProperty->UpdateBorderRadius(BorderRadiusProperty(BUTTON_RADIUS_SIZE));
287         renderContext->UpdateBackgroundColor(Color::TRANSPARENT);
288         PaddingProperty padding;
289         padding.SetEdges(CalcLength(BUTTON_PADDING));
290         menuItemLayoutProperty->UpdatePadding(padding);
291     }
292     return menuItemNode;
293 }
294 
CreateBarItemTextNode(const std::string & text)295 RefPtr<FrameNode> NavigationTitleUtil::CreateBarItemTextNode(const std::string& text)
296 {
297     int32_t nodeId = ElementRegister::GetInstance()->MakeUniqueId();
298     auto textNode = FrameNode::CreateFrameNode(V2::TEXT_ETS_TAG, nodeId, AceType::MakeRefPtr<TextPattern>());
299     auto textLayoutProperty = textNode->GetLayoutProperty<TextLayoutProperty>();
300     CHECK_NULL_RETURN(textLayoutProperty, nullptr);
301     textLayoutProperty->UpdateContent(text);
302     textLayoutProperty->UpdateFontSize(TEXT_FONT_SIZE);
303     textLayoutProperty->UpdateTextColor(TEXT_COLOR);
304     textLayoutProperty->UpdateTextAlign(TextAlign::CENTER);
305     return textNode;
306 }
307 
UpdateSymbolEffect(RefPtr<TextLayoutProperty> symbolProperty,bool isActive)308 void UpdateSymbolEffect(RefPtr<TextLayoutProperty> symbolProperty, bool isActive)
309 {
310     CHECK_NULL_VOID(symbolProperty);
311     auto symbolEffectOptions = SymbolEffectOptions(SymbolEffectType::BOUNCE);
312     symbolEffectOptions.SetIsTxtActive(isActive);
313     symbolEffectOptions.SetIsTxtActiveSource(0);
314     symbolProperty->UpdateSymbolEffectOptions(symbolEffectOptions);
315 }
316 
CreateBarItemIconNode(const BarItem & barItem,const bool isButtonEnabled,const RefPtr<NavigationBarTheme> & theme)317 RefPtr<FrameNode> NavigationTitleUtil::CreateBarItemIconNode(
318     const BarItem& barItem, const bool isButtonEnabled, const RefPtr<NavigationBarTheme>& theme)
319 {
320     CHECK_NULL_RETURN(theme, nullptr);
321 
322     Color iconColor = theme->GetMenuIconColor();
323     double iconOpacity = theme->GetAlphaDisabled();
324     auto iconWidth = theme->GetMenuIconSize();
325     auto iconHeight = theme->GetMenuIconSize();
326     if (AceApplicationInfo::GetInstance().GreatOrEqualTargetAPIVersion(PlatformVersion::VERSION_TWELVE)) {
327         iconColor = theme->GetIconColor();
328         iconOpacity = theme->GetIconDisableAlpha();
329         iconWidth = theme->GetIconWidth();
330         iconHeight = theme->GetIconHeight();
331     }
332 
333     if (barItem.iconSymbol.has_value() && barItem.iconSymbol.value() != nullptr) {
334         auto iconNode = FrameNode::GetOrCreateFrameNode(V2::SYMBOL_ETS_TAG,
335             ElementRegister::GetInstance()->MakeUniqueId(), []() { return AceType::MakeRefPtr<TextPattern>(); });
336         CHECK_NULL_RETURN(iconNode, nullptr);
337         auto symbolProperty = iconNode->GetLayoutProperty<TextLayoutProperty>();
338         CHECK_NULL_RETURN(symbolProperty, nullptr);
339         if (isButtonEnabled) {
340             symbolProperty->UpdateSymbolColorList({ iconColor });
341         } else {
342             symbolProperty->UpdateSymbolColorList({ iconColor.BlendOpacity(iconOpacity) });
343         }
344         barItem.iconSymbol.value()(AccessibilityManager::WeakClaim(AccessibilityManager::RawPtr(iconNode)));
345         UpdateSymbolEffect(symbolProperty, false);
346         symbolProperty->UpdateFontSize(iconWidth);
347         iconNode->MarkModifyDone();
348         return iconNode;
349     }
350     int32_t nodeId = ElementRegister::GetInstance()->MakeUniqueId();
351     ImageSourceInfo info(barItem.icon.value());
352     auto iconNode = FrameNode::CreateFrameNode(V2::IMAGE_ETS_TAG, nodeId, AceType::MakeRefPtr<ImagePattern>());
353     auto imageLayoutProperty = iconNode->GetLayoutProperty<ImageLayoutProperty>();
354     CHECK_NULL_RETURN(imageLayoutProperty, nullptr);
355     if (isButtonEnabled) {
356         info.SetFillColor(iconColor);
357     } else {
358         info.SetFillColor(iconColor.BlendOpacity(iconOpacity));
359     }
360     imageLayoutProperty->UpdateImageSourceInfo(info);
361     imageLayoutProperty->UpdateUserDefinedIdealSize(CalcSize(CalcLength(iconWidth), CalcLength(iconHeight)));
362     iconNode->MarkModifyDone();
363     return iconNode;
364 }
365 
InitTitleBarButtonEvent(const RefPtr<FrameNode> & buttonNode,const RefPtr<FrameNode> & iconNode,bool isMoreButton,const BarItem & menuItem,bool isButtonEnabled)366 void NavigationTitleUtil::InitTitleBarButtonEvent(const RefPtr<FrameNode>& buttonNode,
367     const RefPtr<FrameNode>& iconNode, bool isMoreButton, const BarItem& menuItem, bool isButtonEnabled)
368 {
369     auto eventHub = buttonNode->GetOrCreateInputEventHub();
370     CHECK_NULL_VOID(eventHub);
371 
372     if (isMoreButton) {
373         auto hoverTask = [weakTargetNode = WeakPtr<FrameNode>(buttonNode)](bool isHover) {
374             auto targetNode = weakTargetNode.Upgrade();
375             CHECK_NULL_VOID(targetNode);
376             auto popupParam = AceType::MakeRefPtr<PopupParam>();
377             auto theme = NavigationGetTheme();
378             CHECK_NULL_VOID(theme);
379             popupParam->SetMessage(theme->GetMoreMessage());
380             popupParam->SetIsShow(isHover);
381             popupParam->SetBlockEvent(false);
382             ViewAbstract::BindPopup(popupParam, targetNode, nullptr);
383         };
384         eventHub->AddOnHoverEvent(AceType::MakeRefPtr<InputEvent>(std::move(hoverTask)));
385         return;
386     }
387 
388     if (menuItem.action) {
389         auto gestureEventHub = buttonNode->GetOrCreateGestureEventHub();
390         CHECK_NULL_VOID(gestureEventHub);
391         auto clickCallback = [action = menuItem.action, weakNode = WeakPtr<FrameNode>(iconNode)](GestureEvent& info) {
392             if (info.GetSourceDevice() == SourceType::KEYBOARD) {
393                 return;
394             }
395             if (action) {
396                 action();
397             }
398             auto symbol = weakNode.Upgrade();
399             CHECK_NULL_VOID(symbol);
400             if (symbol->GetTag() == V2::SYMBOL_ETS_TAG) {
401                 auto symbolProperty = symbol->GetLayoutProperty<TextLayoutProperty>();
402                 CHECK_NULL_VOID(symbolProperty);
403                 auto symbolEffectOptions = symbolProperty->GetSymbolEffectOptionsValue(SymbolEffectOptions());
404                 symbolEffectOptions.SetEffectType(SymbolEffectType::BOUNCE);
405                 symbolEffectOptions.SetIsTxtActive(true);
406                 symbolEffectOptions.SetIsTxtActiveSource(0);
407                 symbolProperty->UpdateSymbolEffectOptions(symbolEffectOptions);
408                 symbol->MarkDirtyNode(PROPERTY_UPDATE_MEASURE_SELF);
409             }
410         };
411         gestureEventHub->AddClickEvent(AceType::MakeRefPtr<ClickEvent>(clickCallback));
412     }
413 
414     auto buttonEvent = buttonNode->GetOrCreateEventHub<ButtonEventHub>();
415     CHECK_NULL_VOID(buttonEvent);
416     buttonEvent->SetEnabled(isButtonEnabled);
417     auto focusHub = buttonNode->GetFocusHub();
418     CHECK_NULL_VOID(focusHub);
419     focusHub->SetEnabled(isButtonEnabled);
420 }
421 
UpdateBarItemNodeWithItem(const RefPtr<BarItemNode> & barItemNode,const BarItem & barItem,const bool isButtonEnabled,const RefPtr<NavigationBarTheme> & theme)422 void NavigationTitleUtil::UpdateBarItemNodeWithItem(const RefPtr<BarItemNode>& barItemNode, const BarItem& barItem,
423     const bool isButtonEnabled, const RefPtr<NavigationBarTheme>& theme)
424 {
425     if (Container::LessThanAPIVersion(PlatformVersion::VERSION_TEN) && barItem.text.has_value() &&
426         !barItem.text.value().empty()) {
427         auto textNode = CreateBarItemTextNode(barItem.text.value());
428         barItemNode->SetTextNode(textNode);
429         barItemNode->AddChild(textNode);
430     }
431     if ((barItem.icon.has_value()) || (barItem.iconSymbol.has_value() && barItem.iconSymbol.value() != nullptr)) {
432         auto iconNode = CreateBarItemIconNode(barItem, isButtonEnabled, theme);
433         barItemNode->SetIconNode(iconNode);
434         barItemNode->AddChild(iconNode);
435     }
436     if (barItem.action) {
437         auto eventHub = barItemNode->GetOrCreateEventHub<BarItemEventHub>();
438         CHECK_NULL_VOID(eventHub);
439         eventHub->SetItemAction(barItem.action);
440     }
441     auto barItemPattern = barItemNode->GetPattern<BarItemPattern>();
442     barItemNode->MarkModifyDone();
443 }
444 
BuildImageMoreItemNode(const RefPtr<BarItemNode> & barItemNode,bool isButtonEnabled,const RefPtr<NavigationBarTheme> & theme)445 void BuildImageMoreItemNode(
446     const RefPtr<BarItemNode>& barItemNode, bool isButtonEnabled, const RefPtr<NavigationBarTheme>& theme)
447 {
448     int32_t imageNodeId = ElementRegister::GetInstance()->MakeUniqueId();
449     auto imageNode = FrameNode::CreateFrameNode(V2::IMAGE_ETS_TAG, imageNodeId, AceType::MakeRefPtr<ImagePattern>());
450     CHECK_NULL_VOID(imageNode);
451     auto imageLayoutProperty = imageNode->GetLayoutProperty<ImageLayoutProperty>();
452     CHECK_NULL_VOID(imageLayoutProperty);
453     CHECK_NULL_VOID(theme);
454 
455     auto info = ImageSourceInfo("");
456     info.SetResourceId(theme->GetMoreResourceId());
457     if (isButtonEnabled) {
458         info.SetFillColor(theme->GetMenuIconColor());
459     } else {
460         info.SetFillColor(theme->GetMenuIconColor().BlendOpacity(theme->GetAlphaDisabled()));
461     }
462 
463     imageLayoutProperty->UpdateImageSourceInfo(info);
464     auto iconSize = theme->GetMenuIconSize();
465     imageLayoutProperty->UpdateUserDefinedIdealSize(CalcSize(CalcLength(iconSize), CalcLength(iconSize)));
466     imageNode->MarkModifyDone();
467 
468     barItemNode->SetIsMoreItemNode(true);
469     barItemNode->SetIconNode(imageNode);
470     barItemNode->AddChild(imageNode);
471     barItemNode->MarkModifyDone();
472 }
473 
BuildSymbolMoreItemNode(const RefPtr<BarItemNode> & barItemNode,bool isButtonEnabled,const RefPtr<NavigationBarTheme> & theme)474 void BuildSymbolMoreItemNode(
475     const RefPtr<BarItemNode>& barItemNode, bool isButtonEnabled, const RefPtr<NavigationBarTheme>& theme)
476 {
477     CHECK_NULL_VOID(theme);
478     auto iconSize = theme->GetMenuIconSize();
479     auto symbolNode = FrameNode::GetOrCreateFrameNode(V2::SYMBOL_ETS_TAG,
480         ElementRegister::GetInstance()->MakeUniqueId(), []() { return AceType::MakeRefPtr<TextPattern>(); });
481     CHECK_NULL_VOID(symbolNode);
482     auto symbolProperty = symbolNode->GetLayoutProperty<TextLayoutProperty>();
483     CHECK_NULL_VOID(symbolProperty);
484     symbolProperty->UpdateSymbolSourceInfo(SymbolSourceInfo(theme->GetMoreSymbolId()));
485     symbolProperty->UpdateFontSize(iconSize);
486     if (isButtonEnabled) {
487         symbolProperty->UpdateSymbolColorList({ theme->GetMenuIconColor() });
488     } else {
489         symbolProperty->UpdateSymbolColorList({ theme->GetMenuIconColor().BlendOpacity(theme->GetAlphaDisabled()) });
490     }
491     symbolNode->MarkModifyDone();
492     barItemNode->SetIsMoreItemNode(true);
493     barItemNode->SetIconNode(symbolNode);
494     barItemNode->AddChild(symbolNode);
495     barItemNode->MarkModifyDone();
496 }
497 
BuildMoreIemNode(const RefPtr<BarItemNode> & barItemNode,bool isButtonEnabled,const RefPtr<NavigationBarTheme> & theme)498 void NavigationTitleUtil::BuildMoreIemNode(
499     const RefPtr<BarItemNode>& barItemNode, bool isButtonEnabled, const RefPtr<NavigationBarTheme>& theme)
500 {
501     if (AceApplicationInfo::GetInstance().GreatOrEqualTargetAPIVersion(PlatformVersion::VERSION_TWELVE) &&
502         SystemProperties::IsNeedSymbol()) {
503         BuildSymbolMoreItemNode(barItemNode, isButtonEnabled, theme);
504     } else {
505         BuildImageMoreItemNode(barItemNode, isButtonEnabled, theme);
506     }
507 }
508 
CreateBarItemNode(bool isButtonEnabled,const RefPtr<NavigationBarTheme> & theme)509 RefPtr<BarItemNode> NavigationTitleUtil::CreateBarItemNode(
510     bool isButtonEnabled, const RefPtr<NavigationBarTheme>& theme)
511 {
512     int32_t barItemNodeId = ElementRegister::GetInstance()->MakeUniqueId();
513     auto barItemNode = BarItemNode::GetOrCreateBarItemNode(
514         V2::BAR_ITEM_ETS_TAG, barItemNodeId, []() { return AceType::MakeRefPtr<BarItemPattern>(); });
515     auto barItemLayoutProperty = barItemNode->GetLayoutProperty();
516     CHECK_NULL_RETURN(barItemLayoutProperty, nullptr);
517     barItemLayoutProperty->UpdateMeasureType(MeasureType::MATCH_PARENT);
518     BuildMoreIemNode(barItemNode, isButtonEnabled, theme);
519     return barItemNode;
520 }
521 
CreatePopupDialogNode(const RefPtr<FrameNode> targetNode,const std::vector<NG::BarItem> & menuItems,int32_t index,int32_t themeScopeId)522 RefPtr<FrameNode> NavigationTitleUtil::CreatePopupDialogNode(
523     const RefPtr<FrameNode> targetNode, const std::vector<NG::BarItem>& menuItems, int32_t index, int32_t themeScopeId)
524 {
525     CHECK_NULL_RETURN(targetNode, nullptr);
526     RefPtr<BarItemNode> barItemNode = AceType::DynamicCast<BarItemNode>(targetNode->GetFirstChild());
527     CHECK_NULL_RETURN(barItemNode, nullptr);
528     auto accessibilityProperty = targetNode->GetAccessibilityProperty<AccessibilityProperty>();
529     CHECK_NULL_RETURN(accessibilityProperty, nullptr);
530     ImageSourceInfo imageSourceInfo;
531     std::string message;
532     RefPtr<FrameNode> dialogNode;
533     if (barItemNode->IsMoreItemNode()) {
534         auto theme = NavigationGetTheme();
535         CHECK_NULL_RETURN(theme, nullptr);
536         message = theme->GetMoreMessage();
537         if (message.empty()) {
538             message = accessibilityProperty->GetAccessibilityText();
539         }
540         if (AceApplicationInfo::GetInstance().GreatOrEqualTargetAPIVersion(PlatformVersion::VERSION_TWELVE)) {
541             auto symbolNode = AceType::DynamicCast<FrameNode>(barItemNode->GetFirstChild());
542             CHECK_NULL_RETURN(symbolNode, nullptr);
543             dialogNode = AgingAdapationDialogUtil::ShowLongPressDialog(message, symbolNode);
544             return dialogNode;
545         }
546         imageSourceInfo.SetResourceId(theme->GetMoreResourceId());
547         dialogNode = AgingAdapationDialogUtil::ShowLongPressDialog(message, imageSourceInfo, themeScopeId);
548         return dialogNode;
549     }
550     if (index < 0 || index >= static_cast<int32_t>(menuItems.size())) {
551         return nullptr;
552     }
553     auto menuItem = menuItems.at(index);
554     if (menuItem.text.has_value() && !menuItem.text.value().empty()) {
555         message = menuItem.text.value();
556     } else {
557         message = accessibilityProperty->GetAccessibilityText();
558     }
559     if (menuItem.iconSymbol.has_value() && menuItem.iconSymbol.value() != nullptr) {
560         return CreateSymbolDialog(message, barItemNode, themeScopeId);
561     }
562     if (menuItem.icon.has_value() && !menuItem.icon.value().empty()) {
563         imageSourceInfo = ImageSourceInfo(menuItem.icon.value());
564     }
565     dialogNode = AgingAdapationDialogUtil::ShowLongPressDialog(message, imageSourceInfo, themeScopeId);
566     return dialogNode;
567 }
568 
CreateSymbolDialog(const std::string & message,const RefPtr<FrameNode> & targetNode,int32_t themeScopeId)569 RefPtr<FrameNode> NavigationTitleUtil::CreateSymbolDialog(
570     const std::string& message, const RefPtr<FrameNode>& targetNode, int32_t themeScopeId)
571 {
572     auto barItemNode = AceType::DynamicCast<BarItemNode>(targetNode);
573     CHECK_NULL_RETURN(barItemNode, nullptr);
574     auto iconNode = AceType::DynamicCast<FrameNode>(barItemNode->GetIconNode());
575     CHECK_NULL_RETURN(iconNode, nullptr);
576     return AgingAdapationDialogUtil::ShowLongPressDialog(message, iconNode);
577 }
578 
SetAccessibility(const RefPtr<FrameNode> & node,const std::string & message)579 void NavigationTitleUtil::SetAccessibility(const RefPtr<FrameNode>& node, const std::string& message)
580 {
581     CHECK_NULL_VOID(node);
582     auto accessibilityProperty = node->GetAccessibilityProperty<NG::AccessibilityProperty>();
583     CHECK_NULL_VOID(accessibilityProperty);
584     accessibilityProperty->SetAccessibilityText(message);
585     accessibilityProperty->SetAccessibilityGroup(true);
586 }
587 
GetTitleString(const RefPtr<TitleBarNode> & titleBarNode,bool isCustom)588 std::string NavigationTitleUtil::GetTitleString(const RefPtr<TitleBarNode>& titleBarNode, bool isCustom)
589 {
590     if (isCustom) {
591         return "";
592     }
593     CHECK_NULL_RETURN(titleBarNode, "");
594     auto title = AceType::DynamicCast<FrameNode>(titleBarNode->GetTitle());
595     CHECK_NULL_RETURN(title, "");
596     if (title->GetTag() != V2::TEXT_ETS_TAG) {
597         return "";
598     }
599     auto textLayoutProperty = title->GetLayoutProperty<TextLayoutProperty>();
600     CHECK_NULL_RETURN(textLayoutProperty, "");
601     return UtfUtils::Str16ToStr8(textLayoutProperty->GetContentValue(u""));
602 }
603 
GetSubtitleString(const RefPtr<TitleBarNode> & titleBarNode)604 std::string NavigationTitleUtil::GetSubtitleString(const RefPtr<TitleBarNode>& titleBarNode)
605 {
606     CHECK_NULL_RETURN(titleBarNode, "");
607     auto subtitle = AceType::DynamicCast<FrameNode>(titleBarNode->GetSubtitle());
608     CHECK_NULL_RETURN(subtitle, "");
609     if (subtitle->GetTag() != V2::TEXT_ETS_TAG) {
610         return "";
611     }
612     auto textLayoutProperty = subtitle->GetLayoutProperty<TextLayoutProperty>();
613     CHECK_NULL_RETURN(textLayoutProperty, "");
614     return UtfUtils::Str16ToStr8(textLayoutProperty->GetContentValue(u""));
615 }
616 
ParseCalcDimensionToPx(const std::optional<CalcDimension> & value,const float titleBarWidth)617 float NavigationTitleUtil::ParseCalcDimensionToPx(const std::optional<CalcDimension>& value, const float titleBarWidth)
618 {
619     float result = 0.0f;
620     if (value.value().Unit() == DimensionUnit::PERCENT) {
621         result = value.value().Value() * titleBarWidth;
622     } else {
623         result = value.value().ConvertToPx();
624     }
625     return result;
626 }
627 
CreateOrUpdateMainTitle(const RefPtr<TitleBarNode> & titleBarNode,const NG::NavigationTitleInfo & titleInfo,bool ignoreMainTitle)628 void NavigationTitleUtil::CreateOrUpdateMainTitle(const RefPtr<TitleBarNode>& titleBarNode,
629     const NG::NavigationTitleInfo& titleInfo, bool ignoreMainTitle)
630 {
631     CHECK_NULL_VOID(titleBarNode);
632     if (ignoreMainTitle) {
633         return;
634     }
635     auto mainTitle = AceType::DynamicCast<FrameNode>(titleBarNode->GetTitle());
636     if (!titleInfo.hasMainTitle) {
637         // remove main title if any.
638         titleBarNode->RemoveChild(mainTitle);
639         titleBarNode->SetTitle(nullptr);
640         return;
641     }
642 
643     if (mainTitle) {
644         // update main title
645         auto textLayoutProperty = mainTitle->GetLayoutProperty<TextLayoutProperty>();
646         CHECK_NULL_VOID(textLayoutProperty);
647         textLayoutProperty->UpdateMaxLines(titleInfo.hasSubTitle ? 1 : TITLEBAR_MAX_LINES);
648         textLayoutProperty->UpdateContent(titleInfo.title);
649         return;
650     }
651     // create and init main title
652     mainTitle = FrameNode::CreateFrameNode(
653         V2::TEXT_ETS_TAG, ElementRegister::GetInstance()->MakeUniqueId(), AceType::MakeRefPtr<TextPattern>());
654     auto textLayoutProperty = mainTitle->GetLayoutProperty<TextLayoutProperty>();
655     CHECK_NULL_VOID(textLayoutProperty);
656     textLayoutProperty->UpdateContent(titleInfo.title);
657     auto titleBarPattern = titleBarNode->GetPattern<TitleBarPattern>();
658     CHECK_NULL_VOID(titleBarPattern);
659     titleBarPattern->SetNeedResetMainTitleProperty(true);
660     titleBarNode->SetTitle(mainTitle);
661     titleBarNode->AddChild(mainTitle);
662 }
663 
CreateOrUpdateSubtitle(const RefPtr<TitleBarNode> & titleBarNode,const NG::NavigationTitleInfo & titleInfo)664 void NavigationTitleUtil::CreateOrUpdateSubtitle(const RefPtr<TitleBarNode>& titleBarNode,
665     const NG::NavigationTitleInfo& titleInfo)
666 {
667     CHECK_NULL_VOID(titleBarNode);
668     auto subTitle = AceType::DynamicCast<FrameNode>(titleBarNode->GetSubtitle());
669     if (!titleInfo.hasSubTitle) {
670         // remove subtitle if any.
671         titleBarNode->RemoveChild(subTitle);
672         titleBarNode->SetSubtitle(nullptr);
673         return;
674     }
675     if (subTitle) {
676         // update subtitle
677         auto textLayoutProperty = subTitle->GetLayoutProperty<TextLayoutProperty>();
678         CHECK_NULL_VOID(textLayoutProperty);
679         textLayoutProperty->UpdateContent(titleInfo.subtitle);
680         auto renderContext = subTitle->GetRenderContext();
681         CHECK_NULL_VOID(renderContext);
682         renderContext->UpdateOpacity(1.0);
683         return;
684     }
685     // create and init subtitle
686     subTitle = FrameNode::CreateFrameNode(
687         V2::TEXT_ETS_TAG, ElementRegister::GetInstance()->MakeUniqueId(), AceType::MakeRefPtr<TextPattern>());
688     auto textLayoutProperty = subTitle->GetLayoutProperty<TextLayoutProperty>();
689     CHECK_NULL_VOID(textLayoutProperty);
690     textLayoutProperty->UpdateContent(titleInfo.subtitle);
691     auto titleBarPattern = titleBarNode->GetPattern<TitleBarPattern>();
692     CHECK_NULL_VOID(titleBarPattern);
693     titleBarPattern->SetNeedResetSubTitleProperty(true);
694     titleBarNode->SetSubtitle(subTitle);
695     titleBarNode->AddChild(subTitle);
696 }
697 
CreateOrUpdateDestinationMainTitle(const RefPtr<TitleBarNode> & titleBarNode,const NG::NavigationTitleInfo & titleInfo)698 void NavigationTitleUtil::CreateOrUpdateDestinationMainTitle(const RefPtr<TitleBarNode>& titleBarNode,
699     const NG::NavigationTitleInfo& titleInfo)
700 {
701     CHECK_NULL_VOID(titleBarNode);
702     auto mainTitle = AceType::DynamicCast<FrameNode>(titleBarNode->GetTitle());
703     if (!titleInfo.hasMainTitle) {
704         // remove main title if any.
705         titleBarNode->RemoveChild(mainTitle);
706         titleBarNode->SetTitle(nullptr);
707         return;
708     }
709     if (mainTitle) {
710         // update main title
711         auto textLayoutProperty = mainTitle->GetLayoutProperty<TextLayoutProperty>();
712         CHECK_NULL_VOID(textLayoutProperty);
713         textLayoutProperty->UpdateMaxLines(titleInfo.hasSubTitle ? 1 : TITLEBAR_MAX_LINES);
714         if (AceApplicationInfo::GetInstance().GreatOrEqualTargetAPIVersion(PlatformVersion::VERSION_TWELVE)) {
715             textLayoutProperty->UpdateHeightAdaptivePolicy(titleInfo.hasSubTitle ?
716             TextHeightAdaptivePolicy::MAX_LINES_FIRST : TextHeightAdaptivePolicy::MIN_FONT_SIZE_FIRST);
717         }
718         textLayoutProperty->UpdateContent(titleInfo.title);
719         textLayoutProperty->UpdateMaxFontScale(STANDARD_FONT_SCALE);
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 
CreateOrUpdateDestinationSubtitle(const RefPtr<TitleBarNode> & titleBarNode,const NG::NavigationTitleInfo & titleInfo)735 void NavigationTitleUtil::CreateOrUpdateDestinationSubtitle(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         textLayoutProperty->UpdateMaxFontScale(STANDARD_FONT_SCALE);
752         return;
753     }
754     // create and init subtitle
755     subTitle = FrameNode::CreateFrameNode(
756         V2::TEXT_ETS_TAG, ElementRegister::GetInstance()->MakeUniqueId(), AceType::MakeRefPtr<TextPattern>());
757     auto textLayoutProperty = subTitle->GetLayoutProperty<TextLayoutProperty>();
758     CHECK_NULL_VOID(textLayoutProperty);
759     textLayoutProperty->UpdateContent(titleInfo.subtitle);
760     auto titleBarPattern = titleBarNode->GetPattern<TitleBarPattern>();
761     CHECK_NULL_VOID(titleBarPattern);
762     titleBarPattern->SetNeedResetSubTitleProperty(true);
763     titleBarNode->SetSubtitle(subTitle);
764     titleBarNode->AddChild(subTitle);
765 }
766 
FoldStatusChangedAnimation(const RefPtr<FrameNode> & host)767 void NavigationTitleUtil::FoldStatusChangedAnimation(const RefPtr<FrameNode>& host)
768 {
769     CHECK_NULL_VOID(host);
770     auto pipelineContext = host->GetContext();
771     CHECK_NULL_VOID(pipelineContext);
772     auto titleBar = AceType::DynamicCast<TitleBarNode>(host);
773     CHECK_NULL_VOID(titleBar);
774     auto pattern = titleBar->GetPattern<TitleBarPattern>();
775     CHECK_NULL_VOID(pattern);
776 
777     if (!pipelineContext->IsHoverModeChange() || !IsNeedHoverModeAction(titleBar)) {
778         // Since only expanded to hover or hover to expanded need this animation.
779         return;
780     }
781 
782     AnimationOption option;
783     option.SetCurve(TITLEBAR_OPACITY_ANIMATION_CURVE);
784     auto renderNodeContext = host->GetRenderContext();
785     CHECK_NULL_VOID(renderNodeContext);
786     option.SetDuration(TITLEBAR_OPACITY_ANIMATION_DURATION);
787     renderNodeContext->UpdateOpacity(1.0f);
788     option.SetOnFinishEvent([weakRenderNodeContext = WeakPtr<RenderContext>(renderNodeContext),
789                                 weakHost = WeakPtr<FrameNode>(host)]() {
790         auto host = weakHost.Upgrade();
791         CHECK_NULL_VOID(host);
792         auto renderContext = weakRenderNodeContext.Upgrade();
793         CHECK_NULL_VOID(renderContext);
794         AnimationOption finishOption;
795         finishOption.SetDuration(TITLEBAR_OPACITY_ANIMATION_DURATION);
796         finishOption.SetCurve(TITLEBAR_OPACITY_ANIMATION_CURVE);
797         auto parent = AceType::DynamicCast<FrameNode>(host->GetParent());
798         CHECK_NULL_VOID(parent);
799         parent->MarkDirtyNode(PROPERTY_UPDATE_LAYOUT);
800         AnimationUtils::Animate(
801             finishOption, [weakRenderNodeContext = WeakPtr<RenderContext>(renderContext)]() {
802                 auto renderNodeContext = weakRenderNodeContext.Upgrade();
803                 CHECK_NULL_VOID(renderNodeContext);
804                 renderNodeContext->UpdateOpacity(1.0f);
805             }, nullptr /* finishCallback*/, nullptr /* repeatCallback */, host->GetContextRefPtr());
806     });
807     AnimationUtils::Animate(
808         option,
809         [weakRenderNodeContext = WeakPtr<RenderContext>(renderNodeContext)]() {
810             auto renderContext = weakRenderNodeContext.Upgrade();
811             CHECK_NULL_VOID(renderContext);
812             renderContext->UpdateOpacity(0.0f);
813         },
814         option.GetOnFinishEvent(), nullptr /* repeatCallback */, titleBar->GetContextRefPtr());
815 }
816 
IsNeedHoverModeAction(const RefPtr<TitleBarNode> & titleBarNode)817 bool NavigationTitleUtil::IsNeedHoverModeAction(const RefPtr<TitleBarNode>& titleBarNode)
818 {
819     CHECK_NULL_RETURN(titleBarNode, false);
820     auto pattern = titleBarNode->GetPattern<TitleBarPattern>();
821     CHECK_NULL_RETURN(pattern, false);
822     auto options = pattern->GetTitleBarOptions();
823     auto titleBarLayoutProperty = titleBarNode->GetLayoutProperty<TitleBarLayoutProperty>();
824     CHECK_NULL_RETURN(titleBarLayoutProperty, false);
825     auto parentType = titleBarLayoutProperty->GetTitleBarParentTypeValue(TitleBarParentType::NAVBAR);
826     if (parentType == TitleBarParentType::NAVBAR &&
827         titleBarLayoutProperty->GetTitleModeValue(NavigationTitleMode::MINI) == NavigationTitleMode::FREE) {
828         return false;
829     }
830     if (!options.enableHoverMode || options.brOptions.barStyle == NG::BarStyle::STANDARD) {
831         return false;
832     }
833     RefPtr<NavigationGroupNode> navigationGroupNode;
834     if (parentType == TitleBarParentType::NAVBAR) {
835         auto navBarNode = AceType::DynamicCast<NavBarNode>(titleBarNode->GetParent());
836         CHECK_NULL_RETURN(navBarNode, false);
837         navigationGroupNode = AceType::DynamicCast<NavigationGroupNode>(navBarNode->GetParent());
838     } else {
839         auto navDestination = AceType::DynamicCast<NavDestinationGroupNode>(titleBarNode->GetParent());
840         CHECK_NULL_RETURN(navDestination, false);
841         auto navDestinationPattern = navDestination->GetPattern<NavDestinationPattern>();
842         CHECK_NULL_RETURN(navDestinationPattern, false);
843         navigationGroupNode = AceType::DynamicCast<NavigationGroupNode>(navDestinationPattern->GetNavigationNode());
844     }
845     CHECK_NULL_RETURN(navigationGroupNode, false);
846     auto navigationPattern = AceType::DynamicCast<NavigationPattern>(navigationGroupNode->GetPattern());
847     CHECK_NULL_RETURN(navigationPattern, false);
848     auto pageNode = navigationPattern->GetNavBasePageNode();
849     CHECK_NULL_RETURN(pageNode, false);
850     auto foldCreaseRects = pattern->GetFoldCreaseRects();
851     auto parentNode = AceType::DynamicCast<FrameNode>(titleBarNode->GetParent());
852     CHECK_NULL_RETURN(parentNode, false);
853     bool isParentFullPage = pageNode->GetGeometryNode()->GetFrameSize().Height()
854         == parentNode->GetGeometryNode()->GetFrameSize().Height();
855     return !foldCreaseRects.empty() && isParentFullPage;
856 }
857 
CalculateTitlebarOffset(const RefPtr<UINode> & titleBarNode)858 float NavigationTitleUtil::CalculateTitlebarOffset(const RefPtr<UINode>& titleBarNode)
859 {
860     CHECK_NULL_RETURN(titleBarNode, 0.0f);
861     auto titleBar = AceType::DynamicCast<TitleBarNode>(titleBarNode);
862     CHECK_NULL_RETURN(titleBar, 0.0f);
863     if (!IsNeedHoverModeAction(titleBar)) {
864         return 0.0f;
865     }
866     auto pattern = titleBar->GetPattern<TitleBarPattern>();
867     CHECK_NULL_RETURN(pattern, false);
868     auto foldCreaseRects = pattern->GetFoldCreaseRects();
869     auto pipelineContext = titleBar->GetContext();
870     CHECK_NULL_RETURN(pipelineContext, 0.0f);
871     if (!pipelineContext->IsHalfFoldHoverStatus()) {
872         return 0.0f;
873     }
874     auto safeArea = pipelineContext->GetSafeAreaWithoutProcess();
875     auto length = safeArea.top_.Length();
876     auto foldCrease = foldCreaseRects.front();
877 
878     // offsetY = The Y of the foldCrease + Adapt vertical displacement of hover state - the height of the status bar.
879     return foldCrease.GetOffset().GetY() + TITLEBAR_VERTICAL_PADDING.ConvertToPx() - length;
880 }
881 
UpdateTitleOrToolBarTranslateYAndOpacity(const RefPtr<NavDestinationNodeBase> & nodeBase,const RefPtr<FrameNode> & barNode,float translate,bool isTitle)882 void NavigationTitleUtil::UpdateTitleOrToolBarTranslateYAndOpacity(const RefPtr<NavDestinationNodeBase>& nodeBase,
883     const RefPtr<FrameNode>& barNode, float translate, bool isTitle)
884 {
885     CHECK_NULL_VOID(nodeBase);
886     CHECK_NULL_VOID(barNode);
887     auto renderContext = barNode->GetRenderContext();
888     CHECK_NULL_VOID(renderContext);
889     auto option = renderContext->GetTransformTranslateValue(TranslateOptions(0.0f, 0.0f, 0.0f));
890     option.y = CalcDimension(translate, DimensionUnit::PX);
891     renderContext->UpdateTransformTranslate(option);
892     auto barHeight = renderContext->GetPaintRectWithoutTransform().Height();
893     float opacity = 1.0f;
894     if (!NearZero(barHeight)) {
895         opacity = 1.0f - std::clamp(std::abs(translate) / barHeight, 0.0f, 1.0f);
896     }
897     renderContext->UpdateOpacity(opacity);
898     if (isTitle) {
899         return;
900     }
901     auto divider = AceType::DynamicCast<FrameNode>(nodeBase->GetToolBarDividerNode());
902     CHECK_NULL_VOID(divider);
903     auto dividerRenderContext = divider->GetRenderContext();
904     CHECK_NULL_VOID(dividerRenderContext);
905     dividerRenderContext->UpdateTransformTranslate(option);
906     dividerRenderContext->UpdateOpacity(opacity);
907 }
908 
IsTitleBarHasOffsetY(const RefPtr<FrameNode> & titleBarNode)909 bool NavigationTitleUtil::IsTitleBarHasOffsetY(const RefPtr<FrameNode>& titleBarNode)
910 {
911     return titleBarNode && titleBarNode->IsVisible() && !NearZero(CalculateTitlebarOffset(titleBarNode));
912 }
913 
SetTitleAnimationElapsedTime(AnimationOption & option,const RefPtr<FrameNode> & pushEnterNode)914 bool NavigationTitleUtil::SetTitleAnimationElapsedTime(AnimationOption& option, const RefPtr<FrameNode>& pushEnterNode)
915 {
916     auto pushEnterNavDestination = AceType::DynamicCast<NavDestinationGroupNode>(pushEnterNode);
917     CHECK_NULL_RETURN(pushEnterNavDestination, false);
918     if (pushEnterNavDestination->IsTitleConsumedElapsedTime() ||
919         pushEnterNavDestination->GetSystemTransitionType() != NavigationSystemTransitionType::TITLE) {
920         return false;
921     }
922     auto elapsedTime = pushEnterNavDestination->GetTitleAnimationElapsedTime();
923     if (elapsedTime <= 0 || elapsedTime > DEFAULT_ANIMATION_DURATION) {
924         return false;
925     }
926     TAG_LOGI(AceLogTag::ACE_NAVIGATION,
927         "will skip %{public}d ms animation for enter push NavDestination node", elapsedTime);
928     // elapsed time is the TIME to skip
929     option.SetDelay(option.GetDelay() - elapsedTime);
930     pushEnterNavDestination->MarkTitleConsumedElapsedTime();
931     return true;
932 }
933 } // namespace OHOS::Ace::NG
934