1// Copyright 2014 The Flutter Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5import 'dart:ui' as ui show TextHeightBehavior;
6
7import 'package:flutter/rendering.dart';
8
9import 'basic.dart';
10import 'default_selection_style.dart';
11import 'framework.dart';
12import 'inherited_theme.dart';
13import 'media_query.dart';
14import 'selection_container.dart';
15
16// Examples can assume:
17// late String _name;
18// late BuildContext context;
19
20/// The text style to apply to descendant [Text] widgets which don't have an
21/// explicit style.
22///
23/// {@tool dartpad}
24/// This example shows how to use [DefaultTextStyle.merge] to create a default
25/// text style that inherits styling information from the current default text
26/// style and overrides some properties.
27///
28/// ** See code in examples/api/lib/widgets/text/text.0.dart **
29/// {@end-tool}
30///
31/// See also:
32///
33/// * [AnimatedDefaultTextStyle], which animates changes in the text style
34/// smoothly over a given duration.
35/// * [DefaultTextStyleTransition], which takes a provided [Animation] to
36/// animate changes in text style smoothly over time.
37class DefaultTextStyle extends InheritedTheme {
38 /// Creates a default text style for the given subtree.
39 ///
40 /// Consider using [DefaultTextStyle.merge] to inherit styling information
41 /// from the current default text style for a given [BuildContext].
42 ///
43 /// The [maxLines] property may be null (and indeed defaults to null), but if
44 /// it is not null, it must be greater than zero.
45 const DefaultTextStyle({
46 super.key,
47 required this.style,
48 this.textAlign,
49 this.softWrap = true,
50 this.overflow = TextOverflow.clip,
51 this.maxLines,
52 this.textWidthBasis = TextWidthBasis.parent,
53 this.textHeightBehavior,
54 required super.child,
55 }) : assert(maxLines == null || maxLines > 0);
56
57 /// A const-constructable default text style that provides fallback values.
58 ///
59 /// Returned from [of] when the given [BuildContext] doesn't have an enclosing default text style.
60 ///
61 /// This constructor creates a [DefaultTextStyle] with an invalid [child], which
62 /// means the constructed value cannot be incorporated into the tree.
63 const DefaultTextStyle.fallback({ super.key })
64 : style = const TextStyle(),
65 textAlign = null,
66 softWrap = true,
67 maxLines = null,
68 overflow = TextOverflow.clip,
69 textWidthBasis = TextWidthBasis.parent,
70 textHeightBehavior = null,
71 super(child: const _NullWidget());
72
73 /// Creates a default text style that overrides the text styles in scope at
74 /// this point in the widget tree.
75 ///
76 /// The given [style] is merged with the [style] from the default text style
77 /// for the [BuildContext] where the widget is inserted, and any of the other
78 /// arguments that are not null replace the corresponding properties on that
79 /// same default text style.
80 ///
81 /// This constructor cannot be used to override the [maxLines] property of the
82 /// ancestor with the value null, since null here is used to mean "defer to
83 /// ancestor". To replace a non-null [maxLines] from an ancestor with the null
84 /// value (to remove the restriction on number of lines), manually obtain the
85 /// ambient [DefaultTextStyle] using [DefaultTextStyle.of], then create a new
86 /// [DefaultTextStyle] using the [DefaultTextStyle.new] constructor directly.
87 /// See the source below for an example of how to do this (since that's
88 /// essentially what this constructor does).
89 static Widget merge({
90 Key? key,
91 TextStyle? style,
92 TextAlign? textAlign,
93 bool? softWrap,
94 TextOverflow? overflow,
95 int? maxLines,
96 TextWidthBasis? textWidthBasis,
97 required Widget child,
98 }) {
99 return Builder(
100 builder: (BuildContext context) {
101 final DefaultTextStyle parent = DefaultTextStyle.of(context);
102 return DefaultTextStyle(
103 key: key,
104 style: parent.style.merge(style),
105 textAlign: textAlign ?? parent.textAlign,
106 softWrap: softWrap ?? parent.softWrap,
107 overflow: overflow ?? parent.overflow,
108 maxLines: maxLines ?? parent.maxLines,
109 textWidthBasis: textWidthBasis ?? parent.textWidthBasis,
110 child: child,
111 );
112 },
113 );
114 }
115
116 /// The text style to apply.
117 final TextStyle style;
118
119 /// How each line of text in the Text widget should be aligned horizontally.
120 final TextAlign? textAlign;
121
122 /// Whether the text should break at soft line breaks.
123 ///
124 /// If false, the glyphs in the text will be positioned as if there was unlimited horizontal space.
125 ///
126 /// This also decides the [overflow] property's behavior. If this is true or null,
127 /// the glyph causing overflow, and those that follow, will not be rendered.
128 final bool softWrap;
129
130 /// How visual overflow should be handled.
131 ///
132 /// If [softWrap] is true or null, the glyph causing overflow, and those that follow,
133 /// will not be rendered. Otherwise, it will be shown with the given overflow option.
134 final TextOverflow overflow;
135
136 /// An optional maximum number of lines for the text to span, wrapping if necessary.
137 /// If the text exceeds the given number of lines, it will be truncated according
138 /// to [overflow].
139 ///
140 /// If this is 1, text will not wrap. Otherwise, text will be wrapped at the
141 /// edge of the box.
142 ///
143 /// If this is non-null, it will override even explicit null values of
144 /// [Text.maxLines].
145 final int? maxLines;
146
147 /// The strategy to use when calculating the width of the Text.
148 ///
149 /// See [TextWidthBasis] for possible values and their implications.
150 final TextWidthBasis textWidthBasis;
151
152 /// {@macro dart.ui.textHeightBehavior}
153 final ui.TextHeightBehavior? textHeightBehavior;
154
155 /// The closest instance of this class that encloses the given context.
156 ///
157 /// If no such instance exists, returns an instance created by
158 /// [DefaultTextStyle.fallback], which contains fallback values.
159 ///
160 /// Typical usage is as follows:
161 ///
162 /// ```dart
163 /// DefaultTextStyle style = DefaultTextStyle.of(context);
164 /// ```
165 static DefaultTextStyle of(BuildContext context) {
166 return context.dependOnInheritedWidgetOfExactType<DefaultTextStyle>() ?? const DefaultTextStyle.fallback();
167 }
168
169 @override
170 bool updateShouldNotify(DefaultTextStyle oldWidget) {
171 return style != oldWidget.style ||
172 textAlign != oldWidget.textAlign ||
173 softWrap != oldWidget.softWrap ||
174 overflow != oldWidget.overflow ||
175 maxLines != oldWidget.maxLines ||
176 textWidthBasis != oldWidget.textWidthBasis ||
177 textHeightBehavior != oldWidget.textHeightBehavior;
178 }
179
180 @override
181 Widget wrap(BuildContext context, Widget child) {
182 return DefaultTextStyle(
183 style: style,
184 textAlign: textAlign,
185 softWrap: softWrap,
186 overflow: overflow,
187 maxLines: maxLines,
188 textWidthBasis: textWidthBasis,
189 textHeightBehavior: textHeightBehavior,
190 child: child,
191 );
192 }
193
194 @override
195 void debugFillProperties(DiagnosticPropertiesBuilder properties) {
196 super.debugFillProperties(properties);
197 style.debugFillProperties(properties);
198 properties.add(EnumProperty<TextAlign>('textAlign', textAlign, defaultValue: null));
199 properties.add(FlagProperty('softWrap', value: softWrap, ifTrue: 'wrapping at box width', ifFalse: 'no wrapping except at line break characters', showName: true));
200 properties.add(EnumProperty<TextOverflow>('overflow', overflow, defaultValue: null));
201 properties.add(IntProperty('maxLines', maxLines, defaultValue: null));
202 properties.add(EnumProperty<TextWidthBasis>('textWidthBasis', textWidthBasis, defaultValue: TextWidthBasis.parent));
203 properties.add(DiagnosticsProperty<ui.TextHeightBehavior>('textHeightBehavior', textHeightBehavior, defaultValue: null));
204 }
205}
206
207class _NullWidget extends StatelessWidget {
208 const _NullWidget();
209
210 @override
211 Widget build(BuildContext context) {
212 throw FlutterError(
213 'A DefaultTextStyle constructed with DefaultTextStyle.fallback cannot be incorporated into the widget tree, '
214 'it is meant only to provide a fallback value returned by DefaultTextStyle.of() '
215 'when no enclosing default text style is present in a BuildContext.',
216 );
217 }
218}
219
220/// The [TextHeightBehavior] that will apply to descendant [Text] and [EditableText]
221/// widgets which have not explicitly set [Text.textHeightBehavior].
222///
223/// If there is a [DefaultTextStyle] with a non-null [DefaultTextStyle.textHeightBehavior]
224/// below this widget, the [DefaultTextStyle.textHeightBehavior] will be used
225/// over this widget's [TextHeightBehavior].
226///
227/// See also:
228///
229/// * [DefaultTextStyle], which defines a [TextStyle] to apply to descendant
230/// [Text] widgets.
231class DefaultTextHeightBehavior extends InheritedTheme {
232 /// Creates a default text height behavior for the given subtree.
233 const DefaultTextHeightBehavior({
234 super.key,
235 required this.textHeightBehavior,
236 required super.child,
237 });
238
239 /// {@macro dart.ui.textHeightBehavior}
240 final TextHeightBehavior textHeightBehavior;
241
242 /// The closest instance of [DefaultTextHeightBehavior] that encloses the
243 /// given context, or null if none is found.
244 ///
245 /// If no such instance exists, this method will return `null`.
246 ///
247 /// Calling this method will create a dependency on the closest
248 /// [DefaultTextHeightBehavior] in the [context], if there is one.
249 ///
250 /// Typical usage is as follows:
251 ///
252 /// ```dart
253 /// TextHeightBehavior? defaultTextHeightBehavior = DefaultTextHeightBehavior.of(context);
254 /// ```
255 ///
256 /// See also:
257 ///
258 /// * [DefaultTextHeightBehavior.maybeOf], which is similar to this method,
259 /// but asserts if no [DefaultTextHeightBehavior] ancestor is found.
260 static TextHeightBehavior? maybeOf(BuildContext context) {
261 return context.dependOnInheritedWidgetOfExactType<DefaultTextHeightBehavior>()?.textHeightBehavior;
262 }
263
264 /// The closest instance of [DefaultTextHeightBehavior] that encloses the
265 /// given context.
266 ///
267 /// If no such instance exists, this method will assert in debug mode, and
268 /// throw an exception in release mode.
269 ///
270 /// Typical usage is as follows:
271 ///
272 /// ```dart
273 /// TextHeightBehavior defaultTextHeightBehavior = DefaultTextHeightBehavior.of(context);
274 /// ```
275 ///
276 /// Calling this method will create a dependency on the closest
277 /// [DefaultTextHeightBehavior] in the [context].
278 ///
279 /// See also:
280 ///
281 /// * [DefaultTextHeightBehavior.maybeOf], which is similar to this method,
282 /// but returns null if no [DefaultTextHeightBehavior] ancestor is found.
283 static TextHeightBehavior of(BuildContext context) {
284 final TextHeightBehavior? behavior = maybeOf(context);
285 assert(() {
286 if (behavior == null) {
287 throw FlutterError(
288 'DefaultTextHeightBehavior.of() was called with a context that does not contain a '
289 'DefaultTextHeightBehavior widget.\n'
290 'No DefaultTextHeightBehavior widget ancestor could be found starting from the '
291 'context that was passed to DefaultTextHeightBehavior.of(). This can happen '
292 'because you are using a widget that looks for a DefaultTextHeightBehavior '
293 'ancestor, but no such ancestor exists.\n'
294 'The context used was:\n'
295 ' $context',
296 );
297 }
298 return true;
299 }());
300 return behavior!;
301 }
302
303 @override
304 bool updateShouldNotify(DefaultTextHeightBehavior oldWidget) {
305 return textHeightBehavior != oldWidget.textHeightBehavior;
306 }
307
308 @override
309 Widget wrap(BuildContext context, Widget child) {
310 return DefaultTextHeightBehavior(
311 textHeightBehavior: textHeightBehavior,
312 child: child,
313 );
314 }
315
316 @override
317 void debugFillProperties(DiagnosticPropertiesBuilder properties) {
318 super.debugFillProperties(properties);
319 properties.add(DiagnosticsProperty<ui.TextHeightBehavior>('textHeightBehavior', textHeightBehavior, defaultValue: null));
320 }
321}
322
323/// A run of text with a single style.
324///
325/// The [Text] widget displays a string of text with single style. The string
326/// might break across multiple lines or might all be displayed on the same line
327/// depending on the layout constraints.
328///
329/// The [style] argument is optional. When omitted, the text will use the style
330/// from the closest enclosing [DefaultTextStyle]. If the given style's
331/// [TextStyle.inherit] property is true (the default), the given style will
332/// be merged with the closest enclosing [DefaultTextStyle]. This merging
333/// behavior is useful, for example, to make the text bold while using the
334/// default font family and size.
335///
336/// {@tool snippet}
337///
338/// This example shows how to display text using the [Text] widget with the
339/// [overflow] set to [TextOverflow.ellipsis].
340///
341/// ![If the text is shorter than the available space, it is displayed in full without an ellipsis.](https://flutter.github.io/assets-for-api-docs/assets/widgets/text.png)
342///
343/// ![If the text overflows, the Text widget displays an ellipsis to trim the overflowing text](https://flutter.github.io/assets-for-api-docs/assets/widgets/text_ellipsis.png)
344///
345/// ```dart
346/// Text(
347/// 'Hello, $_name! How are you?',
348/// textAlign: TextAlign.center,
349/// overflow: TextOverflow.ellipsis,
350/// style: const TextStyle(fontWeight: FontWeight.bold),
351/// )
352/// ```
353/// {@end-tool}
354///
355/// Using the [Text.rich] constructor, the [Text] widget can
356/// display a paragraph with differently styled [TextSpan]s. The sample
357/// that follows displays "Hello beautiful world" with different styles
358/// for each word.
359///
360/// {@tool snippet}
361///
362/// ![The word "Hello" is shown with the default text styles. The word "beautiful" is italicized. The word "world" is bold.](https://flutter.github.io/assets-for-api-docs/assets/widgets/text_rich.png)
363///
364/// ```dart
365/// const Text.rich(
366/// TextSpan(
367/// text: 'Hello', // default text style
368/// children: <TextSpan>[
369/// TextSpan(text: ' beautiful ', style: TextStyle(fontStyle: FontStyle.italic)),
370/// TextSpan(text: 'world', style: TextStyle(fontWeight: FontWeight.bold)),
371/// ],
372/// ),
373/// )
374/// ```
375/// {@end-tool}
376///
377/// ## Interactivity
378///
379/// To make [Text] react to touch events, wrap it in a [GestureDetector] widget
380/// with a [GestureDetector.onTap] handler.
381///
382/// In a Material Design application, consider using a [TextButton] instead, or
383/// if that isn't appropriate, at least using an [InkWell] instead of
384/// [GestureDetector].
385///
386/// To make sections of the text interactive, use [RichText] and specify a
387/// [TapGestureRecognizer] as the [TextSpan.recognizer] of the relevant part of
388/// the text.
389///
390/// ## Selection
391///
392/// [Text] is not selectable by default. To make a [Text] selectable, one can
393/// wrap a subtree with a [SelectionArea] widget. To exclude a part of a subtree
394/// under [SelectionArea] from selection, once can also wrap that part of the
395/// subtree with [SelectionContainer.disabled].
396///
397/// {@tool dartpad}
398/// This sample demonstrates how to disable selection for a Text under a
399/// SelectionArea.
400///
401/// ** See code in examples/api/lib/material/selection_container/selection_container_disabled.0.dart **
402/// {@end-tool}
403///
404/// See also:
405///
406/// * [RichText], which gives you more control over the text styles.
407/// * [DefaultTextStyle], which sets default styles for [Text] widgets.
408/// * [SelectableRegion], which provides an overview of the selection system.
409class Text extends StatelessWidget {
410 /// Creates a text widget.
411 ///
412 /// If the [style] argument is null, the text will use the style from the
413 /// closest enclosing [DefaultTextStyle].
414 ///
415 /// The [overflow] property's behavior is affected by the [softWrap] argument.
416 /// If the [softWrap] is true or null, the glyph causing overflow, and those
417 /// that follow, will not be rendered. Otherwise, it will be shown with the
418 /// given overflow option.
419 const Text(
420 String this.data, {
421 super.key,
422 this.style,
423 this.strutStyle,
424 this.textAlign,
425 this.textDirection,
426 this.locale,
427 this.softWrap,
428 this.overflow,
429 @Deprecated(
430 'Use textScaler instead. '
431 'Use of textScaleFactor was deprecated in preparation for the upcoming nonlinear text scaling support. '
432 'This feature was deprecated after v3.12.0-2.0.pre.',
433 )
434 this.textScaleFactor,
435 this.textScaler,
436 this.maxLines,
437 this.semanticsLabel,
438 this.textWidthBasis,
439 this.textHeightBehavior,
440 this.selectionColor,
441 }) : textSpan = null,
442 assert(
443 textScaler == null || textScaleFactor == null,
444 'textScaleFactor is deprecated and cannot be specified when textScaler is specified.',
445 );
446
447 /// Creates a text widget with a [InlineSpan].
448 ///
449 /// The following subclasses of [InlineSpan] may be used to build rich text:
450 ///
451 /// * [TextSpan]s define text and children [InlineSpan]s.
452 /// * [WidgetSpan]s define embedded inline widgets.
453 ///
454 /// See [RichText] which provides a lower-level way to draw text.
455 const Text.rich(
456 InlineSpan this.textSpan, {
457 super.key,
458 this.style,
459 this.strutStyle,
460 this.textAlign,
461 this.textDirection,
462 this.locale,
463 this.softWrap,
464 this.overflow,
465 @Deprecated(
466 'Use textScaler instead. '
467 'Use of textScaleFactor was deprecated in preparation for the upcoming nonlinear text scaling support. '
468 'This feature was deprecated after v3.12.0-2.0.pre.',
469 )
470 this.textScaleFactor,
471 this.textScaler,
472 this.maxLines,
473 this.semanticsLabel,
474 this.textWidthBasis,
475 this.textHeightBehavior,
476 this.selectionColor,
477 }) : data = null,
478 assert(
479 textScaler == null || textScaleFactor == null,
480 'textScaleFactor is deprecated and cannot be specified when textScaler is specified.',
481 );
482
483 /// The text to display.
484 ///
485 /// This will be null if a [textSpan] is provided instead.
486 final String? data;
487
488 /// The text to display as a [InlineSpan].
489 ///
490 /// This will be null if [data] is provided instead.
491 final InlineSpan? textSpan;
492
493 /// If non-null, the style to use for this text.
494 ///
495 /// If the style's "inherit" property is true, the style will be merged with
496 /// the closest enclosing [DefaultTextStyle]. Otherwise, the style will
497 /// replace the closest enclosing [DefaultTextStyle].
498 final TextStyle? style;
499
500 /// {@macro flutter.painting.textPainter.strutStyle}
501 final StrutStyle? strutStyle;
502
503 /// How the text should be aligned horizontally.
504 final TextAlign? textAlign;
505
506 /// The directionality of the text.
507 ///
508 /// This decides how [textAlign] values like [TextAlign.start] and
509 /// [TextAlign.end] are interpreted.
510 ///
511 /// This is also used to disambiguate how to render bidirectional text. For
512 /// example, if the [data] is an English phrase followed by a Hebrew phrase,
513 /// in a [TextDirection.ltr] context the English phrase will be on the left
514 /// and the Hebrew phrase to its right, while in a [TextDirection.rtl]
515 /// context, the English phrase will be on the right and the Hebrew phrase on
516 /// its left.
517 ///
518 /// Defaults to the ambient [Directionality], if any.
519 final TextDirection? textDirection;
520
521 /// Used to select a font when the same Unicode character can
522 /// be rendered differently, depending on the locale.
523 ///
524 /// It's rarely necessary to set this property. By default its value
525 /// is inherited from the enclosing app with `Localizations.localeOf(context)`.
526 ///
527 /// See [RenderParagraph.locale] for more information.
528 final Locale? locale;
529
530 /// Whether the text should break at soft line breaks.
531 ///
532 /// If false, the glyphs in the text will be positioned as if there was unlimited horizontal space.
533 final bool? softWrap;
534
535 /// How visual overflow should be handled.
536 ///
537 /// If this is null [TextStyle.overflow] will be used, otherwise the value
538 /// from the nearest [DefaultTextStyle] ancestor will be used.
539 final TextOverflow? overflow;
540
541 /// Deprecated. Will be removed in a future version of Flutter. Use
542 /// [textScaler] instead.
543 ///
544 /// The number of font pixels for each logical pixel.
545 ///
546 /// For example, if the text scale factor is 1.5, text will be 50% larger than
547 /// the specified font size.
548 ///
549 /// The value given to the constructor as textScaleFactor. If null, will
550 /// use the [MediaQueryData.textScaleFactor] obtained from the ambient
551 /// [MediaQuery], or 1.0 if there is no [MediaQuery] in scope.
552 @Deprecated(
553 'Use textScaler instead. '
554 'Use of textScaleFactor was deprecated in preparation for the upcoming nonlinear text scaling support. '
555 'This feature was deprecated after v3.12.0-2.0.pre.',
556 )
557 final double? textScaleFactor;
558
559 /// {@macro flutter.painting.textPainter.textScaler}
560 final TextScaler? textScaler;
561
562 /// An optional maximum number of lines for the text to span, wrapping if necessary.
563 /// If the text exceeds the given number of lines, it will be truncated according
564 /// to [overflow].
565 ///
566 /// If this is 1, text will not wrap. Otherwise, text will be wrapped at the
567 /// edge of the box.
568 ///
569 /// If this is null, but there is an ambient [DefaultTextStyle] that specifies
570 /// an explicit number for its [DefaultTextStyle.maxLines], then the
571 /// [DefaultTextStyle] value will take precedence. You can use a [RichText]
572 /// widget directly to entirely override the [DefaultTextStyle].
573 final int? maxLines;
574
575 /// {@template flutter.widgets.Text.semanticsLabel}
576 /// An alternative semantics label for this text.
577 ///
578 /// If present, the semantics of this widget will contain this value instead
579 /// of the actual text. This will overwrite any of the semantics labels applied
580 /// directly to the [TextSpan]s.
581 ///
582 /// This is useful for replacing abbreviations or shorthands with the full
583 /// text value:
584 ///
585 /// ```dart
586 /// const Text(r'$$', semanticsLabel: 'Double dollars')
587 /// ```
588 /// {@endtemplate}
589 final String? semanticsLabel;
590
591 /// {@macro flutter.painting.textPainter.textWidthBasis}
592 final TextWidthBasis? textWidthBasis;
593
594 /// {@macro dart.ui.textHeightBehavior}
595 final ui.TextHeightBehavior? textHeightBehavior;
596
597 /// The color to use when painting the selection.
598 ///
599 /// This is ignored if [SelectionContainer.maybeOf] returns null
600 /// in the [BuildContext] of the [Text] widget.
601 ///
602 /// If null, the ambient [DefaultSelectionStyle] is used (if any); failing
603 /// that, the selection color defaults to [DefaultSelectionStyle.defaultColor]
604 /// (semi-transparent grey).
605 final Color? selectionColor;
606
607 @override
608 Widget build(BuildContext context) {
609 final DefaultTextStyle defaultTextStyle = DefaultTextStyle.of(context);
610 TextStyle? effectiveTextStyle = style;
611 if (style == null || style!.inherit) {
612 effectiveTextStyle = defaultTextStyle.style.merge(style);
613 }
614 if (MediaQuery.boldTextOf(context)) {
615 effectiveTextStyle = effectiveTextStyle!.merge(const TextStyle(fontWeight: FontWeight.bold));
616 }
617 final SelectionRegistrar? registrar = SelectionContainer.maybeOf(context);
618 final TextScaler textScaler = switch ((this.textScaler, textScaleFactor)) {
619 (final TextScaler textScaler, _) => textScaler,
620 // For unmigrated apps, fall back to textScaleFactor.
621 (null, final double textScaleFactor) => TextScaler.linear(textScaleFactor),
622 (null, null) => MediaQuery.textScalerOf(context),
623 };
624
625 Widget result = RichText(
626 textAlign: textAlign ?? defaultTextStyle.textAlign ?? TextAlign.start,
627 textDirection: textDirection, // RichText uses Directionality.of to obtain a default if this is null.
628 locale: locale, // RichText uses Localizations.localeOf to obtain a default if this is null
629 softWrap: softWrap ?? defaultTextStyle.softWrap,
630 overflow: overflow ?? effectiveTextStyle?.overflow ?? defaultTextStyle.overflow,
631 textScaler: textScaler,
632 maxLines: maxLines ?? defaultTextStyle.maxLines,
633 strutStyle: strutStyle,
634 textWidthBasis: textWidthBasis ?? defaultTextStyle.textWidthBasis,
635 textHeightBehavior: textHeightBehavior ?? defaultTextStyle.textHeightBehavior ?? DefaultTextHeightBehavior.maybeOf(context),
636 selectionRegistrar: registrar,
637 selectionColor: selectionColor ?? DefaultSelectionStyle.of(context).selectionColor ?? DefaultSelectionStyle.defaultColor,
638 text: TextSpan(
639 style: effectiveTextStyle,
640 text: data,
641 children: textSpan != null ? <InlineSpan>[textSpan!] : null,
642 ),
643 );
644 if (registrar != null) {
645 result = MouseRegion(
646 cursor: DefaultSelectionStyle.of(context).mouseCursor ?? SystemMouseCursors.text,
647 child: result,
648 );
649 }
650 if (semanticsLabel != null) {
651 result = Semantics(
652 textDirection: textDirection,
653 label: semanticsLabel,
654 child: ExcludeSemantics(
655 child: result,
656 ),
657 );
658 }
659 return result;
660 }
661
662 @override
663 void debugFillProperties(DiagnosticPropertiesBuilder properties) {
664 super.debugFillProperties(properties);
665 properties.add(StringProperty('data', data, showName: false));
666 if (textSpan != null) {
667 properties.add(textSpan!.toDiagnosticsNode(name: 'textSpan', style: DiagnosticsTreeStyle.transition));
668 }
669 style?.debugFillProperties(properties);
670 properties.add(EnumProperty<TextAlign>('textAlign', textAlign, defaultValue: null));
671 properties.add(EnumProperty<TextDirection>('textDirection', textDirection, defaultValue: null));
672 properties.add(DiagnosticsProperty<Locale>('locale', locale, defaultValue: null));
673 properties.add(FlagProperty('softWrap', value: softWrap, ifTrue: 'wrapping at box width', ifFalse: 'no wrapping except at line break characters', showName: true));
674 properties.add(EnumProperty<TextOverflow>('overflow', overflow, defaultValue: null));
675 properties.add(DoubleProperty('textScaleFactor', textScaleFactor, defaultValue: null));
676 properties.add(IntProperty('maxLines', maxLines, defaultValue: null));
677 properties.add(EnumProperty<TextWidthBasis>('textWidthBasis', textWidthBasis, defaultValue: null));
678 properties.add(DiagnosticsProperty<ui.TextHeightBehavior>('textHeightBehavior', textHeightBehavior, defaultValue: null));
679 if (semanticsLabel != null) {
680 properties.add(StringProperty('semanticsLabel', semanticsLabel));
681 }
682 }
683}
684