ui

package module
v0.0.0-...-e34c561 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Apr 17, 2015 License: MIT Imports: 8 Imported by: 0

README

ui: platform-native GUI library for Go

NOTE

ui is currently being rewritten for stability. The guts of the package will now be in C. For progress updates, see the new repo for the C backend.

Feature requests wanted! (Really; IDK what to add next!)

This is a library that aims to provide simple GUI software development in Go. It runs on/requires:

  • Windows: cgo, MinGW-w64 (see note below), Windows XP and newer
    • Note: Notice I specifically said MinGW-w64 here. This is important: regular MinGW is missing various recent header files which package ui uses, and thus won't build with it. Make sure your MinGW is that version instead. If you're running on Windows and are not sure what to download, get the mingw-builds distribution.
  • Mac OS X: cgo, Mac OS X 10.7 and newer
  • other Unixes: cgo, GTK+ 3.4 and newer

Go 1.4 RC1 or newer (including Go tip/master/direct from the source repository) is required. This is due to a variety of compiler and linker bugs on Windows and Mac OS X spanning the Go 1.3 release family.

(this README needs some work)

Be sure to have at least each outermost Window escaping to the heap until a good resolution to Go issue 8310 comes out.

prevlib.tar contains the previous version of the library as it stood when I restarted; don't bother using it.

Documentation

The in-code documentation needs improvement. I have written a tutorial in the Wiki.

Updates

21 February 2015
Implemented Table column headers as a uicolumn: struct tag.

This will probably be the last change for a while; I want to redo the backend again.

19 February 2015
ImageList is now gone; you simply store *image.RGBAs in your Table data structure and they'll work.

Alongside this change is the introduction of a new backend for Table on Windows that should be more flexible than the standard list view control. This control is implemented in the wintable/ folder; it is implemented in C and will one day be spun off into its own project for general-purpose use. I have tried to make it work as much like the standard list view control as possible, and it mostly works fine. That being said, there are still issues and incompletenesses. Please feel free to report any issues you may have found (though watch the TODOs in the source; I may know about the issue already).

5 November 2014
TextFields can now be marked as read-only (non-editable). Textboxes will gain this ability soon.

4 November 2014
Added two new controls, Spinbox (which allows numeric entry with up and down buttons) and ProgressBar (which measures progress). Both aren't fully fleshed out, but are good enough for general use now.

28 October 2014
Mac OS X resizing issues should be (mostly?) fixed now. Textbox still doesn't work right...

24 October 2014
Textbox, a multi-line version of TextField, has been added. (Note that it may not work properly on Mac OS X; this is being investigated.) In addition, excess space around controls on Mac OS X should be settled now.

18 October 2014
The container system was rewritten entirely. You can now set a margin on Windows and Groups and spacing between controls ("padding") on Stacks, Grids, and SimpleGrids. Margins on Tabs will come soon. The work needed to change this will make future additions (like Popover and Spinbox) easier/more sensible. (The Mac OS X code is still glitchy; mind the dust.)

As part of the change, standalone Labels have been removed. All Labels now behave like standalone labels. A new layout container, Form, will be introduced in the near future to allow proper layout of widgets with labels.

3 September 2014
The new GtkGrid-style Grid is now implemented! See its documentation for more details. Also, debugging spew has been removed.

31 August 2014
Grid is now renamed SimpleGrid in preparation for implementing a more GtkGrid-like Grid. Mind the change.

Screenshots

The example widget gallery on GTK+ in the Adwaita theme (3.13/master):

widget gallery example

Documentation

Overview

[this is being written]

notes: - default behavior of event handlers is to do nothing - default behavior of event handlers that return bool is to do nothing but return false - passing nil to an event handler set function restores default behavior - only functions safe for calling outside Do() are Go(), Do(), and Stop()

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

func Do

func Do(f func())

Do performs f on the main loop, as if it were an event handler. It waits for f to execute before returning. Do cannot be called within event handlers or within Do itself.

func Go

func Go() error

