import 'dart:io'; import 'package:flutter/material.dart'; import '../models/documents/attribute.dart'; import '../utils/media_pick_setting.dart'; import 'controller.dart'; import 'toolbar/arrow_indicated_button_list.dart'; import 'toolbar/camera_button.dart'; import 'toolbar/clear_format_button.dart'; import 'toolbar/color_button.dart'; import 'toolbar/history_button.dart'; import 'toolbar/image_button.dart'; import 'toolbar/indent_button.dart'; import 'toolbar/insert_embed_button.dart'; import 'toolbar/link_style_button.dart'; import 'toolbar/select_header_style_button.dart'; import 'toolbar/toggle_check_list_button.dart'; import 'toolbar/toggle_style_button.dart'; import 'toolbar/video_button.dart'; export '../utils/media_pick_setting.dart'; export 'toolbar/clear_format_button.dart'; export 'toolbar/color_button.dart'; export 'toolbar/history_button.dart'; export 'toolbar/image_button.dart'; export 'toolbar/indent_button.dart'; export 'toolbar/insert_embed_button.dart'; export 'toolbar/link_style_button.dart'; export 'toolbar/quill_dropdown_button.dart'; export 'toolbar/quill_icon_button.dart'; export 'toolbar/select_header_style_button.dart'; export 'toolbar/toggle_check_list_button.dart'; export 'toolbar/toggle_style_button.dart'; export 'toolbar/video_button.dart'; typedef OnImagePickCallback = Future Function(File file); typedef OnVideoPickCallback = Future Function(File file); typedef FilePickImpl = Future Function(BuildContext context); typedef WebImagePickImpl = Future Function( OnImagePickCallback onImagePickCallback); typedef WebVideoPickImpl = Future Function( OnVideoPickCallback onImagePickCallback); typedef MediaPickSettingSelector = Future Function( BuildContext context); // The default size of the icon of a button. const double kDefaultIconSize = 18; // The factor of how much larger the button is in relation to the icon. const double kIconButtonFactor = 1.77; class QuillToolbar extends StatelessWidget implements PreferredSizeWidget { const QuillToolbar({ required this.children, this.toolBarHeight = 36, this.color, this.filePickImpl, this.multiRowsDisplay, Key? key, }) : super(key: key); factory QuillToolbar.basic({ required QuillController controller, double toolbarIconSize = kDefaultIconSize, bool showBoldButton = true, bool showItalicButton = true, bool showSmallButton = false, bool showUnderLineButton = true, bool showStrikeThrough = true, bool showColorButton = true, bool showBackgroundColorButton = true, bool showClearFormat = true, bool showHeaderStyle = true, bool showListNumbers = true, bool showListBullets = true, bool showListCheck = true, bool showCodeBlock = true, bool showQuote = true, bool showIndent = true, bool showLink = true, bool showHistory = true, bool showHorizontalRule = false, bool multiRowsDisplay = true, bool showImageButton = true, bool showVideoButton = true, bool showCameraButton = true, OnImagePickCallback? onImagePickCallback, OnVideoPickCallback? onVideoPickCallback, MediaPickSettingSelector? mediaPickSettingSelector, FilePickImpl? filePickImpl, WebImagePickImpl? webImagePickImpl, WebVideoPickImpl? webVideoPickImpl, Key? key, }) { final isButtonGroupShown = [ showHistory || showBoldButton || showItalicButton || showSmallButton || showUnderLineButton || showStrikeThrough || showColorButton || showBackgroundColorButton || showClearFormat || onImagePickCallback != null || onVideoPickCallback != null, showHeaderStyle, showListNumbers || showListBullets || showListCheck || showCodeBlock, showQuote || showIndent, showLink || showHorizontalRule ]; return QuillToolbar( key: key, toolBarHeight: toolbarIconSize * 2, multiRowsDisplay: multiRowsDisplay, children: [ if (showHistory) HistoryButton( icon: Icons.undo_outlined, iconSize: toolbarIconSize, controller: controller, undo: true, ), if (showHistory) HistoryButton( icon: Icons.redo_outlined, iconSize: toolbarIconSize, controller: controller, undo: false, ), if (showBoldButton) ToggleStyleButton( attribute: Attribute.bold, icon: Icons.format_bold, iconSize: toolbarIconSize, controller: controller, ), if (showItalicButton) ToggleStyleButton( attribute: Attribute.italic, icon: Icons.format_italic, iconSize: toolbarIconSize, controller: controller, ), if (showSmallButton) ToggleStyleButton( attribute: Attribute.small, icon: Icons.format_size, iconSize: toolbarIconSize, controller: controller, ), if (showUnderLineButton) ToggleStyleButton( attribute: Attribute.underline, icon: Icons.format_underline, iconSize: toolbarIconSize, controller: controller, ), if (showStrikeThrough) ToggleStyleButton( attribute: Attribute.strikeThrough, icon: Icons.format_strikethrough, iconSize: toolbarIconSize, controller: controller, ), if (showColorButton) ColorButton( icon: Icons.color_lens, iconSize: toolbarIconSize, controller: controller, background: false, ), if (showBackgroundColorButton) ColorButton( icon: Icons.format_color_fill, iconSize: toolbarIconSize, controller: controller, background: true, ), if (showClearFormat) ClearFormatButton( icon: Icons.format_clear, iconSize: toolbarIconSize, controller: controller, ), if (showImageButton) ImageButton( icon: Icons.image, iconSize: toolbarIconSize, controller: controller, onImagePickCallback: onImagePickCallback, filePickImpl: filePickImpl, webImagePickImpl: webImagePickImpl, mediaPickSettingSelector: mediaPickSettingSelector, ), if (showVideoButton) VideoButton( icon: Icons.movie_creation, iconSize: toolbarIconSize, controller: controller, onVideoPickCallback: onVideoPickCallback, filePickImpl: filePickImpl, webVideoPickImpl: webImagePickImpl, mediaPickSettingSelector: mediaPickSettingSelector, ), if ((onImagePickCallback != null || onVideoPickCallback != null) && showCameraButton) CameraButton( icon: Icons.photo_camera, iconSize: toolbarIconSize, controller: controller, onImagePickCallback: onImagePickCallback, onVideoPickCallback: onVideoPickCallback, filePickImpl: filePickImpl, webImagePickImpl: webImagePickImpl, webVideoPickImpl: webVideoPickImpl), if (isButtonGroupShown[0] && (isButtonGroupShown[1] || isButtonGroupShown[2] || isButtonGroupShown[3] || isButtonGroupShown[4])) VerticalDivider( indent: 12, endIndent: 12, color: Colors.grey.shade400, ), if (showHeaderStyle) SelectHeaderStyleButton( controller: controller, iconSize: toolbarIconSize, ), if (isButtonGroupShown[1] && (isButtonGroupShown[2] || isButtonGroupShown[3] || isButtonGroupShown[4])) VerticalDivider( indent: 12, endIndent: 12, color: Colors.grey.shade400, ), if (showListNumbers) ToggleStyleButton( attribute: Attribute.ol, controller: controller, icon: Icons.format_list_numbered, iconSize: toolbarIconSize, ), if (showListBullets) ToggleStyleButton( attribute: Attribute.ul, controller: controller, icon: Icons.format_list_bulleted, iconSize: toolbarIconSize, ), if (showListCheck) ToggleCheckListButton( attribute: Attribute.unchecked, controller: controller, icon: Icons.check_box, iconSize: toolbarIconSize, ), if (showCodeBlock) ToggleStyleButton( attribute: Attribute.codeBlock, controller: controller, icon: Icons.code, iconSize: toolbarIconSize, ), if (isButtonGroupShown[2] && (isButtonGroupShown[3] || isButtonGroupShown[4])) VerticalDivider( indent: 12, endIndent: 12, color: Colors.grey.shade400, ), if (showQuote) ToggleStyleButton( attribute: Attribute.blockQuote, controller: controller, icon: Icons.format_quote, iconSize: toolbarIconSize, ), if (showIndent) IndentButton( icon: Icons.format_indent_increase, iconSize: toolbarIconSize, controller: controller, isIncrease: true, ), if (showIndent) IndentButton( icon: Icons.format_indent_decrease, iconSize: toolbarIconSize, controller: controller, isIncrease: false, ), if (isButtonGroupShown[3] && isButtonGroupShown[4]) VerticalDivider( indent: 12, endIndent: 12, color: Colors.grey.shade400, ), if (showLink) LinkStyleButton( controller: controller, iconSize: toolbarIconSize, ), if (showHorizontalRule) InsertEmbedButton( controller: controller, icon: Icons.horizontal_rule, iconSize: toolbarIconSize, ), ], ); } final List children; final double toolBarHeight; final bool? multiRowsDisplay; /// The color of the toolbar. /// /// Defaults to [ThemeData.canvasColor] of the current [Theme] if no color /// is given. final Color? color; final FilePickImpl? filePickImpl; @override Size get preferredSize => Size.fromHeight(toolBarHeight); @override Widget build(BuildContext context) { if (multiRowsDisplay ?? true) { return Wrap( alignment: WrapAlignment.center, runSpacing: 4, spacing: 4, children: children, ); } return Container( constraints: BoxConstraints.tightFor(height: preferredSize.height), color: color ?? Theme.of(context).canvasColor, child: ArrowIndicatedButtonList(buttons: children), ); } }