diff options
| author | Pietro Gagliardi <[email protected]> | 2014-08-03 20:08:25 -0400 |
|---|---|---|
| committer | Pietro Gagliardi <[email protected]> | 2014-08-03 20:08:25 -0400 |
| commit | 8c4cd789ca4dc69a56bf3327ff7ebbb5b88314be (patch) | |
| tree | fe52b1a8a55552d2ebcea3480442f5953374afd3 | |
| parent | b6d07237b423b690570e105e5f0810d35693b0d0 (diff) | |
Migrated the Mac OS X backend to the new Control setup.
| -rw-r--r-- | redo/basicctrls_darwin.m | 18 | ||||
| -rw-r--r-- | redo/button_darwin.go | 60 | ||||
| -rw-r--r-- | redo/checkbox_darwin.go | 74 | ||||
| -rw-r--r-- | redo/control_darwin.go | 86 | ||||
| -rwxr-xr-x | redo/controlbase.sh | 2 | ||||
| -rw-r--r-- | redo/label_darwin.go | 60 | ||||
| -rw-r--r-- | redo/objc_darwin.h | 1 | ||||
| -rw-r--r-- | redo/tab_darwin.go | 52 | ||||
| -rw-r--r-- | redo/table_darwin.go | 47 | ||||
| -rw-r--r-- | redo/textfield_darwin.go | 50 |
10 files changed, 346 insertions, 104 deletions
diff --git a/redo/basicctrls_darwin.m b/redo/basicctrls_darwin.m index 5ed17c1..95567d6 100644 --- a/redo/basicctrls_darwin.m +++ b/redo/basicctrls_darwin.m @@ -47,6 +47,11 @@ void setSmallControlFont(id control) buttonClicked(self->gocontrol); } +- (IBAction)checkboxToggled:(id)sender +{ + checkboxChecked(self->gocontrol); +} + @end id newButton(void) @@ -93,6 +98,16 @@ id newCheckbox(void) return (id) c; } +void checkboxSetDelegate(id checkbox, void *b) +{ + goControlDelegate *d; + + d = [goControlDelegate new]; + d->gocontrol = b; + [toNSButton(checkbox) setTarget:d]; + [toNSButton(checkbox) setAction:@selector(checkboxToggled:)]; +} + BOOL checkboxChecked(id c) { if ([toNSButton(c) state] == NSOnState) @@ -110,6 +125,7 @@ void checkboxSetChecked(id c, BOOL checked) [toNSButton(c) setState:state]; } +// also good for labels static id finishNewTextField(NSTextField *t, BOOL bordered) { // same for text fields, password fields, and labels @@ -144,11 +160,13 @@ id newPasswordField(void) return finishNewTextField(toNSTextField(t), YES); } +// also good for labels const char *textFieldText(id t) { return [[toNSTextField(t) stringValue] UTF8String]; } +// also good for labels void textFieldSetText(id t, char *text) { [toNSTextField(t) setStringValue:[NSString stringWithUTF8String:text]]; diff --git a/redo/button_darwin.go b/redo/button_darwin.go index e5a7f5b..1e6cf33 100644 --- a/redo/button_darwin.go +++ b/redo/button_darwin.go @@ -10,30 +10,36 @@ import ( import "C" type button struct { - *controlbase - clicked *event + _id C.id + clicked *event } -func finishNewButton(id C.id, text string) *button { +func newButton(text string) *button { ctext := C.CString(text) defer C.free(unsafe.Pointer(ctext)) b := &button{ - controlbase: newControl(id), + _id: C.newButton(), clicked: newEvent(), } - C.buttonSetText(b.id, ctext) - C.buttonSetDelegate(b.id, unsafe.Pointer(b)) + C.buttonSetText(b._id, ctext) + C.buttonSetDelegate(b._id, unsafe.Pointer(b)) return b } -func newButton(text string) *button { - return finishNewButton(C.newButton(), text) -} - func (b *button) OnClicked(e func()) { b.clicked.set(e) } +func (b *button) Text() string { + return C.GoString(C.buttonText(b._id)) +} + +func (b *button) SetText(text string) { + ctext := C.CString(text) + defer C.free(unsafe.Pointer(ctext)) + C.buttonSetText(b._id, ctext) +} + //export buttonClicked func buttonClicked(xb unsafe.Pointer) { b := (*button)(unsafe.Pointer(xb)) @@ -41,12 +47,34 @@ func buttonClicked(xb unsafe.Pointer) { println("button clicked") } -func (b *button) Text() string { - return C.GoString(C.buttonText(b.id)) +func (b *button) id() C.id { + return b._id } -func (b *button) SetText(text string) { - ctext := C.CString(text) - defer C.free(unsafe.Pointer(ctext)) - C.buttonSetText(b.id, ctext) +func (b *button) setParent(p *controlParent) { + basesetParent(b, p) +} + +func (b *button) containerShow() { + basecontainerShow(b) +} + +func (b *button) containerHide() { + basecontainerHide(b) +} + +func (b *button) allocate(x int, y int, width int, height int, d *sizing) []*allocation { + return baseallocate(b, x, y, width, height, d) +} + +func (b *button) preferredSize(d *sizing) (width, height int) { + return basepreferredSize(b, d) +} + +func (b *button) commitResize(a *allocation, d *sizing) { + basecommitResize(b, a, d) +} + +func (b *button) getAuxResizeInfo(d *sizing) { + basegetAuxResizeInfo(b, d) } diff --git a/redo/checkbox_darwin.go b/redo/checkbox_darwin.go index ee7e88c..fa27892 100644 --- a/redo/checkbox_darwin.go +++ b/redo/checkbox_darwin.go @@ -2,26 +2,86 @@ package ui +import ( + "unsafe" +) + // #include "objc_darwin.h" import "C" type checkbox struct { - *button + _id C.id + toggled *event } func newCheckbox(text string) *checkbox { - return &checkbox{ - button: finishNewButton(C.newCheckbox(), text), + ctext := C.CString(text) + defer C.free(unsafe.Pointer(ctext)) + c := &checkbox{ + _id: C.newCheckbox(), + toggled: newEvent(), } + C.buttonSetText(c._id, ctext) + C.checkboxSetDelegate(c._id, unsafe.Pointer(c)) + return c +} + +func (c *checkbox) OnToggled(e func()) { + c.toggled.set(e) } -// we don't need to define our own event here; we can just reuse Button's -// (it's all target-action anyway) +func (c *checkbox) Text() string { + return C.GoString(C.buttonText(c._id)) +} + +func (c *checkbox) SetText(text string) { + ctext := C.CString(text) + defer C.free(unsafe.Pointer(ctext)) + C.buttonSetText(c._id, ctext) +} func (c *checkbox) Checked() bool { - return fromBOOL(C.checkboxChecked(c.id)) + return fromBOOL(C.checkboxChecked(c._id)) } func (c *checkbox) SetChecked(checked bool) { - C.checkboxSetChecked(c.id, toBOOL(checked)) + C.checkboxSetChecked(c._id, toBOOL(checked)) +} + +//export checkboxToggled +func checkboxToggled(xc unsafe.Pointer) { + c := (*checkbox)(unsafe.Pointer(xc)) + c.toggled.fire() +} + +func (c *checkbox) id() C.id { + return c._id +} + +func (c *checkbox) setParent(p *controlParent) { + basesetParent(c, p) +} + +func (c *checkbox) containerShow() { + basecontainerShow(c) +} + +func (c *checkbox) containerHide() { + basecontainerHide(c) +} + +func (c *checkbox) allocate(x int, y int, width int, height int, d *sizing) []*allocation { + return baseallocate(c, x, y, width, height, d) +} + +func (c *checkbox) preferredSize(d *sizing) (width, height int) { + return basepreferredSize(c, d) +} + +func (c *checkbox) commitResize(a *allocation, d *sizing) { + basecommitResize(c, a, d) +} + +func (c *checkbox) getAuxResizeInfo(d *sizing) { + basegetAuxResizeInfo(c, d) } diff --git a/redo/control_darwin.go b/redo/control_darwin.go index 09ebdae..c356749 100644 --- a/redo/control_darwin.go +++ b/redo/control_darwin.go @@ -5,55 +5,63 @@ package ui // #include "objc_darwin.h" import "C" -type controlbase struct { - *controldefs - id C.id +// all Controls that call base methods must be this +type controlPrivate interface { + id() C.id + Control } 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 = baseallocate(c) - c.fpreferredSize = func(d *sizing) (int, int) { - s := C.controlPrefSize(c.id) - return int(s.width), int(s.height) - } - c.fcommitResize = func(a *allocation, d *sizing) { - 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) { - d.neighborAlign = C.alignmentInfo(c.id, C.frame(c.id)) - } - return c +func basesetParent(c controlPrivate, p *controlParent) { + // redrawing the new window handled by C.parent() + C.parent(c.id(), p.id) +} + +func basecontainerShow(c controlPrivate) { + C.controlSetHidden(c.id(), C.NO) +} + +func basecontainerHide(c controlPrivate) { + C.controlSetHidden(c.id(), C.YES) +} + +func basepreferredSize(c controlPrivate, d *sizing) (int, int) { + s := C.controlPrefSize(c.id()) + return int(s.width), int(s.height) +} + +func basecommitResize(c controlPrivate, a *allocation, d *sizing) { + dobasecommitResize(c.id(), a, d) +} + +func dobasecommitResize(id C.id, c *allocation, d *sizing) { + C.moveControl(id, C.intptr_t(c.x), C.intptr_t(c.y), C.intptr_t(c.width), C.intptr_t(c.height)) +} + +func basegetAuxResizeInfo(c controlPrivate, d *sizing) { + id := c.id() + d.neighborAlign = C.alignmentInfo(id, C.frame(id)) } -type scrolledcontrol struct { - *controlbase - scroller *controlbase +type scroller struct { + id C.id } -func newScrolledControl(id C.id) *scrolledcontrol { - scroller := C.newScrollView(id) - s := &scrolledcontrol{ - controlbase: newControl(id), - scroller: newControl(scroller), +func newScroller(child C.id) *scroller { + id := C.newScrollView(child) + s := &scroller{ + id: id, } - s.fsetParent = s.scroller.fsetParent - s.fcommitResize = s.scroller.fcommitResize return s } + +func (s *scroller) setParent(p *controlParent) { + C.parent(s.id, p.id) +} + +func (s *scroller) commitResize(c *allocation, d *sizing) { + dobasecommitResize(s.id, c, d) +} diff --git a/redo/controlbase.sh b/redo/controlbase.sh index 24930c9..1945e2d 100755 --- a/redo/controlbase.sh +++ b/redo/controlbase.sh @@ -31,6 +31,6 @@ func (AAA *BBB) commitResize(a *allocation, d *sizing) { } func (AAA *BBB) getAuxResizeInfo(d *sizing) { - basegetAuxResizeInfo(d) + basegetAuxResizeInfo(AAA, d) } END diff --git a/redo/label_darwin.go b/redo/label_darwin.go index 2e73b2e..65b2720 100644 --- a/redo/label_darwin.go +++ b/redo/label_darwin.go @@ -2,24 +2,24 @@ package ui +import ( + "unsafe" +) + // #include "objc_darwin.h" import "C" -// cheap trick type label struct { - *textField - standalone bool - supercommitResize func(c *allocation, d *sizing) + _id C.id + standalone bool } func finishNewLabel(text string, standalone bool) *label { l := &label{ - textField: finishNewTextField(C.newLabel()), + _id: C.newLabel(), standalone: standalone, } l.SetText(text) - l.supercommitResize = l.fcommitResize - l.fcommitResize = l.labelcommitResize return l } @@ -31,13 +31,47 @@ func newStandaloneLabel(text string) Label { return finishNewLabel(text, true) } -func (l *label) labelcommitResize(c *allocation, d *sizing) { +func (l *label) Text() string { + return C.GoString(C.textFieldText(l._id)) +} + +func (l *label) SetText(text string) { + ctext := C.CString(text) + defer C.free(unsafe.Pointer(ctext)) + C.textFieldSetText(l._id, ctext) +} + +func (l *label) id() C.id { + return l._id +} + +func (l *label) setParent(p *controlParent) { + basesetParent(l, p) +} + +func (l *label) containerShow() { + basecontainerShow(l) +} + +func (l *label) containerHide() { + basecontainerHide(l) +} + +func (l *label) allocate(x int, y int, width int, height int, d *sizing) []*allocation { + return baseallocate(l, x, y, width, height, d) +} + +func (l *label) preferredSize(d *sizing) (width, height int) { + return basepreferredSize(l, d) +} + +func (l *label) commitResize(c *allocation, d *sizing) { if !l.standalone && 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(l.id) + origsize := C.controlPrefSize(l._id) c.height = int(origsize.height) newrect := C.struct_xrect{ x: C.intptr_t(c.x), @@ -45,7 +79,7 @@ func (l *label) labelcommitResize(c *allocation, d *sizing) { width: C.intptr_t(c.width), height: C.intptr_t(c.height), } - ourAlign := C.alignmentInfo(l.id, newrect) + ourAlign := C.alignmentInfo(l._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.rect.y + ourAlign.baseline @@ -57,5 +91,9 @@ func (l *label) labelcommitResize(c *allocation, d *sizing) { } // TODO if there's no baseline, the alignment should be to the top /of the alignment rect/, not the frame } - l.supercommitResize(c, d) + basecommitResize(l, c, d) +} + +func (l *label) getAuxResizeInfo(d *sizing) { + basegetAuxResizeInfo(l, d) } diff --git a/redo/objc_darwin.h b/redo/objc_darwin.h index fd79c43..84d1a84 100644 --- a/redo/objc_darwin.h +++ b/redo/objc_darwin.h @@ -41,6 +41,7 @@ extern void buttonSetDelegate(id, void *); extern const char *buttonText(id); extern void buttonSetText(id, char *); extern id newCheckbox(void); +extern void checkboxSetDelegate(id, void *); extern BOOL checkboxChecked(id); extern void checkboxSetChecked(id, BOOL); extern id newTextField(void); diff --git a/redo/tab_darwin.go b/redo/tab_darwin.go index ef834ad..5175698 100644 --- a/redo/tab_darwin.go +++ b/redo/tab_darwin.go @@ -10,16 +10,13 @@ import ( import "C" type tab struct { - *controlbase - - tabs []*sizer + _id C.id + tabs []*sizer } func newTab() Tab { t := new(tab) - id := C.newTab(unsafe.Pointer(t)) - t.controlbase = newControl(id) - t.fpreferredSize = t.tabpreferredSize + t._id = C.newTab(unsafe.Pointer(t)) return t } @@ -28,18 +25,11 @@ func (t *tab) Append(name string, control Control) { t.tabs = append(t.tabs, s) cname := C.CString(name) defer C.free(unsafe.Pointer(cname)) - tabview := C.tabAppend(t.id, cname) + tabview := C.tabAppend(t._id, cname) s.child = control s.child.setParent(&controlParent{tabview}) } -func (t *tab) tabpreferredSize(d *sizing) (width, height int) { - s := C.tabPrefSize(t.id) - return int(s.width), int(s.height) -} - -// no need to override Control.commitResize() 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) { t := (*tab)(unsafe.Pointer(data)) @@ -48,3 +38,37 @@ func tabResized(data unsafe.Pointer, width C.intptr_t, height C.intptr_t) { s.resize(0, 0, int(width), int(height)) } } + +func (t *tab) id() C.id { + return t._id +} + +func (t *tab) setParent(p *controlParent) { + basesetParent(t, p) +} + +func (t *tab) containerShow() { + basecontainerShow(t) +} + +func (t *tab) containerHide() { + basecontainerHide(t) +} + +func (t *tab) allocate(x int, y int, width int, height int, d *sizing) []*allocation { + return baseallocate(t, x, y, width, height, d) +} + +func (t *tab) preferredSize(d *sizing) (width, height int) { + s := C.tabPrefSize(t._id) + return int(s.width), int(s.height) +} + +// no need to override Control.commitResize() as only prepared the tabbed control; its children will be reallocated when that one is resized +func (t *tab) commitResize(a *allocation, d *sizing) { + basecommitResize(t, a, d) +} + +func (t *tab) getAuxResizeInfo(d *sizing) { + basegetAuxResizeInfo(t, d) +} diff --git a/redo/table_darwin.go b/redo/table_darwin.go index 8417afe..a3e3b76 100644 --- a/redo/table_darwin.go +++ b/redo/table_darwin.go @@ -12,20 +12,23 @@ import ( import "C" type table struct { - *scrolledcontrol *tablebase + + _id C.id + scroller *scroller } func finishNewTable(b *tablebase, ty reflect.Type) Table { id := C.newTable() t := &table{ - scrolledcontrol: newScrolledControl(id), - tablebase: b, + _id: id, + scroller: newScroller(id), + tablebase: b, } - C.tableMakeDataSource(t.id, 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.id, cname) + C.tableAppendColumn(t._id, cname) C.free(unsafe.Pointer(cname)) // free now (not deferred) to conserve memory } return t @@ -37,7 +40,7 @@ func (t *table) Unlock() { // not sure about this one... t.RLock() defer t.RUnlock() - C.tableUpdate(t.id) + C.tableUpdate(t._id) } //export goTableDataSource_getValue @@ -59,3 +62,35 @@ func goTableDataSource_getRowCount(data unsafe.Pointer) C.intptr_t { d := reflect.Indirect(reflect.ValueOf(t.data)) return C.intptr_t(d.Len()) } + +func (t *table) id() C.id { + return t._id +} + +func (t *table) setParent(p *controlParent) { + t.scroller.setParent(p) +} + +func (t *table) containerShow() { + basecontainerShow(t) +} + +func (t *table) containerHide() { + basecontainerHide(t) +} + +func (t *table) allocate(x int, y int, width int, height int, d *sizing) []*allocation { + return baseallocate(t, x, y, width, height, d) +} + +func (t *table) preferredSize(d *sizing) (width, height int) { + return basepreferredSize(t, d) +} + +func (t *table) commitResize(c *allocation, d *sizing) { + t.scroller.commitResize(c, d) +} + +func (t *table) getAuxResizeInfo(d *sizing) { + basegetAuxResizeInfo(t, d) +} diff --git a/redo/textfield_darwin.go b/redo/textfield_darwin.go index 0b248a7..475bda7 100644 --- a/redo/textfield_darwin.go +++ b/redo/textfield_darwin.go @@ -10,29 +10,59 @@ import ( import "C" type textField struct { - *controlbase + _id C.id } -func finishNewTextField(id C.id) *textField { +func newTextField() *textField { return &textField{ - controlbase: newControl(id), + _id: C.newTextField(), } } -func newTextField() *textField { - return finishNewTextField(C.newTextField()) -} - func newPasswordField() *textField { - return finishNewTextField(C.newPasswordField()) + return &textField{ + _id: C.newPasswordField(), + } } func (t *textField) Text() string { - return C.GoString(C.textFieldText(t.id)) + return C.GoString(C.textFieldText(t._id)) } func (t *textField) SetText(text string) { ctext := C.CString(text) defer C.free(unsafe.Pointer(ctext)) - C.textFieldSetText(t.id, ctext) + C.textFieldSetText(t._id, ctext) +} + +func (t *textField) id() C.id { + return t._id +} + +func (t *textField) setParent(p *controlParent) { + basesetParent(t, p) +} + +func (t *textField) containerShow() { + basecontainerShow(t) +} + +func (t *textField) containerHide() { + basecontainerHide(t) +} + +func (t *textField) allocate(x int, y int, width int, height int, d *sizing) []*allocation { + return baseallocate(t, x, y, width, height, d) +} + +func (t *textField) preferredSize(d *sizing) (width, height int) { + return basepreferredSize(t, d) +} + +func (t *textField) commitResize(a *allocation, d *sizing) { + basecommitResize(t, a, d) +} + +func (t *textField) getAuxResizeInfo(d *sizing) { + basegetAuxResizeInfo(t, d) } |
