OLD | NEW |
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 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 | 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/app_list/app_list_model_view.h" | 5 #include "ash/app_list/app_list_model_view.h" |
6 | 6 |
7 #include "ash/app_list/app_list_item_view.h" | 7 #include "ash/app_list/app_list_item_view.h" |
8 #include "ash/app_list/app_list_model.h" | 8 #include "ash/app_list/app_list_model.h" |
9 #include "base/utf_string_conversions.h" | |
10 | 9 |
11 namespace ash { | 10 namespace ash { |
12 | 11 |
13 namespace { | 12 namespace { |
14 | 13 |
15 // Minimum label width. | 14 // Calculate preferred icon size for given |content_size| and |num_of_tiles|. |
16 const int kMinLabelWidth = 150; | 15 gfx::Size CalculateIconSize(const gfx::Size& content_size, int num_of_tiles) { |
17 | |
18 // Calculate preferred tile size for given |content_size| and |num_of_tiles|. | |
19 gfx::Size CalculateTileSize(const gfx::Size& content_size, int num_of_tiles) { | |
20 // Icon sizes to try. | 16 // Icon sizes to try. |
21 const int kIconSizes[] = { 64, 48, 32, 16 }; | 17 const int kIconSizes[] = { 64, 48, 32 }; |
22 | |
23 int tile_height = 0; | |
24 int tile_width = 0; | |
25 int rows = 0; | |
26 int cols = 0; | |
27 | 18 |
28 // Chooses the biggest icon size that could fit all tiles. | 19 // Chooses the biggest icon size that could fit all tiles. |
| 20 gfx::Size icon_size; |
29 for (size_t i = 0; i < arraysize(kIconSizes); ++i) { | 21 for (size_t i = 0; i < arraysize(kIconSizes); ++i) { |
30 int icon_size = kIconSizes[i]; | 22 icon_size.SetSize(kIconSizes[i], kIconSizes[i]); |
31 tile_height = icon_size + 2 * AppListItemView::kPadding; | 23 gfx::Size tile_size = AppListItemView::GetPreferredSizeForIconSize( |
32 tile_width = icon_size + std::min(kMinLabelWidth, icon_size * 2) + | 24 icon_size); |
33 2 * AppListItemView::kPadding; | |
34 | 25 |
35 rows = std::max(content_size.height() / tile_height, 1); | 26 int cols = std::max(content_size.width() / tile_size.width(), 1); |
36 cols = std::min(content_size.width() / tile_width, | 27 int rows = std::min(content_size.height() / tile_size.height(), |
37 (num_of_tiles - 1) / rows + 1); | 28 (num_of_tiles - 1) / cols + 1); |
38 if (rows * cols >= num_of_tiles) | 29 if (rows * cols >= num_of_tiles) |
39 break; | 30 break; |
40 } | 31 } |
41 | 32 |
42 if (rows && cols) { | 33 return icon_size; |
43 // Adjusts tile width to fit |content_size| as much as possible. | |
44 tile_width = std::max(tile_width, content_size.width() / cols); | |
45 return gfx::Size(tile_width, tile_height); | |
46 } | |
47 | |
48 return gfx::Size(); | |
49 } | 34 } |
50 | 35 |
51 } // namespace | 36 } // namespace |
52 | 37 |
53 AppListModelView::AppListModelView(views::ButtonListener* listener) | 38 AppListModelView::AppListModelView(views::ButtonListener* listener) |
54 : model_(NULL), | 39 : model_(NULL), |
55 listener_(listener), | 40 listener_(listener), |
56 selected_item_index_(-1), | 41 selected_item_index_(-1), |
57 items_per_col_(0) { | 42 items_per_row_(0) { |
58 set_focusable(true); | 43 set_focusable(true); |
59 } | 44 } |
60 | 45 |
61 AppListModelView::~AppListModelView() { | 46 AppListModelView::~AppListModelView() { |
62 if (model_) | 47 if (model_) |
63 model_->RemoveObserver(this); | 48 model_->RemoveObserver(this); |
64 } | 49 } |
65 | 50 |
66 void AppListModelView::SetModel(AppListModel* model) { | 51 void AppListModelView::SetModel(AppListModel* model) { |
67 DCHECK(model); | 52 DCHECK(model); |
(...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
111 GetItemViewAtIndex(selected_item_index_)->SetSelected(false); | 96 GetItemViewAtIndex(selected_item_index_)->SetSelected(false); |
112 | 97 |
113 if (index < 0 || index >= child_count()) { | 98 if (index < 0 || index >= child_count()) { |
114 selected_item_index_ = -1; | 99 selected_item_index_ = -1; |
115 } else { | 100 } else { |
116 selected_item_index_ = index; | 101 selected_item_index_ = index; |
117 GetItemViewAtIndex(selected_item_index_)->SetSelected(true); | 102 GetItemViewAtIndex(selected_item_index_)->SetSelected(true); |
118 } | 103 } |
119 } | 104 } |
120 | 105 |
121 int AppListModelView::SetTileIconSizeAndGetMaxWidth(int icon_dimension) { | |
122 gfx::Size icon_size(icon_dimension, icon_dimension); | |
123 int max_tile_width = 0; | |
124 for (int i = 0; i < child_count(); ++i) { | |
125 views::View* view = child_at(i); | |
126 static_cast<AppListItemView*>(view)->set_icon_size(icon_size); | |
127 gfx::Size preferred_size = view->GetPreferredSize(); | |
128 if (preferred_size.width() > max_tile_width) | |
129 max_tile_width = preferred_size.width(); | |
130 } | |
131 | |
132 return max_tile_width; | |
133 } | |
134 | |
135 void AppListModelView::Layout() { | 106 void AppListModelView::Layout() { |
136 gfx::Rect rect(GetContentsBounds()); | 107 gfx::Rect rect(GetContentsBounds()); |
137 if (rect.IsEmpty()) { | 108 if (rect.IsEmpty()) { |
138 items_per_col_ = 0; | 109 items_per_row_ = 0; |
139 return; | 110 return; |
140 } | 111 } |
141 | 112 |
142 // Gets |tile_size| based on content rect and number of tiles. | 113 // Gets |icon_size| based on content rect and number of tiles. |
143 gfx::Size tile_size = CalculateTileSize(rect.size(), child_count()); | 114 gfx::Size icon_size = CalculateIconSize(rect.size(), child_count()); |
144 items_per_col_ = rect.height() / tile_size.height(); | |
145 | 115 |
146 // Sets tile's icons size and caps tile width to the max tile width. | 116 gfx::Size tile_size = AppListItemView::GetPreferredSizeForIconSize(icon_size); |
147 int max_tile_width = SetTileIconSizeAndGetMaxWidth( | 117 int cols = std::max(rect.width() / tile_size.width(), 1); |
148 tile_size.height() - 2 * AppListItemView::kPadding); | 118 tile_size.set_width(rect.width() / cols); |
149 if (max_tile_width && tile_size.width() > max_tile_width) | 119 items_per_row_ = rect.width() / tile_size.width(); |
150 tile_size.set_width(max_tile_width); | |
151 | 120 |
152 // Layouts tiles. | 121 // Layouts items. |
153 int col_bottom = rect.bottom(); | 122 int right = rect.right(); |
154 gfx::Rect current_tile(rect.origin(), tile_size); | 123 gfx::Rect current_tile(rect.origin(), tile_size); |
155 for (int i = 0; i < child_count(); ++i) { | 124 for (int i = 0; i < child_count(); ++i) { |
156 views::View* view = child_at(i); | 125 views::View* view = child_at(i); |
| 126 static_cast<AppListItemView*>(view)->set_icon_size(icon_size); |
157 view->SetBoundsRect(current_tile); | 127 view->SetBoundsRect(current_tile); |
| 128 view->SetVisible(rect.Contains(current_tile)); |
158 | 129 |
159 current_tile.Offset(0, tile_size.height()); | 130 current_tile.Offset(tile_size.width(), 0); |
160 if (current_tile.bottom() >= col_bottom) { | 131 if (current_tile.right() > right) { |
161 current_tile.set_x(current_tile.x() + tile_size.width()); | 132 current_tile.set_x(rect.x()); |
162 current_tile.set_y(rect.y()); | 133 current_tile.set_y(current_tile.y() + tile_size.height()); |
163 } | 134 } |
164 } | 135 } |
165 } | 136 } |
166 | 137 |
167 bool AppListModelView::OnKeyPressed(const views::KeyEvent& event) { | 138 bool AppListModelView::OnKeyPressed(const views::KeyEvent& event) { |
168 bool handled = false; | 139 bool handled = false; |
169 if (selected_item_index_ >= 0) | 140 if (selected_item_index_ >= 0) |
170 handled = GetItemViewAtIndex(selected_item_index_)->OnKeyPressed(event); | 141 handled = GetItemViewAtIndex(selected_item_index_)->OnKeyPressed(event); |
171 | 142 |
172 if (!handled) { | 143 if (!handled) { |
173 switch (event.key_code()) { | 144 switch (event.key_code()) { |
174 case ui::VKEY_LEFT: | 145 case ui::VKEY_LEFT: |
175 SetSelectedItemByIndex(std::max(selected_item_index_ - items_per_col_, | 146 SetSelectedItemByIndex(std::max(selected_item_index_ - 1, 0)); |
| 147 return true; |
| 148 case ui::VKEY_RIGHT: |
| 149 SetSelectedItemByIndex(std::min(selected_item_index_ + 1, |
| 150 child_count() - 1)); |
| 151 return true; |
| 152 case ui::VKEY_UP: |
| 153 SetSelectedItemByIndex(std::max(selected_item_index_ - items_per_row_, |
176 0)); | 154 0)); |
177 return true; | 155 return true; |
178 case ui::VKEY_RIGHT: | 156 case ui::VKEY_DOWN: |
179 if (selected_item_index_ < 0) { | 157 if (selected_item_index_ < 0) { |
180 SetSelectedItemByIndex(0); | 158 SetSelectedItemByIndex(0); |
181 } else { | 159 } else { |
182 SetSelectedItemByIndex(std::min(selected_item_index_ + items_per_col_, | 160 SetSelectedItemByIndex(std::min(selected_item_index_ + items_per_row_, |
183 child_count() - 1)); | 161 child_count() - 1)); |
184 } | 162 } |
185 return true; | 163 return true; |
186 case ui::VKEY_UP: | |
187 SetSelectedItemByIndex(std::max(selected_item_index_ - 1, 0)); | |
188 return true; | |
189 case ui::VKEY_DOWN: | |
190 SetSelectedItemByIndex(std::min(selected_item_index_ + 1, | |
191 child_count() - 1)); | |
192 return true; | |
193 default: | 164 default: |
194 break; | 165 break; |
195 } | 166 } |
196 } | 167 } |
197 | 168 |
198 return handled; | 169 return handled; |
199 } | 170 } |
200 | 171 |
201 bool AppListModelView::OnKeyReleased(const views::KeyEvent& event) { | 172 bool AppListModelView::OnKeyReleased(const views::KeyEvent& event) { |
202 bool handled = false; | 173 bool handled = false; |
(...skipping 13 matching lines...) Expand all Loading... |
216 | 187 |
217 void AppListModelView::ListItemsRemoved(int start, int count) { | 188 void AppListModelView::ListItemsRemoved(int start, int count) { |
218 Update(); | 189 Update(); |
219 } | 190 } |
220 | 191 |
221 void AppListModelView::ListItemsChanged(int start, int count) { | 192 void AppListModelView::ListItemsChanged(int start, int count) { |
222 NOTREACHED(); | 193 NOTREACHED(); |
223 } | 194 } |
224 | 195 |
225 } // namespace ash | 196 } // namespace ash |
OLD | NEW |