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"
10 #include "base/callback.h"
11 #include "base/files/file_path.h"
12 #include "base/message_loop/message_loop.h"
13 #include "base/strings/string_util.h"
14 #include "ui/app_list/app_list_constants.h"
15 #include "ui/app_list/app_list_folder_item.h"
16 #include "ui/app_list/app_list_item.h"
17 #include "ui/app_list/app_list_model.h"
18 #include "ui/app_list/app_list_switches.h"
19 #include "ui/app_list/app_list_view_delegate.h"
20 #include "ui/app_list/pagination_model.h"
21 #include "ui/app_list/search_box_model.h"
22 #include "ui/app_list/views/app_list_item_view.h"
23 #include "ui/app_list/views/apps_container_view.h"
24 #include "ui/app_list/views/contents_switcher_view.h"
25 #include "ui/app_list/views/contents_view.h"
26 #include "ui/app_list/views/search_box_view.h"
27 #include "ui/views/controls/textfield/textfield.h"
28 #include "ui/views/layout/box_layout.h"
29 #include "ui/views/widget/widget.h"
35 // Inner padding space in pixels of bubble contents.
36 const int kInnerPadding
= 1;
38 // The maximum allowed time to wait for icon loading in milliseconds.
39 const int kMaxIconLoadingWaitTimeInMs
= 50;
41 const int kContentsViewIndex
= 1;
45 ////////////////////////////////////////////////////////////////////////////////
46 // AppListMainView::IconLoader
48 class AppListMainView::IconLoader
: public AppListItemObserver
{
50 IconLoader(AppListMainView
* owner
,
55 item_
->AddObserver(this);
57 // Triggers icon loading for given |scale_factor|.
58 item_
->icon().GetRepresentation(scale
);
61 virtual ~IconLoader() {
62 item_
->RemoveObserver(this);
66 // AppListItemObserver overrides:
67 virtual void ItemIconChanged() OVERRIDE
{
68 owner_
->OnItemIconLoaded(this);
69 // Note that IconLoader is released here.
71 virtual void ItemNameChanged() OVERRIDE
{}
72 virtual void ItemHighlightedChanged() OVERRIDE
{}
73 virtual void ItemIsInstallingChanged() OVERRIDE
{}
74 virtual void ItemPercentDownloadedChanged() OVERRIDE
{}
76 AppListMainView
* owner_
;
79 DISALLOW_COPY_AND_ASSIGN(IconLoader
);
82 ////////////////////////////////////////////////////////////////////////////////
85 AppListMainView::AppListMainView(AppListViewDelegate
* delegate
,
86 PaginationModel
* pagination_model
,
87 gfx::NativeView parent
)
88 : delegate_(delegate
),
89 pagination_model_(pagination_model
),
90 model_(delegate
->GetModel()),
91 search_box_view_(NULL
),
93 weak_ptr_factory_(this) {
94 // Starts icon loading early.
97 SetLayoutManager(new views::BoxLayout(views::BoxLayout::kVertical
,
102 search_box_view_
= new SearchBoxView(this, delegate
);
103 AddChildView(search_box_view_
);
105 if (app_list::switches::IsExperimentalAppListEnabled())
106 AddChildView(new ContentsSwitcherView(contents_view_
));
109 void AppListMainView::AddContentsView() {
110 contents_view_
= new ContentsView(
111 this, pagination_model_
, model_
, delegate_
);
112 AddChildViewAt(contents_view_
, kContentsViewIndex
);
114 search_box_view_
->set_contents_view(contents_view_
);
116 #if defined(USE_AURA)
117 contents_view_
->SetPaintToLayer(true);
118 contents_view_
->SetFillsBoundsOpaquely(false);
119 contents_view_
->layer()->SetMasksToBounds(true);
123 AppListMainView::~AppListMainView() {
124 pending_icon_loaders_
.clear();
127 void AppListMainView::ShowAppListWhenReady() {
128 if (pending_icon_loaders_
.empty()) {
129 icon_loading_wait_timer_
.Stop();
134 if (icon_loading_wait_timer_
.IsRunning())
137 icon_loading_wait_timer_
.Start(
139 base::TimeDelta::FromMilliseconds(kMaxIconLoadingWaitTimeInMs
),
140 this, &AppListMainView::OnIconLoadingWaitTimer
);
143 void AppListMainView::ResetForShow() {
144 contents_view_
->apps_container_view()->ResetForShowApps();
145 // We clear the search when hiding so when app list appears it is not showing
147 search_box_view_
->ClearSearch();
150 void AppListMainView::Close() {
151 icon_loading_wait_timer_
.Stop();
152 contents_view_
->CancelDrag();
155 void AppListMainView::Prerender() {
156 contents_view_
->Prerender();
159 void AppListMainView::ModelChanged() {
160 pending_icon_loaders_
.clear();
161 model_
= delegate_
->GetModel();
162 search_box_view_
->ModelChanged();
163 delete contents_view_
;
164 contents_view_
= NULL
;
165 pagination_model_
->SelectPage(0, false /* animate */);
170 void AppListMainView::OnContentsViewShowStateChanged() {
171 search_box_view_
->SetVisible(contents_view_
->show_state() !=
172 ContentsView::SHOW_START_PAGE
);
175 void AppListMainView::OnStartPageSearchButtonPressed() {
176 search_box_view_
->SetVisible(true);
177 search_box_view_
->search_box()->SetText(base::string16());
178 search_box_view_
->RequestFocus();
181 void AppListMainView::SetDragAndDropHostOfCurrentAppList(
182 ApplicationDragAndDropHost
* drag_and_drop_host
) {
183 contents_view_
->SetDragAndDropHostOfCurrentAppList(drag_and_drop_host
);
186 bool AppListMainView::ShouldCenterWindow() const {
187 return delegate_
->ShouldCenterWindow();
190 void AppListMainView::PreloadIcons(gfx::NativeView parent
) {
191 float scale_factor
= 1.0f
;
193 scale_factor
= ui::GetScaleFactorForNativeView(parent
);
195 // |pagination_model| could have -1 as the initial selected page and
196 // assumes first page (i.e. index 0) will be used in this case.
197 const int selected_page
= std::max(0, pagination_model_
->selected_page());
199 const int tiles_per_page
= kPreferredCols
* kPreferredRows
;
200 const int start_model_index
= selected_page
* tiles_per_page
;
201 const int end_model_index
=
202 std::min(static_cast<int>(model_
->top_level_item_list()->item_count()),
203 start_model_index
+ tiles_per_page
);
205 pending_icon_loaders_
.clear();
206 for (int i
= start_model_index
; i
< end_model_index
; ++i
) {
207 AppListItem
* item
= model_
->top_level_item_list()->item_at(i
);
208 if (item
->icon().HasRepresentation(scale_factor
))
211 pending_icon_loaders_
.push_back(new IconLoader(this, item
, scale_factor
));
215 void AppListMainView::OnIconLoadingWaitTimer() {
219 void AppListMainView::OnItemIconLoaded(IconLoader
* loader
) {
220 ScopedVector
<IconLoader
>::iterator it
= std::find(
221 pending_icon_loaders_
.begin(), pending_icon_loaders_
.end(), loader
);
222 DCHECK(it
!= pending_icon_loaders_
.end());
223 pending_icon_loaders_
.erase(it
);
225 if (pending_icon_loaders_
.empty() && icon_loading_wait_timer_
.IsRunning()) {
226 icon_loading_wait_timer_
.Stop();
231 void AppListMainView::ChildVisibilityChanged(views::View
* child
) {
232 // Repaint the AppListView's background which will repaint the background for
234 if (child
== search_box_view_
&& parent())
235 parent()->SchedulePaint();
238 void AppListMainView::ActivateApp(AppListItem
* item
, int event_flags
) {
239 // TODO(jennyz): Activate the folder via AppListModel notification.
240 if (item
->GetItemType() == AppListFolderItem::kItemType
)
241 contents_view_
->ShowFolderContent(static_cast<AppListFolderItem
*>(item
));
243 item
->Activate(event_flags
);
246 void AppListMainView::GetShortcutPathForApp(
247 const std::string
& app_id
,
248 const base::Callback
<void(const base::FilePath
&)>& callback
) {
249 delegate_
->GetShortcutPathForApp(app_id
, callback
);
252 void AppListMainView::QueryChanged(SearchBoxView
* sender
) {
253 base::string16 query
;
254 base::TrimWhitespace(model_
->search_box()->text(), base::TRIM_ALL
, &query
);
255 bool should_show_search
= !query
.empty();
256 contents_view_
->ShowSearchResults(should_show_search
);
258 if (should_show_search
)
259 delegate_
->StartSearch();
261 delegate_
->StopSearch();
264 void AppListMainView::OnResultInstalled(SearchResult
* result
) {
265 // Clears the search to show the apps grid. The last installed app
266 // should be highlighted and made visible already.
267 search_box_view_
->ClearSearch();
270 void AppListMainView::OnResultUninstalled(SearchResult
* result
) {
271 // Resubmit the query via a posted task so that all observers for the
272 // uninstall notification are notified.
273 base::MessageLoop::current()->PostTask(
275 base::Bind(&AppListMainView::QueryChanged
,
276 weak_ptr_factory_
.GetWeakPtr(),
280 } // namespace app_list