1// Copyright (c) 2012 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 UI_BASE_MODELS_LIST_MODEL_H_
6#define UI_BASE_MODELS_LIST_MODEL_H_
7
8#include "base/basictypes.h"
9#include "base/logging.h"
10#include "base/memory/scoped_ptr.h"
11#include "base/memory/scoped_vector.h"
12#include "base/observer_list.h"
13#include "ui/base/models/list_model_observer.h"
14
15namespace ui {
16
17// A list model that manages a list of ItemType pointers. Items added to the
18// model are owned by the model. An item can be taken out of the model by
19// RemoveAt.
20template <class ItemType>
21class ListModel {
22 public:
23  ListModel() {}
24  ~ListModel() {}
25
26  // Adds |item| at the |index| into |items_|. Takes ownership of |item|.
27  void AddAt(size_t index, ItemType* item) {
28    DCHECK_LE(index, item_count());
29    items_.insert(items_.begin() + index, item);
30    NotifyItemsAdded(index, 1);
31  }
32
33  // Convenience function to append an item to the model.
34  void Add(ItemType* item) {
35    AddAt(item_count(), item);
36  }
37
38  // Removes the item at |index| from |items_| without deleting it.
39  // Returns a scoped pointer containing the removed item.
40  scoped_ptr<ItemType> RemoveAt(size_t index) {
41    DCHECK_LT(index, item_count());
42    ItemType* item = items_[index];
43    items_.weak_erase(items_.begin() + index);
44    NotifyItemsRemoved(index, 1);
45    return make_scoped_ptr<ItemType>(item);
46  }
47
48  // Removes all items from the model. This does NOT delete the items.
49  void RemoveAll() {
50    size_t count = item_count();
51    items_.weak_clear();
52    NotifyItemsRemoved(0, count);
53  }
54
55  // Removes the item at |index| from |items_| and deletes it.
56  void DeleteAt(size_t index) {
57    scoped_ptr<ItemType> item = RemoveAt(index);
58    // |item| will be deleted on destruction.
59  }
60
61  // Removes and deletes all items from the model.
62  void DeleteAll() {
63    ScopedVector<ItemType> to_be_deleted(items_.Pass());
64    NotifyItemsRemoved(0, to_be_deleted.size());
65  }
66
67  // Moves the item at |index| to |target_index|. |target_index| is in terms
68  // of the model *after* the item at |index| is removed.
69  void Move(size_t index, size_t target_index) {
70    DCHECK_LT(index, item_count());
71    DCHECK_LT(target_index, item_count());
72
73    if (index == target_index)
74      return;
75
76    ItemType* item = items_[index];
77    items_.weak_erase(items_.begin() + index);
78    items_.insert(items_.begin() + target_index, item);
79    NotifyItemMoved(index, target_index);
80  }
81
82  void AddObserver(ListModelObserver* observer) {
83    observers_.AddObserver(observer);
84  }
85
86  void RemoveObserver(ListModelObserver* observer) {
87    observers_.RemoveObserver(observer);
88  }
89
90  void NotifyItemsAdded(size_t start, size_t count) {
91    FOR_EACH_OBSERVER(ListModelObserver,
92                      observers_,
93                      ListItemsAdded(start, count));
94  }
95
96  void NotifyItemsRemoved(size_t start, size_t count) {
97    FOR_EACH_OBSERVER(ListModelObserver,
98                      observers_,
99                      ListItemsRemoved(start, count));
100  }
101
102  void NotifyItemMoved(size_t index, size_t target_index) {
103    FOR_EACH_OBSERVER(ListModelObserver,
104                      observers_,
105                      ListItemMoved(index, target_index));
106  }
107
108  void NotifyItemsChanged(size_t start, size_t count) {
109    FOR_EACH_OBSERVER(ListModelObserver,
110                      observers_,
111                      ListItemsChanged(start, count));
112  }
113
114  size_t item_count() const { return items_.size(); }
115
116  const ItemType* GetItemAt(size_t index) const {
117    DCHECK_LT(index, item_count());
118    return items_[index];
119  }
120  ItemType* GetItemAt(size_t index) {
121    return const_cast<ItemType*>(
122        const_cast<const ListModel<ItemType>*>(this)->GetItemAt(index));
123  }
124
125 private:
126  ScopedVector<ItemType> items_;
127  ObserverList<ListModelObserver> observers_;
128
129  DISALLOW_COPY_AND_ASSIGN(ListModel<ItemType>);
130};
131
132}  // namespace ui
133
134#endif  // UI_BASE_MODELS_LIST_MODEL_H_
135