From a0591e399d5228ce27a2ca55acb5376c2b76ccac Mon Sep 17 00:00:00 2001 From: Petter Rodhelind Date: Sat, 6 Mar 2021 20:14:06 +0100 Subject: Manage columns in a sane way. --- ui/tcell/layout.go | 76 ++++++++++++++++++++++++++-------- ui/tcell/style.go | 19 +++++---- ui/tcell/tcell.go | 118 ++++++++++++++++++++++++++++++++++++++++++++--------- ui/tcell/view.go | 18 +++++--- ui/tcell/window.go | 1 + 5 files changed, 182 insertions(+), 50 deletions(-) (limited to 'ui') diff --git a/ui/tcell/layout.go b/ui/tcell/layout.go index 7a1fa6a..8a96e4b 100644 --- a/ui/tcell/layout.go +++ b/ui/tcell/layout.go @@ -1,17 +1,29 @@ package uitcell +import ( + "fmt" + + "github.com/prodhe/poe/editor" +) + +const ( + RuneVerticalLine = '\u2502' // \u007c = |, \u23b8, \u2502 +) + type Workspace struct { x, y, w, h int + tagline *View cols []*Column } type Column struct { x, y, w, h int + tagline *View windows []*Window } // Add adds a new column and resizes. -func (wrk *Workspace) AddCol() { +func (wrk *Workspace) AddCol() *Column { nx, ny := wrk.x, wrk.y nw, nh := wrk.w, wrk.h @@ -21,10 +33,32 @@ func (wrk *Workspace) AddCol() { wrk.cols[len(wrk.cols)-1].w /= 2 } - newcol := &Column{nx, ny, nw, nh, nil} - wrk.cols = append(wrk.cols, newcol) + newcol := &Column{ + x: nx, + y: ny, + w: nw, + h: nh, + tagline: &View{ + text: &editor.Buffer{}, + what: ViewColumn, + style: bodyStyle, + cursorStyle: bodyCursorStyle, + hilightStyle: bodyHilightStyle, + tabstop: 4, + }, + windows: nil, + } + fmt.Fprintf(newcol.tagline, "%s", "New Delcol ") + + if len(wrk.cols) > 1 { + wrk.cols = append(wrk.cols[:len(wrk.cols)-1], newcol, wrk.cols[len(wrk.cols)-1]) + } else { + wrk.cols = append(wrk.cols, newcol) + } wrk.Resize(wrk.x, wrk.y, wrk.w, wrk.h) // for re-arranging side effects + + return newcol } func (wrk *Workspace) CloseCol(c *Column) { @@ -53,6 +87,8 @@ func (wrk *Workspace) LastCol() *Column { func (wrk *Workspace) Resize(x, y, w, h int) { wrk.x, wrk.y, wrk.w, wrk.h = x, y, w, h + wrk.tagline.x, wrk.tagline.y, wrk.tagline.w = x, y, w + wrk.tagline.h = 1 n := len(wrk.cols) if n == 0 { @@ -69,22 +105,22 @@ func (wrk *Workspace) Resize(x, y, w, h int) { if n > 1 { firstvertline = 1 } - wrk.cols[i].Resize(x, y, (w/n)+remainder-(n-1)-firstvertline, h) + wrk.cols[i].Resize(x, y+1, (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) + wrk.cols[i].Resize((w/n)*i+remainder+i-(n-1), y+1, (w/n)-1, h) } } func (wrk *Workspace) Draw() { + wrk.tagline.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++ { - // 2502 - screen.SetContent(x, y, '\u007c', nil, vertlineStyle) + for x, y := col.x+col.w+1, wrk.y+1; y < wrk.y+wrk.h; y++ { + screen.SetContent(x, y, RuneVerticalLine, nil, vertlineStyle) } } } @@ -106,15 +142,10 @@ func (c *Column) CloseWindow(w *Window) { c.windows = c.windows[:j] if CurWin == w { - // If we are not out of windows in our own column, pick another or exit + // If we are not out of windows in our own column, pick another or do nothing if len(c.windows) > 0 { CurWin = c.windows[j-1] } else { - // remove column - if c != workspace.Col(0) { - workspace.CloseCol(c) - } - // clear clutter screen.Clear() @@ -128,6 +159,8 @@ func (c *Column) CloseWindow(w *Window) { func (c *Column) Resize(x, y, w, h int) { c.x, c.y = x, y c.w, c.h = w, h + c.tagline.x, c.tagline.y = x, y + c.tagline.w, c.tagline.h = w, 1 c.ResizeWindows() } @@ -141,15 +174,26 @@ func (c *Column) ResizeWindows() { } for i, win := range c.windows { if i == 0 { - win.Resize(c.x, c.y, c.w, (c.h/n)+remainder) + win.Resize(c.x, c.y+1, c.w, (c.h/n)+remainder) continue } - win.Resize(c.x, c.y+(c.h/n)*i+remainder, c.w, c.h/n) + win.Resize(c.x, c.y+1+(c.h/n)*i+remainder, c.w, c.h/n) } } func (c *Column) Draw() { + c.tagline.Draw() for _, win := range c.windows { win.Draw() } + if len(c.windows) == 0 { + x, y := c.x, c.y+1 + for ; y < c.y+c.h; y++ { + x = c.x + c.w + for x >= c.x { + screen.SetContent(x, y, ' ', nil, bodyStyle) + x-- + } + } + } } diff --git a/ui/tcell/style.go b/ui/tcell/style.go index fec3390..528dbe6 100644 --- a/ui/tcell/style.go +++ b/ui/tcell/style.go @@ -25,12 +25,18 @@ var ( // initStyles initializes the different styles (colors for background/foreground). func initStyles() error { bodyStyle = tcell.StyleDefault + // bodyCursorStyle = tcell.StyleDefault bodyHilightStyle = bodyStyle.Reverse(true) - unprintableStyle = bodyStyle. - Foreground(tcell.ColorRed) + tagStyle = tcell.StyleDefault.Reverse(true) - vertlineStyle = bodyStyle.Reverse(false) + tagCursorStyle = tcell.StyleDefault.Reverse(true) + tagHilightStyle = tagStyle.Reverse(false) + tagSquareStyle = tcell.StyleDefault.Reverse(true) + tagSquareModifiedStyle = tcell.StyleDefault.Reverse(true) + vertlineStyle = bodyStyle.Reverse(false) + unprintableStyle = bodyStyle. + Foreground(tcell.ColorRed) return nil } @@ -39,8 +45,7 @@ func setStyleAcme() error { bodyStyle = tcell.StyleDefault. Background(tcell.NewHexColor(0xffffea)). Foreground(tcell.ColorBlack.TrueColor()) - bodyCursorStyle = bodyStyle. - Background(tcell.NewHexColor(0xeaea9e)) + // bodyCursorStyle = bodyStyle.Background(tcell.NewHexColor(0xeaea9e)) bodyHilightStyle = bodyStyle. Background(tcell.NewHexColor(0xeeee9e)) unprintableStyle = bodyStyle. @@ -48,9 +53,7 @@ func setStyleAcme() error { tagStyle = tcell.StyleDefault. Background(tcell.NewHexColor(0xeaffff)). Foreground(tcell.ColorBlack.TrueColor()) - tagCursorStyle = tagStyle. - Background(tcell.NewHexColor(0x8888cc)). - Foreground(tcell.ColorBlack.TrueColor()) + // tagCursorStyle = tagStyle.Background(tcell.NewHexColor(0x8888cc)).Foreground(tcell.ColorBlack.TrueColor()) tagHilightStyle = tagStyle. Background(tcell.NewHexColor(0x9eeeee)) tagSquareStyle = tagStyle. diff --git a/ui/tcell/tcell.go b/ui/tcell/tcell.go index 9783a86..c274380 100644 --- a/ui/tcell/tcell.go +++ b/ui/tcell/tcell.go @@ -19,6 +19,7 @@ var ( screen tcell.Screen ed editor.Editor workspace *Workspace + CurCol *Column CurWin *Window poecmds map[string]commandFunc @@ -42,6 +43,10 @@ func (t *Tcell) Init(e editor.Editor) error { return err } + if err := setStyleAcme(); err != nil { + return err + } + if err := initWorkspace(); err != nil { return err } @@ -72,14 +77,21 @@ func (t *Tcell) Close() { func printMsg(format string, a ...interface{}) { // get output window - poename := CurWin.Dir() + string(filepath.Separator) + FnMessageWin + var poename string + + if CurWin != nil { + poename = CurWin.Dir() + } else { + poename = ed.WorkDir() + } + poename += string(filepath.Separator) + FnMessageWin poename = filepath.Clean(poename) poewin := FindWindow(poename) if poewin == nil { id, buf := ed.NewBuffer() - buf.NewFile(CurWin.Dir() + string(filepath.Separator) + FnMessageWin) + buf.NewFile(poename) poewin = NewWindow(id) poewin.body.what = ViewScratch @@ -114,7 +126,17 @@ func initScreen() error { } func initWorkspace() error { - workspace = &Workspace{} // first resize event will set proper dimensions + workspace = &Workspace{ // first resize event will set proper dimensions + tagline: &View{ + text: &editor.Buffer{}, + what: ViewMenu, + style: tagStyle, + cursorStyle: tagCursorStyle, + hilightStyle: tagHilightStyle, + tabstop: 4, + }, + } + fmt.Fprintf(workspace.tagline, "%s", "Newcol Exit ") workspace.AddCol() if ids, _ := ed.Buffers(); len(ids) == 0 { workspace.AddCol() @@ -134,8 +156,9 @@ func initWindows() error { func initCommands() { poecmds = map[string]commandFunc{ - "New": CmdNew, "Newcol": CmdNewcol, + "Delcol": CmdDelcol, + "New": CmdNew, "Del": CmdDel, "Get": CmdGet, "Exit": CmdExit, @@ -182,10 +205,46 @@ outer: default: // let the focused view handle event if CurWin != nil { CurWin.HandleEvent(e) + } else if CurCol != nil { + CurCol.tagline.HandleEvent(e) + } else { + workspace.tagline.HandleEvent(e) } } case *tcell.EventMouse: + screen.HideCursor() mx, my := e.Position() + if CurCol != nil { + CurCol.tagline.focused = false + } + if CurWin != nil { + CurWin.UnFocus() + } + CurCol = nil + CurWin = nil + + if my < 1 { + workspace.tagline.focused = true + workspace.tagline.HandleEvent(e) + } else { + workspace.tagline.focused = false + } + + for _, col := range workspace.cols { + if mx >= col.x && mx < col.x+col.w && + my >= col.y && my < col.y+col.h { + CurCol = col + } + } + + if CurCol != nil { + if my == CurCol.y { + CurCol.tagline.focused = true + CurCol.tagline.HandleEvent(e) + } else { + CurCol.tagline.focused = false + } + } // find which window to send the event to for _, win := range AllWindows() { @@ -238,44 +297,63 @@ func CmdOpen(fn string) { screen.Clear() var win *Window win = FindWindow(fn) - if win == nil { //only load windows that do no already exists - id, buf := ed.NewBuffer() - buf.NewFile(fn) - buf.ReadFile() - win := NewWindow(id) - col := workspace.Col(0) - if buf.IsDir() { - col = workspace.LastCol() + + if win != nil { //only load windows that do no already exists + return + } + + id, buf := ed.NewBuffer() + buf.NewFile(fn) + buf.ReadFile() + win = NewWindow(id) + var col *Column + if !buf.IsDir() { + // add file window second to last or the first + if len(workspace.cols) > 2 { + col = workspace.Col(len(workspace.cols) - 2) + } else { + col = workspace.Col(0) } - col.AddWindow(win) + } else { + // add all dirs to last column + col = workspace.LastCol() } + col.AddWindow(win) } func CmdNew() { screen.Clear() id, _ := ed.NewBuffer() win := NewWindow(id) - workspace.LastCol().AddWindow(win) + CurCol.AddWindow(win) } func CmdDel() { - if len(AllWindows()) == 1 { - CmdExit() - return - } CurWin.Close() + screen.HideCursor() } func CmdNewcol() { workspace.AddCol() - CmdNew() + screen.Clear() +} + +func CmdDelcol() { + if len(workspace.cols) < 2 { + CmdExit() + } else if CurCol != nil { + workspace.CloseCol(CurCol) + } else if CurWin != nil { + workspace.CloseCol(CurWin.col) + } + screen.Clear() } func CmdGet() { screen.Clear() wins := AllWindows() for _, win := range wins { - if win.tagline.focused { + if win.tagline.focused || win.body.focused { q0, q1 := win.body.text.Dot() win.body.text.Destroy() win.body.text.ReadFile() diff --git a/ui/tcell/view.go b/ui/tcell/view.go index 73f1453..55490b9 100644 --- a/ui/tcell/view.go +++ b/ui/tcell/view.go @@ -16,6 +16,7 @@ import ( const ( ViewMenu int = iota + ViewColumn ViewTagline ViewBody ViewScratch @@ -235,7 +236,7 @@ func (v *View) ScrollTo(offset int) { } func (b *View) Draw() { - //screen.HideCursor() + // screen.HideCursor() x, y := b.x, b.y @@ -261,7 +262,7 @@ func (b *View) Draw() { // highlight cursor if on screen if (q0 == q1 && i == q0) && b.focused { - //style = b.cursorStyle + // style = b.cursorStyle screen.ShowCursor(x, y) } @@ -512,9 +513,6 @@ func (v *View) HandleEvent(ev tcell.Event) { ed.WorkDir(), CurWin.Dir(), CurWin.Name(), CurWin.w, CurWin.h, sh, sw) return - case tcell.KeyCtrlN: // new column - CmdNewcol() - return case tcell.KeyCtrlC: // copy to clipboard str := v.text.ReadDot() if str == "" { @@ -533,6 +531,10 @@ func (v *View) HandleEvent(ev tcell.Event) { v.text.Write([]byte(s)) return case tcell.KeyCtrlQ: // close window + if v.what == ViewColumn || v.what == ViewMenu { + CmdDelcol() // calls CmdExit if cols < 2 + return + } CmdDel() return default: @@ -575,7 +577,11 @@ func ButtonSecondary(v *View, mx, my int) { return } if fn != "" && fn[0] != filepath.Separator { - fn = CurWin.Dir() + string(filepath.Separator) + fn + if CurWin != nil { + fn = CurWin.Dir() + string(filepath.Separator) + fn + } else { + fn = ed.WorkDir() + string(filepath.Separator) + fn + } fn = filepath.Clean(fn) } diff --git a/ui/tcell/window.go b/ui/tcell/window.go index ee2de88..28c66f9 100644 --- a/ui/tcell/window.go +++ b/ui/tcell/window.go @@ -127,6 +127,7 @@ func (win *Window) HandleEvent(ev tcell.Event) { win.tagline.focused = false } else { win.tagline.focused = true + win.body.focused = false } case *tcell.EventKey: switch ev.Key() { -- cgit v1.2.3