Go initializes and runs package ui. It returns a non-nil error if initialization fails. Otherwise, it will run the event loop and not return until Stop is called. Due to platform-specific issues, it must be called from the main OS thread; in general, do not call Go() from anywhere except main() (including any goroutines).

func OpenFile

func OpenFile(win Window, f func(filename string))

OpenFile opens a dialog box that asks the user to choose a file. The dialog box is modal to win, which mut not be nil. Some time after the dialog box is closed, OpenFile runs f on the main thread, passing filename. filename is the selected filename, or an empty string if no file was chosen. OpenFile does not ensure that f remains alive; the programmer is responsible for this. If possible on a given system, OpenFile() will not dereference links; it will return the link file itself. Hidden files will not be hidden by OpenFile().

func Stop

func Stop()

Stop informs package ui that it should stop. Stop then returns immediately. Some time after this request is received, Go() will return without performing any final cleanup. Stop will not have an effect until any event handlers return.

Types

type Align

type Align uint

Align represents the alignment of a Control in its cell of a Grid.

const (
	LeftTop Align = iota
	Center
	RightBottom
	Fill
)

type Area

type Area interface {
	Control

	// SetSize sets the Area's internal drawing size.
	// It has no effect on the actual control size.
	// SetSize will also signal the entirety of the Area to be redrawn as in RepaintAll.
	// It panics if width or height is zero or negative.
	SetSize(width int, height int)

	// Repaint marks the given rectangle of the Area as needing to be redrawn.
	// The given rectangle is clipped to the Area's size.
	// If, after clipping, the rectangle is empty, Repaint does nothing.
	Repaint(r image.Rectangle)

	// RepaintAll marks the entirety of the Area as needing to be redrawn.
	RepaintAll()

	// OpenTextFieldAt opens a TextField with the top-left corner at the given coordinates of the Area.
	// It panics if the coordinates fall outside the Area.
	// Any text previously in the TextField (be it by the user or by a call to SetTextFieldText()) is retained.
	// The TextField receives the input focus so the user can type things; when the TextField loses the input focus, it hides itself and signals the event set by OnTextFieldDismissed.
	// The TextField will also dismiss itself on some platforms when the user "completes editing"; the exact meaning of this is platform-specific.
	OpenTextFieldAt(x int, y int)

	// TextFieldText and TextFieldSetText get and set the OpenTextFieldAt TextField's text, respectively.
	TextFieldText() string
	SetTextFieldText(text string)

	// OnTextFieldDismissed is an event that is fired when the OpenTextFieldAt TextField is dismissed.
	OnTextFieldDismissed(f func())
}

Area represents a blank canvas upon which programs may draw anything and receive arbitrary events from the user. An Area has an explicit size, represented in pixels, that may be different from the size shown in its Window. For information on scrollbars, see "Scrollbars" in the Overview. The coordinate system of an Area always has an origin of (0,0) which maps to the top-left corner; all image.Points and image.Rectangles sent across Area's channels conform to this. The size of an Area must be at least 1x1 (that is, neither its width nor its height may be zero or negative). For control layout purposes, an Area prefers to be at the size you set it to (so if an Area is not stretchy in its layout, it will ask to have that size).

To handle events to the Area, an Area must be paired with an AreaHandler. See AreaHandler for details.

Area will accept keyboard focus if tabbed into, but will refuse to relinquish keyboard focus if tabbed out.

Do not use an Area if you intend to read text. Area reads keys based on their position on a standard 101-key keyboard, and does no character processing. Character processing methods differ across operating systems; trying ot recreate these yourself is only going to lead to trouble. If you absolutely need to enter text somehow, use OpenTextFieldAt() and its related methods.

func NewArea

func NewArea(width int, height int, handler AreaHandler) Area

NewArea creates a new Area with the given size and handler. It panics if handler is nil or if width or height is zero or negative.

type AreaHandler

