Use a buffer system for building the panes
This commit is contained in:
parent
72d7cc8280
commit
e6f872fbf6
@ -6,7 +6,7 @@ import (
|
|||||||
"strings"
|
"strings"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/br0xen/termbox-util"
|
termboxUtil "github.com/br0xen/termbox-util"
|
||||||
"github.com/nsf/termbox-go"
|
"github.com/nsf/termbox-go"
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -17,7 +17,7 @@ type ViewPort struct {
|
|||||||
bytesPerRow int
|
bytesPerRow int
|
||||||
numberOfRows int
|
numberOfRows int
|
||||||
firstRow int
|
firstRow int
|
||||||
scrollRow int
|
scrollRow int
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -25,8 +25,8 @@ BrowserScreen holds all that's going on :D
|
|||||||
*/
|
*/
|
||||||
type BrowserScreen struct {
|
type BrowserScreen struct {
|
||||||
db *BoltDB
|
db *BoltDB
|
||||||
leftViewPort ViewPort
|
leftViewPort ViewPort
|
||||||
rightViewPort ViewPort
|
rightViewPort ViewPort
|
||||||
queuedCommand string
|
queuedCommand string
|
||||||
currentPath []string
|
currentPath []string
|
||||||
currentType int
|
currentType int
|
||||||
@ -37,9 +37,6 @@ type BrowserScreen struct {
|
|||||||
messageTimeout time.Duration
|
messageTimeout time.Duration
|
||||||
messageTime time.Time
|
messageTime time.Time
|
||||||
|
|
||||||
rightPaneHeight int
|
|
||||||
rightPaneCursor int
|
|
||||||
|
|
||||||
leftPaneBuffer []Line
|
leftPaneBuffer []Line
|
||||||
rightPaneBuffer []Line
|
rightPaneBuffer []Line
|
||||||
}
|
}
|
||||||
@ -485,15 +482,15 @@ func (screen *BrowserScreen) moveCursorDown() bool {
|
|||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
func (screen *BrowserScreen) moveRightPaneUp() bool {
|
func (screen *BrowserScreen) moveRightPaneUp() bool {
|
||||||
if screen.rightViewPort.scrollRow > 0 {
|
if screen.rightViewPort.scrollRow > 0 {
|
||||||
screen.rightViewPort.scrollRow--
|
screen.rightViewPort.scrollRow--
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
func (screen *BrowserScreen) moveRightPaneDown() bool {
|
func (screen *BrowserScreen) moveRightPaneDown() bool {
|
||||||
screen.rightViewPort.scrollRow++
|
screen.rightViewPort.scrollRow++
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
func (screen *BrowserScreen) performLayout() {}
|
func (screen *BrowserScreen) performLayout() {}
|
||||||
@ -540,42 +537,44 @@ func (screen *BrowserScreen) drawFooter(style Style) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (screen *BrowserScreen) buildLeftPane(style Style) {
|
func (screen *BrowserScreen) buildLeftPane(style Style) {
|
||||||
screen.leftPaneBuffer = nil
|
screen.leftPaneBuffer = nil
|
||||||
if len(screen.currentPath) == 0 {
|
if len(screen.currentPath) == 0 {
|
||||||
screen.currentPath = screen.db.getNextVisiblePath(nil)
|
screen.currentPath = screen.db.getNextVisiblePath(nil)
|
||||||
}
|
}
|
||||||
curPathSpot := 0
|
for i := range screen.db.buckets {
|
||||||
visPaths, err := screen.db.buildVisiblePathSlice()
|
screen.leftPaneBuffer = append(screen.leftPaneBuffer, screen.bucketToLines(&screen.db.buckets[i], style)...)
|
||||||
if err == nil {
|
}
|
||||||
for idx, pth := range visPaths {
|
// Find the cursor in the leftPane
|
||||||
screen.leftPaneBuffer
|
for k, v := range screen.leftPaneBuffer {
|
||||||
|
if v.Fg == style.cursorFg {
|
||||||
|
screen.leftViewPort.scrollRow = k
|
||||||
|
break
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (screen *BrowserScreen) drawLeftPane(style Style) {
|
func (screen *BrowserScreen) drawLeftPane(style Style) {
|
||||||
screen.buildLeftPane(style)
|
screen.buildLeftPane(style)
|
||||||
w, h := termbox.Size()
|
w, h := termbox.Size()
|
||||||
if w > 80 {
|
if w > 80 {
|
||||||
w = w / 2
|
w = w / 2
|
||||||
}
|
}
|
||||||
screen.leftViewPort.bytesPerRow = w
|
screen.leftViewPort.bytesPerRow = w
|
||||||
screen.leftViewPort.numberOfRows = h - 2
|
screen.leftViewPort.numberOfRows = h - 2
|
||||||
termboxUtil.FillWithChar('=', 0, 1, w, 1, style.defaultFg, style.defaultBg)
|
termboxUtil.FillWithChar('=', 0, 1, w, 1, style.defaultFg, style.defaultBg)
|
||||||
y := 2
|
startX, startY := 0, 3
|
||||||
screen.leftViewPort.firstRow = y
|
screen.leftViewPort.firstRow = startY
|
||||||
|
treeOffset := 0
|
||||||
|
maxCursor := screen.leftViewPort.numberOfRows * 2 / 3
|
||||||
|
|
||||||
treeOffset := 0
|
if screen.leftViewPort.scrollRow > maxCursor {
|
||||||
maxCursor := screen.leftViewPort.numberOfRows * 2 / 3
|
treeOffset = screen.leftViewPort.scrollRow - maxCursor
|
||||||
if curPathSpot > maxCursor {
|
}
|
||||||
treeOffset = curPathSpot - maxCursor
|
if len(screen.leftPaneBuffer) > 0 {
|
||||||
}
|
for k, v := range screen.leftPaneBuffer[treeOffset:] {
|
||||||
|
termboxUtil.DrawStringAtPoint(v.Text, startX, (startY + k - 1), v.Fg, v.Bg)
|
||||||
for i := range screen.db.buckets {
|
}
|
||||||
// The drawBucket function returns how many lines it took up
|
}
|
||||||
bktH := screen.drawBucket(&screen.db.buckets[i], style, (y - treeOffset))
|
|
||||||
y += bktH
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (screen *BrowserScreen) buildRightPane(style Style) {
|
func (screen *BrowserScreen) buildRightPane(style Style) {
|
||||||
@ -595,18 +594,18 @@ func (screen *BrowserScreen) buildRightPane(style Style) {
|
|||||||
screen.rightPaneBuffer = append(screen.rightPaneBuffer,
|
screen.rightPaneBuffer = append(screen.rightPaneBuffer,
|
||||||
Line{fmt.Sprintf("Key: %s", stringify([]byte(p.key))), style.defaultFg, style.defaultBg})
|
Line{fmt.Sprintf("Key: %s", stringify([]byte(p.key))), style.defaultFg, style.defaultBg})
|
||||||
|
|
||||||
value := strings.Split(string(formatValue([]byte(p.val))), "\n")
|
value := strings.Split(string(formatValue([]byte(p.val))), "\n")
|
||||||
if len(value) == 1 {
|
if len(value) == 1 {
|
||||||
screen.rightPaneBuffer = append(screen.rightPaneBuffer,
|
screen.rightPaneBuffer = append(screen.rightPaneBuffer,
|
||||||
Line{fmt.Sprintf("Value: %s", value[0]), style.defaultFg, style.defaultBg})
|
Line{fmt.Sprintf("Value: %s", value[0]), style.defaultFg, style.defaultBg})
|
||||||
} else {
|
} else {
|
||||||
screen.rightPaneBuffer = append(screen.rightPaneBuffer,
|
screen.rightPaneBuffer = append(screen.rightPaneBuffer,
|
||||||
Line{"Value:", style.defaultFg, style.defaultBg})
|
Line{"Value:", style.defaultFg, style.defaultBg})
|
||||||
for _, v := range value {
|
for _, v := range value {
|
||||||
screen.rightPaneBuffer = append(screen.rightPaneBuffer,
|
screen.rightPaneBuffer = append(screen.rightPaneBuffer,
|
||||||
Line{v, style.defaultFg, style.defaultBg})
|
Line{v, style.defaultFg, style.defaultBg})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
screen.rightPaneBuffer = append(screen.rightPaneBuffer,
|
screen.rightPaneBuffer = append(screen.rightPaneBuffer,
|
||||||
@ -620,28 +619,28 @@ func (screen *BrowserScreen) drawRightPane(style Style) {
|
|||||||
screen.buildRightPane(style)
|
screen.buildRightPane(style)
|
||||||
w, h := termbox.Size()
|
w, h := termbox.Size()
|
||||||
if w > 80 {
|
if w > 80 {
|
||||||
screen.rightViewPort.bytesPerRow = w / 2
|
screen.rightViewPort.bytesPerRow = w / 2
|
||||||
screen.rightViewPort.numberOfRows = h - 2
|
screen.rightViewPort.numberOfRows = h - 2
|
||||||
// Screen is wide enough, split it
|
// Screen is wide enough, split it
|
||||||
termboxUtil.FillWithChar('=', 0, 1, w, 1, style.defaultFg, style.defaultBg)
|
termboxUtil.FillWithChar('=', 0, 1, w, 1, style.defaultFg, style.defaultBg)
|
||||||
termboxUtil.FillWithChar('|', (w / 2), screen.rightViewPort.firstRow-1, (w / 2), h, style.defaultFg, style.defaultBg)
|
termboxUtil.FillWithChar('|', (w / 2), screen.rightViewPort.firstRow-1, (w / 2), h, style.defaultFg, style.defaultBg)
|
||||||
// Clear the right pane
|
// Clear the right pane
|
||||||
termboxUtil.FillWithChar(' ', (w/2)+1, screen.rightViewPort.firstRow, w, h, style.defaultFg, style.defaultBg)
|
termboxUtil.FillWithChar(' ', (w/2)+1, screen.rightViewPort.firstRow+2, w, h, style.defaultFg, style.defaultBg)
|
||||||
|
|
||||||
startX := (w / 2) + 2
|
startX := (w / 2) + 2
|
||||||
startY := 2
|
startY := 3
|
||||||
maxScroll := len(screen.rightPaneBuffer)-screen.rightViewPort.numberOfRows
|
maxScroll := len(screen.rightPaneBuffer) - screen.rightViewPort.numberOfRows
|
||||||
if maxScroll < 0 {
|
if maxScroll < 0 {
|
||||||
maxScroll = 0
|
maxScroll = 0
|
||||||
}
|
}
|
||||||
if screen.rightViewPort.scrollRow > maxScroll {
|
if screen.rightViewPort.scrollRow > maxScroll {
|
||||||
screen.rightViewPort.scrollRow = maxScroll
|
screen.rightViewPort.scrollRow = maxScroll
|
||||||
}
|
}
|
||||||
if len(screen.rightPaneBuffer) > 0 {
|
if len(screen.rightPaneBuffer) > 0 {
|
||||||
for k, v := range screen.rightPaneBuffer[screen.rightViewPort.scrollRow:] {
|
for k, v := range screen.rightPaneBuffer[screen.rightViewPort.scrollRow:] {
|
||||||
termboxUtil.DrawStringAtPoint(v.Text, startX, (startY + k - 1), v.Fg, v.Bg)
|
termboxUtil.DrawStringAtPoint(v.Text, startX, (startY + k - 1), v.Fg, v.Bg)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -667,105 +666,31 @@ func formatValueJSON(val []byte) ([]byte, error) {
|
|||||||
return out, nil
|
return out, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (screen *BrowserScreen) bucketToStrings(bkt *BoltBucket, style Style) []string {
|
func (screen *BrowserScreen) bucketToLines(bkt *BoltBucket, style Style) []Line {
|
||||||
|
var ret []Line
|
||||||
}
|
bfg, bbg := style.defaultFg, style.defaultBg
|
||||||
|
|
||||||
/* drawBucket
|
|
||||||
* @bkt *BoltBucket - The bucket to draw
|
|
||||||
* @style Style - The style to use
|
|
||||||
* @w int - The Width of the lines
|
|
||||||
* @y int - The Y position to start drawing
|
|
||||||
* return - The number of lines used
|
|
||||||
*/
|
|
||||||
func (screen *BrowserScreen) drawBucket(bkt *BoltBucket, style Style, y int) int {
|
|
||||||
w, _ := termbox.Size()
|
|
||||||
if w > 80 {
|
|
||||||
w = w / 2
|
|
||||||
}
|
|
||||||
usedLines := 0
|
|
||||||
bucketFg := style.defaultFg
|
|
||||||
bucketBg := style.defaultBg
|
|
||||||
if comparePaths(screen.currentPath, bkt.GetPath()) {
|
if comparePaths(screen.currentPath, bkt.GetPath()) {
|
||||||
bucketFg = style.cursorFg
|
bfg, bbg = style.cursorFg, style.cursorBg
|
||||||
bucketBg = style.cursorBg
|
|
||||||
}
|
}
|
||||||
|
bktPrefix := strings.Repeat(" ", len(bkt.GetPath())*2)
|
||||||
prefixSpaces := strings.Repeat(" ", len(bkt.GetPath())*2)
|
|
||||||
bktString := prefixSpaces
|
|
||||||
prefixSpaces = prefixSpaces + " "
|
|
||||||
|
|
||||||
padAmt := (len(bkt.GetPath())*2 + 2)
|
|
||||||
if bkt.expanded {
|
if bkt.expanded {
|
||||||
bktString = bktString + "- " + stringify([]byte(bkt.name))
|
ret = append(ret, Line{bktPrefix + "- " + stringify([]byte(bkt.name)), bfg, bbg})
|
||||||
if len(bktString)+padAmt > w {
|
|
||||||
bktString = bktString[:w-padAmt-3] + "..."
|
|
||||||
}
|
|
||||||
usedLines = screen.drawMultilineText(bktString, (len(bkt.GetPath())*2 + 2), 0, y, (w - 1), bucketFg, bucketBg)
|
|
||||||
|
|
||||||
for i := range bkt.buckets {
|
for i := range bkt.buckets {
|
||||||
usedLines += screen.drawBucket(&bkt.buckets[i], style, y+usedLines)
|
ret = append(ret, screen.bucketToLines(&bkt.buckets[i], style)...)
|
||||||
}
|
}
|
||||||
for i := range bkt.pairs {
|
for _, bp := range bkt.pairs {
|
||||||
usedLines += screen.drawPair(&bkt.pairs[i], style, y+usedLines)
|
pfg, pbg := style.defaultFg, style.defaultBg
|
||||||
|
if comparePaths(screen.currentPath, bp.GetPath()) {
|
||||||
|
pfg, pbg = style.cursorFg, style.cursorBg
|
||||||
|
}
|
||||||
|
prPrefix := strings.Repeat(" ", len(bp.GetPath())*2)
|
||||||
|
pairString := fmt.Sprintf("%s%s: %s", prPrefix, stringify([]byte(bp.key)), stringify([]byte(bp.val)))
|
||||||
|
ret = append(ret, Line{pairString, pfg, pbg})
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
bktString = bktString + "+ " + stringify([]byte(bkt.name))
|
ret = append(ret, Line{bktPrefix + "+ " + stringify([]byte(bkt.name)), bfg, bbg})
|
||||||
if len(bktString)+padAmt > w {
|
|
||||||
bktString = bktString[:w-padAmt-3] + "..."
|
|
||||||
}
|
|
||||||
usedLines = screen.drawMultilineText(bktString, (len(bkt.GetPath())*2 + 2), 0, y, (w - 1), bucketFg, bucketBg)
|
|
||||||
}
|
}
|
||||||
return usedLines
|
return ret
|
||||||
}
|
|
||||||
|
|
||||||
func (screen *BrowserScreen) drawPair(bp *BoltPair, style Style, y int) int {
|
|
||||||
w, _ := termbox.Size()
|
|
||||||
if w > 80 {
|
|
||||||
w = w / 2
|
|
||||||
}
|
|
||||||
usedLines := 0
|
|
||||||
bucketFg := style.defaultFg
|
|
||||||
bucketBg := style.defaultBg
|
|
||||||
if comparePaths(screen.currentPath, bp.GetPath()) {
|
|
||||||
bucketFg = style.cursorFg
|
|
||||||
bucketBg = style.cursorBg
|
|
||||||
}
|
|
||||||
|
|
||||||
prefixSpaces := strings.Repeat(" ", len(bp.GetPath())*2)
|
|
||||||
pairString := prefixSpaces
|
|
||||||
pairString = fmt.Sprintf("%s%s: %s", pairString, stringify([]byte(bp.key)), stringify([]byte(bp.val)))
|
|
||||||
if len(pairString) > w {
|
|
||||||
}
|
|
||||||
prefixSpaces = prefixSpaces + " "
|
|
||||||
if len(pairString) > w {
|
|
||||||
// The long pair strings are causing a problem, for now, truncate
|
|
||||||
pairString = pairString[:w-3] + "..."
|
|
||||||
}
|
|
||||||
/* TODO: Re-enable this when I figure out the display issue
|
|
||||||
// Long pair string, wrap it
|
|
||||||
// We're going to try to wrap it at the :, if we can
|
|
||||||
if len(bp.GetPath())*2+len(bp.key)+1 > w {
|
|
||||||
// We can't... So just wrap it
|
|
||||||
usedLines = screen.drawMultilineText(pairString, (len(bp.GetPath()) * 2), 0, y, (w - 1), style.defaultFg, style.defaultBg)
|
|
||||||
} else {
|
|
||||||
// That's convenient, wrap at the :
|
|
||||||
pairString := strings.Repeat(" ", len(bp.GetPath())*2)
|
|
||||||
pairString = fmt.Sprintf("%s%s:", pairString, bp.key)
|
|
||||||
termboxUtil.DrawStringAtPoint(pairString, 0, y, bucketFg, bucketBg)
|
|
||||||
usedLines++
|
|
||||||
pairString = strings.Repeat(" ", len(bp.GetPath())*2+2) + bp.val
|
|
||||||
usedLines += screen.drawMultilineText(pairString, (len(bp.GetPath())*2)+2, 0, y+1, (w - 1), bucketFg, bucketBg)
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
*/
|
|
||||||
if w-len(pairString) > 0 {
|
|
||||||
pairString = fmt.Sprintf("%s%s", pairString, strings.Repeat(" ", (w-len(pairString))))
|
|
||||||
}
|
|
||||||
termboxUtil.DrawStringAtPoint(pairString, 0, y, bucketFg, bucketBg)
|
|
||||||
usedLines = 1
|
|
||||||
// }
|
|
||||||
return usedLines
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (screen *BrowserScreen) startDeleteItem() bool {
|
func (screen *BrowserScreen) startDeleteItem() bool {
|
||||||
@ -963,31 +888,6 @@ func (screen *BrowserScreen) startExportJSON() bool {
|
|||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
// Print text on multiple lines, if needed
|
|
||||||
// msg - What to print
|
|
||||||
// indentPadding - number of spaces to pad lines after the first
|
|
||||||
// startX - Starting x
|
|
||||||
// startY - Starting y
|
|
||||||
// maxWidth - Maximum width
|
|
||||||
// fg, bg - Colors
|
|
||||||
// Returns the number of lines used
|
|
||||||
func (screen *BrowserScreen) drawMultilineText(msg string, indentPadding, startX, startY, maxWidth int, fg, bg termbox.Attribute) int {
|
|
||||||
var numLines int
|
|
||||||
spacePadding := strings.Repeat(" ", indentPadding)
|
|
||||||
// First we need to split 'msg' into the lines it should have (split on '\n')
|
|
||||||
msgs := strings.Split(msg, "\n")
|
|
||||||
for _, msg = range msgs {
|
|
||||||
for len(msg) > maxWidth {
|
|
||||||
termboxUtil.DrawStringAtPoint(msg[:maxWidth-1], startX, (startY + numLines), fg, bg)
|
|
||||||
msg = spacePadding + msg[maxWidth-1:]
|
|
||||||
numLines++
|
|
||||||
}
|
|
||||||
termboxUtil.DrawStringAtPoint(msg, startX, (startY + numLines), fg, bg)
|
|
||||||
numLines++
|
|
||||||
}
|
|
||||||
return numLines
|
|
||||||
}
|
|
||||||
|
|
||||||
func (screen *BrowserScreen) setMessage(msg string) {
|
func (screen *BrowserScreen) setMessage(msg string) {
|
||||||
screen.message = msg
|
screen.message = msg
|
||||||
screen.messageTime = time.Now()
|
screen.messageTime = time.Now()
|
||||||
|
Loading…
Reference in New Issue
Block a user