• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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_ARRAY_ELEMENT_BIND_H
17 #define META_API_PROPERTY_ARRAY_ELEMENT_BIND_H
18 
19 #include <meta/ext/event_impl.h>
20 #include <meta/interface/property/property.h>
21 
META_BEGIN_NAMESPACE()22 META_BEGIN_NAMESPACE()
23 
24 /// Helper to bind individual array elements
25 class ArrayElementBind : public IntroduceInterfaces<IValue, INotifyOnChange> {
26 public:
27     ArrayElementBind(const IProperty::Ptr& p, size_t index) : p_(p), index_(index)
28     {
29         if (auto i = interface_cast<IPropertyInternalAny>(p)) {
30             if (auto&& any = i->GetInternalAny()) {
31                 if (any->IsArray()) {
32                     value_ = any->Clone({ CloneValueType::DEFAULT_VALUE, TypeIdRole::ITEM });
33                 }
34             }
35         }
36         if (!value_) {
37             CORE_LOG_E("Failed to set any for array element bind");
38             value_ = GetObjectRegistry().GetPropertyRegister().InvalidAny().Clone(false);
39         }
40         p->OnChanged()->AddHandler(MakeCallback<IOnChanged>([&] {
41             if (!settingValue_) {
42                 event_->Invoke();
43             }
44         }),
45             (uintptr_t)this);
46     }
47     ~ArrayElementBind()
48     {
49         if (auto p = p_.lock()) {
50             p->OnChanged()->RemoveHandler((uintptr_t)this);
51         }
52     }
53     BASE_NS::shared_ptr<IEvent> EventOnChanged(MetadataQuery) const override
54     {
55         return event_;
56     }
57     AnyReturnValue SetValue(const IAny& value) override
58     {
59         if (auto p = p_.lock()) {
60             AnyReturnValue ret = AnyReturn::FAIL;
61             settingValue_ = true;
62             {
63                 ArrayPropertyLock l(p);
64                 ret = l->SetAnyAt(index_, value);
65             }
66             settingValue_ = false;
67             return ret;
68         }
69         return AnyReturn::FAIL;
70     }
71     const IAny& GetValue() const override
72     {
73         if (auto p = p_.lock()) {
74             ArrayPropertyLock l(p);
75             l->GetAnyAt(index_, *value_);
76         }
77         return *value_;
78     }
79     bool IsCompatible(const TypeId& id) const override
80     {
81         return META_NS::IsCompatible(*value_, id);
82     }
83 
84 private:
85     std::atomic<bool> settingValue_ {};
86     BASE_NS::shared_ptr<EventImpl<IOnChanged>> event_ { new EventImpl<IOnChanged>("OnChanged") };
87     IProperty::WeakPtr p_;
88     IAny::Ptr value_;
89     std::size_t index_ {};
90 };
91 
92 /// Bind property to single element of array property
AddArrayElementBind(const IProperty::Ptr & p,const IProperty::Ptr & arr,size_t index)93 inline void AddArrayElementBind(const IProperty::Ptr& p, const IProperty::Ptr& arr, size_t index)
94 {
95     if (auto i = interface_cast<IStackProperty>(p)) {
96         BASE_NS::shared_ptr<ArrayElementBind> bind(new ArrayElementBind(arr, index));
97         i->PushValue(interface_pointer_cast<IValue>(bind));
98     }
99 }
100 
101 META_END_NAMESPACE()
102 
103 #endif
104