2015-04-21 21:56:10 +08:00
|
|
|
// Copyright 2015 Zack Guo <gizak@icloud.com>. All rights reserved.
|
|
|
|
// Use of this source code is governed by a MIT license that can
|
|
|
|
// be found in the LICENSE file.
|
|
|
|
|
|
|
|
package termui
|
|
|
|
|
|
|
|
import "image"
|
|
|
|
|
|
|
|
// Cell is a rune with assigned Fg and Bg
|
|
|
|
type Cell struct {
|
|
|
|
Ch rune
|
|
|
|
Fg Attribute
|
|
|
|
Bg Attribute
|
|
|
|
}
|
|
|
|
|
|
|
|
// Buffer is a renderable rectangle cell data container.
|
|
|
|
type Buffer struct {
|
2015-05-10 07:29:22 +08:00
|
|
|
Area image.Rectangle // selected drawing area
|
2015-04-21 21:56:10 +08:00
|
|
|
CellMap map[image.Point]Cell
|
|
|
|
}
|
|
|
|
|
|
|
|
// At returns the cell at (x,y).
|
|
|
|
func (b Buffer) At(x, y int) Cell {
|
|
|
|
return b.CellMap[image.Pt(x, y)]
|
|
|
|
}
|
|
|
|
|
|
|
|
// Set assigns a char to (x,y)
|
|
|
|
func (b Buffer) Set(x, y int, c Cell) {
|
|
|
|
b.CellMap[image.Pt(x, y)] = c
|
|
|
|
}
|
|
|
|
|
|
|
|
// Bounds returns the domain for which At can return non-zero color.
|
|
|
|
func (b Buffer) Bounds() image.Rectangle {
|
|
|
|
x0, y0, x1, y1 := 0, 0, 0, 0
|
|
|
|
for p := range b.CellMap {
|
2015-04-26 12:13:49 +08:00
|
|
|
if p.X > x1 {
|
2015-04-21 21:56:10 +08:00
|
|
|
x1 = p.X
|
2015-04-26 12:13:49 +08:00
|
|
|
}
|
|
|
|
if p.X < x0 {
|
2015-04-21 21:56:10 +08:00
|
|
|
x0 = p.X
|
2015-04-26 12:13:49 +08:00
|
|
|
}
|
|
|
|
if p.Y > y1 {
|
2015-04-21 21:56:10 +08:00
|
|
|
y1 = p.Y
|
2015-04-26 12:13:49 +08:00
|
|
|
}
|
|
|
|
if p.Y < y0 {
|
2015-04-21 21:56:10 +08:00
|
|
|
y0 = p.Y
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return image.Rect(x0, y0, x1, y1)
|
|
|
|
}
|
|
|
|
|
2015-04-26 12:13:49 +08:00
|
|
|
// SetArea assigns a new rect area to Buffer b.
|
2015-05-10 07:29:22 +08:00
|
|
|
func (b *Buffer) SetArea(r image.Rectangle) {
|
2015-04-26 12:13:49 +08:00
|
|
|
b.Area.Max = r.Max
|
|
|
|
b.Area.Min = r.Min
|
|
|
|
}
|
|
|
|
|
|
|
|
// Sync sets drawing area to the buffer's bound
|
|
|
|
func (b Buffer) Sync() {
|
|
|
|
b.SetArea(b.Bounds())
|
2015-04-21 21:56:10 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
// NewCell returns a new cell
|
|
|
|
func NewCell(ch rune, fg, bg Attribute) Cell {
|
|
|
|
return Cell{ch, fg, bg}
|
|
|
|
}
|
|
|
|
|
2015-04-26 12:13:49 +08:00
|
|
|
// Merge merges bs Buffers onto b
|
2015-10-10 23:20:44 +08:00
|
|
|
func (b *Buffer) Merge(bs ...Buffer) {
|
2015-04-26 12:13:49 +08:00
|
|
|
for _, buf := range bs {
|
|
|
|
for p, v := range buf.CellMap {
|
|
|
|
b.Set(p.X, p.Y, v)
|
|
|
|
}
|
2015-05-10 07:29:22 +08:00
|
|
|
b.SetArea(b.Area.Union(buf.Area))
|
2015-04-21 21:56:10 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// NewBuffer returns a new Buffer
|
|
|
|
func NewBuffer() Buffer {
|
2015-04-26 12:13:49 +08:00
|
|
|
return Buffer{
|
|
|
|
CellMap: make(map[image.Point]Cell),
|
2015-05-10 07:29:22 +08:00
|
|
|
Area: image.Rectangle{}}
|
2015-04-26 12:13:49 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
// Fill fills the Buffer b with ch,fg and bg.
|
|
|
|
func (b Buffer) Fill(ch rune, fg, bg Attribute) {
|
|
|
|
for x := b.Area.Min.X; x < b.Area.Max.X; x++ {
|
|
|
|
for y := b.Area.Min.Y; y < b.Area.Max.Y; y++ {
|
|
|
|
b.Set(x, y, Cell{ch, fg, bg})
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// NewFilledBuffer returns a new Buffer filled with ch, fb and bg.
|
|
|
|
func NewFilledBuffer(x0, y0, x1, y1 int, ch rune, fg, bg Attribute) Buffer {
|
|
|
|
buf := NewBuffer()
|
|
|
|
buf.Area.Min = image.Pt(x0, y0)
|
|
|
|
buf.Area.Max = image.Pt(x1, y1)
|
|
|
|
|
|
|
|
for x := buf.Area.Min.X; x < buf.Area.Max.X; x++ {
|
|
|
|
for y := buf.Area.Min.Y; y < buf.Area.Max.Y; y++ {
|
|
|
|
buf.Set(x, y, Cell{ch, fg, bg})
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return buf
|
2015-04-21 21:56:10 +08:00
|
|
|
}
|