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