ui

package module
v0.0.0-...-6c3058a Latest Latest
Warning

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

Go to latest
Published: Apr 15, 2014 License: MIT Imports: 8 Imported by: 0

README

Build Status

Native UI library for Go

THIS PACKAGE IS UNDER ACTIVE DEVELOPMENT. It can be used; the API is stable enough at this point, but keep in mind there may still be crashes and API changes, as suggestions are always open. If you can help, please do! Run ./test to build a test binary test/test which runs a (mostly) feature-complete UI test. Run ./d32 ./test to build a 32-bit version (you will need a cgo-enabled 32-bit go environment, and I have only tested this on Mac OS X).
UPDATE 12 March 2014: Windows 2000 is no longer supported as it is no longer supported by Go.
UPDATE 18 March 2014: Resizes are now assumed to stop other UI event processing, and thus do not run with locks anymore. I changed real control resizing so that it doesn't need to lock (it just fills an array with data fed in), but real control preferredSize() and Stack/Grid.setRect() could potentially still be racy... if I am right it won't be an issue, but if anyone else knows, please let me know. (Everything else is thread-safe again.)
UPDATE 27 March 2014: Unix builds now require go tip due to a cgo fix that affected this package.
UPDATE 12 April 2014: Areas now require their images to be image.RGBA, not image.NRGBA. Update your code appropriately.

This is a simple library for building cross-platform GUI programs in Go. It targets Windows, Mac OS X, Linux, and other Unixes, and provides a thread-safe, channel-based API. The API itself is minimal; it aims to provide only what is necessary for GUI program design. That being said, suggestions are welcome. Layout is done using various layout managers, and some effort is taken to conform to the target platform's UI guidelines. Otherwise, the library uses native toolkits.

ui aims to run on all supported versions of supported platforms. To be more precise, the system requirements are:

  • Windows: Windows XP or newer. The Windows backend uses package syscall and calls Windows DLLs directly, so does not rely on cgo.
  • Mac OS X: Mac OS X 10.6 (Snow Leopard) or newer. Objective-C dispatch is done by interfacing with libobjc directly, and thus this uses cgo.
    • Note: you will need Go 1.3 or newer (so until it is released, go tip) for this verison, as it uses a single .m file due to technical restrictions (read the comments in bleh_darwin.m for details), and earlier versions of Go do not auto-build .m files.
  • Other Unixes: The Unix backend uses GTK+, and thus cgo. It requires GTK+ 3.4 or newer; for Ubuntu this means 12.04 LTS (Precise Pangolin) at minimum. Check your distribution.
    • Note: you will need Go 1.3 or newer (as above) due to various cgo errors fixed in this version (such as this one).

ui itself has no outside Go package dependencies; it is entirely self-contained.

To install, simply go get this package. On Mac OS X, make sure you have the Apple development headers. On other Unixes, make sure you have the GTK+ development files:

  • for Ubuntu, libgtk-3-dev is sufficient
  • for FreeBSD with the pkgng system, gtk3 is sufficient, however you will need to manually install pkgconf to please cgo (and you may need to specify CC=gcc47) (this should be put on the Go wiki)

Package documentation is available at http://godoc.org/github.com/andlabs/ui.

For an example of how ui is used, see https://github.com/andlabs/wakeup, which is a small program that implements a basic alarm clock.

Known To Have Ever Been Built Matrices

For convenience's sake, here are matrices of builds that I have personally done at least once. Each cell represents the run status. These matrices represent builds that I have done at any point in development; it is not a guarantee that the current version works. (I built this list to answer questions of whether or not ui works with a specific configuration.) Only configurations marked with a * are tested during active development. "(invalid)" means the given OS/arch combination is not supported by Go.

| 386 | amd64 | arm ----- | ----- | ----- | ----- windows | works on windows; works on wine* | works on windows; fails on wine | (invalid) linux | see table below | see table below | Raspian: works darwin (Mac OS X) | works* (cross-compiled from 64-bit) | works* | (invalid) dragonfly | untested | untested | (invalid) freebsd | works | untested (VM failure) | untested netbsd | untested | untested | untested openbsd | untested | untested | (invalid) solaris | (invalid) | Oracle Solaris 11: GTK+ 3 not available from official repos | (invalid) plan9 | (not written yet; problems building Go) | (not written) | (invalid) nacl | (not sure how to handle) | (not sure how to handle) | (invalid)

