summaryrefslogtreecommitdiffstats
path: root/chrome/browser/views/tabs
diff options
context:
space:
mode:
authorsky@chromium.org <sky@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2010-05-27 14:54:15 +0000
committersky@chromium.org <sky@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2010-05-27 14:54:15 +0000
commitb68becccf8fd9deb39346f1d36413817ab924e78 (patch)
tree0fa25577bf4034d9e5e380fdfb9f0b7a9d82d564 /chrome/browser/views/tabs
parent539d8f80f984dfed455b40533df0ad5d15e2c2ba (diff)
downloadchromium_src-b68becccf8fd9deb39346f1d36413817ab924e78.zip
chromium_src-b68becccf8fd9deb39346f1d36413817ab924e78.tar.gz
chromium_src-b68becccf8fd9deb39346f1d36413817ab924e78.tar.bz2
Adds the new tab button to side tabs.
BUG=none TEST=none Review URL: http://codereview.chromium.org/2224003 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@48389 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'chrome/browser/views/tabs')
-rw-r--r--chrome/browser/views/tabs/base_tab.cc12
-rw-r--r--chrome/browser/views/tabs/base_tab.h2
-rw-r--r--chrome/browser/views/tabs/base_tab_strip.cc21
-rw-r--r--chrome/browser/views/tabs/base_tab_strip.h5
-rw-r--r--chrome/browser/views/tabs/side_tab.cc6
-rw-r--r--chrome/browser/views/tabs/side_tab.h3
-rw-r--r--chrome/browser/views/tabs/side_tab_strip.cc106
-rw-r--r--chrome/browser/views/tabs/side_tab_strip.h15
-rw-r--r--chrome/browser/views/tabs/tab_strip.cc14
-rw-r--r--chrome/browser/views/tabs/tab_strip.h1
10 files changed, 157 insertions, 28 deletions
diff --git a/chrome/browser/views/tabs/base_tab.cc b/chrome/browser/views/tabs/base_tab.cc
index 070e1ee..f128abc 100644
--- a/chrome/browser/views/tabs/base_tab.cc
+++ b/chrome/browser/views/tabs/base_tab.cc
@@ -248,6 +248,9 @@ void BaseTab::OnMouseExited(const views::MouseEvent& e) {
}
bool BaseTab::OnMousePressed(const views::MouseEvent& event) {
+ if (!controller())
+ return false;
+
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
@@ -261,11 +264,15 @@ bool BaseTab::OnMousePressed(const views::MouseEvent& event) {
}
bool BaseTab::OnMouseDragged(const views::MouseEvent& event) {
- controller()->ContinueDrag(event);
+ if (controller())
+ controller()->ContinueDrag(event);
return true;
}
void BaseTab::OnMouseReleased(const views::MouseEvent& event, bool canceled) {
+ if (!controller())
+ return;
+
// 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
@@ -413,7 +420,8 @@ void BaseTab::ButtonPressed(views::Button* sender, const views::Event& event) {
void BaseTab::ShowContextMenu(views::View* source,
const gfx::Point& p,
bool is_mouse_gesture) {
- controller()->ShowContextMenu(this, p);
+ if (controller())
+ controller()->ShowContextMenu(this, p);
}
void BaseTab::ThemeChanged() {
diff --git a/chrome/browser/views/tabs/base_tab.h b/chrome/browser/views/tabs/base_tab.h
index 678594d..e2ac34a 100644
--- a/chrome/browser/views/tabs/base_tab.h
+++ b/chrome/browser/views/tabs/base_tab.h
@@ -72,7 +72,7 @@ class BaseTab : public AnimationDelegate,
}
// Returns true if the tab is selected.
- bool IsSelected() const;
+ virtual bool IsSelected() const;
// views::View overrides:
virtual void OnMouseEntered(const views::MouseEvent& event);
diff --git a/chrome/browser/views/tabs/base_tab_strip.cc b/chrome/browser/views/tabs/base_tab_strip.cc
index f978385..5008ddb 100644
--- a/chrome/browser/views/tabs/base_tab_strip.cc
+++ b/chrome/browser/views/tabs/base_tab_strip.cc
@@ -172,6 +172,20 @@ void BaseTabStrip::MoveTab(int from_model_index, int to_model_index) {
StartMoveTabAnimation();
}
+void BaseTabStrip::SetTabData(int model_index, const TabRendererData& data) {
+ BaseTab* tab = GetBaseTabAtModelIndex(model_index);
+ bool mini_state_changed = tab->data().mini != data.mini;
+ tab->SetData(data);
+ tab->SchedulePaint();
+
+ if (mini_state_changed) {
+ if (GetWindow() && GetWindow()->IsVisible())
+ StartMiniTabAnimation();
+ else
+ Layout();
+ }
+}
+
BaseTab* BaseTabStrip::GetBaseTabAtModelIndex(int model_index) const {
return base_tab_at_tab_index(ModelIndexToTabIndex(model_index));
}
@@ -342,6 +356,13 @@ void BaseTabStrip::StartRemoveTabAnimation(int model_index) {
true);
}
+void BaseTabStrip::StartMiniTabAnimation() {
+ PrepareForAnimation();
+
+ GenerateIdealBounds();
+ AnimateToIdealBounds();
+}
+
void BaseTabStrip::RemoveAndDeleteTab(BaseTab* tab) {
int tab_data_index = TabIndexOfTab(tab);
diff --git a/chrome/browser/views/tabs/base_tab_strip.h b/chrome/browser/views/tabs/base_tab_strip.h
index ded0b07..244edb2 100644
--- a/chrome/browser/views/tabs/base_tab_strip.h
+++ b/chrome/browser/views/tabs/base_tab_strip.h
@@ -104,7 +104,7 @@ class BaseTabStrip : public views::View,
virtual void TabTitleChangedNotLoading(int model_index) = 0;
// Sets the tab data at the specified model index.
- virtual void SetTabData(int model_index, const TabRendererData& data) = 0;
+ virtual void SetTabData(int model_index, const TabRendererData& data);
// Returns the tab at the specified model index.
virtual BaseTab* GetBaseTabAtModelIndex(int model_index) const;
@@ -183,6 +183,9 @@ class BaseTabStrip : public views::View,
// Starts the remove tab animation.
virtual void StartRemoveTabAnimation(int model_index);
+ // Starts the mini-tab animation.
+ virtual void StartMiniTabAnimation();
+
// Returns whether the highlight button should be highlighted after a remove.
virtual bool ShouldHighlightCloseButtonAfterRemove() { return true; }
diff --git a/chrome/browser/views/tabs/side_tab.cc b/chrome/browser/views/tabs/side_tab.cc
index d456a5d..fab7bf2 100644
--- a/chrome/browser/views/tabs/side_tab.cc
+++ b/chrome/browser/views/tabs/side_tab.cc
@@ -80,7 +80,7 @@ void SideTab::Layout() {
}
void SideTab::Paint(gfx::Canvas* canvas) {
- if (IsSelected() || !controller()) {
+ if (ShouldPaintHighlight()) {
SkPaint paint;
paint.setColor(kTabBackgroundColor);
paint.setAntiAlias(true);
@@ -100,6 +100,10 @@ gfx::Size SideTab::GetPreferredSize() {
return gfx::Size(0, GetPreferredHeight());
}
+bool SideTab::ShouldPaintHighlight() const {
+ return IsSelected() || !controller();
+}
+
bool SideTab::ShouldShowIcon() const {
return data().mini || data().show_icon;
}
diff --git a/chrome/browser/views/tabs/side_tab.h b/chrome/browser/views/tabs/side_tab.h
index d3b4236..9bc9631 100644
--- a/chrome/browser/views/tabs/side_tab.h
+++ b/chrome/browser/views/tabs/side_tab.h
@@ -28,6 +28,9 @@ class SideTab : public BaseTab {
protected:
virtual const gfx::Rect& title_bounds() const { return title_bounds_; }
+ // Returns true if the selected highlight should be rendered.
+ virtual bool ShouldPaintHighlight() const;
+
private:
// Returns true if the icon should be shown.
bool ShouldShowIcon() const;
diff --git a/chrome/browser/views/tabs/side_tab_strip.cc b/chrome/browser/views/tabs/side_tab_strip.cc
index 586f9c4..4b97b08 100644
--- a/chrome/browser/views/tabs/side_tab_strip.cc
+++ b/chrome/browser/views/tabs/side_tab_strip.cc
@@ -4,16 +4,66 @@
#include "chrome/browser/views/tabs/side_tab_strip.h"
+#include "app/l10n_util.h"
+#include "app/resource_bundle.h"
#include "chrome/browser/views/tabs/side_tab.h"
+#include "chrome/browser/views/tabs/tab_strip_controller.h"
#include "chrome/browser/view_ids.h"
+#include "gfx/canvas.h"
+#include "grit/generated_resources.h"
+#include "grit/theme_resources.h"
#include "views/background.h"
+#include "views/controls/button/image_button.h"
namespace {
const int kVerticalTabSpacing = 2;
const int kTabStripWidth = 140;
const SkColor kBackgroundColor = SkColorSetARGB(255, 209, 220, 248);
+const SkColor kSeparatorColor = SkColorSetARGB(255, 151, 159, 179);
+
+// Height of the separator.
+const int kSeparatorHeight = 1;
+
+// The new tab button is rendered using a SideTab.
+class SideTabNewTabButton : public SideTab {
+ public:
+ explicit SideTabNewTabButton(TabStripController* controller);
+
+ virtual bool ShouldPaintHighlight() const { return false; }
+ virtual bool IsSelected() const { return false; }
+ bool OnMousePressed(const views::MouseEvent& event);
+ void OnMouseReleased(const views::MouseEvent& event, bool canceled);
+
+ private:
+ TabStripController* controller_;
+
+ DISALLOW_COPY_AND_ASSIGN(SideTabNewTabButton);
+};
+
+SideTabNewTabButton::SideTabNewTabButton(TabStripController* controller)
+ : SideTab(NULL),
+ controller_(controller) {
+ // Never show a close button for the new tab button.
+ close_button()->SetVisible(false);
+ TabRendererData data;
+ data.favicon = *ResourceBundle::GetSharedInstance().GetBitmapNamed(
+ IDR_SIDETABS_NEW_TAB);
+ data.title = l10n_util::GetStringUTF16(IDS_NEW_TAB_TITLE);
+ SetData(data);
}
+bool SideTabNewTabButton::OnMousePressed(const views::MouseEvent& event) {
+ return true;
+}
+
+void SideTabNewTabButton::OnMouseReleased(const views::MouseEvent& event,
+ bool canceled) {
+ if (!canceled && event.IsOnlyLeftMouseButton() && HitTest(event.location()))
+ controller_->CreateNewTab();
+}
+
+} // namespace
+
// static
const int SideTabStrip::kTabStripInset = 3;
@@ -21,9 +71,15 @@ const int SideTabStrip::kTabStripInset = 3;
// SideTabStrip, public:
SideTabStrip::SideTabStrip(TabStripController* controller)
- : BaseTabStrip(controller, BaseTabStrip::VERTICAL_TAB_STRIP) {
+ : BaseTabStrip(controller, BaseTabStrip::VERTICAL_TAB_STRIP),
+ newtab_button_(new SideTabNewTabButton(controller)),
+ separator_(new views::View()) {
SetID(VIEW_ID_TAB_STRIP);
set_background(views::Background::CreateSolidBackground(kBackgroundColor));
+ AddChildView(newtab_button_);
+ separator_->set_background(
+ views::Background::CreateSolidBackground(kSeparatorColor));
+ AddChildView(separator_);
}
SideTabStrip::~SideTabStrip() {
@@ -77,12 +133,6 @@ void SideTabStrip::SelectTabAt(int old_model_index, int new_model_index) {
void SideTabStrip::TabTitleChangedNotLoading(int model_index) {
}
-void SideTabStrip::SetTabData(int model_index, const TabRendererData& data) {
- BaseTab* tab = GetBaseTabAtModelIndex(model_index);
- tab->SetData(data);
- tab->SchedulePaint();
-}
-
gfx::Size SideTabStrip::GetPreferredSize() {
return gfx::Size(kTabStripWidth, 0);
}
@@ -91,6 +141,11 @@ void SideTabStrip::PaintChildren(gfx::Canvas* canvas) {
// Make sure the dragged tab appears on top of all others by paint it last.
BaseTab* dragging_tab = NULL;
+ // Paint the new tab and separator first so that any tabs animating appear on
+ // top.
+ separator_->ProcessPaint(canvas);
+ newtab_button_->ProcessPaint(canvas);
+
for (int i = tab_count() - 1; i >= 0; --i) {
BaseTab* tab = base_tab_at_tab_index(i);
if (tab->dragging())
@@ -112,15 +167,40 @@ void SideTabStrip::GenerateIdealBounds() {
layout_rect.Inset(kTabStripInset, kTabStripInset);
int y = layout_rect.y();
+ bool last_was_mini = true;
+ bool has_non_closing_tab = false;
+ separator_bounds_.SetRect(0, -kSeparatorHeight, width(), kSeparatorHeight);
for (int i = 0; i < tab_count(); ++i) {
BaseTab* tab = base_tab_at_tab_index(i);
if (!tab->closing()) {
+ if (last_was_mini != tab->data().mini) {
+ if (has_non_closing_tab) {
+ separator_bounds_.SetRect(0, y, width(), kSeparatorHeight);
+ y += kSeparatorHeight + kVerticalTabSpacing;
+ }
+ newtab_button_bounds_.SetRect(
+ layout_rect.x(), y, layout_rect.width(),
+ newtab_button_->GetPreferredSize().height());
+ y = newtab_button_bounds_.bottom() + kVerticalTabSpacing;
+ last_was_mini = tab->data().mini;
+ }
gfx::Rect bounds = gfx::Rect(layout_rect.x(), y, layout_rect.width(),
tab->GetPreferredSize().height());
set_ideal_bounds(i, bounds);
y = bounds.bottom() + kVerticalTabSpacing;
+ has_non_closing_tab = true;
}
}
+
+ if (last_was_mini) {
+ if (has_non_closing_tab) {
+ separator_bounds_.SetRect(0, y, width(), kSeparatorHeight);
+ y += kSeparatorHeight + kVerticalTabSpacing;
+ }
+ newtab_button_bounds_ =
+ gfx::Rect(layout_rect.x(), y, layout_rect.width(),
+ newtab_button_->GetPreferredSize().height());
+ }
}
void SideTabStrip::StartInsertTabAnimation(int model_index, bool foreground) {
@@ -165,4 +245,16 @@ void SideTabStrip::AnimateToIdealBounds() {
if (!tab->closing() && !tab->dragging())
bounds_animator().AnimateViewTo(tab, ideal_bounds(i));
}
+
+ bounds_animator().AnimateViewTo(newtab_button_, newtab_button_bounds_);
+
+ bounds_animator().AnimateViewTo(separator_, separator_bounds_);
+}
+
+void SideTabStrip::Layout() {
+ BaseTabStrip::Layout();
+
+ newtab_button_->SetBounds(newtab_button_bounds_);
+
+ separator_->SetBounds(separator_bounds_);
}
diff --git a/chrome/browser/views/tabs/side_tab_strip.h b/chrome/browser/views/tabs/side_tab_strip.h
index 7603b060..6e52e70 100644
--- a/chrome/browser/views/tabs/side_tab_strip.h
+++ b/chrome/browser/views/tabs/side_tab_strip.h
@@ -31,7 +31,6 @@ class SideTabStrip : public BaseTabStrip {
virtual void RemoveTabAt(int model_index);
virtual void SelectTabAt(int old_model_index, int new_model_index);
virtual void TabTitleChangedNotLoading(int model_index);
- virtual void SetTabData(int model_index, const TabRendererData& data);
// views::View overrides:
virtual gfx::Size GetPreferredSize();
@@ -45,8 +44,22 @@ class SideTabStrip : public BaseTabStrip {
virtual void StartMoveTabAnimation();
virtual void StopAnimating(bool layout);
virtual void AnimateToIdealBounds();
+ virtual void Layout();
private:
+ // The "New Tab" button.
+ views::View* newtab_button_;
+
+ // Ideal bounds of the new tab button.
+ gfx::Rect newtab_button_bounds_;
+
+ // Separator between mini-tabs and the new tab button. The separator is
+ // positioned above the visible area if there are no mini-tabs.
+ views::View* separator_;
+
+ // Bounds of the sepatator.
+ gfx::Rect separator_bounds_;
+
DISALLOW_COPY_AND_ASSIGN(SideTabStrip);
};
diff --git a/chrome/browser/views/tabs/tab_strip.cc b/chrome/browser/views/tabs/tab_strip.cc
index 23d2389..857122a 100644
--- a/chrome/browser/views/tabs/tab_strip.cc
+++ b/chrome/browser/views/tabs/tab_strip.cc
@@ -303,20 +303,6 @@ void TabStrip::TabTitleChangedNotLoading(int model_index) {
tab->StartMiniTabTitleAnimation();
}
-void TabStrip::SetTabData(int model_index, const TabRendererData& data) {
- Tab* tab = GetTabAtModelIndex(model_index);
- bool mini_state_changed = tab->data().mini != data.mini;
- tab->SetData(data);
- tab->SchedulePaint();
-
- if (mini_state_changed) {
- if (GetWindow() && GetWindow()->IsVisible())
- StartMiniTabAnimation();
- else
- Layout();
- }
-}
-
void TabStrip::StartHighlight(int model_index) {
GetTabAtModelIndex(model_index)->StartPulse();
}
diff --git a/chrome/browser/views/tabs/tab_strip.h b/chrome/browser/views/tabs/tab_strip.h
index f547ca3..d1e9b29 100644
--- a/chrome/browser/views/tabs/tab_strip.h
+++ b/chrome/browser/views/tabs/tab_strip.h
@@ -73,7 +73,6 @@ class TabStrip : public BaseTabStrip,
virtual void RemoveTabAt(int model_index);
virtual void SelectTabAt(int old_model_index, int new_model_index);
virtual void TabTitleChangedNotLoading(int model_index);
- virtual void SetTabData(int model_index, const TabRendererData& data);
virtual void StartHighlight(int model_index);
virtual void StopAllHighlighting();
virtual BaseTab* CreateTabForDragging();