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