Skip to content

Commit

Permalink
Add grid and ruler selections
Browse files Browse the repository at this point in the history
  • Loading branch information
CodeDoctorDE committed Dec 29, 2024
1 parent 4b24340 commit 3a49114
Show file tree
Hide file tree
Showing 15 changed files with 155 additions and 28 deletions.
2 changes: 1 addition & 1 deletion api/lib/src/models/tool.dart
Original file line number Diff line number Diff line change
Expand Up @@ -195,7 +195,7 @@ sealed class Tool with _$Tool {
factory Tool.ruler({
@Default('') String name,
@Default('') String displayIcon,
@Default(SRGBColor.black) @ColorJsonConverter() SRGBColor gridColor,
@ColorJsonConverter() SRGBColor? color,
}) = RulerTool;

factory Tool.grid({
Expand Down
23 changes: 11 additions & 12 deletions api/lib/src/models/tool.freezed.dart
Original file line number Diff line number Diff line change
Expand Up @@ -2799,7 +2799,7 @@ abstract class _$$RulerToolImplCopyWith<$Res> implements $ToolCopyWith<$Res> {
$Res call(
{String name,
String displayIcon,
@ColorJsonConverter() SRGBColor gridColor});
@ColorJsonConverter() SRGBColor? color});
}

/// @nodoc
Expand All @@ -2817,7 +2817,7 @@ class __$$RulerToolImplCopyWithImpl<$Res>
$Res call({
Object? name = null,
Object? displayIcon = null,
Object? gridColor = null,
Object? color = freezed,
}) {
return _then(_$RulerToolImpl(
name: null == name
Expand All @@ -2828,10 +2828,10 @@ class __$$RulerToolImplCopyWithImpl<$Res>
? _value.displayIcon
: displayIcon // ignore: cast_nullable_to_non_nullable
as String,
gridColor: null == gridColor
? _value.gridColor
: gridColor // ignore: cast_nullable_to_non_nullable
as SRGBColor,
color: freezed == color
? _value.color
: color // ignore: cast_nullable_to_non_nullable
as SRGBColor?,
));
}
}
Expand All @@ -2842,7 +2842,7 @@ class _$RulerToolImpl extends RulerTool {
_$RulerToolImpl(
{this.name = '',
this.displayIcon = '',
@ColorJsonConverter() this.gridColor = SRGBColor.black,
@ColorJsonConverter() this.color,
final String? $type})
: $type = $type ?? 'ruler',
super._();
Expand All @@ -2857,16 +2857,15 @@ class _$RulerToolImpl extends RulerTool {
@JsonKey()
final String displayIcon;
@override
@JsonKey()
@ColorJsonConverter()
final SRGBColor gridColor;
final SRGBColor? color;

@JsonKey(name: 'type')
final String $type;

@override
String toString() {
return 'Tool.ruler(name: $name, displayIcon: $displayIcon, gridColor: $gridColor)';
return 'Tool.ruler(name: $name, displayIcon: $displayIcon, color: $color)';
}

/// Create a copy of Tool
Expand All @@ -2889,7 +2888,7 @@ abstract class RulerTool extends Tool {
factory RulerTool(
{final String name,
final String displayIcon,
@ColorJsonConverter() final SRGBColor gridColor}) = _$RulerToolImpl;
@ColorJsonConverter() final SRGBColor? color}) = _$RulerToolImpl;
RulerTool._() : super._();

factory RulerTool.fromJson(Map<String, dynamic> json) =
Expand All @@ -2900,7 +2899,7 @@ abstract class RulerTool extends Tool {
@override
String get displayIcon;
@ColorJsonConverter()
SRGBColor get gridColor;
SRGBColor? get color;

/// Create a copy of Tool
/// with the given fields replaced by the non-null parameter values.
Expand Down
21 changes: 16 additions & 5 deletions api/lib/src/models/tool.g.dart

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

5 changes: 3 additions & 2 deletions app/lib/cubits/current_index.dart
Original file line number Diff line number Diff line change
Expand Up @@ -319,15 +319,16 @@ class CurrentIndexCubit extends Cubit<CurrentIndex> {
Handler<Tool>? handler;
bool needsDispose = false;
if (state.index == index) {
handler = fetchHandler<Handler<Tool>>();
handler = fetchHandler<Handler<Tool>>(disableTemporary: true);
} else if (state.toggleableHandlers.containsKey(index)) {
handler = state.toggleableHandlers[index];
}
if (handler == null) {
List<Tool> tools = const [];
final blocState = bloc.state;
if (blocState is DocumentLoaded) tools = blocState.info.tools;
handler = Handler.fromTool(tools.elementAtOrNull(index));
final tool = tools.elementAtOrNull(index) ?? HandTool();
handler = Handler.fromTool(tool);
needsDispose = true;
}
final result = callback(handler);
Expand Down
18 changes: 18 additions & 0 deletions app/lib/dialogs/import/add.dart
Original file line number Diff line number Diff line change
Expand Up @@ -209,6 +209,16 @@ class _AddDialogState extends State<AddDialog> {
.toLowerCase()
.contains(search.toLowerCase()))
.toList();
final view = [
Tool.ruler,
Tool.grid,
]
.map((e) => e())
.where((e) => e
.getLocalizedName(context)
.toLowerCase()
.contains(search.toLowerCase()))
.toList();
return ListView(
shrinkWrap: true,
children: [
Expand Down Expand Up @@ -306,6 +316,14 @@ class _AddDialogState extends State<AddDialog> {
),
const SizedBox(height: 16),
],
if (view.isNotEmpty) ...[
_ToolsListView(
isMobile: isMobile,
title: AppLocalizations.of(context).view,
children: view.map(buildTool).toList(),
),
const SizedBox(height: 16),
],
],
);
}),
Expand Down
4 changes: 4 additions & 0 deletions app/lib/handlers/hand.dart
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,10 @@ class GeneralHandHandler<T> extends Handler<T> {
_moved ? SystemMouseCursors.grabbing : SystemMouseCursors.grab;
}

