OLD | NEW |
1 // Copyright 2013 The Chromium Authors. All rights reserved. | 1 // Copyright 2013 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "ash/common/shelf/shelf_model.h" | 5 #include "ash/common/shelf/shelf_model.h" |
6 | 6 |
7 #include <algorithm> | 7 #include <algorithm> |
8 | 8 |
| 9 #include "ash/common/shelf/shelf_item_delegate.h" |
9 #include "ash/common/shelf/shelf_model_observer.h" | 10 #include "ash/common/shelf/shelf_model_observer.h" |
10 | 11 |
11 namespace ash { | 12 namespace ash { |
12 | 13 |
13 namespace { | 14 namespace { |
14 | 15 |
15 int ShelfItemTypeToWeight(ShelfItemType type) { | 16 int ShelfItemTypeToWeight(ShelfItemType type) { |
16 switch (type) { | 17 switch (type) { |
17 case TYPE_APP_LIST: | 18 case TYPE_APP_LIST: |
18 // TODO(skuhne): If the app list item becomes movable again, this need | 19 // TODO(skuhne): If the app list item becomes movable again, this need |
(...skipping 23 matching lines...) Expand all Loading... |
42 bool CompareByWeight(const ShelfItem& a, const ShelfItem& b) { | 43 bool CompareByWeight(const ShelfItem& a, const ShelfItem& b) { |
43 return ShelfItemTypeToWeight(a.type) < ShelfItemTypeToWeight(b.type); | 44 return ShelfItemTypeToWeight(a.type) < ShelfItemTypeToWeight(b.type); |
44 } | 45 } |
45 | 46 |
46 } // namespace | 47 } // namespace |
47 | 48 |
48 ShelfModel::ShelfModel() : next_id_(1), status_(STATUS_NORMAL) {} | 49 ShelfModel::ShelfModel() : next_id_(1), status_(STATUS_NORMAL) {} |
49 | 50 |
50 ShelfModel::~ShelfModel() {} | 51 ShelfModel::~ShelfModel() {} |
51 | 52 |
| 53 void ShelfModel::DestroyItemDelegates() { |
| 54 // Some ShelfItemDelegates access this model in their destructors and hence |
| 55 // need early cleanup. |
| 56 id_to_item_delegate_map_.clear(); |
| 57 } |
| 58 |
52 int ShelfModel::Add(const ShelfItem& item) { | 59 int ShelfModel::Add(const ShelfItem& item) { |
53 return AddAt(items_.size(), item); | 60 return AddAt(items_.size(), item); |
54 } | 61 } |
55 | 62 |
56 int ShelfModel::AddAt(int index, const ShelfItem& item) { | 63 int ShelfModel::AddAt(int index, const ShelfItem& item) { |
57 index = ValidateInsertionIndex(item.type, index); | 64 index = ValidateInsertionIndex(item.type, index); |
58 items_.insert(items_.begin() + index, item); | 65 items_.insert(items_.begin() + index, item); |
59 items_[index].id = next_id_++; | 66 items_[index].id = next_id_++; |
60 FOR_EACH_OBSERVER(ShelfModelObserver, observers_, ShelfItemAdded(index)); | 67 FOR_EACH_OBSERVER(ShelfModelObserver, observers_, ShelfItemAdded(index)); |
61 return index; | 68 return index; |
62 } | 69 } |
63 | 70 |
64 void ShelfModel::RemoveItemAt(int index) { | 71 void ShelfModel::RemoveItemAt(int index) { |
65 DCHECK(index >= 0 && index < item_count()); | 72 DCHECK(index >= 0 && index < item_count()); |
66 // The app list and browser shortcut can't be removed. | 73 // The app list and browser shortcut can't be removed. |
67 DCHECK(items_[index].type != TYPE_APP_LIST && | 74 DCHECK(items_[index].type != TYPE_APP_LIST && |
68 items_[index].type != TYPE_BROWSER_SHORTCUT); | 75 items_[index].type != TYPE_BROWSER_SHORTCUT); |
69 ShelfID id = items_[index].id; | 76 ShelfID id = items_[index].id; |
70 items_.erase(items_.begin() + index); | 77 items_.erase(items_.begin() + index); |
| 78 RemoveShelfItemDelegate(id); |
| 79 // TODO(jamescook): Fold this into ShelfItemRemoved in existing observers. |
| 80 FOR_EACH_OBSERVER(ShelfModelObserver, observers_, |
| 81 OnSetShelfItemDelegate(id, nullptr)); |
71 FOR_EACH_OBSERVER(ShelfModelObserver, observers_, | 82 FOR_EACH_OBSERVER(ShelfModelObserver, observers_, |
72 ShelfItemRemoved(index, id)); | 83 ShelfItemRemoved(index, id)); |
73 } | 84 } |
74 | 85 |
75 void ShelfModel::Move(int index, int target_index) { | 86 void ShelfModel::Move(int index, int target_index) { |
76 if (index == target_index) | 87 if (index == target_index) |
77 return; | 88 return; |
78 // TODO: this needs to enforce valid ranges. | 89 // TODO: this needs to enforce valid ranges. |
79 ShelfItem item(items_[index]); | 90 ShelfItem item(items_[index]); |
80 items_.erase(items_.begin() + index); | 91 items_.erase(items_.begin() + index); |
(...skipping 63 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
144 } | 155 } |
145 | 156 |
146 int ShelfModel::FirstPanelIndex() const { | 157 int ShelfModel::FirstPanelIndex() const { |
147 ShelfItem weight_dummy; | 158 ShelfItem weight_dummy; |
148 weight_dummy.type = TYPE_APP_PANEL; | 159 weight_dummy.type = TYPE_APP_PANEL; |
149 return std::lower_bound(items_.begin(), items_.end(), weight_dummy, | 160 return std::lower_bound(items_.begin(), items_.end(), weight_dummy, |
150 CompareByWeight) - | 161 CompareByWeight) - |
151 items_.begin(); | 162 items_.begin(); |
152 } | 163 } |
153 | 164 |
| 165 void ShelfModel::SetShelfItemDelegate( |
| 166 ShelfID id, |
| 167 std::unique_ptr<ShelfItemDelegate> item_delegate) { |
| 168 // If another ShelfItemDelegate is already registered for |id|, we assume |
| 169 // that this request is replacing ShelfItemDelegate for |id| with |
| 170 // |item_delegate|. |
| 171 RemoveShelfItemDelegate(id); |
| 172 |
| 173 FOR_EACH_OBSERVER(ShelfModelObserver, observers_, |
| 174 OnSetShelfItemDelegate(id, item_delegate.get())); |
| 175 |
| 176 id_to_item_delegate_map_[id] = std::move(item_delegate); |
| 177 } |
| 178 |
| 179 ShelfItemDelegate* ShelfModel::GetShelfItemDelegate(ShelfID id) { |
| 180 if (id_to_item_delegate_map_.find(id) != id_to_item_delegate_map_.end()) |
| 181 return id_to_item_delegate_map_[id].get(); |
| 182 return nullptr; |
| 183 } |
| 184 |
154 void ShelfModel::AddObserver(ShelfModelObserver* observer) { | 185 void ShelfModel::AddObserver(ShelfModelObserver* observer) { |
155 observers_.AddObserver(observer); | 186 observers_.AddObserver(observer); |
156 } | 187 } |
157 | 188 |
158 void ShelfModel::RemoveObserver(ShelfModelObserver* observer) { | 189 void ShelfModel::RemoveObserver(ShelfModelObserver* observer) { |
159 observers_.RemoveObserver(observer); | 190 observers_.RemoveObserver(observer); |
160 } | 191 } |
161 | 192 |
162 int ShelfModel::ValidateInsertionIndex(ShelfItemType type, int index) const { | 193 int ShelfModel::ValidateInsertionIndex(ShelfItemType type, int index) const { |
163 DCHECK(index >= 0 && index <= item_count() + 1); | 194 DCHECK(index >= 0 && index <= item_count() + 1); |
164 | 195 |
165 // Clamp |index| to the allowed range for the type as determined by |weight|. | 196 // Clamp |index| to the allowed range for the type as determined by |weight|. |
166 ShelfItem weight_dummy; | 197 ShelfItem weight_dummy; |
167 weight_dummy.type = type; | 198 weight_dummy.type = type; |
168 index = std::max(std::lower_bound(items_.begin(), items_.end(), weight_dummy, | 199 index = std::max(std::lower_bound(items_.begin(), items_.end(), weight_dummy, |
169 CompareByWeight) - | 200 CompareByWeight) - |
170 items_.begin(), | 201 items_.begin(), |
171 static_cast<ShelfItems::difference_type>(index)); | 202 static_cast<ShelfItems::difference_type>(index)); |
172 index = std::min(std::upper_bound(items_.begin(), items_.end(), weight_dummy, | 203 index = std::min(std::upper_bound(items_.begin(), items_.end(), weight_dummy, |
173 CompareByWeight) - | 204 CompareByWeight) - |
174 items_.begin(), | 205 items_.begin(), |
175 static_cast<ShelfItems::difference_type>(index)); | 206 static_cast<ShelfItems::difference_type>(index)); |
176 | 207 |
177 return index; | 208 return index; |
178 } | 209 } |
179 | 210 |
| 211 void ShelfModel::RemoveShelfItemDelegate(ShelfID id) { |
| 212 if (id_to_item_delegate_map_.find(id) != id_to_item_delegate_map_.end()) |
| 213 id_to_item_delegate_map_.erase(id); |
| 214 } |
| 215 |
180 } // namespace ash | 216 } // namespace ash |
OLD | NEW |