diff options
author | ben@chromium.org <ben@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2010-02-11 23:46:04 +0000 |
---|---|---|
committer | ben@chromium.org <ben@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2010-02-11 23:46:04 +0000 |
commit | 5a9bb950970d732b3d9f0ed4ecc052c6d213bde4 (patch) | |
tree | a48897126b35d149d0651f4fd53cf789c99af2b7 /chrome/browser/views/tabs | |
parent | 1525c68ec291218d831e29ea34aaf5a516daf855 (diff) | |
download | chromium_src-5a9bb950970d732b3d9f0ed4ecc052c6d213bde4.zip chromium_src-5a9bb950970d732b3d9f0ed4ecc052c6d213bde4.tar.gz chromium_src-5a9bb950970d732b3d9f0ed4ecc052c6d213bde4.tar.bz2 |
Make clicking on side tabs to select them work.
Use a simple round rect for the visual treatment.
Add some rect conversion utils.
http://crbug.com/34509
TEST=none
Review URL: http://codereview.chromium.org/597012
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@38856 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'chrome/browser/views/tabs')
-rw-r--r-- | chrome/browser/views/tabs/browser_tab_strip_controller.cc | 8 | ||||
-rw-r--r-- | chrome/browser/views/tabs/browser_tab_strip_controller.h | 2 | ||||
-rw-r--r-- | chrome/browser/views/tabs/side_tab.cc | 127 | ||||
-rw-r--r-- | chrome/browser/views/tabs/side_tab.h | 35 | ||||
-rw-r--r-- | chrome/browser/views/tabs/side_tab_strip.cc | 22 | ||||
-rw-r--r-- | chrome/browser/views/tabs/side_tab_strip.h | 9 |
6 files changed, 181 insertions, 22 deletions
diff --git a/chrome/browser/views/tabs/browser_tab_strip_controller.cc b/chrome/browser/views/tabs/browser_tab_strip_controller.cc index 2b4706e..ddc147c 100644 --- a/chrome/browser/views/tabs/browser_tab_strip_controller.cc +++ b/chrome/browser/views/tabs/browser_tab_strip_controller.cc @@ -34,6 +34,14 @@ bool BrowserTabStripController::IsSelected(int index) const { return model_->selected_index() == index; } +void BrowserTabStripController::SelectTab(int index) { + model_->SelectTabContentsAt(index, true); +} + +void BrowserTabStripController::CloseTab(int index) { + model_->CloseTabContentsAt(index); +} + //////////////////////////////////////////////////////////////////////////////// // BrowserTabStripController, TabStripModelObserver implementation: diff --git a/chrome/browser/views/tabs/browser_tab_strip_controller.h b/chrome/browser/views/tabs/browser_tab_strip_controller.h index 4db5fde..d2d6a90 100644 --- a/chrome/browser/views/tabs/browser_tab_strip_controller.h +++ b/chrome/browser/views/tabs/browser_tab_strip_controller.h @@ -20,6 +20,8 @@ class BrowserTabStripController : public SideTabStripModel, virtual SkBitmap GetIcon(int index) const; virtual string16 GetTitle(int index) const; virtual bool IsSelected(int index) const; + virtual void SelectTab(int index); + virtual void CloseTab(int index); // TabStripModelObserver implementation: virtual void TabInsertedAt(TabContents* contents, int index, diff --git a/chrome/browser/views/tabs/side_tab.cc b/chrome/browser/views/tabs/side_tab.cc index e435bcb..8907a2e 100644 --- a/chrome/browser/views/tabs/side_tab.cc +++ b/chrome/browser/views/tabs/side_tab.cc @@ -5,50 +5,146 @@ #include "chrome/browser/views/tabs/side_tab.h" #include "app/gfx/canvas.h" +#include "app/gfx/skia_util.h" #include "app/resource_bundle.h" +#include "app/theme_provider.h" #include "base/string_util.h" +#include "grit/theme_resources.h" +#include "views/controls/button/image_button.h" namespace { const int kVerticalTabHeight = 27; -const int kTextPadding = 4; -const int kFavIconHeight = 16; +const int kIconSize = 16; +const int kIconTitleSpacing = 4; +const int kTitleCloseSpacing = 4; +const SkScalar kRoundRectRadius = 5; +const SkColor kTabBackgroundColor = SK_ColorWHITE; +const SkAlpha kBackgroundTabAlpha = 200; +static const int kHoverDurationMs = 900; }; // 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(SideTabModel* model) : model_(model) { +SideTab::SideTab(SideTabModel* model) + : model_(model), + close_button_(NULL) { 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); } 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_); + model_->CloseTab(this); +} + +//////////////////////////////////////////////////////////////////////////////// // SideTab, views::View overrides: void SideTab::Layout() { - // TODO(beng): + int icon_y; + int icon_x = icon_y = (height() - kIconSize) / 2; + icon_bounds_.SetRect(icon_x, icon_y, kIconSize, kIconSize); + + gfx::Size ps = close_button_->GetPreferredSize(); + int close_y = (height() - ps.height()) / 2; + close_button_->SetBounds(width() - ps.width() - close_y, close_y, ps.width(), + ps.height()); + + int title_y = (height() - font_->height()) / 2; + int title_x = icon_bounds_.right() + kIconTitleSpacing; + title_bounds_.SetRect(title_x, title_y, + close_button_->x() - kTitleCloseSpacing - title_x, + font_->height()); } void SideTab::Paint(gfx::Canvas* canvas) { - canvas->FillRectInt(model_->IsSelected(this) ? SK_ColorBLUE : SK_ColorRED, - 0, 0, width(), height()); - gfx::Rect text_rect = GetLocalBounds(false); - text_rect.Inset(kTextPadding, kTextPadding, kTextPadding, kTextPadding); + SkPaint paint; + paint.setColor(kTabBackgroundColor); + paint.setAntiAlias(true); + SkRect background_rect = gfx::RectToSkRect(GetLocalBounds(false)); + canvas->drawRoundRect(background_rect, kRoundRectRadius, kRoundRectRadius, + paint); + canvas->DrawBitmapInt(model_->GetIcon(this), 0, 0, kIconSize, kIconSize, + icon_bounds_.x(), icon_bounds_.y(), + icon_bounds_.width(), icon_bounds_.height(), false); canvas->DrawStringInt(UTF16ToWideHack(model_->GetTitle(this)), *font_, - SK_ColorBLACK, text_rect.x(), text_rect.y(), - text_rect.width(), text_rect.height()); + SK_ColorBLACK, title_bounds_.x(), title_bounds_.y(), + title_bounds_.width(), title_bounds_.height()); + + if (!model_->IsSelected(this) && + GetThemeProvider()->ShouldUseNativeFrame()) { + // Make sure un-selected tabs are somewhat transparent. + SkPaint paint; + + SkAlpha opacity = kBackgroundTabAlpha; + if (hover_animation_->IsAnimating()) + opacity = static_cast<SkAlpha>(hover_animation_->GetCurrentValue() * 255); + + paint.setColor(SkColorSetARGB(kBackgroundTabAlpha, 255, 255, 255)); + paint.setXfermodeMode(SkXfermode::kDstIn_Mode); + paint.setStyle(SkPaint::kFill_Style); + paint.setAntiAlias(true); + canvas->drawRoundRect(background_rect, kRoundRectRadius, kRoundRectRadius, + paint); + } } gfx::Size SideTab::GetPreferredSize() { - const int kTabHeight = std::max(font_->height() + 2 * kTextPadding, - kFavIconHeight + 2 * kTextPadding); - return gfx::Size(0, kTabHeight); + return gfx::Size(0, 27); +} + +void SideTab::OnMouseEntered(const views::MouseEvent& event) { + hover_animation_->SetTweenType(SlideAnimation::EASE_OUT); + hover_animation_->Show(); +} + +void SideTab::OnMouseExited(const views::MouseEvent& event) { + hover_animation_->SetTweenType(SlideAnimation::EASE_IN); + hover_animation_->Hide(); +} + +bool SideTab::OnMousePressed(const views::MouseEvent& event) { + if (event.IsOnlyLeftMouseButton()) + model_->SelectTab(this); + return true; } //////////////////////////////////////////////////////////////////////////////// @@ -60,6 +156,11 @@ void SideTab::InitClass() { 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); + initialized = true; } } diff --git a/chrome/browser/views/tabs/side_tab.h b/chrome/browser/views/tabs/side_tab.h index 767b649..787cd33 100644 --- a/chrome/browser/views/tabs/side_tab.h +++ b/chrome/browser/views/tabs/side_tab.h @@ -6,7 +6,9 @@ #define CHROME_BROWSER_VIEWS_TABS_SIDE_TAB_H_ #include "app/gfx/font.h" +#include "app/slide_animation.h" #include "third_party/skia/include/core/SkBitmap.h" +#include "views/controls/button/button.h" #include "views/view.h" class SideTab; @@ -17,17 +19,36 @@ class SideTabModel { virtual string16 GetTitle(SideTab* tab) const = 0; virtual SkBitmap GetIcon(SideTab* tab) const = 0; virtual bool IsSelected(SideTab* tab) const = 0; + + // Selects the tab. + virtual void SelectTab(SideTab* tab) = 0; + + // Closes the tab. + virtual void CloseTab(SideTab* tab) = 0; }; -class SideTab : public views::View { +class SideTab : public views::View, + public views::ButtonListener, + public AnimationDelegate { public: explicit SideTab(SideTabModel* model); 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::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); private: // Loads class-specific resources. @@ -35,7 +56,19 @@ class SideTab : public views::View { SideTabModel* model_; + 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_; 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 3ea8a3d..04bd44b 100644 --- a/chrome/browser/views/tabs/side_tab_strip.cc +++ b/chrome/browser/views/tabs/side_tab_strip.cc @@ -15,6 +15,7 @@ namespace { const int kVerticalTabSpacing = 2; const int kTabStripWidth = 127; +const int kTabStripInset = 3; } //////////////////////////////////////////////////////////////////////////////// @@ -79,6 +80,14 @@ bool SideTabStrip::IsSelected(SideTab* tab) const { return model_->IsSelected(GetIndexOfSideTab(tab)); } +void SideTabStrip::SelectTab(SideTab* tab) { + model_->SelectTab(GetIndexOfSideTab(tab)); +} + +void SideTabStrip::CloseTab(SideTab* tab) { + model_->CloseTab(GetIndexOfSideTab(tab)); +} + //////////////////////////////////////////////////////////////////////////////// // SideTabStrip, BaseTabStrip implementation: @@ -90,7 +99,7 @@ void SideTabStrip::SetBackgroundOffset(const gfx::Point& offset) { } bool SideTabStrip::IsPositionInWindowCaption(const gfx::Point& point) { - return true; + return GetViewForPoint(point) == this; } void SideTabStrip::SetDraggedTabBounds(int tab_index, @@ -116,18 +125,17 @@ TabStrip* SideTabStrip::AsTabStrip() { // SideTabStrip, views::View overrides: void SideTabStrip::Layout() { - int y = 0; + gfx::Rect layout_rect = GetLocalBounds(false); + layout_rect.Inset(kTabStripInset, kTabStripInset); + int y = layout_rect.y(); for (int c = GetChildViewCount(), i = 0; i < c; ++i) { views::View* child = GetChildViewAt(i); - child->SetBounds(0, y, width(), child->GetPreferredSize().height()); + child->SetBounds(layout_rect.x(), y, layout_rect.width(), + child->GetPreferredSize().height()); y = child->bounds().bottom() + kVerticalTabSpacing; } } -void SideTabStrip::Paint(gfx::Canvas* canvas) { - // canvas->FillRectInt(SK_ColorGREEN, 0, 0, width(), height()); -} - gfx::Size SideTabStrip::GetPreferredSize() { return gfx::Size(kTabStripWidth, 0); } diff --git a/chrome/browser/views/tabs/side_tab_strip.h b/chrome/browser/views/tabs/side_tab_strip.h index 4cde29f..61a0bc4 100644 --- a/chrome/browser/views/tabs/side_tab_strip.h +++ b/chrome/browser/views/tabs/side_tab_strip.h @@ -17,6 +17,12 @@ class SideTabStripModel { virtual SkBitmap GetIcon(int index) const = 0; virtual string16 GetTitle(int index) const = 0; virtual bool IsSelected(int index) const = 0; + + // Select the tab at the specified index in the model. + virtual void SelectTab(int index) = 0; + + // Closes the tab at the specified index in the model. + virtual void CloseTab(int index) = 0; }; class SideTabStrip : public BaseTabStrip, @@ -53,6 +59,8 @@ class SideTabStrip : public BaseTabStrip, virtual string16 GetTitle(SideTab* tab) const; virtual SkBitmap GetIcon(SideTab* tab) const; virtual bool IsSelected(SideTab* tab) const; + virtual void SelectTab(SideTab* tab); + virtual void CloseTab(SideTab* tab); // BaseTabStrip implementation: virtual int GetPreferredHeight(); @@ -67,7 +75,6 @@ class SideTabStrip : public BaseTabStrip, // views::View overrides: virtual void Layout(); - virtual void Paint(gfx::Canvas* canvas); virtual gfx::Size GetPreferredSize(); private: |