aerc/lib/ui/context.go
Markus Ongyerth 80e891a802 switch to tcell from termbox
This is a simple mostly straight forward switch to tcell in favor of
termbox.
It uses the tcell native api (not the compat layer) but does not make
use of most features.

Further changes should include moving to tcell's views.TextArea and the
general built in widget behaviour instead of the current ad hoc
implementation.

Regression: Cursor isn't shown in ex-line
2018-06-01 16:04:43 -07:00

122 lines
2.6 KiB
Go

package ui
import (
"fmt"
"github.com/mattn/go-runewidth"
"github.com/gdamore/tcell"
"github.com/gdamore/tcell/views"
)
// A context allows you to draw in a sub-region of the terminal
type Context struct {
viewport *views.ViewPort
}
func (ctx *Context) X() int {
x, _, _, _ := ctx.viewport.GetPhysical()
return x
}
func (ctx *Context) Y() int {
_, y, _, _ := ctx.viewport.GetPhysical()
return y
}
func (ctx *Context) Width() int {
width, _ := ctx.viewport.Size()
return width
}
func (ctx *Context) Height() int {
_, height := ctx.viewport.Size()
return height
}
func NewContext(width, height int, screen tcell.Screen) *Context {
vp := views.NewViewPort(screen, 0, 0, width, height)
return &Context{vp}
}
func (ctx *Context) Subcontext(x, y, width, height int) *Context {
vp_width, vp_height := ctx.viewport.Size()
if (x < 0 || y < 0) {
panic(fmt.Errorf("Attempted to create context with negative offset"))
}
if (x + width > vp_width || y + height > vp_height) {
panic(fmt.Errorf("Attempted to create context larger than parent"))
}
vp := views.NewViewPort(ctx.viewport, x, y, width, height)
return &Context{vp}
}
func (ctx *Context) SetCell(x, y int, ch rune, style tcell.Style) {
width, height := ctx.viewport.Size()
if x >= width || y >= height {
panic(fmt.Errorf("Attempted to draw outside of context"))
}
crunes := []rune{}
ctx.viewport.SetContent(x, y, ch, crunes, style)
}
func (ctx *Context) Printf(x, y int, style tcell.Style,
format string, a ...interface{}) int {
width, height := ctx.viewport.Size()
if x >= width || y >= height {
panic(fmt.Errorf("Attempted to draw outside of context"))
}
str := fmt.Sprintf(format, a...)
old_x := x
newline := func() bool {
x = old_x
y++
return y < height
}
for _, ch := range str {
if str == " こんにちは " {
fmt.Printf("%c\n", ch)
}
switch ch {
case '\n':
if !newline() {
return runewidth.StringWidth(str)
}
case '\r':
x = old_x
default:
crunes := []rune{}
ctx.viewport.SetContent(x, y, ch, crunes, style)
x += runewidth.RuneWidth(ch)
if x == old_x + width {
if !newline() {
return runewidth.StringWidth(str)
}
}
}
}
return runewidth.StringWidth(str)
}
//func (ctx *Context) Screen() tcell.Screen {
// return ctx.screen
//}
func (ctx *Context) Fill(x, y, width, height int, rune rune, style tcell.Style) {
vp := views.NewViewPort(ctx.viewport, x, y, width, height)
vp.Fill(rune, style)
}
func (ctx *Context) SetCursor(x, y int) {
// FIXME: Cursor needs to be set on tcell.Screen, or layout has to
// provide a CellModel
// cv := views.NewCellView()
// cv.Init()
// cv.SetView(ctx.viewport)
// cv.SetCursor(x, y)
}