lines

package module
v0.10.0 Latest Latest
Warning

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

Go to latest
Published: Feb 25, 2023 License: MIT Imports: 11 Imported by: 4

README

Overview

lines provides an unopinionated simple UI library which does the heavy lifting for you when it comes to

  • concurrency safety
  • event handling
  • layout handling
  • content/format handling
  • feature handling
  • testing

Following example will crash in the go playground since it can't grab a terminal:

package main

import (
    fmt

    "github.com/slukits/lines"
)

type Cmp struct { lines.Component }

func (c *Cmp) OnInit(e *lines.Env) {
    c.Dim().SetWidth(len("hello world")).SetHeight(1)
    fmt.Fprint(e, "hello world")
}

func main() {
    lines.Term(&Cmp{}).WaitForQuit()
}

Term provides an Lines-instance with a terminal backend. It reports user input and programmatically posted events to listener implementations of client provided components. While client listener implementations print to an provided environment which is associated with the component's portion of the screen. lines is designed to add further backends like "shiny" or "fyne" for graphical displays. As of now lines has only a terminal backend which wraps the package tcell.

Above "hello world"-program takes over a terminal screen printing horizontally and vertically centered "hello world" to it. "hello world" stays centered in case the screen is a terminal window which changes its size. Ctrl-c, Ctrl-d or q will quit the application. Note SetWidth in above example works as expected because "hello world" consists of ASCII characters only. Is that not guaranteed you will want to count runes instead of bytes. Setting width and height is not necessary. Left out in above example "hello world" is printed to the screen starting in the upper left corner.

Note lines doesn't come for example with menu, context-menu or tool-tip components but with the means to implement them as intricate and complex as needed. In the cmp/selects-package you can find the List and DropDown components used to implement the components for above demonstration. I.e. lines has a sufficient feature set to build complex components and the code in cmp shows you by example how to do so.

Concurrency safety

What doesn't work

func (c *Cmp) OnInit(e *lines.Env) {
    go func() {
        time.Sleep(1*time.Second)
        fmt.Fprint(e, "awoken") // will panic
    }()
}

what does work

func (c *Cmp) OnInit(e *lines.Env) {
    go func(ll *lines.Lines) {
        time.Sleep(1*time.Second)
        ll.Update(c, nil, func(e *lines.Env) {
             fmt.Fprint(e, "awoken") // will not panic
        })
    }(e.Lines)
}

Also using functionality or properties provided by embedded Component instance in a function that doesn't return in the executing listener won't work.

func (c *Cmp) OnInit(e *lines.Env) {
    go func() {
        time.Sleep(1*time.Second)
        c.FF.Add(Scrollable) // panic or race condition
        c.Dim().SetWidth(42) // panic or race condition
    }()
}

It is only save to pass (the initially created) Lines instance on to a go routine where at the end provided update mechanisms of said Lines-instance are used to report back to a component.

Event handling

The majority of lines' interfaces are for event handling. Is such an interface implemented in a component, corresponding events are reported to that component. See lines.Eventer for a list of reported events. OnKey, OnFocus, OnLayout are exemplary methods of such interfaces. Keyboard and mouse events are bubbling up from the focused/clicked component through all enclosing ancestors. The environment instance e of such a reported bubbling event may be used to suppress bubbling: e.StopBubbling(). See examples/layers for how to work with events.

Layout handling

lines comes with a layout manager which does most of the work for you. If fine grained control is needed the embedded Component's Dim method informs about positioning and size and also provides features to change the later. One can also control there if a component is filling, i.e. uses up unused space, or if its size is fixed. Components can be arbitrarily nested by embedding either the Stacking or Chaining type in a component or by implementing either the Stacker or Chainer interface. Finally components can be layered by other components which makes it possible to implement tooltip, context menu, menu bar or modal dialogs. See examples/layers for how to work with layers.

Content and format handling

The Env(ironment) instance passed to a event listener is associated with the screen portion of the component the event is reported to. Printing to the environment prints provided content to its screen portion. Env comes with a few methods which give fine grained control over what is printer where and how. e.g.:

fmt.Fprint(e.LL(5).AA(lines.Bold),
    lines.Filler + "a centered bold line" + lines.Filler),
)

The above prints "a centered bold line" centered in bold letters into the component's fifth line. Note the line will stay centered if the component's size changes. If there should be many lines associated with a component cmp without storing them in the component a component's source can be set:

cmp.Src = &lines.ComponentSource{Liner: MyLinerImplementation}

Whereas the liner implementation prints the lines as requested by cmp. A similar printing API is provided by embedded Component's Gaps(index)-method

c.Gaps(0).AA(lines.Reverse)
c.Gaps(0).Corners.AA(lines.Revers)

above is as of now the simplest way to frame a component. Gaps allow to do all sorts of framing, padding and guttering of a component. See examples/gaps for an introduction of what can be done with gaps. Remember that Src and Gaps will panic if accessed outside a listener callback.

Feature handling

The feature concept answers the question after the default behavior of an ui-component. Lets assume we have implemented the components App, MessageBar, Statusbar, Workspace and Panel. Lets further assume component App stacks the components MessageBar, Workspace and Statusbar while a Workspace chains two panel instances p1 and p2.

APP--------------------------+
  |           mb             |
  WS-----------+-------------+
  |            |             |
  |    p1      |      p2     |
  |            |             |
  +------------+-------------+
  |           sb             |
  +--------------------------+

If we now click into p2 we probably expect p2 to receive the focus. But if we click into the statusbar will we also want sb to receive the focus? Maybe, maybe not. To avoid opinionated default behavior lines implements the "Feature" concept whose API may be accessed by the FF-property of the embedded Component instance.

type MyComponent { lines.Component }

func (c *MyComponent) OnInit(_ *lines.Env) {
    c.FF.Set(lines.Scrollable)
}

Now our component will react on page up/down key-presses if its content doesn't fit (vertically) into c's screen area. Since most features don't make sens for nesting components setting features at a stacker or chainer will set this feature to a all nested components. E.g.:

func (ws *Workspace) OnInit(e *lines.Env) {
    ws.FF.Set(lines.Focusable)
}

makes all descendants of the workspace focusable, i.e. they receive the focus if clicked with the mouse on them.

An other way to acquire features without fuss is to set a components content source which needs to have a Liner-implementation. According to the features of such a Liner-implementation the component's features are set. E.g. is a Liner a ScrollableLiner then the component gets automatically the scrollable feature set. examples/scrolling has examples for features usage.

Testing

lines comes with testing facilities:

import (
    "testing"

    "github.com/slukits/lines"
)

type CmpFixture struct { lines.Component }

func TestUpdateListenerIsCalled(t *T) {
    tt := lines.TermFixture(t, 0, &CmpFixture{})
    exp :=  "update listener called"
    tt.Lines.Update(tt.Root(), nil, func(e *lines.Env) {
        fmt.Fprint(e, exp)
    })
    if exp != tt.Screen().Trimmed().String() {
        t.Errorf("expected: '%s'; got '%s'", exp,
            tt.Screen().Trimmed().String())
    }
}

lines can be asked for a test fixture. The main features of an Fixture-instance are:

  • setting up and tearing down a corresponding Lines-instance whose WaitForQuit method is not blocking.

  • providing methods for emulating user input events

  • guaranteeing that no event-triggering method returns before its event and all subsequently triggered events have been processed and all writes made it to the screen. (The second argument of TermFixture is a timeout within all such events need to be processed.)

  • providing the screen's content and its styles.

Enjoy!

Documentation

Overview

Package lines provides an unopinionated simple text-oriented UI library. It does the heavy lifting for you when it comes to

  • concurrency safety
  • event handling
  • layout handling
  • content/format handling
  • feature handling
  • testing

Following example will crash in the go playground since it can't grab a terminal:

package main

import (
    fmt

    "github.com/slukits/lines"
)

type Cmp struct { lines.Component }

func (c *Cmp) OnInit(e *lines.Env) {
    c.Dim().SetWidth(len("hello world")).SetHeight(1)
    fmt.Fprint(e, "hello world")
}

func main() {
    lines.Term(&Cmp{}).WaitForQuit()
}

Term provides an Lines-instance with a terminal backend. It reports user input and programmatically posted events to listener of client provided components embedding the Component-type. While client listener implementations print to an provided environment Env which is associated with the component's portion of the screen. lines is designed to add further backends like "shiny" or "fyne" for graphical displays. As of now lines has only a terminal backend which is a wrapper around tcell.

Above "hello world"-program takes over a terminal screen printing horizontally and vertically centered "hello world" to it. "hello world" stays centered in case the screen is a terminal window which changes its size. Ctrl-c, Ctrl-d or q will quit the application. Note SetWidth in above example works as expected because "hello world" consists of ASCII characters only. Is that not guaranteed you will want to count runes instead of bytes. Setting width and height is not necessary. Left out in above example "hello world" is printed to the screen starting in the upper left corner.

Concurrency safety

What doesn't work

func (c *Cmp) OnInit(e *lines.Env) {
    go func() {
        time.Sleep(1*time.Second)
        fmt.Fprint(e, "awoken") // will panic
    }()
}

what does work

func (c *Cmp) OnInit(e *lines.Env) {
    go func(ll *lines.Lines) {
        time.Sleep(1*time.Second)
        ll.Update(c, nil, func(e *lines.Env) {
             fmt.Fprint(e, "awoken") // will not panic
        })
    }(e.Lines)
}

Also using functionality or properties provided by embedded Component instance in a function that doesn't return in the executing listener won't work.

func (c *Cmp) OnInit(e *lines.Env) {
    go func() {
        time.Sleep(1*time.Second)
        c.FF.Set(Scrollable) // panics or creates a race condition
        c.Dim().SetWidth(42) // panics or creates a race condition
    }()
}

It is only save to pass (the initially created) Lines instance on to a go routine where at the end provided update mechanisms of said Lines-instance are used to report back to a component.

Event handling

The majority of lines' interfaces are for event handling. Is such an interface implemented in a component, corresponding events are reported to that component. See lines.Eventer for a list of reported events. OnKey, OnFocus, OnLayout are exemplary methods of such interfaces. Keyboard and mouse events are bubbling up from the focused/clicked component through all enclosing ancestors. The environment instance e of such a reported bubbling event may be used to suppress bubbling: e.StopBubbling(). See examples/layers for how to work with events.

Layout handling

lines comes with a layout manager which does most of the work for you. If fine grained control is needed the embedded Component's Dim method (see Component.Dim) informs about positioning and size and also provides features to change the later. One can also control there if a component is filling, i.e. uses up unused space, or if its size is fixed. Components can be arbitrarily nested by embedding either the Stacking or Chaining type in a component or by implementing either the Stacker or Chainer interface. Finally components can be Component.Layered by other components which makes it possible to implement tooltip, context menu, menu bar or modal dialogs. See examples/layers for how to work with layers.

Content and format handling

The Env(ironment) instance passed to a event listener is associated with the screen portion of the component the event is reported to. Printing to the environment prints provided content to its screen portion. Env comes with a few methods which give fine grained control over what is printer where and how. e.g.:

fmt.Fprint(e.LL(5).AA(lines.Bold),
    lines.Filler + "a centered bold line" + lines.Filler)

The above prints "a centered bold line" centered in bold letters into the component's fifth line. Note the line will stay centered if the component's size changes. If there should be many lines associated with a component c without storing them in the component a component's ContentSource can be set:

c.Src = &lines.ContentSource{Liner: MyLinerImplementation}

Whereas the Liner implementation prints the lines as requested by c. See examples/scrolling for a sourced component example. A similar printing API is provided by embedded Component's Gaps(index)-method

c.Gaps(0).AA(lines.Reverse)
c.Gaps(0).Corners.AA(lines.Revers)

Above is as of now the simplest way to frame a component. Gaps allow to do all sorts of framing, padding and guttering of a component. See examples/gaps for some show cases. Remember that Src and Gaps will panic if accessed outside a listener callback.

Feature handling

The feature concept answers the question after the default behavior of an ui-component. Lets assume we have implemented the components App, MessageBar, Statusbar, Workspace and Panel. Lets further assume component App stacks the components MessageBar, Workspace and Statusbar while a Workspace chains two panel instances p1 and p2.

APP--------------------------+
  |           mb             |
  WS-----------+-------------+
  |            |             |
  |    p1      |      p2     |
  |            |             |
  +------------+-------------+
  |           sb             |
  +--------------------------+

If we now click into p2 we probably expect p2 to receive the focus. But if we click into the statusbar will we also want sb to receive the focus? Maybe, maybe not. To avoid opinionated default behavior lines implements the "Feature" concept whose API may be accessed by the FF-property of the embedded Component instance.

type MyComponent { lines.Component }

func (c *MyComponent) OnInit(_ *Env) {
    c.FF.Add(lines.Scrollable)
}

Now our component will react on page up/down key-presses if its content doesn't fit (vertically) into c's screen area. But we don't need to set each feature for each component separately:

func (ws *Workspace) OnInit(e *Env) {
    ws.FF.AddRecursively(lines.Scrollable | lines.Focusable)
}

The above line makes all descendants of the workspace focusable, i.e. they receive the focus if clicked with the mouse on them.

An other way to acquire features without fuss is to set a components ContentSource which needs to have a Liner-implementation. According to the features of such a Liner-implementation the component's features are set. E.g. is a Liner a ScrollableLiner then the component gets automatically the scrollable feature set. examples/scrolling has examples for features usage.

Testing

lines comes with testing facilities:

import (
    "testing"

    "github.com/slukits/lines"
)

type CmpFixture struct { lines.Component }

func TestUpdateListenerIsCalled(t *T) {
    tt := lines.TermFixture(t, 0, &CmpFixture{})
    exp :=  "update listener called"
    tt.Lines.Update(tt.Root(), nil, func(e *lines.Env) {
        fmt.Fprint(e, exp)
    })
    if exp != tt.Screen().Trimmed().String() {
        t.Errorf("expected: '%s'; got '%s'", exp,
            tt.Screen().Trimmed().String())
    }
}

