diff --git a/newctrl/window_unix.go b/newctrl/window_unix.go new file mode 100644 index 0000000..6b15bc1 --- /dev/null +++ b/newctrl/window_unix.go @@ -0,0 +1,116 @@ +// +build !windows,!darwin + +// 7 july 2014 + +package ui + +import ( + "unsafe" +) + +// #include "gtk_unix.h" +// extern gboolean windowClosing(GtkWidget *, GdkEvent *, gpointer); +// extern void windowResized(GtkWidget *, GdkRectangle *, gpointer); +import "C" + +type window struct { + widget *C.GtkWidget + wc *C.GtkContainer + bin *C.GtkBin + window *C.GtkWindow + + group *C.GtkWindowGroup + + closing *event + + child Control + container *container + + margined bool +} + +func newWindow(title string, width int, height int, control Control) *window { + widget := C.gtk_window_new(C.GTK_WINDOW_TOPLEVEL) + ctitle := togstr(title) + defer freegstr(ctitle) + w := &window{ + widget: widget, + wc: (*C.GtkContainer)(unsafe.Pointer(widget)), + bin: (*C.GtkBin)(unsafe.Pointer(widget)), + window: (*C.GtkWindow)(unsafe.Pointer(widget)), + closing: newEvent(), + child: control, + } + C.gtk_window_set_title(w.window, ctitle) + g_signal_connect( + C.gpointer(unsafe.Pointer(w.window)), + "delete-event", + C.GCallback(C.windowClosing), + C.gpointer(unsafe.Pointer(w))) + C.gtk_window_resize(w.window, C.gint(width), C.gint(height)) + w.container = newContainer() + w.child.setParent(w.container.parent()) + w.container.setParent(&controlParent{w.wc}) + // notice that we connect this to the container + g_signal_connect_after( // so we get it after the child container has been allocated + C.gpointer(unsafe.Pointer(w.container.widget)), + "size-allocate", + C.GCallback(C.windowResized), + C.gpointer(unsafe.Pointer(w))) + // for dialogs; otherwise, they will be modal to all windows, not just this one + w.group = C.gtk_window_group_new() + C.gtk_window_group_add_window(w.group, w.window) + return w +} + +func (w *window) Title() string { + return fromgstr(C.gtk_window_get_title(w.window)) +} + +func (w *window) SetTitle(title string) { + ctitle := togstr(title) + defer freegstr(ctitle) + C.gtk_window_set_title(w.window, ctitle) +} + +func (w *window) Show() { + C.gtk_widget_show_all(w.widget) +} + +func (w *window) Hide() { + C.gtk_widget_hide(w.widget) +} + +func (w *window) Close() { + C.gtk_widget_destroy(w.widget) +} + +func (w *window) OnClosing(e func() bool) { + w.closing.setbool(e) +} + +func (w *window) Margined() bool { + return w.margined +} + +func (w *window) SetMargined(margined bool) { + w.margined = margined +} + +//export windowClosing +func windowClosing(wid *C.GtkWidget, e *C.GdkEvent, data C.gpointer) C.gboolean { + w := (*window)(unsafe.Pointer(data)) + close := w.closing.fire() + if close { + return C.GDK_EVENT_PROPAGATE // will do gtk_widget_destroy(), which is what we want (thanks ebassi in irc.gimp.net/#gtk+) + } + return C.GDK_EVENT_STOP // keeps window alive +} + +//export windowResized +func windowResized(wid *C.GtkWidget, r *C.GdkRectangle, data C.gpointer) { + w := (*window)(unsafe.Pointer(data)) + a := w.container.allocation(w.margined) + d := w.beginResize() + w.child.resize(int(a.x), int(a.y), int(a.width), int(a.height), d) +}