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