diff options
| -rw-r--r-- | gui/widget/focus.go | 84 | ||||
| -rw-r--r-- | gui/widget/widget.go | 24 | ||||
| -rw-r--r-- | main.go | 12 | ||||
| -rw-r--r-- | ui.go | 12 |
4 files changed, 80 insertions, 52 deletions
diff --git a/gui/widget/focus.go b/gui/widget/focus.go index e2d1074..f1bc06e 100644 --- a/gui/widget/focus.go +++ b/gui/widget/focus.go @@ -1,70 +1,98 @@ package widget -import "image" +import ( + "image" + "sync" +) -// Focus keeps track of the currently selected widget. -// A widget receives true when it gains focus and false when it loses focus. -type Focus struct { - Widgets [][]chan bool - p image.Point // coordinates of currently focused widget +type FocusMaster struct { + slaves [][]chan bool + mu sync.Mutex + p image.Point // coordinates of currently focused slave } -func NewFocus(rows []int) Focus { - f := Focus{ +type FocusSlave struct { + Focus <-chan bool + Mu *sync.Mutex +} + +func NewFocusMaster(rows []int) FocusMaster { + f := FocusMaster{ make([][]chan bool, len(rows)), + sync.Mutex{}, image.Point{}, } - for i := range f.Widgets { - f.Widgets[i] = make([]chan bool, rows[i]) - for j := range f.Widgets[i] { - f.Widgets[i][j] = make(chan bool) + for i := range f.slaves { + f.slaves[i] = make([]chan bool, rows[i]) + for j := range f.slaves[i] { + f.slaves[i][j] = make(chan bool) } } return f } -func (f *Focus) Close() { - for i := range f.Widgets { - for j := range f.Widgets[i] { - close(f.Widgets[i][j]) +func (f *FocusMaster) Slave(y, x int) FocusSlave { + return FocusSlave{f.slaves[y][x], &f.mu} +} + +func (f *FocusMaster) Close() { + for i := range f.slaves { + for j := range f.slaves[i] { + close(f.slaves[i][j]) } } } -func (f *Focus) Focus(focus bool) { - f.Widgets[f.p.Y][f.p.X] <- focus +func (f *FocusMaster) Focus(focus bool) { + f.slaves[f.p.Y][f.p.X] <- focus } -func (f *Focus) Left() { +func (f *FocusMaster) TryLeft() { + if !f.mu.TryLock() { + return + } + defer f.mu.Unlock() f.Focus(false) if f.p.X <= 0 { - f.p.X = len(f.Widgets[f.p.Y]) - 1 + f.p.X = len(f.slaves[f.p.Y]) - 1 } else { f.p.X-- } f.Focus(true) } -func (f *Focus) Right() { +func (f *FocusMaster) TryRight() { + if !f.mu.TryLock() { + return + } + defer f.mu.Unlock() f.Focus(false) - f.p.X = (f.p.X + 1) % len(f.Widgets[f.p.Y]) + f.p.X = (f.p.X + 1) % len(f.slaves[f.p.Y]) f.Focus(true) } -func (f *Focus) Up() { +func (f *FocusMaster) TryUp() { + if !f.mu.TryLock() { + return + } + defer f.mu.Unlock() f.Focus(false) if f.p.Y <= 0 { - f.p.Y = len(f.Widgets) - 1 + f.p.Y = len(f.slaves) - 1 } else { f.p.Y-- } - f.p.X = min(f.p.X, len(f.Widgets[f.p.Y])-1) + f.p.X = min(f.p.X, len(f.slaves[f.p.Y])-1) f.Focus(true) } -func (f *Focus) Down() { +func (f *FocusMaster) TryDown() { + if !f.mu.TryLock() { + return + } + defer f.mu.Unlock() f.Focus(false) - f.p.Y = (f.p.Y + 1) % len(f.Widgets) - f.p.X = min(f.p.X, len(f.Widgets[f.p.Y])-1) + f.p.Y = (f.p.Y + 1) % len(f.slaves) + f.p.X = min(f.p.X, len(f.slaves[f.p.Y])-1) f.Focus(true) } diff --git a/gui/widget/widget.go b/gui/widget/widget.go index ae09160..8c80551 100644 --- a/gui/widget/widget.go +++ b/gui/widget/widget.go @@ -41,14 +41,14 @@ func Label(text string, r image.Rectangle, env gui.Env, wg *sync.WaitGroup) { } } -func Input(val chan<- uint, r image.Rectangle, focusChan <-chan bool, env gui.Env, wg *sync.WaitGroup) { +func Input(val chan<- uint, r image.Rectangle, focus FocusSlave, env gui.Env, wg *sync.WaitGroup) { defer wg.Done() defer close(env.Draw()) defer close(val) - redraw := func(text []byte, focus bool) func(draw.Image) image.Rectangle { + redraw := func(text []byte, haveFocus bool) func(draw.Image) image.Rectangle { return func(drw draw.Image) image.Rectangle { - if focus { + if haveFocus { drawText(text, drw, r, GREEN, FOCUS_COLOR) } else { drawText(text, drw, r, GREEN, WHITE) @@ -57,14 +57,14 @@ func Input(val chan<- uint, r image.Rectangle, focusChan <-chan bool, env gui.En } } text := []byte{'0'} - focus := false + haveFocus := false - env.Draw() <- redraw(text, focus) + env.Draw() <- redraw(text, haveFocus) Loop: for { select { - case focus = <-focusChan: - env.Draw() <- redraw(text, focus) + case haveFocus = <-focus.Focus: + env.Draw() <- redraw(text, haveFocus) case event, ok := <-env.Events(): if !ok { // channel closed break Loop @@ -72,18 +72,18 @@ Loop: switch event := event.(type) { case win.WiFocus: if event.Focused { - env.Draw() <- redraw(text, focus) + env.Draw() <- redraw(text, haveFocus) } case win.KbType: - if focus && isDigit(event.Rune) { + if haveFocus && isDigit(event.Rune) { text = fmt.Appendf(text, "%c", event.Rune) - env.Draw() <- redraw(text, focus) + env.Draw() <- redraw(text, haveFocus) val <- atoi(text) } case win.KbDown: - if focus && event.Key == win.KeyBackspace && len(text) > 0 { + if haveFocus && event.Key == win.KeyBackspace && len(text) > 0 { text = text[:len(text)-1] - env.Draw() <- redraw(text, focus) + env.Draw() <- redraw(text, haveFocus) val <- atoi(text) } } @@ -28,7 +28,7 @@ func run() { wg := new(sync.WaitGroup) defer wg.Wait() - focus := widget.NewFocus([]int{1, POINTS, POINTS, POINTS, POINTS}) + focus := widget.NewFocusMaster([]int{1, POINTS, POINTS, POINTS, POINTS}) defer focus.Close() displacementChan := make(chan uint) @@ -87,7 +87,7 @@ func run() { eventLoop(env, &focus) } -func eventLoop(env gui.Env, focus *widget.Focus) { +func eventLoop(env gui.Env, focus *widget.FocusMaster) { for event := range env.Events() { switch event := event.(type) { case win.WiClose: @@ -97,13 +97,13 @@ func eventLoop(env gui.Env, focus *widget.Focus) { case 'q': return case 'h': - focus.Left() + focus.TryLeft() case 'j': - focus.Down() + focus.TryDown() case 'k': - focus.Up() + focus.TryUp() case 'l': - focus.Right() + focus.TryRight() } } } @@ -14,7 +14,7 @@ func spawnWidgets( displacementChan chan uint, rpmChan, veChan, imapChan, actChan [POINTS]chan uint, flowChan [POINTS]chan float64, - focus *widget.Focus, + focus *widget.FocusMaster, mux *gui.Mux, wg *sync.WaitGroup, ) { @@ -36,7 +36,7 @@ func spawnWidgets( go widget.Input( displacementChan, bounds[1], - focus.Widgets[0][0], + focus.Slave(0, 0), mux.MakeEnv(), wg, ) @@ -55,7 +55,7 @@ func spawnWidgets( go widget.Input( // speed rpmChan[i], bounds[3+i], - focus.Widgets[1][i], + focus.Slave(1, i), mux.MakeEnv(), wg, ) @@ -63,7 +63,7 @@ func spawnWidgets( go widget.Input( // VE veChan[i], bounds[4+POINTS+i], - focus.Widgets[2][i], + focus.Slave(2, i), mux.MakeEnv(), wg, ) @@ -71,7 +71,7 @@ func spawnWidgets( go widget.Input( // IMAP imapChan[i], bounds[5+2*POINTS+i], - focus.Widgets[3][i], + focus.Slave(3, i), mux.MakeEnv(), wg, ) @@ -79,7 +79,7 @@ func spawnWidgets( go widget.Input( // ACT actChan[i], bounds[6+3*POINTS+i], - focus.Widgets[4][i], + focus.Slave(4, i), mux.MakeEnv(), wg, ) |