2 * Copyright 2006-2007, Haiku.
3 * Distributed under the terms of the MIT License.
6 * Stephan Aßmus <superstippi@gmx.de>
9 #include "CommandStack.h"
21 CommandStack::CommandStack(RWLocker
* locker
)
29 CommandStack::~CommandStack()
36 CommandStack::Perform(Command
* command
)
38 if (!fLocker
->WriteLock())
41 status_t ret
= command
? B_OK
: B_BAD_VALUE
;
43 ret
= command
->InitCheck();
46 ret
= command
->Perform();
49 ret
= _AddCommand(command
);
52 // no one else feels responsible...
55 fLocker
->WriteUnlock();
66 if (!fLocker
->WriteLock())
69 status_t status
= B_ERROR
;
70 if (!fUndoHistory
.empty()) {
71 Command
* command
= fUndoHistory
.top();
73 status
= command
->Undo();
75 fRedoHistory
.push(command
);
77 fUndoHistory
.push(command
);
79 fLocker
->WriteUnlock();
90 if (!fLocker
->WriteLock())
93 status_t status
= B_ERROR
;
94 if (!fRedoHistory
.empty()) {
95 Command
* command
= fRedoHistory
.top();
97 status
= command
->Redo();
99 fUndoHistory
.push(command
);
101 fRedoHistory
.push(command
);
103 fLocker
->WriteUnlock();
112 CommandStack::GetUndoName(BString
& name
)
114 bool success
= false;
115 if (fLocker
->ReadLock()) {
116 if (!fUndoHistory
.empty()) {
118 fUndoHistory
.top()->GetName(name
);
121 fLocker
->ReadUnlock();
128 CommandStack::GetRedoName(BString
& name
)
130 bool success
= false;
131 if (fLocker
->ReadLock()) {
132 if (!fRedoHistory
.empty()) {
134 fRedoHistory
.top()->GetName(name
);
137 fLocker
->ReadUnlock();
144 CommandStack::Clear()
146 if (fLocker
->WriteLock()) {
147 while (!fUndoHistory
.empty()) {
148 delete fUndoHistory
.top();
151 while (!fRedoHistory
.empty()) {
152 delete fRedoHistory
.top();
155 fLocker
->WriteUnlock();
165 if (fLocker
->WriteLock()) {
166 if (!fUndoHistory
.empty())
167 fSavedCommand
= fUndoHistory
.top();
168 fLocker
->WriteUnlock();
176 CommandStack::IsSaved()
179 if (fLocker
->ReadLock()) {
180 saved
= fUndoHistory
.empty();
181 if (fSavedCommand
&& !saved
) {
182 if (fSavedCommand
== fUndoHistory
.top())
185 fLocker
->ReadUnlock();
194 CommandStack::_AddCommand(Command
* command
)
196 status_t status
= B_OK
;
199 if (!fUndoHistory
.empty()) {
200 // try to collapse commands to a single command
201 // or remove this and the previous command if
202 // they reverse each other
203 if (Command
* top
= fUndoHistory
.top()) {
204 if (command
->UndoesPrevious(top
)) {
209 } else if (top
->CombineWithNext(command
)) {
212 // after collapsing, the command might
213 // have changed it's mind about InitCheck()
214 // (the commands reversed each other)
215 if (top
->InitCheck() < B_OK
) {
219 } else if (command
->CombineWithPrevious(top
)) {
222 // after collapsing, the command might
223 // have changed it's mind about InitCheck()
224 // (the commands reversed each other)
225 if (command
->InitCheck() < B_OK
) {
234 fUndoHistory
.push(command
);
240 if (status
== B_OK
) {
241 // the redo stack needs to be empty
242 // as soon as a command was added (also in case of collapsing)
243 while (!fRedoHistory
.empty()) {
244 delete fRedoHistory
.top();