From dcc22d0f2bfd31a79e87ab30076483f04d35f5ae Mon Sep 17 00:00:00 2001 From: ilopX Date: Mon, 23 May 2022 01:55:21 +0300 Subject: [PATCH 01/91] Add "ManipulatorStateApp" empty project. --- patterns/state/manipulator_state/app/app.dart | 15 +++++ .../state/manipulator_state/app/shapes.dart | 14 +++++ .../state/manipulator_state/app/tool.dart | 13 +++++ patterns/state/manipulator_state/main.dart | 56 +++++++++++++++++++ .../pattern/manipulation_state.dart | 9 +++ .../pattern/manipulator_context.dart | 19 +++++++ .../state/manipulator_state/shapes/shape.dart | 5 ++ .../states/create_circle_state.dart | 5 ++ .../states/create_rectangle_state.dart | 5 ++ .../states/create_text_state.dart | 5 ++ .../manipulator_state/states/free_sate.dart | 5 ++ .../widgets/drawing_board.dart | 42 ++++++++++++++ .../manipulator_state/widgets/tool_bar.dart | 10 ++++ 13 files changed, 203 insertions(+) create mode 100644 patterns/state/manipulator_state/app/app.dart create mode 100644 patterns/state/manipulator_state/app/shapes.dart create mode 100644 patterns/state/manipulator_state/app/tool.dart create mode 100644 patterns/state/manipulator_state/main.dart create mode 100644 patterns/state/manipulator_state/pattern/manipulation_state.dart create mode 100644 patterns/state/manipulator_state/pattern/manipulator_context.dart create mode 100644 patterns/state/manipulator_state/shapes/shape.dart create mode 100644 patterns/state/manipulator_state/states/create_circle_state.dart create mode 100644 patterns/state/manipulator_state/states/create_rectangle_state.dart create mode 100644 patterns/state/manipulator_state/states/create_text_state.dart create mode 100644 patterns/state/manipulator_state/states/free_sate.dart create mode 100644 patterns/state/manipulator_state/widgets/drawing_board.dart create mode 100644 patterns/state/manipulator_state/widgets/tool_bar.dart diff --git a/patterns/state/manipulator_state/app/app.dart b/patterns/state/manipulator_state/app/app.dart new file mode 100644 index 0000000..e1ef653 --- /dev/null +++ b/patterns/state/manipulator_state/app/app.dart @@ -0,0 +1,15 @@ +import '../pattern/manipulator_context.dart'; +import 'shapes.dart'; +import 'tool.dart'; + +class App { + final Shapes shapes; + final ManipulatorContext manipulator; + final List tools; + + App({ + required this.shapes, + required this.manipulator, + required this.tools, + }); +} diff --git a/patterns/state/manipulator_state/app/shapes.dart b/patterns/state/manipulator_state/app/shapes.dart new file mode 100644 index 0000000..ecb158c --- /dev/null +++ b/patterns/state/manipulator_state/app/shapes.dart @@ -0,0 +1,14 @@ +import 'dart:collection'; + +import '../shapes/shape.dart'; + +class Shapes with IterableMixin { + final _shapes = []; + + void add(Shape shape) { + _shapes.add(shape); + } + + @override + Iterator get iterator => _shapes.iterator; +} diff --git a/patterns/state/manipulator_state/app/tool.dart b/patterns/state/manipulator_state/app/tool.dart new file mode 100644 index 0000000..e846e72 --- /dev/null +++ b/patterns/state/manipulator_state/app/tool.dart @@ -0,0 +1,13 @@ +import 'package:flutter/widgets.dart'; + +import '../pattern/manipulation_state.dart'; + +class Tool { + final Icon icon; + final ManipulationState state; + + Tool({ + required this.icon, + required this.state, + }); +} diff --git a/patterns/state/manipulator_state/main.dart b/patterns/state/manipulator_state/main.dart new file mode 100644 index 0000000..c326621 --- /dev/null +++ b/patterns/state/manipulator_state/main.dart @@ -0,0 +1,56 @@ +import 'package:flutter/material.dart'; + +import 'app/app.dart'; +import 'app/shapes.dart'; +import 'app/tool.dart'; +import 'pattern/manipulator_context.dart'; +import 'states/create_circle_state.dart'; +import 'states/create_rectangle_state.dart'; +import 'states/create_text_state.dart'; +import 'states/free_sate.dart'; +import 'widgets/drawing_board.dart'; +import 'widgets/tool_bar.dart'; + +class ManipulatorStateApp extends StatefulWidget { + const ManipulatorStateApp({Key? key}) : super(key: key); + + @override + _ManipulatorStateAppState createState() => _ManipulatorStateAppState(); +} + +class _ManipulatorStateAppState extends State { + final app = App( + shapes: Shapes(), + manipulator: ManipulatorContext( + initState: FreeState(), + ), + tools: [ + Tool( + icon: Icon(Icons.agriculture_sharp), + state: FreeState(), + ), + Tool( + icon: Icon(Icons.loupe), + state: CreateRectangleState(), + ), + Tool( + icon: Icon(Icons.checklist_outlined), + state: CreateCircleState(), + ), + Tool( + icon: Icon(Icons.fiber_dvr), + state: CreateTextState(), + ), + ], + ); + + @override + Widget build(BuildContext context) { + return Stack( + children: [ + DrawingBoard(app: app), + ToolBar(), + ], + ); + } +} diff --git a/patterns/state/manipulator_state/pattern/manipulation_state.dart b/patterns/state/manipulator_state/pattern/manipulation_state.dart new file mode 100644 index 0000000..1457102 --- /dev/null +++ b/patterns/state/manipulator_state/pattern/manipulation_state.dart @@ -0,0 +1,9 @@ +class ManipulationState { + void mouseMove(double x, double y) {} + + void mouseDown(double x, y) {} + + void mouseUp() {} + + void keyDown(String key) {} +} diff --git a/patterns/state/manipulator_state/pattern/manipulator_context.dart b/patterns/state/manipulator_state/pattern/manipulator_context.dart new file mode 100644 index 0000000..28e6609 --- /dev/null +++ b/patterns/state/manipulator_state/pattern/manipulator_context.dart @@ -0,0 +1,19 @@ +import 'dart:ui'; + +import 'manipulation_state.dart'; + +class ManipulatorContext { + final ManipulationState initState; + + ManipulatorContext({required this.initState}); + + void mouseMove(double x, double y) {} + + void mouseDown(double x, y) {} + + void mouseUp() {} + + void keyDown(String key) {} + + void paint(Canvas canvas) {} +} diff --git a/patterns/state/manipulator_state/shapes/shape.dart b/patterns/state/manipulator_state/shapes/shape.dart new file mode 100644 index 0000000..77db6e0 --- /dev/null +++ b/patterns/state/manipulator_state/shapes/shape.dart @@ -0,0 +1,5 @@ +import 'dart:ui'; + +abstract class Shape { + void paint(Canvas canvas); +} diff --git a/patterns/state/manipulator_state/states/create_circle_state.dart b/patterns/state/manipulator_state/states/create_circle_state.dart new file mode 100644 index 0000000..755b348 --- /dev/null +++ b/patterns/state/manipulator_state/states/create_circle_state.dart @@ -0,0 +1,5 @@ +import '../pattern/manipulation_state.dart'; + +class CreateCircleState extends ManipulationState { + +} diff --git a/patterns/state/manipulator_state/states/create_rectangle_state.dart b/patterns/state/manipulator_state/states/create_rectangle_state.dart new file mode 100644 index 0000000..8e6dfa4 --- /dev/null +++ b/patterns/state/manipulator_state/states/create_rectangle_state.dart @@ -0,0 +1,5 @@ +import '../pattern/manipulation_state.dart'; + +class CreateRectangleState extends ManipulationState{ + +} diff --git a/patterns/state/manipulator_state/states/create_text_state.dart b/patterns/state/manipulator_state/states/create_text_state.dart new file mode 100644 index 0000000..228edda --- /dev/null +++ b/patterns/state/manipulator_state/states/create_text_state.dart @@ -0,0 +1,5 @@ +import '../pattern/manipulation_state.dart'; + +class CreateTextState extends ManipulationState { + +} diff --git a/patterns/state/manipulator_state/states/free_sate.dart b/patterns/state/manipulator_state/states/free_sate.dart new file mode 100644 index 0000000..e39bae8 --- /dev/null +++ b/patterns/state/manipulator_state/states/free_sate.dart @@ -0,0 +1,5 @@ +import '../pattern/manipulation_state.dart'; + +class FreeState extends ManipulationState { + +} diff --git a/patterns/state/manipulator_state/widgets/drawing_board.dart b/patterns/state/manipulator_state/widgets/drawing_board.dart new file mode 100644 index 0000000..0fac333 --- /dev/null +++ b/patterns/state/manipulator_state/widgets/drawing_board.dart @@ -0,0 +1,42 @@ +import 'package:flutter/material.dart'; + +import '../app/app.dart'; + +class DrawingBoard extends StatelessWidget { + final App app; + + const DrawingBoard({Key? key, required this.app}) : super(key: key); + + @override + Widget build(BuildContext context) { + return Container( + color: Colors.black12, + child: CustomPaint( + painter: _Painter(app), + ), + ); + } +} + +class _Painter extends CustomPainter { + final App app; + + _Painter(this.app); + + @override + void paint(Canvas canvas, Size size) { + for(final shape in app.shapes) { + shape.paint(canvas); + } + + app.manipulator.paint(canvas); + } + + @override + bool shouldRepaint(covariant CustomPainter oldDelegate) { + return true; + } + +} + + diff --git a/patterns/state/manipulator_state/widgets/tool_bar.dart b/patterns/state/manipulator_state/widgets/tool_bar.dart new file mode 100644 index 0000000..5bdeda9 --- /dev/null +++ b/patterns/state/manipulator_state/widgets/tool_bar.dart @@ -0,0 +1,10 @@ +import 'package:flutter/widgets.dart'; + +class ToolBar extends StatelessWidget { + const ToolBar({Key? key}) : super(key: key); + + @override + Widget build(BuildContext context) { + return Container(); + } +} From 2777d62ba31d149f78ee22b09de2135f04320d3c Mon Sep 17 00:00:00 2001 From: ilopX Date: Mon, 23 May 2022 18:28:20 +0300 Subject: [PATCH 02/91] Add toolbar. --- bin/main.dart | 12 +++++- .../widgets/independent/panel.dart | 13 ++++--- .../widgets/independent/tool_button.dart | 2 +- patterns/state/manipulator_state/main.dart | 37 ++++++++++-------- .../manipulator_state/widgets/tool_bar.dart | 38 +++++++++++++++++-- 5 files changed, 74 insertions(+), 28 deletions(-) diff --git a/bin/main.dart b/bin/main.dart index 1180c2d..5200232 100644 --- a/bin/main.dart +++ b/bin/main.dart @@ -3,6 +3,7 @@ import '../patterns/abstract_factory/tool_panel_factory/main.dart'; import '../patterns/observer/subscriber_flutter_widget/main.dart'; import '../patterns/adapter/flutter_adapter/main.dart'; import '../patterns/memento/memento_editor/main.dart'; +import '../patterns/state/manipulator_state/main.dart'; void main() { runApp(MyApp()); @@ -13,13 +14,20 @@ class MyApp extends StatelessWidget { Widget build(BuildContext context) { return MaterialApp( title: 'Refactoring Guru: Flutter launcher', - theme: ThemeData(primarySwatch: Colors.pink), - initialRoute: '/abstract_factory/tool_panel_factory', + theme: ThemeData( + primarySwatch: Colors.pink, + iconTheme: IconThemeData( + size: 32, + color: Colors.white, + ), + ), + initialRoute: '/state/manipulator_state', routes: { '/observer/subscriber_flutter_widget': (_) => SubscriberFlutterApp(), '/adapter/flutter_adapter': (_) => FlutterAdapterApp(), '/memento/flutter_memento_editor': (_) => FlutterMementoEditorApp(), '/abstract_factory/tool_panel_factory': (_) => ToolPanelFactoryApp(), + '/state/manipulator_state': (_) => ManipulatorStateApp(), }, ); } diff --git a/patterns/abstract_factory/tool_panel_factory/widgets/independent/panel.dart b/patterns/abstract_factory/tool_panel_factory/widgets/independent/panel.dart index 06343f5..6dd4670 100644 --- a/patterns/abstract_factory/tool_panel_factory/widgets/independent/panel.dart +++ b/patterns/abstract_factory/tool_panel_factory/widgets/independent/panel.dart @@ -2,16 +2,17 @@ import 'package:flutter/material.dart'; class Panel extends StatelessWidget { static const thicknessWidth = 64.0; - static const thicknessHeight = 48.0; + final double thicknessHeight; final Axis direction; final Widget child; - const Panel({ - Key? key, - required this.direction, - required this.child, - }) : super(key: key); + const Panel( + {Key? key, + required this.direction, + required this.child, + this.thicknessHeight = 48.0}) + : super(key: key); @override Widget build(BuildContext context) { diff --git a/patterns/abstract_factory/tool_panel_factory/widgets/independent/tool_button.dart b/patterns/abstract_factory/tool_panel_factory/widgets/independent/tool_button.dart index c0a633b..441154a 100644 --- a/patterns/abstract_factory/tool_panel_factory/widgets/independent/tool_button.dart +++ b/patterns/abstract_factory/tool_panel_factory/widgets/independent/tool_button.dart @@ -10,7 +10,7 @@ class ToolButton extends StatelessWidget { const ToolButton({ Key? key, required this.onTap, - required this.active, + this.active = false, required this.icon, }) : super(key: key); diff --git a/patterns/state/manipulator_state/main.dart b/patterns/state/manipulator_state/main.dart index c326621..4912ab4 100644 --- a/patterns/state/manipulator_state/main.dart +++ b/patterns/state/manipulator_state/main.dart @@ -1,12 +1,13 @@ import 'package:flutter/material.dart'; +import 'package:material_design_icons_flutter/material_design_icons_flutter.dart'; import 'app/app.dart'; import 'app/shapes.dart'; import 'app/tool.dart'; import 'pattern/manipulator_context.dart'; -import 'states/create_circle_state.dart'; -import 'states/create_rectangle_state.dart'; -import 'states/create_text_state.dart'; +import 'states/creations/circle_creation_state.dart'; +import 'states/creations/rectangle_creation_state.dart'; +import 'states/creations/text_creation_state.dart'; import 'states/free_sate.dart'; import 'widgets/drawing_board.dart'; import 'widgets/tool_bar.dart'; @@ -15,7 +16,7 @@ class ManipulatorStateApp extends StatefulWidget { const ManipulatorStateApp({Key? key}) : super(key: key); @override - _ManipulatorStateAppState createState() => _ManipulatorStateAppState(); + State createState() => _ManipulatorStateAppState(); } class _ManipulatorStateAppState extends State { @@ -26,31 +27,35 @@ class _ManipulatorStateAppState extends State { ), tools: [ Tool( - icon: Icon(Icons.agriculture_sharp), + icon: Icon(MdiIcons.cursorDefaultOutline), state: FreeState(), ), Tool( - icon: Icon(Icons.loupe), - state: CreateRectangleState(), + icon: Icon(MdiIcons.rectangleOutline), + state: RectangleCreationState(), ), Tool( - icon: Icon(Icons.checklist_outlined), - state: CreateCircleState(), + icon: Icon(MdiIcons.circleOutline), + state: CircleCreationState(), ), Tool( - icon: Icon(Icons.fiber_dvr), - state: CreateTextState(), + icon: Icon(MdiIcons.formatTextVariant), + state: TextCreationState(), ), ], ); @override Widget build(BuildContext context) { - return Stack( - children: [ - DrawingBoard(app: app), - ToolBar(), - ], + return Scaffold( + body: SizedBox.expand( + child: Stack( + children: [ + DrawingBoard(app: app), + ToolBar(app: app), + ], + ), + ), ); } } diff --git a/patterns/state/manipulator_state/widgets/tool_bar.dart b/patterns/state/manipulator_state/widgets/tool_bar.dart index 5bdeda9..1779959 100644 --- a/patterns/state/manipulator_state/widgets/tool_bar.dart +++ b/patterns/state/manipulator_state/widgets/tool_bar.dart @@ -1,10 +1,42 @@ -import 'package:flutter/widgets.dart'; +import 'package:flutter/cupertino.dart'; +import 'package:flutter/material.dart'; + +import '../../../abstract_factory/tool_panel_factory/widgets/independent/event_listenable_builder.dart'; +import '../../../abstract_factory/tool_panel_factory/widgets/independent/panel.dart'; +import '../../../abstract_factory/tool_panel_factory/widgets/independent/tool_button.dart'; +import '../app/app.dart'; class ToolBar extends StatelessWidget { - const ToolBar({Key? key}) : super(key: key); + final App app; + + const ToolBar({Key? key, required this.app}) : super(key: key); @override Widget build(BuildContext context) { - return Container(); + return Positioned( + top: 12, + left: 12, + child: Panel( + thicknessHeight: 64, + direction: Axis.horizontal, + child: EventListenableBuilder( + event: app.manipulator.onStateChange, + builder: (_) { + return Row( + children: [ + for (final tool in app.tools) + ToolButton( + active: tool.state == app.manipulator.state, + icon: Center(child: tool.icon), + onTap: () { + app.manipulator.changeState(tool.state); + }, + ) + ], + ); + } + ), + ), + ); } } From e99cc4dc5ef853fbca8fe989d4e3be04f3bb7135 Mon Sep 17 00:00:00 2001 From: ilopX Date: Mon, 23 May 2022 18:30:01 +0300 Subject: [PATCH 03/91] Migrate to flutter 3. --- analysis_options.yaml | 7 +++---- bin/deploy_flutter_demos.dart | 6 +++--- .../widgets/property_widgets/primitive/filed_label.dart | 2 +- patterns/builder/cars/main.dart | 2 +- patterns/command/text_editor/main.dart | 2 +- patterns/composite/products_and_boxes/products/box.dart | 4 ++-- pubspec.yaml | 4 ++-- 7 files changed, 13 insertions(+), 14 deletions(-) diff --git a/analysis_options.yaml b/analysis_options.yaml index dee8927..39e5146 100644 --- a/analysis_options.yaml +++ b/analysis_options.yaml @@ -15,10 +15,9 @@ include: package:lints/recommended.yaml # Uncomment the following section to specify additional rules. -# linter: -# rules: -# - camel_case_types - +linter: + rules: + library_private_types_in_public_api: false # analyzer: # exclude: # - path/to/excluded/files/** diff --git a/bin/deploy_flutter_demos.dart b/bin/deploy_flutter_demos.dart index 8721544..18b34db 100644 --- a/bin/deploy_flutter_demos.dart +++ b/bin/deploy_flutter_demos.dart @@ -20,9 +20,9 @@ void main() async { clear(); } -late final tmpDir = Directory.systemTemp.createTempSync(); -late final projectDir = thisPath(r'..\'); -late final webBuildDir = Directory(projectDir.uri.toFilePath() + r'build\web'); + final tmpDir = Directory.systemTemp.createTempSync(); + final projectDir = thisPath(r'..\'); + final webBuildDir = Directory(projectDir.uri.toFilePath() + r'build\web'); late final String originUrl; Future init() async { diff --git a/patterns/abstract_factory/tool_panel_factory/widgets/property_widgets/primitive/filed_label.dart b/patterns/abstract_factory/tool_panel_factory/widgets/property_widgets/primitive/filed_label.dart index 3371e09..7bc950d 100644 --- a/patterns/abstract_factory/tool_panel_factory/widgets/property_widgets/primitive/filed_label.dart +++ b/patterns/abstract_factory/tool_panel_factory/widgets/property_widgets/primitive/filed_label.dart @@ -15,7 +15,7 @@ class FieldLabel extends StatelessWidget { return Row( children: [ SizedBox(width: 10), - Text(text + ':'), + Text('$text:'), SizedBox(width: 10), child, SizedBox(width: 20), diff --git a/patterns/builder/cars/main.dart b/patterns/builder/cars/main.dart index a7a3bc3..e1c55c5 100644 --- a/patterns/builder/cars/main.dart +++ b/patterns/builder/cars/main.dart @@ -34,5 +34,5 @@ void main() { // RU: Директор может знать больше одного рецепта строительства director.constructSportsCar(manualBuilder); final carManual = manualBuilder.getResult(); - print("Car manual built:\n" + carManual.print()); + print("Car manual built:\n${carManual.print()}"); } diff --git a/patterns/command/text_editor/main.dart b/patterns/command/text_editor/main.dart index 5862594..2d1b217 100644 --- a/patterns/command/text_editor/main.dart +++ b/patterns/command/text_editor/main.dart @@ -32,5 +32,5 @@ void log({ }) { final addOrUndo = isUndo ? 'Undo_' : '[➕] '; final description = '$addOrUndo$command'; - print(description.padRight(72, '_') + '"$editorText"'); + print('${description.padRight(72, '_')}"$editorText"'); } diff --git a/patterns/composite/products_and_boxes/products/box.dart b/patterns/composite/products_and_boxes/products/box.dart index db2c88a..35e091b 100644 --- a/patterns/composite/products_and_boxes/products/box.dart +++ b/patterns/composite/products_and_boxes/products/box.dart @@ -9,8 +9,8 @@ class Box implements Product { @override String get content { final places = size > 1 ? "places: $size, " : ""; - final _price = size > 1 ? "price: $price\$" : "$price\$"; - return 'Box($places$_price)'; + final localPrice = size > 1 ? "price: $price\$" : "$price\$"; + return 'Box($places$localPrice)'; } @override diff --git a/pubspec.yaml b/pubspec.yaml index 1e9ed57..64bff52 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -6,7 +6,7 @@ repository: https://github.com/RefactoringGuru/design-patterns-dart issue_tracker: https://github.com/RefactoringGuru/design-patterns-dart/issue environment: - sdk: '>=2.15.0-68.0.dev <3.0.0' + sdk: ">=2.17.1 <3.0.0" dependencies: collection: ^1.15.0 @@ -15,7 +15,7 @@ dependencies: cupertino_icons: ^1.0.2 dev_dependencies: - lints: ^1.0.0 + flutter_lints: ^2.0.0 flutter: uses-material-design: true From 3e115843a3c177598324bc8aba3c61e3c80823f1 Mon Sep 17 00:00:00 2001 From: ilopX Date: Mon, 23 May 2022 18:32:28 +0300 Subject: [PATCH 04/91] Add material icons. --- pubspec.yaml | 1 + 1 file changed, 1 insertion(+) diff --git a/pubspec.yaml b/pubspec.yaml index 64bff52..4dbd358 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -13,6 +13,7 @@ dependencies: flutter: sdk: flutter cupertino_icons: ^1.0.2 + material_design_icons_flutter: ^5.0.6595 dev_dependencies: flutter_lints: ^2.0.0 From 1db9e2f075c175b599bddd4bdd8a19d41f1e70fd Mon Sep 17 00:00:00 2001 From: ilopX Date: Mon, 23 May 2022 18:33:08 +0300 Subject: [PATCH 05/91] Add states. --- .../pattern/manipulation_state.dart | 12 ++++++++ .../pattern/manipulator_context.dart | 29 ++++++++++++++++--- .../states/create_circle_state.dart | 5 ---- .../states/create_rectangle_state.dart | 5 ---- .../states/create_text_state.dart | 5 ---- .../creations/circle_creation_state.dart | 8 +++++ .../states/creations/creation_state.dart | 12 ++++++++ .../creations/rectangle_creation_state.dart | 8 +++++ .../states/creations/text_creation_state.dart | 8 +++++ .../manipulator_state/states/free_sate.dart | 5 +++- 10 files changed, 77 insertions(+), 20 deletions(-) delete mode 100644 patterns/state/manipulator_state/states/create_circle_state.dart delete mode 100644 patterns/state/manipulator_state/states/create_rectangle_state.dart delete mode 100644 patterns/state/manipulator_state/states/create_text_state.dart create mode 100644 patterns/state/manipulator_state/states/creations/circle_creation_state.dart create mode 100644 patterns/state/manipulator_state/states/creations/creation_state.dart create mode 100644 patterns/state/manipulator_state/states/creations/rectangle_creation_state.dart create mode 100644 patterns/state/manipulator_state/states/creations/text_creation_state.dart diff --git a/patterns/state/manipulator_state/pattern/manipulation_state.dart b/patterns/state/manipulator_state/pattern/manipulation_state.dart index 1457102..0d55a8e 100644 --- a/patterns/state/manipulator_state/pattern/manipulation_state.dart +++ b/patterns/state/manipulator_state/pattern/manipulation_state.dart @@ -1,4 +1,8 @@ +import 'manipulator_context.dart'; + class ManipulationState { + ManipulatorContext? context; + void mouseMove(double x, double y) {} void mouseDown(double x, y) {} @@ -6,4 +10,12 @@ class ManipulationState { void mouseUp() {} void keyDown(String key) {} + + @override + bool operator ==(Object other) { + return runtimeType == other.runtimeType; + } + + @override + int get hashCode => super.hashCode.toInt(); } diff --git a/patterns/state/manipulator_state/pattern/manipulator_context.dart b/patterns/state/manipulator_state/pattern/manipulator_context.dart index 28e6609..453a95d 100644 --- a/patterns/state/manipulator_state/pattern/manipulator_context.dart +++ b/patterns/state/manipulator_state/pattern/manipulator_context.dart @@ -1,15 +1,32 @@ -import 'dart:ui'; +import 'package:flutter/cupertino.dart'; import 'manipulation_state.dart'; class ManipulatorContext { - final ManipulationState initState; + late ManipulationState _state; - ManipulatorContext({required this.initState}); + ManipulatorContext({required ManipulationState initState}) + : _state = initState { + _state.context = this; + } + + ManipulationState get state => _state; + + void changeState(ManipulationState newState) { + if (_state == newState) { + return; + } + + _state = newState; + _state.context = this; + onStateChange._emit(); + } + + final onStateChange = Event(); void mouseMove(double x, double y) {} - void mouseDown(double x, y) {} + void mouseDown(double x, y) => _state.mouseDown(x, y); void mouseUp() {} @@ -17,3 +34,7 @@ class ManipulatorContext { void paint(Canvas canvas) {} } + +class Event extends ChangeNotifier { + void _emit() => notifyListeners(); +} diff --git a/patterns/state/manipulator_state/states/create_circle_state.dart b/patterns/state/manipulator_state/states/create_circle_state.dart deleted file mode 100644 index 755b348..0000000 --- a/patterns/state/manipulator_state/states/create_circle_state.dart +++ /dev/null @@ -1,5 +0,0 @@ -import '../pattern/manipulation_state.dart'; - -class CreateCircleState extends ManipulationState { - -} diff --git a/patterns/state/manipulator_state/states/create_rectangle_state.dart b/patterns/state/manipulator_state/states/create_rectangle_state.dart deleted file mode 100644 index 8e6dfa4..0000000 --- a/patterns/state/manipulator_state/states/create_rectangle_state.dart +++ /dev/null @@ -1,5 +0,0 @@ -import '../pattern/manipulation_state.dart'; - -class CreateRectangleState extends ManipulationState{ - -} diff --git a/patterns/state/manipulator_state/states/create_text_state.dart b/patterns/state/manipulator_state/states/create_text_state.dart deleted file mode 100644 index 228edda..0000000 --- a/patterns/state/manipulator_state/states/create_text_state.dart +++ /dev/null @@ -1,5 +0,0 @@ -import '../pattern/manipulation_state.dart'; - -class CreateTextState extends ManipulationState { - -} diff --git a/patterns/state/manipulator_state/states/creations/circle_creation_state.dart b/patterns/state/manipulator_state/states/creations/circle_creation_state.dart new file mode 100644 index 0000000..e6a849b --- /dev/null +++ b/patterns/state/manipulator_state/states/creations/circle_creation_state.dart @@ -0,0 +1,8 @@ +import 'creation_state.dart'; + +class CircleCreationState extends CreationState { + @override + String createShape() { + return 'Circle'; + } +} diff --git a/patterns/state/manipulator_state/states/creations/creation_state.dart b/patterns/state/manipulator_state/states/creations/creation_state.dart new file mode 100644 index 0000000..74c5bbb --- /dev/null +++ b/patterns/state/manipulator_state/states/creations/creation_state.dart @@ -0,0 +1,12 @@ +import '../../pattern/manipulation_state.dart'; +import '../free_sate.dart'; + +abstract class CreationState extends ManipulationState { + @override + void mouseDown(double x, y) { + print(createShape()); + context!.changeState(FreeState()); + } + + String createShape(); +} diff --git a/patterns/state/manipulator_state/states/creations/rectangle_creation_state.dart b/patterns/state/manipulator_state/states/creations/rectangle_creation_state.dart new file mode 100644 index 0000000..824bff1 --- /dev/null +++ b/patterns/state/manipulator_state/states/creations/rectangle_creation_state.dart @@ -0,0 +1,8 @@ +import 'creation_state.dart'; + +class RectangleCreationState extends CreationState { + @override + String createShape() { + return 'Rectangle'; + } +} diff --git a/patterns/state/manipulator_state/states/creations/text_creation_state.dart b/patterns/state/manipulator_state/states/creations/text_creation_state.dart new file mode 100644 index 0000000..77da857 --- /dev/null +++ b/patterns/state/manipulator_state/states/creations/text_creation_state.dart @@ -0,0 +1,8 @@ +import 'creation_state.dart'; + +class TextCreationState extends CreationState { + @override + String createShape() { + return 'Text'; + } +} diff --git a/patterns/state/manipulator_state/states/free_sate.dart b/patterns/state/manipulator_state/states/free_sate.dart index e39bae8..6c39482 100644 --- a/patterns/state/manipulator_state/states/free_sate.dart +++ b/patterns/state/manipulator_state/states/free_sate.dart @@ -1,5 +1,8 @@ import '../pattern/manipulation_state.dart'; class FreeState extends ManipulationState { - + @override + void mouseDown(double x, y) { + print('selected'); + } } From 50e10a5f5407c534da8123dd4ac59b459870e3a9 Mon Sep 17 00:00:00 2001 From: ilopX Date: Mon, 23 May 2022 18:33:54 +0300 Subject: [PATCH 06/91] Add "mouseDown" event to DrawingBoard. --- .../manipulator_state/widgets/drawing_board.dart | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/patterns/state/manipulator_state/widgets/drawing_board.dart b/patterns/state/manipulator_state/widgets/drawing_board.dart index 0fac333..e353242 100644 --- a/patterns/state/manipulator_state/widgets/drawing_board.dart +++ b/patterns/state/manipulator_state/widgets/drawing_board.dart @@ -9,10 +9,14 @@ class DrawingBoard extends StatelessWidget { @override Widget build(BuildContext context) { - return Container( - color: Colors.black12, - child: CustomPaint( - painter: _Painter(app), + return Listener( + onPointerUp: (e) => app.manipulator.mouseDown(0, 0), + child: Container( + constraints: BoxConstraints.expand(), + color: Color(0xff1f1f1f), + child: CustomPaint( + painter: _Painter(app), + ), ), ); } From 1f44a84b9d5632748acdea1eeb7e477361dc8eac Mon Sep 17 00:00:00 2001 From: ilopX Date: Mon, 23 May 2022 19:21:55 +0300 Subject: [PATCH 07/91] Add empty behaviors states. --- .../state/manipulator_state/app/shapes.dart | 9 ++++ patterns/state/manipulator_state/main.dart | 54 +++++++++++-------- .../pattern/manipulator_context.dart | 8 ++- .../manipulator_state/shapes/base_shape.dart | 51 ++++++++++++++++++ .../state/manipulator_state/shapes/shape.dart | 16 ++++++ .../creations/circle_creation_state.dart | 6 ++- .../states/creations/creation_state.dart | 9 ++-- .../creations/rectangle_creation_state.dart | 8 +-- .../states/creations/text_creation_state.dart | 6 ++- .../states/selections/selection_state.dart | 8 +++ .../widgets/drawing_board.dart | 18 ++++--- .../manipulator_state/widgets/tool_bar.dart | 31 ++++++----- 12 files changed, 164 insertions(+), 60 deletions(-) create mode 100644 patterns/state/manipulator_state/shapes/base_shape.dart create mode 100644 patterns/state/manipulator_state/states/selections/selection_state.dart diff --git a/patterns/state/manipulator_state/app/shapes.dart b/patterns/state/manipulator_state/app/shapes.dart index ecb158c..c4ba15d 100644 --- a/patterns/state/manipulator_state/app/shapes.dart +++ b/patterns/state/manipulator_state/app/shapes.dart @@ -1,5 +1,7 @@ import 'dart:collection'; +import 'package:flutter/foundation.dart'; + import '../shapes/shape.dart'; class Shapes with IterableMixin { @@ -7,8 +9,15 @@ class Shapes with IterableMixin { void add(Shape shape) { _shapes.add(shape); + onChange._emit(); } @override Iterator get iterator => _shapes.iterator; + + final onChange = Event(); +} + +class Event extends ChangeNotifier { + void _emit() => notifyListeners(); } diff --git a/patterns/state/manipulator_state/main.dart b/patterns/state/manipulator_state/main.dart index 4912ab4..728c8d5 100644 --- a/patterns/state/manipulator_state/main.dart +++ b/patterns/state/manipulator_state/main.dart @@ -20,30 +20,38 @@ class ManipulatorStateApp extends StatefulWidget { } class _ManipulatorStateAppState extends State { - final app = App( - shapes: Shapes(), - manipulator: ManipulatorContext( - initState: FreeState(), - ), - tools: [ - Tool( - icon: Icon(MdiIcons.cursorDefaultOutline), - state: FreeState(), - ), - Tool( - icon: Icon(MdiIcons.rectangleOutline), - state: RectangleCreationState(), - ), - Tool( - icon: Icon(MdiIcons.circleOutline), - state: CircleCreationState(), - ), - Tool( - icon: Icon(MdiIcons.formatTextVariant), - state: TextCreationState(), + late final App app; + + @override + void initState() { + final shapes = Shapes(); + app = App( + shapes: shapes, + manipulator: ManipulatorContext( + initState: FreeState(), + shapes: shapes, ), - ], - ); + tools: [ + Tool( + icon: Icon(MdiIcons.cursorDefaultOutline), + state: FreeState(), + ), + Tool( + icon: Icon(MdiIcons.rectangleOutline), + state: RectangleCreationState(), + ), + Tool( + icon: Icon(MdiIcons.circleOutline), + state: CircleCreationState(), + ), + Tool( + icon: Icon(MdiIcons.formatTextVariant), + state: TextCreationState(), + ), + ], + ); + super.initState(); + } @override Widget build(BuildContext context) { diff --git a/patterns/state/manipulator_state/pattern/manipulator_context.dart b/patterns/state/manipulator_state/pattern/manipulator_context.dart index 453a95d..5763b0f 100644 --- a/patterns/state/manipulator_state/pattern/manipulator_context.dart +++ b/patterns/state/manipulator_state/pattern/manipulator_context.dart @@ -1,12 +1,16 @@ import 'package:flutter/cupertino.dart'; +import '../app/shapes.dart'; import 'manipulation_state.dart'; class ManipulatorContext { + final Shapes shapes; late ManipulationState _state; - ManipulatorContext({required ManipulationState initState}) - : _state = initState { + ManipulatorContext({ + required this.shapes, + required ManipulationState initState, + }) : _state = initState { _state.context = this; } diff --git a/patterns/state/manipulator_state/shapes/base_shape.dart b/patterns/state/manipulator_state/shapes/base_shape.dart new file mode 100644 index 0000000..fb8b7a4 --- /dev/null +++ b/patterns/state/manipulator_state/shapes/base_shape.dart @@ -0,0 +1,51 @@ +import '../states/selections/selection_state.dart'; +import 'dart:ui'; + +import 'shape.dart'; + +class BaseShape implements Shape { + BaseShape(double x, double y, double width, double height) + : _x = x, + _y = y, + _width = width, + _height = height; + + @override + double get x => _x; + + @override + double get y => _y; + + @override + double get height => _height; + + @override + double get width => _width; + + @override + SelectionState createSelectionState() { + return SelectionState(); + } + + @override + void move(double x, double y) { + _x = x; + _y = y; + } + + @override + void resize(double width, double height) { + _width = width; + _height = height; + } + + @override + void paint(Canvas canvas) { + + } + + double _x; + double _y; + double _width; + double _height; +} diff --git a/patterns/state/manipulator_state/shapes/shape.dart b/patterns/state/manipulator_state/shapes/shape.dart index 77db6e0..84b0d5a 100644 --- a/patterns/state/manipulator_state/shapes/shape.dart +++ b/patterns/state/manipulator_state/shapes/shape.dart @@ -1,5 +1,21 @@ import 'dart:ui'; +import '../states/selections/selection_state.dart'; + abstract class Shape { + double get x; + + double get y; + + double get width; + + double get height; + + void move(double x, double y); + + void resize(double width, double height); + void paint(Canvas canvas); + + SelectionState createSelectionState(); } diff --git a/patterns/state/manipulator_state/states/creations/circle_creation_state.dart b/patterns/state/manipulator_state/states/creations/circle_creation_state.dart index e6a849b..a9ca010 100644 --- a/patterns/state/manipulator_state/states/creations/circle_creation_state.dart +++ b/patterns/state/manipulator_state/states/creations/circle_creation_state.dart @@ -1,8 +1,10 @@ +import '../../shapes/base_shape.dart'; +import '../../shapes/shape.dart'; import 'creation_state.dart'; class CircleCreationState extends CreationState { @override - String createShape() { - return 'Circle'; + Shape createShape() { + return BaseShape(100, 100, 100, 100); } } diff --git a/patterns/state/manipulator_state/states/creations/creation_state.dart b/patterns/state/manipulator_state/states/creations/creation_state.dart index 74c5bbb..f867a80 100644 --- a/patterns/state/manipulator_state/states/creations/creation_state.dart +++ b/patterns/state/manipulator_state/states/creations/creation_state.dart @@ -1,12 +1,13 @@ import '../../pattern/manipulation_state.dart'; -import '../free_sate.dart'; +import '../../shapes/shape.dart'; abstract class CreationState extends ManipulationState { @override void mouseDown(double x, y) { - print(createShape()); - context!.changeState(FreeState()); + final newShape = createShape(); + context!.shapes.add(newShape); + context!.changeState(newShape.createSelectionState()); } - String createShape(); + Shape createShape(); } diff --git a/patterns/state/manipulator_state/states/creations/rectangle_creation_state.dart b/patterns/state/manipulator_state/states/creations/rectangle_creation_state.dart index 824bff1..f6c5ec3 100644 --- a/patterns/state/manipulator_state/states/creations/rectangle_creation_state.dart +++ b/patterns/state/manipulator_state/states/creations/rectangle_creation_state.dart @@ -1,8 +1,10 @@ +import '../../shapes/base_shape.dart'; +import '../../shapes/shape.dart'; import 'creation_state.dart'; -class RectangleCreationState extends CreationState { +class RectangleCreationState extends CreationState { @override - String createShape() { - return 'Rectangle'; + Shape createShape() { + return BaseShape(100, 100, 100, 100); } } diff --git a/patterns/state/manipulator_state/states/creations/text_creation_state.dart b/patterns/state/manipulator_state/states/creations/text_creation_state.dart index 77da857..8e0c143 100644 --- a/patterns/state/manipulator_state/states/creations/text_creation_state.dart +++ b/patterns/state/manipulator_state/states/creations/text_creation_state.dart @@ -1,8 +1,10 @@ +import '../../shapes/base_shape.dart'; +import '../../shapes/shape.dart'; import 'creation_state.dart'; class TextCreationState extends CreationState { @override - String createShape() { - return 'Text'; + Shape createShape() { + return BaseShape(100, 100, 100, 100); } } diff --git a/patterns/state/manipulator_state/states/selections/selection_state.dart b/patterns/state/manipulator_state/states/selections/selection_state.dart new file mode 100644 index 0000000..6230e60 --- /dev/null +++ b/patterns/state/manipulator_state/states/selections/selection_state.dart @@ -0,0 +1,8 @@ +import '../../pattern/manipulation_state.dart'; + +class SelectionState extends ManipulationState { + @override + void mouseDown(double x, y) { + print('SelectionState'); + } +} diff --git a/patterns/state/manipulator_state/widgets/drawing_board.dart b/patterns/state/manipulator_state/widgets/drawing_board.dart index e353242..395f40a 100644 --- a/patterns/state/manipulator_state/widgets/drawing_board.dart +++ b/patterns/state/manipulator_state/widgets/drawing_board.dart @@ -1,5 +1,6 @@ import 'package:flutter/material.dart'; +import '../../../abstract_factory/tool_panel_factory/widgets/independent/event_listenable_builder.dart'; import '../app/app.dart'; class DrawingBoard extends StatelessWidget { @@ -13,10 +14,14 @@ class DrawingBoard extends StatelessWidget { onPointerUp: (e) => app.manipulator.mouseDown(0, 0), child: Container( constraints: BoxConstraints.expand(), - color: Color(0xff1f1f1f), - child: CustomPaint( - painter: _Painter(app), - ), + color: Color(0xff1f1f1f), + child: EventListenableBuilder( + event: app.shapes.onChange, + builder: (_) { + return CustomPaint( + painter: _Painter(app), + ); + }), ), ); } @@ -29,7 +34,7 @@ class _Painter extends CustomPainter { @override void paint(Canvas canvas, Size size) { - for(final shape in app.shapes) { + for (final shape in app.shapes) { shape.paint(canvas); } @@ -40,7 +45,4 @@ class _Painter extends CustomPainter { bool shouldRepaint(covariant CustomPainter oldDelegate) { return true; } - } - - diff --git a/patterns/state/manipulator_state/widgets/tool_bar.dart b/patterns/state/manipulator_state/widgets/tool_bar.dart index 1779959..017dcc4 100644 --- a/patterns/state/manipulator_state/widgets/tool_bar.dart +++ b/patterns/state/manipulator_state/widgets/tool_bar.dart @@ -20,22 +20,21 @@ class ToolBar extends StatelessWidget { thicknessHeight: 64, direction: Axis.horizontal, child: EventListenableBuilder( - event: app.manipulator.onStateChange, - builder: (_) { - return Row( - children: [ - for (final tool in app.tools) - ToolButton( - active: tool.state == app.manipulator.state, - icon: Center(child: tool.icon), - onTap: () { - app.manipulator.changeState(tool.state); - }, - ) - ], - ); - } - ), + event: app.manipulator.onStateChange, + builder: (_) { + return Row( + children: [ + for (final tool in app.tools) + ToolButton( + active: tool.state == app.manipulator.state, + icon: Center(child: tool.icon), + onTap: () { + app.manipulator.changeState(tool.state); + }, + ) + ], + ); + }), ), ); } From 163eff9281528d0032fa9782937268899a19fbf9 Mon Sep 17 00:00:00 2001 From: ilopX Date: Mon, 23 May 2022 19:26:38 +0300 Subject: [PATCH 08/91] Add default shape painting. --- patterns/state/manipulator_state/shapes/base_shape.dart | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/patterns/state/manipulator_state/shapes/base_shape.dart b/patterns/state/manipulator_state/shapes/base_shape.dart index fb8b7a4..e51d83a 100644 --- a/patterns/state/manipulator_state/shapes/base_shape.dart +++ b/patterns/state/manipulator_state/shapes/base_shape.dart @@ -1,3 +1,5 @@ +import 'package:flutter/material.dart'; + import '../states/selections/selection_state.dart'; import 'dart:ui'; @@ -41,7 +43,12 @@ class BaseShape implements Shape { @override void paint(Canvas canvas) { - + canvas.drawRect( + Rect.fromCenter(center: Offset(_x, _y), width: _width, height: _height), + Paint() + ..color = Colors.white + ..style = PaintingStyle.stroke, + ); } double _x; From 1b437b118fd642160a2ed588546bcb827835e903 Mon Sep 17 00:00:00 2001 From: ilopX Date: Tue, 24 May 2022 00:26:11 +0300 Subject: [PATCH 09/91] Make context is private. --- patterns/state/manipulator_state/app/tool.dart | 2 +- .../manipulator_state/pattern/manipulation_state.dart | 6 ++++-- .../manipulator_state/pattern/manipulator_context.dart | 10 ++++++---- .../state/manipulator_state/shapes/base_shape.dart | 2 -- .../states/creations/creation_state.dart | 6 +++--- patterns/state/manipulator_state/states/free_sate.dart | 2 +- .../states/selections/selection_state.dart | 2 +- 7 files changed, 16 insertions(+), 14 deletions(-) diff --git a/patterns/state/manipulator_state/app/tool.dart b/patterns/state/manipulator_state/app/tool.dart index e846e72..8ac8fac 100644 --- a/patterns/state/manipulator_state/app/tool.dart +++ b/patterns/state/manipulator_state/app/tool.dart @@ -1,6 +1,6 @@ import 'package:flutter/widgets.dart'; -import '../pattern/manipulation_state.dart'; +import '../pattern/manipulator_context.dart'; class Tool { final Icon icon; diff --git a/patterns/state/manipulator_state/pattern/manipulation_state.dart b/patterns/state/manipulator_state/pattern/manipulation_state.dart index 0d55a8e..6e98006 100644 --- a/patterns/state/manipulator_state/pattern/manipulation_state.dart +++ b/patterns/state/manipulator_state/pattern/manipulation_state.dart @@ -1,7 +1,9 @@ -import 'manipulator_context.dart'; +part of manipulator; class ManipulationState { - ManipulatorContext? context; + ManipulatorContext? _context; + + ManipulatorContext get context => _context!; void mouseMove(double x, double y) {} diff --git a/patterns/state/manipulator_state/pattern/manipulator_context.dart b/patterns/state/manipulator_state/pattern/manipulator_context.dart index 5763b0f..c2c2757 100644 --- a/patterns/state/manipulator_state/pattern/manipulator_context.dart +++ b/patterns/state/manipulator_state/pattern/manipulator_context.dart @@ -1,7 +1,9 @@ -import 'package:flutter/cupertino.dart'; +library manipulator; +import 'package:flutter/material.dart'; import '../app/shapes.dart'; -import 'manipulation_state.dart'; + +part 'manipulation_state.dart'; class ManipulatorContext { final Shapes shapes; @@ -11,7 +13,7 @@ class ManipulatorContext { required this.shapes, required ManipulationState initState, }) : _state = initState { - _state.context = this; + _state._context = this; } ManipulationState get state => _state; @@ -22,7 +24,7 @@ class ManipulatorContext { } _state = newState; - _state.context = this; + _state._context = this; onStateChange._emit(); } diff --git a/patterns/state/manipulator_state/shapes/base_shape.dart b/patterns/state/manipulator_state/shapes/base_shape.dart index e51d83a..e4d7bea 100644 --- a/patterns/state/manipulator_state/shapes/base_shape.dart +++ b/patterns/state/manipulator_state/shapes/base_shape.dart @@ -1,8 +1,6 @@ import 'package:flutter/material.dart'; import '../states/selections/selection_state.dart'; -import 'dart:ui'; - import 'shape.dart'; class BaseShape implements Shape { diff --git a/patterns/state/manipulator_state/states/creations/creation_state.dart b/patterns/state/manipulator_state/states/creations/creation_state.dart index f867a80..d3c20d6 100644 --- a/patterns/state/manipulator_state/states/creations/creation_state.dart +++ b/patterns/state/manipulator_state/states/creations/creation_state.dart @@ -1,12 +1,12 @@ -import '../../pattern/manipulation_state.dart'; +import '../../pattern/manipulator_context.dart'; import '../../shapes/shape.dart'; abstract class CreationState extends ManipulationState { @override void mouseDown(double x, y) { final newShape = createShape(); - context!.shapes.add(newShape); - context!.changeState(newShape.createSelectionState()); + context.shapes.add(newShape); + context.changeState(newShape.createSelectionState()); } Shape createShape(); diff --git a/patterns/state/manipulator_state/states/free_sate.dart b/patterns/state/manipulator_state/states/free_sate.dart index 6c39482..219b65d 100644 --- a/patterns/state/manipulator_state/states/free_sate.dart +++ b/patterns/state/manipulator_state/states/free_sate.dart @@ -1,4 +1,4 @@ -import '../pattern/manipulation_state.dart'; +import '../pattern/manipulator_context.dart'; class FreeState extends ManipulationState { @override diff --git a/patterns/state/manipulator_state/states/selections/selection_state.dart b/patterns/state/manipulator_state/states/selections/selection_state.dart index 6230e60..af0786e 100644 --- a/patterns/state/manipulator_state/states/selections/selection_state.dart +++ b/patterns/state/manipulator_state/states/selections/selection_state.dart @@ -1,4 +1,4 @@ -import '../../pattern/manipulation_state.dart'; +import '../../pattern/manipulator_context.dart'; class SelectionState extends ManipulationState { @override From 60b0785e9d5e913e1d33c27e19bdfc518cc71114 Mon Sep 17 00:00:00 2001 From: ilopX Date: Tue, 24 May 2022 00:40:54 +0300 Subject: [PATCH 10/91] Fix: add type to "y" argument. --- .../state/manipulator_state/pattern/manipulation_state.dart | 2 +- .../manipulator_state/states/creations/creation_state.dart | 2 +- patterns/state/manipulator_state/states/free_sate.dart | 2 +- .../manipulator_state/states/selections/selection_state.dart | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/patterns/state/manipulator_state/pattern/manipulation_state.dart b/patterns/state/manipulator_state/pattern/manipulation_state.dart index 6e98006..3a0d285 100644 --- a/patterns/state/manipulator_state/pattern/manipulation_state.dart +++ b/patterns/state/manipulator_state/pattern/manipulation_state.dart @@ -7,7 +7,7 @@ class ManipulationState { void mouseMove(double x, double y) {} - void mouseDown(double x, y) {} + void mouseDown(double x, double y) {} void mouseUp() {} diff --git a/patterns/state/manipulator_state/states/creations/creation_state.dart b/patterns/state/manipulator_state/states/creations/creation_state.dart index d3c20d6..f3bc87b 100644 --- a/patterns/state/manipulator_state/states/creations/creation_state.dart +++ b/patterns/state/manipulator_state/states/creations/creation_state.dart @@ -3,7 +3,7 @@ import '../../shapes/shape.dart'; abstract class CreationState extends ManipulationState { @override - void mouseDown(double x, y) { + void mouseDown(double x, double y) { final newShape = createShape(); context.shapes.add(newShape); context.changeState(newShape.createSelectionState()); diff --git a/patterns/state/manipulator_state/states/free_sate.dart b/patterns/state/manipulator_state/states/free_sate.dart index 219b65d..3a73f92 100644 --- a/patterns/state/manipulator_state/states/free_sate.dart +++ b/patterns/state/manipulator_state/states/free_sate.dart @@ -2,7 +2,7 @@ import '../pattern/manipulator_context.dart'; class FreeState extends ManipulationState { @override - void mouseDown(double x, y) { + void mouseDown(double x, double y) { print('selected'); } } diff --git a/patterns/state/manipulator_state/states/selections/selection_state.dart b/patterns/state/manipulator_state/states/selections/selection_state.dart index af0786e..6b4bcf4 100644 --- a/patterns/state/manipulator_state/states/selections/selection_state.dart +++ b/patterns/state/manipulator_state/states/selections/selection_state.dart @@ -2,7 +2,7 @@ import '../../pattern/manipulator_context.dart'; class SelectionState extends ManipulationState { @override - void mouseDown(double x, y) { + void mouseDown(double x, double y) { print('SelectionState'); } } From f77c5e5bf4adc3f434228809d5e36af43744737f Mon Sep 17 00:00:00 2001 From: ilopX Date: Tue, 24 May 2022 00:43:30 +0300 Subject: [PATCH 11/91] Add x,y args to CreationState --- .../states/creations/circle_creation_state.dart | 4 ++-- .../manipulator_state/states/creations/creation_state.dart | 7 ++++--- .../states/creations/rectangle_creation_state.dart | 4 ++-- .../states/creations/text_creation_state.dart | 4 ++-- 4 files changed, 10 insertions(+), 9 deletions(-) diff --git a/patterns/state/manipulator_state/states/creations/circle_creation_state.dart b/patterns/state/manipulator_state/states/creations/circle_creation_state.dart index a9ca010..c24e0cd 100644 --- a/patterns/state/manipulator_state/states/creations/circle_creation_state.dart +++ b/patterns/state/manipulator_state/states/creations/circle_creation_state.dart @@ -4,7 +4,7 @@ import 'creation_state.dart'; class CircleCreationState extends CreationState { @override - Shape createShape() { - return BaseShape(100, 100, 100, 100); + Shape createShape(double x, double y) { + return BaseShape(x, y, 100, 100); } } diff --git a/patterns/state/manipulator_state/states/creations/creation_state.dart b/patterns/state/manipulator_state/states/creations/creation_state.dart index f3bc87b..6b588c9 100644 --- a/patterns/state/manipulator_state/states/creations/creation_state.dart +++ b/patterns/state/manipulator_state/states/creations/creation_state.dart @@ -1,13 +1,14 @@ import '../../pattern/manipulator_context.dart'; import '../../shapes/shape.dart'; +import '../free_sate.dart'; abstract class CreationState extends ManipulationState { @override void mouseDown(double x, double y) { - final newShape = createShape(); + final newShape = createShape(x, y); context.shapes.add(newShape); - context.changeState(newShape.createSelectionState()); + context.changeState(FreeState()); } - Shape createShape(); + Shape createShape(double x, double y); } diff --git a/patterns/state/manipulator_state/states/creations/rectangle_creation_state.dart b/patterns/state/manipulator_state/states/creations/rectangle_creation_state.dart index f6c5ec3..8ca53b3 100644 --- a/patterns/state/manipulator_state/states/creations/rectangle_creation_state.dart +++ b/patterns/state/manipulator_state/states/creations/rectangle_creation_state.dart @@ -4,7 +4,7 @@ import 'creation_state.dart'; class RectangleCreationState extends CreationState { @override - Shape createShape() { - return BaseShape(100, 100, 100, 100); + Shape createShape(double x, double y) { + return BaseShape(x, y, 100, 100); } } diff --git a/patterns/state/manipulator_state/states/creations/text_creation_state.dart b/patterns/state/manipulator_state/states/creations/text_creation_state.dart index 8e0c143..462a0b8 100644 --- a/patterns/state/manipulator_state/states/creations/text_creation_state.dart +++ b/patterns/state/manipulator_state/states/creations/text_creation_state.dart @@ -4,7 +4,7 @@ import 'creation_state.dart'; class TextCreationState extends CreationState { @override - Shape createShape() { - return BaseShape(100, 100, 100, 100); + Shape createShape(double x, double y) { + return BaseShape(x, y, 100, 100); } } From fc48e3478ce67cfc252f903adf8936092c2a225d Mon Sep 17 00:00:00 2001 From: ilopX Date: Tue, 24 May 2022 00:49:42 +0300 Subject: [PATCH 12/91] Fix: x,y in mouseDown. --- .../manipulator_state/pattern/manipulator_context.dart | 2 +- patterns/state/manipulator_state/widgets/drawing_board.dart | 6 +++++- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/patterns/state/manipulator_state/pattern/manipulator_context.dart b/patterns/state/manipulator_state/pattern/manipulator_context.dart index c2c2757..a1e8c7a 100644 --- a/patterns/state/manipulator_state/pattern/manipulator_context.dart +++ b/patterns/state/manipulator_state/pattern/manipulator_context.dart @@ -32,7 +32,7 @@ class ManipulatorContext { void mouseMove(double x, double y) {} - void mouseDown(double x, y) => _state.mouseDown(x, y); + void mouseDown(double x, double y) => _state.mouseDown(x, y); void mouseUp() {} diff --git a/patterns/state/manipulator_state/widgets/drawing_board.dart b/patterns/state/manipulator_state/widgets/drawing_board.dart index 395f40a..6bd3c36 100644 --- a/patterns/state/manipulator_state/widgets/drawing_board.dart +++ b/patterns/state/manipulator_state/widgets/drawing_board.dart @@ -11,7 +11,10 @@ class DrawingBoard extends StatelessWidget { @override Widget build(BuildContext context) { return Listener( - onPointerUp: (e) => app.manipulator.mouseDown(0, 0), + onPointerUp: (e) => app.manipulator.mouseDown( + e.localPosition.dx, + e.localPosition.dy, + ), child: Container( constraints: BoxConstraints.expand(), color: Color(0xff1f1f1f), @@ -34,6 +37,7 @@ class _Painter extends CustomPainter { @override void paint(Canvas canvas, Size size) { + canvas.translate(0.5, 0.5); for (final shape in app.shapes) { shape.paint(canvas); } From 4a707b4b6f745313ae73e6aa32f3253fd506984e Mon Sep 17 00:00:00 2001 From: ilopX Date: Tue, 24 May 2022 03:01:03 +0300 Subject: [PATCH 13/91] Draggable adds. --- .../pattern/manipulation_state.dart | 2 + .../pattern/manipulator_context.dart | 30 ++++++++--- .../manipulator_state/shapes/base_shape.dart | 5 +- .../states/creations/creation_state.dart | 51 +++++++++++++++++-- .../creations/rectangle_creation_state.dart | 2 +- .../states/selections/selection_state.dart | 25 ++++++++- .../widgets/drawing_board.dart | 24 ++++++--- 7 files changed, 117 insertions(+), 22 deletions(-) diff --git a/patterns/state/manipulator_state/pattern/manipulation_state.dart b/patterns/state/manipulator_state/pattern/manipulation_state.dart index 3a0d285..27234c7 100644 --- a/patterns/state/manipulator_state/pattern/manipulation_state.dart +++ b/patterns/state/manipulator_state/pattern/manipulation_state.dart @@ -13,6 +13,8 @@ class ManipulationState { void keyDown(String key) {} + void paint(Canvas canvas) {} + @override bool operator ==(Object other) { return runtimeType == other.runtimeType; diff --git a/patterns/state/manipulator_state/pattern/manipulator_context.dart b/patterns/state/manipulator_state/pattern/manipulator_context.dart index a1e8c7a..ebd9d58 100644 --- a/patterns/state/manipulator_state/pattern/manipulator_context.dart +++ b/patterns/state/manipulator_state/pattern/manipulator_context.dart @@ -7,7 +7,8 @@ part 'manipulation_state.dart'; class ManipulatorContext { final Shapes shapes; - late ManipulationState _state; + + ManipulationState _state; ManipulatorContext({ required this.shapes, @@ -29,18 +30,35 @@ class ManipulatorContext { } final onStateChange = Event(); + final onUpdate = Event(); - void mouseMove(double x, double y) {} + void update(){ + onUpdate._emit(); + } - void mouseDown(double x, double y) => _state.mouseDown(x, y); + void mouseMove(double x, double y) { + _state.mouseMove(x, y); + } + + void mouseDown(double x, double y) { + _state.mouseDown(x, y); + } - void mouseUp() {} + void mouseUp() { + _state.mouseUp(); + } - void keyDown(String key) {} + void keyDown(String key) { + _state.keyDown(key); + } - void paint(Canvas canvas) {} + void paint(Canvas canvas) { + _state.paint(canvas); + } } class Event extends ChangeNotifier { void _emit() => notifyListeners(); } + + diff --git a/patterns/state/manipulator_state/shapes/base_shape.dart b/patterns/state/manipulator_state/shapes/base_shape.dart index e4d7bea..55a8578 100644 --- a/patterns/state/manipulator_state/shapes/base_shape.dart +++ b/patterns/state/manipulator_state/shapes/base_shape.dart @@ -24,7 +24,7 @@ class BaseShape implements Shape { @override SelectionState createSelectionState() { - return SelectionState(); + return SelectionState(selectedShape: this); } @override @@ -42,10 +42,9 @@ class BaseShape implements Shape { @override void paint(Canvas canvas) { canvas.drawRect( - Rect.fromCenter(center: Offset(_x, _y), width: _width, height: _height), + Rect.fromLTWH(_x, _y, _width, _height), Paint() ..color = Colors.white - ..style = PaintingStyle.stroke, ); } diff --git a/patterns/state/manipulator_state/states/creations/creation_state.dart b/patterns/state/manipulator_state/states/creations/creation_state.dart index 6b588c9..2564946 100644 --- a/patterns/state/manipulator_state/states/creations/creation_state.dart +++ b/patterns/state/manipulator_state/states/creations/creation_state.dart @@ -1,13 +1,56 @@ +import 'dart:ui'; + import '../../pattern/manipulator_context.dart'; import '../../shapes/shape.dart'; -import '../free_sate.dart'; +import '../selections/selection_state.dart'; abstract class CreationState extends ManipulationState { + var _startX = 0.0; + var _startY = 0.0; + Shape? _newShape; + var _isDragged = false; + @override void mouseDown(double x, double y) { - final newShape = createShape(x, y); - context.shapes.add(newShape); - context.changeState(FreeState()); + _startX = x; + _startY = y; + _newShape = createShape(x, y); + } + + @override + void mouseMove(double x, double y) { + if (_newShape == null) { + return; + } + + _isDragged = true; + _newShape!.resize(x - _startX, y - _startY); + context.update(); + } + + @override + void mouseUp() { + if (_newShape == null) { + return; + } + + if (!_isDragged) { + _newShape!.move(_startX-50, _startY-50); + _newShape!.resize(100, 100); + } + + _isDragged = false; + context.shapes.add(_newShape!); + context.changeState( + SelectionState( + selectedShape: _newShape!, + ), + ); + } + + @override + void paint(Canvas canvas) { + _newShape?.paint(canvas); } Shape createShape(double x, double y); diff --git a/patterns/state/manipulator_state/states/creations/rectangle_creation_state.dart b/patterns/state/manipulator_state/states/creations/rectangle_creation_state.dart index 8ca53b3..d9fbbb7 100644 --- a/patterns/state/manipulator_state/states/creations/rectangle_creation_state.dart +++ b/patterns/state/manipulator_state/states/creations/rectangle_creation_state.dart @@ -5,6 +5,6 @@ import 'creation_state.dart'; class RectangleCreationState extends CreationState { @override Shape createShape(double x, double y) { - return BaseShape(x, y, 100, 100); + return BaseShape(x, y, 0, 0); } } diff --git a/patterns/state/manipulator_state/states/selections/selection_state.dart b/patterns/state/manipulator_state/states/selections/selection_state.dart index 6b4bcf4..1eb529f 100644 --- a/patterns/state/manipulator_state/states/selections/selection_state.dart +++ b/patterns/state/manipulator_state/states/selections/selection_state.dart @@ -1,8 +1,31 @@ +import 'package:flutter/material.dart'; + import '../../pattern/manipulator_context.dart'; +import '../../shapes/shape.dart'; +import '../free_sate.dart'; class SelectionState extends ManipulationState { + final Shape selectedShape; + + SelectionState({required this.selectedShape}); + @override void mouseDown(double x, double y) { - print('SelectionState'); + context.changeState(FreeState()); + } + + @override + void paint(Canvas canvas) { + canvas.drawRect( + Rect.fromLTWH( + selectedShape.x - 1, + selectedShape.y - 1, + selectedShape.width + 1, + selectedShape.height + 1, + ), + Paint() + ..color = Colors.cyanAccent + ..style = PaintingStyle.stroke, + ); } } diff --git a/patterns/state/manipulator_state/widgets/drawing_board.dart b/patterns/state/manipulator_state/widgets/drawing_board.dart index 6bd3c36..6ad0efb 100644 --- a/patterns/state/manipulator_state/widgets/drawing_board.dart +++ b/patterns/state/manipulator_state/widgets/drawing_board.dart @@ -11,20 +11,30 @@ class DrawingBoard extends StatelessWidget { @override Widget build(BuildContext context) { return Listener( - onPointerUp: (e) => app.manipulator.mouseDown( + onPointerDown: (e) => app.manipulator.mouseDown( e.localPosition.dx, e.localPosition.dy, ), + onPointerMove: (e) => app.manipulator.mouseMove( + e.localPosition.dx, + e.localPosition.dy, + ), + onPointerUp: (e) => app.manipulator.mouseUp(), child: Container( constraints: BoxConstraints.expand(), color: Color(0xff1f1f1f), child: EventListenableBuilder( - event: app.shapes.onChange, - builder: (_) { - return CustomPaint( - painter: _Painter(app), - ); - }), + event: app.shapes.onChange, + builder: (_) { + return EventListenableBuilder( + event: app.manipulator.onUpdate, + builder: (_) { + return CustomPaint( + painter: _Painter(app), + ); + }); + }, + ), ), ); } From 005c1d1db5f2becd9a5445875bc43de2543986a7 Mon Sep 17 00:00:00 2001 From: ilopX Date: Tue, 24 May 2022 15:24:38 +0300 Subject: [PATCH 14/91] Add specific actions to states. --- .../state/manipulator_state/app/shapes.dart | 13 ++++++++++++ .../pattern/manipulation_state.dart | 8 -------- .../states/creations/creation_state.dart | 3 ++- .../manipulator_state/states/free_sate.dart | 7 +++++-- .../states/selections/selection_state.dart | 20 ++++++++++++------- .../states/specific_actions_mixin.dart | 20 +++++++++++++++++++ .../manipulator_state/widgets/tool_bar.dart | 2 +- pubspec.yaml | 2 +- 8 files changed, 55 insertions(+), 20 deletions(-) create mode 100644 patterns/state/manipulator_state/states/specific_actions_mixin.dart diff --git a/patterns/state/manipulator_state/app/shapes.dart b/patterns/state/manipulator_state/app/shapes.dart index c4ba15d..094cb1b 100644 --- a/patterns/state/manipulator_state/app/shapes.dart +++ b/patterns/state/manipulator_state/app/shapes.dart @@ -1,4 +1,5 @@ import 'dart:collection'; +import 'dart:ui'; import 'package:flutter/foundation.dart'; @@ -16,6 +17,18 @@ class Shapes with IterableMixin { Iterator get iterator => _shapes.iterator; final onChange = Event(); + + Shape? shapeFromCoordinate(x, y) { + for(final shape in _shapes){ + final shapeRect = Rect.fromLTWH(shape.x, shape.y, shape.width, shape.height,); + + if (shapeRect.contains(Offset(x, y))) { + return shape; + } + } + + return null; + } } class Event extends ChangeNotifier { diff --git a/patterns/state/manipulator_state/pattern/manipulation_state.dart b/patterns/state/manipulator_state/pattern/manipulation_state.dart index 27234c7..c041708 100644 --- a/patterns/state/manipulator_state/pattern/manipulation_state.dart +++ b/patterns/state/manipulator_state/pattern/manipulation_state.dart @@ -14,12 +14,4 @@ class ManipulationState { void keyDown(String key) {} void paint(Canvas canvas) {} - - @override - bool operator ==(Object other) { - return runtimeType == other.runtimeType; - } - - @override - int get hashCode => super.hashCode.toInt(); } diff --git a/patterns/state/manipulator_state/states/creations/creation_state.dart b/patterns/state/manipulator_state/states/creations/creation_state.dart index 2564946..dc8cee3 100644 --- a/patterns/state/manipulator_state/states/creations/creation_state.dart +++ b/patterns/state/manipulator_state/states/creations/creation_state.dart @@ -11,10 +11,11 @@ abstract class CreationState extends ManipulationState { var _isDragged = false; @override - void mouseDown(double x, double y) { + bool mouseDown(double x, double y) { _startX = x; _startY = y; _newShape = createShape(x, y); + return true; } @override diff --git a/patterns/state/manipulator_state/states/free_sate.dart b/patterns/state/manipulator_state/states/free_sate.dart index 3a73f92..0e20988 100644 --- a/patterns/state/manipulator_state/states/free_sate.dart +++ b/patterns/state/manipulator_state/states/free_sate.dart @@ -1,8 +1,11 @@ import '../pattern/manipulator_context.dart'; +import 'specific_actions_mixin.dart'; -class FreeState extends ManipulationState { +class FreeState extends ManipulationState with SpecificActionsMixin { @override void mouseDown(double x, double y) { - print('selected'); + trySelectShape(x, y); } } + + diff --git a/patterns/state/manipulator_state/states/selections/selection_state.dart b/patterns/state/manipulator_state/states/selections/selection_state.dart index 1eb529f..a7616f0 100644 --- a/patterns/state/manipulator_state/states/selections/selection_state.dart +++ b/patterns/state/manipulator_state/states/selections/selection_state.dart @@ -3,29 +3,35 @@ import 'package:flutter/material.dart'; import '../../pattern/manipulator_context.dart'; import '../../shapes/shape.dart'; import '../free_sate.dart'; +import '../specific_actions_mixin.dart'; -class SelectionState extends ManipulationState { +class SelectionState extends ManipulationState with SpecificActionsMixin { final Shape selectedShape; SelectionState({required this.selectedShape}); @override void mouseDown(double x, double y) { - context.changeState(FreeState()); + final isNotShapeSelected = !trySelectShape(x, y); + + if (isNotShapeSelected) { + context.changeState(FreeState()); + } } @override void paint(Canvas canvas) { canvas.drawRect( Rect.fromLTWH( - selectedShape.x - 1, - selectedShape.y - 1, - selectedShape.width + 1, - selectedShape.height + 1, + selectedShape.x-1, + selectedShape.y-1, + selectedShape.width+2, + selectedShape.height+2, ), Paint() ..color = Colors.cyanAccent - ..style = PaintingStyle.stroke, + ..style = PaintingStyle.stroke + ..strokeWidth = 2.0, ); } } diff --git a/patterns/state/manipulator_state/states/specific_actions_mixin.dart b/patterns/state/manipulator_state/states/specific_actions_mixin.dart new file mode 100644 index 0000000..e1c4de1 --- /dev/null +++ b/patterns/state/manipulator_state/states/specific_actions_mixin.dart @@ -0,0 +1,20 @@ +import '../pattern/manipulator_context.dart'; +import 'selections/selection_state.dart'; + +mixin SpecificActionsMixin implements ManipulationState { + bool trySelectShape(double x, double y) { + final shape = context.shapes.shapeFromCoordinate(x, y); + + if (shape == null) { + return false; + } + + context.changeState( + SelectionState( + selectedShape: shape, + ), + ); + + return true; + } +} diff --git a/patterns/state/manipulator_state/widgets/tool_bar.dart b/patterns/state/manipulator_state/widgets/tool_bar.dart index 017dcc4..10bfe2c 100644 --- a/patterns/state/manipulator_state/widgets/tool_bar.dart +++ b/patterns/state/manipulator_state/widgets/tool_bar.dart @@ -26,7 +26,7 @@ class ToolBar extends StatelessWidget { children: [ for (final tool in app.tools) ToolButton( - active: tool.state == app.manipulator.state, + active: tool.state.runtimeType == app.manipulator.state.runtimeType, icon: Center(child: tool.icon), onTap: () { app.manipulator.changeState(tool.state); diff --git a/pubspec.yaml b/pubspec.yaml index 4dbd358..becc532 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -6,7 +6,7 @@ repository: https://github.com/RefactoringGuru/design-patterns-dart issue_tracker: https://github.com/RefactoringGuru/design-patterns-dart/issue environment: - sdk: ">=2.17.1 <3.0.0" + sdk: ">=2.17.0 <3.0.0" dependencies: collection: ^1.15.0 From b508da3581565f34dc16ef9b550072c7eac4f7a2 Mon Sep 17 00:00:00 2001 From: ilopX Date: Tue, 24 May 2022 15:40:41 +0300 Subject: [PATCH 15/91] Remove duplicate selection. --- .../manipulator_state/states/specific_actions_mixin.dart | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/patterns/state/manipulator_state/states/specific_actions_mixin.dart b/patterns/state/manipulator_state/states/specific_actions_mixin.dart index e1c4de1..7fad5a5 100644 --- a/patterns/state/manipulator_state/states/specific_actions_mixin.dart +++ b/patterns/state/manipulator_state/states/specific_actions_mixin.dart @@ -9,12 +9,18 @@ mixin SpecificActionsMixin implements ManipulationState { return false; } + if (context.state is SelectionState && + (context.state as SelectionState).selectedShape == shape) { + return true; + } + context.changeState( SelectionState( selectedShape: shape, ), ); + context.update(); return true; } } From e5d9525df7c66e9382c3ea5326fd973a78fa35d6 Mon Sep 17 00:00:00 2001 From: ilopX Date: Tue, 24 May 2022 17:04:13 +0300 Subject: [PATCH 16/91] Add hover event. --- .../state/manipulator_state/app/shapes.dart | 9 +++- .../pattern/manipulator_context.dart | 6 +-- .../manipulator_state/shapes/base_shape.dart | 10 +++-- .../states/creations/creation_state.dart | 12 ++++-- .../manipulator_state/states/free_sate.dart | 2 - .../states/selections/selection_state.dart | 11 ++--- .../states/specific_actions_mixin.dart | 41 +++++++++++++++++-- .../widgets/drawing_board.dart | 18 +++++--- .../manipulator_state/widgets/tool_bar.dart | 3 +- 9 files changed, 85 insertions(+), 27 deletions(-) diff --git a/patterns/state/manipulator_state/app/shapes.dart b/patterns/state/manipulator_state/app/shapes.dart index 094cb1b..67701b9 100644 --- a/patterns/state/manipulator_state/app/shapes.dart +++ b/patterns/state/manipulator_state/app/shapes.dart @@ -19,8 +19,13 @@ class Shapes with IterableMixin { final onChange = Event(); Shape? shapeFromCoordinate(x, y) { - for(final shape in _shapes){ - final shapeRect = Rect.fromLTWH(shape.x, shape.y, shape.width, shape.height,); + for (final shape in _shapes) { + final shapeRect = Rect.fromLTWH( + shape.x, + shape.y, + shape.width, + shape.height, + ); if (shapeRect.contains(Offset(x, y))) { return shape; diff --git a/patterns/state/manipulator_state/pattern/manipulator_context.dart b/patterns/state/manipulator_state/pattern/manipulator_context.dart index ebd9d58..d5bda00 100644 --- a/patterns/state/manipulator_state/pattern/manipulator_context.dart +++ b/patterns/state/manipulator_state/pattern/manipulator_context.dart @@ -32,7 +32,9 @@ class ManipulatorContext { final onStateChange = Event(); final onUpdate = Event(); - void update(){ + var cursor = MouseCursor.defer; + + void update() { onUpdate._emit(); } @@ -60,5 +62,3 @@ class ManipulatorContext { class Event extends ChangeNotifier { void _emit() => notifyListeners(); } - - diff --git a/patterns/state/manipulator_state/shapes/base_shape.dart b/patterns/state/manipulator_state/shapes/base_shape.dart index 55a8578..5938f15 100644 --- a/patterns/state/manipulator_state/shapes/base_shape.dart +++ b/patterns/state/manipulator_state/shapes/base_shape.dart @@ -42,9 +42,13 @@ class BaseShape implements Shape { @override void paint(Canvas canvas) { canvas.drawRect( - Rect.fromLTWH(_x, _y, _width, _height), - Paint() - ..color = Colors.white + Rect.fromLTWH( + _x, + _y, + _width, + _height, + ), + Paint()..color = Colors.white, ); } diff --git a/patterns/state/manipulator_state/states/creations/creation_state.dart b/patterns/state/manipulator_state/states/creations/creation_state.dart index dc8cee3..88d136f 100644 --- a/patterns/state/manipulator_state/states/creations/creation_state.dart +++ b/patterns/state/manipulator_state/states/creations/creation_state.dart @@ -3,8 +3,10 @@ import 'dart:ui'; import '../../pattern/manipulator_context.dart'; import '../../shapes/shape.dart'; import '../selections/selection_state.dart'; +import '../specific_actions_mixin.dart'; -abstract class CreationState extends ManipulationState { +abstract class CreationState extends ManipulationState + with SpecificActionsMixin { var _startX = 0.0; var _startY = 0.0; Shape? _newShape; @@ -21,6 +23,7 @@ abstract class CreationState extends ManipulationState { @override void mouseMove(double x, double y) { if (_newShape == null) { + super.mouseMove(x, y); return; } @@ -36,22 +39,25 @@ abstract class CreationState extends ManipulationState { } if (!_isDragged) { - _newShape!.move(_startX-50, _startY-50); + _newShape!.move(_startX - 50, _startY - 50); _newShape!.resize(100, 100); } - _isDragged = false; context.shapes.add(_newShape!); context.changeState( SelectionState( selectedShape: _newShape!, ), ); + + _isDragged = false; + _newShape = null; } @override void paint(Canvas canvas) { _newShape?.paint(canvas); + super.paint(canvas); } Shape createShape(double x, double y); diff --git a/patterns/state/manipulator_state/states/free_sate.dart b/patterns/state/manipulator_state/states/free_sate.dart index 0e20988..7a0b4c0 100644 --- a/patterns/state/manipulator_state/states/free_sate.dart +++ b/patterns/state/manipulator_state/states/free_sate.dart @@ -7,5 +7,3 @@ class FreeState extends ManipulationState with SpecificActionsMixin { trySelectShape(x, y); } } - - diff --git a/patterns/state/manipulator_state/states/selections/selection_state.dart b/patterns/state/manipulator_state/states/selections/selection_state.dart index a7616f0..bca8284 100644 --- a/patterns/state/manipulator_state/states/selections/selection_state.dart +++ b/patterns/state/manipulator_state/states/selections/selection_state.dart @@ -21,17 +21,18 @@ class SelectionState extends ManipulationState with SpecificActionsMixin { @override void paint(Canvas canvas) { + super.paint(canvas); canvas.drawRect( Rect.fromLTWH( - selectedShape.x-1, - selectedShape.y-1, - selectedShape.width+2, - selectedShape.height+2, + selectedShape.x - 1, + selectedShape.y - 1, + selectedShape.width + 2, + selectedShape.height + 2, ), Paint() ..color = Colors.cyanAccent ..style = PaintingStyle.stroke - ..strokeWidth = 2.0, + ..strokeWidth = 2.0, ); } } diff --git a/patterns/state/manipulator_state/states/specific_actions_mixin.dart b/patterns/state/manipulator_state/states/specific_actions_mixin.dart index 7fad5a5..a93caef 100644 --- a/patterns/state/manipulator_state/states/specific_actions_mixin.dart +++ b/patterns/state/manipulator_state/states/specific_actions_mixin.dart @@ -1,5 +1,8 @@ +import 'package:flutter/material.dart'; + import '../pattern/manipulator_context.dart'; import 'selections/selection_state.dart'; +import '../shapes/shape.dart'; mixin SpecificActionsMixin implements ManipulationState { bool trySelectShape(double x, double y) { @@ -15,12 +18,44 @@ mixin SpecificActionsMixin implements ManipulationState { } context.changeState( - SelectionState( - selectedShape: shape, - ), + shape.createSelectionState(), ); context.update(); return true; } + + @override + void mouseMove(double x, double y) { + final newHover = context.shapes.shapeFromCoordinate(x, y); + + if (newHover == _hoverShape) { + return; + } + + _hoverShape = newHover; + context.update(); + } + + Shape? _hoverShape; + + @override + void paint(Canvas canvas) { + if (_hoverShape == null) { + return; + } + + canvas.drawRect( + Rect.fromLTWH( + _hoverShape!.x - 1, + _hoverShape!.y - 1, + _hoverShape!.width + 2, + _hoverShape!.height + 2, + ), + Paint() + ..color = Colors.cyanAccent + ..style = PaintingStyle.stroke + ..strokeWidth = 1.0, + ); + } } diff --git a/patterns/state/manipulator_state/widgets/drawing_board.dart b/patterns/state/manipulator_state/widgets/drawing_board.dart index 6ad0efb..b36b8ab 100644 --- a/patterns/state/manipulator_state/widgets/drawing_board.dart +++ b/patterns/state/manipulator_state/widgets/drawing_board.dart @@ -15,6 +15,10 @@ class DrawingBoard extends StatelessWidget { e.localPosition.dx, e.localPosition.dy, ), + onPointerHover: (e) => app.manipulator.mouseMove( + e.localPosition.dx, + e.localPosition.dy, + ), onPointerMove: (e) => app.manipulator.mouseMove( e.localPosition.dx, e.localPosition.dy, @@ -27,12 +31,16 @@ class DrawingBoard extends StatelessWidget { event: app.shapes.onChange, builder: (_) { return EventListenableBuilder( - event: app.manipulator.onUpdate, - builder: (_) { - return CustomPaint( + event: app.manipulator.onUpdate, + builder: (_) { + return MouseRegion( + cursor: app.manipulator.cursor, + child: CustomPaint( painter: _Painter(app), - ); - }); + ), + ); + }, + ); }, ), ), diff --git a/patterns/state/manipulator_state/widgets/tool_bar.dart b/patterns/state/manipulator_state/widgets/tool_bar.dart index 10bfe2c..448716e 100644 --- a/patterns/state/manipulator_state/widgets/tool_bar.dart +++ b/patterns/state/manipulator_state/widgets/tool_bar.dart @@ -26,7 +26,8 @@ class ToolBar extends StatelessWidget { children: [ for (final tool in app.tools) ToolButton( - active: tool.state.runtimeType == app.manipulator.state.runtimeType, + active: tool.state.runtimeType == + app.manipulator.state.runtimeType, icon: Center(child: tool.icon), onTap: () { app.manipulator.changeState(tool.state); From ec59bed9abb7de62387f0676086b39f8181e620f Mon Sep 17 00:00:00 2001 From: ilopX Date: Tue, 24 May 2022 18:03:23 +0300 Subject: [PATCH 17/91] Add HoverStateMixin. --- .../states/creations/creation_state.dart | 3 +- .../manipulator_state/states/free_sate.dart | 4 +- .../states/hover_state_mixin.dart | 40 +++++++++++++++++++ .../states/selections/selection_state.dart | 4 +- .../states/specific_actions_mixin.dart | 37 ----------------- 5 files changed, 48 insertions(+), 40 deletions(-) create mode 100644 patterns/state/manipulator_state/states/hover_state_mixin.dart diff --git a/patterns/state/manipulator_state/states/creations/creation_state.dart b/patterns/state/manipulator_state/states/creations/creation_state.dart index 88d136f..092cc84 100644 --- a/patterns/state/manipulator_state/states/creations/creation_state.dart +++ b/patterns/state/manipulator_state/states/creations/creation_state.dart @@ -2,11 +2,12 @@ import 'dart:ui'; import '../../pattern/manipulator_context.dart'; import '../../shapes/shape.dart'; +import '../hover_state_mixin.dart'; import '../selections/selection_state.dart'; import '../specific_actions_mixin.dart'; abstract class CreationState extends ManipulationState - with SpecificActionsMixin { + with SpecificActionsMixin, HoverStateMixin { var _startX = 0.0; var _startY = 0.0; Shape? _newShape; diff --git a/patterns/state/manipulator_state/states/free_sate.dart b/patterns/state/manipulator_state/states/free_sate.dart index 7a0b4c0..ce4ca25 100644 --- a/patterns/state/manipulator_state/states/free_sate.dart +++ b/patterns/state/manipulator_state/states/free_sate.dart @@ -1,7 +1,9 @@ import '../pattern/manipulator_context.dart'; +import 'hover_state_mixin.dart'; import 'specific_actions_mixin.dart'; -class FreeState extends ManipulationState with SpecificActionsMixin { +class FreeState extends ManipulationState + with SpecificActionsMixin, HoverStateMixin { @override void mouseDown(double x, double y) { trySelectShape(x, y); diff --git a/patterns/state/manipulator_state/states/hover_state_mixin.dart b/patterns/state/manipulator_state/states/hover_state_mixin.dart new file mode 100644 index 0000000..2ed65fa --- /dev/null +++ b/patterns/state/manipulator_state/states/hover_state_mixin.dart @@ -0,0 +1,40 @@ +import 'package:flutter/material.dart'; + +import '../pattern/manipulator_context.dart'; +import '../shapes/shape.dart'; + +mixin HoverStateMixin implements ManipulationState { + @override + void mouseMove(double x, double y) { + final newHover = context.shapes.shapeFromCoordinate(x, y); + + if (newHover == _hoverShape) { + return; + } + + _hoverShape = newHover; + context.update(); + } + + Shape? _hoverShape; + + @override + void paint(Canvas canvas) { + if (_hoverShape == null) { + return; + } + + canvas.drawRect( + Rect.fromLTWH( + _hoverShape!.x - 1, + _hoverShape!.y - 1, + _hoverShape!.width + 2, + _hoverShape!.height + 2, + ), + Paint() + ..color = Colors.cyanAccent + ..style = PaintingStyle.stroke + ..strokeWidth = 1.0, + ); + } +} diff --git a/patterns/state/manipulator_state/states/selections/selection_state.dart b/patterns/state/manipulator_state/states/selections/selection_state.dart index bca8284..153c87b 100644 --- a/patterns/state/manipulator_state/states/selections/selection_state.dart +++ b/patterns/state/manipulator_state/states/selections/selection_state.dart @@ -3,9 +3,11 @@ import 'package:flutter/material.dart'; import '../../pattern/manipulator_context.dart'; import '../../shapes/shape.dart'; import '../free_sate.dart'; +import '../hover_state_mixin.dart'; import '../specific_actions_mixin.dart'; -class SelectionState extends ManipulationState with SpecificActionsMixin { +class SelectionState extends ManipulationState + with SpecificActionsMixin, HoverStateMixin { final Shape selectedShape; SelectionState({required this.selectedShape}); diff --git a/patterns/state/manipulator_state/states/specific_actions_mixin.dart b/patterns/state/manipulator_state/states/specific_actions_mixin.dart index a93caef..4026e75 100644 --- a/patterns/state/manipulator_state/states/specific_actions_mixin.dart +++ b/patterns/state/manipulator_state/states/specific_actions_mixin.dart @@ -1,8 +1,5 @@ -import 'package:flutter/material.dart'; - import '../pattern/manipulator_context.dart'; import 'selections/selection_state.dart'; -import '../shapes/shape.dart'; mixin SpecificActionsMixin implements ManipulationState { bool trySelectShape(double x, double y) { @@ -24,38 +21,4 @@ mixin SpecificActionsMixin implements ManipulationState { context.update(); return true; } - - @override - void mouseMove(double x, double y) { - final newHover = context.shapes.shapeFromCoordinate(x, y); - - if (newHover == _hoverShape) { - return; - } - - _hoverShape = newHover; - context.update(); - } - - Shape? _hoverShape; - - @override - void paint(Canvas canvas) { - if (_hoverShape == null) { - return; - } - - canvas.drawRect( - Rect.fromLTWH( - _hoverShape!.x - 1, - _hoverShape!.y - 1, - _hoverShape!.width + 2, - _hoverShape!.height + 2, - ), - Paint() - ..color = Colors.cyanAccent - ..style = PaintingStyle.stroke - ..strokeWidth = 1.0, - ); - } } From 23ac8cdb46a1d1febb07217fcd6060b29cd7c69d Mon Sep 17 00:00:00 2001 From: ilopX Date: Tue, 24 May 2022 18:05:41 +0300 Subject: [PATCH 18/91] Move states mixin to separate directory. --- .../manipulator_state/states/creations/creation_state.dart | 4 ++-- patterns/state/manipulator_state/states/free_sate.dart | 4 ++-- .../states/{ => mixins}/hover_state_mixin.dart | 4 ++-- .../states/{ => mixins}/specific_actions_mixin.dart | 4 ++-- .../manipulator_state/states/selections/selection_state.dart | 4 ++-- 5 files changed, 10 insertions(+), 10 deletions(-) rename patterns/state/manipulator_state/states/{ => mixins}/hover_state_mixin.dart (89%) rename patterns/state/manipulator_state/states/{ => mixins}/specific_actions_mixin.dart (83%) diff --git a/patterns/state/manipulator_state/states/creations/creation_state.dart b/patterns/state/manipulator_state/states/creations/creation_state.dart index 092cc84..272905f 100644 --- a/patterns/state/manipulator_state/states/creations/creation_state.dart +++ b/patterns/state/manipulator_state/states/creations/creation_state.dart @@ -2,9 +2,9 @@ import 'dart:ui'; import '../../pattern/manipulator_context.dart'; import '../../shapes/shape.dart'; -import '../hover_state_mixin.dart'; +import '../mixins/hover_state_mixin.dart'; import '../selections/selection_state.dart'; -import '../specific_actions_mixin.dart'; +import '../mixins/specific_actions_mixin.dart'; abstract class CreationState extends ManipulationState with SpecificActionsMixin, HoverStateMixin { diff --git a/patterns/state/manipulator_state/states/free_sate.dart b/patterns/state/manipulator_state/states/free_sate.dart index ce4ca25..ce88e46 100644 --- a/patterns/state/manipulator_state/states/free_sate.dart +++ b/patterns/state/manipulator_state/states/free_sate.dart @@ -1,6 +1,6 @@ import '../pattern/manipulator_context.dart'; -import 'hover_state_mixin.dart'; -import 'specific_actions_mixin.dart'; +import 'mixins/hover_state_mixin.dart'; +import 'mixins/specific_actions_mixin.dart'; class FreeState extends ManipulationState with SpecificActionsMixin, HoverStateMixin { diff --git a/patterns/state/manipulator_state/states/hover_state_mixin.dart b/patterns/state/manipulator_state/states/mixins/hover_state_mixin.dart similarity index 89% rename from patterns/state/manipulator_state/states/hover_state_mixin.dart rename to patterns/state/manipulator_state/states/mixins/hover_state_mixin.dart index 2ed65fa..55d3697 100644 --- a/patterns/state/manipulator_state/states/hover_state_mixin.dart +++ b/patterns/state/manipulator_state/states/mixins/hover_state_mixin.dart @@ -1,7 +1,7 @@ import 'package:flutter/material.dart'; -import '../pattern/manipulator_context.dart'; -import '../shapes/shape.dart'; +import '../../pattern/manipulator_context.dart'; +import '../../shapes/shape.dart'; mixin HoverStateMixin implements ManipulationState { @override diff --git a/patterns/state/manipulator_state/states/specific_actions_mixin.dart b/patterns/state/manipulator_state/states/mixins/specific_actions_mixin.dart similarity index 83% rename from patterns/state/manipulator_state/states/specific_actions_mixin.dart rename to patterns/state/manipulator_state/states/mixins/specific_actions_mixin.dart index 4026e75..38a1504 100644 --- a/patterns/state/manipulator_state/states/specific_actions_mixin.dart +++ b/patterns/state/manipulator_state/states/mixins/specific_actions_mixin.dart @@ -1,5 +1,5 @@ -import '../pattern/manipulator_context.dart'; -import 'selections/selection_state.dart'; +import '../../pattern/manipulator_context.dart'; +import '../selections/selection_state.dart'; mixin SpecificActionsMixin implements ManipulationState { bool trySelectShape(double x, double y) { diff --git a/patterns/state/manipulator_state/states/selections/selection_state.dart b/patterns/state/manipulator_state/states/selections/selection_state.dart index 153c87b..87783a6 100644 --- a/patterns/state/manipulator_state/states/selections/selection_state.dart +++ b/patterns/state/manipulator_state/states/selections/selection_state.dart @@ -3,8 +3,8 @@ import 'package:flutter/material.dart'; import '../../pattern/manipulator_context.dart'; import '../../shapes/shape.dart'; import '../free_sate.dart'; -import '../hover_state_mixin.dart'; -import '../specific_actions_mixin.dart'; +import '../mixins/hover_state_mixin.dart'; +import '../mixins/specific_actions_mixin.dart'; class SelectionState extends ManipulationState with SpecificActionsMixin, HoverStateMixin { From edf5506576dff0affd9c6eeabfc31c66b55778cb Mon Sep 17 00:00:00 2001 From: ilopX Date: Wed, 25 May 2022 00:21:56 +0300 Subject: [PATCH 19/91] Add ResizableState. *Add RectangleShape --- .../widgets/independent/panel.dart | 12 +-- .../state/manipulator_state/app/shapes.dart | 2 +- patterns/state/manipulator_state/main.dart | 2 + .../pattern/manipulator_context.dart | 5 ++ .../shapes/rectangle_shape.dart | 12 +++ .../creations/circle_creation_state.dart | 5 ++ .../states/creations/creation_state.dart | 36 ++++----- .../creations/rectangle_creation_state.dart | 9 ++- .../states/creations/text_creation_state.dart | 5 ++ .../manipulator_state/states/free_sate.dart | 7 +- .../states/mixins/hover_state_mixin.dart | 23 ++++-- .../states/mixins/specific_actions_mixin.dart | 21 ++--- .../states/selections/moving_state.dart | 31 ++++++++ .../states/selections/resizable_state.dart | 76 +++++++++++++++++++ .../states/selections/selection_state.dart | 12 +-- .../widgets/current_state.dart | 45 +++++++++++ .../widgets/drawing_board.dart | 1 - 17 files changed, 255 insertions(+), 49 deletions(-) create mode 100644 patterns/state/manipulator_state/shapes/rectangle_shape.dart create mode 100644 patterns/state/manipulator_state/states/selections/moving_state.dart create mode 100644 patterns/state/manipulator_state/states/selections/resizable_state.dart create mode 100644 patterns/state/manipulator_state/widgets/current_state.dart diff --git a/patterns/abstract_factory/tool_panel_factory/widgets/independent/panel.dart b/patterns/abstract_factory/tool_panel_factory/widgets/independent/panel.dart index 6dd4670..c123fa8 100644 --- a/patterns/abstract_factory/tool_panel_factory/widgets/independent/panel.dart +++ b/patterns/abstract_factory/tool_panel_factory/widgets/independent/panel.dart @@ -7,12 +7,12 @@ class Panel extends StatelessWidget { final Axis direction; final Widget child; - const Panel( - {Key? key, - required this.direction, - required this.child, - this.thicknessHeight = 48.0}) - : super(key: key); + const Panel({ + Key? key, + required this.direction, + required this.child, + this.thicknessHeight = 48.0, + }) : super(key: key); @override Widget build(BuildContext context) { diff --git a/patterns/state/manipulator_state/app/shapes.dart b/patterns/state/manipulator_state/app/shapes.dart index 67701b9..a72546f 100644 --- a/patterns/state/manipulator_state/app/shapes.dart +++ b/patterns/state/manipulator_state/app/shapes.dart @@ -18,7 +18,7 @@ class Shapes with IterableMixin { final onChange = Event(); - Shape? shapeFromCoordinate(x, y) { + Shape? findShapeByCoordinates(x, y) { for (final shape in _shapes) { final shapeRect = Rect.fromLTWH( shape.x, diff --git a/patterns/state/manipulator_state/main.dart b/patterns/state/manipulator_state/main.dart index 728c8d5..7111d4c 100644 --- a/patterns/state/manipulator_state/main.dart +++ b/patterns/state/manipulator_state/main.dart @@ -9,6 +9,7 @@ import 'states/creations/circle_creation_state.dart'; import 'states/creations/rectangle_creation_state.dart'; import 'states/creations/text_creation_state.dart'; import 'states/free_sate.dart'; +import 'widgets/current_state.dart'; import 'widgets/drawing_board.dart'; import 'widgets/tool_bar.dart'; @@ -61,6 +62,7 @@ class _ManipulatorStateAppState extends State { children: [ DrawingBoard(app: app), ToolBar(app: app), + CurrentState(manipulator: app.manipulator), ], ), ), diff --git a/patterns/state/manipulator_state/pattern/manipulator_context.dart b/patterns/state/manipulator_state/pattern/manipulator_context.dart index d5bda00..021845a 100644 --- a/patterns/state/manipulator_state/pattern/manipulator_context.dart +++ b/patterns/state/manipulator_state/pattern/manipulator_context.dart @@ -38,6 +38,11 @@ class ManipulatorContext { onUpdate._emit(); } + @override + String toString() { + return _state.toString(); + } + void mouseMove(double x, double y) { _state.mouseMove(x, y); } diff --git a/patterns/state/manipulator_state/shapes/rectangle_shape.dart b/patterns/state/manipulator_state/shapes/rectangle_shape.dart new file mode 100644 index 0000000..648d0d2 --- /dev/null +++ b/patterns/state/manipulator_state/shapes/rectangle_shape.dart @@ -0,0 +1,12 @@ +import '../states/selections/resizable_state.dart'; +import '../states/selections/selection_state.dart'; +import 'base_shape.dart'; + +class RectangleShape extends BaseShape { + RectangleShape(super.x, super.y, super.width, super.height); + + @override + SelectionState createSelectionState() { + return ResizableState(selectedShape: this); + } +} diff --git a/patterns/state/manipulator_state/states/creations/circle_creation_state.dart b/patterns/state/manipulator_state/states/creations/circle_creation_state.dart index c24e0cd..427218d 100644 --- a/patterns/state/manipulator_state/states/creations/circle_creation_state.dart +++ b/patterns/state/manipulator_state/states/creations/circle_creation_state.dart @@ -7,4 +7,9 @@ class CircleCreationState extends CreationState { Shape createShape(double x, double y) { return BaseShape(x, y, 100, 100); } + + @override + String toString() { + return 'Circle Creation State'; + } } diff --git a/patterns/state/manipulator_state/states/creations/creation_state.dart b/patterns/state/manipulator_state/states/creations/creation_state.dart index 272905f..f43c4dd 100644 --- a/patterns/state/manipulator_state/states/creations/creation_state.dart +++ b/patterns/state/manipulator_state/states/creations/creation_state.dart @@ -3,28 +3,21 @@ import 'dart:ui'; import '../../pattern/manipulator_context.dart'; import '../../shapes/shape.dart'; import '../mixins/hover_state_mixin.dart'; -import '../selections/selection_state.dart'; import '../mixins/specific_actions_mixin.dart'; abstract class CreationState extends ManipulationState with SpecificActionsMixin, HoverStateMixin { - var _startX = 0.0; - var _startY = 0.0; - Shape? _newShape; - var _isDragged = false; + Shape createShape(double x, double y); @override - bool mouseDown(double x, double y) { - _startX = x; - _startY = y; - _newShape = createShape(x, y); - return true; + void mouseDown(double x, double y) { + _startCreatingShape(x, y); } @override void mouseMove(double x, double y) { - if (_newShape == null) { - super.mouseMove(x, y); + if (_isCreatingNotStart) { + super.mouseMove(x, y); // HoverStateMixin return; } @@ -35,7 +28,7 @@ abstract class CreationState extends ManipulationState @override void mouseUp() { - if (_newShape == null) { + if (_isCreatingNotStart) { return; } @@ -46,9 +39,7 @@ abstract class CreationState extends ManipulationState context.shapes.add(_newShape!); context.changeState( - SelectionState( - selectedShape: _newShape!, - ), + _newShape!.createSelectionState(), ); _isDragged = false; @@ -61,5 +52,16 @@ abstract class CreationState extends ManipulationState super.paint(canvas); } - Shape createShape(double x, double y); + var _startX = 0.0; + var _startY = 0.0; + Shape? _newShape; + var _isDragged = false; + + void _startCreatingShape(double x, double y) { + _startX = x; + _startY = y; + _newShape = createShape(x, y); + } + + bool get _isCreatingNotStart => _newShape == null; } diff --git a/patterns/state/manipulator_state/states/creations/rectangle_creation_state.dart b/patterns/state/manipulator_state/states/creations/rectangle_creation_state.dart index d9fbbb7..75967fd 100644 --- a/patterns/state/manipulator_state/states/creations/rectangle_creation_state.dart +++ b/patterns/state/manipulator_state/states/creations/rectangle_creation_state.dart @@ -1,10 +1,15 @@ -import '../../shapes/base_shape.dart'; +import '../../shapes/rectangle_shape.dart'; import '../../shapes/shape.dart'; import 'creation_state.dart'; class RectangleCreationState extends CreationState { @override Shape createShape(double x, double y) { - return BaseShape(x, y, 0, 0); + return RectangleShape(x, y, 0, 0); + } + + @override + String toString() { + return 'Rectangle Creation State'; } } diff --git a/patterns/state/manipulator_state/states/creations/text_creation_state.dart b/patterns/state/manipulator_state/states/creations/text_creation_state.dart index 462a0b8..0befbff 100644 --- a/patterns/state/manipulator_state/states/creations/text_creation_state.dart +++ b/patterns/state/manipulator_state/states/creations/text_creation_state.dart @@ -7,4 +7,9 @@ class TextCreationState extends CreationState { Shape createShape(double x, double y) { return BaseShape(x, y, 100, 100); } + + @override + String toString() { + return 'Text Creation State'; + } } diff --git a/patterns/state/manipulator_state/states/free_sate.dart b/patterns/state/manipulator_state/states/free_sate.dart index ce88e46..0f7fad0 100644 --- a/patterns/state/manipulator_state/states/free_sate.dart +++ b/patterns/state/manipulator_state/states/free_sate.dart @@ -6,6 +6,11 @@ class FreeState extends ManipulationState with SpecificActionsMixin, HoverStateMixin { @override void mouseDown(double x, double y) { - trySelectShape(x, y); + trySelectAndStartMovingShape(x, y); + } + + @override + String toString() { + return 'Free State'; } } diff --git a/patterns/state/manipulator_state/states/mixins/hover_state_mixin.dart b/patterns/state/manipulator_state/states/mixins/hover_state_mixin.dart index 55d3697..0cc8b2a 100644 --- a/patterns/state/manipulator_state/states/mixins/hover_state_mixin.dart +++ b/patterns/state/manipulator_state/states/mixins/hover_state_mixin.dart @@ -6,16 +6,27 @@ import '../../shapes/shape.dart'; mixin HoverStateMixin implements ManipulationState { @override void mouseMove(double x, double y) { - final newHover = context.shapes.shapeFromCoordinate(x, y); + final newHover = context.shapes.findShapeByCoordinates(x, y); if (newHover == _hoverShape) { return; } _hoverShape = newHover; + + if (newHover == null) { + onMouseLeave(); + } else { + onHover(); + } + context.update(); } + void onHover(){} + + void onMouseLeave(){} + Shape? _hoverShape; @override @@ -26,15 +37,15 @@ mixin HoverStateMixin implements ManipulationState { canvas.drawRect( Rect.fromLTWH( - _hoverShape!.x - 1, - _hoverShape!.y - 1, - _hoverShape!.width + 2, - _hoverShape!.height + 2, + _hoverShape!.x+2, + _hoverShape!.y+2, + _hoverShape!.width-4, + _hoverShape!.height-4, ), Paint() ..color = Colors.cyanAccent ..style = PaintingStyle.stroke - ..strokeWidth = 1.0, + ..strokeWidth = 4.0, ); } } diff --git a/patterns/state/manipulator_state/states/mixins/specific_actions_mixin.dart b/patterns/state/manipulator_state/states/mixins/specific_actions_mixin.dart index 38a1504..963de7e 100644 --- a/patterns/state/manipulator_state/states/mixins/specific_actions_mixin.dart +++ b/patterns/state/manipulator_state/states/mixins/specific_actions_mixin.dart @@ -1,24 +1,27 @@ import '../../pattern/manipulator_context.dart'; -import '../selections/selection_state.dart'; +import '../selections/moving_state.dart'; mixin SpecificActionsMixin implements ManipulationState { - bool trySelectShape(double x, double y) { - final shape = context.shapes.shapeFromCoordinate(x, y); + bool trySelectAndStartMovingShape(double x, double y) { + final shape = context.shapes.findShapeByCoordinates(x, y); if (shape == null) { return false; } - if (context.state is SelectionState && - (context.state as SelectionState).selectedShape == shape) { - return true; - } + // if (context.state is SelectionState && + // (context.state as SelectionState).selectedShape == shape) { + // return true; + // } context.changeState( - shape.createSelectionState(), + MovingState( + startX: x, + startY: y, + selectedShape: shape, + ), ); - context.update(); return true; } } diff --git a/patterns/state/manipulator_state/states/selections/moving_state.dart b/patterns/state/manipulator_state/states/selections/moving_state.dart new file mode 100644 index 0000000..f13a8a2 --- /dev/null +++ b/patterns/state/manipulator_state/states/selections/moving_state.dart @@ -0,0 +1,31 @@ +import 'selection_state.dart'; + +class MovingState extends SelectionState { + final double startX; + final double startY; + + MovingState({ + required double startX, + required double startY, + required super.selectedShape, + }) : startX = startX - selectedShape.x, + startY = startY - selectedShape.y; + + @override + void mouseMove(double x, double y) { + selectedShape.move(x - startX, y - startY); + context.update(); + } + + @override + void mouseUp() { + context.changeState( + selectedShape.createSelectionState(), + ); + } + + @override + String toString() { + return 'Selection State + Moving State'; + } +} diff --git a/patterns/state/manipulator_state/states/selections/resizable_state.dart b/patterns/state/manipulator_state/states/selections/resizable_state.dart new file mode 100644 index 0000000..e30418e --- /dev/null +++ b/patterns/state/manipulator_state/states/selections/resizable_state.dart @@ -0,0 +1,76 @@ +import 'package:flutter/cupertino.dart'; +import 'package:flutter/material.dart'; + +import 'selection_state.dart'; + +class ResizableState extends SelectionState { + ResizableState({required super.selectedShape}); + + @override + void mouseMove(double x, double y) { + super.mouseMove(x, y); + + final rect1 = Rect.fromLTWH( + selectedShape.x - 5, + selectedShape.y - 5, + 10, + 10, + ); + if (rect1.contains(Offset(x, y))) { + context.cursor = SystemMouseCursors.resizeUpLeft; + context.update(); + return; + } + + final rect2 = Rect.fromLTWH( + selectedShape.x + selectedShape.width - 5, + selectedShape.y - 5, + 10, + 10, + ); + if (rect2.contains(Offset(x, y))) { + context.cursor = SystemMouseCursors.resizeUpRight; + context.update(); + return; + } + + context.cursor = SystemMouseCursors.basic; + context.update(); + } + + @override + void paint(Canvas canvas) { + super.paint(canvas); + final xPlusWidth = selectedShape.x + selectedShape.width; + final yPlusHeight = selectedShape.y + selectedShape.height; + + final point1 = Offset(selectedShape.x, selectedShape.y); + final point2 = Offset(xPlusWidth, selectedShape.y); + final point3 = Offset(xPlusWidth, yPlusHeight); + final point4 = Offset(selectedShape.x, yPlusHeight); + + final paint1 = Paint() + ..style = PaintingStyle.fill + ..color = Colors.black; + const radius = 5.0; + canvas.drawCircle(point1, radius, paint1); + canvas.drawCircle(point2, radius, paint1); + canvas.drawCircle(point3, radius, paint1); + canvas.drawCircle(point4, radius, paint1); + + final paint2 = Paint() + ..style = PaintingStyle.stroke + ..strokeWidth = 1.5 + ..color = Colors.cyanAccent; + + canvas.drawCircle(point1, radius, paint2); + canvas.drawCircle(point2, radius, paint2); + canvas.drawCircle(point3, radius, paint2); + canvas.drawCircle(point4, radius, paint2); + } + + @override + String toString() { + return 'Selection State + Resizable State'; + } +} diff --git a/patterns/state/manipulator_state/states/selections/selection_state.dart b/patterns/state/manipulator_state/states/selections/selection_state.dart index 87783a6..fd18bfe 100644 --- a/patterns/state/manipulator_state/states/selections/selection_state.dart +++ b/patterns/state/manipulator_state/states/selections/selection_state.dart @@ -14,9 +14,9 @@ class SelectionState extends ManipulationState @override void mouseDown(double x, double y) { - final isNotShapeSelected = !trySelectShape(x, y); + final isShapeNotSelected = !trySelectAndStartMovingShape(x, y); - if (isNotShapeSelected) { + if (isShapeNotSelected) { context.changeState(FreeState()); } } @@ -26,10 +26,10 @@ class SelectionState extends ManipulationState super.paint(canvas); canvas.drawRect( Rect.fromLTWH( - selectedShape.x - 1, - selectedShape.y - 1, - selectedShape.width + 2, - selectedShape.height + 2, + selectedShape.x+1, + selectedShape.y+1, + selectedShape.width-2, + selectedShape.height-2, ), Paint() ..color = Colors.cyanAccent diff --git a/patterns/state/manipulator_state/widgets/current_state.dart b/patterns/state/manipulator_state/widgets/current_state.dart new file mode 100644 index 0000000..03ed29f --- /dev/null +++ b/patterns/state/manipulator_state/widgets/current_state.dart @@ -0,0 +1,45 @@ +import 'package:flutter/material.dart'; + +import '../../../abstract_factory/tool_panel_factory/widgets/independent/event_listenable_builder.dart'; +import '../../../abstract_factory/tool_panel_factory/widgets/independent/panel.dart'; +import '../pattern/manipulator_context.dart'; + +class CurrentState extends StatelessWidget { + final ManipulatorContext manipulator; + + const CurrentState({ + Key? key, + required this.manipulator, + }) : super(key: key); + + @override + Widget build(BuildContext context) { + return Positioned( + top: 12, + left: 300, + child: Panel( + thicknessHeight: 64, + direction: Axis.horizontal, + child: Padding( + padding: EdgeInsets.symmetric(horizontal: 16), + child: Center( + child: EventListenableBuilder( + event: manipulator.onStateChange, + builder: (context) { + return EventListenableBuilder( + event: manipulator.onUpdate, + builder: (context) { + return Text( + manipulator.toString(), + style: TextStyle(color: Colors.white, fontSize: 16), + ); + } + ); + } + ), + ), + ), + ), + ); + } +} diff --git a/patterns/state/manipulator_state/widgets/drawing_board.dart b/patterns/state/manipulator_state/widgets/drawing_board.dart index b36b8ab..f0a37b0 100644 --- a/patterns/state/manipulator_state/widgets/drawing_board.dart +++ b/patterns/state/manipulator_state/widgets/drawing_board.dart @@ -55,7 +55,6 @@ class _Painter extends CustomPainter { @override void paint(Canvas canvas, Size size) { - canvas.translate(0.5, 0.5); for (final shape in app.shapes) { shape.paint(canvas); } From 13294bf094787d26f6c920506ccc82bfb0ac76ab Mon Sep 17 00:00:00 2001 From: ilopX Date: Wed, 25 May 2022 01:43:02 +0300 Subject: [PATCH 20/91] Add CircleShape. --- .../shapes/circle_shape.dart | 38 +++++++++++++++++++ .../creations/circle_creation_state.dart | 4 +- .../states/mixins/hover_state_mixin.dart | 12 +++--- .../states/mixins/specific_actions_mixin.dart | 5 --- .../selections/circle_inner_radius_state.dart | 23 +++++++++++ .../states/selections/resizable_state.dart | 1 - .../states/selections/selection_state.dart | 8 ++-- .../widgets/current_state.dart | 24 ++++++------ 8 files changed, 84 insertions(+), 31 deletions(-) create mode 100644 patterns/state/manipulator_state/shapes/circle_shape.dart create mode 100644 patterns/state/manipulator_state/states/selections/circle_inner_radius_state.dart diff --git a/patterns/state/manipulator_state/shapes/circle_shape.dart b/patterns/state/manipulator_state/shapes/circle_shape.dart new file mode 100644 index 0000000..d8a1d9a --- /dev/null +++ b/patterns/state/manipulator_state/shapes/circle_shape.dart @@ -0,0 +1,38 @@ +import 'package:flutter/material.dart'; + +import '../states/selections/circle_inner_radius_state.dart'; +import '../states/selections/selection_state.dart'; +import 'base_shape.dart'; + +class CircleShape extends BaseShape { + CircleShape(super.x, super.y, super.width, super.height); + + @override + SelectionState createSelectionState() { + return CircleInnerRadiusState(selectedShape: this); + } + + @override + void paint(Canvas canvas) { + final w = width / 2; + final h = height / 2; + final path = Path() + ..fillType = PathFillType.evenOdd + ..addOval(Rect.fromLTWH( + x, + y, + width, + height, + )) + ..addOval(Rect.fromLTWH( + x + w / 2, + y + h / 2, + w, + h, + )); + canvas.drawPath( + path, + Paint()..color = Colors.white, + ); + } +} diff --git a/patterns/state/manipulator_state/states/creations/circle_creation_state.dart b/patterns/state/manipulator_state/states/creations/circle_creation_state.dart index 427218d..2d7b55d 100644 --- a/patterns/state/manipulator_state/states/creations/circle_creation_state.dart +++ b/patterns/state/manipulator_state/states/creations/circle_creation_state.dart @@ -1,11 +1,11 @@ -import '../../shapes/base_shape.dart'; +import '../../shapes/circle_shape.dart'; import '../../shapes/shape.dart'; import 'creation_state.dart'; class CircleCreationState extends CreationState { @override Shape createShape(double x, double y) { - return BaseShape(x, y, 100, 100); + return CircleShape(x, y, 100, 100); } @override diff --git a/patterns/state/manipulator_state/states/mixins/hover_state_mixin.dart b/patterns/state/manipulator_state/states/mixins/hover_state_mixin.dart index 0cc8b2a..8832088 100644 --- a/patterns/state/manipulator_state/states/mixins/hover_state_mixin.dart +++ b/patterns/state/manipulator_state/states/mixins/hover_state_mixin.dart @@ -23,9 +23,9 @@ mixin HoverStateMixin implements ManipulationState { context.update(); } - void onHover(){} + void onHover() {} - void onMouseLeave(){} + void onMouseLeave() {} Shape? _hoverShape; @@ -37,10 +37,10 @@ mixin HoverStateMixin implements ManipulationState { canvas.drawRect( Rect.fromLTWH( - _hoverShape!.x+2, - _hoverShape!.y+2, - _hoverShape!.width-4, - _hoverShape!.height-4, + _hoverShape!.x + 2, + _hoverShape!.y + 2, + _hoverShape!.width - 4, + _hoverShape!.height - 4, ), Paint() ..color = Colors.cyanAccent diff --git a/patterns/state/manipulator_state/states/mixins/specific_actions_mixin.dart b/patterns/state/manipulator_state/states/mixins/specific_actions_mixin.dart index 963de7e..aa55eb5 100644 --- a/patterns/state/manipulator_state/states/mixins/specific_actions_mixin.dart +++ b/patterns/state/manipulator_state/states/mixins/specific_actions_mixin.dart @@ -9,11 +9,6 @@ mixin SpecificActionsMixin implements ManipulationState { return false; } - // if (context.state is SelectionState && - // (context.state as SelectionState).selectedShape == shape) { - // return true; - // } - context.changeState( MovingState( startX: x, diff --git a/patterns/state/manipulator_state/states/selections/circle_inner_radius_state.dart b/patterns/state/manipulator_state/states/selections/circle_inner_radius_state.dart new file mode 100644 index 0000000..873f2cd --- /dev/null +++ b/patterns/state/manipulator_state/states/selections/circle_inner_radius_state.dart @@ -0,0 +1,23 @@ +import 'package:flutter/cupertino.dart'; +import 'package:flutter/material.dart'; + +import 'resizable_state.dart'; + +class CircleInnerRadiusState extends ResizableState { + CircleInnerRadiusState({required super.selectedShape}); + + @override + void mouseMove(double x, double y) { + super.mouseMove(x, y); + } + + @override + void paint(Canvas canvas) { + super.paint(canvas); + } + + @override + String toString() { + return 'Selection State + Resizable State + Circle Inner Radius State'; + } +} diff --git a/patterns/state/manipulator_state/states/selections/resizable_state.dart b/patterns/state/manipulator_state/states/selections/resizable_state.dart index e30418e..c113d17 100644 --- a/patterns/state/manipulator_state/states/selections/resizable_state.dart +++ b/patterns/state/manipulator_state/states/selections/resizable_state.dart @@ -1,4 +1,3 @@ -import 'package:flutter/cupertino.dart'; import 'package:flutter/material.dart'; import 'selection_state.dart'; diff --git a/patterns/state/manipulator_state/states/selections/selection_state.dart b/patterns/state/manipulator_state/states/selections/selection_state.dart index fd18bfe..6bf7108 100644 --- a/patterns/state/manipulator_state/states/selections/selection_state.dart +++ b/patterns/state/manipulator_state/states/selections/selection_state.dart @@ -26,10 +26,10 @@ class SelectionState extends ManipulationState super.paint(canvas); canvas.drawRect( Rect.fromLTWH( - selectedShape.x+1, - selectedShape.y+1, - selectedShape.width-2, - selectedShape.height-2, + selectedShape.x + 1, + selectedShape.y + 1, + selectedShape.width - 2, + selectedShape.height - 2, ), Paint() ..color = Colors.cyanAccent diff --git a/patterns/state/manipulator_state/widgets/current_state.dart b/patterns/state/manipulator_state/widgets/current_state.dart index 03ed29f..1a8d6b2 100644 --- a/patterns/state/manipulator_state/widgets/current_state.dart +++ b/patterns/state/manipulator_state/widgets/current_state.dart @@ -24,19 +24,17 @@ class CurrentState extends StatelessWidget { padding: EdgeInsets.symmetric(horizontal: 16), child: Center( child: EventListenableBuilder( - event: manipulator.onStateChange, - builder: (context) { - return EventListenableBuilder( - event: manipulator.onUpdate, - builder: (context) { - return Text( - manipulator.toString(), - style: TextStyle(color: Colors.white, fontSize: 16), - ); - } - ); - } - ), + event: manipulator.onStateChange, + builder: (context) { + return EventListenableBuilder( + event: manipulator.onUpdate, + builder: (context) { + return Text( + manipulator.toString(), + style: TextStyle(color: Colors.white, fontSize: 16), + ); + }); + }), ), ), ), From dcbad123488c041ab4fcc4e7532aa1304f73f438 Mon Sep 17 00:00:00 2001 From: ilopX Date: Wed, 25 May 2022 01:57:50 +0300 Subject: [PATCH 21/91] Render Circle manipulation state. --- .../pattern/manipulator_context.dart | 4 +-- .../selections/circle_inner_radius_state.dart | 30 +++++++++++++++++++ 2 files changed, 32 insertions(+), 2 deletions(-) diff --git a/patterns/state/manipulator_state/pattern/manipulator_context.dart b/patterns/state/manipulator_state/pattern/manipulator_context.dart index 021845a..89f7ee4 100644 --- a/patterns/state/manipulator_state/pattern/manipulator_context.dart +++ b/patterns/state/manipulator_state/pattern/manipulator_context.dart @@ -8,8 +8,6 @@ part 'manipulation_state.dart'; class ManipulatorContext { final Shapes shapes; - ManipulationState _state; - ManipulatorContext({ required this.shapes, required ManipulationState initState, @@ -17,6 +15,8 @@ class ManipulatorContext { _state._context = this; } + ManipulationState _state; + ManipulationState get state => _state; void changeState(ManipulationState newState) { diff --git a/patterns/state/manipulator_state/states/selections/circle_inner_radius_state.dart b/patterns/state/manipulator_state/states/selections/circle_inner_radius_state.dart index 873f2cd..0b6245e 100644 --- a/patterns/state/manipulator_state/states/selections/circle_inner_radius_state.dart +++ b/patterns/state/manipulator_state/states/selections/circle_inner_radius_state.dart @@ -14,6 +14,36 @@ class CircleInnerRadiusState extends ResizableState { @override void paint(Canvas canvas) { super.paint(canvas); + canvas.save(); + canvas.translate(selectedShape.x, selectedShape.y); + + final p1 = Offset(selectedShape.width / 4 * 3, selectedShape.height / 2); + canvas.drawLine( + p1, + Offset(selectedShape.width, selectedShape.height / 2), + Paint() + ..color = Colors.cyanAccent + ..strokeWidth = 2, + ); + + canvas.drawCircle( + p1, + 5, + Paint() + + ..color = Colors.black + ..style = PaintingStyle.fill, + ); + canvas.drawCircle( + p1, + 5, + Paint() + ..strokeWidth = 2 + ..color = Colors.cyanAccent + ..style = PaintingStyle.stroke, + ); + + canvas.restore(); } @override From 3344d3dcd7306d4a7d3056d22474e3129aa2fbda Mon Sep 17 00:00:00 2001 From: ilopX Date: Wed, 25 May 2022 12:50:44 +0300 Subject: [PATCH 22/91] Rename ManipulatorContext to ManipulationContext. --- patterns/state/manipulator_state/app/app.dart | 4 ++-- patterns/state/manipulator_state/app/tool.dart | 2 +- patterns/state/manipulator_state/main.dart | 4 ++-- .../{manipulator_context.dart => manipulation_context.dart} | 4 ++-- .../state/manipulator_state/pattern/manipulation_state.dart | 4 ++-- .../manipulator_state/states/creations/creation_state.dart | 2 +- patterns/state/manipulator_state/states/free_sate.dart | 2 +- .../manipulator_state/states/mixins/hover_state_mixin.dart | 2 +- .../states/mixins/specific_actions_mixin.dart | 2 +- .../manipulator_state/states/selections/selection_state.dart | 2 +- patterns/state/manipulator_state/widgets/current_state.dart | 4 ++-- 11 files changed, 16 insertions(+), 16 deletions(-) rename patterns/state/manipulator_state/pattern/{manipulator_context.dart => manipulation_context.dart} (95%) diff --git a/patterns/state/manipulator_state/app/app.dart b/patterns/state/manipulator_state/app/app.dart index e1ef653..e30cab2 100644 --- a/patterns/state/manipulator_state/app/app.dart +++ b/patterns/state/manipulator_state/app/app.dart @@ -1,10 +1,10 @@ -import '../pattern/manipulator_context.dart'; +import '../pattern/manipulation_context.dart'; import 'shapes.dart'; import 'tool.dart'; class App { final Shapes shapes; - final ManipulatorContext manipulator; + final ManipulationContext manipulator; final List tools; App({ diff --git a/patterns/state/manipulator_state/app/tool.dart b/patterns/state/manipulator_state/app/tool.dart index 8ac8fac..4ff38a2 100644 --- a/patterns/state/manipulator_state/app/tool.dart +++ b/patterns/state/manipulator_state/app/tool.dart @@ -1,6 +1,6 @@ import 'package:flutter/widgets.dart'; -import '../pattern/manipulator_context.dart'; +import '../pattern/manipulation_context.dart'; class Tool { final Icon icon; diff --git a/patterns/state/manipulator_state/main.dart b/patterns/state/manipulator_state/main.dart index 7111d4c..6abc22b 100644 --- a/patterns/state/manipulator_state/main.dart +++ b/patterns/state/manipulator_state/main.dart @@ -4,7 +4,7 @@ import 'package:material_design_icons_flutter/material_design_icons_flutter.dart import 'app/app.dart'; import 'app/shapes.dart'; import 'app/tool.dart'; -import 'pattern/manipulator_context.dart'; +import 'pattern/manipulation_context.dart'; import 'states/creations/circle_creation_state.dart'; import 'states/creations/rectangle_creation_state.dart'; import 'states/creations/text_creation_state.dart'; @@ -28,7 +28,7 @@ class _ManipulatorStateAppState extends State { final shapes = Shapes(); app = App( shapes: shapes, - manipulator: ManipulatorContext( + manipulator: ManipulationContext( initState: FreeState(), shapes: shapes, ), diff --git a/patterns/state/manipulator_state/pattern/manipulator_context.dart b/patterns/state/manipulator_state/pattern/manipulation_context.dart similarity index 95% rename from patterns/state/manipulator_state/pattern/manipulator_context.dart rename to patterns/state/manipulator_state/pattern/manipulation_context.dart index 89f7ee4..fd759d8 100644 --- a/patterns/state/manipulator_state/pattern/manipulator_context.dart +++ b/patterns/state/manipulator_state/pattern/manipulation_context.dart @@ -5,10 +5,10 @@ import '../app/shapes.dart'; part 'manipulation_state.dart'; -class ManipulatorContext { +class ManipulationContext { final Shapes shapes; - ManipulatorContext({ + ManipulationContext({ required this.shapes, required ManipulationState initState, }) : _state = initState { diff --git a/patterns/state/manipulator_state/pattern/manipulation_state.dart b/patterns/state/manipulator_state/pattern/manipulation_state.dart index c041708..4595675 100644 --- a/patterns/state/manipulator_state/pattern/manipulation_state.dart +++ b/patterns/state/manipulator_state/pattern/manipulation_state.dart @@ -1,9 +1,9 @@ part of manipulator; class ManipulationState { - ManipulatorContext? _context; + ManipulationContext? _context; - ManipulatorContext get context => _context!; + ManipulationContext get context => _context!; void mouseMove(double x, double y) {} diff --git a/patterns/state/manipulator_state/states/creations/creation_state.dart b/patterns/state/manipulator_state/states/creations/creation_state.dart index f43c4dd..091093b 100644 --- a/patterns/state/manipulator_state/states/creations/creation_state.dart +++ b/patterns/state/manipulator_state/states/creations/creation_state.dart @@ -1,6 +1,6 @@ import 'dart:ui'; -import '../../pattern/manipulator_context.dart'; +import '../../pattern/manipulation_context.dart'; import '../../shapes/shape.dart'; import '../mixins/hover_state_mixin.dart'; import '../mixins/specific_actions_mixin.dart'; diff --git a/patterns/state/manipulator_state/states/free_sate.dart b/patterns/state/manipulator_state/states/free_sate.dart index 0f7fad0..f4da264 100644 --- a/patterns/state/manipulator_state/states/free_sate.dart +++ b/patterns/state/manipulator_state/states/free_sate.dart @@ -1,4 +1,4 @@ -import '../pattern/manipulator_context.dart'; +import '../pattern/manipulation_context.dart'; import 'mixins/hover_state_mixin.dart'; import 'mixins/specific_actions_mixin.dart'; diff --git a/patterns/state/manipulator_state/states/mixins/hover_state_mixin.dart b/patterns/state/manipulator_state/states/mixins/hover_state_mixin.dart index 8832088..91d84b8 100644 --- a/patterns/state/manipulator_state/states/mixins/hover_state_mixin.dart +++ b/patterns/state/manipulator_state/states/mixins/hover_state_mixin.dart @@ -1,6 +1,6 @@ import 'package:flutter/material.dart'; -import '../../pattern/manipulator_context.dart'; +import '../../pattern/manipulation_context.dart'; import '../../shapes/shape.dart'; mixin HoverStateMixin implements ManipulationState { diff --git a/patterns/state/manipulator_state/states/mixins/specific_actions_mixin.dart b/patterns/state/manipulator_state/states/mixins/specific_actions_mixin.dart index aa55eb5..4e45bc6 100644 --- a/patterns/state/manipulator_state/states/mixins/specific_actions_mixin.dart +++ b/patterns/state/manipulator_state/states/mixins/specific_actions_mixin.dart @@ -1,4 +1,4 @@ -import '../../pattern/manipulator_context.dart'; +import '../../pattern/manipulation_context.dart'; import '../selections/moving_state.dart'; mixin SpecificActionsMixin implements ManipulationState { diff --git a/patterns/state/manipulator_state/states/selections/selection_state.dart b/patterns/state/manipulator_state/states/selections/selection_state.dart index 6bf7108..72ac01e 100644 --- a/patterns/state/manipulator_state/states/selections/selection_state.dart +++ b/patterns/state/manipulator_state/states/selections/selection_state.dart @@ -1,6 +1,6 @@ import 'package:flutter/material.dart'; -import '../../pattern/manipulator_context.dart'; +import '../../pattern/manipulation_context.dart'; import '../../shapes/shape.dart'; import '../free_sate.dart'; import '../mixins/hover_state_mixin.dart'; diff --git a/patterns/state/manipulator_state/widgets/current_state.dart b/patterns/state/manipulator_state/widgets/current_state.dart index 1a8d6b2..79b0a2f 100644 --- a/patterns/state/manipulator_state/widgets/current_state.dart +++ b/patterns/state/manipulator_state/widgets/current_state.dart @@ -2,10 +2,10 @@ import 'package:flutter/material.dart'; import '../../../abstract_factory/tool_panel_factory/widgets/independent/event_listenable_builder.dart'; import '../../../abstract_factory/tool_panel_factory/widgets/independent/panel.dart'; -import '../pattern/manipulator_context.dart'; +import '../pattern/manipulation_context.dart'; class CurrentState extends StatelessWidget { - final ManipulatorContext manipulator; + final ManipulationContext manipulator; const CurrentState({ Key? key, From b711376461526f05790cb9c1f02e56f00024d2b2 Mon Sep 17 00:00:00 2001 From: ilopX Date: Wed, 25 May 2022 12:57:38 +0300 Subject: [PATCH 23/91] Add paint method to RectangleShape. --- .../manipulator_state/shapes/rectangle_shape.dart | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/patterns/state/manipulator_state/shapes/rectangle_shape.dart b/patterns/state/manipulator_state/shapes/rectangle_shape.dart index 648d0d2..27e04c9 100644 --- a/patterns/state/manipulator_state/shapes/rectangle_shape.dart +++ b/patterns/state/manipulator_state/shapes/rectangle_shape.dart @@ -1,3 +1,5 @@ +import 'package:flutter/material.dart'; + import '../states/selections/resizable_state.dart'; import '../states/selections/selection_state.dart'; import 'base_shape.dart'; @@ -9,4 +11,17 @@ class RectangleShape extends BaseShape { SelectionState createSelectionState() { return ResizableState(selectedShape: this); } + + @override + void paint(Canvas canvas) { + canvas.drawRect( + Rect.fromLTWH( + x, + y, + width, + height, + ), + Paint()..color = Colors.white, + ); + } } From 343cd9008e57cbf1ab479bfcf7b77af6afdb7c15 Mon Sep 17 00:00:00 2001 From: ilopX Date: Wed, 25 May 2022 14:44:15 +0300 Subject: [PATCH 24/91] Refactoring CreationState class. --- .../states/creations/creation_state.dart | 46 +++++++++++-------- 1 file changed, 26 insertions(+), 20 deletions(-) diff --git a/patterns/state/manipulator_state/states/creations/creation_state.dart b/patterns/state/manipulator_state/states/creations/creation_state.dart index 091093b..b29528d 100644 --- a/patterns/state/manipulator_state/states/creations/creation_state.dart +++ b/patterns/state/manipulator_state/states/creations/creation_state.dart @@ -2,11 +2,8 @@ import 'dart:ui'; import '../../pattern/manipulation_context.dart'; import '../../shapes/shape.dart'; -import '../mixins/hover_state_mixin.dart'; -import '../mixins/specific_actions_mixin.dart'; -abstract class CreationState extends ManipulationState - with SpecificActionsMixin, HoverStateMixin { +abstract class CreationState extends ManipulationState { Shape createShape(double x, double y); @override @@ -17,13 +14,10 @@ abstract class CreationState extends ManipulationState @override void mouseMove(double x, double y) { if (_isCreatingNotStart) { - super.mouseMove(x, y); // HoverStateMixin return; } - _isDragged = true; - _newShape!.resize(x - _startX, y - _startY); - context.update(); + _resizeNewShape(x, y); } @override @@ -32,24 +26,14 @@ abstract class CreationState extends ManipulationState return; } - if (!_isDragged) { - _newShape!.move(_startX - 50, _startY - 50); - _newShape!.resize(100, 100); - } - + _repositionNewShape(); context.shapes.add(_newShape!); - context.changeState( - _newShape!.createSelectionState(), - ); - - _isDragged = false; - _newShape = null; + _finishCreatingShape(); } @override void paint(Canvas canvas) { _newShape?.paint(canvas); - super.paint(canvas); } var _startX = 0.0; @@ -64,4 +48,26 @@ abstract class CreationState extends ManipulationState } bool get _isCreatingNotStart => _newShape == null; + + void _resizeNewShape(double x, double y) { + _isDragged = true; + _newShape!.resize(x - _startX, y - _startY); + context.update(); + } + + void _finishCreatingShape() { + context.changeState( + _newShape!.createSelectionState(), + ); + + _isDragged = false; + _newShape = null; + } + + void _repositionNewShape() { + if (!_isDragged) { + _newShape!.move(_startX - 50, _startY - 50); + _newShape!.resize(100, 100); + } + } } From 53f67b6406b51636ab283eb182550a5ffac737be Mon Sep 17 00:00:00 2001 From: ilopX Date: Wed, 25 May 2022 14:45:23 +0300 Subject: [PATCH 25/91] Add sub "toString" to selection states. --- .../states/selections/circle_inner_radius_state.dart | 2 +- .../states/selections/moving_state.dart | 2 +- .../states/selections/resizable_state.dart | 2 +- .../states/selections/selection_state.dart | 11 ++++++----- 4 files changed, 9 insertions(+), 8 deletions(-) diff --git a/patterns/state/manipulator_state/states/selections/circle_inner_radius_state.dart b/patterns/state/manipulator_state/states/selections/circle_inner_radius_state.dart index 0b6245e..ba2f31c 100644 --- a/patterns/state/manipulator_state/states/selections/circle_inner_radius_state.dart +++ b/patterns/state/manipulator_state/states/selections/circle_inner_radius_state.dart @@ -48,6 +48,6 @@ class CircleInnerRadiusState extends ResizableState { @override String toString() { - return 'Selection State + Resizable State + Circle Inner Radius State'; + return 'Circle Inner Radius State + ${super.toString()}'; } } diff --git a/patterns/state/manipulator_state/states/selections/moving_state.dart b/patterns/state/manipulator_state/states/selections/moving_state.dart index f13a8a2..052ce59 100644 --- a/patterns/state/manipulator_state/states/selections/moving_state.dart +++ b/patterns/state/manipulator_state/states/selections/moving_state.dart @@ -26,6 +26,6 @@ class MovingState extends SelectionState { @override String toString() { - return 'Selection State + Moving State'; + return 'Moving State + ${super.toString()}'; } } diff --git a/patterns/state/manipulator_state/states/selections/resizable_state.dart b/patterns/state/manipulator_state/states/selections/resizable_state.dart index c113d17..d326a85 100644 --- a/patterns/state/manipulator_state/states/selections/resizable_state.dart +++ b/patterns/state/manipulator_state/states/selections/resizable_state.dart @@ -70,6 +70,6 @@ class ResizableState extends SelectionState { @override String toString() { - return 'Selection State + Resizable State'; + return 'Resizable State + ${super.toString()}'; } } diff --git a/patterns/state/manipulator_state/states/selections/selection_state.dart b/patterns/state/manipulator_state/states/selections/selection_state.dart index 72ac01e..872d40e 100644 --- a/patterns/state/manipulator_state/states/selections/selection_state.dart +++ b/patterns/state/manipulator_state/states/selections/selection_state.dart @@ -1,13 +1,9 @@ import 'package:flutter/material.dart'; -import '../../pattern/manipulation_context.dart'; import '../../shapes/shape.dart'; import '../free_sate.dart'; -import '../mixins/hover_state_mixin.dart'; -import '../mixins/specific_actions_mixin.dart'; -class SelectionState extends ManipulationState - with SpecificActionsMixin, HoverStateMixin { +class SelectionState extends FreeState { final Shape selectedShape; SelectionState({required this.selectedShape}); @@ -37,4 +33,9 @@ class SelectionState extends ManipulationState ..strokeWidth = 2.0, ); } + + @override + String toString() { + return 'Selection State + ${super.toString()}'; + } } From 2f39598afe126a87efeb69191e6d997554d0c45b Mon Sep 17 00:00:00 2001 From: ilopX Date: Wed, 25 May 2022 17:56:07 +0300 Subject: [PATCH 26/91] Add child MarkerState to ResizableState. --- .../shapes/marker_shape.dart | 25 +++ .../states/mixins/hover_state_mixin.dart | 15 +- .../selections/children/marker_state.dart | 142 +++++++++++++++ .../selections/circle_inner_radius_state.dart | 5 - .../states/selections/resizable_state.dart | 165 ++++++++++++------ 5 files changed, 293 insertions(+), 59 deletions(-) create mode 100644 patterns/state/manipulator_state/shapes/marker_shape.dart create mode 100644 patterns/state/manipulator_state/states/selections/children/marker_state.dart diff --git a/patterns/state/manipulator_state/shapes/marker_shape.dart b/patterns/state/manipulator_state/shapes/marker_shape.dart new file mode 100644 index 0000000..7d77946 --- /dev/null +++ b/patterns/state/manipulator_state/shapes/marker_shape.dart @@ -0,0 +1,25 @@ +import 'package:flutter/material.dart'; + +import 'base_shape.dart'; + +class MarkerShape extends BaseShape { + MarkerShape(super.x, super.y, [super.width = 5, super.height = 5]); + + @override + void paint(Canvas canvas) { + final point1 = Offset(x, y); + + final paint1 = Paint() + ..style = PaintingStyle.fill + ..color = Colors.black; + + canvas.drawCircle(point1, width, paint1); + + final paint2 = Paint() + ..style = PaintingStyle.stroke + ..strokeWidth = 1.5 + ..color = Colors.cyanAccent; + + canvas.drawCircle(point1, width, paint2); + } +} diff --git a/patterns/state/manipulator_state/states/mixins/hover_state_mixin.dart b/patterns/state/manipulator_state/states/mixins/hover_state_mixin.dart index 91d84b8..5764aa8 100644 --- a/patterns/state/manipulator_state/states/mixins/hover_state_mixin.dart +++ b/patterns/state/manipulator_state/states/mixins/hover_state_mixin.dart @@ -4,9 +4,15 @@ import '../../pattern/manipulation_context.dart'; import '../../shapes/shape.dart'; mixin HoverStateMixin implements ManipulationState { + Shape? findShapeByCoordinates(double x, double y) { + return context.shapes.findShapeByCoordinates(x, y); + } + + bool get isHover => _isHover; + @override void mouseMove(double x, double y) { - final newHover = context.shapes.findShapeByCoordinates(x, y); + final newHover = findShapeByCoordinates(x, y); if (newHover == _hoverShape) { return; @@ -15,8 +21,10 @@ mixin HoverStateMixin implements ManipulationState { _hoverShape = newHover; if (newHover == null) { + _isHover = false; onMouseLeave(); } else { + _isHover = true; onHover(); } @@ -27,7 +35,7 @@ mixin HoverStateMixin implements ManipulationState { void onMouseLeave() {} - Shape? _hoverShape; + @override void paint(Canvas canvas) { @@ -48,4 +56,7 @@ mixin HoverStateMixin implements ManipulationState { ..strokeWidth = 4.0, ); } + + Shape? _hoverShape; + bool _isHover = false; } diff --git a/patterns/state/manipulator_state/states/selections/children/marker_state.dart b/patterns/state/manipulator_state/states/selections/children/marker_state.dart new file mode 100644 index 0000000..eeb5541 --- /dev/null +++ b/patterns/state/manipulator_state/states/selections/children/marker_state.dart @@ -0,0 +1,142 @@ +import 'dart:ui'; + +import 'package:flutter/services.dart'; + +import '../../../shapes/marker_shape.dart'; +import '../../../shapes/shape.dart'; +import '../../../pattern/manipulation_context.dart'; +import '../../mixins/hover_state_mixin.dart'; +import '../resizable_state.dart'; +import '../selection_state.dart'; + +class MarkerState extends ManipulationState with HoverStateMixin { + final SelectionState parentState; + final Shape markerShape; + final MouseCursor hoverCursor; + + MarkerState({ + required double x, + required double y, + required this.hoverCursor, + required this.parentState, + }) : markerShape = MarkerShape(x, y); + + factory MarkerState.topLeft(SelectionState parentState) { + return MarkerState( + x: parentState.selectedShape.x, + y: parentState.selectedShape.y, + hoverCursor: SystemMouseCursors.resizeUpLeft, + parentState: parentState, + ).._name = 'MarkerState.topLeft'; + } + + factory MarkerState.topRight(SelectionState parentState) { + return MarkerState( + x: parentState.selectedShape.x + parentState.selectedShape.width, + y: parentState.selectedShape.y, + hoverCursor: SystemMouseCursors.resizeUpRight, + parentState: parentState, + ).._name = 'MarkerState.topRight'; + } + + factory MarkerState.bottomRight(SelectionState parentState) { + return MarkerState( + x: parentState.selectedShape.x + parentState.selectedShape.width, + y: parentState.selectedShape.y + parentState.selectedShape.height, + hoverCursor: SystemMouseCursors.resizeDownRight, + parentState: parentState, + ).._name = 'MarkerState.bottomRight'; + } + + factory MarkerState.bottomLeft(SelectionState parentState) { + return MarkerState( + x: parentState.selectedShape.x, + y: parentState.selectedShape.y + parentState.selectedShape.height, + hoverCursor: SystemMouseCursors.resizeDownLeft, + parentState: parentState, + ).._name = 'MarkerState.bottomLeft'; + } + + + @override + void mouseDown(double x, double y) { + if (isHover) { + _isDown = true; + context.changeState(this); + } + } + + @override + void mouseMove(double x, double y) { + super.mouseMove(x, y); + if (_isDown) { + parentState.selectedShape.resize( + x - parentState.selectedShape.x, + y - parentState.selectedShape.y, + ); + + markerShape.move( + parentState.selectedShape.x + parentState.selectedShape.width, + parentState.selectedShape.y + parentState.selectedShape.height, + ); + context.update(); + } + } + + @override + void mouseUp() { + if (!_isDown) { + return; + } + + context.changeState( + ResizableState( + selectedShape: parentState.selectedShape, + ), + ); + _isDown = false; + } + + @override + void onHover() { + context.cursor = hoverCursor; + } + + @override + void onMouseLeave() { + context.cursor = SystemMouseCursors.basic; + } + + void render(Canvas canvas) { + markerShape.paint(canvas); + } + + @override + ManipulationContext get context => parentState.context; + + @override + Shape? findShapeByCoordinates(double x, double y) { + final rect = Rect.fromLTWH( + markerShape.x - markerShape.width, + markerShape.y - markerShape.width, + markerShape.width * 2, + markerShape.width * 2, + ); + return rect.contains(Offset(x, y)) ? markerShape : null; + } + + @override + void paint(Canvas canvas) { + parentState.paint(canvas); + } + + bool get isDown => _isDown; + + bool _isDown = false; + String _name = 'MarkerState'; + + @override + String toString() { + return '$parentState + $_name'; + } +} diff --git a/patterns/state/manipulator_state/states/selections/circle_inner_radius_state.dart b/patterns/state/manipulator_state/states/selections/circle_inner_radius_state.dart index ba2f31c..8637916 100644 --- a/patterns/state/manipulator_state/states/selections/circle_inner_radius_state.dart +++ b/patterns/state/manipulator_state/states/selections/circle_inner_radius_state.dart @@ -6,11 +6,6 @@ import 'resizable_state.dart'; class CircleInnerRadiusState extends ResizableState { CircleInnerRadiusState({required super.selectedShape}); - @override - void mouseMove(double x, double y) { - super.mouseMove(x, y); - } - @override void paint(Canvas canvas) { super.paint(canvas); diff --git a/patterns/state/manipulator_state/states/selections/resizable_state.dart b/patterns/state/manipulator_state/states/selections/resizable_state.dart index d326a85..da1a3f4 100644 --- a/patterns/state/manipulator_state/states/selections/resizable_state.dart +++ b/patterns/state/manipulator_state/states/selections/resizable_state.dart @@ -1,71 +1,132 @@ import 'package:flutter/material.dart'; +import 'children/marker_state.dart'; import 'selection_state.dart'; +import '../../shapes/shape.dart'; + +class MarkerState extends ManipulationState with HoverStateMixin { + final SelectionState parentState; + final Shape markerShape; + final MouseCursor hoverCursor; + + MarkerState({ + required double x, + required double y, + required this.hoverCursor, + required this.parentState, + }) : markerShape = MarkerShape(x, y); + + factory MarkerState.topLeft(SelectionState parentState) { + return MarkerState( + x: parentState.selectedShape.x, + y: parentState.selectedShape.y, + hoverCursor: SystemMouseCursors.resizeUpLeft, + parentState: parentState, + ).._name = 'MarkerState.topLeft'; + } + + factory MarkerState.topRight(SelectionState parentState) { + return MarkerState( + x: parentState.selectedShape.x + parentState.selectedShape.width, + y: parentState.selectedShape.y, + hoverCursor: SystemMouseCursors.resizeUpRight, + parentState: parentState, + ).._name = 'MarkerState.topRight'; + } + + factory MarkerState.bottomRight(SelectionState parentState) { + return MarkerState( + x: parentState.selectedShape.x + parentState.selectedShape.width, + y: parentState.selectedShape.y + parentState.selectedShape.height, + hoverCursor: SystemMouseCursors.resizeDownRight, + parentState: parentState, + ).._name = 'MarkerState.bottomRight'; + } + + factory MarkerState.bottomLeft(SelectionState parentState) { + return MarkerState( + x: parentState.selectedShape.x, + y: parentState.selectedShape.y + parentState.selectedShape.height, + hoverCursor: SystemMouseCursors.resizeDownLeft, + parentState: parentState, + ).._name = 'MarkerState.bottomLeft'; + } + + @override + void onHover() { + context.cursor = hoverCursor; + } + + @override + void onMouseLeave() { + context.cursor = SystemMouseCursors.basic; + } + + void render(Canvas canvas) { + markerShape.paint(canvas); + } + + @override + ManipulationContext get context => parentState.context; + + @override + Shape? findShapeByCoordinates(double x, double y) { + final rect = Rect.fromLTWH( + markerShape.x - markerShape.width, + markerShape.y - markerShape.width, + markerShape.width * 2, + markerShape.width * 2, + ); + return rect.contains(Offset(x, y)) ? markerShape : null; + } + + @override + void paint(Canvas canvas) { + parentState.paint(canvas); + } + + String _name = 'MarkerState'; + + @override + String toString() { + return _name; + } +} + class ResizableState extends SelectionState { - ResizableState({required super.selectedShape}); + late final MarkerState markerState; + + late final List _markers; + + ResizableState({required super.selectedShape}) { + _markers = [ + MarkerState.topLeft(this), + MarkerState.topRight(this), + MarkerState.bottomRight(this), + MarkerState.bottomLeft(this), + ]; + } @override void mouseMove(double x, double y) { super.mouseMove(x, y); - final rect1 = Rect.fromLTWH( - selectedShape.x - 5, - selectedShape.y - 5, - 10, - 10, - ); - if (rect1.contains(Offset(x, y))) { - context.cursor = SystemMouseCursors.resizeUpLeft; - context.update(); - return; + for (final marker in _markers) { + marker.mouseMove(x, y); + if (marker.isHover) { + return; + } } - - final rect2 = Rect.fromLTWH( - selectedShape.x + selectedShape.width - 5, - selectedShape.y - 5, - 10, - 10, - ); - if (rect2.contains(Offset(x, y))) { - context.cursor = SystemMouseCursors.resizeUpRight; - context.update(); - return; - } - - context.cursor = SystemMouseCursors.basic; - context.update(); } @override void paint(Canvas canvas) { super.paint(canvas); - final xPlusWidth = selectedShape.x + selectedShape.width; - final yPlusHeight = selectedShape.y + selectedShape.height; - - final point1 = Offset(selectedShape.x, selectedShape.y); - final point2 = Offset(xPlusWidth, selectedShape.y); - final point3 = Offset(xPlusWidth, yPlusHeight); - final point4 = Offset(selectedShape.x, yPlusHeight); - - final paint1 = Paint() - ..style = PaintingStyle.fill - ..color = Colors.black; - const radius = 5.0; - canvas.drawCircle(point1, radius, paint1); - canvas.drawCircle(point2, radius, paint1); - canvas.drawCircle(point3, radius, paint1); - canvas.drawCircle(point4, radius, paint1); - - final paint2 = Paint() - ..style = PaintingStyle.stroke - ..strokeWidth = 1.5 - ..color = Colors.cyanAccent; - - canvas.drawCircle(point1, radius, paint2); - canvas.drawCircle(point2, radius, paint2); - canvas.drawCircle(point3, radius, paint2); - canvas.drawCircle(point4, radius, paint2); + + for (final marker in _markers) { + marker.render(canvas); + } } @override From bad43843fc0790aa51634e7a1ca7835206ca2d4b Mon Sep 17 00:00:00 2001 From: ilopX Date: Wed, 25 May 2022 18:45:17 +0300 Subject: [PATCH 27/91] Make left to right state text. --- .../selections/circle_inner_radius_state.dart | 3 +- .../states/selections/moving_state.dart | 2 +- .../states/selections/resizable_state.dart | 114 +++--------------- .../states/selections/selection_state.dart | 2 +- 4 files changed, 23 insertions(+), 98 deletions(-) diff --git a/patterns/state/manipulator_state/states/selections/circle_inner_radius_state.dart b/patterns/state/manipulator_state/states/selections/circle_inner_radius_state.dart index 8637916..88ccec7 100644 --- a/patterns/state/manipulator_state/states/selections/circle_inner_radius_state.dart +++ b/patterns/state/manipulator_state/states/selections/circle_inner_radius_state.dart @@ -1,4 +1,3 @@ -import 'package:flutter/cupertino.dart'; import 'package:flutter/material.dart'; import 'resizable_state.dart'; @@ -43,6 +42,6 @@ class CircleInnerRadiusState extends ResizableState { @override String toString() { - return 'Circle Inner Radius State + ${super.toString()}'; + return '${super.toString()} + Circle Inner Radius State'; } } diff --git a/patterns/state/manipulator_state/states/selections/moving_state.dart b/patterns/state/manipulator_state/states/selections/moving_state.dart index 052ce59..2b12468 100644 --- a/patterns/state/manipulator_state/states/selections/moving_state.dart +++ b/patterns/state/manipulator_state/states/selections/moving_state.dart @@ -26,6 +26,6 @@ class MovingState extends SelectionState { @override String toString() { - return 'Moving State + ${super.toString()}'; + return '${super.toString()} + Moving State'; } } diff --git a/patterns/state/manipulator_state/states/selections/resizable_state.dart b/patterns/state/manipulator_state/states/selections/resizable_state.dart index da1a3f4..0a9a180 100644 --- a/patterns/state/manipulator_state/states/selections/resizable_state.dart +++ b/patterns/state/manipulator_state/states/selections/resizable_state.dart @@ -3,100 +3,7 @@ import 'package:flutter/material.dart'; import 'children/marker_state.dart'; import 'selection_state.dart'; -import '../../shapes/shape.dart'; - -class MarkerState extends ManipulationState with HoverStateMixin { - final SelectionState parentState; - final Shape markerShape; - final MouseCursor hoverCursor; - - MarkerState({ - required double x, - required double y, - required this.hoverCursor, - required this.parentState, - }) : markerShape = MarkerShape(x, y); - - factory MarkerState.topLeft(SelectionState parentState) { - return MarkerState( - x: parentState.selectedShape.x, - y: parentState.selectedShape.y, - hoverCursor: SystemMouseCursors.resizeUpLeft, - parentState: parentState, - ).._name = 'MarkerState.topLeft'; - } - - factory MarkerState.topRight(SelectionState parentState) { - return MarkerState( - x: parentState.selectedShape.x + parentState.selectedShape.width, - y: parentState.selectedShape.y, - hoverCursor: SystemMouseCursors.resizeUpRight, - parentState: parentState, - ).._name = 'MarkerState.topRight'; - } - - factory MarkerState.bottomRight(SelectionState parentState) { - return MarkerState( - x: parentState.selectedShape.x + parentState.selectedShape.width, - y: parentState.selectedShape.y + parentState.selectedShape.height, - hoverCursor: SystemMouseCursors.resizeDownRight, - parentState: parentState, - ).._name = 'MarkerState.bottomRight'; - } - - factory MarkerState.bottomLeft(SelectionState parentState) { - return MarkerState( - x: parentState.selectedShape.x, - y: parentState.selectedShape.y + parentState.selectedShape.height, - hoverCursor: SystemMouseCursors.resizeDownLeft, - parentState: parentState, - ).._name = 'MarkerState.bottomLeft'; - } - - @override - void onHover() { - context.cursor = hoverCursor; - } - - @override - void onMouseLeave() { - context.cursor = SystemMouseCursors.basic; - } - - void render(Canvas canvas) { - markerShape.paint(canvas); - } - - @override - ManipulationContext get context => parentState.context; - - @override - Shape? findShapeByCoordinates(double x, double y) { - final rect = Rect.fromLTWH( - markerShape.x - markerShape.width, - markerShape.y - markerShape.width, - markerShape.width * 2, - markerShape.width * 2, - ); - return rect.contains(Offset(x, y)) ? markerShape : null; - } - - @override - void paint(Canvas canvas) { - parentState.paint(canvas); - } - - String _name = 'MarkerState'; - - @override - String toString() { - return _name; - } -} - class ResizableState extends SelectionState { - late final MarkerState markerState; - late final List _markers; ResizableState({required super.selectedShape}) { @@ -108,6 +15,18 @@ class ResizableState extends SelectionState { ]; } + @override + void mouseDown(double x, double y) { + for (final marker in _markers) { + marker.mouseDown(x, y); + if (marker.isDown) { + return; + } + } + + super.mouseDown(x, y); + } + @override void mouseMove(double x, double y) { super.mouseMove(x, y); @@ -120,6 +39,13 @@ class ResizableState extends SelectionState { } } + @override + void mouseUp() { + for (final marker in _markers) { + marker.mouseUp(); + } + } + @override void paint(Canvas canvas) { super.paint(canvas); @@ -131,6 +57,6 @@ class ResizableState extends SelectionState { @override String toString() { - return 'Resizable State + ${super.toString()}'; + return '${super.toString()} + Resizable State'; } } diff --git a/patterns/state/manipulator_state/states/selections/selection_state.dart b/patterns/state/manipulator_state/states/selections/selection_state.dart index 872d40e..9cb540c 100644 --- a/patterns/state/manipulator_state/states/selections/selection_state.dart +++ b/patterns/state/manipulator_state/states/selections/selection_state.dart @@ -36,6 +36,6 @@ class SelectionState extends FreeState { @override String toString() { - return 'Selection State + ${super.toString()}'; + return '${super.toString()} + Selection State'; } } From b518934ea1070f5bd1293ca7d502cfae2eed41e6 Mon Sep 17 00:00:00 2001 From: ilopX Date: Wed, 25 May 2022 22:07:40 +0300 Subject: [PATCH 28/91] Fix: markers reposition. --- .../shapes/marker_shape.dart | 2 +- .../states/mixins/hover_state_mixin.dart | 12 ++-- .../selections/children/marker_state.dart | 60 +++++++++++-------- .../selections/circle_inner_radius_state.dart | 1 - .../states/selections/resizable_state.dart | 6 ++ 5 files changed, 47 insertions(+), 34 deletions(-) diff --git a/patterns/state/manipulator_state/shapes/marker_shape.dart b/patterns/state/manipulator_state/shapes/marker_shape.dart index 7d77946..3ffaaa7 100644 --- a/patterns/state/manipulator_state/shapes/marker_shape.dart +++ b/patterns/state/manipulator_state/shapes/marker_shape.dart @@ -3,7 +3,7 @@ import 'package:flutter/material.dart'; import 'base_shape.dart'; class MarkerShape extends BaseShape { - MarkerShape(super.x, super.y, [super.width = 5, super.height = 5]); + MarkerShape([super.x = 0, super.y = 0, super.width = 5, super.height = 5]); @override void paint(Canvas canvas) { diff --git a/patterns/state/manipulator_state/states/mixins/hover_state_mixin.dart b/patterns/state/manipulator_state/states/mixins/hover_state_mixin.dart index 5764aa8..c3e7f6b 100644 --- a/patterns/state/manipulator_state/states/mixins/hover_state_mixin.dart +++ b/patterns/state/manipulator_state/states/mixins/hover_state_mixin.dart @@ -35,8 +35,6 @@ mixin HoverStateMixin implements ManipulationState { void onMouseLeave() {} - - @override void paint(Canvas canvas) { if (_hoverShape == null) { @@ -45,15 +43,15 @@ mixin HoverStateMixin implements ManipulationState { canvas.drawRect( Rect.fromLTWH( - _hoverShape!.x + 2, - _hoverShape!.y + 2, - _hoverShape!.width - 4, - _hoverShape!.height - 4, + _hoverShape!.x + 1, + _hoverShape!.y + 1, + _hoverShape!.width - 2, + _hoverShape!.height - 2, ), Paint() ..color = Colors.cyanAccent ..style = PaintingStyle.stroke - ..strokeWidth = 4.0, + ..strokeWidth = 2.0, ); } diff --git a/patterns/state/manipulator_state/states/selections/children/marker_state.dart b/patterns/state/manipulator_state/states/selections/children/marker_state.dart index eeb5541..755264b 100644 --- a/patterns/state/manipulator_state/states/selections/children/marker_state.dart +++ b/patterns/state/manipulator_state/states/selections/children/marker_state.dart @@ -7,56 +7,71 @@ import '../../../shapes/shape.dart'; import '../../../pattern/manipulation_context.dart'; import '../../mixins/hover_state_mixin.dart'; import '../resizable_state.dart'; -import '../selection_state.dart'; class MarkerState extends ManipulationState with HoverStateMixin { - final SelectionState parentState; - final Shape markerShape; + final ResizableState parentState; + late final Shape markerShape; final MouseCursor hoverCursor; MarkerState({ - required double x, - required double y, + required Offset Function() updatePosition, required this.hoverCursor, required this.parentState, - }) : markerShape = MarkerShape(x, y); + }) : markerShape = MarkerShape(), + _updatePosition = updatePosition { + this.updatePosition(); + } - factory MarkerState.topLeft(SelectionState parentState) { + factory MarkerState.topLeft(ResizableState parentState) { return MarkerState( - x: parentState.selectedShape.x, - y: parentState.selectedShape.y, + updatePosition: () => Offset( + parentState.selectedShape.x, + parentState.selectedShape.y, + ), hoverCursor: SystemMouseCursors.resizeUpLeft, parentState: parentState, ).._name = 'MarkerState.topLeft'; } - factory MarkerState.topRight(SelectionState parentState) { + factory MarkerState.topRight(ResizableState parentState) { return MarkerState( - x: parentState.selectedShape.x + parentState.selectedShape.width, - y: parentState.selectedShape.y, + updatePosition: () => Offset( + parentState.selectedShape.x + parentState.selectedShape.width, + parentState.selectedShape.y, + ), hoverCursor: SystemMouseCursors.resizeUpRight, parentState: parentState, ).._name = 'MarkerState.topRight'; } - factory MarkerState.bottomRight(SelectionState parentState) { + factory MarkerState.bottomRight(ResizableState parentState) { return MarkerState( - x: parentState.selectedShape.x + parentState.selectedShape.width, - y: parentState.selectedShape.y + parentState.selectedShape.height, + updatePosition: () => Offset( + parentState.selectedShape.x + parentState.selectedShape.width, + parentState.selectedShape.y + parentState.selectedShape.height, + ), hoverCursor: SystemMouseCursors.resizeDownRight, parentState: parentState, ).._name = 'MarkerState.bottomRight'; } - factory MarkerState.bottomLeft(SelectionState parentState) { + factory MarkerState.bottomLeft(ResizableState parentState) { return MarkerState( - x: parentState.selectedShape.x, - y: parentState.selectedShape.y + parentState.selectedShape.height, + updatePosition: () => Offset( + parentState.selectedShape.x, + parentState.selectedShape.y + parentState.selectedShape.height, + ), hoverCursor: SystemMouseCursors.resizeDownLeft, parentState: parentState, ).._name = 'MarkerState.bottomLeft'; } + final Offset Function() _updatePosition; + + void updatePosition() { + final p = _updatePosition(); + markerShape.move(p.dx, p.dy); + } @override void mouseDown(double x, double y) { @@ -75,10 +90,7 @@ class MarkerState extends ManipulationState with HoverStateMixin { y - parentState.selectedShape.y, ); - markerShape.move( - parentState.selectedShape.x + parentState.selectedShape.width, - parentState.selectedShape.y + parentState.selectedShape.height, - ); + parentState.updateMarkersPosition(); context.update(); } } @@ -90,9 +102,7 @@ class MarkerState extends ManipulationState with HoverStateMixin { } context.changeState( - ResizableState( - selectedShape: parentState.selectedShape, - ), + parentState, ); _isDown = false; } diff --git a/patterns/state/manipulator_state/states/selections/circle_inner_radius_state.dart b/patterns/state/manipulator_state/states/selections/circle_inner_radius_state.dart index 88ccec7..d994e4d 100644 --- a/patterns/state/manipulator_state/states/selections/circle_inner_radius_state.dart +++ b/patterns/state/manipulator_state/states/selections/circle_inner_radius_state.dart @@ -24,7 +24,6 @@ class CircleInnerRadiusState extends ResizableState { p1, 5, Paint() - ..color = Colors.black ..style = PaintingStyle.fill, ); diff --git a/patterns/state/manipulator_state/states/selections/resizable_state.dart b/patterns/state/manipulator_state/states/selections/resizable_state.dart index 0a9a180..a466501 100644 --- a/patterns/state/manipulator_state/states/selections/resizable_state.dart +++ b/patterns/state/manipulator_state/states/selections/resizable_state.dart @@ -27,6 +27,12 @@ class ResizableState extends SelectionState { super.mouseDown(x, y); } + void updateMarkersPosition() { + for (final marker in _markers) { + marker.updatePosition(); + } + } + @override void mouseMove(double x, double y) { super.mouseMove(x, y); From 2d04245229e2f3de1241b619fcca85da537f25d8 Mon Sep 17 00:00:00 2001 From: ilopX Date: Wed, 25 May 2022 22:26:42 +0300 Subject: [PATCH 29/91] Add mouse effect to marker. --- .../selections/children/marker_state.dart | 27 +++++++++++++------ .../states/selections/resizable_state.dart | 13 ++++----- 2 files changed, 26 insertions(+), 14 deletions(-) diff --git a/patterns/state/manipulator_state/states/selections/children/marker_state.dart b/patterns/state/manipulator_state/states/selections/children/marker_state.dart index 755264b..d4b952d 100644 --- a/patterns/state/manipulator_state/states/selections/children/marker_state.dart +++ b/patterns/state/manipulator_state/states/selections/children/marker_state.dart @@ -15,6 +15,7 @@ class MarkerState extends ManipulationState with HoverStateMixin { MarkerState({ required Offset Function() updatePosition, + required this.mouseEffect, required this.hoverCursor, required this.parentState, }) : markerShape = MarkerShape(), @@ -28,6 +29,10 @@ class MarkerState extends ManipulationState with HoverStateMixin { parentState.selectedShape.x, parentState.selectedShape.y, ), + mouseEffect: (double x, double y) => parentState.selectedShape.resize( + x - parentState.selectedShape.x, + y - parentState.selectedShape.y, + ), hoverCursor: SystemMouseCursors.resizeUpLeft, parentState: parentState, ).._name = 'MarkerState.topLeft'; @@ -39,6 +44,10 @@ class MarkerState extends ManipulationState with HoverStateMixin { parentState.selectedShape.x + parentState.selectedShape.width, parentState.selectedShape.y, ), + mouseEffect: (double x, double y) => parentState.selectedShape.resize( + x - parentState.selectedShape.x, + y - parentState.selectedShape.y, + ), hoverCursor: SystemMouseCursors.resizeUpRight, parentState: parentState, ).._name = 'MarkerState.topRight'; @@ -50,6 +59,10 @@ class MarkerState extends ManipulationState with HoverStateMixin { parentState.selectedShape.x + parentState.selectedShape.width, parentState.selectedShape.y + parentState.selectedShape.height, ), + mouseEffect: (double x, double y) => parentState.selectedShape.resize( + x - parentState.selectedShape.x, + y - parentState.selectedShape.y, + ), hoverCursor: SystemMouseCursors.resizeDownRight, parentState: parentState, ).._name = 'MarkerState.bottomRight'; @@ -61,13 +74,14 @@ class MarkerState extends ManipulationState with HoverStateMixin { parentState.selectedShape.x, parentState.selectedShape.y + parentState.selectedShape.height, ), + mouseEffect: (double x, double y) { + parentState.selectedShape.move(x, parentState.selectedShape.y); + }, hoverCursor: SystemMouseCursors.resizeDownLeft, parentState: parentState, ).._name = 'MarkerState.bottomLeft'; } - final Offset Function() _updatePosition; - void updatePosition() { final p = _updatePosition(); markerShape.move(p.dx, p.dy); @@ -77,7 +91,6 @@ class MarkerState extends ManipulationState with HoverStateMixin { void mouseDown(double x, double y) { if (isHover) { _isDown = true; - context.changeState(this); } } @@ -85,11 +98,7 @@ class MarkerState extends ManipulationState with HoverStateMixin { void mouseMove(double x, double y) { super.mouseMove(x, y); if (_isDown) { - parentState.selectedShape.resize( - x - parentState.selectedShape.x, - y - parentState.selectedShape.y, - ); - + mouseEffect.call(x, y); parentState.updateMarkersPosition(); context.update(); } @@ -142,6 +151,8 @@ class MarkerState extends ManipulationState with HoverStateMixin { bool get isDown => _isDown; + final void Function(double x, double y) mouseEffect; + final Offset Function() _updatePosition; bool _isDown = false; String _name = 'MarkerState'; diff --git a/patterns/state/manipulator_state/states/selections/resizable_state.dart b/patterns/state/manipulator_state/states/selections/resizable_state.dart index a466501..1c4cb10 100644 --- a/patterns/state/manipulator_state/states/selections/resizable_state.dart +++ b/patterns/state/manipulator_state/states/selections/resizable_state.dart @@ -20,6 +20,7 @@ class ResizableState extends SelectionState { for (final marker in _markers) { marker.mouseDown(x, y); if (marker.isDown) { + context.changeState(marker); return; } } @@ -27,12 +28,6 @@ class ResizableState extends SelectionState { super.mouseDown(x, y); } - void updateMarkersPosition() { - for (final marker in _markers) { - marker.updatePosition(); - } - } - @override void mouseMove(double x, double y) { super.mouseMove(x, y); @@ -61,6 +56,12 @@ class ResizableState extends SelectionState { } } + void updateMarkersPosition() { + for (final marker in _markers) { + marker.updatePosition(); + } + } + @override String toString() { return '${super.toString()} + Resizable State'; From d76e90015f748e635eacde4fcc53a6c2c636b2d8 Mon Sep 17 00:00:00 2001 From: ilopX Date: Thu, 26 May 2022 03:08:14 +0300 Subject: [PATCH 30/91] Add ParentState & ChildState. --- .../pattern/manipulation_context.dart | 13 +- .../pattern/manipulation_state.dart | 2 + .../manipulator_state/states/free_sate.dart | 23 ++- .../states/mixins/parent_state_mixin.dart | 1 + .../states/mixins/specific_actions_mixin.dart | 22 --- .../selections/children/marker_state.dart | 163 ------------------ .../states/selections/resizable_state.dart | 66 +------ .../selections/sub_states/child_state.dart | 92 ++++++++++ .../selections/sub_states/parent_state.dart | 54 ++++++ .../sub_states/top_right_marker_state.dart | 25 +++ 10 files changed, 206 insertions(+), 255 deletions(-) create mode 100644 patterns/state/manipulator_state/states/mixins/parent_state_mixin.dart delete mode 100644 patterns/state/manipulator_state/states/mixins/specific_actions_mixin.dart delete mode 100644 patterns/state/manipulator_state/states/selections/children/marker_state.dart create mode 100644 patterns/state/manipulator_state/states/selections/sub_states/child_state.dart create mode 100644 patterns/state/manipulator_state/states/selections/sub_states/parent_state.dart create mode 100644 patterns/state/manipulator_state/states/selections/sub_states/top_right_marker_state.dart diff --git a/patterns/state/manipulator_state/pattern/manipulation_context.dart b/patterns/state/manipulator_state/pattern/manipulation_context.dart index fd759d8..93df5dc 100644 --- a/patterns/state/manipulator_state/pattern/manipulation_context.dart +++ b/patterns/state/manipulator_state/pattern/manipulation_context.dart @@ -7,6 +7,9 @@ part 'manipulation_state.dart'; class ManipulationContext { final Shapes shapes; + final onStateChange = Event(); + final onUpdate = Event(); + var cursor = MouseCursor.defer; ManipulationContext({ required this.shapes, @@ -15,8 +18,6 @@ class ManipulationContext { _state._context = this; } - ManipulationState _state; - ManipulationState get state => _state; void changeState(ManipulationState newState) { @@ -24,16 +25,12 @@ class ManipulationContext { return; } + _state._context = null; _state = newState; _state._context = this; onStateChange._emit(); } - final onStateChange = Event(); - final onUpdate = Event(); - - var cursor = MouseCursor.defer; - void update() { onUpdate._emit(); } @@ -62,6 +59,8 @@ class ManipulationContext { void paint(Canvas canvas) { _state.paint(canvas); } + + ManipulationState _state; } class Event extends ChangeNotifier { diff --git a/patterns/state/manipulator_state/pattern/manipulation_state.dart b/patterns/state/manipulator_state/pattern/manipulation_state.dart index 4595675..7db5fe2 100644 --- a/patterns/state/manipulator_state/pattern/manipulation_state.dart +++ b/patterns/state/manipulator_state/pattern/manipulation_state.dart @@ -14,4 +14,6 @@ class ManipulationState { void keyDown(String key) {} void paint(Canvas canvas) {} + + void updateChildrenStates() {} } diff --git a/patterns/state/manipulator_state/states/free_sate.dart b/patterns/state/manipulator_state/states/free_sate.dart index f4da264..6a48bb8 100644 --- a/patterns/state/manipulator_state/states/free_sate.dart +++ b/patterns/state/manipulator_state/states/free_sate.dart @@ -1,14 +1,31 @@ import '../pattern/manipulation_context.dart'; import 'mixins/hover_state_mixin.dart'; -import 'mixins/specific_actions_mixin.dart'; +import 'selections/moving_state.dart'; -class FreeState extends ManipulationState - with SpecificActionsMixin, HoverStateMixin { +class FreeState extends ManipulationState with HoverStateMixin { @override void mouseDown(double x, double y) { trySelectAndStartMovingShape(x, y); } + bool trySelectAndStartMovingShape(double x, double y) { + final shape = context.shapes.findShapeByCoordinates(x, y); + + if (shape == null) { + return false; + } + + context.changeState( + MovingState( + startX: x, + startY: y, + selectedShape: shape, + ), + ); + + return true; + } + @override String toString() { return 'Free State'; diff --git a/patterns/state/manipulator_state/states/mixins/parent_state_mixin.dart b/patterns/state/manipulator_state/states/mixins/parent_state_mixin.dart new file mode 100644 index 0000000..8b13789 --- /dev/null +++ b/patterns/state/manipulator_state/states/mixins/parent_state_mixin.dart @@ -0,0 +1 @@ + diff --git a/patterns/state/manipulator_state/states/mixins/specific_actions_mixin.dart b/patterns/state/manipulator_state/states/mixins/specific_actions_mixin.dart deleted file mode 100644 index 4e45bc6..0000000 --- a/patterns/state/manipulator_state/states/mixins/specific_actions_mixin.dart +++ /dev/null @@ -1,22 +0,0 @@ -import '../../pattern/manipulation_context.dart'; -import '../selections/moving_state.dart'; - -mixin SpecificActionsMixin implements ManipulationState { - bool trySelectAndStartMovingShape(double x, double y) { - final shape = context.shapes.findShapeByCoordinates(x, y); - - if (shape == null) { - return false; - } - - context.changeState( - MovingState( - startX: x, - startY: y, - selectedShape: shape, - ), - ); - - return true; - } -} diff --git a/patterns/state/manipulator_state/states/selections/children/marker_state.dart b/patterns/state/manipulator_state/states/selections/children/marker_state.dart deleted file mode 100644 index d4b952d..0000000 --- a/patterns/state/manipulator_state/states/selections/children/marker_state.dart +++ /dev/null @@ -1,163 +0,0 @@ -import 'dart:ui'; - -import 'package:flutter/services.dart'; - -import '../../../shapes/marker_shape.dart'; -import '../../../shapes/shape.dart'; -import '../../../pattern/manipulation_context.dart'; -import '../../mixins/hover_state_mixin.dart'; -import '../resizable_state.dart'; - -class MarkerState extends ManipulationState with HoverStateMixin { - final ResizableState parentState; - late final Shape markerShape; - final MouseCursor hoverCursor; - - MarkerState({ - required Offset Function() updatePosition, - required this.mouseEffect, - required this.hoverCursor, - required this.parentState, - }) : markerShape = MarkerShape(), - _updatePosition = updatePosition { - this.updatePosition(); - } - - factory MarkerState.topLeft(ResizableState parentState) { - return MarkerState( - updatePosition: () => Offset( - parentState.selectedShape.x, - parentState.selectedShape.y, - ), - mouseEffect: (double x, double y) => parentState.selectedShape.resize( - x - parentState.selectedShape.x, - y - parentState.selectedShape.y, - ), - hoverCursor: SystemMouseCursors.resizeUpLeft, - parentState: parentState, - ).._name = 'MarkerState.topLeft'; - } - - factory MarkerState.topRight(ResizableState parentState) { - return MarkerState( - updatePosition: () => Offset( - parentState.selectedShape.x + parentState.selectedShape.width, - parentState.selectedShape.y, - ), - mouseEffect: (double x, double y) => parentState.selectedShape.resize( - x - parentState.selectedShape.x, - y - parentState.selectedShape.y, - ), - hoverCursor: SystemMouseCursors.resizeUpRight, - parentState: parentState, - ).._name = 'MarkerState.topRight'; - } - - factory MarkerState.bottomRight(ResizableState parentState) { - return MarkerState( - updatePosition: () => Offset( - parentState.selectedShape.x + parentState.selectedShape.width, - parentState.selectedShape.y + parentState.selectedShape.height, - ), - mouseEffect: (double x, double y) => parentState.selectedShape.resize( - x - parentState.selectedShape.x, - y - parentState.selectedShape.y, - ), - hoverCursor: SystemMouseCursors.resizeDownRight, - parentState: parentState, - ).._name = 'MarkerState.bottomRight'; - } - - factory MarkerState.bottomLeft(ResizableState parentState) { - return MarkerState( - updatePosition: () => Offset( - parentState.selectedShape.x, - parentState.selectedShape.y + parentState.selectedShape.height, - ), - mouseEffect: (double x, double y) { - parentState.selectedShape.move(x, parentState.selectedShape.y); - }, - hoverCursor: SystemMouseCursors.resizeDownLeft, - parentState: parentState, - ).._name = 'MarkerState.bottomLeft'; - } - - void updatePosition() { - final p = _updatePosition(); - markerShape.move(p.dx, p.dy); - } - - @override - void mouseDown(double x, double y) { - if (isHover) { - _isDown = true; - } - } - - @override - void mouseMove(double x, double y) { - super.mouseMove(x, y); - if (_isDown) { - mouseEffect.call(x, y); - parentState.updateMarkersPosition(); - context.update(); - } - } - - @override - void mouseUp() { - if (!_isDown) { - return; - } - - context.changeState( - parentState, - ); - _isDown = false; - } - - @override - void onHover() { - context.cursor = hoverCursor; - } - - @override - void onMouseLeave() { - context.cursor = SystemMouseCursors.basic; - } - - void render(Canvas canvas) { - markerShape.paint(canvas); - } - - @override - ManipulationContext get context => parentState.context; - - @override - Shape? findShapeByCoordinates(double x, double y) { - final rect = Rect.fromLTWH( - markerShape.x - markerShape.width, - markerShape.y - markerShape.width, - markerShape.width * 2, - markerShape.width * 2, - ); - return rect.contains(Offset(x, y)) ? markerShape : null; - } - - @override - void paint(Canvas canvas) { - parentState.paint(canvas); - } - - bool get isDown => _isDown; - - final void Function(double x, double y) mouseEffect; - final Offset Function() _updatePosition; - bool _isDown = false; - String _name = 'MarkerState'; - - @override - String toString() { - return '$parentState + $_name'; - } -} diff --git a/patterns/state/manipulator_state/states/selections/resizable_state.dart b/patterns/state/manipulator_state/states/selections/resizable_state.dart index 1c4cb10..970b92d 100644 --- a/patterns/state/manipulator_state/states/selections/resizable_state.dart +++ b/patterns/state/manipulator_state/states/selections/resizable_state.dart @@ -1,65 +1,11 @@ -import 'package:flutter/material.dart'; - -import 'children/marker_state.dart'; -import 'selection_state.dart'; - -class ResizableState extends SelectionState { - late final List _markers; +import 'sub_states/parent_state.dart'; +import 'sub_states/top_right_marker_state.dart'; +class ResizableState extends ParentState { ResizableState({required super.selectedShape}) { - _markers = [ - MarkerState.topLeft(this), - MarkerState.topRight(this), - MarkerState.bottomRight(this), - MarkerState.bottomLeft(this), - ]; - } - - @override - void mouseDown(double x, double y) { - for (final marker in _markers) { - marker.mouseDown(x, y); - if (marker.isDown) { - context.changeState(marker); - return; - } - } - - super.mouseDown(x, y); - } - - @override - void mouseMove(double x, double y) { - super.mouseMove(x, y); - - for (final marker in _markers) { - marker.mouseMove(x, y); - if (marker.isHover) { - return; - } - } - } - - @override - void mouseUp() { - for (final marker in _markers) { - marker.mouseUp(); - } - } - - @override - void paint(Canvas canvas) { - super.paint(canvas); - - for (final marker in _markers) { - marker.render(canvas); - } - } - - void updateMarkersPosition() { - for (final marker in _markers) { - marker.updatePosition(); - } + addMarkers([ + TopRightMarkerState(parentState: this), + ]); } @override diff --git a/patterns/state/manipulator_state/states/selections/sub_states/child_state.dart b/patterns/state/manipulator_state/states/selections/sub_states/child_state.dart new file mode 100644 index 0000000..c1628c7 --- /dev/null +++ b/patterns/state/manipulator_state/states/selections/sub_states/child_state.dart @@ -0,0 +1,92 @@ +import 'dart:ui'; + +import 'package:flutter/services.dart'; + +import '../../../shapes/shape.dart'; +import '../../../pattern/manipulation_context.dart'; +import '../../mixins/hover_state_mixin.dart'; + +abstract class ChildState extends ManipulationState with HoverStateMixin { + final ManipulationState parentState; + final Shape markerShape; + final MouseCursor hoverCursor; + + ChildState({ + required this.parentState, + required this.markerShape, + this.hoverCursor = SystemMouseCursors.basic, + }) { + updatePosition(); + } + + void updatePosition(); + + void mouseMoveAction(double x, double y); + + void render(Canvas canvas) { + markerShape.paint(canvas); + } + + @override + void onHover() { + context.cursor = hoverCursor; + } + + @override + void onMouseLeave() { + context.cursor = SystemMouseCursors.basic; + } + + @override + void mouseDown(double x, double y) { + if (isHover) { + _isDown = true; + } + } + + @override + void mouseMove(double x, double y) { + super.mouseMove(x, y); + if (_isDown) { + mouseMoveAction(x, y); + parentState.updateChildrenStates(); + context.update(); + } + } + + @override + void mouseUp() { + if (!_isDown) { + return; + } + + context.changeState( + parentState, + ); + _isDown = false; + } + + @override + void paint(Canvas canvas) { + parentState.paint(canvas); + } + + @override + ManipulationContext get context => parentState.context; + + @override + Shape? findShapeByCoordinates(double x, double y) { + final rect = Rect.fromLTWH( + markerShape.x - markerShape.width, + markerShape.y - markerShape.width, + markerShape.width * 2, + markerShape.width * 2, + ); + + return rect.contains(Offset(x, y)) ? markerShape : null; + } + + bool get isDown => _isDown; + + bool _isDown = false; +} diff --git a/patterns/state/manipulator_state/states/selections/sub_states/parent_state.dart b/patterns/state/manipulator_state/states/selections/sub_states/parent_state.dart new file mode 100644 index 0000000..6e12fff --- /dev/null +++ b/patterns/state/manipulator_state/states/selections/sub_states/parent_state.dart @@ -0,0 +1,54 @@ +import 'dart:ui'; + +import '../sub_states/child_state.dart'; +import '../selection_state.dart'; + +class ParentState extends SelectionState { + ParentState({required super.selectedShape}); + + void addMarkers(List markers) { + _markers.addAll(markers); + } + + @override + void mouseDown(double x, double y) { + for (final marker in _markers) { + marker.mouseDown(x, y); + if (marker.isDown) { + context.changeState(marker); + return; + } + } + + super.mouseDown(x, y); + } + + @override + void mouseMove(double x, double y) { + super.mouseMove(x, y); + + for (final marker in _markers) { + marker.mouseMove(x, y); + if (marker.isHover) { + return; + } + } + } + + @override + void paint(Canvas canvas) { + super.paint(canvas); + + for (final marker in _markers) { + marker.render(canvas); + } + } + + void updateMarkersPosition() { + for (final marker in _markers) { + marker.updatePosition(); + } + } + + List _markers = []; +} diff --git a/patterns/state/manipulator_state/states/selections/sub_states/top_right_marker_state.dart b/patterns/state/manipulator_state/states/selections/sub_states/top_right_marker_state.dart new file mode 100644 index 0000000..58d1ac9 --- /dev/null +++ b/patterns/state/manipulator_state/states/selections/sub_states/top_right_marker_state.dart @@ -0,0 +1,25 @@ +import 'package:flutter/rendering.dart'; + +import '../../../pattern/manipulation_context.dart'; +import '../../../shapes/marker_shape.dart'; +import 'child_state.dart'; + +class TopRightMarkerState extends ChildState { + TopRightMarkerState({ + required ManipulationState parentState, + }) : super( + parentState: parentState, + hoverCursor: SystemMouseCursors.resizeDownRight, + markerShape: MarkerShape(), + ); + + @override + void mouseMoveAction(double x, double y) { + + } + + @override + void updatePosition() { + + } +} From b45ad4bce09547a746230af67f23fe5e54a2aa02 Mon Sep 17 00:00:00 2001 From: ilopX Date: Thu, 26 May 2022 13:14:18 +0300 Subject: [PATCH 31/91] New separate interface for ManipulationState. --- .../app/base_manipulation_context.dart | 78 +++++++++++++++++++ patterns/state/manipulator_state/main.dart | 2 +- .../pattern/manipulation_context.dart | 63 ++++----------- .../pattern/manipulation_state.dart | 4 +- .../states/mixins/parent_state_mixin.dart | 1 - 5 files changed, 96 insertions(+), 52 deletions(-) create mode 100644 patterns/state/manipulator_state/app/base_manipulation_context.dart delete mode 100644 patterns/state/manipulator_state/states/mixins/parent_state_mixin.dart diff --git a/patterns/state/manipulator_state/app/base_manipulation_context.dart b/patterns/state/manipulator_state/app/base_manipulation_context.dart new file mode 100644 index 0000000..ce110af --- /dev/null +++ b/patterns/state/manipulator_state/app/base_manipulation_context.dart @@ -0,0 +1,78 @@ +part of manipulator; + +class BaseManipulationContext implements ManipulationContext { + BaseManipulationContext({ + required this.shapes, + required ManipulationState initState, + }) : _state = initState { + _state._context = this; + } + + @override + final Shapes shapes; + + @override + final onStateChange = Event(); + + @override + final onUpdate = Event(); + + @override + var cursor = MouseCursor.defer; + + @override + ManipulationState get state => _state; + + @override + void changeState(ManipulationState newState) { + if (_state == newState) { + return; + } + + _state._context = null; + _state = newState; + _state._context = this; + onStateChange._emit(); + } + + @override + void update() { + onUpdate._emit(); + } + + @override + void mouseMove(double x, double y) { + _state.mouseMove(x, y); + } + + @override + void mouseDown(double x, double y) { + _state.mouseDown(x, y); + } + + @override + void mouseUp() { + _state.mouseUp(); + } + + @override + void keyDown(String key) { + _state.keyDown(key); + } + + @override + void paint(Canvas canvas) { + _state.paint(canvas); + } + + @override + String toString() { + return _state.toString(); + } + + ManipulationState _state; +} + +class Event extends ChangeNotifier { + void _emit() => notifyListeners(); +} diff --git a/patterns/state/manipulator_state/main.dart b/patterns/state/manipulator_state/main.dart index 6abc22b..09105f3 100644 --- a/patterns/state/manipulator_state/main.dart +++ b/patterns/state/manipulator_state/main.dart @@ -28,7 +28,7 @@ class _ManipulatorStateAppState extends State { final shapes = Shapes(); app = App( shapes: shapes, - manipulator: ManipulationContext( + manipulator: BaseManipulationContext( initState: FreeState(), shapes: shapes, ), diff --git a/patterns/state/manipulator_state/pattern/manipulation_context.dart b/patterns/state/manipulator_state/pattern/manipulation_context.dart index 93df5dc..2d195a6 100644 --- a/patterns/state/manipulator_state/pattern/manipulation_context.dart +++ b/patterns/state/manipulator_state/pattern/manipulation_context.dart @@ -4,65 +4,32 @@ import 'package:flutter/material.dart'; import '../app/shapes.dart'; part 'manipulation_state.dart'; +part '../app/base_manipulation_context.dart'; -class ManipulationContext { - final Shapes shapes; - final onStateChange = Event(); - final onUpdate = Event(); - var cursor = MouseCursor.defer; +abstract class ManipulationContext { + Shapes get shapes; - ManipulationContext({ - required this.shapes, - required ManipulationState initState, - }) : _state = initState { - _state._context = this; - } + MouseCursor get cursor; - ManipulationState get state => _state; + set cursor(MouseCursor cursor); - void changeState(ManipulationState newState) { - if (_state == newState) { - return; - } + ManipulationState get state; - _state._context = null; - _state = newState; - _state._context = this; - onStateChange._emit(); - } + Event get onStateChange; - void update() { - onUpdate._emit(); - } + Event get onUpdate; - @override - String toString() { - return _state.toString(); - } + void changeState(ManipulationState newState); - void mouseMove(double x, double y) { - _state.mouseMove(x, y); - } + void update(); - void mouseDown(double x, double y) { - _state.mouseDown(x, y); - } + void mouseMove(double x, double y); - void mouseUp() { - _state.mouseUp(); - } + void mouseDown(double x, double y); - void keyDown(String key) { - _state.keyDown(key); - } + void mouseUp(); - void paint(Canvas canvas) { - _state.paint(canvas); - } + void keyDown(String key); - ManipulationState _state; -} - -class Event extends ChangeNotifier { - void _emit() => notifyListeners(); + void paint(Canvas canvas); } diff --git a/patterns/state/manipulator_state/pattern/manipulation_state.dart b/patterns/state/manipulator_state/pattern/manipulation_state.dart index 7db5fe2..0a7ed80 100644 --- a/patterns/state/manipulator_state/pattern/manipulation_state.dart +++ b/patterns/state/manipulator_state/pattern/manipulation_state.dart @@ -1,8 +1,6 @@ part of manipulator; class ManipulationState { - ManipulationContext? _context; - ManipulationContext get context => _context!; void mouseMove(double x, double y) {} @@ -16,4 +14,6 @@ class ManipulationState { void paint(Canvas canvas) {} void updateChildrenStates() {} + + ManipulationContext? _context; } diff --git a/patterns/state/manipulator_state/states/mixins/parent_state_mixin.dart b/patterns/state/manipulator_state/states/mixins/parent_state_mixin.dart deleted file mode 100644 index 8b13789..0000000 --- a/patterns/state/manipulator_state/states/mixins/parent_state_mixin.dart +++ /dev/null @@ -1 +0,0 @@ - From 65be1f4bf315b20119c108880798b863da187133 Mon Sep 17 00:00:00 2001 From: ilopX Date: Thu, 26 May 2022 15:13:37 +0300 Subject: [PATCH 32/91] Add corner markers for ResizableState. --- .../app/base_manipulation_context.dart | 1 - .../state/manipulator_state/app/shapes.dart | 4 +- .../shapes/rectangle_shape.dart | 2 +- .../selections/circle_inner_radius_state.dart | 2 +- .../states/selections/resizable_state.dart | 15 -------- .../bottom_left_marker_state.dart | 37 ++++++++++++++++++ .../bottom_right_marker_state.dart | 38 +++++++++++++++++++ .../resizable_state/resizable_state.dart | 21 ++++++++++ .../top_left_marker_state.dart | 34 +++++++++++++++++ .../top_right_marker_state.dart | 38 +++++++++++++++++++ .../selections/sub_states/child_state.dart | 3 +- .../selections/sub_states/parent_state.dart | 9 +++-- .../sub_states/top_right_marker_state.dart | 25 ------------ 13 files changed, 181 insertions(+), 48 deletions(-) delete mode 100644 patterns/state/manipulator_state/states/selections/resizable_state.dart create mode 100644 patterns/state/manipulator_state/states/selections/resizable_state/bottom_left_marker_state.dart create mode 100644 patterns/state/manipulator_state/states/selections/resizable_state/bottom_right_marker_state.dart create mode 100644 patterns/state/manipulator_state/states/selections/resizable_state/resizable_state.dart create mode 100644 patterns/state/manipulator_state/states/selections/resizable_state/top_left_marker_state.dart create mode 100644 patterns/state/manipulator_state/states/selections/resizable_state/top_right_marker_state.dart delete mode 100644 patterns/state/manipulator_state/states/selections/sub_states/top_right_marker_state.dart diff --git a/patterns/state/manipulator_state/app/base_manipulation_context.dart b/patterns/state/manipulator_state/app/base_manipulation_context.dart index ce110af..dda5ff6 100644 --- a/patterns/state/manipulator_state/app/base_manipulation_context.dart +++ b/patterns/state/manipulator_state/app/base_manipulation_context.dart @@ -29,7 +29,6 @@ class BaseManipulationContext implements ManipulationContext { return; } - _state._context = null; _state = newState; _state._context = this; onStateChange._emit(); diff --git a/patterns/state/manipulator_state/app/shapes.dart b/patterns/state/manipulator_state/app/shapes.dart index a72546f..5bd8de7 100644 --- a/patterns/state/manipulator_state/app/shapes.dart +++ b/patterns/state/manipulator_state/app/shapes.dart @@ -6,7 +6,9 @@ import 'package:flutter/foundation.dart'; import '../shapes/shape.dart'; class Shapes with IterableMixin { - final _shapes = []; + final List_shapes; + + Shapes([this._shapes = const []]); void add(Shape shape) { _shapes.add(shape); diff --git a/patterns/state/manipulator_state/shapes/rectangle_shape.dart b/patterns/state/manipulator_state/shapes/rectangle_shape.dart index 27e04c9..e32b864 100644 --- a/patterns/state/manipulator_state/shapes/rectangle_shape.dart +++ b/patterns/state/manipulator_state/shapes/rectangle_shape.dart @@ -1,6 +1,6 @@ import 'package:flutter/material.dart'; -import '../states/selections/resizable_state.dart'; +import '../states/selections/resizable_state/resizable_state.dart'; import '../states/selections/selection_state.dart'; import 'base_shape.dart'; diff --git a/patterns/state/manipulator_state/states/selections/circle_inner_radius_state.dart b/patterns/state/manipulator_state/states/selections/circle_inner_radius_state.dart index d994e4d..5eede75 100644 --- a/patterns/state/manipulator_state/states/selections/circle_inner_radius_state.dart +++ b/patterns/state/manipulator_state/states/selections/circle_inner_radius_state.dart @@ -1,6 +1,6 @@ import 'package:flutter/material.dart'; -import 'resizable_state.dart'; +import 'resizable_state/resizable_state.dart'; class CircleInnerRadiusState extends ResizableState { CircleInnerRadiusState({required super.selectedShape}); diff --git a/patterns/state/manipulator_state/states/selections/resizable_state.dart b/patterns/state/manipulator_state/states/selections/resizable_state.dart deleted file mode 100644 index 970b92d..0000000 --- a/patterns/state/manipulator_state/states/selections/resizable_state.dart +++ /dev/null @@ -1,15 +0,0 @@ -import 'sub_states/parent_state.dart'; -import 'sub_states/top_right_marker_state.dart'; - -class ResizableState extends ParentState { - ResizableState({required super.selectedShape}) { - addMarkers([ - TopRightMarkerState(parentState: this), - ]); - } - - @override - String toString() { - return '${super.toString()} + Resizable State'; - } -} diff --git a/patterns/state/manipulator_state/states/selections/resizable_state/bottom_left_marker_state.dart b/patterns/state/manipulator_state/states/selections/resizable_state/bottom_left_marker_state.dart new file mode 100644 index 0000000..71c23ee --- /dev/null +++ b/patterns/state/manipulator_state/states/selections/resizable_state/bottom_left_marker_state.dart @@ -0,0 +1,37 @@ +import 'package:flutter/rendering.dart'; + +import '../../../shapes/marker_shape.dart'; +import '../selection_state.dart'; +import '../sub_states/child_state.dart'; + +class BottomLeftMarkerState extends ChildState { + BottomLeftMarkerState({ + required SelectionState parentState, + }) : super( + parentState: parentState, + hoverCursor: SystemMouseCursors.resizeDownLeft, + markerShape: MarkerShape(), + ); + + @override + void mouseMoveAction(double x, double y) { + final selectedShape = parentState.selectedShape; + selectedShape.resize( + selectedShape.width +selectedShape.x - x, + y - selectedShape.y, + ); + selectedShape.move(x, selectedShape.y); + } + + @override + void updatePosition() { + markerShape.move( + parentState.selectedShape.x, + parentState.selectedShape.y + parentState.selectedShape.height, + ); + } + @override + String toString() { + return '${parentState.toString()} + Bottom Left Marker State'; + } +} diff --git a/patterns/state/manipulator_state/states/selections/resizable_state/bottom_right_marker_state.dart b/patterns/state/manipulator_state/states/selections/resizable_state/bottom_right_marker_state.dart new file mode 100644 index 0000000..350d700 --- /dev/null +++ b/patterns/state/manipulator_state/states/selections/resizable_state/bottom_right_marker_state.dart @@ -0,0 +1,38 @@ +import 'package:flutter/rendering.dart'; + +import '../../../shapes/marker_shape.dart'; +import '../selection_state.dart'; +import '../sub_states/child_state.dart'; + +class BottomRightMarkerState extends ChildState { + BottomRightMarkerState({ + required SelectionState parentState, + }) : super( + parentState: parentState, + hoverCursor: SystemMouseCursors.resizeDownRight, + markerShape: MarkerShape(), + ); + + @override + void mouseMoveAction(double x, double y) { + final selectedShape = parentState.selectedShape; + selectedShape.resize( + x-selectedShape.x, + y - selectedShape.y, + ); + + } + + @override + void updatePosition() { + markerShape.move( + parentState.selectedShape.x + parentState.selectedShape.width, + parentState.selectedShape.y+ parentState.selectedShape.height, + ); + } + + @override + String toString() { + return '${parentState.toString()} + Bottom Right Marker State'; + } +} diff --git a/patterns/state/manipulator_state/states/selections/resizable_state/resizable_state.dart b/patterns/state/manipulator_state/states/selections/resizable_state/resizable_state.dart new file mode 100644 index 0000000..d578dcb --- /dev/null +++ b/patterns/state/manipulator_state/states/selections/resizable_state/resizable_state.dart @@ -0,0 +1,21 @@ +import 'bottom_left_marker_state.dart'; +import 'bottom_right_marker_state.dart'; +import 'top_left_marker_state.dart'; +import 'top_right_marker_state.dart'; +import '../sub_states/parent_state.dart'; + +class ResizableState extends ParentState { + ResizableState({required super.selectedShape}) { + addMarkers([ + TopLeftMarkerState(parentState: this), + TopRightMarkerState(parentState: this), + BottomRightMarkerState(parentState: this), + BottomLeftMarkerState(parentState: this), + ]); + } + + @override + String toString() { + return '${super.toString()} + Resizable State'; + } +} diff --git a/patterns/state/manipulator_state/states/selections/resizable_state/top_left_marker_state.dart b/patterns/state/manipulator_state/states/selections/resizable_state/top_left_marker_state.dart new file mode 100644 index 0000000..63e5671 --- /dev/null +++ b/patterns/state/manipulator_state/states/selections/resizable_state/top_left_marker_state.dart @@ -0,0 +1,34 @@ +import 'package:flutter/rendering.dart'; + +import '../../../shapes/marker_shape.dart'; +import '../selection_state.dart'; +import '../sub_states/child_state.dart'; + +class TopLeftMarkerState extends ChildState { + TopLeftMarkerState({ + required SelectionState parentState, + }) : super( + parentState: parentState, + hoverCursor: SystemMouseCursors.resizeDownRight, + markerShape: MarkerShape(), + ); + + @override + void mouseMoveAction(double x, double y) { + parentState.selectedShape.resize( + parentState.selectedShape.width + parentState.selectedShape.x - x, + parentState.selectedShape.height + parentState.selectedShape.y - y, + ); + parentState.selectedShape.move(x, y); + } + + @override + void updatePosition() { + markerShape.move(parentState.selectedShape.x, parentState.selectedShape.y); + } + + @override + String toString() { + return '${parentState.toString()} + Top Left Marker State'; + } +} diff --git a/patterns/state/manipulator_state/states/selections/resizable_state/top_right_marker_state.dart b/patterns/state/manipulator_state/states/selections/resizable_state/top_right_marker_state.dart new file mode 100644 index 0000000..74d3399 --- /dev/null +++ b/patterns/state/manipulator_state/states/selections/resizable_state/top_right_marker_state.dart @@ -0,0 +1,38 @@ +import 'package:flutter/rendering.dart'; + +import '../../../shapes/marker_shape.dart'; +import '../selection_state.dart'; +import '../sub_states/child_state.dart'; + +class TopRightMarkerState extends ChildState { + TopRightMarkerState({ + required SelectionState parentState, + }) : super( + parentState: parentState, + hoverCursor: SystemMouseCursors.resizeUpRight, + markerShape: MarkerShape(), + ); + + @override + void mouseMoveAction(double x, double y) { + final selectedShape = parentState.selectedShape; + selectedShape.resize( + x - selectedShape.x, + selectedShape.height + selectedShape.y - y, + ); + selectedShape.move(selectedShape.x, y); + } + + @override + void updatePosition() { + markerShape.move( + parentState.selectedShape.x + parentState.selectedShape.width, + parentState.selectedShape.y, + ); + } + + @override + String toString() { + return '${parentState.toString()} + Top Right Marker State'; + } +} diff --git a/patterns/state/manipulator_state/states/selections/sub_states/child_state.dart b/patterns/state/manipulator_state/states/selections/sub_states/child_state.dart index c1628c7..e6e965f 100644 --- a/patterns/state/manipulator_state/states/selections/sub_states/child_state.dart +++ b/patterns/state/manipulator_state/states/selections/sub_states/child_state.dart @@ -5,9 +5,10 @@ import 'package:flutter/services.dart'; import '../../../shapes/shape.dart'; import '../../../pattern/manipulation_context.dart'; import '../../mixins/hover_state_mixin.dart'; +import '../selection_state.dart'; abstract class ChildState extends ManipulationState with HoverStateMixin { - final ManipulationState parentState; + final SelectionState parentState; final Shape markerShape; final MouseCursor hoverCursor; diff --git a/patterns/state/manipulator_state/states/selections/sub_states/parent_state.dart b/patterns/state/manipulator_state/states/selections/sub_states/parent_state.dart index 6e12fff..1e002d3 100644 --- a/patterns/state/manipulator_state/states/selections/sub_states/parent_state.dart +++ b/patterns/state/manipulator_state/states/selections/sub_states/parent_state.dart @@ -4,7 +4,9 @@ import '../sub_states/child_state.dart'; import '../selection_state.dart'; class ParentState extends SelectionState { - ParentState({required super.selectedShape}); + ParentState({ + required super.selectedShape, + }); void addMarkers(List markers) { _markers.addAll(markers); @@ -44,11 +46,12 @@ class ParentState extends SelectionState { } } - void updateMarkersPosition() { + @override + void updateChildrenStates() { for (final marker in _markers) { marker.updatePosition(); } } - List _markers = []; + final _markers = []; } diff --git a/patterns/state/manipulator_state/states/selections/sub_states/top_right_marker_state.dart b/patterns/state/manipulator_state/states/selections/sub_states/top_right_marker_state.dart deleted file mode 100644 index 58d1ac9..0000000 --- a/patterns/state/manipulator_state/states/selections/sub_states/top_right_marker_state.dart +++ /dev/null @@ -1,25 +0,0 @@ -import 'package:flutter/rendering.dart'; - -import '../../../pattern/manipulation_context.dart'; -import '../../../shapes/marker_shape.dart'; -import 'child_state.dart'; - -class TopRightMarkerState extends ChildState { - TopRightMarkerState({ - required ManipulationState parentState, - }) : super( - parentState: parentState, - hoverCursor: SystemMouseCursors.resizeDownRight, - markerShape: MarkerShape(), - ); - - @override - void mouseMoveAction(double x, double y) { - - } - - @override - void updatePosition() { - - } -} From ab80bfcf711961e3bfaf526674e8b2d8e5c98673 Mon Sep 17 00:00:00 2001 From: ilopX Date: Thu, 26 May 2022 20:20:55 +0300 Subject: [PATCH 33/91] Add 'rect' property ru Shape. --- .../state/manipulator_state/app/shapes.dart | 13 +++------- patterns/state/manipulator_state/main.dart | 2 +- .../manipulator_state/shapes/base_shape.dart | 3 +++ .../shapes/circle_shape.dart | 24 +++++++++---------- .../shapes/marker_shape.dart | 13 ++++++---- .../state/manipulator_state/shapes/shape.dart | 2 ++ .../bottom_left_marker_state.dart | 3 ++- .../bottom_right_marker_state.dart | 5 ++-- .../states/selections/selection_state.dart | 7 +----- .../selections/sub_states/child_state.dart | 9 +------ 10 files changed, 35 insertions(+), 46 deletions(-) diff --git a/patterns/state/manipulator_state/app/shapes.dart b/patterns/state/manipulator_state/app/shapes.dart index 5bd8de7..29cdef7 100644 --- a/patterns/state/manipulator_state/app/shapes.dart +++ b/patterns/state/manipulator_state/app/shapes.dart @@ -6,9 +6,9 @@ import 'package:flutter/foundation.dart'; import '../shapes/shape.dart'; class Shapes with IterableMixin { - final List_shapes; + final List _shapes; - Shapes([this._shapes = const []]); + Shapes(List shapes) : _shapes = shapes; void add(Shape shape) { _shapes.add(shape); @@ -22,14 +22,7 @@ class Shapes with IterableMixin { Shape? findShapeByCoordinates(x, y) { for (final shape in _shapes) { - final shapeRect = Rect.fromLTWH( - shape.x, - shape.y, - shape.width, - shape.height, - ); - - if (shapeRect.contains(Offset(x, y))) { + if (shape.rect.contains(Offset(x, y))) { return shape; } } diff --git a/patterns/state/manipulator_state/main.dart b/patterns/state/manipulator_state/main.dart index 09105f3..fb64bdc 100644 --- a/patterns/state/manipulator_state/main.dart +++ b/patterns/state/manipulator_state/main.dart @@ -25,7 +25,7 @@ class _ManipulatorStateAppState extends State { @override void initState() { - final shapes = Shapes(); + final shapes = Shapes([]); app = App( shapes: shapes, manipulator: BaseManipulationContext( diff --git a/patterns/state/manipulator_state/shapes/base_shape.dart b/patterns/state/manipulator_state/shapes/base_shape.dart index 5938f15..540fbe1 100644 --- a/patterns/state/manipulator_state/shapes/base_shape.dart +++ b/patterns/state/manipulator_state/shapes/base_shape.dart @@ -22,6 +22,9 @@ class BaseShape implements Shape { @override double get width => _width; + @override + Rect get rect => Rect.fromLTWH(x, y, width, height); + @override SelectionState createSelectionState() { return SelectionState(selectedShape: this); diff --git a/patterns/state/manipulator_state/shapes/circle_shape.dart b/patterns/state/manipulator_state/shapes/circle_shape.dart index d8a1d9a..8aeb9f9 100644 --- a/patterns/state/manipulator_state/shapes/circle_shape.dart +++ b/patterns/state/manipulator_state/shapes/circle_shape.dart @@ -12,24 +12,24 @@ class CircleShape extends BaseShape { return CircleInnerRadiusState(selectedShape: this); } + @override + Rect get rect => Rect.fromLTWH(x, y, width, height); + @override void paint(Canvas canvas) { final w = width / 2; final h = height / 2; final path = Path() ..fillType = PathFillType.evenOdd - ..addOval(Rect.fromLTWH( - x, - y, - width, - height, - )) - ..addOval(Rect.fromLTWH( - x + w / 2, - y + h / 2, - w, - h, - )); + ..addOval(rect) + ..addOval( + Rect.fromLTWH( + x + w / 2, + y + h / 2, + w, + h, + ), + ); canvas.drawPath( path, Paint()..color = Colors.white, diff --git a/patterns/state/manipulator_state/shapes/marker_shape.dart b/patterns/state/manipulator_state/shapes/marker_shape.dart index 3ffaaa7..a29b609 100644 --- a/patterns/state/manipulator_state/shapes/marker_shape.dart +++ b/patterns/state/manipulator_state/shapes/marker_shape.dart @@ -3,23 +3,26 @@ import 'package:flutter/material.dart'; import 'base_shape.dart'; class MarkerShape extends BaseShape { - MarkerShape([super.x = 0, super.y = 0, super.width = 5, super.height = 5]); + MarkerShape([super.x = 0, super.y = 0, super.width = 5, super.height = -1]); + + @override + Rect get rect => Rect.fromLTWH(x - width, y - width, width * 2, width * 2); @override void paint(Canvas canvas) { - final point1 = Offset(x, y); + final point = Offset(x, y); - final paint1 = Paint() + final paint = Paint() ..style = PaintingStyle.fill ..color = Colors.black; - canvas.drawCircle(point1, width, paint1); + canvas.drawCircle(point, width, paint); final paint2 = Paint() ..style = PaintingStyle.stroke ..strokeWidth = 1.5 ..color = Colors.cyanAccent; - canvas.drawCircle(point1, width, paint2); + canvas.drawCircle(point, width, paint2); } } diff --git a/patterns/state/manipulator_state/shapes/shape.dart b/patterns/state/manipulator_state/shapes/shape.dart index 84b0d5a..4484439 100644 --- a/patterns/state/manipulator_state/shapes/shape.dart +++ b/patterns/state/manipulator_state/shapes/shape.dart @@ -11,6 +11,8 @@ abstract class Shape { double get height; + Rect get rect; + void move(double x, double y); void resize(double width, double height); diff --git a/patterns/state/manipulator_state/states/selections/resizable_state/bottom_left_marker_state.dart b/patterns/state/manipulator_state/states/selections/resizable_state/bottom_left_marker_state.dart index 71c23ee..f5f9801 100644 --- a/patterns/state/manipulator_state/states/selections/resizable_state/bottom_left_marker_state.dart +++ b/patterns/state/manipulator_state/states/selections/resizable_state/bottom_left_marker_state.dart @@ -17,7 +17,7 @@ class BottomLeftMarkerState extends ChildState { void mouseMoveAction(double x, double y) { final selectedShape = parentState.selectedShape; selectedShape.resize( - selectedShape.width +selectedShape.x - x, + selectedShape.width + selectedShape.x - x, y - selectedShape.y, ); selectedShape.move(x, selectedShape.y); @@ -30,6 +30,7 @@ class BottomLeftMarkerState extends ChildState { parentState.selectedShape.y + parentState.selectedShape.height, ); } + @override String toString() { return '${parentState.toString()} + Bottom Left Marker State'; diff --git a/patterns/state/manipulator_state/states/selections/resizable_state/bottom_right_marker_state.dart b/patterns/state/manipulator_state/states/selections/resizable_state/bottom_right_marker_state.dart index 350d700..d2d360f 100644 --- a/patterns/state/manipulator_state/states/selections/resizable_state/bottom_right_marker_state.dart +++ b/patterns/state/manipulator_state/states/selections/resizable_state/bottom_right_marker_state.dart @@ -17,17 +17,16 @@ class BottomRightMarkerState extends ChildState { void mouseMoveAction(double x, double y) { final selectedShape = parentState.selectedShape; selectedShape.resize( - x-selectedShape.x, + x - selectedShape.x, y - selectedShape.y, ); - } @override void updatePosition() { markerShape.move( parentState.selectedShape.x + parentState.selectedShape.width, - parentState.selectedShape.y+ parentState.selectedShape.height, + parentState.selectedShape.y + parentState.selectedShape.height, ); } diff --git a/patterns/state/manipulator_state/states/selections/selection_state.dart b/patterns/state/manipulator_state/states/selections/selection_state.dart index 9cb540c..b7eb9d7 100644 --- a/patterns/state/manipulator_state/states/selections/selection_state.dart +++ b/patterns/state/manipulator_state/states/selections/selection_state.dart @@ -21,12 +21,7 @@ class SelectionState extends FreeState { void paint(Canvas canvas) { super.paint(canvas); canvas.drawRect( - Rect.fromLTWH( - selectedShape.x + 1, - selectedShape.y + 1, - selectedShape.width - 2, - selectedShape.height - 2, - ), + selectedShape.rect.deflate(1), Paint() ..color = Colors.cyanAccent ..style = PaintingStyle.stroke diff --git a/patterns/state/manipulator_state/states/selections/sub_states/child_state.dart b/patterns/state/manipulator_state/states/selections/sub_states/child_state.dart index e6e965f..8f67d9e 100644 --- a/patterns/state/manipulator_state/states/selections/sub_states/child_state.dart +++ b/patterns/state/manipulator_state/states/selections/sub_states/child_state.dart @@ -77,14 +77,7 @@ abstract class ChildState extends ManipulationState with HoverStateMixin { @override Shape? findShapeByCoordinates(double x, double y) { - final rect = Rect.fromLTWH( - markerShape.x - markerShape.width, - markerShape.y - markerShape.width, - markerShape.width * 2, - markerShape.width * 2, - ); - - return rect.contains(Offset(x, y)) ? markerShape : null; + return markerShape.rect.contains(Offset(x, y)) ? markerShape : null; } bool get isDown => _isDown; From 104aa14ab0d2da6e31fdb84c2fbdd23222a423ed Mon Sep 17 00:00:00 2001 From: ilopX Date: Fri, 27 May 2022 01:38:55 +0300 Subject: [PATCH 34/91] Rename ManipulationContext to Manipulator. --- patterns/state/manipulator_state/app/app.dart | 4 ++-- ...base_manipulation_context.dart => base_manipulationt.dart} | 4 ++-- patterns/state/manipulator_state/app/tool.dart | 2 +- patterns/state/manipulator_state/main.dart | 4 ++-- .../state/manipulator_state/pattern/manipulation_state.dart | 4 ++-- .../pattern/{manipulation_context.dart => manipulator.dart} | 4 ++-- .../manipulator_state/states/creations/creation_state.dart | 2 +- patterns/state/manipulator_state/states/free_sate.dart | 2 +- .../manipulator_state/states/mixins/hover_state_mixin.dart | 2 +- .../states/selections/sub_states/child_state.dart | 4 ++-- patterns/state/manipulator_state/widgets/current_state.dart | 4 ++-- 11 files changed, 18 insertions(+), 18 deletions(-) rename patterns/state/manipulator_state/app/{base_manipulation_context.dart => base_manipulationt.dart} (92%) rename patterns/state/manipulator_state/pattern/{manipulation_context.dart => manipulator.dart} (86%) diff --git a/patterns/state/manipulator_state/app/app.dart b/patterns/state/manipulator_state/app/app.dart index e30cab2..2e754d1 100644 --- a/patterns/state/manipulator_state/app/app.dart +++ b/patterns/state/manipulator_state/app/app.dart @@ -1,10 +1,10 @@ -import '../pattern/manipulation_context.dart'; +import '../pattern/manipulator.dart'; import 'shapes.dart'; import 'tool.dart'; class App { final Shapes shapes; - final ManipulationContext manipulator; + final Manipulator manipulator; final List tools; App({ diff --git a/patterns/state/manipulator_state/app/base_manipulation_context.dart b/patterns/state/manipulator_state/app/base_manipulationt.dart similarity index 92% rename from patterns/state/manipulator_state/app/base_manipulation_context.dart rename to patterns/state/manipulator_state/app/base_manipulationt.dart index dda5ff6..50a4cee 100644 --- a/patterns/state/manipulator_state/app/base_manipulation_context.dart +++ b/patterns/state/manipulator_state/app/base_manipulationt.dart @@ -1,7 +1,7 @@ part of manipulator; -class BaseManipulationContext implements ManipulationContext { - BaseManipulationContext({ +class BaseManipulator implements Manipulator { + BaseManipulator({ required this.shapes, required ManipulationState initState, }) : _state = initState { diff --git a/patterns/state/manipulator_state/app/tool.dart b/patterns/state/manipulator_state/app/tool.dart index 4ff38a2..a3e7ca6 100644 --- a/patterns/state/manipulator_state/app/tool.dart +++ b/patterns/state/manipulator_state/app/tool.dart @@ -1,6 +1,6 @@ import 'package:flutter/widgets.dart'; -import '../pattern/manipulation_context.dart'; +import '../pattern/manipulator.dart'; class Tool { final Icon icon; diff --git a/patterns/state/manipulator_state/main.dart b/patterns/state/manipulator_state/main.dart index fb64bdc..0ca9a62 100644 --- a/patterns/state/manipulator_state/main.dart +++ b/patterns/state/manipulator_state/main.dart @@ -4,7 +4,7 @@ import 'package:material_design_icons_flutter/material_design_icons_flutter.dart import 'app/app.dart'; import 'app/shapes.dart'; import 'app/tool.dart'; -import 'pattern/manipulation_context.dart'; +import 'pattern/manipulator.dart'; import 'states/creations/circle_creation_state.dart'; import 'states/creations/rectangle_creation_state.dart'; import 'states/creations/text_creation_state.dart'; @@ -28,7 +28,7 @@ class _ManipulatorStateAppState extends State { final shapes = Shapes([]); app = App( shapes: shapes, - manipulator: BaseManipulationContext( + manipulator: BaseManipulator( initState: FreeState(), shapes: shapes, ), diff --git a/patterns/state/manipulator_state/pattern/manipulation_state.dart b/patterns/state/manipulator_state/pattern/manipulation_state.dart index 0a7ed80..c994333 100644 --- a/patterns/state/manipulator_state/pattern/manipulation_state.dart +++ b/patterns/state/manipulator_state/pattern/manipulation_state.dart @@ -1,7 +1,7 @@ part of manipulator; class ManipulationState { - ManipulationContext get context => _context!; + Manipulator get context => _context!; void mouseMove(double x, double y) {} @@ -15,5 +15,5 @@ class ManipulationState { void updateChildrenStates() {} - ManipulationContext? _context; + Manipulator? _context; } diff --git a/patterns/state/manipulator_state/pattern/manipulation_context.dart b/patterns/state/manipulator_state/pattern/manipulator.dart similarity index 86% rename from patterns/state/manipulator_state/pattern/manipulation_context.dart rename to patterns/state/manipulator_state/pattern/manipulator.dart index 2d195a6..14729d3 100644 --- a/patterns/state/manipulator_state/pattern/manipulation_context.dart +++ b/patterns/state/manipulator_state/pattern/manipulator.dart @@ -4,9 +4,9 @@ import 'package:flutter/material.dart'; import '../app/shapes.dart'; part 'manipulation_state.dart'; -part '../app/base_manipulation_context.dart'; +part '../app/base_manipulationt.dart'; -abstract class ManipulationContext { +abstract class Manipulator { Shapes get shapes; MouseCursor get cursor; diff --git a/patterns/state/manipulator_state/states/creations/creation_state.dart b/patterns/state/manipulator_state/states/creations/creation_state.dart index b29528d..58e4a52 100644 --- a/patterns/state/manipulator_state/states/creations/creation_state.dart +++ b/patterns/state/manipulator_state/states/creations/creation_state.dart @@ -1,6 +1,6 @@ import 'dart:ui'; -import '../../pattern/manipulation_context.dart'; +import '../../pattern/manipulator.dart'; import '../../shapes/shape.dart'; abstract class CreationState extends ManipulationState { diff --git a/patterns/state/manipulator_state/states/free_sate.dart b/patterns/state/manipulator_state/states/free_sate.dart index 6a48bb8..bcdd2ed 100644 --- a/patterns/state/manipulator_state/states/free_sate.dart +++ b/patterns/state/manipulator_state/states/free_sate.dart @@ -1,4 +1,4 @@ -import '../pattern/manipulation_context.dart'; +import '../pattern/manipulator.dart'; import 'mixins/hover_state_mixin.dart'; import 'selections/moving_state.dart'; diff --git a/patterns/state/manipulator_state/states/mixins/hover_state_mixin.dart b/patterns/state/manipulator_state/states/mixins/hover_state_mixin.dart index c3e7f6b..95482d9 100644 --- a/patterns/state/manipulator_state/states/mixins/hover_state_mixin.dart +++ b/patterns/state/manipulator_state/states/mixins/hover_state_mixin.dart @@ -1,6 +1,6 @@ import 'package:flutter/material.dart'; -import '../../pattern/manipulation_context.dart'; +import '../../pattern/manipulator.dart'; import '../../shapes/shape.dart'; mixin HoverStateMixin implements ManipulationState { diff --git a/patterns/state/manipulator_state/states/selections/sub_states/child_state.dart b/patterns/state/manipulator_state/states/selections/sub_states/child_state.dart index 8f67d9e..e781df9 100644 --- a/patterns/state/manipulator_state/states/selections/sub_states/child_state.dart +++ b/patterns/state/manipulator_state/states/selections/sub_states/child_state.dart @@ -3,7 +3,7 @@ import 'dart:ui'; import 'package:flutter/services.dart'; import '../../../shapes/shape.dart'; -import '../../../pattern/manipulation_context.dart'; +import '../../../pattern/manipulator.dart'; import '../../mixins/hover_state_mixin.dart'; import '../selection_state.dart'; @@ -73,7 +73,7 @@ abstract class ChildState extends ManipulationState with HoverStateMixin { } @override - ManipulationContext get context => parentState.context; + Manipulator get context => parentState.context; @override Shape? findShapeByCoordinates(double x, double y) { diff --git a/patterns/state/manipulator_state/widgets/current_state.dart b/patterns/state/manipulator_state/widgets/current_state.dart index 79b0a2f..c319bce 100644 --- a/patterns/state/manipulator_state/widgets/current_state.dart +++ b/patterns/state/manipulator_state/widgets/current_state.dart @@ -2,10 +2,10 @@ import 'package:flutter/material.dart'; import '../../../abstract_factory/tool_panel_factory/widgets/independent/event_listenable_builder.dart'; import '../../../abstract_factory/tool_panel_factory/widgets/independent/panel.dart'; -import '../pattern/manipulation_context.dart'; +import '../pattern/manipulator.dart'; class CurrentState extends StatelessWidget { - final ManipulationContext manipulator; + final Manipulator manipulator; const CurrentState({ Key? key, From bfbca6ac6d404c24dc63badbb33d259941d956aa Mon Sep 17 00:00:00 2001 From: ilopX Date: Fri, 27 May 2022 02:00:45 +0300 Subject: [PATCH 35/91] Rename HoverStateMixin to HoverShape. --- patterns/state/manipulator_state/states/free_sate.dart | 4 ++-- .../mixins/{hover_state_mixin.dart => hover_shape.dart} | 2 +- .../states/selections/sub_states/child_state.dart | 4 ++-- 3 files changed, 5 insertions(+), 5 deletions(-) rename patterns/state/manipulator_state/states/mixins/{hover_state_mixin.dart => hover_shape.dart} (95%) diff --git a/patterns/state/manipulator_state/states/free_sate.dart b/patterns/state/manipulator_state/states/free_sate.dart index bcdd2ed..0e186da 100644 --- a/patterns/state/manipulator_state/states/free_sate.dart +++ b/patterns/state/manipulator_state/states/free_sate.dart @@ -1,8 +1,8 @@ import '../pattern/manipulator.dart'; -import 'mixins/hover_state_mixin.dart'; +import 'mixins/hover_shape.dart'; import 'selections/moving_state.dart'; -class FreeState extends ManipulationState with HoverStateMixin { +class FreeState extends ManipulationState with HoverShape { @override void mouseDown(double x, double y) { trySelectAndStartMovingShape(x, y); diff --git a/patterns/state/manipulator_state/states/mixins/hover_state_mixin.dart b/patterns/state/manipulator_state/states/mixins/hover_shape.dart similarity index 95% rename from patterns/state/manipulator_state/states/mixins/hover_state_mixin.dart rename to patterns/state/manipulator_state/states/mixins/hover_shape.dart index 95482d9..2091a25 100644 --- a/patterns/state/manipulator_state/states/mixins/hover_state_mixin.dart +++ b/patterns/state/manipulator_state/states/mixins/hover_shape.dart @@ -3,7 +3,7 @@ import 'package:flutter/material.dart'; import '../../pattern/manipulator.dart'; import '../../shapes/shape.dart'; -mixin HoverStateMixin implements ManipulationState { +mixin HoverShape implements ManipulationState { Shape? findShapeByCoordinates(double x, double y) { return context.shapes.findShapeByCoordinates(x, y); } diff --git a/patterns/state/manipulator_state/states/selections/sub_states/child_state.dart b/patterns/state/manipulator_state/states/selections/sub_states/child_state.dart index e781df9..7ce59eb 100644 --- a/patterns/state/manipulator_state/states/selections/sub_states/child_state.dart +++ b/patterns/state/manipulator_state/states/selections/sub_states/child_state.dart @@ -4,10 +4,10 @@ import 'package:flutter/services.dart'; import '../../../shapes/shape.dart'; import '../../../pattern/manipulator.dart'; -import '../../mixins/hover_state_mixin.dart'; +import '../../mixins/hover_shape.dart'; import '../selection_state.dart'; -abstract class ChildState extends ManipulationState with HoverStateMixin { +abstract class ChildState extends ManipulationState with HoverShape { final SelectionState parentState; final Shape markerShape; final MouseCursor hoverCursor; From 6abe57223fae1e8eff7b99a8b46d777e5315ae61 Mon Sep 17 00:00:00 2001 From: ilopX Date: Fri, 27 May 2022 02:19:27 +0300 Subject: [PATCH 36/91] Rename HoverStateMixin to HoverShapeMixin. --- patterns/state/manipulator_state/states/free_sate.dart | 10 ++++------ .../{hover_shape.dart => hover_shape_mixin.dart} | 9 ++++----- .../states/selections/sub_states/child_state.dart | 4 ++-- 3 files changed, 10 insertions(+), 13 deletions(-) rename patterns/state/manipulator_state/states/mixins/{hover_shape.dart => hover_shape_mixin.dart} (86%) diff --git a/patterns/state/manipulator_state/states/free_sate.dart b/patterns/state/manipulator_state/states/free_sate.dart index 0e186da..aefd865 100644 --- a/patterns/state/manipulator_state/states/free_sate.dart +++ b/patterns/state/manipulator_state/states/free_sate.dart @@ -1,17 +1,15 @@ import '../pattern/manipulator.dart'; -import 'mixins/hover_shape.dart'; +import 'mixins/hover_shape_mixin.dart'; import 'selections/moving_state.dart'; -class FreeState extends ManipulationState with HoverShape { +class FreeState extends ManipulationState with HoverShapeMixin { @override void mouseDown(double x, double y) { trySelectAndStartMovingShape(x, y); } bool trySelectAndStartMovingShape(double x, double y) { - final shape = context.shapes.findShapeByCoordinates(x, y); - - if (shape == null) { + if (hoverShape == null) { return false; } @@ -19,7 +17,7 @@ class FreeState extends ManipulationState with HoverShape { MovingState( startX: x, startY: y, - selectedShape: shape, + selectedShape: hoverShape!, ), ); diff --git a/patterns/state/manipulator_state/states/mixins/hover_shape.dart b/patterns/state/manipulator_state/states/mixins/hover_shape_mixin.dart similarity index 86% rename from patterns/state/manipulator_state/states/mixins/hover_shape.dart rename to patterns/state/manipulator_state/states/mixins/hover_shape_mixin.dart index 2091a25..b322b05 100644 --- a/patterns/state/manipulator_state/states/mixins/hover_shape.dart +++ b/patterns/state/manipulator_state/states/mixins/hover_shape_mixin.dart @@ -3,12 +3,14 @@ import 'package:flutter/material.dart'; import '../../pattern/manipulator.dart'; import '../../shapes/shape.dart'; -mixin HoverShape implements ManipulationState { +mixin HoverShapeMixin implements ManipulationState { Shape? findShapeByCoordinates(double x, double y) { return context.shapes.findShapeByCoordinates(x, y); } - bool get isHover => _isHover; + Shape? get hoverShape => _hoverShape; + + bool get isHover => _hoverShape != null; @override void mouseMove(double x, double y) { @@ -21,10 +23,8 @@ mixin HoverShape implements ManipulationState { _hoverShape = newHover; if (newHover == null) { - _isHover = false; onMouseLeave(); } else { - _isHover = true; onHover(); } @@ -56,5 +56,4 @@ mixin HoverShape implements ManipulationState { } Shape? _hoverShape; - bool _isHover = false; } diff --git a/patterns/state/manipulator_state/states/selections/sub_states/child_state.dart b/patterns/state/manipulator_state/states/selections/sub_states/child_state.dart index 7ce59eb..ab85642 100644 --- a/patterns/state/manipulator_state/states/selections/sub_states/child_state.dart +++ b/patterns/state/manipulator_state/states/selections/sub_states/child_state.dart @@ -4,10 +4,10 @@ import 'package:flutter/services.dart'; import '../../../shapes/shape.dart'; import '../../../pattern/manipulator.dart'; -import '../../mixins/hover_shape.dart'; +import '../../mixins/hover_shape_mixin.dart'; import '../selection_state.dart'; -abstract class ChildState extends ManipulationState with HoverShape { +abstract class ChildState extends ManipulationState with HoverShapeMixin { final SelectionState parentState; final Shape markerShape; final MouseCursor hoverCursor; From 0e579fc858391680b95d22ee5872c12222849dd4 Mon Sep 17 00:00:00 2001 From: ilopX Date: Fri, 27 May 2022 03:09:56 +0300 Subject: [PATCH 37/91] Add PaintStyle. --- .../app/base_manipulationt.dart | 6 ++- patterns/state/manipulator_state/main.dart | 2 + .../pattern/manipulation_state.dart | 2 +- .../pattern/manipulator.dart | 5 ++- .../shapes/marker_shape.dart | 17 +-------- .../states/mixins/hover_shape_mixin.dart | 13 +------ .../states/mixins/paint_style.dart | 38 +++++++++++++++++++ .../bottom_left_marker_state.dart | 4 +- .../bottom_right_marker_state.dart | 4 +- .../top_left_marker_state.dart | 4 +- .../top_right_marker_state.dart | 4 +- .../states/selections/selection_state.dart | 8 +--- .../selections/sub_states/child_state.dart | 12 ++---- .../selections/sub_states/parent_state.dart | 4 +- 14 files changed, 67 insertions(+), 56 deletions(-) create mode 100644 patterns/state/manipulator_state/states/mixins/paint_style.dart diff --git a/patterns/state/manipulator_state/app/base_manipulationt.dart b/patterns/state/manipulator_state/app/base_manipulationt.dart index 50a4cee..3a04e28 100644 --- a/patterns/state/manipulator_state/app/base_manipulationt.dart +++ b/patterns/state/manipulator_state/app/base_manipulationt.dart @@ -4,10 +4,14 @@ class BaseManipulator implements Manipulator { BaseManipulator({ required this.shapes, required ManipulationState initState, + required this.paintStyle, }) : _state = initState { _state._context = this; } + @override + ManipulationState get state => _state; + @override final Shapes shapes; @@ -21,7 +25,7 @@ class BaseManipulator implements Manipulator { var cursor = MouseCursor.defer; @override - ManipulationState get state => _state; + final PaintStyle paintStyle; @override void changeState(ManipulationState newState) { diff --git a/patterns/state/manipulator_state/main.dart b/patterns/state/manipulator_state/main.dart index 0ca9a62..d564ea1 100644 --- a/patterns/state/manipulator_state/main.dart +++ b/patterns/state/manipulator_state/main.dart @@ -9,6 +9,7 @@ import 'states/creations/circle_creation_state.dart'; import 'states/creations/rectangle_creation_state.dart'; import 'states/creations/text_creation_state.dart'; import 'states/free_sate.dart'; +import 'states/mixins/paint_style.dart'; import 'widgets/current_state.dart'; import 'widgets/drawing_board.dart'; import 'widgets/tool_bar.dart'; @@ -31,6 +32,7 @@ class _ManipulatorStateAppState extends State { manipulator: BaseManipulator( initState: FreeState(), shapes: shapes, + paintStyle: PaintStyle(Colors.pink), ), tools: [ Tool( diff --git a/patterns/state/manipulator_state/pattern/manipulation_state.dart b/patterns/state/manipulator_state/pattern/manipulation_state.dart index c994333..268513e 100644 --- a/patterns/state/manipulator_state/pattern/manipulation_state.dart +++ b/patterns/state/manipulator_state/pattern/manipulation_state.dart @@ -13,7 +13,7 @@ class ManipulationState { void paint(Canvas canvas) {} - void updateChildrenStates() {} + void updateMarkers() {} Manipulator? _context; } diff --git a/patterns/state/manipulator_state/pattern/manipulator.dart b/patterns/state/manipulator_state/pattern/manipulator.dart index 14729d3..5a9e829 100644 --- a/patterns/state/manipulator_state/pattern/manipulator.dart +++ b/patterns/state/manipulator_state/pattern/manipulator.dart @@ -2,18 +2,21 @@ library manipulator; import 'package:flutter/material.dart'; import '../app/shapes.dart'; +import '../states/mixins/paint_style.dart'; part 'manipulation_state.dart'; part '../app/base_manipulationt.dart'; abstract class Manipulator { + ManipulationState get state; + Shapes get shapes; MouseCursor get cursor; set cursor(MouseCursor cursor); - ManipulationState get state; + PaintStyle get paintStyle; Event get onStateChange; diff --git a/patterns/state/manipulator_state/shapes/marker_shape.dart b/patterns/state/manipulator_state/shapes/marker_shape.dart index a29b609..40d95a0 100644 --- a/patterns/state/manipulator_state/shapes/marker_shape.dart +++ b/patterns/state/manipulator_state/shapes/marker_shape.dart @@ -9,20 +9,5 @@ class MarkerShape extends BaseShape { Rect get rect => Rect.fromLTWH(x - width, y - width, width * 2, width * 2); @override - void paint(Canvas canvas) { - final point = Offset(x, y); - - final paint = Paint() - ..style = PaintingStyle.fill - ..color = Colors.black; - - canvas.drawCircle(point, width, paint); - - final paint2 = Paint() - ..style = PaintingStyle.stroke - ..strokeWidth = 1.5 - ..color = Colors.cyanAccent; - - canvas.drawCircle(point, width, paint2); - } + void paint(Canvas canvas) {} } diff --git a/patterns/state/manipulator_state/states/mixins/hover_shape_mixin.dart b/patterns/state/manipulator_state/states/mixins/hover_shape_mixin.dart index b322b05..98fc887 100644 --- a/patterns/state/manipulator_state/states/mixins/hover_shape_mixin.dart +++ b/patterns/state/manipulator_state/states/mixins/hover_shape_mixin.dart @@ -41,18 +41,7 @@ mixin HoverShapeMixin implements ManipulationState { return; } - canvas.drawRect( - Rect.fromLTWH( - _hoverShape!.x + 1, - _hoverShape!.y + 1, - _hoverShape!.width - 2, - _hoverShape!.height - 2, - ), - Paint() - ..color = Colors.cyanAccent - ..style = PaintingStyle.stroke - ..strokeWidth = 2.0, - ); + context.paintStyle.paintHover(canvas, _hoverShape!); } Shape? _hoverShape; diff --git a/patterns/state/manipulator_state/states/mixins/paint_style.dart b/patterns/state/manipulator_state/states/mixins/paint_style.dart new file mode 100644 index 0000000..db0c95c --- /dev/null +++ b/patterns/state/manipulator_state/states/mixins/paint_style.dart @@ -0,0 +1,38 @@ +import 'dart:ui'; + +import 'package:flutter/material.dart'; + +import '../../shapes/shape.dart'; + +class PaintStyle { + PaintStyle(this.color); + + final Color color; + + void paintHover(Canvas canvas, Shape shape) { + canvas.drawRect( + shape.rect.deflate(1), + Paint() + ..color = color + ..style = PaintingStyle.stroke + ..strokeWidth = 2.0, + ); + } + + void paintMarker(Canvas canvas, Shape shape) { + final point = Offset(shape.x, shape.y); + + final paint = Paint() + ..style = PaintingStyle.fill + ..color = Colors.black; + + canvas.drawCircle(point, shape.width, paint); + + final paint2 = Paint() + ..style = PaintingStyle.stroke + ..strokeWidth = 1.5 + ..color = color; + + canvas.drawCircle(point, shape.width, paint2); + } +} diff --git a/patterns/state/manipulator_state/states/selections/resizable_state/bottom_left_marker_state.dart b/patterns/state/manipulator_state/states/selections/resizable_state/bottom_left_marker_state.dart index f5f9801..6ef69a7 100644 --- a/patterns/state/manipulator_state/states/selections/resizable_state/bottom_left_marker_state.dart +++ b/patterns/state/manipulator_state/states/selections/resizable_state/bottom_left_marker_state.dart @@ -10,7 +10,7 @@ class BottomLeftMarkerState extends ChildState { }) : super( parentState: parentState, hoverCursor: SystemMouseCursors.resizeDownLeft, - markerShape: MarkerShape(), + shape: MarkerShape(), ); @override @@ -25,7 +25,7 @@ class BottomLeftMarkerState extends ChildState { @override void updatePosition() { - markerShape.move( + shape.move( parentState.selectedShape.x, parentState.selectedShape.y + parentState.selectedShape.height, ); diff --git a/patterns/state/manipulator_state/states/selections/resizable_state/bottom_right_marker_state.dart b/patterns/state/manipulator_state/states/selections/resizable_state/bottom_right_marker_state.dart index d2d360f..312cf8e 100644 --- a/patterns/state/manipulator_state/states/selections/resizable_state/bottom_right_marker_state.dart +++ b/patterns/state/manipulator_state/states/selections/resizable_state/bottom_right_marker_state.dart @@ -10,7 +10,7 @@ class BottomRightMarkerState extends ChildState { }) : super( parentState: parentState, hoverCursor: SystemMouseCursors.resizeDownRight, - markerShape: MarkerShape(), + shape: MarkerShape(), ); @override @@ -24,7 +24,7 @@ class BottomRightMarkerState extends ChildState { @override void updatePosition() { - markerShape.move( + shape.move( parentState.selectedShape.x + parentState.selectedShape.width, parentState.selectedShape.y + parentState.selectedShape.height, ); diff --git a/patterns/state/manipulator_state/states/selections/resizable_state/top_left_marker_state.dart b/patterns/state/manipulator_state/states/selections/resizable_state/top_left_marker_state.dart index 63e5671..cee7428 100644 --- a/patterns/state/manipulator_state/states/selections/resizable_state/top_left_marker_state.dart +++ b/patterns/state/manipulator_state/states/selections/resizable_state/top_left_marker_state.dart @@ -10,7 +10,7 @@ class TopLeftMarkerState extends ChildState { }) : super( parentState: parentState, hoverCursor: SystemMouseCursors.resizeDownRight, - markerShape: MarkerShape(), + shape: MarkerShape(), ); @override @@ -24,7 +24,7 @@ class TopLeftMarkerState extends ChildState { @override void updatePosition() { - markerShape.move(parentState.selectedShape.x, parentState.selectedShape.y); + shape.move(parentState.selectedShape.x, parentState.selectedShape.y); } @override diff --git a/patterns/state/manipulator_state/states/selections/resizable_state/top_right_marker_state.dart b/patterns/state/manipulator_state/states/selections/resizable_state/top_right_marker_state.dart index 74d3399..d9b4021 100644 --- a/patterns/state/manipulator_state/states/selections/resizable_state/top_right_marker_state.dart +++ b/patterns/state/manipulator_state/states/selections/resizable_state/top_right_marker_state.dart @@ -10,7 +10,7 @@ class TopRightMarkerState extends ChildState { }) : super( parentState: parentState, hoverCursor: SystemMouseCursors.resizeUpRight, - markerShape: MarkerShape(), + shape: MarkerShape(), ); @override @@ -25,7 +25,7 @@ class TopRightMarkerState extends ChildState { @override void updatePosition() { - markerShape.move( + shape.move( parentState.selectedShape.x + parentState.selectedShape.width, parentState.selectedShape.y, ); diff --git a/patterns/state/manipulator_state/states/selections/selection_state.dart b/patterns/state/manipulator_state/states/selections/selection_state.dart index b7eb9d7..02dc815 100644 --- a/patterns/state/manipulator_state/states/selections/selection_state.dart +++ b/patterns/state/manipulator_state/states/selections/selection_state.dart @@ -20,13 +20,7 @@ class SelectionState extends FreeState { @override void paint(Canvas canvas) { super.paint(canvas); - canvas.drawRect( - selectedShape.rect.deflate(1), - Paint() - ..color = Colors.cyanAccent - ..style = PaintingStyle.stroke - ..strokeWidth = 2.0, - ); + context.paintStyle.paintHover(canvas, selectedShape); } @override diff --git a/patterns/state/manipulator_state/states/selections/sub_states/child_state.dart b/patterns/state/manipulator_state/states/selections/sub_states/child_state.dart index ab85642..f02a5c3 100644 --- a/patterns/state/manipulator_state/states/selections/sub_states/child_state.dart +++ b/patterns/state/manipulator_state/states/selections/sub_states/child_state.dart @@ -9,12 +9,12 @@ import '../selection_state.dart'; abstract class ChildState extends ManipulationState with HoverShapeMixin { final SelectionState parentState; - final Shape markerShape; + final Shape shape; final MouseCursor hoverCursor; ChildState({ required this.parentState, - required this.markerShape, + required this.shape, this.hoverCursor = SystemMouseCursors.basic, }) { updatePosition(); @@ -24,10 +24,6 @@ abstract class ChildState extends ManipulationState with HoverShapeMixin { void mouseMoveAction(double x, double y); - void render(Canvas canvas) { - markerShape.paint(canvas); - } - @override void onHover() { context.cursor = hoverCursor; @@ -50,7 +46,7 @@ abstract class ChildState extends ManipulationState with HoverShapeMixin { super.mouseMove(x, y); if (_isDown) { mouseMoveAction(x, y); - parentState.updateChildrenStates(); + parentState.updateMarkers(); context.update(); } } @@ -77,7 +73,7 @@ abstract class ChildState extends ManipulationState with HoverShapeMixin { @override Shape? findShapeByCoordinates(double x, double y) { - return markerShape.rect.contains(Offset(x, y)) ? markerShape : null; + return shape.rect.contains(Offset(x, y)) ? shape : null; } bool get isDown => _isDown; diff --git a/patterns/state/manipulator_state/states/selections/sub_states/parent_state.dart b/patterns/state/manipulator_state/states/selections/sub_states/parent_state.dart index 1e002d3..8c73b9b 100644 --- a/patterns/state/manipulator_state/states/selections/sub_states/parent_state.dart +++ b/patterns/state/manipulator_state/states/selections/sub_states/parent_state.dart @@ -42,12 +42,12 @@ class ParentState extends SelectionState { super.paint(canvas); for (final marker in _markers) { - marker.render(canvas); + context.paintStyle.paintMarker(canvas, marker.shape); } } @override - void updateChildrenStates() { + void updateMarkers() { for (final marker in _markers) { marker.updatePosition(); } From 7670a5efea760170dd62ed8b531fd511124b5ed3 Mon Sep 17 00:00:00 2001 From: ilopX Date: Fri, 27 May 2022 17:23:33 +0300 Subject: [PATCH 38/91] Fix cursor in corner markers. --- .../pattern/manipulation_state.dart | 4 +- .../manipulator_state/shapes/base_shape.dart | 7 ++- .../states/mixins/paint_style.dart | 47 +++++++++++-------- .../bottom_left_marker_state.dart | 16 ++----- .../bottom_right_marker_state.dart | 27 ++++------- .../top_left_marker_state.dart | 16 ++----- .../top_right_marker_state.dart | 17 ++----- .../selections/sub_states/child_state.dart | 10 ++-- 8 files changed, 62 insertions(+), 82 deletions(-) diff --git a/patterns/state/manipulator_state/pattern/manipulation_state.dart b/patterns/state/manipulator_state/pattern/manipulation_state.dart index 268513e..bd52909 100644 --- a/patterns/state/manipulator_state/pattern/manipulation_state.dart +++ b/patterns/state/manipulator_state/pattern/manipulation_state.dart @@ -1,7 +1,7 @@ part of manipulator; class ManipulationState { - Manipulator get context => _context!; + Manipulator get context => _context; void mouseMove(double x, double y) {} @@ -15,5 +15,5 @@ class ManipulationState { void updateMarkers() {} - Manipulator? _context; + late Manipulator _context; } diff --git a/patterns/state/manipulator_state/shapes/base_shape.dart b/patterns/state/manipulator_state/shapes/base_shape.dart index 540fbe1..9395fca 100644 --- a/patterns/state/manipulator_state/shapes/base_shape.dart +++ b/patterns/state/manipulator_state/shapes/base_shape.dart @@ -23,7 +23,12 @@ class BaseShape implements Shape { double get width => _width; @override - Rect get rect => Rect.fromLTWH(x, y, width, height); + Rect get rect => Rect.fromLTWH( + _width < 0 ? x + _width : x, + _height < 0 ? y + _height : y, + _width.abs(), + _height.abs(), + ); @override SelectionState createSelectionState() { diff --git a/patterns/state/manipulator_state/states/mixins/paint_style.dart b/patterns/state/manipulator_state/states/mixins/paint_style.dart index db0c95c..624a338 100644 --- a/patterns/state/manipulator_state/states/mixins/paint_style.dart +++ b/patterns/state/manipulator_state/states/mixins/paint_style.dart @@ -1,38 +1,45 @@ -import 'dart:ui'; - import 'package:flutter/material.dart'; import '../../shapes/shape.dart'; class PaintStyle { - PaintStyle(this.color); + PaintStyle(this.color) + : _selectStroke = Paint() + ..color = color + ..style = PaintingStyle.stroke + ..strokeWidth = 2.0, + _markerStroke = Paint() + ..color = color + ..style = PaintingStyle.stroke + ..strokeWidth = 1.5, + _markerFill = Paint() + ..style = PaintingStyle.fill + ..color = Colors.black; final Color color; void paintHover(Canvas canvas, Shape shape) { canvas.drawRect( shape.rect.deflate(1), - Paint() - ..color = color - ..style = PaintingStyle.stroke - ..strokeWidth = 2.0, + _selectStroke, ); } void paintMarker(Canvas canvas, Shape shape) { final point = Offset(shape.x, shape.y); - - final paint = Paint() - ..style = PaintingStyle.fill - ..color = Colors.black; - - canvas.drawCircle(point, shape.width, paint); - - final paint2 = Paint() - ..style = PaintingStyle.stroke - ..strokeWidth = 1.5 - ..color = color; - - canvas.drawCircle(point, shape.width, paint2); + canvas.drawCircle( + point, + shape.width, + _markerFill, + ); + canvas.drawCircle( + point, + shape.width, + _markerStroke, + ); } + + final Paint _selectStroke; + final Paint _markerStroke; + final Paint _markerFill; } diff --git a/patterns/state/manipulator_state/states/selections/resizable_state/bottom_left_marker_state.dart b/patterns/state/manipulator_state/states/selections/resizable_state/bottom_left_marker_state.dart index 6ef69a7..a58d3bb 100644 --- a/patterns/state/manipulator_state/states/selections/resizable_state/bottom_left_marker_state.dart +++ b/patterns/state/manipulator_state/states/selections/resizable_state/bottom_left_marker_state.dart @@ -1,17 +1,9 @@ -import 'package:flutter/rendering.dart'; +import 'corner_marker.dart'; -import '../../../shapes/marker_shape.dart'; -import '../selection_state.dart'; -import '../sub_states/child_state.dart'; - -class BottomLeftMarkerState extends ChildState { +class BottomLeftMarkerState extends CornerMarker { BottomLeftMarkerState({ - required SelectionState parentState, - }) : super( - parentState: parentState, - hoverCursor: SystemMouseCursors.resizeDownLeft, - shape: MarkerShape(), - ); + required super.parentState, + }); @override void mouseMoveAction(double x, double y) { diff --git a/patterns/state/manipulator_state/states/selections/resizable_state/bottom_right_marker_state.dart b/patterns/state/manipulator_state/states/selections/resizable_state/bottom_right_marker_state.dart index 312cf8e..7923545 100644 --- a/patterns/state/manipulator_state/states/selections/resizable_state/bottom_right_marker_state.dart +++ b/patterns/state/manipulator_state/states/selections/resizable_state/bottom_right_marker_state.dart @@ -1,31 +1,24 @@ -import 'package:flutter/rendering.dart'; +import 'corner_marker.dart'; -import '../../../shapes/marker_shape.dart'; -import '../selection_state.dart'; -import '../sub_states/child_state.dart'; - -class BottomRightMarkerState extends ChildState { +class BottomRightMarkerState extends CornerMarker { BottomRightMarkerState({ - required SelectionState parentState, - }) : super( - parentState: parentState, - hoverCursor: SystemMouseCursors.resizeDownRight, - shape: MarkerShape(), - ); + required super.parentState, + }); @override void mouseMoveAction(double x, double y) { - final selectedShape = parentState.selectedShape; - selectedShape.resize( - x - selectedShape.x, - y - selectedShape.y, + final parentShape = parentState.selectedShape; + parentShape.resize( + x - parentShape.x, + y - parentShape.y, ); } @override void updatePosition() { + final parentShape = parentState.selectedShape; shape.move( - parentState.selectedShape.x + parentState.selectedShape.width, + parentShape.x + parentState.selectedShape.width, parentState.selectedShape.y + parentState.selectedShape.height, ); } diff --git a/patterns/state/manipulator_state/states/selections/resizable_state/top_left_marker_state.dart b/patterns/state/manipulator_state/states/selections/resizable_state/top_left_marker_state.dart index cee7428..7574327 100644 --- a/patterns/state/manipulator_state/states/selections/resizable_state/top_left_marker_state.dart +++ b/patterns/state/manipulator_state/states/selections/resizable_state/top_left_marker_state.dart @@ -1,17 +1,9 @@ -import 'package:flutter/rendering.dart'; +import 'corner_marker.dart'; -import '../../../shapes/marker_shape.dart'; -import '../selection_state.dart'; -import '../sub_states/child_state.dart'; - -class TopLeftMarkerState extends ChildState { +class TopLeftMarkerState extends CornerMarker { TopLeftMarkerState({ - required SelectionState parentState, - }) : super( - parentState: parentState, - hoverCursor: SystemMouseCursors.resizeDownRight, - shape: MarkerShape(), - ); + required super.parentState, + }); @override void mouseMoveAction(double x, double y) { diff --git a/patterns/state/manipulator_state/states/selections/resizable_state/top_right_marker_state.dart b/patterns/state/manipulator_state/states/selections/resizable_state/top_right_marker_state.dart index d9b4021..6d56aaf 100644 --- a/patterns/state/manipulator_state/states/selections/resizable_state/top_right_marker_state.dart +++ b/patterns/state/manipulator_state/states/selections/resizable_state/top_right_marker_state.dart @@ -1,18 +1,9 @@ -import 'package:flutter/rendering.dart'; +import 'corner_marker.dart'; -import '../../../shapes/marker_shape.dart'; -import '../selection_state.dart'; -import '../sub_states/child_state.dart'; - -class TopRightMarkerState extends ChildState { +class TopRightMarkerState extends CornerMarker { TopRightMarkerState({ - required SelectionState parentState, - }) : super( - parentState: parentState, - hoverCursor: SystemMouseCursors.resizeUpRight, - shape: MarkerShape(), - ); - + required super.parentState, + }); @override void mouseMoveAction(double x, double y) { final selectedShape = parentState.selectedShape; diff --git a/patterns/state/manipulator_state/states/selections/sub_states/child_state.dart b/patterns/state/manipulator_state/states/selections/sub_states/child_state.dart index f02a5c3..3ce2bb6 100644 --- a/patterns/state/manipulator_state/states/selections/sub_states/child_state.dart +++ b/patterns/state/manipulator_state/states/selections/sub_states/child_state.dart @@ -10,12 +10,12 @@ import '../selection_state.dart'; abstract class ChildState extends ManipulationState with HoverShapeMixin { final SelectionState parentState; final Shape shape; - final MouseCursor hoverCursor; + + MouseCursor get hoverCursor; ChildState({ required this.parentState, required this.shape, - this.hoverCursor = SystemMouseCursors.basic, }) { updatePosition(); } @@ -47,6 +47,7 @@ abstract class ChildState extends ManipulationState with HoverShapeMixin { if (_isDown) { mouseMoveAction(x, y); parentState.updateMarkers(); + context.cursor = hoverCursor; context.update(); } } @@ -57,9 +58,8 @@ abstract class ChildState extends ManipulationState with HoverShapeMixin { return; } - context.changeState( - parentState, - ); + context.changeState(parentState); + _isDown = false; } From f348d148022040d520d90e39d1c3968eeda343b6 Mon Sep 17 00:00:00 2001 From: ilopX Date: Fri, 27 May 2022 17:23:44 +0300 Subject: [PATCH 39/91] Fix cursor in corner markers. --- .../resizable_state/corner_marker.dart | 32 +++++++++++++++++++ 1 file changed, 32 insertions(+) create mode 100644 patterns/state/manipulator_state/states/selections/resizable_state/corner_marker.dart diff --git a/patterns/state/manipulator_state/states/selections/resizable_state/corner_marker.dart b/patterns/state/manipulator_state/states/selections/resizable_state/corner_marker.dart new file mode 100644 index 0000000..e1dd87b --- /dev/null +++ b/patterns/state/manipulator_state/states/selections/resizable_state/corner_marker.dart @@ -0,0 +1,32 @@ +import 'package:flutter/rendering.dart'; + +import '../../../shapes/marker_shape.dart'; +import '../selection_state.dart'; +import '../sub_states/child_state.dart'; + +abstract class CornerMarker extends ChildState { + CornerMarker({ + required SelectionState parentState, + }) : super( + parentState: parentState, + shape: MarkerShape(), + ); + + @override + MouseCursor get hoverCursor { + final rect = parentState.selectedShape.rect; + final corner = Offset(shape.x, shape.y); + + if (corner == rect.topLeft) { + return SystemMouseCursors.resizeUpLeft; + } else if (corner == rect.topRight) { + return SystemMouseCursors.resizeUpRight; + } else if (corner == rect.bottomLeft) { + return SystemMouseCursors.resizeDownLeft; + } else if (corner == rect.bottomRight) { + return SystemMouseCursors.resizeDownRight; + } + + return SystemMouseCursors.move; + } +} From 8d58f622720338221a62ec8730ef89ec508ce979 Mon Sep 17 00:00:00 2001 From: ilopX Date: Fri, 27 May 2022 17:27:05 +0300 Subject: [PATCH 40/91] Rename mouseMoveAction to mouseDragAction. --- .../selections/resizable_state/bottom_left_marker_state.dart | 2 +- .../selections/resizable_state/bottom_right_marker_state.dart | 2 +- .../selections/resizable_state/top_left_marker_state.dart | 2 +- .../selections/resizable_state/top_right_marker_state.dart | 2 +- .../states/selections/sub_states/child_state.dart | 4 ++-- 5 files changed, 6 insertions(+), 6 deletions(-) diff --git a/patterns/state/manipulator_state/states/selections/resizable_state/bottom_left_marker_state.dart b/patterns/state/manipulator_state/states/selections/resizable_state/bottom_left_marker_state.dart index a58d3bb..cacf128 100644 --- a/patterns/state/manipulator_state/states/selections/resizable_state/bottom_left_marker_state.dart +++ b/patterns/state/manipulator_state/states/selections/resizable_state/bottom_left_marker_state.dart @@ -6,7 +6,7 @@ class BottomLeftMarkerState extends CornerMarker { }); @override - void mouseMoveAction(double x, double y) { + void mouseDragAction(double x, double y) { final selectedShape = parentState.selectedShape; selectedShape.resize( selectedShape.width + selectedShape.x - x, diff --git a/patterns/state/manipulator_state/states/selections/resizable_state/bottom_right_marker_state.dart b/patterns/state/manipulator_state/states/selections/resizable_state/bottom_right_marker_state.dart index 7923545..51ce857 100644 --- a/patterns/state/manipulator_state/states/selections/resizable_state/bottom_right_marker_state.dart +++ b/patterns/state/manipulator_state/states/selections/resizable_state/bottom_right_marker_state.dart @@ -6,7 +6,7 @@ class BottomRightMarkerState extends CornerMarker { }); @override - void mouseMoveAction(double x, double y) { + void mouseDragAction(double x, double y) { final parentShape = parentState.selectedShape; parentShape.resize( x - parentShape.x, diff --git a/patterns/state/manipulator_state/states/selections/resizable_state/top_left_marker_state.dart b/patterns/state/manipulator_state/states/selections/resizable_state/top_left_marker_state.dart index 7574327..8b54540 100644 --- a/patterns/state/manipulator_state/states/selections/resizable_state/top_left_marker_state.dart +++ b/patterns/state/manipulator_state/states/selections/resizable_state/top_left_marker_state.dart @@ -6,7 +6,7 @@ class TopLeftMarkerState extends CornerMarker { }); @override - void mouseMoveAction(double x, double y) { + void mouseDragAction(double x, double y) { parentState.selectedShape.resize( parentState.selectedShape.width + parentState.selectedShape.x - x, parentState.selectedShape.height + parentState.selectedShape.y - y, diff --git a/patterns/state/manipulator_state/states/selections/resizable_state/top_right_marker_state.dart b/patterns/state/manipulator_state/states/selections/resizable_state/top_right_marker_state.dart index 6d56aaf..e278da3 100644 --- a/patterns/state/manipulator_state/states/selections/resizable_state/top_right_marker_state.dart +++ b/patterns/state/manipulator_state/states/selections/resizable_state/top_right_marker_state.dart @@ -5,7 +5,7 @@ class TopRightMarkerState extends CornerMarker { required super.parentState, }); @override - void mouseMoveAction(double x, double y) { + void mouseDragAction(double x, double y) { final selectedShape = parentState.selectedShape; selectedShape.resize( x - selectedShape.x, diff --git a/patterns/state/manipulator_state/states/selections/sub_states/child_state.dart b/patterns/state/manipulator_state/states/selections/sub_states/child_state.dart index 3ce2bb6..5d7af8b 100644 --- a/patterns/state/manipulator_state/states/selections/sub_states/child_state.dart +++ b/patterns/state/manipulator_state/states/selections/sub_states/child_state.dart @@ -22,7 +22,7 @@ abstract class ChildState extends ManipulationState with HoverShapeMixin { void updatePosition(); - void mouseMoveAction(double x, double y); + void mouseDragAction(double x, double y); @override void onHover() { @@ -45,7 +45,7 @@ abstract class ChildState extends ManipulationState with HoverShapeMixin { void mouseMove(double x, double y) { super.mouseMove(x, y); if (_isDown) { - mouseMoveAction(x, y); + mouseDragAction(x, y); parentState.updateMarkers(); context.cursor = hoverCursor; context.update(); From 064e904ab5806e103ffebd81b3fb020931351e96 Mon Sep 17 00:00:00 2001 From: ilopX Date: Fri, 27 May 2022 17:33:27 +0300 Subject: [PATCH 41/91] Fic CircleShape rect. --- patterns/state/manipulator_state/shapes/circle_shape.dart | 2 -- 1 file changed, 2 deletions(-) diff --git a/patterns/state/manipulator_state/shapes/circle_shape.dart b/patterns/state/manipulator_state/shapes/circle_shape.dart index 8aeb9f9..9018f76 100644 --- a/patterns/state/manipulator_state/shapes/circle_shape.dart +++ b/patterns/state/manipulator_state/shapes/circle_shape.dart @@ -12,8 +12,6 @@ class CircleShape extends BaseShape { return CircleInnerRadiusState(selectedShape: this); } - @override - Rect get rect => Rect.fromLTWH(x, y, width, height); @override void paint(Canvas canvas) { From e969fba3939c6b6b86e77c81ed27d8e9f1fea8ec Mon Sep 17 00:00:00 2001 From: ilopX Date: Fri, 27 May 2022 18:05:02 +0300 Subject: [PATCH 42/91] Reversed shape search. --- patterns/state/manipulator_state/app/shapes.dart | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/patterns/state/manipulator_state/app/shapes.dart b/patterns/state/manipulator_state/app/shapes.dart index 29cdef7..381b96c 100644 --- a/patterns/state/manipulator_state/app/shapes.dart +++ b/patterns/state/manipulator_state/app/shapes.dart @@ -21,7 +21,7 @@ class Shapes with IterableMixin { final onChange = Event(); Shape? findShapeByCoordinates(x, y) { - for (final shape in _shapes) { + for (final shape in _shapes.reversed) { if (shape.rect.contains(Offset(x, y))) { return shape; } From 7625e79eb891f0b4b20329e104e20838f216144a Mon Sep 17 00:00:00 2001 From: ilopX Date: Fri, 27 May 2022 18:34:55 +0300 Subject: [PATCH 43/91] Move changeState to children. --- .../states/selections/sub_states/child_state.dart | 1 + .../states/selections/sub_states/parent_state.dart | 3 +-- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/patterns/state/manipulator_state/states/selections/sub_states/child_state.dart b/patterns/state/manipulator_state/states/selections/sub_states/child_state.dart index 5d7af8b..5877569 100644 --- a/patterns/state/manipulator_state/states/selections/sub_states/child_state.dart +++ b/patterns/state/manipulator_state/states/selections/sub_states/child_state.dart @@ -38,6 +38,7 @@ abstract class ChildState extends ManipulationState with HoverShapeMixin { void mouseDown(double x, double y) { if (isHover) { _isDown = true; + context.changeState(this); } } diff --git a/patterns/state/manipulator_state/states/selections/sub_states/parent_state.dart b/patterns/state/manipulator_state/states/selections/sub_states/parent_state.dart index 8c73b9b..b1930c9 100644 --- a/patterns/state/manipulator_state/states/selections/sub_states/parent_state.dart +++ b/patterns/state/manipulator_state/states/selections/sub_states/parent_state.dart @@ -16,8 +16,7 @@ class ParentState extends SelectionState { void mouseDown(double x, double y) { for (final marker in _markers) { marker.mouseDown(x, y); - if (marker.isDown) { - context.changeState(marker); + if (context.state == marker) { return; } } From 13ffcc920510d2c3f4e26adeb8e0d1350289dd0f Mon Sep 17 00:00:00 2001 From: ilopX Date: Fri, 27 May 2022 22:45:50 +0300 Subject: [PATCH 44/91] Refactor CreationState. --- .../states/creations/creation_state.dart | 22 +++++++++---------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/patterns/state/manipulator_state/states/creations/creation_state.dart b/patterns/state/manipulator_state/states/creations/creation_state.dart index 58e4a52..18612a5 100644 --- a/patterns/state/manipulator_state/states/creations/creation_state.dart +++ b/patterns/state/manipulator_state/states/creations/creation_state.dart @@ -41,33 +41,33 @@ abstract class CreationState extends ManipulationState { Shape? _newShape; var _isDragged = false; + bool get _isCreatingNotStart => _newShape == null; + void _startCreatingShape(double x, double y) { _startX = x; _startY = y; _newShape = createShape(x, y); } - bool get _isCreatingNotStart => _newShape == null; - void _resizeNewShape(double x, double y) { _isDragged = true; _newShape!.resize(x - _startX, y - _startY); context.update(); } - void _finishCreatingShape() { - context.changeState( - _newShape!.createSelectionState(), - ); - - _isDragged = false; - _newShape = null; - } - void _repositionNewShape() { if (!_isDragged) { _newShape!.move(_startX - 50, _startY - 50); _newShape!.resize(100, 100); } } + + void _finishCreatingShape() { + final selectedShapeState = _newShape!.createSelectionState(); + context.changeState(selectedShapeState); + _isDragged = false; + _newShape = null; + } + + } From f8934765d372188364803d6194e97467042cb5e8 Mon Sep 17 00:00:00 2001 From: ilopX Date: Fri, 27 May 2022 22:57:40 +0300 Subject: [PATCH 45/91] Fix ToolBar: selected FreeState after creation shape. --- .../manipulator_state/widgets/tool_bar.dart | 49 +++++++++++++------ 1 file changed, 33 insertions(+), 16 deletions(-) diff --git a/patterns/state/manipulator_state/widgets/tool_bar.dart b/patterns/state/manipulator_state/widgets/tool_bar.dart index 448716e..ec40cd5 100644 --- a/patterns/state/manipulator_state/widgets/tool_bar.dart +++ b/patterns/state/manipulator_state/widgets/tool_bar.dart @@ -5,6 +5,9 @@ import '../../../abstract_factory/tool_panel_factory/widgets/independent/event_l import '../../../abstract_factory/tool_panel_factory/widgets/independent/panel.dart'; import '../../../abstract_factory/tool_panel_factory/widgets/independent/tool_button.dart'; import '../app/app.dart'; +import '../app/tool.dart'; +import '../states/free_sate.dart'; +import '../states/selections/selection_state.dart'; class ToolBar extends StatelessWidget { final App app; @@ -20,23 +23,37 @@ class ToolBar extends StatelessWidget { thicknessHeight: 64, direction: Axis.horizontal, child: EventListenableBuilder( - event: app.manipulator.onStateChange, - builder: (_) { - return Row( - children: [ - for (final tool in app.tools) - ToolButton( - active: tool.state.runtimeType == - app.manipulator.state.runtimeType, - icon: Center(child: tool.icon), - onTap: () { - app.manipulator.changeState(tool.state); - }, - ) - ], - ); - }), + event: app.manipulator.onStateChange, + builder: (_) { + return Row( + children: [ + for (final tool in app.tools) + ToolButton( + active: isSelected(tool), + icon: Center(child: tool.icon), + onTap: () { + app.manipulator.changeState(tool.state); + }, + ) + ], + ); + }, + ), ), ); } + + bool isSelected(Tool tool) { + if (app.manipulator.state is SelectionState) { + if ( tool.state is FreeState) { + return true; + } + } + + if(app.manipulator.state.runtimeType == tool.state.runtimeType){ + return true; + } + + return false; + } } From 92ce5c6309431d35abac4c9f961a193e0f061d81 Mon Sep 17 00:00:00 2001 From: ilopX Date: Sun, 29 May 2022 19:28:33 +0300 Subject: [PATCH 46/91] Add InnerRadiusState. --- .../shapes/circle_shape.dart | 62 +++++++++++++++---- .../shapes/marker_shape.dart | 2 +- .../states/creations/creation_state.dart | 10 ++- .../selections/circle_inner_radius_state.dart | 46 -------------- .../inner_radius_marker_state.dart | 36 +++++++++++ .../states/selections/inner_radius_state.dart | 39 ++++++++++++ .../resizable_state/corner_marker.dart | 6 +- 7 files changed, 133 insertions(+), 68 deletions(-) delete mode 100644 patterns/state/manipulator_state/states/selections/circle_inner_radius_state.dart create mode 100644 patterns/state/manipulator_state/states/selections/inner_radius/inner_radius_marker_state.dart create mode 100644 patterns/state/manipulator_state/states/selections/inner_radius_state.dart diff --git a/patterns/state/manipulator_state/shapes/circle_shape.dart b/patterns/state/manipulator_state/shapes/circle_shape.dart index 9018f76..74de84b 100644 --- a/patterns/state/manipulator_state/shapes/circle_shape.dart +++ b/patterns/state/manipulator_state/shapes/circle_shape.dart @@ -1,36 +1,74 @@ import 'package:flutter/material.dart'; -import '../states/selections/circle_inner_radius_state.dart'; +import '../states/selections/inner_radius_state.dart'; import '../states/selections/selection_state.dart'; import 'base_shape.dart'; class CircleShape extends BaseShape { - CircleShape(super.x, super.y, super.width, super.height); + CircleShape( + super.x, + super.y, + super.width, + super.height, + double innerRadius, + ) { + this.innerRadius = innerRadius; + } + + double get innerRadius => + _turnOnInnerRadius && _drawInnerRadius ? _innerRadius : width / 2; + + bool get turnOnInnerRadius => _turnOnInnerRadius; + + set innerRadius(double newValue) { + if (newValue > width / 2) { + _turnOnInnerRadius = false; + _innerRadius = newValue; + return; + } else if (newValue < 1) { + newValue = 1; + } + _drawInnerRadius = true; + _turnOnInnerRadius = true; + _innerRadius = newValue; + } @override - SelectionState createSelectionState() { - return CircleInnerRadiusState(selectedShape: this); + void resize(double width, double height) { + _drawInnerRadius = width > _innerRadius * 2; + super.resize(width, height); } + @override + SelectionState createSelectionState() { + return InnerRadiusState(selectedShape: this); + } @override void paint(Canvas canvas) { - final w = width / 2; - final h = height / 2; final path = Path() ..fillType = PathFillType.evenOdd - ..addOval(rect) - ..addOval( + ..addOval(rect); + + if (_drawInnerRadius) { + final fixHeight = height / width; + path.addOval( Rect.fromLTWH( - x + w / 2, - y + h / 2, - w, - h, + x + innerRadius, + y + innerRadius * fixHeight, + width - innerRadius * 2, + height - innerRadius * 2 * fixHeight, ), ); + } + canvas.drawPath( path, Paint()..color = Colors.white, ); } + + late double _innerRadius; + bool _drawInnerRadius = true; + bool _turnOnInnerRadius = true; } diff --git a/patterns/state/manipulator_state/shapes/marker_shape.dart b/patterns/state/manipulator_state/shapes/marker_shape.dart index 40d95a0..8545295 100644 --- a/patterns/state/manipulator_state/shapes/marker_shape.dart +++ b/patterns/state/manipulator_state/shapes/marker_shape.dart @@ -3,7 +3,7 @@ import 'package:flutter/material.dart'; import 'base_shape.dart'; class MarkerShape extends BaseShape { - MarkerShape([super.x = 0, super.y = 0, super.width = 5, super.height = -1]); + MarkerShape(double size) : super(0, 0, size, -1); @override Rect get rect => Rect.fromLTWH(x - width, y - width, width * 2, width * 2); diff --git a/patterns/state/manipulator_state/states/creations/creation_state.dart b/patterns/state/manipulator_state/states/creations/creation_state.dart index 18612a5..fb7f0e2 100644 --- a/patterns/state/manipulator_state/states/creations/creation_state.dart +++ b/patterns/state/manipulator_state/states/creations/creation_state.dart @@ -36,11 +36,6 @@ abstract class CreationState extends ManipulationState { _newShape?.paint(canvas); } - var _startX = 0.0; - var _startY = 0.0; - Shape? _newShape; - var _isDragged = false; - bool get _isCreatingNotStart => _newShape == null; void _startCreatingShape(double x, double y) { @@ -69,5 +64,8 @@ abstract class CreationState extends ManipulationState { _newShape = null; } - + var _startX = 0.0; + var _startY = 0.0; + Shape? _newShape; + var _isDragged = false; } diff --git a/patterns/state/manipulator_state/states/selections/circle_inner_radius_state.dart b/patterns/state/manipulator_state/states/selections/circle_inner_radius_state.dart deleted file mode 100644 index 5eede75..0000000 --- a/patterns/state/manipulator_state/states/selections/circle_inner_radius_state.dart +++ /dev/null @@ -1,46 +0,0 @@ -import 'package:flutter/material.dart'; - -import 'resizable_state/resizable_state.dart'; - -class CircleInnerRadiusState extends ResizableState { - CircleInnerRadiusState({required super.selectedShape}); - - @override - void paint(Canvas canvas) { - super.paint(canvas); - canvas.save(); - canvas.translate(selectedShape.x, selectedShape.y); - - final p1 = Offset(selectedShape.width / 4 * 3, selectedShape.height / 2); - canvas.drawLine( - p1, - Offset(selectedShape.width, selectedShape.height / 2), - Paint() - ..color = Colors.cyanAccent - ..strokeWidth = 2, - ); - - canvas.drawCircle( - p1, - 5, - Paint() - ..color = Colors.black - ..style = PaintingStyle.fill, - ); - canvas.drawCircle( - p1, - 5, - Paint() - ..strokeWidth = 2 - ..color = Colors.cyanAccent - ..style = PaintingStyle.stroke, - ); - - canvas.restore(); - } - - @override - String toString() { - return '${super.toString()} + Circle Inner Radius State'; - } -} diff --git a/patterns/state/manipulator_state/states/selections/inner_radius/inner_radius_marker_state.dart b/patterns/state/manipulator_state/states/selections/inner_radius/inner_radius_marker_state.dart new file mode 100644 index 0000000..536066c --- /dev/null +++ b/patterns/state/manipulator_state/states/selections/inner_radius/inner_radius_marker_state.dart @@ -0,0 +1,36 @@ +import 'package:flutter/cupertino.dart'; +import 'package:flutter/src/services/mouse_cursor.dart'; + +import '../../../shapes/circle_shape.dart'; +import '../../../shapes/marker_shape.dart'; +import '../sub_states/child_state.dart'; +import '../sub_states/parent_state.dart'; + +class InnerRadiusMarkerState extends ChildState { + InnerRadiusMarkerState({ + required ParentState parentState, + }) : super( + parentState: parentState, + shape: MarkerShape(5), + ); + + @override + void mouseDragAction(double x, double y) { + final selectedCircle = parentState.selectedShape as CircleShape; + selectedCircle.innerRadius = selectedCircle.rect.right - x; + } + + @override + void updatePosition() { + final selectedCircle = parentState.selectedShape as CircleShape; + final y = selectedCircle.y + selectedCircle.height / 2; + final x = selectedCircle.x + selectedCircle.width; + shape.move( + x - selectedCircle.innerRadius, + y, + ); + } + + @override + MouseCursor get hoverCursor => SystemMouseCursors.resizeLeftRight; +} diff --git a/patterns/state/manipulator_state/states/selections/inner_radius_state.dart b/patterns/state/manipulator_state/states/selections/inner_radius_state.dart new file mode 100644 index 0000000..b9ff0f0 --- /dev/null +++ b/patterns/state/manipulator_state/states/selections/inner_radius_state.dart @@ -0,0 +1,39 @@ +import 'package:flutter/material.dart'; + +import '../../shapes/circle_shape.dart'; +import 'inner_radius/inner_radius_marker_state.dart'; +import 'resizable_state.dart'; + +class InnerRadiusState extends ResizableState { + InnerRadiusState({required super.selectedShape}) { + addMarkers([ + InnerRadiusMarkerState(parentState: this), + ]); + } + + @override + void paint(Canvas canvas) { + canvas.save(); + canvas.translate(selectedShape.x, selectedShape.y); + final y = selectedShape.height / 2; + final p1 = Offset( + selectedShape.width - (selectedShape as CircleShape).innerRadius, + y, + ); + canvas.drawLine( + p1, + Offset(selectedShape.width, y), + Paint() + ..color = Colors.cyanAccent + ..strokeWidth = 1, + ); + + canvas.restore(); + super.paint(canvas); + } + + @override + String toString() { + return '${super.toString()} + Inner Radius State'; + } +} diff --git a/patterns/state/manipulator_state/states/selections/resizable_state/corner_marker.dart b/patterns/state/manipulator_state/states/selections/resizable_state/corner_marker.dart index e1dd87b..495d2d8 100644 --- a/patterns/state/manipulator_state/states/selections/resizable_state/corner_marker.dart +++ b/patterns/state/manipulator_state/states/selections/resizable_state/corner_marker.dart @@ -1,15 +1,15 @@ import 'package:flutter/rendering.dart'; import '../../../shapes/marker_shape.dart'; -import '../selection_state.dart'; import '../sub_states/child_state.dart'; +import '../sub_states/parent_state.dart'; abstract class CornerMarker extends ChildState { CornerMarker({ - required SelectionState parentState, + required ParentState parentState, }) : super( parentState: parentState, - shape: MarkerShape(), + shape: MarkerShape(5), ); @override From d6029ae3ad55050c69a7bffa929d1adabc8799f3 Mon Sep 17 00:00:00 2001 From: ilopX Date: Sun, 29 May 2022 19:29:46 +0300 Subject: [PATCH 47/91] Rename trySelectAndStartMovingShape to tryToSelectAndStartMovingShape. --- .../manipulator_state/states/selections/selection_state.dart | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/patterns/state/manipulator_state/states/selections/selection_state.dart b/patterns/state/manipulator_state/states/selections/selection_state.dart index 02dc815..826155d 100644 --- a/patterns/state/manipulator_state/states/selections/selection_state.dart +++ b/patterns/state/manipulator_state/states/selections/selection_state.dart @@ -10,7 +10,7 @@ class SelectionState extends FreeState { @override void mouseDown(double x, double y) { - final isShapeNotSelected = !trySelectAndStartMovingShape(x, y); + final isShapeNotSelected = !tryToSelectAndStartMovingShape(x, y); if (isShapeNotSelected) { context.changeState(FreeState()); From bc8e6d15cbe4f1f7090482d26c73ced2d6a8025a Mon Sep 17 00:00:00 2001 From: ilopX Date: Sun, 29 May 2022 19:30:35 +0300 Subject: [PATCH 48/91] Add default width CircleCreationState. --- .../states/creations/circle_creation_state.dart | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/patterns/state/manipulator_state/states/creations/circle_creation_state.dart b/patterns/state/manipulator_state/states/creations/circle_creation_state.dart index 2d7b55d..63674d3 100644 --- a/patterns/state/manipulator_state/states/creations/circle_creation_state.dart +++ b/patterns/state/manipulator_state/states/creations/circle_creation_state.dart @@ -5,7 +5,7 @@ import 'creation_state.dart'; class CircleCreationState extends CreationState { @override Shape createShape(double x, double y) { - return CircleShape(x, y, 100, 100); + return CircleShape(x, y, 100, 100, 25); } @override From 8b93cafe770436a5877b8ea284e76b751d96e9d5 Mon Sep 17 00:00:00 2001 From: ilopX Date: Sun, 29 May 2022 19:32:11 +0300 Subject: [PATCH 49/91] Rename again tryToSelectAndStartMovingShape. --- patterns/state/manipulator_state/states/free_sate.dart | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/patterns/state/manipulator_state/states/free_sate.dart b/patterns/state/manipulator_state/states/free_sate.dart index aefd865..6f4a408 100644 --- a/patterns/state/manipulator_state/states/free_sate.dart +++ b/patterns/state/manipulator_state/states/free_sate.dart @@ -5,10 +5,10 @@ import 'selections/moving_state.dart'; class FreeState extends ManipulationState with HoverShapeMixin { @override void mouseDown(double x, double y) { - trySelectAndStartMovingShape(x, y); + tryToSelectAndStartMovingShape(x, y); } - bool trySelectAndStartMovingShape(double x, double y) { + bool tryToSelectAndStartMovingShape(double x, double y) { if (hoverShape == null) { return false; } From f1b21fa282fcd30fe4e19252e3b98e139a932fbd Mon Sep 17 00:00:00 2001 From: ilopX Date: Sun, 29 May 2022 19:33:25 +0300 Subject: [PATCH 50/91] Change SelectionState to ParentState int ChildState. --- .../pattern/manipulation_state.dart | 2 -- .../states/selections/sub_states/child_state.dart | 14 +++++++++----- .../states/selections/sub_states/parent_state.dart | 13 ++++++------- 3 files changed, 15 insertions(+), 14 deletions(-) diff --git a/patterns/state/manipulator_state/pattern/manipulation_state.dart b/patterns/state/manipulator_state/pattern/manipulation_state.dart index bd52909..dd7b036 100644 --- a/patterns/state/manipulator_state/pattern/manipulation_state.dart +++ b/patterns/state/manipulator_state/pattern/manipulation_state.dart @@ -13,7 +13,5 @@ class ManipulationState { void paint(Canvas canvas) {} - void updateMarkers() {} - late Manipulator _context; } diff --git a/patterns/state/manipulator_state/states/selections/sub_states/child_state.dart b/patterns/state/manipulator_state/states/selections/sub_states/child_state.dart index 5877569..c16a1f7 100644 --- a/patterns/state/manipulator_state/states/selections/sub_states/child_state.dart +++ b/patterns/state/manipulator_state/states/selections/sub_states/child_state.dart @@ -5,14 +5,12 @@ import 'package:flutter/services.dart'; import '../../../shapes/shape.dart'; import '../../../pattern/manipulator.dart'; import '../../mixins/hover_shape_mixin.dart'; -import '../selection_state.dart'; +import 'parent_state.dart'; abstract class ChildState extends ManipulationState with HoverShapeMixin { - final SelectionState parentState; + final ParentState parentState; final Shape shape; - MouseCursor get hoverCursor; - ChildState({ required this.parentState, required this.shape, @@ -24,6 +22,8 @@ abstract class ChildState extends ManipulationState with HoverShapeMixin { void mouseDragAction(double x, double y); + MouseCursor get hoverCursor; + @override void onHover() { context.cursor = hoverCursor; @@ -60,8 +60,12 @@ abstract class ChildState extends ManipulationState with HoverShapeMixin { } context.changeState(parentState); - _isDown = false; + + if (!isHover) { + context.cursor = SystemMouseCursors.basic; + context.update(); + } } @override diff --git a/patterns/state/manipulator_state/states/selections/sub_states/parent_state.dart b/patterns/state/manipulator_state/states/selections/sub_states/parent_state.dart index b1930c9..eaf9d19 100644 --- a/patterns/state/manipulator_state/states/selections/sub_states/parent_state.dart +++ b/patterns/state/manipulator_state/states/selections/sub_states/parent_state.dart @@ -12,6 +12,12 @@ class ParentState extends SelectionState { _markers.addAll(markers); } + void updateMarkers() { + for (final marker in _markers) { + marker.updatePosition(); + } + } + @override void mouseDown(double x, double y) { for (final marker in _markers) { @@ -45,12 +51,5 @@ class ParentState extends SelectionState { } } - @override - void updateMarkers() { - for (final marker in _markers) { - marker.updatePosition(); - } - } - final _markers = []; } From f8f1f18696fdcc355f2504b3c8b0516db9f29cd4 Mon Sep 17 00:00:00 2001 From: ilopX Date: Sun, 29 May 2022 19:34:46 +0300 Subject: [PATCH 51/91] Move resizable_state.dart to root directory. --- .../manipulator_state/shapes/rectangle_shape.dart | 2 +- .../{resizable_state => }/resizable_state.dart | 10 +++++----- 2 files changed, 6 insertions(+), 6 deletions(-) rename patterns/state/manipulator_state/states/selections/{resizable_state => }/resizable_state.dart (60%) diff --git a/patterns/state/manipulator_state/shapes/rectangle_shape.dart b/patterns/state/manipulator_state/shapes/rectangle_shape.dart index e32b864..27e04c9 100644 --- a/patterns/state/manipulator_state/shapes/rectangle_shape.dart +++ b/patterns/state/manipulator_state/shapes/rectangle_shape.dart @@ -1,6 +1,6 @@ import 'package:flutter/material.dart'; -import '../states/selections/resizable_state/resizable_state.dart'; +import '../states/selections/resizable_state.dart'; import '../states/selections/selection_state.dart'; import 'base_shape.dart'; diff --git a/patterns/state/manipulator_state/states/selections/resizable_state/resizable_state.dart b/patterns/state/manipulator_state/states/selections/resizable_state.dart similarity index 60% rename from patterns/state/manipulator_state/states/selections/resizable_state/resizable_state.dart rename to patterns/state/manipulator_state/states/selections/resizable_state.dart index d578dcb..c35ad70 100644 --- a/patterns/state/manipulator_state/states/selections/resizable_state/resizable_state.dart +++ b/patterns/state/manipulator_state/states/selections/resizable_state.dart @@ -1,8 +1,8 @@ -import 'bottom_left_marker_state.dart'; -import 'bottom_right_marker_state.dart'; -import 'top_left_marker_state.dart'; -import 'top_right_marker_state.dart'; -import '../sub_states/parent_state.dart'; +import 'resizable_state/bottom_left_marker_state.dart'; +import 'resizable_state/bottom_right_marker_state.dart'; +import 'resizable_state/top_left_marker_state.dart'; +import 'resizable_state/top_right_marker_state.dart'; +import 'sub_states/parent_state.dart'; class ResizableState extends ParentState { ResizableState({required super.selectedShape}) { From f9e571c38ebe0f538ecaa339a5b7d4af8a54dc63 Mon Sep 17 00:00:00 2001 From: ilopX Date: Sun, 29 May 2022 19:38:38 +0300 Subject: [PATCH 52/91] Format tool_bar.dart. --- patterns/state/manipulator_state/widgets/tool_bar.dart | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/patterns/state/manipulator_state/widgets/tool_bar.dart b/patterns/state/manipulator_state/widgets/tool_bar.dart index ec40cd5..bc3c14a 100644 --- a/patterns/state/manipulator_state/widgets/tool_bar.dart +++ b/patterns/state/manipulator_state/widgets/tool_bar.dart @@ -45,15 +45,15 @@ class ToolBar extends StatelessWidget { bool isSelected(Tool tool) { if (app.manipulator.state is SelectionState) { - if ( tool.state is FreeState) { + if (tool.state is FreeState) { return true; } } - if(app.manipulator.state.runtimeType == tool.state.runtimeType){ + if (app.manipulator.state.runtimeType == tool.state.runtimeType) { return true; } - return false; + return false; } } From 8f364ad1b47f85054a483872d97ffd169a6d7857 Mon Sep 17 00:00:00 2001 From: ilopX Date: Sun, 29 May 2022 19:47:47 +0300 Subject: [PATCH 53/91] Add generic type to SelectionState.selectedShape. --- .../states/selections/inner_radius_state.dart | 2 +- .../manipulator_state/states/selections/resizable_state.dart | 3 ++- .../manipulator_state/states/selections/selection_state.dart | 4 ++-- .../states/selections/sub_states/parent_state.dart | 3 ++- 4 files changed, 7 insertions(+), 5 deletions(-) diff --git a/patterns/state/manipulator_state/states/selections/inner_radius_state.dart b/patterns/state/manipulator_state/states/selections/inner_radius_state.dart index b9ff0f0..1a555e4 100644 --- a/patterns/state/manipulator_state/states/selections/inner_radius_state.dart +++ b/patterns/state/manipulator_state/states/selections/inner_radius_state.dart @@ -4,7 +4,7 @@ import '../../shapes/circle_shape.dart'; import 'inner_radius/inner_radius_marker_state.dart'; import 'resizable_state.dart'; -class InnerRadiusState extends ResizableState { +class InnerRadiusState extends ResizableState { InnerRadiusState({required super.selectedShape}) { addMarkers([ InnerRadiusMarkerState(parentState: this), diff --git a/patterns/state/manipulator_state/states/selections/resizable_state.dart b/patterns/state/manipulator_state/states/selections/resizable_state.dart index c35ad70..1377006 100644 --- a/patterns/state/manipulator_state/states/selections/resizable_state.dart +++ b/patterns/state/manipulator_state/states/selections/resizable_state.dart @@ -3,8 +3,9 @@ import 'resizable_state/bottom_right_marker_state.dart'; import 'resizable_state/top_left_marker_state.dart'; import 'resizable_state/top_right_marker_state.dart'; import 'sub_states/parent_state.dart'; +import '../../shapes/shape.dart'; -class ResizableState extends ParentState { +class ResizableState extends ParentState { ResizableState({required super.selectedShape}) { addMarkers([ TopLeftMarkerState(parentState: this), diff --git a/patterns/state/manipulator_state/states/selections/selection_state.dart b/patterns/state/manipulator_state/states/selections/selection_state.dart index 826155d..c50311b 100644 --- a/patterns/state/manipulator_state/states/selections/selection_state.dart +++ b/patterns/state/manipulator_state/states/selections/selection_state.dart @@ -3,8 +3,8 @@ import 'package:flutter/material.dart'; import '../../shapes/shape.dart'; import '../free_sate.dart'; -class SelectionState extends FreeState { - final Shape selectedShape; +class SelectionState extends FreeState { + final T selectedShape; SelectionState({required this.selectedShape}); diff --git a/patterns/state/manipulator_state/states/selections/sub_states/parent_state.dart b/patterns/state/manipulator_state/states/selections/sub_states/parent_state.dart index eaf9d19..979b4b6 100644 --- a/patterns/state/manipulator_state/states/selections/sub_states/parent_state.dart +++ b/patterns/state/manipulator_state/states/selections/sub_states/parent_state.dart @@ -2,8 +2,9 @@ import 'dart:ui'; import '../sub_states/child_state.dart'; import '../selection_state.dart'; +import '../../../shapes/shape.dart'; -class ParentState extends SelectionState { +class ParentState extends SelectionState { ParentState({ required super.selectedShape, }); From 706d031acbb0f9ce5656ae0508a1ab4703035cb3 Mon Sep 17 00:00:00 2001 From: ilopX Date: Sun, 29 May 2022 19:48:46 +0300 Subject: [PATCH 54/91] Move inner radius painter to PaintStyle. --- .../states/mixins/paint_style.dart | 17 +++++++++++++++++ .../states/selections/inner_radius_state.dart | 16 +--------------- 2 files changed, 18 insertions(+), 15 deletions(-) diff --git a/patterns/state/manipulator_state/states/mixins/paint_style.dart b/patterns/state/manipulator_state/states/mixins/paint_style.dart index 624a338..4d346b1 100644 --- a/patterns/state/manipulator_state/states/mixins/paint_style.dart +++ b/patterns/state/manipulator_state/states/mixins/paint_style.dart @@ -1,5 +1,6 @@ import 'package:flutter/material.dart'; +import '../../shapes/circle_shape.dart'; import '../../shapes/shape.dart'; class PaintStyle { @@ -42,4 +43,20 @@ class PaintStyle { final Paint _selectStroke; final Paint _markerStroke; final Paint _markerFill; + + void paintRadiusLine(CircleShape selectedShape, Canvas canvas) { + canvas.save(); + canvas.translate(selectedShape.x, selectedShape.y); + final x = selectedShape.width - selectedShape.innerRadius; + final y = selectedShape.height / 2; + canvas.drawLine( + Offset(x,y), + Offset(selectedShape.width, y), + Paint() + ..color = color + ..strokeWidth = 1, + ); + + canvas.restore(); + } } diff --git a/patterns/state/manipulator_state/states/selections/inner_radius_state.dart b/patterns/state/manipulator_state/states/selections/inner_radius_state.dart index 1a555e4..c244228 100644 --- a/patterns/state/manipulator_state/states/selections/inner_radius_state.dart +++ b/patterns/state/manipulator_state/states/selections/inner_radius_state.dart @@ -13,22 +13,8 @@ class InnerRadiusState extends ResizableState { @override void paint(Canvas canvas) { - canvas.save(); - canvas.translate(selectedShape.x, selectedShape.y); - final y = selectedShape.height / 2; - final p1 = Offset( - selectedShape.width - (selectedShape as CircleShape).innerRadius, - y, - ); - canvas.drawLine( - p1, - Offset(selectedShape.width, y), - Paint() - ..color = Colors.cyanAccent - ..strokeWidth = 1, - ); + context.paintStyle.paintRadiusLine(selectedShape, canvas); - canvas.restore(); super.paint(canvas); } From 5fcd818974347075716347fd9f03a4c5b35a9047 Mon Sep 17 00:00:00 2001 From: ilopX Date: Sun, 29 May 2022 19:53:42 +0300 Subject: [PATCH 55/91] InnerRadiusMarkerState add toString. --- .../selections/inner_radius/inner_radius_marker_state.dart | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/patterns/state/manipulator_state/states/selections/inner_radius/inner_radius_marker_state.dart b/patterns/state/manipulator_state/states/selections/inner_radius/inner_radius_marker_state.dart index 536066c..a9f96a8 100644 --- a/patterns/state/manipulator_state/states/selections/inner_radius/inner_radius_marker_state.dart +++ b/patterns/state/manipulator_state/states/selections/inner_radius/inner_radius_marker_state.dart @@ -1,4 +1,3 @@ -import 'package:flutter/cupertino.dart'; import 'package:flutter/src/services/mouse_cursor.dart'; import '../../../shapes/circle_shape.dart'; @@ -33,4 +32,9 @@ class InnerRadiusMarkerState extends ChildState { @override MouseCursor get hoverCursor => SystemMouseCursors.resizeLeftRight; + + @override + String toString() { + return '${parentState.toString()} + Inner Radius Marker State'; + } } From 6bc19138042f6c20ed9fa4651d2e029437d4fea7 Mon Sep 17 00:00:00 2001 From: ilopX Date: Sun, 29 May 2022 20:01:35 +0300 Subject: [PATCH 56/91] Add generic shape type to ChildState & rename shape to markerShape. --- .../state/manipulator_state/shapes/base_shape.dart | 12 +----------- .../state/manipulator_state/shapes/marker_shape.dart | 3 --- .../manipulator_state/states/mixins/paint_style.dart | 8 ++++---- .../inner_radius/inner_radius_marker_state.dart | 12 ++++++------ .../resizable_state/bottom_left_marker_state.dart | 2 +- .../resizable_state/bottom_right_marker_state.dart | 2 +- .../selections/resizable_state/corner_marker.dart | 4 ++-- .../resizable_state/top_left_marker_state.dart | 2 +- .../resizable_state/top_right_marker_state.dart | 2 +- .../states/selections/sub_states/child_state.dart | 10 +++++----- .../states/selections/sub_states/parent_state.dart | 2 +- 11 files changed, 23 insertions(+), 36 deletions(-) diff --git a/patterns/state/manipulator_state/shapes/base_shape.dart b/patterns/state/manipulator_state/shapes/base_shape.dart index 9395fca..04d0839 100644 --- a/patterns/state/manipulator_state/shapes/base_shape.dart +++ b/patterns/state/manipulator_state/shapes/base_shape.dart @@ -48,17 +48,7 @@ class BaseShape implements Shape { } @override - void paint(Canvas canvas) { - canvas.drawRect( - Rect.fromLTWH( - _x, - _y, - _width, - _height, - ), - Paint()..color = Colors.white, - ); - } + void paint(Canvas canvas) {} double _x; double _y; diff --git a/patterns/state/manipulator_state/shapes/marker_shape.dart b/patterns/state/manipulator_state/shapes/marker_shape.dart index 8545295..72ce1fa 100644 --- a/patterns/state/manipulator_state/shapes/marker_shape.dart +++ b/patterns/state/manipulator_state/shapes/marker_shape.dart @@ -7,7 +7,4 @@ class MarkerShape extends BaseShape { @override Rect get rect => Rect.fromLTWH(x - width, y - width, width * 2, width * 2); - - @override - void paint(Canvas canvas) {} } diff --git a/patterns/state/manipulator_state/states/mixins/paint_style.dart b/patterns/state/manipulator_state/states/mixins/paint_style.dart index 4d346b1..5894099 100644 --- a/patterns/state/manipulator_state/states/mixins/paint_style.dart +++ b/patterns/state/manipulator_state/states/mixins/paint_style.dart @@ -26,16 +26,16 @@ class PaintStyle { ); } - void paintMarker(Canvas canvas, Shape shape) { - final point = Offset(shape.x, shape.y); + void paintMarker(Canvas canvas, Shape markerShape) { + final point = Offset(markerShape.x, markerShape.y); canvas.drawCircle( point, - shape.width, + markerShape.width, _markerFill, ); canvas.drawCircle( point, - shape.width, + markerShape.width, _markerStroke, ); } diff --git a/patterns/state/manipulator_state/states/selections/inner_radius/inner_radius_marker_state.dart b/patterns/state/manipulator_state/states/selections/inner_radius/inner_radius_marker_state.dart index a9f96a8..6d9acbb 100644 --- a/patterns/state/manipulator_state/states/selections/inner_radius/inner_radius_marker_state.dart +++ b/patterns/state/manipulator_state/states/selections/inner_radius/inner_radius_marker_state.dart @@ -5,26 +5,26 @@ import '../../../shapes/marker_shape.dart'; import '../sub_states/child_state.dart'; import '../sub_states/parent_state.dart'; -class InnerRadiusMarkerState extends ChildState { +class InnerRadiusMarkerState extends ChildState { InnerRadiusMarkerState({ - required ParentState parentState, + required ParentState parentState, }) : super( parentState: parentState, - shape: MarkerShape(5), + markerShape: MarkerShape(5), ); @override void mouseDragAction(double x, double y) { - final selectedCircle = parentState.selectedShape as CircleShape; + final selectedCircle = parentState.selectedShape; selectedCircle.innerRadius = selectedCircle.rect.right - x; } @override void updatePosition() { - final selectedCircle = parentState.selectedShape as CircleShape; + final selectedCircle = parentState.selectedShape; final y = selectedCircle.y + selectedCircle.height / 2; final x = selectedCircle.x + selectedCircle.width; - shape.move( + markerShape.move( x - selectedCircle.innerRadius, y, ); diff --git a/patterns/state/manipulator_state/states/selections/resizable_state/bottom_left_marker_state.dart b/patterns/state/manipulator_state/states/selections/resizable_state/bottom_left_marker_state.dart index cacf128..45d9078 100644 --- a/patterns/state/manipulator_state/states/selections/resizable_state/bottom_left_marker_state.dart +++ b/patterns/state/manipulator_state/states/selections/resizable_state/bottom_left_marker_state.dart @@ -17,7 +17,7 @@ class BottomLeftMarkerState extends CornerMarker { @override void updatePosition() { - shape.move( + markerShape.move( parentState.selectedShape.x, parentState.selectedShape.y + parentState.selectedShape.height, ); diff --git a/patterns/state/manipulator_state/states/selections/resizable_state/bottom_right_marker_state.dart b/patterns/state/manipulator_state/states/selections/resizable_state/bottom_right_marker_state.dart index 51ce857..6b6371d 100644 --- a/patterns/state/manipulator_state/states/selections/resizable_state/bottom_right_marker_state.dart +++ b/patterns/state/manipulator_state/states/selections/resizable_state/bottom_right_marker_state.dart @@ -17,7 +17,7 @@ class BottomRightMarkerState extends CornerMarker { @override void updatePosition() { final parentShape = parentState.selectedShape; - shape.move( + markerShape.move( parentShape.x + parentState.selectedShape.width, parentState.selectedShape.y + parentState.selectedShape.height, ); diff --git a/patterns/state/manipulator_state/states/selections/resizable_state/corner_marker.dart b/patterns/state/manipulator_state/states/selections/resizable_state/corner_marker.dart index 495d2d8..5bccdeb 100644 --- a/patterns/state/manipulator_state/states/selections/resizable_state/corner_marker.dart +++ b/patterns/state/manipulator_state/states/selections/resizable_state/corner_marker.dart @@ -9,13 +9,13 @@ abstract class CornerMarker extends ChildState { required ParentState parentState, }) : super( parentState: parentState, - shape: MarkerShape(5), + markerShape: MarkerShape(5), ); @override MouseCursor get hoverCursor { final rect = parentState.selectedShape.rect; - final corner = Offset(shape.x, shape.y); + final corner = Offset(markerShape.x, markerShape.y); if (corner == rect.topLeft) { return SystemMouseCursors.resizeUpLeft; diff --git a/patterns/state/manipulator_state/states/selections/resizable_state/top_left_marker_state.dart b/patterns/state/manipulator_state/states/selections/resizable_state/top_left_marker_state.dart index 8b54540..2b336ab 100644 --- a/patterns/state/manipulator_state/states/selections/resizable_state/top_left_marker_state.dart +++ b/patterns/state/manipulator_state/states/selections/resizable_state/top_left_marker_state.dart @@ -16,7 +16,7 @@ class TopLeftMarkerState extends CornerMarker { @override void updatePosition() { - shape.move(parentState.selectedShape.x, parentState.selectedShape.y); + markerShape.move(parentState.selectedShape.x, parentState.selectedShape.y); } @override diff --git a/patterns/state/manipulator_state/states/selections/resizable_state/top_right_marker_state.dart b/patterns/state/manipulator_state/states/selections/resizable_state/top_right_marker_state.dart index e278da3..7c1489b 100644 --- a/patterns/state/manipulator_state/states/selections/resizable_state/top_right_marker_state.dart +++ b/patterns/state/manipulator_state/states/selections/resizable_state/top_right_marker_state.dart @@ -16,7 +16,7 @@ class TopRightMarkerState extends CornerMarker { @override void updatePosition() { - shape.move( + markerShape.move( parentState.selectedShape.x + parentState.selectedShape.width, parentState.selectedShape.y, ); diff --git a/patterns/state/manipulator_state/states/selections/sub_states/child_state.dart b/patterns/state/manipulator_state/states/selections/sub_states/child_state.dart index c16a1f7..b1d18f4 100644 --- a/patterns/state/manipulator_state/states/selections/sub_states/child_state.dart +++ b/patterns/state/manipulator_state/states/selections/sub_states/child_state.dart @@ -7,13 +7,13 @@ import '../../../pattern/manipulator.dart'; import '../../mixins/hover_shape_mixin.dart'; import 'parent_state.dart'; -abstract class ChildState extends ManipulationState with HoverShapeMixin { - final ParentState parentState; - final Shape shape; +abstract class ChildState extends ManipulationState with HoverShapeMixin { + final ParentState parentState; + final Shape markerShape; ChildState({ required this.parentState, - required this.shape, + required this.markerShape, }) { updatePosition(); } @@ -78,7 +78,7 @@ abstract class ChildState extends ManipulationState with HoverShapeMixin { @override Shape? findShapeByCoordinates(double x, double y) { - return shape.rect.contains(Offset(x, y)) ? shape : null; + return markerShape.rect.contains(Offset(x, y)) ? markerShape : null; } bool get isDown => _isDown; diff --git a/patterns/state/manipulator_state/states/selections/sub_states/parent_state.dart b/patterns/state/manipulator_state/states/selections/sub_states/parent_state.dart index 979b4b6..2c8b217 100644 --- a/patterns/state/manipulator_state/states/selections/sub_states/parent_state.dart +++ b/patterns/state/manipulator_state/states/selections/sub_states/parent_state.dart @@ -48,7 +48,7 @@ class ParentState extends SelectionState { super.paint(canvas); for (final marker in _markers) { - context.paintStyle.paintMarker(canvas, marker.shape); + context.paintStyle.paintMarker(canvas, marker.markerShape); } } From 7c8d2a9770459fff63972b55de6c6cba2f9a9e60 Mon Sep 17 00:00:00 2001 From: ilopX Date: Sun, 29 May 2022 20:02:46 +0300 Subject: [PATCH 57/91] PaintStyle: move private vars to bottom. --- .../manipulator_state/states/mixins/paint_style.dart | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/patterns/state/manipulator_state/states/mixins/paint_style.dart b/patterns/state/manipulator_state/states/mixins/paint_style.dart index 5894099..46339d4 100644 --- a/patterns/state/manipulator_state/states/mixins/paint_style.dart +++ b/patterns/state/manipulator_state/states/mixins/paint_style.dart @@ -40,17 +40,13 @@ class PaintStyle { ); } - final Paint _selectStroke; - final Paint _markerStroke; - final Paint _markerFill; - void paintRadiusLine(CircleShape selectedShape, Canvas canvas) { canvas.save(); canvas.translate(selectedShape.x, selectedShape.y); final x = selectedShape.width - selectedShape.innerRadius; final y = selectedShape.height / 2; canvas.drawLine( - Offset(x,y), + Offset(x, y), Offset(selectedShape.width, y), Paint() ..color = color @@ -59,4 +55,8 @@ class PaintStyle { canvas.restore(); } + + final Paint _selectStroke; + final Paint _markerStroke; + final Paint _markerFill; } From 268773e7b4ed9b452e3634cb9ef6ef67d946ed2e Mon Sep 17 00:00:00 2001 From: ilopX Date: Sun, 29 May 2022 23:52:10 +0300 Subject: [PATCH 58/91] Set radius line to 1.5. --- patterns/state/manipulator_state/states/mixins/paint_style.dart | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/patterns/state/manipulator_state/states/mixins/paint_style.dart b/patterns/state/manipulator_state/states/mixins/paint_style.dart index 46339d4..985dbde 100644 --- a/patterns/state/manipulator_state/states/mixins/paint_style.dart +++ b/patterns/state/manipulator_state/states/mixins/paint_style.dart @@ -50,7 +50,7 @@ class PaintStyle { Offset(selectedShape.width, y), Paint() ..color = color - ..strokeWidth = 1, + ..strokeWidth = 1.5, ); canvas.restore(); From 28a92020f318ab07680c2b705c651d49b34a8108 Mon Sep 17 00:00:00 2001 From: ilopX Date: Mon, 30 May 2022 00:46:13 +0300 Subject: [PATCH 59/91] Refactor: create separate variable currentState. --- patterns/state/manipulator_state/widgets/tool_bar.dart | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/patterns/state/manipulator_state/widgets/tool_bar.dart b/patterns/state/manipulator_state/widgets/tool_bar.dart index bc3c14a..e8f06b4 100644 --- a/patterns/state/manipulator_state/widgets/tool_bar.dart +++ b/patterns/state/manipulator_state/widgets/tool_bar.dart @@ -44,13 +44,15 @@ class ToolBar extends StatelessWidget { } bool isSelected(Tool tool) { - if (app.manipulator.state is SelectionState) { + final currentState = app.manipulator.state; + + if (currentState is SelectionState) { if (tool.state is FreeState) { return true; } } - if (app.manipulator.state.runtimeType == tool.state.runtimeType) { + if (currentState.runtimeType == tool.state.runtimeType) { return true; } From 7ebba53a6a4943092c4a2417f674ddc7284c79d0 Mon Sep 17 00:00:00 2001 From: ilopX Date: Mon, 30 May 2022 00:48:27 +0300 Subject: [PATCH 60/91] Refactor: create separate function "buildButton". --- .../manipulator_state/widgets/tool_bar.dart | 19 +++++++++++-------- 1 file changed, 11 insertions(+), 8 deletions(-) diff --git a/patterns/state/manipulator_state/widgets/tool_bar.dart b/patterns/state/manipulator_state/widgets/tool_bar.dart index e8f06b4..2b5c5fa 100644 --- a/patterns/state/manipulator_state/widgets/tool_bar.dart +++ b/patterns/state/manipulator_state/widgets/tool_bar.dart @@ -1,4 +1,3 @@ -import 'package:flutter/cupertino.dart'; import 'package:flutter/material.dart'; import '../../../abstract_factory/tool_panel_factory/widgets/independent/event_listenable_builder.dart'; @@ -28,13 +27,7 @@ class ToolBar extends StatelessWidget { return Row( children: [ for (final tool in app.tools) - ToolButton( - active: isSelected(tool), - icon: Center(child: tool.icon), - onTap: () { - app.manipulator.changeState(tool.state); - }, - ) + buildButton(tool), ], ); }, @@ -43,6 +36,16 @@ class ToolBar extends StatelessWidget { ); } + Widget buildButton(Tool tool) { + return ToolButton( + active: isSelected(tool), + icon: Center(child: tool.icon), + onTap: () { + app.manipulator.changeState(tool.state); + }, + ); + } + bool isSelected(Tool tool) { final currentState = app.manipulator.state; From 4c3ed7bdd55e049f36ddbfdf8a7a8f5c30f3e09d Mon Sep 17 00:00:00 2001 From: ilopX Date: Mon, 30 May 2022 00:49:55 +0300 Subject: [PATCH 61/91] Refactor: CurrentState widget. --- .../widgets/current_state.dart | 24 ++++++++++--------- 1 file changed, 13 insertions(+), 11 deletions(-) diff --git a/patterns/state/manipulator_state/widgets/current_state.dart b/patterns/state/manipulator_state/widgets/current_state.dart index c319bce..458c06d 100644 --- a/patterns/state/manipulator_state/widgets/current_state.dart +++ b/patterns/state/manipulator_state/widgets/current_state.dart @@ -24,17 +24,19 @@ class CurrentState extends StatelessWidget { padding: EdgeInsets.symmetric(horizontal: 16), child: Center( child: EventListenableBuilder( - event: manipulator.onStateChange, - builder: (context) { - return EventListenableBuilder( - event: manipulator.onUpdate, - builder: (context) { - return Text( - manipulator.toString(), - style: TextStyle(color: Colors.white, fontSize: 16), - ); - }); - }), + event: manipulator.onStateChange, + builder: (context) { + return EventListenableBuilder( + event: manipulator.onUpdate, + builder: (context) { + return Text( + manipulator.toString(), + style: TextStyle(color: Colors.white, fontSize: 16), + ); + }, + ); + }, + ), ), ), ), From ea963611fc2cbf0467e337799674be358ce525be Mon Sep 17 00:00:00 2001 From: ilopX Date: Mon, 30 May 2022 00:53:48 +0300 Subject: [PATCH 62/91] Add "paintSelection" method to PaintStyle. --- .../state/manipulator_state/states/mixins/paint_style.dart | 4 ++++ .../manipulator_state/states/selections/selection_state.dart | 2 +- 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/patterns/state/manipulator_state/states/mixins/paint_style.dart b/patterns/state/manipulator_state/states/mixins/paint_style.dart index 985dbde..90cb74a 100644 --- a/patterns/state/manipulator_state/states/mixins/paint_style.dart +++ b/patterns/state/manipulator_state/states/mixins/paint_style.dart @@ -26,6 +26,10 @@ class PaintStyle { ); } + void paintSelection(Canvas canvas, Shape shape) { + paintHover(canvas, shape); + } + void paintMarker(Canvas canvas, Shape markerShape) { final point = Offset(markerShape.x, markerShape.y); canvas.drawCircle( diff --git a/patterns/state/manipulator_state/states/selections/selection_state.dart b/patterns/state/manipulator_state/states/selections/selection_state.dart index c50311b..f580a8e 100644 --- a/patterns/state/manipulator_state/states/selections/selection_state.dart +++ b/patterns/state/manipulator_state/states/selections/selection_state.dart @@ -20,7 +20,7 @@ class SelectionState extends FreeState { @override void paint(Canvas canvas) { super.paint(canvas); - context.paintStyle.paintHover(canvas, selectedShape); + context.paintStyle.paintSelection(canvas, selectedShape); } @override From e5993d6f4ce1f34fbd775a8c9246688f0dcf190c Mon Sep 17 00:00:00 2001 From: ilopX Date: Mon, 30 May 2022 01:07:18 +0300 Subject: [PATCH 63/91] Add selectedShape getter to CornerMarker. --- .../states/selections/inner_radius_state.dart | 1 - .../bottom_left_marker_state.dart | 13 ++++++------- .../bottom_right_marker_state.dart | 15 ++++++--------- .../resizable_state/corner_marker.dart | 3 +++ .../resizable_state/top_left_marker_state.dart | 16 ++++++++++------ .../resizable_state/top_right_marker_state.dart | 16 ++++++++-------- 6 files changed, 33 insertions(+), 31 deletions(-) diff --git a/patterns/state/manipulator_state/states/selections/inner_radius_state.dart b/patterns/state/manipulator_state/states/selections/inner_radius_state.dart index c244228..87fa67a 100644 --- a/patterns/state/manipulator_state/states/selections/inner_radius_state.dart +++ b/patterns/state/manipulator_state/states/selections/inner_radius_state.dart @@ -14,7 +14,6 @@ class InnerRadiusState extends ResizableState { @override void paint(Canvas canvas) { context.paintStyle.paintRadiusLine(selectedShape, canvas); - super.paint(canvas); } diff --git a/patterns/state/manipulator_state/states/selections/resizable_state/bottom_left_marker_state.dart b/patterns/state/manipulator_state/states/selections/resizable_state/bottom_left_marker_state.dart index 45d9078..47734fa 100644 --- a/patterns/state/manipulator_state/states/selections/resizable_state/bottom_left_marker_state.dart +++ b/patterns/state/manipulator_state/states/selections/resizable_state/bottom_left_marker_state.dart @@ -7,19 +7,18 @@ class BottomLeftMarkerState extends CornerMarker { @override void mouseDragAction(double x, double y) { - final selectedShape = parentState.selectedShape; - selectedShape.resize( - selectedShape.width + selectedShape.x - x, - y - selectedShape.y, - ); + final newX = selectedShape.width + selectedShape.x - x; + final newY = y - selectedShape.y; + + selectedShape.resize(newX, newY); selectedShape.move(x, selectedShape.y); } @override void updatePosition() { markerShape.move( - parentState.selectedShape.x, - parentState.selectedShape.y + parentState.selectedShape.height, + selectedShape.x, + selectedShape.y + selectedShape.height, ); } diff --git a/patterns/state/manipulator_state/states/selections/resizable_state/bottom_right_marker_state.dart b/patterns/state/manipulator_state/states/selections/resizable_state/bottom_right_marker_state.dart index 6b6371d..a87c563 100644 --- a/patterns/state/manipulator_state/states/selections/resizable_state/bottom_right_marker_state.dart +++ b/patterns/state/manipulator_state/states/selections/resizable_state/bottom_right_marker_state.dart @@ -7,20 +7,17 @@ class BottomRightMarkerState extends CornerMarker { @override void mouseDragAction(double x, double y) { - final parentShape = parentState.selectedShape; - parentShape.resize( - x - parentShape.x, - y - parentShape.y, + selectedShape.resize( + x - selectedShape.x, + y - selectedShape.y, ); } @override void updatePosition() { - final parentShape = parentState.selectedShape; - markerShape.move( - parentShape.x + parentState.selectedShape.width, - parentState.selectedShape.y + parentState.selectedShape.height, - ); + final width = selectedShape.x + selectedShape.width; + final height = selectedShape.y + selectedShape.height; + markerShape.move(width, height); } @override diff --git a/patterns/state/manipulator_state/states/selections/resizable_state/corner_marker.dart b/patterns/state/manipulator_state/states/selections/resizable_state/corner_marker.dart index 5bccdeb..43ec1af 100644 --- a/patterns/state/manipulator_state/states/selections/resizable_state/corner_marker.dart +++ b/patterns/state/manipulator_state/states/selections/resizable_state/corner_marker.dart @@ -3,6 +3,7 @@ import 'package:flutter/rendering.dart'; import '../../../shapes/marker_shape.dart'; import '../sub_states/child_state.dart'; import '../sub_states/parent_state.dart'; +import '../../../shapes/shape.dart'; abstract class CornerMarker extends ChildState { CornerMarker({ @@ -29,4 +30,6 @@ abstract class CornerMarker extends ChildState { return SystemMouseCursors.move; } + + Shape get selectedShape => parentState.selectedShape; } diff --git a/patterns/state/manipulator_state/states/selections/resizable_state/top_left_marker_state.dart b/patterns/state/manipulator_state/states/selections/resizable_state/top_left_marker_state.dart index 2b336ab..14d646b 100644 --- a/patterns/state/manipulator_state/states/selections/resizable_state/top_left_marker_state.dart +++ b/patterns/state/manipulator_state/states/selections/resizable_state/top_left_marker_state.dart @@ -7,16 +7,20 @@ class TopLeftMarkerState extends CornerMarker { @override void mouseDragAction(double x, double y) { - parentState.selectedShape.resize( - parentState.selectedShape.width + parentState.selectedShape.x - x, - parentState.selectedShape.height + parentState.selectedShape.y - y, - ); - parentState.selectedShape.move(x, y); + final newWidth = selectedShape.width + selectedShape.x - x; + final newHeight = selectedShape.height + selectedShape.y - y; + + selectedShape + ..resize(newWidth, newHeight) + ..move(x, y); } @override void updatePosition() { - markerShape.move(parentState.selectedShape.x, parentState.selectedShape.y); + markerShape.move( + selectedShape.x, + selectedShape.y, + ); } @override diff --git a/patterns/state/manipulator_state/states/selections/resizable_state/top_right_marker_state.dart b/patterns/state/manipulator_state/states/selections/resizable_state/top_right_marker_state.dart index 7c1489b..7191c45 100644 --- a/patterns/state/manipulator_state/states/selections/resizable_state/top_right_marker_state.dart +++ b/patterns/state/manipulator_state/states/selections/resizable_state/top_right_marker_state.dart @@ -4,21 +4,21 @@ class TopRightMarkerState extends CornerMarker { TopRightMarkerState({ required super.parentState, }); + @override void mouseDragAction(double x, double y) { - final selectedShape = parentState.selectedShape; - selectedShape.resize( - x - selectedShape.x, - selectedShape.height + selectedShape.y - y, - ); - selectedShape.move(selectedShape.x, y); + final newX = x - selectedShape.x; + final newY = selectedShape.height + selectedShape.y - y; + + selectedShape.resize(newX, newY); + selectedShape.move(selectedShape.x, newY); } @override void updatePosition() { markerShape.move( - parentState.selectedShape.x + parentState.selectedShape.width, - parentState.selectedShape.y, + selectedShape.x + selectedShape.width, + selectedShape.y, ); } From bbfd1339fa9a5dde7b3fbcc8a9928eceb5307d31 Mon Sep 17 00:00:00 2001 From: ilopX Date: Mon, 30 May 2022 15:18:21 +0300 Subject: [PATCH 64/91] Refactoring: RectangleShape & CircleShape. --- .../shapes/circle_shape.dart | 32 +++++++++++-------- .../shapes/rectangle_shape.dart | 7 +--- 2 files changed, 20 insertions(+), 19 deletions(-) diff --git a/patterns/state/manipulator_state/shapes/circle_shape.dart b/patterns/state/manipulator_state/shapes/circle_shape.dart index 74de84b..2cd3a11 100644 --- a/patterns/state/manipulator_state/shapes/circle_shape.dart +++ b/patterns/state/manipulator_state/shapes/circle_shape.dart @@ -18,25 +18,27 @@ class CircleShape extends BaseShape { double get innerRadius => _turnOnInnerRadius && _drawInnerRadius ? _innerRadius : width / 2; - bool get turnOnInnerRadius => _turnOnInnerRadius; - set innerRadius(double newValue) { if (newValue > width / 2) { _turnOnInnerRadius = false; _innerRadius = newValue; + _buildPath(); return; } else if (newValue < 1) { newValue = 1; } + _drawInnerRadius = true; - _turnOnInnerRadius = true; + _turnOnInnerRadius = _drawInnerRadius; _innerRadius = newValue; + _buildPath(); } @override void resize(double width, double height) { - _drawInnerRadius = width > _innerRadius * 2; super.resize(width, height); + _drawInnerRadius = width > _innerRadius * 2; + _buildPath(); } @override @@ -46,29 +48,33 @@ class CircleShape extends BaseShape { @override void paint(Canvas canvas) { - final path = Path() + canvas.drawPath( + _path, + Paint()..color = Colors.white, + ); + } + + void _buildPath() { + _path = Path() ..fillType = PathFillType.evenOdd ..addOval(rect); if (_drawInnerRadius) { final fixHeight = height / width; - path.addOval( + final doubleRadius = innerRadius * 2; + _path.addOval( Rect.fromLTWH( x + innerRadius, y + innerRadius * fixHeight, - width - innerRadius * 2, - height - innerRadius * 2 * fixHeight, + width - doubleRadius, + height - doubleRadius * fixHeight, ), ); } - - canvas.drawPath( - path, - Paint()..color = Colors.white, - ); } late double _innerRadius; + late Path _path; bool _drawInnerRadius = true; bool _turnOnInnerRadius = true; } diff --git a/patterns/state/manipulator_state/shapes/rectangle_shape.dart b/patterns/state/manipulator_state/shapes/rectangle_shape.dart index 27e04c9..c6eeedd 100644 --- a/patterns/state/manipulator_state/shapes/rectangle_shape.dart +++ b/patterns/state/manipulator_state/shapes/rectangle_shape.dart @@ -15,12 +15,7 @@ class RectangleShape extends BaseShape { @override void paint(Canvas canvas) { canvas.drawRect( - Rect.fromLTWH( - x, - y, - width, - height, - ), + rect, Paint()..color = Colors.white, ); } From b0ac3d13c7632d4ff5044e05cd5ec1f88ebfd3b1 Mon Sep 17 00:00:00 2001 From: ilopX Date: Mon, 30 May 2022 17:08:56 +0300 Subject: [PATCH 65/91] Add TextShape, TextResizeState. --- .../manipulator_state/shapes/base_shape.dart | 11 +--- .../shapes/circle_shape.dart | 6 ++ .../shapes/marker_shape.dart | 8 +++ .../manipulator_state/shapes/text_shape.dart | 58 +++++++++++++++++++ .../states/creations/creation_state.dart | 6 +- .../states/creations/text_creation_state.dart | 4 +- .../inner_radius_marker_state.dart | 13 +---- .../resizable_state/corner_marker.dart | 6 +- .../selections/sub_states/child_state.dart | 3 +- .../states/selections/text_resize_state.dart | 42 ++++++++++++++ .../manipulator_state/widgets/tool_bar.dart | 3 +- 11 files changed, 131 insertions(+), 29 deletions(-) create mode 100644 patterns/state/manipulator_state/shapes/text_shape.dart create mode 100644 patterns/state/manipulator_state/states/selections/text_resize_state.dart diff --git a/patterns/state/manipulator_state/shapes/base_shape.dart b/patterns/state/manipulator_state/shapes/base_shape.dart index 04d0839..c14eae8 100644 --- a/patterns/state/manipulator_state/shapes/base_shape.dart +++ b/patterns/state/manipulator_state/shapes/base_shape.dart @@ -1,9 +1,8 @@ import 'package:flutter/material.dart'; -import '../states/selections/selection_state.dart'; import 'shape.dart'; -class BaseShape implements Shape { +abstract class BaseShape implements Shape { BaseShape(double x, double y, double width, double height) : _x = x, _y = y, @@ -30,11 +29,6 @@ class BaseShape implements Shape { _height.abs(), ); - @override - SelectionState createSelectionState() { - return SelectionState(selectedShape: this); - } - @override void move(double x, double y) { _x = x; @@ -47,9 +41,6 @@ class BaseShape implements Shape { _height = height; } - @override - void paint(Canvas canvas) {} - double _x; double _y; double _width; diff --git a/patterns/state/manipulator_state/shapes/circle_shape.dart b/patterns/state/manipulator_state/shapes/circle_shape.dart index 2cd3a11..6efb1a5 100644 --- a/patterns/state/manipulator_state/shapes/circle_shape.dart +++ b/patterns/state/manipulator_state/shapes/circle_shape.dart @@ -41,6 +41,12 @@ class CircleShape extends BaseShape { _buildPath(); } + @override + void move(double x, double y) { + super.move(x, y); + _buildPath(); + } + @override SelectionState createSelectionState() { return InnerRadiusState(selectedShape: this); diff --git a/patterns/state/manipulator_state/shapes/marker_shape.dart b/patterns/state/manipulator_state/shapes/marker_shape.dart index 72ce1fa..aef7acf 100644 --- a/patterns/state/manipulator_state/shapes/marker_shape.dart +++ b/patterns/state/manipulator_state/shapes/marker_shape.dart @@ -1,10 +1,18 @@ import 'package:flutter/material.dart'; +import '../states/selections/selection_state.dart'; import 'base_shape.dart'; +import 'shape.dart'; class MarkerShape extends BaseShape { MarkerShape(double size) : super(0, 0, size, -1); @override Rect get rect => Rect.fromLTWH(x - width, y - width, width * 2, width * 2); + + @override + void paint(Canvas canvas) => throw UnimplementedError(); + + @override + SelectionState createSelectionState() => throw UnimplementedError(); } diff --git a/patterns/state/manipulator_state/shapes/text_shape.dart b/patterns/state/manipulator_state/shapes/text_shape.dart new file mode 100644 index 0000000..fd973af --- /dev/null +++ b/patterns/state/manipulator_state/shapes/text_shape.dart @@ -0,0 +1,58 @@ +import 'dart:ui'; + +import '../states/selections/selection_state.dart'; +import '../states/selections/text_resize_state.dart'; +import 'base_shape.dart'; + +class TextShape extends BaseShape { + TextShape(super.x, super.y, super.width, super.height) { + _buildParagraph(); + } + + @override + void paint(Canvas can) { + can.drawParagraph(_paragraph, Offset(x, y)); + } + + @override + SelectionState createSelectionState() { + return TextResizeState(selectedShape: this); + } + + @override + double get width => _paragraph.maxIntrinsicWidth; + + @override + Rect get rect => Rect.fromLTWH(x, y, width, height); + + @override + void resize(double _, double newHeight) { + if (newHeight < 2) { + newHeight = 2; + } + + super.resize(_, newHeight); + final prevWidth = width; + _buildParagraph(); + final centerX = x + (prevWidth - width) / 2; + move(centerX, y); + } + + void _buildParagraph() { + final style = ParagraphStyle( + textDirection: TextDirection.ltr, + ); + final tStyle = TextStyle( + fontFamily: 'Arial', + color: Color(0xffffffff), + fontSize: height, + ); + _paragraph = (ParagraphBuilder(style) + ..pushStyle(tStyle) + ..addText('Text')) + .build(); + _paragraph.layout(ParagraphConstraints(width: double.infinity)); + } + + late Paragraph _paragraph; +} diff --git a/patterns/state/manipulator_state/states/creations/creation_state.dart b/patterns/state/manipulator_state/states/creations/creation_state.dart index fb7f0e2..3485c86 100644 --- a/patterns/state/manipulator_state/states/creations/creation_state.dart +++ b/patterns/state/manipulator_state/states/creations/creation_state.dart @@ -52,8 +52,12 @@ abstract class CreationState extends ManipulationState { void _repositionNewShape() { if (!_isDragged) { - _newShape!.move(_startX - 50, _startY - 50); _newShape!.resize(100, 100); + final rect = _newShape!.rect; + _newShape!.move( + _startX - rect.width / 2, + _startY - rect.height / 2, + ); } } diff --git a/patterns/state/manipulator_state/states/creations/text_creation_state.dart b/patterns/state/manipulator_state/states/creations/text_creation_state.dart index 0befbff..559c4c9 100644 --- a/patterns/state/manipulator_state/states/creations/text_creation_state.dart +++ b/patterns/state/manipulator_state/states/creations/text_creation_state.dart @@ -1,11 +1,11 @@ -import '../../shapes/base_shape.dart'; import '../../shapes/shape.dart'; +import '../../shapes/text_shape.dart'; import 'creation_state.dart'; class TextCreationState extends CreationState { @override Shape createShape(double x, double y) { - return BaseShape(x, y, 100, 100); + return TextShape(x, y, 2, 2); } @override diff --git a/patterns/state/manipulator_state/states/selections/inner_radius/inner_radius_marker_state.dart b/patterns/state/manipulator_state/states/selections/inner_radius/inner_radius_marker_state.dart index 6d9acbb..72f1761 100644 --- a/patterns/state/manipulator_state/states/selections/inner_radius/inner_radius_marker_state.dart +++ b/patterns/state/manipulator_state/states/selections/inner_radius/inner_radius_marker_state.dart @@ -1,17 +1,10 @@ import 'package:flutter/src/services/mouse_cursor.dart'; import '../../../shapes/circle_shape.dart'; -import '../../../shapes/marker_shape.dart'; -import '../sub_states/child_state.dart'; -import '../sub_states/parent_state.dart'; +import '../resizable_state/corner_marker.dart'; -class InnerRadiusMarkerState extends ChildState { - InnerRadiusMarkerState({ - required ParentState parentState, - }) : super( - parentState: parentState, - markerShape: MarkerShape(5), - ); +class InnerRadiusMarkerState extends CornerMarker { + InnerRadiusMarkerState({required super.parentState}); @override void mouseDragAction(double x, double y) { diff --git a/patterns/state/manipulator_state/states/selections/resizable_state/corner_marker.dart b/patterns/state/manipulator_state/states/selections/resizable_state/corner_marker.dart index 43ec1af..9c46c0f 100644 --- a/patterns/state/manipulator_state/states/selections/resizable_state/corner_marker.dart +++ b/patterns/state/manipulator_state/states/selections/resizable_state/corner_marker.dart @@ -5,9 +5,9 @@ import '../sub_states/child_state.dart'; import '../sub_states/parent_state.dart'; import '../../../shapes/shape.dart'; -abstract class CornerMarker extends ChildState { +abstract class CornerMarker extends ChildState { CornerMarker({ - required ParentState parentState, + required ParentState parentState, }) : super( parentState: parentState, markerShape: MarkerShape(5), @@ -31,5 +31,5 @@ abstract class CornerMarker extends ChildState { return SystemMouseCursors.move; } - Shape get selectedShape => parentState.selectedShape; + T get selectedShape => parentState.selectedShape; } diff --git a/patterns/state/manipulator_state/states/selections/sub_states/child_state.dart b/patterns/state/manipulator_state/states/selections/sub_states/child_state.dart index b1d18f4..15bfcdd 100644 --- a/patterns/state/manipulator_state/states/selections/sub_states/child_state.dart +++ b/patterns/state/manipulator_state/states/selections/sub_states/child_state.dart @@ -7,7 +7,8 @@ import '../../../pattern/manipulator.dart'; import '../../mixins/hover_shape_mixin.dart'; import 'parent_state.dart'; -abstract class ChildState extends ManipulationState with HoverShapeMixin { +abstract class ChildState extends ManipulationState + with HoverShapeMixin { final ParentState parentState; final Shape markerShape; diff --git a/patterns/state/manipulator_state/states/selections/text_resize_state.dart b/patterns/state/manipulator_state/states/selections/text_resize_state.dart new file mode 100644 index 0000000..50659e8 --- /dev/null +++ b/patterns/state/manipulator_state/states/selections/text_resize_state.dart @@ -0,0 +1,42 @@ +import 'package:flutter/src/services/mouse_cursor.dart'; + +import '../../shapes/text_shape.dart'; +import 'resizable_state/corner_marker.dart'; +import 'sub_states/parent_state.dart'; + +class TextResizeState extends ParentState { + TextResizeState({required super.selectedShape}) { + addMarkers([ + TextSizeMarkerState(parentState: this), + ]); + } + + @override + String toString() { + return '${super.toString()} + Text Resize State'; + } +} + +class TextSizeMarkerState extends CornerMarker { + TextSizeMarkerState({required super.parentState}); + + @override + void mouseDragAction(double x, double y) { + final newHeight = y - selectedShape.y; + selectedShape.resize(-1, newHeight); + } + + @override + void updatePosition() { + final bottomCenter = selectedShape.rect.bottomCenter; + markerShape.move(bottomCenter.dx, bottomCenter.dy); + } + + @override + MouseCursor get hoverCursor => SystemMouseCursors.resizeUpDown; + + @override + String toString() { + return '${parentState.toString()} + Text Size Marker State'; + } +} diff --git a/patterns/state/manipulator_state/widgets/tool_bar.dart b/patterns/state/manipulator_state/widgets/tool_bar.dart index 2b5c5fa..b40adaf 100644 --- a/patterns/state/manipulator_state/widgets/tool_bar.dart +++ b/patterns/state/manipulator_state/widgets/tool_bar.dart @@ -26,8 +26,7 @@ class ToolBar extends StatelessWidget { builder: (_) { return Row( children: [ - for (final tool in app.tools) - buildButton(tool), + for (final tool in app.tools) buildButton(tool), ], ); }, From a1bc1a3b1faa8ddaa06144dd5051aa94a3c143aa Mon Sep 17 00:00:00 2001 From: ilopX Date: Mon, 30 May 2022 17:15:15 +0300 Subject: [PATCH 66/91] Fix wrong repeat selection in "tryToSelectAndStartMovingShape" function. --- patterns/state/manipulator_state/states/free_sate.dart | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/patterns/state/manipulator_state/states/free_sate.dart b/patterns/state/manipulator_state/states/free_sate.dart index 6f4a408..f1a9e62 100644 --- a/patterns/state/manipulator_state/states/free_sate.dart +++ b/patterns/state/manipulator_state/states/free_sate.dart @@ -9,7 +9,9 @@ class FreeState extends ManipulationState with HoverShapeMixin { } bool tryToSelectAndStartMovingShape(double x, double y) { - if (hoverShape == null) { + final selectedShape = context.shapes.findShapeByCoordinates(x, y); + + if (selectedShape == null) { return false; } @@ -17,7 +19,7 @@ class FreeState extends ManipulationState with HoverShapeMixin { MovingState( startX: x, startY: y, - selectedShape: hoverShape!, + selectedShape: selectedShape, ), ); From b4fcf68a936e40c5101038234969e6066477eb92 Mon Sep 17 00:00:00 2001 From: ilopX Date: Mon, 30 May 2022 23:52:52 +0300 Subject: [PATCH 67/91] Move the state helper classes to the "_" directory. --- patterns/state/manipulator_state/main.dart | 2 +- .../state/manipulator_state/pattern/manipulator.dart | 2 +- .../resizable_state => _}/corner_marker.dart | 8 ++++---- .../states/{ => _}/mixins/hover_shape_mixin.dart | 4 ++-- .../states/{mixins => _}/paint_style.dart | 0 .../{selections => _}/sub_states/child_state.dart | 2 +- .../{selections => _}/sub_states/parent_state.dart | 4 ++-- patterns/state/manipulator_state/states/free_sate.dart | 2 +- .../inner_radius_marker_state.dart | 2 +- .../states/selections/inner_radius_state.dart | 2 +- .../bottom_left_marker_state.dart | 2 +- .../bottom_right_marker_state.dart | 2 +- .../top_left_marker_state.dart | 2 +- .../top_right_marker_state.dart | 2 +- .../states/selections/resizable_state.dart | 10 +++++----- .../states/selections/text_resize_state.dart | 4 ++-- 16 files changed, 25 insertions(+), 25 deletions(-) rename patterns/state/manipulator_state/states/{selections/resizable_state => _}/corner_marker.dart (84%) rename patterns/state/manipulator_state/states/{ => _}/mixins/hover_shape_mixin.dart (91%) rename patterns/state/manipulator_state/states/{mixins => _}/paint_style.dart (100%) rename patterns/state/manipulator_state/states/{selections => _}/sub_states/child_state.dart (97%) rename patterns/state/manipulator_state/states/{selections => _}/sub_states/parent_state.dart (93%) rename patterns/state/manipulator_state/states/selections/{inner_radius => inner_radius_markers}/inner_radius_marker_state.dart (94%) rename patterns/state/manipulator_state/states/selections/{resizable_state => resizable_markers}/bottom_left_marker_state.dart (94%) rename patterns/state/manipulator_state/states/selections/{resizable_state => resizable_markers}/bottom_right_marker_state.dart (93%) rename patterns/state/manipulator_state/states/selections/{resizable_state => resizable_markers}/top_left_marker_state.dart (94%) rename patterns/state/manipulator_state/states/selections/{resizable_state => resizable_markers}/top_right_marker_state.dart (94%) diff --git a/patterns/state/manipulator_state/main.dart b/patterns/state/manipulator_state/main.dart index d564ea1..f235a2f 100644 --- a/patterns/state/manipulator_state/main.dart +++ b/patterns/state/manipulator_state/main.dart @@ -9,7 +9,7 @@ import 'states/creations/circle_creation_state.dart'; import 'states/creations/rectangle_creation_state.dart'; import 'states/creations/text_creation_state.dart'; import 'states/free_sate.dart'; -import 'states/mixins/paint_style.dart'; +import 'states/_/paint_style.dart'; import 'widgets/current_state.dart'; import 'widgets/drawing_board.dart'; import 'widgets/tool_bar.dart'; diff --git a/patterns/state/manipulator_state/pattern/manipulator.dart b/patterns/state/manipulator_state/pattern/manipulator.dart index 5a9e829..dc39ad6 100644 --- a/patterns/state/manipulator_state/pattern/manipulator.dart +++ b/patterns/state/manipulator_state/pattern/manipulator.dart @@ -1,8 +1,8 @@ library manipulator; import 'package:flutter/material.dart'; +import '../states/_/paint_style.dart'; import '../app/shapes.dart'; -import '../states/mixins/paint_style.dart'; part 'manipulation_state.dart'; part '../app/base_manipulationt.dart'; diff --git a/patterns/state/manipulator_state/states/selections/resizable_state/corner_marker.dart b/patterns/state/manipulator_state/states/_/corner_marker.dart similarity index 84% rename from patterns/state/manipulator_state/states/selections/resizable_state/corner_marker.dart rename to patterns/state/manipulator_state/states/_/corner_marker.dart index 9c46c0f..3fff2a0 100644 --- a/patterns/state/manipulator_state/states/selections/resizable_state/corner_marker.dart +++ b/patterns/state/manipulator_state/states/_/corner_marker.dart @@ -1,9 +1,9 @@ import 'package:flutter/rendering.dart'; -import '../../../shapes/marker_shape.dart'; -import '../sub_states/child_state.dart'; -import '../sub_states/parent_state.dart'; -import '../../../shapes/shape.dart'; +import '../../shapes/marker_shape.dart'; +import '../../shapes/shape.dart'; +import 'sub_states/child_state.dart'; +import 'sub_states/parent_state.dart'; abstract class CornerMarker extends ChildState { CornerMarker({ diff --git a/patterns/state/manipulator_state/states/mixins/hover_shape_mixin.dart b/patterns/state/manipulator_state/states/_/mixins/hover_shape_mixin.dart similarity index 91% rename from patterns/state/manipulator_state/states/mixins/hover_shape_mixin.dart rename to patterns/state/manipulator_state/states/_/mixins/hover_shape_mixin.dart index 98fc887..6e5679f 100644 --- a/patterns/state/manipulator_state/states/mixins/hover_shape_mixin.dart +++ b/patterns/state/manipulator_state/states/_/mixins/hover_shape_mixin.dart @@ -1,7 +1,7 @@ import 'package:flutter/material.dart'; -import '../../pattern/manipulator.dart'; -import '../../shapes/shape.dart'; +import '../../../pattern/manipulator.dart'; +import '../../../shapes/shape.dart'; mixin HoverShapeMixin implements ManipulationState { Shape? findShapeByCoordinates(double x, double y) { diff --git a/patterns/state/manipulator_state/states/mixins/paint_style.dart b/patterns/state/manipulator_state/states/_/paint_style.dart similarity index 100% rename from patterns/state/manipulator_state/states/mixins/paint_style.dart rename to patterns/state/manipulator_state/states/_/paint_style.dart diff --git a/patterns/state/manipulator_state/states/selections/sub_states/child_state.dart b/patterns/state/manipulator_state/states/_/sub_states/child_state.dart similarity index 97% rename from patterns/state/manipulator_state/states/selections/sub_states/child_state.dart rename to patterns/state/manipulator_state/states/_/sub_states/child_state.dart index 15bfcdd..2d66f0d 100644 --- a/patterns/state/manipulator_state/states/selections/sub_states/child_state.dart +++ b/patterns/state/manipulator_state/states/_/sub_states/child_state.dart @@ -4,7 +4,7 @@ import 'package:flutter/services.dart'; import '../../../shapes/shape.dart'; import '../../../pattern/manipulator.dart'; -import '../../mixins/hover_shape_mixin.dart'; +import '../../_/mixins/hover_shape_mixin.dart'; import 'parent_state.dart'; abstract class ChildState extends ManipulationState diff --git a/patterns/state/manipulator_state/states/selections/sub_states/parent_state.dart b/patterns/state/manipulator_state/states/_/sub_states/parent_state.dart similarity index 93% rename from patterns/state/manipulator_state/states/selections/sub_states/parent_state.dart rename to patterns/state/manipulator_state/states/_/sub_states/parent_state.dart index 2c8b217..e6e60b8 100644 --- a/patterns/state/manipulator_state/states/selections/sub_states/parent_state.dart +++ b/patterns/state/manipulator_state/states/_/sub_states/parent_state.dart @@ -1,7 +1,7 @@ import 'dart:ui'; -import '../sub_states/child_state.dart'; -import '../selection_state.dart'; +import '../../selections/selection_state.dart'; +import 'child_state.dart'; import '../../../shapes/shape.dart'; class ParentState extends SelectionState { diff --git a/patterns/state/manipulator_state/states/free_sate.dart b/patterns/state/manipulator_state/states/free_sate.dart index f1a9e62..c7e46ca 100644 --- a/patterns/state/manipulator_state/states/free_sate.dart +++ b/patterns/state/manipulator_state/states/free_sate.dart @@ -1,5 +1,5 @@ import '../pattern/manipulator.dart'; -import 'mixins/hover_shape_mixin.dart'; +import '_/mixins/hover_shape_mixin.dart'; import 'selections/moving_state.dart'; class FreeState extends ManipulationState with HoverShapeMixin { diff --git a/patterns/state/manipulator_state/states/selections/inner_radius/inner_radius_marker_state.dart b/patterns/state/manipulator_state/states/selections/inner_radius_markers/inner_radius_marker_state.dart similarity index 94% rename from patterns/state/manipulator_state/states/selections/inner_radius/inner_radius_marker_state.dart rename to patterns/state/manipulator_state/states/selections/inner_radius_markers/inner_radius_marker_state.dart index 72f1761..cdf5833 100644 --- a/patterns/state/manipulator_state/states/selections/inner_radius/inner_radius_marker_state.dart +++ b/patterns/state/manipulator_state/states/selections/inner_radius_markers/inner_radius_marker_state.dart @@ -1,7 +1,7 @@ import 'package:flutter/src/services/mouse_cursor.dart'; import '../../../shapes/circle_shape.dart'; -import '../resizable_state/corner_marker.dart'; +import '../../_/corner_marker.dart'; class InnerRadiusMarkerState extends CornerMarker { InnerRadiusMarkerState({required super.parentState}); diff --git a/patterns/state/manipulator_state/states/selections/inner_radius_state.dart b/patterns/state/manipulator_state/states/selections/inner_radius_state.dart index 87fa67a..25343fc 100644 --- a/patterns/state/manipulator_state/states/selections/inner_radius_state.dart +++ b/patterns/state/manipulator_state/states/selections/inner_radius_state.dart @@ -1,7 +1,7 @@ import 'package:flutter/material.dart'; import '../../shapes/circle_shape.dart'; -import 'inner_radius/inner_radius_marker_state.dart'; +import 'inner_radius_markers/inner_radius_marker_state.dart'; import 'resizable_state.dart'; class InnerRadiusState extends ResizableState { diff --git a/patterns/state/manipulator_state/states/selections/resizable_state/bottom_left_marker_state.dart b/patterns/state/manipulator_state/states/selections/resizable_markers/bottom_left_marker_state.dart similarity index 94% rename from patterns/state/manipulator_state/states/selections/resizable_state/bottom_left_marker_state.dart rename to patterns/state/manipulator_state/states/selections/resizable_markers/bottom_left_marker_state.dart index 47734fa..fc533ca 100644 --- a/patterns/state/manipulator_state/states/selections/resizable_state/bottom_left_marker_state.dart +++ b/patterns/state/manipulator_state/states/selections/resizable_markers/bottom_left_marker_state.dart @@ -1,4 +1,4 @@ -import 'corner_marker.dart'; +import '../../_/corner_marker.dart'; class BottomLeftMarkerState extends CornerMarker { BottomLeftMarkerState({ diff --git a/patterns/state/manipulator_state/states/selections/resizable_state/bottom_right_marker_state.dart b/patterns/state/manipulator_state/states/selections/resizable_markers/bottom_right_marker_state.dart similarity index 93% rename from patterns/state/manipulator_state/states/selections/resizable_state/bottom_right_marker_state.dart rename to patterns/state/manipulator_state/states/selections/resizable_markers/bottom_right_marker_state.dart index a87c563..9376cc6 100644 --- a/patterns/state/manipulator_state/states/selections/resizable_state/bottom_right_marker_state.dart +++ b/patterns/state/manipulator_state/states/selections/resizable_markers/bottom_right_marker_state.dart @@ -1,4 +1,4 @@ -import 'corner_marker.dart'; +import '../../_/corner_marker.dart'; class BottomRightMarkerState extends CornerMarker { BottomRightMarkerState({ diff --git a/patterns/state/manipulator_state/states/selections/resizable_state/top_left_marker_state.dart b/patterns/state/manipulator_state/states/selections/resizable_markers/top_left_marker_state.dart similarity index 94% rename from patterns/state/manipulator_state/states/selections/resizable_state/top_left_marker_state.dart rename to patterns/state/manipulator_state/states/selections/resizable_markers/top_left_marker_state.dart index 14d646b..59d1424 100644 --- a/patterns/state/manipulator_state/states/selections/resizable_state/top_left_marker_state.dart +++ b/patterns/state/manipulator_state/states/selections/resizable_markers/top_left_marker_state.dart @@ -1,4 +1,4 @@ -import 'corner_marker.dart'; +import '../../_/corner_marker.dart'; class TopLeftMarkerState extends CornerMarker { TopLeftMarkerState({ diff --git a/patterns/state/manipulator_state/states/selections/resizable_state/top_right_marker_state.dart b/patterns/state/manipulator_state/states/selections/resizable_markers/top_right_marker_state.dart similarity index 94% rename from patterns/state/manipulator_state/states/selections/resizable_state/top_right_marker_state.dart rename to patterns/state/manipulator_state/states/selections/resizable_markers/top_right_marker_state.dart index 7191c45..90cfecf 100644 --- a/patterns/state/manipulator_state/states/selections/resizable_state/top_right_marker_state.dart +++ b/patterns/state/manipulator_state/states/selections/resizable_markers/top_right_marker_state.dart @@ -1,4 +1,4 @@ -import 'corner_marker.dart'; +import '../../_/corner_marker.dart'; class TopRightMarkerState extends CornerMarker { TopRightMarkerState({ diff --git a/patterns/state/manipulator_state/states/selections/resizable_state.dart b/patterns/state/manipulator_state/states/selections/resizable_state.dart index 1377006..a4448a6 100644 --- a/patterns/state/manipulator_state/states/selections/resizable_state.dart +++ b/patterns/state/manipulator_state/states/selections/resizable_state.dart @@ -1,8 +1,8 @@ -import 'resizable_state/bottom_left_marker_state.dart'; -import 'resizable_state/bottom_right_marker_state.dart'; -import 'resizable_state/top_left_marker_state.dart'; -import 'resizable_state/top_right_marker_state.dart'; -import 'sub_states/parent_state.dart'; +import 'resizable_markers/bottom_left_marker_state.dart'; +import 'resizable_markers/bottom_right_marker_state.dart'; +import 'resizable_markers/top_left_marker_state.dart'; +import 'resizable_markers/top_right_marker_state.dart'; +import '../_/sub_states/parent_state.dart'; import '../../shapes/shape.dart'; class ResizableState extends ParentState { diff --git a/patterns/state/manipulator_state/states/selections/text_resize_state.dart b/patterns/state/manipulator_state/states/selections/text_resize_state.dart index 50659e8..d680c4d 100644 --- a/patterns/state/manipulator_state/states/selections/text_resize_state.dart +++ b/patterns/state/manipulator_state/states/selections/text_resize_state.dart @@ -1,8 +1,8 @@ import 'package:flutter/src/services/mouse_cursor.dart'; import '../../shapes/text_shape.dart'; -import 'resizable_state/corner_marker.dart'; -import 'sub_states/parent_state.dart'; +import '../_/corner_marker.dart'; +import '../_/sub_states/parent_state.dart'; class TextResizeState extends ParentState { TextResizeState({required super.selectedShape}) { From 4a92407c7d4b02f5cafb475a214092c95d04c3f0 Mon Sep 17 00:00:00 2001 From: ilopX Date: Mon, 30 May 2022 23:58:46 +0300 Subject: [PATCH 68/91] Rename marker to child. --- .../states/_/corner_marker.dart | 4 +-- .../states/_/sub_states/child_state.dart | 2 +- .../states/_/sub_states/parent_state.dart | 28 +++++++++---------- .../inner_radius_marker_state.dart | 2 +- .../states/selections/inner_radius_state.dart | 2 +- .../bottom_left_marker_state.dart | 2 +- .../bottom_right_marker_state.dart | 2 +- .../top_left_marker_state.dart | 2 +- .../top_right_marker_state.dart | 2 +- .../states/selections/resizable_state.dart | 2 +- .../states/selections/text_resize_state.dart | 4 +-- 11 files changed, 26 insertions(+), 26 deletions(-) diff --git a/patterns/state/manipulator_state/states/_/corner_marker.dart b/patterns/state/manipulator_state/states/_/corner_marker.dart index 3fff2a0..ea9a188 100644 --- a/patterns/state/manipulator_state/states/_/corner_marker.dart +++ b/patterns/state/manipulator_state/states/_/corner_marker.dart @@ -5,8 +5,8 @@ import '../../shapes/shape.dart'; import 'sub_states/child_state.dart'; import 'sub_states/parent_state.dart'; -abstract class CornerMarker extends ChildState { - CornerMarker({ +abstract class Marker extends ChildState { + Marker({ required ParentState parentState, }) : super( parentState: parentState, diff --git a/patterns/state/manipulator_state/states/_/sub_states/child_state.dart b/patterns/state/manipulator_state/states/_/sub_states/child_state.dart index 2d66f0d..b1a1747 100644 --- a/patterns/state/manipulator_state/states/_/sub_states/child_state.dart +++ b/patterns/state/manipulator_state/states/_/sub_states/child_state.dart @@ -48,7 +48,7 @@ abstract class ChildState extends ManipulationState super.mouseMove(x, y); if (_isDown) { mouseDragAction(x, y); - parentState.updateMarkers(); + parentState.updateKids(); context.cursor = hoverCursor; context.update(); } diff --git a/patterns/state/manipulator_state/states/_/sub_states/parent_state.dart b/patterns/state/manipulator_state/states/_/sub_states/parent_state.dart index e6e60b8..da151eb 100644 --- a/patterns/state/manipulator_state/states/_/sub_states/parent_state.dart +++ b/patterns/state/manipulator_state/states/_/sub_states/parent_state.dart @@ -9,21 +9,21 @@ class ParentState extends SelectionState { required super.selectedShape, }); - void addMarkers(List markers) { - _markers.addAll(markers); + void addChildren(List markers) { + _children.addAll(markers); } - void updateMarkers() { - for (final marker in _markers) { - marker.updatePosition(); + void updateKids() { + for (final child in _children) { + child.updatePosition(); } } @override void mouseDown(double x, double y) { - for (final marker in _markers) { - marker.mouseDown(x, y); - if (context.state == marker) { + for (final child in _children) { + child.mouseDown(x, y); + if (context.state == child) { return; } } @@ -35,9 +35,9 @@ class ParentState extends SelectionState { void mouseMove(double x, double y) { super.mouseMove(x, y); - for (final marker in _markers) { - marker.mouseMove(x, y); - if (marker.isHover) { + for (final child in _children) { + child.mouseMove(x, y); + if (child.isHover) { return; } } @@ -47,10 +47,10 @@ class ParentState extends SelectionState { void paint(Canvas canvas) { super.paint(canvas); - for (final marker in _markers) { - context.paintStyle.paintMarker(canvas, marker.markerShape); + for (final child in _children) { + context.paintStyle.paintMarker(canvas, child.markerShape); } } - final _markers = []; + final _children = []; } diff --git a/patterns/state/manipulator_state/states/selections/inner_radius_markers/inner_radius_marker_state.dart b/patterns/state/manipulator_state/states/selections/inner_radius_markers/inner_radius_marker_state.dart index cdf5833..5922cc5 100644 --- a/patterns/state/manipulator_state/states/selections/inner_radius_markers/inner_radius_marker_state.dart +++ b/patterns/state/manipulator_state/states/selections/inner_radius_markers/inner_radius_marker_state.dart @@ -3,7 +3,7 @@ import 'package:flutter/src/services/mouse_cursor.dart'; import '../../../shapes/circle_shape.dart'; import '../../_/corner_marker.dart'; -class InnerRadiusMarkerState extends CornerMarker { +class InnerRadiusMarkerState extends Marker { InnerRadiusMarkerState({required super.parentState}); @override diff --git a/patterns/state/manipulator_state/states/selections/inner_radius_state.dart b/patterns/state/manipulator_state/states/selections/inner_radius_state.dart index 25343fc..898b5b5 100644 --- a/patterns/state/manipulator_state/states/selections/inner_radius_state.dart +++ b/patterns/state/manipulator_state/states/selections/inner_radius_state.dart @@ -6,7 +6,7 @@ import 'resizable_state.dart'; class InnerRadiusState extends ResizableState { InnerRadiusState({required super.selectedShape}) { - addMarkers([ + addChildren([ InnerRadiusMarkerState(parentState: this), ]); } diff --git a/patterns/state/manipulator_state/states/selections/resizable_markers/bottom_left_marker_state.dart b/patterns/state/manipulator_state/states/selections/resizable_markers/bottom_left_marker_state.dart index fc533ca..dc391f5 100644 --- a/patterns/state/manipulator_state/states/selections/resizable_markers/bottom_left_marker_state.dart +++ b/patterns/state/manipulator_state/states/selections/resizable_markers/bottom_left_marker_state.dart @@ -1,6 +1,6 @@ import '../../_/corner_marker.dart'; -class BottomLeftMarkerState extends CornerMarker { +class BottomLeftMarkerState extends Marker { BottomLeftMarkerState({ required super.parentState, }); diff --git a/patterns/state/manipulator_state/states/selections/resizable_markers/bottom_right_marker_state.dart b/patterns/state/manipulator_state/states/selections/resizable_markers/bottom_right_marker_state.dart index 9376cc6..aabb9ec 100644 --- a/patterns/state/manipulator_state/states/selections/resizable_markers/bottom_right_marker_state.dart +++ b/patterns/state/manipulator_state/states/selections/resizable_markers/bottom_right_marker_state.dart @@ -1,6 +1,6 @@ import '../../_/corner_marker.dart'; -class BottomRightMarkerState extends CornerMarker { +class BottomRightMarkerState extends Marker { BottomRightMarkerState({ required super.parentState, }); diff --git a/patterns/state/manipulator_state/states/selections/resizable_markers/top_left_marker_state.dart b/patterns/state/manipulator_state/states/selections/resizable_markers/top_left_marker_state.dart index 59d1424..c2a3371 100644 --- a/patterns/state/manipulator_state/states/selections/resizable_markers/top_left_marker_state.dart +++ b/patterns/state/manipulator_state/states/selections/resizable_markers/top_left_marker_state.dart @@ -1,6 +1,6 @@ import '../../_/corner_marker.dart'; -class TopLeftMarkerState extends CornerMarker { +class TopLeftMarkerState extends Marker { TopLeftMarkerState({ required super.parentState, }); diff --git a/patterns/state/manipulator_state/states/selections/resizable_markers/top_right_marker_state.dart b/patterns/state/manipulator_state/states/selections/resizable_markers/top_right_marker_state.dart index 90cfecf..d75f8b3 100644 --- a/patterns/state/manipulator_state/states/selections/resizable_markers/top_right_marker_state.dart +++ b/patterns/state/manipulator_state/states/selections/resizable_markers/top_right_marker_state.dart @@ -1,6 +1,6 @@ import '../../_/corner_marker.dart'; -class TopRightMarkerState extends CornerMarker { +class TopRightMarkerState extends Marker { TopRightMarkerState({ required super.parentState, }); diff --git a/patterns/state/manipulator_state/states/selections/resizable_state.dart b/patterns/state/manipulator_state/states/selections/resizable_state.dart index a4448a6..92236b0 100644 --- a/patterns/state/manipulator_state/states/selections/resizable_state.dart +++ b/patterns/state/manipulator_state/states/selections/resizable_state.dart @@ -7,7 +7,7 @@ import '../../shapes/shape.dart'; class ResizableState extends ParentState { ResizableState({required super.selectedShape}) { - addMarkers([ + addChildren([ TopLeftMarkerState(parentState: this), TopRightMarkerState(parentState: this), BottomRightMarkerState(parentState: this), diff --git a/patterns/state/manipulator_state/states/selections/text_resize_state.dart b/patterns/state/manipulator_state/states/selections/text_resize_state.dart index d680c4d..d19325e 100644 --- a/patterns/state/manipulator_state/states/selections/text_resize_state.dart +++ b/patterns/state/manipulator_state/states/selections/text_resize_state.dart @@ -6,7 +6,7 @@ import '../_/sub_states/parent_state.dart'; class TextResizeState extends ParentState { TextResizeState({required super.selectedShape}) { - addMarkers([ + addChildren([ TextSizeMarkerState(parentState: this), ]); } @@ -17,7 +17,7 @@ class TextResizeState extends ParentState { } } -class TextSizeMarkerState extends CornerMarker { +class TextSizeMarkerState extends Marker { TextSizeMarkerState({required super.parentState}); @override From e657d9564e28fcdfe9f32d08bc75a93512d0c782 Mon Sep 17 00:00:00 2001 From: ilopX Date: Tue, 31 May 2022 00:00:29 +0300 Subject: [PATCH 69/91] Move abstract CreationState to "_" directory. --- .../states/{creations => _}/creation_state.dart | 0 .../states/creations/circle_creation_state.dart | 2 +- .../states/creations/rectangle_creation_state.dart | 2 +- .../manipulator_state/states/creations/text_creation_state.dart | 2 +- 4 files changed, 3 insertions(+), 3 deletions(-) rename patterns/state/manipulator_state/states/{creations => _}/creation_state.dart (100%) diff --git a/patterns/state/manipulator_state/states/creations/creation_state.dart b/patterns/state/manipulator_state/states/_/creation_state.dart similarity index 100% rename from patterns/state/manipulator_state/states/creations/creation_state.dart rename to patterns/state/manipulator_state/states/_/creation_state.dart diff --git a/patterns/state/manipulator_state/states/creations/circle_creation_state.dart b/patterns/state/manipulator_state/states/creations/circle_creation_state.dart index 63674d3..dabf811 100644 --- a/patterns/state/manipulator_state/states/creations/circle_creation_state.dart +++ b/patterns/state/manipulator_state/states/creations/circle_creation_state.dart @@ -1,6 +1,6 @@ import '../../shapes/circle_shape.dart'; import '../../shapes/shape.dart'; -import 'creation_state.dart'; +import '../_/creation_state.dart'; class CircleCreationState extends CreationState { @override diff --git a/patterns/state/manipulator_state/states/creations/rectangle_creation_state.dart b/patterns/state/manipulator_state/states/creations/rectangle_creation_state.dart index 75967fd..4a61891 100644 --- a/patterns/state/manipulator_state/states/creations/rectangle_creation_state.dart +++ b/patterns/state/manipulator_state/states/creations/rectangle_creation_state.dart @@ -1,6 +1,6 @@ import '../../shapes/rectangle_shape.dart'; import '../../shapes/shape.dart'; -import 'creation_state.dart'; +import '../_/creation_state.dart'; class RectangleCreationState extends CreationState { @override diff --git a/patterns/state/manipulator_state/states/creations/text_creation_state.dart b/patterns/state/manipulator_state/states/creations/text_creation_state.dart index 559c4c9..9ba634e 100644 --- a/patterns/state/manipulator_state/states/creations/text_creation_state.dart +++ b/patterns/state/manipulator_state/states/creations/text_creation_state.dart @@ -1,6 +1,6 @@ import '../../shapes/shape.dart'; import '../../shapes/text_shape.dart'; -import 'creation_state.dart'; +import '../_/creation_state.dart'; class TextCreationState extends CreationState { @override From f7ba8e27386fd151d493d6cd267f5e7139d43f3e Mon Sep 17 00:00:00 2001 From: ilopX Date: Tue, 31 May 2022 00:21:57 +0300 Subject: [PATCH 70/91] Fix TopRightMarkerState resize. --- .../resizable_markers/top_right_marker_state.dart | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/patterns/state/manipulator_state/states/selections/resizable_markers/top_right_marker_state.dart b/patterns/state/manipulator_state/states/selections/resizable_markers/top_right_marker_state.dart index d75f8b3..8bfdf40 100644 --- a/patterns/state/manipulator_state/states/selections/resizable_markers/top_right_marker_state.dart +++ b/patterns/state/manipulator_state/states/selections/resizable_markers/top_right_marker_state.dart @@ -7,11 +7,11 @@ class TopRightMarkerState extends Marker { @override void mouseDragAction(double x, double y) { - final newX = x - selectedShape.x; - final newY = selectedShape.height + selectedShape.y - y; + final width = x - selectedShape.x; + final height = selectedShape.height + selectedShape.y - y; - selectedShape.resize(newX, newY); - selectedShape.move(selectedShape.x, newY); + selectedShape.resize(width, height); + selectedShape.move(selectedShape.x, y); } @override From 76ce7db2f10a7297518c085d85bff71d4695b634 Mon Sep 17 00:00:00 2001 From: ilopX Date: Tue, 31 May 2022 00:59:02 +0300 Subject: [PATCH 71/91] Refactoring InnerRadiusMarkerState. Replace selectedCircle variable to selectedShape. --- .../inner_radius_marker_state.dart | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/patterns/state/manipulator_state/states/selections/inner_radius_markers/inner_radius_marker_state.dart b/patterns/state/manipulator_state/states/selections/inner_radius_markers/inner_radius_marker_state.dart index 5922cc5..97a4d00 100644 --- a/patterns/state/manipulator_state/states/selections/inner_radius_markers/inner_radius_marker_state.dart +++ b/patterns/state/manipulator_state/states/selections/inner_radius_markers/inner_radius_marker_state.dart @@ -8,17 +8,16 @@ class InnerRadiusMarkerState extends Marker { @override void mouseDragAction(double x, double y) { - final selectedCircle = parentState.selectedShape; - selectedCircle.innerRadius = selectedCircle.rect.right - x; + selectedShape.innerRadius = selectedShape.rect.right - x; } @override void updatePosition() { - final selectedCircle = parentState.selectedShape; - final y = selectedCircle.y + selectedCircle.height / 2; - final x = selectedCircle.x + selectedCircle.width; + final y = selectedShape.y + selectedShape.height / 2; + final x = selectedShape.x + selectedShape.width; + markerShape.move( - x - selectedCircle.innerRadius, + x - selectedShape.innerRadius, y, ); } From 86d953320a018836c0d78aca946aa7798de5b30e Mon Sep 17 00:00:00 2001 From: ilopX Date: Tue, 31 May 2022 01:03:35 +0300 Subject: [PATCH 72/91] Move TextSizeMarkerState to separate file. --- .../text_resize_marker_state.dart | 28 +++++++++++++++++++ .../states/selections/text_resize_state.dart | 28 +------------------ 2 files changed, 29 insertions(+), 27 deletions(-) create mode 100644 patterns/state/manipulator_state/states/selections/text_resize_marker/text_resize_marker_state.dart diff --git a/patterns/state/manipulator_state/states/selections/text_resize_marker/text_resize_marker_state.dart b/patterns/state/manipulator_state/states/selections/text_resize_marker/text_resize_marker_state.dart new file mode 100644 index 0000000..5499c89 --- /dev/null +++ b/patterns/state/manipulator_state/states/selections/text_resize_marker/text_resize_marker_state.dart @@ -0,0 +1,28 @@ +import 'package:flutter/services.dart'; + +import '../../../shapes/text_shape.dart'; +import '../../_/corner_marker.dart'; + +class TextSizeMarkerState extends Marker { + TextSizeMarkerState({required super.parentState}); + + @override + void mouseDragAction(double x, double y) { + final newHeight = y - selectedShape.y; + selectedShape.resize(-1, newHeight); + } + + @override + void updatePosition() { + final bottomCenter = selectedShape.rect.bottomCenter; + markerShape.move(bottomCenter.dx, bottomCenter.dy); + } + + @override + MouseCursor get hoverCursor => SystemMouseCursors.resizeUpDown; + + @override + String toString() { + return '${parentState.toString()} + Text Size Marker State'; + } +} diff --git a/patterns/state/manipulator_state/states/selections/text_resize_state.dart b/patterns/state/manipulator_state/states/selections/text_resize_state.dart index d19325e..4d62eb3 100644 --- a/patterns/state/manipulator_state/states/selections/text_resize_state.dart +++ b/patterns/state/manipulator_state/states/selections/text_resize_state.dart @@ -1,8 +1,6 @@ -import 'package:flutter/src/services/mouse_cursor.dart'; - import '../../shapes/text_shape.dart'; -import '../_/corner_marker.dart'; import '../_/sub_states/parent_state.dart'; +import 'text_resize_marker/text_resize_marker_state.dart'; class TextResizeState extends ParentState { TextResizeState({required super.selectedShape}) { @@ -16,27 +14,3 @@ class TextResizeState extends ParentState { return '${super.toString()} + Text Resize State'; } } - -class TextSizeMarkerState extends Marker { - TextSizeMarkerState({required super.parentState}); - - @override - void mouseDragAction(double x, double y) { - final newHeight = y - selectedShape.y; - selectedShape.resize(-1, newHeight); - } - - @override - void updatePosition() { - final bottomCenter = selectedShape.rect.bottomCenter; - markerShape.move(bottomCenter.dx, bottomCenter.dy); - } - - @override - MouseCursor get hoverCursor => SystemMouseCursors.resizeUpDown; - - @override - String toString() { - return '${parentState.toString()} + Text Size Marker State'; - } -} From fa1331668c9167c64ae1d78a0f3024731e7f4708 Mon Sep 17 00:00:00 2001 From: ilopX Date: Tue, 31 May 2022 01:08:39 +0300 Subject: [PATCH 73/91] Refactoring BottomLeftMarkerState, TopRightMarkerState: remove unnecessary variables. --- .../resizable_markers/bottom_left_marker_state.dart | 5 +++-- .../selections/resizable_markers/top_right_marker_state.dart | 5 +++-- 2 files changed, 6 insertions(+), 4 deletions(-) diff --git a/patterns/state/manipulator_state/states/selections/resizable_markers/bottom_left_marker_state.dart b/patterns/state/manipulator_state/states/selections/resizable_markers/bottom_left_marker_state.dart index dc391f5..713c5d9 100644 --- a/patterns/state/manipulator_state/states/selections/resizable_markers/bottom_left_marker_state.dart +++ b/patterns/state/manipulator_state/states/selections/resizable_markers/bottom_left_marker_state.dart @@ -10,8 +10,9 @@ class BottomLeftMarkerState extends Marker { final newX = selectedShape.width + selectedShape.x - x; final newY = y - selectedShape.y; - selectedShape.resize(newX, newY); - selectedShape.move(x, selectedShape.y); + selectedShape + ..resize(newX, newY) + ..move(x, selectedShape.y); } @override diff --git a/patterns/state/manipulator_state/states/selections/resizable_markers/top_right_marker_state.dart b/patterns/state/manipulator_state/states/selections/resizable_markers/top_right_marker_state.dart index 8bfdf40..ed18b97 100644 --- a/patterns/state/manipulator_state/states/selections/resizable_markers/top_right_marker_state.dart +++ b/patterns/state/manipulator_state/states/selections/resizable_markers/top_right_marker_state.dart @@ -10,8 +10,9 @@ class TopRightMarkerState extends Marker { final width = x - selectedShape.x; final height = selectedShape.height + selectedShape.y - y; - selectedShape.resize(width, height); - selectedShape.move(selectedShape.x, y); + selectedShape + ..resize(width, height) + ..move(selectedShape.x, y); } @override From 518ada60fae6cd4acfa8c03cf51a01d59e380549 Mon Sep 17 00:00:00 2001 From: ilopX Date: Tue, 31 May 2022 15:09:54 +0300 Subject: [PATCH 74/91] Add double click event. --- .../app/base_manipulationt.dart | 5 ++ .../pattern/manipulation_state.dart | 2 + .../pattern/manipulator.dart | 2 + .../widgets/drawing_board.dart | 67 ++++++++++--------- 4 files changed, 44 insertions(+), 32 deletions(-) diff --git a/patterns/state/manipulator_state/app/base_manipulationt.dart b/patterns/state/manipulator_state/app/base_manipulationt.dart index 3a04e28..9c75187 100644 --- a/patterns/state/manipulator_state/app/base_manipulationt.dart +++ b/patterns/state/manipulator_state/app/base_manipulationt.dart @@ -58,6 +58,11 @@ class BaseManipulator implements Manipulator { _state.mouseUp(); } + @override + void mouseDoubleClick() { + _state.mouseDoubleClick(); + } + @override void keyDown(String key) { _state.keyDown(key); diff --git a/patterns/state/manipulator_state/pattern/manipulation_state.dart b/patterns/state/manipulator_state/pattern/manipulation_state.dart index dd7b036..75d64ce 100644 --- a/patterns/state/manipulator_state/pattern/manipulation_state.dart +++ b/patterns/state/manipulator_state/pattern/manipulation_state.dart @@ -9,6 +9,8 @@ class ManipulationState { void mouseUp() {} + void mouseDoubleClick() {} + void keyDown(String key) {} void paint(Canvas canvas) {} diff --git a/patterns/state/manipulator_state/pattern/manipulator.dart b/patterns/state/manipulator_state/pattern/manipulator.dart index dc39ad6..6bb973b 100644 --- a/patterns/state/manipulator_state/pattern/manipulator.dart +++ b/patterns/state/manipulator_state/pattern/manipulator.dart @@ -32,6 +32,8 @@ abstract class Manipulator { void mouseUp(); + void mouseDoubleClick(); + void keyDown(String key); void paint(Canvas canvas); diff --git a/patterns/state/manipulator_state/widgets/drawing_board.dart b/patterns/state/manipulator_state/widgets/drawing_board.dart index f0a37b0..880b6bf 100644 --- a/patterns/state/manipulator_state/widgets/drawing_board.dart +++ b/patterns/state/manipulator_state/widgets/drawing_board.dart @@ -10,38 +10,41 @@ class DrawingBoard extends StatelessWidget { @override Widget build(BuildContext context) { - return Listener( - onPointerDown: (e) => app.manipulator.mouseDown( - e.localPosition.dx, - e.localPosition.dy, - ), - onPointerHover: (e) => app.manipulator.mouseMove( - e.localPosition.dx, - e.localPosition.dy, - ), - onPointerMove: (e) => app.manipulator.mouseMove( - e.localPosition.dx, - e.localPosition.dy, - ), - onPointerUp: (e) => app.manipulator.mouseUp(), - child: Container( - constraints: BoxConstraints.expand(), - color: Color(0xff1f1f1f), - child: EventListenableBuilder( - event: app.shapes.onChange, - builder: (_) { - return EventListenableBuilder( - event: app.manipulator.onUpdate, - builder: (_) { - return MouseRegion( - cursor: app.manipulator.cursor, - child: CustomPaint( - painter: _Painter(app), - ), - ); - }, - ); - }, + return GestureDetector( + onDoubleTap: app.manipulator.mouseDoubleClick, + child: Listener( + onPointerDown: (e) => app.manipulator.mouseDown( + e.localPosition.dx, + e.localPosition.dy, + ), + onPointerHover: (e) => app.manipulator.mouseMove( + e.localPosition.dx, + e.localPosition.dy, + ), + onPointerMove: (e) => app.manipulator.mouseMove( + e.localPosition.dx, + e.localPosition.dy, + ), + onPointerUp: (e) => app.manipulator.mouseUp(), + child: Container( + constraints: BoxConstraints.expand(), + color: Color(0xff1f1f1f), + child: EventListenableBuilder( + event: app.shapes.onChange, + builder: (_) { + return EventListenableBuilder( + event: app.manipulator.onUpdate, + builder: (_) { + return MouseRegion( + cursor: app.manipulator.cursor, + child: CustomPaint( + painter: _Painter(app), + ), + ); + }, + ); + }, + ), ), ), ); From a90961414347a9c56b9b9b4d327bf5d43a73ad38 Mon Sep 17 00:00:00 2001 From: ilopX Date: Tue, 31 May 2022 17:43:56 +0300 Subject: [PATCH 75/91] Add keyboard event. --- .../app/base_manipulationt.dart | 4 +- .../pattern/manipulation_state.dart | 2 +- .../pattern/manipulator.dart | 2 +- .../widgets/drawing_board.dart | 97 ++++++++++++------- 4 files changed, 66 insertions(+), 39 deletions(-) diff --git a/patterns/state/manipulator_state/app/base_manipulationt.dart b/patterns/state/manipulator_state/app/base_manipulationt.dart index 9c75187..2896e53 100644 --- a/patterns/state/manipulator_state/app/base_manipulationt.dart +++ b/patterns/state/manipulator_state/app/base_manipulationt.dart @@ -64,8 +64,8 @@ class BaseManipulator implements Manipulator { } @override - void keyDown(String key) { - _state.keyDown(key); + void keyDown(KeyEvent keyEvent) { + _state.keyDown(keyEvent); } @override diff --git a/patterns/state/manipulator_state/pattern/manipulation_state.dart b/patterns/state/manipulator_state/pattern/manipulation_state.dart index 75d64ce..ffd201f 100644 --- a/patterns/state/manipulator_state/pattern/manipulation_state.dart +++ b/patterns/state/manipulator_state/pattern/manipulation_state.dart @@ -11,7 +11,7 @@ class ManipulationState { void mouseDoubleClick() {} - void keyDown(String key) {} + void keyDown(KeyEvent keyEvent) {} void paint(Canvas canvas) {} diff --git a/patterns/state/manipulator_state/pattern/manipulator.dart b/patterns/state/manipulator_state/pattern/manipulator.dart index 6bb973b..8be5b05 100644 --- a/patterns/state/manipulator_state/pattern/manipulator.dart +++ b/patterns/state/manipulator_state/pattern/manipulator.dart @@ -34,7 +34,7 @@ abstract class Manipulator { void mouseDoubleClick(); - void keyDown(String key); + void keyDown(KeyEvent keyEvent); void paint(Canvas canvas); } diff --git a/patterns/state/manipulator_state/widgets/drawing_board.dart b/patterns/state/manipulator_state/widgets/drawing_board.dart index 880b6bf..f3be1b0 100644 --- a/patterns/state/manipulator_state/widgets/drawing_board.dart +++ b/patterns/state/manipulator_state/widgets/drawing_board.dart @@ -3,52 +3,79 @@ import 'package:flutter/material.dart'; import '../../../abstract_factory/tool_panel_factory/widgets/independent/event_listenable_builder.dart'; import '../app/app.dart'; -class DrawingBoard extends StatelessWidget { +class DrawingBoard extends StatefulWidget { final App app; const DrawingBoard({Key? key, required this.app}) : super(key: key); + @override + State createState() => _DrawingBoardState(); +} + +class _DrawingBoardState extends State { + late FocusNode focusNode; + + @override + void initState() { + focusNode = FocusNode(skipTraversal: true); + super.initState(); + } + @override Widget build(BuildContext context) { - return GestureDetector( - onDoubleTap: app.manipulator.mouseDoubleClick, - child: Listener( - onPointerDown: (e) => app.manipulator.mouseDown( - e.localPosition.dx, - e.localPosition.dy, - ), - onPointerHover: (e) => app.manipulator.mouseMove( - e.localPosition.dx, - e.localPosition.dy, - ), - onPointerMove: (e) => app.manipulator.mouseMove( - e.localPosition.dx, - e.localPosition.dy, - ), - onPointerUp: (e) => app.manipulator.mouseUp(), - child: Container( - constraints: BoxConstraints.expand(), - color: Color(0xff1f1f1f), - child: EventListenableBuilder( - event: app.shapes.onChange, - builder: (_) { - return EventListenableBuilder( - event: app.manipulator.onUpdate, - builder: (_) { - return MouseRegion( - cursor: app.manipulator.cursor, - child: CustomPaint( - painter: _Painter(app), - ), - ); - }, - ); - }, + return KeyboardListener( + autofocus: true, + focusNode: focusNode, + onKeyEvent: widget.app.manipulator.keyDown, + child: GestureDetector( + onDoubleTap: widget.app.manipulator.mouseDoubleClick, + child: Listener( + onPointerDown: (e) { + FocusScope.of(context).requestFocus(focusNode); + widget.app.manipulator.mouseDown( + e.localPosition.dx, + e.localPosition.dy, + ); + }, + onPointerHover: (e) => widget.app.manipulator.mouseMove( + e.localPosition.dx, + e.localPosition.dy, + ), + onPointerMove: (e) => widget.app.manipulator.mouseMove( + e.localPosition.dx, + e.localPosition.dy, + ), + onPointerUp: (e) => widget.app.manipulator.mouseUp(), + child: Container( + constraints: BoxConstraints.expand(), + color: Color(0xff1f1f1f), + child: EventListenableBuilder( + event: widget.app.shapes.onChange, + builder: (_) { + return EventListenableBuilder( + event: widget.app.manipulator.onUpdate, + builder: (_) { + return MouseRegion( + cursor: widget.app.manipulator.cursor, + child: CustomPaint( + painter: _Painter(widget.app), + ), + ); + }, + ); + }, + ), ), ), ), ); } + + @override + void dispose() { + focusNode.dispose(); + super.dispose(); + } } class _Painter extends CustomPainter { From 8c478b811ccec25ae42dbb3b40e19603512694ff Mon Sep 17 00:00:00 2001 From: ilopX Date: Tue, 31 May 2022 17:46:50 +0300 Subject: [PATCH 76/91] Add TextChangeState. --- .../manipulator_state/shapes/text_shape.dart | 10 ++++- .../states/selections/text_change_state.dart | 40 +++++++++++++++++++ .../states/selections/text_resize_state.dart | 10 +++++ 3 files changed, 59 insertions(+), 1 deletion(-) create mode 100644 patterns/state/manipulator_state/states/selections/text_change_state.dart diff --git a/patterns/state/manipulator_state/shapes/text_shape.dart b/patterns/state/manipulator_state/shapes/text_shape.dart index fd973af..f510e7e 100644 --- a/patterns/state/manipulator_state/shapes/text_shape.dart +++ b/patterns/state/manipulator_state/shapes/text_shape.dart @@ -9,6 +9,13 @@ class TextShape extends BaseShape { _buildParagraph(); } + set text(String newText) { + _text = newText; + _buildParagraph(); + } + + String get text => _text; + @override void paint(Canvas can) { can.drawParagraph(_paragraph, Offset(x, y)); @@ -49,10 +56,11 @@ class TextShape extends BaseShape { ); _paragraph = (ParagraphBuilder(style) ..pushStyle(tStyle) - ..addText('Text')) + ..addText(_text)) .build(); _paragraph.layout(ParagraphConstraints(width: double.infinity)); } late Paragraph _paragraph; + String _text = 'Text'; } diff --git a/patterns/state/manipulator_state/states/selections/text_change_state.dart b/patterns/state/manipulator_state/states/selections/text_change_state.dart new file mode 100644 index 0000000..7a5c207 --- /dev/null +++ b/patterns/state/manipulator_state/states/selections/text_change_state.dart @@ -0,0 +1,40 @@ +import 'package:flutter/material.dart'; +import 'package:flutter/services.dart'; + +import '../../shapes/text_shape.dart'; +import 'selection_state.dart'; + +class TextChangeState extends SelectionState { + TextChangeState({required super.selectedShape}); + + @override + void mouseDown(double x, double y) { + super.mouseDown(x, y); + if (selectedShape.rect.contains(Offset(x, y))) { + } else {} + } + + @override + void keyDown(KeyEvent keyEvent) { + if ((keyEvent is KeyDownEvent || keyEvent is KeyRepeatEvent) && + keyEvent.character != null) { + print(keyEvent.character); + selectedShape.text += keyEvent.character!; + context.update(); + } + } + + @override + void paint(Canvas canvas) { + canvas.drawRect( + selectedShape.rect, + Paint()..color = Colors.pink.withOpacity(0.3), + ); + super.paint(canvas); + } + + @override + String toString() { + return '${super.toString()} + Text Change State'; + } +} diff --git a/patterns/state/manipulator_state/states/selections/text_resize_state.dart b/patterns/state/manipulator_state/states/selections/text_resize_state.dart index 4d62eb3..cf64e30 100644 --- a/patterns/state/manipulator_state/states/selections/text_resize_state.dart +++ b/patterns/state/manipulator_state/states/selections/text_resize_state.dart @@ -1,5 +1,6 @@ import '../../shapes/text_shape.dart'; import '../_/sub_states/parent_state.dart'; +import 'text_change_state.dart'; import 'text_resize_marker/text_resize_marker_state.dart'; class TextResizeState extends ParentState { @@ -9,6 +10,15 @@ class TextResizeState extends ParentState { ]); } + @override + void mouseDoubleClick() { + context.changeState( + TextChangeState( + selectedShape: selectedShape, + ), + ); + } + @override String toString() { return '${super.toString()} + Text Resize State'; From 399f86a6d9058bd828dd576a06b1fe402918b630 Mon Sep 17 00:00:00 2001 From: ilopX Date: Wed, 1 Jun 2022 23:28:49 +0300 Subject: [PATCH 77/91] Add (x,y) to mousedDoubleClick. --- patterns/state/manipulator_state/app/base_manipulationt.dart | 4 ++-- .../state/manipulator_state/pattern/manipulation_state.dart | 2 +- patterns/state/manipulator_state/pattern/manipulator.dart | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/patterns/state/manipulator_state/app/base_manipulationt.dart b/patterns/state/manipulator_state/app/base_manipulationt.dart index 2896e53..fa92f2e 100644 --- a/patterns/state/manipulator_state/app/base_manipulationt.dart +++ b/patterns/state/manipulator_state/app/base_manipulationt.dart @@ -59,8 +59,8 @@ class BaseManipulator implements Manipulator { } @override - void mouseDoubleClick() { - _state.mouseDoubleClick(); + void mouseDoubleClick(double x, double y) { + _state.mouseDoubleClick(x, y); } @override diff --git a/patterns/state/manipulator_state/pattern/manipulation_state.dart b/patterns/state/manipulator_state/pattern/manipulation_state.dart index ffd201f..167b6ec 100644 --- a/patterns/state/manipulator_state/pattern/manipulation_state.dart +++ b/patterns/state/manipulator_state/pattern/manipulation_state.dart @@ -9,7 +9,7 @@ class ManipulationState { void mouseUp() {} - void mouseDoubleClick() {} + void mouseDoubleClick(double x, double y) {} void keyDown(KeyEvent keyEvent) {} diff --git a/patterns/state/manipulator_state/pattern/manipulator.dart b/patterns/state/manipulator_state/pattern/manipulator.dart index 8be5b05..a14eb31 100644 --- a/patterns/state/manipulator_state/pattern/manipulator.dart +++ b/patterns/state/manipulator_state/pattern/manipulator.dart @@ -32,7 +32,7 @@ abstract class Manipulator { void mouseUp(); - void mouseDoubleClick(); + void mouseDoubleClick(double x, double y); void keyDown(KeyEvent keyEvent); From 95e370d6f49225574e504553387c3dcebce509ef Mon Sep 17 00:00:00 2001 From: ilopX Date: Wed, 1 Jun 2022 23:29:32 +0300 Subject: [PATCH 78/91] Add method init() to State interface. --- patterns/state/manipulator_state/app/base_manipulationt.dart | 1 + .../state/manipulator_state/pattern/manipulation_state.dart | 2 ++ 2 files changed, 3 insertions(+) diff --git a/patterns/state/manipulator_state/app/base_manipulationt.dart b/patterns/state/manipulator_state/app/base_manipulationt.dart index fa92f2e..85db133 100644 --- a/patterns/state/manipulator_state/app/base_manipulationt.dart +++ b/patterns/state/manipulator_state/app/base_manipulationt.dart @@ -35,6 +35,7 @@ class BaseManipulator implements Manipulator { _state = newState; _state._context = this; + _state.init(); onStateChange._emit(); } diff --git a/patterns/state/manipulator_state/pattern/manipulation_state.dart b/patterns/state/manipulator_state/pattern/manipulation_state.dart index 167b6ec..49221a2 100644 --- a/patterns/state/manipulator_state/pattern/manipulation_state.dart +++ b/patterns/state/manipulator_state/pattern/manipulation_state.dart @@ -3,6 +3,8 @@ part of manipulator; class ManipulationState { Manipulator get context => _context; + void init() {} + void mouseMove(double x, double y) {} void mouseDown(double x, double y) {} From f7c6fba299e90f2b48b30f1625655400b1a9e1da Mon Sep 17 00:00:00 2001 From: ilopX Date: Wed, 1 Jun 2022 23:30:27 +0300 Subject: [PATCH 79/91] Fix height changer. --- .../manipulator_state/shapes/text_shape.dart | 40 +++++++++++-------- 1 file changed, 24 insertions(+), 16 deletions(-) diff --git a/patterns/state/manipulator_state/shapes/text_shape.dart b/patterns/state/manipulator_state/shapes/text_shape.dart index f510e7e..9c8d51f 100644 --- a/patterns/state/manipulator_state/shapes/text_shape.dart +++ b/patterns/state/manipulator_state/shapes/text_shape.dart @@ -5,16 +5,26 @@ import '../states/selections/text_resize_state.dart'; import 'base_shape.dart'; class TextShape extends BaseShape { - TextShape(super.x, super.y, super.width, super.height) { - _buildParagraph(); + TextShape(double x, double y, double height) : super(x, y, 0, height) { + _buildParagraph(height); } + String get text => _text; + set text(String newText) { _text = newText; - _buildParagraph(); + _buildParagraph(_textHeight); } - String get text => _text; + double get userHeight => _textHeight; + + Paragraph get paragraph => _paragraph; + + @override + Rect get rect { + final fixY = height - _textHeight; + return Rect.fromLTWH(x, y + fixY, width, height - fixY); + } @override void paint(Canvas can) { @@ -26,41 +36,39 @@ class TextShape extends BaseShape { return TextResizeState(selectedShape: this); } - @override - double get width => _paragraph.maxIntrinsicWidth; - - @override - Rect get rect => Rect.fromLTWH(x, y, width, height); - @override void resize(double _, double newHeight) { if (newHeight < 2) { newHeight = 2; } - super.resize(_, newHeight); - final prevWidth = width; - _buildParagraph(); - final centerX = x + (prevWidth - width) / 2; + final oldWidth = width; + _buildParagraph(newHeight); + final centerX = x - (width - oldWidth) / 2; move(centerX, y); } - void _buildParagraph() { + void _buildParagraph(double newHeight) { + _textHeight = newHeight; + final style = ParagraphStyle( textDirection: TextDirection.ltr, ); final tStyle = TextStyle( fontFamily: 'Arial', color: Color(0xffffffff), - fontSize: height, + fontSize: newHeight, ); _paragraph = (ParagraphBuilder(style) ..pushStyle(tStyle) ..addText(_text)) .build(); _paragraph.layout(ParagraphConstraints(width: double.infinity)); + + super.resize(_paragraph.maxIntrinsicWidth, _paragraph.height); } late Paragraph _paragraph; String _text = 'Text'; + late double _textHeight; } From 4d67df97d2be73cf8a0d83311dd798b5cde6d342 Mon Sep 17 00:00:00 2001 From: ilopX Date: Wed, 1 Jun 2022 23:31:04 +0300 Subject: [PATCH 80/91] Add (x, y) to view. --- .../state/manipulator_state/widgets/drawing_board.dart | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/patterns/state/manipulator_state/widgets/drawing_board.dart b/patterns/state/manipulator_state/widgets/drawing_board.dart index f3be1b0..2f25926 100644 --- a/patterns/state/manipulator_state/widgets/drawing_board.dart +++ b/patterns/state/manipulator_state/widgets/drawing_board.dart @@ -14,6 +14,7 @@ class DrawingBoard extends StatefulWidget { class _DrawingBoardState extends State { late FocusNode focusNode; + late Offset _lastMouseDown; @override void initState() { @@ -28,9 +29,13 @@ class _DrawingBoardState extends State { focusNode: focusNode, onKeyEvent: widget.app.manipulator.keyDown, child: GestureDetector( - onDoubleTap: widget.app.manipulator.mouseDoubleClick, + onDoubleTap: () => widget.app.manipulator.mouseDoubleClick( + _lastMouseDown.dx, + _lastMouseDown.dy, + ), child: Listener( onPointerDown: (e) { + _lastMouseDown = e.localPosition; FocusScope.of(context).requestFocus(focusNode); widget.app.manipulator.mouseDown( e.localPosition.dx, From 7588a769c43a3c2e74e67c55ab2eed98d212dc2c Mon Sep 17 00:00:00 2001 From: ilopX Date: Wed, 1 Jun 2022 23:34:07 +0300 Subject: [PATCH 81/91] Add text editor. * Add TextCursor class. * Add cursor & selectedText painter. * Add hover text cursor. * Change TextShape factory to default height = 2. * Add startPoint cursor to TextChangeState. --- .../states/_/paint_style.dart | 21 +++ .../states/creations/text_creation_state.dart | 2 +- .../states/selections/text_change_state.dart | 123 ++++++++++++++++-- .../text_resize_marker_state.dart | 6 +- .../states/selections/text_resize_state.dart | 5 +- 5 files changed, 141 insertions(+), 16 deletions(-) diff --git a/patterns/state/manipulator_state/states/_/paint_style.dart b/patterns/state/manipulator_state/states/_/paint_style.dart index 90cb74a..3f34cac 100644 --- a/patterns/state/manipulator_state/states/_/paint_style.dart +++ b/patterns/state/manipulator_state/states/_/paint_style.dart @@ -2,6 +2,8 @@ import 'package:flutter/material.dart'; import '../../shapes/circle_shape.dart'; import '../../shapes/shape.dart'; +import '../../shapes/text_shape.dart'; +import '../selections/text_change_state.dart'; class PaintStyle { PaintStyle(this.color) @@ -60,6 +62,25 @@ class PaintStyle { canvas.restore(); } + void paintSelectedText(TextShape selectedShape, Canvas canvas) { + canvas.drawRect( + selectedShape.rect, + Paint()..color = color.withOpacity(0.3), + ); + } + + void paintTextCursor( + TextCursor cursor, TextShape selectedShape, Canvas canvas) { + canvas.drawRect( + Rect.fromLTWH( + cursor.xCoordinate, + selectedShape.y + (selectedShape.height - selectedShape.userHeight), + 1.5, + selectedShape.userHeight), + Paint()..color = Colors.white, + ); + } + final Paint _selectStroke; final Paint _markerStroke; final Paint _markerFill; diff --git a/patterns/state/manipulator_state/states/creations/text_creation_state.dart b/patterns/state/manipulator_state/states/creations/text_creation_state.dart index 9ba634e..4425a84 100644 --- a/patterns/state/manipulator_state/states/creations/text_creation_state.dart +++ b/patterns/state/manipulator_state/states/creations/text_creation_state.dart @@ -5,7 +5,7 @@ import '../_/creation_state.dart'; class TextCreationState extends CreationState { @override Shape createShape(double x, double y) { - return TextShape(x, y, 2, 2); + return TextShape(x, y, 2); } @override diff --git a/patterns/state/manipulator_state/states/selections/text_change_state.dart b/patterns/state/manipulator_state/states/selections/text_change_state.dart index 7a5c207..56b924a 100644 --- a/patterns/state/manipulator_state/states/selections/text_change_state.dart +++ b/patterns/state/manipulator_state/states/selections/text_change_state.dart @@ -5,36 +5,135 @@ import '../../shapes/text_shape.dart'; import 'selection_state.dart'; class TextChangeState extends SelectionState { - TextChangeState({required super.selectedShape}); + TextChangeState({ + required Offset startPointer, + required super.selectedShape, + }) : _startPointer = startPointer, + _textCursor = TextCursor(selectedShape); + + @override + void init() { + _textCursor.changePosition(_startPointer.dx, _startPointer.dy); + context.cursor = SystemMouseCursors.text; + context.update(); + } @override void mouseDown(double x, double y) { - super.mouseDown(x, y); if (selectedShape.rect.contains(Offset(x, y))) { - } else {} + _textCursor.changePosition(x, y); + context.update(); + return; + } + + super.mouseDown(x, y); } @override void keyDown(KeyEvent keyEvent) { - if ((keyEvent is KeyDownEvent || keyEvent is KeyRepeatEvent) && - keyEvent.character != null) { - print(keyEvent.character); - selectedShape.text += keyEvent.character!; - context.update(); + if (keyEvent is KeyDownEvent || keyEvent is KeyRepeatEvent) { + if (keyEvent.physicalKey == PhysicalKeyboardKey.backspace) { + _textCursor.backspace(); + context.update(); + } else if (keyEvent.character != null) { + _textCursor.inputText(keyEvent.character!); + context.update(); + } } } @override void paint(Canvas canvas) { - canvas.drawRect( - selectedShape.rect, - Paint()..color = Colors.pink.withOpacity(0.3), - ); + context.paintStyle.paintSelectedText(selectedShape, canvas); super.paint(canvas); + context.paintStyle.paintTextCursor(_textCursor, selectedShape, canvas); + } + + @override + void onHover() { + if (hoverShape == selectedShape) { + context.cursor = SystemMouseCursors.text; + } } + @override + void onMouseLeave() { + context.cursor = SystemMouseCursors.basic; + } + + double xx0 = 0; + int len = 0; + final Offset _startPointer; + final TextCursor _textCursor; + @override String toString() { return '${super.toString()} + Text Change State'; } } + +class TextCursor { + TextCursor(this._shape); + + double get xCoordinate => _xPosition; + + void changePosition(double x, double y) { + x = x - _shape.x; + y = y - _shape.y; + + final pos = _shape.paragraph.getPositionForOffset(Offset(x, y)); + _charIndex = pos.offset; + + final range = _shape.paragraph.getBoxesForRange( + pos.offset - 1, + pos.offset, + ); + + _xPosition = _shape.x; + + if (range.isNotEmpty) { + _xPosition += range.first.right; + } + } + + String inputText(String char) { + final start = _shape.text.substring(0, _charIndex); + final end = _shape.text.substring(_charIndex); + _shape.text = '$start$char$end'; + final range = _shape.paragraph.getBoxesForRange(_charIndex, ++_charIndex); + _xPosition = _shape.x; + + if (range.isNotEmpty) { + _xPosition += range.first.right; + } + + return '$start$char$end'; + } + + void backspace() { + if (_charIndex <= 0) { + return; + } + + final start = _shape.text.substring(0, _charIndex - 1); + final end = _shape.text.length > start.length + ? _shape.text.substring(_charIndex) + : ''; + + _shape.text = '$start$end'; + + final range = _shape.paragraph.getBoxesForRange(_charIndex - 1, _charIndex); + _xPosition = _shape.x; + + if (range.isNotEmpty) { + _xPosition += range.first.left; + } else { + _xPosition += _shape.width; + } + _charIndex--; + } + + final TextShape _shape; + int _charIndex = 0; + double _xPosition = 0; +} diff --git a/patterns/state/manipulator_state/states/selections/text_resize_marker/text_resize_marker_state.dart b/patterns/state/manipulator_state/states/selections/text_resize_marker/text_resize_marker_state.dart index 5499c89..8a18fec 100644 --- a/patterns/state/manipulator_state/states/selections/text_resize_marker/text_resize_marker_state.dart +++ b/patterns/state/manipulator_state/states/selections/text_resize_marker/text_resize_marker_state.dart @@ -8,8 +8,10 @@ class TextSizeMarkerState extends Marker { @override void mouseDragAction(double x, double y) { - final newHeight = y - selectedShape.y; - selectedShape.resize(-1, newHeight); + final newHeight = + y - selectedShape.y - (selectedShape.height - selectedShape.userHeight); + + selectedShape.resize(0, newHeight); } @override diff --git a/patterns/state/manipulator_state/states/selections/text_resize_state.dart b/patterns/state/manipulator_state/states/selections/text_resize_state.dart index cf64e30..7690559 100644 --- a/patterns/state/manipulator_state/states/selections/text_resize_state.dart +++ b/patterns/state/manipulator_state/states/selections/text_resize_state.dart @@ -1,3 +1,5 @@ +import 'dart:ui'; + import '../../shapes/text_shape.dart'; import '../_/sub_states/parent_state.dart'; import 'text_change_state.dart'; @@ -11,9 +13,10 @@ class TextResizeState extends ParentState { } @override - void mouseDoubleClick() { + void mouseDoubleClick(double x, double y) { context.changeState( TextChangeState( + startPointer: Offset(x, y), selectedShape: selectedShape, ), ); From 0a01034c4075aae4c9661b07ccd9237ca6f2a8db Mon Sep 17 00:00:00 2001 From: ilopX Date: Thu, 2 Jun 2022 00:26:38 +0300 Subject: [PATCH 82/91] Move TextCursor to text_cursor.dart. --- .../states/_/paint_style.dart | 7 +- .../states/selections/text/text_cursor.dart | 69 +++++++++++++++++++ .../text_resize_marker_state.dart | 0 .../states/selections/text_change_state.dart | 67 +----------------- .../states/selections/text_resize_state.dart | 2 +- 5 files changed, 76 insertions(+), 69 deletions(-) create mode 100644 patterns/state/manipulator_state/states/selections/text/text_cursor.dart rename patterns/state/manipulator_state/states/selections/{text_resize_marker => text}/text_resize_marker_state.dart (100%) diff --git a/patterns/state/manipulator_state/states/_/paint_style.dart b/patterns/state/manipulator_state/states/_/paint_style.dart index 3f34cac..4244abb 100644 --- a/patterns/state/manipulator_state/states/_/paint_style.dart +++ b/patterns/state/manipulator_state/states/_/paint_style.dart @@ -3,7 +3,7 @@ import 'package:flutter/material.dart'; import '../../shapes/circle_shape.dart'; import '../../shapes/shape.dart'; import '../../shapes/text_shape.dart'; -import '../selections/text_change_state.dart'; +import '../selections/text/text_cursor.dart'; class PaintStyle { PaintStyle(this.color) @@ -70,7 +70,10 @@ class PaintStyle { } void paintTextCursor( - TextCursor cursor, TextShape selectedShape, Canvas canvas) { + TextCursor cursor, + TextShape selectedShape, + Canvas canvas, + ) { canvas.drawRect( Rect.fromLTWH( cursor.xCoordinate, diff --git a/patterns/state/manipulator_state/states/selections/text/text_cursor.dart b/patterns/state/manipulator_state/states/selections/text/text_cursor.dart new file mode 100644 index 0000000..971877b --- /dev/null +++ b/patterns/state/manipulator_state/states/selections/text/text_cursor.dart @@ -0,0 +1,69 @@ +import 'dart:ui'; + +import '../../../shapes/text_shape.dart'; + +class TextCursor { + TextCursor(this._shape); + + double get xCoordinate => _xPosition; + + void changePosition(double x, double y) { + x = x - _shape.x; + y = y - _shape.y; + + final pos = _shape.paragraph.getPositionForOffset(Offset(x, y)); + _charIndex = pos.offset; + + final range = _shape.paragraph.getBoxesForRange( + pos.offset - 1, + pos.offset, + ); + + _xPosition = _shape.x; + + if (range.isNotEmpty) { + _xPosition += range.first.right; + } + } + + String inputText(String char) { + final start = _shape.text.substring(0, _charIndex); + final end = _shape.text.substring(_charIndex); + _shape.text = '$start$char$end'; + final range = _shape.paragraph.getBoxesForRange(_charIndex, ++_charIndex); + _xPosition = _shape.x; + + if (range.isNotEmpty) { + _xPosition += range.first.right; + } + + return '$start$char$end'; + } + + void backspace() { + if (_charIndex <= 0) { + return; + } + + final start = _shape.text.substring(0, _charIndex - 1); + final end = _shape.text.length > start.length + ? _shape.text.substring(_charIndex) + : ''; + + _shape.text = '$start$end'; + + final range = _shape.paragraph.getBoxesForRange(_charIndex - 1, _charIndex); + _xPosition = _shape.x; + + if (range.isNotEmpty) { + _xPosition += range.first.left; + } else { + _xPosition += _shape.width; + } + _charIndex--; + } + + final TextShape _shape; + int _charIndex = 0; + double _xPosition = 0; +} diff --git a/patterns/state/manipulator_state/states/selections/text_resize_marker/text_resize_marker_state.dart b/patterns/state/manipulator_state/states/selections/text/text_resize_marker_state.dart similarity index 100% rename from patterns/state/manipulator_state/states/selections/text_resize_marker/text_resize_marker_state.dart rename to patterns/state/manipulator_state/states/selections/text/text_resize_marker_state.dart diff --git a/patterns/state/manipulator_state/states/selections/text_change_state.dart b/patterns/state/manipulator_state/states/selections/text_change_state.dart index 56b924a..68a715d 100644 --- a/patterns/state/manipulator_state/states/selections/text_change_state.dart +++ b/patterns/state/manipulator_state/states/selections/text_change_state.dart @@ -3,6 +3,7 @@ import 'package:flutter/services.dart'; import '../../shapes/text_shape.dart'; import 'selection_state.dart'; +import 'text/text_cursor.dart'; class TextChangeState extends SelectionState { TextChangeState({ @@ -71,69 +72,3 @@ class TextChangeState extends SelectionState { return '${super.toString()} + Text Change State'; } } - -class TextCursor { - TextCursor(this._shape); - - double get xCoordinate => _xPosition; - - void changePosition(double x, double y) { - x = x - _shape.x; - y = y - _shape.y; - - final pos = _shape.paragraph.getPositionForOffset(Offset(x, y)); - _charIndex = pos.offset; - - final range = _shape.paragraph.getBoxesForRange( - pos.offset - 1, - pos.offset, - ); - - _xPosition = _shape.x; - - if (range.isNotEmpty) { - _xPosition += range.first.right; - } - } - - String inputText(String char) { - final start = _shape.text.substring(0, _charIndex); - final end = _shape.text.substring(_charIndex); - _shape.text = '$start$char$end'; - final range = _shape.paragraph.getBoxesForRange(_charIndex, ++_charIndex); - _xPosition = _shape.x; - - if (range.isNotEmpty) { - _xPosition += range.first.right; - } - - return '$start$char$end'; - } - - void backspace() { - if (_charIndex <= 0) { - return; - } - - final start = _shape.text.substring(0, _charIndex - 1); - final end = _shape.text.length > start.length - ? _shape.text.substring(_charIndex) - : ''; - - _shape.text = '$start$end'; - - final range = _shape.paragraph.getBoxesForRange(_charIndex - 1, _charIndex); - _xPosition = _shape.x; - - if (range.isNotEmpty) { - _xPosition += range.first.left; - } else { - _xPosition += _shape.width; - } - _charIndex--; - } - - final TextShape _shape; - int _charIndex = 0; - double _xPosition = 0; -} diff --git a/patterns/state/manipulator_state/states/selections/text_resize_state.dart b/patterns/state/manipulator_state/states/selections/text_resize_state.dart index 7690559..45f9440 100644 --- a/patterns/state/manipulator_state/states/selections/text_resize_state.dart +++ b/patterns/state/manipulator_state/states/selections/text_resize_state.dart @@ -3,7 +3,7 @@ import 'dart:ui'; import '../../shapes/text_shape.dart'; import '../_/sub_states/parent_state.dart'; import 'text_change_state.dart'; -import 'text_resize_marker/text_resize_marker_state.dart'; +import 'text/text_resize_marker_state.dart'; class TextResizeState extends ParentState { TextResizeState({required super.selectedShape}) { From 9507a28173f6a4176edf4a37ec42e405d9f81e16 Mon Sep 17 00:00:00 2001 From: ilopX Date: Thu, 2 Jun 2022 00:40:35 +0300 Subject: [PATCH 83/91] Remove unnecessary vars. --- .../states/selections/text_change_state.dart | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/patterns/state/manipulator_state/states/selections/text_change_state.dart b/patterns/state/manipulator_state/states/selections/text_change_state.dart index 68a715d..ab11edb 100644 --- a/patterns/state/manipulator_state/states/selections/text_change_state.dart +++ b/patterns/state/manipulator_state/states/selections/text_change_state.dart @@ -62,13 +62,12 @@ class TextChangeState extends SelectionState { context.cursor = SystemMouseCursors.basic; } - double xx0 = 0; - int len = 0; - final Offset _startPointer; - final TextCursor _textCursor; @override String toString() { return '${super.toString()} + Text Change State'; } + + final Offset _startPointer; + final TextCursor _textCursor; } From 484f69c3ec9481f348116db97efd5f88cd4a9122 Mon Sep 17 00:00:00 2001 From: ilopX Date: Thu, 2 Jun 2022 04:11:20 +0300 Subject: [PATCH 84/91] Add keyboard cursor moving: left, right. --- .../states/selections/text/text_cursor.dart | 63 ++++++++++++------- .../states/selections/text_change_state.dart | 31 +++++++-- 2 files changed, 65 insertions(+), 29 deletions(-) diff --git a/patterns/state/manipulator_state/states/selections/text/text_cursor.dart b/patterns/state/manipulator_state/states/selections/text/text_cursor.dart index 971877b..ffff5d9 100644 --- a/patterns/state/manipulator_state/states/selections/text/text_cursor.dart +++ b/patterns/state/manipulator_state/states/selections/text/text_cursor.dart @@ -7,11 +7,10 @@ class TextCursor { double get xCoordinate => _xPosition; - void changePosition(double x, double y) { + void changePosition(double x) { x = x - _shape.x; - y = y - _shape.y; - final pos = _shape.paragraph.getPositionForOffset(Offset(x, y)); + final pos = _shape.paragraph.getPositionForOffset(Offset(x, _shape.y)); _charIndex = pos.offset; final range = _shape.paragraph.getBoxesForRange( @@ -26,41 +25,59 @@ class TextCursor { } } - String inputText(String char) { - final start = _shape.text.substring(0, _charIndex); - final end = _shape.text.substring(_charIndex); - _shape.text = '$start$char$end'; - final range = _shape.paragraph.getBoxesForRange(_charIndex, ++_charIndex); - _xPosition = _shape.x; + void inputText(String char) { + _changeText(char: char); + moveRight(); + } - if (range.isNotEmpty) { - _xPosition += range.first.right; + void backspace() { + if (_charIndex <= 0) { + return; } - return '$start$char$end'; + _changeText(removeChars: -1); + moveLeft(); } - void backspace() { + void moveLeft() { + _charIndex--; + _xPosition = _shape.x; + if (_charIndex <= 0) { + _charIndex = 0; return; } - final start = _shape.text.substring(0, _charIndex - 1); - final end = _shape.text.length > start.length - ? _shape.text.substring(_charIndex) - : ''; + final range = _shape.paragraph.getBoxesForRange(_charIndex - 1, _charIndex); + + if (range.isNotEmpty) { + _xPosition += range.first.right; + } + } - _shape.text = '$start$end'; + void moveRight() { + _charIndex++; + _xPosition = _shape.x; + + if (_charIndex >= _shape.text.length) { + _charIndex = _shape.text.length; + _xPosition += _shape.width; + return; + } final range = _shape.paragraph.getBoxesForRange(_charIndex - 1, _charIndex); - _xPosition = _shape.x; if (range.isNotEmpty) { - _xPosition += range.first.left; - } else { - _xPosition += _shape.width; + _xPosition += range.first.right; } - _charIndex--; + } + + void _changeText({String char = '', int removeChars = 0}) { + final start = _shape.text.substring(0, _charIndex + removeChars); + final end = _shape.text.length > start.length + ? _shape.text.substring(_charIndex) + : ''; + _shape.text = '$start$char$end'; } final TextShape _shape; diff --git a/patterns/state/manipulator_state/states/selections/text_change_state.dart b/patterns/state/manipulator_state/states/selections/text_change_state.dart index ab11edb..491d51d 100644 --- a/patterns/state/manipulator_state/states/selections/text_change_state.dart +++ b/patterns/state/manipulator_state/states/selections/text_change_state.dart @@ -1,3 +1,5 @@ +import 'dart:async'; + import 'package:flutter/material.dart'; import 'package:flutter/services.dart'; @@ -14,19 +16,27 @@ class TextChangeState extends SelectionState { @override void init() { - _textCursor.changePosition(_startPointer.dx, _startPointer.dy); + _textCursor.changePosition(_startPointer.dx); context.cursor = SystemMouseCursors.text; + + _cursorAnimateTimer = Timer.periodic(Duration(milliseconds: 500), (_) { + _isShowCursor = !_isShowCursor; + context.update(); + }); + context.update(); } @override void mouseDown(double x, double y) { if (selectedShape.rect.contains(Offset(x, y))) { - _textCursor.changePosition(x, y); + _textCursor.changePosition(x); + _isShowCursor = true; context.update(); return; } + _cursorAnimateTimer.cancel(); super.mouseDown(x, y); } @@ -35,11 +45,16 @@ class TextChangeState extends SelectionState { if (keyEvent is KeyDownEvent || keyEvent is KeyRepeatEvent) { if (keyEvent.physicalKey == PhysicalKeyboardKey.backspace) { _textCursor.backspace(); - context.update(); + } else if (keyEvent.physicalKey == PhysicalKeyboardKey.arrowLeft) { + _textCursor.moveLeft(); + } else if (keyEvent.physicalKey == PhysicalKeyboardKey.arrowRight) { + _textCursor.moveRight(); } else if (keyEvent.character != null) { _textCursor.inputText(keyEvent.character!); - context.update(); } + + _isShowCursor = true; + context.update(); } } @@ -47,7 +62,10 @@ class TextChangeState extends SelectionState { void paint(Canvas canvas) { context.paintStyle.paintSelectedText(selectedShape, canvas); super.paint(canvas); - context.paintStyle.paintTextCursor(_textCursor, selectedShape, canvas); + + if (_isShowCursor) { + context.paintStyle.paintTextCursor(_textCursor, selectedShape, canvas); + } } @override @@ -62,7 +80,6 @@ class TextChangeState extends SelectionState { context.cursor = SystemMouseCursors.basic; } - @override String toString() { return '${super.toString()} + Text Change State'; @@ -70,4 +87,6 @@ class TextChangeState extends SelectionState { final Offset _startPointer; final TextCursor _textCursor; + bool _isShowCursor = true; + late Timer _cursorAnimateTimer; } From 385cf61f226c07a4193ac681233ff2eadd9b0c78 Mon Sep 17 00:00:00 2001 From: ilopX Date: Thu, 2 Jun 2022 15:44:37 +0300 Subject: [PATCH 85/91] Add KeyboardActions & TextCursorAnimation. --- .../states/_/paint_style.dart | 19 +++--- .../selections/text/keyboard_actions.dart | 31 ++++++++++ .../states/selections/text/text_cursor.dart | 4 +- .../text/text_cursor_animation.dart | 30 ++++++++++ .../states/selections/text_change_state.dart | 59 +++++++++---------- 5 files changed, 102 insertions(+), 41 deletions(-) create mode 100644 patterns/state/manipulator_state/states/selections/text/keyboard_actions.dart create mode 100644 patterns/state/manipulator_state/states/selections/text/text_cursor_animation.dart diff --git a/patterns/state/manipulator_state/states/_/paint_style.dart b/patterns/state/manipulator_state/states/_/paint_style.dart index 4244abb..a26d70e 100644 --- a/patterns/state/manipulator_state/states/_/paint_style.dart +++ b/patterns/state/manipulator_state/states/_/paint_style.dart @@ -74,13 +74,18 @@ class PaintStyle { TextShape selectedShape, Canvas canvas, ) { - canvas.drawRect( - Rect.fromLTWH( - cursor.xCoordinate, - selectedShape.y + (selectedShape.height - selectedShape.userHeight), - 1.5, - selectedShape.userHeight), - Paint()..color = Colors.white, + canvas.drawLine( + Offset( + cursor.xCoordinate, + selectedShape.y + (selectedShape.height - selectedShape.userHeight) + 2, + ), + Offset( + cursor.xCoordinate, + selectedShape.y + (selectedShape.height) - 2, + ), + Paint() + ..strokeWidth = 2.2 + ..color = Colors.white, ); } diff --git a/patterns/state/manipulator_state/states/selections/text/keyboard_actions.dart b/patterns/state/manipulator_state/states/selections/text/keyboard_actions.dart new file mode 100644 index 0000000..ed0f11b --- /dev/null +++ b/patterns/state/manipulator_state/states/selections/text/keyboard_actions.dart @@ -0,0 +1,31 @@ +import 'package:flutter/services.dart'; + +class KeyboardActions { + final Map actions; + final void Function(String) inputCharAction; + + KeyboardActions({ + required this.actions, + required this.inputCharAction, + }); + + void keyDown(KeyEvent keyEvent) { + final isNotKeyDown = + !(keyEvent is KeyDownEvent || keyEvent is KeyRepeatEvent); + + if (isNotKeyDown) { + return; + } + + final foundEvent = actions[keyEvent.physicalKey]; + + if (foundEvent != null) { + foundEvent.call(); + return; + } + + if (keyEvent.character != null) { + inputCharAction.call(keyEvent.character!); + } + } +} diff --git a/patterns/state/manipulator_state/states/selections/text/text_cursor.dart b/patterns/state/manipulator_state/states/selections/text/text_cursor.dart index ffff5d9..c5dc25a 100644 --- a/patterns/state/manipulator_state/states/selections/text/text_cursor.dart +++ b/patterns/state/manipulator_state/states/selections/text/text_cursor.dart @@ -11,15 +11,15 @@ class TextCursor { x = x - _shape.x; final pos = _shape.paragraph.getPositionForOffset(Offset(x, _shape.y)); + _charIndex = pos.offset; + _xPosition = _shape.x; final range = _shape.paragraph.getBoxesForRange( pos.offset - 1, pos.offset, ); - _xPosition = _shape.x; - if (range.isNotEmpty) { _xPosition += range.first.right; } diff --git a/patterns/state/manipulator_state/states/selections/text/text_cursor_animation.dart b/patterns/state/manipulator_state/states/selections/text/text_cursor_animation.dart new file mode 100644 index 0000000..22b6bee --- /dev/null +++ b/patterns/state/manipulator_state/states/selections/text/text_cursor_animation.dart @@ -0,0 +1,30 @@ +import 'dart:async'; + +class TextCursorAnimation { + final Duration speed; + final void Function() onBlink; + + TextCursorAnimation({ + required this.speed, + required this.onBlink, + }) { + _timer = Timer.periodic(speed, (_) { + _isShowCursor = !_isShowCursor; + onBlink.call(); + }); + } + + bool get isVisible => _isShowCursor; + + void touch() { + _isShowCursor = true; + onBlink.call(); + } + + void dispose() { + _timer.cancel(); + } + + bool _isShowCursor = true; + late Timer _timer; +} diff --git a/patterns/state/manipulator_state/states/selections/text_change_state.dart b/patterns/state/manipulator_state/states/selections/text_change_state.dart index 491d51d..d09a474 100644 --- a/patterns/state/manipulator_state/states/selections/text_change_state.dart +++ b/patterns/state/manipulator_state/states/selections/text_change_state.dart @@ -1,29 +1,37 @@ -import 'dart:async'; - import 'package:flutter/material.dart'; import 'package:flutter/services.dart'; import '../../shapes/text_shape.dart'; import 'selection_state.dart'; +import 'text/keyboard_actions.dart'; import 'text/text_cursor.dart'; +import 'text/text_cursor_animation.dart'; class TextChangeState extends SelectionState { TextChangeState({ required Offset startPointer, required super.selectedShape, - }) : _startPointer = startPointer, - _textCursor = TextCursor(selectedShape); + }) : _startPointer = startPointer; @override void init() { - _textCursor.changePosition(_startPointer.dx); - context.cursor = SystemMouseCursors.text; - - _cursorAnimateTimer = Timer.periodic(Duration(milliseconds: 500), (_) { - _isShowCursor = !_isShowCursor; - context.update(); - }); + _textCursor = TextCursor(selectedShape)..changePosition(_startPointer.dx); + + _keyboardActions = KeyboardActions( + actions: { + PhysicalKeyboardKey.backspace: _textCursor.backspace, + PhysicalKeyboardKey.arrowLeft: _textCursor.moveLeft, + PhysicalKeyboardKey.arrowRight: _textCursor.moveRight, + }, + inputCharAction: _textCursor.inputText, + ); + + _animationCursor = TextCursorAnimation( + speed: Duration(milliseconds: 400), + onBlink: context.update, + ); + context.cursor = SystemMouseCursors.text; context.update(); } @@ -31,31 +39,18 @@ class TextChangeState extends SelectionState { void mouseDown(double x, double y) { if (selectedShape.rect.contains(Offset(x, y))) { _textCursor.changePosition(x); - _isShowCursor = true; - context.update(); + _animationCursor.touch(); return; } - _cursorAnimateTimer.cancel(); + _animationCursor.dispose(); super.mouseDown(x, y); } @override void keyDown(KeyEvent keyEvent) { - if (keyEvent is KeyDownEvent || keyEvent is KeyRepeatEvent) { - if (keyEvent.physicalKey == PhysicalKeyboardKey.backspace) { - _textCursor.backspace(); - } else if (keyEvent.physicalKey == PhysicalKeyboardKey.arrowLeft) { - _textCursor.moveLeft(); - } else if (keyEvent.physicalKey == PhysicalKeyboardKey.arrowRight) { - _textCursor.moveRight(); - } else if (keyEvent.character != null) { - _textCursor.inputText(keyEvent.character!); - } - - _isShowCursor = true; - context.update(); - } + _keyboardActions.keyDown(keyEvent); + _animationCursor.touch(); } @override @@ -63,7 +58,7 @@ class TextChangeState extends SelectionState { context.paintStyle.paintSelectedText(selectedShape, canvas); super.paint(canvas); - if (_isShowCursor) { + if (_animationCursor.isVisible) { context.paintStyle.paintTextCursor(_textCursor, selectedShape, canvas); } } @@ -86,7 +81,7 @@ class TextChangeState extends SelectionState { } final Offset _startPointer; - final TextCursor _textCursor; - bool _isShowCursor = true; - late Timer _cursorAnimateTimer; + late final TextCursor _textCursor; + late final KeyboardActions _keyboardActions; + late final TextCursorAnimation _animationCursor; } From 23888d031c40a7d65c588eb8f2345bce59da1443 Mon Sep 17 00:00:00 2001 From: ilopX Date: Thu, 2 Jun 2022 15:48:56 +0300 Subject: [PATCH 86/91] Refactoring TextCursor. --- .../states/selections/text/text_cursor.dart | 36 +++++++++---------- 1 file changed, 18 insertions(+), 18 deletions(-) diff --git a/patterns/state/manipulator_state/states/selections/text/text_cursor.dart b/patterns/state/manipulator_state/states/selections/text/text_cursor.dart index c5dc25a..85379a0 100644 --- a/patterns/state/manipulator_state/states/selections/text/text_cursor.dart +++ b/patterns/state/manipulator_state/states/selections/text/text_cursor.dart @@ -3,19 +3,19 @@ import 'dart:ui'; import '../../../shapes/text_shape.dart'; class TextCursor { - TextCursor(this._shape); + TextCursor(this._textShape) : _xPosition = _textShape.x; double get xCoordinate => _xPosition; void changePosition(double x) { - x = x - _shape.x; + x = x - _textShape.x; - final pos = _shape.paragraph.getPositionForOffset(Offset(x, _shape.y)); + final pos = _textShape.paragraph.getPositionForOffset(Offset(x, _textShape.y)); _charIndex = pos.offset; - _xPosition = _shape.x; + _xPosition = _textShape.x; - final range = _shape.paragraph.getBoxesForRange( + final range = _textShape.paragraph.getBoxesForRange( pos.offset - 1, pos.offset, ); @@ -41,14 +41,14 @@ class TextCursor { void moveLeft() { _charIndex--; - _xPosition = _shape.x; + _xPosition = _textShape.x; if (_charIndex <= 0) { _charIndex = 0; return; } - final range = _shape.paragraph.getBoxesForRange(_charIndex - 1, _charIndex); + final range = _textShape.paragraph.getBoxesForRange(_charIndex - 1, _charIndex); if (range.isNotEmpty) { _xPosition += range.first.right; @@ -57,15 +57,15 @@ class TextCursor { void moveRight() { _charIndex++; - _xPosition = _shape.x; + _xPosition = _textShape.x; - if (_charIndex >= _shape.text.length) { - _charIndex = _shape.text.length; - _xPosition += _shape.width; + if (_charIndex >= _textShape.text.length) { + _charIndex = _textShape.text.length; + _xPosition += _textShape.width; return; } - final range = _shape.paragraph.getBoxesForRange(_charIndex - 1, _charIndex); + final range = _textShape.paragraph.getBoxesForRange(_charIndex - 1, _charIndex); if (range.isNotEmpty) { _xPosition += range.first.right; @@ -73,14 +73,14 @@ class TextCursor { } void _changeText({String char = '', int removeChars = 0}) { - final start = _shape.text.substring(0, _charIndex + removeChars); - final end = _shape.text.length > start.length - ? _shape.text.substring(_charIndex) + final start = _textShape.text.substring(0, _charIndex + removeChars); + final end = _textShape.text.length > start.length + ? _textShape.text.substring(_charIndex) : ''; - _shape.text = '$start$char$end'; + _textShape.text = '$start$char$end'; } - final TextShape _shape; + final TextShape _textShape; int _charIndex = 0; - double _xPosition = 0; + late double _xPosition = 0; } From 09fbf0e5c9c58cdb2ec63c8df5b6d8a39d9081a3 Mon Sep 17 00:00:00 2001 From: ilopX Date: Thu, 2 Jun 2022 16:16:58 +0300 Subject: [PATCH 87/91] Rename TextChangeState to TextEditState. --- .../{text_change_state.dart => text_edit_state.dart} | 6 +++--- .../states/selections/text_resize_state.dart | 4 ++-- 2 files changed, 5 insertions(+), 5 deletions(-) rename patterns/state/manipulator_state/states/selections/{text_change_state.dart => text_edit_state.dart} (93%) diff --git a/patterns/state/manipulator_state/states/selections/text_change_state.dart b/patterns/state/manipulator_state/states/selections/text_edit_state.dart similarity index 93% rename from patterns/state/manipulator_state/states/selections/text_change_state.dart rename to patterns/state/manipulator_state/states/selections/text_edit_state.dart index d09a474..c11b288 100644 --- a/patterns/state/manipulator_state/states/selections/text_change_state.dart +++ b/patterns/state/manipulator_state/states/selections/text_edit_state.dart @@ -7,8 +7,8 @@ import 'text/keyboard_actions.dart'; import 'text/text_cursor.dart'; import 'text/text_cursor_animation.dart'; -class TextChangeState extends SelectionState { - TextChangeState({ +class TextEditState extends SelectionState { + TextEditState({ required Offset startPointer, required super.selectedShape, }) : _startPointer = startPointer; @@ -77,7 +77,7 @@ class TextChangeState extends SelectionState { @override String toString() { - return '${super.toString()} + Text Change State'; + return '${super.toString()} + Text Edit State'; } final Offset _startPointer; diff --git a/patterns/state/manipulator_state/states/selections/text_resize_state.dart b/patterns/state/manipulator_state/states/selections/text_resize_state.dart index 45f9440..0e9494c 100644 --- a/patterns/state/manipulator_state/states/selections/text_resize_state.dart +++ b/patterns/state/manipulator_state/states/selections/text_resize_state.dart @@ -2,7 +2,7 @@ import 'dart:ui'; import '../../shapes/text_shape.dart'; import '../_/sub_states/parent_state.dart'; -import 'text_change_state.dart'; +import 'text_edit_state.dart'; import 'text/text_resize_marker_state.dart'; class TextResizeState extends ParentState { @@ -15,7 +15,7 @@ class TextResizeState extends ParentState { @override void mouseDoubleClick(double x, double y) { context.changeState( - TextChangeState( + TextEditState( startPointer: Offset(x, y), selectedShape: selectedShape, ), From c42aadf644b3233abb41df3ff928e22c0820c377 Mon Sep 17 00:00:00 2001 From: ilopX Date: Fri, 3 Jun 2022 00:26:17 +0300 Subject: [PATCH 88/91] Refactoring: compare to class diagram. --- .../{base_manipulationt.dart => base_manipulation.dart} | 0 .../state/manipulator_state/pattern/manipulator.dart | 2 +- .../states/_/{corner_marker.dart => marker.dart} | 0 .../states/_/sub_states/parent_state.dart | 2 +- patterns/state/manipulator_state/states/free_sate.dart | 4 ++-- .../inner_radius_markers/inner_radius_marker_state.dart | 2 +- .../selections/{moving_state.dart => move_state.dart} | 4 ++-- .../resizable_markers/bottom_left_marker_state.dart | 2 +- .../resizable_markers/bottom_right_marker_state.dart | 2 +- .../resizable_markers/top_left_marker_state.dart | 2 +- .../resizable_markers/top_right_marker_state.dart | 2 +- .../states/selections/selection_state.dart | 4 ++-- .../states/selections/text/text_cursor.dart | 9 ++++++--- ...ize_marker_state.dart => text_size_marker_state.dart} | 2 +- .../states/selections/text_resize_state.dart | 2 +- 15 files changed, 21 insertions(+), 18 deletions(-) rename patterns/state/manipulator_state/app/{base_manipulationt.dart => base_manipulation.dart} (100%) rename patterns/state/manipulator_state/states/_/{corner_marker.dart => marker.dart} (100%) rename patterns/state/manipulator_state/states/selections/{moving_state.dart => move_state.dart} (90%) rename patterns/state/manipulator_state/states/selections/text/{text_resize_marker_state.dart => text_size_marker_state.dart} (95%) diff --git a/patterns/state/manipulator_state/app/base_manipulationt.dart b/patterns/state/manipulator_state/app/base_manipulation.dart similarity index 100% rename from patterns/state/manipulator_state/app/base_manipulationt.dart rename to patterns/state/manipulator_state/app/base_manipulation.dart diff --git a/patterns/state/manipulator_state/pattern/manipulator.dart b/patterns/state/manipulator_state/pattern/manipulator.dart index a14eb31..b7df969 100644 --- a/patterns/state/manipulator_state/pattern/manipulator.dart +++ b/patterns/state/manipulator_state/pattern/manipulator.dart @@ -5,7 +5,7 @@ import '../states/_/paint_style.dart'; import '../app/shapes.dart'; part 'manipulation_state.dart'; -part '../app/base_manipulationt.dart'; +part '../app/base_manipulation.dart'; abstract class Manipulator { ManipulationState get state; diff --git a/patterns/state/manipulator_state/states/_/corner_marker.dart b/patterns/state/manipulator_state/states/_/marker.dart similarity index 100% rename from patterns/state/manipulator_state/states/_/corner_marker.dart rename to patterns/state/manipulator_state/states/_/marker.dart diff --git a/patterns/state/manipulator_state/states/_/sub_states/parent_state.dart b/patterns/state/manipulator_state/states/_/sub_states/parent_state.dart index da151eb..ba0638f 100644 --- a/patterns/state/manipulator_state/states/_/sub_states/parent_state.dart +++ b/patterns/state/manipulator_state/states/_/sub_states/parent_state.dart @@ -4,7 +4,7 @@ import '../../selections/selection_state.dart'; import 'child_state.dart'; import '../../../shapes/shape.dart'; -class ParentState extends SelectionState { +abstract class ParentState extends SelectionState { ParentState({ required super.selectedShape, }); diff --git a/patterns/state/manipulator_state/states/free_sate.dart b/patterns/state/manipulator_state/states/free_sate.dart index c7e46ca..e001070 100644 --- a/patterns/state/manipulator_state/states/free_sate.dart +++ b/patterns/state/manipulator_state/states/free_sate.dart @@ -1,6 +1,6 @@ import '../pattern/manipulator.dart'; import '_/mixins/hover_shape_mixin.dart'; -import 'selections/moving_state.dart'; +import 'selections/move_state.dart'; class FreeState extends ManipulationState with HoverShapeMixin { @override @@ -16,7 +16,7 @@ class FreeState extends ManipulationState with HoverShapeMixin { } context.changeState( - MovingState( + MoveState( startX: x, startY: y, selectedShape: selectedShape, diff --git a/patterns/state/manipulator_state/states/selections/inner_radius_markers/inner_radius_marker_state.dart b/patterns/state/manipulator_state/states/selections/inner_radius_markers/inner_radius_marker_state.dart index 97a4d00..ae60e1b 100644 --- a/patterns/state/manipulator_state/states/selections/inner_radius_markers/inner_radius_marker_state.dart +++ b/patterns/state/manipulator_state/states/selections/inner_radius_markers/inner_radius_marker_state.dart @@ -1,7 +1,7 @@ import 'package:flutter/src/services/mouse_cursor.dart'; import '../../../shapes/circle_shape.dart'; -import '../../_/corner_marker.dart'; +import '../../_/marker.dart'; class InnerRadiusMarkerState extends Marker { InnerRadiusMarkerState({required super.parentState}); diff --git a/patterns/state/manipulator_state/states/selections/moving_state.dart b/patterns/state/manipulator_state/states/selections/move_state.dart similarity index 90% rename from patterns/state/manipulator_state/states/selections/moving_state.dart rename to patterns/state/manipulator_state/states/selections/move_state.dart index 2b12468..8f0773c 100644 --- a/patterns/state/manipulator_state/states/selections/moving_state.dart +++ b/patterns/state/manipulator_state/states/selections/move_state.dart @@ -1,10 +1,10 @@ import 'selection_state.dart'; -class MovingState extends SelectionState { +class MoveState extends SelectionState { final double startX; final double startY; - MovingState({ + MoveState({ required double startX, required double startY, required super.selectedShape, diff --git a/patterns/state/manipulator_state/states/selections/resizable_markers/bottom_left_marker_state.dart b/patterns/state/manipulator_state/states/selections/resizable_markers/bottom_left_marker_state.dart index 713c5d9..9d2a1f8 100644 --- a/patterns/state/manipulator_state/states/selections/resizable_markers/bottom_left_marker_state.dart +++ b/patterns/state/manipulator_state/states/selections/resizable_markers/bottom_left_marker_state.dart @@ -1,4 +1,4 @@ -import '../../_/corner_marker.dart'; +import '../../_/marker.dart'; class BottomLeftMarkerState extends Marker { BottomLeftMarkerState({ diff --git a/patterns/state/manipulator_state/states/selections/resizable_markers/bottom_right_marker_state.dart b/patterns/state/manipulator_state/states/selections/resizable_markers/bottom_right_marker_state.dart index aabb9ec..5db6e10 100644 --- a/patterns/state/manipulator_state/states/selections/resizable_markers/bottom_right_marker_state.dart +++ b/patterns/state/manipulator_state/states/selections/resizable_markers/bottom_right_marker_state.dart @@ -1,4 +1,4 @@ -import '../../_/corner_marker.dart'; +import '../../_/marker.dart'; class BottomRightMarkerState extends Marker { BottomRightMarkerState({ diff --git a/patterns/state/manipulator_state/states/selections/resizable_markers/top_left_marker_state.dart b/patterns/state/manipulator_state/states/selections/resizable_markers/top_left_marker_state.dart index c2a3371..74bd92d 100644 --- a/patterns/state/manipulator_state/states/selections/resizable_markers/top_left_marker_state.dart +++ b/patterns/state/manipulator_state/states/selections/resizable_markers/top_left_marker_state.dart @@ -1,4 +1,4 @@ -import '../../_/corner_marker.dart'; +import '../../_/marker.dart'; class TopLeftMarkerState extends Marker { TopLeftMarkerState({ diff --git a/patterns/state/manipulator_state/states/selections/resizable_markers/top_right_marker_state.dart b/patterns/state/manipulator_state/states/selections/resizable_markers/top_right_marker_state.dart index ed18b97..f03f484 100644 --- a/patterns/state/manipulator_state/states/selections/resizable_markers/top_right_marker_state.dart +++ b/patterns/state/manipulator_state/states/selections/resizable_markers/top_right_marker_state.dart @@ -1,4 +1,4 @@ -import '../../_/corner_marker.dart'; +import '../../_/marker.dart'; class TopRightMarkerState extends Marker { TopRightMarkerState({ diff --git a/patterns/state/manipulator_state/states/selections/selection_state.dart b/patterns/state/manipulator_state/states/selections/selection_state.dart index f580a8e..26fb82d 100644 --- a/patterns/state/manipulator_state/states/selections/selection_state.dart +++ b/patterns/state/manipulator_state/states/selections/selection_state.dart @@ -3,8 +3,8 @@ import 'package:flutter/material.dart'; import '../../shapes/shape.dart'; import '../free_sate.dart'; -class SelectionState extends FreeState { - final T selectedShape; +class SelectionState extends FreeState { + final TShape selectedShape; SelectionState({required this.selectedShape}); diff --git a/patterns/state/manipulator_state/states/selections/text/text_cursor.dart b/patterns/state/manipulator_state/states/selections/text/text_cursor.dart index 85379a0..b09f9b8 100644 --- a/patterns/state/manipulator_state/states/selections/text/text_cursor.dart +++ b/patterns/state/manipulator_state/states/selections/text/text_cursor.dart @@ -10,7 +10,8 @@ class TextCursor { void changePosition(double x) { x = x - _textShape.x; - final pos = _textShape.paragraph.getPositionForOffset(Offset(x, _textShape.y)); + final pos = + _textShape.paragraph.getPositionForOffset(Offset(x, _textShape.y)); _charIndex = pos.offset; _xPosition = _textShape.x; @@ -48,7 +49,8 @@ class TextCursor { return; } - final range = _textShape.paragraph.getBoxesForRange(_charIndex - 1, _charIndex); + final range = + _textShape.paragraph.getBoxesForRange(_charIndex - 1, _charIndex); if (range.isNotEmpty) { _xPosition += range.first.right; @@ -65,7 +67,8 @@ class TextCursor { return; } - final range = _textShape.paragraph.getBoxesForRange(_charIndex - 1, _charIndex); + final range = + _textShape.paragraph.getBoxesForRange(_charIndex - 1, _charIndex); if (range.isNotEmpty) { _xPosition += range.first.right; diff --git a/patterns/state/manipulator_state/states/selections/text/text_resize_marker_state.dart b/patterns/state/manipulator_state/states/selections/text/text_size_marker_state.dart similarity index 95% rename from patterns/state/manipulator_state/states/selections/text/text_resize_marker_state.dart rename to patterns/state/manipulator_state/states/selections/text/text_size_marker_state.dart index 8a18fec..05c250f 100644 --- a/patterns/state/manipulator_state/states/selections/text/text_resize_marker_state.dart +++ b/patterns/state/manipulator_state/states/selections/text/text_size_marker_state.dart @@ -1,7 +1,7 @@ import 'package:flutter/services.dart'; import '../../../shapes/text_shape.dart'; -import '../../_/corner_marker.dart'; +import '../../_/marker.dart'; class TextSizeMarkerState extends Marker { TextSizeMarkerState({required super.parentState}); diff --git a/patterns/state/manipulator_state/states/selections/text_resize_state.dart b/patterns/state/manipulator_state/states/selections/text_resize_state.dart index 0e9494c..c79e4cb 100644 --- a/patterns/state/manipulator_state/states/selections/text_resize_state.dart +++ b/patterns/state/manipulator_state/states/selections/text_resize_state.dart @@ -3,7 +3,7 @@ import 'dart:ui'; import '../../shapes/text_shape.dart'; import '../_/sub_states/parent_state.dart'; import 'text_edit_state.dart'; -import 'text/text_resize_marker_state.dart'; +import 'text/text_size_marker_state.dart'; class TextResizeState extends ParentState { TextResizeState({required super.selectedShape}) { From 2dde10404038dc049a942c4f6abd345324a2efd1 Mon Sep 17 00:00:00 2001 From: ilopX Date: Fri, 3 Jun 2022 00:49:13 +0300 Subject: [PATCH 89/91] Add README. --- patterns/state/manipulator_state/README.md | 76 ++++++++++++++++++++++ 1 file changed, 76 insertions(+) create mode 100644 patterns/state/manipulator_state/README.md diff --git a/patterns/state/manipulator_state/README.md b/patterns/state/manipulator_state/README.md new file mode 100644 index 0000000..93d1e38 --- /dev/null +++ b/patterns/state/manipulator_state/README.md @@ -0,0 +1,76 @@ +# State Pattern +State is a behavioral design pattern that lets an object alter its behavior when its internal state +changes. It appears as if the object changed its class. + +Tutorial: [here](https://refactoring.guru/design-patterns/state). + +### Online demo: +Click on the picture to see the [demo](https://RefactoringGuru.github.io/design-patterns-dart/#/state/manipulator_state). + +[![image](https://user-images.githubusercontent.com/8049534/171070341-1decb58f-033b-4eb5-89d4-355aafa6b680.png)](https://refactoringguru.github.io/design-patterns-dart/#/state/manipulator_state) + +### Video +https://user-images.githubusercontent.com/8049534/171499203-1400c3ae-d5cd-4e48-a0b6-0252f4345d19.mp4 + +### Diagram: +![image](https://user-images.githubusercontent.com/8049534/171740942-659d3ec9-8355-4078-a7d6-b4a338b41187.png) + +## Client code: +### Change FreeState to MoveState: +```dart +class FreeState extends ManipulationState { + @override + void mouseDown(double x, double y) { + tryToSelectAndStartMovingShape(x, y); + } + + bool tryToSelectAndStartMovingShape(double x, double y) { + final selectedShape = context.shapes.findShapeByCoordinates(x, y); + + context.changeState( + MoveState( + startX: x, + startY: y, + selectedShape: selectedShape, + ), + ); + + return true; + } +} +``` + +### Change MoveState to ResizableState: +```dart +class MoveState extends SelectionState { + @override + void mouseMove(double x, double y) { + selectedShape.move(x, y); + context.update(); + } + + @override + void mouseUp() { + context.changeState( + selectedShape.createSelectionState(), + ); + } +} +``` + +### Each shape has its own state manipulator: +```dart +class RectangleShape extends BaseShape { + @override + SelectionState createSelectionState() { + return ResizableState(selectedShape: this); + } +} + +class CircleShape extends BaseShape { + @override + SelectionState createSelectionState() { + return InnerRadiusState(selectedShape: this); + } +} +``` From 1def8ee8e74e992150571e86720266bfd788d968 Mon Sep 17 00:00:00 2001 From: ilopX Date: Fri, 3 Jun 2022 00:53:21 +0300 Subject: [PATCH 90/91] Update main README. --- README.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index 5c6a719..bca5237 100644 --- a/README.md +++ b/README.md @@ -17,7 +17,7 @@ It contains **Dart** examples for all classic **GoF** design patterns. - [ ] **Mediator** - [x] **Memento** - [[Conceptual](https://github.com/RefactoringGuru/design-patterns-dart/tree/main/patterns/memento/conceptual)] [[Memento Editor](https://github.com/RefactoringGuru/design-patterns-dart/tree/main/patterns/memento/memento_editor)] - [x] **Observer** - [[Open-Close Editor Events](https://github.com/RefactoringGuru/design-patterns-dart/tree/main/patterns/observer/open_close_editor_events)] [[AppObserver](https://github.com/RefactoringGuru/design-patterns-dart/tree/main/patterns/observer/app_observer)] [[Subscriber Flutter Widget](https://github.com/RefactoringGuru/design-patterns-dart/tree/main/patterns/observer/subscriber_flutter_widget)] - - [ ] **State** + - [x] **State** - [[State Manipulator](https://github.com/RefactoringGuru/design-patterns-dart/tree/main/patterns/state/manipulator_state)] - [ ] **Template Method** - [X] **Visitor** [[Shape XML Exporter](https://github.com/RefactoringGuru/design-patterns-dart/tree/main/patterns/visitor/shapes_exporter)] - [X] **Strategy** [[Reservation Cargo Spaces](https://github.com/RefactoringGuru/design-patterns-dart/tree/main/patterns/strategy/reservation_cargo_spaces)] @@ -32,8 +32,8 @@ It contains **Dart** examples for all classic **GoF** design patterns. ## Requirements -The examples were written in **Dart 2.15**. -Some complex examples require **Flutter 2.12**. +The examples were written in **Dart 2.17**. +Some complex examples require **Flutter 3.0.0**. ## Contributor's Guide From 8f95300d89ed658763a55ede08645b5c5cfe0b8d Mon Sep 17 00:00:00 2001 From: ilopX Date: Fri, 3 Jun 2022 00:53:49 +0300 Subject: [PATCH 91/91] Bump version 0.24.0. --- CHANGELOG.md | 3 +++ pubspec.yaml | 2 +- 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index a1a15e3..55dceb0 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,6 @@ +## 0.24.0 +- Add state pattern: State Manipulator. + ## 0.23.14 - Replace web renderer html to canvakit (deploy_flutter_demo.dart). diff --git a/pubspec.yaml b/pubspec.yaml index becc532..b24b6fd 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -1,6 +1,6 @@ name: design_patterns_dart description: Dart examples for all classic GoF design patterns. -version: 0.23.14 +version: 0.24.0 homepage: https://refactoring.guru/design-patterns repository: https://github.com/RefactoringGuru/design-patterns-dart issue_tracker: https://github.com/RefactoringGuru/design-patterns-dart/issue