• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1/*
2 * Copyright (c) 2021 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#include "bridge/declarative_frontend/jsview/js_view_common_def.h"
17
18#include <string>
19#include <type_traits>
20
21#include "base/geometry/dimension.h"
22#include "base/log/log.h"
23#include "bridge/declarative_frontend/view_stack_processor.h"
24#include "bridge/declarative_frontend/jsview/js_view_abstract.h"
25#include "core/components/common/properties/color.h"
26
27namespace OHOS::Ace::Framework {
28
29template<class T>
30JSRef<JSVal> ConvertToJSValue(T&& value)
31{
32    using ValueType = std::remove_cv_t<std::remove_reference_t<T>>;
33    if constexpr (std::is_arithmetic_v<ValueType> || std::is_same_v<ValueType, std::string> ||
34        std::is_same_v<ValueType, std::u16string>) {
35        return JSRef<JSVal>::Make(ToJSValue(std::forward<T>(value)));
36    } else if constexpr (std::is_enum_v<ValueType>) {
37        return JSRef<JSVal>::Make(ToJSValue(static_cast<std::make_signed_t<ValueType>>(value)));
38    } else if constexpr (std::is_same_v<ValueType, Dimension> || std::is_same_v<ValueType, CalcDimension>) {
39        if (value.Unit() == DimensionUnit::VP) {
40            return JSRef<JSVal>::Make(ToJSValue(value.Value()));
41        } else {
42            LOGE("Failed to convert to JS value with dimension which it not using 'VP' unit");
43            return JSRef<JSVal>();
44        }
45    } else {
46        LOGE("Failed to convert to JS value");
47        return JSRef<JSVal>();
48    }
49}
50
51template<class T>
52void ConvertToJSValuesImpl(std::vector<JSRef<JSVal>>& result, T&& value)
53{
54    result.emplace_back(ConvertToJSValue(std::forward<T>(value)));
55}
56
57template<class T, class V, class... Args>
58void ConvertToJSValuesImpl(std::vector<JSRef<JSVal>>& result, T&& value, V&& nextValue, Args&&... args)
59{
60    result.emplace_back(ConvertToJSValue(std::forward<T>(value)));
61    ConvertToJSValuesImpl(result, std::forward<V>(nextValue), std::forward<Args>(args)...);
62}
63
64template<class... Args>
65std::vector<JSRef<JSVal>> ConvertToJSValues(Args... args)
66{
67    std::vector<JSRef<JSVal>> result;
68    ConvertToJSValuesImpl(result, args...);
69    return result;
70}
71
72template<class T>
73bool ConvertFromJSValueNG(const JSRef<JSVal>& jsValue, T& result)
74{
75    if constexpr (std::is_same_v<T, bool>) {
76        if (jsValue->IsBoolean()) {
77            result = jsValue->ToBoolean();
78            return true;
79        }
80        result = false;
81    } else if constexpr (std::is_integral_v<T> || std::is_floating_point_v<T>) {
82        double value;
83        if (JSViewAbstract::ParseJsDouble(jsValue, value)) {
84            result = static_cast<T>(value);
85            return true;
86        }
87        result = 0;
88    } else if constexpr (std::is_same_v<T, std::string>) {
89        if (jsValue->IsString()) {
90            result = jsValue->ToString();
91            return true;
92        }
93    } else if constexpr (std::is_same_v<T, Dimension>) {
94        CalcDimension calc;
95        bool ret = JSViewAbstract::ParseJsDimensionVpNG(jsValue, calc);
96        result = calc;
97        return ret;
98    } else if constexpr (std::is_same_v<T, CalcDimension>) {
99        return JSViewAbstract::ParseJsDimensionVpNG(jsValue, result);
100    } else if constexpr (std::is_same_v<T, NG::CalcLength>) {
101        return JSViewAbstract::ParseJsLengthVpNG(jsValue, result);
102    } else if constexpr (std::is_same_v<T, Color>) {
103        return JSViewAbstract::ParseJsColor(jsValue, result);
104    }
105    return false;
106}
107
108template<class T>
109bool ConvertFromJSValue(const JSRef<JSVal>& jsValue, T& result)
110{
111    if constexpr (std::is_same_v<T, bool>) {
112        if (jsValue->IsBoolean()) {
113            result = jsValue->ToBoolean();
114            return true;
115        }
116        result = false;
117    } else if constexpr (std::is_integral_v<T> || std::is_floating_point_v<T>) {
118        double value;
119        if (JSViewAbstract::ParseJsDouble(jsValue, value)) {
120            result = static_cast<T>(value);
121            return true;
122        }
123        result = 0;
124    } else if constexpr (std::is_same_v<T, std::string>) {
125        if (jsValue->IsString()) {
126            result = jsValue->ToString();
127            return true;
128        }
129    } else if constexpr (std::is_same_v<T, Dimension>) {
130        CalcDimension calc;
131        bool ret = JSViewAbstract::ParseJsDimensionVp(jsValue, calc);
132        result = calc;
133        return ret;
134    } else if constexpr (std::is_same_v<T, CalcDimension>) {
135        return JSViewAbstract::ParseJsDimensionVp(jsValue, result);
136    } else if constexpr (std::is_same_v<T, Color>) {
137        return JSViewAbstract::ParseJsColor(jsValue, result);
138    }
139    return false;
140}
141
142template<class T, size_t N>
143bool ConvertFromJSValue(const JSRef<JSVal>& jsValue, const T (&enumValues)[N], T& result)
144{
145    int32_t value = 0;
146    if (!ConvertFromJSValue(jsValue, value) || value < 0 || static_cast<size_t>(value) >= N) {
147        return false;
148    }
149    result = enumValues[value];
150    return true;
151}
152
153template<class T>
154T FastConvertFromJSValue(const JSRef<JSVal>& jsValue)
155{
156    T result;
157    if (!ConvertFromJSValue(jsValue, result)) {
158        LOGE("Failed to convert from JS value");
159    }
160    return result;
161}
162
163template<class C, class V, class T, size_t N>
164void JSViewSetProperty(void (C::*setMethod)(V), int32_t param, const T (&enumValues)[N], T defValue)
165{
166#ifndef NG_BUILD
167    auto component = AceType::DynamicCast<C>(ViewStackProcessor::GetInstance()->GetMainComponent());
168    if (!component) {
169        LOGW("Failed to get '%{public}s' in view stack", AceType::TypeName<C>());
170        return;
171    }
172    T value = defValue;
173    if (param >= 0 && static_cast<size_t>(param) < N) {
174        value = enumValues[param];
175    }
176    ((*component).*setMethod)(value);
177#else
178    LOGE("do not support JSViewSetProperty in new pipeline");
179#endif
180}
181
182template<class C, class V, class T>
183void JSViewSetProperty(void (C::*setMethod)(V), T&& param)
184{
185#ifndef NG_BUILD
186    auto component = AceType::DynamicCast<C>(ViewStackProcessor::GetInstance()->GetMainComponent());
187    if (!component) {
188        LOGW("Failed to get '%{public}s' in view stack", AceType::TypeName<C>());
189        return;
190    }
191    ((*component).*setMethod)(std::forward<T>(param));
192#else
193    LOGE("do not support JSViewSetProperty in new pipeline");
194#endif
195}
196
197template<class C, class F>
198bool JSViewBindEvent(
199    void (C::*setMethod)(std::function<F>&&), const JSExecutionContext& context, const JSRef<JSVal>& jsValue)
200{
201#ifndef NG_BUILD
202    if (!jsValue->IsFunction()) {
203        LOGW("Argument is not a function object");
204        return false;
205    }
206    auto component = AceType::DynamicCast<C>(ViewStackProcessor::GetInstance()->GetMainComponent());
207    if (!component) {
208        LOGW("Failed to get '%{public}s' in view stack", AceType::TypeName<C>());
209        return false;
210    }
211    ((*component).*setMethod)(JsEventCallback<F>(context, JSRef<JSFunc>::Cast(jsValue)));
212    return true;
213#else
214    LOGE("do not support JSViewBindEvent in new pipeline");
215    return false;
216#endif
217}
218
219template<class C, class F>
220bool JSViewBindEvent(void (C::*setMethod)(std::function<F>&&), const JSCallbackInfo& args)
221{
222    if (args.Length() < 1) {
223        LOGW("Must contain at least 1 argument");
224        return false;
225    }
226    return JSViewBindEvent(setMethod, args.GetExecutionContext(), args[0]);
227}
228
229} // namespace OHOS::Ace::Framework
230