Update path of checkdeps to buildtools checkout
[chromium-blink-merge.git] / ui / app_list / views / app_list_main_view.cc
blobdcb57803c4acf6d55539b8c7838c12b0baa27f7b
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"
7 #include <algorithm>
9 #include "base/bind.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"
31 namespace app_list {
33 namespace {
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;
43 } // namespace
45 ////////////////////////////////////////////////////////////////////////////////
46 // AppListMainView::IconLoader
48 class AppListMainView::IconLoader : public AppListItemObserver {
49 public:
50 IconLoader(AppListMainView* owner,
51 AppListItem* item,
52 float scale)
53 : owner_(owner),
54 item_(item) {
55 item_->AddObserver(this);
57 // Triggers icon loading for given |scale_factor|.
58 item_->icon().GetRepresentation(scale);
61 virtual ~IconLoader() {
62 item_->RemoveObserver(this);
65 private:
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_;
77 AppListItem* item_;
79 DISALLOW_COPY_AND_ASSIGN(IconLoader);
82 ////////////////////////////////////////////////////////////////////////////////
83 // AppListMainView:
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),
92 contents_view_(NULL),
93 weak_ptr_factory_(this) {
94 // Starts icon loading early.
95 PreloadIcons(parent);
97 SetLayoutManager(new views::BoxLayout(views::BoxLayout::kVertical,
98 kInnerPadding,
99 kInnerPadding,
100 kInnerPadding));
102 search_box_view_ = new SearchBoxView(this, delegate);
103 AddChildView(search_box_view_);
104 AddContentsView();
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);
120 #endif
123 AppListMainView::~AppListMainView() {
124 pending_icon_loaders_.clear();
127 void AppListMainView::ShowAppListWhenReady() {
128 if (pending_icon_loaders_.empty()) {
129 icon_loading_wait_timer_.Stop();
130 GetWidget()->Show();
131 return;
134 if (icon_loading_wait_timer_.IsRunning())
135 return;
137 icon_loading_wait_timer_.Start(
138 FROM_HERE,
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
146 // search results.
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 */);
166 AddContentsView();
167 Layout();
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;
192 if (parent)
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))
209 continue;
211 pending_icon_loaders_.push_back(new IconLoader(this, item, scale_factor));
215 void AppListMainView::OnIconLoadingWaitTimer() {
216 GetWidget()->Show();
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();
227 GetWidget()->Show();
231 void AppListMainView::ChildVisibilityChanged(views::View* child) {
232 // Repaint the AppListView's background which will repaint the background for
233 // the search box.
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));
242 else
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();
260 else
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(
274 FROM_HERE,
275 base::Bind(&AppListMainView::QueryChanged,
276 weak_ptr_factory_.GetWeakPtr(),
277 search_box_view_));
280 } // namespace app_list