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 24namespace OHOS { 25UIViewGroup::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 40UIViewGroup::~UIViewGroup() {} 41 42void 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 72void 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 111void 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 152void 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 171void 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 209void 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 254Rect 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 276UIView* UIViewGroup::GetChildrenRenderHead() const 277{ 278 return childrenRenderHead_; 279} 280 281void 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 290UIView* 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 318void 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 329void UIViewGroup::AutoResize() 330{ 331 Rect rect = GetAllChildRelativeRect(); 332 SetWidth(rect.GetWidth() + rect.GetLeft()); 333 SetHeight(rect.GetHeight() + rect.GetTop()); 334} 335 336void 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 366void 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 421namespace { 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 438void 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