1a3e0fd82Sopenharmony_ci/* 2a3e0fd82Sopenharmony_ci * Copyright (c) 2020-2021 Huawei Device Co., Ltd. 3a3e0fd82Sopenharmony_ci * Licensed under the Apache License, Version 2.0 (the "License"); 4a3e0fd82Sopenharmony_ci * you may not use this file except in compliance with the License. 5a3e0fd82Sopenharmony_ci * You may obtain a copy of the License at 6a3e0fd82Sopenharmony_ci * 7a3e0fd82Sopenharmony_ci * http://www.apache.org/licenses/LICENSE-2.0 8a3e0fd82Sopenharmony_ci * 9a3e0fd82Sopenharmony_ci * Unless required by applicable law or agreed to in writing, software 10a3e0fd82Sopenharmony_ci * distributed under the License is distributed on an "AS IS" BASIS, 11a3e0fd82Sopenharmony_ci * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12a3e0fd82Sopenharmony_ci * See the License for the specific language governing permissions and 13a3e0fd82Sopenharmony_ci * limitations under the License. 14a3e0fd82Sopenharmony_ci */ 15a3e0fd82Sopenharmony_ci 16a3e0fd82Sopenharmony_ci#include "layout/flex_layout.h" 17a3e0fd82Sopenharmony_ci 18a3e0fd82Sopenharmony_cinamespace OHOS { 19a3e0fd82Sopenharmony_civoid FlexLayout::LayoutChildren(bool needInvalidate) 20a3e0fd82Sopenharmony_ci{ 21a3e0fd82Sopenharmony_ci if (childrenHead_ == nullptr) { 22a3e0fd82Sopenharmony_ci return; 23a3e0fd82Sopenharmony_ci } 24a3e0fd82Sopenharmony_ci 25a3e0fd82Sopenharmony_ci if ((direction_ == LAYOUT_HOR) || (direction_ == LAYOUT_HOR_R)) { 26a3e0fd82Sopenharmony_ci LayoutHorizontal(); 27a3e0fd82Sopenharmony_ci } else { 28a3e0fd82Sopenharmony_ci LayoutVertical(); 29a3e0fd82Sopenharmony_ci } 30a3e0fd82Sopenharmony_ci if (needInvalidate) { 31a3e0fd82Sopenharmony_ci Invalidate(); 32a3e0fd82Sopenharmony_ci } 33a3e0fd82Sopenharmony_ci} 34a3e0fd82Sopenharmony_ci 35a3e0fd82Sopenharmony_civoid FlexLayout::GetStartPos(const int16_t& length, 36a3e0fd82Sopenharmony_ci int16_t& pos, 37a3e0fd82Sopenharmony_ci int16_t& interval, 38a3e0fd82Sopenharmony_ci int16_t count, 39a3e0fd82Sopenharmony_ci uint16_t* validLengths, 40a3e0fd82Sopenharmony_ci uint16_t* childsNum) 41a3e0fd82Sopenharmony_ci{ 42a3e0fd82Sopenharmony_ci if (!validLengths || !childsNum) { 43a3e0fd82Sopenharmony_ci return; 44a3e0fd82Sopenharmony_ci } 45a3e0fd82Sopenharmony_ci pos = 0; 46a3e0fd82Sopenharmony_ci interval = 0; 47a3e0fd82Sopenharmony_ci 48a3e0fd82Sopenharmony_ci if (majorAlign_ == ALIGN_START) { 49a3e0fd82Sopenharmony_ci pos = 0; 50a3e0fd82Sopenharmony_ci } else if (majorAlign_ == ALIGN_END) { 51a3e0fd82Sopenharmony_ci pos = length - validLengths[count]; 52a3e0fd82Sopenharmony_ci /* if total length of children is too long or only one child, layout them centerly no matter what key word set. 53a3e0fd82Sopenharmony_ci */ 54a3e0fd82Sopenharmony_ci } else if ((majorAlign_ == ALIGN_CENTER) || (validLengths[count] >= length) || (childsNum[count] == 1)) { 55a3e0fd82Sopenharmony_ci pos = (length - validLengths[count]) / 2; // 2: half 56a3e0fd82Sopenharmony_ci } else if (majorAlign_ == ALIGN_AROUND) { 57a3e0fd82Sopenharmony_ci if (childsNum[count] == 0) { 58a3e0fd82Sopenharmony_ci return; 59a3e0fd82Sopenharmony_ci } 60a3e0fd82Sopenharmony_ci interval = (length - validLengths[count]) / childsNum[count]; 61a3e0fd82Sopenharmony_ci pos = interval / 2; // 2: half 62a3e0fd82Sopenharmony_ci } else if (majorAlign_ == ALIGN_EVENLY) { 63a3e0fd82Sopenharmony_ci interval = (length - validLengths[count]) / (childsNum[count] + 1); 64a3e0fd82Sopenharmony_ci pos = interval; 65a3e0fd82Sopenharmony_ci } else { 66a3e0fd82Sopenharmony_ci interval = (length - validLengths[count]) / (childsNum[count] - 1); 67a3e0fd82Sopenharmony_ci pos = 0; 68a3e0fd82Sopenharmony_ci } 69a3e0fd82Sopenharmony_ci} 70a3e0fd82Sopenharmony_ci 71a3e0fd82Sopenharmony_civoid FlexLayout::GetNoWrapStartPos(const int16_t& length, int16_t& majorPos, int16_t& interval) 72a3e0fd82Sopenharmony_ci{ 73a3e0fd82Sopenharmony_ci uint16_t childrenNum = 0; 74a3e0fd82Sopenharmony_ci uint16_t totalValidLength = 0; 75a3e0fd82Sopenharmony_ci 76a3e0fd82Sopenharmony_ci CalValidLength(totalValidLength, childrenNum); 77a3e0fd82Sopenharmony_ci GetStartPos(length, majorPos, interval, 0, &totalValidLength, &childrenNum); 78a3e0fd82Sopenharmony_ci} 79a3e0fd82Sopenharmony_ci 80a3e0fd82Sopenharmony_civoid FlexLayout::GetRowStartPos(int16_t& pos, 81a3e0fd82Sopenharmony_ci int16_t& interval, 82a3e0fd82Sopenharmony_ci int16_t count, 83a3e0fd82Sopenharmony_ci uint16_t* rowsWidth, 84a3e0fd82Sopenharmony_ci uint16_t* rowsChildNum) 85a3e0fd82Sopenharmony_ci{ 86a3e0fd82Sopenharmony_ci GetStartPos(GetWidth(), pos, interval, count, rowsWidth, rowsChildNum); 87a3e0fd82Sopenharmony_ci} 88a3e0fd82Sopenharmony_ci 89a3e0fd82Sopenharmony_civoid FlexLayout::GetColumnStartPos(int16_t& pos, 90a3e0fd82Sopenharmony_ci int16_t& interval, 91a3e0fd82Sopenharmony_ci int16_t count, 92a3e0fd82Sopenharmony_ci uint16_t* columnsHeight, 93a3e0fd82Sopenharmony_ci uint16_t* columnsChildNum) 94a3e0fd82Sopenharmony_ci{ 95a3e0fd82Sopenharmony_ci GetStartPos(GetHeight(), pos, interval, count, columnsHeight, columnsChildNum); 96a3e0fd82Sopenharmony_ci} 97a3e0fd82Sopenharmony_ci 98a3e0fd82Sopenharmony_civoid FlexLayout::CalValidLength(uint16_t& totalValidLength, uint16_t& allChildNum) 99a3e0fd82Sopenharmony_ci{ 100a3e0fd82Sopenharmony_ci UIView* child = childrenHead_; 101a3e0fd82Sopenharmony_ci int16_t left; 102a3e0fd82Sopenharmony_ci int16_t right; 103a3e0fd82Sopenharmony_ci int16_t top; 104a3e0fd82Sopenharmony_ci int16_t bottom; 105a3e0fd82Sopenharmony_ci 106a3e0fd82Sopenharmony_ci /* calculate valid length of all children views */ 107a3e0fd82Sopenharmony_ci while (child != nullptr) { 108a3e0fd82Sopenharmony_ci if (child->IsVisible()) { 109a3e0fd82Sopenharmony_ci child->ReMeasure(); 110a3e0fd82Sopenharmony_ci if ((direction_ == LAYOUT_HOR) || (direction_ == LAYOUT_HOR_R)) { 111a3e0fd82Sopenharmony_ci left = child->GetStyle(STYLE_MARGIN_LEFT); 112a3e0fd82Sopenharmony_ci right = child->GetStyle(STYLE_MARGIN_RIGHT); 113a3e0fd82Sopenharmony_ci totalValidLength += (child->GetRelativeRect().GetWidth() + left + right); 114a3e0fd82Sopenharmony_ci } else { 115a3e0fd82Sopenharmony_ci top = child->GetStyle(STYLE_MARGIN_TOP); 116a3e0fd82Sopenharmony_ci bottom = child->GetStyle(STYLE_MARGIN_BOTTOM); 117a3e0fd82Sopenharmony_ci totalValidLength += (child->GetRelativeRect().GetHeight() + top + bottom); 118a3e0fd82Sopenharmony_ci } 119a3e0fd82Sopenharmony_ci allChildNum++; 120a3e0fd82Sopenharmony_ci } 121a3e0fd82Sopenharmony_ci child = child->GetNextSibling(); 122a3e0fd82Sopenharmony_ci } 123a3e0fd82Sopenharmony_ci} 124a3e0fd82Sopenharmony_ci 125a3e0fd82Sopenharmony_civoid FlexLayout::CalRowCount() 126a3e0fd82Sopenharmony_ci{ 127a3e0fd82Sopenharmony_ci UIView* child = childrenHead_; 128a3e0fd82Sopenharmony_ci int16_t pos = 0; 129a3e0fd82Sopenharmony_ci int16_t left; 130a3e0fd82Sopenharmony_ci int16_t right; 131a3e0fd82Sopenharmony_ci 132a3e0fd82Sopenharmony_ci rowCount_ = 1; 133a3e0fd82Sopenharmony_ci while (child != nullptr) { 134a3e0fd82Sopenharmony_ci if (child->IsVisible()) { 135a3e0fd82Sopenharmony_ci child->ReMeasure(); 136a3e0fd82Sopenharmony_ci left = child->GetStyle(STYLE_MARGIN_LEFT); 137a3e0fd82Sopenharmony_ci right = child->GetStyle(STYLE_MARGIN_RIGHT); 138a3e0fd82Sopenharmony_ci pos += left; 139a3e0fd82Sopenharmony_ci if ((pos + child->GetRelativeRect().GetWidth() + right) > GetWidth()) { 140a3e0fd82Sopenharmony_ci pos = left; 141a3e0fd82Sopenharmony_ci rowCount_++; 142a3e0fd82Sopenharmony_ci } 143a3e0fd82Sopenharmony_ci pos += child->GetRelativeRect().GetWidth() + right; 144a3e0fd82Sopenharmony_ci } 145a3e0fd82Sopenharmony_ci child = child->GetNextSibling(); 146a3e0fd82Sopenharmony_ci } 147a3e0fd82Sopenharmony_ci} 148a3e0fd82Sopenharmony_ci 149a3e0fd82Sopenharmony_civoid FlexLayout::GetRowMaxHeight(uint16_t size, uint16_t* maxRosHegiht) 150a3e0fd82Sopenharmony_ci{ 151a3e0fd82Sopenharmony_ci UIView* child = childrenHead_; 152a3e0fd82Sopenharmony_ci int16_t pos = 0; 153a3e0fd82Sopenharmony_ci int16_t left; 154a3e0fd82Sopenharmony_ci int16_t right; 155a3e0fd82Sopenharmony_ci int16_t top; 156a3e0fd82Sopenharmony_ci int16_t bottom; 157a3e0fd82Sopenharmony_ci uint16_t i = 0; 158a3e0fd82Sopenharmony_ci uint16_t height = 0; 159a3e0fd82Sopenharmony_ci 160a3e0fd82Sopenharmony_ci if ((maxRosHegiht == nullptr) || (size > rowCount_)) { 161a3e0fd82Sopenharmony_ci return; 162a3e0fd82Sopenharmony_ci } 163a3e0fd82Sopenharmony_ci 164a3e0fd82Sopenharmony_ci while (child != nullptr) { 165a3e0fd82Sopenharmony_ci if (child->IsVisible()) { 166a3e0fd82Sopenharmony_ci left = child->GetStyle(STYLE_MARGIN_LEFT); 167a3e0fd82Sopenharmony_ci right = child->GetStyle(STYLE_MARGIN_RIGHT); 168a3e0fd82Sopenharmony_ci top = child->GetStyle(STYLE_MARGIN_TOP); 169a3e0fd82Sopenharmony_ci bottom = child->GetStyle(STYLE_MARGIN_BOTTOM); 170a3e0fd82Sopenharmony_ci pos += left; 171a3e0fd82Sopenharmony_ci if ((pos + child->GetRelativeRect().GetWidth() + right) > GetWidth()) { 172a3e0fd82Sopenharmony_ci pos = left; 173a3e0fd82Sopenharmony_ci maxRosHegiht[i] = height; 174a3e0fd82Sopenharmony_ci height = 0; 175a3e0fd82Sopenharmony_ci i++; 176a3e0fd82Sopenharmony_ci } 177a3e0fd82Sopenharmony_ci height = MATH_MAX(height, child->GetRelativeRect().GetHeight() + top + bottom); 178a3e0fd82Sopenharmony_ci maxRosHegiht[i] = height; 179a3e0fd82Sopenharmony_ci pos += child->GetRelativeRect().GetWidth() + right; 180a3e0fd82Sopenharmony_ci } 181a3e0fd82Sopenharmony_ci child = child->GetNextSibling(); 182a3e0fd82Sopenharmony_ci } 183a3e0fd82Sopenharmony_ci} 184a3e0fd82Sopenharmony_ci 185a3e0fd82Sopenharmony_civoid FlexLayout::GetRowsWidth(uint16_t rowNum, uint16_t* rowsWidth, uint16_t* rowsChildNum) 186a3e0fd82Sopenharmony_ci{ 187a3e0fd82Sopenharmony_ci UIView* child = childrenHead_; 188a3e0fd82Sopenharmony_ci int16_t pos = 0; 189a3e0fd82Sopenharmony_ci int16_t left; 190a3e0fd82Sopenharmony_ci int16_t right; 191a3e0fd82Sopenharmony_ci uint16_t rowChildNum = 0; 192a3e0fd82Sopenharmony_ci uint16_t rowCount = 0; 193a3e0fd82Sopenharmony_ci uint16_t width = 0; 194a3e0fd82Sopenharmony_ci 195a3e0fd82Sopenharmony_ci if ((rowsWidth == nullptr) || (rowsChildNum == nullptr) || (rowNum > rowCount_)) { 196a3e0fd82Sopenharmony_ci return; 197a3e0fd82Sopenharmony_ci } 198a3e0fd82Sopenharmony_ci 199a3e0fd82Sopenharmony_ci while (child != nullptr) { 200a3e0fd82Sopenharmony_ci if (child->IsVisible()) { 201a3e0fd82Sopenharmony_ci left = child->GetStyle(STYLE_MARGIN_LEFT); 202a3e0fd82Sopenharmony_ci right = child->GetStyle(STYLE_MARGIN_RIGHT); 203a3e0fd82Sopenharmony_ci pos += left; 204a3e0fd82Sopenharmony_ci if ((pos + child->GetRelativeRect().GetWidth() + right) > GetWidth()) { 205a3e0fd82Sopenharmony_ci pos = left; 206a3e0fd82Sopenharmony_ci rowsWidth[rowCount] = width; 207a3e0fd82Sopenharmony_ci width = 0; 208a3e0fd82Sopenharmony_ci rowsChildNum[rowCount] = rowChildNum; 209a3e0fd82Sopenharmony_ci rowChildNum = 0; 210a3e0fd82Sopenharmony_ci rowCount++; 211a3e0fd82Sopenharmony_ci } 212a3e0fd82Sopenharmony_ci width += child->GetRelativeRect().GetWidth() + right + left; 213a3e0fd82Sopenharmony_ci rowsWidth[rowCount] = width; 214a3e0fd82Sopenharmony_ci rowChildNum++; 215a3e0fd82Sopenharmony_ci rowsChildNum[rowCount] = rowChildNum; 216a3e0fd82Sopenharmony_ci pos += child->GetRelativeRect().GetWidth() + right; 217a3e0fd82Sopenharmony_ci } 218a3e0fd82Sopenharmony_ci child = child->GetNextSibling(); 219a3e0fd82Sopenharmony_ci } 220a3e0fd82Sopenharmony_ci} 221a3e0fd82Sopenharmony_ci 222a3e0fd82Sopenharmony_civoid FlexLayout::GetCrossAxisPosY(int16_t& posY, uint16_t& count, uint16_t* rowsMaxHeight, UIView* child) 223a3e0fd82Sopenharmony_ci{ 224a3e0fd82Sopenharmony_ci if ((rowsMaxHeight == nullptr) || (child == nullptr)) { 225a3e0fd82Sopenharmony_ci return; 226a3e0fd82Sopenharmony_ci } 227a3e0fd82Sopenharmony_ci 228a3e0fd82Sopenharmony_ci uint16_t i = 0; 229a3e0fd82Sopenharmony_ci uint16_t offset = 0; 230a3e0fd82Sopenharmony_ci int16_t top = child->GetStyle(STYLE_MARGIN_TOP); 231a3e0fd82Sopenharmony_ci int16_t bottom = child->GetStyle(STYLE_MARGIN_BOTTOM); 232a3e0fd82Sopenharmony_ci 233a3e0fd82Sopenharmony_ci if (secondaryAlign_ == ALIGN_START) { 234a3e0fd82Sopenharmony_ci for (i = 0; i < count; i++) { 235a3e0fd82Sopenharmony_ci offset += rowsMaxHeight[i]; 236a3e0fd82Sopenharmony_ci } 237a3e0fd82Sopenharmony_ci posY = top + offset; 238a3e0fd82Sopenharmony_ci } else if (secondaryAlign_ == ALIGN_END) { 239a3e0fd82Sopenharmony_ci for (i = rowCount_ - 1; i > count; i--) { 240a3e0fd82Sopenharmony_ci offset += rowsMaxHeight[i]; 241a3e0fd82Sopenharmony_ci } 242a3e0fd82Sopenharmony_ci posY = GetHeight() - child->GetRelativeRect().GetHeight() - bottom - offset; 243a3e0fd82Sopenharmony_ci } else { 244a3e0fd82Sopenharmony_ci for (i = 0; i < rowCount_; i++) { 245a3e0fd82Sopenharmony_ci offset += rowsMaxHeight[i]; 246a3e0fd82Sopenharmony_ci } 247a3e0fd82Sopenharmony_ci offset = (rowsMaxHeight[0] - offset) / 2; // 2: half 248a3e0fd82Sopenharmony_ci for (i = 1; i <= count; i++) { 249a3e0fd82Sopenharmony_ci offset += (rowsMaxHeight[i - 1] + rowsMaxHeight[i]) / 2; // 2: half 250a3e0fd82Sopenharmony_ci } 251a3e0fd82Sopenharmony_ci posY = (GetHeight() - child->GetRelativeRect().GetHeight() - top - bottom) / 2 + top + offset; // 2: half 252a3e0fd82Sopenharmony_ci } 253a3e0fd82Sopenharmony_ci} 254a3e0fd82Sopenharmony_ci 255a3e0fd82Sopenharmony_civoid FlexLayout::LayoutHorizontal() 256a3e0fd82Sopenharmony_ci{ 257a3e0fd82Sopenharmony_ci UIView* child = childrenHead_; 258a3e0fd82Sopenharmony_ci int16_t interval = 0; 259a3e0fd82Sopenharmony_ci int16_t posX = 0; 260a3e0fd82Sopenharmony_ci int16_t posY = 0; 261a3e0fd82Sopenharmony_ci uint16_t count = 0; 262a3e0fd82Sopenharmony_ci uint16_t widthsBuf[MAX_COUNT_DEFAULT] = {0}; 263a3e0fd82Sopenharmony_ci uint16_t maxHeightsBuf[MAX_COUNT_DEFAULT] = {0}; 264a3e0fd82Sopenharmony_ci uint16_t childsNumBuf[MAX_COUNT_DEFAULT] = {0}; 265a3e0fd82Sopenharmony_ci uint16_t* rowsWidth = widthsBuf; 266a3e0fd82Sopenharmony_ci uint16_t* rowsMaxHeight = maxHeightsBuf; 267a3e0fd82Sopenharmony_ci uint16_t* rowsChildNum = childsNumBuf; 268a3e0fd82Sopenharmony_ci bool allocFlag = false; 269a3e0fd82Sopenharmony_ci 270a3e0fd82Sopenharmony_ci if (wrap_ == WRAP) { 271a3e0fd82Sopenharmony_ci CalRowCount(); 272a3e0fd82Sopenharmony_ci if (rowCount_ > MAX_COUNT_DEFAULT) { 273a3e0fd82Sopenharmony_ci rowsWidth = new uint16_t[rowCount_](); 274a3e0fd82Sopenharmony_ci rowsMaxHeight = new uint16_t[rowCount_](); 275a3e0fd82Sopenharmony_ci rowsChildNum = new uint16_t[rowCount_](); 276a3e0fd82Sopenharmony_ci allocFlag = true; 277a3e0fd82Sopenharmony_ci } 278a3e0fd82Sopenharmony_ci GetRowMaxHeight(rowCount_, rowsMaxHeight); 279a3e0fd82Sopenharmony_ci GetRowsWidth(rowCount_, rowsWidth, rowsChildNum); 280a3e0fd82Sopenharmony_ci GetRowStartPos(posX, interval, count, rowsWidth, rowsChildNum); 281a3e0fd82Sopenharmony_ci } else { 282a3e0fd82Sopenharmony_ci GetNoWrapStartPos(GetWidth(), posX, interval); 283a3e0fd82Sopenharmony_ci } 284a3e0fd82Sopenharmony_ci 285a3e0fd82Sopenharmony_ci while (child != nullptr) { 286a3e0fd82Sopenharmony_ci if (child->IsVisible()) { 287a3e0fd82Sopenharmony_ci int16_t left = child->GetStyle(STYLE_MARGIN_LEFT); 288a3e0fd82Sopenharmony_ci int16_t right = child->GetStyle(STYLE_MARGIN_RIGHT); 289a3e0fd82Sopenharmony_ci posX += left; 290a3e0fd82Sopenharmony_ci if (((posX + child->GetRelativeRect().GetWidth() + right) > GetWidth()) && (wrap_ == WRAP)) { 291a3e0fd82Sopenharmony_ci GetRowStartPos(posX, interval, ++count, rowsWidth, rowsChildNum); 292a3e0fd82Sopenharmony_ci posX += left; 293a3e0fd82Sopenharmony_ci } 294a3e0fd82Sopenharmony_ci 295a3e0fd82Sopenharmony_ci GetCrossAxisPosY(posY, count, rowsMaxHeight, child); 296a3e0fd82Sopenharmony_ci if (direction_ == LAYOUT_HOR_R) { 297a3e0fd82Sopenharmony_ci child->SetPosition(GetWidth() - posX - child->GetRelativeRect().GetWidth() - right, 298a3e0fd82Sopenharmony_ci posY - child->GetStyle(STYLE_MARGIN_TOP)); 299a3e0fd82Sopenharmony_ci } else { 300a3e0fd82Sopenharmony_ci child->SetPosition(posX - left, posY - child->GetStyle(STYLE_MARGIN_TOP)); 301a3e0fd82Sopenharmony_ci } 302a3e0fd82Sopenharmony_ci posX += child->GetRelativeRect().GetWidth() + right + interval; 303a3e0fd82Sopenharmony_ci child->LayoutChildren(); 304a3e0fd82Sopenharmony_ci } 305a3e0fd82Sopenharmony_ci child = child->GetNextSibling(); 306a3e0fd82Sopenharmony_ci } 307a3e0fd82Sopenharmony_ci 308a3e0fd82Sopenharmony_ci if (allocFlag) { 309a3e0fd82Sopenharmony_ci delete[] rowsWidth; 310a3e0fd82Sopenharmony_ci delete[] rowsMaxHeight; 311a3e0fd82Sopenharmony_ci delete[] rowsChildNum; 312a3e0fd82Sopenharmony_ci } 313a3e0fd82Sopenharmony_ci} 314a3e0fd82Sopenharmony_ci 315a3e0fd82Sopenharmony_civoid FlexLayout::CalColumnCount() 316a3e0fd82Sopenharmony_ci{ 317a3e0fd82Sopenharmony_ci UIView* child = childrenHead_; 318a3e0fd82Sopenharmony_ci int16_t pos = 0; 319a3e0fd82Sopenharmony_ci int16_t top; 320a3e0fd82Sopenharmony_ci int16_t bottom; 321a3e0fd82Sopenharmony_ci 322a3e0fd82Sopenharmony_ci columnCount_ = 1; 323a3e0fd82Sopenharmony_ci while (child != nullptr) { 324a3e0fd82Sopenharmony_ci if (child->IsVisible()) { 325a3e0fd82Sopenharmony_ci child->ReMeasure(); 326a3e0fd82Sopenharmony_ci top = child->GetStyle(STYLE_MARGIN_TOP); 327a3e0fd82Sopenharmony_ci bottom = child->GetStyle(STYLE_MARGIN_BOTTOM); 328a3e0fd82Sopenharmony_ci pos += top; 329a3e0fd82Sopenharmony_ci if ((pos + child->GetRelativeRect().GetHeight() + bottom) > GetHeight()) { 330a3e0fd82Sopenharmony_ci pos = top; 331a3e0fd82Sopenharmony_ci columnCount_++; 332a3e0fd82Sopenharmony_ci } 333a3e0fd82Sopenharmony_ci pos += child->GetRelativeRect().GetHeight() + bottom; 334a3e0fd82Sopenharmony_ci } 335a3e0fd82Sopenharmony_ci child = child->GetNextSibling(); 336a3e0fd82Sopenharmony_ci } 337a3e0fd82Sopenharmony_ci} 338a3e0fd82Sopenharmony_ci 339a3e0fd82Sopenharmony_civoid FlexLayout::GetColumnMaxWidth(uint16_t size, uint16_t* maxColumnsWidth) 340a3e0fd82Sopenharmony_ci{ 341a3e0fd82Sopenharmony_ci UIView* child = childrenHead_; 342a3e0fd82Sopenharmony_ci int16_t pos = 0; 343a3e0fd82Sopenharmony_ci int16_t left; 344a3e0fd82Sopenharmony_ci int16_t right; 345a3e0fd82Sopenharmony_ci int16_t bottom; 346a3e0fd82Sopenharmony_ci uint16_t i = 0; 347a3e0fd82Sopenharmony_ci uint16_t width = 0; 348a3e0fd82Sopenharmony_ci 349a3e0fd82Sopenharmony_ci if ((maxColumnsWidth == nullptr) || (size > columnCount_)) { 350a3e0fd82Sopenharmony_ci return; 351a3e0fd82Sopenharmony_ci } 352a3e0fd82Sopenharmony_ci 353a3e0fd82Sopenharmony_ci while (child != nullptr) { 354a3e0fd82Sopenharmony_ci if (child->IsVisible()) { 355a3e0fd82Sopenharmony_ci left = child->GetStyle(STYLE_MARGIN_LEFT); 356a3e0fd82Sopenharmony_ci right = child->GetStyle(STYLE_MARGIN_RIGHT); 357a3e0fd82Sopenharmony_ci bottom = child->GetStyle(STYLE_MARGIN_BOTTOM); 358a3e0fd82Sopenharmony_ci pos += left; 359a3e0fd82Sopenharmony_ci if ((pos + child->GetRelativeRect().GetHeight() + bottom) > GetHeight()) { 360a3e0fd82Sopenharmony_ci pos = left; 361a3e0fd82Sopenharmony_ci maxColumnsWidth[i] = width; 362a3e0fd82Sopenharmony_ci width = 0; 363a3e0fd82Sopenharmony_ci i++; 364a3e0fd82Sopenharmony_ci } 365a3e0fd82Sopenharmony_ci width = MATH_MAX(width, child->GetRelativeRect().GetWidth() + left + right); 366a3e0fd82Sopenharmony_ci maxColumnsWidth[i] = width; 367a3e0fd82Sopenharmony_ci pos += child->GetRelativeRect().GetHeight() + bottom; 368a3e0fd82Sopenharmony_ci } 369a3e0fd82Sopenharmony_ci child = child->GetNextSibling(); 370a3e0fd82Sopenharmony_ci } 371a3e0fd82Sopenharmony_ci} 372a3e0fd82Sopenharmony_ci 373a3e0fd82Sopenharmony_civoid FlexLayout::GetColumnsHeight(uint16_t columnNum, uint16_t* columnsHeight, uint16_t* columnsChildNum) 374a3e0fd82Sopenharmony_ci{ 375a3e0fd82Sopenharmony_ci UIView* child = childrenHead_; 376a3e0fd82Sopenharmony_ci int16_t pos = 0; 377a3e0fd82Sopenharmony_ci int16_t top; 378a3e0fd82Sopenharmony_ci int16_t bottom; 379a3e0fd82Sopenharmony_ci uint16_t columnChildNum = 0; 380a3e0fd82Sopenharmony_ci uint16_t columnCount = 0; 381a3e0fd82Sopenharmony_ci uint16_t height = 0; 382a3e0fd82Sopenharmony_ci 383a3e0fd82Sopenharmony_ci if ((columnsHeight == nullptr) || (columnsChildNum == nullptr) || (columnNum > columnCount_)) { 384a3e0fd82Sopenharmony_ci return; 385a3e0fd82Sopenharmony_ci } 386a3e0fd82Sopenharmony_ci 387a3e0fd82Sopenharmony_ci while (child != nullptr) { 388a3e0fd82Sopenharmony_ci if (child->IsVisible()) { 389a3e0fd82Sopenharmony_ci top = child->GetStyle(STYLE_MARGIN_TOP); 390a3e0fd82Sopenharmony_ci bottom = child->GetStyle(STYLE_MARGIN_BOTTOM); 391a3e0fd82Sopenharmony_ci pos += top; 392a3e0fd82Sopenharmony_ci if ((pos + child->GetRelativeRect().GetHeight() + bottom) > GetHeight()) { 393a3e0fd82Sopenharmony_ci pos = top; 394a3e0fd82Sopenharmony_ci columnsHeight[columnCount] = height; 395a3e0fd82Sopenharmony_ci height = 0; 396a3e0fd82Sopenharmony_ci columnsChildNum[columnCount] = columnChildNum; 397a3e0fd82Sopenharmony_ci columnChildNum = 0; 398a3e0fd82Sopenharmony_ci columnCount++; 399a3e0fd82Sopenharmony_ci } 400a3e0fd82Sopenharmony_ci height += child->GetRelativeRect().GetHeight() + top + bottom; 401a3e0fd82Sopenharmony_ci columnsHeight[columnCount] = height; 402a3e0fd82Sopenharmony_ci columnChildNum++; 403a3e0fd82Sopenharmony_ci columnsChildNum[columnCount] = columnChildNum; 404a3e0fd82Sopenharmony_ci pos += child->GetRelativeRect().GetHeight() + bottom; 405a3e0fd82Sopenharmony_ci } 406a3e0fd82Sopenharmony_ci child = child->GetNextSibling(); 407a3e0fd82Sopenharmony_ci } 408a3e0fd82Sopenharmony_ci} 409a3e0fd82Sopenharmony_ci 410a3e0fd82Sopenharmony_civoid FlexLayout::GetCrossAxisPosX(int16_t& posX, uint16_t& count, uint16_t* columnsMaxWidth, UIView* child) 411a3e0fd82Sopenharmony_ci{ 412a3e0fd82Sopenharmony_ci if ((columnsMaxWidth == nullptr) || (child == nullptr)) { 413a3e0fd82Sopenharmony_ci return; 414a3e0fd82Sopenharmony_ci } 415a3e0fd82Sopenharmony_ci 416a3e0fd82Sopenharmony_ci uint16_t i = 0; 417a3e0fd82Sopenharmony_ci uint16_t offset = 0; 418a3e0fd82Sopenharmony_ci int16_t left = child->GetStyle(STYLE_MARGIN_LEFT); 419a3e0fd82Sopenharmony_ci int16_t right = child->GetStyle(STYLE_MARGIN_RIGHT); 420a3e0fd82Sopenharmony_ci 421a3e0fd82Sopenharmony_ci if (secondaryAlign_ == ALIGN_START) { 422a3e0fd82Sopenharmony_ci for (i = 0; i < count; i++) { 423a3e0fd82Sopenharmony_ci offset += columnsMaxWidth[i]; 424a3e0fd82Sopenharmony_ci } 425a3e0fd82Sopenharmony_ci posX = left + offset; 426a3e0fd82Sopenharmony_ci } else if (secondaryAlign_ == ALIGN_END) { 427a3e0fd82Sopenharmony_ci for (i = columnCount_ - 1; i > count; i--) { 428a3e0fd82Sopenharmony_ci offset += columnsMaxWidth[i]; 429a3e0fd82Sopenharmony_ci } 430a3e0fd82Sopenharmony_ci posX = GetWidth() - child->GetRelativeRect().GetWidth() - right - offset; 431a3e0fd82Sopenharmony_ci } else { 432a3e0fd82Sopenharmony_ci for (i = 0; i < columnCount_; i++) { 433a3e0fd82Sopenharmony_ci offset += columnsMaxWidth[i]; 434a3e0fd82Sopenharmony_ci } 435a3e0fd82Sopenharmony_ci offset = (columnsMaxWidth[0] - offset) / 2; // 2: half 436a3e0fd82Sopenharmony_ci for (i = 1; i <= count; i++) { 437a3e0fd82Sopenharmony_ci offset += (columnsMaxWidth[i - 1] + columnsMaxWidth[i]) / 2; // 2: half 438a3e0fd82Sopenharmony_ci } 439a3e0fd82Sopenharmony_ci posX = (GetWidth() - child->GetRelativeRect().GetWidth() - left - right) / 2 + left + offset; // 2: half 440a3e0fd82Sopenharmony_ci } 441a3e0fd82Sopenharmony_ci} 442a3e0fd82Sopenharmony_ci 443a3e0fd82Sopenharmony_civoid FlexLayout::LayoutVertical() 444a3e0fd82Sopenharmony_ci{ 445a3e0fd82Sopenharmony_ci UIView* child = childrenHead_; 446a3e0fd82Sopenharmony_ci int16_t interval = 0; 447a3e0fd82Sopenharmony_ci int16_t posX = 0; 448a3e0fd82Sopenharmony_ci int16_t posY = 0; 449a3e0fd82Sopenharmony_ci uint16_t count = 0; 450a3e0fd82Sopenharmony_ci uint16_t heightsBuf[MAX_COUNT_DEFAULT] = {0}; 451a3e0fd82Sopenharmony_ci uint16_t maxWidthsBuf[MAX_COUNT_DEFAULT] = {0}; 452a3e0fd82Sopenharmony_ci uint16_t childsNumBuf[MAX_COUNT_DEFAULT] = {0}; 453a3e0fd82Sopenharmony_ci uint16_t* columnsHeight = heightsBuf; 454a3e0fd82Sopenharmony_ci uint16_t* columnsMaxWidth = maxWidthsBuf; 455a3e0fd82Sopenharmony_ci uint16_t* columnsChildNum = childsNumBuf; 456a3e0fd82Sopenharmony_ci bool allocFlag = false; 457a3e0fd82Sopenharmony_ci 458a3e0fd82Sopenharmony_ci if (wrap_ == WRAP) { 459a3e0fd82Sopenharmony_ci CalColumnCount(); 460a3e0fd82Sopenharmony_ci if (columnCount_ > MAX_COUNT_DEFAULT) { 461a3e0fd82Sopenharmony_ci columnsHeight = new uint16_t[columnCount_](); 462a3e0fd82Sopenharmony_ci columnsMaxWidth = new uint16_t[columnCount_](); 463a3e0fd82Sopenharmony_ci columnsChildNum = new uint16_t[columnCount_](); 464a3e0fd82Sopenharmony_ci allocFlag = true; 465a3e0fd82Sopenharmony_ci } 466a3e0fd82Sopenharmony_ci GetColumnMaxWidth(columnCount_, columnsMaxWidth); 467a3e0fd82Sopenharmony_ci GetColumnsHeight(columnCount_, columnsHeight, columnsChildNum); 468a3e0fd82Sopenharmony_ci GetColumnStartPos(posY, interval, count, columnsHeight, columnsChildNum); 469a3e0fd82Sopenharmony_ci } else { 470a3e0fd82Sopenharmony_ci GetNoWrapStartPos(GetHeight(), posY, interval); 471a3e0fd82Sopenharmony_ci } 472a3e0fd82Sopenharmony_ci 473a3e0fd82Sopenharmony_ci while (child != nullptr) { 474a3e0fd82Sopenharmony_ci if (child->IsVisible()) { 475a3e0fd82Sopenharmony_ci int16_t top = child->GetStyle(STYLE_MARGIN_TOP); 476a3e0fd82Sopenharmony_ci int16_t bottom = child->GetStyle(STYLE_MARGIN_BOTTOM); 477a3e0fd82Sopenharmony_ci posY += top; 478a3e0fd82Sopenharmony_ci if (((posY + child->GetRelativeRect().GetHeight() + bottom) > GetHeight()) && (wrap_ == WRAP)) { 479a3e0fd82Sopenharmony_ci GetColumnStartPos(posY, interval, ++count, columnsHeight, columnsChildNum); 480a3e0fd82Sopenharmony_ci posY += top; 481a3e0fd82Sopenharmony_ci } 482a3e0fd82Sopenharmony_ci 483a3e0fd82Sopenharmony_ci GetCrossAxisPosX(posX, count, columnsMaxWidth, child); 484a3e0fd82Sopenharmony_ci if (direction_ == LAYOUT_VER_R) { 485a3e0fd82Sopenharmony_ci child->SetPosition(posX - child->GetStyle(STYLE_MARGIN_LEFT), 486a3e0fd82Sopenharmony_ci GetHeight() - posY - child->GetRelativeRect().GetHeight() - bottom); 487a3e0fd82Sopenharmony_ci } else { 488a3e0fd82Sopenharmony_ci child->SetPosition(posX - child->GetStyle(STYLE_MARGIN_LEFT), posY - top); 489a3e0fd82Sopenharmony_ci } 490a3e0fd82Sopenharmony_ci posY += child->GetRelativeRect().GetHeight() + bottom + interval; 491a3e0fd82Sopenharmony_ci child->LayoutChildren(); 492a3e0fd82Sopenharmony_ci } 493a3e0fd82Sopenharmony_ci child = child->GetNextSibling(); 494a3e0fd82Sopenharmony_ci } 495a3e0fd82Sopenharmony_ci 496a3e0fd82Sopenharmony_ci if (allocFlag) { 497a3e0fd82Sopenharmony_ci delete[] columnsHeight; 498a3e0fd82Sopenharmony_ci delete[] columnsMaxWidth; 499a3e0fd82Sopenharmony_ci delete[] columnsChildNum; 500a3e0fd82Sopenharmony_ci } 501a3e0fd82Sopenharmony_ci} 502a3e0fd82Sopenharmony_ci} // namespace OHOS 503