annotate doodle/main/undo_manager.d @ 29:960b408d3ac5

Builds and runs ok with builder now. Still heaps of cleaning up to do, especially code roughly imported from dog.
author Graham St Jack <graham.stjack@internode.on.net>
date Mon, 03 Aug 2009 23:19:55 +0930
parents 1754cb773d41
children
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
rev   line source
29
960b408d3ac5 Builds and runs ok with builder now.
Graham St Jack <graham.stjack@internode.on.net>
parents: 28
diff changeset
1 module doodle.main.undo_manager;
25
8f58a8f88735 Checkpoint
"David Bryant <bagnose@gmail.com>"
parents:
diff changeset
2
28
1754cb773d41 Part-way through getting to compile with configure/builder.
Graham St Jack <graham.stjack@internode.on.net>
parents: 25
diff changeset
3 version(none) {
1754cb773d41 Part-way through getting to compile with configure/builder.
Graham St Jack <graham.stjack@internode.on.net>
parents: 25
diff changeset
4
25
8f58a8f88735 Checkpoint
"David Bryant <bagnose@gmail.com>"
parents:
diff changeset
5 class UndoManager : IUndoManager {
8f58a8f88735 Checkpoint
"David Bryant <bagnose@gmail.com>"
parents:
diff changeset
6 this() {
8f58a8f88735 Checkpoint
"David Bryant <bagnose@gmail.com>"
parents:
diff changeset
7 }
8f58a8f88735 Checkpoint
"David Bryant <bagnose@gmail.com>"
parents:
diff changeset
8
8f58a8f88735 Checkpoint
"David Bryant <bagnose@gmail.com>"
parents:
diff changeset
9 void addObserver(IUndoObserver observer) {
8f58a8f88735 Checkpoint
"David Bryant <bagnose@gmail.com>"
parents:
diff changeset
10 _observers.add(observer);
8f58a8f88735 Checkpoint
"David Bryant <bagnose@gmail.com>"
parents:
diff changeset
11 }
8f58a8f88735 Checkpoint
"David Bryant <bagnose@gmail.com>"
parents:
diff changeset
12
8f58a8f88735 Checkpoint
"David Bryant <bagnose@gmail.com>"
parents:
diff changeset
13 void removeObserver(IUndoObserver observer) {
8f58a8f88735 Checkpoint
"David Bryant <bagnose@gmail.com>"
parents:
diff changeset
14 _observers.remove(observer);
8f58a8f88735 Checkpoint
"David Bryant <bagnose@gmail.com>"
parents:
diff changeset
15 }
8f58a8f88735 Checkpoint
"David Bryant <bagnose@gmail.com>"
parents:
diff changeset
16
8f58a8f88735 Checkpoint
"David Bryant <bagnose@gmail.com>"
parents:
diff changeset
17 void reset() {
8f58a8f88735 Checkpoint
"David Bryant <bagnose@gmail.com>"
parents:
diff changeset
18 assert(!inTransaction());
8f58a8f88735 Checkpoint
"David Bryant <bagnose@gmail.com>"
parents:
diff changeset
19 _past.clear();
8f58a8f88735 Checkpoint
"David Bryant <bagnose@gmail.com>"
parents:
diff changeset
20 _future.clear();
8f58a8f88735 Checkpoint
"David Bryant <bagnose@gmail.com>"
parents:
diff changeset
21 foreach(IUndoObserver obs; _observers) {
8f58a8f88735 Checkpoint
"David Bryant <bagnose@gmail.com>"
parents:
diff changeset
22 obs.canUndo(false, "");
8f58a8f88735 Checkpoint
"David Bryant <bagnose@gmail.com>"
parents:
diff changeset
23 obs.canRedo(false, "");
8f58a8f88735 Checkpoint
"David Bryant <bagnose@gmail.com>"
parents:
diff changeset
24 }
8f58a8f88735 Checkpoint
"David Bryant <bagnose@gmail.com>"
parents:
diff changeset
25 }
8f58a8f88735 Checkpoint
"David Bryant <bagnose@gmail.com>"
parents:
diff changeset
26
8f58a8f88735 Checkpoint
"David Bryant <bagnose@gmail.com>"
parents:
diff changeset
27 void undo() {
8f58a8f88735 Checkpoint
"David Bryant <bagnose@gmail.com>"
parents:
diff changeset
28 assert(canUndo());
8f58a8f88735 Checkpoint
"David Bryant <bagnose@gmail.com>"
parents:
diff changeset
29 Transaction t = _past.pop();
8f58a8f88735 Checkpoint
"David Bryant <bagnose@gmail.com>"
parents:
diff changeset
30 t.undo();
8f58a8f88735 Checkpoint
"David Bryant <bagnose@gmail.com>"
parents:
diff changeset
31 _future.push(t);
8f58a8f88735 Checkpoint
"David Bryant <bagnose@gmail.com>"
parents:
diff changeset
32 }
8f58a8f88735 Checkpoint
"David Bryant <bagnose@gmail.com>"
parents:
diff changeset
33
8f58a8f88735 Checkpoint
"David Bryant <bagnose@gmail.com>"
parents:
diff changeset
34 void redo() {
8f58a8f88735 Checkpoint
"David Bryant <bagnose@gmail.com>"
parents:
diff changeset
35 assert(canRedo());
8f58a8f88735 Checkpoint
"David Bryant <bagnose@gmail.com>"
parents:
diff changeset
36 Transaction t = _future.pop();
8f58a8f88735 Checkpoint
"David Bryant <bagnose@gmail.com>"
parents:
diff changeset
37 t.redo();
8f58a8f88735 Checkpoint
"David Bryant <bagnose@gmail.com>"
parents:
diff changeset
38 _past.push(t);
8f58a8f88735 Checkpoint
"David Bryant <bagnose@gmail.com>"
parents:
diff changeset
39 }
8f58a8f88735 Checkpoint
"David Bryant <bagnose@gmail.com>"
parents:
diff changeset
40
8f58a8f88735 Checkpoint
"David Bryant <bagnose@gmail.com>"
parents:
diff changeset
41 bool canUndo() {
8f58a8f88735 Checkpoint
"David Bryant <bagnose@gmail.com>"
parents:
diff changeset
42 assert(!inTransaction());
8f58a8f88735 Checkpoint
"David Bryant <bagnose@gmail.com>"
parents:
diff changeset
43 return !_past.empty();
8f58a8f88735 Checkpoint
"David Bryant <bagnose@gmail.com>"
parents:
diff changeset
44 }
8f58a8f88735 Checkpoint
"David Bryant <bagnose@gmail.com>"
parents:
diff changeset
45
8f58a8f88735 Checkpoint
"David Bryant <bagnose@gmail.com>"
parents:
diff changeset
46 bool canRedo() {
28
1754cb773d41 Part-way through getting to compile with configure/builder.
Graham St Jack <graham.stjack@internode.on.net>
parents: 25
diff changeset
47 assert(!inTransaction());
1754cb773d41 Part-way through getting to compile with configure/builder.
Graham St Jack <graham.stjack@internode.on.net>
parents: 25
diff changeset
48 return !_future.empty();
25
8f58a8f88735 Checkpoint
"David Bryant <bagnose@gmail.com>"
parents:
diff changeset
49 }
8f58a8f88735 Checkpoint
"David Bryant <bagnose@gmail.com>"
parents:
diff changeset
50
8f58a8f88735 Checkpoint
"David Bryant <bagnose@gmail.com>"
parents:
diff changeset
51 void beginTransaction(char[] description) {
8f58a8f88735 Checkpoint
"David Bryant <bagnose@gmail.com>"
parents:
diff changeset
52 assert(!inTransaction());
8f58a8f88735 Checkpoint
"David Bryant <bagnose@gmail.com>"
parents:
diff changeset
53 _current_transaction = new Transaction(description);
8f58a8f88735 Checkpoint
"David Bryant <bagnose@gmail.com>"
parents:
diff changeset
54 }
8f58a8f88735 Checkpoint
"David Bryant <bagnose@gmail.com>"
parents:
diff changeset
55
8f58a8f88735 Checkpoint
"David Bryant <bagnose@gmail.com>"
parents:
diff changeset
56 void cancelTransaction() {
8f58a8f88735 Checkpoint
"David Bryant <bagnose@gmail.com>"
parents:
diff changeset
57 assert(inTransaction());
8f58a8f88735 Checkpoint
"David Bryant <bagnose@gmail.com>"
parents:
diff changeset
58 _current_transaction.cancel();
8f58a8f88735 Checkpoint
"David Bryant <bagnose@gmail.com>"
parents:
diff changeset
59 _current_transaction = null;
8f58a8f88735 Checkpoint
"David Bryant <bagnose@gmail.com>"
parents:
diff changeset
60 }
8f58a8f88735 Checkpoint
"David Bryant <bagnose@gmail.com>"
parents:
diff changeset
61
8f58a8f88735 Checkpoint
"David Bryant <bagnose@gmail.com>"
parents:
diff changeset
62 void endTransaction() {
8f58a8f88735 Checkpoint
"David Bryant <bagnose@gmail.com>"
parents:
diff changeset
63 assert(inTransaction());
8f58a8f88735 Checkpoint
"David Bryant <bagnose@gmail.com>"
parents:
diff changeset
64 _current_transaction.finalise();
8f58a8f88735 Checkpoint
"David Bryant <bagnose@gmail.com>"
parents:
diff changeset
65
8f58a8f88735 Checkpoint
"David Bryant <bagnose@gmail.com>"
parents:
diff changeset
66 if (!_future.empty()) {
8f58a8f88735 Checkpoint
"David Bryant <bagnose@gmail.com>"
parents:
diff changeset
67 _future.clear();
8f58a8f88735 Checkpoint
"David Bryant <bagnose@gmail.com>"
parents:
diff changeset
68 foreach(IUndoObserver obs; _observers) {
8f58a8f88735 Checkpoint
"David Bryant <bagnose@gmail.com>"
parents:
diff changeset
69 obs.canRedo(false, "");
8f58a8f88735 Checkpoint
"David Bryant <bagnose@gmail.com>"
parents:
diff changeset
70 }
8f58a8f88735 Checkpoint
"David Bryant <bagnose@gmail.com>"
parents:
diff changeset
71 }
8f58a8f88735 Checkpoint
"David Bryant <bagnose@gmail.com>"
parents:
diff changeset
72
8f58a8f88735 Checkpoint
"David Bryant <bagnose@gmail.com>"
parents:
diff changeset
73 _past.push(_current_transaction);
8f58a8f88735 Checkpoint
"David Bryant <bagnose@gmail.com>"
parents:
diff changeset
74
8f58a8f88735 Checkpoint
"David Bryant <bagnose@gmail.com>"
parents:
diff changeset
75 foreach(IUndoObserver obs; _observers) {
8f58a8f88735 Checkpoint
"David Bryant <bagnose@gmail.com>"
parents:
diff changeset
76 bs.canUndo(true, _current_transaction.name());
8f58a8f88735 Checkpoint
"David Bryant <bagnose@gmail.com>"
parents:
diff changeset
77 }
8f58a8f88735 Checkpoint
"David Bryant <bagnose@gmail.com>"
parents:
diff changeset
78
8f58a8f88735 Checkpoint
"David Bryant <bagnose@gmail.com>"
parents:
diff changeset
79 _current_transaction = null;
8f58a8f88735 Checkpoint
"David Bryant <bagnose@gmail.com>"
parents:
diff changeset
80 }
8f58a8f88735 Checkpoint
"David Bryant <bagnose@gmail.com>"
parents:
diff changeset
81
8f58a8f88735 Checkpoint
"David Bryant <bagnose@gmail.com>"
parents:
diff changeset
82 // IUndoManager implementations:
8f58a8f88735 Checkpoint
"David Bryant <bagnose@gmail.com>"
parents:
diff changeset
83
8f58a8f88735 Checkpoint
"David Bryant <bagnose@gmail.com>"
parents:
diff changeset
84 void addAction(Action action) {
8f58a8f88735 Checkpoint
"David Bryant <bagnose@gmail.com>"
parents:
diff changeset
85 assert(inTransaction());
8f58a8f88735 Checkpoint
"David Bryant <bagnose@gmail.com>"
parents:
diff changeset
86 _current_transaction.add(action);
8f58a8f88735 Checkpoint
"David Bryant <bagnose@gmail.com>"
parents:
diff changeset
87 }
8f58a8f88735 Checkpoint
"David Bryant <bagnose@gmail.com>"
parents:
diff changeset
88
8f58a8f88735 Checkpoint
"David Bryant <bagnose@gmail.com>"
parents:
diff changeset
89 private {
8f58a8f88735 Checkpoint
"David Bryant <bagnose@gmail.com>"
parents:
diff changeset
90 bool inTransaction() {
8f58a8f88735 Checkpoint
"David Bryant <bagnose@gmail.com>"
parents:
diff changeset
91 return _current_transaction !is null;
8f58a8f88735 Checkpoint
"David Bryant <bagnose@gmail.com>"
parents:
diff changeset
92 }
8f58a8f88735 Checkpoint
"David Bryant <bagnose@gmail.com>"
parents:
diff changeset
93
8f58a8f88735 Checkpoint
"David Bryant <bagnose@gmail.com>"
parents:
diff changeset
94 class Transaction {
8f58a8f88735 Checkpoint
"David Bryant <bagnose@gmail.com>"
parents:
diff changeset
95 enum State {
8f58a8f88735 Checkpoint
"David Bryant <bagnose@gmail.com>"
parents:
diff changeset
96 Accumulating,
8f58a8f88735 Checkpoint
"David Bryant <bagnose@gmail.com>"
parents:
diff changeset
97 Finalised,
8f58a8f88735 Checkpoint
"David Bryant <bagnose@gmail.com>"
parents:
diff changeset
98 Canceled
8f58a8f88735 Checkpoint
"David Bryant <bagnose@gmail.com>"
parents:
diff changeset
99 }
8f58a8f88735 Checkpoint
"David Bryant <bagnose@gmail.com>"
parents:
diff changeset
100
8f58a8f88735 Checkpoint
"David Bryant <bagnose@gmail.com>"
parents:
diff changeset
101 this(char[] description) {
8f58a8f88735 Checkpoint
"David Bryant <bagnose@gmail.com>"
parents:
diff changeset
102 _description = description;
8f58a8f88735 Checkpoint
"David Bryant <bagnose@gmail.com>"
parents:
diff changeset
103 _state = Accumulating;
8f58a8f88735 Checkpoint
"David Bryant <bagnose@gmail.com>"
parents:
diff changeset
104 }
8f58a8f88735 Checkpoint
"David Bryant <bagnose@gmail.com>"
parents:
diff changeset
105
8f58a8f88735 Checkpoint
"David Bryant <bagnose@gmail.com>"
parents:
diff changeset
106 char[] description() {
8f58a8f88735 Checkpoint
"David Bryant <bagnose@gmail.com>"
parents:
diff changeset
107 return _description;
8f58a8f88735 Checkpoint
"David Bryant <bagnose@gmail.com>"
parents:
diff changeset
108 }
8f58a8f88735 Checkpoint
"David Bryant <bagnose@gmail.com>"
parents:
diff changeset
109
8f58a8f88735 Checkpoint
"David Bryant <bagnose@gmail.com>"
parents:
diff changeset
110 void add(Action action) {
8f58a8f88735 Checkpoint
"David Bryant <bagnose@gmail.com>"
parents:
diff changeset
111 assert(_state == State.Accumulating);
8f58a8f88735 Checkpoint
"David Bryant <bagnose@gmail.com>"
parents:
diff changeset
112 _actions.addTail(action);
8f58a8f88735 Checkpoint
"David Bryant <bagnose@gmail.com>"
parents:
diff changeset
113 }
8f58a8f88735 Checkpoint
"David Bryant <bagnose@gmail.com>"
parents:
diff changeset
114
8f58a8f88735 Checkpoint
"David Bryant <bagnose@gmail.com>"
parents:
diff changeset
115 void finalise() {
8f58a8f88735 Checkpoint
"David Bryant <bagnose@gmail.com>"
parents:
diff changeset
116 assert(_state == State.Accumulating);
8f58a8f88735 Checkpoint
"David Bryant <bagnose@gmail.com>"
parents:
diff changeset
117 assert(!_actions.empty());
8f58a8f88735 Checkpoint
"David Bryant <bagnose@gmail.com>"
parents:
diff changeset
118 _finalised = true;
8f58a8f88735 Checkpoint
"David Bryant <bagnose@gmail.com>"
parents:
diff changeset
119 }
8f58a8f88735 Checkpoint
"David Bryant <bagnose@gmail.com>"
parents:
diff changeset
120
8f58a8f88735 Checkpoint
"David Bryant <bagnose@gmail.com>"
parents:
diff changeset
121 void cancel() {
8f58a8f88735 Checkpoint
"David Bryant <bagnose@gmail.com>"
parents:
diff changeset
122 assert(_state == State.Accumulating);
28
1754cb773d41 Part-way through getting to compile with configure/builder.
Graham St Jack <graham.stjack@internode.on.net>
parents: 25
diff changeset
123 foreach_reverse(UndoAction ua; _actions) {
25
8f58a8f88735 Checkpoint
"David Bryant <bagnose@gmail.com>"
parents:
diff changeset
124 ua.undo();
8f58a8f88735 Checkpoint
"David Bryant <bagnose@gmail.com>"
parents:
diff changeset
125 }
8f58a8f88735 Checkpoint
"David Bryant <bagnose@gmail.com>"
parents:
diff changeset
126 }
8f58a8f88735 Checkpoint
"David Bryant <bagnose@gmail.com>"
parents:
diff changeset
127
8f58a8f88735 Checkpoint
"David Bryant <bagnose@gmail.com>"
parents:
diff changeset
128 void redo() {
8f58a8f88735 Checkpoint
"David Bryant <bagnose@gmail.com>"
parents:
diff changeset
129 assert(_finalised);
8f58a8f88735 Checkpoint
"David Bryant <bagnose@gmail.com>"
parents:
diff changeset
130 foreach (UndoAction ua; _actions) {
8f58a8f88735 Checkpoint
"David Bryant <bagnose@gmail.com>"
parents:
diff changeset
131 ua.redo();
8f58a8f88735 Checkpoint
"David Bryant <bagnose@gmail.com>"
parents:
diff changeset
132 }
8f58a8f88735 Checkpoint
"David Bryant <bagnose@gmail.com>"
parents:
diff changeset
133 }
8f58a8f88735 Checkpoint
"David Bryant <bagnose@gmail.com>"
parents:
diff changeset
134
8f58a8f88735 Checkpoint
"David Bryant <bagnose@gmail.com>"
parents:
diff changeset
135 void undo() {
8f58a8f88735 Checkpoint
"David Bryant <bagnose@gmail.com>"
parents:
diff changeset
136 assert(_finalised);
28
1754cb773d41 Part-way through getting to compile with configure/builder.
Graham St Jack <graham.stjack@internode.on.net>
parents: 25
diff changeset
137 foreach_reverse(UndoAction ua; _actions) {
25
8f58a8f88735 Checkpoint
"David Bryant <bagnose@gmail.com>"
parents:
diff changeset
138 ua.undo();
8f58a8f88735 Checkpoint
"David Bryant <bagnose@gmail.com>"
parents:
diff changeset
139 }
8f58a8f88735 Checkpoint
"David Bryant <bagnose@gmail.com>"
parents:
diff changeset
140 }
8f58a8f88735 Checkpoint
"David Bryant <bagnose@gmail.com>"
parents:
diff changeset
141
8f58a8f88735 Checkpoint
"David Bryant <bagnose@gmail.com>"
parents:
diff changeset
142 private {
8f58a8f88735 Checkpoint
"David Bryant <bagnose@gmail.com>"
parents:
diff changeset
143 char[] _description;
28
1754cb773d41 Part-way through getting to compile with configure/builder.
Graham St Jack <graham.stjack@internode.on.net>
parents: 25
diff changeset
144 List!(Action) _actions;
25
8f58a8f88735 Checkpoint
"David Bryant <bagnose@gmail.com>"
parents:
diff changeset
145 State _state;
8f58a8f88735 Checkpoint
"David Bryant <bagnose@gmail.com>"
parents:
diff changeset
146 }
8f58a8f88735 Checkpoint
"David Bryant <bagnose@gmail.com>"
parents:
diff changeset
147 }
8f58a8f88735 Checkpoint
"David Bryant <bagnose@gmail.com>"
parents:
diff changeset
148
8f58a8f88735 Checkpoint
"David Bryant <bagnose@gmail.com>"
parents:
diff changeset
149 Transaction _current_transaction;
8f58a8f88735 Checkpoint
"David Bryant <bagnose@gmail.com>"
parents:
diff changeset
150 Stack!(Transaction) _past;
8f58a8f88735 Checkpoint
"David Bryant <bagnose@gmail.com>"
parents:
diff changeset
151 Stack!(Transaction) _future;
8f58a8f88735 Checkpoint
"David Bryant <bagnose@gmail.com>"
parents:
diff changeset
152 Set!(IUndoObserver) _observers;
8f58a8f88735 Checkpoint
"David Bryant <bagnose@gmail.com>"
parents:
diff changeset
153 }
8f58a8f88735 Checkpoint
"David Bryant <bagnose@gmail.com>"
parents:
diff changeset
154 }
28
1754cb773d41 Part-way through getting to compile with configure/builder.
Graham St Jack <graham.stjack@internode.on.net>
parents: 25
diff changeset
155 }