diff --git a/area.go b/area.go index 358a3912..1689ce8f 100644 --- a/area.go +++ b/area.go @@ -18,7 +18,7 @@ var areas = make(map[*C.uiArea]*Area) // and event handling are handled through an instance of a type // that implements AreaHandler that every Area has; see AreaHandler // for details. -// +// // There are two types of areas. Non-scrolling areas are rectangular // and have no scrollbars. Programs can draw on and get mouse // events from any point in the Area, and the size of the Area is @@ -28,7 +28,7 @@ var areas = make(map[*C.uiArea]*Area) // size changes; instead, you are given the area size as part of the // draw and mouse event handlers, for use solely within those // handlers. -// +// // Scrolling areas have horziontal and vertical scrollbars. The amount // that can be scrolled is determined by the area's size, which is // decided by the programmer (both when creating the Area and by @@ -36,7 +36,7 @@ var areas = make(map[*C.uiArea]*Area) // drawing and mouse events are automatically adjusted to match // what portion is visible, so you do not have to worry about scrolling // in your event handlers. AreaHandler has more information. -// +// // The internal coordinate system of an Area is points, which are // floating-point and device-independent. For more details, see // AreaHandler. The size of a scrolling Area must be an exact integer @@ -74,7 +74,7 @@ func NewScrollingArea(handler AreaHandler, width int, height int) *Area { a.scrolling = true a.ah = registerAreaHandler(handler) - a.a = C.uiNewScrollingArea(a.ah, C.intmax_t(width), C.intmax_t(height)) + a.a = C.uiNewScrollingArea(a.ah, C.int(width), C.int(height)) a.c = (*C.uiControl)(unsafe.Pointer(a.a)) areas[a.a] = a @@ -133,7 +133,7 @@ func (a *Area) SetSize(width int, height int) { if !a.scrolling { panic("attempt to call SetSize on non-scrolling Area") } - C.uiAreaSetSize(a.a, C.intmax_t(width), C.intmax_t(height)) + C.uiAreaSetSize(a.a, C.int(width), C.int(height)) } // QueueRedrawAll queues the entire Area for redraw. diff --git a/box.go b/box.go index caf49e38..cc72cf68 100644 --- a/box.go +++ b/box.go @@ -103,8 +103,7 @@ func (b *Box) Append(child Control, stretchy bool) { // Delete deletes the nth control of the Box. func (b *Box) Delete(n int) { b.children = append(b.children[:n], b.children[n + 1:]...) - // TODO why is this uintmax_t instead of intmax_t - C.uiBoxDelete(b.b, C.uintmax_t(n)) + C.uiBoxDelete(b.b, C.int(n)) } // Padded returns whether there is space between each control diff --git a/combobox.go b/combobox.go index 2afa294c..9aa0a045 100644 --- a/combobox.go +++ b/combobox.go @@ -114,7 +114,7 @@ func (c *Combobox) Selected() int { // SetChecked sets the currently select item in the Combobox // to index. If index is -1 no item will be selected. func (c *Combobox) SetSelected(index int) { - C.uiComboboxSetSelected(c.c, C.intmax_t(index)) + C.uiComboboxSetSelected(c.c, C.int(index)) } // OnSelected registers f to be run when the user selects an item in diff --git a/draw.go b/draw.go index eb4158d6..236410cd 100644 --- a/draw.go +++ b/draw.go @@ -9,14 +9,14 @@ package ui // static uiDrawBrush *newBrush(void) // { // uiDrawBrush *b; -// +// // b = (uiDrawBrush *) uimalloc(sizeof (uiDrawBrush)); // return b; // } // static uiDrawBrushGradientStop *newStops(size_t n) // { // uiDrawBrushGradientStop *stops; -// +// // stops = (uiDrawBrushGradientStop *) malloc(n * sizeof (uiDrawBrushGradientStop)); // // TODO // return stops; @@ -38,7 +38,7 @@ package ui // static uiDrawStrokeParams *newStrokeParams(void) // { // uiDrawStrokeParams *b; -// +// // b = (uiDrawStrokeParams *) malloc(sizeof (uiDrawStrokeParams)); // // TODO // return b; @@ -46,7 +46,7 @@ package ui // static double *newDashes(size_t n) // { // double *dashes; -// +// // dashes = (double *) malloc(n * sizeof (double)); // // TODO // return dashes; @@ -64,7 +64,7 @@ package ui // static uiDrawMatrix *newMatrix(void) // { // uiDrawMatrix *m; -// +// // m = (uiDrawMatrix *) malloc(sizeof (uiDrawMatrix)); // // TODO // return m; @@ -76,7 +76,7 @@ package ui // static uiDrawTextFontDescriptor *newFontDescriptor(void) // { // uiDrawTextFontDescriptor *desc; -// +// // desc = (uiDrawTextFontDescriptor *) malloc(sizeof (uiDrawTextFontDescriptor)); // // TODO // return desc; @@ -84,7 +84,7 @@ package ui // static uiDrawTextFont *newFont(uiDrawTextFontDescriptor *desc) // { // uiDrawTextFont *font; -// +// // font = uiDrawLoadClosestFont(desc); // free((char *) (desc->Family)); // free(desc); @@ -93,7 +93,7 @@ package ui // static uiDrawTextLayout *newTextLayout(char *text, uiDrawTextFont *defaultFont, double width) // { // uiDrawTextLayout *layout; -// +// // layout = uiDrawNewTextLayout(text, defaultFont, width); // free(text); // return layout; @@ -101,7 +101,7 @@ package ui // static uiDrawTextFontMetrics *newFontMetrics(void) // { // uiDrawTextFontMetrics *m; -// +// // m = (uiDrawTextFontMetrics *) malloc(sizeof (uiDrawTextFontMetrics)); // // TODO // return m; @@ -113,7 +113,7 @@ package ui // static double *newDouble(void) // { // double *d; -// +// // d = (double *) malloc(sizeof (double)); // // TODO // return d; @@ -135,7 +135,7 @@ import "C" // figures to a path, you must "end" the path to make it ready to draw // with. // TODO rewrite all that -// +// // Or more visually, the lifecycle of a Path is // p := NewPath() // for every figure { @@ -154,7 +154,7 @@ import "C" // dp.Context.Clip(p) // // ... // p.Free() // when done with the path -// +// // A Path also defines its fill mode. (This should ideally be a fill // parameter, but some implementations prevent it.) // TODO talk about fill modes @@ -163,7 +163,7 @@ type Path struct { } // TODO -// +// // TODO disclaimer type FillMode uint const ( @@ -274,7 +274,7 @@ type DrawContext struct { } // BrushType defines the various types of brushes. -// +// // TODO disclaimer type BrushType int const ( @@ -285,7 +285,7 @@ const ( ) // TODO -// +// // TODO disclaimer // TODO rename these to put LineCap at the beginning? or just Cap? type LineCap int @@ -296,7 +296,7 @@ const ( ) // TODO -// +// // TODO disclaimer type LineJoin int const ( @@ -514,7 +514,7 @@ func (m *Matrix) Invertible() bool { } // TODO -// +// // If m is not invertible, false is returned and m is left unchanged. func (m *Matrix) Invert() bool { cm := m.toC() @@ -564,10 +564,10 @@ func (c *DrawContext) Restore() { // call (TODO verify). Use NumFamilies to get the number of families, // and Family to get the name of a given family by index. When // finished, call Free. -// +// // There is no guarantee that the list of families is sorted. You will // need to do sorting yourself if you need it. -// +// // TODO thread affinity type FontFamilies struct { ff *C.uiDrawFontFamilies @@ -593,7 +593,7 @@ func (f *FontFamilies) NumFamilies() int { // Family returns the name of the nth family in the list. func (f *FontFamilies) Family(n int) string { - cname := C.uiDrawFontFamiliesFamily(f.ff, C.uintmax_t(n)) + cname := C.uiDrawFontFamiliesFamily(f.ff, C.int(n)) name := C.GoString(cname) C.uiFreeText(cname) return name @@ -601,12 +601,12 @@ func (f *FontFamilies) Family(n int) string { // TextWeight defines the various text weights, in order of // increasing weight. -// +// // Note that if you leave this field unset, it will default to // TextWeightThin. If you want the normal font weight, explicitly // use the constant TextWeightNormal instead. // TODO realign these? -// +// // TODO disclaimer type TextWeight int const ( @@ -624,7 +624,7 @@ const ( ) // TextItalic defines the various text italic modes. -// +// // TODO disclaimer type TextItalic int const ( @@ -635,13 +635,13 @@ const ( // TextStretch defines the various text stretches, in order of // increasing wideness. -// +// // Note that if you leave this field unset, it will default to // TextStretchUltraCondensed. If you want the normal font // stretch, explicitly use the constant TextStretchNormal // instead. // TODO realign these? -// +// // TODO disclaimer type TextStretch int const ( @@ -671,7 +671,7 @@ type Font struct { } // LoadClosestFont loads a Font. -// +// // You pass the properties of the ideal font you want to load in the // FontDescriptor you pass to this function. If the requested font // is not available on the system, the closest matching font is used. @@ -682,7 +682,7 @@ type Font struct { // description are implementation defined. This also means that // getting a descriptor back out of a Font may return a different // desriptor. -// +// // TODO guarantee that passing *that* back into LoadClosestFont() returns the same font func LoadClosestFont(desc *FontDescriptor) *Font { d := C.newFontDescriptor() // both of these are freed by C.newFont() @@ -705,11 +705,11 @@ func (f *Font) Free() { // that use reference counting for font objects, Handle does not // increment the reference count; you are sharing package ui's // reference. -// +// // On Windows this is a pointer to an IDWriteFont. -// +// // On Unix systems this is a pointer to a PangoFont. -// +// // On OS X this is a CTFontRef. func (f *Font) Handle() uintptr { return uintptr(C.uiDrawTextFontHandle(f.f)) @@ -764,7 +764,7 @@ func (f *Font) Metrics() *FontMetrics { // TextLayout is the entry point for formatting a block of text to be // drawn onto a DrawContext. -// +// // The block of text to lay out and the default font that is used if no // font attributes are applied to a given character are provided // at TextLayout creation time and cannot be changed later. @@ -772,7 +772,7 @@ func (f *Font) Metrics() *FontMetrics { // at any time, even after drawing the text once (unlike a DrawPath). // Some of these attributes also have initial values; refer to each // method to see what they are. -// +// // The block of text can either be a single line or multiple // word-wrapped lines, each with a given maximum width. type TextLayout struct { @@ -806,7 +806,7 @@ func (l *TextLayout) SetWidth(width float64) { // even if no glyph reaches to the top of its ascent or bottom of its // descent; it does not return a "best fit" rectnagle for the points that // are actually drawn. -// +// // For a single-line TextLayout (where the width is negative), if there // are no font changes throughout the TextLayout, then the height // returned by TextLayout is equivalent to the sum of the ascent and diff --git a/entry.go b/entry.go index ee14fc89..42a29936 100644 --- a/entry.go +++ b/entry.go @@ -43,6 +43,32 @@ func NewEntry() *Entry { return e } +// NewPasswordEntry creates a new Entry suitable for entering passwords. +func NewPasswordEntry() *Entry { + e := new(Entry) + + e.e = C.uiNewPasswordEntry() + e.c = (*C.uiControl)(unsafe.Pointer(e.e)) + + C.realuiEntryOnChanged(e.e) + entries[e.e] = e + + return e +} + +// NewSearchEntry creates a new Entry suitable for searching. +func NewSearchEntry() *Entry { + e := new(Entry) + + e.e = C.uiNewSearchEntry() + e.c = (*C.uiControl)(unsafe.Pointer(e.e)) + + C.realuiEntryOnChanged(e.e) + entries[e.e] = e + + return e +} + // Destroy destroys the Entry. func (e *Entry) Destroy() { delete(entries, e.e) diff --git a/form.go b/form.go new file mode 100644 index 00000000..3a3afc1e --- /dev/null +++ b/form.go @@ -0,0 +1,106 @@ +// 14 june 2016 + +package ui + +import ( + "unsafe" +) + +// #include "ui.h" +import "C" + +type Form struct { + c *C.uiControl + f *C.uiForm + + children []Control +} + +// NewForm creates a new Form. +func NewForm() *Form { + f := new(Form) + + f.f = C.uiNewForm() + f.c = (*C.uiControl)(unsafe.Pointer(f.f)) + + return f +} + +// Destroy destroys the Form. If the Form has children, +// Destroy calls Destroy on those Controls as well. +func (f *Form) Destroy() { + for len(f.children) != 0 { + c := f.children[0] + f.Delete(0) + c.Destroy() + } + C.uiControlDestroy(f.c) +} + +// LibuiControl returns the libui uiControl pointer that backs +// the Form. This is only used by package ui itself and should +// not be called by programs. +func (f *Form) LibuiControl() uintptr { + return uintptr(unsafe.Pointer(f.c)) +} + +// Handle returns the OS-level handle associated with this Form. +func (f *Form) Handle() uintptr { + return uintptr(C.uiControlHandle(f.c)) +} + +// Show shows the Form. +func (f *Form) Show() { + C.uiControlShow(f.c) +} + +// Hide hides the Form. +func (f *Form) Hide() { + C.uiControlHide(f.c) +} + +// Enable enables the Form. +func (f *Form) Enable() { + C.uiControlEnable(f.c) +} + +// Disable disables the Form. +func (f *Form) Disable() { + C.uiControlDisable(f.c) +} + +// Append adds the given control to the end of the Form. +func (f *Form) Append(label string, child Control, stretchy bool) { + clabel := C.CString(label) + + c := (*C.uiControl)(nil) + if child != nil { + c = touiControl(child.LibuiControl()) + } + + C.uiFormAppend(f.f, clabel, c, frombool(stretchy)) + freestr(clabel) + + f.children = append(f.children, child) +} + +// Delete deletes the nth control of the Form. +func (f *Form) Delete(n int) { + f.children = append(f.children[:n], f.children[n + 1:]...) + //C.uiFormDelete(f.f, C.int(n)) +} + +// TODO: InsertAt + +// Padded returns whether there is space between each control +// of the Form. +func (f *Form) Padded() bool { + return tobool(C.uiFormPadded(f.f)) +} + +// SetPadded controls whether there is space between each control +// of the Form. The size of the padding is determined by the OS and +// its best practices. +func (f *Form) SetPadded(padded bool) { + C.uiFormSetPadded(f.f, frombool(padded)) +} diff --git a/grid.go b/grid.go new file mode 100644 index 00000000..4f52a70f --- /dev/null +++ b/grid.go @@ -0,0 +1,121 @@ +// 14 june 2016 + +package ui + +import ( + "unsafe" +) + +// #include "ui.h" +import "C" + +type Align int +const ( + AlignFill Align = iota + AlignStart + AlignCenter + AlignEnd +) + +type At int +const ( + AtLeading At = iota + AtTop + AtTrailing + AtBottom +) + +// Grid is a container Control that arranges controls in rows and columns, with +// stretchy ("expanding") rows, stretchy ("expanding") columns, cells that span +// rows and columns, and cells whose content is aligned in either direction +// rather than just filling. +type Grid struct { + c *C.uiControl + g *C.uiGrid + + children []Control +} + +// NewGrid creates a new Grid. +func NewGrid() *Grid { + g := new(Grid) + + g.g = C.uiNewGrid() + g.c = (*C.uiControl)(unsafe.Pointer(g.g)) + + return g +} + +// Destroy destroys the Grid. If the Grid has children, +// Destroy calls Destroy on those Controls as well. +func (g *Grid) Destroy() { + for len(g.children) != 0 { + c := g.children[0] + g.Delete(0) + c.Destroy() + } + C.uiControlDestroy(g.c) +} + +// LibuiControl returns the libui uiControl pointer that backs +// the Grid. This is only used by package ui itself and should +// not be called by programs. +func (g *Grid) LibuiControl() uintptr { + return uintptr(unsafe.Pointer(g.c)) +} + +// Handle returns the OS-level handle associated with this Grid. +func (g *Grid) Handle() uintptr { + return uintptr(C.uiControlHandle(g.c)) +} + +// Show shows the Grid. +func (g *Grid) Show() { + C.uiControlShow(g.c) +} + +// Hide hides the Grid. +func (g *Grid) Hide() { + C.uiControlHide(g.c) +} + +// Enable enables the Grid. +func (g *Grid) Enable() { + C.uiControlEnable(g.c) +} + +// Disable disables the Grid. +func (g *Grid) Disable() { + C.uiControlDisable(g.c) +} + +// Append adds the given control to the end of the Grid. +func (g *Grid) Append(child Control, left, top, xspan, yspan int, hexpand bool, uialign Align, vexpand bool, valign Align) { + c := (*C.uiControl)(nil) + if child != nil { + c = touiControl(child.LibuiControl()) + } + C.uiGridAppend(g.g, c, C.int(left), C.int(top), C.int(xspan), C.int(yspan), frombool(hexpand), C.uiAlign(uialign), frombool(vexpand), C.uiAlign(valign)) + g.children = append(g.children, child) +} + +// Delete deletes the nth control of the Grid. +func (g *Grid) Delete(n int) { + g.children = append(g.children[:n], g.children[n + 1:]...) + //C.uiGridDelete(g.g, C.int(n)) +} + +// TODO: InsertAt + +// Padded returns whether there is space between each control +// of the Grid. +func (g *Grid) Padded() bool { + return tobool(C.uiGridPadded(g.g)) +} + +// SetPadded controls whether there is space between each control +// of the Grid. The size of the padding is determined by the OS and +// its best practices. +func (g *Grid) SetPadded(padded bool) { + C.uiGridSetPadded(g.g, frombool(padded)) +} diff --git a/libui_linux_amd64.a b/libui_linux_amd64.a index 10c78c14..c47305f7 100644 Binary files a/libui_linux_amd64.a and b/libui_linux_amd64.a differ diff --git a/multilineentry.go b/multilineentry.go new file mode 100644 index 00000000..9154fa8a --- /dev/null +++ b/multilineentry.go @@ -0,0 +1,137 @@ +// multiline entry + +package ui + +import ( + "unsafe" +) + +// #include "ui.h" +// extern void doMultilineEntryOnChanged(uiMultilineEntry*, void *); +// static inline void realuiMultilineEntryOnChanged(uiMultilineEntry *e) +// { +// uiMultilineEntryOnChanged(e, doMultilineEntryOnChanged, NULL); +// } +import "C" + +// no need to lock this; only the GUI thread can access it +var mEntries = make(map[*C.uiMultilineEntry]*MultilineEntry) + +// MultilineEntry is a Control that represents a space that the user can +// type multiple lines of text into. +type MultilineEntry struct { + c *C.uiControl + e *C.uiMultilineEntry + + onChanged func(*MultilineEntry) +} + +// NewMultilineEntry creates a new MultilineEntry. +func NewMultilineEntry() *MultilineEntry { + e := new(MultilineEntry) + + e.e = C.uiNewMultilineEntry() + e.c = (*C.uiControl)(unsafe.Pointer(e.e)) + + C.realuiMultilineEntryOnChanged(e.e) + mEntries[e.e] = e + + return e +} + +// NewMultilineNonWrappingEntry creates a new MultilineEntry. +func NewMultilineNonWrappingEntry() *MultilineEntry { + e := new(MultilineEntry) + + e.e = C.uiNewNonWrappingMultilineEntry() + e.c = (*C.uiControl)(unsafe.Pointer(e.e)) + + C.realuiMultilineEntryOnChanged(e.e) + mEntries[e.e] = e + + return e +} + +// Destroy destroys the MultilineEntry. +func (e *MultilineEntry) Destroy() { + delete(mEntries, e.e) + C.uiControlDestroy(e.c) +} + +// LibuiControl returns the libui uiControl pointer that backs +// the Window. This is only used by package ui itself and should +// not be called by programs. +func (e *MultilineEntry) LibuiControl() uintptr { + return uintptr(unsafe.Pointer(e.c)) +} + +// Handle returns the OS-level handle associated with this MultilineEntry. +func (e *MultilineEntry) Handle() uintptr { + return uintptr(C.uiControlHandle(e.c)) +} + +// Show shows the MultilineEntry. +func (e *MultilineEntry) Show() { + C.uiControlShow(e.c) +} + +// Hide hides the MultilineEntry. +func (e *MultilineEntry) Hide() { + C.uiControlHide(e.c) +} + +// Enable enables the MultilineEntry. +func (e *MultilineEntry) Enable() { + C.uiControlEnable(e.c) +} + +// Disable disables the MultilineEntry. +func (e *MultilineEntry) Disable() { + C.uiControlDisable(e.c) +} + +// Text returns the MultilineEntry's text. +func (e *MultilineEntry) Text() string { + ctext := C.uiMultilineEntryText(e.e) + text := C.GoString(ctext) + C.uiFreeText(ctext) + return text +} + +// SetText sets the MultilineEntry's text to text. +func (e *MultilineEntry) SetText(text string) { + ctext := C.CString(text) + C.uiMultilineEntrySetText(e.e, ctext) + freestr(ctext) +} + +// Append text to the MultilineEntry's text. +func (e *MultilineEntry) Append(text string) { + ctext := C.CString(text) + C.uiMultilineEntryAppend(e.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 (e *MultilineEntry) OnChanged(f func(*MultilineEntry)) { + e.onChanged = f +} + +//export doMultilineEntryOnChanged +func doMultilineEntryOnChanged(ee *C.uiMultilineEntry, data unsafe.Pointer) { + e := mEntries[ee] + if e.onChanged != nil { + e.onChanged(e) + } +} + +// ReadOnly returns whether the MultilineEntry can be changed. +func (e *MultilineEntry) ReadOnly() bool { + return tobool(C.uiMultilineEntryReadOnly(e.e)) +} + +// SetReadOnly sets whether the MultilineEntry can be changed. +func (e *MultilineEntry) SetReadOnly(ro bool) { + C.uiMultilineEntrySetReadOnly(e.e, frombool(ro)) +} diff --git a/radiobuttons.go b/radiobuttons.go index b8399ea0..7c959916 100644 --- a/radiobuttons.go +++ b/radiobuttons.go @@ -2,18 +2,26 @@ package ui -import ( - "unsafe" -) +import "unsafe" // #include "ui.h" +// extern void doRadioButtonsOnSelected(uiRadioButtons *, void *); +// static inline void realuiRadioButtonsOnSelected(uiRadioButtons *r) +// { +// uiRadioButtonsOnSelected(r, doRadioButtonsOnSelected, NULL); +// } import "C" +// no need to lock this; only the GUI thread can access it +var radioButtons = make(map[*C.uiRadioButtons]*RadioButtons) + // RadioButtons is a Control that represents a set of checkable // buttons from which exactly one may be chosen by the user. type RadioButtons struct { - c *C.uiControl - r *C.uiRadioButtons + c *C.uiControl + r *C.uiRadioButtons + + onSelected func(*RadioButtons) } // NewRadioButtons creates a new RadioButtons. @@ -23,11 +31,15 @@ func NewRadioButtons() *RadioButtons { r.r = C.uiNewRadioButtons() r.c = (*C.uiControl)(unsafe.Pointer(r.r)) + C.realuiRadioButtonsOnSelected(r.r) + radioButtons[r.r] = r + return r } // Destroy destroys the RadioButtons. func (r *RadioButtons) Destroy() { + delete(radioButtons, r.r) C.uiControlDestroy(r.c) } @@ -75,3 +87,29 @@ func (r *RadioButtons) Append(text string) { C.uiRadioButtonsAppend(r.r, ctext) freestr(ctext) } + +// Selected returns the index of the currently selected item in the +// RadioButtons. +func (r *RadioButtons) Selected() int { + return int(C.uiRadioButtonsSelected(r.r)) +} + +// SetSelected sets the currently select item 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 item 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 := radioButtons[rr] + if r.onSelected != nil { + r.onSelected(r) + } +} diff --git a/slider.go b/slider.go index 99b8d2cf..eb1031b1 100644 --- a/slider.go +++ b/slider.go @@ -31,7 +31,7 @@ type Slider struct { func NewSlider(min int, max int) *Slider { s := new(Slider) - s.s = C.uiNewSlider(C.intmax_t(min), C.intmax_t(max)) + s.s = C.uiNewSlider(C.int(min), C.int(max)) s.c = (*C.uiControl)(unsafe.Pointer(s.s)) C.realuiSliderOnChanged(s.s) @@ -90,7 +90,7 @@ func (s *Slider) Value() int { // SetText sets the Slider's current value to value. func (s *Slider) SetValue(value int) { - C.uiSliderSetValue(s.s, C.intmax_t(value)) + C.uiSliderSetValue(s.s, C.int(value)) } // OnChanged registers f to be run when the user changes the value diff --git a/spinbox.go b/spinbox.go index 5e5e43ff..26ca133c 100644 --- a/spinbox.go +++ b/spinbox.go @@ -31,7 +31,7 @@ type Spinbox struct { func NewSpinbox(min int, max int) *Spinbox { s := new(Spinbox) - s.s = C.uiNewSpinbox(C.intmax_t(min), C.intmax_t(max)) + s.s = C.uiNewSpinbox(C.int(min), C.int(max)) s.c = (*C.uiControl)(unsafe.Pointer(s.s)) C.realuiSpinboxOnChanged(s.s) @@ -93,7 +93,7 @@ func (s *Spinbox) Value() int { // SetText sets the Spinbox's current value to value. func (s *Spinbox) SetValue(value int) { - C.uiSpinboxSetValue(s.s, C.intmax_t(value)) + C.uiSpinboxSetValue(s.s, C.int(value)) } // OnChanged registers f to be run when the user changes the value diff --git a/tab.go b/tab.go index d18cecde..676c9b4e 100644 --- a/tab.go +++ b/tab.go @@ -91,8 +91,8 @@ func (t *Tab) InsertAt(name string, n int, child Control) { c = touiControl(child.LibuiControl()) } cname := C.CString(name) - // TODO why is this uintmax_t and not intmax_t - C.uiTabInsertAt(t.t, cname, C.uintmax_t(n), c) + + 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 @@ -105,7 +105,7 @@ func (t *Tab) InsertAt(name string, n int, child Control) { // 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.uintmax_t(n)) + C.uiTabDelete(t.t, C.int(n)) } // NumPages returns the number of pages in the Tab. @@ -116,12 +116,12 @@ func (t *Tab) NumPages() int { // 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.uintmax_t(n))) + 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.uintmax_t(n), frombool(margined)) + C.uiTabSetMargined(t.t, C.int(n), frombool(margined)) } diff --git a/ui.h b/ui.h index c7a8858b..5a2069e8 100644 --- a/ui.h +++ b/ui.h @@ -32,6 +32,8 @@ extern "C" { // This comes from Go's math.Pi, which in turn comes from http://oeis.org/A000796. #define uiPi 3.14159265358979323846264338327950288419716939937510582097494459 +// TODO uiBool? + typedef struct uiInitOptions uiInitOptions; struct uiInitOptions { @@ -43,6 +45,7 @@ _UI_EXTERN void uiUninit(void); _UI_EXTERN void uiFreeInitError(const char *err); _UI_EXTERN void uiMain(void); +_UI_EXTERN void uiMainSteps(void); _UI_EXTERN int uiMainStep(int wait); _UI_EXTERN void uiQuit(void); @@ -97,7 +100,14 @@ typedef struct uiWindow uiWindow; #define uiWindow(this) ((uiWindow *) (this)) _UI_EXTERN char *uiWindowTitle(uiWindow *w); _UI_EXTERN void uiWindowSetTitle(uiWindow *w, const char *title); +_UI_EXTERN void uiWindowContentSize(uiWindow *w, int *width, int *height); +_UI_EXTERN void uiWindowSetContentSize(uiWindow *w, int width, int height); +_UI_EXTERN int uiWindowFullscreen(uiWindow *w); +_UI_EXTERN void uiWindowSetFullscreen(uiWindow *w, int fullscreen); +_UI_EXTERN void uiWindowOnContentSizeChanged(uiWindow *w, void (*f)(uiWindow *, void *), void *data); _UI_EXTERN void uiWindowOnClosing(uiWindow *w, int (*f)(uiWindow *w, void *data), void *data); +_UI_EXTERN int uiWindowBorderless(uiWindow *w); +_UI_EXTERN void uiWindowSetBorderless(uiWindow *w, int borderless); _UI_EXTERN void uiWindowSetChild(uiWindow *w, uiControl *child); _UI_EXTERN int uiWindowMargined(uiWindow *w); _UI_EXTERN void uiWindowSetMargined(uiWindow *w, int margined); @@ -113,7 +123,7 @@ _UI_EXTERN uiButton *uiNewButton(const char *text); typedef struct uiBox uiBox; #define uiBox(this) ((uiBox *) (this)) _UI_EXTERN void uiBoxAppend(uiBox *b, uiControl *child, int stretchy); -_UI_EXTERN void uiBoxDelete(uiBox *b, uintmax_t index); +_UI_EXTERN void uiBoxDelete(uiBox *b, int index); _UI_EXTERN int uiBoxPadded(uiBox *b); _UI_EXTERN void uiBoxSetPadded(uiBox *b, int padded); _UI_EXTERN uiBox *uiNewHorizontalBox(void); @@ -136,6 +146,8 @@ _UI_EXTERN void uiEntryOnChanged(uiEntry *e, void (*f)(uiEntry *e, void *data), _UI_EXTERN int uiEntryReadOnly(uiEntry *e); _UI_EXTERN void uiEntrySetReadOnly(uiEntry *e, int readonly); _UI_EXTERN uiEntry *uiNewEntry(void); +_UI_EXTERN uiEntry *uiNewPasswordEntry(void); +_UI_EXTERN uiEntry *uiNewSearchEntry(void); typedef struct uiLabel uiLabel; #define uiLabel(this) ((uiLabel *) (this)) @@ -146,11 +158,11 @@ _UI_EXTERN uiLabel *uiNewLabel(const char *text); typedef struct uiTab uiTab; #define uiTab(this) ((uiTab *) (this)) _UI_EXTERN void uiTabAppend(uiTab *t, const char *name, uiControl *c); -_UI_EXTERN void uiTabInsertAt(uiTab *t, const char *name, uintmax_t before, uiControl *c); -_UI_EXTERN void uiTabDelete(uiTab *t, uintmax_t index); -_UI_EXTERN uintmax_t uiTabNumPages(uiTab *t); -_UI_EXTERN int uiTabMargined(uiTab *t, uintmax_t page); -_UI_EXTERN void uiTabSetMargined(uiTab *t, uintmax_t page, int margined); +_UI_EXTERN void uiTabInsertAt(uiTab *t, const char *name, int before, uiControl *c); +_UI_EXTERN void uiTabDelete(uiTab *t, int index); +_UI_EXTERN int uiTabNumPages(uiTab *t); +_UI_EXTERN int uiTabMargined(uiTab *t, int page); +_UI_EXTERN void uiTabSetMargined(uiTab *t, int page, int margined); _UI_EXTERN uiTab *uiNewTab(void); typedef struct uiGroup uiGroup; @@ -169,33 +181,34 @@ _UI_EXTERN uiGroup *uiNewGroup(const char *title); typedef struct uiSpinbox uiSpinbox; #define uiSpinbox(this) ((uiSpinbox *) (this)) -_UI_EXTERN intmax_t uiSpinboxValue(uiSpinbox *s); -_UI_EXTERN void uiSpinboxSetValue(uiSpinbox *s, intmax_t value); +_UI_EXTERN int uiSpinboxValue(uiSpinbox *s); +_UI_EXTERN void uiSpinboxSetValue(uiSpinbox *s, int value); _UI_EXTERN void uiSpinboxOnChanged(uiSpinbox *s, void (*f)(uiSpinbox *s, void *data), void *data); -_UI_EXTERN uiSpinbox *uiNewSpinbox(intmax_t min, intmax_t max); +_UI_EXTERN uiSpinbox *uiNewSpinbox(int min, int max); typedef struct uiSlider uiSlider; #define uiSlider(this) ((uiSlider *) (this)) -_UI_EXTERN intmax_t uiSliderValue(uiSlider *s); -_UI_EXTERN void uiSliderSetValue(uiSlider *s, intmax_t value); +_UI_EXTERN int uiSliderValue(uiSlider *s); +_UI_EXTERN void uiSliderSetValue(uiSlider *s, int value); _UI_EXTERN void uiSliderOnChanged(uiSlider *s, void (*f)(uiSlider *s, void *data), void *data); -_UI_EXTERN uiSlider *uiNewSlider(intmax_t min, intmax_t max); +_UI_EXTERN uiSlider *uiNewSlider(int min, int max); typedef struct uiProgressBar uiProgressBar; #define uiProgressBar(this) ((uiProgressBar *) (this)) -// TODO uiProgressBarValue() +_UI_EXTERN int uiProgressBarValue(uiProgressBar *p); _UI_EXTERN void uiProgressBarSetValue(uiProgressBar *p, int n); _UI_EXTERN uiProgressBar *uiNewProgressBar(void); typedef struct uiSeparator uiSeparator; #define uiSeparator(this) ((uiSeparator *) (this)) _UI_EXTERN uiSeparator *uiNewHorizontalSeparator(void); +_UI_EXTERN uiSeparator *uiNewVerticalSeparator(void); typedef struct uiCombobox uiCombobox; #define uiCombobox(this) ((uiCombobox *) (this)) _UI_EXTERN void uiComboboxAppend(uiCombobox *c, const char *text); -_UI_EXTERN intmax_t uiComboboxSelected(uiCombobox *c); -_UI_EXTERN void uiComboboxSetSelected(uiCombobox *c, intmax_t n); +_UI_EXTERN int uiComboboxSelected(uiCombobox *c); +_UI_EXTERN void uiComboboxSetSelected(uiCombobox *c, int n); _UI_EXTERN void uiComboboxOnSelected(uiCombobox *c, void (*f)(uiCombobox *c, void *data), void *data); _UI_EXTERN uiCombobox *uiNewCombobox(void); @@ -211,6 +224,9 @@ _UI_EXTERN uiEditableCombobox *uiNewEditableCombobox(void); typedef struct uiRadioButtons uiRadioButtons; #define uiRadioButtons(this) ((uiRadioButtons *) (this)) _UI_EXTERN void uiRadioButtonsAppend(uiRadioButtons *r, const char *text); +_UI_EXTERN int uiRadioButtonsSelected(uiRadioButtons *r); +_UI_EXTERN void uiRadioButtonsSetSelected(uiRadioButtons *r, int n); +_UI_EXTERN void uiRadioButtonsOnSelected(uiRadioButtons *r, void (*f)(uiRadioButtons *, void *), void *data); _UI_EXTERN uiRadioButtons *uiNewRadioButtons(void); typedef struct uiDateTimePicker uiDateTimePicker; @@ -273,15 +289,38 @@ struct uiAreaHandler { int (*KeyEvent)(uiAreaHandler *, uiArea *, uiAreaKeyEvent *); }; +// TODO RTL layouts? +// TODO reconcile edge and corner naming +_UI_ENUM(uiWindowResizeEdge) { + uiWindowResizeEdgeLeft, + uiWindowResizeEdgeTop, + uiWindowResizeEdgeRight, + uiWindowResizeEdgeBottom, + uiWindowResizeEdgeTopLeft, + uiWindowResizeEdgeTopRight, + uiWindowResizeEdgeBottomLeft, + uiWindowResizeEdgeBottomRight, + // TODO have one for keyboard resizes? + // TODO GDK doesn't seem to have any others, including for keyboards... + // TODO way to bring up the system menu instead? +}; + #define uiArea(this) ((uiArea *) (this)) // TODO give a better name // TODO document the types of width and height -_UI_EXTERN void uiAreaSetSize(uiArea *a, intmax_t width, intmax_t height); +_UI_EXTERN void uiAreaSetSize(uiArea *a, int width, int height); // TODO uiAreaQueueRedraw() _UI_EXTERN void uiAreaQueueRedrawAll(uiArea *a); _UI_EXTERN void uiAreaScrollTo(uiArea *a, double x, double y, double width, double height); +// TODO document these can only be called within Mouse() handlers +// TODO should these be allowed on scrolling areas? +// TODO decide which mouse events should be accepted; Down is the only one guaranteed to work right now +// TODO what happens to events after calling this up to and including the next mouse up? +// TODO release capture? +_UI_EXTERN void uiAreaBeginUserWindowMove(uiArea *a); +_UI_EXTERN void uiAreaBeginUserWindowResize(uiArea *a, uiWindowResizeEdge edge); _UI_EXTERN uiArea *uiNewArea(uiAreaHandler *ah); -_UI_EXTERN uiArea *uiNewScrollingArea(uiAreaHandler *ah, intmax_t width, intmax_t height); +_UI_EXTERN uiArea *uiNewScrollingArea(uiAreaHandler *ah, int width, int height); struct uiAreaDrawParams { uiDrawContext *Context; @@ -438,12 +477,12 @@ _UI_EXTERN void uiDrawRestore(uiDrawContext *c); // TODO manage the use of Text, Font, and TextFont, and of the uiDrawText prefix in general -///// TODO +///// TODO reconsider this typedef struct uiDrawFontFamilies uiDrawFontFamilies; _UI_EXTERN uiDrawFontFamilies *uiDrawListFontFamilies(void); -_UI_EXTERN uintmax_t uiDrawFontFamiliesNumFamilies(uiDrawFontFamilies *ff); -_UI_EXTERN char *uiDrawFontFamiliesFamily(uiDrawFontFamilies *ff, uintmax_t n); +_UI_EXTERN int uiDrawFontFamiliesNumFamilies(uiDrawFontFamilies *ff); +_UI_EXTERN char *uiDrawFontFamiliesFamily(uiDrawFontFamilies *ff, int n); _UI_EXTERN void uiDrawFreeFontFamilies(uiDrawFontFamilies *ff); ///// END TODO @@ -461,7 +500,7 @@ _UI_ENUM(uiDrawTextWeight) { uiDrawTextWeightMedium, uiDrawTextWeightSemiBold, uiDrawTextWeightBold, - uiDrawTextWeightUtraBold, + uiDrawTextWeightUltraBold, uiDrawTextWeightHeavy, uiDrawTextWeightUltraHeavy, }; @@ -517,7 +556,7 @@ _UI_EXTERN void uiDrawTextLayoutSetWidth(uiDrawTextLayout *layout, double width) _UI_EXTERN void uiDrawTextLayoutExtents(uiDrawTextLayout *layout, double *width, double *height); // and the attributes that you can set on a text layout -_UI_EXTERN void uiDrawTextLayoutSetColor(uiDrawTextLayout *layout, intmax_t startChar, intmax_t endChar, double r, double g, double b, double a); +_UI_EXTERN void uiDrawTextLayoutSetColor(uiDrawTextLayout *layout, int startChar, int endChar, double r, double g, double b, double a); _UI_EXTERN void uiDrawText(uiDrawContext *c, double x, double y, uiDrawTextLayout *layout); @@ -538,10 +577,10 @@ struct uiAreaMouseEvent { double AreaWidth; double AreaHeight; - uintmax_t Down; - uintmax_t Up; + int Down; + int Up; - uintmax_t Count; + int Count; uiModifiers Modifiers; @@ -615,6 +654,36 @@ _UI_EXTERN void uiColorButtonSetColor(uiColorButton *b, double r, double g, doub _UI_EXTERN void uiColorButtonOnChanged(uiColorButton *b, void (*f)(uiColorButton *, void *), void *data); _UI_EXTERN uiColorButton *uiNewColorButton(void); +typedef struct uiForm uiForm; +#define uiForm(this) ((uiForm *) (this)) +_UI_EXTERN void uiFormAppend(uiForm *f, const char *label, uiControl *c, int stretchy); +_UI_EXTERN void uiFormDelete(uiForm *f, int index); +_UI_EXTERN int uiFormPadded(uiForm *f); +_UI_EXTERN void uiFormSetPadded(uiForm *f, int padded); +_UI_EXTERN uiForm *uiNewForm(void); + +_UI_ENUM(uiAlign) { + uiAlignFill, + uiAlignStart, + uiAlignCenter, + uiAlignEnd, +}; + +_UI_ENUM(uiAt) { + uiAtLeading, + uiAtTop, + uiAtTrailing, + uiAtBottom, +}; + +typedef struct uiGrid uiGrid; +#define uiGrid(this) ((uiGrid *) (this)) +_UI_EXTERN void uiGridAppend(uiGrid *g, uiControl *c, int left, int top, int xspan, int yspan, int hexpand, uiAlign halign, int vexpand, uiAlign valign); +_UI_EXTERN void uiGridInsertAt(uiGrid *g, uiControl *c, uiControl *existing, uiAt at, int xspan, int yspan, int hexpand, uiAlign halign, int vexpand, uiAlign valign); +_UI_EXTERN int uiGridPadded(uiGrid *g); +_UI_EXTERN void uiGridSetPadded(uiGrid *g, int padded); +_UI_EXTERN uiGrid *uiNewGrid(void); + #ifdef __cplusplus } #endif diff --git a/window.go b/window.go index bdd230c6..9ed18e03 100644 --- a/window.go +++ b/window.go @@ -114,6 +114,10 @@ func (w *Window) SetTitle(title string) { freestr(ctitle) } +// TODO: uiWindowContentSize, uiWindowSetContentSize +// TODO: uiWindowFullscreen, uiWindowSetFullscreen +// TODO: uiWindowOnContentSizeChanged + // OnClosing registers f to be run when the user clicks the Window's // close button. Only one function can be registered at a time. // If f returns true, the window is destroyed with the Destroy method.