Back to index

lightning-sunbird  0.9+nobinonly
Public Member Functions | Static Public Member Functions | Public Attributes | Protected Attributes | Private Member Functions | Friends
PlaceholderTxn Class Reference

An aggregate transaction that knows how to absorb all subsequent transactions with the same name. More...

#include <PlaceholderTxn.h>

Inheritance diagram for PlaceholderTxn:
Inheritance graph
[legend]
Collaboration diagram for PlaceholderTxn:
Collaboration graph
[legend]

List of all members.

Public Member Functions

virtual ~PlaceholderTxn ()
NS_IMETHOD DoTransaction (void)
NS_IMETHOD UndoTransaction (void)
NS_IMETHOD RedoTransaction (void)
NS_IMETHOD Merge (nsITransaction *aTransaction, PRBool *aDidMerge)
NS_IMETHOD GetTxnDescription (nsAString &aTxnDescription)
NS_IMETHOD Init (nsIAtom *aName, nsSelectionState *aSelState, nsIEditor *aEditor)
NS_IMETHOD GetTxnName (nsIAtom **aName)
NS_IMETHOD StartSelectionEquals (nsSelectionState *aSelState, PRBool *aResult)
NS_IMETHOD EndPlaceHolderBatch ()
NS_IMETHOD ForwardEndBatchTo (nsIAbsorbingTransaction *aForwardingAddress)
NS_IMETHOD Commit ()
NS_IMETHOD RememberEndingSelection ()
NS_IMETHOD GetIsTransient (PRBool *aIsTransient)
NS_IMETHOD AppendChild (EditTxn *aTxn)
 append a transaction to this aggregate
NS_IMETHOD GetCount (PRUint32 *aCount)
 get the number of nested txns.
NS_IMETHOD GetTxnAt (PRInt32 aIndex, EditTxn **aTxn)
 get the txn at index aIndex.
NS_IMETHOD SetName (nsIAtom *aName)
 set the name assigned to this txn
NS_IMETHOD GetName (nsIAtom **aName)
 get the name assigned to this txn
void doTransaction ()
 Executes the transaction.
void undoTransaction ()
 Restores the state to what it was before the transaction was executed.
void redoTransaction ()
 Executes the transaction again.
boolean merge (in nsITransaction aTransaction)
 Attempts to merge a transaction into "this" transaction.

Static Public Member Functions

static const nsIIDGetCID ()

Public Attributes

readonly attribute boolean isTransient
 The transaction's transient state.
readonly attribute DOMString txnDescription

Protected Attributes

PRBool mAbsorb
 the presentation shell, which we'll need to get the selection
nsWeakPtr mForwarding
IMETextTxnmIMETextTxn
PRBool mCommitted
nsSelectionStatemStartSel
nsSelectionState mEndSel
nsIEditormEditor
nsCOMPtr< nsISupportsArraymChildren
nsCOMPtr< nsIAtommName

Private Member Functions

 PlaceholderTxn ()

Friends

class TransactionFactory

Detailed Description

An aggregate transaction that knows how to absorb all subsequent transactions with the same name.

This transaction does not "Do" anything. But it absorbs other transactions via merge, and can undo/redo the transactions it has absorbed.

Definition at line 64 of file PlaceholderTxn.h.


Constructor & Destructor Documentation

Definition at line 56 of file PlaceholderTxn.cpp.

{
  delete mStartSel;
}

Member Function Documentation

append a transaction to this aggregate

Definition at line 156 of file EditAggregateTxn.cpp.

{
  if (mChildren && aTxn)
  {
    // aaahhhh! broken interfaces drive me crazy!!!
    nsCOMPtr<nsISupports> isupports;
    aTxn->QueryInterface(NS_GET_IID(nsISupports), getter_AddRefs(isupports));
    mChildren->AppendElement(isupports);
    return NS_OK;
  }
  return NS_ERROR_NULL_POINTER;
}

Here is the call graph for this function:

Here is the caller graph for this function:

Implements nsIAbsorbingTransaction.

Definition at line 288 of file PlaceholderTxn.cpp.

{
  mCommitted = PR_TRUE;
  return NS_OK;
}

Executes the transaction.

Reimplemented from EditAggregateTxn.

Definition at line 92 of file PlaceholderTxn.cpp.

{
  return NS_OK;
}

Implements nsIAbsorbingTransaction.

Definition at line 268 of file PlaceholderTxn.cpp.

