2 * Copyright 2006-2012, Stephan Aßmus <superstippi@gmx.de>
3 * Distributed under the terms of the MIT License.
6 #include "EditManager.h"
15 EditManager::Listener::~Listener()
20 EditManager::EditManager()
25 EditManager::~EditManager()
32 EditManager::Perform(UndoableEdit
* edit
, EditContext
& context
)
37 return Perform(UndoableEditRef(edit
, true), context
);
42 EditManager::Perform(const UndoableEditRef
& edit
, EditContext
& context
)
44 status_t ret
= edit
.Get() != NULL
? B_OK
: B_BAD_VALUE
;
46 ret
= edit
->InitCheck();
49 ret
= edit
->Perform(context
);
64 EditManager::Undo(EditContext
& context
)
66 status_t status
= B_ERROR
;
67 if (!fUndoHistory
.IsEmpty()) {
68 UndoableEditRef
edit(fUndoHistory
.Top());
70 status
= edit
->Undo(context
);
72 fRedoHistory
.Push(edit
);
74 fUndoHistory
.Push(edit
);
84 EditManager::Redo(EditContext
& context
)
86 status_t status
= B_ERROR
;
87 if (!fRedoHistory
.IsEmpty()) {
88 UndoableEditRef
edit(fRedoHistory
.Top());
90 status
= edit
->Redo(context
);
92 fUndoHistory
.Push(edit
);
94 fRedoHistory
.Push(edit
);
104 EditManager::GetUndoName(BString
& name
)
106 if (!fUndoHistory
.IsEmpty()) {
108 fUndoHistory
.Top()->GetName(name
);
116 EditManager::GetRedoName(BString
& name
)
118 if (!fRedoHistory
.IsEmpty()) {
120 fRedoHistory
.Top()->GetName(name
);
130 while (!fUndoHistory
.IsEmpty())
132 while (!fRedoHistory
.IsEmpty())
142 if (!fUndoHistory
.IsEmpty())
143 fEditAtSave
= fUndoHistory
.Top();
150 EditManager::IsSaved()
152 bool saved
= fUndoHistory
.IsEmpty();
153 if (fEditAtSave
.Get() != NULL
&& !saved
) {
154 if (fEditAtSave
== fUndoHistory
.Top())
165 EditManager::AddListener(Listener
* listener
)
167 return fListeners
.Add(listener
);
172 EditManager::RemoveListener(Listener
* listener
)
174 fListeners
.Remove(listener
);
182 EditManager::_AddEdit(const UndoableEditRef
& edit
)
184 status_t status
= B_OK
;
187 if (!fUndoHistory
.IsEmpty()) {
188 // Try to collapse edits to a single edit
189 // or remove this and the previous edit if
190 // they reverse each other
191 const UndoableEditRef
& top
= fUndoHistory
.Top();
192 if (edit
->UndoesPrevious(top
.Get())) {
195 } else if (top
->CombineWithNext(edit
.Get())) {
197 // After collapsing, the edit might
198 // have changed it's mind about InitCheck()
199 // (the commands reversed each other)
200 if (top
->InitCheck() != B_OK
) {
203 } else if (edit
->CombineWithPrevious(top
.Get())) {
205 // After collapsing, the edit might
206 // have changed it's mind about InitCheck()
207 // (the commands reversed each other)
208 if (edit
->InitCheck() != B_OK
) {
214 if (!fUndoHistory
.Push(edit
))
215 status
= B_NO_MEMORY
;
218 if (status
== B_OK
) {
219 // The redo stack needs to be empty
220 // as soon as an edit was added (also in case of collapsing)
221 while (!fRedoHistory
.IsEmpty()) {
231 EditManager::_NotifyListeners()
233 int32 count
= fListeners
.CountItems();
236 // Iterate a copy of the list, so we don't crash if listeners
237 // detach themselves while being notified.
238 ListenerList
listenersCopy(fListeners
);
239 if (listenersCopy
.CountItems() != count
)
241 for (int32 i
= 0; i
< count
; i
++)
242 listenersCopy
.ItemAtFast(i
)->EditManagerChanged(this);