summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--dialog.go14
-rw-r--r--dialog_windows.go60
-rw-r--r--test/main.go38
3 files changed, 77 insertions, 35 deletions
diff --git a/dialog.go b/dialog.go
index 9a5ec5e..2e96b22 100644
--- a/dialog.go
+++ b/dialog.go
@@ -19,7 +19,7 @@ var dialogWindow *Window
// Whether or not resizing Windows will still be allowed is implementation-defined; if the implementation does allow it, resizes will still work properly.
// Whether or not the message box stays above all other W+indows in the program is also implementation-defined.
func MsgBox(primaryText string, secondaryText string) {
- dialogWindow.msgBox(parent, primaryText, secondaryText)
+ <-dialogWindow.msgBox(primaryText, secondaryText)
}
// MsgBox behaves like the package-scope MsgBox function, except the message box is modal to w only.
@@ -28,24 +28,26 @@ func MsgBox(primaryText string, secondaryText string) {
// Whether w can be resized while the message box is displayed is implementation-defined, but will work properly if allowed.
// If w has not yet been created, MsgBox() panics.
// If w has not been shown yet or is currently hidden, what MsgBox does is implementation-defined.
-func (w *Window) MsgBox(primaryText string, secondaryText string) {
+//
+// On return, done will be a channel that is pulsed when the message box is dismissed.
+func (w *Window) MsgBox(primaryText string, secondaryText string) (done chan struct{}) {
if !w.created {
panic("parent window passed to Window.MsgBox() before it was created")
}
- w.msgBox(primaryText, secondaryText)
+ return w.msgBox(primaryText, secondaryText)
}
// MsgBoxError displays a message box to the user with just an OK button and an icon indicating an error.
// Otherwise, it behaves like MsgBox.
func MsgBoxError(primaryText string, secondaryText string) {
- dialogWindow.msgBoxError(parent, primaryText, secondaryText)
+ <-dialogWindow.msgBoxError(primaryText, secondaryText)
}
// MsgBoxError displays a message box to the user with just an OK button and an icon indicating an error.
// Otherwise, it behaves like Window.MsgBox.
-func (w *Window) MsgBoxError(primaryText string, secondaryText string) {
+func (w *Window) MsgBoxError(primaryText string, secondaryText string) (done chan struct{}) {
if !w.created {
panic("parent window passed to MsgBoxError() before it was created")
}
- w.msgBoxError(primaryText, secondaryText)
+ return w.msgBoxError(primaryText, secondaryText)
}
diff --git a/dialog_windows.go b/dialog_windows.go
index 131319d..d863f13 100644
--- a/dialog_windows.go
+++ b/dialog_windows.go
@@ -11,7 +11,7 @@ var (
_messageBox = user32.NewProc("MessageBoxW")
)
-func _msgBox(parent *Window, primarytext string, secondarytext string, uType uint32) (result int) {
+func _msgBox(parent *Window, primarytext string, secondarytext string, uType uint32) (result chan int) {
// http://msdn.microsoft.com/en-us/library/windows/desktop/aa511267.aspx says "Use task dialogs whenever appropriate to achieve a consistent look and layout. Task dialogs require Windows Vista® or later, so they aren't suitable for earlier versions of Windows. If you must use a message box, separate the main instruction from the supplemental instruction with two line breaks."
text := primarytext
if secondarytext != "" {
@@ -19,36 +19,50 @@ func _msgBox(parent *Window, primarytext string, secondarytext string, uType uin
}
ptext := toUTF16(text)
ptitle := toUTF16(os.Args[0])
- ret := make(chan uiret)
- defer close(ret)
parenthwnd := _HWND(_NULL)
- if parent != nil {
+ if parent != dialogWindow {
parenthwnd = parent.sysData.hwnd
uType |= _MB_APPLMODAL // only for this window
} else {
uType |= _MB_TASKMODAL // make modal to every window in the program (they're all windows of the uitask, which is a single thread)
}
- uitask <- &uimsg{
- call: _messageBox,
- p: []uintptr{
- uintptr(parenthwnd),
- utf16ToArg(ptext),
- utf16ToArg(ptitle),
- uintptr(uType),
- },
- ret: ret,
- }
- r := <-ret
- if r.ret == 0 { // failure
- panic(fmt.Sprintf("error displaying message box to user: %v\nstyle: 0x%08X\ntitle: %q\ntext:\n%s", r.err, uType, os.Args[0], text))
- }
- return int(r.ret)
+ retchan := make(chan int)
+ go func() {
+ ret := make(chan uiret)
+ defer close(ret)
+ uitask <- &uimsg{
+ call: _messageBox,
+ p: []uintptr{
+ uintptr(parenthwnd),
+ utf16ToArg(ptext),
+ utf16ToArg(ptitle),
+ uintptr(uType),
+ },
+ ret: ret,
+ }
+ r := <-ret
+ if r.ret == 0 { // failure
+ panic(fmt.Sprintf("error displaying message box to user: %v\nstyle: 0x%08X\ntitle: %q\ntext:\n%s", r.err, uType, os.Args[0], text))
+ }
+ retchan <- int(r.ret)
+ }()
+ return retchan
}
-func msgBox(parent *Window, primarytext string, secondarytext string) {
- _msgBox(parent, primarytext, secondarytext, _MB_OK)
+func (w *Window) msgBox(primarytext string, secondarytext string) (done chan struct{}) {
+ done = make(chan struct{})
+ go func() {
+ <-_msgBox(w, primarytext, secondarytext, _MB_OK)
+ done <- struct{}{}
+ }()
+ return done
}
-func msgBoxError(parent *Window, primarytext string, secondarytext string) {
- _msgBox(parent, primarytext, secondarytext, _MB_OK | _MB_ICONERROR)
+func (w *Window) msgBoxError(primarytext string, secondarytext string) (done chan struct{}) {
+ done = make(chan struct{})
+ go func() {
+ <-_msgBox(w, primarytext, secondarytext, _MB_OK | _MB_ICONERROR)
+ done <- struct{}{}
+ }()
+ return done
}
diff --git a/test/main.go b/test/main.go
index 31e66c1..59a5791 100644
--- a/test/main.go
+++ b/test/main.go
@@ -49,7 +49,7 @@ var macCrashTest = flag.Bool("maccrash", false, "attempt crash on Mac OS X on de
func invalidTest(c *Combobox, l *Listbox, s *Stack, g *Grid) {
x := func(what string ) {
if j := recover(); j == nil {
- MsgBoxError(nil, "test", fmt.Sprintf("%s: no panic", what))
+ MsgBoxError("test", fmt.Sprintf("%s: no panic", what))
panic("invalid test fail")
} else {
println("got", j.(error).Error())
@@ -143,7 +143,7 @@ func invalidTest(c *Combobox, l *Listbox, s *Stack, g *Grid) {
defer x("Area.SetSize() " + q.msg); a.SetSize(q.x, q.y); panic(nil)
}()
}
- MsgBox(nil, "test", "all working as intended")
+ MsgBox("test", "all working as intended")
}
var invalidBefore = flag.Bool("invalid", false, "run invalid test before opening window")
@@ -226,7 +226,7 @@ func areaTest() {
if err != nil { println(err); continue }
a.SetSize(width, height)
case <-modaltest.Clicked:
- MsgBox(nil, "Modal Test", "")
+ MsgBox("Modal Test", "")
}
}
}
@@ -260,6 +260,8 @@ func areaboundsTest() {
<-w.Closing
}
+var dialogTest = flag.Bool("dialog", false, "add Window.MsgBox() channel test window")
+
func myMain() {
if *doArea {
areaTest()
@@ -284,6 +286,9 @@ func myMain() {
cb2 := NewCombobox("You can't edit me!", "No you can't!", "No you won't!")
e := NewLineEdit("Enter text here too")
l := NewLabel("This is a label")
+ resetl := func() {
+ l.SetText("This is a label")
+ }
b3 := NewButton("List Info")
s3 := NewHorizontalStack(l, b3)
s3.SetStretchy(0)
@@ -330,6 +335,17 @@ func myMain() {
ticker := time.Tick(time.Second)
+ dialog_bMsgBox := NewButton("MsgBox()")
+ dialog_bMsgBoxError := NewButton("MsgBoxError()")
+ dialog_win := NewWindow("Dialogs", 200, 200)
+ if *dialogTest {
+ dialog_win.Open(NewVerticalStack(
+ dialog_bMsgBox,
+ dialog_bMsgBoxError))
+ }
+
+ var dialog_sret chan struct{} = nil
+
mainloop:
for {
select {
@@ -368,7 +384,7 @@ _=curtime
if c.Checked() {
f = MsgBoxError
}
- f(nil, "List Info",
+ f("List Info",
fmt.Sprintf("cb1: %d %q (len %d)\ncb2: %d %q (len %d)\nlb1: %d %q (len %d)\nlb2: %d %q (len %d)",
cb1.SelectedIndex(), cb1.Selection(), cb1.Len(),
cb2.SelectedIndex(), cb2.Selection(), cb2.Len(),
@@ -393,8 +409,18 @@ _=curtime
case <-invalidButton.Clicked:
invalidTest(cb1, lb1, nil, nil)
case <-bmsg.Clicked:
- MsgBox(nil, "Title Only, no parent", "")
- MsgBox(w, "Title and Text", "parent")
+ MsgBox("Title Only, no parent", "")
+ MsgBox("Title and Text", "parent")
+ // dialogs
+ case <-dialog_bMsgBox.Clicked:
+ dialog_sret = dialog_win.MsgBox("Message Box", "Dismiss")
+ l.SetText("DIALOG")
+ case <-dialog_bMsgBoxError.Clicked:
+ dialog_sret = dialog_win.MsgBoxError("Message Box", "Dismiss")
+ l.SetText("DIALOG")
+ case <-dialog_sret:
+ dialog_sret = nil
+ resetl()
}
}
w.Hide()