summaryrefslogtreecommitdiffstats
path: root/chrome/browser
diff options
context:
space:
mode:
authorkuan@chromium.org <kuan@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2009-11-18 19:24:48 +0000
committerkuan@chromium.org <kuan@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2009-11-18 19:24:48 +0000
commitdfc8db9d8df51c51f89de2044695ce0993f80228 (patch)
tree3898e261b28252b3f7c332513250c49108616015 /chrome/browser
parent34812353c4b42a30e17da31b081c8c049d4fd28c (diff)
downloadchromium_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.cc240
-rw-r--r--chrome/browser/gtk/sad_tab_gtk.h41
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);
};