adjusted the filterview aesthetics
This commit is contained in:
parent
c961041ec3
commit
e942bb7794
@ -82,16 +82,17 @@ func (view *FileTreeView) Setup(v *gocui.View, header *gocui.View) error {
|
||||
if err := view.gui.SetKeybinding(view.Name, gocui.KeyCtrlU, gocui.ModNone, func(*gocui.Gui, *gocui.View) error { return view.toggleShowDiffType(filetree.Unchanged) }); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := view.gui.SetKeybinding(view.Name, gocui.KeyCtrlSlash, gocui.ModNone, func(*gocui.Gui, *gocui.View) error { return nil }); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
view.updateViewTree()
|
||||
view.Update()
|
||||
view.Render()
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (view *FileTreeView) IsVisible() bool {
|
||||
if view == nil {return false}
|
||||
return true
|
||||
}
|
||||
|
||||
|
||||
func (view *FileTreeView) setTreeByLayer(bottomTreeStart, bottomTreeStop, topTreeStart, topTreeStop int) error {
|
||||
@ -117,7 +118,7 @@ func (view *FileTreeView) setTreeByLayer(bottomTreeStart, bottomTreeStop, topTre
|
||||
view.view.SetCursor(0, 0)
|
||||
view.TreeIndex = 0
|
||||
view.ModelTree = newTree
|
||||
view.updateViewTree()
|
||||
view.Update()
|
||||
return view.Render()
|
||||
}
|
||||
|
||||
@ -155,7 +156,7 @@ func (view *FileTreeView) getAbsPositionNode() (node *filetree.FileNode) {
|
||||
}
|
||||
var filterBytes []byte
|
||||
var filterRegex *regexp.Regexp
|
||||
read, err := Views.Command.view.Read(filterBytes)
|
||||
read, err := Views.Filter.view.Read(filterBytes)
|
||||
if read > 0 && err == nil {
|
||||
regex, err := regexp.Compile(string(filterBytes))
|
||||
if err == nil {
|
||||
@ -185,7 +186,7 @@ func (view *FileTreeView) toggleCollapse() error {
|
||||
if node != nil {
|
||||
node.Data.ViewInfo.Collapsed = !node.Data.ViewInfo.Collapsed
|
||||
}
|
||||
view.updateViewTree()
|
||||
view.Update()
|
||||
return view.Render()
|
||||
}
|
||||
|
||||
@ -194,15 +195,15 @@ func (view *FileTreeView) toggleShowDiffType(diffType filetree.DiffType) error {
|
||||
|
||||
view.view.SetCursor(0, 0)
|
||||
view.TreeIndex = 0
|
||||
view.updateViewTree()
|
||||
view.Update()
|
||||
return view.Render()
|
||||
}
|
||||
|
||||
func filterRegex() *regexp.Regexp {
|
||||
if Views.Command == nil || Views.Command.view == nil {
|
||||
if Views.Filter == nil || Views.Filter.view == nil {
|
||||
return nil
|
||||
}
|
||||
filterString := strings.TrimSpace(Views.Command.view.Buffer())
|
||||
filterString := strings.TrimSpace(Views.Filter.view.Buffer())
|
||||
if len(filterString) < 1 {
|
||||
return nil
|
||||
}
|
||||
@ -215,7 +216,7 @@ func filterRegex() *regexp.Regexp {
|
||||
return regex
|
||||
}
|
||||
|
||||
func (view *FileTreeView) updateViewTree() {
|
||||
func (view *FileTreeView) Update() error {
|
||||
regex := filterRegex()
|
||||
|
||||
// keep the view selection in parity with the current DiffType selection
|
||||
@ -242,6 +243,7 @@ func (view *FileTreeView) updateViewTree() {
|
||||
}
|
||||
return nil
|
||||
}, nil)
|
||||
return nil;
|
||||
}
|
||||
|
||||
func (view *FileTreeView) KeyHelp() string {
|
||||
@ -275,8 +277,3 @@ func (view *FileTreeView) Render() error {
|
||||
})
|
||||
return nil
|
||||
}
|
||||
|
||||
func (view *FileTreeView) ReRender() error {
|
||||
view.updateViewTree()
|
||||
return view.Render()
|
||||
}
|
||||
|
@ -8,11 +8,14 @@ import (
|
||||
|
||||
// with special thanks to https://gist.github.com/jroimartin/3b2e943a3811d795e0718b4a95b89bec
|
||||
|
||||
type CommandView struct {
|
||||
type FilterView struct {
|
||||
Name string
|
||||
gui *gocui.Gui
|
||||
view *gocui.View
|
||||
header *gocui.View
|
||||
headerStr string
|
||||
maxLength int
|
||||
hidden bool
|
||||
}
|
||||
|
||||
type Input struct {
|
||||
@ -22,17 +25,19 @@ type Input struct {
|
||||
maxLength int
|
||||
}
|
||||
|
||||
func NewCommandView(name string, gui *gocui.Gui) (commandview *CommandView) {
|
||||
commandview = new(CommandView)
|
||||
func NewFilterView(name string, gui *gocui.Gui) (filterview *FilterView) {
|
||||
filterview = new(FilterView)
|
||||
|
||||
// populate main fields
|
||||
commandview.Name = name
|
||||
commandview.gui = gui
|
||||
filterview.Name = name
|
||||
filterview.gui = gui
|
||||
filterview.headerStr = "Path Filter: "
|
||||
filterview.hidden = true
|
||||
|
||||
return commandview
|
||||
return filterview
|
||||
}
|
||||
|
||||
func (view *CommandView) Setup(v *gocui.View, header *gocui.View) error {
|
||||
func (view *FilterView) Setup(v *gocui.View, header *gocui.View) error {
|
||||
|
||||
// set view options
|
||||
view.view = v
|
||||
@ -41,6 +46,13 @@ func (view *CommandView) Setup(v *gocui.View, header *gocui.View) error {
|
||||
view.view.BgColor = gocui.ColorDefault + gocui.AttrReverse
|
||||
view.view.Editable = true
|
||||
view.view.Editor = view
|
||||
|
||||
view.header = header
|
||||
view.header.BgColor = gocui.ColorDefault + gocui.AttrReverse
|
||||
view.header.Editable = false
|
||||
view.header.Wrap = false
|
||||
view.header.Frame = false
|
||||
|
||||
// set keybindings
|
||||
// if err := view.gui.SetKeybinding(view.Name, gocui.KeyArrowDown, gocui.ModNone, func(*gocui.Gui, *gocui.View) error { return view.CursorDown() }); err != nil {
|
||||
// return err
|
||||
@ -54,18 +66,27 @@ func (view *CommandView) Setup(v *gocui.View, header *gocui.View) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (view *CommandView) CursorDown() error {
|
||||
func (view *FilterView) IsVisible() bool {
|
||||
if view == nil {return false}
|
||||
return !view.hidden
|
||||
}
|
||||
|
||||
func (view *FilterView) CursorDown() error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (view *CommandView) CursorUp() error {
|
||||
func (view *FilterView) CursorUp() error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (i *CommandView) Edit(v *gocui.View, key gocui.Key, ch rune, mod gocui.Modifier) {
|
||||
func (view *FilterView) Edit(v *gocui.View, key gocui.Key, ch rune, mod gocui.Modifier) {
|
||||
if !view.IsVisible() {
|
||||
return
|
||||
}
|
||||
|
||||
cx, _ := v.Cursor()
|
||||
ox, _ := v.Origin()
|
||||
limit := ox+cx+1 > i.maxLength
|
||||
limit := ox+cx+1 > view.maxLength
|
||||
switch {
|
||||
case ch != 0 && mod == 0 && !limit:
|
||||
v.EditWrite(ch)
|
||||
@ -75,17 +96,23 @@ func (i *CommandView) Edit(v *gocui.View, key gocui.Key, ch rune, mod gocui.Modi
|
||||
v.EditDelete(true)
|
||||
}
|
||||
if Views.Tree != nil {
|
||||
Views.Tree.ReRender()
|
||||
Views.Tree.Update()
|
||||
Views.Tree.Render()
|
||||
}
|
||||
}
|
||||
|
||||
func (view *CommandView) KeyHelp() string {
|
||||
return "Type string to filter"
|
||||
func (view *FilterView) KeyHelp() string {
|
||||
return Formatting.Control("Type string to filter the file tree")
|
||||
}
|
||||
|
||||
func (view *CommandView) Render() error {
|
||||
func (view *FilterView) Update() error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (view *FilterView) Render() error {
|
||||
view.gui.Update(func(g *gocui.Gui) error {
|
||||
fmt.Fprintln(view.view, "")
|
||||
// render the header
|
||||
fmt.Fprintln(view.header, Formatting.Header(view.headerStr))
|
||||
|
||||
return nil
|
||||
})
|
@ -64,6 +64,11 @@ func (view *LayerView) Setup(v *gocui.View, header *gocui.View) error {
|
||||
return view.Render()
|
||||
}
|
||||
|
||||
func (view *LayerView) IsVisible() bool {
|
||||
if view == nil {return false}
|
||||
return true
|
||||
}
|
||||
|
||||
func (view *LayerView) setCompareMode(compareMode CompareType) error {
|
||||
view.CompareMode = compareMode
|
||||
view.Render()
|
||||
@ -120,10 +125,14 @@ func (view *LayerView) renderCompareBar(layerIdx int) string {
|
||||
return result
|
||||
}
|
||||
|
||||
func (view *LayerView) Update() error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (view *LayerView) Render() error {
|
||||
view.gui.Update(func(g *gocui.Gui) error {
|
||||
// update header
|
||||
headerStr := fmt.Sprintf("Cmp "+image.LayerFormat, "Image ID", "Size", "Command")
|
||||
headerStr := fmt.Sprintf("Cmp "+image.LayerFormat, "Image ID", "Size", "Filter")
|
||||
fmt.Fprintln(view.header, Formatting.Header(vtclean.Clean(headerStr, false)))
|
||||
|
||||
// update contents
|
||||
|
@ -29,19 +29,16 @@ func (view *StatusView) Setup(v *gocui.View, header *gocui.View) error {
|
||||
view.view.Frame = false
|
||||
view.view.BgColor = gocui.ColorDefault + gocui.AttrReverse
|
||||
|
||||
// set keybindings
|
||||
// if err := view.gui.SetKeybinding(view.Name, gocui.KeyArrowDown, gocui.ModNone, func(*gocui.Gui, *gocui.View) error { return view.CursorDown() }); err != nil {
|
||||
// return err
|
||||
// }
|
||||
// if err := view.gui.SetKeybinding(view.Name, gocui.KeyArrowUp, gocui.ModNone, func(*gocui.Gui, *gocui.View) error { return view.CursorUp() }); err != nil {
|
||||
// return err
|
||||
// }
|
||||
|
||||
view.Render()
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (view *StatusView) IsVisible() bool {
|
||||
if view == nil {return false}
|
||||
return true
|
||||
}
|
||||
|
||||
func (view *StatusView) CursorDown() error {
|
||||
return nil
|
||||
}
|
||||
@ -53,7 +50,11 @@ func (view *StatusView) CursorUp() error {
|
||||
func (view *StatusView) KeyHelp() string {
|
||||
return Formatting.Control("[^C]") + ": Quit " +
|
||||
Formatting.Control("[^Space]") + ": Switch View " +
|
||||
Formatting.Control("[^/]") + ": Filter files"
|
||||
Formatting.Control("[^/]") + ": Filter files"
|
||||
}
|
||||
|
||||
func (view *StatusView) Update() error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (view *StatusView) Render() error {
|
||||
|
90
ui/ui.go
90
ui/ui.go
@ -34,11 +34,11 @@ var Formatting struct {
|
||||
}
|
||||
|
||||
var Views struct {
|
||||
Tree *FileTreeView
|
||||
Layer *LayerView
|
||||
Status *StatusView
|
||||
Command *CommandView
|
||||
lookup map[string]View
|
||||
Tree *FileTreeView
|
||||
Layer *LayerView
|
||||
Status *StatusView
|
||||
Filter *FilterView
|
||||
lookup map[string]View
|
||||
}
|
||||
|
||||
type View interface {
|
||||
@ -46,32 +46,44 @@ type View interface {
|
||||
CursorDown() error
|
||||
CursorUp() error
|
||||
Render() error
|
||||
Update() error
|
||||
KeyHelp() string
|
||||
IsVisible() bool
|
||||
}
|
||||
|
||||
func toggleView(g *gocui.Gui, v *gocui.View) error {
|
||||
if v == nil || v.Name() == Views.Layer.Name {
|
||||
_, err := g.SetCurrentView(Views.Tree.Name)
|
||||
Update()
|
||||
Render()
|
||||
return err
|
||||
}
|
||||
_, err := g.SetCurrentView(Views.Layer.Name)
|
||||
Update()
|
||||
Render()
|
||||
return err
|
||||
}
|
||||
|
||||
func focusFilterView(g *gocui.Gui, v *gocui.View) error {
|
||||
_, err := g.SetCurrentView(Views.Command.Name)
|
||||
Render()
|
||||
return err
|
||||
}
|
||||
func toggleFilterView(g *gocui.Gui, v *gocui.View) error {
|
||||
// delete all user input from the tree view
|
||||
Views.Filter.view.Clear()
|
||||
Views.Filter.view.SetCursor(0,0)
|
||||
|
||||
func returnToTreeView(g *gocui.Gui, v *gocui.View) error {
|
||||
_, err := g.SetCurrentView(Views.Tree.Name)
|
||||
if Views.Tree != nil {
|
||||
Views.Tree.ReRender()
|
||||
// toggle hiding
|
||||
Views.Filter.hidden = !Views.Filter.hidden
|
||||
|
||||
if !Views.Filter.hidden {
|
||||
_, err := g.SetCurrentView(Views.Filter.Name)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
Update()
|
||||
Render()
|
||||
} else {
|
||||
toggleView(g, v)
|
||||
}
|
||||
return err
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func CursorDown(g *gocui.Gui, v *gocui.View) error {
|
||||
@ -116,16 +128,10 @@ func keybindings(g *gocui.Gui) error {
|
||||
//if err := g.SetKeybinding("main", gocui.MouseLeft, gocui.ModNone, toggleCollapse); err != nil {
|
||||
// return err
|
||||
//}
|
||||
if err := g.SetKeybinding("side", gocui.KeyCtrlSpace, gocui.ModNone, toggleView); err != nil {
|
||||
if err := g.SetKeybinding("", gocui.KeyCtrlSpace, gocui.ModNone, toggleView); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := g.SetKeybinding("main", gocui.KeyCtrlSpace, gocui.ModNone, toggleView); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := g.SetKeybinding("", gocui.KeyCtrlSlash, gocui.ModNone, focusFilterView); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := g.SetKeybinding("command", gocui.KeyEnter, gocui.ModNone, returnToTreeView); err != nil {
|
||||
if err := g.SetKeybinding("", gocui.KeyCtrlSlash, gocui.ModNone, toggleFilterView); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
@ -144,6 +150,7 @@ func isNewView(errs ...error) bool {
|
||||
return true
|
||||
}
|
||||
|
||||
// TODO: this logic should be refactored into an abstraction that takes care of the math for us
|
||||
func layout(g *gocui.Gui) error {
|
||||
maxX, maxY := g.Size()
|
||||
splitCols := maxX / 2
|
||||
@ -154,9 +161,21 @@ func layout(g *gocui.Gui) error {
|
||||
debugCols := maxX - debugWidth
|
||||
bottomRows := 1
|
||||
headerRows := 1
|
||||
|
||||
filterBarHeight := 1
|
||||
statusBarHeight := 1
|
||||
|
||||
statusBarIndex := 1
|
||||
filterBarIndex := 2
|
||||
|
||||
var view, header *gocui.View
|
||||
var viewErr, headerErr, err error
|
||||
|
||||
if Views.Filter.hidden {
|
||||
bottomRows--
|
||||
filterBarHeight = 0
|
||||
}
|
||||
|
||||
// Debug pane
|
||||
if debug {
|
||||
if _, err := g.SetView("debug", debugCols, -1, maxX, maxY-bottomRows); err != nil {
|
||||
@ -185,24 +204,33 @@ func layout(g *gocui.Gui) error {
|
||||
}
|
||||
|
||||
// Status Bar
|
||||
view, viewErr = g.SetView(Views.Status.Name, -1, maxY-bottomRows-1, maxX, maxY)
|
||||
view, viewErr = g.SetView(Views.Status.Name, -1, maxY-statusBarHeight-statusBarIndex, maxX, maxY-(statusBarIndex-1))
|
||||
if isNewView(viewErr, headerErr) {
|
||||
Views.Status.Setup(view, nil)
|
||||
}
|
||||
|
||||
// Command Bar
|
||||
view, viewErr = g.SetView(Views.Command.Name, -1, maxY-bottomRows-2, maxX, maxY-1)
|
||||
// Filter Bar
|
||||
view, viewErr = g.SetView(Views.Filter.Name, len(Views.Filter.headerStr)-1, maxY-filterBarHeight-filterBarIndex, maxX, maxY-(filterBarIndex-1))
|
||||
header, headerErr = g.SetView(Views.Filter.Name+"header", -1, maxY-filterBarHeight - filterBarIndex, len(Views.Filter.headerStr), maxY-(filterBarIndex-1))
|
||||
if isNewView(viewErr, headerErr) {
|
||||
debugPrint("Setup...")
|
||||
Views.Command.Setup(view, nil)
|
||||
Views.Filter.Setup(view, header)
|
||||
}
|
||||
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func Update() {
|
||||
for _, view := range Views.lookup {
|
||||
view.Update()
|
||||
}
|
||||
}
|
||||
|
||||
func Render() {
|
||||
for _, view := range Views.lookup {
|
||||
view.Render()
|
||||
if view.IsVisible() {
|
||||
view.Render()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -230,8 +258,8 @@ func Run(layers []*image.Layer, refTrees []*filetree.FileTree) {
|
||||
Views.Status = NewStatusView("status", g)
|
||||
Views.lookup[Views.Status.Name] = Views.Status
|
||||
|
||||
Views.Command = NewCommandView("command", g)
|
||||
Views.lookup[Views.Command.Name] = Views.Command
|
||||
Views.Filter = NewFilterView("command", g)
|
||||
Views.lookup[Views.Filter.Name] = Views.Filter
|
||||
|
||||
g.Cursor = false
|
||||
//g.Mouse = true
|
||||
|
Loading…
x
Reference in New Issue
Block a user