lines can be asked for a test fixture. The main features of an Fixture-instance are:

  • setting up and tearing down a corresponding Lines-instance whose WaitForQuit method is not blocking.

  • providing methods for emulating user input events

  • guaranteeing that no event-triggering method returns before its event and all subsequently triggered events have been processed and all writes made it to the screen. (The second argument of TermFixture is a timeout within all such events need to be processed.)

  • providing the screen's content and its styles.

Enjoy!

Index

Constants

View Source
const (
	ZeroCursor              CursorStyle = api.ZeroCursor
	DefaultCursor                       = api.DefaultCursor
	BlockCursorBlinking                 = api.BlockCursorBlinking
	BlockCursorSteady                   = api.BlockCursorSteady
	UnderlineCursorBlinking             = api.UnderlineCursorBlinking
	UnderlineCursorSteady               = api.UnderlineCursorSteady
	BarCursorBlinking                   = api.BarCursorBlinking
	BarCursorSteady                     = api.BarCursorSteady
)
View Source
const All = -1

All indicates for an operation with a line-index that the operation should be executed for all lines, e.g. Component.Reset on a component.

View Source
const Filler = string(filler)

A Filler in a string printed to a component's environment e indicates that a line l should fill up its whole width whereas its remaining empty space is distributed equally over filler found in l.

fmt.Fprint(e.LL(0), lines.Filler+"centered first line"+lines.Filler)

See EnvAtWriter.Filling for a more sophisticated filling mechanism.

Variables

View Source
var ColorNames = map[Color]string{}/* 247 elements not displayed */
View Source
var DefaultStyle = api.DefaultStyle

The DefaultStyle has no style attributes and "default" colors. The semantics of the later is determined by the backend implementation. Use the With* methods to create new styles from the default style:

myStyle := lines.DefaultStyle.WithFG(lines.Yellow).WithBG(lines.Blue)
View Source
var NewLayerPos = lyt.NewLayerPos

NewLayerPos creates new layer positioning instance from given origin, width and height and returns a pointer to it which can be passed to Component.Layered.

View Source
var NewStyle = api.NewStyle

NewStyle creates a new style with given style attributes and given fore- and background color:

myStyle := lines.NewStyle(lines.Bold|lines.Dim, lines.White, lines.Black)
View Source
var StyleAttributeNames = map[StyleAttributeMask]string{
	Bold:          "bold",
	Blink:         "blink",
	Reverse:       "reverse",
	Underline:     "underline",
	Dim:           "dim",
	Italic:        "italic",
	StrikeThrough: "strike through",
	Invalid:       "invalid",
}

Functions

func Print

func Print(w AtWriter, rr interface{})

Print to an AtWriter a rune or slice of runes. The common AtWriter of lines are provided by a component listener environment and a components gaps:

lines.Print(e.LL(0).At(0), []rune("print to first line's first cell"))
lines.Print(cmp.Gaps(0).Left.At(5), []rune("print to left gutter"))

Types

type AfterIniter

type AfterIniter interface {

	// OnAfterInit is executed after all components have been
	// initialized and their respective OnInit event was reported.  I.e.
	// all components of an initial layout should be created and
	// available now.  Hence the main use case are initializations
	// depending on the existence of nested components. E.g. set the
	// focus or do size calculations depending on nested components.
	OnAfterInit(*Env)
}

AfterInit is implemented by components which want to be notified after all initial components have been created and their respective OnInit event was reported, see Initer; but before the first layout, see Layouter.

type AfterLayouter added in v0.10.0

type AfterLayouter interface {

	// OnAfterLayout implementations are called after all OnLayout
	// events have been reported and processed.  Since the typical
	// use-case is to adjust the layout of stacker and chainer according
	// to the layout of their nested components a "dimensions function"
	// DD is passed along which allows to extract layout dimensions for
	// an arbitrary component of the layout.
	OnAfterLayout(*Env, DD) (reflow bool)
}

AfterLayouter is implemented by components who want to be notified after all OnLayout-events have been reported and processed. Typically these are components nesting other components, i.e. Stacker and Chainer, who want to adjust their layout after their nested components have finished their layout settings.

type AtWriter

type AtWriter interface {
	WriteAt(rr []rune)
}

AtWriter is for printing runes at specific screen cells commonly used to define differentiated stylings printing to a component's environment e:

fmt.Fprint(e.LL(0), "An ")
lines.Print(e.LL(0).At(3).AA(Italic), "italic")
lines.Print(e.LL(0).At(9), " word")

type ButtonMask

type ButtonMask = api.ButtonMask

A ButtonMask mask is reported by a mouse event to a Mouser implementing component.

const (
	Button1    ButtonMask = api.Button1 // Usually the left (primary) mouse button.
	Button2    ButtonMask = api.Button2 // Usually the right (secondary) mouse button.
	Button3    ButtonMask = api.Button3 // Usually the middle mouse button.
	Button4    ButtonMask = api.Button4 // Often a side button (thumb/next).
	Button5    ButtonMask = api.Button5 // Often a side button (thumb/prev).
	Button6    ButtonMask = api.Button6
	Button7    ButtonMask = api.Button7
	Button8    ButtonMask = api.Button8
	WheelUp    ButtonMask = api.WheelUp    // Wheel motion up/away from user.
	WheelDown  ButtonMask = api.WheelDown  // Wheel motion down/towards user.
	WheelLeft  ButtonMask = api.WheelLeft  // Wheel motion to left.
	WheelRight ButtonMask = api.WheelRight // Wheel motion to right.
	ZeroButton ButtonMask = api.ZeroButton // No button or wheel events.

	Primary   ButtonMask = Button1
	Secondary ButtonMask = Button2
	Middle    ButtonMask = Button3
)

type CellsLine

type CellsLine = api.CellsLine

CellsLine represents a line of a CellsScreen providing of each cell in the line its displayed rune and style information for test-evaluations.

type CellsScreen

type CellsScreen = api.CellsScreen

CellsScreen is a screen representation at a specific point in time of of a [Fixtures]'s Lines instances. E.g. see Fixture.CellsOf or Fixture.Cells. NOTE use CellsScreen's Trimmed-method to minimize the reported screen area.

type Chainer

type Chainer interface {

	// ForChained calls back for each component of this Chainer
	// respectively until the callback asks to stop.
	ForChained(func(Componenter) (stop bool))
}

Chainer is implemented by components which want to provided nested components which are horizontally chained in the layout.

type Chaining

type Chaining struct {

	// CC holds the chained components
	CC []Componenter
}

Chaining embedded in a component makes the component implement the Chainer interface. Typically the Componenter slice CC is filled in a component's OnInit-listener:

type chainedCmp struct { lines.Component }

type myCmp struct{
	lines.Component
	lines.Chaining
}

func (c *myCmp) OnInit(_ *lines.Env) {
	for i := 0; i < 3; i++ {
		c.CC = append(c.CC, &chainedCmp{})
	}
}

func (Chaining) ForChained

func (cg Chaining) ForChained(cb func(Componenter) (stop bool))

ForChained calls back for each component of this Chainer respectively until the callback asks to stop.

type Clicker

type Clicker interface {

	// OnClick implementation of a component c gets "left click"-events
	// reported which is an aggregated mouse event.  I.e. Mouser
	// implementer will not receive a "left click" event.  x and y
	// provide the click coordinates translated into the "content area"
	// (c.ContentArea) of c.  This event bubbles; use e.StopBubbling()
	// to suppress further bubbling.  Note e.Evt.(*lines.MouseClick).Mod
	// provides also the modifiers information.
	OnClick(e *Env, x, y int)
}

Clicker is implemented by components which want to be informed about a "left"-mouse click event in their "content area". If the clicked component, i.e. the component with the smallest layout area containing the event coordinates, does not have the focus an OnFocus event is reported first if and only if the clicked component has the Focusable feature. See Mouser event interface for a more general mouse event handling.

type Color

type Color = api.Color

Color represents an rgb color which is usually given in the typical hex-format 0xRRGGBB whereas R, G and B are hex-digits, i.e. red is 0xFF0000.

