From 4a68c3cb7a984d144378c683e7587dadd5ebe62f Mon Sep 17 00:00:00 2001 From: Pietro Gagliardi Date: Wed, 25 Jun 2014 23:44:22 -0400 Subject: [PATCH] Applied the new control sizing system to the GTK+ backend. --- callbacks_unix.go | 6 ++-- controlsize_unix.go | 78 +++++++++++++++++++++++++++++++++++++++++++++ gtkcalls_unix.go | 8 +++-- prefsize_unix.go | 24 -------------- todo.md | 7 ++-- 5 files changed, 89 insertions(+), 34 deletions(-) create mode 100644 controlsize_unix.go delete mode 100644 prefsize_unix.go diff --git a/callbacks_unix.go b/callbacks_unix.go index f66be7c..ff3e3b9 100644 --- a/callbacks_unix.go +++ b/callbacks_unix.go @@ -37,10 +37,10 @@ var window_delete_event_callback = C.GCallback(C.our_window_delete_event_callbac func our_window_configure_event_callback(widget *C.GtkWidget, event *C.GdkEvent, what C.gpointer) C.gboolean { // called when the window is resized s := (*sysData)(unsafe.Pointer(what)) - if s.container != nil && s.resize != nil { // wait for init + if s.container != nil && s.allocate != nil { // wait for init width, height := gtk_window_get_size(s.widget) - // top-left is (0,0) so no need for winheight - s.doResize(0, 0, width, height, 0) + // top-left is (0,0) here + s.resizeWindow(width, height) } // no need to manually redraw everything: since we use gtk_widget_set_size_request(), that queues both resize and redraw for us (thanks Company in irc.gimp.net/#gtk+) return C.FALSE // continue the event chain diff --git a/controlsize_unix.go b/controlsize_unix.go new file mode 100644 index 0000000..5ea7bf7 --- /dev/null +++ b/controlsize_unix.go @@ -0,0 +1,78 @@ +// +build !windows,!darwin,!plan9 + +// 23 february 2014 + +package ui + +type sysSizeData struct { + cSysSizeData + + // for size calculations + // gtk+ needs nothing + + // for the actual resizing + shouldVAlignTop bool +} + +const ( + gtkXMargin = 12 + gtkYMargin = 12 + gtkXPadding = 12 + gtkYPadding = 6 +) + +func (s *sysData) beginResize() (d *sysSizeData) { + d = new(sysSizeData) + if s.spaced { + d.xmargin = gtkXMargin + d.ymargin = gtkYMargin + d.xpadding = gtkXPadding + d.ypadding = gtkYPadding + } + return d +} + +func (s *sysData) endResize(d *sysSizeData) { + // redraw +} + +func (s *sysData) translateAllocationCoords(allocations []*allocation, winwidth, winheight int) { + // no need for coordinate conversion with gtk+ +} + +func (s *sysData) commitResize(c *allocation, d *sysSizeData) { + if s.ctype == c_label && !s.alternate && c.neighbor != nil { + c.neighbor.getAuxResizeInfo(d) + if d.shouldVAlignTop { + // TODO should it be center-aligned to the first line or not + gtk_misc_set_alignment(s.widget, 0, 0) + } else { + gtk_misc_set_alignment(s.widget, 0, 0.5) + } + } + // TODO merge this here + s.setRect(c.x, c.y, c.width, c.height, 0) +} + +func (s *sysData) getAuxResizeInfo(d *sysSizeData) { + d.shouldVAlignTop = (s.ctype == c_listbox) || (s.ctype == c_area) +} + +// GTK+ 3 makes this easy: controls can tell us what their preferred size is! +// ...actually, it tells us two things: the "minimum size" and the "natural size". +// The "minimum size" is the smallest size we /can/ display /anything/. The "natural size" is the smallest size we would /prefer/ to display. +// The difference? Minimum size takes into account things like truncation with ellipses: the minimum size of a label can allot just the ellipses! +// So we use the natural size instead. +// There is a warning about height-for-width controls, but in my tests this isn't an issue. +// For Areas, we manually save the Area size and use that, just to be safe. + +// We don't need to worry about y-offset because label alignment is "vertically center", which GtkLabel does for us. + +func (s *sysData) preferredSize(d *sysSizeData) (width int, height int) { + if s.ctype == c_area { + return s.areawidth, s.areaheight + } + + _, _, width, height = gtk_widget_get_preferred_size(s.widget) + return width, height +} diff --git a/gtkcalls_unix.go b/gtkcalls_unix.go index fdd3d61..766c3fe 100644 --- a/gtkcalls_unix.go +++ b/gtkcalls_unix.go @@ -239,6 +239,10 @@ func gtk_entry_get_text(widget *C.GtkWidget) string { var _emptystring = [1]C.gchar{0} var emptystring = &_emptystring[0] +func gtk_misc_set_alignment(widget *C.GtkWidget, x float64, y float64) { + C.gtk_misc_set_alignment((*C.GtkMisc)(unsafe.Pointer(widget)), C.gfloat(x), C.gfloat(y)) +} + func gtk_label_new() *C.GtkWidget { label := C.gtk_label_new(emptystring) C.gtk_label_set_line_wrap(togtklabel(label), C.FALSE) // turn off line wrap @@ -250,14 +254,14 @@ func gtk_label_new() *C.GtkWidget { // this will valign to the center, which is what the HIG says (https://developer.gnome.org/hig-book/3.4/design-text-labels.html.en) for all controls that label to the side; thankfully this means we don't need to do any extra positioning magic // this will also valign to the top // thanks to mclasen in irc.gimp.net/#gtk+ - C.gtk_misc_set_alignment((*C.GtkMisc)(unsafe.Pointer(label)), 0, 0.5) + gtk_misc_set_alignment(label, 0, 0.5) return label } func gtk_label_new_standalone() *C.GtkWidget { label := gtk_label_new() // this will valign to the top - C.gtk_misc_set_alignment((*C.GtkMisc)(unsafe.Pointer(label)), 0, 0) + gtk_misc_set_alignment(label, 0, 0) return label } diff --git a/prefsize_unix.go b/prefsize_unix.go deleted file mode 100644 index 68ea589..0000000 --- a/prefsize_unix.go +++ /dev/null @@ -1,24 +0,0 @@ -// +build !windows,!darwin,!plan9 - -// 23 february 2014 - -package ui - -// GTK+ 3 makes this easy: controls can tell us what their preferred size is! -// ...actually, it tells us two things: the "minimum size" and the "natural size". -// The "minimum size" is the smallest size we /can/ display /anything/. The "natural size" is the smallest size we would /prefer/ to display. -// The difference? Minimum size takes into account things like truncation with ellipses: the minimum size of a label can allot just the ellipses! -// So we use the natural size instead. -// There is a warning about height-for-width controls, but in my tests this isn't an issue. -// For Areas, we manually save the Area size and use that, just to be safe. - -// We don't need to worry about y-offset because label alignment is "vertically center", which GtkLabel does for us. - -func (s *sysData) preferredSize() (width int, height int, yoff int) { - if s.ctype == c_area { - return s.areawidth, s.areaheight, 0 - } - - _, _, width, height = gtk_widget_get_preferred_size(s.widget) - return width, height, 0 -} diff --git a/todo.md b/todo.md index 49b9f96..47856fb 100644 --- a/todo.md +++ b/todo.md @@ -1,10 +1,6 @@ ALL: - vertical alignment of labels is a botch right now - - windows: unilaterally applied; not much tow orry about here though - - gtk: mostly fine, just that list box labels need to be top-aligned - os x: very very wrong - - will need to make yoff a function of a control and its neighbor to the right for this to work - - on gtk+ the yoff function will need to do the text alignment MAC OS X: - NSComboBox scans the entered text to see if it matches one of the items and returns the index of that item if it does; find out how to suppress this so that it returns -1 unless the item was chosen from the list (like the other platforms) @@ -22,7 +18,8 @@ WINDOWS: - control sizing is a MAJOR pain - http://stackoverflow.com/questions/24130548/is-there-a-proper-way-to-get-the-preferred-size-of-windows-controls-there-are-s - redrawing controls after a window resize on Windows does not work properly -- when adding IsDialogMessage() find out if that make sthe area in the area bounds test automatically focused +- when adding IsDialogMessage() find out if that makes the area in the area bounds test automatically focused +- vertical alignment of labels can be wrong (I think; need to check again - TODO) UNIX: - figure out how to detect the alt key and mouse buttons above 5 properly for modifiers/Held[]