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 PROPERTY_PROXY_H
17 #define PROPERTY_PROXY_H
18 #include <meta/interface/intf_event.h>
19 #include <meta/interface/intf_task_queue.h>
20 #include <meta/interface/property/property.h>
21 #include <meta/interface/property/property_events.h>
22 #include <napi_api.h>
23
24 #include <scene/interface/intf_bitmap.h>
25 #include <base/containers/string.h>
26 #include <base/containers/string_view.h>
27 #include <base/containers/vector.h>
28
29 class PropertyProxy {
30 public:
31 explicit PropertyProxy(META_NS::IProperty::Ptr prop);
32 virtual ~PropertyProxy();
33
34 virtual void SetValue(NapiApi::FunctionContext<>& info) = 0;
35 virtual napi_value Value() = 0;
36
37 // removes hooks.(if removeProperty is true, the property will be fully removed from the object)
38 virtual void Reset() = 0;
39
40 virtual void SetExtra(const BASE_NS::shared_ptr<CORE_NS::IInterface>);
41 virtual const BASE_NS::shared_ptr<CORE_NS::IInterface> GetExtra() const;
42 protected:
43 void RemoveHandlers();
44
45 virtual void UpdateLocalValues() = 0;
46 virtual void UpdateRemoteValues() = 0;
47 void UpdateLocal();
48 int32_t UpdateRemote();
49 void ScheduleUpdate();
50
51 // synchronized get value.
52 void SyncGet();
53
54 void Lock();
55 void Unlock();
56
57 BASE_NS::weak_ptr<CORE_NS::IInterface> extra_;
58 META_NS::IProperty::Ptr prop_;
59 META_NS::IEvent::Token changeToken_ { 0 };
60 META_NS::ITaskQueue::Token updateToken_ { nullptr };
61 META_NS::IOnChanged::InterfaceTypePtr changeHandler_;
62 META_NS::ITaskQueueTask::Ptr updateTask_;
63
64 private:
65 CORE_NS::SpinLock lock_;
66 };
67
68 class ObjectPropertyProxy : public PropertyProxy {
69 public:
70 explicit ObjectPropertyProxy(META_NS::IProperty::Ptr prop);
71 ~ObjectPropertyProxy();
72 void Reset() override;
73 // copy data from jsobject
74 void SetValue(NapiApi::FunctionContext<>& info) override;
75 napi_value Value() override;
76
77 virtual void SetValue(NapiApi::Object obj) = 0;
78
79 virtual void SetMemberValue(NapiApi::FunctionContext<>& info, BASE_NS::string_view memb) = 0;
80 virtual napi_value GetMemberValue(const NapiApi::Env info, BASE_NS::string_view memb) = 0;
81
82 void Create(napi_env env, const BASE_NS::string jsName);
83 void Hook(const BASE_NS::string member);
84 void Destroy();
85 NapiApi::StrongRef obj_;
86
87 class MemberProxy {
88 public:
89 MemberProxy(ObjectPropertyProxy* p, BASE_NS::string m);
90 ~MemberProxy();
91 const BASE_NS::string_view Name() const;
92 static napi_value Getter(napi_env e, napi_callback_info i);
93 static napi_value Setter(napi_env e, napi_callback_info i);
94
95 private:
96 ObjectPropertyProxy* proxy_;
97 BASE_NS::string memb_;
98 };
99
100 BASE_NS::vector<BASE_NS::unique_ptr<MemberProxy>> accessors_;
101 };
102 class BitmapProxy : public PropertyProxy {
103 public:
104 BitmapProxy(NapiApi::Object scn, NapiApi::Object obj, META_NS::Property<SCENE_NS::IBitmap::Ptr> prop);
105 ~BitmapProxy() override;
106
107 void Reset() override;
108
109 protected:
110 napi_value Value() override;
111 void SetValue(NapiApi::FunctionContext<>& info) override;
112 void SetValue(const SCENE_NS::IBitmap::Ptr v);
113 void UpdateLocalValues() override;
114 void UpdateRemoteValues() override;
115 SCENE_NS::IBitmap::Ptr value {};
116 NapiApi::WeakRef obj_;
117 NapiApi::WeakRef scene_;
118 };
119
120 template<typename type>
121 class TypeProxy : public PropertyProxy {
122 public:
123 TypeProxy(NapiApi::Object obj, META_NS::Property<type> prop);
124 ~TypeProxy() override;
125
126 void Reset() override;
127
128 protected:
129 napi_value Value() override;
130 void SetValue(NapiApi::FunctionContext<>& info) override;
131 void SetValue(const type v);
132 void UpdateLocalValues() override;
133 void UpdateRemoteValues() override;
134 type value {};
135 NapiApi::WeakRef obj_;
136 };
137
138 template<typename type>
Reset()139 void TypeProxy<type>::Reset()
140 {
141 Lock();
142 if (!prop_) {
143 Unlock();
144 return;
145 }
146 BASE_NS::string name = prop_->GetName();
147 RemoveHandlers();
148
149 if (!obj_.IsEmpty()) {
150 obj_.GetObject().DeleteProperty(name);
151 }
152 obj_.Reset();
153 Unlock();
154 }
155 template<typename type>
TypeProxy(NapiApi::Object obj,META_NS::Property<type> prop)156 TypeProxy<type>::TypeProxy(NapiApi::Object obj, META_NS::Property<type> prop) : PropertyProxy(prop)
157 {
158 obj_ = obj;
159 SyncGet();
160 }
161
162 template<typename type>
~TypeProxy()163 TypeProxy<type>::~TypeProxy()
164 {
165 // Unhook the objects.
166 Reset();
167 }
168 template<typename type>
UpdateLocalValues()169 void TypeProxy<type>::UpdateLocalValues()
170 {
171 // executed in engine thread (locks handled outside)
172 if (prop_) {
173 value = META_NS::Property<type>(prop_)->GetValue();
174 }
175 }
176 template<typename type>
UpdateRemoteValues()177 void TypeProxy<type>::UpdateRemoteValues()
178 {
179 // executed in engine thread (locks handled outside)
180 if (prop_) {
181 META_NS::Property<type>(prop_)->SetValue(value);
182 }
183 }
184
185 template<typename type>
SetValue(const type v)186 void TypeProxy<type>::SetValue(const type v)
187 {
188 Lock();
189 if (value != v) {
190 value = v;
191 ScheduleUpdate();
192 }
193 Unlock();
194 }
195 template<typename type>
Value()196 napi_value TypeProxy<type>::Value()
197 {
198 Lock();
199 type res = value;
200 Unlock();
201 return NapiApi::Env(obj_.GetEnv()).GetNumber((type)res);
202 }
203 template<typename type>
SetValue(NapiApi::FunctionContext<> & info)204 void TypeProxy<type>::SetValue(NapiApi::FunctionContext<>& info)
205 {
206 NapiApi::FunctionContext<type> data { info };
207 if (data) {
208 type val = data.template Arg<0>();
209 Lock();
210 value = val;
211 ScheduleUpdate();
212 Unlock();
213 }
214 }
215
216 BASE_NS::shared_ptr<PropertyProxy> PropertyToProxy(
217
218 NapiApi::Object scene, NapiApi::Object obj, const META_NS::IProperty::Ptr& t);
219
220 napi_property_descriptor CreateProxyDesc(const char* name, BASE_NS::shared_ptr<PropertyProxy> proxy);
221
222 #endif
223