Documentation ¶
Overview ¶
Package duit is a pure go, cross-platform, MIT-licensed, UI toolkit for developers.
The examples/ directory has small code examples for working with duit and its UIs. Examples are the recommended starting point.
Instructions and information ¶
Start with NewDUI to create a DUI: essentially a window and all the UI state.
The user interface consists of a hierarchy of "UIs" like Box, Scroll, Button, Label, etc. They are called UIs, after the interface UI they all implement. The zero structs for UIs have sane default behaviour so you only have to fill in the fields you need.
UIs are kept/wrapped in a Kid, to track their layout/draw state. Use NewKids() to build up the UIs for your application. You won't see much of the Kid-types/functions otherwise, unless you implement a new UI.
You are in charge of the main event loop, receiving mouse/keyboard/window events from the dui.Inputs channel, and typically passing them on unchanged to dui.Input. All callbacks and functions on UIs are called from inside dui.Input. From there you can also safely change the the UIs, no locking required. After changing a UI you are responsible for calling MarkLayout or MarkDraw to tell duit the UI needs a new layout or draw. This may sound like more work, but this tradeoff keeps the API small and easy to use. If you need to change the UI from a goroutine outside of the main loop, e.g. for blocking calls, you can send a function that makes those modifications on the dui.Call channel, which will be run on the main channel through dui.Inputs. After handling an input, duit will layout or draw as necessary, no need to render explicitly.
Embedding a UI into your own data structure is often an easy way to build up UI hiearchies.
Scrolling ¶
Scroll and Edit show a scrollbar. Use button 1 on the scrollbar to scroll up, button 3 to scroll down. If you click more near the top, you scroll less. More near the bottom, more. Button 2 scrolls to the absolute place, where you clicked. Button 4 and 5 are wheel up and wheel down, and also scroll less/more depending on position in the UI.
Index ¶
- Constants
- Variables
- func Alert(text string) (err error)
- func AppDataDir(app string) string
- func KidsDraw(dui *DUI, self *Kid, kids []*Kid, uiSize image.Point, bg, img *draw.Image, ...)
- func KidsFirstFocus(dui *DUI, self *Kid, kids []*Kid) *image.Point
- func KidsFocus(dui *DUI, self *Kid, kids []*Kid, ui UI) *image.Point
- func KidsLayout(dui *DUI, self *Kid, kids []*Kid, force bool) (done bool)
- func KidsMark(self *Kid, kids []*Kid, o UI, forLayout bool) (marked bool)
- func KidsPrint(kids []*Kid, indent int)
- func PrintUI(s string, self *Kid, indent int)
- func ReadImage(display *draw.Display, f io.Reader) (*draw.Image, error)
- func ReadImagePath(display *draw.Display, path string) (*draw.Image, error)
- type Box
- func (ui *Box) Draw(dui *DUI, self *Kid, img *draw.Image, orig image.Point, m draw.Mouse, ...)
- func (ui *Box) FirstFocus(dui *DUI, self *Kid) *image.Point
- func (ui *Box) Focus(dui *DUI, self *Kid, o UI) *image.Point
- func (ui *Box) Key(dui *DUI, self *Kid, k rune, m draw.Mouse, orig image.Point) (r Result)
- func (ui *Box) Layout(dui *DUI, self *Kid, sizeAvail image.Point, force bool)
- func (ui *Box) Mark(self *Kid, o UI, forLayout bool) (marked bool)
- func (ui *Box) Mouse(dui *DUI, self *Kid, m draw.Mouse, origM draw.Mouse, orig image.Point) (r Result)
- func (ui *Box) Print(self *Kid, indent int)
- type Button
- func (ui *Button) Draw(dui *DUI, self *Kid, img *draw.Image, orig image.Point, m draw.Mouse, ...)
- func (ui *Button) FirstFocus(dui *DUI, self *Kid) *image.Point
- func (ui *Button) Focus(dui *DUI, self *Kid, o UI) *image.Point
- func (ui *Button) Key(dui *DUI, self *Kid, k rune, m draw.Mouse, orig image.Point) (r Result)
- func (ui *Button) Layout(dui *DUI, self *Kid, sizeAvail image.Point, force bool)
- func (ui *Button) Mark(self *Kid, o UI, forLayout bool) (marked bool)
- func (ui *Button) Mouse(dui *DUI, self *Kid, m draw.Mouse, origM draw.Mouse, orig image.Point) (r Result)
- func (ui *Button) Print(self *Kid, indent int)
- type Buttongroup
- func (ui *Buttongroup) Draw(dui *DUI, self *Kid, img *draw.Image, orig image.Point, m draw.Mouse, ...)
- func (ui *Buttongroup) FirstFocus(dui *DUI, self *Kid) *image.Point
- func (ui *Buttongroup) Focus(dui *DUI, self *Kid, o UI) *image.Point
- func (ui *Buttongroup) Key(dui *DUI, self *Kid, k rune, m draw.Mouse, orig image.Point) (r Result)
- func (ui *Buttongroup) Layout(dui *DUI, self *Kid, sizeAvail image.Point, force bool)
- func (ui *Buttongroup) Mark(self *Kid, o UI, forLayout bool) (marked bool)
- func (ui *Buttongroup) Mouse(dui *DUI, self *Kid, m draw.Mouse, origM draw.Mouse, orig image.Point) (r Result)
- func (ui *Buttongroup) Print(self *Kid, indent int)
- type Checkbox
- func (ui *Checkbox) Draw(dui *DUI, self *Kid, img *draw.Image, orig image.Point, m draw.Mouse, ...)
- func (ui *Checkbox) FirstFocus(dui *DUI, self *Kid) *image.Point
- func (ui *Checkbox) Focus(dui *DUI, self *Kid, o UI) *image.Point
- func (ui *Checkbox) Key(dui *DUI, self *Kid, k rune, m draw.Mouse, orig image.Point) (r Result)
- func (ui *Checkbox) Layout(dui *DUI, self *Kid, sizeAvail image.Point, force bool)
- func (ui *Checkbox) Mark(self *Kid, o UI, forLayout bool) (marked bool)
- func (ui *Checkbox) Mouse(dui *DUI, self *Kid, m draw.Mouse, origM draw.Mouse, orig image.Point) (r Result)
- func (ui *Checkbox) Print(self *Kid, indent int)
- type Colors
- type Colorset
- type Cursor
- type DUI
- func (d *DUI) Close()
- func (d *DUI) Draw()
- func (d *DUI) Focus(ui UI)
- func (d *DUI) Font(font *draw.Font) *draw.Font
- func (d *DUI) Input(e Input)
- func (d *DUI) Key(k rune)
- func (d *DUI) Layout()
- func (d *DUI) MarkDraw(ui UI)
- func (d *DUI) MarkLayout(ui UI)
- func (d *DUI) Mouse(m draw.Mouse)
- func (d *DUI) ReadSettings(self *Kid, v interface{}) bool
- func (d *DUI) ReadSnarf() (buf []byte, success bool)
- func (d *DUI) Render()
- func (d *DUI) Resize()
- func (d *DUI) Scale(n int) int
- func (d *DUI) ScaleSpace(s Space) Space
- func (d *DUI) WriteSettings(self *Kid, v interface{}) bool
- func (d *DUI) WriteSnarf(buf []byte)
- type DUIOpts
- type Edit
- func (ui *Edit) Append(buf []byte)
- func (ui *Edit) Cursor() Cursor
- func (ui *Edit) Draw(dui *DUI, self *Kid, img *draw.Image, orig image.Point, m draw.Mouse, ...)
- func (ui *Edit) EditReader(offset int64) EditReader
- func (ui *Edit) ExpandedText() ([]byte, error)
- func (ui *Edit) FirstFocus(dui *DUI, self *Kid) (warp *image.Point)
- func (ui *Edit) Focus(dui *DUI, self *Kid, o UI) (warp *image.Point)
- func (ui *Edit) Key(dui *DUI, self *Kid, k rune, m draw.Mouse, orig image.Point) (r Result)
- func (ui *Edit) Layout(dui *DUI, self *Kid, sizeAvail image.Point, force bool)
- func (ui *Edit) Mark(self *Kid, o UI, forLayout bool) (marked bool)
- func (ui *Edit) Mouse(dui *DUI, self *Kid, m draw.Mouse, origM draw.Mouse, orig image.Point) (r Result)
- func (ui *Edit) Print(self *Kid, indent int)
- func (ui *Edit) Reader() ReaderReaderAt
- func (ui *Edit) Replace(c Cursor, buf []byte)
- func (ui *Edit) ReverseEditReader(offset int64) EditReader
- func (ui *Edit) Saved()
- func (ui *Edit) ScrollCursor(dui *DUI)
- func (ui *Edit) Search(dui *DUI, reverse bool) (match bool)
- func (ui *Edit) Selection() ([]byte, error)
- func (ui *Edit) SetCursor(c Cursor)
- func (ui *Edit) Text() ([]byte, error)
- type EditColors
- type EditReader
- type Event
- type Field
- func (ui *Field) Draw(dui *DUI, self *Kid, img *draw.Image, orig image.Point, m draw.Mouse, ...)
- func (ui *Field) FirstFocus(dui *DUI, self *Kid) *image.Point
- func (ui *Field) Focus(dui *DUI, self *Kid, o UI) *image.Point
- func (ui *Field) Key(dui *DUI, self *Kid, k rune, m draw.Mouse, orig image.Point) (r Result)
- func (ui *Field) Layout(dui *DUI, self *Kid, sizeAvail image.Point, force bool)
- func (ui *Field) Mark(self *Kid, o UI, forLayout bool) (marked bool)
- func (ui *Field) Mouse(dui *DUI, self *Kid, m draw.Mouse, origM draw.Mouse, orig image.Point) (r Result)
- func (ui *Field) Print(self *Kid, indent int)
- type Grid
- func (ui *Grid) Draw(dui *DUI, self *Kid, img *draw.Image, orig image.Point, m draw.Mouse, ...)
- func (ui *Grid) FirstFocus(dui *DUI, self *Kid) *image.Point
- func (ui *Grid) Focus(dui *DUI, self *Kid, o UI) *image.Point
- func (ui *Grid) Key(dui *DUI, self *Kid, k rune, m draw.Mouse, orig image.Point) (r Result)
- func (ui *Grid) Layout(dui *DUI, self *Kid, sizeAvail image.Point, force bool)
- func (ui *Grid) Mark(self *Kid, o UI, forLayout bool) (marked bool)
- func (ui *Grid) Mouse(dui *DUI, self *Kid, m draw.Mouse, origM draw.Mouse, orig image.Point) (r Result)
- func (ui *Grid) Print(self *Kid, indent int)
- type Gridfit
- type Gridlist
- func (ui *Gridlist) Draw(dui *DUI, self *Kid, img *draw.Image, orig image.Point, m draw.Mouse, ...)
- func (ui *Gridlist) FirstFocus(dui *DUI, self *Kid) (warp *image.Point)
- func (ui *Gridlist) Focus(dui *DUI, self *Kid, o UI) (warp *image.Point)
- func (ui *Gridlist) Key(dui *DUI, self *Kid, k rune, m draw.Mouse, orig image.Point) (r Result)
- func (ui *Gridlist) Layout(dui *DUI, self *Kid, sizeAvail image.Point, force bool)
- func (ui *Gridlist) Mark(self *Kid, o UI, forLayout bool) (marked bool)
- func (ui *Gridlist) Mouse(dui *DUI, self *Kid, m draw.Mouse, origM draw.Mouse, orig image.Point) (r Result)
- func (ui *Gridlist) Print(self *Kid, indent int)
- func (ui *Gridlist) Selected() (indices []int)
- type Gridrow
- type Halign
- type Icon
- type Image
- func (ui *Image) Draw(dui *DUI, self *Kid, img *draw.Image, orig image.Point, m draw.Mouse, ...)
- func (ui *Image) FirstFocus(dui *DUI, self *Kid) *image.Point
- func (ui *Image) Focus(dui *DUI, self *Kid, o UI) *image.Point
- func (ui *Image) Key(dui *DUI, self *Kid, k rune, m draw.Mouse, orig image.Point) (r Result)
- func (ui *Image) Layout(dui *DUI, self *Kid, sizeAvail image.Point, force bool)
- func (ui *Image) Mark(self *Kid, o UI, forLayout bool) (marked bool)
- func (ui *Image) Mouse(dui *DUI, self *Kid, m draw.Mouse, origM draw.Mouse, orig image.Point) (r Result)
- func (ui *Image) Print(self *Kid, indent int)
- type Input
- type InputType
- type Kid
- type Label
- func (ui *Label) Draw(dui *DUI, self *Kid, img *draw.Image, orig image.Point, m draw.Mouse, ...)
- func (ui *Label) FirstFocus(dui *DUI, self *Kid) *image.Point
- func (ui *Label) Focus(dui *DUI, self *Kid, o UI) *image.Point
- func (ui *Label) Key(dui *DUI, self *Kid, k rune, m draw.Mouse, orig image.Point) (r Result)
- func (ui *Label) Layout(dui *DUI, self *Kid, sizeAvail image.Point, force bool)
- func (ui *Label) Mark(self *Kid, o UI, forLayout bool) (marked bool)
- func (ui *Label) Mouse(dui *DUI, self *Kid, m draw.Mouse, origM draw.Mouse, orig image.Point) (r Result)
- func (ui *Label) Print(self *Kid, indent int)
- type List
- func (ui *List) Draw(dui *DUI, self *Kid, img *draw.Image, orig image.Point, m draw.Mouse, ...)
- func (ui *List) FirstFocus(dui *DUI, self *Kid) *image.Point
- func (ui *List) Focus(dui *DUI, self *Kid, o UI) *image.Point
- func (ui *List) Key(dui *DUI, self *Kid, k rune, m draw.Mouse, orig image.Point) (r Result)
- func (ui *List) Layout(dui *DUI, self *Kid, sizeAvail image.Point, force bool)
- func (ui *List) Mark(self *Kid, o UI, forLayout bool) (marked bool)
- func (ui *List) Mouse(dui *DUI, self *Kid, m draw.Mouse, origM draw.Mouse, orig image.Point) (r Result)
- func (ui *List) Print(self *Kid, indent int)
- func (ui *List) Selected() (indices []int)
- func (ui *List) Unselect(indices []int)
- type ListValue
- type Middle
- func (ui *Middle) Draw(dui *DUI, self *Kid, img *draw.Image, orig image.Point, m draw.Mouse, ...)
- func (ui *Middle) FirstFocus(dui *DUI, self *Kid) (warp *image.Point)
- func (ui *Middle) Focus(dui *DUI, self *Kid, o UI) (warp *image.Point)
- func (ui *Middle) Key(dui *DUI, self *Kid, k rune, m draw.Mouse, orig image.Point) (r Result)
- func (ui *Middle) Layout(dui *DUI, self *Kid, sizeAvail image.Point, force bool)
- func (ui *Middle) Mark(self *Kid, o UI, forLayout bool) (marked bool)
- func (ui *Middle) Mouse(dui *DUI, self *Kid, m draw.Mouse, origM draw.Mouse, orig image.Point) (r Result)
- func (ui *Middle) Print(self *Kid, indent int)
- type Pick
- func (ui *Pick) Draw(dui *DUI, self *Kid, img *draw.Image, orig image.Point, m draw.Mouse, ...)
- func (ui *Pick) FirstFocus(dui *DUI, self *Kid) (warp *image.Point)
- func (ui *Pick) Focus(dui *DUI, self *Kid, o UI) (warp *image.Point)
- func (ui *Pick) Key(dui *DUI, self *Kid, k rune, m draw.Mouse, orig image.Point) (r Result)
- func (ui *Pick) Layout(dui *DUI, self *Kid, sizeAvail image.Point, force bool)
- func (ui *Pick) Mark(self *Kid, o UI, forLayout bool) (marked bool)
- func (ui *Pick) Mouse(dui *DUI, self *Kid, m draw.Mouse, origM draw.Mouse, orig image.Point) (r Result)
- func (ui *Pick) Print(self *Kid, indent int)
- type Place
- func (ui *Place) Draw(dui *DUI, self *Kid, img *draw.Image, orig image.Point, m draw.Mouse, ...)
- func (ui *Place) FirstFocus(dui *DUI, self *Kid) (warp *image.Point)
- func (ui *Place) Focus(dui *DUI, self *Kid, o UI) (warp *image.Point)
- func (ui *Place) Key(dui *DUI, self *Kid, k rune, m draw.Mouse, orig image.Point) (r Result)
- func (ui *Place) Layout(dui *DUI, self *Kid, sizeAvail image.Point, force bool)
- func (ui *Place) Mark(self *Kid, o UI, forLayout bool) (marked bool)
- func (ui *Place) Mouse(dui *DUI, self *Kid, m draw.Mouse, origM draw.Mouse, orig image.Point) (r Result)
- func (ui *Place) Print(self *Kid, indent int)
- type Radiobutton
- func (ui *Radiobutton) Draw(dui *DUI, self *Kid, img *draw.Image, orig image.Point, m draw.Mouse, ...)
- func (ui *Radiobutton) FirstFocus(dui *DUI, self *Kid) *image.Point
- func (ui *Radiobutton) Focus(dui *DUI, self *Kid, o UI) *image.Point
- func (ui *Radiobutton) Key(dui *DUI, self *Kid, k rune, m draw.Mouse, orig image.Point) (r Result)
- func (ui *Radiobutton) Layout(dui *DUI, self *Kid, sizeAvail image.Point, force bool)
- func (ui *Radiobutton) Mark(self *Kid, o UI, forLayout bool) (marked bool)
- func (ui *Radiobutton) Mouse(dui *DUI, self *Kid, m draw.Mouse, origM draw.Mouse, orig image.Point) (r Result)
- func (ui *Radiobutton) Print(self *Kid, indent int)
- func (ui *Radiobutton) Select(dui *DUI)
- type RadiobuttonGroup
- type ReaderReaderAt
- type Result
- type Scroll
- func (ui *Scroll) Draw(dui *DUI, self *Kid, img *draw.Image, orig image.Point, m draw.Mouse, ...)
- func (ui *Scroll) FirstFocus(dui *DUI, self *Kid) *image.Point
- func (ui *Scroll) Focus(dui *DUI, self *Kid, o UI) *image.Point
- func (ui *Scroll) Key(dui *DUI, self *Kid, k rune, m draw.Mouse, orig image.Point) (r Result)
- func (ui *Scroll) Layout(dui *DUI, self *Kid, sizeAvail image.Point, force bool)
- func (ui *Scroll) Mark(self *Kid, o UI, forLayout bool) (marked bool)
- func (ui *Scroll) Mouse(dui *DUI, self *Kid, m draw.Mouse, origM draw.Mouse, orig image.Point) (r Result)
- func (ui *Scroll) Print(self *Kid, indent int)
- type SeekReaderAt
- type Space
- type Split
- func (ui *Split) Dimensions(dui *DUI, dims []int) []int
- func (ui *Split) Draw(dui *DUI, self *Kid, img *draw.Image, orig image.Point, m draw.Mouse, ...)
- func (ui *Split) FirstFocus(dui *DUI, self *Kid) *image.Point
- func (ui *Split) Focus(dui *DUI, self *Kid, o UI) *image.Point
- func (ui *Split) Key(dui *DUI, self *Kid, k rune, m draw.Mouse, orig image.Point) (r Result)
- func (ui *Split) Layout(dui *DUI, self *Kid, sizeAvail image.Point, force bool)
- func (ui *Split) Mark(self *Kid, o UI, forLayout bool) (marked bool)
- func (ui *Split) Mouse(dui *DUI, self *Kid, m draw.Mouse, origM draw.Mouse, orig image.Point) (r Result)
- func (ui *Split) Print(self *Kid, indent int)
- type State
- type Tabs
- type UI
- type Valign
Constants ¶
const ( BorderSize = 1 // regardless of lowDPI/hiDPI, won't be scaled ScrollbarSize = 10 // in lowDPI pixels )
const ( Button1 = 1 << iota Button2 Button3 Button4 // wheel up Button5 // wheel down )
Mouse buttons, see draw.Mouse.Buttons.
const ( Dirty = State(iota) // UI itself needs layout/draw; kids will also get a UI.Layout/UI.Draw call, with force set. DirtyKid // UI itself does not need layout/draw, but one of its children does, so pass the call on. Clean // UI and its children do not need layout/draw. )
Variables ¶
var (
EditPadding = Space{0, 3, 0, 3} // LowDPI padding, drawn with a distinct color when in vi modes.
)
Functions ¶
func Alert ¶
Alert creates a new window that show text and a button labeled OK that closes the window.
func AppDataDir ¶
AppdataDir returns the directory where the application can store its files, like configuration. On unix this is $HOME/lib/<app>. On Windows it is $APPDATA/<app>.
func KidsDraw ¶
func KidsDraw(dui *DUI, self *Kid, kids []*Kid, uiSize image.Point, bg, img *draw.Image, orig image.Point, m draw.Mouse, force bool)
KidsDraw draws a UI by drawing all its kids. uiSize is the size of the entire UI, used in case it has to be redrawn entirely. Bg can override the default duit background color. Img is the whether the UI should be drawn on, with orig as origin (offset). M is used for passing a mouse position to the kid's UI draw, for possibly drawing hover states. KidsDraw only draws if draw state indicates a need for drawing, or if force is set.
func KidsFirstFocus ¶
KidsFirstFocus delivers the FirstFocus request to the first leaf UI, and returns the location where the mouse should warp to.
func KidsFocus ¶
KidsFocus delivers the Focus request to the first leaf UI, and returns the location where the mouse should warp to.
func KidsLayout ¶
KidsLayout is called by layout UIs before they do their own layouts. KidsLayout returns whether there is any work left to do, determined by looking at self.Layout. Children will be layed out if necessary. KidsLayout updates layout and draw state of self and kids.
func KidsMark ¶
KidsMark finds o in this UI subtree (self and kids), marks it as needing layout or draw (forLayout false), and returns whether it found and marked the UI.
func PrintUI ¶
PrintUI is a helper function UIs can use to implement UI.Print. "s" is typically the ui type, possibly with additional properties. Indent should be increased for each child UI that is printed.
Types ¶
type Box ¶
type Box struct { Kids []*Kid // Kids and UIs in this box. Reverse bool // Lay out children from bottom to top. First kid will be at the bottom. Margin image.Point // In lowDPI pixels, will be adjusted for highDPI screens. Padding Space // Padding inside box, so children don't touch the sides; in lowDPI pixels, also adjusted for highDPI screens. Valign Valign // How to align children on a line. Width int // 0 means dynamic (as much as needed), -1 means full width, >0 means that exact amount of lowDPI pixels. Height int // 0 means dynamic (as much as needed), -1 means full height, >0 means that exact amount of lowDPI pixels. MaxWidth int // if >0, the max number of lowDPI pixels that will be used. Background *draw.Image `json:"-"` // Background for this box, instead of default duit background. // contains filtered or unexported fields }
Box keeps elements on a line as long as they fit, then moves on to the next line.
func NewReverseBox ¶
NewReverseBox returns a box containing all uis in original order in its Kids field, with the Reverse field set.
type Button ¶
type Button struct { Text string // Displayed on button. Icon Icon `json:"-"` // Displayed before text, if Icon.Font is not nil. Disabled bool // If disabled, colors used indicate disabledness, clicks don't result in Click being called. Colorset *Colorset `json:"-"` // Colors used, for example DUI.Primary. Defaults to DUI.Regular. Font *draw.Font `json:"-"` // Used to draw Text, if not nil. Click func() (e Event) `json:"-"` // Called on click on the button. // contains filtered or unexported fields }
Button with text and optional icon with a click function.
type Buttongroup ¶
type Buttongroup struct { Texts []string // Texts to display on the buttons. Selected int // Index in Text of the currently selected button. Disabled bool // If disabled, the duit.Disabled colors are used and clicks have no effect. Font *draw.Font `json:"-"` // Used for drawing Texts. Changed func(index int) (e Event) `json:"-"` // Called on click on a different button in the group then previously selected. // contains filtered or unexported fields }
Buttongroup shows multiple joined buttons, with one of them active.
func (*Buttongroup) FirstFocus ¶
func (ui *Buttongroup) FirstFocus(dui *DUI, self *Kid) *image.Point
func (*Buttongroup) Mark ¶
func (ui *Buttongroup) Mark(self *Kid, o UI, forLayout bool) (marked bool)
func (*Buttongroup) Print ¶
func (ui *Buttongroup) Print(self *Kid, indent int)
type Checkbox ¶
type Checkbox struct { Checked bool // Whether checked or not. Disabled bool // Whether clicks have any effect. Font *draw.Font `json:"-"` // Only used to determine height of the checkbox. Specify same font as for label. Changed func() (e Event) `json:"-"` // Called after the value changed. // contains filtered or unexported fields }
Checkbox holds a true/false value. A label is not part of the checkbox, you should create it explicitly and add a click handler to toggle the checkbox.
type Colors ¶
type Colors struct { Text *draw.Image `json:"-"` Background *draw.Image `json:"-"` Border *draw.Image `json:"-"` }
Colors represents the style in one state of the UI.
type Colorset ¶
type Colorset struct {
Normal, Hover Colors
}
Colorset is typically used to style buttons. Duit provides some builtin colorsets like Primary, Danger, Success.
type Cursor ¶
type Cursor struct { Cur int64 // Current location/end of selection. Start int64 // Start of selection, not necessarily larger than Cur! }
Cursor represents the current editing location, and optionally text selection.
type DUI ¶
type DUI struct { Inputs chan Input // Duit sends input events on this channel, needs to be read from the main loop. Top Kid // Root of the UI hierarchy. Wrapped in a Kid for state management. Call chan func() // Functions sent here will go through DUI.Inputs and run by DUI.Input() in the main event loop. For code that changes UI state. Error chan error // Receives errors from UIs. For example when memory for an image could not be allocated. Closed when window is closed. Needs to be read from the main loop. Display *draw.Display // Colors. Disabled, Inverse, Selection, SelectionHover, Placeholder, Striped Colors // Colors with hover-variants. Regular, Primary, Secondary, Success, Danger Colorset // Background color UIs should have. BackgroundColor draw.Color Background *draw.Image // Scrollbar colors. ScrollBGNormal, ScrollBGHover, ScrollVisibleNormal, ScrollVisibleHover *draw.Image // Gutter color. Gutter *draw.Image Debug bool // Log errors interesting to developers. DebugDraw int // If 1, UIs print each draw they do. If 2, UIs print all calls to their Draw function. Cycle through 0-2 with F7. DebugLayout int // If 1, UIs print each Layout they do. If 2, UIs print all calls to their Layout function. Cycle through 0-2 with F8. DebugKids bool // Whether to print distinct backgrounds in kids* functions. // Border colors for vi modes for Edit. CommandMode, VisualMode *draw.Image // contains filtered or unexported fields }
DUI represents a window and all UI state for that window.
func NewDUI ¶
NewDUI creates a DUI for an application called name, and optional opts. A DUI is a new window and its UI state. Window dimensions and UI settings are automatically written to $APPDATA/duit/<name>, with $APPDATA being $HOME/lib on unix.
func (*DUI) Close ¶
func (d *DUI) Close()
Close stops mouse/keyboard event reading and closes the window. After closing a DUI you should no longer call functions on it.
func (*DUI) Draw ¶
func (d *DUI) Draw()
Draw the entire UI tree, as necessary. Only UIs marked as requiring a draw are actually drawn, and their children.
func (*DUI) Focus ¶
Focus renders the UI, then changes focus to ui by warping the mouse pointer to it. Container UIs ensure the UI is in place, e.g. scrolling if necessary.
func (*DUI) Font ¶
Font is a helper function for UI implementations. It returns the passed font. Unless font is nil, then it returns the default font.
func (*DUI) Input ¶
Input propagates the input event through the UI tree. Mouse and key events are delivered the right UIs. Resize is handled by reattaching to devdraw and doing a layout and draw. Func calls the function. Error implies an error from devdraw and terminates the program.
func (*DUI) Layout ¶
func (d *DUI) Layout()
Layout the entire UI tree, as necessary. Only UIs marked as requiring a layout are actually layed out. UIs that receive a layout are marked as requiring a draw.
func (*DUI) MarkLayout ¶
MarkLayout marks ui as requiring a layout. If you have access to the Kid that holds this UI, it is more efficient to change the Kid itself. MarkLayout is more convenient. Using it can cut down on bookkeeping. If ui is nil, the top UI is marked.
func (*DUI) Mouse ¶
Mouse delivers a mouse event to the UI tree. Mouse is typically called by Input.
func (*DUI) ReadSettings ¶
ReadSettings reads the settings for self.ID if any into v. Settings are stored as JSON, (un)marshalled with encoding/json. ReadSettings returns whether reading settings was successful.
func (*DUI) ReadSnarf ¶
ReadSnarf reads the entire snarf buffer and logs an error in case of failure.
func (*DUI) Render ¶
func (d *DUI) Render()
Render calls Layout followed by Draw. This only does a layout/draw for UIs marked as needing it. If you want to force a layout/draw, mark the top UI as requiring a layout/draw.
func (*DUI) Resize ¶
func (d *DUI) Resize()
Resize handles a resize of the window. Resize is called automatically through Input when the user resizes a window.
func (*DUI) ScaleSpace ¶
ScaleSpace is like Scale, but for a Space.
func (*DUI) WriteSettings ¶
WriteSettings writes settings v for self.ID as JSON. WriteSettings delays a write for an ID for 2 seconds. Delayed writes are canceled by new writes.
func (*DUI) WriteSnarf ¶
WriteSnarf writes the snarf buffer and logs an error in case of failure.
type DUIOpts ¶
type DUIOpts struct { FontName string // eg "/mnt/font/Lato-Regular/15a/font" Dimensions string // eg "800x600", duit has a sane default and remembers size per application name after resize. }
DUIOpts are options for creating a new DUI. Zero values have sane behaviour.
type Edit ¶
type Edit struct { NoScrollbar bool // If set, no scrollbar is shown. Content will still scroll. LastSearch string // If starting with slash, the remainder is interpreted as regexp. used by cmd+[/?] and vi [*nN] commands. Literal text search should start with a space. Error chan error // If set, errors from Edit (including read errors from underlying files) are sent here. If nil, errors go to dui.Error. Colors *EditColors `json:"-"` // Colors to use for drawing the Edit UI, allows for creating an acme look. Font *draw.Font `json:"-"` // Used for drawing all text. Keys func(k rune, m draw.Mouse) (e Event) `json:"-"` // Called before handling keys. If you set e.Consumed, the key is not handled further. Click func(m draw.Mouse, offset int64) (e Event) `json:"-"` // Called for clicks with button 1,2,3. Offset is the file offset that was clicked on. DirtyChanged func(dirty bool) `json:"-"` // Called when the dirty-state of the underlying file changes. // contains filtered or unexported fields }
Edit is a text editor inspired by acme, with vi key bindings. An edit has its own scrollbar, unlimited undo. It can read utf-8 encoded files of arbritary length, only reading data when necessary, to display or search.
The usual arrow and pageup/pagedown keys can be used for navigation. Key shortcuts when combined with control:
a, to start of line e, to end of line h, remove character before cursor w, remove word before cursor u, delete to start of line k, delete to end of line
Key shortcuts when combined with the command key:
a, select all text n, no selection c, copy selection x, cut selection v, paste selection z, undo last change Z, redo last undone change [, unindent selection or line ], indent selection or line m, warp mouse to the cursor y, select last modification /, repeat last search forward ?, repeat last search backward
Edit has a vi command and visual mode, entered through the familiar escape key. Not all commands have been implemented yet, Edit does not aim to be feature-complete or a clone of any specific existing vi-clone.
func NewEdit ¶
func NewEdit(f SeekReaderAt) (ui *Edit, err error)
NewEdit returns an Edit initialized with f.
func (*Edit) EditReader ¶
func (ui *Edit) EditReader(offset int64) EditReader
EditReader from which contents of edit can be read, starting at offset.
func (*Edit) ExpandedText ¶
todo: maybe not have this here?
func (*Edit) Reader ¶
func (ui *Edit) Reader() ReaderReaderAt
Reader from which contents of edit can be read.
func (*Edit) ReverseEditReader ¶
func (ui *Edit) ReverseEditReader(offset int64) EditReader
ReverseEditReader from which contents of edit can be read in reverse (whole utf-8 characters), starting at offset, to 0.
func (*Edit) Saved ¶
func (ui *Edit) Saved()
Saved marks content as saved, calling the DirtyChanged callback if set, and updating the history state.
func (*Edit) ScrollCursor ¶
ScrollCursor ensure cursor is visible, scrolling if necessary.
func (*Edit) Search ¶
Search finds the next occurrence of LastSearch and selects it and scrolls to it. The first character determines the kind of search. If slash, the remainder is interpreted as regular expression. If space (and currently anything else), the remainder is interpreted as a literal string.
type EditColors ¶
type EditColors struct {
Fg, Bg,
SelFg, SelBg,
ScrollVis, ScrollBg,
HoverScrollVis, HoverScrollBg,
CommandBorder, VisualBorder *draw.Image
}
EditColors hold all the colors used for rendering an Edit.
type EditReader ¶
type EditReader interface { Peek() (r rune, eof bool) // Return next character without consuming. TryGet() (r rune, err error) // Returns and consume next character. Get() (r rune) // Return and consume next character. On error, returns -1 and sends on Edit.Error. Offset() (offset int64) // Current offset. Whitespace(newline bool) (s string, eof bool) // Consume and return whitespace, possibly including newlines. Nonwhitespace() (s string, eof bool) // Consume all except whitespace. Whitespacepunct(newline bool) (s string, eof bool) // Consume whitespace and punctation. Nonwhitespacepunct() (s string, eof bool) // Consume non-whitespace and punctutation. Punctuation() (s string, eof bool) // Consume punctuation. Line(includeNewline bool) (runes int, s string, eof bool) // Reads to end of newline, possibly including the newline itself. }
EditReader provides a reader to the current contents of an Edit. It is used by navigation commands and keyboard shortcuts. Both Edit.EditReader and Edit.ReverseEditReader return an EditReader. ReverseEditReader reads utf-8 characters in reverse, towards the start of the file.
type Event ¶
type Event struct { Consumed bool // Whether event was consumed, and should not be further handled by upper UI's. Container UIs can handle some mouse/key events and decide whether they want to pass them on, or first pass them on and only consume them when a child UI hasn't done so yet. NeedLayout bool // Whether UI now needs a layout. Only the UI generating the event will be marked. If you another UI needs to be marked, call MarkLayout. NeedDraw bool // Like NeedLayout, but for draw. }
Event is returned by handlers, such as click or key handlers.
type Field ¶
type Field struct { Target **Field `json:"-"` // Reference to itself. Text string // Current text. Placeholder string // Text displayed in lighter color as example. Disabled bool // If disabled, mouse and key input have no effect. Cursor1 int // Index in string of cursor in bytes, start at 1, 0 means end of string. SelectionStart1 int // If > 0, 1 beyond the start of the selection in bytes, with Cursor being the end. Password bool // Render text as bullet items to hide the password (but not length). Font *draw.Font `json:"-"` // Font to use for drawing text. Changed func(text string) (e Event) `json:"-"` // Called after contents of field have changed. Keys func(k rune, m draw.Mouse) (e Event) `json:"-"` // Called before handling key. If you consume the event, Changed will not be called. // contains filtered or unexported fields }
Field is a single line text field. The cursor is always visible, and determines which part of the text is shown.
type Grid ¶
type Grid struct { Kids []*Kid // Holds UIs in the grid, per row. Columns int // Number of clumns. Valign []Valign // Vertical alignment per column. Halign []Halign // Horizontal alignment per column. Padding []Space // Padding in lowDPI pixels per column. Width int // -1 means full width, 0 means automatic width, >0 means exactly that many lowDPI pixels. Background *draw.Image `json:"-"` // Background color. // contains filtered or unexported fields }
Grid lays out other UIs in a table-like grid.
type Gridlist ¶
type Gridlist struct { Header *Gridrow // Optional header to display at the the top. Rows []*Gridrow // Rows, each holds whether it is selected. Multiple bool // Whether multiple rows can be selected at a time. Halign []Halign // Horizontal alignment for the values. Padding Space // Padding for each cell, in lowDPI pixels. Striped bool // If set, odd cells have a slightly contrasting background color. Fit Gridfit // Layout strategy, how much space columns receive. Font *draw.Font `json:"-"` // Used for drawing text. Changed func(index int) (e Event) `json:"-"` // Called after the selection changed. -1 is multiple may have changed. Click func(index int, m draw.Mouse) (e Event) `json:"-"` // Called on click at given index. If consumed, processing stops. Keys func(k rune, m draw.Mouse) (e Event) `json:"-"` // Called before handling a key event. If consumed, processing stops. // contains filtered or unexported fields }
Gridlist is a table-like list of selectable values. Currently each cell in each row is drawn as a single-line string. Column widths can be adjusted by dragging the separator in the header.
Keys:
arrow up, move selection up arrow down, move selection down home, move selection to first element end, move selection to last element cmd-n, clear selection cmd-a, select all cmd-c, copy selected rows, as tab-separated values
func (*Gridlist) FirstFocus ¶
type Gridrow ¶
type Gridrow struct { Selected bool // If currently selected. Values []string // Values displayed in the row. Value interface{} `json:"-"` // Auxiliary data. }
Gridrow is used for each row in a Gridlist.
type Icon ¶
type Icon struct { Rune rune // Codepoint to draw. Font *draw.Font `json:"-"` // Font to draw in. If nil, nothing is typically drawn. }
Icon is a single codepoint in the given font. Typically for an "icon font" like fontawesome.
type Image ¶
Image shows an image. Currently always in its original size.
type Kid ¶
type Kid struct { UI UI // UI this state is about. R image.Rectangle // Location and size within this UI. Draw State // Whether UI or its children need a draw. Layout State // Whether UI or its children need a layout. ID string // For (re)storing settings with ReadSettings and WriteSettings. If empty, no settings for the UI will be (re)stored. }
Kid holds a UI and its layout/draw state.
func (*Kid) Mark ¶
Mark checks if o is its UI, and if so marks it as needing a layout or draw (forLayout false).
func (*Kid) MarshalJSON ¶
MarshalJSON writes k with an additional field Type containing the name of the UI type.
type Label ¶
type Label struct { Target **Label `json:"-"` Text string // Text to draw, wrapped at glyph boundary. Font *draw.Font `json:"-"` // For drawing text. Click func() (e Event) `json:"-"` // Called on button1 click. // contains filtered or unexported fields }
Label draws multiline text in a single font.:
Keys:
cmd-c, copy text \n, like button1 click, calls the Click function
type List ¶
type List struct { Values []*ListValue // Values, each contains whether it is selected. Multiple bool // Whether multiple values can be selected at a time. Font *draw.Font `json:"-"` // For drawing the values. Changed func(index int) (e Event) `json:"-"` // Called after the selection changes, index being the new single selected item if >= 0. Click func(index int, m draw.Mouse) (e Event) `json:"-"` // Called on click at value at index, before handling selection change. If consumed, processing stops. Keys func(k rune, m draw.Mouse) (e Event) `json:"-"` // Called on key. If consumed, processing stops. // contains filtered or unexported fields }
List shows values, allowing for single or multiple selection, with callbacks when the selection changes.
Keys:
arrow up, move selection up arrow down, move selection down home, move selection to first element end, move selection to last element
type ListValue ¶
type ListValue struct { Text string // Text shown, as single line. Value interface{} `json:"-"` // Auxiliary data. Selected bool }
ListValue is used for values in a List.
type Middle ¶
type Middle struct { Kid *Kid // Contains the UI displayed in the middle. Background *draw.Image `json:"-"` // For background color. // contains filtered or unexported fields }
Middle lays out a single child in the middle of the available space, both vertically and horizontally.
type Pick ¶
type Pick struct { Pick func(sizeAvail image.Point) UI `json:"-"` // Called during layout, must return a non-nil UI. // contains filtered or unexported fields }
Pick makes it possible to create responsive UI layouts. You must provide the function Pick that is called at layout with the available window space. It must return the current UI to show. You could return different layouts depending on the size of the window.
type Place ¶
type Place struct { // Place is called during layout. It must configure Kids, and set self.R, based on sizeAvail. Place func(self *Kid, sizeAvail image.Point) `json:"-"` Kids []*Kid // Kids to draw, set by the Place function. Background *draw.Image `json:"-"` // For background color. // contains filtered or unexported fields }
Place contains other UIs it can position absolute, possibly on top of each other.
type Radiobutton ¶
type Radiobutton struct { // Not called if selected with Select(). Changed func(v interface{}) (e Event) `json:"-"` // contains filtered or unexported fields }
Radiobutton is typically part of a group of radiobuttons, with exactly one of them selected. Labels are not part of the radiobutton itself.
func (*Radiobutton) FirstFocus ¶
func (ui *Radiobutton) FirstFocus(dui *DUI, self *Kid) *image.Point
func (*Radiobutton) Mark ¶
func (ui *Radiobutton) Mark(self *Kid, o UI, forLayout bool) (marked bool)
func (*Radiobutton) Print ¶
func (ui *Radiobutton) Print(self *Kid, indent int)
func (*Radiobutton) Select ¶
func (ui *Radiobutton) Select(dui *DUI)
Select this radiobutton from the group, unselecting the previously selected radiobutton. Select does not call Changed.
type RadiobuttonGroup ¶
type RadiobuttonGroup []*Radiobutton
RadiobuttonGroup is the group of all possible radiobuttons of which only one can be selected.
func (RadiobuttonGroup) Selected ¶
func (g RadiobuttonGroup) Selected() *Radiobutton
Selected returns the currently selected radiobutton in the group.
type Result ¶
type Result struct { Hit UI // the UI where the event ended up Consumed bool // whether event was consumed, and should not be further handled by upper UI's Warp *image.Point // if set, mouse will warp to location }
Result holds the effects of a mouse/key event, as implement by UIs.
func KidsKey ¶
KidsKey delivers key event key to the UI at m. Orig is passed so UIs can calculate locations to warp the mouse to.
func KidsMouse ¶
func KidsMouse(dui *DUI, self *Kid, kids []*Kid, m draw.Mouse, origM draw.Mouse, orig image.Point) (r Result)
KidsMouse delivers mouse event m to the UI at origM (often the same, but not in case button is held pressed). Mouse positions are always relative to their own origin. Orig is passed so UIs can calculate locations to warp the mouse to.
type Scroll ¶
type Scroll struct { Kid Kid Height int // < 0 means full height, 0 means as much as necessary, >0 means exactly that many lowdpi pixels // contains filtered or unexported fields }
Scroll shows a part of its single child, typically a box, and lets you scroll the content.
type SeekReaderAt ¶
SeekReaderAt is used as a source for edits. The seeker is used to determine file size, the readerAt for reading.
type Space ¶
type Space struct {
Top, Right, Bottom, Left int
}
Space represents the padding or margin on a UI element. In duit functions, these are typically in lowDPI pixels.
type Split ¶
type Split struct { // Space between the UIs, in lowDPI pixels. // If >0, users can drag the gutter. Manual changes are automatically stored and restored on next load, if you set ID in the containing Kid. Gutter int // Optional, must return the division of available space. Sum of dims must be dim. Split func(dim int) (dims []int) `json:"-"` Vertical bool Kids []*Kid // Hold UIs shown in split. Background *draw.Image `json:"-"` // For background color. // contains filtered or unexported fields }
Split is a horizontal or vertical split of the available space, with 1 or more UIs.
type Tabs ¶
type Tabs struct { Buttongroup *Buttongroup // Shown at top of Tabs. UIs []UI // UIs selected by Buttongroup, must have same number of elements as buttons in Buttongroup. Box }
Tabs has a Buttongroup and displays only the active selected UI.
type UI ¶
type UI interface { // Layout asks the UI to layout itself and its children in `availSize`. // Layout must check `self.Layout` and `force`. // If force is set, it must layout itself and its kids, and pass on force. // Else, if self.Layout is DirtyKid, it only needs to call Layout on its kids (common for layout UIs). // The UI can lay itself out beyond size.Y, not beyond size.X. // size.Y is the amount of screen real estate that will still be visible. // Layout must update self.Draw if it needs to be drawn after. // Layout must update self.R with a image.ZP-origin image.Rectangle of the size it allocated. Layout(dui *DUI, self *Kid, sizeAvail image.Point, force bool) // Draw asks the UI to draw itself on `img`, with `orig` as offset and `m` as the current mouse (for hover states) // as self.Kid indicates, and pass further Draw calls on to its children as necessary. // If `force` is set, the UI must draw itself, overriding self.Draw. Draw(dui *DUI, self *Kid, img *draw.Image, orig image.Point, m draw.Mouse, force bool) // Mouse tells the UI about mouse movement over it. // Layout UI's are in charge of passing these mouse events to their children. // `self.Layout` and `self.Draw` can be updated if the mouse event resulted in UIs needing relayout/redraw. // Again it's layout UI's responsibility to propagate requests from self.Layout and self.Draw to its parent. // `m` is the current mouse state, relative to this UIs zero point. // `origM` is the mouse of first button down change, to facilitate tracking dragging. If no button is down, origM is the same as m. // `orig` is the origin location of this UI. If you want to warp the mouse, add the origin to the UI-relative point. // Result is used to communicate results of the event back to the top. Mouse(dui *DUI, self *Kid, m draw.Mouse, origM draw.Mouse, orig image.Point) (r Result) // Key tells the UI about a key press over it. // Like in Mouse, `self.Layout` and `self.Draw` can be updated. // `k` is the key pressed. There are no key down/up events, only keys typed. // See the Key-constants in the draw library for use special keys like the arrow keys, // function keys and combinations with the cmd key. // `m` is the mouse location at the time of the key, relative to this UIs zero point. // `orig` is the origin location of this UI. If you want to warp the mouse, add the origin to the UI-relative point. Key(dui *DUI, self *Kid, k rune, m draw.Mouse, orig image.Point) (r Result) // FirstFocus returns where the focus should go next when "tab" is hit, if anything. FirstFocus(dui *DUI, self *Kid) (warp *image.Point) // Focus returns the focus-point for `ui`. Focus(dui *DUI, self *Kid, o UI) (warp *image.Point) // Mark looks for ui (itself or children), marks it as dirty for layout or draw (forLayout), // and propagates whether it marked anything back to the caller. Mark(self *Kid, o UI, forLayout bool) (marked bool) // Print line about ui that includes r and is prefixed with indent spaces, following by a Print on each child. Print(self *Kid, indent int) }
UI is the interface implemented by a user interface element. For example Button, List, Grid, Scroll. UIs must be able to layout themselves, draw themselves, handle mouse events, key presses, deal with focus requests. UIs also help with propagating UI state and logging. For contain UIs (those that mostly just contain other UIs), many of these functions can be implemented by a single call to the corresponding Kids*-function.
Source Files ¶
- alert.go
- box.go
- button.go
- buttongroup.go
- center.go
- checkbox.go
- doc.go
- duit.go
- edit.go
- edithist.go
- editvi.go
- error.go
- field.go
- grid.go
- gridlist.go
- helper.go
- icon.go
- image.go
- kids.go
- label.go
- list.go
- middle.go
- pick.go
- place.go
- radiobutton.go
- readimage.go
- rounded.go
- scroll.go
- space.go
- split.go
- tabs.go
- ui.go
Directories ¶
Path | Synopsis |
---|---|
examples
|
|
Scene provides a widget for duit, that can render a 3d scene and react to mouse and key events with changing the transformation matrix.
|
Scene provides a widget for duit, that can render a 3d scene and react to mouse and key events with changing the transformation matrix. |