1 /*
2  * Copyright (c) 2024 Huawei Device Co., Ltd.
3  * Licensed under the Apache License, Version 2.0 (the "License");
4  * you may not use this file except in compliance with the License.
5  * You may obtain a copy of the License at
6  *
7  *     http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software
10  * distributed under the License is distributed on an "AS IS" BASIS,
11  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12  * See the License for the specific language governing permissions and
13  * limitations under the License.
14  */
15 #include "core/components_ng/pattern/grid/irregular/grid_layout_utils.h"
16 
17 #include "core/components_ng/pattern/grid/grid_layout_info.h"
18 #include "core/components_ng/pattern/grid/grid_layout_property.h"
19 #include "core/components_ng/pattern/grid/grid_pattern.h"
20 
21 namespace OHOS::Ace::NG {
GetItemSize(const GridLayoutInfo * info,const LayoutWrapper * wrapper,int32_t idx)22 GridItemSize GridLayoutUtils::GetItemSize(const GridLayoutInfo* info, const LayoutWrapper* wrapper, int32_t idx)
23 {
24     GridItemSize size { 1, 1 };
25     auto props = AceType::DynamicCast<GridLayoutProperty>(wrapper->GetLayoutProperty());
26     const auto& opts = *props->GetLayoutOptions();
27     if (opts.irregularIndexes.find(idx) != opts.irregularIndexes.end()) {
28         if (!opts.getSizeByIndex) {
29             // default irregular size = [1, full cross length]
30             size.rows = 1;
31             size.columns = info->crossCount_;
32         } else {
33             size = opts.getSizeByIndex(idx);
34             // assume [row] represents mainLength and [column] represents crossLength in this class, so flip sides if
35             // horizontal
36             if (info->axis_ == Axis::HORIZONTAL) {
37                 std::swap(size.rows, size.columns);
38             }
39         }
40     }
41 
42     // handle illegal size
43     if (size.columns > info->crossCount_) {
44         size.columns = info->crossCount_;
45     }
46     size.columns = std::max(1, size.columns);
47     size.rows = std::max(1, size.rows);
48     return size;
49 }
50 
PreloadGridItems(const RefPtr<GridPattern> & pattern,std::list<GridPreloadItem> && items,const BuildGridItemCallback & buildCb)51 void GridLayoutUtils::PreloadGridItems(
52     const RefPtr<GridPattern>& pattern, std::list<GridPreloadItem>&& items, const BuildGridItemCallback& buildCb)
53 {
54     if (items.empty()) {
55         return;
56     }
57     CHECK_NULL_VOID(pattern);
58     const bool taskAdded = pattern->HasPreloadItemList();
59     pattern->SetPreloadItemList(std::move(items));
60     if (taskAdded) {
61         // task already in queue, only need to update item list
62         return;
63     }
64     PreloadGridItemsHelper(pattern, buildCb);
65 }
66 
PreloadGridItemsHelper(const RefPtr<GridPattern> & pattern,const BuildGridItemCallback & buildCb)67 void GridLayoutUtils::PreloadGridItemsHelper(const RefPtr<GridPattern>& pattern, const BuildGridItemCallback& buildCb)
68 {
69     auto context = PipelineContext::GetCurrentContextSafely();
70     CHECK_NULL_VOID(context);
71     context->AddPredictTask([weak = AceType::WeakClaim(AceType::RawPtr(pattern)), buildCb](int64_t deadline, bool _) {
72         ACE_SCOPED_TRACE("Grid preload items");
73         auto pattern = weak.Upgrade();
74         CHECK_NULL_VOID(pattern);
75         const auto items = pattern->MovePreloadItemList();
76         if (items.empty()) {
77             return;
78         }
79         auto it = items.begin();
80         if (pattern->IsPredictOutOfRange(it->idx)) {
81             return;
82         }
83         bool needMarkDirty = false;
84         auto host = pattern->GetHost();
85         CHECK_NULL_VOID(host);
86         for (; it != items.end(); ++it) {
87             if (GetSysTimestamp() > deadline) {
88                 break;
89             }
90             if (it->buildOnly) {
91                 host->GetOrCreateChildByIndex(it->idx, false, true);
92                 continue;
93             }
94             if (buildCb) {
95                 needMarkDirty = buildCb(host, it->idx) || needMarkDirty;
96             }
97         }
98         if (needMarkDirty) {
99             host->MarkDirtyNode(PROPERTY_UPDATE_MEASURE_SELF);
100         }
101         if (it != items.end() && !needMarkDirty) {
102             pattern->SetPreloadItemList(std::list<GridPreloadItem>(it, items.end()));
103             PreloadGridItemsHelper(pattern, buildCb);
104         } else {
105             pattern->SetPreloadItemList({});
106         }
107     });
108 }
109 } // namespace OHOS::Ace::NG
110