summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--redo/dialog.go10
-rw-r--r--redo/dialog_windows.c40
-rw-r--r--redo/dialog_windows.go33
-rw-r--r--redo/uitask_windows.go2
-rw-r--r--redo/winapi_windows.h3
-rw-r--r--redo/zz_test.go16
6 files changed, 102 insertions, 2 deletions
diff --git a/redo/dialog.go b/redo/dialog.go
new file mode 100644
index 0000000..f6a041f
--- /dev/null
+++ b/redo/dialog.go
@@ -0,0 +1,10 @@
+// 18 august 2014
+
+package ui
+
+// OpenFile opens a dialog box that asks the user to choose a file.
+// It returns the selected filename, or an empty string if no file was chosen.
+// All events stop while OpenFile is executing. (TODO move to doc.go)
+func OpenFile() (filename string) {
+ return openFile()
+}
diff --git a/redo/dialog_windows.c b/redo/dialog_windows.c
new file mode 100644
index 0000000..d5b69f7
--- /dev/null
+++ b/redo/dialog_windows.c
@@ -0,0 +1,40 @@
+// 18 august 2014
+
+#include "winapi_windows.h"
+#include "_cgo_export.h"
+
+// this should be reasonable
+#define NFILENAME 4096
+
+WCHAR *openFile(void)
+{
+ OPENFILENAMEW ofn;
+ DWORD err;
+ WCHAR *filenameBuffer;
+
+ // freed on the Go side
+ filenameBuffer = (WCHAR *) malloc((NFILENAME + 1) * sizeof (WCHAR));
+ if (filenameBuffer == NULL)
+ xpanic("memory exhausted in OpenFile()", GetLastError());
+ filenameBuffer[0] = L'\0'; // required by GetOpenFileName() to indicate no previous filename
+ ZeroMemory(&ofn, sizeof (OPENFILENAMEW));
+ ofn.lStructSize = sizeof (OPENFILENAMEW);
+ ofn.hwndOwner = NULL;
+ ofn.hInstance = hInstance;
+ ofn.lpstrFilter = NULL; // no filters
+ ofn.lpstrFile = filenameBuffer;
+ ofn.nMaxFile = NFILENAME + 1; // TODO include + 1?
+ ofn.lpstrInitialDir = NULL; // let system decide
+ ofn.lpstrTitle = NULL; // let system decide
+ // TODO OFN_SHAREAWARE?
+ // TODO remove OFN_NODEREFERENCELINKS? or does no filters ensure that anyway?
+ ofn.Flags = OFN_EXPLORER | OFN_FILEMUSTEXIST | OFN_FORCESHOWHIDDEN | OFN_HIDEREADONLY | OFN_LONGNAMES | OFN_NOCHANGEDIR | OFN_NODEREFERENCELINKS | OFN_NOTESTFILECREATE | OFN_PATHMUSTEXIST;
+ if (GetOpenFileNameW(&ofn) == FALSE) {
+ // TODO stringify
+ err = CommDlgExtendedError();
+ if (err == 0) // user cancelled
+ return NULL;
+ xpanic("error running open file dialog", GetLastError());
+ }
+ return filenameBuffer;
+}
diff --git a/redo/dialog_windows.go b/redo/dialog_windows.go
new file mode 100644
index 0000000..0346f56
--- /dev/null
+++ b/redo/dialog_windows.go
@@ -0,0 +1,33 @@
+// 18 august 2014
+
+package ui
+
+import (
+ "syscall"
+ "unsafe"
+ "reflect"
+)
+
+// #include "winapi_windows.h"
+import "C"
+
+// TODO move to common_windows.go
+func wstrToString(wstr *C.WCHAR) string {
+ n := C.wcslen((*C.wchar_t)(unsafe.Pointer(wstr)))
+ xbuf := &reflect.SliceHeader{
+ Data: uintptr(unsafe.Pointer(wstr)),
+ Len: int(n + 1),
+ Cap: int(n + 1),
+ }
+ buf := (*[]uint16)(unsafe.Pointer(xbuf))
+ return syscall.UTF16ToString(*buf)
+}
+
+func openFile() string {
+ name := C.openFile()
+ if name == nil {
+ return ""
+ }
+ defer C.free(unsafe.Pointer(name))
+ return wstrToString(name)
+}
diff --git a/redo/uitask_windows.go b/redo/uitask_windows.go
index 54b29cb..c3c1884 100644
--- a/redo/uitask_windows.go
+++ b/redo/uitask_windows.go
@@ -9,7 +9,7 @@ import (
)
// #cgo CFLAGS: --std=c99
-// #cgo LDFLAGS: -luser32 -lkernel32 -lgdi32 -luxtheme -lmsimg32
+// #cgo LDFLAGS: -luser32 -lkernel32 -lgdi32 -luxtheme -lmsimg32 -lcomdlg32
// #include "winapi_windows.h"
import "C"
diff --git a/redo/winapi_windows.h b/redo/winapi_windows.h
index 18db8db..e888c99 100644
--- a/redo/winapi_windows.h
+++ b/redo/winapi_windows.h
@@ -133,4 +133,7 @@ enum {
extern HIMAGELIST checkboxImageList;
extern void makeCheckboxImageList(HWND);
+// dialog_windows.c
+extern WCHAR *openFile(void);
+
#endif
diff --git a/redo/zz_test.go b/redo/zz_test.go
index 601d0ec..2477de0 100644
--- a/redo/zz_test.go
+++ b/redo/zz_test.go
@@ -38,6 +38,8 @@ type testwin struct {
festart Button
felabel Label
festop Button
+ openbtn Button
+ fnlabel Label
icons []icon
il ImageList
icontbl Table
@@ -89,7 +91,19 @@ func (tw *testwin) addfe() {
tw.fe = nil
}
})
- tw.festack = NewVerticalStack(tw.festart, tw.felabel, tw.festop)
+ tw.openbtn = NewButton("Open")
+ tw.openbtn.OnClicked(func() {
+ fn := OpenFile()
+ if fn == "" {
+ fn = "<no file selected>"
+ }
+ tw.fnlabel.SetText(fn)
+ })
+ tw.fnlabel = NewStandaloneLabel("<no file selected>")
+ tw.festack = NewVerticalStack(tw.festart, tw.felabel, tw.festop,
+ Space(),
+ tw.openbtn, tw.fnlabel)
+ tw.festack.SetStretchy(3)
tw.t.Append("Foreign Events", tw.festack)
}