const (
	Black             Color = api.Black
	Maroon            Color = api.Maroon
	Green             Color = api.Green
	Olive             Color = api.Olive
	Navy              Color = api.Navy
	Purple            Color = api.Purple
	Teal              Color = api.Teal
	Silver            Color = api.Silver
	Grey              Color = api.Grey
	Red               Color = api.Red
	Lime              Color = api.Lime
	Yellow            Color = api.Yellow
	Blue              Color = api.Blue
	Fuchsia           Color = api.Fuchsia
	Aqua              Color = api.Aqua
	White             Color = api.White
	Grey0             Color = api.Grey0
	NavyBlue          Color = api.NavyBlue
	DarkBlue          Color = api.DarkBlue
	Blue3             Color = api.Blue3
	Blue3_2           Color = api.Blue3_2
	Blue1             Color = api.Blue1
	DarkGreen         Color = api.DarkGreen
	DeepSkyBlue4      Color = api.DeepSkyBlue4
	DeepSkyBlue4_2    Color = api.DeepSkyBlue4_2
	DeepSkyBlue4_3    Color = api.DeepSkyBlue4_3
	DodgerBlue3       Color = api.DodgerBlue3
	DodgerBlue2       Color = api.DodgerBlue2
	Green4            Color = api.Green4
	SpringGreen4      Color = api.SpringGreen4
	Turquoise4        Color = api.Turquoise4
	DeepSkyBlue3      Color = api.DeepSkyBlue3
	DeepSkyBlue3_2    Color = api.DeepSkyBlue3_2
	DodgerBlue1       Color = api.DodgerBlue1
	Green3            Color = api.Green3
	SpringGreen3      Color = api.SpringGreen3
	DarkCyan          Color = api.DarkCyan
	LightSeaGreen     Color = api.LightSeaGreen
	DeepSkyBlue2      Color = api.DeepSkyBlue2
	DeepSkyBlue1      Color = api.DeepSkyBlue1
	Green3_2          Color = api.Green3_2
	SpringGreen3_2    Color = api.SpringGreen3_2
	SpringGreen2      Color = api.SpringGreen2
	Cyan3             Color = api.Cyan3
	DarkTurquoise     Color = api.DarkTurquoise
	Turquoise2        Color = api.Turquoise2
	Green1            Color = api.Green1
	SpringGreen2_2    Color = api.SpringGreen2_2
	SpringGreen1      Color = api.SpringGreen1
	MediumSpringGreen Color = api.MediumSpringGreen
	Cyan2             Color = api.Cyan2
	Cyan1             Color = api.Cyan1
	DarkRed           Color = api.DarkRed
	DeepPink4_3       Color = api.DeepPink4_3
	Purple4           Color = api.Purple4
	Purple4_2         Color = api.Purple4_2
	Purple3           Color = api.Purple3
	BlueViolet        Color = api.BlueViolet
	Orange4           Color = api.Orange4
	Grey37            Color = api.Grey37
	MediumPurple4     Color = api.MediumPurple4
	SlateBlue3        Color = api.SlateBlue3
	SlateBlue3_2      Color = api.SlateBlue3_2
	RoyalBlue1        Color = api.RoyalBlue1
	Chartreuse4       Color = api.Chartreuse4
	DarkSeaGreen4     Color = api.DarkSeaGreen4
	PaleTurquoise4    Color = api.PaleTurquoise4
	SteelBlue         Color = api.SteelBlue
	SteelBlue3        Color = api.SteelBlue3
	CornflowerBlue    Color = api.CornflowerBlue
	Chartreuse3       Color = api.Chartreuse3
	DarkSeaGreen4_2   Color = api.DarkSeaGreen4_2
	CadetBlue         Color = api.CadetBlue
	CadetBlue_2       Color = api.CadetBlue_2
	SkyBlue3          Color = api.SkyBlue3
	SteelBlue1        Color = api.SteelBlue1
	Chartreuse3_2     Color = api.Chartreuse3_2
	PaleGreen3        Color = api.PaleGreen3
	SeaGreen3         Color = api.SeaGreen3
	Aquamarine3       Color = api.Aquamarine3
	MediumTurquoise   Color = api.MediumTurquoise
	SteelBlue1_2      Color = api.SteelBlue1_2
	Chartreuse2       Color = api.Chartreuse2
	SeaGreen2         Color = api.SeaGreen2
	SeaGreen1         Color = api.SeaGreen1
	SeaGreen1_2       Color = api.SeaGreen1_2
	Aquamarine1       Color = api.Aquamarine1
	DarkSlateGray2    Color = api.DarkSlateGray2
	DarkRed_2         Color = api.DarkRed_2
	DeepPink4_2       Color = api.DeepPink4_2
	DarkMagenta       Color = api.DarkMagenta
	DarkMagenta_2     Color = api.DarkMagenta_2
	DarkViolet        Color = api.DarkViolet
	Purple_1          Color = api.Purple_1
	Orange4_2         Color = api.Orange4_2
	LightPink4        Color = api.LightPink4
	Plum4             Color = api.Plum4
	MediumPurple3     Color = api.MediumPurple3
	MediumPurple3_2   Color = api.MediumPurple3_2
	SlateBlue1        Color = api.SlateBlue1
	Yellow4           Color = api.Yellow4
	Wheat4            Color = api.Wheat4
	Grey53            Color = api.Grey53
	LightSlateGrey    Color = api.LightSlateGrey
	MediumPurple      Color = api.MediumPurple
	LightSlateBlue    Color = api.LightSlateBlue
	Yellow4_2         Color = api.Yellow4_2
	DarkOliveGreen3   Color = api.DarkOliveGreen3
	DarkSeaGreen      Color = api.DarkSeaGreen
	LightSkyBlue3     Color = api.LightSkyBlue3
	LightSkyBlue3_2   Color = api.LightSkyBlue3_2
	SkyBlue2          Color = api.SkyBlue2
	Chartreuse2_2     Color = api.Chartreuse2_2
	DarkOliveGreen3_2 Color = api.DarkOliveGreen3_2
	PaleGreen3_2      Color = api.PaleGreen3_2
	DarkSeaGreen3     Color = api.DarkSeaGreen3
	DarkSlateGray3    Color = api.DarkSlateGray3
	SkyBlue1          Color = api.SkyBlue1
	Chartreuse1       Color = api.Chartreuse1
	LightGreen        Color = api.LightGreen
	LightGreen_2      Color = api.LightGreen_2
	PaleGreen1        Color = api.PaleGreen1
	Aquamarine1_2     Color = api.Aquamarine1_2
	DarkSlateGray1    Color = api.DarkSlateGray1
	Red3              Color = api.Red3
	DeepPink4         Color = api.DeepPink4
	MediumVioletRed   Color = api.MediumVioletRed
	Magenta3          Color = api.Magenta3
	DarkViolet_2      Color = api.DarkViolet_2
	Purple_2          Color = api.Purple_2
	DarkOrange3       Color = api.DarkOrange3
	IndianRed         Color = api.IndianRed
	HotPink3          Color = api.HotPink3
	MediumOrchid3     Color = api.MediumOrchid3
	MediumOrchid      Color = api.MediumOrchid
	MediumPurple2     Color = api.MediumPurple2
	DarkGoldenrod     Color = api.DarkGoldenrod
	LightSalmon3      Color = api.LightSalmon3
	RosyBrown         Color = api.RosyBrown
	Grey63            Color = api.Grey63
	MediumPurple2_2   Color = api.MediumPurple2_2
	MediumPurple1     Color = api.MediumPurple1
	Gold3             Color = api.Gold3
	DarkKhaki         Color = api.DarkKhaki
	NavajoWhite3      Color = api.NavajoWhite3
	Grey69            Color = api.Grey69
	LightSteelBlue3   Color = api.LightSteelBlue3
	LightSteelBlue    Color = api.LightSteelBlue
	Yellow3           Color = api.Yellow3
	DarkOliveGreen3_3 Color = api.DarkOliveGreen3_3
	DarkSeaGreen3_2   Color = api.DarkSeaGreen3_2
	DarkSeaGreen2     Color = api.DarkSeaGreen2
	LightCyan3        Color = api.LightCyan3
	LightSkyBlue1     Color = api.LightSkyBlue1
	GreenYellow       Color = api.GreenYellow
	DarkOliveGreen2   Color = api.DarkOliveGreen2
	PaleGreen1_2      Color = api.PaleGreen1_2
	DarkSeaGreen2_2   Color = api.DarkSeaGreen2_2
	DarkSeaGreen1     Color = api.DarkSeaGreen1
	PaleTurquoise1    Color = api.PaleTurquoise1
	Red3_2            Color = api.Red3_2
	DeepPink3         Color = api.DeepPink3
	DeepPink3_2       Color = api.DeepPink3_2
	Magenta3_2        Color = api.Magenta3_2
	Magenta3_3        Color = api.Magenta3_3
	Magenta2          Color = api.Magenta2
	DarkOrange3_2     Color = api.DarkOrange3_2
	IndianRed_2       Color = api.IndianRed_2
	HotPink3_2        Color = api.HotPink3_2
	HotPink2          Color = api.HotPink2
	Orchid            Color = api.Orchid
	MediumOrchid1     Color = api.MediumOrchid1
	Orange3           Color = api.Orange3
	LightSalmon3_2    Color = api.LightSalmon3_2
	LightPink3        Color = api.LightPink3
	Pink3             Color = api.Pink3
	Plum3             Color = api.Plum3
	Violet            Color = api.Violet
	Gold3_2           Color = api.Gold3_2
	LightGoldenrod3   Color = api.LightGoldenrod3
	Tan               Color = api.Tan
	MistyRose3        Color = api.MistyRose3
	Thistle3          Color = api.Thistle3
	Plum2             Color = api.Plum2
	Yellow3_2         Color = api.Yellow3_2
	Khaki3            Color = api.Khaki3
	LightGoldenrod2   Color = api.LightGoldenrod2
	LightYellow3      Color = api.LightYellow3
	Grey84            Color = api.Grey84
	LightSteelBlue1   Color = api.LightSteelBlue1
	Yellow2           Color = api.Yellow2
	DarkOliveGreen1   Color = api.DarkOliveGreen1
	DarkOliveGreen1_2 Color = api.DarkOliveGreen1_2
	DarkSeaGreen1_2   Color = api.DarkSeaGreen1_2
	Honeydew2         Color = api.Honeydew2
	LightCyan1        Color = api.LightCyan1
	Red1              Color = api.Red1
	DeepPink2         Color = api.DeepPink2
	DeepPink1         Color = api.DeepPink1
	DeepPink1_2       Color = api.DeepPink1_2
	Magenta2_2        Color = api.Magenta2_2
	Magenta1          Color = api.Magenta1
	OrangeRed1        Color = api.OrangeRed1
	IndianRed1        Color = api.IndianRed1
	IndianRed1_2      Color = api.IndianRed1_2
	HotPink           Color = api.HotPink
	HotPink_2         Color = api.HotPink_2
	MediumOrchid1_2   Color = api.MediumOrchid1_2
	DarkOrange        Color = api.DarkOrange
	Salmon1           Color = api.Salmon1
	LightCoral        Color = api.LightCoral
	PaleVioletRed1    Color = api.PaleVioletRed1
	Orchid2           Color = api.Orchid2
	Orchid1           Color = api.Orchid1
	Orange1           Color = api.Orange1
	SandyBrown        Color = api.SandyBrown
	LightSalmon1      Color = api.LightSalmon1
	LightPink1        Color = api.LightPink1
	Pink1             Color = api.Pink1
	Plum1             Color = api.Plum1
	Gold1             Color = api.Gold1
	LightGoldenrod2_2 Color = api.LightGoldenrod2_2
	LightGoldenrod2_3 Color = api.LightGoldenrod2_3
	NavajoWhite1      Color = api.NavajoWhite1
	MistyRose1        Color = api.MistyRose1
	Thistle1          Color = api.Thistle1
	Yellow1           Color = api.Yellow1
	LightGoldenrod1   Color = api.LightGoldenrod1
	Khaki1            Color = api.Khaki1
	Wheat1            Color = api.Wheat1
	Cornsilk1         Color = api.Cornsilk1
	Grey100           Color = api.Grey100
	Grey3             Color = api.Grey3
	Grey7             Color = api.Grey7
	Grey11            Color = api.Grey11
	Grey15            Color = api.Grey15
	Grey19            Color = api.Grey19
	Grey23            Color = api.Grey23
	Grey27            Color = api.Grey27
	Grey30            Color = api.Grey30
	Grey35            Color = api.Grey35
	Grey39            Color = api.Grey39
	Grey42            Color = api.Grey42
	Grey46            Color = api.Grey46
	Grey50            Color = api.Grey50
	Grey54            Color = api.Grey54
	Grey58            Color = api.Grey58
	Grey62            Color = api.Grey62
	Grey66            Color = api.Grey66
	Grey70            Color = api.Grey70
	Grey74            Color = api.Grey74
	Grey78            Color = api.Grey78
	Grey82            Color = api.Grey82
	Grey85            Color = api.Grey85
	Grey89            Color = api.Grey89
	Grey93            Color = api.Grey93

	DefaultColor Color = api.DefaultColor
)

type Component

type Component struct {

	// FF provides access and fine grained control over a components
	// default behavior.
	FF *Features

	// Register provides the api to register keys and runes listeners
	// for a component.  See Keyer and Runer for a more general way of
	// keyboard listening.
	Register *Listeners

	// Edit provides a component's API to control editing its content.
	Edit *Editor
	// contains filtered or unexported fields
}

Component enables a user implemented UI-component to be processed by lines, i.e. all user UI-components which are provided to lines must embed this type. NOTE accessing features of an embedded Component is only supported during an event reporting callback to embedding component c:

func (c *cmp) OnInit(_ *lines.Env) {
    go func() {
        time.Sleep(1*time.Second)
        c.Dim().SetHeight(5) // will panic
    }
    c.Dim().SetHeight(5) // will not panic
}

Note that there are three rectangles on the screen associated with component:

c.Dim().Rect() // the component's "screen area" including margins
c.Dim().Area() // the "printable area", i.e. without margins
c.ContentArea() // the "content area", i.e. without margins and gaps

Next to embedding the Component type a client component will usually also implement event listener interfaces to receive events like:

  • Initer is informed once before a component becomes part of the layout
  • AfterIniter is informed once after all components are initialize before the layout is calculated
  • Layouter is informed that a component's layout was calculated
  • Focuser/FocusLooser is informed about focus gain/loss
  • Keyer is informed about any user special key-press like 'enter' or 'tab'
  • Runer is informed about user rune-key input
  • Mouser is informed about any mouse event see also Clicker/Contexter
  • LineSelecter is informed if a component's line was selected
  • LineFocuser is informed if a component's line received the focus

func (Component) AA

func (c Component) AA(aa StyleAttributeMask) *component

AA replaces a component's style attributes like bold or dimmed. Note changing the style attributes of the default style of the Lines' globals will have no effect on components whose style attributes has been set.

func (Component) BG

func (c Component) BG(color Color) *component

BG replaces a component's background color. Note changing the background color of the default style of the Lines' globals will have no effect on components whose background color has been set.

func (Component) ContentArea

func (c Component) ContentArea() (x, y, w, h int)

func (Component) ContentScreenLines added in v0.9.1

func (c Component) ContentScreenLines() int

ContentScreenLines returns a component c's number of screen lines which are not used for gaps.

func (*Component) CursorPosition added in v0.9.1

func (c *Component) CursorPosition() (line, column int, _ bool)

CursorPosition returns relative to given component c's content origin the line and column index of the cursor in the content area and true if c has the cursor set; otherwise -1, -1 and false is return.

func (Component) Dim

func (c Component) Dim() *lyt.Dim

Dim provides a components layout dimensions and features to adapt them.

func (Component) FG

func (c Component) FG(color Color) *component

FG replaces a component's foreground color. Note changing the foreground color of the default style of the Lines' globals will have no effect on components whose foreground color has been set.

func (Component) First added in v0.10.0

func (c Component) First() int

First returns the content index of the content displayed in the components first screen line.

func (*Component) Gaps

func (c *Component) Gaps(level int) *GapsWriter

Gaps returns a gaps writer at given leven allowing to do framing, padding or guttering around a component's content:

fmt.Fprint(c.Gaps(0).AA(Reverse).Filling(), "•")
fmt.Fprint(c.Gaps(0).Corners.AA(Reverse), "•")
c.Gaps(1).AA(Reverse)
c.Gaps(1).Corners.AA(Reverse)

func (Component) GapsLen added in v0.9.1

func (c Component) GapsLen() (top, right, bottom, left int)

GapsLen returns the numbers of lines/columns a gap at the top, right, bottom and left consumes. Note a gap must have been written in order to be created. I.e. if gaps are written at OnLayout and gaps-lengths are queried in OnAfterInit then these lengths might not be what is expected.

func (*Component) Globals

func (c *Component) Globals() *Globals

Globals provides access to the API for manipulating component c specific globally inherited properties like tab-width. Note to change such a property globally use the Lines-instance ll which layouts c. ll's Globals-property provides the same Api but propagates manipulations to all components of the layout.

func (Component) InContentArea added in v0.10.0

func (c Component) InContentArea(x, y int) bool

func (Component) IsDirty

func (c Component) IsDirty() bool

IsDirty is true if given component c is flagged dirty or one of its lines or gaps.

func (*Component) Layered added in v0.9.0

func (c *Component) Layered(e *Env, l Componenter, pos *LayerPos)

Layered associates given component c with given layering component l while l will be layed out according to given layer positioning pos.

func (Component) Len

func (c Component) Len() int

Len returns the number of lines currently maintained by a component either through its own set of lines or through a source's Liner set of lines. Note the number of component lines is independent of a component's available screen lines.

func (*Component) RemoveLayer added in v0.9.0

func (c *Component) RemoveLayer(e *Env)

RemoveLayer removes given component c's association with a layering component which is removed from the layout.

func (Component) Reset

func (c Component) Reset(idx int, ff ...LineFlags)

Reset blanks out the content of the line (or all lines) with given index the next time it is printed to the screen. Provide line flags if for example a Reset line should not be focusable:

c.Reset(lines.All, lines.NotFocusable)

If provided lines index is -1, see All-constant, Reset scrolls to the top, truncates its lines to the available screen-lines and resets the remaining lines.

func (*Component) SetCursor added in v0.9.1

func (c *Component) SetCursor(
	line, column int, cs ...CursorStyle,
) *Component

SetCursor of given component c to given line and column with optionally given cursor style within c's content area. I.e. line=0, column=0 refers to the first column in the first content-line while gaps and margins are ignored. Note setting the cursor is only effective after the first layout. SetCursor is a no-op for stacker and chainer. Lines.SetCursor allows for absolute cursor positioning whereas there the cursor is set to (x,y) coordinates, i.e. it has switched argument order compared to (line,column).

func (Component) SetDirty

func (c Component) SetDirty()

SetDirty flags a component as dirty having the effect that at the next syncing the component's screen area is cleared before it is written to. Note usually you don't need this method since a component is automatically flagged dirty if its layout changed, if one of its global properties changed etc.

func (Component) Sty

func (c Component) Sty(s Style) *component

Sty replaces a component's style, i.e. its style attributes and its fore- and background color. Note changing the default style of the Lines' globals will have no effect on components whose style has been set.

type ComponentLines

type ComponentLines struct {
	Focus *LineFocus
	// contains filtered or unexported fields
}

