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