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