ComponentLines provides the API to manipulate ui-aspects of a component's lines like which line has the focus. A component's lines are accessed through its LL-property. To manipulate their content print to an Env(ironment) instance provided to an event listener implementation.

func (*ComponentLines) AA

func (cll *ComponentLines) AA(aa StyleAttributeMask)

AA set the style attributes of all content lines of associated component to given style attributes aa.

func (*ComponentLines) BG

func (cll *ComponentLines) BG(c Color)

BG set the background color of all content lines of associated component to given color c.

func (*ComponentLines) By

func (cll *ComponentLines) By(idx int) *Line

By returns the component line with given non negative index idx. By panics if idx is negative. Is idx < ComponentLines.Len lines are padded accordingly.

func (*ComponentLines) FG

func (cll *ComponentLines) FG(c Color)

FG set the foreground color of all content lines of associated component to given color c.

func (*ComponentLines) Len

func (cll *ComponentLines) Len() int

Len returns the number of component lines, which is independent from the number of screen lines.

func (*ComponentLines) Mod

func (cll *ComponentLines) Mod(cm ComponentMode)

Mod sets how given component lines cll are maintained.

type ComponentMode

type ComponentMode uint
const (

	// Overwriting a components content by an write operation.
	Overwriting ComponentMode = 1 << iota

	// Appending to a components content by an write operation.
	Appending

	// Tailing is appending and displaying the contents "tail"
	// especially if the display area cannot show all the content.
	Tailing
)

type Componenter

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

Componenter is the private interface a type must implement to be used as an lines ui component. Embedding lines.Component in a type automatically fulfills this condition:

type MyCmp struct { lines.Component }
lines.Term(&MyCmp{}).WaitForQuit()

a Componenter implementation is informed about application events if it also implements event listener interfaces like

  • Initer is informed once before a component becomes part of the layout
  • Layouter is informed that a component's layout was calculated
  • Focuser/FocusLooser is informed about focus gain/loss
  • Keyer is informed about any user special key-press like 'enter' or 'tab'
  • Runer is informed about user rune-key input
  • Mouser is informed about any mouse event see also Clicker/Contexter
  • LineSelecter is informed if a component's line was selected
  • LineFocuser is informed if a component's line received the focus

type ContentSource

type ContentSource struct {

	// Liner provides a components content
	Liner
	// contains filtered or unexported fields
}

A ContentSource instance may be assigned to a Component's Src property whose Liner is then used by the Component to print its content. E.g. if MyLiner is a Liner implementation and c a Component:

c.Src = &lines.ContentSource{Liner: &MyLiner{}}

now c uses provided Liner instance to print its content. NOTE according to a ContentSource's Liner implementation the setting of corresponding features is triggered. E.g. is a Liner implementation a ScrollableLiner the component has the feature Scrollable set.

func (*ContentSource) IsDirty

func (cs *ContentSource) IsDirty() bool

IsDirty returns true if an initial content write from set Liner to associated component has happened; false otherwise.

type Contexter

type Contexter interface {

	// OnContext implementation of a component c gets "right click"
	// events reported which is an aggregated mouse event.  I.e. Mouser
	// implementer will not receive a "right click" event.  x and y
	// provide the click coordinates translated into the "content area"
	// (c.ContentArea) of c.  This event bubbles; use e.StopBubbling()
	// to suppress further bubbling.  Note e.Evt.(*lines.MouseClick).Mod
	// provides also the modifiers information.
	OnContext(e *Env, x, y int)
}

Contexter is implemented by components which want to be informed about a mouse "right click" event in their content area. If the clicked component, i.e. the component with the smallest layout area containing the event coordinates, does not have the focus an OnFocus event is reported first if and only if the clicked component has the Focusable feature. See Mouser event interface for a more general mouse event handling.

TODO: implement: see if event can also be reported for a potential context-menu key press (having x/y set to -1 then?).

type CursorStyle added in v0.9.1

type CursorStyle = api.CursorStyle

type Cursorer added in v0.9.1

type Cursorer interface {

	// OnCursor implemented by a component c is called by Lines if the
	// cursor position has changed; use c.CursorPosition() to retrieve
	// the current cursor position.  Note if the display resizes Lines
	// either removes the cursor iff it is not in the content area of a
	// component; otherwise it keeps the cursor in c's content area
	// trying to keep it relative to the content areas origin at the
	// same position.  If the later can be achieved absOnly is true.
	OnCursor(_ *Env, absOnly bool)
}

Cursorer is implemented by a component which wants to be notified about cursor movement.

type DD added in v0.10.0

type DD func(Componenter) Dimensions

DD is a function which extracts layout information from a component without the need of being inside one of the components event-callbacks.

type Dimensions added in v0.10.0

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

func (Dimensions) Height added in v0.10.0

func (dd Dimensions) Height() int

Height of component without margins.

func (Dimensions) Printable added in v0.10.0

func (dd Dimensions) Printable() (x, y, width, height int)

Printable returns the screen area of a component it can print to i.e. its area without margins and without clippings.

func (Dimensions) Screen added in v0.10.0

func (dd Dimensions) Screen() (x, y, width, height int)

Screen returns the screen area of a component i.e. its area without clippings (including margins).

func (Dimensions) Width added in v0.10.0

func (dd Dimensions) Width() int

Width of component without margins.

type Dimer

type Dimer = lyt.Dimer

Dimer provides dimensions of a component in the layout. Note each type embedding lines.Component implements the Dimer interface.

type Drager added in v0.9.0

type Drager interface {

	// OnDrag implementation of a component c gets move movement
	// reported while a button is pressed.  Given environment provides
	// the origin of a drag e.Evt(*lines.MouseDrag).Origin().  Reported
	// coordinates are absolute coordinates.
	OnDrag(e *Env, _ ButtonMask, x, y int)
}

Drager is implemented by a component which wants to be informed about mouse movement while a button is pressed. NOTE reported coordinates are absolute coordinates.

type Dropper added in v0.9.0

type Dropper interface {

	// OnDrop implementation of a component c gets reported the absolute
	// position where a sequence of mouse movements ended while given
	// button was pressed.
	OnDrop(_ *Env, _ ButtonMask, x, y int)
}

Dropper is implemented by a component which wants to be informed when a (sequence of) drags ends.

type Edit added in v0.9.1

type Edit struct {
	Line int
	Cell int
	Type EditType
	Rune rune
}

type EditLiner added in v0.9.1

type EditLiner interface {
	FocusableLiner

	// OnEdit implementation gets edit requests of a component's screen
	// cell reported and returns true iff the edit request should be
	// carried out.  Given line writer allows to print to edited line
	// while given Edit-instance provides the information about the
	// edit.
	OnEdit(w *EnvLineWriter, e *Edit) bool
}

EditLiner implementations are FocusableLiner implementations turning the editable feature of associated component on.

type EditType added in v0.9.1

type EditType int
const (
	Ins EditType = iota
	Rpl
	Del
	JoinNext
	JoinPrev
)

type Editer added in v0.9.1

type Editer interface {

	// OnEdit is called right before a user requested edit of a
	// component's cell content is applied.  In case OnEdit returns
	// false the following application of the edit request is omitted.
	// Provided Edit instance holds the information about the requested
	// edit.
	OnEdit(*Env, *Edit) bool
}

Editer implementations are informed about user edits of a components content having the option to suppress the edit.

type Editor added in v0.9.1

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

An Editor provides the client API to control a components editing behavior. The zero-type is NOT ready to use; an Editor instance for a component c's Edit-property is automatically created iff c gets the Editable (or HighlightedEditable) feature set. The later may happen in two ways: Either using c's FF-property to Add the feature explicitly or by setting c's Src property with a ContentSource having a Liner implementing the EditLiner interface.

func (*Editor) IsActive added in v0.9.1

func (e *Editor) IsActive() bool

IsActive returns false if given Editor e is nil or suspended; otherwise true is returned.

func (*Editor) IsReplacing added in v0.9.1

func (e *Editor) IsReplacing() bool

func (*Editor) MapEvent added in v0.9.1

func (e *Editor) MapEvent(evt KeyEventer) *Edit

func (*Editor) Replacing added in v0.9.1

func (e *Editor) Replacing()

func (*Editor) Resume added in v0.9.1

func (e *Editor) Resume()

Resume reactivates a components (non nil) Editor e.

func (*Editor) Suspend added in v0.9.1

func (e *Editor) Suspend()

Suspend deactivates a components (non nil) Editor e.

type Enterer added in v0.9.0

type Enterer interface {

	// OnEnter implementation of a component c gets the first mouse move
	// inside c's printable area reported.
	OnEnter(e *Env, x, y int)
}

Enterer is implemented by components which want to be informed if the mouse pointer enters their printable area.

type Env

type Env struct {

	// Lines is the Lines instance providing given environment
	// instance.  Use it to post Update or Focus events.
	Lines *Lines

	// Evt is the event which triggered the creation of the environment
	// instance.  NOTE with Evt.Source() a backend event may be accessed.
	Evt Eventer
	// contains filtered or unexported fields
}

Env is an environment provided to event listeners when their event is reported. An Env instance implements the io.Writer interface and is associated with a portion of the screen it writes to. Writing to an Env instance after the event listener has returned will panic, e.g.

func (c *MyUIComponent) myListener(e *lines.Env) {
    go func() {
        time.Sleep(1*time.Second)
        fmt.Fprint(e, "awoken") // will panic
    }()
}

func (c *MyUIComponent) myListener(e *lines.Env) {
    go func(ll *lines.Lines) {
        time.Sleep(1*time.Second)
        ll.UpdateComponent(c, nil, func(e *lines.Env) {
             fmt.Fprint(e, "awoken") // will not panic
        })
    }(e.Lines)
}

An Env e instance also informs about the triggering backend event see Evt-property which may be nil. Last but not least an Env instance provides features to communicate back to the reporting Lines instance, e.g. Env.StopBubbling:

func (c *MyUIComponent) Runes(e *lines.Env, r rune) {
    fmt.Fprintf(
        e, "received rune: '%c' of event %T",
        r, e.Env.Source(),
    )
    // the event stops bubbling through enclosing components
    e.StopBubbling()
}

func (*Env) AA

func (e *Env) AA(aa StyleAttributeMask) *EnvWriter

AA sets the next write's style attributes like Bold.

func (*Env) BG

func (e *Env) BG(color Color) *EnvWriter

BG sets the next write's background color.

func (*Env) FG

func (e *Env) FG(color Color) *EnvWriter

FG sets the next write's foreground color.

func (*Env) Focused

func (e *Env) Focused() Componenter

Focused returns the currently focused component. Please remember to ask your Lines-instance (e.Lines) for an update event of the focused component if you want it to be changed.

func (*Env) LL

func (e *Env) LL(idx int) *EnvLineWriter

LL returns a writer which writes to the line and its following lines at given index.

func (*Env) ScreenSize

func (e *Env) ScreenSize() (width, height int)

ScreenSize provides the currently total screen size. Use Component.Dim to get layout information about the environment receiving component.

func (*Env) StopBubbling

func (e *Env) StopBubbling()

StopBubbling prevents any further reporting of an mouse or key event after the listener calling StopBubbling returns.

func (*Env) Sty

func (e *Env) Sty(s Style) *EnvWriter

Sty sets the next lines write's style, i.e. its style attributes and fore- and background color.

func (*Env) Write

func (e *Env) Write(bb []byte) (int, error)

Write given bytes bb to the screen area of the component whose event handler was called with given environment e. For that purpose given bytes a broken into screen lines at new-lines and optionally set style-attributes as well as fore- and background colors are passed as default style to these lines. NOTE all previous content of the component is removed.

type EnvAtWriter

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

An EnvAtWriter writes to a selected line at a selected cell and allows to set style information for this write.

func (*EnvAtWriter) AA

AA sets the next write's style attributes like Bold.

func (*EnvAtWriter) BG

func (w *EnvAtWriter) BG(color Color) *EnvAtWriter

BG sets the next write's foreground color.

func (*EnvAtWriter) FG

func (w *EnvAtWriter) FG(color Color) *EnvAtWriter

FG sets the next write's foreground color.

func (*EnvAtWriter) Filling

func (w *EnvAtWriter) Filling() *envAtFillingWriter

Filling returns a filling writer which adds first printed rune to provided line-index at provided cell as a filling rune.

func (*EnvAtWriter) Sty

func (w *EnvAtWriter) Sty(s Style) *EnvAtWriter

Sty sets the next write's style, i.e. its style attributes and colors.

func (*EnvAtWriter) WriteAt

func (w *EnvAtWriter) WriteAt(rr []rune)

WriteAt writes given runes rr to selected line and cell indices with optionally set style information. If there is style information it will be only applied for given rune sequence rr.

type EnvLineWriter

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

An EnvLineWriter provides an API for styling and formatting the writing to a selected and its following component-lines.

func (*EnvLineWriter) AA

AA sets the next write's style attributes like Bold.

func (*EnvLineWriter) At

func (w *EnvLineWriter) At(cell int) *EnvAtWriter

At returns a writer which writes at given line writer w's line at given cell. Note you need to use the lines.Print-function to print to an at-writer and can only provide a rune or a rune-slice. Styles of an at-writer are only applied for the printed range of runes.

func (*EnvLineWriter) BG

func (w *EnvLineWriter) BG(color Color) *EnvLineWriter

BG sets the next write's foreground color.

func (*EnvLineWriter) FG

func (w *EnvLineWriter) FG(color Color) *EnvLineWriter

FG sets the next write's foreground color.

func (*EnvLineWriter) Sty

func (w *EnvLineWriter) Sty(s Style) *EnvLineWriter

Sty sets the next write's style, i.e. its style attributes and colors.

func (*EnvLineWriter) Write

func (w *EnvLineWriter) Write(bb []byte) (int, error)

Write given bytes bb to a selected line and its following by splitting bb in screen lines at new lines. Optionally set style attributes or fore- and background colors are applied for these lines.

type EnvWriter

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

