summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPietro Gagliardi <[email protected]>2014-08-03 20:08:25 -0400
committerPietro Gagliardi <[email protected]>2014-08-03 20:08:25 -0400
commit8c4cd789ca4dc69a56bf3327ff7ebbb5b88314be (patch)
treefe52b1a8a55552d2ebcea3480442f5953374afd3
parentb6d07237b423b690570e105e5f0810d35693b0d0 (diff)
Migrated the Mac OS X backend to the new Control setup.
-rw-r--r--redo/basicctrls_darwin.m18
-rw-r--r--redo/button_darwin.go60
-rw-r--r--redo/checkbox_darwin.go74
-rw-r--r--redo/control_darwin.go86
-rwxr-xr-xredo/controlbase.sh2
-rw-r--r--redo/label_darwin.go60
-rw-r--r--redo/objc_darwin.h1
-rw-r--r--redo/tab_darwin.go52
-rw-r--r--redo/table_darwin.go47
-rw-r--r--redo/textfield_darwin.go50
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)
}