Format code

pull/162/head
Xin Yao 4 years ago
parent bc5eb86a8f
commit df602cfa9b
  1. 2
      lib/models/documents/nodes/line.dart
  2. 8
      lib/models/documents/style.dart
  3. 9
      lib/widgets/controller.dart
  4. 32
      lib/widgets/editor.dart
  5. 6
      lib/widgets/raw_editor.dart
  6. 377
      lib/widgets/toolbar.dart

@ -197,7 +197,7 @@ class Line extends Container<Leaf?> {
} }
applyStyle(newStyle); applyStyle(newStyle);
final blockStyle = newStyle.getNotNullValueBlockExceptHeader(); final blockStyle = newStyle.getBlockExceptHeader();
if (blockStyle == null) { if (blockStyle == null) {
return; return;
} // No block-level changes } // No block-level changes

@ -49,16 +49,12 @@ class Style {
Attribute? getBlockExceptHeader() { Attribute? getBlockExceptHeader() {
for (final val in values) { for (final val in values) {
if (val.isBlockExceptHeader) { if (val.isBlockExceptHeader && val.value != null) {
return val; return val;
} }
} }
return null;
}
Attribute? getNotNullValueBlockExceptHeader() {
for (final val in values) { for (final val in values) {
if (val.isBlockExceptHeader && val.value != null) { if (val.isBlockExceptHeader) {
return val; return val;
} }
} }

@ -11,7 +11,11 @@ import '../models/quill_delta.dart';
import '../utils/diff_delta.dart'; import '../utils/diff_delta.dart';
class QuillController extends ChangeNotifier { class QuillController extends ChangeNotifier {
QuillController({required this.document, required this.selection, this.iconSize = 18, this.toolbarHeightFactor = 2}); QuillController(
{required this.document,
required this.selection,
this.iconSize = 18,
this.toolbarHeightFactor = 2});
factory QuillController.basic() { factory QuillController.basic() {
return QuillController( return QuillController(
@ -80,7 +84,8 @@ class QuillController extends ChangeNotifier {
bool get hasRedo => document.hasRedo; bool get hasRedo => document.hasRedo;
void replaceText( void replaceText(
int index, int len, Object? data, TextSelection? textSelection, {bool ignoreFocus = false}) { int index, int len, Object? data, TextSelection? textSelection,
{bool ignoreFocus = false}) {
assert(data is String || data is Embeddable); assert(data is String || data is Embeddable);
Delta? delta; Delta? delta;

@ -176,18 +176,25 @@ class QuillEditor extends StatefulWidget {
final ScrollPhysics? scrollPhysics; final ScrollPhysics? scrollPhysics;
final ValueChanged<String>? onLaunchUrl; final ValueChanged<String>? onLaunchUrl;
// Returns whether gesture is handled // Returns whether gesture is handled
final bool Function(TapDownDetails details, TextPosition Function(Offset offset))? onTapDown; final bool Function(
TapDownDetails details, TextPosition Function(Offset offset))? onTapDown;
// Returns whether gesture is handled // Returns whether gesture is handled
final bool Function(TapUpDetails details, TextPosition Function(Offset offset))? onTapUp; final bool Function(
TapUpDetails details, TextPosition Function(Offset offset))? onTapUp;
// Returns whether gesture is handled // Returns whether gesture is handled
final bool Function(LongPressStartDetails details, TextPosition Function(Offset offset))? onSingleLongTapStart; final bool Function(
LongPressStartDetails details, TextPosition Function(Offset offset))?
onSingleLongTapStart;
// Returns whether gesture is handled // Returns whether gesture is handled
final bool Function(LongPressMoveUpdateDetails details, TextPosition Function(Offset offset))? onSingleLongTapMoveUpdate; final bool Function(LongPressMoveUpdateDetails details,
TextPosition Function(Offset offset))? onSingleLongTapMoveUpdate;
// Returns whether gesture is handled // Returns whether gesture is handled
final bool Function(LongPressEndDetails details, TextPosition Function(Offset offset))? onSingleLongTapEnd; final bool Function(
LongPressEndDetails details, TextPosition Function(Offset offset))?
onSingleLongTapEnd;
final EmbedBuilder embedBuilder; final EmbedBuilder embedBuilder;
@ -339,7 +346,8 @@ class _QuillEditorSelectionGestureDetectorBuilder
if (_state.widget.onSingleLongTapMoveUpdate != null) { if (_state.widget.onSingleLongTapMoveUpdate != null) {
final renderEditor = getRenderEditor(); final renderEditor = getRenderEditor();
if (renderEditor != null) { if (renderEditor != null) {
if (_state.widget.onSingleLongTapMoveUpdate!(details, renderEditor.getPositionForOffset)) { if (_state.widget.onSingleLongTapMoveUpdate!(
details, renderEditor.getPositionForOffset)) {
return; return;
} }
} }
@ -468,7 +476,8 @@ class _QuillEditorSelectionGestureDetectorBuilder
if (_state.widget.onTapDown != null) { if (_state.widget.onTapDown != null) {
final renderEditor = getRenderEditor(); final renderEditor = getRenderEditor();
if (renderEditor != null) { if (renderEditor != null) {
if (_state.widget.onTapDown!(details, renderEditor.getPositionForOffset)) { if (_state.widget.onTapDown!(
details, renderEditor.getPositionForOffset)) {
return; return;
} }
} }
@ -481,7 +490,8 @@ class _QuillEditorSelectionGestureDetectorBuilder
if (_state.widget.onTapUp != null) { if (_state.widget.onTapUp != null) {
final renderEditor = getRenderEditor(); final renderEditor = getRenderEditor();
if (renderEditor != null) { if (renderEditor != null) {
if (_state.widget.onTapUp!(details, renderEditor.getPositionForOffset)) { if (_state.widget.onTapUp!(
details, renderEditor.getPositionForOffset)) {
return; return;
} }
} }
@ -523,7 +533,8 @@ class _QuillEditorSelectionGestureDetectorBuilder
if (_state.widget.onSingleLongTapStart != null) { if (_state.widget.onSingleLongTapStart != null) {
final renderEditor = getRenderEditor(); final renderEditor = getRenderEditor();
if (renderEditor != null) { if (renderEditor != null) {
if (_state.widget.onSingleLongTapStart!(details, renderEditor.getPositionForOffset)) { if (_state.widget.onSingleLongTapStart!(
details, renderEditor.getPositionForOffset)) {
return; return;
} }
} }
@ -557,7 +568,8 @@ class _QuillEditorSelectionGestureDetectorBuilder
if (_state.widget.onSingleLongTapEnd != null) { if (_state.widget.onSingleLongTapEnd != null) {
final renderEditor = getRenderEditor(); final renderEditor = getRenderEditor();
if (renderEditor != null) { if (renderEditor != null) {
if (_state.widget.onSingleLongTapEnd!(details, renderEditor.getPositionForOffset)) { if (_state.widget.onSingleLongTapEnd!(
details, renderEditor.getPositionForOffset)) {
return; return;
} }
} }

@ -913,14 +913,16 @@ class RawEditorState extends EditorState
return; return;
} }
_showCaretOnScreen(); _showCaretOnScreen();
_cursorCont.startOrStopCursorTimerIfNeeded(_hasFocus, widget.controller.selection); _cursorCont.startOrStopCursorTimerIfNeeded(
_hasFocus, widget.controller.selection);
if (hasConnection) { if (hasConnection) {
_cursorCont _cursorCont
..stopCursorTimer(resetCharTicks: false) ..stopCursorTimer(resetCharTicks: false)
..startCursorTimer(); ..startCursorTimer();
} }
SchedulerBinding.instance!.addPostFrameCallback((_) => _updateOrDisposeSelectionOverlayIfNeeded()); SchedulerBinding.instance!.addPostFrameCallback(
(_) => _updateOrDisposeSelectionOverlayIfNeeded());
if (mounted) { if (mounted) {
setState(() { setState(() {
// Use widget.controller.value in build() // Use widget.controller.value in build()

@ -432,7 +432,8 @@ class _SelectHeaderStyleButtonState extends State<SelectHeaderStyleButton> {
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
return _selectHeadingStyleButtonBuilder(context, _value, _selectAttribute, widget.controller.iconSize); return _selectHeadingStyleButtonBuilder(
context, _value, _selectAttribute, widget.controller.iconSize);
} }
} }
@ -774,7 +775,8 @@ class _HistoryButtonState extends State<HistoryButton> {
highlightElevation: 0, highlightElevation: 0,
hoverElevation: 0, hoverElevation: 0,
size: widget.controller.iconSize * 1.77, size: widget.controller.iconSize * 1.77,
icon: Icon(widget.icon, size: widget.controller.iconSize, color: _iconColor), icon: Icon(widget.icon,
size: widget.controller.iconSize, color: _iconColor),
fillColor: fillColor, fillColor: fillColor,
onPressed: _changeHistory, onPressed: _changeHistory,
); );
@ -839,7 +841,8 @@ class _IndentButtonState extends State<IndentButton> {
highlightElevation: 0, highlightElevation: 0,
hoverElevation: 0, hoverElevation: 0,
size: widget.controller.iconSize * 1.77, size: widget.controller.iconSize * 1.77,
icon: Icon(widget.icon, size: widget.controller.iconSize, color: iconColor), icon:
Icon(widget.icon, size: widget.controller.iconSize, color: iconColor),
fillColor: fillColor, fillColor: fillColor,
onPressed: () { onPressed: () {
final indent = widget.controller final indent = widget.controller
@ -893,7 +896,8 @@ class _ClearFormatButtonState extends State<ClearFormatButton> {
highlightElevation: 0, highlightElevation: 0,
hoverElevation: 0, hoverElevation: 0,
size: widget.controller.iconSize * 1.77, size: widget.controller.iconSize * 1.77,
icon: Icon(widget.icon, size: widget.controller.iconSize, color: iconColor), icon: Icon(widget.icon,
size: widget.controller.iconSize, color: iconColor),
fillColor: fillColor, fillColor: fillColor,
onPressed: () { onPressed: () {
for (final k for (final k
@ -905,7 +909,9 @@ class _ClearFormatButtonState extends State<ClearFormatButton> {
} }
class QuillToolbar extends StatefulWidget implements PreferredSizeWidget { class QuillToolbar extends StatefulWidget implements PreferredSizeWidget {
const QuillToolbar({required this.children, this.toolBarHeight = 36, Key? key}) : super(key: key); const QuillToolbar(
{required this.children, this.toolBarHeight = 36, Key? key})
: super(key: key);
factory QuillToolbar.basic({ factory QuillToolbar.basic({
required QuillController controller, required QuillController controller,
@ -932,178 +938,195 @@ class QuillToolbar extends StatefulWidget implements PreferredSizeWidget {
}) { }) {
controller.iconSize = toolbarIconSize; controller.iconSize = toolbarIconSize;
return QuillToolbar(key: key, toolBarHeight: toolbarIconSize * controller.toolbarHeightFactor, children: [ return QuillToolbar(
Visibility( key: key,
visible: showHistory, toolBarHeight: toolbarIconSize * controller.toolbarHeightFactor,
child: HistoryButton( children: [
icon: Icons.undo_outlined, Visibility(
controller: controller, visible: showHistory,
undo: true, child: HistoryButton(
), icon: Icons.undo_outlined,
), controller: controller,
Visibility( undo: true,
visible: showHistory, ),
child: HistoryButton( ),
icon: Icons.redo_outlined, Visibility(
controller: controller, visible: showHistory,
undo: false, child: HistoryButton(
), icon: Icons.redo_outlined,
), controller: controller,
const SizedBox(width: 0.6), undo: false,
Visibility( ),
visible: showBoldButton, ),
child: ToggleStyleButton( const SizedBox(width: 0.6),
attribute: Attribute.bold, Visibility(
icon: Icons.format_bold, visible: showBoldButton,
controller: controller, child: ToggleStyleButton(
), attribute: Attribute.bold,
), icon: Icons.format_bold,
const SizedBox(width: 0.6), controller: controller,
Visibility( ),
visible: showItalicButton, ),
child: ToggleStyleButton( const SizedBox(width: 0.6),
attribute: Attribute.italic, Visibility(
icon: Icons.format_italic, visible: showItalicButton,
controller: controller, child: ToggleStyleButton(
), attribute: Attribute.italic,
), icon: Icons.format_italic,
const SizedBox(width: 0.6), controller: controller,
Visibility( ),
visible: showUnderLineButton, ),
child: ToggleStyleButton( const SizedBox(width: 0.6),
attribute: Attribute.underline, Visibility(
icon: Icons.format_underline, visible: showUnderLineButton,
controller: controller, child: ToggleStyleButton(
), attribute: Attribute.underline,
), icon: Icons.format_underline,
const SizedBox(width: 0.6), controller: controller,
Visibility( ),
visible: showStrikeThrough, ),
child: ToggleStyleButton( const SizedBox(width: 0.6),
attribute: Attribute.strikeThrough, Visibility(
icon: Icons.format_strikethrough, visible: showStrikeThrough,
controller: controller, child: ToggleStyleButton(
), attribute: Attribute.strikeThrough,
), icon: Icons.format_strikethrough,
const SizedBox(width: 0.6), controller: controller,
Visibility( ),
visible: showColorButton, ),
child: ColorButton( const SizedBox(width: 0.6),
icon: Icons.color_lens, Visibility(
controller: controller, visible: showColorButton,
background: false, child: ColorButton(
), icon: Icons.color_lens,
), controller: controller,
const SizedBox(width: 0.6), background: false,
Visibility( ),
visible: showBackgroundColorButton, ),
child: ColorButton( const SizedBox(width: 0.6),
icon: Icons.format_color_fill, Visibility(
controller: controller, visible: showBackgroundColorButton,
background: true, child: ColorButton(
), icon: Icons.format_color_fill,
), controller: controller,
const SizedBox(width: 0.6), background: true,
Visibility( ),
visible: showClearFormat, ),
child: ClearFormatButton( const SizedBox(width: 0.6),
icon: Icons.format_clear, Visibility(
controller: controller, visible: showClearFormat,
), child: ClearFormatButton(
), icon: Icons.format_clear,
const SizedBox(width: 0.6), controller: controller,
Visibility( ),
visible: onImagePickCallback != null, ),
child: ImageButton( const SizedBox(width: 0.6),
icon: Icons.image, Visibility(
controller: controller, visible: onImagePickCallback != null,
imageSource: ImageSource.gallery, child: ImageButton(
onImagePickCallback: onImagePickCallback, icon: Icons.image,
), controller: controller,
), imageSource: ImageSource.gallery,
const SizedBox(width: 0.6), onImagePickCallback: onImagePickCallback,
Visibility( ),
visible: onImagePickCallback != null, ),
child: ImageButton( const SizedBox(width: 0.6),
icon: Icons.photo_camera, Visibility(
controller: controller, visible: onImagePickCallback != null,
imageSource: ImageSource.camera, child: ImageButton(
onImagePickCallback: onImagePickCallback, icon: Icons.photo_camera,
), controller: controller,
), imageSource: ImageSource.camera,
Visibility( onImagePickCallback: onImagePickCallback,
visible: showHeaderStyle, child: VerticalDivider(indent: 12, endIndent: 12, color: Colors.grey.shade400)), ),
Visibility(visible: showHeaderStyle, child: SelectHeaderStyleButton(controller: controller)), ),
VerticalDivider(indent: 12, endIndent: 12, color: Colors.grey.shade400), Visibility(
Visibility( visible: showHeaderStyle,
visible: showListNumbers, child: VerticalDivider(
child: ToggleStyleButton( indent: 12, endIndent: 12, color: Colors.grey.shade400)),
attribute: Attribute.ol, Visibility(
controller: controller, visible: showHeaderStyle,
icon: Icons.format_list_numbered, child: SelectHeaderStyleButton(controller: controller)),
), VerticalDivider(
), indent: 12, endIndent: 12, color: Colors.grey.shade400),
Visibility( Visibility(
visible: showListBullets, visible: showListNumbers,
child: ToggleStyleButton( child: ToggleStyleButton(
attribute: Attribute.ul, attribute: Attribute.ol,
controller: controller, controller: controller,
icon: Icons.format_list_bulleted, icon: Icons.format_list_numbered,
), ),
), ),
Visibility( Visibility(
visible: showListCheck, visible: showListBullets,
child: ToggleCheckListButton( child: ToggleStyleButton(
attribute: Attribute.unchecked, attribute: Attribute.ul,
controller: controller, controller: controller,
icon: Icons.check_box, icon: Icons.format_list_bulleted,
), ),
), ),
Visibility( Visibility(
visible: showCodeBlock, visible: showListCheck,
child: ToggleStyleButton( child: ToggleCheckListButton(
attribute: Attribute.codeBlock, attribute: Attribute.unchecked,
controller: controller, controller: controller,
icon: Icons.code, icon: Icons.check_box,
), ),
), ),
Visibility( Visibility(
visible: !showListNumbers && !showListBullets && !showListCheck && !showCodeBlock, visible: showCodeBlock,
child: VerticalDivider(indent: 12, endIndent: 12, color: Colors.grey.shade400)), child: ToggleStyleButton(
Visibility( attribute: Attribute.codeBlock,
visible: showQuote, controller: controller,
child: ToggleStyleButton( icon: Icons.code,
attribute: Attribute.blockQuote, ),
controller: controller, ),
icon: Icons.format_quote, Visibility(
), visible: !showListNumbers &&
), !showListBullets &&
Visibility( !showListCheck &&
visible: showIndent, !showCodeBlock,
child: IndentButton( child: VerticalDivider(
icon: Icons.format_indent_increase, indent: 12, endIndent: 12, color: Colors.grey.shade400)),
controller: controller, Visibility(
isIncrease: true, visible: showQuote,
), child: ToggleStyleButton(
), attribute: Attribute.blockQuote,
Visibility( controller: controller,
visible: showIndent, icon: Icons.format_quote,
child: IndentButton( ),
icon: Icons.format_indent_decrease, ),
controller: controller, Visibility(
isIncrease: false, visible: showIndent,
), child: IndentButton(
), icon: Icons.format_indent_increase,
Visibility(visible: showQuote, child: VerticalDivider(indent: 12, endIndent: 12, color: Colors.grey.shade400)), controller: controller,
Visibility(visible: showLink, child: LinkStyleButton(controller: controller)), isIncrease: true,
Visibility( ),
visible: showHorizontalRule, ),
child: InsertEmbedButton( Visibility(
controller: controller, visible: showIndent,
icon: Icons.horizontal_rule, child: IndentButton(
), icon: Icons.format_indent_decrease,
), controller: controller,
]); isIncrease: false,
),
),
Visibility(
visible: showQuote,
child: VerticalDivider(
indent: 12, endIndent: 12, color: Colors.grey.shade400)),
Visibility(
visible: showLink,
child: LinkStyleButton(controller: controller)),
Visibility(
visible: showHorizontalRule,
child: InsertEmbedButton(
controller: controller,
icon: Icons.horizontal_rule,
),
),
]);
} }
final List<Widget> children; final List<Widget> children;

Loading…
Cancel
Save