Skip to content

Commit 73fd9cc

Browse files
committed
PAINTROID-796 add clip area command
1 parent 0479b9c commit 73fd9cc

File tree

15 files changed

+290
-23
lines changed

15 files changed

+290
-23
lines changed

lib/core/commands/command_factory/command_factory.dart

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
import 'package:flutter/material.dart';
22
import 'package:paintroid/core/commands/command_implementation/graphic/text_command.dart';
3+
import 'package:paintroid/core/commands/command_implementation/graphic/clip_area_command.dart';
34
import 'package:paintroid/core/commands/command_implementation/graphic/clip_path_command.dart';
45
import 'package:paintroid/core/commands/command_implementation/graphic/line_command.dart';
56
import 'package:paintroid/core/commands/command_implementation/graphic/path_command.dart';
@@ -86,4 +87,10 @@ class CommandFactory {
8687
SprayCommand createSprayCommand(List<Offset> points, Paint paint) {
8788
return SprayCommand(points, paint);
8889
}
90+
91+
ClipAreaCommand createClipAreaCommand(
92+
PathWithActionHistory path,
93+
Paint paint,
94+
) =>
95+
ClipAreaCommand(path, paint);
8996
}
Lines changed: 69 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,69 @@
1+
import 'dart:ui';
2+
3+
import 'package:json_annotation/json_annotation.dart';
4+
import 'package:paintroid/core/commands/command_implementation/graphic/graphic_command.dart';
5+
import 'package:paintroid/core/commands/path_with_action_history.dart';
6+
import 'package:paintroid/core/json_serialization/converter/paint_converter.dart';
7+
import 'package:paintroid/core/json_serialization/converter/path_with_action_history_converter.dart';
8+
import 'package:paintroid/core/json_serialization/versioning/serializer_version.dart';
9+
import 'package:paintroid/core/json_serialization/versioning/version_strategy.dart';
10+
11+
part 'clip_area_command.g.dart';
12+
13+
@JsonSerializable()
14+
class ClipAreaCommand extends GraphicCommand {
15+
@JsonKey(includeToJson: true, includeFromJson: true)
16+
final String type;
17+
@JsonKey(includeToJson: true, includeFromJson: true)
18+
final int version;
19+
20+
@PathWithActionHistoryConverter()
21+
final PathWithActionHistory clipPathData;
22+
23+
ClipAreaCommand(
24+
this.clipPathData,
25+
Paint paint, {
26+
this.type = SerializerType.CLIP_AREA_COMMAND,
27+
int? version,
28+
}) : version = version ??
29+
VersionStrategyManager.strategy.getClipAreaCommandVersion(),
30+
super(paint);
31+
32+
@override
33+
void call(Canvas canvas) {
34+
final Rect canvasBounds = canvas.getLocalClipBounds();
35+
36+
Path areaToClear = Path.combine(
37+
PathOperation.difference,
38+
Path()..addRect(canvasBounds),
39+
clipPathData.path,
40+
);
41+
42+
canvas.drawPath(
43+
areaToClear,
44+
Paint()
45+
..blendMode = BlendMode.clear
46+
..style = PaintingStyle.fill);
47+
}
48+
49+
@override
50+
List<Object?> get props => [paint, clipPathData, type, version];
51+
52+
factory ClipAreaCommand.fromJson(Map<String, dynamic> json) {
53+
int version = json['version'] as int;
54+
55+
switch (version) {
56+
case Version.v1:
57+
return _$ClipAreaCommandFromJson(json);
58+
case Version.v2:
59+
// For different versions of ClipAreaCommand the deserialization
60+
// has to be implemented manually.
61+
// Autogenerated code can only be used for one version
62+
default:
63+
return _$ClipAreaCommandFromJson(json);
64+
}
65+
}
66+
67+
@override
68+
Map<String, dynamic> toJson() => _$ClipAreaCommandToJson(this);
69+
}

lib/core/commands/command_implementation/graphic/clip_area_command.g.dart

Lines changed: 25 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

lib/core/commands/command_manager/command_manager.dart

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -23,13 +23,19 @@ class CommandManager {
2323
_undoStack.add(command);
2424
}
2525

