Documentation ¶
Overview ¶
Package view provides an api to build a simple graphical user interface through the GUI type, e.g.
--------------------------main.go------------------------------- package main import ( "fmt" "os" "git.sr.ht/slukits/tdd-gio/view" ) func main() { gui, observer := view.GUI{}, make(chan *view.Message, 10) go controller(&gui, observer) gui.Main(observer, view.Size(300, 200)) } func controller(gui *view.GUI, observer chan *view.Message) { defer func() { if err, ok := gui.Mtx(view.MsgExit).(error); ok && err != nil { log.Fatal(err) } os.Exit(0) }() for { msg := <-observer switch msg { case view.MsgExit: return case view.MsgEventHandlingStarted: gui.Display(&view.Crosshair{}) default: fmt.Printf("view: %s\n", msg.Txt()) } } } ----------------------------------------------------------------
While a stateless ui-library has appeal a painted ui represents state and keeping track of it has serious advantages:
- Is the viewport size of a widget unchanged its last painting may be reused
- It makes the ui testable: If we want to do black box testing and there is no state we can't compare state which is typically how test assertions work.
- It allows for mouse events to be mapped to widgets.
Last but not least I think usability also counts and taking statelessness to the extreme seems to lead to unintuitive apis, e.g. it makes it quite hard to implement an MVC architecture.
Index ¶
- Constants
- Variables
- func SendTimeout(t time.Duration) internal.Option
- func Size(width, height int) internal.Option
- type Blank
- type Centered
- type Crosshair
- type CrosshairLayout
- type GUI
- type HAxis
- type Message
- type Metricer
- type MsgID
- type Option
- type Padded
- type Painter
- type SizedPainter
- type Sizer
- type String
- type StringLayout
- type VAxis
- type Widget
- type Widgeter
Constants ¶
const ( // SendTimeoutDflt is the default timeout a gui waits for a message // to be send. SendTimeoutDflt = time.Minute // SendTimeoutMsg is reported on setting the send timeout option SendTimeoutMsg = "send-timeout set to %v" // SendPnc is the panic message of a timed out message-send SendPnc = "sending a message timed out" )
const CrosshairMsg = "crosshair layout x-axis: %d,%d; y-axis %d,%d"
CrosshairMsg is the format string for the text of a crosshair layout message.
const PncMain = "view: gui: observer must not be zero"
PncMain is reported if a zero observer is passed into GUI.Main.
const StringMsg = "layed out string '%s' into rectangle %v"
StringMsg is reported if a Runes instance is painted with a viewport different from the last.
const WidgetMsg = "viewport(%d): %v"
WidgetMsg is the default message of an embedding widget that only wants its viewport reported on change of any of its dimensions.
const WindowSizeMsg = "window size set to %dx%d"
WindowSizeMsg is reported on setting initial window size
Variables ¶
var ( // MsgExit is send when a DestroyEvent (window closed) was received. // MsgExit context see [GUI.Mtx] provides a potentially occurred // system error. MsgExit = &Message{id: Exit, txt: "window closed"} // MsgPanic is reported when a panic in the event loop happened its // context see [GUI.Mtx] reports the panic-value. NOTE the SendPnc // issued by a timed out message send is naturally not reported but // reissued. MsgPanic = &Message{txt: "event-handling panicked"} // MsgEventHandlingStarted is reported right before the event- and // display-loop is entered. MsgEventHandlingStarted = &Message{txt: "event-handling started"} // MsgResize is reported on a frame event if the window size changed // since the last frame event. MsgResize = &Message{txt: "window resized"} )
var ErrMain = errors.New("gui: main must not be called twice")
ErrMain is reported if GUI.Main is called more often than once.
var ZeroViewportDelta image.Rectangle
ZeroViewportDelta is used by Widget.Update to express an unchanged viewport.
Functions ¶
func SendTimeout ¶
SendTimeout determines how long a GUI waits on the observer channel for a message to be picked up before it panics.
Types ¶
type Blank ¶
type Blank struct {
Widget
}
A Blank widget embeds the internals a widget needs; its Size defaults to zero and its Paint-method is a noop. A Blank widget may be used to implement your own widget or comes in handy for testing layout aspects.
type Centered ¶
type Centered struct { // SizedPainter which should be layed out centered. Widgeter }
Centered lays out mandatory set sized painter in the center of a provided viewport.
type Crosshair ¶
type Crosshair struct {
// contains filtered or unexported fields
}
Crosshair draws in its dimensions a vertically centered line over the whole height and a horizontally centered line over the whole width.
type CrosshairLayout ¶
type CrosshairLayout struct { // VAxis defines a crosshair's vertical axis VAxis VAxis // HAxis defines a crosshair's horizontal axis HAxis HAxis }
CrosshairLayout describes a Crosshair widget's layout.
type GUI ¶
type GUI struct {
// contains filtered or unexported fields
}
GUI provides an api to build graphical user interfaces.
func (*GUI) Display ¶
Display reports given widgets to the event handler which will layout and draw them on the next app.FrameEvent.
func (*GUI) Main ¶
Main ensures that the event-loop is started, the application window is shown and provides the main-thread to the underlying graphics system. On most systems Main will block forever. Main will panic if given observer is nil otherwise given GUI g reports its events to given observer. Main will fail on any subsequent call.
type Message ¶
type Message struct {
// contains filtered or unexported fields
}
A Message is reported by an GUI to an initially given observer.
type MsgID ¶
type MsgID = int
const ( // Exit ids the context of an event handler's exit message whose // context a potential error is. Exit MsgID = -iota - 1 // InitialWindowSize is reported by a GUI's setup having the Size // option set. InitialWindowSize // Resize is reported by the event handler on a frame event // providing a different size than the previous frame event. Resize ContextFree MsgID = 0 )
type Painter ¶
type Painter interface { // Paint a widget in given viewport. Paint(viewport image.Rectangle, ops *op.Ops) }
Painter implementations are paintable widgets.
type SizedPainter ¶
SizedPainter implementations provide a size relative to a given viewport and are paintable.
type Sizer ¶
type Sizer interface { // Size returns the size a widget would like to use of a given // viewport. Size(viewport image.Rectangle) image.Point }
Sizer implementations provide a size relative to a given viewport.
type String ¶
type String struct { // Sequence to paint and measure set string. giorune.Sequence // S is the string to paint on the window. S string Options []giorune.Option // contains filtered or unexported fields }
String wraps a set giorune.Sequence together with a string into a widget allowing for the sequence to be layed out in the gui.
type StringLayout ¶
StringLayout is the definition of a Runes layout which is reported as a message context if a Runes-widget is painted with a viewport different from the last.
type Widget ¶
type Widget struct {
// contains filtered or unexported fields
}
Widget implements what all Widgets of the view package have in common. Any widget must embed an instance of this type because it also implements private methods of the Widgeter interface.
func (Widget) ID ¶
ID returns the unique ID of a widget whose main use is to recognize messages referring to given widget w.
func (*Widget) Paint ¶
Paint of given widget w is a noop when it comes to painting but it reports its viewport each time it changes any of its dimensions.
Directories ¶
Path | Synopsis |
---|---|
Package internal provides functions/types that should be accessible for the testing backend and for the view but not for any one else.
|
Package internal provides functions/types that should be accessible for the testing backend and for the view but not for any one else. |