initial commit
This commit is contained in:
25
uiterm/attributes.go
Normal file
25
uiterm/attributes.go
Normal file
@@ -0,0 +1,25 @@
|
||||
package uiterm
|
||||
|
||||
/*
|
||||
* Source: https://godoc.org/github.com/nsf/termbox-go
|
||||
*/
|
||||
|
||||
type Attribute int
|
||||
|
||||
const (
|
||||
ColorDefault Attribute = iota
|
||||
ColorBlack
|
||||
ColorRed
|
||||
ColorGreen
|
||||
ColorYellow
|
||||
ColorBlue
|
||||
ColorMagenta
|
||||
ColorCyan
|
||||
ColorWhite
|
||||
)
|
||||
|
||||
const (
|
||||
AttrBold Attribute = 1 << (iota + 4)
|
||||
AttrUnderline
|
||||
AttrReverse
|
||||
)
|
||||
91
uiterm/keys.go
Normal file
91
uiterm/keys.go
Normal file
@@ -0,0 +1,91 @@
|
||||
package uiterm
|
||||
|
||||
/*
|
||||
* Source: https://godoc.org/github.com/nsf/termbox-go
|
||||
*/
|
||||
|
||||
type Modifier uint8
|
||||
|
||||
const (
|
||||
ModAlt Modifier = 0x01
|
||||
)
|
||||
|
||||
type Key uint16
|
||||
|
||||
const (
|
||||
KeyF1 Key = 0xFFFF - iota
|
||||
KeyF2
|
||||
KeyF3
|
||||
KeyF4
|
||||
KeyF5
|
||||
KeyF6
|
||||
KeyF7
|
||||
KeyF8
|
||||
KeyF9
|
||||
KeyF10
|
||||
KeyF11
|
||||
KeyF12
|
||||
KeyInsert
|
||||
KeyDelete
|
||||
KeyHome
|
||||
KeyEnd
|
||||
KeyPgup
|
||||
KeyPgdn
|
||||
KeyArrowUp
|
||||
KeyArrowDown
|
||||
KeyArrowLeft
|
||||
KeyArrowRight
|
||||
|
||||
MouseLeft
|
||||
MouseMiddle
|
||||
MouseRight
|
||||
)
|
||||
|
||||
const (
|
||||
KeyCtrlTilde Key = 0x00
|
||||
KeyCtrl2 Key = 0x00
|
||||
KeyCtrlSpace Key = 0x00
|
||||
KeyCtrlA Key = 0x01
|
||||
KeyCtrlB Key = 0x02
|
||||
KeyCtrlC Key = 0x03
|
||||
KeyCtrlD Key = 0x04
|
||||
KeyCtrlE Key = 0x05
|
||||
KeyCtrlF Key = 0x06
|
||||
KeyCtrlG Key = 0x07
|
||||
KeyBackspace Key = 0x08
|
||||
KeyCtrlH Key = 0x08
|
||||
KeyTab Key = 0x09
|
||||
KeyCtrlI Key = 0x09
|
||||
KeyCtrlJ Key = 0x0A
|
||||
KeyCtrlK Key = 0x0B
|
||||
KeyCtrlL Key = 0x0C
|
||||
KeyEnter Key = 0x0D
|
||||
KeyCtrlM Key = 0x0D
|
||||
KeyCtrlN Key = 0x0E
|
||||
KeyCtrlO Key = 0x0F
|
||||
KeyCtrlP Key = 0x10
|
||||
KeyCtrlQ Key = 0x11
|
||||
KeyCtrlR Key = 0x12
|
||||
KeyCtrlS Key = 0x13
|
||||
KeyCtrlT Key = 0x14
|
||||
KeyCtrlU Key = 0x15
|
||||
KeyCtrlV Key = 0x16
|
||||
KeyCtrlW Key = 0x17
|
||||
KeyCtrlX Key = 0x18
|
||||
KeyCtrlY Key = 0x19
|
||||
KeyCtrlZ Key = 0x1A
|
||||
KeyEsc Key = 0x1B
|
||||
KeyCtrlLsqBracket Key = 0x1B
|
||||
KeyCtrl3 Key = 0x1B
|
||||
KeyCtrl4 Key = 0x1C
|
||||
KeyCtrlBackslash Key = 0x1C
|
||||
KeyCtrl5 Key = 0x1D
|
||||
KeyCtrlRsqBracket Key = 0x1D
|
||||
KeyCtrl6 Key = 0x1E
|
||||
KeyCtrl7 Key = 0x1F
|
||||
KeyCtrlSlash Key = 0x1F
|
||||
KeyCtrlUnderscore Key = 0x1F
|
||||
KeySpace Key = 0x20
|
||||
KeyBackspace2 Key = 0x7F
|
||||
KeyCtrl8 Key = 0x7F
|
||||
)
|
||||
46
uiterm/label.go
Normal file
46
uiterm/label.go
Normal file
@@ -0,0 +1,46 @@
|
||||
package uiterm
|
||||
|
||||
import (
|
||||
"strings"
|
||||
|
||||
"github.com/nsf/termbox-go"
|
||||
)
|
||||
|
||||
type Label struct {
|
||||
Text string
|
||||
Fg Attribute
|
||||
Bg Attribute
|
||||
|
||||
x0, y0, x1, y1 int
|
||||
}
|
||||
|
||||
func (l *Label) SetActive(ui *Ui, active bool) {
|
||||
}
|
||||
|
||||
func (l *Label) SetBounds(ui *Ui, x0, y0, x1, y1 int) {
|
||||
l.x0 = x0
|
||||
l.y0 = y0
|
||||
l.x1 = x1
|
||||
l.y1 = y1
|
||||
}
|
||||
|
||||
func (l *Label) Draw(ui *Ui) {
|
||||
reader := strings.NewReader(l.Text)
|
||||
for y := l.y0; y < l.y1; y++ {
|
||||
for x := l.x0; x < l.x1; x++ {
|
||||
var chr rune
|
||||
if ch, _, err := reader.ReadRune(); err != nil {
|
||||
chr = ' '
|
||||
} else {
|
||||
chr = ch
|
||||
}
|
||||
termbox.SetCell(x, y, chr, termbox.Attribute(l.Fg), termbox.Attribute(l.Bg))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func (l *Label) KeyEvent(ui *Ui, mod Modifier, key Key) {
|
||||
}
|
||||
|
||||
func (l *Label) CharacterEvent(ui *Ui, chr rune) {
|
||||
}
|
||||
88
uiterm/textbox.go
Normal file
88
uiterm/textbox.go
Normal file
@@ -0,0 +1,88 @@
|
||||
package uiterm
|
||||
|
||||
import (
|
||||
"strings"
|
||||
"unicode/utf8"
|
||||
|
||||
"github.com/nsf/termbox-go"
|
||||
)
|
||||
|
||||
type InputFunc func(ui *Ui, textbox *Textbox, text string)
|
||||
|
||||
type Textbox struct {
|
||||
Text string
|
||||
Fg Attribute
|
||||
Bg Attribute
|
||||
|
||||
Input InputFunc
|
||||
|
||||
active bool
|
||||
x0, y0, x1, y1 int
|
||||
}
|
||||
|
||||
func (t *Textbox) SetBounds(ui *Ui, x0, y0, x1, y1 int) {
|
||||
t.x0 = x0
|
||||
t.y0 = y0
|
||||
t.x1 = x1
|
||||
t.y1 = y1
|
||||
}
|
||||
|
||||
func (t *Textbox) SetActive(ui *Ui, active bool) {
|
||||
t.active = active
|
||||
}
|
||||
|
||||
func (t *Textbox) Draw(ui *Ui) {
|
||||
var setCursor = false
|
||||
reader := strings.NewReader(t.Text)
|
||||
for y := t.y0; y < t.y1; y++ {
|
||||
for x := t.x0; x < t.x1; x++ {
|
||||
var chr rune
|
||||
if ch, _, err := reader.ReadRune(); err != nil {
|
||||
if t.active && !setCursor {
|
||||
termbox.SetCursor(x, y)
|
||||
setCursor = true
|
||||
}
|
||||
chr = ' '
|
||||
} else {
|
||||
chr = ch
|
||||
}
|
||||
termbox.SetCell(x, y, chr, termbox.Attribute(t.Fg), termbox.Attribute(t.Bg))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func (t *Textbox) KeyEvent(ui *Ui, mod Modifier, key Key) {
|
||||
redraw := false
|
||||
switch key {
|
||||
case KeyCtrlC:
|
||||
t.Text = ""
|
||||
redraw = true
|
||||
case KeyEnter:
|
||||
if t.Input != nil {
|
||||
t.Input(ui, t, t.Text)
|
||||
}
|
||||
t.Text = ""
|
||||
redraw = true
|
||||
case KeySpace:
|
||||
t.Text = t.Text + " "
|
||||
redraw = true
|
||||
case KeyBackspace:
|
||||
case KeyBackspace2:
|
||||
if len(t.Text) > 0 {
|
||||
if r, size := utf8.DecodeLastRuneInString(t.Text); r != utf8.RuneError {
|
||||
t.Text = t.Text[:len(t.Text)-size]
|
||||
redraw = true
|
||||
}
|
||||
}
|
||||
}
|
||||
if redraw {
|
||||
t.Draw(ui)
|
||||
termbox.Flush()
|
||||
}
|
||||
}
|
||||
|
||||
func (t *Textbox) CharacterEvent(ui *Ui, chr rune) {
|
||||
t.Text = t.Text + string(chr)
|
||||
t.Draw(ui)
|
||||
termbox.Flush()
|
||||
}
|
||||
141
uiterm/textview.go
Normal file
141
uiterm/textview.go
Normal file
@@ -0,0 +1,141 @@
|
||||
package uiterm
|
||||
|
||||
import (
|
||||
"strings"
|
||||
|
||||
"github.com/nsf/termbox-go"
|
||||
)
|
||||
|
||||
type Textview struct {
|
||||
Lines []string
|
||||
CurrentLine int
|
||||
Fg Attribute
|
||||
Bg Attribute
|
||||
|
||||
parsedLines []string
|
||||
x0, y0, x1, y1 int
|
||||
}
|
||||
|
||||
func (t *Textview) SetActive(ui *Ui, active bool) {
|
||||
}
|
||||
|
||||
func (t *Textview) SetBounds(ui *Ui, x0, y0, x1, y1 int) {
|
||||
t.x0 = x0
|
||||
t.y0 = y0
|
||||
t.x1 = x1
|
||||
t.y1 = y1
|
||||
t.updateParsedLines()
|
||||
}
|
||||
|
||||
func (t *Textview) ScrollUp() {
|
||||
if newLine := t.CurrentLine + 1; newLine < len(t.parsedLines) {
|
||||
t.CurrentLine = newLine
|
||||
}
|
||||
}
|
||||
|
||||
func (t *Textview) ScrollDown() {
|
||||
if newLine := t.CurrentLine - 1; newLine >= 0 {
|
||||
t.CurrentLine = newLine
|
||||
}
|
||||
}
|
||||
|
||||
func (t *Textview) ScrollTop() {
|
||||
if newLine := len(t.parsedLines) - 1; newLine > 0 {
|
||||
t.CurrentLine = newLine
|
||||
} else {
|
||||
t.CurrentLine = 0
|
||||
}
|
||||
}
|
||||
|
||||
func (t *Textview) ScrollBottom() {
|
||||
t.CurrentLine = 0
|
||||
}
|
||||
|
||||
func (t *Textview) updateParsedLines() {
|
||||
width := t.x1 - t.x0 - 3
|
||||
|
||||
if t.Lines == nil || width <= 0 {
|
||||
t.parsedLines = nil
|
||||
return
|
||||
}
|
||||
|
||||
parsed := make([]string, 0, len(t.Lines))
|
||||
for _, line := range t.Lines {
|
||||
current := ""
|
||||
chars := 0
|
||||
reader := strings.NewReader(line)
|
||||
for {
|
||||
if chars >= width {
|
||||
parsed = append(parsed, current)
|
||||
chars = 0
|
||||
current = ""
|
||||
}
|
||||
if reader.Len() <= 0 {
|
||||
if chars > 0 {
|
||||
parsed = append(parsed, current)
|
||||
}
|
||||
break
|
||||
}
|
||||
if ch, _, err := reader.ReadRune(); err == nil {
|
||||
current = current + string(ch)
|
||||
chars++
|
||||
}
|
||||
}
|
||||
}
|
||||
t.parsedLines = parsed
|
||||
}
|
||||
|
||||
func (t *Textview) AddLine(line string) {
|
||||
t.Lines = append(t.Lines, line)
|
||||
t.updateParsedLines()
|
||||
}
|
||||
|
||||
func (t *Textview) Clear() {
|
||||
t.Lines = nil
|
||||
t.CurrentLine = 0
|
||||
t.parsedLines = nil
|
||||
}
|
||||
|
||||
func (t *Textview) Draw(ui *Ui) {
|
||||
var reader *strings.Reader
|
||||
line := len(t.parsedLines) - 1 - t.CurrentLine
|
||||
if line < 0 {
|
||||
line = 0
|
||||
}
|
||||
totalLines := len(t.parsedLines)
|
||||
if totalLines == 0 {
|
||||
totalLines = 1
|
||||
}
|
||||
currentScrollLine := t.y1 - 1 - int((float32(t.CurrentLine)/float32(totalLines))*float32(t.y1-t.y0))
|
||||
for y := t.y1 - 1; y >= t.y0; y-- {
|
||||
if t.parsedLines != nil && line >= 0 {
|
||||
reader = strings.NewReader(t.parsedLines[line])
|
||||
} else {
|
||||
reader = nil
|
||||
}
|
||||
for x := t.x0; x < t.x1; x++ {
|
||||
var chr rune = ' '
|
||||
if x == t.x1-1 { // scrollbar
|
||||
if y == currentScrollLine {
|
||||
chr = '█'
|
||||
} else {
|
||||
chr = '░'
|
||||
}
|
||||
} else if x < t.x1-3 {
|
||||
if reader != nil {
|
||||
if ch, _, err := reader.ReadRune(); err == nil {
|
||||
chr = ch
|
||||
}
|
||||
}
|
||||
}
|
||||
termbox.SetCell(x, y, chr, termbox.Attribute(t.Fg), termbox.Attribute(t.Bg))
|
||||
}
|
||||
line--
|
||||
}
|
||||
}
|
||||
|
||||
func (t *Textview) KeyEvent(ui *Ui, mod Modifier, key Key) {
|
||||
}
|
||||
|
||||
func (t *Textview) CharacterEvent(ui *Ui, chr rune) {
|
||||
}
|
||||
140
uiterm/tree.go
Normal file
140
uiterm/tree.go
Normal file
@@ -0,0 +1,140 @@
|
||||
package uiterm
|
||||
|
||||
import (
|
||||
"strings"
|
||||
|
||||
"github.com/nsf/termbox-go"
|
||||
)
|
||||
|
||||
type TreeItem interface {
|
||||
TreeItemStyle(active bool) (Attribute, Attribute)
|
||||
String() string
|
||||
}
|
||||
|
||||
type renderedTreeItem struct {
|
||||
//String string
|
||||
Level int
|
||||
Item TreeItem
|
||||
}
|
||||
|
||||
type TreeFunc func(item TreeItem) []TreeItem
|
||||
type TreeListener func(ui *Ui, tree *Tree, item TreeItem)
|
||||
|
||||
type Tree struct {
|
||||
Fg Attribute
|
||||
Bg Attribute
|
||||
Generator TreeFunc
|
||||
Listener TreeListener
|
||||
|
||||
lines []renderedTreeItem
|
||||
activeLine int
|
||||
active bool
|
||||
x0, y0, x1, y1 int
|
||||
}
|
||||
|
||||
func bounded(i, lower, upper int) int {
|
||||
if i < lower {
|
||||
return lower
|
||||
}
|
||||
if i > upper {
|
||||
return upper
|
||||
}
|
||||
return i
|
||||
}
|
||||
|
||||
func (t *Tree) SetBounds(ui *Ui, x0, y0, x1, y1 int) {
|
||||
t.x0 = x0
|
||||
t.y0 = y0
|
||||
t.x1 = x1
|
||||
t.y1 = y1
|
||||
}
|
||||
|
||||
func (t *Tree) Rebuild() {
|
||||
if t.Generator == nil {
|
||||
t.lines = []renderedTreeItem{}
|
||||
return
|
||||
}
|
||||
|
||||
lines := []renderedTreeItem{}
|
||||
for _, item := range t.Generator(nil) {
|
||||
children := t.rebuild_rec(item, 0)
|
||||
if children != nil {
|
||||
lines = append(lines, children...)
|
||||
}
|
||||
}
|
||||
t.lines = lines
|
||||
t.activeLine = bounded(t.activeLine, 0, len(t.lines)-1)
|
||||
}
|
||||
|
||||
func (t *Tree) rebuild_rec(parent TreeItem, level int) []renderedTreeItem {
|
||||
if parent == nil {
|
||||
return nil
|
||||
}
|
||||
lines := []renderedTreeItem{
|
||||
renderedTreeItem{
|
||||
Level: level,
|
||||
Item: parent,
|
||||
},
|
||||
}
|
||||
for _, item := range t.Generator(parent) {
|
||||
children := t.rebuild_rec(item, level+1)
|
||||
if children != nil {
|
||||
lines = append(lines, children...)
|
||||
}
|
||||
}
|
||||
return lines
|
||||
}
|
||||
|
||||
func (t *Tree) Draw(ui *Ui) {
|
||||
if t.lines == nil {
|
||||
t.Rebuild()
|
||||
}
|
||||
|
||||
line := 0
|
||||
for y := t.y0; y < t.y1; y++ {
|
||||
var reader *strings.Reader
|
||||
var item TreeItem
|
||||
level := 0
|
||||
if line < len(t.lines) {
|
||||
item = t.lines[line].Item
|
||||
level = t.lines[line].Level
|
||||
reader = strings.NewReader(item.String())
|
||||
}
|
||||
for x := t.x0; x < t.x1; x++ {
|
||||
var chr rune = ' '
|
||||
fg := t.Fg
|
||||
bg := t.Bg
|
||||
dx := x - t.x0
|
||||
dy := y - t.y0
|
||||
if reader != nil && level*2 <= dx {
|
||||
if ch, _, err := reader.ReadRune(); err == nil {
|
||||
chr = ch
|
||||
fg, bg = item.TreeItemStyle(t.active && t.activeLine == dy)
|
||||
}
|
||||
}
|
||||
termbox.SetCell(x, y, chr, termbox.Attribute(fg), termbox.Attribute(bg))
|
||||
}
|
||||
line++
|
||||
}
|
||||
}
|
||||
|
||||
func (t *Tree) SetActive(ui *Ui, active bool) {
|
||||
t.active = active
|
||||
}
|
||||
|
||||
func (t *Tree) KeyEvent(ui *Ui, mod Modifier, key Key) {
|
||||
switch key {
|
||||
case KeyArrowUp:
|
||||
t.activeLine = bounded(t.activeLine-1, 0, len(t.lines)-1)
|
||||
case KeyArrowDown:
|
||||
t.activeLine = bounded(t.activeLine+1, 0, len(t.lines)-1)
|
||||
case KeyEnter:
|
||||
if t.Listener != nil && t.activeLine >= 0 && t.activeLine < len(t.lines) {
|
||||
t.Listener(ui, t, t.lines[t.activeLine].Item)
|
||||
}
|
||||
}
|
||||
ui.Refresh()
|
||||
}
|
||||
|
||||
func (t *Tree) CharacterEvent(ui *Ui, ch rune) {
|
||||
}
|
||||
170
uiterm/ui.go
Normal file
170
uiterm/ui.go
Normal file
@@ -0,0 +1,170 @@
|
||||
package uiterm
|
||||
|
||||
import (
|
||||
"github.com/nsf/termbox-go"
|
||||
)
|
||||
|
||||
type LayoutFunc func(ui *Ui, width, height int)
|
||||
|
||||
type KeyListener func(ui *Ui, key Key)
|
||||
|
||||
type UiManager interface {
|
||||
OnUiInitialize(ui *Ui)
|
||||
OnUiResize(ui *Ui, width, height int)
|
||||
}
|
||||
|
||||
type Ui struct {
|
||||
close chan bool
|
||||
manager UiManager
|
||||
|
||||
elements map[string]*uiElement
|
||||
activeElement *uiElement
|
||||
|
||||
keyListeners map[Key][]KeyListener
|
||||
|
||||
fg Attribute
|
||||
bg Attribute
|
||||
}
|
||||
|
||||
type uiElement struct {
|
||||
X0, Y0, X1, Y1 int
|
||||
View View
|
||||
}
|
||||
|
||||
func New(manager UiManager) *Ui {
|
||||
ui := &Ui{
|
||||
close: make(chan bool, 10),
|
||||
elements: make(map[string]*uiElement),
|
||||
manager: manager,
|
||||
keyListeners: make(map[Key][]KeyListener),
|
||||
}
|
||||
return ui
|
||||
}
|
||||
|
||||
func (ui *Ui) Close() {
|
||||
if termbox.IsInit {
|
||||
ui.close <- true
|
||||
}
|
||||
}
|
||||
|
||||
func (ui *Ui) Refresh() {
|
||||
if termbox.IsInit {
|
||||
termbox.Clear(termbox.Attribute(ui.fg), termbox.Attribute(ui.bg))
|
||||
termbox.HideCursor()
|
||||
for _, element := range ui.elements {
|
||||
element.View.Draw(ui)
|
||||
}
|
||||
termbox.Flush()
|
||||
}
|
||||
}
|
||||
|
||||
func (ui *Ui) Active() View {
|
||||
return ui.activeElement.View
|
||||
}
|
||||
|
||||
func (ui *Ui) SetActive(name string) {
|
||||
element, _ := ui.elements[name]
|
||||
if ui.activeElement != nil {
|
||||
ui.activeElement.View.SetActive(ui, false)
|
||||
}
|
||||
ui.activeElement = element
|
||||
if element != nil {
|
||||
element.View.SetActive(ui, true)
|
||||
}
|
||||
ui.Refresh()
|
||||
}
|
||||
|
||||
func (ui *Ui) SetClear(fg, bg Attribute) {
|
||||
ui.fg = fg
|
||||
ui.bg = bg
|
||||
}
|
||||
|
||||
func (ui *Ui) Run() error {
|
||||
if termbox.IsInit {
|
||||
return nil
|
||||
}
|
||||
if err := termbox.Init(); err != nil {
|
||||
return nil
|
||||
}
|
||||
defer termbox.Close()
|
||||
termbox.SetInputMode(termbox.InputAlt)
|
||||
|
||||
events := make(chan termbox.Event)
|
||||
go func() {
|
||||
for {
|
||||
events <- termbox.PollEvent()
|
||||
}
|
||||
}()
|
||||
|
||||
ui.manager.OnUiInitialize(ui)
|
||||
width, height := termbox.Size()
|
||||
ui.manager.OnUiResize(ui, width, height)
|
||||
ui.Refresh()
|
||||
|
||||
for {
|
||||
select {
|
||||
case <-ui.close:
|
||||
return nil
|
||||
case event := <-events:
|
||||
switch event.Type {
|
||||
case termbox.EventResize:
|
||||
ui.manager.OnUiResize(ui, event.Width, event.Height)
|
||||
ui.Refresh()
|
||||
case termbox.EventKey:
|
||||
if event.Ch != 0 {
|
||||
ui.onCharacterEvent(event.Ch)
|
||||
} else {
|
||||
ui.onKeyEvent(Modifier(event.Mod), Key(event.Key))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func (ui *Ui) onCharacterEvent(ch rune) {
|
||||
if ui.activeElement != nil {
|
||||
ui.activeElement.View.CharacterEvent(ui, ch)
|
||||
}
|
||||
}
|
||||
|
||||
func (ui *Ui) onKeyEvent(mod Modifier, key Key) {
|
||||
if ui.keyListeners[key] != nil {
|
||||
for _, listener := range ui.keyListeners[key] {
|
||||
listener(ui, key)
|
||||
}
|
||||
}
|
||||
if ui.activeElement != nil {
|
||||
ui.activeElement.View.KeyEvent(ui, mod, key)
|
||||
}
|
||||
}
|
||||
|
||||
func (ui *Ui) SetView(name string, x0, y0, x1, y1 int, view View) {
|
||||
if element, ok := ui.elements[name]; ok {
|
||||
element.X0 = x0
|
||||
element.Y0 = y0
|
||||
element.X1 = x1
|
||||
element.Y1 = y1
|
||||
view = element.View
|
||||
} else {
|
||||
ui.elements[name] = &uiElement{
|
||||
X0: x0,
|
||||
Y0: y0,
|
||||
X1: x1,
|
||||
Y1: y1,
|
||||
View: view,
|
||||
}
|
||||
}
|
||||
view.SetBounds(ui, x0, y0, x1, y1)
|
||||
}
|
||||
|
||||
func (ui *Ui) View(name string) View {
|
||||
if element, ok := ui.elements[name]; !ok {
|
||||
return nil
|
||||
} else {
|
||||
return element.View
|
||||
}
|
||||
}
|
||||
|
||||
func (ui *Ui) AddKeyListener(listener KeyListener, key Key) {
|
||||
ui.keyListeners[key] = append(ui.keyListeners[key], listener)
|
||||
}
|
||||
9
uiterm/view.go
Normal file
9
uiterm/view.go
Normal file
@@ -0,0 +1,9 @@
|
||||
package uiterm
|
||||
|
||||
type View interface {
|
||||
SetBounds(ui *Ui, x0, y0, x1, y1 int)
|
||||
Draw(ui *Ui)
|
||||
SetActive(ui *Ui, active bool)
|
||||
KeyEvent(ui *Ui, mod Modifier, key Key)
|
||||
CharacterEvent(ui *Ui, ch rune)
|
||||
}
|
||||
Reference in New Issue
Block a user