From c0473db73c11927144f79bb69d01a290753b5de0 Mon Sep 17 00:00:00 2001 From: Pietro Gagliardi Date: Wed, 30 Jul 2014 12:34:54 -0400 Subject: [PATCH] Ported the new Control setup to Mac OS X. --- redo/basicctrls_darwin.go | 37 ++----------- redo/containerctrls_darwin.go | 9 ++-- redo/control_darwin.go | 97 +++++++++++++++++++++++++++++++++++ redo/sizing_darwin.go | 53 ++----------------- redo/table_darwin.go | 16 +++--- 5 files changed, 113 insertions(+), 99 deletions(-) create mode 100644 redo/control_darwin.go diff --git a/redo/basicctrls_darwin.go b/redo/basicctrls_darwin.go index 78e9138..1899133 100644 --- a/redo/basicctrls_darwin.go +++ b/redo/basicctrls_darwin.go @@ -9,37 +9,8 @@ import ( // #include "objc_darwin.h" import "C" -type widgetbase struct { - id C.id -} - -func newWidget(id C.id) *widgetbase { - return &widgetbase{ - id: id, - } -} - -// these few methods are embedded by all the various Controls since they all will do the same thing - -type controlParent struct { - id C.id -} - -func (w *widgetbase) setParent(parent *controlParent) { - // redrawing the new window handled by C.parent() - C.parent(w.id, parent.id) -} - -func (w *widgetbase) containerShow() { - C.controlSetHidden(w.id, C.NO) -} - -func (w *widgetbase) containerHide() { - C.controlSetHidden(w.id, C.YES) -} - type button struct { - *widgetbase + *controlbase clicked *event } @@ -47,7 +18,7 @@ func finishNewButton(id C.id, text string) *button { ctext := C.CString(text) defer C.free(unsafe.Pointer(ctext)) b := &button{ - widgetbase: newWidget(id), + controlbase: newControl(id), clicked: newEvent(), } C.buttonSetText(b.id, ctext) @@ -102,12 +73,12 @@ func (c *checkbox) SetChecked(checked bool) { } type textField struct { - *widgetbase + *controlbase } func finishNewTextField(id C.id) *textField { return &textField{ - widgetbase: newWidget(id), + controlbase: newControl(id), } } diff --git a/redo/containerctrls_darwin.go b/redo/containerctrls_darwin.go index 0e0221a..7249134 100644 --- a/redo/containerctrls_darwin.go +++ b/redo/containerctrls_darwin.go @@ -10,7 +10,7 @@ import ( import "C" type tab struct { - *widgetbase + *controlbase containers []*container } @@ -18,7 +18,7 @@ type tab struct { func newTab() Tab { t := new(tab) id := C.newTab(unsafe.Pointer(t)) - t.widgetbase = newWidget(id) + t.controlbase = newControl(id) return t } @@ -33,10 +33,7 @@ func (t *tab) Append(name string, control Control) { c.child.setParent(&controlParent{tabview}) } -func (t *tab) allocate(x int, y int, width int, height int, d *sizing) []*allocation { - // only prepared the tabbed control; its children will be reallocated when that one is resized - return t.widgetbase.allocate(x, y, width, height, d) -} +// no need to override Control.allocate() as only prepared the tabbed control; its children will be reallocated when that one is resized //export tabResized func tabResized(data unsafe.Pointer, width C.intptr_t, height C.intptr_t) { diff --git a/redo/control_darwin.go b/redo/control_darwin.go new file mode 100644 index 0000000..f6f9312 --- /dev/null +++ b/redo/control_darwin.go @@ -0,0 +1,97 @@ +// 30 july 2014 + +package ui + +// #include "objc_darwin.h" +import "C" + +type controlbase struct { + *controldefs + id C.id +} + +type controlParent struct { + id C.id +} + +func newControl(id C.id) *controlbase { + c := new(controlbase) + c.id = id + c.controldefs = new(controldefs) + c.fsetParent = func(p *controlParent) { + // redrawing the new window handled by C.parent() + C.parent(c.id, p.id) + } + c.fcontainerShow = func() { + C.controlSetHidden(c.id, C.NO) + } + c.fcontainerHide = func() { + C.controlSetHidden(c.id, C.YES) + } + c.fallocate = func(x int, y int, width int, height int, d *sizing) []*allocation { + // TODO split into its own function + return []*allocation{&allocation{ + x: x, + y: y, + width: width, + height: height, + this: c, + }} + } + c.fpreferredSize = func(d *sizing) (int, int) { + // TODO + return 64, 32 + } + c.fcommitResize = func(a *allocation, d *sizing) { +//TODO +/* + if s.ctype == c_label && !s.alternate && c.neighbor != nil { + c.neighbor.getAuxResizeInfo(d) + if d.neighborAlign.baseline != 0 { // no adjustment needed if the given control has no baseline + // in order for the baseline value to be correct, the label MUST BE AT THE HEIGHT THAT OS X WANTS IT TO BE! + // otherwise, the baseline calculation will be relative to the bottom of the control, and everything will be wrong + origsize := C.controlPrefSize(s.id) + c.height = int(origsize.height) + newrect := C.struct_xrect{ + x: C.intptr_t(c.x), + y: C.intptr_t(c.y), + width: C.intptr_t(c.width), + height: C.intptr_t(c.height), + } + ourAlign := C.alignmentInfo(s.id, newrect) + // we need to find the exact Y positions of the baselines + // fortunately, this is easy now that (x,y) is the bottom-left corner + thisbasey := ourAlign.alignmentRect.y + ourAlign.baseline + neighborbasey := d.neighborAlign.alignmentRect.y + d.neighborAlign.baseline + // now the amount we have to move the label down by is easy to find + yoff := neighborbasey - thisbasey + // and we just add that + c.y += int(yoff) + } + // TODO if there's no baseline, the alignment should be to the top /of the alignment rect/, not the frame + } +*/ + C.moveControl(c.id, C.intptr_t(a.x), C.intptr_t(a.y), C.intptr_t(a.width), C.intptr_t(a.height)) + } + c.fgetAuxResizeInfo = func(d *sizing) { +// TODO +// d.neighborAlign = C.alignmentInfo(s.id, C.frame(s.id)) + } + return c +} + +type scrolledcontrol struct { + *controlbase + scroller *controlbase +} + +func newScrolledControl(id C.id) *scrolledcontrol { + scroller := C.newScrollView(id) + s := &scrolledcontrol{ + controlbase: newControl(id), + scroller: newControl(scroller), + } + s.fsetParent = s.scroller.fsetParent + s.fcommitResize = s.scroller.fcommitResize + return s +} diff --git a/redo/sizing_darwin.go b/redo/sizing_darwin.go index be29666..6eb29b2 100644 --- a/redo/sizing_darwin.go +++ b/redo/sizing_darwin.go @@ -43,53 +43,6 @@ func (c *container) translateAllocationCoords(allocations []*allocation, winwidt } } -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.neighborAlign.baseline != 0 { // no adjustment needed if the given control has no baseline - // in order for the baseline value to be correct, the label MUST BE AT THE HEIGHT THAT OS X WANTS IT TO BE! - // otherwise, the baseline calculation will be relative to the bottom of the control, and everything will be wrong - origsize := C.controlPrefSize(s.id) - c.height = int(origsize.height) - newrect := C.struct_xrect{ - x: C.intptr_t(c.x), - y: C.intptr_t(c.y), - width: C.intptr_t(c.width), - height: C.intptr_t(c.height), - } - ourAlign := C.alignmentInfo(s.id, newrect) - // we need to find the exact Y positions of the baselines - // fortunately, this is easy now that (x,y) is the bottom-left corner - thisbasey := ourAlign.alignmentRect.y + ourAlign.baseline - neighborbasey := d.neighborAlign.alignmentRect.y + d.neighborAlign.baseline - // now the amount we have to move the label down by is easy to find - yoff := neighborbasey - thisbasey - // and we just add that - c.y += int(yoff) - } - // TODO if there's no baseline, the alignment should be to the top /of the alignment rect/, not the frame - } -*/ - C.moveControl(w.id, C.intptr_t(c.x), C.intptr_t(c.y), C.intptr_t(c.width), C.intptr_t(c.height)) -} - -func (w *widgetbase) getAuxResizeInfo(d *sizing) { -// TODO -// d.neighborAlign = C.alignmentInfo(s.id, C.frame(s.id)) -} - /* Cocoa doesn't provide a reliable way to get the preferred size of a control (you're supposed to use Interface Builder and have it set up autoresizing for you). The best we can do is call [control sizeToFit] (which is defined for NSControls and has a custom implementation for the other types here) and read the preferred size. Though this changes the size, we're immediately overriding the change on return from sysData.preferredSize(), so no harm done. (This is similar to what we are doing with GTK+, except GTK+ does not actually change the size.) */ @@ -132,8 +85,8 @@ var prefsizefuncs = [nctypes]func(C.id) (int, int){ } */ -func (w *widgetbase) preferredSize(d *sizing) (width int, height int) { +//func (w *widgetbase) preferredSize(d *sizing) (width int, height int) { //TODO // return prefsizefuncs[s.ctype](s.id) -return 0,0 -} +//return 0,0 +//} diff --git a/redo/table_darwin.go b/redo/table_darwin.go index 206820a..8417afe 100644 --- a/redo/table_darwin.go +++ b/redo/table_darwin.go @@ -12,24 +12,20 @@ import ( import "C" type table struct { - *widgetbase + *scrolledcontrol *tablebase - - // TODO kludge - table C.id } func finishNewTable(b *tablebase, ty reflect.Type) Table { id := C.newTable() t := &table{ - widgetbase: newWidget(C.newScrollView(id)), - tablebase: b, - table: id, + scrolledcontrol: newScrolledControl(id), + tablebase: b, } - C.tableMakeDataSource(t.table, unsafe.Pointer(t)) + C.tableMakeDataSource(t.id, unsafe.Pointer(t)) for i := 0; i < ty.NumField(); i++ { cname := C.CString(ty.Field(i).Name) - C.tableAppendColumn(t.table, cname) + C.tableAppendColumn(t.id, cname) C.free(unsafe.Pointer(cname)) // free now (not deferred) to conserve memory } return t @@ -41,7 +37,7 @@ func (t *table) Unlock() { // not sure about this one... t.RLock() defer t.RUnlock() - C.tableUpdate(t.table) + C.tableUpdate(t.id) } //export goTableDataSource_getValue