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