1 /* 2 * Copyright (c) 2024 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 META_INTERFACE_DETAIL_PROPERTY_H 17 #define META_INTERFACE_DETAIL_PROPERTY_H 18 19 #include <base/containers/type_traits.h> 20 21 #include <meta/interface/detail/any.h> 22 #include <meta/interface/intf_lockable.h> 23 #include <meta/interface/intf_object_registry.h> 24 #include <meta/interface/intf_value.h> 25 #include <meta/interface/property/intf_property.h> 26 #include <meta/interface/property/intf_property_internal.h> 27 #include <meta/interface/property/intf_property_register.h> 28 #include <meta/interface/property/intf_stack_property.h> 29 30 META_BEGIN_NAMESPACE() 31 32 class ConstTypelessPropertyInterface { 33 public: 34 using PropertyType = const IProperty*; 35 ConstTypelessPropertyInterface(PropertyType p)36 explicit ConstTypelessPropertyInterface(PropertyType p) : p_(p) {} 37 GetName() const38 BASE_NS::string GetName() const 39 { 40 return p_->GetName(); 41 } GetOwner() const42 IObject::WeakPtr GetOwner() const 43 { 44 return p_->GetOwner(); 45 } 46 GetValueAny() const47 const IAny& GetValueAny() const 48 { 49 return p_->GetValue(); 50 } 51 GetDefaultValueAny() const52 const IAny& GetDefaultValueAny() const 53 { 54 IAny::ConstPtr ret; 55 if (auto i = interface_cast<IStackProperty>(p_)) { 56 return i->GetDefaultValue(); 57 } 58 return META_NS::GetObjectRegistry().GetPropertyRegister().InvalidAny(); 59 } 60 IsDefaultValue() const61 bool IsDefaultValue() const 62 { 63 return p_->IsDefaultValue(); 64 } IsValueSet() const65 bool IsValueSet() const 66 { 67 return !p_->IsDefaultValue(); 68 } 69 GetTypeId() const70 TypeId GetTypeId() const 71 { 72 return p_->GetTypeId(); 73 } 74 IsCompatible(const TypeId& id) const75 bool IsCompatible(const TypeId& id) const 76 { 77 return p_->IsCompatible(id); 78 } 79 OnChanged() const80 auto OnChanged() const 81 { 82 return p_->OnChanged(); 83 } 84 NotifyChange() const85 void NotifyChange() const 86 { 87 p_->NotifyChange(); 88 } 89 GetProperty() const90 PropertyType GetProperty() const 91 { 92 return p_; 93 } 94 GetStackProperty() const95 const IStackProperty* GetStackProperty() const 96 { 97 return interface_cast<IStackProperty>(p_); 98 } 99 100 template<typename Interface> GetModifiers() const101 BASE_NS::vector<typename Interface::Ptr> GetModifiers() const 102 { 103 BASE_NS::vector<typename Interface::Ptr> res; 104 if (auto i = interface_cast<IStackProperty>(p_)) { 105 const TypeId view[] = { Interface::UID }; 106 for (auto& v : i->GetModifiers(view, true)) { 107 res.push_back(interface_pointer_cast<Interface>(v)); 108 } 109 } 110 return res; 111 } 112 GetBind() const113 IFunction::ConstPtr GetBind() const 114 { 115 if (auto i = interface_cast<IStackProperty>(p_)) { 116 const TypeId binds[] = { IBind::UID }; 117 auto vec = i->GetValues(binds, false); 118 if (!vec.empty()) { 119 if (auto bind = interface_cast<IBind>(vec.back())) { 120 return bind->GetTarget(); 121 } 122 } 123 } 124 return nullptr; 125 } 126 127 protected: 128 PropertyType p_; 129 }; 130 131 class TypelessPropertyInterface : public ConstTypelessPropertyInterface { 132 public: 133 using PropertyType = IProperty*; 134 TypelessPropertyInterface(PropertyType p)135 TypelessPropertyInterface(PropertyType p) : ConstTypelessPropertyInterface(p), p_(p) {} 136 SetValueAny(const IAny& any)137 AnyReturnValue SetValueAny(const IAny& any) 138 { 139 return p_->SetValue(any); 140 } 141 SetDefaultValueAny(const IAny& value)142 AnyReturnValue SetDefaultValueAny(const IAny& value) 143 { 144 if (auto i = interface_cast<IStackProperty>(p_)) { 145 return i->SetDefaultValue(value); 146 } 147 return AnyReturn::FAIL; 148 } 149 150 template<typename Intf> PushValue(const BASE_NS::shared_ptr<Intf>& value)151 ReturnError PushValue(const BASE_NS::shared_ptr<Intf>& value) 152 { 153 if (auto i = interface_cast<IStackProperty>(p_)) { 154 if (auto v = interface_pointer_cast<IValue>(value)) { 155 return i->PushValue(v); 156 } 157 } 158 return GenericError::FAIL; 159 } 160 PopValue()161 ReturnError PopValue() 162 { 163 if (auto i = interface_cast<IStackProperty>(p_)) { 164 return i->PopValue(); 165 } 166 return GenericError::FAIL; 167 } 168 AddModifier(const IModifier::Ptr& mod)169 ReturnError AddModifier(const IModifier::Ptr& mod) 170 { 171 if (auto i = interface_cast<IStackProperty>(p_)) { 172 return i->AddModifier(mod); 173 } 174 return GenericError::FAIL; 175 } 176 SetBind(const IFunction::ConstPtr& func, const BASE_NS::array_view<const INotifyOnChange::ConstPtr>& deps = {})177 bool SetBind(const IFunction::ConstPtr& func, const BASE_NS::array_view<const INotifyOnChange::ConstPtr>& deps = {}) 178 { 179 if (auto i = interface_cast<IStackProperty>(p_)) { 180 auto b = CreateBind(*i); 181 if (!b->SetTarget(func, deps.empty(), p_)) { 182 return false; 183 } 184 for (auto& d : deps) { 185 b->AddDependency(d); 186 } 187 return i->PushValue(interface_pointer_cast<IValue>(b)); 188 } 189 return false; 190 } 191 SetBind(const IProperty::ConstPtr& prop, const BASE_NS::array_view<const INotifyOnChange::ConstPtr>& deps = {})192 bool SetBind(const IProperty::ConstPtr& prop, const BASE_NS::array_view<const INotifyOnChange::ConstPtr>& deps = {}) 193 { 194 if (auto i = interface_cast<IStackProperty>(p_)) { 195 auto b = CreateBind(*i); 196 if (!b->SetTarget(prop, deps.empty(), p_)) { 197 return false; 198 } 199 for (auto& d : deps) { 200 b->AddDependency(d); 201 } 202 return i->PushValue(interface_pointer_cast<IValue>(b)); 203 } 204 return false; 205 } 206 ResetBind()207 void ResetBind() 208 { 209 if (auto i = interface_cast<IStackProperty>(p_)) { 210 const TypeId binds[] = { IBind::UID }; 211 auto vec = i->GetValues(binds, false); 212 if (!vec.empty()) { 213 i->RemoveValue(vec.back()); 214 NotifyChange(); 215 } 216 } 217 } 218 ResetValue()219 void ResetValue() 220 { 221 p_->ResetValue(); 222 } 223 Reset()224 void Reset() 225 { 226 ResetValue(); 227 } 228 GetProperty()229 PropertyType GetProperty() 230 { 231 return p_; 232 } 233 GetStackProperty()234 IStackProperty* GetStackProperty() 235 { 236 return interface_cast<IStackProperty>(p_); 237 } 238 239 protected: CreateBind(IStackProperty& prop)240 IBind::Ptr CreateBind(IStackProperty& prop) 241 { 242 if (interface_cast<IBind>(prop.TopValue())) { 243 prop.PopValue(); 244 } 245 return META_NS::GetObjectRegistry().GetPropertyRegister().CreateBind(); 246 } 247 248 protected: 249 PropertyType p_; 250 }; 251 252 template<typename Type> 253 using PropertyBaseType = 254 BASE_NS::conditional_t<BASE_NS::is_const_v<Type>, ConstTypelessPropertyInterface, TypelessPropertyInterface>; 255 256 template<typename Type> 257 class PropertyInterface : public PropertyBaseType<Type> { 258 using Super = PropertyBaseType<Type>; 259 using Super::p_; 260 261 public: 262 using ValueType = BASE_NS::remove_const_t<Type>; 263 using PropertyType = typename Super::PropertyType; 264 PropertyInterface(PropertyType p)265 explicit PropertyInterface(PropertyType p) : Super(p) {} 266 GetDefaultValue() const267 ValueType GetDefaultValue() const 268 { 269 ValueType v {}; 270 this->GetDefaultValueAny().GetValue(v); 271 return v; 272 } 273 SetDefaultValue(ValueType value, bool resetToDefault)274 AnyReturnValue SetDefaultValue(ValueType value, bool resetToDefault) 275 { 276 auto ret = this->SetDefaultValueAny(Any<ValueType>(value)); 277 if (resetToDefault && ret) { 278 this->ResetValue(); 279 } 280 return ret; 281 } 282 SetDefaultValue(ValueType value)283 AnyReturnValue SetDefaultValue(ValueType value) 284 { 285 return SetDefaultValue(BASE_NS::move(value), false); 286 } 287 GetValue() const288 ValueType GetValue() const 289 { 290 ValueType v {}; 291 this->GetValueAny().GetValue(v); 292 return v; 293 } 294 SetValue(ValueType value)295 AnyReturnValue SetValue(ValueType value) 296 { 297 return this->SetValueAny(Any<ValueType>(value)); 298 } 299 }; 300 301 template<typename Type> 302 class TypedPropertyLock final : public PropertyInterface<Type> { 303 using PropertyType = typename PropertyInterface<Type>::PropertyType; 304 using IT = PropertyInterface<Type>; 305 using InterfaceType = BASE_NS::conditional_t<BASE_NS::is_const_v<Type>, const IT*, IT*>; 306 307 META_NO_COPY_MOVE(TypedPropertyLock) 308 309 public: TypedPropertyLock(PropertyType p)310 explicit TypedPropertyLock(PropertyType p) : PropertyInterface<Type>(p) 311 { 312 if (auto i = interface_cast<ILockable>(p)) { 313 i->Lock(); 314 } 315 } ~TypedPropertyLock()316 ~TypedPropertyLock() 317 { 318 if (auto i = interface_cast<ILockable>(this->GetProperty())) { 319 i->Unlock(); 320 } 321 } 322 operator ->() const323 InterfaceType operator->() const 324 { 325 return const_cast<TypedPropertyLock*>(this); 326 } 327 }; 328 329 template<typename Property> 330 class PropertyLock final : public PropertyBaseType<Property> { 331 using InterfaceType = PropertyBaseType<Property>*; 332 333 META_NO_COPY_MOVE(PropertyLock) 334 335 public: PropertyLock(BASE_NS::shared_ptr<Property> p)336 explicit PropertyLock(BASE_NS::shared_ptr<Property> p) : PropertyBaseType<Property>(p.get()) 337 { 338 if (auto i = interface_cast<ILockable>(p)) { 339 i->Lock(); 340 } 341 } ~PropertyLock()342 ~PropertyLock() 343 { 344 if (auto i = interface_cast<ILockable>(this->GetProperty())) { 345 i->Unlock(); 346 } 347 } 348 operator ->() const349 InterfaceType operator->() const 350 { 351 return const_cast<PropertyLock*>(this); 352 } 353 }; 354 355 META_END_NAMESPACE() 356 357 #endif 358