[haiku-commits] haiku: hrev48826 - in src/apps/haikudepot: edits_generic textview

  • From: superstippi@xxxxxx
  • To: haiku-commits@xxxxxxxxxxxxx
  • Date: Sun, 22 Feb 2015 21:42:21 +0100 (CET)

hrev48826 adds 3 changesets to branch 'master'
old head: ee3b36afff686ee8686e759799b487395c251c96
new head: 4bf45bfb5d2366ab2e4b7d1cdd427729ed449c73
overview: 
http://cgit.haiku-os.org/haiku/log/?qt=range&q=4bf45bfb5d23+%5Eee3b36afff68

----------------------------------------------------------------------------

651e8326ca65: HaikuDepot: Base-classes for generic undo/redo support.
  
  I plan to use these in the text view and editor framework.

b5cbbf804128: HaikuDepot: UndoableEditListener base class added

4bf45bfb5d23: HaikuDepot: Added UndoableEditListener list to TextDocument
  
  This is all work in progress. The plan is to move the code that does any
  actual changes to the TextDocument into UndoableEdit implementations, then
  emit these edits to interesed listeners. They can then store them to
  implement the edit history. If there are not listeners, the edits will
  simply be released after they've done their work.
  Implemented so far is only the support for storing the edit listeners.

                                      [ Stephan Aßmus <superstippi@xxxxxx> ]

----------------------------------------------------------------------------

15 files changed, 810 insertions(+), 3 deletions(-)
src/apps/haikudepot/Jamfile                      |  10 +-
.../haikudepot/edits_generic/CompoundEdit.cpp    | 117 +++++++++
src/apps/haikudepot/edits_generic/CompoundEdit.h |  36 +++
.../haikudepot/edits_generic/EditContext.cpp     |  18 ++
src/apps/haikudepot/edits_generic/EditContext.h  |  26 ++
.../haikudepot/edits_generic/EditManager.cpp     | 244 +++++++++++++++++++
src/apps/haikudepot/edits_generic/EditManager.h  |  60 +++++
src/apps/haikudepot/edits_generic/EditStack.cpp  |  49 ++++
src/apps/haikudepot/edits_generic/EditStack.h    |  30 +++
.../haikudepot/edits_generic/UndoableEdit.cpp    |  86 +++++++
src/apps/haikudepot/edits_generic/UndoableEdit.h |  41 ++++
src/apps/haikudepot/textview/TextDocument.cpp    |  29 +++
src/apps/haikudepot/textview/TextDocument.h      |  13 +-
.../haikudepot/textview/UndoableEditListener.cpp |  25 ++
.../haikudepot/textview/UndoableEditListener.h   |  29 +++

############################################################################

Commit:      651e8326ca65a7ed8616db1efc466d17e71baf28
URL:         http://cgit.haiku-os.org/haiku/commit/?id=651e8326ca65
Author:      Stephan Aßmus <superstippi@xxxxxx>
Date:        Sat Feb  7 22:12:02 2015 UTC

HaikuDepot: Base-classes for generic undo/redo support.

I plan to use these in the text view and editor framework.

----------------------------------------------------------------------------

diff --git a/src/apps/haikudepot/Jamfile b/src/apps/haikudepot/Jamfile
index 2d6a5b3..0a38be2 100644
--- a/src/apps/haikudepot/Jamfile
+++ b/src/apps/haikudepot/Jamfile
@@ -4,7 +4,7 @@ UsePrivateHeaders interface shared package ;
 
 # source directories
 local sourceDirs =
-       model textview ui ui_generic
+       edits_generic model textview ui ui_generic
 ;
 
 local sourceDir ;
