1 /*
2 * Copyright (c) 2022-2023 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/side_bar/side_bar_container_layout_algorithm.h"
17
18 #include "core/components_ng/pattern/side_bar/side_bar_container_pattern.h"
19 #include "core/components_ng/property/measure_utils.h"
20 namespace OHOS::Ace::NG {
21
22 namespace {
23 constexpr int32_t DEFAULT_MIN_CHILDREN_SIZE = 3;
24 constexpr Dimension DEFAULT_CONTROL_BUTTON_LEFT = 16.0_vp;
25 constexpr Dimension DEFAULT_CONTROL_BUTTON_TOP = 48.0_vp;
26 constexpr Dimension DEFAULT_MAX_SIDE_BAR_WIDTH = 280.0_vp;
27 constexpr Dimension DEFAULT_DIVIDER_STROKE_WIDTH = 1.0_vp;
28 constexpr Dimension DEFAULT_DIVIDER_START_MARGIN = 0.0_vp;
29 constexpr Dimension DEFAULT_DIVIDER_END_MARGIN = 0.0_vp;
30
31 constexpr static int INDEX_CONTRON_BUTTON = 1;
32 constexpr static int INDEX_DIVIDER = 2;
33 constexpr static int INDEX_SIDE_BAR = 3;
34 constexpr static int32_t PLATFORM_VERSION_TEN = 10;
35 static Dimension DEFAULT_SIDE_BAR_WIDTH = 200.0_vp;
36 static Dimension DEFAULT_MIN_SIDE_BAR_WIDTH = 200.0_vp;
37 static Dimension DEFAULT_MIN_CONTENT_WIDTH = 0.0_vp;
38 constexpr Dimension CONTROL_BUTTON_PADDING = 12.0_vp;
39 } // namespace
40
Measure(LayoutWrapper * layoutWrapper)41 void SideBarContainerLayoutAlgorithm::Measure(LayoutWrapper* layoutWrapper)
42 {
43 autoHide_ = false;
44 CHECK_NULL_VOID(layoutWrapper);
45 UpdateDefaultValueByVersion(layoutWrapper);
46 const auto& children = layoutWrapper->GetAllChildrenWithBuild(layoutWrapper->IsActive());
47 if (children.size() < DEFAULT_MIN_CHILDREN_SIZE) {
48 return;
49 }
50 auto layoutProperty = AceType::DynamicCast<SideBarContainerLayoutProperty>(layoutWrapper->GetLayoutProperty());
51 CHECK_NULL_VOID(layoutProperty);
52 const auto& constraint = layoutProperty->GetLayoutConstraint();
53 auto hostNode = layoutWrapper->GetHostNode();
54 CHECK_NULL_VOID(hostNode);
55 auto pipeline = hostNode->GetContextRefPtr();
56 CHECK_NULL_VOID(pipeline);
57 auto idealSize = pipeline->GetMinPlatformVersion() >= PLATFORM_VERSION_TEN ?
58 CreateIdealSizeByPercentRef(constraint.value(), Axis::HORIZONTAL,
59 layoutProperty->GetMeasureType(MeasureType::MATCH_PARENT)).ConvertToSizeT() :
60 CreateIdealSize(
61 constraint.value(), Axis::HORIZONTAL, layoutProperty->GetMeasureType(MeasureType::MATCH_PARENT), true);
62 layoutWrapper->GetGeometryNode()->SetFrameSize(idealSize);
63
64 AdjustMinAndMaxSideBarWidth(layoutWrapper);
65
66 auto parentWidth = idealSize.Width();
67 realSideBarWidth_ = ConvertToPx(realSideBarWidthDimension_, constraint->scaleProperty, parentWidth).value_or(-1.0f);
68 if (needInitRealSideBarWidth_ || NearZero(realSideBarWidth_)) {
69 if (pipeline->GetMinPlatformVersion() >= PLATFORM_VERSION_TEN) {
70 GetAllPropertyValue(layoutProperty, layoutWrapper, parentWidth);
71 } else {
72 InitRealSideBarWidth(layoutWrapper, parentWidth);
73 }
74 }
75
76 if (parentWidth >= typeUpdateWidth_) {
77 type_ = layoutProperty->GetSideBarContainerType().value_or(SideBarContainerType::EMBED);
78 }
79
80 auto type = layoutProperty->GetSideBarContainerType().value_or(SideBarContainerType::EMBED);
81 if (type == SideBarContainerType::AUTO) {
82 AutoMode(layoutProperty, parentWidth);
83 }
84
85 if ((parentWidth < typeUpdateWidth_) && (!layoutProperty->GetShowSideBar().has_value()) &&
86 (type_ != SideBarContainerType::OVERLAY)) {
87 if (isControlButtonClick_) {
88 type_ = SideBarContainerType::OVERLAY;
89 } else if (layoutProperty->GetAutoHide().value_or(true)) {
90 sideBarStatus_ = SideBarStatus::HIDDEN;
91 autoHide_ = true;
92 }
93 }
94 if (type_ != SideBarContainerType::OVERLAY) {
95 AutoChangeSideBarWidth(layoutProperty, parentWidth);
96 }
97
98 /*
99 * child inverted order is: controlbutton, divider, sidebar, contentxxx, ..., content2, content1
100 * content only display the first one, use itor from end
101 */
102 int index = 0;
103 RefPtr<LayoutWrapper> dividerLayoutWrapper = nullptr;
104 for (auto it = children.rbegin(); it != children.rend(); ++it) {
105 index++;
106 if (index == INDEX_CONTRON_BUTTON) {
107 auto imgLayoutWrapper = (*it);
108 MeasureControlButton(layoutProperty, imgLayoutWrapper, parentWidth);
109 } else if (index == INDEX_DIVIDER) {
110 dividerLayoutWrapper = (*it);
111 } else if (index == INDEX_SIDE_BAR) {
112 auto sideBarLayoutWrapper = (*it);
113 MeasureSideBar(layoutProperty, sideBarLayoutWrapper);
114 } else { // other break
115 continue;
116 }
117 }
118
119 if (dividerLayoutWrapper) {
120 MeasureDivider(layoutProperty, dividerLayoutWrapper, parentWidth);
121 }
122
123 if (children.size() > DEFAULT_MIN_CHILDREN_SIZE) { // when sidebar only add one component, content is not display
124 auto contentLayoutWrapper = children.front();
125 MeasureSideBarContent(layoutProperty, contentLayoutWrapper, parentWidth);
126 }
127
128 if (realSideBarWidthDimension_.Unit() == DimensionUnit::PERCENT) {
129 realSideBarWidthDimension_ = NearZero(parentWidth)
130 ? Dimension(0.0, DimensionUnit::PERCENT)
131 : Dimension(realSideBarWidth_ / parentWidth, DimensionUnit::PERCENT);
132 } else {
133 realSideBarWidthDimension_ = Dimension(realSideBarWidth_, DimensionUnit::PX);
134 }
135
136 AddChildToIgnoreLayoutSafeBundle(layoutWrapper);
137 }
138
AddChildToIgnoreLayoutSafeBundle(LayoutWrapper * layoutWrapper)139 void SideBarContainerLayoutAlgorithm::AddChildToIgnoreLayoutSafeBundle(LayoutWrapper* layoutWrapper)
140 {
141 const auto& children = layoutWrapper->GetAllChildrenWithBuild(layoutWrapper->IsActive());
142 auto host = layoutWrapper->GetHostNode();
143 CHECK_NULL_VOID(host);
144 auto layoutConstraint = layoutWrapper->GetLayoutProperty()->CreateChildConstraint();
145 auto context = host->GetContext();
146 CHECK_NULL_VOID(context);
147 IgnoreLayoutSafeAreaBundle bundle;
148 int32_t index = 0;
149 for (auto it = children.rbegin(); it != children.rend(); ++it) {
150 index++;
151 if (index != INDEX_SIDE_BAR) {
152 continue;
153 }
154 auto sideBarLayoutWrapper = (*it);
155 CHECK_NULL_VOID(sideBarLayoutWrapper);
156 auto sideBarNode = sideBarLayoutWrapper->GetHostNode();
157 CHECK_NULL_VOID(sideBarNode);
158 auto sideBarLayoutProperty = sideBarNode->GetLayoutProperty();
159 if (sideBarLayoutProperty && sideBarLayoutProperty->IsExpandConstraintNeeded()) {
160 bundle.first.emplace_back(sideBarNode);
161 auto sideBarGeo = sideBarLayoutWrapper->GetGeometryNode();
162 CHECK_NULL_VOID(sideBarGeo);
163 layoutConstraint.parentIdealSize.SetSize(sideBarGeo->GetFrameSize());
164 sideBarGeo->SetParentLayoutConstraint(layoutConstraint);
165 SetNeedPostponeForIgnore();
166 }
167 }
168 if (children.size() > DEFAULT_MIN_CHILDREN_SIZE) { // when sidebar only add one component, content is not display
169 auto contentLayoutWrapper = children.front();
170 CHECK_NULL_VOID(contentLayoutWrapper);
171 auto contentNode = contentLayoutWrapper->GetHostNode();
172 CHECK_NULL_VOID(contentNode);
173 auto contentLayoutProperty = contentNode->GetLayoutProperty();
174 if (contentLayoutProperty && contentLayoutProperty->IsExpandConstraintNeeded()) {
175 bundle.first.emplace_back(contentNode);
176 auto contentGeo = contentLayoutWrapper->GetGeometryNode();
177 CHECK_NULL_VOID(contentGeo);
178 layoutConstraint.parentIdealSize.SetSize(contentGeo->GetFrameSize());
179 contentGeo->SetParentLayoutConstraint(layoutConstraint);
180 SetNeedPostponeForIgnore();
181 }
182 }
183 if (GetNeedPostponeForIgnore()) {
184 bundle.second = host;
185 context->AddIgnoreLayoutSafeAreaBundle(std::move(bundle));
186 }
187 }
188
UpdateDefaultValueByVersion(LayoutWrapper * layoutWrapper)189 void SideBarContainerLayoutAlgorithm::UpdateDefaultValueByVersion(LayoutWrapper* layoutWrapper)
190 {
191 CHECK_NULL_VOID(layoutWrapper);
192 auto hostNode = layoutWrapper->GetHostNode();
193 CHECK_NULL_VOID(hostNode);
194 auto pipeline = hostNode->GetContextRefPtr();
195 CHECK_NULL_VOID(pipeline);
196 if (pipeline->GetMinPlatformVersion() >= PLATFORM_VERSION_TEN) {
197 DEFAULT_SIDE_BAR_WIDTH = 240.0_vp;
198 DEFAULT_MIN_SIDE_BAR_WIDTH = 240.0_vp;
199 DEFAULT_MIN_CONTENT_WIDTH = 360.0_vp;
200 }
201 }
202
GetSideBarLayoutWrapper(LayoutWrapper * layoutWrapper) const203 RefPtr<LayoutWrapper> SideBarContainerLayoutAlgorithm::GetSideBarLayoutWrapper(LayoutWrapper* layoutWrapper) const
204 {
205 CHECK_NULL_RETURN(layoutWrapper, nullptr);
206 const auto& children = layoutWrapper->GetAllChildrenWithBuild(layoutWrapper->IsActive());
207 if (children.size() < DEFAULT_MIN_CHILDREN_SIZE) {
208 return nullptr;
209 }
210
211 int index = 0;
212 for (auto it = children.rbegin(); it != children.rend(); ++it) {
213 index++;
214 if (index == INDEX_SIDE_BAR) {
215 return (*it);
216 }
217 }
218
219 return nullptr;
220 }
221
AdjustMinAndMaxSideBarWidth(LayoutWrapper * layoutWrapper)222 void SideBarContainerLayoutAlgorithm::AdjustMinAndMaxSideBarWidth(LayoutWrapper* layoutWrapper)
223 {
224 adjustMinSideBarWidth_ = DEFAULT_MIN_SIDE_BAR_WIDTH;
225 adjustMaxSideBarWidth_ = DEFAULT_MAX_SIDE_BAR_WIDTH;
226 CHECK_NULL_VOID(layoutWrapper);
227 auto layoutProperty = AceType::DynamicCast<SideBarContainerLayoutProperty>(layoutWrapper->GetLayoutProperty());
228 CHECK_NULL_VOID(layoutProperty);
229
230 auto hostNode = layoutWrapper->GetHostNode();
231 CHECK_NULL_VOID(hostNode);
232 auto pipeline = hostNode->GetContextRefPtr();
233 CHECK_NULL_VOID(pipeline);
234
235 if (pipeline->GetMinPlatformVersion() < PLATFORM_VERSION_TEN) {
236 adjustMinSideBarWidth_ = layoutProperty->GetMinSideBarWidth().value_or(DEFAULT_MIN_SIDE_BAR_WIDTH);
237 adjustMaxSideBarWidth_ = layoutProperty->GetMaxSideBarWidth().value_or(DEFAULT_MAX_SIDE_BAR_WIDTH);
238 if (adjustMinSideBarWidth_ > adjustMaxSideBarWidth_) {
239 adjustMinSideBarWidth_ = DEFAULT_MIN_SIDE_BAR_WIDTH;
240 adjustMaxSideBarWidth_ = DEFAULT_MAX_SIDE_BAR_WIDTH;
241 }
242 return;
243 }
244
245 auto sideBarLayoutWrapper = GetSideBarLayoutWrapper(layoutWrapper);
246 CHECK_NULL_VOID(sideBarLayoutWrapper);
247
248 auto sideBarLayoutProperty = sideBarLayoutWrapper->GetLayoutProperty();
249 CHECK_NULL_VOID(sideBarLayoutProperty);
250
251 auto&& calcConstraint = sideBarLayoutProperty->GetCalcLayoutConstraint();
252 if (layoutProperty->GetMinSideBarWidth().has_value()) {
253 adjustMinSideBarWidth_ = layoutProperty->GetMinSideBarWidthValue();
254 } else if (calcConstraint && calcConstraint->minSize.has_value() &&
255 calcConstraint->minSize.value().Width().has_value()) {
256 adjustMinSideBarWidth_ = calcConstraint->minSize->Width()->GetDimension();
257 }
258
259 if (layoutProperty->GetMaxSideBarWidth().has_value()) {
260 adjustMaxSideBarWidth_ = layoutProperty->GetMaxSideBarWidthValue();
261 } else if (calcConstraint && calcConstraint->maxSize.has_value() && calcConstraint->maxSize->Width().has_value()) {
262 adjustMaxSideBarWidth_ = calcConstraint->maxSize->Width()->GetDimension();
263 }
264
265 if (adjustMinSideBarWidth_ > adjustMaxSideBarWidth_) {
266 adjustMinSideBarWidth_ = DEFAULT_MIN_SIDE_BAR_WIDTH;
267 adjustMaxSideBarWidth_ = DEFAULT_MAX_SIDE_BAR_WIDTH;
268 }
269 }
270
GetAllPropertyValue(const RefPtr<SideBarContainerLayoutProperty> & layoutProperty,LayoutWrapper * layoutWrapper,float parentWidth)271 void SideBarContainerLayoutAlgorithm::GetAllPropertyValue(
272 const RefPtr<SideBarContainerLayoutProperty>& layoutProperty, LayoutWrapper* layoutWrapper, float parentWidth)
273 {
274 const auto& constraint = layoutProperty->GetLayoutConstraint();
275 const auto& scaleProperty = constraint->scaleProperty;
276 auto realSideBarWidth = GetSideBarWidth(layoutProperty, layoutWrapper);
277 auto minSideBarWidth = layoutProperty->GetMinSideBarWidth().value_or(-1.0_vp);
278 auto minContentWidth = layoutProperty->GetMinContentWidth().value_or(-1.0_vp);
279 auto maxSideBarWidth = layoutProperty->GetMaxSideBarWidth().value_or(-1.0_vp);
280
281 realSideBarWidth_ = ConvertToPx(realSideBarWidth, scaleProperty, parentWidth).value_or(-1.0f);
282 if (preSideBarWidth_.IsValid()) {
283 realSideBarWidth_ = ConvertToPx(preSideBarWidth_, scaleProperty, parentWidth).value_or(-1.0f);
284 }
285
286 minSideBarWidth_ = ConvertToPx(minSideBarWidth, scaleProperty, parentWidth).value_or(-1.0f);
287 minContentWidth_ = ConvertToPx(minContentWidth, scaleProperty, parentWidth).value_or(-1.0f);
288 maxSideBarWidth_ = ConvertToPx(maxSideBarWidth, scaleProperty, parentWidth).value_or(-1.0f);
289
290 defaultRealSideBarWidth_ = ConvertToPx(DEFAULT_SIDE_BAR_WIDTH, scaleProperty, parentWidth).value_or(-1.0f);
291 defaultMinSideBarWidth_ = ConvertToPx(DEFAULT_MIN_SIDE_BAR_WIDTH, scaleProperty, parentWidth).value_or(-1.0f);
292 defaultMaxSideBarWidth_ = ConvertToPx(DEFAULT_MAX_SIDE_BAR_WIDTH, scaleProperty, parentWidth).value_or(-1.0f);
293 defaultMinContentWidth_ = ConvertToPx(DEFAULT_MIN_CONTENT_WIDTH, scaleProperty, parentWidth).value_or(-1.0f);
294
295 MeasureTypeUpdateWidth();
296 minContentWidth_ = std::max(0.0f, minContentWidth_);
297 InitSideBarWidth(parentWidth);
298 MeasureRealSideBarWidth(parentWidth);
299
300 auto sideBarContainerPattern = AceType::DynamicCast<SideBarContainerPattern>(pattern_.Upgrade());
301 sideBarContainerPattern->SetMinSideBarWidth(minSideBarWidth_);
302 sideBarContainerPattern->SetMaxSideBarWidth(maxSideBarWidth_);
303 sideBarContainerPattern->SetMinContentWidth(minContentWidth_);
304 sideBarContainerPattern->SetTypeUpdateWidth(typeUpdateWidth_);
305 }
306
GetSideBarWidth(const RefPtr<SideBarContainerLayoutProperty> & layoutProperty,LayoutWrapper * layoutWrapper)307 Dimension SideBarContainerLayoutAlgorithm::GetSideBarWidth(
308 const RefPtr<SideBarContainerLayoutProperty>& layoutProperty, LayoutWrapper* layoutWrapper)
309 {
310 CHECK_NULL_RETURN(layoutProperty, -1.0_vp);
311 if (layoutProperty->GetSideBarWidth().has_value()) {
312 return layoutProperty->GetSideBarWidth().value();
313 }
314 auto hostNode = layoutWrapper->GetHostNode();
315 CHECK_NULL_RETURN(hostNode, -1.0_vp);
316 auto pipelineContext = hostNode->GetContext();
317 CHECK_NULL_RETURN(pipelineContext, -1.0_vp);
318 auto searchTheme = pipelineContext->GetTheme<SideBarTheme>();
319 CHECK_NULL_RETURN(searchTheme, -1.0_vp);
320 return searchTheme->GetSideBarWidth();
321 }
322
MeasureTypeUpdateWidth()323 void SideBarContainerLayoutAlgorithm::MeasureTypeUpdateWidth()
324 {
325 if (minSideBarWidth_ >= 0.0f && minContentWidth_ >= 0.0f) {
326 typeUpdateWidth_ = minSideBarWidth_ + minContentWidth_;
327 return;
328 } else if (minSideBarWidth_ >= 0.0f) {
329 typeUpdateWidth_ = minSideBarWidth_ + defaultMinContentWidth_;
330 } else if (minContentWidth_ >= 0.0f) {
331 typeUpdateWidth_ = minContentWidth_ + defaultMinSideBarWidth_;
332 } else {
333 typeUpdateWidth_ = defaultMinSideBarWidth_ + defaultMinContentWidth_;
334 }
335 if (typeUpdateWidth_ < defaultMinSideBarWidth_ + defaultMinContentWidth_) {
336 typeUpdateWidth_ = defaultMinSideBarWidth_ + defaultMinContentWidth_;
337 }
338 }
339
InitSideBarWidth(float parentWidth)340 void SideBarContainerLayoutAlgorithm::InitSideBarWidth(float parentWidth)
341 {
342 if (minSideBarWidth_ >= parentWidth) {
343 minSideBarWidth_ = parentWidth;
344 maxSideBarWidth_ = parentWidth;
345 realSideBarWidth_ = parentWidth;
346 minContentWidth_ = 0.0f;
347 return;
348 }
349
350 if (maxSideBarWidth_ >= parentWidth) {
351 maxSideBarWidth_ = parentWidth;
352 if (realSideBarWidth_ <= minSideBarWidth_) {
353 realSideBarWidth_ = minSideBarWidth_;
354 } else if (realSideBarWidth_ >= maxSideBarWidth_) {
355 realSideBarWidth_ = maxSideBarWidth_;
356 }
357 return;
358 }
359 if (minSideBarWidth_ >= 0.0f && maxSideBarWidth_ >= 0.0f) {
360 if (minSideBarWidth_ >= maxSideBarWidth_) {
361 maxSideBarWidth_ = minSideBarWidth_;
362 realSideBarWidth_ = minSideBarWidth_;
363 return;
364 }
365 }
366
367 if (realSideBarWidth_ < 0.0f) {
368 return;
369 }
370 if (realSideBarWidth_ <= minSideBarWidth_) {
371 realSideBarWidth_ = minSideBarWidth_;
372 return;
373 } else if (realSideBarWidth_ >= maxSideBarWidth_ && maxSideBarWidth_ >= 0) {
374 realSideBarWidth_ = maxSideBarWidth_;
375 return;
376 } else if (realSideBarWidth_ >= parentWidth) {
377 realSideBarWidth_ = parentWidth;
378 }
379 }
380
MeasureRealSideBarWidth(float parentWidth)381 void SideBarContainerLayoutAlgorithm::MeasureRealSideBarWidth(float parentWidth)
382 {
383 if (minSideBarWidth_ < 0.0f) {
384 if (realSideBarWidth_ >= 0.0f) {
385 minSideBarWidth_ = realSideBarWidth_;
386 } else if (maxSideBarWidth_ >= 0.0f) {
387 minSideBarWidth_ = maxSideBarWidth_;
388 } else {
389 minSideBarWidth_ = defaultMinSideBarWidth_;
390 }
391 if (minSideBarWidth_ >= defaultMinSideBarWidth_) {
392 minSideBarWidth_ = defaultMinSideBarWidth_;
393 }
394 if (minSideBarWidth_ >= parentWidth) {
395 minSideBarWidth_ = parentWidth;
396 maxSideBarWidth_ = parentWidth;
397 realSideBarWidth_ = parentWidth;
398 return;
399 }
400 }
401
402 if (maxSideBarWidth_ < 0.0f) {
403 maxSideBarWidth_ = defaultMaxSideBarWidth_;
404 if (maxSideBarWidth_ <= realSideBarWidth_) {
405 maxSideBarWidth_ = realSideBarWidth_;
406 } else if (maxSideBarWidth_ <= minSideBarWidth_) {
407 maxSideBarWidth_ = minSideBarWidth_;
408 realSideBarWidth_ = minSideBarWidth_;
409 return;
410 }
411 }
412
413 if (realSideBarWidth_ < 0.0f) {
414 realSideBarWidth_ = defaultRealSideBarWidth_;
415 if (realSideBarWidth_ <= minSideBarWidth_) {
416 realSideBarWidth_ = minSideBarWidth_;
417 } else if (realSideBarWidth_ >= maxSideBarWidth_) {
418 realSideBarWidth_ = maxSideBarWidth_;
419 }
420 }
421 }
422
InitRealSideBarWidth(LayoutWrapper * layoutWrapper,float parentWidth)423 void SideBarContainerLayoutAlgorithm::InitRealSideBarWidth(LayoutWrapper* layoutWrapper, float parentWidth)
424 {
425 auto layoutProperty = AceType::DynamicCast<SideBarContainerLayoutProperty>(layoutWrapper->GetLayoutProperty());
426 CHECK_NULL_VOID(layoutProperty);
427 auto constraint = layoutProperty->GetLayoutConstraint();
428 auto scaleProperty = constraint->scaleProperty;
429 auto sideBarWidth = layoutProperty->GetSideBarWidth().value_or(DEFAULT_SIDE_BAR_WIDTH);
430 auto sideBarWidthPx = ConvertToPx(sideBarWidth, scaleProperty, parentWidth).value_or(0);
431 auto minSideBarWidthPx = ConvertToPx(adjustMinSideBarWidth_, scaleProperty, parentWidth).value_or(0);
432 auto maxSideBarWidthPx = ConvertToPx(adjustMaxSideBarWidth_, scaleProperty, parentWidth).value_or(0);
433 if (minSideBarWidthPx > maxSideBarWidthPx) {
434 minSideBarWidthPx = ConvertToPx(DEFAULT_MIN_SIDE_BAR_WIDTH, scaleProperty, parentWidth).value_or(0);
435 maxSideBarWidthPx = ConvertToPx(DEFAULT_MAX_SIDE_BAR_WIDTH, scaleProperty, parentWidth).value_or(0);
436 }
437
438 if (sideBarWidthPx <= minSideBarWidthPx) {
439 realSideBarWidth_ = minSideBarWidthPx;
440 } else if (sideBarWidthPx >= maxSideBarWidthPx) {
441 realSideBarWidth_ = maxSideBarWidthPx;
442 } else {
443 realSideBarWidth_ = sideBarWidthPx;
444 }
445 }
446
AutoChangeSideBarWidth(const RefPtr<SideBarContainerLayoutProperty> & layoutProperty,float parentWidth)447 void SideBarContainerLayoutAlgorithm::AutoChangeSideBarWidth(
448 const RefPtr<SideBarContainerLayoutProperty>& layoutProperty, float parentWidth)
449 {
450 /*
451 * When reducing component width, first reduce the width of the content to minContentWidth,
452 * and then reduce the width of the sidebar
453 */
454 const auto& constraint = layoutProperty->GetLayoutConstraint();
455 const auto& scaleProperty = constraint->scaleProperty;
456 auto dividerStrokeWidth = layoutProperty->GetDividerStrokeWidth().value_or(DEFAULT_DIVIDER_STROKE_WIDTH);
457 auto dividerStrokeWidthPx = ConvertToPx(dividerStrokeWidth, scaleProperty, parentWidth).value_or(1);
458 if ((realSideBarWidth_ + minContentWidth_ + dividerStrokeWidthPx) >= parentWidth) {
459 realSideBarWidth_ = parentWidth - minContentWidth_ - dividerStrokeWidthPx;
460 }
461 if (realSideBarWidth_ <= minSideBarWidth_) {
462 realSideBarWidth_ = minSideBarWidth_;
463 }
464 }
465
AutoMode(const RefPtr<SideBarContainerLayoutProperty> & layoutProperty,float parentWidth)466 void SideBarContainerLayoutAlgorithm::AutoMode(
467 const RefPtr<SideBarContainerLayoutProperty>& layoutProperty, float parentWidth)
468 {
469 /*
470 * SideBarContainer AUTO mode:
471 * When the component width is greater or equal to minNavBarWidth+minContentWidth,
472 * it is displayed in Embed mode;
473 * When the component width is smaller than minNavBarWidth+minContentWidth,
474 * it is displayed in Overlay mode.
475 */
476 if (parentWidth < typeUpdateWidth_) {
477 type_ = SideBarContainerType::OVERLAY;
478 } else {
479 type_ = SideBarContainerType::EMBED;
480 }
481 }
482
MeasureSideBar(const RefPtr<SideBarContainerLayoutProperty> & layoutProperty,const RefPtr<LayoutWrapper> & sideBarLayoutWrapper)483 void SideBarContainerLayoutAlgorithm::MeasureSideBar(
484 const RefPtr<SideBarContainerLayoutProperty>& layoutProperty, const RefPtr<LayoutWrapper>& sideBarLayoutWrapper)
485 {
486 auto constraint = layoutProperty->GetLayoutConstraint();
487 CHECK_NULL_VOID(sideBarLayoutWrapper);
488 auto hostNode = sideBarLayoutWrapper->GetHostNode();
489 CHECK_NULL_VOID(hostNode);
490 auto pipeline = hostNode->GetContextRefPtr();
491 CHECK_NULL_VOID(pipeline);
492 auto sideBarIdealSize = pipeline->GetMinPlatformVersion() >= PLATFORM_VERSION_TEN ?
493 CreateIdealSizeByPercentRef(constraint.value(), Axis::HORIZONTAL,
494 layoutProperty->GetMeasureType(MeasureType::MATCH_PARENT)).ConvertToSizeT():
495 CreateIdealSize(constraint.value(), Axis::HORIZONTAL,
496 layoutProperty->GetMeasureType(MeasureType::MATCH_PARENT), true);
497 const auto& padding = layoutProperty->CreatePaddingAndBorder();
498 realSideBarHeight_ = sideBarIdealSize.Height() - padding.top.value_or(0) - padding.bottom.value_or(0);
499 if (LessNotEqual(realSideBarHeight_, 0.0f)) {
500 realSideBarHeight_ = 0.0f;
501 }
502 sideBarIdealSize.SetWidth(realSideBarWidth_);
503 sideBarIdealSize.SetHeight(realSideBarHeight_);
504
505 if (pipeline->GetMinPlatformVersion() >= PLATFORM_VERSION_TEN) {
506 auto sideBarLayoutProperty = sideBarLayoutWrapper->GetLayoutProperty();
507 CHECK_NULL_VOID(sideBarLayoutProperty);
508 auto&& calcConstraint = sideBarLayoutProperty->GetCalcLayoutConstraint();
509 if (calcConstraint) {
510 if (calcConstraint->maxSize.has_value()) {
511 auto maxWidth = CalcLength(realSideBarWidth_);
512 auto maxHeight = CalcLength(realSideBarHeight_);
513 calcConstraint->UpdateMaxSizeWithCheck(CalcSize(maxWidth, maxHeight));
514 }
515
516 if (calcConstraint->minSize.has_value()) {
517 auto minWidth = CalcLength(realSideBarWidth_);
518 auto minHeight = CalcLength(realSideBarHeight_);
519 calcConstraint->UpdateMinSizeWithCheck(CalcSize(minWidth, minHeight));
520 }
521 }
522 }
523
524 auto sideBarConstraint = layoutProperty->CreateChildConstraint();
525 sideBarConstraint.selfIdealSize = OptionalSizeF(sideBarIdealSize);
526
527 sideBarLayoutWrapper->Measure(sideBarConstraint);
528 }
529
MeasureDivider(const RefPtr<SideBarContainerLayoutProperty> & layoutProperty,const RefPtr<LayoutWrapper> & dividerLayoutWrapper,float parentWidth)530 void SideBarContainerLayoutAlgorithm::MeasureDivider(const RefPtr<SideBarContainerLayoutProperty>& layoutProperty,
531 const RefPtr<LayoutWrapper>& dividerLayoutWrapper, float parentWidth)
532 {
533 CHECK_NULL_VOID(layoutProperty);
534 CHECK_NULL_VOID(dividerLayoutWrapper);
535 auto constraint = layoutProperty->GetLayoutConstraint();
536 CHECK_NULL_VOID(constraint);
537 auto scaleProperty = constraint->scaleProperty;
538 auto dividerIdealSize = Container::GreatOrEqualAPIVersion(PlatformVersion::VERSION_TEN) ?
539 CreateIdealSizeByPercentRef(constraint.value(), Axis::HORIZONTAL,
540 layoutProperty->GetMeasureType(MeasureType::MATCH_PARENT)).ConvertToSizeT() :
541 CreateIdealSize(
542 constraint.value(), Axis::HORIZONTAL, layoutProperty->GetMeasureType(MeasureType::MATCH_PARENT), true);
543
544 auto dividerStrokeWidth = layoutProperty->GetDividerStrokeWidth().value_or(DEFAULT_DIVIDER_STROKE_WIDTH);
545 auto dividerStartMargin = layoutProperty->GetDividerStartMargin().value_or(DEFAULT_DIVIDER_START_MARGIN);
546 auto dividerEndMargin = layoutProperty->GetDividerEndMargin().value_or(DEFAULT_DIVIDER_END_MARGIN);
547
548 auto dividerStrokeWidthPx = ConvertToPx(dividerStrokeWidth, scaleProperty, parentWidth).value_or(1);
549 auto dividerStartMarginPx = ConvertToPx(dividerStartMargin, scaleProperty, parentWidth).value_or(0);
550 auto dividerEndMarginPx = ConvertToPx(dividerEndMargin, scaleProperty, parentWidth).value_or(0);
551
552 dividerIdealSize.SetWidth(dividerStrokeWidthPx);
553 dividerIdealSize.SetHeight(realSideBarHeight_ - dividerStartMarginPx - dividerEndMarginPx);
554 realDividerWidth_ = dividerStrokeWidthPx;
555
556 auto dividerLayoutConstraint = layoutProperty->CreateChildConstraint();
557 dividerLayoutConstraint.selfIdealSize = OptionalSizeF(dividerIdealSize);
558 dividerLayoutWrapper->Measure(dividerLayoutConstraint);
559 }
560
MeasureSideBarContent(const RefPtr<SideBarContainerLayoutProperty> & layoutProperty,const RefPtr<LayoutWrapper> & contentLayoutWrapper,float parentWidth)561 void SideBarContainerLayoutAlgorithm::MeasureSideBarContent(
562 const RefPtr<SideBarContainerLayoutProperty>& layoutProperty, const RefPtr<LayoutWrapper>& contentLayoutWrapper,
563 float parentWidth)
564 {
565 auto sideBarPosition = GetSideBarPositionWithRtl(layoutProperty);
566 auto constraint = layoutProperty->GetLayoutConstraint();
567 const auto& padding = layoutProperty->CreatePaddingAndBorder();
568 auto contentWidth = parentWidth - padding.left.value_or(0) - padding.right.value_or(0);
569
570 if (type_ == SideBarContainerType::EMBED) {
571 if (sideBarStatus_ == SideBarStatus::SHOW) {
572 contentWidth -= (realSideBarWidth_ + realDividerWidth_);
573 } else if (sideBarStatus_ == SideBarStatus::CHANGING) {
574 contentWidth = (sideBarPosition == SideBarPosition::START)
575 ? (contentWidth - realSideBarWidth_ - realDividerWidth_ - currentOffset_)
576 : (contentWidth - realDividerWidth_ + currentOffset_);
577 }
578 }
579 contentWidth = std::max(contentWidth, minContentWidth_);
580
581 CHECK_NULL_VOID(contentLayoutWrapper);
582 auto contentNode = contentLayoutWrapper->GetHostNode();
583 CHECK_NULL_VOID(contentNode);
584 auto pipeline = contentNode->GetContextRefPtr();
585 CHECK_NULL_VOID(pipeline);
586 auto contentIdealSize = pipeline->GetMinPlatformVersion() >= PLATFORM_VERSION_TEN ?
587 CreateIdealSizeByPercentRef(constraint.value(), Axis::HORIZONTAL,
588 layoutProperty->GetMeasureType(MeasureType::MATCH_PARENT)).ConvertToSizeT() :
589 CreateIdealSize(
590 constraint.value(), Axis::HORIZONTAL, layoutProperty->GetMeasureType(MeasureType::MATCH_PARENT), true);
591 contentIdealSize.SetWidth(contentWidth);
592 contentIdealSize.SetHeight(realSideBarHeight_);
593 auto contentConstraint = layoutProperty->CreateChildConstraint();
594 contentConstraint.selfIdealSize = OptionalSizeF(contentIdealSize);
595 contentLayoutWrapper->Measure(contentConstraint);
596 }
597
MeasureControlButton(const RefPtr<SideBarContainerLayoutProperty> & layoutProperty,const RefPtr<LayoutWrapper> & buttonLayoutWrapper,float parentWidth)598 void SideBarContainerLayoutAlgorithm::MeasureControlButton(const RefPtr<SideBarContainerLayoutProperty>& layoutProperty,
599 const RefPtr<LayoutWrapper>& buttonLayoutWrapper, float parentWidth)
600 {
601 auto constraint = layoutProperty->GetLayoutConstraint();
602 auto scaleProperty = constraint->scaleProperty;
603
604 auto controlButtonWidth = controlImageWidth_ + CONTROL_BUTTON_PADDING * 2;
605 auto controlButtonHeight = controlImageHeight_ + CONTROL_BUTTON_PADDING * 2;
606 auto controlButtonWidthPx = ConvertToPx(controlButtonWidth, scaleProperty, parentWidth).value_or(0);
607 auto controlButtonHeightPx = ConvertToPx(controlButtonHeight, scaleProperty, parentWidth).value_or(0);
608
609 auto controlButtonLayoutConstraint = layoutProperty->CreateChildConstraint();
610 controlButtonLayoutConstraint.selfIdealSize.SetWidth(controlButtonWidthPx);
611 controlButtonLayoutConstraint.selfIdealSize.SetHeight(controlButtonHeightPx);
612 buttonLayoutWrapper->Measure(controlButtonLayoutConstraint);
613 }
614
Layout(LayoutWrapper * layoutWrapper)615 void SideBarContainerLayoutAlgorithm::Layout(LayoutWrapper* layoutWrapper)
616 {
617 const auto& children = layoutWrapper->GetAllChildrenWithBuild(layoutWrapper->IsActive());
618 if (children.size() < DEFAULT_MIN_CHILDREN_SIZE) {
619 return;
620 }
621
622 auto host = layoutWrapper->GetHostNode();
623 if (host && !host->GetIgnoreLayoutProcess() && GetNeedPostponeForIgnore()) {
624 return;
625 }
626
627 int index = 0;
628 for (auto it = children.rbegin(); it != children.rend(); ++it) {
629 index++;
630 if (index == INDEX_CONTRON_BUTTON) {
631 auto controlButtonLayoutWrapper = (*it);
632 LayoutControlButton(layoutWrapper, controlButtonLayoutWrapper);
633 } else if (index == INDEX_DIVIDER) {
634 auto dividerLayoutWrapper = (*it);
635 LayoutDivider(layoutWrapper, dividerLayoutWrapper);
636 } else if (index == INDEX_SIDE_BAR) {
637 auto sideBarLayoutWrapper = (*it);
638 LayoutSideBar(layoutWrapper, sideBarLayoutWrapper);
639 } else { // other break
640 break;
641 }
642 }
643
644 if (children.size() > DEFAULT_MIN_CHILDREN_SIZE) { // when sidebar only add one component, content is not display
645 auto contentLayoutWrapper = children.front();
646 LayoutSideBarContent(layoutWrapper, contentLayoutWrapper);
647 }
648 }
649
LayoutControlButton(LayoutWrapper * layoutWrapper,const RefPtr<LayoutWrapper> & buttonLayoutWrapper)650 void SideBarContainerLayoutAlgorithm::LayoutControlButton(
651 LayoutWrapper* layoutWrapper, const RefPtr<LayoutWrapper>& buttonLayoutWrapper)
652 {
653 auto layoutProperty = AceType::DynamicCast<SideBarContainerLayoutProperty>(layoutWrapper->GetLayoutProperty());
654 CHECK_NULL_VOID(layoutProperty);
655
656 CHECK_NULL_VOID(layoutWrapper->GetGeometryNode());
657 auto parentWidth = layoutWrapper->GetGeometryNode()->GetFrameSize().Width();
658 auto constraint = layoutProperty->GetLayoutConstraint();
659 auto scaleProperty = constraint->scaleProperty;
660 const auto& padding = layoutProperty->CreatePaddingAndBorder();
661 auto controlImageLeft = layoutProperty->GetControlButtonLeft().value_or(DEFAULT_CONTROL_BUTTON_LEFT);
662 auto controlImageTop = layoutProperty->GetControlButtonTop().value_or(DEFAULT_CONTROL_BUTTON_TOP);
663
664 if (LessNotEqual(controlImageLeft.Value(), 0.0)) {
665 controlImageLeft = DEFAULT_CONTROL_BUTTON_LEFT;
666 }
667
668 if (LessNotEqual(controlImageTop.Value(), 0.0)) {
669 controlImageTop = DEFAULT_CONTROL_BUTTON_TOP;
670 }
671 auto controlButtonLeft = controlImageLeft - CONTROL_BUTTON_PADDING;
672 auto controlButtonTop = controlImageTop - CONTROL_BUTTON_PADDING;
673
674 auto controlButtonLeftPx = ConvertToPx(controlButtonLeft, scaleProperty, parentWidth).value_or(0);
675 auto controlButtonTopPx = ConvertToPx(controlButtonTop, scaleProperty, parentWidth).value_or(0);
676 controlButtonLeftPx += padding.left.value_or(0);
677 controlButtonTopPx += padding.top.value_or(0);
678 auto sideBarContainerPattern = AceType::DynamicCast<SideBarContainerPattern>(pattern_.Upgrade());
679 if (sideBarContainerPattern) {
680 auto toolbarManager = sideBarContainerPattern->GetToolBarManager();
681 if (toolbarManager != nullptr && toolbarManager->GetIsMoveUp()) {
682 auto decorBarHeight = static_cast<float>(toolbarManager->GetTitleHeight().ConvertToPx());
683 controlButtonTopPx += decorBarHeight;
684 }
685 }
686 /*
687 * Control buttion left position need to special handle:
688 * 1. when sideBarPosition set to END and controlButtonLeft do not set in ButtonStyle
689 * control button need to move follow the sidebar to the right
690 * 2. when sideBarPosition set to START or controlButtonLeft has set by user
691 * control button keep before handle
692 * 3. if the controlButtonLeft has set, whether sideBarPosition set to START or END
693 * control button offset the left, if value invalid set to default 16vp
694 */
695 auto sideBarPosition = GetSideBarPositionWithRtl(layoutProperty);
696 auto controlButtonWidth = controlImageWidth_ + CONTROL_BUTTON_PADDING * 2;
697
698 if ((sideBarPosition == SideBarPosition::END) && // sideBarPosition is End, other pass
699 (!layoutProperty->GetControlButtonLeft().has_value())) { // origin value has not set
700 auto defaultControlButtonLeft = DEFAULT_CONTROL_BUTTON_LEFT - CONTROL_BUTTON_PADDING;
701 auto defaultControlButtonLeftPx = ConvertToPx(defaultControlButtonLeft, scaleProperty, parentWidth).value_or(0)
702 + padding.right.value_or(0);
703 auto controlButtonWidthPx = ConvertToPx(controlButtonWidth, scaleProperty, parentWidth).value_or(0);
704 controlButtonLeftPx = parentWidth - defaultControlButtonLeftPx - controlButtonWidthPx;
705 }
706
707 auto imgOffset = OffsetF(controlButtonLeftPx, controlButtonTopPx);
708 buttonLayoutWrapper->GetGeometryNode()->SetMarginFrameOffset(imgOffset);
709 buttonLayoutWrapper->Layout();
710 }
711
LayoutSideBar(LayoutWrapper * layoutWrapper,const RefPtr<LayoutWrapper> & sideBarLayoutWrapper)712 void SideBarContainerLayoutAlgorithm::LayoutSideBar(
713 LayoutWrapper* layoutWrapper, const RefPtr<LayoutWrapper>& sideBarLayoutWrapper)
714 {
715 auto layoutProperty = AceType::DynamicCast<SideBarContainerLayoutProperty>(layoutWrapper->GetLayoutProperty());
716 CHECK_NULL_VOID(layoutProperty);
717
718 CHECK_NULL_VOID(layoutWrapper->GetGeometryNode());
719 auto parentWidth = layoutWrapper->GetGeometryNode()->GetFrameSize().Width();
720 auto sideBarPosition = GetSideBarPositionWithRtl(layoutProperty);
721 const auto& padding = layoutProperty->CreatePaddingAndBorder();
722 float sideBarOffsetX = padding.left.value_or(0);
723 float sideBarOffsetY = padding.top.value_or(0);
724
725 switch (sideBarStatus_) {
726 case SideBarStatus::SHOW:
727 if (sideBarPosition == SideBarPosition::END) {
728 sideBarOffsetX = parentWidth - realSideBarWidth_ - padding.right.value_or(0);
729 }
730 break;
731 case SideBarStatus::HIDDEN:
732 if (sideBarPosition == SideBarPosition::START) {
733 sideBarOffsetX = -(realSideBarWidth_ + realDividerWidth_ - padding.left.value_or(0));
734 } else {
735 sideBarOffsetX = parentWidth + realDividerWidth_ - padding.right.value_or(0);
736 }
737 break;
738 case SideBarStatus::CHANGING:
739 if (sideBarPosition == SideBarPosition::START) {
740 sideBarOffsetX = currentOffset_ + padding.left.value_or(0);
741 } else {
742 sideBarOffsetX = parentWidth - padding.right.value_or(0) + currentOffset_;
743 }
744 break;
745 default:
746 break;
747 }
748
749 auto decorBarHeight = 0.0f;
750 auto sideBarContainerPattern = AceType::DynamicCast<SideBarContainerPattern>(pattern_.Upgrade());
751 if (sideBarContainerPattern) {
752 auto toolbarManager = sideBarContainerPattern->GetToolBarManager();
753 if (toolbarManager && toolbarManager->GetIsMoveUp()) {
754 decorBarHeight = static_cast<float>(toolbarManager->GetTitleHeight().ConvertToPx());
755 }
756 }
757 sideBarOffset_ = OffsetF(sideBarOffsetX, sideBarOffsetY + decorBarHeight);
758
759 AdjustChildOffset(sideBarLayoutWrapper, sideBarOffset_);
760
761 sideBarLayoutWrapper->GetGeometryNode()->SetMarginFrameOffset(sideBarOffset_);
762 sideBarLayoutWrapper->Layout();
763 }
764
LayoutSideBarContent(LayoutWrapper * layoutWrapper,const RefPtr<LayoutWrapper> & contentLayoutWrapper)765 void SideBarContainerLayoutAlgorithm::LayoutSideBarContent(
766 LayoutWrapper* layoutWrapper, const RefPtr<LayoutWrapper>& contentLayoutWrapper)
767 {
768 auto layoutProperty = AceType::DynamicCast<SideBarContainerLayoutProperty>(layoutWrapper->GetLayoutProperty());
769 CHECK_NULL_VOID(layoutProperty);
770
771 auto sideBarPosition = GetSideBarPositionWithRtl(layoutProperty);
772 const auto& padding = layoutProperty->CreatePaddingAndBorder();
773 float contentOffsetX = padding.left.value_or(0);
774 float contentOffsetY = padding.top.value_or(0);
775
776 if (type_ == SideBarContainerType::EMBED && sideBarPosition == SideBarPosition::START) {
777 if (sideBarStatus_ == SideBarStatus::SHOW) {
778 contentOffsetX = realSideBarWidth_ + realDividerWidth_ + padding.left.value_or(0);
779 } else if (sideBarStatus_ == SideBarStatus::CHANGING) {
780 contentOffsetX = realSideBarWidth_ + realDividerWidth_ + currentOffset_ + padding.left.value_or(0);
781 }
782 }
783
784 auto contentOffset = OffsetF(contentOffsetX, contentOffsetY);
785
786 AdjustChildOffset(contentLayoutWrapper, contentOffset);
787
788 contentLayoutWrapper->GetGeometryNode()->SetMarginFrameOffset(contentOffset);
789 contentLayoutWrapper->Layout();
790 }
791
LayoutDivider(LayoutWrapper * layoutWrapper,const RefPtr<LayoutWrapper> & dividerLayoutWrapper)792 void SideBarContainerLayoutAlgorithm::LayoutDivider(
793 LayoutWrapper* layoutWrapper, const RefPtr<LayoutWrapper>& dividerLayoutWrapper)
794 {
795 CHECK_NULL_VOID(layoutWrapper);
796 CHECK_NULL_VOID(dividerLayoutWrapper);
797 auto layoutProperty = AceType::DynamicCast<SideBarContainerLayoutProperty>(layoutWrapper->GetLayoutProperty());
798 CHECK_NULL_VOID(layoutProperty);
799
800 auto sideBarPosition = GetSideBarPositionWithRtl(layoutProperty);
801
802 CHECK_NULL_VOID(layoutWrapper->GetGeometryNode());
803 auto parentWidth = layoutWrapper->GetGeometryNode()->GetFrameSize().Width();
804 auto constraint = layoutProperty->GetLayoutConstraint();
805 CHECK_NULL_VOID(constraint);
806 auto scaleProperty = constraint->scaleProperty;
807
808 auto dividerStartMargin = layoutProperty->GetDividerStartMargin().value_or(DEFAULT_DIVIDER_START_MARGIN);
809 auto dividerStartMarginPx = ConvertToPx(dividerStartMargin, scaleProperty, parentWidth).value_or(0);
810 const auto& padding = layoutProperty->CreatePaddingAndBorder();
811 float dividerOffsetX = padding.left.value_or(0);
812 float dividerOffsetY = padding.top.value_or(0);
813
814 switch (sideBarStatus_) {
815 case SideBarStatus::SHOW:
816 if (sideBarPosition == SideBarPosition::START) {
817 dividerOffsetX = realSideBarWidth_ + padding.left.value_or(0);
818 } else {
819 dividerOffsetX = parentWidth - realSideBarWidth_ - realDividerWidth_ - padding.right.value_or(0);
820 }
821 break;
822 case SideBarStatus::HIDDEN:
823 if (sideBarPosition == SideBarPosition::START) {
824 dividerOffsetX = -realDividerWidth_ + padding.left.value_or(0);
825 } else {
826 dividerOffsetX = parentWidth - padding.right.value_or(0);
827 }
828 break;
829 case SideBarStatus::CHANGING:
830 if (sideBarPosition == SideBarPosition::START) {
831 dividerOffsetX = realSideBarWidth_ + currentOffset_ + padding.left.value_or(0);
832 } else {
833 dividerOffsetX = parentWidth - realDividerWidth_ + currentOffset_ - padding.right.value_or(0);
834 }
835 break;
836 default:
837 break;
838 }
839
840 auto dividerOffset = OffsetF(dividerOffsetX, dividerStartMarginPx + dividerOffsetY);
841 CHECK_NULL_VOID(dividerLayoutWrapper->GetGeometryNode());
842 dividerLayoutWrapper->GetGeometryNode()->SetMarginFrameOffset(dividerOffset);
843 dividerLayoutWrapper->Layout();
844 }
845
GetSideBarPositionWithRtl(const RefPtr<SideBarContainerLayoutProperty> & layoutProperty)846 SideBarPosition SideBarContainerLayoutAlgorithm::GetSideBarPositionWithRtl(
847 const RefPtr<SideBarContainerLayoutProperty>& layoutProperty)
848 {
849 auto sideBarPosition = layoutProperty->GetSideBarPosition().value_or(SideBarPosition::START);
850 if (layoutProperty->GetLayoutDirection() == TextDirection::RTL ||
851 AceApplicationInfo::GetInstance().IsRightToLeft()) {
852 sideBarPosition = (sideBarPosition == SideBarPosition::START) ? SideBarPosition::END : SideBarPosition::START;
853 }
854 return sideBarPosition;
855 }
856
AdjustChildOffset(const RefPtr<LayoutWrapper> & layoutWrapper,OffsetF & offset)857 void SideBarContainerLayoutAlgorithm::AdjustChildOffset(const RefPtr<LayoutWrapper>& layoutWrapper, OffsetF& offset)
858 {
859 auto node = layoutWrapper->GetHostNode();
860 CHECK_NULL_VOID(node);
861 auto layoutProperty = node->GetLayoutProperty();
862 if (layoutProperty && layoutProperty->IsIgnoreOptsValid()) {
863 auto geometryNode = layoutWrapper->GetGeometryNode();
864 CHECK_NULL_VOID(geometryNode);
865 geometryNode->SetMarginFrameOffset(offset);
866 IgnoreLayoutSafeAreaOpts& opts = *(layoutProperty->GetIgnoreLayoutSafeAreaOpts());
867 auto safeExpand = node->GetAccumulatedSafeAreaExpand(false, opts);
868 auto offsetX = safeExpand.left.value_or(0.0f);
869 auto offsetY = safeExpand.top.value_or(0.0f);
870 offset -= OffsetF(offsetX, offsetY);
871 }
872 }
873 } // namespace OHOS::Ace::NG
874