Added a StateWatcher class that will automatically send notices for

all changed states during the lifetime of the object upon destruction.
Added some comments.
Uncommented the IsModified() method (does not yet work correctly, though).


git-svn-id: file:///srv/svn/repos/haiku/trunk/current@6760 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
Axel Dörfler
2004-02-26 15:18:02 +00:00
parent 35789209bd
commit c65f61d4ad
2 changed files with 77 additions and 38 deletions
+70 -36
View File
@@ -15,6 +15,18 @@
#include <unistd.h> #include <unistd.h>
class StateWatcher {
public:
StateWatcher(DataEditor &editor);
~StateWatcher();
private:
DataEditor &fEditor;
bool fCouldUndo;
bool fCouldRedo;
bool fWasModified;
};
class DataChange { class DataChange {
public: public:
virtual ~DataChange(); virtual ~DataChange();
@@ -44,6 +56,36 @@ class ReplaceChange : public DataChange {
}; };
//---------------------
StateWatcher::StateWatcher(DataEditor &editor)
:
fEditor(editor)
{
fCouldUndo = editor.CanUndo();
fCouldRedo = editor.CanRedo();
fWasModified = editor.IsModified();
}
StateWatcher::~StateWatcher()
{
BMessage update;
if (fCouldRedo != fEditor.CanRedo())
update.AddBool("can_redo", fEditor.CanRedo());
if (fCouldUndo != fEditor.CanUndo())
update.AddBool("can_undo", fEditor.CanUndo());
if (fWasModified != fEditor.IsModified())
update.AddBool("modified", fEditor.IsModified());
fEditor.SendNotices(kMsgDataEditorStateChange, &update);
}
// #pragma mark -
DataChange::~DataChange() DataChange::~DataChange()
{ {
} }
@@ -272,34 +314,30 @@ DataEditor::InitCheck()
} }
void void
DataEditor::AddChange(DataChange *change) DataEditor::AddChange(DataChange *change)
{ {
if (change == NULL) if (change == NULL)
return; return;
bool removed = RemoveRedos(); StateWatcher watcher(*this);
bool changed = !CanUndo(); // update state observers
RemoveRedos();
fChanges.AddItem(change); fChanges.AddItem(change);
fLastChange = change; fLastChange = change;
fLastChange->Apply(fRealViewOffset, fView, fRealViewSize); fLastChange->Apply(fRealViewOffset, fView, fRealViewSize);
// ToDo: try to join changes
// update observers // update observers
SendNotices(fLastChange); SendNotices(fLastChange);
BMessage update;
if (removed)
update.AddBool("can_redo", false);
if (changed)
update.AddBool("can_undo", true);
SendNotices(kMsgDataEditorStateChange, &update);
} }
status_t status_t
DataEditor::Replace(off_t offset, const uint8 *data, size_t length) DataEditor::Replace(off_t offset, const uint8 *data, size_t length)
{ {
BAutolock locker(this); BAutolock locker(this);
@@ -322,29 +360,31 @@ DataEditor::Replace(off_t offset, const uint8 *data, size_t length)
} }
status_t status_t
DataEditor::Remove(off_t offset, off_t length) DataEditor::Remove(off_t offset, off_t length)
{ {
BAutolock locker(this); BAutolock locker(this);
// not yet implemented // not yet implemented
// ToDo: this needs some changes to the whole change mechanism
return B_ERROR; return B_ERROR;
} }
status_t status_t
DataEditor::Insert(off_t offset, const uint8 *text, size_t length) DataEditor::Insert(off_t offset, const uint8 *text, size_t length)
{ {
BAutolock locker(this); BAutolock locker(this);
// not yet implemented // not yet implemented
// ToDo: this needs some changes to the whole change mechanism
return B_ERROR; return B_ERROR;
} }
void void
DataEditor::ApplyChanges() DataEditor::ApplyChanges()
{ {
if (fLastChange == NULL) if (fLastChange == NULL)
@@ -359,28 +399,33 @@ DataEditor::ApplyChanges()
} }
status_t
DataEditor::Save()
{
// collect ranges of data we need to write
// read in data and apply changes, write it back to disk
}
/** This method will be called by DataEditor::AddChange() /** This method will be called by DataEditor::AddChange()
* immediately before a change is applied. * immediately before a change is applied.
* It removes all pending redo nodes from the list that would * It removes all pending redo nodes from the list that would
* come after the current change. * come after the current change.
*/ */
bool void
DataEditor::RemoveRedos() DataEditor::RemoveRedos()
{ {
if (fLastChange == NULL) if (fLastChange == NULL)
return false; return;
int32 start = fChanges.IndexOf(fLastChange) + 1; int32 start = fChanges.IndexOf(fLastChange) + 1;
bool removed = false;
for (int32 i = fChanges.CountItems(); i-- > start; ) { for (int32 i = fChanges.CountItems(); i-- > start; ) {
DataChange *change = fChanges.RemoveItemAt(i); DataChange *change = fChanges.RemoveItemAt(i);
delete change; delete change;
removed = true;
} }
return removed;
} }
@@ -392,7 +437,9 @@ DataEditor::Undo()
if (!CanUndo()) if (!CanUndo())
return B_ERROR; return B_ERROR;
bool couldRedo = CanRedo(); StateWatcher watcher(*this);
// update state observers
DataChange *undoChange = fLastChange; DataChange *undoChange = fLastChange;
int32 index = fChanges.IndexOf(undoChange); int32 index = fChanges.IndexOf(undoChange);
@@ -406,13 +453,6 @@ DataEditor::Undo()
// update observers // update observers
SendNotices(undoChange); SendNotices(undoChange);
BMessage update;
if (!couldRedo)
update.AddBool("can_redo", true);
if (!CanUndo())
update.AddBool("can_undo", false);
SendNotices(kMsgDataEditorStateChange, &update);
return B_OK; return B_OK;
} }
@@ -425,7 +465,8 @@ DataEditor::Redo()
if (!CanRedo()) if (!CanRedo())
return B_ERROR; return B_ERROR;
bool couldUndo = CanUndo(); StateWatcher watcher(*this);
// update state observers
int32 index = fChanges.IndexOf(fLastChange); int32 index = fChanges.IndexOf(fLastChange);
fLastChange = fChanges.ItemAt(index + 1); fLastChange = fChanges.ItemAt(index + 1);
@@ -435,13 +476,6 @@ DataEditor::Redo()
// update observers // update observers
SendNotices(fLastChange); SendNotices(fLastChange);
BMessage update;
if (!CanRedo())
update.AddBool("can_redo", false);
if (!couldUndo)
update.AddBool("can_undo", true);
SendNotices(kMsgDataEditorStateChange, &update);
return B_OK; return B_OK;
} }
+7 -2
View File
@@ -13,6 +13,7 @@
class DataChange; class DataChange;
class StateWatcher;
class DataEditor : public BLocker { class DataEditor : public BLocker {
public: public:
@@ -26,10 +27,12 @@ class DataEditor : public BLocker {
status_t SetTo(entry_ref &ref, const char *attribute = NULL); status_t SetTo(entry_ref &ref, const char *attribute = NULL);
status_t SetTo(BEntry &entry, const char *attribute = NULL); status_t SetTo(BEntry &entry, const char *attribute = NULL);
status_t Save();
bool IsReadOnly() const { return fIsReadOnly; } bool IsReadOnly() const { return fIsReadOnly; }
bool IsDevice() const { return fIsDevice; } bool IsDevice() const { return fIsDevice; }
bool IsAttribute() const { return fAttribute != NULL; } bool IsAttribute() const { return fAttribute != NULL; }
//bool IsModified() const { return fIsModified; } bool IsModified() const { return fLastChange != fFirstChange; }
const char *Attribute() const { return fAttribute; } const char *Attribute() const { return fAttribute; }
type_code Type() const { return fType; } type_code Type() const { return fType; }
@@ -73,12 +76,14 @@ class DataEditor : public BLocker {
const entry_ref &Ref() const { return fRef; } const entry_ref &Ref() const { return fRef; }
private: private:
friend class StateWatcher;
void SendNotices(uint32 what, BMessage *message = NULL); void SendNotices(uint32 what, BMessage *message = NULL);
void SendNotices(DataChange *change); void SendNotices(DataChange *change);
status_t Update(); status_t Update();
void AddChange(DataChange *change); void AddChange(DataChange *change);
void ApplyChanges(); void ApplyChanges();
bool RemoveRedos(); void RemoveRedos();
BObjectList<BMessenger> fObservers; BObjectList<BMessenger> fObservers;