From 61ee34af7f5e0e7df2ecd96b51c951fd00e49e1c Mon Sep 17 00:00:00 2001 From: Amit-Matth Date: Fri, 7 Aug 2026 18:50:10 +0530 Subject: [PATCH] PAINTROID-814 add import tool --- hex_dump.ps1 | 19 + lib/core/commands/command_painter.dart | 5 + .../object/tools/import_tool_provider.dart | 29 + .../object/tools/import_tool_provider.g.dart | 27 + .../state/toolbox_state_provider.dart | 11 + .../state/toolbox_state_provider.g.dart | 2 +- .../tools/implementation/import_tool.dart | 156 ++ lib/core/tools/tool.dart | 3 +- .../components/top_bar/top_app_bar.dart | 11 +- test/unit/tools/import_tool_test.dart | 147 ++ test/unit/tools/import_tool_test.mocks.dart | 1331 +++++++++++++++++ .../workspace_page/import_tool_test.dart | 52 + 12 files changed, 1787 insertions(+), 6 deletions(-) create mode 100644 hex_dump.ps1 create mode 100644 lib/core/providers/object/tools/import_tool_provider.dart create mode 100644 lib/core/providers/object/tools/import_tool_provider.g.dart create mode 100644 lib/core/tools/implementation/import_tool.dart create mode 100644 test/unit/tools/import_tool_test.dart create mode 100644 test/unit/tools/import_tool_test.mocks.dart create mode 100644 test/widget/workspace_page/import_tool_test.dart diff --git a/hex_dump.ps1 b/hex_dump.ps1 new file mode 100644 index 00000000..7f5ae5d3 --- /dev/null +++ b/hex_dump.ps1 @@ -0,0 +1,19 @@ +foreach ($fname in @("image1.catrobat-image", "image2.catrobat-image", "img.catrobat-image")) { + $path = "C:\Users\amitm\Desktop\New folder\$fname" + $bytes = [System.IO.File]::ReadAllBytes($path) + Write-Host "=== $fname (size: $($bytes.Length)) ===" + Write-Host "First 100 bytes (hex):" + $hexLine = "" + for ($i = 0; $i -lt 100 -and $i -lt $bytes.Length; $i++) { + $hexLine += "{0:X2} " -f $bytes[$i] + if (($i + 1) % 16 -eq 0) { + Write-Host (" {0:D4}: {1}" -f ($i - 15), $hexLine) + $hexLine = "" + } + } + if ($hexLine -ne "") { + $padI = [math]::Floor(($i-1) / 16) * 16 + Write-Host (" {0:D4}: {1}" -f $padI, $hexLine) + } + Write-Host "" +} diff --git a/lib/core/commands/command_painter.dart b/lib/core/commands/command_painter.dart index aca3588f..66501ac8 100644 --- a/lib/core/commands/command_painter.dart +++ b/lib/core/commands/command_painter.dart @@ -7,6 +7,7 @@ import 'package:paintroid/core/providers/state/canvas_state_provider.dart'; import 'package:paintroid/core/providers/state/paint_provider.dart'; import 'package:paintroid/core/providers/state/toolbox_state_provider.dart'; import 'package:paintroid/core/tools/implementation/clipboard_tool.dart'; +import 'package:paintroid/core/tools/implementation/import_tool.dart'; import 'package:paintroid/core/tools/implementation/cursor_tool.dart'; import 'package:paintroid/core/tools/implementation/shapes_tool.dart'; import 'package:paintroid/core/tools/implementation/text_tool.dart'; @@ -65,6 +66,10 @@ class CommandPainter extends CustomPainter { break; case ToolType.CLIPBOARD: (currentTool as ClipboardTool).paint(canvas, size); + break; + case ToolType.IMPORT: + (currentTool as ImportTool).paint(canvas, size); + break; case ToolType.TEXT: (currentTool as TextTool).drawGuides(canvas, ref.read(paintProvider)); break; diff --git a/lib/core/providers/object/tools/import_tool_provider.dart b/lib/core/providers/object/tools/import_tool_provider.dart new file mode 100644 index 00000000..8e8dcdd4 --- /dev/null +++ b/lib/core/providers/object/tools/import_tool_provider.dart @@ -0,0 +1,29 @@ +import 'dart:ui'; + +import 'package:paintroid/core/enums/tool_types.dart'; +import 'package:paintroid/core/providers/state/canvas_state_provider.dart'; +import 'package:paintroid/core/tools/bounding_box.dart'; +import 'package:riverpod_annotation/riverpod_annotation.dart'; +import 'package:paintroid/core/commands/command_factory/command_factory_provider.dart'; +import 'package:paintroid/core/commands/command_manager/command_manager_provider.dart'; +import 'package:paintroid/core/tools/implementation/import_tool.dart'; + +part 'import_tool_provider.g.dart'; + +@Riverpod(keepAlive: true) +class ImportToolProvider extends _$ImportToolProvider { + @override + ImportTool build() { + Rect initialBoundingBox = Rect.fromCenter( + center: ref.read(canvasStateProvider).size.center(Offset.zero), + width: 300, + height: 300, + ); + return ImportTool( + commandManager: ref.watch(commandManagerProvider), + commandFactory: ref.watch(commandFactoryProvider), + boundingBox: BoundingBox.fromRect(initialBoundingBox), + type: ToolType.IMPORT, + ); + } +} diff --git a/lib/core/providers/object/tools/import_tool_provider.g.dart b/lib/core/providers/object/tools/import_tool_provider.g.dart new file mode 100644 index 00000000..3dac1839 --- /dev/null +++ b/lib/core/providers/object/tools/import_tool_provider.g.dart @@ -0,0 +1,27 @@ +// GENERATED CODE - DO NOT MODIFY BY HAND + +part of 'import_tool_provider.dart'; + +// ************************************************************************** +// RiverpodGenerator +// ************************************************************************** + +String _$importToolProviderHash() => + r'0c9c26ef432d992b740ee717780d9cec5c17e739'; + +/// See also [ImportToolProvider]. +@ProviderFor(ImportToolProvider) +final importToolProvider = + NotifierProvider.internal( + ImportToolProvider.new, + name: r'importToolProvider', + debugGetCreateSourceHash: const bool.fromEnvironment('dart.vm.product') + ? null + : _$importToolProviderHash, + dependencies: null, + allTransitiveDependencies: null, +); + +typedef _$ImportToolProvider = Notifier; +// ignore_for_file: type=lint +// ignore_for_file: subtype_of_sealed_class, invalid_use_of_internal_member, invalid_use_of_visible_for_testing_member diff --git a/lib/core/providers/state/toolbox_state_provider.dart b/lib/core/providers/state/toolbox_state_provider.dart index b7fb5e47..2f4c26fa 100644 --- a/lib/core/providers/state/toolbox_state_provider.dart +++ b/lib/core/providers/state/toolbox_state_provider.dart @@ -5,6 +5,9 @@ import 'package:paintroid/core/enums/tool_types.dart'; import 'package:paintroid/core/providers/object/canvas_painter_provider.dart'; import 'package:paintroid/core/providers/object/tools/brush_tool_provider.dart'; import 'package:paintroid/core/providers/object/tools/clipboard_tool_provider.dart'; +import 'package:paintroid/core/providers/object/tools/import_tool_provider.dart'; +import 'package:paintroid/core/providers/object/load_image_from_photo_library.dart'; +import 'package:paintroid/core/tools/implementation/import_tool.dart'; import 'package:paintroid/core/providers/object/tools/cursor_tool_provider.dart'; import 'package:paintroid/core/providers/object/tools/eraser_tool_provider.dart'; import 'package:paintroid/core/providers/object/tools/hand_tool_provider.dart'; @@ -95,6 +98,14 @@ class ToolBoxStateProvider extends _$ToolBoxStateProvider { state = state.copyWith(currentTool: ref.read(clipboardToolProvider)); ref.read(canvasPainterProvider.notifier).repaint(); break; + case ToolType.IMPORT: + final importTool = ref.read(importToolProvider); + state = state.copyWith(currentTool: importTool); + ref.read(canvasPainterProvider.notifier).repaint(); + importTool.pickImage(ref.read(LoadImageFromPhotoLibrary.provider)).then((_) { + ref.read(canvasPainterProvider.notifier).repaint(); + }); + break; case ToolType.PIPETTE: state = state.copyWith(currentTool: ref.read(pipetteToolProvider)); break; diff --git a/lib/core/providers/state/toolbox_state_provider.g.dart b/lib/core/providers/state/toolbox_state_provider.g.dart index f6c224e0..fcc1cf67 100644 --- a/lib/core/providers/state/toolbox_state_provider.g.dart +++ b/lib/core/providers/state/toolbox_state_provider.g.dart @@ -7,7 +7,7 @@ part of 'toolbox_state_provider.dart'; // ************************************************************************** String _$toolBoxStateProviderHash() => - r'c6fa1661445899c5abd6725b49ccbaf6ca3340e8'; + r'8907c8eec404f9d9cedd4066cfe7ea0880b555f4'; /// See also [ToolBoxStateProvider]. @ProviderFor(ToolBoxStateProvider) diff --git a/lib/core/tools/implementation/import_tool.dart b/lib/core/tools/implementation/import_tool.dart new file mode 100644 index 00000000..4b15aec5 --- /dev/null +++ b/lib/core/tools/implementation/import_tool.dart @@ -0,0 +1,156 @@ +import 'dart:math' as dart_math; +import 'dart:ui' as ui; + +import 'package:flutter/material.dart'; +import 'package:paintroid/core/enums/bounding_box_action.dart'; +import 'package:paintroid/core/providers/object/load_image_from_photo_library.dart'; +import 'package:paintroid/core/tools/bounding_box.dart'; +import 'package:paintroid/core/tools/tool.dart'; + +class ImportTool extends Tool { + final BoundingBox boundingBox; + ui.Image? importedImage; + bool _isInteracting = false; + + ImportTool({ + required super.commandManager, + required super.commandFactory, + required this.boundingBox, + required super.type, + super.hasAddFunctionality = false, + super.hasFinalizeFunctionality = true, + }); + + Future pickImage(LoadImageFromPhotoLibrary loadImageFromPhotoLibrary) async { + final result = await loadImageFromPhotoLibrary.call(); + result.match( + (image) { + importedImage = image; + // Keep the provider-created box centered on the canvas and reset its + // transform for each newly selected image. + boundingBox.width = image.width.toDouble(); + boundingBox.height = image.height.toDouble(); + boundingBox.angle = 0.0; + }, + (failure) { + // If failed or cancelled, we don't change anything + }, + ); + } + + @override + void onDown(ui.Offset point, Paint paint) { + boundingBox.determineAction(point); + _isInteracting = boundingBox.currentAction != BoundingBoxAction.none; + } + + @override + void onDrag(ui.Offset point, Paint paint) { + if (_isInteracting) boundingBox.updateDrag(point); + } + + @override + void onUp(ui.Offset point, Paint paint) { + if (_isInteracting) { + boundingBox.endDrag(); + _isInteracting = false; + } + } + + @override + void onCancel() { + if (_isInteracting) { + boundingBox.endDrag(); + _isInteracting = false; + } + } + + void paint(Canvas canvas, Size size) { + boundingBox.drawGuides(canvas); + final image = importedImage; + if (image == null) return; + if (image.width == 0 || image.height == 0) return; + + final rect = boundingBox.rect; + if (rect.width <= 0 || rect.height <= 0) return; + + double previewScale = 1.0; + if (image.width > 0 && + image.height > 0 && + rect.width > 0 && + rect.height > 0) { + final double widthScale = rect.width / image.width.toDouble(); + final double heightScale = rect.height / image.height.toDouble(); + previewScale = dart_math.min(widthScale, heightScale); + } + + final double scaledWidth = image.width.toDouble() * previewScale; + final double scaledHeight = image.height.toDouble() * previewScale; + + final src = ui.Rect.fromLTWH( + 0, + 0, + image.width.toDouble(), + image.height.toDouble(), + ); + final dst = ui.Rect.fromLTWH( + -scaledWidth / 2, + -scaledHeight / 2, + scaledWidth, + scaledHeight, + ); + + canvas.save(); + canvas.translate(rect.center.dx, rect.center.dy); + canvas.rotate(boundingBox.angle); + final paintImage = Paint()..filterQuality = FilterQuality.high; + canvas.drawImageRect(image, src, dst, paintImage); + canvas.restore(); + } + + @override + Future onCheckmark(Paint paint) async { + final image = importedImage; + if (image == null) return; + + final byteData = await image.toByteData(format: ui.ImageByteFormat.png); + if (byteData == null) return; + final bytes = byteData.buffer.asUint8List(); + + final pasteOffset = boundingBox.rect.center; + final pasteRotation = boundingBox.angle; + + double pasteScale = 1.0; + if (image.width > 0 && + image.height > 0 && + boundingBox.rect.width > 0 && + boundingBox.rect.height > 0) { + final double widthScale = boundingBox.rect.width / image.width.toDouble(); + final double heightScale = + boundingBox.rect.height / image.height.toDouble(); + pasteScale = dart_math.min(widthScale, heightScale); + } else if (image.width > 0 && boundingBox.rect.width > 0) { + pasteScale = boundingBox.rect.width / image.width.toDouble(); + } + + final command = commandFactory.createClipboardCommand( + paint, + bytes, + pasteOffset, + pasteScale, + pasteRotation, + ); + await command.prepareForRuntime(); + commandManager.addGraphicCommand(command); + importedImage = null; + } + + @override + void onPlus() {} + + @override + void onUndo() => commandManager.undo(); + + @override + void onRedo() => commandManager.redo(); +} diff --git a/lib/core/tools/tool.dart b/lib/core/tools/tool.dart index dc0b9999..4c3bfc06 100644 --- a/lib/core/tools/tool.dart +++ b/lib/core/tools/tool.dart @@ -1,3 +1,4 @@ +import 'dart:async'; import 'dart:ui'; import 'package:flutter/cupertino.dart'; @@ -28,7 +29,7 @@ abstract class Tool { void onCancel(); - void onCheckmark(Paint paint); + FutureOr onCheckmark(Paint paint); void onPlus(); diff --git a/lib/ui/pages/workspace_page/components/top_bar/top_app_bar.dart b/lib/ui/pages/workspace_page/components/top_bar/top_app_bar.dart index 319a2f39..13c00e23 100644 --- a/lib/ui/pages/workspace_page/components/top_bar/top_app_bar.dart +++ b/lib/ui/pages/workspace_page/components/top_bar/top_app_bar.dart @@ -7,8 +7,9 @@ import 'package:paintroid/core/providers/state/app_bar_provider.dart'; import 'package:paintroid/core/providers/state/canvas_state_provider.dart'; import 'package:paintroid/core/providers/state/paint_provider.dart'; import 'package:paintroid/core/providers/state/toolbox_state_provider.dart'; -import 'package:paintroid/core/tools/implementation/text_tool.dart'; +import 'package:paintroid/core/tools/implementation/import_tool.dart'; import 'package:paintroid/core/tools/line_tool/line_tool.dart'; +import 'package:paintroid/core/tools/implementation/text_tool.dart'; import 'package:paintroid/core/tools/tool.dart'; import 'package:paintroid/ui/pages/workspace_page/components/top_bar/overflow_menu.dart'; import 'package:paintroid/ui/shared/action_button.dart'; @@ -74,9 +75,11 @@ class TopAppBar extends ConsumerWidget implements PreferredSizeWidget { currentTool is LineTool && currentTool.vertexStack.isNotEmpty; final isShapeTool = currentTool.type == ToolType.SHAPES; final isTextTool = currentTool is TextTool; - if (isLineTool || isShapeTool || isTextTool) { - return () { - currentTool.onCheckmark(ref.read(paintProvider)); + final isImportTool = currentTool is ImportTool && + currentTool.importedImage != null; + if (isLineTool || isShapeTool || isTextTool || isImportTool) { + return () async { + await currentTool.onCheckmark(ref.read(paintProvider)); ref.read(appBarProvider.notifier).update(); ref .read(canvasStateProvider.notifier) diff --git a/test/unit/tools/import_tool_test.dart b/test/unit/tools/import_tool_test.dart new file mode 100644 index 00000000..68ab0353 --- /dev/null +++ b/test/unit/tools/import_tool_test.dart @@ -0,0 +1,147 @@ +import 'dart:typed_data'; +import 'dart:ui' as ui; + +import 'package:flutter_test/flutter_test.dart'; +import 'package:mockito/annotations.dart'; +import 'package:mockito/mockito.dart'; +import 'package:oxidized/oxidized.dart'; + +import 'package:paintroid/core/enums/bounding_box_action.dart'; +import 'package:paintroid/core/enums/tool_types.dart'; +import 'package:paintroid/core/tools/bounding_box.dart'; +import 'package:paintroid/core/tools/implementation/import_tool.dart'; +import 'package:paintroid/core/commands/command_factory/command_factory.dart'; +import 'package:paintroid/core/commands/command_manager/command_manager.dart'; +import 'package:paintroid/core/commands/command_implementation/graphic/clipboard_command.dart'; +import 'package:paintroid/core/providers/object/load_image_from_photo_library.dart'; +import 'package:paintroid/core/utils/load_image_failure.dart'; + +import '../../utils/clipboard_tool_util.dart'; +import 'import_tool_test.mocks.dart'; + +@GenerateMocks([ + BoundingBox, + CommandManager, + CommandFactory, + ClipboardCommand, + ui.Image, + LoadImageFromPhotoLibrary, +]) +void main() { + late ImportTool sut; + late MockBoundingBox boundingBox; + late MockCommandManager commandManager; + late MockCommandFactory commandFactory; + late MockImage mockImage; + late MockLoadImageFromPhotoLibrary mockPicker; + + setUp(() { + boundingBox = MockBoundingBox(); + commandManager = MockCommandManager(); + commandFactory = MockCommandFactory(); + mockImage = MockImage(); + mockPicker = MockLoadImageFromPhotoLibrary(); + + when(boundingBox.rect).thenReturn(const ui.Rect.fromLTWH(0, 0, 100, 100)); + when(boundingBox.angle).thenReturn(0.0); + when(boundingBox.currentAction).thenReturn(BoundingBoxAction.none); + + sut = ImportTool( + commandManager: commandManager, + commandFactory: commandFactory, + boundingBox: boundingBox, + type: ToolType.IMPORT, + ); + }); + + group('image selection', () { + test('pickImage updates importedImage and boundingBox dimensions on success', () async { + when(mockImage.width).thenReturn(200); + when(mockImage.height).thenReturn(150); + when(mockPicker.call()).thenAnswer((_) async => Result.ok(mockImage)); + + await sut.pickImage(mockPicker); + + expect(sut.importedImage, equals(mockImage)); + verify(boundingBox.width = 200.0).called(1); + verify(boundingBox.height = 150.0).called(1); + verify(boundingBox.angle = 0.0).called(1); + }); + + test('keeps the current image when image selection fails', () async { + sut.importedImage = mockImage; + when(mockPicker.call()).thenAnswer((_) async => + const Result.err(LoadImageFailure.permissionDenied)); + + await sut.pickImage(mockPicker); + + expect(sut.importedImage, same(mockImage)); + verifyNever(boundingBox.width = any); + verifyNever(boundingBox.height = any); + }); + }); + + group('bounding box gestures', () { + test('delegates a complete interaction to the bounding box', () { + when(boundingBox.determineAction(any)).thenAnswer((_) { + when(boundingBox.currentAction).thenReturn(BoundingBoxAction.move); + }); + + sut.onDown(ui.Offset.zero, ui.Paint()); + verify(boundingBox.determineAction(ui.Offset.zero)).called(1); + + sut.onDrag(ui.Offset.zero, ui.Paint()); + verify(boundingBox.updateDrag(ui.Offset.zero)).called(1); + + sut.onUp(ui.Offset.zero, ui.Paint()); + verify(boundingBox.endDrag()).called(1); + + sut.onDrag(ui.Offset.zero, ui.Paint()); + verifyNever(boundingBox.updateDrag(any)); + }); + + test('ignores a drag when no handle or image is being interacted with', () { + sut.onDown(ui.Offset.zero, ui.Paint()); + sut.onDrag(ui.Offset.zero, ui.Paint()); + sut.onUp(ui.Offset.zero, ui.Paint()); + + verifyNever(boundingBox.updateDrag(any)); + verifyNever(boundingBox.endDrag()); + }); + }); + + group('finalization and command integration', () { + test('does nothing when no image has been selected', () async { + await sut.onCheckmark(ui.Paint()); + + verifyNever( + commandFactory.createClipboardCommand(any, any, any, any, any)); + verifyNever(commandManager.addGraphicCommand(any)); + }); + + test('creates a transformed clipboard command and clears the preview', + () async { + final image = await ClipboardIntegrationTestUtils.createTestImage(50, 50); + sut.importedImage = image; + + final command = MockClipboardCommand(); + when(commandFactory.createClipboardCommand(any, any, any, any, any)) + .thenReturn(command); + when(command.prepareForRuntime()).thenAnswer((_) async {}); + + await sut.onCheckmark(ui.Paint()); + + final imageBytes = verify(commandFactory.createClipboardCommand( + any, + captureAny, + const ui.Offset(50, 50), + 2.0, + 0.0, + )).captured.single as Uint8List; + expect(imageBytes, isNotEmpty); + verify(command.prepareForRuntime()).called(1); + verify(commandManager.addGraphicCommand(command)).called(1); + expect(sut.importedImage, isNull); + }); + }); +} diff --git a/test/unit/tools/import_tool_test.mocks.dart b/test/unit/tools/import_tool_test.mocks.dart new file mode 100644 index 00000000..fc64773d --- /dev/null +++ b/test/unit/tools/import_tool_test.mocks.dart @@ -0,0 +1,1331 @@ +// Mocks generated by Mockito 5.4.4 from annotations +// in paintroid/test/unit/tools/import_tool_test.dart. +// Do not manually edit this file. + +// ignore_for_file: no_leading_underscores_for_library_prefixes +import 'dart:async' as _i33; +import 'dart:typed_data' as _i31; +import 'dart:ui' as _i2; + +import 'package:flutter/material.dart' as _i32; +import 'package:logging/logging.dart' as _i16; +import 'package:mockito/mockito.dart' as _i1; +import 'package:mockito/src/dummies.dart' as _i24; +import 'package:oxidized/oxidized.dart' as _i20; +import 'package:paintroid/core/commands/command_factory/command_factory.dart' + as _i28; +import 'package:paintroid/core/commands/command_implementation/command.dart' + as _i3; +import 'package:paintroid/core/commands/command_implementation/graphic/clipboard_command.dart' + as _i9; +import 'package:paintroid/core/commands/command_implementation/graphic/color_changed_command.dart' + as _i15; +import 'package:paintroid/core/commands/command_implementation/graphic/delete_region_command.dart' + as _i14; +import 'package:paintroid/core/commands/command_implementation/graphic/graphic_command.dart' + as _i26; +import 'package:paintroid/core/commands/command_implementation/graphic/line_command.dart' + as _i6; +import 'package:paintroid/core/commands/command_implementation/graphic/path_command.dart' + as _i5; +import 'package:paintroid/core/commands/command_implementation/graphic/shape/ellipse_shape_command.dart' + as _i8; +import 'package:paintroid/core/commands/command_implementation/graphic/shape/heart_shape_command.dart' + as _i12; +import 'package:paintroid/core/commands/command_implementation/graphic/shape/square_shape_command.dart' + as _i7; +import 'package:paintroid/core/commands/command_implementation/graphic/shape/star_shape_command.dart' + as _i11; +import 'package:paintroid/core/commands/command_implementation/graphic/spray_command.dart' + as _i13; +import 'package:paintroid/core/commands/command_implementation/graphic/text_command.dart' + as _i10; +import 'package:paintroid/core/commands/command_manager/command_manager.dart' + as _i25; +import 'package:paintroid/core/commands/path_with_action_history.dart' as _i29; +import 'package:paintroid/core/enums/bounding_box_action.dart' as _i22; +import 'package:paintroid/core/enums/bounding_box_resize_action.dart' as _i23; +import 'package:paintroid/core/enums/shape_style.dart' as _i30; +import 'package:paintroid/core/providers/object/image_service.dart' as _i17; +import 'package:paintroid/core/providers/object/load_image_from_photo_library.dart' + as _i34; +import 'package:paintroid/core/providers/object/permission_service.dart' + as _i18; +import 'package:paintroid/core/providers/object/photo_library_service.dart' + as _i19; +import 'package:paintroid/core/tools/bounding_box.dart' as _i21; +import 'package:paintroid/core/tools/line_tool/vertex_stack.dart' as _i27; +import 'package:paintroid/core/tools/tool_data.dart' as _i4; +import 'package:paintroid/core/utils/failure.dart' as _i35; + +// ignore_for_file: type=lint +// ignore_for_file: avoid_redundant_argument_values +// ignore_for_file: avoid_setters_without_getters +// ignore_for_file: comment_references +// ignore_for_file: deprecated_member_use +// ignore_for_file: deprecated_member_use_from_same_package +// ignore_for_file: implementation_imports +// ignore_for_file: invalid_use_of_visible_for_testing_member +// ignore_for_file: prefer_const_constructors +// ignore_for_file: unnecessary_parenthesis +// ignore_for_file: camel_case_types +// ignore_for_file: subtype_of_sealed_class + +class _FakeOffset_0 extends _i1.SmartFake implements _i2.Offset { + _FakeOffset_0( + Object parent, + Invocation parentInvocation, + ) : super( + parent, + parentInvocation, + ); +} + +class _FakeRect_1 extends _i1.SmartFake implements _i2.Rect { + _FakeRect_1( + Object parent, + Invocation parentInvocation, + ) : super( + parent, + parentInvocation, + ); +} + +class _FakeCommand_2 extends _i1.SmartFake implements _i3.Command { + _FakeCommand_2( + Object parent, + Invocation parentInvocation, + ) : super( + parent, + parentInvocation, + ); +} + +class _FakeToolData_3 extends _i1.SmartFake implements _i4.ToolData { + _FakeToolData_3( + Object parent, + Invocation parentInvocation, + ) : super( + parent, + parentInvocation, + ); +} + +class _FakePathCommand_4 extends _i1.SmartFake implements _i5.PathCommand { + _FakePathCommand_4( + Object parent, + Invocation parentInvocation, + ) : super( + parent, + parentInvocation, + ); +} + +class _FakeLineCommand_5 extends _i1.SmartFake implements _i6.LineCommand { + _FakeLineCommand_5( + Object parent, + Invocation parentInvocation, + ) : super( + parent, + parentInvocation, + ); +} + +class _FakeSquareShapeCommand_6 extends _i1.SmartFake + implements _i7.SquareShapeCommand { + _FakeSquareShapeCommand_6( + Object parent, + Invocation parentInvocation, + ) : super( + parent, + parentInvocation, + ); +} + +class _FakeEllipseShapeCommand_7 extends _i1.SmartFake + implements _i8.EllipseShapeCommand { + _FakeEllipseShapeCommand_7( + Object parent, + Invocation parentInvocation, + ) : super( + parent, + parentInvocation, + ); +} + +class _FakeClipboardCommand_8 extends _i1.SmartFake + implements _i9.ClipboardCommand { + _FakeClipboardCommand_8( + Object parent, + Invocation parentInvocation, + ) : super( + parent, + parentInvocation, + ); +} + +class _FakeTextCommand_9 extends _i1.SmartFake implements _i10.TextCommand { + _FakeTextCommand_9( + Object parent, + Invocation parentInvocation, + ) : super( + parent, + parentInvocation, + ); +} + +class _FakeStarShapeCommand_10 extends _i1.SmartFake + implements _i11.StarShapeCommand { + _FakeStarShapeCommand_10( + Object parent, + Invocation parentInvocation, + ) : super( + parent, + parentInvocation, + ); +} + +class _FakeHeartShapeCommand_11 extends _i1.SmartFake + implements _i12.HeartShapeCommand { + _FakeHeartShapeCommand_11( + Object parent, + Invocation parentInvocation, + ) : super( + parent, + parentInvocation, + ); +} + +class _FakeSprayCommand_12 extends _i1.SmartFake implements _i13.SprayCommand { + _FakeSprayCommand_12( + Object parent, + Invocation parentInvocation, + ) : super( + parent, + parentInvocation, + ); +} + +class _FakeDeleteRegionCommand_13 extends _i1.SmartFake + implements _i14.DeleteRegionCommand { + _FakeDeleteRegionCommand_13( + Object parent, + Invocation parentInvocation, + ) : super( + parent, + parentInvocation, + ); +} + +class _FakeColorChangedCommand_14 extends _i1.SmartFake + implements _i15.ColorChangedCommand { + _FakeColorChangedCommand_14( + Object parent, + Invocation parentInvocation, + ) : super( + parent, + parentInvocation, + ); +} + +class _FakeLogger_15 extends _i1.SmartFake implements _i16.Logger { + _FakeLogger_15( + Object parent, + Invocation parentInvocation, + ) : super( + parent, + parentInvocation, + ); +} + +class _FakeImage_16 extends _i1.SmartFake implements _i2.Image { + _FakeImage_16( + Object parent, + Invocation parentInvocation, + ) : super( + parent, + parentInvocation, + ); +} + +class _FakeIImageService_17 extends _i1.SmartFake + implements _i17.IImageService { + _FakeIImageService_17( + Object parent, + Invocation parentInvocation, + ) : super( + parent, + parentInvocation, + ); +} + +class _FakeIPermissionService_18 extends _i1.SmartFake + implements _i18.IPermissionService { + _FakeIPermissionService_18( + Object parent, + Invocation parentInvocation, + ) : super( + parent, + parentInvocation, + ); +} + +class _FakeIPhotoLibraryService_19 extends _i1.SmartFake + implements _i19.IPhotoLibraryService { + _FakeIPhotoLibraryService_19( + Object parent, + Invocation parentInvocation, + ) : super( + parent, + parentInvocation, + ); +} + +class _FakeResult_20 extends _i1.SmartFake + implements _i20.Result { + _FakeResult_20( + Object parent, + Invocation parentInvocation, + ) : super( + parent, + parentInvocation, + ); +} + +/// A class which mocks [BoundingBox]. +/// +/// See the documentation for Mockito's code generation for more information. +class MockBoundingBox extends _i1.Mock implements _i21.BoundingBox { + MockBoundingBox() { + _i1.throwOnMissingStub(this); + } + + @override + _i2.Offset get center => (super.noSuchMethod( + Invocation.getter(#center), + returnValue: _FakeOffset_0( + this, + Invocation.getter(#center), + ), + ) as _i2.Offset); + + @override + set center(_i2.Offset? _center) => super.noSuchMethod( + Invocation.setter( + #center, + _center, + ), + returnValueForMissingStub: null, + ); + + @override + double get width => (super.noSuchMethod( + Invocation.getter(#width), + returnValue: 0.0, + ) as double); + + @override + set width(double? _width) => super.noSuchMethod( + Invocation.setter( + #width, + _width, + ), + returnValueForMissingStub: null, + ); + + @override + double get height => (super.noSuchMethod( + Invocation.getter(#height), + returnValue: 0.0, + ) as double); + + @override + set height(double? _height) => super.noSuchMethod( + Invocation.setter( + #height, + _height, + ), + returnValueForMissingStub: null, + ); + + @override + double get angle => (super.noSuchMethod( + Invocation.getter(#angle), + returnValue: 0.0, + ) as double); + + @override + set angle(double? _angle) => super.noSuchMethod( + Invocation.setter( + #angle, + _angle, + ), + returnValueForMissingStub: null, + ); + + @override + _i22.BoundingBoxAction get currentAction => (super.noSuchMethod( + Invocation.getter(#currentAction), + returnValue: _i22.BoundingBoxAction.none, + ) as _i22.BoundingBoxAction); + + @override + set currentAction(_i22.BoundingBoxAction? _currentAction) => + super.noSuchMethod( + Invocation.setter( + #currentAction, + _currentAction, + ), + returnValueForMissingStub: null, + ); + + @override + _i23.BoundingBoxResizeAction get currentBoundingBoxResizeAction => + (super.noSuchMethod( + Invocation.getter(#currentBoundingBoxResizeAction), + returnValue: _i23.BoundingBoxResizeAction.none, + ) as _i23.BoundingBoxResizeAction); + + @override + set currentBoundingBoxResizeAction( + _i23.BoundingBoxResizeAction? _currentBoundingBoxResizeAction) => + super.noSuchMethod( + Invocation.setter( + #currentBoundingBoxResizeAction, + _currentBoundingBoxResizeAction, + ), + returnValueForMissingStub: null, + ); + + @override + set lastDragGlobalPosition(_i2.Offset? _lastDragGlobalPosition) => + super.noSuchMethod( + Invocation.setter( + #lastDragGlobalPosition, + _lastDragGlobalPosition, + ), + returnValueForMissingStub: null, + ); + + @override + set dragStartLocalPosition(_i2.Offset? _dragStartLocalPosition) => + super.noSuchMethod( + Invocation.setter( + #dragStartLocalPosition, + _dragStartLocalPosition, + ), + returnValueForMissingStub: null, + ); + + @override + int get activeRotationArcIndex => (super.noSuchMethod( + Invocation.getter(#activeRotationArcIndex), + returnValue: 0, + ) as int); + + @override + set activeRotationArcIndex(int? _activeRotationArcIndex) => + super.noSuchMethod( + Invocation.setter( + #activeRotationArcIndex, + _activeRotationArcIndex, + ), + returnValueForMissingStub: null, + ); + + @override + _i2.Paint get boxPaint => (super.noSuchMethod( + Invocation.getter(#boxPaint), + returnValue: _i24.dummyValue<_i2.Paint>( + this, + Invocation.getter(#boxPaint), + ), + ) as _i2.Paint); + + @override + set boxPaint(_i2.Paint? _boxPaint) => super.noSuchMethod( + Invocation.setter( + #boxPaint, + _boxPaint, + ), + returnValueForMissingStub: null, + ); + + @override + _i2.Paint get handlePaint => (super.noSuchMethod( + Invocation.getter(#handlePaint), + returnValue: _i24.dummyValue<_i2.Paint>( + this, + Invocation.getter(#handlePaint), + ), + ) as _i2.Paint); + + @override + set handlePaint(_i2.Paint? _handlePaint) => super.noSuchMethod( + Invocation.setter( + #handlePaint, + _handlePaint, + ), + returnValueForMissingStub: null, + ); + + @override + _i2.Paint get rotationHandlePaint => (super.noSuchMethod( + Invocation.getter(#rotationHandlePaint), + returnValue: _i24.dummyValue<_i2.Paint>( + this, + Invocation.getter(#rotationHandlePaint), + ), + ) as _i2.Paint); + + @override + set rotationHandlePaint(_i2.Paint? _rotationHandlePaint) => + super.noSuchMethod( + Invocation.setter( + #rotationHandlePaint, + _rotationHandlePaint, + ), + returnValueForMissingStub: null, + ); + + @override + bool get isAspectRatioLocked => (super.noSuchMethod( + Invocation.getter(#isAspectRatioLocked), + returnValue: false, + ) as bool); + + @override + set isAspectRatioLocked(bool? _isAspectRatioLocked) => super.noSuchMethod( + Invocation.setter( + #isAspectRatioLocked, + _isAspectRatioLocked, + ), + returnValueForMissingStub: null, + ); + + @override + _i2.Rect get rect => (super.noSuchMethod( + Invocation.getter(#rect), + returnValue: _FakeRect_1( + this, + Invocation.getter(#rect), + ), + ) as _i2.Rect); + + @override + List<_i2.Offset> getCorners() => (super.noSuchMethod( + Invocation.method( + #getCorners, + [], + ), + returnValue: <_i2.Offset>[], + ) as List<_i2.Offset>); + + @override + void determineAction(_i2.Offset? globalPoint) => super.noSuchMethod( + Invocation.method( + #determineAction, + [globalPoint], + ), + returnValueForMissingStub: null, + ); + + @override + void updateDrag(_i2.Offset? globalPoint) => super.noSuchMethod( + Invocation.method( + #updateDrag, + [globalPoint], + ), + returnValueForMissingStub: null, + ); + + @override + void endDrag() => super.noSuchMethod( + Invocation.method( + #endDrag, + [], + ), + returnValueForMissingStub: null, + ); + + @override + void drawGuides(_i2.Canvas? canvas) => super.noSuchMethod( + Invocation.method( + #drawGuides, + [canvas], + ), + returnValueForMissingStub: null, + ); +} + +/// A class which mocks [CommandManager]. +/// +/// See the documentation for Mockito's code generation for more information. +class MockCommandManager extends _i1.Mock implements _i25.CommandManager { + MockCommandManager() { + _i1.throwOnMissingStub(this); + } + + @override + List<_i3.Command> get redoStack => (super.noSuchMethod( + Invocation.getter(#redoStack), + returnValue: <_i3.Command>[], + ) as List<_i3.Command>); + + @override + List<_i3.Command> get undoStack => (super.noSuchMethod( + Invocation.getter(#undoStack), + returnValue: <_i3.Command>[], + ) as List<_i3.Command>); + + @override + void addGraphicCommand(_i26.GraphicCommand? command) => super.noSuchMethod( + Invocation.method( + #addGraphicCommand, + [command], + ), + returnValueForMissingStub: null, + ); + + @override + void setUndoStack(List<_i3.Command>? commands) => super.noSuchMethod( + Invocation.method( + #setUndoStack, + [commands], + ), + returnValueForMissingStub: null, + ); + + @override + void executeLastCommand(_i2.Canvas? canvas) => super.noSuchMethod( + Invocation.method( + #executeLastCommand, + [canvas], + ), + returnValueForMissingStub: null, + ); + + @override + void executeAllCommands(_i2.Canvas? canvas) => super.noSuchMethod( + Invocation.method( + #executeAllCommands, + [canvas], + ), + returnValueForMissingStub: null, + ); + + @override + void discardLastCommand() => super.noSuchMethod( + Invocation.method( + #discardLastCommand, + [], + ), + returnValueForMissingStub: null, + ); + + @override + void clearUndoStack({Iterable<_i3.Command>? newCommands}) => + super.noSuchMethod( + Invocation.method( + #clearUndoStack, + [], + {#newCommands: newCommands}, + ), + returnValueForMissingStub: null, + ); + + @override + void clearRedoStack() => super.noSuchMethod( + Invocation.method( + #clearRedoStack, + [], + ), + returnValueForMissingStub: null, + ); + + @override + void drawLineToolGhostPaths( + _i2.Canvas? canvas, + _i6.LineCommand? ingoingGhostPathCommand, + _i6.LineCommand? outgoingGhostPathCommand, + ) => + super.noSuchMethod( + Invocation.method( + #drawLineToolGhostPaths, + [ + canvas, + ingoingGhostPathCommand, + outgoingGhostPathCommand, + ], + ), + returnValueForMissingStub: null, + ); + + @override + void drawLineToolVertices( + _i2.Canvas? canvas, + _i27.VertexStack? vertexStack, + ) => + super.noSuchMethod( + Invocation.method( + #drawLineToolVertices, + [ + canvas, + vertexStack, + ], + ), + returnValueForMissingStub: null, + ); + + @override + _i3.Command redo() => (super.noSuchMethod( + Invocation.method( + #redo, + [], + ), + returnValue: _FakeCommand_2( + this, + Invocation.method( + #redo, + [], + ), + ), + ) as _i3.Command); + + @override + void undo() => super.noSuchMethod( + Invocation.method( + #undo, + [], + ), + returnValueForMissingStub: null, + ); + + @override + _i4.ToolData getNextTool(_i25.ActionType? actionType) => (super.noSuchMethod( + Invocation.method( + #getNextTool, + [actionType], + ), + returnValue: _FakeToolData_3( + this, + Invocation.method( + #getNextTool, + [actionType], + ), + ), + ) as _i4.ToolData); + + @override + List<_i6.LineCommand> getTopLineCommandSequence() => (super.noSuchMethod( + Invocation.method( + #getTopLineCommandSequence, + [], + ), + returnValue: <_i6.LineCommand>[], + ) as List<_i6.LineCommand>); +} + +/// A class which mocks [CommandFactory]. +/// +/// See the documentation for Mockito's code generation for more information. +class MockCommandFactory extends _i1.Mock implements _i28.CommandFactory { + MockCommandFactory() { + _i1.throwOnMissingStub(this); + } + + @override + _i5.PathCommand createPathCommand( + _i29.PathWithActionHistory? path, + _i2.Paint? paint, { + bool? isCursor = false, + }) => + (super.noSuchMethod( + Invocation.method( + #createPathCommand, + [ + path, + paint, + ], + {#isCursor: isCursor}, + ), + returnValue: _FakePathCommand_4( + this, + Invocation.method( + #createPathCommand, + [ + path, + paint, + ], + {#isCursor: isCursor}, + ), + ), + ) as _i5.PathCommand); + + @override + _i6.LineCommand createLineCommand( + _i29.PathWithActionHistory? path, + _i2.Paint? paint, + _i2.Offset? startPoint, + _i2.Offset? endPoint, + ) => + (super.noSuchMethod( + Invocation.method( + #createLineCommand, + [ + path, + paint, + startPoint, + endPoint, + ], + ), + returnValue: _FakeLineCommand_5( + this, + Invocation.method( + #createLineCommand, + [ + path, + paint, + startPoint, + endPoint, + ], + ), + ), + ) as _i6.LineCommand); + + @override + _i7.SquareShapeCommand createSquareShapeCommand( + _i2.Paint? paint, + _i2.Offset? topLeft, + _i2.Offset? topRight, + _i2.Offset? bottomLeft, + _i2.Offset? bottomRight, + _i30.ShapeStyle? style, + ) => + (super.noSuchMethod( + Invocation.method( + #createSquareShapeCommand, + [ + paint, + topLeft, + topRight, + bottomLeft, + bottomRight, + style, + ], + ), + returnValue: _FakeSquareShapeCommand_6( + this, + Invocation.method( + #createSquareShapeCommand, + [ + paint, + topLeft, + topRight, + bottomLeft, + bottomRight, + style, + ], + ), + ), + ) as _i7.SquareShapeCommand); + + @override + _i8.EllipseShapeCommand createEllipseShapeCommand( + _i2.Paint? paint, + double? radiusX, + double? radiusY, + _i2.Offset? center, + _i30.ShapeStyle? style, + double? angle, + ) => + (super.noSuchMethod( + Invocation.method( + #createEllipseShapeCommand, + [ + paint, + radiusX, + radiusY, + center, + style, + angle, + ], + ), + returnValue: _FakeEllipseShapeCommand_7( + this, + Invocation.method( + #createEllipseShapeCommand, + [ + paint, + radiusX, + radiusY, + center, + style, + angle, + ], + ), + ), + ) as _i8.EllipseShapeCommand); + + @override + _i9.ClipboardCommand createClipboardCommand( + _i2.Paint? paint, + _i31.Uint8List? imageData, + _i2.Offset? offset, + double? scale, + double? rotation, + ) => + (super.noSuchMethod( + Invocation.method( + #createClipboardCommand, + [ + paint, + imageData, + offset, + scale, + rotation, + ], + ), + returnValue: _FakeClipboardCommand_8( + this, + Invocation.method( + #createClipboardCommand, + [ + paint, + imageData, + offset, + scale, + rotation, + ], + ), + ), + ) as _i9.ClipboardCommand); + + @override + _i10.TextCommand createTextCommand( + _i2.Offset? point, + String? text, + _i32.TextStyle? style, + double? fontSize, + _i2.Paint? paint, + double? rotationAngle, { + double? scaleX = 1.0, + double? scaleY = 1.0, + }) => + (super.noSuchMethod( + Invocation.method( + #createTextCommand, + [ + point, + text, + style, + fontSize, + paint, + rotationAngle, + ], + { + #scaleX: scaleX, + #scaleY: scaleY, + }, + ), + returnValue: _FakeTextCommand_9( + this, + Invocation.method( + #createTextCommand, + [ + point, + text, + style, + fontSize, + paint, + rotationAngle, + ], + { + #scaleX: scaleX, + #scaleY: scaleY, + }, + ), + ), + ) as _i10.TextCommand); + + @override + _i11.StarShapeCommand createStarShapeCommand( + _i2.Paint? paint, + int? numPoints, + double? angle, + _i2.Offset? center, + _i30.ShapeStyle? style, + double? radiusX, + double? radiusY, + ) => + (super.noSuchMethod( + Invocation.method( + #createStarShapeCommand, + [ + paint, + numPoints, + angle, + center, + style, + radiusX, + radiusY, + ], + ), + returnValue: _FakeStarShapeCommand_10( + this, + Invocation.method( + #createStarShapeCommand, + [ + paint, + numPoints, + angle, + center, + style, + radiusX, + radiusY, + ], + ), + ), + ) as _i11.StarShapeCommand); + + @override + _i12.HeartShapeCommand createHeartShapeCommand( + _i2.Paint? paint, + double? width, + double? height, + double? angle, + _i2.Offset? center, + _i30.ShapeStyle? style, + ) => + (super.noSuchMethod( + Invocation.method( + #createHeartShapeCommand, + [ + paint, + width, + height, + angle, + center, + style, + ], + ), + returnValue: _FakeHeartShapeCommand_11( + this, + Invocation.method( + #createHeartShapeCommand, + [ + paint, + width, + height, + angle, + center, + style, + ], + ), + ), + ) as _i12.HeartShapeCommand); + + @override + _i13.SprayCommand createSprayCommand( + List<_i2.Offset>? points, + _i2.Paint? paint, + ) => + (super.noSuchMethod( + Invocation.method( + #createSprayCommand, + [ + points, + paint, + ], + ), + returnValue: _FakeSprayCommand_12( + this, + Invocation.method( + #createSprayCommand, + [ + points, + paint, + ], + ), + ), + ) as _i13.SprayCommand); + + @override + _i14.DeleteRegionCommand createDeleteRegionCommand(_i2.Rect? region) => + (super.noSuchMethod( + Invocation.method( + #createDeleteRegionCommand, + [region], + ), + returnValue: _FakeDeleteRegionCommand_13( + this, + Invocation.method( + #createDeleteRegionCommand, + [region], + ), + ), + ) as _i14.DeleteRegionCommand); + + @override + _i15.ColorChangedCommand createColorChangedCommand( + _i2.Color? oldColor, + _i2.Color? newColor, + _i2.Paint? paint, + ) => + (super.noSuchMethod( + Invocation.method( + #createColorChangedCommand, + [ + oldColor, + newColor, + paint, + ], + ), + returnValue: _FakeColorChangedCommand_14( + this, + Invocation.method( + #createColorChangedCommand, + [ + oldColor, + newColor, + paint, + ], + ), + ), + ) as _i15.ColorChangedCommand); +} + +/// A class which mocks [ClipboardCommand]. +/// +/// See the documentation for Mockito's code generation for more information. +class MockClipboardCommand extends _i1.Mock implements _i9.ClipboardCommand { + MockClipboardCommand() { + _i1.throwOnMissingStub(this); + } + + @override + _i31.Uint8List get imageData => (super.noSuchMethod( + Invocation.getter(#imageData), + returnValue: _i31.Uint8List(0), + ) as _i31.Uint8List); + + @override + _i2.Offset get offset => (super.noSuchMethod( + Invocation.getter(#offset), + returnValue: _FakeOffset_0( + this, + Invocation.getter(#offset), + ), + ) as _i2.Offset); + + @override + double get scale => (super.noSuchMethod( + Invocation.getter(#scale), + returnValue: 0.0, + ) as double); + + @override + double get rotation => (super.noSuchMethod( + Invocation.getter(#rotation), + returnValue: 0.0, + ) as double); + + @override + int get version => (super.noSuchMethod( + Invocation.getter(#version), + returnValue: 0, + ) as int); + + @override + String get type => (super.noSuchMethod( + Invocation.getter(#type), + returnValue: _i24.dummyValue( + this, + Invocation.getter(#type), + ), + ) as String); + + @override + List get props => (super.noSuchMethod( + Invocation.getter(#props), + returnValue: [], + ) as List); + + @override + _i2.Paint get paint => (super.noSuchMethod( + Invocation.getter(#paint), + returnValue: _i24.dummyValue<_i2.Paint>( + this, + Invocation.getter(#paint), + ), + ) as _i2.Paint); + + @override + _i16.Logger get logger => (super.noSuchMethod( + Invocation.getter(#logger), + returnValue: _FakeLogger_15( + this, + Invocation.getter(#logger), + ), + ) as _i16.Logger); + + @override + _i33.Future prepareForRuntime() => (super.noSuchMethod( + Invocation.method( + #prepareForRuntime, + [], + ), + returnValue: _i33.Future.value(), + returnValueForMissingStub: _i33.Future.value(), + ) as _i33.Future); + + @override + void call(_i2.Canvas? canvas) => super.noSuchMethod( + Invocation.method( + #call, + [canvas], + ), + returnValueForMissingStub: null, + ); + + @override + Map toJson() => (super.noSuchMethod( + Invocation.method( + #toJson, + [], + ), + returnValue: {}, + ) as Map); +} + +/// A class which mocks [Image]. +/// +/// See the documentation for Mockito's code generation for more information. +class MockImage extends _i1.Mock implements _i2.Image { + MockImage() { + _i1.throwOnMissingStub(this); + } + + @override + int get width => (super.noSuchMethod( + Invocation.getter(#width), + returnValue: 0, + ) as int); + + @override + int get height => (super.noSuchMethod( + Invocation.getter(#height), + returnValue: 0, + ) as int); + + @override + bool get debugDisposed => (super.noSuchMethod( + Invocation.getter(#debugDisposed), + returnValue: false, + ) as bool); + + @override + _i2.ColorSpace get colorSpace => (super.noSuchMethod( + Invocation.getter(#colorSpace), + returnValue: _i2.ColorSpace.sRGB, + ) as _i2.ColorSpace); + + @override + void dispose() => super.noSuchMethod( + Invocation.method( + #dispose, + [], + ), + returnValueForMissingStub: null, + ); + + @override + _i33.Future<_i31.ByteData?> toByteData( + {_i2.ImageByteFormat? format = _i2.ImageByteFormat.rawRgba}) => + (super.noSuchMethod( + Invocation.method( + #toByteData, + [], + {#format: format}, + ), + returnValue: _i33.Future<_i31.ByteData?>.value(), + ) as _i33.Future<_i31.ByteData?>); + + @override + _i2.Image clone() => (super.noSuchMethod( + Invocation.method( + #clone, + [], + ), + returnValue: _FakeImage_16( + this, + Invocation.method( + #clone, + [], + ), + ), + ) as _i2.Image); + + @override + bool isCloneOf(_i2.Image? other) => (super.noSuchMethod( + Invocation.method( + #isCloneOf, + [other], + ), + returnValue: false, + ) as bool); +} + +/// A class which mocks [LoadImageFromPhotoLibrary]. +/// +/// See the documentation for Mockito's code generation for more information. +class MockLoadImageFromPhotoLibrary extends _i1.Mock + implements _i34.LoadImageFromPhotoLibrary { + MockLoadImageFromPhotoLibrary() { + _i1.throwOnMissingStub(this); + } + + @override + _i17.IImageService get imageService => (super.noSuchMethod( + Invocation.getter(#imageService), + returnValue: _FakeIImageService_17( + this, + Invocation.getter(#imageService), + ), + ) as _i17.IImageService); + + @override + _i18.IPermissionService get permissionService => (super.noSuchMethod( + Invocation.getter(#permissionService), + returnValue: _FakeIPermissionService_18( + this, + Invocation.getter(#permissionService), + ), + ) as _i18.IPermissionService); + + @override + _i19.IPhotoLibraryService get photoLibraryService => (super.noSuchMethod( + Invocation.getter(#photoLibraryService), + returnValue: _FakeIPhotoLibraryService_19( + this, + Invocation.getter(#photoLibraryService), + ), + ) as _i19.IPhotoLibraryService); + + @override + _i33.Future<_i20.Result<_i2.Image, _i35.Failure>> call() => + (super.noSuchMethod( + Invocation.method( + #call, + [], + ), + returnValue: _i33.Future<_i20.Result<_i2.Image, _i35.Failure>>.value( + _FakeResult_20<_i2.Image, _i35.Failure>( + this, + Invocation.method( + #call, + [], + ), + )), + ) as _i33.Future<_i20.Result<_i2.Image, _i35.Failure>>); +} diff --git a/test/widget/workspace_page/import_tool_test.dart b/test/widget/workspace_page/import_tool_test.dart new file mode 100644 index 00000000..256b4ce5 --- /dev/null +++ b/test/widget/workspace_page/import_tool_test.dart @@ -0,0 +1,52 @@ +import 'package:flutter/material.dart'; +import 'package:flutter_riverpod/flutter_riverpod.dart'; +import 'package:flutter_test/flutter_test.dart'; +import 'package:paintroid/core/commands/command_factory/command_factory.dart'; +import 'package:paintroid/core/commands/command_manager/command_manager.dart'; +import 'package:paintroid/core/enums/tool_types.dart'; +import 'package:paintroid/core/providers/state/toolbox_state_data.dart'; +import 'package:paintroid/core/providers/state/toolbox_state_provider.dart'; +import 'package:paintroid/core/tools/bounding_box.dart'; +import 'package:paintroid/core/tools/implementation/import_tool.dart'; +import 'package:paintroid/ui/pages/workspace_page/components/top_bar/top_app_bar.dart'; +import 'package:paintroid/ui/utils/top_bar_action_data.dart'; + +import '../../utils/fake_toolbox_state_provider.dart'; + +void main() { + Widget createSut(ImportTool importTool) { + return ProviderScope( + overrides: [ + toolBoxStateProvider.overrideWith(() => FakeToolBoxStateProvider( + ToolBoxStateData(currentTool: importTool, isDown: false), + )), + ], + child: const MaterialApp( + home: Scaffold(appBar: TopAppBar(title: 'Paintroid')), + ), + ); + } + + ImportTool createImportTool() { + return ImportTool( + commandManager: CommandManager(), + commandFactory: const CommandFactory(), + boundingBox: BoundingBox.fromCenter( + center: const Offset(100, 100), + width: 100, + height: 100, + ), + type: ToolType.IMPORT, + ); + } + + testWidgets('shows a disabled checkmark until an image is selected', + (tester) async { + await tester.pumpWidget(createSut(createImportTool())); + + final checkmark = tester.widget( + find.byKey(const ValueKey(TopBarActionData.CHECKMARK.name)), + ); + expect(checkmark.onPressed, isNull); + }); +}