1 // Copyright 2013 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4 
5 #ifndef COMPONENTS_UNDO_UNDO_MANAGER_H_
6 #define COMPONENTS_UNDO_UNDO_MANAGER_H_
7 
8 #include <stddef.h>
9 
10 #include <memory>
11 #include <vector>
12 
13 #include "base/macros.h"
14 #include "base/observer_list.h"
15 #include "base/strings/string16.h"
16 
17 class UndoManagerObserver;
18 class UndoOperation;
19 
20 // UndoGroup ------------------------------------------------------------------
21 
22 // UndoGroup represents a user action and stores all the operations that
23 // make that action.  Typically there is only one operation per UndoGroup.
24 class UndoGroup {
25  public:
26   UndoGroup();
27   ~UndoGroup();
28 
29   void AddOperation(std::unique_ptr<UndoOperation> operation);
undo_operations()30   const std::vector<std::unique_ptr<UndoOperation>>& undo_operations() {
31     return operations_;
32   }
33   void Undo();
34 
35   // The resource string id describing the undo and redo action.
get_undo_label_id()36   int get_undo_label_id() const { return undo_label_id_; }
set_undo_label_id(int label_id)37   void set_undo_label_id(int label_id) { undo_label_id_ = label_id; }
38 
get_redo_label_id()39   int get_redo_label_id() const { return redo_label_id_; }
set_redo_label_id(int label_id)40   void set_redo_label_id(int label_id) { redo_label_id_ = label_id; }
41 
42  private:
43   std::vector<std::unique_ptr<UndoOperation>> operations_;
44 
45   // The resource string id describing the undo and redo action.
46   int undo_label_id_;
47   int redo_label_id_;
48 
49   DISALLOW_COPY_AND_ASSIGN(UndoGroup);
50 };
51 
52 // UndoManager ----------------------------------------------------------------
53 
54 // Maintains user actions as a group of operations that store enough info to
55 // undo and redo those operations.
56 class UndoManager {
57  public:
58   UndoManager();
59   ~UndoManager();
60 
61   // Perform an undo or redo operation.
62   void Undo();
63   void Redo();
64 
undo_count()65   size_t undo_count() const { return undo_actions_.size(); }
redo_count()66   size_t redo_count() const { return redo_actions_.size(); }
67 
68   base::string16 GetUndoLabel() const;
69   base::string16 GetRedoLabel() const;
70 
71   void AddUndoOperation(std::unique_ptr<UndoOperation> operation);
72 
73   // Group multiple operations into one undoable action.
74   void StartGroupingActions();
75   void EndGroupingActions();
76 
77   // Suspend undo tracking while processing non-user initiated changes such as
78   // profile synchonization.
79   void SuspendUndoTracking();
80   void ResumeUndoTracking();
81   bool IsUndoTrakingSuspended() const;
82 
83   // Remove all undo and redo operations. Note that grouping of actions and
84   // suspension of undo tracking states are left unchanged.
85   void RemoveAllOperations();
86 
87   // Observers are notified when the internal state of this class changes.
88   void AddObserver(UndoManagerObserver* observer);
89   void RemoveObserver(UndoManagerObserver* observer);
90 
91  private:
92   friend class UndoManagerTestApi;
93 
94   void Undo(bool* performing_indicator,
95             std::vector<std::unique_ptr<UndoGroup>>* active_undo_group);
is_user_action()96   bool is_user_action() const { return !performing_undo_ && !performing_redo_; }
97 
98   // Notifies the observers that the undo manager's state has changed.
99   void NotifyOnUndoManagerStateChange();
100 
101   // Handle the addition of |new_undo_group| to the active undo group container.
102   void AddUndoGroup(UndoGroup* new_undo_group);
103 
104   // Returns the undo or redo UndoGroup container that should store the next
105   // change taking into account if an undo or redo is being executed.
106   std::vector<std::unique_ptr<UndoGroup>>* GetActiveUndoGroup();
107 
108   // Containers of user actions ready for an undo or redo treated as a stack.
109   std::vector<std::unique_ptr<UndoGroup>> undo_actions_;
110   std::vector<std::unique_ptr<UndoGroup>> redo_actions_;
111 
112   // The observers to notify when internal state changes.
113   base::ObserverList<UndoManagerObserver>::Unchecked observers_;
114 
115   // Supports grouping operations into a single undo action.
116   int group_actions_count_;
117 
118   // The container that is used when actions are grouped.
119   std::unique_ptr<UndoGroup> pending_grouped_action_;
120 
121   // The action that is in the process of being undone.
122   UndoGroup* undo_in_progress_action_;
123 
124   // Supports the suspension of undo tracking.
125   int undo_suspended_count_;
126 
127   // Set when executing Undo or Redo so that incoming changes are correctly
128   // processed.
129   bool performing_undo_;
130   bool performing_redo_;
131 
132   DISALLOW_COPY_AND_ASSIGN(UndoManager);
133 };
134 
135 #endif  // COMPONENTS_UNDO_UNDO_MANAGER_H_
136