summaryrefslogtreecommitdiffstats
path: root/termui
diff options
context:
space:
mode:
authorCaleb Bassi <calebjbassi@gmail.com>2018-03-29 15:48:43 -0700
committerCaleb Bassi <calebjbassi@gmail.com>2018-03-29 15:48:43 -0700
commitdc41895011e95d07b3929506cd557d80a4c871ae (patch)
treecbb7df1da51e39c50897750d98ed2ef1456e3bfb /termui
parentdc8cc5aa4db5cc08ae01b2ce48b6d310b98e858f (diff)
Move termui to seperate repo
Diffstat (limited to 'termui')
-rw-r--r--termui/block.go100
-rw-r--r--termui/block_common.go18
-rw-r--r--termui/block_windows.go18
-rw-r--r--termui/buffer.go99
-rw-r--r--termui/colors.go49
-rw-r--r--termui/events.go204
-rw-r--r--termui/gauge.go51
-rw-r--r--termui/grid.go66
-rw-r--r--termui/init.go26
-rw-r--r--termui/linegraph.go126
-rw-r--r--termui/render.go40
-rw-r--r--termui/sparkline.go77
-rw-r--r--termui/table.go179
-rw-r--r--termui/utils.go24
14 files changed, 0 insertions, 1077 deletions
diff --git a/termui/block.go b/termui/block.go
deleted file mode 100644
index 4695f25..0000000
--- a/termui/block.go
+++ /dev/null
@@ -1,100 +0,0 @@
-package termui
-
-import (
- "image"
-)
-
-// Block is a base struct for all other upper level widgets.
-type Block struct {
- Grid image.Rectangle
- X int // largest X value in the inner square
- Y int // largest Y value in the inner square
- XOffset int // the X position of the widget on the terminal
- YOffset int // the Y position of the widget on the terminal
- Label string
- BorderFg Color
- BorderBg Color
- LabelFg Color
- LabelBg Color
- Fg Color
- Bg Color
-}
-
-// NewBlock returns a *Block which inherits styles from the current theme.
-func NewBlock() *Block {
- return &Block{
- Fg: Theme.Fg,
- Bg: Theme.Bg,
- BorderFg: Theme.BorderFg,
- BorderBg: Theme.BorderBg,
- LabelFg: Theme.LabelFg,
- LabelBg: Theme.LabelBg,
- }
-}
-
-func (self *Block) drawBorder(buf *Buffer) {
- x := self.X + 1
- y := self.Y + 1
-
- // draw lines
- buf.Merge(NewFilledBuffer(0, 0, x, 1, Cell{HORIZONTAL_LINE, self.BorderFg, self.BorderBg}))
- buf.Merge(NewFilledBuffer(0, y, x, y+1, Cell{HORIZONTAL_LINE, self.BorderFg, self.BorderBg}))
- buf.Merge(NewFilledBuffer(0, 0, 1, y+1, Cell{VERTICAL_LINE, self.BorderFg, self.BorderBg}))
- buf.Merge(NewFilledBuffer(x, 0, x+1, y+1, Cell{VERTICAL_LINE, self.BorderFg, self.BorderBg}))
-
- // draw corners
- buf.SetCell(0, 0, Cell{TOP_LEFT, self.BorderFg, self.BorderBg})
- buf.SetCell(x, 0, Cell{TOP_RIGHT, self.BorderFg, self.BorderBg})
- buf.SetCell(0, y, Cell{BOTTOM_LEFT, self.BorderFg, self.BorderBg})
- buf.SetCell(x, y, Cell{BOTTOM_RIGHT, self.BorderFg, self.BorderBg})
-}
-
-func (self *Block) drawLabel(buf *Buffer) {
- r := MaxString(self.Label, (self.X-3)-1)
- buf.SetString(3, 0, r, self.LabelFg, self.LabelBg)
- if self.Label == "" {
- return
- }
- c := Cell{' ', self.Fg, self.Bg}
- buf.SetCell(2, 0, c)
- if len(self.Label)+3 < self.X {
- buf.SetCell(len(self.Label)+3, 0, c)
- } else {
- buf.SetCell(self.X-1, 0, c)
- }
-}
-
-// Resize computes Height, Width, XOffset, and YOffset given terminal dimensions.
-func (self *Block) Resize(termWidth, termHeight, termCols, termRows int) {
- self.X = int((float64(self.Grid.Dx())/float64(termCols))*float64(termWidth)) - 2
- self.Y = int((float64(self.Grid.Dy())/float64(termRows))*float64(termHeight)) - 2
- self.XOffset = int((float64(self.Grid.Min.X) / float64(termCols)) * float64(termWidth))
- self.YOffset = int((float64(self.Grid.Min.Y) / float64(termRows)) * float64(termHeight))
-}
-
-// SetGrid create a rectangle representing the block's dimensions in the grid.
-func (self *Block) SetGrid(c0, r0, c1, r1 int) {
- self.Grid = image.Rect(c0, r0, c1, r1)
-}
-
-// GetXOffset implements Bufferer interface.
-func (self *Block) GetXOffset() int {
- return self.XOffset
-}
-
-// GetYOffset implements Bufferer interface.
-func (self *Block) GetYOffset() int {
- return self.YOffset
-}
-
-// Buffer implements Bufferer interface and draws background, border, and borderlabel.
-func (self *Block) Buffer() *Buffer {
- buf := NewBuffer()
- buf.SetAreaXY(self.X+2, self.Y+2)
- buf.Fill(Cell{' ', ColorDefault, self.Bg})
-
- self.drawBorder(buf)
- self.drawLabel(buf)
-
- return buf
-}
diff --git a/termui/block_common.go b/termui/block_common.go
deleted file mode 100644
index aeef1c8..0000000
--- a/termui/block_common.go
+++ /dev/null
@@ -1,18 +0,0 @@
-// +build !windows
-
-package termui
-
-const (
- TOP_RIGHT = '┐'
- VERTICAL_LINE = '│'
- HORIZONTAL_LINE = '─'
- TOP_LEFT = '┌'
- BOTTOM_RIGHT = '┘'
- BOTTOM_LEFT = '└'
- VERTICAL_LEFT = '┤'
- VERTICAL_RIGHT = '├'
- HORIZONTAL_DOWN = '┬'
- HORIZONTAL_UP = '┴'
- QUOTA_LEFT = '«'
- QUOTA_RIGHT = '»'
-)
diff --git a/termui/block_windows.go b/termui/block_windows.go
deleted file mode 100644
index af0307f..0000000
--- a/termui/block_windows.go
+++ /dev/null
@@ -1,18 +0,0 @@
-// +build windows
-
-package termui
-
-const (
- TOP_RIGHT = '+'
- VERTICAL_LINE = '|'
- HORIZONTAL_LINE = '-'
- TOP_LEFT = '+'
- BOTTOM_RIGHT = '+'
- BOTTOM_LEFT = '+'
- VERTICAL_LEFT = '+'
- VERTICAL_RIGHT = '+'
- HORIZONTAL_DOWN = '+'
- HORIZONTAL_UP = '+'
- QUOTA_LEFT = '<'
- QUOTA_RIGHT = '>'
-)
diff --git a/termui/buffer.go b/termui/buffer.go
deleted file mode 100644
index 9faabaf..0000000
--- a/termui/buffer.go
+++ /dev/null
@@ -1,99 +0,0 @@
-package termui
-
-import (
- "image"
-)
-
-// Cell is a rune with assigned Fg and Bg.
-type Cell struct {
- Ch rune
- Fg Color
- Bg Color
-}
-
-// Buffer is a renderable rectangle cell data container.
-type Buffer struct {
- Area image.Rectangle // selected drawing area
- CellMap map[image.Point]Cell
-}
-
-// NewCell returne a new Cell given all necessary fields.
-func NewCell(ch rune, Fg, Bg Color) Cell {
- return Cell{ch, Fg, Bg}
-}
-
-// NewBuffer returns a new empty Buffer.
-func NewBuffer() *Buffer {
- return &Buffer{
- CellMap: make(map[image.Point]Cell),
- Area: image.Rectangle{},
- }
-}
-
-// NewFilledBuffer returns a new Buffer filled with the given Cell.
-func NewFilledBuffer(x0, y0, x1, y1 int, c Cell) *Buffer {
- buf := NewBuffer()
- buf.Area.Min = image.Pt(x0, y0)
- buf.Area.Max = image.Pt(x1, y1)
- buf.Fill(c)
- return buf
-}
-
-// SetCell assigns a Cell to (x,y).
-func (self *Buffer) SetCell(x, y int, c Cell) {
- self.CellMap[image.Pt(x, y)] = c
-}
-
-// SetString assigns a string to a Buffer starting at (x,y).
-func (self *Buffer) SetString(x, y int, s string, fg, bg Color) {
- for i, char := range s {
- self.SetCell(x+i, y, Cell{char, fg, bg})
- }
-}
-
-// At returns the cell at (x,y).
-func (self *Buffer) At(x, y int) Cell {
- return self.CellMap[image.Pt(x, y)]
-}
-
-// SetArea assigns a new rect area to self.
-func (self *Buffer) SetArea(r image.Rectangle) {
- self.Area.Max = r.Max
- self.Area.Min = r.Min
-}
-
-// SetAreaXY sets the Buffer bounds from (0,0) to (x,y).
-func (self *Buffer) SetAreaXY(x, y int) {
- self.Area.Min.Y = 0
- self.Area.Min.X = 0
- self.Area.Max.Y = y
- self.Area.Max.X = x
-}
-
-// Merge merges the given buffers onto the current Buffer.
-func (self *Buffer) Merge(bs ...*Buffer) {
- for _, buf := range bs {
- for p, c := range buf.CellMap {
- self.SetCell(p.X, p.Y, c)
- }
- self.SetArea(self.Area.Union(buf.Area))
- }
-}
-
-// MergeWithOffset merges a Buffer onto another with an offset.
-func (self *Buffer) MergeWithOffset(buf *Buffer, xOffset, yOffset int) {
- for p, c := range buf.CellMap {
- self.SetCell(p.X+xOffset, p.Y+yOffset, c)
- }
- rect := image.Rect(xOffset, yOffset, buf.Area.Max.X+xOffset, buf.Area.Max.Y+yOffset)
- self.SetArea(self.Area.Union(rect))
-}
-
-// Fill fills the Buffer with a Cell.
-func (self *Buffer) Fill(c Cell) {
- for x := self.Area.Min.X; x < self.Area.Max.X; x++ {
- for y := self.Area.Min.Y; y < self.Area.Max.Y; y++ {
- self.SetCell(x, y, c)
- }
- }
-}
diff --git a/termui/colors.go b/termui/colors.go
deleted file mode 100644
index 3af2469..0000000
--- a/termui/colors.go
+++ /dev/null
@@ -1,49 +0,0 @@
-package termui
-
-// Color is an integer in the range -1 to 255.
-type Color int
-
-// ColorDefault = clear
-const ColorDefault = -1
-
-// Copied from termbox. Attributes that can be bitwise OR'ed with a color.
-const (
- AttrBold Color = 1 << (iota + 9)
- AttrUnderline
- AttrReverse
-)
-
-// Theme is assigned to the current theme.
-var Theme = DefaultTheme
-
-// DefaultTheme implements a generic set of colors to use by default.
-var DefaultTheme = Colorscheme{
- Fg: 7,
- Bg: -1,
-
- LabelFg: 7,
- LabelBg: -1,
- BorderFg: 6,
- BorderBg: -1,
-
- Sparkline: 4,
- LineGraph: 0,
- TableCursor: 4,
- GaugeColor: 7,
-}
-
-// A Colorscheme represents the current look-and-feel of the dashboard.
-type Colorscheme struct {
- Fg Color
- Bg Color
-
- LabelFg Color
- LabelBg Color
- BorderFg Color
- BorderBg Color
-
- Sparkline Color
- LineGraph Color
- TableCursor Color
- GaugeColor Color
-}
diff --git a/termui/events.go b/termui/events.go
deleted file mode 100644
index 3bc5459..0000000
--- a/termui/events.go
+++ /dev/null
@@ -1,204 +0,0 @@
-package termui
-
-import (
- "strconv"
-
- tb "github.com/nsf/termbox-go"
-)
-
-/*
-here's the list of events which you can assign handlers too using the `On` function:
- mouse events:
- <MouseLeft> <MouseRight> <MouseMiddle>
- <MouseWheelUp> <MouseWheelDown>
- keyboard events:
- any uppercase or lowercase letter or a set of two letters like j or jj or J or JJ
- <C-d> etc
- <M-d> etc
- <up> <down> <left> <right>
- <insert> <delete> <home> <end> <previous> <next>
- <backspace> <tab> <enter> <escape> <space>
- <C-<space>> etc
- terminal events:
- <resize>
-*/
-
-var eventStream = EventStream{
- make(map[string]func(Event)),
- "",
- make(chan bool, 1),
- make(chan tb.Event),
-}
-
-type EventStream struct {
- eventHandlers map[string]func(Event)
- prevKey string // previous keypress
- stopLoop chan bool
- eventQueue chan tb.Event // list of events from termbox
-}
-
-// Event is a copy of termbox.Event that only contains the fields we need.
-type Event struct {
- Key string
- Width int
- Height int
- MouseX int
- MouseY int
-}
-
-// handleEvent calls the approriate callback function if there is one.
-func handleEvent(e tb.Event) {
- if e.Type == tb.EventError {
- panic(e.Err)
- }
-
- ne := convertTermboxEvent(e)
-
- if val, ok := eventStream.eventHandlers[ne.Key]; ok {
- val(ne)
- eventStream.prevKey = ""
- } else { // check if the last 2 keys form a key combo with a handler
- // if this is a keyboard event and the previous event was unhandled
- if e.Type == tb.EventKey && eventStream.prevKey != "" {
- combo := eventStream.prevKey + ne.Key
- if val, ok := eventStream.eventHandlers[combo]; ok {
- ne.Key = combo
- val(ne)
- eventStream.prevKey = ""
- } else {
- eventStream.prevKey = ne.Key
- }
- } else {
- eventStream.prevKey = ne.Key
- }
- }
-}
-
-// Loop gets events from termbox and passes them off to handleEvent.
-// Stops when StopLoop is called.
-func Loop() {
- go func() {
- for {
- eventStream.eventQueue <- tb.PollEvent()
- }
- }()
-
- for {
- select {
- case <-eventStream.stopLoop:
- return
- case e := <-eventStream.eventQueue:
- handleEvent(e)
- }
- }
-}
-
-// StopLoop stops the event loop.
-func StopLoop() {
- eventStream.stopLoop <- true
-}
-
-// On assigns event names to their handlers. Takes a string, strings, or a slice of strings, and a function.
-func On(things ...interface{}) {
- function := things[len(things)-1].(func(Event))
- for _, thing := range things {
- if value, ok := thing.(string); ok {
- eventStream.eventHandlers[value] = function
- }
- if value, ok := thing.([]string); ok {
- for _, name := range value {
- eventStream.eventHandlers[name] = function
- }
- }
- }
-}
-
-// convertTermboxKeyValue converts a termbox keyboard event to a more friendly string format.
-// Combines modifiers into the string instead of having them as additional fields in an event.
-func convertTermboxKeyValue(e tb.Event) string {
- k := string(e.Ch)
- pre := ""
- mod := ""
-
- if e.Mod == tb.ModAlt {
- mod = "<M-"
- }
- if e.Ch == 0 {
- if e.Key > 0xFFFF-12 {
- k = "<f" + strconv.Itoa(0xFFFF-int(e.Key)+1) + ">"
- } else if e.Key > 0xFFFF-25 {
- ks := []string{"<insert>", "<delete>", "<home>", "<end>", "<previous>", "<next>", "<up>", "<down>", "<left>", "<right>"}
- k = ks[0xFFFF-int(e.Key)-12]
- }
-
- if e.Key <= 0x7F {
- pre = "<C-"
- k = string('a' - 1 + int(e.Key))
- kmap := map[tb.Key][2]string{
- tb.KeyCtrlSpace: {"C-", "<space>"},
- tb.KeyBackspace: {"", "<backspace>"},
- tb.KeyTab: {"", "<tab>"},
- tb.KeyEnter: {"", "<enter>"},
- tb.KeyEsc: {"", "<escape>"},
- tb.KeyCtrlBackslash: {"C-", "\\"},
- tb.KeyCtrlSlash: {"C-", "/"},
- tb.KeySpace: {"", "<space>"},
- tb.KeyCtrl8: {"C-", "8"},
- }
- if sk, ok := kmap[e.Key]; ok {
- pre = sk[0]
- k = sk[1]
- }
- }
- }
-
- if pre != "" {
- k += ">"
- }
-
- return pre + mod + k
-}
-
-func convertTermboxMouseValue(e tb.Event) string {
- switch e.Key {
- case tb.MouseLeft:
- return "<MouseLeft>"
- case tb.MouseMiddle:
- return "<MouseMiddle>"
- case tb.MouseRight:
- return "<MouseRight>"
- case tb.MouseWheelUp:
- return "<MouseWheelUp>"
- case tb.MouseWheelDown:
- return "<MouseWheelDown>"
- case tb.MouseRelease:
- return "<MouseRelease>"
- }
- return ""
-}
-
-// convertTermboxEvent turns a termbox event into a termui event.
-func convertTermboxEvent(e tb.Event) Event {
- var ne Event
-
- switch e.Type {
- case tb.EventKey:
- ne = Event{
- Key: convertTermboxKeyValue(e),
- }
- case tb.EventMouse:
- ne = Event{
- Key: convertTermboxMouseValue(e),
- MouseX: e.MouseX,
- MouseY: e.MouseY,
- }
- case tb.EventResize:
- ne = Event{
- Key: "<resize>",
- Width: e.Width,
- Height: e.Height,
- }
- }
-
- return ne
-}
diff --git a/termui/gauge.go b/termui/gauge.go
deleted file mode 100644
index a5b3b2a..0000000
--- a/termui/gauge.go
+++ /dev/null
@@ -1,51 +0,0 @@
-package termui
-
-import (
- "strconv"
-)
-
-// Gauge is a progress bar like widget.
-type Gauge struct {
- *Block
- Percent int
- GaugeColor Color
- Description string
-}
-
-// NewGauge return a new gauge with current theme.
-func NewGauge() *Gauge {
- return &Gauge{
- Block: NewBlock(),
- GaugeColor: Theme.GaugeColor,
- }
-}
-
-// Buffer implements Bufferer interface.
-func (self *Gauge) Buffer() *Buffer {
- buf := self.Block.Buffer()
-
- // plot bar
- width := self.Percent * self.X / 100
- for y := 1; y <= self.Y; y++ {
- for x := 1; x <= width; x++ {
- buf.SetCell(x, y, Cell{' ', self.GaugeColor, self.GaugeColor})
- }
- }
-
- // plot percentage
- s := strconv.Itoa(self.Percent) + "%" + self.Description
- s = MaxString(s, self.X)
- y := (self.Y + 1) / 2
- x := ((self.X - len(s)) + 1) / 2
- for i, char := range s {
- bg := self.Bg
- fg := self.Fg
- if x+i < width {
- fg = self.GaugeColor
- bg = AttrReverse
- }
- buf.SetCell(1+x+i, y, Cell{char, fg, bg})
- }
-
- return buf
-}
diff --git a/termui/grid.go b/termui/grid.go
deleted file mode 100644
index 58b4839..0000000
--- a/termui/grid.go
+++ /dev/null
@@ -1,66 +0,0 @@
-package termui
-
-var Body *Grid
-
-// GridBufferer introduces a Bufferer that can be manipulated by Grid.
-type GridBufferer interface {
- Bufferer
- Resize(int, int, int, int)
- SetGrid(int, int, int, int)
-}
-
-// Grid holds widgets and information about terminal dimensions.
-// Widgets are adjusted and rendered through the grid.
-type Grid struct {
- Widgets []GridBufferer
- Width int
- Height int
- Cols int
- Rows int
-}
-
-// NewGrid creates an empty Grid.
-func NewGrid() *Grid {
- return &Grid{}
-}
-
-// Set assigns a widget and its grid dimensions to Grid.
-func (self *Grid) Set(x0, y0, x1, y1 int, widget GridBufferer) {
- if widget == nil {
- return
- }
- if x1 <= x0 || y1 <= y0 {
- panic("Invalid widget coordinates")
- }
-
- widget.SetGrid(x0, y0, x1, y1)
- widget.Resize(self.Width, self.Height, self.Cols, self.Rows)
-
- self.Widgets = append(self.Widgets, widget)
-}
-
-// Resize resizes each widget in the grid.
-func (self *Grid) Resize() {
- for _, w := range self.Widgets {
- w.Resize(self.Width, self.Height, self.Cols, self.Rows)
- }
-}
-
-// Buffer implements the Bufferer interface by merging each widget in Grid into one buffer.
-func (self *Grid) Buffer() *Buffer {
- buf := NewFilledBuffer(0, 0, self.Width, self.Height, Cell{' ', ColorDefault, Theme.Bg})
- for _, w := range self.Widgets {
- buf.MergeWithOffset(w.Buffer(), w.GetXOffset(), w.GetYOffset())
- }
- return buf
-}
-
-// GetXOffset implements Bufferer interface.
-func (self *Grid) GetXOffset() int {
- return 0
-}
-
-// GetYOffset implements Bufferer interface.
-func (self *Grid) GetYOffset() int {
- return 0
-}
diff --git a/termui/init.go b/termui/init.go
deleted file mode 100644
index 764de2b..0000000
--- a/termui/init.go
+++ /dev/null
@@ -1,26 +0,0 @@
-package termui
-
-import (
- tb "github.com/nsf/termbox-go"
-)
-
-// Init initializes termui library. This function should be called before any others.
-// After initialization, the library must be finalized by 'Close' function.
-func Init() error {
- if err := tb.Init(); err != nil {
- return err
- }
- tb.SetInputMode(tb.InputEsc | tb.InputMouse)
- tb.SetOutputMode(tb.Output256)
-
- Body = NewGrid()
- Body.Width, Body.Height = tb.Size()
-
- return nil
-}
-
-// Close finalizes termui library.
-// It should be called after successful initialization when termui's functionality isn't required anymore.
-func Close() {
- tb.Close()
-}
diff --git a/termui/linegraph.go b/termui/linegraph.go
deleted file mode 100644
index cc71e8f..0000000
--- a/termui/linegraph.go
+++ /dev/null
@@ -1,126 +0,0 @@
-package termui
-
-import (
- "fmt"
- "sort"
-
- drawille "github.com/cjbassi/drawille-go"
-)
-
-// LineGraph implements a line graph of data points.
-type LineGraph struct {
- *Block
- Data map[string][]float64
- LineColor map[string]Color
- Zoom int
-
- DefaultLineColor Color
-}
-
-// NewLineGraph returns a new LineGraph with current theme.
-func NewLineGraph() *LineGraph {
- return &LineGraph{
- Block: NewBlock(),
- Data: make(map[string][]float64),
- LineColor: make(map[string]Color),
- Zoom: 5,
-
- DefaultLineColor: Theme.LineGraph,
- }
-}
-
-// Buffer implements Bufferer interface.
-func (self *LineGraph) Buffer() *Buffer {
- buf := self.Block.Buffer()
- // we render each data point on to the canvas then copy over the braille to the buffer at the end
- // fyi braille characters have 2x4 dots for each character
- c := drawille.NewCanvas()
- // used to keep track of the braille colors until the end when we render the braille to the buffer
- colors := make([][]Color, self.X+2)
- for i := range colors {
- colors[i] = make([]Color, self.Y+2)
- }
-
- // sort the series so that overlapping data will overlap the same way each time
- seriesList := make([]string, len(self.Data))
- i := 0
- for seriesName := range self.Data {
- seriesList[i] = seriesName
- i++
- }
- sort.Strings(seriesList)
-
- // draw lines in reverse order so that the first color defined in the colorscheme is on top
- for i := len(seriesList) - 1; i >= 0; i-- {
- seriesName := seriesList[i]
- seriesData := self.Data[seriesName]
- seriesLineColor, ok := self.LineColor[seriesName]
- if !ok {
- seriesLineColor = self.DefaultLineColor
- }
-
- // coordinates of last point
- lastY, lastX := -1, -1
- // assign colors to `colors` and lines/points to the canvas
- for i := len(seriesData) - 1; i >= 0; i-- {
- x := ((self.X + 1) * 2) - 1 - (((len(seriesData) - 1) - i) * self.Zoom)
- y := ((self.Y + 1) * 4) - 1 - int((float64((self.Y)*4)-1)*(seriesData[i]/100))
- if x < 0 {
- // render the line to the last point up to the wall
- if x > 0-self.Zoom {
- for _, p := range drawille.Line(lastX, lastY, x, y) {
- if p.X > 0 {
- c.Set(p.X, p.Y)
- colors[p.X/2][p.Y/4] = seriesLineColor
- }
- }
- }
- break
- }
- if lastY == -1 { // if this is the first point
- c.Set(x, y)
- colors[x/2][y/4] = seriesLineColor
- } else {
- c.DrawLine(lastX, lastY, x, y)
- for _, p := range drawille.Line(lastX, lastY, x, y) {
- colors[p.X/2][p.Y/4] = seriesLineColor
- }
- }
- lastX, lastY = x, y
- }
-
- // copy braille and colors to buffer
- for y, line := range c.Rows(c.MinX(), c.MinY(), c.MaxX(), c.MaxY()) {
- for x, char := range line {
- x /= 3 // idk why but it works
- if x == 0 {
- continue
- }
- if char != 10240 { // empty braille character
- buf.SetCell(x, y, Cell{char, colors[x][y], self.Bg})
- }
- }
- }
- }
-
- // renders key ontop
- for j, seriesName := range seriesList {
- // sorts lines again
- seriesData := self.Data[seriesName]
- seriesLineColor, ok := self.LineColor[seriesName]
- if !ok {
- seriesLineColor = self.DefaultLineColor
- }
-
- // render key ontop, but let braille be drawn over space characters
- str := fmt.Sprintf("%s %3.0f%%", seriesName, seriesData[len(seriesData)-1])
- for k, char := range str {
- if char != ' ' {
- buf.SetCell(3+k, j+2, Cell{char, seriesLineColor, self.Bg})
- }
- }
-
- }
-
- return buf
-}
diff --git a/termui/render.go b/termui/render.go
deleted file mode 100644
index 52bcdf3..0000000
--- a/termui/render.go
+++ /dev/null
@@ -1,40 +0,0 @@
-package termui
-
-import (
- "sync"
-
- tb "github.com/nsf/termbox-go"
-)
-
-// Bufferer should be implemented by all renderable components.
-type Bufferer interface {
- Buffer() *Buffer
- GetXOffset() int
- GetYOffset() int
-}
-
-// Render renders all Bufferers in the given order to termbox, then asks termbox to print the screen.
-func Render(bs ...Bufferer) {
- var wg sync.WaitGroup
- for _, b := range bs {
- wg.Add(1)
- go func(b Bufferer) {
- defer wg.Done()
- buf := b.Buffer()
- // set cells in buf
- for p, c := range buf.CellMap {
- if p.In(buf.Area) {
- tb.SetCell(p.X+b.GetXOffset(), p.Y+b.GetYOffset(), c.Ch, tb.Attribute(c.Fg)+1, tb.Attribute(c.Bg)+1)
- }
- }
- }(b)
- }
-
- wg.Wait()
- tb.Flush()
-}
-
-// Clear clears the screen with the default Bg color.
-func Clear() {
- tb.Clear(tb.ColorDefault+1, tb.Attribute(Theme.Bg)+1)
-}
diff --git a/termui/sparkline.go b/termui/sparkline.go
deleted file mode 100644
index 8cefff8..0000000
--- a/termui/sparkline.go
+++ /dev/null
@@ -1,77 +0,0 @@
-package termui
-
-var SPARKS = [8]rune{'▁', '▂', '▃', '▄', '▅', '▆', '▇', '█'}
-
-// Sparkline is like: ▅▆▂▂▅▇▂▂▃▆▆▆▅▃. The data points should be non-negative integers.
-type Sparkline struct {
- Data []int
- Title1 string
- Title2 string
- TitleColor Color
- LineColor Color
-}
-
-// Sparklines is a renderable widget which groups together the given sparklines.
-type Sparklines struct {
- *Block
- Lines []*Sparkline
-}
-
-// Add appends a given Sparkline to the *Sparklines.
-func (self *Sparklines) Add(sl Sparkline) {
- self.Lines = append(self.Lines, &sl)
-}
-
-// NewSparkline returns an unrenderable single sparkline that intended to be added into a Sparklines.
-func NewSparkline() *Sparkline {
- return &Sparkline{
- TitleColor: Theme.Fg,
- LineColor: Theme.Sparkline,
- }
-}
-
-// NewSparklines return a new *Sparklines with given Sparklines, you can always add a new Sparkline later.
-func NewSparklines(ss ...*Sparkline) *Sparklines {
- return &Sparklines{
- Block: NewBlock(),
- Lines: ss,
- }
-}
-
-// Buffer implements Bufferer interface.
-func (self *Sparklines) Buffer() *Buffer {
- buf := self.Block.Buffer()
-
- lc := len(self.Lines) // lineCount
-
- // renders each sparkline and its titles
- for i, line := range self.Lines {
-
- // prints titles
- title1Y := 2 + (self.Y/lc)*i
- title2Y := (2 + (self.Y/lc)*i) + 1
- title1 := MaxString(line.Title1, self.X)
- title2 := MaxString(line.Title2, self.X)
- buf.SetString(1, title1Y, title1, line.TitleColor|AttrBold, self.Bg)
- buf.SetString(1, title2Y, title2, line.TitleColor|AttrBold, self.Bg)
-
- sparkY := (self.Y / lc) * (i + 1)
- // finds max data in current view used for relative heights
- max := 1
- for i := len(line.Data) - 1; i >= 0 && self.X-((len(line.Data)-1)-i) >= 1; i-- {
- if line.Data[i] > max {
- max = line.Data[i]
- }
- }
- // prints sparkline
- for x := self.X; x >= 1; x-- {
- char := SPARKS[0]
- if (self.X - x) < len(line.Data) {
- char = SPARKS[int((float64(line.Data[(len(line.Data)-1)-(self.X-x)])/float64(max))*7)]
- }
- buf.SetCell(x, sparkY, Cell{char, line.LineColor, self.Bg})
- }
- }
-
- return buf
-}
diff --git a/termui/table.go b/termui/table.go
deleted file mode 100644
index e24031b..0000000
--- a/termui/table.go
+++ /dev/null
@@ -1,179 +0,0 @@
-package termui
-
-import (
- "strings"
-)
-
-// Table tracks all the attributes of a Table instance
-type Table struct {
- *Block
- Header []string
- Rows [][]string
- ColWidths []int
- CellXPos []int // column position
- Gap int // gap between columns
- Cursor Color
- UniqueCol int // the column used to identify the selected item
- SelectedItem string // used to keep the cursor on the correct item if the data changes
- SelectedRow int
- TopRow int // used to indicate where in the table we are scrolled at
- ColResizer func() // for widgets that inherit a Table and want to overload the ColResize method
-}
-
-// NewTable returns a new Table instance
-func NewTable() *Table {
- self := &Table{
- Block: NewBlock(),
- Cursor: Theme.TableCursor,
- SelectedRow: 0,
- TopRow: 0,
- UniqueCol: 0,
- }
- self.ColResizer = self.ColResize
- return self
-}
-
-// ColResize is the default column resizer, but can be overriden.
-// ColResize calculates the width of each column.
-func (self *Table) ColResize() {
- // calculate gap size based on total width
- self.Gap = 3
- if self.X < 50 {
- self.Gap = 1
- } else if self.X < 75 {
- self.Gap = 2
- }
-
- cur := 0
- for _, w := range self.ColWidths {
- cur += self.Gap
- self.CellXPos = append(self.CellXPos, cur)
- cur += w
- }
-}
-
-// Buffer implements the Bufferer interface.
-func (self *Table) Buffer() *Buffer {
- buf := self.Block.Buffer()
-
- // removes gap at the bottom of the current view if there is one
- if self.TopRow > len(self.Rows)-(self.Y-1) {
- self.TopRow = len(self.Rows) - (self.Y - 1)
- }
-
- self.ColResizer()
-
- // prints header
- for i, width := range self.ColWidths {
- if width == 0 {
- break
- }
- r := MaxString(self.Header[i], self.X-6)
- buf.SetString(self.CellXPos[i], 1, r, self.Fg|AttrBold, self.Bg)
- }
-
- // prints each row
- for rowNum := self.TopRow; rowNum < self.TopRow+self.Y-1 && rowNum < len(self.Rows); rowNum++ {
- row := self.Rows[rowNum]
- y := (rowNum + 2) - self.TopRow
-
- // prints cursor
- bg := self.Bg
- if (self.SelectedItem == "" && rowNum == self.SelectedRow) || (self.SelectedItem != "" && self.SelectedItem == row[self.UniqueCol]) {
- bg = self.Cursor
- for _, width := range self.ColWidths {
- if width == 0 {
- break
- }
- buf.SetString(1, y, strings.Repeat(" ", self.X), self.Fg, bg)
- }
- self.SelectedItem = row[self.UniqueCol]
- self.SelectedRow = rowNum
- }
-
- // prints each col of the row
- for i, width := range self.ColWidths {
- if width == 0 {
- break
- }
- r := MaxString(row[i], self.X-6)
- buf.SetString(self.CellXPos[i], y, r, self.Fg, bg)
- }
- }
-
- return buf
-}
-
-/////////////////////////////////////////////////////////////////////////////////
-// Cursor Movement //
-/////////////////////////////////////////////////////////////////////////////////
-
-// calcPos is used to calculate the cursor position and the current view.
-func (self *Table) calcPos() {
- self.SelectedItem = ""
-
- if self.SelectedRow < 0 {
- self.SelectedRow = 0
- }
- if self.SelectedRow < self.TopRow {
- self.TopRow = self.SelectedRow
- }
-
- if self.SelectedRow > len(self.Rows)-1 {
- self.SelectedRow = len(self.Rows) - 1
- }
- if self.SelectedRow > self.TopRow+(self.Y-2) {
- self.TopRow = self.SelectedRow - (self.Y - 2)
- }
-}
-
-func (self *Table) Up() {
- self.SelectedRow -= 1
- self.calcPos()
-}
-
-func (self *Table) Down() {
- self.SelectedRow += 1
- self.calcPos()
-}
-
-func (self *Table) Top() {
- self.SelectedRow = 0
- self.calcPos()
-}
-
-func (self *Table) Bottom() {
- self.SelectedRow = len(self.Rows) - 1
- self.calcPos()
-}
-
-// The number of lines in a page is equal to the height of the widgeself.
-
-func (self *Table) HalfPageUp() {
- self.SelectedRow = self.SelectedRow - (self.Y-2)/2
- self.calcPos()
-}
-
-func (self *Table) HalfPageDown() {
- self.SelectedRow = self.SelectedRow + (self.Y-2)/2
- self.calcPos()
-}
-
-func (self *Table) PageUp() {
- self.SelectedRow -= (self.Y - 2)
- self.calcPos()
-}
-
-func (self *Table) PageDown() {
- self.SelectedRow += (self.Y - 2)
- self.calcPos()