summaryrefslogtreecommitdiffstats
path: root/ui/base
diff options
context:
space:
mode:
authorxiyuan@chromium.org <xiyuan@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2011-12-22 11:16:58 +0000
committerxiyuan@chromium.org <xiyuan@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2011-12-22 11:16:58 +0000
commit61af999511b96b3a9adffdb657f312771e8658e3 (patch)
tree8c27d4fb8ec795c887549f33d73b6531af0a1f51 /ui/base
parentc649d52d0c673eae23af01f266ae8c657d8e8fd7 (diff)
downloadchromium_src-61af999511b96b3a9adffdb657f312771e8658e3.zip
chromium_src-61af999511b96b3a9adffdb657f312771e8658e3.tar.gz
chromium_src-61af999511b96b3a9adffdb657f312771e8658e3.tar.bz2
[Aura] Implement views-based applist.
Implement a views-based applist behind "aura-views-applist" flag. BUG=98308,105913 TEST=Views-based app list should have no lag. Review URL: http://codereview.chromium.org/8890049 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@115515 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'ui/base')
-rw-r--r--ui/base/models/list_model.h116
-rw-r--r--ui/base/models/list_model_observer.h31
-rw-r--r--ui/base/models/list_model_unittest.cc149
3 files changed, 296 insertions, 0 deletions
diff --git a/ui/base/models/list_model.h b/ui/base/models/list_model.h
new file mode 100644
index 0000000..3634ed1
--- /dev/null
+++ b/ui/base/models/list_model.h
@@ -0,0 +1,116 @@
+// Copyright (c) 2011 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 UI_BASE_MODELS_LIST_MODEL_H_
+#define UI_BASE_MODELS_LIST_MODEL_H_
+#pragma once
+
+#include "base/basictypes.h"
+#include "base/logging.h"
+#include "base/observer_list.h"
+#include "base/memory/scoped_vector.h"
+#include "ui/base/models/list_model_observer.h"
+
+namespace ui {
+
+// A list model that manages a list of ItemType pointers. Items added to the
+// model are owned by the model. An item can be taken out of the model by
+// RemoveAt.
+template <class ItemType>
+class ListModel {
+ public:
+ typedef std::vector<ItemType*> Items;
+
+ ListModel() {}
+ virtual ~ListModel() {}
+
+ // Adds |item| to the model at given |index|.
+ virtual void AddAt(int index, ItemType* item) {
+ DCHECK(index >= 0 && index <= item_count());
+ items_->insert(items_.begin() + index, item);
+ NotifyItemsAdded(index, 1);
+ }
+
+ // Removes an item at given |index| from the model. Note the removed item
+ // is NOT deleted and it's up to the caller to delete it.
+ virtual ItemType* RemoveAt(int index) {
+ DCHECK(index >= 0 && index < item_count());
+ ItemType* item = items_[index];
+ items_->erase(items_.begin() + index);
+ NotifyItemsRemoved(index, 1);
+ return item;
+ }
+
+ // Removes all items from the model. This does NOT delete the items.
+ virtual void RemoveAll() {
+ int count = item_count();
+ items_->clear();
+ NotifyItemsRemoved(0, count);
+ }
+
+ // Removes an item at given |index| from the model and deletes it.
+ virtual void DeleteAt(int index) {
+ delete RemoveAt(index);
+ }
+
+ // Removes and deletes all items from the model.
+ virtual void DeleteAll() {
+ int count = item_count();
+ items_.reset();
+ NotifyItemsRemoved(0, count);
+ }
+
+ // Convenience function to append an item to the model.
+ void Add(ItemType* item) {
+ AddAt(item_count(), item);
+ }
+
+ void AddObserver(ListModelObserver* observer) {
+ observers_.AddObserver(observer);
+ }
+
+ void RemoveObserver(ListModelObserver* observer) {
+ observers_.RemoveObserver(observer);
+ }
+
+ void NotifyItemsAdded(int start, int count) {
+ FOR_EACH_OBSERVER(ListModelObserver,
+ observers_,
+ ListItemsAdded(start, count));
+ }
+
+ void NotifyItemsRemoved(int start, int count) {
+ FOR_EACH_OBSERVER(ListModelObserver,
+ observers_,
+ ListItemsRemoved(start, count));
+ }
+
+ void NotifyItemsChanged(int start, int count) {
+ FOR_EACH_OBSERVER(ListModelObserver,
+ observers_,
+ ListItemsChanged(start, count));
+ }
+
+ int item_count() const { return static_cast<int>(items_.size()); }
+ const Items& items() const { return items_.get(); }
+
+ const ItemType* item_at(int index) const {
+ DCHECK(index >= 0 && index < item_count());
+ return items_[index];
+ }
+ ItemType* item_at(int index) {
+ return const_cast<ItemType*>(
+ const_cast<const ListModel<ItemType>*>(this)->item_at(index));
+ }
+
+ private:
+ ScopedVector<ItemType> items_;
+ ObserverList<ListModelObserver> observers_;
+
+ DISALLOW_COPY_AND_ASSIGN(ListModel<ItemType>);
+};
+
+} // namespace ui
+
+#endif // UI_BASE_MODELS_LIST_MODEL_H_
diff --git a/ui/base/models/list_model_observer.h b/ui/base/models/list_model_observer.h
new file mode 100644
index 0000000..65b22a8
--- /dev/null
+++ b/ui/base/models/list_model_observer.h
@@ -0,0 +1,31 @@
+// Copyright (c) 2011 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 UI_BASE_MODELS_LIST_MODEL_OBSERVER_H_
+#define UI_BASE_MODELS_LIST_MODEL_OBSERVER_H_
+#pragma once
+
+#include "ui/base/ui_export.h"
+
+namespace ui {
+
+class UI_EXPORT ListModelObserver {
+ public:
+ // Invoked after items has been added to the model.
+ virtual void ListItemsAdded(int start, int count) = 0;
+
+ // Invoked after items has been removed. |start| is the index before the
+ // removal.
+ virtual void ListItemsRemoved(int start, int count) = 0;
+
+ // Invoked after items has been changed.
+ virtual void ListItemsChanged(int start, int count) = 0;
+
+ protected:
+ virtual ~ListModelObserver() {}
+};
+
+} // namespace ui
+
+#endif // UI_BASE_MODELS_LIST_MODEL_OBSERVER_H_
diff --git a/ui/base/models/list_model_unittest.cc b/ui/base/models/list_model_unittest.cc
new file mode 100644
index 0000000..1718431
--- /dev/null
+++ b/ui/base/models/list_model_unittest.cc
@@ -0,0 +1,149 @@
+// Copyright (c) 2011 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.
+
+#include "ui/base/models/list_model.h"
+
+#include "base/basictypes.h"
+#include "base/compiler_specific.h"
+#include "base/memory/scoped_ptr.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+namespace ui {
+
+class FooItem {
+ public:
+ explicit FooItem(int id) : id_(id) {}
+
+ int id() const { return id_; }
+
+ private:
+ int id_;
+ DISALLOW_COPY_AND_ASSIGN(FooItem);
+};
+
+class ListModelTest : public testing::Test,
+ public ListModelObserver {
+ public:
+ ListModelTest()
+ : added_count_(0),
+ removed_count_(0),
+ changed_count_(0) {
+ }
+
+ void ExpectCountsEqual(int added_count,
+ int removed_count,
+ int changed_count) {
+ EXPECT_EQ(added_count, added_count_);
+ EXPECT_EQ(removed_count, removed_count_);
+ EXPECT_EQ(changed_count, changed_count_);
+ }
+
+ void ClearCounts() {
+ added_count_ = removed_count_ = changed_count_ = 0;
+ }
+
+ // ListModelObserver implementation:
+ virtual void ListItemsAdded(int start, int count) OVERRIDE {
+ added_count_ += count;
+ }
+ virtual void ListItemsRemoved(int start, int count) OVERRIDE {
+ removed_count_ += count;
+ }
+ virtual void ListItemsChanged(int start, int count) OVERRIDE {
+ changed_count_ += count;
+ }
+
+ private:
+ int added_count_;
+ int removed_count_;
+ int changed_count_;
+
+ DISALLOW_COPY_AND_ASSIGN(ListModelTest);
+};
+
+TEST_F(ListModelTest, Add) {
+ ListModel<FooItem> model;
+ model.AddObserver(this);
+
+ // Append FooItem(0)
+ model.Add(new FooItem(0));
+ ExpectCountsEqual(1, 0, 0);
+
+ // Append FooItem(1)
+ model.Add(new FooItem(1));
+ ExpectCountsEqual(2, 0, 0);
+
+ // Insert FooItem(2) at position 0
+ model.AddAt(0, new FooItem(2));
+ ExpectCountsEqual(3, 0, 0);
+
+ // Total 3 items in mode.
+ EXPECT_EQ(3, model.item_count());
+
+ // First one should be FooItem(2), followed by FooItem(0) and FooItem(1)
+ EXPECT_EQ(2, model.item_at(0)->id());
+ EXPECT_EQ(0, model.item_at(1)->id());
+ EXPECT_EQ(1, model.item_at(2)->id());
+}
+
+TEST_F(ListModelTest, Remove) {
+ ListModel<FooItem> model;
+ model.AddObserver(this);
+
+ model.Add(new FooItem(0));
+ model.Add(new FooItem(1));
+ model.Add(new FooItem(2));
+
+ ClearCounts();
+
+ // Remove item at index 1 from model and release memory.
+ model.DeleteAt(1);
+ ExpectCountsEqual(0, 1, 0);
+
+ EXPECT_EQ(2, model.item_count());
+ EXPECT_EQ(0, model.item_at(0)->id());
+ EXPECT_EQ(2, model.item_at(1)->id());
+
+ // Remove all items from model and delete them.
+ model.DeleteAll();
+ ExpectCountsEqual(0, 3, 0);
+}
+
+TEST_F(ListModelTest, RemoveAll) {
+ ListModel<FooItem> model;
+ model.AddObserver(this);
+
+ scoped_ptr<FooItem> foo0(new FooItem(0));
+ scoped_ptr<FooItem> foo1(new FooItem(1));
+ scoped_ptr<FooItem> foo2(new FooItem(2));
+
+ model.Add(foo0.get());
+ model.Add(foo1.get());
+ model.Add(foo2.get());
+
+ ClearCounts();
+
+ // Remove all items and scoped_ptr above would release memory.
+ model.RemoveAll();
+ ExpectCountsEqual(0, 3, 0);
+}
+
+TEST_F(ListModelTest, FakeUpdate) {
+ ListModel<FooItem> model;
+ model.AddObserver(this);
+
+ model.Add(new FooItem(0));
+ model.Add(new FooItem(1));
+ model.Add(new FooItem(2));
+
+ ClearCounts();
+
+ model.NotifyItemsChanged(0, 1);
+ ExpectCountsEqual(0, 0, 1);
+
+ model.NotifyItemsChanged(1, 2);
+ ExpectCountsEqual(0, 0, 3);
+}
+
+} // namespace ui