Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[SuperEditor][SuperTextField] Improve RTL support (Resolves #2472) #2518

Merged
merged 3 commits into from
Jan 25, 2025
Merged
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
138 changes: 86 additions & 52 deletions super_editor/lib/src/default_editor/list_items.dart
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import 'package:super_editor/src/core/editor.dart';
import 'package:super_editor/src/core/styles.dart';
import 'package:super_editor/src/default_editor/attributions.dart';
import 'package:super_editor/src/default_editor/blocks/indentation.dart';
import 'package:super_editor/src/default_editor/text_tools.dart';
import 'package:super_editor/src/infrastructure/_logging.dart';
import 'package:super_editor/src/infrastructure/attributed_text_styles.dart';
import 'package:super_editor/src/infrastructure/keyboard.dart';
Expand Down Expand Up @@ -161,11 +162,16 @@ class ListItemComponentBuilder implements ComponentBuilder {
ordinalValue = computeListItemOrdinalValue(node, document);
}

final textDirection = getParagraphDirection(node.text.toPlainText());
final textAlignment = textDirection == TextDirection.ltr ? TextAlign.left : TextAlign.right;

return switch (node.type) {
ListItemType.unordered => UnorderedListItemComponentViewModel(
nodeId: node.id,
indent: node.indent,
text: node.text,
textDirection: textDirection,
textAlignment: textAlignment,
textStyleBuilder: noStyleBuilder,
selectionColor: const Color(0x00000000),
),
Expand All @@ -174,6 +180,8 @@ class ListItemComponentBuilder implements ComponentBuilder {
indent: node.indent,
ordinalValue: ordinalValue,
text: node.text,
textDirection: textDirection,
textAlignment: textAlignment,
textStyleBuilder: noStyleBuilder,
selectionColor: const Color(0x00000000),
),
Expand All @@ -196,6 +204,8 @@ class ListItemComponentBuilder implements ComponentBuilder {
indent: componentViewModel.indent,
dotStyle: componentViewModel.dotStyle,
textSelection: componentViewModel.selection,
textDirection: componentViewModel.textDirection,
textAlignment: componentViewModel.textAlignment,
selectionColor: componentViewModel.selectionColor,
highlightWhenEmpty: componentViewModel.highlightWhenEmpty,
underlines: componentViewModel.createUnderlines(),
Expand All @@ -206,6 +216,8 @@ class ListItemComponentBuilder implements ComponentBuilder {
indent: componentViewModel.indent,
listIndex: componentViewModel.ordinalValue!,
text: componentViewModel.text,
textDirection: componentViewModel.textDirection,
textAlignment: componentViewModel.textAlignment,
styleBuilder: componentViewModel.textStyleBuilder,
numeralStyle: componentViewModel.numeralStyle,
textSelection: componentViewModel.selection,
Expand Down Expand Up @@ -281,6 +293,7 @@ abstract class ListItemComponentViewModel extends SingleColumnLayoutComponentVie
indent == other.indent &&
text == other.text &&
textDirection == other.textDirection &&
textAlignment == other.textAlignment &&
selection == other.selection &&
selectionColor == other.selectionColor &&
highlightWhenEmpty == other.highlightWhenEmpty &&
Expand All @@ -298,6 +311,7 @@ abstract class ListItemComponentViewModel extends SingleColumnLayoutComponentVie
indent.hashCode ^
text.hashCode ^
textDirection.hashCode ^
textAlignment.hashCode ^
selection.hashCode ^
selectionColor.hashCode ^
highlightWhenEmpty.hashCode ^
Expand Down Expand Up @@ -355,6 +369,7 @@ class UnorderedListItemComponentViewModel extends ListItemComponentViewModel {
textStyleBuilder: textStyleBuilder,
dotStyle: dotStyle,
textDirection: textDirection,
textAlignment: textAlignment,
selection: selection,
selectionColor: selectionColor,
composingRegion: composingRegion,
Expand Down Expand Up @@ -423,6 +438,7 @@ class OrderedListItemComponentViewModel extends ListItemComponentViewModel {
text: text,
textStyleBuilder: textStyleBuilder,
textDirection: textDirection,
textAlignment: textAlignment,
selection: selection,
selectionColor: selectionColor,
composingRegion: composingRegion,
Expand Down Expand Up @@ -493,6 +509,8 @@ class UnorderedListItemComponent extends StatefulWidget {
Key? key,
required this.componentKey,
required this.text,
this.textDirection = TextDirection.ltr,
this.textAlignment = TextAlign.left,
required this.styleBuilder,
this.inlineWidgetBuilders = const [],
this.dotBuilder = _defaultUnorderedListItemDotBuilder,
Expand All @@ -510,6 +528,8 @@ class UnorderedListItemComponent extends StatefulWidget {

final GlobalKey componentKey;
final AttributedText text;
final TextDirection textDirection;
final TextAlign textAlignment;
final AttributionStyleBuilder styleBuilder;
final InlineWidgetBuilderChain inlineWidgetBuilders;
final UnorderedListItemDotBuilder dotBuilder;
Expand Down Expand Up @@ -558,34 +578,39 @@ class _UnorderedListItemComponentState extends State<UnorderedListItemComponent>
return ProxyTextDocumentComponent(
key: widget.componentKey,
textComponentKey: _innerTextComponentKey,
child: Row(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Container(
width: indentSpace,
decoration: BoxDecoration(
border: widget.showDebugPaint ? Border.all(width: 1, color: Colors.grey) : null,
),
child: SizedBox(
height: lineHeight,
child: widget.dotBuilder(context, widget),
child: Directionality(
textDirection: widget.textDirection,
child: Row(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Container(
width: indentSpace,
decoration: BoxDecoration(
border: widget.showDebugPaint ? Border.all(width: 1, color: Colors.grey) : null,
),
child: SizedBox(
height: lineHeight,
child: widget.dotBuilder(context, widget),
),
),
),
Expanded(
child: TextComponent(
key: _innerTextComponentKey,
text: widget.text,
textStyleBuilder: widget.styleBuilder,
inlineWidgetBuilders: widget.inlineWidgetBuilders,
textSelection: widget.textSelection,
textScaler: textScaler,
selectionColor: widget.selectionColor,
highlightWhenEmpty: widget.highlightWhenEmpty,
underlines: widget.underlines,
showDebugPaint: widget.showDebugPaint,
Expanded(
child: TextComponent(
key: _innerTextComponentKey,
text: widget.text,
textDirection: widget.textDirection,
textAlign: widget.textAlignment,
textStyleBuilder: widget.styleBuilder,
inlineWidgetBuilders: widget.inlineWidgetBuilders,
textSelection: widget.textSelection,
textScaler: textScaler,
selectionColor: widget.selectionColor,
highlightWhenEmpty: widget.highlightWhenEmpty,
underlines: widget.underlines,
showDebugPaint: widget.showDebugPaint,
),
),
),
],
],
),
),
);
}
Expand Down Expand Up @@ -659,6 +684,8 @@ class OrderedListItemComponent extends StatefulWidget {
required this.componentKey,
required this.listIndex,
required this.text,
this.textDirection = TextDirection.ltr,
this.textAlignment = TextAlign.left,
required this.styleBuilder,
this.inlineWidgetBuilders = const [],
this.numeralBuilder = _defaultOrderedListItemNumeralBuilder,
Expand All @@ -677,6 +704,8 @@ class OrderedListItemComponent extends StatefulWidget {
final GlobalKey componentKey;
final int listIndex;
final AttributedText text;
final TextDirection textDirection;
final TextAlign textAlignment;
final AttributionStyleBuilder styleBuilder;
final InlineWidgetBuilderChain inlineWidgetBuilders;
final OrderedListItemNumeralBuilder numeralBuilder;
Expand Down Expand Up @@ -725,35 +754,40 @@ class _OrderedListItemComponentState extends State<OrderedListItemComponent> {
return ProxyTextDocumentComponent(
key: widget.componentKey,
textComponentKey: _innerTextComponentKey,
child: Row(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Container(
width: indentSpace,
height: lineHeight,
decoration: BoxDecoration(
border: widget.showDebugPaint ? Border.all(width: 1, color: Colors.grey) : null,
),
child: SizedBox(
child: Directionality(
textDirection: widget.textDirection,
child: Row(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Container(
width: indentSpace,
height: lineHeight,
child: widget.numeralBuilder(context, widget),
decoration: BoxDecoration(
border: widget.showDebugPaint ? Border.all(width: 1, color: Colors.grey) : null,
),
child: SizedBox(
height: lineHeight,
child: widget.numeralBuilder(context, widget),
),
),
),
Expanded(
child: TextComponent(
key: _innerTextComponentKey,
text: widget.text,
textStyleBuilder: widget.styleBuilder,
inlineWidgetBuilders: widget.inlineWidgetBuilders,
textSelection: widget.textSelection,
textScaler: textScaler,
selectionColor: widget.selectionColor,
highlightWhenEmpty: widget.highlightWhenEmpty,
underlines: widget.underlines,
showDebugPaint: widget.showDebugPaint,
Expanded(
child: TextComponent(
key: _innerTextComponentKey,
text: widget.text,
textDirection: widget.textDirection,
textAlign: widget.textAlignment,
textStyleBuilder: widget.styleBuilder,
inlineWidgetBuilders: widget.inlineWidgetBuilders,
textSelection: widget.textSelection,
textScaler: textScaler,
selectionColor: widget.selectionColor,
highlightWhenEmpty: widget.highlightWhenEmpty,
underlines: widget.underlines,
showDebugPaint: widget.showDebugPaint,
),
),
),
],
],
),
),
);
}
Expand Down
64 changes: 34 additions & 30 deletions super_editor/lib/src/default_editor/paragraph.dart
Original file line number Diff line number Diff line change
Expand Up @@ -331,38 +331,42 @@ class _ParagraphComponentState extends State<ParagraphComponent>

@override
Widget build(BuildContext context) {
return Row(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
// Indent spacing on left.
SizedBox(
width: widget.viewModel.indentCalculator(
widget.viewModel.textStyleBuilder({}),
widget.viewModel.indent,
return Directionality(
textDirection: widget.viewModel.textDirection,
child: Row(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
// Indent spacing on left.
SizedBox(
width: widget.viewModel.indentCalculator(
widget.viewModel.textStyleBuilder({}),
widget.viewModel.indent,
),
),
),
// The actual paragraph UI.
Expanded(
child: TextComponent(
key: _textKey,
text: widget.viewModel.text,
textAlign: widget.viewModel.textAlignment,
textScaler: widget.viewModel.textScaler,
textStyleBuilder: widget.viewModel.textStyleBuilder,
inlineWidgetBuilders: widget.viewModel.inlineWidgetBuilders,
metadata: widget.viewModel.blockType != null
? {
'blockType': widget.viewModel.blockType,
}
: {},
textSelection: widget.viewModel.selection,
selectionColor: widget.viewModel.selectionColor,
highlightWhenEmpty: widget.viewModel.highlightWhenEmpty,
underlines: widget.viewModel.createUnderlines(),
showDebugPaint: widget.showDebugPaint,
// The actual paragraph UI.
Expanded(
child: TextComponent(
key: _textKey,
text: widget.viewModel.text,
textDirection: widget.viewModel.textDirection,
textAlign: widget.viewModel.textAlignment,
textScaler: widget.viewModel.textScaler,
textStyleBuilder: widget.viewModel.textStyleBuilder,
inlineWidgetBuilders: widget.viewModel.inlineWidgetBuilders,
metadata: widget.viewModel.blockType != null
? {
'blockType': widget.viewModel.blockType,
}
: {},
textSelection: widget.viewModel.selection,
selectionColor: widget.viewModel.selectionColor,
highlightWhenEmpty: widget.viewModel.highlightWhenEmpty,
underlines: widget.viewModel.createUnderlines(),
showDebugPaint: widget.showDebugPaint,
),
),
),
],
],
),
);
}
}
Expand Down
Loading
Loading