• 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>) {
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 ConvertFromJSValue(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        return JSViewAbstract::ParseJsDimensionVp(jsValue, result);
94    } else if constexpr (std::is_same_v<T, Color>) {
95        return JSViewAbstract::ParseJsColor(jsValue, result);
96    }
97    return false;
98}
99
100template<class T, size_t N>
101bool ConvertFromJSValue(const JSRef<JSVal>& jsValue, const T (&enumValues)[N], T& result)
102{
103    int32_t value = 0;
104    if (!ConvertFromJSValue(jsValue, value) || value < 0 || static_cast<size_t>(value) >= N) {
105        return false;
106    }
107    result = enumValues[value];
108    return true;
109}
110
111template<class T>
112T FastConvertFromJSValue(const JSRef<JSVal>& jsValue)
113{
114    T result;
115    if (!ConvertFromJSValue(jsValue, result)) {
116        LOGE("Failed to convert from JS value");
117    }
118    return result;
119}
120
121template<class C, class V, class T, size_t N>
122void JSViewSetProperty(void (C::*setMethod)(V), int32_t param, const T (&enumValues)[N], T defValue)
123{
124    auto component = AceType::DynamicCast<C>(ViewStackProcessor::GetInstance()->GetMainComponent());
125    if (!component) {
126        LOGW("Failed to get '%{public}s' in view stack", AceType::TypeName<C>());
127        return;
128    }
129    T value = defValue;
130    if (param >= 0 && static_cast<size_t>(param) < N) {
131        value = enumValues[param];
132    }
133    ((*component).*setMethod)(value);
134}
135
136template<class C, class V, class T>
137void JSViewSetProperty(void (C::*setMethod)(V), T&& param)
138{
139    auto component = AceType::DynamicCast<C>(ViewStackProcessor::GetInstance()->GetMainComponent());
140    if (!component) {
141        LOGW("Failed to get '%{public}s' in view stack", AceType::TypeName<C>());
142        return;
143    }
144    ((*component).*setMethod)(std::forward<T>(param));
145}
146
147template<class C, class F>
148bool JSViewBindEvent(
149    void (C::*setMethod)(std::function<F>&&), const JSExecutionContext& context, const JSRef<JSVal>& jsValue)
150{
151    if (!jsValue->IsFunction()) {
152        LOGW("Argument is not a function object");
153        return false;
154    }
155    auto component = AceType::DynamicCast<C>(ViewStackProcessor::GetInstance()->GetMainComponent());
156    if (!component) {
157        LOGW("Failed to get '%{public}s' in view stack", AceType::TypeName<C>());
158        return false;
159    }
160    ((*component).*setMethod)(JsEventCallback<F>(context, JSRef<JSFunc>::Cast(jsValue)));
161    return true;
162}
163
164template<class C, class F>
165bool JSViewBindEvent(void (C::*setMethod)(std::function<F>&&), const JSCallbackInfo& args)
166{
167    if (args.Length() < 1) {
168        LOGW("Must contain at least 1 argument");
169        return false;
170    }
171    return JSViewBindEvent(setMethod, args.GetExecutionContext(), args[0]);
172}
173
174} // namespace OHOS::Ace::Framework
175