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:
Masayuki Nakano 2018-10-30 09:56:41 +00:00
Родитель 719ab63a7d
Коммит 7f8df77fb6
3 изменённых файлов: 121 добавлений и 2 удалений

Просмотреть файл

@ -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.