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