• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2025 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 #include "core/components_ng/pattern/container_modal/container_modal_toolbar.h"
16 
17 #include "ui/base/ace_type.h"
18 #include "ui/base/referenced.h"
19 #include "ui/base/utils/utils.h"
20 
21 #include "core/components/container_modal/container_modal_constants.h"
22 #include "core/components_ng/base/frame_node.h"
23 #include "core/components_ng/base/ui_node.h"
24 #include "core/components_ng/layout/layout_wrapper.h"
25 #include "core/components_ng/layout/layout_wrapper_node.h"
26 #include "core/components_ng/manager/toolbar/toolbar_manager.h"
27 #include "core/components_ng/pattern/container_modal/container_modal_pattern.h"
28 #include "core/components_ng/pattern/flex/flex_layout_styles.h"
29 #include "core/components_ng/pattern/linear_layout/linear_layout_pattern.h"
30 #include "core/components_ng/pattern/navigation/nav_bar_node.h"
31 #include "core/components_ng/pattern/navigation/nav_bar_pattern.h"
32 #include "core/components_ng/pattern/navigation/navigation_pattern.h"
33 #include "core/components_ng/pattern/navigation/navigation_title_util.h"
34 #include "core/components_ng/pattern/navrouter/navdestination_layout_algorithm.h"
35 #include "core/components_ng/pattern/navrouter/navdestination_layout_property.h"
36 #include "core/components_ng/pattern/navrouter/navdestination_pattern.h"
37 #include "core/components_ng/pattern/side_bar/side_bar_container_layout_algorithm.h"
38 #include "core/components_ng/pattern/side_bar/side_bar_container_pattern.h"
39 #include "core/components_ng/pattern/stack/stack_layout_property.h"
40 #include "core/components_ng/pattern/toolbaritem/toolbaritem_pattern.h"
41 
42 namespace OHOS::Ace::NG {
43 
44 namespace {
45 constexpr float TITLE_ITEM_HEIGT_S = 56.0; // 56vp height of title
46 constexpr float TITLE_ITEM_HEIGT_M = 64.0; // 64vp height of title
47 constexpr float TITLE_ITEM_HEIGT_L = 72.0; // 72vp height of title
48 constexpr float ROW_MARGIN = 4.0;
49 constexpr float ROW_TOTAL_MARGIN = 8.0;
50 constexpr uint32_t TITLE_MGR_CALLBACK_ID = 0;
51 constexpr uint32_t FLOATING_TITLE_MGR_CALLBACK_ID = 1;
52 } // namespace
53 
InitToolBarManager()54 void ContainerModalToolBar::InitToolBarManager()
55 {
56     if (!toolbarManager_) {
57         auto toolbar = pattern_.Upgrade();
58         CHECK_NULL_VOID(toolbar);
59         auto pipeline = toolbar->GetContext();
60         CHECK_NULL_VOID(pipeline);
61         toolbarManager_ = pipeline->GetToolbarManager();
62     }
63 }
64 
SetOnChangeCallback()65 void ContainerModalToolBar::SetOnChangeCallback()
66 {
67     CHECK_NULL_VOID(toolbarManager_);
68     if (!hasSetOnchangeCallback_) {
69         std::function<void()> func = [weak = WeakClaim(this)]() {
70             auto pattern = weak.Upgrade();
71             CHECK_NULL_VOID(pattern);
72             pattern->OnToolBarLayoutChange();
73         };
74         toolbarManager_->SetToolBarChangeCallback(std::move(func));
75         hasSetOnchangeCallback_ = true;
76     }
77     if (!isFloating_ && !hasSetUpdateSideTitleBgColor_) {
78         std::function<void(const Color&, const Color&, const BlurStyle&)> func =
79             [wk = WeakClaim(this)](
80                 const Color& sideBarColor, const Color& sideBarContainerColor, const BlurStyle& sideBarBlurStyle) {
81                 auto pattern = wk.Upgrade();
82                 CHECK_NULL_VOID(pattern);
83                 pattern->UpdateSideTitleBgColor(sideBarColor, sideBarContainerColor, sideBarBlurStyle);
84             };
85         toolbarManager_->SetSideBarColorChangeCallback(std::move(func));
86         hasSetUpdateSideTitleBgColor_ = true;
87     }
88     if (!hasSetNavigationModeChangeCallback_) {
89         std::function<void()> navigationModefunc = [weak = WeakClaim(this), toolbarMgr = toolbarManager_]() {
90             CHECK_NULL_VOID(toolbarMgr);
91             auto pattern = weak.Upgrade();
92             CHECK_NULL_VOID(pattern);
93             NavigationMode navigationMode = toolbarMgr->GetNavigationMode();
94             if (navigationMode != NavigationMode::SPLIT) {
95                 pattern->RemoveAllToolbarItem();
96             }
97         };
98         toolbarManager_->SetNavigationModeChangeCallback(std::move(navigationModefunc));
99         hasSetNavigationModeChangeCallback_ = true;
100     }
101 }
102 
SetToolbarBuilder(const RefPtr<FrameNode> & parent,std::function<RefPtr<UINode> ()> & builder)103 void ContainerModalToolBar::SetToolbarBuilder(const RefPtr<FrameNode>& parent, std::function<RefPtr<UINode>()>& builder)
104 {
105     CHECK_NULL_VOID(parent);
106     RemoveToolbarItem(parent);
107     UpdateTitleLayout();
108     CHECK_NULL_VOID(builder);
109     auto nodes = builder();
110     CHECK_NULL_VOID(nodes);
111     auto it = itemsWillOnTree_.find(parent);
112     if (it != itemsWillOnTree_.end()) {
113         it->second.clear();
114     }
115     auto children = nodes->GetChildren();
116     for (auto& item : children) {
117         itemsWillOnTree_[parent].push_back(item);
118     }
119     auto callback = [weak = WeakClaim(this), frame = WeakClaim(RawPtr(parent))]() {
120         auto toolbar = weak.Upgrade();
121         CHECK_NULL_VOID(toolbar);
122         auto frameNode = frame.Upgrade();
123         CHECK_NULL_VOID(frameNode);
124         toolbar->RemoveToolbarItem(frameNode);
125         toolbar->UpdateTitleLayout();
126     };
127     parent->SetRemoveToolbarItemCallback(
128         isFloating_ ? FLOATING_TITLE_MGR_CALLBACK_ID : TITLE_MGR_CALLBACK_ID, std::move(callback));
129     InitToolBarManager();
130     SetOnChangeCallback();
131     auto pattern = pattern_.Upgrade();
132     CHECK_NULL_VOID(pattern);
133     auto pipeline = pattern->GetContext();
134     CHECK_NULL_VOID(pipeline);
135     pipeline->AddAfterRenderTask([weak = WeakClaim(this)]() {
136         auto toolbar = weak.Upgrade();
137         CHECK_NULL_VOID(toolbar);
138         if (toolbar->GetNavOrSideBarNodes()) {
139             if (!(toolbar->HasNavOrSideBarNodes())) {
140                 toolbar->SetHasNavOrSideBarNodes(true);
141                 toolbar->ToInitNavOrSideBarNode();
142             }
143         } else {
144             return;
145         }
146         toolbar->ParsePlacementType();
147     });
148 }
149 
ParsePlacementType()150 void ContainerModalToolBar::ParsePlacementType()
151 {
152     if (!GetNavOrSideBarNodes() || !HasNavOrSideBarNodes()) {
153         return;
154     }
155 
156     bool hasItem = false;
157     for (auto it = itemsWillOnTree_.begin(); it != itemsWillOnTree_.end();) {
158         auto parent = it->first;
159         auto& list = it->second;
160         if (HandleToolbarItemList(parent, list)) {
161             it = itemsWillOnTree_.erase(it);
162             hasItem = true;
163         } else {
164             it++;
165         }
166     }
167     if (hasItem) {
168         AddToolbarItemToContainer();
169         OnToolBarLayoutChange();
170     }
171 }
172 
GetItemTypeFromTag(const std::string & tag,uint32_t placement)173 ItemPlacementType ContainerModalToolBar::GetItemTypeFromTag(const std::string& tag, uint32_t placement)
174 {
175     if (tag == V2::SIDE_BAR_ETS_TAG) {
176         return placement ? ItemPlacementType::SIDE_BAR_END : ItemPlacementType::SIDE_BAR_START;
177     }
178     if (tag == V2::NAVBAR_ETS_TAG) {
179         return placement ? ItemPlacementType::NAV_BAR_END : ItemPlacementType::NAV_BAR_START;
180     }
181     if (tag == V2::NAVDESTINATION_VIEW_ETS_TAG) {
182         return placement ? ItemPlacementType::NAVDEST_END : ItemPlacementType::NAVDEST_START;
183     }
184     return ItemPlacementType::NONE;
185 }
186 
HandleToolbarItemList(const RefPtr<FrameNode> & parentNode,std::list<RefPtr<UINode>> & list)187 bool ContainerModalToolBar::HandleToolbarItemList(const RefPtr<FrameNode>& parentNode, std::list<RefPtr<UINode>>& list)
188 {
189     CHECK_NULL_RETURN(parentNode, true);
190     std::string tag = GetTagFromNode(parentNode);
191     if (tag == "") {
192         return false;
193     }
194     for (auto& item : list) {
195         auto frameNode = AceType::DynamicCast<FrameNode>(item);
196         itemsOnTree_[parentNode].push_back(item);
197         auto pattern = frameNode->GetPattern<ToolBarItemPattern>();
198         int32_t placement = 0;
199         if (pattern) {
200             placement = pattern->GetPlacement();
201             auto id = GetItemTypeFromTag(tag, placement);
202             itemWillAdd_[id].emplace_back(frameNode);
203         }
204     }
205     return true;
206 }
207 
UpdateTitleAfterRemove()208 void ContainerModalToolBar::UpdateTitleAfterRemove()
209 {
210     if (navbarRow_) {
211         navbarRow_->MarkDirtyNode(
212             PROPERTY_UPDATE_LAYOUT | PROPERTY_UPDATE_RENDER | PROPERTY_UPDATE_MEASURE_SELF_AND_CHILD);
213         if (leftNavRow_) {
214             leftNavRow_->MarkDirtyNode(
215                 PROPERTY_UPDATE_LAYOUT | PROPERTY_UPDATE_RENDER | PROPERTY_UPDATE_MEASURE_SELF_AND_CHILD);
216         }
217         if (rightNavRow_) {
218             rightNavRow_->MarkDirtyNode(
219                 PROPERTY_UPDATE_LAYOUT | PROPERTY_UPDATE_RENDER | PROPERTY_UPDATE_MEASURE_SELF_AND_CHILD);
220         }
221     }
222     if (navDestbarRow_) {
223         navDestbarRow_->MarkDirtyNode(
224             PROPERTY_UPDATE_LAYOUT | PROPERTY_UPDATE_RENDER | PROPERTY_UPDATE_MEASURE_SELF_AND_CHILD);
225         if (leftNavDestRow_) {
226             leftNavDestRow_->MarkDirtyNode(
227                 PROPERTY_UPDATE_LAYOUT | PROPERTY_UPDATE_RENDER | PROPERTY_UPDATE_MEASURE_SELF_AND_CHILD);
228         }
229         if (rightNavDestRow_) {
230             rightNavDestRow_->MarkDirtyNode(
231                 PROPERTY_UPDATE_LAYOUT | PROPERTY_UPDATE_RENDER | PROPERTY_UPDATE_MEASURE_SELF_AND_CHILD);
232         }
233     }
234 }
235 
RemoveAllToolbarItem()236 void ContainerModalToolBar::RemoveAllToolbarItem()
237 {
238     for (auto& [_, list] : itemsOnTree_) {
239         for (auto& item : list) {
240             auto parent = item->GetParent();
241             if (parent) {
242                 parent->RemoveChild(item);
243                 parent->MarkNeedSyncRenderTree();
244                 parent->RebuildRenderContextTree();
245             }
246         }
247     }
248     itemsOnTree_.clear();
249     UpdateTitleLayout();
250 }
251 
RemoveToolbarItem(const RefPtr<FrameNode> & frameNode)252 void ContainerModalToolBar::RemoveToolbarItem(const RefPtr<FrameNode>& frameNode)
253 {
254     CHECK_NULL_VOID(frameNode);
255     auto& list = itemsOnTree_[frameNode];
256     for (auto& item : list) {
257         auto parent = item->GetParent();
258         if (parent) {
259             parent->RemoveChild(item);
260             parent->MarkNeedSyncRenderTree();
261             parent->RebuildRenderContextTree();
262         }
263     }
264     list.clear();
265     itemsOnTree_.erase(frameNode);
266 }
267 
UpdateTitleLayout()268 void ContainerModalToolBar::UpdateTitleLayout()
269 {
270     auto pattern = pattern_.Upgrade();
271     CHECK_NULL_VOID(pattern);
272     UpdateTitleAfterRemove();
273     toolbarItemMaxHeight_ = 0.0f;
274     for (auto it = itemsOnTree_.begin(); it != itemsOnTree_.end(); it++) {
275         auto& list = it->second;
276         for (auto iit = list.begin(); iit != list.end(); iit++) {
277             auto toolbarNode = AceType::DynamicCast<FrameNode>(*iit);
278             CHECK_NULL_VOID(toolbarNode);
279             LayoutConstraintF Constraint;
280             toolbarNode->Measure(Constraint);
281             auto toolbarItemHeight = Dimension(toolbarNode->GetGeometryNode()->GetFrameSize().Height()).ConvertToVp();
282             if (GreatNotEqual(toolbarItemHeight, toolbarItemMaxHeight_)) {
283                 toolbarItemMaxHeight_ = toolbarItemHeight;
284             }
285         }
286     }
287     if (!isTitleShow_ || customTitleShow_) {
288         RemoveToolbarRowContainers();
289         OnToolBarLayoutChange();
290         AdjustContainerModalTitleHeight();
291     }
292 }
293 
AddToolbarItemToContainer()294 void ContainerModalToolBar::AddToolbarItemToContainer()
295 {
296     for (auto it = itemWillAdd_.begin(); it != itemWillAdd_.end(); it++) {
297         auto placementType = it->first;
298         if (placementType == ItemPlacementType::NONE) {
299             continue;
300         }
301         auto& list = it->second;
302         for (auto iit = list.begin(); iit != list.end();) {
303             if (AddToolbarItemToRow(placementType, *iit)) {
304                 iit = list.erase(iit);
305             } else {
306                 iit++;
307             }
308         }
309     }
310 }
311 
AddToolbarItemToRow(ItemPlacementType placeMent,const RefPtr<FrameNode> & frameNode)312 bool ContainerModalToolBar::AddToolbarItemToRow(ItemPlacementType placeMent, const RefPtr<FrameNode>& frameNode)
313 {
314     if ((!toolbarManager_->HasNavBar() &&
315             (placeMent == ItemPlacementType::NAV_BAR_END || placeMent == ItemPlacementType::NAV_BAR_START)) ||
316         (!toolbarManager_->HasNavDest() &&
317             (placeMent == ItemPlacementType::NAVDEST_START || placeMent == ItemPlacementType::NAVDEST_END))) {
318         return false;
319     }
320 
321     CHECK_NULL_RETURN(frameNode, false);
322     LayoutConstraintF Constraint;
323     frameNode->Measure(Constraint);
324     auto toolbarItemHeight = Dimension(frameNode->GetGeometryNode()->GetFrameSize().Height()).ConvertToVp();
325     if (GreatNotEqual(toolbarItemHeight, toolbarItemMaxHeight_)) {
326         toolbarItemMaxHeight_ = toolbarItemHeight;
327     }
328 
329     return AddToolbarItemToSpecificRow(placeMent, frameNode);
330 }
331 
AddToolbarItemToSpecificRow(ItemPlacementType placeMent,const RefPtr<FrameNode> & frameNode)332 bool ContainerModalToolBar::AddToolbarItemToSpecificRow(ItemPlacementType placeMent, const RefPtr<FrameNode>& frameNode)
333 {
334     bool ref = false;
335     switch (placeMent) {
336         case ItemPlacementType::NAV_BAR_START:
337             ref = AddToolbarItemToNavBarStart(frameNode);
338             break;
339         case ItemPlacementType::NAV_BAR_END:
340             ref = AddToolbarItemToNavBarEnd(frameNode);
341             break;
342         case ItemPlacementType::NAVDEST_START:
343             ref = AddToolbarItemToNavDestStart(frameNode);
344             break;
345         case ItemPlacementType::NAVDEST_END:
346             ref = AddToolbarItemToNavDestEnd(frameNode);
347             break;
348         default:
349             TAG_LOGE(AceLogTag::ACE_SUB_WINDOW, "Unknown placement");
350             return false;
351     }
352     auto containermodal = pattern_.Upgrade();
353     CHECK_NULL_RETURN(containermodal, ref);
354     containermodal->SetIsHaveToolBar(true);
355     if (!isTitleShow_ || customTitleShow_) {
356         auto pipeline = containermodal->GetContext();
357         CHECK_NULL_RETURN(pipeline, true);
358         auto overlayTask = [weak = WeakClaim(this)]() {
359             auto pattern = weak.Upgrade();
360             CHECK_NULL_VOID(pattern);
361             pattern->AdjustContainerModalTitleHeight();
362         };
363         pipeline->AddAfterRenderTask(overlayTask);
364     }
365     return ref;
366 }
367 
AddToolbarItemToNavBarStart(const RefPtr<FrameNode> & frameNode)368 bool ContainerModalToolBar::AddToolbarItemToNavBarStart(const RefPtr<FrameNode>& frameNode)
369 {
370     if (!navbarRow_) {
371         AddNavBarRow();
372     }
373     if (navbarRow_) {
374         if (!leftNavRow_) {
375             AddLeftNavRow();
376         }
377         leftNavRow_->AddChild(frameNode);
378         leftNavRow_->MarkDirtyNode(PROPERTY_UPDATE_MEASURE_SELF_AND_PARENT);
379         return true;
380     }
381     return false;
382 }
383 
AddToolbarItemToNavBarEnd(const RefPtr<FrameNode> & frameNode)384 bool ContainerModalToolBar::AddToolbarItemToNavBarEnd(const RefPtr<FrameNode>& frameNode)
385 {
386     if (!navbarRow_) {
387         AddNavBarRow();
388     }
389 
390     if (navbarRow_) {
391         if (!rightNavRow_) {
392             AddLeftNavRow();
393             AddRightNavRow();
394         }
395         rightNavRow_->AddChild(frameNode);
396         rightNavRow_->MarkDirtyNode(PROPERTY_UPDATE_MEASURE_SELF_AND_PARENT);
397         return true;
398     }
399     return false;
400 }
401 
AddToolbarItemToNavDestStart(const RefPtr<FrameNode> & frameNode)402 bool ContainerModalToolBar::AddToolbarItemToNavDestStart(const RefPtr<FrameNode>& frameNode)
403 {
404     if (!navDestbarRow_) {
405         AddNavDestBarRow();
406     }
407 
408     if (navDestbarRow_) {
409         if (!leftNavDestRow_) {
410             AddLeftNavDestRow();
411         }
412         leftNavDestRow_->AddChild(frameNode);
413         leftNavDestRow_->MarkDirtyNode(PROPERTY_UPDATE_MEASURE_SELF_AND_PARENT);
414         return true;
415     }
416     return false;
417 }
418 
AddToolbarItemToNavDestEnd(const RefPtr<FrameNode> & frameNode)419 bool ContainerModalToolBar::AddToolbarItemToNavDestEnd(const RefPtr<FrameNode>& frameNode)
420 {
421     if (!navDestbarRow_) {
422         AddNavDestBarRow();
423     }
424 
425     if (navDestbarRow_) {
426         if (!rightNavDestRow_) {
427             AddLeftNavDestRow();
428             AddRightNavDestRow();
429         }
430         rightNavDestRow_->AddChild(frameNode);
431         rightNavDestRow_->MarkDirtyNode(PROPERTY_UPDATE_MEASURE_SELF_AND_PARENT);
432         return true;
433     }
434     return false;
435 }
436 
AddNavBarRow()437 void ContainerModalToolBar::AddNavBarRow()
438 {
439     CHECK_NULL_VOID(title_);
440     auto navBarInfo = toolbarManager_->GetNavBarInfo();
441     if (navBarInfo.isShow) {
442         if (!navbarRow_) {
443             navbarRow_ = FrameNode::CreateFrameNode(V2::ROW_ETS_TAG, ElementRegister::GetInstance()->MakeUniqueId(),
444                 MakeRefPtr<LinearLayoutPattern>(false));
445             navbarRow_->UpdateInspectorId("NavBar");
446             auto layout = navbarRow_->GetLayoutProperty<LinearLayoutProperty>();
447             CHECK_NULL_VOID(layout);
448             layout->UpdateMainAxisAlign(FlexAlign::SPACE_BETWEEN);
449             layout->UpdateCrossAxisAlign(FlexAlign::CENTER);
450             auto renderContext = navbarRow_->GetRenderContext();
451             CHECK_NULL_VOID(renderContext);
452             renderContext->SetClipToFrame(true);
453             title_->AddChild(navbarRow_, 1);
454             navbarRow_->MarkDirtyNode(PROPERTY_UPDATE_MEASURE_SELF_AND_PARENT);
455         }
456     }
457     title_->MarkDirtyNode(PROPERTY_UPDATE_MEASURE_SELF_AND_CHILD);
458 }
459 
AddLeftNavRow()460 void ContainerModalToolBar::AddLeftNavRow()
461 {
462     if (navbarRow_) {
463         if (!leftNavRow_) {
464             leftNavRow_ = FrameNode::CreateFrameNode(V2::ROW_ETS_TAG, ElementRegister::GetInstance()->MakeUniqueId(),
465                 MakeRefPtr<LinearLayoutPattern>(false));
466             leftNavRow_->UpdateInspectorId("LeftNavRow");
467             auto layout = leftNavRow_->GetLayoutProperty<LinearLayoutProperty>();
468             CHECK_NULL_VOID(layout);
469             MarginProperty margin;
470             margin.SetEdges(CalcLength(Dimension(ROW_MARGIN, DimensionUnit::VP)));
471             layout->UpdateMargin(margin);
472             navbarRow_->AddChild(leftNavRow_, 0);
473             leftNavRow_->MarkDirtyNode(PROPERTY_UPDATE_MEASURE_SELF_AND_PARENT);
474         }
475         navbarRow_->MarkDirtyNode(PROPERTY_UPDATE_MEASURE_SELF_AND_PARENT);
476         title_->MarkDirtyNode(PROPERTY_UPDATE_MEASURE_SELF_AND_PARENT);
477     }
478     AdjustNavbarRowWidth();
479 }
480 
AddRightNavRow()481 void ContainerModalToolBar::AddRightNavRow()
482 {
483     if (navbarRow_) {
484         if (!rightNavRow_) {
485             rightNavRow_ = FrameNode::CreateFrameNode(V2::ROW_ETS_TAG, ElementRegister::GetInstance()->MakeUniqueId(),
486                 MakeRefPtr<LinearLayoutPattern>(false));
487             rightNavRow_->UpdateInspectorId("RightNavRow");
488             navbarRow_->AddChild(rightNavRow_);
489             auto layout = rightNavRow_->GetLayoutProperty<LinearLayoutProperty>();
490             CHECK_NULL_VOID(layout);
491             MarginProperty margin;
492             margin.SetEdges(CalcLength(Dimension(ROW_MARGIN, DimensionUnit::VP)));
493             layout->UpdateMargin(margin);
494             layout->UpdateMainAxisAlign(FlexAlign::FLEX_END);
495             rightNavRow_->MarkDirtyNode(PROPERTY_UPDATE_MEASURE_SELF_AND_PARENT);
496         }
497         navbarRow_->MarkDirtyNode(PROPERTY_UPDATE_MEASURE_SELF_AND_PARENT);
498         title_->MarkDirtyNode(PROPERTY_UPDATE_MEASURE_SELF_AND_PARENT);
499     }
500     AdjustNavbarRowWidth();
501 }
502 
AddNavDestBarRow()503 void ContainerModalToolBar::AddNavDestBarRow()
504 {
505     auto navDestInfo = toolbarManager_->GetNavDestInfo();
506     if (navDestInfo.isShow) {
507         if (!navDestbarRow_) {
508             navDestbarRow_ = FrameNode::CreateFrameNode(V2::ROW_ETS_TAG, ElementRegister::GetInstance()->MakeUniqueId(),
509                 MakeRefPtr<LinearLayoutPattern>(false));
510             navDestbarRow_->UpdateInspectorId("NavDestBar");
511             auto layout = navDestbarRow_->GetLayoutProperty<LinearLayoutProperty>();
512             CHECK_NULL_VOID(layout);
513             layout->UpdateMainAxisAlign(FlexAlign::SPACE_BETWEEN);
514             layout->UpdateCrossAxisAlign(FlexAlign::CENTER);
515             auto renderContext = navDestbarRow_->GetRenderContext();
516             CHECK_NULL_VOID(renderContext);
517             renderContext->SetClipToFrame(true);
518             title_->AddChild(navDestbarRow_);
519             navDestbarRow_->MarkDirtyNode(PROPERTY_UPDATE_MEASURE_SELF_AND_PARENT);
520         }
521     }
522     title_->MarkDirtyNode(PROPERTY_UPDATE_MEASURE_SELF_AND_CHILD);
523 }
524 
AddLeftNavDestRow()525 void ContainerModalToolBar::AddLeftNavDestRow()
526 {
527     if (navDestbarRow_) {
528         if (!leftNavDestRow_) {
529             leftNavDestRow_ = FrameNode::CreateFrameNode(V2::ROW_ETS_TAG,
530                 ElementRegister::GetInstance()->MakeUniqueId(), MakeRefPtr<LinearLayoutPattern>(false));
531             leftNavDestRow_->UpdateInspectorId("LeftNavDest");
532             auto layout = leftNavDestRow_->GetLayoutProperty<LinearLayoutProperty>();
533             CHECK_NULL_VOID(layout);
534             MarginProperty margin;
535             margin.SetEdges(CalcLength(Dimension(ROW_MARGIN, DimensionUnit::VP)));
536             layout->UpdateMargin(margin);
537             navDestbarRow_->AddChild(leftNavDestRow_, 0);
538             leftNavDestRow_->MarkDirtyNode(PROPERTY_UPDATE_MEASURE_SELF_AND_PARENT);
539         }
540         navDestbarRow_->MarkDirtyNode(PROPERTY_UPDATE_MEASURE_SELF_AND_PARENT);
541         title_->MarkDirtyNode(PROPERTY_UPDATE_MEASURE_SELF_AND_PARENT);
542     }
543     AdjustNavDestRowWidth();
544 }
545 
AddRightNavDestRow()546 void ContainerModalToolBar::AddRightNavDestRow()
547 {
548     if (navDestbarRow_) {
549         if (!rightNavDestRow_) {
550             rightNavDestRow_ = FrameNode::CreateFrameNode(V2::ROW_ETS_TAG,
551                 ElementRegister::GetInstance()->MakeUniqueId(), MakeRefPtr<LinearLayoutPattern>(false));
552             rightNavDestRow_->UpdateInspectorId("RightNavDest");
553             navDestbarRow_->AddChild(rightNavDestRow_);
554             auto layout = rightNavDestRow_->GetLayoutProperty<LinearLayoutProperty>();
555             CHECK_NULL_VOID(layout);
556             MarginProperty margin;
557             margin.SetEdges(CalcLength(Dimension(ROW_MARGIN, DimensionUnit::VP)));
558             layout->UpdateMargin(margin);
559             layout->UpdateMainAxisAlign(FlexAlign::FLEX_END);
560             rightNavDestRow_->MarkDirtyNode(PROPERTY_UPDATE_MEASURE_SELF_AND_PARENT);
561         }
562         navDestbarRow_->MarkDirtyNode(PROPERTY_UPDATE_MEASURE_SELF_AND_PARENT);
563         title_->MarkDirtyNode(PROPERTY_UPDATE_MEASURE_SELF_AND_PARENT);
564     }
565     AdjustNavDestRowWidth();
566 }
567 
RemoveToolbarRowContainers()568 void ContainerModalToolBar::RemoveToolbarRowContainers()
569 {
570     auto RemoveIfEmpty = [this](RefPtr<FrameNode>& container, const RefPtr<FrameNode>& parent) {
571         if (container && container->GetChildren().empty()) {
572             if (parent) {
573                 parent->RemoveChild(container);
574                 parent->MarkDirtyNode(
575                     PROPERTY_UPDATE_LAYOUT | PROPERTY_UPDATE_RENDER | PROPERTY_UPDATE_MEASURE_SELF_AND_PARENT);
576             }
577             container = nullptr;
578         }
579     };
580     RemoveIfEmpty(rightNavRow_, navbarRow_);
581     RemoveIfEmpty(rightNavDestRow_, navDestbarRow_);
582     if (!rightNavRow_ && navbarRow_) {
583         RemoveIfEmpty(leftNavRow_, navbarRow_);
584     }
585     if (!rightNavDestRow_ && navDestbarRow_) {
586         RemoveIfEmpty(leftNavDestRow_, navDestbarRow_);
587     }
588     RemoveIfEmpty(navbarRow_, title_);
589     RemoveIfEmpty(navDestbarRow_, title_);
590     if (title_) {
591         title_->MarkDirtyNode(PROPERTY_UPDATE_MEASURE_SELF_AND_CHILD);
592     }
593     if (!navbarRow_ && !navDestbarRow_) {
594         auto containermodal = pattern_.Upgrade();
595         CHECK_NULL_VOID(containermodal);
596         containermodal->SetIsHaveToolBar(false);
597     }
598 }
599 
OnToolBarLayoutChange()600 void ContainerModalToolBar::OnToolBarLayoutChange()
601 {
602     if (!toolbarManager_ || !HasNavOrSideBarNodes()) {
603         return;
604     }
605 
606     auto pattern = pattern_.Upgrade();
607     CHECK_NULL_VOID(pattern);
608     auto pipeline = pattern->GetContext();
609     CHECK_NULL_VOID(pipeline);
610     pipeline->AddAfterRenderTask([weak = WeakClaim(this), toolbarMgr = toolbarManager_]() {
611         auto toolbar = weak.Upgrade();
612         CHECK_NULL_VOID(toolbar);
613         toolbar->AdjustTitleNodeWidth();
614         CHECK_NULL_VOID(toolbarMgr);
615         if (toolbarMgr->GetNavBarInfo().isShow) {
616             toolbar->AdjustNavbarRowWidth();
617         }
618         if (toolbarMgr->GetNavDestInfo().isShow) {
619             toolbar->AdjustNavDestRowWidth();
620         }
621     });
622 }
623 
AdjustTitleNodeWidth()624 void ContainerModalToolBar::AdjustTitleNodeWidth()
625 {
626     auto sideBarInfo = toolbarManager_->GetSideBarInfo();
627     float titleNodeWidth = sideBarInfo.isShow ? sideBarInfo.width : 0;
628 
629     auto titleNode = AceType::DynamicCast<FrameNode>(title_->GetChildren().front());
630     CHECK_NULL_VOID(titleNode);
631     auto titleNodeProperty = titleNode->GetLayoutProperty<LayoutProperty>();
632     CHECK_NULL_VOID(titleNodeProperty);
633     titleNodeProperty->UpdateMeasureType(MeasureType::MATCH_PARENT);
634 
635     if (itemsOnTree_.empty()) {
636         titleNodeProperty->UpdateUserDefinedIdealSize(
637             CalcSize(CalcLength(1.0, DimensionUnit::PERCENT), CalcLength(1.0, DimensionUnit::PERCENT)));
638         titleNode->MarkDirtyNode(PROPERTY_UPDATE_MEASURE_SELF_AND_PARENT);
639         return;
640     }
641 
642     auto renderContext = titleNode->GetRenderContext();
643     CHECK_NULL_VOID(renderContext);
644     renderContext->SetClipToFrame(true);
645     titleNodeProperty->UpdateUserDefinedIdealSize(
646         CalcSize(CalcLength(titleNodeWidth), CalcLength(1.0, DimensionUnit::PERCENT)));
647     titleNode->MarkDirtyNode(PROPERTY_UPDATE_MEASURE_SELF_AND_PARENT);
648 }
649 
AdjustNavbarRowWidth()650 void ContainerModalToolBar::AdjustNavbarRowWidth()
651 {
652     auto pattern = pattern_.Upgrade();
653     CHECK_NULL_VOID(pattern);
654 
655     auto sideBarInfo = toolbarManager_->GetSideBarInfo();
656     auto sideBarDividerInfo = toolbarManager_->GetSideBarDividerInfo();
657     auto navbarInfo = toolbarManager_->GetNavBarInfo();
658     auto navbarDividerInfo = toolbarManager_->GetNavBarDividerInfo();
659     auto navDestInfo = toolbarManager_->GetNavDestInfo();
660     auto controlButtonsWidth = pattern->GetControlButtonRowWidth();
661     float navbarRowWidth = 0.0f;
662 
663     if (navbarInfo.isShow && navbarRow_) {
664         auto navbarRowProperty = navbarRow_->GetLayoutProperty<LinearLayoutProperty>();
665         CHECK_NULL_VOID(navbarRowProperty);
666         if (navDestInfo.isShow && LessOrEqual(navDestInfo.width, controlButtonsWidth.GetDimension().ConvertToPx())) {
667             navbarRowWidth = navDestInfo.width + navbarInfo.width - controlButtonsWidth.GetDimension().ConvertToPx();
668         } else {
669             navbarRowWidth = navbarInfo.width;
670         }
671         navbarRowProperty->UpdateUserDefinedIdealSize(CalcSize(CalcLength(navbarRowWidth), std::nullopt));
672         auto isRtl = AceApplicationInfo::GetInstance().IsRightToLeft();
673         MarginProperty navbarRowMargin;
674         if (isRtl) {
675             if (navDestInfo.isShow &&
676                 LessOrEqual(navDestInfo.width, controlButtonsWidth.GetDimension().ConvertToPx())) {
677                 navbarRowMargin.left = CalcLength(controlButtonsWidth.GetDimension().ConvertToPx());
678                 navbarRowMargin.right = sideBarInfo.isShow ? CalcLength(sideBarDividerInfo.width) : CalcLength(0);
679             } else {
680                 navbarRowMargin.left = CalcLength(navbarDividerInfo.width);
681                 navbarRowMargin.right = sideBarInfo.isShow ? CalcLength(sideBarDividerInfo.width) : CalcLength(0);
682             }
683         } else {
684             if (navDestInfo.isShow &&
685                 LessOrEqual(navDestInfo.width, controlButtonsWidth.GetDimension().ConvertToPx())) {
686                 navbarRowMargin.left = sideBarInfo.isShow ? CalcLength(sideBarDividerInfo.width) : CalcLength(0);
687                 navbarRowMargin.right = CalcLength(controlButtonsWidth.GetDimension().ConvertToPx());
688             } else {
689                 navbarRowMargin.left = sideBarInfo.isShow ? CalcLength(sideBarDividerInfo.width) : CalcLength(0);
690                 navbarRowMargin.right = CalcLength(navbarDividerInfo.width);
691             }
692         }
693         navbarRowProperty->UpdateMargin(navbarRowMargin);
694         navbarRow_->MarkDirtyNode(PROPERTY_UPDATE_MEASURE_SELF_AND_CHILD);
695         navbarRowProperty->UpdateVisibility(
696             NearEqual(navbarInfo.width, 0.0f) ? VisibleType::INVISIBLE : VisibleType::VISIBLE);
697     }
698 }
699 
AdjustNavDestRowWidth()700 void ContainerModalToolBar::AdjustNavDestRowWidth()
701 {
702     auto pattern = pattern_.Upgrade();
703     CHECK_NULL_VOID(pattern);
704 
705     CHECK_NULL_VOID(toolbarManager_);
706     auto sideBarInfo = toolbarManager_->GetSideBarInfo();
707     auto sideBarDividerInfo = toolbarManager_->GetSideBarDividerInfo();
708     auto navbarInfo = toolbarManager_->GetNavBarInfo();
709     auto navbarDividerInfo = toolbarManager_->GetNavBarDividerInfo();
710     auto navDestInfo = toolbarManager_->GetNavDestInfo();
711     auto controlButtonsWidth = pattern->GetControlButtonRowWidth();
712 
713     if (navDestInfo.isShow && navDestbarRow_) {
714         float navDestbarRowAvailableWidth = navDestInfo.width - controlButtonsWidth.GetDimension().ConvertToPx();
715         auto navDestbarRowProperty = navDestbarRow_->GetLayoutProperty<LinearLayoutProperty>();
716         CHECK_NULL_VOID(navDestbarRowProperty);
717         navDestbarRowProperty->UpdateUserDefinedIdealSize(
718             CalcSize(CalcLength(navDestbarRowAvailableWidth), std::nullopt));
719         float navDestbarRowLeftMargin = 0.0f;
720         if (navbarRow_) {
721             navDestbarRowLeftMargin = navbarDividerInfo.width;
722         } else if (!sideBarInfo.isShow && !navbarInfo.isShow) {
723             navDestbarRowLeftMargin = 0.0f;
724         } else if (!sideBarInfo.isShow) {
725             navDestbarRowLeftMargin = navbarInfo.width + navbarDividerInfo.width;
726         } else if (!navbarInfo.isShow) {
727             navDestbarRowLeftMargin = sideBarDividerInfo.width;
728         } else {
729             navDestbarRowLeftMargin = sideBarDividerInfo.width + navbarInfo.width + navbarDividerInfo.width;
730         }
731         auto isRtl = AceApplicationInfo::GetInstance().IsRightToLeft();
732         MarginProperty navDestbarRowMargin;
733         if (isRtl) {
734             navDestbarRowMargin.left = CalcLength(controlButtonsWidth.GetDimension().ConvertToPx());
735             navDestbarRowMargin.right = CalcLength(navDestbarRowLeftMargin);
736         } else {
737             navDestbarRowMargin.left = CalcLength(navDestbarRowLeftMargin);
738             navDestbarRowMargin.right = CalcLength(controlButtonsWidth.GetDimension().ConvertToPx());
739         }
740         navDestbarRowProperty->UpdateMargin(navDestbarRowMargin);
741         navDestbarRow_->MarkDirtyNode(PROPERTY_UPDATE_MEASURE_SELF_AND_CHILD);
742         navDestbarRowProperty->UpdateVisibility(
743             NearEqual(navDestInfo.width, 0.0f) ? VisibleType::INVISIBLE : VisibleType::VISIBLE);
744     }
745 }
746 
UpdateToolbarShow(bool isTitleShow,bool customTitleSettedShow)747 void ContainerModalToolBar::UpdateToolbarShow(bool isTitleShow, bool customTitleSettedShow)
748 {
749     auto pattern = pattern_.Upgrade();
750     CHECK_NULL_VOID(pattern);
751     isTitleShow_ = isTitleShow;
752     customTitleShow_ = customTitleSettedShow;
753 
754     if (!isTitleShow || customTitleSettedShow) {
755         UpdateTitleLayout();
756     } else if (!customTitleSettedShow) {
757         pattern->SetControlButtonsRowHeight(CONTAINER_TITLE_HEIGHT);
758     }
759 }
760 
AdjustContainerModalTitleHeight()761 void ContainerModalToolBar::AdjustContainerModalTitleHeight()
762 {
763     auto pattern = pattern_.Upgrade();
764     CHECK_NULL_VOID(pattern);
765 
766     if (itemsOnTree_.empty()) {
767         pattern->titleHeight_ = CONTAINER_TITLE_HEIGHT;
768         pattern->SetContainerModalTitleHeight(CONTAINER_TITLE_HEIGHT.ConvertToPx());
769         ResetExpandStackNode();
770         return;
771     }
772 
773     auto rowHeight = toolbarItemMaxHeight_ + ROW_TOTAL_MARGIN;
774     if (NearEqual(toolbarItemMaxHeight_, 0.0f)) {
775         pattern->titleHeight_ = CONTAINER_TITLE_HEIGHT;
776     } else if (LessOrEqual(rowHeight, TITLE_ITEM_HEIGT_S)) {
777         pattern->titleHeight_ = Dimension(TITLE_ITEM_HEIGT_S, DimensionUnit::VP);
778     } else if (GreatNotEqual(rowHeight, TITLE_ITEM_HEIGT_S) && LessOrEqual(rowHeight, TITLE_ITEM_HEIGT_M)) {
779         pattern->titleHeight_ = Dimension(TITLE_ITEM_HEIGT_M, DimensionUnit::VP);
780     } else if (GreatNotEqual(rowHeight, TITLE_ITEM_HEIGT_M)) {
781         pattern->titleHeight_ = Dimension(TITLE_ITEM_HEIGT_L, DimensionUnit::VP);
782     }
783     pattern->SetContainerModalTitleHeight(pattern->titleHeight_.ConvertToPx());
784     UpdateTargetNodesBarMargin();
785 }
786 
GetTagFromNode(RefPtr<UINode> node)787 std::string ContainerModalToolBar::GetTagFromNode(RefPtr<UINode> node)
788 {
789     std::string tag = "";
790     CHECK_NULL_RETURN(node, tag);
791     auto navigationNode = navigationNode_.Upgrade();
792     while (node && node->GetTag() != V2::ROOT_ETS_TAG) {
793         if (node->GetTag() == V2::NAVBAR_ETS_TAG && navigationNode && navigationNode == node->GetParent()) {
794             tag = node->GetTag();
795             break;
796         }
797         if (node->GetTag() == V2::NAVDESTINATION_VIEW_ETS_TAG) {
798             if (node == navDestNode_) {
799                 tag = node->GetTag();
800                 break;
801             }
802             auto navDestContentNode = node->GetParent();
803             if (navDestContentNode && navigationNode && navigationNode == navDestContentNode->GetParent()) {
804                 tag = node->GetTag();
805                 break;
806             }
807         }
808         node = node->GetParent();
809     }
810     return tag;
811 }
812 
813 /**
814  * @brief This method traverses the node hierarchy to identify and set specific target nodes
815  *        (SideBar, Navigation, and Navigation Destination nodes) based on their tags and geometry.
816  *
817  * @return Returns true if any of the target nodes (SideBar, Navigation, or Navigation Destination)
818  *         are found and set; otherwise, returns false.
819  *
820  * @details The method performs the following steps:
821  * - Retrieves the root content node and its geometry content.
822  * - Initializes a queue for breadth-first traversal of the node hierarchy.
823  * - Iterates through the child nodes to find nodes with specific tags:
824  *   - SIDE_BAR_ETS_TAG: Identifies the SideBar node if its width matches the root content width.
825  *   - NAVBAR_ETS_TAG: If the SideBar node has not be finded, identifies the Navigation node if its width matches
826  * the root content width, else identifies the Navigation node direct
827  *   - NAVDESTINATION_VIEW_ETS_TAG: Identifies the Navigation Destination node.
828  * - Stops traversal once all required nodes are found or the hierarchy is fully traversed.
829  *
830  * @note The method uses a queue to perform breadth-first traversal and ensures that
831  *       the search stops as soon as the required nodes are identified.
832  */
GetNavOrSideBarNodes()833 bool ContainerModalToolBar::GetNavOrSideBarNodes()
834 {
835     auto pattern = pattern_.Upgrade();
836     CHECK_NULL_RETURN(pattern, false);
837     auto contentNode = pattern->GetContentNode();
838     CHECK_NULL_RETURN(contentNode, false);
839     auto stage = contentNode->GetFirstChild();
840     CHECK_NULL_RETURN(stage, false);
841     auto page = stage->GetFirstChild();
842     CHECK_NULL_RETURN(page, false);
843     auto custom = page->GetFirstChild();
844     CHECK_NULL_RETURN(custom, false);
845     auto customNode = AceType::DynamicCast<FrameNode>(custom);
846     CHECK_NULL_RETURN(customNode, false);
847     auto customGeometryNode = customNode->GetGeometryNode();
848     CHECK_NULL_RETURN(customGeometryNode, false);
849     auto pageWidth = customGeometryNode->GetFrameSize().Width();
850     return GetNavOrSideBarNodesParseChildren(page, pageWidth);
851 }
852 
GetNavOrSideBarNodesParseChildren(const RefPtr<UINode> & page,float pageWidth)853 bool ContainerModalToolBar::GetNavOrSideBarNodesParseChildren(const RefPtr<UINode>& page, float pageWidth)
854 {
855     std::queue<RefPtr<UINode>> queue {};
856     bool isSideBarFound = false;
857     bool isNavigationFound = false;
858     bool isNavDestFound = false;
859     queue.emplace(page);
860     RefPtr<UINode> parentNode;
861     float sideBarHeight = 0.0f;
862     while (!queue.empty()) {
863         parentNode = queue.front();
864         queue.pop();
865         auto children = parentNode->GetChildren();
866         if (children.empty()) {
867             continue;
868         }
869         for (auto child : children) {
870             queue.emplace(child);
871             auto childFrameNode = AceType::DynamicCast<FrameNode>(child);
872             CHECK_NULL_CONTINUE(childFrameNode)
873             if (IsTragetSideBarNodeParse(childFrameNode, pageWidth, sideBarHeight, isSideBarFound)) {
874                 std::queue<RefPtr<UINode>>().swap(queue);
875                 queue.emplace(child);
876                 isSideBarFound = true;
877                 break;
878             } else if (IsTragetNavigationNodeParse(
879                 childFrameNode, pageWidth, sideBarHeight, isNavigationFound, isSideBarFound)) {
880                 std::queue<RefPtr<UINode>>().swap(queue);
881                 queue.emplace(child);
882                 isSideBarFound = true;
883                 isNavigationFound = true;
884                 break;
885             } else if ((isNavigationFound && isSideBarFound) || (isNavigationFound &&
886                 childFrameNode->GetTag() == V2::NAVDESTINATION_VIEW_ETS_TAG)) {
887                 isSideBarFound = true;
888                 isNavigationFound = true;
889                 isNavDestFound = true;
890                 navDestNode_ = childFrameNode;
891             }
892             if ((isNavigationFound && isSideBarFound) || (isNavigationFound && isNavDestFound)) {
893                 break;
894             }
895         }
896         if ((isNavigationFound && isSideBarFound) || (isNavigationFound && isNavDestFound)) {
897             break;
898         }
899     }
900     if ((isNavigationFound && isSideBarFound) || (isNavigationFound && isNavDestFound)) {
901         return true;
902     }
903     return false;
904 }
905 
IsTragetSideBarNodeParse(const RefPtr<FrameNode> & childFrameNode,float pageWidth,float & sideBarHeight,bool isSideBarFound)906 bool ContainerModalToolBar::IsTragetSideBarNodeParse(
907     const RefPtr<FrameNode>& childFrameNode, float pageWidth, float& sideBarHeight, bool isSideBarFound)
908 {
909     CHECK_NULL_RETURN(childFrameNode, false);
910     if (!isSideBarFound && childFrameNode->GetTag() == V2::SIDE_BAR_ETS_TAG) {
911         auto geometryNode = childFrameNode->GetGeometryNode();
912         CHECK_NULL_RETURN(geometryNode, false);
913         auto childWidth = geometryNode->GetFrameSize().Width();
914         if (NearEqual(pageWidth, childWidth)) {
915             sideBarHeight = geometryNode->GetFrameSize().Height();
916             sideBarNode_ = childFrameNode;
917             return true;
918         }
919     }
920     return false;
921 }
922 
IsTragetNavigationNodeParse(const RefPtr<FrameNode> & childFrameNode,float pageWidth,float sideBarHeight,bool isNavigationFound,bool isSideBarFound)923 bool ContainerModalToolBar::IsTragetNavigationNodeParse(const RefPtr<FrameNode>& childFrameNode, float pageWidth,
924     float sideBarHeight, bool isNavigationFound, bool isSideBarFound)
925 {
926     CHECK_NULL_RETURN(childFrameNode, false);
927     CHECK_NULL_RETURN(toolbarManager_, false);
928 
929     if (!isNavigationFound && childFrameNode->GetTag() == V2::NAVIGATION_VIEW_ETS_TAG) {
930         auto navigationPattern = childFrameNode->GetPattern<NavigationPattern>();
931         CHECK_NULL_RETURN(navigationPattern, false);
932         NavigationMode navigationMode = navigationPattern->GetNavigationMode();
933         if (!isSideBarFound) {
934             auto geometryNode = childFrameNode->GetGeometryNode();
935             CHECK_NULL_RETURN(geometryNode, false);
936             auto childWidth = geometryNode->GetFrameSize().Width();
937             if (NearEqual(pageWidth, childWidth) && navigationMode == NavigationMode::SPLIT) {
938                 navigationNode_ = childFrameNode;
939                 return true;
940             }
941         } else {
942             auto geometryNode = childFrameNode->GetGeometryNode();
943             CHECK_NULL_RETURN(geometryNode, false);
944             auto childHeight = geometryNode->GetFrameSize().Height();
945             if ((NearEqual(sideBarHeight, childHeight) || NearEqual(sideBarHeight, 0.0f)) &&
946                 navigationMode == NavigationMode::SPLIT) {
947                 navigationNode_ = childFrameNode;
948                 return true;
949             }
950         }
951     }
952     return false;
953 }
954 
ToInitNavOrSideBarNode()955 void ContainerModalToolBar::ToInitNavOrSideBarNode()
956 {
957     auto sideBarNode = sideBarNode_.Upgrade();
958     if (sideBarNode) {
959         auto sideBarPattern = AceType::DynamicCast<NG::SideBarContainerPattern>(sideBarNode->GetPattern());
960         if (sideBarPattern) {
961             sideBarPattern->InitToolBarManager();
962             sideBarNode->MarkModifyDone();
963         }
964     }
965     auto navigationNode = navigationNode_.Upgrade();
966     if (navigationNode) {
967         auto navigationPattern = AceType::DynamicCast<NG::NavigationPattern>(navigationNode->GetPattern());
968         if (navigationPattern) {
969             navigationPattern->InitToolBarManager();
970             navigationNode->MarkModifyDone();
971         }
972     }
973     CHECK_NULL_VOID(toolbarManager_);
974     std::function<void()> getTypeOfItem = [weak = WeakClaim(this)]() {
975         auto pattern = weak.Upgrade();
976         CHECK_NULL_VOID(pattern);
977         pattern->ParsePlacementType();
978     };
979     toolbarManager_->SetModifyDoneCallback(std::move(getTypeOfItem));
980 }
981 
UpdateSideTitleBgColor(const Color & sideBarColor,const Color & sideBarContainerColor,const BlurStyle & blurStyle)982 void ContainerModalToolBar::UpdateSideTitleBgColor(
983     const Color& sideBarColor, const Color& sideBarContainerColor, const BlurStyle& blurStyle)
984 {
985     CHECK_NULL_VOID(title_);
986     auto titleNode = AceType::DynamicCast<FrameNode>(title_->GetChildren().front());
987     CHECK_NULL_VOID(titleNode);
988     auto ctx = titleNode->GetRenderContext();
989     CHECK_NULL_VOID(ctx);
990     Color color = sideBarContainerColor.BlendColorWithAlpha(sideBarColor);
991     ctx->UpdateBackgroundColor(color);
992     BlurStyleOption option;
993     option.blurStyle = blurStyle;
994     ctx->UpdateBackBlurStyle(option);
995 }
996 
SetCustomTitleRowBlurStyle(BlurStyle & blurStyle)997 void ContainerModalToolBar::SetCustomTitleRowBlurStyle(BlurStyle& blurStyle)
998 {
999     auto pattern = pattern_.Upgrade();
1000     CHECK_NULL_VOID(pattern);
1001     auto customTitleRow = pattern->GetCustomTitleRow();
1002     CHECK_NULL_VOID(customTitleRow);
1003     auto renderContext = customTitleRow->GetRenderContext();
1004     CHECK_NULL_VOID(renderContext);
1005     BlurStyleOption styleOption;
1006     styleOption.blurStyle = blurStyle;
1007     renderContext->UpdateBackBlurStyle(styleOption);
1008 }
UpdateSidebarMargin()1009 void ContainerModalToolBar::UpdateSidebarMargin()
1010 {
1011     CHECK_NULL_VOID(toolbarManager_);
1012     if (toolbarManager_->GetIsMoveUp()) {
1013         auto sideBarContainerModelNode = toolbarManager_->GetSideBarContainerModel().Upgrade();
1014         CHECK_NULL_VOID(sideBarContainerModelNode);
1015         sideBarContainerModelNode->MarkDirtyNode(
1016             PROPERTY_UPDATE_LAYOUT | PROPERTY_UPDATE_RENDER | PROPERTY_UPDATE_MEASURE_SELF_AND_CHILD);
1017         sideBarContainerModelNode->MarkModifyDone();
1018         isUpdateTargetNode_ = true;
1019     }
1020 }
1021 
UpdateNavbarTitlebarMargin()1022 void ContainerModalToolBar::UpdateNavbarTitlebarMargin()
1023 {
1024     CHECK_NULL_VOID(toolbarManager_);
1025     if (toolbarManager_->GetIsMoveUp()) {
1026         auto navBarNode = toolbarManager_->GetNavBar().Upgrade();
1027         CHECK_NULL_VOID(navBarNode);
1028         auto navigation = navBarNode->GetParent();
1029         CHECK_NULL_VOID(navigation);
1030         auto navigationFrameNode = AceType::DynamicCast<FrameNode>(navigation);
1031         CHECK_NULL_VOID(navigationFrameNode);
1032         navigationFrameNode->MarkDirtyNode(
1033             PROPERTY_UPDATE_LAYOUT | PROPERTY_UPDATE_RENDER | PROPERTY_UPDATE_MEASURE_SELF_AND_CHILD);
1034         navigationFrameNode->MarkModifyDone();
1035         isUpdateTargetNode_ = true;
1036     }
1037 }
1038 
UpdateNavDestinationTitlebarMargin()1039 void ContainerModalToolBar::UpdateNavDestinationTitlebarMargin()
1040 {
1041     CHECK_NULL_VOID(toolbarManager_);
1042     if (toolbarManager_->GetIsMoveUp()) {
1043         auto navigationContentNode = toolbarManager_->GetNavDest().Upgrade();
1044         CHECK_NULL_VOID(navigationContentNode);
1045         auto navigationFrameNode = AceType::DynamicCast<FrameNode>(navigationContentNode->GetParent());
1046         CHECK_NULL_VOID(navigationFrameNode);
1047         auto navigationPattern = navigationFrameNode->GetPattern<NG::NavigationPattern>();
1048         CHECK_NULL_VOID(navigationPattern);
1049         auto navigationStack = navigationPattern->GetNavigationStack();
1050         CHECK_NULL_VOID(navigationStack);
1051         auto topNavDestinationNode = navigationStack->GetTopNavPath();
1052         if (!topNavDestinationNode.has_value()) {
1053             return;
1054         }
1055         auto navDestinationNode = AceType::DynamicCast<NG::NavDestinationGroupNode>(
1056             NG::NavigationGroupNode::GetNavDestinationNode(topNavDestinationNode->second));
1057         CHECK_NULL_VOID(navDestinationNode);
1058         navDestinationNode->MarkDirtyNode(
1059             PROPERTY_UPDATE_LAYOUT | PROPERTY_UPDATE_RENDER | PROPERTY_UPDATE_MEASURE_SELF_AND_CHILD);
1060         navDestinationNode->MarkModifyDone();
1061         isUpdateTargetNode_ = true;
1062     }
1063 }
1064 
UpdateTargetNodesBarMargin(bool reset)1065 void ContainerModalToolBar::UpdateTargetNodesBarMargin(bool reset)
1066 {
1067     if (!toolbarManager_ || isFloating_) {
1068         return;
1069     }
1070     auto pattern = pattern_.Upgrade();
1071     CHECK_NULL_VOID(pattern);
1072     if (reset) {
1073         if (!isUpdateTargetNode_) {
1074             return;
1075         }
1076         toolbarManager_->SetTitleHeight(Dimension(0.0f));
1077     } else {
1078         if (!isUpdateTargetNode_ && pattern->GetIsHaveToolBar() && pattern->IsExpandStackNode()) {
1079             ExpandStackNodeLayout();
1080             BlurStyle blurStyle = BlurStyle::THIN;
1081             SetCustomTitleRowBlurStyle(blurStyle);
1082             toolbarManager_->SetIsMoveUp(true);
1083         }
1084         toolbarManager_->SetTitleHeight(pattern->titleHeight_);
1085     }
1086 
1087     UpdateNavDestinationTitlebarMargin();
1088     UpdateNavbarTitlebarMargin();
1089     UpdateSidebarMargin();
1090 }
1091 
ExpandStackNodeLayout(bool reset)1092 void ContainerModalToolBar::ExpandStackNodeLayout(bool reset)
1093 {
1094     CHECK_NULL_VOID(title_);
1095     auto pattern = pattern_.Upgrade();
1096     CHECK_NULL_VOID(pattern);
1097     auto stackNode = pattern->GetStackNode();
1098     CHECK_NULL_VOID(stackNode);
1099     auto renderContext = stackNode->GetRenderContext();
1100     CHECK_NULL_VOID(renderContext);
1101     auto stackLayoutProperty = stackNode->GetLayoutProperty<StackLayoutProperty>();
1102     CHECK_NULL_VOID(stackLayoutProperty);
1103     if (reset) {
1104         auto titleRenderContext = title_->GetRenderContext();
1105         CHECK_NULL_VOID(titleRenderContext);
1106         titleRenderContext->ResetBackBlurStyle();
1107         renderContext->ResetPosition();
1108         renderContext->ResetZIndex();
1109         auto titleNode = AceType::DynamicCast<FrameNode>(title_->GetChildren().front());
1110         CHECK_NULL_VOID(titleNode);
1111         auto titleNodeCtx = titleNode->GetRenderContext();
1112         CHECK_NULL_VOID(titleNodeCtx);
1113         titleNodeCtx->ResetBackBlurStyle();
1114         titleNodeCtx->UpdateBackgroundColor(Color::TRANSPARENT);
1115     } else {
1116         renderContext->UpdatePosition(OffsetT(Dimension(0.0f), Dimension(0.0f)));
1117         renderContext->UpdateZIndex(-1);
1118     }
1119     auto columnNode = pattern->GetColumnNode();
1120     CHECK_NULL_VOID(columnNode);
1121     columnNode->MarkDirtyNode(PROPERTY_UPDATE_LAYOUT | PROPERTY_UPDATE_RENDER | PROPERTY_UPDATE_MEASURE_SELF_AND_CHILD);
1122     columnNode->MarkModifyDone();
1123 }
1124 
ResetExpandStackNode()1125 void ContainerModalToolBar::ResetExpandStackNode()
1126 {
1127     if (!isUpdateTargetNode_ || isFloating_ || !toolbarManager_) {
1128         return;
1129     }
1130     UpdateTargetNodesBarMargin(true);
1131     isUpdateTargetNode_ = false;
1132     toolbarManager_->SetIsMoveUp(false);
1133     ExpandStackNodeLayout(true);
1134 }
1135 } // namespace OHOS::Ace::NG