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 #include "core/interfaces/native/node/flex_modifier.h"
16 
17 #include "base/utils/utils.h"
18 #include "core/components/common/layout/constants.h"
19 #include "core/components/common/properties/alignment.h"
20 #include "core/components_ng/base/frame_node.h"
21 #include "core/components_ng/base/view_abstract.h"
22 #include "core/components_ng/pattern/flex/flex_model_ng.h"
23 #include "core/pipeline/base/element_register.h"
24 #include "frameworks/core/components/common/layout/constants.h"
25 
26 namespace OHOS::Ace::NG {
27 constexpr int NUM_0 = 0;
28 constexpr int NUM_1 = 1;
29 constexpr int NUM_2 = 2;
30 constexpr int NUM_3 = 3;
31 constexpr int NUM_4 = 4;
32 constexpr int NUM_5 = 5;
33 constexpr int NUM_6 = 6;
34 constexpr int NUM_7 = 7;
35 
ParseFlexToWrap(int align)36 int ParseFlexToWrap(int align)
37 {
38     FlexAlign alignment = FlexAlign::AUTO;
39     switch (align) {
40         case NUM_0: //WrapAlignment::START
41             alignment = FlexAlign::FLEX_START;
42             break;
43         case NUM_1: //WrapAlignment::CENTER
44             alignment = FlexAlign::CENTER;
45             break;
46         case NUM_2: //WrapAlignment::END
47             alignment = FlexAlign::FLEX_END;
48             break;
49         case NUM_3: //WrapAlignment::SPACE_AROUND
50             alignment = FlexAlign::SPACE_AROUND;
51             break;
52         case NUM_4: //WrapAlignment::SPACE_BETWEEN
53             alignment = FlexAlign::SPACE_BETWEEN;
54             break;
55         case NUM_5: //WrapAlignment::STRETCH
56             alignment = FlexAlign::STRETCH;
57             break;
58         case NUM_6: //WrapAlignment::SPACE_EVENLY
59             alignment = FlexAlign::SPACE_EVENLY;
60             break;
61         case NUM_7: //WrapAlignment::BASELINE
62             alignment = FlexAlign::BASELINE;
63             break;
64         default:
65             break;
66     }
67     return static_cast<int32_t>(alignment);
68 }
69 
SetFlexOptions(ArkUINodeHandle node,int * options,int length)70 void SetFlexOptions(ArkUINodeHandle node, int* options, int length)
71 {
72     auto* frameNode = reinterpret_cast<FrameNode*>(node);
73     CHECK_NULL_VOID(frameNode);
74     CHECK_NULL_VOID(options);
75     int direction = options[NUM_0];
76     int wrap = options[NUM_1];
77     int justifyContent = options[NUM_2];
78     int alignItems = options[NUM_3];
79     int alignContent = options[NUM_4];
80     if (wrap <= 0) {
81         FlexModelNG::SetFlexRow(frameNode);
82         if (direction >= 0 && direction <= DIRECTION_MAX_VALUE) {
83             FlexModelNG::SetFlexDirection(frameNode, static_cast<OHOS::Ace::FlexDirection>(direction));
84         }
85 
86         if (justifyContent >= 0 && justifyContent <= MAIN_ALIGN_MAX_VALUE) {
87             FlexModelNG::SetFlexJustifyContent(frameNode, justifyContent);
88         }
89 
90         if (alignItems >= 0 && alignItems <= CROSS_ALIGN_MAX_VALUE) {
91             FlexModelNG::SetFlexAlignItems(frameNode, alignItems);
92         }
93     } else if (wrap > 0) {
94         FlexModelNG::SetFlexWrap(frameNode);
95         if (direction >= 0 && direction <= DIRECTION_MAX_VALUE) {
96             FlexModelNG::SetFlexDirection(frameNode, static_cast<OHOS::Ace::FlexDirection>(direction));
97             // WrapReverse means wrapVal = 2. Wrap means wrapVal = 1.
98             direction <= 1 ? direction += NUM_2 * (wrap - NUM_1) : direction -= NUM_2 * (wrap - NUM_1);
99             FlexModelNG::SetFlexWrapDirection(frameNode, static_cast<WrapDirection>(direction));
100         } else {
101             // No direction set case: wrapVal == 2 means FlexWrap.WrapReverse.
102             WrapDirection wrapDirection = wrap == NUM_2 ? WrapDirection::HORIZONTAL_REVERSE : WrapDirection::HORIZONTAL;
103             FlexModelNG::SetFlexWrapDirection(frameNode, wrapDirection);
104         }
105 
106         if (justifyContent >= 0 && justifyContent <= MAIN_ALIGN_MAX_VALUE) {
107             FlexModelNG::SetFlexJustifyContent(frameNode, static_cast<int>(WRAP_TABLE[justifyContent]));
108         }
109 
110         if (alignItems >= 0 && alignItems <= CROSS_ALIGN_MAX_VALUE) {
111             FlexModelNG::SetFlexAlignItems(frameNode, static_cast<int>(WRAP_TABLE[alignItems]));
112         }
113 
114         if (alignContent >= 0 && alignContent <= MAIN_ALIGN_MAX_VALUE) {
115             FlexModelNG::SetFlexAlignContent(frameNode, static_cast<int>(WRAP_TABLE[alignContent]));
116         }
117     }
118 }
119 
ResetFlexOptions(ArkUINodeHandle node)120 void ResetFlexOptions(ArkUINodeHandle node)
121 {
122     auto* frameNode = reinterpret_cast<FrameNode*>(node);
123     CHECK_NULL_VOID(frameNode);
124     FlexModelNG::SetFlexRow(frameNode);
125     FlexModelNG::SetFlexDirection(frameNode, OHOS::Ace::FlexDirection::ROW);
126     FlexModelNG::SetFlexJustifyContent(frameNode, NUM_1);
127     FlexModelNG::SetFlexAlignItems(frameNode, NUM_1);
128     FlexModelNG::SetFlexAlignContent(frameNode, NUM_1);
129 }
130 
GetFlexOptions(ArkUINodeHandle node,ArkUIFlexOptions * options)131 void GetFlexOptions(ArkUINodeHandle node, ArkUIFlexOptions* options)
132 {
133     auto* frameNode = reinterpret_cast<FrameNode*>(node);
134     CHECK_NULL_VOID(frameNode);
135     options->direction = FlexModelNG::GetFlexDirection(frameNode);
136     options->wrap = FlexModelNG::GetFlexWrap(frameNode);
137     if (FlexModelNG::GetFlexWrap(frameNode) <= 0) {
138         options->justifyContent = FlexModelNG::GetFlexJustifyContent(frameNode);
139         options->alignItems = FlexModelNG::GetFlexAlignItems(frameNode);
140         options->alignContent = FlexModelNG::GetFlexAlignContent(frameNode);
141     } else {
142         options->justifyContent = ParseFlexToWrap(FlexModelNG::GetFlexJustifyContent(frameNode));
143         options->alignItems = ParseFlexToWrap(FlexModelNG::GetFlexAlignItems(frameNode));
144         options->alignContent = ParseFlexToWrap(FlexModelNG::GetFlexAlignContent(frameNode));
145     }
146 }
147 
setFlexCrossSpace(ArkUINodeHandle node,ArkUI_Float32 value,ArkUI_Int32 unit)148 void setFlexCrossSpace(ArkUINodeHandle node, ArkUI_Float32 value, ArkUI_Int32 unit)
149 {
150     auto* frameNode = reinterpret_cast<FrameNode*>(node);
151     CHECK_NULL_VOID(frameNode);
152     FlexModelNG::SetCrossSpace(frameNode, CalcDimension(value, (DimensionUnit)unit));
153 }
154 
SetMainSpace(ArkUINodeHandle node,ArkUI_Float32 value,ArkUI_Int32 unit)155 void SetMainSpace(ArkUINodeHandle node, ArkUI_Float32 value, ArkUI_Int32 unit)
156 {
157     auto* frameNode = reinterpret_cast<FrameNode*>(node);
158     CHECK_NULL_VOID(frameNode);
159     FlexModelNG::SetMainSpace(frameNode, CalcDimension(value, (DimensionUnit)unit));
160 }
161 
162 namespace NodeModifier {
GetFlexModifier()163 const ArkUIFlexModifier* GetFlexModifier()
164 {
165     static const ArkUIFlexModifier modifier = { SetFlexOptions, ResetFlexOptions, GetFlexOptions, setFlexCrossSpace,
166         SetMainSpace };
167     return &modifier;
168 }
169 
GetCJUIFlexModifier()170 const CJUIFlexModifier* GetCJUIFlexModifier()
171 {
172     static const CJUIFlexModifier modifier = {
173         SetFlexOptions, ResetFlexOptions, GetFlexOptions, setFlexCrossSpace, SetMainSpace
174     };
175     return &modifier;
176 }
177 }
178 }
179