Chromium Code Reviews| OLD | NEW |
|---|---|
| 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 ~IconLoader() { | |
|
tfarina
2012/12/04 19:00:14
virtual
xiyuan
2012/12/04 19:50:38
Done.
| |
| 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 Loading... | |
| 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 GetWidget()->Show(); | |
| 166 return; | |
| 167 } | |
| 168 | |
| 169 icon_loading_wait_timer_.Start( | |
| 170 FROM_HERE, | |
| 171 base::TimeDelta::FromMilliseconds(kMaxIconLoadingWaitTimeInMs), | |
| 172 this, &AppListView::OnIconLoadingWaitTimer); | |
| 173 } | |
| 174 | |
| 114 void AppListView::Close() { | 175 void AppListView::Close() { |
| 115 if (delegate_.get()) | 176 if (delegate_.get()) |
| 116 delegate_->Close(); | 177 delegate_->Close(); |
| 117 else | 178 else |
| 118 GetWidget()->Close(); | 179 GetWidget()->Close(); |
| 119 } | 180 } |
| 120 | 181 |
| 121 void AppListView::UpdateBounds() { | 182 void AppListView::UpdateBounds() { |
| 122 SizeToContents(); | 183 SizeToContents(); |
| 123 } | 184 } |
| 124 | 185 |
| 125 void AppListView::CreateModel() { | 186 void AppListView::PreloadIcons(PaginationModel* pagination_model, |
| 126 if (delegate_.get()) { | 187 views::View* anchor) { |
| 127 // Creates a new model and update all references before releasing old one. | 188 ui::ScaleFactor scale_factor = ui::SCALE_FACTOR_100P; |
| 128 scoped_ptr<AppListModel> new_model(new AppListModel); | 189 if (anchor && anchor->GetWidget()) { |
| 190 scale_factor = ui::GetScaleFactorForNativeView( | |
| 191 anchor->GetWidget()->GetNativeView()); | |
| 192 } | |
| 129 | 193 |
| 130 delegate_->SetModel(new_model.get()); | 194 // |pagination_model| could have -1 as the initial selected page and |
| 131 search_box_view_->SetModel(new_model->search_box()); | 195 // assumes first page (i.e. index 0) will be used in this case. |
| 132 contents_view_->SetModel(new_model.get()); | 196 const int selected_page = std::max(0, pagination_model->selected_page()); |
| 133 | 197 |
| 134 model_.reset(new_model.release()); | 198 const int tiles_per_page = kPreferredCols * kPreferredRows; |
| 199 const int start_model_index = selected_page * tiles_per_page; | |
| 200 const int end_model_index = std::min( | |
| 201 static_cast<int>(model_->apps()->item_count()), | |
| 202 start_model_index + tiles_per_page); | |
| 203 | |
| 204 pending_icon_loaders_.clear(); | |
| 205 for (int i = start_model_index; i < end_model_index; ++i) { | |
| 206 AppListItemModel* item = model_->apps()->GetItemAt(i); | |
| 207 if (item->icon().HasRepresentation(scale_factor)) | |
| 208 continue; | |
| 209 | |
| 210 pending_icon_loaders_.push_back(new IconLoader(this, item, scale_factor)); | |
| 135 } | 211 } |
| 136 } | 212 } |
| 137 | 213 |
| 214 void AppListView::OnIconLoadingWaitTimer() { | |
| 215 GetWidget()->Show(); | |
| 216 } | |
| 217 | |
| 218 void AppListView::OnItemIconLoaded(IconLoader* loader) { | |
| 219 ScopedVector<IconLoader>::iterator it = std::find( | |
| 220 pending_icon_loaders_.begin(), pending_icon_loaders_.end(), loader); | |
| 221 CHECK(it != pending_icon_loaders_.end()); | |
| 222 pending_icon_loaders_.erase(it); | |
| 223 | |
| 224 if (pending_icon_loaders_.empty() && icon_loading_wait_timer_.IsRunning()) { | |
| 225 icon_loading_wait_timer_.Stop(); | |
| 226 GetWidget()->Show(); | |
| 227 } | |
| 228 } | |
| 229 | |
| 138 views::View* AppListView::GetInitiallyFocusedView() { | 230 views::View* AppListView::GetInitiallyFocusedView() { |
| 139 return search_box_view_->search_box(); | 231 return search_box_view_->search_box(); |
| 140 } | 232 } |
| 141 | 233 |
| 142 bool AppListView::WidgetHasHitTestMask() const { | 234 bool AppListView::WidgetHasHitTestMask() const { |
| 143 return true; | 235 return true; |
| 144 } | 236 } |
| 145 | 237 |
| 146 void AppListView::GetWidgetHitTestMask(gfx::Path* mask) const { | 238 void AppListView::GetWidgetHitTestMask(gfx::Path* mask) const { |
| 147 DCHECK(mask); | 239 DCHECK(mask); |
| (...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 197 | 289 |
| 198 void AppListView::OnWidgetActivationChanged(views::Widget* widget, | 290 void AppListView::OnWidgetActivationChanged(views::Widget* widget, |
| 199 bool active) { | 291 bool active) { |
| 200 // Do not called inherited function as the bubble delegate auto close | 292 // Do not called inherited function as the bubble delegate auto close |
| 201 // functionality is not used. | 293 // functionality is not used. |
| 202 if (delegate_.get() && widget == GetWidget()) | 294 if (delegate_.get() && widget == GetWidget()) |
| 203 delegate_->ViewActivationChanged(active); | 295 delegate_->ViewActivationChanged(active); |
| 204 } | 296 } |
| 205 | 297 |
| 206 } // namespace app_list | 298 } // namespace app_list |
| OLD | NEW |