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