global_error_bubble_view.cc revision 868fa2fe829687343ffae624259930155e16dbd8
15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Copyright (c) 2012 The Chromium Authors. All rights reserved. 25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be 35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// found in the LICENSE file. 45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 55821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/ui/views/global_error_bubble_view.h" 65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 7868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "base/strings/utf_string_conversions.h" 85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/ui/global_error/global_error.h" 95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/ui/global_error/global_error_service.h" 105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/ui/global_error/global_error_service_factory.h" 115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/ui/views/frame/browser_view.h" 125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/ui/views/toolbar_view.h" 135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ui/base/resource/resource_bundle.h" 145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ui/gfx/image/image.h" 15c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "ui/views/controls/button/label_button.h" 165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ui/views/controls/image_view.h" 175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ui/views/controls/label.h" 185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ui/views/layout/grid_layout.h" 195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ui/views/layout/layout_constants.h" 205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace { 225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)enum { 245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) TAG_ACCEPT_BUTTON = 1, 255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) TAG_CANCEL_BUTTON, 265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}; 275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const int kMaxBubbleViewWidth = 262; 295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// The horizontal padding between the title and the icon. 31c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)const int kTitleHorizontalPadding = 5; 325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// The vertical inset of the wrench bubble anchor from the wrench menu button. 345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const int kAnchorVerticalInset = 5; 355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 36c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)const int kBubblePadding = 6; 375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} // namespace 395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// GlobalErrorBubbleViewBase --------------------------------------------------- 415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// static 435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)GlobalErrorBubbleViewBase* GlobalErrorBubbleViewBase::ShowBubbleView( 445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Browser* browser, 455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const base::WeakPtr<GlobalError>& error) { 465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) BrowserView* browser_view = BrowserView::GetBrowserViewForBrowser(browser); 475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) views::View* wrench_button = browser_view->toolbar()->app_menu(); 485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) GlobalErrorBubbleView* bubble_view = 495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) new GlobalErrorBubbleView(wrench_button, 505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) views::BubbleBorder::TOP_RIGHT, 515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) browser, 525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) error); 535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) views::BubbleDelegateView::CreateBubble(bubble_view); 545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bubble_view->StartFade(true); 555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return bubble_view; 565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// GlobalErrorBubbleView ------------------------------------------------------- 595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)GlobalErrorBubbleView::GlobalErrorBubbleView( 615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) views::View* anchor_view, 62c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) views::BubbleBorder::Arrow arrow, 635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Browser* browser, 645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const base::WeakPtr<GlobalError>& error) 65c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) : BubbleDelegateView(anchor_view, arrow), 665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) browser_(browser), 675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) error_(error) { 685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Compensate for built-in vertical padding in the anchor view's image. 69c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) set_anchor_view_insets( 705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) gfx::Insets(kAnchorVerticalInset, 0, kAnchorVerticalInset, 0)); 715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ui::ResourceBundle& rb = ui::ResourceBundle::GetSharedInstance(); 7390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) gfx::Image image = error_->GetBubbleViewIcon(); 7490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) CHECK(!image.IsEmpty()); 755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) scoped_ptr<views::ImageView> image_view(new views::ImageView()); 7690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) image_view->SetImage(image.ToImageSkia()); 775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) string16 title_string(error_->GetBubbleViewTitle()); 795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) scoped_ptr<views::Label> title_label(new views::Label(title_string)); 805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) title_label->SetMultiLine(true); 815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) title_label->SetHorizontalAlignment(gfx::ALIGN_LEFT); 822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) title_label->SetFont(rb.GetFont(ui::ResourceBundle::MediumFont)); 835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 84c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) std::vector<string16> message_strings(error_->GetBubbleViewMessages()); 85c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) std::vector<views::Label*> message_labels; 86c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) for (size_t i = 0; i < message_strings.size(); ++i) { 87c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) views::Label* message_label = new views::Label(message_strings[i]); 88c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) message_label->SetMultiLine(true); 89c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) message_label->SizeToFit(kMaxBubbleViewWidth); 90c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) message_label->SetHorizontalAlignment(gfx::ALIGN_LEFT); 91c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) message_labels.push_back(message_label); 92c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) } 935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) string16 accept_string(error_->GetBubbleViewAcceptButtonLabel()); 95c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) scoped_ptr<views::LabelButton> accept_button( 96c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) new views::LabelButton(this, accept_string)); 97c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) accept_button->SetStyle(views::Button::STYLE_NATIVE_TEXTBUTTON); 985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) accept_button->SetIsDefault(true); 995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) accept_button->set_tag(TAG_ACCEPT_BUTTON); 1005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) string16 cancel_string(error_->GetBubbleViewCancelButtonLabel()); 102c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) scoped_ptr<views::LabelButton> cancel_button; 1035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!cancel_string.empty()) { 104c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) cancel_button.reset(new views::LabelButton(this, cancel_string)); 105c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) cancel_button->SetStyle(views::Button::STYLE_NATIVE_TEXTBUTTON); 1065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) cancel_button->set_tag(TAG_CANCEL_BUTTON); 1075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) views::GridLayout* layout = new views::GridLayout(this); 1105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SetLayoutManager(layout); 111c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) layout->SetInsets(kBubblePadding, kBubblePadding, 112c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) kBubblePadding, kBubblePadding); 1135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Top row, icon and title. 1155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) views::ColumnSet* cs = layout->AddColumnSet(0); 1165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) cs->AddColumn(views::GridLayout::LEADING, views::GridLayout::LEADING, 1175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 0, views::GridLayout::USE_PREF, 0, 0); 1185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) cs->AddPaddingColumn(0, kTitleHorizontalPadding); 1195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) cs->AddColumn(views::GridLayout::FILL, views::GridLayout::FILL, 1205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1, views::GridLayout::USE_PREF, 0, 0); 1215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 122c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) // Middle rows, message labels. 1235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) cs = layout->AddColumnSet(1); 1245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) cs->AddColumn(views::GridLayout::FILL, views::GridLayout::FILL, 1255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1, views::GridLayout::USE_PREF, 0, 0); 1265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Bottom row, accept and cancel button. 1285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) cs = layout->AddColumnSet(2); 1295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) cs->AddPaddingColumn(1, views::kRelatedControlHorizontalSpacing); 1305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) cs->AddColumn(views::GridLayout::TRAILING, views::GridLayout::LEADING, 1315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 0, views::GridLayout::USE_PREF, 0, 0); 1325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (cancel_button.get()) { 1335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) cs->AddPaddingColumn(0, views::kRelatedButtonHSpacing); 1345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) cs->AddColumn(views::GridLayout::TRAILING, views::GridLayout::LEADING, 1355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 0, views::GridLayout::USE_PREF, 0, 0); 1365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) layout->StartRow(1, 0); 1395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) layout->AddView(image_view.release()); 1405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) layout->AddView(title_label.release()); 141c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) layout->AddPaddingRow(0, views::kRelatedControlVerticalSpacing); 1425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 143c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) for (size_t i = 0; i < message_labels.size(); ++i) { 144c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) layout->StartRow(1, 1); 145c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) layout->AddView(message_labels[i]); 146c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) if (i < message_labels.size() - 1) 147c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) layout->AddPaddingRow(0, views::kRelatedControlVerticalSpacing); 148c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) } 1495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) layout->AddPaddingRow(0, views::kLabelToControlVerticalSpacing); 1505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) layout->StartRow(0, 2); 1525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) layout->AddView(accept_button.release()); 1535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (cancel_button.get()) 1545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) layout->AddView(cancel_button.release()); 1555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Adjust the message label size in case buttons are too long. 157c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) for (size_t i = 0; i < message_labels.size(); ++i) 158c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) message_labels[i]->SizeToFit(layout->GetPreferredSize(this).width()); 1595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)GlobalErrorBubbleView::~GlobalErrorBubbleView() { 1625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void GlobalErrorBubbleView::ButtonPressed(views::Button* sender, 1655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const ui::Event& event) { 1665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (error_) { 1675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (sender->tag() == TAG_ACCEPT_BUTTON) 1685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) error_->BubbleViewAcceptButtonPressed(browser_); 1695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) else if (sender->tag() == TAG_CANCEL_BUTTON) 1705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) error_->BubbleViewCancelButtonPressed(browser_); 1715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) else 1725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) NOTREACHED(); 1735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) GetWidget()->Close(); 1755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void GlobalErrorBubbleView::WindowClosing() { 1785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (error_) 1795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) error_->BubbleViewDidClose(browser_); 1805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void GlobalErrorBubbleView::CloseBubbleView() { 1835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) GetWidget()->Close(); 1845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 185