Skip to content

Commit e31af6b

Browse files
authored
Merge pull request #35 from ilopX/add-memento-editor
[work in progress] Add memento editor example.
2 parents a69760d + 849a2c0 commit e31af6b

27 files changed

+855
-14
lines changed

CHANGELOG.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,6 @@
1+
## 0.18.0
2+
- Add Memento Editor.
3+
14
## 0.17.16 - refactoring
25
- Simplifying the ternary construction.
36
- Remove multiline comment from main README.

README.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ It contains **Dart** examples for all classic **GoF** design patterns.
1515
- [ ] Interpreter
1616
- [ ] **Iterator**
1717
- [ ] **Mediator**
18-
- [x] **Memento** - [[Conceptual](https://github.com/RefactoringGuru/design-patterns-dart/tree/master/patterns/memento/conceptual)]
18+
- [x] **Memento** - [[Conceptual](https://github.com/RefactoringGuru/design-patterns-dart/tree/master/patterns/memento/conceptual)] [[Memento Editor](https://github.com/RefactoringGuru/design-patterns-dart/tree/master/patterns/memento/memento_editor)]
1919
- [x] **Observer** - [[Open-Close Editor Events](https://github.com/RefactoringGuru/design-patterns-dart/tree/master/patterns/observer/open_close_editor_events)] [[AppObserver](https://github.com/RefactoringGuru/design-patterns-dart/tree/master/patterns/observer/app_observer)] [[Subscriber Flutter Widget](https://github.com/RefactoringGuru/design-patterns-dart/tree/master/patterns/observer/subscriber_flutter_widget)]
2020
- [ ] **State**
2121
- [ ] **Template Method**
@@ -33,7 +33,7 @@ It contains **Dart** examples for all classic **GoF** design patterns.
3333
## Requirements
3434

3535
The examples were written in **Dart 2.15**.
36-
Some complex examples require **Flutter 2.15.0**.
36+
Some complex examples require **Flutter 2.12**.
3737

3838
## Contributor's Guide
3939

bin/deploy_flutter_demos.dart

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -119,7 +119,7 @@ Future<String> repositoryOriginUrl(Directory workingDir) async {
119119
Future<String> lastProjectCommit() async {
120120
final rawCommit =
121121
await cmd('git log -1 --pretty=%B', workingDirectory: projectDir);
122-
final formatCommit = rawCommit.replaceAll(' ', '_');
122+
final formatCommit = rawCommit.replaceAll(' ', '_').replaceAll('&', '');
123123
return 'auto_commit:_$formatCommit';
124124
}
125125

bin/main.dart

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
import 'package:flutter/material.dart';
22
import '../patterns/observer/subscriber_flutter_widget/main.dart';
33
import '../patterns/adapter/flutter_adapter/main.dart';
4+
import '../patterns/memento/memento_editor/main.dart';
45

56
void main() {
67
runApp(MyApp());
@@ -12,10 +13,11 @@ class MyApp extends StatelessWidget {
1213
return MaterialApp(
1314
title: 'Refactoring Guru: Flutter launcher',
1415
theme: ThemeData(primarySwatch: Colors.pink),
15-
initialRoute: '/adapter/flutter_adapter',
16+
initialRoute: '/memento/flutter_memento_editor',
1617
routes: {
1718
'/observer/subscriber_flutter_widget': (_) => SubscriberFlutterApp(),
1819
'/adapter/flutter_adapter': (_) => FlutterAdapterApp(),
20+
'/memento/flutter_memento_editor': (_) => FlutterMementoEditorApp(),
1921
},
2022
);
2123
}

patterns/adapter/flutter_adapter/adapter/classic_app_render_object.dart

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -63,13 +63,16 @@ class ClassicAppRenderObject extends RenderBox {
6363
@override
6464
void handleEvent(PointerEvent event, covariant BoxHitTestEntry entry) {
6565
if (event is PointerHoverEvent || event is PointerMoveEvent) {
66-
} else if (event is PointerDownEvent) {
67-
if (event.buttons == kPrimaryMouseButton) {
68-
_classicApp.onMouseDown();
69-
} else if (event.buttons == kSecondaryMouseButton) {}
70-
else if (event.buttons == kMiddleMouseButton) {}
66+
_classicApp.onMouseMove(event.position.dx, event.position.dy);
7167
} else if (event is PointerScrollEvent) {
7268
_classicApp.onPointerWheel(event.scrollDelta.dx, event.scrollDelta.dy);
69+
} else if (event is PointerDownEvent) {
70+
if (event.buttons == kPrimaryMouseButton) {
71+
_classicApp.onMouseDown(event.position.dx, event.position.dy);
72+
} else if (event.buttons == kSecondaryMouseButton) {
73+
} else if (event.buttons == kMiddleMouseButton) {}
74+
} else if (event is PointerUpEvent) {
75+
_classicApp.onMouseUp();
7376
}
7477
}
7578

patterns/adapter/flutter_adapter/classic_app/classic_app.dart

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,11 @@ import 'repaint_compatible.dart';
77
abstract class ClassicApp implements RepaintCompatible {
88
final events = AppObserver();
99

10-
void onMouseDown() {}
10+
void onMouseDown(double x, double y) {}
11+
12+
void onMouseUp() {}
13+
14+
void onMouseMove(double x, double y) {}
1115

1216
void onPointerWheel(double deltaX, double deltaY) {}
1317

patterns/adapter/flutter_adapter/client_app/app.dart

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ class App extends ClassicApp {
1919
}
2020

2121
@override
22-
void onMouseDown() {
22+
void onMouseDown(_, __) {
2323
textColoring.color = colorRules.nextColor(textColoring.color);
2424
}
2525

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
# Memento pattern
2+
Memento is a behavioral design pattern that lets you save and restore the previous state of an
3+
object without revealing the details of its implementation.
4+
5+
Tutorial: [here](https://refactoring.guru/design-patterns/memento).
6+
7+
### Online demo:
8+
Click on the picture to see a [demo](https://RefactoringGuru.github.io/design-patterns-dart/#/memento/flutter_memento_editor).
9+
10+
[![image](https://user-images.githubusercontent.com/8049534/165401175-88bc4593-4624-45b4-8c03-6f1390ed771a.png)](https://refactoringguru.github.io/design-patterns-dart/#/memento/flutter_memento_editor)
11+
12+
13+
### Dependency Patterns
14+
This complex example includes these implementations:
15+
- [[AppObserver](https://github.com/RefactoringGuru/design-patterns-dart/tree/master/patterns/observer/app_observer)]
16+
- [[SubscriberWidget](https://github.com/RefactoringGuru/design-patterns-dart/tree/master/patterns/observer/subscriber_flutter_widget)]
17+
18+
### Diagram:
19+
![image](https://user-images.githubusercontent.com/8049534/165399085-06835617-8ef1-4e2f-930f-03d730433afb.png)
20+
21+
### Client code:
22+
```dart
23+
class MementoEditorApplication {
24+
final editor = Editor();
25+
final caretaker = Caretaker();
26+
27+
void createDefaultShapes() {/*...*/}
28+
29+
void saveState() {
30+
final snapshot = editor.backup();
31+
32+
if (caretaker.isSnapshotExists(snapshot)) {
33+
return;
34+
}
35+
36+
final memento = Memento(DateTime.now(), snapshot);
37+
caretaker.addMemento(memento);
38+
editor.events.notify(MementoCreateEvent());
39+
}
40+
41+
void restoreState(Memento memento) {
42+
editor
43+
..unSelect()
44+
..restore(memento.snapshot)
45+
..repaint();
46+
}
47+
}
48+
```
Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
import 'dart:math';
2+
3+
import 'editor/memento_create_event.dart';
4+
import 'editor/editor.dart';
5+
import 'memento_pattern/caretaker.dart';
6+
import 'memento_pattern/memento.dart';
7+
import 'shapes/shape.dart';
8+
9+
class MementoEditorApplication {
10+
final editor = Editor();
11+
final caretaker = Caretaker();
12+
13+
MementoEditorApplication() {
14+
createDefaultShapes();
15+
}
16+
17+
void createDefaultShapes() {
18+
const radius = 300.0;
19+
for (var i = 0; i < 7; i++) {
20+
final x = 60 + radius + cos(i / 1.15) * radius;
21+
final y = 60 + radius + sin(i / 1.15) * radius;
22+
editor.shapes.add(Shape(x, y));
23+
}
24+
}
25+
26+
void saveState() {
27+
final snapshot = editor.backup();
28+
29+
if (caretaker.isSnapshotExists(snapshot)) {
30+
return;
31+
}
32+
33+
final memento = Memento(DateTime.now(), snapshot);
34+
caretaker.addMemento(memento);
35+
editor.events.notify(MementoCreateEvent());
36+
}
37+
38+
void restoreState(Memento memento) {
39+
editor
40+
..unSelect()
41+
..restore(memento.snapshot)
42+
..repaint();
43+
}
44+
}
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
import 'dart:ui';
2+
3+
import '../../../adapter/flutter_adapter/classic_app/classic_app.dart';
4+
import '../memento_pattern/originator.dart';
5+
import '../shapes/shapes.dart';
6+
import 'manipulator.dart';
7+
8+
class Editor extends ClassicApp with Manipulator, Shapes, Originator {
9+
@override
10+
void onPaint(Canvas canvas, Size canvasSize) {
11+
_paintBackground(canvas, canvasSize);
12+
paintShapes(canvas);
13+
activeShape?.paintSelectionBox(canvas);
14+
}
15+
16+
void _paintBackground(Canvas canvas, Size canvasSize) {
17+
canvas.drawRect(
18+
Offset.zero & canvasSize,
19+
Paint()..color = Color(0xff404040),
20+
);
21+
}
22+
}

0 commit comments

Comments
 (0)