type AreaHandler interface {
	// Paint is called when the Area needs to be redrawn.
	// The part of the Area that needs to be redrawn is stored in cliprect.
	// Before Paint() is called, this region is cleared with a system-defined background color.
	// You MUST handle this event, and you MUST return a valid image, otherwise deadlocks and panicking will occur.
	// The image returned must have the same size as rect (but does not have to have the same origin points).
	// Example:
	// 	imgFromFile, _, err := image.Decode(file)
	// 	if err != nil { panic(err) }
	// 	img := image.NewRGBA(imgFromFile.Rect)
	// 	draw.Draw(img, img.Rect, imgFromFile, image.ZP, draw.Over)
	// 	// ...
	// 	func (h *myAreaHandler) Paint(rect image.Rectangle) *image.RGBA {
	// 		return img.SubImage(rect).(*image.RGBA)
	// 	}
	Paint(cliprect image.Rectangle) *image.RGBA

	// Mouse is called when the Area receives a mouse event.
	// You are allowed to do nothing in this handler (to ignore mouse events).
	// See MouseEvent for details.
	// After handling the mouse event, package ui will decide whether to perform platform-dependent event chain continuation based on that platform's designated action (so it is not possible to override global mouse events this way).
	Mouse(e MouseEvent)

	// Key is called when the Area receives a keyboard event.
	// Return true to indicate that you handled the event; return false to indicate that you did not and let the system handle the event.
	// You are allowed to do nothing in this handler (to ignore keyboard events); in this case, return false.
	// See KeyEvent for details.
	Key(e KeyEvent) (handled bool)
}

AreaHandler represents the events that an Area should respond to. These methods are all executed on the main goroutine, not necessarily the same one that you created the AreaHandler in; you are responsible for the thread safety of any members of the actual type that implements ths interface. (Having to use this interface does not strike me as being particularly Go-like, but the nature of Paint makes channel-based event handling a non-option; in practice, deadlocks occur.)

type Button

type Button interface {
	Control

	// OnClicked sets the event handler for when the Button is clicked.
	OnClicked(func())

	// Text and SetText get and set the Button's label text.
	Text() string
	SetText(text string)
}

Button is a clickable button that performs some task.

func NewButton

func NewButton(text string) Button

NewButton creates a new Button with the given label text.

type Checkbox

type Checkbox interface {
	Control

	// OnToggled sets the event handler for when the Checkbox is toggled.
	OnToggled(func())

	// Text and SetText get and set the Checkbox's label text.
	Text() string
	SetText(text string)

	// Checked and SetChecked get and set the Checkbox's check state.
	Checked() bool
	SetChecked(checked bool)
}

Checkbox is a clickable box that indicates some Boolean value.

func NewCheckbox

func NewCheckbox(text string) Checkbox

NewCheckbox creates a new Checkbox with the given label text. The Checkbox will be initially unchecked.

type Control

type Control interface {
	// contains filtered or unexported methods
}

Control represents a control.

func Space

func Space() Control

Space returns a null Control intended for padding layouts with blank space. It appears to its owner as a Control of 0x0 size.

For a Stack, Space can be used to insert spaces in the beginning or middle of Stacks (Stacks by nature handle spaces at the end themselves). In order for this to work properly, make the Space stretchy.

For a SimpleGrid, Space can be used to have an empty cell. A stretchy Grid cell with a Space can be used to anchor the perimeter of a Grid to the respective Window edges without making one of the other controls stretchy instead (leaving empty space in the Window otherwise). Otherwise, you do not need to do anything special for the Space to work (though remember that an entire row or column of Spaces will appear as having height or width zero, respectively, unless one is marked as stretchy).

The value returned from Space() is guaranteed to be unique.

type ExtKey

type ExtKey uintptr

ExtKey represents keys that are not in the typewriter section of the keyboard.

const (
	Escape ExtKey = iota + 1
	Insert        // equivalent to "Help" on Apple keyboards
	Delete
	Home
	End
	PageUp
	PageDown
	Up
	Down
	Left
	Right
	F1 // F1..F12 are guaranteed to be consecutive
	F2
	F3
	F4
	F5
	F6
	F7
	F8
	F9
	F10
	F11
	F12
	N0 // numpad keys; independent of Num Lock state
	N1 // N0..N9 are guaranteed to be consecutive
	N2
	N3
	N4
	N5
	N6
	N7
	N8
	N9
	NDot
	NEnter
	NAdd
	NSubtract
	NMultiply
	NDivide
)

