-
Notifications
You must be signed in to change notification settings - Fork 0
/
undo.h
193 lines (171 loc) · 3.86 KB
/
undo.h
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
// undo.h implementation
// Author - Keith Rule ([email protected])
//
// A description of this code can be found in May 1997 - Windows Tech Journal.
#ifndef _UNDO_H_
#define _UNDO_H_
//------------------------------------------------------------
// Undo/Redo for MFC By Keith Rule
class CUndo {
private:
CObList m_undolist; // Stores undo states
CObList m_redolist; // Stores redo states
long m_growsize; // Adjust for faster saves
long m_undoLevels; // Requested Undolevels
long m_chkpt;
void AddUndo(CMemFile*);
void AddRedo(CMemFile *pFile);
void Load(CMemFile*);
void Store(CMemFile*);
void ClearRedoList();
public:
// Here are the hooks into the CDocument class
virtual void Serialize(CArchive& ar) = 0;
virtual void DeleteContents() = 0;
// User accessable functions
CUndo(long undolevels = 4, long = 32768); // Constructor
~CUndo(); // Destructor
BOOL CanUndo(); // Returns TRUE if can Undo
BOOL CanRedo(); // Returns TRUE if can Redo
void Undo(); // Restore next Undo state
void Redo(); // Restore next Redo state
void CheckPoint(); // Save current state
void EnableCheckPoint();
void DisableCheckPoint();
};
// Constructor
inline CUndo::
CUndo(long undolevels, long growsize) :
m_growsize(growsize), m_undoLevels(undolevels),
m_chkpt(0)
{
;
}
// Remove contents of the redo list
inline void CUndo::
ClearRedoList()
{
// Clear redo list
POSITION pos = m_redolist.GetHeadPosition();
CMemFile* nextFile = NULL;
while(pos) {
nextFile = (CMemFile *) m_redolist.GetNext(pos);
delete nextFile;
}
m_redolist.RemoveAll();
}
// Destructor
inline CUndo::
~CUndo()
{
// Clear undo list
POSITION pos = m_undolist.GetHeadPosition();
CMemFile *nextFile = NULL;
while(pos) {
nextFile = (CMemFile *) m_undolist.GetNext(pos);
delete nextFile;
}
m_undolist.RemoveAll();
// Clear redo list
ClearRedoList();
}
// Checks undo availability, may be used to enable menus
inline BOOL CUndo::
CanUndo()
{
return (m_undolist.GetCount() > 1);
}
// Checks redo availability, may be used to enable menus
inline BOOL CUndo::
CanRedo()
{
return (m_redolist.GetCount() > 0);
}
// Adds state to the beginning of undo list
inline void CUndo::
AddUndo(CMemFile* file)
{
// Remove old state if there are more than max allowed
if (m_undolist.GetCount() > m_undoLevels) {
CMemFile* pFile = (CMemFile *) m_undolist.RemoveTail();
delete pFile;
}
// Add new state to head of undo list
m_undolist.AddHead(file);
}
// Saves current object into CMemFile instance
inline void CUndo::
Store(CMemFile* file)
{
file->SeekToBegin();
CArchive ar(file, CArchive::store);
Serialize(ar);
ar.Close();
}
// Loads CMemfile instance to current object
inline void CUndo::
Load(CMemFile* file)
{
DeleteContents();
file->SeekToBegin();
CArchive ar(file, CArchive::load);
Serialize(ar);
ar.Close();
}
// Save current object state to Undo list
inline void CUndo::
CheckPoint()
{
if (m_chkpt <= 0) {
CMemFile* file = new CMemFile(m_growsize);
Store(file);
AddUndo(file);
ClearRedoList();
}
}
inline void CUndo::
EnableCheckPoint()
{
if (m_chkpt > 0) {
m_chkpt--;
}
}
inline void CUndo::
DisableCheckPoint()
{
m_chkpt++;
}
// Place CMemFile instnace on Redo list
inline void CUndo::
AddRedo(CMemFile *file)
{
// Move state to head of redo list
m_redolist.AddHead(file);
}
// Perform an Undo command
inline void CUndo::
Undo()
{
if (CanUndo()) {
// Remember that the head of the undo list
// is the current state. So we just move that
// to the Redo list and load then previous state.
CMemFile *pFile = (CMemFile *) m_undolist.GetHead();
m_undolist.RemoveHead();
AddRedo(pFile);
pFile = (CMemFile *)m_undolist.GetHead();
Load(pFile);
}
}
//Perform a Redo Command
inline void CUndo::
Redo()
{
if (CanRedo()) {
CMemFile *pFile = (CMemFile *) m_redolist.GetHead() ;
m_redolist.RemoveHead();
AddUndo(pFile);
Load(pFile);
}
}
#endif