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