diff options
Diffstat (limited to '')
-rw-r--r-- | editor/composer/ComposerCommandsUpdater.cpp | 270 |
1 files changed, 270 insertions, 0 deletions
diff --git a/editor/composer/ComposerCommandsUpdater.cpp b/editor/composer/ComposerCommandsUpdater.cpp new file mode 100644 index 0000000000..c7e1a376b1 --- /dev/null +++ b/editor/composer/ComposerCommandsUpdater.cpp @@ -0,0 +1,270 @@ +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +#include "mozilla/ComposerCommandsUpdater.h" + +#include "mozilla/mozalloc.h" // for operator new +#include "mozilla/TransactionManager.h" // for TransactionManager +#include "mozilla/dom/Selection.h" +#include "nsCommandManager.h" // for nsCommandManager +#include "nsComponentManagerUtils.h" // for do_CreateInstance +#include "nsDebug.h" // for NS_ENSURE_TRUE, etc +#include "nsDocShell.h" // for nsIDocShell +#include "nsError.h" // for NS_OK, NS_ERROR_FAILURE, etc +#include "nsID.h" // for NS_GET_IID, etc +#include "nsIInterfaceRequestorUtils.h" // for do_GetInterface +#include "nsITransactionManager.h" // for nsITransactionManager +#include "nsLiteralString.h" // for NS_LITERAL_STRING +#include "nsPIDOMWindow.h" // for nsPIDOMWindow + +class nsITransaction; + +namespace mozilla { + +ComposerCommandsUpdater::ComposerCommandsUpdater() + : mDirtyState(eStateUninitialized), + mSelectionCollapsed(eStateUninitialized), + mFirstDoOfFirstUndo(true) {} + +ComposerCommandsUpdater::~ComposerCommandsUpdater() { + // cancel any outstanding update timer + if (mUpdateTimer) { + mUpdateTimer->Cancel(); + } +} + +NS_IMPL_CYCLE_COLLECTING_ADDREF(ComposerCommandsUpdater) +NS_IMPL_CYCLE_COLLECTING_RELEASE(ComposerCommandsUpdater) + +NS_INTERFACE_MAP_BEGIN(ComposerCommandsUpdater) + NS_INTERFACE_MAP_ENTRY(nsITransactionListener) + NS_INTERFACE_MAP_ENTRY(nsITimerCallback) + NS_INTERFACE_MAP_ENTRY(nsINamed) + NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsITransactionListener) + NS_INTERFACE_MAP_ENTRIES_CYCLE_COLLECTION(ComposerCommandsUpdater) +NS_INTERFACE_MAP_END + +NS_IMPL_CYCLE_COLLECTION(ComposerCommandsUpdater, mUpdateTimer, mDOMWindow, + mDocShell) + +#if 0 +# pragma mark - +#endif + +NS_IMETHODIMP ComposerCommandsUpdater::WillDo(nsITransactionManager* aManager, + nsITransaction* aTransaction, + bool* aInterrupt) { + *aInterrupt = false; + return NS_OK; +} + +MOZ_CAN_RUN_SCRIPT_BOUNDARY +NS_IMETHODIMP ComposerCommandsUpdater::DidDo(nsITransactionManager* aManager, + nsITransaction* aTransaction, + nsresult aDoResult) { + // only need to update if the status of the Undo menu item changes. + size_t undoCount = aManager->AsTransactionManager()->NumberOfUndoItems(); + if (undoCount == 1) { + if (mFirstDoOfFirstUndo) { + UpdateCommandGroup(CommandGroup::Undo); + } + mFirstDoOfFirstUndo = false; + } + + return NS_OK; +} + +NS_IMETHODIMP ComposerCommandsUpdater::WillUndo(nsITransactionManager* aManager, + nsITransaction* aTransaction, + bool* aInterrupt) { + *aInterrupt = false; + return NS_OK; +} + +MOZ_CAN_RUN_SCRIPT_BOUNDARY +NS_IMETHODIMP ComposerCommandsUpdater::DidUndo(nsITransactionManager* aManager, + nsITransaction* aTransaction, + nsresult aUndoResult) { + size_t undoCount = aManager->AsTransactionManager()->NumberOfUndoItems(); + if (!undoCount) { + mFirstDoOfFirstUndo = true; // reset the state for the next do + } + UpdateCommandGroup(CommandGroup::Undo); + return NS_OK; +} + +NS_IMETHODIMP ComposerCommandsUpdater::WillRedo(nsITransactionManager* aManager, + nsITransaction* aTransaction, + bool* aInterrupt) { + *aInterrupt = false; + return NS_OK; +} + +MOZ_CAN_RUN_SCRIPT_BOUNDARY +NS_IMETHODIMP ComposerCommandsUpdater::DidRedo(nsITransactionManager* aManager, + nsITransaction* aTransaction, + nsresult aRedoResult) { + UpdateCommandGroup(CommandGroup::Undo); + return NS_OK; +} + +NS_IMETHODIMP ComposerCommandsUpdater::WillBeginBatch( + nsITransactionManager* aManager, bool* aInterrupt) { + *aInterrupt = false; + return NS_OK; +} + +NS_IMETHODIMP ComposerCommandsUpdater::DidBeginBatch( + nsITransactionManager* aManager, nsresult aResult) { + return NS_OK; +} + +NS_IMETHODIMP ComposerCommandsUpdater::WillEndBatch( + nsITransactionManager* aManager, bool* aInterrupt) { + *aInterrupt = false; + return NS_OK; +} + +NS_IMETHODIMP ComposerCommandsUpdater::DidEndBatch( + nsITransactionManager* aManager, nsresult aResult) { + return NS_OK; +} + +NS_IMETHODIMP ComposerCommandsUpdater::WillMerge( + nsITransactionManager* aManager, nsITransaction* aTopTransaction, + nsITransaction* aTransactionToMerge, bool* aInterrupt) { + *aInterrupt = false; + return NS_OK; +} + +NS_IMETHODIMP ComposerCommandsUpdater::DidMerge( + nsITransactionManager* aManager, nsITransaction* aTopTransaction, + nsITransaction* aTransactionToMerge, bool aDidMerge, + nsresult aMergeResult) { + return NS_OK; +} + +#if 0 +# pragma mark - +#endif + +void ComposerCommandsUpdater::Init(nsPIDOMWindowOuter& aDOMWindow) { + mDOMWindow = &aDOMWindow; + mDocShell = aDOMWindow.GetDocShell(); +} + +nsresult ComposerCommandsUpdater::PrimeUpdateTimer() { + if (!mUpdateTimer) { + mUpdateTimer = NS_NewTimer(); + } + const uint32_t kUpdateTimerDelay = 150; + return mUpdateTimer->InitWithCallback(static_cast<nsITimerCallback*>(this), + kUpdateTimerDelay, + nsITimer::TYPE_ONE_SHOT); +} + +MOZ_CAN_RUN_SCRIPT_BOUNDARY +void ComposerCommandsUpdater::TimerCallback() { + mSelectionCollapsed = SelectionIsCollapsed(); + UpdateCommandGroup(CommandGroup::Style); +} + +void ComposerCommandsUpdater::UpdateCommandGroup(CommandGroup aCommandGroup) { + RefPtr<nsCommandManager> commandManager = GetCommandManager(); + if (NS_WARN_IF(!commandManager)) { + return; + } + + switch (aCommandGroup) { + case CommandGroup::Undo: + commandManager->CommandStatusChanged("cmd_undo"); + commandManager->CommandStatusChanged("cmd_redo"); + return; + case CommandGroup::Style: + commandManager->CommandStatusChanged("cmd_bold"); + commandManager->CommandStatusChanged("cmd_italic"); + commandManager->CommandStatusChanged("cmd_underline"); + commandManager->CommandStatusChanged("cmd_tt"); + + commandManager->CommandStatusChanged("cmd_strikethrough"); + commandManager->CommandStatusChanged("cmd_superscript"); + commandManager->CommandStatusChanged("cmd_subscript"); + commandManager->CommandStatusChanged("cmd_nobreak"); + + commandManager->CommandStatusChanged("cmd_em"); + commandManager->CommandStatusChanged("cmd_strong"); + commandManager->CommandStatusChanged("cmd_cite"); + commandManager->CommandStatusChanged("cmd_abbr"); + commandManager->CommandStatusChanged("cmd_acronym"); + commandManager->CommandStatusChanged("cmd_code"); + commandManager->CommandStatusChanged("cmd_samp"); + commandManager->CommandStatusChanged("cmd_var"); + + commandManager->CommandStatusChanged("cmd_increaseFont"); + commandManager->CommandStatusChanged("cmd_decreaseFont"); + + commandManager->CommandStatusChanged("cmd_paragraphState"); + commandManager->CommandStatusChanged("cmd_fontFace"); + commandManager->CommandStatusChanged("cmd_fontColor"); + commandManager->CommandStatusChanged("cmd_backgroundColor"); + commandManager->CommandStatusChanged("cmd_highlight"); + return; + case CommandGroup::Save: + commandManager->CommandStatusChanged("cmd_setDocumentModified"); + commandManager->CommandStatusChanged("cmd_save"); + return; + default: + MOZ_ASSERT_UNREACHABLE("New command group hasn't been implemented yet"); + } +} + +nsresult ComposerCommandsUpdater::UpdateOneCommand(const char* aCommand) { + RefPtr<nsCommandManager> commandManager = GetCommandManager(); + NS_ENSURE_TRUE(commandManager, NS_ERROR_FAILURE); + commandManager->CommandStatusChanged(aCommand); + return NS_OK; +} + +bool ComposerCommandsUpdater::SelectionIsCollapsed() { + if (NS_WARN_IF(!mDOMWindow)) { + return true; + } + + RefPtr<dom::Selection> domSelection = mDOMWindow->GetSelection(); + if (NS_WARN_IF(!domSelection)) { + return false; + } + + return domSelection->IsCollapsed(); +} + +nsCommandManager* ComposerCommandsUpdater::GetCommandManager() { + if (NS_WARN_IF(!mDocShell)) { + return nullptr; + } + return mDocShell->GetCommandManager(); +} + +NS_IMETHODIMP ComposerCommandsUpdater::GetName(nsACString& aName) { + aName.AssignLiteral("ComposerCommandsUpdater"); + return NS_OK; +} + +#if 0 +# pragma mark - +#endif + +nsresult ComposerCommandsUpdater::Notify(nsITimer* aTimer) { + NS_ASSERTION(aTimer == mUpdateTimer.get(), "Hey, this ain't my timer!"); + TimerCallback(); + return NS_OK; +} + +#if 0 +# pragma mark - +#endif + +} // namespace mozilla |