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