|
|
|
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,
|
|
|
|
);
|
|
|
|
}
|