@@ -15,6 +15,13 @@ for sourceDir in $(sourceDirs) {
 SEARCH_SOURCE += [ FDirName $(HAIKU_TOP) src servers package ] ;
 
 local textDocumentSources =
+       # edits_generic
+       CompoundEdit.cpp
+       EditContext.cpp
+       EditManager.cpp
+       EditStack.cpp
+       UndoableEdit.cpp
+       # textview
        Bullet.cpp
        BulletData.cpp
        CharacterStyle.cpp
diff --git a/src/apps/haikudepot/edits_generic/CompoundEdit.cpp 
b/src/apps/haikudepot/edits_generic/CompoundEdit.cpp
new file mode 100644
index 0000000..7c2c405
--- /dev/null
+++ b/src/apps/haikudepot/edits_generic/CompoundEdit.cpp
@@ -0,0 +1,117 @@
+/*
+ * Copyright 2006-2112, Stephan Aßmus <superstippi@xxxxxx>
+ * Distributed under the terms of the MIT License.
+ */
+
+#include "CompoundEdit.h"
+
+#include <stdio.h>
+
+
+CompoundEdit::CompoundEdit(const char* name)
+       : UndoableEdit()
+       , fEdits()
+       , fName(name)
+{
+}
+
+
+CompoundEdit::~CompoundEdit()
+{
+}
+
+
+status_t
+CompoundEdit::InitCheck()
+{
+       return B_OK;
+}
+
+
+status_t
+CompoundEdit::Perform(EditContext& context)
+{
+       status_t status = B_OK;
+
+       int32 count = fEdits.CountItems();
+       int32 i = 0;
+       for (; i < count; i++) {
+               status = fEdits.ItemAtFast(i)->Perform(context);
+               if (status != B_OK)
+                       break;
+       }
+
+       if (status != B_OK) {
+               // roll back
+               i--;
+               for (; i >= 0; i--) {
+                       fEdits.ItemAtFast(i)->Undo(context);
+               }
+       }
+
+       return status;
+}
+
+
+status_t
+CompoundEdit::Undo(EditContext& context)
+{
+       status_t status = B_OK;
+
+       int32 count = fEdits.CountItems();
+       int32 i = count - 1;
+       for (; i >= 0; i--) {
+               status = fEdits.ItemAtFast(i)->Undo(context);
+               if (status != B_OK)
+                       break;
+       }
+
+       if (status != B_OK) {
+               // roll back
+               i++;
+               for (; i < count; i++) {
+                       fEdits.ItemAtFast(i)->Redo(context);
+               }
+       }
+
+       return status;
+}
+
+
+status_t
+CompoundEdit::Redo(EditContext& context)
+{
+       status_t status = B_OK;
+
+       int32 count = fEdits.CountItems();
+       int32 i = 0;
+       for (; i < count; i++) {
+               status = fEdits.ItemAtFast(i)->Redo(context);
+               if (status != B_OK)
+                       break;
+       }
+
+       if (status != B_OK) {
+               // roll back
+               i--;
+               for (; i >= 0; i--) {
+                       fEdits.ItemAtFast(i)->Undo(context);
+               }
+       }
+
+       return status;
+}
+
+
+void
+CompoundEdit::GetName(BString& name)
+{
+       name << fName;
+}
+
+
+bool
+CompoundEdit::AppendEdit(const UndoableEditRef& edit)
+{
+       return fEdits.Add(edit);
+}
diff --git a/src/apps/haikudepot/edits_generic/CompoundEdit.h 
b/src/apps/haikudepot/edits_generic/CompoundEdit.h
new file mode 100644
index 0000000..3edf639
--- /dev/null
+++ b/src/apps/haikudepot/edits_generic/CompoundEdit.h
@@ -0,0 +1,36 @@
+/*
+ * Copyright 2006-2112, Stephan Aßmus <superstippi@xxxxxx>
+ * Distributed under the terms of the MIT License.
+ */
+
+#ifndef COMPOUND_EDIT_H
+#define COMPOUND_EDIT_H
+
+#include <String.h>
+
+#include "List.h"
+#include "UndoableEdit.h"
+
+class CompoundEdit : public UndoableEdit {
+public:
+                                                               
CompoundEdit(const char* name);
+       virtual                                         ~CompoundEdit();
+
+       virtual status_t                        InitCheck();
+
+       virtual status_t                        Perform(EditContext& context);
+       virtual status_t                        Undo(EditContext& context);
+       virtual status_t                        Redo(EditContext& context);
+
+       virtual void                            GetName(BString& name);
+
+                       bool                            AppendEdit(const 
UndoableEditRef& edit);
+
+private:
+                       typedef List<UndoableEditRef, false, 2> EditList;
+
+                       EditList                        fEdits;
+                       BString                         fName;
+};
+
+#endif // COMPOUND_EDIT_H
diff --git a/src/apps/haikudepot/edits_generic/EditContext.cpp 
b/src/apps/haikudepot/edits_generic/EditContext.cpp
new file mode 100644
index 0000000..afb956e
--- /dev/null
+++ b/src/apps/haikudepot/edits_generic/EditContext.cpp
@@ -0,0 +1,18 @@
+/*
+ * Copyright 2013 Stephan Aßmus <superstippi@xxxxxx>
+ * Distributed under the terms of the MIT License.
+ */
+
+#include "EditContext.h"
+
+#include <stdio.h>
+
+
+EditContext::EditContext()
+{
+}
+
+
+EditContext::~EditContext()
+{
+}
diff --git a/src/apps/haikudepot/edits_generic/EditContext.h 
b/src/apps/haikudepot/edits_generic/EditContext.h
new file mode 100644
index 0000000..6f30813
--- /dev/null
+++ b/src/apps/haikudepot/edits_generic/EditContext.h
@@ -0,0 +1,26 @@
+/*
+ * Copyright 2013 Stephan Aßmus <superstippi@xxxxxx>
+ * Distributed under the terms of the MIT License.
+ */
+
+#ifndef EDIT_CONTEXT_H
+#define EDIT_CONTEXT_H
+
+#include <Referenceable.h>
+
+/**
+ * EditContext is passed to UndoableEdits in Perform(), Undo(), and Redo().
+ * It provides a context in which the user performs these operations
+ * and can be used for example to control the selection or visible
+ * portion of the document to focus the user's attention on the
+ * elements affected by the UndoableEdit.
+ */
+class EditContext : public BReferenceable {
+public:
+                                                               EditContext();
+       virtual                                         ~EditContext();
+};
+
+typedef BReference<EditContext> EditContextRef;
+
+#endif // EDIT_CONTEXT_H
diff --git a/src/apps/haikudepot/edits_generic/EditManager.cpp 
b/src/apps/haikudepot/edits_generic/EditManager.cpp
new file mode 100644
index 0000000..b91f195
--- /dev/null
+++ b/src/apps/haikudepot/edits_generic/EditManager.cpp
@@ -0,0 +1,244 @@
+/*
+ * Copyright 2006-2012, Stephan Aßmus <superstippi@xxxxxx>
+ * Distributed under the terms of the MIT License.
+ */
+
+#include "EditManager.h"
+
+#include <stdio.h>
+#include <string.h>
+
+#include <Locker.h>
+#include <String.h>
+
+
+EditManager::Listener::~Listener()
+{
+}
+
+
+EditManager::EditManager()
+{
+}
+
+
+EditManager::~EditManager()
+{
+       Clear();
+}
+
+
+status_t
+EditManager::Perform(UndoableEdit* edit, EditContext& context)
+{
+       if (edit == NULL)
+               return B_BAD_VALUE;
+
+       return Perform(UndoableEditRef(edit, true), context);
+}
+
+
+status_t
+EditManager::Perform(const UndoableEditRef& edit, EditContext& context)
+{
+       status_t ret = edit.Get() != NULL ? B_OK : B_BAD_VALUE;
+       if (ret == B_OK)
+               ret = edit->InitCheck();
+
+       if (ret == B_OK)
+               ret = edit->Perform(context);
+
+       if (ret == B_OK) {
+               ret = _AddEdit(edit);
+               if (ret != B_OK)
+                       edit->Undo(context);
+       }
+
+       _NotifyListeners();
+
+       return ret;
+}
+
+
+status_t
+EditManager::Undo(EditContext& context)
+{
+       status_t status = B_ERROR;
+       if (!fUndoHistory.IsEmpty()) {
+               UndoableEditRef edit(fUndoHistory.Top());
+               fUndoHistory.Pop();
+               status = edit->Undo(context);
+               if (status == B_OK)
+                       fRedoHistory.Push(edit);
+               else
+                       fUndoHistory.Push(edit);
+       }
+
+       _NotifyListeners();
+
+       return status;
+}
+
+
+status_t
+EditManager::Redo(EditContext& context)
+{
+       status_t status = B_ERROR;
+       if (!fRedoHistory.IsEmpty()) {
+               UndoableEditRef edit(fRedoHistory.Top());
+               fRedoHistory.Pop();
+               status = edit->Redo(context);
+               if (status == B_OK)
+                       fUndoHistory.Push(edit);
+               else
+                       fRedoHistory.Push(edit);
+       }
+
+       _NotifyListeners();
+
+       return status;
+}
+
+
+bool
+EditManager::GetUndoName(BString& name)
+{
+       if (!fUndoHistory.IsEmpty()) {
+               name << " ";
+               fUndoHistory.Top()->GetName(name);
+               return true;
+       }
+       return false;
+}
+
+
+bool
+EditManager::GetRedoName(BString& name)
+{
+       if (!fRedoHistory.IsEmpty()) {
+               name << " ";
+               fRedoHistory.Top()->GetName(name);
+               return true;
+       }
+       return false;
+}
+
+
+void
+EditManager::Clear()
+{
+       while (!fUndoHistory.IsEmpty())
+               fUndoHistory.Pop();
+       while (!fRedoHistory.IsEmpty())
+               fRedoHistory.Pop();
+
+       _NotifyListeners();
+}
+
+
+void
+EditManager::Save()
+{
+       if (!fUndoHistory.IsEmpty())
+               fEditAtSave = fUndoHistory.Top();
+
+       _NotifyListeners();
+}
+
+
+bool
+EditManager::IsSaved()
+{
+       bool saved = fUndoHistory.IsEmpty();
+       if (fEditAtSave.Get() != NULL && !saved) {
+               if (fEditAtSave == fUndoHistory.Top())
+                       saved = true;
+       }
+       return saved;
+}
+
+
+// #pragma mark -
+
+
+bool
+EditManager::AddListener(Listener* listener)
+{
+       return fListeners.Add(listener);
+}
+
+
+void
+EditManager::RemoveListener(Listener* listener)
+{
+       fListeners.Remove(listener);
+}
+
+
+// #pragma mark -
+
+
+status_t
+EditManager::_AddEdit(const UndoableEditRef& edit)
+{
+       status_t status = B_OK;
+
+       bool add = true;
+       if (!fUndoHistory.IsEmpty()) {
+               // Try to collapse edits to a single edit
+               // or remove this and the previous edit if
+               // they reverse each other
+               const UndoableEditRef& top = fUndoHistory.Top();
+               if (edit->UndoesPrevious(top.Get())) {
+                       add = false;
+                       fUndoHistory.Pop();
+               } else if (top->CombineWithNext(edit.Get())) {
+                       add = false;
+                       // After collapsing, the edit might
+                       // have changed it's mind about InitCheck()
+                       // (the commands reversed each other)
+                       if (top->InitCheck() != B_OK) {
+                               fUndoHistory.Pop();
+                       }
+               } else if (edit->CombineWithPrevious(top.Get())) {
+                       fUndoHistory.Pop();
+                       // After collapsing, the edit might
+                       // have changed it's mind about InitCheck()
+                       // (the commands reversed each other)
+                       if (edit->InitCheck() != B_OK) {
+                               add = false;
+                       }
+               }
+       }
+       if (add) {
+               if (!fUndoHistory.Push(edit))
+                       status = B_NO_MEMORY;
+       }
+
+       if (status == B_OK) {
+               // The redo stack needs to be empty
+               // as soon as an edit was added (also in case of collapsing)
+               while (!fRedoHistory.IsEmpty()) {
+                       fRedoHistory.Pop();
+               }
+       }
+
+       return status;
+}
+
+
+void
+EditManager::_NotifyListeners()
+{
+       int32 count = fListeners.CountItems();
+       if (count == 0)
+               return;
+       // Iterate a copy of the list, so we don't crash if listeners
+       // detach themselves while being notified.
+       ListenerList listenersCopy(fListeners);
+       if (listenersCopy.CountItems() != count)
+               return;
+       for (int32 i = 0; i < count; i++)
+               listenersCopy.ItemAtFast(i)->EditManagerChanged(this);
+}
+
diff --git a/src/apps/haikudepot/edits_generic/EditManager.h 
b/src/apps/haikudepot/edits_generic/EditManager.h
new file mode 100644
index 0000000..31dcb95
--- /dev/null
+++ b/src/apps/haikudepot/edits_generic/EditManager.h
@@ -0,0 +1,60 @@
+/*
+ * Copyright 2006-2012, Stephan Aßmus <superstippi@xxxxxx>
+ * Distributed under the terms of the MIT License.
+ */
+#ifndef EDIT_MANAGER_H
+#define EDIT_MANAGER_H
+
+#include "EditStack.h"
+#include "UndoableEdit.h"
+
+class BString;
+class EditContext;
+
+
+class EditManager {
+public:
+       class Listener {
+       public:
+               virtual                                 ~Listener();
+               virtual void                    EditManagerChanged(
+                                                                       const 
EditManager* manager) = 0;
+       };
+
+public:
+                                                               EditManager();
+       virtual                                         ~EditManager();
+
+                       status_t                        Perform(UndoableEdit* 
edit,
+                                                                       
EditContext& context);
+                       status_t                        Perform(const 
UndoableEditRef& edit,
+                                                                       
EditContext& context);
+
+                       status_t                        Undo(EditContext& 
context);
+                       status_t                        Redo(EditContext& 
context);
+
+                       bool                            GetUndoName(BString& 
name);
+                       bool                            GetRedoName(BString& 
name);
+
+                       void                            Clear();
+                       void                            Save();
+                       bool                            IsSaved();
+
+                       bool                            AddListener(Listener* 
listener);
+                       void                            
RemoveListener(Listener* listener);
+
+private:
+                       status_t                        _AddEdit(const 
UndoableEditRef& edit);
+
+                       void                            _NotifyListeners();
+
+private:
+                       EditStack                       fUndoHistory;
+                       EditStack                       fRedoHistory;
+                       UndoableEditRef         fEditAtSave;
+
+       typedef List<Listener*, true, 4> ListenerList;
+                       ListenerList            fListeners;
+};
+
+#endif // EDIT_MANAGER_H
diff --git a/src/apps/haikudepot/edits_generic/EditStack.cpp 
b/src/apps/haikudepot/edits_generic/EditStack.cpp
new file mode 100644
index 0000000..9c903d6
--- /dev/null
+++ b/src/apps/haikudepot/edits_generic/EditStack.cpp
@@ -0,0 +1,49 @@
+/*
+ * Copyright 2012, Stephan Aßmus <superstippi@xxxxxx>
+ * Distributed under the terms of the MIT License.
+ */
+
+#include "EditStack.h"
+
+#include <stdio.h>
+
+
+EditStack::EditStack()
+       : fEdits()
+{
+}
+
+
+EditStack::~EditStack()
+{
+}
+
+
+bool
+EditStack::Push(const UndoableEditRef& edit)
+{
+       return fEdits.Add(edit);
+}
+
+
+UndoableEditRef
+EditStack::Pop()
+{
+       UndoableEditRef edit(Top());
+       fEdits.Remove();
+       return edit;
+}
+
+
+const UndoableEditRef&
+EditStack::Top() const
+{
+       return fEdits.LastItem();
+}
+
+
+bool
+EditStack::IsEmpty() const
+{
+       return fEdits.CountItems() == 0;
+}
diff --git a/src/apps/haikudepot/edits_generic/EditStack.h 
b/src/apps/haikudepot/edits_generic/EditStack.h
new file mode 100644
index 0000000..051ca9a
--- /dev/null
+++ b/src/apps/haikudepot/edits_generic/EditStack.h
@@ -0,0 +1,30 @@
+/*
+ * Copyright 2012, Stephan Aßmus <superstippi@xxxxxx>
+ * Distributed under the terms of the MIT License.
+ */
+
+#ifndef EDIT_STACK_H
+#define EDIT_STACK_H
+
+#include "List.h"
+#include "UndoableEdit.h"
+
+class EditStack {
+public:
+                                                               EditStack();
+       virtual                                         ~EditStack();
+
+                       bool                            Push(const 
UndoableEditRef& edit);
+                       UndoableEditRef         Pop();
+
+                       const UndoableEditRef&  Top() const;
+
+                       bool                            IsEmpty() const;
+
+private:
+                       typedef List<UndoableEditRef, false>    EditList;
+
+                       EditList                        fEdits;
+};
+
+#endif // EDIT_STACK_H
diff --git a/src/apps/haikudepot/edits_generic/UndoableEdit.cpp 
b/src/apps/haikudepot/edits_generic/UndoableEdit.cpp
new file mode 100644
index 0000000..fc1e2af
--- /dev/null
+++ b/src/apps/haikudepot/edits_generic/UndoableEdit.cpp
@@ -0,0 +1,86 @@
+/*
+ * Copyright 2006-2012, Stephan Aßmus <superstippi@xxxxxx>
+ * Distributed under the terms of the MIT License.
+ */
+
+#include "UndoableEdit.h"
+
+#include <stdio.h>
+
+#include <OS.h>
+#include <String.h>
+
+
+//static int32 sInstanceCount = 0;
+
+
+UndoableEdit::UndoableEdit()
+       :
+       fTimeStamp(system_time())
+{
+//     sInstanceCount++;
+//     printf("UndoableEdits: %ld\n", sInstanceCount);
+}
+
+
+UndoableEdit::~UndoableEdit()
+{
+//     sInstanceCount--;
+//     printf("UndoableEdits: %ld\n", sInstanceCount);
+}
+
+
+status_t
+UndoableEdit::InitCheck()
+{
+       return B_NO_INIT;
+}
+
+
+status_t
+UndoableEdit::Perform(EditContext& context)
+{
+       return B_ERROR;
+}
+
+
+status_t
+UndoableEdit::Undo(EditContext& context)
+{
+       return B_ERROR;
+}
+
+
+status_t
+UndoableEdit::Redo(EditContext& context)
+{
+       return Perform(context);
+}
+
+
+void
+UndoableEdit::GetName(BString& name)
+{
+       name << "Name of edit goes here.";
+}
+
+
+bool
+UndoableEdit::UndoesPrevious(const UndoableEdit* previous)
+{
+       return false;
+}
+
+
+bool
+UndoableEdit::CombineWithNext(const UndoableEdit* next)
+{
+       return false;
+}
+
+
+bool
+UndoableEdit::CombineWithPrevious(const UndoableEdit* previous)
+{
+       return false;
+}
diff --git a/src/apps/haikudepot/edits_generic/UndoableEdit.h 
b/src/apps/haikudepot/edits_generic/UndoableEdit.h
new file mode 100644
index 0000000..d6c8ad3
--- /dev/null
+++ b/src/apps/haikudepot/edits_generic/UndoableEdit.h
@@ -0,0 +1,41 @@
+/*
+ * Copyright 2006-2012 Stephan Aßmus <superstippi@xxxxxx>
+ * Distributed under the terms of the MIT License.
+ */
+
+#ifndef UNDOABLE_EDIT_H
+#define UNDOABLE_EDIT_H
+
+#include <Referenceable.h>
+
+class BString;
+class EditContext;
+
+class UndoableEdit : public BReferenceable {
+public:
+                                                               UndoableEdit();
+       virtual                                         ~UndoableEdit();
+
+       virtual status_t                        InitCheck();
+
+       virtual status_t                        Perform(EditContext& context);
+       virtual status_t                        Undo(EditContext& context);
+       virtual status_t                        Redo(EditContext& context);
+
+       virtual void                            GetName(BString& name);
+
+       virtual bool                            UndoesPrevious(const 
UndoableEdit* previous);
+       virtual bool                            CombineWithNext(const 
UndoableEdit* next);
+       virtual bool                            CombineWithPrevious(
+                                                                       const 
UndoableEdit* previous);
+
+       inline  bigtime_t                       TimeStamp() const
+                                                                       { 
return fTimeStamp; }
+
+protected:
+                       bigtime_t                       fTimeStamp;
+};
+
+typedef BReference<UndoableEdit> UndoableEditRef;
+
+#endif // UNDOABLE_EDIT_H

############################################################################

Commit:      b5cbbf80412827b0e968f8929c00d02c6965463e
URL:         http://cgit.haiku-os.org/haiku/commit/?id=b5cbbf804128
Author:      Stephan Aßmus <superstippi@xxxxxx>
Date:        Sun Feb 22 20:25:11 2015 UTC

HaikuDepot: UndoableEditListener base class added

----------------------------------------------------------------------------

diff --git a/src/apps/haikudepot/Jamfile b/src/apps/haikudepot/Jamfile
index 0a38be2..315e8d1 100644
--- a/src/apps/haikudepot/Jamfile
+++ b/src/apps/haikudepot/Jamfile
@@ -39,6 +39,7 @@ local textDocumentSources =
        TextSelection.cpp
        TextSpan.cpp
        TextView.cpp
+       UndoableEditListener.cpp
 ;
 
 Application HaikuDepot :
diff --git a/src/apps/haikudepot/textview/UndoableEditListener.cpp 
b/src/apps/haikudepot/textview/UndoableEditListener.cpp
new file mode 100644
index 0000000..eb0868d
--- /dev/null
+++ b/src/apps/haikudepot/textview/UndoableEditListener.cpp
@@ -0,0 +1,25 @@
+/*
+ * Copyright 2015, Stephan Aßmus <superstippi@xxxxxx>.
+ * All rights reserved. Distributed under the terms of the MIT License.
+ */
+
+#include "UndoableEditListener.h"
+
+
+UndoableEditListener::UndoableEditListener()
+       :
+       BReferenceable()
+{
+}
+
+
+UndoableEditListener::~UndoableEditListener()
+{
+}
+
+
+void
+UndoableEditListener::UndoableEditHappened(const TextDocument* document,
+       const UndoableEditRef& edit)
+{
+}
diff --git a/src/apps/haikudepot/textview/UndoableEditListener.h 
b/src/apps/haikudepot/textview/UndoableEditListener.h
new file mode 100644
index 0000000..45369c8
--- /dev/null
+++ b/src/apps/haikudepot/textview/UndoableEditListener.h
@@ -0,0 +1,29 @@
+/*
+ * Copyright 2015, Stephan Aßmus <superstippi@xxxxxx>.
+ * All rights reserved. Distributed under the terms of the MIT License.
+ */
+#ifndef UNDOABLE_EDIT_LISTENER_H
+#define UNDOABLE_EDIT_LISTENER_H
+
+
+#include <Referenceable.h>
+
+class TextDocument;
+class UndoableEditRef;
+
+
+class UndoableEditListener : public BReferenceable {
+public:
+                                                               
UndoableEditListener();
+       virtual                                         ~UndoableEditListener();
+
+       virtual void                            UndoableEditHappened(
+                                                                       const 
TextDocument* document,
+                                                                       const 
UndoableEditRef& edit);
+};
+
+
+typedef BReference<UndoableEditListener> UndoableEditListenerRef;
+
+
+#endif // UNDOABLE_EDIT_LISTENER_H

############################################################################

Revision:    hrev48826
Commit:      4bf45bfb5d2366ab2e4b7d1cdd427729ed449c73
URL:         http://cgit.haiku-os.org/haiku/commit/?id=4bf45bfb5d23
Author:      Stephan Aßmus <superstippi@xxxxxx>
Date:        Sun Feb 22 20:25:49 2015 UTC

HaikuDepot: Added UndoableEditListener list to TextDocument

This is all work in progress. The plan is to move the code that does any
actual changes to the TextDocument into UndoableEdit implementations, then
emit these edits to interesed listeners. They can then store them to
implement the edit history. If there are not listeners, the edits will
simply be released after they've done their work.
Implemented so far is only the support for storing the edit listeners.

----------------------------------------------------------------------------

diff --git a/src/apps/haikudepot/textview/TextDocument.cpp 
b/src/apps/haikudepot/textview/TextDocument.cpp
index 42e113a..e222d99 100644
--- a/src/apps/haikudepot/textview/TextDocument.cpp
+++ b/src/apps/haikudepot/textview/TextDocument.cpp
@@ -516,6 +516,20 @@ TextDocument::RemoveListener(const TextListenerRef& 
listener)
 }
 
 
