summaryrefslogtreecommitdiff
path: root/tui/layout.go
diff options
context:
space:
mode:
Diffstat (limited to 'tui/layout.go')
-rw-r--r--tui/layout.go123
1 files changed, 109 insertions, 14 deletions
diff --git a/tui/layout.go b/tui/layout.go
index 1b3c3ed..210924f 100644
--- a/tui/layout.go
+++ b/tui/layout.go
@@ -7,12 +7,13 @@ import (
)
type Box struct {
+ id string
Width, Height BoxSize
Dir Direction
Overflow bool
- Scroll int
Style *Style
Margins [4]int
+ Scroll *ScrollState
text []textRun
computedLines [][]textRun
children []*Box
@@ -68,10 +69,29 @@ type rect struct {
max [2]int
}
-type BoxEvent struct {
+type ScrollState struct {
+ at string
+ offset int
+ absolute int
+ atFirst bool
+ atLast bool
}
-type TextEvent struct {
+func (s *ScrollState) ToStart() {
+ *s = ScrollState {}
+}
+
+func (s *ScrollState) AtFirst() bool {
+ return s.atFirst
+}
+
+func (s *ScrollState) AtLast() bool {
+ return s.atLast
+}
+
+func (s *ScrollState) Scroll(amnt int) {
+ s.offset += amnt
+ s.absolute += amnt
}
var layout struct {
@@ -89,23 +109,22 @@ func top() *Box {
return layout.stack[len(layout.stack) - 1]
}
-func Push(id string, box Box) BoxEvent {
+func Push(id string, box Box) {
if len(layout.stack) > 0 {
top().children = append(top().children, &box)
}
layout.stack = append(layout.stack, &box)
layout.front[id] = &box
+ box.id = id
for axis, value := range box.axes() {
if value >= 0 {
box.computedSize[axis] = int(value)
}
}
- return BoxEvent {}
}
-func Text(text string, style *Style) TextEvent {
+func Text(text string, style *Style) {
top().text = append(top().text, textRun {text, style})
- return TextEvent {}
}
func Pop() {
@@ -292,12 +311,65 @@ func (b *Box) computePositions(axis int) {
if b.Dir.reverse() {
pos -= c.computedSize[axis]
}
+
c.computedPosition = pos
- c.computedRect.min[axis] = b.computedRect.min[axis] + pos
- c.computedRect.max[axis] = c.computedRect.min[axis] + c.computedSize[axis]
+
+ if b.Scroll != nil && b.Scroll.at != "" && b.Scroll.at == c.id {
+ p := c.computedPosition
+ if b.Dir.reverse() {
+ p = b.computedSize[axis] - p
+ }
+ b.Scroll.absolute = p
+ if !b.Dir.reverse() {
+ b.Scroll.absolute += b.Scroll.offset
+ } else {
+ b.Scroll.absolute += b.Scroll.offset
+ }
+ }
+
if !b.Dir.reverse() {
pos += c.computedSize[axis]
}
+ }
+ if b.Scroll != nil {
+ var first *Box
+ var last *Box
+ for _, c := range b.children {
+ if !b.Dir.reverse() {
+ c.computedPosition -= b.Scroll.absolute
+ } else {
+ c.computedPosition += b.Scroll.absolute
+ }
+ if c.computedPosition > b.computedRect.min[axis] &&
+ c.computedPosition < b.computedRect.max[axis] {
+ if first == nil {
+ first = c
+ }
+ last = c
+ }
+ }
+ if first == b.children[0] {
+ b.Scroll.atFirst = true
+ }
+ if last == b.children[len(b.children) - 1] {
+ b.Scroll.atLast = true
+ }
+ if first != nil {
+ p := first.computedPosition
+ if b.Dir.reverse() {
+ p = b.computedSize[axis] - p
+ }
+ b.Scroll.offset = -p
+ b.Scroll.at = first.id
+ }
+ if b.Scroll.absolute == 0 {
+ b.Scroll.at = ""
+ b.Scroll.offset = 0
+ }
+ }
+ for _, c := range b.children {
+ c.computedRect.min[axis] = b.computedRect.min[axis] + c.computedPosition
+ c.computedRect.max[axis] = c.computedRect.min[axis] + c.computedSize[axis]
c.computePositions(axis)
}
} else {
@@ -309,12 +381,22 @@ func (b *Box) computePositions(axis int) {
}
}
-func (b *Box) drawComputed(parentStyle Style) {
+func (b *Box) drawComputed(parentRect rect, parentStyle Style) {
+ var viewRect rect = parentRect;
+ for i := 0; i < 2; i++ {
+ bMin := b.computedRect.min[i] + b.Margins[i * 2]
+ viewRect.min[i] = max(bMin, parentRect.min[i])
+ }
+ for i := 0; i < 2; i++ {
+ bMax := b.computedRect.max[i] - b.Margins[i * 2 + 1]
+ viewRect.max[i] = min(bMax, parentRect.max[i])
+ }
+
style := parentStyle
if b.Style != nil {
style = *b.Style
- for y := b.computedRect.min[1]; y < b.computedRect.max[1]; y++ {
- for x := b.computedRect.min[0]; x < b.computedRect.max[0]; x++ {
+ for y := viewRect.min[1]; y < viewRect.max[1]; y++ {
+ for x := viewRect.min[0]; x < viewRect.max[0]; x++ {
WriteAt(x, y, " ", style)
}
}
@@ -325,6 +407,15 @@ func (b *Box) drawComputed(parentStyle Style) {
if y > b.computedRect.max[1] - b.Margins[3] {
break
}
+ if y < b.computedRect.min[1] + b.Margins[2] {
+ continue
+ }
+ if y > parentRect.max[1] {
+ break
+ }
+ if y < parentRect.min[1] {
+ continue
+ }
for _, t := range l {
var s Style
if t.style != nil {
@@ -336,7 +427,7 @@ func (b *Box) drawComputed(parentStyle Style) {
}
}
for _, c := range b.children {
- c.drawComputed(style)
+ c.drawComputed(viewRect, style)
}
}
@@ -357,5 +448,9 @@ func DrawLayout() {
b.solve(axis)
b.computePositions(axis)
}
- b.drawComputed(DefaultStyle)
+ var parentRect rect
+ size := Size()
+ parentRect.max = [2]int {size.Width, size.Height}
+ b.computedRect = parentRect
+ b.drawComputed(parentRect, DefaultStyle)
}