mirror of
https://github.com/mvvasilev/last_light.git
synced 2025-05-03 10:49:53 +03:00
290 lines
5.9 KiB
Go
290 lines
5.9 KiB
Go
package render
|
|
|
|
import (
|
|
"mvvasilev/last_light/util"
|
|
"strings"
|
|
"unicode/utf8"
|
|
|
|
"github.com/gdamore/tcell/v2"
|
|
"github.com/google/uuid"
|
|
)
|
|
|
|
type Drawable interface {
|
|
UniqueId() uuid.UUID
|
|
Draw(s tcell.Screen)
|
|
}
|
|
|
|
type rectangle struct {
|
|
id uuid.UUID
|
|
|
|
size util.Size
|
|
position util.Position
|
|
style tcell.Style
|
|
|
|
northBorder rune
|
|
westBorder rune
|
|
eastBorder rune
|
|
southBorder rune
|
|
|
|
nwCorner rune
|
|
swCorner rune
|
|
seCorner rune
|
|
neCorner rune
|
|
|
|
fillRune rune
|
|
}
|
|
|
|
func CreateSimpleRectangle(x uint16, y uint16, width uint16, height uint16, borderRune rune, fillRune rune, style tcell.Style) rectangle {
|
|
return CreateRectangle(
|
|
x, y, width, height,
|
|
borderRune, borderRune, borderRune,
|
|
borderRune, fillRune, borderRune,
|
|
borderRune, borderRune, borderRune,
|
|
style,
|
|
)
|
|
}
|
|
|
|
// CreateRectangle(
|
|
//
|
|
// x, y, width, height,
|
|
// '┌', '─', '┐',
|
|
// '│', ' ', '│',
|
|
// '└', '─', '┘',
|
|
// style
|
|
//
|
|
// )
|
|
func CreateRectangle(
|
|
x uint16,
|
|
y uint16,
|
|
width uint16,
|
|
height uint16,
|
|
nwCorner, northBorder, neCorner,
|
|
westBorder, fillRune, eastBorder,
|
|
swCorner, southBorder, seCorner rune,
|
|
style tcell.Style,
|
|
) rectangle {
|
|
return rectangle{
|
|
id: uuid.New(),
|
|
size: util.SizeOf(width, height),
|
|
position: util.PositionAt(x, y),
|
|
style: style,
|
|
northBorder: northBorder,
|
|
eastBorder: eastBorder,
|
|
southBorder: southBorder,
|
|
westBorder: westBorder,
|
|
nwCorner: nwCorner,
|
|
seCorner: seCorner,
|
|
swCorner: swCorner,
|
|
neCorner: neCorner,
|
|
fillRune: fillRune,
|
|
}
|
|
}
|
|
|
|
func (rect rectangle) UniqueId() uuid.UUID {
|
|
return rect.id
|
|
}
|
|
|
|
func (rect rectangle) Draw(s tcell.Screen) {
|
|
width := rect.size.Width()
|
|
height := rect.size.Height()
|
|
x := rect.position.X()
|
|
y := rect.position.Y()
|
|
|
|
for h := range height {
|
|
for w := range width {
|
|
|
|
// nw corner
|
|
if w == 0 && h == 0 {
|
|
s.SetContent(x+w, y+h, rect.nwCorner, nil, rect.style)
|
|
continue
|
|
}
|
|
|
|
// ne corner
|
|
if w == (width-1) && h == 0 {
|
|
s.SetContent(x+w, y+h, rect.neCorner, nil, rect.style)
|
|
continue
|
|
}
|
|
|
|
// sw corner
|
|
if w == 0 && h == (height-1) {
|
|
s.SetContent(x+w, y+h, rect.swCorner, nil, rect.style)
|
|
continue
|
|
}
|
|
|
|
// se corner
|
|
if w == (width-1) && h == (height-1) {
|
|
s.SetContent(x+w, y+h, rect.seCorner, nil, rect.style)
|
|
continue
|
|
}
|
|
|
|
// north border
|
|
if h == 0 && (w != 0 && w != (width-1)) {
|
|
s.SetContent(x+w, y+h, rect.northBorder, nil, rect.style)
|
|
continue
|
|
}
|
|
|
|
// south border
|
|
if h == (height-1) && (w != 0 && w != (width-1)) {
|
|
s.SetContent(x+w, y+h, rect.southBorder, nil, rect.style)
|
|
continue
|
|
}
|
|
|
|
// west border
|
|
if w == 0 && (h != 0 && h != (height-1)) {
|
|
s.SetContent(x+w, y+h, rect.westBorder, nil, rect.style)
|
|
continue
|
|
}
|
|
|
|
// east border
|
|
if w == (width-1) && (h != 0 && h != (height-1)) {
|
|
s.SetContent(x+w, y+h, rect.eastBorder, nil, rect.style)
|
|
continue
|
|
}
|
|
|
|
s.SetContent(x+w, y+h, rect.fillRune, nil, rect.style)
|
|
}
|
|
}
|
|
|
|
}
|
|
|
|
type text struct {
|
|
id uuid.UUID
|
|
content []string
|
|
position util.Position
|
|
size util.Size
|
|
style tcell.Style
|
|
}
|
|
|
|
func CreateText(
|
|
x, y uint16,
|
|
width, height uint16,
|
|
content string,
|
|
style tcell.Style,
|
|
) text {
|
|
return text{
|
|
id: uuid.New(),
|
|
content: strings.Split(content, " "),
|
|
style: style,
|
|
size: util.SizeOf(width, height),
|
|
position: util.PositionAt(x, y),
|
|
}
|
|
}
|
|
|
|
func (t text) UniqueId() uuid.UUID {
|
|
return t.id
|
|
}
|
|
|
|
func (t text) Draw(s tcell.Screen) {
|
|
width := t.size.Width()
|
|
height := t.size.Height()
|
|
x := t.position.X()
|
|
y := t.position.Y()
|
|
|
|
currentHPos := 0
|
|
currentVPos := 0
|
|
|
|
drawText := func(text string) {
|
|
for i, r := range text {
|
|
s.SetContent(x+currentHPos+i, y+currentVPos, r, nil, t.style)
|
|
}
|
|
}
|
|
|
|
for _, s := range t.content {
|
|
runeCount := utf8.RuneCountInString(s)
|
|
|
|
if currentVPos > height {
|
|
break
|
|
}
|
|
|
|
// The current word cannot fit within the remaining space on the line
|
|
if runeCount > (width - currentHPos) {
|
|
currentVPos += 1 // next line
|
|
currentHPos = 0 // reset to start of line
|
|
|
|
drawText(s + " ")
|
|
currentHPos += runeCount + 1
|
|
|
|
continue
|
|
}
|
|
|
|
// The current word fits exactly within the remaining space on the line
|
|
if runeCount == (width - currentHPos) {
|
|
drawText(s)
|
|
|
|
currentVPos += 1 // next line
|
|
currentHPos = 0 // reset to start of line
|
|
|
|
continue
|
|
}
|
|
|
|
// The current word fits within the remaining space, and there's more space left over
|
|
drawText(s + " ")
|
|
currentHPos += runeCount + 1 // add +1 to account for space after word
|
|
}
|
|
}
|
|
|
|
type grid struct {
|
|
id uuid.UUID
|
|
|
|
internalCellSize util.Size
|
|
numCellsHorizontal uint16
|
|
numCellsVertical uint16
|
|
position util.Position
|
|
style tcell.Style
|
|
|
|
northBorder rune
|
|
westBorder rune
|
|
eastBorder rune
|
|
southBorder rune
|
|
|
|
nwCorner rune
|
|
swCorner rune
|
|
seCorner rune
|
|
neCorner rune
|
|
|
|
verticalTJunction rune
|
|
horizontalTJunction rune
|
|
crossJunction rune
|
|
|
|
fillRune rune
|
|
}
|
|
|
|
func CreateGrid(
|
|
x uint16,
|
|
y uint16,
|
|
cellWidth uint16,
|
|
cellHeight uint16,
|
|
numCellsHorizontal uint16,
|
|
numCellsVertical uint16,
|
|
nwCorner, northBorder, neCorner,
|
|
westBorder, fillRune, eastBorder,
|
|
swCorner, southBorder, seCorner,
|
|
verticalTJunction, horizontalTJunction,
|
|
crossJunction rune,
|
|
style tcell.Style,
|
|
) grid {
|
|
return grid{
|
|
id: uuid.New(),
|
|
internalCellSize: util.SizeOf(cellWidth, cellHeight),
|
|
numCellsHorizontal: numCellsHorizontal,
|
|
numCellsVertical: numCellsVertical,
|
|
position: util.PositionAt(x, y),
|
|
style: style,
|
|
northBorder: northBorder,
|
|
eastBorder: eastBorder,
|
|
southBorder: southBorder,
|
|
westBorder: westBorder,
|
|
nwCorner: nwCorner,
|
|
seCorner: seCorner,
|
|
swCorner: swCorner,
|
|
neCorner: neCorner,
|
|
fillRune: fillRune,
|
|
verticalTJunction: verticalTJunction,
|
|
horizontalTJunction: horizontalTJunction,
|
|
crossJunction: crossJunction,
|
|
}
|
|
}
|
|
|
|
func (g grid) Draw(s tcell.Screen) {
|
|
|
|
}
|