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