/* * Copyright (c) 2024 Huawei Device Co., Ltd. * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #ifndef META_INTERFACE_DETAIL_PROPERTY_H #define META_INTERFACE_DETAIL_PROPERTY_H #include #include #include #include #include #include #include #include #include META_BEGIN_NAMESPACE() class ConstTypelessPropertyInterface { public: using PropertyType = const IProperty*; explicit ConstTypelessPropertyInterface(PropertyType p) : p_(p) {} BASE_NS::string GetName() const { return p_->GetName(); } IObject::WeakPtr GetOwner() const { return p_->GetOwner(); } const IAny& GetValueAny() const { return p_->GetValue(); } const IAny& GetDefaultValueAny() const { IAny::ConstPtr ret; if (auto i = interface_cast(p_)) { return i->GetDefaultValue(); } return META_NS::GetObjectRegistry().GetPropertyRegister().InvalidAny(); } bool IsDefaultValue() const { return p_->IsDefaultValue(); } bool IsValueSet() const { return !p_->IsDefaultValue(); } TypeId GetTypeId() const { return p_->GetTypeId(); } bool IsCompatible(const TypeId& id) const { return p_->IsCompatible(id); } auto OnChanged() const { return p_->OnChanged(); } void NotifyChange() const { p_->NotifyChange(); } PropertyType GetProperty() const { return p_; } const IStackProperty* GetStackProperty() const { return interface_cast(p_); } template BASE_NS::vector GetModifiers() const { BASE_NS::vector res; if (auto i = interface_cast(p_)) { const TypeId view[] = { Interface::UID }; for (auto& v : i->GetModifiers(view, true)) { res.push_back(interface_pointer_cast(v)); } } return res; } IFunction::ConstPtr GetBind() const { if (auto i = interface_cast(p_)) { const TypeId binds[] = { IBind::UID }; auto vec = i->GetValues(binds, false); if (!vec.empty()) { if (auto bind = interface_cast(vec.back())) { return bind->GetTarget(); } } } return nullptr; } protected: PropertyType p_; }; class TypelessPropertyInterface : public ConstTypelessPropertyInterface { public: using PropertyType = IProperty*; TypelessPropertyInterface(PropertyType p) : ConstTypelessPropertyInterface(p), p_(p) {} AnyReturnValue SetValueAny(const IAny& any) { return p_->SetValue(any); } AnyReturnValue SetDefaultValueAny(const IAny& value) { if (auto i = interface_cast(p_)) { return i->SetDefaultValue(value); } return AnyReturn::FAIL; } template ReturnError PushValue(const BASE_NS::shared_ptr& value) { if (auto i = interface_cast(p_)) { if (auto v = interface_pointer_cast(value)) { return i->PushValue(v); } } return GenericError::FAIL; } ReturnError PopValue() { if (auto i = interface_cast(p_)) { return i->PopValue(); } return GenericError::FAIL; } ReturnError AddModifier(const IModifier::Ptr& mod) { if (auto i = interface_cast(p_)) { return i->AddModifier(mod); } return GenericError::FAIL; } bool SetBind(const IFunction::ConstPtr& func, const BASE_NS::array_view& deps = {}) { if (auto i = interface_cast(p_)) { auto b = CreateBind(*i); if (!b->SetTarget(func, deps.empty(), p_)) { return false; } for (auto& d : deps) { b->AddDependency(d); } return i->PushValue(interface_pointer_cast(b)); } return false; } bool SetBind(const IProperty::ConstPtr& prop, const BASE_NS::array_view& deps = {}) { if (auto i = interface_cast(p_)) { auto b = CreateBind(*i); if (!b->SetTarget(prop, deps.empty(), p_)) { return false; } for (auto& d : deps) { b->AddDependency(d); } return i->PushValue(interface_pointer_cast(b)); } return false; } void ResetBind() { if (auto i = interface_cast(p_)) { const TypeId binds[] = { IBind::UID }; auto vec = i->GetValues(binds, false); if (!vec.empty()) { i->RemoveValue(vec.back()); NotifyChange(); } } } void ResetValue() { p_->ResetValue(); } void Reset() { ResetValue(); } PropertyType GetProperty() { return p_; } IStackProperty* GetStackProperty() { return interface_cast(p_); } protected: IBind::Ptr CreateBind(IStackProperty& prop) { if (interface_cast(prop.TopValue())) { prop.PopValue(); } return META_NS::GetObjectRegistry().GetPropertyRegister().CreateBind(); } protected: PropertyType p_; }; template using PropertyBaseType = BASE_NS::conditional_t, ConstTypelessPropertyInterface, TypelessPropertyInterface>; template class PropertyInterface : public PropertyBaseType { using Super = PropertyBaseType; using Super::p_; public: using ValueType = BASE_NS::remove_const_t; using PropertyType = typename Super::PropertyType; explicit PropertyInterface(PropertyType p) : Super(p) {} ValueType GetDefaultValue() const { ValueType v {}; this->GetDefaultValueAny().GetValue(v); return v; } AnyReturnValue SetDefaultValue(ValueType value, bool resetToDefault) { auto ret = this->SetDefaultValueAny(Any(value)); if (resetToDefault && ret) { this->ResetValue(); } return ret; } AnyReturnValue SetDefaultValue(ValueType value) { return SetDefaultValue(BASE_NS::move(value), false); } ValueType GetValue() const { ValueType v {}; this->GetValueAny().GetValue(v); return v; } AnyReturnValue SetValue(ValueType value) { return this->SetValueAny(Any(value)); } }; template class TypedPropertyLock final : public PropertyInterface { using PropertyType = typename PropertyInterface::PropertyType; using IT = PropertyInterface; using InterfaceType = BASE_NS::conditional_t, const IT*, IT*>; META_NO_COPY_MOVE(TypedPropertyLock) public: explicit TypedPropertyLock(PropertyType p) : PropertyInterface(p) { if (auto i = interface_cast(p)) { i->Lock(); } } ~TypedPropertyLock() { if (auto i = interface_cast(this->GetProperty())) { i->Unlock(); } } InterfaceType operator->() const { return const_cast(this); } }; template class PropertyLock final : public PropertyBaseType { using InterfaceType = PropertyBaseType*; META_NO_COPY_MOVE(PropertyLock) public: explicit PropertyLock(BASE_NS::shared_ptr p) : PropertyBaseType(p.get()) { if (auto i = interface_cast(p)) { i->Lock(); } } ~PropertyLock() { if (auto i = interface_cast(this->GetProperty())) { i->Unlock(); } } InterfaceType operator->() const { return const_cast(this); } }; META_END_NAMESPACE() #endif