From 181384278b8cffefe8b53fcfc6d5618c2bea0ed2 Mon Sep 17 00:00:00 2001 From: jiangchong Date: Fri, 28 Apr 2023 17:11:36 +0800 Subject: [PATCH] add superscript and subscript styles --- lib/src/models/documents/attribute.dart | 10 ++++++- lib/src/translations/toolbar.i18n.dart | 4 +++ lib/src/widgets/default_styles.dart | 9 +++++++ lib/src/widgets/text_line.dart | 8 ++++++ lib/src/widgets/toolbar.dart | 27 +++++++++++++++++++ lib/src/widgets/toolbar/enum.dart | 2 ++ .../widgets/toolbar/toggle_style_button.dart | 2 +- 7 files changed, 60 insertions(+), 2 deletions(-) diff --git a/lib/src/models/documents/attribute.dart b/lib/src/models/documents/attribute.dart index 9bf75396..83861aa6 100644 --- a/lib/src/models/documents/attribute.dart +++ b/lib/src/models/documents/attribute.dart @@ -19,6 +19,8 @@ class Attribute { static final Map _registry = LinkedHashMap.of({ Attribute.bold.key: Attribute.bold, + Attribute.subscript.key: Attribute.subscript, + Attribute.superscript.key: Attribute.superscript, Attribute.italic.key: Attribute.italic, Attribute.small.key: Attribute.small, Attribute.underline.key: Attribute.underline, @@ -48,6 +50,10 @@ class Attribute { static const BoldAttribute bold = BoldAttribute(); + static final ScriptAttribute subscript = ScriptAttribute(ScriptAttributes.sub); + + static final ScriptAttribute superscript = ScriptAttribute(ScriptAttributes.sup); + static const ItalicAttribute italic = ItalicAttribute(); static const SmallAttribute small = SmallAttribute(); @@ -108,6 +114,8 @@ class Attribute { static final Set inlineKeys = { Attribute.bold.key, + Attribute.subscript.key, + Attribute.superscript.key, Attribute.italic.key, Attribute.small.key, Attribute.underline.key, @@ -359,7 +367,7 @@ class TokenAttribute extends Attribute { // `script` is supposed to be inline attribute but it is not supported yet class ScriptAttribute extends Attribute { ScriptAttribute(ScriptAttributes? val) - : super('script', AttributeScope.IGNORE, val?.value); + : super('script', AttributeScope.INLINE, val?.value); } enum ScriptAttributes { diff --git a/lib/src/translations/toolbar.i18n.dart b/lib/src/translations/toolbar.i18n.dart index 305e0152..583b81f1 100644 --- a/lib/src/translations/toolbar.i18n.dart +++ b/lib/src/translations/toolbar.i18n.dart @@ -40,6 +40,8 @@ extension Localization on String { 'Font family': 'Font family', 'Font size': 'Font size', 'Bold': 'Bold', + 'Subscript': 'Subscript', + 'Superscript': 'Superscript', 'Italic': 'Italic', 'Underline': 'Underline', 'Strike through': 'Strike through', @@ -104,6 +106,8 @@ extension Localization on String { 'Font family': 'Font family', 'Font size': 'Font size', 'Bold': 'Bold', + 'Subscript': 'Subscript', + 'Superscript': 'Superscript', 'Italic': 'Italic', 'Underline': 'Underline', 'Strike through': 'Strike through', diff --git a/lib/src/widgets/default_styles.dart b/lib/src/widgets/default_styles.dart index f9fef5d0..5ca0e95b 100644 --- a/lib/src/widgets/default_styles.dart +++ b/lib/src/widgets/default_styles.dart @@ -1,4 +1,5 @@ import 'package:flutter/material.dart'; +import 'dart:ui'; import '../models/documents/attribute.dart'; import '../models/documents/style.dart'; @@ -141,6 +142,8 @@ class DefaultStyles { this.h3, this.paragraph, this.bold, + this.subscript, + this.superscript, this.italic, this.small, this.underline, @@ -165,6 +168,8 @@ class DefaultStyles { final DefaultTextBlockStyle? h3; final DefaultTextBlockStyle? paragraph; final TextStyle? bold; + final TextStyle? subscript; + final TextStyle? superscript; final TextStyle? italic; final TextStyle? small; final TextStyle? underline; @@ -244,6 +249,8 @@ class DefaultStyles { paragraph: DefaultTextBlockStyle(baseStyle, const VerticalSpacing(0, 0), const VerticalSpacing(0, 0), null), bold: const TextStyle(fontWeight: FontWeight.bold), + subscript: TextStyle(fontFeatures: [FontFeature.subscripts()]), + superscript: TextStyle(fontFeatures: [FontFeature.superscripts()]), italic: const TextStyle(fontStyle: FontStyle.italic), small: const TextStyle(fontSize: 12), underline: const TextStyle(decoration: TextDecoration.underline), @@ -317,6 +324,8 @@ class DefaultStyles { h3: other.h3 ?? h3, paragraph: other.paragraph ?? paragraph, bold: other.bold ?? bold, + subscript: other.subscript ?? subscript, + superscript: other.superscript ?? superscript, italic: other.italic ?? italic, small: other.small ?? small, underline: other.underline ?? underline, diff --git a/lib/src/widgets/text_line.dart b/lib/src/widgets/text_line.dart index 22623f4d..86c35da8 100644 --- a/lib/src/widgets/text_line.dart +++ b/lib/src/widgets/text_line.dart @@ -352,6 +352,14 @@ class _TextLineState extends State { } }); + if (nodeStyle.containsKey(Attribute.script.key)) { + if (nodeStyle.attributes.values.contains(Attribute.subscript)) { + res = _merge(res, defaultStyles.subscript!); + }else if (nodeStyle.attributes.values.contains(Attribute.superscript)) { + res = _merge(res, defaultStyles.superscript!); + } + } + if (nodeStyle.containsKey(Attribute.inlineCode.key)) { res = _merge(res, defaultStyles.inlineCode!.styleFor(lineStyle)); } diff --git a/lib/src/widgets/toolbar.dart b/lib/src/widgets/toolbar.dart index f28eaee9..bc08c027 100644 --- a/lib/src/widgets/toolbar.dart +++ b/lib/src/widgets/toolbar.dart @@ -103,6 +103,8 @@ class QuillToolbar extends StatelessWidget implements PreferredSizeWidget { bool showRedo = true, bool showDirection = false, bool showSearchButton = true, + bool showSubscript = true, + bool showSuperscript = true, List customButtons = const [], ///Map of font sizes in string @@ -208,6 +210,8 @@ class QuillToolbar extends StatelessWidget implements PreferredSizeWidget { ToolbarButtons.fontFamily: 'Font family'.i18n, ToolbarButtons.fontSize: 'Font size'.i18n, ToolbarButtons.bold: 'Bold'.i18n, + ToolbarButtons.subscript: 'Subscript'.i18n, + ToolbarButtons.superscript: 'Superscript'.i18n, ToolbarButtons.italic: 'Italic'.i18n, ToolbarButtons.small: 'Small'.i18n, ToolbarButtons.underline: 'Underline'.i18n, @@ -296,6 +300,29 @@ class QuillToolbar extends StatelessWidget implements PreferredSizeWidget { iconTheme: iconTheme, afterButtonPressed: afterButtonPressed, ), + + if (showSubscript) + ToggleStyleButton( + attribute: Attribute.subscript, + icon: Icons.subscript, + iconSize: toolbarIconSize, + tooltip: buttonTooltips[ToolbarButtons.subscript], + controller: controller, + iconTheme: iconTheme, + afterButtonPressed: afterButtonPressed, + ), + + if (showSuperscript) + ToggleStyleButton( + attribute: Attribute.superscript, + icon: Icons.superscript, + iconSize: toolbarIconSize, + tooltip: buttonTooltips[ToolbarButtons.superscript], + controller: controller, + iconTheme: iconTheme, + afterButtonPressed: afterButtonPressed, + ), + if (showItalicButton) ToggleStyleButton( attribute: Attribute.italic, diff --git a/lib/src/widgets/toolbar/enum.dart b/lib/src/widgets/toolbar/enum.dart index 197bea56..e6719e50 100644 --- a/lib/src/widgets/toolbar/enum.dart +++ b/lib/src/widgets/toolbar/enum.dart @@ -4,6 +4,8 @@ enum ToolbarButtons { fontFamily, fontSize, bold, + subscript, + superscript, italic, small, underline, diff --git a/lib/src/widgets/toolbar/toggle_style_button.dart b/lib/src/widgets/toolbar/toggle_style_button.dart index 1eb0eb57..6800cc7b 100644 --- a/lib/src/widgets/toolbar/toggle_style_button.dart +++ b/lib/src/widgets/toolbar/toggle_style_button.dart @@ -105,7 +105,7 @@ class _ToggleStyleButtonState extends State { } bool _getIsToggled(Map attrs) { - if (widget.attribute.key == Attribute.list.key) { + if (widget.attribute.key == Attribute.list.key || widget.attribute.key == Attribute.script.key) { final attribute = attrs[widget.attribute.key]; if (attribute == null) { return false;