+bool
+TextDocument::AddUndoListener(const UndoableEditListenerRef& listener)
+{
+       return fUndoListeners.Add(listener);
+}
+
+
+bool
+TextDocument::RemoveUndoListener(const UndoableEditListenerRef& listener)
+{
+       return fUndoListeners.Remove(listener);
+}
+
+
 void
 TextDocument::_NotifyTextChanging(TextChangingEvent& event) const
 {
@@ -549,3 +563,18 @@ TextDocument::_NotifyTextChanged(const TextChangedEvent& 
event) const
        }
 }
 
+
+void
+TextDocument::_NotifyUndoableEditHappened(const UndoableEditRef& edit) const
+{
+       // Copy listener list to have a stable list in case listeners
+       // are added/removed from within the notification hook.
+       UndoListenerList listeners(fUndoListeners);
+       int32 count = listeners.CountItems();
+       for (int32 i = 0; i < count; i++) {
+               const UndoableEditListenerRef& listener = 
listeners.ItemAtFast(i);
+               if (listener.Get() == NULL)
+                       continue;
+               listener->UndoableEditHappened(this, edit);
+       }
+}
diff --git a/src/apps/haikudepot/textview/TextDocument.h 
b/src/apps/haikudepot/textview/TextDocument.h
index d2a4d55..e86d295 100644
--- a/src/apps/haikudepot/textview/TextDocument.h
+++ b/src/apps/haikudepot/textview/TextDocument.h
@@ -11,10 +11,12 @@
 #include "List.h"
 #include "Paragraph.h"
 #include "TextListener.h"
