From 7b7ae9d7ce2aa6f99677fde7b8a0c21c7024e3e9 Mon Sep 17 00:00:00 2001 From: Pietro Gagliardi Date: Sun, 26 Aug 2018 13:43:05 -0400 Subject: More control migration. Everything beyond this point is nontrivial. --- BBB_GOFILES/multilineentry.go | 97 ------------------------------------------- BBB_GOFILES/radiobuttons.go | 66 ----------------------------- BBB_GOFILES/separator.go | 37 ----------------- BBB_GOFILES/slider.go | 58 -------------------------- BBB_GOFILES/spinbox.go | 58 -------------------------- BBB_GOFILES/tab.go | 87 -------------------------------------- multilineentry.go | 94 +++++++++++++++++++++++++++++++++++++++++ pkgui.c | 20 +++++++++ pkgui.h | 12 ++++++ radiobuttons.go | 63 ++++++++++++++++++++++++++++ separator.go | 37 +++++++++++++++++ slider.go | 55 ++++++++++++++++++++++++ spinbox.go | 55 ++++++++++++++++++++++++ tab.go | 87 ++++++++++++++++++++++++++++++++++++++ 14 files changed, 423 insertions(+), 403 deletions(-) delete mode 100644 BBB_GOFILES/multilineentry.go delete mode 100644 BBB_GOFILES/radiobuttons.go delete mode 100644 BBB_GOFILES/separator.go delete mode 100644 BBB_GOFILES/slider.go delete mode 100644 BBB_GOFILES/spinbox.go delete mode 100644 BBB_GOFILES/tab.go create mode 100644 multilineentry.go create mode 100644 radiobuttons.go create mode 100644 separator.go create mode 100644 slider.go create mode 100644 spinbox.go create mode 100644 tab.go diff --git a/BBB_GOFILES/multilineentry.go b/BBB_GOFILES/multilineentry.go deleted file mode 100644 index 88a75c4..0000000 --- a/BBB_GOFILES/multilineentry.go +++ /dev/null @@ -1,97 +0,0 @@ -// 12 december 2015 - -// TODO typing in entry in OS X crashes libui -// I've had similar issues with checkboxes on libui -// something's wrong with NSMapTable - -package ui - -import ( - "unsafe" -) - -// #include "ui.h" -// extern void doMultilineEntryOnChanged(uiMultilineEntry *, void *); -// // see golang/go#19835 -// typedef void (*multilineEntryCallback)(uiMultilineEntry *, void *); -import "C" - -// MultilineEntry is a Control that represents a space that the user -// can type multiple lines of text into. -type MultilineEntry struct { - ControlBase - e *C.uiMultilineEntry - onChanged func(*MultilineEntry) -} - -func finishNewMultilineEntry(ee *C.uiMultilineEntry) *MultilineEntry { - m := new(MultilineEntry) - - m.e = ee - - C.uiMultilineEntryOnChanged(m.e, C.multilineEntryCallback(C.doMultilineEntryOnChanged), nil) - - m.ControlBase = NewControlBase(m, uintptr(unsafe.Pointer(m.e))) - return m -} - -// NewMultilineEntry creates a new MultilineEntry. -// The MultilineEntry soft-word-wraps and has no horizontal -// scrollbar. -func NewMultilineEntry() *MultilineEntry { - return finishNewMultilineEntry(C.uiNewMultilineEntry()) -} - -// NewNonWrappingMultilineEntry creates a new MultilineEntry. -// The MultilineEntry does not word-wrap and thus has horizontal -// scrollbar. -func NewNonWrappingMultilineEntry() *MultilineEntry { - return finishNewMultilineEntry(C.uiNewNonWrappingMultilineEntry()) -} - -// Text returns the MultilineEntry's text. -func (m *MultilineEntry) Text() string { - ctext := C.uiMultilineEntryText(m.e) - text := C.GoString(ctext) - C.uiFreeText(ctext) - return text -} - -// SetText sets the MultilineEntry's text to text. -func (m *MultilineEntry) SetText(text string) { - ctext := C.CString(text) - C.uiMultilineEntrySetText(m.e, ctext) - freestr(ctext) -} - -// Append adds text to the end of the MultilineEntry's text. -// TODO selection and scroll behavior -func (m *MultilineEntry) Append(text string) { - ctext := C.CString(text) - C.uiMultilineEntryAppend(m.e, ctext) - freestr(ctext) -} - -// OnChanged registers f to be run when the user makes a change to -// the MultilineEntry. Only one function can be registered at a time. -func (m *MultilineEntry) OnChanged(f func(*MultilineEntry)) { - m.onChanged = f -} - -//export doMultilineEntryOnChanged -func doMultilineEntryOnChanged(ee *C.uiMultilineEntry, data unsafe.Pointer) { - m := ControlFromLibui(uintptr(unsafe.Pointer(ee))).(*MultilineEntry) - if m.onChanged != nil { - m.onChanged(m) - } -} - -// ReadOnly returns whether the MultilineEntry can be changed. -func (m *MultilineEntry) ReadOnly() bool { - return tobool(C.uiMultilineEntryReadOnly(m.e)) -} - -// SetReadOnly sets whether the MultilineEntry can be changed. -func (m *MultilineEntry) SetReadOnly(ro bool) { - C.uiMultilineEntrySetReadOnly(m.e, frombool(ro)) -} diff --git a/BBB_GOFILES/radiobuttons.go b/BBB_GOFILES/radiobuttons.go deleted file mode 100644 index 2413544..0000000 --- a/BBB_GOFILES/radiobuttons.go +++ /dev/null @@ -1,66 +0,0 @@ -// 12 december 2015 - -package ui - -import ( - "unsafe" -) - -// #include "ui.h" -// extern void doRadioButtonsOnSelected(uiRadioButtons *, void *); -// // see golang/go#19835 -// typedef void (*radioButtonsCallback)(uiRadioButtons *, void *); -import "C" - -// RadioButtons is a Control that represents a set of checkable -// buttons from which exactly one may be chosen by the user. -type RadioButtons struct { - ControlBase - r *C.uiRadioButtons - onSelected func(*RadioButtons) -} - -// NewRadioButtons creates a new RadioButtons. -func NewRadioButtons() *RadioButtons { - r := new(RadioButtons) - - r.r = C.uiNewRadioButtons() - - C.uiRadioButtonsOnSelected(r.r, C.radioButtonsCallback(C.doRadioButtonsOnSelected), nil) - - r.ControlBase = NewControlBase(r, uintptr(unsafe.Pointer(r.r))) - return r -} - -// Append adds the named button to the end of the RadioButtons. -func (r *RadioButtons) Append(text string) { - ctext := C.CString(text) - C.uiRadioButtonsAppend(r.r, ctext) - freestr(ctext) -} - -// Selected returns the index of the currently selected option in the -// RadioButtons, or -1 if no item is selected. -func (r *RadioButtons) Selected() int { - return int(C.uiRadioButtonsSelected(r.r)) -} - -// SetSelected sets the currently selected option in the RadioButtons -// to index. -func (r *RadioButtons) SetSelected(index int) { - C.uiRadioButtonsSetSelected(r.r, C.int(index)) -} - -// OnSelected registers f to be run when the user selects an option in -// the RadioButtons. Only one function can be registered at a time. -func (r *RadioButtons) OnSelected(f func(*RadioButtons)) { - r.onSelected = f -} - -//export doRadioButtonsOnSelected -func doRadioButtonsOnSelected(rr *C.uiRadioButtons, data unsafe.Pointer) { - r := ControlFromLibui(uintptr(unsafe.Pointer(rr))).(*RadioButtons) - if r.onSelected != nil { - r.onSelected(r) - } -} diff --git a/BBB_GOFILES/separator.go b/BBB_GOFILES/separator.go deleted file mode 100644 index 67dea4f..0000000 --- a/BBB_GOFILES/separator.go +++ /dev/null @@ -1,37 +0,0 @@ -// 12 december 2015 - -package ui - -import ( - "unsafe" -) - -// #include "ui.h" -import "C" - -// Separator is a Control that represents a horizontal line that -// visually separates controls. -type Separator struct { - ControlBase - s *C.uiSeparator -} - -// NewHorizontalSeparator creates a new horizontal Separator. -func NewHorizontalSeparator() *Separator { - s := new(Separator) - - s.s = C.uiNewHorizontalSeparator() - - s.ControlBase = NewControlBase(s, uintptr(unsafe.Pointer(s.s))) - return s -} - -// NewVerticalSeparator creates a new vertical Separator. -func NewVerticalSeparator() *Separator { - s := new(Separator) - - s.s = C.uiNewVerticalSeparator() - - s.ControlBase = NewControlBase(s, uintptr(unsafe.Pointer(s.s))) - return s -} diff --git a/BBB_GOFILES/slider.go b/BBB_GOFILES/slider.go deleted file mode 100644 index 91656cf..0000000 --- a/BBB_GOFILES/slider.go +++ /dev/null @@ -1,58 +0,0 @@ -// 12 december 2015 - -package ui - -import ( - "unsafe" -) - -// #include "ui.h" -// extern void doSliderOnChanged(uiSlider *, void *); -// // see golang/go#19835 -// typedef void (*sliderCallback)(uiSlider *, void *); -import "C" - -// Slider is a Control that represents a horizontal bar that represents -// a range of integers. The user can drag a pointer on the bar to -// select an integer. -type Slider struct { - ControlBase - s *C.uiSlider - onChanged func(*Slider) -} - -// NewSlider creates a new Slider. If min >= max, they are swapped. -func NewSlider(min int, max int) *Slider { - s := new(Slider) - - s.s = C.uiNewSlider(C.int(min), C.int(max)) - - C.uiSliderOnChanged(s.s, C.sliderCallback(C.doSliderOnChanged), nil) - - s.ControlBase = NewControlBase(s, uintptr(unsafe.Pointer(s.s))) - return s -} - -// Value returns the Slider's current value. -func (s *Slider) Value() int { - return int(C.uiSliderValue(s.s)) -} - -// SetValue sets the Slider's current value to value. -func (s *Slider) SetValue(value int) { - C.uiSliderSetValue(s.s, C.int(value)) -} - -// OnChanged registers f to be run when the user changes the value -// of the Slider. Only one function can be registered at a time. -func (s *Slider) OnChanged(f func(*Slider)) { - s.onChanged = f -} - -//export doSliderOnChanged -func doSliderOnChanged(ss *C.uiSlider, data unsafe.Pointer) { - s := ControlFromLibui(uintptr(unsafe.Pointer(ss))).(*Slider) - if s.onChanged != nil { - s.onChanged(s) - } -} diff --git a/BBB_GOFILES/spinbox.go b/BBB_GOFILES/spinbox.go deleted file mode 100644 index 27dd287..0000000 --- a/BBB_GOFILES/spinbox.go +++ /dev/null @@ -1,58 +0,0 @@ -// 12 december 2015 - -package ui - -import ( - "unsafe" -) - -// #include "ui.h" -// extern void doSpinboxOnChanged(uiSpinbox *, void *); -// // see golang/go#19835 -// typedef void (*spinboxCallback)(uiSpinbox *, void *); -import "C" - -// Spinbox is a Control that represents a space where the user can -// enter integers. The space also comes with buttons to add or -// subtract 1 from the integer. -type Spinbox struct { - ControlBase - s *C.uiSpinbox - onChanged func(*Spinbox) -} - -// NewSpinbox creates a new Spinbox. If min >= max, they are swapped. -func NewSpinbox(min int, max int) *Spinbox { - s := new(Spinbox) - - s.s = C.uiNewSpinbox(C.int(min), C.int(max)) - - C.uiSpinboxOnChanged(s.s, C.spinboxCallback(C.doSpinboxOnChanged), nil) - - s.ControlBase = NewControlBase(s, uintptr(unsafe.Pointer(s.s))) - return s -} - -// Value returns the Spinbox's current value. -func (s *Spinbox) Value() int { - return int(C.uiSpinboxValue(s.s)) -} - -// SetValue sets the Spinbox's current value to value. -func (s *Spinbox) SetValue(value int) { - C.uiSpinboxSetValue(s.s, C.int(value)) -} - -// OnChanged registers f to be run when the user changes the value -// of the Spinbox. Only one function can be registered at a time. -func (s *Spinbox) OnChanged(f func(*Spinbox)) { - s.onChanged = f -} - -//export doSpinboxOnChanged -func doSpinboxOnChanged(ss *C.uiSpinbox, data unsafe.Pointer) { - s := ControlFromLibui(uintptr(unsafe.Pointer(ss))).(*Spinbox) - if s.onChanged != nil { - s.onChanged(s) - } -} diff --git a/BBB_GOFILES/tab.go b/BBB_GOFILES/tab.go deleted file mode 100644 index 0b0b0b9..0000000 --- a/BBB_GOFILES/tab.go +++ /dev/null @@ -1,87 +0,0 @@ -// 12 december 2015 - -package ui - -import ( - "unsafe" -) - -// #include "ui.h" -import "C" - -// Tab is a Control that holds tabbed pages of Controls. Each tab -// has a label. The user can click on the tabs themselves to switch -// pages. Individual pages can also have margins. -type Tab struct { - ControlBase - t *C.uiTab - children []Control -} - -// NewTab creates a new Tab. -func NewTab() *Tab { - t := new(Tab) - - t.t = C.uiNewTab() - - t.ControlBase = NewControlBase(t, uintptr(unsafe.Pointer(t.t))) - return t -} - -// Destroy destroys the Tab. If the Tab has pages, -// Destroy calls Destroy on the pages's Controls as well. -func (t *Tab) Destroy() { - for len(t.children) != 0 { - c := t.children[0] - t.Delete(0) - c.Destroy() - } - t.ControlBase.Destroy() -} - -// Append adds the given page to the end of the Tab. -func (t *Tab) Append(name string, child Control) { - t.InsertAt(name, len(t.children), child) -} - -// InsertAt adds the given page to the Tab such that it is the -// nth page of the Tab (starting at 0). -func (t *Tab) InsertAt(name string, n int, child Control) { - c := (*C.uiControl)(nil) - if child != nil { - c = touiControl(child.LibuiControl()) - } - cname := C.CString(name) - C.uiTabInsertAt(t.t, cname, C.int(n), c) - freestr(cname) - ch := make([]Control, len(t.children) + 1) - // and insert into t.children at the right place - copy(ch[:n], t.children[:n]) - ch[n] = child - copy(ch[n + 1:], t.children[n:]) - t.children = ch -} - -// Delete deletes the nth page of the Tab. -func (t *Tab) Delete(n int) { - t.children = append(t.children[:n], t.children[n + 1:]...) - C.uiTabDelete(t.t, C.int(n)) -} - -// NumPages returns the number of pages in the Tab. -func (t *Tab) NumPages() int { - return len(t.children) -} - -// Margined returns whether page n (starting at 0) of the Tab -// has margins around its child. -func (t *Tab) Margined(n int) bool { - return tobool(C.uiTabMargined(t.t, C.int(n))) -} - -// SetMargined controls whether page n (starting at 0) of the Tab -// has margins around its child. The size of the margins are -// determined by the OS and its best practices. -func (t *Tab) SetMargined(n int, margined bool) { - C.uiTabSetMargined(t.t, C.int(n), frombool(margined)) -} diff --git a/multilineentry.go b/multilineentry.go new file mode 100644 index 0000000..34ba637 --- /dev/null +++ b/multilineentry.go @@ -0,0 +1,94 @@ +// 12 december 2015 + +// TODO typing in entry in OS X crashes libui +// I've had similar issues with checkboxes on libui +// something's wrong with NSMapTable + +package ui + +import ( + "unsafe" +) + +// #include "pkgui.h" +import "C" + +// MultilineEntry is a Control that represents a space that the user +// can type multiple lines of text into. +type MultilineEntry struct { + ControlBase + e *C.uiMultilineEntry + onChanged func(*MultilineEntry) +} + +func finishNewMultilineEntry(ee *C.uiMultilineEntry) *MultilineEntry { + m := new(MultilineEntry) + + m.e = ee + + C.pkguiMultilineEntryOnChanged(m.e) + + m.ControlBase = NewControlBase(m, uintptr(unsafe.Pointer(m.e))) + return m +} + +// NewMultilineEntry creates a new MultilineEntry. +// The MultilineEntry soft-word-wraps and has no horizontal +// scrollbar. +func NewMultilineEntry() *MultilineEntry { + return finishNewMultilineEntry(C.uiNewMultilineEntry()) +} + +// NewNonWrappingMultilineEntry creates a new MultilineEntry. +// The MultilineEntry does not word-wrap and thus has horizontal +// scrollbar. +func NewNonWrappingMultilineEntry() *MultilineEntry { + return finishNewMultilineEntry(C.uiNewNonWrappingMultilineEntry()) +} + +// Text returns the MultilineEntry's text. +func (m *MultilineEntry) Text() string { + ctext := C.uiMultilineEntryText(m.e) + text := C.GoString(ctext) + C.uiFreeText(ctext) + return text +} + +// SetText sets the MultilineEntry's text to text. +func (m *MultilineEntry) SetText(text string) { + ctext := C.CString(text) + C.uiMultilineEntrySetText(m.e, ctext) + freestr(ctext) +} + +// Append adds text to the end of the MultilineEntry's text. +// TODO selection and scroll behavior +func (m *MultilineEntry) Append(text string) { + ctext := C.CString(text) + C.uiMultilineEntryAppend(m.e, ctext) + freestr(ctext) +} + +// OnChanged registers f to be run when the user makes a change to +// the MultilineEntry. Only one function can be registered at a time. +func (m *MultilineEntry) OnChanged(f func(*MultilineEntry)) { + m.onChanged = f +} + +//export pkguiDoMultilineEntryOnChanged +func pkguiDoMultilineEntryOnChanged(ee *C.uiMultilineEntry, data unsafe.Pointer) { + m := ControlFromLibui(uintptr(unsafe.Pointer(ee))).(*MultilineEntry) + if m.onChanged != nil { + m.onChanged(m) + } +} + +// ReadOnly returns whether the MultilineEntry can be changed. +func (m *MultilineEntry) ReadOnly() bool { + return tobool(C.uiMultilineEntryReadOnly(m.e)) +} + +// SetReadOnly sets whether the MultilineEntry can be changed. +func (m *MultilineEntry) SetReadOnly(ro bool) { + C.uiMultilineEntrySetReadOnly(m.e, frombool(ro)) +} diff --git a/pkgui.c b/pkgui.c index 643f50e..cdc2a3f 100644 --- a/pkgui.c +++ b/pkgui.c @@ -51,3 +51,23 @@ void pkguiEntryOnChanged(uiEntry *e) { uiEntryOnChanged(e, pkguiDoEntryOnChanged, NULL); } + +void pkguiMultilineEntryOnChanged(uiMultilineEntry *e) +{ + uiMultilineEntryOnChanged(e, pkguiDoMultilineEntryOnChanged, NULL); +} + +void pkguiRadioButtonsOnSelected(uiRadioButtons *r) +{ + uiRadioButtonsOnSelected(r, pkguiDoRadioButtonsOnSelected, NULL); +} + +void pkguiSliderOnChanged(uiSlider *s) +{ + uiSliderOnChanged(s, pkguiDoSliderOnChanged, NULL); +} + +void pkguiSpinboxOnChanged(uiSpinbox *s) +{ + uiSpinboxOnChanged(s, pkguiDoSpinboxOnChanged, NULL); +} diff --git a/pkgui.h b/pkgui.h index eefea53..418f781 100644 --- a/pkgui.h +++ b/pkgui.h @@ -29,4 +29,16 @@ extern void pkguiEditableComboboxOnChanged(uiEditableCombobox *c); // entry.go extern void pkguiEntryOnChanged(uiEntry *e); +// multilineentry.go +extern void pkguiMultilineEntryOnChanged(uiMultilineEntry *e); + +// radiobuttons.go +extern void pkguiRadioButtonsOnSelected(uiRadioButtons *r); + +// slider.go +extern void pkguiSliderOnChanged(uiSlider *s); + +// spinbox.go +extern void pkguiSpinboxOnChanged(uiSpinbox *s); + #endif diff --git a/radiobuttons.go b/radiobuttons.go new file mode 100644 index 0000000..7f39933 --- /dev/null +++ b/radiobuttons.go @@ -0,0 +1,63 @@ +// 12 december 2015 + +package ui + +import ( + "unsafe" +) + +// #include "pkgui.h" +import "C" + +// RadioButtons is a Control that represents a set of checkable +// buttons from which exactly one may be chosen by the user. +type RadioButtons struct { + ControlBase + r *C.uiRadioButtons + onSelected func(*RadioButtons) +} + +// NewRadioButtons creates a new RadioButtons. +func NewRadioButtons() *RadioButtons { + r := new(RadioButtons) + + r.r = C.uiNewRadioButtons() + + C.pkguiRadioButtonsOnSelected(r.r) + + r.ControlBase = NewControlBase(r, uintptr(unsafe.Pointer(r.r))) + return r +} + +// Append adds the named button to the end of the RadioButtons. +func (r *RadioButtons) Append(text string) { + ctext := C.CString(text) + C.uiRadioButtonsAppend(r.r, ctext) + freestr(ctext) +} + +// Selected returns the index of the currently selected option in the +// RadioButtons, or -1 if no item is selected. +func (r *RadioButtons) Selected() int { + return int(C.uiRadioButtonsSelected(r.r)) +} + +// SetSelected sets the currently selected option in the RadioButtons +// to index. +func (r *RadioButtons) SetSelected(index int) { + C.uiRadioButtonsSetSelected(r.r, C.int(index)) +} + +// OnSelected registers f to be run when the user selects an option in +// the RadioButtons. Only one function can be registered at a time. +func (r *RadioButtons) OnSelected(f func(*RadioButtons)) { + r.onSelected = f +} + +//export pkguiDoRadioButtonsOnSelected +func pkguiDoRadioButtonsOnSelected(rr *C.uiRadioButtons, data unsafe.Pointer) { + r := ControlFromLibui(uintptr(unsafe.Pointer(rr))).(*RadioButtons) + if r.onSelected != nil { + r.onSelected(r) + } +} diff --git a/separator.go b/separator.go new file mode 100644 index 0000000..f1a1249 --- /dev/null +++ b/separator.go @@ -0,0 +1,37 @@ +// 12 december 2015 + +package ui + +import ( + "unsafe" +) + +// #include "pkgui.h" +import "C" + +// Separator is a Control that represents a horizontal line that +// visually separates controls. +type Separator struct { + ControlBase + s *C.uiSeparator +} + +// NewHorizontalSeparator creates a new horizontal Separator. +func NewHorizontalSeparator() *Separator { + s := new(Separator) + + s.s = C.uiNewHorizontalSeparator() + + s.ControlBase = NewControlBase(s, uintptr(unsafe.Pointer(s.s))) + return s +} + +// NewVerticalSeparator creates a new vertical Separator. +func NewVerticalSeparator() *Separator { + s := new(Separator) + + s.s = C.uiNewVerticalSeparator() + + s.ControlBase = NewControlBase(s, uintptr(unsafe.Pointer(s.s))) + return s +} diff --git a/slider.go b/slider.go new file mode 100644 index 0000000..19bc31b --- /dev/null +++ b/slider.go @@ -0,0 +1,55 @@ +// 12 december 2015 + +package ui + +import ( + "unsafe" +) + +// #include "pkgui.h" +import "C" + +// Slider is a Control that represents a horizontal bar that represents +// a range of integers. The user can drag a pointer on the bar to +// select an integer. +type Slider struct { + ControlBase + s *C.uiSlider + onChanged func(*Slider) +} + +// NewSlider creates a new Slider. If min >= max, they are swapped. +func NewSlider(min int, max int) *Slider { + s := new(Slider) + + s.s = C.uiNewSlider(C.int(min), C.int(max)) + + C.pkguiSliderOnChanged(s.s) + + s.ControlBase = NewControlBase(s, uintptr(unsafe.Pointer(s.s))) + return s +} + +// Value returns the Slider's current value. +func (s *Slider) Value() int { + return int(C.uiSliderValue(s.s)) +} + +// SetValue sets the Slider's current value to value. +func (s *Slider) SetValue(value int) { + C.uiSliderSetValue(s.s, C.int(value)) +} + +// OnChanged registers f to be run when the user changes the value +// of the Slider. Only one function can be registered at a time. +func (s *Slider) OnChanged(f func(*Slider)) { + s.onChanged = f +} + +//export pkguiDoSliderOnChanged +func pkguiDoSliderOnChanged(ss *C.uiSlider, data unsafe.Pointer) { + s := ControlFromLibui(uintptr(unsafe.Pointer(ss))).(*Slider) + if s.onChanged != nil { + s.onChanged(s) + } +} diff --git a/spinbox.go b/spinbox.go new file mode 100644 index 0000000..a7161f3 --- /dev/null +++ b/spinbox.go @@ -0,0 +1,55 @@ +// 12 december 2015 + +package ui + +import ( + "unsafe" +) + +// #include "pkgui.h" +import "C" + +// Spinbox is a Control that represents a space where the user can +// enter integers. The space also comes with buttons to add or +// subtract 1 from the integer. +type Spinbox struct { + ControlBase + s *C.uiSpinbox + onChanged func(*Spinbox) +} + +// NewSpinbox creates a new Spinbox. If min >= max, they are swapped. +func NewSpinbox(min int, max int) *Spinbox { + s := new(Spinbox) + + s.s = C.uiNewSpinbox(C.int(min), C.int(max)) + + C.pkguiSpinboxOnChanged(s.s) + + s.ControlBase = NewControlBase(s, uintptr(unsafe.Pointer(s.s))) + return s +} + +// Value returns the Spinbox's current value. +func (s *Spinbox) Value() int { + return int(C.uiSpinboxValue(s.s)) +} + +// SetValue sets the Spinbox's current value to value. +func (s *Spinbox) SetValue(value int) { + C.uiSpinboxSetValue(s.s, C.int(value)) +} + +// OnChanged registers f to be run when the user changes the value +// of the Spinbox. Only one function can be registered at a time. +func (s *Spinbox) OnChanged(f func(*Spinbox)) { + s.onChanged = f +} + +//export pkguiDoSpinboxOnChanged +func pkguiDoSpinboxOnChanged(ss *C.uiSpinbox, data unsafe.Pointer) { + s := ControlFromLibui(uintptr(unsafe.Pointer(ss))).(*Spinbox) + if s.onChanged != nil { + s.onChanged(s) + } +} diff --git a/tab.go b/tab.go new file mode 100644 index 0000000..d744769 --- /dev/null +++ b/tab.go @@ -0,0 +1,87 @@ +// 12 december 2015 + +package ui + +import ( + "unsafe" +) + +// #include "pkgui.h" +import "C" + +// Tab is a Control that holds tabbed pages of Controls. Each tab +// has a label. The user can click on the tabs themselves to switch +// pages. Individual pages can also have margins. +type Tab struct { + ControlBase + t *C.uiTab + children []Control +} + +// NewTab creates a new Tab. +func NewTab() *Tab { + t := new(Tab) + + t.t = C.uiNewTab() + + t.ControlBase = NewControlBase(t, uintptr(unsafe.Pointer(t.t))) + return t +} + +// Destroy destroys the Tab. If the Tab has pages, +// Destroy calls Destroy on the pages's Controls as well. +func (t *Tab) Destroy() { + for len(t.children) != 0 { + c := t.children[0] + t.Delete(0) + c.Destroy() + } + t.ControlBase.Destroy() +} + +// Append adds the given page to the end of the Tab. +func (t *Tab) Append(name string, child Control) { + t.InsertAt(name, len(t.children), child) +} + +// InsertAt adds the given page to the Tab such that it is the +// nth page of the Tab (starting at 0). +func (t *Tab) InsertAt(name string, n int, child Control) { + c := (*C.uiControl)(nil) + if child != nil { + c = touiControl(child.LibuiControl()) + } + cname := C.CString(name) + C.uiTabInsertAt(t.t, cname, C.int(n), c) + freestr(cname) + ch := make([]Control, len(t.children) + 1) + // and insert into t.children at the right place + copy(ch[:n], t.children[:n]) + ch[n] = child + copy(ch[n + 1:], t.children[n:]) + t.children = ch +} + +// Delete deletes the nth page of the Tab. +func (t *Tab) Delete(n int) { + t.children = append(t.children[:n], t.children[n + 1:]...) + C.uiTabDelete(t.t, C.int(n)) +} + +// NumPages returns the number of pages in the Tab. +func (t *Tab) NumPages() int { + return len(t.children) +} + +// Margined returns whether page n (starting at 0) of the Tab +// has margins around its child. +func (t *Tab) Margined(n int) bool { + return tobool(C.uiTabMargined(t.t, C.int(n))) +} + +// SetMargined controls whether page n (starting at 0) of the Tab +// has margins around its child. The size of the margins are +// determined by the OS and its best practices. +func (t *Tab) SetMargined(n int, margined bool) { + C.uiTabSetMargined(t.t, C.int(n), frombool(margined)) +} -- cgit v1.2.3