simple_message_box_views.cc revision effb81e5f8246d0db0270817048dc992db66e9fb
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. 4 5#include "chrome/browser/ui/simple_message_box.h" 6 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" 19 20#if defined(OS_WIN) 21#include "ui/base/win/message_box_win.h" 22#include "ui/views/win/hwnd_util.h" 23#endif 24 25namespace chrome { 26 27namespace { 28 29class 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 MessageBoxResult* result); 37 virtual ~SimpleMessageBoxViews(); 38 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; 45 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; 53 54 private: 55 56 // This terminates the nested message-loop. 57 void Done(); 58 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_; 65 66 DISALLOW_COPY_AND_ASSIGN(SimpleMessageBoxViews); 67}; 68 69//////////////////////////////////////////////////////////////////////////////// 70// SimpleMessageBoxViews, public: 71 72SimpleMessageBoxViews::SimpleMessageBoxViews(const base::string16& title, 73 const base::string16& message, 74 MessageBoxType type, 75 const base::string16& yes_text, 76 const base::string16& no_text, 77 MessageBoxResult* result) 78 : window_title_(title), 79 type_(type), 80 yes_text_(yes_text), 81 no_text_(no_text), 82 result_(result), 83 message_box_view_(new views::MessageBoxView( 84 views::MessageBoxView::InitParams(message))) { 85 CHECK(result_); 86 if (yes_text_.empty()) { 87 if (type_ == MESSAGE_BOX_TYPE_QUESTION) 88 yes_text_ = 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); 92 else 93 yes_text_ = l10n_util::GetStringUTF16(IDS_OK); 94 } 95 96 if (no_text_.empty()) { 97 if (type_ == MESSAGE_BOX_TYPE_QUESTION) 98 no_text_ = 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); 102 } 103} 104 105SimpleMessageBoxViews::~SimpleMessageBoxViews() { 106} 107 108int 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; 112 } 113 114 return ui::DIALOG_BUTTON_OK; 115} 116 117base::string16 SimpleMessageBoxViews::GetDialogButtonLabel( 118 ui::DialogButton button) const { 119 if (button == ui::DIALOG_BUTTON_CANCEL) 120 return no_text_; 121 return yes_text_; 122} 123 124bool SimpleMessageBoxViews::Cancel() { 125 *result_ = MESSAGE_BOX_RESULT_NO; 126 Done(); 127 return true; 128} 129 130bool SimpleMessageBoxViews::Accept() { 131 *result_ = MESSAGE_BOX_RESULT_YES; 132 Done(); 133 return true; 134} 135 136base::string16 SimpleMessageBoxViews::GetWindowTitle() const { 137 return window_title_; 138} 139 140void SimpleMessageBoxViews::DeleteDelegate() { 141 delete this; 142} 143 144ui::ModalType SimpleMessageBoxViews::GetModalType() const { 145 return ui::MODAL_TYPE_WINDOW; 146} 147 148views::View* SimpleMessageBoxViews::GetContentsView() { 149 return message_box_view_; 150} 151 152views::Widget* SimpleMessageBoxViews::GetWidget() { 153 return message_box_view_->GetWidget(); 154} 155 156const views::Widget* SimpleMessageBoxViews::GetWidget() const { 157 return message_box_view_->GetWidget(); 158} 159 160//////////////////////////////////////////////////////////////////////////////// 161// SimpleMessageBoxViews, private: 162 163void SimpleMessageBoxViews::Done() { 164 aura::Window* window = GetWidget()->GetNativeView(); 165 aura::client::DispatcherClient* client = 166 aura::client::GetDispatcherClient(window->GetRootWindow()); 167 client->QuitNestedMessageLoop(); 168} 169 170#if defined(OS_WIN) 171UINT GetMessageBoxFlagsFromType(MessageBoxType type) { 172 UINT flags = MB_SETFOREGROUND; 173 switch (type) { 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; 182 } 183 NOTREACHED(); 184 return flags | MB_OK | MB_ICONWARNING; 185} 186#endif 187 188MessageBoxResult ShowMessageBoxImpl(gfx::NativeWindow parent, 189 const base::string16& title, 190 const base::string16& message, 191 MessageBoxType type, 192 const base::string16& yes_text, 193 const base::string16& no_text) { 194#if defined(OS_WIN) 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; 201 } 202#endif 203 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(); 208 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. 217 218 return result; 219} 220 221} // namespace 222 223MessageBoxResult 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()); 229} 230 231MessageBoxResult 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); 238} 239 240} // namespace chrome 241