mirror of
https://github.com/mvvasilev/last_light.git
synced 2025-04-19 12:49:52 +03:00
Render context, centered window, better rectangle drawing
This commit is contained in:
parent
422840fc7b
commit
dce7d29a99
6 changed files with 352 additions and 159 deletions
79
main.go
79
main.go
|
@ -5,88 +5,61 @@ import (
|
||||||
"log"
|
"log"
|
||||||
"mvvasilev/last_light/render"
|
"mvvasilev/last_light/render"
|
||||||
"os"
|
"os"
|
||||||
"time"
|
|
||||||
|
|
||||||
"github.com/gdamore/tcell/v2"
|
"github.com/gdamore/tcell/v2"
|
||||||
|
"github.com/gdamore/tcell/v2/views"
|
||||||
)
|
)
|
||||||
|
|
||||||
func main() {
|
func main() {
|
||||||
|
|
||||||
s, err := tcell.NewScreen()
|
c, err := render.CreateRenderContext()
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Fatalf("%~v", err)
|
log.Fatalf("%~v", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := s.Init(); err != nil {
|
c.HandleInput(func(ev *tcell.EventKey) {
|
||||||
log.Fatalf("%+v", err)
|
if ev.Key() == tcell.KeyEscape || ev.Key() == tcell.KeyCtrlC {
|
||||||
|
c.Stop()
|
||||||
|
os.Exit(0)
|
||||||
}
|
}
|
||||||
|
})
|
||||||
// width, height := s.Size()
|
|
||||||
|
|
||||||
// if width < 50 || height < 50 {
|
|
||||||
// log.Fatalf("Your terminal must be at least 50x50")
|
|
||||||
// }
|
|
||||||
|
|
||||||
defStyle := tcell.StyleDefault.Background(tcell.ColorReset).Foreground(tcell.ColorReset)
|
defStyle := tcell.StyleDefault.Background(tcell.ColorReset).Foreground(tcell.ColorReset)
|
||||||
|
|
||||||
rect := render.CreateRectangle(
|
rect := render.CreateRectangle(
|
||||||
0, 1, 10, 10,
|
0, 0, 80, 24,
|
||||||
'┌', '─', '┐',
|
'┌', '─', '┐',
|
||||||
'│', '#', '│',
|
'│', '#', '│',
|
||||||
'└', '─', '┘',
|
'└', '─', '┘',
|
||||||
defStyle,
|
false, true, defStyle,
|
||||||
)
|
)
|
||||||
|
|
||||||
text := render.CreateText(1, 2, 8, 8, "Hello World! How are you today?", defStyle)
|
// text := render.CreateText(1, 2, 8, 8, "Hello World! How are you today?", defStyle)
|
||||||
|
|
||||||
|
// grid := render.CreateGrid(
|
||||||
|
// 11, 1, 3, 3, 3, 3,
|
||||||
|
// '┌', '─', '┬', '┐',
|
||||||
|
// '│', '#', '│', '│',
|
||||||
|
// '├', '─', '┼', '┤',
|
||||||
|
// '└', '─', '┴', '┘',
|
||||||
|
// defStyle,
|
||||||
|
// )
|
||||||
|
|
||||||
layers := render.CreateLayeredDrawContainer()
|
layers := render.CreateLayeredDrawContainer()
|
||||||
|
|
||||||
layers.Insert(0, rect)
|
layers.Insert(0, rect)
|
||||||
layers.Insert(1, text)
|
// layers.Insert(1, text)
|
||||||
|
// layers.Insert(0, grid)
|
||||||
//layers.Remove(text.UniqueId())
|
|
||||||
|
|
||||||
events := make(chan tcell.Event)
|
|
||||||
quit := make(chan struct{})
|
|
||||||
|
|
||||||
go s.ChannelEvents(events, quit)
|
|
||||||
|
|
||||||
lastTime := time.Now()
|
|
||||||
|
|
||||||
for {
|
|
||||||
deltaTime := 1 + time.Since(lastTime).Microseconds()
|
|
||||||
lastTime = time.Now()
|
|
||||||
|
|
||||||
s.Clear()
|
|
||||||
|
|
||||||
|
c.HandleRender(func(view views.View, deltaTime int64) {
|
||||||
fps := 1_000_000 / deltaTime
|
fps := 1_000_000 / deltaTime
|
||||||
|
|
||||||
fpsText := render.CreateText(0, 0, 16, 1, fmt.Sprintf("%v FPS", fps), defStyle)
|
fpsText := render.CreateText(0, 0, 16, 1, fmt.Sprintf("%v FPS", fps), defStyle)
|
||||||
|
|
||||||
layers.Draw(s)
|
layers.Draw(view)
|
||||||
fpsText.Draw(s)
|
fpsText.Draw(view)
|
||||||
|
})
|
||||||
s.Show()
|
|
||||||
|
|
||||||
select {
|
|
||||||
case ev, ok := <-events:
|
|
||||||
|
|
||||||
if !ok {
|
|
||||||
break
|
|
||||||
}
|
|
||||||
|
|
||||||
switch ev := ev.(type) {
|
|
||||||
case *tcell.EventResize:
|
|
||||||
s.Sync()
|
|
||||||
case *tcell.EventKey:
|
|
||||||
if ev.Key() == tcell.KeyEscape || ev.Key() == tcell.KeyCtrlC {
|
|
||||||
s.Fini()
|
|
||||||
os.Exit(0)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
default:
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
c.BeginRendering()
|
||||||
}
|
}
|
||||||
|
|
147
render/context.go
Normal file
147
render/context.go
Normal file
|
@ -0,0 +1,147 @@
|
||||||
|
package render
|
||||||
|
|
||||||
|
import (
|
||||||
|
"errors"
|
||||||
|
"log"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"github.com/gdamore/tcell/v2"
|
||||||
|
"github.com/gdamore/tcell/v2/views"
|
||||||
|
"github.com/google/uuid"
|
||||||
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
|
TERMINAL_SIZE_WIDTH int = 80
|
||||||
|
TERMINAL_SIZE_HEIGHT int = 24
|
||||||
|
DEFAULT_STYLE_BACKGROUND tcell.Color = tcell.ColorReset
|
||||||
|
DEFAULT_STYLE_FOREGROUND tcell.Color = tcell.ColorReset
|
||||||
|
)
|
||||||
|
|
||||||
|
type Drawable interface {
|
||||||
|
UniqueId() uuid.UUID
|
||||||
|
Draw(v views.View)
|
||||||
|
}
|
||||||
|
|
||||||
|
type renderContext struct {
|
||||||
|
screen tcell.Screen
|
||||||
|
view *views.ViewPort
|
||||||
|
defaultStyle tcell.Style
|
||||||
|
|
||||||
|
events chan tcell.Event
|
||||||
|
quit chan struct{}
|
||||||
|
|
||||||
|
lastRenderTime time.Time
|
||||||
|
|
||||||
|
renderHandler func(view views.View, deltaTime int64)
|
||||||
|
inputHandler func(ev *tcell.EventKey)
|
||||||
|
}
|
||||||
|
|
||||||
|
func CreateRenderContext() (*renderContext, error) {
|
||||||
|
s, err := tcell.NewScreen()
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
log.Fatal(err)
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
stopScreen := func() {
|
||||||
|
s.Fini()
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := s.Init(); err != nil {
|
||||||
|
stopScreen()
|
||||||
|
log.Fatal(err)
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
width, height := s.Size()
|
||||||
|
|
||||||
|
if width < TERMINAL_SIZE_WIDTH || height < TERMINAL_SIZE_HEIGHT {
|
||||||
|
stopScreen()
|
||||||
|
log.Fatal("Unable to start; Terminal must be at least 80x24")
|
||||||
|
return nil, errors.New("Terminal is undersized; must be at least 80x24")
|
||||||
|
}
|
||||||
|
|
||||||
|
view := views.NewViewPort(
|
||||||
|
s,
|
||||||
|
(width/2)-(TERMINAL_SIZE_WIDTH/2),
|
||||||
|
(height/2)-(TERMINAL_SIZE_HEIGHT/2),
|
||||||
|
TERMINAL_SIZE_WIDTH,
|
||||||
|
TERMINAL_SIZE_HEIGHT,
|
||||||
|
)
|
||||||
|
|
||||||
|
defStyle := tcell.StyleDefault.Background(DEFAULT_STYLE_BACKGROUND).Foreground(DEFAULT_STYLE_FOREGROUND)
|
||||||
|
|
||||||
|
events := make(chan tcell.Event)
|
||||||
|
quit := make(chan struct{})
|
||||||
|
|
||||||
|
go s.ChannelEvents(events, quit)
|
||||||
|
|
||||||
|
context := new(renderContext)
|
||||||
|
|
||||||
|
context.screen = s
|
||||||
|
context.defaultStyle = defStyle
|
||||||
|
context.events = events
|
||||||
|
context.quit = quit
|
||||||
|
context.view = view
|
||||||
|
|
||||||
|
return context, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *renderContext) Stop() {
|
||||||
|
c.screen.Fini()
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *renderContext) HandleRender(renderHandler func(view views.View, deltaTime int64)) {
|
||||||
|
c.renderHandler = renderHandler
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *renderContext) HandleInput(inputHandler func(ev *tcell.EventKey)) {
|
||||||
|
c.inputHandler = inputHandler
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *renderContext) onResize(ev *tcell.EventResize) {
|
||||||
|
width, height := ev.Size()
|
||||||
|
|
||||||
|
c.screen.Clear()
|
||||||
|
|
||||||
|
c.view.Resize(
|
||||||
|
(width/2)-(TERMINAL_SIZE_WIDTH/2),
|
||||||
|
(height/2)-(TERMINAL_SIZE_HEIGHT/2),
|
||||||
|
TERMINAL_SIZE_WIDTH,
|
||||||
|
TERMINAL_SIZE_HEIGHT,
|
||||||
|
)
|
||||||
|
|
||||||
|
c.screen.Sync()
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *renderContext) BeginRendering() {
|
||||||
|
c.lastRenderTime = time.Now()
|
||||||
|
|
||||||
|
for {
|
||||||
|
deltaTime := 1 + time.Since(c.lastRenderTime).Microseconds()
|
||||||
|
c.lastRenderTime = time.Now()
|
||||||
|
|
||||||
|
c.screen.Clear()
|
||||||
|
|
||||||
|
c.renderHandler(c.view, deltaTime)
|
||||||
|
|
||||||
|
c.screen.Show()
|
||||||
|
|
||||||
|
select {
|
||||||
|
case ev, ok := <-c.events:
|
||||||
|
|
||||||
|
if !ok {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
|
||||||
|
switch ev := ev.(type) {
|
||||||
|
case *tcell.EventResize:
|
||||||
|
c.onResize(ev)
|
||||||
|
case *tcell.EventKey:
|
||||||
|
c.inputHandler(ev)
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -4,6 +4,7 @@ import (
|
||||||
"mvvasilev/last_light/util"
|
"mvvasilev/last_light/util"
|
||||||
|
|
||||||
"github.com/gdamore/tcell/v2"
|
"github.com/gdamore/tcell/v2"
|
||||||
|
"github.com/gdamore/tcell/v2/views"
|
||||||
"github.com/google/uuid"
|
"github.com/google/uuid"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -21,18 +22,44 @@ type grid struct {
|
||||||
eastBorder rune
|
eastBorder rune
|
||||||
southBorder rune
|
southBorder rune
|
||||||
|
|
||||||
|
internalVerticalBorder rune
|
||||||
|
internalHorizontalBorder rune
|
||||||
|
|
||||||
nwCorner rune
|
nwCorner rune
|
||||||
swCorner rune
|
swCorner rune
|
||||||
seCorner rune
|
seCorner rune
|
||||||
neCorner rune
|
neCorner rune
|
||||||
|
|
||||||
verticalTJunction rune
|
verticalDownwardsTJunction rune
|
||||||
horizontalTJunction rune
|
verticalUpwardsTJunction rune
|
||||||
|
horizontalLeftTJunction rune
|
||||||
|
horizontalRightTJunction rune
|
||||||
crossJunction rune
|
crossJunction rune
|
||||||
|
|
||||||
fillRune rune
|
fillRune rune
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func CreateSimpleGrid(
|
||||||
|
x, y uint16,
|
||||||
|
cellWidth, cellHeight uint16,
|
||||||
|
numCellsHorizontal, numCellsVertical uint16,
|
||||||
|
borderRune, fillRune rune,
|
||||||
|
style tcell.Style,
|
||||||
|
) grid {
|
||||||
|
return CreateGrid(
|
||||||
|
x, y, cellWidth, cellHeight, numCellsHorizontal, numCellsVertical,
|
||||||
|
borderRune, borderRune, borderRune, borderRune,
|
||||||
|
borderRune, fillRune, borderRune, borderRune,
|
||||||
|
borderRune, borderRune, borderRune, borderRune,
|
||||||
|
borderRune, borderRune, borderRune, borderRune,
|
||||||
|
style,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
// '┌', '─', '┬', '┐',
|
||||||
|
// '│', '#', '│', '│',
|
||||||
|
// '├', '─', '┼', '┤',
|
||||||
|
// '└', '─', '┴', '┘',
|
||||||
func CreateGrid(
|
func CreateGrid(
|
||||||
x uint16,
|
x uint16,
|
||||||
y uint16,
|
y uint16,
|
||||||
|
@ -40,11 +67,10 @@ func CreateGrid(
|
||||||
cellHeight uint16,
|
cellHeight uint16,
|
||||||
numCellsHorizontal uint16,
|
numCellsHorizontal uint16,
|
||||||
numCellsVertical uint16,
|
numCellsVertical uint16,
|
||||||
nwCorner, northBorder, neCorner,
|
nwCorner, northBorder, verticalDownwardsTJunction, neCorner,
|
||||||
westBorder, fillRune, eastBorder,
|
westBorder, fillRune, internalVerticalBorder, eastBorder,
|
||||||
swCorner, southBorder, seCorner,
|
horizontalRightTJunction, internalHorizontalBorder, crossJunction, horizontalLeftTJunction,
|
||||||
verticalTJunction, horizontalTJunction,
|
swCorner, southBorder, verticalUpwardsTJunction, seCorner rune,
|
||||||
crossJunction rune,
|
|
||||||
style tcell.Style,
|
style tcell.Style,
|
||||||
) grid {
|
) grid {
|
||||||
return grid{
|
return grid{
|
||||||
|
@ -58,13 +84,18 @@ func CreateGrid(
|
||||||
eastBorder: eastBorder,
|
eastBorder: eastBorder,
|
||||||
southBorder: southBorder,
|
southBorder: southBorder,
|
||||||
westBorder: westBorder,
|
westBorder: westBorder,
|
||||||
|
internalVerticalBorder: internalVerticalBorder,
|
||||||
|
internalHorizontalBorder: internalHorizontalBorder,
|
||||||
nwCorner: nwCorner,
|
nwCorner: nwCorner,
|
||||||
seCorner: seCorner,
|
seCorner: seCorner,
|
||||||
swCorner: swCorner,
|
swCorner: swCorner,
|
||||||
neCorner: neCorner,
|
neCorner: neCorner,
|
||||||
|
verticalDownwardsTJunction: verticalDownwardsTJunction,
|
||||||
|
verticalUpwardsTJunction: verticalUpwardsTJunction,
|
||||||
|
horizontalRightTJunction: horizontalRightTJunction,
|
||||||
|
horizontalLeftTJunction: horizontalLeftTJunction,
|
||||||
fillRune: fillRune,
|
fillRune: fillRune,
|
||||||
verticalTJunction: verticalTJunction,
|
|
||||||
horizontalTJunction: horizontalTJunction,
|
|
||||||
crossJunction: crossJunction,
|
crossJunction: crossJunction,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -73,6 +104,46 @@ func (g grid) UniqueId() uuid.UUID {
|
||||||
return g.id
|
return g.id
|
||||||
}
|
}
|
||||||
|
|
||||||
func (g grid) Draw(s tcell.Screen) {
|
// C###T###T###C
|
||||||
|
// # # # #
|
||||||
|
// # # # #
|
||||||
|
// # # # #
|
||||||
|
// T###X###X###T
|
||||||
|
// # # # #
|
||||||
|
// # # # #
|
||||||
|
// # # # #
|
||||||
|
// T###X###X###T
|
||||||
|
// # # # #
|
||||||
|
// # # # #
|
||||||
|
// # # # #
|
||||||
|
// C###T###T###C
|
||||||
|
func (g grid) drawBorders(v views.View) {
|
||||||
|
width := 2 + (g.internalCellSize.Width() * int(g.numCellsHorizontal)) + (int(g.numCellsHorizontal) - 1)
|
||||||
|
height := 2 + (g.internalCellSize.Height() * int(g.numCellsVertical)) + (int(g.numCellsVertical) - 1)
|
||||||
|
x := g.position.X()
|
||||||
|
y := g.position.Y()
|
||||||
|
|
||||||
|
v.SetContent(x, y, g.nwCorner, nil, g.style)
|
||||||
|
v.SetContent(x+width-1, y, g.neCorner, nil, g.style)
|
||||||
|
v.SetContent(x, y+height-1, g.swCorner, nil, g.style)
|
||||||
|
v.SetContent(x+width-1, y+height-1, g.seCorner, nil, g.style)
|
||||||
|
|
||||||
|
for w := range width - 2 {
|
||||||
|
v.SetContent(1+w, y, g.northBorder, nil, g.style)
|
||||||
|
v.SetContent(1+w, y+height-1, g.southBorder, nil, g.style)
|
||||||
|
}
|
||||||
|
|
||||||
|
for h := range height - 2 {
|
||||||
|
v.SetContent(x, 1+h, g.westBorder, nil, g.style)
|
||||||
|
v.SetContent(x+width-1, 1+h, g.eastBorder, nil, g.style)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (g grid) drawFill(v views.View) {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (g grid) Draw(v views.View) {
|
||||||
|
g.drawBorders(v)
|
||||||
|
g.drawFill(v)
|
||||||
|
}
|
||||||
|
|
|
@ -3,7 +3,7 @@ package render
|
||||||
import (
|
import (
|
||||||
"slices"
|
"slices"
|
||||||
|
|
||||||
"github.com/gdamore/tcell/v2"
|
"github.com/gdamore/tcell/v2/views"
|
||||||
"github.com/google/uuid"
|
"github.com/google/uuid"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -31,7 +31,7 @@ func (l *layer) remove(uuid uuid.UUID) {
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
func (l *layer) draw(s tcell.Screen) {
|
func (l *layer) draw(s views.View) {
|
||||||
for _, d := range l.contents {
|
for _, d := range l.contents {
|
||||||
d.Draw(s)
|
d.Draw(s)
|
||||||
}
|
}
|
||||||
|
@ -112,7 +112,7 @@ func (ldc *layeredDrawContainer) UniqueId() uuid.UUID {
|
||||||
return ldc.id
|
return ldc.id
|
||||||
}
|
}
|
||||||
|
|
||||||
func (ldc *layeredDrawContainer) Draw(s tcell.Screen) {
|
func (ldc *layeredDrawContainer) Draw(s views.View) {
|
||||||
for _, d := range ldc.layers {
|
for _, d := range ldc.layers {
|
||||||
d.draw(s)
|
d.draw(s)
|
||||||
}
|
}
|
||||||
|
|
|
@ -4,6 +4,7 @@ import (
|
||||||
"mvvasilev/last_light/util"
|
"mvvasilev/last_light/util"
|
||||||
|
|
||||||
"github.com/gdamore/tcell/v2"
|
"github.com/gdamore/tcell/v2"
|
||||||
|
"github.com/gdamore/tcell/v2/views"
|
||||||
"github.com/google/uuid"
|
"github.com/google/uuid"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -24,16 +25,39 @@ type rectangle struct {
|
||||||
seCorner rune
|
seCorner rune
|
||||||
neCorner rune
|
neCorner rune
|
||||||
|
|
||||||
|
isBorderless bool
|
||||||
|
isFilled bool
|
||||||
|
|
||||||
fillRune rune
|
fillRune rune
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func CreateBorderlessRectangle(x, y uint16, width, height uint16, fillRune rune, style tcell.Style) rectangle {
|
||||||
|
return CreateRectangle(
|
||||||
|
x, y, width, height,
|
||||||
|
0, 0, 0,
|
||||||
|
0, fillRune, 0,
|
||||||
|
0, 0, 0,
|
||||||
|
true, true, style,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
func CreateSimpleEmptyRectangle(x, y uint16, width, height uint16, borderRune rune, style tcell.Style) rectangle {
|
||||||
|
return CreateRectangle(
|
||||||
|
x, y, width, height,
|
||||||
|
borderRune, borderRune, borderRune,
|
||||||
|
borderRune, 0, borderRune,
|
||||||
|
borderRune, borderRune, borderRune,
|
||||||
|
false, false, style,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
func CreateSimpleRectangle(x uint16, y uint16, width uint16, height uint16, borderRune rune, fillRune rune, style tcell.Style) rectangle {
|
func CreateSimpleRectangle(x uint16, y uint16, width uint16, height uint16, borderRune rune, fillRune rune, style tcell.Style) rectangle {
|
||||||
return CreateRectangle(
|
return CreateRectangle(
|
||||||
x, y, width, height,
|
x, y, width, height,
|
||||||
borderRune, borderRune, borderRune,
|
borderRune, borderRune, borderRune,
|
||||||
borderRune, fillRune, borderRune,
|
borderRune, fillRune, borderRune,
|
||||||
borderRune, borderRune, borderRune,
|
borderRune, borderRune, borderRune,
|
||||||
style,
|
false, true, style,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -43,6 +67,7 @@ func CreateSimpleRectangle(x uint16, y uint16, width uint16, height uint16, bord
|
||||||
// '┌', '─', '┐',
|
// '┌', '─', '┐',
|
||||||
// '│', ' ', '│',
|
// '│', ' ', '│',
|
||||||
// '└', '─', '┘',
|
// '└', '─', '┘',
|
||||||
|
// false, true,
|
||||||
// style
|
// style
|
||||||
//
|
//
|
||||||
// )
|
// )
|
||||||
|
@ -54,6 +79,7 @@ func CreateRectangle(
|
||||||
nwCorner, northBorder, neCorner,
|
nwCorner, northBorder, neCorner,
|
||||||
westBorder, fillRune, eastBorder,
|
westBorder, fillRune, eastBorder,
|
||||||
swCorner, southBorder, seCorner rune,
|
swCorner, southBorder, seCorner rune,
|
||||||
|
isBorderless, isFilled bool,
|
||||||
style tcell.Style,
|
style tcell.Style,
|
||||||
) rectangle {
|
) rectangle {
|
||||||
return rectangle{
|
return rectangle{
|
||||||
|
@ -69,6 +95,8 @@ func CreateRectangle(
|
||||||
seCorner: seCorner,
|
seCorner: seCorner,
|
||||||
swCorner: swCorner,
|
swCorner: swCorner,
|
||||||
neCorner: neCorner,
|
neCorner: neCorner,
|
||||||
|
isBorderless: isBorderless,
|
||||||
|
isFilled: isFilled,
|
||||||
fillRune: fillRune,
|
fillRune: fillRune,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -77,64 +105,42 @@ func (rect rectangle) UniqueId() uuid.UUID {
|
||||||
return rect.id
|
return rect.id
|
||||||
}
|
}
|
||||||
|
|
||||||
func (rect rectangle) Draw(s tcell.Screen) {
|
func (rect rectangle) drawBorders(v views.View) {
|
||||||
width := rect.size.Width()
|
width := rect.size.Width()
|
||||||
height := rect.size.Height()
|
height := rect.size.Height()
|
||||||
x := rect.position.X()
|
x := rect.position.X()
|
||||||
y := rect.position.Y()
|
y := rect.position.Y()
|
||||||
|
|
||||||
for h := range height {
|
v.SetContent(x, y, rect.nwCorner, nil, rect.style)
|
||||||
for w := range width {
|
v.SetContent(x+width-1, y, rect.neCorner, nil, rect.style)
|
||||||
|
v.SetContent(x, y+height-1, rect.swCorner, nil, rect.style)
|
||||||
|
v.SetContent(x+width-1, y+height-1, rect.seCorner, nil, rect.style)
|
||||||
|
|
||||||
// nw corner
|
for w := range width - 2 {
|
||||||
if w == 0 && h == 0 {
|
v.SetContent(1+w, y, rect.northBorder, nil, rect.style)
|
||||||
s.SetContent(x+w, y+h, rect.nwCorner, nil, rect.style)
|
v.SetContent(1+w, y+height-1, rect.southBorder, nil, rect.style)
|
||||||
continue
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// ne corner
|
for h := range height - 2 {
|
||||||
if w == (width-1) && h == 0 {
|
v.SetContent(x, 1+h, rect.westBorder, nil, rect.style)
|
||||||
s.SetContent(x+w, y+h, rect.neCorner, nil, rect.style)
|
v.SetContent(x+width-1, 1+h, rect.eastBorder, nil, rect.style)
|
||||||
continue
|
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// sw corner
|
func (rect rectangle) drawFill(v views.View) {
|
||||||
if w == 0 && h == (height-1) {
|
for w := range rect.size.Width() - 2 {
|
||||||
s.SetContent(x+w, y+h, rect.swCorner, nil, rect.style)
|
for h := range rect.size.Height() - 2 {
|
||||||
continue
|
v.SetContent(1+w, 1+h, rect.fillRune, nil, rect.style)
|
||||||
}
|
|
||||||
|
|
||||||
// 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)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (rect rectangle) Draw(v views.View) {
|
||||||
|
if !rect.isBorderless {
|
||||||
|
rect.drawBorders(v)
|
||||||
|
}
|
||||||
|
|
||||||
|
if rect.isFilled {
|
||||||
|
rect.drawFill(v)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -6,14 +6,10 @@ import (
|
||||||
"unicode/utf8"
|
"unicode/utf8"
|
||||||
|
|
||||||
"github.com/gdamore/tcell/v2"
|
"github.com/gdamore/tcell/v2"
|
||||||
|
"github.com/gdamore/tcell/v2/views"
|
||||||
"github.com/google/uuid"
|
"github.com/google/uuid"
|
||||||
)
|
)
|
||||||
|
|
||||||
type Drawable interface {
|
|
||||||
UniqueId() uuid.UUID
|
|
||||||
Draw(s tcell.Screen)
|
|
||||||
}
|
|
||||||
|
|
||||||
type text struct {
|
type text struct {
|
||||||
id uuid.UUID
|
id uuid.UUID
|
||||||
content []string
|
content []string
|
||||||
|
@ -41,7 +37,7 @@ func (t text) UniqueId() uuid.UUID {
|
||||||
return t.id
|
return t.id
|
||||||
}
|
}
|
||||||
|
|
||||||
func (t text) Draw(s tcell.Screen) {
|
func (t text) Draw(s views.View) {
|
||||||
width := t.size.Width()
|
width := t.size.Width()
|
||||||
height := t.size.Height()
|
height := t.size.Height()
|
||||||
x := t.position.X()
|
x := t.position.X()
|
||||||
|
|
Loading…
Add table
Reference in a new issue