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