+#include "UndoableEditListener.h"
 
 
-typedef List<Paragraph, false>                 ParagraphList;
-typedef List<TextListenerRef, false>   TextListenerList;
+typedef List<Paragraph, false>                                 ParagraphList;
+typedef List<TextListenerRef, false>                   TextListenerList;
+typedef List<UndoableEditListenerRef, false>   UndoListenerList;
 
 class TextDocument;
 typedef BReference<TextDocument> TextDocumentRef;
@@ -83,12 +85,18 @@ public:
                        // Listener support
                        bool                            AddListener(const 
TextListenerRef& listener);
                        bool                            RemoveListener(const 
TextListenerRef& listener);
+                       bool                            AddUndoListener(
+                                                                       const 
UndoableEditListenerRef& listener);
+                       bool                            RemoveUndoListener(
+                                                                       const 
UndoableEditListenerRef& listener);
 
 private:
                        void                            _NotifyTextChanging(
                                                                        
TextChangingEvent& event) const;
                        void                            _NotifyTextChanged(
                                                                        const 
TextChangedEvent& event) const;
+                       void                            
_NotifyUndoableEditHappened(
+                                                                       const 
UndoableEditRef& edit) const;
 
 private:
                        ParagraphList           fParagraphs;
@@ -96,6 +104,7 @@ private:
                        CharacterStyle          fDefaultCharacterStyle;
 
                        TextListenerList        fTextListeners;
+                       UndoListenerList        fUndoListeners;
 };
 
 


Other related posts:

  • » [haiku-commits] haiku: hrev48826 - in src/apps/haikudepot: edits_generic textview - superstippi