• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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