Added theming options for toolbar icons and LinkDialog() (#418)

pull/421/head
Namli1 4 years ago committed by GitHub
parent 0d83169c07
commit 85df4033d8
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
  1. 2
      lib/flutter_quill.dart
  2. 15
      lib/src/models/themes/quill_dialog_theme.dart
  3. 30
      lib/src/models/themes/quill_icon_theme.dart
  4. 19
      lib/src/widgets/editor.dart
  5. 17
      lib/src/widgets/link_dialog.dart
  6. 52
      lib/src/widgets/toolbar.dart
  7. 12
      lib/src/widgets/toolbar/camera_button.dart
  8. 9
      lib/src/widgets/toolbar/clear_format_button.dart
  9. 11
      lib/src/widgets/toolbar/color_button.dart
  10. 13
      lib/src/widgets/toolbar/history_button.dart
  11. 18
      lib/src/widgets/toolbar/image_button.dart
  12. 12
      lib/src/widgets/toolbar/indent_button.dart
  13. 13
      lib/src/widgets/toolbar/insert_embed_button.dart
  14. 14
      lib/src/widgets/toolbar/link_style_button.dart
  15. 16
      lib/src/widgets/toolbar/select_alignment_button.dart
  16. 16
      lib/src/widgets/toolbar/select_header_style_button.dart
  17. 5
      lib/src/widgets/toolbar/toggle_check_list_button.dart
  18. 27
      lib/src/widgets/toolbar/toggle_style_button.dart
  19. 18
      lib/src/widgets/toolbar/video_button.dart

@ -5,6 +5,8 @@ export 'src/models/documents/document.dart';
export 'src/models/documents/nodes/embed.dart'; export 'src/models/documents/nodes/embed.dart';
export 'src/models/documents/nodes/leaf.dart'; export 'src/models/documents/nodes/leaf.dart';
export 'src/models/quill_delta.dart'; export 'src/models/quill_delta.dart';
export 'src/models/themes/quill_dialog_theme.dart';
export 'src/models/themes/quill_icon_theme.dart';
export 'src/widgets/controller.dart'; export 'src/widgets/controller.dart';
export 'src/widgets/default_styles.dart'; export 'src/widgets/default_styles.dart';
export 'src/widgets/editor.dart'; export 'src/widgets/editor.dart';

@ -0,0 +1,15 @@
import 'package:flutter/material.dart';
class QuillDialogTheme {
QuillDialogTheme(
{this.labelTextStyle, this.inputTextStyle, this.dialogBackgroundColor});
///The text style to use for the label shown in the link-input dialog
final TextStyle? labelTextStyle;
///The text style to use for the input text shown in the link-input dialog
final TextStyle? inputTextStyle;
///The background color for the [LinkDialog()]
final Color? dialogBackgroundColor;
}

@ -0,0 +1,30 @@
import 'package:flutter/material.dart';
class QuillIconTheme {
const QuillIconTheme({
this.iconSelectedColor,
this.iconUnselectedColor,
this.iconSelectedFillColor,
this.iconUnselectedFillColor,
this.disabledIconColor,
this.disabledIconFillColor,
});
///The color to use for selected icons in the toolbar
final Color? iconSelectedColor;
///The color to use for unselected icons in the toolbar
final Color? iconUnselectedColor;
///The fill color to use for the selected icons in the toolbar
final Color? iconSelectedFillColor;
///The fill color to use for the unselected icons in the toolbar
final Color? iconUnselectedFillColor;
///The color to use for disabled icons in the toolbar
final Color? disabledIconColor;
///The fill color to use for disabled icons in the toolbar
final Color? disabledIconFillColor;
}

@ -258,16 +258,19 @@ class QuillEditor extends StatefulWidget {
factory QuillEditor.basic({ factory QuillEditor.basic({
required QuillController controller, required QuillController controller,
required bool readOnly, required bool readOnly,
Brightness? keyboardAppearance,
}) { }) {
return QuillEditor( return QuillEditor(
controller: controller, controller: controller,
scrollController: ScrollController(), scrollController: ScrollController(),
scrollable: true, scrollable: true,
focusNode: FocusNode(), focusNode: FocusNode(),
autoFocus: true, autoFocus: true,
readOnly: readOnly, readOnly: readOnly,
expands: false, expands: false,
padding: EdgeInsets.zero); padding: EdgeInsets.zero,
keyboardAppearance: keyboardAppearance ?? Brightness.light,
);
} }
final QuillController controller; final QuillController controller;

@ -1,7 +1,10 @@
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import '../models/themes/quill_dialog_theme.dart';
class LinkDialog extends StatefulWidget { class LinkDialog extends StatefulWidget {
const LinkDialog({Key? key}) : super(key: key); const LinkDialog({this.dialogTheme, Key? key}) : super(key: key);
final QuillDialogTheme? dialogTheme;
@override @override
LinkDialogState createState() => LinkDialogState(); LinkDialogState createState() => LinkDialogState();
@ -13,15 +16,23 @@ class LinkDialogState extends State<LinkDialog> {
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
return AlertDialog( return AlertDialog(
backgroundColor: widget.dialogTheme?.dialogBackgroundColor,
content: TextField( content: TextField(
decoration: const InputDecoration(labelText: 'Paste a link'), style: widget.dialogTheme?.inputTextStyle,
decoration: InputDecoration(
labelText: 'Paste a link',
labelStyle: widget.dialogTheme?.labelTextStyle,
floatingLabelStyle: widget.dialogTheme?.labelTextStyle),
autofocus: true, autofocus: true,
onChanged: _linkChanged, onChanged: _linkChanged,
), ),
actions: [ actions: [
TextButton( TextButton(
onPressed: _link.isNotEmpty ? _applyLink : null, onPressed: _link.isNotEmpty ? _applyLink : null,
child: const Text('Ok'), child: Text(
'Ok',
style: widget.dialogTheme?.labelTextStyle,
),
), ),
], ],
); );

@ -3,6 +3,8 @@ import 'dart:io';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import '../models/documents/attribute.dart'; import '../models/documents/attribute.dart';
import '../models/themes/quill_icon_theme.dart';
import '../models/themes/quill_dialog_theme.dart';
import '../utils/media_pick_setting.dart'; import '../utils/media_pick_setting.dart';
import 'controller.dart'; import 'controller.dart';
import 'toolbar/arrow_indicated_button_list.dart'; import 'toolbar/arrow_indicated_button_list.dart';
@ -95,6 +97,12 @@ class QuillToolbar extends StatelessWidget implements PreferredSizeWidget {
FilePickImpl? filePickImpl, FilePickImpl? filePickImpl,
WebImagePickImpl? webImagePickImpl, WebImagePickImpl? webImagePickImpl,
WebVideoPickImpl? webVideoPickImpl, WebVideoPickImpl? webVideoPickImpl,
///The theme to use for the icons in the toolbar, uses type [QuillIconTheme]
QuillIconTheme? iconTheme,
///The theme to use for the theming of the [LinkDialog()], shown when embedding an image, for example
QuillDialogTheme? dialogTheme,
Key? key, Key? key,
}) { }) {
final isButtonGroupShown = [ final isButtonGroupShown = [
@ -128,6 +136,7 @@ class QuillToolbar extends StatelessWidget implements PreferredSizeWidget {
iconSize: toolbarIconSize, iconSize: toolbarIconSize,
controller: controller, controller: controller,
undo: true, undo: true,
iconTheme: iconTheme,
), ),
if (showHistory) if (showHistory)
HistoryButton( HistoryButton(
@ -135,6 +144,7 @@ class QuillToolbar extends StatelessWidget implements PreferredSizeWidget {
iconSize: toolbarIconSize, iconSize: toolbarIconSize,
controller: controller, controller: controller,
undo: false, undo: false,
iconTheme: iconTheme,
), ),
if (showBoldButton) if (showBoldButton)
ToggleStyleButton( ToggleStyleButton(
@ -142,6 +152,7 @@ class QuillToolbar extends StatelessWidget implements PreferredSizeWidget {
icon: Icons.format_bold, icon: Icons.format_bold,
iconSize: toolbarIconSize, iconSize: toolbarIconSize,
controller: controller, controller: controller,
iconTheme: iconTheme,
), ),
if (showItalicButton) if (showItalicButton)
ToggleStyleButton( ToggleStyleButton(
@ -149,6 +160,7 @@ class QuillToolbar extends StatelessWidget implements PreferredSizeWidget {
icon: Icons.format_italic, icon: Icons.format_italic,
iconSize: toolbarIconSize, iconSize: toolbarIconSize,
controller: controller, controller: controller,
iconTheme: iconTheme,
), ),
if (showSmallButton) if (showSmallButton)
ToggleStyleButton( ToggleStyleButton(
@ -156,6 +168,7 @@ class QuillToolbar extends StatelessWidget implements PreferredSizeWidget {
icon: Icons.format_size, icon: Icons.format_size,
iconSize: toolbarIconSize, iconSize: toolbarIconSize,
controller: controller, controller: controller,
iconTheme: iconTheme,
), ),
if (showUnderLineButton) if (showUnderLineButton)
ToggleStyleButton( ToggleStyleButton(
@ -163,6 +176,7 @@ class QuillToolbar extends StatelessWidget implements PreferredSizeWidget {
icon: Icons.format_underline, icon: Icons.format_underline,
iconSize: toolbarIconSize, iconSize: toolbarIconSize,
controller: controller, controller: controller,
iconTheme: iconTheme,
), ),
if (showStrikeThrough) if (showStrikeThrough)
ToggleStyleButton( ToggleStyleButton(
@ -170,6 +184,7 @@ class QuillToolbar extends StatelessWidget implements PreferredSizeWidget {
icon: Icons.format_strikethrough, icon: Icons.format_strikethrough,
iconSize: toolbarIconSize, iconSize: toolbarIconSize,
controller: controller, controller: controller,
iconTheme: iconTheme,
), ),
if (showInlineCode) if (showInlineCode)
ToggleStyleButton( ToggleStyleButton(
@ -177,6 +192,7 @@ class QuillToolbar extends StatelessWidget implements PreferredSizeWidget {
icon: Icons.code, icon: Icons.code,
iconSize: toolbarIconSize, iconSize: toolbarIconSize,
controller: controller, controller: controller,
iconTheme: iconTheme,
), ),
if (showColorButton) if (showColorButton)
ColorButton( ColorButton(
@ -184,6 +200,7 @@ class QuillToolbar extends StatelessWidget implements PreferredSizeWidget {
iconSize: toolbarIconSize, iconSize: toolbarIconSize,
controller: controller, controller: controller,
background: false, background: false,
iconTheme: iconTheme,
), ),
if (showBackgroundColorButton) if (showBackgroundColorButton)
ColorButton( ColorButton(
@ -191,12 +208,14 @@ class QuillToolbar extends StatelessWidget implements PreferredSizeWidget {
iconSize: toolbarIconSize, iconSize: toolbarIconSize,
controller: controller, controller: controller,
background: true, background: true,
iconTheme: iconTheme,
), ),
if (showClearFormat) if (showClearFormat)
ClearFormatButton( ClearFormatButton(
icon: Icons.format_clear, icon: Icons.format_clear,
iconSize: toolbarIconSize, iconSize: toolbarIconSize,
controller: controller, controller: controller,
iconTheme: iconTheme,
), ),
if (showImageButton) if (showImageButton)
ImageButton( ImageButton(
@ -207,6 +226,8 @@ class QuillToolbar extends StatelessWidget implements PreferredSizeWidget {
filePickImpl: filePickImpl, filePickImpl: filePickImpl,
webImagePickImpl: webImagePickImpl, webImagePickImpl: webImagePickImpl,
mediaPickSettingSelector: mediaPickSettingSelector, mediaPickSettingSelector: mediaPickSettingSelector,
iconTheme: iconTheme,
dialogTheme: dialogTheme,
), ),
if (showVideoButton) if (showVideoButton)
VideoButton( VideoButton(
@ -217,18 +238,22 @@ class QuillToolbar extends StatelessWidget implements PreferredSizeWidget {
filePickImpl: filePickImpl, filePickImpl: filePickImpl,
webVideoPickImpl: webImagePickImpl, webVideoPickImpl: webImagePickImpl,
mediaPickSettingSelector: mediaPickSettingSelector, mediaPickSettingSelector: mediaPickSettingSelector,
iconTheme: iconTheme,
dialogTheme: dialogTheme,
), ),
if ((onImagePickCallback != null || onVideoPickCallback != null) && if ((onImagePickCallback != null || onVideoPickCallback != null) &&
showCameraButton) showCameraButton)
CameraButton( CameraButton(
icon: Icons.photo_camera, icon: Icons.photo_camera,
iconSize: toolbarIconSize, iconSize: toolbarIconSize,
controller: controller, controller: controller,
onImagePickCallback: onImagePickCallback, onImagePickCallback: onImagePickCallback,
onVideoPickCallback: onVideoPickCallback, onVideoPickCallback: onVideoPickCallback,
filePickImpl: filePickImpl, filePickImpl: filePickImpl,
webImagePickImpl: webImagePickImpl, webImagePickImpl: webImagePickImpl,
webVideoPickImpl: webVideoPickImpl), webVideoPickImpl: webVideoPickImpl,
iconTheme: iconTheme,
),
if (isButtonGroupShown[0] && if (isButtonGroupShown[0] &&
(isButtonGroupShown[1] || (isButtonGroupShown[1] ||
isButtonGroupShown[2] || isButtonGroupShown[2] ||
@ -259,6 +284,7 @@ class QuillToolbar extends StatelessWidget implements PreferredSizeWidget {
SelectHeaderStyleButton( SelectHeaderStyleButton(
controller: controller, controller: controller,
iconSize: toolbarIconSize, iconSize: toolbarIconSize,
iconTheme: iconTheme,
), ),
if (isButtonGroupShown[2] && if (isButtonGroupShown[2] &&
(isButtonGroupShown[3] || (isButtonGroupShown[3] ||
@ -275,6 +301,7 @@ class QuillToolbar extends StatelessWidget implements PreferredSizeWidget {
controller: controller, controller: controller,
icon: Icons.format_list_numbered, icon: Icons.format_list_numbered,
iconSize: toolbarIconSize, iconSize: toolbarIconSize,
iconTheme: iconTheme,
), ),
if (showListBullets) if (showListBullets)
ToggleStyleButton( ToggleStyleButton(
@ -282,6 +309,7 @@ class QuillToolbar extends StatelessWidget implements PreferredSizeWidget {
controller: controller, controller: controller,
icon: Icons.format_list_bulleted, icon: Icons.format_list_bulleted,
iconSize: toolbarIconSize, iconSize: toolbarIconSize,
iconTheme: iconTheme,
), ),
if (showListCheck) if (showListCheck)
ToggleCheckListButton( ToggleCheckListButton(
@ -289,6 +317,7 @@ class QuillToolbar extends StatelessWidget implements PreferredSizeWidget {
controller: controller, controller: controller,
icon: Icons.check_box, icon: Icons.check_box,
iconSize: toolbarIconSize, iconSize: toolbarIconSize,
iconTheme: iconTheme,
), ),
if (showCodeBlock) if (showCodeBlock)
ToggleStyleButton( ToggleStyleButton(
@ -296,6 +325,7 @@ class QuillToolbar extends StatelessWidget implements PreferredSizeWidget {
controller: controller, controller: controller,
icon: Icons.code, icon: Icons.code,
iconSize: toolbarIconSize, iconSize: toolbarIconSize,
iconTheme: iconTheme,
), ),
if (isButtonGroupShown[3] && if (isButtonGroupShown[3] &&
(isButtonGroupShown[4] || isButtonGroupShown[5])) (isButtonGroupShown[4] || isButtonGroupShown[5]))
@ -310,6 +340,7 @@ class QuillToolbar extends StatelessWidget implements PreferredSizeWidget {
controller: controller, controller: controller,
icon: Icons.format_quote, icon: Icons.format_quote,
iconSize: toolbarIconSize, iconSize: toolbarIconSize,
iconTheme: iconTheme,
), ),
if (showIndent) if (showIndent)
IndentButton( IndentButton(
@ -317,6 +348,7 @@ class QuillToolbar extends StatelessWidget implements PreferredSizeWidget {
iconSize: toolbarIconSize, iconSize: toolbarIconSize,
controller: controller, controller: controller,
isIncrease: true, isIncrease: true,
iconTheme: iconTheme,
), ),
if (showIndent) if (showIndent)
IndentButton( IndentButton(
@ -324,6 +356,7 @@ class QuillToolbar extends StatelessWidget implements PreferredSizeWidget {
iconSize: toolbarIconSize, iconSize: toolbarIconSize,
controller: controller, controller: controller,
isIncrease: false, isIncrease: false,
iconTheme: iconTheme,
), ),
if (isButtonGroupShown[4] && isButtonGroupShown[5]) if (isButtonGroupShown[4] && isButtonGroupShown[5])
VerticalDivider( VerticalDivider(
@ -335,12 +368,15 @@ class QuillToolbar extends StatelessWidget implements PreferredSizeWidget {
LinkStyleButton( LinkStyleButton(
controller: controller, controller: controller,
iconSize: toolbarIconSize, iconSize: toolbarIconSize,
iconTheme: iconTheme,
dialogTheme: dialogTheme,
), ),
if (showHorizontalRule) if (showHorizontalRule)
InsertEmbedButton( InsertEmbedButton(
controller: controller, controller: controller,
icon: Icons.horizontal_rule, icon: Icons.horizontal_rule,
iconSize: toolbarIconSize, iconSize: toolbarIconSize,
iconTheme: iconTheme,
), ),
], ],
); );

@ -4,6 +4,7 @@ import 'package:image_picker/image_picker.dart';
import '../controller.dart'; import '../controller.dart';
import '../toolbar.dart'; import '../toolbar.dart';
import '../../models/themes/quill_icon_theme.dart';
import 'image_video_utils.dart'; import 'image_video_utils.dart';
import 'quill_icon_button.dart'; import 'quill_icon_button.dart';
@ -18,6 +19,7 @@ class CameraButton extends StatelessWidget {
this.filePickImpl, this.filePickImpl,
this.webImagePickImpl, this.webImagePickImpl,
this.webVideoPickImpl, this.webVideoPickImpl,
this.iconTheme,
Key? key, Key? key,
}) : super(key: key); }) : super(key: key);
@ -38,16 +40,22 @@ class CameraButton extends StatelessWidget {
final FilePickImpl? filePickImpl; final FilePickImpl? filePickImpl;
final QuillIconTheme? iconTheme;
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
final theme = Theme.of(context); final theme = Theme.of(context);
final iconColor = iconTheme?.iconUnselectedColor ?? theme.iconTheme.color;
final iconFillColor =
iconTheme?.iconUnselectedFillColor ?? (fillColor ?? theme.canvasColor);
return QuillIconButton( return QuillIconButton(
icon: Icon(icon, size: iconSize, color: theme.iconTheme.color), icon: Icon(icon, size: iconSize, color: iconColor),
highlightElevation: 0, highlightElevation: 0,
hoverElevation: 0, hoverElevation: 0,
size: iconSize * 1.77, size: iconSize * 1.77,
fillColor: fillColor ?? theme.canvasColor, fillColor: iconFillColor,
onPressed: () => _handleCameraButtonTap(context, controller, onPressed: () => _handleCameraButtonTap(context, controller,
onImagePickCallback: onImagePickCallback, onImagePickCallback: onImagePickCallback,
onVideoPickCallback: onVideoPickCallback, onVideoPickCallback: onVideoPickCallback,

@ -8,6 +8,7 @@ class ClearFormatButton extends StatefulWidget {
required this.icon, required this.icon,
required this.controller, required this.controller,
this.iconSize = kDefaultIconSize, this.iconSize = kDefaultIconSize,
this.iconTheme,
Key? key, Key? key,
}) : super(key: key); }) : super(key: key);
@ -16,6 +17,8 @@ class ClearFormatButton extends StatefulWidget {
final QuillController controller; final QuillController controller;
final QuillIconTheme? iconTheme;
@override @override
_ClearFormatButtonState createState() => _ClearFormatButtonState(); _ClearFormatButtonState createState() => _ClearFormatButtonState();
} }
@ -24,8 +27,10 @@ class _ClearFormatButtonState extends State<ClearFormatButton> {
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
final theme = Theme.of(context); final theme = Theme.of(context);
final iconColor = theme.iconTheme.color; final iconColor =
final fillColor = theme.canvasColor; widget.iconTheme?.iconUnselectedColor ?? theme.iconTheme.color;
final fillColor =
widget.iconTheme?.iconUnselectedFillColor ?? theme.canvasColor;
return QuillIconButton( return QuillIconButton(
highlightElevation: 0, highlightElevation: 0,
hoverElevation: 0, hoverElevation: 0,

@ -3,6 +3,7 @@ import 'package:flutter_colorpicker/flutter_colorpicker.dart';
import '../../models/documents/attribute.dart'; import '../../models/documents/attribute.dart';
import '../../models/documents/style.dart'; import '../../models/documents/style.dart';
import '../../models/themes/quill_icon_theme.dart';
import '../../utils/color.dart'; import '../../utils/color.dart';
import '../controller.dart'; import '../controller.dart';
import '../toolbar.dart'; import '../toolbar.dart';
@ -18,6 +19,7 @@ class ColorButton extends StatefulWidget {
required this.controller, required this.controller,
required this.background, required this.background,
this.iconSize = kDefaultIconSize, this.iconSize = kDefaultIconSize,
this.iconTheme,
Key? key, Key? key,
}) : super(key: key); }) : super(key: key);
@ -25,6 +27,7 @@ class ColorButton extends StatefulWidget {
final double iconSize; final double iconSize;
final bool background; final bool background;
final QuillController controller; final QuillController controller;
final QuillIconTheme? iconTheme;
@override @override
_ColorButtonState createState() => _ColorButtonState(); _ColorButtonState createState() => _ColorButtonState();
@ -98,20 +101,20 @@ class _ColorButtonState extends State<ColorButton> {
final theme = Theme.of(context); final theme = Theme.of(context);
final iconColor = _isToggledColor && !widget.background && !_isWhite final iconColor = _isToggledColor && !widget.background && !_isWhite
? stringToColor(_selectionStyle.attributes['color']!.value) ? stringToColor(_selectionStyle.attributes['color']!.value)
: theme.iconTheme.color; : (widget.iconTheme?.iconUnselectedColor ?? theme.iconTheme.color);
final iconColorBackground = final iconColorBackground =
_isToggledBackground && widget.background && !_isWhitebackground _isToggledBackground && widget.background && !_isWhitebackground
? stringToColor(_selectionStyle.attributes['background']!.value) ? stringToColor(_selectionStyle.attributes['background']!.value)
: theme.iconTheme.color; : (widget.iconTheme?.iconUnselectedColor ?? theme.iconTheme.color);
final fillColor = _isToggledColor && !widget.background && _isWhite final fillColor = _isToggledColor && !widget.background && _isWhite
? stringToColor('#ffffff') ? stringToColor('#ffffff')
: theme.canvasColor; : (widget.iconTheme?.iconUnselectedFillColor ?? theme.canvasColor);
final fillColorBackground = final fillColorBackground =
_isToggledBackground && widget.background && _isWhitebackground _isToggledBackground && widget.background && _isWhitebackground
? stringToColor('#ffffff') ? stringToColor('#ffffff')
: theme.canvasColor; : (widget.iconTheme?.iconUnselectedFillColor ?? theme.canvasColor);
return QuillIconButton( return QuillIconButton(
highlightElevation: 0, highlightElevation: 0,

@ -9,6 +9,7 @@ class HistoryButton extends StatefulWidget {
required this.controller, required this.controller,
required this.undo, required this.undo,
this.iconSize = kDefaultIconSize, this.iconSize = kDefaultIconSize,
this.iconTheme,
Key? key, Key? key,
}) : super(key: key); }) : super(key: key);
@ -16,6 +17,7 @@ class HistoryButton extends StatefulWidget {
final double iconSize; final double iconSize;
final bool undo; final bool undo;
final QuillController controller; final QuillController controller;
final QuillIconTheme? iconTheme;
@override @override
_HistoryButtonState createState() => _HistoryButtonState(); _HistoryButtonState createState() => _HistoryButtonState();
@ -30,7 +32,8 @@ class _HistoryButtonState extends State<HistoryButton> {
theme = Theme.of(context); theme = Theme.of(context);
_setIconColor(); _setIconColor();
final fillColor = theme.canvasColor; final fillColor =
widget.iconTheme?.iconUnselectedFillColor ?? theme.canvasColor;
widget.controller.changes.listen((event) async { widget.controller.changes.listen((event) async {
_setIconColor(); _setIconColor();
}); });
@ -50,14 +53,14 @@ class _HistoryButtonState extends State<HistoryButton> {
if (widget.undo) { if (widget.undo) {
setState(() { setState(() {
_iconColor = widget.controller.hasUndo _iconColor = widget.controller.hasUndo
? theme.iconTheme.color ? widget.iconTheme?.iconUnselectedColor ?? theme.iconTheme.color
: theme.disabledColor; : widget.iconTheme?.disabledIconColor ?? theme.disabledColor;
}); });
} else { } else {
setState(() { setState(() {
_iconColor = widget.controller.hasRedo _iconColor = widget.controller.hasRedo
? theme.iconTheme.color ? widget.iconTheme?.iconUnselectedColor ?? theme.iconTheme.color
: theme.disabledColor; : widget.iconTheme?.disabledIconColor ?? theme.disabledColor;
}); });
} }
} }

@ -2,6 +2,8 @@ import 'package:flutter/material.dart';
import 'package:image_picker/image_picker.dart'; import 'package:image_picker/image_picker.dart';
import '../../models/documents/nodes/embed.dart'; import '../../models/documents/nodes/embed.dart';
import '../../models/themes/quill_dialog_theme.dart';
import '../../models/themes/quill_icon_theme.dart';
import '../../utils/media_pick_setting.dart'; import '../../utils/media_pick_setting.dart';
import '../controller.dart'; import '../controller.dart';
import '../link_dialog.dart'; import '../link_dialog.dart';
@ -19,6 +21,8 @@ class ImageButton extends StatelessWidget {
this.filePickImpl, this.filePickImpl,
this.webImagePickImpl, this.webImagePickImpl,
this.mediaPickSettingSelector, this.mediaPickSettingSelector,
this.iconTheme,
this.dialogTheme,
Key? key, Key? key,
}) : super(key: key); }) : super(key: key);
@ -37,16 +41,24 @@ class ImageButton extends StatelessWidget {
final MediaPickSettingSelector? mediaPickSettingSelector; final MediaPickSettingSelector? mediaPickSettingSelector;
final QuillIconTheme? iconTheme;
final QuillDialogTheme? dialogTheme;
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
final theme = Theme.of(context); final theme = Theme.of(context);
final iconColor = iconTheme?.iconUnselectedColor ?? theme.iconTheme.color;
final iconFillColor =
iconTheme?.iconUnselectedFillColor ?? (fillColor ?? theme.canvasColor);
return QuillIconButton( return QuillIconButton(
icon: Icon(icon, size: iconSize, color: theme.iconTheme.color), icon: Icon(icon, size: iconSize, color: iconColor),
highlightElevation: 0, highlightElevation: 0,
hoverElevation: 0, hoverElevation: 0,
size: iconSize * 1.77, size: iconSize * 1.77,
fillColor: fillColor ?? theme.canvasColor, fillColor: iconFillColor,
onPressed: () => _onPressedHandler(context), onPressed: () => _onPressedHandler(context),
); );
} }
@ -80,7 +92,7 @@ class ImageButton extends StatelessWidget {
void _typeLink(BuildContext context) { void _typeLink(BuildContext context) {
showDialog<String>( showDialog<String>(
context: context, context: context,
builder: (_) => const LinkDialog(), builder: (_) => LinkDialog(dialogTheme: dialogTheme),
).then(_linkSubmitted); ).then(_linkSubmitted);
} }

@ -9,6 +9,7 @@ class IndentButton extends StatefulWidget {
required this.controller, required this.controller,
required this.isIncrease, required this.isIncrease,
this.iconSize = kDefaultIconSize, this.iconSize = kDefaultIconSize,
this.iconTheme,
Key? key, Key? key,
}) : super(key: key); }) : super(key: key);
@ -17,6 +18,8 @@ class IndentButton extends StatefulWidget {
final QuillController controller; final QuillController controller;
final bool isIncrease; final bool isIncrease;
final QuillIconTheme? iconTheme;
@override @override
_IndentButtonState createState() => _IndentButtonState(); _IndentButtonState createState() => _IndentButtonState();
} }
@ -25,14 +28,17 @@ class _IndentButtonState extends State<IndentButton> {
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
final theme = Theme.of(context); final theme = Theme.of(context);
final iconColor = theme.iconTheme.color;
final fillColor = theme.canvasColor; final iconColor =
widget.iconTheme?.iconUnselectedColor ?? theme.iconTheme.color;
final iconFillColor =
widget.iconTheme?.iconUnselectedFillColor ?? theme.canvasColor;
return QuillIconButton( return QuillIconButton(
highlightElevation: 0, highlightElevation: 0,
hoverElevation: 0, hoverElevation: 0,
size: widget.iconSize * 1.77, size: widget.iconSize * 1.77,
icon: Icon(widget.icon, size: widget.iconSize, color: iconColor), icon: Icon(widget.icon, size: widget.iconSize, color: iconColor),
fillColor: fillColor, fillColor: iconFillColor,
onPressed: () { onPressed: () {
final indent = widget.controller final indent = widget.controller
.getSelectionStyle() .getSelectionStyle()

@ -1,6 +1,7 @@
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import '../../models/documents/nodes/embed.dart'; import '../../models/documents/nodes/embed.dart';
import '../../models/themes/quill_icon_theme.dart';
import '../controller.dart'; import '../controller.dart';
import '../toolbar.dart'; import '../toolbar.dart';
import 'quill_icon_button.dart'; import 'quill_icon_button.dart';
@ -11,6 +12,7 @@ class InsertEmbedButton extends StatelessWidget {
required this.icon, required this.icon,
this.iconSize = kDefaultIconSize, this.iconSize = kDefaultIconSize,
this.fillColor, this.fillColor,
this.iconTheme,
Key? key, Key? key,
}) : super(key: key); }) : super(key: key);
@ -18,9 +20,16 @@ class InsertEmbedButton extends StatelessWidget {
final IconData icon; final IconData icon;
final double iconSize; final double iconSize;
final Color? fillColor; final Color? fillColor;
final QuillIconTheme? iconTheme;
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
final theme = Theme.of(context);
final iconColor = iconTheme?.iconUnselectedColor ?? theme.iconTheme.color;
final iconFillColor =
iconTheme?.iconUnselectedFillColor ?? (fillColor ?? theme.canvasColor);
return QuillIconButton( return QuillIconButton(
highlightElevation: 0, highlightElevation: 0,
hoverElevation: 0, hoverElevation: 0,
@ -28,9 +37,9 @@ class InsertEmbedButton extends StatelessWidget {
icon: Icon( icon: Icon(
icon, icon,
size: iconSize, size: iconSize,
color: Theme.of(context).iconTheme.color, color: iconColor,
), ),
fillColor: fillColor ?? Theme.of(context).canvasColor, fillColor: iconFillColor,
onPressed: () { onPressed: () {
final index = controller.selection.baseOffset; final index = controller.selection.baseOffset;
final length = controller.selection.extentOffset - index; final length = controller.selection.extentOffset - index;

@ -1,6 +1,8 @@
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import '../../models/documents/attribute.dart'; import '../../models/documents/attribute.dart';
import '../../models/themes/quill_dialog_theme.dart';
import '../../models/themes/quill_icon_theme.dart';
import '../controller.dart'; import '../controller.dart';
import '../link_dialog.dart'; import '../link_dialog.dart';
import '../toolbar.dart'; import '../toolbar.dart';
@ -11,12 +13,16 @@ class LinkStyleButton extends StatefulWidget {
required this.controller, required this.controller,
this.iconSize = kDefaultIconSize, this.iconSize = kDefaultIconSize,
this.icon, this.icon,
this.iconTheme,
this.dialogTheme,
Key? key, Key? key,
}) : super(key: key); }) : super(key: key);
final QuillController controller; final QuillController controller;
final IconData? icon; final IconData? icon;
final double iconSize; final double iconSize;
final QuillIconTheme? iconTheme;
final QuillDialogTheme? dialogTheme;
@override @override
_LinkStyleButtonState createState() => _LinkStyleButtonState(); _LinkStyleButtonState createState() => _LinkStyleButtonState();
@ -60,9 +66,11 @@ class _LinkStyleButtonState extends State<LinkStyleButton> {
icon: Icon( icon: Icon(
widget.icon ?? Icons.link, widget.icon ?? Icons.link,
size: widget.iconSize, size: widget.iconSize,
color: isEnabled ? theme.iconTheme.color : theme.disabledColor, color: isEnabled
? (widget.iconTheme?.iconUnselectedColor ?? theme.iconTheme.color)
: (widget.iconTheme?.disabledIconColor ?? theme.disabledColor),
), ),
fillColor: Theme.of(context).canvasColor, fillColor: widget.iconTheme?.iconUnselectedFillColor ?? theme.canvasColor,
onPressed: pressedHandler, onPressed: pressedHandler,
); );
} }
@ -71,7 +79,7 @@ class _LinkStyleButtonState extends State<LinkStyleButton> {
showDialog<String>( showDialog<String>(
context: context, context: context,
builder: (ctx) { builder: (ctx) {
return const LinkDialog(); return LinkDialog(dialogTheme: widget.dialogTheme);
}, },
).then(_linkSubmitted); ).then(_linkSubmitted);
} }

@ -3,6 +3,7 @@ import 'package:flutter/material.dart';
import '../../models/documents/attribute.dart'; import '../../models/documents/attribute.dart';
import '../../models/documents/style.dart'; import '../../models/documents/style.dart';
import '../../models/themes/quill_icon_theme.dart';
import '../controller.dart'; import '../controller.dart';
import '../toolbar.dart'; import '../toolbar.dart';
@ -10,12 +11,15 @@ class SelectAlignmentButton extends StatefulWidget {
const SelectAlignmentButton({ const SelectAlignmentButton({
required this.controller, required this.controller,
this.iconSize = kDefaultIconSize, this.iconSize = kDefaultIconSize,
this.iconTheme,
Key? key, Key? key,
}) : super(key: key); }) : super(key: key);
final QuillController controller; final QuillController controller;
final double iconSize; final double iconSize;
final QuillIconTheme? iconTheme;
@override @override
_SelectAlignmentButtonState createState() => _SelectAlignmentButtonState(); _SelectAlignmentButtonState createState() => _SelectAlignmentButtonState();
} }
@ -77,8 +81,10 @@ class _SelectAlignmentButtonState extends State<SelectAlignmentButton> {
shape: RoundedRectangleBorder( shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(2)), borderRadius: BorderRadius.circular(2)),
fillColor: _valueToText[_value] == _valueString[index] fillColor: _valueToText[_value] == _valueString[index]
? theme.toggleableActiveColor ? (widget.iconTheme?.iconSelectedFillColor ??
: theme.canvasColor, theme.toggleableActiveColor)
: (widget.iconTheme?.iconUnselectedFillColor ??
theme.canvasColor),
onPressed: () => _valueAttribute[index] == Attribute.leftAlignment onPressed: () => _valueAttribute[index] == Attribute.leftAlignment
? widget.controller ? widget.controller
.formatSelection(Attribute.clone(Attribute.align, null)) .formatSelection(Attribute.clone(Attribute.align, null))
@ -93,8 +99,10 @@ class _SelectAlignmentButtonState extends State<SelectAlignmentButton> {
: Icons.format_align_justify, : Icons.format_align_justify,
size: widget.iconSize, size: widget.iconSize,
color: _valueToText[_value] == _valueString[index] color: _valueToText[_value] == _valueString[index]
? theme.primaryIconTheme.color ? (widget.iconTheme?.iconSelectedColor ??
: theme.iconTheme.color, theme.primaryIconTheme.color)
: (widget.iconTheme?.iconUnselectedColor ??
theme.iconTheme.color),
), ),
), ),
), ),

@ -3,6 +3,7 @@ import 'package:flutter/material.dart';
import '../../models/documents/attribute.dart'; import '../../models/documents/attribute.dart';
import '../../models/documents/style.dart'; import '../../models/documents/style.dart';
import '../../models/themes/quill_icon_theme.dart';
import '../controller.dart'; import '../controller.dart';
import '../toolbar.dart'; import '../toolbar.dart';
@ -10,12 +11,15 @@ class SelectHeaderStyleButton extends StatefulWidget {
const SelectHeaderStyleButton({ const SelectHeaderStyleButton({
required this.controller, required this.controller,
this.iconSize = kDefaultIconSize, this.iconSize = kDefaultIconSize,
this.iconTheme,
Key? key, Key? key,
}) : super(key: key); }) : super(key: key);
final QuillController controller; final QuillController controller;
final double iconSize; final double iconSize;
final QuillIconTheme? iconTheme;
@override @override
_SelectHeaderStyleButtonState createState() => _SelectHeaderStyleButtonState createState() =>
_SelectHeaderStyleButtonState(); _SelectHeaderStyleButtonState();
@ -77,16 +81,20 @@ class _SelectHeaderStyleButtonState extends State<SelectHeaderStyleButton> {
shape: RoundedRectangleBorder( shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(2)), borderRadius: BorderRadius.circular(2)),
fillColor: _valueToText[_value] == _valueString[index] fillColor: _valueToText[_value] == _valueString[index]
? theme.toggleableActiveColor ? (widget.iconTheme?.iconSelectedFillColor ??
: theme.canvasColor, theme.toggleableActiveColor)
: (widget.iconTheme?.iconUnselectedFillColor ??
theme.canvasColor),
onPressed: () => onPressed: () =>
widget.controller.formatSelection(_valueAttribute[index]), widget.controller.formatSelection(_valueAttribute[index]),
child: Text( child: Text(
_valueString[index], _valueString[index],
style: style.copyWith( style: style.copyWith(
color: _valueToText[_value] == _valueString[index] color: _valueToText[_value] == _valueString[index]
? theme.primaryIconTheme.color ? (widget.iconTheme?.iconSelectedColor ??
: theme.iconTheme.color, theme.primaryIconTheme.color)
: (widget.iconTheme?.iconUnselectedColor ??
theme.iconTheme.color),
), ),
), ),
), ),

@ -2,6 +2,7 @@ import 'package:flutter/material.dart';
import '../../models/documents/attribute.dart'; import '../../models/documents/attribute.dart';
import '../../models/documents/style.dart'; import '../../models/documents/style.dart';
import '../../models/themes/quill_icon_theme.dart';
import '../controller.dart'; import '../controller.dart';
import '../toolbar.dart'; import '../toolbar.dart';
import 'toggle_style_button.dart'; import 'toggle_style_button.dart';
@ -14,6 +15,7 @@ class ToggleCheckListButton extends StatefulWidget {
this.iconSize = kDefaultIconSize, this.iconSize = kDefaultIconSize,
this.fillColor, this.fillColor,
this.childBuilder = defaultToggleStyleButtonBuilder, this.childBuilder = defaultToggleStyleButtonBuilder,
this.iconTheme,
Key? key, Key? key,
}) : super(key: key); }) : super(key: key);
@ -28,6 +30,8 @@ class ToggleCheckListButton extends StatefulWidget {
final Attribute attribute; final Attribute attribute;
final QuillIconTheme? iconTheme;
@override @override
_ToggleCheckListButtonState createState() => _ToggleCheckListButtonState(); _ToggleCheckListButtonState createState() => _ToggleCheckListButtonState();
} }
@ -89,6 +93,7 @@ class _ToggleCheckListButtonState extends State<ToggleCheckListButton> {
_isToggled, _isToggled,
_toggleAttribute, _toggleAttribute,
widget.iconSize, widget.iconSize,
widget.iconTheme,
); );
} }

@ -2,6 +2,7 @@ import 'package:flutter/material.dart';
import '../../models/documents/attribute.dart'; import '../../models/documents/attribute.dart';
import '../../models/documents/style.dart'; import '../../models/documents/style.dart';
import '../../models/themes/quill_icon_theme.dart';
import '../controller.dart'; import '../controller.dart';
import '../toolbar.dart'; import '../toolbar.dart';
import 'quill_icon_button.dart'; import 'quill_icon_button.dart';
@ -14,6 +15,7 @@ typedef ToggleStyleButtonBuilder = Widget Function(
bool? isToggled, bool? isToggled,
VoidCallback? onPressed, [ VoidCallback? onPressed, [
double iconSize, double iconSize,
QuillIconTheme? iconTheme,
]); ]);
class ToggleStyleButton extends StatefulWidget { class ToggleStyleButton extends StatefulWidget {
@ -24,6 +26,7 @@ class ToggleStyleButton extends StatefulWidget {
this.iconSize = kDefaultIconSize, this.iconSize = kDefaultIconSize,
this.fillColor, this.fillColor,
this.childBuilder = defaultToggleStyleButtonBuilder, this.childBuilder = defaultToggleStyleButtonBuilder,
this.iconTheme,
Key? key, Key? key,
}) : super(key: key); }) : super(key: key);
@ -38,6 +41,9 @@ class ToggleStyleButton extends StatefulWidget {
final ToggleStyleButtonBuilder childBuilder; final ToggleStyleButtonBuilder childBuilder;
///Specify an icon theme for the icons in the toolbar
final QuillIconTheme? iconTheme;
@override @override
_ToggleStyleButtonState createState() => _ToggleStyleButtonState(); _ToggleStyleButtonState createState() => _ToggleStyleButtonState();
} }
@ -64,6 +70,7 @@ class _ToggleStyleButtonState extends State<ToggleStyleButton> {
_isToggled, _isToggled,
_toggleAttribute, _toggleAttribute,
widget.iconSize, widget.iconSize,
widget.iconTheme,
); );
} }
@ -113,17 +120,25 @@ Widget defaultToggleStyleButtonBuilder(
bool? isToggled, bool? isToggled,
VoidCallback? onPressed, [ VoidCallback? onPressed, [
double iconSize = kDefaultIconSize, double iconSize = kDefaultIconSize,
QuillIconTheme? iconTheme,
]) { ]) {
final theme = Theme.of(context); final theme = Theme.of(context);
final isEnabled = onPressed != null; final isEnabled = onPressed != null;
final iconColor = isEnabled final iconColor = isEnabled
? isToggled == true ? isToggled == true
? theme.primaryIconTheme.color ? (iconTheme?.iconSelectedColor ??
: theme.iconTheme.color theme
: theme.disabledColor; .primaryIconTheme.color) //You can specify your own icon color
final fill = isToggled == true : (iconTheme?.iconUnselectedColor ?? theme.iconTheme.color)
? theme.toggleableActiveColor : (iconTheme?.disabledIconColor ?? theme.disabledColor);
: fillColor ?? theme.canvasColor; final fill = isEnabled
? isToggled == true
? (iconTheme?.iconSelectedFillColor ??
theme.toggleableActiveColor) //Selected icon fill color
: (iconTheme?.iconUnselectedFillColor ??
theme.canvasColor) //Unselected icon fill color :
: (iconTheme?.disabledIconFillColor ??
(fillColor ?? theme.canvasColor)); //Disabled icon fill color
return QuillIconButton( return QuillIconButton(
highlightElevation: 0, highlightElevation: 0,
hoverElevation: 0, hoverElevation: 0,

@ -2,6 +2,8 @@ import 'package:flutter/material.dart';
import 'package:image_picker/image_picker.dart'; import 'package:image_picker/image_picker.dart';
import '../../models/documents/nodes/embed.dart'; import '../../models/documents/nodes/embed.dart';
import '../../models/themes/quill_dialog_theme.dart';
import '../../models/themes/quill_icon_theme.dart';
import '../../utils/media_pick_setting.dart'; import '../../utils/media_pick_setting.dart';
import '../controller.dart'; import '../controller.dart';
import '../link_dialog.dart'; import '../link_dialog.dart';
@ -19,6 +21,8 @@ class VideoButton extends StatelessWidget {
this.filePickImpl, this.filePickImpl,
this.webVideoPickImpl, this.webVideoPickImpl,
this.mediaPickSettingSelector, this.mediaPickSettingSelector,
this.iconTheme,
this.dialogTheme,
Key? key, Key? key,
}) : super(key: key); }) : super(key: key);
@ -37,16 +41,24 @@ class VideoButton extends StatelessWidget {
final MediaPickSettingSelector? mediaPickSettingSelector; final MediaPickSettingSelector? mediaPickSettingSelector;
final QuillIconTheme? iconTheme;
final QuillDialogTheme? dialogTheme;
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
final theme = Theme.of(context); final theme = Theme.of(context);
final iconColor = iconTheme?.iconUnselectedColor ?? theme.iconTheme.color;
final iconFillColor =
iconTheme?.iconUnselectedFillColor ?? (fillColor ?? theme.canvasColor);
return QuillIconButton( return QuillIconButton(
icon: Icon(icon, size: iconSize, color: theme.iconTheme.color), icon: Icon(icon, size: iconSize, color: iconColor),
highlightElevation: 0, highlightElevation: 0,
hoverElevation: 0, hoverElevation: 0,
size: iconSize * 1.77, size: iconSize * 1.77,
fillColor: fillColor ?? theme.canvasColor, fillColor: iconFillColor,
onPressed: () => _onPressedHandler(context), onPressed: () => _onPressedHandler(context),
); );
} }
@ -80,7 +92,7 @@ class VideoButton extends StatelessWidget {
void _typeLink(BuildContext context) { void _typeLink(BuildContext context) {
showDialog<String>( showDialog<String>(
context: context, context: context,
builder: (_) => const LinkDialog(), builder: (_) => LinkDialog(dialogTheme: dialogTheme),
).then(_linkSubmitted); ).then(_linkSubmitted);
} }

Loading…
Cancel
Save