ComposerCommandsUpdater.cpp (6622B)
1 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- 2 * 3 * This Source Code Form is subject to the terms of the Mozilla Public 4 * License, v. 2.0. If a copy of the MPL was not distributed with this 5 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 6 7 #include "mozilla/ComposerCommandsUpdater.h" 8 9 #include "mozilla/mozalloc.h" // for operator new 10 #include "mozilla/TransactionManager.h" // for TransactionManager 11 #include "mozilla/dom/Selection.h" 12 #include "nsCommandManager.h" // for nsCommandManager 13 #include "nsComponentManagerUtils.h" // for do_CreateInstance 14 #include "nsDebug.h" // for NS_ENSURE_TRUE, etc 15 #include "nsDocShell.h" // for nsIDocShell 16 #include "nsError.h" // for NS_OK, NS_ERROR_FAILURE, etc 17 #include "nsID.h" // for NS_GET_IID, etc 18 #include "nsIInterfaceRequestorUtils.h" // for do_GetInterface 19 #include "nsLiteralString.h" // for NS_LITERAL_STRING 20 #include "nsPIDOMWindow.h" // for nsPIDOMWindow 21 22 class nsITransaction; 23 24 namespace mozilla { 25 26 ComposerCommandsUpdater::ComposerCommandsUpdater() 27 : mDirtyState(eStateUninitialized), 28 mSelectionCollapsed(eStateUninitialized), 29 mFirstDoOfFirstUndo(true) {} 30 31 ComposerCommandsUpdater::~ComposerCommandsUpdater() { 32 // cancel any outstanding update timer 33 if (mUpdateTimer) { 34 mUpdateTimer->Cancel(); 35 } 36 } 37 38 NS_IMPL_CYCLE_COLLECTING_ADDREF(ComposerCommandsUpdater) 39 NS_IMPL_CYCLE_COLLECTING_RELEASE(ComposerCommandsUpdater) 40 41 NS_INTERFACE_MAP_BEGIN(ComposerCommandsUpdater) 42 NS_INTERFACE_MAP_ENTRY(nsITimerCallback) 43 NS_INTERFACE_MAP_ENTRY(nsINamed) 44 NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsITimerCallback) 45 NS_INTERFACE_MAP_ENTRIES_CYCLE_COLLECTION(ComposerCommandsUpdater) 46 NS_INTERFACE_MAP_END 47 48 NS_IMPL_CYCLE_COLLECTION(ComposerCommandsUpdater, mUpdateTimer, mDOMWindow, 49 mDocShell) 50 51 #if 0 52 # pragma mark - 53 #endif 54 55 void ComposerCommandsUpdater::DidDoTransaction( 56 TransactionManager& aTransactionManager) { 57 // only need to update if the status of the Undo menu item changes. 58 if (aTransactionManager.NumberOfUndoItems() == 1) { 59 if (mFirstDoOfFirstUndo) { 60 UpdateCommandGroup(CommandGroup::Undo); 61 } 62 mFirstDoOfFirstUndo = false; 63 } 64 } 65 66 void ComposerCommandsUpdater::DidUndoTransaction( 67 TransactionManager& aTransactionManager) { 68 if (!aTransactionManager.NumberOfUndoItems()) { 69 mFirstDoOfFirstUndo = true; // reset the state for the next do 70 } 71 UpdateCommandGroup(CommandGroup::Undo); 72 } 73 74 void ComposerCommandsUpdater::DidRedoTransaction( 75 TransactionManager& aTransactionManager) { 76 UpdateCommandGroup(CommandGroup::Undo); 77 } 78 79 #if 0 80 # pragma mark - 81 #endif 82 83 void ComposerCommandsUpdater::Init(nsPIDOMWindowOuter& aDOMWindow) { 84 mDOMWindow = &aDOMWindow; 85 mDocShell = aDOMWindow.GetDocShell(); 86 } 87 88 nsresult ComposerCommandsUpdater::PrimeUpdateTimer() { 89 if (!mUpdateTimer) { 90 mUpdateTimer = NS_NewTimer(); 91 } 92 const uint32_t kUpdateTimerDelay = 150; 93 return mUpdateTimer->InitWithCallback(static_cast<nsITimerCallback*>(this), 94 kUpdateTimerDelay, 95 nsITimer::TYPE_ONE_SHOT); 96 } 97 98 MOZ_CAN_RUN_SCRIPT_BOUNDARY 99 void ComposerCommandsUpdater::TimerCallback() { 100 mSelectionCollapsed = SelectionIsCollapsed(); 101 UpdateCommandGroup(CommandGroup::Style); 102 } 103 104 void ComposerCommandsUpdater::UpdateCommandGroup(CommandGroup aCommandGroup) { 105 RefPtr<nsCommandManager> commandManager = GetCommandManager(); 106 if (NS_WARN_IF(!commandManager)) { 107 return; 108 } 109 110 switch (aCommandGroup) { 111 case CommandGroup::Undo: 112 commandManager->CommandStatusChanged("cmd_undo"); 113 commandManager->CommandStatusChanged("cmd_redo"); 114 return; 115 case CommandGroup::Style: 116 commandManager->CommandStatusChanged("cmd_bold"); 117 commandManager->CommandStatusChanged("cmd_italic"); 118 commandManager->CommandStatusChanged("cmd_underline"); 119 commandManager->CommandStatusChanged("cmd_tt"); 120 121 commandManager->CommandStatusChanged("cmd_strikethrough"); 122 commandManager->CommandStatusChanged("cmd_superscript"); 123 commandManager->CommandStatusChanged("cmd_subscript"); 124 commandManager->CommandStatusChanged("cmd_nobreak"); 125 126 commandManager->CommandStatusChanged("cmd_em"); 127 commandManager->CommandStatusChanged("cmd_strong"); 128 commandManager->CommandStatusChanged("cmd_cite"); 129 commandManager->CommandStatusChanged("cmd_abbr"); 130 commandManager->CommandStatusChanged("cmd_acronym"); 131 commandManager->CommandStatusChanged("cmd_code"); 132 commandManager->CommandStatusChanged("cmd_samp"); 133 commandManager->CommandStatusChanged("cmd_var"); 134 135 commandManager->CommandStatusChanged("cmd_increaseFont"); 136 commandManager->CommandStatusChanged("cmd_decreaseFont"); 137 138 commandManager->CommandStatusChanged("cmd_paragraphState"); 139 commandManager->CommandStatusChanged("cmd_fontFace"); 140 commandManager->CommandStatusChanged("cmd_fontColor"); 141 commandManager->CommandStatusChanged("cmd_backgroundColor"); 142 commandManager->CommandStatusChanged("cmd_highlight"); 143 return; 144 case CommandGroup::Save: 145 commandManager->CommandStatusChanged("cmd_setDocumentModified"); 146 commandManager->CommandStatusChanged("cmd_save"); 147 return; 148 default: 149 MOZ_ASSERT_UNREACHABLE("New command group hasn't been implemented yet"); 150 } 151 } 152 153 nsresult ComposerCommandsUpdater::UpdateOneCommand(const char* aCommand) { 154 RefPtr<nsCommandManager> commandManager = GetCommandManager(); 155 NS_ENSURE_TRUE(commandManager, NS_ERROR_FAILURE); 156 commandManager->CommandStatusChanged(aCommand); 157 return NS_OK; 158 } 159 160 bool ComposerCommandsUpdater::SelectionIsCollapsed() { 161 if (NS_WARN_IF(!mDOMWindow)) { 162 return true; 163 } 164 165 RefPtr<dom::Selection> domSelection = mDOMWindow->GetSelection(); 166 if (NS_WARN_IF(!domSelection)) { 167 return false; 168 } 169 170 return domSelection->IsCollapsed(); 171 } 172 173 nsCommandManager* ComposerCommandsUpdater::GetCommandManager() { 174 if (NS_WARN_IF(!mDocShell)) { 175 return nullptr; 176 } 177 return mDocShell->GetCommandManager(); 178 } 179 180 NS_IMETHODIMP ComposerCommandsUpdater::GetName(nsACString& aName) { 181 aName.AssignLiteral("ComposerCommandsUpdater"); 182 return NS_OK; 183 } 184 185 #if 0 186 # pragma mark - 187 #endif 188 189 nsresult ComposerCommandsUpdater::Notify(nsITimer* aTimer) { 190 NS_ASSERTION(aTimer == mUpdateTimer.get(), "Hey, this ain't my timer!"); 191 TimerCallback(); 192 return NS_OK; 193 } 194 195 #if 0 196 # pragma mark - 197 #endif 198 199 } // namespace mozilla