• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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     UIView* view = GetChildrenRenderHead();
235     while (view != nullptr) {
236         if (!view->IsViewGroup()) {
237             rect = view->GetRect();
238             if (rect.IsContains(point)) {
239                 view->GetTargetView(point, current, target);
240             }
241         } else {
242             UIViewGroup* viewGroup = static_cast<UIViewGroup*>(view);
243             viewGroup->GetTargetView(point, current, target);
244         }
245         view = view->GetNextRenderSibling();
246     }
247 }
248 
GetAllChildRelativeRect() const249 Rect UIViewGroup::GetAllChildRelativeRect() const
250 {
251     Rect rect = {0, 0, 0, 0};
252     UIView* view = childrenHead_;
253     bool isRectValid = false;
254     while (view != nullptr) {
255         if (!view->IsVisible()) {
256             view = view->GetNextSibling();
257             continue;
258         }
259         Rect rectChild = view->GetRelativeRect();
260         if (!isRectValid) {
261             rect = rectChild;
262             isRectValid = true;
263         } else {
264             rect.Join(rect, rectChild);
265         }
266         view = view->GetNextSibling();
267     }
268     return rect;
269 }
270 
GetChildrenRenderHead() const271 UIView* UIViewGroup::GetChildrenRenderHead() const
272 {
273     return childrenRenderHead_;
274 }
275 
SetChildrenRenderHead(UIView * renderHead)276 void UIViewGroup::SetChildrenRenderHead(UIView* renderHead)
277 {
278     if ((renderHead != nullptr) && (renderHead->GetParent() != this)) {
279         GRAPHIC_LOGE("can not set as render head if it is not a child view");
280         return;
281     }
282     childrenRenderHead_ = renderHead;
283 }
284 
GetChildById(const char * id) const285 UIView* UIViewGroup::GetChildById(const char* id) const
286 {
287     if (id == nullptr || childrenHead_ == nullptr) {
288         return nullptr;
289     }
290     UIView* child = childrenHead_;
291     while (child != nullptr) {
292         if ((child->GetViewId() != nullptr) && !strcmp(child->GetViewId(), id)) {
293             return child;
294         } else if (child->IsViewGroup() && static_cast<UIViewGroup*>(child)->GetChildrenHead() != nullptr) {
295             child = static_cast<UIViewGroup*>(child)->GetChildrenHead();
296             continue;
297         } else if (child->GetNextSibling() != nullptr) {
298             child = child->GetNextSibling();
299             continue;
300         }
301         while (child->GetParent() != this && child->GetParent()->GetNextSibling() == nullptr) {
302             child = child->GetParent();
303         }
304         if (child->GetParent() != this) {
305             child = child->GetParent()->GetNextSibling();
306             continue;
307         }
308         break;
309     }
310     return nullptr;
311 }
312 
MoveChildByOffset(int16_t xOffset,int16_t yOffset)313 void UIViewGroup::MoveChildByOffset(int16_t xOffset, int16_t yOffset)
314 {
315     UIView* view = childrenHead_;
316     while (view != nullptr) {
317         int16_t x = view->GetX() + xOffset;
318         int16_t y = view->GetY() + yOffset;
319         view->SetPosition(x, y);
320         view = view->GetNextSibling();
321     }
322 }
323 
AutoResize()324 void UIViewGroup::AutoResize()
325 {
326     Rect rect = GetAllChildRelativeRect();
327     SetWidth(rect.GetWidth() + rect.GetLeft());
328     SetHeight(rect.GetHeight() + rect.GetTop());
329 }
330 
RemoveRenderView(UIView * targetView)331 void UIViewGroup::RemoveRenderView(UIView* targetView)
332 {
333     if (targetView == nullptr) {
334         return;
335     }
336 
337     if (targetView->GetParent() == nullptr) {
338         return;
339     }
340 
341     UIViewGroup* viewGroup = reinterpret_cast<UIViewGroup*>(targetView->GetParent());
342     UIView* node = viewGroup->GetChildrenRenderHead();
343     if (node == nullptr) {
344         return;
345     }
346     if (node == targetView) {
347         viewGroup->SetChildrenRenderHead(node->GetNextRenderSibling());
348         targetView->SetNextRenderSibling(nullptr);
349     } else {
350         while (node->GetNextRenderSibling() != nullptr) {
351             if (node->GetNextRenderSibling() == targetView) {
352                 node->SetNextRenderSibling(targetView->GetNextRenderSibling());
353                 targetView->SetNextRenderSibling(nullptr);
354                 break;
355             }
356             node = node->GetNextRenderSibling();
357         }
358     }
359 }
360 
UpdateRenderView(UIView * targetView)361 void UIViewGroup::UpdateRenderView(UIView* targetView)
362 {
363     if (targetView == nullptr) {
364         return;
365     }
366 
367     if (targetView->GetParent() == nullptr) {
368         return;
369     }
370     RemoveRenderView(targetView);
371 
372     UIViewGroup* viewGroup = reinterpret_cast<UIViewGroup*>(targetView->GetParent());
373     UIView* curView = viewGroup->GetChildrenRenderHead();
374     if (curView == nullptr) {
375         viewGroup->SetChildrenRenderHead(targetView);
376         targetView->SetNextRenderSibling(nullptr);
377         return;
378     }
379 
380     int16_t curZIndex = curView->GetZIndex();
381     int16_t targetZIndex = targetView->GetZIndex();
382     UIView* nextView = curView->GetNextRenderSibling();
383     UIView* preView = nullptr;
384 
385     if (curZIndex > targetZIndex) {
386         targetView->SetNextRenderSibling(curView);
387         viewGroup->SetChildrenRenderHead(targetView);
388         return;
389     }
390 
391     if (nextView == nullptr) {
392         curView->SetNextRenderSibling(targetView);
393         targetView->SetNextRenderSibling(nullptr);
394         return;
395     }
396 
397     while (nextView != nullptr) {
398         curZIndex = curView->GetZIndex();
399         int16_t nextZIndex = nextView->GetZIndex();
400         if (curZIndex == targetZIndex) {
401             InsertRenderView(curView, preView, targetView);
402             return;
403         }
404         if ((curZIndex < targetZIndex) && (targetZIndex < nextZIndex)) {
405             curView->SetNextRenderSibling(targetView);
406             targetView->SetNextRenderSibling(nextView);
407             return;
408         }
409         preView = curView;
410         curView = nextView;
411         nextView = nextView->GetNextRenderSibling();
412     }
413 
414     curView->SetNextRenderSibling(targetView);
415     targetView->SetNextRenderSibling(nullptr);
416 }
417 
InsertRenderView(UIView * archorView,UIView * anchorPreView,UIView * targetView)418 void UIViewGroup::InsertRenderView(UIView* archorView, UIView* anchorPreView, UIView* targetView)
419 {
420     if ((targetView == nullptr) || (archorView == nullptr)) {
421         return;
422     }
423 
424     if (archorView->GetParent() == nullptr) {
425         return;
426     }
427 
428     UIViewGroup* viewGroup = reinterpret_cast<UIViewGroup*>(archorView->GetParent());
429     UIView* node = viewGroup->GetChildrenHead();
430     if (node == nullptr) {
431         return;
432     }
433 
434     int16_t targetZIndex = targetView->GetZIndex();
435     UIView* newArchorView = nullptr;
436 
437     if (node == targetView) {
438         targetView->SetNextRenderSibling(viewGroup->GetChildrenRenderHead());
439         viewGroup->SetChildrenRenderHead(targetView);
440         return;
441     }
442 
443     while (node->GetNextSibling() != nullptr) {
444         int16_t curZIndex = node->GetNextSibling()->GetZIndex();
445         if (curZIndex == targetZIndex) {
446             if ((node->GetNextSibling() == targetView) && (newArchorView == nullptr)) {
447                 targetView->SetNextRenderSibling(archorView);
448                 if (viewGroup->GetChildrenRenderHead() == archorView) {
449                     viewGroup->SetChildrenRenderHead(targetView);
450                 }
451                 if (anchorPreView != nullptr) {
452                     anchorPreView->SetNextRenderSibling(targetView);
453                 }
454                 break;
455             }
456             if (node->GetNextSibling() != targetView) {
457                 newArchorView = node->GetNextSibling();
458             }
459         }
460         if (node->GetNextSibling() == targetView) {
461             if (newArchorView != nullptr) {
462                 targetView->SetNextRenderSibling(newArchorView->GetNextRenderSibling());
463                 newArchorView->SetNextRenderSibling(targetView);
464             }
465             break;
466         }
467         node = node->GetNextSibling();
468     }
469 }
470 } // namespace OHOS
471