type ForeignEvent

type ForeignEvent struct {
	// contains filtered or unexported fields
}

ForeignEvent wraps a channel in such a way that it can be used safely with package ui.

func NewForeignEvent

func NewForeignEvent(channel interface{}, handler func(data interface{})) *ForeignEvent

NewForeignEvent creates a new ForeignEvent with the specified channel. It panics if the argument is not a receivable channel. The returned ForeignEvent assumes ownership of the channel. Each time a value is received on the channel, the returned function is invoked on the main thread.

func (*ForeignEvent) Stop

func (fe *ForeignEvent) Stop()

Stop ceases all future invocations of the handler passed to NewForeignEvent() on fe; the values read from the channel are merely discarded.

type Grid

type Grid interface {
	Control

	// Add adds a Control to the Grid.
	// If this is the first Control in the Grid, it is merely added; nextTo should be nil.
	// Otherwise, it is placed relative to nextTo.
	// If nextTo is nil, it is placed next to the previously added Control.
	// The effect of adding the same Control multiple times is undefined, as is the effect of adding a Control next to one not present in the Grid.
	// The effect of overlapping spanning Controls is also undefined.
	// Add panics if either xspan or yspan are zero or negative.
	Add(control Control, nextTo Control, side Side, xexpand bool, xalign Align, yexpand bool, yalign Align, xspan int, yspan int)

	// Padded and SetPadded get and set whether the controls of the Grid have padding between them.
	// The size of the padding is platform-dependent.
	Padded() bool
	SetPadded(padded bool)
}

Grid is a Control that arranges other Controls in a grid. Grid is a very powerful container: it can position and size each Control in several ways and can (and must) have Controls added to it at any time, in any direction. it can also have Controls spanning multiple rows and columns.

Each Control in a Grid has associated "expansion" and "alignment" values in both the X and Y direction. Expansion determines whether all cells in the same row/column are given whatever space is left over after figuring out how big the rest of the Grid should be. Alignment determines the position of a Control relative to its cell after computing the above. The special alignment Fill can be used to grow a Control to fit its cell. Note that expansion and alignment are independent variables. For more information on expansion and alignment, read https://developer.gnome.org/gtk3/unstable/ch28s02.html.

func NewGrid

func NewGrid() Grid

NewGrid creates a new Grid with no Controls.

type Group

type Group interface {
	Control

	// Text and SetText get and set the Group's label text.
	Text() string
	SetText(text string)

	// Margined and SetMargined get and set whether the contents of the Group have a margin around them.
	// The size of the margin is platform-dependent.
	Margined() bool
	SetMargined(margined bool)
}

Group is a Control that holds a single Control; if that Control also contains other Controls, then the Controls will appear visually grouped together. The appearance of a Group varies from system to system; for the most part a Group consists of a thin frame. All Groups have a text label indicating what the Group is for.

func NewGroup

func NewGroup(text string, control Control) Group

NewGroup creates a new Group with the given text label and child Control.

type KeyEvent

