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_API_PROPERTY_DEFAULT_VALUE_BIND_H 17 #define META_API_PROPERTY_DEFAULT_VALUE_BIND_H 18 19 #include <meta/api/make_callback.h> 20 #include <meta/base/interface_macros.h> 21 #include <meta/interface/property/property.h> 22 #include <meta/interface/property/property_events.h> 23 META_BEGIN_NAMESPACE()24META_BEGIN_NAMESPACE() 25 26 /** 27 * @brief A helper class for binding the default value of a property to the value of a source property 28 */ 29 class DefaultValueBind final { 30 public: 31 DefaultValueBind() = default; 32 explicit DefaultValueBind(const IProperty::Ptr& property) : property_(property) {} 33 ~DefaultValueBind() 34 { 35 UnBind(); 36 property_.reset(); 37 } 38 DefaultValueBind(const DefaultValueBind& other) : property_(other.property_) 39 { 40 Bind(other.source_.lock()); 41 } 42 DefaultValueBind(DefaultValueBind&& other) : property_(other.property_) 43 { 44 Bind(other.source_.lock()); 45 other.UnBind(); 46 other.property_ = nullptr; 47 } 48 DefaultValueBind& operator=(const DefaultValueBind& other) 49 { 50 UnBind(); 51 property_ = other.property_; 52 Bind(other.source_.lock()); 53 return *this; 54 } 55 DefaultValueBind& operator=(DefaultValueBind&& other) 56 { 57 UnBind(); 58 property_ = other.property_; 59 Bind(other.source_.lock()); 60 other.UnBind(); 61 other.property_ = nullptr; 62 return *this; 63 } 64 65 bool Bind(const IProperty::ConstPtr& source) 66 { 67 if (source == source_.lock()) { 68 return true; // No change 69 } 70 UnBind(); 71 const auto property = property_.lock(); 72 if (property && source) { 73 source_ = source; 74 token_ = source->OnChanged()->AddHandler(MakeCallback<IOnChanged>([this]() { 75 const auto property = property_.lock(); 76 const auto source = source_.lock(); 77 if (property && source) { 78 if (auto s = interface_cast<IStackProperty>(property)) { 79 s->SetDefaultValue(source->GetValue()); 80 } 81 } 82 })); 83 if (auto s = interface_cast<IStackProperty>(property)) { 84 s->SetDefaultValue(source->GetValue()); 85 } 86 } 87 return token_ != 0; 88 } 89 void UnBind() 90 { 91 if (token_) { 92 if (const auto source = source_.lock()) { 93 source->OnChanged()->RemoveHandler(token_); 94 } 95 token_ = {}; 96 source_.reset(); 97 } 98 } 99 void SetProperty(const IProperty::Ptr& property) 100 { 101 UnBind(); 102 property_ = property; 103 } 104 IProperty::Ptr GetProperty() const 105 { 106 return property_.lock(); 107 } 108 bool IsDefaultValue() const 109 { 110 if (token_) { 111 if (auto p = GetProperty()) { 112 PropertyLock s { p }; 113 return s.IsDefaultValue(); 114 } 115 } 116 return false; 117 } 118 119 private: 120 IProperty::WeakPtr property_; 121 IProperty::ConstWeakPtr source_; 122 IEvent::Token token_ {}; 123 }; 124 125 META_END_NAMESPACE() 126 127 #endif 128