1 /*
2 * Copyright (c) 2020-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 "components/ui_view_group.h"
17
18 #include <cstring>
19
20 #include "components/root_view.h"
21 #include "components/ui_tree_manager.h"
22 #include "gfx_utils/graphic_log.h"
23
24 namespace OHOS {
UIViewGroup()25 UIViewGroup::UIViewGroup()
26 : childrenHead_(nullptr),
27 childrenRenderHead_(nullptr),
28 childrenTail_(nullptr),
29 childrenNum_(0),
30 isDragging_(false),
31 disallowIntercept_(false),
32 isAutoSize_(false)
33 {
34 isViewGroup_ = true;
35 #if ENABLE_FOCUS_MANAGER
36 isInterceptFocus_ = false;
37 #endif
38 }
39
~UIViewGroup()40 UIViewGroup::~UIViewGroup() {}
41
Add(UIView * view)42 void UIViewGroup::Add(UIView* view)
43 {
44 if ((view == this) || (view == nullptr)) {
45 GRAPHIC_LOGE("view can not be nullptr and added to self");
46 return;
47 }
48 if (view->GetParent() != nullptr) {
49 GRAPHIC_LOGE("can not add view multi times");
50 return;
51 }
52
53 if (childrenHead_ == nullptr) {
54 childrenHead_ = view;
55 } else {
56 if (childrenTail_ == nullptr) {
57 return;
58 }
59 childrenTail_->SetNextSibling(view);
60 }
61 view->SetParent(this);
62 view->SetNextSibling(nullptr);
63 childrenTail_ = view;
64 childrenNum_++;
65 if (isAutoSize_) {
66 AutoResize();
67 }
68 UpdateRenderView(view);
69 OnChildChanged();
70 }
71
Insert(UIView * prevView,UIView * insertView)72 void UIViewGroup::Insert(UIView* prevView, UIView* insertView)
73 {
74 if ((insertView == nullptr) || (insertView == this)) {
75 GRAPHIC_LOGE("insertView can not be nullptr and insert to self");
76 return;
77 }
78
79 if (insertView->GetParent() != nullptr) {
80 GRAPHIC_LOGE("can not insert view multi times");
81 return;
82 }
83
84 if (childrenHead_ == nullptr) {
85 Add(insertView);
86 UpdateRenderView(insertView);
87 return;
88 }
89
90 if (prevView == nullptr) {
91 insertView->SetNextSibling(childrenHead_);
92 insertView->SetParent(this);
93 childrenHead_ = insertView;
94 } else {
95 UIView* nextView = prevView->GetNextSibling();
96 prevView->SetNextSibling(insertView);
97 insertView->SetNextSibling(nextView);
98 insertView->SetParent(this);
99 }
100 if (childrenTail_ == prevView) {
101 childrenTail_ = insertView;
102 }
103 childrenNum_++;
104 if (isAutoSize_) {
105 AutoResize();
106 }
107 UpdateRenderView(insertView);
108 OnChildChanged();
109 }
110
Remove(UIView * view)111 void UIViewGroup::Remove(UIView* view)
112 {
113 if ((childrenHead_ == nullptr) || (view == nullptr)) {
114 return;
115 }
116 UITreeManager::GetInstance().OnLifeEvent(view, UITreeManager::REMOVE);
117
118 #if LOCAL_RENDER
119 RootView::GetInstance()->RemoveViewFromInvalidMap(view);
120 InvalidateRect(view->GetRect());
121 #endif
122 if (childrenHead_ == view) {
123 RemoveRenderView(view);
124 childrenHead_ = childrenHead_->GetNextSibling();
125 view->SetParent(nullptr);
126 view->SetNextSibling(nullptr);
127 if (childrenTail_ == view) {
128 childrenTail_ = nullptr;
129 }
130 childrenNum_--;
131 OnChildChanged();
132 return;
133 }
134 UIView* node = childrenHead_;
135 while (node->GetNextSibling() != nullptr) {
136 if (node->GetNextSibling() == view) {
137 RemoveRenderView(view);
138 node->SetNextSibling(view->GetNextSibling());
139 view->SetParent(nullptr);
140 view->SetNextSibling(nullptr);
141 if (childrenTail_ == view) {
142 childrenTail_ = node;
143 }
144 childrenNum_--;
145 OnChildChanged();
146 return;
147 }
148 node = node->GetNextSibling();
149 }
150 }
151
RemoveAll()152 void UIViewGroup::RemoveAll()
153 {
154 UIView* node = childrenHead_;
155 childrenHead_ = nullptr;
156 childrenTail_ = nullptr;
157 childrenRenderHead_ = nullptr;
158 childrenNum_ = 0;
159 UIView* tmp = nullptr;
160 while (node != nullptr) {
161 tmp = node;
162 UITreeManager::GetInstance().OnLifeEvent(node, UITreeManager::REMOVE);
163 node = node->GetNextSibling();
164 tmp->SetParent(nullptr);
165 tmp->SetNextSibling(nullptr);
166 tmp->SetNextRenderSibling(nullptr);
167 }
168 OnChildChanged();
169 }
170
GetTargetView(const Point & point,UIView ** last)171 void UIViewGroup::GetTargetView(const Point& point, UIView** last)
172 {
173 if (last == nullptr) {
174 return;
175 }
176
177 Rect rect = GetRect();
178 if (disallowIntercept_) {
179 *last = nullptr;
180 return;
181 }
182 if (!rect.IsContains(point)) {
183 return;
184 }
185 if (!visible_) {
186 return;
187 }
188 if (touchable_) {
189 *last = this;
190 }
191 if (isDragging_) {
192 return;
193 }
194 UIView* view = GetChildrenRenderHead();
195 while (view != nullptr) {
196 if (!view->IsViewGroup()) {
197 rect = view->GetRect();
198 if (rect.IsContains(point)) {
199 view->GetTargetView(point, last);
200 }
201 } else {
202 UIViewGroup* viewGroup = static_cast<UIViewGroup*>(view);
203 viewGroup->GetTargetView(point, last);
204 }
205 view = view->GetNextRenderSibling();
206 }
207 }
208
GetTargetView(const Point & point,UIView ** current,UIView ** target)209 void UIViewGroup::GetTargetView(const Point& point, UIView** current, UIView** target)
210 {
211 if ((current == nullptr) || (target == nullptr)) {
212 return;
213 }
214
215 Rect rect = GetRect();
216 if (disallowIntercept_) {
217 *current = nullptr;
218 *target = nullptr;
219 return;
220 }
221 if (!rect.IsContains(point)) {
222 return;
223 }
224 if (!visible_) {
225 return;
226 }
227 *target = this;
228 if (touchable_) {
229 *current = this;
230 }
231 if (isDragging_) {
232 return;
233 }
234 Point pointTran = point;
235 if (transMap_ != nullptr && !GetTransformMap().IsInvalid()) {
236 Rect relativeRect = GetOrigRect();
237 pointTran = GetTransformMap().GetOrigPoint(point, relativeRect);
238 }
239 UIView* view = GetChildrenRenderHead();
240 while (view != nullptr) {
241 if (!view->IsViewGroup()) {
242 rect = view->GetRect();
243 if (rect.IsContains(pointTran)) {
244 view->GetTargetView(pointTran, current, target);
245 }
246 } else {
247 UIViewGroup* viewGroup = static_cast<UIViewGroup*>(view);
248 viewGroup->GetTargetView(pointTran, current, target);
249 }
250 view = view->GetNextRenderSibling();
251 }
252 }
253
GetAllChildRelativeRect() const254 Rect UIViewGroup::GetAllChildRelativeRect() const
255 {
256 Rect rect = {0, 0, 0, 0};
257 UIView* view = childrenHead_;
258 bool isRectValid = false;
259 while (view != nullptr) {
260 if (!view->IsVisible()) {
261 view = view->GetNextSibling();
262 continue;
263 }
264 Rect rectChild = view->GetRelativeRect();
265 if (!isRectValid) {
266 rect = rectChild;
267 isRectValid = true;
268 } else {
269 rect.Join(rect, rectChild);
270 }
271 view = view->GetNextSibling();
272 }
273 return rect;
274 }
275
GetChildrenRenderHead() const276 UIView* UIViewGroup::GetChildrenRenderHead() const
277 {
278 return childrenRenderHead_;
279 }
280
SetChildrenRenderHead(UIView * renderHead)281 void UIViewGroup::SetChildrenRenderHead(UIView* renderHead)
282 {
283 if ((renderHead != nullptr) && (renderHead->GetParent() != this)) {
284 GRAPHIC_LOGE("can not set as render head if it is not a child view");
285 return;
286 }
287 childrenRenderHead_ = renderHead;
288 }
289
GetChildById(const char * id) const290 UIView* UIViewGroup::GetChildById(const char* id) const
291 {
292 if (id == nullptr || childrenHead_ == nullptr) {
293 return nullptr;
294 }
295 UIView* child = childrenHead_;
296 while (child != nullptr) {
297 if ((child->GetViewId() != nullptr) && !strcmp(child->GetViewId(), id)) {
298 return child;
299 } else if (child->IsViewGroup() && static_cast<UIViewGroup*>(child)->GetChildrenHead() != nullptr) {
300 child = static_cast<UIViewGroup*>(child)->GetChildrenHead();
301 continue;
302 } else if (child->GetNextSibling() != nullptr) {
303 child = child->GetNextSibling();
304 continue;
305 }
306 while (child->GetParent() != this && child->GetParent()->GetNextSibling() == nullptr) {
307 child = child->GetParent();
308 }
309 if (child->GetParent() != this) {
310 child = child->GetParent()->GetNextSibling();
311 continue;
312 }
313 break;
314 }
315 return nullptr;
316 }
317
MoveChildByOffset(int16_t xOffset,int16_t yOffset)318 void UIViewGroup::MoveChildByOffset(int16_t xOffset, int16_t yOffset)
319 {
320 UIView* view = childrenHead_;
321 while (view != nullptr) {
322 int16_t x = view->GetX() + xOffset;
323 int16_t y = view->GetY() + yOffset;
324 view->SetPosition(x, y);
325 view = view->GetNextSibling();
326 }
327 }
328
AutoResize()329 void UIViewGroup::AutoResize()
330 {
331 Rect rect = GetAllChildRelativeRect();
332 SetWidth(rect.GetWidth() + rect.GetLeft());
333 SetHeight(rect.GetHeight() + rect.GetTop());
334 }
335
RemoveRenderView(UIView * targetView)336 void UIViewGroup::RemoveRenderView(UIView* targetView)
337 {
338 if (targetView == nullptr) {
339 return;
340 }
341
342 if (targetView->GetParent() == nullptr) {
343 return;
344 }
345
346 UIViewGroup* viewGroup = reinterpret_cast<UIViewGroup*>(targetView->GetParent());
347 UIView* node = viewGroup->GetChildrenRenderHead();
348 if (node == nullptr) {
349 return;
350 }
351 if (node == targetView) {
352 viewGroup->SetChildrenRenderHead(node->GetNextRenderSibling());
353 targetView->SetNextRenderSibling(nullptr);
354 } else {
355 while (node->GetNextRenderSibling() != nullptr) {
356 if (node->GetNextRenderSibling() == targetView) {
357 node->SetNextRenderSibling(targetView->GetNextRenderSibling());
358 targetView->SetNextRenderSibling(nullptr);
359 break;
360 }
361 node = node->GetNextRenderSibling();
362 }
363 }
364 }
365
UpdateRenderView(UIView * targetView)366 void UIViewGroup::UpdateRenderView(UIView* targetView)
367 {
368 if (targetView == nullptr) {
369 return;
370 }
371
372 if (targetView->GetParent() == nullptr) {
373 return;
374 }
375 RemoveRenderView(targetView);
376
377 UIViewGroup* viewGroup = reinterpret_cast<UIViewGroup*>(targetView->GetParent());
378 UIView* curView = viewGroup->GetChildrenRenderHead();
379 if (curView == nullptr) {
380 viewGroup->SetChildrenRenderHead(targetView);
381 targetView->SetNextRenderSibling(nullptr);
382 return;
383 }
384
385 int16_t curZIndex = curView->GetZIndex();
386 int16_t targetZIndex = targetView->GetZIndex();
387 UIView* nextView = curView->GetNextRenderSibling();
388 UIView* preView = nullptr;
389
390 if (curZIndex > targetZIndex) {
391 targetView->SetNextRenderSibling(curView);
392 viewGroup->SetChildrenRenderHead(targetView);
393 return;
394 }
395
396 while (nextView != nullptr) {
397 int16_t nextZIndex = nextView->GetZIndex();
398 if (curZIndex == targetZIndex) {
399 InsertRenderView(curView, preView, targetView);
400 return;
401 }
402 if ((curZIndex < targetZIndex) && (targetZIndex < nextZIndex)) {
403 curView->SetNextRenderSibling(targetView);
404 targetView->SetNextRenderSibling(nextView);
405 return;
406 }
407 preView = curView;
408 curView = nextView;
409 nextView = nextView->GetNextRenderSibling();
410 curZIndex = curView->GetZIndex();
411 }
412
413 if (curZIndex == targetZIndex) {
414 InsertRenderView(curView, preView, targetView);
415 } else {
416 curView->SetNextRenderSibling(targetView);
417 targetView->SetNextRenderSibling(nullptr);
418 }
419 }
420
421 namespace {
AheadOfTargetView(UIView * currentView,UIView * targetView)422 bool AheadOfTargetView(UIView* currentView, UIView* targetView)
423 {
424 if ((targetView == nullptr) || (currentView == nullptr)) {
425 return false;
426 }
427 while (currentView != nullptr) {
428 UIView* nextView = currentView->GetNextSibling();
429 if (nextView == targetView) {
430 return true;
431 }
432 currentView = nextView;
433 }
434 return false;
435 }
436 }
437
InsertRenderView(UIView * anchorView,UIView * anchorPreView,UIView * targetView)438 void UIViewGroup::InsertRenderView(UIView* anchorView, UIView* anchorPreView, UIView* targetView)
439 {
440 if ((targetView == nullptr) || (anchorView == nullptr)) {
441 return;
442 }
443
444 if (anchorView->GetParent() == nullptr) {
445 return;
446 }
447 int16_t targetZIndex = targetView->GetZIndex();
448 int16_t curZIndex;
449 UIView* node = anchorView;
450 UIView* lastView = anchorPreView;
451 while (node != nullptr) {
452 curZIndex = node->GetZIndex();
453 if (curZIndex == targetZIndex) {
454 if (AheadOfTargetView(node, targetView)) {
455 lastView = node;
456 } else if (lastView == nullptr) {
457 UIViewGroup* viewGroup = reinterpret_cast<UIViewGroup*>(anchorView->GetParent());
458 targetView->SetNextRenderSibling(viewGroup->GetChildrenRenderHead());
459 viewGroup->SetChildrenRenderHead(targetView);
460 return;
461 } else {
462 lastView->SetNextRenderSibling(targetView);
463 targetView->SetNextRenderSibling(node);
464 return;
465 }
466 } else if (curZIndex > targetZIndex) {
467 lastView->SetNextRenderSibling(targetView);
468 targetView->SetNextRenderSibling(node);
469 return;
470 }
471 node = node->GetNextRenderSibling();
472 }
473 lastView->SetNextRenderSibling(targetView);
474 targetView->SetNextRenderSibling(nullptr);
475 }
476 } // namespace OHOS
477