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 }