type KeyEvent struct {
	// Key is a byte representing a character pressed
	// in the typewriter section of the keyboard.
	// The value, which is independent of whether the
	// Shift key is held, is a constant with one of the
	// following (case-sensitive) values, drawn according
	// to the key's position on the keyboard.
	//    ` 1 2 3 4 5 6 7 8 9 0 - =
	//     q w e r t y u i o p [ ] \
	//      a s d f g h j k l ; '
	//       z x c v b n m , . /
	// The actual key entered will be the key at the respective
	// position on the user's keyboard, regardless of the actual
	// layout. (Some keyboards move \ to either the row above
	// or the row below but in roughly the same spot; this is
	// accounted for. Some keyboards have an additonal key
	// to the left of 'z' or additional keys to the right of '='; these
	// cannot be read.)
	// In addition, Key will contain
	// - ' ' (space) if the spacebar was pressed
	// - '\t' if Tab was pressed, regardless of Modifiers
	// - '\n' if the typewriter Enter key was pressed
	// - '\b' if the typewriter Backspace key was pressed
	// If this value is zero, see ExtKey.
	Key byte

	// If Key is zero, ExtKey contains a predeclared identifier
	// naming an extended key. See ExtKey for details.
	// If both Key and ExtKey are zero, a Modifier by itself
	// was pressed. Key and ExtKey will not both be nonzero.
	ExtKey ExtKey

	// If both Key and ExtKey are zero, Modifier will contain exactly one of its bits set, indicating which Modifier was pressed or released.
	// As with Modifiers itself, there is no way to differentiate between left and right modifier keys.
	// As such, the result of pressing and/or releasing both left and right of the same Modifier is system-defined.
	// Furthermore, the result of holding down a Key or ExtKey, then pressing a Modifier, and then releasing the original key is system-defined.
	// Under no condition shall Key, ExtKey, AND Modifier all be zero.
	Modifier Modifiers

	// Modifiers contains all the modifier keys currently being held at the time of the KeyEvent.
	// If Modifier is nonzero, Modifiers will not contain Modifier itself.
	Modifiers Modifiers

	// If Up is true, the key was released; if not, the key was pressed.
	// There is no guarantee that all pressed keys shall have
	// corresponding release events (for instance, if the user switches
	// programs while holding the key down, then releases the key).
	// Keys that have been held down are reported as multiple
	// key press events.
	Up bool
}

A KeyEvent represents a keypress in an Area.

Key presses are based on their positions on a standard 101-key keyboard found on most computers. The names chosen for keys here are based on their names on US English QWERTY keyboards; see Key for details.

If a key is pressed that is not supported by Key, ExtKey, or Modifiers, no KeyEvent will be produced and package ui will behave as if false was returned from the event handler.

func (KeyEvent) EffectiveKey

func (e KeyEvent) EffectiveKey() byte

EffectiveKey returns e.Key if it is set. Otherwise, if e.ExtKey denotes a numpad key, EffectiveKey returns the equivalent e.Key value ('0'..'9', '.', '\n', '+', '-', '*', or '/'). Otherwise, EffectiveKey returns zero.

type Label

type Label interface {
	Control

	// Text and SetText get and set the Label's text.
	Text() string
	SetText(text string)
}

Label is a Control that shows a static line of text. Label shows one line of text; any text that does not fit is truncated. Labels are left-aligned. [FUTURE PLANS: For platform-specific horizontal alignment rules, use a Form.]

func NewLabel

func NewLabel(text string) Label

NewLabel creates a new Label with the given text.

type Modifiers

type Modifiers uintptr

Modifiers indicates modifier keys being held during an event. There is no way to differentiate between left and right modifier keys. As such, what KeyEvents get sent if the user does something unusual with both of a certain modifier key at once is undefined.

const (
	Ctrl  Modifiers = 1 << iota // the keys labelled Ctrl or Control on all platforms
	Alt                         // the keys labelled Alt or Option or Meta on all platforms
	Shift                       // the Shift keys
	Super                       // the Super keys on platforms that have one, or the Windows keys on Windows, or the Command keys on Mac OS X
)

type MouseEvent

type MouseEvent struct {
	// Pos is the position of the mouse in the Area at the time of the event.
	Pos image.Point

	// If the event was generated by a mouse button being pressed, Down contains the ID of that button.
	// Otherwise, Down contains 0.
	// If Down contains nonzero, the Area will also receive keyboard focus.
	Down uint

	// If the event was generated by a mouse button being released, Up contains the ID of that button.
	// Otherwise, Up contains 0.
	// If both Down and Up are 0, the event represents mouse movement (with optional held buttons for dragging; see below).
	// Down and Up shall not both be nonzero.
	Up uint

	// If Down is nonzero, Count indicates the number of clicks: 1 for single-click, 2 for double-click, 3 for triple-click, and so on.
	// The order of events will be Down:Count=1 -> Up -> Down:Count=2 -> Up -> Down:Count=3 -> Up -> ...
	Count uint

	// Modifiers is a bit mask indicating the modifier keys being held during the event.
	Modifiers Modifiers

	// Held is a slice of button IDs that indicate which mouse buttons are being held during the event.
	// Held will not include Down and Up.
	// Held will be sorted.
	// Only buttons 1, 2, and 3 are guaranteed to be detected by Held properly; whether or not any others are is implementation-defined.
	//
	// If Held is non-empty but Up and Down are both zero, the mouse is being dragged, with all the buttons in Held being held.
	// Whether or not a drag into an Area generates MouseEvents is implementation-defined.
	// Whether or not a drag over an Area when the program is inactive generates MouseEvents is also implementation-defined.
	// Moving the mouse over an Area when the program is inactive and no buttons are held will, however, generate MouseEvents.
	Held []uint
}

