diff options
author | erikchen@chromium.org <erikchen@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2014-04-15 21:14:22 +0000 |
---|---|---|
committer | erikchen@chromium.org <erikchen@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2014-04-15 21:14:22 +0000 |
commit | 0167050eca60c7994e810a002f465803863c8d0f (patch) | |
tree | 1fdcb63e55cefe247e4a294cd7a189034f60c16a /chrome/browser/undo | |
parent | 5f52cda2a110b3e722d25c240ae2d7ecaf32197d (diff) | |
download | chromium_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.cc | 20 | ||||
-rw-r--r-- | chrome/browser/undo/undo_manager.h | 12 | ||||
-rw-r--r-- | chrome/browser/undo/undo_manager_observer.h | 18 | ||||
-rw-r--r-- | chrome/browser/undo/undo_manager_test.cc | 47 |
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 |