-package uiterm
+package uiterm // import "layeh.com/barnard/uiterm"
import (
+ "errors"
+ "sync/atomic"
+
"github.com/nsf/termbox-go"
)
-type LayoutFunc func(ui *Ui, width, height int)
-
type KeyListener func(ui *Ui, key Key)
type UiManager interface {
}
type Ui struct {
+ Fg, Bg Attribute
+
close chan bool
manager UiManager
+ drawCount int32
elements map[string]*uiElement
activeElement *uiElement
keyListeners map[Key][]KeyListener
-
- fg Attribute
- bg Attribute
}
type uiElement struct {
+ Name string
X0, Y0, X1, Y1 int
View View
}
func (ui *Ui) Refresh() {
if termbox.IsInit {
- termbox.Clear(termbox.Attribute(ui.fg), termbox.Attribute(ui.bg))
+ ui.beginDraw()
+ defer ui.endDraw()
+
+ termbox.Clear(termbox.Attribute(ui.Fg), termbox.Attribute(ui.Bg))
termbox.HideCursor()
for _, element := range ui.elements {
- element.View.draw()
+ element.View.uiDraw()
}
+ }
+}
+
+func (ui *Ui) beginDraw() {
+ atomic.AddInt32(&ui.drawCount, 1)
+}
+
+func (ui *Ui) endDraw() {
+ if count := atomic.AddInt32(&ui.drawCount, -1); count == 0 {
termbox.Flush()
}
}
-func (ui *Ui) Active() View {
- return ui.activeElement.View
+func (ui *Ui) Active() string {
+ return ui.activeElement.Name
}
func (ui *Ui) SetActive(name string) {
element, _ := ui.elements[name]
if ui.activeElement != nil {
- ui.activeElement.View.setActive(false)
+ ui.activeElement.View.uiSetActive(false)
}
ui.activeElement = element
if element != nil {
- element.View.setActive(true)
+ element.View.uiSetActive(true)
}
ui.Refresh()
}
-func (ui *Ui) SetClear(fg, bg Attribute) {
- ui.fg = fg
- ui.bg = bg
-}
-
func (ui *Ui) Run() error {
if termbox.IsInit {
return nil
func (ui *Ui) onCharacterEvent(ch rune) {
if ui.activeElement != nil {
- ui.activeElement.View.characterEvent(ch)
+ ui.activeElement.View.uiCharacterEvent(ch)
}
}
}
}
if ui.activeElement != nil {
- ui.activeElement.View.keyEvent(mod, key)
+ ui.activeElement.View.uiKeyEvent(mod, key)
}
}
-func (ui *Ui) SetView(name string, x0, y0, x1, y1 int, view View) {
- if element, ok := ui.elements[name]; ok {
- element.X0 = x0
- element.Y0 = y0
- element.X1 = x1
- element.Y1 = y1
- view = element.View
- } else {
- ui.elements[name] = &uiElement{
- X0: x0,
- Y0: y0,
- X1: x1,
- Y1: y1,
- View: view,
- }
- view.uiInitialize(ui)
+func (ui *Ui) Add(name string, view View) error {
+ if _, ok := ui.elements[name]; ok {
+ return errors.New("view already exists")
+ }
+ ui.elements[name] = &uiElement{
+ Name: name,
+ View: view,
}
- view.setBounds(x0, y0, x1, y1)
+ view.uiInitialize(ui)
+ return nil
}
-func (ui *Ui) View(name string) View {
- if element, ok := ui.elements[name]; !ok {
- return nil
- } else {
- return element.View
+func (ui *Ui) SetBounds(name string, x0, y0, x1, y1 int) error {
+ element, ok := ui.elements[name]
+ if !ok {
+ return errors.New("view does not exist")
}
+ element.X0, element.Y0, element.X1, element.Y1 = x0, y0, x1, y1
+ element.View.uiSetBounds(x0, y0, x1, y1)
+ return nil
}
func (ui *Ui) AddKeyListener(listener KeyListener, key Key) {