MouseEvent contains all the information for a mous event sent by Area.Mouse. Mouse button IDs start at 1, with 1 being the left mouse button, 2 being the middle mouse button, and 3 being the right mouse button. If additional buttons are supported, they will be returned with 4 being the first additional button. For example, on Unix systems where mouse buttons 4 through 7 are pseudobuttons for the scroll wheel directions, the next button, button 8, will be returned as 4, 9 as 5, etc. The association between button numbers and physical buttons are system-defined. For example, on Windows, buttons 4 and 5 are mapped to what are internally referred to as "XBUTTON1" and "XBUTTON2", which often correspond to the dedicated back/forward navigation buttons on the sides of many mice. The examples here are NOT a guarantee as to how many buttons maximum will be available on a given system.

If the user clicked on the Area to switch to the Window it is contained in from another window in the OS, the Area will receive a MouseEvent for that click.

func (MouseEvent) HeldBits

func (e MouseEvent) HeldBits() (h uintptr)

HeldBits returns Held as a bit mask. Bit 0 maps to button 1, bit 1 maps to button 2, etc.

type ProgressBar

type ProgressBar interface {
	Control

	// Percent and SetPrecent get and set the current percentage indicated by the ProgressBar, respectively.
	// This value must be between 0 and 100; all other values cause SetPercent to panic.
	// TODO rename to Progress/SetProgress?
	Percent() int
	SetPercent(percent int)
}

ProgressBar is a Control that displays a horizontal bar which shows the level of completion of an operation. TODO indetermiante

func NewProgressBar

func NewProgressBar() ProgressBar

NewProgressBar creates a new ProgressBar. It will initially show a progress of 0%.

type Side

type Side uint

Side represents a side of a Control to add other Controls to a Grid to.

const (
	West Side = iota
	East
	North
	South
)

type SimpleGrid

type SimpleGrid interface {
	Control

	// SetFilling marks the given Control of the SimpleGrid as filling its cell instead of staying at its preferred size.
	// It panics if the given coordinate is invalid.
	SetFilling(row int, column int)

	// SetStretchy marks the given Control of the SimpleGrid as stretchy.
	// Stretchy implies filling.
	// Only one control can be stretchy per SimpleGrid; calling SetStretchy multiple times merely changes which control is stretchy (preserving the previous filling value).
	// It panics if the given coordinate is invalid.
	SetStretchy(row int, column int)

	// Padded and SetPadded get and set whether the controls of the SimpleGrid have padding between them.
	// The size of the padding is platform-dependent.
	Padded() bool
	SetPadded(padded bool)
}

A SimpleGrid arranges Controls in a two-dimensional grid. The height of each row and the width of each column is the maximum preferred height and width (respectively) of all the controls in that row or column (respectively). Controls are aligned to the top left corner of each cell. All Controls in a SimpleGrid maintain their preferred sizes by default; if a Control is marked as being "filling", it will be sized to fill its cell. Even if a Control is marked as filling, its preferred size is used to calculate cell sizes. One Control can be marked as "stretchy": when the Window containing the SimpleGrid is resized, the cell containing that Control resizes to take any remaining space; its row and column are adjusted accordingly (so other filling controls in the same row and column will fill to the new height and width, respectively). A stretchy Control implicitly fills its cell. All cooridnates in a SimpleGrid are given in (row,column) form with (0,0) being the top-left cell.

