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_RELATIVE_CONTAINER_RELATIVE_CONTAINER_LAYOUT_ALGORITHM_H
17 #define FOUNDATION_ACE_FRAMEWORKS_CORE_COMPONENTS_NG_PATTERN_RELATIVE_CONTAINER_RELATIVE_CONTAINER_LAYOUT_ALGORITHM_H
18 
19 #include <cstdint>
20 #include <map>
21 #include <optional>
22 
23 #include "core/components_ng/layout/layout_algorithm.h"
24 #include "core/components_ng/layout/layout_wrapper.h"
25 
26 namespace OHOS::Ace::NG {
27 
28 using AlignRulesItem = std::map<AlignDirection, AlignRule>;
29 using TwoAlignedValues = std::pair<std::optional<float>, std::optional<float>>;
30 using ChildIdealSize = TwoAlignedValues;
31 using GuidelineParams = std::pair<LineDirection, float>;
32 using BarrierParams = std::pair<BarrierDirection, std::vector<std::string>>;
33 
34 
35 class ACE_EXPORT RelativeContainerLayoutAlgorithm : public LayoutAlgorithm {
36     DECLARE_ACE_TYPE(RelativeContainerLayoutAlgorithm, LayoutAlgorithm);
37 
38 public:
39     RelativeContainerLayoutAlgorithm() = default;
40     ~RelativeContainerLayoutAlgorithm() override = default;
41 
42     void Measure(LayoutWrapper* layoutWrapper) override;
43     void Layout(LayoutWrapper* layoutWrapper) override;
44 
45     struct ChildMeasureWrapper {
46         RefPtr<LayoutWrapper> layoutWrapper;
47         // used to prevent concatenating tag + id for nodes
48         // who does not have inspector id set in ets
49         std::string id;
50     };
51 
52     struct BarrierRect
53     {
54         float minLeft = Infinity<float>();
55         float maxRight = 0.0f;
56         float minTop = Infinity<float>();
57         float maxBottom = 0.0f;
58     };
59 
60     struct ChainParam
61     {
62         std::vector<std::string> ids;
63         std::map<std::string, std::optional<float>> itemSize;
64         AlignRule anchorHead;
65         AlignRule anchorTail;
66         ChainStyle chainStyle;
67         BiasPair bias;
68         float totalChainWeight;
69         float remainingSpace = 0.0f; // default
70         bool isCalculated = false;
71         bool isWeightCalculated = false;
72     };
73 
74 private:
75     void DetermineTopologicalOrder(LayoutWrapper* layoutWrapper);
76     void MeasureSelf(LayoutWrapper* layoutWrapper);
77     void CollectNodesById(LayoutWrapper* layoutWrapper);
78     bool IsAlignRuleInChain(const AlignDirection& direction, const std::string& nodeName);
79     void InsertToReliedOnMap(const std::string& anchorName, const std::string& nodeName);
80     void GetDependencyRelationship();
81     void GetDependencyRelationshipInChain(const std::string& anchor, const std::string& nodeName);
82     void GetDependencyRelationshipInBarrier();
83     void CalcHorizontalGuideline(std::optional<CalcSize>& selfIdealSize, float containerHeight,
84         const GuidelineInfo& guidelineInfo);
85     void CalcVerticalGuideline(std::optional<CalcSize>& selfIdealSize, float containerWidth,
86         const GuidelineInfo& guidelineInfo);
87     void CalcGuideline(LayoutWrapper* layoutWrapper);
88     void CalcBarrier(LayoutWrapper* layoutWrapper);
89     bool IsGuideline(const std::string& id);
90     bool IsBarrier(const std::string& id);
91     BarrierRect GetBarrierRectByReferencedIds(const std::vector<std::string>& referencedIds);
92     void MeasureBarrier(const std::string& barrierName);
93     void CheckNodeInHorizontalChain(std::string& currentNode,
94         AlignRulesItem& currentAlignRules, std::vector<std::string>& chainNodes,
95         AlignRule& rightAnchor, float& totalChainWeight);
96     void CheckHorizontalChain(const ChildMeasureWrapper& measureParam);
97     void CheckNodeInVerticalChain(std::string& currentNode, AlignRulesItem& currentAlignRules,
98         std::vector<std::string>& chainNodes, AlignRule& bottomAnchor, float& totalChainWeight);
99     void CheckVerticalChain(const ChildMeasureWrapper& measureParam);
100     void CheckChain(LayoutWrapper* layoutWrapper);
101     void RecordSizeInChain(const std::string& nodeName);
102     bool IsNodeInHorizontalChain(const std::string& nodeName, std::string& chainName);
103     bool IsNodeInVerticalChain(const std::string& nodeName, std::string& chainName);
104     float GetHorizontalAnchorValueByAlignRule(AlignRule& alignRule);
105     float GetVerticalAnchorValueByAlignRule(AlignRule& alignRule);
106     std::pair<float, float> CalcOffsetInChainGetStart(const float& anchorDistance, const float& contentSize,
107         int32_t itemCount, const ChainParam& chainParam, LineDirection direction);
108     void RecordOffsetInChain(float offset, float spaceSize, const std::string& chainName, LineDirection direction);
109     bool CalcOffsetInChain(const std::string& chainName, LineDirection direction);
110     void PreTopologicalLoopDetectionGetAnchorSet(
111         const std::string& nodeName, const AlignRulesItem& alignRulesItem, std::set<std::string>& anchorSet);
112     bool PreTopologicalLoopDetection();
113     void TopologicalSort(std::list<std::string>& renderList);
114     void CalcSizeParam(LayoutWrapper* layoutWrapper, const std::string& nodeName);
115     void CalcOffsetParam(LayoutWrapper* layoutWrapper, const std::string& nodeName);
116     void CalcHorizontalLayoutParam(AlignDirection alignDirection, const AlignRule& alignRule,
117         LayoutWrapper* layoutWrapper, const std::string& nodeName);
118     void CalcVerticalLayoutParam(AlignDirection alignDirection, const AlignRule& alignRule,
119         LayoutWrapper* layoutWrapper, const std::string& nodeName);
120     float CalcHorizontalOffsetAlignLeft(const HorizontalAlign& alignRule, float& anchorWidth);
121     float CalcHorizontalOffsetAlignMiddle(const HorizontalAlign& alignRule, float& anchorWidth, float& flexItemWidth);
122     float CalcHorizontalOffsetAlignRight(const HorizontalAlign& alignRule, float& anchorWidth, float& flexItemWidth);
123     float CalcHorizontalOffset(
124         AlignDirection alignDirection, const AlignRule& alignRule, float containerWidth, const std::string& nodeName);
125     float CalcVerticalOffsetAlignTop(const VerticalAlign& alignRule, float& anchorHeight);
126     float CalcVerticalOffsetAlignCenter(const VerticalAlign& alignRule, float& anchorHeight, float& flexItemHeight);
127     float CalcVerticalOffsetAlignBottom(const VerticalAlign& alignRule, float& anchorHeight, float& flexItemHeight);
128     float CalcVerticalOffset(
129         AlignDirection alignDirection, const AlignRule& alignRule, float containerHeight, const std::string& nodeName);
130     bool IsValidBias(float bias);
131     void CalcBiasTowDirection(std::pair<TwoAlignedValues, TwoAlignedValues>& alignedValuesOnTwoDirections,
132         ChildIdealSize& childIdealSize, BiasPair& biasPair, float& horizontalOffset, float& verticalOffset);
133     OffsetF CalcBias(const std::string& nodeName);
134     std::pair<TwoAlignedValues, TwoAlignedValues> GetFirstTwoAlignValues(const RefPtr<LayoutWrapper>& childWrapper,
135         const std::unique_ptr<FlexItemProperty>& flexItemProperty, const ChildIdealSize& childIdealSize);
136     void UpdateTwoAlignValues(TwoAlignedValues& twoAlignedValues, AlignRule alignRule, LineDirection direction);
137     void UpdateSizeWhenChildrenEmpty(LayoutWrapper* layoutWrapper);
138     bool IsAnchorLegal(const std::string& anchorName);
139     void MeasureChild(LayoutWrapper* layoutWrapper);
140     void MeasureChainWeight(LayoutWrapper* layoutWrapper);
141     void InitRemainingSpace(const std::string & chainName, LineDirection direction);
142     BarrierDirection BarrierDirectionRtl(BarrierDirection barrierDirection);
143     void CalcChainWeightSize(const std::unique_ptr<FlexItemProperty>& flexItem,
144         LayoutConstraintF& childConstraint, const std::string & chainName, LineDirection direction);
145     bool HasWeight(const std::unique_ptr<FlexItemProperty>& flexItem, LineDirection direction);
146     void AdjustOffsetRtl(LayoutWrapper* layoutWrapper);
147     bool versionGreatorOrEqualToEleven_ = false;
148     bool isHorizontalRelyOnContainer_ = false;
149     bool isVerticalRelyOnContainer_ = false;
150     bool isChainWeightMode_ = false;
151     std::list<std::string> renderList_;
152     std::unordered_map<std::string, ChildMeasureWrapper> idNodeMap_;
153     std::unordered_map<std::string, uint32_t> incomingDegreeMap_;
154     std::unordered_map<std::string, std::set<std::string>> reliedOnMap_;
155     std::unordered_map<std::string, OffsetF> recordOffsetMap_;
156     std::unordered_map<std::string, BarrierParams> barriers_;
157     std::unordered_map<std::string, GuidelineParams> guidelines_;
158     std::unordered_map<std::string, ChainParam> horizontalChains_;
159     std::unordered_map<std::string, ChainParam> verticalChains_;
160     std::unordered_map<std::string, std::string> horizontalChainNodeMap_;
161     std::unordered_map<std::string, std::string> verticalChainNodeMap_;
162     PaddingPropertyF padding_;
163     SizeF containerSizeWithoutPaddingBorder_;
164 };
165 
166 } // namespace OHOS::Ace::NG
167 #endif // FOUNDATION_ACE_FRAMEWORKS_CORE_COMPONENTS_NG_PATTERN_RELATIVE_CONTAINER_RELATIVE_CONTAINER_LAYOUT_ALGORITHM_H