1 /*
2 * Copyright (c) 2021-2022 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 "frameworks/bridge/declarative_frontend/jsview/js_marquee.h"
17 #include <limits>
18 #include <optional>
19 #include <string>
20
21 #include "base/geometry/dimension.h"
22 #include "base/log/ace_scoring_log.h"
23 #include "base/utils/utils.h"
24 #include "bridge/declarative_frontend/engine/functions/js_function.h"
25 #include "bridge/declarative_frontend/jsview/js_view_common_def.h"
26 #include "bridge/declarative_frontend/jsview/models/marquee_model_impl.h"
27 #include "core/components/text/text_theme.h"
28 #include "core/components_ng/pattern/marquee/marquee_model.h"
29 #include "core/components_ng/pattern/marquee/marquee_model_ng.h"
30
31 namespace OHOS::Ace {
32
33 std::unique_ptr<MarqueeModel> MarqueeModel::instance_ = nullptr;
34 std::mutex MarqueeModel::mutex_;
GetInstance()35 MarqueeModel* MarqueeModel::GetInstance()
36 {
37 if (!instance_) {
38 std::lock_guard<std::mutex> lock(mutex_);
39 if (!instance_) {
40 #ifdef NG_BUILD
41 instance_.reset(new NG::MarqueeModelNG());
42 #else
43 if (Container::IsCurrentUseNewPipeline()) {
44 instance_.reset(new NG::MarqueeModelNG());
45 } else {
46 instance_.reset(new Framework::MarqueeModelImpl());
47 }
48 #endif
49 }
50 }
51 return instance_.get();
52 }
53 } // namespace OHOS::Ace
54
55 namespace OHOS::Ace::Framework {
56
Create(const JSCallbackInfo & info)57 void JSMarquee::Create(const JSCallbackInfo& info)
58 {
59 if (info.Length() < 1 || !info[0]->IsObject()) {
60 LOGE("marquee create error, info is non-valid");
61 return;
62 }
63
64 MarqueeModel::GetInstance()->Create();
65 auto paramObject = JSRef<JSObject>::Cast(info[0]);
66 auto src = paramObject->GetProperty("src");
67 std::optional<std::string> srcOpt;
68 if (src->IsString()) {
69 srcOpt = src->ToString();
70 }
71 MarqueeModel::GetInstance()->SetValue(srcOpt);
72
73 auto getStart = paramObject->GetProperty("start");
74 std::optional<bool> startOpt = getStart->IsBoolean() ? getStart->ToBoolean() : false;
75 MarqueeModel::GetInstance()->SetPlayerStatus(startOpt);
76
77 auto getStep = paramObject->GetProperty("step");
78 std::optional<double> stepOpt;
79 if (getStep->IsNumber()) {
80 auto step = getStep->ToNumber<double>();
81 if (GreatNotEqual(step, 0.0)) {
82 stepOpt = Dimension(step, DimensionUnit::VP).ConvertToPx();
83 }
84 }
85 MarqueeModel::GetInstance()->SetScrollAmount(stepOpt);
86
87 auto getLoop = paramObject->GetProperty("loop");
88 std::optional<int32_t> loopOpt;
89 if (getLoop->IsNumber()) {
90 auto loopDouble = getLoop->ToNumber<double>();
91 int32_t loop = -1;
92 if (GreatNotEqual(loopDouble, 0.0)) {
93 loop = static_cast<int32_t>(loopDouble);
94 if (loop == std::numeric_limits<int32_t>::max() || loop < 0) {
95 loop = -1;
96 }
97 }
98 loopOpt = loop;
99 }
100 MarqueeModel::GetInstance()->SetLoop(loopOpt);
101
102 auto getFromStart = paramObject->GetProperty("fromStart");
103 bool fromStart = getFromStart->IsBoolean() ? getFromStart->ToBoolean() : true;
104 std::optional<MarqueeDirection> directionOpt;
105 if (fromStart) {
106 directionOpt = MarqueeDirection::LEFT;
107 } else {
108 directionOpt = MarqueeDirection::RIGHT;
109 }
110 MarqueeModel::GetInstance()->SetDirection(directionOpt);
111 }
112
JSBind(BindingTarget globalObj)113 void JSMarquee::JSBind(BindingTarget globalObj)
114 {
115 JSClass<JSMarquee>::Declare("Marquee");
116 MethodOptions opt = MethodOptions::NONE;
117 JSClass<JSMarquee>::StaticMethod("create", &JSMarquee::Create, opt);
118 JSClass<JSMarquee>::StaticMethod("allowScale", &JSMarquee::SetAllowScale);
119 JSClass<JSMarquee>::StaticMethod("fontColor", &JSMarquee::SetTextColor);
120 JSClass<JSMarquee>::StaticMethod("fontSize", &JSMarquee::SetFontSize);
121 JSClass<JSMarquee>::StaticMethod("fontWeight", &JSMarquee::SetFontWeight);
122 JSClass<JSMarquee>::StaticMethod("fontFamily", &JSMarquee::SetFontFamily);
123 JSClass<JSMarquee>::StaticMethod("onStart", &JSMarquee::OnStart);
124 JSClass<JSMarquee>::StaticMethod("onBounce", &JSMarquee::OnBounce);
125 JSClass<JSMarquee>::StaticMethod("onFinish", &JSMarquee::OnFinish);
126 JSClass<JSMarquee>::StaticMethod("onClick", &JSInteractableView::JsOnClick);
127 JSClass<JSMarquee>::StaticMethod("onTouch", &JSInteractableView::JsOnTouch);
128 JSClass<JSMarquee>::StaticMethod("onKeyEvent", &JSInteractableView::JsOnKey);
129 JSClass<JSMarquee>::StaticMethod("onDeleteEvent", &JSInteractableView::JsOnDelete);
130 JSClass<JSMarquee>::StaticMethod("onAppear", &JSInteractableView::JsOnAppear);
131 JSClass<JSMarquee>::StaticMethod("onDisAppear", &JSInteractableView::JsOnDisAppear);
132 JSClass<JSMarquee>::InheritAndBind<JSViewAbstract>(globalObj);
133 }
134
SetTextColor(const JSCallbackInfo & info)135 void JSMarquee::SetTextColor(const JSCallbackInfo& info)
136 {
137 if (info.Length() < 1) {
138 LOGE("SetFontColor create error, info is non-valid");
139 return;
140 }
141 std::optional<Color> colorOpt;
142 Color color;
143 if (ParseJsColor(info[0], color)) {
144 colorOpt = color;
145 }
146 MarqueeModel::GetInstance()->SetTextColor(colorOpt);
147 }
148
SetFontSize(const JSCallbackInfo & info)149 void JSMarquee::SetFontSize(const JSCallbackInfo& info)
150 {
151 if (info.Length() < 1) {
152 LOGE("SetFrontSize create error, info is non-valid");
153 return;
154 }
155 std::optional<Dimension> fontSizeOpt;
156 CalcDimension fontSize;
157 if (ParseJsDimensionFp(info[0], fontSize)) {
158 if (!fontSize.IsNegative() && fontSize.Unit() != DimensionUnit::PERCENT) {
159 fontSizeOpt = fontSize;
160 }
161 }
162 MarqueeModel::GetInstance()->SetFontSize(fontSizeOpt);
163 }
164
SetAllowScale(const JSCallbackInfo & info)165 void JSMarquee::SetAllowScale(const JSCallbackInfo& info)
166 {
167 if (info.Length() < 1) {
168 LOGE("SetAllowScale create error, info is non-valid");
169 return;
170 }
171 std::optional<bool> allowScaleOpt;
172 if (info[0]->IsBoolean()) {
173 allowScaleOpt = info[0]->ToBoolean();
174 }
175 MarqueeModel::GetInstance()->SetAllowScale(allowScaleOpt);
176 }
177
SetFontWeight(const std::string & value)178 void JSMarquee::SetFontWeight(const std::string& value)
179 {
180 std::optional<FontWeight> fontWeightOpt = ConvertStrToFontWeight(value);
181 MarqueeModel::GetInstance()->SetFontWeight(fontWeightOpt);
182 }
183
SetFontFamily(const JSCallbackInfo & info)184 void JSMarquee::SetFontFamily(const JSCallbackInfo& info)
185 {
186 if (info.Length() < 1) {
187 LOGE("SetFrontFamily create error, info is non-valid");
188 return;
189 }
190 std::optional<std::vector<std::string>> fontFamiliesOpt;
191 std::vector<std::string> fontFamilies;
192 if (ParseJsFontFamilies(info[0], fontFamilies)) {
193 fontFamiliesOpt = fontFamilies;
194 }
195 MarqueeModel::GetInstance()->SetFontFamily(fontFamiliesOpt);
196 }
197
OnStart(const JSCallbackInfo & info)198 void JSMarquee::OnStart(const JSCallbackInfo& info)
199 {
200 if (!info[0]->IsFunction()) {
201 return;
202 }
203
204 auto jsFunc = AceType::MakeRefPtr<JsFunction>(JSRef<JSObject>(), JSRef<JSFunc>::Cast(info[0]));
205 auto onChange = [execCtx = info.GetExecutionContext(), func = std::move(jsFunc)]() {
206 JAVASCRIPT_EXECUTION_SCOPE_WITH_CHECK(execCtx);
207 ACE_SCORING_EVENT("Marquee.onStart");
208 func->ExecuteJS();
209 };
210 MarqueeModel::GetInstance()->SetOnStart(std::move(onChange));
211 }
212
OnBounce(const JSCallbackInfo & info)213 void JSMarquee::OnBounce(const JSCallbackInfo& info)
214 {
215 if (!info[0]->IsFunction()) {
216 return;
217 }
218
219 auto jsFunc = AceType::MakeRefPtr<JsFunction>(JSRef<JSObject>(), JSRef<JSFunc>::Cast(info[0]));
220 auto onChange = [execCtx = info.GetExecutionContext(), func = std::move(jsFunc)]() {
221 JAVASCRIPT_EXECUTION_SCOPE_WITH_CHECK(execCtx);
222 ACE_SCORING_EVENT("Marquee.onBounce");
223 func->ExecuteJS();
224 };
225 MarqueeModel::GetInstance()->SetOnBounce(std::move(onChange));
226 }
227
OnFinish(const JSCallbackInfo & info)228 void JSMarquee::OnFinish(const JSCallbackInfo& info)
229 {
230 if (!info[0]->IsFunction()) {
231 return;
232 }
233
234 auto jsFunc = AceType::MakeRefPtr<JsFunction>(JSRef<JSObject>(), JSRef<JSFunc>::Cast(info[0]));
235 auto onChange = [execCtx = info.GetExecutionContext(), func = std::move(jsFunc)]() {
236 JAVASCRIPT_EXECUTION_SCOPE_WITH_CHECK(execCtx);
237 ACE_SCORING_EVENT("Marquee.onFinish");
238 func->ExecuteJS();
239 };
240 MarqueeModel::GetInstance()->SetOnFinish(std::move(onChange));
241 }
242
243 } // namespace OHOS::Ace::Framework
244