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 15 namespace 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. 20 template <class ItemType> 21 class 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