summaryrefslogtreecommitdiffstats
path: root/editor/composer/ComposerCommandsUpdater.cpp
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--editor/composer/ComposerCommandsUpdater.cpp270
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