global_error_bubble_view.cc revision a1401311d1ab56c4ed0a474bd38c108f75cb0cd9
183e168294456ca2f02db421a635f7d5f5d023966kmillikin@chromium.org// Copyright (c) 2012 The Chromium Authors. All rights reserved.
23484964a86451e86dcf04be9bd8c0d76ee04f081rossberg@chromium.org// Use of this source code is governed by a BSD-style license that can be
33484964a86451e86dcf04be9bd8c0d76ee04f081rossberg@chromium.org// found in the LICENSE file.
443d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen
5304cc33f8259ef467e8e3c79f448d0bae0e8cd85yangguo@chromium.org#include "chrome/browser/ui/views/global_error_bubble_view.h"
6304cc33f8259ef467e8e3c79f448d0bae0e8cd85yangguo@chromium.org
743d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen#include "base/strings/utf_string_conversions.h"
871affb54842da76b24f0bb3184e9f0960523f89dkasperl@chromium.org#include "chrome/browser/ui/global_error/global_error.h"
971affb54842da76b24f0bb3184e9f0960523f89dkasperl@chromium.org#include "chrome/browser/ui/global_error/global_error_service.h"
1043d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen#include "chrome/browser/ui/global_error/global_error_service_factory.h"
1143d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen#include "chrome/browser/ui/views/frame/browser_view.h"
12304cc33f8259ef467e8e3c79f448d0bae0e8cd85yangguo@chromium.org#include "chrome/browser/ui/views/toolbar/toolbar_view.h"
13304cc33f8259ef467e8e3c79f448d0bae0e8cd85yangguo@chromium.org#include "ui/base/resource/resource_bundle.h"
1443d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen#include "ui/gfx/image/image.h"
1555ee80713569ab0324fc8dcedcb5518501daa6a6ricow@chromium.org#include "ui/views/controls/button/label_button.h"
16afbdadc5f06365a7889e7c1c1fdb7dbf596cce68machenbach@chromium.org#include "ui/views/controls/image_view.h"
1743d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen#include "ui/views/controls/label.h"
1855ee80713569ab0324fc8dcedcb5518501daa6a6ricow@chromium.org#include "ui/views/layout/grid_layout.h"
19afbdadc5f06365a7889e7c1c1fdb7dbf596cce68machenbach@chromium.org#include "ui/views/layout/layout_constants.h"
2043d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen
2143d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansennamespace {
2243d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen
23afbdadc5f06365a7889e7c1c1fdb7dbf596cce68machenbach@chromium.orgenum {
24304cc33f8259ef467e8e3c79f448d0bae0e8cd85yangguo@chromium.org  TAG_ACCEPT_BUTTON = 1,
25304cc33f8259ef467e8e3c79f448d0bae0e8cd85yangguo@chromium.org  TAG_CANCEL_BUTTON,
2643d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen};
2743d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen
28afbdadc5f06365a7889e7c1c1fdb7dbf596cce68machenbach@chromium.orgconst int kMaxBubbleViewWidth = 262;
29b912362e2b2e704d09faac4290e027fd744bf587kasperl@chromium.org
30afbdadc5f06365a7889e7c1c1fdb7dbf596cce68machenbach@chromium.org// The horizontal padding between the title and the icon.
31b912362e2b2e704d09faac4290e027fd744bf587kasperl@chromium.orgconst int kTitleHorizontalPadding = 5;
32afbdadc5f06365a7889e7c1c1fdb7dbf596cce68machenbach@chromium.org
3343d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen// The vertical inset of the wrench bubble anchor from the wrench menu button.
34a6bbcc801f63c451f814d6da77a1a48fba3d36c6yangguo@chromium.orgconst int kAnchorVerticalInset = 5;
35afbdadc5f06365a7889e7c1c1fdb7dbf596cce68machenbach@chromium.org
3655ee80713569ab0324fc8dcedcb5518501daa6a6ricow@chromium.orgconst int kBubblePadding = 6;
37b912362e2b2e704d09faac4290e027fd744bf587kasperl@chromium.org
3843d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen}  // namespace
39a6bbcc801f63c451f814d6da77a1a48fba3d36c6yangguo@chromium.org
40afbdadc5f06365a7889e7c1c1fdb7dbf596cce68machenbach@chromium.org// GlobalErrorBubbleViewBase ---------------------------------------------------
41a6bbcc801f63c451f814d6da77a1a48fba3d36c6yangguo@chromium.org
42a6bbcc801f63c451f814d6da77a1a48fba3d36c6yangguo@chromium.org// static
43a6bbcc801f63c451f814d6da77a1a48fba3d36c6yangguo@chromium.orgGlobalErrorBubbleViewBase* GlobalErrorBubbleViewBase::ShowStandardBubbleView(
4443d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen    Browser* browser,
4543d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen    const base::WeakPtr<GlobalErrorWithStandardBubble>& error) {
4683e168294456ca2f02db421a635f7d5f5d023966kmillikin@chromium.org  BrowserView* browser_view = BrowserView::GetBrowserViewForBrowser(browser);
4743d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  views::View* wrench_button = browser_view->toolbar()->app_menu();
4843d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  GlobalErrorBubbleView* bubble_view =
4943d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen      new GlobalErrorBubbleView(wrench_button,
5043d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen                                views::BubbleBorder::TOP_RIGHT,
5143d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen                                browser,
52afbdadc5f06365a7889e7c1c1fdb7dbf596cce68machenbach@chromium.org                                error);
5355ee80713569ab0324fc8dcedcb5518501daa6a6ricow@chromium.org  views::BubbleDelegateView::CreateBubble(bubble_view);
5455ee80713569ab0324fc8dcedcb5518501daa6a6ricow@chromium.org  bubble_view->GetWidget()->Show();
5543d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  return bubble_view;
5643d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen}
5743d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen
58afbdadc5f06365a7889e7c1c1fdb7dbf596cce68machenbach@chromium.org// GlobalErrorBubbleView -------------------------------------------------------
59e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org
60a6bbcc801f63c451f814d6da77a1a48fba3d36c6yangguo@chromium.orgGlobalErrorBubbleView::GlobalErrorBubbleView(
61a6bbcc801f63c451f814d6da77a1a48fba3d36c6yangguo@chromium.org    views::View* anchor_view,
62a6bbcc801f63c451f814d6da77a1a48fba3d36c6yangguo@chromium.org    views::BubbleBorder::Arrow arrow,
63a6bbcc801f63c451f814d6da77a1a48fba3d36c6yangguo@chromium.org    Browser* browser,
6483e168294456ca2f02db421a635f7d5f5d023966kmillikin@chromium.org    const base::WeakPtr<GlobalErrorWithStandardBubble>& error)
6543d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen    : BubbleDelegateView(anchor_view, arrow),
6643d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen      browser_(browser),
67afbdadc5f06365a7889e7c1c1fdb7dbf596cce68machenbach@chromium.org      error_(error) {
68304cc33f8259ef467e8e3c79f448d0bae0e8cd85yangguo@chromium.org  // Compensate for built-in vertical padding in the anchor view's image.
69e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org  set_anchor_view_insets(
7055ee80713569ab0324fc8dcedcb5518501daa6a6ricow@chromium.org      gfx::Insets(kAnchorVerticalInset, 0, kAnchorVerticalInset, 0));
71304cc33f8259ef467e8e3c79f448d0bae0e8cd85yangguo@chromium.org
7255ee80713569ab0324fc8dcedcb5518501daa6a6ricow@chromium.org  ui::ResourceBundle& rb = ui::ResourceBundle::GetSharedInstance();
7343d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  gfx::Image image = error_->GetBubbleViewIcon();
7443d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  CHECK(!image.IsEmpty());
7543d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  scoped_ptr<views::ImageView> image_view(new views::ImageView());
76afbdadc5f06365a7889e7c1c1fdb7dbf596cce68machenbach@chromium.org  image_view->SetImage(image.ToImageSkia());
77afbdadc5f06365a7889e7c1c1fdb7dbf596cce68machenbach@chromium.org
78afbdadc5f06365a7889e7c1c1fdb7dbf596cce68machenbach@chromium.org  base::string16 title_string(error_->GetBubbleViewTitle());
79afbdadc5f06365a7889e7c1c1fdb7dbf596cce68machenbach@chromium.org  scoped_ptr<views::Label> title_label(new views::Label(title_string));
80afbdadc5f06365a7889e7c1c1fdb7dbf596cce68machenbach@chromium.org  title_label->SetMultiLine(true);
81afbdadc5f06365a7889e7c1c1fdb7dbf596cce68machenbach@chromium.org  title_label->SetHorizontalAlignment(gfx::ALIGN_LEFT);
82afbdadc5f06365a7889e7c1c1fdb7dbf596cce68machenbach@chromium.org  title_label->SetFontList(rb.GetFontList(ui::ResourceBundle::MediumFont));
835a8ca6c70c6fc9716f18f6223c98d1fef5752cf6kasperl@chromium.org
8443d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  std::vector<base::string16> message_strings(error_->GetBubbleViewMessages());
8555ee80713569ab0324fc8dcedcb5518501daa6a6ricow@chromium.org  std::vector<views::Label*> message_labels;
8643d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  for (size_t i = 0; i < message_strings.size(); ++i) {
8743d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen    views::Label* message_label = new views::Label(message_strings[i]);
88304cc33f8259ef467e8e3c79f448d0bae0e8cd85yangguo@chromium.org    message_label->SetMultiLine(true);
89304cc33f8259ef467e8e3c79f448d0bae0e8cd85yangguo@chromium.org    message_label->SizeToFit(kMaxBubbleViewWidth);
90304cc33f8259ef467e8e3c79f448d0bae0e8cd85yangguo@chromium.org    message_label->SetHorizontalAlignment(gfx::ALIGN_LEFT);
91304cc33f8259ef467e8e3c79f448d0bae0e8cd85yangguo@chromium.org    message_labels.push_back(message_label);
92304cc33f8259ef467e8e3c79f448d0bae0e8cd85yangguo@chromium.org  }
93304cc33f8259ef467e8e3c79f448d0bae0e8cd85yangguo@chromium.org
94304cc33f8259ef467e8e3c79f448d0bae0e8cd85yangguo@chromium.org  base::string16 accept_string(error_->GetBubbleViewAcceptButtonLabel());
95304cc33f8259ef467e8e3c79f448d0bae0e8cd85yangguo@chromium.org  scoped_ptr<views::LabelButton> accept_button(
96304cc33f8259ef467e8e3c79f448d0bae0e8cd85yangguo@chromium.org      new views::LabelButton(this, accept_string));
97304cc33f8259ef467e8e3c79f448d0bae0e8cd85yangguo@chromium.org  accept_button->SetStyle(views::Button::STYLE_BUTTON);
98304cc33f8259ef467e8e3c79f448d0bae0e8cd85yangguo@chromium.org  accept_button->SetIsDefault(true);
99304cc33f8259ef467e8e3c79f448d0bae0e8cd85yangguo@chromium.org  accept_button->set_tag(TAG_ACCEPT_BUTTON);
100304cc33f8259ef467e8e3c79f448d0bae0e8cd85yangguo@chromium.org
101304cc33f8259ef467e8e3c79f448d0bae0e8cd85yangguo@chromium.org  base::string16 cancel_string(error_->GetBubbleViewCancelButtonLabel());
102afbdadc5f06365a7889e7c1c1fdb7dbf596cce68machenbach@chromium.org  scoped_ptr<views::LabelButton> cancel_button;
103afbdadc5f06365a7889e7c1c1fdb7dbf596cce68machenbach@chromium.org  if (!cancel_string.empty()) {
104304cc33f8259ef467e8e3c79f448d0bae0e8cd85yangguo@chromium.org    cancel_button.reset(new views::LabelButton(this, cancel_string));
105afbdadc5f06365a7889e7c1c1fdb7dbf596cce68machenbach@chromium.org    cancel_button->SetStyle(views::Button::STYLE_BUTTON);
106304cc33f8259ef467e8e3c79f448d0bae0e8cd85yangguo@chromium.org    cancel_button->set_tag(TAG_CANCEL_BUTTON);
107304cc33f8259ef467e8e3c79f448d0bae0e8cd85yangguo@chromium.org  }
108304cc33f8259ef467e8e3c79f448d0bae0e8cd85yangguo@chromium.org
109304cc33f8259ef467e8e3c79f448d0bae0e8cd85yangguo@chromium.org  views::GridLayout* layout = new views::GridLayout(this);
110304cc33f8259ef467e8e3c79f448d0bae0e8cd85yangguo@chromium.org  SetLayoutManager(layout);
111304cc33f8259ef467e8e3c79f448d0bae0e8cd85yangguo@chromium.org  layout->SetInsets(kBubblePadding, kBubblePadding,
112750145ab1b720c97adf2b548cc8fbd28c8b8e06dulan@chromium.org                    kBubblePadding, kBubblePadding);
113750145ab1b720c97adf2b548cc8fbd28c8b8e06dulan@chromium.org
114304cc33f8259ef467e8e3c79f448d0bae0e8cd85yangguo@chromium.org  // Top row, icon and title.
115304cc33f8259ef467e8e3c79f448d0bae0e8cd85yangguo@chromium.org  views::ColumnSet* cs = layout->AddColumnSet(0);
116304cc33f8259ef467e8e3c79f448d0bae0e8cd85yangguo@chromium.org  cs->AddColumn(views::GridLayout::LEADING, views::GridLayout::LEADING,
117750145ab1b720c97adf2b548cc8fbd28c8b8e06dulan@chromium.org                0, views::GridLayout::USE_PREF, 0, 0);
118304cc33f8259ef467e8e3c79f448d0bae0e8cd85yangguo@chromium.org  cs->AddPaddingColumn(0, kTitleHorizontalPadding);
119304cc33f8259ef467e8e3c79f448d0bae0e8cd85yangguo@chromium.org  cs->AddColumn(views::GridLayout::FILL, views::GridLayout::FILL,
120304cc33f8259ef467e8e3c79f448d0bae0e8cd85yangguo@chromium.org                1, views::GridLayout::USE_PREF, 0, 0);
121afbdadc5f06365a7889e7c1c1fdb7dbf596cce68machenbach@chromium.org
122afbdadc5f06365a7889e7c1c1fdb7dbf596cce68machenbach@chromium.org  // Middle rows, message labels.
123304cc33f8259ef467e8e3c79f448d0bae0e8cd85yangguo@chromium.org  cs = layout->AddColumnSet(1);
124afbdadc5f06365a7889e7c1c1fdb7dbf596cce68machenbach@chromium.org  cs->AddColumn(views::GridLayout::FILL, views::GridLayout::FILL,
125304cc33f8259ef467e8e3c79f448d0bae0e8cd85yangguo@chromium.org                1, views::GridLayout::USE_PREF, 0, 0);
126304cc33f8259ef467e8e3c79f448d0bae0e8cd85yangguo@chromium.org
127304cc33f8259ef467e8e3c79f448d0bae0e8cd85yangguo@chromium.org  // Bottom row, accept and cancel button.
12843d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  cs = layout->AddColumnSet(2);
12943d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  cs->AddPaddingColumn(1, views::kRelatedControlHorizontalSpacing);
130304cc33f8259ef467e8e3c79f448d0bae0e8cd85yangguo@chromium.org  cs->AddColumn(views::GridLayout::TRAILING, views::GridLayout::LEADING,
131                0, views::GridLayout::USE_PREF, 0, 0);
132  if (cancel_button.get()) {
133    cs->AddPaddingColumn(0, views::kRelatedButtonHSpacing);
134    cs->AddColumn(views::GridLayout::TRAILING, views::GridLayout::LEADING,
135                  0, views::GridLayout::USE_PREF, 0, 0);
136  }
137
138  layout->StartRow(1, 0);
139  layout->AddView(image_view.release());
140  layout->AddView(title_label.release());
141  layout->AddPaddingRow(0, views::kRelatedControlVerticalSpacing);
142
143  for (size_t i = 0; i < message_labels.size(); ++i) {
144    layout->StartRow(1, 1);
145    layout->AddView(message_labels[i]);
146    if (i < message_labels.size() - 1)
147      layout->AddPaddingRow(0, views::kRelatedControlVerticalSpacing);
148  }
149  layout->AddPaddingRow(0, views::kLabelToControlVerticalSpacing);
150
151  layout->StartRow(0, 2);
152  layout->AddView(accept_button.release());
153  if (cancel_button.get())
154    layout->AddView(cancel_button.release());
155
156  // Adjust the message label size in case buttons are too long.
157  for (size_t i = 0; i < message_labels.size(); ++i)
158    message_labels[i]->SizeToFit(layout->GetPreferredSize(this).width());
159}
160
161GlobalErrorBubbleView::~GlobalErrorBubbleView() {
162}
163
164void GlobalErrorBubbleView::ButtonPressed(views::Button* sender,
165                                          const ui::Event& event) {
166  if (error_) {
167    if (sender->tag() == TAG_ACCEPT_BUTTON)
168      error_->BubbleViewAcceptButtonPressed(browser_);
169    else if (sender->tag() == TAG_CANCEL_BUTTON)
170      error_->BubbleViewCancelButtonPressed(browser_);
171    else
172      NOTREACHED();
173  }
174  GetWidget()->Close();
175}
176
177void GlobalErrorBubbleView::WindowClosing() {
178  if (error_)
179    error_->BubbleViewDidClose(browser_);
180}
181
182void GlobalErrorBubbleView::CloseBubbleView() {
183  GetWidget()->Close();
184}
185