Skip to content

Commit

Permalink
Merge pull request #8590 from electron/showmessagebox-checkbox
Browse files Browse the repository at this point in the history
Add support for checkbox with dialog.showMessageBox
  • Loading branch information
kevinsawicki committed Feb 9, 2017
2 parents 9163b60 + 7994acf commit e741097
Show file tree
Hide file tree
Showing 10 changed files with 155 additions and 61 deletions.
6 changes: 4 additions & 2 deletions atom/browser/api/atom_api_dialog.cc
Expand Up @@ -47,6 +47,8 @@ void ShowMessageBox(int type,
const std::string& title,
const std::string& message,
const std::string& detail,
const std::string& checkbox_label,
bool checkbox_checked,
const gfx::ImageSkia& icon,
atom::NativeWindow* window,
mate::Arguments* args) {
Expand All @@ -56,8 +58,8 @@ void ShowMessageBox(int type,
peek,
&callback)) {
atom::ShowMessageBox(window, (atom::MessageBoxType)type, buttons,
default_id, cancel_id, options, title,
message, detail, icon, callback);
default_id, cancel_id, options, title, message, detail,
checkbox_label, checkbox_checked, icon, callback);
} else {
int chosen = atom::ShowMessageBox(window, (atom::MessageBoxType)type,
buttons, default_id, cancel_id,
Expand Down
15 changes: 6 additions & 9 deletions atom/browser/atom_javascript_dialog_manager.cc
Expand Up @@ -38,14 +38,9 @@ void AtomJavaScriptDialogManager::RunJavaScriptDialog(
}

atom::ShowMessageBox(NativeWindow::FromWebContents(web_contents),
atom::MessageBoxType::MESSAGE_BOX_TYPE_NONE,
buttons,
-1,
0,
atom::MessageBoxOptions::MESSAGE_BOX_NONE,
"",
base::UTF16ToUTF8(message_text),
"",
atom::MessageBoxType::MESSAGE_BOX_TYPE_NONE, buttons, -1,
0, atom::MessageBoxOptions::MESSAGE_BOX_NONE, "",
base::UTF16ToUTF8(message_text), "", "", false,
gfx::ImageSkia(),
base::Bind(&OnMessageBoxCallback, callback));
}
Expand All @@ -66,7 +61,9 @@ void AtomJavaScriptDialogManager::CancelDialogs(

// static
void AtomJavaScriptDialogManager::OnMessageBoxCallback(
const DialogClosedCallback& callback, int code) {
const DialogClosedCallback& callback,
int code,
bool checkbox_checked) {
callback.Run(code == 0, base::string16());
}

Expand Down
3 changes: 2 additions & 1 deletion atom/browser/atom_javascript_dialog_manager.h
Expand Up @@ -32,7 +32,8 @@ class AtomJavaScriptDialogManager : public content::JavaScriptDialogManager {

private:
static void OnMessageBoxCallback(const DialogClosedCallback& callback,
int code);
int code,
bool checkbox_checked);
};

} // namespace atom
Expand Down
5 changes: 4 additions & 1 deletion atom/browser/ui/message_box.h
Expand Up @@ -32,7 +32,8 @@ enum MessageBoxOptions {
MESSAGE_BOX_NO_LINK = 1 << 0,
};

typedef base::Callback<void(int code)> MessageBoxCallback;
typedef base::Callback<void(int code, bool checkbox_checked)>
MessageBoxCallback;

