• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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_layout_algorithm.h"
17 
18 #include <cmath>
19 
20 #include "base/geometry/dimension.h"
21 #include "base/geometry/ng/offset_t.h"
22 #include "base/geometry/ng/size_t.h"
23 #include "base/log/ace_trace.h"
24 #include "base/memory/ace_type.h"
25 #include "base/utils/utils.h"
26 #include "core/components/common/layout/constants.h"
27 #include "core/components_ng/base/frame_node.h"
28 #include "core/components_ng/layout/layout_algorithm.h"
29 #include "core/components_ng/pattern/linear_layout/linear_layout_property.h"
30 #include "core/components_ng/pattern/navigation/navigation_declaration.h"
31 #include "core/components_ng/pattern/navigation/navigation_group_node.h"
32 #include "core/components_ng/pattern/navigation/navigation_layout_property.h"
33 #include "core/components_ng/pattern/navigation/navigation_pattern.h"
34 #include "core/components_ng/pattern/navrouter/navdestination_group_node.h"
35 #include "core/components_ng/property/calc_length.h"
36 #include "core/components_ng/property/layout_constraint.h"
37 #include "core/components_ng/property/measure_property.h"
38 #include "core/components_ng/property/measure_utils.h"
39 #include "core/pipeline_ng/pipeline_context.h"
40 
41 namespace OHOS::Ace::NG {
42 
43 constexpr static int32_t PLATFORM_VERSION_TEN = 10;
44 constexpr Dimension WINDOW_WIDTH = 520.0_vp;
45 
46 namespace {
47 
MeasureDivider(LayoutWrapper * layoutWrapper,const RefPtr<NavigationGroupNode> & hostNode,const RefPtr<NavigationLayoutProperty> & navigationLayoutProperty,const SizeF & dividerSize)48 void MeasureDivider(LayoutWrapper* layoutWrapper, const RefPtr<NavigationGroupNode>& hostNode,
49     const RefPtr<NavigationLayoutProperty>& navigationLayoutProperty, const SizeF& dividerSize)
50 {
51     auto dividerNode = hostNode->GetDividerNode();
52     CHECK_NULL_VOID(dividerNode);
53     auto index = hostNode->GetChildIndexById(dividerNode->GetId());
54     auto dividerWrapper = layoutWrapper->GetOrCreateChildByIndex(index);
55     CHECK_NULL_VOID(dividerWrapper);
56     auto constraint = navigationLayoutProperty->CreateChildConstraint();
57     constraint.selfIdealSize = OptionalSizeF(dividerSize.Width(), dividerSize.Height());
58     dividerWrapper->Measure(constraint);
59 }
60 
LayoutNavBar(LayoutWrapper * layoutWrapper,const RefPtr<NavigationGroupNode> & hostNode,const RefPtr<NavigationLayoutProperty> & navigationLayoutProperty,const NavBarPosition & position,OffsetF & returnNavBarOffset)61 float LayoutNavBar(LayoutWrapper* layoutWrapper, const RefPtr<NavigationGroupNode>& hostNode,
62     const RefPtr<NavigationLayoutProperty>& navigationLayoutProperty, const NavBarPosition& position,
63     OffsetF& returnNavBarOffset)
64 {
65     auto layoutAlgorithmWrapper = AceType::DynamicCast<LayoutAlgorithmWrapper>(layoutWrapper->GetLayoutAlgorithm());
66     CHECK_NULL_RETURN(layoutAlgorithmWrapper, 0.0f);
67     auto navigationLayoutAlgorithm =
68         AceType::DynamicCast<NavigationLayoutAlgorithm>(layoutAlgorithmWrapper->GetLayoutAlgorithm());
69     if (navigationLayoutProperty->GetHideNavBar().value_or(false) &&
70         navigationLayoutAlgorithm->GetNavigationMode() == NavigationMode::SPLIT) {
71         return 0.0f;
72     }
73     auto contentNode = hostNode->GetContentNode();
74     CHECK_NULL_RETURN(contentNode, 0.0f);
75     auto navBarNode = hostNode->GetNavBarNode();
76     CHECK_NULL_RETURN(navBarNode, 0.0f);
77     auto index = hostNode->GetChildIndexById(navBarNode->GetId());
78     auto navBarWrapper = layoutWrapper->GetOrCreateChildByIndex(index);
79     CHECK_NULL_RETURN(navBarWrapper, 0.0f);
80     auto geometryNode = navBarWrapper->GetGeometryNode();
81     auto navigationGeometryNode = layoutWrapper->GetGeometryNode();
82     if (position == NavBarPosition::END) {
83         auto navBarOffset =
84             OffsetT<float>(navigationGeometryNode->GetFrameSize().Width() - geometryNode->GetFrameSize().Width(),
85                 geometryNode->GetFrameOffset().GetY());
86         geometryNode->SetMarginFrameOffset(navBarOffset);
87         navBarWrapper->Layout();
88         returnNavBarOffset = navBarOffset;
89         return geometryNode->GetFrameSize().Width();
90     }
91     auto navBarOffset = OffsetT<float>(0.0f, 0.0f);
92     geometryNode->SetMarginFrameOffset(navBarOffset);
93     navBarWrapper->Layout();
94     returnNavBarOffset = navBarOffset;
95     return geometryNode->GetFrameSize().Width();
96 }
97 
LayoutDivider(LayoutWrapper * layoutWrapper,const RefPtr<NavigationGroupNode> & hostNode,const RefPtr<NavigationLayoutProperty> & navigationLayoutProperty,float navBarWidth,const NavBarPosition & position)98 float LayoutDivider(LayoutWrapper* layoutWrapper, const RefPtr<NavigationGroupNode>& hostNode,
99     const RefPtr<NavigationLayoutProperty>& navigationLayoutProperty, float navBarWidth, const NavBarPosition& position)
100 {
101     auto dividerNode = hostNode->GetDividerNode();
102     CHECK_NULL_RETURN(dividerNode, 0.0f);
103     auto index = hostNode->GetChildIndexById(dividerNode->GetId());
104     auto dividerWrapper = layoutWrapper->GetOrCreateChildByIndex(index);
105     CHECK_NULL_RETURN(dividerWrapper, 0.0f);
106     auto geometryNode = dividerWrapper->GetGeometryNode();
107     auto navigationGeometryNode = layoutWrapper->GetGeometryNode();
108     OffsetT<float> dividerOffset;
109     if (position == NavBarPosition::END) {
110         dividerOffset = OffsetT<float>(
111             navigationGeometryNode->GetFrameSize().Width() - geometryNode->GetFrameSize().Width() - navBarWidth,
112             geometryNode->GetFrameOffset().GetY());
113     } else {
114         dividerOffset = OffsetT<float>(navBarWidth, geometryNode->GetFrameOffset().GetY());
115     }
116     geometryNode->SetMarginFrameOffset(dividerOffset);
117     dividerWrapper->Layout();
118     return geometryNode->GetFrameSize().Width();
119 }
120 
LayoutContent(LayoutWrapper * layoutWrapper,const RefPtr<NavigationGroupNode> & hostNode,const RefPtr<NavigationLayoutProperty> & navigationLayoutProperty,float navBarWidth,float dividerWidth,const NavBarPosition & position)121 void LayoutContent(LayoutWrapper* layoutWrapper, const RefPtr<NavigationGroupNode>& hostNode,
122     const RefPtr<NavigationLayoutProperty>& navigationLayoutProperty, float navBarWidth, float dividerWidth,
123     const NavBarPosition& position)
124 {
125     auto contentNode = hostNode->GetContentNode();
126     CHECK_NULL_VOID(contentNode);
127     auto index = hostNode->GetChildIndexById(contentNode->GetId());
128     auto contentWrapper = layoutWrapper->GetOrCreateChildByIndex(index);
129     CHECK_NULL_VOID(contentWrapper);
130     auto geometryNode = contentWrapper->GetGeometryNode();
131     CHECK_NULL_VOID(geometryNode);
132 
133     auto layoutAlgorithmWrapper = AceType::DynamicCast<LayoutAlgorithmWrapper>(layoutWrapper->GetLayoutAlgorithm());
134     CHECK_NULL_VOID(layoutAlgorithmWrapper);
135     auto navigationLayoutAlgorithm =
136         AceType::DynamicCast<NavigationLayoutAlgorithm>(layoutAlgorithmWrapper->GetLayoutAlgorithm());
137     auto contentChildSize = contentNode->GetChildren().size();
138 
139     if ((contentChildSize != 0 && navigationLayoutAlgorithm->GetNavigationMode() == NavigationMode::STACK) ||
140         position == NavBarPosition::END ||
141         (navigationLayoutProperty->GetHideNavBar().value_or(false) &&
142             navigationLayoutAlgorithm->GetNavigationMode() == NavigationMode::SPLIT)) {
143         auto contentOffset = OffsetT<float>(0.0f, 0.0f);
144         geometryNode->SetMarginFrameOffset(contentOffset);
145         contentWrapper->Layout();
146         return;
147     }
148     auto contentOffset = OffsetT<float>(navBarWidth + dividerWidth, geometryNode->GetFrameOffset().GetY());
149     geometryNode->SetMarginFrameOffset(contentOffset);
150     contentWrapper->Layout();
151 }
152 
FitScrollFullWindow(SizeF & frameSize)153 void FitScrollFullWindow(SizeF& frameSize)
154 {
155     auto pipeline = PipelineContext::GetCurrentContext();
156     CHECK_NULL_VOID_NOLOG(pipeline);
157     if (frameSize.Width() == Infinity<float>()) {
158         frameSize.SetWidth(pipeline->GetRootWidth());
159     }
160     if (frameSize.Height() == Infinity<float>()) {
161         frameSize.SetHeight(pipeline->GetRootHeight());
162     }
163 }
164 
165 } // namespace
166 
IsAutoHeight(const RefPtr<LayoutProperty> & layoutProperty)167 bool NavigationLayoutAlgorithm::IsAutoHeight(const RefPtr<LayoutProperty>& layoutProperty)
168 {
169     CHECK_NULL_RETURN(layoutProperty, false);
170     auto& calcLayoutConstraint = layoutProperty->GetCalcLayoutConstraint();
171     if (!calcLayoutConstraint || !calcLayoutConstraint->selfIdealSize.has_value() ||
172         !calcLayoutConstraint->selfIdealSize->Height().has_value() ||
173         (calcLayoutConstraint->selfIdealSize->Height().value().ToString().find("auto") == std::string::npos)) {
174             return false;
175         }
176     return true;
177 }
178 
RangeCalculation(const RefPtr<NavigationGroupNode> & hostNode,const RefPtr<NavigationLayoutProperty> & navigationLayoutProperty)179 void NavigationLayoutAlgorithm::RangeCalculation(
180     const RefPtr<NavigationGroupNode>& hostNode, const RefPtr<NavigationLayoutProperty>& navigationLayoutProperty)
181 {
182     const auto& constraint = navigationLayoutProperty->GetLayoutConstraint();
183     CHECK_NULL_VOID(constraint);
184     auto parentSize = CreateIdealSizeByPercentRef(constraint.value(), Axis::HORIZONTAL, MeasureType::MATCH_PARENT);
185     auto frameSize = parentSize.ConvertToSizeT();
186     float frameSizeWidth = frameSize.Width();
187     Dimension defaultValue = Dimension(-1.0);
188     auto pipeline = PipelineContext::GetCurrentContext();
189     CHECK_NULL_VOID(pipeline);
190 
191     minContentWidthValue_ = navigationLayoutProperty->GetMinContentWidthValue(defaultValue);
192     if (minContentWidthValue_ == defaultValue) {
193         userSetMinContentFlag_ = false;
194         minContentWidthValue_ = DEFAULT_MIN_CONTENT_WIDTH;
195     } else {
196         userSetMinContentFlag_ = true;
197     }
198     minNavBarWidthValue_ = navigationLayoutProperty->GetMinNavBarWidthValue(DEFAULT_MIN_NAV_BAR_WIDTH);
199     auto userSetMaxNavBarWidthValue = navigationLayoutProperty->GetMaxNavBarWidthValue(defaultValue);
200 
201     float minNavBarWidth =
202         std::min(static_cast<float>(minNavBarWidthValue_.ConvertToPxWithSize(parentSize.Width().value_or(0.0f))),
203             frameSizeWidth);
204     float maxNavBarWidth = 0.0f;
205     if (userSetMaxNavBarWidthValue == defaultValue) {
206         userSetNavBarRangeFlag_ = false;
207         maxNavBarWidth = std::min(
208             static_cast<float>(DEFAULT_MAX_NAV_BAR_WIDTH.ConvertToPx()), frameSizeWidth * MAX_NAV_BAR_WIDTH_SCALE);
209     } else {
210         userSetNavBarRangeFlag_ = true;
211         maxNavBarWidth =
212             static_cast<float>(userSetMaxNavBarWidthValue.ConvertToPxWithSize(parentSize.Width().value_or(0.0f)));
213     }
214     maxNavBarWidthValue_ = Dimension(std::max(maxNavBarWidth, minNavBarWidth), DimensionUnit::PX);
215     auto navBarWidthValue = navigationLayoutProperty->GetNavBarWidthValue(DEFAULT_NAV_BAR_WIDTH);
216     auto navBarWidth = navBarWidthValue.ConvertToPxWithSize(parentSize.Width().value_or(0.0f));
217     realNavBarWidth_ = navBarWidth;
218     auto currentPlatformVersion = pipeline->GetMinPlatformVersion();
219     if (currentPlatformVersion >= PLATFORM_VERSION_TEN) {
220         auto minNavBarWidth = minNavBarWidthValue_.ConvertToPxWithSize(parentSize.Width().value_or(0.0f));
221         auto maxNavBarWidth = maxNavBarWidthValue_.ConvertToPxWithSize(parentSize.Width().value_or(0.0f));
222         realNavBarWidth_ = std::max(realNavBarWidth_, static_cast<float>(minNavBarWidth));
223         realNavBarWidth_ = std::min(realNavBarWidth_, static_cast<float>(maxNavBarWidth));
224     }
225     auto navigationPattern = AceType::DynamicCast<NavigationPattern>(hostNode->GetPattern());
226     CHECK_NULL_VOID(navigationPattern);
227     navigationPattern->SetMinNavBarWidthValue(minNavBarWidthValue_);
228     navigationPattern->SetMaxNavBarWidthValue(maxNavBarWidthValue_);
229     navigationPattern->SetMinContentWidthValue(minContentWidthValue_);
230     navigationPattern->SetUserSetNavBarRangeFlag(userSetNavBarRangeFlag_);
231     navigationPattern->SetUserSetMinContentFlag(userSetMinContentFlag_);
232 }
233 
GetRange(const RefPtr<NavigationGroupNode> & hostNode)234 void NavigationLayoutAlgorithm::GetRange(const RefPtr<NavigationGroupNode>& hostNode)
235 {
236     auto navigationPattern = AceType::DynamicCast<NavigationPattern>(hostNode->GetPattern());
237     CHECK_NULL_VOID(navigationPattern);
238     minNavBarWidthValue_ = navigationPattern->GetMinNavBarWidthValue();
239     maxNavBarWidthValue_ = navigationPattern->GetMaxNavBarWidthValue();
240     minContentWidthValue_ = navigationPattern->GetMinContentWidthValue();
241     userSetNavBarRangeFlag_ = navigationPattern->GetUserSetNavBarRangeFlag();
242     userSetMinContentFlag_ = navigationPattern->GetUserSetMinContentFlag();
243     userSetNavBarWidthFlag_ = navigationPattern->GetUserSetNavBarWidthFlag();
244 }
245 
UpdateNavigationMode(const RefPtr<NavigationLayoutProperty> & navigationLayoutProperty,const SizeF & frameSize)246 void NavigationLayoutAlgorithm::UpdateNavigationMode(
247     const RefPtr<NavigationLayoutProperty>& navigationLayoutProperty, const SizeF& frameSize)
248 {
249     auto usrNavigationMode = navigationLayoutProperty->GetUsrNavigationModeValue(NavigationMode::AUTO);
250     auto pipeline = PipelineContext::GetCurrentContext();
251     CHECK_NULL_VOID(pipeline);
252     auto currentPlatformVersion = pipeline->GetMinPlatformVersion();
253 
254     auto navigationWidth = 0.0f;
255     if (currentPlatformVersion >= PLATFORM_VERSION_TEN) {
256         navigationWidth = static_cast<float>(minNavBarWidthValue_.ConvertToPx() + minContentWidthValue_.ConvertToPx());
257     } else {
258         navigationWidth = static_cast<float>(WINDOW_WIDTH.ConvertToPx());
259     }
260     if (usrNavigationMode == NavigationMode::AUTO) {
261         if (frameSize.Width() >= navigationWidth) {
262             usrNavigationMode = NavigationMode::SPLIT;
263         } else {
264             usrNavigationMode = NavigationMode::STACK;
265         }
266     }
267     SetNavigationMode(usrNavigationMode);
268 }
269 
SizeCalculation(LayoutWrapper * layoutWrapper,const RefPtr<NavigationGroupNode> & hostNode,const RefPtr<NavigationLayoutProperty> & navigationLayoutProperty,const SizeF & frameSize)270 void NavigationLayoutAlgorithm::SizeCalculation(LayoutWrapper* layoutWrapper,
271     const RefPtr<NavigationGroupNode>& hostNode, const RefPtr<NavigationLayoutProperty>& navigationLayoutProperty,
272     const SizeF& frameSize)
273 {
274     auto pipeline = PipelineContext::GetCurrentContext();
275     CHECK_NULL_VOID(pipeline);
276     auto constraint = navigationLayoutProperty->GetLayoutConstraint();
277     auto parentSize = CreateIdealSizeByPercentRef(constraint.value(), Axis::HORIZONTAL, MeasureType::MATCH_PARENT);
278     auto layoutAlgorithmWrapper = DynamicCast<LayoutAlgorithmWrapper>(layoutWrapper->GetLayoutAlgorithm());
279     CHECK_NULL_VOID(layoutAlgorithmWrapper);
280     auto navigationLayoutAlgorithm =
281         AceType::DynamicCast<NavigationLayoutAlgorithm>(layoutAlgorithmWrapper->GetLayoutAlgorithm());
282     auto currentPlatformVersion = pipeline->GetMinPlatformVersion();
283     if (currentPlatformVersion >= PLATFORM_VERSION_TEN) {
284         auto minNavBarWidth = minNavBarWidthValue_.ConvertToPxWithSize(parentSize.Width().value_or(0.0f));
285         auto maxNavBarWidth = maxNavBarWidthValue_.ConvertToPxWithSize(parentSize.Width().value_or(0.0f));
286         realNavBarWidth_ = std::min(realNavBarWidth_, static_cast<float>(maxNavBarWidth));
287         realNavBarWidth_ = std::max(realNavBarWidth_, static_cast<float>(minNavBarWidth));
288     } else {
289         auto navBarWidthValue = navigationLayoutProperty->GetNavBarWidthValue(DEFAULT_NAV_BAR_WIDTH);
290         auto navBarWidth = navBarWidthValue.ConvertToPxWithSize(parentSize.Width().value_or(0.0f));
291         realNavBarWidth_ = navBarWidth;
292     }
293     navBarSize_ = frameSize;
294     contentSize_ = frameSize;
295     dividerSize_ = SizeF(0.0f, frameSize.Height());
296     if (GetNavigationMode() == NavigationMode::SPLIT) {
297         SizeCalculationSplit(navigationLayoutProperty, frameSize);
298     } else {
299         SizeCalculationStack(hostNode, navigationLayoutProperty, frameSize);
300     }
301 }
302 
SizeCalculationSplit(const RefPtr<NavigationLayoutProperty> & navigationLayoutProperty,const SizeF & frameSize)303 void NavigationLayoutAlgorithm::SizeCalculationSplit(
304     const RefPtr<NavigationLayoutProperty>& navigationLayoutProperty, const SizeF& frameSize)
305 {
306     float frameWidth = frameSize.Width();
307     auto parentSize = CreateIdealSizeByPercentRef(
308         navigationLayoutProperty->GetLayoutConstraint().value(), Axis::HORIZONTAL, MeasureType::MATCH_PARENT);
309     auto navBarWidthValue = navigationLayoutProperty->GetNavBarWidthValue(DEFAULT_NAV_BAR_WIDTH);
310     auto userSetNavBarWidth = navBarWidthValue.ConvertToPxWithSize(parentSize.Width().value_or(0.0f));
311     auto dividerWidth = static_cast<float>(DIVIDER_WIDTH.ConvertToPx());
312     auto minNavBarWidth = minNavBarWidthValue_.ConvertToPxWithSize(parentSize.Width().value_or(0.0f));
313     auto minContentWidth = minContentWidthValue_.ConvertToPxWithSize(parentSize.Width().value_or(0.0f));
314     realContentWidth_ = minContentWidth;
315 
316     if (navigationLayoutProperty->GetHideNavBar().value_or(false)) {
317         navBarSize_ = SizeF(0.0f, 0.0f);
318         dividerSize_ = SizeF(0.0f, 0.0f);
319         realNavBarWidth_ = 0.0f;
320         realContentWidth_ = frameWidth;
321     } else {
322         CheckSizeInSplit(frameWidth, userSetNavBarWidth, minNavBarWidth, minContentWidth);
323     }
324 
325     realDividerWidth_ = std::max(realDividerWidth_, 0.0f);
326     realContentWidth_ = std::max(realContentWidth_, 0.0f);
327     realNavBarWidth_ = std::min(realNavBarWidth_, frameWidth);
328     realContentWidth_ = std::min(realContentWidth_, frameWidth);
329     if (realNavBarWidth_ == 0.0f || realContentWidth_ == 0.0f) {
330         realDividerWidth_ = 0.0f;
331     } else {
332         realDividerWidth_ = dividerWidth;
333     }
334     navBarSize_.SetWidth(realNavBarWidth_);
335     dividerSize_.SetWidth(realDividerWidth_);
336     contentSize_.SetWidth(realContentWidth_);
337 }
338 
CheckSizeInSplit(const float frameWidth,const float userSetNavBarWidth,const float minNavBarWidth,const float minContentWidth)339 void NavigationLayoutAlgorithm::CheckSizeInSplit(
340     const float frameWidth, const float userSetNavBarWidth, const float minNavBarWidth, const float minContentWidth)
341 {
342     auto dividerWidth = static_cast<float>(DIVIDER_WIDTH.ConvertToPx());
343 
344     if (userSetMinContentFlag_ && !userSetNavBarRangeFlag_) {
345         if (minContentWidth >= frameWidth) {
346             realContentWidth_ = frameWidth;
347             realNavBarWidth_ = 0.0f;
348         } else if (realNavBarWidth_ + dividerWidth + minContentWidth <= frameWidth) {
349             realContentWidth_ = frameWidth - realNavBarWidth_ - dividerWidth;
350         } else {
351             realContentWidth_ = minContentWidth;
352             realNavBarWidth_ = frameWidth - realContentWidth_ - dividerWidth;
353         }
354     } else if (!userSetNavBarRangeFlag_ && !userSetMinContentFlag_ && userSetNavBarWidthFlag_) {
355         realNavBarWidth_ = userSetNavBarWidth;
356         realContentWidth_ = frameWidth - realNavBarWidth_ - dividerWidth;
357     } else {
358         float remainingSpace = frameWidth - realNavBarWidth_ - dividerWidth;
359         float remainingMaxSpace = frameWidth - minNavBarWidth - dividerWidth;
360         if (remainingSpace >= minContentWidth) {
361             realContentWidth_ = remainingSpace;
362         } else if (remainingSpace < minContentWidth && remainingMaxSpace > minContentWidth &&
363                    realNavBarWidth_ > minNavBarWidth) {
364             realContentWidth_ = minContentWidth;
365             realNavBarWidth_ = frameWidth - minContentWidth - dividerWidth;
366         } else {
367             realNavBarWidth_ = minNavBarWidth;
368             realContentWidth_ = frameWidth - minNavBarWidth - dividerWidth;
369         }
370     }
371 }
372 
SizeCalculationStack(const RefPtr<NavigationGroupNode> & hostNode,const RefPtr<NavigationLayoutProperty> & navigationLayoutProperty,const SizeF & frameSize)373 void NavigationLayoutAlgorithm::SizeCalculationStack(const RefPtr<NavigationGroupNode>& hostNode,
374     const RefPtr<NavigationLayoutProperty>& navigationLayoutProperty, const SizeF& frameSize)
375 {
376     auto contentNode = hostNode->GetContentNode();
377     CHECK_NULL_VOID(contentNode);
378     realDividerWidth_ = 0.0f;
379     float frameWidth = frameSize.Width();
380     realContentWidth_ = frameWidth;
381     navBarSize_.SetWidth(frameWidth);
382     dividerSize_.SetWidth(realDividerWidth_);
383     contentSize_.SetWidth(realContentWidth_);
384 
385 }
386 
MeasureNavBar(LayoutWrapper * layoutWrapper,const RefPtr<NavigationGroupNode> & hostNode,const RefPtr<NavigationLayoutProperty> & navigationLayoutProperty,const SizeF & navBarSize)387 void NavigationLayoutAlgorithm::MeasureNavBar(LayoutWrapper* layoutWrapper, const RefPtr<NavigationGroupNode>& hostNode,
388     const RefPtr<NavigationLayoutProperty>& navigationLayoutProperty, const SizeF& navBarSize)
389 {
390     auto navBarNode = hostNode->GetNavBarNode();
391     CHECK_NULL_VOID(navBarNode);
392     auto index = hostNode->GetChildIndexById(navBarNode->GetId());
393     auto navBarWrapper = layoutWrapper->GetOrCreateChildByIndex(index);
394     CHECK_NULL_VOID(navBarWrapper);
395     auto constraint = navigationLayoutProperty->CreateChildConstraint();
396     if (IsAutoHeight(navigationLayoutProperty)) {
397         navBarWrapper->GetLayoutProperty()->UpdateUserDefinedIdealSize(
398             navigationLayoutProperty->GetCalcLayoutConstraint()->selfIdealSize.value());
399         constraint.selfIdealSize.SetWidth(navBarSize.Width());
400     } else {
401         constraint.selfIdealSize = OptionalSizeF(navBarSize.Width(), navBarSize.Height());
402     }
403     navBarWrapper->Measure(constraint);
404     realNavBarHeight_ = navBarWrapper->GetGeometryNode()->GetFrameSize().Height();
405 }
406 
MeasureContentChild(LayoutWrapper * layoutWrapper,const RefPtr<NavigationGroupNode> & hostNode,const RefPtr<NavigationLayoutProperty> & navigationLayoutProperty,const SizeF & contentSize)407 void NavigationLayoutAlgorithm::MeasureContentChild(LayoutWrapper* layoutWrapper,
408     const RefPtr<NavigationGroupNode>& hostNode, const RefPtr<NavigationLayoutProperty>& navigationLayoutProperty,
409     const SizeF& contentSize)
410 {
411     auto contentNode = hostNode->GetContentNode();
412     CHECK_NULL_VOID(contentNode);
413     auto index = hostNode->GetChildIndexById(contentNode->GetId());
414     auto contentWrapper = layoutWrapper->GetOrCreateChildByIndex(index);
415     CHECK_NULL_VOID(contentWrapper);
416     auto constraint = navigationLayoutProperty->CreateChildConstraint();
417     if (contentNode->GetChildren().empty()) {
418         constraint.selfIdealSize = OptionalSizeF(0.0f, 0.0f);
419     } else {
420         if (IsAutoHeight(navigationLayoutProperty)) {
421             constraint.selfIdealSize.SetWidth(contentSize.Width());
422         } else {
423             constraint.selfIdealSize = OptionalSizeF(contentSize.Width(), contentSize.Height());
424         }
425     }
426     contentWrapper->Measure(constraint);
427     realContentHeight_ = contentWrapper->GetGeometryNode()->GetFrameSize().Height();
428 }
429 
Measure(LayoutWrapper * layoutWrapper)430 void NavigationLayoutAlgorithm::Measure(LayoutWrapper* layoutWrapper)
431 {
432     auto hostNode = AceType::DynamicCast<NavigationGroupNode>(layoutWrapper->GetHostNode());
433     CHECK_NULL_VOID(hostNode);
434     auto navigationLayoutProperty = AceType::DynamicCast<NavigationLayoutProperty>(layoutWrapper->GetLayoutProperty());
435     CHECK_NULL_VOID(navigationLayoutProperty);
436     const auto& constraint = navigationLayoutProperty->GetLayoutConstraint();
437     CHECK_NULL_VOID(constraint);
438     auto geometryNode = layoutWrapper->GetGeometryNode();
439     auto size =
440         CreateIdealSizeByPercentRef(constraint.value(), Axis::HORIZONTAL, MeasureType::MATCH_PARENT).ConvertToSizeT();
441     FitScrollFullWindow(size);
442     const auto& padding = layoutWrapper->GetLayoutProperty()->CreatePaddingAndBorder();
443     MinusPaddingToSize(padding, size);
444     if (ifNeedInit_) {
445         RangeCalculation(hostNode, navigationLayoutProperty);
446     }
447     if (size.Width() == 0.0f) {
448         return;
449     }
450     GetRange(hostNode);
451     UpdateNavigationMode(navigationLayoutProperty, size);
452     SizeCalculation(layoutWrapper, hostNode, navigationLayoutProperty, size);
453 
454     MeasureNavBar(layoutWrapper, hostNode, navigationLayoutProperty, navBarSize_);
455     MeasureContentChild(layoutWrapper, hostNode, navigationLayoutProperty, contentSize_);
456     MeasureDivider(layoutWrapper, hostNode, navigationLayoutProperty, dividerSize_);
457     if (IsAutoHeight(navigationLayoutProperty)) {
458         SetNavigationHeight(layoutWrapper, size);
459     }
460     layoutWrapper->GetGeometryNode()->SetFrameSize(size);
461 }
462 
Layout(LayoutWrapper * layoutWrapper)463 void NavigationLayoutAlgorithm::Layout(LayoutWrapper* layoutWrapper)
464 {
465     auto hostNode = AceType::DynamicCast<NavigationGroupNode>(layoutWrapper->GetHostNode());
466     CHECK_NULL_VOID(hostNode);
467     auto navigationLayoutProperty = AceType::DynamicCast<NavigationLayoutProperty>(layoutWrapper->GetLayoutProperty());
468     CHECK_NULL_VOID(navigationLayoutProperty);
469     auto navBarPosition = navigationLayoutProperty->GetNavBarPositionValue(NavBarPosition::START);
470     OffsetF navBarOffset(0.0, 0.0);
471     float navBarWidth = LayoutNavBar(layoutWrapper, hostNode, navigationLayoutProperty, navBarPosition, navBarOffset);
472     float dividerWidth = LayoutDivider(layoutWrapper, hostNode, navigationLayoutProperty, navBarWidth, navBarPosition);
473     LayoutContent(layoutWrapper, hostNode, navigationLayoutProperty, navBarWidth, dividerWidth, navBarPosition);
474     navBarOffset_ = navBarOffset;
475 }
476 
SetNavigationHeight(LayoutWrapper * layoutWrapper,SizeF & size)477 void NavigationLayoutAlgorithm::SetNavigationHeight(LayoutWrapper* layoutWrapper, SizeF& size)
478 {
479 
480     auto hostNode = AceType::DynamicCast<NavigationGroupNode>(layoutWrapper->GetHostNode());
481     CHECK_NULL_VOID(hostNode);
482     auto navigationPattern = AceType::DynamicCast<NavigationPattern>(hostNode->GetPattern());
483     CHECK_NULL_VOID(navigationPattern);
484     auto navigationStack = navigationPattern->GetNavigationStack();
485     CHECK_NULL_VOID(navigationStack);
486     if (navigationStack->Empty()) {
487         size.SetHeight(realNavBarHeight_);
488     } else if (navigationMode_ == NavigationMode::STACK) {
489         size.SetHeight(realContentHeight_);
490     } else if (navigationMode_ == NavigationMode::SPLIT) {
491         float navHeight = std::max(realContentHeight_, realNavBarHeight_);
492         size.SetHeight(navHeight);
493     }
494 }
495 
496 } // namespace OHOS::Ace::NG
497