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
16 #include "frameworks/core/components_ng/pattern/waterflow/water_flow_sections.h"
17
18 namespace OHOS::Ace::NG {
19 // push: start, 0, newSection
20 // update: start, 0, newSection
21 // splice: start, deleteCount, newSections
ChangeData(size_t start,size_t deleteCount,const std::vector<WaterFlowSections::Section> & newSections)22 void WaterFlowSections::ChangeData(
23 size_t start, size_t deleteCount, const std::vector<WaterFlowSections::Section>& newSections)
24 {
25 start = std::min(start, sections_.size());
26 deleteCount = std::min(deleteCount, sections_.size() - start);
27 prevSections_ = sections_;
28
29 TAG_LOGI(AceLogTag::ACE_WATERFLOW,
30 "section changed, start:%{public}zu, deleteCount:%{public}zu, newSections:%{public}zu", start, deleteCount,
31 newSections.size());
32 NotifySectionChange(start, deleteCount, newSections);
33
34 if (start < sections_.size()) {
35 auto it = sections_.begin() + static_cast<int32_t>(start);
36 sections_.erase(it, it + static_cast<int32_t>(deleteCount));
37 sections_.insert(it, newSections.begin(), newSections.end());
38 } else {
39 sections_.insert(sections_.end(), newSections.begin(), newSections.end());
40 }
41
42 // perform diff to get actual [start]
43 for (; start < sections_.size(); ++start) {
44 if (start >= prevSections_.size()) {
45 break;
46 }
47 if (sections_[start] != prevSections_[start]) {
48 // can skip re-init the first modified section with only an itemCount diff
49 // to optimize the common scenario when developers add/remove items at the end
50 if (sections_[start].OnlyCountDiff(prevSections_[start])) {
51 ++start;
52 }
53 break;
54 }
55 }
56
57 if (onSectionDataChange_) {
58 onSectionDataChange_(static_cast<int32_t>(start));
59 }
60 }
61
ReplaceFrom(size_t start,const std::vector<WaterFlowSections::Section> & newSections)62 void WaterFlowSections::ReplaceFrom(size_t start, const std::vector<WaterFlowSections::Section>& newSections)
63 {
64 ChangeData(start, sections_.size(), newSections);
65 }
66
NotifySectionChange(int32_t start,int32_t deleteCount,const std::vector<WaterFlowSections::Section> & newSections)67 void WaterFlowSections::NotifySectionChange(
68 int32_t start, int32_t deleteCount, const std::vector<WaterFlowSections::Section>& newSections)
69 {
70 if (deleteCount == 1 && newSections.size() == 1) {
71 return;
72 }
73 int32_t addItemCount = 0;
74 int32_t n = static_cast<int32_t>(sections_.size());
75 for (int32_t i = 0; i < static_cast<int32_t>(newSections.size()) - 1; i++) {
76 addItemCount += newSections[i].itemsCount;
77 }
78 int32_t deleteItemCount = 0;
79 for (int32_t i = start; i < std::min(start + deleteCount - 1, n); i++) {
80 deleteItemCount += sections_[i].itemsCount;
81 }
82 int32_t itemCount = 0;
83 for (int32_t i = 0; i < std::min(start, n); i++) {
84 itemCount += sections_[i].itemsCount;
85 }
86 if (notifyDataChange_) {
87 notifyDataChange_(itemCount + std::max(addItemCount, deleteItemCount), 0);
88 }
89 }
90 } // namespace OHOS::Ace::NG
91