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