An EnvWriter instance provides an API for styling and formatting the writing to a component's line(s) starting at its first line.

func (*EnvWriter) AA

AA sets the next write's style attributes like Bold.

func (*EnvWriter) BG

func (w *EnvWriter) BG(color Color) *EnvWriter

BG sets the next write's foreground color.

func (*EnvWriter) FG

func (w *EnvWriter) FG(color Color) *EnvWriter

FG sets the next write's foreground color.

func (*EnvWriter) LL

func (w *EnvWriter) LL(idx int) *EnvLineWriter

LL returns a writer which writes to the line and its following lines at given index idx.

func (*EnvWriter) Sty

func (w *EnvWriter) Sty(s Style) *EnvWriter

Sty sets the next write's style, i.e. its style attributes and colors.

func (*EnvWriter) Write

func (w *EnvWriter) Write(bb []byte) (int, error)

Write to a components screen-portion made available by an Env instance provided to a listener implementation.

type Eventer

type Eventer = api.Eventer

Eventer is the interface which all reported events implement. Note each Env instance has an Env.Evt property of type Eventer whereas Env.Evt.Source() provides the backend event if there is any. The following event interfaces with their reported event are defined:

type Exiter added in v0.9.0

type Exiter interface {

	// OnExit implementation of a component c gets the first mouse move
	// outside c's printable area reported.
	OnExit(e *Env)
}

Exiter is implemented by components which want to be informed if the mouse pointer exits their printable area.

type FeatureButton

type FeatureButton struct {
	Mod    ModifierMask
	Button ButtonMask
}

FeatureButton represents a button with its modifier and button value which is typically bound to a feature using Features.SetButtonsOf.

type FeatureButtons

type FeatureButtons []FeatureButton

FeatureButtons are reported by Features.ButtonsOf providing the mouse buttons bound to a given feature. FeatureButtons may be also used as variadic argument of Features.SetButtonsOf to bind several FeatureButton to the same feature.

func (FeatureButtons) Equals

func (fb FeatureButtons) Equals(other FeatureButtons) bool

Equals returns true if given feature buttons fb and given other feature buttons contain the same feature buttons.

type FeatureKey

type FeatureKey struct {
	Mod ModifierMask
	Key Key
}

FeatureKey represents a key with its modifier and key value which is typically bound to a feature using Features.SetKeysOf.

type FeatureKeys

type FeatureKeys []FeatureKey

FeatureKeys are reported by Features.KeysOf providing the keys bound to a given feature. FeatureKeys may be also used as variadic argument for Features.SetKeysOf to bind several FeatureKey to the same feature.

func (FeatureKeys) Equals

func (fk FeatureKeys) Equals(other FeatureKeys) bool

Equals returns true iff given feature keys fk and given other feature keys contain the same FeatureKey values.

type FeatureMask

type FeatureMask uint64

FeatureMask classifies keys/runes/buttons for a components default behavior like focusable, scrollable etc.

const (

	// Focusable enables a component to be focused by a user's mouse
	// input (default first(left)-button, second(right)-button and
	// third(middle)-button, ModMask == ModeNone).
	Focusable FeatureMask = 1 << iota

	// FocusMoveable enables to move focus between FocusMovable
	// components using the default Tab-key.
	FocusMovable

	// UpScrollable makes a component's content up-scrollable by the
	// user (default page-up-key).
	UpScrollable

	// DownScrollable makes a component's content down-scrollable by the
	// user (default page-down-key).
	DownScrollable

	// nextLineFocusable a component's previous focusable line can
	// receive the focus. (default down-key)
	PreviousLineFocusable

	// NextLineFocusable a component's next focusable line can receive
	// the focus. (default up-key)
	NextLineFocusable

	// LineUnfocusable a component's set line-focus can be removed
	// (default Esc)
	LineUnfocusable

	// HighlightEnabled if set will highlight a component c's
	// focused screen line using c.Globals().Style(Highlight).  (NOTE
	// use c.Globals() to modify the Highlight style)
	HighlightEnabled

	// TrimmedHighlightEnabled if set will highlight a component
	// c's focused screen line whereas the highlight is only applied to
	// content without prefixing or suffixing whitespace using
	// c.Globals().Style(Highlight).  (NOTE use c.Globals() to modify
	// the Highlight style)
	TrimmedHighlightEnabled

	// LineSelectable a component's focused line can be reported as
	// selected (default Enter)
	LineSelectable

	// FirstCellFocusable shows/moves the cursor at the beginning of a
	// focused screen line's content in the line's first cell (default
	// Home).
	FirstCellFocusable

	// PreviousCellFocusable shows the cursor in a components focused
	// line while the left arrow key moves the cursor to ("focuses") the
	// previous rune.
	PreviousCellFocusable

	// LastCellFocusable shows/moves the cursor at the end of a screen
	// line's content in the line's last cell (default End).
	LastCellFocusable

	// NextCellFocusable shows the cursor in a components focused
	// line while the right arrow key moves the cursor to ("focuses") the
	// next cell.
	NextCellFocusable

	// NoFeature classifies keys/runes/buttons not registered for any
	// feature.
	NoFeature FeatureMask = 0

	// Scrollable makes a component's content vertically Scrollable by
	// combining up- and down-Scrollable.
	Scrollable = UpScrollable | DownScrollable

	// LinesFocusable makes lines focusable, i.e. a line receiving the
	// focus is reported; see OnLineFocus.
	LinesFocusable = NextLineFocusable | PreviousLineFocusable |
		LineUnfocusable

	// LinesSelectable makes a component's lines selectable by combining
	// LinesFocusable and LineSelectable.
	LinesSelectable = LinesFocusable | LineSelectable

	// CellFocusable turns on LinesFocusable for a component c and shows
	// the cursor whose positioning indicates the "focused cell".
	CellFocusable = PreviousCellFocusable | NextCellFocusable |
		LinesFocusable | LastCellFocusable | FirstCellFocusable

	Editable = Focusable | CellFocusable | Scrollable | editable
)

type FeatureRune

type FeatureRune struct {
	Rune rune
	Mod  ModifierMask
}

FeatureRune represents a rune with its modifier and rune value which is typically bound to a feature using Features.SetRunesOf.

type FeatureRunes

type FeatureRunes []FeatureRune

FeatureRunes are reported by Features.RunesOf providing the runes bound to a given feature. FeatureRunes may be also used as variadic argument of Features.SetRunesOf to bind several FeatureRune to the same feature.

func (FeatureRunes) Equals

func (fr FeatureRunes) Equals(other FeatureRunes) bool

Equals returns true if given feature runes fr and given other feature runes contain the same feature runes.

type Features

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

Features provides access and fine grained control over the behavior of a component provided by lines. Its methods will panic used outside an event reporting listener-callback. Typically you will use a component's FF-property to manipulate a component's supported features, e.g.

type Cmp { lines.Component }

func (c *Cmp) OnInit(_ *lines.Env) {
	c.FF.Set(lines.LinesFocusable)
}

adds the feature "selectable lines" to a component. I.e. if the component has the focus up/down keys highlight selectable lines of the component while an enter-key-press reports an OnLineSelection of the currently highlighted line and an esc-key-press removes the line highlighting.

func (*Features) All

func (ff *Features) All() FeatureMask

All returns all features for which currently key, rune or button bindings are registered. (note Features.Has is faster to determine if a particular feature is set.)

func (*Features) ButtonsOf

func (ff *Features) ButtonsOf(f FeatureMask) FeatureButtons

ButtonsOf returns the buttons with their modifiers bound to given feature for associated component.

func (*Features) Delete

func (ff *Features) Delete(f FeatureMask)

Delete removes all runes, key or button bindings of given feature(s) except for Quitable. The two default Quitable bindings ctrl-c and ctrl-d remain. NOTE use a *Kiosk constructor like TermKiosk for a Lines-instance to avoid having Quitable set by default.

func (*Features) Has

func (ff *Features) Has(f FeatureMask) bool

Has returns true if receiving component features have key, rune or button bindings for given feature(s).

func (*Features) KeysOf

func (ff *Features) KeysOf(f FeatureMask) FeatureKeys

KeysOf returns the keys with their modifiers bound to given feature of associated component.

func (*Features) OfButton

func (ff *Features) OfButton(
	bb ButtonMask, mm ModifierMask,
) FeatureMask

OfButton returns the feature bound to given buttons b with given modifiers mm.

func (*Features) OfKey

func (ff *Features) OfKey(k Key, mm ModifierMask) FeatureMask

OfKey returns the feature bound to given key k with given modifiers mm.

func (*Features) OfRune

func (ff *Features) OfRune(r rune, mm ModifierMask) FeatureMask

OfRune returns the feature bound to given rune r with given modifiers mm.

func (*Features) RunesOf

func (ff *Features) RunesOf(f FeatureMask) FeatureRunes

RunesOf returns the runes bound to given feature for associated component.

func (*Features) Set added in v0.9.1

func (ff *Features) Set(f FeatureMask)

Set adds the default key, rune and button bindings of given feature(s) for associated component.

func (*Features) SetButtonsOf

func (ff *Features) SetButtonsOf(f FeatureMask, bb ...FeatureButton)

SetButtonsOf deletes all set buttons for given feature and binds given buttons to it instead. Set*Of may be used instead of Set to bind features initially to other Runes/Keys/Buttons than default. The call is ignored if given feature is not a power of two i.e. a single feature. Providing no button simply removes all button-bindings for given feature.

func (*Features) SetKeysOf

func (ff *Features) SetKeysOf(f FeatureMask, kk ...FeatureKey)

SetKeysOf deletes all set keys for given feature and binds given keys to it instead. Set*Of may be used instead of Set to bind features initially to other Runes/Keys/Buttons than default. The call is ignored if given feature is not a power of two i.e. a single feature. Providing no keys simply removes all key-bindings for given feature.

func (*Features) SetRunesOf

func (ff *Features) SetRunesOf(f FeatureMask, rr ...FeatureRune)

SetRunesOf deletes all set runes for given feature and binds given runes to it instead. Set*Of may be used instead of Set to bind features initially to other Runes/Keys/Buttons than default. The call is ignored if given feature is not a power of two i.e. a single feature. Providing no runes simply removes all runes-bindings for given feature.

type Fixture

type Fixture struct {

	// Lines instance created by the fixture constructor reporting
	// events to Componenter of the layout.
	Lines *Lines

	Scroll Scroll
	// contains filtered or unexported fields
}

Fixture augments the Lines instance created by a *Fixture constructor like TermFixture with useful features for testing like emulating user input or getting the current screen content.

Note The Lines.WaitForQuit method provided by a Fixture instance is non-blocking.

It is guaranteed that all methods of an Fixture's Lines-instances which trigger an event do not return before the event and all subsequently triggered events are processed and any writes to environments are printed to the screen.

func TermFixture

func TermFixture(
	t *testing.T,
	timeout time.Duration,
	c Componenter,
) *Fixture

TermFixture returns a Fixture instance with a slightly differently behaving Lines instance which has given component c as root and features useful for testing. Potentially occurring errors during the usage of a Fixture fatales given testing instance t.

The here created Lines instance has a non-blocking Lines.WaitForQuit method and all its methods triggering events are guaranteed to return after the event and subsequently triggered events have been processed and the (simulation) screen is synchronized. Or an event triggering method fatales t if given duration timeout has passed before all events have been processed.

Testing provides methods for firing user input events like Fixture.FireRune and retrieving the content of the screen and its stylings. Also user input emulating events do not return before they were processed along with subsequently triggered events and all prints to the screen have been synchronized within timeout.

func (*Fixture) CellsOf

func (fx *Fixture) CellsOf(c Componenter) api.CellsScreen

CellsOf provides a lines of cells representation of given component's printable screen-portion, i.e. without margins and clippings. A CellsScreen provides next to a string representation also style information for each screen coordinate. The returned CellsScreen is nil if given componenter is not part of the layout or off-screen. Note call CellsArea(c.Dim().Screen()) to get the screen area of a component including margins.

func (*Fixture) Dim added in v0.10.0

func (fx *Fixture) Dim(c Componenter) (d *lyt.Dim)

func (*Fixture) FireClick

func (fx *Fixture) FireClick(x, y int) *Fixture

FireClick posts a first (left) button click at given coordinates and returns after this event has been processed. Are given coordinates outside the printable screen area the call is ignored.

func (*Fixture) FireComponentClick

func (fx *Fixture) FireComponentClick(c Componenter, x, y int) *Fixture

FireComponentClick posts an first (left) button click on given relative coordinate in the printable area of given componenter. Note if x or y are outside the printable area of c or c is not part of the layout no click will be fired.

func (*Fixture) FireComponentContext

func (fx *Fixture) FireComponentContext(
	c Componenter, x, y int,
) *Fixture

FireComponentContext posts an second (right) button click on given relative coordinate in to printable area of given componenter c. Note if x or y are outside the printable area of c or c is not part of the layout no click will be fired.

func (*Fixture) FireContext

func (fx *Fixture) FireContext(x, y int) *Fixture

FireContext posts a secondary (right) button click at given coordinates and returns after this event has been processed. Are given coordinates outside the screen area the call is ignored.

func (*Fixture) FireDragNDrop added in v0.9.0

func (fx *Fixture) FireDragNDrop(
	x, y int, b ButtonMask, mm ModifierMask, xy ...int,
) *Fixture

func (*Fixture) FireKey

func (fx *Fixture) FireKey(k api.Key, m ...ModifierMask) *Fixture

FireKey posts given special-key event and returns after this event has been processed.

func (*Fixture) FireKeys added in v0.9.1

func (fx *Fixture) FireKeys(kk ...api.Key) *Fixture

FireKeys for given keys k_0,...,k_n in given fixture fx is a shortcut for

fx.FireKey(k_0, line.ZeroModifier)
// ...
fx.FireKey(k_n, line.ZeroModifier)

func (*Fixture) FireMouse

