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