#ifndef UI_BASE_MODELS_LIST_MODEL_H_
#define UI_BASE_MODELS_LIST_MODEL_H_
#include <stddef.h>
#include <memory>
#include <utility>
#include <vector>
#include "base/check_op.h"
#include "base/observer_list.h"
#include "ui/base/models/list_model_observer.h"
namespace ui {
template <class ItemType>
class ListModel {
public:
using ItemList = std::vector<std::unique_ptr<ItemType>>;
ListModel() {}
ListModel(const ListModel&) = delete;
ListModel& operator=(const ListModel&) = delete;
~ListModel() {}
ItemType* AddAt(size_t index, std::unique_ptr<ItemType> item) {
DCHECK_LE(index, item_count());
ItemType* item_ptr = item.get();
items_.insert(items_.begin() + index, std::move(item));
NotifyItemsAdded(index, 1);
return item_ptr;
}
ItemType* Add(std::unique_ptr<ItemType> item) {
return AddAt(item_count(), std::move(item));
}
std::unique_ptr<ItemType> RemoveAt(size_t index) {
DCHECK_LT(index, item_count());
std::unique_ptr<ItemType> item = std::move(items_[index]);
items_.erase(items_.begin() + index);
NotifyItemsRemoved(index, 1);
return item;
}
ItemList RemoveAll() {
ItemList result;
result.swap(items_);
NotifyItemsRemoved(0, result.size());
return result;
}
void DeleteAt(size_t index) {
std::unique_ptr<ItemType> item = RemoveAt(index);
}
void DeleteAll() {
ItemList to_be_deleted;
to_be_deleted.swap(items_);
NotifyItemsRemoved(0, to_be_deleted.size());
}
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;
std::unique_ptr<ItemType> item = std::move(items_[index]);
items_.erase(items_.begin() + index);
items_.insert(items_.begin() + target_index, std::move(item));
NotifyItemMoved(index, target_index);
}
void AddObserver(ListModelObserver* observer) const {
observers_.AddObserver(observer);
}
void RemoveObserver(ListModelObserver* observer) const {
observers_.RemoveObserver(observer);
}
void NotifyItemsAdded(size_t start, size_t count) {
observers_.Notify(&ListModelObserver::ListItemsAdded, start, count);
}
void NotifyItemsRemoved(size_t start, size_t count) {
observers_.Notify(&ListModelObserver::ListItemsRemoved, start, count);
}
void NotifyItemMoved(size_t index, size_t target_index) {
observers_.Notify(&ListModelObserver::ListItemMoved, index, target_index);
}
void NotifyItemsChanged(size_t start, size_t count) {
observers_.Notify(&ListModelObserver::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].get();
}
ItemType* GetItemAt(size_t index) {
return const_cast<ItemType*>(
const_cast<const ListModel<ItemType>*>(this)->GetItemAt(index));
}
typename ItemList::iterator begin() { return items_.begin(); }
typename ItemList::const_iterator begin() const { return items_.begin(); }
typename ItemList::iterator end() { return items_.end(); }
typename ItemList::const_iterator end() const { return items_.end(); }
private:
ItemList items_;
mutable base::ObserverList<ListModelObserver>::Unchecked observers_;
};
}
#endif