1 /*
2 * Copyright (c) 2021-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/flex/render_flex_item.h"
17
18 #include "base/log/dump_log.h"
19 #include "base/utils/utils.h"
20 #include "core/components/flex/flex_item_component.h"
21
22 namespace OHOS::Ace {
23
Create()24 RefPtr<RenderNode> RenderFlexItem::Create()
25 {
26 return AceType::MakeRefPtr<RenderFlexItem>();
27 }
28
Update(const RefPtr<Component> & component)29 void RenderFlexItem::Update(const RefPtr<Component>& component)
30 {
31 const RefPtr<FlexItemComponent> flexItem = AceType::DynamicCast<FlexItemComponent>(component);
32 if (!flexItem) {
33 return;
34 }
35 // check the validity of properties
36 SetId(flexItem->GetInspectorKey());
37 SetAlignRules(flexItem->GetAlignRules());
38 if (flexItem->GetFlexShrink() >= 0.0) {
39 flexShrink_ = flexItem->GetFlexShrink();
40 }
41 if (flexItem->GetFlexBasis().Value() >= 0.0) {
42 flexBasis_ = flexItem->GetFlexBasis();
43 }
44 if (flexItem->GetFlexGrow() >= 0.0) {
45 flexGrow_ = flexItem->GetFlexGrow();
46 }
47 gridColumnInfo_ = flexItem->GetGridColumnInfo();
48 canStretch_ = flexItem->GetStretchFlag();
49 mustStretch_ = flexItem->MustStretch();
50 alignSelf_ = flexItem->GetAlignSelf();
51 if (minWidth_ != flexItem->GetMinWidth() || maxWidth_ != flexItem->GetMaxWidth() ||
52 minHeight_ != flexItem->GetMinHeight() || maxHeight_ != flexItem->GetMaxHeight()) {
53 auto parentFlex = GetParent().Upgrade();
54 if (parentFlex) {
55 parentFlex->MarkNeedLayout();
56 }
57 }
58 minWidth_ = flexItem->GetMinWidth();
59 minHeight_ = flexItem->GetMinHeight();
60 maxWidth_ = flexItem->GetMaxWidth();
61 maxHeight_ = flexItem->GetMaxHeight();
62 isHidden_ = flexItem->IsHidden();
63 displayType_ = flexItem->GetDisplayType();
64 MarkNeedLayout();
65 }
66
PerformLayout()67 void RenderFlexItem::PerformLayout()
68 {
69 RenderProxy::PerformLayout();
70 if (!gridColumnInfo_) {
71 return;
72 }
73 auto offset = gridColumnInfo_->GetOffset();
74 if (offset != UNDEFINED_DIMENSION) {
75 positionParam_.type = PositionType::PTSEMI_RELATIVE;
76 std::pair<AnimatableDimension, bool>& edge =
77 (GetTextDirection() == TextDirection::RTL) ? positionParam_.right : positionParam_.left;
78 edge.first = offset;
79 edge.second = true;
80 }
81 }
82
MaybeRelease()83 bool RenderFlexItem::MaybeRelease()
84 {
85 auto context = GetContext().Upgrade();
86 if (context && context->GetRenderFactory() &&
87 context->GetRenderFactory()->GetRenderFlexItemFactory()->Recycle(this)) {
88 ClearRenderObject();
89 return false;
90 }
91 return true;
92 }
93
ClearRenderObject()94 void RenderFlexItem::ClearRenderObject()
95 {
96 RenderNode::ClearRenderObject();
97 flexGrow_ = 0.0;
98 flexShrink_ = 0.0;
99 flexBasis_ = 0.0_px;
100 canStretch_ = true;
101 mustStretch_ = false;
102 minWidth_ = Dimension();
103 minHeight_ = Dimension();
104 maxWidth_ = Dimension(Size::INFINITE_SIZE);
105 maxHeight_ = Dimension(Size::INFINITE_SIZE);
106 alignSelf_ = FlexAlign::AUTO;
107 relativeLeftAligned_ = false;
108 relativeRightAligned_ = false;
109 relativeMiddleAligned_ = false;
110 relativeTopAligned_ = false;
111 relativeBottomAligned_ = false;
112 relativeCenterAligned_ = false;
113 relativeLeft_ = 0.0;
114 relativeRight_ = 0.0;
115 relativeMiddle_ = 0.0;
116 relativeTop_ = 0.0;
117 relativeBottom_ = 0.0;
118 relativeCenter_ = 0.0;
119 }
120
SetAligned(const AlignDirection & alignDirection)121 void RenderFlexItem::SetAligned(const AlignDirection& alignDirection)
122 {
123 static const std::unordered_map<AlignDirection, void (*)(RenderFlexItem&)> operators = {
124 { AlignDirection::LEFT, [](RenderFlexItem& item) {
125 item.relativeLeftAligned_ = true;
126 }},
127 { AlignDirection::RIGHT, [](RenderFlexItem& item) {
128 item.relativeRightAligned_ = true;
129 }},
130 { AlignDirection::MIDDLE, [](RenderFlexItem& item) {
131 item.relativeMiddleAligned_ = true;
132 }},
133 { AlignDirection::TOP, [](RenderFlexItem& item) {
134 item.relativeTopAligned_ = true;
135 }},
136 { AlignDirection::BOTTOM, [](RenderFlexItem& item) {
137 item.relativeBottomAligned_ = true;
138 }},
139 { AlignDirection::CENTER, [](RenderFlexItem& item) {
140 item.relativeCenterAligned_ = true;
141 }},
142 };
143 auto operatorIter = operators.find(alignDirection);
144 if (operatorIter != operators.end()) {
145 operatorIter->second(*this);
146 return;
147 }
148 LOGE("Unknown Align Direction");
149 }
150
GetAligned(AlignDirection & alignDirection)151 bool RenderFlexItem::GetAligned(AlignDirection& alignDirection)
152 {
153 static const std::unordered_map<AlignDirection, bool (*)(RenderFlexItem&)> operators = {
154 { AlignDirection::LEFT, [](RenderFlexItem& item) {
155 return item.relativeLeftAligned_;
156 }},
157 { AlignDirection::RIGHT, [](RenderFlexItem& item) {
158 return item.relativeRightAligned_;
159 }},
160 { AlignDirection::MIDDLE, [](RenderFlexItem& item) {
161 return item.relativeMiddleAligned_;
162 }},
163 { AlignDirection::TOP, [](RenderFlexItem& item) {
164 return item.relativeTopAligned_;
165 }},
166 { AlignDirection::BOTTOM, [](RenderFlexItem& item) {
167 return item.relativeBottomAligned_;
168 }},
169 { AlignDirection::CENTER, [](RenderFlexItem& item) {
170 return item.relativeCenterAligned_;
171 }},
172 };
173 auto operatorIter = operators.find(alignDirection);
174 if (operatorIter != operators.end()) {
175 return operatorIter->second(*this);
176 }
177 LOGE("Unknown Align Direction");
178 return false;
179 }
180
GetAlignValue(AlignDirection & alignDirection)181 double RenderFlexItem::GetAlignValue(AlignDirection& alignDirection)
182 {
183 static const std::unordered_map<AlignDirection, double (*)(RenderFlexItem&)> operators = {
184 { AlignDirection::LEFT, [](RenderFlexItem& item) {
185 return item.relativeLeft_;
186 }},
187 { AlignDirection::RIGHT, [](RenderFlexItem& item) {
188 return item.relativeRight_;
189 }},
190 { AlignDirection::MIDDLE, [](RenderFlexItem& item) {
191 return item.relativeMiddle_;
192 }},
193 { AlignDirection::TOP, [](RenderFlexItem& item) {
194 return item.relativeTop_;
195 }},
196 { AlignDirection::BOTTOM, [](RenderFlexItem& item) {
197 return item.relativeBottom_;
198 }},
199 { AlignDirection::CENTER, [](RenderFlexItem& item) {
200 return item.relativeCenter_;
201 }},
202 };
203 auto operatorIter = operators.find(alignDirection);
204 if (operatorIter != operators.end()) {
205 return operatorIter->second(*this);
206 }
207 LOGE("Unknown Align Direction");
208 return 0.0;
209 }
210
SetAlignValue(AlignDirection & alignDirection,double value)211 void RenderFlexItem::SetAlignValue(AlignDirection& alignDirection, double value)
212 {
213 static const std::unordered_map<AlignDirection, void (*)(double, RenderFlexItem&)> operators = {
214 { AlignDirection::LEFT, [](double inMapvalue, RenderFlexItem& item) {
215 item.relativeLeft_ = inMapvalue;
216 item.relativeLeftAligned_ = true;
217 }},
218 { AlignDirection::RIGHT, [](double inMapvalue, RenderFlexItem& item) {
219 item.relativeRight_ = inMapvalue;
220 item.relativeRightAligned_ = true;
221 }},
222 { AlignDirection::MIDDLE, [](double inMapvalue, RenderFlexItem& item) {
223 item.relativeMiddle_ = inMapvalue;
224 item.relativeMiddleAligned_ = true;
225 }},
226 { AlignDirection::TOP, [](double inMapvalue, RenderFlexItem& item) {
227 item.relativeTop_ = inMapvalue;
228 item.relativeTopAligned_ = true;
229 }},
230 { AlignDirection::BOTTOM, [](double inMapvalue, RenderFlexItem& item) {
231 item.relativeBottom_ = inMapvalue;
232 item.relativeBottomAligned_ = true;
233 }},
234 { AlignDirection::CENTER, [](double inMapvalue, RenderFlexItem& item) {
235 item.relativeCenter_ = inMapvalue;
236 item.relativeCenterAligned_ = true;
237 }},
238 };
239 auto operatorIter = operators.find(alignDirection);
240 if (operatorIter != operators.end()) {
241 operatorIter->second(value, *this);
242 return;
243 }
244 LOGE("Unknown Align Direction");
245 }
246
Dump()247 void RenderFlexItem::Dump()
248 {
249 DumpLog::GetInstance().AddDesc(std::string("FlexGrow: ")
250 .append(std::to_string(flexGrow_))
251 .append(", FlexShrink: ")
252 .append(std::to_string(flexShrink_))
253 .append(", FlexBasis: ")
254 .append(std::to_string(flexBasis_.Value())));
255 }
256
257 } // namespace OHOS::Ace
258