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
3 // found in the LICENSE file.
5 #include "ui/app_list/views/app_list_main_view.h"
9 #include "base/string_util.h"
10 #include "ui/app_list/app_list_constants.h"
11 #include "ui/app_list/app_list_item_model.h"
12 #include "ui/app_list/app_list_model.h"
13 #include "ui/app_list/app_list_view_delegate.h"
14 #include "ui/app_list/pagination_model.h"
15 #include "ui/app_list/search_box_model.h"
16 #include "ui/app_list/views/app_list_item_view.h"
17 #include "ui/app_list/views/contents_view.h"
18 #include "ui/app_list/views/search_box_view.h"
19 #include "ui/views/controls/textfield/textfield.h"
20 #include "ui/views/layout/box_layout.h"
21 #include "ui/views/widget/widget.h"
27 // Inner padding space in pixels of bubble contents.
28 const int kInnerPadding
= 1;
30 // The maximum allowed time to wait for icon loading in milliseconds.
31 const int kMaxIconLoadingWaitTimeInMs
= 50;
35 ////////////////////////////////////////////////////////////////////////////////
36 // AppListMainView::IconLoader
38 class AppListMainView::IconLoader
: public AppListItemModelObserver
{
40 IconLoader(AppListMainView
* owner
,
41 AppListItemModel
* item
,
42 ui::ScaleFactor scale_factor
)
45 item_
->AddObserver(this);
47 // Triggers icon loading for given |scale_factor|.
48 item_
->icon().GetRepresentation(scale_factor
);
51 virtual ~IconLoader() {
52 item_
->RemoveObserver(this);
56 // AppListItemModelObserver overrides:
57 virtual void ItemIconChanged() OVERRIDE
{
58 owner_
->OnItemIconLoaded(this);
59 // Note that IconLoader is released here.
61 virtual void ItemTitleChanged() OVERRIDE
{}
62 virtual void ItemHighlightedChanged() OVERRIDE
{}
63 virtual void ItemIsInstallingChanged() OVERRIDE
{};
64 virtual void ItemPercentDownloadedChanged() OVERRIDE
{};
66 AppListMainView
* owner_
;
67 AppListItemModel
* item_
;
69 DISALLOW_COPY_AND_ASSIGN(IconLoader
);
72 ////////////////////////////////////////////////////////////////////////////////
75 AppListMainView::AppListMainView(AppListViewDelegate
* delegate
,
77 PaginationModel
* pagination_model
,
79 : delegate_(delegate
),
81 search_box_view_(NULL
),
82 contents_view_(NULL
) {
83 // Starts icon loading early.
84 PreloadIcons(pagination_model
, anchor
);
86 SetLayoutManager(new views::BoxLayout(views::BoxLayout::kVertical
,
91 search_box_view_
= new SearchBoxView(this, delegate
);
92 AddChildView(search_box_view_
);
94 contents_view_
= new ContentsView(this, pagination_model
);
95 AddChildView(contents_view_
);
97 search_box_view_
->set_contents_view(contents_view_
);
100 contents_view_
->SetPaintToLayer(true);
101 contents_view_
->SetFillsBoundsOpaquely(false);
102 contents_view_
->layer()->SetMasksToBounds(true);
105 search_box_view_
->SetModel(model_
->search_box());
106 contents_view_
->SetModel(model_
);
109 AppListMainView::~AppListMainView() {
110 pending_icon_loaders_
.clear();
113 void AppListMainView::ShowAppListWhenReady() {
114 if (pending_icon_loaders_
.empty()) {
115 icon_loading_wait_timer_
.Stop();
120 if (icon_loading_wait_timer_
.IsRunning())
123 icon_loading_wait_timer_
.Start(
125 base::TimeDelta::FromMilliseconds(kMaxIconLoadingWaitTimeInMs
),
126 this, &AppListMainView::OnIconLoadingWaitTimer
);
129 void AppListMainView::Close() {
130 icon_loading_wait_timer_
.Stop();
133 void AppListMainView::Prerender() {
134 contents_view_
->Prerender();
137 void AppListMainView::PreloadIcons(PaginationModel
* pagination_model
,
138 views::View
* anchor
) {
139 ui::ScaleFactor scale_factor
= ui::SCALE_FACTOR_100P
;
140 if (anchor
&& anchor
->GetWidget()) {
141 scale_factor
= ui::GetScaleFactorForNativeView(
142 anchor
->GetWidget()->GetNativeView());
145 // |pagination_model| could have -1 as the initial selected page and
146 // assumes first page (i.e. index 0) will be used in this case.
147 const int selected_page
= std::max(0, pagination_model
->selected_page());
149 const int tiles_per_page
= kPreferredCols
* kPreferredRows
;
150 const int start_model_index
= selected_page
* tiles_per_page
;
151 const int end_model_index
= std::min(
152 static_cast<int>(model_
->apps()->item_count()),
153 start_model_index
+ tiles_per_page
);
155 pending_icon_loaders_
.clear();
156 for (int i
= start_model_index
; i
< end_model_index
; ++i
) {
157 AppListItemModel
* item
= model_
->apps()->GetItemAt(i
);
158 if (item
->icon().HasRepresentation(scale_factor
))
161 pending_icon_loaders_
.push_back(new IconLoader(this, item
, scale_factor
));
165 void AppListMainView::OnIconLoadingWaitTimer() {
169 void AppListMainView::OnItemIconLoaded(IconLoader
* loader
) {
170 ScopedVector
<IconLoader
>::iterator it
= std::find(
171 pending_icon_loaders_
.begin(), pending_icon_loaders_
.end(), loader
);
172 DCHECK(it
!= pending_icon_loaders_
.end());
173 pending_icon_loaders_
.erase(it
);
175 if (pending_icon_loaders_
.empty() && icon_loading_wait_timer_
.IsRunning()) {
176 icon_loading_wait_timer_
.Stop();
181 void AppListMainView::ActivateApp(AppListItemModel
* item
, int event_flags
) {
183 delegate_
->ActivateAppListItem(item
, event_flags
);
186 void AppListMainView::QueryChanged(SearchBoxView
* sender
) {
188 TrimWhitespace(model_
->search_box()->text(), TRIM_ALL
, &query
);
189 bool should_show_search
= !query
.empty();
190 contents_view_
->ShowSearchResults(should_show_search
);
193 if (should_show_search
)
194 delegate_
->StartSearch();
196 delegate_
->StopSearch();
200 void AppListMainView::OpenResult(const SearchResult
& result
, int event_flags
) {
202 delegate_
->OpenSearchResult(result
, event_flags
);
205 void AppListMainView::InvokeResultAction(const SearchResult
& result
,
209 delegate_
->InvokeSearchResultAction(result
, action_index
, event_flags
);
212 } // namespace app_list