diff options
author | Drew DeVault <sir@cmpwn.com> | 2018-02-17 19:42:29 -0500 |
---|---|---|
committer | Drew DeVault <sir@cmpwn.com> | 2018-02-17 19:42:29 -0500 |
commit | 5b2e3a0ca0b549c569ff6c01549c2dc425b0ba40 (patch) | |
tree | 7ac92fe8cb13e662aeeb851c3a9a945bf837f600 /ui | |
parent | 60b351b78c930110716b0c9db2227e13704f826d (diff) | |
download | aerc-5b2e3a0ca0b549c569ff6c01549c2dc425b0ba40.tar.gz |
Implement tab container
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 e7d9ebe0..ae9e5610 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 00000000..e6a8aa5f --- /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 +} |