1 /*
2 * Copyright (c) 2021-2023 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_text.h"
17
18 #include <sstream>
19 #include <string>
20 #include <vector>
21
22 #include "base/geometry/dimension.h"
23 #include "base/log/ace_scoring_log.h"
24 #include "base/log/ace_trace.h"
25 #include "base/utils/utils.h"
26 #include "bridge/common/utils/utils.h"
27 #include "bridge/declarative_frontend/engine/functions/js_click_function.h"
28 #include "bridge/declarative_frontend/engine/functions/js_drag_function.h"
29 #include "bridge/declarative_frontend/jsview/js_interactable_view.h"
30 #include "bridge/declarative_frontend/jsview/js_text.h"
31 #include "bridge/declarative_frontend/jsview/js_utils.h"
32 #include "bridge/declarative_frontend/jsview/js_view_abstract.h"
33 #include "bridge/declarative_frontend/jsview/models/text_model_impl.h"
34 #include "bridge/declarative_frontend/view_stack_processor.h"
35 #include "core/common/container.h"
36 #include "core/components/text/text_theme.h"
37 #include "core/components_ng/event/gesture_event_hub.h"
38 #include "core/components_ng/pattern/text/text_model.h"
39 #include "core/components_ng/pattern/text/text_model_ng.h"
40 #include "core/event/ace_event_handler.h"
41 #include "core/pipeline/pipeline_base.h"
42
43 namespace OHOS::Ace {
44
45 std::unique_ptr<TextModel> TextModel::instance_ = nullptr;
46 std::mutex TextModel::mutex_;
47
GetInstance()48 TextModel* TextModel::GetInstance()
49 {
50 if (!instance_) {
51 std::lock_guard<std::mutex> lock(mutex_);
52 if (!instance_) {
53 #ifdef NG_BUILD
54 instance_.reset(new NG::TextModelNG());
55 #else
56 if (Container::IsCurrentUseNewPipeline()) {
57 instance_.reset(new NG::TextModelNG());
58 } else {
59 instance_.reset(new Framework::TextModelImpl());
60 }
61 #endif
62 }
63 }
64 return instance_.get();
65 }
66
67 } // namespace OHOS::Ace
68
69 namespace OHOS::Ace::Framework {
70 namespace {
71
72 const std::vector<TextCase> TEXT_CASES = { TextCase::NORMAL, TextCase::LOWERCASE, TextCase::UPPERCASE };
73 const std::vector<TextOverflow> TEXT_OVERFLOWS = { TextOverflow::NONE, TextOverflow::CLIP, TextOverflow::ELLIPSIS,
74 TextOverflow::MARQUEE };
75 const std::vector<FontStyle> FONT_STYLES = { FontStyle::NORMAL, FontStyle::ITALIC };
76 const std::vector<TextAlign> TEXT_ALIGNS = { TextAlign::START, TextAlign::CENTER, TextAlign::END, TextAlign::JUSTIFY,
77 TextAlign::LEFT, TextAlign::RIGHT };
78 const std::vector<TextHeightAdaptivePolicy> HEIGHT_ADAPTIVE_POLICY = { TextHeightAdaptivePolicy::MAX_LINES_FIRST,
79 TextHeightAdaptivePolicy::MIN_FONT_SIZE_FIRST, TextHeightAdaptivePolicy::LAYOUT_CONSTRAINT_FIRST };
80 }; // namespace
81
SetWidth(const JSCallbackInfo & info)82 void JSText::SetWidth(const JSCallbackInfo& info)
83 {
84 JSViewAbstract::JsWidth(info);
85 TextModel::GetInstance()->OnSetWidth();
86 }
87
SetHeight(const JSCallbackInfo & info)88 void JSText::SetHeight(const JSCallbackInfo& info)
89 {
90 JSViewAbstract::JsHeight(info);
91 TextModel::GetInstance()->OnSetHeight();
92 }
93
SetFont(const JSCallbackInfo & info)94 void JSText::SetFont(const JSCallbackInfo& info)
95 {
96 Font font;
97 GetFontInfo(info, font);
98 TextModel::GetInstance()->SetFont(font);
99 }
100
GetFontInfo(const JSCallbackInfo & info,Font & font)101 void JSText::GetFontInfo(const JSCallbackInfo& info, Font& font)
102 {
103 auto tmpInfo = info[0];
104 if (!tmpInfo->IsObject()) {
105 return;
106 }
107 auto paramObject = JSRef<JSObject>::Cast(tmpInfo);
108 auto fontSize = paramObject->GetProperty("size");
109 CalcDimension size;
110 if (!JSContainerBase::ParseJsDimensionFp(fontSize, size) || fontSize->IsNull()) {
111 font.fontSize = std::nullopt;
112 } else {
113 if (fontSize->IsUndefined() || size.IsNegative() || size.Unit() == DimensionUnit::PERCENT) {
114 auto pipelineContext = PipelineContext::GetCurrentContext();
115 CHECK_NULL_VOID_NOLOG(pipelineContext);
116 auto theme = pipelineContext->GetTheme<TextTheme>();
117 CHECK_NULL_VOID_NOLOG(theme);
118 font.fontSize = theme->GetTextStyle().GetFontSize();
119 } else {
120 font.fontSize = size;
121 }
122 }
123 std::string weight;
124 auto fontWeight = paramObject->GetProperty("weight");
125 if (!fontWeight->IsNull()) {
126 if (fontWeight->IsNumber()) {
127 weight = std::to_string(fontWeight->ToNumber<int32_t>());
128 } else {
129 JSContainerBase::ParseJsString(fontWeight, weight);
130 }
131 font.fontWeight = ConvertStrToFontWeight(weight);
132 }
133 auto fontFamily = paramObject->GetProperty("family");
134 if (!fontFamily->IsNull()) {
135 std::vector<std::string> fontFamilies;
136 if (JSContainerBase::ParseJsFontFamilies(fontFamily, fontFamilies)) {
137 font.fontFamilies = fontFamilies;
138 }
139 }
140 auto style = paramObject->GetProperty("style");
141 if (!style->IsNull() || style->IsNumber()) {
142 font.fontStyle = static_cast<FontStyle>(style->ToNumber<int32_t>());
143 }
144 }
145
SetFontSize(const JSCallbackInfo & info)146 void JSText::SetFontSize(const JSCallbackInfo& info)
147 {
148 if (info.Length() < 1) {
149 LOGI("The argv is wrong, it is supposed to have at least 1 argument");
150 return;
151 }
152 auto pipelineContext = PipelineBase::GetCurrentContext();
153 CHECK_NULL_VOID_NOLOG(pipelineContext);
154 auto theme = pipelineContext->GetTheme<TextTheme>();
155 CHECK_NULL_VOID_NOLOG(theme);
156 CalcDimension fontSize = theme->GetTextStyle().GetFontSize();
157 ParseJsDimensionFp(info[0], fontSize);
158 if (fontSize.IsNegative() || fontSize.Unit() == DimensionUnit::PERCENT) {
159 fontSize = theme->GetTextStyle().GetFontSize();
160 }
161 TextModel::GetInstance()->SetFontSize(fontSize);
162 }
163
SetFontWeight(const std::string & value)164 void JSText::SetFontWeight(const std::string& value)
165 {
166 TextModel::GetInstance()->SetFontWeight(ConvertStrToFontWeight(value));
167 }
168
SetTextColor(const JSCallbackInfo & info)169 void JSText::SetTextColor(const JSCallbackInfo& info)
170 {
171 if (info.Length() < 1) {
172 LOGI("The argv is wrong, it is supposed to have at least 1 argument");
173 return;
174 }
175 Color textColor;
176 if (!ParseJsColor(info[0], textColor)) {
177 auto pipelineContext = PipelineBase::GetCurrentContext();
178 CHECK_NULL_VOID_NOLOG(pipelineContext);
179 auto theme = pipelineContext->GetTheme<TextTheme>();
180 CHECK_NULL_VOID_NOLOG(theme);
181 textColor = theme->GetTextStyle().GetTextColor();
182 }
183 TextModel::GetInstance()->SetTextColor(textColor);
184 }
185
SetTextShadow(const JSCallbackInfo & info)186 void JSText::SetTextShadow(const JSCallbackInfo& info)
187 {
188 if (info.Length() < 1) {
189 LOGW("The argv is wrong, it is supposed to have at least 1 argument");
190 return;
191 }
192 if (!info[0]->IsNumber() && !info[0]->IsObject()) {
193 LOGW("info[0] not is Object or Number");
194 return;
195 }
196 int32_t shadowStyle = 0;
197 if (ParseJsInteger<int32_t>(info[0], shadowStyle)) {
198 auto style = static_cast<ShadowStyle>(shadowStyle);
199 Shadow shadow = Shadow::CreateShadow(style);
200 TextModel::GetInstance()->SetTextShadow(shadow);
201 return;
202 }
203
204 auto jsObject = JSRef<JSObject>::Cast(info[0]);
205 Shadow shadow;
206 double radius = 0.0;
207 if (ParseJsDouble(jsObject->GetProperty("radius"), radius)) {
208 if (LessNotEqual(radius, 0.0)) {
209 radius = 0.0;
210 }
211 shadow.SetBlurRadius(radius);
212 CalcDimension offsetX;
213 if (ParseJsDimensionVp(jsObject->GetProperty("offsetX"), offsetX)) {
214 shadow.SetOffsetX(offsetX.Value());
215 }
216 CalcDimension offsetY;
217 if (ParseJsDimensionVp(jsObject->GetProperty("offsetY"), offsetY)) {
218 shadow.SetOffsetY(offsetY.Value());
219 }
220 Color color;
221 if (ParseJsColor(jsObject->GetProperty("color"), color)) {
222 shadow.SetColor(color);
223 }
224 }
225 TextModel::GetInstance()->SetTextShadow(shadow);
226 }
227
SetTextOverflow(const JSCallbackInfo & info)228 void JSText::SetTextOverflow(const JSCallbackInfo& info)
229 {
230 do {
231 auto tmpInfo = info[0];
232 if (!tmpInfo->IsObject()) {
233 break;
234 }
235 JSRef<JSObject> obj = JSRef<JSObject>::Cast(tmpInfo);
236 JSRef<JSVal> overflowValue = obj->GetProperty("overflow");
237 if (!overflowValue->IsNumber()) {
238 break;
239 }
240 auto overflow = overflowValue->ToNumber<int32_t>();
241 if (overflow < 0 || overflow >= static_cast<int32_t>(TEXT_OVERFLOWS.size())) {
242 LOGI("Text: textOverflow(%{public}d) illegal value", overflow);
243 break;
244 }
245 TextModel::GetInstance()->SetTextOverflow(TEXT_OVERFLOWS[overflow]);
246 } while (false);
247
248 info.SetReturnValue(info.This());
249 }
250
SetMaxLines(const JSCallbackInfo & info)251 void JSText::SetMaxLines(const JSCallbackInfo& info)
252 {
253 int32_t value = Infinity<uint32_t>();
254 if (info[0]->ToString() != "Infinity") {
255 ParseJsInt32(info[0], value);
256 }
257 TextModel::GetInstance()->SetMaxLines(value);
258 }
259
SetTextIndent(const JSCallbackInfo & info)260 void JSText::SetTextIndent(const JSCallbackInfo& info)
261 {
262 if (info.Length() < 1) {
263 LOGE("The argv is wrong, it is supposed to have at least 1 argument");
264 return;
265 }
266 CalcDimension value;
267 if (!ParseJsDimensionFp(info[0], value)) {
268 TextModel::GetInstance()->SetTextIndent(value);
269 return;
270 }
271 TextModel::GetInstance()->SetTextIndent(value);
272 }
273
SetFontStyle(int32_t value)274 void JSText::SetFontStyle(int32_t value)
275 {
276 if (value < 0 || value >= static_cast<int32_t>(FONT_STYLES.size())) {
277 LOGI("Text fontStyle(%{public}d) illegal value", value);
278 return;
279 }
280 TextModel::GetInstance()->SetItalicFontStyle(FONT_STYLES[value]);
281 }
282
SetTextAlign(int32_t value)283 void JSText::SetTextAlign(int32_t value)
284 {
285 if (value < 0 || value >= static_cast<int32_t>(TEXT_ALIGNS.size())) {
286 LOGI("Text: TextAlign(%d) expected positive number", value);
287 return;
288 }
289 TextModel::GetInstance()->SetTextAlign(TEXT_ALIGNS[value]);
290 }
291
SetAlign(const JSCallbackInfo & info)292 void JSText::SetAlign(const JSCallbackInfo& info)
293 {
294 JSViewAbstract::JsAlign(info);
295 if (!info[0]->IsNumber()) {
296 return;
297 }
298 TextModel::GetInstance()->OnSetAlign();
299 }
300
SetLineHeight(const JSCallbackInfo & info)301 void JSText::SetLineHeight(const JSCallbackInfo& info)
302 {
303 if (info.Length() < 1) {
304 LOGI("The argv is wrong, it is supposed to have at least 1 argument");
305 return;
306 }
307 CalcDimension value;
308 ParseJsDimensionFp(info[0], value);
309 if (value.IsNegative()) {
310 value.Reset();
311 }
312 TextModel::GetInstance()->SetLineHeight(value);
313 }
314
SetFontFamily(const JSCallbackInfo & info)315 void JSText::SetFontFamily(const JSCallbackInfo& info)
316 {
317 if (info.Length() < 1) {
318 LOGI("The argv is wrong, it is supposed to have at least 1 argument");
319 return;
320 }
321 std::vector<std::string> fontFamilies;
322 if (!ParseJsFontFamilies(info[0], fontFamilies)) {
323 LOGI("Parse FontFamilies failed");
324 return;
325 }
326 TextModel::GetInstance()->SetFontFamily(fontFamilies);
327 }
328
SetMinFontSize(const JSCallbackInfo & info)329 void JSText::SetMinFontSize(const JSCallbackInfo& info)
330 {
331 if (info.Length() < 1) {
332 LOGI("The argv is wrong, it is supposed to have at least 1 argument");
333 return;
334 }
335 CalcDimension fontSize;
336 ParseJsDimensionFp(info[0], fontSize);
337 TextModel::GetInstance()->SetAdaptMinFontSize(fontSize);
338 }
339
SetMaxFontSize(const JSCallbackInfo & info)340 void JSText::SetMaxFontSize(const JSCallbackInfo& info)
341 {
342 if (info.Length() < 1) {
343 LOGI("The argv is wrong, it is supposed to have at least 1 argument");
344 return;
345 }
346 CalcDimension fontSize;
347 ParseJsDimensionFp(info[0], fontSize);
348 TextModel::GetInstance()->SetAdaptMaxFontSize(fontSize);
349 }
350
SetLetterSpacing(const JSCallbackInfo & info)351 void JSText::SetLetterSpacing(const JSCallbackInfo& info)
352 {
353 if (info.Length() < 1) {
354 LOGI("The argv is wrong, it is supposed to have at least 1 argument");
355 return;
356 }
357 if (info[0]->IsString()) {
358 auto value = info[0]->ToString();
359 if (!value.empty() && value.back() == '%') {
360 auto pipelineContext = PipelineBase::GetCurrentContext();
361 CHECK_NULL_VOID_NOLOG(pipelineContext);
362 auto theme = pipelineContext->GetTheme<TextTheme>();
363 CHECK_NULL_VOID_NOLOG(theme);
364 CalcDimension defaultValue = theme->GetTextStyle().GetLetterSpacing();
365 TextModel::GetInstance()->SetLetterSpacing(defaultValue);
366 return;
367 }
368 }
369 CalcDimension value;
370 if (!ParseJsDimensionFp(info[0], value)) {
371 return;
372 }
373 TextModel::GetInstance()->SetLetterSpacing(value);
374 }
375
SetTextCase(int32_t value)376 void JSText::SetTextCase(int32_t value)
377 {
378 if (value < 0 || value >= static_cast<int32_t>(TEXT_CASES.size())) {
379 LOGI("Text textCase(%{public}d) illegal value", value);
380 return;
381 }
382 TextModel::GetInstance()->SetTextCase(TEXT_CASES[value]);
383 }
384
SetBaselineOffset(const JSCallbackInfo & info)385 void JSText::SetBaselineOffset(const JSCallbackInfo& info)
386 {
387 if (info.Length() < 1) {
388 LOGI("The argv is wrong, it is supposed to have at least 1 argument");
389 return;
390 }
391 CalcDimension value;
392 if (!ParseJsDimensionFp(info[0], value)) {
393 return;
394 }
395 TextModel::GetInstance()->SetBaselineOffset(value);
396 }
397
SetDecoration(const JSCallbackInfo & info)398 void JSText::SetDecoration(const JSCallbackInfo& info)
399 {
400 do {
401 auto tmpInfo = info[0];
402 if (!tmpInfo->IsObject()) {
403 break;
404 }
405 JSRef<JSObject> obj = JSRef<JSObject>::Cast(tmpInfo);
406 JSRef<JSVal> typeValue = obj->GetProperty("type");
407 JSRef<JSVal> colorValue = obj->GetProperty("color");
408 auto pipelineContext = PipelineBase::GetCurrentContext();
409 CHECK_NULL_VOID_NOLOG(pipelineContext);
410 auto theme = pipelineContext->GetTheme<TextTheme>();
411 CHECK_NULL_VOID_NOLOG(theme);
412 TextDecoration textDecoration = theme->GetTextStyle().GetTextDecoration();
413 if (typeValue->IsNumber()) {
414 textDecoration = static_cast<TextDecoration>(typeValue->ToNumber<int32_t>());
415 }
416 Color result = theme->GetTextStyle().GetTextDecorationColor();
417 ParseJsColor(colorValue, result);
418 TextModel::GetInstance()->SetTextDecoration(textDecoration);
419 TextModel::GetInstance()->SetTextDecorationColor(result);
420 } while (false);
421 info.SetReturnValue(info.This());
422 }
423
SetHeightAdaptivePolicy(int32_t value)424 void JSText::SetHeightAdaptivePolicy(int32_t value)
425 {
426 if (value < 0 || value >= static_cast<int32_t>(HEIGHT_ADAPTIVE_POLICY.size())) {
427 LOGW("Text: HeightAdaptivePolicy(%d) expected positive number", value);
428 return;
429 }
430 TextModel::GetInstance()->SetHeightAdaptivePolicy(HEIGHT_ADAPTIVE_POLICY[value]);
431 }
432
JsOnClick(const JSCallbackInfo & info)433 void JSText::JsOnClick(const JSCallbackInfo& info)
434 {
435 if (Container::IsCurrentUseNewPipeline()) {
436 if (info[0]->IsUndefined() && IsDisableEventVersion()) {
437 LOGD("JsOnClick callback is undefined");
438 TextModel::GetInstance()->ClearOnClick();
439 return;
440 }
441 if (!info[0]->IsFunction()) {
442 LOGW("the info is not click function");
443 return;
444 }
445 auto jsOnClickFunc = AceType::MakeRefPtr<JsClickFunction>(JSRef<JSFunc>::Cast(info[0]));
446 auto onClick = [execCtx = info.GetExecutionContext(), func = jsOnClickFunc](const BaseEventInfo* info) {
447 JAVASCRIPT_EXECUTION_SCOPE_WITH_CHECK(execCtx);
448 LOGD("About to call onclick method on js");
449 const auto* clickInfo = TypeInfoHelper::DynamicCast<GestureEvent>(info);
450 ACE_SCORING_EVENT("Text.onClick");
451 func->Execute(*clickInfo);
452 };
453 TextModel::GetInstance()->SetOnClick(std::move(onClick));
454 } else {
455 #ifndef NG_BUILD
456 if (info[0]->IsFunction()) {
457 auto inspector = ViewStackProcessor::GetInstance()->GetInspectorComposedComponent();
458 auto impl = inspector ? inspector->GetInspectorFunctionImpl() : nullptr;
459 RefPtr<JsClickFunction> jsOnClickFunc = AceType::MakeRefPtr<JsClickFunction>(JSRef<JSFunc>::Cast(info[0]));
460 auto onClickId = [execCtx = info.GetExecutionContext(), func = std::move(jsOnClickFunc), impl](
461 const BaseEventInfo* info) {
462 JAVASCRIPT_EXECUTION_SCOPE_WITH_CHECK(execCtx);
463 LOGD("About to call onclick method on js");
464 const auto* clickInfo = TypeInfoHelper::DynamicCast<ClickInfo>(info);
465 auto newInfo = *clickInfo;
466 if (impl) {
467 impl->UpdateEventInfo(newInfo);
468 }
469 ACE_SCORING_EVENT("Text.onClick");
470 func->Execute(newInfo);
471 };
472 TextModel::GetInstance()->SetOnClick(std::move(onClickId));
473 }
474 #endif
475 }
476 }
477
JsRemoteMessage(const JSCallbackInfo & info)478 void JSText::JsRemoteMessage(const JSCallbackInfo& info)
479 {
480 JSInteractableView::JsCommonRemoteMessage(info);
481 auto callback = JSInteractableView::GetRemoteMessageEventCallback(info);
482 TextModel::GetInstance()->SetRemoteMessage(std::move(callback));
483 }
484
Create(const JSCallbackInfo & info)485 void JSText::Create(const JSCallbackInfo& info)
486 {
487 std::string data;
488 if (info.Length() > 0) {
489 ParseJsString(info[0], data);
490 }
491
492 TextModel::GetInstance()->Create(data);
493 }
494
SetCopyOption(const JSCallbackInfo & info)495 void JSText::SetCopyOption(const JSCallbackInfo& info)
496 {
497 if (info.Length() == 0) {
498 return;
499 }
500 auto copyOptions = CopyOptions::None;
501 auto tmpInfo = info[0];
502 if (tmpInfo->IsNumber()) {
503 auto emunNumber = tmpInfo->ToNumber<int>();
504 copyOptions = static_cast<CopyOptions>(emunNumber);
505 }
506 TextModel::GetInstance()->SetCopyOption(copyOptions);
507 }
508
JsOnDragStart(const JSCallbackInfo & info)509 void JSText::JsOnDragStart(const JSCallbackInfo& info)
510 {
511 CHECK_NULL_VOID(info[0]->IsFunction());
512 RefPtr<JsDragFunction> jsOnDragStartFunc = AceType::MakeRefPtr<JsDragFunction>(JSRef<JSFunc>::Cast(info[0]));
513 auto onDragStart = [execCtx = info.GetExecutionContext(), func = std::move(jsOnDragStartFunc)](
514 const RefPtr<DragEvent>& info, const std::string& extraParams) -> NG::DragDropBaseInfo {
515 NG::DragDropBaseInfo itemInfo;
516 JAVASCRIPT_EXECUTION_SCOPE_WITH_CHECK(execCtx, itemInfo);
517
518 auto ret = func->Execute(info, extraParams);
519 if (!ret->IsObject()) {
520 LOGI("builder param is not an object.");
521 return itemInfo;
522 }
523 auto node = ParseDragNode(ret);
524 if (node) {
525 LOGI("use custom builder param.");
526 itemInfo.node = node;
527 return itemInfo;
528 }
529
530 auto builderObj = JSRef<JSObject>::Cast(ret);
531 #if defined(PIXEL_MAP_SUPPORTED)
532 auto pixmap = builderObj->GetProperty("pixelMap");
533 itemInfo.pixelMap = CreatePixelMapFromNapiValue(pixmap);
534 #endif
535 auto extraInfo = builderObj->GetProperty("extraInfo");
536 ParseJsString(extraInfo, itemInfo.extraInfo);
537 node = ParseDragNode(builderObj->GetProperty("builder"));
538 itemInfo.node = node;
539 return itemInfo;
540 };
541
542 TextModel::GetInstance()->SetOnDragStart(std::move(onDragStart));
543 }
544
JsOnDragEnter(const JSCallbackInfo & info)545 void JSText::JsOnDragEnter(const JSCallbackInfo& info)
546 {
547 CHECK_NULL_VOID(info[0]->IsFunction());
548 RefPtr<JsDragFunction> jsOnDragEnterFunc = AceType::MakeRefPtr<JsDragFunction>(JSRef<JSFunc>::Cast(info[0]));
549 auto onDragEnterId = [execCtx = info.GetExecutionContext(), func = std::move(jsOnDragEnterFunc)](
550 const RefPtr<DragEvent>& info, const std::string& extraParams) {
551 JAVASCRIPT_EXECUTION_SCOPE_WITH_CHECK(execCtx);
552 ACE_SCORING_EVENT("onDragEnter");
553 func->Execute(info, extraParams);
554 };
555 TextModel::GetInstance()->SetOnDragEnter(std::move(onDragEnterId));
556 }
557
JsOnDragMove(const JSCallbackInfo & info)558 void JSText::JsOnDragMove(const JSCallbackInfo& info)
559 {
560 CHECK_NULL_VOID(info[0]->IsFunction());
561 RefPtr<JsDragFunction> jsOnDragMoveFunc = AceType::MakeRefPtr<JsDragFunction>(JSRef<JSFunc>::Cast(info[0]));
562 auto onDragMoveId = [execCtx = info.GetExecutionContext(), func = std::move(jsOnDragMoveFunc)](
563 const RefPtr<DragEvent>& info, const std::string& extraParams) {
564 JAVASCRIPT_EXECUTION_SCOPE_WITH_CHECK(execCtx);
565 ACE_SCORING_EVENT("onDragMove");
566 func->Execute(info, extraParams);
567 };
568 TextModel::GetInstance()->SetOnDragMove(std::move(onDragMoveId));
569 }
570
JsOnDragLeave(const JSCallbackInfo & info)571 void JSText::JsOnDragLeave(const JSCallbackInfo& info)
572 {
573 CHECK_NULL_VOID(info[0]->IsFunction());
574 RefPtr<JsDragFunction> jsOnDragLeaveFunc = AceType::MakeRefPtr<JsDragFunction>(JSRef<JSFunc>::Cast(info[0]));
575 auto onDragLeaveId = [execCtx = info.GetExecutionContext(), func = std::move(jsOnDragLeaveFunc)](
576 const RefPtr<DragEvent>& info, const std::string& extraParams) {
577 JAVASCRIPT_EXECUTION_SCOPE_WITH_CHECK(execCtx);
578 ACE_SCORING_EVENT("onDragLeave");
579 func->Execute(info, extraParams);
580 };
581 TextModel::GetInstance()->SetOnDragLeave(std::move(onDragLeaveId));
582 }
583
JsOnDrop(const JSCallbackInfo & info)584 void JSText::JsOnDrop(const JSCallbackInfo& info)
585 {
586 CHECK_NULL_VOID(info[0]->IsFunction());
587 RefPtr<JsDragFunction> jsOnDropFunc = AceType::MakeRefPtr<JsDragFunction>(JSRef<JSFunc>::Cast(info[0]));
588 auto onDropId = [execCtx = info.GetExecutionContext(), func = std::move(jsOnDropFunc)](
589 const RefPtr<DragEvent>& info, const std::string& extraParams) {
590 JAVASCRIPT_EXECUTION_SCOPE_WITH_CHECK(execCtx);
591 ACE_SCORING_EVENT("onDrop");
592 func->Execute(info, extraParams);
593 };
594 TextModel::GetInstance()->SetOnDrop(std::move(onDropId));
595 }
596
JsFocusable(const JSCallbackInfo & info)597 void JSText::JsFocusable(const JSCallbackInfo& info)
598 {
599 auto tmpInfo = info[0];
600 if (!tmpInfo->IsBoolean()) {
601 LOGI("The info is wrong, it is supposed to be an boolean");
602 return;
603 }
604 JSInteractableView::SetFocusable(tmpInfo->ToBoolean());
605 JSInteractableView::SetFocusNode(false);
606 }
607
JsDraggable(const JSCallbackInfo & info)608 void JSText::JsDraggable(const JSCallbackInfo& info)
609 {
610 auto tmpInfo = info[0];
611 if (!tmpInfo->IsBoolean()) {
612 LOGI("The info is wrong, it is supposed to be an boolean");
613 return;
614 }
615 TextModel::GetInstance()->SetDraggable(tmpInfo->ToBoolean());
616 }
617
JsMenuOptionsExtension(const JSCallbackInfo & info)618 void JSText::JsMenuOptionsExtension(const JSCallbackInfo& info)
619 {
620 if (Container::IsCurrentUseNewPipeline()) {
621 auto tmpInfo = info[0];
622 if (tmpInfo->IsArray()) {
623 std::vector<NG::MenuOptionsParam> menuOptionsItems;
624 JSViewAbstract::ParseMenuOptions(info, JSRef<JSArray>::Cast(tmpInfo), menuOptionsItems);
625 TextModel::GetInstance()->SetMenuOptionItems(std::move(menuOptionsItems));
626 }
627 } else {
628 LOGI("only newPipeline supply");
629 }
630 }
631
JSBind(BindingTarget globalObj)632 void JSText::JSBind(BindingTarget globalObj)
633 {
634 JSClass<JSText>::Declare("Text");
635 MethodOptions opt = MethodOptions::NONE;
636 JSClass<JSText>::StaticMethod("create", &JSText::Create, opt);
637 JSClass<JSText>::StaticMethod("width", &JSText::SetWidth);
638 JSClass<JSText>::StaticMethod("height", &JSText::SetHeight);
639 JSClass<JSText>::StaticMethod("font", &JSText::SetFont, opt);
640 JSClass<JSText>::StaticMethod("fontColor", &JSText::SetTextColor, opt);
641 JSClass<JSText>::StaticMethod("textShadow", &JSText::SetTextShadow, opt);
642 JSClass<JSText>::StaticMethod("fontSize", &JSText::SetFontSize, opt);
643 JSClass<JSText>::StaticMethod("fontWeight", &JSText::SetFontWeight, opt);
644 JSClass<JSText>::StaticMethod("maxLines", &JSText::SetMaxLines, opt);
645 JSClass<JSText>::StaticMethod("textIndent", &JSText::SetTextIndent);
646 JSClass<JSText>::StaticMethod("textOverflow", &JSText::SetTextOverflow, opt);
647 JSClass<JSText>::StaticMethod("fontStyle", &JSText::SetFontStyle, opt);
648 JSClass<JSText>::StaticMethod("align", &JSText::SetAlign, opt);
649 JSClass<JSText>::StaticMethod("textAlign", &JSText::SetTextAlign, opt);
650 JSClass<JSText>::StaticMethod("lineHeight", &JSText::SetLineHeight, opt);
651 JSClass<JSText>::StaticMethod("fontFamily", &JSText::SetFontFamily, opt);
652 JSClass<JSText>::StaticMethod("minFontSize", &JSText::SetMinFontSize, opt);
653 JSClass<JSText>::StaticMethod("maxFontSize", &JSText::SetMaxFontSize, opt);
654 JSClass<JSText>::StaticMethod("letterSpacing", &JSText::SetLetterSpacing, opt);
655 JSClass<JSText>::StaticMethod("textCase", &JSText::SetTextCase, opt);
656 JSClass<JSText>::StaticMethod("baselineOffset", &JSText::SetBaselineOffset, opt);
657 JSClass<JSText>::StaticMethod("decoration", &JSText::SetDecoration);
658 JSClass<JSText>::StaticMethod("heightAdaptivePolicy", &JSText::SetHeightAdaptivePolicy);
659 JSClass<JSText>::StaticMethod("onTouch", &JSInteractableView::JsOnTouch);
660 JSClass<JSText>::StaticMethod("onHover", &JSInteractableView::JsOnHover);
661 JSClass<JSText>::StaticMethod("onKeyEvent", &JSInteractableView::JsOnKey);
662 JSClass<JSText>::StaticMethod("onDeleteEvent", &JSInteractableView::JsOnDelete);
663 JSClass<JSText>::StaticMethod("remoteMessage", &JSText::JsRemoteMessage);
664 JSClass<JSText>::StaticMethod("copyOption", &JSText::SetCopyOption);
665 JSClass<JSText>::StaticMethod("onClick", &JSText::JsOnClick);
666 JSClass<JSText>::StaticMethod("onAppear", &JSInteractableView::JsOnAppear);
667 JSClass<JSText>::StaticMethod("onDisAppear", &JSInteractableView::JsOnDisAppear);
668 JSClass<JSText>::StaticMethod("onDragStart", &JSText::JsOnDragStart);
669 JSClass<JSText>::StaticMethod("onDragEnter", &JSText::JsOnDragEnter);
670 JSClass<JSText>::StaticMethod("onDragMove", &JSText::JsOnDragMove);
671 JSClass<JSText>::StaticMethod("onDragLeave", &JSText::JsOnDragLeave);
672 JSClass<JSText>::StaticMethod("onDrop", &JSText::JsOnDrop);
673 JSClass<JSText>::StaticMethod("focusable", &JSText::JsFocusable);
674 JSClass<JSText>::StaticMethod("draggable", &JSText::JsDraggable);
675 JSClass<JSText>::StaticMethod("textMenuOptions", &JSText::JsMenuOptionsExtension);
676 JSClass<JSText>::InheritAndBind<JSContainerBase>(globalObj);
677 }
678
679 } // namespace OHOS::Ace::Framework
680