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