mirror of
https://github.com/make-42/hayai.git
synced 2025-01-19 02:47:35 +01:00
122 lines
3.9 KiB
Go
122 lines
3.9 KiB
Go
package dialog
|
|
|
|
// #cgo pkg-config: gtk+-3.0
|
|
// #cgo LDFLAGS: -lX11
|
|
// #include <X11/Xlib.h>
|
|
// #include <gtk/gtk.h>
|
|
// #include <stdlib.h>
|
|
// static GtkWidget* msgdlg(GtkWindow *parent, GtkDialogFlags flags, GtkMessageType type, GtkButtonsType buttons, char *msg) {
|
|
// return gtk_message_dialog_new(parent, flags, type, buttons, "%s", msg);
|
|
// }
|
|
// static GtkWidget* filedlg(char *title, GtkWindow *parent, GtkFileChooserAction action, char* acceptText) {
|
|
// return gtk_file_chooser_dialog_new(title, parent, action, "Cancel", GTK_RESPONSE_CANCEL, acceptText, GTK_RESPONSE_ACCEPT, NULL);
|
|
// }
|
|
import "C"
|
|
import "unsafe"
|
|
|
|
var initSuccess bool
|
|
|
|
func init() {
|
|
C.XInitThreads()
|
|
initSuccess = (C.gtk_init_check(nil, nil) == C.TRUE)
|
|
}
|
|
|
|
func checkStatus() {
|
|
if !initSuccess {
|
|
panic("gtk initialisation failed; presumably no X server is available")
|
|
}
|
|
}
|
|
|
|
func closeDialog(dlg *C.GtkWidget) {
|
|
C.gtk_widget_destroy(dlg)
|
|
/* The Destroy call itself isn't enough to remove the dialog from the screen; apparently
|
|
** that happens once the GTK main loop processes some further events. But if we're
|
|
** in a non-GTK app the main loop isn't running, so we empty the event queue before
|
|
** returning from the dialog functions.
|
|
** Not sure how this interacts with an actual GTK app... */
|
|
for C.gtk_events_pending() != 0 {
|
|
C.gtk_main_iteration()
|
|
}
|
|
}
|
|
|
|
func runMsgDlg(defaultTitle string, flags C.GtkDialogFlags, msgtype C.GtkMessageType, buttons C.GtkButtonsType, b *MsgBuilder) C.gint {
|
|
checkStatus()
|
|
cmsg := C.CString(b.Msg)
|
|
defer C.free(unsafe.Pointer(cmsg))
|
|
dlg := C.msgdlg(nil, flags, msgtype, buttons, cmsg)
|
|
ctitle := C.CString(firstOf(b.Dlg.Title, defaultTitle))
|
|
defer C.free(unsafe.Pointer(ctitle))
|
|
C.gtk_window_set_title((*C.GtkWindow)(unsafe.Pointer(dlg)), ctitle)
|
|
defer closeDialog(dlg)
|
|
return C.gtk_dialog_run((*C.GtkDialog)(unsafe.Pointer(dlg)))
|
|
}
|
|
|
|
func (b *MsgBuilder) yesNo() bool {
|
|
return runMsgDlg("Confirm?", 0, C.GTK_MESSAGE_QUESTION, C.GTK_BUTTONS_YES_NO, b) == C.GTK_RESPONSE_YES
|
|
}
|
|
|
|
func (b *MsgBuilder) info() {
|
|
runMsgDlg("Information", 0, C.GTK_MESSAGE_INFO, C.GTK_BUTTONS_OK, b)
|
|
}
|
|
|
|
func (b *MsgBuilder) error() {
|
|
runMsgDlg("Error", 0, C.GTK_MESSAGE_ERROR, C.GTK_BUTTONS_OK, b)
|
|
}
|
|
|
|
func (b *FileBuilder) load() (string, error) {
|
|
return chooseFile("Open File", "Open", C.GTK_FILE_CHOOSER_ACTION_OPEN, b)
|
|
}
|
|
|
|
func (b *FileBuilder) save() (string, error) {
|
|
f, err := chooseFile("Save File", "Save", C.GTK_FILE_CHOOSER_ACTION_SAVE, b)
|
|
if err != nil {
|
|
return "", err
|
|
}
|
|
return f, nil
|
|
}
|
|
|
|
func chooseFile(title string, buttonText string, action C.GtkFileChooserAction, b *FileBuilder) (string, error) {
|
|
checkStatus()
|
|
ctitle := C.CString(title)
|
|
defer C.free(unsafe.Pointer(ctitle))
|
|
cbuttonText := C.CString(buttonText)
|
|
defer C.free(unsafe.Pointer(cbuttonText))
|
|
dlg := C.filedlg(ctitle, nil, action, cbuttonText)
|
|
fdlg := (*C.GtkFileChooser)(unsafe.Pointer(dlg))
|
|
|
|
for _, filt := range b.Filters {
|
|
filter := C.gtk_file_filter_new()
|
|
cdesc := C.CString(filt.Desc)
|
|
defer C.free(unsafe.Pointer(cdesc))
|
|
C.gtk_file_filter_set_name(filter, cdesc)
|
|
|
|
for _, ext := range filt.Extensions {
|
|
cpattern := C.CString("*." + ext)
|
|
defer C.free(unsafe.Pointer(cpattern))
|
|
C.gtk_file_filter_add_pattern(filter, cpattern)
|
|
}
|
|
C.gtk_file_chooser_add_filter(fdlg, filter)
|
|
}
|
|
if b.StartDir != "" {
|
|
cdir := C.CString(b.StartDir)
|
|
defer C.free(unsafe.Pointer(cdir))
|
|
C.gtk_file_chooser_set_current_folder(fdlg, cdir)
|
|
}
|
|
if b.StartFile != "" {
|
|
cfile := C.CString(b.StartFile)
|
|
defer C.free(unsafe.Pointer(cfile))
|
|
C.gtk_file_chooser_set_current_name(fdlg, cfile)
|
|
}
|
|
C.gtk_file_chooser_set_do_overwrite_confirmation(fdlg, C.TRUE)
|
|
r := C.gtk_dialog_run((*C.GtkDialog)(unsafe.Pointer(dlg)))
|
|
defer closeDialog(dlg)
|
|
if r == C.GTK_RESPONSE_ACCEPT {
|
|
return C.GoString(C.gtk_file_chooser_get_filename(fdlg)), nil
|
|
}
|
|
return "", ErrCancelled
|
|
}
|
|
|
|
func (b *DirectoryBuilder) browse() (string, error) {
|
|
return chooseFile("Open Folder", "Open", C.GTK_FILE_CHOOSER_ACTION_SELECT_FOLDER, &FileBuilder{Dlg: b.Dlg})
|
|
}
|