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 }