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_PROPERTIES_FLEX_PROPERTIES_H
17 #define FOUNDATION_ACE_FRAMEWORKS_CORE_COMPONENTS_NG_PROPERTIES_FLEX_PROPERTIES_H
18
19 #include <map>
20
21 #include "base/geometry/dimension.h"
22 #include "base/json/json_util.h"
23 #include "core/components/common/layout/constants.h"
24 #include "core/components/common/layout/position_param.h"
25 #include "core/components_ng/base/inspector_filter.h"
26 #include "core/components_ng/property/property.h"
27
28 namespace OHOS::Ace::NG {
29 using AlignRulesItem = std::map<AlignDirection, AlignRule>;
30 using BiasPair = std::pair<float, float>;
31 using GuidelineItem = std::vector<GuidelineInfo>;
32 using BarrierItem = std::vector<BarrierInfo>;
33 namespace {
34 constexpr int32_t HORIZONTAL_DIRECTION_RANGE = 3;
35 constexpr int32_t VERTICAL_DIRECTION_RANGE = 6;
HorizontalAlignToString(HorizontalAlign align)36 std::string HorizontalAlignToString(HorizontalAlign align)
37 {
38 switch (align) {
39 case HorizontalAlign::CENTER:
40 return "HorizontalAlign::Center";
41 case HorizontalAlign::START:
42 return "HorizontalAlign::Start";
43 case HorizontalAlign::END:
44 return "HorizontalAlign::End";
45 default:
46 return "Unknown";
47 }
48 }
49
VerticalAlignToString(VerticalAlign align)50 std::string VerticalAlignToString(VerticalAlign align)
51 {
52 switch (align) {
53 case VerticalAlign::TOP:
54 return "VerticalAlign::Top";
55 case VerticalAlign::CENTER:
56 return "VerticalAlign::Center";
57 case VerticalAlign::BOTTOM:
58 return "VerticalAlign::Bottom";
59 case VerticalAlign::BASELINE:
60 return "VerticalAlign::BaseLine";
61 default:
62 return "Unknown";
63 }
64 }
65
AlignDirectionToString(AlignDirection direction)66 std::string AlignDirectionToString(AlignDirection direction)
67 {
68 switch (direction) {
69 case AlignDirection::MIDDLE:
70 return "AlignDirection::Middle";
71 case AlignDirection::LEFT:
72 return "AlignDirection::Left";
73 case AlignDirection::RIGHT:
74 return "AlignDirection::Middle";
75 case AlignDirection::TOP:
76 return "AlignDirection::Top";
77 case AlignDirection::CENTER:
78 return "AlignDirection::Center";
79 case AlignDirection::BOTTOM:
80 return "AlignDirection::Bottom";
81 default:
82 return "Unknown";
83 }
84 }
85
SingleAlignRuleToString(AlignDirection direction,AlignRule rule)86 std::string SingleAlignRuleToString(AlignDirection direction, AlignRule rule)
87 {
88 std::string result = AlignDirectionToString(direction) + ": {'" + rule.anchor + "', ";
89 if (static_cast<int32_t>(direction) < HORIZONTAL_DIRECTION_RANGE) {
90 result += HorizontalAlignToString(rule.horizontal);
91 } else if (static_cast<int32_t>(direction) < VERTICAL_DIRECTION_RANGE) {
92 result += VerticalAlignToString(rule.vertical);
93 } else {
94 result += "Unknown";
95 }
96 result += "}";
97 return result;
98 }
99 } // namespace
100
101 struct FlexItemProperty {
102 ACE_DEFINE_PROPERTY_GROUP_ITEM(FlexGrow, float);
103 ACE_DEFINE_PROPERTY_GROUP_ITEM(FlexShrink, float);
104 ACE_DEFINE_PROPERTY_GROUP_ITEM(AlignSelf, FlexAlign);
105 ACE_DEFINE_PROPERTY_GROUP_ITEM(FlexBasis, Dimension);
106 ACE_DEFINE_PROPERTY_GROUP_ITEM(DisplayIndex, int32_t);
107 ACE_DEFINE_PROPERTY_GROUP_ITEM(AlignRules, AlignRulesItem);
108 ACE_DEFINE_PROPERTY_GROUP_ITEM(HorizontalChainStyle, ChainInfo);
109 ACE_DEFINE_PROPERTY_GROUP_ITEM(VerticalChainStyle, ChainInfo);
110 ACE_DEFINE_PROPERTY_GROUP_ITEM(AlignLeft, float);
111 ACE_DEFINE_PROPERTY_GROUP_ITEM(AlignMiddle, float);
112 ACE_DEFINE_PROPERTY_GROUP_ITEM(AlignRight, float);
113 ACE_DEFINE_PROPERTY_GROUP_ITEM(AlignTop, float);
114 ACE_DEFINE_PROPERTY_GROUP_ITEM(AlignCenter, float);
115 ACE_DEFINE_PROPERTY_GROUP_ITEM(AlignBottom, float);
116 ACE_DEFINE_PROPERTY_GROUP_ITEM(Bias, BiasPair);
117 ACE_DEFINE_PROPERTY_GROUP_ITEM(Barrier, BarrierItem);
118 ACE_DEFINE_PROPERTY_GROUP_ITEM(Guideline, GuidelineItem);
119
ToJsonValueFlexItemProperty120 void ToJsonValue(std::unique_ptr<JsonValue>& json, const InspectorFilter& filter) const
121 {
122 static const char* ITEM_ALIGN[] = { "ItemAlign.Auto", "ItemAlign.Start", "ItemAlign.Center", "ItemAlign.End",
123 "ItemAlign.Stretch", "ItemAlign.Baseline" };
124 /* no fixed attr below, just return */
125 if (filter.IsFastFilter()) {
126 return;
127 }
128 json->PutExtAttr("flexBasis",
129 propFlexBasis.has_value() ? propFlexBasis.value().ToString().c_str() : "auto", filter);
130 json->PutExtAttr("flexGrow", round(static_cast<double>(propFlexGrow.value_or(0.0)) * 100) / 100, filter);
131 json->PutExtAttr("flexShrink", round(static_cast<double>(propFlexShrink.value_or(1)) * 100) / 100, filter);
132 json->PutExtAttr("alignSelf",
133 ITEM_ALIGN[static_cast<int32_t>(propAlignSelf.value_or(FlexAlign::AUTO))], filter);
134 json->PutExtAttr("displayPriority", propDisplayIndex.value_or(1), filter);
135 }
136
AlignRulesToStringFlexItemProperty137 std::string AlignRulesToString()
138 {
139 std::string result;
140 if (!HasAlignRules()) {
141 return result;
142 }
143 auto rules = GetAlignRules().value();
144 auto iter = rules.begin();
145 for (; iter != rules.end(); iter++) {
146 result.append(SingleAlignRuleToString(iter->first, iter->second));
147 result.append(", ");
148 }
149 return result;
150 }
151
ClearAlignValueFlexItemProperty152 void ClearAlignValue()
153 {
154 ResetAlignLeft();
155 ResetAlignRight();
156 ResetAlignMiddle();
157 ResetAlignTop();
158 ResetAlignBottom();
159 ResetAlignCenter();
160 }
161
GetTwoHorizontalDirectionAlignedFlexItemProperty162 bool GetTwoHorizontalDirectionAligned() const
163 {
164 return (HasAlignLeft() && HasAlignRight()) || (HasAlignRight() && HasAlignMiddle()) ||
165 (HasAlignLeft() && HasAlignMiddle());
166 }
167
GetTwoVerticalDirectionAlignedFlexItemProperty168 bool GetTwoVerticalDirectionAligned() const
169 {
170 return (HasAlignTop() && HasAlignCenter()) || (HasAlignBottom() && HasAlignCenter()) ||
171 (HasAlignTop() && HasAlignBottom());
172 }
173
SetAlignValueFlexItemProperty174 void SetAlignValue(const AlignDirection& alignDirection, float value)
175 {
176 static const std::unordered_map<AlignDirection, void (*)(float, FlexItemProperty&)> operators = {
177 { AlignDirection::LEFT,
178 [](float inMapValue, FlexItemProperty& item) { item.UpdateAlignLeft(inMapValue); } },
179 { AlignDirection::RIGHT,
180 [](float inMapValue, FlexItemProperty& item) { item.UpdateAlignRight(inMapValue); } },
181 { AlignDirection::MIDDLE,
182 [](float inMapValue, FlexItemProperty& item) { item.UpdateAlignMiddle(inMapValue); } },
183 { AlignDirection::TOP, [](float inMapValue, FlexItemProperty& item) { item.UpdateAlignTop(inMapValue); } },
184 { AlignDirection::BOTTOM,
185 [](float inMapValue, FlexItemProperty& item) { item.UpdateAlignBottom(inMapValue); } },
186 { AlignDirection::CENTER,
187 [](float inMapValue, FlexItemProperty& item) { item.UpdateAlignCenter(inMapValue); } },
188 };
189 auto operatorIter = operators.find(alignDirection);
190 if (operatorIter != operators.end()) {
191 operatorIter->second(value, *this);
192 return;
193 }
194 LOGE("Unknown Align Direction");
195 }
196
GetAlignedFlexItemProperty197 bool GetAligned(const AlignDirection& alignDirection)
198 {
199 static const std::unordered_map<AlignDirection, bool (*)(FlexItemProperty&)> operators = {
200 { AlignDirection::LEFT, [](FlexItemProperty& item) { return item.HasAlignLeft(); } },
201 { AlignDirection::RIGHT, [](FlexItemProperty& item) { return item.HasAlignRight(); } },
202 { AlignDirection::MIDDLE, [](FlexItemProperty& item) { return item.HasAlignMiddle(); } },
203 { AlignDirection::TOP, [](FlexItemProperty& item) { return item.HasAlignTop(); } },
204 { AlignDirection::BOTTOM, [](FlexItemProperty& item) { return item.HasAlignBottom(); } },
205 { AlignDirection::CENTER, [](FlexItemProperty& item) { return item.HasAlignCenter(); } },
206 };
207 auto operatorIter = operators.find(alignDirection);
208 if (operatorIter != operators.end()) {
209 return operatorIter->second(*this);
210 }
211 LOGE("Unknown Align Direction");
212 return false;
213 }
214
GetAlignValueFlexItemProperty215 float GetAlignValue(const AlignDirection& alignDirection)
216 {
217 static const std::unordered_map<AlignDirection, float (*)(FlexItemProperty&)> operators = {
218 { AlignDirection::LEFT, [](FlexItemProperty& item) { return item.GetAlignLeft().value_or(0.0f); } },
219 { AlignDirection::RIGHT, [](FlexItemProperty& item) { return item.GetAlignRight().value_or(0.0f); } },
220 { AlignDirection::MIDDLE, [](FlexItemProperty& item) { return item.GetAlignMiddle().value_or(0.0f); } },
221 { AlignDirection::TOP, [](FlexItemProperty& item) { return item.GetAlignTop().value_or(0.0f); } },
222 { AlignDirection::BOTTOM, [](FlexItemProperty& item) { return item.GetAlignBottom().value_or(0.0f); } },
223 { AlignDirection::CENTER, [](FlexItemProperty& item) { return item.GetAlignCenter().value_or(0.0f); } },
224 };
225 auto operatorIter = operators.find(alignDirection);
226 if (operatorIter != operators.end()) {
227 return operatorIter->second(*this);
228 }
229 LOGE("Unknown Align Direction");
230 return 0.0f;
231 }
232 };
233 } // namespace OHOS::Ace::NG
234
235 #endif // FOUNDATION_ACE_FRAMEWORKS_CORE_COMPONENTS_NG_PROPERTIES_FLEX_PROPERTIES_H
236