From 264fc4081aa266134b7ec8074ab86d5a94db509a Mon Sep 17 00:00:00 2001 From: CodeDoctorDE Date: Thu, 28 Dec 2023 09:28:26 +0100 Subject: [PATCH] Add scale to label toolbar and unify selection view --- api/lib/src/models/element.dart | 9 ++-- app/lib/handlers/label.dart | 2 +- app/lib/selections/elements/element.dart | 4 +- app/lib/selections/elements/text.dart | 33 +++++++++++--- app/lib/views/toolbar/label.dart | 45 ++++++++++++++++++- .../metadata/android/en-US/changelogs/86.txt | 3 ++ 6 files changed, 80 insertions(+), 16 deletions(-) diff --git a/api/lib/src/models/element.dart b/api/lib/src/models/element.dart index 0703e6b6650d..cbe677d719e4 100644 --- a/api/lib/src/models/element.dart +++ b/api/lib/src/models/element.dart @@ -53,7 +53,8 @@ abstract class PathElement { PathProperty get property; } -mixin LabelElement { +mixin LabelElement on PadElement { + @override String get layer; Point get position; double get scale; @@ -62,8 +63,7 @@ mixin LabelElement { int get foreground; AreaProperty get areaProperty { - final element = this as PadElement; - return element.maybeMap( + return maybeMap( markdown: (e) => e.areaProperty, text: (e) => e.area.areaProperty, orElse: () => throw UnimplementedError(), @@ -71,8 +71,7 @@ mixin LabelElement { } String get text { - final element = this as PadElement; - return element.maybeMap( + return maybeMap( markdown: (e) => e.text, text: (e) => e.area.paragraph.text, orElse: () => throw UnimplementedError(), diff --git a/app/lib/handlers/label.dart b/app/lib/handlers/label.dart index 92e850ba03f7..6726ae50e81a 100644 --- a/app/lib/handlers/label.dart +++ b/app/lib/handlers/label.dart @@ -159,7 +159,7 @@ class LabelHandler extends Handler } else { final page = context.getPage(); if (page == null) return; - final index = page.content.indexOf(labelRenderer.element as PadElement); + final index = page.content.indexOf(labelRenderer.element); context.getDocumentBloc().add(ElementsRemoved([index])); _context = _createContext(document, element: labelRenderer.element); } diff --git a/app/lib/selections/elements/element.dart b/app/lib/selections/elements/element.dart index b1c23e15b315..3b40dc83aed4 100644 --- a/app/lib/selections/elements/element.dart +++ b/app/lib/selections/elements/element.dart @@ -12,8 +12,8 @@ class ElementSelection extends Selection> { return ImageElementSelection([selected as Renderer]) as ElementSelection; } - if (selected is Renderer) { - return TextElementSelection([selected as Renderer]) + if (selected is Renderer) { + return LabelElementSelection([selected as Renderer]) as ElementSelection; } if (selected is Renderer) { diff --git a/app/lib/selections/elements/text.dart b/app/lib/selections/elements/text.dart index 609fe82bc8ad..d4df457d112e 100644 --- a/app/lib/selections/elements/text.dart +++ b/app/lib/selections/elements/text.dart @@ -1,25 +1,46 @@ part of '../selection.dart'; -class TextElementSelection extends ElementSelection { - TextElementSelection(super.selected); +class LabelElementSelection extends ElementSelection { + LabelElementSelection(super.selected); @override List buildProperties(BuildContext context) { final element = selected.first.element; return [ ...super.buildProperties(context), + ExactSlider( + header: Text(AppLocalizations.of(context).scale), + min: 0.1, + max: 15, + value: element.scale, + defaultValue: 5, + onChangeEnd: (value) => updateElements( + context, + elements + .map((e) => e.maybeMap( + text: (e) => e.copyWith(scale: value), + markdown: (e) => e.copyWith(scale: value), + orElse: () => e)) + .toList()), + ), ConstraintView( initialConstraint: element.constraint, - onChanged: (constraint) => updateElements(context, - elements.map((e) => e.copyWith(constraint: constraint)).toList()), + onChanged: (constraint) => updateElements( + context, + elements + .map((e) => e.maybeMap( + text: (e) => e.copyWith(constraint: constraint), + markdown: (e) => e.copyWith(constraint: constraint), + orElse: () => e)) + .toList()), ), ]; } @override Selection insert(element) { - if (element is Renderer) { - return TextElementSelection([...selected, element]); + if (element is Renderer) { + return LabelElementSelection([...selected, element]); } return super.insert(element); } diff --git a/app/lib/views/toolbar/label.dart b/app/lib/views/toolbar/label.dart index 26726d0b206e..8b21acc41dc4 100644 --- a/app/lib/views/toolbar/label.dart +++ b/app/lib/views/toolbar/label.dart @@ -35,7 +35,8 @@ class LabelToolbarView extends StatefulWidget implements PreferredSizeWidget { class _LabelToolbarViewState extends State { final ScrollController _scrollController = ScrollController(); - final TextEditingController _sizeController = TextEditingController(); + final TextEditingController _sizeController = TextEditingController(), + _scaleController = TextEditingController(); final GlobalKey _paragraphKey = GlobalKey(), _spanKey = GlobalKey(); @@ -88,6 +89,8 @@ class _LabelToolbarViewState extends State { value.mapOrNull(text: (e) => e.getDefinedForcedSpanProperty(document)); final styleSheet = value.styleSheet; final style = styleSheet.resolveStyle(document); + _scaleController.text = + (value.labelElement?.scale ?? value.tool.scale).toString(); _sizeController.text = span?.getSize(paragraph).toString() ?? ''; var paragraphSelection = paragraph.mapOrNull(named: (value) => value.name); final paragraphSelections = [ @@ -254,8 +257,46 @@ class _LabelToolbarViewState extends State { AppLocalizations.of(context).chooseLabelMode, ), ), + const SizedBox(width: 16), + SizedBox( + width: 100, + child: TextFormField( + decoration: InputDecoration( + labelText: AppLocalizations.of(context).scale, + filled: true, + floatingLabelAlignment: + FloatingLabelAlignment.center, + alignLabelWithHint: true, + ), + textAlign: TextAlign.center, + keyboardType: TextInputType.number, + controller: _scaleController, + onFieldSubmitted: (current) { + final newScale = double.tryParse(current); + if (newScale == null) return; + final element = value.element; + if (element == null) { + widget.onChanged(value.copyWith( + tool: value.tool.copyWith( + scale: newScale, + ), + )); + return; + } + widget.onChanged( + value.map( + text: (e) => e.copyWith( + element: e.element! + .copyWith(scale: newScale)), + markdown: (e) => e.copyWith( + element: e.element! + .copyWith(scale: newScale))), + ); + }, + ), + ), if (value is TextContext) ...[ - const SizedBox(width: 16), + const SizedBox(width: 8), IconButton( icon: const PhosphorIcon(PhosphorIconsLight.article), diff --git a/fastlane/metadata/android/en-US/changelogs/86.txt b/fastlane/metadata/android/en-US/changelogs/86.txt index 8fb3f612e20f..7614620dd8d5 100644 --- a/fastlane/metadata/android/en-US/changelogs/86.txt +++ b/fastlane/metadata/android/en-US/changelogs/86.txt @@ -1,3 +1,6 @@ * Add support for multi character input languages ([#539](https://github.com/LinwoodDev/Butterfly/issues/539)) +* Add scale to label toolbar +* Add scale to label selection view +* Add markdown element selection view * Fix moving data directory ([#562](https://github.com/LinwoodDev/Butterfly/issues/562)) * Fix various issues with the label tool \ No newline at end of file