func (fx *Fixture) FireMouse(
	x, y int, bm api.ButtonMask, mm api.ModifierMask,
) *Fixture

FireMouse posts a mouse event with provided arguments and returns after this event has been processed. Are given coordinates outside the printable screen area the call is ignored.

func (*Fixture) FireMove added in v0.9.0

func (fx *Fixture) FireMove(x, y int, xy ...int) *Fixture

FireMove posts a mouse move to given coordinates; an other two given ints will be reported as the origin of the mouse move. Are any given coordinates outside the screen area the call is ignored.

func (*Fixture) FireResize

func (fx *Fixture) FireResize(width, height int) *Fixture

FireResize posts a resize event and returns after this event has been processed. NOTE this event as such is not reported but it triggers OnInit and OnLayout events of components which are not initialized or whose layout dimensions have changed.

func (*Fixture) FireRune

func (fx *Fixture) FireRune(r rune, m ...ModifierMask) *Fixture

FireRune posts given run-key-press event and returns after this event has been processed.

func (*Fixture) Root

func (fx *Fixture) Root() Componenter

Root returns the initially to the fixture constructor given component. It fatales the test if root is nil.

func (*Fixture) ScreenOf

func (fx *Fixture) ScreenOf(c Componenter) api.StringScreen

ScreenOf provides a string representation of given component's screen-area, i.e. without margins and without clippings. The returned StringScreen is nil if given componenter is not part of the layout or off-screen. Note call ScreenArea(c.Dim().Rect()) to get the ScreenArea of a component including layout margins.

type FocusLooser

type FocusLooser interface {

	// OnFocusLost is called back if an implementing component looses
	// the focus.
	OnFocusLost(*Env)
}

FocusLooser is implemented by components which want to be informed when they loose the focus. Note if a component c looses the focus to a component c' then all parents of c which are no parents of c' get also OnFocusLost reported, e.g.

+-App-----------------------------------------+
| +-chainer---------------------------------+ |
| | +-cmp1---------+ +-stacker------------+ | |
| | |              | | +-cmp2-----------+ | | |
| | |              | | |                | | | |
| | |              | | |                | | | |
| | |              | | +----------------+ | | |
| | +--------------+ +--------------------+ | |
| +-----------------------------------------+ |
+---------------------------------------------+

if cmp2 looses the focus to cmp1 then cmp2 and stacker get OnFocusLost reported (if implemented) while chainer and App which are parents of cmp1 and cmp2 don't.

type FocusableLiner

type FocusableLiner interface {
	ScrollableLiner

	// IsFocusable returns true iff the line with given index idx is
	// focusable.
	IsFocusable(idx int) bool
}

FocusableLiner implementations are ScrollableLiner implementations triggering the lines-focusable feature of associated component, i.e. a content source with a focusable liner makes its associated component automatically lines-focusable.

type Focuser

type Focuser interface {

	// OnFocus is called back if an implementing component receives the
	// focus.
	OnFocus(*Env)
}

Focuser is implemented by components which want to be notified when they gain the focus. Note if a component c has the focus and a component c' gets the focus then also all components which are parents of c' and are no parents of c get the focus, e.g.

+-App-----------------------------------------+
| +-chainer---------------------------------+ |
| | +-cmp1---------+ +-stacker------------+ | |
| | |              | | +-cmp2-----------+ | | |
| | |              | | |                | | | |
| | |              | | |                | | | |
| | |              | | +----------------+ | | |
| | +--------------+ +--------------------+ | |
| +-----------------------------------------+ |
+---------------------------------------------+

if cmp1 has the focus and cmp2 gets the focus then stacker and cmp2 get OnFocus reported (if implemented) while chainer and App which are parents of cmp1 and cmp2 don't.

type GapWriter added in v0.9.1

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

GapWriter lets a client print to a specific gap. A gap writer is obtained from a component c's gaps API, see Component.Gaps:

gw := c.Gaps(1).Top.FG(lines.LightGray).BG(lines.DarkGray)
fmt.Fprint(gw, "second gap-line of the top gap")

func (*GapWriter) AA added in v0.9.1

AA stets given style attributes aa for selected gap's next write at selected level.

func (*GapWriter) At added in v0.9.1

func (g *GapWriter) At(idx int) *gapAtWriter

At sets the column index idx for the next write of return gap-at-writer.

func (*GapWriter) BG added in v0.9.1

func (g *GapWriter) BG(c Color) *GapWriter

BG stets given color c as background color for selected gap's next write at selected level.

func (*GapWriter) FG added in v0.9.1

func (g *GapWriter) FG(c Color) *GapWriter

FG stets given color c as foreground color for selected gap's next write at selected level.

func (*GapWriter) Reset added in v0.10.0

func (w *GapWriter) Reset(sty Style)

func (*GapWriter) Sty added in v0.9.1

func (g *GapWriter) Sty(s Style) *GapWriter

Sty stets given style s for selected gap's next write at selected level, i.e. sets style attributes and colors.

func (*GapWriter) Write added in v0.9.1

func (w *GapWriter) Write(bb []byte) (int, error)

Write given bytes bb to the gaps given gap-writer w is associated with while ensuring set optional gap style information.

type GapsWriter

type GapsWriter struct {

	// Top writes to the top gap, i.e. first line of a component's
	// screen area (plus provided level).
	Top *GapWriter

	// Bottom writes to the bottom gap, i.e. last line of a component's
	// screen area (minus provided level).
	Bottom *GapWriter

	// Left writes to the left gap, i.e. first column of a component's
	// screen area (plus provided level).
	Left *GapWriter

	// Right writes to the right gap, i.e. last column of a component's
	// screen area (minus provided level).
	Right *GapWriter

	// Horizontal writes to bottom and top gap.
	Horizontal *GapWriter

	// Vertical writes to left and right gap.
	Vertical *GapWriter

	// TopLeft writes to the top left corner at selected level.
	TopLeft *cornerWriter

	// TopRight writes to the top right corner at selected level.
	TopRight *cornerWriter

	// BottomRight writes to the bottom right corner at selected level.
	BottomRight *cornerWriter

	// BottomLeft writes to the bottom left corner at selected level.
	BottomLeft *cornerWriter

	// Corners writes to all corners at selected level.
	Corners *cornerWriter
	// contains filtered or unexported fields
}

GapsWriter allows to get more specific gap writer to create gaps between contents of different components. Use Component.Gaps method of a component c to obtain a gaps writer for c.

func (*GapsWriter) AA

AA stets given style attributes aa for selected gap-level.

func (*GapsWriter) BG

func (ggw *GapsWriter) BG(c Color) *GapsWriter

BG sets given color c as background color for selected gap-level.

func (*GapsWriter) FG

func (ggw *GapsWriter) FG(c Color) *GapsWriter

FG sets given color c as foreground color for selected gap-level.

func (*GapsWriter) Filling

func (ggw *GapsWriter) Filling() *allGapsFiller

Filling returns a filling writer filling all gaps of selected level with what's printed to it. Note lines.Print is needed to print to a filling writer.

func (*GapsWriter) Sty

func (ggw *GapsWriter) Sty(s Style) *GapsWriter

Sty stets given style s as style for selected gap-level, i.e. sets style attributes and colors.

type Globals added in v0.10.0

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

Globals represents setup/behavior for a component's lines.

func (*Globals) AA added in v0.10.0

AA returns the style attributes mask of given style type st in given globals gg. If no style for st is found the default style's attributes are returned.

func (*Globals) BG added in v0.10.0

func (gg *Globals) BG(st StyleType) Color

BG returns the background color of given style type st in given globals gg. If no style for st is found the default style's background color is returned.

func (*Globals) FG added in v0.10.0

func (gg *Globals) FG(st StyleType) Color

FG returns the foreground color of given style type st in given globals gg. If no style for st is found the default style's foreground color is returned.

func (*Globals) Highlight added in v0.10.0

func (gg *Globals) Highlight(s Style) Style

func (*Globals) ScrollBarDef added in v0.10.0

func (gg *Globals) ScrollBarDef() ScrollBarDef

ScrollBarDef returns the default definition for a component's scroll bar.

func (*Globals) SetAA added in v0.10.0

func (gg *Globals) SetAA(st StyleType, aa StyleAttributeMask) *Globals

SetAA sets in given globals gg for given style type st given style attributes aa.

func (*Globals) SetBG added in v0.10.0

func (gg *Globals) SetBG(st StyleType, c Color) *Globals

SetBG sets in given globals gg for given style type st given color c as background color.

func (*Globals) SetFG added in v0.10.0

func (gg *Globals) SetFG(st StyleType, c Color) *Globals

SetFG sets in given globals gg for given style type st given color c as foreground color.

func (*Globals) SetHighlighter added in v0.10.0

func (gg *Globals) SetHighlighter(h func(Style) Style) *Globals

SetHighlighter sets the function which is used to highlight a focused line. It does so either globally with propagation or component local. In the later case further global Highlighter updates are ignored by that component.

func (*Globals) SetScrollBarDef added in v0.10.0

func (gg *Globals) SetScrollBarDef(sbd ScrollBarDef) *Globals

SetScrollBarDef sets the scrollbar definition either globally with propagation or component local. In the later case future global scrollbar definition updates are ignored by that component.

func (*Globals) SetStyle added in v0.10.0

func (gg *Globals) SetStyle(st StyleType, sty Style)

SetStyle sets in given globals gg for given style type st given style sty.

func (*Globals) SetTabWidth added in v0.10.0

func (gg *Globals) SetTabWidth(w int) *Globals

SetTabWidth sets given width w as tab-width globally with propagation or component local. In the later case future global tab-width updates are ignored by that component. SetTabWidth is an no-op if w not positive.

func (*Globals) SetUpdateListener added in v0.10.0

func (gg *Globals) SetUpdateListener(
	l func(globalsUpdates, StyleType, globalStyleUpdates),
) *Globals

SetUpdateListener stores given function which is called in case a globals property is updated informing about what was updated.

func (*Globals) Style added in v0.10.0

func (gg *Globals) Style(st StyleType) Style

Style returns set style in given globals gg for given style type st. If no style is set the DefaultStyle is returned.

func (*Globals) TabWidth added in v0.10.0

func (gg *Globals) TabWidth() int

TabWidth returns the currently set tab-width in given globals gg.

type Highlighter added in v0.10.0

type Highlighter interface {

	// Highlight implementation of a *Liner is set a Highlighter in the
	// globals of the component whose source has this liner.
	Highlight(Style) Style
}

Highlighter provides a highlighter which may be set to a components globals.

type Initer

type Initer interface {

	// OnInit is executed before a component's layout is calculated the
	// first time.  Main use case of this event is to create nested
	// components and print initial content to a component.  NOTE if
	// several instances of a component type which implements OnInit are
	// added then OnInit is reported to each of this components.
	//
	// If specific dimensions should be set before the first layout
	// Env.ScreenSize provides the screen size to help with that.  If
	// these dimensions depend on subsequently created components
	// OnAfterInit is probably the right event.  If the calculated
	// layout should be adapted OnLayout may be the better event to do
	// so because it is called after the layout manager did its work.
	OnInit(*Env)
}

Initer is implemented by components which want to be notified for initialization purposes before the first layout and before user input events are processed. Note implement AfterIniter to be notified after all components were initialized; implement Layouter to be notified after each layout calculation of a component.

type Key

type Key = api.Key

A Key is the pressed key of a key event.