int ShowMessageBox(NativeWindow* parent_window,
MessageBoxType type,
Expand All @@ -54,6 +55,8 @@ void ShowMessageBox(NativeWindow* parent_window,
const std::string& title,
const std::string& message,
const std::string& detail,
const std::string& checkbox_label,
bool checkbox_checked,
const gfx::ImageSkia& icon,
const MessageBoxCallback& callback);

Expand Down
45 changes: 36 additions & 9 deletions atom/browser/ui/message_box_gtk.cc
Expand Up @@ -36,8 +36,11 @@ class GtkMessageBox : public NativeWindowObserver {
const std::string& title,
const std::string& message,
const std::string& detail,
const std::string& checkbox_label,
bool checkbox_checked,
const gfx::ImageSkia& icon)
: cancel_id_(cancel_id),
checkbox_checked_(false),
parent_(static_cast<NativeWindowViews*>(parent_window)) {
// Create dialog.
dialog_ = gtk_message_dialog_new(
Expand Down Expand Up @@ -68,6 +71,18 @@ class GtkMessageBox : public NativeWindowObserver {
g_object_unref(pixbuf);
}

if (!checkbox_label.empty()) {
GtkWidget* message_area =
gtk_message_dialog_get_message_area(GTK_MESSAGE_DIALOG(dialog_));
GtkWidget* check_button =
gtk_check_button_new_with_label(checkbox_label.c_str());
g_signal_connect(check_button, "toggled",
G_CALLBACK(OnCheckboxToggledThunk), this);
gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(check_button),
checkbox_checked);
gtk_container_add(GTK_CONTAINER(message_area), check_button);
}

// Add buttons.
for (size_t i = 0; i < buttons.size(); ++i) {
GtkWidget* button = gtk_dialog_add_button(
Expand Down Expand Up @@ -154,13 +169,16 @@ class GtkMessageBox : public NativeWindowObserver {
}

CHROMEGTK_CALLBACK_1(GtkMessageBox, void, OnResponseDialog, int);
CHROMEGTK_CALLBACK_0(GtkMessageBox, void, OnCheckboxToggled);

private:
atom::UnresponsiveSuppressor unresponsive_suppressor_;

// The id to return when the dialog is closed without pressing buttons.
int cancel_id_;

bool checkbox_checked_;

NativeWindowViews* parent_;
GtkWidget* dialog_;
MessageBoxCallback callback_;
Expand All @@ -172,12 +190,16 @@ void GtkMessageBox::OnResponseDialog(GtkWidget* widget, int response) {
gtk_widget_hide(dialog_);

if (response < 0)
callback_.Run(cancel_id_);
callback_.Run(cancel_id_, checkbox_checked_);
else
callback_.Run(response);
callback_.Run(response, checkbox_checked_);
delete this;
}

void GtkMessageBox::OnCheckboxToggled(GtkWidget* widget) {
checkbox_checked_ = GTK_TOGGLE_BUTTON(widget)->active;
}

} // namespace

int ShowMessageBox(NativeWindow* parent,
Expand All @@ -190,8 +212,9 @@ int ShowMessageBox(NativeWindow* parent,
const std::string& message,
const std::string& detail,
const gfx::ImageSkia& icon) {
return GtkMessageBox(parent, type, buttons, default_id, cancel_id,
title, message, detail, icon).RunSynchronous();
return GtkMessageBox(parent, type, buttons, default_id, cancel_id, title,
message, detail, "", false, icon)
.RunSynchronous();
}

void ShowMessageBox(NativeWindow* parent,
Expand All @@ -203,18 +226,22 @@ void ShowMessageBox(NativeWindow* parent,
const std::string& title,
const std::string& message,
const std::string& detail,
const std::string& checkbox_label,
bool checkbox_checked,
const gfx::ImageSkia& icon,
const MessageBoxCallback& callback) {
(new GtkMessageBox(parent, type, buttons, default_id, cancel_id,
title, message, detail, icon))->RunAsynchronous(callback);
(new GtkMessageBox(parent, type, buttons, default_id, cancel_id, title,
message, detail, checkbox_label, checkbox_checked, icon))
->RunAsynchronous(callback);
}

void ShowErrorBox(const base::string16& title, const base::string16& content) {
if (Browser::Get()->is_ready()) {
GtkMessageBox(nullptr, MESSAGE_BOX_TYPE_ERROR, { "OK" }, -1, 0, "Error",
GtkMessageBox(nullptr, MESSAGE_BOX_TYPE_ERROR, {"OK"}, -1, 0, "Error",
base::UTF16ToUTF8(title).c_str(),
base::UTF16ToUTF8(content).c_str(),
gfx::ImageSkia()).RunSynchronous();
base::UTF16ToUTF8(content).c_str(), "", false,
gfx::ImageSkia())
.RunSynchronous();
} else {
fprintf(stderr,
ANSI_TEXT_BOLD ANSI_BACKGROUND_GRAY
Expand Down
25 changes: 17 additions & 8 deletions atom/browser/ui/message_box_mac.mm
Expand Up @@ -39,7 +39,7 @@ - (id)initWithCallback:(const atom::MessageBoxCallback&)callback
- (void)alertDidEnd:(NSAlert*)alert
returnCode:(NSInteger)returnCode
contextInfo:(void*)contextInfo {
callback_.Run(returnCode);
callback_.Run(returnCode, alert.suppressionButton.state == NSOnState);
[alert_ release];
[self release];

Expand All @@ -60,6 +60,8 @@ - (void)alertDidEnd:(NSAlert*)alert
const std::string& title,
const std::string& message,
const std::string& detail,
const std::string& checkbox_label,
bool checkbox_checked,
const gfx::ImageSkia& icon) {
// Ignore the title; it's the window title on other platforms and ignorable.
NSAlert* alert = [[NSAlert alloc] init];
Expand Down Expand Up @@ -95,6 +97,12 @@ - (void)alertDidEnd:(NSAlert*)alert
[[ns_buttons objectAtIndex:default_id] setKeyEquivalent:@"\r"];
}

if (!checkbox_label.empty()) {
alert.showsSuppressionButton = YES;
alert.suppressionButton.title = base::SysUTF8ToNSString(checkbox_label);
alert.suppressionButton.state = checkbox_checked ? NSOnState : NSOffState;
}

if (!icon.isNull()) {
NSImage* image = skia::SkBitmapToNSImageWithColorSpace(
*icon.bitmap(), base::mac::GetGenericRGBColorSpace());
Expand All @@ -104,7 +112,7 @@ - (void)alertDidEnd:(NSAlert*)alert
return alert;
}

void SetReturnCode(int* ret_code, int result) {
void SetReturnCode(int* ret_code, int result, bool checkbox_checked) {
*ret_code = result;
}

Expand All @@ -120,9 +128,8 @@ int ShowMessageBox(NativeWindow* parent_window,
const std::string& message,
const std::string& detail,
const gfx::ImageSkia& icon) {
NSAlert* alert = CreateNSAlert(
parent_window, type, buttons, default_id, title, message,
detail, icon);
NSAlert* alert = CreateNSAlert(parent_window, type, buttons, default_id,
title, message, detail, "", false, icon);

// Use runModal for synchronous alert without parent, since we don't have a
// window to wait for.
Expand Down Expand Up @@ -154,11 +161,13 @@ void ShowMessageBox(NativeWindow* parent_window,
const std::string& title,
const std::string& message,
const std::string& detail,
const std::string& checkbox_label,
bool checkbox_checked,
const gfx::ImageSkia& icon,
const MessageBoxCallback& callback) {
NSAlert* alert = CreateNSAlert(
parent_window, type, buttons, default_id, title, message,
detail, icon);
NSAlert* alert =
CreateNSAlert(parent_window, type, buttons, default_id, title, message,
detail, checkbox_label, checkbox_checked, icon);
ModalDelegate* delegate = [[ModalDelegate alloc] initWithCallback:callback
andAlert:alert
callEndModal:false];
Expand Down

0 comments on commit e741097

Please sign in to comment.