editor/composer/src/nsComposerCommandsUpdater.cpp

Wed, 31 Dec 2014 06:09:35 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Wed, 31 Dec 2014 06:09:35 +0100
changeset 0
6474c204b198
permissions
-rw-r--r--

Cloned upstream origin tor-browser at tor-browser-31.3.0esr-4.5-1-build1
revision ID fc1c9ff7c1b2defdbc039f12214767608f46423f for hacking purpose.

     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/. */
     7 #include "mozilla/mozalloc.h"           // for operator new
     8 #include "nsAString.h"
     9 #include "nsComponentManagerUtils.h"    // for do_CreateInstance
    10 #include "nsComposerCommandsUpdater.h"
    11 #include "nsDebug.h"                    // for NS_ENSURE_TRUE, etc
    12 #include "nsError.h"                    // for NS_OK, NS_ERROR_FAILURE, etc
    13 #include "nsICommandManager.h"          // for nsICommandManager
    14 #include "nsID.h"                       // for NS_GET_IID, etc
    15 #include "nsIDOMWindow.h"               // for nsIDOMWindow
    16 #include "nsIDocShell.h"                // for nsIDocShell
    17 #include "nsIInterfaceRequestorUtils.h"  // for do_GetInterface
    18 #include "nsISelection.h"               // for nsISelection
    19 #include "nsITransactionManager.h"      // for nsITransactionManager
    20 #include "nsLiteralString.h"            // for NS_LITERAL_STRING
    21 #include "nsPICommandUpdater.h"         // for nsPICommandUpdater
    22 #include "nsPIDOMWindow.h"              // for nsPIDOMWindow
    24 class nsIDOMDocument;
    25 class nsITransaction;
    27 nsComposerCommandsUpdater::nsComposerCommandsUpdater()
    28 :  mDirtyState(eStateUninitialized)
    29 ,  mSelectionCollapsed(eStateUninitialized)
    30 ,  mFirstDoOfFirstUndo(true)
    31 {
    32 }
    34 nsComposerCommandsUpdater::~nsComposerCommandsUpdater()
    35 {
    36   // cancel any outstanding update timer
    37   if (mUpdateTimer)
    38   {
    39     mUpdateTimer->Cancel();
    40   }
    41 }
    43 NS_IMPL_ISUPPORTS(nsComposerCommandsUpdater, nsISelectionListener,
    44                   nsIDocumentStateListener, nsITransactionListener, nsITimerCallback)
    46 #if 0
    47 #pragma mark -
    48 #endif
    50 NS_IMETHODIMP
    51 nsComposerCommandsUpdater::NotifyDocumentCreated()
    52 {
    53   // Trigger an nsIObserve notification that the document has been created
    54   UpdateOneCommand("obs_documentCreated");
    55   return NS_OK;
    56 }
    58 NS_IMETHODIMP
    59 nsComposerCommandsUpdater::NotifyDocumentWillBeDestroyed()
    60 {
    61   // cancel any outstanding update timer
    62   if (mUpdateTimer)
    63   {
    64     mUpdateTimer->Cancel();
    65     mUpdateTimer = nullptr;
    66   }
    68   // We can't call this right now; it is too late in some cases and the window
    69   // is already partially destructed (e.g. JS objects may be gone).
    70 #if 0
    71   // Trigger an nsIObserve notification that the document will be destroyed
    72   UpdateOneCommand("obs_documentWillBeDestroyed");
    73 #endif
    74   return NS_OK;
    75 }
    78 NS_IMETHODIMP
    79 nsComposerCommandsUpdater::NotifyDocumentStateChanged(bool aNowDirty)
    80 {
    81   // update document modified. We should have some other notifications for this too.
    82   return UpdateDirtyState(aNowDirty);
    83 }
    85 NS_IMETHODIMP
    86 nsComposerCommandsUpdater::NotifySelectionChanged(nsIDOMDocument *,
    87                                                   nsISelection *, int16_t)
    88 {
    89   return PrimeUpdateTimer();
    90 }
    92 #if 0
    93 #pragma mark -
    94 #endif
    96 NS_IMETHODIMP
    97 nsComposerCommandsUpdater::WillDo(nsITransactionManager *aManager,
    98                                   nsITransaction *aTransaction, bool *aInterrupt)
    99 {
   100   *aInterrupt = false;
   101   return NS_OK;
   102 }
   104 NS_IMETHODIMP
   105 nsComposerCommandsUpdater::DidDo(nsITransactionManager *aManager,
   106   nsITransaction *aTransaction, nsresult aDoResult)
   107 {
   108   // only need to update if the status of the Undo menu item changes.
   109   int32_t undoCount;
   110   aManager->GetNumberOfUndoItems(&undoCount);
   111   if (undoCount == 1)
   112   {
   113     if (mFirstDoOfFirstUndo)
   114       UpdateCommandGroup(NS_LITERAL_STRING("undo"));
   115     mFirstDoOfFirstUndo = false;
   116   }
   118   return NS_OK;
   119 }
   121 NS_IMETHODIMP 
   122 nsComposerCommandsUpdater::WillUndo(nsITransactionManager *aManager,
   123                                     nsITransaction *aTransaction,
   124                                     bool *aInterrupt)
   125 {
   126   *aInterrupt = false;
   127   return NS_OK;
   128 }
   130 NS_IMETHODIMP
   131 nsComposerCommandsUpdater::DidUndo(nsITransactionManager *aManager,
   132                                    nsITransaction *aTransaction,
   133                                    nsresult aUndoResult)
   134 {
   135   int32_t undoCount;
   136   aManager->GetNumberOfUndoItems(&undoCount);
   137   if (undoCount == 0)
   138     mFirstDoOfFirstUndo = true;    // reset the state for the next do
   140   UpdateCommandGroup(NS_LITERAL_STRING("undo"));
   141   return NS_OK;
   142 }
   144 NS_IMETHODIMP
   145 nsComposerCommandsUpdater::WillRedo(nsITransactionManager *aManager,
   146                                     nsITransaction *aTransaction,
   147                                     bool *aInterrupt)
   148 {
   149   *aInterrupt = false;
   150   return NS_OK;
   151 }
   153 NS_IMETHODIMP
   154 nsComposerCommandsUpdater::DidRedo(nsITransactionManager *aManager,  
   155                                    nsITransaction *aTransaction,
   156                                    nsresult aRedoResult)
   157 {
   158   UpdateCommandGroup(NS_LITERAL_STRING("undo"));
   159   return NS_OK;
   160 }
   162 NS_IMETHODIMP
   163 nsComposerCommandsUpdater::WillBeginBatch(nsITransactionManager *aManager,
   164                                           bool *aInterrupt)
   165 {
   166   *aInterrupt = false;
   167   return NS_OK;
   168 }
   170 NS_IMETHODIMP
   171 nsComposerCommandsUpdater::DidBeginBatch(nsITransactionManager *aManager,
   172                                          nsresult aResult)
   173 {
   174   return NS_OK;
   175 }
   177 NS_IMETHODIMP
   178 nsComposerCommandsUpdater::WillEndBatch(nsITransactionManager *aManager,
   179                                         bool *aInterrupt)
   180 {
   181   *aInterrupt = false;
   182   return NS_OK;
   183 }
   185 NS_IMETHODIMP
   186 nsComposerCommandsUpdater::DidEndBatch(nsITransactionManager *aManager, 
   187                                        nsresult aResult)
   188 {
   189   return NS_OK;
   190 }
   192 NS_IMETHODIMP
   193 nsComposerCommandsUpdater::WillMerge(nsITransactionManager *aManager,
   194                                      nsITransaction *aTopTransaction,
   195                                      nsITransaction *aTransactionToMerge,
   196                                      bool *aInterrupt)
   197 {
   198   *aInterrupt = false;
   199   return NS_OK;
   200 }
   202 NS_IMETHODIMP
   203 nsComposerCommandsUpdater::DidMerge(nsITransactionManager *aManager,
   204                                     nsITransaction *aTopTransaction,
   205                                     nsITransaction *aTransactionToMerge,
   206                                     bool aDidMerge, nsresult aMergeResult)
   207 {
   208   return NS_OK;
   209 }
   211 #if 0
   212 #pragma mark -
   213 #endif
   215 nsresult
   216 nsComposerCommandsUpdater::Init(nsIDOMWindow* aDOMWindow)
   217 {
   218   NS_ENSURE_ARG(aDOMWindow);
   219   mDOMWindow = do_GetWeakReference(aDOMWindow);
   221   nsCOMPtr<nsPIDOMWindow> window(do_QueryInterface(aDOMWindow));
   222   if (window)
   223   {
   224     mDocShell = do_GetWeakReference(window->GetDocShell());
   225   }
   226   return NS_OK;
   227 }
   229 nsresult
   230 nsComposerCommandsUpdater::PrimeUpdateTimer()
   231 {
   232   if (!mUpdateTimer)
   233   {
   234     nsresult rv = NS_OK;
   235     mUpdateTimer = do_CreateInstance("@mozilla.org/timer;1", &rv);
   236     NS_ENSURE_SUCCESS(rv, rv);
   237   }
   239   const uint32_t kUpdateTimerDelay = 150;
   240   return mUpdateTimer->InitWithCallback(static_cast<nsITimerCallback*>(this),
   241                                         kUpdateTimerDelay,
   242                                         nsITimer::TYPE_ONE_SHOT);
   243 }
   246 void nsComposerCommandsUpdater::TimerCallback()
   247 {
   248   // if the selection state has changed, update stuff
   249   bool isCollapsed = SelectionIsCollapsed();
   250   if (static_cast<int8_t>(isCollapsed) != mSelectionCollapsed)
   251   {
   252     UpdateCommandGroup(NS_LITERAL_STRING("select"));
   253     mSelectionCollapsed = isCollapsed;
   254   }
   256   // isn't this redundant with the UpdateCommandGroup above?
   257   // can we just nuke the above call? or create a meta command group?
   258   UpdateCommandGroup(NS_LITERAL_STRING("style"));
   259 }
   261 nsresult
   262 nsComposerCommandsUpdater::UpdateDirtyState(bool aNowDirty)
   263 {
   264   if (mDirtyState != static_cast<int8_t>(aNowDirty))
   265   {
   266     UpdateCommandGroup(NS_LITERAL_STRING("save"));
   267     UpdateCommandGroup(NS_LITERAL_STRING("undo"));
   268     mDirtyState = aNowDirty;
   269   }
   271   return NS_OK;
   272 }
   274 nsresult
   275 nsComposerCommandsUpdater::UpdateCommandGroup(const nsAString& aCommandGroup)
   276 {
   277   nsCOMPtr<nsPICommandUpdater> commandUpdater = GetCommandUpdater();
   278   NS_ENSURE_TRUE(commandUpdater, NS_ERROR_FAILURE);
   281   // This hardcoded list of commands is temporary.
   282   // This code should use nsIControllerCommandGroup.
   283   if (aCommandGroup.EqualsLiteral("undo"))
   284   {
   285     commandUpdater->CommandStatusChanged("cmd_undo");
   286     commandUpdater->CommandStatusChanged("cmd_redo");
   287   }
   288   else if (aCommandGroup.EqualsLiteral("select") ||
   289            aCommandGroup.EqualsLiteral("style"))
   290   {
   291     commandUpdater->CommandStatusChanged("cmd_bold");
   292     commandUpdater->CommandStatusChanged("cmd_italic");
   293     commandUpdater->CommandStatusChanged("cmd_underline");
   294     commandUpdater->CommandStatusChanged("cmd_tt");
   296     commandUpdater->CommandStatusChanged("cmd_strikethrough");
   297     commandUpdater->CommandStatusChanged("cmd_superscript");
   298     commandUpdater->CommandStatusChanged("cmd_subscript");
   299     commandUpdater->CommandStatusChanged("cmd_nobreak");
   301     commandUpdater->CommandStatusChanged("cmd_em");
   302     commandUpdater->CommandStatusChanged("cmd_strong");
   303     commandUpdater->CommandStatusChanged("cmd_cite");
   304     commandUpdater->CommandStatusChanged("cmd_abbr");
   305     commandUpdater->CommandStatusChanged("cmd_acronym");
   306     commandUpdater->CommandStatusChanged("cmd_code");
   307     commandUpdater->CommandStatusChanged("cmd_samp");
   308     commandUpdater->CommandStatusChanged("cmd_var");
   310     commandUpdater->CommandStatusChanged("cmd_increaseFont");
   311     commandUpdater->CommandStatusChanged("cmd_decreaseFont");
   313     commandUpdater->CommandStatusChanged("cmd_paragraphState");
   314     commandUpdater->CommandStatusChanged("cmd_fontFace");
   315     commandUpdater->CommandStatusChanged("cmd_fontColor");
   316     commandUpdater->CommandStatusChanged("cmd_backgroundColor");
   317     commandUpdater->CommandStatusChanged("cmd_highlight");
   318   }  
   319   else if (aCommandGroup.EqualsLiteral("save"))
   320   {
   321     // save commands (most are not in C++)
   322     commandUpdater->CommandStatusChanged("cmd_setDocumentModified");
   323     commandUpdater->CommandStatusChanged("cmd_save");
   324   }
   325   return NS_OK;  
   326 }
   328 nsresult
   329 nsComposerCommandsUpdater::UpdateOneCommand(const char *aCommand)
   330 {
   331   nsCOMPtr<nsPICommandUpdater> commandUpdater = GetCommandUpdater();
   332   NS_ENSURE_TRUE(commandUpdater, NS_ERROR_FAILURE);
   334   commandUpdater->CommandStatusChanged(aCommand);
   336   return NS_OK;  
   337 }
   339 bool
   340 nsComposerCommandsUpdater::SelectionIsCollapsed()
   341 {
   342   nsCOMPtr<nsIDOMWindow> domWindow = do_QueryReferent(mDOMWindow);
   343   NS_ENSURE_TRUE(domWindow, true);
   345   nsCOMPtr<nsISelection> domSelection;
   346   if (NS_SUCCEEDED(domWindow->GetSelection(getter_AddRefs(domSelection))) && domSelection)
   347   {
   348     bool selectionCollapsed = false;
   349     domSelection->GetIsCollapsed(&selectionCollapsed);
   350     return selectionCollapsed;
   351   }
   353   NS_WARNING("nsComposerCommandsUpdater::SelectionIsCollapsed - no domSelection");
   355   return false;
   356 }
   358 already_AddRefed<nsPICommandUpdater>
   359 nsComposerCommandsUpdater::GetCommandUpdater()
   360 {
   361   nsCOMPtr<nsIDocShell> docShell = do_QueryReferent(mDocShell);
   362   NS_ENSURE_TRUE(docShell, nullptr);
   363   nsCOMPtr<nsICommandManager> manager = do_GetInterface(docShell);
   364   nsCOMPtr<nsPICommandUpdater> updater = do_QueryInterface(manager);
   365   return updater.forget();
   366 }
   368 #if 0
   369 #pragma mark -
   370 #endif
   372 nsresult
   373 nsComposerCommandsUpdater::Notify(nsITimer *timer)
   374 {
   375   NS_ASSERTION(timer == mUpdateTimer.get(), "Hey, this ain't my timer!");
   376   TimerCallback();
   377   return NS_OK;
   378 }
   380 #if 0
   381 #pragma mark -
   382 #endif
   385 nsresult
   386 NS_NewComposerCommandsUpdater(nsISelectionListener** aInstancePtrResult)
   387 {
   388   nsComposerCommandsUpdater* newThang = new nsComposerCommandsUpdater;
   389   NS_ENSURE_TRUE(newThang, NS_ERROR_OUT_OF_MEMORY);
   391   return newThang->QueryInterface(NS_GET_IID(nsISelectionListener),
   392                                   (void **)aInstancePtrResult);
   393 }

mercurial