const (
	NUL            Key = api.NUL
	SOH            Key = api.SOH
	STX            Key = api.STX
	ETX            Key = api.ETX
	EOT            Key = api.EOT
	ENQ            Key = api.ENQ
	ACK            Key = api.ACK
	BEL            Key = api.BEL
	BS             Key = api.BS
	TAB            Key = api.TAB
	LF             Key = api.LF
	VT             Key = api.VT
	FF             Key = api.FF
	CR             Key = api.CR
	SO             Key = api.SO
	SI             Key = api.SI
	DLE            Key = api.DLE
	DC1            Key = api.DC1
	DC2            Key = api.DC2
	DC3            Key = api.DC3
	DC4            Key = api.DC4
	NAK            Key = api.NAK
	SYN            Key = api.SYN
	ETB            Key = api.ETB
	CAN            Key = api.CAN
	EM             Key = api.EM
	SUB            Key = api.SUB
	ESC            Key = api.ESC
	FS             Key = api.FS
	GS             Key = api.GS
	RS             Key = api.RS
	US             Key = api.US
	DEL            Key = api.DEL
	Up             Key = api.Up
	Down           Key = api.Down
	Right          Key = api.Right
	Left           Key = api.Left
	UpLeft         Key = api.UpLeft
	UpRight        Key = api.UpRight
	DownLeft       Key = api.DownLeft
	DownRight      Key = api.DownRight
	Center         Key = api.Center
	PgUp           Key = api.PgUp
	PgDn           Key = api.PgDn
	Home           Key = api.Home
	End            Key = api.End
	Insert         Key = api.Insert
	Delete         Key = api.Delete
	Help           Key = api.Help
	Exit           Key = api.Exit
	Clear          Key = api.Clear
	Cancel         Key = api.Cancel
	PrintScr       Key = api.Print
	Pause          Key = api.Pause
	Backtab        Key = api.Backtab
	F1             Key = api.F1
	F2             Key = api.F2
	F3             Key = api.F3
	F4             Key = api.F4
	F5             Key = api.F5
	F6             Key = api.F6
	F7             Key = api.F7
	F8             Key = api.F8
	F9             Key = api.F9
	F10            Key = api.F10
	F11            Key = api.F11
	F12            Key = api.F12
	F13            Key = api.F13
	F14            Key = api.F14
	F15            Key = api.F15
	F16            Key = api.F16
	F17            Key = api.F17
	F18            Key = api.F18
	F19            Key = api.F19
	F20            Key = api.F20
	F21            Key = api.F21
	F22            Key = api.F22
	F23            Key = api.F23
	F24            Key = api.F24
	F25            Key = api.F25
	F26            Key = api.F26
	F27            Key = api.F27
	F28            Key = api.F28
	F29            Key = api.F29
	F30            Key = api.F30
	F31            Key = api.F31
	F32            Key = api.F32
	F33            Key = api.F33
	F34            Key = api.F34
	F35            Key = api.F35
	F36            Key = api.F36
	F37            Key = api.F37
	F38            Key = api.F38
	F39            Key = api.F39
	F40            Key = api.F40
	F41            Key = api.F41
	F42            Key = api.F42
	F43            Key = api.F43
	F44            Key = api.F44
	F45            Key = api.F45
	F46            Key = api.F46
	F47            Key = api.F47
	F48            Key = api.F48
	F49            Key = api.F49
	F50            Key = api.F50
	F51            Key = api.F51
	F52            Key = api.F52
	F53            Key = api.F53
	F54            Key = api.F54
	F55            Key = api.F55
	F56            Key = api.F56
	F57            Key = api.F57
	F58            Key = api.F58
	F59            Key = api.F59
	F60            Key = api.F60
	F61            Key = api.F61
	F62            Key = api.F62
	F63            Key = api.F63
	F64            Key = api.F64
	CtrlSpace      Key = api.CtrlSpace
	CtrlA          Key = api.CtrlA
	CtrlB          Key = api.CtrlB
	CtrlC          Key = api.CtrlC
	CtrlD          Key = api.CtrlD
	CtrlE          Key = api.CtrlE
	CtrlF          Key = api.CtrlF
	CtrlG          Key = api.CtrlG
	CtrlH          Key = api.CtrlH
	CtrlI          Key = api.CtrlI
	CtrlJ          Key = api.CtrlJ
	CtrlK          Key = api.CtrlK
	CtrlL          Key = api.CtrlL
	CtrlM          Key = api.CtrlM
	CtrlN          Key = api.CtrlN
	CtrlO          Key = api.CtrlO
	CtrlP          Key = api.CtrlP
	CtrlQ          Key = api.CtrlQ
	CtrlR          Key = api.CtrlR
	CtrlS          Key = api.CtrlS
	CtrlT          Key = api.CtrlT
	CtrlU          Key = api.CtrlU
	CtrlV          Key = api.CtrlV
	CtrlW          Key = api.CtrlW
	CtrlX          Key = api.CtrlX
	CtrlY          Key = api.CtrlY
	CtrlZ          Key = api.CtrlZ
	CtrlLeftSq     Key = api.CtrlLeftSq
	CtrlBackslash  Key = api.CtrlBackslash
	CtrlRightSq    Key = api.CtrlRightSq
	CtrlCarat      Key = api.CtrlCarat
	CtrlUnderscore Key = api.CtrlUnderscore
	Enter          Key = api.Enter
	Tab            Key = api.Tab
	Backspace      Key = api.Backspace
	Esc            Key = api.Esc
)

type KeyEventer

type KeyEventer = api.KeyEventer

A KeyEventer is implemented by a reported key-event. Key events may be received from a Componenter by implementing the Keyer interface. KeyEventer.Source() provides the backend event triggering the key event.

type Keyer

type Keyer interface {

	// OnKey is provided with every key-press and reported modifiers which
	// were pressed at the same time.
	OnKey(*Env, Key, ModifierMask)
}

Keyer is implemented by components who want to take over the user's key-input if they are focused. Note a Component's Register property allows to register handler for specific keys (see Listeners.Key).

type LayerPos added in v0.9.0

type LayerPos = lyt.LayerPos

LayerPos lets a user define the dimensions and alignment of an overlaying component.

type Layouter

type Layouter interface {

	// OnLayout is called after the layout manager has changed the
	// screen area of a component.
	OnLayout(*Env) (reflow bool)
}

Layouter is implemented by components which want to be notified if their layout has changed.

type Line

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

A Line structure stores a Line's flags, its content, style-information and line filler and provides methods to modify its flags and styles. A Component's Line instance is obtained through its LL property (see ComponentLines.By).

func (*Line) AddStyleRange

func (l *Line) AddStyleRange(sr SR, rr ...SR)

AddStyleRange adds given style ranges sr and rr to given line l's style ranges iff they don't overlap with already existing style ranges.

func (*Line) Flag

func (l *Line) Flag(ff LineFlags)

func (*Line) IsFlagged

func (l *Line) IsFlagged(ff LineFlags) bool

IsFlagged returns true if given line l has given flags ff set; false otherwise.

func (*Line) Len added in v0.9.1

func (l *Line) Len() int

func (*Line) String added in v0.10.0

func (l *Line) String() string

func (*Line) Switch

func (l *Line) Switch(ff LineFlags)

Switch turns given flag(s) on if they are not all set otherwise these flags are removed.

func (*Line) Unflag

func (l *Line) Unflag(ff LineFlags)

Unflag removes given flags ff from given line l.

type LineFlags

type LineFlags uint64

LineFlags control the behavior and layout of a displayed line.

const (

	// NotFocusable flagged line can not be focused
	NotFocusable LineFlags

	// Highlighted flagged line has additive the global highlight style applied
	Highlighted

	// TrimmedHighlighted flagged line has additive the global highlight
	// style applied except on leading and trailing spaces.
	TrimmedHighlighted

	// ZeroLineFlag is the LineFlags zero type
	ZeroLineFlag LineFlags = 0
)

type LineFocus

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

A LineFocus instance is associated with each initialized Component through its LL property (see ComponentLines) and provides the api for focusing component lines.

func (*LineFocus) AtCoordinate added in v0.10.0

func (s *LineFocus) AtCoordinate(y int)

AtCoordinate tries to focus the screen line with given coordinate y.

func (*LineFocus) Content added in v0.10.0

func (s *LineFocus) Content() int

Content returns the component's content line index in which the currently focused content is stored or -1 if no line is focused. (Note this line may not be on the screen if there is no component source and there are more content-lines than screen lines then the first line could be focused and the user scrolls down i.e. the currently focused line is not on the screen anymore)

func (*LineFocus) Current

func (s *LineFocus) Current() int

Current returns the index associated with the currently focused content from either associated component's content or the content from its content source liner.

func (*LineFocus) Eol added in v0.9.1

func (f *LineFocus) Eol() bool

Eol returns true iff the cursor is at the most right position of the current line's content.

func (*LineFocus) EolAfterLastRune added in v0.9.1

func (s *LineFocus) EolAfterLastRune() *LineFocus

EolAfterLastRune enables the cursor to go one rune over the last content rune of a line.

func (*LineFocus) EolAtLastRune added in v0.9.1

func (s *LineFocus) EolAtLastRune() *LineFocus

EolAtLastRune restricts a line's most right cursor position to the lines last content rune.

func (*LineFocus) FirstCell added in v0.9.1

func (s *LineFocus) FirstCell() (slIdx, cl int, moved bool)

FirstCell moves the cursor of the currently focused component line to its first screen column and its content to the right that the first content rune is in the first column.

func (*LineFocus) LastCell added in v0.9.1

func (s *LineFocus) LastCell() (slIdx, scIdx int, moved bool)

LastCell moves the cursor of currently focused component line to the right most non empty screen column and moves the content so far to the left in case of an overflowing line that the last content rune is in the component's last screen column. Last cell returns the currently focused line, the currently focused cell and if the cursor was moved.

func (*LineFocus) Line added in v0.10.0

func (f *LineFocus) Line() *Line

Line returns the component's content Line holding the content associated with the currently focused Line which may be from the component's content line or from a content source's Liner-content.

func (*LineFocus) Next

func (s *LineFocus) Next() (ln int, cl int)

Next focuses the next focusable line at the currently focused line's cursor position if possible and returns its index as well as the cell index which defaults to -1 if CellsFocusable feature is not set. If highlighted is true the highlight of the current line is removed while the next is highlighted.

func (*LineFocus) NextCell added in v0.9.1

func (s *LineFocus) NextCell() (slIdx, scIdx int, moved bool)

NextCell moves the cursor to the next cell in the currently focused line and returns the later's screen line index with the cell index of the cursor position and a boolean value indicating if the cursor was moved.

func (*LineFocus) Previous

func (s *LineFocus) Previous() (slIdx int, cl int)

Previous focuses the first focusable line previous to LineFocus.Current and returns its index along with the cursor position which defaults to -1 for an unset cursor. If highlighted is true the highlight of the current line is removed while the previous line is highlighted.

func (*LineFocus) PreviousCell added in v0.9.1

func (s *LineFocus) PreviousCell() (slIdx, cl int, moved bool)

PreviousCell moves a components cursor to the previous cell in the currently focused line if possible and returns the screen line index, cell index and a boolean indicating if the cursor was moved. Last cell returns the currently focused line, the currently focused cell and if the cursor was moved.

func (*LineFocus) Reset

func (s *LineFocus) Reset()

Reset removes a set line-focus switching of a potential highlight independent of given argument.

func (*LineFocus) Screen added in v0.9.1

func (s *LineFocus) Screen() int

Screen returns the screen line-index of the currently focused line or -1 if no line is focused or it is not on the screen.

type LineFocusLooser added in v0.9.1

type LineFocusLooser interface {

	// OnLineFocusLost is called by Lines if the line with given content
	// line index cIdx and given screen line index sIdx of implementing
	// component lost the focus.  Note "on line focus lost" is reported
	// after the focus change has happened, i.e. given screen line sIdx
	// not necessary displays the content line cIdx.  "on line focus
	// lost" is reported before "on line focus" is report (if it is
	// reported).
	OnLineFocusLost(_ *Env, cIdx, sIdx int)
}

LineFocusLooser is implemented by a component who wants to be informed when a focused line looses its focus.

type LineFocuser

type LineFocuser interface {

	// OnLineFocus is called by Lines if the line with given content
	// line index cIdx and given screen line index sIdx receives the
	// focus.  Note is a component is associated with a source or there
	// are more content lines than fitting on the screen cLine and sLine
	// may differ.
	OnLineFocus(_ *Env, cIdx, sIdx int)
}

LineFocuser is implemented by a component who wants to be informed when one of its lines receives the focus.

type LineOverflower added in v0.9.1

type LineOverflower interface {

	// LineOverflows is called by Lines if a components line receives
	// the focus whose content overflows to the left or to the right or
	// at both sides.
	OnLineOverflowing(_ *Env, left, right bool)
}

LineOverflower implementations are called back when a line receives the focus whose content either overflows to the left or to the right or at both sides.

type LineSelecter

type LineSelecter interface {

	// OnLineSelection is called by Lines if the focused line having
	// index i of implementing component was selected.
	OnLineSelection(_ *Env, cIdx, sIdx int)
}

LineSelecter is implemented by a component who wants to be informed when its focused line was selected.

type Liner

type Liner interface {

	// Print prints the line with given index idx to given line writer w
	// and returns true if there are lines with a greater index than
	// idx.
	Print(idx int, w *EnvLineWriter) bool
}

A Liner implementations is a different way to provide a component's content in case many lines should be associated with a component. This approach allows a component to control its features like scrolling and line focusing without bothering the client while only the number of screen lines of lines is stored in the component.

type Lines

type Lines struct {

	// Quitting provides an instance to control key/rune-bindings for
	// terminating the event-loop and unblocking [Lines.WaitForQuit].
	// Note if Quitting is set the keys CtrlC/CtrlD always quit.
	Quitting *quitting

	// Globals are properties whose changing is propagated to all its
	// clones in components who update iff the updated property is still
	// in sync with the origin.
	Globals *Globals
	// contains filtered or unexported fields
}

Lines listens to a backend implementation's reporting of events and controls the event reporting to client components (see Component) and their layout accordingly. Use one of the constructors Term, TermKiosk or TermFixture to obtain a Lines-instance.

func Term

func Term(cmp Componenter) *Lines

Term returns a Lines l instance with a terminal backend displaying and reporting events to given component cmp and its nested components. By default 'q', ctrl-c and ctrl-d terminate the event-loop and unblock l.WaitForQuit(). The binding to 'q' may be removed. The bindings to ctrl-c and ctrl-d may not be removed. Use the TermKiosk constructor for an setup without any quit bindings. Term panics if the terminal screen can't be obtained. NOTE to create a Componenter-instance define a type which embeds the Component type:

type myComponent struct { lines.Component }
lines.Term(&myComponent{}).WaitForQuit()

Leverage Lines.OnQuit registration if you want to be informed about the quit event which is triggered by user-input that is associated with the quitable feature or by calling Lines.Quit. After your application is initialized you typically will want to wait while processing user input until the quit event occurs using Lines.WaitForQuit.

func TermKiosk

func TermKiosk(cmp Componenter) *Lines

TermKiosk returns a Lines instance like Term but without registered Quitable feature, i.e. the application can't be quit by the user by default.

func (*Lines) Colors added in v0.10.0

func (ll *Lines) Colors() int

func (*Lines) CursorComponent added in v0.9.1

func (ll *Lines) CursorComponent() Componenter

CursorComponent returns the component where currently the cursor is set or nil if the cursor is not set.

func (*Lines) CursorPosition added in v0.9.1

func (ll *Lines) CursorPosition() (x, y int, _ bool)

CursorPosition returns given lines ll instance's cursor screen position (x,y) and true in case the cursor is set; otherwise -1, -1 and false is returned.

func (*Lines) Focus

func (ll *Lines) Focus(cmp Componenter) error

MoveFocus posts a new MoveFocus event into the event loop which once it is polled calls the currently focused component's OnFocusLost implementation while given component's OnFocus implementation is executed. Finally the focus is set to given component. MoveFocus fails if the event-loop is full returned error will wrap tcell's *PostEvent* error. MoveFocus is an no-op if Componenter is nil, is not part of the layout, is off-screen or is already focused.

func (*Lines) OnQuit

func (ll *Lines) OnQuit(listener func()) *Lines

