1 /* 2 * Copyright (c) 2021-2022 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_THEME_THEME_STYLE_H 17 #define FOUNDATION_ACE_FRAMEWORKS_CORE_COMPONENTS_THEME_THEME_STYLE_H 18 19 #include <string> 20 #include <type_traits> 21 #include <unordered_map> 22 #include <variant> 23 #include <future> 24 #include <mutex> 25 #include <shared_mutex> 26 27 #include "base/geometry/dimension.h" 28 #include "base/log/log.h" 29 #include "base/memory/ace_type.h" 30 #include "base/resource/internal_resource.h" 31 #include "core/components/common/properties/color.h" 32 #include "core/components/theme/theme_utils.h" 33 34 namespace OHOS::Ace { 35 36 class ThemeStyle; 37 class ThemeUtils; 38 class StateResource; 39 40 using ResRawValue = std::variant<Color, Dimension, int32_t, uint32_t, double, InternalResource::ResourceId, std::string, 41 RefPtr<ThemeStyle>, RefPtr<StateResource>>; 42 using BlendAlpha = std::variant<double, uint32_t>; 43 44 enum class ThemeConstantsType { 45 // Error type for check if key is match with value 46 ERROR = -1, 47 COLOR = 0, 48 DIMENSION, 49 INT, 50 DOUBLE, 51 RESOURCE_ID, 52 REFERENCE, 53 REFERENCE_ATTR, 54 STRING, 55 PATTERN, 56 STATE_RESOURCE, 57 THEME, 58 }; 59 60 struct ResValueWrapper { 61 template<typename T> GetValueResValueWrapper62 std::pair<bool, T> GetValue(const T& errorValue) const 63 { 64 auto valuePtr = std::get_if<T>(&value); 65 if (!valuePtr) { 66 return std::make_pair(false, errorValue); 67 } 68 return std::make_pair(true, *valuePtr); 69 } 70 71 ThemeConstantsType type { ThemeConstantsType::COLOR }; 72 ResRawValue value; 73 // Whether style value is public to app. 74 bool isPublic { false }; 75 // Extra alpha needs to blend with color(uint means an ID reference, double means an alpha value). 76 BlendAlpha blendAlpha { 1.0 }; 77 }; 78 79 using ThemeConstantsMap = std::unordered_map<uint32_t, ResValueWrapper>; 80 81 class ThemeStyle : public virtual AceType { 82 DECLARE_ACE_TYPE(ThemeStyle, AceType); 83 84 private: 85 mutable std::shared_mutex attributesMutex_; 86 87 public: 88 ThemeStyle() = default; ~ThemeStyle()89 ~ThemeStyle() override 90 { 91 attributes_.clear(); 92 } 93 SetName(const std::string & name)94 void SetName(const std::string& name) 95 { 96 name_ = name; 97 } 98 GetName()99 std::string GetName() const 100 { 101 return name_; 102 } 103 ParseContent()104 virtual void ParseContent() {} 105 SetAttributes(const std::unordered_map<std::string,ResValueWrapper> & attributes)106 void SetAttributes(const std::unordered_map<std::string, ResValueWrapper>& attributes) 107 { 108 std::unique_lock<std::shared_mutex> lock(attributesMutex_); 109 attributes_ = attributes; 110 } 111 GetAttributes()112 const std::unordered_map<std::string, ResValueWrapper>& GetAttributes() const 113 { 114 std::shared_lock<std::shared_mutex> lock(attributesMutex_); 115 return attributes_; 116 } 117 HasAttr(const std::string & attr)118 bool HasAttr(const std::string& attr) const 119 { 120 std::shared_lock<std::shared_mutex> lock(attributesMutex_); 121 return attributes_.find(attr) != attributes_.end(); 122 } 123 SetAttr(const std::string & attr,const ResValueWrapper & value)124 void SetAttr(const std::string& attr, const ResValueWrapper& value) 125 { 126 std::unique_lock<std::shared_mutex> lock(attributesMutex_); 127 attributes_[attr] = value; 128 } CheckThemeStyleLoaded(const std::string & patternName)129 virtual void CheckThemeStyleLoaded(const std::string& patternName) {} 130 template<typename T> GetAttr(const std::string & attr,const T & errorValue)131 T GetAttr(const std::string& attr, const T& errorValue) const 132 { 133 std::shared_lock<std::shared_mutex> lock(attributesMutex_); 134 auto findIter = attributes_.find(attr); 135 if (findIter == attributes_.end()) { 136 TAG_LOGW(AceLogTag::ACE_THEME, "style %{public}s not contains %{public}s!", name_.c_str(), attr.c_str()); 137 return errorValue; 138 } 139 const auto& valueWrapper = findIter->second; 140 // parse attr reference. 141 if (valueWrapper.type == ThemeConstantsType::REFERENCE_ATTR) { 142 auto parent = parentStyle_.Upgrade(); 143 if (!parent) { 144 return errorValue; 145 } 146 auto parseResult = ThemeUtils::ParseThemeIdReference(valueWrapper.GetValue<std::string>("").second); 147 if (!parseResult.parseSuccess || parseResult.isIdRef) { 148 return errorValue; 149 } 150 return parent->GetAttr<T>(parseResult.refAttr, errorValue); 151 } 152 auto valuePair = valueWrapper.GetValue<T>(errorValue); 153 if (!valuePair.first) { 154 TAG_LOGW(AceLogTag::ACE_THEME, "style %{public}s get attr %{public}s error!", name_.c_str(), attr.c_str()); 155 } 156 return valuePair.second; 157 } 158 159 protected: 160 std::string name_; 161 std::unordered_map<std::string, ResValueWrapper> attributes_; 162 WeakPtr<ThemeStyle> parentStyle_; 163 }; 164 165 class StateResource : public virtual AceType { 166 DECLARE_ACE_TYPE(StateResource, AceType); 167 168 public: 169 StateResource() = default; 170 ~StateResource() override = default; 171 SetName(const std::string & name)172 void SetName(const std::string& name) 173 { 174 name_ = name; 175 } 176 SetStateValue(uint32_t state,const ResValueWrapper & value)177 void SetStateValue(uint32_t state, const ResValueWrapper& value) 178 { 179 states_[state] = value; 180 } 181 182 template<typename T> GetState(uint32_t state,const T & defaultValue)183 T GetState(uint32_t state, const T& defaultValue) const 184 { 185 auto findIter = states_.find(state); 186 if (findIter == states_.end()) { 187 return defaultValue; 188 } 189 auto valuePair = findIter->second.GetValue<T>(defaultValue); 190 if (!valuePair.first) { 191 TAG_LOGW(AceLogTag::ACE_THEME, "style %{public}s get state %{public}u error!", name_.c_str(), state); 192 } 193 return valuePair.second; 194 } 195 196 private: 197 std::string name_; 198 std::unordered_map<uint32_t, ResValueWrapper> states_; 199 }; 200 201 } // namespace OHOS::Ace 202 203 #endif // FOUNDATION_ACE_FRAMEWORKS_CORE_COMPONENTS_THEME_THEME_STYLE_H 204