From 76e5a830661314963b20dea174f0d159b80c587e Mon Sep 17 00:00:00 2001 From: Tianer Zhou Date: Wed, 31 Jan 2024 14:39:19 +0800 Subject: [PATCH 1/5] use -idx for tiles Signed-off-by: Tianer Zhou Change-Id: I8db05c2e3d91f9c5938a673d1cd3af43468bb2f5 --- .../grid/irregular/grid_irregular_filler.cpp | 36 +++++++++++++------ .../grid/irregular/grid_irregular_filler.h | 14 +++++++- .../irregular/grid_layout_range_solver.cpp | 17 +++++---- 3 files changed, 50 insertions(+), 17 deletions(-) diff --git a/frameworks/core/components_ng/pattern/grid/irregular/grid_irregular_filler.cpp b/frameworks/core/components_ng/pattern/grid/irregular/grid_irregular_filler.cpp index 0defd2227df..f7b3ea2a6b9 100644 --- a/frameworks/core/components_ng/pattern/grid/irregular/grid_irregular_filler.cpp +++ b/frameworks/core/components_ng/pattern/grid/irregular/grid_irregular_filler.cpp @@ -23,7 +23,7 @@ namespace OHOS::Ace::NG { GridIrregularFiller::GridIrregularFiller(GridLayoutInfo* info, LayoutWrapper* wrapper) : info_(info), wrapper_(wrapper) {} -void GridIrregularFiller::InitPos(int32_t lineIdx) +int32_t GridIrregularFiller::InitPos(int32_t lineIdx) { // to land on the first item after advancing once posX_ = -1; @@ -32,19 +32,19 @@ void GridIrregularFiller::InitPos(int32_t lineIdx) const auto& row = info_->gridMatrix_.find(lineIdx); if (row == info_->gridMatrix_.end()) { // implies empty matrix - return; + return -1; } - info_->endIndex_ = row->second.at(0) - 1; + return row->second.at(0) - 1; } bool GridIrregularFiller::IsFull(float len, float targetLen) { - return len > targetLen || info_->endIndex_ == wrapper_->GetTotalChildCount() - 1; + return len > targetLen || info_->endIndex_ == info_->childrenCount_ - 1; } float GridIrregularFiller::Fill(const FillParameters& params, int32_t startIdx) { - InitPos(startIdx); + info_->endIndex_ = InitPos(startIdx); float len = 0.0f; while (!IsFull(len, params.targetLen)) { int32_t prevRow = posY_; @@ -116,10 +116,10 @@ void GridIrregularFiller::FillOne() info_->gridMatrix_[row] = {}; } - // top left square should be set to [idx], the rest to -1 + // top left square should be set to [idx], the rest to -[idx] for (int32_t r = 0; r < size.rows; ++r) { for (int32_t c = 0; c < size.columns; ++c) { - info_->gridMatrix_[row + r][col + c] = -1; + info_->gridMatrix_[row + r][col + c] = -idx; } } @@ -172,6 +172,7 @@ void GridIrregularFiller::UpdateLength(float& len, int32_t prevRow, int32_t curR void GridIrregularFiller::MeasureItem(const FillParameters& params, int32_t col, int32_t row) { auto child = wrapper_->GetOrCreateChildByIndex(info_->endIndex_); + std::cout << "measure idx " << info_->endIndex_ << std::endl; auto props = AceType::DynamicCast(wrapper_->GetLayoutProperty()); auto constraint = props->CreateChildConstraint(); @@ -204,11 +205,11 @@ void GridIrregularFiller::MeasureItem(const FillParameters& params, int32_t col, void GridIrregularFiller::FillMatrixOnly(int32_t startingLine, int32_t targetIdx) { - if (targetIdx >= wrapper_->GetTotalChildCount() || targetIdx < info_->startIndex_) { + if (targetIdx >= info_->childrenCount_ || targetIdx < info_->startIndex_) { return; } - InitPos(startingLine); + info_->endIndex_ = InitPos(startingLine); while (info_->endIndex_ < targetIdx) { if (!FindNextItem(++info_->endIndex_)) { FillOne(); @@ -217,6 +218,17 @@ void GridIrregularFiller::FillMatrixOnly(int32_t startingLine, int32_t targetIdx info_->endMainLineIndex_ = posY_; } +int32_t GridIrregularFiller::FillMatrixByLine(int32_t startingLine, int32_t targetLine) +{ + int32_t idx = InitPos(startingLine); + while (posY_ < targetLine && idx < info_->childrenCount_ - 1) { + if (!FindNextItem(++idx)) { + FillOne(); + } + } + return idx; +} + float GridIrregularFiller::MeasureBackward(const FillParameters& params, int32_t jumpLineIdx) { float len = 0.0f; @@ -254,7 +266,11 @@ float GridIrregularFiller::MeasureBackward(const FillParameters& params, int32_t int32_t GridIrregularFiller::FindItemTopRow(int32_t row, int32_t col) const { - while (info_->gridMatrix_.at(row).at(col) == -1) { + if (info_->gridMatrix_.at(row).at(col) == 0) { + return 0; + } + + while (info_->gridMatrix_.at(row).at(col) < 0) { --row; } return row; diff --git a/frameworks/core/components_ng/pattern/grid/irregular/grid_irregular_filler.h b/frameworks/core/components_ng/pattern/grid/irregular/grid_irregular_filler.h index 256ac5b70cc..c3e6ed60c8d 100644 --- a/frameworks/core/components_ng/pattern/grid/irregular/grid_irregular_filler.h +++ b/frameworks/core/components_ng/pattern/grid/irregular/grid_irregular_filler.h @@ -69,6 +69,17 @@ public: */ void FillMatrixOnly(int32_t startingLine, int32_t targetIdx); + /** + * @brief Fills the gridMatrix in forward direction until the target line is reached. Measure isn't performed, + * and lineHeightMap_ isn't updated. + * + * @param startingLine The starting line index. + * @param targetLine The target GridItem index to fill. + * + * @return Last item index filled. + */ + int32_t FillMatrixByLine(int32_t startingLine, int32_t targetLine); + /** * @brief Measures the GridItems in the backward direction until the target length is filled. * @@ -109,8 +120,9 @@ private: * @brief Initializes the position of the filler in the grid to GridLayoutInfo::startIndex_. * * @param lineIdx The line index of the starting position. + * @return startIndex_ - 1, for initializing endIndex_ in Fill */ - void InitPos(int32_t lineIdx); + int32_t InitPos(int32_t lineIdx); /** * @brief Try to find the GridItem with target index in the grid matrix. diff --git a/frameworks/core/components_ng/pattern/grid/irregular/grid_layout_range_solver.cpp b/frameworks/core/components_ng/pattern/grid/irregular/grid_layout_range_solver.cpp index 0cc3699699c..4e8cda2bc06 100644 --- a/frameworks/core/components_ng/pattern/grid/irregular/grid_layout_range_solver.cpp +++ b/frameworks/core/components_ng/pattern/grid/irregular/grid_layout_range_solver.cpp @@ -105,7 +105,10 @@ std::pair GridLayoutRangeSolver::AddNextRows(float mainGap, int3 continue; } const auto& itemIdx = row.at(c); - if (itemIdx == -1) { + if (itemIdx < 0) { + continue; + } + if (itemIdx == 0 && (idx > 0 || c > 0)) { continue; } if (opts_->getSizeByIndex && irregulars.find(itemIdx) != irregulars.end()) { @@ -137,13 +140,12 @@ std::pair GridLayoutRangeSolver::SolveForwardForEndIdx(float m for (int r = idx; r >= 0; --r) { const auto& row = info_->gridMatrix_.at(r); for (auto it = row.rbegin(); it != row.rend(); ++it) { - if (it->second != -1) { + if (it->second > 0) { return { idx, it->second }; } } } - // should never reach here - return {}; + return { 0, 0 }; } Result GridLayoutRangeSolver::SolveBackward(float mainGap, float targetLen, int32_t idx) @@ -175,12 +177,15 @@ int32_t GridLayoutRangeSolver::CheckMultiRow(int32_t idx) } int32_t r = idx; - if (row.at(c) == -1) { + if (row.at(c) < 0) { // traverse upwards to find the first row occupied by this item - while (r > 0 && mat.at(r).at(c) == -1) { + while (r > 0 && mat.at(r).at(c) < 0) { --r; } rowCnt = std::max(rowCnt, idx - r + 1); + } else if (row.at(c) == 0) { + // Item 0 always start at [0, 0] + rowCnt = idx + 1; } // skip the columns occupied by this item -- Gitee From 6c2309b70ea866313da8815371533a77adbec8c8 Mon Sep 17 00:00:00 2001 From: Tianer Zhou Date: Wed, 31 Jan 2024 15:54:05 +0800 Subject: [PATCH 2/5] implement skipping Signed-off-by: Tianer Zhou Change-Id: I0b842dccc8c3e14991513c1c7e90a1dd73b6f86c --- .../pattern/grid/grid_layout_info.cpp | 74 ++++++++++------- .../pattern/grid/grid_layout_info.h | 29 +++---- .../grid_scroll_layout_algorithm.cpp | 6 +- .../grid/irregular/grid_irregular_filler.cpp | 11 +-- .../grid/irregular/grid_irregular_filler.h | 4 +- .../grid_irregular_layout_algorithm.cpp | 83 ++++++++++++++++--- .../grid_irregular_layout_algorithm.h | 36 +++++++- 7 files changed, 169 insertions(+), 74 deletions(-) diff --git a/frameworks/core/components_ng/pattern/grid/grid_layout_info.cpp b/frameworks/core/components_ng/pattern/grid/grid_layout_info.cpp index c88dc3a2eb4..60ed2c1df49 100644 --- a/frameworks/core/components_ng/pattern/grid/grid_layout_info.cpp +++ b/frameworks/core/components_ng/pattern/grid/grid_layout_info.cpp @@ -336,23 +336,6 @@ float GridLayoutInfo::GetCurrentLineHeight() const return 0.0f; } -void GridLayoutInfo::UpdateStartIdxToLastItem() -{ - // find last index in gridMatrix - for (auto line = gridMatrix_.rbegin(); line != gridMatrix_.rend(); ++line) { - const auto& row = line->second; - for (auto c = row.rbegin(); c != row.rend(); ++c) { - if (c->second != -1) { - startIndex_ = c->second; - startMainLineIndex_ = line->first; - return; - } - } - } - startIndex_ = 0; - startMainLineIndex_ = 0; -} - std::pair GridLayoutInfo::FindItemInRange(int32_t target) const { if (gridMatrix_.empty()) { @@ -488,8 +471,26 @@ bool GridLayoutInfo::GetGridItemAnimatePos(const GridLayoutInfo& currentGridLayo return true; } -decltype(GridLayoutInfo::gridMatrix_)::const_iterator GridLayoutInfo::FindInMatrix(int32_t index) const +namespace { +bool CheckRow(int32_t& maxV, const std::map& row, int32_t target) { + for (auto [_, item] : row) { + maxV = std::max(maxV, std::abs(item)); + if (item == target) { + return true; + } + } + return false; +} + +using iter = decltype(GridLayoutInfo::gridMatrix_)::const_iterator; +} // namespace + +iter GridLayoutInfo::FindInMatrix(int32_t index) const +{ + if (index == 0) { + return gridMatrix_.begin(); + } size_t count = gridMatrix_.size(); size_t step = 0; auto left = gridMatrix_.begin(); @@ -500,15 +501,12 @@ decltype(GridLayoutInfo::gridMatrix_)::const_iterator GridLayoutInfo::FindInMatr std::advance(it, step); // with irregular items, only the max index on each row is guaranteed to be in order. - int32_t maxV = 0; - for (auto [_, item] : it->second) { - maxV = std::max(maxV, item); - if (item == index) { - return it; - } + int32_t maxV = -1; + if (CheckRow(maxV, it->second, index)) { + return it; } - if (index < maxV) { + if (index <= maxV) { count = step; } else { // index on the right side of current row @@ -519,19 +517,33 @@ decltype(GridLayoutInfo::gridMatrix_)::const_iterator GridLayoutInfo::FindInMatr return gridMatrix_.end(); } -void GridLayoutInfo::ClearMapsToEnd(int32_t idx) +void GridLayoutInfo::ClearHeightsToEnd(int32_t idx) { - auto gridIt = gridMatrix_.lower_bound(idx); - gridMatrix_.erase(gridIt, gridMatrix_.end()); auto lineIt = lineHeightMap_.lower_bound(idx); lineHeightMap_.erase(lineIt, lineHeightMap_.end()); } -void GridLayoutInfo::ClearMapsFromStart(int32_t idx) +void GridLayoutInfo::ClearHeightsFromStart(int32_t idx) { - auto gridIt = gridMatrix_.lower_bound(idx); - gridMatrix_.erase(gridMatrix_.begin(), gridIt); auto lineIt = lineHeightMap_.lower_bound(idx); lineHeightMap_.erase(lineHeightMap_.begin(), lineIt); } + +void GridLayoutInfo::ClearMatrixToEnd(int32_t idx, int32_t lineIdx) +{ + auto it = gridMatrix_.find(lineIdx); + for (; it != gridMatrix_.end(); ++it) { + for (auto itemIt = it->second.begin(); itemIt != it->second.end();) { + if (std::abs(itemIt->second) < idx) { + ++itemIt; + continue; + } + itemIt = it->second.erase(itemIt); + } + if (it->second.empty()) { + break; + } + } + gridMatrix_.erase(it, gridMatrix_.end()); +} } // namespace OHOS::Ace::NG \ No newline at end of file diff --git a/frameworks/core/components_ng/pattern/grid/grid_layout_info.h b/frameworks/core/components_ng/pattern/grid/grid_layout_info.h index c8b98261ae3..404f226db62 100644 --- a/frameworks/core/components_ng/pattern/grid/grid_layout_info.h +++ b/frameworks/core/components_ng/pattern/grid/grid_layout_info.h @@ -38,13 +38,14 @@ constexpr float HALF = 0.5f; // Try not to add more variables in [GridLayoutInfo] because the more state variables, the more problematic and the // harder it is to maintain struct GridLayoutInfo { - float GetTotalHeightOfItemsInView(float mainGap) + float GetTotalHeightOfItemsInView(float mainGap) const { float lengthOfItemsInViewport = 0.0; for (auto i = startMainLineIndex_; i <= endMainLineIndex_; i++) { - if (GreatOrEqual(lineHeightMap_[i], 0)) { - lengthOfItemsInViewport += (lineHeightMap_[i] + mainGap); + if (lineHeightMap_.find(i) == lineHeightMap_.end()) { + continue; } + lengthOfItemsInViewport += (lineHeightMap_.at(i) + mainGap); } return lengthOfItemsInViewport - mainGap; } @@ -132,21 +133,11 @@ struct GridLayoutInfo { /** * @brief Perform a binary search to find item with [index] in the gridMatrix_. * - * Designed for old ScrollLayoutAlgorithm only, where tiles of large items are all filled with index. Correct answer - * not guaranteed for new GridIrregularLayout, where all except the top-left tile are filled with -1. - * * @param index target item index - * @return iterator to that item, or ::end() if not found. + * @return iterator to that item, or map::end if not found. */ std::map>::const_iterator FindInMatrix(int32_t index) const; - /** - * @brief Finds the index of the last item in the grid matrix, and update startIndex_ and startMainLineIndex_ to - * that last item. - * - */ - void UpdateStartIdxToLastItem(); - /** * @brief Tries to find the item between startMainLine and endMainLine. * @@ -156,18 +147,20 @@ struct GridLayoutInfo { std::pair FindItemInRange(int32_t target) const; /** - * @brief clears gridMatrix_ and lineHeightMap_ starting from line [idx] + * @brief clears lineHeightMap_ starting from line [idx] * * @param idx starting line index */ - void ClearMapsToEnd(int32_t idx); + void ClearHeightsToEnd(int32_t idx); /** - * @brief clears gridMatrix_ and lineHeightMap_ in range [0, idx) + * @brief clears lineHeightMap_ in range [0, idx) * * @param idx ending line index, exclusive. */ - void ClearMapsFromStart(int32_t idx); + void ClearHeightsFromStart(int32_t idx); + + void ClearMatrixToEnd(int32_t idx, int32_t lineIdx); void ResetPositionFlags() { diff --git a/frameworks/core/components_ng/pattern/grid/grid_scroll/grid_scroll_layout_algorithm.cpp b/frameworks/core/components_ng/pattern/grid/grid_scroll/grid_scroll_layout_algorithm.cpp index b7c4530257f..23606dcd155 100644 --- a/frameworks/core/components_ng/pattern/grid/grid_scroll/grid_scroll_layout_algorithm.cpp +++ b/frameworks/core/components_ng/pattern/grid/grid_scroll/grid_scroll_layout_algorithm.cpp @@ -1103,9 +1103,9 @@ bool GridScrollLayoutAlgorithm::UseCurrentLines( gridLayoutInfo_.offsetEnd_ = false; } if (!cacheValid) { - info.ClearMapsToEnd(info.endMainLineIndex_ + 1); - // run out of reord, startMainLineIndex is larger by 1 than real start main line index, so reduce 1 - info.ClearMapsFromStart(info.startMainLineIndex_ > info.endMainLineIndex_ ? info.startMainLineIndex_ - 1 + info.ClearHeightsToEnd(info.endMainLineIndex_ + 1); + // run out of record, startMainLineIndex is larger by 1 than real start main line index, so reduce 1 + info.ClearHeightsFromStart(info.startMainLineIndex_ > info.endMainLineIndex_ ? info.startMainLineIndex_ - 1 : info.startMainLineIndex_); } return runOutOfRecord; diff --git a/frameworks/core/components_ng/pattern/grid/irregular/grid_irregular_filler.cpp b/frameworks/core/components_ng/pattern/grid/irregular/grid_irregular_filler.cpp index f7b3ea2a6b9..3d79e82582e 100644 --- a/frameworks/core/components_ng/pattern/grid/irregular/grid_irregular_filler.cpp +++ b/frameworks/core/components_ng/pattern/grid/irregular/grid_irregular_filler.cpp @@ -49,7 +49,7 @@ float GridIrregularFiller::Fill(const FillParameters& params, int32_t startIdx) while (!IsFull(len, params.targetLen)) { int32_t prevRow = posY_; if (!FindNextItem(++info_->endIndex_)) { - FillOne(); + FillOne(info_->endIndex_); } if (posY_ > prevRow) { @@ -95,10 +95,8 @@ int32_t GridIrregularFiller::FitItem(const decltype(GridLayoutInfo::gridMatrix_) return -1; } -void GridIrregularFiller::FillOne() +void GridIrregularFiller::FillOne(const int32_t idx) { - /* alias */ - const int32_t& idx = info_->endIndex_; int32_t row = posY_; auto size = GridLayoutUtils::GetItemSize(info_, wrapper_, idx); @@ -172,7 +170,6 @@ void GridIrregularFiller::UpdateLength(float& len, int32_t prevRow, int32_t curR void GridIrregularFiller::MeasureItem(const FillParameters& params, int32_t col, int32_t row) { auto child = wrapper_->GetOrCreateChildByIndex(info_->endIndex_); - std::cout << "measure idx " << info_->endIndex_ << std::endl; auto props = AceType::DynamicCast(wrapper_->GetLayoutProperty()); auto constraint = props->CreateChildConstraint(); @@ -212,7 +209,7 @@ void GridIrregularFiller::FillMatrixOnly(int32_t startingLine, int32_t targetIdx info_->endIndex_ = InitPos(startingLine); while (info_->endIndex_ < targetIdx) { if (!FindNextItem(++info_->endIndex_)) { - FillOne(); + FillOne(info_->endIndex_); } } info_->endMainLineIndex_ = posY_; @@ -223,7 +220,7 @@ int32_t GridIrregularFiller::FillMatrixByLine(int32_t startingLine, int32_t targ int32_t idx = InitPos(startingLine); while (posY_ < targetLine && idx < info_->childrenCount_ - 1) { if (!FindNextItem(++idx)) { - FillOne(); + FillOne(idx); } } return idx; diff --git a/frameworks/core/components_ng/pattern/grid/irregular/grid_irregular_filler.h b/frameworks/core/components_ng/pattern/grid/irregular/grid_irregular_filler.h index c3e6ed60c8d..69da1bb22c1 100644 --- a/frameworks/core/components_ng/pattern/grid/irregular/grid_irregular_filler.h +++ b/frameworks/core/components_ng/pattern/grid/irregular/grid_irregular_filler.h @@ -94,8 +94,10 @@ public: private: /** * @brief Fills one GridItem into the Grid. + * + * @param idx Item index to fill in the matrix. */ - void FillOne(); + void FillOne(int32_t idx); /** * @brief Updates the length of the main axis after filling a row or column. Add heights in range [prevRow, curRow). diff --git a/frameworks/core/components_ng/pattern/grid/irregular/grid_irregular_layout_algorithm.cpp b/frameworks/core/components_ng/pattern/grid/irregular/grid_irregular_layout_algorithm.cpp index f4a4b37aaec..ddeff6d12d9 100644 --- a/frameworks/core/components_ng/pattern/grid/irregular/grid_irregular_layout_algorithm.cpp +++ b/frameworks/core/components_ng/pattern/grid/irregular/grid_irregular_layout_algorithm.cpp @@ -107,6 +107,9 @@ void GridIrregularLayoutAlgorithm::Init(const RefPtr& props) void GridIrregularLayoutAlgorithm::MeasureOnOffset(float mainSize) { auto& info = gridLayoutInfo_; + if (TrySkipping(mainSize)) { + return; + } GridLayoutRangeSolver solver(&info, wrapper_); auto res = solver.FindStartingRow(mainGap_); @@ -122,6 +125,24 @@ void GridIrregularLayoutAlgorithm::MeasureOnOffset(float mainSize) filler.Fill({ crossLens_, mainSize - res.pos, crossGap_, mainGap_ }, info.startMainLineIndex_); } +bool GridIrregularLayoutAlgorithm::TrySkipping(float mainSize) +{ + auto& info = gridLayoutInfo_; + float offset = std::abs(info.currentOffset_); + if (enableSkip_ && GreatNotEqual(offset, mainSize)) { + // a more costly check, therefore perform after comparing to [mainSize] + if (LessOrEqual(offset, info.GetTotalHeightOfItemsInView(mainGap_))) { + return false; + } + info.jumpIndex_ = (info.currentOffset_ < 0.0f) ? SkipLinesForward() : SkipLinesBackward(); + info.scrollAlign_ = ScrollAlign::START; + info.currentOffset_ = 0.0f; + MeasureOnJump(mainSize); + return true; + } + return false; +} + void GridIrregularLayoutAlgorithm::MeasureOnJump(float mainSize) { auto& info = gridLayoutInfo_; @@ -201,7 +222,10 @@ void GridIrregularLayoutAlgorithm::LayoutChildren(float mainOffset) for (int32_t r = info.startMainLineIndex_; r <= info.endMainLineIndex_; ++r) { const auto& row = info.gridMatrix_.at(r); for (int32_t c = 0; c < info.crossCount_; ++c) { - if (row.find(c) == row.end() || row.at(c) == -1) { + if (row.find(c) == row.end() || row.at(c) < 0) { + continue; + } + if (row.at(c) == 0 && (r > 0 || c > 0)) { continue; } auto child = wrapper_->GetOrCreateChildByIndex(row.at(c)); @@ -264,23 +288,14 @@ int32_t GridIrregularLayoutAlgorithm::FindJumpLineIdx(int32_t jumpIdx) if (jumpIdx >= info.startIndex_ && jumpIdx <= info.endIndex_) { return info.FindItemInRange(jumpIdx).first; } - if (jumpIdx > info.endIndex_) { + auto it = info.FindInMatrix(jumpIdx); + if (it == info.gridMatrix_.end()) { // fill matrix up to jumpIndex_ GridIrregularFiller filler(&info, wrapper_); - info.UpdateStartIdxToLastItem(); filler.FillMatrixOnly(jumpIdx, info.startMainLineIndex_); return info.endMainLineIndex_; } - // find jumpIdx above startMainLine - for (int r = info.startMainLineIndex_; r >= 0; --r) { - auto row = info.gridMatrix_.at(r); - for (auto it = row.rbegin(); it != row.rend(); ++it) { - if (it->second == jumpIdx) { - return r; - } - } - } - return -1; + return it->first; } void GridIrregularLayoutAlgorithm::PrepareLineHeight(float mainSize, int32_t& jumpLineIdx) @@ -335,4 +350,46 @@ void GridIrregularLayoutAlgorithm::PrepareLineHeight(float mainSize, int32_t& ju break; } } + +namespace { +void AddLineHeight(float& height, int32_t curLine, int32_t startLine, const std::map& lineHeights) +{ + if (lineHeights.find(curLine) != lineHeights.end()) { + height += lineHeights.at(curLine); + } else { + // estimation + height += height / std::abs(curLine - startLine); + } +} +} // namespace + +int32_t GridIrregularLayoutAlgorithm::SkipLinesForward() +{ + auto& info = gridLayoutInfo_; + int32_t idx = info.startMainLineIndex_; + float height = 0.0f; + while (LessNotEqual(height, -info.currentOffset_)) { + AddLineHeight(height, idx++, info.startMainLineIndex_, info.lineHeightMap_); + } + GridIrregularFiller filler(&info, wrapper_); + return filler.FillMatrixByLine(info.startMainLineIndex_, idx); +} + +int32_t GridIrregularLayoutAlgorithm::SkipLinesBackward() const +{ + const auto& info = gridLayoutInfo_; + float height = 0.0f; + for (int r = info.startMainLineIndex_; r <= info.endMainLineIndex_; ++r) { + height += info.lineHeightMap_.at(r); + } + float target = info.currentOffset_ + height; + int32_t idx = info.startMainLineIndex_; + while (LessNotEqual(height, target) && idx > 0) { + AddLineHeight(height, --idx, info.endMainLineIndex_, info.lineHeightMap_); + } + while (info.gridMatrix_.at(idx).begin()->second == -1) { + --idx; + } + return info.gridMatrix_.at(idx).begin()->second; +} } // namespace OHOS::Ace::NG diff --git a/frameworks/core/components_ng/pattern/grid/irregular/grid_irregular_layout_algorithm.h b/frameworks/core/components_ng/pattern/grid/irregular/grid_irregular_layout_algorithm.h index a93f2a7612e..bf6b8041590 100644 --- a/frameworks/core/components_ng/pattern/grid/irregular/grid_irregular_layout_algorithm.h +++ b/frameworks/core/components_ng/pattern/grid/irregular/grid_irregular_layout_algorithm.h @@ -23,6 +23,8 @@ /** * @brief GridIrregularLayout class supports irregular grid items that take multiple rows and multiple columns. + * + * INVARIANT: The gridMatrix_ is always filled from the first row up to endIndex_ at the beginning of each layout. */ namespace OHOS::Ace::NG { class GridIrregularLayoutAlgorithm : public GridLayoutBaseAlgorithm { @@ -38,6 +40,11 @@ public: void Layout(LayoutWrapper* layoutWrapper) override; + void SetEnableSkip(bool value) + { + enableSkip_ = value; + } + private: /** * @brief Measures the size of Grid based on the given GridLayoutProperty. @@ -54,7 +61,14 @@ private: void MeasureOnOffset(float mainSize); - void MeasureOnJump(float mainSize); + /** + * @brief Check if offset is larger than the entire viewport. If so, skip measuring intermediate items and jump + * directly to the estimated destination. + * + * @param mainSize main-axis length of the viewport. + * @return true if a skip is performed. + */ + bool TrySkipping(float mainSize); /** * @brief Performs the layout of the children based on the main offset. @@ -80,6 +94,9 @@ private: */ inline bool ReachedEnd() const; + // ========================================== MeasureOnJump functions ===================================== + + void MeasureOnJump(float mainSize); /** * @brief Transforms GridLayoutInfo::scrollAlign_ into other ScrollAlign values, based on current position of * jumpIdx_ item. @@ -108,6 +125,21 @@ private: * @param jumpLineIdx The line index to jump to, can be adjusted during the function call. */ void PrepareLineHeight(float mainSize, int32_t& jumpLineIdx); + // ========================================== MeasureOnJump ends =========================================== + + /** + * @brief Skip forward by currentOffset_ and fill the matrix along the way. + * + * @return item index to jump to after skipping. + */ + int32_t SkipLinesForward(); + + /** + * @brief Skip backward by currentOffset_. Can assume that the matrix is already filled up to startIdx_ + * + * @return item index to jump to after skipping. + */ + int32_t SkipLinesBackward() const; LayoutWrapper* wrapper_ = nullptr; @@ -115,6 +147,8 @@ private: float crossGap_ = 0.0f; /**< The cross-axis gap between GridItems. */ float mainGap_ = 0.0f; /**< The main-axis gap between GridItems. */ + bool enableSkip_ = true; + ACE_DISALLOW_COPY_AND_MOVE(GridIrregularLayoutAlgorithm); }; -- Gitee From a4d4af0e368948ece0998b59ed2e57a1edb79902 Mon Sep 17 00:00:00 2001 From: Tianer Zhou Date: Wed, 31 Jan 2024 15:54:10 +0800 Subject: [PATCH 3/5] restructure tests Signed-off-by: Tianer Zhou Change-Id: I035cf5b402876e06059862f30b64ab81e1f9a459 --- .../grid/irregular/grid_irregular_filler.cpp | 27 +- .../grid/irregular/grid_irregular_filler.h | 7 +- .../grid_irregular_layout_algorithm.cpp | 26 +- .../irregular/grid_layout_range_solver.cpp | 5 +- test/unittest/core/pattern/grid/BUILD.gn | 2 + .../grid/grid_irregular_layout_test.cpp | 1338 +++++++++++++++++ .../core/pattern/grid/grid_layout_test_ng.cpp | 1233 +-------------- .../core/pattern/grid/irregular_matrices.h | 154 ++ .../core/pattern/grid/irregular_matrics.cpp | 173 +++ .../core/pattern/grid/layout_info_test.cpp | 117 +- 10 files changed, 1737 insertions(+), 1345 deletions(-) create mode 100644 test/unittest/core/pattern/grid/grid_irregular_layout_test.cpp create mode 100644 test/unittest/core/pattern/grid/irregular_matrices.h create mode 100644 test/unittest/core/pattern/grid/irregular_matrics.cpp diff --git a/frameworks/core/components_ng/pattern/grid/irregular/grid_irregular_filler.cpp b/frameworks/core/components_ng/pattern/grid/irregular/grid_irregular_filler.cpp index 3d79e82582e..de2febf0e67 100644 --- a/frameworks/core/components_ng/pattern/grid/irregular/grid_irregular_filler.cpp +++ b/frameworks/core/components_ng/pattern/grid/irregular/grid_irregular_filler.cpp @@ -135,6 +135,17 @@ bool GridIrregularFiller::FindNextItem(int32_t target) return true; } } + // to handle empty tiles in the middle of matrix, check next row + auto nextRow = mat.find(posY_ + 1); + if (nextRow != mat.end()) { + for (const auto [col, item] : nextRow->second) { + if (item == target) { + ++posY_; + posX_ = col; + return true; + } + } + } return false; } @@ -200,19 +211,19 @@ void GridIrregularFiller::MeasureItem(const FillParameters& params, int32_t col, } } -void GridIrregularFiller::FillMatrixOnly(int32_t startingLine, int32_t targetIdx) +int32_t GridIrregularFiller::FillMatrixOnly(int32_t startingLine, int32_t targetIdx) { - if (targetIdx >= info_->childrenCount_ || targetIdx < info_->startIndex_) { - return; + if (targetIdx >= info_->childrenCount_) { + targetIdx = info_->childrenCount_ - 1; } - info_->endIndex_ = InitPos(startingLine); - while (info_->endIndex_ < targetIdx) { - if (!FindNextItem(++info_->endIndex_)) { - FillOne(info_->endIndex_); + int32_t idx = InitPos(startingLine); + while (idx < targetIdx) { + if (!FindNextItem(++idx)) { + FillOne(idx); } } - info_->endMainLineIndex_ = posY_; + return posY_; } int32_t GridIrregularFiller::FillMatrixByLine(int32_t startingLine, int32_t targetLine) diff --git a/frameworks/core/components_ng/pattern/grid/irregular/grid_irregular_filler.h b/frameworks/core/components_ng/pattern/grid/irregular/grid_irregular_filler.h index 69da1bb22c1..d22183ac262 100644 --- a/frameworks/core/components_ng/pattern/grid/irregular/grid_irregular_filler.h +++ b/frameworks/core/components_ng/pattern/grid/irregular/grid_irregular_filler.h @@ -61,13 +61,12 @@ public: * @brief Fills the gridMatrix in forward direction until the target GridItem is included. Measure isn't performed, * and lineHeightMap_ isn't updated. * - * EFFECT: updates GridLayoutInfo::endIndex_ to targetIdx and GridLayoutInfo::endMainLineIndex_ to the - * corresponding line index. - * * @param startingLine The starting line index. * @param targetIdx The target GridItem index to fill. + * + * @return Line index in which Item [targetIdx] resides. */ - void FillMatrixOnly(int32_t startingLine, int32_t targetIdx); + int32_t FillMatrixOnly(int32_t startingLine, int32_t targetIdx); /** * @brief Fills the gridMatrix in forward direction until the target line is reached. Measure isn't performed, diff --git a/frameworks/core/components_ng/pattern/grid/irregular/grid_irregular_layout_algorithm.cpp b/frameworks/core/components_ng/pattern/grid/irregular/grid_irregular_layout_algorithm.cpp index ddeff6d12d9..092bb7dbf8a 100644 --- a/frameworks/core/components_ng/pattern/grid/irregular/grid_irregular_layout_algorithm.cpp +++ b/frameworks/core/components_ng/pattern/grid/irregular/grid_irregular_layout_algorithm.cpp @@ -21,10 +21,10 @@ #include "core/components_ng/pattern/grid/grid_utils.h" #include "core/components_ng/pattern/grid/irregular/grid_irregular_filler.h" #include "core/components_ng/pattern/grid/irregular/grid_layout_range_solver.h" +#include "core/components_ng/pattern/grid/irregular/grid_layout_utils.h" #include "core/components_ng/pattern/scrollable/scrollable_utils.h" #include "core/components_ng/property/measure_property.h" #include "core/components_ng/property/templates_parser.h" -#include "core/components_ng/pattern/grid/irregular/grid_layout_utils.h" namespace OHOS::Ace::NG { void GridIrregularLayoutAlgorithm::Measure(LayoutWrapper* layoutWrapper) @@ -160,9 +160,6 @@ void GridIrregularLayoutAlgorithm::MeasureOnJump(float mainSize) } int32_t jumpLineIdx = FindJumpLineIdx(info.jumpIndex_); - - info.startMainLineIndex_ = jumpLineIdx; - info.startIndex_ = info.jumpIndex_; info.jumpIndex_ = EMPTY_JUMP_INDEX; PrepareLineHeight(mainSize, jumpLineIdx); @@ -172,7 +169,7 @@ void GridIrregularLayoutAlgorithm::MeasureOnJump(float mainSize) info.currentOffset_ = res.pos; info.startMainLineIndex_ = res.startRow; - info.startIndex_ = info.gridMatrix_[res.startRow][0]; + info.startIndex_ = info.gridMatrix_.at(res.startRow).at(0); info.endMainLineIndex_ = res.endRow; info.endIndex_ = res.endIdx; } @@ -285,17 +282,24 @@ ScrollAlign GridIrregularLayoutAlgorithm::TransformAutoScrollAlign(float mainSiz int32_t GridIrregularLayoutAlgorithm::FindJumpLineIdx(int32_t jumpIdx) { auto& info = gridLayoutInfo_; - if (jumpIdx >= info.startIndex_ && jumpIdx <= info.endIndex_) { - return info.FindItemInRange(jumpIdx).first; - } + int32_t jumpLine = -1; auto it = info.FindInMatrix(jumpIdx); if (it == info.gridMatrix_.end()) { // fill matrix up to jumpIndex_ GridIrregularFiller filler(&info, wrapper_); - filler.FillMatrixOnly(jumpIdx, info.startMainLineIndex_); - return info.endMainLineIndex_; + jumpLine = filler.FillMatrixOnly(info.startMainLineIndex_, jumpIdx); + } else { + jumpLine = it->first; + } + + if (info.scrollAlign_ == ScrollAlign::END) { + // jump to the last line the item occupies + auto lastLine = jumpLine + GridLayoutUtils::GetItemSize(&info, wrapper_, jumpIdx).rows - 1; + GridIrregularFiller filler(&info, wrapper_); + filler.FillMatrixByLine(jumpLine, lastLine + 1); + jumpLine = lastLine; } - return it->first; + return jumpLine; } void GridIrregularLayoutAlgorithm::PrepareLineHeight(float mainSize, int32_t& jumpLineIdx) diff --git a/frameworks/core/components_ng/pattern/grid/irregular/grid_layout_range_solver.cpp b/frameworks/core/components_ng/pattern/grid/irregular/grid_layout_range_solver.cpp index 4e8cda2bc06..dcafcaf63fe 100644 --- a/frameworks/core/components_ng/pattern/grid/irregular/grid_layout_range_solver.cpp +++ b/frameworks/core/components_ng/pattern/grid/irregular/grid_layout_range_solver.cpp @@ -66,10 +66,7 @@ GridLayoutRangeSolver::RangeInfo GridLayoutRangeSolver::FindRangeOnJump(int32_t int32_t endIdx = 0; const auto& lastRow = info_->gridMatrix_.at(jumpLineIdx); for (auto it = lastRow.rbegin(); it != lastRow.rend(); ++it) { - if (it->second != -1) { - endIdx = it->second; - break; - } + endIdx = std::max(endIdx, std::abs(it->second)); } return { res.row, res.pos, jumpLineIdx, endIdx }; } diff --git a/test/unittest/core/pattern/grid/BUILD.gn b/test/unittest/core/pattern/grid/BUILD.gn index 5d35f11fb0b..c1eea275a9e 100644 --- a/test/unittest/core/pattern/grid/BUILD.gn +++ b/test/unittest/core/pattern/grid/BUILD.gn @@ -21,9 +21,11 @@ ace_unittest("grid_test_ng") { "$ace_root/frameworks/bridge/js_frontend/engine/common/js_constants.cpp", "grid_attr_test_ng.cpp", "grid_common_test_ng.cpp", + "grid_irregular_layout_test.cpp", "grid_layout_test_ng.cpp", "grid_scroller_test_ng.cpp", "grid_test_ng.cpp", + "irregular_matrics.cpp", "layout_info_test.cpp", ] } diff --git a/test/unittest/core/pattern/grid/grid_irregular_layout_test.cpp b/test/unittest/core/pattern/grid/grid_irregular_layout_test.cpp new file mode 100644 index 00000000000..15508b00afb --- /dev/null +++ b/test/unittest/core/pattern/grid/grid_irregular_layout_test.cpp @@ -0,0 +1,1338 @@ +/* + * Copyright (c) 2024 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "grid_test_ng.h" +#include "irregular_matrices.h" + +#include "core/components/scroll/scroll_controller_base.h" +#include "core/components_ng/pattern/grid/grid_layout_info.h" +#include "core/components_ng/pattern/grid/irregular/grid_irregular_filler.h" +#include "core/components_ng/pattern/grid/irregular/grid_irregular_layout_algorithm.h" +#include "core/components_ng/pattern/grid/irregular/grid_layout_range_solver.h" + +namespace OHOS::Ace::NG { +class GridIrregularLayoutTest : public GridTestNg {}; + +/** + * @tc.name: IrregularFiller::AdvancePos001 + * @tc.desc: Test IrregularFiller::AdvancePos + * @tc.type: FUNC + */ +HWTEST_F(GridIrregularLayoutTest, AdvancePos001, TestSize.Level1) +{ + // empty matrix + GridLayoutInfo info; + info.crossCount_ = 2; + GridIrregularFiller filler(&info, nullptr); + EXPECT_FALSE(filler.AdvancePos()); + + filler.posX_ = 1; + filler.posY_ = 0; + EXPECT_FALSE(filler.AdvancePos()); + EXPECT_EQ(filler.posX_, 0); + EXPECT_EQ(filler.posY_, 1); + + // init matrix + info.gridMatrix_[0][0] = 1; + info.gridMatrix_[0][1] = -1; + info.gridMatrix_[1][0] = -1; + EXPECT_FALSE(filler.AdvancePos()); + EXPECT_EQ(filler.posX_, 1); + EXPECT_EQ(filler.posY_, 1); + + // reset pos and make [1][1] available + filler.posX_ = 0; + filler.posY_ = 1; + info.gridMatrix_[1][1] = -1; + EXPECT_TRUE(filler.AdvancePos()); +} + +/** + * @tc.name: IrregularFiller::FindNextItem001 + * @tc.desc: Test IrregularFiller::FindNextItem + * @tc.type: FUNC + */ +HWTEST_F(GridIrregularLayoutTest, FindNextItem001, TestSize.Level1) +{ + // empty matrix + GridLayoutInfo info; + info.crossCount_ = 2; + { + GridIrregularFiller filler(&info, nullptr); + + EXPECT_FALSE(filler.FindNextItem(0)); + } + + info.gridMatrix_[0][0] = 1; + info.gridMatrix_[0][1] = 2; + info.gridMatrix_[1][0] = 3; + info.gridMatrix_[1][1] = -1; + { + GridIrregularFiller filler(&info, nullptr); + + EXPECT_TRUE(filler.FindNextItem(1)); + EXPECT_EQ(filler.posX_, 0); + EXPECT_EQ(filler.posY_, 0); + + EXPECT_TRUE(filler.FindNextItem(2)); + EXPECT_EQ(filler.posX_, 1); + EXPECT_EQ(filler.posY_, 0); + + EXPECT_TRUE(filler.FindNextItem(3)); + EXPECT_EQ(filler.posX_, 0); + EXPECT_EQ(filler.posY_, 1); + + EXPECT_FALSE(filler.FindNextItem(4)); + } + + info.gridMatrix_[0][1] = -1; + info.gridMatrix_[1][0] = 2; + info.gridMatrix_[1].erase(1); + { + GridIrregularFiller filler(&info, nullptr); + + EXPECT_TRUE(filler.FindNextItem(1)); + EXPECT_EQ(filler.posX_, 0); + EXPECT_EQ(filler.posY_, 0); + + EXPECT_TRUE(filler.FindNextItem(2)); + EXPECT_EQ(filler.posX_, 0); + EXPECT_EQ(filler.posY_, 1); + + EXPECT_FALSE(filler.FindNextItem(3)); + EXPECT_EQ(filler.posX_, 1); + EXPECT_EQ(filler.posY_, 1); + } +} + +/** + * @tc.name: IrregularFiller::UpdateLength001 + * @tc.desc: Test IrregularFiller::UpdateLength + * @tc.type: FUNC + */ +HWTEST_F(GridIrregularLayoutTest, UpdateLength001, TestSize.Level1) +{ + GridLayoutInfo info; + info.lineHeightMap_[0] = 50.0f; + info.lineHeightMap_[1] = 30.0f; + + GridIrregularFiller filler(&info, nullptr); + float len = 0.0f; + filler.UpdateLength(len, 0, 2, 5.0f); + EXPECT_EQ(len, 85.0f); + + info.lineHeightMap_[2] = 50.0f; + filler.UpdateLength(len, 2, 3, 10.0f); + EXPECT_EQ(len, 85.0f + 50.0f + 10.0f); +} + +/** + * @tc.name: IrregularFiller::FillOne001 + * @tc.desc: Test IrregularFiller::FillOne + * @tc.type: FUNC + */ +HWTEST_F(GridIrregularLayoutTest, FillOne001, TestSize.Level1) +{ + GridLayoutOptions option; + option.irregularIndexes = { + 0, // [2 x 1] + 1, // [1 x 2] + 2 // [2 x 1] + }; + auto onGetIrregularSizeByIndex = [](int32_t index) -> GridItemSize { + if (index == 1) { + return { .rows = 2, .columns = 1 }; + } + return { .rows = 1, .columns = 2 }; + }; + + option.getSizeByIndex = std::move(onGetIrregularSizeByIndex); + Create([option](GridModelNG model) { + model.SetColumnsTemplate("1fr 1fr"); + model.SetLayoutOptions(option); + }); + + GridLayoutInfo info; + info.crossCount_ = 2; + GridIrregularFiller filler(&info, AceType::RawPtr(frameNode_)); + + filler.FillOne(0); + EXPECT_EQ(info.gridMatrix_.at(0).at(0), 0); + EXPECT_EQ(info.gridMatrix_.at(0).at(1), 0); + EXPECT_EQ(filler.posX_, 0); + EXPECT_EQ(filler.posY_, 0); + + filler.FillOne(1); + EXPECT_EQ(info.gridMatrix_.at(1).at(0), 1); + EXPECT_EQ(info.gridMatrix_.at(1).size(), 1); + EXPECT_EQ(info.gridMatrix_.at(2).at(0), -1); + EXPECT_EQ(info.gridMatrix_.at(2).size(), 1); + EXPECT_TRUE(info.gridMatrix_.find(3) == info.gridMatrix_.end()); + EXPECT_EQ(filler.posX_, 0); + EXPECT_EQ(filler.posY_, 1); + + filler.FillOne(2); + EXPECT_EQ(info.gridMatrix_.at(3).at(0), 2); + EXPECT_EQ(info.gridMatrix_.at(3).at(1), -2); + EXPECT_TRUE(info.gridMatrix_.find(4) == info.gridMatrix_.end()); + EXPECT_EQ(filler.posX_, 0); + EXPECT_EQ(filler.posY_, 3); +} + +/** + * @tc.name: IrregularFiller::FillOne002 + * @tc.desc: Test IrregularFiller::FillOne with 3 columns + * @tc.type: FUNC + */ +HWTEST_F(GridIrregularLayoutTest, FillOne002, TestSize.Level1) +{ + Create([](GridModelNG model) { + model.SetColumnsTemplate("1fr 1fr 1fr"); + model.SetLayoutOptions(GetOptionDemo10()); + }); + + GridLayoutInfo info; + info.crossCount_ = 3; + GridIrregularFiller filler(&info, AceType::RawPtr(frameNode_)); + + for (int i = 0; i < 8; ++i) { + filler.FillOne(i); + } + + EXPECT_EQ(info.gridMatrix_, MATRIX_DEMO_10); +} + +/** + * @tc.name: IrregularFiller::MeasureItem001 + * @tc.desc: Test IrregularFiller::MeasureItem + * @tc.type: FUNC + */ +HWTEST_F(GridIrregularLayoutTest, MeasureItem001, TestSize.Level1) +{ + GridLayoutOptions option; + option.irregularIndexes = { + 0, + }; + auto onGetIrregularSizeByIndex = [](int32_t index) -> GridItemSize { return { .columns = 1, .rows = 2 }; }; + option.getSizeByIndex = std::move(onGetIrregularSizeByIndex); + Create([option](GridModelNG model) { + model.SetColumnsTemplate("1fr 1fr 1fr 1fr"); + model.SetLayoutOptions(option); + CreateRowItem(10); + }); + + GridLayoutInfo info; + info.crossCount_ = 4; + GridIrregularFiller filler(&info, AceType::RawPtr(frameNode_)); + + info.endIndex_ = 0; + + GridIrregularFiller::FillParameters params { + .crossLens = { 50.0f, 50.0f, 100.0f, 100.0f }, .crossGap = 5.0f, .mainGap = 1.0f + }; + filler.MeasureItem(params, 0, 0); + + EXPECT_TRUE(info.lineHeightMap_.find(0) != info.lineHeightMap_.end()); + EXPECT_TRUE(info.lineHeightMap_.find(1) != info.lineHeightMap_.end()); + auto child = frameNode_->GetChildByIndex(0); + ASSERT_TRUE(child); + auto constraint = *child->GetGeometryNode()->GetParentLayoutConstraint(); + EXPECT_EQ(constraint.maxSize.Width(), 50.0f); + EXPECT_EQ(*constraint.selfIdealSize.Width(), 50.0f); + EXPECT_EQ(constraint.percentReference.Width(), 50.0f); +} + +/** + * @tc.name: IrregularFiller::MeasureItem002 + * @tc.desc: Test IrregularFiller::MeasureItem + * @tc.type: FUNC + */ +HWTEST_F(GridIrregularLayoutTest, MeasureItem002, TestSize.Level1) +{ + GridLayoutOptions option; + option.irregularIndexes = { + 0, + }; + Create([option](GridModelNG model) { + model.SetColumnsTemplate("1fr 1fr 1fr 1fr"); + model.SetLayoutOptions(option); + CreateRowItem(10); + }); + + GridLayoutInfo info; + info.crossCount_ = 4; + GridIrregularFiller filler(&info, AceType::RawPtr(frameNode_)); + + info.endIndex_ = 0; + filler.posY_ = 0; + + GridIrregularFiller::FillParameters params { + .crossLens = { 50.0f, 50.0f, 100.0f, 100.0f }, .crossGap = 5.0f, .mainGap = 1.0f + }; + filler.MeasureItem(params, 0, 0); + + EXPECT_TRUE(info.lineHeightMap_.find(0) != info.lineHeightMap_.end()); + EXPECT_TRUE(info.lineHeightMap_.find(1) == info.lineHeightMap_.end()); + auto child = frameNode_->GetChildByIndex(0); + ASSERT_TRUE(child); + auto constraint = *child->GetGeometryNode()->GetParentLayoutConstraint(); + EXPECT_EQ(constraint.maxSize.Width(), 315.0f); + EXPECT_EQ(*constraint.selfIdealSize.Width(), 315.0f); + EXPECT_EQ(constraint.percentReference.Width(), 315.0f); +} + +/** + * @tc.name: IrregularFiller::Fill001 + * @tc.desc: Test IrregularFiller::Fill + * @tc.type: FUNC + */ +HWTEST_F(GridIrregularLayoutTest, Fill001, TestSize.Level1) +{ + Create([](GridModelNG model) { + model.SetColumnsTemplate("1fr 1fr 1fr"); + model.SetLayoutOptions(GetOptionDemo9()); + CreateRowItem(10); + }); + + GridLayoutInfo info; + info.crossCount_ = 3; + info.childrenCount_ = 10; + GridIrregularFiller filler(&info, AceType::RawPtr(frameNode_)); + + float len = filler.Fill( + { .crossLens = { 50.0f, 50.0f, 100.0f }, .targetLen = 1000.0f, .crossGap = 5.0f, .mainGap = 1.0f }, 0); + + EXPECT_EQ(len, 6.0f); + + EXPECT_EQ(info.endIndex_, 9); + EXPECT_EQ(info.endMainLineIndex_, 6); + + EXPECT_EQ(info.gridMatrix_, MATRIX_DEMO_9); +} + +/** + * @tc.name: IrregularFiller::Fill002 + * @tc.desc: Test IrregularFiller::Fill + * @tc.type: FUNC + */ +HWTEST_F(GridIrregularLayoutTest, Fill002, TestSize.Level1) +{ + Create([](GridModelNG model) { + model.SetColumnsTemplate("1fr 1fr 1fr"); + model.SetLayoutOptions(GetOptionDemo11()); + CreateRowItem(10); + }); + + GridLayoutInfo info; + info.crossCount_ = 3; + info.childrenCount_ = 10; + GridIrregularFiller filler(&info, AceType::RawPtr(frameNode_)); + + float len = filler.Fill( + { .crossLens = { 50.0f, 50.0f, 100.0f }, .targetLen = 1000.0f, .crossGap = 5.0f, .mainGap = 1.0f }, 0); + + EXPECT_EQ(len, 6.0f); + + EXPECT_EQ(info.endIndex_, 9); + EXPECT_EQ(info.endMainLineIndex_, 6); + + EXPECT_EQ(info.gridMatrix_, MATRIX_DEMO_11); + + // call Fill on an already filled matrix + len = filler.Fill( + { .crossLens = { 50.0f, 50.0f, 100.0f }, .targetLen = 1000.0f, .crossGap = 5.0f, .mainGap = 1.0f }, 0); + + EXPECT_EQ(len, 6.0f); + + EXPECT_EQ(info.endIndex_, 9); + EXPECT_EQ(info.endMainLineIndex_, 6); + + EXPECT_EQ(info.gridMatrix_, MATRIX_DEMO_11); +} + +/** + * @tc.name: LayoutRangeSolver::AddNextRow001 + * @tc.desc: Test LayoutRangeSolver::AddNextRow + * @tc.type: FUNC + */ +HWTEST_F(GridIrregularLayoutTest, AddNextRow001, TestSize.Level1) +{ + GridLayoutOptions option; + option.irregularIndexes = { + 0, // [1 x 2] + 3, // [2 x 1] + }; + auto onGetIrregularSizeByIndex = [](int32_t index) -> GridItemSize { + if (index == 0) { + return { .rows = 2, .columns = 1 }; + } + return { .rows = 1, .columns = 2 }; + }; + + option.getSizeByIndex = std::move(onGetIrregularSizeByIndex); + Create([option](GridModelNG model) { + model.SetColumnsTemplate("1fr 1fr 1fr"); + model.SetLayoutOptions(option); + }); + + GridLayoutInfo info; + info.crossCount_ = 3; + info.gridMatrix_ = { + { 0, { { 0, 0 }, { 1, 1 }, { 2, 2 } } }, // 0 | 1 | 2 + { 1, { { 0, 0 }, { 1, 3 }, { 2, -3 } } }, // 0 | 3 | 3 + }; + info.lineHeightMap_ = { { 0, 50.0f }, { 1, 30.0f } }; + + GridLayoutRangeSolver solver(&info, AceType::RawPtr(frameNode_)); + auto res = solver.AddNextRows(5.0f, 0); + EXPECT_EQ(res.first, 2); + EXPECT_EQ(res.second, 80.0f + 5.0f); // top line doesn't have main gap +} + +/** + * @tc.name: LayoutRangeSolver::AddNextRows002 + * @tc.desc: Test LayoutRangeSolver::AddNextRows + * @tc.type: FUNC + */ +HWTEST_F(GridIrregularLayoutTest, AddNextRows002, TestSize.Level1) +{ + GridLayoutOptions option; + option.irregularIndexes = { + 0, // [1 x 3] + 3, // [2 x 1] + }; + auto onGetIrregularSizeByIndex = [](int32_t index) -> GridItemSize { + if (index == 0) { + return { .rows = 3, .columns = 1 }; + } + return { .rows = 1, .columns = 2 }; + }; + + option.getSizeByIndex = std::move(onGetIrregularSizeByIndex); + Create([option](GridModelNG model) { + model.SetColumnsTemplate("1fr 1fr 1fr"); + model.SetLayoutOptions(option); + }); + + GridLayoutInfo info; + info.crossCount_ = 3; + info.gridMatrix_ = { + { 0, { { 0, 0 }, { 0, 1 }, { 2, 2 } } }, // 0 | 1 | 2 + { 1, { { 0, 0 }, { 1, 3 }, { 2, -3 } } }, // 0 | 3 | 3 + { 2, { { 0, 0 } } }, // 0 | x | x + }; + info.lineHeightMap_ = { { 0, 50.0f }, { 1, 60.0f }, { 2, 40.0f } }; + + GridLayoutRangeSolver solver(&info, AceType::RawPtr(frameNode_)); + auto res = solver.AddNextRows(5.0f, 0); + EXPECT_EQ(res.first, 3); + EXPECT_EQ(res.second, 160.0f); + + // in real scenario, parameter rowIdx = 1 is impossible + res = solver.AddNextRows(5.0f, 1); + EXPECT_EQ(res.first, 1); + EXPECT_EQ(res.second, 65.0f); + + res = solver.AddNextRows(5.0f, 2); + EXPECT_EQ(res.first, 1); + EXPECT_EQ(res.second, 45.0f); +} + +/** + * @tc.name: LayoutRangeSolver::SolveForward001 + * @tc.desc: Test LayoutRangeSolver::SolveForward + * @tc.type: FUNC + */ +HWTEST_F(GridIrregularLayoutTest, SolveForward001, TestSize.Level1) +{ + Create([](GridModelNG model) { + model.SetColumnsTemplate("1fr 1fr 1fr"); + model.SetLayoutOptions(GetOptionDemo2()); + }); + + GridLayoutInfo info; + info.crossCount_ = 3; + info.gridMatrix_ = MATRIX_DEMO_2; + info.lineHeightMap_ = { { 0, 20.0f }, { 1, 40.0f }, { 2, 40.0f }, { 3, 10.0f }, { 4, 50.0f }, { 5, 70.0f } }; + + GridLayoutRangeSolver solver(&info, AceType::RawPtr(frameNode_)); + + info.currentOffset_ = 0.0f; + info.startMainLineIndex_ = 3; + auto res = solver.FindStartingRow(1.0f); + EXPECT_EQ(res.row, 3); + EXPECT_EQ(res.pos, 0.0f); + + info.currentOffset_ = -20.0f; + info.startMainLineIndex_ = 0; + res = solver.FindStartingRow(1.0f); + EXPECT_EQ(res.row, 0); + EXPECT_EQ(res.pos, -20.0f); + + info.currentOffset_ = -70.0f; + info.startMainLineIndex_ = 0; + res = solver.FindStartingRow(1.0f); + EXPECT_EQ(res.row, 0); + EXPECT_EQ(res.pos, -70.0f); + + // startMainLineIndex_ == 1 || startMainLineIndex_ == 2 is impossible. + // LayoutRangeSolver always finds the first row of irregular items. + + info.currentOffset_ = -11.0f; + info.startMainLineIndex_ = 3; + res = solver.FindStartingRow(1.0f); + EXPECT_EQ(res.row, 4); + EXPECT_EQ(res.pos, 0.0f); + + info.currentOffset_ = -10.0f; + info.startMainLineIndex_ = 3; + res = solver.FindStartingRow(1.0f); + EXPECT_EQ(res.row, 3); + EXPECT_EQ(res.pos, -10.0f); + + info.currentOffset_ = -110.0f; + info.startMainLineIndex_ = 3; + res = solver.FindStartingRow(1.0f); + EXPECT_EQ(res.row, 4); + EXPECT_EQ(res.pos, -99.0f); +} + +/** + * @tc.name: LayoutRangeSolver::CheckMultiRow001 + * @tc.desc: Test LayoutRangeSolver::CheckMultiRow + * @tc.type: FUNC + */ +HWTEST_F(GridIrregularLayoutTest, CheckMultiRow001, TestSize.Level1) +{ + GridLayoutOptions option; + option.irregularIndexes = { + 0, // [2 x 1] + 3, // [3 x 2] + }; + auto onGetIrregularSizeByIndex = [](int32_t index) -> GridItemSize { + if (index == 0) { + return { .rows = 1, .columns = 2 }; + } + return { .rows = 2, .columns = 3 }; + }; + + option.getSizeByIndex = std::move(onGetIrregularSizeByIndex); + Create([option](GridModelNG model) { + model.SetColumnsTemplate("1fr 1fr 1fr"); + model.SetLayoutOptions(option); + }); + + GridLayoutInfo info; + info.crossCount_ = 3; + info.gridMatrix_ = { + { 0, { { 0, 0 }, { 0, -1 }, { 2, 2 } } }, // 0 | 0 | 2 + { 1, { { 0, 3 }, { 1, -3 }, { 2, -3 } } }, // 3 | 3 | 3 + { 2, { { 0, -3 }, { 1, -3 }, { 2, -3 } } }, // 3 | 3 | 3 + }; + + GridLayoutRangeSolver solver(&info, AceType::RawPtr(frameNode_)); + EXPECT_EQ(solver.CheckMultiRow(2), 2); + + EXPECT_EQ(solver.CheckMultiRow(0), 1); + EXPECT_EQ(solver.CheckMultiRow(1), 1); +} + +/** + * @tc.name: LayoutRangeSolver::SolveBackward001 + * @tc.desc: Test LayoutRangeSolver::SolveBackward + * @tc.type: FUNC + */ +HWTEST_F(GridIrregularLayoutTest, SolveBackward001, TestSize.Level1) +{ + GridLayoutOptions option; + option.irregularIndexes = { + 0, // [2 x 1] + 3, // [2 x 2] + 4, // [1 x 2] + 6, // [2 x 1] + }; + auto onGetIrregularSizeByIndex = [](int32_t index) -> GridItemSize { + if (index == 4) { + return { .rows = 2, .columns = 1 }; + } + if (index == 3) { + return { 2, 2 }; + } + return { .rows = 1, .columns = 2 }; + }; + + option.getSizeByIndex = std::move(onGetIrregularSizeByIndex); + Create([option](GridModelNG model) { + model.SetColumnsTemplate("1fr 1fr 1fr"); + model.SetLayoutOptions(option); + }); + + GridLayoutInfo info; + info.crossCount_ = 3; + info.gridMatrix_ = { + { 0, { { 0, 0 }, { 0, 0 }, { 2, 1 } } }, // 0 | 0 | 1 + { 1, { { 0, 2 }, { 1, 3 }, { 2, -3 } } }, // 2 | 3 | 3 + { 2, { { 0, 4 }, { 1, -3 }, { 2, -3 } } }, // 4 | 3 | 3 + { 3, { { 0, -4 }, { 1, 5 } } }, // 4 | 5 | x + { 4, { { 0, 6 }, { 1, -6 }, { 2, 7 } } }, // 6 | 6 | 7 + }; + info.lineHeightMap_ = { { 0, 50.0f }, { 1, 30.0f }, { 2, 40.0f }, { 3, 30.0f }, { 4, 50.0f } }; + + info.currentOffset_ = 20.0f; + info.startMainLineIndex_ = 4; + + GridLayoutRangeSolver solver(&info, AceType::RawPtr(frameNode_)); + auto res = solver.FindStartingRow(5.0f); + EXPECT_EQ(res.pos, -60.0f); + EXPECT_EQ(res.row, 2); + + info.currentOffset_ = 80.0f; + info.startMainLineIndex_ = 4; + + res = solver.FindStartingRow(5.0f); + EXPECT_EQ(res.pos, -35.0f); + EXPECT_EQ(res.row, 1); + + info.currentOffset_ = 200.0f; + info.startMainLineIndex_ = 4; + + res = solver.FindStartingRow(5.0f); + EXPECT_EQ(res.pos, 30.0f); + EXPECT_EQ(res.row, 0); +} + +/** + * @tc.name: LayoutRangeSolver::Solve001 + * @tc.desc: Test LayoutRangeSolver::FindStartingRow when matrix is empty. + * @tc.type: FUNC + */ +HWTEST_F(GridIrregularLayoutTest, Solve001, TestSize.Level1) +{ + Create([](GridModelNG model) { + model.SetColumnsTemplate("1fr 1fr 1fr"); + model.SetLayoutOptions({}); + }); + + GridLayoutInfo info; + info.crossCount_ = 3; + + info.currentOffset_ = 0.0f; + info.startMainLineIndex_ = 0; + + GridLayoutRangeSolver solver(&info, AceType::RawPtr(frameNode_)); + auto res = solver.FindStartingRow(5.0f); + EXPECT_EQ(res.pos, 0.0f); + EXPECT_EQ(res.row, 0); +} + +/** + * @tc.name: GridIrregularLayout::LayoutChildren001 + * @tc.desc: Test GridIrregularLayout::LayoutChildren + * @tc.type: FUNC + */ +HWTEST_F(GridIrregularLayoutTest, LayoutChildren001, TestSize.Level1) +{ + Create([](GridModelNG model) { + model.SetColumnsTemplate("1fr 1fr 1fr"); + CreateRowItem(10); + }); + + frameNode_->GetGeometryNode()->UpdatePaddingWithBorder(PaddingPropertyF { .left = 5.0f, .top = 3.0f }); + + GridLayoutInfo info; + info.gridMatrix_ = { + { 0, { { 0, 0 }, { 0, 0 }, { 2, 1 } } }, // 0 | 0 | 1 + { 1, { { 0, 2 }, { 1, 3 }, { 2, 4 } } }, // 2 | 3 | 4 + { 2, { { 0, 5 }, { 1, 6 }, { 2, 7 } } }, // 5 | 6 | 7 + { 3, { { 0, 8 }, { 1, -8 } } }, // 8 | 8 | x + { 4, { { 0, 9 }, { 1, -9 } } }, // 9 | 9 | x + }; + info.lineHeightMap_ = { { 0, 20.0f }, { 1, 20.0f }, { 2, 10.0f }, { 3, 15.0f }, { 4, 30.0f } }; + info.crossCount_ = 3; + info.startMainLineIndex_ = 0; + info.endMainLineIndex_ = 4; + + auto algorithm = AceType::MakeRefPtr(info); + algorithm->wrapper_ = AceType::RawPtr(frameNode_); + algorithm->crossLens_ = { 50.0f, 50.0f, 100.0f }; + algorithm->crossGap_ = 5.0f; + algorithm->mainGap_ = 1.0f; + algorithm->LayoutChildren(0.0f); + + EXPECT_EQ(frameNode_->GetChildByIndex(0)->GetGeometryNode()->GetFrameOffset().GetX(), 5.0f); + EXPECT_EQ(frameNode_->GetChildByIndex(0)->GetGeometryNode()->GetFrameOffset().GetY(), 3.0f); + EXPECT_EQ(frameNode_->GetChildByIndex(1)->GetGeometryNode()->GetFrameOffset(), OffsetF(115.0f, 3.0f)); + EXPECT_EQ(frameNode_->GetChildByIndex(2)->GetGeometryNode()->GetFrameOffset(), OffsetF(5.0f, 24.0f)); + EXPECT_EQ(frameNode_->GetChildByIndex(3)->GetGeometryNode()->GetFrameOffset(), OffsetF(60.0f, 24.0f)); + EXPECT_EQ(frameNode_->GetChildByIndex(4)->GetGeometryNode()->GetFrameOffset(), OffsetF(115.0f, 24.0f)); + EXPECT_EQ(frameNode_->GetChildByIndex(5)->GetGeometryNode()->GetFrameOffset(), OffsetF(5.0f, 45.0f)); + EXPECT_EQ(frameNode_->GetChildByIndex(6)->GetGeometryNode()->GetFrameOffset(), OffsetF(60.0f, 45.0f)); + EXPECT_EQ(frameNode_->GetChildByIndex(7)->GetGeometryNode()->GetFrameOffset(), OffsetF(115.0f, 45.0f)); + EXPECT_EQ(frameNode_->GetChildByIndex(8)->GetGeometryNode()->GetFrameOffset(), OffsetF(5.0f, 56.0f)); + EXPECT_EQ(frameNode_->GetChildByIndex(9)->GetGeometryNode()->GetFrameOffset(), OffsetF(5.0f, 72.0f)); +} + +/** + * @tc.name: GridIrregularLayout::Measure001 + * @tc.desc: Test GridIrregularLayout::Measure with offset + * @tc.type: FUNC + */ +HWTEST_F(GridIrregularLayoutTest, Measure001, TestSize.Level1) +{ + Create([](GridModelNG model) { + model.SetColumnsTemplate("1fr 1fr 1fr"); + model.SetLayoutOptions(GetOptionDemo11()); + model.SetColumnsGap(Dimension { 5.0f }); + model.SetRowsGap(Dimension { 1.0f }); + CreateRowItem(10); + }); + LayoutConstraintF constraint { .maxSize = { 610.0f, 600.0f }, .percentReference = { 610.0f, 600.0f } }; + layoutProperty_->layoutConstraint_ = constraint; + + auto algorithm = AceType::MakeRefPtr(GridLayoutInfo {}); + algorithm->gridLayoutInfo_.currentOffset_ = 0.0f; + algorithm->gridLayoutInfo_.childrenCount_ = 10; + algorithm->Measure(AceType::RawPtr(frameNode_)); + + std::vector cmp = { 200.0f, 200.0f, 200.0f }; + EXPECT_EQ(frameNode_->GetGeometryNode()->GetFrameSize().Width(), 610.0f); + EXPECT_EQ(algorithm->crossLens_, cmp); + + const auto& info = algorithm->gridLayoutInfo_; + EXPECT_EQ(algorithm->mainGap_, 1.0f); + EXPECT_EQ(algorithm->crossGap_, 5.0f); + EXPECT_EQ(info.startMainLineIndex_, 0); + EXPECT_EQ(info.endMainLineIndex_, 6); + EXPECT_EQ(info.startIndex_, 0); + EXPECT_EQ(info.endIndex_, 9); + + EXPECT_EQ(info.gridMatrix_, MATRIX_DEMO_11); + + algorithm->gridLayoutInfo_.currentOffset_ = 5.0f; + algorithm->Measure(AceType::RawPtr(frameNode_)); + EXPECT_EQ(info.gridMatrix_, MATRIX_DEMO_11); + EXPECT_EQ(info.startMainLineIndex_, 0); + EXPECT_EQ(info.endMainLineIndex_, 6); + EXPECT_EQ(info.startIndex_, 0); + EXPECT_EQ(info.endIndex_, 9); +} + +/** + * @tc.name: GridIrregularLayout::MeasureJump001 + * @tc.desc: Test GridIrregularLayout::Measure with jump index + * @tc.type: FUNC + */ +HWTEST_F(GridIrregularLayoutTest, MeasureJump001, TestSize.Level1) +{ + Create([](GridModelNG model) { + model.SetColumnsTemplate("1fr 1fr 1fr"); + model.SetLayoutOptions(GetOptionDemo11()); + model.SetColumnsGap(Dimension { 5.0f }); + model.SetRowsGap(Dimension { 1.0f }); + CreateFixedItem(10); + }); + LayoutConstraintF constraint { .maxSize = { 610.0f, 600.0f }, .percentReference = { 610.0f, 600.0f } }; + layoutProperty_->layoutConstraint_ = constraint; + + auto algorithm = AceType::MakeRefPtr(GridLayoutInfo {}); + auto& info = algorithm->gridLayoutInfo_; + info.jumpIndex_ = 7; + info.scrollAlign_ = ScrollAlign::AUTO; + info.childrenCount_ = 10; + algorithm->Measure(AceType::RawPtr(frameNode_)); + + std::vector cmp = { 200.0f, 200.0f, 200.0f }; + EXPECT_EQ(frameNode_->GetGeometryNode()->GetFrameSize().Width(), 610.0f); + EXPECT_EQ(algorithm->crossLens_, cmp); + + EXPECT_EQ(algorithm->mainGap_, 1.0f); + EXPECT_EQ(algorithm->crossGap_, 5.0f); + + EXPECT_EQ(info.endMainLineIndex_, 6); + EXPECT_EQ(info.scrollAlign_, ScrollAlign::END); + EXPECT_EQ(info.jumpIndex_, EMPTY_JUMP_INDEX); + EXPECT_EQ(info.endIndex_, 9); + + EXPECT_EQ(info.gridMatrix_, MATRIX_DEMO_11); + + info.jumpIndex_ = 6; + info.scrollAlign_ = ScrollAlign::END; + algorithm->Measure(AceType::RawPtr(frameNode_)); + EXPECT_EQ(info.jumpIndex_, EMPTY_JUMP_INDEX); + EXPECT_EQ(info.scrollAlign_, ScrollAlign::END); + EXPECT_EQ(info.gridMatrix_, MATRIX_DEMO_11); + EXPECT_EQ(info.endMainLineIndex_, 5); + EXPECT_EQ(info.endIndex_, 6); +} + +/** + * @tc.name: GridIrregularLayout::Layout001 + * @tc.desc: Test GridIrregularLayout::Layout + * @tc.type: FUNC + */ +HWTEST_F(GridIrregularLayoutTest, Layout001, TestSize.Level1) +{ + Create([](GridModelNG model) { + model.SetColumnsTemplate("1fr 1fr 1fr"); + CreateRowItem(10); + }); + frameNode_->GetGeometryNode()->UpdatePaddingWithBorder(PaddingPropertyF { .left = 1.0f, .top = 1.0f }); + frameNode_->GetGeometryNode()->SetFrameSize(SizeF { 200.0f, 500.0f }); + + auto algorithm = AceType::MakeRefPtr(GridLayoutInfo {}); + algorithm->crossLens_ = { 50.0f, 50.0f, 50.0f }; + auto& info = algorithm->gridLayoutInfo_; + info.gridMatrix_ = { + { 0, { { 0, 0 }, { 1, 0 }, { 2, 0 } } }, // 0 | 0 | 0 + { 1, { { 0, 2 }, { 1, 3 }, { 2, 4 } } }, // 2 | 3 | 4 + { 2, { { 0, 5 }, { 1, 6 }, { 2, 7 } } }, // 5 | 6 | 7 + { 3, { { 0, 8 }, { 1, -6 }, { 2, 9 } } }, // 8 | 6 | 9 + }; + info.lineHeightMap_ = { { 0, 20.0f }, { 1, 20.0f }, { 2, 10.0f }, { 3, 15.0f } }; + info.childrenCount_ = 10; + info.crossCount_ = 3; + info.startMainLineIndex_ = 0; + info.endMainLineIndex_ = 3; + info.startIndex_ = 0; + info.endIndex_ = 9; + info.currentOffset_ = 10.0f; + algorithm->Layout(AceType::RawPtr(frameNode_)); + + EXPECT_TRUE(info.reachStart_); + EXPECT_TRUE(info.reachEnd_); + EXPECT_TRUE(info.offsetEnd_); +} + +/** + * @tc.name: GridIrregularLayout::FillMatrixOnly001 + * @tc.desc: Test GridIrregularFiller::FillMatrixOnly + * @tc.type: FUNC + */ +HWTEST_F(GridIrregularLayoutTest, FillMatrixOnly001, TestSize.Level1) +{ + Create([](GridModelNG model) { + model.SetColumnsTemplate("1fr 1fr 1fr"); + model.SetLayoutOptions(GetOptionDemo8()); + CreateColItem(7); + }); + + GridLayoutInfo info; + info.crossCount_ = 3; + // partially filled + info.gridMatrix_ = { + { 0, { { 0, 0 }, { 1, 0 }, { 2, 1 } } }, // 0 | 0 | 1 + }; + info.childrenCount_ = 7; + + GridIrregularFiller filler(&info, AceType::RawPtr(frameNode_)); + EXPECT_EQ(filler.FillMatrixOnly(0, 6), 4); + EXPECT_EQ(info.gridMatrix_, MATRIX_DEMO_8); +} + +/** + * @tc.name: GridIrregularLayout::MeasureBackward001 + * @tc.desc: Test GridIrregularFiller::MeasureBackward + * @tc.type: FUNC + */ +HWTEST_F(GridIrregularLayoutTest, MeasureBackward001, TestSize.Level1) +{ + GridLayoutInfo info; + info.gridMatrix_ = MATRIX_DEMO_8; + info.crossCount_ = 3; + + Create([](GridModelNG model) { + model.SetColumnsTemplate("1fr 1fr 1fr"); + model.SetLayoutOptions(GetOptionDemo8()); + CreateRowItem(10); + }); + + GridIrregularFiller filler(&info, AceType::RawPtr(frameNode_)); + float len = filler.MeasureBackward({ { 50.0f, 50.0f, 50.0f }, 1000.0f, 5.0f, 5.0f }, 5); + + EXPECT_EQ(len, 30.0f); + EXPECT_EQ(info.lineHeightMap_.size(), 6); +} + +/** + * @tc.name: GridIrregularLayout::FindJumpLineIndex001 + * @tc.desc: Test GridLayoutRangeFinder::FindJumpLineIndex + * @tc.type: FUNC + */ +HWTEST_F(GridIrregularLayoutTest, FindJumpLineIndex001, TestSize.Level1) +{ + Create([](GridModelNG model) { + model.SetColumnsTemplate("1fr 1fr 1fr"); + model.SetLayoutOptions(GetOptionDemo1()); + }); + + auto algo = AceType::MakeRefPtr(GridLayoutInfo {}); + algo->wrapper_ = AceType::RawPtr(frameNode_); + + auto& info = algo->gridLayoutInfo_; + info.childrenCount_ = 11; + info.crossCount_ = 3; + + info.scrollAlign_ = ScrollAlign::END; + EXPECT_EQ(algo->FindJumpLineIdx(5), 6); + EXPECT_EQ(info.gridMatrix_, MATRIX_DEMO_1); + + info.scrollAlign_ = ScrollAlign::CENTER; + EXPECT_EQ(algo->FindJumpLineIdx(5), 3); + EXPECT_EQ(info.gridMatrix_, MATRIX_DEMO_1); + + info.gridMatrix_.clear(); + info.scrollAlign_ = ScrollAlign::START; + EXPECT_EQ(algo->FindJumpLineIdx(10), 5); + EXPECT_EQ(info.gridMatrix_, MATRIX_DEMO_1); + + info.startIndex_ = 2; + info.endIndex_ = 7; + info.startMainLineIndex_ = 1; + info.endMainLineIndex_ = 4; + EXPECT_EQ(algo->FindJumpLineIdx(6), 3); + EXPECT_EQ(info.gridMatrix_, MATRIX_DEMO_1); +} + +/** + * @tc.name: GridIrregularLayout::FindRangeOnJump001 + * @tc.desc: Test GridLayoutRangeFinder::FindRangeOnJump + * @tc.type: FUNC + */ +HWTEST_F(GridIrregularLayoutTest, FindRangeOnJump001, TestSize.Level1) +{ + GridLayoutInfo info; + info.crossCount_ = 3; + info.lineHeightMap_ = { { 0, 50.0f }, { 1, 100.0f }, { 2, 50.0f }, { 3, 50.0f }, { 4, 80.0f }, { 5, 75.0f }, + { 6, 10.0f } }; + info.gridMatrix_ = MATRIX_DEMO_1; + + Create([](GridModelNG model) { + model.SetColumnsTemplate("1fr 1fr 1fr"); + model.SetLayoutOptions(GetOptionDemo1()); + }); + frameNode_->GetGeometryNode()->SetContentSize({ 500.0f, 250.0f }); + + GridLayoutRangeSolver solver(&info, AceType::RawPtr(frameNode_)); + + info.scrollAlign_ = ScrollAlign::START; + auto res = solver.FindRangeOnJump(2, 5.0f); + EXPECT_EQ(res.startRow, 0); + EXPECT_EQ(res.pos, -160.0f); + EXPECT_EQ(res.endIdx, 10); + EXPECT_EQ(res.endRow, 5); + + info.scrollAlign_ = ScrollAlign::CENTER; + res = solver.FindRangeOnJump(4, 5.0f); + EXPECT_EQ(res.startRow, 0); + EXPECT_EQ(res.pos, -185.0f); + EXPECT_EQ(res.endIdx, 10); + EXPECT_EQ(res.endRow, 5); + + info.scrollAlign_ = ScrollAlign::END; + res = solver.FindRangeOnJump(4, 5.0f); + EXPECT_EQ(res.startRow, 0); + EXPECT_EQ(res.pos, -100.0f); + EXPECT_EQ(res.endIdx, 8); + EXPECT_EQ(res.endRow, 4); +} + +/** + * @tc.name: GridIrregularLayout::SolveForwardForEndIdx001 + * @tc.desc: Test GridLayoutRangeFinder::SolveForwardForEndIdx + * @tc.type: FUNC + */ +HWTEST_F(GridIrregularLayoutTest, SolveForwardForEndIdx001, TestSize.Level1) +{ + GridLayoutInfo info; + info.lineHeightMap_ = { { 0, 50.0f }, { 1, 100.0f }, { 2, 50.0f }, { 3, 50.0f }, { 4, 80.0f } }; + info.gridMatrix_ = { + { 0, { { 0, 0 }, { 1, 0 }, { 2, 1 } } }, // 0 | 0 | 1 + { 1, { { 0, 2 }, { 1, -2 }, { 2, -2 } } }, // 2 | 2 | 2 + { 2, { { 0, -2 }, { 1, -2 }, { 2, -2 } } }, // 2 | 2 | 2 + { 3, { { 0, 3 }, { 1, 4 }, { 2, 5 } } }, // 3 | 4 | 5 + { 4, { { 0, 6 }, { 1, -6 }, { 2, -5 } } }, // 6 | 6 | 5 + }; + + Create([](GridModelNG model) { + model.SetColumnsTemplate("1fr 1fr 1fr"); + model.SetLayoutOptions({}); + }); + + GridLayoutRangeSolver solver(&info, AceType::RawPtr(frameNode_)); + auto [endLineIdx, endIdx] = solver.SolveForwardForEndIdx(5.0f, 250.0f, 1); + EXPECT_EQ(endIdx, 6); + EXPECT_EQ(endLineIdx, 4); +} + +namespace { +void CheckAlignStart(const RefPtr& algorithm, GridLayoutInfo& info) +{ + info.scrollAlign_ = ScrollAlign::START; + int32_t idx = 0; + algorithm->PrepareLineHeight(70.0f, idx); + EXPECT_EQ(info.scrollAlign_, ScrollAlign::START); + EXPECT_EQ(idx, 0); + + info.scrollAlign_ = ScrollAlign::START; + idx = 2; + algorithm->PrepareLineHeight(300.0f, idx); + EXPECT_EQ(info.scrollAlign_, ScrollAlign::START); + EXPECT_EQ(idx, 2); + + // can't align start with idx 4 + info.scrollAlign_ = ScrollAlign::START; + idx = 4; + algorithm->PrepareLineHeight(300.0f, idx); + EXPECT_EQ(info.scrollAlign_, ScrollAlign::END); + EXPECT_EQ(idx, 4); +} + +void CheckAlignCenter(const RefPtr& algorithm, GridLayoutInfo& info) +{ + // can't align center with idx 0 + info.scrollAlign_ = ScrollAlign::CENTER; + int32_t idx = 0; + algorithm->PrepareLineHeight(350.0f, idx); + EXPECT_EQ(info.scrollAlign_, ScrollAlign::START); + EXPECT_EQ(idx, 0); + + // can't align center with idx 4 + info.scrollAlign_ = ScrollAlign::CENTER; + idx = 4; + algorithm->PrepareLineHeight(350.0f, idx); + EXPECT_EQ(info.scrollAlign_, ScrollAlign::END); + EXPECT_EQ(idx, 4); + + // align center with idx 4 and len 30.0f + info.scrollAlign_ = ScrollAlign::CENTER; + idx = 4; + algorithm->PrepareLineHeight(30.0f, idx); + EXPECT_EQ(info.scrollAlign_, ScrollAlign::CENTER); + EXPECT_EQ(idx, 4); +} + +void CheckAlignEnd(const RefPtr& algorithm, GridLayoutInfo& info) +{ + // can't align end with idx 1 and len 200.0f + info.scrollAlign_ = ScrollAlign::END; + int32_t idx = 1; + algorithm->PrepareLineHeight(500.0f, idx); + EXPECT_EQ(info.scrollAlign_, ScrollAlign::START); + EXPECT_EQ(idx, 0); + + info.scrollAlign_ = ScrollAlign::END; + idx = 3; + algorithm->PrepareLineHeight(300.0f, idx); + EXPECT_EQ(info.scrollAlign_, ScrollAlign::END); + EXPECT_EQ(idx, 3); + + info.scrollAlign_ = ScrollAlign::END; + idx = 4; + algorithm->PrepareLineHeight(1000.0f, idx); + EXPECT_EQ(info.scrollAlign_, ScrollAlign::END); + EXPECT_EQ(idx, 4); + + // can't align end with len 340 + info.scrollAlign_ = ScrollAlign::END; + idx = 4; + algorithm->PrepareLineHeight(1040.0f, idx); + EXPECT_EQ(info.scrollAlign_, ScrollAlign::START); + EXPECT_EQ(idx, 0); +} +} // namespace + +/** + * @tc.name: GridIrregularLayout::PrepareLineHeights001 + * @tc.desc: Test GridIrregularLayout::PrepareLineHeights001 + * @tc.type: FUNC + */ +HWTEST_F(GridIrregularLayoutTest, PrepareLineHeights001, TestSize.Level1) +{ + Create([](GridModelNG model) { + model.SetColumnsTemplate("1fr 1fr 1fr"); + model.SetLayoutOptions({}); + CreateColItem(15); + }); + + auto algorithm = AceType::MakeRefPtr(GridLayoutInfo {}); + algorithm->wrapper_ = AceType::RawPtr(frameNode_); + algorithm->crossLens_ = { 1.0f, 1.0f, 1.0f }; + auto& info = algorithm->gridLayoutInfo_; + // because measuring children might not generate proper heights in test, we set them manually. + decltype(info.lineHeightMap_) cmpH = { { 0, 200.0f }, { 1, 200.0f }, { 2, 200.0f }, { 3, 200.0f }, { 4, 200.0f } }; + info.lineHeightMap_ = cmpH; + decltype(info.gridMatrix_) cmp = { + { 0, { { 0, 0 }, { 1, 1 }, { 2, 2 } } }, + { 1, { { 0, 3 }, { 1, 4 }, { 2, 5 } } }, + { 2, { { 0, 6 }, { 1, 7 }, { 2, 8 } } }, + { 3, { { 0, 9 }, { 1, 10 }, { 2, 11 } } }, + { 4, { { 0, 12 }, { 1, 13 }, { 2, 14 } } }, + }; + info.gridMatrix_ = cmp; + + info.crossCount_ = 3; + info.childrenCount_ = 15; + + CheckAlignStart(algorithm, info); + CheckAlignCenter(algorithm, info); + CheckAlignEnd(algorithm, info); + + EXPECT_EQ(cmp, info.gridMatrix_); + EXPECT_EQ(cmpH, info.lineHeightMap_); +} + +/** + * @tc.name: GridIrregularLayout::SkipLines001 + * @tc.desc: Test GridIrregularLayout::SkipLines001 + * @tc.type: FUNC + */ +HWTEST_F(GridIrregularLayoutTest, SkipLines001, TestSize.Level1) +{ + Create([](GridModelNG model) { + model.SetColumnsTemplate("1fr 1fr 1fr"); + model.SetLayoutOptions(GetOptionDemo1()); + }); + + auto algorithm = AceType::MakeRefPtr(GridLayoutInfo {}); + algorithm->wrapper_ = AceType::RawPtr(frameNode_); + + auto& info = algorithm->gridLayoutInfo_; + info.crossCount_ = 3; + info.lineHeightMap_ = { { 0, 200.0f }, { 1, 200.0f }, { 2, 200.0f } }; + info.gridMatrix_ = MATRIX_DEMO_1; + info.childrenCount_ = 11; + + info.currentOffset_ = -500.0f; + EXPECT_EQ(algorithm->SkipLinesForward(), 5); + info.currentOffset_ = -900.0f; + EXPECT_EQ(algorithm->SkipLinesForward(), 9); + info.currentOffset_ = -1500.0f; + EXPECT_EQ(algorithm->SkipLinesForward(), 10); + + info.lineHeightMap_ = { { 3, 200.0f }, { 4, 200.0f } }; + info.startIndex_ = 5; + info.startMainLineIndex_ = 3; + info.endMainLineIndex_ = 4; + + info.currentOffset_ = 400.0f; + EXPECT_EQ(algorithm->SkipLinesBackward(), 2); + + info.currentOffset_ = 800.0f; + EXPECT_EQ(algorithm->SkipLinesBackward(), 0); + + info.currentOffset_ = 1500.0f; + EXPECT_EQ(algorithm->SkipLinesBackward(), 0); +} + +/** + * @tc.name: GridIrregularLayout::TrySkipping001 + * @tc.desc: Test GridIrregularLayout::TrySkipping001 + * @tc.type: FUNC + */ +HWTEST_F(GridIrregularLayoutTest, TrySkipping001, TestSize.Level1) +{ + Create([](GridModelNG model) { + model.SetColumnsTemplate("1fr 1fr 1fr"); + model.SetLayoutOptions(GetOptionDemo2()); + CreateFixedItem(8); + }); + + auto algorithm = AceType::MakeRefPtr(GridLayoutInfo {}); + algorithm->wrapper_ = AceType::RawPtr(frameNode_); + algorithm->crossLens_ = { 200.0f, 200.0f, 200.0f }; + + auto& info = algorithm->gridLayoutInfo_; + info.crossCount_ = 3; + info.childrenCount_ = 8; + + info.lineHeightMap_ = { { 0, 200.0f }, { 1, 200.0f }, { 2, 200.0f } }; + info.gridMatrix_ = MATRIX_DEMO_2; + info.startMainLineIndex_ = 0; + info.endMainLineIndex_ = 1; + info.startIndex_ = 0; + info.endIndex_ = 1; + + info.currentOffset_ = -50.0f; + EXPECT_FALSE(algorithm->TrySkipping(300.0f)); + info.currentOffset_ = -300.0f; + EXPECT_FALSE(algorithm->TrySkipping(300.0f)); + info.currentOffset_ = -400.0f; + EXPECT_FALSE(algorithm->TrySkipping(300.0f)); + info.currentOffset_ = -401.0f; + EXPECT_TRUE(algorithm->TrySkipping(300.0f)); + EXPECT_EQ(info.startIndex_, 4); + EXPECT_EQ(info.scrollAlign_, ScrollAlign::START); + + info.scrollAlign_ = ScrollAlign::NONE; + info.lineHeightMap_ = { { 3, 200.0f }, { 4, 200.0f } }; + info.startMainLineIndex_ = 3; + info.endMainLineIndex_ = 4; + info.startIndex_ = 4; + info.endIndex_ = 7; + + info.currentOffset_ = 50.0f; + EXPECT_FALSE(algorithm->TrySkipping(300.0f)); + info.currentOffset_ = 300.0f; + EXPECT_FALSE(algorithm->TrySkipping(300.0f)); + info.currentOffset_ = 400.0f; + EXPECT_FALSE(algorithm->TrySkipping(300.0f)); + info.currentOffset_ = 401.0f; + EXPECT_TRUE(algorithm->TrySkipping(300.0f)); + EXPECT_EQ(info.startIndex_, 0); + EXPECT_EQ(info.scrollAlign_, ScrollAlign::START); +} + +/** + * @tc.name: GridIrregularFiller::FillMatrixByLine001 + * @tc.desc: Test GridIrregularFiller::FillMatrixByLine + * @tc.type: FUNC + */ +HWTEST_F(GridIrregularLayoutTest, FillMatrixByLine001, TestSize.Level1) +{ + Create([](GridModelNG model) { + model.SetColumnsTemplate("1fr 1fr 1fr"); + model.SetLayoutOptions(GetOptionDemo2()); + CreateFixedItem(8); + }); + + GridLayoutInfo info; + info.crossCount_ = 3; + info.childrenCount_ = 8; + info.gridMatrix_ = MATRIX_DEMO_2; + info.startMainLineIndex_ = 0; + info.endMainLineIndex_ = 1; + info.startIndex_ = 0; + info.endIndex_ = 1; + + GridIrregularFiller filler(&info, AceType::RawPtr(frameNode_)); + int32_t idx = filler.FillMatrixByLine(0, 3); + EXPECT_EQ(idx, 4); + + idx = filler.FillMatrixByLine(0, 10); + EXPECT_EQ(idx, 7); + + info.gridMatrix_.clear(); + idx = filler.FillMatrixByLine(0, 3); + EXPECT_EQ(idx, 4); + idx = filler.FillMatrixByLine(2, 5); + EXPECT_EQ(idx, 7); + + info.gridMatrix_.clear(); + idx = filler.FillMatrixByLine(0, 10); + EXPECT_EQ(idx, 7); + EXPECT_EQ(info.gridMatrix_, MATRIX_DEMO_2); +} + +/** + * @tc.name: GridIrregularLayout::TransformAutoScrollAlign001 + * @tc.desc: Test IrregularLayout::TransformAutoScrollAlign + * @tc.type: FUNC + */ +HWTEST_F(GridIrregularLayoutTest, TransformAutoScrollAlign001, TestSize.Level1) +{ + Create([](GridModelNG model) { + model.SetColumnsTemplate("1fr 1fr 1fr"); + model.SetLayoutOptions(GetOptionDemo8()); + }); + + auto algo = AceType::MakeRefPtr(GridLayoutInfo {}); + algo->wrapper_ = AceType::RawPtr(frameNode_); + + auto& info = algo->gridLayoutInfo_; + info.lineHeightMap_ = { { 0, 50.0f }, { 1, 300.0f }, { 2, 30.0f }, { 3, 50.0f }, { 4, 80.0f } }; + info.gridMatrix_ = MATRIX_DEMO_8; + algo->mainGap_ = 5.0f; + + info.jumpIndex_ = 2; + info.startMainLineIndex_ = 0; + info.endMainLineIndex_ = 4; + info.startIndex_ = 0; + info.endIndex_ = 6; + EXPECT_EQ(algo->TransformAutoScrollAlign(500.0f), ScrollAlign::NONE); + + info.jumpIndex_ = 0; + info.startMainLineIndex_ = 3; + info.endMainLineIndex_ = 4; + info.startIndex_ = 3; + info.endIndex_ = 6; + info.currentOffset_ = -10.0f; + EXPECT_EQ(algo->TransformAutoScrollAlign(100.0f), ScrollAlign::START); + + info.jumpIndex_ = 2; + info.startMainLineIndex_ = 1; + info.endMainLineIndex_ = 2; + info.startIndex_ = 2; + info.endIndex_ = 2; + info.currentOffset_ = -25.0f; + EXPECT_EQ(algo->TransformAutoScrollAlign(310.0f), ScrollAlign::NONE); +} + +/** + * @tc.name: GridIrregularLayout::TransformAutoScrollAlign002 + * @tc.desc: Test IrregularLayout::TransformAutoScrollAlign + * @tc.type: FUNC + */ +HWTEST_F(GridIrregularLayoutTest, TransformAutoScrollAlign002, TestSize.Level1) +{ + Create([](GridModelNG model) { + model.SetColumnsTemplate("1fr 1fr 1fr"); + model.SetLayoutOptions(GetOptionDemo8()); + }); + + auto algo = AceType::MakeRefPtr(GridLayoutInfo {}); + algo->wrapper_ = AceType::RawPtr(frameNode_); + + auto& info = algo->gridLayoutInfo_; + info.lineHeightMap_ = { { 0, 50.0f }, { 1, 300.0f }, { 2, 30.0f }, { 3, 50.0f }, { 4, 80.0f } }; + info.gridMatrix_ = MATRIX_DEMO_8; + algo->mainGap_ = 5.0f; + + // line 3 now matches with the end of the viewport, should endMainlineIndex_ be updated to 3? + info.currentOffset_ = -30.0f; + info.endMainLineIndex_ = 3; + info.endIndex_ = 5; + EXPECT_EQ(algo->TransformAutoScrollAlign(310.0f), ScrollAlign::START); + info.currentOffset_ = -31.0f; + EXPECT_EQ(algo->TransformAutoScrollAlign(310.0f), ScrollAlign::START); + + info.jumpIndex_ = 0; + info.startMainLineIndex_ = 3; + info.endMainLineIndex_ = 4; + info.startIndex_ = 3; + info.endIndex_ = 6; + EXPECT_EQ(algo->TransformAutoScrollAlign(100.0f), ScrollAlign::START); + + info.jumpIndex_ = 4; + info.startMainLineIndex_ = 1; + info.endMainLineIndex_ = 4; + info.startIndex_ = 2; + info.endIndex_ = 6; + + info.currentOffset_ = -379.0f; + algo->mainGap_ = 50.0f; + EXPECT_EQ(algo->TransformAutoScrollAlign(152.0f), ScrollAlign::NONE); + + algo->mainGap_ = 5.0f; + // emulate init + info.lineHeightMap_.clear(); + info.gridMatrix_.clear(); + info.jumpIndex_ = 3; + info.startMainLineIndex_ = 0; + info.endMainLineIndex_ = 0; + info.startIndex_ = 0; + info.endIndex_ = -1; + EXPECT_EQ(algo->TransformAutoScrollAlign(300.0f), ScrollAlign::END); +} +} // namespace OHOS::Ace::NG diff --git a/test/unittest/core/pattern/grid/grid_layout_test_ng.cpp b/test/unittest/core/pattern/grid/grid_layout_test_ng.cpp index 084ba248f5e..22e8f742a50 100644 --- a/test/unittest/core/pattern/grid/grid_layout_test_ng.cpp +++ b/test/unittest/core/pattern/grid/grid_layout_test_ng.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2023 Huawei Device Co., Ltd. + * Copyright (c) 2023-2024 Huawei Device Co., Ltd. * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at @@ -14,12 +14,9 @@ */ #include "grid_test_ng.h" +#include "irregular_matrices.h" -#include "core/components_ng/pattern/grid/grid_layout_info.h" #include "core/components_ng/pattern/grid/grid_layout/grid_layout_algorithm.h" -#include "core/components_ng/pattern/grid/irregular/grid_irregular_filler.h" -#include "core/components_ng/pattern/grid/irregular/grid_irregular_layout_algorithm.h" -#include "core/components_ng/pattern/grid/irregular/grid_layout_range_solver.h" #include "core/components_ng/pattern/grid/irregular/grid_layout_utils.h" namespace OHOS::Ace::NG { @@ -1019,119 +1016,6 @@ HWTEST_F(GridLayoutTestNg, UpdateGridMatrix001, TestSize.Level1) EXPECT_TRUE(IsEqual(pattern_->gridLayoutInfo_.lineHeightMap_.size(), 25)); } -/** - * @tc.name: IrregularFiller::AdvancePos001 - * @tc.desc: Test IrregularFiller::AdvancePos - * @tc.type: FUNC - */ -HWTEST_F(GridLayoutTestNg, AdvancePos001, TestSize.Level1) -{ - // empty matrix - GridLayoutInfo info; - info.crossCount_ = 2; - GridIrregularFiller filler(&info, nullptr); - EXPECT_FALSE(filler.AdvancePos()); - - filler.posX_ = 1; - filler.posY_ = 0; - EXPECT_FALSE(filler.AdvancePos()); - EXPECT_EQ(filler.posX_, 0); - EXPECT_EQ(filler.posY_, 1); - - // init matrix - info.gridMatrix_[0][0] = 1; - info.gridMatrix_[0][1] = -1; - info.gridMatrix_[1][0] = -1; - EXPECT_FALSE(filler.AdvancePos()); - EXPECT_EQ(filler.posX_, 1); - EXPECT_EQ(filler.posY_, 1); - - // reset pos and make [1][1] available - filler.posX_ = 0; - filler.posY_ = 1; - info.gridMatrix_[1][1] = -1; - EXPECT_TRUE(filler.AdvancePos()); -} - -/** - * @tc.name: IrregularFiller::FindNextItem001 - * @tc.desc: Test IrregularFiller::FindNextItem - * @tc.type: FUNC - */ -HWTEST_F(GridLayoutTestNg, FindNextItem001, TestSize.Level1) -{ - // empty matrix - GridLayoutInfo info; - info.crossCount_ = 2; - { - GridIrregularFiller filler(&info, nullptr); - - EXPECT_FALSE(filler.FindNextItem(0)); - } - - info.gridMatrix_[0][0] = 1; - info.gridMatrix_[0][1] = 2; - info.gridMatrix_[1][0] = 3; - info.gridMatrix_[1][1] = -1; - { - GridIrregularFiller filler(&info, nullptr); - - EXPECT_TRUE(filler.FindNextItem(1)); - EXPECT_EQ(filler.posX_, 0); - EXPECT_EQ(filler.posY_, 0); - - EXPECT_TRUE(filler.FindNextItem(2)); - EXPECT_EQ(filler.posX_, 1); - EXPECT_EQ(filler.posY_, 0); - - EXPECT_TRUE(filler.FindNextItem(3)); - EXPECT_EQ(filler.posX_, 0); - EXPECT_EQ(filler.posY_, 1); - - EXPECT_FALSE(filler.FindNextItem(4)); - } - - info.gridMatrix_[0][1] = -1; - info.gridMatrix_[1][0] = 2; - info.gridMatrix_[1].erase(1); - { - GridIrregularFiller filler(&info, nullptr); - - EXPECT_TRUE(filler.FindNextItem(1)); - EXPECT_EQ(filler.posX_, 0); - EXPECT_EQ(filler.posY_, 0); - - EXPECT_TRUE(filler.FindNextItem(2)); - EXPECT_EQ(filler.posX_, 0); - EXPECT_EQ(filler.posY_, 1); - - EXPECT_FALSE(filler.FindNextItem(3)); - EXPECT_EQ(filler.posX_, 1); - EXPECT_EQ(filler.posY_, 1); - } -} - -/** - * @tc.name: IrregularFiller::UpdateLength001 - * @tc.desc: Test IrregularFiller::UpdateLength - * @tc.type: FUNC - */ -HWTEST_F(GridLayoutTestNg, UpdateLength001, TestSize.Level1) -{ - GridLayoutInfo info; - info.lineHeightMap_[0] = 50.0f; - info.lineHeightMap_[1] = 30.0f; - - GridIrregularFiller filler(&info, nullptr); - float len = 0.0f; - filler.UpdateLength(len, 0, 2, 5.0f); - EXPECT_EQ(len, 85.0f); - - info.lineHeightMap_[2] = 50.0f; - filler.UpdateLength(len, 2, 3, 10.0f); - EXPECT_EQ(len, 85.0f + 50.0f + 10.0f); -} - /** * @tc.name: LayoutUtils::GetItemSize001 * @tc.desc: Test LayoutUtils::GetItemSize @@ -1211,1119 +1095,6 @@ HWTEST_F(GridLayoutTestNg, GetItemSize002, TestSize.Level1) EXPECT_EQ(GridLayoutUtils::GetItemSize(&info, wrapper, 2).columns, 3); } -/** - * @tc.name: IrregularFiller::FillOne001 - * @tc.desc: Test IrregularFiller::FillOne - * @tc.type: FUNC - */ -HWTEST_F(GridLayoutTestNg, FillOne001, TestSize.Level1) -{ - GridLayoutOptions option; - option.irregularIndexes = { - 0, // [2 x 1] - 1, // [1 x 2] - 2 // [2 x 1] - }; - auto onGetIrregularSizeByIndex = [](int32_t index) -> GridItemSize { - if (index == 1) { - return { .rows = 2, .columns = 1 }; - } - return { .rows = 1, .columns = 2 }; - }; - - option.getSizeByIndex = std::move(onGetIrregularSizeByIndex); - Create([option](GridModelNG model) { - model.SetColumnsTemplate("1fr 1fr"); - model.SetLayoutOptions(option); - }); - - GridLayoutInfo info; - info.crossCount_ = 2; - GridIrregularFiller filler(&info, AceType::RawPtr(frameNode_)); - - info.endIndex_ = 0; - filler.FillOne(); - EXPECT_EQ(info.gridMatrix_.at(0).at(0), 0); - EXPECT_EQ(info.gridMatrix_.at(0).at(1), -1); - EXPECT_EQ(filler.posX_, 0); - EXPECT_EQ(filler.posY_, 0); - - info.endIndex_ = 1; - filler.FillOne(); - EXPECT_EQ(info.gridMatrix_.at(1).at(0), 1); - EXPECT_EQ(info.gridMatrix_.at(1).size(), 1); - EXPECT_EQ(info.gridMatrix_.at(2).at(0), -1); - EXPECT_EQ(info.gridMatrix_.at(2).size(), 1); - EXPECT_TRUE(info.gridMatrix_.find(3) == info.gridMatrix_.end()); - EXPECT_EQ(filler.posX_, 0); - EXPECT_EQ(filler.posY_, 1); - - info.endIndex_ = 2; - filler.FillOne(); - EXPECT_EQ(info.gridMatrix_.at(3).at(0), 2); - EXPECT_EQ(info.gridMatrix_.at(3).at(1), -1); - EXPECT_TRUE(info.gridMatrix_.find(4) == info.gridMatrix_.end()); - EXPECT_EQ(filler.posX_, 0); - EXPECT_EQ(filler.posY_, 3); -} - -/** - * @tc.name: IrregularFiller::FillOne002 - * @tc.desc: Test IrregularFiller::FillOne with 3 columns - * @tc.type: FUNC - */ -HWTEST_F(GridLayoutTestNg, FillOne002, TestSize.Level1) -{ - GridLayoutOptions option; - option.irregularIndexes = { - 0, // [1 x 1] - 1, // [2 x 1] - 2, // [1 x 1] - 3, // [2 x 2] - 4, // [1 x 1] - 5, // [1 x 1] - 6, // [1 x 2] - 7, // [2 x 1] - }; - auto onGetIrregularSizeByIndex = [](int32_t index) -> GridItemSize { - if (index == 6) { - return { .rows = 2, .columns = 1 }; - } - if (index == 0 || index == 2 || index == 5 || index == 4) { - return { 1, 1 }; - } - if (index == 3) { - return { 2, 2 }; - } - return { .rows = 1, .columns = 2 }; - }; - - option.getSizeByIndex = std::move(onGetIrregularSizeByIndex); - Create([option](GridModelNG model) { - model.SetColumnsTemplate("1fr 1fr 1fr"); - model.SetLayoutOptions(option); - }); - - GridLayoutInfo info; - info.crossCount_ = 3; - GridIrregularFiller filler(&info, AceType::RawPtr(frameNode_)); - - for (int i = 0; i < 8; ++i) { - info.endIndex_ = i; - filler.FillOne(); - } - - decltype(info.gridMatrix_) cmp = { - { 0, { { 0, 0 }, { 1, 1 }, { 2, -1 } } }, // 0 | 1 | 1 - { 1, { { 0, 2 }, { 1, 3 }, { 2, -1 } } }, // 2 | 3 | 3 - { 2, { { 0, 4 }, { 1, -1 }, { 2, -1 } } }, // 4 | 3 | 3 - { 3, { { 0, 5 }, { 1, 6 } } }, // 5 | 6 | x - { 4, { { 1, -1 } } }, // x | 6 | x - { 5, { { 0, 7 }, { 1, -1 } } } // 7 | 7 | x - }; - - EXPECT_EQ(info.gridMatrix_, cmp); -} - -/** - * @tc.name: IrregularFiller::MeasureItem001 - * @tc.desc: Test IrregularFiller::MeasureItem - * @tc.type: FUNC - */ -HWTEST_F(GridLayoutTestNg, MeasureItem001, TestSize.Level1) -{ - GridLayoutOptions option; - option.irregularIndexes = { - 0, - }; - auto onGetIrregularSizeByIndex = [](int32_t index) -> GridItemSize { return { .columns = 1, .rows = 2 }; }; - option.getSizeByIndex = std::move(onGetIrregularSizeByIndex); - Create([option](GridModelNG model) { - model.SetColumnsTemplate("1fr 1fr 1fr 1fr"); - model.SetLayoutOptions(option); - CreateRowItem(10); - }); - - GridLayoutInfo info; - info.crossCount_ = 4; - GridIrregularFiller filler(&info, AceType::RawPtr(frameNode_)); - - info.endIndex_ = 0; - - GridIrregularFiller::FillParameters params { - .crossLens = { 50.0f, 50.0f, 100.0f, 100.0f }, .crossGap = 5.0f, .mainGap = 1.0f - }; - filler.MeasureItem(params, 0, 0); - - EXPECT_TRUE(info.lineHeightMap_.find(0) != info.lineHeightMap_.end()); - EXPECT_TRUE(info.lineHeightMap_.find(1) != info.lineHeightMap_.end()); - auto child = frameNode_->GetChildByIndex(0); - ASSERT_TRUE(child); - auto constraint = *child->GetGeometryNode()->GetParentLayoutConstraint(); - EXPECT_EQ(constraint.maxSize.Width(), 50.0f); - EXPECT_EQ(*constraint.selfIdealSize.Width(), 50.0f); - EXPECT_EQ(constraint.percentReference.Width(), 50.0f); -} - -/** - * @tc.name: IrregularFiller::MeasureItem002 - * @tc.desc: Test IrregularFiller::MeasureItem - * @tc.type: FUNC - */ -HWTEST_F(GridLayoutTestNg, MeasureItem002, TestSize.Level1) -{ - GridLayoutOptions option; - option.irregularIndexes = { - 0, - }; - Create([option](GridModelNG model) { - model.SetColumnsTemplate("1fr 1fr 1fr 1fr"); - model.SetLayoutOptions(option); - CreateRowItem(10); - }); - - GridLayoutInfo info; - info.crossCount_ = 4; - GridIrregularFiller filler(&info, AceType::RawPtr(frameNode_)); - - info.endIndex_ = 0; - filler.posY_ = 0; - - GridIrregularFiller::FillParameters params { - .crossLens = { 50.0f, 50.0f, 100.0f, 100.0f }, .crossGap = 5.0f, .mainGap = 1.0f - }; - filler.MeasureItem(params, 0, 0); - - EXPECT_TRUE(info.lineHeightMap_.find(0) != info.lineHeightMap_.end()); - EXPECT_TRUE(info.lineHeightMap_.find(1) == info.lineHeightMap_.end()); - auto child = frameNode_->GetChildByIndex(0); - ASSERT_TRUE(child); - auto constraint = *child->GetGeometryNode()->GetParentLayoutConstraint(); - EXPECT_EQ(constraint.maxSize.Width(), 315.0f); - EXPECT_EQ(*constraint.selfIdealSize.Width(), 315.0f); - EXPECT_EQ(constraint.percentReference.Width(), 315.0f); -} - -/** - * @tc.name: IrregularFiller::Fill001 - * @tc.desc: Test IrregularFiller::Fill - * @tc.type: FUNC - */ -HWTEST_F(GridLayoutTestNg, Fill001, TestSize.Level1) -{ - GridLayoutOptions option; - option.irregularIndexes = { - 0, // [1 x 2] - 3, // [2 x 2] - 6, // [3 x 2] - }; - auto onGetIrregularSizeByIndex = [](int32_t index) -> GridItemSize { - if (index == 0) { - return { .rows = 2, .columns = 1 }; - } - if (index == 3) { - return { 2, 2 }; - } - return { .rows = 2, .columns = 3 }; - }; - - option.getSizeByIndex = std::move(onGetIrregularSizeByIndex); - Create([option](GridModelNG model) { - model.SetColumnsTemplate("1fr 1fr 1fr"); - model.SetLayoutOptions(option); - CreateRowItem(10); - }); - - GridLayoutInfo info; - info.crossCount_ = 3; - GridIrregularFiller filler(&info, AceType::RawPtr(frameNode_)); - - float len = filler.Fill( - { .crossLens = { 50.0f, 50.0f, 100.0f }, .targetLen = 1000.0f, .crossGap = 5.0f, .mainGap = 1.0f }, 0); - - EXPECT_EQ(len, 6.0f); - - EXPECT_EQ(info.endIndex_, 9); - EXPECT_EQ(info.endMainLineIndex_, 6); - - decltype(info.gridMatrix_) cmp = { - { 0, { { 0, 0 }, { 1, 1 }, { 2, 2 } } }, // 0 | 1 | 2 - { 1, { { 0, -1 }, { 1, 3 }, { 2, -1 } } }, // 0 | 3 | 3 - { 2, { { 0, 4 }, { 1, -1 }, { 2, -1 } } }, // 4 | 3 | 3 - { 3, { { 0, 5 } } }, // 5 | x | x - { 4, { { 0, 6 }, { 1, -1 }, { 2, -1 } } }, // 6 | 6 | 6 - { 5, { { 0, -1 }, { 1, -1 }, { 2, -1 } } }, // 6 | 6 | 6 - { 6, { { 0, 7 }, { 1, 8 }, { 2, 9 } } } // 7 | 8 | 9 - }; - - EXPECT_EQ(info.gridMatrix_, cmp); -} - -/** - * @tc.name: LayoutRangeSolver::AddNextRow001 - * @tc.desc: Test LayoutRangeSolver::AddNextRow - * @tc.type: FUNC - */ -HWTEST_F(GridLayoutTestNg, AddNextRow001, TestSize.Level1) -{ - GridLayoutOptions option; - option.irregularIndexes = { - 0, // [1 x 2] - 3, // [2 x 1] - }; - auto onGetIrregularSizeByIndex = [](int32_t index) -> GridItemSize { - if (index == 0) { - return { .rows = 2, .columns = 1 }; - } - return { .rows = 1, .columns = 2 }; - }; - - option.getSizeByIndex = std::move(onGetIrregularSizeByIndex); - Create([option](GridModelNG model) { - model.SetColumnsTemplate("1fr 1fr 1fr"); - model.SetLayoutOptions(option); - }); - - GridLayoutInfo info; - info.crossCount_ = 3; - info.gridMatrix_ = { - { 0, { { 0, 0 }, { 1, 1 }, { 2, 2 } } }, // 0 | 1 | 2 - { 1, { { 0, -1 }, { 1, 3 }, { 2, -1 } } }, // 0 | 3 | 3 - }; - info.lineHeightMap_ = { { 0, 50.0f }, { 1, 30.0f } }; - - GridLayoutRangeSolver solver(&info, AceType::RawPtr(frameNode_)); - auto res = solver.AddNextRows(5.0f, 0); - EXPECT_EQ(res.first, 2); - EXPECT_EQ(res.second, 80.0f + 5.0f); // top line doesn't have main gap -} - -/** - * @tc.name: LayoutRangeSolver::AddNextRows002 - * @tc.desc: Test LayoutRangeSolver::AddNextRows - * @tc.type: FUNC - */ -HWTEST_F(GridLayoutTestNg, AddNextRows002, TestSize.Level1) -{ - GridLayoutOptions option; - option.irregularIndexes = { - 0, // [1 x 3] - 3, // [2 x 1] - }; - auto onGetIrregularSizeByIndex = [](int32_t index) -> GridItemSize { - if (index == 0) { - return { .rows = 3, .columns = 1 }; - } - return { .rows = 1, .columns = 2 }; - }; - - option.getSizeByIndex = std::move(onGetIrregularSizeByIndex); - Create([option](GridModelNG model) { - model.SetColumnsTemplate("1fr 1fr 1fr"); - model.SetLayoutOptions(option); - }); - - GridLayoutInfo info; - info.crossCount_ = 3; - info.gridMatrix_ = { - { 0, { { 0, 0 }, { 0, 1 }, { 2, 2 } } }, // 0 | 1 | 2 - { 1, { { 0, -1 }, { 1, 3 }, { 2, -1 } } }, // 0 | 3 | 3 - { 2, { { 0, -1 } } }, // 0 | x | x - }; - info.lineHeightMap_ = { { 0, 50.0f }, { 1, 60.0f }, { 2, 40.0f } }; - - GridLayoutRangeSolver solver(&info, AceType::RawPtr(frameNode_)); - auto res = solver.AddNextRows(5.0f, 0); - EXPECT_EQ(res.first, 3); - EXPECT_EQ(res.second, 160.0f); - - // in real scenario, parameter rowIdx = 1 is impossible - res = solver.AddNextRows(5.0f, 1); - EXPECT_EQ(res.first, 1); - EXPECT_EQ(res.second, 65.0f); - - res = solver.AddNextRows(5.0f, 2); - EXPECT_EQ(res.first, 1); - EXPECT_EQ(res.second, 45.0f); -} - -/** - * @tc.name: LayoutRangeSolver::SolveForward001 - * @tc.desc: Test LayoutRangeSolver::SolveForward - * @tc.type: FUNC - */ -HWTEST_F(GridLayoutTestNg, SolveForward001, TestSize.Level1) -{ - GridLayoutOptions option; - option.irregularIndexes = { - 0, // [2 x 2] - 1, // [1 x 3] - 4, // [3 x 1] - 5, // [1 x 2] - 7, // [1 x 2] - }; - auto onGetIrregularSizeByIndex = [](int32_t index) -> GridItemSize { - if (index == 1) { - return { .rows = 3, .columns = 1 }; - } - if (index == 0) { - return { 2, 2 }; - } - if (index == 4) { - return { .rows = 1, .columns = 3 }; - } - return { .rows = 2, .columns = 1 }; - }; - - option.getSizeByIndex = std::move(onGetIrregularSizeByIndex); - Create([option](GridModelNG model) { - model.SetColumnsTemplate("1fr 1fr 1fr"); - model.SetLayoutOptions(option); - }); - - GridLayoutInfo info; - info.crossCount_ = 3; - info.gridMatrix_ = { - { 0, { { 0, 0 }, { 0, -1 }, { 2, 1 } } }, // 0 | 0 | 1 - { 1, { { 0, -1 }, { 1, -1 }, { 2, -1 } } }, // 0 | 0 | 1 - { 2, { { 0, 2 }, { 1, 3 }, { 2, -1 } } }, // 2 | 3 | 1 - { 3, { { 0, 4 }, { 1, -1 }, { 2, -1 } } }, // 4 | 4 | 4 - { 4, { { 0, 5 }, { 1, 6 }, { 2, 7 } } }, // 5 | 6 | 7 - { 4, { { 0, -1 }, { 2, -1 } } }, // 5 | x | 7 - }; - info.lineHeightMap_ = { { 0, 20.0f }, { 1, 40.0f }, { 2, 40.0f }, { 3, 10.0f }, { 4, 50.0f }, { 5, 70.0f } }; - - GridLayoutRangeSolver solver(&info, AceType::RawPtr(frameNode_)); - - info.currentOffset_ = 0.0f; - info.startMainLineIndex_ = 3; - auto res = solver.FindStartingRow(1.0f); - EXPECT_EQ(res.row, 3); - EXPECT_EQ(res.pos, 0.0f); - - info.currentOffset_ = -20.0f; - info.startMainLineIndex_ = 0; - res = solver.FindStartingRow(1.0f); - EXPECT_EQ(res.row, 0); - EXPECT_EQ(res.pos, -20.0f); - - info.currentOffset_ = -70.0f; - info.startMainLineIndex_ = 0; - res = solver.FindStartingRow(1.0f); - EXPECT_EQ(res.row, 0); - EXPECT_EQ(res.pos, -70.0f); - - // startMainLineIndex_ == 1 || startMainLineIndex_ == 2 is impossible. - // LayoutRangeSolver always finds the first row of irregular items. - - info.currentOffset_ = -11.0f; - info.startMainLineIndex_ = 3; - res = solver.FindStartingRow(1.0f); - EXPECT_EQ(res.row, 4); - EXPECT_EQ(res.pos, 0.0f); - - info.currentOffset_ = -10.0f; - info.startMainLineIndex_ = 3; - res = solver.FindStartingRow(1.0f); - EXPECT_EQ(res.row, 3); - EXPECT_EQ(res.pos, -10.0f); - - info.currentOffset_ = -110.0f; - info.startMainLineIndex_ = 3; - res = solver.FindStartingRow(1.0f); - EXPECT_EQ(res.row, 4); - EXPECT_EQ(res.pos, -99.0f); -} - -/** - * @tc.name: LayoutRangeSolver::CheckMultiRow001 - * @tc.desc: Test LayoutRangeSolver::CheckMultiRow - * @tc.type: FUNC - */ -HWTEST_F(GridLayoutTestNg, CheckMultiRow001, TestSize.Level1) -{ - GridLayoutOptions option; - option.irregularIndexes = { - 0, // [2 x 1] - 3, // [3 x 2] - }; - auto onGetIrregularSizeByIndex = [](int32_t index) -> GridItemSize { - if (index == 0) { - return { .rows = 1, .columns = 2 }; - } - return { .rows = 2, .columns = 3 }; - }; - - option.getSizeByIndex = std::move(onGetIrregularSizeByIndex); - Create([option](GridModelNG model) { - model.SetColumnsTemplate("1fr 1fr 1fr"); - model.SetLayoutOptions(option); - }); - - GridLayoutInfo info; - info.crossCount_ = 3; - info.gridMatrix_ = { - { 0, { { 0, 0 }, { 0, -1 }, { 2, 2 } } }, // 0 | 0 | 2 - { 1, { { 0, 3 }, { 1, -1 }, { 2, -1 } } }, // 3 | 3 | 3 - { 2, { { 0, -1 }, { 1, -1 }, { 2, -1 } } }, // 3 | 3 | 3 - }; - - GridLayoutRangeSolver solver(&info, AceType::RawPtr(frameNode_)); - EXPECT_EQ(solver.CheckMultiRow(2), 2); - - EXPECT_EQ(solver.CheckMultiRow(0), 1); - EXPECT_EQ(solver.CheckMultiRow(1), 1); -} - -/** - * @tc.name: LayoutRangeSolver::SolveBackward001 - * @tc.desc: Test LayoutRangeSolver::SolveBackward - * @tc.type: FUNC - */ -HWTEST_F(GridLayoutTestNg, SolveBackward001, TestSize.Level1) -{ - GridLayoutOptions option; - option.irregularIndexes = { - 0, // [2 x 1] - 3, // [2 x 2] - 4, // [1 x 2] - 6, // [2 x 1] - }; - auto onGetIrregularSizeByIndex = [](int32_t index) -> GridItemSize { - if (index == 4) { - return { .rows = 2, .columns = 1 }; - } - if (index == 3) { - return { 2, 2 }; - } - return { .rows = 1, .columns = 2 }; - }; - - option.getSizeByIndex = std::move(onGetIrregularSizeByIndex); - Create([option](GridModelNG model) { - model.SetColumnsTemplate("1fr 1fr 1fr"); - model.SetLayoutOptions(option); - }); - - GridLayoutInfo info; - info.crossCount_ = 3; - info.gridMatrix_ = { - { 0, { { 0, 0 }, { 0, -1 }, { 2, 1 } } }, // 0 | 0 | 1 - { 1, { { 0, 2 }, { 1, 3 }, { 2, -1 } } }, // 2 | 3 | 3 - { 2, { { 0, 4 }, { 1, -1 }, { 2, -1 } } }, // 4 | 3 | 3 - { 3, { { 0, -1 }, { 1, 5 } } }, // 4 | 5 | x - { 4, { { 0, 6 }, { 1, -1 }, { 2, 7 } } }, // 6 | 6 | 7 - }; - info.lineHeightMap_ = { { 0, 50.0f }, { 1, 30.0f }, { 2, 40.0f }, { 3, 30.0f }, { 4, 50.0f } }; - - info.currentOffset_ = 20.0f; - info.startMainLineIndex_ = 4; - - GridLayoutRangeSolver solver(&info, AceType::RawPtr(frameNode_)); - auto res = solver.FindStartingRow(5.0f); - EXPECT_EQ(res.pos, -60.0f); - EXPECT_EQ(res.row, 2); - - info.currentOffset_ = 80.0f; - info.startMainLineIndex_ = 4; - - res = solver.FindStartingRow(5.0f); - EXPECT_EQ(res.pos, -35.0f); - EXPECT_EQ(res.row, 1); - - info.currentOffset_ = 200.0f; - info.startMainLineIndex_ = 4; - - res = solver.FindStartingRow(5.0f); - EXPECT_EQ(res.pos, 30.0f); - EXPECT_EQ(res.row, 0); -} - -/** - * @tc.name: LayoutRangeSolver::Solve001 - * @tc.desc: Test LayoutRangeSolver::FindStartingRow when matrix is empty. - * @tc.type: FUNC - */ -HWTEST_F(GridLayoutTestNg, Solve001, TestSize.Level1) -{ - Create([](GridModelNG model) { - model.SetColumnsTemplate("1fr 1fr 1fr"); - model.SetLayoutOptions({}); - }); - - GridLayoutInfo info; - info.crossCount_ = 3; - - info.currentOffset_ = 0.0f; - info.startMainLineIndex_ = 0; - - GridLayoutRangeSolver solver(&info, AceType::RawPtr(frameNode_)); - auto res = solver.FindStartingRow(5.0f); - EXPECT_EQ(res.pos, 0.0f); - EXPECT_EQ(res.row, 0); -} - -/** - * @tc.name: GridIrregularLayout::LayoutChildren001 - * @tc.desc: Test GridIrregularLayout::LayoutChildren - * @tc.type: FUNC - */ -HWTEST_F(GridLayoutTestNg, LayoutChildren001, TestSize.Level1) -{ - Create([](GridModelNG model) { - model.SetColumnsTemplate("1fr 1fr 1fr"); - CreateRowItem(10); - }); - - frameNode_->GetGeometryNode()->UpdatePaddingWithBorder(PaddingPropertyF { .left = 5.0f, .top = 3.0f }); - - GridLayoutInfo info; - info.gridMatrix_ = { - { 0, { { 0, 0 }, { 0, -1 }, { 2, 1 } } }, // 0 | 0 | 1 - { 1, { { 0, 2 }, { 1, 3 }, { 2, 4 } } }, // 2 | 3 | 4 - { 2, { { 0, 5 }, { 1, 6 }, { 2, 7 } } }, // 5 | 6 | 7 - { 3, { { 0, 8 }, { 1, -1 } } }, // 8 | 8 | x - { 4, { { 0, 9 }, { 1, -1 } } }, // 9 | 9 | x - }; - info.lineHeightMap_ = { { 0, 20.0f }, { 1, 20.0f }, { 2, 10.0f }, { 3, 15.0f }, { 4, 30.0f } }; - info.crossCount_ = 3; - info.startMainLineIndex_ = 0; - info.endMainLineIndex_ = 4; - - auto algorithm = AceType::MakeRefPtr(info); - algorithm->wrapper_ = AceType::RawPtr(frameNode_); - algorithm->crossLens_ = { 50.0f, 50.0f, 100.0f }; - algorithm->crossGap_ = 5.0f; - algorithm->mainGap_ = 1.0f; - algorithm->LayoutChildren(0.0f); - - EXPECT_EQ(frameNode_->GetChildByIndex(0)->GetGeometryNode()->GetFrameOffset().GetX(), 5.0f); - EXPECT_EQ(frameNode_->GetChildByIndex(0)->GetGeometryNode()->GetFrameOffset().GetY(), 3.0f); - EXPECT_EQ(frameNode_->GetChildByIndex(1)->GetGeometryNode()->GetFrameOffset(), OffsetF(115.0f, 3.0f)); - EXPECT_EQ(frameNode_->GetChildByIndex(2)->GetGeometryNode()->GetFrameOffset(), OffsetF(5.0f, 24.0f)); - EXPECT_EQ(frameNode_->GetChildByIndex(3)->GetGeometryNode()->GetFrameOffset(), OffsetF(60.0f, 24.0f)); - EXPECT_EQ(frameNode_->GetChildByIndex(4)->GetGeometryNode()->GetFrameOffset(), OffsetF(115.0f, 24.0f)); - EXPECT_EQ(frameNode_->GetChildByIndex(5)->GetGeometryNode()->GetFrameOffset(), OffsetF(5.0f, 45.0f)); - EXPECT_EQ(frameNode_->GetChildByIndex(6)->GetGeometryNode()->GetFrameOffset(), OffsetF(60.0f, 45.0f)); - EXPECT_EQ(frameNode_->GetChildByIndex(7)->GetGeometryNode()->GetFrameOffset(), OffsetF(115.0f, 45.0f)); - EXPECT_EQ(frameNode_->GetChildByIndex(8)->GetGeometryNode()->GetFrameOffset(), OffsetF(5.0f, 56.0f)); - EXPECT_EQ(frameNode_->GetChildByIndex(9)->GetGeometryNode()->GetFrameOffset(), OffsetF(5.0f, 72.0f)); -} - -/** - * @tc.name: GridIrregularLayout::Measure001 - * @tc.desc: Test GridIrregularLayout::Measure - * @tc.type: FUNC - */ -HWTEST_F(GridLayoutTestNg, Measure001, TestSize.Level1) -{ - GridLayoutOptions option; - option.irregularIndexes = { - 0, // [2 x 2] - 3, // [1 x 2] - 4, // [1 x 2] - 6, // [3 x 2] - }; - - // 0 | 0 | 1 - // 0 | 0 | 2 - // 3 | 4 | 5 - // 3 | 4 | x - // 6 | 6 | 6 - // 6 | 6 | 6 - // 7 | 8 | 9 - - auto onGetIrregularSizeByIndex = [](int32_t index) -> GridItemSize { - if (index == 0) { - return { 2, 2 }; - } - if (index == 6) { - return { .rows = 2, .columns = 3 }; - } - return { .rows = 2, .columns = 1 }; - }; - - option.getSizeByIndex = std::move(onGetIrregularSizeByIndex); - Create([option](GridModelNG model) { - model.SetColumnsTemplate("1fr 1fr 1fr"); - model.SetLayoutOptions(option); - model.SetColumnsGap(Dimension { 5.0f }); - model.SetRowsGap(Dimension { 1.0f }); - CreateRowItem(10); - }); - LayoutConstraintF constraint { .maxSize = { 610.0f, 600.0f }, .percentReference = { 610.0f, 600.0f } }; - layoutProperty_->layoutConstraint_ = constraint; - - auto algorithm = AceType::MakeRefPtr(GridLayoutInfo {}); - algorithm->gridLayoutInfo_.currentOffset_ = 0.0f; - algorithm->Measure(AceType::RawPtr(frameNode_)); - - std::vector cmp = { 200.0f, 200.0f, 200.0f }; - EXPECT_EQ(frameNode_->GetGeometryNode()->GetFrameSize().Width(), 610.0f); - EXPECT_EQ(algorithm->crossLens_, cmp); - - const auto& info = algorithm->gridLayoutInfo_; - EXPECT_EQ(algorithm->mainGap_, 1.0f); - EXPECT_EQ(algorithm->crossGap_, 5.0f); - EXPECT_EQ(info.startMainLineIndex_, 0); - EXPECT_EQ(info.endMainLineIndex_, 6); - EXPECT_EQ(info.startIndex_, 0); - EXPECT_EQ(info.endIndex_, 9); -} - -/** - * @tc.name: GridIrregularLayout::Layout001 - * @tc.desc: Test GridIrregularLayout::Layout - * @tc.type: FUNC - */ -HWTEST_F(GridLayoutTestNg, Layout001, TestSize.Level1) -{ - Create([](GridModelNG model) { - model.SetColumnsTemplate("1fr 1fr 1fr"); - CreateRowItem(10); - }); - frameNode_->GetGeometryNode()->UpdatePaddingWithBorder(PaddingPropertyF { .left = 1.0f, .top = 1.0f }); - frameNode_->GetGeometryNode()->SetFrameSize(SizeF { 200.0f, 500.0f }); - - auto algorithm = AceType::MakeRefPtr(GridLayoutInfo {}); - algorithm->crossLens_ = { 50.0f, 50.0f, 50.0f }; - auto& info = algorithm->gridLayoutInfo_; - info.gridMatrix_ = { - { 0, { { 0, 0 }, { 1, -1 }, { 2, -1 } } }, // 0 | 0 | 0 - { 1, { { 0, 2 }, { 1, 3 }, { 2, 4 } } }, // 2 | 3 | 4 - { 2, { { 0, 5 }, { 1, 6 }, { 2, 7 } } }, // 5 | 6 | 7 - { 3, { { 0, 8 }, { 1, -1 }, { 2, 9 } } }, // 8 | 6 | 9 - }; - info.lineHeightMap_ = { { 0, 20.0f }, { 1, 20.0f }, { 2, 10.0f }, { 3, 15.0f } }; - info.childrenCount_ = 10; - info.crossCount_ = 3; - info.startMainLineIndex_ = 0; - info.endMainLineIndex_ = 3; - info.startIndex_ = 0; - info.endIndex_ = 9; - info.currentOffset_ = 10.0f; - algorithm->Layout(AceType::RawPtr(frameNode_)); - - EXPECT_TRUE(info.reachStart_); - EXPECT_TRUE(info.reachEnd_); - EXPECT_TRUE(info.offsetEnd_); -} - -/** - * @tc.name: GridIrregularLayout::FillMatrixOnly001 - * @tc.desc: Test GridIrregularFiller::FillMatrixOnly - * @tc.type: FUNC - */ -HWTEST_F(GridLayoutTestNg, FillMatrixOnly001, TestSize.Level1) -{ - GridLayoutOptions option; - option.irregularIndexes = { - 0, // [2 x 1] - 2, // [3 x 2] - 5, // [1 x 3] - 6, // [2 x 1] - }; - auto onGetIrregularSizeByIndex = [](int32_t index) -> GridItemSize { - if (index == 2) { - return { .rows = 2, .columns = 3 }; - } - if (index == 5) { - return { .rows = 3, .columns = 1 }; - } - return { .rows = 1, .columns = 2 }; - }; - - decltype(GridLayoutInfo::gridMatrix_) expected = { - { 0, { { 0, 0 }, { 1, -1 }, { 2, 1 } } }, // 0 | 0 | 1 - { 1, { { 0, 2 }, { 1, -1 }, { 2, -1 } } }, // 2 | 2 | 2 - { 2, { { 0, -1 }, { 1, -1 }, { 2, -1 } } }, // 2 | 2 | 2 - { 3, { { 0, 3 }, { 1, 4 }, { 2, 5 } } }, // 3 | 4 | 5 - { 4, { { 0, 6 }, { 1, -1 }, { 2, -1 } } }, // 6 | 6 | 5 - { 5, { { 2, -1 } } } // x | x | 5 - }; - - option.getSizeByIndex = std::move(onGetIrregularSizeByIndex); - Create([option](GridModelNG model) { - model.SetColumnsTemplate("1fr 1fr 1fr"); - model.SetLayoutOptions(option); - CreateColItem(7); - }); - - GridLayoutInfo info; - info.crossCount_ = 3; - // partially filled - info.gridMatrix_ = { - { 0, { { 0, 0 }, { 1, -1 }, { 2, 1 } } }, // 0 | 0 | 1 - }; - info.childrenCount_ = 7; - - GridIrregularFiller filler(&info, AceType::RawPtr(frameNode_)); - filler.FillMatrixOnly(0, 6); - - EXPECT_EQ(info.gridMatrix_, expected); - EXPECT_EQ(info.endIndex_, 6); - EXPECT_EQ(info.endMainLineIndex_, 4); -} - -/** - * @tc.name: GridIrregularLayout::MeasureBackward001 - * @tc.desc: Test GridIrregularFiller::MeasureBackward - * @tc.type: FUNC - */ -HWTEST_F(GridLayoutTestNg, MeasureBackward001, TestSize.Level1) -{ - GridLayoutOptions option; - option.irregularIndexes = { - 0, // [2 x 1] - 2, // [3 x 2] - 5, // [1 x 3] - 6, // [2 x 1] - }; - auto onGetIrregularSizeByIndex = [](int32_t index) -> GridItemSize { - if (index == 2) { - return { .rows = 2, .columns = 3 }; - } - if (index == 5) { - return { .rows = 3, .columns = 1 }; - } - return { .rows = 1, .columns = 2 }; - }; - - GridLayoutInfo info; - info.gridMatrix_ = { - { 0, { { 0, 0 }, { 1, -1 }, { 2, 1 } } }, // 0 | 0 | 1 - { 1, { { 0, 2 }, { 1, -1 }, { 2, -1 } } }, // 2 | 2 | 2 - { 2, { { 0, -1 }, { 1, -1 }, { 2, -1 } } }, // 2 | 2 | 2 - { 3, { { 0, 3 }, { 1, 4 }, { 2, 5 } } }, // 3 | 4 | 5 - { 4, { { 0, 6 }, { 1, -1 }, { 2, -1 } } }, // 6 | 6 | 5 - { 5, { { 2, -1 } } } // x | x | 5 - }; - info.crossCount_ = 3; - - option.getSizeByIndex = std::move(onGetIrregularSizeByIndex); - Create([option](GridModelNG model) { - model.SetColumnsTemplate("1fr 1fr 1fr"); - model.SetLayoutOptions(option); - CreateRowItem(10); - }); - - GridIrregularFiller filler(&info, AceType::RawPtr(frameNode_)); - float len = filler.MeasureBackward({ { 50.0f, 50.0f, 50.0f }, 1000.0f, 5.0f, 5.0f }, 5); - - EXPECT_EQ(len, 30.0f); - EXPECT_EQ(info.lineHeightMap_.size(), 6); -} - -/** - * @tc.name: GridIrregularLayout::FindRangeOnJump001 - * @tc.desc: Test GridLayoutRangeFinder::FindRangeOnJump - * @tc.type: FUNC - */ -HWTEST_F(GridLayoutTestNg, FindRangeOnJump001, TestSize.Level1) -{ - GridLayoutOptions option; - option.irregularIndexes = { - 0, // [2 x 1] - 1, // [1 x 3] - 2, // [2 x 1] - 5, // [1 x 4] - 7, // [1 x 2] - 9, // [1 x 2] - 10, // [1 x 2] - }; - auto onGetIrregularSizeByIndex = [](int32_t index) -> GridItemSize { - switch (index) { - case 0: - return { .columns = 2, .rows = 1 }; - case 1: - return { .columns = 1, .rows = 3 }; - case 2: - return { .columns = 2, .rows = 1 }; - case 5: - return { .columns = 1, .rows = 4 }; - default: - return { .columns = 1, .rows = 2 }; - } - }; - option.getSizeByIndex = std::move(onGetIrregularSizeByIndex); - - GridLayoutInfo info; - info.crossCount_ = 3; - info.lineHeightMap_ = { { 0, 50.0f }, { 1, 100.0f }, { 2, 50.0f }, { 3, 50.0f }, { 4, 80.0f }, { 5, 75.0f }, - { 6, 10.0f } }; - info.gridMatrix_ = { - { 0, { { 0, 0 }, { 1, -1 }, { 2, 1 } } }, // 0 | 0 | 1 - { 1, { { 0, 2 }, { 1, -1 }, { 2, -1 } } }, // 2 | 2 | 1 - { 2, { { 0, 3 }, { 1, 4 }, { 2, -1 } } }, // 3 | 4 | 1 - { 3, { { 0, 5 }, { 1, 6 }, { 2, 7 } } }, // 5 | 6 | 7 - { 4, { { 0, -1 }, { 1, 8 }, { 2, -1 } } }, // 5 | 8 | 7 - { 5, { { 0, -1 }, { 1, 9 }, { 2, 10 } } }, // 5 | 9 | 10 - { 6, { { 0, -1 }, { 1, -1 }, { 2, -1 } } }, // 5 | 9 | 10 - }; - - Create([option](GridModelNG model) { - model.SetColumnsTemplate("1fr 1fr 1fr"); - model.SetLayoutOptions(option); - }); - frameNode_->GetGeometryNode()->SetContentSize({ 500.0f, 250.0f }); - - GridLayoutRangeSolver solver(&info, AceType::RawPtr(frameNode_)); - - info.scrollAlign_ = ScrollAlign::START; - auto res = solver.FindRangeOnJump(2, 5.0f); - EXPECT_EQ(res.startRow, 0); - EXPECT_EQ(res.pos, -160.0f); - EXPECT_EQ(res.endIdx, 10); - EXPECT_EQ(res.endRow, 5); - - info.scrollAlign_ = ScrollAlign::CENTER; - res = solver.FindRangeOnJump(4, 5.0f); - EXPECT_EQ(res.startRow, 0); - EXPECT_EQ(res.pos, -185.0f); - EXPECT_EQ(res.endIdx, 10); - EXPECT_EQ(res.endRow, 5); - - info.scrollAlign_ = ScrollAlign::END; - res = solver.FindRangeOnJump(4, 5.0f); - EXPECT_EQ(res.startRow, 0); - EXPECT_EQ(res.pos, -100.0f); - EXPECT_EQ(res.endIdx, 8); - EXPECT_EQ(res.endRow, 4); -} - -/** - * @tc.name: GridIrregularLayout::SolveForwardForEndIdx001 - * @tc.desc: Test GridLayoutRangeFinder::SolveForwardForEndIdx - * @tc.type: FUNC - */ -HWTEST_F(GridLayoutTestNg, SolveForwardForEndIdx001, TestSize.Level1) -{ - GridLayoutInfo info; - info.lineHeightMap_ = { { 0, 50.0f }, { 1, 100.0f }, { 2, 50.0f }, { 3, 50.0f }, { 4, 80.0f } }; - info.gridMatrix_ = { - { 0, { { 0, 0 }, { 1, -1 }, { 2, 1 } } }, // 0 | 0 | 1 - { 1, { { 0, 2 }, { 1, -1 }, { 2, -1 } } }, // 2 | 2 | 2 - { 2, { { 0, -1 }, { 1, -1 }, { 2, -1 } } }, // 2 | 2 | 2 - { 3, { { 0, 3 }, { 1, 4 }, { 2, 5 } } }, // 3 | 4 | 5 - { 4, { { 0, 6 }, { 1, -1 }, { 2, -1 } } }, // 6 | 6 | 5 - }; - - Create([](GridModelNG model) { - model.SetColumnsTemplate("1fr 1fr 1fr"); - model.SetLayoutOptions({}); - }); - - GridLayoutRangeSolver solver(&info, AceType::RawPtr(frameNode_)); - auto [endLineIdx, endIdx] = solver.SolveForwardForEndIdx(5.0f, 250.0f, 1); - EXPECT_EQ(endIdx, 6); - EXPECT_EQ(endLineIdx, 4); -} - -/** - * @tc.name: GridIrregularLayout::PrepareLineHeights001 - * @tc.desc: Test GridIrregularLayout::PrepareLineHeights001 - * @tc.type: FUNC - */ -HWTEST_F(GridLayoutTestNg, PrepareLineHeights001, TestSize.Level1) -{ - Create([](GridModelNG model) { - model.SetColumnsTemplate("1fr 1fr 1fr"); - model.SetLayoutOptions({}); - CreateColItem(15); - }); - - auto algorithm = AceType::MakeRefPtr(GridLayoutInfo {}); - algorithm->wrapper_ = AceType::RawPtr(frameNode_); - algorithm->crossLens_ = { 1.0f, 1.0f, 1.0f }; - auto& info = algorithm->gridLayoutInfo_; - // because measuring children might not generate proper heights in test, we set them manually. - decltype(info.lineHeightMap_) cmpH = { { 0, 200.0f }, { 1, 200.0f }, { 2, 200.0f }, { 3, 200.0f }, { 4, 200.0f } }; - info.lineHeightMap_ = cmpH; - decltype(info.gridMatrix_) cmp = { - { 0, { { 0, 0 }, { 1, 1 }, { 2, 2 } } }, - { 1, { { 0, 3 }, { 1, 4 }, { 2, 5 } } }, - { 2, { { 0, 6 }, { 1, 7 }, { 2, 8 } } }, - { 3, { { 0, 9 }, { 1, 10 }, { 2, 11 } } }, - { 4, { { 0, 12 }, { 1, 13 }, { 2, 14 } } }, - }; - info.gridMatrix_ = cmp; - - info.crossCount_ = 3; - - info.scrollAlign_ = ScrollAlign::START; - int32_t idx = 0; - algorithm->PrepareLineHeight(70.0f, idx); - EXPECT_EQ(info.scrollAlign_, ScrollAlign::START); - EXPECT_EQ(idx, 0); - - info.scrollAlign_ = ScrollAlign::START; - idx = 2; - algorithm->PrepareLineHeight(300.0f, idx); - EXPECT_EQ(info.scrollAlign_, ScrollAlign::START); - EXPECT_EQ(idx, 2); - - // can't align start with idx 4 - info.scrollAlign_ = ScrollAlign::START; - idx = 4; - algorithm->PrepareLineHeight(300.0f, idx); - EXPECT_EQ(info.scrollAlign_, ScrollAlign::END); - EXPECT_EQ(idx, 4); - - // can't align center with idx 0 - info.scrollAlign_ = ScrollAlign::CENTER; - idx = 0; - algorithm->PrepareLineHeight(350.0f, idx); - EXPECT_EQ(info.scrollAlign_, ScrollAlign::START); - EXPECT_EQ(idx, 0); - - // can't align center with idx 4 - info.scrollAlign_ = ScrollAlign::CENTER; - idx = 4; - algorithm->PrepareLineHeight(350.0f, idx); - EXPECT_EQ(info.scrollAlign_, ScrollAlign::END); - EXPECT_EQ(idx, 4); - - // align center with idx 4 and len 30.0f - info.scrollAlign_ = ScrollAlign::CENTER; - idx = 4; - algorithm->PrepareLineHeight(30.0f, idx); - EXPECT_EQ(info.scrollAlign_, ScrollAlign::CENTER); - EXPECT_EQ(idx, 4); - - // can't align end with idx 1 and len 200.0f - info.scrollAlign_ = ScrollAlign::END; - idx = 1; - algorithm->PrepareLineHeight(500.0f, idx); - EXPECT_EQ(info.scrollAlign_, ScrollAlign::START); - EXPECT_EQ(idx, 0); - - info.scrollAlign_ = ScrollAlign::END; - idx = 3; - algorithm->PrepareLineHeight(300.0f, idx); - EXPECT_EQ(info.scrollAlign_, ScrollAlign::END); - EXPECT_EQ(idx, 3); - - info.scrollAlign_ = ScrollAlign::END; - idx = 4; - algorithm->PrepareLineHeight(1000.0f, idx); - EXPECT_EQ(info.scrollAlign_, ScrollAlign::END); - EXPECT_EQ(idx, 4); - - // can't align end with len 340 - info.scrollAlign_ = ScrollAlign::END; - idx = 4; - algorithm->PrepareLineHeight(1040.0f, idx); - EXPECT_EQ(info.scrollAlign_, ScrollAlign::START); - EXPECT_EQ(idx, 0); - - EXPECT_EQ(cmp, info.gridMatrix_); - EXPECT_EQ(cmpH, info.lineHeightMap_); -} - -/** - * @tc.name: GridIrregularLayout::TransformAutoScrollAlign001 - * @tc.desc: Test IrregularLayout::TransformAutoScrollAlign - * @tc.type: FUNC - */ -HWTEST_F(GridLayoutTestNg, TransformAutoScrollAlign001, TestSize.Level1) -{ - GridLayoutOptions option; - option.irregularIndexes = { - 0, // [2 x 1] - 2, // [3 x 2] - 5, // [1 x 3] - 6, // [2 x 1] - }; - auto onGetIrregularSizeByIndex = [](int32_t index) -> GridItemSize { - if (index == 2) { - return { .rows = 2, .columns = 3 }; - } - if (index == 5) { - return { .rows = 3, .columns = 1 }; - } - return { .rows = 1, .columns = 2 }; - }; - - option.getSizeByIndex = std::move(onGetIrregularSizeByIndex); - Create([option](GridModelNG model) { - model.SetColumnsTemplate("1fr 1fr 1fr"); - model.SetLayoutOptions(option); - }); - - auto algo = AceType::MakeRefPtr(GridLayoutInfo {}); - algo->wrapper_ = AceType::RawPtr(frameNode_); - - auto& info = algo->gridLayoutInfo_; - info.lineHeightMap_ = { { 0, 50.0f }, { 1, 300.0f }, { 2, 30.0f }, { 3, 50.0f }, { 4, 80.0f } }; - info.gridMatrix_ = { - { 0, { { 0, 0 }, { 1, -1 }, { 2, 1 } } }, // 0 | 0 | 1 - { 1, { { 0, 2 }, { 1, -1 }, { 2, -1 } } }, // 2 | 2 | 2 - { 2, { { 0, -1 }, { 1, -1 }, { 2, -1 } } }, // 2 | 2 | 2 - { 3, { { 0, 3 }, { 1, 4 }, { 2, 5 } } }, // 3 | 4 | 5 - { 4, { { 0, 6 }, { 1, -1 }, { 2, -1 } } }, // 6 | 6 | 5 - }; - algo->mainGap_ = 5.0f; - - info.jumpIndex_ = 2; - info.startMainLineIndex_ = 0; - info.endMainLineIndex_ = 4; - info.startIndex_ = 0; - info.endIndex_ = 6; - EXPECT_EQ(algo->TransformAutoScrollAlign(500.0f), ScrollAlign::NONE); - - info.jumpIndex_ = 0; - info.startMainLineIndex_ = 3; - info.endMainLineIndex_ = 4; - info.startIndex_ = 3; - info.endIndex_ = 6; - info.currentOffset_ = -10.0f; - EXPECT_EQ(algo->TransformAutoScrollAlign(100.0f), ScrollAlign::START); - - info.jumpIndex_ = 2; - info.startMainLineIndex_ = 1; - info.endMainLineIndex_ = 2; - info.startIndex_ = 2; - info.endIndex_ = 2; - info.currentOffset_ = -25.0f; - EXPECT_EQ(algo->TransformAutoScrollAlign(310.0f), ScrollAlign::NONE); - - // line 3 now matches with the end of the viewport, should endMainlineIndex_ be updated to 3? - info.currentOffset_ = -30.0f; - info.endMainLineIndex_ = 3; - info.endIndex_ = 5; - EXPECT_EQ(algo->TransformAutoScrollAlign(310.0f), ScrollAlign::START); - info.currentOffset_ = -31.0f; - EXPECT_EQ(algo->TransformAutoScrollAlign(310.0f), ScrollAlign::START); - - info.jumpIndex_ = 0; - info.startMainLineIndex_ = 3; - info.endMainLineIndex_ = 4; - info.startIndex_ = 3; - info.endIndex_ = 6; - EXPECT_EQ(algo->TransformAutoScrollAlign(100.0f), ScrollAlign::START); - - info.jumpIndex_ = 4; - info.startMainLineIndex_ = 1; - info.endMainLineIndex_ = 4; - info.startIndex_ = 2; - info.endIndex_ = 6; - - info.currentOffset_ = -379.0f; - algo->mainGap_ = 50.0f; - EXPECT_EQ(algo->TransformAutoScrollAlign(152.0f), ScrollAlign::NONE); - - algo->mainGap_ = 5.0f; - // emulate init - info.lineHeightMap_.clear(); - info.gridMatrix_.clear(); - info.jumpIndex_ = 3; - info.startMainLineIndex_ = 0; - info.endMainLineIndex_ = 0; - info.startIndex_ = 0; - info.endIndex_ = -1; - EXPECT_EQ(algo->TransformAutoScrollAlign(300.0f), ScrollAlign::END); -} - /** * @tc.name: GridLayout001 * @tc.desc: Test GridLayoutAlgorithm for coverage diff --git a/test/unittest/core/pattern/grid/irregular_matrices.h b/test/unittest/core/pattern/grid/irregular_matrices.h new file mode 100644 index 00000000000..a8f03cf2488 --- /dev/null +++ b/test/unittest/core/pattern/grid/irregular_matrices.h @@ -0,0 +1,154 @@ +/* + * Copyright (c) 2024 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef FOUNDATION_ACE_TEST_UNITTEST_CORE_PATTERN_GRID_IRREGULAR_MATRICES_H +#define FOUNDATION_ACE_TEST_UNITTEST_CORE_PATTERN_GRID_IRREGULAR_MATRICES_H + +#include "core/components_ng/pattern/grid/grid_layout_info.h" +#include "core/components_ng/pattern/grid/grid_layout_options.h" + +namespace OHOS::Ace::NG { +GridLayoutOptions GetOptionDemo1(); +const decltype(GridLayoutInfo::gridMatrix_) MATRIX_DEMO_1 = { + { 0, { { 0, 0 }, { 1, 0 }, { 2, 1 } } }, // 0 | 0 | 1 + { 1, { { 0, 2 }, { 1, -2 }, { 2, -1 } } }, // 2 | 2 | 1 + { 2, { { 0, 3 }, { 1, 4 }, { 2, -1 } } }, // 3 | 4 | 1 + { 3, { { 0, 5 }, { 1, 6 }, { 2, 7 } } }, // 5 | 6 | 7 + { 4, { { 0, -5 }, { 1, 8 }, { 2, -7 } } }, // 5 | 8 | 7 + { 5, { { 0, -5 }, { 1, 9 }, { 2, 10 } } }, // 5 | 9 | 10 + { 6, { { 0, -5 }, { 1, -9 }, { 2, -10 } } }, // 5 | 9 | 10 +}; + +GridLayoutOptions GetOptionDemo2(); +const decltype(GridLayoutInfo::gridMatrix_) MATRIX_DEMO_2 = { + { 0, { { 0, 0 }, { 1, 0 }, { 2, 1 } } }, // 0 | 0 | 1 + { 1, { { 0, 0 }, { 1, 0 }, { 2, -1 } } }, // 0 | 0 | 1 + { 2, { { 0, 2 }, { 1, 3 }, { 2, -1 } } }, // 2 | 3 | 1 + { 3, { { 0, 4 }, { 1, -4 }, { 2, -4 } } }, // 4 | 4 | 4 + { 4, { { 0, 5 }, { 1, 6 }, { 2, 7 } } }, // 5 | 6 | 7 + { 5, { { 0, -5 }, { 2, -7 } } }, // 5 | x | 7 +}; + +const decltype(GridLayoutInfo::gridMatrix_) MATRIX_DEMO_3 = { + { 0, { { 0, 0 }, { 1, 1 } } }, + { 1, { { 0, 2 }, { 1, -2 } } }, + { 2, { { 0, 3 }, { 1, 4 } } }, + { 3, { { 0, 5 }, { 1, -5 } } }, + { 4, { { 0, 6 }, { 1, 7 } } }, + { 5, { { 0, 8 }, { 1, 9 } } }, + { 6, { { 0, 10 }, { 1, -10 } } }, + { 7, { { 0, 11 } } }, +}; + +const decltype(GridLayoutInfo::gridMatrix_) MATRIX_DEMO_4 = { + { 0, { { 1, 0 }, { 2, 0 } } }, + { 1, { { 0, 1 }, { 1, 0 }, { 2, 0 } } }, + { 2, { { 0, 2 }, { 1, 3 }, { 2, 4 } } }, + { 3, { { 0, 5 }, { 1, 6 }, { 2, 7 } } }, + { 4, { { 0, 8 }, { 1, 8 }, { 1, 7 } } }, + { 5, { { 0, 8 }, { 1, 8 }, { 2, 9 } } }, + { 6, { { 0, 8 }, { 1, 8 }, { 2, 10 } } }, + { 7, { { 0, 8 }, { 1, 8 }, { 2, 11 } } }, + { 8, { { 0, 8 }, { 1, 8 }, { 2, 12 } } }, + { 9, { { 0, 8 }, { 1, 8 }, { 2, 13 } } }, + { 10, { { 0, 8 }, { 1, 8 }, { 2, 14 } } }, + { 11, { { 0, 15 }, { 1, 16 }, { 2, 17 } } }, + { 12, { { 0, 18 }, { 1, 19 } } }, + { 13, { { 0, 20 }, { 1, 20 }, { 2, 21 } } }, + { 14, { { 0, 20 }, { 1, 20 }, { 2, 22 } } }, + { 15, { { 0, 23 }, { 1, 24 }, { 2, 25 } } }, + { 16, { { 0, 26 }, { 1, 27 }, { 2, 28 } } }, + { 17, { { 0, 29 }, { 1, 30 } } }, + { 18, { { 0, 31 }, { 1, 31 } } }, + { 19, { { 0, 31 }, { 1, 31 } } }, +}; + +const decltype(GridLayoutInfo::gridMatrix_) MATRIX_DEMO_5 = { + { 0, { { 0, 0 }, { 1, 1 } } }, + { 1, { { 0, 2 }, { 1, -2 } } }, + { 2, { { 0, 3 }, { 1, -3 } } }, + { 3, { { 0, -3 }, { 1, -3 } } }, + { 4, { { 0, -3 }, { 1, -3 } } }, + { 5, { { 0, -3 }, { 1, -3 } } }, + { 6, { { 0, 4 }, { 1, -4 } } }, + { 7, { { 0, 5 }, { 1, 6 } } }, + { 8, { { 0, -5 }, { 1, 7 } } }, + { 9, { { 0, 8 }, { 1, -8 } } }, + { 10, { { 0, -8 }, { 1, -8 } } }, + { 11, { { 0, 9 }, { 1, 10 } } }, +}; + +const decltype(GridLayoutInfo::gridMatrix_) MATRIX_DEMO_6 = { + { 0, { { 0, 0 }, { 1, 1 } } }, + { 1, { { 0, 2 }, { 1, -2 } } }, + { 2, { { 0, 3 }, { 1, 4 } } }, + { 3, { { 0, 5 }, { 1, -5 } } }, + { 4, { { 0, 6 }, { 1, 7 } } }, + { 5, { { 0, 8 }, { 1, 9 } } }, + { 6, { { 0, 10 }, { 1, -10 } } }, + { 7, { { 0, 11 } } }, +}; + +const decltype(GridLayoutInfo::gridMatrix_) MATRIX_DEMO_7 = { + { 0, { { 0, 0 }, { 1, 0 }, { 2, 1 } } }, + { 1, { { 0, 2 }, { 1, 3 }, { 2, 4 } } }, + { 2, { { 0, 5 }, { 1, 6 }, { 2, -4 } } }, + { 3, { { 0, 7 }, { 1, -6 }, { 2, 9 } } }, +}; + +GridLayoutOptions GetOptionDemo8(); +const decltype(GridLayoutInfo::gridMatrix_) MATRIX_DEMO_8 = { + { 0, { { 0, 0 }, { 1, 0 }, { 2, 1 } } }, // 0 | 0 | 1 + { 1, { { 0, 2 }, { 1, -2 }, { 2, -2 } } }, // 2 | 2 | 2 + { 2, { { 0, -2 }, { 1, -2 }, { 2, -2 } } }, // 2 | 2 | 2 + { 3, { { 0, 3 }, { 1, 4 }, { 2, 5 } } }, // 3 | 4 | 5 + { 4, { { 0, 6 }, { 1, -6 }, { 2, -5 } } }, // 6 | 6 | 5 + { 5, { { 2, -5 } } } // x | x | 5 +}; + +GridLayoutOptions GetOptionDemo9(); +const decltype(GridLayoutInfo::gridMatrix_) MATRIX_DEMO_9 = { + { 0, { { 0, 0 }, { 1, 1 }, { 2, 2 } } }, // 0 | 1 | 2 + { 1, { { 0, 0 }, { 1, 3 }, { 2, -3 } } }, // 0 | 3 | 3 + { 2, { { 0, 4 }, { 1, -3 }, { 2, -3 } } }, // 4 | 3 | 3 + { 3, { { 0, 5 } } }, // 5 | x | x + { 4, { { 0, 6 }, { 1, -6 }, { 2, -6 } } }, // 6 | 6 | 6 + { 5, { { 0, -6 }, { 1, -6 }, { 2, -6 } } }, // 6 | 6 | 6 + { 6, { { 0, 7 }, { 1, 8 }, { 2, 9 } } } // 7 | 8 | 9 +}; + +GridLayoutOptions GetOptionDemo10(); +const decltype(GridLayoutInfo::gridMatrix_) MATRIX_DEMO_10 = { + { 0, { { 0, 0 }, { 1, 1 }, { 2, -1 } } }, // 0 | 1 | 1 + { 1, { { 0, 2 }, { 1, 3 }, { 2, -3 } } }, // 2 | 3 | 3 + { 2, { { 0, 4 }, { 1, -3 }, { 2, -3 } } }, // 4 | 3 | 3 + { 3, { { 0, 5 }, { 1, 6 } } }, // 5 | 6 | x + { 4, { { 1, -6 } } }, // x | 6 | x + { 5, { { 0, 7 }, { 1, -7 } } } // 7 | 7 | x +}; + +GridLayoutOptions GetOptionDemo11(); +const decltype(GridLayoutInfo::gridMatrix_) MATRIX_DEMO_11 = { + { 0, { { 0, 0 }, { 1, 0 }, { 2, 1 } } }, // 0 | 0 | 1 + { 1, { { 0, 0 }, { 1, 0 }, { 2, 2 } } }, // 0 | 0 | 2 + { 2, { { 0, 3 }, { 1, 4 }, { 2, 5 } } }, // 3 | 4 | 5 + { 3, { { 0, -3 }, { 1, -4 } } }, // 3 | 4 | x + { 4, { { 0, 6 }, { 1, -6 }, { 2, -6 } } }, // 6 | 6 | 6 + { 5, { { 0, -6 }, { 1, -6 }, { 2, -6 } } }, // 6 | 6 | 6 + { 6, { { 0, 7 }, { 1, 8 }, { 2, 9 } } }, // 7 | 8 | 9 +}; + +} // namespace OHOS::Ace::NG +#endif diff --git a/test/unittest/core/pattern/grid/irregular_matrics.cpp b/test/unittest/core/pattern/grid/irregular_matrics.cpp new file mode 100644 index 00000000000..245d65ae30a --- /dev/null +++ b/test/unittest/core/pattern/grid/irregular_matrics.cpp @@ -0,0 +1,173 @@ +/* + * Copyright (c) 2024 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + + #include "irregular_matrices.h" + + namespace OHOS::Ace::NG { + GridLayoutOptions GetOptionDemo1() +{ + GridLayoutOptions option; + option.irregularIndexes = { + 0, // [2 x 1] + 1, // [1 x 3] + 2, // [2 x 1] + 5, // [1 x 4] + 7, // [1 x 2] + 9, // [1 x 2] + 10, // [1 x 2] + }; + auto onGetIrregularSizeByIndex = [](int32_t index) -> GridItemSize { + switch (index) { + case 0: + return { .columns = 2, .rows = 1 }; + case 1: + return { .columns = 1, .rows = 3 }; + case 2: + return { .columns = 2, .rows = 1 }; + case 5: + return { .columns = 1, .rows = 4 }; + default: + return { .columns = 1, .rows = 2 }; + } + }; + option.getSizeByIndex = std::move(onGetIrregularSizeByIndex); + return option; +} + +GridLayoutOptions GetOptionDemo2() +{ + GridLayoutOptions option; + option.irregularIndexes = { + 0, // [2 x 2] + 1, // [1 x 3] + 4, // [3 x 1] + 5, // [1 x 2] + 7, // [1 x 2] + }; + auto onGetIrregularSizeByIndex = [](int32_t index) -> GridItemSize { + if (index == 1) { + return { .rows = 3, .columns = 1 }; + } + if (index == 0) { + return { 2, 2 }; + } + if (index == 4) { + return { .rows = 1, .columns = 3 }; + } + return { .rows = 2, .columns = 1 }; + }; + + option.getSizeByIndex = std::move(onGetIrregularSizeByIndex); + return option; +} + +GridLayoutOptions GetOptionDemo8() +{ + GridLayoutOptions option; + option.irregularIndexes = { + 0, // [2 x 1] + 2, // [3 x 2] + 5, // [1 x 3] + 6, // [2 x 1] + }; + auto onGetIrregularSizeByIndex = [](int32_t index) -> GridItemSize { + if (index == 2) { + return { .rows = 2, .columns = 3 }; + } + if (index == 5) { + return { .rows = 3, .columns = 1 }; + } + return { .rows = 1, .columns = 2 }; + }; + option.getSizeByIndex = std::move(onGetIrregularSizeByIndex); + return option; +} + +GridLayoutOptions GetOptionDemo9() +{ + GridLayoutOptions option; + option.irregularIndexes = { + 0, // [1 x 2] + 3, // [2 x 2] + 6, // [3 x 2] + }; + auto onGetIrregularSizeByIndex = [](int32_t index) -> GridItemSize { + if (index == 0) { + return { .rows = 2, .columns = 1 }; + } + if (index == 3) { + return { 2, 2 }; + } + return { .rows = 2, .columns = 3 }; + }; + + option.getSizeByIndex = std::move(onGetIrregularSizeByIndex); + return option; +} + +GridLayoutOptions GetOptionDemo10() +{ + GridLayoutOptions option; + option.irregularIndexes = { + 0, // [1 x 1] + 1, // [2 x 1] + 2, // [1 x 1] + 3, // [2 x 2] + 4, // [1 x 1] + 5, // [1 x 1] + 6, // [1 x 2] + 7, // [2 x 1] + }; + auto onGetIrregularSizeByIndex = [](int32_t index) -> GridItemSize { + if (index == 6) { + return { .rows = 2, .columns = 1 }; + } + if (index == 0 || index == 2 || index == 5 || index == 4) { + return { 1, 1 }; + } + if (index == 3) { + return { 2, 2 }; + } + return { .rows = 1, .columns = 2 }; + }; + + option.getSizeByIndex = std::move(onGetIrregularSizeByIndex); + return option; +} + +GridLayoutOptions GetOptionDemo11() +{ + GridLayoutOptions option; + option.irregularIndexes = { + 0, // [2 x 2] + 3, // [1 x 2] + 4, // [1 x 2] + 6, // [3 x 2] + }; + + auto onGetIrregularSizeByIndex = [](int32_t index) -> GridItemSize { + if (index == 0) { + return { 2, 2 }; + } + if (index == 6) { + return { .rows = 2, .columns = 3 }; + } + return { .rows = 2, .columns = 1 }; + }; + + option.getSizeByIndex = std::move(onGetIrregularSizeByIndex); + return option; +} + } \ No newline at end of file diff --git a/test/unittest/core/pattern/grid/layout_info_test.cpp b/test/unittest/core/pattern/grid/layout_info_test.cpp index 98cf6fc018d..65e9b0ce674 100644 --- a/test/unittest/core/pattern/grid/layout_info_test.cpp +++ b/test/unittest/core/pattern/grid/layout_info_test.cpp @@ -15,25 +15,13 @@ #include "gtest/gtest.h" #define private public -#include "core/components_ng/pattern/grid/grid_layout_info.h" +#include "irregular_matrices.h" using namespace testing; using namespace testing::ext; namespace OHOS::Ace::NG { class GridLayoutInfoTest : public testing::Test {}; -namespace { -const decltype(GridLayoutInfo::gridMatrix_) MATRIX_DEMO_1 = { - { 0, { { 0, 0 }, { 1, 1 } } }, - { 1, { { 0, 2 }, { 1, -1 } } }, - { 2, { { 0, 3 }, { 1, 4 } } }, - { 3, { { 0, 5 }, { 1, -1 } } }, - { 4, { { 0, 6 }, { 1, 7 } } }, - { 5, { { 0, 8 }, { 1, 9 } } }, - { 6, { { 0, 10 }, { 1, -1 } } }, - { 7, { { 0, 11 } } }, -}; -} /** * @tc.name: GridLayoutInfo::GetContentHeight001 * @tc.desc: test GetContentHeight while changing endIndex @@ -44,7 +32,7 @@ HWTEST_F(GridLayoutInfoTest, GetContentHeight001, TestSize.Level1) GridLayoutInfo info; info.lineHeightMap_ = { { 0, 5.0f }, { 1, 10.0f }, { 2, 5.0f }, { 3, 10.0f }, { 4, 5.0f }, { 5, 5.0f }, { 6, 10.0f }, { 7, 5.0f } }; - info.gridMatrix_ = MATRIX_DEMO_1; + info.gridMatrix_ = MATRIX_DEMO_3; GridLayoutOptions option { .irregularIndexes = { 2, 5, 10 }, @@ -75,7 +63,7 @@ HWTEST_F(GridLayoutInfoTest, GetContentHeight002, TestSize.Level1) GridLayoutInfo info; info.lineHeightMap_ = { { 0, 5.0f }, { 1, 5.0f }, { 2, 5.0f } }; info.gridMatrix_ = { - { 0, { { 0, 0 }, { 1, -1 }, { 2, -1 } } }, + { 0, { { 0, 0 }, { 1, 0 }, { 2, 0 } } }, { 1, { { 0, 1 }, { 1, 2 }, { 2, 3 } } }, { 2, { { 0, 4 } } }, }; @@ -101,7 +89,7 @@ HWTEST_F(GridLayoutInfoTest, GetContentHeightBigItem001, TestSize.Level1) info.crossCount_ = 2; info.childrenCount_ = 12; - info.gridMatrix_ = MATRIX_DEMO_1; + info.gridMatrix_ = MATRIX_DEMO_3; constexpr float trueHeight = 47.0f; constexpr float error = trueHeight * 0.1f; @@ -119,31 +107,6 @@ HWTEST_F(GridLayoutInfoTest, GetContentHeightBigItem001, TestSize.Level1) EXPECT_LE(std::abs(estimation - trueHeight), error); } -namespace { -const decltype(GridLayoutInfo::gridMatrix_) MATRIX_DEMO_2 = { - { 0, { { 1, 0 }, { 2, 0 } } }, - { 1, { { 0, 1 }, { 1, 0 }, { 2, 0 } } }, - { 2, { { 0, 2 }, { 1, 3 }, { 2, 4 } } }, - { 3, { { 0, 5 }, { 1, 6 }, { 2, 7 } } }, - { 4, { { 0, 8 }, { 1, 8 }, { 1, 7 } } }, - { 5, { { 0, 8 }, { 1, 8 }, { 2, 9 } } }, - { 6, { { 0, 8 }, { 1, 8 }, { 2, 10 } } }, - { 7, { { 0, 8 }, { 1, 8 }, { 2, 11 } } }, - { 8, { { 0, 8 }, { 1, 8 }, { 2, 12 } } }, - { 9, { { 0, 8 }, { 1, 8 }, { 2, 13 } } }, - { 10, { { 0, 8 }, { 1, 8 }, { 2, 14 } } }, - { 11, { { 0, 15 }, { 1, 16 }, { 2, 17 } } }, - { 12, { { 0, 18 }, { 1, 19 } } }, - { 13, { { 0, 20 }, { 1, 20 }, { 2, 21 } } }, - { 14, { { 0, 20 }, { 1, 20 }, { 2, 22 } } }, - { 15, { { 0, 23 }, { 1, 24 }, { 2, 25 } } }, - { 16, { { 0, 26 }, { 1, 27 }, { 2, 28 } } }, - { 17, { { 0, 29 }, { 1, 30 } } }, - { 18, { { 0, 31 }, { 1, 31 } } }, - { 19, { { 0, 31 }, { 1, 31 } } }, -}; -} - /** * @tc.name: GridLayoutInfo::GetContentHeightBigItem002 * @tc.desc: test GetContentHeight when hasBigItem_ == true, adapted from test demo. @@ -156,7 +119,7 @@ HWTEST_F(GridLayoutInfoTest, GetContentHeightBigItem002, TestSize.Level1) info.crossCount_ = 3; info.childrenCount_ = 32; - info.gridMatrix_ = MATRIX_DEMO_2; + info.gridMatrix_ = MATRIX_DEMO_4; // using mainGap = 5.0f and lineHeight = 100.0f constexpr float trueHeight = 2095.0f; constexpr float error = trueHeight * 0.1f; @@ -192,7 +155,7 @@ HWTEST_F(GridLayoutInfoTest, GetContentOffsetBigItem001, TestSize.Level1) info.crossCount_ = 3; info.childrenCount_ = 32; - info.gridMatrix_ = MATRIX_DEMO_2; + info.gridMatrix_ = MATRIX_DEMO_4; info.startIndex_ = 8; info.startMainLineIndex_ = 9; @@ -225,7 +188,7 @@ HWTEST_F(GridLayoutInfoTest, GetContentOffsetBigItem002, TestSize.Level1) info.crossCount_ = 3; info.childrenCount_ = 32; - info.gridMatrix_ = MATRIX_DEMO_2; + info.gridMatrix_ = MATRIX_DEMO_4; info.startIndex_ = 15; info.startMainLineIndex_ = 11; @@ -250,7 +213,7 @@ HWTEST_F(GridLayoutInfoTest, GetContentOffsetBigItem003, TestSize.Level1) info.crossCount_ = 3; info.childrenCount_ = 32; - info.gridMatrix_ = MATRIX_DEMO_2; + info.gridMatrix_ = MATRIX_DEMO_4; info.startIndex_ = 20; info.startMainLineIndex_ = 14; @@ -272,16 +235,7 @@ HWTEST_F(GridLayoutInfoTest, GetContentOffset001, TestSize.Level1) GridLayoutInfo info; info.lineHeightMap_ = { { 0, 5.0f }, { 1, 10.0f }, { 2, 5.0f }, { 3, 10.0f }, { 4, 5.0f }, { 5, 5.0f }, { 6, 10.0f }, { 7, 5.0f } }; - info.gridMatrix_ = { - { 0, { { 0, 0 }, { 1, 1 } } }, - { 1, { { 0, 2 }, { 1, -1 } } }, - { 2, { { 0, 3 }, { 1, 4 } } }, - { 3, { { 0, 5 }, { 1, -1 } } }, - { 4, { { 0, 6 }, { 1, 7 } } }, - { 5, { { 0, 8 }, { 1, 9 } } }, - { 6, { { 0, 10 }, { 1, -1 } } }, - { 7, { { 0, 11 } } }, - }; + info.gridMatrix_ = MATRIX_DEMO_6; GridLayoutOptions option { .irregularIndexes = { 2, 5, 10 }, @@ -362,12 +316,7 @@ HWTEST_F(GridLayoutInfoTest, GetContentHeightRegular001, TestSize.Level1) HWTEST_F(GridLayoutInfoTest, FindItemInRange001, TestSize.Level1) { GridLayoutInfo info; - info.gridMatrix_ = { - { 0, { { 0, 0 }, { 1, -1 }, { 2, -1 } } }, - { 1, { { 0, 2 }, { 1, 3 }, { 2, 4 } } }, - { 2, { { 0, 5 }, { 1, 6 }, { 2, -1 } } }, - { 3, { { 0, 7 }, { 1, -1 }, { 2, 9 } } }, - }; + info.gridMatrix_ = MATRIX_DEMO_7; info.startMainLineIndex_ = 0; info.endMainLineIndex_ = 3; auto res = info.FindItemInRange(5); @@ -390,30 +339,7 @@ HWTEST_F(GridLayoutInfoTest, FindItemInRange001, TestSize.Level1) EXPECT_EQ(info.FindItemInRange(7).first, -1); } -/** - * @tc.name: UpdateStartIdxToLastItem001 - * @tc.desc: Test GridLayoutInfo::UpdateStartIdxToLastItem - * @tc.type: FUNC - */ -HWTEST_F(GridLayoutInfoTest, UpdateStartIdxToLastItem001, TestSize.Level1) -{ - GridLayoutInfo info; - info.gridMatrix_ = { - { 0, { { 0, 0 }, { 1, -1 }, { 2, -1 } } }, - { 1, { { 0, 2 }, { 1, 3 }, { 2, -1 } } }, - { 2, { { 0, 5 }, { 1, -1 }, { 2, -1 } } }, - { 3, { { 0, 7 }, { 1, -1 }, { 2, -1 } } }, - }; - info.UpdateStartIdxToLastItem(); - EXPECT_EQ(info.startIndex_, 7); - EXPECT_EQ(info.startMainLineIndex_, 3); - - info.gridMatrix_.clear(); - info.UpdateStartIdxToLastItem(); - EXPECT_EQ(info.startIndex_, 0); - EXPECT_EQ(info.startMainLineIndex_, 0); -} - +namespace { void CheckEachIndex(const GridLayoutInfo& info, int32_t maxIdx) { for (int i = 0; i <= maxIdx; ++i) { @@ -429,6 +355,7 @@ void CheckEachIndex(const GridLayoutInfo& info, int32_t maxIdx) EXPECT_TRUE(foundFlag); } } +} // namespace /** * @tc.name: FindInMatrix001 @@ -441,7 +368,7 @@ HWTEST_F(GridLayoutInfoTest, FindInMatrix, TestSize.Level1) auto nullIt = info.FindInMatrix(1); EXPECT_EQ(nullIt, info.gridMatrix_.end()); - info.gridMatrix_ = MATRIX_DEMO_2; + info.gridMatrix_ = MATRIX_DEMO_4; CheckEachIndex(info, 31); @@ -457,11 +384,27 @@ HWTEST_F(GridLayoutInfoTest, FindInMatrix, TestSize.Level1) HWTEST_F(GridLayoutInfoTest, FindInMatrix002, TestSize.Level1) { GridLayoutInfo info; - info.gridMatrix_ = MATRIX_DEMO_1; + info.gridMatrix_ = MATRIX_DEMO_3; CheckEachIndex(info, 11); auto nullIt = info.FindInMatrix(12); EXPECT_EQ(nullIt, info.gridMatrix_.end()); } + +/** + * @tc.name: FindInMatrix003 + * @tc.desc: Test GridLayoutInfo::FindInMatrix + * @tc.type: FUNC + */ +HWTEST_F(GridLayoutInfoTest, FindInMatrix003, TestSize.Level1) +{ + GridLayoutInfo info; + info.gridMatrix_ = MATRIX_DEMO_5; + + CheckEachIndex(info, 10); + + auto nullIt = info.FindInMatrix(11); + EXPECT_EQ(nullIt, info.gridMatrix_.end()); +} } // namespace OHOS::Ace::NG -- Gitee From c3a0fcb5f41acf24f81259c4f351231eff459df8 Mon Sep 17 00:00:00 2001 From: Tianer Zhou Date: Thu, 1 Feb 2024 11:59:31 +0800 Subject: [PATCH 4/5] fix finding end index Signed-off-by: Tianer Zhou Change-Id: Ie19b197946a25dc8c620018840bd73cd36e2d744 --- .../pattern/grid/grid_layout_info.cpp | 26 ++++------------- .../pattern/grid/grid_layout_info.h | 11 +++----- .../grid_scroll_layout_algorithm.cpp | 6 ++-- .../irregular/grid_layout_range_solver.cpp | 25 ++++++++--------- .../grid/irregular/grid_layout_range_solver.h | 12 ++++++-- .../grid/grid_irregular_layout_test.cpp | 28 +++++++++++++++++++ .../core/pattern/grid/irregular_matrics.cpp | 8 +++--- 7 files changed, 67 insertions(+), 49 deletions(-) diff --git a/frameworks/core/components_ng/pattern/grid/grid_layout_info.cpp b/frameworks/core/components_ng/pattern/grid/grid_layout_info.cpp index 60ed2c1df49..a3264b71267 100644 --- a/frameworks/core/components_ng/pattern/grid/grid_layout_info.cpp +++ b/frameworks/core/components_ng/pattern/grid/grid_layout_info.cpp @@ -517,33 +517,19 @@ iter GridLayoutInfo::FindInMatrix(int32_t index) const return gridMatrix_.end(); } -void GridLayoutInfo::ClearHeightsToEnd(int32_t idx) +void GridLayoutInfo::ClearMapsToEnd(int32_t idx) { + auto gridIt = gridMatrix_.lower_bound(idx); + gridMatrix_.erase(gridIt, gridMatrix_.end()); auto lineIt = lineHeightMap_.lower_bound(idx); lineHeightMap_.erase(lineIt, lineHeightMap_.end()); } -void GridLayoutInfo::ClearHeightsFromStart(int32_t idx) +void GridLayoutInfo::ClearMapsFromStart(int32_t idx) { + auto gridIt = gridMatrix_.lower_bound(idx); + gridMatrix_.erase(gridMatrix_.begin(), gridIt); auto lineIt = lineHeightMap_.lower_bound(idx); lineHeightMap_.erase(lineHeightMap_.begin(), lineIt); } - -void GridLayoutInfo::ClearMatrixToEnd(int32_t idx, int32_t lineIdx) -{ - auto it = gridMatrix_.find(lineIdx); - for (; it != gridMatrix_.end(); ++it) { - for (auto itemIt = it->second.begin(); itemIt != it->second.end();) { - if (std::abs(itemIt->second) < idx) { - ++itemIt; - continue; - } - itemIt = it->second.erase(itemIt); - } - if (it->second.empty()) { - break; - } - } - gridMatrix_.erase(it, gridMatrix_.end()); -} } // namespace OHOS::Ace::NG \ No newline at end of file diff --git a/frameworks/core/components_ng/pattern/grid/grid_layout_info.h b/frameworks/core/components_ng/pattern/grid/grid_layout_info.h index 404f226db62..4e1da6cac2e 100644 --- a/frameworks/core/components_ng/pattern/grid/grid_layout_info.h +++ b/frameworks/core/components_ng/pattern/grid/grid_layout_info.h @@ -105,7 +105,6 @@ struct GridLayoutInfo { return (removeLastGap) ? totalHeight - mainGap : totalHeight; } - /** * Checks if the item at the specified index is partially or fully above the viewport. * @@ -147,20 +146,18 @@ struct GridLayoutInfo { std::pair FindItemInRange(int32_t target) const; /** - * @brief clears lineHeightMap_ starting from line [idx] + * @brief clears gridMatrix_ and lineHeightMap_ starting from line [idx] * * @param idx starting line index */ - void ClearHeightsToEnd(int32_t idx); + void ClearMapsToEnd(int32_t idx); /** - * @brief clears lineHeightMap_ in range [0, idx) + * @brief clears gridMatrix_ and lineHeightMap_ in range [0, idx) * * @param idx ending line index, exclusive. */ - void ClearHeightsFromStart(int32_t idx); - - void ClearMatrixToEnd(int32_t idx, int32_t lineIdx); + void ClearMapsFromStart(int32_t idx); void ResetPositionFlags() { diff --git a/frameworks/core/components_ng/pattern/grid/grid_scroll/grid_scroll_layout_algorithm.cpp b/frameworks/core/components_ng/pattern/grid/grid_scroll/grid_scroll_layout_algorithm.cpp index 23606dcd155..b7c4530257f 100644 --- a/frameworks/core/components_ng/pattern/grid/grid_scroll/grid_scroll_layout_algorithm.cpp +++ b/frameworks/core/components_ng/pattern/grid/grid_scroll/grid_scroll_layout_algorithm.cpp @@ -1103,9 +1103,9 @@ bool GridScrollLayoutAlgorithm::UseCurrentLines( gridLayoutInfo_.offsetEnd_ = false; } if (!cacheValid) { - info.ClearHeightsToEnd(info.endMainLineIndex_ + 1); - // run out of record, startMainLineIndex is larger by 1 than real start main line index, so reduce 1 - info.ClearHeightsFromStart(info.startMainLineIndex_ > info.endMainLineIndex_ ? info.startMainLineIndex_ - 1 + info.ClearMapsToEnd(info.endMainLineIndex_ + 1); + // run out of reord, startMainLineIndex is larger by 1 than real start main line index, so reduce 1 + info.ClearMapsFromStart(info.startMainLineIndex_ > info.endMainLineIndex_ ? info.startMainLineIndex_ - 1 : info.startMainLineIndex_); } return runOutOfRecord; diff --git a/frameworks/core/components_ng/pattern/grid/irregular/grid_layout_range_solver.cpp b/frameworks/core/components_ng/pattern/grid/irregular/grid_layout_range_solver.cpp index dcafcaf63fe..c77df5b628e 100644 --- a/frameworks/core/components_ng/pattern/grid/irregular/grid_layout_range_solver.cpp +++ b/frameworks/core/components_ng/pattern/grid/irregular/grid_layout_range_solver.cpp @@ -63,12 +63,7 @@ GridLayoutRangeSolver::RangeInfo GridLayoutRangeSolver::FindRangeOnJump(int32_t } case ScrollAlign::END: { auto res = SolveBackward(mainGap, mainSize - info_->lineHeightMap_.at(jumpLineIdx), jumpLineIdx); - int32_t endIdx = 0; - const auto& lastRow = info_->gridMatrix_.at(jumpLineIdx); - for (auto it = lastRow.rbegin(); it != lastRow.rend(); ++it) { - endIdx = std::max(endIdx, std::abs(it->second)); - } - return { res.row, res.pos, jumpLineIdx, endIdx }; + return { res.row, res.pos, jumpLineIdx, FindEndIdx(jumpLineIdx) }; } default: return {}; @@ -126,23 +121,27 @@ std::pair GridLayoutRangeSolver::AddNextRows(float mainGap, int3 return { rowCnt, len }; } -std::pair GridLayoutRangeSolver::SolveForwardForEndIdx(float mainGap, float targetLen, int32_t idx) +std::pair GridLayoutRangeSolver::SolveForwardForEndIdx(float mainGap, float targetLen, int32_t line) { float len = 0.0f; - while (len < targetLen && idx <= info_->lineHeightMap_.rbegin()->first) { - len += info_->lineHeightMap_.at(idx++) + mainGap; + while (len < targetLen && line <= info_->lineHeightMap_.rbegin()->first) { + len += info_->lineHeightMap_.at(line++) + mainGap; } - --idx; + --line; + return { line, FindEndIdx(line) }; +} - for (int r = idx; r >= 0; --r) { +int32_t GridLayoutRangeSolver::FindEndIdx(int32_t endLine) +{ + for (int r = endLine; r >= 0; --r) { const auto& row = info_->gridMatrix_.at(r); for (auto it = row.rbegin(); it != row.rend(); ++it) { if (it->second > 0) { - return { idx, it->second }; + return it->second; } } } - return { 0, 0 }; + return 0; } Result GridLayoutRangeSolver::SolveBackward(float mainGap, float targetLen, int32_t idx) diff --git a/frameworks/core/components_ng/pattern/grid/irregular/grid_layout_range_solver.h b/frameworks/core/components_ng/pattern/grid/irregular/grid_layout_range_solver.h index bff31fa75d9..6e63ad5cd7e 100644 --- a/frameworks/core/components_ng/pattern/grid/irregular/grid_layout_range_solver.h +++ b/frameworks/core/components_ng/pattern/grid/irregular/grid_layout_range_solver.h @@ -76,10 +76,18 @@ private: * * @param mainGap The main gap between grid items. * @param targetLen The target length for the forward traversal. - * @param idx The starting line index. + * @param line The starting line index. * @return { ending line index, ending GridItem index } */ - std::pair SolveForwardForEndIdx(float mainGap, float targetLen, int32_t idx); + std::pair SolveForwardForEndIdx(float mainGap, float targetLen, int32_t line); + + /** + * @brief Traverse the matrix backward to find the last item index, starting from Line [endLine]. + * + * @param endLine index of the line to start traversing. + * @return last item index above endLine (inclusive) + */ + int32_t FindEndIdx(int32_t endLine); /** * @brief Adds the next rows to the layout in SolveForward. diff --git a/test/unittest/core/pattern/grid/grid_irregular_layout_test.cpp b/test/unittest/core/pattern/grid/grid_irregular_layout_test.cpp index 15508b00afb..28d2c6f0511 100644 --- a/test/unittest/core/pattern/grid/grid_irregular_layout_test.cpp +++ b/test/unittest/core/pattern/grid/grid_irregular_layout_test.cpp @@ -948,6 +948,34 @@ HWTEST_F(GridIrregularLayoutTest, FindRangeOnJump001, TestSize.Level1) EXPECT_EQ(res.endRow, 4); } +/** + * @tc.name: GridIrregularLayout::FindRangeOnJump002 + * @tc.desc: Test GridLayoutRangeFinder::FindRangeOnJump special endIndex (endIndex not on the last line). + * @tc.type: FUNC + */ +HWTEST_F(GridIrregularLayoutTest, FindRangeOnJump002, TestSize.Level1) +{ + GridLayoutInfo info; + info.crossCount_ = 3; + info.lineHeightMap_ = { { 0, 50.0f }, { 1, 100.0f }, { 2, 50.0f }, { 3, 50.0f }, { 4, 80.0f }, { 5, 75.0f } }; + info.gridMatrix_ = MATRIX_DEMO_8; + + Create([](GridModelNG model) { + model.SetColumnsTemplate("1fr 1fr 1fr"); + model.SetLayoutOptions(GetOptionDemo8()); + }); + frameNode_->GetGeometryNode()->SetContentSize({ 500.0f, 250.0f }); + + GridLayoutRangeSolver solver(&info, AceType::RawPtr(frameNode_)); + + info.scrollAlign_ = ScrollAlign::END; + auto res = solver.FindRangeOnJump(5, 5.0f); + EXPECT_EQ(res.startRow, 1); + EXPECT_EQ(res.pos, -125.0f); + EXPECT_EQ(res.endIdx, 6); + EXPECT_EQ(res.endRow, 5); +} + /** * @tc.name: GridIrregularLayout::SolveForwardForEndIdx001 * @tc.desc: Test GridLayoutRangeFinder::SolveForwardForEndIdx diff --git a/test/unittest/core/pattern/grid/irregular_matrics.cpp b/test/unittest/core/pattern/grid/irregular_matrics.cpp index 245d65ae30a..ccd8fe54395 100644 --- a/test/unittest/core/pattern/grid/irregular_matrics.cpp +++ b/test/unittest/core/pattern/grid/irregular_matrics.cpp @@ -13,10 +13,10 @@ * limitations under the License. */ - #include "irregular_matrices.h" +#include "irregular_matrices.h" - namespace OHOS::Ace::NG { - GridLayoutOptions GetOptionDemo1() +namespace OHOS::Ace::NG { +GridLayoutOptions GetOptionDemo1() { GridLayoutOptions option; option.irregularIndexes = { @@ -170,4 +170,4 @@ GridLayoutOptions GetOptionDemo11() option.getSizeByIndex = std::move(onGetIrregularSizeByIndex); return option; } - } \ No newline at end of file +} // namespace OHOS::Ace::NG \ No newline at end of file -- Gitee From 265ea412f10c137214821f99416c9b3b1b5c12a2 Mon Sep 17 00:00:00 2001 From: Tianer Zhou Date: Thu, 1 Feb 2024 17:18:02 +0800 Subject: [PATCH 5/5] review fix Signed-off-by: Tianer Zhou Change-Id: I15cfa62c2e09345232b249236c7184a6e5866b0c --- .../core/components_ng/pattern/grid/grid_layout_info.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/frameworks/core/components_ng/pattern/grid/grid_layout_info.cpp b/frameworks/core/components_ng/pattern/grid/grid_layout_info.cpp index a3264b71267..933d2d79afc 100644 --- a/frameworks/core/components_ng/pattern/grid/grid_layout_info.cpp +++ b/frameworks/core/components_ng/pattern/grid/grid_layout_info.cpp @@ -483,10 +483,10 @@ bool CheckRow(int32_t& maxV, const std::map& row, int32_t target) return false; } -using iter = decltype(GridLayoutInfo::gridMatrix_)::const_iterator; +using MatIter = decltype(GridLayoutInfo::gridMatrix_)::const_iterator; } // namespace -iter GridLayoutInfo::FindInMatrix(int32_t index) const +MatIter GridLayoutInfo::FindInMatrix(int32_t index) const { if (index == 0) { return gridMatrix_.begin(); -- Gitee