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