{
  mAbsorb = PR_FALSE;
  
  if (mForwarding) 
  {
    nsCOMPtr<nsIAbsorbingTransaction> plcTxn = do_QueryReferent(mForwarding);
    if (plcTxn) plcTxn->EndPlaceHolderBatch();
  }
  
  // remember our selection state.
  return RememberEndingSelection();
}

Here is the call graph for this function:

Implements nsIAbsorbingTransaction.

Definition at line 282 of file PlaceholderTxn.cpp.

{   
  mForwarding = do_GetWeakReference(aForwardingAddress);
  return NS_OK;
}

Here is the call graph for this function:

static const nsIID& PlaceholderTxn::GetCID ( ) [inline, static]

Reimplemented from EditAggregateTxn.

Definition at line 70 of file PlaceholderTxn.h.

{ static const nsIID iid = PLACEHOLDER_TXN_CID; return iid; }

Here is the caller graph for this function:

get the number of nested txns.

This is the number of top-level txns, it does not do recursive decent.

Definition at line 169 of file EditAggregateTxn.cpp.

{
  if (!aCount) {
    return NS_ERROR_NULL_POINTER;
  }
  *aCount=0;
  if (mChildren) {
    mChildren->Count(aCount);
  }
  return NS_OK;
}
NS_IMETHODIMP EditAggregateTxn::GetIsTransient ( PRBool aIsTransient) [inherited]

Reimplemented from EditTxn.

Definition at line 114 of file EditAggregateTxn.cpp.

{
  if (aIsTransient)
    *aIsTransient = PR_FALSE;
  return NS_OK;
}
NS_IMETHODIMP EditAggregateTxn::GetName ( nsIAtom **  aName) [inherited]

get the name assigned to this txn

Definition at line 215 of file EditAggregateTxn.cpp.

{
  if (aName && mName)
  {
    *aName = mName;
    NS_ADDREF(*aName);
    return NS_OK;
  }
  return NS_ERROR_NULL_POINTER;
}

Here is the call graph for this function:

Here is the caller graph for this function:

NS_IMETHODIMP EditAggregateTxn::GetTxnAt ( PRInt32  aIndex,
EditTxn **  aTxn 
) [inherited]

get the txn at index aIndex.

returns NS_ERROR_UNEXPECTED if there is no txn at aIndex.

Definition at line 181 of file EditAggregateTxn.cpp.

{
  // preconditions
  NS_PRECONDITION(aTxn, "null out param");
  NS_PRECONDITION(mChildren, "bad internal state");

  if (!aTxn) {
    return NS_ERROR_NULL_POINTER;
  }
  *aTxn = nsnull; // initialize out param as soon as we know it's a valid pointer
  if (!mChildren) {
    return NS_ERROR_UNEXPECTED;
  }

  // get the transaction at aIndex
  PRUint32 txnCount;
  mChildren->Count(&txnCount);
  if (0>aIndex || ((PRInt32)txnCount)<=aIndex) {
    return NS_ERROR_UNEXPECTED;
  }
  // ugh, this is all wrong - what a mess we have with editor transaction interfaces
  mChildren->QueryElementAt(aIndex, EditTxn::GetCID(), (void**)aTxn);
  if (!*aTxn)
    return NS_ERROR_UNEXPECTED;
  return NS_OK;
}

Here is the call graph for this function:

NS_IMETHODIMP PlaceholderTxn::GetTxnDescription ( nsAString &  aTxnDescription)

Reimplemented from EditAggregateTxn.

Definition at line 235 of file PlaceholderTxn.cpp.

{
  aString.AssignLiteral("PlaceholderTxn: ");

  if (mName)
  {
    nsAutoString name;
    mName->ToString(name);
    aString += name;
  }

  return NS_OK;
}

Implements nsIAbsorbingTransaction.

Definition at line 249 of file PlaceholderTxn.cpp.

{
  return GetName(aName);
}

Here is the call graph for this function:

NS_IMETHODIMP PlaceholderTxn::Init ( nsIAtom aName,
nsSelectionState aSelState,
nsIEditor aEditor 
) [virtual]

Implements nsIAbsorbingTransaction.

Definition at line 82 of file PlaceholderTxn.cpp.

{
  if (!aEditor || !aSelState) return NS_ERROR_NULL_POINTER;

  mName = aName;
  mStartSel = aSelState;
  mEditor = aEditor;
  return NS_OK;
}
NS_IMETHODIMP PlaceholderTxn::Merge ( nsITransaction aTransaction,
PRBool aDidMerge 
)

Reimplemented from EditAggregateTxn.

Definition at line 129 of file PlaceholderTxn.cpp.

