• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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