class FallbackHandler<T extends Tool> extends GeneralHandHandler<T> {
FallbackHandler(super.data);
}

class HandHandler extends GeneralHandHandler<HandTool> {
HandHandler([HandTool? tool]) : super(tool ?? HandTool());
}
4 changes: 2 additions & 2 deletions app/lib/handlers/handler.dart
Original file line number Diff line number Diff line change
Expand Up @@ -221,7 +221,7 @@ abstract class Handler<T> {
return Handler.fromTool(tool);
}

static Handler<T> fromTool<T extends Tool>(T? tool) {
static Handler<T> fromTool<T extends Tool>(T tool) {
return switch (tool) {
HandTool() => HandHandler(tool),
SelectTool() => SelectHandler(tool),
Expand All @@ -244,7 +244,7 @@ abstract class Handler<T> {
AssetTool() => AssetHandler(tool),
EyeDropperTool() => EyeDropperHandler(tool),
ExportTool() => ExportHandler(tool),
_ => GeneralHandHandler(tool),
_ => FallbackHandler<T>(tool),
} as Handler<T>;
}

Expand Down
4 changes: 2 additions & 2 deletions app/lib/handlers/import.dart
Original file line number Diff line number Diff line change
Expand Up @@ -61,8 +61,8 @@ class ImportHandler extends Handler<ImportTool> {
.copyWith(id: createUniqueId()))
.nonNulls
.toList()));
context.refresh();
context.bake();
await context.refresh();
await context.bake();
}

@override
Expand Down
5 changes: 3 additions & 2 deletions app/lib/l10n/app_en.arb
Original file line number Diff line number Diff line change
Expand Up @@ -626,13 +626,14 @@
"renderResolution": "Render resolution",
"translate": "Translate",
"unencrypted": "Unencrypted",
"encrypted": "Decrypted",
"encrypted": "Encrypted",
"encryptDocumentMessage": "Click to encrypt the document",
"unencryptDocumentMessage": "Click to unencrypt the document",
"unencrypt": "Unencrypt",
"encrypt": "Encrypt",
"encryptWarning": "This will encrypt the document. You will need to remember the password to decrypt it.",
"unencryptWarning": "This will unencrypt the document. The password will be removed and everyone with access will be able to open it.",
"confirmPassword": "Confirm password",
"passwordMismatch": "The passwords do not match"
"passwordMismatch": "The passwords do not match",
"action": "Action"
}
2 changes: 2 additions & 0 deletions app/lib/selections/selection.dart
Original file line number Diff line number Diff line change
Expand Up @@ -31,10 +31,12 @@ part 'tools/tool.dart';
part 'tools/hand.dart';
part 'tools/area.dart';
part 'tools/eraser.dart';
part 'tools/grid.dart';
part 'tools/label.dart';
part 'tools/laser.dart';
part 'tools/path_eraser.dart';
part 'tools/pen.dart';
part 'tools/ruler.dart';
part 'tools/shape.dart';
part 'tools/stamp.dart';
part 'tools/texture.dart';
Expand Down
40 changes: 40 additions & 0 deletions app/lib/selections/tools/grid.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
part of '../selection.dart';

