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:
parent
c19e371390
commit
062c970c0d
1
termbox-test/.gitignore
vendored
Normal file
1
termbox-test/.gitignore
vendored
Normal file
@ -0,0 +1 @@
|
||||
termbox-test
|
@ -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
|
||||
}
|
@ -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 {
|
||||
|
@ -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
|
||||
}
|
||||
|
||||
|
@ -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
190
termbox_dropmenu.go
Normal 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
213
termbox_frame.go
Normal 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])
|
||||
}
|
||||
}
|
@ -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)
|
||||
}
|
||||
}
|
||||
|
@ -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
149
termbox_label.go
Normal 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)
|
||||
}
|
135
termbox_menu.go
135
termbox_menu.go
@ -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)
|
||||
}
|
||||
|
@ -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
|
||||
}
|
||||
|
||||
|
@ -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])
|
||||
}
|
||||
}
|
||||
|
@ -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
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user