Working on buffer stuff...
Trying to figure out how/if it fits...
This commit is contained in:
24
buffer.go
24
buffer.go
@@ -27,7 +27,6 @@ import (
|
||||
)
|
||||
|
||||
type Buffer struct {
|
||||
// cells [][]Cell
|
||||
cells map[Coord]Cell
|
||||
maxX, maxY int
|
||||
minX, minY int
|
||||
@@ -46,6 +45,22 @@ func (b *Buffer) Draw(x, y int, screen tcell.Screen) {
|
||||
}
|
||||
}
|
||||
|
||||
// MoveTo moves the minimum x and y of the buffer to x, y
|
||||
// All cell coordinates are updated accordingly
|
||||
func (b *Buffer) MoveTo(x, y int) {
|
||||
diffX := b.minX - x
|
||||
diffY := b.minY - y
|
||||
cells := make(map[Coord]Cell)
|
||||
for k, v := range b.cells {
|
||||
cells[Coord{X: k.X - diffX, Y: k.Y - diffY}] = v
|
||||
}
|
||||
}
|
||||
|
||||
func (b *Buffer) Clear() {
|
||||
b.cells = make(map[Coord]Cell)
|
||||
b.maxX, b.maxY, b.minX, b.minY = 0, 0, 0, 0
|
||||
}
|
||||
|
||||
func (b *Buffer) SetCell(x, y int, c Cell) {
|
||||
b.cells[Coord{X: x, Y: y}] = c
|
||||
b.maxX, b.maxY = h.Max(b.maxX, x), h.Max(b.maxY, y)
|
||||
@@ -60,6 +75,13 @@ func (b *Buffer) SetCells(x, y int, c [][]Cell) {
|
||||
}
|
||||
}
|
||||
|
||||
func (b *Buffer) Merge(atX, atY int, b2 *Buffer) {
|
||||
b2.MoveTo(atX, atY)
|
||||
for k, v := range b2.cells {
|
||||
b.cells[k] = v
|
||||
}
|
||||
}
|
||||
|
||||
// Buffer Helpers
|
||||
func (b *Buffer) FillText(x, y int, txt string, style tcell.Style) {
|
||||
for i := range txt {
|
||||
|
||||
@@ -50,7 +50,7 @@ type AbsoluteLayout struct {
|
||||
cursor int
|
||||
disableTab bool
|
||||
|
||||
logger func(string)
|
||||
logger func(string, ...any)
|
||||
}
|
||||
|
||||
var _ Widget = (*AbsoluteLayout)(nil)
|
||||
@@ -209,10 +209,10 @@ func (w *AbsoluteLayout) Clear() {
|
||||
|
||||
func (w *AbsoluteLayout) SetDefaultAnchor(d LayoutFlag) { w.defAnchor = d }
|
||||
|
||||
func (w *AbsoluteLayout) SetLogger(l func(string)) { w.logger = l }
|
||||
func (w *AbsoluteLayout) Log(txt string) {
|
||||
func (w *AbsoluteLayout) SetLogger(l func(string, ...any)) { w.logger = l }
|
||||
func (w *AbsoluteLayout) Log(txt string, args ...any) {
|
||||
if w.logger != nil {
|
||||
w.logger(txt)
|
||||
w.logger(txt, args...)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -229,21 +229,39 @@ func (w *AbsoluteLayout) updateWidgetLayouts() {
|
||||
for _, wd := range w.widgets {
|
||||
w.updateWidgetPos(wd)
|
||||
}
|
||||
var updated []Widget
|
||||
for wd := range w.wManualSizes {
|
||||
w.updateWidgetSize(wd)
|
||||
updated = append(updated, wd)
|
||||
}
|
||||
for wd := range w.wDynamicSizes {
|
||||
w.updateWidgetSize(wd)
|
||||
updated = append(updated, wd)
|
||||
}
|
||||
for i := range w.widgets {
|
||||
var next bool
|
||||
for j := range updated {
|
||||
if updated[j] == w.widgets[i] {
|
||||
next = true
|
||||
}
|
||||
}
|
||||
if next {
|
||||
continue
|
||||
}
|
||||
w.updateWidgetSize(w.widgets[i])
|
||||
}
|
||||
}
|
||||
|
||||
// Set a widgets position relative to the layout
|
||||
func (w *AbsoluteLayout) updateWidgetPos(wd Widget) {
|
||||
wd.SetPos(w.getRelPos(wd))
|
||||
p := w.getRelPos(wd)
|
||||
w.Log("%s: Setting Pos: %s (%d,%d)", w.Id(), wd.Id(), p.X, p.Y)
|
||||
wd.SetPos(p)
|
||||
}
|
||||
|
||||
func (w *AbsoluteLayout) updateWidgetSize(wd Widget) {
|
||||
if sz, ok := w.wManualSizes[wd]; ok {
|
||||
w.Log("%s: Updating Size: %s (%d,%d)", w.Id(), wd.Id(), sz.X, sz.Y)
|
||||
wd.SetW(sz.X)
|
||||
wd.SetH(sz.Y)
|
||||
return
|
||||
@@ -252,19 +270,17 @@ func (w *AbsoluteLayout) updateWidgetSize(wd Widget) {
|
||||
// X: Layout Width - Widget X
|
||||
// Y: Layout Height - Widget Y
|
||||
available := Coord{X: w.GetW() - wd.GetX(), Y: w.GetH() - wd.GetY()}
|
||||
ww := wd.WantW()
|
||||
if ww < available.X {
|
||||
wd.SetW(ww)
|
||||
} else if wd.MinW() < available.X {
|
||||
if wd.WantW() < available.X {
|
||||
wd.SetW(wd.WantW())
|
||||
} else if wd.MinW() > available.X {
|
||||
wd.SetW(available.X)
|
||||
} else {
|
||||
wd.SetW(wd.MinW())
|
||||
}
|
||||
|
||||
wh := wd.WantH()
|
||||
if wh < available.Y {
|
||||
wd.SetH(wh)
|
||||
} else if wd.MinH() < available.Y {
|
||||
if wd.WantH() < available.Y {
|
||||
wd.SetH(wd.WantH())
|
||||
} else if wd.MinH() > available.Y {
|
||||
wd.SetH(available.Y)
|
||||
} else {
|
||||
wd.SetH(wd.MinH())
|
||||
@@ -272,8 +288,13 @@ func (w *AbsoluteLayout) updateWidgetSize(wd Widget) {
|
||||
}
|
||||
|
||||
// Manually set the size of a widget, the Layout won't override it
|
||||
func (w *AbsoluteLayout) SetWidgetSize(wd Widget, sz Coord) { w.wManualSizes[wd] = sz }
|
||||
func (w *AbsoluteLayout) SetDynamicWidgetSize(wd Widget, flg LayoutFlag) { w.wDynamicSizes[wd] = flg }
|
||||
func (w *AbsoluteLayout) SetWidgetSize(wd Widget, sz Coord) {
|
||||
w.wManualSizes[wd] = sz
|
||||
}
|
||||
|
||||
func (w *AbsoluteLayout) SetDynamicWidgetSize(wd Widget, flg LayoutFlag) {
|
||||
w.wDynamicSizes[wd] = flg
|
||||
}
|
||||
|
||||
func (w *AbsoluteLayout) getRelPos(wd Widget) Coord {
|
||||
var p Coord
|
||||
@@ -339,6 +360,7 @@ func (w *AbsoluteLayout) DeleteIndex(idx int) {
|
||||
delete(w.wAnchor, p)
|
||||
}
|
||||
}
|
||||
|
||||
func (w *AbsoluteLayout) Delete(n Widget) {
|
||||
for i := 0; i < len(w.widgets); i++ {
|
||||
if w.widgets[i] == n {
|
||||
@@ -347,6 +369,7 @@ func (w *AbsoluteLayout) Delete(n Widget) {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func (w *AbsoluteLayout) IndexOf(n Widget) int {
|
||||
for i := range w.widgets {
|
||||
if w.widgets[i] == n {
|
||||
|
||||
@@ -32,10 +32,12 @@ import (
|
||||
// ArtWidget displays it's text as ascii art.
|
||||
type ArtWidget struct {
|
||||
id string
|
||||
x, y int
|
||||
w, h int
|
||||
style tcell.Style
|
||||
|
||||
x, y int
|
||||
w, h int
|
||||
buffer Buffer
|
||||
|
||||
active bool
|
||||
visible bool
|
||||
focusable bool
|
||||
@@ -60,6 +62,7 @@ func NewArtWidget(id string, st tcell.Style) *ArtWidget {
|
||||
|
||||
func (w *ArtWidget) Init(id string, st tcell.Style) {
|
||||
w.id = id
|
||||
w.visible = true
|
||||
w.style = st
|
||||
w.keyMap = BlankKeyMap()
|
||||
w.initFonts()
|
||||
@@ -79,34 +82,10 @@ func (w *ArtWidget) RemoveFromKeyMap(km KeyMap) {
|
||||
func (w *ArtWidget) HandleKey(ev *tcell.EventKey) bool { return false }
|
||||
func (w *ArtWidget) HandleTime(ev *tcell.EventTime) {}
|
||||
func (w *ArtWidget) Draw(screen tcell.Screen) {
|
||||
x, y := w.x, w.y
|
||||
for _, ch := range w.text {
|
||||
w.drawRune(ch, x, y, screen)
|
||||
x += w.getRuneWidth(ch)
|
||||
if !w.visible {
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
func (w *ArtWidget) drawRune(r rune, x, y int, screen tcell.Screen) {
|
||||
wx, wy := x, y
|
||||
rs := w.getRune(r)
|
||||
for _, ln := range rs {
|
||||
wx = x
|
||||
for _, d := range ln {
|
||||
screen.SetContent(wx, wy, d, nil, w.style)
|
||||
wx++
|
||||
}
|
||||
wy++
|
||||
}
|
||||
}
|
||||
|
||||
func (w *ArtWidget) getRune(r rune) [][]rune { return w.currFont.GetRune(r) }
|
||||
func (w *ArtWidget) getRuneHeight(r rune) int { return len(w.getRune(r)) }
|
||||
func (w *ArtWidget) getRuneWidth(r rune) int {
|
||||
rn := w.getRune(r)
|
||||
if len(rn) > 0 {
|
||||
return len(rn[0])
|
||||
}
|
||||
return 0
|
||||
w.buffer.Draw(w.x, w.y, screen)
|
||||
}
|
||||
|
||||
func (w *ArtWidget) Active() bool { return w.active }
|
||||
@@ -127,31 +106,47 @@ func (w *ArtWidget) SetH(h int) { w.h = h }
|
||||
func (w *ArtWidget) GetW() int { return w.w }
|
||||
func (w *ArtWidget) GetH() int { return w.h }
|
||||
|
||||
func (w *ArtWidget) WantW() int {
|
||||
var wd int
|
||||
func (w *ArtWidget) WantW() int { return w.buffer.Width() }
|
||||
func (w *ArtWidget) WantH() int { return w.buffer.Height() }
|
||||
func (w *ArtWidget) MinW() int { return w.buffer.Width() }
|
||||
func (w *ArtWidget) MinH() int { return w.buffer.Height() }
|
||||
|
||||
func (w *ArtWidget) SetText(txt string) {
|
||||
w.text = txt
|
||||
w.buildBuffer()
|
||||
}
|
||||
func (w *ArtWidget) GetText() string { return w.text }
|
||||
|
||||
func (w *ArtWidget) SetFont(fnt string) {
|
||||
w.font = fnt
|
||||
w.buildBuffer()
|
||||
}
|
||||
func (w *ArtWidget) GetFont() string { return w.font }
|
||||
func (w *ArtWidget) buildBuffer() {
|
||||
b := NewBuffer()
|
||||
x, y := w.x, w.y
|
||||
chX := x
|
||||
for _, ch := range w.text {
|
||||
r := w.getRune(ch)
|
||||
if len(r) > 0 {
|
||||
wd += len(r[0])
|
||||
if ch == '\n' {
|
||||
x = w.x
|
||||
y = b.Height() + 1
|
||||
continue
|
||||
}
|
||||
rs := w.getRune(ch)
|
||||
var maxX int
|
||||
for rY, ln := range rs {
|
||||
for rX, bt := range ln {
|
||||
b.SetCell(chX+rX, y+rY, *NewCell(bt, w.style))
|
||||
if chX+rX > maxX {
|
||||
maxX = chX + rX
|
||||
}
|
||||
}
|
||||
}
|
||||
chX = maxX + 1
|
||||
}
|
||||
w.Log("%s: Want Width: %d", w.Id(), wd)
|
||||
return wd
|
||||
w.buffer = b
|
||||
}
|
||||
|
||||
func (w *ArtWidget) WantH() int {
|
||||
h := len(w.getRune('Q'))
|
||||
w.Log("%s: Want Height: %d", w.Id(), h)
|
||||
return h
|
||||
}
|
||||
func (w *ArtWidget) MinW() int { return w.WantW() }
|
||||
func (w *ArtWidget) MinH() int { return w.WantH() }
|
||||
|
||||
func (w *ArtWidget) SetText(txt string) { w.text = txt }
|
||||
func (w *ArtWidget) GetText() string { return w.text }
|
||||
|
||||
func (w *ArtWidget) SetFont(fnt string) { w.font = fnt }
|
||||
func (w *ArtWidget) GetFont() string { return w.font }
|
||||
func (w *ArtWidget) getRune(r rune) [][]rune { return w.currFont.GetRune(r) }
|
||||
|
||||
func (w *ArtWidget) initFonts() {
|
||||
f := NewArtWidgetFont("miniwi")
|
||||
|
||||
@@ -33,8 +33,10 @@ type Searcher struct {
|
||||
id string
|
||||
style tcell.Style
|
||||
|
||||
x, y int
|
||||
w, h int
|
||||
x, y int
|
||||
w, h int
|
||||
buffer Buffer
|
||||
|
||||
active bool
|
||||
visible bool
|
||||
focusable bool
|
||||
@@ -94,6 +96,7 @@ func (w *Searcher) HandleResize(ev *tcell.EventResize) {
|
||||
}
|
||||
w.search.SetPos(Coord{X: 1, Y: 1})
|
||||
w.search.HandleResize(Coord{X: aW, Y: aH}.ResizeEvent())
|
||||
// w.buildBuffer()
|
||||
}
|
||||
|
||||
func (w *Searcher) SetKeyMap(km KeyMap, def bool) {
|
||||
@@ -126,7 +129,11 @@ func (w *Searcher) HandleKey(ev *tcell.EventKey) bool {
|
||||
if w.cursor != sel && w.onChange != nil {
|
||||
w.onChange(w.cursor, w.filteredData[w.cursor])
|
||||
}
|
||||
return b1 || b2 || ret
|
||||
if b1 || b2 || ret {
|
||||
// w.buildBuffer()
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
func (w *Searcher) handleKeyUp(ev *tcell.EventKey) bool {
|
||||
@@ -134,6 +141,7 @@ func (w *Searcher) handleKeyUp(ev *tcell.EventKey) bool {
|
||||
return false
|
||||
}
|
||||
w.cursor = ((w.cursor - 1) + len(w.filteredData)) % len(w.filteredData)
|
||||
// w.buildBuffer()
|
||||
return true
|
||||
}
|
||||
|
||||
@@ -142,6 +150,7 @@ func (w *Searcher) handleKeyDown(ev *tcell.EventKey) bool {
|
||||
return false
|
||||
}
|
||||
w.cursor = ((w.cursor + 1) + len(w.filteredData)) % len(w.filteredData)
|
||||
// w.buildBuffer()
|
||||
return true
|
||||
}
|
||||
|
||||
@@ -150,6 +159,7 @@ func (w *Searcher) handleKeyHome(ev *tcell.EventKey) bool {
|
||||
return false
|
||||
}
|
||||
w.cursor = 0
|
||||
// w.buildBuffer()
|
||||
return true
|
||||
}
|
||||
|
||||
@@ -158,6 +168,7 @@ func (w *Searcher) handleKeyEnd(ev *tcell.EventKey) bool {
|
||||
return false
|
||||
}
|
||||
w.cursor = len(w.filteredData) - 1
|
||||
// w.buildBuffer()
|
||||
return true
|
||||
}
|
||||
|
||||
@@ -169,8 +180,8 @@ func (w *Searcher) handleKeyPgUp(ev *tcell.EventKey) bool {
|
||||
if w.cursor < 0 {
|
||||
w.cursor = 0
|
||||
}
|
||||
|
||||
return false
|
||||
// w.buildBuffer()
|
||||
return true
|
||||
}
|
||||
|
||||
func (w *Searcher) handleKeyPgDn(ev *tcell.EventKey) bool {
|
||||
@@ -182,7 +193,8 @@ func (w *Searcher) handleKeyPgDn(ev *tcell.EventKey) bool {
|
||||
if w.cursor > mx {
|
||||
w.cursor = mx
|
||||
}
|
||||
return false
|
||||
// w.buildBuffer()
|
||||
return true
|
||||
}
|
||||
|
||||
func (w *Searcher) handleKeyEnter(ev *tcell.EventKey) bool {
|
||||
@@ -200,7 +212,9 @@ func (w *Searcher) handleKeyEnter(ev *tcell.EventKey) bool {
|
||||
idx = i
|
||||
}
|
||||
}
|
||||
return w.selectFunc(idx, selV)
|
||||
res := w.selectFunc(idx, selV)
|
||||
// w.buildBuffer()
|
||||
return res
|
||||
}
|
||||
|
||||
func (w *Searcher) HandleTime(ev *tcell.EventTime) { w.search.HandleTime(ev) }
|
||||
@@ -208,6 +222,11 @@ func (w *Searcher) Draw(screen tcell.Screen) {
|
||||
if !w.visible {
|
||||
return
|
||||
}
|
||||
w.oldDraw(screen)
|
||||
// w.buffer.Draw(w.x, w.y, screen)
|
||||
}
|
||||
|
||||
func (w *Searcher) oldDraw(screen tcell.Screen) {
|
||||
dStyle := w.style.Dim(!w.active)
|
||||
if !w.disableBorder {
|
||||
if len(w.title) > 0 {
|
||||
@@ -216,7 +235,7 @@ func (w *Searcher) Draw(screen tcell.Screen) {
|
||||
wh.BorderFilled(w.x, w.y, w.x+w.w, w.y+w.h, wh.BRD_CSIMPLE, dStyle, screen)
|
||||
}
|
||||
}
|
||||
//w.GetPos().DrawOffset(w.search, screen)
|
||||
// w.GetPos().DrawOffset(w.search, screen)
|
||||
x, y := w.x+1, w.y+2
|
||||
w.search.SetPos(Coord{X: w.x + 1, Y: w.y + 1})
|
||||
w.search.Draw(screen)
|
||||
@@ -242,6 +261,20 @@ func (w *Searcher) Draw(screen tcell.Screen) {
|
||||
}
|
||||
}
|
||||
|
||||
func (w *Searcher) buildBuffer() {
|
||||
b := NewBuffer()
|
||||
dStyle := w.style.Dim(!w.active)
|
||||
if !w.disableBorder {
|
||||
if len(w.title) > 0 {
|
||||
w.buffer.TitledBorderFilled(0, 0, w.w, w.y, w.title, wh.BRD_CSIMPLE, dStyle)
|
||||
} else {
|
||||
w.buffer.BorderFilled(0, 0, w.w, w.y, wh.BRD_CSIMPLE, dStyle)
|
||||
}
|
||||
}
|
||||
// x, y := 1, 1
|
||||
w.buffer = b
|
||||
}
|
||||
|
||||
func (w *Searcher) Active() bool { return w.active }
|
||||
func (w *Searcher) SetActive(a bool) {
|
||||
w.active = a
|
||||
|
||||
Reference in New Issue
Block a user