{
  if (!aDidMerge || !aTransaction) return NS_ERROR_NULL_POINTER;

  // set out param default value
  *aDidMerge=PR_FALSE;
    
  if (mForwarding) 
  {
    NS_NOTREACHED("tried to merge into a placeholder that was in forwarding mode!");
    return NS_ERROR_FAILURE;
  }

  // check to see if aTransaction is one of the editor's
  // private transactions. If not, we want to avoid merging
  // the foreign transaction into our placeholder since we
  // don't know what it does.

  nsCOMPtr<nsPIEditorTransaction> pTxn = do_QueryInterface(aTransaction);
  if (!pTxn) return NS_OK; // it's foreign so just bail!

  EditTxn *editTxn = (EditTxn*)aTransaction;  //XXX: hack, not safe!  need nsIEditTransaction!
  // determine if this incoming txn is a placeholder txn
  nsCOMPtr<nsIAbsorbingTransaction> plcTxn;// = do_QueryInterface(editTxn);
  // cant do_QueryInterface() above due to our broken transaction interfaces.
  // instead have to brute it below. ugh. 
  editTxn->QueryInterface(NS_GET_IID(nsIAbsorbingTransaction), getter_AddRefs(plcTxn));

  // we are absorbing all txn's if mAbsorb is lit.
  if (mAbsorb)
  { 
    nsRefPtr<IMETextTxn> otherTxn;
    if (NS_SUCCEEDED(aTransaction->QueryInterface(IMETextTxn::GetCID(), getter_AddRefs(otherTxn))) && otherTxn)
    {
      // special handling for IMETextTxn's: they need to merge with any previous
      // IMETextTxn in this placeholder, if possible.
      if (!mIMETextTxn) 
      {
        // this is the first IME txn in the placeholder
        mIMETextTxn =otherTxn;
        AppendChild(editTxn);
      }
      else  
      {
        PRBool didMerge;
        mIMETextTxn->Merge(otherTxn, &didMerge);
        if (!didMerge)
        {
          // it wouldn't merge.  Earlier IME txn is already commited and will 
          // not absorb further IME txns.  So just stack this one after it
          // and remember it as a candidate for further merges.
          mIMETextTxn =otherTxn;
          AppendChild(editTxn);
        }
      }
    }
    else if (!plcTxn)  // see bug 171243: just drop incoming placeholders on the floor.
    {                  // their children will be swallowed by this preexisting one.
      AppendChild(editTxn);
    }
    *aDidMerge = PR_TRUE;
//  RememberEndingSelection();
//  efficiency hack: no need to remember selection here, as we haven't yet 
//  finished the inital batch and we know we will be told when the batch ends.
//  we can remeber the selection then.
  }
  else
  { // merge typing or IME or deletion transactions if the selection matches
    if (((mName.get() == nsEditor::gTypingTxnName) ||
         (mName.get() == nsEditor::gIMETxnName)    ||
         (mName.get() == nsEditor::gDeleteTxnName)) 
         && !mCommitted ) 
    {
      nsCOMPtr<nsIAbsorbingTransaction> plcTxn;// = do_QueryInterface(editTxn);
      // can't do_QueryInterface() above due to our broken transaction interfaces.
      // instead have to brute it below. ugh. 
      editTxn->QueryInterface(NS_GET_IID(nsIAbsorbingTransaction), getter_AddRefs(plcTxn));
      if (plcTxn)
      {
        nsCOMPtr<nsIAtom> atom;
        plcTxn->GetTxnName(getter_AddRefs(atom));
        if (atom && (atom == mName))
        {
          // check if start selection of next placeholder matches
          // end selection of this placeholder
          PRBool isSame;
          plcTxn->StartSelectionEquals(&mEndSel, &isSame);
          if (isSame)
          {
            mAbsorb = PR_TRUE;  // we need to start absorbing again
            plcTxn->ForwardEndBatchTo(this);
            // AppendChild(editTxn);
            // see bug 171243: we don't need to merge placeholders
            // into placeholders.  We just reactivate merging in the pre-existing
            // placeholder and drop the new one on the floor.  The EndPlaceHolderBatch()
            // call on the new placeholder will be forwarded to this older one.
            RememberEndingSelection();
            *aDidMerge = PR_TRUE;
          }
        }
      }
    }
  }
  return NS_OK;
}

Here is the call graph for this function:

boolean nsITransaction::merge ( in nsITransaction  aTransaction) [inherited]

Attempts to merge a transaction into "this" transaction.

