• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2022-2023 Huawei Device Co., Ltd.
3  * Licensed under the Apache License, Version 2.0 (the "License");
4  * you may not use this file except in compliance with the License.
5  * You may obtain a copy of the License at
6  *
7  *     http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software
10  * distributed under the License is distributed on an "AS IS" BASIS,
11  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12  * See the License for the specific language governing permissions and
13  * limitations under the License.
14  */
15 
16 #include "core/components_ng/syntax/lazy_layout_wrapper_builder.h"
17 
18 namespace OHOS::Ace::NG {
19 
LazyLayoutWrapperBuilder(const RefPtr<LazyForEachBuilder> & builder,const WeakPtr<LazyForEachNode> & host)20 LazyLayoutWrapperBuilder::LazyLayoutWrapperBuilder(
21     const RefPtr<LazyForEachBuilder>& builder, const WeakPtr<LazyForEachNode>& host)
22     : builder_(builder), host_(host)
23 {}
24 
SwapDirtyAndUpdateBuildCache()25 void LazyLayoutWrapperBuilder::SwapDirtyAndUpdateBuildCache() {}
26 
AdjustGridOffset()27 void LazyLayoutWrapperBuilder::AdjustGridOffset()
28 {
29     for (const auto& wrapper : childWrappers_) {
30         auto frameNode = wrapper->GetHostNode();
31         CHECK_NULL_VOID(frameNode);
32         frameNode->AdjustGridOffset();
33     }
34 }
35 
OnGetTotalCount()36 int32_t LazyLayoutWrapperBuilder::OnGetTotalCount()
37 {
38     CHECK_NULL_RETURN(builder_, 0);
39     return builder_->GetTotalCount();
40 }
41 
OnGetOrCreateWrapperByIndex(int32_t index)42 RefPtr<LayoutWrapper> LazyLayoutWrapperBuilder::OnGetOrCreateWrapperByIndex(int32_t index)
43 {
44     auto totalCount = GetTotalCount();
45     if ((index < 0) || (index >= totalCount)) {
46         LOGE("index is illegal: %{public}d", index);
47         return nullptr;
48     }
49     // check if the index needs to be converted to virtual index.
50     if (lazySwiper_ &&
51         ((startIndex_ && index < startIndex_.value() - 1) || (endIndex_ && index > endIndex_.value() + 1))) {
52         if (index > startIndex_.value()) {
53             index -= totalCount;
54         } else {
55             index += totalCount;
56         }
57     }
58     return OnGetOrCreateWrapperByIndexLegacy(index);
59 }
60 
GetOrCreateFrameNode(int32_t index,int32_t totalCount)61 std::pair<RefPtr<UINode>, std::string> LazyLayoutWrapperBuilder::GetOrCreateFrameNode(int32_t index, int32_t totalCount)
62 {
63     RefPtr<UINode> uiNode;
64     std::string id;
65     // get frame node from previous cached.
66     if ((index >= preStartIndex_) && (index <= preEndIndex_)) {
67         auto iter = preNodeIds_.begin();
68         std::advance(iter, index - preStartIndex_);
69         if ((iter != preNodeIds_.end()) && (iter->has_value())) {
70             id = iter->value();
71             uiNode = builder_->GetChildByKey(id);
72         }
73     }
74     if (!uiNode) {
75         // convert index to real index.
76         int32_t realIndex = index;
77         if (lazySwiper_) {
78             if (index >= totalCount) {
79                 realIndex -= totalCount;
80             } else if (index < 0) {
81                 realIndex += totalCount;
82             }
83         }
84         // create frame node.
85         auto itemInfo = builder_->GetChildByIndex(realIndex, true);
86         id = itemInfo.first;
87         uiNode = itemInfo.second;
88     }
89     return std::pair(uiNode, id);
90 }
91 
OnGetOrCreateWrapperByIndexLegacy(int32_t index)92 RefPtr<LayoutWrapper> LazyLayoutWrapperBuilder::OnGetOrCreateWrapperByIndexLegacy(int32_t index)
93 {
94     int32_t totalCount = GetTotalCount();
95     // The first time get the item, do not do the range check, and the subsequent get the item
96     // needs to check whether it is in the upper and lower bounds (-1, +1) of the existing index.
97     if (!startIndex_) {
98         startIndex_ = index;
99         endIndex_ = index;
100     } else {
101         if ((index >= startIndex_.value()) && (index <= endIndex_.value())) {
102             auto iter = childWrappers_.begin();
103             std::advance(iter, index - startIndex_.value());
104             return *iter;
105         }
106         if ((index < (startIndex_.value() - 1)) || (index > (endIndex_.value() + 1))) {
107             LOGE("need to obtain the item node in order and by step one: %{public}d", index);
108             return nullptr;
109         }
110     }
111 
112     CHECK_NULL_RETURN(builder_, nullptr);
113     const std::pair<RefPtr<UINode>, std::string>& pair = GetOrCreateFrameNode(index, totalCount);
114     RefPtr<UINode> uiNode = pair.first;
115     std::string id = pair.second;
116     CHECK_NULL_RETURN(uiNode, nullptr);
117     RefPtr<LayoutWrapper> wrapper;
118     auto frameNode = DynamicCast<FrameNode>(uiNode);
119     if (frameNode) {
120         wrapper = frameNode->CreateLayoutWrapper(forceMeasure_, forceLayout_);
121     } else {
122         wrapper = uiNode->CreateLayoutWrapper(forceMeasure_, forceLayout_);
123     }
124     CHECK_NULL_RETURN(wrapper, nullptr);
125     if (index == (startIndex_.value() - 1)) {
126         // insert at begin.
127         startIndex_ = index;
128         childWrappers_.emplace_front(wrapper);
129         nodeIds_.emplace_front(id);
130         return wrapper;
131     }
132     // insert at end.
133     endIndex_ = index;
134     childWrappers_.emplace_back(wrapper);
135     nodeIds_.emplace_back(id);
136     return wrapper;
137 }
138 
GetCachedChildLayoutWrapper()139 const std::list<RefPtr<LayoutWrapper>>& LazyLayoutWrapperBuilder::GetCachedChildLayoutWrapper()
140 {
141     return childWrappers_;
142 }
143 
OnExpandChildLayoutWrapper()144 const std::list<RefPtr<LayoutWrapper>>& LazyLayoutWrapperBuilder::OnExpandChildLayoutWrapper()
145 {
146     auto total = GetTotalCount();
147     if (!childWrappers_.empty()) {
148         if (static_cast<int32_t>(childWrappers_.size()) == total) {
149             return childWrappers_;
150         }
151         LOGE("can not mix lazy get and full get method!");
152         childWrappers_.clear();
153         return childWrappers_;
154     }
155 
156     CHECK_NULL_RETURN(builder_, childWrappers_);
157     for (int32_t index = 0; index < total; ++index) {
158         auto itemInfo = builder_->GetChildByIndex(index, true);
159         RefPtr<LayoutWrapper> wrapper;
160         auto frameNode = DynamicCast<FrameNode>(itemInfo.second);
161         auto uiNode = itemInfo.second;
162         if (frameNode) {
163             wrapper = frameNode->CreateLayoutWrapper(forceMeasure_, forceLayout_);
164         } else if (uiNode) {
165             wrapper = uiNode->CreateLayoutWrapper(forceMeasure_, forceLayout_);
166         }
167         if (!wrapper) {
168             LOGE("fail to create wrapper");
169             childWrappers_.clear();
170             return childWrappers_;
171         }
172         nodeIds_.emplace_back(itemInfo.first);
173         childWrappers_.emplace_back(wrapper);
174     }
175     startIndex_ = 0;
176     endIndex_ = total - 1;
177     return childWrappers_;
178 }
179 
GetKeyByIndexFromPreNodes(int32_t index)180 std::optional<std::string> LazyLayoutWrapperBuilder::GetKeyByIndexFromPreNodes(int32_t index)
181 {
182     if ((index >= preStartIndex_) && (index <= preEndIndex_)) {
183         auto iter = preNodeIds_.begin();
184         std::advance(iter, index - preStartIndex_);
185         if ((iter != preNodeIds_.end()) && (iter->has_value())) {
186             return iter->value();
187         }
188     }
189     return std::nullopt;
190 }
191 
192 } // namespace OHOS::Ace::NG
193