Support text direction rtl

pull/681/head
X Code 3 years ago
parent a92bfe9d6d
commit 4f9ee27f7d
  1. 12
      lib/src/models/documents/attribute.dart
  2. 11
      lib/src/utils/delta.dart
  3. 7
      lib/src/widgets/raw_editor.dart
  4. 5
      lib/src/widgets/text_block.dart
  5. 11
      lib/src/widgets/toolbar.dart

@ -79,6 +79,8 @@ class Attribute<T> {
static final BlockQuoteAttribute blockQuote = BlockQuoteAttribute();
static final DirectionAttribute direction = DirectionAttribute(null);
static final WidthAttribute width = WidthAttribute(null);
static final HeightAttribute height = HeightAttribute(null);
@ -116,6 +118,7 @@ class Attribute<T> {
Attribute.codeBlock.key,
Attribute.blockQuote.key,
Attribute.indent.key,
Attribute.direction.key,
});
static final Set<String> blockKeysExceptHeader = LinkedHashSet.of({
@ -124,6 +127,7 @@ class Attribute<T> {
Attribute.codeBlock.key,
Attribute.blockQuote.key,
Attribute.indent.key,
Attribute.direction.key,
});
static final Set<String> exclusiveBlockKeys = LinkedHashSet.of({
@ -163,6 +167,9 @@ class Attribute<T> {
// "attributes":{"list":"unchecked"}
static Attribute<String?> get unchecked => ListAttribute('unchecked');
// "attributes":{"direction":"rtl"}
static Attribute<String?> get rtl => DirectionAttribute('rtl');
// "attributes":{"indent":1"}
static Attribute<int?> get indentL1 => IndentAttribute(level: 1);
@ -309,6 +316,11 @@ class BlockQuoteAttribute extends Attribute<bool> {
BlockQuoteAttribute() : super('blockquote', AttributeScope.BLOCK, true);
}
class DirectionAttribute extends Attribute<String?> {
DirectionAttribute(String? val)
: super('direction', AttributeScope.BLOCK, val);
}
class WidthAttribute extends Attribute<String?> {
WidthAttribute(String? val) : super('width', AttributeScope.IGNORE, val);
}

@ -1,5 +1,8 @@
import 'dart:math' as math;
import 'dart:ui';
import '../models/documents/attribute.dart';
import '../models/documents/nodes/node.dart';
import '../models/quill_delta.dart';
// Diff between two texts - old text and new text
@ -72,3 +75,11 @@ int getPositionDelta(Delta user, Delta actual) {
}
return diff;
}
TextDirection getDirectionOfNode(Node node) {
final direction = node.style.attributes[Attribute.direction.key];
if (direction == Attribute.rtl) {
return TextDirection.rtl;
}
return TextDirection.ltr;
}

@ -19,6 +19,7 @@ import '../models/documents/nodes/embeddable.dart';
import '../models/documents/nodes/line.dart';
import '../models/documents/nodes/node.dart';
import '../models/documents/style.dart';
import '../utils/delta.dart';
import '../utils/platform.dart';
import 'controller.dart';
import 'cursor.dart';
@ -436,7 +437,8 @@ class RawEditorState extends EditorState
for (final node in doc.root.children) {
if (node is Line) {
final editableTextLine = _getEditableTextLineFromNode(node, context);
result.add(editableTextLine);
result.add(Directionality(
textDirection: getDirectionOfNode(node), child: editableTextLine));
} else if (node is Block) {
final attrs = node.style.attributes;
final editableTextBlock = EditableTextBlock(
@ -461,7 +463,8 @@ class RawEditorState extends EditorState
onCheckboxTap: _handleCheckboxTap,
readOnly: widget.readOnly,
customStyleBuilder: widget.customStyleBuilder);
result.add(editableTextBlock);
result.add(Directionality(
textDirection: getDirectionOfNode(node), child: editableTextBlock));
} else {
throw StateError('Unreachable.');
}

@ -5,6 +5,7 @@ import 'package:tuple/tuple.dart';
import '../../flutter_quill.dart';
import '../models/documents/nodes/block.dart';
import '../models/documents/nodes/line.dart';
import '../utils/delta.dart';
import 'box.dart';
import 'cursor.dart';
import 'delegate.dart';
@ -146,7 +147,9 @@ class EditableTextBlock extends StatelessWidget {
hasFocus,
MediaQuery.of(context).devicePixelRatio,
cursorCont);
children.add(editableTextLine);
final nodeTextDirection = getDirectionOfNode(line);
children.add(Directionality(
textDirection: nodeTextDirection, child: editableTextLine));
}
return children.toList(growable: false);
}

@ -100,6 +100,7 @@ class QuillToolbar extends StatelessWidget implements PreferredSizeWidget {
bool showImageButton = true,
bool showVideoButton = true,
bool showCameraButton = true,
bool showDirection = false,
OnImagePickCallback? onImagePickCallback,
OnVideoPickCallback? onVideoPickCallback,
MediaPickSettingSelector? mediaPickSettingSelector,
@ -131,7 +132,7 @@ class QuillToolbar extends StatelessWidget implements PreferredSizeWidget {
showClearFormat ||
onImagePickCallback != null ||
onVideoPickCallback != null,
showAlignmentButtons,
showAlignmentButtons || showDirection,
showLeftAlignment,
showCenterAlignment,
showRightAlignment,
@ -296,6 +297,14 @@ class QuillToolbar extends StatelessWidget implements PreferredSizeWidget {
showRightAlignment: showRightAlignment,
showJustifyAlignment: showJustifyAlignment,
),
if (showDirection)
ToggleStyleButton(
attribute: Attribute.rtl,
controller: controller,
icon: Icons.format_textdirection_r_to_l,
iconSize: toolbarIconSize,
iconTheme: iconTheme,
),
if (showDividers &&
isButtonGroupShown[1] &&
(isButtonGroupShown[2] ||

Loading…
Cancel
Save