blob: 9b4440d9a020d2db41d8bfb7adade37fe2ec173e [file] [log] [blame]
// Copyright (c) 2012 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef UI_BASE_MODELS_LIST_MODEL_H_
#define UI_BASE_MODELS_LIST_MODEL_H_
#include "base/basictypes.h"
#include "base/logging.h"
#include "base/memory/scoped_vector.h"
#include "base/observer_list.h"
#include "ui/base/models/list_model_observer.h"
namespace ui {
// A list model that manages a list of ItemType pointers. Items added to the
// model are owned by the model. An item can be taken out of the model by
// RemoveAt.
template <class ItemType>
class ListModel {
public:
ListModel() {}
~ListModel() {}
// Adds |item| to the model at given |index|.
void AddAt(size_t index, ItemType* item) {
DCHECK_LE(index, item_count());
items_.insert(items_.begin() + index, item);
NotifyItemsAdded(index, 1);
}
// Convenience function to append an item to the model.
void Add(ItemType* item) {
AddAt(item_count(), item);
}
// Removes an item at given |index| from the model. Note the removed item
// is NOT deleted and it's up to the caller to delete it.
ItemType* RemoveAt(size_t index) {
DCHECK_LT(index, item_count());
ItemType* item = items_[index];
items_.weak_erase(items_.begin() + index);
NotifyItemsRemoved(index, 1);
return item;
}
// Removes all items from the model. This does NOT delete the items.
void RemoveAll() {
size_t count = item_count();
items_.weak_clear();
NotifyItemsRemoved(0, count);
}
// Removes an item at given |index| from the model and deletes it.
void DeleteAt(size_t index) {
delete RemoveAt(index);
}
// Removes and deletes all items from the model.
void DeleteAll() {
ScopedVector<ItemType> to_be_deleted(items_.Pass());
NotifyItemsRemoved(0, to_be_deleted.size());
}
// Moves the item at |index| to |target_index|. |target_index| is in terms
// of the model *after* the item at |index| is removed.
void Move(size_t index, size_t target_index) {
DCHECK_LT(index, item_count());
DCHECK_LT(target_index, item_count());
if (index == target_index)
return;
ItemType* item = items_[index];
items_.weak_erase(items_.begin() + index);
items_.insert(items_.begin() + target_index, item);
NotifyItemMoved(index, target_index);
}
void AddObserver(ListModelObserver* observer) {
observers_.AddObserver(observer);
}
void RemoveObserver(ListModelObserver* observer) {
observers_.RemoveObserver(observer);
}
void NotifyItemsAdded(size_t start, size_t count) {
FOR_EACH_OBSERVER(ListModelObserver,
observers_,
ListItemsAdded(start, count));
}
void NotifyItemsRemoved(size_t start, size_t count) {
FOR_EACH_OBSERVER(ListModelObserver,
observers_,
ListItemsRemoved(start, count));
}
void NotifyItemMoved(size_t index, size_t target_index) {
FOR_EACH_OBSERVER(ListModelObserver,
observers_,
ListItemMoved(index, target_index));
}
void NotifyItemsChanged(size_t start, size_t count) {
FOR_EACH_OBSERVER(ListModelObserver,
observers_,
ListItemsChanged(start, count));
}
size_t item_count() const { return items_.size(); }
const ItemType* GetItemAt(size_t index) const {
DCHECK_LT(index, item_count());
return items_[index];
}
ItemType* GetItemAt(size_t index) {
return const_cast<ItemType*>(
const_cast<const ListModel<ItemType>*>(this)->GetItemAt(index));
}
private:
ScopedVector<ItemType> items_;
ObserverList<ListModelObserver> observers_;
DISALLOW_COPY_AND_ASSIGN(ListModel<ItemType>);
};
} // namespace ui
#endif // UI_BASE_MODELS_LIST_MODEL_H_