diff --git a/lib/interfaces/renderer.go b/lib/interfaces/renderer.go index f8d127ba1..b487d2e38 100644 --- a/lib/interfaces/renderer.go +++ b/lib/interfaces/renderer.go @@ -17,9 +17,9 @@ type Renderer interface { NotifyEvent(eventData *messages.EventData) error // Dialog Runtime - SelectFile() string + SelectFile(filter string) string SelectDirectory() string - SelectSaveFile() string + SelectSaveFile(filter string) string // Window Runtime SetColour(string) error diff --git a/lib/renderer/bridge/bridge.go b/lib/renderer/bridge/bridge.go index 85a9cfd99..af827f25f 100644 --- a/lib/renderer/bridge/bridge.go +++ b/lib/renderer/bridge/bridge.go @@ -114,7 +114,7 @@ func (h *Bridge) NewBinding(methodName string) error { // SelectFile is unsupported for Bridge but required // for the Renderer interface -func (h *Bridge) SelectFile() string { +func (h *Bridge) SelectFile(filter string) string { h.log.Warn("SelectFile() unsupported in bridge mode") return "" } @@ -128,7 +128,7 @@ func (h *Bridge) SelectDirectory() string { // SelectSaveFile is unsupported for Bridge but required // for the Renderer interface -func (h *Bridge) SelectSaveFile() string { +func (h *Bridge) SelectSaveFile(filter string) string { h.log.Warn("SelectSaveFile() unsupported in bridge mode") return "" } diff --git a/lib/renderer/webview.go b/lib/renderer/webview.go index 6589d0fb3..583f58cbb 100644 --- a/lib/renderer/webview.go +++ b/lib/renderer/webview.go @@ -245,7 +245,7 @@ func (w *WebView) NewBinding(methodName string) error { } // SelectFile opens a dialog that allows the user to select a file -func (w *WebView) SelectFile() string { +func (w *WebView) SelectFile(filter string) string { var result string // We need to run this on the main thread, however Dispatch is @@ -255,7 +255,7 @@ func (w *WebView) SelectFile() string { wg.Add(1) go func() { w.window.Dispatch(func() { - result = w.window.Dialog(wv.DialogTypeOpen, 0, "Select File", "") + result = w.window.Dialog(wv.DialogTypeOpen, 0, "Select File", "", filter) wg.Done() }) }() @@ -273,7 +273,7 @@ func (w *WebView) SelectDirectory() string { wg.Add(1) go func() { w.window.Dispatch(func() { - result = w.window.Dialog(wv.DialogTypeOpen, wv.DialogFlagDirectory, "Select Directory", "") + result = w.window.Dialog(wv.DialogTypeOpen, wv.DialogFlagDirectory, "Select Directory", "", "") wg.Done() }) }() @@ -282,7 +282,7 @@ func (w *WebView) SelectDirectory() string { } // SelectSaveFile opens a dialog that allows the user to select a file to save -func (w *WebView) SelectSaveFile() string { +func (w *WebView) SelectSaveFile(filter string) string { var result string // We need to run this on the main thread, however Dispatch is // non-blocking so we launch this in a goroutine and wait for @@ -291,7 +291,7 @@ func (w *WebView) SelectSaveFile() string { wg.Add(1) go func() { w.window.Dispatch(func() { - result = w.window.Dialog(wv.DialogTypeSave, 0, "Save file", "") + result = w.window.Dialog(wv.DialogTypeSave, 0, "Save file", "", filter) wg.Done() }) }() diff --git a/lib/renderer/webview/webview.go b/lib/renderer/webview/webview.go index cb302e97f..f8ac2b706 100755 --- a/lib/renderer/webview/webview.go +++ b/lib/renderer/webview/webview.go @@ -74,9 +74,9 @@ static inline void CgoWebViewSetColor(void *w, uint8_t r, uint8_t g, uint8_t b, } static inline void CgoDialog(void *w, int dlgtype, int flags, - char *title, char *arg, char *res, size_t ressz) { +char *title, char *arg, char *res, size_t ressz, char *filter) { webview_dialog(w, dlgtype, flags, - (const char*)title, (const char*) arg, res, ressz); + (const char*)title, (const char*) arg, res, ressz, filter); } static inline int CgoWebViewEval(void *w, char *js) { @@ -186,7 +186,7 @@ type WebView interface { // Dialog() opens a system dialog of the given type and title. String // argument can be provided for certain dialogs, such as alert boxes. For // alert boxes argument is a message inside the dialog box. - Dialog(dlgType DialogType, flags int, title string, arg string) string + Dialog(dlgType DialogType, flags int, title string, arg string, filter string) string // Terminate() breaks the main UI loop. This method must be called from the main thread // only. See Dispatch() for more details. Terminate() @@ -311,7 +311,7 @@ func (w *webview) SetFullscreen(fullscreen bool) { C.CgoWebViewSetFullscreen(w.w, C.int(boolToInt(fullscreen))) } -func (w *webview) Dialog(dlgType DialogType, flags int, title string, arg string) string { +func (w *webview) Dialog(dlgType DialogType, flags int, title string, arg string, filter string) string { const maxPath = 4096 titlePtr := C.CString(title) defer C.free(unsafe.Pointer(titlePtr)) @@ -319,8 +319,10 @@ func (w *webview) Dialog(dlgType DialogType, flags int, title string, arg string defer C.free(unsafe.Pointer(argPtr)) resultPtr := (*C.char)(C.calloc((C.size_t)(unsafe.Sizeof((*C.char)(nil))), (C.size_t)(maxPath))) defer C.free(unsafe.Pointer(resultPtr)) + filterPtr := C.CString(filter) + defer C.free(unsafe.Pointer(filterPtr)) C.CgoDialog(w.w, C.int(dlgType), C.int(flags), titlePtr, - argPtr, resultPtr, C.size_t(maxPath)) + argPtr, resultPtr, C.size_t(maxPath), filterPtr) return C.GoString(resultPtr) } diff --git a/lib/renderer/webview/webview.h b/lib/renderer/webview/webview.h index 9d4761ca3..5b18dc7f7 100644 --- a/lib/renderer/webview/webview.h +++ b/lib/renderer/webview/webview.h @@ -174,7 +174,7 @@ struct webview_priv WEBVIEW_API void webview_dialog(struct webview *w, enum webview_dialog_type dlgtype, int flags, const char *title, const char *arg, - char *result, size_t resultsz); + char *result, size_t resultsz, char *filter); WEBVIEW_API void webview_dispatch(struct webview *w, webview_dispatch_fn fn, void *arg); WEBVIEW_API void webview_terminate(struct webview *w); @@ -418,7 +418,7 @@ struct webview_priv WEBVIEW_API void webview_dialog(struct webview *w, enum webview_dialog_type dlgtype, int flags, const char *title, const char *arg, - char *result, size_t resultsz) + char *result, size_t resultsz, char *filter) { GtkWidget *dlg; if (result != NULL) @@ -438,6 +438,16 @@ struct webview_priv "_Cancel", GTK_RESPONSE_CANCEL, (dlgtype == WEBVIEW_DIALOG_TYPE_OPEN ? "_Open" : "_Save"), GTK_RESPONSE_ACCEPT, NULL); + if (filter[0] != '\0') { + GtkFileFilter *file_filter = gtk_file_filter_new(); + gchar **filters = g_strsplit(filter, ",", -1); + gint i; + for(i = 0; filters && filters[i]; i++) { + gtk_file_filter_add_pattern(file_filter, filters[i]); + } + gtk_file_filter_set_name(file_filter, filter); + gtk_file_chooser_add_filter(GTK_FILE_CHOOSER(dlg), file_filter); + } gtk_file_chooser_set_local_only(GTK_FILE_CHOOSER(dlg), FALSE); gtk_file_chooser_set_select_multiple(GTK_FILE_CHOOSER(dlg), FALSE); gtk_file_chooser_set_show_hidden(GTK_FILE_CHOOSER(dlg), TRUE); diff --git a/runtime/dialog.go b/runtime/dialog.go index b29182637..642b55d2c 100644 --- a/runtime/dialog.go +++ b/runtime/dialog.go @@ -15,8 +15,12 @@ func NewDialog(renderer interfaces.Renderer) *Dialog { } // SelectFile prompts the user to select a file -func (r *Dialog) SelectFile() string { - return r.renderer.SelectFile() +func (r *Dialog) SelectFile(params ...string) string { + filter := "" + if len(params) > 0 { + filter = params[0] + } + return r.renderer.SelectFile(filter) } // SelectDirectory prompts the user to select a directory @@ -25,6 +29,10 @@ func (r *Dialog) SelectDirectory() string { } // SelectSaveFile prompts the user to select a file for saving -func (r *Dialog) SelectSaveFile() string { - return r.renderer.SelectSaveFile() +func (r *Dialog) SelectSaveFile(params ...string) string { + filter := "" + if len(params) > 0 { + filter = params[0] + } + return r.renderer.SelectSaveFile(filter) }