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