// Copyright (c) 2009 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/gtk/sad_tab_gtk.h" #include #include "app/gfx/canvas_paint.h" #include "app/gfx/font.h" #include "app/l10n_util.h" #include "app/resource_bundle.h" #include "base/gfx/size.h" #include "base/lazy_instance.h" #include "grit/generated_resources.h" #include "grit/theme_resources.h" #include "skia/ext/skia_utils.h" #include "third_party/skia/include/effects/SkGradientShader.h" namespace { // The y offset from the center at which to paint the icon. const int kSadTabOffset = -64; // The spacing between the icon and the title. const int kIconTitleSpacing = 20; // The spacing between the title and the message. const int kTitleMessageSpacing = 15; const SkColor kTitleTextColor = SK_ColorWHITE; const SkColor kMessageTextColor = SK_ColorWHITE; const SkColor kBackgroundColor = SkColorSetRGB(35, 48, 64); const SkColor kBackgroundEndColor = SkColorSetRGB(35, 48, 64); struct SadTabGtkConstants { SadTabGtkConstants() : sad_tab_bitmap( ResourceBundle::GetSharedInstance().GetBitmapNamed(IDR_SAD_TAB)), title_font( ResourceBundle::GetSharedInstance().GetFont( ResourceBundle::BaseFont).DeriveFont(2, gfx::Font::BOLD)), message_font( ResourceBundle::GetSharedInstance().GetFont( ResourceBundle::BaseFont).DeriveFont(1)), title(l10n_util::GetString(IDS_SAD_TAB_TITLE)), message(l10n_util::GetString(IDS_SAD_TAB_MESSAGE)) {} const SkBitmap* sad_tab_bitmap; gfx::Font title_font; gfx::Font message_font; std::wstring title; std::wstring message; }; base::LazyInstance g_sad_tab_constants(base::LINKER_INITIALIZED); } // namespace SadTabGtk::SadTabGtk() : width_(0), height_(0), title_y_(0), message_y_(0), widget_(gtk_drawing_area_new()) { gtk_widget_set_double_buffered(widget_.get(), FALSE); g_signal_connect(widget_.get(), "expose-event", G_CALLBACK(OnExposeThunk), this); g_signal_connect(widget_.get(), "configure-event", G_CALLBACK(OnConfigureThunk), this); } SadTabGtk::~SadTabGtk() { widget_.Destroy(); } // static gboolean SadTabGtk::OnExposeThunk(GtkWidget* widget, GdkEventExpose* event, const SadTabGtk* sad_tab) { return sad_tab->OnExpose(widget, event); } gboolean SadTabGtk::OnExpose(GtkWidget* widget, GdkEventExpose* event) const { gfx::CanvasPaint canvas(event); SkPaint paint; paint.setShader(skia::CreateGradientShader(0, height_, kBackgroundColor, kBackgroundEndColor))->safeUnref(); paint.setStyle(SkPaint::kFill_Style); canvas.drawRectCoords(0, 0, SkIntToScalar(width_), SkIntToScalar(height_), paint); const SadTabGtkConstants& sad_tab_constants = g_sad_tab_constants.Get(); // Paint the sad tab icon. canvas.DrawBitmapInt(*sad_tab_constants.sad_tab_bitmap, icon_bounds_.x(), icon_bounds_.y()); // Paint the "Aw, snap!" canvas.DrawStringInt(sad_tab_constants.title, sad_tab_constants.title_font, kTitleTextColor, 0, title_y_, width_, sad_tab_constants.title_font.height(), gfx::Canvas::TEXT_ALIGN_CENTER); // Paint the explanatory message. canvas.DrawStringInt( sad_tab_constants.message, sad_tab_constants.message_font, kMessageTextColor, 0, message_y_, width_, 99999, // Let the height be large, and we'll clip if needed. gfx::Canvas::TEXT_ALIGN_CENTER | gfx::Canvas::MULTI_LINE | gfx::Canvas::TEXT_VALIGN_TOP); return TRUE; } // static gboolean SadTabGtk::OnConfigureThunk(GtkWidget* widget, GdkEventConfigure* event, SadTabGtk* sad_tab) { return sad_tab->OnConfigure(widget, event); } gboolean SadTabGtk::OnConfigure(GtkWidget* widget, GdkEventConfigure* event) { const SadTabGtkConstants& sad_tab_constants = g_sad_tab_constants.Get(); width_ = event->width; height_= event->height; int icon_width = sad_tab_constants.sad_tab_bitmap->width(); int icon_height = sad_tab_constants.sad_tab_bitmap->height(); int icon_x = (event->width - icon_width) / 2; int icon_y = ((event->height - icon_height) / 2) + kSadTabOffset; icon_bounds_.SetRect(icon_x, icon_y, icon_width, icon_height); title_y_ = icon_bounds_.bottom() + kIconTitleSpacing; int title_height = sad_tab_constants.title_font.height(); message_y_ = title_y_ + title_height + kTitleMessageSpacing; return TRUE; }