Added support for nsITransactionListener.

Cleaned up includes in header files.


git-svn-id: svn://10.0.0.236/trunk@32713 18797224-902f-48f8-a5cc-f745e15eee43
This commit is contained in:
kin%netscape.com
1999-05-26 21:16:25 +00:00
parent 7b98a8d777
commit cf9cdb1bd0
9 changed files with 744 additions and 116 deletions

View File

@@ -20,9 +20,8 @@
#define nsITransactionListener_h__
#include "nsISupports.h"
#include "nsITransaction.h"
#include "nsITransactionManager.h"
class nsITransaction;
class nsITransactionManager;
/*
@@ -45,37 +44,154 @@ public:
static const nsIID& GetIID() { static nsIID iid = NS_ITRANSACTIONLISTENER_IID; return iid; }
/**
* Called when a transaction manager is doing a transaction.
* @param aContinue if true, transaction manager continues normal processing.
* if false, transaction manager discontinues processing.
* Called before a transaction manager calls a transaction's
* Do() method.
* @param aManager the transaction manager doing the transaction.
* @param aTransaction the transaction being done.
* @result error status returned by the listener. NS_OK
* should be used to indicate no error, proceed with normal control
* flow. NS_COMFALSE can be returned by the listener to
* indicate no error, interrupt normal control flow.
*/
virtual nsresult Do(PRBool *aContinue,
nsITransactionManager *aManager,
NS_IMETHOD WillDo(nsITransactionManager *aManager,
nsITransaction *aTransaction) = 0;
/**
* Called after a transaction manager calls the Do() method of
* a transaction.
* @param aManager the transaction manager that did the transaction.
* @param aTransaction the transaction that was done.
* @param aDoResult the nsresult returned after doing the transaction.
* @result error status returned by the listener.
*/
NS_IMETHOD DidDo(nsITransactionManager *aManager,
nsITransaction *aTransaction,
nsresult aDoResult) = 0;
/**
* Called before a transaction manager calls the Undo() method of
* a transaction.
* @param aManager the transaction manager undoing the transaction.
* @param aTransaction the transaction being undone.
* @result error status returned by the listener. NS_OK
* should be used to indicate no error, proceed with normal control
* flow. NS_COMFALSE can be returned by the listener to
* indicate no error, interrupt normal control flow.
*/
NS_IMETHOD WillUndo(nsITransactionManager *aManager,
nsITransaction *aTransaction) = 0;
/**
* Called when a transaction manager is undoing a transaction.
* @param aContinue if true, transaction manager continues normal processing.
* if false, transaction manager discontinues processing.
* Called after a transaction manager calls the Undo() method of
* a transaction.
* @param aManager the transaction manager undoing the transaction.
* @param aTransaction the transaction being undone.
* @param aUndoResult the nsresult returned after undoing the transaction.
* @result error status returned by the listener.
*/
virtual nsresult Undo(PRBool *aContinue,
nsITransactionManager *aManager,
nsITransaction *aTransaction) = 0;
NS_IMETHOD DidUndo(nsITransactionManager *aManager,
nsITransaction *aTransaction,
nsresult aUndoResult) = 0;
/**
* Called when a transaction manager is redoing a transaction.
* @param aContinue if true, transaction manager continues normal processing.
* if false, transaction manager discontinues processing.
* Called before a transaction manager calls the Redo() method of
* a transaction.
* @param aManager the transaction manager redoing the transaction.
* @param aTransaction the transaction being redone.
* @result error status returned by the listener. NS_OK
* should be used to indicate no error, proceed with normal control
* flow. NS_COMFALSE can be returned by the listener to
* indicate no error, interrupt normal control flow.
*/
virtual nsresult Redo(PRBool *aContinue,
nsITransactionManager *aManager,
nsITransaction *aTransaction) = 0;
NS_IMETHOD WillRedo(nsITransactionManager *aManager,
nsITransaction *aTransaction) = 0;
/**
* Called after a transaction manager calls the Redo() method of
* a transaction.
* @param aManager the transaction manager redoing the transaction.
* @param aTransaction the transaction being redone.
* @param aRedoResult the nsresult returned after redoing the transaction.
* @result error status returned by the listener.
*/
NS_IMETHOD DidRedo(nsITransactionManager *aManager,
nsITransaction *aTransaction,
nsresult aRedoResult) = 0;
/**
* Called before a transaction manager begins a batch.
* @param aManager the transaction manager beginning a batch.
* @result error status returned by the listener. NS_OK
* should be used to indicate no error, proceed with normal control
* flow. NS_COMFALSE can be returned by the listener to
* indicate no error, interrupt normal control flow.
*/
NS_IMETHOD WillBeginBatch(nsITransactionManager *aManager) = 0;
/**
* Called after a transaction manager begins a batch.
* @param aManager the transaction manager that began a batch.
* @param aResult the nsresult returned after beginning a batch.
* @result error status returned by the listener.
*/
NS_IMETHOD DidBeginBatch(nsITransactionManager *aManager,
nsresult aResult) = 0;
/**
* Called before a transaction manager ends a batch.
* @param aManager the transaction manager ending a batch.
* @result error status returned by the listener. NS_OK
* should be used to indicate no error, proceed with normal control
* flow. NS_COMFALSE can be returned by the listener to
* indicate no error, interrupt normal control flow.
*/
NS_IMETHOD WillEndBatch(nsITransactionManager *aManager) = 0;
/**
* Called after a transaction manager ends a batch.
* @param aManager the transaction manager ending a batch.
* @param aResult the nsresult returned after ending a batch.
* @result error status returned by the listener.
*/
NS_IMETHOD DidEndBatch(nsITransactionManager *aManager,
nsresult aResult) = 0;
/**
* Called before a transaction manager tries to merge
* a transaction, that was just executed, with the
* transaction at the top of the undo stack.
* @param aManager the transaction manager ending a batch.
* @param aTopTransaction the transaction at the top of the undo stack.
* @param aTransactionToMerge the transaction to merge.
* @result error status returned by the listener. NS_OK
* should be used to indicate no error, proceed with normal control
* flow. NS_COMFALSE can be returned by the listener to
* indicate no error, interrupt normal control flow.
*/
NS_IMETHOD WillMerge(nsITransactionManager *aManager,
nsITransaction *aTopTransaction,
nsITransaction *aTransactionToMerge) = 0;
/**
* Called after a transaction manager tries to merge
* a transaction, that was just executed, with the
* transaction at the top of the undo stack.
* @param aManager the transaction manager ending a batch.
* @param aTopTransaction the transaction at the top of the undo stack.
* @param aTransactionToMerge the transaction to merge.
* @param aDidMerge true if transaction was merged, else false.
* @param aMergeResult the nsresult returned after the merge attempt.
* @result error status returned by the listener. NS_OK
* should be used to indicate no error, proceed with normal control
* flow. NS_COMFALSE can be returned by the listener to
* indicate no error, interrupt normal control flow.
*/
NS_IMETHOD DidMerge(nsITransactionManager *aManager,
nsITransaction *aTopTransaction,
nsITransaction *aTransactionToMerge,
PRBool aDidMerge,
nsresult aMergeResult) = 0;
/* XXX: We should probably add pruning notification methods. */
};

