Switching views, wrapping values
This commit is contained in:
parent
dfc79b4986
commit
dce6e6c368
@ -3,11 +3,12 @@ package ui
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"strings"
|
||||
|
||||
"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"
|
||||
)
|
||||
|
||||
/*
|
||||
@ -22,18 +23,34 @@ type BoltDetailPane struct {
|
||||
pair *models.BoltPair
|
||||
scrollRow int
|
||||
active bool
|
||||
visible bool
|
||||
|
||||
firstRow int
|
||||
buffer []string
|
||||
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 { return nil }
|
||||
func (p *BoltDetailPane) Update(wandle.Msg) wandle.Cmd { return nil }
|
||||
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 {
|
||||
if len(p.buffer) == 0 || !p.visible {
|
||||
return
|
||||
}
|
||||
for i := range p.buffer {
|
||||
@ -41,40 +58,49 @@ func (p *BoltDetailPane) View(style wandle.Style) {
|
||||
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 }
|
||||
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 := strings.Split(string(p.formatValue([]byte(p.pair.GetValue()))), "\n")
|
||||
if len(value) == 1 {
|
||||
p.buffer = append(p.buffer, fmt.Sprintf("Value: %s", value[0]))
|
||||
} else {
|
||||
p.buffer = append(p.buffer, "Value:")
|
||||
p.buffer = append(p.buffer, value...)
|
||||
}
|
||||
//fmt.Sprintf("Value: %s", ),
|
||||
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("")
|
||||
}
|
||||
}
|
||||
|
||||
@ -98,6 +124,18 @@ func (p *BoltDetailPane) SetPair(pair *models.BoltPair) {
|
||||
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)
|
||||
|
@ -15,6 +15,7 @@ type BoltTreePane struct {
|
||||
height int
|
||||
scrollRow int
|
||||
active bool
|
||||
visible bool
|
||||
|
||||
buffer []string
|
||||
pathBuffer [][]string
|
||||
@ -134,6 +135,9 @@ func (w *BoltTreePane) handleTermboxEvent(msg termbox.Event) wandle.Cmd {
|
||||
return nil
|
||||
}
|
||||
func (w *BoltTreePane) View(style wandle.Style) {
|
||||
if !w.visible {
|
||||
return
|
||||
}
|
||||
if w.db == nil {
|
||||
txt := "No Database Loaded"
|
||||
midX := (w.x + w.width/2) - len(txt)/2
|
||||
@ -164,7 +168,12 @@ func (w *BoltTreePane) View(style wandle.Style) {
|
||||
pos := (w.y + kIdx - 1)
|
||||
bot := (w.y + w.height)
|
||||
if pos < bot {
|
||||
wandle.Print(w.x, pos, st, util.Stringify([]byte(v)))
|
||||
valBuffer := wandle.WrapText(util.Stringify([]byte(v)), w.width)
|
||||
for i := range valBuffer {
|
||||
wandle.Print(w.x, pos, st, valBuffer[i])
|
||||
pos++
|
||||
}
|
||||
//wandle.Print(w.x, pos, st, out)
|
||||
}
|
||||
kIdx++
|
||||
}
|
||||
@ -188,17 +197,19 @@ func (w *BoltTreePane) SetRenameBucketCommand(cmd func(*models.BoltBucket) wandl
|
||||
func (w *BoltTreePane) SetDeleteItemCommand(cmd func([]string) wandle.Cmd) {
|
||||
w.deleteItemCmd = cmd
|
||||
}
|
||||
func (w *BoltTreePane) IsActive() bool { return w.active }
|
||||
func (w *BoltTreePane) SetActive(b bool) { w.active = b }
|
||||
func (w *BoltTreePane) Focusable() bool { return true }
|
||||
func (w *BoltTreePane) SetX(x int) { w.x = x }
|
||||
func (w *BoltTreePane) SetY(y int) { w.y = y }
|
||||
func (w *BoltTreePane) GetX() int { return w.x }
|
||||
func (w *BoltTreePane) GetY() int { return w.y }
|
||||
func (w *BoltTreePane) SetHeight(h int) { w.height = h }
|
||||
func (w *BoltTreePane) GetHeight() int { return w.height }
|
||||
func (w *BoltTreePane) SetWidth(wdt int) { w.height = wdt }
|
||||
func (w *BoltTreePane) GetWidth() int { return w.width }
|
||||
func (w *BoltTreePane) IsActive() bool { return w.active }
|
||||
func (w *BoltTreePane) SetActive(b bool) { w.active = b }
|
||||
func (w *BoltTreePane) IsVisible() bool { return w.visible }
|
||||
func (w *BoltTreePane) SetVisible(b bool) { w.visible = b }
|
||||
func (w *BoltTreePane) Focusable() bool { return true }
|
||||
func (w *BoltTreePane) SetX(x int) { w.x = x }
|
||||
func (w *BoltTreePane) SetY(y int) { w.y = y }
|
||||
func (w *BoltTreePane) GetX() int { return w.x }
|
||||
func (w *BoltTreePane) GetY() int { return w.y }
|
||||
func (w *BoltTreePane) SetHeight(h int) { w.height = h }
|
||||
func (w *BoltTreePane) GetHeight() int { return w.height }
|
||||
func (w *BoltTreePane) SetWidth(wdt int) { w.height = wdt }
|
||||
func (w *BoltTreePane) GetWidth() int { return w.width }
|
||||
|
||||
func (w *BoltTreePane) HasDB() bool { return w.db != nil }
|
||||
func (w *BoltTreePane) SetDB(db *models.BoltDB) {
|
||||
@ -397,7 +408,7 @@ func (w *BoltTreePane) insertBucketAtParent() wandle.Msg {
|
||||
insertPath := w.currentPath[:len(w.currentPath)-1]
|
||||
b, e := w.db.GetBucketFromPath(insertPath)
|
||||
if e != nil {
|
||||
w.setStatus("Error inserting new pair. Invalid Path.", time.Second)
|
||||
w.setStatus("Error inserting new bucket. Invalid Path.", time.Second)
|
||||
return nil
|
||||
}
|
||||
return w.insertBucketCmd(b)
|
||||
|
@ -18,6 +18,11 @@ const (
|
||||
BS_CmdRefresh = BrowseId | iota
|
||||
BS_CmdRefreshTree
|
||||
BS_CmdDBTimeout
|
||||
|
||||
BS_ScreenAuto = iota
|
||||
BS_ScreenSplit
|
||||
BS_ScreenFullTree
|
||||
BS_ScreenFullDetail
|
||||
)
|
||||
|
||||
type BrowseMsg struct {
|
||||
@ -31,7 +36,12 @@ type browseScreen struct {
|
||||
dbPath string
|
||||
db *models.BoltDB
|
||||
|
||||
status *widdles.Text
|
||||
status *widdles.Text
|
||||
statusMsg string
|
||||
statusIdx int
|
||||
|
||||
screenMode int
|
||||
screenModeIsAuto bool
|
||||
|
||||
treePane *BoltTreePane
|
||||
detailPane *BoltDetailPane
|
||||
@ -39,14 +49,17 @@ type browseScreen struct {
|
||||
inputDialog *widdles.InputDialog
|
||||
confirmDialog *widdles.ConfirmDialog
|
||||
|
||||
initialized bool
|
||||
width, height int
|
||||
initialized bool
|
||||
}
|
||||
|
||||
func NewBrowseScreen(u *Ui) *browseScreen {
|
||||
return &browseScreen{
|
||||
ui: u,
|
||||
inputDialog: widdles.NewInputDialog("Edit", ""),
|
||||
confirmDialog: widdles.NewConfirmDialog("Are you sure?", ""),
|
||||
ui: u,
|
||||
screenMode: BS_ScreenSplit,
|
||||
screenModeIsAuto: true,
|
||||
inputDialog: widdles.NewInputDialog("Edit", ""),
|
||||
confirmDialog: widdles.NewConfirmDialog("Are you sure?", ""),
|
||||
}
|
||||
}
|
||||
|
||||
@ -54,14 +67,15 @@ func (s *browseScreen) Init() wandle.Cmd {
|
||||
if s.initialized {
|
||||
return nil
|
||||
}
|
||||
w, h := termbox.Size()
|
||||
s.width, s.height = termbox.Size()
|
||||
dbs := viper.GetStringSlice("dbs")
|
||||
dbidx := viper.GetInt("dbidx")
|
||||
if len(dbs) <= dbidx {
|
||||
return wandle.Quit
|
||||
}
|
||||
s.dbPath = dbs[dbidx]
|
||||
s.treePane = NewBoltTreePane(0, 3, w/2, h-6)
|
||||
s.treePane = NewBoltTreePane(0, 3, s.width/2, s.height-6)
|
||||
s.treePane.SetVisible(true)
|
||||
s.treePane.SetInsertPairCommand(s.insertPair)
|
||||
s.treePane.SetInsertBucketCommand(s.insertBucket)
|
||||
s.treePane.SetEditPairKeyCommand(s.editPairKey)
|
||||
@ -70,14 +84,16 @@ func (s *browseScreen) Init() wandle.Cmd {
|
||||
s.treePane.SetDeleteItemCommand(s.deleteItem)
|
||||
s.treePane.SetStatusFunc(s.setStatus)
|
||||
s.detailPane = &BoltDetailPane{
|
||||
x: w/2 + 2, y: 2,
|
||||
width: w / 2, height: h - 6,
|
||||
x: s.width/2 + 2, y: 2,
|
||||
width: s.width / 2, height: s.height - 6,
|
||||
}
|
||||
s.detailPane.SetVisible(true)
|
||||
s.detailPane.Init()
|
||||
s.treePane.SetDetailPane(s.detailPane)
|
||||
s.status = widdles.NewText("Press '?' for help", 0, (h - 1), w, 1)
|
||||
s.status = widdles.NewText("Press '?' for help", 0, (s.height - 1), s.width, 1)
|
||||
s.inputDialog.Init()
|
||||
s.confirmDialog.Init()
|
||||
s.setScreenToAuto()
|
||||
|
||||
return func() wandle.Msg {
|
||||
timeout, err := time.ParseDuration(viper.GetString("version"))
|
||||
@ -93,8 +109,12 @@ func (s *browseScreen) Init() wandle.Cmd {
|
||||
db.Close()
|
||||
}
|
||||
s.treePane.SetDB(s.db)
|
||||
s.resizeWindow(w, h)
|
||||
s.resizeWindow(s.width, s.height)
|
||||
s.initialized = true
|
||||
// If this is an empty database, force a bucket entry
|
||||
if len(s.db.GetBuckets()) == 0 {
|
||||
return s.insertBucket(nil)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
}
|
||||
@ -116,33 +136,38 @@ func (s *browseScreen) handleBrowseMsg(msg BrowseMsg) wandle.Cmd {
|
||||
return nil
|
||||
}
|
||||
func (s *browseScreen) handleTermboxEvent(msg termbox.Event) wandle.Cmd {
|
||||
if s.inputDialog.IsActive() {
|
||||
return s.inputDialog.Update(msg)
|
||||
if cmd := s.inputDialog.Update(msg); cmd != nil {
|
||||
return cmd
|
||||
}
|
||||
if s.confirmDialog.IsActive() {
|
||||
return s.confirmDialog.Update(msg)
|
||||
if cmd := s.confirmDialog.Update(msg); cmd != nil {
|
||||
return cmd
|
||||
}
|
||||
|
||||
var cmds []wandle.Cmd
|
||||
cmds = append(cmds, s.treePane.Update(msg))
|
||||
cmds = append(cmds, s.detailPane.Update(msg))
|
||||
|
||||
switch msg.Type {
|
||||
case termbox.EventKey:
|
||||
if cmd := s.treePane.Update(msg); cmd != nil {
|
||||
return cmd
|
||||
}
|
||||
switch {
|
||||
case msg.Ch == '?':
|
||||
return wandle.SwitchScreenCmd(NewAboutScreen(s.ui))
|
||||
cmds = append(cmds, wandle.SwitchScreenCmd(NewAboutScreen(s.ui)))
|
||||
case msg.Ch == 'q' || msg.Key == termbox.KeyCtrlC:
|
||||
return wandle.Quit
|
||||
case msg.Ch == 'x':
|
||||
return s.exportValue
|
||||
cmds = append(cmds, s.exportValue)
|
||||
case msg.Ch == 'X':
|
||||
return s.exportJSON
|
||||
cmds = append(cmds, s.exportJSON)
|
||||
case msg.Ch == 'v':
|
||||
// Toggle through screen view modes
|
||||
cmds = append(cmds, s.toggleScreenMode())
|
||||
case msg.Ch == 'V':
|
||||
// Set screen mode to Auto
|
||||
cmds = append(cmds, s.setScreenToAuto())
|
||||
return nil
|
||||
// TODO: External editor
|
||||
//case msg.Ch == 'E':
|
||||
// return s.startEditor
|
||||
case msg.Ch == 'J':
|
||||
// TODO: Move Right Pane Down
|
||||
case msg.Ch == 'K':
|
||||
// TODO: Move Right Pane Up
|
||||
case msg.Key == termbox.KeyCtrlN:
|
||||
// Next File
|
||||
idx := viper.GetInt("dbidx") + 1
|
||||
@ -150,7 +175,7 @@ func (s *browseScreen) handleTermboxEvent(msg termbox.Event) wandle.Cmd {
|
||||
s.setStatus("Already at last file", time.Second)
|
||||
} else {
|
||||
viper.Set("dbidx", idx)
|
||||
return wandle.SwitchScreenCmd(NewBrowseScreen(s.ui))
|
||||
cmds = append(cmds, wandle.SwitchScreenCmd(NewBrowseScreen(s.ui)))
|
||||
}
|
||||
case msg.Key == termbox.KeyCtrlP:
|
||||
// Previous File
|
||||
@ -159,32 +184,88 @@ func (s *browseScreen) handleTermboxEvent(msg termbox.Event) wandle.Cmd {
|
||||
s.setStatus("Already at first file", time.Second)
|
||||
} else {
|
||||
viper.Set("dbidx", idx)
|
||||
return wandle.SwitchScreenCmd(NewBrowseScreen(s.ui))
|
||||
cmds = append(cmds, wandle.SwitchScreenCmd(NewBrowseScreen(s.ui)))
|
||||
}
|
||||
}
|
||||
case termbox.EventResize:
|
||||
s.resizeWindow(msg.Width, msg.Height)
|
||||
}
|
||||
return nil
|
||||
return wandle.Batch(cmds...)
|
||||
}
|
||||
|
||||
func (s *browseScreen) toggleScreenMode() wandle.Cmd {
|
||||
switch s.screenMode {
|
||||
case BS_ScreenSplit:
|
||||
return s.setScreenToFullTree
|
||||
case BS_ScreenFullTree:
|
||||
return s.setScreenToFullDetail
|
||||
case BS_ScreenFullDetail:
|
||||
return s.setScreenToSplit
|
||||
default:
|
||||
return s.setScreenToAuto()
|
||||
}
|
||||
}
|
||||
func (s *browseScreen) setScreenToAuto() wandle.Cmd {
|
||||
s.screenModeIsAuto = true
|
||||
s.setStatus("Setting screen mode to Auto", time.Second)
|
||||
if s.width >= 80 {
|
||||
return s.setScreenToSplit
|
||||
} else {
|
||||
return s.setScreenToFullTree
|
||||
}
|
||||
}
|
||||
func (s *browseScreen) setScreenToSplit() wandle.Msg {
|
||||
s.screenMode = BS_ScreenSplit
|
||||
s.setStatus("Setting screen mode to Split", time.Second)
|
||||
s.treePane.SetVisible(true)
|
||||
s.treePane.SetWidth(s.width / 2)
|
||||
s.detailPane.SetX(s.width/2 + 1)
|
||||
s.detailPane.SetWidth(s.width / 2)
|
||||
return nil
|
||||
}
|
||||
func (s *browseScreen) setScreenToFullTree() wandle.Msg {
|
||||
s.screenMode = BS_ScreenFullTree
|
||||
s.setStatus("Setting screen mode to Full Tree", time.Second)
|
||||
s.treePane.SetVisible(true)
|
||||
s.treePane.SetWidth(s.width)
|
||||
s.detailPane.SetVisible(false)
|
||||
return nil
|
||||
}
|
||||
func (s *browseScreen) setScreenToFullDetail() wandle.Msg {
|
||||
s.screenMode = BS_ScreenFullDetail
|
||||
s.setStatus("Setting screen mode to Full Detail", time.Second)
|
||||
s.treePane.SetVisible(false)
|
||||
s.detailPane.SetVisible(true)
|
||||
s.detailPane.SetX(0)
|
||||
s.detailPane.SetWidth(s.width)
|
||||
return nil
|
||||
}
|
||||
func (s *browseScreen) resizeWindow(w, h int) {
|
||||
s.width, s.height = w, h
|
||||
lw := w
|
||||
dlgWidth := 2
|
||||
if lw > 80 {
|
||||
lw = lw / 2
|
||||
dlgWidth = 4
|
||||
}
|
||||
if s.screenModeIsAuto {
|
||||
s.setScreenToAuto()
|
||||
} else {
|
||||
switch s.screenMode {
|
||||
case BS_ScreenSplit:
|
||||
s.setScreenToSplit()
|
||||
case BS_ScreenFullTree:
|
||||
s.setScreenToFullTree()
|
||||
case BS_ScreenFullDetail:
|
||||
s.setScreenToFullDetail()
|
||||
}
|
||||
}
|
||||
|
||||
// Re-build Tree pane
|
||||
s.treePane.SetWidth(lw)
|
||||
s.treePane.SetHeight(h - 4)
|
||||
// Re-build Right Pane buffer
|
||||
s.detailPane.SetX(lw + 1)
|
||||
s.detailPane.SetWidth(w - lw)
|
||||
s.detailPane.SetHeight(h - 2)
|
||||
// Re-build the input dialog
|
||||
dlgWidth := 4
|
||||
if w < 80 {
|
||||
dlgWidth = 2
|
||||
}
|
||||
s.inputDialog.SetX((w / 2) - (w / (dlgWidth * 2)))
|
||||
s.inputDialog.SetWidth(w / dlgWidth)
|
||||
s.inputDialog.SetY((h / 2) - (h / 4))
|
||||
@ -198,17 +279,15 @@ func (s *browseScreen) resizeWindow(w, h int) {
|
||||
}
|
||||
|
||||
func (s *browseScreen) View(style wandle.Style) {
|
||||
w, h := termbox.Size()
|
||||
s.drawHeader(style)
|
||||
s.treePane.View(style)
|
||||
midX := s.detailPane.GetX() - 1
|
||||
if w > 80 {
|
||||
termbox.SetCell(midX, 1, '╤', style.Foreground, style.Background)
|
||||
wandle.Fill('│', midX, 2, midX, h-3, style)
|
||||
s.detailPane.View(style)
|
||||
s.detailPane.View(style)
|
||||
if s.treePane.IsVisible() && s.detailPane.IsVisible() {
|
||||
termbox.SetCell(s.width/2, 1, '╤', style.Foreground, style.Background)
|
||||
wandle.Fill('│', s.width/2, 2, s.width/2, s.height-3, style)
|
||||
termbox.SetCell(s.width/2, s.height-2, '╧', style.Foreground, style.Background)
|
||||
}
|
||||
wandle.Fill('═', 0, h-2, w, h-2, style)
|
||||
termbox.SetCell(midX, h-2, '╧', style.Foreground, style.Background)
|
||||
wandle.Fill('═', 0, s.height-2, s.width, s.height-2, style)
|
||||
s.status.View(style)
|
||||
if s.inputDialog.IsVisible() {
|
||||
s.inputDialog.View(style)
|
||||
@ -219,34 +298,53 @@ func (s *browseScreen) View(style wandle.Style) {
|
||||
}
|
||||
|
||||
func (s *browseScreen) drawHeader(style wandle.Style) {
|
||||
width, _ := termbox.Size()
|
||||
headerStringLen := func(fileName string) int {
|
||||
return len("boltbrowser") + len(fileName) + 1
|
||||
}
|
||||
headerFileName := s.dbPath
|
||||
if headerStringLen(headerFileName) > width {
|
||||
if headerStringLen(headerFileName) > s.width {
|
||||
headerFileName = filepath.Base(headerFileName)
|
||||
}
|
||||
headerString := "boltbrowser" + ": " + headerFileName
|
||||
count := ((width - len(headerString)) / 2) + 1
|
||||
count := ((s.width - len(headerString)) / 2) + 1
|
||||
if count < 0 {
|
||||
count = 0
|
||||
}
|
||||
spaces := strings.Repeat(" ", count)
|
||||
wandle.Print(0, 0, style, fmt.Sprintf("%s%s%s", spaces, headerString, spaces))
|
||||
wandle.Fill('═', 0, 1, width, 1, style)
|
||||
wandle.Fill('═', 0, 1, s.width, 1, style)
|
||||
}
|
||||
|
||||
func (s *browseScreen) setStatus(status string, timeout time.Duration) {
|
||||
s.status.SetText(status)
|
||||
s.status.ClearStyle()
|
||||
s.statusIdx++
|
||||
idx := s.statusIdx
|
||||
if timeout > 0 {
|
||||
go func() {
|
||||
time.Sleep(timeout)
|
||||
if s.status.GetText() == status {
|
||||
s.status.SetText("")
|
||||
time.AfterFunc(timeout, func() {
|
||||
if idx == s.statusIdx {
|
||||
s.setStatus("", -1)
|
||||
s.ui.wandle.Send(BS_CmdRefresh)
|
||||
}
|
||||
}()
|
||||
})
|
||||
}
|
||||
}
|
||||
func (s *browseScreen) setErrorStatus(status string, timeout time.Duration) {
|
||||
s.status.SetStyle(wandle.NewStyle(
|
||||
termbox.RGBToAttribute(uint8(255), uint8(0), uint8(0)),
|
||||
termbox.RGBToAttribute(uint8(0), uint8(0), uint8(0)),
|
||||
).Blink(true))
|
||||
s.status.SetText(status)
|
||||
s.statusIdx++
|
||||
idx := s.statusIdx
|
||||
if timeout > 0 {
|
||||
time.AfterFunc(timeout, func() {
|
||||
if idx == s.statusIdx {
|
||||
s.setStatus("", -1)
|
||||
s.status.ClearStyle()
|
||||
s.ui.wandle.Send(BS_CmdRefresh)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
func (s *browseScreen) insertPair(bucket *models.BoltBucket) wandle.Cmd {
|
||||
@ -257,14 +355,14 @@ func (s *browseScreen) insertPair(bucket *models.BoltBucket) wandle.Cmd {
|
||||
s.inputDialog.SetOkCommand(func() wandle.Msg {
|
||||
key := s.inputDialog.GetValue()
|
||||
if key == "" {
|
||||
s.setStatus("Pair key cannot be empty", time.Second)
|
||||
s.setErrorStatus("! Pair key cannot be empty", time.Second*5)
|
||||
} else {
|
||||
s.inputDialog.SetMessage("New Pair Value")
|
||||
s.inputDialog.SetValue("")
|
||||
s.inputDialog.SetOkCommand(func() wandle.Msg {
|
||||
val := s.inputDialog.GetValue()
|
||||
if err := s.db.InsertPair(bucket.GetPath(), key, val); err != nil {
|
||||
s.setStatus("Error inserting pair.", time.Second)
|
||||
s.setErrorStatus("! Error inserting pair.", time.Second*5)
|
||||
} else {
|
||||
s.inputDialog.Hide()
|
||||
return BrowseMsg{source: BS_CmdRefreshTree}
|
||||
@ -288,10 +386,14 @@ func (s *browseScreen) insertBucket(bucket *models.BoltBucket) wandle.Cmd {
|
||||
s.inputDialog.SetOkCommand(func() wandle.Msg {
|
||||
key := s.inputDialog.GetValue()
|
||||
if key == "" {
|
||||
s.setStatus("Pair key cannot be empty", time.Second)
|
||||
s.setErrorStatus("! Bucket key cannot be empty", time.Second*5)
|
||||
} else {
|
||||
if err := s.db.InsertBucket(bucket.GetPath(), key); err != nil {
|
||||
s.setStatus("Error inserting pair.", time.Second)
|
||||
path := []string{}
|
||||
if bucket != nil {
|
||||
path = bucket.GetPath()
|
||||
}
|
||||
if err := s.db.InsertBucket(path, key); err != nil {
|
||||
s.setErrorStatus("! Error inserting bucket", time.Second*5)
|
||||
} else {
|
||||
s.inputDialog.Hide()
|
||||
return BrowseMsg{source: BS_CmdRefreshTree}
|
||||
@ -307,14 +409,15 @@ func (s *browseScreen) insertBucket(bucket *models.BoltBucket) wandle.Cmd {
|
||||
return nil
|
||||
}
|
||||
func (s *browseScreen) editPairKey(pair *models.BoltPair) wandle.Cmd {
|
||||
s.inputDialog.SetTitle(fmt.Sprintf("Input new value for '%s'", pair.GetKey()))
|
||||
s.inputDialog.SetTitle(fmt.Sprintf("Edit pair key for '%s'", pair.GetKey()))
|
||||
s.inputDialog.SetValue(pair.GetKey())
|
||||
s.inputDialog.SetMessage("")
|
||||
s.inputDialog.SetOkCommand(func() wandle.Msg {
|
||||
v := s.inputDialog.GetValue()
|
||||
if v == "" {
|
||||
s.setStatus("No value given, did you mean to (d)elete?", time.Second)
|
||||
s.setErrorStatus("! No value given, did you mean to (d)elete?", time.Second*5)
|
||||
} else if err := s.db.UpdatePairKey(s.treePane.currentPath, v); err != nil {
|
||||
s.setStatus("Error changing pair key", time.Second)
|
||||
s.setErrorStatus("! Error changing pair key", time.Second*5)
|
||||
} else {
|
||||
s.treePane.currentPath[len(s.treePane.currentPath)-1] = v
|
||||
s.inputDialog.Hide()
|
||||
@ -330,14 +433,15 @@ func (s *browseScreen) editPairKey(pair *models.BoltPair) wandle.Cmd {
|
||||
return nil
|
||||
}
|
||||
func (s *browseScreen) editPairValue(pair *models.BoltPair) wandle.Cmd {
|
||||
s.inputDialog.SetTitle(fmt.Sprintf("Input new value for '%s'", pair.GetKey()))
|
||||
s.inputDialog.SetTitle(fmt.Sprintf("Edit pair value for '%s'", pair.GetKey()))
|
||||
s.inputDialog.SetValue(pair.GetValue())
|
||||
s.inputDialog.SetMessage("")
|
||||
s.inputDialog.SetOkCommand(func() wandle.Msg {
|
||||
v := s.inputDialog.GetValue()
|
||||
if v == "" {
|
||||
s.setStatus("No value given, did you mean to (d)elete?", time.Second)
|
||||
s.setErrorStatus("! No value given, did you mean to (d)elete?", time.Second*5)
|
||||
} else if err := s.treePane.db.UpdatePairValue(s.treePane.currentPath, v); err != nil {
|
||||
s.setStatus("Error updating pair value.", time.Second)
|
||||
s.setErrorStatus("! Error updating pair value.", time.Second*5)
|
||||
} else {
|
||||
s.inputDialog.Hide()
|
||||
return BrowseMsg{source: BS_CmdRefreshTree}
|
||||
@ -354,12 +458,13 @@ func (s *browseScreen) editPairValue(pair *models.BoltPair) wandle.Cmd {
|
||||
func (s *browseScreen) editBucket(bucket *models.BoltBucket) wandle.Cmd {
|
||||
s.inputDialog.SetTitle(fmt.Sprintf("Rename Bucket '%s' to:", bucket.GetName()))
|
||||
s.inputDialog.SetValue(bucket.GetName())
|
||||
s.inputDialog.SetMessage("")
|
||||
s.inputDialog.SetOkCommand(func() wandle.Msg {
|
||||
v := s.inputDialog.GetValue()
|
||||
if v == "" {
|
||||
s.setStatus("A Bucket has to have a name.", time.Second)
|
||||
s.setErrorStatus("! A Bucket has to have a name.", time.Second*5)
|
||||
} else if err := s.db.RenameBucket(s.treePane.currentPath, v); err != nil {
|
||||
s.setStatus("Error renaming bucket.", time.Second)
|
||||
s.setErrorStatus("! Error renaming bucket.", time.Second*5)
|
||||
} else {
|
||||
bkt, _ := s.treePane.db.GetBucketFromPath(s.treePane.currentPath)
|
||||
if bkt != nil {
|
||||
@ -391,7 +496,7 @@ func (s *browseScreen) deleteItem(path []string) wandle.Cmd {
|
||||
} else if p != nil {
|
||||
itemType = "Pair"
|
||||
} else {
|
||||
s.setStatus("Error deleting item.", time.Second)
|
||||
s.setErrorStatus("! Error deleting item.", time.Second*5)
|
||||
}
|
||||
|
||||
s.confirmDialog.SetTitle(fmt.Sprintf("Delete %s '%s'?", itemType, key))
|
||||
@ -399,7 +504,7 @@ func (s *browseScreen) deleteItem(path []string) wandle.Cmd {
|
||||
s.confirmDialog.SetOkCommand(func() wandle.Msg {
|
||||
s.treePane.moveCursorUp()
|
||||
if err := s.treePane.db.DeleteKey(path); err != nil {
|
||||
s.setStatus(fmt.Sprintf("Error deleting %s.", itemType), time.Second)
|
||||
s.setErrorStatus(fmt.Sprintf("! Error deleting %s.", itemType), time.Second*5)
|
||||
}
|
||||
s.confirmDialog.Hide()
|
||||
return BrowseMsg{source: BS_CmdRefreshTree}
|
||||
@ -416,18 +521,19 @@ func (s *browseScreen) exportValue() wandle.Msg {
|
||||
path := s.treePane.GetCurrentPath()
|
||||
b, p, e := s.treePane.GetSelected()
|
||||
if e != nil || p == nil {
|
||||
s.setStatus("Couldn't do string export on "+path[len(path)-1]+" (did you mean 'X'?)", time.Second)
|
||||
s.setErrorStatus("! Couldn't do string export on "+path[len(path)-1]+" (did you mean 'X'?)", time.Second*5)
|
||||
return nil
|
||||
}
|
||||
s.inputDialog.SetTitle(fmt.Sprintf("Export value of '%s' to:", b.GetName()))
|
||||
s.inputDialog.SetMessage("")
|
||||
s.inputDialog.SetValue("")
|
||||
s.inputDialog.SetOkCommand(func() wandle.Msg {
|
||||
v := s.inputDialog.GetValue()
|
||||
if v == "" {
|
||||
s.setStatus("Must give a file name to export to.", time.Second)
|
||||
s.setErrorStatus("! Must give a file name to export to.", time.Second*5)
|
||||
} else {
|
||||
if err := s.db.ExportValue(s.treePane.GetCurrentPath(), v); err != nil {
|
||||
s.setStatus("Error Exporting Value", time.Second)
|
||||
s.setErrorStatus("! Error Exporting Value", time.Second*5)
|
||||
}
|
||||
}
|
||||
return nil
|
||||
@ -439,7 +545,7 @@ func (s *browseScreen) exportValue() wandle.Msg {
|
||||
func (s *browseScreen) exportJSON() wandle.Msg {
|
||||
b, p, e := s.treePane.GetSelected()
|
||||
if e != nil {
|
||||
s.setStatus("Error getting value to export", time.Second)
|
||||
s.setErrorStatus("! Error getting value to export", time.Second*5)
|
||||
return nil
|
||||
}
|
||||
var nm string
|
||||
@ -450,14 +556,15 @@ func (s *browseScreen) exportJSON() wandle.Msg {
|
||||
}
|
||||
|
||||
s.inputDialog.SetTitle(fmt.Sprintf("Export JSON of '%s' to:", nm))
|
||||
s.inputDialog.SetMessage("")
|
||||
s.inputDialog.SetValue("")
|
||||
s.inputDialog.SetOkCommand(func() wandle.Msg {
|
||||
v := s.inputDialog.GetValue()
|
||||
if v == "" {
|
||||
s.setStatus("Must give a file name to export to.", time.Second)
|
||||
s.setErrorStatus("! Must give a file name to export to.", time.Second*5)
|
||||
} else {
|
||||
if err := s.db.ExportJSON(s.treePane.GetCurrentPath(), v); err != nil {
|
||||
s.setStatus("Error Exporting JSON", time.Second)
|
||||
s.setErrorStatus("! Error Exporting JSON", time.Second*5)
|
||||
}
|
||||
}
|
||||
return nil
|
||||
|
Loading…
Reference in New Issue
Block a user