1 // Copyright (c) 2011 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #include "chrome/browser/ui/gtk/sad_tab_gtk.h"
6
7 #include <string>
8
9 #include "chrome/browser/google/google_util.h"
10 #include "chrome/browser/ui/gtk/gtk_chrome_link_button.h"
11 #include "chrome/browser/ui/gtk/gtk_util.h"
12 #include "chrome/common/url_constants.h"
13 #include "content/browser/tab_contents/tab_contents.h"
14 #include "grit/generated_resources.h"
15 #include "grit/locale_settings.h"
16 #include "grit/theme_resources.h"
17 #include "ui/base/l10n/l10n_util.h"
18 #include "ui/base/resource/resource_bundle.h"
19
20 namespace {
21
22 // Background color of the content (a grayish blue) for a crashed tab.
23 const GdkColor kCrashedBackgroundColor = GDK_COLOR_RGB(35, 48, 64);
24
25 // Background color of the content (a grayish purple) for a killed
26 // tab. TODO(gspencer): update this for the "real" color when the UI
27 // team provides one. See http://crosbug.com/10711
28 const GdkColor kKilledBackgroundColor = GDK_COLOR_RGB(57, 48, 88);
29
30 // Construct a centered GtkLabel with a white foreground.
31 // |format| is a printf-style format containing a %s;
32 // |str| is substituted into the format.
MakeWhiteMarkupLabel(const char * format,const std::string & str)33 GtkWidget* MakeWhiteMarkupLabel(const char* format, const std::string& str) {
34 GtkWidget* label = gtk_label_new(NULL);
35 char* markup = g_markup_printf_escaped(format, str.c_str());
36 gtk_label_set_markup(GTK_LABEL(label), markup);
37 g_free(markup);
38
39 // Center align and justify it.
40 gtk_misc_set_alignment(GTK_MISC(label), 0.5, 0.5);
41 gtk_label_set_justify(GTK_LABEL(label), GTK_JUSTIFY_CENTER);
42
43 // Set text to white.
44 GdkColor white = gtk_util::kGdkWhite;
45 gtk_widget_modify_fg(label, GTK_STATE_NORMAL, &white);
46
47 return label;
48 }
49
50 } // namespace
51
SadTabGtk(TabContents * tab_contents,Kind kind)52 SadTabGtk::SadTabGtk(TabContents* tab_contents, Kind kind)
53 : tab_contents_(tab_contents),
54 kind_(kind) {
55 DCHECK(tab_contents_);
56
57 // Use an event box to get the background painting correctly.
58 event_box_.Own(gtk_event_box_new());
59 gtk_widget_modify_bg(event_box_.get(), GTK_STATE_NORMAL,
60 kind == CRASHED ?
61 &kCrashedBackgroundColor :
62 &kKilledBackgroundColor);
63 // Allow ourselves to be resized arbitrarily small.
64 gtk_widget_set_size_request(event_box_.get(), 0, 0);
65
66 GtkWidget* centering = gtk_alignment_new(0.5, 0.5, 0.0, 0.0);
67 gtk_container_add(GTK_CONTAINER(event_box_.get()), centering);
68
69 // Use a vertical box to contain icon, title, message and link.
70 GtkWidget* vbox = gtk_vbox_new(FALSE, 0);
71 gtk_container_add(GTK_CONTAINER(centering), vbox);
72
73 // Add center-aligned image.
74 GtkWidget* image = gtk_image_new_from_pixbuf(
75 ResourceBundle::GetSharedInstance().GetPixbufNamed(kind == CRASHED ?
76 IDR_SAD_TAB :
77 IDR_KILLED_TAB));
78 gtk_misc_set_alignment(GTK_MISC(image), 0.5, 0.5);
79 gtk_box_pack_start(GTK_BOX(vbox), image, FALSE, FALSE, 0);
80
81 // Add spacer between image and title.
82 GtkWidget* spacer = gtk_label_new(NULL);
83 gtk_label_set_markup(GTK_LABEL(spacer), "<span size=\"larger\"> </span>");
84 gtk_box_pack_start(GTK_BOX(vbox), spacer, FALSE, FALSE, 0);
85
86 // Add center-aligned title.
87 GtkWidget* title = MakeWhiteMarkupLabel(
88 "<span size=\"larger\" style=\"normal\"><b>%s</b></span>",
89 l10n_util::GetStringUTF8(kind == CRASHED ?
90 IDS_SAD_TAB_TITLE :
91 IDS_KILLED_TAB_TITLE));
92 gtk_box_pack_start(GTK_BOX(vbox), title, FALSE, FALSE, 0);
93
94 // Add spacer between title and message.
95 spacer = gtk_label_new(" ");
96 gtk_box_pack_start(GTK_BOX(vbox), spacer, FALSE, FALSE, 0);
97
98 // Add center-aligned message.
99 GtkWidget* message = MakeWhiteMarkupLabel(
100 "<span style=\"normal\">%s</span>",
101 l10n_util::GetStringUTF8(kind == CRASHED ?
102 IDS_SAD_TAB_MESSAGE :
103 IDS_KILLED_TAB_MESSAGE));
104 gtk_label_set_line_wrap(GTK_LABEL(message), TRUE);
105 gtk_box_pack_start(GTK_BOX(vbox), message, FALSE, FALSE, 0);
106
107 // Add spacer between message and link.
108 spacer = gtk_label_new(" ");
109 gtk_box_pack_start(GTK_BOX(vbox), spacer, FALSE, FALSE, 0);
110
111 if (tab_contents_ != NULL) {
112 // Add the learn-more link and center-align it in an alignment.
113 GtkWidget* link = gtk_chrome_link_button_new(
114 l10n_util::GetStringUTF8(IDS_LEARN_MORE).c_str());
115 gtk_chrome_link_button_set_normal_color(GTK_CHROME_LINK_BUTTON(link),
116 >k_util::kGdkWhite);
117 g_signal_connect(link, "clicked", G_CALLBACK(OnLinkButtonClickThunk), this);
118 GtkWidget* link_alignment = gtk_alignment_new(0.5, 0.5, 0.0, 0.0);
119 gtk_container_add(GTK_CONTAINER(link_alignment), link);
120 gtk_box_pack_start(GTK_BOX(vbox), link_alignment, FALSE, FALSE, 0);
121 }
122
123 gtk_widget_show_all(event_box_.get());
124 }
125
~SadTabGtk()126 SadTabGtk::~SadTabGtk() {
127 event_box_.Destroy();
128 }
129
OnLinkButtonClick(GtkWidget * sender)130 void SadTabGtk::OnLinkButtonClick(GtkWidget* sender) {
131 if (tab_contents_ != NULL) {
132 GURL help_url =
133 google_util::AppendGoogleLocaleParam(GURL(
134 kind_ == CRASHED ?
135 chrome::kCrashReasonURL :
136 chrome::kKillReasonURL));
137 tab_contents_->OpenURL(help_url, GURL(), CURRENT_TAB, PageTransition::LINK);
138 }
139 }
140