diff --git a/app/lib/l10n/app_en.arb b/app/lib/l10n/app_en.arb index b2c6b3b078cc..d4e6601d992a 100644 --- a/app/lib/l10n/app_en.arb +++ b/app/lib/l10n/app_en.arb @@ -618,6 +618,7 @@ }, "inputGestures": "Input gestures", "nativeTitleBar": "Native title bar", + "mode": "Mode", "syncMode": "Sync mode", "connection": "Connection", "always": "Always", @@ -919,6 +920,7 @@ "bringForward": "Bring forward", "sendBackward": "Send backward", "rotation": "Rotation", + "direction": "Direction", "onlyAvailableLargerScreen": "Only available on larger screens", "toolbarPosition": "Toolbar position", "rotate": "Rotate", diff --git a/app/lib/selections/selection.dart b/app/lib/selections/selection.dart index bd897a23d464..8fc12cc153db 100644 --- a/app/lib/selections/selection.dart +++ b/app/lib/selections/selection.dart @@ -41,6 +41,7 @@ part 'tools/eraser.dart'; part 'tools/grid.dart'; part 'tools/label.dart'; part 'tools/laser.dart'; +part 'tools/selection.dart'; part 'tools/path_eraser.dart'; part 'tools/pen.dart'; part 'tools/polygon.dart'; @@ -48,6 +49,7 @@ part 'tools/ruler.dart'; part 'tools/shape.dart'; part 'tools/stamp.dart'; part 'tools/texture.dart'; +part 'tools/spacer.dart'; part 'properties/property.dart'; part 'properties/pen.dart'; diff --git a/app/lib/selections/tools/selection.dart b/app/lib/selections/tools/selection.dart new file mode 100644 index 000000000000..a8962ad9abcd --- /dev/null +++ b/app/lib/selections/tools/selection.dart @@ -0,0 +1,44 @@ +part of '../selection.dart'; + +class SelectToolSelection extends ToolSelection { + SelectToolSelection(super.selected); + + @override + List buildProperties(BuildContext context) { + final loc = AppLocalizations.of(context); + return [ + ...super.buildProperties(context), + ListTile( + title: Text(loc.mode), + trailing: DropdownMenu( + initialSelection: selected.first.mode, + dropdownMenuEntries: SelectMode.values + .map( + (e) => DropdownMenuEntry( + label: e.getLocalizedName(context), + leadingIcon: Icon(e.icon(PhosphorIconsStyle.light)), + value: e, + ), + ) + .toList(), + onSelected: (value) { + if (value != null) { + update( + context, + selected.map((e) => e.copyWith(mode: value)).toList(), + ); + } + }, + ), + ), + ]; + } + + @override + Selection insert(dynamic element) { + if (element is SelectTool) { + return SelectToolSelection([...selected, element]); + } + return super.insert(element); + } +} diff --git a/app/lib/selections/tools/spacer.dart b/app/lib/selections/tools/spacer.dart new file mode 100644 index 000000000000..b83f463eebc5 --- /dev/null +++ b/app/lib/selections/tools/spacer.dart @@ -0,0 +1,44 @@ +part of '../selection.dart'; + +class SpacerToolSelection extends ToolSelection { + SpacerToolSelection(super.selected); + + @override + List buildProperties(BuildContext context) { + final loc = AppLocalizations.of(context); + return [ + ...super.buildProperties(context), + ListTile( + title: Text(loc.direction), + trailing: DropdownMenu( + initialSelection: selected.first.axis, + dropdownMenuEntries: Axis2D.values + .map( + (e) => DropdownMenuEntry( + label: e.getLocalizedName(context), + leadingIcon: Icon(e.icon(PhosphorIconsStyle.light)), + value: e, + ), + ) + .toList(), + onSelected: (value) { + if (value != null) { + update( + context, + selected.map((e) => e.copyWith(axis: value)).toList(), + ); + } + }, + ), + ), + ]; + } + + @override + Selection insert(dynamic element) { + if (element is SpacerTool) { + return SpacerToolSelection([...selected, element]); + } + return super.insert(element); + } +} diff --git a/app/lib/selections/tools/tool.dart b/app/lib/selections/tools/tool.dart index e901a91ff0d2..f9fba3d81bfb 100644 --- a/app/lib/selections/tools/tool.dart +++ b/app/lib/selections/tools/tool.dart @@ -19,6 +19,8 @@ class ToolSelection extends Selection { TextureTool e => TextureToolSelection([e]), BarcodeTool e => BarcodeToolSelection([e]), PolygonTool e => PolygonToolSelection([e]), + SelectTool e => SelectToolSelection([e]), + SpacerTool e => SpacerToolSelection([e]), _ => ToolSelection([selected]), } as ToolSelection; diff --git a/app/lib/visualizer/tool.dart b/app/lib/visualizer/tool.dart index 953be4ecb1d2..77d8276c1aac 100644 --- a/app/lib/visualizer/tool.dart +++ b/app/lib/visualizer/tool.dart @@ -21,6 +21,7 @@ extension ToolCategoryVisualizer on ToolCategory { ToolCategory.action => PhosphorIcons.play, ToolCategory.view => PhosphorIcons.eye, }; + String getLocalizedName(BuildContext context) => switch (this) { ToolCategory.normal => AppLocalizations.of(context).normal, ToolCategory.import => AppLocalizations.of(context).import, @@ -36,6 +37,7 @@ extension BarcodeTypeVisualizer on BarcodeType { BarcodeType.dataMatrix => AppLocalizations.of(context).dataMatrix, BarcodeType.code128 => AppLocalizations.of(context).code128, }; + IconGetter get icon => switch (this) { BarcodeType.qrCode => PhosphorIcons.qrCode, BarcodeType.dataMatrix => PhosphorIcons.scan, @@ -43,6 +45,30 @@ extension BarcodeTypeVisualizer on BarcodeType { }; } +extension SelectModeVisualizer on SelectMode { + String getLocalizedName(BuildContext context) => switch (this) { + SelectMode.rectangle => AppLocalizations.of(context).rectangle, + SelectMode.lasso => AppLocalizations.of(context).lasso, + }; + + IconGetter get icon => switch (this) { + SelectMode.rectangle => PhosphorIcons.selection, + SelectMode.lasso => PhosphorIcons.lasso, + }; +} + +extension Axis2DVisualizer on Axis2D { + String getLocalizedName(BuildContext context) => switch (this) { + Axis2D.horizontal => AppLocalizations.of(context).horizontal, + Axis2D.vertical => AppLocalizations.of(context).vertical, + }; + + IconGetter get icon => switch (this) { + Axis2D.horizontal => PhosphorIcons.splitHorizontal, + Axis2D.vertical => PhosphorIcons.splitVertical, + }; +} + extension ToolVisualizer on Tool { String getDisplay(BuildContext context) { if (name.trim().isEmpty) return getLocalizedName(context); @@ -83,9 +109,8 @@ extension ToolVisualizer on Tool { String getLocalizedCaption(BuildContext context) { final loc = AppLocalizations.of(context); return switch (this) { - SpacerTool e => - e.axis == Axis2D.horizontal ? loc.horizontal : loc.vertical, - SelectTool e => e.mode == SelectMode.lasso ? loc.lasso : loc.rectangle, + SpacerTool e => e.axis.getLocalizedName(context), + SelectTool e => e.mode.getLocalizedName(context), ExportTool e => switch (e.options) { ImageExportOptions() => loc.image, SvgExportOptions() => loc.svg,