1 /*
2 * Copyright (c) 2021 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/list/list_component.h"
17
18 #include "frameworks/core/components/ifelse/if_else_component.h"
19
20 namespace OHOS::Ace {
21
ListComponent(const std::list<RefPtr<Component>> & children)22 ListComponent::ListComponent(const std::list<RefPtr<Component>>& children) : ComponentGroup(children)
23 {
24 needPreBuild_ = true;
25 }
26
CreateElement()27 RefPtr<Element> ListComponent::CreateElement()
28 {
29 // This func will be called repeatedly when list in dialog.
30 needUpdateElement_ = true;
31 auto listElement = AceType::MakeRefPtr<ListElement>();
32 listElement_ = AceType::WeakClaim(AceType::RawPtr(listElement));
33 return listElement;
34 }
35
CreateRenderNode()36 RefPtr<RenderNode> ListComponent::CreateRenderNode()
37 {
38 return RenderList::Create();
39 }
40
InitStyle(const RefPtr<ListTheme> & theme)41 void ListComponent::InitStyle(const RefPtr<ListTheme>& theme)
42 {
43 if (theme) {
44 gradientWidth_ = theme->GetGradientWidth();
45 backgroundColor_ = theme->GetBackgroundColor();
46 }
47 }
48
SetFlexAlign(FlexAlign flexAlign)49 void ListComponent::SetFlexAlign(FlexAlign flexAlign)
50 {
51 if (flexAlign < FlexAlign::FLEX_START || flexAlign > FlexAlign::STRETCH) {
52 LOGW("Invalid flexAlign %{public}d", flexAlign);
53 return;
54 }
55 flexAlign_ = flexAlign;
56 }
57
SetColumnCount(int32_t count)58 void ListComponent::SetColumnCount(int32_t count)
59 {
60 if (count <= 0) {
61 LOGW("Invalid ColumnCount %{public}d", count);
62 return;
63 }
64 columnCount_ = count;
65 }
66
SetColumnExtent(int32_t extent)67 void ListComponent::SetColumnExtent(int32_t extent)
68 {
69 if (extent <= 0) {
70 return;
71 }
72 columnExtent_ = extent;
73 }
74
SetItemExtent(const Dimension & itemExtent)75 void ListComponent::SetItemExtent(const Dimension& itemExtent)
76 {
77 if (!itemExtent.IsValid()) {
78 return;
79 }
80 itemExtent_ = itemExtent;
81 }
82
SetWidth(double width)83 void ListComponent::SetWidth(double width)
84 {
85 if (width <= 0.0) {
86 LOGW("Invalid Width %{public}lf", width);
87 return;
88 }
89 width_ = width;
90 }
91
SetHeight(double height)92 void ListComponent::SetHeight(double height)
93 {
94 if (height <= 0.0) {
95 LOGW("Invalid Height %{public}lf", height);
96 return;
97 }
98 height_ = height;
99 }
100
InsertChild(int32_t position,const RefPtr<Component> & child)101 void ListComponent::InsertChild(int32_t position, const RefPtr<Component>& child)
102 {
103 if (position < 0) {
104 LOGE("InsertChild: the position is negative");
105 return;
106 }
107 auto pos = static_cast<uint32_t>(position);
108 auto item = ListItemComponent::GetListItem(child);
109 if (!item) {
110 LOGE("InsertChild: no list item in child");
111 return;
112 }
113
114 const auto& children = GetChildren();
115 if (!child || pos > children.size()) {
116 return;
117 }
118
119 if (pos == children.size()) {
120 AppendChild(child);
121 return;
122 }
123
124 int32_t current = 0;
125 auto it = children.begin();
126 while (it != children.end()) {
127 auto listItemComponent = ListItemComponent::GetListItem(*it);
128 if (listItemComponent && listItemComponent->GetOperation() == LIST_ITEM_OP_REMOVE) {
129 --current;
130 }
131
132 if (current == static_cast<int32_t>(pos)) {
133 break;
134 }
135
136 ++current;
137 ++it;
138 }
139
140 item->SetOperation(LIST_ITEM_OP_ADD);
141 needUpdateElement_ = true;
142 ComponentGroup::InsertChild(std::distance(children.begin(), it), child);
143 }
144
AppendChild(const RefPtr<Component> & child)145 void ListComponent::AppendChild(const RefPtr<Component>& child)
146 {
147 auto item = ListItemComponent::GetListItem(child);
148 if (!item) {
149 auto multiComposed = AceType::DynamicCast<MultiComposedComponent>(child);
150 if (!multiComposed) {
151 return;
152 }
153
154 for (const auto& childComponent : multiComposed->GetChildren()) {
155 AppendChild(childComponent);
156 }
157 return;
158 }
159 if (needDivider_) {
160 item->MarkNeedDivider(needDivider_);
161 item->SetDividerColor(dividerColor_);
162 item->SetDividerHeight(dividerHeight_);
163 item->SetDividerLength(dividerLength_);
164 item->SetDividerOrigin(dividerOrigin_);
165 }
166
167 item->SetIndex(GetChildren().size());
168 item->SetOperation(LIST_ITEM_OP_ADD);
169
170 needUpdateElement_ = true;
171 // Version 1.0 will wrap ComposedComponent for ListItem by DomNode.
172 if (AceType::InstanceOf<ComposedComponent>(child)) {
173 ComponentGroup::AppendChild(child);
174 } else {
175 ComponentGroup::AppendChild(
176 AceType::MakeRefPtr<ComposedComponent>((const char*)&item, "ListItemWrapper", child));
177 }
178 }
179
RemoveChild(const RefPtr<Component> & child)180 void ListComponent::RemoveChild(const RefPtr<Component>& child)
181 {
182 auto item = ListItemComponent::GetListItem(child);
183 if (!item) {
184 LOGE("RemoveChild: no list item in child");
185 return;
186 }
187
188 if (beginIndex_ != LIST_PARAM_INVAID && endIndex_ != LIST_PARAM_INVAID) {
189 ComponentGroup::RemoveChild(child);
190 needUpdateElement_ = true;
191 } else {
192 if (item->GetOperation() == LIST_ITEM_OP_ADD) {
193 ComponentGroup::RemoveChild(child);
194 return;
195 }
196 item->SetOperation(LIST_ITEM_OP_REMOVE);
197 needUpdateElement_ = true;
198 }
199 }
200
SetGroupState(int32_t expandIndex,bool expand)201 void ListComponent::SetGroupState(int32_t expandIndex, bool expand)
202 {
203 auto listElement = listElement_.Upgrade();
204 if (!listElement) {
205 LOGE("SetGroupState failed");
206 return;
207 }
208 listElement->SetGroupState(expandIndex, expand);
209 }
210
211 } // namespace OHOS::Ace
212