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/base/resource/resource_bundle.h"
15 #include "ui/gfx/native_widget_types.h"
16 #include "ui/views/controls/message_box_view.h"
17 #include "ui/views/widget/widget.h"
18 #include "ui/views/window/dialog_delegate.h"
19 #include "ui/wm/public/dispatcher_client.h"
22 #include "ui/base/win/message_box_win.h"
23 #include "ui/views/win/hwnd_util.h"
30 class SimpleMessageBoxViews
: public views::DialogDelegate
{
32 SimpleMessageBoxViews(const base::string16
& title
,
33 const base::string16
& message
,
35 const base::string16
& yes_text
,
36 const base::string16
& no_text
,
38 MessageBoxResult
* result
);
39 virtual ~SimpleMessageBoxViews();
41 // Overridden from views::DialogDelegate:
42 virtual int GetDialogButtons() const OVERRIDE
;
43 virtual base::string16
GetDialogButtonLabel(
44 ui::DialogButton button
) const OVERRIDE
;
45 virtual bool Cancel() OVERRIDE
;
46 virtual bool Accept() OVERRIDE
;
48 // Overridden from views::WidgetDelegate:
49 virtual base::string16
GetWindowTitle() const OVERRIDE
;
50 virtual void DeleteDelegate() OVERRIDE
;
51 virtual ui::ModalType
GetModalType() const OVERRIDE
;
52 virtual views::View
* GetContentsView() OVERRIDE
;
53 virtual views::Widget
* GetWidget() OVERRIDE
;
54 virtual const views::Widget
* GetWidget() const OVERRIDE
;
58 // This terminates the nested message-loop.
61 const base::string16 window_title_
;
62 const MessageBoxType type_
;
63 base::string16 yes_text_
;
64 base::string16 no_text_
;
65 MessageBoxResult
* result_
;
66 bool is_system_modal_
;
67 views::MessageBoxView
* message_box_view_
;
69 DISALLOW_COPY_AND_ASSIGN(SimpleMessageBoxViews
);
72 ////////////////////////////////////////////////////////////////////////////////
73 // SimpleMessageBoxViews, public:
75 SimpleMessageBoxViews::SimpleMessageBoxViews(const base::string16
& title
,
76 const base::string16
& message
,
78 const base::string16
& yes_text
,
79 const base::string16
& no_text
,
81 MessageBoxResult
* result
)
82 : window_title_(title
),
87 is_system_modal_(is_system_modal
),
88 message_box_view_(new views::MessageBoxView(
89 views::MessageBoxView::InitParams(message
))) {
91 if (yes_text_
.empty()) {
92 if (type_
== MESSAGE_BOX_TYPE_QUESTION
)
94 l10n_util::GetStringUTF16(IDS_CONFIRM_MESSAGEBOX_YES_BUTTON_LABEL
);
95 else if (type_
== MESSAGE_BOX_TYPE_OK_CANCEL
)
96 yes_text_
= l10n_util::GetStringUTF16(IDS_OK
);
98 yes_text_
= l10n_util::GetStringUTF16(IDS_OK
);
101 if (no_text_
.empty()) {
102 if (type_
== MESSAGE_BOX_TYPE_QUESTION
)
104 l10n_util::GetStringUTF16(IDS_CONFIRM_MESSAGEBOX_NO_BUTTON_LABEL
);
105 else if (type_
== MESSAGE_BOX_TYPE_OK_CANCEL
)
106 no_text_
= l10n_util::GetStringUTF16(IDS_CANCEL
);
110 SimpleMessageBoxViews::~SimpleMessageBoxViews() {
113 int SimpleMessageBoxViews::GetDialogButtons() const {
114 if (type_
== MESSAGE_BOX_TYPE_QUESTION
||
115 type_
== MESSAGE_BOX_TYPE_OK_CANCEL
) {
116 return ui::DIALOG_BUTTON_OK
| ui::DIALOG_BUTTON_CANCEL
;
119 return ui::DIALOG_BUTTON_OK
;
122 base::string16
SimpleMessageBoxViews::GetDialogButtonLabel(
123 ui::DialogButton button
) const {
124 if (button
== ui::DIALOG_BUTTON_CANCEL
)
129 bool SimpleMessageBoxViews::Cancel() {
130 *result_
= MESSAGE_BOX_RESULT_NO
;
135 bool SimpleMessageBoxViews::Accept() {
136 *result_
= MESSAGE_BOX_RESULT_YES
;
141 base::string16
SimpleMessageBoxViews::GetWindowTitle() const {
142 return window_title_
;
145 void SimpleMessageBoxViews::DeleteDelegate() {
149 ui::ModalType
SimpleMessageBoxViews::GetModalType() const {
150 return is_system_modal_
? ui::MODAL_TYPE_SYSTEM
: ui::MODAL_TYPE_WINDOW
;
153 views::View
* SimpleMessageBoxViews::GetContentsView() {
154 return message_box_view_
;
157 views::Widget
* SimpleMessageBoxViews::GetWidget() {
158 return message_box_view_
->GetWidget();
161 const views::Widget
* SimpleMessageBoxViews::GetWidget() const {
162 return message_box_view_
->GetWidget();
165 ////////////////////////////////////////////////////////////////////////////////
166 // SimpleMessageBoxViews, private:
168 void SimpleMessageBoxViews::Done() {
169 aura::Window
* window
= GetWidget()->GetNativeView();
170 aura::client::DispatcherClient
* client
=
171 aura::client::GetDispatcherClient(window
->GetRootWindow());
172 client
->QuitNestedMessageLoop();
176 UINT
GetMessageBoxFlagsFromType(MessageBoxType type
) {
177 UINT flags
= MB_SETFOREGROUND
;
179 case MESSAGE_BOX_TYPE_INFORMATION
:
180 return flags
| MB_OK
| MB_ICONINFORMATION
;
181 case MESSAGE_BOX_TYPE_WARNING
:
182 return flags
| MB_OK
| MB_ICONWARNING
;
183 case MESSAGE_BOX_TYPE_QUESTION
:
184 return flags
| MB_YESNO
| MB_ICONQUESTION
;
185 case MESSAGE_BOX_TYPE_OK_CANCEL
:
186 return flags
| MB_OKCANCEL
| MB_ICONWARNING
;
189 return flags
| MB_OK
| MB_ICONWARNING
;
193 MessageBoxResult
ShowMessageBoxImpl(gfx::NativeWindow parent
,
194 const base::string16
& title
,
195 const base::string16
& message
,
197 const base::string16
& yes_text
,
198 const base::string16
& no_text
) {
199 // Views dialogs cannot be shown outside the UI thread message loop or if the
200 // ResourceBundle is not initialized yet.
201 // Fallback to logging with a default response or a Windows MessageBox.
203 if (!base::MessageLoopForUI::IsCurrent() ||
204 !base::MessageLoopForUI::current()->is_running() ||
205 !ResourceBundle::HasSharedInstance()) {
206 int result
= ui::MessageBox(views::HWNDForNativeWindow(parent
), message
,
207 title
, GetMessageBoxFlagsFromType(type
));
208 return (result
== IDYES
|| result
== IDOK
) ?
209 MESSAGE_BOX_RESULT_YES
: MESSAGE_BOX_RESULT_NO
;
212 if (!base::MessageLoopForUI::IsCurrent() ||
213 !ResourceBundle::HasSharedInstance()) {
214 LOG(ERROR
) << "Unable to show a dialog outside the UI thread message loop: "
215 << title
<< " - " << message
;
216 return MESSAGE_BOX_RESULT_NO
;
220 MessageBoxResult result
= MESSAGE_BOX_RESULT_NO
;
221 SimpleMessageBoxViews
* dialog
= new SimpleMessageBoxViews(
227 parent
== NULL
, // is_system_modal
229 CreateBrowserModalDialogViews(dialog
, parent
)->Show();
231 // Use the widget's window itself so that the message loop exists when the
232 // dialog is closed by some other means than |Cancel| or |Accept|.
233 aura::Window
* anchor
= dialog
->GetWidget()->GetNativeWindow();
234 aura::client::DispatcherClient
* client
=
235 aura::client::GetDispatcherClient(anchor
->GetRootWindow());
236 client
->RunWithDispatcher(NULL
);
237 // NOTE: |dialog| will have been deleted by the time control returns here.
244 MessageBoxResult
ShowMessageBox(gfx::NativeWindow parent
,
245 const base::string16
& title
,
246 const base::string16
& message
,
247 MessageBoxType type
) {
248 return ShowMessageBoxImpl(
249 parent
, title
, message
, type
, base::string16(), base::string16());
252 MessageBoxResult
ShowMessageBoxWithButtonText(gfx::NativeWindow parent
,
253 const base::string16
& title
,
254 const base::string16
& message
,
255 const base::string16
& yes_text
,
256 const base::string16
& no_text
) {
257 return ShowMessageBoxImpl(
258 parent
, title
, message
, MESSAGE_BOX_TYPE_QUESTION
, yes_text
, no_text
);
261 } // namespace chrome