Both transactions must be in their undo state, doTransaction() methods already called. The transaction manager calls this method to coalesce a new transaction with the transaction on the top of the undo stack. This method returns a boolean value that indicates the merge result. A true value indicates that the transactions were merged successfully, a false value if the merge was not possible or failed. If true, the transaction manager will Release() the new transacton instead of pushing it on the undo stack.

Parameters:
aTransactionthe previously executed transaction to merge.

Executes the transaction again.

Can only be called on a transaction that was previously undone.

In most cases, the redoTransaction() method will actually call the doTransaction() method to execute the transaction again.

Reimplemented from EditAggregateTxn.

Definition at line 114 of file PlaceholderTxn.cpp.

{
  // redo txns
  nsresult res = EditAggregateTxn::RedoTransaction();
  if (NS_FAILED(res)) return res;
  
  // now restore selection
  nsCOMPtr<nsISelection> selection;
  res = mEditor->GetSelection(getter_AddRefs(selection));
  if (NS_FAILED(res)) return res;
  if (!selection) return NS_ERROR_NULL_POINTER;
  return mEndSel.RestoreSelection(selection);
}

Here is the call graph for this function:

Definition at line 294 of file PlaceholderTxn.cpp.

{
  nsCOMPtr<nsISelection> selection;
  nsresult res = mEditor->GetSelection(getter_AddRefs(selection));
  if (NS_FAILED(res)) return res;
  if (!selection) return NS_ERROR_NULL_POINTER;
  return mEndSel.SaveSelection(selection);
}

Here is the call graph for this function:

Here is the caller graph for this function:

set the name assigned to this txn

Definition at line 209 of file EditAggregateTxn.cpp.

{
  mName = do_QueryInterface(aName);
  return NS_OK;
}

Here is the call graph for this function:

NS_IMETHODIMP PlaceholderTxn::StartSelectionEquals ( nsSelectionState aSelState,
PRBool aResult 
) [virtual]

Implements nsIAbsorbingTransaction.

Definition at line 254 of file PlaceholderTxn.cpp.

{
  // determine if starting selection matches the given selection state.
  // note that we only care about collapsed selections.
  if (!aResult || !aSelState) return NS_ERROR_NULL_POINTER;
  if (!mStartSel->IsCollapsed() || !aSelState->IsCollapsed())
  {
    *aResult = PR_FALSE;
    return NS_OK;
  }
  *aResult = mStartSel->IsEqual(aSelState);
  return NS_OK;
}

Here is the call graph for this function:

Restores the state to what it was before the transaction was executed.

Reimplemented from EditAggregateTxn.

Definition at line 97 of file PlaceholderTxn.cpp.

{
  // undo txns
  nsresult res = EditAggregateTxn::UndoTransaction();
  if (NS_FAILED(res)) return res;
  
  if (!mStartSel) return NS_ERROR_NULL_POINTER;

  // now restore selection
  nsCOMPtr<nsISelection> selection;
  res = mEditor->GetSelection(getter_AddRefs(selection));
  if (NS_FAILED(res)) return res;
  if (!selection) return NS_ERROR_NULL_POINTER;
  return mStartSel->RestoreSelection(selection);
}

Here is the call graph for this function:


Friends And Related Function Documentation

friend class TransactionFactory [friend]

Definition at line 109 of file PlaceholderTxn.h.


Member Data Documentation

The transaction's transient state.

This attribute is checked by the transaction manager after the transaction's Execute() method is called. If the transient state is false, a reference to the transaction is held by the transaction manager so that the transactions' undoTransaction() and redoTransaction() methods can be called. If the transient state is true, the transaction manager returns immediately after the transaction's doTransaction() method is called, no references to the transaction are maintained. Transient transactions cannot be undone or redone by the transaction manager.

Definition at line 79 of file nsITransaction.idl.

the presentation shell, which we'll need to get the selection

Definition at line 114 of file PlaceholderTxn.h.

Definition at line 101 of file EditAggregateTxn.h.

Definition at line 118 of file PlaceholderTxn.h.

Definition at line 125 of file PlaceholderTxn.h.

Definition at line 124 of file PlaceholderTxn.h.

Definition at line 115 of file PlaceholderTxn.h.

Definition at line 116 of file PlaceholderTxn.h.

nsCOMPtr<nsIAtom> EditAggregateTxn::mName [protected, inherited]

Definition at line 102 of file EditAggregateTxn.h.

Definition at line 123 of file PlaceholderTxn.h.

readonly attribute DOMString nsPIEditorTransaction::txnDescription [inherited]

Definition at line 50 of file nsPIEditorTransaction.idl.


The documentation for this class was generated from the following files: