7 "github.com/nsf/termbox-go"
10 type KeyListener func(ui *Ui, key Key)
12 type UiManager interface {
13 OnUiInitialize(ui *Ui)
14 OnUiResize(ui *Ui, width, height int)
25 elements map[string]*uiElement
26 activeElement *uiElement
28 keyListeners map[Key][]KeyListener
31 type uiElement struct {
37 func New(manager UiManager) *Ui {
39 close: make(chan bool, 10),
40 elements: make(map[string]*uiElement),
42 keyListeners: make(map[Key][]KeyListener),
47 func (ui *Ui) Close() {
53 func (ui *Ui) Refresh() {
58 termbox.Clear(termbox.Attribute(ui.Fg), termbox.Attribute(ui.Bg))
60 for _, element := range ui.elements {
66 func (ui *Ui) beginDraw() {
67 atomic.AddInt32(&ui.drawCount, 1)
70 func (ui *Ui) endDraw() {
71 if count := atomic.AddInt32(&ui.drawCount, -1); count == 0 {
76 func (ui *Ui) Active() string {
77 return ui.activeElement.Name
80 func (ui *Ui) SetActive(name string) {
81 element, _ := ui.elements[name]
82 if ui.activeElement != nil {
83 ui.activeElement.View.uiSetActive(false)
85 ui.activeElement = element
87 element.View.uiSetActive(true)
92 func (ui *Ui) Run() error {
96 if err := termbox.Init(); err != nil {
100 termbox.SetInputMode(termbox.InputAlt)
102 events := make(chan termbox.Event)
105 events <- termbox.PollEvent()
109 ui.manager.OnUiInitialize(ui)
110 width, height := termbox.Size()
111 ui.manager.OnUiResize(ui, width, height)
118 case event := <-events:
120 case termbox.EventResize:
121 ui.manager.OnUiResize(ui, event.Width, event.Height)
123 case termbox.EventKey:
125 ui.onCharacterEvent(event.Ch)
127 ui.onKeyEvent(Modifier(event.Mod), Key(event.Key))
134 func (ui *Ui) onCharacterEvent(ch rune) {
135 if ui.activeElement != nil {
136 ui.activeElement.View.uiCharacterEvent(ch)
140 func (ui *Ui) onKeyEvent(mod Modifier, key Key) {
141 if ui.keyListeners[key] != nil {
142 for _, listener := range ui.keyListeners[key] {
146 if ui.activeElement != nil {
147 ui.activeElement.View.uiKeyEvent(mod, key)
151 func (ui *Ui) Add(name string, view View) error {
152 if _, ok := ui.elements[name]; ok {
153 return errors.New("view already exists")
155 ui.elements[name] = &uiElement{
159 view.uiInitialize(ui)
163 func (ui *Ui) SetBounds(name string, x0, y0, x1, y1 int) error {
164 element, ok := ui.elements[name]
166 return errors.New("view does not exist")
168 element.X0, element.Y0, element.X1, element.Y1 = x0, y0, x1, y1
169 element.View.uiSetBounds(x0, y0, x1, y1)
173 func (ui *Ui) AddKeyListener(listener KeyListener, key Key) {
174 ui.keyListeners[key] = append(ui.keyListeners[key], listener)