Rich text editor for Flutter
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 

163 lines
4.5 KiB

import 'package:flutter/material.dart';
import '../../models/documents/attribute.dart';
import '../../models/documents/style.dart';
import '../../models/themes/quill_icon_theme.dart';
import '../../utils/widgets.dart';
import '../controller.dart';
import '../toolbar.dart';
typedef ToggleStyleButtonBuilder = Widget Function(
BuildContext context,
Attribute attribute,
IconData icon,
Color? fillColor,
bool? isToggled,
VoidCallback? onPressed,
VoidCallback? afterPressed, [
double iconSize,
QuillIconTheme? iconTheme,
]);
class ToggleStyleButton extends StatefulWidget {
const ToggleStyleButton({
required this.attribute,
required this.icon,
required this.controller,
this.iconSize = kDefaultIconSize,
this.fillColor,
this.childBuilder = defaultToggleStyleButtonBuilder,
this.iconTheme,
this.afterButtonPressed,
this.tooltip,
Key? key,
}) : super(key: key);
final Attribute attribute;
final IconData icon;
final double iconSize;
final Color? fillColor;
final QuillController controller;
final ToggleStyleButtonBuilder childBuilder;
///Specify an icon theme for the icons in the toolbar
final QuillIconTheme? iconTheme;
final VoidCallback? afterButtonPressed;
final String? tooltip;
@override
_ToggleStyleButtonState createState() => _ToggleStyleButtonState();
}
class _ToggleStyleButtonState extends State<ToggleStyleButton> {
bool? _isToggled;
Style get _selectionStyle => widget.controller.getSelectionStyle();
@override
void initState() {
super.initState();
_isToggled = _getIsToggled(_selectionStyle.attributes);
widget.controller.addListener(_didChangeEditingValue);
}
@override
Widget build(BuildContext context) {
return UtilityWidgets.maybeTooltip(
message: widget.tooltip,
child: widget.childBuilder(
context,
widget.attribute,
widget.icon,
widget.fillColor,
_isToggled,
_toggleAttribute,
widget.afterButtonPressed,
widget.iconSize,
widget.iconTheme,
),
);
}
@override
void didUpdateWidget(covariant ToggleStyleButton oldWidget) {
super.didUpdateWidget(oldWidget);
if (oldWidget.controller != widget.controller) {
oldWidget.controller.removeListener(_didChangeEditingValue);
widget.controller.addListener(_didChangeEditingValue);
_isToggled = _getIsToggled(_selectionStyle.attributes);
}
}
@override
void dispose() {
widget.controller.removeListener(_didChangeEditingValue);
super.dispose();
}
void _didChangeEditingValue() {
setState(() => _isToggled = _getIsToggled(_selectionStyle.attributes));
}
bool _getIsToggled(Map<String, Attribute> attrs) {
if (widget.attribute.key == Attribute.list.key) {
final attribute = attrs[widget.attribute.key];
if (attribute == null) {
return false;
}
return attribute.value == widget.attribute.value;
}
return attrs.containsKey(widget.attribute.key);
}
void _toggleAttribute() {
widget.controller.formatSelection(_isToggled!
? Attribute.clone(widget.attribute, null)
: widget.attribute);
}
}
Widget defaultToggleStyleButtonBuilder(
BuildContext context,
Attribute attribute,
IconData icon,
Color? fillColor,
bool? isToggled,
VoidCallback? onPressed,
VoidCallback? afterPressed, [
double iconSize = kDefaultIconSize,
QuillIconTheme? iconTheme,
]) {
final theme = Theme.of(context);
final isEnabled = onPressed != null;
final iconColor = isEnabled
? isToggled == true
? (iconTheme?.iconSelectedColor ??
theme
.primaryIconTheme.color) //You can specify your own icon color
: (iconTheme?.iconUnselectedColor ?? theme.iconTheme.color)
: (iconTheme?.disabledIconColor ?? theme.disabledColor);
final fill = isEnabled
? isToggled == true
? (iconTheme?.iconSelectedFillColor ??
Theme.of(context).primaryColor) //Selected icon fill color
: (iconTheme?.iconUnselectedFillColor ??
theme.canvasColor) //Unselected icon fill color :
: (iconTheme?.disabledIconFillColor ??
(fillColor ?? theme.canvasColor)); //Disabled icon fill color
return QuillIconButton(
highlightElevation: 0,
hoverElevation: 0,
size: iconSize * kIconButtonFactor,
icon: Icon(icon, size: iconSize, color: iconColor),
fillColor: fill,
onPressed: onPressed,
afterPressed: afterPressed,
borderRadius: iconTheme?.borderRadius ?? 2,
);
}