func NewSimpleGrid

func NewSimpleGrid(nPerRow int, controls ...Control) SimpleGrid

NewSimpleGrid creates a new SimpleGrid with the given Controls. NewSimpleGrid needs to know the number of Controls in a row (alternatively, the number of columns); it will determine the number in a column from the number of Controls given. NewSimpleGrid panics if not given a full grid of Controls. Example:

grid := NewSimpleGrid(3,
	control00, control01, control02,
	control10, control11, control12,
	control20, control21, control22)

type Spinbox

type Spinbox interface {
	Control

	// Value and SetValue get and set the current value of the Spinbox, respectively.
	// For SetValue, if the new value is outside the current range of the Spinbox, it is set to the nearest extremity.
	Value() int
	SetValue(value int)

	// OnChanged sets the event handler for when the Spinbox's value is changed.
	// Under what conditions this event is raised when the user types into the Spinbox's edit field is platform-defined.
	OnChanged(func())
}

Spinbox is a Control that provides a text entry field that accepts integers and up and down buttons to increment and decrement those values. This control is in its preliminary state. TODO everything: - TODO set increment? (work on windows) - TODO set page step? - TODO wrapping - TODO negative values

func NewSpinbox

func NewSpinbox(min int, max int) Spinbox

NewSpinbox creates a new Spinbox with the given minimum and maximum. The initial value will be the minimum value. NewSpinbox() panics if min > max.

type Stack

type Stack interface {
	Control

	// SetStretchy marks a control in a Stack as stretchy.
	// It panics if index is out of range.
	SetStretchy(index int)

	// Padded and SetPadded get and set whether the controls of the Stack have padding between them.
	// The size of the padding is platform-dependent.
	Padded() bool
	SetPadded(padded bool)
}

A Stack stacks controls horizontally or vertically within the Stack's parent. A horizontal Stack gives all controls the same height and their preferred widths. A vertical Stack gives all controls the same width and their preferred heights. Any extra space at the end of a Stack is left blank. Some controls may be marked as "stretchy": when the Window they are in changes size, stretchy controls resize to take up the remaining space after non-stretchy controls are laid out. If multiple controls are marked stretchy, they are alloted equal distribution of the remaining space.

func NewHorizontalStack

func NewHorizontalStack(controls ...Control) Stack

NewHorizontalStack creates a new Stack that arranges the given Controls horizontally.

func NewVerticalStack

func NewVerticalStack(controls ...Control) Stack

NewVerticalStack creates a new Stack that arranges the given Controls vertically.

type Tab

type Tab interface {
	Control

	// Append adds a new tab to Tab.
	// The tab is added to the end of the current list of tabs.
	Append(name string, control Control)
}

Tab is a Control that contains multiple pages of tabs, each containing a single Control. You can add and remove tabs from the Tab at any time. The appearance of a Tab with no tabs is implementation-defined.

func NewTab

func NewTab() Tab

NewTab creates a new Tab with no tabs.

type Table

type Table interface {
	Control

	// Lock and Unlock lock and unlock Data for reading or writing.
	// RLock and RUnlock lock and unlock Data for reading only.
	// These methods have identical semantics to the analogous methods of sync.RWMutex.
	// In addition, Unlock() will request an update of the Table to account for whatever was changed.
	Lock()
	Unlock()
	RLock()
	RUnlock()

	// Data returns the internal data.
	// The returned value will contain an object of type pointer to slice of some structure; use a type assertion to get the properly typed object out.
	// Do not call this outside a Lock()..Unlock() or RLock()..RUnlock() pair.
	Data() interface{}

	// Selected and Select get and set the currently selected item in the Table.
	// Selected returns -1 if no item is selected.
	// Pass -1 to Select to deselect all items.
	Selected() int
	Select(index int)

	// OnSelected is an event that gets triggered after the selection in the Table changes in whatever way (item selected or item deselected).
	OnSelected(func())
}

