fix custom checkbox issue (#573)

pull/574/head
AppFlowy.IO 3 years ago committed by GitHub
parent 5b126c8b36
commit 7030784e52
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
  1. 133
      lib/src/widgets/text_block.dart

@ -12,37 +12,9 @@ import 'link.dart';
import 'text_line.dart'; import 'text_line.dart';
import 'text_selection.dart'; import 'text_selection.dart';
const List<int> arabianRomanNumbers = [ const List<int> arabianRomanNumbers = [1000, 900, 500, 400, 100, 90, 50, 40, 10, 9, 5, 4, 1];
1000,
900, const List<String> romanNumbers = ['M', 'CM', 'D', 'CD', 'C', 'XC', 'L', 'XL', 'X', 'IX', 'V', 'IV', 'I'];
500,
400,
100,
90,
50,
40,
10,
9,
5,
4,
1
];
const List<String> romanNumbers = [
'M',
'CM',
'D',
'CD',
'C',
'XC',
'L',
'XL',
'X',
'IX',
'V',
'IV',
'I'
];
class EditableTextBlock extends StatelessWidget { class EditableTextBlock extends StatelessWidget {
const EditableTextBlock( const EditableTextBlock(
@ -102,8 +74,7 @@ class EditableTextBlock extends StatelessWidget {
_buildChildren(context, indentLevelCounts)); _buildChildren(context, indentLevelCounts));
} }
BoxDecoration? _getDecorationForBlock( BoxDecoration? _getDecorationForBlock(Block node, DefaultStyles? defaultStyles) {
Block node, DefaultStyles? defaultStyles) {
final attrs = block.style.attributes; final attrs = block.style.attributes;
if (attrs.containsKey(Attribute.blockQuote.key)) { if (attrs.containsKey(Attribute.blockQuote.key)) {
return defaultStyles!.quote!.decoration; return defaultStyles!.quote!.decoration;
@ -114,8 +85,7 @@ class EditableTextBlock extends StatelessWidget {
return null; return null;
} }
List<Widget> _buildChildren( List<Widget> _buildChildren(BuildContext context, Map<int, int> indentLevelCounts) {
BuildContext context, Map<int, int> indentLevelCounts) {
final defaultStyles = QuillStyles.getStyles(context, false); final defaultStyles = QuillStyles.getStyles(context, false);
final count = block.children.length; final count = block.children.length;
final children = <Widget>[]; final children = <Widget>[];
@ -150,8 +120,7 @@ class EditableTextBlock extends StatelessWidget {
return children.toList(growable: false); return children.toList(growable: false);
} }
Widget? _buildLeading(BuildContext context, Line line, int index, Widget? _buildLeading(BuildContext context, Line line, int index, Map<int, int> indentLevelCounts, int count) {
Map<int, int> indentLevelCounts, int count) {
final defaultStyles = QuillStyles.getStyles(context, false); final defaultStyles = QuillStyles.getStyles(context, false);
final attrs = line.style.attributes; final attrs = line.style.attributes;
if (attrs[Attribute.list.key] == Attribute.ol) { if (attrs[Attribute.list.key] == Attribute.ol) {
@ -168,8 +137,7 @@ class EditableTextBlock extends StatelessWidget {
if (attrs[Attribute.list.key] == Attribute.ul) { if (attrs[Attribute.list.key] == Attribute.ul) {
return QuillBulletPoint( return QuillBulletPoint(
style: style: defaultStyles!.leading!.style.copyWith(fontWeight: FontWeight.bold),
defaultStyles!.leading!.style.copyWith(fontWeight: FontWeight.bold),
width: 32, width: 32,
); );
} }
@ -180,6 +148,7 @@ class EditableTextBlock extends StatelessWidget {
value: true, value: true,
enabled: !readOnly, enabled: !readOnly,
onChanged: (checked) => onCheckboxTap(line.documentOffset, checked), onChanged: (checked) => onCheckboxTap(line.documentOffset, checked),
uiBuilder: defaultStyles?.lists?.checkboxUIBuilder,
); );
} }
@ -189,6 +158,7 @@ class EditableTextBlock extends StatelessWidget {
value: false, value: false,
enabled: !readOnly, enabled: !readOnly,
onChanged: (checked) => onCheckboxTap(line.documentOffset, checked), onChanged: (checked) => onCheckboxTap(line.documentOffset, checked),
uiBuilder: defaultStyles?.lists?.checkboxUIBuilder,
); );
} }
@ -197,8 +167,7 @@ class EditableTextBlock extends StatelessWidget {
index: index, index: index,
indentLevelCounts: indentLevelCounts, indentLevelCounts: indentLevelCounts,
count: count, count: count,
style: defaultStyles!.code!.style style: defaultStyles!.code!.style.copyWith(color: defaultStyles.code!.style.color!.withOpacity(0.4)),
.copyWith(color: defaultStyles.code!.style.color!.withOpacity(0.4)),
width: 32, width: 32,
attrs: attrs, attrs: attrs,
padding: 16, padding: 16,
@ -223,16 +192,14 @@ class EditableTextBlock extends StatelessWidget {
var baseIndent = 0.0; var baseIndent = 0.0;
if (attrs.containsKey(Attribute.list.key) || if (attrs.containsKey(Attribute.list.key) || attrs.containsKey(Attribute.codeBlock.key)) {
attrs.containsKey(Attribute.codeBlock.key)) {
baseIndent = 32.0; baseIndent = 32.0;
} }
return baseIndent + extraIndent; return baseIndent + extraIndent;
} }
Tuple2 _getSpacingForLine( Tuple2 _getSpacingForLine(Line node, int index, int count, DefaultStyles? defaultStyles) {
Line node, int index, int count, DefaultStyles? defaultStyles) {
var top = 0.0, bottom = 0.0; var top = 0.0, bottom = 0.0;
final attrs = block.style.attributes; final attrs = block.style.attributes;
@ -283,8 +250,7 @@ class EditableTextBlock extends StatelessWidget {
} }
} }
class RenderEditableTextBlock extends RenderEditableContainerBox class RenderEditableTextBlock extends RenderEditableContainerBox implements RenderEditableBox {
implements RenderEditableBox {
RenderEditableTextBlock({ RenderEditableTextBlock({
required Block block, required Block block,
required TextDirection textDirection, required TextDirection textDirection,
@ -370,8 +336,7 @@ class RenderEditableTextBlock extends RenderEditableContainerBox
TextPosition getPositionForOffset(Offset offset) { TextPosition getPositionForOffset(Offset offset) {
final child = childAtOffset(offset)!; final child = childAtOffset(offset)!;
final parentData = child.parentData as BoxParentData; final parentData = child.parentData as BoxParentData;
final localPosition = final localPosition = child.getPositionForOffset(offset - parentData.offset);
child.getPositionForOffset(offset - parentData.offset);
return TextPosition( return TextPosition(
offset: localPosition.offset + child.getContainer().offset, offset: localPosition.offset + child.getContainer().offset,
affinity: localPosition.affinity, affinity: localPosition.affinity,
@ -382,8 +347,7 @@ class RenderEditableTextBlock extends RenderEditableContainerBox
TextRange getWordBoundary(TextPosition position) { TextRange getWordBoundary(TextPosition position) {
final child = childAtPosition(position); final child = childAtPosition(position);
final nodeOffset = child.getContainer().offset; final nodeOffset = child.getContainer().offset;
final childWord = child final childWord = child.getWordBoundary(TextPosition(offset: position.offset - nodeOffset));
.getWordBoundary(TextPosition(offset: position.offset - nodeOffset));
return TextRange( return TextRange(
start: childWord.start + nodeOffset, start: childWord.start + nodeOffset,
end: childWord.end + nodeOffset, end: childWord.end + nodeOffset,
@ -395,8 +359,7 @@ class RenderEditableTextBlock extends RenderEditableContainerBox
assert(position.offset < getContainer().length); assert(position.offset < getContainer().length);
final child = childAtPosition(position); final child = childAtPosition(position);
final childLocalPosition = final childLocalPosition = TextPosition(offset: position.offset - child.getContainer().offset);
TextPosition(offset: position.offset - child.getContainer().offset);
final result = child.getPositionAbove(childLocalPosition); final result = child.getPositionAbove(childLocalPosition);
if (result != null) { if (result != null) {
return TextPosition(offset: result.offset + child.getContainer().offset); return TextPosition(offset: result.offset + child.getContainer().offset);
@ -408,13 +371,10 @@ class RenderEditableTextBlock extends RenderEditableContainerBox
} }
final caretOffset = child.getOffsetForCaret(childLocalPosition); final caretOffset = child.getOffsetForCaret(childLocalPosition);
final testPosition = final testPosition = TextPosition(offset: sibling.getContainer().length - 1);
TextPosition(offset: sibling.getContainer().length - 1);
final testOffset = sibling.getOffsetForCaret(testPosition); final testOffset = sibling.getOffsetForCaret(testPosition);
final finalOffset = Offset(caretOffset.dx, testOffset.dy); final finalOffset = Offset(caretOffset.dx, testOffset.dy);
return TextPosition( return TextPosition(offset: sibling.getContainer().offset + sibling.getPositionForOffset(finalOffset).offset);
offset: sibling.getContainer().offset +
sibling.getPositionForOffset(finalOffset).offset);
} }
@override @override
@ -422,8 +382,7 @@ class RenderEditableTextBlock extends RenderEditableContainerBox
assert(position.offset < getContainer().length); assert(position.offset < getContainer().length);
final child = childAtPosition(position); final child = childAtPosition(position);
final childLocalPosition = final childLocalPosition = TextPosition(offset: position.offset - child.getContainer().offset);
TextPosition(offset: position.offset - child.getContainer().offset);
final result = child.getPositionBelow(childLocalPosition); final result = child.getPositionBelow(childLocalPosition);
if (result != null) { if (result != null) {
return TextPosition(offset: result.offset + child.getContainer().offset); return TextPosition(offset: result.offset + child.getContainer().offset);
@ -437,25 +396,20 @@ class RenderEditableTextBlock extends RenderEditableContainerBox
final caretOffset = child.getOffsetForCaret(childLocalPosition); final caretOffset = child.getOffsetForCaret(childLocalPosition);
final testOffset = sibling.getOffsetForCaret(const TextPosition(offset: 0)); final testOffset = sibling.getOffsetForCaret(const TextPosition(offset: 0));
final finalOffset = Offset(caretOffset.dx, testOffset.dy); final finalOffset = Offset(caretOffset.dx, testOffset.dy);
return TextPosition( return TextPosition(offset: sibling.getContainer().offset + sibling.getPositionForOffset(finalOffset).offset);
offset: sibling.getContainer().offset +
sibling.getPositionForOffset(finalOffset).offset);
} }
@override @override
double preferredLineHeight(TextPosition position) { double preferredLineHeight(TextPosition position) {
final child = childAtPosition(position); final child = childAtPosition(position);
return child.preferredLineHeight( return child.preferredLineHeight(TextPosition(offset: position.offset - child.getContainer().offset));
TextPosition(offset: position.offset - child.getContainer().offset));
} }
@override @override
TextSelectionPoint getBaseEndpointForSelection(TextSelection selection) { TextSelectionPoint getBaseEndpointForSelection(TextSelection selection) {
if (selection.isCollapsed) { if (selection.isCollapsed) {
return TextSelectionPoint( return TextSelectionPoint(
Offset(0, preferredLineHeight(selection.extent)) + Offset(0, preferredLineHeight(selection.extent)) + getOffsetForCaret(selection.extent), null);
getOffsetForCaret(selection.extent),
null);
} }
final baseNode = getContainer().queryChild(selection.start, false).node; final baseNode = getContainer().queryChild(selection.start, false).node;
@ -468,20 +422,15 @@ class RenderEditableTextBlock extends RenderEditableContainerBox
} }
assert(baseChild != null); assert(baseChild != null);
final basePoint = baseChild!.getBaseEndpointForSelection( final basePoint = baseChild!.getBaseEndpointForSelection(localSelection(baseChild.getContainer(), selection, true));
localSelection(baseChild.getContainer(), selection, true)); return TextSelectionPoint(basePoint.point + (baseChild.parentData as BoxParentData).offset, basePoint.direction);
return TextSelectionPoint(
basePoint.point + (baseChild.parentData as BoxParentData).offset,
basePoint.direction);
} }
@override @override
TextSelectionPoint getExtentEndpointForSelection(TextSelection selection) { TextSelectionPoint getExtentEndpointForSelection(TextSelection selection) {
if (selection.isCollapsed) { if (selection.isCollapsed) {
return TextSelectionPoint( return TextSelectionPoint(
Offset(0, preferredLineHeight(selection.extent)) + Offset(0, preferredLineHeight(selection.extent)) + getOffsetForCaret(selection.extent), null);
getOffsetForCaret(selection.extent),
null);
} }
final extentNode = getContainer().queryChild(selection.end, false).node; final extentNode = getContainer().queryChild(selection.end, false).node;
@ -495,11 +444,10 @@ class RenderEditableTextBlock extends RenderEditableContainerBox
} }
assert(extentChild != null); assert(extentChild != null);
final extentPoint = extentChild!.getExtentEndpointForSelection( final extentPoint =
localSelection(extentChild.getContainer(), selection, true)); extentChild!.getExtentEndpointForSelection(localSelection(extentChild.getContainer(), selection, true));
return TextSelectionPoint( return TextSelectionPoint(
extentPoint.point + (extentChild.parentData as BoxParentData).offset, extentPoint.point + (extentChild.parentData as BoxParentData).offset, extentPoint.direction);
extentPoint.direction);
} }
@override @override
@ -521,12 +469,10 @@ class RenderEditableTextBlock extends RenderEditableContainerBox
final decorationPadding = resolvedPadding! - _contentPadding; final decorationPadding = resolvedPadding! - _contentPadding;
final filledConfiguration = final filledConfiguration = configuration.copyWith(size: decorationPadding.deflateSize(size));
configuration.copyWith(size: decorationPadding.deflateSize(size));
final debugSaveCount = context.canvas.getSaveCount(); final debugSaveCount = context.canvas.getSaveCount();
final decorationOffset = final decorationOffset = offset.translate(decorationPadding.left, decorationPadding.top);
offset.translate(decorationPadding.left, decorationPadding.top);
_painter!.paint(context.canvas, decorationOffset, filledConfiguration); _painter!.paint(context.canvas, decorationOffset, filledConfiguration);
if (debugSaveCount != context.canvas.getSaveCount()) { if (debugSaveCount != context.canvas.getSaveCount()) {
throw '${_decoration.runtimeType} painter had mismatching save and ' throw '${_decoration.runtimeType} painter had mismatching save and '
@ -555,8 +501,7 @@ class RenderEditableTextBlock extends RenderEditableContainerBox
@override @override
TextPosition globalToLocalPosition(TextPosition position) { TextPosition globalToLocalPosition(TextPosition position) {
assert(getContainer().containsOffset(position.offset), assert(getContainer().containsOffset(position.offset), 'The provided text position is not in the current node');
'The provided text position is not in the current node');
return TextPosition( return TextPosition(
offset: position.offset - getContainer().documentOffset, offset: position.offset - getContainer().documentOffset,
affinity: position.affinity, affinity: position.affinity,
@ -575,14 +520,8 @@ class RenderEditableTextBlock extends RenderEditableContainerBox
} }
class _EditableBlock extends MultiChildRenderObjectWidget { class _EditableBlock extends MultiChildRenderObjectWidget {
_EditableBlock( _EditableBlock(this.block, this.textDirection, this.padding, this.scrollBottomInset, this.decoration,
this.block, this.contentPadding, List<Widget> children)
this.textDirection,
this.padding,
this.scrollBottomInset,
this.decoration,
this.contentPadding,
List<Widget> children)
: super(children: children); : super(children: children);
final Block block; final Block block;
@ -592,8 +531,7 @@ class _EditableBlock extends MultiChildRenderObjectWidget {
final Decoration decoration; final Decoration decoration;
final EdgeInsets? contentPadding; final EdgeInsets? contentPadding;
EdgeInsets get _padding => EdgeInsets get _padding => EdgeInsets.only(top: padding.item1, bottom: padding.item2);
EdgeInsets.only(top: padding.item1, bottom: padding.item2);
EdgeInsets get _contentPadding => contentPadding ?? EdgeInsets.zero; EdgeInsets get _contentPadding => contentPadding ?? EdgeInsets.zero;
@ -610,8 +548,7 @@ class _EditableBlock extends MultiChildRenderObjectWidget {
} }
@override @override
void updateRenderObject( void updateRenderObject(BuildContext context, covariant RenderEditableTextBlock renderObject) {
BuildContext context, covariant RenderEditableTextBlock renderObject) {
renderObject renderObject
..setContainer(block) ..setContainer(block)
..textDirection = textDirection ..textDirection = textDirection

Loading…
Cancel
Save