Add Progress Bars

Also, add vim navigation to menus
This commit is contained in:
Brian Buller 2015-11-30 08:21:22 -06:00
parent 02537f2b96
commit 9ca0888000
2 changed files with 259 additions and 0 deletions

View File

@ -15,6 +15,7 @@ type Menu struct {
disabledBg, disabledFg termbox.Attribute
isDone bool
bordered bool
vimMode bool
}
// CreateMenu Creates a menu with the specified attributes
@ -178,6 +179,20 @@ func (i *Menu) SelectNextOption() *Menu {
return i
}
// SetOptionDisabled Disables the specified option
func (i *Menu) SetOptionDisabled(idx int) {
if len(i.options) > idx {
i.GetOptionFromIndex(idx).Disable()
}
}
// SetOptionEnabled Enables the specified option
func (i *Menu) SetOptionEnabled(idx int) {
if len(i.options) > idx {
i.GetOptionFromIndex(idx).Enable()
}
}
// HelpIsShown returns true or false if the help is displayed
func (i *Menu) HelpIsShown() bool { return i.showHelp }
@ -223,6 +238,18 @@ func (i *Menu) SetBordered(b bool) *Menu {
return i
}
// EnableVimMode Enables h,j,k,l navigation
func (i *Menu) EnableVimMode() *Menu {
i.vimMode = true
return i
}
// DisableVimMode Disables h,j,k,l navigation
func (i *Menu) DisableVimMode() *Menu {
i.vimMode = false
return i
}
// HandleKeyPress handles the termbox event and returns whether it was consumed
func (i *Menu) HandleKeyPress(event termbox.Event) bool {
if event.Key == termbox.KeyEnter {
@ -236,6 +263,14 @@ func (i *Menu) HandleKeyPress(event termbox.Event) bool {
case termbox.KeyArrowDown:
i.SelectNextOption()
}
if i.vimMode {
switch event.Ch {
case 'j':
i.SelectNextOption()
case 'k':
i.SelectPrevOption()
}
}
if i.GetSelectedIndex() != currentIdx {
return true
}

224
termbox_progressbar.go Normal file
View File

@ -0,0 +1,224 @@
package termboxUtil
import "github.com/nsf/termbox-go"
// ProgressBar Just contains the data needed to display a progress bar
type ProgressBar struct {
total int
progress int
allowOverflow bool
allowUnderflow bool
fullChar rune
emptyChar rune
bordered bool
alignment TextAlignment
x, y int
width, height int
bg, fg termbox.Attribute
}
// CreateProgressBar Create a progress bar object
func CreateProgressBar(tot, x, y int, fg, bg termbox.Attribute) *ProgressBar {
i := ProgressBar{total: tot,
fullChar: '#', emptyChar: ' ',
x: x, y: y, height: 1, width: 10,
bordered: true, fg: fg, bg: bg,
alignment: AlignLeft,
}
return &i
}
// GetProgress returns the curret progress value
func (i *ProgressBar) GetProgress() int {
return i.progress
}
// SetProgress sets the current progress of the bar
func (i *ProgressBar) SetProgress(p int) *ProgressBar {
if (p <= i.total || i.allowOverflow) || (p >= 0 || i.allowUnderflow) {
i.progress = p
}
return i
}
// IncrProgress increments the current progress of the bar
func (i *ProgressBar) IncrProgress() *ProgressBar {
if i.progress < i.total || i.allowOverflow {
i.progress++
}
return i
}
// DecrProgress decrements the current progress of the bar
func (i *ProgressBar) DecrProgress() *ProgressBar {
if i.progress > 0 || i.allowUnderflow {
i.progress--
}
return i
}
// GetPercent returns the percent full of the bar
func (i *ProgressBar) GetPercent() int {
return int(float64(i.progress) / float64(i.total) * 100)
}
// EnableOverflow Tells the progress bar that it can go over the total
func (i *ProgressBar) EnableOverflow() *ProgressBar {
i.allowOverflow = true
return i
}
// DisableOverflow Tells the progress bar that it can NOT go over the total
func (i *ProgressBar) DisableOverflow() *ProgressBar {
i.allowOverflow = false
return i
}
// EnableUnderflow Tells the progress bar that it can go below zero
func (i *ProgressBar) EnableUnderflow() *ProgressBar {
i.allowUnderflow = true
return i
}
// DisableUnderflow Tells the progress bar that it can NOT go below zero
func (i *ProgressBar) DisableUnderflow() *ProgressBar {
i.allowUnderflow = false
return i
}
// GetFullChar returns the rune used for 'full'
func (i *ProgressBar) GetFullChar() rune {
return i.fullChar
}
// SetFullChar sets the rune used for 'full'
func (i *ProgressBar) SetFullChar(f rune) *ProgressBar {
i.fullChar = f
return i
}
// GetEmptyChar gets the rune used for 'empty'
func (i *ProgressBar) GetEmptyChar() rune {
return i.emptyChar
}
// SetEmptyChar sets the rune used for 'empty'
func (i *ProgressBar) SetEmptyChar(f rune) *ProgressBar {
i.emptyChar = f
return i
}
// GetX Return the x position of the Progress Bar
func (i *ProgressBar) GetX() int { return i.x }
// SetX set the x position of the ProgressBar to x
func (i *ProgressBar) SetX(x int) *ProgressBar {
i.x = x
return i
}
// GetY Return the y position of the ProgressBar
func (i *ProgressBar) GetY() int { return i.y }
// SetY Set the y position of the ProgressBar to y
func (i *ProgressBar) SetY(y int) *ProgressBar {
i.y = y
return i
}
// GetHeight returns the height of the progress bar
// Defaults to 1 (3 if bordered)
func (i *ProgressBar) GetHeight() int {
return i.height
}
// SetHeight Sets the height of the progress bar
func (i *ProgressBar) SetHeight(h int) *ProgressBar {
i.height = h
return i
}
// GetWidth returns the width of the progress bar
func (i *ProgressBar) GetWidth() int {
return i.width
}
// SetWidth Sets the width of the progress bar
func (i *ProgressBar) SetWidth(w int) *ProgressBar {
i.width = w
return i
}
// GetBackground Return the current background color of the modal
func (i *ProgressBar) GetBackground() termbox.Attribute { return i.bg }
// SetBackground Set the current background color to bg
func (i *ProgressBar) SetBackground(bg termbox.Attribute) *ProgressBar {
i.bg = bg
return i
}
// GetForeground Return the current foreground color
func (i *ProgressBar) GetForeground() termbox.Attribute { return i.fg }
// SetForeground Set the foreground color to fg
func (i *ProgressBar) SetForeground(fg termbox.Attribute) *ProgressBar {
i.fg = fg
return i
}
// Align Tells which direction the progress bar empties
func (i *ProgressBar) Align(a TextAlignment) *ProgressBar {
i.alignment = a
return i
}
// HandleKeyPress accepts the termbox event and returns whether it was consumed
func (i *ProgressBar) HandleKeyPress(event termbox.Event) bool {
return false
}
// Draw outputs the input field on the screen
func (i *ProgressBar) Draw() {
// For now, just draw a [#### ] bar
// TODO: make this more advanced
drawX, drawY := i.x, i.y
fillWidth, fillHeight := i.width-2, i.height
DrawStringAtPoint("[", drawX, drawY, i.fg, i.bg)
numFull := int(float64(fillWidth) * float64(i.progress) / float64(i.total))
FillWithChar(i.fullChar, drawX+1, drawY, drawX+1+numFull, drawY+(fillHeight-1), i.fg, i.bg)
DrawStringAtPoint("]", drawX+i.width-1, drawY, i.fg, i.bg)
/*
drawX, drawY := i.x, i.y
drawWidth, drawHeight := i.width, i.height
if i.bordered {
if i.height == 1 && i.width > 2 {
// Just using [ & ] for the border
DrawStringAtPoint("[", drawX, drawY, i.fg, i.bg)
DrawStringAtPoint("]", drawX+i.width-1, drawY, i.fg, i.bg)
drawX++
drawWidth -= 2
} else if i.height >= 3 {
DrawBorder(drawX, drawY, drawX+i.width, drawY+i.height, i.fg, i.bg)
drawX++
drawY++
drawWidth -= 2
drawHeight -= 2
}
}
// Figure out how many chars are full
numFull := drawWidth * (i.progress / i.total)
switch i.alignment {
case AlignRight: // TODO: Fill from right to left
case AlignCenter: // TODO: Fill from middle out
default: // Fill from left to right
FillWithChar(i.fullChar, drawX, drawY, drawX+numFull, drawY+(drawHeight-1), i.fg, i.bg)
if numFull < drawWidth {
FillWithChar(i.emptyChar, drawX+numFull, drawY, drawX+drawWidth-1, drawY+(drawHeight-1), i.fg, i.bg)
}
}
*/
}