Table is a Control that displays a list of like-structured data in a grid where each row represents an item and each column represents a bit of data. Tables store and render a slice of struct values. Each field of the struct of type *image.RGBA is rendered as an icon. The Table itself will resize the image to an icon size if needed; the original *image.RGBA will not be modified and the icon size is implementation-defined. Each field whose type is bool or equivalent to bool is rendered as a checkbox. All other fields are rendered as strings formatted with package fmt's %v format specifier.

Tables are read-only by default, except for checkboxes, which are user-settable.

Tables have headers on top of all columns. By default, the name of the header is the same as the name of the field. If the struct field has a tag "uicolumn", its value is used as the header string instead.

Tables maintain their own storage behind a sync.RWMutex-compatible sync.Locker; use Table.Lock()/Table.Unlock() to make changes and Table.RLock()/Table.RUnlock() to merely read values.

func NewTable

func NewTable(ty reflect.Type) Table

NewTable creates a new Table. Currently, the argument must be a reflect.Type representing the structure that each item in the Table will hold, and the Table will be initially empty. This will change in the future.

type TextField

type TextField interface {
	Control

	// Text and SetText are Requests that get and set the TextField's text.
	Text() string
	SetText(text string)

	// OnChanged is triggered when the text in a TextField is changed somehow.
	// Do not bother trying to figure out how the text was changed; instead, perform your validation and use Invalid to inform the user that the entered text is invalid instead.
	OnChanged(func())

	// Invalid throws a non-modal alert (whose nature is system-defined) on or near the TextField that alerts the user that input is invalid.
	// The string passed to Invalid will be displayed to the user to inform them of what specifically is wrong with the input.
	// Pass an empty string to remove the warning.
	Invalid(reason string)

	// ReadOnly and SetReadOnly get and set whether the TextField is read-only.
	// A read-only TextField cannot be changed by the user, but its text can still be manipulated in other ways (selecting, copying, etc.).
	ReadOnly() bool
	SetReadOnly(readonly bool)
}

TextField is a Control in which the user can enter a single line of text.

func NewPasswordField

func NewPasswordField() TextField

NewPasswordField creates a new TextField for entering passwords; that is, it hides the text being entered.

func NewTextField

func NewTextField() TextField

NewTextField creates a new TextField.

type Textbox

type Textbox interface {
	Control

	// Text and SetText get and set the Textbox's text.
	Text() string
	SetText(text string)
}

Textbox represents a multi-line text entry box. Text in a Textbox is unformatted, and scrollbars are applied automatically. TODO rename to TextBox? merge with TextField (but cannot use Invalid())? enable/disable line wrapping? TODO events TODO Tab key - insert horizontal tab or tab stop? TODO ReadOnly TODO line endings

func NewTextbox

func NewTextbox() Textbox

NewTextbox creates a new Textbox.

type Window

type Window interface {
	// Title and SetTitle get and set the Window's title, respectively.
	Title() string
	SetTitle(title string)

	// Show and Hide bring the Window on-screen and off-screen, respectively.
	Show()
	Hide()

	// Close closes the Window.
	// Any Controls within the Window are destroyed, and the Window itself is also destroyed.
	// Attempting to use a Window after it has been closed results in undefined behavior.
	// Close unconditionally closes the Window; it neither raises OnClosing nor checks for a return from OnClosing.
	Close()

	// OnClosing registers an event handler that is triggered when the user clicks the Window's close button.
	// On systems where whole applications own windows, OnClosing is also triggered when the user asks to close the application.
	// If this handler returns true, the Window is closed as defined by Close above.
	// If this handler returns false, the Window is not closed.
	OnClosing(func() bool)

	// Margined and SetMargined get and set whether the contents of the Window have a margin around them.
	// The size of the margin is platform-dependent.
	Margined() bool
	SetMargined(margined bool)
	// contains filtered or unexported methods
}

Window represents a top-level window on screen that contains other Controls. Windows in package ui can only contain one control; the Stack, Grid, and SimpleGrid layout Controls allow you to pack multiple Controls in a Window. Note that a Window is not itself a Control.

func NewWindow

func NewWindow(title string, width int, height int, control Control) Window

NewWindow creates a new Window with the given title text, size, and control.

Directories

Path Synopsis
examples

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL