1 /*
2  * Copyright (c) 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 #ifndef FOUNDATION_ACE_FRAMEWORKS_CORE_COMPONENTS_NG_PATTERNS_LIST_LIST_DIVIDER_ARITHMETIC_H
17 #define FOUNDATION_ACE_FRAMEWORKS_CORE_COMPONENTS_NG_PATTERNS_LIST_LIST_DIVIDER_ARITHMETIC_H
18 
19 #include "core/components_ng/animation/animatable_arithmetic.h"
20 
21 namespace OHOS::Ace::NG {
22 using OHOS::Ace::NG::CustomAnimatableArithmetic;
23 struct ListDivider {
24     bool isDelta = true;
25     OffsetF offset;
26     float length = 0.0f;
27 };
28 using ListDividerMap = std::map<int32_t, ListDivider>;
29 
30 class RefDividerMap : public AceType {
31     DECLARE_ACE_TYPE(RefDividerMap, AceType);
32 public:
SetMap(const ListDividerMap & map)33     void SetMap(const ListDividerMap& map)
34     {
35         refMap_ = map;
36         for (auto& div : refMap_) {
37             div.second.isDelta = false;
38         }
39     }
GetMap()40     const ListDividerMap& GetMap() const
41     {
42         return  refMap_;
43     }
44 private:
45     ListDividerMap refMap_;
46 };
47 
48 class ListDividerArithmetic : public CustomAnimatableArithmetic {
49     DECLARE_ACE_TYPE(ListDividerArithmetic, CustomAnimatableArithmetic);
50 public:
51     ListDividerArithmetic() = default;
52     ~ListDividerArithmetic() override = default;
53 
ListDividerArithmetic(const ListDividerMap & dividerMap,RefPtr<RefDividerMap> ref)54     ListDividerArithmetic(const ListDividerMap& dividerMap, RefPtr<RefDividerMap> ref)
55         : dividermap_(dividerMap), refDivider_(ref) {}
56 
Add(const RefPtr<CustomAnimatableArithmetic> & value)57     RefPtr<CustomAnimatableArithmetic> Add(const RefPtr<CustomAnimatableArithmetic>& value) const override
58     {
59         return Calculate(value, true);
60     }
61 
Minus(const RefPtr<CustomAnimatableArithmetic> & value)62     RefPtr<CustomAnimatableArithmetic> Minus(const RefPtr<CustomAnimatableArithmetic>& value) const override
63     {
64         return Calculate(value, false);
65     }
66 
Multiply(const float scale)67     RefPtr<CustomAnimatableArithmetic> Multiply(const float scale) const override
68     {
69         if (!refDivider_) {
70             return {};
71         }
72         ListDividerMap result;
73         for (const auto& child : refDivider_->GetMap()) {
74             auto it = dividermap_.find(child.first);
75             if (it == dividermap_.end() || !it->second.isDelta) {
76                 result.emplace(child.first, child.second);
77                 continue;
78             }
79             ListDivider divider = {
80                 .isDelta = true,
81                 .offset = it->second.offset * scale,
82                 .length = it->second.length * scale,
83             };
84             result.emplace(child.first, divider);
85         }
86         return MakeRefPtr<ListDividerArithmetic>(result, refDivider_);
87     }
88 
IsEqual(const RefPtr<CustomAnimatableArithmetic> & value)89     bool IsEqual(const RefPtr<CustomAnimatableArithmetic>& value) const override
90     {
91         RefPtr<ListDividerArithmetic> rhs = AceType::DynamicCast<ListDividerArithmetic>(value);
92         if (!rhs) {
93             return false;
94         }
95         const ListDividerMap& another = rhs->GetDividerMap();
96         if (another.size() != dividermap_.size()) {
97             return false;
98         }
99         for (const auto& child : dividermap_) {
100             auto it = another.find(child.first);
101             if (it == another.end() || it->second.offset != child.second.offset ||
102                 it->second.length != child.second.length) {
103                 return false;
104             }
105         }
106         return true;
107     }
108 
GetDividerMap()109     ListDividerMap GetDividerMap() const
110     {
111         return dividermap_;
112     }
113 
114 private:
Calculate(const RefPtr<CustomAnimatableArithmetic> & value,bool isAdd)115     RefPtr<CustomAnimatableArithmetic> Calculate(const RefPtr<CustomAnimatableArithmetic>& value, bool isAdd) const
116     {
117         if (!refDivider_) {
118             return {};
119         }
120         RefPtr<ListDividerArithmetic> rhs = AceType::DynamicCast<ListDividerArithmetic>(value);
121         if (!rhs) {
122             return {};
123         }
124         const ListDividerMap& another = rhs->GetDividerMap();
125         ListDividerMap result;
126         for (const auto& child : refDivider_->GetMap()) {
127             auto it1 = dividermap_.find(child.first);
128             if (it1 == dividermap_.end() || !it1->second.isDelta) {
129                 result.emplace(child.first, child.second);
130                 continue;
131             }
132             auto it2 = another.find(child.first);
133             if (it2 == another.end() || !it2->second.isDelta) {
134                 result.emplace(child.first, child.second);
135                 continue;
136             }
137             if (isAdd) {
138                 ListDivider divider = {
139                     .isDelta = true,
140                     .offset = it1->second.offset + it2->second.offset,
141                     .length = it1->second.length + it2->second.length,
142                 };
143                 result.emplace(child.first, divider);
144             } else {
145                 ListDivider divider = {
146                     .isDelta = true,
147                     .offset = it1->second.offset - it2->second.offset,
148                     .length = it1->second.length - it2->second.length,
149                 };
150                 result.emplace(child.first, divider);
151             }
152         }
153         return MakeRefPtr<ListDividerArithmetic>(result, refDivider_);
154     }
155     ListDividerMap dividermap_;
156     RefPtr<RefDividerMap> refDivider_;
157 
158     ACE_DISALLOW_COPY_AND_MOVE(ListDividerArithmetic);
159 };
160 } // namespace OHOS::Ace::NG
161 
162 #endif // FOUNDATION_ACE_FRAMEWORKS_CORE_COMPONENTS_NG_PATTERNS_LIST_LIST_DIVIDER_ARITHMETIC_H
163