boltbrowser/ui/bolt_detail_pane.go

160 lines
4.0 KiB
Go

package ui
import (
"encoding/json"
"fmt"
"git.bullercodeworks.com/brian/boltbrowser/models"
"git.bullercodeworks.com/brian/boltbrowser/util"
"git.bullercodeworks.com/brian/wandle"
"git.bullercodeworks.com/brian/widdles"
"github.com/nsf/termbox-go"
)
/*
BoltDetailPane shows detail about either a bolt bucket or bolt pair
(as defined in the models subpackage)
*/
type BoltDetailPane struct {
x, y int
width int
height int
bucket *models.BoltBucket
pair *models.BoltPair
scrollRow int
active bool
visible bool
firstRow int
buffer []string
valueText *widdles.Text
db *models.BoltDB
}
func (p *BoltDetailPane) SetDB(db *models.BoltDB) { p.db = db }
func (p *BoltDetailPane) Init() wandle.Cmd {
p.valueText = widdles.NewText("", p.x, p.y, p.width-2, p.height)
return nil
}
func (p *BoltDetailPane) Update(msg wandle.Msg) wandle.Cmd {
switch msg := msg.(type) {
case termbox.Event:
switch msg.Ch {
case 'J':
return p.ScrollValueDown()
case 'K':
return p.ScrollValueUp()
}
}
return nil
}
func (p *BoltDetailPane) View(style wandle.Style) {
if len(p.buffer) == 0 || !p.visible {
return
}
for i := range p.buffer {
if i < len(p.buffer) {
wandle.Print(p.x, p.y+i, style, p.buffer[i])
}
}
if p.valueText.GetText() != "" {
p.valueText.View(style)
}
}
func (p *BoltDetailPane) IsActive() bool { return p.active }
func (p *BoltDetailPane) SetActive(b bool) { p.active = b }
func (p *BoltDetailPane) Focusable() bool { return true }
func (p *BoltDetailPane) SetX(x int) { p.x = x }
func (p *BoltDetailPane) SetY(y int) { p.y = y }
func (p *BoltDetailPane) GetX() int { return p.x }
func (p *BoltDetailPane) GetY() int { return p.y }
func (p *BoltDetailPane) GetHeight() int { return p.height }
func (p *BoltDetailPane) SetHeight(h int) { p.height = h }
func (p *BoltDetailPane) GetWidth() int { return p.width }
func (p *BoltDetailPane) SetWidth(w int) {
p.width = w
p.refresh()
}
func (p *BoltDetailPane) SetVisible(v bool) { p.visible = v }
func (p *BoltDetailPane) IsVisible() bool { return p.visible }
func (p *BoltDetailPane) SetBuffer(buffer []string) { p.buffer = buffer }
func (p *BoltDetailPane) refresh() {
p.buffer = []string{}
p.valueText.SetX(p.x + 1)
p.valueText.SetWidth(p.width - 2)
p.valueText.SetHeight(p.height - (p.y + len(p.buffer)))
if p.pair != nil {
p.buffer = append(p.buffer, []string{
fmt.Sprintf("Path: %s", pathToString(util.StringifyPath(p.pair.GetPath()))),
fmt.Sprintf("Key: %s", util.Stringify([]byte(p.pair.GetKey()))),
"Value:",
}...)
value := string(p.formatValue([]byte(p.pair.GetValue())))
p.valueText.SetText(value)
} else if p.bucket != nil {
p.buffer = append(p.buffer, []string{
fmt.Sprintf("Path: %s", pathToString(util.StringifyPath(p.bucket.GetPath()))),
fmt.Sprintf("Buckets: %d", len(p.bucket.GetBuckets())),
fmt.Sprintf("Pairs: %d", len(p.bucket.GetPairs())),
}...)
p.valueText.SetY(p.y + len(p.buffer))
p.valueText.SetText("")
}
}
func (p *BoltDetailPane) SetActiveItem(bucket *models.BoltBucket, pair *models.BoltPair, e error) {
if bucket != nil {
p.SetBucket(bucket)
} else if pair != nil {
p.SetPair(pair)
}
}
func (p *BoltDetailPane) SetBucket(b *models.BoltBucket) {
p.pair = nil
p.bucket = b
p.refresh()
}
func (p *BoltDetailPane) SetPair(pair *models.BoltPair) {
p.bucket = nil
p.pair = pair
p.refresh()
}
func (p *BoltDetailPane) ScrollValueUp() wandle.Cmd {
return func() wandle.Msg {
return nil
}
}
func (p *BoltDetailPane) ScrollValueDown() wandle.Cmd {
return func() wandle.Msg {
//p.valueText.
return nil
}
}
func (p *BoltDetailPane) formatValue(val []byte) []byte {
// Attempt JSON parsing and formatting
out, err := formatValueJSON(val)
if err == nil {
return out
}
return []byte(util.Stringify([]byte(val)))
}
func formatValueJSON(val []byte) ([]byte, error) {
var jsonOut interface{}
err := json.Unmarshal(val, &jsonOut)
if err != nil {
return val, err
}
out, err := json.MarshalIndent(jsonOut, "", " ")
if err != nil {
return val, err
}
return out, nil
}