Skip to content

Commit 077a1fa

Browse files
angelosilvestrematthew-carroll
authored andcommitted
[SuperEditor][SuperTextField] - Improve RTL support (Resolves #2472) (#2518)
1 parent 60eaf11 commit 077a1fa

File tree

36 files changed

+626
-291
lines changed

36 files changed

+626
-291
lines changed

super_editor/lib/src/default_editor/list_items.dart

Lines changed: 86 additions & 52 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ import 'package:super_editor/src/core/editor.dart';
99
import 'package:super_editor/src/core/styles.dart';
1010
import 'package:super_editor/src/default_editor/attributions.dart';
1111
import 'package:super_editor/src/default_editor/blocks/indentation.dart';
12+
import 'package:super_editor/src/default_editor/text_tools.dart';
1213
import 'package:super_editor/src/infrastructure/_logging.dart';
1314
import 'package:super_editor/src/infrastructure/attributed_text_styles.dart';
1415
import 'package:super_editor/src/infrastructure/keyboard.dart';
@@ -161,11 +162,16 @@ class ListItemComponentBuilder implements ComponentBuilder {
161162
ordinalValue = computeListItemOrdinalValue(node, document);
162163
}
163164

165+
final textDirection = getParagraphDirection(node.text.toPlainText());
166+
final textAlignment = textDirection == TextDirection.ltr ? TextAlign.left : TextAlign.right;
167+
164168
return switch (node.type) {
165169
ListItemType.unordered => UnorderedListItemComponentViewModel(
166170
nodeId: node.id,
167171
indent: node.indent,
168172
text: node.text,
173+
textDirection: textDirection,
174+
textAlignment: textAlignment,
169175
textStyleBuilder: noStyleBuilder,
170176
selectionColor: const Color(0x00000000),
171177
),
@@ -174,6 +180,8 @@ class ListItemComponentBuilder implements ComponentBuilder {
174180
indent: node.indent,
175181
ordinalValue: ordinalValue,
176182
text: node.text,
183+
textDirection: textDirection,
184+
textAlignment: textAlignment,
177185
textStyleBuilder: noStyleBuilder,
178186
selectionColor: const Color(0x00000000),
179187
),
@@ -196,6 +204,8 @@ class ListItemComponentBuilder implements ComponentBuilder {
196204
indent: componentViewModel.indent,
197205
dotStyle: componentViewModel.dotStyle,
198206
textSelection: componentViewModel.selection,
207+
textDirection: componentViewModel.textDirection,
208+
textAlignment: componentViewModel.textAlignment,
199209
selectionColor: componentViewModel.selectionColor,
200210
highlightWhenEmpty: componentViewModel.highlightWhenEmpty,
201211
underlines: componentViewModel.createUnderlines(),
@@ -206,6 +216,8 @@ class ListItemComponentBuilder implements ComponentBuilder {
206216
indent: componentViewModel.indent,
207217
listIndex: componentViewModel.ordinalValue!,
208218
text: componentViewModel.text,
219+
textDirection: componentViewModel.textDirection,
220+
textAlignment: componentViewModel.textAlignment,
209221
styleBuilder: componentViewModel.textStyleBuilder,
210222
numeralStyle: componentViewModel.numeralStyle,
211223
textSelection: componentViewModel.selection,
@@ -281,6 +293,7 @@ abstract class ListItemComponentViewModel extends SingleColumnLayoutComponentVie
281293
indent == other.indent &&
282294
text == other.text &&
283295
textDirection == other.textDirection &&
296+
textAlignment == other.textAlignment &&
284297
selection == other.selection &&
285298
selectionColor == other.selectionColor &&
286299
highlightWhenEmpty == other.highlightWhenEmpty &&
@@ -298,6 +311,7 @@ abstract class ListItemComponentViewModel extends SingleColumnLayoutComponentVie
298311
indent.hashCode ^
299312
text.hashCode ^
300313
textDirection.hashCode ^
314+
textAlignment.hashCode ^
301315
selection.hashCode ^
302316
selectionColor.hashCode ^
303317
highlightWhenEmpty.hashCode ^
@@ -355,6 +369,7 @@ class UnorderedListItemComponentViewModel extends ListItemComponentViewModel {
355369
textStyleBuilder: textStyleBuilder,
356370
dotStyle: dotStyle,
357371
textDirection: textDirection,
372+
textAlignment: textAlignment,
358373
selection: selection,
359374
selectionColor: selectionColor,
360375
composingRegion: composingRegion,
@@ -423,6 +438,7 @@ class OrderedListItemComponentViewModel extends ListItemComponentViewModel {
423438
text: text,
424439
textStyleBuilder: textStyleBuilder,
425440
textDirection: textDirection,
441+
textAlignment: textAlignment,
426442
selection: selection,
427443
selectionColor: selectionColor,
428444
composingRegion: composingRegion,
@@ -493,6 +509,8 @@ class UnorderedListItemComponent extends StatefulWidget {
493509
Key? key,
494510
required this.componentKey,
495511
required this.text,
512+
this.textDirection = TextDirection.ltr,
513+
this.textAlignment = TextAlign.left,
496514
required this.styleBuilder,
497515
this.inlineWidgetBuilders = const [],
498516
this.dotBuilder = _defaultUnorderedListItemDotBuilder,
@@ -510,6 +528,8 @@ class UnorderedListItemComponent extends StatefulWidget {
510528

511529
final GlobalKey componentKey;
512530
final AttributedText text;
531+
final TextDirection textDirection;
532+
final TextAlign textAlignment;
513533
final AttributionStyleBuilder styleBuilder;
514534
final InlineWidgetBuilderChain inlineWidgetBuilders;
515535
final UnorderedListItemDotBuilder dotBuilder;
@@ -558,34 +578,39 @@ class _UnorderedListItemComponentState extends State<UnorderedListItemComponent>
558578
return ProxyTextDocumentComponent(
559579
key: widget.componentKey,
560580
textComponentKey: _innerTextComponentKey,
561-
child: Row(
562-
crossAxisAlignment: CrossAxisAlignment.start,
563-
children: [
564-
Container(
565-
width: indentSpace,
566-
decoration: BoxDecoration(
567-
border: widget.showDebugPaint ? Border.all(width: 1, color: Colors.grey) : null,
568-
),
569-
child: SizedBox(
570-
height: lineHeight,
571-
child: widget.dotBuilder(context, widget),
581+
child: Directionality(
582+
textDirection: widget.textDirection,
583+
child: Row(
584+
crossAxisAlignment: CrossAxisAlignment.start,
585+
children: [
586+
Container(
587+
width: indentSpace,
588+
decoration: BoxDecoration(
589+
border: widget.showDebugPaint ? Border.all(width: 1, color: Colors.grey) : null,
590+
),
591+
child: SizedBox(
592+
height: lineHeight,
593+
child: widget.dotBuilder(context, widget),
594+
),
572595
),
573-
),
574-
Expanded(
575-
child: TextComponent(
576-
key: _innerTextComponentKey,
577-
text: widget.text,
578-
textStyleBuilder: widget.styleBuilder,
579-
inlineWidgetBuilders: widget.inlineWidgetBuilders,
580-
textSelection: widget.textSelection,
581-
textScaler: textScaler,
582-
selectionColor: widget.selectionColor,
583-
highlightWhenEmpty: widget.highlightWhenEmpty,
584-
underlines: widget.underlines,
585-
showDebugPaint: widget.showDebugPaint,
596+
Expanded(
597+
child: TextComponent(
598+
key: _innerTextComponentKey,
599+
text: widget.text,
600+
textDirection: widget.textDirection,
601+
textAlign: widget.textAlignment,
602+
textStyleBuilder: widget.styleBuilder,
603+
inlineWidgetBuilders: widget.inlineWidgetBuilders,
604+
textSelection: widget.textSelection,
605+
textScaler: textScaler,
606+
selectionColor: widget.selectionColor,
607+
highlightWhenEmpty: widget.highlightWhenEmpty,
608+
underlines: widget.underlines,
609+
showDebugPaint: widget.showDebugPaint,
610+
),
586611
),
587-
),
588-
],
612+
],
613+
),
589614
),
590615
);
591616
}
@@ -659,6 +684,8 @@ class OrderedListItemComponent extends StatefulWidget {
659684
required this.componentKey,
660685
required this.listIndex,
661686
required this.text,
687+
this.textDirection = TextDirection.ltr,
688+
this.textAlignment = TextAlign.left,
662689
required this.styleBuilder,
663690
this.inlineWidgetBuilders = const [],
664691
this.numeralBuilder = _defaultOrderedListItemNumeralBuilder,
@@ -677,6 +704,8 @@ class OrderedListItemComponent extends StatefulWidget {
677704
final GlobalKey componentKey;
678705
final int listIndex;
679706
final AttributedText text;
707+
final TextDirection textDirection;
708+
final TextAlign textAlignment;
680709
final AttributionStyleBuilder styleBuilder;
681710
final InlineWidgetBuilderChain inlineWidgetBuilders;
682711
final OrderedListItemNumeralBuilder numeralBuilder;
@@ -725,35 +754,40 @@ class _OrderedListItemComponentState extends State<OrderedListItemComponent> {
725754
return ProxyTextDocumentComponent(
726755
key: widget.componentKey,
727756
textComponentKey: _innerTextComponentKey,
728-
child: Row(
729-
crossAxisAlignment: CrossAxisAlignment.start,
730-
children: [
731-
Container(
732-
width: indentSpace,
733-
height: lineHeight,
734-
decoration: BoxDecoration(
735-
border: widget.showDebugPaint ? Border.all(width: 1, color: Colors.grey) : null,
736-
),
737-
child: SizedBox(
757+
child: Directionality(
758+
textDirection: widget.textDirection,
759+
child: Row(
760+
crossAxisAlignment: CrossAxisAlignment.start,
761+
children: [
762+
Container(
763+
width: indentSpace,
738764
height: lineHeight,
739-
child: widget.numeralBuilder(context, widget),
765+
decoration: BoxDecoration(
766+
border: widget.showDebugPaint ? Border.all(width: 1, color: Colors.grey) : null,
767+
),
768+
child: SizedBox(
769+
height: lineHeight,
770+
child: widget.numeralBuilder(context, widget),
771+
),
740772
),
741-
),
742-
Expanded(
743-
child: TextComponent(
744-
key: _innerTextComponentKey,
745-
text: widget.text,
746-
textStyleBuilder: widget.styleBuilder,
747-
inlineWidgetBuilders: widget.inlineWidgetBuilders,
748-
textSelection: widget.textSelection,
749-
textScaler: textScaler,
750-
selectionColor: widget.selectionColor,
751-
highlightWhenEmpty: widget.highlightWhenEmpty,
752-
underlines: widget.underlines,
753-
showDebugPaint: widget.showDebugPaint,
773+
Expanded(
774+
child: TextComponent(
775+
key: _innerTextComponentKey,
776+
text: widget.text,
777+
textDirection: widget.textDirection,
778+
textAlign: widget.textAlignment,
779+
textStyleBuilder: widget.styleBuilder,
780+
inlineWidgetBuilders: widget.inlineWidgetBuilders,
781+
textSelection: widget.textSelection,
782+
textScaler: textScaler,
783+
selectionColor: widget.selectionColor,
784+
highlightWhenEmpty: widget.highlightWhenEmpty,
785+
underlines: widget.underlines,
786+
showDebugPaint: widget.showDebugPaint,
787+
),
754788
),
755-
),
756-
],
789+
],
790+
),
757791
),
758792
);
759793
}

super_editor/lib/src/default_editor/paragraph.dart

Lines changed: 34 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -331,38 +331,42 @@ class _ParagraphComponentState extends State<ParagraphComponent>
331331

332332
@override
333333
Widget build(BuildContext context) {
334-
return Row(
335-
crossAxisAlignment: CrossAxisAlignment.start,
336-
children: [
337-
// Indent spacing on left.
338-
SizedBox(
339-
width: widget.viewModel.indentCalculator(
340-
widget.viewModel.textStyleBuilder({}),
341-
widget.viewModel.indent,
334+
return Directionality(
335+
textDirection: widget.viewModel.textDirection,
336+
child: Row(
337+
crossAxisAlignment: CrossAxisAlignment.start,
338+
children: [
339+
// Indent spacing on left.
340+
SizedBox(
341+
width: widget.viewModel.indentCalculator(
342+
widget.viewModel.textStyleBuilder({}),
343+
widget.viewModel.indent,
344+
),
342345
),
343-
),
344-
// The actual paragraph UI.
345-
Expanded(
346-
child: TextComponent(
347-
key: _textKey,
348-
text: widget.viewModel.text,
349-
textAlign: widget.viewModel.textAlignment,
350-
textScaler: widget.viewModel.textScaler,
351-
textStyleBuilder: widget.viewModel.textStyleBuilder,
352-
inlineWidgetBuilders: widget.viewModel.inlineWidgetBuilders,
353-
metadata: widget.viewModel.blockType != null
354-
? {
355-
'blockType': widget.viewModel.blockType,
356-
}
357-
: {},
358-
textSelection: widget.viewModel.selection,
359-
selectionColor: widget.viewModel.selectionColor,
360-
highlightWhenEmpty: widget.viewModel.highlightWhenEmpty,
361-
underlines: widget.viewModel.createUnderlines(),
362-
showDebugPaint: widget.showDebugPaint,
346+
// The actual paragraph UI.
347+
Expanded(
348+
child: TextComponent(
349+
key: _textKey,
350+
text: widget.viewModel.text,
351+
textDirection: widget.viewModel.textDirection,
352+
textAlign: widget.viewModel.textAlignment,
353+
textScaler: widget.viewModel.textScaler,
354+
textStyleBuilder: widget.viewModel.textStyleBuilder,
355+
inlineWidgetBuilders: widget.viewModel.inlineWidgetBuilders,
356+
metadata: widget.viewModel.blockType != null
357+
? {
358+
'blockType': widget.viewModel.blockType,
359+
}
360+
: {},
361+
textSelection: widget.viewModel.selection,
362+
selectionColor: widget.viewModel.selectionColor,
363+
highlightWhenEmpty: widget.viewModel.highlightWhenEmpty,
364+
underlines: widget.viewModel.createUnderlines(),
365+
showDebugPaint: widget.showDebugPaint,
366+
),
363367
),
364-
),
365-
],
368+
],
369+
),
366370
);
367371
}
368372
}

0 commit comments

Comments
 (0)