Ported the new Control setup to Mac OS X.
This commit is contained in:
parent
4740f72efb
commit
c0473db73c
|
@ -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),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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) {
|
||||||
|
|
|
@ -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
|
||||||
|
}
|
|
@ -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
|
||||||
}
|
//}
|
||||||
|
|
|
@ -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
|
||||||
|
|
Loading…
Reference in New Issue