class GridToolSelection extends ToolSelection<GridTool> {
GridToolSelection(super.selected);

@override
List<Widget> buildProperties(BuildContext context) {
return [
...super.buildProperties(context),
const SizedBox(height: 8),
OffsetPropertyView(
title: Text(AppLocalizations.of(context).size),
value: Offset(selected.first.xSize, selected.first.ySize),
onChanged: (value) => update(
context,
selected
.map((e) => e.copyWith(xSize: value.dx, ySize: value.dy))
.toList(),
),
),
const SizedBox(height: 8),
ColorField(
value: selected.first.color,
onChanged: (value) => update(
context,
selected.map((e) => e.copyWith(color: value)).toList(),
),
title: Text(LeapLocalizations.of(context).color),
),
];
}

@override
Selection insert(dynamic element) {
if (element is GridTool) {
return GridToolSelection([...selected, element]);
}
return super.insert(element);
}
}
41 changes: 41 additions & 0 deletions app/lib/selections/tools/ruler.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
part of '../selection.dart';

class RulerToolSelection extends ToolSelection<RulerTool> {
RulerToolSelection(super.selected);

@override
List<Widget> buildProperties(BuildContext context) {
return [
...super.buildProperties(context),
ColorField(
title: Text(LeapLocalizations.of(context).color),
value:
selected.first.color?.withValues(a: 255) ?? SRGBColor.transparent,
subtitle: selected.first.color == null
? Text(AppLocalizations.of(context).notSet)
: null,
leading: selected.first.color == null
? null
: IconButton(
icon: const Icon(PhosphorIconsLight.trash),
onPressed: () => update(
context,
selected.map((e) => e.copyWith(color: null)).toList(),
),
),
onChanged: (value) => update(
context,
selected.map((e) => e.copyWith(color: value)).toList(),
),
),
];
}

@override
Selection insert(dynamic element) {
if (element is RulerTool) {
return RulerToolSelection([...selected, element]);
}
return super.insert(element);
}
}
2 changes: 2 additions & 0 deletions app/lib/selections/tools/tool.dart
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,9 @@ class ToolSelection<T extends Tool> extends Selection<T> {
EraserTool e => EraserToolSelection([e]),
PathEraserTool e => PathEraserToolSelection([e]),
AreaTool e => AreaToolSelection([e]),
GridTool e => GridToolSelection([e]),
LaserTool e => LaserToolSelection([e]),
RulerTool e => RulerToolSelection([e]),
ShapeTool e => ShapeToolSelection([e]),
StampTool e => StampToolSelection([e]),
TextureTool e => TextureToolSelection([e]),
Expand Down
3 changes: 2 additions & 1 deletion app/lib/services/import.dart
Original file line number Diff line number Diff line change
Expand Up @@ -229,7 +229,8 @@ class ImportService {
password = await showDialog<String>(
context: context,
builder: (context) => NameDialog(
title: AppLocalizations.of(context).password,
title: AppLocalizations.of(context).encrypted,
hint: AppLocalizations.of(context).password,
button: AppLocalizations.of(context).open,
obscureText: true,
),
Expand Down
9 changes: 8 additions & 1 deletion app/lib/visualizer/tool.dart
Original file line number Diff line number Diff line change
Expand Up @@ -19,9 +19,16 @@ extension ToolCategoryVisualizer on ToolCategory {
ToolCategory.normal => PhosphorIcons.paintBrush,
ToolCategory.import => PhosphorIcons.arrowSquareIn,
ToolCategory.surface => PhosphorIcons.monitor,
ToolCategory.action => PhosphorIcons.arrowClockwise,
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,
ToolCategory.surface => AppLocalizations.of(context).surface,
ToolCategory.action => AppLocalizations.of(context).action,
ToolCategory.view => AppLocalizations.of(context).view,
};
}

extension ToolVisualizer on Tool {
Expand Down

0 comments on commit 3a49114

Please sign in to comment.