1
0
mirror of https://github.com/br0xen/termbox-util.git synced 2024-11-22 05:33:13 +00:00

Syncing Repos

This commit is contained in:
Brian Buller 2016-02-09 10:21:57 -06:00
parent c19e371390
commit 062c970c0d
14 changed files with 1231 additions and 302 deletions

1
termbox-test/.gitignore vendored Normal file
View File

@ -0,0 +1 @@
termbox-test

View File

@ -1,17 +1,21 @@
package main
import (
"fmt"
"github.com/nsf/termbox-go"
"gogs.bullercodeworks.com/brian/termbox-util"
"os"
"strconv"
"syscall"
"gogs.bullercodeworks.com/brian/termbox-util"
"github.com/nsf/termbox-go"
)
var keep_running bool
var keepRunning bool
var initialized bool
var frame *termboxUtil.Frame
func main() {
keep_running = true
keepRunning = true
err := termbox.Init()
if err != nil {
panic(err)
@ -21,82 +25,7 @@ func main() {
mainLoop()
}
//var input *termbox_util.InputField
var input *termbox_util.InputModal
var new_key, new_val string
var mode string
var drawY int
var added_stuff []string
func layoutAndDrawScreen() {
termbox.Clear(0, termbox.ColorBlack)
drawScreen()
termbox.Flush()
}
func drawScreen() {
w, h := termbox.Size()
termbox_util.DrawStringAtPoint(termbox_util.AlignText("Termbox Utility Test", w, termbox_util.ALIGN_CENTER), 0, 0, termbox.ColorWhite, termbox.ColorRed)
if input == nil {
mw, mh := w/4, h/4
mx, my := (w/2)-(mw/2), (h/2)-(mh/2)
input = termbox_util.CreateInputModal("", mx, my, mw, mh, termbox.ColorWhite, termbox.ColorBlack)
input.Clear()
}
if mode == "bucket" {
if input.IsDone() {
added_stuff = append(added_stuff, fmt.Sprintf("New Bucket %s", input.GetValue()))
input.Clear()
mode = ""
} else {
input.Draw()
}
} else if mode == "pair" {
if input.IsDone() {
if new_key == "" {
new_key = input.GetValue()
input.Clear()
input.SetTitle("Pair Value")
} else {
added_stuff = append(added_stuff, fmt.Sprintf("New Pair %s => %s", new_key, input.GetValue()))
mode = ""
input.Clear()
}
}
if mode == "pair" && !input.IsDone() {
input.Draw()
}
}
if mode == "" {
for i := range added_stuff {
termbox_util.DrawStringAtPoint(added_stuff[i], 1, 3+i, termbox.ColorWhite, termbox.ColorRed)
}
}
}
func handleKeyEvent(event termbox.Event) bool {
if event.Key == termbox.KeyEsc {
return false
} else if event.Key == termbox.KeyCtrlB {
mode = "bucket"
new_key = ""
new_val = ""
input.Clear()
input.SetTitle("Bucket Name")
} else if event.Key == termbox.KeyCtrlP {
mode = "pair"
new_key = ""
new_val = ""
input.Clear()
input.SetTitle("Pair Key")
} else {
input.HandleKeyPress(event)
}
return true
}
func mainLoop() {
added_stuff = append(added_stuff, "Ctrl+B = Add Bucket; Ctrl+P = Add Pair")
layoutAndDrawScreen()
for {
event := termbox.PollEvent()
@ -106,9 +35,12 @@ func mainLoop() {
termbox.Close()
process.Signal(syscall.SIGSTOP)
termbox.Init()
} else if event.Key == termbox.KeyCtrlC {
termbox.Close()
os.Exit(0)
}
keep_running = handleKeyEvent(event)
if !keep_running {
keepRunning = handleEvent(event)
if !keepRunning {
break
}
layoutAndDrawScreen()
@ -117,4 +49,70 @@ func mainLoop() {
layoutAndDrawScreen()
}
}
}
func layoutAndDrawScreen() {
w, h := termbox.Size()
if !initialized {
fg, bg := termbox.ColorWhite, termbox.ColorBlack
frame = termboxUtil.CreateFrame(1, 1, w-3, h-3, termbox.ColorWhite, termbox.ColorBlack)
/*
frame.AddControl(termboxUtil.CreateASCIIArt([]string{
"/" + strings.Repeat("=====", 5) + "\\",
"|" + strings.Repeat(".oOo.", 5) + "|",
"\\" + strings.Repeat("=====", 5) + "/",
}, 1, frame.GetBottomY()+1, fg, bg))
frame.AddControl(termboxUtil.CreateAlertModal("AlertModal", 1, 1, w-5, 6, termbox.ColorGreen, bg))
frame.AddControl(termboxUtil.CreateConfirmModal("ConfirmModal", 1, frame.GetBottomY()+1, w-5, 7, fg, bg))
frame.AddControl(termboxUtil.CreateInputModal("InputModal", 1, frame.GetBottomY()+1, w-5, 7, fg, bg))
*/
frame.AddControl(termboxUtil.CreateDropMenu("Add Control", []string{
"AlertModal",
"ASCIIArt",
"ConfirmModal",
"DropMenu",
"Frame",
"InputField",
"InputModal",
"Label",
"Menu",
"ProgressBar",
"ScrollFrame",
},
1, frame.GetBottomY()+1, w-5, 7, fg, bg, termbox.ColorBlack, termbox.ColorGreen))
frame.GetLastControl().SetBordered(true)
frame.SetActiveFlag(true)
initialized = true
}
termbox.Clear(0, termbox.ColorBlack)
drawScreen()
termboxUtil.DrawStringAtPoint(strconv.Itoa(frame.GetBottomY()), 0, h-1, termbox.ColorWhite, termbox.ColorBlack)
termbox.Flush()
}
func drawScreen() {
frame.Draw()
}
func handleEvent(event termbox.Event) bool {
frame.HandleEvent(event)
for _, k := range frame.GetControls() {
switch v := k.(type) {
case *termboxUtil.DropMenu:
if v.IsDone() {
}
case *termboxUtil.AlertModal:
if v.IsDone() {
v.SetText("Finished")
}
case *termboxUtil.ConfirmModal:
if v.IsDone() {
v.SetText("Finished")
}
}
k.SetFgColor(termbox.ColorWhite)
}
frame.GetActiveControl().SetFgColor(termbox.ColorGreen)
return true
}

View File

@ -6,6 +6,7 @@ import (
// AlertModal is a modal with yes/no (or similar) buttons
type AlertModal struct {
id string
title string
text string
x, y, width, height int
@ -16,18 +17,29 @@ type AlertModal struct {
accepted bool
value string
isVisible bool
bordered bool
tabSkip bool
active bool
}
// CreateAlertModal Creates a confirmation modal with the specified attributes
func CreateAlertModal(title string, x, y, width, height int, fg, bg termbox.Attribute) *AlertModal {
i := AlertModal{title: title, x: x, y: y, width: width, height: height, fg: fg, bg: bg}
if i.title == "" && i.text == "" {
i := AlertModal{title: title, x: x, y: y, width: width, height: height, fg: fg, bg: bg, bordered: true}
if i.title == "" {
i.title = "Alert!"
}
i.showHelp = true
return &i
}
// GetID returns this control's ID
func (i *AlertModal) GetID() string { return i.id }
// SetID sets this control's ID
func (i *AlertModal) SetID(newID string) {
i.id = newID
}
// GetTitle returns the current title of the modal
func (i *AlertModal) GetTitle() string { return i.title }
@ -44,38 +56,74 @@ func (i *AlertModal) SetText(s string) {
i.text = s
}
// GetX returns the current x coordinate of the modal
// GetX returns the current x coordinate of the control
func (i *AlertModal) GetX() int { return i.x }
// SetX sets the current x coordinate of the modal to x
// SetX sets the current x coordinate of the control to x
func (i *AlertModal) SetX(x int) {
i.x = x
}
// GetY returns the current y coordinate of the modal
// GetY returns the current y coordinate of the control
func (i *AlertModal) GetY() int { return i.y }
// SetY sets the current y coordinate of the modal to y
// SetY sets the current y coordinate of the control to y
func (i *AlertModal) SetY(y int) {
i.y = y
}
// GetWidth returns the current width of the modal
// GetWidth returns the current width of the control
func (i *AlertModal) GetWidth() int { return i.width }
// SetWidth sets the current modal width to width
// SetWidth sets the current control width to width
func (i *AlertModal) SetWidth(width int) {
i.width = width
}
// GetHeight returns the current height of the modal
// GetHeight returns the current height of the control
func (i *AlertModal) GetHeight() int { return i.height }
// SetHeight set the height of the modal to height
// SetHeight set the height of the control to height
func (i *AlertModal) SetHeight(height int) {
i.height = height
}
// GetFgColor returns the foreground color
func (i *AlertModal) GetFgColor() termbox.Attribute { return i.fg }
// SetFgColor sets the foreground color
func (i *AlertModal) SetFgColor(fg termbox.Attribute) {
i.fg = fg
}
// GetBgColor returns the background color
func (i *AlertModal) GetBgColor() termbox.Attribute { return i.bg }
// SetBgColor sets the current background color
func (i *AlertModal) SetBgColor(bg termbox.Attribute) {
i.bg = bg
}
// IsBordered returns whether this control is bordered or not
func (i *AlertModal) IsBordered() bool {
return i.bordered
}
// SetBordered sets whether we render a border around the frame
func (i *AlertModal) SetBordered(b bool) {
i.bordered = b
}
// IsTabSkipped returns whether this control has it's tabskip flag set
func (i *AlertModal) IsTabSkipped() bool {
return i.tabSkip
}
// SetTabSkip sets the tabskip flag for this control
func (i *AlertModal) SetTabSkip(b bool) {
i.tabSkip = b
}
// HelpIsShown returns true or false if the help is displayed
func (i *AlertModal) HelpIsShown() bool { return i.showHelp }
@ -129,11 +177,21 @@ func (i *AlertModal) Clear() {
i.isDone = false
}
// HandleKeyPress handles the termbox event and returns whether it was consumed
func (i *AlertModal) HandleKeyPress(event termbox.Event) bool {
if event.Key == termbox.KeyEnter {
i.isDone = true
return true
// SetActiveFlag sets this control's active flag
func (i *AlertModal) SetActiveFlag(b bool) {
i.active = b
}
// IsActive returns whether this control is active
func (i *AlertModal) IsActive() bool { return i.active }
// HandleEvent handles the termbox event and returns whether it was consumed
func (i *AlertModal) HandleEvent(event termbox.Event) bool {
if !i.active {
if event.Key == termbox.KeyEnter {
i.isDone = true
return true
}
}
return false
}
@ -155,7 +213,6 @@ func (i *AlertModal) Draw() {
}
if i.text != "" {
DrawStringAtPoint(i.text, i.x+1, nextY, i.fg, i.bg)
nextY++
}
nextY += 2
if i.showHelp {

View File

@ -8,17 +8,37 @@ import (
// ASCIIArt is a []string with more functions
type ASCIIArt struct {
id string
contents []string
x, y int
bg, fg termbox.Attribute
bordered bool
tabSkip bool
active bool
}
// CreateASCIIArt Create an ASCII art object from a string slice
func CreateASCIIArt(c []string, x, y int, fg, bg termbox.Attribute) *ASCIIArt {
i := ASCIIArt{contents: c, x: x, y: y, fg: fg, bg: bg}
i := ASCIIArt{contents: c, x: x, y: y, fg: fg, bg: bg, bordered: false, tabSkip: true}
return &i
}
// SetActiveFlag sets this control's active flag
func (i *ASCIIArt) SetActiveFlag(b bool) {
i.active = b
}
// IsActive returns whether this control is active
func (i *ASCIIArt) IsActive() bool { return i.active }
// GetID returns this control's ID
func (i *ASCIIArt) GetID() string { return i.id }
// SetID sets this control's ID
func (i *ASCIIArt) SetID(newID string) {
i.id = newID
}
// GetX Return the x position of the modal
func (i *ASCIIArt) GetX() int { return i.x }
@ -93,20 +113,20 @@ func (i *ASCIIArt) SetContentLine(s string, idx int) {
}
}
// GetBackground Return the current background color of the modal
func (i *ASCIIArt) GetBackground() termbox.Attribute { return i.bg }
// GetFgColor returns the foreground color
func (i *ASCIIArt) GetFgColor() termbox.Attribute { return i.fg }
// SetBackground Set the current background color to bg
func (i *ASCIIArt) SetBackground(bg termbox.Attribute) {
i.bg = bg
// SetFgColor sets the foreground color
func (i *ASCIIArt) SetFgColor(fg termbox.Attribute) {
i.fg = fg
}
// GetForeground Return the current foreground color
func (i *ASCIIArt) GetForeground() termbox.Attribute { return i.fg }
// GetBgColor returns the background color
func (i *ASCIIArt) GetBgColor() termbox.Attribute { return i.bg }
// SetForeground Set the foreground color to fg
func (i *ASCIIArt) SetForeground(fg termbox.Attribute) {
i.fg = fg
// SetBgColor sets the current background color
func (i *ASCIIArt) SetBgColor(bg termbox.Attribute) {
i.bg = bg
}
// Align Align the Ascii art over width width with alignment a
@ -125,8 +145,28 @@ func (i *ASCIIArt) Align(a TextAlignment, width int) {
i.contents = newContents
}
// HandleKeyPress accepts the termbox event and returns whether it was consumed
func (i *ASCIIArt) HandleKeyPress(event termbox.Event) bool {
// IsBordered returns whether this modal is bordered or not
func (i *ASCIIArt) IsBordered() bool {
return i.bordered
}
// SetBordered sets whether we render a border around the frame
func (i *ASCIIArt) SetBordered(b bool) {
i.bordered = b
}
// IsTabSkipped returns whether this modal has it's tabskip flag set
func (i *ASCIIArt) IsTabSkipped() bool {
return i.tabSkip
}
// SetTabSkip sets the tabskip flag for this control
func (i *ASCIIArt) SetTabSkip(b bool) {
i.tabSkip = b
}
// HandleEvent accepts the termbox event and returns whether it was consumed
func (i *ASCIIArt) HandleEvent(event termbox.Event) bool {
return false
}

View File

@ -6,6 +6,7 @@ import (
// ConfirmModal is a modal with yes/no (or similar) buttons
type ConfirmModal struct {
id string
title string
text string
x, y, width, height int
@ -16,6 +17,9 @@ type ConfirmModal struct {
accepted bool
value string
isVisible bool
bordered bool
tabSkip bool
active bool
}
// CreateConfirmModal Creates a confirmation modal with the specified attributes
@ -28,6 +32,22 @@ func CreateConfirmModal(title string, x, y, width, height int, fg, bg termbox.At
return &i
}
// SetActiveFlag sets this control's active flag
func (i *ConfirmModal) SetActiveFlag(b bool) {
i.active = b
}
// IsActive returns whether this control is active
func (i *ConfirmModal) IsActive() bool { return i.active }
// GetID returns this control's ID
func (i *ConfirmModal) GetID() string { return i.id }
// SetID sets this control's ID
func (i *ConfirmModal) SetID(newID string) {
i.id = newID
}
// GetTitle returns the current title of the modal
func (i *ConfirmModal) GetTitle() string { return i.title }
@ -84,20 +104,20 @@ func (i *ConfirmModal) ShowHelp(b bool) {
i.showHelp = b
}
// GetBackground returns the current background color
func (i *ConfirmModal) GetBackground() termbox.Attribute { return i.bg }
// GetFgColor returns the foreground color
func (i *ConfirmModal) GetFgColor() termbox.Attribute { return i.fg }
// SetBackground sets the background color to bg
func (i *ConfirmModal) SetBackground(bg termbox.Attribute) {
i.bg = bg
// SetFgColor sets the foreground color
func (i *ConfirmModal) SetFgColor(fg termbox.Attribute) {
i.fg = fg
}
// GetForeground returns the current foreground color
func (i *ConfirmModal) GetForeground() termbox.Attribute { return i.fg }
// GetBgColor returns the background color
func (i *ConfirmModal) GetBgColor() termbox.Attribute { return i.bg }
// SetForeground sets the current foreground color to fg
func (i *ConfirmModal) SetForeground(fg termbox.Attribute) {
i.fg = fg
// SetBgColor sets the current background color
func (i *ConfirmModal) SetBgColor(bg termbox.Attribute) {
i.bg = bg
}
// IsDone returns whether the user has answered the modal
@ -129,16 +149,38 @@ func (i *ConfirmModal) Clear() {
i.isDone = false
}
// HandleKeyPress handles the termbox event and returns whether it was consumed
func (i *ConfirmModal) HandleKeyPress(event termbox.Event) bool {
if event.Ch == 'Y' || event.Ch == 'y' {
i.accepted = true
i.isDone = true
return true
} else if event.Ch == 'N' || event.Ch == 'n' {
i.accepted = false
i.isDone = true
return true
// IsBordered returns whether this modal is bordered or not
func (i *ConfirmModal) IsBordered() bool {
return i.bordered
}
// SetBordered sets whether we render a border around the frame
func (i *ConfirmModal) SetBordered(b bool) {
i.bordered = b
}
// IsTabSkipped returns whether this modal has it's tabskip flag set
func (i *ConfirmModal) IsTabSkipped() bool {
return i.tabSkip
}
// SetTabSkip sets the tabskip flag for this control
func (i *ConfirmModal) SetTabSkip(b bool) {
i.tabSkip = b
}
// HandleEvent handles the termbox event and returns whether it was consumed
func (i *ConfirmModal) HandleEvent(event termbox.Event) bool {
if i.active {
if event.Ch == 'Y' || event.Ch == 'y' {
i.accepted = true
i.isDone = true
return true
} else if event.Ch == 'N' || event.Ch == 'n' {
i.accepted = false
i.isDone = true
return true
}
}
return false
}
@ -160,7 +202,6 @@ func (i *ConfirmModal) Draw() {
}
if i.text != "" {
DrawStringAtPoint(i.text, i.x+1, nextY, i.fg, i.bg)
nextY++
}
nextY += 2
if i.showHelp {

190
termbox_dropmenu.go Normal file
View File

@ -0,0 +1,190 @@
package termboxUtil
import "github.com/nsf/termbox-go"
// DropMenu is a title that, when active drops a menu down
type DropMenu struct {
id string
title string
x, y, width, height int
bg, fg termbox.Attribute
selectedBg, selectedFg termbox.Attribute
menu *Menu
menuSelected bool
showMenu bool
bordered bool
tabSkip bool
active bool
}
// CreateDropMenu Creates a menu with the specified attributes
func CreateDropMenu(title string, options []string, x, y, width, height int, fg, bg, selectedFg, selectedBg termbox.Attribute) *DropMenu {
i := DropMenu{
title: title,
x: x, y: y, width: width, height: height,
fg: fg, bg: bg,
selectedFg: fg, selectedBg: bg,
}
i.menu = CreateMenu("", options, x, y+2, width, height, fg, bg)
return &i
}
// GetID returns this control's ID
func (i *DropMenu) GetID() string { return i.id }
// SetID sets this control's ID
func (i *DropMenu) SetID(newID string) {
i.id = newID
}
// GetTitle returns the current title of the menu
func (i *DropMenu) GetTitle() string { return i.title }
// SetTitle sets the current title of the menu to s
func (i *DropMenu) SetTitle(s string) {
i.title = s
}
// GetMenu returns the menu for this dropmenu
func (i *DropMenu) GetMenu() *Menu {
return i.menu
}
// GetX returns the current x coordinate of the menu
func (i *DropMenu) GetX() int { return i.x }
// SetX sets the current x coordinate of the menu to x
func (i *DropMenu) SetX(x int) {
i.x = x
}
// GetY returns the current y coordinate of the menu
func (i *DropMenu) GetY() int { return i.y }
// SetY sets the current y coordinate of the menu to y
func (i *DropMenu) SetY(y int) {
i.y = y
}
// GetWidth returns the current width of the menu
func (i *DropMenu) GetWidth() int { return i.width }
// SetWidth sets the current menu width to width
func (i *DropMenu) SetWidth(width int) {
i.width = width
}
// GetHeight returns the current height of the menu
func (i *DropMenu) GetHeight() int { return i.height }
// SetHeight set the height of the menu to height
func (i *DropMenu) SetHeight(height int) {
i.height = height
}
// GetFgColor returns the foreground color
func (i *DropMenu) GetFgColor() termbox.Attribute { return i.fg }
// SetFgColor sets the foreground color
func (i *DropMenu) SetFgColor(fg termbox.Attribute) {
i.fg = fg
}
// GetBgColor returns the background color
func (i *DropMenu) GetBgColor() termbox.Attribute { return i.bg }
// SetBgColor sets the current background color
func (i *DropMenu) SetBgColor(bg termbox.Attribute) {
i.bg = bg
}
// IsBordered returns the bordered flag
func (i *DropMenu) IsBordered() bool { return i.bordered }
// SetBordered sets the bordered flag
func (i *DropMenu) SetBordered(b bool) {
i.bordered = b
i.menu.SetBordered(b)
}
// IsDone returns whether the user has answered the modal
func (i *DropMenu) IsDone() bool { return i.menu.isDone }
// SetDone sets whether the modal has completed it's purpose
func (i *DropMenu) SetDone(b bool) {
i.menu.isDone = b
}
// IsTabSkipped returns whether this modal has it's tabskip flag set
func (i *DropMenu) IsTabSkipped() bool {
return i.tabSkip
}
// SetTabSkip sets the tabskip flag for this control
func (i *DropMenu) SetTabSkip(b bool) {
i.tabSkip = b
}
// SetActiveFlag sets the dropmenu active flag
func (i *DropMenu) SetActiveFlag(b bool) {
i.active = b
}
// IsActive returns whether the DropMenu is active
func (i *DropMenu) IsActive() bool {
return i.active
}
// ShowMenu tells the menu to draw the options
func (i *DropMenu) ShowMenu() {
i.showMenu = true
i.menuSelected = true
}
// HideMenu tells the menu to hide the options
func (i *DropMenu) HideMenu() {
i.showMenu = false
i.menuSelected = false
}
// HandleEvent handles the termbox event and returns whether it was consumed
func (i *DropMenu) HandleEvent(event termbox.Event) bool {
if i.active {
moveUp := (event.Key == termbox.KeyArrowUp || (i.menu.vimMode && event.Ch == 'k'))
moveDown := (event.Key == termbox.KeyArrowDown || (i.menu.vimMode && event.Ch == 'j'))
if i.menuSelected {
selIdx := i.menu.GetSelectedIndex()
if (moveUp && selIdx == 0) || (moveDown && selIdx == (len(i.menu.options)-1)) {
i.menuSelected = false
} else {
if i.menu.HandleEvent(event) {
if i.menu.IsDone() {
i.HideMenu()
}
return true
}
}
} else {
i.ShowMenu()
return true
}
}
return false
}
// Draw draws the menu
func (i *DropMenu) Draw() {
// The title
ttlFg, ttlBg := i.fg, i.bg
if i.active && !i.menuSelected {
ttlFg, ttlBg = i.selectedFg, i.selectedBg
}
ttlTxt := i.title
if i.showMenu {
ttlTxt = ttlTxt + "-Showing Menu"
}
DrawStringAtPoint(AlignText(i.title, i.width, AlignLeft), i.x, i.y, ttlFg, ttlBg)
if i.showMenu {
i.menu.Draw()
}
}

213
termbox_frame.go Normal file
View File

@ -0,0 +1,213 @@
package termboxUtil
import "github.com/nsf/termbox-go"
// Frame is a frame for holding other elements
// It manages it's own x/y, tab index
type Frame struct {
id string
x, y, width, height int
tabIdx int
fg, bg termbox.Attribute
bordered bool
controls []termboxControl
tabSkip bool
active bool
}
// CreateFrame creates a Frame at x, y that is w by h
func CreateFrame(x, y, w, h int, fg, bg termbox.Attribute) *Frame {
s := Frame{x: x, y: y, width: w, height: h, fg: fg, bg: bg, bordered: true}
return &s
}
// SetActiveFlag sets this control's active flag
func (i *Frame) SetActiveFlag(b bool) {
i.active = b
}
// IsActive returns whether this control is active
func (i *Frame) IsActive() bool { return i.active }
// GetID returns this control's ID
func (i *Frame) GetID() string { return i.id }
// SetID sets this control's ID
func (i *Frame) SetID(newID string) {
i.id = newID
}
// GetX returns the x position of the frame
func (i *Frame) GetX() int { return i.x }
// SetX sets the x position of the frame
func (i *Frame) SetX(x int) {
i.x = x
}
// GetY returns the y position of the frame
func (i *Frame) GetY() int { return i.y }
// SetY sets the y position of the frame
func (i *Frame) SetY(y int) {
i.y = y
}
// GetWidth returns the current width of the frame
func (i *Frame) GetWidth() int { return i.width }
// SetWidth sets the current width of the frame
func (i *Frame) SetWidth(w int) {
i.width = w
}
// GetHeight returns the current height of the frame
func (i *Frame) GetHeight() int { return i.height }
// SetHeight sets the current height of the frame
func (i *Frame) SetHeight(h int) {
i.height = h
}
// GetFgColor returns the foreground color
func (i *Frame) GetFgColor() termbox.Attribute { return i.fg }
// SetFgColor sets the foreground color
func (i *Frame) SetFgColor(fg termbox.Attribute) {
i.fg = fg
}
// GetBgColor returns the background color
func (i *Frame) GetBgColor() termbox.Attribute { return i.bg }
// SetBgColor sets the current background color
func (i *Frame) SetBgColor(bg termbox.Attribute) {
i.bg = bg
}
// IsBordered returns true or false if this frame has a border
func (i *Frame) IsBordered() bool { return i.bordered }
// SetBordered sets whether we render a border around the frame
func (i *Frame) SetBordered(b bool) {
i.bordered = b
}
// IsTabSkipped returns whether this modal has it's tabskip flag set
func (i *Frame) IsTabSkipped() bool {
return i.tabSkip
}
// SetTabSkip sets the tabskip flag for this control
func (i *Frame) SetTabSkip(b bool) {
i.tabSkip = b
}
// AddControl adds a control to the frame
func (i *Frame) AddControl(t termboxControl) {
i.controls = append(i.controls, t)
}
// GetActiveControl returns the control at tabIdx
func (i *Frame) GetActiveControl() termboxControl {
if len(i.controls) >= i.tabIdx {
return i.controls[i.tabIdx]
}
return nil
}
// GetControls returns a slice of all controls
func (i *Frame) GetControls() []termboxControl {
return i.controls
}
// GetControl returns the control at index i
func (i *Frame) GetControl(idx int) termboxControl {
if len(i.controls) >= idx {
return i.controls[idx]
}
return nil
}
// GetControlCount returns the number of controls contained
func (i *Frame) GetControlCount() int {
return len(i.controls)
}
// GetLastControl returns the last control contained
func (i *Frame) GetLastControl() termboxControl {
return i.controls[len(i.controls)-1]
}
// DrawControl figures out the relative position of the control,
// sets it, draws it, then resets it.
func (i *Frame) DrawControl(t termboxControl) {
ctlX, ctlY := t.GetX(), t.GetY()
t.SetX((i.GetX() + ctlX))
t.SetY((i.GetY() + ctlY))
t.Draw()
t.SetX(ctlX)
t.SetY(ctlY)
}
// GetBottomY returns the y of the lowest control in the frame
func (i *Frame) GetBottomY() int {
var ret int
for idx := range i.controls {
if i.controls[idx].GetY()+i.controls[idx].GetHeight() > ret {
ret = i.controls[idx].GetY() + i.controls[idx].GetHeight()
}
}
return ret
}
// HandleEvent accepts the termbox event and returns whether it was consumed
func (i *Frame) HandleEvent(event termbox.Event) bool {
if i.active {
if event.Key == termbox.KeyTab {
i.FindNextTabStop()
return true
}
return i.controls[i.tabIdx].HandleEvent(event)
}
return false
}
// FindNextTabStop finds the next control that can be tabbed to
// A return of true means it found a different one than we started on.
func (i *Frame) FindNextTabStop() bool {
startTab := i.tabIdx
i.tabIdx = (i.tabIdx + 1) % len(i.controls)
for i.controls[i.tabIdx].IsTabSkipped() {
i.tabIdx = (i.tabIdx + 1) % len(i.controls)
if i.tabIdx == startTab {
break
}
}
for idx := range i.controls {
i.controls[idx].SetActiveFlag(idx == i.tabIdx)
}
return i.tabIdx != startTab
}
// Draw outputs the Scoll Frame on the screen
func (i *Frame) Draw() {
maxWidth := i.width
maxHeight := i.height
x, y := i.x, i.y
startX := i.x
startY := i.y
if i.bordered {
FillWithChar(' ', i.x, i.y, i.x+i.width, i.y+i.height, i.fg, i.bg)
DrawBorder(i.x, i.y, i.x+i.width, i.y+i.height, i.fg, i.bg)
maxWidth--
maxHeight--
x++
y++
startX++
startY++
}
for idx := range i.controls {
i.DrawControl(i.controls[idx])
}
}

View File

@ -4,6 +4,7 @@ import "github.com/nsf/termbox-go"
// InputField is a field for inputting text
type InputField struct {
id string
value string
x, y, width, height int
cursor int
@ -11,14 +12,32 @@ type InputField struct {
bordered bool
wrap bool
multiline bool
tabSkip bool
active bool
}
// CreateInputField creates an input field at x, y that is w by h
func CreateInputField(x, y, w, h int, fg, bg termbox.Attribute) *InputField {
i := InputField{x: x, y: y, width: w, height: h, fg: fg, bg: bg}
i := InputField{x: x, y: y, width: w, height: h, fg: fg, bg: bg, active: true}
return &i
}
// SetActiveFlag sets this control's active flag
func (i *InputField) SetActiveFlag(b bool) {
i.active = b
}
// IsActive returns whether this control is active
func (i *InputField) IsActive() bool { return i.active }
// GetID returns this control's ID
func (i *InputField) GetID() string { return i.id }
// SetID sets this control's ID
func (i *InputField) SetID(newID string) {
i.id = newID
}
// GetValue gets the current text that is in the InputField
func (i *InputField) GetValue() string { return i.value }
@ -59,6 +78,22 @@ func (i *InputField) SetHeight(h int) {
i.height = h
}
// GetFgColor returns the foreground color
func (i *InputField) GetFgColor() termbox.Attribute { return i.fg }
// SetFgColor sets the foreground color
func (i *InputField) SetFgColor(fg termbox.Attribute) {
i.fg = fg
}
// GetBgColor returns the background color
func (i *InputField) GetBgColor() termbox.Attribute { return i.bg }
// SetBgColor sets the current background color
func (i *InputField) SetBgColor(bg termbox.Attribute) {
i.bg = bg
}
// IsBordered returns true or false if this input field has a border
func (i *InputField) IsBordered() bool { return i.bordered }
@ -67,6 +102,16 @@ func (i *InputField) SetBordered(b bool) {
i.bordered = b
}
// IsTabSkipped returns whether this modal has it's tabskip flag set
func (i *InputField) IsTabSkipped() bool {
return i.tabSkip
}
// SetTabSkip sets the tabskip flag for this control
func (i *InputField) SetTabSkip(b bool) {
i.tabSkip = b
}
// DoesWrap returns true or false if this input field wraps text
func (i *InputField) DoesWrap() bool { return i.wrap }
@ -83,55 +128,58 @@ func (i *InputField) SetMultiline(b bool) {
i.multiline = b
}
// HandleKeyPress accepts the termbox event and returns whether it was consumed
func (i *InputField) HandleKeyPress(event termbox.Event) bool {
if event.Key == termbox.KeyBackspace || event.Key == termbox.KeyBackspace2 {
if len(i.value) > 0 {
i.value = i.value[:len(i.value)-1]
}
} else if event.Key == termbox.KeyArrowLeft {
if i.cursor+len(i.value) > 0 {
i.cursor--
}
} else if event.Key == termbox.KeyArrowRight {
if i.cursor < 0 {
i.cursor++
}
} else if event.Key == termbox.KeyCtrlU {
// Ctrl+U Clears the Input (before the cursor)
i.value = i.value[i.cursor:]
} else {
// Get the rune to add to our value. Space and Tab are special cases where
// we can't use the event's rune directly
var ch string
switch event.Key {
case termbox.KeySpace:
ch = " "
case termbox.KeyTab:
ch = "\t"
/* Multiline is disabled right now
case termbox.KeyEnter:
if i.multiline {
ch = "\n"
// HandleEvent accepts the termbox event and returns whether it was consumed
func (i *InputField) HandleEvent(event termbox.Event) bool {
if i.active {
if event.Key == termbox.KeyBackspace || event.Key == termbox.KeyBackspace2 {
if len(i.value) > 0 {
i.value = i.value[:len(i.value)-1]
}
} else if event.Key == termbox.KeyArrowLeft {
if i.cursor+len(i.value) > 0 {
i.cursor--
}
} else if event.Key == termbox.KeyArrowRight {
if i.cursor < 0 {
i.cursor++
}
} else if event.Key == termbox.KeyCtrlU {
// Ctrl+U Clears the Input (before the cursor)
i.value = i.value[i.cursor:]
} else {
// Get the rune to add to our value. Space and Tab are special cases where
// we can't use the event's rune directly
var ch string
switch event.Key {
case termbox.KeySpace:
ch = " "
case termbox.KeyTab:
ch = "\t"
/* Multiline is disabled right now
case termbox.KeyEnter:
if i.multiline {
ch = "\n"
}
*/
default:
if KeyIsAlphaNumeric(event) || KeyIsSymbol(event) {
ch = string(event.Ch)
}
*/
default:
if KeyIsAlphaNumeric(event) || KeyIsSymbol(event) {
ch = string(event.Ch)
}
if i.cursor+len(i.value) == 0 {
i.value = string(ch) + i.value
} else if i.cursor == 0 {
i.value = i.value + string(ch)
} else {
strPt1 := i.value[:(len(i.value) + i.cursor)]
strPt2 := i.value[(len(i.value) + i.cursor):]
i.value = strPt1 + string(ch) + strPt2
}
}
if i.cursor+len(i.value) == 0 {
i.value = string(ch) + i.value
} else if i.cursor == 0 {
i.value = i.value + string(ch)
} else {
strPt1 := i.value[:(len(i.value) + i.cursor)]
strPt2 := i.value[(len(i.value) + i.cursor):]
i.value = strPt1 + string(ch) + strPt2
}
return true
}
return true
return false
}
// Draw outputs the input field on the screen
@ -190,7 +238,11 @@ func (i *InputField) Draw() {
y++
x = startX
}
termbox.SetCell(x, y, cursorRune, i.bg, i.fg)
if i.active {
termbox.SetCell(x, y, cursorRune, i.bg, i.fg)
} else {
termbox.SetCell(x, y, cursorRune, i.fg, i.bg)
}
x++
if len(strPt2) > 0 {
lenLeft := maxWidth - len(strPt1) - 1
@ -219,7 +271,11 @@ func (i *InputField) Draw() {
}
}
x, y = DrawStringAtPoint(strPt1, i.x+1, i.y+1, i.fg, i.bg)
termbox.SetCell(x, y, cursorRune, i.bg, i.fg)
if i.active {
termbox.SetCell(x, y, cursorRune, i.bg, i.fg)
} else {
termbox.SetCell(x, y, cursorRune, i.fg, i.bg)
}
DrawStringAtPoint(strPt2, x+1, y, i.fg, i.bg)
}
}

View File

@ -6,6 +6,7 @@ import (
// InputModal A modal for text input
type InputModal struct {
id string
title string
text string
input *InputField
@ -15,18 +16,37 @@ type InputModal struct {
bg, fg termbox.Attribute
isDone bool
isVisible bool
bordered bool
tabSkip bool
active bool
}
// CreateInputModal Create an input modal with the given attributes
func CreateInputModal(title string, x, y, width, height int, fg, bg termbox.Attribute) *InputModal {
i := InputModal{title: title, x: x, y: y, width: width, height: height, fg: fg, bg: bg}
i.input = CreateInputField(i.x+1, i.y+3, i.width-2, 2, i.fg, i.bg)
i := InputModal{title: title, x: x, y: y, width: width, height: height, fg: fg, bg: bg, bordered: true}
i.input = CreateInputField(i.x+2, i.y+3, i.width-2, 2, i.fg, i.bg)
i.showHelp = true
i.input.bordered = true
i.isVisible = true
return &i
}
// SetActiveFlag sets this control's active flag
func (i *InputModal) SetActiveFlag(b bool) {
i.active = b
}
// IsActive returns whether this control is active
func (i *InputModal) IsActive() bool { return i.active }
// GetID returns this control's ID
func (i *InputModal) GetID() string { return i.id }
// SetID sets this control's ID
func (i *InputModal) SetID(newID string) {
i.id = newID
}
// GetTitle Return the title of the modal
func (i *InputModal) GetTitle() string { return i.title }
@ -75,6 +95,26 @@ func (i *InputModal) SetHeight(height int) {
i.height = height
}
// IsBordered returns whether this control is bordered or not
func (i *InputModal) IsBordered() bool {
return i.bordered
}
// SetBordered sets whether we render a border around the frame
func (i *InputModal) SetBordered(b bool) {
i.bordered = b
}
// IsTabSkipped returns whether this control has it's tabskip flag set
func (i *InputModal) IsTabSkipped() bool {
return i.tabSkip
}
// SetTabSkip sets the tabskip flag for this control
func (i *InputModal) SetTabSkip(b bool) {
i.tabSkip = b
}
// HelpIsShown Returns whether the modal is showing it's help text or not
func (i *InputModal) HelpIsShown() bool { return i.showHelp }
@ -83,20 +123,20 @@ func (i *InputModal) ShowHelp(b bool) {
i.showHelp = b
}
// GetBackground Return the current background color of the modal
func (i *InputModal) GetBackground() termbox.Attribute { return i.bg }
// GetFgColor returns the foreground color
func (i *InputModal) GetFgColor() termbox.Attribute { return i.fg }
// SetBackground Set the current background color to bg
func (i *InputModal) SetBackground(bg termbox.Attribute) {
i.bg = bg
// SetFgColor sets the foreground color
func (i *InputModal) SetFgColor(fg termbox.Attribute) {
i.fg = fg
}
// GetForeground Return the current foreground color
func (i *InputModal) GetForeground() termbox.Attribute { return i.fg }
// GetBgColor returns the background color
func (i *InputModal) GetBgColor() termbox.Attribute { return i.bg }
// SetForeground Set the foreground color to fg
func (i *InputModal) SetForeground(fg termbox.Attribute) {
i.fg = fg
// SetBgColor sets the current background color
func (i *InputModal) SetBgColor(bg termbox.Attribute) {
i.bg = bg
}
// Show Sets the visibility flag to true
@ -141,14 +181,17 @@ func (i *InputModal) Clear() {
i.isVisible = false
}
// HandleKeyPress Handle the termbox event, return true if it was consumed
func (i *InputModal) HandleKeyPress(event termbox.Event) bool {
if event.Key == termbox.KeyEnter {
// Done editing
i.isDone = true
return true
// HandleEvent Handle the termbox event, return true if it was consumed
func (i *InputModal) HandleEvent(event termbox.Event) bool {
if i.active {
if event.Key == termbox.KeyEnter {
// Done editing
i.isDone = true
return true
}
return i.input.HandleEvent(event)
}
return i.input.HandleKeyPress(event)
return false
}
// Draw Draw the modal
@ -181,7 +224,9 @@ func (i *InputModal) Draw() {
helpX := (i.x + i.width - len(helpString)) - 1
DrawStringAtPoint(helpString, helpX, nextY, i.fg, i.bg)
}
// Now draw the border
DrawBorder(i.x, i.y, i.x+i.width, i.y+i.height, i.fg, i.bg)
if i.bordered {
// Now draw the border
DrawBorder(i.x, i.y, i.x+i.width, i.y+i.height, i.fg, i.bg)
}
}
}

149
termbox_label.go Normal file
View File

@ -0,0 +1,149 @@
package termboxUtil
import "github.com/nsf/termbox-go"
// Label is a field for inputting text
type Label struct {
id string
value string
x, y, width, height int
cursor int
fg, bg termbox.Attribute
bordered bool
wrap bool
multiline bool
active bool
}
// CreateLabel creates an input field at x, y that is w by h
func CreateLabel(lbl string, x, y, w, h int, fg, bg termbox.Attribute) *Label {
i := Label{value: lbl, x: x, y: y, width: w, height: h, fg: fg, bg: bg}
return &i
}
// SetActiveFlag sets this control's active flag
func (i *Label) SetActiveFlag(b bool) {
i.active = b
}
// IsActive returns whether this control is active
func (i *Label) IsActive() bool { return i.active }
// GetID returns this control's ID
func (i *Label) GetID() string { return i.id }
// SetID sets this control's ID
func (i *Label) SetID(newID string) {
i.id = newID
}
// GetValue gets the current text that is in the Label
func (i *Label) GetValue() string { return i.value }
// SetValue sets the current text in the Label to s
func (i *Label) SetValue(s string) {
i.value = s
}
// GetX returns the x position of the input field
func (i *Label) GetX() int { return i.x }
// SetX sets the x position of the input field
func (i *Label) SetX(x int) {
i.x = x
}
// GetY returns the y position of the input field
func (i *Label) GetY() int { return i.y }
// SetY sets the y position of the input field
func (i *Label) SetY(y int) {
i.y = y
}
// GetWidth returns the current width of the input field
func (i *Label) GetWidth() int {
if i.width == -1 {
if i.bordered {
return len(i.value) + 2
}
return len(i.value)
}
return i.width
}
// SetWidth sets the current width of the input field
func (i *Label) SetWidth(w int) {
i.width = w
}
// GetHeight returns the current height of the input field
func (i *Label) GetHeight() int { return i.height }
// SetHeight sets the current height of the input field
func (i *Label) SetHeight(h int) {
i.height = h
}
// GetFgColor returns the foreground color
func (i *Label) GetFgColor() termbox.Attribute { return i.fg }
// SetFgColor sets the foreground color
func (i *Label) SetFgColor(fg termbox.Attribute) {
i.fg = fg
}
// GetBgColor returns the background color
func (i *Label) GetBgColor() termbox.Attribute { return i.bg }
// SetBgColor sets the current background color
func (i *Label) SetBgColor(bg termbox.Attribute) {
i.bg = bg
}
// IsBordered returns true or false if this input field has a border
func (i *Label) IsBordered() bool { return i.bordered }
// SetBordered sets whether we render a border around the input field
func (i *Label) SetBordered(b bool) {
i.bordered = b
}
// DoesWrap returns true or false if this input field wraps text
func (i *Label) DoesWrap() bool { return i.wrap }
// SetWrap sets whether we wrap the text at width.
func (i *Label) SetWrap(b bool) {
i.wrap = b
}
// IsMultiline returns true or false if this field can have multiple lines
func (i *Label) IsMultiline() bool { return i.multiline }
// SetMultiline sets whether the field can have multiple lines
func (i *Label) SetMultiline(b bool) {
i.multiline = b
}
// HandleEvent accepts the termbox event and returns whether it was consumed
func (i *Label) HandleEvent(event termbox.Event) bool { return false }
// Draw outputs the input field on the screen
func (i *Label) Draw() {
maxWidth := i.width
maxHeight := i.height
x, y := i.x, i.y
startX := i.x
startY := i.y
if i.bordered {
DrawBorder(i.x, i.y, i.x+i.GetWidth(), i.y+i.height, i.fg, i.bg)
maxWidth--
maxHeight--
x++
y++
startX++
startY++
}
DrawStringAtPoint(i.value, x, y, i.fg, i.bg)
}

View File

@ -1,9 +1,14 @@
package termboxUtil
import "github.com/nsf/termbox-go"
import (
"strings"
"github.com/nsf/termbox-go"
)
// Menu is a menu with a list of options
type Menu struct {
id string
title string
options []MenuOption
// If height is -1, then it is adaptive to the menu
@ -16,6 +21,8 @@ type Menu struct {
isDone bool
bordered bool
vimMode bool
tabSkip bool
active bool
}
// CreateMenu Creates a menu with the specified attributes
@ -35,6 +42,14 @@ func CreateMenu(title string, options []string, x, y, width, height int, fg, bg
return &i
}
// GetID returns this control's ID
func (i *Menu) GetID() string { return i.id }
// SetID sets this control's ID
func (i *Menu) SetID(newID string) {
i.id = newID
}
// GetTitle returns the current title of the menu
func (i *Menu) GetTitle() string { return i.title }
@ -193,20 +208,20 @@ func (i *Menu) ShowHelp(b bool) {
i.showHelp = b
}
// GetBackground returns the current background color
func (i *Menu) GetBackground() termbox.Attribute { return i.bg }
// GetFgColor returns the foreground color
func (i *Menu) GetFgColor() termbox.Attribute { return i.fg }
// SetBackground sets the background color to bg
func (i *Menu) SetBackground(bg termbox.Attribute) {
i.bg = bg
// SetFgColor sets the foreground color
func (i *Menu) SetFgColor(fg termbox.Attribute) {
i.fg = fg
}
// GetForeground returns the current foreground color
func (i *Menu) GetForeground() termbox.Attribute { return i.fg }
// GetBgColor returns the background color
func (i *Menu) GetBgColor() termbox.Attribute { return i.bg }
// SetForeground sets the current foreground color to fg
func (i *Menu) SetForeground(fg termbox.Attribute) {
i.fg = fg
// SetBgColor sets the current background color
func (i *Menu) SetBgColor(bg termbox.Attribute) {
i.bg = bg
}
// IsDone returns whether the user has answered the modal
@ -235,29 +250,39 @@ func (i *Menu) DisableVimMode() {
i.vimMode = false
}
// HandleKeyPress handles the termbox event and returns whether it was consumed
func (i *Menu) HandleKeyPress(event termbox.Event) bool {
if event.Key == termbox.KeyEnter || event.Key == termbox.KeySpace {
i.isDone = true
return true
}
currentIdx := i.GetSelectedIndex()
switch event.Key {
case termbox.KeyArrowUp:
i.SelectPrevOption()
case termbox.KeyArrowDown:
i.SelectNextOption()
}
if i.vimMode {
switch event.Ch {
case 'j':
i.SelectNextOption()
case 'k':
i.SelectPrevOption()
// SetActiveFlag sets this control's active flag
func (i *Menu) SetActiveFlag(b bool) {
i.active = b
}
// IsActive returns whether this control is active
func (i *Menu) IsActive() bool { return i.active }
// HandleEvent handles the termbox event and returns whether it was consumed
func (i *Menu) HandleEvent(event termbox.Event) bool {
if i.active {
if event.Key == termbox.KeyEnter || event.Key == termbox.KeySpace {
i.isDone = true
return true
}
currentIdx := i.GetSelectedIndex()
switch event.Key {
case termbox.KeyArrowUp:
i.SelectPrevOption()
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
}
}
if i.GetSelectedIndex() != currentIdx {
return true
}
return false
}
@ -325,16 +350,55 @@ func (i *Menu) Draw() {
}
}
}
i.DrawOptions(optionStartX, optionStartY, optionHeight, optionWidth)
}
// DrawOptions draws the menu options at x, y
func (i *Menu) DrawOptions(x, y, h, w int) {
DrawStringAtPoint(strings.Repeat("-", w), x, y, i.disabledFg, i.disabledBg)
y++
if len(i.options) > 0 {
// If the currently selected option is disabled, move to the next
if i.GetSelectedOption().IsDisabled() {
i.SelectNextOption()
}
// Print the options
for idx := range i.options {
if i.GetSelectedIndex()-idx >= h-1 {
// Skip this one
continue
}
currOpt := &i.options[idx]
outTxt := currOpt.GetText()
if len(outTxt) >= i.width {
outTxt = outTxt[:i.width]
}
if currOpt.IsDisabled() {
DrawStringAtPoint(outTxt, x, y, i.disabledFg, i.disabledBg)
} else if i.GetSelectedOption() == currOpt {
DrawStringAtPoint(AlignText(outTxt, w, AlignLeft), x, y, i.selectedFg, i.selectedBg)
} else {
DrawStringAtPoint(outTxt, x, y, i.fg, i.bg)
}
y++
if y > i.y+h-1 {
break
}
}
}
}
/* MenuOption Struct & methods */
// MenuOption An option in the menu
type MenuOption struct {
id string
text string
selected bool
disabled bool
helpText string
subMenu []MenuOption
}
// CreateOptionFromText just returns a MenuOption object
@ -388,3 +452,8 @@ func (i *MenuOption) SetHelpText(s string) {
// GetHelpText Returns the help text for this option
func (i *MenuOption) GetHelpText() string { return i.helpText }
// AddToSubMenu adds a slice of MenuOptions to this option
func (i *MenuOption) AddToSubMenu(sub *MenuOption) {
i.subMenu = append(i.subMenu, *sub)
}

View File

@ -4,6 +4,7 @@ import "github.com/nsf/termbox-go"
// ProgressBar Just contains the data needed to display a progress bar
type ProgressBar struct {
id string
total int
progress int
allowOverflow bool
@ -17,6 +18,7 @@ type ProgressBar struct {
x, y int
width, height int
bg, fg termbox.Attribute
active bool
}
// CreateProgressBar Create a progress bar object
@ -30,6 +32,22 @@ func CreateProgressBar(tot, x, y int, fg, bg termbox.Attribute) *ProgressBar {
return &i
}
// SetActiveFlag sets this control's active flag
func (i *ProgressBar) SetActiveFlag(b bool) {
i.active = b
}
// IsActive returns whether this control is active
func (i *ProgressBar) IsActive() bool { return i.active }
// GetID returns this control's ID
func (i *ProgressBar) GetID() string { return i.id }
// SetID sets this control's ID
func (i *ProgressBar) SetID(newID string) {
i.id = newID
}
// GetProgress returns the curret progress value
func (i *ProgressBar) GetProgress() int {
return i.progress
@ -138,20 +156,20 @@ func (i *ProgressBar) SetWidth(w int) {
i.width = w
}
// GetBackground Return the current background color of the modal
func (i *ProgressBar) GetBackground() termbox.Attribute { return i.bg }
// GetFgColor returns the foreground color
func (i *ProgressBar) GetFgColor() termbox.Attribute { return i.fg }
// SetBackground Set the current background color to bg
func (i *ProgressBar) SetBackground(bg termbox.Attribute) {
i.bg = bg
// SetFgColor sets the foreground color
func (i *ProgressBar) SetFgColor(fg termbox.Attribute) {
i.fg = fg
}
// GetForeground Return the current foreground color
func (i *ProgressBar) GetForeground() termbox.Attribute { return i.fg }
// GetBgColor returns the background color
func (i *ProgressBar) GetBgColor() termbox.Attribute { return i.bg }
// SetForeground Set the foreground color to fg
func (i *ProgressBar) SetForeground(fg termbox.Attribute) {
i.fg = fg
// SetBgColor sets the current background color
func (i *ProgressBar) SetBgColor(bg termbox.Attribute) {
i.bg = bg
}
// Align Tells which direction the progress bar empties
@ -168,8 +186,8 @@ func (i *ProgressBar) SetColorized(c bool) {
i.colorized = c
}
// HandleKeyPress accepts the termbox event and returns whether it was consumed
func (i *ProgressBar) HandleKeyPress(event termbox.Event) bool {
// HandleEvent accepts the termbox event and returns whether it was consumed
func (i *ProgressBar) HandleEvent(event termbox.Event) bool {
return false
}

View File

@ -5,12 +5,14 @@ import "github.com/nsf/termbox-go"
// ScrollFrame is a frame for holding other elements
// It manages it's own x/y, tab index
type ScrollFrame struct {
id string
x, y, width, height int
scrollX, scrollY int
tabIdx int
fg, bg termbox.Attribute
bordered bool
controls []termboxControl
active bool
}
// CreateScrollFrame creates Scrolling Frame at x, y that is w by h
@ -19,92 +21,124 @@ func CreateScrollFrame(x, y, w, h int, fg, bg termbox.Attribute) *ScrollFrame {
return &s
}
// SetActiveFlag sets this control's active flag
func (i *ScrollFrame) SetActiveFlag(b bool) {
i.active = b
}
// IsActive returns whether this control is active
func (i *ScrollFrame) IsActive() bool { return i.active }
// GetID returns this control's ID
func (i *ScrollFrame) GetID() string { return i.id }
// SetID sets this control's ID
func (i *ScrollFrame) SetID(newID string) {
i.id = newID
}
// GetX returns the x position of the scroll frame
func (s *ScrollFrame) GetX() int { return s.x }
func (i *ScrollFrame) GetX() int { return i.x }
// SetX sets the x position of the scroll frame
func (s *ScrollFrame) SetX(x int) {
s.x = x
func (i *ScrollFrame) SetX(x int) {
i.x = x
}
// GetY returns the y position of the scroll frame
func (s *ScrollFrame) GetY() int { return s.y }
func (i *ScrollFrame) GetY() int { return i.y }
// SetY sets the y position of the scroll frame
func (s *ScrollFrame) SetY(y int) {
s.y = y
func (i *ScrollFrame) SetY(y int) {
i.y = y
}
// GetWidth returns the current width of the scroll frame
func (s *ScrollFrame) GetWidth() int { return s.width }
func (i *ScrollFrame) GetWidth() int { return i.width }
// SetWidth sets the current width of the scroll frame
func (s *ScrollFrame) SetWidth(w int) {
s.width = w
func (i *ScrollFrame) SetWidth(w int) {
i.width = w
}
// GetHeight returns the current height of the scroll frame
func (s *ScrollFrame) GetHeight() int { return s.height }
func (i *ScrollFrame) GetHeight() int { return i.height }
// SetHeight sets the current height of the scroll frame
func (s *ScrollFrame) SetHeight(h int) {
s.height = h
func (i *ScrollFrame) SetHeight(h int) {
i.height = h
}
// GetFgColor returns the foreground color
func (i *ScrollFrame) GetFgColor() termbox.Attribute { return i.fg }
// SetFgColor sets the foreground color
func (i *ScrollFrame) SetFgColor(fg termbox.Attribute) {
i.fg = fg
}
// GetBgColor returns the background color
func (i *ScrollFrame) GetBgColor() termbox.Attribute { return i.bg }
// SetBgColor sets the current background color
func (i *ScrollFrame) SetBgColor(bg termbox.Attribute) {
i.bg = bg
}
// IsBordered returns true or false if this scroll frame has a border
func (s *ScrollFrame) IsBordered() bool { return s.bordered }
func (i *ScrollFrame) IsBordered() bool { return i.bordered }
// SetBordered sets whether we render a border around the scroll frame
func (s *ScrollFrame) SetBordered(b bool) {
s.bordered = b
func (i *ScrollFrame) SetBordered(b bool) {
i.bordered = b
}
// GetScrollX returns the x distance scrolled
func (s *ScrollFrame) GetScrollX() int {
return s.scrollX
func (i *ScrollFrame) GetScrollX() int {
return i.scrollX
}
// GetScrollY returns the y distance scrolled
func (s *ScrollFrame) GetScrollY() int {
return s.scrollY
func (i *ScrollFrame) GetScrollY() int {
return i.scrollY
}
// ScrollDown scrolls the frame down
func (s *ScrollFrame) ScrollDown() {
s.scrollY++
func (i *ScrollFrame) ScrollDown() {
i.scrollY++
}
// ScrollUp scrolls the frame up
func (s *ScrollFrame) ScrollUp() {
if s.scrollY > 0 {
s.scrollY--
func (i *ScrollFrame) ScrollUp() {
if i.scrollY > 0 {
i.scrollY--
}
}
// ScrollLeft scrolls the frame left
func (s *ScrollFrame) ScrollLeft() {
if s.scrollX > 0 {
s.scrollX--
func (i *ScrollFrame) ScrollLeft() {
if i.scrollX > 0 {
i.scrollX--
}
}
// ScrollRight scrolls the frame right
func (s *ScrollFrame) ScrollRight() {
s.scrollX++
func (i *ScrollFrame) ScrollRight() {
i.scrollX++
}
// AddControl adds a control to the frame
func (s *ScrollFrame) AddControl(t termboxControl) {
s.controls = append(s.controls, t)
func (i *ScrollFrame) AddControl(t termboxControl) {
i.controls = append(i.controls, t)
}
// DrawControl figures out the relative position of the control,
// sets it, draws it, then resets it.
func (s *ScrollFrame) DrawControl(t termboxControl) {
if s.IsVisible(t) {
func (i *ScrollFrame) DrawControl(t termboxControl) {
if i.IsVisible(t) {
ctlX, ctlY := t.GetX(), t.GetY()
t.SetX((s.GetX() + ctlX))
t.SetY((s.GetY() + ctlY))
t.SetX((i.GetX() + ctlX))
t.SetY((i.GetY() + ctlY))
t.Draw()
t.SetX(ctlX)
t.SetY(ctlY)
@ -113,35 +147,35 @@ func (s *ScrollFrame) DrawControl(t termboxControl) {
// IsVisible takes a Termbox Control and returns whether
// that control would be visible in the frame
func (s *ScrollFrame) IsVisible(t termboxControl) bool {
func (i *ScrollFrame) IsVisible(t termboxControl) bool {
// Check if any part of t should be visible
cX, cY := t.GetX(), t.GetY()
if cX+t.GetWidth() >= s.scrollX && cX <= s.scrollX+s.width {
return cY+t.GetHeight() >= s.scrollY && cY <= s.scrollY+s.height
if cX+t.GetWidth() >= i.scrollX && cX <= i.scrollX+i.width {
return cY+t.GetHeight() >= i.scrollY && cY <= i.scrollY+i.height
}
return false
}
// HandleKeyPress accepts the termbox event and returns whether it was consumed
func (s *ScrollFrame) HandleKeyPress(event termbox.Event) bool {
// HandleEvent accepts the termbox event and returns whether it was consumed
func (i *ScrollFrame) HandleEvent(event termbox.Event) bool {
return false
}
// DrawToStrings generates a slice of strings with what should
// be drawn to the screen
func (s *ScrollFrame) DrawToStrings() []string {
func (i *ScrollFrame) DrawToStrings() []string {
return []string{}
}
// Draw outputs the Scoll Frame on the screen
func (s *ScrollFrame) Draw() {
maxWidth := s.width
maxHeight := s.height
x, y := s.x, s.y
startX := s.x
startY := s.y
if s.bordered {
DrawBorder(s.x, s.y, s.x+s.width, s.y+s.height, s.fg, s.bg)
func (i *ScrollFrame) Draw() {
maxWidth := i.width
maxHeight := i.height
x, y := i.x, i.y
startX := i.x
startY := i.y
if i.bordered {
DrawBorder(i.x, i.y, i.x+i.width, i.y+i.height, i.fg, i.bg)
maxWidth--
maxHeight--
x++
@ -149,7 +183,7 @@ func (s *ScrollFrame) Draw() {
startX++
startY++
}
for i := range s.controls {
s.DrawControl(s.controls[i])
for idx := range i.controls {
i.DrawControl(i.controls[idx])
}
}

View File

@ -8,6 +8,7 @@ import (
)
type termboxControl interface {
GetID() string
GetX() int
SetX(int)
GetY() int
@ -16,7 +17,17 @@ type termboxControl interface {
SetWidth(int)
GetHeight() int
SetHeight(int)
HandleKeyPress(termbox.Event) bool
GetFgColor() termbox.Attribute
SetFgColor(termbox.Attribute)
GetBgColor() termbox.Attribute
SetBgColor(termbox.Attribute)
HandleEvent(termbox.Event) bool
IsBordered() bool
SetBordered(bool)
SetTabSkip(bool)
IsTabSkipped() bool
IsActive() bool
SetActiveFlag(bool)
Draw()
}
@ -112,21 +123,28 @@ func DrawBorder(x1, y1, x2, y2 int, fg termbox.Attribute, bg termbox.Attribute)
// AlignText Aligns the text txt within width characters using the specified alignment
func AlignText(txt string, width int, align TextAlignment) string {
return AlignTextWithFill(txt, width, align, ' ')
}
// AlignTextWithFill Aligns the text txt within width characters using the specified alignment
// filling any spaces with the 'fill' character
func AlignTextWithFill(txt string, width int, align TextAlignment, fill rune) string {
fillChar := string(fill)
numSpaces := width - len(txt)
switch align {
case AlignCenter:
if numSpaces/2 > 0 {
return fmt.Sprintf("%s%s%s",
strings.Repeat(" ", numSpaces/2),
txt, strings.Repeat(" ", numSpaces/2),
strings.Repeat(fillChar, numSpaces/2),
txt, strings.Repeat(fillChar, numSpaces/2),
)
}
return txt
case AlignRight:
return fmt.Sprintf("%s%s", strings.Repeat(" ", numSpaces), txt)
return fmt.Sprintf("%s%s", strings.Repeat(fillChar, numSpaces), txt)
default:
if numSpaces >= 0 {
return fmt.Sprintf("%s%s", txt, strings.Repeat(" ", numSpaces))
return fmt.Sprintf("%s%s", txt, strings.Repeat(fillChar, numSpaces))
}
return txt
}