Chromium Code Reviews| 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..6a2f5cedc35ae5b6c0603285bda9756d213d6c72 100644 |
| --- a/chrome/browser/ui/views/tabs/tab.cc |
| +++ b/chrome/browser/ui/views/tabs/tab.cc |
| @@ -137,6 +137,63 @@ const int kImmersiveLoadingStepCount = 32; |
| const char kTabCloseButtonName[] = "TabCloseButton"; |
| const int kTabCloseButtonSize = 16; |
| +// Layer-backed view for updating a waiting or loading tab spinner. |
| +class ThrobberView : public views::View { |
| + public: |
| + ThrobberView(Tab* owner, const gfx::Rect& bounds) : owner_(owner) { |
| + SetPaintToLayer(true); |
|
danakj
2015/10/08 14:09:01
Can you leave a comment that this paints to separa
tapted
2015/10/09 06:39:02
Done.
|
| + SetFillsBoundsOpaquely(false); |
| + SetBoundsRect(bounds); |
| + owner_->AddChildView(this); |
| + } |
| + |
| + // views::View: |
| + 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(); |
| + |
| + // Paint network activity (aka throbber) animation frame. |
| + ui::ThemeProvider* tp = owner_->GetThemeProvider(); |
|
sky
2015/10/08 15:52:23
Do you really need owner_ here?
tapted
2015/10/09 06:39:02
Whoops - removed.
|
| + 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. |
|
danakj
2015/10/08 14:09:01
"Owns this" can be a bit ambiguous. "Owns |this|"?
tapted
2015/10/09 06:39:02
Done.
|
| + |
| + // 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 +469,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()), |
| @@ -552,9 +610,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 +844,8 @@ void Tab::Layout() { |
| favicon_bounds_.set_y(lb.y() + (lb.height() - gfx::kFaviconSize + 1) / 2); |
| MaybeAdjustLeftForPinnedTab(&favicon_bounds_); |
| } |
| + if (throbber_) |
| + throbber_->SetBoundsRect(favicon_bounds_); |
| showing_close_button_ = ShouldShowCloseBox(); |
| if (showing_close_button_) { |
| @@ -1347,28 +1406,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 +1425,35 @@ 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 { |
| + return; |
| + } |
| + |
| + const bool needs_throbber = state != TabRendererData::NETWORK_STATE_NONE; |
| + if (needs_throbber && !throbber_) { |
| + throbber_ = new ThrobberView(this, favicon_bounds_); |
| + ScheduleIconPaint(); // Repaint the icon area to not show the icon. |
| + } else if (!needs_throbber) { |
| + delete throbber_; |
|
sky
2015/10/08 15:52:23
I would hide the throbber when you don't need it r
tapted
2015/10/09 06:39:02
Done.
|
| + throbber_ = nullptr; |
| ScheduleIconPaint(); |
| } |
| + if (throbber_) |
| + throbber_->SchedulePaint(); |
| } |
| int Tab::IconCapacity() const { |