diff options
author | kuan@chromium.org <kuan@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2009-11-18 19:24:48 +0000 |
---|---|---|
committer | kuan@chromium.org <kuan@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2009-11-18 19:24:48 +0000 |
commit | dfc8db9d8df51c51f89de2044695ce0993f80228 (patch) | |
tree | 3898e261b28252b3f7c332513250c49108616015 /chrome/browser | |
parent | 34812353c4b42a30e17da31b081c8c049d4fd28c (diff) | |
download | chromium_src-dfc8db9d8df51c51f89de2044695ce0993f80228.zip chromium_src-dfc8db9d8df51c51f89de2044695ce0993f80228.tar.gz chromium_src-dfc8db9d8df51c51f89de2044695ce0993f80228.tar.bz2 |
This cl reimplements the entire "Aw Snap" page to use gtk widgets to layout and draw the icon, title, message and add new "Learn more" link; the old implementation used skia to do simple drawing, but couldn't be used for link, hence the rewrite.
BUG=27211
TEST=Verify that "Aw Snap" page is displayed correctly, and new "Learn more" link shows up centralized beneath the message, and when window is resized bi-directionally, especially smaller to force wrapping of message.
Review URL: http://codereview.chromium.org/385145
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@32365 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'chrome/browser')
-rw-r--r-- | chrome/browser/gtk/sad_tab_gtk.cc | 240 | ||||
-rw-r--r-- | chrome/browser/gtk/sad_tab_gtk.h | 41 |
2 files changed, 156 insertions, 125 deletions
diff --git a/chrome/browser/gtk/sad_tab_gtk.cc b/chrome/browser/gtk/sad_tab_gtk.cc index 4adfeec..b805c1d 100644 --- a/chrome/browser/gtk/sad_tab_gtk.cc +++ b/chrome/browser/gtk/sad_tab_gtk.cc @@ -6,16 +6,15 @@ #include <string> -#include "app/gfx/canvas_paint.h" -#include "app/gfx/font.h" +#include "app/gfx/gtk_util.h" #include "app/l10n_util.h" #include "app/resource_bundle.h" -#include "base/gfx/size.h" #include "base/lazy_instance.h" +#include "chrome/browser/browser_list.h" +#include "chrome/browser/gtk/gtk_chrome_link_button.h" #include "grit/generated_resources.h" +#include "grit/locale_settings.h" #include "grit/theme_resources.h" -#include "skia/ext/skia_utils.h" -#include "third_party/skia/include/effects/SkGradientShader.h" namespace { @@ -25,128 +24,157 @@ const int kSadTabOffset = -64; 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); +const int kMessageLinkSpacing = 15; +const int kTabHorzMargin = 13; +const double kBackgroundColorTop[3] = { + 35.0 / 255.0, 48.0 / 255.0, 64.0 / 255.0 }; +const double kBackgroundColorBottom[3] = { + 35.0 / 255.0, 48.0 / 255.0, 64.0 / 255.0 }; 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; + ResourceBundle::GetSharedInstance().GetPixbufNamed(IDR_SAD_TAB)), + title(l10n_util::GetStringUTF8(IDS_SAD_TAB_TITLE)), + message(l10n_util::GetStringUTF8(IDS_SAD_TAB_MESSAGE)), + learn_more_url(l10n_util::GetStringUTF8(IDS_CRASH_REASON_URL)) {} + + const GdkPixbuf* sad_tab_bitmap; + std::string title; + std::string message; + std::string learn_more_url; }; base::LazyInstance<SadTabGtkConstants> g_sad_tab_constants(base::LINKER_INITIALIZED); +GtkWidget* MakeWhiteMarkupLabel(const char* format, const std::string& str) { + GtkWidget* label = gtk_label_new(NULL); + char* markup = g_markup_printf_escaped(format, str.c_str()); + gtk_label_set_markup(GTK_LABEL(label), markup); + g_free(markup); + + // Center align and justify it. + gtk_misc_set_alignment(GTK_MISC(label), 0.5, 0.5); + gtk_label_set_justify(GTK_LABEL(label), GTK_JUSTIFY_CENTER); + + // Set text to white. + GdkColor white = gfx::kGdkWhite; + gtk_widget_modify_fg(label, GTK_STATE_NORMAL, &white); + + return label; +} + } // 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); + height_(0) { + // Use an event box to get the background painting correctly. + event_box_.Own(gtk_event_box_new()); + gtk_widget_set_app_paintable(event_box_.get(), TRUE); + g_signal_connect(event_box_.get(), "expose-event", + G_CALLBACK(OnBackgroundExposeThunk), this); + // Listen to signal for resizing of widget. + g_signal_connect(event_box_.get(), "size-allocate", + G_CALLBACK(OnSizeAllocateThunk), this); + + // Use an alignment to set the top and horizontal paddings. The padding will + // be set later when we receive expose-event which gives us the width and + // height of the widget. + top_padding_ = gtk_alignment_new(0.0, 0.0, 1.0, 1.0); + gtk_container_add(GTK_CONTAINER(event_box_.get()), top_padding_); + + // Use a vertical box to contain icon, title, message and link. + GtkWidget* vbox = gtk_vbox_new(FALSE, 0); + gtk_container_add(GTK_CONTAINER(top_padding_), vbox); + + const SadTabGtkConstants& sad_tab_constants = g_sad_tab_constants.Get(); + + // Add center-aligned image. + GtkWidget* image = gtk_image_new_from_pixbuf( + const_cast<GdkPixbuf*>(sad_tab_constants.sad_tab_bitmap)); + gtk_misc_set_alignment(GTK_MISC(image), 0.5, 0.5); + gtk_box_pack_start(GTK_BOX(vbox), image, FALSE, FALSE, kIconTitleSpacing); + + // Add center-aligned title. + GtkWidget* title = MakeWhiteMarkupLabel( + "<span size=\"larger\" style=\"normal\"><b>%s</b></span>", + sad_tab_constants.title); + gtk_box_pack_start(GTK_BOX(vbox), title, FALSE, FALSE, kTitleMessageSpacing); + + // Add center-aligned message. + message_ = MakeWhiteMarkupLabel("<span style=\"normal\">%s</span>", + sad_tab_constants.message); + gtk_label_set_line_wrap(GTK_LABEL(message_), TRUE); + gtk_box_pack_start(GTK_BOX(vbox), message_, FALSE, FALSE, + kMessageLinkSpacing); + + // Add the learn-more link and center-align it in an alignment. + GtkWidget* link = gtk_chrome_link_button_new( + l10n_util::GetStringUTF8(IDS_LEARN_MORE).c_str()); + g_signal_connect(link, "clicked", G_CALLBACK(OnLinkButtonClick), + const_cast<char*>(sad_tab_constants.learn_more_url.c_str())); + GtkWidget* link_alignment = gtk_alignment_new(0.5, 0.5, 0.0, 0.0); + gtk_container_add(GTK_CONTAINER(link_alignment), link); + gtk_box_pack_start(GTK_BOX(vbox), link_alignment, FALSE, FALSE, 0); + + gtk_widget_show_all(event_box_.get()); } SadTabGtk::~SadTabGtk() { - widget_.Destroy(); + event_box_.Destroy(); } -// static -gboolean SadTabGtk::OnExposeThunk(GtkWidget* widget, - GdkEventExpose* event, - const SadTabGtk* sad_tab) { - return sad_tab->OnExpose(widget, event); +gboolean SadTabGtk::OnBackgroundExpose( + GtkWidget* widget, GdkEventExpose* event) { + // Clip to our damage rect. + cairo_t* cr = gdk_cairo_create(GDK_DRAWABLE(event->window)); + cairo_rectangle(cr, event->area.x, event->area.y, + event->area.width, event->area.height); + cairo_clip(cr); + + // Draw the gradient background. + int half_width = width_ / 2; + cairo_pattern_t* pattern = cairo_pattern_create_linear( + half_width, 0, half_width, height_); + cairo_pattern_add_color_stop_rgb( + pattern, 0.0, + kBackgroundColorTop[0], kBackgroundColorTop[1], kBackgroundColorTop[2]); + cairo_pattern_add_color_stop_rgb( + pattern, 1.0, + kBackgroundColorBottom[0], kBackgroundColorBottom[1], + kBackgroundColorBottom[2]); + cairo_set_source(cr, pattern); + cairo_paint(cr); + cairo_pattern_destroy(pattern); + + cairo_destroy(cr); + + return FALSE; // Propagate expose event to children. } -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_, - height_ - message_y_, - gfx::Canvas::TEXT_ALIGN_CENTER | - gfx::Canvas::MULTI_LINE | - gfx::Canvas::TEXT_VALIGN_TOP); - - return TRUE; +void SadTabGtk::OnSizeAllocate(GtkWidget* widget, GtkAllocation* allocation) { + // Only readjust top and horizontal paddings if height of widget has changed. + if (allocation->height != 0 && allocation->height != height_) { + height_ = allocation->height; + const SadTabGtkConstants& sad_tab_constants = g_sad_tab_constants.Get(); + int icon_height = gdk_pixbuf_get_height(sad_tab_constants.sad_tab_bitmap); + int icon_y = ((height_ - icon_height) / 2) + kSadTabOffset; + gtk_alignment_set_padding(GTK_ALIGNMENT(top_padding_), std::max(icon_y, 0), + 0, kTabHorzMargin, kTabHorzMargin); + } + + // Only readjust width for message if width of widget has changed. + if (allocation->width != 0 && allocation->width != width_) { + width_ = allocation->width; + // Set width for wrappable message. + gtk_widget_set_size_request(message_, width_ - (kTabHorzMargin * 2), -1); + } } // 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; +void SadTabGtk::OnLinkButtonClick(GtkWidget* button, const char* url) { + BrowserList::GetLastActive()->OpenURL(GURL(url), GURL(), CURRENT_TAB, + PageTransition::LINK); } diff --git a/chrome/browser/gtk/sad_tab_gtk.h b/chrome/browser/gtk/sad_tab_gtk.h index aed2454..cc140f8 100644 --- a/chrome/browser/gtk/sad_tab_gtk.h +++ b/chrome/browser/gtk/sad_tab_gtk.h @@ -16,34 +16,37 @@ class SadTabGtk { SadTabGtk(); ~SadTabGtk(); - GtkWidget* widget() { return widget_.get(); } + GtkWidget* widget() { return event_box_.get(); } private: - // expose-event handler that redraws the SadTabGtk. - static gboolean OnExposeThunk(GtkWidget* widget, - GdkEventExpose* event, - const SadTabGtk* sad_tab); + // expose-event handler that draws the gradient background of the SadTabGtk. + static gboolean OnBackgroundExposeThunk(GtkWidget* widget, + GdkEventExpose* event, + SadTabGtk* sad_tab) { + return sad_tab->OnBackgroundExpose(widget, event); + } - gboolean OnExpose(GtkWidget* widget, GdkEventExpose* event) const; + gboolean OnBackgroundExpose(GtkWidget* widget, GdkEventExpose* event); - // configure-event handler that gets the new bounds of the SadTabGtk. - static gboolean OnConfigureThunk(GtkWidget* widget, - GdkEventConfigure* event, - SadTabGtk* sad_tab); + // size-allocate handler to adjust dimensions for children widgets. + static void OnSizeAllocateThunk(GtkWidget* widget, + GtkAllocation* allocation, + SadTabGtk* sad_tab) { + sad_tab->OnSizeAllocate(widget, allocation); + } - gboolean OnConfigure(GtkWidget* widget, GdkEventConfigure* event); + void OnSizeAllocate(GtkWidget* widget, GtkAllocation* allocation); - // Track the view's width and height from configure-event signals. + // click-event handler that opens the url of the clicked link. + static void OnLinkButtonClick(GtkWidget* button, const char* url); + + // Track the view's width and height from size-allocate signals. int width_; int height_; - // Regions within the display for different components, set on a - // configure-event. These are relative to the bounds of the widget. - gfx::Rect icon_bounds_; - int title_y_; - int message_y_; - - OwnedWidgetGtk widget_; + OwnedWidgetGtk event_box_; + GtkWidget* top_padding_; + GtkWidget* message_; DISALLOW_COPY_AND_ASSIGN(SadTabGtk); }; |