15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Copyright (c) 2012 The Chromium Authors. All rights reserved. 25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be 35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// found in the LICENSE file. 45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 55821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#ifndef UI_BASE_MODELS_LIST_MODEL_H_ 65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define UI_BASE_MODELS_LIST_MODEL_H_ 75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/basictypes.h" 95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/logging.h" 105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/memory/scoped_vector.h" 115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/observer_list.h" 125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ui/base/models/list_model_observer.h" 135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace ui { 155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// A list model that manages a list of ItemType pointers. Items added to the 175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// model are owned by the model. An item can be taken out of the model by 185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// RemoveAt. 195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)template <class ItemType> 205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class ListModel { 215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public: 225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ListModel() {} 235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ~ListModel() {} 245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Adds |item| to the model at given |index|. 265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) void AddAt(size_t index, ItemType* item) { 275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK_LE(index, item_count()); 285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) items_.insert(items_.begin() + index, item); 295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) NotifyItemsAdded(index, 1); 305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Convenience function to append an item to the model. 335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) void Add(ItemType* item) { 345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) AddAt(item_count(), item); 355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Removes an item at given |index| from the model. Note the removed item 385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // is NOT deleted and it's up to the caller to delete it. 395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ItemType* RemoveAt(size_t index) { 405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK_LT(index, item_count()); 415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ItemType* item = items_[index]; 425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) items_.weak_erase(items_.begin() + index); 435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) NotifyItemsRemoved(index, 1); 445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return item; 455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Removes all items from the model. This does NOT delete the items. 485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) void RemoveAll() { 495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) size_t count = item_count(); 505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) items_.weak_clear(); 515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) NotifyItemsRemoved(0, count); 525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Removes an item at given |index| from the model and deletes it. 555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) void DeleteAt(size_t index) { 565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) delete RemoveAt(index); 575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Removes and deletes all items from the model. 605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) void DeleteAll() { 615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ScopedVector<ItemType> to_be_deleted(items_.Pass()); 625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) NotifyItemsRemoved(0, to_be_deleted.size()); 635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Moves the item at |index| to |target_index|. |target_index| is in terms 665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // of the model *after* the item at |index| is removed. 675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) void Move(size_t index, size_t target_index) { 685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK_LT(index, item_count()); 695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK_LT(target_index, item_count()); 705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (index == target_index) 725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ItemType* item = items_[index]; 755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) items_.weak_erase(items_.begin() + index); 765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) items_.insert(items_.begin() + target_index, item); 775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) NotifyItemMoved(index, target_index); 785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) void AddObserver(ListModelObserver* observer) { 815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) observers_.AddObserver(observer); 825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) void RemoveObserver(ListModelObserver* observer) { 855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) observers_.RemoveObserver(observer); 865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) void NotifyItemsAdded(size_t start, size_t count) { 895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) FOR_EACH_OBSERVER(ListModelObserver, 905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) observers_, 915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ListItemsAdded(start, count)); 925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) void NotifyItemsRemoved(size_t start, size_t count) { 955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) FOR_EACH_OBSERVER(ListModelObserver, 965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) observers_, 975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ListItemsRemoved(start, count)); 985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) void NotifyItemMoved(size_t index, size_t target_index) { 1015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) FOR_EACH_OBSERVER(ListModelObserver, 1025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) observers_, 1035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ListItemMoved(index, target_index)); 1045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) void NotifyItemsChanged(size_t start, size_t count) { 1075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) FOR_EACH_OBSERVER(ListModelObserver, 1085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) observers_, 1095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ListItemsChanged(start, count)); 1105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) size_t item_count() const { return items_.size(); } 1135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const ItemType* GetItemAt(size_t index) const { 1155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK_LT(index, item_count()); 1165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return items_[index]; 1175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ItemType* GetItemAt(size_t index) { 1195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return const_cast<ItemType*>( 1205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const_cast<const ListModel<ItemType>*>(this)->GetItemAt(index)); 1215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) private: 1245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ScopedVector<ItemType> items_; 1255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ObserverList<ListModelObserver> observers_; 1265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DISALLOW_COPY_AND_ASSIGN(ListModel<ItemType>); 1285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}; 1295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} // namespace ui 1315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif // UI_BASE_MODELS_LIST_MODEL_H_ 133