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 <cstdint>
19 #include <sstream>
20 #include <string>
21 #include <vector>
22 #if !defined(PREVIEW) && defined(OHOS_PLATFORM)
23 #include "core/components_ng/pattern/text/text_layout_property.h"
24 #include "interfaces/inner_api/ui_session/ui_session_manager.h"
25 #endif
26
27 #include "base/geometry/dimension.h"
28 #include "base/log/ace_scoring_log.h"
29 #include "base/log/ace_trace.h"
30 #include "base/utils/utils.h"
31 #include "bridge/common/utils/utils.h"
32 #include "bridge/declarative_frontend/ark_theme/theme_apply/js_text_theme.h"
33 #include "bridge/declarative_frontend/engine/functions/js_click_function.h"
34 #include "bridge/declarative_frontend/engine/functions/js_drag_function.h"
35 #include "bridge/declarative_frontend/engine/functions/js_function.h"
36 #include "bridge/declarative_frontend/engine/jsi/js_ui_index.h"
37 #include "bridge/declarative_frontend/jsview/js_interactable_view.h"
38 #include "bridge/declarative_frontend/jsview/js_layout_manager.h"
39 #include "bridge/declarative_frontend/jsview/js_text.h"
40 #include "bridge/declarative_frontend/jsview/js_utils.h"
41 #include "bridge/declarative_frontend/jsview/js_view_abstract.h"
42 #include "bridge/declarative_frontend/jsview/js_view_common_def.h"
43 #include "bridge/declarative_frontend/jsview/models/text_model_impl.h"
44 #include "bridge/declarative_frontend/style_string/js_span_string.h"
45 #include "bridge/declarative_frontend/view_stack_processor.h"
46 #include "core/common/container.h"
47 #include "core/components/common/layout/constants.h"
48 #include "core/components/common/properties/text_style_parser.h"
49 #include "core/components/text/text_theme.h"
50 #include "core/components_ng/base/view_stack_processor.h"
51 #include "core/components_ng/event/gesture_event_hub.h"
52 #include "core/components_ng/pattern/text/text_model.h"
53 #include "core/components_ng/pattern/text/text_model_ng.h"
54 #include "core/event/ace_event_handler.h"
55 #include "core/pipeline/pipeline_base.h"
56
57 namespace OHOS::Ace {
58
59 std::unique_ptr<TextModel> TextModel::instance_ = nullptr;
60 std::mutex TextModel::mutex_;
61
GetInstance()62 TextModel* TextModel::GetInstance()
63 {
64 if (!instance_) {
65 std::lock_guard<std::mutex> lock(mutex_);
66 if (!instance_) {
67 #ifdef NG_BUILD
68 instance_.reset(new NG::TextModelNG());
69 #else
70 if (Container::IsCurrentUseNewPipeline()) {
71 instance_.reset(new NG::TextModelNG());
72 } else {
73 instance_.reset(new Framework::TextModelImpl());
74 }
75 #endif
76 }
77 }
78 return instance_.get();
79 }
80
81 } // namespace OHOS::Ace
82
83 namespace OHOS::Ace::Framework {
84 namespace {
85
86 const std::vector<TextCase> TEXT_CASES = { TextCase::NORMAL, TextCase::LOWERCASE, TextCase::UPPERCASE };
87 const std::vector<TextOverflow> TEXT_OVERFLOWS = { TextOverflow::NONE, TextOverflow::CLIP, TextOverflow::ELLIPSIS,
88 TextOverflow::MARQUEE };
89 const std::vector<FontStyle> FONT_STYLES = { FontStyle::NORMAL, FontStyle::ITALIC };
90 const std::vector<TextAlign> TEXT_ALIGNS = { TextAlign::START, TextAlign::CENTER, TextAlign::END, TextAlign::JUSTIFY,
91 TextAlign::LEFT, TextAlign::RIGHT };
92 const std::vector<TextHeightAdaptivePolicy> HEIGHT_ADAPTIVE_POLICY = { TextHeightAdaptivePolicy::MAX_LINES_FIRST,
93 TextHeightAdaptivePolicy::MIN_FONT_SIZE_FIRST, TextHeightAdaptivePolicy::LAYOUT_CONSTRAINT_FIRST };
94 const std::vector<LineBreakStrategy> LINE_BREAK_STRATEGY_TYPES = { LineBreakStrategy::GREEDY,
95 LineBreakStrategy::HIGH_QUALITY, LineBreakStrategy::BALANCED };
96 const std::vector<EllipsisMode> ELLIPSIS_MODALS = { EllipsisMode::HEAD, EllipsisMode::MIDDLE, EllipsisMode::TAIL };
97 const std::vector<TextSelectableMode> TEXT_SELECTABLE_MODE = { TextSelectableMode::SELECTABLE_UNFOCUSABLE,
98 TextSelectableMode::SELECTABLE_FOCUSABLE, TextSelectableMode::UNSELECTABLE };
99 constexpr TextDecorationStyle DEFAULT_TEXT_DECORATION_STYLE = TextDecorationStyle::SOLID;
100 const int32_t DEFAULT_VARIABLE_FONT_WEIGHT = 400;
101 }; // namespace
102
SetWidth(const JSCallbackInfo & info)103 void JSText::SetWidth(const JSCallbackInfo& info)
104 {
105 JSViewAbstract::JsWidth(info);
106 TextModel::GetInstance()->OnSetWidth();
107 }
108
SetHeight(const JSCallbackInfo & info)109 void JSText::SetHeight(const JSCallbackInfo& info)
110 {
111 JSViewAbstract::JsHeight(info);
112 TextModel::GetInstance()->OnSetHeight();
113 }
114
SetFont(const JSCallbackInfo & info)115 void JSText::SetFont(const JSCallbackInfo& info)
116 {
117 Font font;
118 GetFontInfo(info, font);
119 TextModel::GetInstance()->SetFont(font);
120 if (info.Length() < 2) { // 2 : two args
121 return;
122 }
123 auto tmpInfo = info[1];
124 if (!tmpInfo->IsObject()) {
125 return;
126 }
127 auto paramObject = JSRef<JSObject>::Cast(tmpInfo);
128 auto enableVariableFontWeight = paramObject->GetProperty("enableVariableFontWeight");
129 if (enableVariableFontWeight->IsBoolean()) {
130 TextModel::GetInstance()->SetEnableVariableFontWeight(enableVariableFontWeight->ToBoolean());
131 } else {
132 TextModel::GetInstance()->SetEnableVariableFontWeight(false);
133 }
134 }
135
GetFontInfo(const JSCallbackInfo & info,Font & font)136 void JSText::GetFontInfo(const JSCallbackInfo& info, Font& font)
137 {
138 auto tmpInfo = info[0];
139 auto pipelineContext = PipelineContext::GetCurrentContext();
140 CHECK_NULL_VOID(pipelineContext);
141 auto theme = pipelineContext->GetTheme<TextTheme>();
142 CHECK_NULL_VOID(theme);
143 font.fontSize = theme->GetTextStyle().GetFontSize();
144 font.fontWeight = theme->GetTextStyle().GetFontWeight();
145 font.fontFamilies = theme->GetTextStyle().GetFontFamilies();
146 font.fontStyle = theme->GetTextStyle().GetFontStyle();
147
148 if (!tmpInfo->IsObject()) {
149 return;
150 }
151 auto paramObject = JSRef<JSObject>::Cast(tmpInfo);
152 auto fontSize = paramObject->GetProperty(static_cast<int32_t>(ArkUIIndex::SIZE));
153 CalcDimension size;
154 if (ParseJsDimensionFpNG(fontSize, size, false) && size.IsNonNegative()) {
155 font.fontSize = size;
156 }
157 std::string weight;
158 auto fontWeight = paramObject->GetProperty(static_cast<int32_t>(ArkUIIndex::WEIGHT));
159 if (!fontWeight->IsNull()) {
160 int32_t variableFontWeight = DEFAULT_VARIABLE_FONT_WEIGHT;
161 ParseJsInt32(fontWeight, variableFontWeight);
162 TextModel::GetInstance()->SetVariableFontWeight(variableFontWeight);
163 if (fontWeight->IsNumber()) {
164 weight = std::to_string(fontWeight->ToNumber<int32_t>());
165 } else {
166 JSContainerBase::ParseJsString(fontWeight, weight);
167 }
168 font.fontWeight = ConvertStrToFontWeight(weight);
169 }
170 auto fontFamily = paramObject->GetProperty(static_cast<int32_t>(ArkUIIndex::FAMILY));
171 if (!fontFamily->IsNull()) {
172 std::vector<std::string> fontFamilies;
173 if (JSContainerBase::ParseJsFontFamilies(fontFamily, fontFamilies)) {
174 font.fontFamilies = fontFamilies;
175 }
176 }
177 auto style = paramObject->GetProperty(static_cast<int32_t>(ArkUIIndex::STYLE));
178 if (!style->IsNull() || style->IsNumber()) {
179 font.fontStyle = static_cast<FontStyle>(style->ToNumber<int32_t>());
180 }
181 }
182
SetFontSize(const JSCallbackInfo & info)183 void JSText::SetFontSize(const JSCallbackInfo& info)
184 {
185 if (info.Length() < 1) {
186 return;
187 }
188 CalcDimension fontSize;
189 JSRef<JSVal> args = info[0];
190 if (!ParseJsDimensionFpNG(args, fontSize, false) || fontSize.IsNegative()) {
191 auto pipelineContext = PipelineBase::GetCurrentContext();
192 CHECK_NULL_VOID(pipelineContext);
193 auto theme = pipelineContext->GetTheme<TextTheme>();
194 CHECK_NULL_VOID(theme);
195 fontSize = theme->GetTextStyle().GetFontSize();
196 TextModel::GetInstance()->SetFontSize(fontSize);
197 return;
198 }
199 TextModel::GetInstance()->SetFontSize(fontSize);
200 }
201
SetFontWeight(const JSCallbackInfo & info)202 void JSText::SetFontWeight(const JSCallbackInfo& info)
203 {
204 if (info.Length() < 1) {
205 return;
206 }
207 JSRef<JSVal> args = info[0];
208 std::string fontWeight;
209 int32_t variableFontWeight = DEFAULT_VARIABLE_FONT_WEIGHT;
210 ParseJsInt32(args, variableFontWeight);
211 TextModel::GetInstance()->SetVariableFontWeight(variableFontWeight);
212
213 if (args->IsNumber()) {
214 fontWeight = args->ToString();
215 } else {
216 ParseJsString(args, fontWeight);
217 }
218 TextModel::GetInstance()->SetFontWeight(ConvertStrToFontWeight(fontWeight));
219
220 if (info.Length() < 2) { // 2 : two args
221 return;
222 }
223 auto tmpInfo = info[1];
224 if (!tmpInfo->IsObject()) {
225 return;
226 }
227 auto paramObject = JSRef<JSObject>::Cast(tmpInfo);
228 auto enableVariableFontWeight = paramObject->GetProperty("enableVariableFontWeight");
229 if (enableVariableFontWeight->IsBoolean()) {
230 TextModel::GetInstance()->SetEnableVariableFontWeight(enableVariableFontWeight->ToBoolean());
231 } else {
232 TextModel::GetInstance()->SetEnableVariableFontWeight(false);
233 }
234 }
235
SetMinFontScale(const JSCallbackInfo & info)236 void JSText::SetMinFontScale(const JSCallbackInfo& info)
237 {
238 double minFontScale;
239 if (info.Length() < 1 || !ParseJsDouble(info[0], minFontScale)) {
240 return;
241 }
242 if (LessOrEqual(minFontScale, 0.0f)) {
243 TextModel::GetInstance()->SetMinFontScale(0.0f);
244 return;
245 }
246 if (GreatOrEqual(minFontScale, 1.0f)) {
247 TextModel::GetInstance()->SetMinFontScale(1.0f);
248 return;
249 }
250 TextModel::GetInstance()->SetMinFontScale(static_cast<float>(minFontScale));
251 }
252
SetMaxFontScale(const JSCallbackInfo & info)253 void JSText::SetMaxFontScale(const JSCallbackInfo& info)
254 {
255 double maxFontScale;
256 if (info.Length() < 1 || !ParseJsDouble(info[0], maxFontScale)) {
257 return;
258 }
259 if (LessOrEqual(maxFontScale, 1.0f)) {
260 TextModel::GetInstance()->SetMaxFontScale(1.0f);
261 return;
262 }
263 TextModel::GetInstance()->SetMaxFontScale(static_cast<float>(maxFontScale));
264 }
265
SetForegroundColor(const JSCallbackInfo & info)266 void JSText::SetForegroundColor(const JSCallbackInfo& info)
267 {
268 if (info.Length() < 1) {
269 return;
270 }
271 ForegroundColorStrategy strategy;
272 if (ParseJsColorStrategy(info[0], strategy)) {
273 TextModel::GetInstance()->SetTextColor(Color::FOREGROUND);
274 ViewAbstractModel::GetInstance()->SetForegroundColorStrategy(strategy);
275 return;
276 }
277 SetTextColor(info);
278 }
279
SetTextColor(const JSCallbackInfo & info)280 void JSText::SetTextColor(const JSCallbackInfo& info)
281 {
282 if (info.Length() < 1) {
283 return;
284 }
285 Color textColor;
286 JSRef<JSVal> args = info[0];
287 if (!ParseJsColor(args, textColor)) {
288 auto pipelineContext = PipelineBase::GetCurrentContext();
289 CHECK_NULL_VOID(pipelineContext);
290 auto theme = pipelineContext->GetTheme<TextTheme>();
291 CHECK_NULL_VOID(theme);
292 textColor = theme->GetTextStyle().GetTextColor();
293 }
294 TextModel::GetInstance()->SetTextColor(textColor);
295 }
296
SetTextShadow(const JSCallbackInfo & info)297 void JSText::SetTextShadow(const JSCallbackInfo& info)
298 {
299 if (info.Length() < 1) {
300 return;
301 }
302 std::vector<Shadow> shadows;
303 JSRef<JSVal> args = info[0];
304 ParseTextShadowFromShadowObject(args, shadows);
305 TextModel::GetInstance()->SetTextShadow(shadows);
306 }
307
SetTextOverflow(const JSCallbackInfo & info)308 void JSText::SetTextOverflow(const JSCallbackInfo& info)
309 {
310 do {
311 auto tmpInfo = info[0];
312 if (!tmpInfo->IsObject()) {
313 break;
314 }
315 JSRef<JSObject> obj = JSRef<JSObject>::Cast(tmpInfo);
316 JSRef<JSVal> overflowValue = obj->GetProperty("overflow");
317 if (!overflowValue->IsNumber() && !overflowValue->IsUndefined()) {
318 break;
319 }
320 auto overflow = overflowValue->ToNumber<int32_t>();
321 if (overflowValue->IsUndefined()) {
322 overflow = 0;
323 } else if (overflow < 0 || overflow >= static_cast<int32_t>(TEXT_OVERFLOWS.size())) {
324 break;
325 }
326 TextModel::GetInstance()->SetTextOverflow(TEXT_OVERFLOWS[overflow]);
327 } while (false);
328
329 info.SetReturnValue(info.This());
330 }
331
SetWordBreak(const JSCallbackInfo & info)332 void JSText::SetWordBreak(const JSCallbackInfo& info)
333 {
334 JSRef<JSVal> args = info[0];
335 if (!args->IsNumber()) {
336 return;
337 }
338 uint32_t index = args->ToNumber<uint32_t>();
339 if (index < WORD_BREAK_TYPES.size()) {
340 TextModel::GetInstance()->SetWordBreak(WORD_BREAK_TYPES[index]);
341 }
342 }
343
SetEllipsisMode(const JSCallbackInfo & info)344 void JSText::SetEllipsisMode(const JSCallbackInfo& info)
345 {
346 JSRef<JSVal> args = info[0];
347 if (!args->IsNumber()) {
348 return;
349 }
350 uint32_t index = args->ToNumber<uint32_t>();
351 if (index < ELLIPSIS_MODALS.size()) {
352 TextModel::GetInstance()->SetEllipsisMode(ELLIPSIS_MODALS[index]);
353 }
354 }
355
SetLineBreakStrategy(const JSCallbackInfo & info)356 void JSText::SetLineBreakStrategy(const JSCallbackInfo& info)
357 {
358 if (info.Length() < 1) {
359 TextModel::GetInstance()->SetLineBreakStrategy(LineBreakStrategy::GREEDY);
360 return;
361 }
362 if (!info[0]->IsNumber()) {
363 TextModel::GetInstance()->SetLineBreakStrategy(LineBreakStrategy::GREEDY);
364 return;
365 }
366 auto index = info[0]->ToNumber<int32_t>();
367 if (index < 0 || index >= static_cast<int32_t>(LINE_BREAK_STRATEGY_TYPES.size())) {
368 TextModel::GetInstance()->SetLineBreakStrategy(LineBreakStrategy::GREEDY);
369 return;
370 }
371 TextModel::GetInstance()->SetLineBreakStrategy(LINE_BREAK_STRATEGY_TYPES[index]);
372 }
373
SetTextSelection(const JSCallbackInfo & info)374 void JSText::SetTextSelection(const JSCallbackInfo& info)
375 {
376 if (info.Length() < 1) {
377 return;
378 }
379 JSRef<JSVal> argsStartIndex = info[0];
380 JSRef<JSVal> argsEndIndex = info[1];
381 if (!argsStartIndex->IsNumber() || !argsEndIndex->IsNumber()) {
382 return;
383 }
384 auto startIndex = argsStartIndex->ToNumber<int32_t>();
385 auto endIndex = argsEndIndex->ToNumber<int32_t>();
386 if (startIndex == -1 && endIndex == -1) {
387 TextModel::GetInstance()->SetTextSelection(startIndex, endIndex);
388 return;
389 }
390 if (startIndex >= endIndex) {
391 return;
392 }
393 TextModel::GetInstance()->SetTextSelection(startIndex, endIndex);
394 }
395
SetTextSelectableMode(const JSCallbackInfo & info)396 void JSText::SetTextSelectableMode(const JSCallbackInfo& info)
397 {
398 if (info.Length() < 1) {
399 TextModel::GetInstance()->SetTextSelectableMode(TextSelectableMode::SELECTABLE_UNFOCUSABLE);
400 return;
401 }
402 if (!info[0]->IsNumber()) {
403 TextModel::GetInstance()->SetTextSelectableMode(TextSelectableMode::SELECTABLE_UNFOCUSABLE);
404 return;
405 }
406 auto index = info[0]->ToNumber<int32_t>();
407 if (index < 0 || index >= static_cast<int32_t>(TEXT_SELECTABLE_MODE.size())) {
408 TextModel::GetInstance()->SetTextSelectableMode(TextSelectableMode::SELECTABLE_UNFOCUSABLE);
409 return;
410 }
411 TextModel::GetInstance()->SetTextSelectableMode(TEXT_SELECTABLE_MODE[index]);
412 }
413
SetMaxLines(const JSCallbackInfo & info)414 void JSText::SetMaxLines(const JSCallbackInfo& info)
415 {
416 JSRef<JSVal> args = info[0];
417 auto value = Infinity<int32_t>();
418 if (args->ToString() != "Infinity") {
419 ParseJsInt32(args, value);
420 }
421 TextModel::GetInstance()->SetMaxLines(value);
422 }
423
SetTextIndent(const JSCallbackInfo & info)424 void JSText::SetTextIndent(const JSCallbackInfo& info)
425 {
426 CalcDimension value;
427 JSRef<JSVal> args = info[0];
428 if (!ParseJsDimensionFpNG(args, value)) {
429 value.Reset();
430 TextModel::GetInstance()->SetTextIndent(value);
431 return;
432 }
433 TextModel::GetInstance()->SetTextIndent(value);
434 }
435
SetFontStyle(int32_t value)436 void JSText::SetFontStyle(int32_t value)
437 {
438 if (value < 0 || value >= static_cast<int32_t>(FONT_STYLES.size())) {
439 if (!(AceApplicationInfo::GetInstance().GreatOrEqualTargetAPIVersion(PlatformVersion::VERSION_TWELVE))) {
440 return;
441 }
442 value = 0;
443 }
444 TextModel::GetInstance()->SetItalicFontStyle(FONT_STYLES[value]);
445 }
446
SetTextAlign(int32_t value)447 void JSText::SetTextAlign(int32_t value)
448 {
449 if (value < 0 || value >= static_cast<int32_t>(TEXT_ALIGNS.size())) {
450 if (!(AceApplicationInfo::GetInstance().GreatOrEqualTargetAPIVersion(PlatformVersion::VERSION_TWELVE))) {
451 return;
452 }
453 value = 0;
454 }
455 TextModel::GetInstance()->SetTextAlign(TEXT_ALIGNS[value]);
456 }
457
SetAlign(const JSCallbackInfo & info)458 void JSText::SetAlign(const JSCallbackInfo& info)
459 {
460 JSViewAbstract::JsAlign(info);
461 JSRef<JSVal> args = info[0];
462 if (!args->IsNumber()) {
463 return;
464 }
465 TextModel::GetInstance()->OnSetAlign();
466 }
467
SetLineHeight(const JSCallbackInfo & info)468 void JSText::SetLineHeight(const JSCallbackInfo& info)
469 {
470 CalcDimension value;
471 JSRef<JSVal> args = info[0];
472 if (!ParseJsDimensionFpNG(args, value)) {
473 value.Reset();
474 TextModel::GetInstance()->SetLineHeight(value);
475 return;
476 }
477 if (value.IsNegative()) {
478 value.Reset();
479 }
480 TextModel::GetInstance()->SetLineHeight(value);
481 }
482
SetLineSpacing(const JSCallbackInfo & info)483 void JSText::SetLineSpacing(const JSCallbackInfo& info)
484 {
485 CalcDimension value;
486 JSRef<JSVal> args = info[0];
487 if (!ParseLengthMetricsToPositiveDimension(args, value)) {
488 value.Reset();
489 }
490 if (value.IsNegative()) {
491 value.Reset();
492 }
493 TextModel::GetInstance()->SetLineSpacing(value);
494 }
495
SetFontFamily(const JSCallbackInfo & info)496 void JSText::SetFontFamily(const JSCallbackInfo& info)
497 {
498 std::vector<std::string> fontFamilies;
499 JSRef<JSVal> args = info[0];
500 ParseJsFontFamilies(args, fontFamilies);
501 TextModel::GetInstance()->SetFontFamily(fontFamilies);
502 }
503
SetMinFontSize(const JSCallbackInfo & info)504 void JSText::SetMinFontSize(const JSCallbackInfo& info)
505 {
506 if (info.Length() < 1) {
507 return;
508 }
509 auto pipelineContext = PipelineBase::GetCurrentContext();
510 CHECK_NULL_VOID(pipelineContext);
511 auto theme = pipelineContext->GetTheme<TextTheme>();
512 CHECK_NULL_VOID(theme);
513 CalcDimension minFontSize = theme->GetTextStyle().GetAdaptMinFontSize();
514 JSRef<JSVal> args = info[0];
515 if (!ParseJsDimensionFpNG(args, minFontSize, false)) {
516 minFontSize = theme->GetTextStyle().GetAdaptMinFontSize();
517 TextModel::GetInstance()->SetAdaptMinFontSize(minFontSize);
518 return;
519 }
520 if (minFontSize.IsNegative()) {
521 minFontSize = theme->GetTextStyle().GetAdaptMinFontSize();
522 }
523 TextModel::GetInstance()->SetAdaptMinFontSize(minFontSize);
524 }
525
SetMaxFontSize(const JSCallbackInfo & info)526 void JSText::SetMaxFontSize(const JSCallbackInfo& info)
527 {
528 if (info.Length() < 1) {
529 return;
530 }
531 auto pipelineContext = PipelineBase::GetCurrentContext();
532 CHECK_NULL_VOID(pipelineContext);
533 auto theme = pipelineContext->GetTheme<TextTheme>();
534 CHECK_NULL_VOID(theme);
535 CalcDimension maxFontSize = theme->GetTextStyle().GetAdaptMaxFontSize();
536 JSRef<JSVal> args = info[0];
537 if (!ParseJsDimensionFpNG(args, maxFontSize, false)) {
538 maxFontSize = theme->GetTextStyle().GetAdaptMaxFontSize();
539 TextModel::GetInstance()->SetAdaptMaxFontSize(maxFontSize);
540 return;
541 }
542 if (maxFontSize.IsNegative()) {
543 maxFontSize = theme->GetTextStyle().GetAdaptMaxFontSize();
544 }
545 TextModel::GetInstance()->SetAdaptMaxFontSize(maxFontSize);
546 }
547
SetLetterSpacing(const JSCallbackInfo & info)548 void JSText::SetLetterSpacing(const JSCallbackInfo& info)
549 {
550 CalcDimension value;
551 JSRef<JSVal> args = info[0];
552 if (!ParseJsDimensionFpNG(args, value, false)) {
553 value.Reset();
554 TextModel::GetInstance()->SetLetterSpacing(value);
555 return;
556 }
557 TextModel::GetInstance()->SetLetterSpacing(value);
558 }
559
SetTextCase(int32_t value)560 void JSText::SetTextCase(int32_t value)
561 {
562 if (value < 0 || value >= static_cast<int32_t>(TEXT_CASES.size())) {
563 if (!(AceApplicationInfo::GetInstance().GreatOrEqualTargetAPIVersion(PlatformVersion::VERSION_TWELVE))) {
564 return;
565 }
566 value = 0;
567 }
568 TextModel::GetInstance()->SetTextCase(TEXT_CASES[value]);
569 }
570
SetBaselineOffset(const JSCallbackInfo & info)571 void JSText::SetBaselineOffset(const JSCallbackInfo& info)
572 {
573 CalcDimension value;
574 JSRef<JSVal> args = info[0];
575 if (!ParseJsDimensionFpNG(args, value, false)) {
576 value.Reset();
577 TextModel::GetInstance()->SetBaselineOffset(value);
578 return;
579 }
580 TextModel::GetInstance()->SetBaselineOffset(value);
581 }
582
SetDecoration(const JSCallbackInfo & info)583 void JSText::SetDecoration(const JSCallbackInfo& info)
584 {
585 auto tmpInfo = info[0];
586 if (tmpInfo->IsUndefined()) {
587 TextModel::GetInstance()->SetTextDecoration(TextDecoration::NONE);
588 info.ReturnSelf();
589 return;
590 }
591 if (!tmpInfo->IsObject()) {
592 info.ReturnSelf();
593 return;
594 }
595 JSRef<JSObject> obj = JSRef<JSObject>::Cast(tmpInfo);
596 JSRef<JSVal> typeValue = obj->GetProperty("type");
597 JSRef<JSVal> colorValue = obj->GetProperty("color");
598 JSRef<JSVal> styleValue = obj->GetProperty("style");
599
600 TextDecoration textDecoration;
601 if (typeValue->IsNumber()) {
602 textDecoration = static_cast<TextDecoration>(typeValue->ToNumber<int32_t>());
603 } else {
604 auto theme = GetTheme<TextTheme>();
605 CHECK_NULL_VOID(theme);
606 textDecoration = theme->GetTextStyle().GetTextDecoration();
607 }
608 Color result;
609 if (!ParseJsColor(colorValue, result)) {
610 auto theme = GetTheme<TextTheme>();
611 CHECK_NULL_VOID(theme);
612 if (SystemProperties::GetColorMode() == ColorMode::DARK) {
613 result = theme->GetTextStyle().GetTextColor();
614 } else {
615 result = theme->GetTextStyle().GetTextDecorationColor();
616 }
617 }
618 std::optional<TextDecorationStyle> textDecorationStyle;
619 if (styleValue->IsNumber()) {
620 textDecorationStyle = static_cast<TextDecorationStyle>(styleValue->ToNumber<int32_t>());
621 } else {
622 textDecorationStyle = DEFAULT_TEXT_DECORATION_STYLE;
623 }
624 TextModel::GetInstance()->SetTextDecoration(textDecoration);
625 TextModel::GetInstance()->SetTextDecorationColor(result);
626 if (textDecorationStyle) {
627 TextModel::GetInstance()->SetTextDecorationStyle(textDecorationStyle.value());
628 }
629 info.ReturnSelf();
630 }
631
SetHeightAdaptivePolicy(int32_t value)632 void JSText::SetHeightAdaptivePolicy(int32_t value)
633 {
634 if (value < 0 || value >= static_cast<int32_t>(HEIGHT_ADAPTIVE_POLICY.size())) {
635 if (!(AceApplicationInfo::GetInstance().GreatOrEqualTargetAPIVersion(PlatformVersion::VERSION_TWELVE))) {
636 return;
637 }
638 value = 0;
639 }
640 TextModel::GetInstance()->SetHeightAdaptivePolicy(HEIGHT_ADAPTIVE_POLICY[value]);
641 }
642
JsOnClick(const JSCallbackInfo & info)643 void JSText::JsOnClick(const JSCallbackInfo& info)
644 {
645 JSRef<JSVal> args = info[0];
646 if (Container::IsCurrentUseNewPipeline()) {
647 if (args->IsUndefined() && IsDisableEventVersion()) {
648 TextModel::GetInstance()->ClearOnClick();
649 return;
650 }
651 if (!args->IsFunction()) {
652 return;
653 }
654 auto frameNode = AceType::WeakClaim(NG::ViewStackProcessor::GetInstance()->GetMainFrameNode());
655 auto jsOnClickFunc = AceType::MakeRefPtr<JsClickFunction>(JSRef<JSFunc>::Cast(args));
656 auto onClick = [execCtx = info.GetExecutionContext(), func = jsOnClickFunc, node = frameNode]
657 (BaseEventInfo* info) {
658 JAVASCRIPT_EXECUTION_SCOPE_WITH_CHECK(execCtx);
659 auto* clickInfo = TypeInfoHelper::DynamicCast<GestureEvent>(info);
660 ACE_SCORING_EVENT("Text.onClick");
661 PipelineContext::SetCallBackNode(node);
662 func->Execute(*clickInfo);
663 #if !defined(PREVIEW) && defined(OHOS_PLATFORM)
664 std::string label = "";
665 if (!node.Invalid()) {
666 auto pattern = node.GetRawPtr()->GetPattern();
667 CHECK_NULL_VOID(pattern);
668 auto layoutProperty = pattern->GetLayoutProperty<NG::TextLayoutProperty>();
669 CHECK_NULL_VOID(layoutProperty);
670 label = layoutProperty->GetContent().value_or("");
671 }
672 JSInteractableView::ReportClickEvent(node, label);
673 #endif
674 };
675 TextModel::GetInstance()->SetOnClick(std::move(onClick));
676
677 auto focusHub = NG::ViewStackProcessor::GetInstance()->GetOrCreateMainFrameNodeFocusHub();
678 CHECK_NULL_VOID(focusHub);
679 focusHub->SetFocusable(true, false);
680 } else {
681 JsOnClickWithoutNGBUILD(info);
682 }
683 }
684
JsOnClickWithoutNGBUILD(const JSCallbackInfo & info)685 void JSText::JsOnClickWithoutNGBUILD(const JSCallbackInfo& info)
686 {
687 #ifndef NG_BUILD
688 JSRef<JSVal> args = info[0];
689 if (args->IsFunction()) {
690 auto inspector = ViewStackProcessor::GetInstance()->GetInspectorComposedComponent();
691 auto impl = inspector ? inspector->GetInspectorFunctionImpl() : nullptr;
692 auto frameNode = AceType::WeakClaim(NG::ViewStackProcessor::GetInstance()->GetMainFrameNode());
693 RefPtr<JsClickFunction> jsOnClickFunc = AceType::MakeRefPtr<JsClickFunction>(JSRef<JSFunc>::Cast(args));
694 auto onClickId = [execCtx = info.GetExecutionContext(), func = std::move(jsOnClickFunc), impl,
695 node = frameNode](const BaseEventInfo* info) {
696 JAVASCRIPT_EXECUTION_SCOPE_WITH_CHECK(execCtx);
697 const auto* clickInfo = TypeInfoHelper::DynamicCast<ClickInfo>(info);
698 auto newInfo = *clickInfo;
699 if (impl) {
700 impl->UpdateEventInfo(newInfo);
701 }
702 ACE_SCORING_EVENT("Text.onClick");
703 PipelineContext::SetCallBackNode(node);
704 func->Execute(newInfo);
705 };
706 TextModel::GetInstance()->SetOnClick(std::move(onClickId));
707 }
708 #endif
709 }
710
JsRemoteMessage(const JSCallbackInfo & info)711 void JSText::JsRemoteMessage(const JSCallbackInfo& info)
712 {
713 JSInteractableView::JsCommonRemoteMessage(info);
714 auto callback = JSInteractableView::GetRemoteMessageEventCallback(info);
715 TextModel::GetInstance()->SetRemoteMessage(std::move(callback));
716 }
717
Create(const JSCallbackInfo & info)718 void JSText::Create(const JSCallbackInfo& info)
719 {
720 std::string data;
721 if (info.Length() <= 0) {
722 TextModel::GetInstance()->Create(data);
723 return;
724 }
725
726 if (info[0]->IsObject() && JSRef<JSObject>::Cast(info[0])->Unwrap<JSSpanString>()) {
727 auto *spanString = JSRef<JSObject>::Cast(info[0])->Unwrap<JSSpanString>();
728 if (spanString == nullptr) {
729 return;
730 }
731 auto spanStringController = spanString->GetController();
732 if (spanStringController) {
733 TextModel::GetInstance()->Create(spanStringController);
734 } else {
735 TextModel::GetInstance()->Create(data);
736 }
737 } else {
738 ParseJsString(info[0], data);
739 TextModel::GetInstance()->Create(data);
740 }
741
742 JSTextTheme::ApplyTheme();
743 if (info.Length() <= 1 || !info[1]->IsObject()) {
744 return;
745 }
746
747 JSTextController* jsController = nullptr;
748 auto paramObject = JSRef<JSObject>::Cast(info[1]);
749 auto controllerObj = paramObject->GetProperty("controller");
750 if (!controllerObj->IsUndefined() && !controllerObj->IsNull() && controllerObj->IsObject()) {
751 jsController = JSRef<JSObject>::Cast(controllerObj)->Unwrap<JSTextController>();
752 }
753
754 RefPtr<TextControllerBase> controller = TextModel::GetInstance()->GetTextController();
755 if (jsController) {
756 jsController->SetController(controller);
757 }
758 }
759
SetCopyOption(const JSCallbackInfo & info)760 void JSText::SetCopyOption(const JSCallbackInfo& info)
761 {
762 if (info.Length() == 0) {
763 return;
764 }
765 auto copyOptions = CopyOptions::None;
766 auto tmpInfo = info[0];
767 if (tmpInfo->IsNumber()) {
768 auto emunNumber = tmpInfo->ToNumber<int>();
769 copyOptions = static_cast<CopyOptions>(emunNumber);
770 }
771 TextModel::GetInstance()->SetCopyOption(copyOptions);
772 }
773
SetOnCopy(const JSCallbackInfo & info)774 void JSText::SetOnCopy(const JSCallbackInfo& info)
775 {
776 JSRef<JSVal> args = info[0];
777 CHECK_NULL_VOID(args->IsFunction());
778 JsEventCallback<void(const std::string&)> callback(info.GetExecutionContext(), JSRef<JSFunc>::Cast(args));
779 TextModel::GetInstance()->SetOnCopy(std::move(callback));
780 }
781
JsOnDragStart(const JSCallbackInfo & info)782 void JSText::JsOnDragStart(const JSCallbackInfo& info)
783 {
784 JSRef<JSVal> args = info[0];
785 CHECK_NULL_VOID(args->IsFunction());
786 RefPtr<JsDragFunction> jsOnDragStartFunc = AceType::MakeRefPtr<JsDragFunction>(JSRef<JSFunc>::Cast(args));
787 auto frameNode = AceType::WeakClaim(NG::ViewStackProcessor::GetInstance()->GetMainFrameNode());
788 auto onDragStart = [execCtx = info.GetExecutionContext(), func = std::move(jsOnDragStartFunc),
789 targetNode = frameNode](
790 const RefPtr<DragEvent>& info, const std::string& extraParams) -> NG::DragDropBaseInfo {
791 NG::DragDropBaseInfo itemInfo;
792 JAVASCRIPT_EXECUTION_SCOPE_WITH_CHECK(execCtx, itemInfo);
793 PipelineContext::SetCallBackNode(targetNode);
794 auto ret = func->Execute(info, extraParams);
795 if (!ret->IsObject()) {
796 return itemInfo;
797 }
798 auto node = ParseDragNode(ret);
799 if (node) {
800 itemInfo.node = node;
801 return itemInfo;
802 }
803 auto builderObj = JSRef<JSObject>::Cast(ret);
804 #if defined(PIXEL_MAP_SUPPORTED)
805 auto pixmap = builderObj->GetProperty("pixelMap");
806 itemInfo.pixelMap = CreatePixelMapFromNapiValue(pixmap);
807 #endif
808 auto extraInfo = builderObj->GetProperty("extraInfo");
809 ParseJsString(extraInfo, itemInfo.extraInfo);
810 node = ParseDragNode(builderObj->GetProperty("builder"));
811 itemInfo.node = node;
812 return itemInfo;
813 };
814
815 TextModel::GetInstance()->SetOnDragStart(std::move(onDragStart));
816 }
817
JsOnDragEnter(const JSCallbackInfo & info)818 void JSText::JsOnDragEnter(const JSCallbackInfo& info)
819 {
820 JSRef<JSVal> args = info[0];
821 CHECK_NULL_VOID(args->IsFunction());
822 auto frameNode = AceType::WeakClaim(NG::ViewStackProcessor::GetInstance()->GetMainFrameNode());
823 RefPtr<JsDragFunction> jsOnDragEnterFunc = AceType::MakeRefPtr<JsDragFunction>(JSRef<JSFunc>::Cast(args));
824 auto onDragEnterId = [execCtx = info.GetExecutionContext(), func = std::move(jsOnDragEnterFunc), node = frameNode](
825 const RefPtr<DragEvent>& info, const std::string& extraParams) {
826 JAVASCRIPT_EXECUTION_SCOPE_WITH_CHECK(execCtx);
827 ACE_SCORING_EVENT("onDragEnter");
828 PipelineContext::SetCallBackNode(node);
829 func->Execute(info, extraParams);
830 };
831 TextModel::GetInstance()->SetOnDragEnter(std::move(onDragEnterId));
832 }
833
JsOnDragMove(const JSCallbackInfo & info)834 void JSText::JsOnDragMove(const JSCallbackInfo& info)
835 {
836 JSRef<JSVal> args = info[0];
837 CHECK_NULL_VOID(args->IsFunction());
838 auto frameNode = AceType::WeakClaim(NG::ViewStackProcessor::GetInstance()->GetMainFrameNode());
839 RefPtr<JsDragFunction> jsOnDragMoveFunc = AceType::MakeRefPtr<JsDragFunction>(JSRef<JSFunc>::Cast(args));
840 auto onDragMoveId = [execCtx = info.GetExecutionContext(), func = std::move(jsOnDragMoveFunc), node = frameNode](
841 const RefPtr<DragEvent>& info, const std::string& extraParams) {
842 JAVASCRIPT_EXECUTION_SCOPE_WITH_CHECK(execCtx);
843 ACE_SCORING_EVENT("onDragMove");
844 PipelineContext::SetCallBackNode(node);
845 func->Execute(info, extraParams);
846 };
847 TextModel::GetInstance()->SetOnDragMove(std::move(onDragMoveId));
848 }
849
JsOnDragLeave(const JSCallbackInfo & info)850 void JSText::JsOnDragLeave(const JSCallbackInfo& info)
851 {
852 JSRef<JSVal> args = info[0];
853 CHECK_NULL_VOID(args->IsFunction());
854 auto frameNode = AceType::WeakClaim(NG::ViewStackProcessor::GetInstance()->GetMainFrameNode());
855 RefPtr<JsDragFunction> jsOnDragLeaveFunc = AceType::MakeRefPtr<JsDragFunction>(JSRef<JSFunc>::Cast(args));
856 auto onDragLeaveId = [execCtx = info.GetExecutionContext(), func = std::move(jsOnDragLeaveFunc), node = frameNode](
857 const RefPtr<DragEvent>& info, const std::string& extraParams) {
858 JAVASCRIPT_EXECUTION_SCOPE_WITH_CHECK(execCtx);
859 ACE_SCORING_EVENT("onDragLeave");
860 PipelineContext::SetCallBackNode(node);
861 func->Execute(info, extraParams);
862 };
863 TextModel::GetInstance()->SetOnDragLeave(std::move(onDragLeaveId));
864 }
865
JsOnDrop(const JSCallbackInfo & info)866 void JSText::JsOnDrop(const JSCallbackInfo& info)
867 {
868 JSRef<JSVal> args = info[0];
869 CHECK_NULL_VOID(args->IsFunction());
870 RefPtr<JsDragFunction> jsOnDropFunc = AceType::MakeRefPtr<JsDragFunction>(JSRef<JSFunc>::Cast(args));
871 auto onDropId = [execCtx = info.GetExecutionContext(), func = std::move(jsOnDropFunc)](
872 const RefPtr<DragEvent>& info, const std::string& extraParams) {
873 JAVASCRIPT_EXECUTION_SCOPE_WITH_CHECK(execCtx);
874 ACE_SCORING_EVENT("onDrop");
875 func->Execute(info, extraParams);
876 };
877 TextModel::GetInstance()->SetOnDrop(std::move(onDropId));
878 }
879
JsFocusable(const JSCallbackInfo & info)880 void JSText::JsFocusable(const JSCallbackInfo& info)
881 {
882 auto tmpInfo = info[0];
883 if (!tmpInfo->IsBoolean()) {
884 return;
885 }
886 JSInteractableView::SetFocusable(tmpInfo->ToBoolean());
887 JSInteractableView::SetFocusNode(false);
888 }
889
JsDraggable(const JSCallbackInfo & info)890 void JSText::JsDraggable(const JSCallbackInfo& info)
891 {
892 auto tmpInfo = info[0];
893 if (!tmpInfo->IsBoolean()) {
894 return;
895 }
896 ViewAbstractModel::GetInstance()->SetDraggable(tmpInfo->ToBoolean());
897 }
898
JsEnableDataDetector(const JSCallbackInfo & info)899 void JSText::JsEnableDataDetector(const JSCallbackInfo& info)
900 {
901 if (info.Length() < 1) {
902 LOGI("The argv is wrong, it is supposed to have at least 1 argument");
903 return;
904 }
905 auto tmpInfo = info[0];
906 if (!tmpInfo->IsBoolean()) {
907 TextModel::GetInstance()->SetTextDetectEnable(false);
908 return;
909 }
910 auto enable = tmpInfo->ToBoolean();
911 TextModel::GetInstance()->SetTextDetectEnable(enable);
912 }
913
JsDataDetectorConfig(const JSCallbackInfo & info)914 void JSText::JsDataDetectorConfig(const JSCallbackInfo& info)
915 {
916 if (info.Length() < 1) {
917 LOGI("The argv is wrong, it is supposed to have at least 1 argument");
918 return;
919 }
920 JSRef<JSVal> args = info[0];
921 if (!args->IsObject()) {
922 return;
923 }
924
925 TextDetectConfig textDetectConfig;
926 if (!ParseDataDetectorConfig(info, textDetectConfig)) {
927 return;
928 }
929 TextModel::GetInstance()->SetTextDetectConfig(textDetectConfig);
930 }
931
BindSelectionMenu(const JSCallbackInfo & info)932 void JSText::BindSelectionMenu(const JSCallbackInfo& info)
933 {
934 // TextSpanType
935 NG::TextSpanType testSpanType = NG::TextSpanType::TEXT;
936 JSRef<JSVal> argsSpanType = info[0];
937 if (argsSpanType->IsNumber()) {
938 auto spanType = argsSpanType->ToNumber<int32_t>();
939 testSpanType = static_cast<NG::TextSpanType>(spanType);
940 }
941
942 // Builder
943 JSRef<JSVal> argsMenuObj = info[1];
944 if (!argsMenuObj->IsObject()) {
945 return;
946 }
947 JSRef<JSObject> menuObj = JSRef<JSObject>::Cast(argsMenuObj);
948 auto builder = menuObj->GetProperty("builder");
949 if (!builder->IsFunction()) {
950 return;
951 }
952 auto builderFunc = AceType::MakeRefPtr<JsFunction>(JSRef<JSFunc>::Cast(builder));
953 CHECK_NULL_VOID(builderFunc);
954
955 // TextResponseType
956 int32_t resquiredParameterCount = 3;
957 JSRef<JSVal> argsResponse = info[resquiredParameterCount - 1];
958 NG::TextResponseType responseType = NG::TextResponseType::LONG_PRESS;
959 if (argsResponse->IsNumber()) {
960 auto response = argsResponse->ToNumber<int32_t>();
961 responseType = static_cast<NG::TextResponseType>(response);
962 }
963
964 WeakPtr<NG::FrameNode> frameNode = AceType::WeakClaim(NG::ViewStackProcessor::GetInstance()->GetMainFrameNode());
965 std::function<void()> buildFunc = [execCtx = info.GetExecutionContext(), func = std::move(builderFunc),
966 node = frameNode]() {
967 JAVASCRIPT_EXECUTION_SCOPE_WITH_CHECK(execCtx);
968 ACE_SCORING_EVENT("BindSelectionMenu");
969 PipelineContext::SetCallBackNode(node);
970 func->Execute();
971 };
972
973 // SelectionMenuOptions
974 NG::SelectMenuParam menuParam;
975 if (info.Length() > resquiredParameterCount) {
976 JSRef<JSVal> argsMenuOptions = info[resquiredParameterCount];
977 if (argsMenuOptions->IsObject()) {
978 ParseMenuParam(info, argsMenuOptions, menuParam);
979 }
980 }
981
982 TextModel::GetInstance()->BindSelectionMenu(testSpanType, responseType, buildFunc, menuParam);
983 }
984
SetOnTextSelectionChange(const JSCallbackInfo & info)985 void JSText::SetOnTextSelectionChange(const JSCallbackInfo& info)
986 {
987 JSRef<JSVal> args = info[0];
988 CHECK_NULL_VOID(args->IsFunction());
989 JsEventCallback<void(int32_t, int32_t)> callback(info.GetExecutionContext(), JSRef<JSFunc>::Cast(args));
990 TextModel::GetInstance()->SetOnTextSelectionChange(std::move(callback));
991 }
992
JsClip(const JSCallbackInfo & info)993 void JSText::JsClip(const JSCallbackInfo& info)
994 {
995 JSViewAbstract::JsClip(info);
996 JSRef<JSVal> args = info[0];
997 if (args->IsBoolean()) {
998 TextModel::GetInstance()->SetClipEdge(args->ToBoolean());
999 }
1000 }
1001
SetFontFeature(const JSCallbackInfo & info)1002 void JSText::SetFontFeature(const JSCallbackInfo& info)
1003 {
1004 if (info.Length() < 1) {
1005 return;
1006 }
1007
1008 if (!info[0]->IsString() && !info[0]->IsObject()) {
1009 return;
1010 }
1011 std::string fontFeatureSettings = info[0]->ToString();
1012 TextModel::GetInstance()->SetFontFeature(ParseFontFeatureSettings(fontFeatureSettings));
1013 }
1014
JsResponseRegion(const JSCallbackInfo & info)1015 void JSText::JsResponseRegion(const JSCallbackInfo& info)
1016 {
1017 JSViewAbstract::JsResponseRegion(info);
1018 TextModel::GetInstance()->SetResponseRegion(true);
1019 }
1020
SetHalfLeading(const JSCallbackInfo & info)1021 void JSText::SetHalfLeading(const JSCallbackInfo& info)
1022 {
1023 if (info.Length() < 1) {
1024 return;
1025 }
1026 auto halfLeading = info[0];
1027 if (!halfLeading->IsBoolean()) {
1028 TextModel::GetInstance()->SetHalfLeading(false);
1029 return;
1030 }
1031 auto enable = halfLeading->ToBoolean();
1032 TextModel::GetInstance()->SetHalfLeading(enable);
1033 }
1034
SetEnableHapticFeedback(const JSCallbackInfo & info)1035 void JSText::SetEnableHapticFeedback(const JSCallbackInfo& info)
1036 {
1037 bool state = true;
1038 if (info.Length() > 0 && info[0]->IsBoolean()) {
1039 state = info[0]->ToBoolean();
1040 }
1041 TextModel::GetInstance()->SetEnableHapticFeedback(state);
1042 }
1043
JSBind(BindingTarget globalObj)1044 void JSText::JSBind(BindingTarget globalObj)
1045 {
1046 JSClass<JSText>::Declare("Text");
1047 MethodOptions opt = MethodOptions::NONE;
1048 JSClass<JSText>::StaticMethod("create", &JSText::Create, opt);
1049 JSClass<JSText>::StaticMethod("width", &JSText::SetWidth);
1050 JSClass<JSText>::StaticMethod("height", &JSText::SetHeight);
1051 JSClass<JSText>::StaticMethod("font", &JSText::SetFont, opt);
1052 JSClass<JSText>::StaticMethod("fontColor", &JSText::SetTextColor, opt);
1053 JSClass<JSText>::StaticMethod("textShadow", &JSText::SetTextShadow, opt);
1054 JSClass<JSText>::StaticMethod("fontSize", &JSText::SetFontSize, opt);
1055 JSClass<JSText>::StaticMethod("fontWeight", &JSText::SetFontWeight, opt);
1056 JSClass<JSText>::StaticMethod("minFontScale", &JSText::SetMinFontScale, opt);
1057 JSClass<JSText>::StaticMethod("maxFontScale", &JSText::SetMaxFontScale, opt);
1058 JSClass<JSText>::StaticMethod("wordBreak", &JSText::SetWordBreak, opt);
1059 JSClass<JSText>::StaticMethod("lineBreakStrategy", &JSText::SetLineBreakStrategy, opt);
1060 JSClass<JSText>::StaticMethod("selection", &JSText::SetTextSelection, opt);
1061 JSClass<JSText>::StaticMethod("ellipsisMode", &JSText::SetEllipsisMode, opt);
1062 JSClass<JSText>::StaticMethod("textSelectable", &JSText::SetTextSelectableMode, opt);
1063 JSClass<JSText>::StaticMethod("maxLines", &JSText::SetMaxLines, opt);
1064 JSClass<JSText>::StaticMethod("textIndent", &JSText::SetTextIndent);
1065 JSClass<JSText>::StaticMethod("textOverflow", &JSText::SetTextOverflow, opt);
1066 JSClass<JSText>::StaticMethod("fontStyle", &JSText::SetFontStyle, opt);
1067 JSClass<JSText>::StaticMethod("align", &JSText::SetAlign, opt);
1068 JSClass<JSText>::StaticMethod("textAlign", &JSText::SetTextAlign, opt);
1069 JSClass<JSText>::StaticMethod("lineHeight", &JSText::SetLineHeight, opt);
1070 JSClass<JSText>::StaticMethod("lineSpacing", &JSText::SetLineSpacing, opt);
1071 JSClass<JSText>::StaticMethod("fontFamily", &JSText::SetFontFamily, opt);
1072 JSClass<JSText>::StaticMethod("minFontSize", &JSText::SetMinFontSize, opt);
1073 JSClass<JSText>::StaticMethod("maxFontSize", &JSText::SetMaxFontSize, opt);
1074 JSClass<JSText>::StaticMethod("letterSpacing", &JSText::SetLetterSpacing, opt);
1075 JSClass<JSText>::StaticMethod("textCase", &JSText::SetTextCase, opt);
1076 JSClass<JSText>::StaticMethod("baselineOffset", &JSText::SetBaselineOffset, opt);
1077 JSClass<JSText>::StaticMethod("decoration", &JSText::SetDecoration);
1078 JSClass<JSText>::StaticMethod("heightAdaptivePolicy", &JSText::SetHeightAdaptivePolicy);
1079 JSClass<JSText>::StaticMethod("onTouch", &JSInteractableView::JsOnTouch);
1080 JSClass<JSText>::StaticMethod("onHover", &JSInteractableView::JsOnHover);
1081 JSClass<JSText>::StaticMethod("onKeyEvent", &JSInteractableView::JsOnKey);
1082 JSClass<JSText>::StaticMethod("onDeleteEvent", &JSInteractableView::JsOnDelete);
1083 JSClass<JSText>::StaticMethod("remoteMessage", &JSText::JsRemoteMessage);
1084 JSClass<JSText>::StaticMethod("copyOption", &JSText::SetCopyOption);
1085 JSClass<JSText>::StaticMethod("onClick", &JSText::JsOnClick);
1086 JSClass<JSText>::StaticMethod("onCopy", &JSText::SetOnCopy);
1087 JSClass<JSText>::StaticMethod("onAttach", &JSInteractableView::JsOnAttach);
1088 JSClass<JSText>::StaticMethod("onAppear", &JSInteractableView::JsOnAppear);
1089 JSClass<JSText>::StaticMethod("onDetach", &JSInteractableView::JsOnDetach);
1090 JSClass<JSText>::StaticMethod("onDisAppear", &JSInteractableView::JsOnDisAppear);
1091 JSClass<JSText>::StaticMethod("onDragStart", &JSText::JsOnDragStart);
1092 JSClass<JSText>::StaticMethod("onDragEnter", &JSText::JsOnDragEnter);
1093 JSClass<JSText>::StaticMethod("onDragMove", &JSText::JsOnDragMove);
1094 JSClass<JSText>::StaticMethod("onDragLeave", &JSText::JsOnDragLeave);
1095 JSClass<JSText>::StaticMethod("onDrop", &JSText::JsOnDrop);
1096 JSClass<JSText>::StaticMethod("focusable", &JSText::JsFocusable);
1097 JSClass<JSText>::StaticMethod("draggable", &JSText::JsDraggable);
1098 JSClass<JSText>::StaticMethod("enableDataDetector", &JSText::JsEnableDataDetector);
1099 JSClass<JSText>::StaticMethod("dataDetectorConfig", &JSText::JsDataDetectorConfig);
1100 JSClass<JSText>::StaticMethod("bindSelectionMenu", &JSText::BindSelectionMenu);
1101 JSClass<JSText>::StaticMethod("onTextSelectionChange", &JSText::SetOnTextSelectionChange);
1102 JSClass<JSText>::StaticMethod("clip", &JSText::JsClip);
1103 JSClass<JSText>::StaticMethod("foregroundColor", &JSText::SetForegroundColor);
1104 JSClass<JSText>::StaticMethod("fontFeature", &JSText::SetFontFeature);
1105 JSClass<JSText>::StaticMethod("editMenuOptions", &JSText::EditMenuOptions);
1106 JSClass<JSText>::StaticMethod("responseRegion", &JSText::JsResponseRegion);
1107 JSClass<JSText>::StaticMethod("halfLeading", &JSText::SetHalfLeading);
1108 JSClass<JSText>::StaticMethod("enableHapticFeedback", &JSText::SetEnableHapticFeedback);
1109 JSClass<JSText>::InheritAndBind<JSContainerBase>(globalObj);
1110 }
1111
CloseSelectionMenu()1112 void JSTextController::CloseSelectionMenu()
1113 {
1114 auto controller = controllerWeak_.Upgrade();
1115 CHECK_NULL_VOID(controller);
1116 controller->CloseSelectionMenu();
1117 }
1118
GetLayoutManager(const JSCallbackInfo & args)1119 void JSTextController::GetLayoutManager(const JSCallbackInfo& args)
1120 {
1121 JSRef<JSObject> obj = JSClass<JSLayoutManager>::NewInstance();
1122 auto jsLayoutManager = Referenced::Claim(obj->Unwrap<JSLayoutManager>());
1123 CHECK_NULL_VOID(jsLayoutManager);
1124 jsLayoutManager->IncRefCount();
1125 auto controller = controllerWeak_.Upgrade();
1126 CHECK_NULL_VOID(controller);
1127 auto layoutInfoInterface = controller->GetLayoutInfoInterface();
1128 jsLayoutManager->SetLayoutInfoInterface(layoutInfoInterface);
1129 args.SetReturnValue(obj);
1130 }
1131
SetStyledString(const JSCallbackInfo & info)1132 void JSTextController::SetStyledString(const JSCallbackInfo& info)
1133 {
1134 if (info.Length() != 1 || !info[0]->IsObject()) {
1135 JSException::Throw(ERROR_CODE_PARAM_INVALID, "%s", "Input parameter check failed.");
1136 return;
1137 }
1138 auto* spanString = JSRef<JSObject>::Cast(info[0])->Unwrap<JSSpanString>();
1139 if (!spanString) {
1140 JSException::Throw(ERROR_CODE_PARAM_INVALID, "%s", "Input parameter check failed.");
1141 return;
1142 }
1143 auto controller = controllerWeak_.Upgrade();
1144 CHECK_NULL_VOID(controller);
1145 auto spanStringController = spanString->GetController();
1146 CHECK_NULL_VOID(spanStringController);
1147 controller->SetStyledString(spanStringController);
1148 auto thisObj = info.This();
1149 thisObj->SetPropertyObject("STYLED_STRING_IN_CONTROLLER", info[0]);
1150 }
1151
JSBind(BindingTarget globalObj)1152 void JSTextController::JSBind(BindingTarget globalObj)
1153 {
1154 JSClass<JSTextController>::Declare("TextController");
1155 JSClass<JSTextController>::Method("closeSelectionMenu", &JSTextController::CloseSelectionMenu);
1156 JSClass<JSTextController>::CustomMethod("setStyledString", &JSTextController::SetStyledString);
1157 JSClass<JSTextController>::CustomMethod("getLayoutManager", &JSTextController::GetLayoutManager);
1158 JSClass<JSTextController>::Bind(globalObj, JSTextController::Constructor, JSTextController::Destructor);
1159 }
1160
ParseMenuParam(const JSCallbackInfo & info,const JSRef<JSObject> & menuOptions,NG::SelectMenuParam & menuParam)1161 void JSText::ParseMenuParam(
1162 const JSCallbackInfo& info, const JSRef<JSObject>& menuOptions, NG::SelectMenuParam& menuParam)
1163 {
1164 WeakPtr<NG::FrameNode> frameNode = AceType::WeakClaim(NG::ViewStackProcessor::GetInstance()->GetMainFrameNode());
1165 auto onAppearValue = menuOptions->GetProperty("onAppear");
1166 if (onAppearValue->IsFunction()) {
1167 RefPtr<JsFunction> jsOnAppearFunc =
1168 AceType::MakeRefPtr<JsFunction>(JSRef<JSObject>(), JSRef<JSFunc>::Cast(onAppearValue));
1169 auto onAppear = [execCtx = info.GetExecutionContext(), func = std::move(jsOnAppearFunc), node = frameNode](
1170 int32_t start, int32_t end) {
1171 JAVASCRIPT_EXECUTION_SCOPE_WITH_CHECK(execCtx);
1172 ACE_SCORING_EVENT("onAppear");
1173
1174 JSRef<JSVal> params[2];
1175 params[0] = JSRef<JSVal>::Make(ToJSValue(start));
1176 params[1] = JSRef<JSVal>::Make(ToJSValue(end));
1177 PipelineContext::SetCallBackNode(node);
1178 func->ExecuteJS(2, params);
1179 };
1180 menuParam.onAppear = std::move(onAppear);
1181 }
1182
1183 auto onDisappearValue = menuOptions->GetProperty("onDisappear");
1184 if (onDisappearValue->IsFunction()) {
1185 RefPtr<JsFunction> jsOnDisAppearFunc =
1186 AceType::MakeRefPtr<JsFunction>(JSRef<JSObject>(), JSRef<JSFunc>::Cast(onDisappearValue));
1187 auto onDisappear = [execCtx = info.GetExecutionContext(), func = std::move(jsOnDisAppearFunc),
1188 node = frameNode]() {
1189 JAVASCRIPT_EXECUTION_SCOPE_WITH_CHECK(execCtx);
1190 ACE_SCORING_EVENT("onDisappear");
1191 PipelineContext::SetCallBackNode(node);
1192 func->Execute();
1193 };
1194 menuParam.onDisappear = std::move(onDisappear);
1195 }
1196 }
1197
EditMenuOptions(const JSCallbackInfo & info)1198 void JSText::EditMenuOptions(const JSCallbackInfo& info)
1199 {
1200 NG::OnCreateMenuCallback onCreateMenuCallback;
1201 NG::OnMenuItemClickCallback onMenuItemClick;
1202 JSViewAbstract::ParseEditMenuOptions(info, onCreateMenuCallback, onMenuItemClick);
1203 TextModel::GetInstance()->SetSelectionMenuOptions(std::move(onCreateMenuCallback), std::move(onMenuItemClick));
1204 }
1205 } // namespace OHOS::Ace::Framework
1206