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/views/sad_tab_view.h" 6 7 #include "base/utf_string_conversions.h" 8 #include "chrome/browser/google/google_util.h" 9 #include "chrome/common/url_constants.h" 10 #include "content/browser/tab_contents/tab_contents.h" 11 #include "content/browser/tab_contents/tab_contents_delegate.h" 12 #include "grit/generated_resources.h" 13 #include "grit/locale_settings.h" 14 #include "grit/theme_resources.h" 15 #include "third_party/skia/include/effects/SkGradientShader.h" 16 #include "ui/base/l10n/l10n_util.h" 17 #include "ui/base/resource/resource_bundle.h" 18 #include "ui/gfx/canvas.h" 19 #include "ui/gfx/canvas_skia.h" 20 #include "ui/gfx/size.h" 21 #include "ui/gfx/skia_util.h" 22 23 static const int kSadTabOffset = -64; 24 static const int kIconTitleSpacing = 20; 25 static const int kTitleMessageSpacing = 15; 26 static const int kMessageBottomMargin = 20; 27 static const float kMessageSize = 0.65f; 28 static const SkColor kTitleColor = SK_ColorWHITE; 29 static const SkColor kMessageColor = SK_ColorWHITE; 30 static const SkColor kLinkColor = SK_ColorWHITE; 31 static const SkColor kCrashBackgroundColor = SkColorSetRGB(35, 48, 64); 32 static const SkColor kCrashBackgroundEndColor = SkColorSetRGB(35, 48, 64); 33 // TODO(gspencer): update these colors when the UI team has picked 34 // official versions. See http://crosbug.com/10711. 35 static const SkColor kKillBackgroundColor = SkColorSetRGB(57, 48, 88); 36 static const SkColor kKillBackgroundEndColor = SkColorSetRGB(57, 48, 88); 37 38 // Font size correction. 39 #if defined(CROS_FONTS_USING_BCI) 40 static const int kTitleFontSizeDelta = 1; 41 static const int kMessageFontSizeDelta = 0; 42 #else 43 static const int kTitleFontSizeDelta = 2; 44 static const int kMessageFontSizeDelta = 1; 45 #endif 46 47 // static 48 SkBitmap* SadTabView::sad_tab_bitmap_ = NULL; 49 gfx::Font* SadTabView::title_font_ = NULL; 50 gfx::Font* SadTabView::message_font_ = NULL; 51 std::wstring SadTabView::title_; 52 std::wstring SadTabView::message_; 53 int SadTabView::title_width_; 54 55 SadTabView::SadTabView(TabContents* tab_contents, Kind kind) 56 : tab_contents_(tab_contents), 57 learn_more_link_(NULL), 58 kind_(kind) { 59 DCHECK(tab_contents); 60 61 InitClass(kind); 62 63 if (tab_contents != NULL) { 64 learn_more_link_ = 65 new views::Link(UTF16ToWide(l10n_util::GetStringUTF16(IDS_LEARN_MORE))); 66 learn_more_link_->SetFont(*message_font_); 67 learn_more_link_->SetNormalColor(kLinkColor); 68 learn_more_link_->SetController(this); 69 AddChildView(learn_more_link_); 70 } 71 } 72 73 SadTabView::~SadTabView() {} 74 75 void SadTabView::OnPaint(gfx::Canvas* canvas) { 76 SkPaint paint; 77 SkSafeUnref(paint.setShader( 78 gfx::CreateGradientShader( 79 0, 80 height(), 81 kind_ == CRASHED ? kCrashBackgroundColor : kKillBackgroundColor, 82 kind_ == CRASHED ? 83 kCrashBackgroundEndColor : kKillBackgroundEndColor))); 84 paint.setStyle(SkPaint::kFill_Style); 85 canvas->AsCanvasSkia()->drawRectCoords( 86 0, 0, SkIntToScalar(width()), SkIntToScalar(height()), paint); 87 88 canvas->DrawBitmapInt(*sad_tab_bitmap_, icon_bounds_.x(), icon_bounds_.y()); 89 90 canvas->DrawStringInt(WideToUTF16Hack(title_), *title_font_, kTitleColor, 91 title_bounds_.x(), title_bounds_.y(), 92 title_bounds_.width(), title_bounds_.height(), 93 gfx::Canvas::TEXT_ALIGN_CENTER); 94 95 canvas->DrawStringInt(WideToUTF16Hack(message_), *message_font_, 96 kMessageColor, message_bounds_.x(), message_bounds_.y(), 97 message_bounds_.width(), message_bounds_.height(), 98 gfx::Canvas::MULTI_LINE); 99 100 if (learn_more_link_ != NULL) 101 learn_more_link_->SetBounds(link_bounds_.x(), link_bounds_.y(), 102 link_bounds_.width(), link_bounds_.height()); 103 } 104 105 void SadTabView::Layout() { 106 int icon_width = sad_tab_bitmap_->width(); 107 int icon_height = sad_tab_bitmap_->height(); 108 int icon_x = (width() - icon_width) / 2; 109 int icon_y = ((height() - icon_height) / 2) + kSadTabOffset; 110 icon_bounds_.SetRect(icon_x, icon_y, icon_width, icon_height); 111 112 int title_x = (width() - title_width_) / 2; 113 int title_y = icon_bounds_.bottom() + kIconTitleSpacing; 114 int title_height = title_font_->GetHeight(); 115 title_bounds_.SetRect(title_x, title_y, title_width_, title_height); 116 117 gfx::CanvasSkia cc(0, 0, true); 118 int message_width = static_cast<int>(width() * kMessageSize); 119 int message_height = 0; 120 cc.SizeStringInt(WideToUTF16Hack(message_), *message_font_, &message_width, 121 &message_height, gfx::Canvas::MULTI_LINE); 122 int message_x = (width() - message_width) / 2; 123 int message_y = title_bounds_.bottom() + kTitleMessageSpacing; 124 message_bounds_.SetRect(message_x, message_y, message_width, message_height); 125 126 if (learn_more_link_ != NULL) { 127 gfx::Size sz = learn_more_link_->GetPreferredSize(); 128 gfx::Insets insets = learn_more_link_->GetInsets(); 129 link_bounds_.SetRect((width() - sz.width()) / 2, 130 message_bounds_.bottom() + kTitleMessageSpacing - 131 insets.top(), sz.width(), sz.height()); 132 } 133 } 134 135 void SadTabView::LinkActivated(views::Link* source, int event_flags) { 136 if (tab_contents_ != NULL && source == learn_more_link_) { 137 GURL help_url = 138 google_util::AppendGoogleLocaleParam(GURL(kind_ == CRASHED ? 139 chrome::kCrashReasonURL : 140 chrome::kKillReasonURL)); 141 tab_contents_->OpenURL(help_url, GURL(), CURRENT_TAB, PageTransition::LINK); 142 } 143 } 144 145 // static 146 void SadTabView::InitClass(Kind kind) { 147 static bool initialized = false; 148 if (!initialized) { 149 ResourceBundle& rb = ResourceBundle::GetSharedInstance(); 150 title_font_ = new gfx::Font( 151 rb.GetFont(ResourceBundle::BaseFont).DeriveFont(kTitleFontSizeDelta, 152 gfx::Font::BOLD)); 153 message_font_ = new gfx::Font( 154 rb.GetFont(ResourceBundle::BaseFont).DeriveFont(kMessageFontSizeDelta)); 155 sad_tab_bitmap_ = rb.GetBitmapNamed( 156 kind == CRASHED ? IDR_SAD_TAB : IDR_KILLED_TAB); 157 158 title_ = UTF16ToWide(l10n_util::GetStringUTF16( 159 kind == CRASHED ? IDS_SAD_TAB_TITLE : IDS_KILLED_TAB_TITLE)); 160 title_width_ = title_font_->GetStringWidth(WideToUTF16Hack(title_)); 161 message_ = UTF16ToWide(l10n_util::GetStringUTF16( 162 kind == CRASHED ? IDS_SAD_TAB_MESSAGE : IDS_KILLED_TAB_MESSAGE)); 163 164 initialized = true; 165 } 166 } 167