app_list: Fix label misalignment after installation.
[chromium-blink-merge.git] / ui / app_list / views / app_list_main_view.cc
blobe966ec970295eabfc9205f939bbbec4002fe10ba
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/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"
23 namespace app_list {
25 namespace {
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;
33 } // namespace
35 ////////////////////////////////////////////////////////////////////////////////
36 // AppListMainView::IconLoader
38 class AppListMainView::IconLoader : public AppListItemModelObserver {
39 public:
40 IconLoader(AppListMainView* owner,
41 AppListItemModel* item,
42 ui::ScaleFactor scale_factor)
43 : owner_(owner),
44 item_(item) {
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);
55 private:
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 ////////////////////////////////////////////////////////////////////////////////
73 // AppListMainView:
75 AppListMainView::AppListMainView(AppListViewDelegate* delegate,
76 AppListModel* model,
77 PaginationModel* pagination_model,
78 views::View* anchor)
79 : delegate_(delegate),
80 model_(model),
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,
87 kInnerPadding,
88 kInnerPadding,
89 kInnerPadding));
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_);
99 #if defined(USE_AURA)
100 contents_view_->SetPaintToLayer(true);
101 contents_view_->SetFillsBoundsOpaquely(false);
102 contents_view_->layer()->SetMasksToBounds(true);
103 #endif
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();
116 GetWidget()->Show();
117 return;
120 if (icon_loading_wait_timer_.IsRunning())
121 return;
123 icon_loading_wait_timer_.Start(
124 FROM_HERE,
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))
159 continue;
161 pending_icon_loaders_.push_back(new IconLoader(this, item, scale_factor));
165 void AppListMainView::OnIconLoadingWaitTimer() {
166 GetWidget()->Show();
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();
177 GetWidget()->Show();
181 void AppListMainView::ActivateApp(AppListItemModel* item, int event_flags) {
182 if (delegate_)
183 delegate_->ActivateAppListItem(item, event_flags);
186 void AppListMainView::QueryChanged(SearchBoxView* sender) {
187 string16 query;
188 TrimWhitespace(model_->search_box()->text(), TRIM_ALL, &query);
189 bool should_show_search = !query.empty();
190 contents_view_->ShowSearchResults(should_show_search);
192 if (delegate_) {
193 if (should_show_search)
194 delegate_->StartSearch();
195 else
196 delegate_->StopSearch();
200 void AppListMainView::OpenResult(const SearchResult& result, int event_flags) {
201 if (delegate_)
202 delegate_->OpenSearchResult(result, event_flags);
205 void AppListMainView::InvokeResultAction(const SearchResult& result,
206 int action_index,
207 int event_flags) {
208 if (delegate_)
209 delegate_->InvokeSearchResultAction(result, action_index, event_flags);
212 } // namespace app_list