simple_message_box_views.cc revision e5d81f57cb97b3b6b7fccc9c5610d21eb81db09d
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 // Views dialogs cannot be shown outside the UI thread message loop. 195 // Fallback to logging with a default response or a Windows MessageBox. 196 if (!base::MessageLoopForUI::IsCurrent() || 197 !base::MessageLoopForUI::current()->is_running()) { 198#if defined(OS_WIN) 199 int result = ui::MessageBox(views::HWNDForNativeWindow(parent), message, 200 title, GetMessageBoxFlagsFromType(type)); 201 return (result == IDYES || result == IDOK) ? 202 MESSAGE_BOX_RESULT_YES : MESSAGE_BOX_RESULT_NO; 203#else 204 LOG(ERROR) << "Unable to show a dialog outside the UI thread message loop: " 205 << title << " - " << message; 206 return MESSAGE_BOX_RESULT_NO; 207#endif 208 } 209 210 MessageBoxResult result = MESSAGE_BOX_RESULT_NO; 211 SimpleMessageBoxViews* dialog = new SimpleMessageBoxViews( 212 title, message, type, yes_text, no_text, &result); 213 CreateBrowserModalDialogViews(dialog, parent)->Show(); 214 215 // Use the widget's window itself so that the message loop exists when the 216 // dialog is closed by some other means than |Cancel| or |Accept|. 217 aura::Window* anchor = dialog->GetWidget()->GetNativeWindow(); 218 aura::client::DispatcherClient* client = 219 aura::client::GetDispatcherClient(anchor->GetRootWindow()); 220 client->RunWithDispatcher(NULL); 221 // NOTE: |dialog| will have been deleted by the time control returns here. 222 223 return result; 224} 225 226} // namespace 227 228MessageBoxResult ShowMessageBox(gfx::NativeWindow parent, 229 const base::string16& title, 230 const base::string16& message, 231 MessageBoxType type) { 232 return ShowMessageBoxImpl( 233 parent, title, message, type, base::string16(), base::string16()); 234} 235 236MessageBoxResult ShowMessageBoxWithButtonText(gfx::NativeWindow parent, 237 const base::string16& title, 238 const base::string16& message, 239 const base::string16& yes_text, 240 const base::string16& no_text) { 241 return ShowMessageBoxImpl( 242 parent, title, message, MESSAGE_BOX_TYPE_QUESTION, yes_text, no_text); 243} 244 245} // namespace chrome 246