diff --git a/darwin/stddialogs.m b/darwin/stddialogs.m index d51d1471..c9639a5e 100644 --- a/darwin/stddialogs.m +++ b/darwin/stddialogs.m @@ -1,6 +1,12 @@ // 26 june 2015 #import "uipriv_darwin.h" +// TODO while a dialog is running no other window receives events + +#define windowWindow(w) ((NSWindow *) uiControlHandle(uiControl(w))) + +// source of code modal logic: http://stackoverflow.com/questions/604768/wait-for-nsalert-beginsheetmodalforwindow + // note: whether extensions are actually shown depends on a user setting in Finder; we can't control it here static void setupSavePanel(NSSavePanel *s) { @@ -11,17 +17,20 @@ static void setupSavePanel(NSSavePanel *s) [s setTreatsFilePackagesAsDirectories:YES]; } -static char *runSavePanel(NSSavePanel *s) +static char *runSavePanel(NSWindow *parent, NSSavePanel *s) { char *filename; - if ([s runModal] != NSFileHandlingPanelOKButton) + [s beginSheetModalForWindow:parent completionHandler:^(NSInteger result) { + [realNSApp() stopModalWithCode:result]; + }]; + if ([realNSApp() runModalForWindow:s] != NSFileHandlingPanelOKButton) return NULL; filename = uiDarwinNSStringToText([[s URL] path]); return filename; } -char *uiOpenFile(void) +char *uiOpenFile(uiWindow *parent) { NSOpenPanel *o; @@ -32,22 +41,61 @@ char *uiOpenFile(void) [o setAllowsMultipleSelection:NO]; setupSavePanel(o); // panel is autoreleased - return runSavePanel(o); + return runSavePanel(windowWindow(parent), o); } -char *uiSaveFile(void) +char *uiSaveFile(uiWindow *parent) { NSSavePanel *s; s = [NSSavePanel savePanel]; setupSavePanel(s); // panel is autoreleased - return runSavePanel(s); + return runSavePanel(windowWindow(parent), s); } -static void msgbox(const char *title, const char *description, NSAlertStyle style) +// I would use a completion handler for NSAlert as well, but alas NSAlert's are 10.9 and higher only +@interface libuiCodeModalAlertPanel : NSObject { + NSAlert *panel; + NSWindow *parent; +} +- (id)initWithPanel:(NSAlert *)p parent:(NSWindow *)w; +- (NSInteger)run; +- (void)panelEnded:(NSAlert *)panel result:(NSInteger)result data:(void *)data; +@end + +@implementation libuiCodeModalAlertPanel + +- (id)initWithPanel:(NSAlert *)p parent:(NSWindow *)w +{ + self = [super init]; + if (self) { + self->panel = p; + self->parent = w; + } + return self; +} + +- (NSInteger)run +{ + [self->panel beginSheetModalForWindow:self->parent + modalDelegate:self + didEndSelector:@selector(panelEnded:result:data:) + contextInfo:NULL]; + return [realNSApp() runModalForWindow:[self->panel window]]; +} + +- (void)panelEnded:(NSAlert *)panel result:(NSInteger)result data:(void *)data +{ + [realNSApp() stopModalWithCode:result]; +} + +@end + +static void msgbox(NSWindow *parent, const char *title, const char *description, NSAlertStyle style) { NSAlert *a; + libuiCodeModalAlertPanel *cm; a = [NSAlert new]; [a setAlertStyle:style]; @@ -56,16 +104,18 @@ static void msgbox(const char *title, const char *description, NSAlertStyle styl [a setMessageText:toNSString(title)]; [a setInformativeText:toNSString(description)]; [a addButtonWithTitle:@"OK"]; - [a runModal]; + cm = [[libuiCodeModalAlertPanel alloc] initWithPanel:a parent:parent]; + [cm run]; + [cm release]; [a release]; } -void uiMsgBox(const char *title, const char *description) +void uiMsgBox(uiWindow *parent, const char *title, const char *description) { - msgbox(title, description, NSInformationalAlertStyle); + msgbox(windowWindow(parent), title, description, NSInformationalAlertStyle); } -void uiMsgBoxError(const char *title, const char *description) +void uiMsgBoxError(uiWindow *parent, const char *title, const char *description) { - msgbox(title, description, NSCriticalAlertStyle); + msgbox(windowWindow(parent), title, description, NSCriticalAlertStyle); }