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:
@@ -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. */
|
||||
};
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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. */
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -16,6 +16,8 @@
|
||||
* Reserved.
|
||||
*/
|
||||
|
||||
#include "nsITransaction.h"
|
||||
#include "nsTransactionItem.h"
|
||||
#include "nsTransactionStack.h"
|
||||
#include "nsCOMPtr.h"
|
||||
|
||||
|
||||
@@ -19,7 +19,6 @@
|
||||
#ifndef nsTransactionStack_h__
|
||||
#define nsTransactionStack_h__
|
||||
|
||||
#include "nsTransactionItem.h"
|
||||
#include "nsDeque.h"
|
||||
|
||||
class nsTransactionItem;
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user