OLD | NEW |
1 // Copyright 2014 The Chromium Authors. All rights reserved. | 1 // Copyright 2014 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 "ui/app_list/views/start_page_view.h" | 5 #include "ui/app_list/views/start_page_view.h" |
6 | 6 |
7 #include "base/strings/utf_string_conversions.h" | 7 #include "base/strings/utf_string_conversions.h" |
8 #include "ui/app_list/app_list_constants.h" | 8 #include "ui/app_list/app_list_constants.h" |
9 #include "ui/app_list/app_list_item.h" | 9 #include "ui/app_list/app_list_item.h" |
10 #include "ui/app_list/app_list_model.h" | 10 #include "ui/app_list/app_list_model.h" |
11 #include "ui/app_list/app_list_view_delegate.h" | 11 #include "ui/app_list/app_list_view_delegate.h" |
12 #include "ui/app_list/search_result.h" | 12 #include "ui/app_list/search_result.h" |
13 #include "ui/app_list/views/all_apps_tile_item_view.h" | 13 #include "ui/app_list/views/all_apps_tile_item_view.h" |
14 #include "ui/app_list/views/app_list_main_view.h" | 14 #include "ui/app_list/views/app_list_main_view.h" |
15 #include "ui/app_list/views/contents_view.h" | 15 #include "ui/app_list/views/contents_view.h" |
16 #include "ui/app_list/views/search_box_view.h" | 16 #include "ui/app_list/views/search_box_view.h" |
17 #include "ui/app_list/views/search_result_list_view.h" | 17 #include "ui/app_list/views/search_result_container_view.h" |
18 #include "ui/app_list/views/search_result_tile_item_view.h" | 18 #include "ui/app_list/views/search_result_tile_item_view.h" |
19 #include "ui/app_list/views/tile_item_view.h" | 19 #include "ui/app_list/views/tile_item_view.h" |
20 #include "ui/gfx/canvas.h" | 20 #include "ui/gfx/canvas.h" |
21 #include "ui/views/background.h" | 21 #include "ui/views/background.h" |
22 #include "ui/views/controls/image_view.h" | 22 #include "ui/views/controls/image_view.h" |
23 #include "ui/views/controls/label.h" | 23 #include "ui/views/controls/label.h" |
24 #include "ui/views/controls/textfield/textfield.h" | 24 #include "ui/views/controls/textfield/textfield.h" |
25 #include "ui/views/layout/box_layout.h" | 25 #include "ui/views/layout/box_layout.h" |
26 #include "ui/views/widget/widget.h" | 26 #include "ui/views/widget/widget.h" |
27 | 27 |
(...skipping 28 matching lines...) Expand all Loading... |
56 gfx::Size GetPreferredSize() const override { return size_; } | 56 gfx::Size GetPreferredSize() const override { return size_; } |
57 | 57 |
58 private: | 58 private: |
59 gfx::Size size_; | 59 gfx::Size size_; |
60 | 60 |
61 DISALLOW_COPY_AND_ASSIGN(SearchBoxSpacerView); | 61 DISALLOW_COPY_AND_ASSIGN(SearchBoxSpacerView); |
62 }; | 62 }; |
63 | 63 |
64 } // namespace | 64 } // namespace |
65 | 65 |
| 66 // A container that holds the start page recommendation tiles and the all apps |
| 67 // tile. |
| 68 class StartPageView::StartPageTilesContainer |
| 69 : public SearchResultContainerView { |
| 70 public: |
| 71 explicit StartPageTilesContainer(AllAppsTileItemView* all_apps_button); |
| 72 ~StartPageTilesContainer() override; |
| 73 |
| 74 TileItemView* GetTileItemView(size_t index); |
| 75 |
| 76 const std::vector<SearchResultTileItemView*>& tile_views() const { |
| 77 return search_result_tile_views_; |
| 78 } |
| 79 |
| 80 AllAppsTileItemView* all_apps_button() { return all_apps_button_; } |
| 81 |
| 82 // Overridden from SearchResultContainerView: |
| 83 int Update() override; |
| 84 void UpdateSelectedIndex(int old_selected, int new_selected) override; |
| 85 void OnContainerSelected(bool from_bottom) override; |
| 86 |
| 87 private: |
| 88 std::vector<SearchResultTileItemView*> search_result_tile_views_; |
| 89 AllAppsTileItemView* all_apps_button_; |
| 90 |
| 91 DISALLOW_COPY_AND_ASSIGN(StartPageTilesContainer); |
| 92 }; |
| 93 |
| 94 StartPageView::StartPageTilesContainer::StartPageTilesContainer( |
| 95 AllAppsTileItemView* all_apps_button) |
| 96 : all_apps_button_(all_apps_button) { |
| 97 views::BoxLayout* tiles_layout_manager = |
| 98 new views::BoxLayout(views::BoxLayout::kHorizontal, 0, 0, kTileSpacing); |
| 99 tiles_layout_manager->set_main_axis_alignment( |
| 100 views::BoxLayout::MAIN_AXIS_ALIGNMENT_CENTER); |
| 101 SetLayoutManager(tiles_layout_manager); |
| 102 set_background( |
| 103 views::Background::CreateSolidBackground(kLabelBackgroundColor)); |
| 104 |
| 105 // Add SearchResultTileItemViews to the container. |
| 106 for (size_t i = 0; i < kNumStartPageTiles; ++i) { |
| 107 SearchResultTileItemView* tile_item = new SearchResultTileItemView(); |
| 108 AddChildView(tile_item); |
| 109 tile_item->SetParentBackgroundColor(kLabelBackgroundColor); |
| 110 search_result_tile_views_.push_back(tile_item); |
| 111 } |
| 112 |
| 113 // Also add a special "all apps" button to the end of the container. |
| 114 all_apps_button_->UpdateIcon(); |
| 115 all_apps_button_->SetParentBackgroundColor(kLabelBackgroundColor); |
| 116 AddChildView(all_apps_button_); |
| 117 } |
| 118 |
| 119 StartPageView::StartPageTilesContainer::~StartPageTilesContainer() { |
| 120 } |
| 121 |
| 122 TileItemView* StartPageView::StartPageTilesContainer::GetTileItemView( |
| 123 size_t index) { |
| 124 DCHECK_GT(kNumStartPageTiles + 1, index); |
| 125 if (index == kNumStartPageTiles) |
| 126 return all_apps_button_; |
| 127 |
| 128 return search_result_tile_views_[index]; |
| 129 } |
| 130 |
| 131 int StartPageView::StartPageTilesContainer::Update() { |
| 132 std::vector<SearchResult*> display_results = |
| 133 AppListModel::FilterSearchResultsByDisplayType( |
| 134 results(), SearchResult::DISPLAY_RECOMMENDATION, kNumStartPageTiles); |
| 135 |
| 136 // Update the tile item results. |
| 137 for (size_t i = 0; i < search_result_tile_views_.size(); ++i) { |
| 138 SearchResult* item = nullptr; |
| 139 if (i < display_results.size()) |
| 140 item = display_results[i]; |
| 141 search_result_tile_views_[i]->SetSearchResult(item); |
| 142 } |
| 143 |
| 144 Layout(); |
| 145 parent()->Layout(); |
| 146 // Add 1 to the results size to account for the all apps button. |
| 147 return display_results.size() + 1; |
| 148 } |
| 149 |
| 150 void StartPageView::StartPageTilesContainer::UpdateSelectedIndex( |
| 151 int old_selected, |
| 152 int new_selected) { |
| 153 if (old_selected >= 0) |
| 154 GetTileItemView(old_selected)->SetSelected(false); |
| 155 |
| 156 if (new_selected >= 0) |
| 157 GetTileItemView(new_selected)->SetSelected(true); |
| 158 } |
| 159 |
| 160 void StartPageView::StartPageTilesContainer::OnContainerSelected( |
| 161 bool from_bottom) { |
| 162 } |
| 163 |
| 164 //////////////////////////////////////////////////////////////////////////////// |
| 165 // StartPageView implementation: |
66 StartPageView::StartPageView(AppListMainView* app_list_main_view, | 166 StartPageView::StartPageView(AppListMainView* app_list_main_view, |
67 AppListViewDelegate* view_delegate) | 167 AppListViewDelegate* view_delegate) |
68 : app_list_main_view_(app_list_main_view), | 168 : app_list_main_view_(app_list_main_view), |
69 view_delegate_(view_delegate), | 169 view_delegate_(view_delegate), |
70 search_box_spacer_view_(new SearchBoxSpacerView( | 170 search_box_spacer_view_(new SearchBoxSpacerView( |
71 app_list_main_view->search_box_view()->GetPreferredSize())), | 171 app_list_main_view->search_box_view()->GetPreferredSize())), |
72 instant_container_(new views::View), | 172 instant_container_(new views::View), |
73 tiles_container_(new views::View) { | 173 tiles_container_(new StartPageTilesContainer(new AllAppsTileItemView( |
| 174 app_list_main_view_->contents_view(), |
| 175 view_delegate_->GetModel()->top_level_item_list()))) { |
74 // The view containing the start page WebContents and SearchBoxSpacerView. | 176 // The view containing the start page WebContents and SearchBoxSpacerView. |
75 InitInstantContainer(); | 177 InitInstantContainer(); |
76 AddChildView(instant_container_); | 178 AddChildView(instant_container_); |
77 | 179 |
78 // The view containing the start page tiles. | 180 // The view containing the start page tiles. |
79 InitTilesContainer(); | |
80 AddChildView(tiles_container_); | 181 AddChildView(tiles_container_); |
81 | 182 |
82 SetResults(view_delegate_->GetModel()->results()); | 183 tiles_container_->SetResults(view_delegate_->GetModel()->results()); |
83 Reset(); | 184 Reset(); |
84 } | 185 } |
85 | 186 |
86 StartPageView::~StartPageView() { | 187 StartPageView::~StartPageView() { |
87 } | 188 } |
88 | 189 |
89 void StartPageView::InitInstantContainer() { | 190 void StartPageView::InitInstantContainer() { |
90 views::BoxLayout* instant_layout_manager = new views::BoxLayout( | 191 views::BoxLayout* instant_layout_manager = new views::BoxLayout( |
91 views::BoxLayout::kVertical, 0, 0, kInstantContainerSpacing); | 192 views::BoxLayout::kVertical, 0, 0, kInstantContainerSpacing); |
92 instant_layout_manager->set_inside_border_insets( | 193 instant_layout_manager->set_inside_border_insets( |
93 gfx::Insets(0, 0, kSearchBoxAndTilesSpacing, 0)); | 194 gfx::Insets(0, 0, kSearchBoxAndTilesSpacing, 0)); |
94 instant_layout_manager->set_main_axis_alignment( | 195 instant_layout_manager->set_main_axis_alignment( |
95 views::BoxLayout::MAIN_AXIS_ALIGNMENT_END); | 196 views::BoxLayout::MAIN_AXIS_ALIGNMENT_END); |
96 instant_layout_manager->set_cross_axis_alignment( | 197 instant_layout_manager->set_cross_axis_alignment( |
97 views::BoxLayout::CROSS_AXIS_ALIGNMENT_CENTER); | 198 views::BoxLayout::CROSS_AXIS_ALIGNMENT_CENTER); |
98 instant_container_->SetLayoutManager(instant_layout_manager); | 199 instant_container_->SetLayoutManager(instant_layout_manager); |
99 | 200 |
100 views::View* web_view = view_delegate_->CreateStartPageWebView( | 201 views::View* web_view = view_delegate_->CreateStartPageWebView( |
101 gfx::Size(kWebViewWidth, kWebViewHeight)); | 202 gfx::Size(kWebViewWidth, kWebViewHeight)); |
102 if (web_view) { | 203 if (web_view) { |
103 web_view->SetFocusable(false); | 204 web_view->SetFocusable(false); |
104 instant_container_->AddChildView(web_view); | 205 instant_container_->AddChildView(web_view); |
105 } | 206 } |
106 | 207 |
107 instant_container_->AddChildView(search_box_spacer_view_); | 208 instant_container_->AddChildView(search_box_spacer_view_); |
108 } | 209 } |
109 | 210 |
110 void StartPageView::InitTilesContainer() { | |
111 views::BoxLayout* tiles_layout_manager = | |
112 new views::BoxLayout(views::BoxLayout::kHorizontal, 0, 0, kTileSpacing); | |
113 tiles_layout_manager->set_main_axis_alignment( | |
114 views::BoxLayout::MAIN_AXIS_ALIGNMENT_CENTER); | |
115 tiles_container_->SetLayoutManager(tiles_layout_manager); | |
116 tiles_container_->set_background( | |
117 views::Background::CreateSolidBackground(kLabelBackgroundColor)); | |
118 | |
119 // Add SearchResultTileItemViews to the container. | |
120 for (size_t i = 0; i < kNumStartPageTiles; ++i) { | |
121 SearchResultTileItemView* tile_item = new SearchResultTileItemView(); | |
122 tiles_container_->AddChildView(tile_item); | |
123 tile_item->SetParentBackgroundColor(kLabelBackgroundColor); | |
124 search_result_tile_views_.push_back(tile_item); | |
125 } | |
126 | |
127 // Also add a special "all apps" button to the end of the container. | |
128 all_apps_button_ = new AllAppsTileItemView( | |
129 app_list_main_view_->contents_view(), | |
130 view_delegate_->GetModel()->top_level_item_list()); | |
131 all_apps_button_->UpdateIcon(); | |
132 all_apps_button_->SetParentBackgroundColor(kLabelBackgroundColor); | |
133 tiles_container_->AddChildView(all_apps_button_); | |
134 } | |
135 | |
136 void StartPageView::Reset() { | 211 void StartPageView::Reset() { |
137 Update(); | 212 tiles_container_->Update(); |
138 } | 213 } |
139 | 214 |
140 void StartPageView::UpdateForTesting() { | 215 void StartPageView::UpdateForTesting() { |
141 Update(); | 216 tiles_container_->Update(); |
| 217 } |
| 218 |
| 219 const std::vector<SearchResultTileItemView*>& StartPageView::tile_views() |
| 220 const { |
| 221 return tiles_container_->tile_views(); |
142 } | 222 } |
143 | 223 |
144 TileItemView* StartPageView::all_apps_button() const { | 224 TileItemView* StartPageView::all_apps_button() const { |
145 return all_apps_button_; | 225 return tiles_container_->all_apps_button(); |
146 } | 226 } |
147 | 227 |
148 void StartPageView::OnShow() { | 228 void StartPageView::OnShow() { |
149 DCHECK(app_list_main_view_->contents_view()->ShouldShowCustomPageClickzone()); | 229 DCHECK(app_list_main_view_->contents_view()->ShouldShowCustomPageClickzone()); |
150 UpdateCustomPageClickzoneVisibility(); | 230 UpdateCustomPageClickzoneVisibility(); |
151 ClearSelectedIndex(); | 231 tiles_container_->ClearSelectedIndex(); |
152 } | 232 } |
153 | 233 |
154 void StartPageView::OnHide() { | 234 void StartPageView::OnHide() { |
155 DCHECK( | 235 DCHECK( |
156 !app_list_main_view_->contents_view()->ShouldShowCustomPageClickzone()); | 236 !app_list_main_view_->contents_view()->ShouldShowCustomPageClickzone()); |
157 UpdateCustomPageClickzoneVisibility(); | 237 UpdateCustomPageClickzoneVisibility(); |
158 } | 238 } |
159 | 239 |
160 void StartPageView::Layout() { | 240 void StartPageView::Layout() { |
161 gfx::Rect bounds(GetContentsBounds()); | 241 gfx::Rect bounds(GetContentsBounds()); |
162 bounds.set_height(instant_container_->GetHeightForWidth(bounds.width())); | 242 bounds.set_height(instant_container_->GetHeightForWidth(bounds.width())); |
163 instant_container_->SetBoundsRect(bounds); | 243 instant_container_->SetBoundsRect(bounds); |
164 | 244 |
165 // Tiles begin where the instant container ends. | 245 // Tiles begin where the instant container ends. |
166 bounds.set_y(bounds.bottom()); | 246 bounds.set_y(bounds.bottom()); |
167 bounds.set_height(tiles_container_->GetHeightForWidth(bounds.width())); | 247 bounds.set_height(tiles_container_->GetHeightForWidth(bounds.width())); |
168 tiles_container_->SetBoundsRect(bounds); | 248 tiles_container_->SetBoundsRect(bounds); |
169 } | 249 } |
170 | 250 |
171 bool StartPageView::OnKeyPressed(const ui::KeyEvent& event) { | 251 bool StartPageView::OnKeyPressed(const ui::KeyEvent& event) { |
172 if (selected_index() >= 0 && | 252 int selected_index = tiles_container_->selected_index(); |
173 tiles_container_->child_at(selected_index())->OnKeyPressed(event)) | 253 if (selected_index >= 0 && |
| 254 tiles_container_->child_at(selected_index)->OnKeyPressed(event)) |
174 return true; | 255 return true; |
175 | 256 |
176 int dir = 0; | 257 int dir = 0; |
177 switch (event.key_code()) { | 258 switch (event.key_code()) { |
178 case ui::VKEY_LEFT: | 259 case ui::VKEY_LEFT: |
179 dir = -1; | 260 dir = -1; |
180 break; | 261 break; |
181 case ui::VKEY_RIGHT: | 262 case ui::VKEY_RIGHT: |
182 dir = 1; | 263 dir = 1; |
183 break; | 264 break; |
184 case ui::VKEY_DOWN: | 265 case ui::VKEY_DOWN: |
185 // Down selects the first tile if nothing is selected. | 266 // Down selects the first tile if nothing is selected. |
186 if (!IsValidSelectionIndex(selected_index())) | 267 if (!tiles_container_->IsValidSelectionIndex(selected_index)) |
187 dir = 1; | 268 dir = 1; |
188 break; | 269 break; |
189 case ui::VKEY_TAB: | 270 case ui::VKEY_TAB: |
190 dir = event.IsShiftDown() ? -1 : 1; | 271 dir = event.IsShiftDown() ? -1 : 1; |
191 break; | 272 break; |
192 default: | 273 default: |
193 break; | 274 break; |
194 } | 275 } |
195 | 276 |
196 if (dir == 0) | 277 if (dir == 0) |
197 return false; | 278 return false; |
198 | 279 |
199 if (!IsValidSelectionIndex(selected_index())) { | 280 if (!tiles_container_->IsValidSelectionIndex(selected_index)) { |
200 SetSelectedIndex(dir == -1 ? num_results() - 1 : 0); | 281 tiles_container_->SetSelectedIndex( |
| 282 dir == -1 ? tiles_container_->num_results() - 1 : 0); |
201 return true; | 283 return true; |
202 } | 284 } |
203 | 285 |
204 int selection_index = selected_index() + dir; | 286 int selection_index = selected_index + dir; |
205 if (IsValidSelectionIndex(selection_index)) { | 287 if (tiles_container_->IsValidSelectionIndex(selection_index)) { |
206 SetSelectedIndex(selection_index); | 288 tiles_container_->SetSelectedIndex(selection_index); |
207 return true; | 289 return true; |
208 } | 290 } |
209 | 291 |
210 return false; | 292 return false; |
211 } | 293 } |
212 | 294 |
213 void StartPageView::OnContainerSelected(bool from_bottom) { | |
214 } | |
215 | |
216 gfx::Rect StartPageView::GetSearchBoxBounds() const { | 295 gfx::Rect StartPageView::GetSearchBoxBounds() const { |
217 return search_box_spacer_view_->bounds(); | 296 return search_box_spacer_view_->bounds(); |
218 } | 297 } |
219 | 298 |
220 void StartPageView::UpdateCustomPageClickzoneVisibility() { | 299 void StartPageView::UpdateCustomPageClickzoneVisibility() { |
221 // This can get called before InitWidgets(), so we cannot guarantee that | 300 // This can get called before InitWidgets(), so we cannot guarantee that |
222 // custom_page_clickzone_ will not be null. | 301 // custom_page_clickzone_ will not be null. |
223 views::Widget* custom_page_clickzone = | 302 views::Widget* custom_page_clickzone = |
224 app_list_main_view_->GetCustomPageClickzone(); | 303 app_list_main_view_->GetCustomPageClickzone(); |
225 if (!custom_page_clickzone) | 304 if (!custom_page_clickzone) |
226 return; | 305 return; |
227 | 306 |
228 if (app_list_main_view_->contents_view()->ShouldShowCustomPageClickzone()) { | 307 if (app_list_main_view_->contents_view()->ShouldShowCustomPageClickzone()) { |
229 custom_page_clickzone->ShowInactive(); | 308 custom_page_clickzone->ShowInactive(); |
230 return; | 309 return; |
231 } | 310 } |
232 | 311 |
233 custom_page_clickzone->Hide(); | 312 custom_page_clickzone->Hide(); |
234 } | 313 } |
235 | 314 |
236 int StartPageView::Update() { | |
237 std::vector<SearchResult*> display_results = | |
238 AppListModel::FilterSearchResultsByDisplayType( | |
239 results(), SearchResult::DISPLAY_RECOMMENDATION, kNumStartPageTiles); | |
240 | |
241 // Update the tile item results. | |
242 for (size_t i = 0; i < search_result_tile_views_.size(); ++i) { | |
243 SearchResult* item = NULL; | |
244 if (i < display_results.size()) | |
245 item = display_results[i]; | |
246 search_result_tile_views_[i]->SetSearchResult(item); | |
247 } | |
248 | |
249 tiles_container_->Layout(); | |
250 Layout(); | |
251 // Add 1 to the results size to account for the all apps button. | |
252 return display_results.size() + 1; | |
253 } | |
254 | |
255 void StartPageView::UpdateSelectedIndex(int old_selected, int new_selected) { | |
256 if (old_selected >= 0) | |
257 GetTileItemView(old_selected)->SetSelected(false); | |
258 | |
259 if (new_selected >= 0) | |
260 GetTileItemView(new_selected)->SetSelected(true); | |
261 } | |
262 | |
263 TileItemView* StartPageView::GetTileItemView(size_t index) { | 315 TileItemView* StartPageView::GetTileItemView(size_t index) { |
264 DCHECK_GT(kNumStartPageTiles + 1, index); | 316 return tiles_container_->GetTileItemView(index); |
265 if (index == kNumStartPageTiles) | |
266 return all_apps_button_; | |
267 | |
268 return search_result_tile_views_[index]; | |
269 } | 317 } |
270 | 318 |
271 } // namespace app_list | 319 } // namespace app_list |
OLD | NEW |