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 fde98892ecf4e44523e02ef81c9d4da247d205dc..5dc68b249ed3ddac9435de17ae89a741ee7eb6b9 100644 |
| --- a/chrome/browser/ui/views/tabs/tab.cc |
| +++ b/chrome/browser/ui/views/tabs/tab.cc |
| @@ -465,6 +465,7 @@ Tab::Tab(TabController* controller) |
| tab_activated_with_last_gesture_begin_(false), |
| hover_controller_(this), |
| showing_icon_(false), |
| + showing_audio_indicator_(false), |
| showing_close_button_(false), |
| close_button_color_(0) { |
| InitTabResources(); |
| @@ -492,8 +493,6 @@ Tab::Tab(TabController* controller) |
| AddChildView(close_button_); |
| set_context_menu_controller(this); |
| - |
| - tab_audio_indicator_.reset(new TabAudioIndicator(this)); |
| } |
| Tab::~Tab() { |
| @@ -502,7 +501,6 @@ Tab::~Tab() { |
| void Tab::set_animation_container(ui::AnimationContainer* container) { |
| animation_container_ = container; |
| hover_controller_.SetAnimationContainer(container); |
| - tab_audio_indicator_->SetAnimationContainer(container); |
| } |
| bool Tab::IsActive() const { |
| @@ -556,8 +554,6 @@ void Tab::SetData(const TabRendererData& data) { |
| } |
| } |
| - tab_audio_indicator_->SetIsPlayingAudio(data_.AudioActive()); |
| - |
| DataChanged(old); |
| Layout(); |
| @@ -679,16 +675,6 @@ int Tab::GetImmersiveHeight() { |
| } |
| //////////////////////////////////////////////////////////////////////////////// |
| -// Tab, TabAudioIndicator::Delegate overrides: |
| - |
| -void Tab::ScheduleAudioIndicatorPaint() { |
| - // No need to schedule a paint if another animation is active. The other |
| - // animation will do its own scheduling. |
| - if (!icon_animation_) |
| - ScheduleIconPaint(); |
| -} |
| - |
| -//////////////////////////////////////////////////////////////////////////////// |
| // Tab, AnimationDelegate overrides: |
| void Tab::AnimationProgressed(const ui::Animation* animation) { |
| @@ -781,20 +767,7 @@ void Tab::Layout() { |
| int favicon_left = lb.x(); |
| favicon_bounds_.SetRect(favicon_left, favicon_top, |
| tab_icon_size(), tab_icon_size()); |
| - if (data().mini && width() < kMiniTabRendererAsNormalTabWidth) { |
| - // Adjust the location of the favicon when transitioning from a normal |
| - // tab to a mini-tab. |
| - int mini_delta = kMiniTabRendererAsNormalTabWidth - GetMiniWidth(); |
| - int ideal_delta = width() - GetMiniWidth(); |
| - if (ideal_delta < mini_delta) { |
| - int ideal_x = (GetMiniWidth() - tab_icon_size()) / 2; |
| - int x = favicon_bounds_.x() + static_cast<int>( |
| - (1 - static_cast<float>(ideal_delta) / |
| - static_cast<float>(mini_delta)) * |
| - (ideal_x - favicon_bounds_.x())); |
| - favicon_bounds_.set_x(x); |
| - } |
| - } |
| + MaybeAdjustLeftForMiniTab(&favicon_bounds_); |
| } else { |
| favicon_bounds_.SetRect(lb.x(), lb.y(), 0, 0); |
| } |
| @@ -831,6 +804,23 @@ void Tab::Layout() { |
| close_button_->SetVisible(false); |
| } |
| + showing_audio_indicator_ = ShouldShowAudioIndicator(); |
| + if (showing_audio_indicator_) { |
| + ui::ResourceBundle& rb = ui::ResourceBundle::GetSharedInstance(); |
| + gfx::ImageSkia audio_indicator_image( |
| + *rb.GetImageSkiaNamed(IDR_TAB_AUDIO_INDICATOR)); |
| + const int top = |
| + top_padding() + (content_height - audio_indicator_image.height()) / 2; |
| + const int right = showing_close_button_ ? |
|
sky
2013/09/16 23:47:19
Does this work when RTL?
miu
2013/09/19 02:37:11
Yes. All the layout code sets its bounds under th
|
| + close_button_->x() + close_button_->GetInsets().left() : lb.right(); |
| + const int left = std::max(lb.x(), right - audio_indicator_image.width()); |
| + audio_indicator_bounds_.SetRect(left, top, |
| + tab_icon_size(), tab_icon_size()); |
| + MaybeAdjustLeftForMiniTab(&audio_indicator_bounds_); |
| + } else { |
| + audio_indicator_bounds_.SetRect(lb.x(), lb.y(), 0, 0); |
| + } |
| + |
| const int title_text_offset = is_host_desktop_type_ash ? |
| kTitleTextOffsetYAsh : kTitleTextOffsetY; |
| int title_left = favicon_bounds_.right() + kFaviconTitleSpacing; |
| @@ -847,16 +837,19 @@ void Tab::Layout() { |
| title_top -= (text_height - minimum_size.height()) / 2; |
| int title_width; |
| - if (close_button_->visible()) { |
| + if (showing_audio_indicator_) { |
| + title_width = audio_indicator_bounds_.x() - kTitleCloseButtonSpacing - |
| + title_left; |
| + } else if (close_button_->visible()) { |
| // The close button has an empty border with some padding (see details |
| // above where the close-button's bounds is set). Allow the title to |
| // overlap the empty padding. |
| - title_width = std::max(close_button_->x() + |
| - close_button_->GetInsets().left() - |
| - kTitleCloseButtonSpacing - title_left, 0); |
| + title_width = close_button_->x() + close_button_->GetInsets().left() - |
| + kTitleCloseButtonSpacing - title_left; |
| } else { |
| - title_width = std::max(lb.width() - title_left, 0); |
| + title_width = lb.width() - title_left; |
| } |
| + title_width = std::max(title_width, 0); |
| title_bounds_.SetRect(title_left, title_top, title_width, font_height_); |
| } else { |
| title_bounds_.SetRect(title_left, title_top, 0, 0); |
| @@ -1077,6 +1070,17 @@ const gfx::Rect& Tab::GetIconBounds() const { |
| return favicon_bounds_; |
| } |
| +void Tab::MaybeAdjustLeftForMiniTab(gfx::Rect* bounds) const { |
| + if (!data().mini || width() >= kMiniTabRendererAsNormalTabWidth) |
| + return; |
| + const int mini_delta = kMiniTabRendererAsNormalTabWidth - GetMiniWidth(); |
| + const int ideal_delta = width() - GetMiniWidth(); |
| + const int ideal_x = (GetMiniWidth() - bounds->width()) / 2; |
| + bounds->set_x(bounds->x() + static_cast<int>( |
|
sky
2013/09/16 23:47:19
Wasn't the old code conditionally doing this? (789
miu
2013/09/19 02:37:11
Sort of. Yes, there was an "if (ideal_delta < min
|
| + (1 - static_cast<float>(ideal_delta) / static_cast<float>(mini_delta)) * |
| + (ideal_x - bounds->x()))); |
| +} |
| + |
| void Tab::DataChanged(const TabRendererData& old) { |
| if (data().blocked == old.blocked) |
| return; |
| @@ -1090,9 +1094,13 @@ void Tab::DataChanged(const TabRendererData& old) { |
| void Tab::PaintTab(gfx::Canvas* canvas) { |
| // See if the model changes whether the icons should be painted. |
| const bool show_icon = ShouldShowIcon(); |
| + const bool show_audio_indicator = ShouldShowAudioIndicator(); |
| const bool show_close_button = ShouldShowCloseBox(); |
| - if (show_icon != showing_icon_ || show_close_button != showing_close_button_) |
| + if (show_icon != showing_icon_ || |
| + show_audio_indicator != showing_audio_indicator_ || |
| + show_close_button != showing_close_button_) { |
| Layout(); |
| + } |
| PaintTabBackground(canvas); |
| @@ -1107,6 +1115,9 @@ void Tab::PaintTab(gfx::Canvas* canvas) { |
| if (show_icon) |
| PaintIcon(canvas); |
| + if (show_audio_indicator) |
| + PaintAudioIndicator(canvas); |
| + |
| // If the close button color has changed, generate a new one. |
| if (!close_button_color_ || title_color != close_button_color_) { |
| close_button_color_ = title_color; |
| @@ -1457,13 +1468,6 @@ void Tab::PaintIcon(gfx::Canvas* canvas) { |
| data().favicon.width(), |
| data().favicon.height(), |
| bounds, true, SkPaint()); |
| - } else if (!icon_animation_ && tab_audio_indicator_->IsAnimating()) { |
| - // Draw the audio indicator UI only if no other icon animation is |
| - // active. |
| - if (!icon_animation_ && tab_audio_indicator_->IsAnimating()) { |
| - tab_audio_indicator_->set_favicon(data().favicon); |
| - tab_audio_indicator_->Paint(canvas, bounds); |
| - } |
| } else { |
| DrawIconCenter(canvas, data().favicon, 0, |
| data().favicon.width(), |
| @@ -1573,6 +1577,25 @@ void Tab::PaintCaptureState(gfx::Canvas* canvas, gfx::Rect bounds) { |
| } |
| } |
| +void Tab::PaintAudioIndicator(gfx::Canvas* canvas) { |
| + gfx::Rect bounds = audio_indicator_bounds_; |
| + if (bounds.IsEmpty()) |
|
sky
2013/09/16 23:47:19
nit: do the test on audio_indicator_bounds_ and mo
miu
2013/09/19 02:37:11
Done.
|
| + return; |
| + |
| + bounds.set_x(GetMirroredXForRect(bounds)); |
| + |
| + canvas->Save(); |
|
sky
2013/09/16 23:47:19
DrawIconAtLocation?
miu
2013/09/19 02:37:11
Oh, duh. Yeah, that's much cleaner. :)
|
| + canvas->ClipRect(GetLocalBounds()); |
| + ui::ResourceBundle& rb = ui::ResourceBundle::GetSharedInstance(); |
| + gfx::ImageSkia audio_indicator_image( |
| + *rb.GetImageSkiaNamed(IDR_TAB_AUDIO_INDICATOR)); |
| + DrawIconCenter(canvas, audio_indicator_image, 0, |
| + audio_indicator_image.width(), |
| + audio_indicator_image.height(), |
| + bounds, true, SkPaint()); |
| + canvas->Restore(); |
| +} |
| + |
| void Tab::PaintTitle(gfx::Canvas* canvas, SkColor title_color) { |
| // Paint the Title. |
| const gfx::Rect& title_bounds = GetTitleBounds(); |
| @@ -1652,19 +1675,44 @@ void Tab::AdvanceLoadingAnimation(TabRendererData::NetworkState old_state, |
| int Tab::IconCapacity() const { |
| if (height() < GetMinimumUnselectedSize().height()) |
| return 0; |
| - return (width() - left_padding() - right_padding()) / tab_icon_size(); |
| + const int kPaddingBetweenIcons = 2; |
| + return (width() - left_padding() - right_padding()) / |
| + (tab_icon_size() + kPaddingBetweenIcons); |
| } |
| bool Tab::ShouldShowIcon() const { |
| + if (!data().show_icon) |
| + return false; |
| + const bool should_show_audio_indicator = ShouldShowAudioIndicator(); |
| + if (data().mini && height() >= GetMinimumUnselectedSize().height()) { |
| + // Audio indicator always takes precendence over the favicon for mini tabs. |
| + return !should_show_audio_indicator; |
| + } |
| + int required_capacity = should_show_audio_indicator ? 2 : 1; |
| + if (IsActive()) { |
| + // Active tabs give priority to the close button, then the audio indicator, |
| + // then the favicon. |
| + ++required_capacity; |
| + } else { |
| + // Non-active tabs give priority to the audio indicator, then the favicon, |
| + // and finally the close button. |
| + } |
| + return IconCapacity() >= required_capacity; |
| +} |
| + |
| +bool Tab::ShouldShowAudioIndicator() const { |
| + // Note: If the capture indicator is active, then do not show the audio |
| + // indicator. This allows the favicon "throbber" animation to be shown in |
| + // small-width situations. |
| + if (!data().AudioActive() || data().CaptureActive()) |
| + return false; |
| if (data().mini && height() >= GetMinimumUnselectedSize().height()) |
| return true; |
| - if (!data().show_icon) { |
| - return false; |
| - } else if (IsActive()) { |
| - // The active tab clips favicon before close button. |
| + if (IsActive()) { |
| + // The active tab clips the audio indicator before the close button. |
| return IconCapacity() >= 2; |
| } |
| - // Non-selected tabs clip close button before favicon. |
| + // Non-active tabs clip close button before the audio indicator. |
| return IconCapacity() >= 1; |
| } |