зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1465702 - part 1: Add EditorBase::AutoEditActionDataSetter to store edit action and grab Selection instance while editor classes handle an edit action r=m_kato
Like TextEditRules, EditorBase should have a stack class which cache necessary objects and current handling edit action. The edit action will be necessary when we implement InputEvent.inputType. Different from TextEditRules, this adds |const RefPtr<Selection>&| instead of |Selection&|. The reason is, when I add MOZ_CAN_RUN_SCRIPT to some methods, it's not allowed like this: > foo->CanRunScriptMethod(SelectionRef()); I'll update TextEditRules for consistency in the following patches. Differential Revision: https://phabricator.services.mozilla.com/D10005 --HG-- extra : moz-landing-system : lando
This commit is contained in:
Родитель
719ab63a7d
Коммит
7f8df77fb6
|
@ -8,6 +8,21 @@
|
|||
|
||||
namespace mozilla {
|
||||
|
||||
/**
|
||||
* EditAction indicates which operation or command causes running the methods
|
||||
* of editors.
|
||||
*/
|
||||
enum class EditAction
|
||||
{
|
||||
// eNone indicates no edit action is being handled.
|
||||
eNone,
|
||||
|
||||
// eNotEditing indicates that something is retrieved or initializing
|
||||
// something at creating, destroying or focus move etc, i.e., not edit
|
||||
// action is being handled but editor is doing something.
|
||||
eNotEditing,
|
||||
};
|
||||
|
||||
// This is int32_t instead of int16_t because nsIInlineSpellChecker.idl's
|
||||
// spellCheckAfterEditorChange is defined to take it as a long.
|
||||
// TODO: Make each name eFoo and investigate whether the numeric values
|
||||
|
|
|
@ -155,7 +155,8 @@ EditorBase::MoveNodeWithTransaction(nsIContent& aContent,
|
|||
const EditorRawDOMPoint& aPointToInsert);
|
||||
|
||||
EditorBase::EditorBase()
|
||||
: mPlaceholderName(nullptr)
|
||||
: mEditActionData(nullptr)
|
||||
, mPlaceholderName(nullptr)
|
||||
, mModCount(0)
|
||||
, mFlags(0)
|
||||
, mUpdateCount(0)
|
||||
|
@ -5186,4 +5187,41 @@ EditorBase::AutoSelectionRestorer::Abort()
|
|||
}
|
||||
}
|
||||
|
||||
/*****************************************************************************
|
||||
* mozilla::EditorBase::AutoEditActionDataSetter
|
||||
*****************************************************************************/
|
||||
|
||||
EditorBase::AutoEditActionDataSetter::AutoEditActionDataSetter(
|
||||
const EditorBase& aEditorBase,
|
||||
EditAction aEditAction)
|
||||
: mEditorBase(const_cast<EditorBase&>(aEditorBase))
|
||||
, mParentData(aEditorBase.mEditActionData)
|
||||
{
|
||||
// If we're nested edit action, copies necessary data from the parent.
|
||||
if (mParentData) {
|
||||
mSelection = mParentData->mSelection;
|
||||
// If we're eNotEditing, we should inherit the parent's edit action.
|
||||
// This may occur if creator or its callee use public methods which
|
||||
// just returns something.
|
||||
if (aEditAction != EditAction::eNotEditing) {
|
||||
mEditAction = aEditAction;
|
||||
}
|
||||
} else {
|
||||
mSelection = mEditorBase.GetSelection();
|
||||
if (NS_WARN_IF(!mSelection)) {
|
||||
return;
|
||||
}
|
||||
mEditAction = aEditAction;
|
||||
}
|
||||
mEditorBase.mEditActionData = this;
|
||||
}
|
||||
|
||||
EditorBase::AutoEditActionDataSetter::~AutoEditActionDataSetter()
|
||||
{
|
||||
if (!mSelection || NS_WARN_IF(mEditorBase.mEditActionData != this)) {
|
||||
return;
|
||||
}
|
||||
mEditorBase.mEditActionData = mParentData;
|
||||
}
|
||||
|
||||
} // namespace mozilla
|
||||
|
|
|
@ -7,7 +7,7 @@
|
|||
#define mozilla_EditorBase_h
|
||||
|
||||
#include "mozilla/Assertions.h" // for MOZ_ASSERT, etc.
|
||||
#include "mozilla/EditAction.h" // for EditSubAction
|
||||
#include "mozilla/EditAction.h" // for EditAction and EditSubAction
|
||||
#include "mozilla/EditorDOMPoint.h" // for EditorDOMPoint
|
||||
#include "mozilla/Maybe.h" // for Maybe
|
||||
#include "mozilla/OwningNonNull.h" // for OwningNonNull
|
||||
|
@ -682,6 +682,41 @@ public:
|
|||
*/
|
||||
void ReinitializeSelection(Element& aElement);
|
||||
|
||||
protected: // AutoEditActionDataSetter, this shouldn't be accessed by friends.
|
||||
/**
|
||||
* AutoEditActionDataSetter grabs some necessary objects for handling any
|
||||
* edit actions and store the edit action what we're handling. When this is
|
||||
* created, its pointer is set to the mEditActionData, and this guarantees
|
||||
* the lifetime of grabbing objects until it's destroyed.
|
||||
*/
|
||||
class MOZ_STACK_CLASS AutoEditActionDataSetter final
|
||||
{
|
||||
public:
|
||||
AutoEditActionDataSetter(const EditorBase& aEditorBase,
|
||||
EditAction aEditAction);
|
||||
~AutoEditActionDataSetter();
|
||||
|
||||
bool CanHandle() const
|
||||
{
|
||||
return mSelection && mEditorBase.IsInitialized();
|
||||
}
|
||||
|
||||
const RefPtr<Selection>& SelectionRefPtr() const { return mSelection; }
|
||||
EditAction GetEditAction() const { return mEditAction; }
|
||||
|
||||
private:
|
||||
EditorBase& mEditorBase;
|
||||
RefPtr<Selection> mSelection;
|
||||
// EditAction may be nested, for example, a command may be executed
|
||||
// from mutation event listener which is run while editor changes
|
||||
// the DOM tree. In such case, we need to handle edit action separately.
|
||||
AutoEditActionDataSetter* mParentData;
|
||||
EditAction mEditAction;
|
||||
|
||||
AutoEditActionDataSetter() = delete;
|
||||
AutoEditActionDataSetter(const AutoEditActionDataSetter& aOther) = delete;
|
||||
};
|
||||
|
||||
protected: // May be called by friends.
|
||||
/****************************************************************************
|
||||
* Some classes like TextEditRules, HTMLEditRules, WSRunObject which are
|
||||
|
@ -692,6 +727,35 @@ protected: // May be called by friends.
|
|||
* and call it.
|
||||
****************************************************************************/
|
||||
|
||||
bool IsEditActionDataAvailable() const
|
||||
{
|
||||
return mEditActionData && mEditActionData->CanHandle();
|
||||
}
|
||||
|
||||
/**
|
||||
* SelectionRefPtr() returns cached Selection. This is pretty faster than
|
||||
* EditorBase::GetSelection() if available.
|
||||
* Note that this never returns nullptr unless public methods ignore
|
||||
* result of AutoEditActionDataSetter::CanHandle() and keep handling edit
|
||||
* action but any methods should stop handling edit action if it returns
|
||||
* false.
|
||||
*/
|
||||
const RefPtr<Selection>& SelectionRefPtr() const
|
||||
{
|
||||
MOZ_ASSERT(mEditActionData);
|
||||
return mEditActionData->SelectionRefPtr();
|
||||
}
|
||||
|
||||
/**
|
||||
* GetEditAction() returns EditAction which is being handled. If some
|
||||
* edit actions are nested, this returns the innermost edit action.
|
||||
*/
|
||||
EditAction GetEditAction() const
|
||||
{
|
||||
return mEditActionData ? mEditActionData->GetEditAction() :
|
||||
EditAction::eNone;
|
||||
}
|
||||
|
||||
/**
|
||||
* InsertTextWithTransaction() inserts aStringToInsert to aPointToInsert or
|
||||
* better insertion point around it. If aPointToInsert isn't in a text node,
|
||||
|
@ -1903,6 +1967,8 @@ private:
|
|||
nsCOMPtr<nsISelectionController> mSelectionController;
|
||||
nsCOMPtr<nsIDocument> mDocument;
|
||||
|
||||
AutoEditActionDataSetter* mEditActionData;
|
||||
|
||||
|
||||
/**
|
||||
* SetTextDirectionTo() sets text-direction of the root element.
|
||||
|
|
Загрузка…
Ссылка в новой задаче