1 /*
2 * Copyright (c) 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 "frameworks/core/components_ng/pattern/stack/stack_layout_algorithm.h"
17
18 #include "core/common/ace_application_info.h"
19 #include "core/components_ng/layout/layout_wrapper.h"
20 #include "core/components_ng/pattern/stack/stack_layout_property.h"
21
22 namespace OHOS::Ace::NG {
23
24 StackLayoutAlgorithm::StackLayoutAlgorithm() = default;
25
Layout(LayoutWrapper * layoutWrapper)26 void StackLayoutAlgorithm::Layout(LayoutWrapper* layoutWrapper)
27 {
28 PerformLayout(layoutWrapper);
29 for (auto&& child : layoutWrapper->GetAllChildrenWithBuild()) {
30 child->Layout();
31 }
32 }
33
34 // Called to perform layout render node and child.
PerformLayout(LayoutWrapper * layoutWrapper)35 void StackLayoutAlgorithm::PerformLayout(LayoutWrapper* layoutWrapper)
36 {
37 // update child position.
38 auto size = layoutWrapper->GetGeometryNode()->GetFrameSize();
39 const auto& padding = layoutWrapper->GetLayoutProperty()->CreatePaddingAndBorder();
40 auto layoutDirection = layoutWrapper->GetLayoutProperty()->GetLayoutDirection();
41 if (layoutDirection == TextDirection::AUTO) {
42 layoutDirection = AceApplicationInfo::GetInstance().IsRightToLeft() ? TextDirection::RTL : TextDirection::LTR;
43 }
44 MinusPaddingToSize(padding, size);
45 auto left = padding.left.value_or(0);
46 auto top = padding.top.value_or(0);
47 auto paddingOffset = OffsetF(left, top);
48 auto align = Alignment::CENTER;
49 auto layoutProperty = DynamicCast<StackLayoutProperty>(layoutWrapper->GetLayoutProperty());
50 CHECK_NULL_VOID(layoutProperty);
51 if (layoutProperty->GetPositionProperty()) {
52 align = layoutProperty->GetPositionProperty()->GetAlignment().value_or(Alignment::CENTER);
53 }
54 // Update child position.
55 for (const auto& child : layoutWrapper->GetAllChildrenWithBuild()) {
56 auto translate =
57 CalculateStackAlignment(size, child->GetGeometryNode()->GetMarginFrameSize(), align) + paddingOffset;
58 if (layoutDirection == TextDirection::RTL) {
59 translate.SetX(size.Width() - translate.GetX() - child->GetGeometryNode()->GetMarginFrameSize().Width());
60 }
61 child->GetGeometryNode()->SetMarginFrameOffset(translate);
62 }
63 // Update content position.
64 const auto& content = layoutWrapper->GetGeometryNode()->GetContent();
65 if (content) {
66 auto translate = CalculateStackAlignment(size, content->GetRect().GetSize(), align) + paddingOffset;
67 if (layoutDirection == TextDirection::RTL) {
68 translate.SetX(size.Width() - translate.GetX() - content->GetRect().GetSize().Width());
69 }
70 content->SetOffset(translate);
71 }
72 }
73
CalculateStackAlignment(const NG::SizeF & parentSize,const NG::SizeF & childSize,const Alignment & alignment)74 NG::OffsetF StackLayoutAlgorithm::CalculateStackAlignment(
75 const NG::SizeF& parentSize, const NG::SizeF& childSize, const Alignment& alignment)
76 {
77 NG::OffsetF offset;
78 offset.SetX((1.0 + alignment.GetHorizontal()) * (parentSize.Width() - childSize.Width()) / 2.0);
79 offset.SetY((1.0 + alignment.GetVertical()) * (parentSize.Height() - childSize.Height()) / 2.0);
80 return offset;
81 }
82 } // namespace OHOS::Ace::NG
83