tbuikit

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

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

Go to latest
Published: Feb 13, 2014 License: MIT Imports: 3 Imported by: 2

README

Termbox UI Kit

Termbox UI Kit is a helper library which wraps around the Termbox-go library.

It offers a few levels of abstraction to build console-based user interfaces. The main types are the UI, which represents the ui in its entirety. Next is the screen, which is a container for widgets. A UI can contain any number of screens, of which one can be active. Finally there are the widgets, which can be placed onto screens. Some kinds of widgets can be "selected" and others are read only. Additionally, some widgets are backed by buffers, which the application can read from / write to and the contents of which will be displayed in the widget.

Widget positioning is handled by callback function (the scope of which belongs to your application). This means you can define either fixed positions and sizes or use resizable (by accessing the console's width and height).

Keybindings are handled similarly; keys are bound to the ui, screens and widgets which take a callback function. The functions return an instance of whatever ui element owned the key binding, as well as the binding itself.

IMPORTANT - WARNING

The API is still very much in flux - at the moment there are some very long constructor methods to make new widgets and I'm still considering whether or not I'd prefer to have a bunch of setter methods instead of that.

There are also a lot of features I'd like to add, some of which could have consequences on the API.

Installation

Install and update this go package with go get -u github.com/gabriel-comeau/tbuikit You'll also want to install termbox-go (for access to the colors) with go get -u github.com/nsf/termbox-go

Examples

As an example application, there's a simple chat client (and server to go with it) which I've written at SimpleChatClient and SimpleChatServer

Documentation

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

func GetTermboxHeight

func GetTermboxHeight() int

Same as getTermboxWith but for height

func GetTermboxWidth

func GetTermboxWidth() int

Gets only the termbox's width - since it constantly returns both values and we don't always want both, this is basically a wrapper around _ = h

func MoveCursor

func MoveCursor(xOffset, y int, bufferLine string)

Move the cursor to the end of the provided string, starting at a given xOffset (not all widgets start at the left edge of the screen!)

func SplitBufferLines

func SplitBufferLines(stringToSplit string, width int) []string

Splits up a string into a slice of strings, making "lines" of text to display. The criteria is to split by width (buffer widget width)

TODO It'd be nice to split on whitespace instead of in the middle of a word!

func TermboxPrint

func TermboxPrint(x, y int, fg, bg termbox.Attribute, msg string)

Prints a string to a termbox buffer. Takes the height and starting x position and then prints the string RTL

func TermboxPrintf

func TermboxPrintf(x, y int, fg, bg termbox.Attribute, format string, args ...interface{})

Same as print_tb but takes a formatted string

Types

type ButtonWidget

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

A widget which acts like a button. It can be selected and then "pressed" via a key binding.

func CreateButtonWidget

func CreateButtonWidget(buttonText string, textPos ScreenPosition, defTextCol, selTextCol, defBgCol, selBgCol, defBorCol, selBorCol termbox.Attribute,
	calcFunction CalcFunction, selectable, selected bool) *ButtonWidget

A "constructor" function to create new widgets.

func (*ButtonWidget) AddCharKeyCallback

func (this *ButtonWidget) AddCharKeyCallback(char rune, callback EventCallback)

Take widget level printable-key (rune) handler function

func (*ButtonWidget) AddSpecialKeyCallback

func (this *ButtonWidget) AddSpecialKeyCallback(key termbox.Key, callback EventCallback)

Take widget level meta-key (termbox.Key) handler function

func (*ButtonWidget) CalculateSize

func (this *ButtonWidget) CalculateSize()

Meant to be called when the terminal dimensions are resized, it calls the callback function and refigures out the sizing and positioning of the rectacngle.

func (*ButtonWidget) Draw

func (this *ButtonWidget) Draw()

Draw the button every iteration of the main loop. Figure out where to put the button text within the button, make sure the borders get drawn and then draw the text in the figured out location.

func (*ButtonWidget) HandleEvents

func (this *ButtonWidget) HandleEvents(event interface{})

If this widget is selected, handle key inputs based on mapped keys

func (*ButtonWidget) IsSelectable

func (this *ButtonWidget) IsSelectable() bool

Check if this widget should be flaggable as selected.

func (*ButtonWidget) IsSelected

func (this *ButtonWidget) IsSelected() bool

Check if this widget is flagged as selected. Accessor because eventually want to implement logic to test for isSelectable

func (*ButtonWidget) Select

func (this *ButtonWidget) Select()

Selects this widget - it'd probably make sense to return an error if this widget isn't selectable

func (*ButtonWidget) SetText

func (this *ButtonWidget) SetText(btnText string)

Setter for the button's displayed text.

func (*ButtonWidget) Unselect

func (this *ButtonWidget) Unselect()

Unset selection status

type CalcFunction

type CalcFunction func() (x1, x2, y1, y2 int)

Callback function used to dynamically resize the rectangle when the screen changes size

type ColorizedString

type ColorizedString struct {
	Color termbox.Attribute
	Text  string
}

Holds a string and a color to print it in

type ColorizedStringBuffer

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

This type wraps a string slice to be used to display string-wrapper objects on the screen. The objects are simple tuples, containing the string and the color to display it as. Has a maximum size and will truncate old strings once this is reached

func (*ColorizedStringBuffer) Add

func (this *ColorizedStringBuffer) Add(msg *ColorizedString)

Adds a new element to the end of the stack, and will clip anything over capacity off the bottom.

func (*ColorizedStringBuffer) Clear

func (this *ColorizedStringBuffer) Clear()

Clear the buffer's contents.

func (*ColorizedStringBuffer) GetContents

func (this *ColorizedStringBuffer) GetContents(lineLength, lineCount int) []*ColorizedString

Gets the lines out of the buffer. This will split any lines that are too long into two (or as many as it takes until they are shorter than line length) lines and then returns the last <lineCount> number of lines.

func (*ColorizedStringBuffer) Prepare

func (this *ColorizedStringBuffer) Prepare(capacity int)

Call this to setup the slice when creating one of these

type ColorizedStringWidget

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

A widget which essentially knows how to draw message objects. It relies on a buffer type which meets the TextBuffer interface being passed in.

To control where it is drawn on the screen, it uses a function value which returns the four corners of a rectangle, which represents it's location on the screen.

These shouldn't be created via new() - use the CreateColorizedTextWidget() call instead.

func CreateColorizedTextWidget

func CreateColorizedTextWidget(textColor, borderColor, bgColor termbox.Attribute, calcFunction CalcFunction, buffer *ColorizedStringBuffer) *ColorizedStringWidget

A "constructor" function to create new widgets.

func (*ColorizedStringWidget) CalculateSize

func (this *ColorizedStringWidget) CalculateSize()

Meant to be called when the terminal dimensions are resized, it calls the callback function and refigures out the sizing and positioning of the rectacngle.

func (*ColorizedStringWidget) Draw

func (this *ColorizedStringWidget) Draw()

This is the draw call - it takes a buffer type which meets the text buffer interface and draws the text in it to the screen at the positions defined by its rectangle.

func (*ColorizedStringWidget) HandleEvents

func (this *ColorizedStringWidget) HandleEvents(event interface{})

This kind of widget cannot be selected. For the moment do nothing, this is just here to satisfy the interface.

func (*ColorizedStringWidget) IsSelectable

func (this *ColorizedStringWidget) IsSelectable() bool

This widget cannot ever be selectable, so always return false.

func (*ColorizedStringWidget) IsSelected

func (this *ColorizedStringWidget) IsSelected() bool

This widget cannot ever be selectable, so always return false.

func (*ColorizedStringWidget) Select

func (this *ColorizedStringWidget) Select()

This kind of widget cannot be selected. For the moment do nothing, this is just here to satisfy the interface.

func (*ColorizedStringWidget) Unselect

func (this *ColorizedStringWidget) Unselect()

This kind of widget cannot be selected. For the moment do nothing, this is just here to satisfy the interface.s

type EventCallback

type EventCallback func(interface{}, interface{})

A callback function which can be mapped to a key in various levels of the interface. When the keybinding is detected, the callback is executed and passed a pointer to the ui element which was called and the key which was pressed.

The key pressed can either be a rune (for printable keys) or a meta character of type termbox.Key

type LabelWidget

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

A widget which prints text to the screen, like a button but deliberately can't be selected.

func CreateLabelWidget

func CreateLabelWidget(text string, drawBor bool, textPos ScreenPosition, textCol, bgCol, borCol termbox.Attribute,
	calcFunction CalcFunction) *LabelWidget

A "constructor" function to create new widgets.

func (*LabelWidget) CalculateSize

func (this *LabelWidget) CalculateSize()

Meant to be called when the terminal dimensions are resized, it calls the callback function and refigures out the sizing and positioning of the rectacngle.

func (*LabelWidget) Draw

func (this *LabelWidget) Draw()

Draw the label every iteration of the main loop. Figure out where to put the button text within the label, make sure the borders get drawn and then draw the text in the figured out location.

func (*LabelWidget) HandleEvents

func (this *LabelWidget) HandleEvents(event interface{})

This kind of widget cannot be selected. For the moment do nothing, this is just here to satisfy the interface.

func (*LabelWidget) IsSelectable

func (this *LabelWidget) IsSelectable() bool

This widget cannot ever be selectable, so always return false.

func (*LabelWidget) IsSelected

func (this *LabelWidget) IsSelected() bool

This widget cannot ever be selectable, so always return false.

func (*LabelWidget) Select

func (this *LabelWidget) Select()

This kind of widget cannot be selected. For the moment do nothing, this is just here to satisfy the interface.

func (*LabelWidget) SetText

func (this *LabelWidget) SetText(text string)

Setter for the label's displayed text.

func (*LabelWidget) Unselect

func (this *LabelWidget) Unselect()

This kind of widget cannot be selected. For the moment do nothing, this is just here to satisfy the interface.s

type PasswordInputWidget

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

A widget meant for password input. It stores the real value in the buffer but it displays everything as an "*"

To control where it is drawn on the screen, it uses a function value which returns the four corners of a rectangle, which represents it's location on the screen.

These shouldn't be created via new() - use the CreatePasswordInputWidget() call instead.

func CreatePasswordInputWidget

func CreatePasswordInputWidget(hasCursor bool, color termbox.Attribute, bg termbox.Attribute, selbg termbox.Attribute,
	calcFunction CalcFunction, buffer *TextInputBuffer, selectable bool, selected bool) *PasswordInputWidget

A "constructor" function to create new widgets.

func (*PasswordInputWidget) AddCharKeyCallback

func (this *PasswordInputWidget) AddCharKeyCallback(char rune, callback EventCallback)

Take widget level printable-key (rune) handler function

func (*PasswordInputWidget) AddSpecialKeyCallback

func (this *PasswordInputWidget) AddSpecialKeyCallback(key termbox.Key, callback EventCallback)

Take widget level meta-key (termbox.Key) handler function

func (*PasswordInputWidget) CalculateSize

func (this *PasswordInputWidget) CalculateSize()

Meant to be called when the terminal dimensions are resized, it calls the callback function and refigures out the sizing and positioning of the rectacngle.

func (*PasswordInputWidget) Draw

func (this *PasswordInputWidget) Draw()

This is the draw call - it takes a buffer type which meets the text buffer interface and draws the text in it to the screen at the positions defined by its rectangle.

func (*PasswordInputWidget) GetBuffer

func (this *PasswordInputWidget) GetBuffer() *TextInputBuffer

Get the buffer - if we're able to switch selected items we'll probably want to be able to switch the buffer at the same time.

func (*PasswordInputWidget) HandleEvents

func (this *PasswordInputWidget) HandleEvents(event interface{})

If this widget is selected, handle key inputs based on mapped keys

func (*PasswordInputWidget) IsSelectable

func (this *PasswordInputWidget) IsSelectable() bool

Check if this widget should be flaggable as selected.

func (*PasswordInputWidget) IsSelected

func (this *PasswordInputWidget) IsSelected() bool

Check if this widget is flagged as selected. Accessor because eventually want to implement logic to test for isSelectable

func (*PasswordInputWidget) Select

func (this *PasswordInputWidget) Select()

Selects this widget - it'd probably make sense to return an error if this widget isn't selectable

func (*PasswordInputWidget) Unselect

func (this *PasswordInputWidget) Unselect()

Unset selection status

func (*PasswordInputWidget) UseDefaultKeys

func (this *PasswordInputWidget) UseDefaultKeys(use bool)

Enable using the default key bindings for the widget.

type Rectangle

type Rectangle struct {
	X1 int
	X2 int
	Y1 int
	Y2 int
}

Represents a simple rectangle

func CreateRectangle

func CreateRectangle(x1, x2, y1, y2 int) *Rectangle

Creates a new rectangle object

func (*Rectangle) Height

func (this *Rectangle) Height() int

Gets the rectangle's height

func (*Rectangle) Width

func (this *Rectangle) Width() int

Gets the rectangle's width

type Screen

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

Basically a widget holder at the moment

func (*Screen) Activate

func (this *Screen) Activate()

Sets this screen to active

func (*Screen) AddCharKeyCallback

func (this *Screen) AddCharKeyCallback(char rune, callback EventCallback)

Add a keybinding to the screen -- these override widget level keybindings so don't add keys here unless you're sure that the containing widgets won't need them.

This function is for printing keys - everything that normally prints a character to the screen. It takes runes as it's argument.

func (*Screen) AddSpecialKeyCallback

func (this *Screen) AddSpecialKeyCallback(event termbox.Key, callback EventCallback)

Add a keybinding to the screen -- these override widget level keybindings so don't add keys here unless you're sure that the containing widgets won't need them.

This function is for metakeys (those of type termbox.Key) - nonprinting keys basically

func (*Screen) AddWidget

func (this *Screen) AddWidget(widget Widget)

Adds a new widget to the screen

func (*Screen) Deactivate

func (this *Screen) Deactivate()

Sets this screen to active

func (*Screen) DoResize

func (this *Screen) DoResize()

To call when the screen resizes - it cycles through each widget and forces them to recalculate

func (*Screen) Draw

func (this *Screen) Draw()

Loop through our widgets and draw them all to the screen.

func (*Screen) GetCurrentSelectedWidget

func (this *Screen) GetCurrentSelectedWidget() (w Widget, ind int)

Iterate through the widgets and return the selected one or nil if there isn't one. Also returns position this widget was

func (*Screen) GetSelectableWidgets

func (this *Screen) GetSelectableWidgets() []Widget

Get all of the selectable widgets held by the screen

func (*Screen) HandleEvents

func (this *Screen) HandleEvents(event interface{})

Keyboard event handling. All calls to screen level callbacks get a pointer to the screen in question.

func (*Screen) IsActive

func (this *Screen) IsActive() bool

Predicate to see whether or not this screen is active.

func (*Screen) SelectNextWidget

func (this *Screen) SelectNextWidget()

Cycles through the selectable widgets

type ScreenPosition

type ScreenPosition int

Represents positions - typically where text is inside a widget.

const (
	// Positions
	TOP_LEFT     ScreenPosition = 0
	TOP_RIGHT    ScreenPosition = 1
	BOTTOM_LEFT  ScreenPosition = 2
	BOTTOM_RIGHT ScreenPosition = 3
	CENTER       ScreenPosition = 4
)

Declare some library wide constants

type StringBuffer

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

This type wraps a string slice to be used to display strings on the screen. Has a maximum size and will truncate old strings once this is reached

func (*StringBuffer) Add

func (this *StringBuffer) Add(str string)

Adds a new element to the end of the stack, and will clip anything over capacity off the bottom.

func (*StringBuffer) Clear

func (this *StringBuffer) Clear()

Clear the buffer's contents.

func (*StringBuffer) GetContents

func (this *StringBuffer) GetContents(lineLength, lineCount int) []string

Gets the lines out of the buffer. This will split any lines that are too long into two (or as many as it takes until they are shorter than line length) lines and then returns the last <lineCount> number of lines.

func (*StringBuffer) Prepare

func (this *StringBuffer) Prepare(capacity int)

Call this to setup the slice when creating one of these

type StringDisplayWidget

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

A widget which knows how to draw strings.

It pulls the strings from a buffer, which can be populated by the application. Unlike a text input widget, this is supposed to be a readonly widget.

To control where it is drawn on the screen, it uses a function value which returns the four corners of a rectangle, which represents it's location on the screen.

These shouldn't be created via new() - use the CreateColorizedTextWidget() call instead.

func CreateStringDisplayWidget

func CreateStringDisplayWidget(textColor, borderColor, bgColor termbox.Attribute, calcFunction CalcFunction, buffer *StringBuffer) *StringDisplayWidget

A "constructor" function to create new widgets.

func (*StringDisplayWidget) CalculateSize

func (this *StringDisplayWidget) CalculateSize()

Meant to be called when the terminal dimensions are resized, it calls the callback function and refigures out the sizing and positioning of the rectacngle.

func (*StringDisplayWidget) Draw

func (this *StringDisplayWidget) Draw()

This is the draw call - it takes a buffer type which meets the text buffer interface and draws the text in it to the screen at the positions defined by its rectangle.

func (*StringDisplayWidget) HandleEvents

func (this *StringDisplayWidget) HandleEvents(event interface{})

This kind of widget cannot be selected. For the moment do nothing, this is just here to satisfy the interface.

func (*StringDisplayWidget) IsSelectable

func (this *StringDisplayWidget) IsSelectable() bool

This widget cannot ever be selectable, so always return false.

func (*StringDisplayWidget) IsSelected

func (this *StringDisplayWidget) IsSelected() bool

This widget cannot ever be selectable, so always return false.

func (*StringDisplayWidget) Select

func (this *StringDisplayWidget) Select()

This kind of widget cannot be selected. For the moment do nothing, this is just here to satisfy the interface.

func (*StringDisplayWidget) Unselect

func (this *StringDisplayWidget) Unselect()

This kind of widget cannot be selected. For the moment do nothing, this is just here to satisfy the interface.s

type TextInputBuffer

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

This buffer represents the storage for any field a user can type text into

func (*TextInputBuffer) Add

func (this *TextInputBuffer) Add(char rune)

Adds a new element to the end of the stack (just a method form of append)

func (*TextInputBuffer) Backspace

func (this *TextInputBuffer) Backspace()

Removes the last element from the buffer

func (*TextInputBuffer) Clear

func (this *TextInputBuffer) Clear()

Clears the buffer

func (*TextInputBuffer) GetLines

func (this *TextInputBuffer) GetLines(lineLength, lineCount int) []string

Returns the text contents of this buffer as a slice of strings. The number of strings returned depends on how long the text the buffer contains and how long the desired lineLength is. lineLength can be set to 0 in order to force the buffer's contents into a single string and return a single element slice containing it.

Line count can optionally be used to return only the last n lines, if a maximum number of lines is a concern.

func (*TextInputBuffer) IsEmpty

func (this *TextInputBuffer) IsEmpty() bool

Checks if this buffer is empty

func (*TextInputBuffer) ReturnAndClear

func (this *TextInputBuffer) ReturnAndClear() string

Wraps the call to toString and then clear, which is what the enter key should do

func (*TextInputBuffer) SetLength

func (this *TextInputBuffer) SetLength(length int)

type TextInputWidget

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

A widget which essentially knows how to draw a slice of strings. It relies on a buffer type which meets the TextBuffer interface being passed in.

To control where it is drawn on the screen, it uses a function value which returns the four corners of a rectangle, which represents it's location on the screen.

These shouldn't be created via new() - use the CreateTextInputBufferWidget() call instead.

func CreateTextInputWidget

func CreateTextInputWidget(hasCursor bool, color termbox.Attribute, bg termbox.Attribute, selbg termbox.Attribute,
	calcFunction CalcFunction, buffer *TextInputBuffer, selectable bool, selected bool) *TextInputWidget

A "constructor" function to create new widgets.

func (*TextInputWidget) AddCharKeyCallback

func (this *TextInputWidget) AddCharKeyCallback(char rune, callback EventCallback)

Take widget level printable-key (rune) handler function

func (*TextInputWidget) AddSpecialKeyCallback

func (this *TextInputWidget) AddSpecialKeyCallback(key termbox.Key, callback EventCallback)

Take widget level meta-key (termbox.Key) handler function

func (*TextInputWidget) CalculateSize

func (this *TextInputWidget) CalculateSize()

Meant to be called when the terminal dimensions are resized, it calls the callback function and refigures out the sizing and positioning of the rectacngle.

func (*TextInputWidget) Draw

func (this *TextInputWidget) Draw()

This is the draw call - it takes a buffer type which meets the text buffer interface and draws the text in it to the screen at the positions defined by its rectangle.

func (*TextInputWidget) GetBuffer

func (this *TextInputWidget) GetBuffer() *TextInputBuffer

Get the buffer - if we're able to switch selected items we'll probably want to be able to switch the buffer at the same time.

func (*TextInputWidget) HandleEvents

func (this *TextInputWidget) HandleEvents(event interface{})

If this widget is selected, handle key inputs based on mapped keys

func (*TextInputWidget) IsSelectable

func (this *TextInputWidget) IsSelectable() bool

Check if this widget should be flaggable as selected.

func (*TextInputWidget) IsSelected

func (this *TextInputWidget) IsSelected() bool

Check if this widget is flagged as selected. Accessor because eventually want to implement logic to test for isSelectable

func (*TextInputWidget) Select

func (this *TextInputWidget) Select()

Selects this widget - it'd probably make sense to return an error if this widget isn't selectable

func (*TextInputWidget) Unselect

func (this *TextInputWidget) Unselect()

Unset selection status

func (*TextInputWidget) UseDefaultKeys

func (this *TextInputWidget) UseDefaultKeys(use bool)

Enable using the default key bindings for the widget.

type UI

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

Represents the top level of a TermboxUIKit UI. It manages screens, handles the global level keyboard (or resize) events, and handles shutting the entire UI down.

func (*UI) AddCharKeyCallback

func (this *UI) AddCharKeyCallback(char rune, callback EventCallback)

Adds a global level event binding for a printable key

func (*UI) AddScreen

func (this *UI) AddScreen(screen *Screen)

Adds a screen to the collection

func (*UI) AddSpecialKeyCallback

func (this *UI) AddSpecialKeyCallback(event termbox.Key, callback EventCallback)

Adds a global level event binding for a meta key

func (*UI) SetDrawDelay

func (this *UI) SetDrawDelay(delay int)

Set the delay time between redraws, in milliseconds If this isn't set, it will default to 10 ms between refreshes, which can be plenty fast enough or very slow, depending on what you want your app to do. Using actual zero, even with minimal UI elements, quickly chews through CPU time.

func (*UI) Shutdown

func (this *UI) Shutdown()

Sends the shutdown signal, breaking the main loop

func (*UI) Start

func (this *UI) Start(quitChan chan bool)

type Widget

type Widget interface {
	Draw()
	CalculateSize()

	// Handle widget selection
	IsSelectable() bool
	IsSelected() bool
	Select()
	Unselect()

	// Handle keyboard events -- this is an interface{} because
	// it can either be a termbox.Key or rune at the moment
	HandleEvents(interface{})
}

Interface defining widgets - a function to draw them to the screen and one to call when the screen is resized.

Jump to

Keyboard shortcuts

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