- add sources.
[platform/framework/web/crosswalk.git] / src / ui / app_list / app_list_item_list.cc
1 // Copyright (c) 2013 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 #include "ui/app_list/app_list_item_list.h"
6
7 #include "ui/app_list/app_list_item_model.h"
8
9 namespace app_list {
10
11 AppListItemList::AppListItemList() {
12 }
13
14 AppListItemList::~AppListItemList() {
15 }
16
17 void AppListItemList::AddObserver(AppListItemListObserver* observer) {
18   observers_.AddObserver(observer);
19 }
20
21 void AppListItemList::RemoveObserver(AppListItemListObserver* observer) {
22   observers_.RemoveObserver(observer);
23 }
24
25 AppListItemModel* AppListItemList::FindItem(const std::string& id) {
26   for (size_t i = 0; i < app_list_items_.size(); ++i) {
27     AppListItemModel* item = app_list_items_[i];
28     if (item->id() == id)
29       return item;
30   }
31   return NULL;
32 }
33
34 size_t AppListItemList::AddItem(AppListItemModel* item) {
35   size_t index = GetItemSortOrderIndex(item);
36   app_list_items_.insert(app_list_items_.begin() + index, item);
37   FOR_EACH_OBSERVER(AppListItemListObserver,
38                     observers_,
39                     OnListItemAdded(index, item));
40   return index;
41 }
42
43 void AppListItemList::DeleteItem(const std::string& id) {
44   for (size_t i = 0; i < app_list_items_.size(); ++i) {
45     AppListItemModel* item = app_list_items_[i];
46     if (item->id() == id) {
47       DeleteItemAt(i);
48       break;
49     }
50   }
51 }
52
53 void AppListItemList::DeleteItemsByType(const char* type) {
54   for (int i = static_cast<int>(app_list_items_.size()) - 1;
55        i >= 0; --i) {
56     AppListItemModel* item = app_list_items_[i];
57     if (!type || item->GetAppType() == type)
58       DeleteItemAt(i);
59   }
60 }
61
62 void AppListItemList::MoveItem(size_t from_index, size_t to_index) {
63   DCHECK_LT(from_index, item_count());
64   DCHECK_LT(to_index, item_count());
65   if (from_index == to_index)
66     return;
67
68   AppListItemModel* target_item = app_list_items_[from_index];
69   app_list_items_.weak_erase(app_list_items_.begin() + from_index);
70   app_list_items_.insert(app_list_items_.begin() + to_index, target_item);
71
72   // Update position
73   AppListItemModel* prev = to_index > 0 ? app_list_items_[to_index - 1] : NULL;
74   AppListItemModel* next = to_index < app_list_items_.size() - 1 ?
75       app_list_items_[to_index + 1] : NULL;
76   CHECK_NE(prev, next);
77
78   // It is possible that items were added with the same ordinal. Rather than
79   // resolving a potentially complicated chain of conflicts, just set the
80   // ordinal before |next| (which will place it before both items).
81   if (prev && next && prev->position().Equals(next->position()))
82     prev = NULL;
83
84   VLOG(2) << "Move: " << target_item->position().ToDebugString()
85           << " Prev: " << (prev ? prev->position().ToDebugString() : "(none)")
86           << " Next: " << (next ? next->position().ToDebugString() : "(none)");
87   if (!prev)
88     target_item->set_position(next->position().CreateBefore());
89   else if (!next)
90     target_item->set_position(prev->position().CreateAfter());
91   else
92     target_item->set_position(prev->position().CreateBetween(next->position()));
93   FOR_EACH_OBSERVER(AppListItemListObserver,
94                     observers_,
95                     OnListItemMoved(from_index, to_index, target_item));
96 }
97
98 // AppListItemList private
99
100 void AppListItemList::DeleteItemAt(size_t index) {
101   DCHECK_LT(index, item_count());
102   AppListItemModel* item = app_list_items_[index];
103   app_list_items_.weak_erase(app_list_items_.begin() + index);
104   FOR_EACH_OBSERVER(AppListItemListObserver,
105                     observers_,
106                     OnListItemRemoved(index, item));
107   delete item;
108 }
109
110 size_t AppListItemList::GetItemSortOrderIndex(AppListItemModel* item) {
111   syncer::StringOrdinal position = item->position();
112   if (!position.IsValid()) {
113     size_t nitems = app_list_items_.size();
114     if (nitems == 0) {
115       position = syncer::StringOrdinal::CreateInitialOrdinal();
116     } else {
117       position = app_list_items_[nitems - 1]->position().CreateAfter();
118     }
119     item->set_position(position);
120     return nitems;
121   }
122   // Note: app_list_items_ is sorted by convention, but sorting is not enforced
123   // (items' positions might be changed outside this class).
124   size_t index = 0;
125   for (; index < app_list_items_.size(); ++index) {
126     if (position.LessThan(app_list_items_[index]->position()))
127       break;
128   }
129   return index;
130 }
131
132 }  // namespace app_list