aboutsummaryrefslogtreecommitdiff
path: root/ui/tcell/layout.go
diff options
context:
space:
mode:
Diffstat (limited to 'ui/tcell/layout.go')
-rw-r--r--ui/tcell/layout.go170
1 files changed, 170 insertions, 0 deletions
diff --git a/ui/tcell/layout.go b/ui/tcell/layout.go
new file mode 100644
index 0000000..599fb6a
--- /dev/null
+++ b/ui/tcell/layout.go
@@ -0,0 +1,170 @@
+package uitcell
+
+type Workspace struct {
+ x, y, w, h int
+ cols []*Column
+}
+
+type Column struct {
+ x, y, w, h int
+ windows []*Window
+}
+
+// Add adds a new column and resizes.
+func (wrk *Workspace) AddCol() {
+ nx, ny := wrk.x, wrk.y
+ nw, nh := wrk.w, wrk.h
+
+ if len(wrk.cols) > 0 {
+ nx = wrk.cols[len(wrk.cols)-1].x + wrk.cols[len(wrk.cols)-1].w/2
+ nw = wrk.cols[len(wrk.cols)-1].w / 2
+ wrk.cols[len(wrk.cols)-1].w /= 2
+ }
+
+ newcol := &Column{nx, ny, nw, nh, nil}
+ wrk.cols = append(wrk.cols, newcol)
+
+ wrk.Resize(wrk.x, wrk.y, wrk.w, wrk.h) // for re-arranging side effects
+}
+
+func (wrk *Workspace) CloseCol(c *Column) {
+ var j int
+ for _, col := range wrk.cols {
+ if col != c {
+ wrk.cols[j] = col
+ j++
+ }
+ }
+ wrk.cols = wrk.cols[:j]
+
+ wrk.Resize(wrk.x, wrk.y, wrk.w, wrk.h) // for re-arranging side effects
+}
+
+func (wrk *Workspace) Col(i int) *Column {
+ return wrk.cols[i]
+}
+
+func (wrk *Workspace) LastCol() *Column {
+ return wrk.cols[len(wrk.cols)-1]
+}
+
+func (wrk *Workspace) Resize(x, y, w, h int) {
+ wrk.x, wrk.y, wrk.w, wrk.h = x, y, w, h
+
+ n := len(wrk.cols)
+ if n == 0 {
+ return
+ }
+
+ var remainder int
+ if n > 0 {
+ remainder = w % (n)
+ }
+ for i := range wrk.cols {
+ if i == 0 {
+ var firstvertline int
+ if n > 1 {
+ firstvertline = 1
+ }
+ wrk.cols[i].Resize(x, y, (w/n)+remainder-(n-1)-firstvertline, h)
+ continue
+ }
+ // +i-n-1 on x so we do not draw on last vert line of previous col
+ wrk.cols[i].Resize((w/n)*i+remainder+i-(n-1), y, (w/n)-1, h)
+ }
+}
+
+func (wrk *Workspace) Draw() {
+ for _, col := range wrk.cols {
+ col.Draw()
+
+ // draw vertical lines between cols
+ for x, y := col.x+col.w+1, wrk.y; y < wrk.y+wrk.h; y++ {
+ screen.SetContent(x, y, '|', nil, vertlineStyle)
+ }
+ }
+}
+
+func (c *Column) AddWindow(win *Window) {
+ win.col = c
+ c.windows = append(c.windows, win)
+ c.ResizeWindows()
+}
+
+func (c *Column) CloseWindow(w *Window) {
+ var j int
+ for _, win := range c.windows {
+ if win != w {
+ c.windows[j] = win
+ j++
+ }
+ }
+ c.windows = c.windows[:j]
+
+ // If we deleted the current window (probably), select another
+ if CurWin == w {
+ all := AllWindows()
+
+ // If we are out of windows in our own column, pick another or exit
+ if len(c.windows) > 0 {
+ CurWin = c.windows[j-1]
+ } else {
+ // remove column
+ workspace.CloseCol(c)
+
+ // clear clutter
+ screen.Clear()
+
+ // find another window to focus or exit
+ if len(all) > 0 {
+ CurWin = AllWindows()[0]
+
+ } else {
+ ed.Run("Exit")
+ }
+ }
+
+ // if the only win left is the message win, close all
+ if len(all) == 1 && CurWin.Name() == FnMessageWin {
+ ed.Run("Exit")
+ }
+ }
+
+ c.ResizeWindows()
+}
+
+func (c *Column) Resize(x, y, w, h int) {
+ c.x, c.y = x, y
+ c.w, c.h = w, h
+
+ c.ResizeWindows()
+}
+
+func (c *Column) ResizeWindows() {
+ var n int
+ for _, win := range c.windows {
+ if !win.hidden {
+ n++
+ }
+ }
+
+ var remainder int
+ if n > 0 {
+ remainder = c.h % n
+ }
+ for i, win := range c.windows {
+ if i == 0 {
+ win.Resize(c.x, c.y, c.w, (c.h/n)+remainder)
+ continue
+ }
+ win.Resize(c.x, c.y+(c.h/n)*i+remainder, c.w, c.h/n)
+ }
+}
+
+func (c *Column) Draw() {
+ for _, win := range c.windows {
+ if !win.hidden {
+ win.Draw()
+ }
+ }
+}