summaryrefslogtreecommitdiff
path: root/tui/layout.go
diff options
context:
space:
mode:
Diffstat (limited to 'tui/layout.go')
-rw-r--r--tui/layout.go131
1 files changed, 20 insertions, 111 deletions
diff --git a/tui/layout.go b/tui/layout.go
index 0681e8e..e2c3e0f 100644
--- a/tui/layout.go
+++ b/tui/layout.go
@@ -2,7 +2,6 @@ package tui
import (
"github.com/rivo/uniseg"
- "strings"
"unicode"
)
@@ -16,9 +15,6 @@ type Box struct {
Scroll *ScrollState
text []textRun
computedLines [][]textRun
- cursorLine int
- cursorCol int
- hasCursor bool
children []*Box
computedPosition int
computedSize [2]int
@@ -36,43 +32,12 @@ func (s BoxSize) isFlexible() bool {
return s == Fill
}
-type Direction int
-const (
- Down = iota
- Up
- Right
- Left
-)
-
-func (d Direction) axis() int {
- switch d {
- case Down, Up:
- return 1
- default:
- return 0
- }
-}
-
-func (d Direction) reverse() bool {
- switch d {
- case Down, Right:
- return false
- default:
- return true
- }
-}
-
type textRun struct {
text string
style *Style
hasCursor bool
}
-type rect struct {
- min [2]int
- max [2]int
-}
-
type ScrollState struct {
at string
offset int
@@ -81,6 +46,8 @@ type ScrollState struct {
atLast bool
}
+var Selected string
+
func (s *ScrollState) ToStart() {
*s = ScrollState {}
}
@@ -237,85 +204,32 @@ func (b *Box) computeText(axis int) {
} else {
var (
limit = b.computedSize[0]
- line []textRun
- text, word strings.Builder
- lineWidth, wordWidth int
- hasCursor bool
- cursorAt int
- run textRun
+ line, word builder
)
- flushText := func() {
- if text.Len() != 0 {
- line = append(line, textRun {text.String(), run.style, false})
- }
- text.Reset()
- }
- flushLine := func() {
- flushText()
- b.computedLines = append(b.computedLines, line)
- lineWidth = 0
- line = nil
- }
- breakWord := func() {
- if lineWidth + wordWidth > limit {
- flushLine()
- }
- g := uniseg.NewGraphemes(word.String())
- pos := 0
- for g.Next() {
- if hasCursor && pos == cursorAt {
- b.cursorLine = len(b.computedLines)
- b.cursorCol = lineWidth
- b.hasCursor = true
- hasCursor = false
- }
-
- if g.Width() > limit {
- continue
- }
- if lineWidth == 0 && g.Str() == " " {
- continue
- }
- text.WriteString(g.Str())
- if g.Width() + lineWidth > limit {
- flushLine()
- }
- lineWidth += g.Width()
-
- pos++
- }
- wordWidth = 0
- word.Reset()
- }
for _, run := range b.text {
if run.hasCursor {
- hasCursor = true
- cursorAt = wordWidth
+ word.addRun(run)
+ word.addRun(textRun {"", nil, false})
}
g := uniseg.NewGraphemes(run.text)
for g.Next() {
- if g.LineBreak() == uniseg.LineCanBreak {
- breakWord()
+ word.add(g.Str(), run.style)
+ if word.width >= limit {
+ line.addRuns(word.flush())
+ } else if line.width + word.width >= limit {
+ b.computedLines = append(b.computedLines, line.flush())
}
- if lineWidth != 0 || !unicode.IsSpace(g.Runes()[0]) {
- word.WriteString(g.Str())
- wordWidth += g.Width()
+ if unicode.IsSpace(g.Runes()[0]) {
+ line.addRuns(word.flush())
}
- _, end := g.Positions()
- if end == len(run.text) {
- breakWord()
- break
- }
- if g.LineBreak() == uniseg.LineMustBreak {
- breakWord()
- flushLine()
+ if g.Str() == "\n" {
+ line.addRuns(word.flush())
+ b.computedLines = append(b.computedLines, line.flush())
}
}
- flushText()
- }
- if len(line) != 0 || text.Len() != 0 {
- flushLine()
}
+ line.addRuns(word.flush())
+ b.computedLines = append(b.computedLines, line.flush())
if b.Height == TextSize {
b.computedSize[axis] = len(b.computedLines) + b.marginsSize(axis)
}
@@ -458,17 +372,12 @@ func (b *Box) drawComputed(parentRect rect, parentStyle Style) {
} else {
s = style
}
+ if t.hasCursor {
+ ShowCursor(x, y)
+ }
x += WriteAt(x, y, t.text, s)
}
}
- if b.hasCursor {
- cx := b.cursorCol + b.computedRect.min[0] + b.Margins[0]
- cy := b.cursorLine + b.computedRect.min[1] + b.Margins[2]
- if cx >= viewRect.min[0] && cx < viewRect.max[0] &&
- cy >= viewRect.min[1] && cy < viewRect.max[1] {
- ShowCursor(cx, cy)
- }
- }
for _, c := range b.children {
c.drawComputed(viewRect, style)
}