80e891a802
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
121 lines
2.6 KiB
Go
121 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)
|
|
}
|