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

Unified Diff: chrome/browser/ui/views/tabs/tab.cc

Issue 1393193002: Paint tab-loading throbbers into a ui::Layer. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: cl format Created 5 years, 2 months 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 | « chrome/browser/ui/views/tabs/tab.h ('k') | chrome/browser/ui/views/tabs/tab_strip.h » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: chrome/browser/ui/views/tabs/tab.cc
diff --git a/chrome/browser/ui/views/tabs/tab.cc b/chrome/browser/ui/views/tabs/tab.cc
index 6d0d78ae342129de7cfe6e2eb8a11b18c20d701b..c828f1f42e515968c7d11840eec806832e05f77a 100644
--- a/chrome/browser/ui/views/tabs/tab.cc
+++ b/chrome/browser/ui/views/tabs/tab.cc
@@ -137,6 +137,65 @@ const int kImmersiveLoadingStepCount = 32;
const char kTabCloseButtonName[] = "TabCloseButton";
const int kTabCloseButtonSize = 16;
+// Layer-backed view for updating a waiting or loading tab spinner.
Peter Kasting 2015/10/09 08:03:23 Tiny nit: Please be consistent about using the wor
tapted 2015/10/09 11:00:31 Done.
+class ThrobberView : public views::View {
+ public:
+ explicit ThrobberView(Tab* owner) : owner_(owner) {
Peter Kasting 2015/10/09 08:03:24 Don't define any of these class methods inline; de
tapted 2015/10/09 11:00:31 Done.
+ // Since the throbber animates, paint to a separate layer do reduce repaint
Peter Kasting 2015/10/09 08:03:24 Nit: do -> to ? Maybe you want "can animate for a
tapted 2015/10/09 11:00:31 Done.
+ // overheads.
Peter Kasting 2015/10/09 08:03:23 Nit: overheads -> overhead
tapted 2015/10/09 11:00:31 Done.
+ SetPaintToLayer(true);
+ SetFillsBoundsOpaquely(false);
+ }
+
+ // views::View:
+ bool CanProcessEventsWithinSubtree() const override { return false; }
+
+ void OnPaint(gfx::Canvas* canvas) override {
+ const TabRendererData::NetworkState state = owner_->data().network_state;
+ if (state == TabRendererData::NETWORK_STATE_NONE)
+ return;
+
+ const gfx::Rect bounds = GetLocalBounds();
Peter Kasting 2015/10/09 08:03:23 Nit: Might as well define this just below |tp|, th
tapted 2015/10/09 11:00:31 Done.
+
+ // Paint network activity (aka throbber) animation frame.
Peter Kasting 2015/10/09 08:03:24 Nit: It's weird to say "aka throbber" in a class w
tapted 2015/10/09 11:00:31 Done.
+ ui::ThemeProvider* tp = GetThemeProvider();
+ if (state == TabRendererData::NETWORK_STATE_WAITING) {
+ if (waiting_start_time_ == base::TimeTicks())
+ waiting_start_time_ = base::TimeTicks::Now();
+
+ waiting_state_.elapsed_time =
+ base::TimeTicks::Now() - waiting_start_time_;
+ gfx::PaintThrobberWaiting(
+ canvas, bounds, tp->GetColor(ThemeProperties::COLOR_THROBBER_WAITING),
+ waiting_state_.elapsed_time);
+ } else {
+ if (loading_start_time_ == base::TimeTicks())
+ loading_start_time_ = base::TimeTicks::Now();
+
+ waiting_state_.color =
+ tp->GetColor(ThemeProperties::COLOR_THROBBER_WAITING);
+ gfx::PaintThrobberSpinningAfterWaiting(
+ canvas, bounds,
+ tp->GetColor(ThemeProperties::COLOR_THROBBER_SPINNING),
+ base::TimeTicks::Now() - loading_start_time_, &waiting_state_);
+ }
+ }
+
+ private:
+ Tab* owner_; // Weak. Owns |this|.
+
+ // The point in time when the tab icon was first painted in the waiting state.
+ base::TimeTicks waiting_start_time_;
+
+ // The point in time when the tab icon was first painted in the loading state.
+ base::TimeTicks loading_start_time_;
+
+ // Paint state for the throbber after the most recent waiting paint.
+ gfx::ThrobberWaitingState waiting_state_;
+
+ DISALLOW_COPY_AND_ASSIGN(ThrobberView);
+};
+
void DrawIconAtLocation(gfx::Canvas* canvas,
const gfx::ImageSkia& image,
int image_offset,
@@ -412,6 +471,7 @@ Tab::Tab(TabController* controller)
favicon_hiding_offset_(0),
immersive_loading_step_(0),
should_display_crashed_favicon_(false),
+ throbber_(nullptr),
media_indicator_button_(nullptr),
close_button_(nullptr),
title_(new views::Label()),
@@ -440,6 +500,9 @@ Tab::Tab(TabController* controller)
SetEventTargeter(
scoped_ptr<views::ViewTargeter>(new views::ViewTargeter(this)));
+ throbber_ = new ThrobberView(this);
+ AddChildView(throbber_);
+
media_indicator_button_ = new MediaIndicatorButton(this);
AddChildView(media_indicator_button_);
@@ -494,6 +557,7 @@ void Tab::SetData(const TabRendererData& data) {
return;
TabRendererData old(data_);
+ UpdateLoadingAnimation(data.network_state);
tapted 2015/10/09 06:39:02 I noticed the throbber would hang around with some
data_ = data;
base::string16 title = data_.title;
@@ -552,9 +616,8 @@ void Tab::UpdateLoadingAnimation(TabRendererData::NetworkState state) {
return;
}
- TabRendererData::NetworkState old_state = data_.network_state;
data_.network_state = state;
- AdvanceLoadingAnimation(old_state, state);
+ AdvanceLoadingAnimation(state);
}
void Tab::StartPulse() {
@@ -787,6 +850,7 @@ void Tab::Layout() {
favicon_bounds_.set_y(lb.y() + (lb.height() - gfx::kFaviconSize + 1) / 2);
MaybeAdjustLeftForPinnedTab(&favicon_bounds_);
}
+ throbber_->SetBoundsRect(favicon_bounds_);
showing_close_button_ = ShouldShowCloseBox();
if (showing_close_button_) {
@@ -1347,28 +1411,7 @@ void Tab::PaintIcon(gfx::Canvas* canvas) {
bounds.set_x(GetMirroredXForRect(bounds));
if (data().network_state != TabRendererData::NETWORK_STATE_NONE) {
- // Paint network activity (aka throbber) animation frame.
- ui::ThemeProvider* tp = GetThemeProvider();
- if (data().network_state == TabRendererData::NETWORK_STATE_WAITING) {
- if (waiting_start_time_ == base::TimeTicks())
- waiting_start_time_ = base::TimeTicks::Now();
-
- waiting_state_.elapsed_time =
- base::TimeTicks::Now() - waiting_start_time_;
- gfx::PaintThrobberWaiting(
- canvas, bounds, tp->GetColor(ThemeProperties::COLOR_THROBBER_WAITING),
- waiting_state_.elapsed_time);
- } else {
- if (loading_start_time_ == base::TimeTicks())
- loading_start_time_ = base::TimeTicks::Now();
-
- waiting_state_.color =
- tp->GetColor(ThemeProperties::COLOR_THROBBER_WAITING);
- gfx::PaintThrobberSpinningAfterWaiting(
- canvas, bounds,
- tp->GetColor(ThemeProperties::COLOR_THROBBER_SPINNING),
- base::TimeTicks::Now() - loading_start_time_, &waiting_state_);
- }
+ // Throbber will do its own painting.
} else if (should_display_crashed_favicon_) {
// Paint crash favicon.
ui::ResourceBundle& rb = ui::ResourceBundle::GetSharedInstance();
@@ -1387,27 +1430,37 @@ void Tab::PaintIcon(gfx::Canvas* canvas) {
}
}
-void Tab::AdvanceLoadingAnimation(TabRendererData::NetworkState old_state,
- TabRendererData::NetworkState state) {
- if (state == TabRendererData::NETWORK_STATE_WAITING) {
- // Waiting steps backwards.
- immersive_loading_step_ =
- (immersive_loading_step_ - 1 + kImmersiveLoadingStepCount) %
- kImmersiveLoadingStepCount;
- } else if (state == TabRendererData::NETWORK_STATE_LOADING) {
- immersive_loading_step_ = (immersive_loading_step_ + 1) %
- kImmersiveLoadingStepCount;
- } else {
- waiting_start_time_ = base::TimeTicks();
- loading_start_time_ = base::TimeTicks();
- waiting_state_ = gfx::ThrobberWaitingState();
- immersive_loading_step_ = 0;
- }
+void Tab::AdvanceLoadingAnimation(TabRendererData::NetworkState state) {
if (controller_->IsImmersiveStyle()) {
+ if (state == TabRendererData::NETWORK_STATE_WAITING) {
+ // Waiting steps backwards.
+ immersive_loading_step_ =
+ (immersive_loading_step_ - 1 + kImmersiveLoadingStepCount) %
+ kImmersiveLoadingStepCount;
+ } else if (state == TabRendererData::NETWORK_STATE_LOADING) {
+ immersive_loading_step_ =
+ (immersive_loading_step_ + 1) % kImmersiveLoadingStepCount;
+ } else {
+ immersive_loading_step_ = 0;
+ }
+
SchedulePaintInRect(GetImmersiveBarRect());
- } else {
- ScheduleIconPaint();
+ return;
+ }
+
+ // To ensure the throbber layer does not paint over stacked or dragged tabs,
+ // hide it when the favicon would be clipped out. Check for any clipping on
+ // the left since the shoulder of a dragged tab can still paint over the icon.
+ gfx::Rect clip = GetLocalBounds();
+ const bool needs_throbber = state != TabRendererData::NETWORK_STATE_NONE &&
+ controller_->ShouldPaintTab(this, &clip) &&
+ clip.x() == 0 && clip.Contains(favicon_bounds_);
+
+ if (needs_throbber != throbber_->visible()) {
+ ScheduleIconPaint(); // Repaint the icon area to update favicon visibility.
+ throbber_->SetVisible(needs_throbber);
Peter Kasting 2015/10/09 08:03:23 Nit: For clarity, you might want to reverse these
tapted 2015/10/09 11:00:31 Done.
}
+ throbber_->SchedulePaint();
}
int Tab::IconCapacity() const {
« no previous file with comments | « chrome/browser/ui/views/tabs/tab.h ('k') | chrome/browser/ui/views/tabs/tab_strip.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698