summaryrefslogtreecommitdiffstats
path: root/chrome/browser/undo
diff options
context:
space:
mode:
authorerikchen@chromium.org <erikchen@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2014-04-15 21:14:22 +0000
committererikchen@chromium.org <erikchen@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2014-04-15 21:14:22 +0000
commit0167050eca60c7994e810a002f465803863c8d0f (patch)
tree1fdcb63e55cefe247e4a294cd7a189034f60c16a /chrome/browser/undo
parent5f52cda2a110b3e722d25c240ae2d7ecaf32197d (diff)
downloadchromium_src-0167050eca60c7994e810a002f465803863c8d0f.zip
chromium_src-0167050eca60c7994e810a002f465803863c8d0f.tar.gz
chromium_src-0167050eca60c7994e810a002f465803863c8d0f.tar.bz2
Add observers to UndoManager.
Observers are notified when the internal state of UndoManager changes. BUG=361413 Review URL: https://codereview.chromium.org/231073003 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@264001 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'chrome/browser/undo')
-rw-r--r--chrome/browser/undo/undo_manager.cc20
-rw-r--r--chrome/browser/undo/undo_manager.h12
-rw-r--r--chrome/browser/undo/undo_manager_observer.h18
-rw-r--r--chrome/browser/undo/undo_manager_test.cc47
4 files changed, 97 insertions, 0 deletions
diff --git a/chrome/browser/undo/undo_manager.cc b/chrome/browser/undo/undo_manager.cc
index 89ffe30..94e28f4 100644
--- a/chrome/browser/undo/undo_manager.cc
+++ b/chrome/browser/undo/undo_manager.cc
@@ -6,6 +6,7 @@
#include "base/auto_reset.h"
#include "base/logging.h"
+#include "chrome/browser/undo/undo_manager_observer.h"
#include "chrome/browser/undo/undo_operation.h"
#include "grit/generated_resources.h"
#include "ui/base/l10n/l10n_util.h"
@@ -165,6 +166,16 @@ void UndoManager::RemoveAllOperations() {
DCHECK(!group_actions_count_);
undo_actions_.clear();
redo_actions_.clear();
+
+ NotifyOnUndoManagerStateChange();
+}
+
+void UndoManager::AddObserver(UndoManagerObserver* observer) {
+ observers_.AddObserver(observer);
+}
+
+void UndoManager::RemoveObserver(UndoManagerObserver* observer) {
+ observers_.RemoveObserver(observer);
}
void UndoManager::Undo(bool* performing_indicator,
@@ -185,6 +196,13 @@ void UndoManager::Undo(bool* performing_indicator,
StartGroupingActions();
action->Undo();
EndGroupingActions();
+
+ NotifyOnUndoManagerStateChange();
+}
+
+void UndoManager::NotifyOnUndoManagerStateChange() {
+ FOR_EACH_OBSERVER(
+ UndoManagerObserver, observers_, OnUndoManagerStateChange());
}
void UndoManager::AddUndoGroup(UndoGroup* new_undo_group) {
@@ -197,6 +215,8 @@ void UndoManager::AddUndoGroup(UndoGroup* new_undo_group) {
// Limit the number of undo levels so the undo stack does not grow unbounded.
if (GetActiveUndoGroup()->size() > kMaxUndoGroups)
GetActiveUndoGroup()->erase(GetActiveUndoGroup()->begin());
+
+ NotifyOnUndoManagerStateChange();
}
ScopedVector<UndoGroup>* UndoManager::GetActiveUndoGroup() {
diff --git a/chrome/browser/undo/undo_manager.h b/chrome/browser/undo/undo_manager.h
index d05edc3..443d2d7 100644
--- a/chrome/browser/undo/undo_manager.h
+++ b/chrome/browser/undo/undo_manager.h
@@ -8,8 +8,10 @@
#include "base/basictypes.h"
#include "base/memory/scoped_ptr.h"
#include "base/memory/scoped_vector.h"
+#include "base/observer_list.h"
#include "base/strings/string16.h"
+class UndoManagerObserver;
class UndoOperation;
// UndoGroup ------------------------------------------------------------------
@@ -83,11 +85,18 @@ class UndoManager {
// suspension of undo tracking states are left unchanged.
void RemoveAllOperations();
+ // Observers are notified when the internal state of this class changes.
+ void AddObserver(UndoManagerObserver* observer);
+ void RemoveObserver(UndoManagerObserver* observer);
+
private:
void Undo(bool* performing_indicator,
ScopedVector<UndoGroup>* active_undo_group);
bool is_user_action() const { return !performing_undo_ && !performing_redo_; }
+ // Notifies the observers that the undo manager's state has changed.
+ void NotifyOnUndoManagerStateChange();
+
// Handle the addition of |new_undo_group| to the active undo group container.
void AddUndoGroup(UndoGroup* new_undo_group);
@@ -99,6 +108,9 @@ class UndoManager {
ScopedVector<UndoGroup> undo_actions_;
ScopedVector<UndoGroup> redo_actions_;
+ // The observers to notify when internal state changes.
+ ObserverList<UndoManagerObserver> observers_;
+
// Supports grouping operations into a single undo action.
int group_actions_count_;
diff --git a/chrome/browser/undo/undo_manager_observer.h b/chrome/browser/undo/undo_manager_observer.h
new file mode 100644
index 0000000..c61aea2
--- /dev/null
+++ b/chrome/browser/undo/undo_manager_observer.h
@@ -0,0 +1,18 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CHROME_BROWSER_UNDO_UNDO_MANAGER_OBSERVER_H_
+#define CHROME_BROWSER_UNDO_UNDO_MANAGER_OBSERVER_H_
+
+// Observer for the UndoManager.
+class UndoManagerObserver {
+ public:
+ // Invoked when the internal state of the UndoManager has changed.
+ virtual void OnUndoManagerStateChange() = 0;
+
+ protected:
+ virtual ~UndoManagerObserver() {}
+};
+
+#endif // CHROME_BROWSER_UNDO_UNDO_MANAGER_OBSERVER_H_
diff --git a/chrome/browser/undo/undo_manager_test.cc b/chrome/browser/undo/undo_manager_test.cc
index 70215d7..4ed7d49 100644
--- a/chrome/browser/undo/undo_manager_test.cc
+++ b/chrome/browser/undo/undo_manager_test.cc
@@ -4,6 +4,7 @@
#include "base/auto_reset.h"
#include "chrome/browser/undo/undo_manager.h"
+#include "chrome/browser/undo/undo_manager_observer.h"
#include "chrome/browser/undo/undo_operation.h"
#include "testing/gtest/include/gtest/gtest.h"
@@ -95,6 +96,22 @@ void TestUndoService::RecordUndoCall() {
++undo_operation_count_;
}
+// TestObserver ----------------------------------------------------------------
+
+class TestObserver : public UndoManagerObserver {
+ public:
+ TestObserver() : state_change_count_(0) {}
+ // Returns the number of state change callbacks
+ int state_change_count() { return state_change_count_; }
+
+ virtual void OnUndoManagerStateChange() OVERRIDE { ++state_change_count_; }
+
+ private:
+ int state_change_count_;
+
+ DISALLOW_COPY_AND_ASSIGN(TestObserver);
+};
+
// Tests -----------------------------------------------------------------------
TEST(UndoServiceTest, AddUndoActions) {
@@ -216,4 +233,34 @@ TEST(UndoServiceTest, GetAllUndoOperations) {
EXPECT_EQ(4U, all_operations.size());
}
+TEST(UndoServiceTest, ObserverCallbacks) {
+ TestObserver observer;
+ TestUndoService undo_service;
+ undo_service.undo_manager_.AddObserver(&observer);
+ EXPECT_EQ(0, observer.state_change_count());
+
+ undo_service.TriggerOperation();
+ EXPECT_EQ(1, observer.state_change_count());
+
+ undo_service.undo_manager_.StartGroupingActions();
+ undo_service.TriggerOperation();
+ undo_service.TriggerOperation();
+ undo_service.undo_manager_.EndGroupingActions();
+ EXPECT_EQ(2, observer.state_change_count());
+
+ // There should be at least 1 observer callback for undo.
+ undo_service.undo_manager_.Undo();
+ int callback_count_after_undo = observer.state_change_count();
+ EXPECT_GT(callback_count_after_undo, 2);
+
+ // There should be at least 1 observer callback for redo.
+ undo_service.undo_manager_.Redo();
+ int callback_count_after_redo = observer.state_change_count();
+ EXPECT_GT(callback_count_after_redo, callback_count_after_undo);
+
+ undo_service.undo_manager_.RemoveObserver(&observer);
+ undo_service.undo_manager_.Undo();
+ EXPECT_EQ(callback_count_after_redo, observer.state_change_count());
+}
+
} // namespace