1 /*
2 * Copyright (c) 2022 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_view.h"
17
18 #include <cstdint>
19 #include <iterator>
20
21 #include "base/memory/ace_type.h"
22 #include "base/memory/referenced.h"
23 #include "base/utils/utils.h"
24 #include "core/components_ng/base/frame_node.h"
25 #include "core/components_ng/base/view_stack_processor.h"
26 #include "core/components_ng/pattern/button/button_layout_property.h"
27 #include "core/components_ng/pattern/button/button_pattern.h"
28 #include "core/components_ng/pattern/custom/custom_node.h"
29 #include "core/components_ng/pattern/divider/divider_layout_property.h"
30 #include "core/components_ng/pattern/divider/divider_pattern.h"
31 #include "core/components_ng/pattern/divider/divider_render_property.h"
32 #include "core/components_ng/pattern/image/image_layout_property.h"
33 #include "core/components_ng/pattern/image/image_pattern.h"
34 #include "core/components_ng/pattern/linear_layout/linear_layout_pattern.h"
35 #include "core/components_ng/pattern/menu/menu_view.h"
36 #include "core/components_ng/pattern/navigation/bar_item_event_hub.h"
37 #include "core/components_ng/pattern/navigation/bar_item_node.h"
38 #include "core/components_ng/pattern/navigation/bar_item_pattern.h"
39 #include "core/components_ng/pattern/navigation/nav_bar_layout_property.h"
40 #include "core/components_ng/pattern/navigation/nav_bar_node.h"
41 #include "core/components_ng/pattern/navigation/nav_bar_pattern.h"
42 #include "core/components_ng/pattern/navigation/navigation_declaration.h"
43 #include "core/components_ng/pattern/navigation/navigation_group_node.h"
44 #include "core/components_ng/pattern/navigation/navigation_layout_property.h"
45 #include "core/components_ng/pattern/navigation/navigation_pattern.h"
46 #include "core/components_ng/pattern/navigation/title_bar_node.h"
47 #include "core/components_ng/pattern/navigation/title_bar_pattern.h"
48 #include "core/components_ng/pattern/navigator/navigator_event_hub.h"
49 #include "core/components_ng/pattern/navigator/navigator_pattern.h"
50 #include "core/components_ng/pattern/navrouter/navdestination_group_node.h"
51 #include "core/components_ng/pattern/navrouter/navdestination_layout_property.h"
52 #include "core/components_ng/pattern/navrouter/navrouter_group_node.h"
53 #include "core/components_ng/pattern/option/option_view.h"
54 #include "core/components_ng/pattern/select/select_view.h"
55 #include "core/components_ng/pattern/text/text_layout_property.h"
56 #include "core/components_ng/pattern/text/text_pattern.h"
57 #include "core/components_v2/inspector/inspector_constants.h"
58 #include "core/pipeline/base/element_register.h"
59 #include "core/pipeline_ng/ui_task_scheduler.h"
60
61 namespace OHOS::Ace::NG {
62 namespace {
63
CreateBarItemTextNode(const std::string & text)64 RefPtr<FrameNode> CreateBarItemTextNode(const std::string& text)
65 {
66 int32_t nodeId = ElementRegister::GetInstance()->MakeUniqueId();
67 auto textNode = FrameNode::CreateFrameNode(V2::TEXT_ETS_TAG, nodeId, AceType::MakeRefPtr<TextPattern>());
68 auto textLayoutProperty = textNode->GetLayoutProperty<TextLayoutProperty>();
69 CHECK_NULL_RETURN(textLayoutProperty, nullptr);
70 textLayoutProperty->UpdateContent(text);
71 textLayoutProperty->UpdateFontSize(TEXT_FONT_SIZE);
72 textLayoutProperty->UpdateTextColor(TEXT_COLOR);
73 textLayoutProperty->UpdateTextAlign(TextAlign::CENTER);
74 return textNode;
75 }
76
CreateBarItemIconNode(const std::string & src)77 RefPtr<FrameNode> CreateBarItemIconNode(const std::string& src)
78 {
79 int32_t nodeId = ElementRegister::GetInstance()->MakeUniqueId();
80 ImageSourceInfo info(src);
81 auto iconNode = FrameNode::CreateFrameNode(V2::IMAGE_ETS_TAG, nodeId, AceType::MakeRefPtr<ImagePattern>());
82 auto imageLayoutProperty = iconNode->GetLayoutProperty<ImageLayoutProperty>();
83 CHECK_NULL_RETURN(imageLayoutProperty, nullptr);
84 auto theme = NavigationGetTheme();
85 CHECK_NULL_RETURN(theme, nullptr);
86
87 auto frameNode = ViewStackProcessor::GetInstance()->GetMainFrameNode();
88 auto navigationGroupNode = AceType::DynamicCast<NavigationGroupNode>(frameNode);
89 CHECK_NULL_RETURN(navigationGroupNode, nullptr);
90 auto hub = navigationGroupNode->GetEventHub<EventHub>();
91 CHECK_NULL_RETURN(hub, nullptr);
92 if (!hub->IsEnabled()) {
93 info.SetFillColor(theme->GetMenuIconColor().BlendOpacity(theme->GetAlphaDisabled()));
94 } else {
95 info.SetFillColor(theme->GetMenuIconColor());
96 }
97 imageLayoutProperty->UpdateImageSourceInfo(info);
98 auto iconSize = theme->GetMenuIconSize();
99 imageLayoutProperty->UpdateUserDefinedIdealSize(CalcSize(CalcLength(iconSize), CalcLength(iconSize)));
100 iconNode->MarkModifyDone();
101 return iconNode;
102 }
103
UpdateBarItemNodeWithItem(const RefPtr<BarItemNode> & barItemNode,const BarItem & barItem)104 void UpdateBarItemNodeWithItem(const RefPtr<BarItemNode>& barItemNode, const BarItem& barItem)
105 {
106 if (barItem.text.has_value() && !barItem.text.value().empty()) {
107 auto textNode = CreateBarItemTextNode(barItem.text.value());
108 barItemNode->SetTextNode(textNode);
109 barItemNode->AddChild(textNode);
110 }
111 if (barItem.icon.has_value() && !barItem.icon.value().empty()) {
112 auto iconNode = CreateBarItemIconNode(barItem.icon.value());
113 barItemNode->SetIconNode(iconNode);
114 barItemNode->AddChild(iconNode);
115 }
116 if (barItem.action) {
117 auto eventHub = barItemNode->GetEventHub<BarItemEventHub>();
118 CHECK_NULL_VOID(eventHub);
119 eventHub->SetItemAction(barItem.action);
120 }
121 auto barItemPattern = barItemNode->GetPattern<BarItemPattern>();
122 barItemNode->MarkModifyDone();
123 }
124
BuildMoreIemNode(const RefPtr<BarItemNode> & barItemNode)125 void BuildMoreIemNode(const RefPtr<BarItemNode>& barItemNode)
126 {
127 int32_t imageNodeId = ElementRegister::GetInstance()->MakeUniqueId();
128 auto imageNode = FrameNode::CreateFrameNode(V2::IMAGE_ETS_TAG, imageNodeId, AceType::MakeRefPtr<ImagePattern>());
129 auto imageLayoutProperty = imageNode->GetLayoutProperty<ImageLayoutProperty>();
130 CHECK_NULL_VOID(imageLayoutProperty);
131 auto theme = NavigationGetTheme();
132 CHECK_NULL_VOID(theme);
133
134 auto frameNode = ViewStackProcessor::GetInstance()->GetMainFrameNode();
135 auto navigationGroupNode = AceType::DynamicCast<NavigationGroupNode>(frameNode);
136 CHECK_NULL_VOID(navigationGroupNode);
137 auto hub = navigationGroupNode->GetEventHub<EventHub>();
138 CHECK_NULL_VOID(hub);
139 auto info = ImageSourceInfo("");
140 info.SetResourceId(theme->GetMoreResourceId());
141 if (!hub->IsEnabled()) {
142 info.SetFillColor(theme->GetMenuIconColor().BlendOpacity(theme->GetAlphaDisabled()));
143 } else {
144 info.SetFillColor(theme->GetMenuIconColor());
145 }
146 imageLayoutProperty->UpdateImageSourceInfo(info);
147
148 auto iconSize = theme->GetMenuIconSize();
149 imageLayoutProperty->UpdateUserDefinedIdealSize(CalcSize(CalcLength(iconSize), CalcLength(iconSize)));
150 imageNode->MarkModifyDone();
151
152 barItemNode->SetIconNode(imageNode);
153 barItemNode->AddChild(imageNode);
154 barItemNode->MarkModifyDone();
155 }
156
BuildMoreItemNodeAction(const RefPtr<BarItemNode> & barItemNode,const RefPtr<FrameNode> & barMenuNode)157 void BuildMoreItemNodeAction(const RefPtr<BarItemNode>& barItemNode, const RefPtr<FrameNode>& barMenuNode)
158 {
159 auto eventHub = barItemNode->GetEventHub<BarItemEventHub>();
160 CHECK_NULL_VOID(eventHub);
161
162 auto context = PipelineContext::GetCurrentContext();
163 auto clickCallback = [weakContext = AceType::WeakClaim(AceType::RawPtr(context)), id = barItemNode->GetId(),
164 weakMenu = AceType::WeakClaim(AceType::RawPtr(barMenuNode)),
165 weakBarItemNode = AceType::WeakClaim(AceType::RawPtr(barItemNode))]() {
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
175 auto barItemNode = weakBarItemNode.Upgrade();
176 CHECK_NULL_VOID(barItemNode);
177
178 auto imageNode = barItemNode->GetChildAtIndex(0);
179 CHECK_NULL_VOID(imageNode);
180
181 auto imageFrameNode = AceType::DynamicCast<FrameNode>(imageNode);
182 CHECK_NULL_VOID(imageFrameNode);
183 auto imgOffset = imageFrameNode->GetOffsetRelativeToWindow();
184 auto imageSize = imageFrameNode->GetGeometryNode()->GetFrameSize();
185
186 imgOffset.SetX(imgOffset.GetX() + imageSize.Width());
187 imgOffset.SetY(imgOffset.GetY() + imageSize.Height() + static_cast<float>(MENU_AND_BUTTON_SPACE.ConvertToPx()));
188 overlayManager->ShowMenu(id, imgOffset, menu);
189 };
190 eventHub->SetItemAction(clickCallback);
191 }
192
UpdateOldBarItems(const RefPtr<UINode> & oldBarContainer,const std::vector<BarItem> & newBarItems)193 void UpdateOldBarItems(const RefPtr<UINode>& oldBarContainer, const std::vector<BarItem>& newBarItems)
194 {
195 auto oldBarItems = oldBarContainer->GetChildren();
196 auto prevChildrenSize = static_cast<int32_t>(oldBarItems.size());
197 auto newChildrenSize = static_cast<int32_t>(newBarItems.size());
198 auto oldIter = oldBarItems.begin();
199 auto newIter = newBarItems.begin();
200 // if old container has m items and incoming array has n items
201 // we update first min(m, n) items in the old container
202 for (int32_t i = 0; i < std::min(prevChildrenSize, newChildrenSize); i++) {
203 do {
204 auto oldBarItem = AceType::DynamicCast<BarItemNode>(*oldIter);
205 BarItem newBarItem = *newIter;
206 if (!oldBarItem) {
207 break;
208 }
209 // TODO: fix error for update condition when add or delete child, and update old bar item will not work
210 if (newBarItem.text.has_value()) {
211 oldBarItem->UpdateText(newBarItem.text.value());
212 if (oldBarItem->GetTextNode()) {
213 auto textNode = AceType::DynamicCast<FrameNode>(oldBarItem->GetTextNode());
214 CHECK_NULL_VOID(textNode);
215 auto textLayoutProperty = textNode->GetLayoutProperty<TextLayoutProperty>();
216 CHECK_NULL_VOID(textLayoutProperty);
217 textLayoutProperty->UpdateContent(newBarItem.text.value());
218 textNode->MarkModifyDone();
219 } else {
220 auto textNode = CreateBarItemTextNode(newBarItem.text.value());
221 oldBarItem->SetTextNode(textNode);
222 oldBarItem->AddChild(textNode);
223 oldBarItem->MarkModifyDone();
224 }
225 } else {
226 oldBarItem->ResetText();
227 if (oldBarItem->GetTextNode()) {
228 auto textNode = AceType::DynamicCast<FrameNode>(oldBarItem->GetTextNode());
229 CHECK_NULL_VOID(textNode);
230 oldBarItem->RemoveChild(textNode);
231 }
232 }
233 if (newBarItem.icon.has_value()) {
234 oldBarItem->UpdateIconSrc(newBarItem.icon.value());
235 if (oldBarItem->GetIconNode()) {
236 auto iconNode = AceType::DynamicCast<FrameNode>(oldBarItem->GetIconNode());
237 CHECK_NULL_VOID(iconNode);
238 auto imageLayoutProperty = iconNode->GetLayoutProperty<ImageLayoutProperty>();
239 CHECK_NULL_VOID(imageLayoutProperty);
240 imageLayoutProperty->UpdateImageSourceInfo(ImageSourceInfo(newBarItem.icon.value()));
241 iconNode->MarkModifyDone();
242 } else {
243 auto iconNode = CreateBarItemIconNode(newBarItem.icon.value());
244 oldBarItem->SetIconNode(iconNode);
245 oldBarItem->AddChild(iconNode);
246 oldBarItem->MarkModifyDone();
247 }
248 } else {
249 oldBarItem->ResetIconSrc();
250 if (oldBarItem->GetIconNode()) {
251 auto iconNode = AceType::DynamicCast<FrameNode>(oldBarItem->GetIconNode());
252 CHECK_NULL_VOID(iconNode);
253 oldBarItem->RemoveChild(iconNode);
254 }
255 }
256 } while (false);
257 oldIter++;
258 newIter++;
259 }
260 // if m > n, we remove (m - n) children from the back of old container
261 if (prevChildrenSize > newChildrenSize) {
262 for (int32_t i = 0; i < prevChildrenSize - newChildrenSize; i++) {
263 oldBarContainer->RemoveChild(oldBarItems.back());
264 oldBarItems.pop_back();
265 }
266 } else if (prevChildrenSize < newChildrenSize) {
267 // if m < n, we add (n - m) children created by info in new item list
268 for (int32_t i = 0; i < newChildrenSize - prevChildrenSize; i++) {
269 auto nodeId = ElementRegister::GetInstance()->MakeUniqueId();
270 auto barItemNode = AceType::MakeRefPtr<BarItemNode>(V2::BAR_ITEM_ETS_TAG, nodeId);
271 barItemNode->InitializePatternAndContext();
272 UpdateBarItemNodeWithItem(barItemNode, *newIter);
273 oldBarContainer->AddChild(barItemNode);
274 newIter++;
275 }
276 }
277 auto container = AceType::DynamicCast<TitleBarNode>(oldBarContainer);
278 CHECK_NULL_VOID(container);
279 container->MarkModifyDone();
280 }
281 } // namespace
282
Create()283 void NavigationView::Create()
284 {
285 auto* stack = ViewStackProcessor::GetInstance();
286 // navigation node
287 int32_t nodeId = stack->ClaimNodeId();
288 auto navigationGroupNode = NavigationGroupNode::GetOrCreateGroupNode(
289 V2::NAVIGATION_VIEW_ETS_TAG, nodeId, []() { return AceType::MakeRefPtr<NavigationPattern>(); });
290
291 // navBar node
292 if (!navigationGroupNode->GetNavBarNode()) {
293 int32_t navBarNodeId = ElementRegister::GetInstance()->MakeUniqueId();
294 auto navBarNode = NavBarNode::GetOrCreateNavBarNode(
295 V2::NAVBAR_ETS_TAG, navBarNodeId, []() { return AceType::MakeRefPtr<NavBarPattern>(); });
296 navigationGroupNode->AddChild(navBarNode);
297 navigationGroupNode->SetNavBarNode(navBarNode);
298
299 // titleBar node
300 if (!navBarNode->GetTitleBarNode()) {
301 int32_t titleBarNodeId = ElementRegister::GetInstance()->MakeUniqueId();
302 auto titleBarNode = TitleBarNode::GetOrCreateTitleBarNode(
303 V2::TITLE_BAR_ETS_TAG, titleBarNodeId, []() { return AceType::MakeRefPtr<TitleBarPattern>(); });
304 navBarNode->AddChild(titleBarNode);
305 navBarNode->SetTitleBarNode(titleBarNode);
306 }
307
308 // navBar content node
309 if (!navBarNode->GetNavBarContentNode()) {
310 int32_t navBarContentNodeId = ElementRegister::GetInstance()->MakeUniqueId();
311 auto navBarContentNode = FrameNode::GetOrCreateFrameNode(V2::NAVBAR_CONTENT_ETS_TAG, navBarContentNodeId,
312 []() { return AceType::MakeRefPtr<LinearLayoutPattern>(true); });
313 navBarNode->AddChild(navBarContentNode);
314 navBarNode->SetNavBarContentNode(navBarContentNode);
315 }
316
317 // toolBar node
318 if (!navBarNode->GetToolBarNode()) {
319 int32_t toolBarNodeId = ElementRegister::GetInstance()->MakeUniqueId();
320 auto toolBarNode = FrameNode::GetOrCreateFrameNode(
321 V2::TOOL_BAR_ETS_TAG, toolBarNodeId, []() { return AceType::MakeRefPtr<LinearLayoutPattern>(false); });
322 navBarNode->AddChild(toolBarNode);
323 navBarNode->SetToolBarNode(toolBarNode);
324 navBarNode->SetPreToolBarNode(toolBarNode);
325 navBarNode->UpdatePrevToolBarIsCustom(false);
326 }
327 auto navBarLayoutProperty = navBarNode->GetLayoutProperty<NavBarLayoutProperty>();
328 CHECK_NULL_VOID(navBarLayoutProperty);
329 navBarLayoutProperty->UpdateTitleMode(NavigationTitleMode::FREE);
330 }
331
332 // content node
333 if (!navigationGroupNode->GetContentNode()) {
334 int32_t contentNodeId = ElementRegister::GetInstance()->MakeUniqueId();
335 auto contentNode = FrameNode::GetOrCreateFrameNode(V2::NAVIGATION_CONTENT_ETS_TAG, contentNodeId,
336 []() { return AceType::MakeRefPtr<LinearLayoutPattern>(true); });
337 navigationGroupNode->AddChild(contentNode);
338 navigationGroupNode->SetContentNode(contentNode);
339
340 auto context = contentNode->GetRenderContext();
341 CHECK_NULL_VOID(context);
342 context->UpdateBackgroundColor(CONTENT_COLOR);
343 }
344
345 // divider node
346 if (!navigationGroupNode->GetDividerNode()) {
347 int32_t dividerNodeId = ElementRegister::GetInstance()->MakeUniqueId();
348 auto dividerNode = FrameNode::GetOrCreateFrameNode(
349 V2::DIVIDER_ETS_TAG, dividerNodeId, []() { return AceType::MakeRefPtr<DividerPattern>(); });
350 navigationGroupNode->AddChild(dividerNode);
351 navigationGroupNode->SetDividerNode(dividerNode);
352
353 auto dividerLayoutProperty = dividerNode->GetLayoutProperty<DividerLayoutProperty>();
354 CHECK_NULL_VOID(dividerLayoutProperty);
355 dividerLayoutProperty->UpdateStrokeWidth(DIVIDER_WIDTH);
356 dividerLayoutProperty->UpdateVertical(true);
357 auto dividerRenderProperty = dividerNode->GetPaintProperty<DividerRenderProperty>();
358 CHECK_NULL_VOID(dividerRenderProperty);
359 dividerRenderProperty->UpdateDividerColor(DIVIDER_COLOR);
360 }
361
362 stack->Push(navigationGroupNode);
363 auto navigationLayoutProperty = navigationGroupNode->GetLayoutProperty<NavigationLayoutProperty>();
364 navigationLayoutProperty->UpdateNavigationMode(NavigationMode::AUTO);
365 navigationLayoutProperty->UpdateNavBarWidth(DEFAULT_NAV_BAR_WIDTH);
366 }
367
SetTitle(const std::string & title,bool hasSubTitle)368 void NavigationView::SetTitle(const std::string& title, bool hasSubTitle)
369 {
370 auto frameNode = ViewStackProcessor::GetInstance()->GetMainFrameNode();
371 auto navigationGroupNode = AceType::DynamicCast<NavigationGroupNode>(frameNode);
372 CHECK_NULL_VOID(navigationGroupNode);
373 auto navBarNode = AceType::DynamicCast<NavBarNode>(navigationGroupNode->GetNavBarNode());
374 CHECK_NULL_VOID(navBarNode);
375 do {
376 if (!navBarNode->GetTitle()) {
377 navBarNode->UpdateTitleNodeOperation(ChildNodeOperation::ADD);
378 break;
379 }
380 // if previous title is not a frame node, we remove it and create a new node
381 auto titleNode = AceType::DynamicCast<FrameNode>(navBarNode->GetTitle());
382 if (!titleNode) {
383 navBarNode->UpdateTitleNodeOperation(ChildNodeOperation::REPLACE);
384 break;
385 }
386 auto titleProperty = titleNode->GetLayoutProperty<TextLayoutProperty>();
387 // if no subtitle, title's maxLine = 1. if has subtitle, title's maxLine = 2.
388 if (!hasSubTitle && navBarNode->GetSubtitle()) {
389 navBarNode->SetSubtitle(nullptr);
390 titleProperty->UpdateMaxLines(1);
391 } else {
392 titleProperty->UpdateMaxLines(2);
393 }
394 // previous title is not a text node and might be custom, we remove it and create a new node
395 if (!titleProperty) {
396 navBarNode->UpdateTitleNodeOperation(ChildNodeOperation::REPLACE);
397 break;
398 }
399 // text content is the same, do nothing
400 if (titleProperty->GetContentValue() == title) {
401 navBarNode->UpdateTitleNodeOperation(ChildNodeOperation::NONE);
402 return;
403 }
404 // update title content only without changing node
405 titleProperty->UpdateContent(title);
406 navBarNode->UpdateTitleNodeOperation(ChildNodeOperation::NONE);
407 navBarNode->MarkDirtyNode(PROPERTY_UPDATE_MEASURE);
408 return;
409 } while (false);
410 int32_t titleNodeId = ElementRegister::GetInstance()->MakeUniqueId();
411 auto titleNode = FrameNode::CreateFrameNode(V2::TEXT_ETS_TAG, titleNodeId, AceType::MakeRefPtr<TextPattern>());
412 auto textLayoutProperty = titleNode->GetLayoutProperty<TextLayoutProperty>();
413 CHECK_NULL_VOID(textLayoutProperty);
414 textLayoutProperty->UpdateContent(title);
415
416 auto theme = NavigationGetTheme();
417 CHECK_NULL_VOID(theme);
418 auto navBarLayoutProperty = navBarNode->GetLayoutProperty<NavBarLayoutProperty>();
419 CHECK_NULL_VOID(navBarLayoutProperty);
420 if (navBarLayoutProperty->GetTitleModeValue(NavigationTitleMode::FREE) == NavigationTitleMode::MINI) {
421 textLayoutProperty->UpdateFontSize(theme->GetTitleFontSize());
422 } else {
423 textLayoutProperty->UpdateFontSize(theme->GetTitleFontSizeBig());
424 }
425 textLayoutProperty->UpdateTextColor(theme->GetTitleColor());
426 textLayoutProperty->UpdateFontWeight(FontWeight::MEDIUM);
427 if (!hasSubTitle) {
428 textLayoutProperty->UpdateMaxLines(1);
429 } else {
430 textLayoutProperty->UpdateMaxLines(2);
431 }
432 textLayoutProperty->UpdateTextOverflow(TextOverflow::ELLIPSIS);
433 navBarNode->SetTitle(titleNode);
434 navBarNode->UpdatePrevTitleIsCustom(false);
435 }
436
SetCustomTitle(const RefPtr<UINode> & customTitle)437 void NavigationView::SetCustomTitle(const RefPtr<UINode>& customTitle)
438 {
439 CHECK_NULL_VOID(customTitle);
440 auto frameNode = ViewStackProcessor::GetInstance()->GetMainFrameNode();
441 auto navigationGroupNode = AceType::DynamicCast<NavigationGroupNode>(frameNode);
442 CHECK_NULL_VOID(navigationGroupNode);
443 auto navBarNode = AceType::DynamicCast<NavBarNode>(navigationGroupNode->GetNavBarNode());
444 CHECK_NULL_VOID(navBarNode);
445 if (navBarNode->GetTitle()) {
446 if (customTitle->GetId() == navBarNode->GetTitle()->GetId()) {
447 navBarNode->UpdateTitleNodeOperation(ChildNodeOperation::NONE);
448 } else {
449 navBarNode->SetTitle(customTitle);
450 navBarNode->UpdateTitleNodeOperation(ChildNodeOperation::REPLACE);
451 navBarNode->MarkDirtyNode(PROPERTY_UPDATE_MEASURE);
452 }
453 return;
454 }
455 navBarNode->SetTitle(customTitle);
456 navBarNode->UpdateTitleNodeOperation(ChildNodeOperation::ADD);
457 navBarNode->UpdatePrevTitleIsCustom(true);
458 }
459
SetSubtitle(const std::string & subtitle)460 void NavigationView::SetSubtitle(const std::string& subtitle)
461 {
462 auto frameNode = ViewStackProcessor::GetInstance()->GetMainFrameNode();
463 auto navigationGroupNode = AceType::DynamicCast<NavigationGroupNode>(frameNode);
464 CHECK_NULL_VOID(navigationGroupNode);
465 auto navBarNode = AceType::DynamicCast<NavBarNode>(navigationGroupNode->GetNavBarNode());
466 CHECK_NULL_VOID(navBarNode);
467 do {
468 if (!navBarNode->GetSubtitle()) {
469 navBarNode->UpdateSubtitleNodeOperation(ChildNodeOperation::ADD);
470 break;
471 }
472 auto subtitleNode = AceType::DynamicCast<FrameNode>(navBarNode->GetSubtitle());
473 if (!subtitleNode) {
474 navBarNode->UpdateSubtitleNodeOperation(ChildNodeOperation::REPLACE);
475 break;
476 }
477 auto subtitleProperty = subtitleNode->GetLayoutProperty<TextLayoutProperty>();
478 if (!subtitleProperty) {
479 navBarNode->UpdateSubtitleNodeOperation(ChildNodeOperation::REPLACE);
480 break;
481 }
482 if (subtitleProperty->GetContentValue() == subtitle) {
483 navBarNode->UpdateSubtitleNodeOperation(ChildNodeOperation::NONE);
484 return;
485 }
486 subtitleProperty->UpdateContent(subtitle);
487 navBarNode->UpdateSubtitleNodeOperation(ChildNodeOperation::NONE);
488 navBarNode->MarkDirtyNode(PROPERTY_UPDATE_MEASURE);
489 return;
490 } while (false);
491 int32_t subtitleNodeId = ElementRegister::GetInstance()->MakeUniqueId();
492 auto subtitleNode =
493 FrameNode::CreateFrameNode(V2::TEXT_ETS_TAG, subtitleNodeId, AceType::MakeRefPtr<TextPattern>());
494 auto textLayoutProperty = subtitleNode->GetLayoutProperty<TextLayoutProperty>();
495 CHECK_NULL_VOID(textLayoutProperty);
496 textLayoutProperty->UpdateContent(subtitle);
497 textLayoutProperty->UpdateFontSize(SUBTITLE_FONT_SIZE);
498 textLayoutProperty->UpdateTextColor(SUBTITLE_COLOR);
499 textLayoutProperty->UpdateFontWeight(FontWeight::REGULAR); // ohos_id_text_font_family_regular
500 textLayoutProperty->UpdateMaxLines(1);
501 textLayoutProperty->UpdateTextOverflow(TextOverflow::ELLIPSIS);
502 navBarNode->SetSubtitle(subtitleNode);
503 }
504
SetMenuItems(std::vector<BarItem> && menuItems)505 void NavigationView::SetMenuItems(std::vector<BarItem>&& menuItems)
506 {
507 auto frameNode = ViewStackProcessor::GetInstance()->GetMainFrameNode();
508 auto navigationGroupNode = AceType::DynamicCast<NavigationGroupNode>(frameNode);
509 CHECK_NULL_VOID(navigationGroupNode);
510 auto navBarNode = AceType::DynamicCast<NavBarNode>(navigationGroupNode->GetNavBarNode());
511 CHECK_NULL_VOID(navBarNode);
512 // if previous menu is custom, just remove it and create new menu, otherwise update old menu
513 if (navBarNode->GetPrevMenuIsCustom().value_or(false)) {
514 navBarNode->UpdateMenuNodeOperation(ChildNodeOperation::REPLACE);
515 } else {
516 if (navBarNode->GetMenu()) {
517 navBarNode->UpdateMenuNodeOperation(ChildNodeOperation::REPLACE);
518 } else {
519 navBarNode->UpdateMenuNodeOperation(ChildNodeOperation::ADD);
520 }
521 }
522 int32_t menuNodeId = ElementRegister::GetInstance()->MakeUniqueId();
523 auto menuNode = FrameNode::GetOrCreateFrameNode(
524 V2::NAVIGATION_MENU_ETS_TAG, menuNodeId, []() { return AceType::MakeRefPtr<LinearLayoutPattern>(false); });
525 auto rowProperty = menuNode->GetLayoutProperty<LinearLayoutProperty>();
526 CHECK_NULL_VOID(rowProperty);
527 rowProperty->UpdateMainAxisAlign(FlexAlign::SPACE_BETWEEN);
528
529 auto theme = NavigationGetTheme();
530 auto mostMenuItemCount = theme->GetMostMenuItemCountInBar();
531 bool needMoreButton = menuItems.size() > mostMenuItemCount ? true : false;
532 int32_t count = 0;
533 std::vector<OptionParam> params;
534 for (const auto& menuItem : menuItems) {
535 ++count;
536 if (needMoreButton && (count > mostMenuItemCount - 1)) {
537 params.push_back(std::make_pair(menuItem.text.value(), menuItem.action));
538 } else {
539 auto menuItemNode = FrameNode::CreateFrameNode(V2::MENU_ITEM_ETS_TAG,
540 ElementRegister::GetInstance()->MakeUniqueId(), AceType::MakeRefPtr<ButtonPattern>());
541 CHECK_NULL_VOID(menuItemNode);
542 auto menuItemLayoutProperty = menuItemNode->GetLayoutProperty<ButtonLayoutProperty>();
543 CHECK_NULL_VOID(menuItemLayoutProperty);
544 menuItemLayoutProperty->UpdateUserDefinedIdealSize(CalcSize(CalcLength(BACK_BUTTON_SIZE.ConvertToPx()),
545 CalcLength(BACK_BUTTON_SIZE.ConvertToPx())));
546 menuItemLayoutProperty->UpdateType(ButtonType::NORMAL);
547 menuItemLayoutProperty->UpdateBorderRadius(BUTTON_RADIUS);
548 auto renderContext = menuItemNode->GetRenderContext();
549 CHECK_NULL_VOID(renderContext);
550 renderContext->UpdateBackgroundColor(Color::TRANSPARENT);
551
552 auto eventHub = menuItemNode->GetOrCreateInputEventHub();
553 CHECK_NULL_VOID(eventHub);
554 eventHub->SetHoverEffect(HoverEffectType::BOARD);
555
556 PaddingProperty padding;
557 padding.left = CalcLength(BUTTON_PADDING.ConvertToPx());
558 padding.right = CalcLength(BUTTON_PADDING.ConvertToPx());
559 padding.top = CalcLength(BUTTON_PADDING.ConvertToPx());
560 padding.bottom = CalcLength(BUTTON_PADDING.ConvertToPx());
561 menuItemLayoutProperty->UpdatePadding(padding);
562
563 int32_t barItemNodeId = ElementRegister::GetInstance()->MakeUniqueId();
564 auto barItemNode = AceType::MakeRefPtr<BarItemNode>(V2::BAR_ITEM_ETS_TAG, barItemNodeId);
565 barItemNode->InitializePatternAndContext();
566 UpdateBarItemNodeWithItem(barItemNode, menuItem);
567 auto barItemLayoutProperty = barItemNode->GetLayoutProperty();
568 CHECK_NULL_VOID(barItemLayoutProperty);
569 barItemLayoutProperty->UpdateMeasureType(MeasureType::MATCH_PARENT);
570
571 barItemNode->MountToParent(menuItemNode);
572 barItemNode->MarkModifyDone();
573 menuItemNode->MarkModifyDone();
574 menuNode->AddChild(menuItemNode);
575 }
576 }
577
578 // build more button
579 if (needMoreButton) {
580 int32_t barItemNodeId = ElementRegister::GetInstance()->MakeUniqueId();
581 auto barItemNode = AceType::MakeRefPtr<BarItemNode>(V2::BAR_ITEM_ETS_TAG, barItemNodeId);
582 barItemNode->InitializePatternAndContext();
583 auto barItemLayoutProperty = barItemNode->GetLayoutProperty();
584 CHECK_NULL_VOID(barItemLayoutProperty);
585 barItemLayoutProperty->UpdateMeasureType(MeasureType::MATCH_PARENT);
586
587 BuildMoreIemNode(barItemNode);
588
589 auto barMenuNode = MenuView::Create(std::move(params), barItemNodeId, MenuType::NAVIGATION_MENU);
590 BuildMoreItemNodeAction(barItemNode, barMenuNode);
591 auto menuItemNode = FrameNode::CreateFrameNode(V2::MENU_ITEM_ETS_TAG,
592 ElementRegister::GetInstance()->MakeUniqueId(), AceType::MakeRefPtr<ButtonPattern>());
593 CHECK_NULL_VOID(menuItemNode);
594 auto menuItemLayoutProperty = menuItemNode->GetLayoutProperty<ButtonLayoutProperty>();
595 CHECK_NULL_VOID(menuItemLayoutProperty);
596 menuItemLayoutProperty->UpdateUserDefinedIdealSize(CalcSize(CalcLength(BACK_BUTTON_SIZE.ConvertToPx()),
597 CalcLength(BACK_BUTTON_SIZE.ConvertToPx())));
598 menuItemLayoutProperty->UpdateType(ButtonType::NORMAL);
599 menuItemLayoutProperty->UpdateBorderRadius(BUTTON_RADIUS);
600 auto renderContext = menuItemNode->GetRenderContext();
601 CHECK_NULL_VOID(renderContext);
602 renderContext->UpdateBackgroundColor(Color::TRANSPARENT);
603
604 auto eventHub = menuItemNode->GetOrCreateInputEventHub();
605 CHECK_NULL_VOID(eventHub);
606 eventHub->SetHoverEffect(HoverEffectType::BOARD);
607
608 PaddingProperty padding;
609 padding.left = CalcLength(BUTTON_PADDING.ConvertToPx());
610 padding.right = CalcLength(BUTTON_PADDING.ConvertToPx());
611 padding.top = CalcLength(BUTTON_PADDING.ConvertToPx());
612 padding.bottom = CalcLength(BUTTON_PADDING.ConvertToPx());
613 menuItemLayoutProperty->UpdatePadding(padding);
614
615 barItemNode->MountToParent(menuItemNode);
616 barItemNode->MarkModifyDone();
617 menuItemNode->MarkModifyDone();
618 menuNode->AddChild(menuItemNode);
619 navBarNode->SetMenuNode(barMenuNode);
620 }
621
622 navBarNode->SetMenu(menuNode);
623 navBarNode->UpdatePrevMenuIsCustom(false);
624 }
625
SetCustomMenu(const RefPtr<UINode> & customMenu)626 void NavigationView::SetCustomMenu(const RefPtr<UINode>& customMenu)
627 {
628 CHECK_NULL_VOID(customMenu);
629 auto frameNode = ViewStackProcessor::GetInstance()->GetMainFrameNode();
630 auto navigationGroupNode = AceType::DynamicCast<NavigationGroupNode>(frameNode);
631 CHECK_NULL_VOID(navigationGroupNode);
632 auto navBarNode = AceType::DynamicCast<NavBarNode>(navigationGroupNode->GetNavBarNode());
633 CHECK_NULL_VOID(navBarNode);
634 // if previous menu exists, remove it if their ids are not the same
635 // if previous node is not custom, their ids must not be the same
636 if (navBarNode->GetMenu()) {
637 if (customMenu->GetId() == navBarNode->GetMenu()->GetId()) {
638 navBarNode->UpdateMenuNodeOperation(ChildNodeOperation::NONE);
639 return;
640 }
641 navBarNode->SetMenu(customMenu);
642 navBarNode->UpdatePrevMenuIsCustom(true);
643 navBarNode->UpdateMenuNodeOperation(ChildNodeOperation::REPLACE);
644 return;
645 }
646 navBarNode->SetMenu(customMenu);
647 navBarNode->UpdatePrevMenuIsCustom(true);
648 navBarNode->UpdateMenuNodeOperation(ChildNodeOperation::ADD);
649 }
650
SetTitleMode(NavigationTitleMode mode)651 void NavigationView::SetTitleMode(NavigationTitleMode mode)
652 {
653 auto frameNode = ViewStackProcessor::GetInstance()->GetMainFrameNode();
654 auto navigationGroupNode = AceType::DynamicCast<NavigationGroupNode>(frameNode);
655 CHECK_NULL_VOID(navigationGroupNode);
656 auto navBarNode = AceType::DynamicCast<NavBarNode>(navigationGroupNode->GetNavBarNode());
657 CHECK_NULL_VOID(navBarNode);
658 auto navBarLayoutProperty = navBarNode->GetLayoutProperty<NavBarLayoutProperty>();
659 CHECK_NULL_VOID(navBarLayoutProperty);
660 bool needAddBackButton = false;
661 bool needRemoveBackButton = false;
662
663 do {
664 // add back button if current mode is mini and one of the following condition:
665 // first create or not first create but previous mode is not mini
666 if (navBarLayoutProperty->GetTitleModeValue(NavigationTitleMode::FREE) != NavigationTitleMode::MINI &&
667 mode == NavigationTitleMode::MINI) {
668 needAddBackButton = true;
669 break;
670 }
671 // remove back button if current mode is not mini and previous mode is mini
672 if (navBarLayoutProperty->GetTitleModeValue(NavigationTitleMode::FREE) == NavigationTitleMode::MINI &&
673 mode != NavigationTitleMode::MINI) {
674 needRemoveBackButton = true;
675 break;
676 }
677 } while (false);
678 navBarLayoutProperty->UpdateTitleMode(static_cast<NG::NavigationTitleMode>(mode));
679 if (needAddBackButton) {
680 // put component inside navigator pattern to trigger back navigation
681 auto navigator = FrameNode::CreateFrameNode(V2::NAVIGATOR_ETS_TAG,
682 ElementRegister::GetInstance()->MakeUniqueId(), AceType::MakeRefPtr<NavigatorPattern>());
683 auto hub = navigator->GetEventHub<NavigatorEventHub>();
684 CHECK_NULL_VOID(hub);
685 hub->SetType(NavigatorType::BACK);
686 navigator->MarkModifyDone();
687
688 auto backButtonNode = FrameNode::CreateFrameNode(V2::BACK_BUTTON_ETS_TAG,
689 ElementRegister::GetInstance()->MakeUniqueId(), AceType::MakeRefPtr<ButtonPattern>());
690 CHECK_NULL_VOID(backButtonNode);
691 auto backButtonLayoutProperty = backButtonNode->GetLayoutProperty<ButtonLayoutProperty>();
692 CHECK_NULL_VOID(backButtonLayoutProperty);
693 backButtonLayoutProperty->UpdateUserDefinedIdealSize(CalcSize(CalcLength(BACK_BUTTON_SIZE.ConvertToPx()),
694 CalcLength(BACK_BUTTON_SIZE.ConvertToPx())));
695 backButtonLayoutProperty->UpdateType(ButtonType::NORMAL);
696 backButtonLayoutProperty->UpdateBorderRadius(BUTTON_RADIUS);
697 backButtonLayoutProperty->UpdateMeasureType(MeasureType::MATCH_PARENT);
698 auto renderContext = backButtonNode->GetRenderContext();
699 CHECK_NULL_VOID(renderContext);
700 renderContext->UpdateBackgroundColor(Color::TRANSPARENT);
701
702 auto eventHub = backButtonNode->GetOrCreateInputEventHub();
703 CHECK_NULL_VOID(eventHub);
704 eventHub->SetHoverEffect(HoverEffectType::BOARD);
705
706 PaddingProperty padding;
707 padding.left = CalcLength(BUTTON_PADDING.ConvertToPx());
708 padding.right = CalcLength(BUTTON_PADDING.ConvertToPx());
709 padding.top = CalcLength(BUTTON_PADDING.ConvertToPx());
710 padding.bottom = CalcLength(BUTTON_PADDING.ConvertToPx());
711 backButtonLayoutProperty->UpdatePadding(padding);
712
713 auto backButtonImageNode = FrameNode::CreateFrameNode(V2::BACK_BUTTON_IMAGE_ETS_TAG,
714 ElementRegister::GetInstance()->MakeUniqueId(), AceType::MakeRefPtr<ImagePattern>());
715 CHECK_NULL_VOID(backButtonImageNode);
716 auto theme = NavigationGetTheme();
717 CHECK_NULL_VOID(theme);
718 ImageSourceInfo imageSourceInfo;
719 imageSourceInfo.SetResourceId(theme->GetBackResourceId());
720 auto backButtonImageLayoutProperty = backButtonImageNode->GetLayoutProperty<ImageLayoutProperty>();
721 CHECK_NULL_VOID(backButtonImageLayoutProperty);
722 auto navigationEventHub = navigationGroupNode->GetEventHub<EventHub>();
723 CHECK_NULL_VOID(navigationEventHub);
724 if (!navigationEventHub->IsEnabled()) {
725 imageSourceInfo.SetFillColor(theme->GetBackButtonIconColor().BlendOpacity(theme->GetAlphaDisabled()));
726 } else {
727 imageSourceInfo.SetFillColor(theme->GetBackButtonIconColor());
728 }
729 backButtonImageLayoutProperty->UpdateImageSourceInfo(imageSourceInfo);
730 backButtonImageLayoutProperty->UpdateMeasureType(MeasureType::MATCH_PARENT);
731
732 backButtonImageNode->MountToParent(backButtonNode);
733 backButtonImageNode->MarkModifyDone();
734 backButtonNode->MountToParent(navigator);
735 backButtonNode->MarkModifyDone();
736
737 navBarNode->SetBackButton(navigator);
738 navBarNode->UpdateBackButtonNodeOperation(ChildNodeOperation::ADD);
739 return;
740 }
741 if (needRemoveBackButton) {
742 navBarNode->UpdateBackButtonNodeOperation(ChildNodeOperation::REMOVE);
743 }
744 }
745
SetNavBarWidth(const Dimension & value)746 void NavigationView::SetNavBarWidth(const Dimension& value)
747 {
748 ACE_UPDATE_LAYOUT_PROPERTY(NavigationLayoutProperty, NavBarWidth, value);
749 }
750
SetNavigationMode(NavigationMode mode)751 void NavigationView::SetNavigationMode(NavigationMode mode)
752 {
753 ACE_UPDATE_LAYOUT_PROPERTY(NavigationLayoutProperty, NavigationMode, mode);
754 }
755
SetUsrNavigationMode(NavigationMode mode)756 void NavigationView::SetUsrNavigationMode(NavigationMode mode)
757 {
758 ACE_UPDATE_LAYOUT_PROPERTY(NavigationLayoutProperty, UsrNavigationMode, mode);
759 }
760
SetNavBarPosition(NG::NavBarPosition mode)761 void NavigationView::SetNavBarPosition(NG::NavBarPosition mode)
762 {
763 ACE_UPDATE_LAYOUT_PROPERTY(NavigationLayoutProperty, NavBarPosition, static_cast<NG::NavBarPosition>(mode));
764 }
765
SetHideNavBar(bool hideNavBar)766 void NavigationView::SetHideNavBar(bool hideNavBar)
767 {
768 ACE_UPDATE_LAYOUT_PROPERTY(NavigationLayoutProperty, HideNavBar, hideNavBar);
769 }
770
SetTitleHeight(const Dimension & height)771 void NavigationView::SetTitleHeight(const Dimension& height)
772 {
773 auto frameNode = ViewStackProcessor::GetInstance()->GetMainFrameNode();
774 auto navigationGroupNode = AceType::DynamicCast<NavigationGroupNode>(frameNode);
775 CHECK_NULL_VOID(navigationGroupNode);
776 auto navBarNode = AceType::DynamicCast<NavBarNode>(navigationGroupNode->GetNavBarNode());
777 CHECK_NULL_VOID(navBarNode);
778 auto titleBarNode = AceType::DynamicCast<TitleBarNode>(navBarNode->GetTitleBarNode());
779 CHECK_NULL_VOID(titleBarNode);
780 auto titleBarLayoutProperty = titleBarNode->GetLayoutProperty<TitleBarLayoutProperty>();
781 CHECK_NULL_VOID(titleBarLayoutProperty);
782 titleBarLayoutProperty->UpdateTitleHeight(height);
783 }
784
SetHideTitleBar(bool hideTitleBar)785 void NavigationView::SetHideTitleBar(bool hideTitleBar)
786 {
787 auto frameNode = ViewStackProcessor::GetInstance()->GetMainFrameNode();
788 auto navigationGroupNode = AceType::DynamicCast<NavigationGroupNode>(frameNode);
789 CHECK_NULL_VOID(navigationGroupNode);
790 auto navBarNode = AceType::DynamicCast<NavBarNode>(navigationGroupNode->GetNavBarNode());
791 CHECK_NULL_VOID(navBarNode);
792 auto navBarLayoutProperty = navBarNode->GetLayoutProperty<NavBarLayoutProperty>();
793 CHECK_NULL_VOID(navBarLayoutProperty);
794 navBarLayoutProperty->UpdateHideTitleBar(hideTitleBar);
795 }
796
SetHideBackButton(bool hideBackButton)797 void NavigationView::SetHideBackButton(bool hideBackButton)
798 {
799 auto frameNode = ViewStackProcessor::GetInstance()->GetMainFrameNode();
800 auto navigationGroupNode = AceType::DynamicCast<NavigationGroupNode>(frameNode);
801 CHECK_NULL_VOID(navigationGroupNode);
802 auto navBarNode = AceType::DynamicCast<NavBarNode>(navigationGroupNode->GetNavBarNode());
803 CHECK_NULL_VOID(navBarNode);
804 auto navBarLayoutProperty = navBarNode->GetLayoutProperty<NavBarLayoutProperty>();
805 CHECK_NULL_VOID(navBarLayoutProperty);
806 navBarLayoutProperty->UpdateHideBackButton(hideBackButton);
807 }
808
SetHideToolBar(bool hideToolBar)809 void NavigationView::SetHideToolBar(bool hideToolBar)
810 {
811 auto frameNode = ViewStackProcessor::GetInstance()->GetMainFrameNode();
812 auto navigationGroupNode = AceType::DynamicCast<NavigationGroupNode>(frameNode);
813 CHECK_NULL_VOID(navigationGroupNode);
814 auto navBarNode = AceType::DynamicCast<NavBarNode>(navigationGroupNode->GetNavBarNode());
815 CHECK_NULL_VOID(navBarNode);
816 auto navBarLayoutProperty = navBarNode->GetLayoutProperty<NavBarLayoutProperty>();
817 CHECK_NULL_VOID(navBarLayoutProperty);
818 navBarLayoutProperty->UpdateHideToolBar(hideToolBar);
819 }
820
SetToolBarItems(std::vector<BarItem> && toolBarItems)821 void NavigationView::SetToolBarItems(std::vector<BarItem>&& toolBarItems)
822 {
823 auto frameNode = ViewStackProcessor::GetInstance()->GetMainFrameNode();
824 auto navigationGroupNode = AceType::DynamicCast<NavigationGroupNode>(frameNode);
825 CHECK_NULL_VOID(navigationGroupNode);
826 auto navBarNode = AceType::DynamicCast<NavBarNode>(navigationGroupNode->GetNavBarNode());
827 CHECK_NULL_VOID(navBarNode);
828 if (navBarNode->GetPrevToolBarIsCustom().value_or(false)) {
829 navBarNode->UpdateToolBarNodeOperation(ChildNodeOperation::REPLACE);
830 } else {
831 if (navBarNode->GetPreToolBarNode() &&
832 static_cast<int32_t>(navBarNode->GetPreToolBarNode()->GetChildren().size()) != 0) {
833 UpdateOldBarItems(navBarNode->GetPreToolBarNode(), toolBarItems);
834 navBarNode->SetToolBarNode(navBarNode->GetPreToolBarNode());
835 navBarNode->UpdateToolBarNodeOperation(ChildNodeOperation::NONE);
836 return;
837 }
838 navBarNode->UpdateToolBarNodeOperation(ChildNodeOperation::REPLACE);
839 }
840 auto toolBarNode = AceType::DynamicCast<FrameNode>(navBarNode->GetPreToolBarNode());
841 CHECK_NULL_VOID(toolBarNode);
842 auto rowProperty = toolBarNode->GetLayoutProperty<LinearLayoutProperty>();
843 CHECK_NULL_VOID(rowProperty);
844 rowProperty->UpdateMainAxisAlign(FlexAlign::SPACE_EVENLY);
845 for (const auto& toolBarItem : toolBarItems) {
846 int32_t barItemNodeId = ElementRegister::GetInstance()->MakeUniqueId();
847 auto barItemNode = AceType::MakeRefPtr<BarItemNode>(V2::BAR_ITEM_ETS_TAG, barItemNodeId);
848 barItemNode->InitializePatternAndContext();
849 UpdateBarItemNodeWithItem(barItemNode, toolBarItem);
850 toolBarNode->AddChild(barItemNode);
851 }
852 navBarNode->SetToolBarNode(toolBarNode);
853 navBarNode->SetPreToolBarNode(toolBarNode);
854 navBarNode->UpdatePrevToolBarIsCustom(false);
855 }
856
SetCustomToolBar(const RefPtr<UINode> & customToolBar)857 void NavigationView::SetCustomToolBar(const RefPtr<UINode>& customToolBar)
858 {
859 CHECK_NULL_VOID(customToolBar);
860 auto frameNode = ViewStackProcessor::GetInstance()->GetMainFrameNode();
861 auto navigationGroupNode = AceType::DynamicCast<NavigationGroupNode>(frameNode);
862 CHECK_NULL_VOID(navigationGroupNode);
863 auto navBarNode = AceType::DynamicCast<NavBarNode>(navigationGroupNode->GetNavBarNode());
864 CHECK_NULL_VOID(navBarNode);
865 if (navBarNode->GetPrevToolBarIsCustom().value_or(false)) {
866 if (customToolBar->GetId() == navBarNode->GetToolBarNode()->GetId()) {
867 navBarNode->UpdateToolBarNodeOperation(ChildNodeOperation::NONE);
868 navBarNode->UpdatePrevToolBarIsCustom(true);
869 return;
870 }
871 }
872 navBarNode->UpdateToolBarNodeOperation(ChildNodeOperation::REPLACE);
873 auto toolBarNode = navBarNode->GetToolBarNode();
874 CHECK_NULL_VOID(toolBarNode);
875 toolBarNode->Clean();
876 customToolBar->MountToParent(toolBarNode);
877 navBarNode->UpdatePrevToolBarIsCustom(true);
878 }
879
SetOnTitleModeChange(std::function<void (NavigationTitleMode)> && onTitleModeChange)880 void NavigationView::SetOnTitleModeChange(std::function<void(NavigationTitleMode)>&& onTitleModeChange)
881 {
882 auto frameNode = ViewStackProcessor::GetInstance()->GetMainFrameNode();
883 auto navigationGroupNode = AceType::DynamicCast<NavigationGroupNode>(frameNode);
884 CHECK_NULL_VOID(navigationGroupNode);
885 auto eventHub = navigationGroupNode->GetEventHub<NavigationEventHub>();
886 CHECK_NULL_VOID(eventHub);
887 eventHub->SetOnTitleModeChange(std::move(onTitleModeChange));
888 }
889
SetOnNavBarStateChange(std::function<void (bool)> && onNavBarStateChange)890 void NavigationView::SetOnNavBarStateChange(std::function<void(bool)>&& onNavBarStateChange)
891 {
892 auto frameNode = ViewStackProcessor::GetInstance()->GetMainFrameNode();
893 auto navigationEventHub = AceType::DynamicCast<NavigationEventHub>(frameNode->GetEventHub<EventHub>());
894 CHECK_NULL_VOID(navigationEventHub);
895 navigationEventHub->SetOnNavBarStateChange(std::move(onNavBarStateChange));
896 }
897
SetBackButtonIcon(const std::string & src,bool noPixMap,RefPtr<PixelMap> & pixMap)898 void NavigationView::SetBackButtonIcon(const std::string& src, bool noPixMap, RefPtr<PixelMap>& pixMap)
899 {
900 ImageSourceInfo imageSourceInfo(src);
901 ACE_UPDATE_LAYOUT_PROPERTY(NavigationLayoutProperty, NoPixMap, noPixMap);
902 ACE_UPDATE_LAYOUT_PROPERTY(NavigationLayoutProperty, ImageSource, imageSourceInfo);
903 ACE_UPDATE_LAYOUT_PROPERTY(NavigationLayoutProperty, PixelMap, pixMap);
904 auto frameNode = ViewStackProcessor::GetInstance()->GetMainFrameNode();
905 auto navigationGroupNode = AceType::DynamicCast<NavigationGroupNode>(frameNode);
906 CHECK_NULL_VOID(navigationGroupNode);
907 auto navBarNode = AceType::DynamicCast<NavBarNode>(navigationGroupNode->GetNavBarNode());
908 CHECK_NULL_VOID(navBarNode);
909 auto navBarContentNode = navBarNode->GetNavBarContentNode();
910 CHECK_NULL_VOID(navBarContentNode);
911 if (navBarContentNode->GetChildren().empty()) {
912 return;
913 }
914 for (const auto& navBarContentChild : navBarContentNode->GetChildren()) {
915 auto navBarContentChildFrameNode = AceType::DynamicCast<FrameNode>(navBarContentChild);
916 CHECK_NULL_VOID(navBarContentChildFrameNode);
917 if (navBarContentChildFrameNode->GetTag() != V2::NAVROUTER_VIEW_ETS_TAG) {
918 return;
919 }
920 auto navRouterNode = AceType::DynamicCast<NavRouterGroupNode>(navBarContentChildFrameNode);
921 CHECK_NULL_VOID(navRouterNode);
922 auto navDestinationNode = AceType::DynamicCast<NavDestinationGroupNode>(navRouterNode->GetNavDestinationNode());
923 CHECK_NULL_VOID(navDestinationNode);
924 auto navDestinationLayoutProperty = navDestinationNode->GetLayoutProperty<NavDestinationLayoutProperty>();
925 navDestinationLayoutProperty->UpdateImageSource(imageSourceInfo);
926 navDestinationLayoutProperty->UpdateNoPixMap(noPixMap);
927 navDestinationLayoutProperty->UpdatePixelMap(pixMap);
928 navDestinationNode->MarkModifyDone();
929 }
930 }
931
932 } // namespace OHOS::Ace::NG
933