Ported the new Control setup to Mac OS X.

This commit is contained in:
Pietro Gagliardi 2014-07-30 12:34:54 -04:00
parent 4740f72efb
commit c0473db73c
5 changed files with 113 additions and 99 deletions

View File

@ -9,37 +9,8 @@ import (
// #include "objc_darwin.h" // #include "objc_darwin.h"
import "C" 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 { type button struct {
*widgetbase *controlbase
clicked *event clicked *event
} }
@ -47,7 +18,7 @@ func finishNewButton(id C.id, text string) *button {
ctext := C.CString(text) ctext := C.CString(text)
defer C.free(unsafe.Pointer(ctext)) defer C.free(unsafe.Pointer(ctext))
b := &button{ b := &button{
widgetbase: newWidget(id), controlbase: newControl(id),
clicked: newEvent(), clicked: newEvent(),
} }
C.buttonSetText(b.id, ctext) C.buttonSetText(b.id, ctext)
@ -102,12 +73,12 @@ func (c *checkbox) SetChecked(checked bool) {
} }
type textField struct { type textField struct {
*widgetbase *controlbase
} }
func finishNewTextField(id C.id) *textField { func finishNewTextField(id C.id) *textField {
return &textField{ return &textField{
widgetbase: newWidget(id), controlbase: newControl(id),
} }
} }

View File

@ -10,7 +10,7 @@ import (
import "C" import "C"
type tab struct { type tab struct {
*widgetbase *controlbase
containers []*container containers []*container
} }
@ -18,7 +18,7 @@ type tab struct {
func newTab() Tab { func newTab() Tab {
t := new(tab) t := new(tab)
id := C.newTab(unsafe.Pointer(t)) id := C.newTab(unsafe.Pointer(t))
t.widgetbase = newWidget(id) t.controlbase = newControl(id)
return t return t
} }
@ -33,10 +33,7 @@ func (t *tab) Append(name string, control Control) {
c.child.setParent(&controlParent{tabview}) c.child.setParent(&controlParent{tabview})
} }
func (t *tab) allocate(x int, y int, width int, height int, d *sizing) []*allocation { // no need to override Control.allocate() as only prepared the tabbed control; its children will be reallocated when that one is resized
// only prepared the tabbed control; its children will be reallocated when that one is resized
return t.widgetbase.allocate(x, y, width, height, d)
}
//export tabResized //export tabResized
func tabResized(data unsafe.Pointer, width C.intptr_t, height C.intptr_t) { func tabResized(data unsafe.Pointer, width C.intptr_t, height C.intptr_t) {

97
redo/control_darwin.go Normal file
View File

@ -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
}

View File

@ -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.) 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 //TODO
// return prefsizefuncs[s.ctype](s.id) // return prefsizefuncs[s.ctype](s.id)
return 0,0 //return 0,0
} //}

View File

@ -12,24 +12,20 @@ import (
import "C" import "C"
type table struct { type table struct {
*widgetbase *scrolledcontrol
*tablebase *tablebase
// TODO kludge
table C.id
} }
func finishNewTable(b *tablebase, ty reflect.Type) Table { func finishNewTable(b *tablebase, ty reflect.Type) Table {
id := C.newTable() id := C.newTable()
t := &table{ t := &table{
widgetbase: newWidget(C.newScrollView(id)), scrolledcontrol: newScrolledControl(id),
tablebase: b, tablebase: b,
table: id,
} }
C.tableMakeDataSource(t.table, unsafe.Pointer(t)) C.tableMakeDataSource(t.id, unsafe.Pointer(t))
for i := 0; i < ty.NumField(); i++ { for i := 0; i < ty.NumField(); i++ {
cname := C.CString(ty.Field(i).Name) 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 C.free(unsafe.Pointer(cname)) // free now (not deferred) to conserve memory
} }
return t return t
@ -41,7 +37,7 @@ func (t *table) Unlock() {
// not sure about this one... // not sure about this one...
t.RLock() t.RLock()
defer t.RUnlock() defer t.RUnlock()
C.tableUpdate(t.table) C.tableUpdate(t.id)
} }
//export goTableDataSource_getValue //export goTableDataSource_getValue