summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorsky@chromium.org <sky@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2010-05-17 23:44:34 +0000
committersky@chromium.org <sky@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2010-05-17 23:44:34 +0000
commit633698db41fb44ade5f64c6597b1065099bc52b9 (patch)
treecad60838646a4f657e399167ad18e4b98c486cfb
parent8621715ceeb4533aca1d27d639cd2e47c33cd961 (diff)
downloadchromium_src-633698db41fb44ade5f64c6597b1065099bc52b9.zip
chromium_src-633698db41fb44ade5f64c6597b1065099bc52b9.tar.gz
chromium_src-633698db41fb44ade5f64c6597b1065099bc52b9.tar.bz2
Refactors renderer related classes for better sharing.
BUG=none TEST=none Review URL: http://codereview.chromium.org/2089012 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@47473 0039d316-1c4b-4281-b951-d872f2087c98
-rw-r--r--chrome/browser/views/extensions/extension_installed_bubble.cc4
-rw-r--r--chrome/browser/views/frame/glass_browser_frame_view.cc3
-rw-r--r--chrome/browser/views/tabs/base_tab.cc530
-rw-r--r--chrome/browser/views/tabs/base_tab.h220
-rw-r--r--chrome/browser/views/tabs/base_tab_renderer.cc31
-rw-r--r--chrome/browser/views/tabs/base_tab_renderer.h94
-rw-r--r--chrome/browser/views/tabs/base_tab_strip.cc28
-rw-r--r--chrome/browser/views/tabs/base_tab_strip.h39
-rw-r--r--chrome/browser/views/tabs/browser_tab_strip_controller.cc20
-rw-r--r--chrome/browser/views/tabs/browser_tab_strip_controller.h16
-rw-r--r--chrome/browser/views/tabs/dragged_tab_controller.cc13
-rw-r--r--chrome/browser/views/tabs/dragged_tab_controller.h8
-rw-r--r--chrome/browser/views/tabs/side_tab.cc184
-rw-r--r--chrome/browser/views/tabs/side_tab.h49
-rw-r--r--chrome/browser/views/tabs/side_tab_strip.cc26
-rw-r--r--chrome/browser/views/tabs/side_tab_strip.h9
-rw-r--r--chrome/browser/views/tabs/tab.cc720
-rw-r--r--chrome/browser/views/tabs/tab.h170
-rwxr-xr-xchrome/browser/views/tabs/tab_controller.h50
-rw-r--r--chrome/browser/views/tabs/tab_renderer.cc1062
-rw-r--r--chrome/browser/views/tabs/tab_renderer.h248
-rw-r--r--chrome/browser/views/tabs/tab_strip.cc26
-rw-r--r--chrome/browser/views/tabs/tab_strip.h13
-rw-r--r--chrome/browser/views/tabs/tab_strip_controller.h4
-rw-r--r--chrome/chrome_browser.gypi14
25 files changed, 1695 insertions, 1886 deletions
diff --git a/chrome/browser/views/extensions/extension_installed_bubble.cc b/chrome/browser/views/extensions/extension_installed_bubble.cc
index 29aa69a..33f4dcf 100644
--- a/chrome/browser/views/extensions/extension_installed_bubble.cc
+++ b/chrome/browser/views/extensions/extension_installed_bubble.cc
@@ -14,7 +14,7 @@
#include "chrome/browser/views/browser_actions_container.h"
#include "chrome/browser/views/frame/browser_view.h"
#include "chrome/browser/views/location_bar/location_bar_view.h"
-#include "chrome/browser/views/tabs/base_tab_renderer.h"
+#include "chrome/browser/views/tabs/base_tab.h"
#include "chrome/browser/views/tabs/base_tab_strip.h"
#include "chrome/browser/views/toolbar_view.h"
#include "chrome/browser/web_applications/web_app.h"
@@ -318,7 +318,7 @@ void ExtensionInstalledBubble::ShowInternal() {
DCHECK(reference_view);
} else if (type_ == EXTENSION_APP) {
BaseTabStrip* tabstrip = browser_view->tabstrip();
- BaseTabRenderer* tab = tabstrip->GetSelectedBaseTab();
+ BaseTab* tab = tabstrip->GetSelectedBaseTab();
DCHECK(tab->data().app);
reference_view = tab;
}
diff --git a/chrome/browser/views/frame/glass_browser_frame_view.cc b/chrome/browser/views/frame/glass_browser_frame_view.cc
index 2e009c8..6838a3e 100644
--- a/chrome/browser/views/frame/glass_browser_frame_view.cc
+++ b/chrome/browser/views/frame/glass_browser_frame_view.cc
@@ -10,6 +10,7 @@
#include "chrome/browser/browser_theme_provider.h"
#include "chrome/browser/views/frame/browser_view.h"
#include "chrome/browser/views/tabs/side_tab_strip.h"
+#include "chrome/browser/views/tabs/tab.h"
#include "chrome/browser/views/tabs/tab_strip.h"
#include "gfx/canvas.h"
#include "gfx/icon_util.h"
@@ -257,7 +258,7 @@ void GlassBrowserFrameView::PaintToolbarBackground(gfx::Canvas* canvas) {
// Draw the toolbar background, setting src_y of the paint to the tab
// strip height as the toolbar background begins at the top of the tabs.
int src_y = browser_view_->UseVerticalTabs()
- ? TabRenderer::GetMinimumUnselectedSize().height()
+ ? Tab::GetMinimumUnselectedSize().height()
: browser_view_->GetTabStripHeight() - 1;
canvas->TileImageInt(*theme_toolbar, 0, src_y,
toolbar_bounds.x() - 1, toolbar_bounds.y() + 2,
diff --git a/chrome/browser/views/tabs/base_tab.cc b/chrome/browser/views/tabs/base_tab.cc
new file mode 100644
index 0000000..070e1ee
--- /dev/null
+++ b/chrome/browser/views/tabs/base_tab.cc
@@ -0,0 +1,530 @@
+// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chrome/browser/views/tabs/base_tab.h"
+
+#include <limits>
+
+#include "app/animation_container.h"
+#include "app/l10n_util.h"
+#include "app/resource_bundle.h"
+#include "app/slide_animation.h"
+#include "app/throb_animation.h"
+#include "base/command_line.h"
+#include "base/utf_string_conversions.h"
+#include "chrome/browser/browser.h"
+#include "chrome/browser/tab_contents/tab_contents.h"
+#include "chrome/browser/views/tabs/tab_controller.h"
+#include "chrome/common/chrome_switches.h"
+#include "gfx/canvas.h"
+#include "gfx/favicon_size.h"
+#include "gfx/font.h"
+#include "grit/app_resources.h"
+#include "grit/generated_resources.h"
+#include "grit/theme_resources.h"
+#include "views/controls/button/image_button.h"
+
+#ifdef WIN32
+#include "app/win_util.h"
+#endif
+
+// How long the pulse throb takes.
+static const int kPulseDurationMs = 200;
+
+// How long the hover state takes.
+static const int kHoverDurationMs = 90;
+
+static SkBitmap* waiting_animation_frames = NULL;
+static SkBitmap* loading_animation_frames = NULL;
+static int loading_animation_frame_count = 0;
+static int waiting_animation_frame_count = 0;
+static int waiting_to_loading_frame_count_ratio = 0;
+
+// Close button images.
+static SkBitmap* close_button_n = NULL;
+static SkBitmap* close_button_h = NULL;
+static SkBitmap* close_button_p = NULL;
+
+static SkBitmap* crashed_fav_icon = NULL;
+
+namespace {
+
+////////////////////////////////////////////////////////////////////////////////
+// TabCloseButton
+//
+// This is a Button subclass that causes middle clicks to be forwarded to the
+// parent View by explicitly not handling them in OnMousePressed.
+class TabCloseButton : public views::ImageButton {
+ public:
+ explicit TabCloseButton(views::ButtonListener* listener)
+ : views::ImageButton(listener) {
+ }
+ virtual ~TabCloseButton() {}
+
+ virtual bool OnMousePressed(const views::MouseEvent& event) {
+ bool handled = ImageButton::OnMousePressed(event);
+ // Explicitly mark midle-mouse clicks as non-handled to ensure the tab
+ // sees them.
+ return event.IsOnlyMiddleMouseButton() ? false : handled;
+ }
+
+ // We need to let the parent know about mouse state so that it
+ // can highlight itself appropriately. Note that Exit events
+ // fire before Enter events, so this works.
+ virtual void OnMouseEntered(const views::MouseEvent& event) {
+ CustomButton::OnMouseEntered(event);
+ GetParent()->OnMouseEntered(event);
+ }
+
+ virtual void OnMouseExited(const views::MouseEvent& event) {
+ CustomButton::OnMouseExited(event);
+ GetParent()->OnMouseExited(event);
+ }
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(TabCloseButton);
+};
+
+} // namespace
+
+// static
+int BaseTab::close_button_width_ = 0;
+// static
+int BaseTab::close_button_height_ = 0;
+// static
+int BaseTab::loading_animation_size_ = 0;
+
+// static
+gfx::Font* BaseTab::font_ = NULL;
+// static
+int BaseTab::font_height_ = 0;
+
+////////////////////////////////////////////////////////////////////////////////
+// FaviconCrashAnimation
+//
+// A custom animation subclass to manage the favicon crash animation.
+class BaseTab::FavIconCrashAnimation : public LinearAnimation,
+ public AnimationDelegate {
+ public:
+ explicit FavIconCrashAnimation(BaseTab* target)
+ : ALLOW_THIS_IN_INITIALIZER_LIST(LinearAnimation(1000, 25, this)),
+ target_(target) {
+ }
+ virtual ~FavIconCrashAnimation() {}
+
+ // Animation overrides:
+ virtual void AnimateToState(double state) {
+ const double kHidingOffset = 27;
+
+ if (state < .5) {
+ target_->SetFavIconHidingOffset(
+ static_cast<int>(floor(kHidingOffset * 2.0 * state)));
+ } else {
+ target_->DisplayCrashedFavIcon();
+ target_->SetFavIconHidingOffset(
+ static_cast<int>(
+ floor(kHidingOffset - ((state - .5) * 2.0 * kHidingOffset))));
+ }
+ }
+
+ // AnimationDelegate overrides:
+ virtual void AnimationCanceled(const Animation* animation) {
+ target_->SetFavIconHidingOffset(0);
+ }
+
+ private:
+ BaseTab* target_;
+
+ DISALLOW_COPY_AND_ASSIGN(FavIconCrashAnimation);
+};
+
+BaseTab::BaseTab(TabController* controller)
+ : controller_(controller),
+ closing_(false),
+ dragging_(false),
+ loading_animation_frame_(0),
+ throbber_disabled_(false),
+ theme_provider_(NULL),
+ fav_icon_hiding_offset_(0),
+ should_display_crashed_favicon_(false) {
+ BaseTab::InitResources();
+
+ // Add the Close Button.
+ TabCloseButton* close_button = new TabCloseButton(this);
+ close_button_ = close_button;
+ close_button->SetImage(views::CustomButton::BS_NORMAL, close_button_n);
+ close_button->SetImage(views::CustomButton::BS_HOT, close_button_h);
+ close_button->SetImage(views::CustomButton::BS_PUSHED, close_button_p);
+ close_button->SetTooltipText(l10n_util::GetString(IDS_TOOLTIP_CLOSE_TAB));
+ close_button->SetAccessibleName(l10n_util::GetString(IDS_ACCNAME_CLOSE));
+ close_button->SetAnimationDuration(0);
+ AddChildView(close_button);
+
+ SetContextMenuController(this);
+}
+
+BaseTab::~BaseTab() {
+}
+
+void BaseTab::SetData(const TabRendererData& data) {
+ TabRendererData old(data_);
+ data_ = data;
+
+ if (data_.crashed) {
+ if (!should_display_crashed_favicon_ && !IsPerformingCrashAnimation())
+ StartCrashAnimation();
+ } else {
+ if (IsPerformingCrashAnimation())
+ StopCrashAnimation();
+ ResetCrashedFavIcon();
+ }
+
+ // Sets the accessible name for the tab.
+ SetAccessibleName(UTF16ToWide(data_.title));
+
+ DataChanged(old);
+
+ Layout();
+}
+
+void BaseTab::UpdateLoadingAnimation(TabRendererData::NetworkState state) {
+ // If this is an extension app and a command line flag is set,
+ // then disable the throbber.
+ throbber_disabled_ = data().app &&
+ CommandLine::ForCurrentProcess()->HasSwitch(switches::kAppsNoThrob);
+
+ if (throbber_disabled_)
+ return;
+
+ if (state == data_.network_state &&
+ state == TabRendererData::NETWORK_STATE_NONE) {
+ // If the network state is none and hasn't changed, do nothing. Otherwise we
+ // need to advance the animation frame.
+ return;
+ }
+
+ TabRendererData::NetworkState old_state = data_.network_state;
+ data_.network_state = state;
+ AdvanceLoadingAnimation(old_state, state);
+}
+
+void BaseTab::StartPulse() {
+ if (!pulse_animation_.get()) {
+ pulse_animation_.reset(new ThrobAnimation(this));
+ pulse_animation_->SetSlideDuration(kPulseDurationMs);
+ if (animation_container_.get())
+ pulse_animation_->SetContainer(animation_container_.get());
+ }
+ pulse_animation_->Reset();
+ pulse_animation_->StartThrobbing(std::numeric_limits<int>::max());
+}
+
+void BaseTab::StopPulse() {
+ if (!pulse_animation_.get())
+ return;
+
+ pulse_animation_->Stop(); // Do stop so we get notified.
+ pulse_animation_.reset(NULL);
+}
+
+bool BaseTab::IsSelected() const {
+ return controller() ? controller()->IsTabSelected(this) : true;
+}
+
+void BaseTab::OnMouseEntered(const views::MouseEvent& e) {
+ if (!hover_animation_.get()) {
+ hover_animation_.reset(new SlideAnimation(this));
+ hover_animation_->SetContainer(animation_container_.get());
+ hover_animation_->SetSlideDuration(kHoverDurationMs);
+ }
+ hover_animation_->SetTweenType(Tween::EASE_OUT);
+ hover_animation_->Show();
+}
+
+void BaseTab::OnMouseExited(const views::MouseEvent& e) {
+ hover_animation_->SetTweenType(Tween::EASE_IN);
+ hover_animation_->Hide();
+}
+
+bool BaseTab::OnMousePressed(const views::MouseEvent& event) {
+ if (event.IsOnlyLeftMouseButton()) {
+ // Store whether or not we were selected just now... we only want to be
+ // able to drag foreground tabs, so we don't start dragging the tab if
+ // it was in the background.
+ bool just_selected = !IsSelected();
+ if (just_selected)
+ controller()->SelectTab(this);
+ controller()->MaybeStartDrag(this, event);
+ }
+ return true;
+}
+
+bool BaseTab::OnMouseDragged(const views::MouseEvent& event) {
+ controller()->ContinueDrag(event);
+ return true;
+}
+
+void BaseTab::OnMouseReleased(const views::MouseEvent& event, bool canceled) {
+ // Notify the drag helper that we're done with any potential drag operations.
+ // Clean up the drag helper, which is re-created on the next mouse press.
+ // In some cases, ending the drag will schedule the tab for destruction; if
+ // so, bail immediately, since our members are already dead and we shouldn't
+ // do anything else except drop the tab where it is.
+ if (controller()->EndDrag(canceled))
+ return;
+
+ // Close tab on middle click, but only if the button is released over the tab
+ // (normal windows behavior is to discard presses of a UI element where the
+ // releases happen off the element).
+ if (event.IsMiddleMouseButton() && HitTest(event.location()))
+ controller()->CloseTab(this);
+}
+
+bool BaseTab::GetTooltipText(const gfx::Point& p, std::wstring* tooltip) {
+ if (data_.title.empty())
+ return false;
+
+ std::wstring title = UTF16ToWide(data_.title);
+ // Only show the tooltip if the title is truncated.
+ if (font_->GetStringWidth(title) > title_bounds().width()) {
+ *tooltip = title;
+ return true;
+ }
+ return false;
+}
+
+bool BaseTab::GetAccessibleRole(AccessibilityTypes::Role* role) {
+ DCHECK(role);
+
+ *role = AccessibilityTypes::ROLE_PAGETAB;
+ return true;
+}
+
+ThemeProvider* BaseTab::GetThemeProvider() {
+ ThemeProvider* tp = View::GetThemeProvider();
+ return tp ? tp : theme_provider_;
+}
+
+void BaseTab::AdvanceLoadingAnimation(TabRendererData::NetworkState old_state,
+ TabRendererData::NetworkState state) {
+ // The waiting animation is the reverse of the loading animation, but at a
+ // different rate - the following reverses and scales the animation_frame_
+ // so that the frame is at an equivalent position when going from one
+ // animation to the other.
+ if (state != old_state) {
+ loading_animation_frame_ = loading_animation_frame_count -
+ (loading_animation_frame_ / waiting_to_loading_frame_count_ratio);
+ }
+
+ if (state != TabRendererData::NETWORK_STATE_NONE) {
+ loading_animation_frame_ = ++loading_animation_frame_ %
+ ((state == TabRendererData::NETWORK_STATE_WAITING) ?
+ waiting_animation_frame_count : loading_animation_frame_count);
+ } else {
+ loading_animation_frame_ = 0;
+ }
+ SchedulePaint();
+}
+
+void BaseTab::PaintIcon(gfx::Canvas* canvas, int x, int y) {
+ if (base::i18n::IsRTL()) {
+ if (!data().favicon.isNull())
+ x = width() - x - data().favicon.width();
+ else
+ x = width() - x - kFavIconSize;
+ }
+
+ int favicon_x = x;
+ if (!data().favicon.isNull() && data().favicon.width() != kFavIconSize)
+ favicon_x += (data().favicon.width() - kFavIconSize) / 2;
+
+ if (data().network_state != TabRendererData::NETWORK_STATE_NONE) {
+ SkBitmap* frames =
+ (data().network_state == TabRendererData::NETWORK_STATE_WAITING) ?
+ waiting_animation_frames : loading_animation_frames;
+ int image_size = frames->height();
+ int image_offset = loading_animation_frame_ * image_size;
+ int dst_y = (height() - image_size) / 2;
+ canvas->DrawBitmapInt(*frames, image_offset, 0, image_size,
+ image_size, favicon_x, dst_y, image_size, image_size,
+ false);
+ } else {
+ canvas->save();
+ canvas->ClipRectInt(0, 0, width(), height());
+ if (should_display_crashed_favicon_) {
+ canvas->DrawBitmapInt(*crashed_fav_icon, 0, 0,
+ crashed_fav_icon->width(),
+ crashed_fav_icon->height(),
+ favicon_x,
+ (height() - crashed_fav_icon->height()) / 2 +
+ fav_icon_hiding_offset_,
+ kFavIconSize, kFavIconSize,
+ true);
+ } else {
+ if (!data().favicon.isNull()) {
+ // TODO(pkasting): Use code in tab_icon_view.cc:PaintIcon() (or switch
+ // to using that class to render the favicon).
+ int size = data().favicon.width();
+ canvas->DrawBitmapInt(data().favicon, 0, 0,
+ data().favicon.width(),
+ data().favicon.height(),
+ x, y + fav_icon_hiding_offset_, size, size,
+ true);
+ }
+ }
+ canvas->restore();
+ }
+}
+
+void BaseTab::PaintTitle(gfx::Canvas* canvas, SkColor title_color) {
+ // Paint the Title.
+ string16 title = data().title;
+ if (title.empty()) {
+ title = data().loading ?
+ l10n_util::GetStringUTF16(IDS_TAB_LOADING_TITLE) :
+ TabContents::GetDefaultTitle();
+ } else {
+ Browser::FormatTitleForDisplay(&title);
+ }
+
+ canvas->DrawStringInt(UTF16ToWideHack(title), *font_, title_color,
+ title_bounds().x(), title_bounds().y(),
+ title_bounds().width(), title_bounds().height());
+}
+
+void BaseTab::AnimationProgressed(const Animation* animation) {
+ SchedulePaint();
+}
+
+void BaseTab::AnimationCanceled(const Animation* animation) {
+ SchedulePaint();
+}
+
+void BaseTab::AnimationEnded(const Animation* animation) {
+ SchedulePaint();
+}
+
+void BaseTab::ButtonPressed(views::Button* sender, const views::Event& event) {
+ DCHECK(sender == close_button_);
+ controller()->CloseTab(this);
+}
+
+void BaseTab::ShowContextMenu(views::View* source,
+ const gfx::Point& p,
+ bool is_mouse_gesture) {
+ controller()->ShowContextMenu(this, p);
+}
+
+void BaseTab::ThemeChanged() {
+ views::View::ThemeChanged();
+ LoadThemeImages();
+}
+
+void BaseTab::SetFavIconHidingOffset(int offset) {
+ fav_icon_hiding_offset_ = offset;
+ SchedulePaint();
+}
+
+void BaseTab::DisplayCrashedFavIcon() {
+ should_display_crashed_favicon_ = true;
+}
+
+void BaseTab::ResetCrashedFavIcon() {
+ should_display_crashed_favicon_ = false;
+}
+
+void BaseTab::StartCrashAnimation() {
+ if (!crash_animation_.get())
+ crash_animation_.reset(new FavIconCrashAnimation(this));
+ crash_animation_->Stop();
+ crash_animation_->Start();
+}
+
+void BaseTab::StopCrashAnimation() {
+ if (!crash_animation_.get())
+ return;
+ crash_animation_->Stop();
+}
+
+bool BaseTab::IsPerformingCrashAnimation() const {
+ return crash_animation_.get() && crash_animation_->is_animating();
+}
+
+// static
+void BaseTab::InitResources() {
+ static bool initialized = false;
+ if (initialized)
+ return;
+
+ initialized = true;
+
+ ResourceBundle& rb = ResourceBundle::GetSharedInstance();
+
+ crashed_fav_icon = rb.GetBitmapNamed(IDR_SAD_FAVICON);
+
+ close_button_n = rb.GetBitmapNamed(IDR_TAB_CLOSE);
+ close_button_h = rb.GetBitmapNamed(IDR_TAB_CLOSE_H);
+ close_button_p = rb.GetBitmapNamed(IDR_TAB_CLOSE_P);
+
+ close_button_width_ = close_button_n->width();
+ close_button_height_ = close_button_n->height();
+
+ // The loading animation image is a strip of states. Each state must be
+ // square, so the height must divide the width evenly.
+ loading_animation_frames = rb.GetBitmapNamed(IDR_THROBBER);
+ loading_animation_size_ = loading_animation_frames->height();
+ DCHECK(loading_animation_frames);
+ DCHECK(loading_animation_frames->width() %
+ loading_animation_frames->height() == 0);
+ loading_animation_frame_count =
+ loading_animation_frames->width() / loading_animation_frames->height();
+
+ // We get a DIV0 further down when the throbber is replaced by an image which
+ // is taller than wide. In this case we cannot deduce an animation sequence
+ // from it since we assume that each animation frame has the width of the
+ // image's height.
+ if (loading_animation_frame_count == 0) {
+#ifdef WIN32
+ // TODO(idanan): Remove this when we have a way to handle theme errors.
+ // See: http://code.google.com/p/chromium/issues/detail?id=12531 For now,
+ // this is Windows-specific because some users have downloaded a DLL from
+ // outside of Google to override the theme.
+ std::wstring text = l10n_util::GetString(IDS_RESOURCE_ERROR);
+ std::wstring caption = l10n_util::GetString(IDS_RESOURCE_ERROR_CAPTION);
+ UINT flags = MB_OK | MB_ICONWARNING | MB_TOPMOST;
+ win_util::MessageBox(NULL, text, caption, flags);
+#endif
+ CHECK(loading_animation_frame_count) <<
+ "Invalid throbber size. Width = " <<
+ loading_animation_frames->width() << ", height = " <<
+ loading_animation_frames->height();
+ }
+
+ waiting_animation_frames = rb.GetBitmapNamed(IDR_THROBBER_WAITING);
+ DCHECK(waiting_animation_frames);
+ DCHECK(waiting_animation_frames->width() %
+ waiting_animation_frames->height() == 0);
+ waiting_animation_frame_count =
+ waiting_animation_frames->width() / waiting_animation_frames->height();
+
+ waiting_to_loading_frame_count_ratio =
+ waiting_animation_frame_count / loading_animation_frame_count;
+ // TODO(beng): eventually remove this when we have a proper themeing system.
+ // themes not supporting IDR_THROBBER_WAITING are causing this
+ // value to be 0 which causes DIV0 crashes. The value of 5
+ // matches the current bitmaps in our source.
+ if (waiting_to_loading_frame_count_ratio == 0)
+ waiting_to_loading_frame_count_ratio = 5;
+
+ font_ = new gfx::Font(rb.GetFont(ResourceBundle::BaseFont));
+ font_height_ = font_->height();
+}
+
+// static
+void BaseTab::LoadThemeImages() {
+ ResourceBundle& rb = ResourceBundle::GetSharedInstance();
+ loading_animation_frames = rb.GetBitmapNamed(IDR_THROBBER);
+ waiting_animation_frames = rb.GetBitmapNamed(IDR_THROBBER_WAITING);
+ loading_animation_size_ = loading_animation_frames->height();
+}
diff --git a/chrome/browser/views/tabs/base_tab.h b/chrome/browser/views/tabs/base_tab.h
new file mode 100644
index 0000000..678594d
--- /dev/null
+++ b/chrome/browser/views/tabs/base_tab.h
@@ -0,0 +1,220 @@
+// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CHROME_BROWSER_VIEWS_TABS_BASE_TAB_H_
+#define CHROME_BROWSER_VIEWS_TABS_BASE_TAB_H_
+
+#include "app/animation.h"
+#include "base/ref_counted.h"
+#include "base/scoped_ptr.h"
+#include "chrome/browser/views/tabs/tab_renderer_data.h"
+#include "views/controls/button/button.h"
+#include "views/view.h"
+
+class AnimationContainer;
+class BaseTab;
+class SlideAnimation;
+class TabController;
+class ThrobAnimation;
+
+namespace gfx {
+class Font;
+} // namespace gfx
+
+namespace views {
+class ImageButton;
+} // namespace views
+
+// Base class for tab renderers.
+class BaseTab : public AnimationDelegate,
+ public views::ButtonListener,
+ public views::ContextMenuController,
+ public views::View {
+ public:
+ explicit BaseTab(TabController* controller);
+ ~BaseTab();
+
+ // Sets the data this tabs displays. Invokes DataChanged for subclasses to
+ // update themselves appropriately.
+ void SetData(const TabRendererData& data);
+ const TabRendererData& data() const { return data_; }
+
+ // Sets the network state. If the network state changes NetworkStateChanged is
+ // invoked.
+ virtual void UpdateLoadingAnimation(TabRendererData::NetworkState state);
+
+ // Starts/Stops a pulse animation.
+ void StartPulse();
+ void StopPulse();
+
+ // Used to set/check whether this Tab is being animated closed.
+ void set_closing(bool closing) { closing_ = closing; }
+ bool closing() const { return closing_; }
+
+ // See description above field.
+ void set_dragging(bool dragging) { dragging_ = dragging; }
+ bool dragging() const { return dragging_; }
+
+ // Sets the container all animations run from.
+ void set_animation_container(AnimationContainer* container) {
+ animation_container_ = container;
+ }
+ AnimationContainer* animation_container() const {
+ return animation_container_.get();
+ }
+
+ // Set the theme provider - because we get detached, we are frequently
+ // outside of a hierarchy with a theme provider at the top. This should be
+ // called whenever we're detached or attached to a hierarchy.
+ void set_theme_provider(ThemeProvider* provider) {
+ theme_provider_ = provider;
+ }
+
+ // Returns true if the tab is selected.
+ bool IsSelected() const;
+
+ // views::View overrides:
+ virtual void OnMouseEntered(const views::MouseEvent& event);
+ virtual void OnMouseExited(const views::MouseEvent& event);
+ virtual bool OnMousePressed(const views::MouseEvent& event);
+ virtual bool OnMouseDragged(const views::MouseEvent& event);
+ virtual void OnMouseReleased(const views::MouseEvent& event,
+ bool canceled);
+ virtual bool GetTooltipText(const gfx::Point& p, std::wstring* tooltip);
+ virtual bool GetAccessibleRole(AccessibilityTypes::Role* role);
+ virtual ThemeProvider* GetThemeProvider();
+
+ protected:
+ // Invoked from SetData after |data_| has been updated to the new data.
+ virtual void DataChanged(const TabRendererData& old) {}
+
+ // Invoked if data_.network_state changes, or the network_state is not none.
+ virtual void AdvanceLoadingAnimation(TabRendererData::NetworkState old_state,
+ TabRendererData::NetworkState state);
+
+ TabController* controller() const { return controller_; }
+
+ // Returns the pulse animation. The pulse animation is non-null if StartPulse
+ // has been invoked.
+ ThrobAnimation* pulse_animation() const { return pulse_animation_.get(); }
+
+ // Returns the hover animation. This may return null.
+ const SlideAnimation* hover_animation() const {
+ return hover_animation_.get();
+ }
+
+ views::ImageButton* close_button() const { return close_button_; }
+
+ // Paints the icon at the specified x-coordinate.
+ void PaintIcon(gfx::Canvas* canvas, int x, int y);
+ void PaintTitle(gfx::Canvas* canvas, SkColor title_color);
+
+ // Overridden from AnimationDelegate:
+ virtual void AnimationProgressed(const Animation* animation);
+ virtual void AnimationCanceled(const Animation* animation);
+ virtual void AnimationEnded(const Animation* animation);
+
+ // views::ButtonListener overrides:
+ virtual void ButtonPressed(views::Button* sender,
+ const views::Event& event);
+
+ // views::ContextMenuController overrides:
+ virtual void ShowContextMenu(views::View* source,
+ const gfx::Point& p,
+ bool is_mouse_gesture);
+
+ // views::View overrides:
+ virtual void ThemeChanged();
+
+ // Returns the bounds of the title.
+ virtual const gfx::Rect& title_bounds() const = 0;
+
+ // Close button size.
+ static int close_button_height() { return close_button_height_; }
+ static int close_button_width() { return close_button_width_; }
+
+ // Size (width/height) of the loading animation.
+ static int loading_animation_size() { return loading_animation_size_; }
+
+ static gfx::Font* font() { return font_; }
+ static int font_height() { return font_height_; }
+
+ private:
+ // The animation object used to swap the favicon with the sad tab icon.
+ class FavIconCrashAnimation;
+
+ // Set the temporary offset for the favicon. This is used during the crash
+ // animation.
+ void SetFavIconHidingOffset(int offset);
+
+ void DisplayCrashedFavIcon();
+ void ResetCrashedFavIcon();
+
+ // Starts/Stops the crash animation.
+ void StartCrashAnimation();
+ void StopCrashAnimation();
+
+ // Return true if the crash animation is currently running.
+ bool IsPerformingCrashAnimation() const;
+
+ static void InitResources();
+
+ // Invoked when the theme changes to reload theme images.
+ static void LoadThemeImages();
+
+ // The controller.
+ // WARNING: this is null during detached tab dragging.
+ TabController* controller_;
+
+ TabRendererData data_;
+
+ // True if the tab is being animated closed.
+ bool closing_;
+
+ // True if the tab is being dragged.
+ bool dragging_;
+
+ // Pulse animation.
+ scoped_ptr<ThrobAnimation> pulse_animation_;
+
+ // Hover animation.
+ scoped_ptr<SlideAnimation> hover_animation_;
+
+ // Crash animation.
+ scoped_ptr<FavIconCrashAnimation> crash_animation_;
+
+ scoped_refptr<AnimationContainer> animation_container_;
+
+ views::ImageButton* close_button_;
+
+ // The current index of the loading animation.
+ int loading_animation_frame_;
+
+ // Whether to disable throbber animations. Only true if this is a nano tab
+ // renderer and a command line flag has been passed in to disable the
+ // animations.
+ bool throbber_disabled_;
+
+ ThemeProvider* theme_provider_;
+
+ // The offset used to animate the favicon location. This is used when the tab
+ // crashes.
+ int fav_icon_hiding_offset_;
+
+ bool should_display_crashed_favicon_;
+
+ // Size of the close button.
+ static int close_button_width_;
+ static int close_button_height_;
+
+ // Size of the loading animation frames.
+ static int loading_animation_size_;
+
+ static gfx::Font* font_;
+ static int font_height_;
+
+ DISALLOW_COPY_AND_ASSIGN(BaseTab);
+};
+
+#endif // CHROME_BROWSER_VIEWS_TABS_BASE_TAB_H_
diff --git a/chrome/browser/views/tabs/base_tab_renderer.cc b/chrome/browser/views/tabs/base_tab_renderer.cc
deleted file mode 100644
index e2c2251..0000000
--- a/chrome/browser/views/tabs/base_tab_renderer.cc
+++ /dev/null
@@ -1,31 +0,0 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "chrome/browser/views/tabs/base_tab_renderer.h"
-
-BaseTabRenderer::BaseTabRenderer(TabController* controller)
- : controller_(controller),
- closing_(false),
- dragging_(false) {
-}
-
-void BaseTabRenderer::SetData(const TabRendererData& data) {
- TabRendererData old(data_);
- data_ = data;
- DataChanged(old);
- Layout();
-}
-
-void BaseTabRenderer::UpdateLoadingAnimation(
- TabRendererData::NetworkState state) {
- if (state == data_.network_state &&
- state == TabRendererData::NETWORK_STATE_NONE) {
- // If the network state is none and hasn't changed, do nothing. Otherwise we
- // need to advance the animation frame.
- return;
- }
-
- data_.network_state = state;
- AdvanceLoadingAnimation(state);
-}
diff --git a/chrome/browser/views/tabs/base_tab_renderer.h b/chrome/browser/views/tabs/base_tab_renderer.h
deleted file mode 100644
index 12491c4..0000000
--- a/chrome/browser/views/tabs/base_tab_renderer.h
+++ /dev/null
@@ -1,94 +0,0 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef CHROME_BROWSER_VIEWS_TABS_BASE_TAB_RENDERER_H_
-#define CHROME_BROWSER_VIEWS_TABS_BASE_TAB_RENDERER_H_
-
-#include "chrome/browser/views/tabs/tab_renderer_data.h"
-#include "views/view.h"
-
-class BaseTabRenderer;
-
-// Controller for tabs.
-class TabController {
- public:
- // Selects the tab.
- virtual void SelectTab(BaseTabRenderer* tab) = 0;
-
- // Closes the tab.
- virtual void CloseTab(BaseTabRenderer* tab) = 0;
-
- // Shows a context menu for the tab at the specified point in screen coords.
- virtual void ShowContextMenu(BaseTabRenderer* tab, const gfx::Point& p) = 0;
-
- // Returns true if the specified Tab is selected.
- virtual bool IsTabSelected(const BaseTabRenderer* tab) const = 0;
-
- // Returns true if the specified Tab is pinned.
- virtual bool IsTabPinned(const BaseTabRenderer* tab) const = 0;
-
- // Potentially starts a drag for the specified Tab.
- virtual void MaybeStartDrag(BaseTabRenderer* tab,
- const views::MouseEvent& event) = 0;
-
- // Continues dragging a Tab.
- virtual void ContinueDrag(const views::MouseEvent& event) = 0;
-
- // Ends dragging a Tab. |canceled| is true if the drag was aborted in a way
- // other than the user releasing the mouse. Returns whether the tab has been
- // destroyed.
- virtual bool EndDrag(bool canceled) = 0;
-
- protected:
- virtual ~TabController() {}
-};
-
-// Base class for tab renderers.
-class BaseTabRenderer : public views::View {
- public:
- explicit BaseTabRenderer(TabController* controller);
-
- // Sets the data this tabs displays. Invokes DataChanged for subclasses to
- // update themselves appropriately.
- void SetData(const TabRendererData& data);
- const TabRendererData& data() const { return data_; }
-
- // Sets the network state. If the network state changes NetworkStateChanged is
- // invoked.
- virtual void UpdateLoadingAnimation(TabRendererData::NetworkState state);
-
- // Used to set/check whether this Tab is being animated closed.
- void set_closing(bool closing) { closing_ = closing; }
- bool closing() const { return closing_; }
-
- // See description above field.
- void set_dragging(bool dragging) { dragging_ = dragging; }
- bool dragging() const { return dragging_; }
-
- protected:
- // Invoked from SetData after |data_| has been updated to the new data.
- virtual void DataChanged(const TabRendererData& old) {}
-
- // Invoked if data_.network_state changes, or the network_state is not none.
- virtual void AdvanceLoadingAnimation(TabRendererData::NetworkState state) {}
-
- TabController* controller() const { return controller_; }
-
- private:
- // The controller.
- // WARNING: this is null during detached tab dragging.
- TabController* controller_;
-
- TabRendererData data_;
-
- // True if the tab is being animated closed.
- bool closing_;
-
- // True if the tab is being dragged.
- bool dragging_;
-
- DISALLOW_COPY_AND_ASSIGN(BaseTabRenderer);
-};
-
-#endif // CHROME_BROWSER_VIEWS_TABS_BASE_TAB_RENDERER_H_
diff --git a/chrome/browser/views/tabs/base_tab_strip.cc b/chrome/browser/views/tabs/base_tab_strip.cc
index 6afa538..da59c28 100644
--- a/chrome/browser/views/tabs/base_tab_strip.cc
+++ b/chrome/browser/views/tabs/base_tab_strip.cc
@@ -23,14 +23,14 @@ void BaseTabStrip::UpdateLoadingAnimations() {
controller_->UpdateLoadingAnimations();
}
-BaseTabRenderer* BaseTabStrip::GetSelectedBaseTab() const {
+BaseTab* BaseTabStrip::GetSelectedBaseTab() const {
return GetBaseTabAtModelIndex(controller_->GetSelectedIndex());
}
void BaseTabStrip::AddTabAt(int model_index,
bool foreground,
const TabRendererData& data) {
- BaseTabRenderer* tab = CreateTab();
+ BaseTab* tab = CreateTab();
tab->SetData(data);
TabData d = { tab, gfx::Rect() };
@@ -49,7 +49,7 @@ void BaseTabStrip::AddTabAt(int model_index,
void BaseTabStrip::MoveTab(int from_model_index, int to_model_index) {
int from_tab_data_index = ModelIndexToTabIndex(from_model_index);
- BaseTabRenderer* tab = tab_data_[from_tab_data_index].tab;
+ BaseTab* tab = tab_data_[from_tab_data_index].tab;
tab_data_.erase(tab_data_.begin() + from_tab_data_index);
TabData data = {tab, gfx::Rect()};
@@ -61,13 +61,13 @@ void BaseTabStrip::MoveTab(int from_model_index, int to_model_index) {
StartMoveTabAnimation();
}
-BaseTabRenderer* BaseTabStrip::GetBaseTabAtModelIndex(int model_index) const {
+BaseTab* BaseTabStrip::GetBaseTabAtModelIndex(int model_index) const {
return base_tab_at_tab_index(ModelIndexToTabIndex(model_index));
}
-int BaseTabStrip::GetModelIndexOfBaseTab(const BaseTabRenderer* tab) const {
+int BaseTabStrip::GetModelIndexOfBaseTab(const BaseTab* tab) const {
for (int i = 0, model_index = 0; i < tab_count(); ++i) {
- BaseTabRenderer* current_tab = base_tab_at_tab_index(i);
+ BaseTab* current_tab = base_tab_at_tab_index(i);
if (!current_tab->closing()) {
if (current_tab == tab)
return model_index;
@@ -101,29 +101,29 @@ bool BaseTabStrip::IsDragSessionActive() const {
return drag_controller_.get() != NULL;
}
-void BaseTabStrip::SelectTab(BaseTabRenderer* tab) {
+void BaseTabStrip::SelectTab(BaseTab* tab) {
int model_index = GetModelIndexOfBaseTab(tab);
if (IsValidModelIndex(model_index))
controller_->SelectTab(model_index);
}
-void BaseTabStrip::CloseTab(BaseTabRenderer* tab) {
+void BaseTabStrip::CloseTab(BaseTab* tab) {
int model_index = GetModelIndexOfBaseTab(tab);
if (IsValidModelIndex(model_index))
controller_->CloseTab(model_index);
}
-void BaseTabStrip::ShowContextMenu(BaseTabRenderer* tab, const gfx::Point& p) {
+void BaseTabStrip::ShowContextMenu(BaseTab* tab, const gfx::Point& p) {
controller_->ShowContextMenu(tab, p);
}
-bool BaseTabStrip::IsTabSelected(const BaseTabRenderer* tab) const {
+bool BaseTabStrip::IsTabSelected(const BaseTab* tab) const {
int model_index = GetModelIndexOfBaseTab(tab);
return IsValidModelIndex(model_index) &&
controller_->IsTabSelected(model_index);
}
-bool BaseTabStrip::IsTabPinned(const BaseTabRenderer* tab) const {
+bool BaseTabStrip::IsTabPinned(const BaseTab* tab) const {
if (tab->closing())
return false;
@@ -132,7 +132,7 @@ bool BaseTabStrip::IsTabPinned(const BaseTabRenderer* tab) const {
controller_->IsTabPinned(model_index);
}
-void BaseTabStrip::MaybeStartDrag(BaseTabRenderer* tab,
+void BaseTabStrip::MaybeStartDrag(BaseTab* tab,
const views::MouseEvent& event) {
// Don't accidentally start any drag operations during animations if the
// mouse is down... during an animation tabs are being resized automatically,
@@ -196,7 +196,7 @@ void BaseTabStrip::OnMouseReleased(const views::MouseEvent& event,
EndDrag(canceled);
}
-void BaseTabStrip::RemoveAndDeleteTab(BaseTabRenderer* tab) {
+void BaseTabStrip::RemoveAndDeleteTab(BaseTab* tab) {
int tab_data_index = TabIndexOfTab(tab);
DCHECK(tab_data_index != -1);
@@ -207,7 +207,7 @@ void BaseTabStrip::RemoveAndDeleteTab(BaseTabRenderer* tab) {
delete tab;
}
-int BaseTabStrip::TabIndexOfTab(BaseTabRenderer* tab) const {
+int BaseTabStrip::TabIndexOfTab(BaseTab* tab) const {
for (int i = 0; i < tab_count(); ++i) {
if (base_tab_at_tab_index(i) == tab)
return i;
diff --git a/chrome/browser/views/tabs/base_tab_strip.h b/chrome/browser/views/tabs/base_tab_strip.h
index b299e72..c10a924 100644
--- a/chrome/browser/views/tabs/base_tab_strip.h
+++ b/chrome/browser/views/tabs/base_tab_strip.h
@@ -8,10 +8,11 @@
#include <vector>
#include "base/scoped_ptr.h"
-#include "chrome/browser/views/tabs/base_tab_renderer.h"
+#include "chrome/browser/views/tabs/base_tab.h"
+#include "chrome/browser/views/tabs/tab_controller.h"
#include "views/view.h"
-class BaseTabRenderer;
+class BaseTab;
class DraggedTabController;
class TabStrip;
class TabStripController;
@@ -65,7 +66,7 @@ class BaseTabStrip : public views::View,
virtual void StopAllHighlighting() = 0;
// Returns the selected tab.
- virtual BaseTabRenderer* GetSelectedBaseTab() const;
+ virtual BaseTab* GetSelectedBaseTab() const;
// Retrieves the ideal bounds for the Tab at the specified index.
const gfx::Rect& ideal_bounds(int tab_data_index) {
@@ -74,7 +75,7 @@ class BaseTabStrip : public views::View,
// Creates and returns a tab that can be used for dragging. Ownership passes
// to the caller.
- virtual BaseTabRenderer* CreateTabForDragging() = 0;
+ virtual BaseTab* CreateTabForDragging() = 0;
// Adds a tab at the specified index.
void AddTabAt(int model_index,
@@ -99,16 +100,16 @@ class BaseTabStrip : public views::View,
virtual void SetTabData(int model_index, const TabRendererData& data) = 0;
// Returns the tab at the specified model index.
- virtual BaseTabRenderer* GetBaseTabAtModelIndex(int model_index) const;
+ virtual BaseTab* GetBaseTabAtModelIndex(int model_index) const;
// Returns the tab at the specified tab index.
- BaseTabRenderer* base_tab_at_tab_index(int tab_index) const {
+ BaseTab* base_tab_at_tab_index(int tab_index) const {
return tab_data_[tab_index].tab;
}
// Returns the index of the specified tab in the model coordiate system, or
// -1 if tab is closing or not valid.
- virtual int GetModelIndexOfBaseTab(const BaseTabRenderer* tab) const;
+ virtual int GetModelIndexOfBaseTab(const BaseTab* tab) const;
// Gets the number of Tabs in the tab strip.
// WARNING: this is the number of tabs displayed by the tabstrip, which if
@@ -133,12 +134,12 @@ class BaseTabStrip : public views::View,
bool IsDragSessionActive() const;
// TabController overrides:
- virtual void SelectTab(BaseTabRenderer* tab);
- virtual void CloseTab(BaseTabRenderer* tab);
- virtual void ShowContextMenu(BaseTabRenderer* tab, const gfx::Point& p);
- virtual bool IsTabSelected(const BaseTabRenderer* tab) const;
- virtual bool IsTabPinned(const BaseTabRenderer* tab) const;
- virtual void MaybeStartDrag(BaseTabRenderer* tab,
+ virtual void SelectTab(BaseTab* tab);
+ virtual void CloseTab(BaseTab* tab);
+ virtual void ShowContextMenu(BaseTab* tab, const gfx::Point& p);
+ virtual bool IsTabSelected(const BaseTab* tab) const;
+ virtual bool IsTabPinned(const BaseTab* tab) const;
+ virtual void MaybeStartDrag(BaseTab* tab,
const views::MouseEvent& event);
virtual void ContinueDrag(const views::MouseEvent& event);
virtual bool EndDrag(bool canceled);
@@ -149,7 +150,7 @@ class BaseTabStrip : public views::View,
protected:
// The Tabs we contain, and their last generated "good" bounds.
struct TabData {
- BaseTabRenderer* tab;
+ BaseTab* tab;
gfx::Rect ideal_bounds;
};
@@ -159,7 +160,7 @@ class BaseTabStrip : public views::View,
bool canceled);
// Creates and returns a new tab. The caller owners the returned tab.
- virtual BaseTabRenderer* CreateTab() = 0;
+ virtual BaseTab* CreateTab() = 0;
// Invoked from |AddTabAt| after the newly created tab has been inserted.
// Subclasses should either start an animation, or layout.
@@ -171,7 +172,7 @@ class BaseTabStrip : public views::View,
// Cleans up the Tab from the TabStrip. This is called from the tab animation
// code and is not a general-purpose method.
- void RemoveAndDeleteTab(BaseTabRenderer* tab);
+ void RemoveAndDeleteTab(BaseTab* tab);
// Resets the bounds of all non-closing tabs.
virtual void GenerateIdealBounds() = 0;
@@ -182,7 +183,7 @@ class BaseTabStrip : public views::View,
// Returns the index into |tab_data_| corresponding to the specified tab, or
// -1 if the tab isn't in |tab_data_|.
- int TabIndexOfTab(BaseTabRenderer* tab) const;
+ int TabIndexOfTab(BaseTab* tab) const;
// Stops any ongoing animations. If |layout| is true and an animation is
// ongoing this does a layout.
@@ -192,8 +193,8 @@ class BaseTabStrip : public views::View,
void DestroyDragController();
// Used by DraggedTabController when the user starts or stops dragging a tab.
- virtual void StartedDraggingTab(BaseTabRenderer* tab) = 0;
- virtual void StoppedDraggingTab(BaseTabRenderer* tab) = 0;
+ virtual void StartedDraggingTab(BaseTab* tab) = 0;
+ virtual void StoppedDraggingTab(BaseTab* tab) = 0;
// See description above field for details.
bool attaching_dragged_tab() const { return attaching_dragged_tab_; }
diff --git a/chrome/browser/views/tabs/browser_tab_strip_controller.cc b/chrome/browser/views/tabs/browser_tab_strip_controller.cc
index 4ebed88..6db41c7 100644
--- a/chrome/browser/views/tabs/browser_tab_strip_controller.cc
+++ b/chrome/browser/views/tabs/browser_tab_strip_controller.cc
@@ -32,7 +32,7 @@ static TabRendererData::NetworkState TabContentsNetworkState(
class BrowserTabStripController::TabContextMenuContents
: public menus::SimpleMenuModel::Delegate {
public:
- TabContextMenuContents(BaseTabRenderer* tab,
+ TabContextMenuContents(BaseTab* tab,
BrowserTabStripController* controller)
: ALLOW_THIS_IN_INITIALIZER_LIST(
model_(this, controller->IsTabPinned(tab))),
@@ -96,7 +96,7 @@ class BrowserTabStripController::TabContextMenuContents
scoped_ptr<views::Menu2> menu_;
// The tab we're showing a menu for.
- BaseTabRenderer* tab_;
+ BaseTab* tab_;
// A pointer back to our hosting controller, for command state information.
BrowserTabStripController* controller_;
@@ -140,7 +140,7 @@ void BrowserTabStripController::InitFromModel(BaseTabStrip* tabstrip) {
bool BrowserTabStripController::IsCommandEnabledForTab(
TabStripModel::ContextMenuCommand command_id,
- BaseTabRenderer* tab) const {
+ BaseTab* tab) const {
int model_index = tabstrip_->GetModelIndexOfBaseTab(tab);
return model_->ContainsIndex(model_index) ?
model_->IsContextMenuCommandEnabled(model_index, command_id) : false;
@@ -148,7 +148,7 @@ bool BrowserTabStripController::IsCommandEnabledForTab(
bool BrowserTabStripController::IsCommandCheckedForTab(
TabStripModel::ContextMenuCommand command_id,
- BaseTabRenderer* tab) const {
+ BaseTab* tab) const {
int model_index = tabstrip_->GetModelIndexOfBaseTab(tab);
return model_->ContainsIndex(model_index) ?
model_->IsContextMenuCommandChecked(model_index, command_id) : false;
@@ -156,13 +156,13 @@ bool BrowserTabStripController::IsCommandCheckedForTab(
void BrowserTabStripController::ExecuteCommandForTab(
TabStripModel::ContextMenuCommand command_id,
- BaseTabRenderer* tab) {
+ BaseTab* tab) {
int model_index = tabstrip_->GetModelIndexOfBaseTab(tab);
if (model_->ContainsIndex(model_index))
model_->ExecuteContextMenuCommand(model_index, command_id);
}
-bool BrowserTabStripController::IsTabPinned(BaseTabRenderer* tab) {
+bool BrowserTabStripController::IsTabPinned(BaseTab* tab) {
return IsTabPinned(tabstrip_->GetModelIndexOfBaseTab(tab));
}
@@ -201,7 +201,7 @@ void BrowserTabStripController::CloseTab(int model_index) {
model_->CloseTabContentsAt(model_index);
}
-void BrowserTabStripController::ShowContextMenu(BaseTabRenderer* tab,
+void BrowserTabStripController::ShowContextMenu(BaseTab* tab,
const gfx::Point& p) {
context_menu_contents_.reset(new TabContextMenuContents(tab, this));
context_menu_contents_->RunMenuAt(p);
@@ -213,7 +213,7 @@ void BrowserTabStripController::UpdateLoadingAnimations() {
// be processed before us and invokes this).
for (int tab_index = 0, tab_count = tabstrip_->tab_count();
tab_index < tab_count; ++tab_index) {
- BaseTabRenderer* tab = tabstrip_->base_tab_at_tab_index(tab_index);
+ BaseTab* tab = tabstrip_->base_tab_at_tab_index(tab_index);
int model_index = tabstrip_->GetModelIndexOfBaseTab(tab);
if (model_->ContainsIndex(model_index)) {
TabContents* contents = model_->GetTabContentsAt(model_index);
@@ -372,7 +372,7 @@ void BrowserTabStripController::SetTabRendererDataFromModel(
void BrowserTabStripController::StartHighlightTabsForCommand(
TabStripModel::ContextMenuCommand command_id,
- BaseTabRenderer* tab) {
+ BaseTab* tab) {
if (command_id == TabStripModel::CommandCloseTabsOpenedBy ||
command_id == TabStripModel::CommandCloseOtherTabs ||
command_id == TabStripModel::CommandCloseTabsToRight) {
@@ -390,7 +390,7 @@ void BrowserTabStripController::StartHighlightTabsForCommand(
void BrowserTabStripController::StopHighlightTabsForCommand(
TabStripModel::ContextMenuCommand command_id,
- BaseTabRenderer* tab) {
+ BaseTab* tab) {
if (command_id == TabStripModel::CommandCloseTabsOpenedBy ||
command_id == TabStripModel::CommandCloseTabsToRight ||
command_id == TabStripModel::CommandCloseOtherTabs) {
diff --git a/chrome/browser/views/tabs/browser_tab_strip_controller.h b/chrome/browser/views/tabs/browser_tab_strip_controller.h
index c0e3244..cff9650 100644
--- a/chrome/browser/views/tabs/browser_tab_strip_controller.h
+++ b/chrome/browser/views/tabs/browser_tab_strip_controller.h
@@ -9,7 +9,7 @@
#include "chrome/browser/tabs/tab_strip_model.h"
#include "chrome/browser/views/tabs/tab_strip_controller.h"
-class BaseTabRenderer;
+class BaseTab;
class BaseTabStrip;
struct TabRendererData;
@@ -27,12 +27,12 @@ class BrowserTabStripController : public TabStripController,
TabStripModel* model() const { return model_; }
bool IsCommandEnabledForTab(TabStripModel::ContextMenuCommand command_id,
- BaseTabRenderer* tab) const;
+ BaseTab* tab) const;
bool IsCommandCheckedForTab(TabStripModel::ContextMenuCommand command_id,
- BaseTabRenderer* tab) const;
+ BaseTab* tab) const;
void ExecuteCommandForTab(TabStripModel::ContextMenuCommand command_id,
- BaseTabRenderer* tab);
- bool IsTabPinned(BaseTabRenderer* tab);
+ BaseTab* tab);
+ bool IsTabPinned(BaseTab* tab);
// TabStripController implementation:
virtual int GetCount() const;
@@ -43,7 +43,7 @@ class BrowserTabStripController : public TabStripController,
virtual bool IsNewTabPage(int model_index) const;
virtual void SelectTab(int model_index);
virtual void CloseTab(int model_index);
- virtual void ShowContextMenu(BaseTabRenderer* tab, const gfx::Point& p);
+ virtual void ShowContextMenu(BaseTab* tab, const gfx::Point& p);
virtual void UpdateLoadingAnimations();
virtual int HasAvailableDragActions() const;
virtual void PerformDrop(bool drop_before, int index, const GURL& url);
@@ -85,10 +85,10 @@ class BrowserTabStripController : public TabStripController,
void StartHighlightTabsForCommand(
TabStripModel::ContextMenuCommand command_id,
- BaseTabRenderer* tab);
+ BaseTab* tab);
void StopHighlightTabsForCommand(
TabStripModel::ContextMenuCommand command_id,
- BaseTabRenderer* tab);
+ BaseTab* tab);
Profile* profile() const { return model_->profile(); }
diff --git a/chrome/browser/views/tabs/dragged_tab_controller.cc b/chrome/browser/views/tabs/dragged_tab_controller.cc
index f3f2fff..a21779b 100644
--- a/chrome/browser/views/tabs/dragged_tab_controller.cc
+++ b/chrome/browser/views/tabs/dragged_tab_controller.cc
@@ -20,11 +20,12 @@
#include "chrome/browser/tabs/tab_strip_model.h"
#include "chrome/browser/metrics/user_metrics.h"
#include "chrome/browser/views/frame/browser_view.h"
-#include "chrome/browser/views/tabs/base_tab_renderer.h"
+#include "chrome/browser/views/tabs/base_tab.h"
#include "chrome/browser/views/tabs/base_tab_strip.h"
#include "chrome/browser/views/tabs/browser_tab_strip_controller.h"
#include "chrome/browser/views/tabs/dragged_tab_view.h"
#include "chrome/browser/views/tabs/native_view_photobooth.h"
+#include "chrome/browser/views/tabs/tab.h"
#include "chrome/browser/views/tabs/tab_strip.h"
#include "chrome/common/notification_service.h"
#include "gfx/canvas.h"
@@ -312,7 +313,7 @@ class DraggedTabController::DockDisplayer : public AnimationDelegate {
///////////////////////////////////////////////////////////////////////////////
// DraggedTabController, public:
-DraggedTabController::DraggedTabController(BaseTabRenderer* source_tab,
+DraggedTabController::DraggedTabController(BaseTab* source_tab,
BaseTabStrip* source_tabstrip)
: dragged_contents_(NULL),
original_delegate_(NULL),
@@ -801,7 +802,7 @@ void DraggedTabController::Attach(BaseTabStrip* attached_tabstrip,
// And we don't need the dragged view.
view_.reset();
- BaseTabRenderer* tab = GetTabMatchingDraggedContents(attached_tabstrip_);
+ BaseTab* tab = GetTabMatchingDraggedContents(attached_tabstrip_);
if (!tab) {
// There is no Tab in |attached_tabstrip| that corresponds to the dragged
@@ -978,7 +979,7 @@ gfx::Point DraggedTabController::GetAttachedTabDragPoint(
return gfx::Point(x, y);
}
-BaseTabRenderer* DraggedTabController::GetTabMatchingDraggedContents(
+BaseTab* DraggedTabController::GetTabMatchingDraggedContents(
BaseTabStrip* tabstrip) const {
int model_index =
GetModel(tabstrip)->GetIndexOfTabContents(dragged_contents_);
@@ -1173,12 +1174,12 @@ void DraggedTabController::EnsureDraggedView(const TabRendererData& data) {
if (!view_.get()) {
gfx::Rect tab_bounds;
dragged_contents_->GetContainerBounds(&tab_bounds);
- BaseTabRenderer* renderer = source_tabstrip_->CreateTabForDragging();
+ BaseTab* renderer = source_tabstrip_->CreateTabForDragging();
renderer->SetData(data);
// DraggedTabView takes ownership of renderer.
view_.reset(new DraggedTabView(renderer, mouse_offset_,
tab_bounds.size(),
- TabRenderer::GetMinimumSelectedSize()));
+ Tab::GetMinimumSelectedSize()));
}
}
diff --git a/chrome/browser/views/tabs/dragged_tab_controller.h b/chrome/browser/views/tabs/dragged_tab_controller.h
index 8e3355f..c1e62df 100644
--- a/chrome/browser/views/tabs/dragged_tab_controller.h
+++ b/chrome/browser/views/tabs/dragged_tab_controller.h
@@ -15,7 +15,7 @@
namespace views {
class View;
}
-class BaseTabRenderer;
+class BaseTab;
class BaseTabStrip;
class DraggedTabView;
class NativeViewPhotobooth;
@@ -38,7 +38,7 @@ class DraggedTabController : public TabContentsDelegate,
public NotificationObserver,
public MessageLoopForUI::Observer {
public:
- DraggedTabController(BaseTabRenderer* source_tab,
+ DraggedTabController(BaseTab* source_tab,
BaseTabStrip* source_tabstrip);
virtual ~DraggedTabController();
@@ -204,7 +204,7 @@ class DraggedTabController : public TabContentsDelegate,
// Finds the Tab within the specified TabStrip that corresponds to the
// dragged TabContents.
- BaseTabRenderer* GetTabMatchingDraggedContents(BaseTabStrip* tabstrip) const;
+ BaseTab* GetTabMatchingDraggedContents(BaseTabStrip* tabstrip) const;
// Does the work for EndDrag. If we actually started a drag and |how_end| is
// not TAB_DESTROYED then one of EndDrag or RevertDrag is invoked.
@@ -266,7 +266,7 @@ class DraggedTabController : public TabContentsDelegate,
BaseTabStrip* attached_tabstrip_;
// If attached this is the tab we're dragging.
- BaseTabRenderer* attached_tab_;
+ BaseTab* attached_tab_;
// The visual representation of the dragged Tab.
scoped_ptr<DraggedTabView> view_;
diff --git a/chrome/browser/views/tabs/side_tab.cc b/chrome/browser/views/tabs/side_tab.cc
index c134b59..58da29d 100644
--- a/chrome/browser/views/tabs/side_tab.cc
+++ b/chrome/browser/views/tabs/side_tab.cc
@@ -23,101 +23,42 @@ const int kTitleCloseSpacing = 4;
const SkScalar kRoundRectRadius = 5;
const SkColor kTabBackgroundColor = SK_ColorWHITE;
const SkAlpha kBackgroundTabAlpha = 170;
-static const int kHoverDurationMs = 900;
-
-static SkBitmap* waiting_animation_frames = NULL;
-static SkBitmap* loading_animation_frames = NULL;
-static int loading_animation_frame_count = 0;
-static int waiting_animation_frame_count = 0;
-static int waiting_to_loading_frame_count_ratio = 0;
};
-// static
-gfx::Font* SideTab::font_ = NULL;
-SkBitmap* SideTab::close_button_n_ = NULL;
-SkBitmap* SideTab::close_button_h_ = NULL;
-SkBitmap* SideTab::close_button_p_ = NULL;
-
////////////////////////////////////////////////////////////////////////////////
// SideTab, public:
SideTab::SideTab(TabController* controller)
- : BaseTabRenderer(controller),
- close_button_(NULL),
- loading_animation_frame_(0) {
- InitClass();
-
- views::ImageButton* close_button = new views::ImageButton(this);
- close_button->SetImage(views::CustomButton::BS_NORMAL, close_button_n_);
- close_button->SetImage(views::CustomButton::BS_HOT, close_button_h_);
- close_button->SetImage(views::CustomButton::BS_PUSHED, close_button_p_);
- close_button_ = close_button;
- AddChildView(close_button_);
-
- hover_animation_.reset(new SlideAnimation(this));
- hover_animation_->SetSlideDuration(kHoverDurationMs);
-
- SetContextMenuController(this);
+ : BaseTab(controller) {
}
SideTab::~SideTab() {
}
////////////////////////////////////////////////////////////////////////////////
-// SideTab, AnimationDelegate implementation:
-
-void SideTab::AnimationProgressed(const Animation* animation) {
- SchedulePaint();
-}
-
-void SideTab::AnimationCanceled(const Animation* animation) {
- AnimationEnded(animation);
-}
-
-void SideTab::AnimationEnded(const Animation* animation) {
- SchedulePaint();
-}
-
-////////////////////////////////////////////////////////////////////////////////
-// SideTab, views::ButtonListener implementation:
-
-void SideTab::ButtonPressed(views::Button* sender, const views::Event& event) {
- DCHECK(sender == close_button_);
- controller()->CloseTab(this);
-}
-
-////////////////////////////////////////////////////////////////////////////////
-// SideTab, views::ContextMenuController implementation:
-
-void SideTab::ShowContextMenu(views::View* source,
- const gfx::Point& p,
- bool is_mouse_gesture) {
- controller()->ShowContextMenu(this, p);
-}
-
-////////////////////////////////////////////////////////////////////////////////
// SideTab, views::View overrides:
void SideTab::Layout() {
int icon_y;
int icon_x = icon_y = (height() - kIconSize) / 2;
+ // TODO(sky): big mini icons.
icon_bounds_.SetRect(icon_x, icon_y, kIconSize, kIconSize);
- gfx::Size ps = close_button_->GetPreferredSize();
+ gfx::Size ps = close_button()->GetPreferredSize();
int close_y = (height() - ps.height()) / 2;
- close_button_->SetBounds(
+ close_button()->SetBounds(
std::max(0, width() - ps.width() - close_y),
close_y,
ps.width(),
ps.height());
- int title_y = (height() - font_->height()) / 2;
+ int title_y = (height() - font_height()) / 2;
int title_x = icon_bounds_.right() + kIconTitleSpacing;
title_bounds_.SetRect(
title_x,
title_y,
- std::max(0, close_button_->x() - kTitleCloseSpacing - title_x),
- font_->height());
+ std::max(0, close_button()->x() - kTitleCloseSpacing - title_x),
+ font_height());
}
void SideTab::Paint(gfx::Canvas* canvas) {
@@ -128,19 +69,18 @@ void SideTab::Paint(gfx::Canvas* canvas) {
FillTabShapePath(&tab_shape);
canvas->drawPath(tab_shape, paint);
- PaintIcon(canvas);
- canvas->DrawStringInt(UTF16ToWideHack(data().title), *font_,
- SK_ColorBLACK, title_bounds_.x(), title_bounds_.y(),
- title_bounds_.width(), title_bounds_.height());
+ PaintIcon(canvas, icon_bounds_.x(), icon_bounds_.y());
+ PaintTitle(canvas, SK_ColorBLACK);
- if (!controller()->IsTabSelected(this) &&
- GetThemeProvider()->ShouldUseNativeFrame()) {
+ if (!IsSelected() && GetThemeProvider()->ShouldUseNativeFrame()) {
// Make sure un-selected tabs are somewhat transparent.
SkPaint paint;
SkAlpha opacity = kBackgroundTabAlpha;
- if (hover_animation_->is_animating())
- opacity = static_cast<SkAlpha>(hover_animation_->GetCurrentValue() * 255);
+ if (hover_animation() && hover_animation()->is_animating()) {
+ opacity =
+ static_cast<SkAlpha>(hover_animation()->GetCurrentValue() * 255);
+ }
paint.setColor(SkColorSetARGB(kBackgroundTabAlpha, 255, 255, 255));
paint.setXfermodeMode(SkXfermode::kDstIn_Mode);
@@ -154,45 +94,6 @@ gfx::Size SideTab::GetPreferredSize() {
return gfx::Size(0, 27);
}
-void SideTab::OnMouseEntered(const views::MouseEvent& event) {
- hover_animation_->SetTweenType(Tween::EASE_OUT);
- hover_animation_->Show();
-}
-
-void SideTab::OnMouseExited(const views::MouseEvent& event) {
- hover_animation_->SetTweenType(Tween::EASE_IN);
- hover_animation_->Hide();
-}
-
-bool SideTab::OnMousePressed(const views::MouseEvent& event) {
- if (event.IsOnlyLeftMouseButton())
- controller()->SelectTab(this);
- return true;
-}
-
-// TODO(sky): refactor to BaseTabRenderer.
-void SideTab::AdvanceLoadingAnimation(TabRendererData::NetworkState state) {
- // The waiting animation is the reverse of the loading animation, but at a
- // different rate - the following reverses and scales the animation_frame_
- // so that the frame is at an equivalent position when going from one
- // animation to the other.
- if (state == TabRendererData::NETWORK_STATE_WAITING &&
- state == TabRendererData::NETWORK_STATE_LOADING) {
- loading_animation_frame_ = loading_animation_frame_count -
- (loading_animation_frame_ / waiting_to_loading_frame_count_ratio);
- }
-
- if (state != TabRendererData::NETWORK_STATE_NONE) {
- loading_animation_frame_ = ++loading_animation_frame_ %
- ((state == TabRendererData::NETWORK_STATE_WAITING) ?
- waiting_animation_frame_count :
- loading_animation_frame_count);
- } else {
- loading_animation_frame_ = 0;
- }
- SchedulePaint();
-}
-
////////////////////////////////////////////////////////////////////////////////
// SideTab, private:
@@ -214,60 +115,3 @@ void SideTab::FillTabShapePath(gfx::Path* path) {
path->lineTo(SkIntToScalar(kRoundRectRadius), 0);
path->close();
}
-
-void SideTab::PaintIcon(gfx::Canvas* canvas) {
- if (data().network_state == TabRendererData::NETWORK_STATE_NONE) {
- canvas->DrawBitmapInt(data().favicon, 0, 0, kIconSize, kIconSize,
- icon_bounds_.x(), icon_bounds_.y(),
- icon_bounds_.width(), icon_bounds_.height(), false);
- } else {
- PaintLoadingAnimation(canvas);
- }
-}
-
-void SideTab::PaintLoadingAnimation(gfx::Canvas* canvas) {
- SkBitmap* frames =
- (data().network_state == TabRendererData::NETWORK_STATE_WAITING) ?
- waiting_animation_frames : loading_animation_frames;
- int image_size = frames->height();
- int image_offset = loading_animation_frame_ * image_size;
- int dst_y = (height() - image_size) / 2;
- canvas->DrawBitmapInt(*frames, image_offset, 0, image_size,
- image_size, icon_bounds_.x(), dst_y, image_size,
- image_size, false);
-}
-
-// static
-void SideTab::InitClass() {
- static bool initialized = false;
- if (!initialized) {
- ResourceBundle& rb = ResourceBundle::GetSharedInstance();
- font_ = new gfx::Font(rb.GetFont(ResourceBundle::BaseFont));
-
- close_button_n_ = rb.GetBitmapNamed(IDR_TAB_CLOSE);
- close_button_h_ = rb.GetBitmapNamed(IDR_TAB_CLOSE_H);
- close_button_p_ = rb.GetBitmapNamed(IDR_TAB_CLOSE_P);
-
- // The loading animation image is a strip of states. Each state must be
- // square, so the height must divide the width evenly.
- loading_animation_frames = rb.GetBitmapNamed(IDR_THROBBER);
- DCHECK(loading_animation_frames);
- DCHECK(loading_animation_frames->width() %
- loading_animation_frames->height() == 0);
- loading_animation_frame_count =
- loading_animation_frames->width() / loading_animation_frames->height();
-
- waiting_animation_frames = rb.GetBitmapNamed(IDR_THROBBER_WAITING);
- DCHECK(waiting_animation_frames);
- DCHECK(waiting_animation_frames->width() %
- waiting_animation_frames->height() == 0);
- waiting_animation_frame_count =
- waiting_animation_frames->width() / waiting_animation_frames->height();
-
- waiting_to_loading_frame_count_ratio =
- waiting_animation_frame_count / loading_animation_frame_count;
-
- initialized = true;
- }
-}
-
diff --git a/chrome/browser/views/tabs/side_tab.h b/chrome/browser/views/tabs/side_tab.h
index 79fbac8..48918e2 100644
--- a/chrome/browser/views/tabs/side_tab.h
+++ b/chrome/browser/views/tabs/side_tab.h
@@ -6,74 +6,31 @@
#define CHROME_BROWSER_VIEWS_TABS_SIDE_TAB_H_
#include "app/slide_animation.h"
-#include "chrome/browser/views/tabs/base_tab_renderer.h"
+#include "chrome/browser/views/tabs/base_tab.h"
#include "gfx/font.h"
-#include "views/controls/button/button.h"
-#include "views/view.h"
class SideTab;
class TabStripController;
-class SideTab : public BaseTabRenderer,
- public views::ContextMenuController,
- public views::ButtonListener,
- public AnimationDelegate {
+class SideTab : public BaseTab {
public:
explicit SideTab(TabController* controller);
virtual ~SideTab();
- // AnimationDelegate implementation:
- virtual void AnimationProgressed(const Animation* animation);
- virtual void AnimationCanceled(const Animation* animation);
- virtual void AnimationEnded(const Animation* animation);
-
- // views::ButtonListener implementation:
- virtual void ButtonPressed(views::Button* sender, const views::Event& event);
-
- // views::ContextMenuController implementation:
- virtual void ShowContextMenu(views::View* source,
- const gfx::Point& p,
- bool is_mouse_gesture);
-
// views::View Overrides:
virtual void Layout();
virtual void Paint(gfx::Canvas* canvas);
virtual gfx::Size GetPreferredSize();
- virtual void OnMouseEntered(const views::MouseEvent& event);
- virtual void OnMouseExited(const views::MouseEvent& event);
- virtual bool OnMousePressed(const views::MouseEvent& event);
protected:
- // BaseTabRenderer overrides.
- virtual void AdvanceLoadingAnimation(TabRendererData::NetworkState state);
+ virtual const gfx::Rect& title_bounds() const { return title_bounds_; }
private:
void FillTabShapePath(gfx::Path* path);
- // Paint various components of the tab.
- void PaintIcon(gfx::Canvas* canvas);
- void PaintLoadingAnimation(gfx::Canvas* canvas);
-
- // Loads class-specific resources.
- static void InitClass();
-
gfx::Rect icon_bounds_;
gfx::Rect title_bounds_;
- views::Button* close_button_;
-
- // Hover animation.
- scoped_ptr<SlideAnimation> hover_animation_;
-
- static gfx::Font* font_;
- static SkBitmap* close_button_n_;
- static SkBitmap* close_button_m_;
- static SkBitmap* close_button_h_;
- static SkBitmap* close_button_p_;
-
- // The current index into the Animation image strip.
- int loading_animation_frame_;
-
DISALLOW_COPY_AND_ASSIGN(SideTab);
};
diff --git a/chrome/browser/views/tabs/side_tab_strip.cc b/chrome/browser/views/tabs/side_tab_strip.cc
index 2a973d5..216d103 100644
--- a/chrome/browser/views/tabs/side_tab_strip.cc
+++ b/chrome/browser/views/tabs/side_tab_strip.cc
@@ -57,30 +57,28 @@ void SideTabStrip::StartHighlight(int model_index) {
void SideTabStrip::StopAllHighlighting() {
}
-BaseTabRenderer* SideTabStrip::GetBaseTabAtModelIndex(int model_index) const {
- return static_cast<BaseTabRenderer*>(GetChildViewAt(model_index));
+BaseTab* SideTabStrip::CreateTabForDragging() {
+ SideTab* tab = new SideTab(NULL);
+ // Make sure the dragged tab shares our theme provider. We need to explicitly
+ // do this as during dragging there isn't a theme provider.
+ tab->set_theme_provider(GetThemeProvider());
+ return tab;
}
-BaseTabRenderer* SideTabStrip::CreateTabForDragging() {
- return new SideTab(NULL);
-}
-
-void SideTabStrip::RemoveTabAt(int index, bool initiated_close) {
- View* v = GetChildViewAt(index);
- RemoveChildView(v);
- delete v;
+void SideTabStrip::RemoveTabAt(int model_index, bool initiated_close) {
+ RemoveAndDeleteTab(GetBaseTabAtModelIndex(model_index));
Layout();
}
void SideTabStrip::SelectTabAt(int old_model_index, int new_model_index) {
- GetChildViewAt(new_model_index)->SchedulePaint();
+ GetBaseTabAtModelIndex(new_model_index)->SchedulePaint();
}
void SideTabStrip::TabTitleChangedNotLoading(int model_index) {
}
void SideTabStrip::SetTabData(int model_index, const TabRendererData& data) {
- BaseTabRenderer* tab = GetBaseTabAtModelIndex(model_index);
+ BaseTab* tab = GetBaseTabAtModelIndex(model_index);
tab->SetData(data);
tab->SchedulePaint();
}
@@ -89,7 +87,7 @@ gfx::Size SideTabStrip::GetPreferredSize() {
return gfx::Size(kTabStripWidth, 0);
}
-BaseTabRenderer* SideTabStrip::CreateTab() {
+BaseTab* SideTabStrip::CreateTab() {
return new SideTab(this);
}
@@ -99,7 +97,7 @@ void SideTabStrip::GenerateIdealBounds() {
int y = layout_rect.y();
for (int i = 0; i < tab_count(); ++i) {
- BaseTabRenderer* tab = base_tab_at_tab_index(i);
+ BaseTab* tab = base_tab_at_tab_index(i);
if (!tab->closing()) {
gfx::Rect bounds = gfx::Rect(layout_rect.x(), y, layout_rect.width(),
tab->GetPreferredSize().height());
diff --git a/chrome/browser/views/tabs/side_tab_strip.h b/chrome/browser/views/tabs/side_tab_strip.h
index 67f9e82..fb23a4f 100644
--- a/chrome/browser/views/tabs/side_tab_strip.h
+++ b/chrome/browser/views/tabs/side_tab_strip.h
@@ -25,8 +25,7 @@ class SideTabStrip : public BaseTabStrip {
virtual void StartHighlight(int model_index);
virtual void StopAllHighlighting();
- virtual BaseTabRenderer* GetBaseTabAtModelIndex(int model_index) const;
- virtual BaseTabRenderer* CreateTabForDragging();
+ virtual BaseTab* CreateTabForDragging();
virtual void RemoveTabAt(int model_index, bool initiated_close);
virtual void SelectTabAt(int old_model_index, int new_model_index);
virtual void TabTitleChangedNotLoading(int model_index);
@@ -37,13 +36,13 @@ class SideTabStrip : public BaseTabStrip {
protected:
// BaseTabStrip overrides:
- virtual BaseTabRenderer* CreateTab();
+ virtual BaseTab* CreateTab();
virtual void GenerateIdealBounds();
virtual void StartInsertTabAnimation(int model_index, bool foreground);
virtual void StartMoveTabAnimation();
virtual void StopAnimating(bool layout);
- virtual void StartedDraggingTab(BaseTabRenderer* tab) {}
- virtual void StoppedDraggingTab(BaseTabRenderer* tab) {}
+ virtual void StartedDraggingTab(BaseTab* tab) {}
+ virtual void StoppedDraggingTab(BaseTab* tab) {}
private:
DISALLOW_COPY_AND_ASSIGN(SideTabStrip);
diff --git a/chrome/browser/views/tabs/tab.cc b/chrome/browser/views/tabs/tab.cc
index 9920f69..7c91604 100644
--- a/chrome/browser/views/tabs/tab.cc
+++ b/chrome/browser/views/tabs/tab.cc
@@ -4,143 +4,348 @@
#include "chrome/browser/views/tabs/tab.h"
-#include "app/l10n_util.h"
-#include "app/menus/simple_menu_model.h"
+#include <limits>
+
+#include "app/multi_animation.h"
#include "app/resource_bundle.h"
-#include "base/compiler_specific.h"
-#include "chrome/browser/tab_menu_model.h"
-#include "chrome/browser/views/frame/browser_view.h"
-#include "chrome/browser/views/tabs/tab_strip.h"
+#include "app/slide_animation.h"
+#include "app/throb_animation.h"
+#include "base/utf_string_conversions.h"
+#include "chrome/browser/browser_theme_provider.h"
+#include "chrome/browser/defaults.h"
#include "gfx/canvas.h"
+#include "gfx/favicon_size.h"
#include "gfx/font.h"
#include "gfx/path.h"
-#include "gfx/size.h"
+#include "gfx/skbitmap_operations.h"
+#include "grit/app_resources.h"
#include "grit/generated_resources.h"
-#include "views/controls/menu/menu_2.h"
+#include "grit/theme_resources.h"
+#include "third_party/skia/include/effects/SkGradientShader.h"
+#include "views/controls/button/image_button.h"
#include "views/widget/tooltip_manager.h"
#include "views/widget/widget.h"
-
-const std::string Tab::kTabClassName = "browser/tabs/Tab";
-
+#include "views/window/non_client_view.h"
+#include "views/window/window.h"
+
+static const int kLeftPadding = 16;
+static const int kTopPadding = 6;
+static const int kRightPadding = 15;
+static const int kBottomPadding = 5;
+static const int kDropShadowHeight = 2;
+static const int kToolbarOverlap = 1;
+static const int kFavIconTitleSpacing = 4;
+static const int kTitleCloseButtonSpacing = 5;
+static const int kStandardTitleWidth = 175;
+static const int kCloseButtonVertFuzz = 0;
+static const int kCloseButtonHorzFuzz = 5;
+
+// Vertical adjustment to the favicon when the tab has a large icon.
+static const int kAppTapFaviconVerticalAdjustment = 2;
+
+// When a non-mini-tab becomes a mini-tab the width of the tab animates. If
+// the width of a mini-tab is >= kMiniTabRendererAsNormalTabWidth then the tab
+// is rendered as a normal tab. This is done to avoid having the title
+// immediately disappear when transitioning a tab from normal to mini-tab.
+static const int kMiniTabRendererAsNormalTabWidth =
+ browser_defaults::kMiniTabWidth + 30;
+
+// How opaque to make the hover state (out of 1).
+static const double kHoverOpacity = 0.33;
+
+// Used when |render_as_new_tab| is true.
+static SkBitmap* new_tab_mask = NULL;
+static SkBitmap* new_tab_shadow = NULL;
+
+Tab::TabImage Tab::tab_alpha = {0};
+Tab::TabImage Tab::tab_active = {0};
+Tab::TabImage Tab::tab_active_nano = {0};
+Tab::TabImage Tab::tab_inactive = {0};
+Tab::TabImage Tab::tab_inactive_nano = {0};
+Tab::TabImage Tab::tab_alpha_nano = {0};
+
+// Durations for the various parts of the mini tab title animation.
+static const int kMiniTitleChangeAnimationDuration1MS = 1000;
+static const int kMiniTitleChangeAnimationDuration2MS = 500;
+static const int kMiniTitleChangeAnimationDuration3MS = 800;
+
+// Offset from the right edge for the start of the mini title change animation.
+static const int kMiniTitleChangeInitialXOffset = 6;
+
+// Radius of the radial gradient used for mini title change animation.
+static const int kMiniTitleChangeGradientRadius = 20;
+
+// Colors of the gradient used during the mini title change animation.
+static const SkColor kMiniTitleChangeGradientColor1 = SK_ColorWHITE;
+static const SkColor kMiniTitleChangeGradientColor2 =
+ SkColorSetARGB(0, 255, 255, 255);
+
+// Hit mask constants.
static const SkScalar kTabCapWidth = 15;
static const SkScalar kTabTopCurveWidth = 4;
static const SkScalar kTabBottomCurveWidth = 3;
-///////////////////////////////////////////////////////////////////////////////
+namespace {
+
+void InitTabResources() {
+ static bool initialized = false;
+ if (initialized)
+ return;
+
+ initialized = true;
+ Tab::LoadTabImages();
+}
+
+} // namespace
+
+// static
+const char Tab::kViewClassName[] = "browser/tabs/Tab";
+
+////////////////////////////////////////////////////////////////////////////////
// Tab, public:
Tab::Tab(TabController* controller)
- : TabRenderer(controller) {
- close_button()->SetTooltipText(l10n_util::GetString(IDS_TOOLTIP_CLOSE_TAB));
- close_button()->SetAccessibleName(l10n_util::GetString(IDS_ACCNAME_CLOSE));
- close_button()->SetAnimationDuration(0);
- SetContextMenuController(this);
+ : BaseTab(controller),
+ showing_icon_(false),
+ showing_close_button_(false),
+ close_button_color_(NULL),
+ render_as_new_tab_(false),
+ render_unselected_(false),
+ alpha_(1) {
+ InitTabResources();
}
Tab::~Tab() {
}
-///////////////////////////////////////////////////////////////////////////////
-// Tab, TabRenderer overrides:
+void Tab::SizeToNewTabButtonImages() {
+ SetBounds(x(), y(), new_tab_shadow->width(), new_tab_shadow->height());
+}
-bool Tab::IsSelected() const {
- return controller() ? controller()->IsTabSelected(this) : true;
+void Tab::StartMiniTabTitleAnimation() {
+ if (!mini_title_animation_.get()) {
+ MultiAnimation::Parts parts;
+ parts.push_back(MultiAnimation::Part(kMiniTitleChangeAnimationDuration1MS,
+ Tween::EASE_OUT));
+ parts.push_back(MultiAnimation::Part(kMiniTitleChangeAnimationDuration2MS,
+ Tween::ZERO));
+ parts.push_back(MultiAnimation::Part(kMiniTitleChangeAnimationDuration3MS,
+ Tween::EASE_IN));
+ mini_title_animation_.reset(new MultiAnimation(parts));
+ mini_title_animation_->SetContainer(animation_container());
+ mini_title_animation_->set_delegate(this);
+ }
+ mini_title_animation_->Start();
}
-///////////////////////////////////////////////////////////////////////////////
-// Tab, views::View overrides:
+void Tab::StopMiniTabTitleAnimation() {
+ if (mini_title_animation_.get())
+ mini_title_animation_->Stop();
+}
-bool Tab::HasHitTestMask() const {
- return true;
+void Tab::PaintIcon(gfx::Canvas* canvas) {
+ BaseTab::PaintIcon(canvas, favicon_bounds_.x(), favicon_bounds_.y());
}
-void Tab::GetHitTestMask(gfx::Path* mask) const {
- MakePathForTab(mask);
+// static
+gfx::Size Tab::GetMinimumUnselectedSize() {
+ InitTabResources();
+
+ gfx::Size minimum_size;
+ minimum_size.set_width(kLeftPadding + kRightPadding);
+ // Since we use bitmap images, the real minimum height of the image is
+ // defined most accurately by the height of the end cap images.
+ minimum_size.set_height(tab_active.image_l->height());
+ return minimum_size;
}
-bool Tab::OnMousePressed(const views::MouseEvent& event) {
- if (event.IsOnlyLeftMouseButton()) {
- // Store whether or not we were selected just now... we only want to be
- // able to drag foreground tabs, so we don't start dragging the tab if
- // it was in the background.
- bool just_selected = !IsSelected();
- if (just_selected) {
- controller()->SelectTab(this);
- }
- controller()->MaybeStartDrag(this, event);
- }
- return true;
+// static
+gfx::Size Tab::GetMinimumSelectedSize() {
+ gfx::Size minimum_size = GetMinimumUnselectedSize();
+ minimum_size.set_width(kLeftPadding + kFavIconSize + kRightPadding);
+ return minimum_size;
}
-bool Tab::OnMouseDragged(const views::MouseEvent& event) {
- controller()->ContinueDrag(event);
- return true;
+// static
+gfx::Size Tab::GetStandardSize() {
+ gfx::Size standard_size = GetMinimumUnselectedSize();
+ standard_size.set_width(
+ standard_size.width() + kFavIconTitleSpacing + kStandardTitleWidth);
+ return standard_size;
}
-void Tab::OnMouseReleased(const views::MouseEvent& event, bool canceled) {
- // Notify the drag helper that we're done with any potential drag operations.
- // Clean up the drag helper, which is re-created on the next mouse press.
- // In some cases, ending the drag will schedule the tab for destruction; if
- // so, bail immediately, since our members are already dead and we shouldn't
- // do anything else except drop the tab where it is.
- if (controller()->EndDrag(canceled))
- return;
+// static
+int Tab::GetMiniWidth() {
+ return browser_defaults::kMiniTabWidth;
+}
- // Close tab on middle click, but only if the button is released over the tab
- // (normal windows behavior is to discard presses of a UI element where the
- // releases happen off the element).
- if (event.IsMiddleMouseButton() && HitTest(event.location()))
- controller()->CloseTab(this);
-}
-
-bool Tab::GetTooltipText(const gfx::Point& p, std::wstring* tooltip) {
- std::wstring title = GetTitle();
- if (!title.empty()) {
- // Only show the tooltip if the title is truncated.
- gfx::Font font;
- if (font.GetStringWidth(title) > title_bounds().width()) {
- *tooltip = title;
- return true;
- }
+////////////////////////////////////////////////////////////////////////////////
+// Tab, protected:
+
+void Tab::DataChanged(const TabRendererData& old) {
+ if (data().phantom)
+ StopMiniTabTitleAnimation();
+
+ if (data().blocked != old.blocked) {
+ if (data().blocked)
+ StartPulse();
+ else
+ StopPulse();
}
- return false;
}
-bool Tab::GetTooltipTextOrigin(const gfx::Point& p, gfx::Point* origin) {
- gfx::Font font;
- origin->set_x(title_bounds().x() + 10);
- origin->set_y(-views::TooltipManager::GetTooltipHeight() - 4);
- return true;
-}
+////////////////////////////////////////////////////////////////////////////////
+// Tab, views::View overrides:
-bool Tab::GetAccessibleRole(AccessibilityTypes::Role* role) {
- DCHECK(role);
+void Tab::Paint(gfx::Canvas* canvas) {
+ if (render_as_new_tab_) {
+ if (base::i18n::IsRTL()) {
+ canvas->TranslateInt(width(), 0);
+ canvas->ScaleInt(-1, 1);
+ }
+ PaintAsNewTab(canvas);
+ return;
+ }
- *role = AccessibilityTypes::ROLE_PAGETAB;
- return true;
+ // Don't paint if we're narrower than we can render correctly. (This should
+ // only happen during animations).
+ if (width() < GetMinimumUnselectedSize().width() && !data().mini)
+ return;
+
+ // See if the model changes whether the icons should be painted.
+ const bool show_icon = ShouldShowIcon() && !data().phantom;
+ const bool show_close_button = ShouldShowCloseBox();
+ if (show_icon != showing_icon_ ||
+ show_close_button != showing_close_button_)
+ Layout();
+
+ PaintTabBackground(canvas);
+
+ SkColor title_color = GetThemeProvider()->
+ GetColor(IsSelected() ?
+ BrowserThemeProvider::COLOR_TAB_TEXT :
+ BrowserThemeProvider::COLOR_BACKGROUND_TAB_TEXT);
+
+ if (!data().mini || width() > kMiniTabRendererAsNormalTabWidth)
+ PaintTitle(canvas, title_color);
+
+ if (show_icon)
+ PaintIcon(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;
+ ResourceBundle& rb = ResourceBundle::GetSharedInstance();
+ close_button()->SetBackground(close_button_color_,
+ rb.GetBitmapNamed(IDR_TAB_CLOSE),
+ rb.GetBitmapNamed(IDR_TAB_CLOSE_MASK));
+ }
}
-///////////////////////////////////////////////////////////////////////////////
-// Tab, views::ContextMenuController implementation:
+void Tab::Layout() {
+ gfx::Rect lb = GetLocalBounds(false);
+ if (lb.IsEmpty())
+ return;
+ lb.Inset(kLeftPadding, kTopPadding, kRightPadding, kBottomPadding);
+
+ // The height of the content of the Tab is the largest of the favicon,
+ // the title text and the close button graphic.
+ int content_height = std::max(kFavIconSize, font_height());
+ content_height = std::max(content_height, close_button_height());
+
+ // Size the Favicon.
+ showing_icon_ = ShouldShowIcon();
+ if (showing_icon_) {
+ // Use the size of the favicon as apps use a bigger favicon size.
+ int favicon_size =
+ !data().favicon.empty() ? data().favicon.width() : kFavIconSize;
+ int favicon_top = kTopPadding + content_height / 2 - favicon_size / 2;
+ int favicon_left = lb.x();
+ if (favicon_size != kFavIconSize) {
+ favicon_left -= (favicon_size - kFavIconSize) / 2;
+ favicon_top -= kAppTapFaviconVerticalAdjustment;
+ }
+ favicon_bounds_.SetRect(favicon_left, favicon_top,
+ favicon_size, favicon_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() - favicon_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);
+ }
+ }
+ } else {
+ favicon_bounds_.SetRect(lb.x(), lb.y(), 0, 0);
+ }
-void Tab::ShowContextMenu(views::View* source,
- const gfx::Point& p,
- bool is_mouse_gesture) {
- controller()->ShowContextMenu(this, p);
-}
+ // Size the Close button.
+ showing_close_button_ = ShouldShowCloseBox();
+ if (showing_close_button_) {
+ int close_button_top =
+ kTopPadding + kCloseButtonVertFuzz +
+ (content_height - close_button_height()) / 2;
+ // If the ratio of the close button size to tab width exceeds the maximum.
+ close_button()->SetBounds(lb.width() + kCloseButtonHorzFuzz,
+ close_button_top, close_button_width(),
+ close_button_height());
+ close_button()->SetVisible(true);
+ } else {
+ close_button()->SetBounds(0, 0, 0, 0);
+ close_button()->SetVisible(false);
+ }
+
+ int title_left = favicon_bounds_.right() + kFavIconTitleSpacing;
+ int title_top = kTopPadding + (content_height - font_height()) / 2;
+ // Size the Title text to fill the remaining space.
+ if (!data().mini || width() >= kMiniTabRendererAsNormalTabWidth) {
+ // If the user has big fonts, the title will appear rendered too far down
+ // on the y-axis if we use the regular top padding, so we need to adjust it
+ // so that the text appears centered.
+ gfx::Size minimum_size = GetMinimumUnselectedSize();
+ int text_height = title_top + font_height() + kBottomPadding;
+ if (text_height > minimum_size.height())
+ title_top -= (text_height - minimum_size.height()) / 2;
+
+ int title_width;
+ if (close_button()->IsVisible()) {
+ title_width = std::max(close_button()->x() -
+ kTitleCloseButtonSpacing - title_left, 0);
+ } else {
+ title_width = std::max(lb.width() - title_left, 0);
+ }
+ title_bounds_.SetRect(title_left, title_top, title_width, font_height());
+ } else {
+ title_bounds_.SetRect(title_left, title_top, 0, 0);
+ }
-///////////////////////////////////////////////////////////////////////////////
-// views::ButtonListener implementation:
+ // Certain UI elements within the Tab (the favicon, etc.) are not represented
+ // as child Views (which is the preferred method). Instead, these UI elements
+ // are drawn directly on the canvas from within Tab::Paint(). The Tab's child
+ // Views (for example, the Tab's close button which is a views::Button
+ // instance) are automatically mirrored by the mirroring infrastructure in
+ // views. The elements Tab draws directly on the canvas need to be manually
+ // mirrored if the View's layout is right-to-left.
+ favicon_bounds_.set_x(MirroredLeftPointForRect(favicon_bounds_));
+ title_bounds_.set_x(MirroredLeftPointForRect(title_bounds_));
+}
-void Tab::ButtonPressed(views::Button* sender, const views::Event& event) {
- if (sender == close_button())
- controller()->CloseTab(this);
+void Tab::ThemeChanged() {
+ BaseTab::ThemeChanged();
+ Tab::LoadTabImages();
}
-///////////////////////////////////////////////////////////////////////////////
-// Tab, private:
+bool Tab::HasHitTestMask() const {
+ return true;
+}
-void Tab::MakePathForTab(gfx::Path* path) const {
+void Tab::GetHitTestMask(gfx::Path* path) const {
DCHECK(path);
SkScalar h = SkIntToScalar(height());
@@ -165,3 +370,334 @@ void Tab::MakePathForTab(gfx::Path* path) const {
path->lineTo(0, h);
path->close();
}
+
+bool Tab::GetTooltipTextOrigin(const gfx::Point& p, gfx::Point* origin) {
+ origin->set_x(title_bounds().x() + 10);
+ origin->set_y(-views::TooltipManager::GetTooltipHeight() - 4);
+ return true;
+}
+
+////////////////////////////////////////////////////////////////////////////////
+// Tab, private
+
+void Tab::PaintTabBackground(gfx::Canvas* canvas) {
+ if (IsSelected()) {
+ PaintActiveTabBackground(canvas);
+ } else {
+ if (mini_title_animation_.get() && mini_title_animation_->is_animating())
+ PaintInactiveTabBackgroundWithTitleChange(canvas);
+ else
+ PaintInactiveTabBackground(canvas);
+
+ double throb_value = GetThrobValue();
+ if (throb_value > 0) {
+ SkRect bounds;
+ bounds.set(0, 0, SkIntToScalar(width()), SkIntToScalar(height()));
+ canvas->saveLayerAlpha(&bounds, static_cast<int>(throb_value * 0xff),
+ SkCanvas::kARGB_ClipLayer_SaveFlag);
+ canvas->drawARGB(0, 255, 255, 255, SkXfermode::kClear_Mode);
+ PaintActiveTabBackground(canvas);
+ canvas->restore();
+ }
+ }
+}
+
+void Tab::PaintInactiveTabBackgroundWithTitleChange(gfx::Canvas* canvas) {
+ // Render the inactive tab background. We'll use this for clipping.
+ gfx::Canvas background_canvas(width(), height(), false);
+ PaintInactiveTabBackground(&background_canvas);
+
+ SkBitmap background_image = background_canvas.ExtractBitmap();
+
+ // Draw a radial gradient to hover_canvas.
+ gfx::Canvas hover_canvas(width(), height(), false);
+ int radius = kMiniTitleChangeGradientRadius;
+ int x0 = width() + radius - kMiniTitleChangeInitialXOffset;
+ int x1 = radius;
+ int x2 = -radius;
+ int x;
+ if (mini_title_animation_->current_part_index() == 0) {
+ x = mini_title_animation_->CurrentValueBetween(x0, x1);
+ } else if (mini_title_animation_->current_part_index() == 1) {
+ x = x1;
+ } else {
+ x = mini_title_animation_->CurrentValueBetween(x1, x2);
+ }
+ SkPaint paint;
+ SkPoint loc = { SkIntToScalar(x), SkIntToScalar(0) };
+ SkColor colors[2];
+ colors[0] = kMiniTitleChangeGradientColor1;
+ colors[1] = kMiniTitleChangeGradientColor2;
+ SkShader* shader = SkGradientShader::CreateRadial(
+ loc,
+ SkIntToScalar(radius),
+ colors,
+ NULL,
+ 2,
+ SkShader::kClamp_TileMode);
+ paint.setShader(shader);
+ shader->unref();
+ hover_canvas.FillRectInt(x - radius, -radius, radius * 2, radius * 2, paint);
+
+ // Draw the radial gradient clipped to the background into hover_image.
+ SkBitmap hover_image = SkBitmapOperations::CreateMaskedBitmap(
+ hover_canvas.ExtractBitmap(), background_image);
+
+ // Draw the tab background to the canvas.
+ canvas->DrawBitmapInt(background_image, 0, 0);
+
+ // And then the gradient on top of that.
+ if (mini_title_animation_->current_part_index() == 2) {
+ canvas->saveLayerAlpha(NULL,
+ mini_title_animation_->CurrentValueBetween(255, 0));
+ canvas->DrawBitmapInt(hover_image, 0, 0);
+ canvas->restore();
+ } else {
+ canvas->DrawBitmapInt(hover_image, 0, 0);
+ }
+}
+
+void Tab::PaintInactiveTabBackground(gfx::Canvas* canvas) {
+ bool is_otr = data().off_the_record;
+
+ // The tab image needs to be lined up with the background image
+ // so that it feels partially transparent. These offsets represent the tab
+ // position within the frame background image.
+ int offset = GetX(views::View::APPLY_MIRRORING_TRANSFORMATION) +
+ background_offset_.x();
+
+ int tab_id;
+ if (GetWidget() &&
+ GetWidget()->GetWindow()->GetNonClientView()->UseNativeFrame()) {
+ tab_id = IDR_THEME_TAB_BACKGROUND_V;
+ } else {
+ tab_id = is_otr ? IDR_THEME_TAB_BACKGROUND_INCOGNITO :
+ IDR_THEME_TAB_BACKGROUND;
+ }
+
+ SkBitmap* tab_bg = GetThemeProvider()->GetBitmapNamed(tab_id);
+
+ // App tabs are drawn slightly differently (as nano tabs).
+ TabImage* tab_image = data().app ? &tab_active_nano : &tab_active;
+ TabImage* tab_inactive_image = data().app ? &tab_inactive_nano :
+ &tab_inactive;
+ TabImage* alpha = data().app ? &tab_alpha_nano : &tab_alpha;
+
+ // If the theme is providing a custom background image, then its top edge
+ // should be at the top of the tab. Otherwise, we assume that the background
+ // image is a composited foreground + frame image.
+ int bg_offset_y = GetThemeProvider()->HasCustomImage(tab_id) ?
+ 0 : background_offset_.y();
+
+ // Draw left edge. Don't draw over the toolbar, as we're not the foreground
+ // tab.
+ SkBitmap tab_l = SkBitmapOperations::CreateTiledBitmap(
+ *tab_bg, offset, bg_offset_y, tab_image->l_width, height());
+ SkBitmap theme_l =
+ SkBitmapOperations::CreateMaskedBitmap(tab_l, *alpha->image_l);
+ canvas->DrawBitmapInt(theme_l,
+ 0, 0, theme_l.width(), theme_l.height() - kToolbarOverlap,
+ 0, 0, theme_l.width(), theme_l.height() - kToolbarOverlap,
+ false);
+
+ // Draw right edge. Again, don't draw over the toolbar.
+ SkBitmap tab_r = SkBitmapOperations::CreateTiledBitmap(*tab_bg,
+ offset + width() - tab_image->r_width, bg_offset_y,
+ tab_image->r_width, height());
+ SkBitmap theme_r =
+ SkBitmapOperations::CreateMaskedBitmap(tab_r, *alpha->image_r);
+ canvas->DrawBitmapInt(theme_r,
+ 0, 0, theme_r.width(), theme_r.height() - kToolbarOverlap,
+ width() - theme_r.width(), 0, theme_r.width(),
+ theme_r.height() - kToolbarOverlap, false);
+
+ // Draw center. Instead of masking out the top portion we simply skip over
+ // it by incrementing by kDropShadowHeight, since it's a simple rectangle.
+ // And again, don't draw over the toolbar.
+ canvas->TileImageInt(*tab_bg,
+ offset + tab_image->l_width,
+ bg_offset_y + kDropShadowHeight + tab_image->y_offset,
+ tab_image->l_width,
+ kDropShadowHeight + tab_image->y_offset,
+ width() - tab_image->l_width - tab_image->r_width,
+ height() - kDropShadowHeight - kToolbarOverlap - tab_image->y_offset);
+
+ // Now draw the highlights/shadows around the tab edge.
+ canvas->DrawBitmapInt(*tab_inactive_image->image_l, 0, 0);
+ canvas->TileImageInt(*tab_inactive_image->image_c,
+ tab_inactive_image->l_width, 0,
+ width() - tab_inactive_image->l_width -
+ tab_inactive_image->r_width,
+ height());
+ canvas->DrawBitmapInt(*tab_inactive_image->image_r,
+ width() - tab_inactive_image->r_width, 0);
+}
+
+void Tab::PaintActiveTabBackground(gfx::Canvas* canvas) {
+ int offset = GetX(views::View::APPLY_MIRRORING_TRANSFORMATION) +
+ background_offset_.x();
+ ThemeProvider* tp = GetThemeProvider();
+ if (!tp)
+ NOTREACHED() << "Unable to get theme provider";
+
+ SkBitmap* tab_bg = GetThemeProvider()->GetBitmapNamed(IDR_THEME_TOOLBAR);
+
+ // App tabs are drawn slightly differently (as nano tabs).
+ TabImage* tab_image = data().app ? &tab_active_nano : &tab_active;
+ TabImage* alpha = data().app ? &tab_alpha_nano : &tab_alpha;
+
+ // Draw left edge.
+ SkBitmap tab_l = SkBitmapOperations::CreateTiledBitmap(
+ *tab_bg, offset, 0, tab_image->l_width, height());
+ SkBitmap theme_l =
+ SkBitmapOperations::CreateMaskedBitmap(tab_l, *alpha->image_l);
+ canvas->DrawBitmapInt(theme_l, 0, 0);
+
+ // Draw right edge.
+ SkBitmap tab_r = SkBitmapOperations::CreateTiledBitmap(*tab_bg,
+ offset + width() - tab_image->r_width, 0, tab_image->r_width, height());
+ SkBitmap theme_r =
+ SkBitmapOperations::CreateMaskedBitmap(tab_r, *alpha->image_r);
+ canvas->DrawBitmapInt(theme_r, width() - tab_image->r_width, 0);
+
+ // Draw center. Instead of masking out the top portion we simply skip over it
+ // by incrementing by kDropShadowHeight, since it's a simple rectangle.
+ canvas->TileImageInt(*tab_bg,
+ offset + tab_image->l_width,
+ kDropShadowHeight + tab_image->y_offset,
+ tab_image->l_width,
+ kDropShadowHeight + tab_image->y_offset,
+ width() - tab_image->l_width - tab_image->r_width,
+ height() - kDropShadowHeight - tab_image->y_offset);
+
+ // Now draw the highlights/shadows around the tab edge.
+ canvas->DrawBitmapInt(*tab_image->image_l, 0, 0);
+ canvas->TileImageInt(*tab_image->image_c, tab_image->l_width, 0,
+ width() - tab_image->l_width - tab_image->r_width, height());
+ canvas->DrawBitmapInt(*tab_image->image_r, width() - tab_image->r_width, 0);
+}
+
+void Tab::PaintAsNewTab(gfx::Canvas* canvas) {
+ bool is_otr = data().off_the_record;
+
+ // The tab image needs to be lined up with the background image
+ // so that it feels partially transparent. These offsets represent the tab
+ // position within the frame background image.
+ int offset = GetX(views::View::APPLY_MIRRORING_TRANSFORMATION) +
+ background_offset_.x();
+
+ int tab_id;
+ if (GetWidget() &&
+ GetWidget()->GetWindow()->GetNonClientView()->UseNativeFrame()) {
+ tab_id = IDR_THEME_TAB_BACKGROUND_V;
+ } else {
+ tab_id = is_otr ? IDR_THEME_TAB_BACKGROUND_INCOGNITO :
+ IDR_THEME_TAB_BACKGROUND;
+ }
+
+ SkBitmap* tab_bg = GetThemeProvider()->GetBitmapNamed(tab_id);
+
+ // If the theme is providing a custom background image, then its top edge
+ // should be at the top of the tab. Otherwise, we assume that the background
+ // image is a composited foreground + frame image.
+ int bg_offset_y = GetThemeProvider()->HasCustomImage(tab_id) ?
+ 0 : background_offset_.y();
+
+ SkBitmap image = SkBitmapOperations::CreateTiledBitmap(
+ *tab_bg, offset, bg_offset_y, new_tab_mask->width(),
+ new_tab_mask->height());
+ image = SkBitmapOperations::CreateMaskedBitmap(image, *new_tab_mask);
+ canvas->DrawBitmapInt(image,
+ 0, 0, image.width(), image.height(),
+ 0, 0, image.width(), image.height(),
+ false);
+
+ canvas->DrawBitmapInt(*new_tab_shadow,
+ 0, 0, new_tab_shadow->width(), new_tab_shadow->height(),
+ 0, 0, new_tab_shadow->width(), new_tab_shadow->height(),
+ false);
+}
+
+int Tab::IconCapacity() const {
+ if (height() < GetMinimumUnselectedSize().height())
+ return 0;
+ return (width() - kLeftPadding - kRightPadding) / kFavIconSize;
+}
+
+bool Tab::ShouldShowIcon() const {
+ if (data().mini && height() >= GetMinimumUnselectedSize().height())
+ return true;
+ if (!data().show_icon) {
+ return false;
+ } else if (IsSelected()) {
+ // The selected tab clips favicon before close button.
+ return IconCapacity() >= 2;
+ }
+ // Non-selected tabs clip close button before favicon.
+ return IconCapacity() >= 1;
+}
+
+bool Tab::ShouldShowCloseBox() const {
+ // The selected tab never clips close button.
+ return !data().mini && (IsSelected() || IconCapacity() >= 3);
+}
+
+double Tab::GetThrobValue() {
+ if (alpha_ != 1)
+ return alpha_;
+
+ if (pulse_animation() && pulse_animation()->is_animating())
+ return pulse_animation()->GetCurrentValue() * kHoverOpacity;
+
+ return hover_animation() ?
+ kHoverOpacity * hover_animation()->GetCurrentValue() : 0;
+}
+
+////////////////////////////////////////////////////////////////////////////////
+// Tab, private:
+
+// static
+void Tab::LoadTabImages() {
+ // We're not letting people override tab images just yet.
+ ResourceBundle& rb = ResourceBundle::GetSharedInstance();
+
+ tab_alpha.image_l = rb.GetBitmapNamed(IDR_TAB_ALPHA_LEFT);
+ tab_alpha.image_r = rb.GetBitmapNamed(IDR_TAB_ALPHA_RIGHT);
+
+ tab_alpha_nano.image_l = rb.GetBitmapNamed(IDR_TAB_ALPHA_NANO_LEFT);
+ tab_alpha_nano.image_r = rb.GetBitmapNamed(IDR_TAB_ALPHA_NANO_RIGHT);
+
+ tab_active.image_l = rb.GetBitmapNamed(IDR_TAB_ACTIVE_LEFT);
+ tab_active.image_c = rb.GetBitmapNamed(IDR_TAB_ACTIVE_CENTER);
+ tab_active.image_r = rb.GetBitmapNamed(IDR_TAB_ACTIVE_RIGHT);
+ tab_active.l_width = tab_active.image_l->width();
+ tab_active.r_width = tab_active.image_r->width();
+
+ // The regular tab is much taller *visually* than the nano tabs.
+ // The images are the same height, this is really just the difference
+ // in whitespace above the tab image (regular vs nano).
+ const int kNanoTabDiffHeight = 13;
+
+ tab_active_nano.image_l = rb.GetBitmapNamed(IDR_TAB_ACTIVE_NANO_LEFT);
+ tab_active_nano.image_c = rb.GetBitmapNamed(IDR_TAB_ACTIVE_NANO_CENTER);
+ tab_active_nano.image_r = rb.GetBitmapNamed(IDR_TAB_ACTIVE_NANO_RIGHT);
+ tab_active_nano.l_width = tab_active_nano.image_l->width();
+ tab_active_nano.r_width = tab_active_nano.image_r->width();
+ tab_active_nano.y_offset = kNanoTabDiffHeight;
+
+ tab_inactive.image_l = rb.GetBitmapNamed(IDR_TAB_INACTIVE_LEFT);
+ tab_inactive.image_c = rb.GetBitmapNamed(IDR_TAB_INACTIVE_CENTER);
+ tab_inactive.image_r = rb.GetBitmapNamed(IDR_TAB_INACTIVE_RIGHT);
+ tab_inactive.l_width = tab_inactive.image_l->width();
+ tab_inactive.r_width = tab_inactive.image_r->width();
+
+ tab_inactive_nano.image_l = rb.GetBitmapNamed(IDR_TAB_INACTIVE_NANO_LEFT);
+ tab_inactive_nano.image_c = rb.GetBitmapNamed(IDR_TAB_INACTIVE_NANO_CENTER);
+ tab_inactive_nano.image_r = rb.GetBitmapNamed(IDR_TAB_INACTIVE_NANO_RIGHT);
+ tab_inactive_nano.l_width = tab_inactive_nano.image_l->width();
+ tab_inactive_nano.r_width = tab_inactive_nano.image_r->width();
+ tab_inactive_nano.y_offset = kNanoTabDiffHeight;
+
+ new_tab_mask = rb.GetBitmapNamed(IDR_TAB_ALPHA_NEW_TAB);
+ new_tab_shadow = rb.GetBitmapNamed(IDR_TAB_NEW_TAB_SHADOW);
+}
diff --git a/chrome/browser/views/tabs/tab.h b/chrome/browser/views/tabs/tab.h
index f798618..fdd550c 100644
--- a/chrome/browser/views/tabs/tab.h
+++ b/chrome/browser/views/tabs/tab.h
@@ -5,56 +5,164 @@
#ifndef CHROME_BROWSER_VIEWS_TABS_TAB_H_
#define CHROME_BROWSER_VIEWS_TABS_TAB_H_
-#include "chrome/browser/tabs/tab_strip_model.h"
-#include "chrome/browser/views/tabs/tab_renderer.h"
+#include <string>
-namespace gfx {
-class Path;
-class Point;
-}
+#include "base/scoped_ptr.h"
+#include "chrome/browser/views/tabs/base_tab.h"
+#include "gfx/point.h"
+
+class MultiAnimation;
+class SlideAnimation;
///////////////////////////////////////////////////////////////////////////////
//
-// Tab
+// TabRenderer
//
-// A subclass of TabRenderer that represents an individual Tab in a TabStrip.
+// A View that renders a Tab, either in a TabStrip or in a DraggedTabView.
//
///////////////////////////////////////////////////////////////////////////////
-class Tab : public TabRenderer,
- public views::ContextMenuController {
+class Tab : public BaseTab {
public:
- static const std::string kTabClassName;
+ // The menu button's class name.
+ static const char kViewClassName[];
explicit Tab(TabController* controller);
virtual ~Tab();
- // TabRenderer overrides:
- virtual bool IsSelected() const;
+ // Sizes the renderer to the size of the new tab images. This is used
+ // during the new tab animation. See TabStrip's description of AnimationType
+ // for details.
+ void SizeToNewTabButtonImages();
+
+ // Used during new tab animation to force the tab to render a new tab like
+ // animation.
+ void set_render_as_new_tab(bool value) { render_as_new_tab_ = value; }
+
+ // Sets the alpha value to render the tab at. This is used during the new
+ // tab animation.
+ void set_alpha(double value) { alpha_ = value; }
+
+ // Forces the tab to render unselected even though it is selected.
+ void set_render_unselected(bool value) { render_unselected_ = value; }
+ bool render_unselected() const { return render_unselected_; }
+
+ // Start/stop the mini-tab title animation.
+ void StartMiniTabTitleAnimation();
+ void StopMiniTabTitleAnimation();
+
+ // Set the background offset used to match the image in the inactive tab
+ // to the frame image.
+ void SetBackgroundOffset(const gfx::Point& offset) {
+ background_offset_ = offset;
+ }
+
+ // Paints the icon. Most of the time you'll want to invoke Paint directly, but
+ // in certain situations this invoked outside of Paint.
+ void PaintIcon(gfx::Canvas* canvas);
+
+ // Returns the minimum possible size of a single unselected Tab.
+ static gfx::Size GetMinimumUnselectedSize();
+ // Returns the minimum possible size of a selected Tab. Selected tabs must
+ // always show a close button and have a larger minimum size than unselected
+ // tabs.
+ static gfx::Size GetMinimumSelectedSize();
+ // Returns the preferred size of a single Tab, assuming space is
+ // available.
+ static gfx::Size GetStandardSize();
+
+ // Returns the width for mini-tabs. Mini-tabs always have this width.
+ static int GetMiniWidth();
+
+ // Loads the images to be used for the tab background.
+ static void LoadTabImages();
+
+ protected:
+ virtual const gfx::Rect& title_bounds() const { return title_bounds_; }
+
+ // BaseTab overrides:
+ virtual void DataChanged(const TabRendererData& old);
private:
- // views::View overrides:
+ // Overridden from views::View:
+ virtual void Paint(gfx::Canvas* canvas);
+ virtual void Layout();
+ virtual void ThemeChanged();
+ virtual std::string GetClassName() const { return kViewClassName; }
virtual bool HasHitTestMask() const;
- virtual void GetHitTestMask(gfx::Path* mask) const;
- virtual bool OnMousePressed(const views::MouseEvent& event);
- virtual bool OnMouseDragged(const views::MouseEvent& event);
- virtual void OnMouseReleased(const views::MouseEvent& event,
- bool canceled);
- virtual bool GetTooltipText(const gfx::Point& p, std::wstring* tooltip);
+ virtual void GetHitTestMask(gfx::Path* path) const;
virtual bool GetTooltipTextOrigin(const gfx::Point& p, gfx::Point* origin);
- virtual std::string GetClassName() const { return kTabClassName; }
- virtual bool GetAccessibleRole(AccessibilityTypes::Role* role);
- // views::ContextMenuController overrides:
- virtual void ShowContextMenu(views::View* source,
- const gfx::Point& p,
- bool is_mouse_gesture);
+ // Paint various portions of the Tab
+ void PaintTabBackground(gfx::Canvas* canvas);
+ void PaintInactiveTabBackgroundWithTitleChange(gfx::Canvas* canvas);
+ void PaintInactiveTabBackground(gfx::Canvas* canvas);
+ void PaintActiveTabBackground(gfx::Canvas* canvas);
+ void PaintAsNewTab(gfx::Canvas* canvas);
+
+ // Returns the number of favicon-size elements that can fit in the tab's
+ // current size.
+ int IconCapacity() const;
+
+ // Returns whether the Tab should display a favicon.
+ bool ShouldShowIcon() const;
+
+ // Returns whether the Tab should display a close button.
+ bool ShouldShowCloseBox() const;
+
+ // Gets the throb value for the tab. When a tab is not selected the
+ // active background is drawn at |GetThrobValue()|%. This is used for hover,
+ // mini tab title change and pulsing.
+ double GetThrobValue();
+
+ // The bounds of various sections of the display.
+ gfx::Rect favicon_bounds_;
+ gfx::Rect title_bounds_;
+
+ // The offset used to paint the inactive background image.
+ gfx::Point background_offset_;
+
+ // Hover animation.
+ scoped_ptr<SlideAnimation> hover_animation_;
+
+ // Animation used when the title of an inactive mini tab changes.
+ scoped_ptr<MultiAnimation> mini_title_animation_;
+
+ struct TabImage {
+ SkBitmap* image_l;
+ SkBitmap* image_c;
+ SkBitmap* image_r;
+ int l_width;
+ int r_width;
+ int y_offset;
+ };
+ static TabImage tab_active;
+ static TabImage tab_active_nano;
+ static TabImage tab_inactive;
+ static TabImage tab_inactive_nano;
+ static TabImage tab_alpha;
+ static TabImage tab_alpha_nano;
+
+ // Whether we're showing the icon. It is cached so that we can detect when it
+ // changes and layout appropriately.
+ bool showing_icon_;
+
+ // Whether we are showing the close button. It is cached so that we can
+ // detect when it changes and layout appropriately.
+ bool showing_close_button_;
+
+ // The current color of the close button.
+ SkColor close_button_color_;
+
+ // See description above setter.
+ bool render_as_new_tab_;
+
+ // See description above setter.
+ bool render_unselected_;
- // views::ButtonListener overrides:
- virtual void ButtonPressed(views::Button* sender, const views::Event& event);
+ // See description above setter.
+ double alpha_;
- // Creates a path that contains the clickable region of the tab's visual
- // representation. Used by GetViewForPoint for hit-testing.
- void MakePathForTab(gfx::Path* path) const;
+ static bool initialized_;
DISALLOW_COPY_AND_ASSIGN(Tab);
};
diff --git a/chrome/browser/views/tabs/tab_controller.h b/chrome/browser/views/tabs/tab_controller.h
new file mode 100755
index 0000000..937d3be
--- /dev/null
+++ b/chrome/browser/views/tabs/tab_controller.h
@@ -0,0 +1,50 @@
+// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CHROME_BROWSER_VIEWS_TABS_TAB_CONTROLLER_H_
+#define CHROME_BROWSER_VIEWS_TABS_TAB_CONTROLLER_H_
+
+class BaseTab;
+
+namespace gfx {
+class Point;
+}
+namespace views {
+class MouseEvent;
+}
+
+// Controller for tabs.
+class TabController {
+ public:
+ // Selects the tab.
+ virtual void SelectTab(BaseTab* tab) = 0;
+
+ // Closes the tab.
+ virtual void CloseTab(BaseTab* tab) = 0;
+
+ // Shows a context menu for the tab at the specified point in screen coords.
+ virtual void ShowContextMenu(BaseTab* tab, const gfx::Point& p) = 0;
+
+ // Returns true if the specified Tab is selected.
+ virtual bool IsTabSelected(const BaseTab* tab) const = 0;
+
+ // Returns true if the specified Tab is pinned.
+ virtual bool IsTabPinned(const BaseTab* tab) const = 0;
+
+ // Potentially starts a drag for the specified Tab.
+ virtual void MaybeStartDrag(BaseTab* tab, const views::MouseEvent& event) = 0;
+
+ // Continues dragging a Tab.
+ virtual void ContinueDrag(const views::MouseEvent& event) = 0;
+
+ // Ends dragging a Tab. |canceled| is true if the drag was aborted in a way
+ // other than the user releasing the mouse. Returns whether the tab has been
+ // destroyed.
+ virtual bool EndDrag(bool canceled) = 0;
+
+ protected:
+ virtual ~TabController() {}
+};
+
+#endif // CHROME_BROWSER_VIEWS_TABS_TAB_CONTROLLER_H_
diff --git a/chrome/browser/views/tabs/tab_renderer.cc b/chrome/browser/views/tabs/tab_renderer.cc
deleted file mode 100644
index f32d718..0000000
--- a/chrome/browser/views/tabs/tab_renderer.cc
+++ /dev/null
@@ -1,1062 +0,0 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "chrome/browser/views/tabs/tab_renderer.h"
-
-#include <limits>
-
-#include "app/animation_container.h"
-#include "app/l10n_util.h"
-#include "app/multi_animation.h"
-#include "app/resource_bundle.h"
-#include "app/slide_animation.h"
-#include "app/throb_animation.h"
-#include "base/command_line.h"
-#include "base/utf_string_conversions.h"
-#include "chrome/browser/browser.h"
-#include "chrome/browser/browser_theme_provider.h"
-#include "chrome/browser/defaults.h"
-#include "chrome/browser/tab_contents/tab_contents.h"
-#include "chrome/common/chrome_switches.h"
-#include "gfx/canvas.h"
-#include "gfx/favicon_size.h"
-#include "gfx/font.h"
-#include "gfx/skbitmap_operations.h"
-#include "grit/app_resources.h"
-#include "grit/generated_resources.h"
-#include "grit/theme_resources.h"
-#include "third_party/skia/include/effects/SkGradientShader.h"
-#include "views/widget/widget.h"
-#include "views/window/non_client_view.h"
-#include "views/window/window.h"
-
-#ifdef WIN32
-#include "app/win_util.h"
-#endif
-
-static const int kLeftPadding = 16;
-static const int kTopPadding = 6;
-static const int kRightPadding = 15;
-static const int kBottomPadding = 5;
-static const int kDropShadowHeight = 2;
-static const int kToolbarOverlap = 1;
-static const int kFavIconTitleSpacing = 4;
-static const int kTitleCloseButtonSpacing = 5;
-static const int kStandardTitleWidth = 175;
-static const int kCloseButtonVertFuzz = 0;
-static const int kCloseButtonHorzFuzz = 5;
-static const int kSelectedTitleColor = SK_ColorBLACK;
-
-// Vertical adjustment to the favicon when the tab has a large icon.
-static const int kAppTapFaviconVerticalAdjustment = 2;
-
-// When a non-mini-tab becomes a mini-tab the width of the tab animates. If
-// the width of a mini-tab is >= kMiniTabRendererAsNormalTabWidth then the tab
-// is rendered as a normal tab. This is done to avoid having the title
-// immediately disappear when transitioning a tab from normal to mini-tab.
-static const int kMiniTabRendererAsNormalTabWidth =
- browser_defaults::kMiniTabWidth + 30;
-
-// How long the hover state takes.
-static const int kHoverDurationMs = 90;
-
-// How long the pulse throb takes.
-static const int kPulseDurationMs = 200;
-
-// How opaque to make the hover state (out of 1).
-static const double kHoverOpacity = 0.33;
-
-// TODO(beng): (Cleanup) This stuff should move onto the class.
-static gfx::Font* title_font = NULL;
-static int title_font_height = 0;
-static SkBitmap* close_button_n = NULL;
-static SkBitmap* close_button_m = NULL;
-static SkBitmap* close_button_h = NULL;
-static SkBitmap* close_button_p = NULL;
-static int close_button_height = 0;
-static int close_button_width = 0;
-
-static SkBitmap* waiting_animation_frames = NULL;
-static SkBitmap* loading_animation_frames = NULL;
-static SkBitmap* crashed_fav_icon = NULL;
-static int loading_animation_frame_count = 0;
-static int waiting_animation_frame_count = 0;
-static int waiting_to_loading_frame_count_ratio = 0;
-
-// Used when |render_as_new_tab| is true.
-static SkBitmap* new_tab_mask = NULL;
-static SkBitmap* new_tab_shadow = NULL;
-
-TabRenderer::TabImage TabRenderer::tab_alpha = {0};
-TabRenderer::TabImage TabRenderer::tab_active = {0};
-TabRenderer::TabImage TabRenderer::tab_active_nano = {0};
-TabRenderer::TabImage TabRenderer::tab_inactive = {0};
-TabRenderer::TabImage TabRenderer::tab_inactive_nano = {0};
-TabRenderer::TabImage TabRenderer::tab_alpha_nano = {0};
-
-// Durations for the various parts of the mini tab title animation.
-static const int kMiniTitleChangeAnimationDuration1MS = 1000;
-static const int kMiniTitleChangeAnimationDuration2MS = 500;
-static const int kMiniTitleChangeAnimationDuration3MS = 800;
-
-// Offset from the right edge for the start of the mini title change animation.
-static const int kMiniTitleChangeInitialXOffset = 6;
-
-// Radius of the radial gradient used for mini title change animation.
-static const int kMiniTitleChangeGradientRadius = 20;
-
-// Colors of the gradient used during the mini title change animation.
-static const SkColor kMiniTitleChangeGradientColor1 = SK_ColorWHITE;
-static const SkColor kMiniTitleChangeGradientColor2 =
- SkColorSetARGB(0, 255, 255, 255);
-
-namespace {
-
-void InitResources() {
- static bool initialized = false;
- if (!initialized) {
- // TODO(glen): Allow theming of these.
- ResourceBundle& rb = ResourceBundle::GetSharedInstance();
- title_font = new gfx::Font(rb.GetFont(ResourceBundle::BaseFont));
- title_font_height = title_font->height();
-
- close_button_n = rb.GetBitmapNamed(IDR_TAB_CLOSE);
- close_button_m = rb.GetBitmapNamed(IDR_TAB_CLOSE_MASK);
- close_button_h = rb.GetBitmapNamed(IDR_TAB_CLOSE_H);
- close_button_p = rb.GetBitmapNamed(IDR_TAB_CLOSE_P);
- close_button_width = close_button_n->width();
- close_button_height = close_button_n->height();
-
- TabRenderer::LoadTabImages();
-
- // The loading animation image is a strip of states. Each state must be
- // square, so the height must divide the width evenly.
- loading_animation_frames = rb.GetBitmapNamed(IDR_THROBBER);
- DCHECK(loading_animation_frames);
- DCHECK(loading_animation_frames->width() %
- loading_animation_frames->height() == 0);
- loading_animation_frame_count =
- loading_animation_frames->width() / loading_animation_frames->height();
-
- // We get a DIV0 further down when the throbber is replaced by an image
- // which is taller than wide. In this case we cannot deduce an animation
- // sequence from it since we assume that each animation frame has the width
- // of the image's height.
- if (loading_animation_frame_count == 0) {
-#ifdef WIN32
- // TODO(idanan): Remove this when we have a way to handle theme errors.
- // See: http://code.google.com/p/chromium/issues/detail?id=12531
- // For now, this is Windows-specific because some users have downloaded
- // a DLL from outside of Google to override the theme.
- std::wstring text = l10n_util::GetString(IDS_RESOURCE_ERROR);
- std::wstring caption = l10n_util::GetString(IDS_RESOURCE_ERROR_CAPTION);
- UINT flags = MB_OK | MB_ICONWARNING | MB_TOPMOST;
- win_util::MessageBox(NULL, text, caption, flags);
-#endif
- CHECK(loading_animation_frame_count) << "Invalid throbber size. Width = "
- << loading_animation_frames->width() << ", height = "
- << loading_animation_frames->height();
- }
-
- waiting_animation_frames = rb.GetBitmapNamed(IDR_THROBBER_WAITING);
- DCHECK(waiting_animation_frames);
- DCHECK(waiting_animation_frames->width() %
- waiting_animation_frames->height() == 0);
- waiting_animation_frame_count =
- waiting_animation_frames->width() / waiting_animation_frames->height();
-
- waiting_to_loading_frame_count_ratio =
- waiting_animation_frame_count / loading_animation_frame_count;
- // TODO(beng): eventually remove this when we have a proper themeing system.
- // themes not supporting IDR_THROBBER_WAITING are causing this
- // value to be 0 which causes DIV0 crashes. The value of 5
- // matches the current bitmaps in our source.
- if (waiting_to_loading_frame_count_ratio == 0)
- waiting_to_loading_frame_count_ratio = 5;
-
- crashed_fav_icon = rb.GetBitmapNamed(IDR_SAD_FAVICON);
-
- initialized = true;
- }
-}
-
-int GetContentHeight() {
- // The height of the content of the Tab is the largest of the favicon,
- // the title text and the close button graphic.
- int content_height = std::max(kFavIconSize, title_font_height);
- return std::max(content_height, close_button_height);
-}
-
-////////////////////////////////////////////////////////////////////////////////
-// TabCloseButton
-//
-// This is a Button subclass that causes middle clicks to be forwarded to the
-// parent View by explicitly not handling them in OnMousePressed.
-class TabCloseButton : public views::ImageButton {
- public:
- explicit TabCloseButton(views::ButtonListener* listener)
- : views::ImageButton(listener) {
- }
- virtual ~TabCloseButton() {}
-
- virtual bool OnMousePressed(const views::MouseEvent& event) {
- bool handled = ImageButton::OnMousePressed(event);
- // Explicitly mark midle-mouse clicks as non-handled to ensure the tab
- // sees them.
- return event.IsOnlyMiddleMouseButton() ? false : handled;
- }
-
- // We need to let the parent know about mouse state so that it
- // can highlight itself appropriately. Note that Exit events
- // fire before Enter events, so this works.
- virtual void OnMouseEntered(const views::MouseEvent& event) {
- CustomButton::OnMouseEntered(event);
- GetParent()->OnMouseEntered(event);
- }
-
- virtual void OnMouseExited(const views::MouseEvent& event) {
- CustomButton::OnMouseExited(event);
- GetParent()->OnMouseExited(event);
- }
-
- private:
- DISALLOW_COPY_AND_ASSIGN(TabCloseButton);
-};
-
-} // namespace
-
-////////////////////////////////////////////////////////////////////////////////
-// FaviconCrashAnimation
-//
-// A custom animation subclass to manage the favicon crash animation.
-class TabRenderer::FavIconCrashAnimation : public LinearAnimation,
- public AnimationDelegate {
- public:
- explicit FavIconCrashAnimation(TabRenderer* target)
- : ALLOW_THIS_IN_INITIALIZER_LIST(LinearAnimation(1000, 25, this)),
- target_(target) {
- }
- virtual ~FavIconCrashAnimation() {}
-
- // Animation overrides:
- virtual void AnimateToState(double state) {
- const double kHidingOffset = 27;
-
- if (state < .5) {
- target_->SetFavIconHidingOffset(
- static_cast<int>(floor(kHidingOffset * 2.0 * state)));
- } else {
- target_->DisplayCrashedFavIcon();
- target_->SetFavIconHidingOffset(
- static_cast<int>(
- floor(kHidingOffset - ((state - .5) * 2.0 * kHidingOffset))));
- }
- }
-
- // AnimationDelegate overrides:
- virtual void AnimationCanceled(const Animation* animation) {
- target_->SetFavIconHidingOffset(0);
- }
-
- private:
- TabRenderer* target_;
-
- DISALLOW_COPY_AND_ASSIGN(FavIconCrashAnimation);
-};
-
-////////////////////////////////////////////////////////////////////////////////
-// TabRenderer, public:
-
-TabRenderer::TabRenderer(TabController* controller)
- : BaseTabRenderer(controller),
- animation_frame_(0),
- throbber_disabled_(false),
- showing_icon_(false),
- showing_close_button_(false),
- fav_icon_hiding_offset_(0),
- close_button_color_(NULL),
- render_as_new_tab_(false),
- render_unselected_(false),
- alpha_(1),
- crash_animation_(NULL),
- should_display_crashed_favicon_(false),
- theme_provider_(NULL) {
- InitResources();
-
- // Add the Close Button.
- close_button_ = new TabCloseButton(this);
- close_button_->SetImage(views::CustomButton::BS_NORMAL, close_button_n);
- close_button_->SetImage(views::CustomButton::BS_HOT, close_button_h);
- close_button_->SetImage(views::CustomButton::BS_PUSHED, close_button_p);
- AddChildView(close_button_);
-
- hover_animation_.reset(new SlideAnimation(this));
- hover_animation_->SetSlideDuration(kHoverDurationMs);
-
- pulse_animation_.reset(new ThrobAnimation(this));
- pulse_animation_->SetSlideDuration(kPulseDurationMs);
-}
-
-TabRenderer::~TabRenderer() {
- delete crash_animation_;
-}
-
-void TabRenderer::SizeToNewTabButtonImages() {
- SetBounds(x(), y(), new_tab_shadow->width(), new_tab_shadow->height());
-}
-
-void TabRenderer::ViewHierarchyChanged(bool is_add, View* parent, View* child) {
- if (parent->GetThemeProvider())
- SetThemeProvider(parent->GetThemeProvider());
-}
-
-ThemeProvider* TabRenderer::GetThemeProvider() {
- ThemeProvider* tp = View::GetThemeProvider();
- if (tp)
- return tp;
-
- if (theme_provider_)
- return theme_provider_;
-
- return NULL;
-}
-
-bool TabRenderer::IsSelected() const {
- return true;
-}
-
-void TabRenderer::StartPulse() {
- pulse_animation_->Reset();
- pulse_animation_->StartThrobbing(std::numeric_limits<int>::max());
-}
-
-void TabRenderer::StopPulse() {
- pulse_animation_->Stop();
-}
-
-void TabRenderer::StartMiniTabTitleAnimation() {
- if (!mini_title_animation_.get()) {
- MultiAnimation::Parts parts;
- parts.push_back(MultiAnimation::Part(kMiniTitleChangeAnimationDuration1MS,
- Tween::EASE_OUT));
- parts.push_back(MultiAnimation::Part(kMiniTitleChangeAnimationDuration2MS,
- Tween::ZERO));
- parts.push_back(MultiAnimation::Part(kMiniTitleChangeAnimationDuration3MS,
- Tween::EASE_IN));
- mini_title_animation_.reset(new MultiAnimation(parts));
- mini_title_animation_->SetContainer(container_.get());
- mini_title_animation_->set_delegate(this);
- }
- mini_title_animation_->Start();
-}
-
-void TabRenderer::StopMiniTabTitleAnimation() {
- if (mini_title_animation_.get())
- mini_title_animation_->Stop();
-}
-
-void TabRenderer::SetAnimationContainer(AnimationContainer* container) {
- container_ = container;
- pulse_animation_->SetContainer(container);
-}
-
-void TabRenderer::PaintIcon(gfx::Canvas* canvas) {
- if (data().network_state != TabRendererData::NETWORK_STATE_NONE) {
- PaintLoadingAnimation(canvas);
- } else {
- canvas->save();
- canvas->ClipRectInt(0, 0, width(), height());
- if (should_display_crashed_favicon_) {
- canvas->DrawBitmapInt(*crashed_fav_icon, 0, 0,
- crashed_fav_icon->width(),
- crashed_fav_icon->height(),
- favicon_bounds_.x(),
- favicon_bounds_.y() + fav_icon_hiding_offset_,
- kFavIconSize, kFavIconSize,
- true);
- } else {
- if (!data().favicon.isNull()) {
- // TODO(pkasting): Use code in tab_icon_view.cc:PaintIcon() (or switch
- // to using that class to render the favicon).
- int x = favicon_bounds_.x();
- int y = favicon_bounds_.y() + fav_icon_hiding_offset_;
- int size = data().favicon.width();
- canvas->DrawBitmapInt(data().favicon, 0, 0,
- data().favicon.width(),
- data().favicon.height(),
- x, y, size, size,
- true);
- }
- }
- canvas->restore();
- }
-}
-
-// static
-gfx::Size TabRenderer::GetMinimumUnselectedSize() {
- InitResources();
-
- gfx::Size minimum_size;
- minimum_size.set_width(kLeftPadding + kRightPadding);
- // Since we use bitmap images, the real minimum height of the image is
- // defined most accurately by the height of the end cap images.
- minimum_size.set_height(tab_active.image_l->height());
- return minimum_size;
-}
-
-// static
-gfx::Size TabRenderer::GetMinimumSelectedSize() {
- gfx::Size minimum_size = GetMinimumUnselectedSize();
- minimum_size.set_width(kLeftPadding + kFavIconSize + kRightPadding);
- return minimum_size;
-}
-
-// static
-gfx::Size TabRenderer::GetStandardSize() {
- gfx::Size standard_size = GetMinimumUnselectedSize();
- standard_size.set_width(
- standard_size.width() + kFavIconTitleSpacing + kStandardTitleWidth);
- return standard_size;
-}
-
-// static
-int TabRenderer::GetMiniWidth() {
- return browser_defaults::kMiniTabWidth;
-}
-
-////////////////////////////////////////////////////////////////////////////////
-// TabRenderer, protected:
-
-std::wstring TabRenderer::GetTitle() const {
- return UTF16ToWideHack(data().title);
-}
-
-void TabRenderer::OnMouseEntered(const views::MouseEvent& e) {
- hover_animation_->SetTweenType(Tween::EASE_OUT);
- hover_animation_->Show();
-}
-
-void TabRenderer::OnMouseExited(const views::MouseEvent& e) {
- hover_animation_->SetTweenType(Tween::EASE_IN);
- hover_animation_->Hide();
-}
-
-void TabRenderer::DataChanged(const TabRendererData& old) {
- if (data().phantom)
- StopMiniTabTitleAnimation();
-
- // Sets the accessible name for the tab.
- SetAccessibleName(UTF16ToWide(data().title));
-
- if (data().blocked != old.blocked) {
- if (data().blocked)
- StartPulse();
- else
- StopPulse();
- }
-
- // If this is an extension app and a command line flag is set,
- // then disable the throbber.
- throbber_disabled_ = data().app &&
- CommandLine::ForCurrentProcess()->HasSwitch(switches::kAppsNoThrob);
-
- if (data().crashed) {
- if (!should_display_crashed_favicon_ && !IsPerformingCrashAnimation())
- StartCrashAnimation();
- } else {
- if (IsPerformingCrashAnimation())
- StopCrashAnimation();
- ResetCrashedFavIcon();
- }
-}
-
-void TabRenderer::AdvanceLoadingAnimation(TabRendererData::NetworkState state) {
- if (throbber_disabled_)
- return;
-
- // The waiting animation is the reverse of the loading animation, but at a
- // different rate - the following reverses and scales the animation_frame_ so
- // that the frame is at an equivalent position when going from one animation
- // to the other.
- if (state == TabRendererData::NETWORK_STATE_WAITING &&
- state == TabRendererData::NETWORK_STATE_LOADING) {
- animation_frame_ = loading_animation_frame_count -
- (animation_frame_ / waiting_to_loading_frame_count_ratio);
- }
-
- if (state != TabRendererData::NETWORK_STATE_NONE) {
- animation_frame_ = ++animation_frame_ %
- ((state == TabRendererData::NETWORK_STATE_WAITING) ?
- waiting_animation_frame_count :
- loading_animation_frame_count);
- } else {
- animation_frame_ = 0;
- }
-
- SchedulePaint();
-}
-
-////////////////////////////////////////////////////////////////////////////////
-// TabRenderer, views::View overrides:
-
-void TabRenderer::Paint(gfx::Canvas* canvas) {
- if (render_as_new_tab_) {
- if (base::i18n::IsRTL()) {
- canvas->TranslateInt(width(), 0);
- canvas->ScaleInt(-1, 1);
- }
- PaintAsNewTab(canvas);
- return;
- }
-
- // Don't paint if we're narrower than we can render correctly. (This should
- // only happen during animations).
- if (width() < GetMinimumUnselectedSize().width() && !data().mini)
- return;
-
- // See if the model changes whether the icons should be painted.
- const bool show_icon = ShouldShowIcon() && !data().phantom;
- const bool show_close_button = ShouldShowCloseBox();
- if (show_icon != showing_icon_ ||
- show_close_button != showing_close_button_)
- Layout();
-
- PaintTabBackground(canvas);
-
- SkColor title_color = GetThemeProvider()->
- GetColor(IsSelected() ?
- BrowserThemeProvider::COLOR_TAB_TEXT :
- BrowserThemeProvider::COLOR_BACKGROUND_TAB_TEXT);
-
- if (!data().mini || width() > kMiniTabRendererAsNormalTabWidth)
- PaintTitle(title_color, canvas);
-
- if (show_icon)
- PaintIcon(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;
- ResourceBundle& rb = ResourceBundle::GetSharedInstance();
- close_button_->SetBackground(close_button_color_,
- rb.GetBitmapNamed(IDR_TAB_CLOSE),
- rb.GetBitmapNamed(IDR_TAB_CLOSE_MASK));
- }
-}
-
-void TabRenderer::Layout() {
- gfx::Rect lb = GetLocalBounds(false);
- if (lb.IsEmpty())
- return;
- lb.Inset(kLeftPadding, kTopPadding, kRightPadding, kBottomPadding);
-
- // First of all, figure out who is tallest.
- int content_height = GetContentHeight();
-
- // Size the Favicon.
- showing_icon_ = ShouldShowIcon();
- if (showing_icon_) {
- // Use the size of the favicon as apps use a bigger favicon size.
- int favicon_size =
- !data().favicon.empty() ? data().favicon.width() : kFavIconSize;
- int favicon_top = kTopPadding + content_height / 2 - favicon_size / 2;
- int favicon_left = lb.x();
- if (favicon_size != kFavIconSize) {
- favicon_left -= (favicon_size - kFavIconSize) / 2;
- favicon_top -= kAppTapFaviconVerticalAdjustment;
- }
- favicon_bounds_.SetRect(favicon_left, favicon_top,
- favicon_size, favicon_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() - favicon_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);
- }
- }
- } else {
- favicon_bounds_.SetRect(lb.x(), lb.y(), 0, 0);
- }
-
- // Size the Close button.
- showing_close_button_ = ShouldShowCloseBox();
- if (showing_close_button_) {
- int close_button_top =
- kTopPadding + kCloseButtonVertFuzz +
- (content_height - close_button_height) / 2;
- // If the ratio of the close button size to tab width exceeds the maximum.
- close_button_->SetBounds(lb.width() + kCloseButtonHorzFuzz,
- close_button_top, close_button_width,
- close_button_height);
- close_button_->SetVisible(true);
- } else {
- close_button_->SetBounds(0, 0, 0, 0);
- close_button_->SetVisible(false);
- }
-
- int title_left = favicon_bounds_.right() + kFavIconTitleSpacing;
- int title_top = kTopPadding + (content_height - title_font_height) / 2;
- // Size the Title text to fill the remaining space.
- if (!data().mini || width() >= kMiniTabRendererAsNormalTabWidth) {
- // If the user has big fonts, the title will appear rendered too far down
- // on the y-axis if we use the regular top padding, so we need to adjust it
- // so that the text appears centered.
- gfx::Size minimum_size = GetMinimumUnselectedSize();
- int text_height = title_top + title_font_height + kBottomPadding;
- if (text_height > minimum_size.height())
- title_top -= (text_height - minimum_size.height()) / 2;
-
- int title_width;
- if (close_button_->IsVisible()) {
- title_width = std::max(close_button_->x() -
- kTitleCloseButtonSpacing - title_left, 0);
- } else {
- title_width = std::max(lb.width() - title_left, 0);
- }
- title_bounds_.SetRect(title_left, title_top, title_width,
- title_font_height);
- } else {
- title_bounds_.SetRect(title_left, title_top, 0, 0);
- }
-
- // Certain UI elements within the Tab (the favicon, etc.) are not represented
- // as child Views (which is the preferred method). Instead, these UI elements
- // are drawn directly on the canvas from within Tab::Paint(). The Tab's child
- // Views (for example, the Tab's close button which is a views::Button
- // instance) are automatically mirrored by the mirroring infrastructure in
- // views. The elements Tab draws directly on the canvas need to be manually
- // mirrored if the View's layout is right-to-left.
- favicon_bounds_.set_x(MirroredLeftPointForRect(favicon_bounds_));
- title_bounds_.set_x(MirroredLeftPointForRect(title_bounds_));
-}
-
-void TabRenderer::ThemeChanged() {
- LoadTabImages();
- View::ThemeChanged();
-}
-
-///////////////////////////////////////////////////////////////////////////////
-// TabRenderer, AnimationDelegate implementation:
-
-void TabRenderer::AnimationProgressed(const Animation* animation) {
- SchedulePaint();
-}
-
-void TabRenderer::AnimationCanceled(const Animation* animation) {
- AnimationEnded(animation);
-}
-
-void TabRenderer::AnimationEnded(const Animation* animation) {
- SchedulePaint();
-}
-
-////////////////////////////////////////////////////////////////////////////////
-// TabRenderer, private
-
-void TabRenderer::PaintTitle(SkColor title_color, gfx::Canvas* canvas) {
- // Paint the Title.
- string16 title = data().title;
- if (title.empty()) {
- title = data().loading ?
- l10n_util::GetStringUTF16(IDS_TAB_LOADING_TITLE) :
- TabContents::GetDefaultTitle();
- } else {
- Browser::FormatTitleForDisplay(&title);
- }
-
- canvas->DrawStringInt(UTF16ToWideHack(title), *title_font, title_color,
- title_bounds_.x(), title_bounds_.y(),
- title_bounds_.width(), title_bounds_.height());
-}
-
-void TabRenderer::PaintTabBackground(gfx::Canvas* canvas) {
- if (IsSelected()) {
- PaintActiveTabBackground(canvas);
- } else {
- if (mini_title_animation_.get() && mini_title_animation_->is_animating())
- PaintInactiveTabBackgroundWithTitleChange(canvas);
- else
- PaintInactiveTabBackground(canvas);
-
- double throb_value = GetThrobValue();
- if (throb_value > 0) {
- SkRect bounds;
- bounds.set(0, 0, SkIntToScalar(width()), SkIntToScalar(height()));
- canvas->saveLayerAlpha(&bounds, static_cast<int>(throb_value * 0xff),
- SkCanvas::kARGB_ClipLayer_SaveFlag);
- canvas->drawARGB(0, 255, 255, 255, SkXfermode::kClear_Mode);
- PaintActiveTabBackground(canvas);
- canvas->restore();
- }
- }
-}
-
-void TabRenderer::PaintInactiveTabBackgroundWithTitleChange(
- gfx::Canvas* canvas) {
- // Render the inactive tab background. We'll use this for clipping.
- gfx::Canvas background_canvas(width(), height(), false);
- PaintInactiveTabBackground(&background_canvas);
-
- SkBitmap background_image = background_canvas.ExtractBitmap();
-
- // Draw a radial gradient to hover_canvas.
- gfx::Canvas hover_canvas(width(), height(), false);
- int radius = kMiniTitleChangeGradientRadius;
- int x0 = width() + radius - kMiniTitleChangeInitialXOffset;
- int x1 = radius;
- int x2 = -radius;
- int x;
- if (mini_title_animation_->current_part_index() == 0) {
- x = mini_title_animation_->CurrentValueBetween(x0, x1);
- } else if (mini_title_animation_->current_part_index() == 1) {
- x = x1;
- } else {
- x = mini_title_animation_->CurrentValueBetween(x1, x2);
- }
- SkPaint paint;
- SkPoint loc = { SkIntToScalar(x), SkIntToScalar(0) };
- SkColor colors[2];
- colors[0] = kMiniTitleChangeGradientColor1;
- colors[1] = kMiniTitleChangeGradientColor2;
- SkShader* shader = SkGradientShader::CreateRadial(
- loc,
- SkIntToScalar(radius),
- colors,
- NULL,
- 2,
- SkShader::kClamp_TileMode);
- paint.setShader(shader);
- shader->unref();
- hover_canvas.FillRectInt(x - radius, -radius, radius * 2, radius * 2, paint);
-
- // Draw the radial gradient clipped to the background into hover_image.
- SkBitmap hover_image = SkBitmapOperations::CreateMaskedBitmap(
- hover_canvas.ExtractBitmap(), background_image);
-
- // Draw the tab background to the canvas.
- canvas->DrawBitmapInt(background_image, 0, 0);
-
- // And then the gradient on top of that.
- if (mini_title_animation_->current_part_index() == 2) {
- canvas->saveLayerAlpha(NULL,
- mini_title_animation_->CurrentValueBetween(255, 0));
- canvas->DrawBitmapInt(hover_image, 0, 0);
- canvas->restore();
- } else {
- canvas->DrawBitmapInt(hover_image, 0, 0);
- }
-}
-
-void TabRenderer::PaintInactiveTabBackground(gfx::Canvas* canvas) {
- bool is_otr = data().off_the_record;
-
- // The tab image needs to be lined up with the background image
- // so that it feels partially transparent. These offsets represent the tab
- // position within the frame background image.
- int offset = GetX(views::View::APPLY_MIRRORING_TRANSFORMATION) +
- background_offset_.x();
-
- int tab_id;
- if (GetWidget() &&
- GetWidget()->GetWindow()->GetNonClientView()->UseNativeFrame()) {
- tab_id = IDR_THEME_TAB_BACKGROUND_V;
- } else {
- tab_id = is_otr ? IDR_THEME_TAB_BACKGROUND_INCOGNITO :
- IDR_THEME_TAB_BACKGROUND;
- }
-
- SkBitmap* tab_bg = GetThemeProvider()->GetBitmapNamed(tab_id);
-
- // App tabs are drawn slightly differently (as nano tabs).
- TabImage* tab_image = data().app ? &tab_active_nano : &tab_active;
- TabImage* tab_inactive_image = data().app ? &tab_inactive_nano :
- &tab_inactive;
- TabImage* alpha = data().app ? &tab_alpha_nano : &tab_alpha;
-
- // If the theme is providing a custom background image, then its top edge
- // should be at the top of the tab. Otherwise, we assume that the background
- // image is a composited foreground + frame image.
- int bg_offset_y = GetThemeProvider()->HasCustomImage(tab_id) ?
- 0 : background_offset_.y();
-
- // Draw left edge. Don't draw over the toolbar, as we're not the foreground
- // tab.
- SkBitmap tab_l = SkBitmapOperations::CreateTiledBitmap(
- *tab_bg, offset, bg_offset_y, tab_image->l_width, height());
- SkBitmap theme_l =
- SkBitmapOperations::CreateMaskedBitmap(tab_l, *alpha->image_l);
- canvas->DrawBitmapInt(theme_l,
- 0, 0, theme_l.width(), theme_l.height() - kToolbarOverlap,
- 0, 0, theme_l.width(), theme_l.height() - kToolbarOverlap,
- false);
-
- // Draw right edge. Again, don't draw over the toolbar.
- SkBitmap tab_r = SkBitmapOperations::CreateTiledBitmap(*tab_bg,
- offset + width() - tab_image->r_width, bg_offset_y,
- tab_image->r_width, height());
- SkBitmap theme_r =
- SkBitmapOperations::CreateMaskedBitmap(tab_r, *alpha->image_r);
- canvas->DrawBitmapInt(theme_r,
- 0, 0, theme_r.width(), theme_r.height() - kToolbarOverlap,
- width() - theme_r.width(), 0, theme_r.width(),
- theme_r.height() - kToolbarOverlap, false);
-
- // Draw center. Instead of masking out the top portion we simply skip over
- // it by incrementing by kDropShadowHeight, since it's a simple rectangle.
- // And again, don't draw over the toolbar.
- canvas->TileImageInt(*tab_bg,
- offset + tab_image->l_width,
- bg_offset_y + kDropShadowHeight + tab_image->y_offset,
- tab_image->l_width,
- kDropShadowHeight + tab_image->y_offset,
- width() - tab_image->l_width - tab_image->r_width,
- height() - kDropShadowHeight - kToolbarOverlap - tab_image->y_offset);
-
- // Now draw the highlights/shadows around the tab edge.
- canvas->DrawBitmapInt(*tab_inactive_image->image_l, 0, 0);
- canvas->TileImageInt(*tab_inactive_image->image_c,
- tab_inactive_image->l_width, 0,
- width() - tab_inactive_image->l_width -
- tab_inactive_image->r_width,
- height());
- canvas->DrawBitmapInt(*tab_inactive_image->image_r,
- width() - tab_inactive_image->r_width, 0);
-}
-
-void TabRenderer::PaintActiveTabBackground(gfx::Canvas* canvas) {
- int offset = GetX(views::View::APPLY_MIRRORING_TRANSFORMATION) +
- background_offset_.x();
- ThemeProvider* tp = GetThemeProvider();
- if (!tp)
- NOTREACHED() << "Unable to get theme provider";
-
- SkBitmap* tab_bg = GetThemeProvider()->GetBitmapNamed(IDR_THEME_TOOLBAR);
-
- // App tabs are drawn slightly differently (as nano tabs).
- TabImage* tab_image = data().app ? &tab_active_nano : &tab_active;
- TabImage* alpha = data().app ? &tab_alpha_nano : &tab_alpha;
-
- // Draw left edge.
- SkBitmap tab_l = SkBitmapOperations::CreateTiledBitmap(
- *tab_bg, offset, 0, tab_image->l_width, height());
- SkBitmap theme_l =
- SkBitmapOperations::CreateMaskedBitmap(tab_l, *alpha->image_l);
- canvas->DrawBitmapInt(theme_l, 0, 0);
-
- // Draw right edge.
- SkBitmap tab_r = SkBitmapOperations::CreateTiledBitmap(*tab_bg,
- offset + width() - tab_image->r_width, 0, tab_image->r_width, height());
- SkBitmap theme_r =
- SkBitmapOperations::CreateMaskedBitmap(tab_r, *alpha->image_r);
- canvas->DrawBitmapInt(theme_r, width() - tab_image->r_width, 0);
-
- // Draw center. Instead of masking out the top portion we simply skip over it
- // by incrementing by kDropShadowHeight, since it's a simple rectangle.
- canvas->TileImageInt(*tab_bg,
- offset + tab_image->l_width,
- kDropShadowHeight + tab_image->y_offset,
- tab_image->l_width,
- kDropShadowHeight + tab_image->y_offset,
- width() - tab_image->l_width - tab_image->r_width,
- height() - kDropShadowHeight - tab_image->y_offset);
-
- // Now draw the highlights/shadows around the tab edge.
- canvas->DrawBitmapInt(*tab_image->image_l, 0, 0);
- canvas->TileImageInt(*tab_image->image_c, tab_image->l_width, 0,
- width() - tab_image->l_width - tab_image->r_width, height());
- canvas->DrawBitmapInt(*tab_image->image_r, width() - tab_image->r_width, 0);
-}
-
-void TabRenderer::PaintLoadingAnimation(gfx::Canvas* canvas) {
- SkBitmap* frames =
- (data().network_state == TabRendererData::NETWORK_STATE_WAITING) ?
- waiting_animation_frames : loading_animation_frames;
- int image_size = frames->height();
- int image_offset = animation_frame_ * image_size;
- int dst_y = (height() - image_size) / 2;
-
- // Just like with the Tab's title and favicon, the position for the page
- // loading animation also needs to be mirrored if the View's UI layout is
- // right-to-left.
- int dst_x;
- if (data().mini) {
- dst_x = favicon_bounds_.x();
- if (favicon_bounds_.width() != kFavIconSize)
- dst_x += (favicon_bounds_.width() - kFavIconSize) / 2;
- } else {
- if (base::i18n::IsRTL()) {
- dst_x = width() - kLeftPadding - image_size;
- } else {
- dst_x = kLeftPadding;
- }
- }
- canvas->DrawBitmapInt(*frames, image_offset, 0, image_size,
- image_size, dst_x, dst_y, image_size, image_size,
- false);
-}
-
-void TabRenderer::PaintAsNewTab(gfx::Canvas* canvas) {
- bool is_otr = data().off_the_record;
-
- // The tab image needs to be lined up with the background image
- // so that it feels partially transparent. These offsets represent the tab
- // position within the frame background image.
- int offset = GetX(views::View::APPLY_MIRRORING_TRANSFORMATION) +
- background_offset_.x();
-
- int tab_id;
- if (GetWidget() &&
- GetWidget()->GetWindow()->GetNonClientView()->UseNativeFrame()) {
- tab_id = IDR_THEME_TAB_BACKGROUND_V;
- } else {
- tab_id = is_otr ? IDR_THEME_TAB_BACKGROUND_INCOGNITO :
- IDR_THEME_TAB_BACKGROUND;
- }
-
- SkBitmap* tab_bg = GetThemeProvider()->GetBitmapNamed(tab_id);
-
- // If the theme is providing a custom background image, then its top edge
- // should be at the top of the tab. Otherwise, we assume that the background
- // image is a composited foreground + frame image.
- int bg_offset_y = GetThemeProvider()->HasCustomImage(tab_id) ?
- 0 : background_offset_.y();
-
- SkBitmap image = SkBitmapOperations::CreateTiledBitmap(
- *tab_bg, offset, bg_offset_y, new_tab_mask->width(),
- new_tab_mask->height());
- image = SkBitmapOperations::CreateMaskedBitmap(image, *new_tab_mask);
- canvas->DrawBitmapInt(image,
- 0, 0, image.width(), image.height(),
- 0, 0, image.width(), image.height(),
- false);
-
- canvas->DrawBitmapInt(*new_tab_shadow,
- 0, 0, new_tab_shadow->width(), new_tab_shadow->height(),
- 0, 0, new_tab_shadow->width(), new_tab_shadow->height(),
- false);
-}
-
-int TabRenderer::IconCapacity() const {
- if (height() < GetMinimumUnselectedSize().height())
- return 0;
- return (width() - kLeftPadding - kRightPadding) / kFavIconSize;
-}
-
-bool TabRenderer::ShouldShowIcon() const {
- if (data().mini && height() >= GetMinimumUnselectedSize().height())
- return true;
- if (!data().show_icon) {
- return false;
- } else if (IsSelected()) {
- // The selected tab clips favicon before close button.
- return IconCapacity() >= 2;
- }
- // Non-selected tabs clip close button before favicon.
- return IconCapacity() >= 1;
-}
-
-bool TabRenderer::ShouldShowCloseBox() const {
- // The selected tab never clips close button.
- return !data().mini && (IsSelected() || IconCapacity() >= 3);
-}
-
-double TabRenderer::GetThrobValue() {
- if (alpha_ != 1)
- return alpha_;
-
- if (pulse_animation_->is_animating())
- return pulse_animation_->GetCurrentValue() * kHoverOpacity;
-
- return hover_animation_.get() ?
- kHoverOpacity * hover_animation_->GetCurrentValue() : 0;
-}
-
-////////////////////////////////////////////////////////////////////////////////
-// TabRenderer, private:
-
-void TabRenderer::StartCrashAnimation() {
- if (!crash_animation_)
- crash_animation_ = new FavIconCrashAnimation(this);
- crash_animation_->Stop();
- crash_animation_->Start();
-}
-
-void TabRenderer::StopCrashAnimation() {
- if (!crash_animation_)
- return;
- crash_animation_->Stop();
-}
-
-bool TabRenderer::IsPerformingCrashAnimation() const {
- return crash_animation_ && crash_animation_->is_animating();
-}
-
-void TabRenderer::SetFavIconHidingOffset(int offset) {
- fav_icon_hiding_offset_ = offset;
- SchedulePaint();
-}
-
-void TabRenderer::DisplayCrashedFavIcon() {
- should_display_crashed_favicon_ = true;
-}
-
-void TabRenderer::ResetCrashedFavIcon() {
- should_display_crashed_favicon_ = false;
-}
-
-// static
-void TabRenderer::LoadTabImages() {
- // We're not letting people override tab images just yet.
- ResourceBundle& rb = ResourceBundle::GetSharedInstance();
-
- tab_alpha.image_l = rb.GetBitmapNamed(IDR_TAB_ALPHA_LEFT);
- tab_alpha.image_r = rb.GetBitmapNamed(IDR_TAB_ALPHA_RIGHT);
-
- tab_alpha_nano.image_l = rb.GetBitmapNamed(IDR_TAB_ALPHA_NANO_LEFT);
- tab_alpha_nano.image_r = rb.GetBitmapNamed(IDR_TAB_ALPHA_NANO_RIGHT);
-
- tab_active.image_l = rb.GetBitmapNamed(IDR_TAB_ACTIVE_LEFT);
- tab_active.image_c = rb.GetBitmapNamed(IDR_TAB_ACTIVE_CENTER);
- tab_active.image_r = rb.GetBitmapNamed(IDR_TAB_ACTIVE_RIGHT);
- tab_active.l_width = tab_active.image_l->width();
- tab_active.r_width = tab_active.image_r->width();
-
- // The regular tab is much taller *visually* than the nano tabs.
- // The images are the same height, this is really just the difference
- // in whitespace above the tab image (regular vs nano).
- const int kNanoTabDiffHeight = 13;
-
- tab_active_nano.image_l = rb.GetBitmapNamed(IDR_TAB_ACTIVE_NANO_LEFT);
- tab_active_nano.image_c = rb.GetBitmapNamed(IDR_TAB_ACTIVE_NANO_CENTER);
- tab_active_nano.image_r = rb.GetBitmapNamed(IDR_TAB_ACTIVE_NANO_RIGHT);
- tab_active_nano.l_width = tab_active_nano.image_l->width();
- tab_active_nano.r_width = tab_active_nano.image_r->width();
- tab_active_nano.y_offset = kNanoTabDiffHeight;
-
- tab_inactive.image_l = rb.GetBitmapNamed(IDR_TAB_INACTIVE_LEFT);
- tab_inactive.image_c = rb.GetBitmapNamed(IDR_TAB_INACTIVE_CENTER);
- tab_inactive.image_r = rb.GetBitmapNamed(IDR_TAB_INACTIVE_RIGHT);
- tab_inactive.l_width = tab_inactive.image_l->width();
- tab_inactive.r_width = tab_inactive.image_r->width();
-
- tab_inactive_nano.image_l = rb.GetBitmapNamed(IDR_TAB_INACTIVE_NANO_LEFT);
- tab_inactive_nano.image_c = rb.GetBitmapNamed(IDR_TAB_INACTIVE_NANO_CENTER);
- tab_inactive_nano.image_r = rb.GetBitmapNamed(IDR_TAB_INACTIVE_NANO_RIGHT);
- tab_inactive_nano.l_width = tab_inactive_nano.image_l->width();
- tab_inactive_nano.r_width = tab_inactive_nano.image_r->width();
- tab_inactive_nano.y_offset = kNanoTabDiffHeight;
-
- loading_animation_frames = rb.GetBitmapNamed(IDR_THROBBER);
- waiting_animation_frames = rb.GetBitmapNamed(IDR_THROBBER_WAITING);
-
- new_tab_mask = rb.GetBitmapNamed(IDR_TAB_ALPHA_NEW_TAB);
- new_tab_shadow = rb.GetBitmapNamed(IDR_TAB_NEW_TAB_SHADOW);
-}
diff --git a/chrome/browser/views/tabs/tab_renderer.h b/chrome/browser/views/tabs/tab_renderer.h
deleted file mode 100644
index 7247b50..0000000
--- a/chrome/browser/views/tabs/tab_renderer.h
+++ /dev/null
@@ -1,248 +0,0 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef CHROME_BROWSER_VIEWS_TABS_TAB_RENDERER_H_
-#define CHROME_BROWSER_VIEWS_TABS_TAB_RENDERER_H_
-
-#include "app/animation.h"
-#include "base/scoped_ptr.h"
-#include "chrome/browser/views/tabs/base_tab_renderer.h"
-#include "gfx/point.h"
-#include "views/controls/button/image_button.h"
-
-class AnimationContainer;
-class MultiAnimation;
-class SlideAnimation;
-class ThrobAnimation;
-
-///////////////////////////////////////////////////////////////////////////////
-//
-// TabRenderer
-//
-// A View that renders a Tab, either in a TabStrip or in a DraggedTabView.
-//
-///////////////////////////////////////////////////////////////////////////////
-class TabRenderer : public BaseTabRenderer,
- public views::ButtonListener,
- public AnimationDelegate {
- public:
- explicit TabRenderer(TabController* controller);
- virtual ~TabRenderer();
-
- // Sizes the renderer to the size of the new tab images. This is used
- // during the new tab animation. See TabStrip's description of AnimationType
- // for details.
- void SizeToNewTabButtonImages();
-
- // Overridden from views:
- void ViewHierarchyChanged(bool is_add, View* parent, View* child);
- ThemeProvider* GetThemeProvider();
-
- // Used during new tab animation to force the tab to render a new tab like
- // animation.
- void set_render_as_new_tab(bool value) { render_as_new_tab_ = value; }
-
- // Sets the alpha value to render the tab at. This is used during the new
- // tab animation.
- void set_alpha(double value) { alpha_ = value; }
-
- // Forces the tab to render unselected even though it is selected.
- void set_render_unselected(bool value) { render_unselected_ = value; }
- bool render_unselected() const { return render_unselected_; }
-
- // Returns true if the Tab is selected, false otherwise.
- virtual bool IsSelected() const;
-
- // Starts/Stops a pulse animation.
- void StartPulse();
- void StopPulse();
-
- // Start/stop the mini-tab title animation.
- void StartMiniTabTitleAnimation();
- void StopMiniTabTitleAnimation();
-
- // Set the background offset used to match the image in the inactive tab
- // to the frame image.
- void SetBackgroundOffset(const gfx::Point& offset) {
- background_offset_ = offset;
- }
-
- // Set the theme provider - because we get detached, we are frequently
- // outside of a hierarchy with a theme provider at the top. This should be
- // called whenever we're detached or attached to a hierarchy.
- void SetThemeProvider(ThemeProvider* provider) {
- theme_provider_ = provider;
- }
-
- // Sets the container all animations run from.
- void SetAnimationContainer(AnimationContainer* container);
-
- // Paints the icon. Most of the time you'll want to invoke Paint directly, but
- // in certain situations this invoked outside of Paint.
- void PaintIcon(gfx::Canvas* canvas);
-
- // Returns the minimum possible size of a single unselected Tab.
- static gfx::Size GetMinimumUnselectedSize();
- // Returns the minimum possible size of a selected Tab. Selected tabs must
- // always show a close button and have a larger minimum size than unselected
- // tabs.
- static gfx::Size GetMinimumSelectedSize();
- // Returns the preferred size of a single Tab, assuming space is
- // available.
- static gfx::Size GetStandardSize();
-
- // Returns the width for mini-tabs. Mini-tabs always have this width.
- static int GetMiniWidth();
-
- // Loads the images to be used for the tab background.
- static void LoadTabImages();
-
- protected:
- views::ImageButton* close_button() const { return close_button_; }
- const gfx::Rect& title_bounds() const { return title_bounds_; }
-
- // Returns the title of the Tab.
- std::wstring GetTitle() const;
-
- // Overridden from views::View:
- virtual void OnMouseEntered(const views::MouseEvent& event);
- virtual void OnMouseExited(const views::MouseEvent& event);
-
- // views::ButtonListener overrides:
- virtual void ButtonPressed(views::Button* sender,
- const views::Event& event) {}
-
- // BaseTabRenderer overrides:
- virtual void DataChanged(const TabRendererData& old);
- virtual void AdvanceLoadingAnimation(TabRendererData::NetworkState state);
-
- private:
- // Overridden from views::View:
- virtual void Paint(gfx::Canvas* canvas);
- virtual void Layout();
- virtual void ThemeChanged();
-
- // Overridden from AnimationDelegate:
- virtual void AnimationProgressed(const Animation* animation);
- virtual void AnimationCanceled(const Animation* animation);
- virtual void AnimationEnded(const Animation* animation);
-
- // Starts/Stops the crash animation.
- void StartCrashAnimation();
- void StopCrashAnimation();
-
- // Return true if the crash animation is currently running.
- bool IsPerformingCrashAnimation() const;
-
- // Set the temporary offset for the favicon. This is used during animation.
- void SetFavIconHidingOffset(int offset);
-
- void DisplayCrashedFavIcon();
- void ResetCrashedFavIcon();
-
- // Paint various portions of the Tab
- void PaintTitle(SkColor title_color, gfx::Canvas* canvas);
- void PaintTabBackground(gfx::Canvas* canvas);
- void PaintInactiveTabBackgroundWithTitleChange(gfx::Canvas* canvas);
- void PaintInactiveTabBackground(gfx::Canvas* canvas);
- void PaintActiveTabBackground(gfx::Canvas* canvas);
- void PaintLoadingAnimation(gfx::Canvas* canvas);
- void PaintAsNewTab(gfx::Canvas* canvas);
-
- // Returns the number of favicon-size elements that can fit in the tab's
- // current size.
- int IconCapacity() const;
-
- // Returns whether the Tab should display a favicon.
- bool ShouldShowIcon() const;
-
- // Returns whether the Tab should display a close button.
- bool ShouldShowCloseBox() const;
-
- // Gets the throb value for the tab. When a tab is not selected the
- // active background is drawn at |GetThrobValue()|%. This is used for hover,
- // mini tab title change and pulsing.
- double GetThrobValue();
-
- // The bounds of various sections of the display.
- gfx::Rect favicon_bounds_;
- gfx::Rect title_bounds_;
-
- // The offset used to paint the inactive background image.
- gfx::Point background_offset_;
-
- // The current index into the Animation image strip.
- int animation_frame_;
-
- // Close Button.
- views::ImageButton* close_button_;
-
- // Whether to disable throbber animations. Only true if this is a
- // Nano tab renderer and a command line flag has been passed in to
- // disable the animations.
- bool throbber_disabled_;
-
- // Hover animation.
- scoped_ptr<SlideAnimation> hover_animation_;
-
- // Pulse animation.
- scoped_ptr<ThrobAnimation> pulse_animation_;
-
- // Animation used when the title of an inactive mini tab changes.
- scoped_ptr<MultiAnimation> mini_title_animation_;
-
- struct TabImage {
- SkBitmap* image_l;
- SkBitmap* image_c;
- SkBitmap* image_r;
- int l_width;
- int r_width;
- int y_offset;
- };
- static TabImage tab_active;
- static TabImage tab_active_nano;
- static TabImage tab_inactive;
- static TabImage tab_inactive_nano;
- static TabImage tab_alpha;
- static TabImage tab_alpha_nano;
-
- // Whether we're showing the icon. It is cached so that we can detect when it
- // changes and layout appropriately.
- bool showing_icon_;
-
- // Whether we are showing the close button. It is cached so that we can
- // detect when it changes and layout appropriately.
- bool showing_close_button_;
-
- // The offset used to animate the favicon location.
- int fav_icon_hiding_offset_;
-
- // The current color of the close button.
- SkColor close_button_color_;
-
- // See description above setter.
- bool render_as_new_tab_;
-
- // See description above setter.
- bool render_unselected_;
-
- // See description above setter.
- double alpha_;
-
- // The animation object used to swap the favicon with the sad tab icon.
- class FavIconCrashAnimation;
- FavIconCrashAnimation* crash_animation_;
-
- bool should_display_crashed_favicon_;
-
- ThemeProvider* theme_provider_;
-
- scoped_refptr<AnimationContainer> container_;
-
- static bool initialized_;
-
- DISALLOW_COPY_AND_ASSIGN(TabRenderer);
-};
-
-#endif // CHROME_BROWSER_VIEWS_TABS_TAB_RENDERER_H_
diff --git a/chrome/browser/views/tabs/tab_strip.cc b/chrome/browser/views/tabs/tab_strip.cc
index c6e45fa..2c1af2a 100644
--- a/chrome/browser/views/tabs/tab_strip.cc
+++ b/chrome/browser/views/tabs/tab_strip.cc
@@ -110,7 +110,7 @@ class NewTabAlphaDelegate
class ResetDraggingStateDelegate
: public views::BoundsAnimator::OwnedAnimationDelegate {
public:
- explicit ResetDraggingStateDelegate(BaseTabRenderer* tab) : tab_(tab) {
+ explicit ResetDraggingStateDelegate(BaseTab* tab) : tab_(tab) {
}
virtual void AnimationEnded(const Animation* animation) {
@@ -122,7 +122,7 @@ class ResetDraggingStateDelegate
}
private:
- BaseTabRenderer* tab_;
+ BaseTab* tab_;
DISALLOW_COPY_AND_ASSIGN(ResetDraggingStateDelegate);
};
@@ -419,11 +419,11 @@ void TabStrip::StopAllHighlighting() {
GetTabAtTabDataIndex(i)->StopPulse();
}
-BaseTabRenderer* TabStrip::CreateTabForDragging() {
+BaseTab* TabStrip::CreateTabForDragging() {
Tab* tab = new Tab(NULL);
// Make sure the dragged tab shares our theme provider. We need to explicitly
// do this as during dragging there isn't a theme provider.
- tab->SetThemeProvider(GetThemeProvider());
+ tab->set_theme_provider(GetThemeProvider());
return tab;
}
@@ -610,7 +610,7 @@ views::View* TabStrip::GetViewForPoint(const gfx::Point& point) {
// Return any view that isn't a Tab or this TabStrip immediately. We don't
// want to interfere.
views::View* v = View::GetViewForPoint(point);
- if (v && v != this && v->GetClassName() != Tab::kTabClassName)
+ if (v && v != this && v->GetClassName() != Tab::kViewClassName)
return v;
// The display order doesn't necessarily match the child list order, so we
@@ -643,9 +643,9 @@ void TabStrip::OnBoundsAnimatorDone(views::BoundsAnimator* animator) {
NewTabAnimation2Done();
}
-Tab* TabStrip::CreateTab() {
+BaseTab* TabStrip::CreateTab() {
Tab* tab = new Tab(this);
- tab->SetAnimationContainer(animation_container_.get());
+ tab->set_animation_container(animation_container_.get());
return tab;
}
@@ -665,7 +665,7 @@ void TabStrip::StartMoveTabAnimation() {
AnimateToIdealBounds();
}
-void TabStrip::StartedDraggingTab(BaseTabRenderer* tab) {
+void TabStrip::StartedDraggingTab(BaseTab* tab) {
tab->set_dragging(true);
// Stop any animations on the tab.
@@ -679,7 +679,7 @@ void TabStrip::StartedDraggingTab(BaseTabRenderer* tab) {
SchedulePaint();
}
-void TabStrip::StoppedDraggingTab(BaseTabRenderer* tab) {
+void TabStrip::StoppedDraggingTab(BaseTab* tab) {
int tab_data_index = TabIndexOfTab(tab);
if (tab_data_index == -1) {
// The tab was removed before the drag completed. Don't do anything.
@@ -709,7 +709,7 @@ void TabStrip::ViewHierarchyChanged(bool is_add,
///////////////////////////////////////////////////////////////////////////////
// TabStrip, Tab::Delegate implementation:
-bool TabStrip::IsTabSelected(const BaseTabRenderer* btr) const {
+bool TabStrip::IsTabSelected(const BaseTab* btr) const {
const Tab* tab = static_cast<const Tab*>(btr);
if (tab->closing() || tab->render_unselected())
return false;
@@ -1159,7 +1159,7 @@ void TabStrip::GenerateIdealBounds() {
int mini_tab_count = 0;
int nano_tab_count = 0;
for (int i = 0; i < tab_count(); ++i) {
- BaseTabRenderer* tab = base_tab_at_tab_index(i);
+ BaseTab* tab = base_tab_at_tab_index(i);
if (!tab->closing()) {
++non_closing_tab_count;
if (tab->data().mini)
@@ -1327,12 +1327,12 @@ void TabStrip::StartInsertTabAnimationImpl(int model_index) {
GenerateIdealBounds();
int tab_data_index = ModelIndexToTabIndex(model_index);
- BaseTabRenderer* tab = base_tab_at_tab_index(tab_data_index);
+ BaseTab* tab = base_tab_at_tab_index(tab_data_index);
if (model_index == 0) {
tab->SetBounds(0, ideal_bounds(tab_data_index).y(), 0,
ideal_bounds(tab_data_index).height());
} else {
- BaseTabRenderer* last_tab = base_tab_at_tab_index(tab_data_index - 1);
+ BaseTab* last_tab = base_tab_at_tab_index(tab_data_index - 1);
tab->SetBounds(last_tab->bounds().right() + kTabHOffset,
ideal_bounds(tab_data_index).y(), 0,
ideal_bounds(tab_data_index).height());
diff --git a/chrome/browser/views/tabs/tab_strip.h b/chrome/browser/views/tabs/tab_strip.h
index 0eadbc1..7486f46 100644
--- a/chrome/browser/views/tabs/tab_strip.h
+++ b/chrome/browser/views/tabs/tab_strip.h
@@ -10,12 +10,13 @@
#include "base/ref_counted.h"
#include "base/timer.h"
#include "chrome/browser/views/tabs/base_tab_strip.h"
-#include "chrome/browser/views/tabs/tab.h"
#include "gfx/point.h"
#include "gfx/rect.h"
#include "views/animation/bounds_animator.h"
#include "views/controls/button/image_button.h"
+class Tab;
+
namespace views {
class ImageView;
#if defined(OS_LINUX)
@@ -76,7 +77,7 @@ class TabStrip : public BaseTabStrip,
virtual void SetTabData(int model_index, const TabRendererData& data);
virtual void StartHighlight(int model_index);
virtual void StopAllHighlighting();
- virtual BaseTabRenderer* CreateTabForDragging();
+ virtual BaseTab* CreateTabForDragging();
// views::View overrides:
virtual void PaintChildren(gfx::Canvas* canvas);
@@ -98,11 +99,11 @@ class TabStrip : public BaseTabStrip,
protected:
// BaseTabStrip overrides:
- virtual Tab* CreateTab();
+ virtual BaseTab* CreateTab();
virtual void StartInsertTabAnimation(int model_index, bool foreground);
virtual void StartMoveTabAnimation();
- virtual void StartedDraggingTab(BaseTabRenderer* tab);
- virtual void StoppedDraggingTab(BaseTabRenderer* tab);
+ virtual void StartedDraggingTab(BaseTab* tab);
+ virtual void StoppedDraggingTab(BaseTab* tab);
// views::View implementation:
virtual void ViewHierarchyChanged(bool is_add,
@@ -110,7 +111,7 @@ class TabStrip : public BaseTabStrip,
views::View* child);
// TabController overrides.
- virtual bool IsTabSelected(const BaseTabRenderer* btr) const;
+ virtual bool IsTabSelected(const BaseTab* btr) const;
// views::ButtonListener implementation:
virtual void ButtonPressed(views::Button* sender, const views::Event& event);
diff --git a/chrome/browser/views/tabs/tab_strip_controller.h b/chrome/browser/views/tabs/tab_strip_controller.h
index 90cd87c..9f6d0cc 100644
--- a/chrome/browser/views/tabs/tab_strip_controller.h
+++ b/chrome/browser/views/tabs/tab_strip_controller.h
@@ -7,7 +7,7 @@
#include <vector>
-class BaseTabRenderer;
+class BaseTab;
class BaseTabStrip;
class GURL;
@@ -46,7 +46,7 @@ class TabStripController {
virtual void CloseTab(int index) = 0;
// Shows a context menu for the tab at the specified point in screen coords.
- virtual void ShowContextMenu(BaseTabRenderer* tab, const gfx::Point& p) = 0;
+ virtual void ShowContextMenu(BaseTab* tab, const gfx::Point& p) = 0;
// Updates the loading animations of all the tabs.
virtual void UpdateLoadingAnimations() = 0;
diff --git a/chrome/chrome_browser.gypi b/chrome/chrome_browser.gypi
index 745952d..55a75ce 100644
--- a/chrome/chrome_browser.gypi
+++ b/chrome/chrome_browser.gypi
@@ -2467,8 +2467,8 @@
'browser/views/tab_contents/tab_contents_view_gtk.h',
'browser/views/tab_contents/tab_contents_view_win.cc',
'browser/views/tab_contents/tab_contents_view_win.h',
- 'browser/views/tabs/base_tab_renderer.cc',
- 'browser/views/tabs/base_tab_renderer.h',
+ 'browser/views/tabs/base_tab.cc',
+ 'browser/views/tabs/base_tab.h',
'browser/views/tabs/base_tab_strip.cc',
'browser/views/tabs/base_tab_strip.h',
'browser/views/tabs/browser_tab_strip_controller.cc',
@@ -2488,8 +2488,7 @@
'browser/views/tabs/side_tab_strip.h',
'browser/views/tabs/tab.cc',
'browser/views/tabs/tab.h',
- 'browser/views/tabs/tab_renderer.cc',
- 'browser/views/tabs/tab_renderer.h',
+ 'browser/views/tabs/tab_controller.h',
'browser/views/tabs/tab_renderer_data.h',
'browser/views/tabs/tab_strip.cc',
'browser/views/tabs/tab_strip.h',
@@ -3045,8 +3044,8 @@
['include', '^browser/views/tab_contents/tab_contents_view_gtk.h'],
['include', '^browser/views/tab_icon_view.cc'],
['include', '^browser/views/tab_icon_view.h'],
- ['include', '^browser/views/tabs/base_tab_renderer.cc'],
- ['include', '^browser/views/tabs/base_tab_renderer.h'],
+ ['include', '^browser/views/tabs/base_tab.cc'],
+ ['include', '^browser/views/tabs/base_tab.h'],
['include', '^browser/views/tabs/base_tab_strip.cc'],
['include', '^browser/views/tabs/base_tab_strip.h'],
['include', '^browser/views/tabs/browser_tab_strip_controller.cc'],
@@ -3066,8 +3065,7 @@
['include', '^browser/views/tabs/side_tab_strip.h'],
['include', '^browser/views/tabs/tab.cc'],
['include', '^browser/views/tabs/tab.h'],
- ['include', '^browser/views/tabs/tab_renderer.cc'],
- ['include', '^browser/views/tabs/tab_renderer.h'],
+ ['include', '^browser/views/tabs/tab_controller.h'],
['include', '^browser/views/tabs/tab_renderer_data.h'],
['include', '^browser/views/tabs/tab_strip.cc'],
['include', '^browser/views/tabs/tab_strip.h'],