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::Shutdown() { | |
54 // Some ShelfItemDelegates access this model in their destructors and hence | |
msw
2016/07/21 21:30:53
Would it be sufficient to inline this in the dtor?
James Cook
2016/07/22 01:20:07
I need to do this in an explicit cleanup pass from
msw
2016/07/22 01:49:51
It's not clear to me why this would need to happen
| |
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 (ItemIndexByID(id) == -1) | |
msw
2016/07/21 21:30:53
Is checking for the item index useful? Consider th
James Cook
2016/07/22 01:20:07
Done. I wonder if this could be related to the she
| |
181 return nullptr; | |
182 // Each ShelfItem has to have a ShelfItemDelegate. | |
183 DCHECK(id_to_item_delegate_map_.find(id) != id_to_item_delegate_map_.end()); | |
184 return id_to_item_delegate_map_[id].get(); | |
185 } | |
186 | |
154 void ShelfModel::AddObserver(ShelfModelObserver* observer) { | 187 void ShelfModel::AddObserver(ShelfModelObserver* observer) { |
155 observers_.AddObserver(observer); | 188 observers_.AddObserver(observer); |
156 } | 189 } |
157 | 190 |
158 void ShelfModel::RemoveObserver(ShelfModelObserver* observer) { | 191 void ShelfModel::RemoveObserver(ShelfModelObserver* observer) { |
159 observers_.RemoveObserver(observer); | 192 observers_.RemoveObserver(observer); |
160 } | 193 } |
161 | 194 |
162 int ShelfModel::ValidateInsertionIndex(ShelfItemType type, int index) const { | 195 int ShelfModel::ValidateInsertionIndex(ShelfItemType type, int index) const { |
163 DCHECK(index >= 0 && index <= item_count() + 1); | 196 DCHECK(index >= 0 && index <= item_count() + 1); |
164 | 197 |
165 // Clamp |index| to the allowed range for the type as determined by |weight|. | 198 // Clamp |index| to the allowed range for the type as determined by |weight|. |
166 ShelfItem weight_dummy; | 199 ShelfItem weight_dummy; |
167 weight_dummy.type = type; | 200 weight_dummy.type = type; |
168 index = std::max(std::lower_bound(items_.begin(), items_.end(), weight_dummy, | 201 index = std::max(std::lower_bound(items_.begin(), items_.end(), weight_dummy, |
169 CompareByWeight) - | 202 CompareByWeight) - |
170 items_.begin(), | 203 items_.begin(), |
171 static_cast<ShelfItems::difference_type>(index)); | 204 static_cast<ShelfItems::difference_type>(index)); |
172 index = std::min(std::upper_bound(items_.begin(), items_.end(), weight_dummy, | 205 index = std::min(std::upper_bound(items_.begin(), items_.end(), weight_dummy, |
173 CompareByWeight) - | 206 CompareByWeight) - |
174 items_.begin(), | 207 items_.begin(), |
175 static_cast<ShelfItems::difference_type>(index)); | 208 static_cast<ShelfItems::difference_type>(index)); |
176 | 209 |
177 return index; | 210 return index; |
178 } | 211 } |
179 | 212 |
213 void ShelfModel::RemoveShelfItemDelegate(ShelfID id) { | |
214 if (id_to_item_delegate_map_.find(id) != id_to_item_delegate_map_.end()) | |
215 id_to_item_delegate_map_.erase(id); | |
216 } | |
217 | |
180 } // namespace ash | 218 } // namespace ash |
OLD | NEW |