OnQuit registers given function to be called on quitting event-polling and -reporting.

func (*Lines) Quit

func (ll *Lines) Quit()

Quit posts a quit event which consequently closes given Lines instance's backend and unblocks WaitForQuit.

func (*Lines) Redraw added in v0.10.0

func (ll *Lines) Redraw() error

func (*Lines) RemoveCursor added in v0.9.1

func (ll *Lines) RemoveCursor()

RemoveCursor removes the cursor from the screen.

func (*Lines) Root added in v0.10.0

func (ll *Lines) Root() Componenter

func (*Lines) SetCursor added in v0.9.1

func (ll *Lines) SetCursor(x, y int, cs ...CursorStyle)

SetCursor sets the cursor to given coordinates (x,y) on the screen having optionally given cursor style cs[0]. The call is ignored respectively a currently set cursor is removed iff x and y are outside the screen area or if they are inside the screen area but cs[0] is the zero cursor style.

func (*Lines) SetRoot added in v0.9.0

func (ll *Lines) SetRoot(c Componenter) error

SetRoot replaces currently used root component by given component.

func (*Lines) Update

func (ll *Lines) Update(
	cmp Componenter, data interface{}, l Listener,
) error

Update posts an update event into the event queue which is reported either to given listener if not nil or to given componenter if given listener is nil. Given data will be provided by the reported Update event. Update is a no-op if componenter and listener are nil.

Note if Update is used in a test to retrieve component properties which may be only retrieved in a listener callback then you can not cancel the test-run inside the listener. "FatalNow" and friends must be only called in the go-routine of the test but the Update-listener callback during testing is done from the go-routine which is running the event-loop and which is different from the go-routine running the test.

func (*Lines) WaitForQuit

func (ll *Lines) WaitForQuit()

WaitForQuit blocks until given Lines-instance is quit. (Except a Lines instance provided by a Fixture in which case WaitForQuit is not blocking.)

type Listener

type Listener func(*Env)

A Listener is the most common type of event listener: a callback provided with an environment.

type Listeners

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

Listeners provide the API to register key and rune event listeners for a component. Use a Component's Register property to obtain its Listeners instance. Listeners methods will panic if they are not used within an event listener callback.

func (*Listeners) Key

func (ll *Listeners) Key(k Key, m ModifierMask, l Listener)

Key adds to given listeners ll a new listener l which is notified on a key event with given key k and modifiers m. Is l nil the key binding is removed. An already registered listener for k and m is overwritten.

func (*Listeners) Rune

func (ll *Listeners) Rune(r rune, m ModifierMask, l Listener)

Rune adds to given listeners ll a new listener l which is notified on a rune event with given rune r and modifiers m. Is l nil the key binding is removed. An already registered listener for k and m is overwritten.

type Modaler added in v0.9.0

type Modaler interface {

	// OnOutOfBoundClick gets mouse clicks reported whose position is
	// outside of a modal focused layer.  Provided environment e may be
	// used to retrieve the mouse event e.Evt.(MouseEventer).  If
	// OnOutOfBoundClick returns true the default reporting of the mouse
	// event is executed; otherwise it is not.  The former typically may
	// happen if an outside click removes the modal layer.
	OnOutOfBoundClick(e *Env) (continueReporting bool)
}

Modaler must be implemented by a layer-component which wants to be dealt with by the user before the user does anything else. A layer component is a component provided to Component.Layered. The "last" modal layer gets the focus and stays focused until the layer is removed. Mouse clicks at a position outside a modal layer are reported to OnOutsideMouse.

type ModifierMask

type ModifierMask = api.ModifierMask

A ModifierMask are the pressed modifier keys of a key, rune or mouse event. Note that the shift modifier of a capital rune event is not reported.

const (
	Shift        ModifierMask = api.Shift
	Ctrl         ModifierMask = api.Ctrl
	Alt          ModifierMask = api.Alt
	Meta         ModifierMask = api.Meta
	ZeroModifier ModifierMask = api.ZeroModifier
)

type MouseClick added in v0.9.0

type MouseClick = api.MouseClick

MouseClick is an MouseEventer implementation reporting the aggregation of mouse events as a mouse click of arbitrary button. Implementing the Clicker interface one gets clicks of the primary button reported. Implementing the Contexter interface one gets clicks of the secondary button reported.

type MouseDrag added in v0.9.0

type MouseDrag = api.MouseDrag

type MouseDrop added in v0.9.0

type MouseDrop = api.MouseDrop

type MouseEventer

type MouseEventer = api.MouseEventer

A MouseEventer is implemented by a reported mouse event. Mouse events may be received from a component by implementing the Mouser interface. MouseEventer.Source() provides the backend event triggering the mouse event.

type MouseMove added in v0.9.0

type MouseMove = api.MouseMove

type Mouser

type Mouser interface {

	// OnMouse implementation of a component c gets any mouse event
	// reported.  x and y provide the click coordinates translated into
	// the "screen area" (c.Dim().Screen()) of c.  Mouse events bubble; use
	// e.StopBubbling() to suppress further bubbling.  Note
	// e.Evt.(MouseEventer).Mod() provides also the modifiers information and
	// e.Evt.Source() provides the event object reported by the backend.
	OnMouse(e *Env, _ ButtonMask, x, y int)
}

Mouser is implemented by components who want to be informed about all mouse event in their "screen area". Note no implicit focusing happens no matter what the event.

type Mover added in v0.9.0

type Mover interface {

	// OnMove implementation of a component c gets mouse movements
	// reported whereas provided coordinates x and y of the movement are
	// translated into the "screen area" of c.
	OnMove(e *Env, x, y int)
}

Mover is implemented by components which want to be informed about a mouse movement events in(to) their printable area.

type OutOfBoundMover added in v0.9.0

type OutOfBoundMover interface {

	// OnOutOfBoundMove implementation of a modal layer gets mouse
	// movement reported happening outside layed out boundaries.
	// Returned bool value indicates if the mouse movement should be
	// continued to be reported normally or not.
	OnOutOfBoundMove(*Env) bool
}

OutOfBoundMover is implemented by a modal layers which want to be informed about mouse movement outside their layed out boundaries.

type Range

type Range [2]int

Range is a two component array of which the first component represents the (inclusive) start of a range while the seconde is the (exclusive) end of the range. Range is typically used to define style ranges for rune-sequences in a Line (see Line.AddStyleRange).

func (Range) End

func (r Range) End() int

End returns the exclusive end-point of given range r.

func (Range) Start

func (r Range) Start() int

Start returns the inclusive start-point of given range r.

type RuneEventer

type RuneEventer = api.RuneEventer

A RuneEventer is implemented by a reported rune-event. Rune events may be received from a Componenter by implementing the Runer interface. RuneEventer.Source() provides the backend event triggering the rune event.

type Runer

type Runer interface {

	// OnRune is provided with every rune-input.
	OnRune(*Env, rune, ModifierMask)
}

Runer is implemented by components who want to take over the user's rune-input if they are focused.

type SR

type SR struct {
	Range
	Style
}

SR represents a ranged style which is used internally to style a sequence of runes in a Component's Line or may be passed to Line.AddStyleRange calls.

func (*SR) IncrementStart

func (sr *SR) IncrementStart()

Increment the start position of embedded range.

func (*SR) SetEnd

func (sr *SR) SetEnd(x int)

SetEnd sets the endpoint of embedded range.

type Scroll added in v0.10.0

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

func (Scroll) BarDef added in v0.10.0

func (s Scroll) BarDef(c Componenter) (sbd ScrollBarDef)

BarDef retrieves given Componenter c's scroll bar definition sparing fx.Lines.Update...

func (Scroll) ToBottom added in v0.10.0

func (s Scroll) ToBottom(c Componenter)

ToBottom scrolls given Componenter c to the bottom sparing fx.Lines.Update...

type ScrollBarDef added in v0.10.0

type ScrollBarDef struct {
	AtLeft   bool
	GapIndex int
	Style    Style
	Position Style
}

func DefaultScrollbarDef added in v0.10.0

func DefaultScrollbarDef() ScrollBarDef

type ScrollableLiner

type ScrollableLiner interface {
	Liner

	// Len returns the total number of content lines a liner
	// implementation can provide to its associated component.
	Len() int
}

ScrollableLiner implementations are Liner implementations triggering the scrolling feature of associated component, i.e. a content source with a scrollable liner makes its associated component automatically scrolling.

type Scroller

type Scroller struct {
	Bar bool
	// contains filtered or unexported fields
}

Scroller provides a component's scrolling API.

func (Scroller) BarContains added in v0.10.0

func (s Scroller) BarContains(x, y int) bool

func (Scroller) BarPosition added in v0.10.0

func (s Scroller) BarPosition() int

func (Scroller) CoordinateToContentIndex added in v0.10.0

func (s Scroller) CoordinateToContentIndex(y int) (line int)

CoordinateToContentIndex maps a y screen-coordinate to its content index whereas this may be an associated component's content line index or the content index of associated component's source liner.

func (Scroller) Down

func (s Scroller) Down()

Down scrolls one page down. Whereas "one page" is in case of a component height of 1 is one line. For a height h with 1 < h < 20 "one page" is h - 1. For h >= 20 "one page" is h - h/10.

func (Scroller) IsAtBottom

func (s Scroller) IsAtBottom() bool

IsAtBottom is true if a component's printable area contains the component's last line.

func (Scroller) IsAtTop

func (s Scroller) IsAtTop() bool

IsAtTop returns true if the first screen line is the first component line.

func (Scroller) To

func (s Scroller) To(idx int)

To scrolls to the index that the line with given index is displayed.

func (Scroller) ToBottom

func (s Scroller) ToBottom()

ToBottom scrolls to the index that the last screen line displays the last component line.

func (Scroller) ToTop

func (s Scroller) ToTop()

ToTop scrolls a component's content to its first line, i.e. the first screen line displays the first component line.

func (Scroller) Up

func (s Scroller) Up()

Up scrolls one page up. Whereas "one page" is in case of a component height of 1 is one line. For a height h with 1 < h < 20 "one page" is h - 1. For h >= 20 "one page" is h - h/10.

type Stacker

type Stacker interface {

	// ForStacked calls back for each component of this Stacker
	// respectively until the callback asks to stop.
	ForStacked(func(Componenter) (stop bool))
}

Stacker is implemented by components which want to provide nested components which are vertically stacked in the layout.

type Stacking

type Stacking struct{ CC []Componenter }

Stacking embedded in a component makes the component implement the Stacker interface. Typically the Componenter slice is filled in a component's Initer-listener:

type stackedCmp struct { lines.Component }

type myCmp struct{
	lines.Component
	lines.Stacking
}

func (c *myCmp) OnInit(_ *lines.Env) {
	for i := 0; i < 3; i++ {
		c.CC = append(c.CC, &stackedCmp{})
	}
}

func (Stacking) ForStacked

func (s Stacking) ForStacked(cb func(Componenter) (stop bool))

ForStacked calls back for each component of this Stacker respectively until the callback asks to stop.

type StringScreen

type StringScreen = api.StringScreen

StringScreen is the string representation of the screen lines at a particular point in time of Fixture's Lines instance. E.g. see Fixture.ScreenOf or Fixture.Screen. NOTE use StringScreen's Trimmed-method to minimize the reported screen area.

type Style

type Style = api.Style

Style represents what a print to the screen should look like. A new Style instance has fore- and background color set to black. Use its With* methods to create a style with desired properties:

myStyle := (lines.Style{}).WithFG(lines.White)

type StyleAttributeMask

type StyleAttributeMask = api.StyleAttributeMask

StyleAttributeMask defines the looks of a rune on the screen; e.g. bold, blinking, dimmed etc.

type StyleType

type StyleType uint

StyleType constants identify a style for a certain function, e.g. default fore- and background color and style attributes of a component, or fore-/background color and style attributes for a component's highlighted line.

const (
	Default StyleType = iota
	Highlight
)

type UpdateEvent

type UpdateEvent struct {

	// Data provided to an update event listener
	Data interface{}
	// contains filtered or unexported fields
}

UpdateEvent is created by an Lines.Update call. Its Data field provides the data which was passed to that Update call. To get notified of an update event a component must implement Updater:

func (c *myCmp) OnUpdate(e *lines.Env) {
    d := e.Evt.(*lines.UpdateEvent).Data
}

Note was an explicit listener passed to Lines.Update the event is not reported to the component.

func (*UpdateEvent) Source

func (u *UpdateEvent) Source() interface{}

func (*UpdateEvent) When

func (u *UpdateEvent) When() time.Time

When of an update event is set to time.Now()

type Updater

type Updater interface {

	// OnUpdate is reported for update requests without listener;
	// e.Evt.(*lines.UpdateEvent).Data provides the data optionally
	// provided to the update event registration.
	OnUpdate(e *Env, data interface{})
}

Updater is implemented by components which want to be informed about update events. NOTE an Update event reaches only an Updater interface implementation if the Lines.Update-call was NOT provided with an event listener.

Directories

Path Synopsis
cmp
fx
Package fx provides test fixtures for the cmp-packages.
Package fx provides test fixtures for the cmp-packages.
selects
Package colors provides helper functions for dealing with colors in context of lines.
Package colors provides helper functions for dealing with colors in context of lines.
examples
demo
Package demo provides helper for the example packages in "examples".
Package demo provides helper for the example packages in "examples".
gpmmouse
Was a first stand alone hack for implementing linux console gpm mouse support.
Was a first stand alone hack for implementing linux console gpm mouse support.
scrolling
Package scrolling chains to components one of which gets its content from a source with a liner implementation while the other one's content is directly written to it.
Package scrolling chains to components one of which gets its content from a source with a liner implementation while the other one's content is directly written to it.
tty
internal
api
lyt
Package lyt provides the means to layout components in a given area.
Package lyt provides the means to layout components in a given area.

Jump to

Keyboard shortcuts

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