From 6227b76b868273cb1ee912d5aea11323ba9d88cd Mon Sep 17 00:00:00 2001 From: lmika Date: Sat, 3 Jan 2015 23:09:35 +1100 Subject: [PATCH] Added a key event listener which components can implement, and have also mapped termio keys into local keys. --- main.go | 1 + ui/component.go | 7 +++++ ui/driver.go | 66 ++++++++++++++++++++++++++++++++++++++-- ui/grid.go | 14 +++++++++ ui/manager.go | 10 +++++- ui/stdcomps.go | 2 +- ui/termboxdriver.go | 74 +++++++++++++++++++++++++++++++++++++++++++-- 7 files changed, 167 insertions(+), 7 deletions(-) diff --git a/main.go b/main.go index 8c5acb8..0095489 100644 --- a/main.go +++ b/main.go @@ -22,6 +22,7 @@ func main() { clientArea := &ui.RelativeLayout{ Client: grid, South: statusLayout } uiManager.SetRootComponent(clientArea) + uiManager.SetFocusedComponent(grid) uiManager.Loop() /* diff --git a/ui/component.go b/ui/component.go index a6a66d9..9fe5e7d 100644 --- a/ui/component.go +++ b/ui/component.go @@ -20,6 +20,13 @@ type UiComponent interface { Remeasure(w, h int) (int, int) } +// A component implementing this interface can be given focus and will receive keyboard events. +type FocusableComponent interface { + + // Called when the component has focus and a key has been pressed + KeyPressed(key rune) +} + // ========================================================================== // UI context. diff --git a/ui/driver.go b/ui/driver.go index c2724d9..4823780 100644 --- a/ui/driver.go +++ b/ui/driver.go @@ -25,6 +25,68 @@ const ( AttrReverse ) + +// Special keys +const ( + KeyF1 rune = 0x8000 + iota + KeyF2 + KeyF3 + KeyF4 + KeyF5 + KeyF6 + KeyF7 + KeyF8 + KeyF9 + KeyF10 + KeyF11 + KeyF12 + KeyInsert + KeyDelete + KeyHome + KeyEnd + KeyPgup + KeyPgdn + KeyArrowUp + KeyArrowDown + KeyArrowLeft + KeyArrowRight + + KeyCtrlSpace + KeyCtrlA + KeyCtrlB + KeyCtrlC + KeyCtrlD + KeyCtrlE + KeyCtrlF + KeyCtrlG + KeyCtrlH + KeyCtrlI + KeyCtrlJ + KeyCtrlK + KeyCtrlL + KeyCtrlM + KeyCtrlN + KeyCtrlO + KeyCtrlP + KeyCtrlQ + KeyCtrlR + KeyCtrlS + KeyCtrlT + KeyCtrlU + KeyCtrlV + KeyCtrlW + KeyCtrlX + KeyCtrlY + KeyCtrlZ + KeyCtrl3 + KeyCtrl4 + KeyCtrl5 + KeyCtrl6 + KeyCtrl7 + KeyCtrl8 + KeySpace +) + // The type of events supported by the driver type EventType int @@ -34,14 +96,14 @@ const ( // Event when the window is resized EventResize - // Event indicating a key press. The event parameter is the key scancode? + // Event indicating a key press. The key is set in Ch EventKeyPress ) // Data from an event callback. type Event struct { Type EventType - Par int + Ch rune } diff --git a/ui/grid.go b/ui/grid.go index f1ae575..8bf8951 100644 --- a/ui/grid.go +++ b/ui/grid.go @@ -323,6 +323,20 @@ func (grid *Grid) Redraw(ctx *DrawContext) { grid.cellsWide, grid.cellsHigh = grid.renderGrid(ctx, viewportRect, 0, 0, 0, 0) } +// Called when the component has focus and a key has been pressed +func (grid *Grid) KeyPressed(key rune) { + if (key == 'i') || (key == KeyArrowUp) { + grid.MoveBy(0, -1) + } else if (key == 'k') || (key == KeyArrowDown) { + grid.MoveBy(0, 1) + } else if (key == 'j') || (key == KeyArrowLeft) { + grid.MoveBy(-1, 0) + } else if (key == 'l') || (key == KeyArrowRight) { + grid.MoveBy(1, 0) + } +} + + // -------------------------------------------------------------------------------------------- // Test Model diff --git a/ui/manager.go b/ui/manager.go index 7690037..7caaa7a 100644 --- a/ui/manager.go +++ b/ui/manager.go @@ -11,6 +11,7 @@ type Ui struct { // The root component rootComponent UiComponent + focusedComponent FocusableComponent drawContext *DrawContext driver Driver @@ -61,6 +62,11 @@ func (ui *Ui) SetRootComponent(comp UiComponent) { ui.Remeasure() } +// Sets the focused component +func (ui *Ui) SetFocusedComponent(newFocused FocusableComponent) { + ui.focusedComponent = newFocused +} + // Remeasures the UI func (ui *Ui) Remeasure() { ui.drawContext.X = 0 @@ -104,7 +110,9 @@ func (ui *Ui) Loop() { // TODO: If the event is a key-press, do something. if event.Type == EventKeyPress { - return + if ui.focusedComponent != nil { + ui.focusedComponent.KeyPressed(event.Ch) + } } else if event.Type == EventResize { // HACK: Find another way to refresh the size of the screen to prevent a full redraw. diff --git a/ui/stdcomps.go b/ui/stdcomps.go index 0870962..ab7a0d2 100644 --- a/ui/stdcomps.go +++ b/ui/stdcomps.go @@ -38,4 +38,4 @@ func (sbar *StatusBar) Redraw(context *DrawContext) { termbox.SetCell(x1, y, runeToPrint, termbox.AttrReverse, termbox.AttrReverse) } */ -} \ No newline at end of file +} diff --git a/ui/termboxdriver.go b/ui/termboxdriver.go index 79f4702..b9f8761 100644 --- a/ui/termboxdriver.go +++ b/ui/termboxdriver.go @@ -33,7 +33,7 @@ func (td *TermboxDriver) SetCell(x, y int, ch rune, fg, bg Attribute) { // Synchronizes the internal buffer with the real buffer func (td *TermboxDriver) Sync() { - termbox.Sync() + termbox.Flush() } // Wait for an event @@ -44,8 +44,76 @@ func (td *TermboxDriver) WaitForEvent() Event { case termbox.EventResize: return Event{EventResize, 0} case termbox.EventKey: - return Event{EventKeyPress, 0} + if tev.Ch != 0 { + return Event{EventKeyPress, tev.Ch} + } else if spec, hasSpec := termboxKeysToSpecialKeys[tev.Key] ; hasSpec { + return Event{EventKeyPress, spec} + } else { + return Event{EventNone, 0} + } default: return Event{EventNone, 0} } -} \ No newline at end of file +} + + +// Map from termbox Keys to driver key runes +var termboxKeysToSpecialKeys = map[termbox.Key]rune { + termbox.KeyF1: KeyF1, + termbox.KeyF2: KeyF2, + termbox.KeyF3: KeyF3, + termbox.KeyF4: KeyF4, + termbox.KeyF5: KeyF5, + termbox.KeyF6: KeyF6, + termbox.KeyF7: KeyF7, + termbox.KeyF8: KeyF8, + termbox.KeyF9: KeyF9, + termbox.KeyF10: KeyF10, + termbox.KeyF11: KeyF11, + termbox.KeyF12: KeyF12, + termbox.KeyInsert: KeyInsert, + termbox.KeyDelete: KeyDelete, + termbox.KeyHome: KeyHome, + termbox.KeyEnd: KeyEnd, + termbox.KeyPgup: KeyPgup, + termbox.KeyPgdn: KeyPgdn, + termbox.KeyArrowUp: KeyArrowUp, + termbox.KeyArrowDown: KeyArrowDown, + termbox.KeyArrowLeft: KeyArrowLeft, + termbox.KeyArrowRight: KeyArrowRight, + + termbox.KeyCtrlSpace: KeyCtrlSpace, + termbox.KeyCtrlA: KeyCtrlA, + termbox.KeyCtrlB: KeyCtrlB, + termbox.KeyCtrlC: KeyCtrlC, + termbox.KeyCtrlD: KeyCtrlD, + termbox.KeyCtrlE: KeyCtrlE, + termbox.KeyCtrlF: KeyCtrlF, + termbox.KeyCtrlG: KeyCtrlG, + termbox.KeyCtrlH: KeyCtrlH, + termbox.KeyCtrlI: KeyCtrlI, + termbox.KeyCtrlJ: KeyCtrlJ, + termbox.KeyCtrlK: KeyCtrlK, + termbox.KeyCtrlL: KeyCtrlL, + termbox.KeyCtrlM: KeyCtrlM, + termbox.KeyCtrlN: KeyCtrlN, + termbox.KeyCtrlO: KeyCtrlO, + termbox.KeyCtrlP: KeyCtrlP, + termbox.KeyCtrlQ: KeyCtrlQ, + termbox.KeyCtrlR: KeyCtrlR, + termbox.KeyCtrlS: KeyCtrlS, + termbox.KeyCtrlT: KeyCtrlT, + termbox.KeyCtrlU: KeyCtrlU, + termbox.KeyCtrlV: KeyCtrlV, + termbox.KeyCtrlW: KeyCtrlW, + termbox.KeyCtrlX: KeyCtrlX, + termbox.KeyCtrlY: KeyCtrlY, + termbox.KeyCtrlZ: KeyCtrlZ, + termbox.KeyCtrl3: KeyCtrl3, + termbox.KeyCtrl4: KeyCtrl4, + termbox.KeyCtrl5: KeyCtrl5, + termbox.KeyCtrl6: KeyCtrl6, + termbox.KeyCtrl7: KeyCtrl7, + termbox.KeySpace: KeySpace, + termbox.KeyCtrl8: KeyCtrl8, +}