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 #include "core/components_ng/pattern/flex/flex_model_ng.h"
17 
18 #include "base/log/log_wrapper.h"
19 #include "base/utils/macros.h"
20 #include "core/components/common/layout/constants.h"
21 #include "core/components_ng/base/frame_node.h"
22 #include "core/components_ng/base/view_stack_processor.h"
23 #include "core/components_ng/pattern/flex/flex_layout_pattern.h"
24 #include "core/components_ng/pattern/flex/flex_layout_property.h"
25 #include "core/components_ng/pattern/linear_layout/linear_layout_pattern.h"
26 #include "core/components_ng/property/measure_utils.h"
27 #include "core/components_v2/inspector/inspector_constants.h"
28 
29 namespace OHOS::Ace::NG {
30 
CreateFlexRow()31 void FlexModelNG::CreateFlexRow()
32 {
33     auto* stack = ViewStackProcessor::GetInstance();
34     auto nodeId = stack->ClaimNodeId();
35     ACE_LAYOUT_SCOPED_TRACE("Create[%s][self:%d]", V2::FLEX_ETS_TAG, nodeId);
36     auto childFrameNode = FrameNode::GetFrameNode(V2::FLEX_ETS_TAG, nodeId);
37     if (!childFrameNode) {
38         auto frameNode = FrameNode::GetOrCreateFrameNode(
39             V2::FLEX_ETS_TAG, nodeId, []() { return AceType::MakeRefPtr<FlexLayoutPattern>(); });
40         stack->Push(frameNode);
41 
42         ACE_UPDATE_LAYOUT_PROPERTY(FlexLayoutProperty, FlexDirection, FlexDirection::ROW);
43         ACE_UPDATE_LAYOUT_PROPERTY(FlexLayoutProperty, MainAxisAlign, FlexAlign::FLEX_START);
44         ACE_UPDATE_LAYOUT_PROPERTY(FlexLayoutProperty, CrossAxisAlign, FlexAlign::FLEX_START);
45         return;
46     }
47     stack->Push(childFrameNode);
48     auto pattern = childFrameNode->GetPattern<FlexLayoutPattern>();
49     if (!pattern->GetIsWrap()) {
50         return;
51     }
52     // wrap to flex
53     pattern->SetIsWrap(false);
54     auto layoutProperty = pattern->GetLayoutProperty<FlexLayoutProperty>();
55     CHECK_NULL_VOID(layoutProperty);
56     layoutProperty->ResetWrapLayoutAttribute();
57 }
58 
CreateWrap()59 void FlexModelNG::CreateWrap()
60 {
61     auto* stack = ViewStackProcessor::GetInstance();
62     auto nodeId = stack->ClaimNodeId();
63     ACE_LAYOUT_SCOPED_TRACE("Create[%s][self:%d]", V2::FLEX_ETS_TAG, nodeId);
64     auto childFrameNode = FrameNode::GetFrameNode(V2::FLEX_ETS_TAG, nodeId);
65     if (!childFrameNode) {
66         auto frameNode = FrameNode::GetOrCreateFrameNode(
67             V2::FLEX_ETS_TAG, nodeId, []() { return AceType::MakeRefPtr<FlexLayoutPattern>(true); });
68         stack->Push(frameNode);
69         ACE_UPDATE_LAYOUT_PROPERTY(FlexLayoutProperty, WrapDirection, WrapDirection::HORIZONTAL);
70         ACE_UPDATE_LAYOUT_PROPERTY(FlexLayoutProperty, Alignment, WrapAlignment::START);
71         ACE_UPDATE_LAYOUT_PROPERTY(FlexLayoutProperty, MainAlignment, WrapAlignment::START);
72         ACE_UPDATE_LAYOUT_PROPERTY(FlexLayoutProperty, CrossAlignment, WrapAlignment::START);
73         return;
74     }
75     stack->Push(childFrameNode);
76     auto pattern = childFrameNode->GetPattern<FlexLayoutPattern>();
77     if (pattern->GetIsWrap()) {
78         return;
79     }
80     // flex to wrap
81     pattern->SetIsWrap(true);
82     auto layoutProperty = childFrameNode->GetLayoutProperty<FlexLayoutProperty>();
83     CHECK_NULL_VOID(layoutProperty);
84     layoutProperty->ResetFlexLayoutAttribute();
85 }
86 
CreateFrameNode(int32_t nodeId)87 RefPtr<FrameNode> FlexModelNG::CreateFrameNode(int32_t nodeId)
88 {
89     auto frameNode = FrameNode::CreateFrameNode(
90         V2::FLEX_ETS_TAG, nodeId, AceType::MakeRefPtr<FlexLayoutPattern>());
91     auto pattern = frameNode->GetPattern<FlexLayoutPattern>();
92     auto layoutProperty = frameNode->GetLayoutProperty<FlexLayoutProperty>();
93     layoutProperty->UpdateFlexDirection(FlexDirection::ROW);
94     layoutProperty->UpdateMainAxisAlign(FlexAlign::FLEX_START);
95     layoutProperty->UpdateCrossAxisAlign(FlexAlign::FLEX_START);
96     return frameNode;
97 }
98 
SetDirection(FlexDirection direction)99 void FlexModelNG::SetDirection(FlexDirection direction)
100 {
101     ACE_UPDATE_LAYOUT_PROPERTY(FlexLayoutProperty, FlexDirection, direction);
102 }
103 
SetWrapDirection(WrapDirection direction)104 void FlexModelNG::SetWrapDirection(WrapDirection direction)
105 {
106     ACE_UPDATE_LAYOUT_PROPERTY(FlexLayoutProperty, WrapDirection, direction);
107 }
108 
SetMainAxisAlign(FlexAlign align)109 void FlexModelNG::SetMainAxisAlign(FlexAlign align)
110 {
111     ACE_UPDATE_LAYOUT_PROPERTY(FlexLayoutProperty, MainAxisAlign, align);
112 }
113 
SetWrapMainAlignment(WrapAlignment value)114 void FlexModelNG::SetWrapMainAlignment(WrapAlignment value)
115 {
116     ACE_UPDATE_LAYOUT_PROPERTY(FlexLayoutProperty, MainAlignment, value);
117 }
118 
SetCrossAxisAlign(FlexAlign align)119 void FlexModelNG::SetCrossAxisAlign(FlexAlign align)
120 {
121     ACE_UPDATE_LAYOUT_PROPERTY(FlexLayoutProperty, CrossAxisAlign, align);
122 }
123 
SetWrapCrossAlignment(WrapAlignment value)124 void FlexModelNG::SetWrapCrossAlignment(WrapAlignment value)
125 {
126     ACE_UPDATE_LAYOUT_PROPERTY(FlexLayoutProperty, CrossAlignment, value);
127 }
128 
SetWrapAlignment(WrapAlignment value)129 void FlexModelNG::SetWrapAlignment(WrapAlignment value)
130 {
131     ACE_UPDATE_LAYOUT_PROPERTY(FlexLayoutProperty, Alignment, value);
132 }
133 
SetAlignItems(int32_t value)134 void FlexModelNG::SetAlignItems(int32_t value)
135 {
136     auto frameNode = ViewStackProcessor::GetInstance()->GetMainFrameNode();
137     CHECK_NULL_VOID(frameNode);
138     auto pattern = frameNode->GetPattern<FlexLayoutPattern>();
139     if (!pattern->GetIsWrap()) {
140         SetCrossAxisAlign(static_cast<FlexAlign>(value));
141         return;
142     }
143     SetWrapCrossAlignment(static_cast<WrapAlignment>(value));
144 }
145 
SetJustifyContent(int32_t value)146 void FlexModelNG::SetJustifyContent(int32_t value)
147 {
148     auto frameNode = ViewStackProcessor::GetInstance()->GetMainFrameNode();
149     CHECK_NULL_VOID(frameNode);
150     auto pattern = frameNode->GetPattern<FlexLayoutPattern>();
151     if (!pattern->GetIsWrap()) {
152         SetMainAxisAlign(static_cast<FlexAlign>(value));
153         return;
154     }
155     SetWrapMainAlignment(static_cast<WrapAlignment>(value));
156 }
157 
SetAlignContent(int32_t value)158 void FlexModelNG::SetAlignContent(int32_t value)
159 {
160     auto frameNode = ViewStackProcessor::GetInstance()->GetMainFrameNode();
161     CHECK_NULL_VOID(frameNode);
162     auto pattern = frameNode->GetPattern<FlexLayoutPattern>();
163     if (!pattern->GetIsWrap()) {
164         return;
165     }
166     SetWrapAlignment(static_cast<WrapAlignment>(value));
167 }
168 
SetFlexRow(FrameNode * frameNode)169 void FlexModelNG::SetFlexRow(FrameNode* frameNode)
170 {
171     ACE_UPDATE_NODE_LAYOUT_PROPERTY(FlexLayoutProperty, FlexDirection, FlexDirection::ROW, frameNode);
172     ACE_UPDATE_NODE_LAYOUT_PROPERTY(FlexLayoutProperty, MainAxisAlign, FlexAlign::FLEX_START, frameNode);
173     ACE_UPDATE_NODE_LAYOUT_PROPERTY(FlexLayoutProperty, CrossAxisAlign, FlexAlign::FLEX_START, frameNode);
174 
175     auto pattern = frameNode->GetPattern<FlexLayoutPattern>();
176     pattern->SetIsWrap(false);
177 }
178 
SetFlexWrap(FrameNode * frameNode)179 void FlexModelNG::SetFlexWrap(FrameNode* frameNode)
180 {
181     ACE_UPDATE_NODE_LAYOUT_PROPERTY(FlexLayoutProperty, WrapDirection, WrapDirection::HORIZONTAL, frameNode);
182     ACE_UPDATE_NODE_LAYOUT_PROPERTY(FlexLayoutProperty, Alignment, WrapAlignment::START, frameNode);
183     ACE_UPDATE_NODE_LAYOUT_PROPERTY(FlexLayoutProperty, MainAlignment, WrapAlignment::START, frameNode);
184     ACE_UPDATE_NODE_LAYOUT_PROPERTY(FlexLayoutProperty, CrossAlignment, WrapAlignment::START, frameNode);
185 
186     auto pattern = frameNode->GetPattern<FlexLayoutPattern>();
187     pattern->SetIsWrap(true);
188 }
189 
SetFlexDirection(FrameNode * frameNode,FlexDirection value)190 void FlexModelNG::SetFlexDirection(FrameNode* frameNode, FlexDirection value)
191 {
192     ACE_UPDATE_NODE_LAYOUT_PROPERTY(FlexLayoutProperty, FlexDirection, value, frameNode);
193 }
194 
SetFlexWrapDirection(FrameNode * frameNode,WrapDirection value)195 void FlexModelNG::SetFlexWrapDirection(FrameNode* frameNode, WrapDirection value)
196 {
197     ACE_UPDATE_NODE_LAYOUT_PROPERTY(FlexLayoutProperty, WrapDirection, value, frameNode);
198 }
199 
SetFlexJustifyContent(FrameNode * frameNode,int32_t value)200 void FlexModelNG::SetFlexJustifyContent(FrameNode* frameNode, int32_t value)
201 {
202     auto pattern = frameNode->GetPattern<FlexLayoutPattern>();
203     if (!pattern->GetIsWrap()) {
204         ACE_UPDATE_NODE_LAYOUT_PROPERTY(FlexLayoutProperty, MainAxisAlign, static_cast<FlexAlign>(value), frameNode);
205         return;
206     }
207     ACE_UPDATE_NODE_LAYOUT_PROPERTY(FlexLayoutProperty, MainAlignment, static_cast<WrapAlignment>(value), frameNode);
208 }
209 
SetFlexAlignItems(FrameNode * frameNode,int32_t value)210 void FlexModelNG::SetFlexAlignItems(FrameNode* frameNode, int32_t value)
211 {
212     auto pattern = frameNode->GetPattern<FlexLayoutPattern>();
213     if (!pattern->GetIsWrap()) {
214         ACE_UPDATE_NODE_LAYOUT_PROPERTY(FlexLayoutProperty, CrossAxisAlign, static_cast<FlexAlign>(value), frameNode);
215         return;
216     }
217     ACE_UPDATE_NODE_LAYOUT_PROPERTY(FlexLayoutProperty, CrossAlignment, static_cast<WrapAlignment>(value), frameNode);
218 }
219 
SetFlexAlignContent(FrameNode * frameNode,int32_t value)220 void FlexModelNG::SetFlexAlignContent(FrameNode* frameNode, int32_t value)
221 {
222     auto pattern = frameNode->GetPattern<FlexLayoutPattern>();
223     if (!pattern->GetIsWrap()) {
224         return;
225     }
226     ACE_UPDATE_NODE_LAYOUT_PROPERTY(FlexLayoutProperty, Alignment, static_cast<WrapAlignment>(value), frameNode);
227 }
228 
GetFlexWrap(FrameNode * frameNode)229 int FlexModelNG::GetFlexWrap(FrameNode* frameNode)
230 {
231     int value = 0;
232     auto pattern = frameNode->GetPattern<FlexLayoutPattern>();
233     if (!pattern->GetIsWrap()) {
234         value = static_cast<int>(FlexWrap::NO_WRAP);
235     } else {
236         WrapDirection direction = WrapDirection::HORIZONTAL;
237         ACE_GET_NODE_LAYOUT_PROPERTY_WITH_DEFAULT_VALUE(
238             FlexLayoutProperty, WrapDirection, direction, frameNode, direction);
239         int intDirection = static_cast<int>(direction);
240         if (intDirection == 0 || intDirection == 1) {
241             value = static_cast<int>(FlexWrap::WRAP);
242         } else {
243             value = static_cast<int>(FlexWrap::WRAP_REVERSE);
244         }
245     }
246     return value;
247 }
248 
GetFlexDirection(FrameNode * frameNode)249 int FlexModelNG::GetFlexDirection(FrameNode* frameNode)
250 {
251     FlexDirection value = FlexDirection::ROW;
252     ACE_GET_NODE_LAYOUT_PROPERTY_WITH_DEFAULT_VALUE(FlexLayoutProperty, FlexDirection, value, frameNode, value);
253     return static_cast<int>(value);
254 }
255 
GetFlexJustifyContent(FrameNode * frameNode)256 int FlexModelNG::GetFlexJustifyContent(FrameNode* frameNode)
257 {
258     auto pattern = frameNode->GetPattern<FlexLayoutPattern>();
259     if (!pattern->GetIsWrap()) {
260         FlexAlign value = FlexAlign::AUTO;
261         ACE_GET_NODE_LAYOUT_PROPERTY_WITH_DEFAULT_VALUE(FlexLayoutProperty, MainAxisAlign, value, frameNode, value);
262         return static_cast<int>(value);
263     }
264     WrapAlignment value = WrapAlignment::START;
265     ACE_GET_NODE_LAYOUT_PROPERTY_WITH_DEFAULT_VALUE(FlexLayoutProperty, MainAlignment, value, frameNode, value);
266     return static_cast<int>(value);
267 }
268 
GetFlexAlignItems(FrameNode * frameNode)269 int FlexModelNG::GetFlexAlignItems(FrameNode* frameNode)
270 {
271     auto pattern = frameNode->GetPattern<FlexLayoutPattern>();
272     if (!pattern->GetIsWrap()) {
273         FlexAlign value = FlexAlign::AUTO;
274         ACE_GET_NODE_LAYOUT_PROPERTY_WITH_DEFAULT_VALUE(FlexLayoutProperty, CrossAxisAlign, value, frameNode, value);
275         return static_cast<int>(value);
276     }
277     WrapAlignment value = WrapAlignment::START;
278     ACE_GET_NODE_LAYOUT_PROPERTY_WITH_DEFAULT_VALUE(FlexLayoutProperty, CrossAlignment, value, frameNode, value);
279     return static_cast<int>(value);
280 }
281 
GetFlexAlignContent(FrameNode * frameNode)282 int FlexModelNG::GetFlexAlignContent(FrameNode* frameNode)
283 {
284     auto pattern = frameNode->GetPattern<FlexLayoutPattern>();
285     if (!pattern->GetIsWrap()) {
286         return 0;
287     }
288     WrapAlignment value = WrapAlignment::START;
289     ACE_GET_NODE_LAYOUT_PROPERTY_WITH_DEFAULT_VALUE(FlexLayoutProperty, Alignment, value, frameNode, value);
290     return static_cast<int>(value);
291 }
292 
SetMainSpace(const std::optional<Dimension> & space)293 void FlexModelNG::SetMainSpace(const std::optional<Dimension>& space)
294 {
295     CHECK_NULL_VOID(space);
296     if (GreatOrEqual(space->Value(), 0.0)) {
297         ACE_UPDATE_LAYOUT_PROPERTY(FlexLayoutProperty, Space, space.value());
298     }
299 }
300 
SetCrossSpace(const std::optional<Dimension> & space)301 void FlexModelNG::SetCrossSpace(const std::optional<Dimension>& space)
302 {
303     CHECK_NULL_VOID(space);
304     if (GreatOrEqual(space->Value(), 0.0)) {
305         ACE_UPDATE_LAYOUT_PROPERTY(FlexLayoutProperty, CrossSpace, space.value());
306     }
307 }
308 
SetMainSpace(FrameNode * frameNode,const std::optional<Dimension> & space)309 void FlexModelNG::SetMainSpace(FrameNode* frameNode, const std::optional<Dimension>& space)
310 {
311     CHECK_NULL_VOID(space);
312     if (GreatOrEqual(space->Value(), 0.0)) {
313         ACE_UPDATE_NODE_LAYOUT_PROPERTY(FlexLayoutProperty, Space, space.value(), frameNode);
314     }
315 }
316 
SetCrossSpace(FrameNode * frameNode,const std::optional<Dimension> & space)317 void FlexModelNG::SetCrossSpace(FrameNode* frameNode, const std::optional<Dimension>& space)
318 {
319     CHECK_NULL_VOID(space);
320     if (GreatOrEqual(space->Value(), 0.0)) {
321         ACE_UPDATE_NODE_LAYOUT_PROPERTY(FlexLayoutProperty, CrossSpace, space.value(), frameNode);
322     }
323 }
324 } // namespace OHOS::Ace::NG
325