diff --git a/darwin/stddialogs.m b/darwin/stddialogs.m index 814456ab..bf9bc192 100644 --- a/darwin/stddialogs.m +++ b/darwin/stddialogs.m @@ -32,7 +32,7 @@ static char *runSavePanel(NSWindow *parent, NSSavePanel *s) return filename; } -char *uiOpenFile(uiWindow *parent) +char *uiOpenFile(uiWindow *parent, char* filter) { NSOpenPanel *o; @@ -46,7 +46,7 @@ char *uiOpenFile(uiWindow *parent) return runSavePanel(windowWindow(parent), o); } -char *uiSaveFile(uiWindow *parent) +char *uiSaveFile(uiWindow *parent, char* filter) { NSSavePanel *s; diff --git a/ui.h b/ui.h index 40aea949..2eb20067 100644 --- a/ui.h +++ b/ui.h @@ -130,7 +130,7 @@ _UI_EXTERN void uiWindowSetBorderless(uiWindow *w, int borderless); _UI_EXTERN void uiWindowSetChild(uiWindow *w, uiControl *child); _UI_EXTERN int uiWindowMargined(uiWindow *w); _UI_EXTERN void uiWindowSetMargined(uiWindow *w, int margined); -_UI_EXTERN uiWindow *uiNewWindow(const char *title, int width, int height, int hasMenubar); +_UI_EXTERN uiWindow *uiNewWindow(const char *title, int width, int height, int hasMenubar, int resizable); typedef struct uiButton uiButton; #define uiButton(this) ((uiButton *) (this)) @@ -292,8 +292,8 @@ _UI_EXTERN uiMenuItem *uiMenuAppendAboutItem(uiMenu *m); _UI_EXTERN void uiMenuAppendSeparator(uiMenu *m); _UI_EXTERN uiMenu *uiNewMenu(const char *name); -_UI_EXTERN char *uiOpenFile(uiWindow *parent); -_UI_EXTERN char *uiSaveFile(uiWindow *parent); +_UI_EXTERN char *uiOpenFile(uiWindow *parent, char* filter); +_UI_EXTERN char *uiSaveFile(uiWindow *parent, char* filter); _UI_EXTERN void uiMsgBox(uiWindow *parent, const char *title, const char *description); _UI_EXTERN void uiMsgBoxError(uiWindow *parent, const char *title, const char *description); diff --git a/unix/stddialogs.c b/unix/stddialogs.c index 93302f75..854baacb 100644 --- a/unix/stddialogs.c +++ b/unix/stddialogs.c @@ -4,20 +4,58 @@ // LONGTERM figure out why, and describe, that this is the desired behavior // LONGTERM also point out that font and color buttons also work like this -#define windowWindow(w) (GTK_WINDOW(uiControlHandle(uiControl(w)))) +#define windowWindow(w) ((w)?(GTK_WINDOW(uiControlHandle(uiControl(w)))):NULL) -static char *filedialog(GtkWindow *parent, GtkFileChooserAction mode, const gchar *confirm) +static char *filedialog(GtkWindow *parent, GtkFileChooserAction mode, const gchar *confirm, char* filter) { GtkWidget *fcd; GtkFileChooser *fc; gint response; char *filename; + GtkFileFilter *filter; + gchar _filter[256]; + gchar* fp = &_filter[0]; + gchar* fname; + gchar *j; + int i; + int s; + fcd = gtk_file_chooser_dialog_new(NULL, parent, mode, "_Cancel", GTK_RESPONSE_CANCEL, confirm, GTK_RESPONSE_ACCEPT, NULL); fc = GTK_FILE_CHOOSER(fcd); + + for (i = s = 0; i < 255; i++) { + if (filter[i] == '|' || filter[i] == '\0') { + _filter[i] = '\0'; + if (s & 1) { + filter = gtk_file_filter_new(); + gtk_file_filter_set_name(filter, fname); + for (j = fp; ; j++) { + if (*j == ';') { + *j = '\0'; + gtk_file_filter_add_pattern(filter, fp); + fp = j + 1; + } else if (*j == '\0') { + gtk_file_filter_add_pattern(filter, fp); + break; + } + } + gtk_file_chooser_add_filter(fc, filter); + } else { + fname = fp; + } + fp = &_filter[i + 1]; + s++; + if (s >= 8) break; + if (filter[i] == '\0') break; + } else { + _filter[i] = filter[i]; + } + } + gtk_file_chooser_set_local_only(fc, FALSE); gtk_file_chooser_set_select_multiple(fc, FALSE); gtk_file_chooser_set_show_hidden(fc, TRUE); @@ -33,14 +71,14 @@ static char *filedialog(GtkWindow *parent, GtkFileChooserAction mode, const gcha return filename; } -char *uiOpenFile(uiWindow *parent) +char *uiOpenFile(uiWindow *parent, char* filter) { - return filedialog(windowWindow(parent), GTK_FILE_CHOOSER_ACTION_OPEN, "_Open"); + return filedialog(windowWindow(parent), GTK_FILE_CHOOSER_ACTION_OPEN, "_Open", filter); } -char *uiSaveFile(uiWindow *parent) +char *uiSaveFile(uiWindow *parent, char* filter) { - return filedialog(windowWindow(parent), GTK_FILE_CHOOSER_ACTION_SAVE, "_Save"); + return filedialog(windowWindow(parent), GTK_FILE_CHOOSER_ACTION_SAVE, "_Save", filter); } static void msgbox(GtkWindow *parent, const char *title, const char *description, GtkMessageType type, GtkButtonsType buttons) diff --git a/unix/window.c b/unix/window.c index c5ba2038..83841e7b 100644 --- a/unix/window.c +++ b/unix/window.c @@ -229,7 +229,7 @@ void uiWindowSetMargined(uiWindow *w, int margined) uiprivSetMargined(w->childHolderContainer, w->margined); } -uiWindow *uiNewWindow(const char *title, int width, int height, int hasMenubar) +uiWindow *uiNewWindow(const char *title, int width, int height, int hasMenubar, int resizable) { uiWindow *w; @@ -275,5 +275,7 @@ uiWindow *uiNewWindow(const char *title, int width, int height, int hasMenubar) // TODO we really need to clean this up, especially since see uiWindowDestroy() above g_object_ref(w->widget); + gtk_window_set_resizable(w->window, resizable?TRUE:FALSE); + return w; } diff --git a/windows/stddialogs.cpp b/windows/stddialogs.cpp index c6ac4557..dc349ae2 100644 --- a/windows/stddialogs.cpp +++ b/windows/stddialogs.cpp @@ -14,9 +14,9 @@ // - when a dialog is active, tab navigation in other windows stops working // - when adding uiOpenFolder(), use IFileDialog as well - https://msdn.microsoft.com/en-us/library/windows/desktop/bb762115%28v=vs.85%29.aspx -#define windowHWND(w) ((HWND) uiControlHandle(uiControl(w))) +#define windowHWND(w) (w ? (HWND) uiControlHandle(uiControl(w)) : NULL) -char *commonItemDialog(HWND parent, REFCLSID clsid, REFIID iid, FILEOPENDIALOGOPTIONS optsadd) +char *commonItemDialog(HWND parent, REFCLSID clsid, REFIID iid, char* filter, FILEOPENDIALOGOPTIONS optsadd) { IFileDialog *d = NULL; FILEOPENDIALOGOPTIONS opts; @@ -25,6 +25,13 @@ char *commonItemDialog(HWND parent, REFCLSID clsid, REFIID iid, FILEOPENDIALOGOP char *name = NULL; HRESULT hr; + COMDLG_FILTERSPEC filterspec[8]; + wchar_t _filter[256]; + wchar_t* fp = &_filter[0]; + wchar_t* fname; + int i; + int s = 0; + hr = CoCreateInstance(clsid, NULL, CLSCTX_INPROC_SERVER, iid, (LPVOID *) (&d)); @@ -46,6 +53,26 @@ char *commonItemDialog(HWND parent, REFCLSID clsid, REFIID iid, FILEOPENDIALOGOP logHRESULT(L"error setting options", hr); goto out; } + + for (i = s = 0; i < 255; i++) { + if (filter[i] == '|' || filter[i] == '\0') { + _filter[i] = '\0'; + if (s & 1) { + filterspec[s>>1].pszName = fname; + filterspec[s>>1].pszSpec = fp; + } else { + fname = fp; + } + fp = &_filter[i + 1]; + s++; + if (s >= 8) break; + if (filter[i] == '\0') break; + } else { + _filter[i] = filter[i]; + } + } + d->SetFileTypes(s >> 1, filterspec); + hr = d->Show(parent); if (hr == HRESULT_FROM_WIN32(ERROR_CANCELLED)) // cancelled; return NULL like we have ready @@ -76,26 +103,28 @@ out: return name; } -char *uiOpenFile(uiWindow *parent) +char *uiOpenFile(uiWindow *parent, char* filter) { char *res; disableAllWindowsExcept(parent); res = commonItemDialog(windowHWND(parent), CLSID_FileOpenDialog, IID_IFileOpenDialog, - FOS_NOCHANGEDIR | FOS_ALLNONSTORAGEITEMS | FOS_NOVALIDATE | FOS_PATHMUSTEXIST | FOS_FILEMUSTEXIST | FOS_SHAREAWARE | FOS_NOTESTFILECREATE | FOS_NODEREFERENCELINKS | FOS_FORCESHOWHIDDEN | FOS_DEFAULTNOMINIMODE); + filter, + FOS_NOCHANGEDIR | FOS_FORCEFILESYSTEM | FOS_NOVALIDATE | FOS_PATHMUSTEXIST | FOS_FILEMUSTEXIST | FOS_SHAREAWARE | FOS_NOTESTFILECREATE | FOS_FORCESHOWHIDDEN | FOS_DEFAULTNOMINIMODE); enableAllWindowsExcept(parent); return res; } -char *uiSaveFile(uiWindow *parent) +char *uiSaveFile(uiWindow *parent, char* filter) { char *res; disableAllWindowsExcept(parent); res = commonItemDialog(windowHWND(parent), CLSID_FileSaveDialog, IID_IFileSaveDialog, - FOS_OVERWRITEPROMPT | FOS_NOCHANGEDIR | FOS_ALLNONSTORAGEITEMS | FOS_NOVALIDATE | FOS_SHAREAWARE | FOS_NOTESTFILECREATE | FOS_NODEREFERENCELINKS | FOS_FORCESHOWHIDDEN | FOS_DEFAULTNOMINIMODE); + filter, + FOS_OVERWRITEPROMPT | FOS_NOCHANGEDIR | FOS_FORCEFILESYSTEM | FOS_NOVALIDATE | FOS_SHAREAWARE | FOS_NOTESTFILECREATE | FOS_FORCESHOWHIDDEN | FOS_DEFAULTNOMINIMODE); enableAllWindowsExcept(parent); return res; } diff --git a/windows/window.cpp b/windows/window.cpp index 2ea5b7ce..ef2933a2 100644 --- a/windows/window.cpp +++ b/windows/window.cpp @@ -452,7 +452,7 @@ static void setClientSize(uiWindow *w, int width, int height, BOOL hasMenubar, D logLastError(L"error resizing window"); } -uiWindow *uiNewWindow(const char *title, int width, int height, int hasMenubar) +uiWindow *uiNewWindow(const char *title, int width, int height, int hasMenubar, int resizable) { uiWindow *w; WCHAR *wtitle; @@ -465,8 +465,11 @@ uiWindow *uiNewWindow(const char *title, int width, int height, int hasMenubar) hasMenubarBOOL = TRUE; w->hasMenubar = hasMenubarBOOL; -#define style WS_OVERLAPPEDWINDOW -#define exstyle 0 + int style = WS_OVERLAPPEDWINDOW; + int exstyle = 0; + + if (!resizable) + style &= ~(WS_THICKFRAME | WS_MAXIMIZEBOX); wtitle = toUTF16(title); w->hwnd = CreateWindowExW(exstyle,