1// Copyright 2014 The gocui Authors. All rights reserved. 2// Use of this source code is governed by a BSD-style 3// license that can be found in the LICENSE file. 4 5package main 6 7import ( 8 "fmt" 9 "log" 10 "strings" 11 12 "github.com/jroimartin/gocui" 13) 14 15const delta = 1 16 17var ( 18 views = []string{} 19 curView = -1 20 idxView = 0 21) 22 23func main() { 24 g := gocui.NewGui() 25 if err := g.Init(); err != nil { 26 log.Panicln(err) 27 } 28 defer g.Close() 29 30 g.SetLayout(layout) 31 if err := initKeybindings(g); err != nil { 32 log.Panicln(err) 33 } 34 if err := newView(g); err != nil { 35 log.Panicln(err) 36 } 37 38 if err := g.MainLoop(); err != nil && err != gocui.ErrQuit { 39 log.Panicln(err) 40 } 41} 42 43func layout(g *gocui.Gui) error { 44 maxX, _ := g.Size() 45 v, err := g.SetView("legend", maxX-25, 0, maxX-1, 8) 46 if err != nil { 47 if err != gocui.ErrUnknownView { 48 return err 49 } 50 fmt.Fprintln(v, "KEYBINDINGS") 51 fmt.Fprintln(v, "Space: New View") 52 fmt.Fprintln(v, "Tab: Next View") 53 fmt.Fprintln(v, "← ↑ → ↓: Move View") 54 fmt.Fprintln(v, "Backspace: Delete View") 55 fmt.Fprintln(v, "t: Set view on top") 56 fmt.Fprintln(v, "^C: Exit") 57 } 58 return nil 59} 60 61func initKeybindings(g *gocui.Gui) error { 62 if err := g.SetKeybinding("", gocui.KeyCtrlC, gocui.ModNone, quit); err != nil { 63 return err 64 } 65 if err := g.SetKeybinding("", gocui.KeySpace, gocui.ModNone, 66 func(g *gocui.Gui, v *gocui.View) error { 67 return newView(g) 68 }); err != nil { 69 return err 70 } 71 if err := g.SetKeybinding("", gocui.KeyBackspace2, gocui.ModNone, 72 func(g *gocui.Gui, v *gocui.View) error { 73 return delView(g) 74 }); err != nil { 75 return err 76 } 77 if err := g.SetKeybinding("", gocui.KeyTab, gocui.ModNone, 78 func(g *gocui.Gui, v *gocui.View) error { 79 return nextView(g, true) 80 }); err != nil { 81 return err 82 } 83 if err := g.SetKeybinding("", gocui.KeyArrowLeft, gocui.ModNone, 84 func(g *gocui.Gui, v *gocui.View) error { 85 return moveView(g, v, -delta, 0) 86 }); err != nil { 87 return err 88 } 89 if err := g.SetKeybinding("", gocui.KeyArrowRight, gocui.ModNone, 90 func(g *gocui.Gui, v *gocui.View) error { 91 return moveView(g, v, delta, 0) 92 }); err != nil { 93 return err 94 } 95 if err := g.SetKeybinding("", gocui.KeyArrowDown, gocui.ModNone, 96 func(g *gocui.Gui, v *gocui.View) error { 97 return moveView(g, v, 0, delta) 98 }); err != nil { 99 return err 100 } 101 if err := g.SetKeybinding("", gocui.KeyArrowUp, gocui.ModNone, 102 func(g *gocui.Gui, v *gocui.View) error { 103 return moveView(g, v, 0, -delta) 104 }); err != nil { 105 return err 106 } 107 if err := g.SetKeybinding("", 't', gocui.ModNone, ontop); err != nil { 108 return err 109 } 110 return nil 111} 112 113func quit(g *gocui.Gui, v *gocui.View) error { 114 return gocui.ErrQuit 115} 116 117func newView(g *gocui.Gui) error { 118 maxX, maxY := g.Size() 119 name := fmt.Sprintf("v%v", idxView) 120 v, err := g.SetView(name, maxX/2-5, maxY/2-5, maxX/2+5, maxY/2+5) 121 if err != nil { 122 if err != gocui.ErrUnknownView { 123 return err 124 } 125 v.Wrap = true 126 fmt.Fprintln(v, strings.Repeat(name+" ", 30)) 127 } 128 if err := g.SetCurrentView(name); err != nil { 129 return err 130 } 131 v.BgColor = gocui.ColorRed 132 133 if curView >= 0 { 134 cv, err := g.View(views[curView]) 135 if err != nil { 136 return err 137 } 138 cv.BgColor = g.BgColor 139 } 140 141 views = append(views, name) 142 curView = len(views) - 1 143 idxView += 1 144 return nil 145} 146 147func delView(g *gocui.Gui) error { 148 if len(views) <= 1 { 149 return nil 150 } 151 152 if err := g.DeleteView(views[curView]); err != nil { 153 return err 154 } 155 views = append(views[:curView], views[curView+1:]...) 156 157 return nextView(g, false) 158} 159 160func nextView(g *gocui.Gui, disableCurrent bool) error { 161 next := curView + 1 162 if next > len(views)-1 { 163 next = 0 164 } 165 166 nv, err := g.View(views[next]) 167 if err != nil { 168 return err 169 } 170 if err := g.SetCurrentView(views[next]); err != nil { 171 return err 172 } 173 nv.BgColor = gocui.ColorRed 174 175 if disableCurrent && len(views) > 1 { 176 cv, err := g.View(views[curView]) 177 if err != nil { 178 return err 179 } 180 cv.BgColor = g.BgColor 181 } 182 183 curView = next 184 return nil 185} 186 187func moveView(g *gocui.Gui, v *gocui.View, dx, dy int) error { 188 name := v.Name() 189 x0, y0, x1, y1, err := g.ViewPosition(name) 190 if err != nil { 191 return err 192 } 193 if _, err := g.SetView(name, x0+dx, y0+dy, x1+dx, y1+dy); err != nil { 194 return err 195 } 196 return nil 197} 198 199func ontop(g *gocui.Gui, v *gocui.View) error { 200 _, err := g.SetViewOnTop(views[curView]) 201 return err 202} 203