Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(273)

Side by Side Diff: ui/app_list/app_list_view.cc

Issue 11418312: app_list: Improve initial icon loading. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: rebase, stop timer when showing widget because no pending icon loads Created 8 years ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « ui/app_list/app_list_view.h ('k') | ui/app_list/apps_grid_view.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2012 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/app_list_view.h" 5 #include "ui/app_list/app_list_view.h"
6 6
7 #include <algorithm>
8
7 #include "base/string_util.h" 9 #include "base/string_util.h"
8 #include "ui/app_list/app_list_background.h" 10 #include "ui/app_list/app_list_background.h"
9 #include "ui/app_list/app_list_constants.h" 11 #include "ui/app_list/app_list_constants.h"
12 #include "ui/app_list/app_list_item_model.h"
10 #include "ui/app_list/app_list_item_view.h" 13 #include "ui/app_list/app_list_item_view.h"
11 #include "ui/app_list/app_list_model.h" 14 #include "ui/app_list/app_list_model.h"
12 #include "ui/app_list/app_list_view_delegate.h" 15 #include "ui/app_list/app_list_view_delegate.h"
13 #include "ui/app_list/contents_view.h" 16 #include "ui/app_list/contents_view.h"
14 #include "ui/app_list/pagination_model.h" 17 #include "ui/app_list/pagination_model.h"
15 #include "ui/app_list/search_box_model.h" 18 #include "ui/app_list/search_box_model.h"
16 #include "ui/app_list/search_box_view.h" 19 #include "ui/app_list/search_box_view.h"
17 #include "ui/base/events/event.h" 20 #include "ui/base/events/event.h"
18 #include "ui/gfx/insets.h" 21 #include "ui/gfx/insets.h"
19 #include "ui/gfx/path.h" 22 #include "ui/gfx/path.h"
20 #include "ui/gfx/skia_util.h" 23 #include "ui/gfx/skia_util.h"
21 #include "ui/views/bubble/bubble_frame_view.h" 24 #include "ui/views/bubble/bubble_frame_view.h"
22 #include "ui/views/controls/textfield/textfield.h" 25 #include "ui/views/controls/textfield/textfield.h"
23 #include "ui/views/layout/box_layout.h" 26 #include "ui/views/layout/box_layout.h"
24 #include "ui/views/widget/widget.h" 27 #include "ui/views/widget/widget.h"
25 28
26 namespace app_list { 29 namespace app_list {
27 30
28 namespace { 31 namespace {
29 32
30 // Inner padding space in pixels of bubble contents. 33 // Inner padding space in pixels of bubble contents.
31 const int kInnerPadding = 1; 34 const int kInnerPadding = 1;
32 35
33 // The distance between the arrow tip and edge of the anchor view. 36 // The distance between the arrow tip and edge of the anchor view.
34 const int kArrowOffset = 10; 37 const int kArrowOffset = 10;
35 38
39 // The maximum allowed time to wait for icon loading in milliseconds.
40 const int kMaxIconLoadingWaitTimeInMs = 50;
41
36 } // namespace 42 } // namespace
37 43
38 //////////////////////////////////////////////////////////////////////////////// 44 ////////////////////////////////////////////////////////////////////////////////
45 // AppListView::IconLoader
46
47 class AppListView::IconLoader : public AppListItemModelObserver {
48 public:
49 IconLoader(AppListView* owner,
50 AppListItemModel* item,
51 ui::ScaleFactor scale_factor)
52 : owner_(owner),
53 item_(item) {
54 item_->AddObserver(this);
55
56 // Triggers icon loading for given |scale_factor|.
57 item_->icon().GetRepresentation(scale_factor);
58 }
59
60 virtual ~IconLoader() {
61 item_->RemoveObserver(this);
62 }
63
64 private:
65 // AppListItemModelObserver overrides:
66 virtual void ItemIconChanged() OVERRIDE {
67 owner_->OnItemIconLoaded(this);
68 // Note that IconLoader is released here.
69 }
70 virtual void ItemTitleChanged() OVERRIDE {}
71 virtual void ItemHighlightedChanged() OVERRIDE {}
72
73 AppListView* owner_;
74 AppListItemModel* item_;
75
76 DISALLOW_COPY_AND_ASSIGN(IconLoader);
77 };
78
79 ////////////////////////////////////////////////////////////////////////////////
39 // AppListView: 80 // AppListView:
40 81
41 AppListView::AppListView(AppListViewDelegate* delegate) 82 AppListView::AppListView(AppListViewDelegate* delegate)
42 : delegate_(delegate), 83 : model_(new AppListModel),
84 delegate_(delegate),
43 search_box_view_(NULL), 85 search_box_view_(NULL),
44 contents_view_(NULL) { 86 contents_view_(NULL) {
87 if (delegate_)
88 delegate_->SetModel(model_.get());
45 } 89 }
46 90
47 AppListView::~AppListView() { 91 AppListView::~AppListView() {
48 // Deletes all child views while the models are still valid. 92 // Models are going away, ensure their references are cleared.
49 RemoveAllChildViews(true); 93 RemoveAllChildViews(true);
94 pending_icon_loaders_.clear();
50 } 95 }
51 96
52 void AppListView::InitAsBubble( 97 void AppListView::InitAsBubble(
53 gfx::NativeView parent, 98 gfx::NativeView parent,
54 PaginationModel* pagination_model, 99 PaginationModel* pagination_model,
55 views::View* anchor, 100 views::View* anchor,
56 const gfx::Point& anchor_point, 101 const gfx::Point& anchor_point,
57 views::BubbleBorder::ArrowLocation arrow_location) { 102 views::BubbleBorder::ArrowLocation arrow_location) {
103 // Starts icon loading early.
104 PreloadIcons(pagination_model, anchor);
105
58 SetLayoutManager(new views::BoxLayout(views::BoxLayout::kVertical, 106 SetLayoutManager(new views::BoxLayout(views::BoxLayout::kVertical,
59 kInnerPadding, 107 kInnerPadding,
60 kInnerPadding, 108 kInnerPadding,
61 kInnerPadding)); 109 kInnerPadding));
62 110
63 search_box_view_ = new SearchBoxView(this); 111 search_box_view_ = new SearchBoxView(this);
64 AddChildView(search_box_view_); 112 AddChildView(search_box_view_);
65 113
66 contents_view_ = new ContentsView(this, pagination_model); 114 contents_view_ = new ContentsView(this, pagination_model);
67 AddChildView(contents_view_); 115 AddChildView(contents_view_);
(...skipping 21 matching lines...) Expand all
89 contents_view_->SetPaintToLayer(true); 137 contents_view_->SetPaintToLayer(true);
90 contents_view_->SetFillsBoundsOpaquely(false); 138 contents_view_->SetFillsBoundsOpaquely(false);
91 contents_view_->layer()->SetMasksToBounds(true); 139 contents_view_->layer()->SetMasksToBounds(true);
92 set_background(NULL); 140 set_background(NULL);
93 #else 141 #else
94 set_background(new AppListBackground( 142 set_background(new AppListBackground(
95 GetBubbleFrameView()->bubble_border()->GetBorderCornerRadius(), 143 GetBubbleFrameView()->bubble_border()->GetBorderCornerRadius(),
96 search_box_view_)); 144 search_box_view_));
97 #endif 145 #endif
98 146
99 CreateModel(); 147 search_box_view_->SetModel(model_->search_box());
148 contents_view_->SetModel(model_.get());
100 } 149 }
101 150
102 void AppListView::SetBubbleArrowLocation( 151 void AppListView::SetBubbleArrowLocation(
103 views::BubbleBorder::ArrowLocation arrow_location) { 152 views::BubbleBorder::ArrowLocation arrow_location) {
104 GetBubbleFrameView()->bubble_border()->set_arrow_location(arrow_location); 153 GetBubbleFrameView()->bubble_border()->set_arrow_location(arrow_location);
105 SizeToContents(); // Recalcuates with new border. 154 SizeToContents(); // Recalcuates with new border.
106 GetBubbleFrameView()->SchedulePaint(); 155 GetBubbleFrameView()->SchedulePaint();
107 } 156 }
108 157
109 void AppListView::SetAnchorPoint(const gfx::Point& anchor_point) { 158 void AppListView::SetAnchorPoint(const gfx::Point& anchor_point) {
110 set_anchor_point(anchor_point); 159 set_anchor_point(anchor_point);
111 SizeToContents(); // Repositions view relative to the anchor. 160 SizeToContents(); // Repositions view relative to the anchor.
112 } 161 }
113 162
163 void AppListView::ShowWhenReady() {
164 if (pending_icon_loaders_.empty()) {
165 icon_loading_wait_timer_.Stop();
166 GetWidget()->Show();
167 return;
168 }
169
170 if (icon_loading_wait_timer_.IsRunning())
171 return;
172
173 icon_loading_wait_timer_.Start(
174 FROM_HERE,
175 base::TimeDelta::FromMilliseconds(kMaxIconLoadingWaitTimeInMs),
176 this, &AppListView::OnIconLoadingWaitTimer);
177 }
178
114 void AppListView::Close() { 179 void AppListView::Close() {
180 icon_loading_wait_timer_.Stop();
181
115 if (delegate_.get()) 182 if (delegate_.get())
116 delegate_->Close(); 183 delegate_->Close();
117 else 184 else
118 GetWidget()->Close(); 185 GetWidget()->Close();
119 } 186 }
120 187
121 void AppListView::UpdateBounds() { 188 void AppListView::UpdateBounds() {
122 SizeToContents(); 189 SizeToContents();
123 } 190 }
124 191
125 void AppListView::CreateModel() { 192 void AppListView::PreloadIcons(PaginationModel* pagination_model,
126 if (delegate_.get()) { 193 views::View* anchor) {
127 // Creates a new model and update all references before releasing old one. 194 ui::ScaleFactor scale_factor = ui::SCALE_FACTOR_100P;
128 scoped_ptr<AppListModel> new_model(new AppListModel); 195 if (anchor && anchor->GetWidget()) {
196 scale_factor = ui::GetScaleFactorForNativeView(
197 anchor->GetWidget()->GetNativeView());
198 }
129 199
130 delegate_->SetModel(new_model.get()); 200 // |pagination_model| could have -1 as the initial selected page and
131 search_box_view_->SetModel(new_model->search_box()); 201 // assumes first page (i.e. index 0) will be used in this case.
132 contents_view_->SetModel(new_model.get()); 202 const int selected_page = std::max(0, pagination_model->selected_page());
133 203
134 model_.reset(new_model.release()); 204 const int tiles_per_page = kPreferredCols * kPreferredRows;
205 const int start_model_index = selected_page * tiles_per_page;
206 const int end_model_index = std::min(
207 static_cast<int>(model_->apps()->item_count()),
208 start_model_index + tiles_per_page);
209
210 pending_icon_loaders_.clear();
211 for (int i = start_model_index; i < end_model_index; ++i) {
212 AppListItemModel* item = model_->apps()->GetItemAt(i);
213 if (item->icon().HasRepresentation(scale_factor))
214 continue;
215
216 pending_icon_loaders_.push_back(new IconLoader(this, item, scale_factor));
135 } 217 }
136 } 218 }
137 219
220 void AppListView::OnIconLoadingWaitTimer() {
221 GetWidget()->Show();
222 }
223
224 void AppListView::OnItemIconLoaded(IconLoader* loader) {
225 ScopedVector<IconLoader>::iterator it = std::find(
226 pending_icon_loaders_.begin(), pending_icon_loaders_.end(), loader);
227 DCHECK(it != pending_icon_loaders_.end());
228 pending_icon_loaders_.erase(it);
229
230 if (pending_icon_loaders_.empty() && icon_loading_wait_timer_.IsRunning()) {
231 icon_loading_wait_timer_.Stop();
232 GetWidget()->Show();
233 }
234 }
235
138 views::View* AppListView::GetInitiallyFocusedView() { 236 views::View* AppListView::GetInitiallyFocusedView() {
139 return search_box_view_->search_box(); 237 return search_box_view_->search_box();
140 } 238 }
141 239
142 bool AppListView::WidgetHasHitTestMask() const { 240 bool AppListView::WidgetHasHitTestMask() const {
143 return true; 241 return true;
144 } 242 }
145 243
146 void AppListView::GetWidgetHitTestMask(gfx::Path* mask) const { 244 void AppListView::GetWidgetHitTestMask(gfx::Path* mask) const {
147 DCHECK(mask); 245 DCHECK(mask);
(...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after
197 295
198 void AppListView::OnWidgetActivationChanged(views::Widget* widget, 296 void AppListView::OnWidgetActivationChanged(views::Widget* widget,
199 bool active) { 297 bool active) {
200 // Do not called inherited function as the bubble delegate auto close 298 // Do not called inherited function as the bubble delegate auto close
201 // functionality is not used. 299 // functionality is not used.
202 if (delegate_.get() && widget == GetWidget()) 300 if (delegate_.get() && widget == GetWidget())
203 delegate_->ViewActivationChanged(active); 301 delegate_->ViewActivationChanged(active);
204 } 302 }
205 303
206 } // namespace app_list 304 } // namespace app_list
OLDNEW
« no previous file with comments | « ui/app_list/app_list_view.h ('k') | ui/app_list/apps_grid_view.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698