refactor: pass MessageBox params as a struct (#18732)

Historically, we've been passing in all MessageBox parameters individually, which makes augmenting or improving MessageBox functionality challenging because to change or add even one argument requires a huge cascade of argument changes that leaves room for errors.

For other file dialog related APIs, we use a struct (DialogSettings), and so this PR takes a similar approach and refactors MessageBox parameters into a struct (MessageBoxSettings) which we then use to simplify argument passing and which will enable us to more quickly iterate and improve upon functionality in the future.
This commit is contained in:
Shelley Vohr 2019-06-14 08:26:25 -07:00 committed by GitHub
parent ffb53405fb
commit bfcce8aa27
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
11 changed files with 207 additions and 247 deletions

View file

@ -19,25 +19,19 @@
namespace atom {
MessageBoxSettings::MessageBoxSettings() = default;
MessageBoxSettings::MessageBoxSettings(const MessageBoxSettings&) = default;
MessageBoxSettings::~MessageBoxSettings() = default;
namespace {
NSAlert* CreateNSAlert(NativeWindow* parent_window,
MessageBoxType type,
const std::vector<std::string>& buttons,
int default_id,
int cancel_id,
const std::string& title,
const std::string& message,
const std::string& detail,
const std::string& checkbox_label,
bool checkbox_checked,
const gfx::ImageSkia& icon) {
NSAlert* CreateNSAlert(const MessageBoxSettings& settings) {
// Ignore the title; it's the window title on other platforms and ignorable.
NSAlert* alert = [[NSAlert alloc] init];
[alert setMessageText:base::SysUTF8ToNSString(message)];
[alert setInformativeText:base::SysUTF8ToNSString(detail)];
[alert setMessageText:base::SysUTF8ToNSString(settings.message)];
[alert setInformativeText:base::SysUTF8ToNSString(settings.detail)];
switch (type) {
switch (settings.type) {
case MessageBoxType::kInformation:
alert.alertStyle = NSInformationalAlertStyle;
break;
@ -52,10 +46,10 @@ NSAlert* CreateNSAlert(NativeWindow* parent_window,
break;
}
for (size_t i = 0; i < buttons.size(); ++i) {
NSString* title = base::SysUTF8ToNSString(buttons[i]);
for (size_t i = 0; i < settings.buttons.size(); ++i) {
NSString* title = base::SysUTF8ToNSString(settings.buttons[i]);
// An empty title causes crash on macOS.
if (buttons[i].empty())
if (settings.buttons[i].empty())
title = @"(empty)";
NSButton* button = [alert addButtonWithTitle:title];
[button setTag:i];
@ -64,28 +58,31 @@ NSAlert* CreateNSAlert(NativeWindow* parent_window,
NSArray* ns_buttons = [alert buttons];
int button_count = static_cast<int>([ns_buttons count]);
if (default_id >= 0 && default_id < button_count) {
if (settings.default_id >= 0 && settings.default_id < button_count) {
// Focus the button at default_id if the user opted to do so.
// The first button added gets set as the default selected.
// So remove that default, and make the requested button the default.
[[ns_buttons objectAtIndex:0] setKeyEquivalent:@""];
[[ns_buttons objectAtIndex:default_id] setKeyEquivalent:@"\r"];
[[ns_buttons objectAtIndex:settings.default_id] setKeyEquivalent:@"\r"];
}
// Bind cancel id button to escape key if there is more than one button
if (button_count > 1 && cancel_id >= 0 && cancel_id < button_count) {
[[ns_buttons objectAtIndex:cancel_id] setKeyEquivalent:@"\e"];
if (button_count > 1 && settings.cancel_id >= 0 &&
settings.cancel_id < button_count) {
[[ns_buttons objectAtIndex:settings.cancel_id] setKeyEquivalent:@"\e"];
}
if (!checkbox_label.empty()) {
if (!settings.checkbox_label.empty()) {
alert.showsSuppressionButton = YES;
alert.suppressionButton.title = base::SysUTF8ToNSString(checkbox_label);
alert.suppressionButton.state = checkbox_checked ? NSOnState : NSOffState;
alert.suppressionButton.title =
base::SysUTF8ToNSString(settings.checkbox_label);
alert.suppressionButton.state =
settings.checkbox_checked ? NSOnState : NSOffState;
}
if (!icon.isNull()) {
if (!settings.icon.isNull()) {
NSImage* image = skia::SkBitmapToNSImageWithColorSpace(
*icon.bitmap(), base::mac::GetGenericRGBColorSpace());
*settings.icon.bitmap(), base::mac::GetGenericRGBColorSpace());
[alert setIcon:image];
}
@ -94,28 +91,18 @@ NSAlert* CreateNSAlert(NativeWindow* parent_window,
} // namespace
int ShowMessageBoxSync(NativeWindow* parent_window,
MessageBoxType type,
const std::vector<std::string>& buttons,
int default_id,
int cancel_id,
int options,
const std::string& title,
const std::string& message,
const std::string& detail,
const gfx::ImageSkia& icon) {
NSAlert* alert =
CreateNSAlert(parent_window, type, buttons, default_id, cancel_id, title,
message, detail, "", false, icon);
int ShowMessageBoxSync(const MessageBoxSettings& settings) {
NSAlert* alert = CreateNSAlert(settings);
// Use runModal for synchronous alert without parent, since we don't have a
// window to wait for.
if (!parent_window)
if (!settings.parent_window)
return [[alert autorelease] runModal];
__block int ret_code = -1;
NSWindow* window = parent_window->GetNativeWindow().GetNativeNSWindow();
NSWindow* window =
settings.parent_window->GetNativeWindow().GetNativeNSWindow();
[alert beginSheetModalForWindow:window
completionHandler:^(NSModalResponse response) {
ret_code = response;
@ -126,32 +113,20 @@ int ShowMessageBoxSync(NativeWindow* parent_window,
return ret_code;
}
void ShowMessageBox(NativeWindow* parent_window,
MessageBoxType type,
const std::vector<std::string>& buttons,
int default_id,
int cancel_id,
int options,
const std::string& title,
const std::string& message,
const std::string& detail,
const std::string& checkbox_label,
bool checkbox_checked,
const gfx::ImageSkia& icon,
void ShowMessageBox(const MessageBoxSettings& settings,
MessageBoxCallback callback) {
NSAlert* alert =
CreateNSAlert(parent_window, type, buttons, default_id, cancel_id, title,
message, detail, checkbox_label, checkbox_checked, icon);
NSAlert* alert = CreateNSAlert(settings);
// Use runModal for synchronous alert without parent, since we don't have a
// window to wait for.
if (!parent_window) {
if (!settings.parent_window) {
int ret = [[alert autorelease] runModal];
std::move(callback).Run(ret, alert.suppressionButton.state == NSOnState);
} else {
NSWindow* window =
parent_window ? parent_window->GetNativeWindow().GetNativeNSWindow()
: nil;
settings.parent_window
? settings.parent_window->GetNativeWindow().GetNativeNSWindow()
: nil;
// Duplicate the callback object here since c is a reference and gcd would
// only store the pointer, by duplication we can force gcd to store a copy.