From b227bd52775cc094bfd54f578a9c7246b67a58ce Mon Sep 17 00:00:00 2001 From: Caleb Bassi Date: Thu, 6 Sep 2018 16:36:14 -0700 Subject: [PATCH] Rework event system * Timers should now be done through Go tickers * Reworked event names used in Handle() * Reworked Event type and payloads --- _examples/barchart.go | 2 +- _examples/dashboard.go | 38 +++- _examples/gauge.go | 2 +- _examples/grid.go | 41 ++-- _examples/linechart.go | 2 +- _examples/list.go | 2 +- _examples/mbarchart.go | 2 +- _examples/par.go | 2 +- _examples/piechart.go | 23 +- _examples/sparklines.go | 2 +- _examples/table.go | 2 +- _examples/tabs.go | 6 +- _examples/theme.go | 17 +- _examples/ttop.go | 40 ++-- _examples/wrapper.go | 2 +- events.go | 494 ++++++++++++++++------------------------ render.go | 21 +- widget.go | 4 +- 18 files changed, 318 insertions(+), 384 deletions(-) diff --git a/_examples/barchart.go b/_examples/barchart.go index 9e48f5e..d84af8f 100644 --- a/_examples/barchart.go +++ b/_examples/barchart.go @@ -24,7 +24,7 @@ func main() { ui.Render(bc) - ui.Handle("/sys/kbd/q", func(ui.Event) { + ui.Handle("q", "", func(ui.Event) { ui.StopLoop() }) diff --git a/_examples/dashboard.go b/_examples/dashboard.go index 1a14b23..aba764e 100644 --- a/_examples/dashboard.go +++ b/_examples/dashboard.go @@ -8,6 +8,7 @@ package main import ( "math" + "time" ui "github.com/gizak/termui" ) @@ -22,14 +23,21 @@ func main() { p.TextFgColor = ui.ColorWhite p.BorderLabel = "Text Box" p.BorderFg = ui.ColorCyan - p.Handle("/timer/1s", func(e ui.Event) { - cnt := e.Data.(ui.EvtTimer) - if cnt.Count%2 == 0 { - p.TextFgColor = ui.ColorRed - } else { - p.TextFgColor = ui.ColorWhite + + 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 } - }) + }() 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"} @@ -136,14 +144,20 @@ func main() { ui.Render(p, l, g, sls, lc, bc, lc2, p2) } - ui.Handle("/sys/kbd/q", func(ui.Event) { + ui.Handle("q", func(ui.Event) { ui.StopLoop() }) - ui.Handle("/timer/1s", func(e ui.Event) { - t := e.Data.(ui.EvtTimer) - draw(int(t.Count)) - }) + drawTicker := time.NewTicker(time.Second) + drawTickerCount := 1 + go func() { + for { + draw(drawTickerCount) + + drawTickerCount++ + <-drawTicker.C + } + }() ui.Loop() } diff --git a/_examples/gauge.go b/_examples/gauge.go index 0485241..f0835ca 100644 --- a/_examples/gauge.go +++ b/_examples/gauge.go @@ -71,7 +71,7 @@ func main() { ui.Render(g0, g1, g2, g3, g4) - ui.Handle("/sys/kbd/q", func(ui.Event) { + ui.Handle("q", func(ui.Event) { ui.StopLoop() }) diff --git a/_examples/grid.go b/_examples/grid.go index cf1f030..1cca0c1 100644 --- a/_examples/grid.go +++ b/_examples/grid.go @@ -8,6 +8,7 @@ package main import ( "math" + "time" ui "github.com/gizak/termui" ) @@ -91,29 +92,33 @@ func main() { ui.Render(ui.Body) - ui.Handle("/sys/kbd/q", func(ui.Event) { + ui.Handle("q", func(ui.Event) { ui.StopLoop() }) - ui.Handle("/timer/1s", func(e ui.Event) { - t := e.Data.(ui.EvtTimer) - i := t.Count - if i > 103 { - ui.StopLoop() - return + drawTicker := time.NewTicker(time.Second) + drawTickerCount := 1 + go func() { + for { + if drawTickerCount > 103 { + ui.StopLoop() + return + } + for _, g := range gs { + g.Percent = (g.Percent + 3) % 100 + } + sp.Lines[0].Data = spdata[:100+drawTickerCount] + lc.Data["default"] = sinps[2*drawTickerCount:] + ui.Render(ui.Body) + + drawTickerCount++ + <-drawTicker.C } + }() - for _, g := range gs { - g.Percent = (g.Percent + 3) % 100 - } - - sp.Lines[0].Data = spdata[:100+i] - lc.Data["default"] = sinps[2*i:] - ui.Render(ui.Body) - }) - - ui.Handle("/sys/wnd/resize", func(e ui.Event) { - ui.Body.Width = ui.TermWidth() + ui.Handle("", func(e ui.Event) { + payload := e.Payload.(ui.Resize) + ui.Body.Width = payload.Width ui.Body.Align() ui.Clear() ui.Render(ui.Body) diff --git a/_examples/linechart.go b/_examples/linechart.go index 6697f51..e8be1f7 100644 --- a/_examples/linechart.go +++ b/_examples/linechart.go @@ -63,7 +63,7 @@ func main() { ui.Render(lc0, lc1, lc2) - ui.Handle("/sys/kbd/q", func(ui.Event) { + ui.Handle("q", func(ui.Event) { ui.StopLoop() }) diff --git a/_examples/list.go b/_examples/list.go index 339aa75..cf68714 100644 --- a/_examples/list.go +++ b/_examples/list.go @@ -32,7 +32,7 @@ func main() { ui.Render(ls) - ui.Handle("/sys/kbd/q", func(ui.Event) { + ui.Handle("q", func(ui.Event) { ui.StopLoop() }) diff --git a/_examples/mbarchart.go b/_examples/mbarchart.go index 70b7d0f..75e9392 100644 --- a/_examples/mbarchart.go +++ b/_examples/mbarchart.go @@ -41,7 +41,7 @@ func main() { ui.Render(bc) - ui.Handle("/sys/kbd/q", func(ui.Event) { + ui.Handle("q", func(ui.Event) { ui.StopLoop() }) diff --git a/_examples/par.go b/_examples/par.go index da98c8a..4944a80 100644 --- a/_examples/par.go +++ b/_examples/par.go @@ -39,7 +39,7 @@ func main() { ui.Render(par0, par1, par2, par3) - ui.Handle("/sys/kbd/q", func(ui.Event) { + ui.Handle("q", func(ui.Event) { ui.StopLoop() }) diff --git a/_examples/piechart.go b/_examples/piechart.go index 1504625..53322a1 100644 --- a/_examples/piechart.go +++ b/_examples/piechart.go @@ -37,14 +37,21 @@ func main() { return fmt.Sprintf("%.02f", v) } - ui.Handle("/timer/1s", func(e ui.Event) { - if run { - pc.Data, pc.Offset = randomDataAndOffset() - ui.Render(pc) - } - }) + drawTicker := time.NewTicker(time.Second) + drawTickerCount := 1 + go func() { + for { + if run { + pc.Data, pc.Offset = randomDataAndOffset() + ui.Render(pc) + } - ui.Handle("/sys/kbd/s", func(ui.Event) { + drawTickerCount++ + <-drawTicker.C + } + }() + + ui.Handle("s", func(ui.Event) { run = !run if run { pc.BorderLabel = "Pie Chart" @@ -54,7 +61,7 @@ func main() { ui.Render(pc) }) - ui.Handle("/sys/kbd/q", func(ui.Event) { + ui.Handle("q", func(ui.Event) { ui.StopLoop() }) diff --git a/_examples/sparklines.go b/_examples/sparklines.go index 77baad7..7d94358 100644 --- a/_examples/sparklines.go +++ b/_examples/sparklines.go @@ -56,7 +56,7 @@ func main() { ui.Render(spls0, spls1, spls2) - ui.Handle("/sys/kbd/q", func(ui.Event) { + ui.Handle("q", func(ui.Event) { ui.StopLoop() }) diff --git a/_examples/table.go b/_examples/table.go index b746ad7..3b6396d 100644 --- a/_examples/table.go +++ b/_examples/table.go @@ -50,7 +50,7 @@ func main() { ui.Render(table2) - ui.Handle("/sys/kbd/q", func(ui.Event) { + ui.Handle("q", func(ui.Event) { ui.StopLoop() }) diff --git a/_examples/tabs.go b/_examples/tabs.go index c25cf6b..8915a12 100644 --- a/_examples/tabs.go +++ b/_examples/tabs.go @@ -58,17 +58,17 @@ func main() { ui.Render(header, tabpane) - ui.Handle("/sys/kbd/q", func(ui.Event) { + ui.Handle("q", func(ui.Event) { ui.StopLoop() }) - ui.Handle("/sys/kbd/j", func(ui.Event) { + ui.Handle("j", func(ui.Event) { tabpane.SetActiveLeft() ui.Clear() ui.Render(header, tabpane) }) - ui.Handle("/sys/kbd/k", func(ui.Event) { + ui.Handle("k", func(ui.Event) { tabpane.SetActiveRight() ui.Clear() ui.Render(header, tabpane) diff --git a/_examples/theme.go b/_examples/theme.go index 70cb8b5..1cc1659 100644 --- a/_examples/theme.go +++ b/_examples/theme.go @@ -8,6 +8,7 @@ package main import ( "math" + "time" ui "github.com/gizak/termui" ) @@ -134,14 +135,20 @@ func main() { ui.Render(p, list, g, sp, lc, bc, lc1, p1) - ui.Handle("/sys/kbd/q", func(ui.Event) { + ui.Handle("q", func(ui.Event) { ui.StopLoop() }) - ui.Handle("/timer/1s", func(e ui.Event) { - t := e.Data.(ui.EvtTimer) - draw(int(t.Count)) - }) + drawTicker := time.NewTicker(time.Second) + drawTickerCount := 1 + go func() { + for { + draw(drawTickerCount) + + drawTickerCount++ + <-drawTicker.C + } + }() ui.Loop() } diff --git a/_examples/ttop.go b/_examples/ttop.go index c049e25..68308ec 100644 --- a/_examples/ttop.go +++ b/_examples/ttop.go @@ -17,6 +17,7 @@ import ( "sort" "strconv" "strings" + "time" ui "github.com/gizak/termui" "github.com/gizak/termui/extra" @@ -330,35 +331,42 @@ func main() { ui.Render(header, tabpane) - ui.Handle("/sys/kbd/q", func(ui.Event) { + ui.Handle("q", func(ui.Event) { ui.StopLoop() }) - ui.Handle("/sys/kbd/j", func(ui.Event) { + ui.Handle("j", func(ui.Event) { tabpane.SetActiveLeft() ui.Render(header, tabpane) }) - ui.Handle("/sys/kbd/k", func(ui.Event) { + ui.Handle("k", func(ui.Event) { tabpane.SetActiveRight() ui.Render(header, tabpane) }) - ui.Handle("/timer/1s", func(e ui.Event) { - cs, errcs := getCpusStatsMap() - if errcs != nil { - panic(errcs) - } - cpusStats.tick(cs) - cpuTabElems.Update(*cpusStats) + drawTicker := time.NewTicker(time.Second) + drawTickerCount := 1 + go func() { + for { + cs, errcs := getCpusStatsMap() + if errcs != nil { + panic(errcs) + } + cpusStats.tick(cs) + cpuTabElems.Update(*cpusStats) - ms, errm := getMemStats() - if errm != nil { - panic(errm) + ms, errm := getMemStats() + if errm != nil { + panic(errm) + } + memTabElems.Update(ms) + ui.Render(header, tabpane) + + drawTickerCount++ + <-drawTicker.C } - memTabElems.Update(ms) - ui.Render(header, tabpane) - }) + }() ui.Loop() } diff --git a/_examples/wrapper.go b/_examples/wrapper.go index c63469b..734ab9a 100644 --- a/_examples/wrapper.go +++ b/_examples/wrapper.go @@ -25,7 +25,7 @@ func main() { ui.Render(p) - ui.Handle("/sys/kbd/q", func(ui.Event) { + ui.Handle("q", func(ui.Event) { ui.StopLoop() }) diff --git a/events.go b/events.go index 195202c..4ae1b80 100644 --- a/events.go +++ b/events.go @@ -5,60 +5,163 @@ package termui import ( - "path" "strconv" "sync" - "time" - "github.com/nsf/termbox-go" + tb "github.com/nsf/termbox-go" ) +/* +Here's the list of events which can be assigned handlers using Handle(): + mouse events: + + + keyboard events: + any uppercase or lowercase letter or a set of two letters like j or jj or J or JJ + etc + etc + + + + > etc + terminal events: + +*/ + +type EventType int + +const ( + KeyboardEvent EventType = iota + MouseEvent + 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 string - Path string - From string - To string - Data interface{} - Time int64 + Type EventType + ID string + Payload interface{} } -var sysEvtChs []chan Event - -type EvtKbd struct { - KeyStr string +// Mouse payload. +type Mouse struct { + Drag bool + X int + Y int } -func evtKbd(e termbox.Event) EvtKbd { - ek := EvtKbd{} +// Resize payload. +type Resize struct { + Width int + 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) + } +} + +// Loop gets events from termbox and passes them off to handleEvent. +// Stops when StopLoop is called. +func Loop() { + go func() { + for { + defaultES.eventQueue <- 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() +} + +// convertTermboxKeyboardEvent 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 convertTermboxKeyboardEvent(e tb.Event) Event { k := string(e.Ch) pre := "" mod := "" - if e.Mod == termbox.ModAlt { - mod = "M-" + if e.Mod == tb.ModAlt { + mod = " 0xFFFF-12 { k = "" } else if e.Key > 0xFFFF-25 { - ks := []string{"", "", "", "", "", "", "", "", "", ""} + ks := []string{"", "", "", "", "", "", "", "", "", ""} k = ks[0xFFFF-int(e.Key)-12] } if e.Key <= 0x7F { - pre = "C-" + pre = ""}, - termbox.KeyBackspace: {"", ""}, - termbox.KeyTab: {"", ""}, - termbox.KeyEnter: {"", ""}, - termbox.KeyEsc: {"", ""}, - termbox.KeyCtrlBackslash: {"C-", "\\"}, - termbox.KeyCtrlSlash: {"C-", "/"}, - termbox.KeySpace: {"", ""}, - termbox.KeyCtrl8: {"C-", "8"}, + kmap := map[tb.Key][2]string{ + tb.KeyCtrlSpace: {"C-", ""}, + tb.KeyBackspace: {"", ""}, + tb.KeyTab: {"", ""}, + tb.KeyEnter: {"", ""}, + tb.KeyEsc: {"", ""}, + tb.KeyCtrlBackslash: {"C-", "\\"}, + tb.KeyCtrlSlash: {"C-", "/"}, + tb.KeySpace: {"", ""}, + tb.KeyCtrl8: {"C-", "8"}, } if sk, ok := kmap[e.Key]; ok { pre = sk[0] @@ -67,288 +170,85 @@ func evtKbd(e termbox.Event) EvtKbd { } } - ek.KeyStr = pre + mod + k - return ek -} - -func crtTermboxEvt(e termbox.Event) Event { - systypemap := map[termbox.EventType]string{ - termbox.EventKey: "keyboard", - termbox.EventResize: "window", - termbox.EventMouse: "mouse", - termbox.EventError: "error", - termbox.EventInterrupt: "interrupt", - } - ne := Event{From: "/sys", Time: time.Now().Unix()} - typ := e.Type - ne.Type = systypemap[typ] - - switch typ { - case termbox.EventKey: - kbd := evtKbd(e) - ne.Path = "/sys/kbd/" + kbd.KeyStr - ne.Data = kbd - case termbox.EventResize: - wnd := EvtWnd{} - wnd.Width = e.Width - wnd.Height = e.Height - ne.Path = "/sys/wnd/resize" - ne.Data = wnd - case termbox.EventError: - err := EvtErr(e.Err) - ne.Path = "/sys/err" - ne.Data = err - case termbox.EventMouse: - m := evtMouse(e) - ne.Path = "/sys/mouse/" + m.Press - ne.Data = m - } - return ne -} - -type EvtWnd struct { - Width int - Height int -} - -type EvtMouse struct { - X int - Y int - Drag bool - Press string -} - -func evtMouse(e termbox.Event) EvtMouse { - em := EvtMouse{} - em.X = e.MouseX - em.Y = e.MouseY - - if e.Mod == termbox.ModMotion { - em.Drag = true + if pre != "" { + k += ">" } - switch e.Key { - case termbox.MouseLeft: - em.Press = "MouseLeft" - case termbox.MouseMiddle: - em.Press = "MouseMiddle" - case termbox.MouseRight: - em.Press = "MouseRight" + id := pre + mod + k - case termbox.MouseRelease: - em.Press = "MouseRelease" - - case termbox.MouseWheelUp: - em.Press = "MouseWheelUp" - case termbox.MouseWheelDown: - em.Press = "MouseWheelDown" - default: - em.Press = "Unknown_Mouse_Button" + return Event{ + Type: KeyboardEvent, + ID: id, } - - return em } -type EvtErr error +func convertTermboxMouseEvent(e tb.Event) Event { + mouseButtonMap := map[tb.Key]string{ + tb.MouseLeft: "", + tb.MouseMiddle: "", + tb.MouseRight: "", + tb.MouseRelease: "", + tb.MouseWheelUp: "", + tb.MouseWheelDown: "", + } -func hookTermboxEvt() { - for { - e := termbox.PollEvent() + converted, ok := mouseButtonMap[e.Key] + if !ok { + converted = "Unknown_Mouse_Button" + } - for _, c := range sysEvtChs { - go func(ch chan Event) { - ch <- crtTermboxEvt(e) - }(c) + Drag := false + if e.Mod == tb.ModMotion { + Drag = true + } + + return Event{ + Type: MouseEvent, + ID: converted, + Payload: Mouse{ + X: e.MouseX, + Y: e.MouseY, + Drag: Drag, + }, + } +} + +// convertTermboxEvent turns a termbox event into a termui event. +func convertTermboxEvent(e tb.Event) Event { + if e.Type == tb.EventError { + panic(e.Err) + } + + switch e.Type { + case tb.EventKey: + return convertTermboxKeyboardEvent(e) + case tb.EventMouse: + return convertTermboxMouseEvent(e) + case tb.EventResize: + return Event{ + Type: ResizeEvent, + ID: "", + Payload: Resize{ + Width: e.Width, + Height: e.Height, + }, } } -} -func NewSysEvtCh() chan Event { - ec := make(chan Event) - sysEvtChs = append(sysEvtChs, ec) - return ec -} - -var DefaultEvtStream *EvtStream - -type EvtStream struct { - sync.RWMutex - srcMap map[string]chan Event - stream chan Event - wg sync.WaitGroup - sigStopLoop chan Event - Handlers map[string]func(Event) - hook func(Event) -} - -func NewEvtStream() *EvtStream { - return &EvtStream{ - srcMap: make(map[string]chan Event), - stream: make(chan Event), - Handlers: make(map[string]func(Event)), - sigStopLoop: make(chan Event), - } -} - -func (es *EvtStream) Init() { - es.Merge("internal", es.sigStopLoop) - go func() { - es.wg.Wait() - close(es.stream) - }() -} - -func cleanPath(p string) string { - if p == "" { - return "/" - } - if p[0] != '/' { - p = "/" + p - } - return path.Clean(p) -} - -func isPathMatch(pattern, path string) bool { - if len(pattern) == 0 { - return false - } - n := len(pattern) - return len(path) >= n && path[0:n] == pattern -} - -func (es *EvtStream) Merge(name string, ec chan Event) { - es.Lock() - defer es.Unlock() - - es.wg.Add(1) - es.srcMap[name] = ec - - go func(a chan Event) { - for n := range a { - n.From = name - es.stream <- n - } - es.wg.Done() - }(ec) -} - -func (es *EvtStream) Handle(path string, handler func(Event)) { - es.Handlers[cleanPath(path)] = handler -} - -func findMatch(mux map[string]func(Event), path string) string { - n := -1 - pattern := "" - for m := range mux { - if !isPathMatch(m, path) { - continue - } - if len(m) > n { - pattern = m - n = len(m) - } - } - return pattern - -} - -// Remove all existing defined Handlers from the map -func (es *EvtStream) ResetHandlers() { - for Path, _ := range es.Handlers { - delete(es.Handlers, Path) - } - return -} - -func (es *EvtStream) match(path string) string { - return findMatch(es.Handlers, path) -} - -func (es *EvtStream) Hook(f func(Event)) { - es.hook = f -} - -func (es *EvtStream) Loop() { - for e := range es.stream { - switch e.Path { - case "/sig/stoploop": - return - } - go func(a Event) { - es.RLock() - defer es.RUnlock() - if pattern := es.match(a.Path); pattern != "" { - es.Handlers[pattern](a) - } - }(e) - if es.hook != nil { - es.hook(e) - } - } -} - -func (es *EvtStream) StopLoop() { - go func() { - e := Event{ - Path: "/sig/stoploop", - } - es.sigStopLoop <- e - }() -} - -func Merge(name string, ec chan Event) { - DefaultEvtStream.Merge(name, ec) -} - -func Handle(path string, handler func(Event)) { - DefaultEvtStream.Handle(path, handler) -} - -func Loop() { - DefaultEvtStream.Loop() -} - -func StopLoop() { - DefaultEvtStream.StopLoop() -} - -type EvtTimer struct { - Duration time.Duration - Count uint64 -} - -func NewTimerCh(du time.Duration) chan Event { - t := make(chan Event) - - go func(a chan Event) { - n := uint64(0) - for { - n++ - time.Sleep(du) - e := Event{} - e.Type = "timer" - e.Path = "/timer/" + du.String() - e.Time = time.Now().Unix() - e.Data = EvtTimer{ - Duration: du, - Count: n, - } - t <- e - - } - }(t) - return t + return Event{} } var DefaultHandler = func(e Event) { } -var usrEvtCh = make(chan Event) - -func SendCustomEvt(path string, data interface{}) { - e := Event{} - e.Path = path - e.Data = data - e.Time = time.Now().Unix() - usrEvtCh <- e +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() } diff --git a/render.go b/render.go index efea961..99f34bb 100644 --- a/render.go +++ b/render.go @@ -8,7 +8,6 @@ import ( "image" "runtime/debug" "sync" - "time" tb "github.com/nsf/termbox-go" ) @@ -25,10 +24,10 @@ func Init() error { return err } tb.SetInputMode(tb.InputEsc | tb.InputMouse) - DefaultEvtStream = NewEvtStream() + // DefaultEvtStream = NewEvtStream() - sysEvtChs = make([]chan Event, 0) - go hookTermboxEvt() + // sysEvtChs = make([]chan Event, 0) + // go hookTermboxEvt() renderJobs = make(chan []Bufferer) //renderLock = new(sync.RWMutex) @@ -39,19 +38,13 @@ func Init() error { Body.BgColor = ThemeAttr("bg") Body.Width = TermWidth() - DefaultEvtStream.Init() - DefaultEvtStream.Merge("termbox", NewSysEvtCh()) - DefaultEvtStream.Merge("timer", NewTimerCh(time.Second)) - DefaultEvtStream.Merge("custom", usrEvtCh) - - DefaultEvtStream.Handle("/", DefaultHandler) - DefaultEvtStream.Handle("/sys/wnd/resize", func(e Event) { - w := e.Data.(EvtWnd) - Body.Width = w.Width + Handle("", func(e Event) { + payload := e.Payload.(Resize) + Body.Width = payload.Width }) DefaultWgtMgr = NewWgtMgr() - DefaultEvtStream.Hook(DefaultWgtMgr.WgtHandlersHook()) + EventHook(DefaultWgtMgr.WgtHandlersHook()) go func() { for bs := range renderJobs { diff --git a/widget.go b/widget.go index 5a0d606..30ed6d4 100644 --- a/widget.go +++ b/widget.go @@ -75,8 +75,8 @@ func GenId() string { func (wm WgtMgr) WgtHandlersHook() func(Event) { return func(e Event) { for _, v := range wm { - if k := findMatch(v.Handlers, e.Path); k != "" { - v.Handlers[k](e) + if val, ok := v.Handlers[e.ID]; ok { + val(e) } } }