Ported over the sizing framework from the old package and implemented it on the GTK+ backend.
This commit is contained in:
parent
1953f2d748
commit
a253f39d68
|
@ -9,7 +9,7 @@ type Control interface {
|
|||
parent(*window)
|
||||
// TODO enable/disable (public)
|
||||
// TODO show/hide (public)
|
||||
// TODO sizing (likely private)
|
||||
controlSizing
|
||||
}
|
||||
|
||||
// Button is a clickable button that performs some task.
|
||||
|
|
|
@ -0,0 +1,48 @@
|
|||
// 25 june 2014
|
||||
|
||||
package ui
|
||||
|
||||
type allocation struct {
|
||||
x int
|
||||
y int
|
||||
width int
|
||||
height int
|
||||
this Control
|
||||
neighbor Control
|
||||
}
|
||||
|
||||
type sizingbase struct {
|
||||
xmargin int
|
||||
ymargin int
|
||||
xpadding int
|
||||
ypadding int
|
||||
}
|
||||
|
||||
// this ensures that all *windows across all platforms contain the necessary functions
|
||||
// if this fails to compile, we have a problem
|
||||
var windowSizeEnsure interface {
|
||||
beginResize() *sizing
|
||||
endResize(*sizing)
|
||||
translateAllocationCoords([]*allocation, int, int)
|
||||
} = &window{}
|
||||
|
||||
type controlSizing interface {
|
||||
allocate(x int, y int, width int, height int, d *sizing) []*allocation
|
||||
preferredSize(*sizing) (int, int)
|
||||
commitResize(*allocation, *sizing)
|
||||
getAuxResizeInfo(*sizing)
|
||||
}
|
||||
|
||||
func (w *window) doresize(width, height int) {
|
||||
if w.child == nil { // no children; nothing to do
|
||||
return
|
||||
}
|
||||
d := w.beginResize()
|
||||
allocations := w.child.allocate(0, 0, width, height, d)
|
||||
w.translateAllocationCoords(allocations, width, height)
|
||||
// move in reverse so as to approximate right->left order so neighbors make sense
|
||||
for i := len(allocations) - 1; i >= 0; i-- {
|
||||
allocations[i].this.commitResize(allocations[i], d)
|
||||
}
|
||||
w.endResize(d)
|
||||
}
|
|
@ -0,0 +1,102 @@
|
|||
// +build !darwin
|
||||
|
||||
// 23 february 2014
|
||||
|
||||
package ui
|
||||
|
||||
// #include "gtk_unix.h"
|
||||
import "C"
|
||||
|
||||
type sizing struct {
|
||||
sizingbase
|
||||
|
||||
// for size calculations
|
||||
// gtk+ needs nothing
|
||||
|
||||
// for the actual resizing
|
||||
shouldVAlignTop bool
|
||||
}
|
||||
|
||||
const (
|
||||
gtkXMargin = 12
|
||||
gtkYMargin = 12
|
||||
gtkXPadding = 12
|
||||
gtkYPadding = 6
|
||||
)
|
||||
|
||||
func (w *window) beginResize() (d *sizing) {
|
||||
d = new(sizing)
|
||||
if w.spaced {
|
||||
d.xmargin = gtkXMargin
|
||||
d.ymargin = gtkYMargin
|
||||
d.xpadding = gtkXPadding
|
||||
d.ypadding = gtkYPadding
|
||||
}
|
||||
return d
|
||||
}
|
||||
|
||||
func (w *window) endResize(d *sizing) {
|
||||
C.gtk_widget_queue_draw(w.widget)
|
||||
}
|
||||
|
||||
func (w *window) translateAllocationCoords(allocations []*allocation, winwidth, winheight int) {
|
||||
// no need for coordinate conversion with gtk+
|
||||
}
|
||||
|
||||
func (w *widgetbase) allocate(x int, y int, width int, height int, d *sizing) []*allocation {
|
||||
return []*allocation{&allocation{
|
||||
x: x,
|
||||
y: y,
|
||||
width: width,
|
||||
height: height,
|
||||
this: w,
|
||||
}}
|
||||
}
|
||||
|
||||
func (w *widgetbase) commitResize(c *allocation, d *sizing) {
|
||||
// TODO
|
||||
/*
|
||||
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 this uses w.parentw directly; change?
|
||||
C.gtk_layout_move(w.parentw.layout, w.widget, C.gint(c.x), C.gint(c.y))
|
||||
C.gtk_widget_set_size_request(w.widget, C.gint(c.width), C.gint(c.height))
|
||||
}
|
||||
|
||||
func (w *widgetbase) getAuxResizeInfo(d *sizing) {
|
||||
//TODO
|
||||
// d.shouldVAlignTop = (s.ctype == c_listbox) || (s.ctype == c_area)
|
||||
d.shouldVAlignTop = false
|
||||
}
|
||||
|
||||
// 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 (w *widgetbase) preferredSize(d *sizing) (width int, height int) {
|
||||
//TODO
|
||||
/*
|
||||
if s.ctype == c_area {
|
||||
return s.areawidth, s.areaheight
|
||||
}
|
||||
*/
|
||||
|
||||
var r C.GtkRequisition
|
||||
|
||||
C.gtk_widget_get_preferred_size(w.widget, nil, &r)
|
||||
return int(r.width), int(r.height)
|
||||
}
|
|
@ -26,6 +26,8 @@ type window struct {
|
|||
child Control
|
||||
|
||||
closing *event
|
||||
|
||||
spaced bool
|
||||
}
|
||||
|
||||
func newWindow(title string, width int, height int) *Request {
|
||||
|
@ -162,7 +164,7 @@ func windowClosing(wid *C.GtkWidget, e *C.GdkEvent, data C.gpointer) C.gboolean
|
|||
func windowResizing(wid *C.GtkWidget, event *C.GdkEvent, data C.gpointer) C.gboolean {
|
||||
w := (*window)(unsafe.Pointer(data))
|
||||
e := (*C.GdkEventConfigure)(unsafe.Pointer(event))
|
||||
_ = w // TODO
|
||||
w.doresize(int(e.width), int(e.height))
|
||||
// TODO this does not take CSD into account; my attempts at doing so so far have failed to work correctly in the face of rapid live resizing
|
||||
// TODO triggered twice on each resize or maximize for some reason???
|
||||
fmt.Printf("new size %d x %d\n", e.width, e.height)
|
||||
|
|
Loading…
Reference in New Issue