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