Refactor views app list services to allow more code sharing
[chromium-blink-merge.git] / chrome / browser / ui / views / simple_message_box_views.cc
blob29d9e6d4848cc7376057960cd0273f955977f63a
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #include "chrome/browser/ui/simple_message_box.h"
7 #include "base/basictypes.h"
8 #include "base/compiler_specific.h"
9 #include "base/message_loop/message_loop.h"
10 #include "chrome/browser/ui/views/constrained_window_views.h"
11 #include "grit/generated_resources.h"
12 #include "ui/aura/window.h"
13 #include "ui/base/l10n/l10n_util.h"
14 #include "ui/gfx/native_widget_types.h"
15 #include "ui/views/controls/message_box_view.h"
16 #include "ui/views/widget/widget.h"
17 #include "ui/views/window/dialog_delegate.h"
18 #include "ui/wm/public/dispatcher_client.h"
20 #if defined(OS_WIN)
21 #include "ui/base/win/message_box_win.h"
22 #include "ui/views/win/hwnd_util.h"
23 #endif
25 namespace chrome {
27 namespace {
29 class SimpleMessageBoxViews : public views::DialogDelegate {
30 public:
31 SimpleMessageBoxViews(const base::string16& title,
32 const base::string16& message,
33 MessageBoxType type,
34 const base::string16& yes_text,
35 const base::string16& no_text,
36 bool is_system_modal,
37 MessageBoxResult* result);
38 virtual ~SimpleMessageBoxViews();
40 // Overridden from views::DialogDelegate:
41 virtual int GetDialogButtons() const OVERRIDE;
42 virtual base::string16 GetDialogButtonLabel(
43 ui::DialogButton button) const OVERRIDE;
44 virtual bool Cancel() OVERRIDE;
45 virtual bool Accept() OVERRIDE;
47 // Overridden from views::WidgetDelegate:
48 virtual base::string16 GetWindowTitle() const OVERRIDE;
49 virtual void DeleteDelegate() OVERRIDE;
50 virtual ui::ModalType GetModalType() const OVERRIDE;
51 virtual views::View* GetContentsView() OVERRIDE;
52 virtual views::Widget* GetWidget() OVERRIDE;
53 virtual const views::Widget* GetWidget() const OVERRIDE;
55 private:
57 // This terminates the nested message-loop.
58 void Done();
60 const base::string16 window_title_;
61 const MessageBoxType type_;
62 base::string16 yes_text_;
63 base::string16 no_text_;
64 MessageBoxResult* result_;
65 bool is_system_modal_;
66 views::MessageBoxView* message_box_view_;
68 DISALLOW_COPY_AND_ASSIGN(SimpleMessageBoxViews);
71 ////////////////////////////////////////////////////////////////////////////////
72 // SimpleMessageBoxViews, public:
74 SimpleMessageBoxViews::SimpleMessageBoxViews(const base::string16& title,
75 const base::string16& message,
76 MessageBoxType type,
77 const base::string16& yes_text,
78 const base::string16& no_text,
79 bool is_system_modal,
80 MessageBoxResult* result)
81 : window_title_(title),
82 type_(type),
83 yes_text_(yes_text),
84 no_text_(no_text),
85 result_(result),
86 is_system_modal_(is_system_modal),
87 message_box_view_(new views::MessageBoxView(
88 views::MessageBoxView::InitParams(message))) {
89 CHECK(result_);
90 if (yes_text_.empty()) {
91 if (type_ == MESSAGE_BOX_TYPE_QUESTION)
92 yes_text_ =
93 l10n_util::GetStringUTF16(IDS_CONFIRM_MESSAGEBOX_YES_BUTTON_LABEL);
94 else if (type_ == MESSAGE_BOX_TYPE_OK_CANCEL)
95 yes_text_ = l10n_util::GetStringUTF16(IDS_OK);
96 else
97 yes_text_ = l10n_util::GetStringUTF16(IDS_OK);
100 if (no_text_.empty()) {
101 if (type_ == MESSAGE_BOX_TYPE_QUESTION)
102 no_text_ =
103 l10n_util::GetStringUTF16(IDS_CONFIRM_MESSAGEBOX_NO_BUTTON_LABEL);
104 else if (type_ == MESSAGE_BOX_TYPE_OK_CANCEL)
105 no_text_ = l10n_util::GetStringUTF16(IDS_CANCEL);
109 SimpleMessageBoxViews::~SimpleMessageBoxViews() {
112 int SimpleMessageBoxViews::GetDialogButtons() const {
113 if (type_ == MESSAGE_BOX_TYPE_QUESTION ||
114 type_ == MESSAGE_BOX_TYPE_OK_CANCEL) {
115 return ui::DIALOG_BUTTON_OK | ui::DIALOG_BUTTON_CANCEL;
118 return ui::DIALOG_BUTTON_OK;
121 base::string16 SimpleMessageBoxViews::GetDialogButtonLabel(
122 ui::DialogButton button) const {
123 if (button == ui::DIALOG_BUTTON_CANCEL)
124 return no_text_;
125 return yes_text_;
128 bool SimpleMessageBoxViews::Cancel() {
129 *result_ = MESSAGE_BOX_RESULT_NO;
130 Done();
131 return true;
134 bool SimpleMessageBoxViews::Accept() {
135 *result_ = MESSAGE_BOX_RESULT_YES;
136 Done();
137 return true;
140 base::string16 SimpleMessageBoxViews::GetWindowTitle() const {
141 return window_title_;
144 void SimpleMessageBoxViews::DeleteDelegate() {
145 delete this;
148 ui::ModalType SimpleMessageBoxViews::GetModalType() const {
149 return is_system_modal_ ? ui::MODAL_TYPE_SYSTEM : ui::MODAL_TYPE_WINDOW;
152 views::View* SimpleMessageBoxViews::GetContentsView() {
153 return message_box_view_;
156 views::Widget* SimpleMessageBoxViews::GetWidget() {
157 return message_box_view_->GetWidget();
160 const views::Widget* SimpleMessageBoxViews::GetWidget() const {
161 return message_box_view_->GetWidget();
164 ////////////////////////////////////////////////////////////////////////////////
165 // SimpleMessageBoxViews, private:
167 void SimpleMessageBoxViews::Done() {
168 aura::Window* window = GetWidget()->GetNativeView();
169 aura::client::DispatcherClient* client =
170 aura::client::GetDispatcherClient(window->GetRootWindow());
171 client->QuitNestedMessageLoop();
174 #if defined(OS_WIN)
175 UINT GetMessageBoxFlagsFromType(MessageBoxType type) {
176 UINT flags = MB_SETFOREGROUND;
177 switch (type) {
178 case MESSAGE_BOX_TYPE_INFORMATION:
179 return flags | MB_OK | MB_ICONINFORMATION;
180 case MESSAGE_BOX_TYPE_WARNING:
181 return flags | MB_OK | MB_ICONWARNING;
182 case MESSAGE_BOX_TYPE_QUESTION:
183 return flags | MB_YESNO | MB_ICONQUESTION;
184 case MESSAGE_BOX_TYPE_OK_CANCEL:
185 return flags | MB_OKCANCEL | MB_ICONWARNING;
187 NOTREACHED();
188 return flags | MB_OK | MB_ICONWARNING;
190 #endif
192 MessageBoxResult ShowMessageBoxImpl(gfx::NativeWindow parent,
193 const base::string16& title,
194 const base::string16& message,
195 MessageBoxType type,
196 const base::string16& yes_text,
197 const base::string16& no_text) {
198 // Views dialogs cannot be shown outside the UI thread message loop.
199 // Fallback to logging with a default response or a Windows MessageBox.
200 if (!base::MessageLoopForUI::IsCurrent() ||
201 !base::MessageLoopForUI::current()->is_running()) {
202 #if defined(OS_WIN)
203 int result = ui::MessageBox(views::HWNDForNativeWindow(parent), message,
204 title, GetMessageBoxFlagsFromType(type));
205 return (result == IDYES || result == IDOK) ?
206 MESSAGE_BOX_RESULT_YES : MESSAGE_BOX_RESULT_NO;
207 #else
208 LOG(ERROR) << "Unable to show a dialog outside the UI thread message loop: "
209 << title << " - " << message;
210 return MESSAGE_BOX_RESULT_NO;
211 #endif
214 MessageBoxResult result = MESSAGE_BOX_RESULT_NO;
215 SimpleMessageBoxViews* dialog = new SimpleMessageBoxViews(
216 title,
217 message,
218 type,
219 yes_text,
220 no_text,
221 parent == NULL, // is_system_modal
222 &result);
223 CreateBrowserModalDialogViews(dialog, parent)->Show();
225 // Use the widget's window itself so that the message loop exists when the
226 // dialog is closed by some other means than |Cancel| or |Accept|.
227 aura::Window* anchor = dialog->GetWidget()->GetNativeWindow();
228 aura::client::DispatcherClient* client =
229 aura::client::GetDispatcherClient(anchor->GetRootWindow());
230 client->RunWithDispatcher(NULL);
231 // NOTE: |dialog| will have been deleted by the time control returns here.
233 return result;
236 } // namespace
238 MessageBoxResult ShowMessageBox(gfx::NativeWindow parent,
239 const base::string16& title,
240 const base::string16& message,
241 MessageBoxType type) {
242 return ShowMessageBoxImpl(
243 parent, title, message, type, base::string16(), base::string16());
246 MessageBoxResult ShowMessageBoxWithButtonText(gfx::NativeWindow parent,
247 const base::string16& title,
248 const base::string16& message,
249 const base::string16& yes_text,
250 const base::string16& no_text) {
251 return ShowMessageBoxImpl(
252 parent, title, message, MESSAGE_BOX_TYPE_QUESTION, yes_text, no_text);
255 } // namespace chrome