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"
21 #include "ui/base/win/message_box_win.h"
22 #include "ui/views/win/hwnd_util.h"
29 class SimpleMessageBoxViews : public views::DialogDelegate {
31 SimpleMessageBoxViews(const base::string16& title,
32 const base::string16& message,
34 const base::string16& yes_text,
35 const base::string16& no_text,
36 MessageBoxResult* result);
37 virtual ~SimpleMessageBoxViews();
39 // Overridden from views::DialogDelegate:
40 virtual int GetDialogButtons() const OVERRIDE;
41 virtual base::string16 GetDialogButtonLabel(
42 ui::DialogButton button) const OVERRIDE;
43 virtual bool Cancel() OVERRIDE;
44 virtual bool Accept() OVERRIDE;
46 // Overridden from views::WidgetDelegate:
47 virtual base::string16 GetWindowTitle() const OVERRIDE;
48 virtual void DeleteDelegate() OVERRIDE;
49 virtual ui::ModalType GetModalType() const OVERRIDE;
50 virtual views::View* GetContentsView() OVERRIDE;
51 virtual views::Widget* GetWidget() OVERRIDE;
52 virtual const views::Widget* GetWidget() const OVERRIDE;
56 // This terminates the nested message-loop.
59 const base::string16 window_title_;
60 const MessageBoxType type_;
61 base::string16 yes_text_;
62 base::string16 no_text_;
63 MessageBoxResult* result_;
64 views::MessageBoxView* message_box_view_;
66 DISALLOW_COPY_AND_ASSIGN(SimpleMessageBoxViews);
69 ////////////////////////////////////////////////////////////////////////////////
70 // SimpleMessageBoxViews, public:
72 SimpleMessageBoxViews::SimpleMessageBoxViews(const base::string16& title,
73 const base::string16& message,
75 const base::string16& yes_text,
76 const base::string16& no_text,
77 MessageBoxResult* result)
78 : window_title_(title),
83 message_box_view_(new views::MessageBoxView(
84 views::MessageBoxView::InitParams(message))) {
86 if (yes_text_.empty()) {
87 if (type_ == MESSAGE_BOX_TYPE_QUESTION)
89 l10n_util::GetStringUTF16(IDS_CONFIRM_MESSAGEBOX_YES_BUTTON_LABEL);
90 else if (type_ == MESSAGE_BOX_TYPE_OK_CANCEL)
91 yes_text_ = l10n_util::GetStringUTF16(IDS_OK);
93 yes_text_ = l10n_util::GetStringUTF16(IDS_OK);
96 if (no_text_.empty()) {
97 if (type_ == MESSAGE_BOX_TYPE_QUESTION)
99 l10n_util::GetStringUTF16(IDS_CONFIRM_MESSAGEBOX_NO_BUTTON_LABEL);
100 else if (type_ == MESSAGE_BOX_TYPE_OK_CANCEL)
101 no_text_ = l10n_util::GetStringUTF16(IDS_CANCEL);
105 SimpleMessageBoxViews::~SimpleMessageBoxViews() {
108 int SimpleMessageBoxViews::GetDialogButtons() const {
109 if (type_ == MESSAGE_BOX_TYPE_QUESTION ||
110 type_ == MESSAGE_BOX_TYPE_OK_CANCEL) {
111 return ui::DIALOG_BUTTON_OK | ui::DIALOG_BUTTON_CANCEL;
114 return ui::DIALOG_BUTTON_OK;
117 base::string16 SimpleMessageBoxViews::GetDialogButtonLabel(
118 ui::DialogButton button) const {
119 if (button == ui::DIALOG_BUTTON_CANCEL)
124 bool SimpleMessageBoxViews::Cancel() {
125 *result_ = MESSAGE_BOX_RESULT_NO;
130 bool SimpleMessageBoxViews::Accept() {
131 *result_ = MESSAGE_BOX_RESULT_YES;
136 base::string16 SimpleMessageBoxViews::GetWindowTitle() const {
137 return window_title_;
140 void SimpleMessageBoxViews::DeleteDelegate() {
144 ui::ModalType SimpleMessageBoxViews::GetModalType() const {
145 return ui::MODAL_TYPE_WINDOW;
148 views::View* SimpleMessageBoxViews::GetContentsView() {
149 return message_box_view_;
152 views::Widget* SimpleMessageBoxViews::GetWidget() {
153 return message_box_view_->GetWidget();
156 const views::Widget* SimpleMessageBoxViews::GetWidget() const {
157 return message_box_view_->GetWidget();
160 ////////////////////////////////////////////////////////////////////////////////
161 // SimpleMessageBoxViews, private:
163 void SimpleMessageBoxViews::Done() {
164 aura::Window* window = GetWidget()->GetNativeView();
165 aura::client::DispatcherClient* client =
166 aura::client::GetDispatcherClient(window->GetRootWindow());
167 client->QuitNestedMessageLoop();
171 UINT GetMessageBoxFlagsFromType(MessageBoxType type) {
172 UINT flags = MB_SETFOREGROUND;
174 case MESSAGE_BOX_TYPE_INFORMATION:
175 return flags | MB_OK | MB_ICONINFORMATION;
176 case MESSAGE_BOX_TYPE_WARNING:
177 return flags | MB_OK | MB_ICONWARNING;
178 case MESSAGE_BOX_TYPE_QUESTION:
179 return flags | MB_YESNO | MB_ICONQUESTION;
180 case MESSAGE_BOX_TYPE_OK_CANCEL:
181 return flags | MB_OKCANCEL | MB_ICONWARNING;
184 return flags | MB_OK | MB_ICONWARNING;
188 MessageBoxResult ShowMessageBoxImpl(gfx::NativeWindow parent,
189 const base::string16& title,
190 const base::string16& message,
192 const base::string16& yes_text,
193 const base::string16& no_text) {
195 // GPU-based dialogs can't be used early on; fallback to a Windows MessageBox.
196 if (!base::MessageLoop::current()->is_running()) {
197 int result = ui::MessageBox(views::HWNDForNativeWindow(parent), message,
198 title, GetMessageBoxFlagsFromType(type));
199 return (result == IDYES || result == IDOK) ?
200 MESSAGE_BOX_RESULT_YES : MESSAGE_BOX_RESULT_NO;
204 MessageBoxResult result = MESSAGE_BOX_RESULT_NO;
205 SimpleMessageBoxViews* dialog = new SimpleMessageBoxViews(
206 title, message, type, yes_text, no_text, &result);
207 CreateBrowserModalDialogViews(dialog, parent)->Show();
209 // Use the widget's window itself so that the message loop
210 // exists when the dialog is closed by some other means than
211 // |Cancel| or |Accept|.
212 aura::Window* anchor = dialog->GetWidget()->GetNativeWindow();
213 aura::client::DispatcherClient* client =
214 aura::client::GetDispatcherClient(anchor->GetRootWindow());
215 client->RunWithDispatcher(NULL);
216 // NOTE: |dialog| will have been deleted by the time control returns here.
223 MessageBoxResult ShowMessageBox(gfx::NativeWindow parent,
224 const base::string16& title,
225 const base::string16& message,
226 MessageBoxType type) {
227 return ShowMessageBoxImpl(
228 parent, title, message, type, base::string16(), base::string16());
231 MessageBoxResult ShowMessageBoxWithButtonText(gfx::NativeWindow parent,
232 const base::string16& title,
233 const base::string16& message,
234 const base::string16& yes_text,
235 const base::string16& no_text) {
236 return ShowMessageBoxImpl(
237 parent, title, message, MESSAGE_BOX_TYPE_QUESTION, yes_text, no_text);
240 } // namespace chrome