View File

@@ -16,13 +16,13 @@
* Reserved.
*/
#include "nsITransaction.h"
#include "nsITransactionManager.h"
#include "nsTransactionStack.h"
#include "nsTransactionManager.h"
#include "nsTransactionItem.h"
#include "nsCOMPtr.h"
#ifdef NS_DEBUG
//#define NOISY
#endif
nsTransactionItem::nsTransactionItem(nsITransaction *aTransaction)
: mTransaction(aTransaction), mUndoStack(0), mRedoStack(0)
{
@@ -104,28 +104,22 @@ nsTransactionItem::Do()
}
nsresult
nsTransactionItem::Undo()
nsTransactionItem::Undo(nsTransactionManager *aTxMgr)
{
nsresult result = UndoChildren();
nsresult result = UndoChildren(aTxMgr);
if (NS_FAILED(result)) {
RecoverFromUndoError();
RecoverFromUndoError(aTxMgr);
return result;
}
if (!mTransaction)
return NS_OK;
#ifdef NOISY
nsAutoString redoString;
mTransaction->GetRedoString(&redoString);
printf("undoing %s\n", redoString);
#endif
result = mTransaction->Undo();
if (NS_FAILED(result)) {
RecoverFromUndoError();
RecoverFromUndoError(aTxMgr);
return result;
}
@@ -133,10 +127,10 @@ nsTransactionItem::Undo()
}
nsresult
nsTransactionItem::UndoChildren()
nsTransactionItem::UndoChildren(nsTransactionManager *aTxMgr)
{
nsTransactionItem *item;
nsresult result;
nsresult result = NS_OK;
PRInt32 sz = 0;
if (mUndoStack) {
@@ -159,61 +153,65 @@ nsTransactionItem::UndoChildren()
return result;
}
#ifdef NOISY
nsAutoString redoString;
item->GetRedoString(&redoString);
printf("undoing %s\n", redoString);
#endif
nsITransaction *t = 0;
result = item->Undo();
result = item->GetTransaction(&t);
if (NS_FAILED(result)) {
return result;
}
result = mUndoStack->Pop(&item);
result = aTxMgr->WillUndoNotify(t);
if (NS_FAILED(result)) {
return result;
}
result = mRedoStack->Push(item);
if (result == NS_COMFALSE) {
return NS_OK;
}
if (NS_FAILED(result)) {
/* XXX: If we got an error here, I doubt we can recover!
* XXX: Should we just push the item back on the undo stack?
*/
return result;
result = item->Undo(aTxMgr);
if (NS_SUCCEEDED(result)) {
result = mUndoStack->Pop(&item);
if (NS_SUCCEEDED(result)) {
result = mRedoStack->Push(item);
/* XXX: If we got an error here, I doubt we can recover!
* XXX: Should we just push the item back on the undo stack?
*/
}
}
nsresult result2 = aTxMgr->DidUndoNotify(t, result);
if (NS_SUCCEEDED(result)) {
result = result2;
}
}
}
return NS_OK;
return result;
}
nsresult
nsTransactionItem::Redo()
nsTransactionItem::Redo(nsTransactionManager *aTxMgr)
{
nsresult result;
if (mTransaction) {
#ifdef NOISY
nsAutoString undoString;
mTransaction->GetUndoString(&undoString);
printf("redoing %s\n", undoString);
#endif
result = mTransaction->Redo();
if (NS_FAILED(result))
return result;
}
result = RedoChildren();
result = RedoChildren(aTxMgr);
if (NS_FAILED(result)) {
RecoverFromRedoError();
RecoverFromRedoError(aTxMgr);
return result;
}
@@ -221,10 +219,10 @@ nsTransactionItem::Redo()
}
nsresult
nsTransactionItem::RedoChildren()
nsTransactionItem::RedoChildren(nsTransactionManager *aTxMgr)
{
nsTransactionItem *item;
nsresult result;
nsresult result = NS_OK;
PRInt32 sz = 0;
if (!mRedoStack)
@@ -244,34 +242,45 @@ nsTransactionItem::RedoChildren()
return result;
}
#ifdef NOISY
nsAutoString undoString;
item->GetUndoString(&undoString);
printf("redoing %s\n", undoString);
#endif
nsITransaction *t = 0;
result = item->Redo();
result = item->GetTransaction(&t);
if (NS_FAILED(result)) {
return result;
}
result = mRedoStack->Pop(&item);
result = aTxMgr->WillRedoNotify(t);
if (NS_FAILED(result)) {
return result;
}
result = mUndoStack->Push(item);
if (result == NS_COMFALSE) {
return NS_OK;
}
if (NS_FAILED(result)) {
// XXX: If we got an error here, I doubt we can recover!
// XXX: Should we just push the item back on the redo stack?
return result;
result = item->Redo(aTxMgr);
if (NS_SUCCEEDED(result)) {
result = mRedoStack->Pop(&item);
if (NS_SUCCEEDED(result)) {
result = mUndoStack->Push(item);
// XXX: If we got an error here, I doubt we can recover!
// XXX: Should we just push the item back on the redo stack?
}
}
nsresult result2 = aTxMgr->DidUndoNotify(t, result);
if (NS_SUCCEEDED(result)) {
result = result2;
}
}
return NS_OK;
return result;
}
nsresult
@@ -325,18 +334,18 @@ nsTransactionItem::Write(nsIOutputStream *aOutputStream)
}
nsresult
nsTransactionItem::RecoverFromUndoError(void)
nsTransactionItem::RecoverFromUndoError(nsTransactionManager *aTxMgr)
{
//
// If this method gets called, we never got to the point where we
// successfully called Undo() for the transaction item itself.
// Just redo any children that successfully called undo!
//
return RedoChildren();
return RedoChildren(aTxMgr);
}
nsresult
nsTransactionItem::RecoverFromRedoError(void)
nsTransactionItem::RecoverFromRedoError(nsTransactionManager *aTxMgr)
{
//
// If this method gets called, we already successfully called Redo()
@@ -346,7 +355,7 @@ nsTransactionItem::RecoverFromRedoError(void)
nsresult result;
result = UndoChildren();
result = UndoChildren(aTxMgr);
if (NS_FAILED(result)) {
return result;

View File

@@ -19,11 +19,10 @@
#ifndef nsTransactionItem_h__
#define nsTransactionItem_h__
#include "nsITransaction.h"
#include "nsTransactionStack.h"
class nsITransaction;
class nsTransactionStack;
class nsTransactionRedoStack;
class nsTransactionManager;
class nsTransactionItem
{
@@ -41,17 +40,17 @@ public:
virtual nsresult GetNumberOfChildren(PRInt32 *aNumChildren);
virtual nsresult Do(void);
virtual nsresult Undo(void);
virtual nsresult Redo(void);
virtual nsresult Undo(nsTransactionManager *aTxMgr);
virtual nsresult Redo(nsTransactionManager *aTxMgr);
virtual nsresult Write(nsIOutputStream *aOutputStream);
private:
virtual nsresult UndoChildren();
virtual nsresult RedoChildren();
virtual nsresult UndoChildren(nsTransactionManager *aTxMgr);
virtual nsresult RedoChildren(nsTransactionManager *aTxMgr);
virtual nsresult RecoverFromUndoError();
virtual nsresult RecoverFromRedoError();
virtual nsresult RecoverFromUndoError(nsTransactionManager *aTxMgr);
virtual nsresult RecoverFromRedoError(nsTransactionManager *aTxMgr);
virtual nsresult GetNumberOfUndoItems(PRInt32 *aNumItems);
virtual nsresult GetNumberOfRedoItems(PRInt32 *aNumItems);

View File

@@ -16,7 +16,15 @@
* Reserved.
*/
#include "nsITransaction.h"
#include "nsITransactionManager.h"
#include "nsITransactionListener.h"
#include "nsTransactionItem.h"
#include "nsTransactionStack.h"
#include "nsVoidArray.h"
#include "nsTransactionManager.h"
#include "nsCOMPtr.h"
#define LOCK_TX_MANAGER(mgr)
@@ -25,20 +33,28 @@
static NS_DEFINE_IID(kISupportsIID, NS_ISUPPORTS_IID);
static NS_DEFINE_IID(kITransactionManagerIID, NS_ITRANSACTIONMANAGER_IID);
#ifdef NS_DEBUG
static PRBool gNoisy = PR_FALSE;
#else
static const PRBool gNoisy = PR_FALSE;
#endif
nsTransactionManager::nsTransactionManager(PRInt32 aMaxTransactionCount)
: mMaxTransactionCount(aMaxTransactionCount)
: mMaxTransactionCount(aMaxTransactionCount), mListeners(0)
{
mRefCnt = 0;
}
nsTransactionManager::~nsTransactionManager()
{
if (mListeners)
{
PRInt32 i;
nsITransactionListener *listener;
for (i = 0; i < mListeners->Count(); i++)
{
listener = (nsITransactionListener *)mListeners->ElementAt(i);
NS_IF_RELEASE(listener);
}
delete mListeners;
mListeners = 0;
}
}
#ifdef DEBUG_TXMGR_REFCNT
@@ -95,15 +111,33 @@ nsTransactionManager::Do(nsITransaction *aTransaction)
LOCK_TX_MANAGER(this);
result = BeginTransaction(aTransaction);
result = WillDoNotify(aTransaction);
if (NS_FAILED(result)) {
UNLOCK_TX_MANAGER(this);
return result;
}
if (result == NS_COMFALSE) {
UNLOCK_TX_MANAGER(this);
return NS_OK;
}
result = BeginTransaction(aTransaction);
if (NS_FAILED(result)) {
DidDoNotify(aTransaction, result);
UNLOCK_TX_MANAGER(this);
return result;
}
result = EndTransaction();
nsresult result2 = DidDoNotify(aTransaction, result);
if (NS_SUCCEEDED(result))
result = result2;
UNLOCK_TX_MANAGER(this);
return result;
@@ -148,13 +182,41 @@ nsTransactionManager::Undo()
return NS_OK;
}
result = tx->Undo();
nsITransaction *t = 0;
result = tx->GetTransaction(&t);
if (NS_FAILED(result)) {
UNLOCK_TX_MANAGER(this);
return result;
}
result = WillUndoNotify(t);
if (NS_FAILED(result)) {
UNLOCK_TX_MANAGER(this);
return result;
}
if (result == NS_COMFALSE) {
UNLOCK_TX_MANAGER(this);
return NS_OK;
}
result = tx->Undo(this);
if (NS_SUCCEEDED(result)) {
result = mUndoStack.Pop(&tx);
result = mRedoStack.Push(tx);
if (NS_SUCCEEDED(result))
result = mRedoStack.Push(tx);
}
nsresult result2 = DidUndoNotify(t, result);
if (NS_SUCCEEDED(result))
result = result2;
UNLOCK_TX_MANAGER(this);
return result;
@@ -199,13 +261,41 @@ nsTransactionManager::Redo()
return NS_OK;
}
result = tx->Redo();
nsITransaction *t = 0;
result = tx->GetTransaction(&t);
if (NS_FAILED(result)) {
UNLOCK_TX_MANAGER(this);
return result;
}
result = WillRedoNotify(t);
if (NS_FAILED(result)) {
UNLOCK_TX_MANAGER(this);
return result;
}
if (result == NS_COMFALSE) {
UNLOCK_TX_MANAGER(this);
return NS_OK;
}
result = tx->Redo(this);
if (NS_SUCCEEDED(result)) {
result = mRedoStack.Pop(&tx);
result = mUndoStack.Push(tx);
if (NS_SUCCEEDED(result))
result = mUndoStack.Push(tx);
}
nsresult result2 = DidRedoNotify(t, result);
if (NS_SUCCEEDED(result))
result = result2;
UNLOCK_TX_MANAGER(this);
return result;
@@ -235,7 +325,6 @@ nsTransactionManager::Clear()
nsresult
nsTransactionManager::BeginBatch()
{
if (gNoisy) { printf("Begin Batch\n"); }
nsresult result;
// We can batch independent transactions together by simply pushing
@@ -245,8 +334,25 @@ nsTransactionManager::BeginBatch()
LOCK_TX_MANAGER(this);
result = WillBeginBatchNotify();
if (NS_FAILED(result)) {
UNLOCK_TX_MANAGER(this);
return result;
}
if (result == NS_COMFALSE) {
UNLOCK_TX_MANAGER(this);
return NS_OK;
}
result = BeginTransaction(0);
nsresult result2 = DidBeginBatchNotify(result);
if (NS_SUCCEEDED(result))
result = result2;
UNLOCK_TX_MANAGER(this);
return result;
@@ -255,7 +361,6 @@ nsTransactionManager::BeginBatch()
nsresult
nsTransactionManager::EndBatch()
{
if (gNoisy) { printf("End Batch\n"); }
nsTransactionItem *tx = 0;
nsITransaction *ti = 0;
nsresult result;
@@ -288,8 +393,25 @@ nsTransactionManager::EndBatch()
return NS_ERROR_FAILURE;
}
result = WillEndBatchNotify();
if (NS_FAILED(result)) {
UNLOCK_TX_MANAGER(this);
return result;
}
if (result == NS_COMFALSE) {
UNLOCK_TX_MANAGER(this);
return NS_OK;
}
result = EndTransaction();
nsresult result2 = DidEndBatchNotify(result);
if (NS_SUCCEEDED(result))
result = result2;
UNLOCK_TX_MANAGER(this);
return result;
@@ -495,15 +617,53 @@ nsTransactionManager::Write(nsIOutputStream *aOutputStream)
nsresult
nsTransactionManager::AddListener(nsITransactionListener *aListener)
{
// XXX: Need to add listener support.
return NS_ERROR_NOT_IMPLEMENTED;
if (!aListener)
return NS_ERROR_NULL_POINTER;
LOCK_TX_MANAGER(this);
if (!mListeners) {
mListeners = new nsVoidArray();
if (!mListeners) {
UNLOCK_TX_MANAGER(this);
return NS_ERROR_OUT_OF_MEMORY;
}
}
if (!mListeners->AppendElement((void *)aListener)) {
UNLOCK_TX_MANAGER(this);
return NS_ERROR_FAILURE;
}
NS_ADDREF(aListener);
UNLOCK_TX_MANAGER(this);
return NS_OK;
}
nsresult
nsTransactionManager::RemoveListener(nsITransactionListener *aListener)
{
// XXX: Need to add listener support.
return NS_ERROR_NOT_IMPLEMENTED;
if (!aListener)
return NS_ERROR_NULL_POINTER;
if (!mListeners)
return NS_ERROR_FAILURE;
if (!mListeners->RemoveElement((void *)aListener))
return NS_ERROR_FAILURE;
NS_IF_RELEASE(aListener);
if (mListeners->Count() < 1)
{
delete mListeners;
mListeners = 0;
}
return NS_OK;
}
nsresult
@@ -530,6 +690,309 @@ nsTransactionManager::ClearRedoStack()
return result;
}
nsresult
nsTransactionManager::WillDoNotify(nsITransaction *aTransaction)
{
if (!mListeners)
return NS_OK;
nsresult result = NS_OK;
PRInt32 i, lcount = mListeners->Count();
for (i = 0; i < lcount; i++)
{
nsITransactionListener *listener = (nsITransactionListener *)mListeners->ElementAt(i);
if (!listener)
return NS_ERROR_FAILURE;
result = listener->WillDo(this, aTransaction);
if (NS_FAILED(result) || result == NS_COMFALSE)
break;
}
return result;
}
nsresult
nsTransactionManager::DidDoNotify(nsITransaction *aTransaction, nsresult aDoResult)
{
if (!mListeners)
return NS_OK;
nsresult result = NS_OK;
PRInt32 i, lcount = mListeners->Count();
for (i = 0; i < lcount; i++)
{
nsITransactionListener *listener = (nsITransactionListener *)mListeners->ElementAt(i);
if (!listener)
return NS_ERROR_FAILURE;
result = listener->DidDo(this, aTransaction, aDoResult);
if (NS_FAILED(result))
break;
}
return result;
}
nsresult
nsTransactionManager::WillUndoNotify(nsITransaction *aTransaction)
{
if (!mListeners)
return NS_OK;
nsresult result = NS_OK;
PRInt32 i, lcount = mListeners->Count();
for (i = 0; i < lcount; i++)
{
nsITransactionListener *listener = (nsITransactionListener *)mListeners->ElementAt(i);
if (!listener)
return NS_ERROR_FAILURE;
result = listener->WillUndo(this, aTransaction);
if (NS_FAILED(result) || result == NS_COMFALSE)
break;
}
return result;
}
nsresult
nsTransactionManager::DidUndoNotify(nsITransaction *aTransaction, nsresult aUndoResult)
{
if (!mListeners)
return NS_OK;
nsresult result = NS_OK;
PRInt32 i, lcount = mListeners->Count();
for (i = 0; i < lcount; i++)
{
nsITransactionListener *listener = (nsITransactionListener *)mListeners->ElementAt(i);
if (!listener)
return NS_ERROR_FAILURE;
result = listener->DidUndo(this, aTransaction, aUndoResult);
if (NS_FAILED(result))
break;
}
return result;
}
nsresult
nsTransactionManager::WillRedoNotify(nsITransaction *aTransaction)
{
if (!mListeners)
return NS_OK;
nsresult result = NS_OK;
PRInt32 i, lcount = mListeners->Count();
for (i = 0; i < lcount; i++)
{
nsITransactionListener *listener = (nsITransactionListener *)mListeners->ElementAt(i);
if (!listener)
return NS_ERROR_FAILURE;
result = listener->WillRedo(this, aTransaction);
if (NS_FAILED(result) || result == NS_COMFALSE)
break;
}
return result;
}
nsresult
nsTransactionManager::DidRedoNotify(nsITransaction *aTransaction, nsresult aRedoResult)
{
if (!mListeners)
return NS_OK;
nsresult result = NS_OK;
PRInt32 i, lcount = mListeners->Count();
for (i = 0; i < lcount; i++)
{
nsITransactionListener *listener = (nsITransactionListener *)mListeners->ElementAt(i);
if (!listener)
return NS_ERROR_FAILURE;
result = listener->DidRedo(this, aTransaction, aRedoResult);
if (NS_FAILED(result))
break;
}
return result;
}
nsresult
nsTransactionManager::WillBeginBatchNotify()
{
if (!mListeners)
return NS_OK;
nsresult result = NS_OK;
PRInt32 i, lcount = mListeners->Count();
for (i = 0; i < lcount; i++)
{
nsITransactionListener *listener = (nsITransactionListener *)mListeners->ElementAt(i);
if (!listener)
return NS_ERROR_FAILURE;
result = listener->WillBeginBatch(this);
if (NS_FAILED(result) || result == NS_COMFALSE)
break;
}
return result;
}
nsresult
nsTransactionManager::DidBeginBatchNotify(nsresult aResult)
{
if (!mListeners)
return NS_OK;
nsresult result = NS_OK;
PRInt32 i, lcount = mListeners->Count();
for (i = 0; i < lcount; i++)
{
nsITransactionListener *listener = (nsITransactionListener *)mListeners->ElementAt(i);
if (!listener)
return NS_ERROR_FAILURE;
result = listener->DidBeginBatch(this, aResult);
if (NS_FAILED(result))
break;
}
return result;
}
nsresult
nsTransactionManager::WillEndBatchNotify()
{
if (!mListeners)
return NS_OK;
nsresult result = NS_OK;
PRInt32 i, lcount = mListeners->Count();
for (i = 0; i < lcount; i++)
{
nsITransactionListener *listener = (nsITransactionListener *)mListeners->ElementAt(i);
if (!listener)
return NS_ERROR_FAILURE;
result = listener->WillEndBatch(this);
if (NS_FAILED(result) || result == NS_COMFALSE)
break;
}
return result;
}
nsresult
nsTransactionManager::DidEndBatchNotify(nsresult aResult)
{
if (!mListeners)
return NS_OK;
nsresult result = NS_OK;
PRInt32 i, lcount = mListeners->Count();
for (i = 0; i < lcount; i++)
{
nsITransactionListener *listener = (nsITransactionListener *)mListeners->ElementAt(i);
if (!listener)
return NS_ERROR_FAILURE;
result = listener->DidEndBatch(this, aResult);
if (NS_FAILED(result))
break;
}
return result;
}
nsresult
nsTransactionManager::WillMergeNotify(nsITransaction *aTop, nsITransaction *aTransaction)
{
if (!mListeners)
return NS_OK;
nsresult result = NS_OK;
PRInt32 i, lcount = mListeners->Count();
for (i = 0; i < lcount; i++)
{
nsITransactionListener *listener = (nsITransactionListener *)mListeners->ElementAt(i);
if (!listener)
return NS_ERROR_FAILURE;
result = listener->WillMerge(this, aTop, aTransaction);
if (NS_FAILED(result) || result == NS_COMFALSE)
break;
}
return result;
}
nsresult
nsTransactionManager::DidMergeNotify(nsITransaction *aTop,
nsITransaction *aTransaction,
PRBool aDidMerge,
nsresult aMergeResult)
{
if (!mListeners)
return NS_OK;
nsresult result = NS_OK;
PRInt32 i, lcount = mListeners->Count();
for (i = 0; i < lcount; i++)
{
nsITransactionListener *listener = (nsITransactionListener *)mListeners->ElementAt(i);
if (!listener)
return NS_ERROR_FAILURE;
result = listener->DidMerge(this, aTop, aTransaction, aDidMerge, aMergeResult);
if (NS_FAILED(result))
break;
}
return result;
}
nsresult
nsTransactionManager::BeginTransaction(nsITransaction *aTransaction)
{
@@ -655,15 +1118,27 @@ nsTransactionManager::EndTransaction()
result = top->GetTransaction(&topTransaction);
if (topTransaction) {
result = topTransaction->Merge(&didMerge, tint);
if (NS_FAILED(result)) {
// XXX: What do we do if this fails?
}
result = WillMergeNotify(topTransaction, tint);
if (didMerge) {
delete tx;
if (NS_FAILED(result))
return result;
if (result != NS_COMFALSE) {
result = topTransaction->Merge(&didMerge, tint);
if (NS_FAILED(result)) {
// XXX: What do we do if this fails?
}
nsresult result2 = DidMergeNotify(topTransaction, tint, didMerge, result);
// XXX: What do we do if this fails?
if (didMerge) {
delete tx;
return result;
}
}
}
}

View File

@@ -19,8 +19,13 @@
#ifndef nsTransactionManager_h__
#define nsTransactionManager_h__
#include "nsITransactionManager.h"
#include "nsTransactionStack.h"
class nsITransaction;
class nsITransactionManager;
class nsITransactionListener;
class nsTransactionItem;
class nsTransactionStack;
class nsTransactionRedoStack;
class nsVoidArray;
/** implementation of a transaction manager object.
*
@@ -33,6 +38,7 @@ private:
nsTransactionStack mDoStack;
nsTransactionStack mUndoStack;
nsTransactionRedoStack mRedoStack;
nsVoidArray *mListeners;
public:
@@ -67,6 +73,23 @@ public:
virtual nsresult ClearUndoStack(void);
virtual nsresult ClearRedoStack(void);
virtual nsresult WillDoNotify(nsITransaction *aTransaction);
virtual nsresult DidDoNotify(nsITransaction *aTransaction, nsresult aDoResult);
virtual nsresult WillUndoNotify(nsITransaction *aTransaction);
virtual nsresult DidUndoNotify(nsITransaction *aTransaction, nsresult aUndoResult);
virtual nsresult WillRedoNotify(nsITransaction *aTransaction);
virtual nsresult DidRedoNotify(nsITransaction *aTransaction, nsresult aRedoResult);
virtual nsresult WillBeginBatchNotify();
virtual nsresult DidBeginBatchNotify(nsresult aResult);
virtual nsresult WillEndBatchNotify();
virtual nsresult DidEndBatchNotify(nsresult aResult);
virtual nsresult WillMergeNotify(nsITransaction *aTop,
nsITransaction *aTransaction);
virtual nsresult DidMergeNotify(nsITransaction *aTop,
nsITransaction *aTransaction,
PRBool aDidMerge,
nsresult aMergeResult);
private:
/* nsTransactionManager specific private methods. */

View File

@@ -23,7 +23,12 @@
#include "nsIServiceManager.h"
#include "nsTransactionManagerCID.h"
#include "nsITransactionManager.h"
#include "nsTransactionItem.h"
#include "nsTransactionStack.h"
#include "nsTransactionManager.h"
#include "nsCOMPtr.h"
static NS_DEFINE_IID(kISupportsIID, NS_ISUPPORTS_IID);

View File

@@ -16,6 +16,8 @@
* Reserved.
*/
#include "nsITransaction.h"
#include "nsTransactionItem.h"
#include "nsTransactionStack.h"
#include "nsCOMPtr.h"

View File

@@ -19,7 +19,6 @@
#ifndef nsTransactionStack_h__
#define nsTransactionStack_h__
#include "nsTransactionItem.h"
#include "nsDeque.h"
class nsTransactionItem;

View File

@@ -1120,7 +1120,7 @@ quick_test(TestTransactionFactory *factory)
result = mgr->AddListener(0);
if (NS_FAILED(result)
&& result != NS_ERROR_NOT_IMPLEMENTED) {
&& result != NS_ERROR_NULL_POINTER) {
printf("ERROR: AddListener() returned unexpected error. (%d)\n", result);
return result;
}
@@ -1138,7 +1138,7 @@ quick_test(TestTransactionFactory *factory)
result = mgr->RemoveListener(0);
if (NS_FAILED(result)
&& result != NS_ERROR_NOT_IMPLEMENTED) {
&& result != NS_ERROR_NULL_POINTER) {
printf("ERROR: RemoveListener() returned unexpected error. (%d)\n", result);
return result;
}