diff --git a/redo/test/GNUmakeinc.mk b/redo/test/GNUmakeinc.mk index 10d00280..6f1bc017 100644 --- a/redo/test/GNUmakeinc.mk +++ b/redo/test/GNUmakeinc.mk @@ -7,6 +7,7 @@ testCFILES = \ test/page2.c \ test/page3.c \ test/page4.c \ + test/page5.c \ test/spaced.c testHFILES = \ diff --git a/redo/test/main.c b/redo/test/main.c index 1ba7a7fc..0cccaa7b 100644 --- a/redo/test/main.c +++ b/redo/test/main.c @@ -39,7 +39,7 @@ int main(int argc, char *argv[]) int i; const char *err; uiWindow *w; - uiBox *page2, *page3, *page4; + uiBox *page2, *page3, *page4, *page5; int nomenus = 0; memset(&o, 0, sizeof (uiInitOptions)); @@ -87,6 +87,9 @@ int main(int argc, char *argv[]) page4 = makePage4(); uiTabAppend(mainTab, "Page 4", uiControl(page4)); + page5 = makePage5(); + uiTabAppend(mainTab, "Page 5", uiControl(page5)); + uiControlShow(uiControl(w)); uiMain(); printf("after uiMain()\n"); diff --git a/redo/test/page5.c b/redo/test/page5.c new file mode 100644 index 00000000..a703f523 --- /dev/null +++ b/redo/test/page5.c @@ -0,0 +1,39 @@ +// 22 may 2015 +#include "test.h" + +static void openFile(uiButton *b, void *data) +{ + char *fn; + + fn = uiOpenFile(); + if (fn == NULL) + uiLabelSetText(uiLabel(data), "(cancelled)"); + else { + uiLabelSetText(uiLabel(data), fn); + uiFreeText(fn); + } +} + +uiBox *makePage5(void) +{ + uiBox *page5; + uiBox *hbox; + uiButton *button; + uiLabel *label; + + page5 = newVerticalBox(); + + // TODO label should not be stretchy - figure out how to autosize it on text change +#define D(n, f) \ + hbox = newHorizontalBox(); \ + button = uiNewButton(n); \ + label = uiNewLabel(""); \ + uiButtonOnClicked(button, f, label); \ + uiBoxAppend(hbox, uiControl(button), 0); \ + uiBoxAppend(hbox, uiControl(label), 1); \ + uiBoxAppend(page5, uiControl(hbox), 0); + + D("Open File", openFile); + + return page5; +} diff --git a/redo/test/test.h b/redo/test/test.h index 79350a34..70164105 100644 --- a/redo/test/test.h +++ b/redo/test/test.h @@ -36,3 +36,6 @@ extern uiBox *makePage3(void); // page4.c extern uiBox *makePage4(void); + +// page5.c +extern uiBox *makePage5(void); diff --git a/redo/ui.idl b/redo/ui.idl index 72d37dc9..74fde141 100644 --- a/redo/ui.idl +++ b/redo/ui.idl @@ -205,4 +205,6 @@ interface MenuItem { func SetChecked(checked int); }; +func OpenFile(void) *char; + }; diff --git a/redo/windows/GNUmakeinc.mk b/redo/windows/GNUmakeinc.mk index 81331122..20974388 100644 --- a/redo/windows/GNUmakeinc.mk +++ b/redo/windows/GNUmakeinc.mk @@ -24,6 +24,7 @@ osCFILES = \ windows/separator.c \ windows/slider.c \ windows/spinbox.c \ + windows/stddialogs.c \ windows/tab.c \ windows/text.c \ windows/util.c \ diff --git a/redo/windows/dialoghelper.c b/redo/windows/dialoghelper.c index 584247c6..1330d0cf 100644 --- a/redo/windows/dialoghelper.c +++ b/redo/windows/dialoghelper.c @@ -87,7 +87,7 @@ ATOM initDialogHelper(HICON hDefaultIcon, HCURSOR hDefaultCursor) return RegisterClassW(&wc); } -uintptr_t beginDialogHelper(void) +HWND beginDialogHelper(void) { HWND hwnd; @@ -98,13 +98,11 @@ uintptr_t beginDialogHelper(void) NULL, NULL, hInstance, NULL); if (hwnd == NULL) logLastError("error creating dialog helper in beginDialogHelper()"); - return (uintptr_t) hwnd; + return hwnd; } -void endDialog(uintptr_t handle) +void endDialogHelper(HWND hwnd) { - HWND hwnd = (HWND) handle; - if (DestroyWindow(hwnd) == 0) logLastError("error cleaning up after dialog helper in endDialogHelper()"); } diff --git a/redo/windows/stddialogs.c b/redo/windows/stddialogs.c new file mode 100644 index 00000000..e1ed95a5 --- /dev/null +++ b/redo/windows/stddialogs.c @@ -0,0 +1,41 @@ +// 22 may 2015 +#include "uipriv_windows.h" + +// TODO when making Vista-only, use common item dialog + +// this should be reasonable +#define NFILENAME 4096 + +char *uiOpenFile(void) +{ + WCHAR wfilename[NFILENAME]; + OPENFILENAMEW ofn; + HWND dialogHelper; + DWORD err; + + dialogHelper = beginDialogHelper(); + wfilename[0] = L'\0'; // required by GetOpenFileName() to indicate no previous filename + ZeroMemory(&ofn, sizeof (OPENFILENAMEW)); + ofn.lStructSize = sizeof (OPENFILENAMEW); + ofn.hwndOwner = dialogHelper; + ofn.hInstance = hInstance; + ofn.lpstrFilter = NULL; // no filters + ofn.lpstrFile = wfilename; + ofn.nMaxFile = NFILENAME; // seems to include null terminator according to docs + ofn.lpstrInitialDir = NULL; // let system decide + ofn.lpstrTitle = NULL; // let system decide + // TODO OFN_SHAREAWARE? + // better question: TODO keep networking? + ofn.Flags = OFN_EXPLORER | OFN_FILEMUSTEXIST | OFN_FORCESHOWHIDDEN | OFN_HIDEREADONLY | OFN_LONGNAMES | OFN_NOCHANGEDIR | OFN_NODEREFERENCELINKS | OFN_NOTESTFILECREATE | OFN_PATHMUSTEXIST; + if (GetOpenFileNameW(&ofn) == FALSE) { + err = CommDlgExtendedError(); + if (err != 0) + // TODO + complain("error running open file dialog", err); + // otherwise user cancelled + endDialogHelper(dialogHelper); + return NULL; + } + endDialogHelper(dialogHelper); + return toUTF8(wfilename); +} diff --git a/redo/windows/uipriv_windows.h b/redo/windows/uipriv_windows.h index 0cbf71b3..1b1aaa91 100644 --- a/redo/windows/uipriv_windows.h +++ b/redo/windows/uipriv_windows.h @@ -125,5 +125,5 @@ extern BOOL runWM_HSCROLL(WPARAM, LPARAM, LRESULT *); extern void dialogHelperRegisterWindow(HWND); extern void dialogHelperUnregisterWindow(HWND); extern ATOM initDialogHelper(HICON, HCURSOR); -extern uintptr_t beginDialogHelper(void); -extern void endDialog(uintptr_t); +extern HWND beginDialogHelper(void); +extern void endDialogHelper(HWND);