linux | 386 | amd64 ----- | ----- | ----- | ----- Kubuntu (14.04) | works; cross-compiling on 64-bit Linux fails due to nonexistent .so symlinks | works* Fedora | untested | untested openSUSE | untested | untested Arch Linux | untested | untested Mandriva (TODO choose between PCLinuxOS and Mageia - it appears the original Mandriva is either dead or nonfree and I would rather choose the fork that structures packages identically for parity; do they both?) | untested | untested Slackware | untested | untested Gentoo | untested | untested

(The above list should cover all the bases of major Linux distributions and variants thereof; I might add a dedicated Debian test later but other than that... suggestions welcome. Kubuntu 64-bit is my main system and the main development platform; the Windows builds are cross-compiled from here. And yes, this also implies I seriously consider a Plan 9 port of the library using libcontrol, though I'm guessing this will blow up in my face due to any possible conflicts between libthread and Go's runtime (I need to see how the Go runtime implements OS threads on Plan 9).)

Contributing

Contributions are welcome. File issues, pull requests, approach me on IRC (pietro10 in #go-nuts; andlabs elsewhere), etc. Even suggestions are welcome: while I'm mainly drawing from my own GUI programming experience, everyone is different. I have received emails, however I am not likely to see those right away, so I don't suggest contacting me by email if your communication is urgent.

If you want to dive in, read implementation.md: this is a description of how the library works. (Feel free to suggest improvements to this as well.) The other .md files in this repository contain various development notes.

Please suggest documentation improvements as well.

Documentation

Overview

Package ui is a simple package which provides a way to write portable GUI programs quickly and easily. It aims to run on as many systems as Go itself, but presently has support for Windows, Mac OS X, and other Unix systems using the Windows API, Cocoa, and GTK+ 3, respectively. It also aims to be Go-like: events are transmitted via channels, and the library is fully safe for concurrent use.

To use the library, place your main program code in another function and call Go(), passing that function as a parameter. (This is necessary due to threading restrictions on some environments, such as Cocoa.) Once in the function you pass to Go(), you can safely use the rest of the library. When this function returns, so does Go(), and package functions become unavailable.

Building GUIs is as simple as creating a Window, populating it with Controls, and then calling Open() on the Window. A Window only has one Control: you pack multiple Controls into a Window by arranging them in layouts (Layouts are also Controls). There are presently two Layouts, Stack and Grid, each with different semantics on sizing and placement. See their documentation.

Once a Window is open, you cannot make layout or event channel changes.

Once your Window is open, you can begin to handle events. Handling events is simple: because all events are channels exposed as exported members of the Window and Control types, simply select on them. Event channels are initialized by default. However, before you Open a Window, you can freely reassign event channels, such that multiple events trigger the same channel, making event logic more compact. You may also choose not to handle events; events are sent asynchronously so the GUI loop is not initerrupted.

Here is a simple, complete program that asks the user for their name and greets them after clicking a button.

package main

import (
	"github.com/andlabs/ui"
)

func myMain() {
	w := ui.NewWindow("Hello", 400, 100)
	ui.AppQuit = w.Closing		// treat quitting the application like closing the main window
	nameField := ui.NewLineEdit("Enter Your Name Here")
	button := ui.NewButton("Click Here For a Greeting")
	err := w.Open(ui.NewVerticalStack(nameField, button))
	if err != nil {
		panic(err)
	}

	for {
		select {
		case <-w.Closing:		// user tries to close the window or quit the program
			return
		case <-button.Clicked:	// user clicked the button
			ui.MsgBox("Hello, " + nameField.Text() + "!", "")
		}
	}
}

func main() {
	err := ui.Go(myMain)
	if err != nil {
		panic(err)
	}
}

Index

Constants

This section is empty.

Variables

View Source
var AppQuit chan struct{}

AppQuit is pulsed when the user decides to quit the program if their operating system provides a facility for quitting an entire application, rather than merely close all windows (for instance, Mac OS X via the Dock icon). You should assign one of your Windows's Closing to this variable so the user choosing to quit the application is treated the same as closing that window. If you do not respond to this signal, nothing will happen; regardless of whether or not you respond to this signal, the application will not quit. Do not merely check this channel alone; it is not guaranteed to be pulsed on all systems or in all conditions.

Functions

func Go

func Go(main func()) error

Go sets up the UI environment and runs main in a goroutine. If initialization fails, Go returns an error and main is not called. Otherwise, Go does not return to its caller until main does, at which point it returns nil. After it returns, you cannot call future ui functions/methods meaningfully. (TODO ideally we would want to be able to call ui.MsgBoxError() to report failures to the user, but I would need to figure out how to do this on platforms other than Windows.)

It is not safe to call ui.Go() in a goroutine. It must be called directly from main().

This model is undesirable, but Cocoa limitations require it.

func MsgBox

func MsgBox(primaryText string, secondaryText string)

MsgBox displays an informational message box to the user with just an OK button. primaryText should be a short string describing the message, and will be displayed with additional emphasis on platforms that support it. Optionally, secondaryText can be used to show additional information. If you pass an empty string for secondaryText, neither additional information nor space for additional information will be shown. On platforms that allow for the message box window to have a title, os.Args[0] is used.

func MsgBoxError

func MsgBoxError(primaryText string, secondaryText string)

MsgBoxError displays a message box to the user with just an OK button and an icon indicating an error. Otherwise, it behaves like MsgBox.

Types

type Area

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

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; Areas have both horizontal and vertical scrollbars that are hidden when not needed. 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).

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

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. [Use TextArea instead, providing a TextAreaHandler.]

