diff options
Diffstat (limited to 'ui')
-rw-r--r-- | ui/context.go | 31 | ||||
-rw-r--r-- | ui/tab.go | 115 |
2 files changed, 134 insertions, 12 deletions
diff --git a/ui/context.go b/ui/context.go index e7d9ebe..ae9e561 100644 --- a/ui/context.go +++ b/ui/context.go @@ -3,7 +3,8 @@ package ui import ( "fmt" - "github.com/nsf/termbox-go" + "github.com/mattn/go-runewidth" + tb "github.com/nsf/termbox-go" ) // A context allows you to draw in a sub-region of the terminal @@ -38,15 +39,15 @@ func (ctx *Context) Subcontext(x, y, width, height int) *Context { } } -func (ctx *Context) SetCell(x, y int, ch rune, fg, bg termbox.Attribute) { +func (ctx *Context) SetCell(x, y int, ch rune, fg, bg tb.Attribute) { if x >= ctx.width || y >= ctx.height { panic(fmt.Errorf("Attempted to draw outside of context")) } - termbox.SetCell(ctx.x+x, ctx.y+y, ch, fg, bg) + tb.SetCell(ctx.x+x, ctx.y+y, ch, fg, bg) } -func (ctx *Context) Printf(x, y int, ref termbox.Cell, - format string, a ...interface{}) { +func (ctx *Context) Printf(x, y int, ref tb.Cell, + format string, a ...interface{}) int { if x >= ctx.width || y >= ctx.height { panic(fmt.Errorf("Attempted to draw outside of context")) @@ -64,29 +65,35 @@ func (ctx *Context) Printf(x, y int, ref termbox.Cell, return y < ctx.height } for _, ch := range str { + if str == " こんにちは " { + fmt.Printf("%c\n", ch) + } switch ch { case '\n': if !newline() { - return + return runewidth.StringWidth(str) } case '\r': x = old_x default: - termbox.SetCell(x, y, ch, ref.Fg, ref.Bg) - x++ + tb.SetCell(x, y, ch, ref.Fg, ref.Bg) + x += runewidth.RuneWidth(ch) if x == old_x+ctx.width { if !newline() { - return + return runewidth.StringWidth(str) } } } } + + return runewidth.StringWidth(str) } -func (ctx *Context) Fill(x, y, width, height int, ref termbox.Cell) { +func (ctx *Context) Fill(x, y, width, height int, ref tb.Cell) { _x := x - for ; y < height && y < ctx.height; y++ { - for ; x < width && x < ctx.width; x++ { + _y := y + for ; y < _y+height && y < ctx.height; y++ { + for ; x < _x+width && x < ctx.width; x++ { ctx.SetCell(x, y, ref.Ch, ref.Fg, ref.Bg) } x = _x diff --git a/ui/tab.go b/ui/tab.go new file mode 100644 index 0000000..e6a8aa5 --- /dev/null +++ b/ui/tab.go @@ -0,0 +1,115 @@ +package ui + +import ( + tb "github.com/nsf/termbox-go" +) + +type Tabs struct { + Tabs []*Tab + TabStrip *TabStrip + TabContent *TabContent + Selected int + + onInvalidateStrip func(d Drawable) + onInvalidateContent func(d Drawable) +} + +type Tab struct { + Content Drawable + Name string + invalid bool +} + +type TabStrip Tabs +type TabContent Tabs + +func NewTabs() *Tabs { + tabs := &Tabs{} + tabs.TabStrip = (*TabStrip)(tabs) + tabs.TabContent = (*TabContent)(tabs) + return tabs +} + +func (tabs *Tabs) Add(content Drawable, name string) { + tabs.Tabs = append(tabs.Tabs, &Tab{ + Content: content, + Name: name, + }) + tabs.TabStrip.Invalidate() + content.OnInvalidate(tabs.invalidateChild) +} + +func (tabs *Tabs) invalidateChild(d Drawable) { + for i, tab := range tabs.Tabs { + if tab.Content == d { + if i == tabs.Selected { + tabs.TabContent.Invalidate() + } + return + } + } +} + +func (tabs *Tabs) Remove(content Drawable) { + for i, tab := range tabs.Tabs { + if tab.Content == content { + tabs.Tabs = append(tabs.Tabs[:i], tabs.Tabs[i+1:]...) + break + } + } + tabs.TabStrip.Invalidate() +} + +func (tabs *Tabs) Select(index int) { + if tabs.Selected != index { + tabs.Selected = index + tabs.TabStrip.Invalidate() + tabs.TabContent.Invalidate() + } +} + +// TODO: Color repository +func (strip *TabStrip) Draw(ctx *Context) { + x := 0 + for i, tab := range strip.Tabs { + cell := tb.Cell{ + Fg: tb.ColorBlack, + Bg: tb.ColorWhite, + } + if strip.Selected == i { + cell.Fg = tb.ColorDefault + cell.Bg = tb.ColorDefault + } + x += ctx.Printf(x, 0, cell, " %s ", tab.Name) + } + cell := tb.Cell{ + Fg: tb.ColorBlack, + Bg: tb.ColorWhite, + } + ctx.Fill(x, 0, ctx.Width()-x, 1, cell) +} + +func (strip *TabStrip) Invalidate() { + if strip.onInvalidateStrip != nil { + strip.onInvalidateStrip(strip) + } +} + +func (strip *TabStrip) OnInvalidate(onInvalidate func(d Drawable)) { + strip.onInvalidateStrip = onInvalidate +} + +func (content *TabContent) Draw(ctx *Context) { + tab := content.Tabs[content.Selected] + tab.Content.Draw(ctx) +} + +func (content *TabContent) Invalidate() { + if content.onInvalidateContent != nil { + content.onInvalidateContent(content) + } +} + +func (content *TabContent) OnInvalidate(onInvalidate func(d Drawable)) { + content.onInvalidateContent = onInvalidate +} |