Merge pull request #142 from singerdmx/fix2

Add tap handles, scrollBottomInset, toolbar button fillColor as param, and fix replace length
pull/145/head
hyouuu 4 years ago committed by GitHub
commit 48d176d864
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
  1. 8
      lib/models/documents/document.dart
  2. 23
      lib/models/rules/insert.dart
  3. 91
      lib/widgets/editor.dart
  4. 8
      lib/widgets/raw_editor.dart
  5. 11
      lib/widgets/text_block.dart
  6. 1
      lib/widgets/text_selection.dart
  7. 24
      lib/widgets/toolbar.dart

@ -47,7 +47,7 @@ class Document {
Stream<Tuple3<Delta, Delta, ChangeSource>> get changes => _observer.stream; Stream<Tuple3<Delta, Delta, ChangeSource>> get changes => _observer.stream;
Delta insert(int index, Object? data) { Delta insert(int index, Object? data, {int replaceLength = 0}) {
assert(index >= 0); assert(index >= 0);
assert(data is String || data is Embeddable); assert(data is String || data is Embeddable);
if (data is Embeddable) { if (data is Embeddable) {
@ -56,7 +56,7 @@ class Document {
return Delta(); return Delta();
} }
final delta = _rules.apply(RuleType.INSERT, this, index, data: data); final delta = _rules.apply(RuleType.INSERT, this, index, data: data, len: replaceLength);
compose(delta, ChangeSource.LOCAL); compose(delta, ChangeSource.LOCAL);
return delta; return delta;
} }
@ -80,8 +80,10 @@ class Document {
var delta = Delta(); var delta = Delta();
// We have to insert before applying delete rules
// Otherwise delete would be operating on stale document snapshot.
if (dataIsNotEmpty) { if (dataIsNotEmpty) {
delta = insert(index + len, data); delta = insert(index, data, replaceLength: len);
} }
if (len > 0) { if (len > 0) {

@ -13,7 +13,6 @@ abstract class InsertRule extends Rule {
@override @override
void validateArgs(int? len, Object? data, Attribute? attribute) { void validateArgs(int? len, Object? data, Attribute? attribute) {
assert(len == null);
assert(data != null); assert(data != null);
assert(attribute == null); assert(attribute == null);
} }
@ -43,7 +42,7 @@ class PreserveLineStyleOnSplitRule extends InsertRule {
final text = after.data as String; final text = after.data as String;
final delta = Delta()..retain(index); final delta = Delta()..retain(index + (len ?? 0));
if (text.contains('\n')) { if (text.contains('\n')) {
assert(after.isPlain); assert(after.isPlain);
delta.insert('\n'); delta.insert('\n');
@ -86,7 +85,7 @@ class PreserveBlockStyleOnInsertRule extends InsertRule {
} }
final lines = data.split('\n'); final lines = data.split('\n');
final delta = Delta()..retain(index); final delta = Delta()..retain(index + (len ?? 0));
for (var i = 0; i < lines.length; i++) { for (var i = 0; i < lines.length; i++) {
final line = lines[i]; final line = lines[i];
if (line.isNotEmpty) { if (line.isNotEmpty) {
@ -157,7 +156,7 @@ class AutoExitBlockRule extends InsertRule {
.firstWhere((k) => Attribute.blockKeysExceptHeader.contains(k)); .firstWhere((k) => Attribute.blockKeysExceptHeader.contains(k));
attributes[k] = null; attributes[k] = null;
// retain(1) should be '\n', set it with no attribute // retain(1) should be '\n', set it with no attribute
return Delta()..retain(index)..retain(1, attributes); return Delta()..retain(index + (len ?? 0))..retain(1, attributes);
} }
} }
@ -183,7 +182,7 @@ class ResetLineFormatOnNewLineRule extends InsertRule {
resetStyle = Attribute.header.toJson(); resetStyle = Attribute.header.toJson();
} }
return Delta() return Delta()
..retain(index) ..retain(index + (len ?? 0))
..insert('\n', cur.attributes) ..insert('\n', cur.attributes)
..retain(1, resetStyle) ..retain(1, resetStyle)
..trim(); ..trim();
@ -200,7 +199,7 @@ class InsertEmbedsRule extends InsertRule {
return null; return null;
} }
final delta = Delta()..retain(index); final delta = Delta()..retain(index + (len ?? 0));
final itr = DeltaIterator(document); final itr = DeltaIterator(document);
final prev = itr.skip(index), cur = itr.next(); final prev = itr.skip(index), cur = itr.next();
@ -258,7 +257,7 @@ class ForceNewlineForInsertsAroundEmbedRule extends InsertRule {
if (!cursorBeforeEmbed && !cursorAfterEmbed) { if (!cursorBeforeEmbed && !cursorAfterEmbed) {
return null; return null;
} }
final delta = Delta()..retain(index); final delta = Delta()..retain(index + (len ?? 0));
if (cursorBeforeEmbed && !text.endsWith('\n')) { if (cursorBeforeEmbed && !text.endsWith('\n')) {
return delta..insert(text)..insert('\n'); return delta..insert(text)..insert('\n');
} }
@ -299,7 +298,7 @@ class AutoFormatLinksRule extends InsertRule {
attributes.addAll(LinkAttribute(link.toString()).toJson()); attributes.addAll(LinkAttribute(link.toString()).toJson());
return Delta() return Delta()
..retain(index - cand.length) ..retain(index + (len ?? 0) - cand.length)
..retain(cand.length, attributes) ..retain(cand.length, attributes)
..insert(data, prev.attributes); ..insert(data, prev.attributes);
} on FormatException { } on FormatException {
@ -330,13 +329,13 @@ class PreserveInlineStylesRule extends InsertRule {
final text = data; final text = data;
if (attributes == null || !attributes.containsKey(Attribute.link.key)) { if (attributes == null || !attributes.containsKey(Attribute.link.key)) {
return Delta() return Delta()
..retain(index) ..retain(index + (len ?? 0))
..insert(text, attributes); ..insert(text, attributes);
} }
attributes.remove(Attribute.link.key); attributes.remove(Attribute.link.key);
final delta = Delta() final delta = Delta()
..retain(index) ..retain(index + (len ?? 0))
..insert(text, attributes.isEmpty ? null : attributes); ..insert(text, attributes.isEmpty ? null : attributes);
final next = itr.next(); final next = itr.next();
@ -346,7 +345,7 @@ class PreserveInlineStylesRule extends InsertRule {
} }
if (attributes[Attribute.link.key] == nextAttributes[Attribute.link.key]) { if (attributes[Attribute.link.key] == nextAttributes[Attribute.link.key]) {
return Delta() return Delta()
..retain(index) ..retain(index + (len ?? 0))
..insert(text, attributes); ..insert(text, attributes);
} }
return delta; return delta;
@ -360,7 +359,7 @@ class CatchAllInsertRule extends InsertRule {
Delta applyRule(Delta document, int index, Delta applyRule(Delta document, int index,
{int? len, Object? data, Attribute? attribute}) { {int? len, Object? data, Attribute? attribute}) {
return Delta() return Delta()
..retain(index) ..retain(index + (len ?? 0))
..insert(data); ..insert(data);
} }
} }

@ -119,6 +119,7 @@ class QuillEditor extends StatefulWidget {
required this.focusNode, required this.focusNode,
required this.scrollController, required this.scrollController,
required this.scrollable, required this.scrollable,
required this.scrollBottomInset,
required this.padding, required this.padding,
required this.autoFocus, required this.autoFocus,
required this.readOnly, required this.readOnly,
@ -133,7 +134,12 @@ class QuillEditor extends StatefulWidget {
this.keyboardAppearance = Brightness.light, this.keyboardAppearance = Brightness.light,
this.scrollPhysics, this.scrollPhysics,
this.onLaunchUrl, this.onLaunchUrl,
this.embedBuilder = _defaultEmbedBuilder, this.onTapDown,
this.onTapUp,
this.onSingleLongTapStart,
this.onSingleLongTapMoveUpdate,
this.onSingleLongTapEnd,
this.embedBuilder = _defaultEmbedBuilder
}); });
factory QuillEditor.basic({ factory QuillEditor.basic({
@ -148,6 +154,7 @@ class QuillEditor extends StatefulWidget {
autoFocus: true, autoFocus: true,
readOnly: readOnly, readOnly: readOnly,
expands: false, expands: false,
scrollBottomInset: 0,
padding: EdgeInsets.zero); padding: EdgeInsets.zero);
} }
@ -155,6 +162,7 @@ class QuillEditor extends StatefulWidget {
final FocusNode focusNode; final FocusNode focusNode;
final ScrollController scrollController; final ScrollController scrollController;
final bool scrollable; final bool scrollable;
final double scrollBottomInset;
final EdgeInsetsGeometry padding; final EdgeInsetsGeometry padding;
final bool autoFocus; final bool autoFocus;
final bool? showCursor; final bool? showCursor;
@ -169,6 +177,16 @@ class QuillEditor extends StatefulWidget {
final Brightness keyboardAppearance; final Brightness keyboardAppearance;
final ScrollPhysics? scrollPhysics; final ScrollPhysics? scrollPhysics;
final ValueChanged<String>? onLaunchUrl; final ValueChanged<String>? onLaunchUrl;
// Returns whether gesture is handled
final bool Function(TapDownDetails details, TextPosition textPosition)? onTapDown;
// Returns whether gesture is handled
final bool Function(TapUpDetails details, TextPosition textPosition)? onTapUp;
// Returns whether gesture is handled
final bool Function(LongPressStartDetails details, TextPosition textPosition)? onSingleLongTapStart;
// Returns whether gesture is handled
final bool Function(LongPressMoveUpdateDetails details, TextPosition textPosition)? onSingleLongTapMoveUpdate;
// Returns whether gesture is handled
final bool Function(LongPressEndDetails details, TextPosition textPosition)? onSingleLongTapEnd;
final EmbedBuilder embedBuilder; final EmbedBuilder embedBuilder;
@override @override
@ -239,6 +257,7 @@ class _QuillEditorState extends State<QuillEditor>
widget.focusNode, widget.focusNode,
widget.scrollController, widget.scrollController,
widget.scrollable, widget.scrollable,
widget.scrollBottomInset,
widget.padding, widget.padding,
widget.readOnly, widget.readOnly,
widget.placeholder, widget.placeholder,
@ -315,6 +334,15 @@ class _QuillEditorSelectionGestureDetectorBuilder
@override @override
void onSingleLongTapMoveUpdate(LongPressMoveUpdateDetails details) { void onSingleLongTapMoveUpdate(LongPressMoveUpdateDetails details) {
if (_state.widget.onSingleLongTapMoveUpdate != null) {
final renderEditor = getRenderEditor();
if (renderEditor != null) {
if (_state.widget.onSingleLongTapMoveUpdate!(details, renderEditor.getPositionForOffset(details.globalPosition)
)) {
return;
}
}
}
if (!delegate.getSelectionEnabled()) { if (!delegate.getSelectionEnabled()) {
return; return;
} }
@ -434,8 +462,30 @@ class _QuillEditorSelectionGestureDetectorBuilder
await launch(url); await launch(url);
} }
@override
void onTapDown(TapDownDetails details) {
if (_state.widget.onTapDown != null) {
final renderEditor = getRenderEditor();
if (renderEditor != null) {
if (_state.widget.onTapDown!(details, renderEditor.getPositionForOffset(details.globalPosition))) {
return;
}
}
}
super.onTapDown(details);
}
@override @override
void onSingleTapUp(TapUpDetails details) { void onSingleTapUp(TapUpDetails details) {
if (_state.widget.onTapUp != null) {
final renderEditor = getRenderEditor();
if (renderEditor != null) {
if (_state.widget.onTapUp!(details, renderEditor.getPositionForOffset(details.globalPosition))) {
return;
}
}
}
getEditor()!.hideToolbar(); getEditor()!.hideToolbar();
final positionSelected = _onTapping(details); final positionSelected = _onTapping(details);
@ -469,6 +519,15 @@ class _QuillEditorSelectionGestureDetectorBuilder
@override @override
void onSingleLongTapStart(LongPressStartDetails details) { void onSingleLongTapStart(LongPressStartDetails details) {
if (_state.widget.onSingleLongTapStart != null) {
final renderEditor = getRenderEditor();
if (renderEditor != null) {
if (_state.widget.onSingleLongTapStart!(details, renderEditor.getPositionForOffset(details.globalPosition))) {
return;
}
}
}
if (delegate.getSelectionEnabled()) { if (delegate.getSelectionEnabled()) {
switch (Theme.of(_state.context).platform) { switch (Theme.of(_state.context).platform) {
case TargetPlatform.iOS: case TargetPlatform.iOS:
@ -491,6 +550,19 @@ class _QuillEditorSelectionGestureDetectorBuilder
} }
} }
} }
@override
void onSingleLongTapEnd(LongPressEndDetails details) {
if (_state.widget.onSingleLongTapEnd != null) {
final renderEditor = getRenderEditor();
if (renderEditor != null) {
if (_state.widget.onSingleLongTapEnd!(details, renderEditor.getPositionForOffset(details.globalPosition))) {
return;
}
}
}
super.onSingleLongTapEnd(details);
}
} }
typedef TextSelectionChangedHandler = void Function( typedef TextSelectionChangedHandler = void Function(
@ -501,6 +573,7 @@ class RenderEditor extends RenderEditableContainerBox
RenderEditor( RenderEditor(
List<RenderEditableBox>? children, List<RenderEditableBox>? children,
TextDirection textDirection, TextDirection textDirection,
double scrollBottomInset,
EdgeInsetsGeometry padding, EdgeInsetsGeometry padding,
this.document, this.document,
this.selection, this.selection,
@ -513,6 +586,7 @@ class RenderEditor extends RenderEditableContainerBox
children, children,
document.root, document.root,
textDirection, textDirection,
scrollBottomInset,
padding, padding,
); );
@ -571,6 +645,14 @@ class RenderEditor extends RenderEditableContainerBox
markNeedsPaint(); markNeedsPaint();
} }
void setScrollBottomInset(double value) {
if (scrollBottomInset == value) {
return;
}
scrollBottomInset = value;
markNeedsPaint();
}
@override @override
List<TextSelectionPoint> getEndpointsForSelection( List<TextSelectionPoint> getEndpointsForSelection(
TextSelection textSelection) { TextSelection textSelection) {
@ -843,8 +925,9 @@ class RenderEditor extends RenderEditableContainerBox
child.preferredLineHeight(TextPosition( child.preferredLineHeight(TextPosition(
offset: selection.extentOffset - child.getContainer().offset)) - offset: selection.extentOffset - child.getContainer().offset)) -
kMargin + kMargin +
offsetInViewport; offsetInViewport +
final caretBottom = endpoint.point.dy + kMargin + offsetInViewport; scrollBottomInset;
final caretBottom = endpoint.point.dy + kMargin + offsetInViewport + scrollBottomInset;
double? dy; double? dy;
if (caretTop < scrollOffset) { if (caretTop < scrollOffset) {
dy = caretTop; dy = caretTop;
@ -871,6 +954,7 @@ class RenderEditableContainerBox extends RenderBox
List<RenderEditableBox>? children, List<RenderEditableBox>? children,
this._container, this._container,
this.textDirection, this.textDirection,
this.scrollBottomInset,
this._padding, this._padding,
) : assert(_padding.isNonNegative) { ) : assert(_padding.isNonNegative) {
addAll(children); addAll(children);
@ -879,6 +963,7 @@ class RenderEditableContainerBox extends RenderBox
container_node.Container _container; container_node.Container _container;
TextDirection textDirection; TextDirection textDirection;
EdgeInsetsGeometry _padding; EdgeInsetsGeometry _padding;
double scrollBottomInset;
EdgeInsets? _resolvedPadding; EdgeInsets? _resolvedPadding;
container_node.Container getContainer() { container_node.Container getContainer() {

@ -34,6 +34,7 @@ class RawEditor extends StatefulWidget {
this.focusNode, this.focusNode,
this.scrollController, this.scrollController,
this.scrollable, this.scrollable,
this.scrollBottomInset,
this.padding, this.padding,
this.readOnly, this.readOnly,
this.placeholder, this.placeholder,
@ -65,6 +66,7 @@ class RawEditor extends StatefulWidget {
final FocusNode focusNode; final FocusNode focusNode;
final ScrollController scrollController; final ScrollController scrollController;
final bool scrollable; final bool scrollable;
final double scrollBottomInset;
final EdgeInsetsGeometry padding; final EdgeInsetsGeometry padding;
final bool readOnly; final bool readOnly;
final String? placeholder; final String? placeholder;
@ -527,6 +529,7 @@ class RawEditorState extends EditorState
startHandleLayerLink: _startHandleLayerLink, startHandleLayerLink: _startHandleLayerLink,
endHandleLayerLink: _endHandleLayerLink, endHandleLayerLink: _endHandleLayerLink,
onSelectionChanged: _handleSelectionChanged, onSelectionChanged: _handleSelectionChanged,
scrollBottomInset: widget.scrollBottomInset,
padding: widget.padding, padding: widget.padding,
children: _buildChildren(_doc, context), children: _buildChildren(_doc, context),
), ),
@ -588,6 +591,7 @@ class RawEditorState extends EditorState
final editableTextBlock = EditableTextBlock( final editableTextBlock = EditableTextBlock(
node, node,
_textDirection, _textDirection,
widget.scrollBottomInset,
_getVerticalSpacingForBlock(node, _styles), _getVerticalSpacingForBlock(node, _styles),
widget.controller.selection, widget.controller.selection,
widget.selectionColor, widget.selectionColor,
@ -1137,6 +1141,7 @@ class _Editor extends MultiChildRenderObjectWidget {
required this.startHandleLayerLink, required this.startHandleLayerLink,
required this.endHandleLayerLink, required this.endHandleLayerLink,
required this.onSelectionChanged, required this.onSelectionChanged,
required this.scrollBottomInset,
this.padding = EdgeInsets.zero, this.padding = EdgeInsets.zero,
}) : super(key: key, children: children); }) : super(key: key, children: children);
@ -1147,6 +1152,7 @@ class _Editor extends MultiChildRenderObjectWidget {
final LayerLink startHandleLayerLink; final LayerLink startHandleLayerLink;
final LayerLink endHandleLayerLink; final LayerLink endHandleLayerLink;
final TextSelectionChangedHandler onSelectionChanged; final TextSelectionChangedHandler onSelectionChanged;
final double scrollBottomInset;
final EdgeInsetsGeometry padding; final EdgeInsetsGeometry padding;
@override @override
@ -1154,6 +1160,7 @@ class _Editor extends MultiChildRenderObjectWidget {
return RenderEditor( return RenderEditor(
null, null,
textDirection, textDirection,
scrollBottomInset,
padding, padding,
document, document,
selection, selection,
@ -1177,6 +1184,7 @@ class _Editor extends MultiChildRenderObjectWidget {
..setStartHandleLayerLink(startHandleLayerLink) ..setStartHandleLayerLink(startHandleLayerLink)
..setEndHandleLayerLink(endHandleLayerLink) ..setEndHandleLayerLink(endHandleLayerLink)
..onSelectionChanged = onSelectionChanged ..onSelectionChanged = onSelectionChanged
..setScrollBottomInset(scrollBottomInset)
..setPadding(padding); ..setPadding(padding);
} }
} }

@ -50,6 +50,7 @@ class EditableTextBlock extends StatelessWidget {
const EditableTextBlock( const EditableTextBlock(
this.block, this.block,
this.textDirection, this.textDirection,
this.scrollBottomInset,
this.verticalSpacing, this.verticalSpacing,
this.textSelection, this.textSelection,
this.color, this.color,
@ -64,6 +65,7 @@ class EditableTextBlock extends StatelessWidget {
final Block block; final Block block;
final TextDirection textDirection; final TextDirection textDirection;
final double scrollBottomInset;
final Tuple2 verticalSpacing; final Tuple2 verticalSpacing;
final TextSelection textSelection; final TextSelection textSelection;
final Color color; final Color color;
@ -84,6 +86,7 @@ class EditableTextBlock extends StatelessWidget {
block, block,
textDirection, textDirection,
verticalSpacing as Tuple2<double, double>, verticalSpacing as Tuple2<double, double>,
scrollBottomInset,
_getDecorationForBlock(block, defaultStyles) ?? const BoxDecoration(), _getDecorationForBlock(block, defaultStyles) ?? const BoxDecoration(),
contentPadding, contentPadding,
_buildChildren(context, indentLevelCounts)); _buildChildren(context, indentLevelCounts));
@ -256,6 +259,7 @@ class RenderEditableTextBlock extends RenderEditableContainerBox
required Block block, required Block block,
required TextDirection textDirection, required TextDirection textDirection,
required EdgeInsetsGeometry padding, required EdgeInsetsGeometry padding,
required double scrollBottomInset,
required Decoration decoration, required Decoration decoration,
List<RenderEditableBox>? children, List<RenderEditableBox>? children,
ImageConfiguration configuration = ImageConfiguration.empty, ImageConfiguration configuration = ImageConfiguration.empty,
@ -268,6 +272,7 @@ class RenderEditableTextBlock extends RenderEditableContainerBox
children, children,
block, block,
textDirection, textDirection,
scrollBottomInset,
padding.add(contentPadding), padding.add(contentPadding),
); );
@ -512,14 +517,16 @@ class _EditableBlock extends MultiChildRenderObjectWidget {
this.block, this.block,
this.textDirection, this.textDirection,
this.padding, this.padding,
this.scrollBottomInset,
this.decoration, this.decoration,
this.contentPadding, this.contentPadding,
List<Widget> children, List<Widget> children
) : super(children: children); ) : super(children: children);
final Block block; final Block block;
final TextDirection textDirection; final TextDirection textDirection;
final Tuple2<double, double> padding; final Tuple2<double, double> padding;
final double scrollBottomInset;
final Decoration decoration; final Decoration decoration;
final EdgeInsets? contentPadding; final EdgeInsets? contentPadding;
@ -534,6 +541,7 @@ class _EditableBlock extends MultiChildRenderObjectWidget {
block: block, block: block,
textDirection: textDirection, textDirection: textDirection,
padding: _padding, padding: _padding,
scrollBottomInset: scrollBottomInset,
decoration: decoration, decoration: decoration,
contentPadding: _contentPadding, contentPadding: _contentPadding,
); );
@ -545,6 +553,7 @@ class _EditableBlock extends MultiChildRenderObjectWidget {
renderObject renderObject
..setContainer(block) ..setContainer(block)
..textDirection = textDirection ..textDirection = textDirection
..scrollBottomInset = scrollBottomInset
..setPadding(_padding) ..setPadding(_padding)
..decoration = decoration ..decoration = decoration
..contentPadding = _contentPadding; ..contentPadding = _contentPadding;

@ -533,6 +533,7 @@ class _EditorTextSelectionGestureDetectorState
} }
void _handleTapDown(TapDownDetails details) { void _handleTapDown(TapDownDetails details) {
// renderObject.resetTapDownStatus();
if (widget.onTapDown != null) { if (widget.onTapDown != null) {
widget.onTapDown!(details); widget.onTapDown!(details);
} }

@ -24,11 +24,13 @@ class InsertEmbedButton extends StatelessWidget {
const InsertEmbedButton({ const InsertEmbedButton({
required this.controller, required this.controller,
required this.icon, required this.icon,
this.fillColor,
Key? key, Key? key,
}) : super(key: key); }) : super(key: key);
final QuillController controller; final QuillController controller;
final IconData icon; final IconData icon;
final Color? fillColor;
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
@ -41,7 +43,7 @@ class InsertEmbedButton extends StatelessWidget {
size: iconSize, size: iconSize,
color: Theme.of(context).iconTheme.color, color: Theme.of(context).iconTheme.color,
), ),
fillColor: Theme.of(context).canvasColor, fillColor: fillColor ?? Theme.of(context).canvasColor,
onPressed: () { onPressed: () {
final index = controller.selection.baseOffset; final index = controller.selection.baseOffset;
final length = controller.selection.extentOffset - index; final length = controller.selection.extentOffset - index;
@ -169,6 +171,7 @@ typedef ToggleStyleButtonBuilder = Widget Function(
BuildContext context, BuildContext context,
Attribute attribute, Attribute attribute,
IconData icon, IconData icon,
Color? fillColor,
bool? isToggled, bool? isToggled,
VoidCallback? onPressed, VoidCallback? onPressed,
); );
@ -178,6 +181,7 @@ class ToggleStyleButton extends StatefulWidget {
required this.attribute, required this.attribute,
required this.icon, required this.icon,
required this.controller, required this.controller,
this.fillColor,
this.childBuilder = defaultToggleStyleButtonBuilder, this.childBuilder = defaultToggleStyleButtonBuilder,
Key? key, Key? key,
}) : super(key: key); }) : super(key: key);
@ -186,6 +190,8 @@ class ToggleStyleButton extends StatefulWidget {
final IconData icon; final IconData icon;
final Color? fillColor;
final QuillController controller; final QuillController controller;
final ToggleStyleButtonBuilder childBuilder; final ToggleStyleButtonBuilder childBuilder;
@ -246,8 +252,7 @@ class _ToggleStyleButtonState extends State<ToggleStyleButton> {
_selectionStyle.attributes.containsKey(Attribute.codeBlock.key); _selectionStyle.attributes.containsKey(Attribute.codeBlock.key);
final isEnabled = final isEnabled =
!isInCodeBlock || widget.attribute.key == Attribute.codeBlock.key; !isInCodeBlock || widget.attribute.key == Attribute.codeBlock.key;
return widget.childBuilder(context, widget.attribute, widget.icon, return widget.childBuilder(context, widget.attribute, widget.icon, widget.fillColor, _isToggled, isEnabled ? _toggleAttribute : null);
_isToggled, isEnabled ? _toggleAttribute : null);
} }
void _toggleAttribute() { void _toggleAttribute() {
@ -262,12 +267,15 @@ class ToggleCheckListButton extends StatefulWidget {
required this.icon, required this.icon,
required this.controller, required this.controller,
required this.attribute, required this.attribute,
this.fillColor,
this.childBuilder = defaultToggleStyleButtonBuilder, this.childBuilder = defaultToggleStyleButtonBuilder,
Key? key, Key? key,
}) : super(key: key); }) : super(key: key);
final IconData icon; final IconData icon;
final Color? fillColor;
final QuillController controller; final QuillController controller;
final ToggleStyleButtonBuilder childBuilder; final ToggleStyleButtonBuilder childBuilder;
@ -331,8 +339,7 @@ class _ToggleCheckListButtonState extends State<ToggleCheckListButton> {
_selectionStyle.attributes.containsKey(Attribute.codeBlock.key); _selectionStyle.attributes.containsKey(Attribute.codeBlock.key);
final isEnabled = final isEnabled =
!isInCodeBlock || Attribute.list.key == Attribute.codeBlock.key; !isInCodeBlock || Attribute.list.key == Attribute.codeBlock.key;
return widget.childBuilder(context, Attribute.unchecked, widget.icon, return widget.childBuilder(context, Attribute.unchecked, widget.icon, widget.fillColor, _isToggled, isEnabled ? _toggleAttribute : null);
_isToggled, isEnabled ? _toggleAttribute : null);
} }
void _toggleAttribute() { void _toggleAttribute() {
@ -346,6 +353,7 @@ Widget defaultToggleStyleButtonBuilder(
BuildContext context, BuildContext context,
Attribute attribute, Attribute attribute,
IconData icon, IconData icon,
Color? fillColor,
bool? isToggled, bool? isToggled,
VoidCallback? onPressed, VoidCallback? onPressed,
) { ) {
@ -356,14 +364,14 @@ Widget defaultToggleStyleButtonBuilder(
? theme.primaryIconTheme.color ? theme.primaryIconTheme.color
: theme.iconTheme.color : theme.iconTheme.color
: theme.disabledColor; : theme.disabledColor;
final fillColor = final fill =
isToggled == true ? theme.toggleableActiveColor : theme.canvasColor; isToggled == true ? theme.toggleableActiveColor : fillColor ?? theme.canvasColor;
return QuillIconButton( return QuillIconButton(
highlightElevation: 0, highlightElevation: 0,
hoverElevation: 0, hoverElevation: 0,
size: iconSize * 1.77, size: iconSize * 1.77,
icon: Icon(icon, size: iconSize, color: iconColor), icon: Icon(icon, size: iconSize, color: iconColor),
fillColor: fillColor, fillColor: fill,
onPressed: onPressed, onPressed: onPressed,
); );
} }

Loading…
Cancel
Save