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