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

Unified 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 side-by-side diff with in-line comments
Download patch
« 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 »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: ui/app_list/app_list_view.cc
diff --git a/ui/app_list/app_list_view.cc b/ui/app_list/app_list_view.cc
index c4e4e3aa3b41ef2b0b8c2d8441adc089fc6d1254..2e07bcd3036f08b0170e961aa71b03de9cd87fac 100644
--- a/ui/app_list/app_list_view.cc
+++ b/ui/app_list/app_list_view.cc
@@ -4,9 +4,12 @@
#include "ui/app_list/app_list_view.h"
+#include <algorithm>
+
#include "base/string_util.h"
#include "ui/app_list/app_list_background.h"
#include "ui/app_list/app_list_constants.h"
+#include "ui/app_list/app_list_item_model.h"
#include "ui/app_list/app_list_item_view.h"
#include "ui/app_list/app_list_model.h"
#include "ui/app_list/app_list_view_delegate.h"
@@ -33,20 +36,62 @@ const int kInnerPadding = 1;
// The distance between the arrow tip and edge of the anchor view.
const int kArrowOffset = 10;
+// The maximum allowed time to wait for icon loading in milliseconds.
+const int kMaxIconLoadingWaitTimeInMs = 50;
+
} // namespace
////////////////////////////////////////////////////////////////////////////////
+// AppListView::IconLoader
+
+class AppListView::IconLoader : public AppListItemModelObserver {
+ public:
+ IconLoader(AppListView* owner,
+ AppListItemModel* item,
+ ui::ScaleFactor scale_factor)
+ : owner_(owner),
+ item_(item) {
+ item_->AddObserver(this);
+
+ // Triggers icon loading for given |scale_factor|.
+ item_->icon().GetRepresentation(scale_factor);
+ }
+
+ virtual ~IconLoader() {
+ item_->RemoveObserver(this);
+ }
+
+ private:
+ // AppListItemModelObserver overrides:
+ virtual void ItemIconChanged() OVERRIDE {
+ owner_->OnItemIconLoaded(this);
+ // Note that IconLoader is released here.
+ }
+ virtual void ItemTitleChanged() OVERRIDE {}
+ virtual void ItemHighlightedChanged() OVERRIDE {}
+
+ AppListView* owner_;
+ AppListItemModel* item_;
+
+ DISALLOW_COPY_AND_ASSIGN(IconLoader);
+};
+
+////////////////////////////////////////////////////////////////////////////////
// AppListView:
AppListView::AppListView(AppListViewDelegate* delegate)
- : delegate_(delegate),
+ : model_(new AppListModel),
+ delegate_(delegate),
search_box_view_(NULL),
contents_view_(NULL) {
+ if (delegate_)
+ delegate_->SetModel(model_.get());
}
AppListView::~AppListView() {
- // Deletes all child views while the models are still valid.
+ // Models are going away, ensure their references are cleared.
RemoveAllChildViews(true);
+ pending_icon_loaders_.clear();
}
void AppListView::InitAsBubble(
@@ -55,6 +100,9 @@ void AppListView::InitAsBubble(
views::View* anchor,
const gfx::Point& anchor_point,
views::BubbleBorder::ArrowLocation arrow_location) {
+ // Starts icon loading early.
+ PreloadIcons(pagination_model, anchor);
+
SetLayoutManager(new views::BoxLayout(views::BoxLayout::kVertical,
kInnerPadding,
kInnerPadding,
@@ -96,7 +144,8 @@ void AppListView::InitAsBubble(
search_box_view_));
#endif
- CreateModel();
+ search_box_view_->SetModel(model_->search_box());
+ contents_view_->SetModel(model_.get());
}
void AppListView::SetBubbleArrowLocation(
@@ -111,7 +160,25 @@ void AppListView::SetAnchorPoint(const gfx::Point& anchor_point) {
SizeToContents(); // Repositions view relative to the anchor.
}
+void AppListView::ShowWhenReady() {
+ if (pending_icon_loaders_.empty()) {
+ icon_loading_wait_timer_.Stop();
+ GetWidget()->Show();
+ return;
+ }
+
+ if (icon_loading_wait_timer_.IsRunning())
+ return;
+
+ icon_loading_wait_timer_.Start(
+ FROM_HERE,
+ base::TimeDelta::FromMilliseconds(kMaxIconLoadingWaitTimeInMs),
+ this, &AppListView::OnIconLoadingWaitTimer);
+}
+
void AppListView::Close() {
+ icon_loading_wait_timer_.Stop();
+
if (delegate_.get())
delegate_->Close();
else
@@ -122,16 +189,47 @@ void AppListView::UpdateBounds() {
SizeToContents();
}
-void AppListView::CreateModel() {
- if (delegate_.get()) {
- // Creates a new model and update all references before releasing old one.
- scoped_ptr<AppListModel> new_model(new AppListModel);
+void AppListView::PreloadIcons(PaginationModel* pagination_model,
+ views::View* anchor) {
+ ui::ScaleFactor scale_factor = ui::SCALE_FACTOR_100P;
+ if (anchor && anchor->GetWidget()) {
+ scale_factor = ui::GetScaleFactorForNativeView(
+ anchor->GetWidget()->GetNativeView());
+ }
+
+ // |pagination_model| could have -1 as the initial selected page and
+ // assumes first page (i.e. index 0) will be used in this case.
+ const int selected_page = std::max(0, pagination_model->selected_page());
+
+ const int tiles_per_page = kPreferredCols * kPreferredRows;
+ const int start_model_index = selected_page * tiles_per_page;
+ const int end_model_index = std::min(
+ static_cast<int>(model_->apps()->item_count()),
+ start_model_index + tiles_per_page);
+
+ pending_icon_loaders_.clear();
+ for (int i = start_model_index; i < end_model_index; ++i) {
+ AppListItemModel* item = model_->apps()->GetItemAt(i);
+ if (item->icon().HasRepresentation(scale_factor))
+ continue;
+
+ pending_icon_loaders_.push_back(new IconLoader(this, item, scale_factor));
+ }
+}
+
+void AppListView::OnIconLoadingWaitTimer() {
+ GetWidget()->Show();
+}
- delegate_->SetModel(new_model.get());
- search_box_view_->SetModel(new_model->search_box());
- contents_view_->SetModel(new_model.get());
+void AppListView::OnItemIconLoaded(IconLoader* loader) {
+ ScopedVector<IconLoader>::iterator it = std::find(
+ pending_icon_loaders_.begin(), pending_icon_loaders_.end(), loader);
+ DCHECK(it != pending_icon_loaders_.end());
+ pending_icon_loaders_.erase(it);
- model_.reset(new_model.release());
+ if (pending_icon_loaders_.empty() && icon_loading_wait_timer_.IsRunning()) {
+ icon_loading_wait_timer_.Stop();
+ GetWidget()->Show();
}
}
« 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