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 #ifndef FOUNDATION_ACE_FRAMEWORKS_CORE_COMPONENTS_NG_PATTERN_WRAP_WRAP_LAYOUT_ALGORITHM_H
17 #define FOUNDATION_ACE_FRAMEWORKS_CORE_COMPONENTS_NG_PATTERN_WRAP_WRAP_LAYOUT_ALGORITHM_H
18 
19 #include <string>
20 
21 #include "base/geometry/ng/size_t.h"
22 #include "core/components/common/layout/constants.h"
23 #include "core/components_ng/base/frame_node.h"
24 #include "core/components_ng/base/geometry_node.h"
25 #include "core/components_ng/layout/layout_algorithm.h"
26 #include "core/components_ng/layout/layout_wrapper.h"
27 #include "core/components_ng/pattern/flex/flex_layout_algorithm.h"
28 #include "core/components_ng/pattern/flex/flex_layout_styles.h"
29 #include "core/components_ng/pattern/text/text_layout_property.h"
30 
31 namespace OHOS::Ace::NG {
32 
33 struct ContentInfo {
ContentInfoContentInfo34     ContentInfo(float main, float cross, int32_t total, const std::list<RefPtr<LayoutWrapper>>& nodeList)
35         : mainLength(main), crossLength(cross), count(total), itemList(nodeList)
36     {}
37 
38     float mainLength = 0.0f;
39     float crossLength = 0.0f;
40     int32_t count = 0;
41     std::list<RefPtr<LayoutWrapper>> itemList;
42     float spaceBetween = 0.0f;
43     float maxBaselineDistance = 0.0f;
44 
ToStringContentInfo45     std::string ToString() const
46     {
47         std::string result;
48         result.append("main length: ");
49         result.append(std::to_string(mainLength));
50         result.append(", cross length: ");
51         result.append(std::to_string(crossLength));
52         result.append(", space between: ");
53         result.append(std::to_string(spaceBetween));
54         result.append(", child count ");
55         result.append(std::to_string(count));
56         result.append(", max baseline distance ");
57         result.append(std::to_string(maxBaselineDistance));
58         return result;
59     }
60 };
61 
62 class ACE_EXPORT WrapLayoutAlgorithm : public LayoutAlgorithm {
63     DECLARE_ACE_TYPE(WrapLayoutAlgorithm, LayoutAlgorithm);
64 
65 public:
66     WrapLayoutAlgorithm() = default;
WrapLayoutAlgorithm(bool stretch)67     explicit WrapLayoutAlgorithm(bool stretch) : isDialogStretch_(stretch) {};
68     ~WrapLayoutAlgorithm() override = default;
69 
70     void Measure(LayoutWrapper* layoutWrapper) override;
71 
72     void Layout(LayoutWrapper* layoutWrapper) override;
73 
74 private:
75     void PerformLayoutInitialize(const RefPtr<LayoutProperty>& layoutProp);
76     void HandleDialogStretch();
77     SizeF GetLeftSize(float crossLength, float mainLeftLength, float crossLeftLength);
78     void LayoutWholeWrap(
79         OffsetF& startPosition, OffsetF& spaceBetweenContentsOnCrossAxis, LayoutWrapper* layoutWrapper);
80     void LayoutWholeColumnWrap(
81         OffsetF& startPosition, OffsetF& spaceBetweenContentsOnCrossAxis, LayoutWrapper* layoutWrapper);
82     void UpdateStartPositionByAlign(OffsetF& startPosition, float crossAxisRemainSpace,
83         OffsetF& spaceBetweenContentsOnCrossAxis, int32_t contentNum);
84     void TraverseColumnContent(const OffsetF& startPosition, const OffsetF& spaceBetweenContentsOnCrossAxis);
85     void AddPaddingToStartPositionForColumn(OffsetF& startPosition) const;
86     void LayoutColumnContent(const ContentInfo& content, const OffsetF& position);
87 
88     float GetItemMainAxisLength(const RefPtr<GeometryNode>& item) const;
89     float GetItemCrossAxisLength(const RefPtr<GeometryNode>& item) const;
90     float GetMainAxisLengthOfSize(const SizeF& size) const;
91     float GetCrossAxisLengthOfSize(const SizeF& size) const;
92     float GetMainAxisOffset(const OffsetF& offset) const;
93     float GetCrossAxisOffset(const OffsetF& offset) const;
94     SizeF GetMainAxisRemainSpace(float totalMainLength) const;
95     SizeF GetCrossAxisRemainSpace(float totalCrossLength) const;
96 
97     void CalcItemMainAxisStartAndSpaceBetween(
98         OffsetF& startPosition, OffsetF& spaceBetweenItemsOnMainAxis, const ContentInfo& content);
99     float CalcItemCrossAxisOffset(
100         const ContentInfo& content, const OffsetF& contentOffset, const RefPtr<GeometryNode>& node);
101 
102     void StretchItemsInContent(LayoutWrapper* layoutWrapper, const ContentInfo& content);
103     void TraverseContent(const OffsetF& startPosition, const OffsetF& spaceBetweenContentsOnCrossAxis);
104     OffsetF GetItemMainOffset(float mainSpace) const;
105     void LayoutContent(const ContentInfo& content, const OffsetF& position);
106 
107     void AddExtraSpaceToStartPosition(OffsetF& startPosition, float extraSpace, bool onMainAxis) const;
108     void AddPaddingToStartPosition(OffsetF& startPosition) const;
109     void GetFlexItemProperties(const ContentInfo& content, FlexItemProperties& flexItemProperties);
110     void CalcFlexGrowLayout(
111         const RefPtr<LayoutWrapper>& itemWrapper, const FlexItemProperties& flexItemProperties, float remainSpace);
112 
113     void UpdatePercentSensitive(LayoutWrapper *layoutWrapper);
114     WrapDirection direction_ = WrapDirection::VERTICAL;
115     WrapAlignment alignment_ = WrapAlignment::START;
116     WrapAlignment mainAlignment_ = WrapAlignment::START;
117     WrapAlignment crossAlignment_ = WrapAlignment::START;
118     TextDirection textDir_ = TextDirection::LTR;
119 
120     bool isHorizontal_ = true;
121     bool isReverse_ = false;
122     bool isColumnReverse_ = false;
123     bool isRightDirection_ = false;
124     bool isDialogStretch_ = false;
125     float totalMainLength_ = 0.0f;
126     float totalCrossLength_ = 0.0f;
127     Dimension spacing_;
128     Dimension contentSpace_;
129     SizeF constraintMaxSize_;
130     PaddingPropertyF padding_;
131     SizeF frameSize_;
132     OffsetF frameOffset_;
133     bool hasIdealWidth_ = false;
134     bool hasIdealHeight_ = false;
135 
136     // Should be clear after Layout.
137     std::list<ContentInfo> contentList_;
138 
139     float mainLengthLimit_ = 0.0f;
140     float crossLengthLimit_ = 0.0f;
141     float currentMainLength_ = 0.0f;
142     std::list<RefPtr<LayoutWrapper>> outOfLayoutChildren_;
143 
144     ACE_DISALLOW_COPY_AND_MOVE(WrapLayoutAlgorithm);
145 };
146 } // namespace OHOS::Ace::NG
147 
148 #endif // FOUNDATION_ACE_FRAMEWORKS_CORE_COMPONENTS_NG_PATTERN_WRAP_WRAP_LAYOUT_ALGORITHM_H
149