From 3db42c8fb01a2e7afdefd6b491f174141adf6036 Mon Sep 17 00:00:00 2001
From: sqweek <sqweek@gmail.com>
Date: Wed, 6 Jan 2016 02:05:36 +0800
Subject: [PATCH] dlgs: implement error message dialog

---
 cocoa/dlg.go        | 43 +++++++++++++++++++++++++++++++++----------
 cocoa/dlg.h         |  6 ++++++
 cocoa/dlg.m         | 12 ++++++++++--
 dlgs.go             |  5 +++++
 dlgs_darwin.go      |  4 ++++
 dlgs_linux.go       |  7 +++++++
 dlgs_windows.go     |  4 ++++
 example/wde/main.go |  2 ++
 8 files changed, 71 insertions(+), 12 deletions(-)

diff --git a/cocoa/dlg.go b/cocoa/dlg.go
index f8b3fc3..d43dc8f 100644
--- a/cocoa/dlg.go
+++ b/cocoa/dlg.go
@@ -11,20 +11,43 @@ import (
 	"unsafe"
 )
 
-func nsStr(s string) unsafe.Pointer {
-	return C.NSStr(unsafe.Pointer(&[]byte(s)[0]), C.int(len(s)))
+type AlertParams struct {
+	p C.AlertDlgParams
 }
 
-func YesNoDlg(msg string, title string) bool {
-	p := C.AlertDlgParams{
-		msg: C.CString(msg),
-	}
-	defer C.free(unsafe.Pointer(p.msg))
+func mkAlertParams(msg, title string, style C.AlertStyle) *AlertParams {
+	a := AlertParams{C.AlertDlgParams{msg: C.CString(msg), style: style}}
 	if title != "" {
-		p.title = C.CString(title)
-		defer C.free(unsafe.Pointer(p.title))
+		a.p.title = C.CString(title)
+	}
+	return &a
+}
+
+func (a *AlertParams) run() C.DlgResult {
+	return C.alertDlg(&a.p)
+}
+
+func (a *AlertParams) free() {
+	C.free(unsafe.Pointer(a.p.msg))
+	if a.p.title != nil {
+		C.free(unsafe.Pointer(a.p.title))
 	}
-	return C.alertDlg(&p) == C.DLG_OK
+}
+
+func nsStr(s string) unsafe.Pointer {
+	return C.NSStr(unsafe.Pointer(&[]byte(s)[0]), C.int(len(s)))
+}
+
+func YesNoDlg(msg, title string) bool {
+	a := mkAlertParams(msg, title, C.MSG_YESNO)
+	defer a.free()
+	return a.run() == C.DLG_OK
+}
+
+func ErrorDlg(msg, title string) {
+	a := mkAlertParams(msg, title, C.MSG_ERROR)
+	defer a.free()
+	a.run()
 }
 
 func FileDlg(save int, title string, exts []string, relaxExt bool) (string, error) {
diff --git a/cocoa/dlg.h b/cocoa/dlg.h
index 3bb9a67..108cc5d 100644
--- a/cocoa/dlg.h
+++ b/cocoa/dlg.h
@@ -1,8 +1,14 @@
 #include <objc/NSObjcRuntime.h>
 
+typedef enum {
+	MSG_YESNO,
+	MSG_ERROR,
+} AlertStyle;
+
 typedef struct {
 	char* msg;
 	char* title;
+	AlertStyle style;
 } AlertDlgParams;
 
 typedef struct {
diff --git a/cocoa/dlg.m b/cocoa/dlg.m
index ad24b09..448f419 100644
--- a/cocoa/dlg.m
+++ b/cocoa/dlg.m
@@ -38,8 +38,16 @@ DlgResult alertDlg(AlertDlgParams* params) {
 		[[alert window] setTitle:[[NSString alloc] initWithUTF8String:self->params->title]];
 	}
 	[alert setMessageText:[[NSString alloc] initWithUTF8String:self->params->msg]];
-	[alert addButtonWithTitle:@"Yes"];
-	[alert addButtonWithTitle:@"No"];
+	switch (self->params->style) {
+	case MSG_YESNO:
+		[alert addButtonWithTitle:@"Yes"];
+		[alert addButtonWithTitle:@"No"];
+		break;
+	case MSG_ERROR:
+		[alert setIcon:[NSImage imageNamed:NSImageNameCaution]];
+		[alert addButtonWithTitle:@"OK"];
+		break;
+	}
 	self->result = [alert runModal] == NSAlertFirstButtonReturn ? DLG_OK : DLG_CANCEL;
 	return self->result;
 }
diff --git a/dlgs.go b/dlgs.go
index c1d863a..9e035f5 100644
--- a/dlgs.go
+++ b/dlgs.go
@@ -46,6 +46,11 @@ func (b *MsgBuilder) YesNo() bool {
 	return b.yesNo()
 }
 
+/* Error spawns the message dialog with an error icon and single button, "Ok". */
+func (b *MsgBuilder) Error() {
+	b.error()
+}
+
 /* FileFilter represents a category of files (eg. audio files, spreadsheets). */
 type FileFilter struct {
 	Desc string
diff --git a/dlgs_darwin.go b/dlgs_darwin.go
index 64fa1bf..a5e5db7 100644
--- a/dlgs_darwin.go
+++ b/dlgs_darwin.go
@@ -8,6 +8,10 @@ func (b *MsgBuilder) yesNo() bool {
 	return cocoa.YesNoDlg(b.Msg, b.Dlg.Title)
 }
 
+func (b *MsgBuilder) error() {
+	cocoa.ErrorDlg(b.Msg, b.Dlg.Title)
+}
+
 func (b *FileBuilder) load() (string, error) {
 	return b.run(0)
 }
diff --git a/dlgs_linux.go b/dlgs_linux.go
index d286de2..5f9423b 100644
--- a/dlgs_linux.go
+++ b/dlgs_linux.go
@@ -29,6 +29,13 @@ func (b *MsgBuilder) yesNo() bool {
 	return dlg.Run() == gtk.RESPONSE_YES
 }
 
+func (b *MsgBuilder) error() {
+	dlg := gtk.NewMessageDialog(nil, 0, gtk.MESSAGE_ERROR, gtk.BUTTONS_OK, "%s", b.Msg)
+	dlg.SetTitle(firstOf(b.Dlg.Title, "Error"))
+	defer closeDialog(&dlg.Dialog)
+	dlg.Run()
+}
+
 func (b *FileBuilder) load() (string, error) {
 	return chooseFile("Load", gtk.FILE_CHOOSER_ACTION_OPEN, b)
 }
diff --git a/dlgs_windows.go b/dlgs_windows.go
index a61dcf6..de78a3c 100644
--- a/dlgs_windows.go
+++ b/dlgs_windows.go
@@ -28,6 +28,10 @@ func (b *MsgBuilder) yesNo() bool {
 	return r == w32.IDYES
 }
 
+func (b *MsgBuilder) error() {
+	w32.MessageBox(w32.HWND(0), firstOf(b.Dlg.Title, "Error"), b.Msg, w32.MB_OK | w32.MB_ICONERROR)
+}
+
 type filedlg struct {
 	buf []uint16
 	filters []uint16
diff --git a/example/wde/main.go b/example/wde/main.go
index b3676c2..833e344 100644
--- a/example/wde/main.go
+++ b/example/wde/main.go
@@ -48,6 +48,8 @@ func events(events <-chan interface{}) {
 				fmt.Println(dialog.Message("Is this sentence false?").YesNo())
 			case e.Glyph == "b":
 				fmt.Println(dialog.Message("R U OK?").Title("Just checking").YesNo())
+			case e.Glyph == "c":
+				dialog.Message("Operation failed").Error()
 			}
 		case wde.CloseEvent:
 			wde.Stop()
-- 
GitLab