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