To facilitate development and debugging, for the time being, Areas only work on GTK+.

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.

func (*Area) SetSize

func (a *Area) SetSize(width int, height int)

SetSize sets the Area's internal drawing size. It has no effect on the actual control size. SetSize is safe for concurrent use; if the Area is being repainted or is handling an event, SetSize will wait for that to complete before changing the Area's size. It panics 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.
	// If repaint is true, the Area is marked as needing to be redrawn.
	Mouse(e MouseEvent) (repaint bool)

	// Key is called when the Area receives a keyboard event.
	// You are allowed to do nothing except return false for handled in this handler (to ignore keyboard events).
	// Do not do nothing but return true for handled; this may have unintended consequences.
	// See KeyEvent for details.
	// If repaint is true, the Area is marked as needing to be redrawn.
	Key(e KeyEvent) (handled bool, repaint 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 struct {
	// Clicked gets a message when the button is clicked.
	// You cannot change it once the Window containing the Button has been opened.
	// If you do not respond to this signal, nothing will happen.
	Clicked chan struct{}
	// contains filtered or unexported fields
}

A Button represents a clickable button with some text.

func NewButton

func NewButton(text string) (b *Button)

NewButton creates a new button with the specified text.

func (*Button) SetText

func (b *Button) SetText(text string)

SetText sets the button's text.

func (*Button) Text

func (b *Button) Text() string

Text returns the button's text.

type Checkbox

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

A Checkbox is a clickable square with a label. The square can be either checked or unchecked. Checkboxes start out unchecked.

func NewCheckbox

func NewCheckbox(text string) (c *Checkbox)

NewCheckbox creates a new checkbox with the specified text.

func (*Checkbox) Checked

func (c *Checkbox) Checked() bool

Checked() returns whether or not the checkbox has been checked.

func (*Checkbox) SetText

func (c *Checkbox) SetText(text string)

SetText sets the checkbox's text.

func (*Checkbox) Text

func (c *Checkbox) Text() string

Text returns the checkbox's text.

type Combobox

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

A Combobox is a drop-down list of items, of which at most one can be selected at any given time. You may optionally make the combobox editable to allow custom items. Initially, no item will be selected (and no text entered in an editable Combobox's entry field).

func NewCombobox

func NewCombobox(items ...string) *Combobox

NewCombobox makes a new Combobox with the given items.

func NewEditableCombobox

func NewEditableCombobox(items ...string) *Combobox

NewEditableCombobox makes a new editable Combobox with the given items.

func (*Combobox) Append

func (c *Combobox) Append(what ...string)

Append adds items to the end of the Combobox's list. Append will panic if something goes wrong on platforms that do not abort themselves.

func (*Combobox) Delete

func (c *Combobox) Delete(index int)

Delete removes the given item from the Combobox. It panics if the given index is out of bounds.

func (*Combobox) InsertBefore

func (c *Combobox) InsertBefore(what string, before int)

InsertBefore inserts a new item in the Combobox before the item at the given position. It panics if the given index is out of bounds. InsertBefore will also panic if something goes wrong on platforms that do not abort themselves.

func (*Combobox) Len

func (c *Combobox) Len() int

Len returns the number of items in the Combobox.

On platforms for which this function may return an error, it panics if one is returned.

func (*Combobox) SelectedIndex

func (c *Combobox) SelectedIndex() int

SelectedIndex returns the index of the current selection in the Combobox. It returns -1 either if no selection was made or if text was manually entered in an editable Combobox.

func (*Combobox) Selection

func (c *Combobox) Selection() string

Selection returns the current selection.

type Control

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

A Control represents an UI control. Note that Control contains unexported members; this has the consequence that you can't build custom controls that interface directly with the system-specific code (fo rinstance, to import an unsupported control), or at least not without some hackery. If you want to make your own controls, create an Area and provide an AreaHandler that does what you need.

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 Grid, 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).

type ExtKey

type ExtKey uintptr

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

const (
	Escape ExtKey = iota + 1
	Insert
	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 Grid

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

A Grid 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 Grid 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 Grid 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 Grid are given in (row,column) form with (0,0) being the top-left cell. Unlike other UI toolkit Grids, this Grid does not (yet? TODO) allow Controls to span multiple rows or columns. TODO differnet row/column control alignment

func NewGrid

func NewGrid(nPerRow int, controls ...Control) *Grid

NewGrid creates a new Grid with the given Controls. NewGrid 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. NewGrid panics if not given a full grid of Controls. Example:

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

func (*Grid) SetFilling

func (g *Grid) SetFilling(row int, column int)

SetFilling marks the given Control of the Grid as filling its cell instead of staying at its preferred size. This function cannot be called after the Window that contains the Grid has been created. It panics if the given coordinate is invalid.

func (*Grid) SetStretchy

func (g *Grid) SetStretchy(row int, column int)

SetStretchy marks the given Control of the Grid as stretchy. Stretchy implies filling. Only one control can be stretchy per Grid; calling SetStretchy multiple times merely changes which control is stretchy. This function cannot be called after the Window that contains the Grid has been created. It panics if the given coordinate is invalid.

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

	// (TODO Modifiers alone needs to be figured out)
	// If a Key or ExtKey is pressed with Modifiers, then the following events WILL be sent:
	// 	[Modifiers != 0, Key/ExtKey == 0] (as the Modifiers keypress(es) will register separately)
	// 	[Modifiers != 0, Key/ExtKey != 0]
	// and the following WILL NOT be:
	// 	[Modifiers == 0, Key/ExtKey != 0]
	// unless the Modifiers were pressed after/released before the Key/ExtKey was.
	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.

When you are finished processing the incoming event, return whether or not you did something in response to the given keystroke as the handled return of your AreaHandler's Key() implementation. If you send false, you indicate that you did not handle the keypress, and that the system should handle it instead. (Some systems will stop processing the keyboard event at all if you return true unconditionally, which may result in unwanted behavior like global task-switching keystrokes not being processed.)

Note that even given the above, some systems might intercept some keystrokes (like Alt-F4 on various Unix systems) before Area will ever see them (and the Area might get an incorrect KeyEvent in this case, but this is not guaranteed); be wary.

If a key is pressed that is not supported by Key, ExtKey, or Modifiers, no KeyEvent will be produced, and package ui will act as if false was returned for handled.

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 struct {
	// contains filtered or unexported fields
}

A Label is a static line of text used to mark other controls. Label text is drawn on a single line; text that does not fit is truncated.

func NewLabel

func NewLabel(text string) *Label

NewLabel creates a new Label with the specified text.

func (*Label) SetText

func (l *Label) SetText(text string)

SetText sets the Label's text.

func (*Label) Text

func (l *Label) Text() string

Text returns the Label's text.

type LineEdit

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

A LineEdit is a control which allows you to enter a single line of text.

func NewLineEdit

func NewLineEdit(text string) *LineEdit

NewLineEdit makes a new LineEdit with the specified text.

func NewPasswordEdit

func NewPasswordEdit() *LineEdit

NewPasswordEdit makes a new LineEdit which allows the user to enter a password.

func (*LineEdit) SetText

func (l *LineEdit) SetText(text string)

SetText sets the LineEdit's text.

func (*LineEdit) Text

func (l *LineEdit) Text() string

Text returns the LineEdit's text.

type Listbox

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

A Listbox is a vertical list of items, of which either at most one or any number of items can be selected at any given time. On creation, no item is selected. Listboxes have vertical scrollbars that are hidden when not needed. The presence of horizontal scrollbars is currently undefined.

func NewListbox

func NewListbox(items ...string) *Listbox

NewListbox creates a new single-selection Listbox with the given items loaded initially.

func NewMultiSelListbox

func NewMultiSelListbox(items ...string) *Listbox

NewMultiSelListbox creates a new multiple-selection Listbox with the given items loaded initially.

func (*Listbox) Append

func (l *Listbox) Append(what ...string)

Append adds items to the end of the Listbox's list. Append will panic if something goes wrong on platforms that do not abort themselves.

func (*Listbox) Delete

func (l *Listbox) Delete(index int)

Delete removes the given item from the Listbox. It panics if the given index is out of bounds.

func (*Listbox) InsertBefore

func (l *Listbox) InsertBefore(what string, before int)

InsertBefore inserts a new item in the Listbox before the item at the given position. It panics if the given index is out of bounds. InsertBefore will also panic if something goes wrong on platforms that do not abort themselves.

func (*Listbox) Len

func (l *Listbox) Len() int

Len returns the number of items in the Listbox.

On platforms for which this function may return an error, it panics if one is returned.

func (*Listbox) SelectedIndices

func (l *Listbox) SelectedIndices() []int

SelectedIndices returns a list of the currently selected indexes in the Listbox, or an empty list if none have been selected. This list will have at most one item on a single-selection Listbox.

func (*Listbox) Selection

func (l *Listbox) Selection() []string

Selection returns a list of strings currently selected in the Listbox, or an empty list if none have been selected. This list will have at most one item on a single-selection Listbox.

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 (presently; TODO) undefined.

const (
	Ctrl  Modifiers = 1 << iota // the canonical Ctrl keys ([TODO] on Mac OS X, Control on others)
	Alt                         // the canonical Alt keys ([TODO] on Mac OS X, Meta on Unix systems, Alt on others)
	Shift                       // the Shift keys

)

type MouseEvent

type MouseEvent struct {
	// Pos is the position of the mouse in the Area at the time of the event.
	// TODO rename to Pt or Point?
	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; 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.
	// If Count == 2, AT LEAST zero events with Count == 1 will have been sent prior.
	// (This is a platform-specific issue: some platforms send none, some send one, and some send two.)
	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.
	// (TODO "There is no guarantee that Held is sorted."?)
	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. (TODO "If additional buttons are supported, they will be returned with 4 being the first additional button (XBUTTON1 on Windows), 5 being the second (XBUTTON2 on Windows), and so on."?) (TODO get the user-facing name for XBUTTON1/2; find out if there's a way to query available button count)

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 struct {
	// contains filtered or unexported fields
}

A ProgressBar is a horizontal rectangle that fills up from left to right to indicate the progress of a long-running task. This progress is represented by an integer within the range [0,100], representing a percentage. Alternatively, a progressbar can show an animation indicating that progress is being made but how much is indeterminate. Newly-created ProgressBars default to showing 0% progress.

func NewProgressBar

func NewProgressBar() *ProgressBar

NewProgressBar creates a new ProgressBar.

func (*ProgressBar) SetProgress

func (p *ProgressBar) SetProgress(percent int)

SetProgress sets the currently indicated progress amount on the ProgressBar. If percent is in the range [0,100], the progressBar shows that much percent complete. If percent is -1, the ProgressBar is made indeterminate. Otherwise, SetProgress panics. TODO what happens if you repeatedly call SetProgress(-1)?

type Stack

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

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.

func (*Stack) SetStretchy

func (s *Stack) SetStretchy(index int)

SetStretchy marks a control in a Stack as stretchy. This cannot be called once the Window containing the Stack has been opened. It panics if index is out of range.

type Window

type Window struct {
	// Closing gets a message when the user clicks the window's close button.
	// You cannot change it once the Window has been opened.
	// If you do not respond to this signal, nothing will happen; regardless of whether you handle the signal or not, the window will not be closed.
	Closing chan struct{}
	// contains filtered or unexported fields
}

Window represents an on-screen window.

func NewWindow

func NewWindow(title string, width int, height int) *Window

NewWindow creates a new window with the given title and size. The window is not constructed at the OS level until a call to Open().

func (*Window) Hide

func (w *Window) Hide()

Hide hides the window.

func (*Window) Open

func (w *Window) Open(control Control) (err error)

Open opens the window, setting its control to the given control, and then shows the window. This can only be called once per window, and finalizes all initialization of the control. TODO rename?

func (*Window) SetSize

func (w *Window) SetSize(width int, height int) (err error)

SetSize sets the window's size.

func (*Window) SetTitle

func (w *Window) SetTitle(title string)

SetTitle sets the window's title.

func (*Window) Show

func (w *Window) Show()

Show shows the window.

Directories

Path Synopsis
27 march 2014 11 february 2014
27 march 2014 11 february 2014

Jump to

Keyboard shortcuts

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