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