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