1 /* 2 * Copyright (c) 2022-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_PROPERTIES_PROPERTY_H 17 #define FOUNDATION_ACE_FRAMEWORKS_CORE_COMPONENTS_NG_PROPERTIES_PROPERTY_H 18 19 #include <cstdint> 20 #include <optional> 21 22 #include "base/memory/ace_type.h" 23 #include "base/utils/macros.h" 24 #include "base/utils/noncopyable.h" 25 26 namespace OHOS::Ace::NG { 27 using PropertyChangeFlag = uint32_t; 28 29 inline constexpr PropertyChangeFlag PROPERTY_UPDATE_NORMAL = 0; 30 // Mark self, parent, children to remeasure. 31 inline constexpr PropertyChangeFlag PROPERTY_UPDATE_MEASURE = 1; 32 // Mark self to reLayout. 33 inline constexpr PropertyChangeFlag PROPERTY_UPDATE_LAYOUT = 1 << 1; 34 35 // Mark self to remeasure. 36 inline constexpr PropertyChangeFlag PROPERTY_UPDATE_MEASURE_SELF = 1 << 3; 37 38 // Mark self and parent to remeasure. 39 inline constexpr PropertyChangeFlag PROPERTY_UPDATE_MEASURE_SELF_AND_PARENT = 1 << 4; 40 41 // Mark self remeasure due to child size may change, which may mark parent, self and children to remeasure. 42 inline constexpr PropertyChangeFlag PROPERTY_UPDATE_BY_CHILD_REQUEST = 1 << 5; 43 44 inline constexpr PropertyChangeFlag PROPERTY_UPDATE_RENDER = 1 << 6; 45 inline constexpr PropertyChangeFlag PROPERTY_UPDATE_RENDER_BY_CHILD_REQUEST = 1 << 7; 46 47 inline constexpr PropertyChangeFlag PROPERTY_UPDATE_EVENT = 1 << 8; 48 49 inline constexpr PropertyChangeFlag PROPERTY_UPDATE_MEASURE_SELF_AND_CHILD = 1 << 9; 50 51 bool CheckNeedRender(PropertyChangeFlag propertyChangeFlag); 52 53 bool CheckNeedRequestMeasureAndLayout(PropertyChangeFlag propertyChangeFlag); 54 55 bool CheckNeedRequestParentMeasure(PropertyChangeFlag propertyChangeFlag); 56 57 bool CheckNeedMeasure(PropertyChangeFlag propertyChangeFlag); 58 59 bool CheckNeedLayout(PropertyChangeFlag propertyChangeFlag); 60 61 bool CheckMeasureFlag(PropertyChangeFlag propertyChangeFlag); 62 63 bool CheckForceParentMeasureFlag(PropertyChangeFlag propertyChangeFlag); 64 65 bool CheckLayoutFlag(PropertyChangeFlag propertyChangeFlag); 66 67 bool CheckMeasureSelfFlag(PropertyChangeFlag propertyChangeFlag); 68 69 bool CheckMeasureSelfAndParentFlag(PropertyChangeFlag propertyChangeFlag); 70 71 bool CheckMeasureSelfAndChildFlag(PropertyChangeFlag propertyChangeFlag); 72 73 bool CheckUpdateByChildRequest(PropertyChangeFlag propertyChangeFlag); 74 75 bool CheckNoChanged(PropertyChangeFlag propertyChangeFlag); 76 77 // For XXXProperty Class 78 #define ACE_DEFINE_PROPERTY_GROUP(group, type) \ 79 public: \ 80 const std::unique_ptr<type>& GetOrCreate##group() \ 81 { \ 82 if (!prop##group##_) { \ 83 prop##group##_ = std::make_unique<type>(); \ 84 } \ 85 return prop##group##_; \ 86 } \ 87 const std::unique_ptr<type>& Get##group() const \ 88 { \ 89 return prop##group##_; \ 90 } \ 91 std::unique_ptr<type> Clone##group() const \ 92 { \ 93 if (prop##group##_) { \ 94 return std::make_unique<type>(*prop##group##_); \ 95 } \ 96 return nullptr; \ 97 } \ 98 void Reset##group() \ 99 { \ 100 return prop##group##_.reset(); \ 101 } \ 102 \ 103 protected: \ 104 std::unique_ptr<type> prop##group##_; 105 106 #define ACE_DEFINE_PROPERTY_ITEM_WITH_GROUP_GET(group, name, type) \ 107 public: \ 108 std::optional<type> Get##name() const \ 109 { \ 110 auto& groupProperty = Get##group(); \ 111 if (groupProperty) { \ 112 return groupProperty->Get##name(); \ 113 } \ 114 return std::nullopt; \ 115 } \ 116 bool Has##name() const \ 117 { \ 118 auto& groupProperty = Get##group(); \ 119 if (groupProperty) { \ 120 return groupProperty->Has##name(); \ 121 } \ 122 return false; \ 123 } \ 124 type Get##name##Value(const type& defaultValue) const \ 125 { \ 126 auto& groupProperty = Get##group(); \ 127 if (groupProperty) { \ 128 if (groupProperty->Has##name()) { \ 129 return groupProperty->Get##name##Value(); \ 130 } \ 131 } \ 132 return defaultValue; \ 133 } \ 134 void Reset##name() \ 135 { \ 136 auto& groupProperty = Get##group(); \ 137 if (groupProperty) { \ 138 groupProperty->Reset##name(); \ 139 } \ 140 } 141 142 // For different members of the same type, such as the same foreground and background color types, but the interface 143 // names provided to the outside world need to be different. 144 #define ACE_DEFINE_PROPERTY_ITEM_WITH_GROUP_ITEM_GET(group, groupItem, name, type) \ 145 public: \ 146 std::optional<type> Get##name() const \ 147 { \ 148 auto& groupProperty = Get##group(); \ 149 if (groupProperty) { \ 150 return groupProperty->Get##groupItem(); \ 151 } \ 152 return std::nullopt; \ 153 } \ 154 bool Has##name() const \ 155 { \ 156 auto& groupProperty = Get##group(); \ 157 if (groupProperty) { \ 158 return groupProperty->Has##groupItem(); \ 159 } \ 160 return false; \ 161 } \ 162 type Get##name##Value(const type& defaultValue) const \ 163 { \ 164 auto& groupProperty = Get##group(); \ 165 if (groupProperty) { \ 166 if (groupProperty->Has##groupItem()) { \ 167 return groupProperty->Get##groupItem##Value(); \ 168 } \ 169 } \ 170 return defaultValue; \ 171 } 172 173 #define ACE_DEFINE_PROPERTY_ITEM_WITH_GROUP(group, name, type, changeFlag) \ 174 ACE_DEFINE_PROPERTY_ITEM_WITH_GROUP_GET(group, name, type) \ 175 void Update##name(const type& value) \ 176 { \ 177 auto& groupProperty = GetOrCreate##group(); \ 178 if (groupProperty->Check##name(value)) { \ 179 LOGD("the %{public}s is same, just ignore", #name); \ 180 return; \ 181 } \ 182 groupProperty->Update##name(value); \ 183 UpdatePropertyChangeFlag(changeFlag); \ 184 } 185 186 #define ACE_DEFINE_PROPERTY_ITEM_WITH_GROUP_ITEM(group, groupItem, name, type, changeFlag) \ 187 ACE_DEFINE_PROPERTY_ITEM_WITH_GROUP_ITEM_GET(group, groupItem, name, type) \ 188 void Update##name(const type& value) \ 189 { \ 190 auto& groupProperty = GetOrCreate##group(); \ 191 if (groupProperty->Check##groupItem(value)) { \ 192 LOGD("the %{public}s is same, just ignore", #name); \ 193 return; \ 194 } \ 195 groupProperty->Update##groupItem(value); \ 196 UpdatePropertyChangeFlag(changeFlag); \ 197 } 198 199 #define ACE_DEFINE_PROPERTY_ITEM_WITH_GROUP_AND_CALLBACK(group, name, type, changeFlag) \ 200 ACE_DEFINE_PROPERTY_ITEM_WITH_GROUP_GET(group, name, type) \ 201 void Update##name(const type& value) \ 202 { \ 203 auto& groupProperty = GetOrCreate##group(); \ 204 if (groupProperty->Check##name(value)) { \ 205 LOGD("the %{public}s is same, just ignore", #name); \ 206 return; \ 207 } \ 208 groupProperty->Update##name(value); \ 209 UpdatePropertyChangeFlag(changeFlag); \ 210 On##name##Update(value); \ 211 } 212 213 #define ACE_DEFINE_PROPERTY_FUNC_WITH_GROUP(group, name, type) \ 214 ACE_DEFINE_PROPERTY_ITEM_WITH_GROUP_GET(group, name, type) \ 215 void Update##name(const type& value) \ 216 { \ 217 auto& groupProperty = GetOrCreate##group(); \ 218 if (groupProperty->Check##name(value)) { \ 219 LOGD("the %{public}s is same, just ignore", #name); \ 220 return; \ 221 } \ 222 groupProperty->Update##name(value); \ 223 On##name##Update(value); \ 224 } 225 226 #define ACE_DEFINE_PROPERTY_ITEM_WITHOUT_GROUP_GET(name, type) \ 227 public: \ 228 const std::optional<type>& Get##name() const \ 229 { \ 230 return prop##name##_; \ 231 } \ 232 bool Has##name() const \ 233 { \ 234 return prop##name##_.has_value(); \ 235 } \ 236 const type& Get##name##Value() const \ 237 { \ 238 return prop##name##_.value(); \ 239 } \ 240 const type& Get##name##Value(const type& defaultValue) const \ 241 { \ 242 if (!Has##name()) { \ 243 return defaultValue; \ 244 } \ 245 return prop##name##_.value(); \ 246 } \ 247 std::optional<type> Clone##name() const \ 248 { \ 249 return prop##name##_; \ 250 } \ 251 void Reset##name() \ 252 { \ 253 return prop##name##_.reset(); \ 254 } \ 255 \ 256 protected: \ 257 std::optional<type> prop##name##_; 258 259 #define ACE_DEFINE_PROPERTY_ITEM_WITHOUT_GROUP(name, type, changeFlag) \ 260 ACE_DEFINE_PROPERTY_ITEM_WITHOUT_GROUP_GET(name, type) \ 261 public: \ 262 void Update##name(const type& value) \ 263 { \ 264 if (prop##name##_.has_value()) { \ 265 if (NearEqual(prop##name##_.value(), value)) { \ 266 LOGD("the %{public}s is same, just ignore", #name); \ 267 return; \ 268 } \ 269 } \ 270 prop##name##_ = value; \ 271 UpdatePropertyChangeFlag(changeFlag); \ 272 } 273 274 #define ACE_DEFINE_PROPERTY_ITEM_WITHOUT_GROUP_AND_USING_CALLBACK(name, type, changeFlag) \ 275 ACE_DEFINE_PROPERTY_ITEM_WITHOUT_GROUP_GET(name, type) \ 276 public: \ 277 void Update##name(const type& value) \ 278 { \ 279 if (prop##name##_.has_value()) { \ 280 if (NearEqual(prop##name##_.value(), value)) { \ 281 LOGD("the %{public}s is same, just ignore", #name); \ 282 return; \ 283 } \ 284 } \ 285 prop##name##_ = value; \ 286 UpdatePropertyChangeFlag(changeFlag); \ 287 On##name##Update(value); \ 288 } 289 290 #define ACE_DEFINE_PROPERTY_ITEM_FUNC_WITHOUT_GROUP(name, type) \ 291 ACE_DEFINE_PROPERTY_ITEM_WITHOUT_GROUP_GET(name, type) \ 292 public: \ 293 void Update##name(const type& value) \ 294 { \ 295 if (prop##name##_.has_value()) { \ 296 if (NearEqual(prop##name##_.value(), value)) { \ 297 LOGD("the %{public}s is same, just ignore", #name); \ 298 return; \ 299 } \ 300 } \ 301 prop##name##_ = value; \ 302 On##name##Update(value); \ 303 } 304 305 // For Property Group Struct 306 #define ACE_DEFINE_PROPERTY_GROUP_ITEM(name, type) \ 307 std::optional<type> prop##name; \ 308 \ 309 const std::optional<type>& Get##name() const \ 310 { \ 311 return prop##name; \ 312 } \ 313 bool Has##name() const \ 314 { \ 315 return prop##name.has_value(); \ 316 } \ 317 type Get##name##Value() const \ 318 { \ 319 return prop##name.value(); \ 320 } \ 321 bool Update##name(const type& value) \ 322 { \ 323 if (prop##name.has_value()) { \ 324 if (NearEqual(prop##name.value(), value)) { \ 325 return false; \ 326 } \ 327 } \ 328 prop##name = value; \ 329 return true; \ 330 } \ 331 bool Check##name(const type& value) const \ 332 { \ 333 if (!prop##name.has_value()) { \ 334 return false; \ 335 } \ 336 return NearEqual(prop##name.value(), value); \ 337 } \ 338 void Reset##name() \ 339 { \ 340 prop##name.reset(); \ 341 } 342 343 #define ACE_PROPERTY_TO_JSON_VALUE(target, type) \ 344 do { \ 345 if (target) { \ 346 (target)->ToJsonValue(json); \ 347 } else { \ 348 type p; \ 349 p.ToJsonValue(json); \ 350 } \ 351 } while (false) 352 353 class ACE_EXPORT Property : public virtual AceType { 354 DECLARE_ACE_TYPE(Property, AceType); 355 356 public: 357 Property() = default; 358 359 ~Property() override = default; 360 GetPropertyChangeFlag()361 PropertyChangeFlag GetPropertyChangeFlag() const 362 { 363 return propertyChangeFlag_; 364 } 365 CleanDirty()366 void CleanDirty() 367 { 368 propertyChangeFlag_ = PROPERTY_UPDATE_NORMAL; 369 } 370 UpdatePropertyChangeFlag(PropertyChangeFlag propertyChangeFlag)371 void UpdatePropertyChangeFlag(PropertyChangeFlag propertyChangeFlag) 372 { 373 propertyChangeFlag_ = propertyChangeFlag_ | propertyChangeFlag; 374 } 375 376 protected: 377 PropertyChangeFlag propertyChangeFlag_ = PROPERTY_UPDATE_NORMAL; 378 379 ACE_DISALLOW_COPY_AND_MOVE(Property); 380 }; 381 } // namespace OHOS::Ace::NG 382 383 #endif // FOUNDATION_ACE_FRAMEWORKS_CORE_COMPONENTS_NG_PROPERTIES_PROPERTY_H