parent
4052779cfe
commit
33e7c46288
107 changed files with 1536 additions and 718 deletions
@ -1,14 +1,13 @@ |
|||||||
import 'package:equatable/equatable.dart'; |
import 'package:equatable/equatable.dart'; |
||||||
import 'package:flutter/foundation.dart' show immutable; |
import 'package:flutter/foundation.dart' show immutable; |
||||||
import 'package:flutter/widgets.dart' show Color; |
|
||||||
|
|
||||||
@immutable |
@immutable |
||||||
class QuillEditorOrderedListElementOptions extends Equatable { |
class QuillEditorOrderedListElementOptions extends Equatable { |
||||||
const QuillEditorOrderedListElementOptions( |
const QuillEditorOrderedListElementOptions({ |
||||||
{this.backgroundColor, this.fontColor}); |
this.useTextColorForDot = true, |
||||||
|
}); |
||||||
|
|
||||||
final Color? backgroundColor; |
final bool useTextColorForDot; |
||||||
final Color? fontColor; |
|
||||||
@override |
@override |
||||||
List<Object?> get props => []; |
List<Object?> get props => []; |
||||||
} |
} |
||||||
|
@ -1,14 +1,13 @@ |
|||||||
import 'package:equatable/equatable.dart'; |
import 'package:equatable/equatable.dart'; |
||||||
import 'package:flutter/foundation.dart' show immutable; |
import 'package:flutter/foundation.dart' show immutable; |
||||||
import 'package:flutter/widgets.dart' show Color; |
|
||||||
|
|
||||||
@immutable |
@immutable |
||||||
class QuillEditorUnOrderedListElementOptions extends Equatable { |
class QuillEditorUnOrderedListElementOptions extends Equatable { |
||||||
const QuillEditorUnOrderedListElementOptions( |
const QuillEditorUnOrderedListElementOptions({ |
||||||
{this.backgroundColor, this.fontColor}); |
this.useTextColorForDot = true, |
||||||
|
}); |
||||||
|
|
||||||
final Color? backgroundColor; |
final bool useTextColorForDot; |
||||||
final Color? fontColor; |
|
||||||
@override |
@override |
||||||
List<Object?> get props => []; |
List<Object?> get props => []; |
||||||
} |
} |
||||||
|
@ -0,0 +1,134 @@ |
|||||||
|
import 'package:flutter/material.dart' show PopupMenuEntry; |
||||||
|
import 'package:flutter/widgets.dart' |
||||||
|
show |
||||||
|
Color, |
||||||
|
EdgeInsets, |
||||||
|
EdgeInsetsGeometry, |
||||||
|
IconData, |
||||||
|
TextOverflow, |
||||||
|
TextStyle, |
||||||
|
ValueChanged, |
||||||
|
VoidCallback; |
||||||
|
|
||||||
|
import '../../../../widgets/toolbar/base_toolbar.dart'; |
||||||
|
import '../../../documents/attribute.dart'; |
||||||
|
import '../../../themes/quill_icon_theme.dart'; |
||||||
|
|
||||||
|
class QuillToolbarSelectHeaderStyleDropdownButtonExtraOptions |
||||||
|
extends QuillToolbarBaseButtonExtraOptions { |
||||||
|
const QuillToolbarSelectHeaderStyleDropdownButtonExtraOptions({ |
||||||
|
required super.controller, |
||||||
|
required super.context, |
||||||
|
required super.onPressed, |
||||||
|
required this.currentValue, |
||||||
|
}); |
||||||
|
final Attribute currentValue; |
||||||
|
} |
||||||
|
|
||||||
|
class QuillToolbarSelectHeaderStyleDropdownButtonOptions |
||||||
|
extends QuillToolbarBaseButtonOptions< |
||||||
|
QuillToolbarSelectHeaderStyleDropdownButtonOptions, |
||||||
|
QuillToolbarSelectHeaderStyleDropdownButtonExtraOptions> { |
||||||
|
const QuillToolbarSelectHeaderStyleDropdownButtonOptions({ |
||||||
|
super.afterButtonPressed, |
||||||
|
super.childBuilder, |
||||||
|
super.iconTheme, |
||||||
|
super.tooltip, |
||||||
|
this.iconSize, |
||||||
|
this.iconButtonFactor, |
||||||
|
this.textStyle, |
||||||
|
super.iconData, |
||||||
|
this.fillColor, |
||||||
|
this.hoverElevation = 1, |
||||||
|
this.highlightElevation = 1, |
||||||
|
this.onSelected, |
||||||
|
this.attributes, |
||||||
|
this.padding, |
||||||
|
this.style, |
||||||
|
this.width, |
||||||
|
this.labelOverflow = TextOverflow.visible, |
||||||
|
this.itemHeight, |
||||||
|
this.itemPadding, |
||||||
|
this.defaultItemColor, |
||||||
|
this.renderItemTextStyle = false, |
||||||
|
}); |
||||||
|
|
||||||
|
/// By default we will the toolbar axis from [QuillSimpleToolbarConfigurations] |
||||||
|
final double? iconSize; |
||||||
|
final double? iconButtonFactor; |
||||||
|
final TextStyle? textStyle; |
||||||
|
|
||||||
|
final Color? fillColor; |
||||||
|
final double hoverElevation; |
||||||
|
final double highlightElevation; |
||||||
|
final ValueChanged<String>? onSelected; |
||||||
|
|
||||||
|
/// Header attributes, defaults to: |
||||||
|
/// ```dart |
||||||
|
/// [ |
||||||
|
/// Attribute.h1, |
||||||
|
/// Attribute.h2, |
||||||
|
/// Attribute.h3, |
||||||
|
/// Attribute.h4, |
||||||
|
/// Attribute.h5, |
||||||
|
/// Attribute.h6, |
||||||
|
/// Attribute.header, |
||||||
|
/// ] |
||||||
|
/// ``` |
||||||
|
final List<Attribute<int>>? attributes; |
||||||
|
final EdgeInsetsGeometry? padding; |
||||||
|
final TextStyle? style; |
||||||
|
final double? width; |
||||||
|
final TextOverflow labelOverflow; |
||||||
|
final double? itemHeight; |
||||||
|
final EdgeInsets? itemPadding; |
||||||
|
final Color? defaultItemColor; |
||||||
|
final bool renderItemTextStyle; |
||||||
|
|
||||||
|
QuillToolbarSelectHeaderStyleDropdownButtonOptions copyWith({ |
||||||
|
Color? fillColor, |
||||||
|
double? hoverElevation, |
||||||
|
double? highlightElevation, |
||||||
|
List<PopupMenuEntry<String>>? items, |
||||||
|
ValueChanged<String>? onSelected, |
||||||
|
List<Attribute<int>>? attributes, |
||||||
|
EdgeInsetsGeometry? padding, |
||||||
|
TextStyle? style, |
||||||
|
double? width, |
||||||
|
TextOverflow? labelOverflow, |
||||||
|
bool? renderFontFamilies, |
||||||
|
bool? overrideTooltipByFontFamily, |
||||||
|
double? itemHeight, |
||||||
|
EdgeInsets? itemPadding, |
||||||
|
Color? defaultItemColor, |
||||||
|
double? iconSize, |
||||||
|
double? iconButtonFactor, |
||||||
|
IconData? iconData, |
||||||
|
VoidCallback? afterButtonPressed, |
||||||
|
String? tooltip, |
||||||
|
QuillIconTheme? iconTheme, |
||||||
|
bool? renderItemTextStyle, |
||||||
|
}) { |
||||||
|
return QuillToolbarSelectHeaderStyleDropdownButtonOptions( |
||||||
|
attributes: attributes ?? this.attributes, |
||||||
|
iconData: iconData ?? this.iconData, |
||||||
|
afterButtonPressed: afterButtonPressed ?? this.afterButtonPressed, |
||||||
|
tooltip: tooltip ?? this.tooltip, |
||||||
|
iconTheme: iconTheme ?? this.iconTheme, |
||||||
|
onSelected: onSelected ?? this.onSelected, |
||||||
|
padding: padding ?? this.padding, |
||||||
|
style: style ?? this.style, |
||||||
|
width: width ?? this.width, |
||||||
|
labelOverflow: labelOverflow ?? this.labelOverflow, |
||||||
|
itemHeight: itemHeight ?? this.itemHeight, |
||||||
|
itemPadding: itemPadding ?? this.itemPadding, |
||||||
|
defaultItemColor: defaultItemColor ?? this.defaultItemColor, |
||||||
|
iconSize: iconSize ?? this.iconSize, |
||||||
|
iconButtonFactor: iconButtonFactor ?? this.iconButtonFactor, |
||||||
|
fillColor: fillColor ?? this.fillColor, |
||||||
|
hoverElevation: hoverElevation ?? this.hoverElevation, |
||||||
|
highlightElevation: highlightElevation ?? this.highlightElevation, |
||||||
|
renderItemTextStyle: renderItemTextStyle ?? this.renderItemTextStyle, |
||||||
|
); |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,136 @@ |
|||||||
|
// ignore_for_file: public_member_api_docs, sort_constructors_first |
||||||
|
import 'package:equatable/equatable.dart'; |
||||||
|
import 'package:flutter/foundation.dart' show immutable; |
||||||
|
|
||||||
|
import 'base_button_configurations.dart'; |
||||||
|
import 'buttons/clear_format_configurations.dart'; |
||||||
|
import 'buttons/color_configurations.dart'; |
||||||
|
import 'buttons/custom_button_configurations.dart'; |
||||||
|
import 'buttons/font_family_configurations.dart'; |
||||||
|
import 'buttons/font_size_configurations.dart'; |
||||||
|
import 'buttons/history_configurations.dart'; |
||||||
|
import 'buttons/indent_configurations.dart'; |
||||||
|
import 'buttons/link_style2_configurations.dart'; |
||||||
|
import 'buttons/link_style_configurations.dart'; |
||||||
|
import 'buttons/search_configurations.dart'; |
||||||
|
import 'buttons/select_alignment_configurations.dart'; |
||||||
|
import 'buttons/select_header_style_buttons_configurations.dart'; |
||||||
|
import 'buttons/select_header_style_dropdown_button_configurations.dart'; |
||||||
|
import 'buttons/toggle_check_list_configurations.dart'; |
||||||
|
import 'buttons/toggle_style_configurations.dart'; |
||||||
|
|
||||||
|
export './../../../widgets/toolbar/buttons/search/search_dialog.dart'; |
||||||
|
export 'base_button_configurations.dart'; |
||||||
|
export 'buttons/clear_format_configurations.dart'; |
||||||
|
export 'buttons/color_configurations.dart'; |
||||||
|
export 'buttons/custom_button_configurations.dart'; |
||||||
|
export 'buttons/font_family_configurations.dart'; |
||||||
|
export 'buttons/font_size_configurations.dart'; |
||||||
|
export 'buttons/history_configurations.dart'; |
||||||
|
export 'buttons/indent_configurations.dart'; |
||||||
|
export 'buttons/link_style2_configurations.dart'; |
||||||
|
export 'buttons/link_style_configurations.dart'; |
||||||
|
export 'buttons/search_configurations.dart'; |
||||||
|
export 'buttons/select_alignment_configurations.dart'; |
||||||
|
export 'buttons/select_header_style_buttons_configurations.dart'; |
||||||
|
export 'buttons/select_header_style_dropdown_button_configurations.dart'; |
||||||
|
export 'buttons/toggle_check_list_configurations.dart'; |
||||||
|
export 'buttons/toggle_style_configurations.dart'; |
||||||
|
|
||||||
|
/// The configurations for the buttons of the toolbar widget of flutter quill |
||||||
|
@immutable |
||||||
|
class QuillSimpleToolbarButtonOptions extends Equatable { |
||||||
|
const QuillSimpleToolbarButtonOptions({ |
||||||
|
this.base = const QuillToolbarBaseButtonOptions(), |
||||||
|
this.undoHistory = const QuillToolbarHistoryButtonOptions(), |
||||||
|
this.redoHistory = const QuillToolbarHistoryButtonOptions(), |
||||||
|
this.fontFamily = const QuillToolbarFontFamilyButtonOptions(), |
||||||
|
this.fontSize = const QuillToolbarFontSizeButtonOptions(), |
||||||
|
this.bold = const QuillToolbarToggleStyleButtonOptions(), |
||||||
|
this.subscript = const QuillToolbarToggleStyleButtonOptions(), |
||||||
|
this.superscript = const QuillToolbarToggleStyleButtonOptions(), |
||||||
|
this.italic = const QuillToolbarToggleStyleButtonOptions(), |
||||||
|
this.small = const QuillToolbarToggleStyleButtonOptions(), |
||||||
|
this.underLine = const QuillToolbarToggleStyleButtonOptions(), |
||||||
|
this.strikeThrough = const QuillToolbarToggleStyleButtonOptions(), |
||||||
|
this.inlineCode = const QuillToolbarToggleStyleButtonOptions(), |
||||||
|
this.direction = const QuillToolbarToggleStyleButtonOptions(), |
||||||
|
this.listNumbers = const QuillToolbarToggleStyleButtonOptions(), |
||||||
|
this.listBullets = const QuillToolbarToggleStyleButtonOptions(), |
||||||
|
this.codeBlock = const QuillToolbarToggleStyleButtonOptions(), |
||||||
|
this.quote = const QuillToolbarToggleStyleButtonOptions(), |
||||||
|
this.toggleCheckList = const QuillToolbarToggleCheckListButtonOptions(), |
||||||
|
this.indentIncrease = const QuillToolbarIndentButtonOptions(), |
||||||
|
this.indentDecrease = const QuillToolbarIndentButtonOptions(), |
||||||
|
this.color = const QuillToolbarColorButtonOptions(), |
||||||
|
this.backgroundColor = const QuillToolbarColorButtonOptions(), |
||||||
|
this.clearFormat = const QuillToolbarClearFormatButtonOptions(), |
||||||
|
this.selectAlignmentButtons = |
||||||
|
const QuillToolbarSelectAlignmentButtonOptions(), |
||||||
|
this.search = const QuillToolbarSearchButtonOptions(), |
||||||
|
this.selectHeaderStyleButtons = |
||||||
|
const QuillToolbarSelectHeaderStyleButtonsOptions(), |
||||||
|
this.selectHeaderStyleDropdownButton = |
||||||
|
const QuillToolbarSelectHeaderStyleDropdownButtonOptions(), |
||||||
|
this.linkStyle = const QuillToolbarLinkStyleButtonOptions(), |
||||||
|
this.linkStyle2 = const QuillToolbarLinkStyleButton2Options(), |
||||||
|
this.customButtons = const QuillToolbarCustomButtonOptions(), |
||||||
|
}); |
||||||
|
|
||||||
|
/// The base configurations for all the buttons which will apply to all |
||||||
|
/// but if the options overrided in the spesefic button options |
||||||
|
/// then it will use that instead |
||||||
|
final QuillToolbarBaseButtonOptions base; |
||||||
|
final QuillToolbarHistoryButtonOptions undoHistory; |
||||||
|
final QuillToolbarHistoryButtonOptions redoHistory; |
||||||
|
final QuillToolbarFontFamilyButtonOptions fontFamily; |
||||||
|
final QuillToolbarFontSizeButtonOptions fontSize; |
||||||
|
final QuillToolbarToggleStyleButtonOptions bold; |
||||||
|
final QuillToolbarToggleStyleButtonOptions subscript; |
||||||
|
final QuillToolbarToggleStyleButtonOptions superscript; |
||||||
|
final QuillToolbarToggleStyleButtonOptions italic; |
||||||
|
final QuillToolbarToggleStyleButtonOptions small; |
||||||
|
final QuillToolbarToggleStyleButtonOptions underLine; |
||||||
|
final QuillToolbarToggleStyleButtonOptions strikeThrough; |
||||||
|
final QuillToolbarToggleStyleButtonOptions inlineCode; |
||||||
|
final QuillToolbarToggleStyleButtonOptions direction; |
||||||
|
final QuillToolbarToggleStyleButtonOptions listNumbers; |
||||||
|
final QuillToolbarToggleStyleButtonOptions listBullets; |
||||||
|
final QuillToolbarToggleStyleButtonOptions codeBlock; |
||||||
|
final QuillToolbarToggleStyleButtonOptions quote; |
||||||
|
final QuillToolbarToggleCheckListButtonOptions toggleCheckList; |
||||||
|
final QuillToolbarIndentButtonOptions indentIncrease; |
||||||
|
final QuillToolbarIndentButtonOptions indentDecrease; |
||||||
|
final QuillToolbarColorButtonOptions color; |
||||||
|
final QuillToolbarColorButtonOptions backgroundColor; |
||||||
|
final QuillToolbarClearFormatButtonOptions clearFormat; |
||||||
|
|
||||||
|
/// The reason we call this buttons in the end because this is responsible |
||||||
|
/// for all the alignment buttons and not just one, you still |
||||||
|
/// can customize the icons and tooltips |
||||||
|
/// and you have child builder |
||||||
|
final QuillToolbarSelectAlignmentButtonOptions selectAlignmentButtons; |
||||||
|
|
||||||
|
final QuillToolbarSearchButtonOptions search; |
||||||
|
|
||||||
|
/// The reason we call this buttons in the end because this is responsible |
||||||
|
/// for all the header style buttons and not just one, you still |
||||||
|
/// can customize it and you also have child builder |
||||||
|
final QuillToolbarSelectHeaderStyleButtonsOptions selectHeaderStyleButtons; |
||||||
|
|
||||||
|
/// The reason we call this buttons in the end because this is responsible |
||||||
|
/// for all the header style buttons and not just one, you still |
||||||
|
/// can customize it and you also have child builder |
||||||
|
final QuillToolbarSelectHeaderStyleDropdownButtonOptions |
||||||
|
selectHeaderStyleDropdownButton; |
||||||
|
|
||||||
|
final QuillToolbarLinkStyleButtonOptions linkStyle; |
||||||
|
final QuillToolbarLinkStyleButton2Options linkStyle2; |
||||||
|
|
||||||
|
final QuillToolbarCustomButtonOptions customButtons; |
||||||
|
|
||||||
|
@override |
||||||
|
List<Object?> get props => [ |
||||||
|
base, |
||||||
|
]; |
||||||
|
} |
@ -1,145 +0,0 @@ |
|||||||
import 'package:flutter/material.dart'; |
|
||||||
|
|
||||||
import '../../../../../translations.dart'; |
|
||||||
import '../../../../models/config/toolbar/buttons/select_header_style_configurations.dart'; |
|
||||||
import '../../../../models/documents/attribute.dart'; |
|
||||||
import '../../../quill/quill_controller.dart'; |
|
||||||
|
|
||||||
enum _HeaderStyleOptions { |
|
||||||
normal, |
|
||||||
headingOne, |
|
||||||
headingTwo, |
|
||||||
headingThree, |
|
||||||
} |
|
||||||
|
|
||||||
class QuillToolbarSelectHeaderStyleButton extends StatefulWidget { |
|
||||||
const QuillToolbarSelectHeaderStyleButton({ |
|
||||||
required this.controller, |
|
||||||
this.options = const QuillToolbarSelectHeaderStyleButtonsOptions(), |
|
||||||
super.key, |
|
||||||
}); |
|
||||||
|
|
||||||
final QuillController controller; |
|
||||||
// TODO: Needs to be reviewed |
|
||||||
final QuillToolbarSelectHeaderStyleButtonsOptions options; |
|
||||||
|
|
||||||
@override |
|
||||||
State<QuillToolbarSelectHeaderStyleButton> createState() => |
|
||||||
_QuillToolbarSelectHeaderStyleButtonState(); |
|
||||||
} |
|
||||||
|
|
||||||
class _QuillToolbarSelectHeaderStyleButtonState |
|
||||||
extends State<QuillToolbarSelectHeaderStyleButton> { |
|
||||||
var _selectedItem = _HeaderStyleOptions.normal; |
|
||||||
final _controller = MenuController(); |
|
||||||
@override |
|
||||||
void initState() { |
|
||||||
super.initState(); |
|
||||||
widget.controller.addListener(_didChangeEditingValue); |
|
||||||
} |
|
||||||
|
|
||||||
@override |
|
||||||
void dispose() { |
|
||||||
widget.controller.removeListener(_didChangeEditingValue); |
|
||||||
super.dispose(); |
|
||||||
} |
|
||||||
|
|
||||||
@override |
|
||||||
void didUpdateWidget( |
|
||||||
covariant QuillToolbarSelectHeaderStyleButton oldWidget) { |
|
||||||
super.didUpdateWidget(oldWidget); |
|
||||||
if (oldWidget.controller == widget.controller) { |
|
||||||
return; |
|
||||||
} |
|
||||||
widget.controller |
|
||||||
..removeListener(_didChangeEditingValue) |
|
||||||
..addListener(_didChangeEditingValue); |
|
||||||
} |
|
||||||
|
|
||||||
void _didChangeEditingValue() { |
|
||||||
final newSelectedItem = _getOptionsItemByAttribute(_getHeaderValue()); |
|
||||||
if (newSelectedItem == _selectedItem) { |
|
||||||
return; |
|
||||||
} |
|
||||||
setState(() { |
|
||||||
_selectedItem = newSelectedItem; |
|
||||||
}); |
|
||||||
} |
|
||||||
|
|
||||||
Attribute<dynamic> _getHeaderValue() { |
|
||||||
final attr = widget.controller.toolbarButtonToggler[Attribute.header.key]; |
|
||||||
if (attr != null) { |
|
||||||
// checkbox tapping causes controller.selection to go to offset 0 |
|
||||||
widget.controller.toolbarButtonToggler.remove(Attribute.header.key); |
|
||||||
return attr; |
|
||||||
} |
|
||||||
return widget.controller |
|
||||||
.getSelectionStyle() |
|
||||||
.attributes[Attribute.header.key] ?? |
|
||||||
Attribute.header; |
|
||||||
} |
|
||||||
|
|
||||||
String _label(_HeaderStyleOptions value) { |
|
||||||
final label = switch (value) { |
|
||||||
_HeaderStyleOptions.normal => context.loc.normal, |
|
||||||
_HeaderStyleOptions.headingOne => context.loc.heading1, |
|
||||||
_HeaderStyleOptions.headingTwo => context.loc.heading2, |
|
||||||
_HeaderStyleOptions.headingThree => context.loc.heading3, |
|
||||||
}; |
|
||||||
return label; |
|
||||||
} |
|
||||||
|
|
||||||
Attribute<dynamic>? getAttributeByOptionsItem(_HeaderStyleOptions option) { |
|
||||||
return switch (option) { |
|
||||||
_HeaderStyleOptions.normal => Attribute.header, |
|
||||||
_HeaderStyleOptions.headingOne => Attribute.h1, |
|
||||||
_HeaderStyleOptions.headingTwo => Attribute.h2, |
|
||||||
_HeaderStyleOptions.headingThree => Attribute.h3, |
|
||||||
}; |
|
||||||
} |
|
||||||
|
|
||||||
_HeaderStyleOptions _getOptionsItemByAttribute( |
|
||||||
Attribute<dynamic>? attribute) { |
|
||||||
return switch (attribute) { |
|
||||||
Attribute.h1 => _HeaderStyleOptions.headingOne, |
|
||||||
Attribute.h2 => _HeaderStyleOptions.headingTwo, |
|
||||||
Attribute.h2 => _HeaderStyleOptions.headingThree, |
|
||||||
Attribute() => _HeaderStyleOptions.normal, |
|
||||||
null => _HeaderStyleOptions.normal, |
|
||||||
}; |
|
||||||
} |
|
||||||
|
|
||||||
@override |
|
||||||
Widget build(BuildContext context) { |
|
||||||
return MenuAnchor( |
|
||||||
controller: _controller, |
|
||||||
menuChildren: _HeaderStyleOptions.values |
|
||||||
.map( |
|
||||||
(e) => MenuItemButton( |
|
||||||
child: Text(_label(e)), |
|
||||||
onPressed: () { |
|
||||||
widget.controller.formatSelection(getAttributeByOptionsItem(e)); |
|
||||||
setState(() => _selectedItem = e); |
|
||||||
}, |
|
||||||
), |
|
||||||
) |
|
||||||
.toList(), |
|
||||||
child: IconButton( |
|
||||||
onPressed: () { |
|
||||||
if (_controller.isOpen) { |
|
||||||
_controller.close(); |
|
||||||
return; |
|
||||||
} |
|
||||||
_controller.open(); |
|
||||||
}, |
|
||||||
icon: Row( |
|
||||||
mainAxisSize: MainAxisSize.min, |
|
||||||
children: [ |
|
||||||
Text(_label(_selectedItem)), |
|
||||||
const Icon(Icons.arrow_drop_down), |
|
||||||
], |
|
||||||
), |
|
||||||
), |
|
||||||
); |
|
||||||
} |
|
||||||
} |
|
@ -0,0 +1,199 @@ |
|||||||
|
import 'package:flutter/material.dart'; |
||||||
|
|
||||||
|
import '../../../../../translations.dart'; |
||||||
|
import '../../../../extensions/quill_configurations_ext.dart'; |
||||||
|
import '../../../../models/documents/attribute.dart'; |
||||||
|
import '../../../../models/themes/quill_icon_theme.dart'; |
||||||
|
import '../../../quill/quill_controller.dart'; |
||||||
|
import '../../base_toolbar.dart'; |
||||||
|
|
||||||
|
class QuillToolbarSelectHeaderStyleDropdownButton extends StatefulWidget { |
||||||
|
const QuillToolbarSelectHeaderStyleDropdownButton({ |
||||||
|
required this.controller, |
||||||
|
this.options = const QuillToolbarSelectHeaderStyleDropdownButtonOptions(), |
||||||
|
super.key, |
||||||
|
}); |
||||||
|
|
||||||
|
final QuillController controller; |
||||||
|
final QuillToolbarSelectHeaderStyleDropdownButtonOptions options; |
||||||
|
|
||||||
|
@override |
||||||
|
State<QuillToolbarSelectHeaderStyleDropdownButton> createState() => |
||||||
|
_QuillToolbarSelectHeaderStyleDropdownButtonState(); |
||||||
|
} |
||||||
|
|
||||||
|
class _QuillToolbarSelectHeaderStyleDropdownButtonState |
||||||
|
extends State<QuillToolbarSelectHeaderStyleDropdownButton> { |
||||||
|
Attribute<dynamic> _selectedItem = Attribute.header; |
||||||
|
|
||||||
|
final _controller = MenuController(); |
||||||
|
@override |
||||||
|
void initState() { |
||||||
|
super.initState(); |
||||||
|
widget.controller.addListener(_didChangeEditingValue); |
||||||
|
} |
||||||
|
|
||||||
|
@override |
||||||
|
void dispose() { |
||||||
|
widget.controller.removeListener(_didChangeEditingValue); |
||||||
|
super.dispose(); |
||||||
|
} |
||||||
|
|
||||||
|
@override |
||||||
|
void didUpdateWidget( |
||||||
|
covariant QuillToolbarSelectHeaderStyleDropdownButton oldWidget) { |
||||||
|
super.didUpdateWidget(oldWidget); |
||||||
|
if (oldWidget.controller == widget.controller) { |
||||||
|
return; |
||||||
|
} |
||||||
|
widget.controller |
||||||
|
..removeListener(_didChangeEditingValue) |
||||||
|
..addListener(_didChangeEditingValue); |
||||||
|
} |
||||||
|
|
||||||
|
void _didChangeEditingValue() { |
||||||
|
final newSelectedItem = _getHeaderValue(); |
||||||
|
if (newSelectedItem == _selectedItem) { |
||||||
|
return; |
||||||
|
} |
||||||
|
setState(() { |
||||||
|
_selectedItem = newSelectedItem; |
||||||
|
}); |
||||||
|
} |
||||||
|
|
||||||
|
Attribute<dynamic> _getHeaderValue() { |
||||||
|
final attr = widget.controller.toolbarButtonToggler[Attribute.header.key]; |
||||||
|
if (attr != null) { |
||||||
|
// checkbox tapping causes controller.selection to go to offset 0 |
||||||
|
widget.controller.toolbarButtonToggler.remove(Attribute.header.key); |
||||||
|
return attr; |
||||||
|
} |
||||||
|
return widget.controller |
||||||
|
.getSelectionStyle() |
||||||
|
.attributes[Attribute.header.key] ?? |
||||||
|
Attribute.header; |
||||||
|
} |
||||||
|
|
||||||
|
String _label(Attribute<dynamic> value) { |
||||||
|
final label = switch (value) { |
||||||
|
Attribute.h1 => context.loc.heading1, |
||||||
|
Attribute.h2 => context.loc.heading2, |
||||||
|
Attribute.h3 => context.loc.heading3, |
||||||
|
Attribute.h4 => context.loc.heading4, |
||||||
|
Attribute.h5 => context.loc.heading5, |
||||||
|
Attribute.h6 => context.loc.heading6, |
||||||
|
Attribute.header => context.loc.normal, |
||||||
|
Attribute<dynamic>() => throw ArgumentError(), |
||||||
|
}; |
||||||
|
return label; |
||||||
|
} |
||||||
|
|
||||||
|
double get iconSize { |
||||||
|
final baseFontSize = context.quillToolbarBaseButtonOptions?.globalIconSize; |
||||||
|
final iconSize = widget.options.iconSize; |
||||||
|
return iconSize ?? baseFontSize ?? kDefaultIconSize; |
||||||
|
} |
||||||
|
|
||||||
|
double get iconButtonFactor { |
||||||
|
final baseIconFactor = |
||||||
|
context.quillToolbarBaseButtonOptions?.globalIconButtonFactor; |
||||||
|
final iconButtonFactor = widget.options.iconButtonFactor; |
||||||
|
return iconButtonFactor ?? baseIconFactor ?? kIconButtonFactor; |
||||||
|
} |
||||||
|
|
||||||
|
QuillIconTheme? get iconTheme { |
||||||
|
return widget.options.iconTheme ?? |
||||||
|
context.quillToolbarBaseButtonOptions?.iconTheme; |
||||||
|
} |
||||||
|
|
||||||
|
List<Attribute<int?>> get headerAttributes { |
||||||
|
return widget.options.attributes ?? |
||||||
|
[ |
||||||
|
Attribute.h1, |
||||||
|
Attribute.h2, |
||||||
|
Attribute.h3, |
||||||
|
Attribute.h4, |
||||||
|
Attribute.h5, |
||||||
|
Attribute.h6, |
||||||
|
Attribute.header, |
||||||
|
]; |
||||||
|
} |
||||||
|
|
||||||
|
QuillToolbarBaseButtonOptions get baseButtonExtraOptions { |
||||||
|
return context.requireQuillToolbarBaseButtonOptions; |
||||||
|
} |
||||||
|
|
||||||
|
VoidCallback? get afterButtonPressed { |
||||||
|
return widget.options.afterButtonPressed ?? |
||||||
|
baseButtonExtraOptions.afterButtonPressed; |
||||||
|
} |
||||||
|
|
||||||
|
void _onPressed(Attribute<int?> e) { |
||||||
|
setState(() => _selectedItem = e); |
||||||
|
widget.controller.formatSelection(_selectedItem); |
||||||
|
} |
||||||
|
|
||||||
|
@override |
||||||
|
Widget build(BuildContext context) { |
||||||
|
final baseButtonConfigurations = |
||||||
|
context.requireQuillToolbarBaseButtonOptions; |
||||||
|
final childBuilder = |
||||||
|
widget.options.childBuilder ?? baseButtonConfigurations.childBuilder; |
||||||
|
if (childBuilder != null) { |
||||||
|
return childBuilder( |
||||||
|
widget.options.copyWith( |
||||||
|
iconSize: iconSize, |
||||||
|
iconTheme: iconTheme, |
||||||
|
afterButtonPressed: afterButtonPressed, |
||||||
|
), |
||||||
|
QuillToolbarSelectHeaderStyleDropdownButtonExtraOptions( |
||||||
|
currentValue: _selectedItem, |
||||||
|
context: context, |
||||||
|
controller: widget.controller, |
||||||
|
onPressed: () { |
||||||
|
throw UnimplementedError('Not implemented yet.'); |
||||||
|
}, |
||||||
|
), |
||||||
|
); |
||||||
|
} |
||||||
|
|
||||||
|
return MenuAnchor( |
||||||
|
controller: _controller, |
||||||
|
menuChildren: headerAttributes |
||||||
|
.map( |
||||||
|
(e) => MenuItemButton( |
||||||
|
onPressed: () { |
||||||
|
_onPressed(e); |
||||||
|
}, |
||||||
|
child: Text(_label(e)), |
||||||
|
), |
||||||
|
) |
||||||
|
.toList(), |
||||||
|
child: IconButton( |
||||||
|
onPressed: () { |
||||||
|
if (_controller.isOpen) { |
||||||
|
_controller.close(); |
||||||
|
return; |
||||||
|
} |
||||||
|
_controller.open(); |
||||||
|
}, |
||||||
|
icon: Row( |
||||||
|
mainAxisSize: MainAxisSize.min, |
||||||
|
children: [ |
||||||
|
Text( |
||||||
|
_label(_selectedItem), |
||||||
|
style: widget.options.textStyle ?? |
||||||
|
TextStyle( |
||||||
|
fontSize: iconSize / 1.15, |
||||||
|
), |
||||||
|
), |
||||||
|
Icon( |
||||||
|
Icons.arrow_drop_down, |
||||||
|
size: iconSize * iconButtonFactor, |
||||||
|
), |
||||||
|
], |
||||||
|
), |
||||||
|
), |
||||||
|
); |
||||||
|
} |
||||||
|
} |
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in new issue