Rework events (again)

This commit is contained in:
Caleb Bassi 2018-11-28 18:19:34 -08:00
parent 4022fa43e0
commit ea15e228f4
17 changed files with 190 additions and 294 deletions

View File

@ -27,9 +27,11 @@ func main() {
ui.Render(bc)
ui.Handle("q", "<Insert>", func(ui.Event) {
ui.StopLoop()
})
ui.Loop()
for {
e := <-ui.PollEvent()
switch e.ID {
case "q", "<C-c>":
return
}
}
}

View File

@ -20,27 +20,20 @@ func main() {
}
defer ui.Close()
p := ui.NewPar(":PRESS q TO QUIT DEMO")
p := ui.NewPar("PRESS q TO QUIT DEMO")
p.Height = 3
p.Width = 50
p.TextFgColor = ui.ColorWhite
p.BorderLabel = "Text Box"
p.BorderFg = ui.ColorCyan
pTicker := time.NewTicker(time.Second)
pTickerCount := 1
go func() {
for {
if pTickerCount%2 == 0 {
p.TextFgColor = ui.ColorRed
} else {
p.TextFgColor = ui.ColorWhite
}
pTickerCount++
<-pTicker.C
updateP := func(count int) {
if count%2 == 0 {
p.TextFgColor = ui.ColorRed
} else {
p.TextFgColor = ui.ColorWhite
}
}()
}
listData := []string{"[0] gizak/termui", "[1] editbox.go", "[2] interrupt.go", "[3] keyboard.go", "[4] output.go", "[5] random_out.go", "[6] dashboard.go", "[7] nsf/termbox-go"}
@ -147,20 +140,18 @@ func main() {
ui.Render(p, l, g, sls, lc, bc, lc2, p2)
}
ui.Handle("q", func(ui.Event) {
ui.StopLoop()
})
drawTicker := time.NewTicker(time.Second)
drawTickerCount := 1
go func() {
for {
draw(drawTickerCount)
drawTickerCount++
<-drawTicker.C
tickerCount := 1
for {
select {
case e := <-ui.PollEvent():
switch e.ID {
case "q", "<C-c>":
return
}
case <-time.NewTicker(time.Second).C:
updateP(tickerCount)
draw(tickerCount)
tickerCount++
}
}()
ui.Loop()
}
}

View File

@ -74,9 +74,11 @@ func main() {
ui.Render(g0, g1, g2, g3, g4)
ui.Handle("q", func(ui.Event) {
ui.StopLoop()
})
ui.Loop()
for {
e := <-ui.PollEvent()
switch e.ID {
case "q", "<C-c>":
return
}
}
}

View File

@ -95,37 +95,31 @@ func main() {
ui.Render(ui.Body)
ui.Handle("q", func(ui.Event) {
ui.StopLoop()
})
drawTicker := time.NewTicker(time.Second)
drawTickerCount := 1
go func() {
for {
if drawTickerCount > 103 {
ui.StopLoop()
tickerCount := 1
for {
select {
case e := <-ui.PollEvent():
switch e.ID {
case "q", "<C-c>":
return
case "<Resize>":
payload := e.Payload.(ui.Resize)
ui.Body.Width = payload.Width
ui.Body.Align()
ui.Clear()
ui.Render(ui.Body)
}
case <-time.NewTicker(time.Second).C:
if tickerCount > 103 {
return
}
for _, g := range gs {
g.Percent = (g.Percent + 3) % 100
}
sp.Lines[0].Data = spdata[:100+drawTickerCount]
lc.Data["default"] = sinps[2*drawTickerCount:]
sp.Lines[0].Data = spdata[:100+tickerCount]
lc.Data["default"] = sinps[2*tickerCount:]
ui.Render(ui.Body)
drawTickerCount++
<-drawTicker.C
tickerCount++
}
}()
ui.Handle("<Resize>", func(e ui.Event) {
payload := e.Payload.(ui.Resize)
ui.Body.Width = payload.Width
ui.Body.Align()
ui.Clear()
ui.Render(ui.Body)
})
ui.Loop()
}
}

View File

@ -66,9 +66,11 @@ func main() {
ui.Render(lc0, lc1, lc2)
ui.Handle("q", func(ui.Event) {
ui.StopLoop()
})
ui.Loop()
for {
e := <-ui.PollEvent()
switch e.ID {
case "q", "<C-c>":
return
}
}
}

View File

@ -35,9 +35,11 @@ func main() {
ui.Render(ls)
ui.Handle("q", func(ui.Event) {
ui.StopLoop()
})
ui.Loop()
for {
e := <-ui.PollEvent()
switch e.ID {
case "q", "<C-c>":
return
}
}
}

View File

@ -44,10 +44,11 @@ func main() {
ui.Render(bc)
ui.Handle("q", func(ui.Event) {
ui.StopLoop()
})
ui.Loop()
for {
e := <-ui.PollEvent()
switch e.ID {
case "q", "<C-c>":
return
}
}
}

View File

@ -42,10 +42,11 @@ func main() {
ui.Render(par0, par1, par2, par3)
ui.Handle("q", func(ui.Event) {
ui.StopLoop()
})
ui.Loop()
for {
e := <-ui.PollEvent()
switch e.ID {
case "q", "<C-c>":
return
}
}
}

View File

@ -40,21 +40,7 @@ func main() {
return fmt.Sprintf("%.02f", v)
}
drawTicker := time.NewTicker(time.Second)
drawTickerCount := 1
go func() {
for {
if run {
pc.Data, pc.Offset = randomDataAndOffset()
ui.Render(pc)
}
drawTickerCount++
<-drawTicker.C
}
}()
ui.Handle("s", func(ui.Event) {
pause := func() {
run = !run
if run {
pc.BorderLabel = "Pie Chart"
@ -62,13 +48,24 @@ func main() {
pc.BorderLabel = "Pie Chart (Stopped)"
}
ui.Render(pc)
})
ui.Handle("q", func(ui.Event) {
ui.StopLoop()
})
}
ui.Render(pc)
ui.Loop()
for {
select {
case e := <-ui.PollEvent():
switch e.ID {
case "q", "<C-c>":
return
case "s":
pause()
}
case <-time.NewTicker(time.Second).C:
if run {
pc.Data, pc.Offset = randomDataAndOffset()
ui.Render(pc)
}
}
}
}

View File

@ -59,9 +59,11 @@ func main() {
ui.Render(spls0, spls1, spls2)
ui.Handle("q", func(ui.Event) {
ui.StopLoop()
})
ui.Loop()
for {
e := <-ui.PollEvent()
switch e.ID {
case "q", "<C-c>":
return
}
}
}

View File

@ -53,9 +53,11 @@ func main() {
ui.Render(table2)
ui.Handle("q", func(ui.Event) {
ui.StopLoop()
})
ui.Loop()
for {
e := <-ui.PollEvent()
switch e.ID {
case "q", "<C-c>":
return
}
}
}

View File

@ -18,14 +18,14 @@ func main() {
}
defer ui.Close()
header := ui.NewPar("Press q to quit, Press j or k to switch tabs")
header := ui.NewPar("Press q to quit, Press h or l to switch tabs")
header.Height = 1
header.Width = 50
header.Border = false
header.TextBgColor = ui.ColorBlue
tab1 := extra.NewTab("pierwszy")
par2 := ui.NewPar("Press q to quit\nPress j or k to switch tabs\n")
par2 := ui.NewPar("Press q to quit\nPress h or l to switch tabs\n")
par2.Height = 5
par2.Width = 37
par2.Y = 0
@ -61,21 +61,19 @@ func main() {
ui.Render(header, tabpane)
ui.Handle("q", func(ui.Event) {
ui.StopLoop()
})
ui.Handle("j", func(ui.Event) {
tabpane.SetActiveLeft()
ui.Clear()
ui.Render(header, tabpane)
})
ui.Handle("k", func(ui.Event) {
tabpane.SetActiveRight()
ui.Clear()
ui.Render(header, tabpane)
})
ui.Loop()
for {
e := <-ui.PollEvent()
switch e.ID {
case "q", "<C-c>":
return
case "h":
tabpane.SetActiveLeft()
ui.Clear()
ui.Render(header, tabpane)
case "l":
tabpane.SetActiveRight()
ui.Clear()
ui.Render(header, tabpane)
}
}
}

View File

@ -138,20 +138,17 @@ func main() {
ui.Render(p, list, g, sp, lc, bc, lc1, p1)
ui.Handle("q", func(ui.Event) {
ui.StopLoop()
})
drawTicker := time.NewTicker(time.Second)
drawTickerCount := 1
go func() {
for {
draw(drawTickerCount)
drawTickerCount++
<-drawTicker.C
tickerCount := 1
for {
select {
case e := <-ui.PollEvent():
switch e.ID {
case "q", "<C-c>":
return
}
case <-time.NewTicker(time.Second).C:
draw(tickerCount)
tickerCount++
}
}()
ui.Loop()
}
}

View File

@ -284,7 +284,7 @@ func main() {
termWidth := 70
header := ui.NewPar("Press q to quit, Press j or k to switch tabs")
header := ui.NewPar("Press q to quit, Press h or l to switch tabs")
header.Height = 1
header.Width = 50
header.Border = false
@ -334,24 +334,21 @@ func main() {
ui.Render(header, tabpane)
ui.Handle("q", func(ui.Event) {
ui.StopLoop()
})
ui.Handle("j", func(ui.Event) {
tabpane.SetActiveLeft()
ui.Render(header, tabpane)
})
ui.Handle("k", func(ui.Event) {
tabpane.SetActiveRight()
ui.Render(header, tabpane)
})
drawTicker := time.NewTicker(time.Second)
drawTickerCount := 1
go func() {
for {
tickerCount := 1
for {
select {
case e := <-ui.PollEvent():
switch e.ID {
case "q", "<C-c>":
return
case "h":
tabpane.SetActiveLeft()
ui.Render(header, tabpane)
case "l":
tabpane.SetActiveRight()
ui.Render(header, tabpane)
}
case <-time.NewTicker(time.Second).C:
cs, errcs := getCpusStatsMap()
if errcs != nil {
panic(errcs)
@ -365,11 +362,7 @@ func main() {
}
memTabElems.Update(ms)
ui.Render(header, tabpane)
drawTickerCount++
<-drawTicker.C
tickerCount++
}
}()
ui.Loop()
}
}

View File

@ -24,13 +24,14 @@ func main() {
p.TextFgColor = ui.ColorWhite
p.BorderLabel = "Text Box with Wrapping"
p.BorderFg = ui.ColorCyan
//p.Border = false
ui.Render(p)
ui.Handle("q", func(ui.Event) {
ui.StopLoop()
})
ui.Loop()
for {
e := <-ui.PollEvent()
switch e.ID {
case "q", "<C-c>":
return
}
}
}

118
events.go
View File

@ -6,13 +6,12 @@ package termui
import (
"strconv"
"sync"
tb "github.com/nsf/termbox-go"
)
/*
Here's the list of events which can be assigned handlers using Handle():
List of events:
mouse events:
<MouseLeft> <MouseRight> <MouseMiddle>
<MouseWheelUp> <MouseWheelDown>
@ -26,9 +25,6 @@ Here's the list of events which can be assigned handlers using Handle():
<C-<Space>> etc
terminal events:
<Resize>
meta events:
<Keyboard>
<Mouse>
*/
type EventType int
@ -39,22 +35,6 @@ const (
ResizeEvent
)
type eventStream struct {
sync.RWMutex
handlers map[string]func(Event)
stopLoop chan bool
eventQueue chan tb.Event // list of events from termbox
hook func(Event)
}
var defaultES = eventStream{
handlers: make(map[string]func(Event)),
stopLoop: make(chan bool, 1),
eventQueue: make(chan tb.Event),
hook: DefaultHandler,
}
// Event contains an ID used for Handle() and an optional payload.
type Event struct {
Type EventType
ID string
@ -74,74 +54,15 @@ type Resize struct {
Height int
}
// handleEvent calls the approriate callback function if there is one.
func handleEvent(e Event) {
if val, ok := defaultES.handlers[e.ID]; ok {
val(e)
}
switch e.Type {
case KeyboardEvent:
if val, ok := defaultES.handlers["<Keyboard>"]; ok {
val(e)
}
case MouseEvent:
if val, ok := defaultES.handlers["<Mouse>"]; ok {
val(e)
}
}
}
var pollingChannels [](chan Event)
// Loop gets events from termbox and passes them off to handleEvent.
// Stops when StopLoop is called.
func Loop() {
// PollEvent gets events from termbox, converts them, then sends them to each of its channels.
func PollEvent() <-chan Event {
ch := make(chan Event)
go func() {
for {
defaultES.eventQueue <- tb.PollEvent()
}
ch <- convertTermboxEvent(tb.PollEvent())
}()
for {
select {
case <-defaultES.stopLoop:
return
case e := <-defaultES.eventQueue:
ne := convertTermboxEvent(e)
defaultES.RLock()
handleEvent(ne)
defaultES.hook(ne)
defaultES.RUnlock()
}
}
}
// StopLoop stops the event loop.
func StopLoop() {
defaultES.stopLoop <- true
}
// Handle assigns event names to their handlers. Takes a string, strings, or a slice of strings, and a function.
func Handle(things ...interface{}) {
function := things[len(things)-1].(func(Event))
for _, thing := range things {
if value, ok := thing.(string); ok {
defaultES.Lock()
defaultES.handlers[value] = function
defaultES.Unlock()
}
if value, ok := thing.([]string); ok {
defaultES.Lock()
for _, name := range value {
defaultES.handlers[name] = function
}
defaultES.Unlock()
}
}
}
func EventHook(f func(Event)) {
defaultES.Lock()
defaultES.hook = f
defaultES.Unlock()
return ch
}
// convertTermboxKeyboardEvent converts a termbox keyboard event to a more friendly string format.
@ -232,13 +153,15 @@ func convertTermboxEvent(e tb.Event) Event {
panic(e.Err)
}
var event Event
switch e.Type {
case tb.EventKey:
return convertTermboxKeyboardEvent(e)
event = convertTermboxKeyboardEvent(e)
case tb.EventMouse:
return convertTermboxMouseEvent(e)
event = convertTermboxMouseEvent(e)
case tb.EventResize:
return Event{
event = Event{
Type: ResizeEvent,
ID: "<Resize>",
Payload: Resize{
@ -248,20 +171,5 @@ func convertTermboxEvent(e tb.Event) Event {
}
}
return Event{}
}
var DefaultHandler = func(e Event) {
}
func ResetHandlers() {
defaultES.Lock()
defaultES.handlers = make(map[string]func(Event))
defaultES.Unlock()
}
func ResetHandler(handle string) {
defaultES.Lock()
delete(defaultES.handlers, handle)
defaultES.Unlock()
return event
}

View File

@ -38,13 +38,16 @@ func Init() error {
Body.BgColor = ThemeAttr("bg")
Body.Width = TermWidth()
Handle("<Resize>", func(e Event) {
payload := e.Payload.(Resize)
Body.Width = payload.Width
})
// resizeCh := Handle("<Resize>")
// go func() {
// for e := range resizeCh {
// payload := e.Payload.(Resize)
// Body.Width = payload.Width
// }
// }()
DefaultWgtMgr = NewWgtMgr()
EventHook(DefaultWgtMgr.WgtHandlersHook())
// DefaultWgtMgr = NewWgtMgr()
// EventHook(DefaultWgtMgr.WgtHandlersHook())
go func() {
for bs := range renderJobs {