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" 12f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)#include "chrome/browser/ui/views/toolbar/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 430f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)GlobalErrorBubbleViewBase* GlobalErrorBubbleViewBase::ShowStandardBubbleView( 445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Browser* browser, 450f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) const base::WeakPtr<GlobalErrorWithStandardBubble>& 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); 54a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) bubble_view->GetWidget()->Show(); 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, 640f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) const base::WeakPtr<GlobalErrorWithStandardBubble>& 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) 78a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) base::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); 825d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) title_label->SetFontList(rb.GetFontList(ui::ResourceBundle::MediumFont)); 835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 845d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) std::vector<base::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) 94a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) base::string16 accept_string(error_->GetBubbleViewAcceptButtonLabel()); 95c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) scoped_ptr<views::LabelButton> accept_button( 96c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) new views::LabelButton(this, accept_string)); 975d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) accept_button->SetStyle(views::Button::STYLE_BUTTON); 985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) accept_button->SetIsDefault(true); 995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) accept_button->set_tag(TAG_ACCEPT_BUTTON); 1005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 101a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) base::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)); 1055d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) cancel_button->SetStyle(views::Button::STYLE_BUTTON); 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()); 159c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch 160c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch // These bubbles show at times where activation is sporadic (like at startup, 161c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch // or a new window opening). Make sure the bubble doesn't disappear before the 162f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) // user sees it, if the bubble needs to be acknowledged. 163f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) set_close_on_deactivate(error_->ShouldCloseOnDeactivate()); 1645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)GlobalErrorBubbleView::~GlobalErrorBubbleView() { 1675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void GlobalErrorBubbleView::ButtonPressed(views::Button* sender, 1705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const ui::Event& event) { 1715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (error_) { 1725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (sender->tag() == TAG_ACCEPT_BUTTON) 1735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) error_->BubbleViewAcceptButtonPressed(browser_); 1745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) else if (sender->tag() == TAG_CANCEL_BUTTON) 1755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) error_->BubbleViewCancelButtonPressed(browser_); 1765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) else 1775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) NOTREACHED(); 1785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) GetWidget()->Close(); 1805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void GlobalErrorBubbleView::WindowClosing() { 1835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (error_) 1845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) error_->BubbleViewDidClose(browser_); 1855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void GlobalErrorBubbleView::CloseBubbleView() { 1885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) GetWidget()->Close(); 1895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 190