26+
void removeCommand(Command commandToRemove) {
27+
_undoStack.remove(commandToRemove);
28+
}
29+
2630
void setUndoStack(List<Command> commands) {
2731
_undoStack.clear();
2832
_undoStack.addAll(commands);
2933
}
3034

3135
void executeLastCommand(Canvas canvas) {
32-
if (_undoStack.isEmpty) return;
36+
if (_undoStack.isEmpty) {
37+
return;
38+
}
3339
final lastCommand = _undoStack.last;
3440
if (lastCommand is GraphicCommand) {
3541
lastCommand.call(canvas);
@@ -45,7 +51,9 @@ class CommandManager {
4551
}
4652

4753
void discardLastCommand() {
48-
if (_undoStack.isNotEmpty) _undoStack.removeLast();
54+
if (_undoStack.isNotEmpty) {
55+
_undoStack.removeLast();
56+
}
4957
}
5058

5159
void clearUndoStack({Iterable<Command>? newCommands}) {

lib/core/json_serialization/versioning/serializer_version.dart

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ class SerializerVersion {
88
static const int TEXT_COMMAND_VERSION = Version.v1;
99
static const int SPRAY_COMMAND_VERSION = Version.v1;
1010
static const int CLIP_PATH_COMMAND_VERSION = Version.v1;
11+
static const int CLIP_AREA_COMMAND_VERSION = Version.v1;
1112
}
1213

1314
class Version {
@@ -27,4 +28,5 @@ class SerializerType {
2728
static const String TEXT_COMMAND = 'TextCommand';
2829
static const String SPRAY_COMMAND = 'SprayCommand';
2930
static const String CLIP_PATH_COMMAND = 'DashedPathCommand';
31+
static const String CLIP_AREA_COMMAND = 'ClipAreaCommand';
3032
}

lib/core/json_serialization/versioning/version_strategy.dart

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,8 @@ abstract class IVersionStrategy {
1616
int getSprayCommandVersion();
1717

1818
int getClipPathCommandVersion();
19+
20+
int getClipAreaCommandVersion();
1921
}
2022

2123
class ProductionVersionStrategy implements IVersionStrategy {
@@ -45,6 +47,10 @@ class ProductionVersionStrategy implements IVersionStrategy {
4547
@override
4648
int getClipPathCommandVersion() =>
4749
SerializerVersion.CLIP_PATH_COMMAND_VERSION;
50+
51+
@override
52+
int getClipAreaCommandVersion() =>
53+
SerializerVersion.CLIP_AREA_COMMAND_VERSION;
4854
}
4955

5056
class VersionStrategyManager {

lib/core/providers/object/tools/clipping_tool_provider.dart

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ import 'package:paintroid/core/commands/command_manager/command_manager_provider
55
import 'package:paintroid/core/commands/graphic_factory/graphic_factory_provider.dart';
66
import 'package:paintroid/core/enums/tool_types.dart';
77
import 'package:paintroid/core/tools/implementation/clipping_tool.dart';
8+
import 'package:paintroid/core/providers/object/tools/clipping_tool_state_provider.dart';
89

910
part 'clipping_tool_provider.g.dart';
1011

@@ -16,7 +17,8 @@ class ClippingToolProvider extends _$ClippingToolProvider {
1617
commandManager: ref.watch(commandManagerProvider),
1718
commandFactory: ref.watch(commandFactoryProvider),
1819
graphicFactory: ref.watch(graphicFactoryProvider),
19-
type: ToolType.CLIPPING, // Ensure ToolType.CLIPPING is defined
20+
clippingToolState: ref.watch(clippingToolState.notifier),
21+
type: ToolType.CLIPPING,
2022
);
2123
}
2224
}

lib/core/providers/object/tools/clipping_tool_provider.g.dart

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
import 'package:riverpod_annotation/riverpod_annotation.dart';
2+
3+
part 'clipping_tool_state_provider.g.dart';
4+
5+
@riverpod
6+
class ClippingToolState extends _$ClippingToolState {
7+
@override
8+
bool build() {
9+
return false;
10+
}
11+
12+
void setHasActiveClipPath(bool hasActive) {
13+
state = hasActive;
14+
}
15+
16+
void clearClipPath() {
17+
state = false;
18+
}
19+
20+
bool get hasActiveClipPath => state;
21+
}

lib/core/providers/object/tools/clipping_tool_state_provider.g.dart

Lines changed: 26 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)