diff --git a/example/.metadata b/example/.metadata index 783bcdc2..95f73f55 100644 --- a/example/.metadata +++ b/example/.metadata @@ -1,10 +1,45 @@ # This file tracks properties of this Flutter project. # Used by Flutter tool to assess capabilities and perform upgrades etc. # -# This file should be version controlled and should not be manually edited. +# This file should be version controlled. version: - revision: 8962f6dc68ec8e2206ac2fa874da4a453856c7d3 + revision: fb57da5f945d02ef4f98dfd9409a72b7cce74268 channel: stable project_type: app + +# Tracks metadata for the flutter migrate command +migration: + platforms: + - platform: root + create_revision: fb57da5f945d02ef4f98dfd9409a72b7cce74268 + base_revision: fb57da5f945d02ef4f98dfd9409a72b7cce74268 + - platform: android + create_revision: fb57da5f945d02ef4f98dfd9409a72b7cce74268 + base_revision: fb57da5f945d02ef4f98dfd9409a72b7cce74268 + - platform: ios + create_revision: fb57da5f945d02ef4f98dfd9409a72b7cce74268 + base_revision: fb57da5f945d02ef4f98dfd9409a72b7cce74268 + - platform: linux + create_revision: fb57da5f945d02ef4f98dfd9409a72b7cce74268 + base_revision: fb57da5f945d02ef4f98dfd9409a72b7cce74268 + - platform: macos + create_revision: fb57da5f945d02ef4f98dfd9409a72b7cce74268 + base_revision: fb57da5f945d02ef4f98dfd9409a72b7cce74268 + - platform: web + create_revision: fb57da5f945d02ef4f98dfd9409a72b7cce74268 + base_revision: fb57da5f945d02ef4f98dfd9409a72b7cce74268 + - platform: windows + create_revision: fb57da5f945d02ef4f98dfd9409a72b7cce74268 + base_revision: fb57da5f945d02ef4f98dfd9409a72b7cce74268 + + # User provided section + + # List of Local paths (relative to this file) that should be + # ignored by the migrate tool. + # + # Files that are not part of the templates will be ignored by default. + unmanaged_files: + - 'lib/main.dart' + - 'ios/Runner.xcodeproj/project.pbxproj' diff --git a/example/lib/main.dart b/example/lib/main.dart index 08e3522f..25c89bd5 100644 --- a/example/lib/main.dart +++ b/example/lib/main.dart @@ -1,12 +1,8 @@ -import 'dart:typed_data'; -import 'dart:ui'; +import 'dart:ui' as ui; import 'package:flutter/foundation.dart'; import 'package:flutter/material.dart'; import 'package:flutter_painter/flutter_painter.dart'; - -import 'dart:ui' as ui; - import 'package:phosphor_flutter/phosphor_flutter.dart'; void main() => runApp(const MyApp()); @@ -19,8 +15,7 @@ class MyApp extends StatelessWidget { return MaterialApp( debugShowCheckedModeBanner: false, title: "Flutter Painter Example", - theme: ThemeData( - primaryColor: Colors.brown, accentColor: Colors.amberAccent), + theme: ThemeData(primaryColor: Colors.brown), home: const FlutterPainterExample(), ); } @@ -80,8 +75,7 @@ class _FlutterPainterExampleState extends State { settings: PainterSettings( text: TextSettings( focusNode: textFocusNode, - textStyle: const TextStyle( - fontWeight: FontWeight.bold, color: red, fontSize: 18), + textStyle: const TextStyle(fontWeight: FontWeight.bold, color: red, fontSize: 18), ), freeStyle: const FreeStyleSettings( color: red, @@ -105,8 +99,7 @@ class _FlutterPainterExampleState extends State { /// to use it as a background void initBackground() async { // Extension getter (.image) to get [ui.Image] from [ImageProvider] - final image = - await const NetworkImage('https://picsum.photos/1920/1080/').image; + final image = await const NetworkImage('https://picsum.photos/1920/1080/').image; setState(() { backgroundImage = image; @@ -136,9 +129,7 @@ class _FlutterPainterExampleState extends State { icon: const Icon( PhosphorIcons.trash, ), - onPressed: controller.selectedObjectDrawable == null - ? null - : removeSelectedDrawable, + onPressed: controller.selectedObjectDrawable == null ? null : removeSelectedDrawable, ), // Delete the selected drawable IconButton( @@ -181,12 +172,9 @@ class _FlutterPainterExampleState extends State { // Enforces constraints Positioned.fill( child: Center( - child: AspectRatio( - aspectRatio: - backgroundImage!.width / backgroundImage!.height, - child: FlutterPainter( - controller: controller, - ), + child: FlutterPainter( + aspectRatio: backgroundImage!.width / backgroundImage!.height, + controller: controller, ), ), ), @@ -206,22 +194,19 @@ class _FlutterPainterExampleState extends State { ), padding: const EdgeInsets.symmetric(horizontal: 15), decoration: const BoxDecoration( - borderRadius: - BorderRadius.vertical(top: Radius.circular(20)), + borderRadius: BorderRadius.vertical(top: Radius.circular(20)), color: Colors.white54, ), child: Column( mainAxisSize: MainAxisSize.min, children: [ - if (controller.freeStyleMode != - FreeStyleMode.none) ...[ + if (controller.freeStyleMode != FreeStyleMode.none) ...[ const Divider(), const Text("Free Style Settings"), // Control free style stroke width Row( children: [ - const Expanded( - flex: 1, child: Text("Stroke Width")), + const Expanded(flex: 1, child: Text("Stroke Width")), Expanded( flex: 3, child: Slider.adaptive( @@ -232,23 +217,18 @@ class _FlutterPainterExampleState extends State { ), ], ), - if (controller.freeStyleMode == - FreeStyleMode.draw) + if (controller.freeStyleMode == FreeStyleMode.draw) Row( children: [ - const Expanded( - flex: 1, child: Text("Color")), + const Expanded(flex: 1, child: Text("Color")), // Control free style color hue Expanded( flex: 3, child: Slider.adaptive( min: 0, max: 359.99, - value: HSVColor.fromColor( - controller.freeStyleColor) - .hue, - activeColor: - controller.freeStyleColor, + value: HSVColor.fromColor(controller.freeStyleColor).hue, + activeColor: controller.freeStyleColor, onChanged: setFreeStyleColor), ), ], @@ -260,15 +240,13 @@ class _FlutterPainterExampleState extends State { // Control text font size Row( children: [ - const Expanded( - flex: 1, child: Text("Font Size")), + const Expanded(flex: 1, child: Text("Font Size")), Expanded( flex: 3, child: Slider.adaptive( min: 8, max: 96, - value: - controller.textStyle.fontSize ?? 14, + value: controller.textStyle.fontSize ?? 14, onChanged: setTextFontSize), ), ], @@ -283,10 +261,7 @@ class _FlutterPainterExampleState extends State { child: Slider.adaptive( min: 0, max: 359.99, - value: HSVColor.fromColor( - controller.textStyle.color ?? - red) - .hue, + value: HSVColor.fromColor(controller.textStyle.color ?? red).hue, activeColor: controller.textStyle.color, onChanged: setTextColor), ), @@ -300,21 +275,15 @@ class _FlutterPainterExampleState extends State { // Control text color hue Row( children: [ - const Expanded( - flex: 1, child: Text("Stroke Width")), + const Expanded(flex: 1, child: Text("Stroke Width")), Expanded( flex: 3, child: Slider.adaptive( min: 2, max: 25, - value: controller - .shapePaint?.strokeWidth ?? - shapePaint.strokeWidth, + value: controller.shapePaint?.strokeWidth ?? shapePaint.strokeWidth, onChanged: (value) => - setShapeFactoryPaint( - (controller.shapePaint ?? - shapePaint) - .copyWith( + setShapeFactoryPaint((controller.shapePaint ?? shapePaint).copyWith( strokeWidth: value, ))), ), @@ -330,22 +299,11 @@ class _FlutterPainterExampleState extends State { child: Slider.adaptive( min: 0, max: 359.99, - value: HSVColor.fromColor( - (controller.shapePaint ?? - shapePaint) - .color) - .hue, - activeColor: (controller.shapePaint ?? - shapePaint) - .color, + value: HSVColor.fromColor((controller.shapePaint ?? shapePaint).color).hue, + activeColor: (controller.shapePaint ?? shapePaint).color, onChanged: (hue) => - setShapeFactoryPaint( - (controller.shapePaint ?? - shapePaint) - .copyWith( - color: HSVColor.fromAHSV( - 1, hue, 1, 1) - .toColor(), + setShapeFactoryPaint((controller.shapePaint ?? shapePaint).copyWith( + color: HSVColor.fromAHSV(1, hue, 1, 1).toColor(), ))), ), ], @@ -353,24 +311,15 @@ class _FlutterPainterExampleState extends State { Row( children: [ - const Expanded( - flex: 1, child: Text("Fill shape")), + const Expanded(flex: 1, child: Text("Fill shape")), Expanded( flex: 3, child: Center( child: Switch( - value: (controller.shapePaint ?? - shapePaint) - .style == - PaintingStyle.fill, + value: (controller.shapePaint ?? shapePaint).style == PaintingStyle.fill, onChanged: (value) => - setShapeFactoryPaint( - (controller.shapePaint ?? - shapePaint) - .copyWith( - style: value - ? PaintingStyle.fill - : PaintingStyle.stroke, + setShapeFactoryPaint((controller.shapePaint ?? shapePaint).copyWith( + style: value ? PaintingStyle.fill : PaintingStyle.stroke, ))), ), ), @@ -396,9 +345,8 @@ class _FlutterPainterExampleState extends State { IconButton( icon: Icon( PhosphorIcons.eraser, - color: controller.freeStyleMode == FreeStyleMode.erase - ? Theme.of(context).accentColor - : null, + color: + controller.freeStyleMode == FreeStyleMode.erase ? Theme.of(context).colorScheme.secondary : null, ), onPressed: toggleFreeStyleErase, ), @@ -406,9 +354,8 @@ class _FlutterPainterExampleState extends State { IconButton( icon: Icon( PhosphorIcons.scribbleLoop, - color: controller.freeStyleMode == FreeStyleMode.draw - ? Theme.of(context).accentColor - : null, + color: + controller.freeStyleMode == FreeStyleMode.draw ? Theme.of(context).colorScheme.secondary : null, ), onPressed: toggleFreeStyleDraw, ), @@ -416,9 +363,7 @@ class _FlutterPainterExampleState extends State { IconButton( icon: Icon( PhosphorIcons.textT, - color: textFocusNode.hasFocus - ? Theme.of(context).accentColor - : null, + color: textFocusNode.hasFocus ? Theme.of(context).colorScheme.secondary : null, ), onPressed: addText, ), @@ -459,9 +404,7 @@ class _FlutterPainterExampleState extends State { padding: const EdgeInsets.all(8.0), child: Icon( getShapeIcon(controller.shapeFactory), - color: controller.shapeFactory != null - ? Theme.of(context).accentColor - : null, + color: controller.shapeFactory != null ? Theme.of(context).colorScheme.secondary : null, ), ), ) @@ -469,7 +412,7 @@ class _FlutterPainterExampleState extends State { IconButton( icon: Icon( getShapeIcon(controller.shapeFactory), - color: Theme.of(context).accentColor, + color: Theme.of(context).colorScheme.secondary, ), onPressed: () => selectShape(null), ), @@ -503,15 +446,12 @@ class _FlutterPainterExampleState extends State { } void toggleFreeStyleDraw() { - controller.freeStyleMode = controller.freeStyleMode != FreeStyleMode.draw - ? FreeStyleMode.draw - : FreeStyleMode.none; + controller.freeStyleMode = controller.freeStyleMode != FreeStyleMode.draw ? FreeStyleMode.draw : FreeStyleMode.none; } void toggleFreeStyleErase() { - controller.freeStyleMode = controller.freeStyleMode != FreeStyleMode.erase - ? FreeStyleMode.erase - : FreeStyleMode.none; + controller.freeStyleMode = + controller.freeStyleMode != FreeStyleMode.erase ? FreeStyleMode.erase : FreeStyleMode.none; } void addText() { @@ -528,8 +468,7 @@ class _FlutterPainterExampleState extends State { imagesLinks: imageLinks, )); if (imageLink == null) return; - controller.addImage( - await NetworkImage(imageLink).image, const Size(100, 100)); + controller.addImage(await NetworkImage(imageLink).image, const Size(100, 100)); } void setFreeStyleStrokeWidth(double value) { @@ -543,9 +482,8 @@ class _FlutterPainterExampleState extends State { void setTextFontSize(double size) { // Set state is just to update the current UI, the [FlutterPainter] UI updates without it setState(() { - controller.textSettings = controller.textSettings.copyWith( - textStyle: - controller.textSettings.textStyle.copyWith(fontSize: size)); + controller.textSettings = + controller.textSettings.copyWith(textStyle: controller.textSettings.textStyle.copyWith(fontSize: size)); }); } @@ -557,8 +495,7 @@ class _FlutterPainterExampleState extends State { } void setTextColor(double hue) { - controller.textStyle = controller.textStyle - .copyWith(color: HSVColor.fromAHSV(1, hue, 1, 1).toColor()); + controller.textStyle = controller.textStyle.copyWith(color: HSVColor.fromAHSV(1, hue, 1, 1).toColor()); } void selectShape(ShapeFactory? factory) { @@ -567,14 +504,12 @@ class _FlutterPainterExampleState extends State { void renderAndDisplayImage() { if (backgroundImage == null) return; - final backgroundImageSize = Size( - backgroundImage!.width.toDouble(), backgroundImage!.height.toDouble()); + final backgroundImageSize = Size(backgroundImage!.width.toDouble(), backgroundImage!.height.toDouble()); // Render the image // Returns a [ui.Image] object, convert to to byte data and then to Uint8List - final imageFuture = controller - .renderImage(backgroundImageSize) - .then((ui.Image image) => image.pngBytes); + final imageFuture = + controller.renderImage(backgroundImageSize).then((ui.Image image) => image.pngBytes); // From here, you can write the PNG image data a file or do whatever you want with it // For example: @@ -585,9 +520,7 @@ class _FlutterPainterExampleState extends State { // I am going to display it using Image.memory // Show a dialog with the image - showDialog( - context: context, - builder: (context) => RenderedImageDialog(imageFuture: imageFuture)); + showDialog(context: context, builder: (context) => RenderedImageDialog(imageFuture: imageFuture)); } void removeSelectedDrawable() { @@ -599,16 +532,14 @@ class _FlutterPainterExampleState extends State { final imageDrawable = controller.selectedObjectDrawable; if (imageDrawable is! ImageDrawable) return; - controller.replaceDrawable( - imageDrawable, imageDrawable.copyWith(flipped: !imageDrawable.flipped)); + controller.replaceDrawable(imageDrawable, imageDrawable.copyWith(flipped: !imageDrawable.flipped)); } } class RenderedImageDialog extends StatelessWidget { final Future imageFuture; - const RenderedImageDialog({Key? key, required this.imageFuture}) - : super(key: key); + const RenderedImageDialog({Key? key, required this.imageFuture}) : super(key: key); @override Widget build(BuildContext context) { @@ -626,8 +557,7 @@ class RenderedImageDialog extends StatelessWidget { if (!snapshot.hasData || snapshot.data == null) { return const SizedBox(); } - return InteractiveViewer( - maxScale: 10, child: Image.memory(snapshot.data!)); + return InteractiveViewer(maxScale: 10, child: Image.memory(snapshot.data!)); }, ), ); @@ -637,8 +567,7 @@ class RenderedImageDialog extends StatelessWidget { class SelectStickerImageDialog extends StatelessWidget { final List imagesLinks; - const SelectStickerImageDialog({Key? key, this.imagesLinks = const []}) - : super(key: key); + const SelectStickerImageDialog({Key? key, this.imagesLinks = const []}) : super(key: key); @override Widget build(BuildContext context) { diff --git a/example/pubspec.lock b/example/pubspec.lock index 53535720..b1395d72 100644 --- a/example/pubspec.lock +++ b/example/pubspec.lock @@ -5,51 +5,50 @@ packages: dependency: transitive description: name: async - url: "https://pub.dartlang.org" + sha256: "947bfcf187f74dbc5e146c9eb9c0f10c9f8b30743e341481c1e2ed3ecc18c20c" + url: "https://pub.dev" source: hosted - version: "2.8.2" + version: "2.11.0" boolean_selector: dependency: transitive description: name: boolean_selector - url: "https://pub.dartlang.org" + sha256: "6cfb5af12253eaf2b368f07bacc5a80d1301a071c73360d746b7f2e32d762c66" + url: "https://pub.dev" source: hosted - version: "2.1.0" + version: "2.1.1" characters: dependency: transitive description: name: characters - url: "https://pub.dartlang.org" + sha256: "04a925763edad70e8443c99234dc3328f442e811f1d8fd1a72f1c8ad0f69a605" + url: "https://pub.dev" source: hosted - version: "1.2.0" - charcode: - dependency: transitive - description: - name: charcode - url: "https://pub.dartlang.org" - source: hosted - version: "1.3.1" + version: "1.3.0" clock: dependency: transitive description: name: clock - url: "https://pub.dartlang.org" + sha256: cb6d7f03e1de671e34607e909a7213e31d7752be4fb66a86d29fe1eb14bfb5cf + url: "https://pub.dev" source: hosted - version: "1.1.0" + version: "1.1.1" collection: dependency: transitive description: name: collection - url: "https://pub.dartlang.org" + sha256: "4a07be6cb69c84d677a6c3096fcf960cc3285a8330b4603e0d463d15d9bd934c" + url: "https://pub.dev" source: hosted - version: "1.16.0" + version: "1.17.1" fake_async: dependency: transitive description: name: fake_async - url: "https://pub.dartlang.org" + sha256: "511392330127add0b769b75a987850d136345d9227c6b94c96a04cf4a391bf78" + url: "https://pub.dev" source: hosted - version: "1.3.0" + version: "1.3.1" flutter: dependency: "direct main" description: flutter @@ -59,7 +58,8 @@ packages: dependency: "direct dev" description: name: flutter_lints - url: "https://pub.dartlang.org" + sha256: b543301ad291598523947dc534aaddc5aaad597b709d2426d3a0e0d44c5cb493 + url: "https://pub.dev" source: hosted version: "1.0.4" flutter_painter: @@ -74,46 +74,60 @@ packages: description: flutter source: sdk version: "0.0.0" + js: + dependency: transitive + description: + name: js + sha256: f2c445dce49627136094980615a031419f7f3eb393237e4ecd97ac15dea343f3 + url: "https://pub.dev" + source: hosted + version: "0.6.7" lints: dependency: transitive description: name: lints - url: "https://pub.dartlang.org" + sha256: a2c3d198cb5ea2e179926622d433331d8b58374ab8f29cdda6e863bd62fd369c + url: "https://pub.dev" source: hosted version: "1.0.1" matcher: dependency: transitive description: name: matcher - url: "https://pub.dartlang.org" + sha256: "6501fbd55da300384b768785b83e5ce66991266cec21af89ab9ae7f5ce1c4cbb" + url: "https://pub.dev" source: hosted - version: "0.12.11" + version: "0.12.15" material_color_utilities: dependency: transitive description: name: material_color_utilities - url: "https://pub.dartlang.org" + sha256: d92141dc6fe1dad30722f9aa826c7fbc896d021d792f80678280601aff8cf724 + url: "https://pub.dev" source: hosted - version: "0.1.4" + version: "0.2.0" meta: dependency: transitive description: name: meta - url: "https://pub.dartlang.org" + sha256: "3c74dbf8763d36539f114c799d8a2d87343b5067e9d796ca22b5eb8437090ee3" + url: "https://pub.dev" source: hosted - version: "1.7.0" + version: "1.9.1" path: dependency: transitive description: name: path - url: "https://pub.dartlang.org" + sha256: "8829d8a55c13fc0e37127c29fedf290c102f4e40ae94ada574091fe0ff96c917" + url: "https://pub.dev" source: hosted - version: "1.8.1" + version: "1.8.3" phosphor_flutter: dependency: "direct main" description: name: phosphor_flutter - url: "https://pub.dartlang.org" + sha256: "82aee69109d55518abbc5d77aeb893bfd2d39796aa51b871cadf2e56d03fa8e3" + url: "https://pub.dev" source: hosted version: "1.4.0" sky_engine: @@ -125,51 +139,58 @@ packages: dependency: transitive description: name: source_span - url: "https://pub.dartlang.org" + sha256: dd904f795d4b4f3b870833847c461801f6750a9fa8e61ea5ac53f9422b31f250 + url: "https://pub.dev" source: hosted - version: "1.8.2" + version: "1.9.1" stack_trace: dependency: transitive description: name: stack_trace - url: "https://pub.dartlang.org" + sha256: c3c7d8edb15bee7f0f74debd4b9c5f3c2ea86766fe4178eb2a18eb30a0bdaed5 + url: "https://pub.dev" source: hosted - version: "1.10.0" + version: "1.11.0" stream_channel: dependency: transitive description: name: stream_channel - url: "https://pub.dartlang.org" + sha256: "83615bee9045c1d322bbbd1ba209b7a749c2cbcdcb3fdd1df8eb488b3279c1c8" + url: "https://pub.dev" source: hosted - version: "2.1.0" + version: "2.1.1" string_scanner: dependency: transitive description: name: string_scanner - url: "https://pub.dartlang.org" + sha256: "556692adab6cfa87322a115640c11f13cb77b3f076ddcc5d6ae3c20242bedcde" + url: "https://pub.dev" source: hosted - version: "1.1.0" + version: "1.2.0" term_glyph: dependency: transitive description: name: term_glyph - url: "https://pub.dartlang.org" + sha256: a29248a84fbb7c79282b40b8c72a1209db169a2e0542bce341da992fe1bc7e84 + url: "https://pub.dev" source: hosted - version: "1.2.0" + version: "1.2.1" test_api: dependency: transitive description: name: test_api - url: "https://pub.dartlang.org" + sha256: eb6ac1540b26de412b3403a163d919ba86f6a973fe6cc50ae3541b80092fdcfb + url: "https://pub.dev" source: hosted - version: "0.4.9" + version: "0.5.1" vector_math: dependency: transitive description: name: vector_math - url: "https://pub.dartlang.org" + sha256: "80b3257d1492ce4d091729e3a67a60407d227c27241d6927be0130c98e741803" + url: "https://pub.dev" source: hosted - version: "2.1.2" + version: "2.1.4" sdks: - dart: ">=2.17.0-0 <3.0.0" - flutter: ">=1.17.0" + dart: ">=3.0.0 <4.0.0" + flutter: ">=3.0.0" diff --git a/example/test/widget_test.dart b/example/test/widget_test.dart new file mode 100644 index 00000000..092d222f --- /dev/null +++ b/example/test/widget_test.dart @@ -0,0 +1,30 @@ +// This is a basic Flutter widget test. +// +// To perform an interaction with a widget in your test, use the WidgetTester +// utility in the flutter_test package. For example, you can send tap and scroll +// gestures. You can also use WidgetTester to find child widgets in the widget +// tree, read text, and verify that the values of widget properties are correct. + +import 'package:flutter/material.dart'; +import 'package:flutter_test/flutter_test.dart'; + +import 'package:example/main.dart'; + +void main() { + testWidgets('Counter increments smoke test', (WidgetTester tester) async { + // Build our app and trigger a frame. + await tester.pumpWidget(const MyApp()); + + // Verify that our counter starts at 0. + expect(find.text('0'), findsOneWidget); + expect(find.text('1'), findsNothing); + + // Tap the '+' icon and trigger a frame. + await tester.tap(find.byIcon(Icons.add)); + await tester.pump(); + + // Verify that our counter has incremented. + expect(find.text('0'), findsNothing); + expect(find.text('1'), findsOneWidget); + }); +} diff --git a/lib/src/controllers/drawables/shape/double_arrow_drawable.dart b/lib/src/controllers/drawables/shape/double_arrow_drawable.dart index c23c5c79..4abdcf55 100644 --- a/lib/src/controllers/drawables/shape/double_arrow_drawable.dart +++ b/lib/src/controllers/drawables/shape/double_arrow_drawable.dart @@ -3,10 +3,10 @@ import 'dart:ui'; import 'package:flutter/foundation.dart'; import 'package:flutter/rendering.dart'; +import '../../../extensions/paint_copy_extension.dart'; import '../object_drawable.dart'; -import 'shape_drawable.dart'; import '../sized1ddrawable.dart'; -import '../../../extensions/paint_copy_extension.dart'; +import 'shape_drawable.dart'; /// A drawable of a arrow on both side shape. class DoubleArrowDrawable extends Sized1DDrawable implements ShapeDrawable { @@ -28,8 +28,7 @@ class DoubleArrowDrawable extends Sized1DDrawable implements ShapeDrawable { double rotationAngle = 0, double scale = 1, Set assists = const {}, - Map assistPaints = - const {}, + Map assistPaints = const {}, bool locked = false, bool hidden = false, }) : paint = paint ?? ShapeDrawable.defaultPaint, @@ -51,18 +50,17 @@ class DoubleArrowDrawable extends Sized1DDrawable implements ShapeDrawable { /// Add padding equal to the stroke width of the line and the size of the arrow head. @protected @override - EdgeInsets get padding => EdgeInsets.symmetric( - horizontal: paint.strokeWidth / 2, - vertical: paint.strokeWidth / 2 + (_arrowHeadSize / 2)); + EdgeInsets get padding => + EdgeInsets.symmetric(horizontal: paint.strokeWidth / 2, vertical: paint.strokeWidth / 2 + (_arrowHeadSize / 2)); /// Draws the arrow on the provided [canvas] of size [size]. @override void drawObject(Canvas canvas, Size size) { final arrowHeadSize = _arrowHeadSize; - final dx = length / 2 * scale - arrowHeadSize; + final dx = length / 2 * scale; - final start = position.translate(-length / 2 * scale + arrowHeadSize, 0); + final start = position.translate(-dx, 0); final end = position.translate(dx, 0); if ((end - start).dx > 0) canvas.drawLine(start, end, paint); diff --git a/lib/src/controllers/painter_controller.dart b/lib/src/controllers/painter_controller.dart index f2de522f..12ed2c4b 100644 --- a/lib/src/controllers/painter_controller.dart +++ b/lib/src/controllers/painter_controller.dart @@ -4,17 +4,17 @@ import 'dart:ui' as ui; import 'package:collection/collection.dart'; import 'package:flutter/material.dart'; -import 'events/selected_object_drawable_removed_event.dart'; + +import '../views/painters/painter.dart'; import '../views/widgets/painter_controller_widget.dart'; import 'actions/actions.dart'; -import 'drawables/image_drawable.dart'; -import 'events/events.dart'; import 'drawables/background/background_drawable.dart'; +import 'drawables/drawable.dart'; +import 'drawables/image_drawable.dart'; import 'drawables/object_drawable.dart'; +import 'events/events.dart'; +import 'events/selected_object_drawable_removed_event.dart'; import 'settings/settings.dart'; -import '../views/painters/painter.dart'; - -import 'drawables/drawable.dart'; /// Controller used to control a [FlutterPainter] widget. /// @@ -56,10 +56,8 @@ class PainterController extends ValueNotifier { PainterSettings settings = const PainterSettings(), List? drawables = const [], BackgroundDrawable? background, - }) : this.fromValue(PainterControllerValue( - settings: settings, - drawables: drawables ?? const [], - background: background)); + }) : this.fromValue( + PainterControllerValue(settings: settings, drawables: drawables ?? const [], background: background)); /// Create a [PainterController] from a [PainterControllerValue]. PainterController.fromValue(PainterControllerValue value) @@ -78,13 +76,11 @@ class PainterController extends ValueNotifier { /// that they need to update (it calls [notifyListeners]). For this reason, /// this value should only be set between frames, e.g. in response to user /// actions, not during the build, layout, or paint phases. - set background(BackgroundDrawable? background) => - value = value.copyWith(background: background); + set background(BackgroundDrawable? background) => value = value.copyWith(background: background); /// Queues used to track the actions performed on drawables in the controller. /// This is used to [undo] and [redo] actions. - Queue performedActions = DoubleLinkedQueue(), - unperformedActions = DoubleLinkedQueue(); + Queue performedActions = DoubleLinkedQueue(), unperformedActions = DoubleLinkedQueue(); /// Uses the [PainterControllerWidget] inherited widget to fetch the [PainterController] instance in this context. /// This is used internally in the library to fetch the controller at different widgets. @@ -118,8 +114,7 @@ class PainterController extends ValueNotifier { /// that they need to update (it calls [notifyListeners]). For this reason, /// this method should only be called between frames, e.g. in response to user /// actions, not during the build, layout, or paint phases. - void insertDrawables(int index, Iterable drawables, - {bool newAction = true}) { + void insertDrawables(int index, Iterable drawables, {bool newAction = true}) { final action = InsertDrawablesAction(index, drawables.toList()); action.perform(this); _addAction(action, newAction); @@ -140,8 +135,7 @@ class PainterController extends ValueNotifier { /// actions, not during the build, layout, or paint phases. /// /// [notifyListeners] will not be called if the return value is `false`. - bool replaceDrawable(Drawable oldDrawable, Drawable newDrawable, - {bool newAction = true}) { + bool replaceDrawable(Drawable oldDrawable, Drawable newDrawable, {bool newAction = true}) { final action = ReplaceDrawableAction(oldDrawable, newDrawable); final value = action.perform(this); if (value) _addAction(action, newAction); @@ -290,8 +284,7 @@ class PainterController extends ValueNotifier { /// ``` void addImage(ui.Image image, [Size? size]) { // Calculate the center of the painter - final renderBox = - painterKey.currentContext?.findRenderObject() as RenderBox?; + final renderBox = painterKey.currentContext?.findRenderObject() as RenderBox?; final center = renderBox == null ? Offset.zero : Offset( @@ -304,8 +297,7 @@ class PainterController extends ValueNotifier { if (size == null) { drawable = ImageDrawable(image: image, position: center); } else { - drawable = ImageDrawable.fittedToSize( - image: image, position: center, size: size); + drawable = ImageDrawable.fittedToSize(image: image, position: center, size: size); } addDrawables([drawable]); @@ -316,17 +308,25 @@ class PainterController extends ValueNotifier { /// The size of the output image is controlled by [size]. /// All drawables will be scaled according to that image size. Future renderImage(Size size) async { + final painterSize = painterKey.currentContext?.size; + + final imageSize = painterSize == null + ? null + : Size( + painterSize.width, + painterSize.width / size.aspectRatio, + ); + + print('passed: $size - imageSize: $imageSize - size: $painterSize'); final recorder = ui.PictureRecorder(); final canvas = Canvas(recorder); final painter = Painter( drawables: value.drawables, - scale: painterKey.currentContext?.size ?? size, + scale: imageSize, background: value.background, ); painter.paint(canvas, size); - return await recorder - .endRecording() - .toImage(size.width.floor(), size.height.floor()); + return await recorder.endRecording().toImage(size.width.floor(), size.height.floor()); } /// The currently selected object drawable. @@ -404,21 +404,16 @@ class PainterControllerValue { PainterControllerValue copyWith({ PainterSettings? settings, List? drawables, - BackgroundDrawable? background = - _NoBackgroundPassedBackgroundDrawable.instance, - ObjectDrawable? selectedObjectDrawable = - _NoObjectPassedBackgroundDrawable.instance, + BackgroundDrawable? background = _NoBackgroundPassedBackgroundDrawable.instance, + ObjectDrawable? selectedObjectDrawable = _NoObjectPassedBackgroundDrawable.instance, }) { return PainterControllerValue( settings: settings ?? this.settings, drawables: drawables ?? _drawables, - background: background == _NoBackgroundPassedBackgroundDrawable.instance - ? this.background - : background, - selectedObjectDrawable: - selectedObjectDrawable == _NoObjectPassedBackgroundDrawable.instance - ? this.selectedObjectDrawable - : selectedObjectDrawable, + background: background == _NoBackgroundPassedBackgroundDrawable.instance ? this.background : background, + selectedObjectDrawable: selectedObjectDrawable == _NoObjectPassedBackgroundDrawable.instance + ? this.selectedObjectDrawable + : selectedObjectDrawable, ); } @@ -433,16 +428,14 @@ class PainterControllerValue { } @override - int get hashCode => hashValues( - hashList(_drawables), background, settings, selectedObjectDrawable); + int get hashCode => hashValues(hashList(_drawables), background, settings, selectedObjectDrawable); } /// Private class that is used internally to represent no /// [BackgroundDrawable] argument passed for [PainterControllerValue.copyWith]. class _NoBackgroundPassedBackgroundDrawable extends BackgroundDrawable { /// Single instance. - static const _NoBackgroundPassedBackgroundDrawable instance = - _NoBackgroundPassedBackgroundDrawable._(); + static const _NoBackgroundPassedBackgroundDrawable instance = _NoBackgroundPassedBackgroundDrawable._(); /// Private constructor. const _NoBackgroundPassedBackgroundDrawable._() : super(); @@ -459,8 +452,7 @@ class _NoBackgroundPassedBackgroundDrawable extends BackgroundDrawable { /// [BackgroundDrawable] argument passed for [PainterControllerValue.copyWith]. class _NoObjectPassedBackgroundDrawable extends ObjectDrawable { /// Single instance. - static const _NoObjectPassedBackgroundDrawable instance = - _NoObjectPassedBackgroundDrawable._(); + static const _NoObjectPassedBackgroundDrawable instance = _NoObjectPassedBackgroundDrawable._(); /// Private constructor. const _NoObjectPassedBackgroundDrawable._() diff --git a/lib/src/views/widgets/flutter_painter.dart b/lib/src/views/widgets/flutter_painter.dart index 201af62d..b2453a18 100644 --- a/lib/src/views/widgets/flutter_painter.dart +++ b/lib/src/views/widgets/flutter_painter.dart @@ -1,41 +1,41 @@ import 'dart:async'; import 'dart:math'; +import 'dart:math' as math; import 'package:flutter/foundation.dart'; import 'package:flutter/gestures.dart'; import 'package:flutter/material.dart'; import 'package:flutter/rendering.dart'; -import '../../controllers/events/selected_object_drawable_removed_event.dart'; -import '../../controllers/helpers/renderer_check/renderer_check.dart'; + import '../../controllers/drawables/drawable.dart'; -import '../../controllers/notifications/notifications.dart'; -import '../../controllers/drawables/sized1ddrawable.dart'; +import '../../controllers/drawables/object_drawable.dart'; +import '../../controllers/drawables/path/path_drawables.dart'; import '../../controllers/drawables/shape/shape_drawable.dart'; +import '../../controllers/drawables/sized1ddrawable.dart'; import '../../controllers/drawables/sized2ddrawable.dart'; -import '../../controllers/drawables/object_drawable.dart'; -import '../../controllers/events/events.dart'; import '../../controllers/drawables/text_drawable.dart'; -import '../../controllers/drawables/path/path_drawables.dart'; -import '../../controllers/settings/settings.dart'; -import '../painters/painter.dart'; -import '../../controllers/painter_controller.dart'; +import '../../controllers/events/events.dart'; +import '../../controllers/events/selected_object_drawable_removed_event.dart'; import '../../controllers/helpers/border_box_shadow.dart'; +import '../../controllers/helpers/renderer_check/renderer_check.dart'; +import '../../controllers/notifications/notifications.dart'; +import '../../controllers/painter_controller.dart'; +import '../../controllers/settings/settings.dart'; import '../../extensions/painter_controller_helper_extension.dart'; +import '../painters/painter.dart'; import 'painter_controller_widget.dart'; -import 'dart:math' as math; part 'free_style_widget.dart'; -part 'text_widget.dart'; part 'object_widget.dart'; part 'shape_widget.dart'; +part 'text_widget.dart'; typedef DrawableCreatedCallback = Function(Drawable drawable); typedef DrawableDeletedCallback = Function(Drawable drawable); /// Defines the builder used with [FlutterPainter.builder] constructor. -typedef FlutterPainterBuilderCallback = Widget Function( - BuildContext context, Widget painter); +typedef FlutterPainterBuilderCallback = Widget Function(BuildContext context, Widget painter); /// Widget that allows user to draw on it class FlutterPainter extends StatelessWidget { @@ -54,6 +54,8 @@ class FlutterPainter extends StatelessWidget { /// Callback when the [PainterSettings] of [PainterController] are updated internally. final ValueChanged? onPainterSettingsChanged; + final double? aspectRatio; + /// The builder used to build this widget. /// /// Using the default constructor, it will default to returning the [_FlutterPainterWidget]. @@ -66,6 +68,7 @@ class FlutterPainter extends StatelessWidget { const FlutterPainter( {Key? key, required this.controller, + this.aspectRatio, this.onDrawableCreated, this.onDrawableDeleted, this.onSelectedObjectDrawableChanged, @@ -80,6 +83,7 @@ class FlutterPainter extends StatelessWidget { const FlutterPainter.builder( {Key? key, required this.controller, + this.aspectRatio, required FlutterPainterBuilderCallback builder, this.onDrawableCreated, this.onDrawableDeleted, @@ -100,11 +104,11 @@ class FlutterPainter extends StatelessWidget { _FlutterPainterWidget( key: controller.painterKey, controller: controller, + aspectRatio: aspectRatio, onDrawableCreated: onDrawableCreated, onDrawableDeleted: onDrawableDeleted, onPainterSettingsChanged: onPainterSettingsChanged, - onSelectedObjectDrawableChanged: - onSelectedObjectDrawableChanged, + onSelectedObjectDrawableChanged: onSelectedObjectDrawableChanged, )); }), ); @@ -121,6 +125,8 @@ class _FlutterPainterWidget extends StatelessWidget { /// The controller for this painter. final PainterController controller; + final double? aspectRatio; + /// Callback when a [Drawable] is created internally in [FlutterPainter]. final DrawableCreatedCallback? onDrawableCreated; @@ -137,6 +143,7 @@ class _FlutterPainterWidget extends StatelessWidget { const _FlutterPainterWidget( {Key? key, required this.controller, + this.aspectRatio, this.onDrawableCreated, this.onDrawableDeleted, this.onSelectedObjectDrawableChanged, @@ -151,37 +158,21 @@ class _FlutterPainterWidget extends StatelessWidget { opaque: false, pageBuilder: (context, animation, secondaryAnimation) { final controller = PainterController.of(context); + return NotificationListener( onNotification: onNotification, child: InteractiveViewer( transformationController: controller.transformationController, - minScale: controller.settings.scale.enabled - ? controller.settings.scale.minScale - : 1, - maxScale: controller.settings.scale.enabled - ? controller.settings.scale.maxScale - : 1, - panEnabled: controller.settings.scale.enabled && - (controller.freeStyleSettings.mode == FreeStyleMode.none), + minScale: controller.settings.scale.enabled ? controller.settings.scale.minScale : 1, + maxScale: controller.settings.scale.enabled ? controller.settings.scale.maxScale : 1, + panEnabled: + controller.settings.scale.enabled && (controller.freeStyleSettings.mode == FreeStyleMode.none), scaleEnabled: controller.settings.scale.enabled, - child: _FreeStyleWidget( - // controller: controller, - child: _TextWidget( - // controller: controller, - child: _ShapeWidget( - // controller: controller, - child: _ObjectWidget( - // controller: controller, - interactionEnabled: true, - child: CustomPaint( - painter: Painter( - drawables: controller.value.drawables, - background: controller.value.background, - ), - ), - ), - ), - )), + child: Center( + child: aspectRatio == null + ? _PainterWidget(controller) + : AspectRatio(aspectRatio: aspectRatio!, child: _PainterWidget(controller)), + ), ), ); })); @@ -201,3 +192,33 @@ class _FlutterPainterWidget extends StatelessWidget { return true; } } + +class _PainterWidget extends StatelessWidget { + _PainterWidget(this.controller, {Key? key}) : super(key: key); + + final PainterController controller; + + @override + Widget build(BuildContext context) { + return _FreeStyleWidget( + // controller: controller, + child: _TextWidget( + // controller: controller, + child: _ShapeWidget( + // controller: controller, + child: _ObjectWidget( + // controller: controller, + interactionEnabled: true, + child: ClipRect( + child: CustomPaint( + painter: Painter( + drawables: controller.value.drawables, + background: controller.value.background, + ), + ), + ), + ), + ), + )); + } +} diff --git a/lib/src/views/widgets/free_style_widget.dart b/lib/src/views/widgets/free_style_widget.dart index 126bdb27..9e915184 100644 --- a/lib/src/views/widgets/free_style_widget.dart +++ b/lib/src/views/widgets/free_style_widget.dart @@ -29,8 +29,7 @@ class _FreeStyleWidgetState extends State<_FreeStyleWidget> { return RawGestureDetector( behavior: HitTestBehavior.opaque, gestures: { - _DragGestureDetector: - GestureRecognizerFactoryWithHandlers<_DragGestureDetector>( + _DragGestureDetector: GestureRecognizerFactoryWithHandlers<_DragGestureDetector>( () => _DragGestureDetector( onHorizontalDragDown: _handleHorizontalDragDown, onHorizontalDragUpdate: _handleHorizontalDragUpdate, @@ -44,12 +43,10 @@ class _FreeStyleWidgetState extends State<_FreeStyleWidget> { } /// Getter for [FreeStyleSettings] from `widget.controller.value` to make code more readable. - FreeStyleSettings get settings => - PainterController.of(context).value.settings.freeStyle; + FreeStyleSettings get settings => PainterController.of(context).value.settings.freeStyle; /// Getter for [ShapeSettings] from `widget.controller.value` to make code more readable. - ShapeSettings get shapeSettings => - PainterController.of(context).value.settings.shape; + ShapeSettings get shapeSettings => PainterController.of(context).value.settings.shape; /// Callback when the user holds their pointer(s) down onto the widget. void _handleHorizontalDragDown(Offset globalPosition) { @@ -92,12 +89,10 @@ class _FreeStyleWidgetState extends State<_FreeStyleWidget> { // Add the new point to a copy of the current drawable final newDrawable = drawable.copyWith( - path: List.from(drawable.path) - ..add(_globalToLocal(globalPosition)), + path: List.from(drawable.path)..add(_globalToLocal(globalPosition)), ); // Replace the current drawable with the copy with the added point - PainterController.of(context) - .replaceDrawable(drawable, newDrawable, newAction: false); + PainterController.of(context).replaceDrawable(drawable, newDrawable, newAction: false); // Update the current drawable to be the new copy this.drawable = newDrawable; } diff --git a/lib/src/views/widgets/object_widget.dart b/lib/src/views/widgets/object_widget.dart index 885f9c07..688ba306 100644 --- a/lib/src/views/widgets/object_widget.dart +++ b/lib/src/views/widgets/object_widget.dart @@ -45,12 +45,10 @@ class _ObjectWidgetState extends State<_ObjectWidget> { double get objectPadding => 25 / transformationScale; /// Getter for the duration of fade-in and out animations for the object controls. - static Duration get controlsTransitionDuration => - const Duration(milliseconds: 100); + static Duration get controlsTransitionDuration => const Duration(milliseconds: 100); /// Getter for the size of the controls of the selected object. - double get controlsSize => - (settings.enlargeControlsResolver() ? 20 : 10) / transformationScale; + double get controlsSize => (settings.enlargeControlsResolver() ? 20 : 10) / transformationScale; /// Getter for the blur radius of the selected object highlighting. double get selectedBlurRadius => 2 / transformationScale; @@ -72,27 +70,20 @@ class _ObjectWidgetState extends State<_ObjectWidget> { /// Keeps track of widgets that have assist lines assigned to them. /// /// This is used to provide haptic feedback when the assist line appears. - Map> assistDrawables = { - for (var e in ObjectDrawableAssist.values) e: {} - }; + Map> assistDrawables = {for (var e in ObjectDrawableAssist.values) e: {}}; /// Keeps track of which controls are being used. /// /// Used to highlight the controls when they are in use. - Map controlsAreActive = { - for (var e in List.generate(8, (index) => index)) e: false - }; + Map controlsAreActive = {for (var e in List.generate(8, (index) => index)) e: false}; /// Subscription to the events coming from the controller. StreamSubscription? controllerEventSubscription; /// Getter for the list of [ObjectDrawable]s in the controller /// to make code more readable. - List get drawables => PainterController.of(context) - .value - .drawables - .whereType() - .toList(); + List get drawables => + PainterController.of(context).value.drawables.whereType().toList(); /// A flag on whether to cancel controls animation or not. /// This is used to cancel the animation after the selected object @@ -105,8 +96,7 @@ class _ObjectWidgetState extends State<_ObjectWidget> { // Listen to the stream of events from the paint controller WidgetsBinding.instance.addPostFrameCallback((timestamp) { - controllerEventSubscription = - PainterController.of(context).events.listen((event) { + controllerEventSubscription = PainterController.of(context).events.listen((event) { // When an [RemoveDrawableEvent] event is received and removed drawable is the selected object // cancel the animation. if (event is SelectedObjectDrawableRemovedEvent) { @@ -117,9 +107,7 @@ class _ObjectWidgetState extends State<_ObjectWidget> { }); // Listen to transformation changes of [InteractiveViewer]. - PainterController.of(context) - .transformationController - .addListener(onTransformUpdated); + PainterController.of(context).transformationController.addListener(onTransformUpdated); }); } @@ -140,17 +128,30 @@ class _ObjectWidgetState extends State<_ObjectWidget> { @override Widget build(BuildContext context) { final drawables = this.drawables; - final drawableAirTransformable = controller?.selectedObjectDrawable != null && controller?.shapeSettings.factory == null ; - final selectedDrawableEntry = drawableAirTransformable ? MapEntry (drawables.indexOf(controller!.selectedObjectDrawable!), controller!.selectedObjectDrawable!) : MapEntry (0, TextDrawable(position: Offset(0,0), text: '', )); + final drawableAirTransformable = + controller?.selectedObjectDrawable != null && controller?.shapeSettings.factory == null; + final selectedDrawableEntry = drawableAirTransformable + ? MapEntry( + drawables.indexOf(controller!.selectedObjectDrawable!), controller!.selectedObjectDrawable!) + : MapEntry( + 0, + TextDrawable( + position: Offset(0, 0), + text: '', + )); return LayoutBuilder(builder: (context, constraints) { return Stack( children: [ Positioned.fill( child: GestureDetector( onTap: onBackgroundTapped, - onScaleStart: drawableAirTransformable ? (details) => onDrawableScaleStart(selectedDrawableEntry, details) : null, - onScaleUpdate: drawableAirTransformable ? (details) => onDrawableScaleUpdate(selectedDrawableEntry, details) : null, - onScaleEnd: drawableAirTransformable ? (_) => onDrawableScaleEnd(selectedDrawableEntry) : null, + onScaleStart: drawableAirTransformable + ? (details) => onDrawableScaleStart(selectedDrawableEntry, details) + : null, + onScaleUpdate: drawableAirTransformable + ? (details) => onDrawableScaleUpdate(selectedDrawableEntry, details) + : null, + onScaleEnd: drawableAirTransformable ? (_) => onDrawableScaleEnd(selectedDrawableEntry) : null, child: widget.child)), ...drawables.asMap().entries.map((entry) { final drawable = entry.value; @@ -175,16 +176,12 @@ class _ObjectWidgetState extends State<_ObjectWidget> { child: freeStyleSettings.mode != FreeStyleMode.none ? widget : MouseRegion( - cursor: drawable.locked - ? MouseCursor.defer - : SystemMouseCursors.allScroll, + cursor: drawable.locked ? MouseCursor.defer : SystemMouseCursors.allScroll, child: GestureDetector( behavior: HitTestBehavior.opaque, onTap: () => tapDrawable(drawable), - onScaleStart: (details) => - onDrawableScaleStart(entry, details), - onScaleUpdate: (details) => - onDrawableScaleUpdate(entry, details), + onScaleStart: (details) => onDrawableScaleStart(entry, details), + onScaleUpdate: (details) => onDrawableScaleUpdate(entry, details), onScaleEnd: (_) => onDrawableScaleEnd(entry), child: AnimatedSwitcher( duration: controlsTransitionDuration, @@ -193,171 +190,110 @@ class _ObjectWidgetState extends State<_ObjectWidget> { children: [ widget, Positioned( - top: objectPadding - - (controlsSize / 2), - bottom: objectPadding - - (controlsSize / 2), - left: objectPadding - - (controlsSize / 2), - right: objectPadding - - (controlsSize / 2), + top: objectPadding - (controlsSize / 2), + bottom: objectPadding - (controlsSize / 2), + left: objectPadding - (controlsSize / 2), + right: objectPadding - (controlsSize / 2), child: Builder( builder: (context) { if (usingHtmlRenderer) { return Container( decoration: BoxDecoration( - border: Border.all( - color: Colors.black, - width: - selectedBorderWidth), + border: Border.all(color: Colors.black, width: selectedBorderWidth), ), child: Container( decoration: BoxDecoration( - border: Border.all( - color: Colors.white, - width: - selectedBorderWidth), + border: + Border.all(color: Colors.white, width: selectedBorderWidth), ), ), ); } return Container( decoration: BoxDecoration( - border: Border.all( - color: Colors.white, - width: - selectedBorderWidth), + border: Border.all(color: Colors.white, width: selectedBorderWidth), boxShadow: [ BorderBoxShadow( color: Colors.black, - blurRadius: - selectedBlurRadius, + blurRadius: selectedBlurRadius, ) ]), ); }, ), ), - if (settings - .showScaleRotationControlsResolver()) ...[ + if (settings.showScaleRotationControlsResolver()) ...[ Positioned( top: objectPadding - (controlsSize), - left: - objectPadding - (controlsSize), + left: objectPadding - (controlsSize), width: controlsSize, height: controlsSize, child: MouseRegion( - cursor: SystemMouseCursors - .resizeUpLeft, + cursor: SystemMouseCursors.resizeUpLeft, child: GestureDetector( - onPanStart: (details) => - onScaleControlPanStart( - 0, entry, details), + onPanStart: (details) => onScaleControlPanStart(0, entry, details), onPanUpdate: (details) => - onScaleControlPanUpdate( - entry, - details, - constraints, - true), - onPanEnd: (details) => - onScaleControlPanEnd( - 0, entry, details), + onScaleControlPanUpdate(entry, details, constraints, true), + onPanEnd: (details) => onScaleControlPanEnd(0, entry, details), child: _ObjectControlBox( - active: - controlsAreActive[0] ?? - false, + active: controlsAreActive[0] ?? false, ), ), ), ), Positioned( - bottom: - objectPadding - (controlsSize), - left: - objectPadding - (controlsSize), + bottom: objectPadding - (controlsSize), + left: objectPadding - (controlsSize), width: controlsSize, height: controlsSize, child: MouseRegion( - cursor: SystemMouseCursors - .resizeDownLeft, + cursor: SystemMouseCursors.resizeDownLeft, child: GestureDetector( - onPanStart: (details) => - onScaleControlPanStart( - 1, entry, details), + onPanStart: (details) => onScaleControlPanStart(1, entry, details), onPanUpdate: (details) => - onScaleControlPanUpdate( - entry, - details, - constraints, - true), - onPanEnd: (details) => - onScaleControlPanEnd( - 1, entry, details), + onScaleControlPanUpdate(entry, details, constraints, true), + onPanEnd: (details) => onScaleControlPanEnd(1, entry, details), child: _ObjectControlBox( - active: - controlsAreActive[1] ?? - false, + active: controlsAreActive[1] ?? false, ), ), ), ), Positioned( top: objectPadding - (controlsSize), - right: - objectPadding - (controlsSize), + right: objectPadding - (controlsSize), width: controlsSize, height: controlsSize, child: MouseRegion( - cursor: initialScaleDrawables - .containsKey(entry.key) + cursor: initialScaleDrawables.containsKey(entry.key) ? SystemMouseCursors.grabbing : SystemMouseCursors.grab, child: GestureDetector( - onPanStart: (details) => - onRotationControlPanStart( - 2, entry, details), + onPanStart: (details) => onRotationControlPanStart(2, entry, details), onPanUpdate: (details) => - onRotationControlPanUpdate( - entry, details, size), - onPanEnd: (details) => - onRotationControlPanEnd( - 2, entry, details), + onRotationControlPanUpdate(entry, details, size), + onPanEnd: (details) => onRotationControlPanEnd(2, entry, details), child: _ObjectControlBox( shape: BoxShape.circle, - active: - controlsAreActive[2] ?? - false, + active: controlsAreActive[2] ?? false, ), ), ), ), Positioned( - bottom: - objectPadding - (controlsSize), - right: - objectPadding - (controlsSize), + bottom: objectPadding - (controlsSize), + right: objectPadding - (controlsSize), width: controlsSize, height: controlsSize, child: MouseRegion( - cursor: SystemMouseCursors - .resizeDownRight, + cursor: SystemMouseCursors.resizeDownRight, child: GestureDetector( - onPanStart: (details) => - onScaleControlPanStart( - 3, entry, details), + onPanStart: (details) => onScaleControlPanStart(3, entry, details), onPanUpdate: (details) => - onScaleControlPanUpdate( - entry, - details, - constraints, - false), - onPanEnd: (details) => - onScaleControlPanEnd( - 3, entry, details), + onScaleControlPanUpdate(entry, details, constraints, false), + onPanEnd: (details) => onScaleControlPanEnd(3, entry, details), child: _ObjectControlBox( - active: - controlsAreActive[3] ?? - false, + active: controlsAreActive[3] ?? false, ), ), ), @@ -366,131 +302,72 @@ class _ObjectWidgetState extends State<_ObjectWidget> { if (entry.value is Sized2DDrawable) ...[ Positioned( top: objectPadding - (controlsSize), - left: (size.width / 2) + - objectPadding - - (controlsSize / 2), + left: (size.width / 2) + objectPadding - (controlsSize / 2), width: controlsSize, height: controlsSize, child: MouseRegion( - cursor: - SystemMouseCursors.resizeUp, + cursor: SystemMouseCursors.resizeUp, child: GestureDetector( - onPanStart: (details) => - onResizeControlPanStart( - 4, entry, details), - onPanUpdate: (details) => - onResizeControlPanUpdate( - entry, - details, - constraints, - Axis.vertical, - true), - onPanEnd: (details) => - onResizeControlPanEnd( - 4, entry, details), + onPanStart: (details) => onResizeControlPanStart(4, entry, details), + onPanUpdate: (details) => onResizeControlPanUpdate( + entry, details, constraints, Axis.vertical, true), + onPanEnd: (details) => onResizeControlPanEnd(4, entry, details), child: _ObjectControlBox( - active: - controlsAreActive[4] ?? - false, + active: controlsAreActive[4] ?? false, ), ), ), ), Positioned( - bottom: - objectPadding - (controlsSize), - left: (size.width / 2) + - objectPadding - - (controlsSize / 2), + bottom: objectPadding - (controlsSize), + left: (size.width / 2) + objectPadding - (controlsSize / 2), width: controlsSize, height: controlsSize, child: MouseRegion( - cursor: - SystemMouseCursors.resizeDown, + cursor: SystemMouseCursors.resizeDown, child: GestureDetector( - onPanStart: (details) => - onResizeControlPanStart( - 5, entry, details), - onPanUpdate: (details) => - onResizeControlPanUpdate( - entry, - details, - constraints, - Axis.vertical, - false), - onPanEnd: (details) => - onResizeControlPanEnd( - 5, entry, details), + onPanStart: (details) => onResizeControlPanStart(5, entry, details), + onPanUpdate: (details) => onResizeControlPanUpdate( + entry, details, constraints, Axis.vertical, false), + onPanEnd: (details) => onResizeControlPanEnd(5, entry, details), child: _ObjectControlBox( - active: - controlsAreActive[5] ?? - false, + active: controlsAreActive[5] ?? false, ), ), ), ), Positioned( - left: - objectPadding - (controlsSize), - top: (size.height / 2) + - objectPadding - - (controlsSize / 2), + left: objectPadding - (controlsSize), + top: (size.height / 2) + objectPadding - (controlsSize / 2), width: controlsSize, height: controlsSize, child: MouseRegion( - cursor: - SystemMouseCursors.resizeLeft, + cursor: SystemMouseCursors.resizeLeft, child: GestureDetector( - onPanStart: (details) => - onResizeControlPanStart( - 6, entry, details), - onPanUpdate: (details) => - onResizeControlPanUpdate( - entry, - details, - constraints, - Axis.horizontal, - true), - onPanEnd: (details) => - onResizeControlPanEnd( - 6, entry, details), + onPanStart: (details) => onResizeControlPanStart(6, entry, details), + onPanUpdate: (details) => onResizeControlPanUpdate( + entry, details, constraints, Axis.horizontal, true), + onPanEnd: (details) => onResizeControlPanEnd(6, entry, details), child: _ObjectControlBox( - active: - controlsAreActive[6] ?? - false, + active: controlsAreActive[6] ?? false, ), ), ), ), Positioned( - right: - objectPadding - (controlsSize), - top: (size.height / 2) + - objectPadding - - (controlsSize / 2), + right: objectPadding - (controlsSize), + top: (size.height / 2) + objectPadding - (controlsSize / 2), width: controlsSize, height: controlsSize, child: MouseRegion( - cursor: SystemMouseCursors - .resizeRight, + cursor: SystemMouseCursors.resizeRight, child: GestureDetector( - onPanStart: (details) => - onResizeControlPanStart( - 7, entry, details), - onPanUpdate: (details) => - onResizeControlPanUpdate( - entry, - details, - constraints, - Axis.horizontal, - false), - onPanEnd: (details) => - onResizeControlPanEnd( - 7, entry, details), + onPanStart: (details) => onResizeControlPanStart(7, entry, details), + onPanUpdate: (details) => onResizeControlPanUpdate( + entry, details, constraints, Axis.horizontal, false), + onPanEnd: (details) => onResizeControlPanEnd(7, entry, details), child: _ObjectControlBox( - active: - controlsAreActive[7] ?? - false, + active: controlsAreActive[7] ?? false, ), ), ), @@ -510,8 +387,7 @@ class _ObjectWidgetState extends State<_ObjectWidget> { cancelControlsAnimation = false; return child ?? const SizedBox(); } - return AnimatedSwitcher.defaultLayoutBuilder( - child, previousChildren); + return AnimatedSwitcher.defaultLayoutBuilder(child, previousChildren); }, ), ), @@ -548,15 +424,13 @@ class _ObjectWidgetState extends State<_ObjectWidget> { } /// Getter for the [ObjectSettings] from the controller to make code more readable. - ObjectSettings get settings => - PainterController.of(context).value.settings.object; + ObjectSettings get settings => PainterController.of(context).value.settings.object; /// Getter for the [FreeStyleSettings] from the controller to make code more readable. /// /// This is used to disable object movement, scaling and rotation /// when free-style drawing is enabled. - FreeStyleSettings get freeStyleSettings => - PainterController.of(context).value.settings.freeStyle; + FreeStyleSettings get freeStyleSettings => PainterController.of(context).value.settings.freeStyle; /// Triggers when the user taps an empty space. /// @@ -591,8 +465,7 @@ class _ObjectWidgetState extends State<_ObjectWidget> { /// Callback when the object drawable starts being moved, scaled and/or rotated. /// /// Saves the initial point of interaction and drawable to be used on update events. - void onDrawableScaleStart( - MapEntry entry, ScaleStartDetails details) { + void onDrawableScaleStart(MapEntry entry, ScaleStartDetails details) { if (!widget.interactionEnabled) return; final index = entry.key; @@ -614,8 +487,7 @@ class _ObjectWidgetState extends State<_ObjectWidget> { final rotateOffset = Matrix4.rotationZ(drawable.rotationAngle) ..translate(details.localFocalPoint.dx, details.localFocalPoint.dy) ..rotateZ(-drawable.rotationAngle); - drawableInitialLocalFocalPoints[index] = - Offset(rotateOffset[12], rotateOffset[13]); + drawableInitialLocalFocalPoints[index] = Offset(rotateOffset[12], rotateOffset[13]); updateDrawable(drawable, drawable, newAction: true); } @@ -652,8 +524,7 @@ class _ObjectWidgetState extends State<_ObjectWidget> { /// Callback when the object drawable is moved, scaled and/or rotated. /// /// Calculates the next position, scale and rotation of the object depending on the event details. - void onDrawableScaleUpdate( - MapEntry entry, ScaleUpdateDetails details) { + void onDrawableScaleUpdate(MapEntry entry, ScaleUpdateDetails details) { if (!widget.interactionEnabled) return; final index = entry.key; @@ -665,8 +536,7 @@ class _ObjectWidgetState extends State<_ObjectWidget> { // This causes events from rotated objects to behave incorrectly // So, a [Matrix4] is used to transform the needed event details to be consistent with // the current rotation of the object - final initialLocalFocalPoint = - drawableInitialLocalFocalPoints[index] ?? Offset.zero; + final initialLocalFocalPoint = drawableInitialLocalFocalPoints[index] ?? Offset.zero; if (initialDrawable == null) return; @@ -681,8 +551,7 @@ class _ObjectWidgetState extends State<_ObjectWidget> { ..rotateZ(initialRotation) ..translate(details.localFocalPoint.dx, details.localFocalPoint.dy) ..rotateZ(-initialRotation); - final position = - initialPosition + Offset(rotateOffset[12], rotateOffset[13]); + final position = initialPosition + Offset(rotateOffset[12], rotateOffset[13]); // Calculate scale of object reference to the initial object scale final scale = initialDrawable.scale * details.scale; @@ -718,10 +587,7 @@ class _ObjectWidgetState extends State<_ObjectWidget> { // The set of assists for the object // If layout assist is disabled, it is empty final assists = settings.layoutAssist.enabled - ? assistDrawables.entries - .where((element) => element.value.contains(index)) - .map((e) => e.key) - .toSet() + ? assistDrawables.entries.where((element) => element.value.contains(index)).map((e) => e.key).toSet() : {}; // Do not display the rotational assist if the user is using less that 2 pointers @@ -732,15 +598,12 @@ class _ObjectWidgetState extends State<_ObjectWidget> { // and layout assist is enabled final assistedPosition = Offset( assists.contains(ObjectDrawableAssist.vertical) ? center.dx : position.dx, - assists.contains(ObjectDrawableAssist.horizontal) - ? center.dy - : position.dy, + assists.contains(ObjectDrawableAssist.horizontal) ? center.dy : position.dy, ); // Snap the object rotation to the nearest angle from [assistAngles] if its near it // and layout assist is enabled - final assistedRotation = assists.contains(ObjectDrawableAssist.rotation) && - closestAssistAngle != null + final assistedRotation = assists.contains(ObjectDrawableAssist.rotation) && closestAssistAngle != null ? closestAssistAngle.remainder(pi * 2) : rotation; @@ -755,24 +618,20 @@ class _ObjectWidgetState extends State<_ObjectWidget> { } /// Calculates whether the object entered or exited the horizontal and vertical assist areas. - void calculatePositionalAssists(ObjectLayoutAssistSettings settings, - int index, Offset position, Offset center) { + void calculatePositionalAssists(ObjectLayoutAssistSettings settings, int index, Offset position, Offset center) { // Horizontal // // If the object is within the enter distance from the center dy and isn't marked // as a drawable with a horizontal assist, mark it if ((position.dy - center.dy).abs() < settings.positionalEnterDistance && - !(assistDrawables[ObjectDrawableAssist.horizontal]?.contains(index) ?? - false)) { + !(assistDrawables[ObjectDrawableAssist.horizontal]?.contains(index) ?? false)) { assistDrawables[ObjectDrawableAssist.horizontal]?.add(index); settings.hapticFeedback.impact(); } // Otherwise, if the object is outside the exit distance from the center dy and is marked as // as a drawable with a horizontal assist, un-mark it - else if ((position.dy - center.dy).abs() > - settings.positionalExitDistance && - (assistDrawables[ObjectDrawableAssist.horizontal]?.contains(index) ?? - false)) { + else if ((position.dy - center.dy).abs() > settings.positionalExitDistance && + (assistDrawables[ObjectDrawableAssist.horizontal]?.contains(index) ?? false)) { assistDrawables[ObjectDrawableAssist.horizontal]?.remove(index); } @@ -781,17 +640,14 @@ class _ObjectWidgetState extends State<_ObjectWidget> { // If the object is within the enter distance from the center dx and isn't marked // as a drawable with a vertical assist, mark it if ((position.dx - center.dx).abs() < settings.positionalEnterDistance && - !(assistDrawables[ObjectDrawableAssist.vertical]?.contains(index) ?? - false)) { + !(assistDrawables[ObjectDrawableAssist.vertical]?.contains(index) ?? false)) { assistDrawables[ObjectDrawableAssist.vertical]?.add(index); settings.hapticFeedback.impact(); } // Otherwise, if the object is outside the exit distance from the center dx and is marked as // as a drawable with a vertical assist, un-mark it - else if ((position.dx - center.dx).abs() > - settings.positionalExitDistance && - (assistDrawables[ObjectDrawableAssist.vertical]?.contains(index) ?? - false)) { + else if ((position.dx - center.dx).abs() > settings.positionalExitDistance && + (assistDrawables[ObjectDrawableAssist.vertical]?.contains(index) ?? false)) { assistDrawables[ObjectDrawableAssist.vertical]?.remove(index); } } @@ -799,22 +655,16 @@ class _ObjectWidgetState extends State<_ObjectWidget> { /// Calculates whether the object entered or exited the rotational assist range. /// /// Returns the angle the object is closest to if it is inside the assist range. - double? calculateRotationalAssist( - ObjectLayoutAssistSettings settings, int index, double rotation) { + double? calculateRotationalAssist(ObjectLayoutAssistSettings settings, int index, double rotation) { // Calculates all angles from [assistAngles] in the exit range of rotational assist - final closeAngles = assistAngles - .where( - (angle) => (rotation - angle).abs() < settings.rotationalExitAngle) - .toList(); + final closeAngles = assistAngles.where((angle) => (rotation - angle).abs() < settings.rotationalExitAngle).toList(); // If the object is close to at least one assist angle if (closeAngles.isNotEmpty) { // If the object is also in the enter range of rotational assist and isn't marked // as a drawable with a rotational assist, mark it - if (closeAngles.any((angle) => - (rotation - angle).abs() < settings.rotationalEnterAngle) && - !(assistDrawables[ObjectDrawableAssist.rotation]?.contains(index) ?? - false)) { + if (closeAngles.any((angle) => (rotation - angle).abs() < settings.rotationalEnterAngle) && + !(assistDrawables[ObjectDrawableAssist.rotation]?.contains(index) ?? false)) { assistDrawables[ObjectDrawableAssist.rotation]?.add(index); settings.hapticFeedback.impact(); } @@ -824,9 +674,7 @@ class _ObjectWidgetState extends State<_ObjectWidget> { // Otherwise, if the object is not in the exit range of any assist angles, // but is marked as a drawable with rotational assist, un-mark it - if (closeAngles.isEmpty && - (assistDrawables[ObjectDrawableAssist.rotation]?.contains(index) ?? - false)) { + if (closeAngles.isEmpty && (assistDrawables[ObjectDrawableAssist.rotation]?.contains(index) ?? false)) { assistDrawables[ObjectDrawableAssist.rotation]?.remove(index); } @@ -837,10 +685,7 @@ class _ObjectWidgetState extends State<_ObjectWidget> { /// /// Uses the [GlobalKey] for the painter from [controller]. Offset get center { - final renderBox = PainterController.of(context) - .painterKey - .currentContext - ?.findRenderObject() as RenderBox?; + final renderBox = PainterController.of(context).painterKey.currentContext?.findRenderObject() as RenderBox?; final center = renderBox == null ? Offset.zero : Offset( @@ -851,16 +696,13 @@ class _ObjectWidgetState extends State<_ObjectWidget> { } /// Replaces a drawable with a new one. - void updateDrawable(ObjectDrawable oldDrawable, ObjectDrawable newDrawable, - {bool newAction = false}) { + void updateDrawable(ObjectDrawable oldDrawable, ObjectDrawable newDrawable, {bool newAction = false}) { setState(() { - PainterController.of(context) - .replaceDrawable(oldDrawable, newDrawable, newAction: newAction); + PainterController.of(context).replaceDrawable(oldDrawable, newDrawable, newAction: newAction); }); } - void onRotationControlPanStart(int controlIndex, - MapEntry entry, DragStartDetails details) { + void onRotationControlPanStart(int controlIndex, MapEntry entry, DragStartDetails details) { setState(() { controlsAreActive[controlIndex] = true; }); @@ -872,15 +714,13 @@ class _ObjectWidgetState extends State<_ObjectWidget> { )); } - void onRotationControlPanUpdate(MapEntry entry, - DragUpdateDetails details, Size size) { + void onRotationControlPanUpdate(MapEntry entry, DragUpdateDetails details, Size size) { final index = entry.key; final initial = initialScaleDrawables[index]; if (initial == null) return; final initialOffset = Offset((size.width / 2), (-size.height / 2)); final initialAngle = atan2(initialOffset.dx, initialOffset.dy); - final angle = atan2((details.localPosition.dx + initialOffset.dx), - (details.localPosition.dy + initialOffset.dy)); + final angle = atan2((details.localPosition.dx + initialOffset.dx), (details.localPosition.dy + initialOffset.dy)); final rotation = initialAngle - angle; onDrawableScaleUpdate( entry, @@ -892,16 +732,14 @@ class _ObjectWidgetState extends State<_ObjectWidget> { )); } - void onRotationControlPanEnd(int controlIndex, - MapEntry entry, DragEndDetails details) { + void onRotationControlPanEnd(int controlIndex, MapEntry entry, DragEndDetails details) { setState(() { controlsAreActive[controlIndex] = false; }); onDrawableScaleEnd(entry); } - void onScaleControlPanStart(int controlIndex, - MapEntry entry, DragStartDetails details) { + void onScaleControlPanStart(int controlIndex, MapEntry entry, DragStartDetails details) { setState(() { controlsAreActive[controlIndex] = true; }); @@ -913,8 +751,8 @@ class _ObjectWidgetState extends State<_ObjectWidget> { )); } - void onScaleControlPanUpdate(MapEntry entry, - DragUpdateDetails details, BoxConstraints constraints, + void onScaleControlPanUpdate( + MapEntry entry, DragUpdateDetails details, BoxConstraints constraints, [bool isReversed = true]) { final index = entry.key; final initial = initialScaleDrawables[index]; @@ -922,9 +760,7 @@ class _ObjectWidgetState extends State<_ObjectWidget> { final length = details.localPosition.dx * (isReversed ? -1 : 1); final initialSize = initial.getSize(maxWidth: constraints.maxWidth); final initialLength = initialSize.width / 2; - final double scale = initialLength == 0 - ? (length * 2) - : ((length + initialLength) / initialLength); + final double scale = initialLength == 0 ? (length * 2) : ((length + initialLength) / initialLength); onDrawableScaleUpdate( entry, ScaleUpdateDetails( @@ -935,16 +771,14 @@ class _ObjectWidgetState extends State<_ObjectWidget> { )); } - void onScaleControlPanEnd(int controlIndex, - MapEntry entry, DragEndDetails details) { + void onScaleControlPanEnd(int controlIndex, MapEntry entry, DragEndDetails details) { setState(() { controlsAreActive[controlIndex] = false; }); onDrawableScaleEnd(entry); } - void onResizeControlPanStart(int controlIndex, - MapEntry entry, DragStartDetails details) { + void onResizeControlPanStart(int controlIndex, MapEntry entry, DragStartDetails details) { setState(() { controlsAreActive[controlIndex] = true; }); @@ -956,8 +790,8 @@ class _ObjectWidgetState extends State<_ObjectWidget> { )); } - void onResizeControlPanUpdate(MapEntry entry, - DragUpdateDetails details, BoxConstraints constraints, Axis axis, + void onResizeControlPanUpdate( + MapEntry entry, DragUpdateDetails details, BoxConstraints constraints, Axis axis, [bool isReversed = true]) { final index = entry.key; @@ -970,13 +804,10 @@ class _ObjectWidgetState extends State<_ObjectWidget> { if (initial == null) return; final vertical = axis == Axis.vertical; - final length = - ((vertical ? details.localPosition.dy : details.localPosition.dx) * - (isReversed ? -1 : 1)); + final length = ((vertical ? details.localPosition.dy : details.localPosition.dx) * (isReversed ? -1 : 1)); final initialLength = vertical ? initial.size.height : initial.size.width; - final totalLength = (length / initial.scale + initialLength) - .clamp(0, double.infinity) as double; + final totalLength = (length / initial.scale + initialLength).clamp(0, double.infinity) as double; // final double scale = initialLength == 0 ? // (length*2).clamp(0.001, double.infinity) : @@ -1012,8 +843,7 @@ class _ObjectWidgetState extends State<_ObjectWidget> { updateDrawable(drawable, newDrawable); } - void onResizeControlPanEnd(int controlIndex, - MapEntry entry, DragEndDetails details) { + void onResizeControlPanEnd(int controlIndex, MapEntry entry, DragEndDetails details) { setState(() { controlsAreActive[controlIndex] = false; }); @@ -1023,11 +853,9 @@ class _ObjectWidgetState extends State<_ObjectWidget> { /// A callback that is called when a transformation occurs in the [InteractiveViewer] in the widget tree. void onTransformUpdated() { setState(() { - final _m4storage = - PainterController.of(context).transformationController.value; - transformationScale = math.sqrt(_m4storage[8] * _m4storage[8] + - _m4storage[9] * _m4storage[9] + - _m4storage[10] * _m4storage[10]); + final _m4storage = PainterController.of(context).transformationController.value; + transformationScale = + math.sqrt(_m4storage[8] * _m4storage[8] + _m4storage[9] * _m4storage[9] + _m4storage[10] * _m4storage[10]); }); } } @@ -1068,7 +896,7 @@ class _ObjectControlBox extends StatelessWidget { Widget build(BuildContext context) { ThemeData? theme = Theme.of(context); if (theme == ThemeData.fallback()) theme = null; - final activeColor = this.activeColor ?? theme?.accentColor ?? Colors.blue; + final activeColor = this.activeColor ?? theme?.colorScheme.secondary ?? Colors.blue; return AnimatedContainer( duration: _ObjectWidgetState.controlsTransitionDuration, decoration: BoxDecoration( diff --git a/lib/src/views/widgets/shape_widget.dart b/lib/src/views/widgets/shape_widget.dart index ed28e9b6..1929523a 100644 --- a/lib/src/views/widgets/shape_widget.dart +++ b/lib/src/views/widgets/shape_widget.dart @@ -20,8 +20,7 @@ class _ShapeWidgetState extends State<_ShapeWidget> { ShapeDrawable? currentShapeDrawable; /// Getter for shape settings to simplify code. - ShapeSettings get settings => - PainterController.of(context).value.settings.shape; + ShapeSettings get settings => PainterController.of(context).value.settings.shape; @override Widget build(BuildContext context) { @@ -39,8 +38,7 @@ class _ShapeWidgetState extends State<_ShapeWidget> { final factory = settings.factory; if (factory == null || details.pointerCount > 1) return; - final shapeDrawable = - factory.create(details.localFocalPoint, settings.paint); + final shapeDrawable = factory.create(details.localFocalPoint, settings.paint); setState(() { PainterController.of(context).addDrawables([shapeDrawable]); @@ -56,11 +54,9 @@ class _ShapeWidgetState extends State<_ShapeWidget> { if (shapeDrawable is Sized1DDrawable) { final sized1DDrawable = (shapeDrawable as Sized1DDrawable); final length = sized1DDrawable.length; - final startingPosition = shapeDrawable.position - - Offset.fromDirection(sized1DDrawable.rotationAngle, length / 2); + final startingPosition = shapeDrawable.position - Offset.fromDirection(sized1DDrawable.rotationAngle, length / 2); final newLine = (details.localFocalPoint - startingPosition); - final newPosition = startingPosition + - Offset.fromDirection(newLine.direction, newLine.distance / 2); + final newPosition = startingPosition + Offset.fromDirection(newLine.direction, newLine.distance / 2); final newDrawable = sized1DDrawable.copyWith( position: newPosition, length: newLine.distance.abs(), @@ -71,13 +67,11 @@ class _ShapeWidgetState extends State<_ShapeWidget> { } else if (shapeDrawable is Sized2DDrawable) { final sized2DDrawable = (shapeDrawable as Sized2DDrawable); final size = sized2DDrawable.size; - final startingPosition = - shapeDrawable.position - Offset(size.width / 2, size.height / 2); + final startingPosition = shapeDrawable.position - Offset(size.width / 2, size.height / 2); - final newSize = Size((details.localFocalPoint.dx - startingPosition.dx), - (details.localFocalPoint.dy - startingPosition.dy)); - final newPosition = - startingPosition + Offset(newSize.width / 2, newSize.height / 2); + final newSize = + Size((details.localFocalPoint.dx - startingPosition.dx), (details.localFocalPoint.dy - startingPosition.dy)); + final newPosition = startingPosition + Offset(newSize.width / 2, newSize.height / 2); final newDrawable = sized2DDrawable.copyWith( position: newPosition, size: newSize, @@ -100,13 +94,11 @@ class _ShapeWidgetState extends State<_ShapeWidget> { updateDrawable(sized2DDrawable as ShapeDrawable, newDrawable); } if (settings.drawOnce) { - PainterController.of(context).settings = - PainterController.of(context).settings.copyWith( - shape: settings.copyWith( - factory: null, - )); - SettingsUpdatedNotification(PainterController.of(context).value.settings) - .dispatch(context); + PainterController.of(context).settings = PainterController.of(context).settings.copyWith( + shape: settings.copyWith( + factory: null, + )); + SettingsUpdatedNotification(PainterController.of(context).value.settings).dispatch(context); } DrawableCreatedNotification(currentShapeDrawable).dispatch(context); @@ -119,8 +111,7 @@ class _ShapeWidgetState extends State<_ShapeWidget> { /// Replaces a drawable with a new one. void updateDrawable(ObjectDrawable oldDrawable, ObjectDrawable newDrawable) { setState(() { - PainterController.of(context) - .replaceDrawable(oldDrawable, newDrawable, newAction: false); + PainterController.of(context).replaceDrawable(oldDrawable, newDrawable, newAction: false); }); } } diff --git a/lib/src/views/widgets/text_widget.dart b/lib/src/views/widgets/text_widget.dart index c1a379cb..621c552c 100644 --- a/lib/src/views/widgets/text_widget.dart +++ b/lib/src/views/widgets/text_widget.dart @@ -30,8 +30,7 @@ class _TextWidgetState extends State<_TextWidget> { // Listen to the stream of events from the paint controller WidgetsBinding.instance.addPostFrameCallback((timeStamp) { - controllerEventSubscription = - PainterController.of(context).events.listen((event) { + controllerEventSubscription = PainterController.of(context).events.listen((event) { // When an [AddTextPainterEvent] event is received, create a new text drawable if (event is AddTextPainterEvent) createDrawable(); }); @@ -54,15 +53,13 @@ class _TextWidgetState extends State<_TextWidget> { } /// Getter for [TextSettings] from `widget.controller.value` to make code more readable. - TextSettings get settings => - PainterController.of(context).value.settings.text; + TextSettings get settings => PainterController.of(context).value.settings.text; /// Handles any [ObjectDrawableReselectedNotification] that might be dispatched in the widget tree. /// /// This handles notifications of type [ObjectDrawableReselectedNotification] to edit /// an existing [TextDrawable]. - bool onObjectDrawableNotification( - ObjectDrawableReselectedNotification notification) { + bool onObjectDrawableNotification(ObjectDrawableReselectedNotification notification) { final drawable = notification.drawable; if (drawable is TextDrawable) { @@ -79,16 +76,8 @@ class _TextWidgetState extends State<_TextWidget> { if (selectedDrawable != null) return; // Calculate the center of the painter - final renderBox = PainterController.of(context) - .painterKey - .currentContext - ?.findRenderObject() as RenderBox?; - final center = renderBox == null - ? Offset.zero - : Offset( - renderBox.size.width / 2, - renderBox.size.height / 2, - ); + final renderBox = context.findRenderObject() as RenderBox?; + Offset center = renderBox == null ? Offset.zero : renderBox.paintBounds.center; // Create a new hidden empty entry in the center of the painter final drawable = TextDrawable( @@ -115,26 +104,22 @@ class _TextWidgetState extends State<_TextWidget> { } /// Opens an editor to edit the text of [drawable]. - Future openTextEditor(TextDrawable drawable, - [bool isNew = false]) async { + Future openTextEditor(TextDrawable drawable, [bool isNew = false]) async { await Navigator.push( context, PageRouteBuilder( transitionDuration: const Duration(milliseconds: 300), reverseTransitionDuration: const Duration(milliseconds: 300), opaque: false, - pageBuilder: (context, animation, secondaryAnimation) => - EditTextWidget( + pageBuilder: (context, animation, secondaryAnimation) => EditTextWidget( controller: PainterController.of(context), drawable: drawable, isNew: isNew, ), - transitionsBuilder: - (context, animation, secondaryAnimation, child) => - FadeTransition( - opacity: animation, - child: child, - ))); + transitionsBuilder: (context, animation, secondaryAnimation, child) => FadeTransition( + opacity: animation, + child: child, + ))); } } @@ -162,8 +147,7 @@ class EditTextWidget extends StatefulWidget { EditTextWidgetState createState() => EditTextWidgetState(); } -class EditTextWidgetState extends State - with WidgetsBindingObserver { +class EditTextWidgetState extends State with WidgetsBindingObserver { /// Text editing controller for the [TextField]. TextEditingController textEditingController = TextEditingController(); @@ -199,6 +183,10 @@ class EditTextWidgetState extends State // Initialize the text in the [TextField] to the drawable text textEditingController.text = widget.drawable.text; + widget.controller.addListener(() { + if (mounted) setState(() {}); + }); + // Add this object as an observer for widget bindings // // This is used to check the bottom view insets (the keyboard size on mobile) @@ -230,8 +218,7 @@ class EditTextWidgetState extends State final mediaQuery = MediaQuery.of(context); final screenHeight = mediaQuery.size.height; final keyboardHeight = mediaQuery.viewInsets.bottom; - final renderBox = widget.controller.painterKey.currentContext - ?.findRenderObject() as RenderBox?; + final renderBox = widget.controller.painterKey.currentContext?.findRenderObject() as RenderBox?; final y = renderBox?.localToGlobal(Offset.zero).dy ?? 0; final height = renderBox?.size.height ?? screenHeight; @@ -241,9 +228,7 @@ class EditTextWidgetState extends State child: Container( color: Colors.black38, child: Padding( - padding: EdgeInsets.only( - bottom: (keyboardHeight - (screenHeight - height - y)) - .clamp(0, screenHeight)), + padding: EdgeInsets.only(bottom: (keyboardHeight - (screenHeight - height - y)).clamp(0, screenHeight)), child: Center( child: TextField( decoration: const InputDecoration( @@ -325,8 +310,7 @@ class EditTextWidgetState extends State /// Updates the drawable in the painter controller. void updateDrawable(TextDrawable oldDrawable, TextDrawable newDrawable) { - widget.controller - .replaceDrawable(oldDrawable, newDrawable, newAction: !widget.isNew); + widget.controller.replaceDrawable(oldDrawable, newDrawable, newAction: !widget.isNew); } /// Builds a null widget for the [TextField] counter. @@ -334,8 +318,6 @@ class EditTextWidgetState extends State /// By default, [TextField] shows a character counter if the maxLength attribute /// is used. This is to override the counter and display nothing. Widget? buildEmptyCounter(BuildContext context, - {required int currentLength, - int? maxLength, - required bool isFocused}) => + {required int currentLength, int? maxLength, required bool isFocused}) => null; } diff --git a/pubspec.lock b/pubspec.lock index 3658ec1c..be92e909 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -5,98 +5,112 @@ packages: dependency: transitive description: name: _fe_analyzer_shared - url: "https://pub.dartlang.org" + sha256: "6824874a3ddeb1530a8b59c8f3cb1181f38717d0c88ff920962125ffbd65babe" + url: "https://pub.dev" source: hosted version: "41.0.0" analyzer: dependency: transitive description: name: analyzer - url: "https://pub.dartlang.org" + sha256: "33f7fdac2d5f7cd0a34adb9ec09282edd45c87135b176174dbf3c83388a9934e" + url: "https://pub.dev" source: hosted version: "4.2.0" args: dependency: transitive description: name: args - url: "https://pub.dartlang.org" + sha256: "0bd9a99b6eb96f07af141f0eb53eace8983e8e5aa5de59777aca31684680ef22" + url: "https://pub.dev" source: hosted version: "2.3.0" async: dependency: transitive description: name: async - url: "https://pub.dartlang.org" + sha256: "947bfcf187f74dbc5e146c9eb9c0f10c9f8b30743e341481c1e2ed3ecc18c20c" + url: "https://pub.dev" source: hosted - version: "2.8.2" + version: "2.11.0" boolean_selector: dependency: transitive description: name: boolean_selector - url: "https://pub.dartlang.org" + sha256: "6cfb5af12253eaf2b368f07bacc5a80d1301a071c73360d746b7f2e32d762c66" + url: "https://pub.dev" source: hosted - version: "2.1.0" + version: "2.1.1" characters: dependency: transitive description: name: characters - url: "https://pub.dartlang.org" + sha256: "04a925763edad70e8443c99234dc3328f442e811f1d8fd1a72f1c8ad0f69a605" + url: "https://pub.dev" source: hosted - version: "1.2.0" + version: "1.3.0" charcode: dependency: transitive description: name: charcode - url: "https://pub.dartlang.org" + sha256: fb98c0f6d12c920a02ee2d998da788bca066ca5f148492b7085ee23372b12306 + url: "https://pub.dev" source: hosted version: "1.3.1" clock: dependency: transitive description: name: clock - url: "https://pub.dartlang.org" + sha256: cb6d7f03e1de671e34607e909a7213e31d7752be4fb66a86d29fe1eb14bfb5cf + url: "https://pub.dev" source: hosted - version: "1.1.0" + version: "1.1.1" collection: dependency: "direct main" description: name: collection - url: "https://pub.dartlang.org" + sha256: "4a07be6cb69c84d677a6c3096fcf960cc3285a8330b4603e0d463d15d9bd934c" + url: "https://pub.dev" source: hosted - version: "1.16.0" + version: "1.17.1" convert: dependency: transitive description: name: convert - url: "https://pub.dartlang.org" + sha256: f08428ad63615f96a27e34221c65e1a451439b5f26030f78d790f461c686d65d + url: "https://pub.dev" source: hosted version: "3.0.1" coverage: dependency: transitive description: name: coverage - url: "https://pub.dartlang.org" + sha256: ad538fa2e8f6b828d54c04a438af816ce814de404690136d3b9dfb3a436cd01c + url: "https://pub.dev" source: hosted version: "1.0.3" crypto: dependency: transitive description: name: crypto - url: "https://pub.dartlang.org" + sha256: cf75650c66c0316274e21d7c43d3dea246273af5955bd94e8184837cd577575c + url: "https://pub.dev" source: hosted version: "3.0.1" fake_async: dependency: transitive description: name: fake_async - url: "https://pub.dartlang.org" + sha256: "511392330127add0b769b75a987850d136345d9227c6b94c96a04cf4a391bf78" + url: "https://pub.dev" source: hosted - version: "1.3.0" + version: "1.3.1" file: dependency: transitive description: name: file - url: "https://pub.dartlang.org" + sha256: b69516f2c26a5bcac4eee2e32512e1a5205ab312b3536c1c1227b2b942b5f9ad + url: "https://pub.dev" source: hosted version: "6.1.2" flutter: @@ -108,9 +122,10 @@ packages: dependency: "direct dev" description: name: flutter_lints - url: "https://pub.dartlang.org" + sha256: aeb0b80a8b3709709c9cc496cdc027c5b3216796bc0af0ce1007eaf24464fd4c + url: "https://pub.dev" source: hosted - version: "1.0.4" + version: "2.0.1" flutter_test: dependency: "direct dev" description: flutter @@ -120,161 +135,184 @@ packages: dependency: transitive description: name: frontend_server_client - url: "https://pub.dartlang.org" + sha256: "408e3ca148b31c20282ad6f37ebfa6f4bdc8fede5b74bc2f08d9d92b55db3612" + url: "https://pub.dev" source: hosted - version: "2.1.3" + version: "3.2.0" glob: dependency: transitive description: name: glob - url: "https://pub.dartlang.org" + sha256: dda85ce2aefce16f7e75586acbcb1e8320bf176f69fd94082e31945d6de67f3e + url: "https://pub.dev" source: hosted version: "2.0.1" http_multi_server: dependency: transitive description: name: http_multi_server - url: "https://pub.dartlang.org" + sha256: ab298ef2b2acd283bd36837df7801dcf6e6b925f8da6e09efb81111230aa9037 + url: "https://pub.dev" source: hosted version: "3.2.0" http_parser: dependency: transitive description: name: http_parser - url: "https://pub.dartlang.org" + sha256: e362d639ba3bc07d5a71faebb98cde68c05bfbcfbbb444b60b6f60bb67719185 + url: "https://pub.dev" source: hosted version: "4.0.0" io: dependency: transitive description: name: io - url: "https://pub.dartlang.org" + sha256: "0d4c73c3653ab85bf696d51a9657604c900a370549196a91f33e4c39af760852" + url: "https://pub.dev" source: hosted version: "1.0.3" js: dependency: transitive description: name: js - url: "https://pub.dartlang.org" + sha256: f2c445dce49627136094980615a031419f7f3eb393237e4ecd97ac15dea343f3 + url: "https://pub.dev" source: hosted - version: "0.6.3" + version: "0.6.7" lints: dependency: transitive description: name: lints - url: "https://pub.dartlang.org" + sha256: "0a217c6c989d21039f1498c3ed9f3ed71b354e69873f13a8dfc3c9fe76f1b452" + url: "https://pub.dev" source: hosted - version: "1.0.1" + version: "2.1.1" logging: dependency: transitive description: name: logging - url: "https://pub.dartlang.org" + sha256: "293ae2d49fd79d4c04944c3a26dfd313382d5f52e821ec57119230ae16031ad4" + url: "https://pub.dev" source: hosted version: "1.0.2" matcher: dependency: transitive description: name: matcher - url: "https://pub.dartlang.org" + sha256: "6501fbd55da300384b768785b83e5ce66991266cec21af89ab9ae7f5ce1c4cbb" + url: "https://pub.dev" source: hosted - version: "0.12.11" + version: "0.12.15" material_color_utilities: dependency: transitive description: name: material_color_utilities - url: "https://pub.dartlang.org" + sha256: d92141dc6fe1dad30722f9aa826c7fbc896d021d792f80678280601aff8cf724 + url: "https://pub.dev" source: hosted - version: "0.1.4" + version: "0.2.0" meta: dependency: transitive description: name: meta - url: "https://pub.dartlang.org" + sha256: "3c74dbf8763d36539f114c799d8a2d87343b5067e9d796ca22b5eb8437090ee3" + url: "https://pub.dev" source: hosted - version: "1.7.0" + version: "1.9.1" mime: dependency: transitive description: name: mime - url: "https://pub.dartlang.org" + sha256: fd5f81041e6a9fc9b9d7fa2cb8a01123f9f5d5d49136e06cb9dc7d33689529f4 + url: "https://pub.dev" source: hosted version: "1.0.1" mocktail: dependency: "direct dev" description: name: mocktail - url: "https://pub.dartlang.org" + sha256: "80a996cd9a69284b3dc521ce185ffe9150cde69767c2d3a0720147d93c0cef53" + url: "https://pub.dev" source: hosted - version: "0.3.0-dev.1" + version: "0.3.0" node_preamble: dependency: transitive description: name: node_preamble - url: "https://pub.dartlang.org" + sha256: "8ebdbaa3b96d5285d068f80772390d27c21e1fa10fb2df6627b1b9415043608d" + url: "https://pub.dev" source: hosted version: "2.0.1" package_config: dependency: transitive description: name: package_config - url: "https://pub.dartlang.org" + sha256: a4d5ede5ca9c3d88a2fef1147a078570c861714c806485c596b109819135bc12 + url: "https://pub.dev" source: hosted version: "2.0.2" path: dependency: transitive description: name: path - url: "https://pub.dartlang.org" + sha256: "8829d8a55c13fc0e37127c29fedf290c102f4e40ae94ada574091fe0ff96c917" + url: "https://pub.dev" source: hosted - version: "1.8.1" + version: "1.8.3" pedantic: dependency: transitive description: name: pedantic - url: "https://pub.dartlang.org" + sha256: "67fc27ed9639506c856c840ccce7594d0bdcd91bc8d53d6e52359449a1d50602" + url: "https://pub.dev" source: hosted version: "1.11.1" pool: dependency: transitive description: name: pool - url: "https://pub.dartlang.org" + sha256: "05955e3de2683e1746222efd14b775df7131139e07695dc8e24650f6b4204504" + url: "https://pub.dev" source: hosted version: "1.5.0" pub_semver: dependency: transitive description: name: pub_semver - url: "https://pub.dartlang.org" + sha256: b5a5fcc6425ea43704852ba4453ba94b08c2226c63418a260240c3a054579014 + url: "https://pub.dev" source: hosted version: "2.1.0" shelf: dependency: transitive description: name: shelf - url: "https://pub.dartlang.org" + sha256: c240984c924796e055e831a0a36db23be8cb04f170b26df572931ab36418421d + url: "https://pub.dev" source: hosted version: "1.2.0" shelf_packages_handler: dependency: transitive description: name: shelf_packages_handler - url: "https://pub.dartlang.org" + sha256: e0b44ebddec91e70a713e13adf93c1b2100821303b86a18e1ef1d082bd8bd9b8 + url: "https://pub.dev" source: hosted version: "3.0.0" shelf_static: dependency: transitive description: name: shelf_static - url: "https://pub.dartlang.org" + sha256: "4a0d12cd512aa4fc55fed5f6280f02ef183f47ba29b4b0dfd621b1c99b7e6361" + url: "https://pub.dev" source: hosted version: "1.1.0" shelf_web_socket: dependency: transitive description: name: shelf_web_socket - url: "https://pub.dartlang.org" + sha256: fd84910bf7d58db109082edf7326b75322b8f186162028482f53dc892f00332d + url: "https://pub.dev" source: hosted version: "1.0.1" sky_engine: @@ -286,121 +324,138 @@ packages: dependency: transitive description: name: source_map_stack_trace - url: "https://pub.dartlang.org" + sha256: "8c463326277f68a628abab20580047b419c2ff66756fd0affd451f73f9508c11" + url: "https://pub.dev" source: hosted version: "2.1.0" source_maps: dependency: transitive description: name: source_maps - url: "https://pub.dartlang.org" + sha256: "52de2200bb098de739794c82d09c41ac27b2e42fd7e23cce7b9c74bf653c7296" + url: "https://pub.dev" source: hosted version: "0.10.10" source_span: dependency: transitive description: name: source_span - url: "https://pub.dartlang.org" + sha256: dd904f795d4b4f3b870833847c461801f6750a9fa8e61ea5ac53f9422b31f250 + url: "https://pub.dev" source: hosted - version: "1.8.2" + version: "1.9.1" stack_trace: dependency: transitive description: name: stack_trace - url: "https://pub.dartlang.org" + sha256: c3c7d8edb15bee7f0f74debd4b9c5f3c2ea86766fe4178eb2a18eb30a0bdaed5 + url: "https://pub.dev" source: hosted - version: "1.10.0" + version: "1.11.0" stream_channel: dependency: transitive description: name: stream_channel - url: "https://pub.dartlang.org" + sha256: "83615bee9045c1d322bbbd1ba209b7a749c2cbcdcb3fdd1df8eb488b3279c1c8" + url: "https://pub.dev" source: hosted - version: "2.1.0" + version: "2.1.1" string_scanner: dependency: transitive description: name: string_scanner - url: "https://pub.dartlang.org" + sha256: "556692adab6cfa87322a115640c11f13cb77b3f076ddcc5d6ae3c20242bedcde" + url: "https://pub.dev" source: hosted - version: "1.1.0" + version: "1.2.0" term_glyph: dependency: transitive description: name: term_glyph - url: "https://pub.dartlang.org" + sha256: a29248a84fbb7c79282b40b8c72a1209db169a2e0542bce341da992fe1bc7e84 + url: "https://pub.dev" source: hosted - version: "1.2.0" + version: "1.2.1" test: dependency: transitive description: name: test - url: "https://pub.dartlang.org" + sha256: "3dac9aecf2c3991d09b9cdde4f98ded7b30804a88a0d7e4e7e1678e78d6b97f4" + url: "https://pub.dev" source: hosted - version: "1.21.1" + version: "1.24.1" test_api: dependency: transitive description: name: test_api - url: "https://pub.dartlang.org" + sha256: eb6ac1540b26de412b3403a163d919ba86f6a973fe6cc50ae3541b80092fdcfb + url: "https://pub.dev" source: hosted - version: "0.4.9" + version: "0.5.1" test_core: dependency: transitive description: name: test_core - url: "https://pub.dartlang.org" + sha256: "5138dbffb77b2289ecb12b81c11ba46036590b72a64a7a90d6ffb880f1a29e93" + url: "https://pub.dev" source: hosted - version: "0.4.13" + version: "0.5.1" typed_data: dependency: transitive description: name: typed_data - url: "https://pub.dartlang.org" + sha256: "53bdf7e979cfbf3e28987552fd72f637e63f3c8724c9e56d9246942dc2fa36ee" + url: "https://pub.dev" source: hosted version: "1.3.0" vector_math: dependency: transitive description: name: vector_math - url: "https://pub.dartlang.org" + sha256: "80b3257d1492ce4d091729e3a67a60407d227c27241d6927be0130c98e741803" + url: "https://pub.dev" source: hosted - version: "2.1.2" + version: "2.1.4" vm_service: dependency: transitive description: name: vm_service - url: "https://pub.dartlang.org" + sha256: "422eda09e2a50eb27fe9eca2c897d624cea7fa432a8442e1ea1a10d50a4321ab" + url: "https://pub.dev" source: hosted version: "6.2.0" watcher: dependency: transitive description: name: watcher - url: "https://pub.dartlang.org" + sha256: "68173f2fa67d241323a4123be7ed4e43424c54befa5505d71c8ad4b7baf8f71d" + url: "https://pub.dev" source: hosted version: "1.0.0" web_socket_channel: dependency: transitive description: name: web_socket_channel - url: "https://pub.dartlang.org" + sha256: "0c2ada1b1aeb2ad031ca81872add6be049b8cb479262c6ad3c4b0f9c24eaab2f" + url: "https://pub.dev" source: hosted version: "2.1.0" webkit_inspection_protocol: dependency: transitive description: name: webkit_inspection_protocol - url: "https://pub.dartlang.org" + sha256: "5adb6ab8ed14e22bb907aae7338f0c206ea21e7a27004e97664b16c120306f00" + url: "https://pub.dev" source: hosted version: "1.0.0" yaml: dependency: transitive description: name: yaml - url: "https://pub.dartlang.org" + sha256: "3cee79b1715110341012d27756d9bae38e650588acd38d3f3c610822e1337ace" + url: "https://pub.dev" source: hosted version: "3.1.0" sdks: - dart: ">=2.17.0 <3.0.0" - flutter: ">=1.17.0" + dart: ">=3.0.0 <4.0.0" + flutter: ">=3.0.0" diff --git a/pubspec.yaml b/pubspec.yaml index e116ab25..bc27fb3f 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -6,19 +6,19 @@ repository: https://github.com/omarhurani/flutter_painter issue_tracker: https://github.com/omarhurani/flutter_painter/issues environment: - sdk: ">=2.12.0 <3.0.0" - flutter: ">=1.17.0" + sdk: ">=3.0.0 <4.0.0" + flutter: ">=3.0.0" dependencies: flutter: sdk: flutter - collection: ^1.15.0 + collection: ^1.17.1 dev_dependencies: - flutter_lints: ^1.0.4 + flutter_lints: ^2.0.1 flutter_test: sdk: flutter - mocktail: ^0.3.0-dev.1 + mocktail: ^0.3.0 flutter: