From 06912d47ab85ab0b8a67ed5af9cef9d5fa382415 Mon Sep 17 00:00:00 2001 From: "jhawkins@chromium.org" Date: Tue, 12 May 2009 21:17:42 +0000 Subject: Update the Linux tabstrip code to handle themes. Review URL: http://codereview.chromium.org/115260 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@15897 0039d316-1c4b-4281-b951-d872f2087c98 --- chrome/browser/gtk/tabs/tab_renderer_gtk.cc | 152 ++++++++++++++++++---------- chrome/browser/gtk/tabs/tab_renderer_gtk.h | 8 +- chrome/browser/gtk/tabs/tab_strip_gtk.cc | 7 -- chrome/browser/gtk/tabs/tab_strip_gtk.h | 3 - 4 files changed, 106 insertions(+), 64 deletions(-) (limited to 'chrome/browser/gtk/tabs') diff --git a/chrome/browser/gtk/tabs/tab_renderer_gtk.cc b/chrome/browser/gtk/tabs/tab_renderer_gtk.cc index 6350203..e840290 100644 --- a/chrome/browser/gtk/tabs/tab_renderer_gtk.cc +++ b/chrome/browser/gtk/tabs/tab_renderer_gtk.cc @@ -7,6 +7,7 @@ #include "app/l10n_util.h" #include "app/resource_bundle.h" #include "chrome/browser/browser.h" +#include "chrome/browser/browser_theme_provider.h" #include "chrome/browser/profile.h" #include "chrome/browser/tab_contents/tab_contents.h" #include "grit/generated_resources.h" @@ -23,6 +24,7 @@ const int kFavIconTitleSpacing = 4; const int kTitleCloseButtonSpacing = 5; const int kStandardTitleWidth = 175; const int kFavIconSize = 16; +const int kDropShadowOffset = 2; const int kSelectedTitleColor = SK_ColorBLACK; const int kUnselectedTitleColor = SkColorSetRGB(64, 64, 64); @@ -81,7 +83,7 @@ void InitializeLoadingAnimationData( bool TabRendererGtk::initialized_ = false; TabRendererGtk::TabImage TabRendererGtk::tab_active_ = {0}; TabRendererGtk::TabImage TabRendererGtk::tab_inactive_ = {0}; -TabRendererGtk::TabImage TabRendererGtk::tab_inactive_otr_ = {0}; +TabRendererGtk::TabImage TabRendererGtk::tab_alpha = {0}; TabRendererGtk::TabImage TabRendererGtk::tab_hover_ = {0}; ChromeFont* TabRendererGtk::title_font_ = NULL; int TabRendererGtk::title_font_height_ = 0; @@ -168,6 +170,8 @@ void TabRendererGtk::UpdateData(TabContents* contents, bool loading_only) { // we display the throbber. data_.loading = contents->is_loading(); data_.show_icon = contents->ShouldDisplayFavIcon(); + + theme_provider_ = contents->profile()->GetThemeProvider(); } void TabRendererGtk::UpdateFromModel() { @@ -225,6 +229,9 @@ int TabRendererGtk::GetContentHeight() { void TabRendererGtk::LoadTabImages() { 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_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); @@ -237,18 +244,6 @@ void TabRendererGtk::LoadTabImages() { tab_inactive_.l_width = tab_inactive_.image_l->width(); tab_inactive_.r_width = tab_inactive_.image_r->width(); - // TODO: Generate these images http://crbug.com/11679 - tab_hover_.image_l = rb.GetBitmapNamed(IDR_TAB_ACTIVE_LEFT); - tab_hover_.image_c = rb.GetBitmapNamed(IDR_TAB_ACTIVE_CENTER); - tab_hover_.image_r = rb.GetBitmapNamed(IDR_TAB_ACTIVE_RIGHT); - - tab_inactive_otr_.image_l = rb.GetBitmapNamed(IDR_TAB_INACTIVE_LEFT); - tab_inactive_otr_.image_c = rb.GetBitmapNamed(IDR_TAB_INACTIVE_CENTER); - tab_inactive_otr_.image_r = rb.GetBitmapNamed(IDR_TAB_INACTIVE_RIGHT); - - // tab_[hover,inactive_otr] width are not used and are initialized to 0 - // during static initialization. - close_button_width_ = rb.GetBitmapNamed(IDR_TAB_CLOSE)->width(); close_button_height_ = rb.GetBitmapNamed(IDR_TAB_CLOSE)->height(); @@ -289,7 +284,7 @@ void TabRendererGtk::AnimationEnded(const Animation* animation) { // TabRendererGtk, private: void TabRendererGtk::Paint(GdkEventExpose* event) { - ChromeCanvasPaint canvas(event); + ChromeCanvasPaint canvas(event, false); if (canvas.isEmpty()) return; @@ -420,58 +415,111 @@ void TabRendererGtk::PaintTabBackground(ChromeCanvasPaint* canvas) { } else { // Draw our hover state. Animation* animation = hover_animation_.get(); + + PaintInactiveTabBackground(canvas); if (animation->GetCurrentValue() > 0) { - PaintHoverTabBackground(canvas, - animation->GetCurrentValue() * kHoverOpacity); - } else { - PaintInactiveTabBackground(canvas); + SkRect bounds; + // TODO(jhawkins): This will only work for the first tab, because + // saveLayerAlpha only uses bounds as the size and not the location. In + // our situation, canvas spans the entire tabstrip, so saving the layer + // at (0,0)x(w,h) will always save the first tab. + bounds.set(0, 0, + SkIntToScalar(width()), SkIntToScalar(height())); + canvas->saveLayerAlpha(&bounds, + static_cast(animation->GetCurrentValue() * kHoverOpacity * 0xff), + SkCanvas::kARGB_ClipLayer_SaveFlag); + canvas->drawARGB(0, 255, 255, 255, SkPorterDuff::kClear_Mode); + PaintActiveTabBackground(canvas); + canvas->restore(); } } } void TabRendererGtk::PaintInactiveTabBackground(ChromeCanvasPaint* canvas) { bool is_otr = data_.off_the_record; - const TabImage& image = is_otr ? tab_inactive_otr_ : tab_inactive_; - canvas->DrawBitmapInt(*image.image_l, bounds_.x(), bounds_.y()); - canvas->TileImageInt(*image.image_c, - bounds_.x() + tab_inactive_.l_width, bounds_.y(), - width() - tab_inactive_.l_width - tab_inactive_.r_width, - height()); - canvas->DrawBitmapInt(*image.image_r, - bounds_.x() + width() - tab_inactive_.r_width, - bounds_.y()); -} - -void TabRendererGtk::PaintHoverTabBackground(ChromeCanvasPaint* canvas, - double opacity) { - bool is_otr = data_.off_the_record; - const TabImage& image = is_otr ? tab_inactive_otr_ : tab_inactive_; - - SkBitmap left = skia::ImageOperations::CreateBlendedBitmap( - *image.image_l, *tab_hover_.image_l, opacity); - SkBitmap center = skia::ImageOperations::CreateBlendedBitmap( - *image.image_c, *tab_hover_.image_c, opacity); - SkBitmap right = skia::ImageOperations::CreateBlendedBitmap( - *image.image_r, *tab_hover_.image_r, opacity); - - canvas->DrawBitmapInt(left, bounds_.x(), bounds_.y()); - canvas->TileImageInt(center, bounds_.x() + tab_active_.l_width, bounds_.y(), - bounds_.width() - tab_active_.l_width - tab_active_.r_width, - bounds_.height()); - canvas->DrawBitmapInt(right, - bounds_.x() + bounds_.width() - tab_active_.r_width, bounds_.y()); + // The tab image needs to be lined up with the background image + // so that it feels partially transparent. + int offset = 1; + int offset_y = 20; + + int tab_id = is_otr ? + IDR_THEME_TAB_BACKGROUND_INCOGNITO : IDR_THEME_TAB_BACKGROUND; + + SkBitmap* tab_bg = theme_provider_->GetBitmapNamed(tab_id); + + // Draw left edge. + SkBitmap tab_l = skia::ImageOperations::CreateTiledBitmap( + *tab_bg, offset, offset_y, + tab_active_.l_width, height()); + SkBitmap theme_l = skia::ImageOperations::CreateMaskedBitmap( + tab_l, *tab_alpha.image_l); + canvas->DrawBitmapInt(theme_l, + 0, 0, theme_l.width(), theme_l.height() - 1, + bounds_.x(), bounds_.y(), theme_l.width(), theme_l.height() - 1, + false); + + // Draw right edge. + SkBitmap tab_r = skia::ImageOperations::CreateTiledBitmap( + *tab_bg, + offset + width() - tab_active_.r_width, offset_y, + tab_active_.r_width, height()); + SkBitmap theme_r = skia::ImageOperations::CreateMaskedBitmap( + tab_r, *tab_alpha.image_r); + canvas->DrawBitmapInt(theme_r, + 0, 0, theme_r.width(), theme_r.height() - 1, + bounds_.x() + width() - theme_r.width(), bounds_.y(), + theme_r.width(), theme_r.height() - 1, + false); + + // Draw center. + canvas->TileImageInt(*tab_bg, + offset + tab_active_.l_width, kDropShadowOffset + offset_y, + bounds_.x() + tab_active_.l_width, bounds_.y() + 2, + width() - tab_active_.l_width - tab_active_.r_width, height() - 3); + + canvas->DrawBitmapInt(*tab_inactive_.image_l, bounds_.x(), bounds_.y()); + canvas->TileImageInt(*tab_inactive_.image_c, tab_inactive_.l_width, 0, + bounds_.x() + width() - tab_inactive_.l_width - tab_inactive_.r_width, + bounds_.y() + height()); + canvas->DrawBitmapInt(*tab_inactive_.image_r, + bounds_.x() + width() - tab_inactive_.r_width, bounds_.y()); } void TabRendererGtk::PaintActiveTabBackground(ChromeCanvasPaint* canvas) { + int offset = 1; + + SkBitmap* tab_bg = theme_provider_->GetBitmapNamed(IDR_THEME_TOOLBAR); + + // Draw left edge. + SkBitmap tab_l = skia::ImageOperations::CreateTiledBitmap( + *tab_bg, offset, 0, tab_active_.l_width, height()); + SkBitmap theme_l = skia::ImageOperations::CreateMaskedBitmap( + tab_l, *tab_alpha.image_l); + canvas->DrawBitmapInt(theme_l, bounds_.x(), bounds_.y()); + + // Draw right edge. + SkBitmap tab_r = skia::ImageOperations::CreateTiledBitmap( + *tab_bg, + offset + width() - tab_active_.r_width, 0, + tab_active_.r_width, height()); + SkBitmap theme_r = skia::ImageOperations::CreateMaskedBitmap( + tab_r, *tab_alpha.image_r); + canvas->DrawBitmapInt(theme_r, + bounds_.x() + width() - tab_active_.r_width, bounds_.y()); + + // Draw center. + canvas->TileImageInt(*tab_bg, + offset + tab_active_.l_width, 2, + bounds_.x() + tab_active_.l_width, bounds_.y() + 2, + width() - tab_active_.l_width - tab_active_.r_width, height() - 2); + canvas->DrawBitmapInt(*tab_active_.image_l, bounds_.x(), bounds_.y()); canvas->TileImageInt(*tab_active_.image_c, - bounds_.x() + tab_active_.l_width, bounds_.y(), - width() - tab_active_.l_width - tab_active_.r_width, - height()); + bounds_.x() + tab_active_.l_width, bounds_.y(), + width() - tab_active_.l_width - tab_active_.r_width, height()); canvas->DrawBitmapInt(*tab_active_.image_r, - bounds_.x() + width() - tab_active_.r_width, - bounds_.y()); + bounds_.x() + width() - tab_active_.r_width, bounds_.y()); } void TabRendererGtk::PaintLoadingAnimation(ChromeCanvasPaint* canvas) { diff --git a/chrome/browser/gtk/tabs/tab_renderer_gtk.h b/chrome/browser/gtk/tabs/tab_renderer_gtk.h index 74f730d..a2f4721 100644 --- a/chrome/browser/gtk/tabs/tab_renderer_gtk.h +++ b/chrome/browser/gtk/tabs/tab_renderer_gtk.h @@ -21,6 +21,7 @@ class Size; } // namespace gfx class TabContents; +class ThemeProvider; class TabRendererGtk : public AnimationDelegate { public: @@ -173,7 +174,6 @@ class TabRendererGtk : public AnimationDelegate { void PaintTabBackground(ChromeCanvasPaint* canvas); void PaintInactiveTabBackground(ChromeCanvasPaint* canvas); void PaintActiveTabBackground(ChromeCanvasPaint* canvas); - void PaintHoverTabBackground(ChromeCanvasPaint* canvas, double opacity); void PaintLoadingAnimation(ChromeCanvasPaint* canvas); // Returns the number of favicon-size elements that can fit in the tab's @@ -204,7 +204,7 @@ class TabRendererGtk : public AnimationDelegate { static TabImage tab_active_; static TabImage tab_inactive_; - static TabImage tab_inactive_otr_; + static TabImage tab_alpha; static TabImage tab_hover_; static ChromeFont* title_font_; @@ -246,6 +246,10 @@ class TabRendererGtk : public AnimationDelegate { // Contains the loading animation state. LoadingAnimation loading_animation_; + // TODO(jhawkins): If the theme is changed after the tab is created, we'll + // still render the old theme for this tab. + ThemeProvider* theme_provider_; + DISALLOW_COPY_AND_ASSIGN(TabRendererGtk); }; diff --git a/chrome/browser/gtk/tabs/tab_strip_gtk.cc b/chrome/browser/gtk/tabs/tab_strip_gtk.cc index 15d1950..2c75bed 100644 --- a/chrome/browser/gtk/tabs/tab_strip_gtk.cc +++ b/chrome/browser/gtk/tabs/tab_strip_gtk.cc @@ -993,8 +993,6 @@ gboolean TabStripGtk::OnExpose(GtkWidget* widget, GdkEventExpose* event, event->area.height = tabstrip->bounds_.height(); gdk_region_union_with_rect(event->region, &event->area); - tabstrip->PaintBackground(event); - // Paint the New Tab button. gtk_container_propagate_expose(GTK_CONTAINER(tabstrip->tabstrip_.get()), tabstrip->newtab_button_.get()->widget(), event); @@ -1058,11 +1056,6 @@ void TabStripGtk::OnNewTabClicked(GtkWidget* widget, TabStripGtk* tabstrip) { tabstrip->model_->delegate()->AddBlankTab(true); } -void TabStripGtk::PaintBackground(GdkEventExpose* event) { - ChromeCanvasPaint canvas(event); - canvas.TileImageInt(*background, 0, 0, bounds_.width(), bounds_.height()); -} - void TabStripGtk::SetTabBounds(TabGtk* tab, const gfx::Rect& bounds) { tab->SetBounds(bounds); gtk_fixed_move(GTK_FIXED(tabstrip_.get()), tab->widget(), diff --git a/chrome/browser/gtk/tabs/tab_strip_gtk.h b/chrome/browser/gtk/tabs/tab_strip_gtk.h index 0e0739c..d79ed11 100644 --- a/chrome/browser/gtk/tabs/tab_strip_gtk.h +++ b/chrome/browser/gtk/tabs/tab_strip_gtk.h @@ -112,9 +112,6 @@ class TabStripGtk : public TabStripModelObserver, // Handles the clicked signal from the new tab button. static void OnNewTabClicked(GtkWidget* widget, TabStripGtk* tabstrip); - // Renders the tabstrip background. - void PaintBackground(GdkEventExpose* event); - // Sets the bounds of the tab and moves the tab widget to those bounds. void SetTabBounds(TabGtk* tab, const gfx::Rect& bounds); -- cgit v1.1