global_error_bubble_view.cc revision 2a99a7e74a7f215066514fe81d2bfa6639d9eddd
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) 75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/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" 155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ui/views/controls/button/text_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. 315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const int kTitleHorizontalPadding = 3; 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) 365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const int kLayoutBottomPadding = 2; 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, 625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) views::BubbleBorder::ArrowLocation location, 635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Browser* browser, 645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const base::WeakPtr<GlobalError>& error) 655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) : BubbleDelegateView(anchor_view, location), 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. 695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) set_anchor_insets( 705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) gfx::Insets(kAnchorVerticalInset, 0, kAnchorVerticalInset, 0)); 715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ui::ResourceBundle& rb = ui::ResourceBundle::GetSharedInstance(); 735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int resource_id = error_->GetBubbleViewIconResourceID(); 745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) scoped_ptr<views::ImageView> image_view(new views::ImageView()); 755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) image_view->SetImage(rb.GetImageNamed(resource_id).ToImageSkia()); 765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) string16 title_string(error_->GetBubbleViewTitle()); 785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) scoped_ptr<views::Label> title_label(new views::Label(title_string)); 795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) title_label->SetMultiLine(true); 805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) title_label->SetHorizontalAlignment(gfx::ALIGN_LEFT); 812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) title_label->SetFont(rb.GetFont(ui::ResourceBundle::MediumFont)); 825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) string16 message_string(error_->GetBubbleViewMessage()); 845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) views::Label* message_label = new views::Label(message_string); 855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) message_label->SetMultiLine(true); 865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) message_label->SizeToFit(kMaxBubbleViewWidth); 875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) message_label->SetHorizontalAlignment(gfx::ALIGN_LEFT); 885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) string16 accept_string(error_->GetBubbleViewAcceptButtonLabel()); 905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) scoped_ptr<views::TextButton> accept_button( 915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) new views::NativeTextButton(this, accept_string)); 925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) accept_button->SetIsDefault(true); 935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) accept_button->set_tag(TAG_ACCEPT_BUTTON); 945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) string16 cancel_string(error_->GetBubbleViewCancelButtonLabel()); 965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) scoped_ptr<views::TextButton> cancel_button; 975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!cancel_string.empty()) { 985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) cancel_button.reset(new views::NativeTextButton(this, cancel_string)); 995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) cancel_button->set_tag(TAG_CANCEL_BUTTON); 1005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) views::GridLayout* layout = new views::GridLayout(this); 1035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SetLayoutManager(layout); 1045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) layout->SetInsets(0, 0, kLayoutBottomPadding, 0); 1055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Top row, icon and title. 1075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) views::ColumnSet* cs = layout->AddColumnSet(0); 1085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) cs->AddColumn(views::GridLayout::LEADING, views::GridLayout::LEADING, 1095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 0, views::GridLayout::USE_PREF, 0, 0); 1105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) cs->AddPaddingColumn(0, kTitleHorizontalPadding); 1115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) cs->AddColumn(views::GridLayout::FILL, views::GridLayout::FILL, 1125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1, views::GridLayout::USE_PREF, 0, 0); 1135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Middle row, message label. 1155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) cs = layout->AddColumnSet(1); 1165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) cs->AddColumn(views::GridLayout::FILL, views::GridLayout::FILL, 1175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1, views::GridLayout::USE_PREF, 0, 0); 1185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Bottom row, accept and cancel button. 1205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) cs = layout->AddColumnSet(2); 1215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) cs->AddPaddingColumn(1, views::kRelatedControlHorizontalSpacing); 1225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) cs->AddColumn(views::GridLayout::TRAILING, views::GridLayout::LEADING, 1235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 0, views::GridLayout::USE_PREF, 0, 0); 1245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (cancel_button.get()) { 1255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) cs->AddPaddingColumn(0, views::kRelatedButtonHSpacing); 1265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) cs->AddColumn(views::GridLayout::TRAILING, views::GridLayout::LEADING, 1275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 0, views::GridLayout::USE_PREF, 0, 0); 1285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) layout->StartRow(1, 0); 1315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) layout->AddView(image_view.release()); 1325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) layout->AddView(title_label.release()); 1335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) layout->AddPaddingRow(0, views::kRelatedControlSmallVerticalSpacing); 1345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) layout->StartRow(1, 1); 1365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) layout->AddView(message_label); 1375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) layout->AddPaddingRow(0, views::kLabelToControlVerticalSpacing); 1385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) layout->StartRow(0, 2); 1405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) layout->AddView(accept_button.release()); 1415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (cancel_button.get()) 1425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) layout->AddView(cancel_button.release()); 1435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Adjust the message label size in case buttons are too long. 1455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) message_label->SizeToFit(layout->GetPreferredSize(this).width()); 1465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)GlobalErrorBubbleView::~GlobalErrorBubbleView() { 1495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void GlobalErrorBubbleView::ButtonPressed(views::Button* sender, 1525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const ui::Event& event) { 1535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (error_) { 1545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (sender->tag() == TAG_ACCEPT_BUTTON) 1555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) error_->BubbleViewAcceptButtonPressed(browser_); 1565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) else if (sender->tag() == TAG_CANCEL_BUTTON) 1575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) error_->BubbleViewCancelButtonPressed(browser_); 1585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) else 1595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) NOTREACHED(); 1605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) GetWidget()->Close(); 1625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void GlobalErrorBubbleView::WindowClosing() { 1655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (error_) 1665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) error_->BubbleViewDidClose(browser_); 1675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void GlobalErrorBubbleView::CloseBubbleView() { 1705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) GetWidget()->Close(); 1715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 172