summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPietro Gagliardi <[email protected]>2014-03-15 14:27:18 -0400
committerPietro Gagliardi <[email protected]>2014-03-15 14:27:18 -0400
commite429b8d6b82f6caf9301e9917e96d7f823dd90bd (patch)
tree6322c374460fe1b24debcd9ac61197de8141f0b6
parent05905e3addd522b7c7d41a4ac6cfefbef52ab546 (diff)
Allowed GTK+ windows to be resized smaller than the size request of the controls within.
-rw-r--r--gtkcalls_unix.go22
-rw-r--r--gtkcasts_unix.go6
-rw-r--r--implementation.md2
-rw-r--r--sysdata_unix.go6
-rw-r--r--todo.md2
5 files changed, 26 insertions, 12 deletions
diff --git a/gtkcalls_unix.go b/gtkcalls_unix.go
index f2bce9e..39effe1 100644
--- a/gtkcalls_unix.go
+++ b/gtkcalls_unix.go
@@ -66,16 +66,30 @@ func gtk_window_get_size(window *gtkWidget) (int, int) {
return int(width), int(height)
}
-func gtk_fixed_new() *gtkWidget {
- return fromgtkwidget(C.gtk_fixed_new())
+// this should allow us to resize the window arbitrarily
+// thanks to Company in irc.gimp.net/#gtk+
+func gtkNewWindowLayout() *gtkWidget {
+ layout := C.gtk_layout_new(nil, nil)
+ scrollarea := C.gtk_scrolled_window_new((*C.GtkAdjustment)(nil), (*C.GtkAdjustment)(nil))
+ C.gtk_container_add((*C.GtkContainer)(unsafe.Pointer(scrollarea)), layout)
+ // never show scrollbars; we're just doing this to allow arbitrary resizes
+ C.gtk_scrolled_window_set_policy((*C.GtkScrolledWindow)(unsafe.Pointer(scrollarea)),
+ C.GTK_POLICY_NEVER, C.GTK_POLICY_NEVER)
+ return fromgtkwidget(scrollarea)
}
func gtk_container_add(container *gtkWidget, widget *gtkWidget) {
C.gtk_container_add(togtkcontainer(container), togtkwidget(widget))
}
-func gtk_fixed_move(container *gtkWidget, widget *gtkWidget, x int, y int) {
- C.gtk_fixed_move(togtkfixed(container), togtkwidget(widget),
+func gtkAddWidgetToLayout(container *gtkWidget, widget *gtkWidget) {
+ layout := C.gtk_bin_get_child((*C.GtkBin)(unsafe.Pointer(container)))
+ C.gtk_container_add((*C.GtkContainer)(unsafe.Pointer(layout)), togtkwidget(widget))
+}
+
+func gtkMoveWidgetInLayout(container *gtkWidget, widget *gtkWidget, x int, y int) {
+ layout := C.gtk_bin_get_child((*C.GtkBin)(unsafe.Pointer(container)))
+ C.gtk_layout_move((*C.GtkLayout)(unsafe.Pointer(layout)), togtkwidget(widget),
C.gint(x), C.gint(y))
}
diff --git a/gtkcasts_unix.go b/gtkcasts_unix.go
index 09ba9ef..b459c46 100644
--- a/gtkcasts_unix.go
+++ b/gtkcasts_unix.go
@@ -61,12 +61,12 @@ func togtkcontainer(what *gtkWidget) *C.GtkContainer {
return (*C.GtkContainer)(unsafe.Pointer(what))
}
-func fromgtkfixed(x *C.GtkFixed) *gtkWidget {
+func fromgtklayout(x *C.GtkLayout) *gtkWidget {
return (*gtkWidget)(unsafe.Pointer(x))
}
-func togtkfixed(what *gtkWidget) *C.GtkFixed {
- return (*C.GtkFixed)(unsafe.Pointer(what))
+func togtklayout(what *gtkWidget) *C.GtkLayout {
+ return (*C.GtkLayout)(unsafe.Pointer(what))
}
func fromgtkbutton(x *C.GtkButton) *gtkWidget {
diff --git a/implementation.md b/implementation.md
index 2bd4232..800ce3a 100644
--- a/implementation.md
+++ b/implementation.md
@@ -47,7 +47,7 @@ GTK+ is strange: there are constructor functions that return `GtkWidget *`, but
As the GTK+ main loop system does not quite run in a sane way (it allows recursion, and the `gtk_main_loop_iteration_do` function only onperates on the innermost call), we cannot use the `for`/`select` template for `ui()`. Fortunately, GDK provides gdk_threads_add_idle(), which allows us to run, and optionally (and importantly) run only once, a function on the `gtk_main()` thread when not processing events. We use this, combined with a goroutine for dispatching, to handle `uitask` requests. See `our_idle_callback` in callbacks_unix.go for details.
-GTK+ layout managers are not used since the UI library's layout managers are coded in a portable way. (`GtkFixed` is used instead.) This isn't ideal, but it works for now.
+GTK+ layout managers are not used since the UI library's layout managers are coded in a portable way. (A `GtkLayout` in a `GtkScrolledWindow` is used instead. This is done instead of just a `GtkFixed` so that a window can be resized smaller than the size requests of its contents.) This isn't ideal, but it works for now.
All event handlers take the `sysData` as their user data parameter; this means all the event-handling code is stored in static functions in callbacks_unix.go. (Early versions of the package generated signal handlers for each control on the fly, but this needed to be changed to accommodoate Area, which not only needs the `sysData` but also needs to connect to a subwidget of a subwidget (specifically the subwidget of the `GtkViewport` of a `GtkScrolledWindow`); the current setup also avoids creating closures for each and every Window and Button created, and also means we can stop having to shove those callbacks in an ever-growing slice to prevent them from being garbage collected.) Should the widget actually be a child widget of a `GtkScrolledWindow`, the `child` function and `childsigs` signal list are used to assign signals as well.
diff --git a/sysdata_unix.go b/sysdata_unix.go
index 8d753da..e9c507a 100644
--- a/sysdata_unix.go
+++ b/sysdata_unix.go
@@ -117,7 +117,7 @@ func (s *sysData) make(initText string, window *sysData) error {
s.widget = <-ret
if window == nil {
uitask <- func() {
- fixed := gtk_fixed_new()
+ fixed := gtkNewWindowLayout()
gtk_container_add(s.widget, fixed)
// TODO return the container before assigning the signals?
for signame, sigfunc := range ct.signals {
@@ -129,7 +129,7 @@ func (s *sysData) make(initText string, window *sysData) error {
} else {
s.container = window.container
uitask <- func() {
- gtk_container_add(s.container, s.widget)
+ gtkAddWidgetToLayout(s.container, s.widget)
for signame, sigfunc := range ct.signals {
g_signal_connect(s.widget, signame, sigfunc, s)
}
@@ -187,7 +187,7 @@ func (s *sysData) setText(text string) {
}
func (s *sysData) setRect(x int, y int, width int, height int, winheight int) error {
- gtk_fixed_move(s.container, s.widget, x, y)
+ gtkMoveWidgetInLayout(s.container, s.widget, x, y)
gtk_widget_set_size_request(s.widget, width, height)
return nil
}
diff --git a/todo.md b/todo.md
index e5e40ab..3d12c2a 100644
--- a/todo.md
+++ b/todo.md
@@ -45,7 +45,6 @@ important things:
- make gcc (Unix)/clang (Mac OS X) pedantic about warnings/errors; also -Werror
- make sure scrollbars in Listbox work identically on all platforms (specifically the existence and autohiding of both horizontal and vertical scrollbars)
- pin down this behavior; also note non-editability
-- GTK+ windows cannot be resized smaller than their controls's current sizes in their current positions; find out how to overrule that so they can be freely resized
- the size of Listboxes on Windows does not fill the requested space completely (wait, wasn't there a style that governed this?)
super ultra important things:
@@ -74,6 +73,7 @@ super ultra important things:
- frame sizes are a bit of a hack: the preferred size of a NSScrollView is the preferred size of its document view; the frameSize method described on the above link might be better but a real solution is optimal
- make sure the image drawn on an Area looks correct on all platforms (is not cropped incorrectly or blurred)
- GTK+: requested clip rect seems to be larger than the size of the Area (also larger than the visible portion? TODO)
+- when resizing a GTK+ window smaller than a certain size, the controls inside will start clipping in bizarre ways (progress bars/entry lines will just cut off; editable comboboxes will stretch slightly longer than noneditable ones; the horizontal scrollbar in Area will disappear smoothly; etc.)
important things:
- make specific wording in documentation consistent (make/create, etc.)