Mercurial > projects > doodle
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 |
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 | 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 | 5 class UndoManager : IUndoManager { |
6 this() { | |
7 } | |
8 | |
9 void addObserver(IUndoObserver observer) { | |
10 _observers.add(observer); | |
11 } | |
12 | |
13 void removeObserver(IUndoObserver observer) { | |
14 _observers.remove(observer); | |
15 } | |
16 | |
17 void reset() { | |
18 assert(!inTransaction()); | |
19 _past.clear(); | |
20 _future.clear(); | |
21 foreach(IUndoObserver obs; _observers) { | |
22 obs.canUndo(false, ""); | |
23 obs.canRedo(false, ""); | |
24 } | |
25 } | |
26 | |
27 void undo() { | |
28 assert(canUndo()); | |
29 Transaction t = _past.pop(); | |
30 t.undo(); | |
31 _future.push(t); | |
32 } | |
33 | |
34 void redo() { | |
35 assert(canRedo()); | |
36 Transaction t = _future.pop(); | |
37 t.redo(); | |
38 _past.push(t); | |
39 } | |
40 | |
41 bool canUndo() { | |
42 assert(!inTransaction()); | |
43 return !_past.empty(); | |
44 } | |
45 | |
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 | 49 } |
50 | |
51 void beginTransaction(char[] description) { | |
52 assert(!inTransaction()); | |
53 _current_transaction = new Transaction(description); | |
54 } | |
55 | |
56 void cancelTransaction() { | |
57 assert(inTransaction()); | |
58 _current_transaction.cancel(); | |
59 _current_transaction = null; | |
60 } | |
61 | |
62 void endTransaction() { | |
63 assert(inTransaction()); | |
64 _current_transaction.finalise(); | |
65 | |
66 if (!_future.empty()) { | |
67 _future.clear(); | |
68 foreach(IUndoObserver obs; _observers) { | |
69 obs.canRedo(false, ""); | |
70 } | |
71 } | |
72 | |
73 _past.push(_current_transaction); | |
74 | |
75 foreach(IUndoObserver obs; _observers) { | |
76 bs.canUndo(true, _current_transaction.name()); | |
77 } | |
78 | |
79 _current_transaction = null; | |
80 } | |
81 | |
82 // IUndoManager implementations: | |
83 | |
84 void addAction(Action action) { | |
85 assert(inTransaction()); | |
86 _current_transaction.add(action); | |
87 } | |
88 | |
89 private { | |
90 bool inTransaction() { | |
91 return _current_transaction !is null; | |
92 } | |
93 | |
94 class Transaction { | |
95 enum State { | |
96 Accumulating, | |
97 Finalised, | |
98 Canceled | |
99 } | |
100 | |
101 this(char[] description) { | |
102 _description = description; | |
103 _state = Accumulating; | |
104 } | |
105 | |
106 char[] description() { | |
107 return _description; | |
108 } | |
109 | |
110 void add(Action action) { | |
111 assert(_state == State.Accumulating); | |
112 _actions.addTail(action); | |
113 } | |
114 | |
115 void finalise() { | |
116 assert(_state == State.Accumulating); | |
117 assert(!_actions.empty()); | |
118 _finalised = true; | |
119 } | |
120 | |
121 void cancel() { | |
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 | 124 ua.undo(); |
125 } | |
126 } | |
127 | |
128 void redo() { | |
129 assert(_finalised); | |
130 foreach (UndoAction ua; _actions) { | |
131 ua.redo(); | |
132 } | |
133 } | |
134 | |
135 void undo() { | |
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 | 138 ua.undo(); |
139 } | |
140 } | |
141 | |
142 private { | |
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 | 145 State _state; |
146 } | |
147 } | |
148 | |
149 Transaction _current_transaction; | |
150 Stack!(Transaction) _past; | |
151 Stack!(Transaction) _future; | |
152 Set!(IUndoObserver) _observers; | |
153 } | |
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 } |