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 #ifndef mozilla_ComposerCommandsUpdater_h
8 #define mozilla_ComposerCommandsUpdater_h
9 
10 #include "nsCOMPtr.h"  // for already_AddRefed, nsCOMPtr
11 #include "nsCycleCollectionParticipant.h"
12 #include "nsINamed.h"
13 #include "nsISupportsImpl.h"         // for NS_DECL_ISUPPORTS
14 #include "nsITimer.h"                // for NS_DECL_NSITIMERCALLBACK, etc
15 #include "nsITransactionListener.h"  // for nsITransactionListener
16 #include "nscore.h"                  // for NS_IMETHOD, nsresult, etc
17 
18 class nsCommandManager;
19 class nsIDocShell;
20 class nsITransaction;
21 class nsITransactionManager;
22 class nsPIDOMWindowOuter;
23 
24 namespace mozilla {
25 
26 class ComposerCommandsUpdater final : public nsITransactionListener,
27                                       public nsITimerCallback,
28                                       public nsINamed {
29  public:
30   ComposerCommandsUpdater();
31 
32   // nsISupports
33   NS_DECL_CYCLE_COLLECTING_ISUPPORTS
34   NS_DECL_CYCLE_COLLECTION_CLASS_AMBIGUOUS(ComposerCommandsUpdater,
35                                            nsITransactionListener)
36 
37   // nsITimerCallback
38   NS_DECL_NSITIMERCALLBACK
39 
40   // nsINamed
41   NS_DECL_NSINAMED
42 
43   // nsITransactionListener
44   NS_DECL_NSITRANSACTIONLISTENER
45 
46   void Init(nsPIDOMWindowOuter& aDOMWindow);
47 
48   /**
49    * OnSelectionChange() is called when selection is changed in the editor.
50    */
OnSelectionChange()51   void OnSelectionChange() { PrimeUpdateTimer(); }
52 
53   /**
54    * OnHTMLEditorCreated() is called when `HTMLEditor` is created and
55    * initialized.
56    */
OnHTMLEditorCreated()57   MOZ_CAN_RUN_SCRIPT void OnHTMLEditorCreated() {
58     UpdateOneCommand("obs_documentCreated");
59   }
60 
61   /**
62    * OnBeforeHTMLEditorDestroyed() is called when `HTMLEditor` is being
63    * destroyed.
64    */
OnBeforeHTMLEditorDestroyed()65   MOZ_CAN_RUN_SCRIPT void OnBeforeHTMLEditorDestroyed() {
66     // cancel any outstanding update timer
67     if (mUpdateTimer) {
68       mUpdateTimer->Cancel();
69       mUpdateTimer = nullptr;
70     }
71 
72     // We can't notify the command manager of this right now; it is too late in
73     // some cases and the window is already partially destructed (e.g. JS
74     // objects may be gone).
75   }
76 
77   /**
78    * OnHTMLEditorDirtyStateChanged() is called when dirty state of `HTMLEditor`
79    * is changed form or to "dirty".
80    */
OnHTMLEditorDirtyStateChanged(bool aNowDirty)81   MOZ_CAN_RUN_SCRIPT void OnHTMLEditorDirtyStateChanged(bool aNowDirty) {
82     if (mDirtyState == static_cast<int8_t>(aNowDirty)) {
83       return;
84     }
85     UpdateCommandGroup(CommandGroup::Save);
86     UpdateCommandGroup(CommandGroup::Undo);
87     mDirtyState = aNowDirty;
88   }
89 
90  protected:
91   virtual ~ComposerCommandsUpdater();
92 
93   enum {
94     eStateUninitialized = -1,
95     eStateOff = 0,
96     eStateOn = 1,
97   };
98 
99   bool SelectionIsCollapsed();
100   MOZ_CAN_RUN_SCRIPT nsresult UpdateOneCommand(const char* aCommand);
101   enum class CommandGroup {
102     Save,
103     Style,
104     Undo,
105   };
106   MOZ_CAN_RUN_SCRIPT void UpdateCommandGroup(CommandGroup aCommandGroup);
107 
108   nsCommandManager* GetCommandManager();
109 
110   nsresult PrimeUpdateTimer();
111   void TimerCallback();
112 
113   nsCOMPtr<nsITimer> mUpdateTimer;
114   nsCOMPtr<nsPIDOMWindowOuter> mDOMWindow;
115   nsCOMPtr<nsIDocShell> mDocShell;
116 
117   int8_t mDirtyState;
118   int8_t mSelectionCollapsed;
119   bool mFirstDoOfFirstUndo;
120 };
121 
122 }  // namespace mozilla
123 
124 #endif  // #ifndef mozilla_ComposerCommandsUpdater_h
125