diff options
Diffstat (limited to 'ui/tcell/layout.go')
-rw-r--r-- | ui/tcell/layout.go | 170 |
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() + } + } +} |