diff --git a/events.go b/events.go new file mode 100644 index 0000000..8ff09ea --- /dev/null +++ b/events.go @@ -0,0 +1,200 @@ +package termui + +import "github.com/nsf/termbox-go" +import "unsafe" + +/***********************************termbox-go**************************************/ + +type ( + EventType uint8 + Modifier uint8 + Key uint16 +) + +// This type represents a termbox event. The 'Mod', 'Key' and 'Ch' fields are +// valid if 'Type' is EventKey. The 'Width' and 'Height' fields are valid if +// 'Type' is EventResize. The 'Err' field is valid if 'Type' is EventError. +type Event struct { + Type EventType // one of Event* constants + Mod Modifier // one of Mod* constants or 0 + Key Key // one of Key* constants, invalid if 'Ch' is not 0 + Ch rune // a unicode character + Width int // width of the screen + Height int // height of the screen + Err error // error in case if input failed + MouseX int // x coord of mouse + MouseY int // y coord of mouse + N int // number of bytes written when getting a raw event +} + +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 + key_min // see terminfo + 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 +) + +// Alt modifier constant, see Event.Mod field and SetInputMode function. +const ( + ModAlt Modifier = 0x01 +) + +// Event type. See Event.Type field. +const ( + EventKey EventType = iota + EventResize + EventMouse + EventError + EventInterrupt + EventRaw + EventNone +) + +/**************************************end**************************************/ + +// convert termbox.Event to termui.Event +func uiEvt(e termbox.Event) Event { + return *(*Event)(unsafe.Pointer(&e)) +} + +var evtChs = make([]chan Event, 0) + +// EventCh returns an output-only event channel. +// This function can be called many times (multiplexer). +func EventCh() <-chan Event { + out := make(chan Event) + evtChs = append(evtChs, out) + return out +} + +// turn on event listener +func evtListen() { + go func() { + for { + e := termbox.PollEvent() + // dispatch + for _, c := range evtChs { + go func(ch chan Event) { + ch <- uiEvt(e) + }(c) + } + } + }() +} + +/* +// EventHandlers is a handler sequence +var EventHandlers []func(Event) + +var signalQuit = make(chan bool) + +// Quit sends quit signal to terminate termui +func Quit() { + signalQuit <- true +} + +// Wait listening to signalQuit, block operation. +func Wait() { + <-signalQuit +} + +// RegEvtHandler register function into TSEventHandler sequence. +func RegEvtHandler(fn func(Event)) { + EventHandlers = append(EventHandlers, fn) +} + +// EventLoop handles all events and +// redirects every event to callbacks in EventHandlers +func EventLoop() { + evt := make(chan termbox.Event) + + go func() { + for { + evt <- termbox.PollEvent() + } + }() + + for { + select { + case c := <-signalQuit: + defer func() { signalQuit <- c }() + return + case e := <-evt: + for _, fn := range EventHandlers { + fn(uiEvt(e)) + } + } + } +} +*/ diff --git a/example/barchart.go b/example/barchart.go index 85963a9..83947f5 100644 --- a/example/barchart.go +++ b/example/barchart.go @@ -7,7 +7,6 @@ package main import "github.com/gizak/termui" -import "github.com/nsf/termbox-go" func main() { err := termui.Init() @@ -32,5 +31,5 @@ func main() { termui.Render(bc) - termbox.PollEvent() + <-termui.EventCh() } diff --git a/example/dashboard.go b/example/dashboard.go index 76531cd..d855ef2 100644 --- a/example/dashboard.go +++ b/example/dashboard.go @@ -7,7 +7,6 @@ package main import ui "github.com/gizak/termui" -import tm "github.com/nsf/termbox-go" import "math" import "time" @@ -128,18 +127,13 @@ func main() { ui.Render(p, list, g, sp, lc, bc, lc1, p1) } - evt := make(chan tm.Event) - go func() { - for { - evt <- tm.PollEvent() - } - }() + evt := ui.EventCh() i := 0 for { select { case e := <-evt: - if e.Type == tm.EventKey && e.Ch == 'q' { + if e.Type == ui.EventKey && e.Ch == 'q' { return } default: diff --git a/example/gauge.go b/example/gauge.go index 213f66d..06e4946 100644 --- a/example/gauge.go +++ b/example/gauge.go @@ -7,7 +7,6 @@ package main import "github.com/gizak/termui" -import "github.com/nsf/termbox-go" func main() { err := termui.Init() @@ -50,5 +49,5 @@ func main() { termui.Render(g0, g1, g2) - termbox.PollEvent() + <-termui.EventCh() } diff --git a/example/grid.go b/example/grid.go index 73b8799..84dc929 100644 --- a/example/grid.go +++ b/example/grid.go @@ -7,7 +7,6 @@ package main import ui "github.com/gizak/termui" -import tm "github.com/nsf/termbox-go" import "math" import "time" @@ -99,21 +98,16 @@ func main() { ui.Render(ui.Body) } - evt := make(chan tm.Event) - go func() { - for { - evt <- tm.PollEvent() - } - }() + evt := ui.EventCh() i := 0 for { select { case e := <-evt: - if e.Type == tm.EventKey && e.Ch == 'q' { + if e.Type == ui.EventKey && e.Ch == 'q' { return } - if e.Type == tm.EventResize { + if e.Type == ui.EventResize { ui.Body.Width = ui.TermWidth() ui.Body.Align() } diff --git a/example/linechart.go b/example/linechart.go index e6c614d..1db5434 100644 --- a/example/linechart.go +++ b/example/linechart.go @@ -11,7 +11,6 @@ import ( "github.com/gizak/termui" ) -import "github.com/nsf/termbox-go" func main() { err := termui.Init() @@ -65,5 +64,5 @@ func main() { termui.Render(lc0, lc1, lc2) - termbox.PollEvent() + <-termui.EventCh() } diff --git a/example/list.go b/example/list.go index 9dcaeea..d33a361 100644 --- a/example/list.go +++ b/example/list.go @@ -7,7 +7,6 @@ package main import "github.com/gizak/termui" -import "github.com/nsf/termbox-go" func main() { err := termui.Init() @@ -38,5 +37,5 @@ func main() { termui.Render(ls) - termbox.PollEvent() + <-termui.EventCh() } diff --git a/example/par.go b/example/par.go index c56660e..ffbc60a 100644 --- a/example/par.go +++ b/example/par.go @@ -7,7 +7,6 @@ package main import "github.com/gizak/termui" -import "github.com/nsf/termbox-go" func main() { err := termui.Init() @@ -45,5 +44,5 @@ func main() { termui.Render(par0, par1, par2, par3) - termbox.PollEvent() + <-termui.EventCh() } diff --git a/example/sparklines.go b/example/sparklines.go index 50fe5f6..f04baf5 100644 --- a/example/sparklines.go +++ b/example/sparklines.go @@ -7,7 +7,6 @@ package main import "github.com/gizak/termui" -import "github.com/nsf/termbox-go" func main() { err := termui.Init() @@ -62,5 +61,5 @@ func main() { termui.Render(spls0, spls1, spls2) - termbox.PollEvent() + <-termui.EventCh() } diff --git a/example/theme.go b/example/theme.go index 039cd2a..f3695c2 100644 --- a/example/theme.go +++ b/example/theme.go @@ -7,7 +7,6 @@ package main import ui "github.com/gizak/termui" -import tm "github.com/nsf/termbox-go" import "math" import "time" @@ -124,18 +123,12 @@ func main() { ui.Render(p, list, g, sp, lc, bc, lc1, p1) } - evt := make(chan tm.Event) - go func() { - for { - evt <- tm.PollEvent() - } - }() - + evt := EventCh() i := 0 for { select { case e := <-evt: - if e.Type == tm.EventKey && e.Ch == 'q' { + if e.Type == ui.EventKey && e.Ch == 'q' { return } default: diff --git a/render.go b/render.go index df09a00..735fe5b 100644 --- a/render.go +++ b/render.go @@ -18,10 +18,11 @@ func Init() error { Body.X = 0 Body.Y = 0 Body.BgColor = theme.BodyBg - defer (func() { + defer func() { w, _ := tm.Size() Body.Width = w - })() + evtListen() + }() return tm.Init() }