mirror of
https://github.com/br0xen/termbox-util.git
synced 2024-11-22 13:33:15 +00:00
Just some stuff
This commit is contained in:
parent
80b1bdea74
commit
c168c0df31
@ -5,7 +5,7 @@ import (
|
|||||||
"strconv"
|
"strconv"
|
||||||
"syscall"
|
"syscall"
|
||||||
|
|
||||||
"gogs.bullercodeworks.com/brian/termbox-util"
|
"github.com/br0xen/termbox-util"
|
||||||
|
|
||||||
"github.com/nsf/termbox-go"
|
"github.com/nsf/termbox-go"
|
||||||
)
|
)
|
||||||
|
@ -13,17 +13,20 @@ type AlertModal struct {
|
|||||||
showHelp bool
|
showHelp bool
|
||||||
cursor int
|
cursor int
|
||||||
bg, fg termbox.Attribute
|
bg, fg termbox.Attribute
|
||||||
|
activeFg, activeBg termbox.Attribute
|
||||||
isDone bool
|
isDone bool
|
||||||
accepted bool
|
accepted bool
|
||||||
value string
|
value string
|
||||||
isVisible bool
|
isVisible bool
|
||||||
bordered bool
|
bordered bool
|
||||||
tabSkip bool
|
tabSkip bool
|
||||||
|
active bool
|
||||||
}
|
}
|
||||||
|
|
||||||
// CreateAlertModal Creates a confirmation modal with the specified attributes
|
// CreateAlertModal Creates a confirmation modal with the specified attributes
|
||||||
func CreateAlertModal(title string, x, y, width, height int, fg, bg termbox.Attribute) *AlertModal {
|
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, bordered: true}
|
i := AlertModal{title: title, x: x, y: y, width: width, height: height, fg: fg, bg: bg, bordered: true}
|
||||||
|
i.activeFg, i.activeBg = fg, bg
|
||||||
if i.title == "" {
|
if i.title == "" {
|
||||||
i.title = "Alert!"
|
i.title = "Alert!"
|
||||||
}
|
}
|
||||||
@ -31,6 +34,11 @@ func CreateAlertModal(title string, x, y, width, height int, fg, bg termbox.Attr
|
|||||||
return &i
|
return &i
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (i *AlertModal) SetActiveFgColor(fg termbox.Attribute) { i.activeFg = fg }
|
||||||
|
func (i *AlertModal) SetActiveBgColor(bg termbox.Attribute) { i.activeBg = bg }
|
||||||
|
func (i *AlertModal) SetActive(a bool) { i.active = a }
|
||||||
|
func (i *AlertModal) IsActive() bool { return i.active }
|
||||||
|
|
||||||
// GetID returns this control's ID
|
// GetID returns this control's ID
|
||||||
func (i *AlertModal) GetID() string { return i.id }
|
func (i *AlertModal) GetID() string { return i.id }
|
||||||
|
|
||||||
|
@ -12,13 +12,16 @@ type ASCIIArt struct {
|
|||||||
contents []string
|
contents []string
|
||||||
x, y int
|
x, y int
|
||||||
bg, fg termbox.Attribute
|
bg, fg termbox.Attribute
|
||||||
|
activeFg, activeBg termbox.Attribute
|
||||||
bordered bool
|
bordered bool
|
||||||
tabSkip bool
|
tabSkip bool
|
||||||
|
active bool
|
||||||
}
|
}
|
||||||
|
|
||||||
// CreateASCIIArt Create an ASCII art object from a string slice
|
// CreateASCIIArt Create an ASCII art object from a string slice
|
||||||
func CreateASCIIArt(c []string, x, y int, fg, bg termbox.Attribute) *ASCIIArt {
|
func CreateASCIIArt(c []string, x, y int, fg, bg termbox.Attribute) *ASCIIArt {
|
||||||
i := ASCIIArt{contents: c, x: x, y: y, fg: fg, bg: bg, bordered: false, tabSkip: true}
|
i := ASCIIArt{contents: c, x: x, y: y, fg: fg, bg: bg, bordered: false, tabSkip: true}
|
||||||
|
i.activeFg, i.activeBg = fg, bg
|
||||||
return &i
|
return &i
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -87,6 +90,11 @@ func (i *ASCIIArt) SetWidth(w int) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (i *ASCIIArt) SetActiveFgColor(fg termbox.Attribute) { i.activeFg = fg }
|
||||||
|
func (i *ASCIIArt) SetActiveBgColor(bg termbox.Attribute) { i.activeBg = bg }
|
||||||
|
func (i *ASCIIArt) SetActive(a bool) { i.active = a }
|
||||||
|
func (i *ASCIIArt) IsActive() bool { return i.active }
|
||||||
|
|
||||||
// SetContents Sets the contents of i to c
|
// SetContents Sets the contents of i to c
|
||||||
func (i *ASCIIArt) SetContents(c []string) {
|
func (i *ASCIIArt) SetContents(c []string) {
|
||||||
i.contents = c
|
i.contents = c
|
||||||
|
59
termbox_button.go
Normal file
59
termbox_button.go
Normal file
@ -0,0 +1,59 @@
|
|||||||
|
package termboxUtil
|
||||||
|
|
||||||
|
import termbox "github.com/nsf/termbox-go"
|
||||||
|
|
||||||
|
type Button struct {
|
||||||
|
id string
|
||||||
|
x, y, width, height int
|
||||||
|
label string
|
||||||
|
fg, bg termbox.Attribute
|
||||||
|
activeFg, activeBg termbox.Attribute
|
||||||
|
bordered bool
|
||||||
|
tabSkip bool
|
||||||
|
active bool
|
||||||
|
}
|
||||||
|
|
||||||
|
func CreateButton(x, y, w, h int, fg, bg termbox.Attribute) *Button {
|
||||||
|
c := Button{
|
||||||
|
x: x, y: y, width: w, height: h,
|
||||||
|
fg: fg, bg: bg, activeFg: bg, activeBg: fg,
|
||||||
|
bordered: true,
|
||||||
|
tabSkip: true,
|
||||||
|
}
|
||||||
|
return &c
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *Button) SetActiveFgColor(fg termbox.Attribute) { c.activeFg = fg }
|
||||||
|
func (c *Button) SetActiveBgColor(bg termbox.Attribute) { c.activeBg = bg }
|
||||||
|
func (c *Button) SetActive(a bool) { c.active = a }
|
||||||
|
func (c *Button) IsActive() bool { return c.active }
|
||||||
|
func (c *Button) GetID() string { return c.id }
|
||||||
|
func (c *Button) SetID(newID string) { c.id = newID }
|
||||||
|
func (c *Button) GetX() int { return c.x }
|
||||||
|
func (c *Button) SetX(x int) { c.x = x }
|
||||||
|
func (c *Button) GetY() int { return c.y }
|
||||||
|
func (c *Button) SetY(y int) { c.y = y }
|
||||||
|
func (c *Button) GetWidth() int { return c.width }
|
||||||
|
func (c *Button) SetWidth(w int) { c.width = w }
|
||||||
|
func (c *Button) GetHeight() int { return c.height }
|
||||||
|
func (c *Button) SetHeight(h int) { c.height = h }
|
||||||
|
func (c *Button) GetFgColor() termbox.Attribute { return c.fg }
|
||||||
|
func (c *Button) SetFgColor(fg termbox.Attribute) { c.fg = fg }
|
||||||
|
func (c *Button) GetBgColor() termbox.Attribute { return c.bg }
|
||||||
|
func (c *Button) SetBgColor(bg termbox.Attribute) { c.bg = bg }
|
||||||
|
func (c *Button) IsBordered() bool { return c.bordered }
|
||||||
|
func (c *Button) SetBordered(bordered bool) { c.bordered = bordered }
|
||||||
|
func (c *Button) SetTabSkip(skip bool) { c.tabSkip = skip }
|
||||||
|
func (c *Button) IsTabSkipped() bool { return c.tabSkip }
|
||||||
|
func (c *Button) HandleEvent(e termbox.Event) bool {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
func (c *Button) Draw() {
|
||||||
|
stX, stY := c.x, c.y
|
||||||
|
if c.bordered {
|
||||||
|
DrawBorder(c.x, c.y, c.x+c.width, c.y+c.height, c.fg, c.bg)
|
||||||
|
stX++
|
||||||
|
stY++
|
||||||
|
}
|
||||||
|
DrawStringAtPoint(c.label, stX, stY, c.fg, c.bg)
|
||||||
|
}
|
@ -12,7 +12,8 @@ type ConfirmModal struct {
|
|||||||
x, y, width, height int
|
x, y, width, height int
|
||||||
showHelp bool
|
showHelp bool
|
||||||
cursor int
|
cursor int
|
||||||
bg, fg termbox.Attribute
|
fg, bg termbox.Attribute
|
||||||
|
activeFg, activeBg termbox.Attribute
|
||||||
isDone bool
|
isDone bool
|
||||||
accepted bool
|
accepted bool
|
||||||
value string
|
value string
|
||||||
@ -23,7 +24,7 @@ type ConfirmModal struct {
|
|||||||
|
|
||||||
// CreateConfirmModal Creates a confirmation modal with the specified attributes
|
// CreateConfirmModal Creates a confirmation modal with the specified attributes
|
||||||
func CreateConfirmModal(title string, x, y, width, height int, fg, bg termbox.Attribute) *ConfirmModal {
|
func CreateConfirmModal(title string, x, y, width, height int, fg, bg termbox.Attribute) *ConfirmModal {
|
||||||
i := ConfirmModal{title: title, x: x, y: y, width: width, height: height, fg: fg, bg: bg}
|
i := ConfirmModal{title: title, x: x, y: y, width: width, height: height, fg: fg, bg: bg, activeFg: fg, activeBg: bg}
|
||||||
if i.title == "" && i.text == "" {
|
if i.title == "" && i.text == "" {
|
||||||
i.title = "Confirm?"
|
i.title = "Confirm?"
|
||||||
}
|
}
|
||||||
|
@ -8,170 +8,177 @@ type DropMenu struct {
|
|||||||
title string
|
title string
|
||||||
x, y, width, height int
|
x, y, width, height int
|
||||||
bg, fg termbox.Attribute
|
bg, fg termbox.Attribute
|
||||||
selectedBg, selectedFg termbox.Attribute
|
activeFg, activeBg termbox.Attribute
|
||||||
|
cursorBg, cursorFg termbox.Attribute
|
||||||
menu *Menu
|
menu *Menu
|
||||||
menuSelected bool
|
menuSelected bool
|
||||||
showMenu bool
|
showMenu bool
|
||||||
bordered bool
|
bordered bool
|
||||||
tabSkip bool
|
tabSkip bool
|
||||||
|
active bool
|
||||||
}
|
}
|
||||||
|
|
||||||
// CreateDropMenu Creates a menu with the specified attributes
|
// 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 {
|
func CreateDropMenu(title string, options []string, x, y, width, height int, fg, bg, cursorFg, cursorBg termbox.Attribute) *DropMenu {
|
||||||
i := DropMenu{
|
c := DropMenu{
|
||||||
title: title,
|
title: title,
|
||||||
x: x, y: y, width: width, height: height,
|
x: x, y: y, width: width, height: height,
|
||||||
fg: fg, bg: bg,
|
fg: fg, bg: bg, activeFg: fg, activeBg: bg,
|
||||||
selectedFg: fg, selectedBg: bg,
|
cursorFg: fg, cursorBg: bg,
|
||||||
}
|
}
|
||||||
i.menu = CreateMenu("", options, x, y+2, width, height, fg, bg)
|
c.menu = CreateMenu("", options, x, y+2, width, height, fg, bg)
|
||||||
return &i
|
return &c
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetID returns this control's ID
|
// GetID returns this control's ID
|
||||||
func (i *DropMenu) GetID() string { return i.id }
|
func (c *DropMenu) GetID() string { return c.id }
|
||||||
|
|
||||||
// SetID sets this control's ID
|
// SetID sets this control's ID
|
||||||
func (i *DropMenu) SetID(newID string) {
|
func (c *DropMenu) SetID(newID string) {
|
||||||
i.id = newID
|
c.id = newID
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (c *DropMenu) SetActiveFgColor(fg termbox.Attribute) { c.activeFg = fg }
|
||||||
|
func (c *DropMenu) SetActiveBgColor(bg termbox.Attribute) { c.activeBg = bg }
|
||||||
|
func (c *DropMenu) SetActive(a bool) { c.active = a }
|
||||||
|
func (c *DropMenu) IsActive() bool { return c.active }
|
||||||
|
|
||||||
// GetTitle returns the current title of the menu
|
// GetTitle returns the current title of the menu
|
||||||
func (i *DropMenu) GetTitle() string { return i.title }
|
func (c *DropMenu) GetTitle() string { return c.title }
|
||||||
|
|
||||||
// SetTitle sets the current title of the menu to s
|
// SetTitle sets the current title of the menu to s
|
||||||
func (i *DropMenu) SetTitle(s string) {
|
func (c *DropMenu) SetTitle(s string) {
|
||||||
i.title = s
|
c.title = s
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetMenu returns the menu for this dropmenu
|
// GetMenu returns the menu for this dropmenu
|
||||||
func (i *DropMenu) GetMenu() *Menu {
|
func (c *DropMenu) GetMenu() *Menu {
|
||||||
return i.menu
|
return c.menu
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetX returns the current x coordinate of the menu
|
// GetX returns the current x coordinate of the menu
|
||||||
func (i *DropMenu) GetX() int { return i.x }
|
func (c *DropMenu) GetX() int { return c.x }
|
||||||
|
|
||||||
// SetX sets the current x coordinate of the menu to x
|
// SetX sets the current x coordinate of the menu to x
|
||||||
func (i *DropMenu) SetX(x int) {
|
func (c *DropMenu) SetX(x int) {
|
||||||
i.x = x
|
c.x = x
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetY returns the current y coordinate of the menu
|
// GetY returns the current y coordinate of the menu
|
||||||
func (i *DropMenu) GetY() int { return i.y }
|
func (c *DropMenu) GetY() int { return c.y }
|
||||||
|
|
||||||
// SetY sets the current y coordinate of the menu to y
|
// SetY sets the current y coordinate of the menu to y
|
||||||
func (i *DropMenu) SetY(y int) {
|
func (c *DropMenu) SetY(y int) {
|
||||||
i.y = y
|
c.y = y
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetWidth returns the current width of the menu
|
// GetWidth returns the current width of the menu
|
||||||
func (i *DropMenu) GetWidth() int { return i.width }
|
func (c *DropMenu) GetWidth() int { return c.width }
|
||||||
|
|
||||||
// SetWidth sets the current menu width to width
|
// SetWidth sets the current menu width to width
|
||||||
func (i *DropMenu) SetWidth(width int) {
|
func (c *DropMenu) SetWidth(width int) {
|
||||||
i.width = width
|
c.width = width
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetHeight returns the current height of the menu
|
// GetHeight returns the current height of the menu
|
||||||
func (i *DropMenu) GetHeight() int { return i.height }
|
func (c *DropMenu) GetHeight() int { return c.height }
|
||||||
|
|
||||||
// SetHeight set the height of the menu to height
|
// SetHeight set the height of the menu to height
|
||||||
func (i *DropMenu) SetHeight(height int) {
|
func (c *DropMenu) SetHeight(height int) {
|
||||||
i.height = height
|
c.height = height
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetFgColor returns the foreground color
|
// GetFgColor returns the foreground color
|
||||||
func (i *DropMenu) GetFgColor() termbox.Attribute { return i.fg }
|
func (c *DropMenu) GetFgColor() termbox.Attribute { return c.fg }
|
||||||
|
|
||||||
// SetFgColor sets the foreground color
|
// SetFgColor sets the foreground color
|
||||||
func (i *DropMenu) SetFgColor(fg termbox.Attribute) {
|
func (c *DropMenu) SetFgColor(fg termbox.Attribute) {
|
||||||
i.fg = fg
|
c.fg = fg
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetBgColor returns the background color
|
// GetBgColor returns the background color
|
||||||
func (i *DropMenu) GetBgColor() termbox.Attribute { return i.bg }
|
func (c *DropMenu) GetBgColor() termbox.Attribute { return c.bg }
|
||||||
|
|
||||||
// SetBgColor sets the current background color
|
// SetBgColor sets the current background color
|
||||||
func (i *DropMenu) SetBgColor(bg termbox.Attribute) {
|
func (c *DropMenu) SetBgColor(bg termbox.Attribute) {
|
||||||
i.bg = bg
|
c.bg = bg
|
||||||
}
|
}
|
||||||
|
|
||||||
// IsBordered returns the bordered flag
|
// IsBordered returns the bordered flag
|
||||||
func (i *DropMenu) IsBordered() bool { return i.bordered }
|
func (c *DropMenu) IsBordered() bool { return c.bordered }
|
||||||
|
|
||||||
// SetBordered sets the bordered flag
|
// SetBordered sets the bordered flag
|
||||||
func (i *DropMenu) SetBordered(b bool) {
|
func (c *DropMenu) SetBordered(b bool) {
|
||||||
i.bordered = b
|
c.bordered = b
|
||||||
i.menu.SetBordered(b)
|
c.menu.SetBordered(b)
|
||||||
}
|
}
|
||||||
|
|
||||||
// IsDone returns whether the user has answered the modal
|
// IsDone returns whether the user has answered the modal
|
||||||
func (i *DropMenu) IsDone() bool { return i.menu.isDone }
|
func (c *DropMenu) IsDone() bool { return c.menu.isDone }
|
||||||
|
|
||||||
// SetDone sets whether the modal has completed it's purpose
|
// SetDone sets whether the modal has completed it's purpose
|
||||||
func (i *DropMenu) SetDone(b bool) {
|
func (c *DropMenu) SetDone(b bool) {
|
||||||
i.menu.isDone = b
|
c.menu.isDone = b
|
||||||
}
|
}
|
||||||
|
|
||||||
// IsTabSkipped returns whether this modal has it's tabskip flag set
|
// IsTabSkipped returns whether this modal has it's tabskip flag set
|
||||||
func (i *DropMenu) IsTabSkipped() bool {
|
func (c *DropMenu) IsTabSkipped() bool {
|
||||||
return i.tabSkip
|
return c.tabSkip
|
||||||
}
|
}
|
||||||
|
|
||||||
// SetTabSkip sets the tabskip flag for this control
|
// SetTabSkip sets the tabskip flag for this control
|
||||||
func (i *DropMenu) SetTabSkip(b bool) {
|
func (c *DropMenu) SetTabSkip(b bool) {
|
||||||
i.tabSkip = b
|
c.tabSkip = b
|
||||||
}
|
}
|
||||||
|
|
||||||
// ShowMenu tells the menu to draw the options
|
// ShowMenu tells the menu to draw the options
|
||||||
func (i *DropMenu) ShowMenu() {
|
func (c *DropMenu) ShowMenu() {
|
||||||
i.showMenu = true
|
c.showMenu = true
|
||||||
i.menuSelected = true
|
c.menuSelected = true
|
||||||
}
|
}
|
||||||
|
|
||||||
// HideMenu tells the menu to hide the options
|
// HideMenu tells the menu to hide the options
|
||||||
func (i *DropMenu) HideMenu() {
|
func (c *DropMenu) HideMenu() {
|
||||||
i.showMenu = false
|
c.showMenu = false
|
||||||
i.menuSelected = false
|
c.menuSelected = false
|
||||||
}
|
}
|
||||||
|
|
||||||
// HandleEvent handles the termbox event and returns whether it was consumed
|
// HandleEvent handles the termbox event and returns whether it was consumed
|
||||||
func (i *DropMenu) HandleEvent(event termbox.Event) bool {
|
func (c *DropMenu) HandleEvent(event termbox.Event) bool {
|
||||||
moveUp := (event.Key == termbox.KeyArrowUp || (i.menu.vimMode && event.Ch == 'k'))
|
moveUp := (event.Key == termbox.KeyArrowUp || (c.menu.vimMode && event.Ch == 'k'))
|
||||||
moveDown := (event.Key == termbox.KeyArrowDown || (i.menu.vimMode && event.Ch == 'j'))
|
moveDown := (event.Key == termbox.KeyArrowDown || (c.menu.vimMode && event.Ch == 'j'))
|
||||||
if i.menuSelected {
|
if c.menuSelected {
|
||||||
selIdx := i.menu.GetSelectedIndex()
|
selIdx := c.menu.GetSelectedIndex()
|
||||||
if (moveUp && selIdx == 0) || (moveDown && selIdx == (len(i.menu.options)-1)) {
|
if (moveUp && selIdx == 0) || (moveDown && selIdx == (len(c.menu.options)-1)) {
|
||||||
i.menuSelected = false
|
c.menuSelected = false
|
||||||
} else {
|
} else {
|
||||||
if i.menu.HandleEvent(event) {
|
if c.menu.HandleEvent(event) {
|
||||||
if i.menu.IsDone() {
|
if c.menu.IsDone() {
|
||||||
i.HideMenu()
|
c.HideMenu()
|
||||||
}
|
}
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
i.ShowMenu()
|
c.ShowMenu()
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
// Draw draws the menu
|
// Draw draws the menu
|
||||||
func (i *DropMenu) Draw() {
|
func (c *DropMenu) Draw() {
|
||||||
// The title
|
// The title
|
||||||
ttlFg, ttlBg := i.fg, i.bg
|
ttlFg, ttlBg := c.fg, c.bg
|
||||||
if !i.menuSelected {
|
if !c.menuSelected {
|
||||||
ttlFg, ttlBg = i.selectedFg, i.selectedBg
|
ttlFg, ttlBg = c.cursorFg, c.cursorBg
|
||||||
}
|
}
|
||||||
ttlTxt := i.title
|
ttlTxt := c.title
|
||||||
if i.showMenu {
|
if c.showMenu {
|
||||||
ttlTxt = ttlTxt + "-Showing Menu"
|
ttlTxt = ttlTxt + "-Showing Menu"
|
||||||
}
|
}
|
||||||
DrawStringAtPoint(AlignText(i.title, i.width, AlignLeft), i.x, i.y, ttlFg, ttlBg)
|
DrawStringAtPoint(AlignText(c.title, c.width, AlignLeft), c.x, c.y, ttlFg, ttlBg)
|
||||||
if i.showMenu {
|
if c.showMenu {
|
||||||
i.menu.Draw()
|
c.menu.Draw()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
218
termbox_frame.go
218
termbox_frame.go
@ -9,187 +9,252 @@ type Frame struct {
|
|||||||
x, y, width, height int
|
x, y, width, height int
|
||||||
tabIdx int
|
tabIdx int
|
||||||
fg, bg termbox.Attribute
|
fg, bg termbox.Attribute
|
||||||
|
activeFg, activeBg termbox.Attribute
|
||||||
bordered bool
|
bordered bool
|
||||||
controls []termboxControl
|
controls []termboxControl
|
||||||
tabSkip bool
|
tabSkip bool
|
||||||
|
active bool
|
||||||
|
title string
|
||||||
}
|
}
|
||||||
|
|
||||||
// CreateFrame creates a Frame at x, y that is w by h
|
// CreateFrame creates a Frame at x, y that is w by h
|
||||||
func CreateFrame(x, y, w, h int, fg, bg termbox.Attribute) *Frame {
|
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}
|
c := Frame{x: x, y: y, width: w, height: h,
|
||||||
return &s
|
fg: fg, bg: bg, activeFg: fg, activeBg: bg,
|
||||||
|
bordered: true,
|
||||||
|
}
|
||||||
|
return &c
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (c *Frame) SetTitle(title string) { c.title = title }
|
||||||
|
|
||||||
|
// Setting color attributes on a frame trickles down to its controls
|
||||||
|
func (c *Frame) SetActiveFgColor(fg termbox.Attribute) {
|
||||||
|
c.activeFg = fg
|
||||||
|
for _, v := range c.controls {
|
||||||
|
v.SetActiveFgColor(fg)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
func (c *Frame) SetActiveBgColor(bg termbox.Attribute) {
|
||||||
|
c.activeBg = bg
|
||||||
|
for _, v := range c.controls {
|
||||||
|
v.SetActiveBgColor(bg)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
func (c *Frame) SetActive(a bool) {
|
||||||
|
c.active = a
|
||||||
|
for idx := range c.controls {
|
||||||
|
if idx == c.tabIdx && a {
|
||||||
|
c.controls[idx].SetActive(true)
|
||||||
|
} else {
|
||||||
|
c.controls[idx].SetActive(false)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
func (c *Frame) IsActive() bool { return c.active }
|
||||||
|
|
||||||
// GetID returns this control's ID
|
// GetID returns this control's ID
|
||||||
func (i *Frame) GetID() string { return i.id }
|
func (c *Frame) GetID() string { return c.id }
|
||||||
|
|
||||||
// SetID sets this control's ID
|
// SetID sets this control's ID
|
||||||
func (i *Frame) SetID(newID string) {
|
func (c *Frame) SetID(newID string) {
|
||||||
i.id = newID
|
c.id = newID
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetX returns the x position of the frame
|
// GetX returns the x position of the frame
|
||||||
func (i *Frame) GetX() int { return i.x }
|
func (c *Frame) GetX() int { return c.x }
|
||||||
|
|
||||||
// SetX sets the x position of the frame
|
// SetX sets the x position of the frame
|
||||||
func (i *Frame) SetX(x int) {
|
func (c *Frame) SetX(x int) {
|
||||||
i.x = x
|
c.x = x
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetY returns the y position of the frame
|
// GetY returns the y position of the frame
|
||||||
func (i *Frame) GetY() int { return i.y }
|
func (c *Frame) GetY() int { return c.y }
|
||||||
|
|
||||||
// SetY sets the y position of the frame
|
// SetY sets the y position of the frame
|
||||||
func (i *Frame) SetY(y int) {
|
func (c *Frame) SetY(y int) {
|
||||||
i.y = y
|
c.y = y
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetWidth returns the current width of the frame
|
// GetWidth returns the current width of the frame
|
||||||
func (i *Frame) GetWidth() int { return i.width }
|
func (c *Frame) GetWidth() int { return c.width }
|
||||||
|
|
||||||
// SetWidth sets the current width of the frame
|
// SetWidth sets the current width of the frame
|
||||||
func (i *Frame) SetWidth(w int) {
|
func (c *Frame) SetWidth(w int) {
|
||||||
i.width = w
|
c.width = w
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetHeight returns the current height of the frame
|
// GetHeight returns the current height of the frame
|
||||||
func (i *Frame) GetHeight() int { return i.height }
|
func (c *Frame) GetHeight() int { return c.height }
|
||||||
|
|
||||||
// SetHeight sets the current height of the frame
|
// SetHeight sets the current height of the frame
|
||||||
func (i *Frame) SetHeight(h int) {
|
func (c *Frame) SetHeight(h int) {
|
||||||
i.height = h
|
c.height = h
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetFgColor returns the foreground color
|
// GetFgColor returns the foreground color
|
||||||
func (i *Frame) GetFgColor() termbox.Attribute { return i.fg }
|
func (c *Frame) GetFgColor() termbox.Attribute { return c.fg }
|
||||||
|
|
||||||
// SetFgColor sets the foreground color
|
// SetFgColor sets the foreground color
|
||||||
func (i *Frame) SetFgColor(fg termbox.Attribute) {
|
func (c *Frame) SetFgColor(fg termbox.Attribute) {
|
||||||
i.fg = fg
|
c.fg = fg
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetBgColor returns the background color
|
// GetBgColor returns the background color
|
||||||
func (i *Frame) GetBgColor() termbox.Attribute { return i.bg }
|
func (c *Frame) GetBgColor() termbox.Attribute { return c.bg }
|
||||||
|
|
||||||
// SetBgColor sets the current background color
|
// SetBgColor sets the current background color
|
||||||
func (i *Frame) SetBgColor(bg termbox.Attribute) {
|
func (c *Frame) SetBgColor(bg termbox.Attribute) {
|
||||||
i.bg = bg
|
c.bg = bg
|
||||||
}
|
}
|
||||||
|
|
||||||
// IsBordered returns true or false if this frame has a border
|
// IsBordered returns true or false if this frame has a border
|
||||||
func (i *Frame) IsBordered() bool { return i.bordered }
|
func (c *Frame) IsBordered() bool { return c.bordered }
|
||||||
|
|
||||||
// SetBordered sets whether we render a border around the frame
|
// SetBordered sets whether we render a border around the frame
|
||||||
func (i *Frame) SetBordered(b bool) {
|
func (c *Frame) SetBordered(b bool) {
|
||||||
i.bordered = b
|
c.bordered = b
|
||||||
}
|
}
|
||||||
|
|
||||||
// IsTabSkipped returns whether this modal has it's tabskip flag set
|
// IsTabSkipped returns whether this modal has it's tabskip flag set
|
||||||
func (i *Frame) IsTabSkipped() bool {
|
func (c *Frame) IsTabSkipped() bool {
|
||||||
return i.tabSkip
|
return c.tabSkip
|
||||||
}
|
}
|
||||||
|
|
||||||
// SetTabSkip sets the tabskip flag for this control
|
// SetTabSkip sets the tabskip flag for this control
|
||||||
func (i *Frame) SetTabSkip(b bool) {
|
func (c *Frame) SetTabSkip(b bool) {
|
||||||
i.tabSkip = b
|
c.tabSkip = b
|
||||||
}
|
}
|
||||||
|
|
||||||
// AddControl adds a control to the frame
|
// AddControl adds a control to the frame
|
||||||
func (i *Frame) AddControl(t termboxControl) {
|
func (c *Frame) AddControl(t termboxControl) {
|
||||||
i.controls = append(i.controls, t)
|
c.controls = append(c.controls, t)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *Frame) ResetTabIndex() {
|
||||||
|
for k, v := range c.controls {
|
||||||
|
if !v.IsTabSkipped() {
|
||||||
|
c.tabIdx = k
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetActiveControl returns the control at tabIdx
|
// GetActiveControl returns the control at tabIdx
|
||||||
func (i *Frame) GetActiveControl() termboxControl {
|
func (c *Frame) GetActiveControl() termboxControl {
|
||||||
if len(i.controls) >= i.tabIdx {
|
if len(c.controls) >= c.tabIdx {
|
||||||
return i.controls[i.tabIdx]
|
if c.controls[c.tabIdx].IsTabSkipped() {
|
||||||
|
c.FindNextTabStop()
|
||||||
|
}
|
||||||
|
return c.controls[c.tabIdx]
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetControls returns a slice of all controls
|
// GetControls returns a slice of all controls
|
||||||
func (i *Frame) GetControls() []termboxControl {
|
func (c *Frame) GetControls() []termboxControl {
|
||||||
return i.controls
|
return c.controls
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetControl returns the control at index i
|
// GetControl returns the control at index i
|
||||||
func (i *Frame) GetControl(idx int) termboxControl {
|
func (c *Frame) GetControl(idx int) termboxControl {
|
||||||
if len(i.controls) >= idx {
|
if len(c.controls) >= idx {
|
||||||
return i.controls[idx]
|
return c.controls[idx]
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetControlCount returns the number of controls contained
|
// GetControlCount returns the number of controls contained
|
||||||
func (i *Frame) GetControlCount() int {
|
func (c *Frame) GetControlCount() int {
|
||||||
return len(i.controls)
|
return len(c.controls)
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetLastControl returns the last control contained
|
// GetLastControl returns the last control contained
|
||||||
func (i *Frame) GetLastControl() termboxControl {
|
func (c *Frame) GetLastControl() termboxControl {
|
||||||
return i.controls[len(i.controls)-1]
|
return c.controls[len(c.controls)-1]
|
||||||
}
|
}
|
||||||
|
|
||||||
// RemoveAllControls clears the control slice
|
// RemoveAllControls clears the control slice
|
||||||
func (i *Frame) RemoveAllControls() {
|
func (c *Frame) RemoveAllControls() {
|
||||||
i.controls = []termboxControl{}
|
c.controls = []termboxControl{}
|
||||||
}
|
}
|
||||||
|
|
||||||
// DrawControl figures out the relative position of the control,
|
// DrawControl figures out the relative position of the control,
|
||||||
// sets it, draws it, then resets it.
|
// sets it, draws it, then resets it.
|
||||||
func (i *Frame) DrawControl(t termboxControl) {
|
func (c *Frame) DrawControl(t termboxControl) {
|
||||||
ctlX, ctlY := t.GetX(), t.GetY()
|
ctlX, ctlY := t.GetX(), t.GetY()
|
||||||
t.SetX((i.GetX() + ctlX))
|
t.SetX((c.GetX() + ctlX))
|
||||||
t.SetY((i.GetY() + ctlY))
|
t.SetY((c.GetY() + ctlY))
|
||||||
t.Draw()
|
t.Draw()
|
||||||
t.SetX(ctlX)
|
t.SetX(ctlX)
|
||||||
t.SetY(ctlY)
|
t.SetY(ctlY)
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetBottomY returns the y of the lowest control in the frame
|
// GetBottomY returns the y of the lowest control in the frame
|
||||||
func (i *Frame) GetBottomY() int {
|
func (c *Frame) GetBottomY() int {
|
||||||
var ret int
|
var ret int
|
||||||
for idx := range i.controls {
|
for idx := range c.controls {
|
||||||
if i.controls[idx].GetY()+i.controls[idx].GetHeight() > ret {
|
if c.controls[idx].GetY()+c.controls[idx].GetHeight() > ret {
|
||||||
ret = i.controls[idx].GetY() + i.controls[idx].GetHeight()
|
ret = c.controls[idx].GetY() + c.controls[idx].GetHeight()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return ret
|
return ret
|
||||||
}
|
}
|
||||||
|
|
||||||
// HandleEvent accepts the termbox event and returns whether it was consumed
|
// HandleEvent accepts the termbox event and returns whether it was consumed
|
||||||
func (i *Frame) HandleEvent(event termbox.Event) bool {
|
func (c *Frame) HandleEvent(event termbox.Event) bool {
|
||||||
if event.Key == termbox.KeyTab {
|
if event.Key == termbox.KeyTab {
|
||||||
i.FindNextTabStop()
|
c.FindNextTabStop()
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
return i.controls[i.tabIdx].HandleEvent(event)
|
return c.controls[c.tabIdx].HandleEvent(event)
|
||||||
}
|
}
|
||||||
|
|
||||||
// FindNextTabStop finds the next control that can be tabbed to
|
// FindNextTabStop finds the next control that can be tabbed to
|
||||||
// A return of true means it found a different one than we started on.
|
// A return of true means it found a different one than we started on.
|
||||||
func (i *Frame) FindNextTabStop() bool {
|
func (c *Frame) FindNextTabStop() bool {
|
||||||
startTab := i.tabIdx
|
startTab := c.tabIdx
|
||||||
i.tabIdx = (i.tabIdx + 1) % len(i.controls)
|
c.tabIdx = (c.tabIdx + 1) % len(c.controls)
|
||||||
for i.controls[i.tabIdx].IsTabSkipped() {
|
for c.controls[c.tabIdx].IsTabSkipped() {
|
||||||
i.tabIdx = (i.tabIdx + 1) % len(i.controls)
|
c.tabIdx = (c.tabIdx + 1) % len(c.controls)
|
||||||
if i.tabIdx == startTab {
|
if c.tabIdx == startTab {
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return i.tabIdx != startTab
|
return c.tabIdx != startTab
|
||||||
|
}
|
||||||
|
|
||||||
|
// IsOnLastControl returns true if the active control
|
||||||
|
// is the last control that isn't tab skippable.
|
||||||
|
func (c *Frame) IsOnLastControl() bool {
|
||||||
|
for _, v := range c.controls[c.tabIdx+1:] {
|
||||||
|
if !v.IsTabSkipped() {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
// Draw outputs the Scoll Frame on the screen
|
// Draw outputs the Scoll Frame on the screen
|
||||||
func (i *Frame) Draw() {
|
func (c *Frame) Draw() {
|
||||||
maxWidth := i.width
|
maxWidth := c.width
|
||||||
maxHeight := i.height
|
maxHeight := c.height
|
||||||
x, y := i.x, i.y
|
x, y := c.x, c.y
|
||||||
startX := i.x
|
startX := c.x
|
||||||
startY := i.y
|
startY := c.y
|
||||||
if i.bordered {
|
borderFg, borderBg := c.fg, c.bg
|
||||||
FillWithChar(' ', i.x, i.y, i.x+i.width, i.y+i.height, i.fg, i.bg)
|
if c.active {
|
||||||
DrawBorder(i.x, i.y, i.x+i.width, i.y+i.height, i.fg, i.bg)
|
borderFg, borderBg = c.activeFg, c.activeBg
|
||||||
|
}
|
||||||
|
if c.bordered {
|
||||||
|
// Clear the framed area
|
||||||
|
FillWithChar(' ', c.x, c.y, c.x+c.width, c.y+c.height, borderFg, borderBg)
|
||||||
|
if c.title == "" {
|
||||||
|
DrawBorder(c.x, c.y, c.x+c.width, c.y+c.height, borderFg, borderBg)
|
||||||
|
} else {
|
||||||
|
DrawBorderWithTitle(c.x, c.y, c.x+c.width, c.y+c.height, " "+c.title+" ", borderFg, borderBg)
|
||||||
|
}
|
||||||
maxWidth--
|
maxWidth--
|
||||||
maxHeight--
|
maxHeight--
|
||||||
x++
|
x++
|
||||||
@ -197,7 +262,12 @@ func (i *Frame) Draw() {
|
|||||||
startX++
|
startX++
|
||||||
startY++
|
startY++
|
||||||
}
|
}
|
||||||
for idx := range i.controls {
|
for idx := range c.controls {
|
||||||
i.DrawControl(i.controls[idx])
|
if idx == c.tabIdx {
|
||||||
|
c.controls[idx].SetActive(true)
|
||||||
|
} else {
|
||||||
|
c.controls[idx].SetActive(false)
|
||||||
|
}
|
||||||
|
c.DrawControl(c.controls[idx])
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -5,153 +5,164 @@ import "github.com/nsf/termbox-go"
|
|||||||
// InputField is a field for inputting text
|
// InputField is a field for inputting text
|
||||||
type InputField struct {
|
type InputField struct {
|
||||||
id string
|
id string
|
||||||
|
title string
|
||||||
value string
|
value string
|
||||||
x, y, width, height int
|
x, y, width, height int
|
||||||
cursor int
|
cursor int
|
||||||
fg, bg termbox.Attribute
|
fg, bg termbox.Attribute
|
||||||
|
activeFg, activeBg termbox.Attribute
|
||||||
cursorFg, cursorBg termbox.Attribute
|
cursorFg, cursorBg termbox.Attribute
|
||||||
bordered bool
|
bordered bool
|
||||||
wrap bool
|
wrap bool
|
||||||
multiline bool
|
multiline bool
|
||||||
tabSkip bool
|
tabSkip bool
|
||||||
|
active bool
|
||||||
}
|
}
|
||||||
|
|
||||||
// CreateInputField creates an input field at x, y that is w by h
|
// 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 {
|
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, cursorFg: bg, cursorBg: fg}
|
c := InputField{x: x, y: y, width: w, height: h,
|
||||||
return &i
|
fg: fg, bg: bg, cursorFg: bg, cursorBg: fg, activeFg: fg, activeBg: bg,
|
||||||
|
}
|
||||||
|
return &c
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (c *InputField) SetTitle(title string) { c.title = title }
|
||||||
|
func (c *InputField) SetActiveFgColor(fg termbox.Attribute) { c.activeFg = fg }
|
||||||
|
func (c *InputField) SetActiveBgColor(bg termbox.Attribute) { c.activeBg = bg }
|
||||||
|
func (c *InputField) SetActive(a bool) { c.active = a }
|
||||||
|
func (c *InputField) IsActive() bool { return c.active }
|
||||||
|
|
||||||
// GetID returns this control's ID
|
// GetID returns this control's ID
|
||||||
func (i *InputField) GetID() string { return i.id }
|
func (c *InputField) GetID() string { return c.id }
|
||||||
|
|
||||||
// SetID sets this control's ID
|
// SetID sets this control's ID
|
||||||
func (i *InputField) SetID(newID string) {
|
func (c *InputField) SetID(newID string) {
|
||||||
i.id = newID
|
c.id = newID
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetValue gets the current text that is in the InputField
|
// GetValue gets the current text that is in the InputField
|
||||||
func (i *InputField) GetValue() string { return i.value }
|
func (c *InputField) GetValue() string { return c.value }
|
||||||
|
|
||||||
// SetValue sets the current text in the InputField to s
|
// SetValue sets the current text in the InputField to s
|
||||||
func (i *InputField) SetValue(s string) {
|
func (c *InputField) SetValue(s string) {
|
||||||
i.value = s
|
c.value = s
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetX returns the x position of the input field
|
// GetX returns the x position of the input field
|
||||||
func (i *InputField) GetX() int { return i.x }
|
func (c *InputField) GetX() int { return c.x }
|
||||||
|
|
||||||
// SetX sets the x position of the input field
|
// SetX sets the x position of the input field
|
||||||
func (i *InputField) SetX(x int) {
|
func (c *InputField) SetX(x int) {
|
||||||
i.x = x
|
c.x = x
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetY returns the y position of the input field
|
// GetY returns the y position of the input field
|
||||||
func (i *InputField) GetY() int { return i.y }
|
func (c *InputField) GetY() int { return c.y }
|
||||||
|
|
||||||
// SetY sets the y position of the input field
|
// SetY sets the y position of the input field
|
||||||
func (i *InputField) SetY(y int) {
|
func (c *InputField) SetY(y int) {
|
||||||
i.y = y
|
c.y = y
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetWidth returns the current width of the input field
|
// GetWidth returns the current width of the input field
|
||||||
func (i *InputField) GetWidth() int { return i.width }
|
func (c *InputField) GetWidth() int { return c.width }
|
||||||
|
|
||||||
// SetWidth sets the current width of the input field
|
// SetWidth sets the current width of the input field
|
||||||
func (i *InputField) SetWidth(w int) {
|
func (c *InputField) SetWidth(w int) {
|
||||||
i.width = w
|
c.width = w
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetHeight returns the current height of the input field
|
// GetHeight returns the current height of the input field
|
||||||
func (i *InputField) GetHeight() int { return i.height }
|
func (c *InputField) GetHeight() int { return c.height }
|
||||||
|
|
||||||
// SetHeight sets the current height of the input field
|
// SetHeight sets the current height of the input field
|
||||||
func (i *InputField) SetHeight(h int) {
|
func (c *InputField) SetHeight(h int) {
|
||||||
i.height = h
|
c.height = h
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetFgColor returns the foreground color
|
// GetFgColor returns the foreground color
|
||||||
func (i *InputField) GetFgColor() termbox.Attribute { return i.fg }
|
func (c *InputField) GetFgColor() termbox.Attribute { return c.fg }
|
||||||
|
|
||||||
// SetFgColor sets the foreground color
|
// SetFgColor sets the foreground color
|
||||||
func (i *InputField) SetFgColor(fg termbox.Attribute) {
|
func (c *InputField) SetFgColor(fg termbox.Attribute) {
|
||||||
i.fg = fg
|
c.fg = fg
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetBgColor returns the background color
|
// GetBgColor returns the background color
|
||||||
func (i *InputField) GetBgColor() termbox.Attribute { return i.bg }
|
func (c *InputField) GetBgColor() termbox.Attribute { return c.bg }
|
||||||
|
|
||||||
// SetBgColor sets the current background color
|
// SetBgColor sets the current background color
|
||||||
func (i *InputField) SetBgColor(bg termbox.Attribute) {
|
func (c *InputField) SetBgColor(bg termbox.Attribute) {
|
||||||
i.bg = bg
|
c.bg = bg
|
||||||
}
|
}
|
||||||
|
|
||||||
func (i *InputField) SetCursorFg(fg termbox.Attribute) {
|
func (c *InputField) SetCursorFg(fg termbox.Attribute) {
|
||||||
i.cursorFg = fg
|
c.cursorFg = fg
|
||||||
}
|
}
|
||||||
func (i *InputField) GetCursorFg() termbox.Attribute { return i.cursorFg }
|
func (c *InputField) GetCursorFg() termbox.Attribute { return c.cursorFg }
|
||||||
|
|
||||||
func (i *InputField) SetCursorBg(bg termbox.Attribute) {
|
func (c *InputField) SetCursorBg(bg termbox.Attribute) {
|
||||||
i.cursorBg = bg
|
c.cursorBg = bg
|
||||||
}
|
}
|
||||||
func (i *InputField) GetCursorBg() termbox.Attribute { return i.cursorBg }
|
func (c *InputField) GetCursorBg() termbox.Attribute { return c.cursorBg }
|
||||||
|
|
||||||
// IsBordered returns true or false if this input field has a border
|
// IsBordered returns true or false if this input field has a border
|
||||||
func (i *InputField) IsBordered() bool { return i.bordered }
|
func (c *InputField) IsBordered() bool { return c.bordered }
|
||||||
|
|
||||||
// SetBordered sets whether we render a border around the input field
|
// SetBordered sets whether we render a border around the input field
|
||||||
func (i *InputField) SetBordered(b bool) {
|
func (c *InputField) SetBordered(b bool) {
|
||||||
i.bordered = b
|
c.bordered = b
|
||||||
}
|
}
|
||||||
|
|
||||||
// IsTabSkipped returns whether this modal has it's tabskip flag set
|
// IsTabSkipped returns whether this modal has it's tabskip flag set
|
||||||
func (i *InputField) IsTabSkipped() bool {
|
func (c *InputField) IsTabSkipped() bool {
|
||||||
return i.tabSkip
|
return c.tabSkip
|
||||||
}
|
}
|
||||||
|
|
||||||
// SetTabSkip sets the tabskip flag for this control
|
// SetTabSkip sets the tabskip flag for this control
|
||||||
func (i *InputField) SetTabSkip(b bool) {
|
func (c *InputField) SetTabSkip(b bool) {
|
||||||
i.tabSkip = b
|
c.tabSkip = b
|
||||||
}
|
}
|
||||||
|
|
||||||
// DoesWrap returns true or false if this input field wraps text
|
// DoesWrap returns true or false if this input field wraps text
|
||||||
func (i *InputField) DoesWrap() bool { return i.wrap }
|
func (c *InputField) DoesWrap() bool { return c.wrap }
|
||||||
|
|
||||||
// SetWrap sets whether we wrap the text at width.
|
// SetWrap sets whether we wrap the text at width.
|
||||||
func (i *InputField) SetWrap(b bool) {
|
func (c *InputField) SetWrap(b bool) {
|
||||||
i.wrap = b
|
c.wrap = b
|
||||||
}
|
}
|
||||||
|
|
||||||
// IsMultiline returns true or false if this field can have multiple lines
|
// IsMultiline returns true or false if this field can have multiple lines
|
||||||
func (i *InputField) IsMultiline() bool { return i.multiline }
|
func (c *InputField) IsMultiline() bool { return c.multiline }
|
||||||
|
|
||||||
// SetMultiline sets whether the field can have multiple lines
|
// SetMultiline sets whether the field can have multiple lines
|
||||||
func (i *InputField) SetMultiline(b bool) {
|
func (c *InputField) SetMultiline(b bool) {
|
||||||
i.multiline = b
|
c.multiline = b
|
||||||
}
|
}
|
||||||
|
|
||||||
// HandleEvent accepts the termbox event and returns whether it was consumed
|
// HandleEvent accepts the termbox event and returns whether it was consumed
|
||||||
func (i *InputField) HandleEvent(event termbox.Event) bool {
|
func (c *InputField) HandleEvent(event termbox.Event) bool {
|
||||||
if event.Key == termbox.KeyBackspace || event.Key == termbox.KeyBackspace2 {
|
if event.Key == termbox.KeyBackspace || event.Key == termbox.KeyBackspace2 {
|
||||||
if i.cursor+len(i.value) > 0 {
|
if c.cursor+len(c.value) > 0 {
|
||||||
crs := len(i.value)
|
crs := len(c.value)
|
||||||
if i.cursor < 0 {
|
if c.cursor < 0 {
|
||||||
crs = i.cursor + len(i.value)
|
crs = c.cursor + len(c.value)
|
||||||
}
|
}
|
||||||
i.value = i.value[:crs-1] + i.value[crs:]
|
c.value = c.value[:crs-1] + c.value[crs:]
|
||||||
//i.value = i.value[:len(i.value)-1]
|
//c.value = c.value[:len(c.value)-1]
|
||||||
}
|
}
|
||||||
} else if event.Key == termbox.KeyArrowLeft {
|
} else if event.Key == termbox.KeyArrowLeft {
|
||||||
if i.cursor+len(i.value) > 0 {
|
if c.cursor+len(c.value) > 0 {
|
||||||
i.cursor--
|
c.cursor--
|
||||||
}
|
}
|
||||||
} else if event.Key == termbox.KeyArrowRight {
|
} else if event.Key == termbox.KeyArrowRight {
|
||||||
if i.cursor < 0 {
|
if c.cursor < 0 {
|
||||||
i.cursor++
|
c.cursor++
|
||||||
}
|
}
|
||||||
} else if event.Key == termbox.KeyCtrlU {
|
} else if event.Key == termbox.KeyCtrlU {
|
||||||
// Ctrl+U Clears the Input (before the cursor)
|
// Ctrl+U Clears the Input (before the cursor)
|
||||||
i.value = i.value[i.cursor+len(i.value):]
|
c.value = c.value[c.cursor+len(c.value):]
|
||||||
} else {
|
} else {
|
||||||
// Get the rune to add to our value. Space and Tab are special cases where
|
// Get the rune to add to our value. Space and Tab are special cases where
|
||||||
// we can't use the event's rune directly
|
// we can't use the event's rune directly
|
||||||
@ -162,7 +173,7 @@ func (i *InputField) HandleEvent(event termbox.Event) bool {
|
|||||||
case termbox.KeyTab:
|
case termbox.KeyTab:
|
||||||
ch = "\t"
|
ch = "\t"
|
||||||
case termbox.KeyEnter:
|
case termbox.KeyEnter:
|
||||||
if i.multiline {
|
if c.multiline {
|
||||||
ch = "\n"
|
ch = "\n"
|
||||||
}
|
}
|
||||||
default:
|
default:
|
||||||
@ -172,28 +183,32 @@ func (i *InputField) HandleEvent(event termbox.Event) bool {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// TODO: Handle newlines
|
// TODO: Handle newlines
|
||||||
if i.cursor+len(i.value) == 0 {
|
if c.cursor+len(c.value) == 0 {
|
||||||
i.value = string(ch) + i.value
|
c.value = string(ch) + c.value
|
||||||
} else if i.cursor == 0 {
|
} else if c.cursor == 0 {
|
||||||
i.value = i.value + string(ch)
|
c.value = c.value + string(ch)
|
||||||
} else {
|
} else {
|
||||||
strPt1 := i.value[:(len(i.value) + i.cursor)]
|
strPt1 := c.value[:(len(c.value) + c.cursor)]
|
||||||
strPt2 := i.value[(len(i.value) + i.cursor):]
|
strPt2 := c.value[(len(c.value) + c.cursor):]
|
||||||
i.value = strPt1 + string(ch) + strPt2
|
c.value = strPt1 + string(ch) + strPt2
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
// Draw outputs the input field on the screen
|
// Draw outputs the input field on the screen
|
||||||
func (i *InputField) Draw() {
|
func (c *InputField) Draw() {
|
||||||
maxWidth := i.width
|
maxWidth := c.width
|
||||||
maxHeight := i.height
|
maxHeight := c.height
|
||||||
x, y := i.x, i.y
|
x, y := c.x, c.y
|
||||||
startX := i.x
|
startX := c.x
|
||||||
startY := i.y
|
startY := c.y
|
||||||
if i.bordered {
|
useFg, useBg := c.fg, c.bg
|
||||||
DrawBorder(i.x, i.y, i.x+i.width, i.y+i.height, i.fg, i.bg)
|
if c.active {
|
||||||
|
useFg, useBg = c.activeFg, c.activeBg
|
||||||
|
}
|
||||||
|
if c.bordered {
|
||||||
|
DrawBorder(c.x, c.y, c.x+c.width, c.y+c.height, useFg, useBg)
|
||||||
maxWidth--
|
maxWidth--
|
||||||
maxHeight--
|
maxHeight--
|
||||||
x++
|
x++
|
||||||
@ -204,53 +219,60 @@ func (i *InputField) Draw() {
|
|||||||
|
|
||||||
var strPt1, strPt2 string
|
var strPt1, strPt2 string
|
||||||
var cursorRune rune
|
var cursorRune rune
|
||||||
if len(i.value) > 0 {
|
if len(c.value) > 0 {
|
||||||
if i.cursor+len(i.value) == 0 {
|
if c.cursor+len(c.value) == 0 {
|
||||||
strPt1 = ""
|
strPt1 = ""
|
||||||
strPt2 = i.value[1:]
|
strPt2 = c.value[1:]
|
||||||
cursorRune = rune(i.value[0])
|
cursorRune = rune(c.value[0])
|
||||||
} else if i.cursor == 0 {
|
} else if c.cursor == 0 {
|
||||||
strPt1 = i.value
|
strPt1 = c.value
|
||||||
strPt2 = ""
|
strPt2 = ""
|
||||||
cursorRune = ' '
|
cursorRune = ' '
|
||||||
} else {
|
} else {
|
||||||
strPt1 = i.value[:(len(i.value) + i.cursor)]
|
strPt1 = c.value[:(len(c.value) + c.cursor)]
|
||||||
strPt2 = i.value[(len(i.value)+i.cursor)+1:]
|
strPt2 = c.value[(len(c.value)+c.cursor)+1:]
|
||||||
cursorRune = rune(i.value[len(i.value)+i.cursor])
|
cursorRune = rune(c.value[len(c.value)+c.cursor])
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
strPt1, strPt2, cursorRune = "", "", ' '
|
strPt1, strPt2, cursorRune = "", "", ' '
|
||||||
}
|
}
|
||||||
if i.wrap {
|
if c.title != "" {
|
||||||
|
if c.active {
|
||||||
|
DrawStringAtPoint(c.title, x, y, c.activeFg, c.activeBg)
|
||||||
|
} else {
|
||||||
|
DrawStringAtPoint(c.title, x, y, useFg, useBg)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if c.wrap {
|
||||||
// Split the text into maxWidth chunks
|
// Split the text into maxWidth chunks
|
||||||
for len(strPt1) > maxWidth {
|
for len(strPt1) > maxWidth {
|
||||||
breakAt := maxWidth
|
breakAt := maxWidth
|
||||||
DrawStringAtPoint(strPt1[:breakAt], x, y, i.fg, i.bg)
|
DrawStringAtPoint(strPt1[:breakAt], x, y, useFg, useBg)
|
||||||
x = startX
|
x = startX
|
||||||
y++
|
y++
|
||||||
strPt1 = strPt1[breakAt:]
|
strPt1 = strPt1[breakAt:]
|
||||||
}
|
}
|
||||||
x, y = DrawStringAtPoint(strPt1, x, y, i.fg, i.bg)
|
x, y = DrawStringAtPoint(strPt1, x, y, useFg, useBg)
|
||||||
if x >= maxWidth {
|
if x >= maxWidth {
|
||||||
y++
|
y++
|
||||||
x = startX
|
x = startX
|
||||||
}
|
}
|
||||||
termbox.SetCell(x, y, cursorRune, i.cursorFg, i.cursorBg)
|
termbox.SetCell(x, y, cursorRune, c.cursorFg, c.cursorBg)
|
||||||
x++
|
x++
|
||||||
if len(strPt2) > 0 {
|
if len(strPt2) > 0 {
|
||||||
lenLeft := maxWidth - len(strPt1) - 1
|
lenLeft := maxWidth - len(strPt1) - 1
|
||||||
if lenLeft > 0 && len(strPt2) > lenLeft {
|
if lenLeft > 0 && len(strPt2) > lenLeft {
|
||||||
DrawStringAtPoint(strPt2[:lenLeft], x+1, y, i.fg, i.bg)
|
DrawStringAtPoint(strPt2[:lenLeft], x+1, y, useFg, useBg)
|
||||||
strPt2 = strPt2[lenLeft:]
|
strPt2 = strPt2[lenLeft:]
|
||||||
}
|
}
|
||||||
for len(strPt2) > maxWidth {
|
for len(strPt2) > maxWidth {
|
||||||
breakAt := maxWidth
|
breakAt := maxWidth
|
||||||
DrawStringAtPoint(strPt2[:breakAt], x, y, i.fg, i.bg)
|
DrawStringAtPoint(strPt2[:breakAt], x, y, useFg, useBg)
|
||||||
x = startX
|
x = startX
|
||||||
y++
|
y++
|
||||||
strPt2 = strPt2[breakAt:]
|
strPt2 = strPt2[breakAt:]
|
||||||
}
|
}
|
||||||
x, y = DrawStringAtPoint(strPt2, x, y, i.fg, i.bg)
|
x, y = DrawStringAtPoint(strPt2, x, y, useFg, useBg)
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
for len(strPt1)+len(strPt2)+1 > maxWidth {
|
for len(strPt1)+len(strPt2)+1 > maxWidth {
|
||||||
@ -263,8 +285,12 @@ func (i *InputField) Draw() {
|
|||||||
strPt2 = strPt2[:len(strPt2)-1]
|
strPt2 = strPt2[:len(strPt2)-1]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
x, y = DrawStringAtPoint(strPt1, i.x+1, i.y+1, i.fg, i.bg)
|
x, y = DrawStringAtPoint(strPt1, c.x+len(c.title), c.y, useFg, useBg)
|
||||||
termbox.SetCell(x, y, cursorRune, i.cursorFg, i.cursorBg)
|
if c.active {
|
||||||
DrawStringAtPoint(strPt2, x+1, y, i.fg, i.bg)
|
termbox.SetCell(x, y, cursorRune, c.cursorFg, c.cursorBg)
|
||||||
|
} else {
|
||||||
|
termbox.SetCell(x, y, cursorRune, useFg, useBg)
|
||||||
|
}
|
||||||
|
DrawStringAtPoint(strPt2, x+1, y, useFg, useBg)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -14,244 +14,251 @@ type InputModal struct {
|
|||||||
showHelp bool
|
showHelp bool
|
||||||
cursor int
|
cursor int
|
||||||
bg, fg termbox.Attribute
|
bg, fg termbox.Attribute
|
||||||
|
activeFg, activeBg termbox.Attribute
|
||||||
isDone bool
|
isDone bool
|
||||||
isAccepted bool
|
isAccepted bool
|
||||||
isVisible bool
|
isVisible bool
|
||||||
bordered bool
|
bordered bool
|
||||||
tabSkip bool
|
tabSkip bool
|
||||||
inputSelected bool
|
inputSelected bool
|
||||||
|
active bool
|
||||||
}
|
}
|
||||||
|
|
||||||
// CreateInputModal Create an input modal with the given attributes
|
// CreateInputModal Create an input modal with the given attributes
|
||||||
func CreateInputModal(title string, x, y, width, height int, fg, bg termbox.Attribute) *InputModal {
|
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, bordered: true}
|
c := 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)
|
c.input = CreateInputField(c.x+2, c.y+3, c.width-2, 2, c.fg, c.bg)
|
||||||
i.showHelp = true
|
c.showHelp = true
|
||||||
i.input.bordered = true
|
c.input.bordered = true
|
||||||
i.isVisible = true
|
c.isVisible = true
|
||||||
i.inputSelected = true
|
c.inputSelected = true
|
||||||
return &i
|
return &c
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (c *InputModal) SetActiveFgColor(fg termbox.Attribute) { c.activeFg = fg }
|
||||||
|
func (c *InputModal) SetActiveBgColor(bg termbox.Attribute) { c.activeBg = bg }
|
||||||
|
func (c *InputModal) SetActive(a bool) { c.active = a }
|
||||||
|
func (c *InputModal) IsActive() bool { return c.active }
|
||||||
|
|
||||||
// GetID returns this control's ID
|
// GetID returns this control's ID
|
||||||
func (i *InputModal) GetID() string { return i.id }
|
func (c *InputModal) GetID() string { return c.id }
|
||||||
|
|
||||||
// SetID sets this control's ID
|
// SetID sets this control's ID
|
||||||
func (i *InputModal) SetID(newID string) {
|
func (c *InputModal) SetID(newID string) {
|
||||||
i.id = newID
|
c.id = newID
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetTitle Return the title of the modal
|
// GetTitle Return the title of the modal
|
||||||
func (i *InputModal) GetTitle() string { return i.title }
|
func (c *InputModal) GetTitle() string { return c.title }
|
||||||
|
|
||||||
// SetTitle Sets the title of the modal to s
|
// SetTitle Sets the title of the modal to s
|
||||||
func (i *InputModal) SetTitle(s string) {
|
func (c *InputModal) SetTitle(s string) {
|
||||||
i.title = s
|
c.title = s
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetText Return the text of the modal
|
// GetText Return the text of the modal
|
||||||
func (i *InputModal) GetText() string { return i.text }
|
func (c *InputModal) GetText() string { return c.text }
|
||||||
|
|
||||||
// SetText Set the text of the modal to s
|
// SetText Set the text of the modal to s
|
||||||
func (i *InputModal) SetText(s string) {
|
func (c *InputModal) SetText(s string) {
|
||||||
i.text = s
|
c.text = s
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetX Return the x position of the modal
|
// GetX Return the x position of the modal
|
||||||
func (i *InputModal) GetX() int { return i.x }
|
func (c *InputModal) GetX() int { return c.x }
|
||||||
|
|
||||||
// SetX set the x position of the modal to x
|
// SetX set the x position of the modal to x
|
||||||
func (i *InputModal) SetX(x int) {
|
func (c *InputModal) SetX(x int) {
|
||||||
i.x = x
|
c.x = x
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetY Return the y position of the modal
|
// GetY Return the y position of the modal
|
||||||
func (i *InputModal) GetY() int { return i.y }
|
func (c *InputModal) GetY() int { return c.y }
|
||||||
|
|
||||||
// SetY Set the y position of the modal to y
|
// SetY Set the y position of the modal to y
|
||||||
func (i *InputModal) SetY(y int) {
|
func (c *InputModal) SetY(y int) {
|
||||||
i.y = y
|
c.y = y
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetWidth Return the width of the modal
|
// GetWidth Return the width of the modal
|
||||||
func (i *InputModal) GetWidth() int { return i.width }
|
func (c *InputModal) GetWidth() int { return c.width }
|
||||||
|
|
||||||
// SetWidth Set the width of the modal to width
|
// SetWidth Set the width of the modal to width
|
||||||
func (i *InputModal) SetWidth(width int) {
|
func (c *InputModal) SetWidth(width int) {
|
||||||
i.width = width
|
c.width = width
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetHeight Return the height of the modal
|
// GetHeight Return the height of the modal
|
||||||
func (i *InputModal) GetHeight() int { return i.height }
|
func (c *InputModal) GetHeight() int { return c.height }
|
||||||
|
|
||||||
// SetHeight Set the height of the modal to height
|
// SetHeight Set the height of the modal to height
|
||||||
func (i *InputModal) SetHeight(height int) {
|
func (c *InputModal) SetHeight(height int) {
|
||||||
i.height = height
|
c.height = height
|
||||||
}
|
}
|
||||||
|
|
||||||
// SetMultiline returns whether this is a multiline modal
|
// SetMultiline returns whether this is a multiline modal
|
||||||
func (i *InputModal) SetMultiline(m bool) {
|
func (c *InputModal) SetMultiline(m bool) {
|
||||||
i.input.multiline = m
|
c.input.multiline = m
|
||||||
}
|
}
|
||||||
|
|
||||||
// IsMultiline returns whether this is a multiline modal
|
// IsMultiline returns whether this is a multiline modal
|
||||||
func (i *InputModal) IsMultiline() bool {
|
func (c *InputModal) IsMultiline() bool {
|
||||||
return i.input.multiline
|
return c.input.multiline
|
||||||
}
|
}
|
||||||
|
|
||||||
// IsBordered returns whether this control is bordered or not
|
// IsBordered returns whether this control is bordered or not
|
||||||
func (i *InputModal) IsBordered() bool {
|
func (c *InputModal) IsBordered() bool {
|
||||||
return i.bordered
|
return c.bordered
|
||||||
}
|
}
|
||||||
|
|
||||||
// SetBordered sets whether we render a border around the frame
|
// SetBordered sets whether we render a border around the frame
|
||||||
func (i *InputModal) SetBordered(b bool) {
|
func (c *InputModal) SetBordered(b bool) {
|
||||||
i.bordered = b
|
c.bordered = b
|
||||||
}
|
}
|
||||||
|
|
||||||
// IsTabSkipped returns whether this control has it's tabskip flag set
|
// IsTabSkipped returns whether this control has it's tabskip flag set
|
||||||
func (i *InputModal) IsTabSkipped() bool {
|
func (c *InputModal) IsTabSkipped() bool {
|
||||||
return i.tabSkip
|
return c.tabSkip
|
||||||
}
|
}
|
||||||
|
|
||||||
// SetTabSkip sets the tabskip flag for this control
|
// SetTabSkip sets the tabskip flag for this control
|
||||||
func (i *InputModal) SetTabSkip(b bool) {
|
func (c *InputModal) SetTabSkip(b bool) {
|
||||||
i.tabSkip = b
|
c.tabSkip = b
|
||||||
}
|
}
|
||||||
|
|
||||||
// HelpIsShown Returns whether the modal is showing it's help text or not
|
// HelpIsShown Returns whether the modal is showing it's help text or not
|
||||||
func (i *InputModal) HelpIsShown() bool { return i.showHelp }
|
func (c *InputModal) HelpIsShown() bool { return c.showHelp }
|
||||||
|
|
||||||
// ShowHelp Set the "Show Help" flag
|
// ShowHelp Set the "Show Help" flag
|
||||||
func (i *InputModal) ShowHelp(b bool) {
|
func (c *InputModal) ShowHelp(b bool) {
|
||||||
i.showHelp = b
|
c.showHelp = b
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetFgColor returns the foreground color
|
// GetFgColor returns the foreground color
|
||||||
func (i *InputModal) GetFgColor() termbox.Attribute { return i.fg }
|
func (c *InputModal) GetFgColor() termbox.Attribute { return c.fg }
|
||||||
|
|
||||||
// SetFgColor sets the foreground color
|
// SetFgColor sets the foreground color
|
||||||
func (i *InputModal) SetFgColor(fg termbox.Attribute) {
|
func (c *InputModal) SetFgColor(fg termbox.Attribute) {
|
||||||
i.fg = fg
|
c.fg = fg
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetBgColor returns the background color
|
// GetBgColor returns the background color
|
||||||
func (i *InputModal) GetBgColor() termbox.Attribute { return i.bg }
|
func (c *InputModal) GetBgColor() termbox.Attribute { return c.bg }
|
||||||
|
|
||||||
// SetBgColor sets the current background color
|
// SetBgColor sets the current background color
|
||||||
func (i *InputModal) SetBgColor(bg termbox.Attribute) {
|
func (c *InputModal) SetBgColor(bg termbox.Attribute) {
|
||||||
i.bg = bg
|
c.bg = bg
|
||||||
}
|
}
|
||||||
|
|
||||||
// Show Sets the visibility flag to true
|
// Show Sets the visibility flag to true
|
||||||
func (i *InputModal) Show() {
|
func (c *InputModal) Show() {
|
||||||
i.isVisible = true
|
c.isVisible = true
|
||||||
}
|
}
|
||||||
|
|
||||||
// Hide Sets the visibility flag to false
|
// Hide Sets the visibility flag to false
|
||||||
func (i *InputModal) Hide() {
|
func (c *InputModal) Hide() {
|
||||||
i.isVisible = false
|
c.isVisible = false
|
||||||
}
|
}
|
||||||
|
|
||||||
// IsVisible returns the isVisible flag
|
// IsVisible returns the isVisible flag
|
||||||
func (i *InputModal) IsVisible() bool {
|
func (c *InputModal) IsVisible() bool {
|
||||||
return i.isVisible
|
return c.isVisible
|
||||||
}
|
}
|
||||||
|
|
||||||
// SetDone Sets the flag that tells whether this modal has completed it's purpose
|
// SetDone Sets the flag that tells whether this modal has completed it's purpose
|
||||||
func (i *InputModal) SetDone(b bool) {
|
func (c *InputModal) SetDone(b bool) {
|
||||||
i.isDone = b
|
c.isDone = b
|
||||||
}
|
}
|
||||||
|
|
||||||
// IsDone Returns the "isDone" flag
|
// IsDone Returns the "isDone" flag
|
||||||
func (i *InputModal) IsDone() bool {
|
func (c *InputModal) IsDone() bool {
|
||||||
return i.isDone
|
return c.isDone
|
||||||
}
|
}
|
||||||
|
|
||||||
// IsAccepted Returns whether the modal has been accepted
|
// IsAccepted Returns whether the modal has been accepted
|
||||||
func (i *InputModal) IsAccepted() bool {
|
func (c *InputModal) IsAccepted() bool {
|
||||||
return i.isAccepted
|
return c.isAccepted
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetValue Return the current value of the input
|
// GetValue Return the current value of the input
|
||||||
func (i *InputModal) GetValue() string { return i.input.GetValue() }
|
func (c *InputModal) GetValue() string { return c.input.GetValue() }
|
||||||
|
|
||||||
// SetValue Sets the value of the input to s
|
// SetValue Sets the value of the input to s
|
||||||
func (i *InputModal) SetValue(s string) {
|
func (c *InputModal) SetValue(s string) {
|
||||||
i.input.SetValue(s)
|
c.input.SetValue(s)
|
||||||
}
|
}
|
||||||
|
|
||||||
// SetInputWrap sets whether the input field will wrap long text or not
|
// SetInputWrap sets whether the input field will wrap long text or not
|
||||||
func (i *InputModal) SetInputWrap(b bool) {
|
func (c *InputModal) SetInputWrap(b bool) {
|
||||||
i.input.SetWrap(b)
|
c.input.SetWrap(b)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Clear Resets all non-positional parameters of the modal
|
// Clear Resets all non-positional parameters of the modal
|
||||||
func (i *InputModal) Clear() {
|
func (c *InputModal) Clear() {
|
||||||
i.title = ""
|
c.title = ""
|
||||||
i.text = ""
|
c.text = ""
|
||||||
i.input.SetValue("")
|
c.input.SetValue("")
|
||||||
i.isDone = false
|
c.isDone = false
|
||||||
i.isVisible = false
|
c.isVisible = false
|
||||||
}
|
}
|
||||||
|
|
||||||
// HandleEvent Handle the termbox event, return true if it was consumed
|
// HandleEvent Handle the termbox event, return true if it was consumed
|
||||||
func (i *InputModal) HandleEvent(event termbox.Event) bool {
|
func (c *InputModal) HandleEvent(event termbox.Event) bool {
|
||||||
if event.Key == termbox.KeyEnter {
|
if event.Key == termbox.KeyEnter {
|
||||||
if !i.input.IsMultiline() || !i.inputSelected {
|
if !c.input.IsMultiline() || !c.inputSelected {
|
||||||
// Done editing
|
// Done editing
|
||||||
i.isDone = true
|
c.isDone = true
|
||||||
i.isAccepted = true
|
c.isAccepted = true
|
||||||
} else {
|
} else {
|
||||||
i.input.HandleEvent(event)
|
c.input.HandleEvent(event)
|
||||||
}
|
}
|
||||||
return true
|
return true
|
||||||
} else if event.Key == termbox.KeyTab {
|
} else if event.Key == termbox.KeyTab {
|
||||||
if i.input.IsMultiline() {
|
if c.input.IsMultiline() {
|
||||||
i.inputSelected = !i.inputSelected
|
c.inputSelected = !c.inputSelected
|
||||||
}
|
}
|
||||||
} else if event.Key == termbox.KeyEsc {
|
} else if event.Key == termbox.KeyEsc {
|
||||||
// Done editing
|
// Done editing
|
||||||
i.isDone = true
|
c.isDone = true
|
||||||
i.isAccepted = false
|
c.isAccepted = false
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
return i.input.HandleEvent(event)
|
return c.input.HandleEvent(event)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Draw Draw the modal
|
// Draw Draw the modal
|
||||||
func (i *InputModal) Draw() {
|
func (c *InputModal) Draw() {
|
||||||
if i.isVisible {
|
if c.isVisible {
|
||||||
// First blank out the area we'll be putting the modal
|
// First blank out the area we'll be putting the modal
|
||||||
FillWithChar(' ', i.x, i.y, i.x+i.width, i.y+i.height, i.fg, i.bg)
|
FillWithChar(' ', c.x, c.y, c.x+c.width, c.y+c.height, c.fg, c.bg)
|
||||||
nextY := i.y + 1
|
nextY := c.y + 1
|
||||||
// The title
|
// The title
|
||||||
if i.title != "" {
|
if c.title != "" {
|
||||||
if len(i.title) > i.width {
|
if len(c.title) > c.width {
|
||||||
diff := i.width - len(i.title)
|
diff := c.width - len(c.title)
|
||||||
DrawStringAtPoint(i.title[:len(i.title)+diff-1], i.x+1, nextY, i.fg, i.bg)
|
DrawStringAtPoint(c.title[:len(c.title)+diff-1], c.x+1, nextY, c.fg, c.bg)
|
||||||
} else {
|
} else {
|
||||||
DrawStringAtPoint(i.title, i.x+1, nextY, i.fg, i.bg)
|
DrawStringAtPoint(c.title, c.x+1, nextY, c.fg, c.bg)
|
||||||
}
|
}
|
||||||
nextY++
|
nextY++
|
||||||
FillWithChar('-', i.x+1, nextY, i.x+i.width-1, nextY, i.fg, i.bg)
|
FillWithChar('-', c.x+1, nextY, c.x+c.width-1, nextY, c.fg, c.bg)
|
||||||
nextY++
|
nextY++
|
||||||
}
|
}
|
||||||
if i.text != "" {
|
if c.text != "" {
|
||||||
DrawStringAtPoint(i.text, i.x+1, nextY, i.fg, i.bg)
|
DrawStringAtPoint(c.text, c.x+1, nextY, c.fg, c.bg)
|
||||||
nextY++
|
nextY++
|
||||||
}
|
}
|
||||||
i.input.SetY(nextY)
|
c.input.SetY(nextY)
|
||||||
i.input.Draw()
|
c.input.Draw()
|
||||||
nextY += 3
|
nextY += 3
|
||||||
if i.showHelp {
|
if c.showHelp {
|
||||||
helpString := " (ENTER) to Accept. (ESC) to Cancel. "
|
helpString := " (ENTER) to Accept. (ESC) to Cancel. "
|
||||||
helpX := (i.x + i.width - len(helpString)) - 1
|
helpX := (c.x + c.width - len(helpString)) - 1
|
||||||
DrawStringAtPoint(helpString, helpX, nextY, i.fg, i.bg)
|
DrawStringAtPoint(helpString, helpX, nextY, c.fg, c.bg)
|
||||||
}
|
}
|
||||||
if i.bordered {
|
if c.bordered {
|
||||||
// Now draw the border
|
// Now draw the border
|
||||||
DrawBorder(i.x, i.y, i.x+i.width, i.y+i.height, i.fg, i.bg)
|
DrawBorder(c.x, c.y, c.x+c.width, c.y+c.height, c.fg, c.bg)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
116
termbox_label.go
116
termbox_label.go
@ -9,133 +9,133 @@ type Label struct {
|
|||||||
x, y, width, height int
|
x, y, width, height int
|
||||||
cursor int
|
cursor int
|
||||||
fg, bg termbox.Attribute
|
fg, bg termbox.Attribute
|
||||||
|
activeFg, activeBg termbox.Attribute
|
||||||
bordered bool
|
bordered bool
|
||||||
wrap bool
|
wrap bool
|
||||||
multiline bool
|
multiline bool
|
||||||
|
active bool
|
||||||
}
|
}
|
||||||
|
|
||||||
// CreateLabel creates an input field at x, y that is w by h
|
// 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 {
|
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}
|
c := Label{
|
||||||
return &i
|
value: lbl, x: x, y: y, width: w, height: h,
|
||||||
|
fg: fg, bg: bg, activeFg: fg, activeBg: bg,
|
||||||
|
}
|
||||||
|
return &c
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (c *Label) SetActiveFgColor(fg termbox.Attribute) { c.activeFg = fg }
|
||||||
|
func (c *Label) SetActiveBgColor(bg termbox.Attribute) { c.activeBg = bg }
|
||||||
|
func (c *Label) SetActive(a bool) { c.active = a }
|
||||||
|
func (c *Label) IsActive() bool { return c.active }
|
||||||
|
|
||||||
// IsTabSkipped is always true for a label
|
// IsTabSkipped is always true for a label
|
||||||
func (i *Label) IsTabSkipped() bool {
|
func (c *Label) IsTabSkipped() bool { return true }
|
||||||
return true
|
|
||||||
}
|
|
||||||
|
|
||||||
// This doesn't do anything for a label
|
// This doesn't do anything for a label
|
||||||
func (i *Label) SetTabSkip(b bool) {}
|
func (c *Label) SetTabSkip(b bool) {}
|
||||||
|
|
||||||
// GetID returns this control's ID
|
// GetID returns this control's ID
|
||||||
func (i *Label) GetID() string { return i.id }
|
func (c *Label) GetID() string { return c.id }
|
||||||
|
|
||||||
// SetID sets this control's ID
|
// SetID sets this control's ID
|
||||||
func (i *Label) SetID(newID string) {
|
func (c *Label) SetID(newID string) { c.id = newID }
|
||||||
i.id = newID
|
|
||||||
}
|
|
||||||
|
|
||||||
// GetValue gets the current text that is in the Label
|
// GetValue gets the current text that is in the Label
|
||||||
func (i *Label) GetValue() string { return i.value }
|
func (c *Label) GetValue() string { return c.value }
|
||||||
|
|
||||||
// SetValue sets the current text in the Label to s
|
// SetValue sets the current text in the Label to s
|
||||||
func (i *Label) SetValue(s string) {
|
func (c *Label) SetValue(s string) { c.value = s }
|
||||||
i.value = s
|
|
||||||
}
|
|
||||||
|
|
||||||
// GetX returns the x position of the input field
|
// GetX returns the x position of the input field
|
||||||
func (i *Label) GetX() int { return i.x }
|
func (c *Label) GetX() int { return c.x }
|
||||||
|
|
||||||
// SetX sets the x position of the input field
|
// SetX sets the x position of the input field
|
||||||
func (i *Label) SetX(x int) {
|
func (c *Label) SetX(x int) { c.x = x }
|
||||||
i.x = x
|
|
||||||
}
|
|
||||||
|
|
||||||
// GetY returns the y position of the input field
|
// GetY returns the y position of the input field
|
||||||
func (i *Label) GetY() int { return i.y }
|
func (c *Label) GetY() int { return c.y }
|
||||||
|
|
||||||
// SetY sets the y position of the input field
|
// SetY sets the y position of the input field
|
||||||
func (i *Label) SetY(y int) {
|
func (c *Label) SetY(y int) { c.y = y }
|
||||||
i.y = y
|
|
||||||
}
|
|
||||||
|
|
||||||
// GetWidth returns the current width of the input field
|
// GetWidth returns the current width of the input field
|
||||||
func (i *Label) GetWidth() int {
|
func (c *Label) GetWidth() int {
|
||||||
if i.width == -1 {
|
if c.width == -1 {
|
||||||
if i.bordered {
|
if c.bordered {
|
||||||
return len(i.value) + 2
|
return len(c.value) + 2
|
||||||
}
|
}
|
||||||
return len(i.value)
|
return len(c.value)
|
||||||
}
|
}
|
||||||
return i.width
|
return c.width
|
||||||
}
|
}
|
||||||
|
|
||||||
// SetWidth sets the current width of the input field
|
// SetWidth sets the current width of the input field
|
||||||
func (i *Label) SetWidth(w int) {
|
func (c *Label) SetWidth(w int) {
|
||||||
i.width = w
|
c.width = w
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetHeight returns the current height of the input field
|
// GetHeight returns the current height of the input field
|
||||||
func (i *Label) GetHeight() int { return i.height }
|
func (c *Label) GetHeight() int { return c.height }
|
||||||
|
|
||||||
// SetHeight sets the current height of the input field
|
// SetHeight sets the current height of the input field
|
||||||
func (i *Label) SetHeight(h int) {
|
func (c *Label) SetHeight(h int) {
|
||||||
i.height = h
|
c.height = h
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetFgColor returns the foreground color
|
// GetFgColor returns the foreground color
|
||||||
func (i *Label) GetFgColor() termbox.Attribute { return i.fg }
|
func (c *Label) GetFgColor() termbox.Attribute { return c.fg }
|
||||||
|
|
||||||
// SetFgColor sets the foreground color
|
// SetFgColor sets the foreground color
|
||||||
func (i *Label) SetFgColor(fg termbox.Attribute) {
|
func (c *Label) SetFgColor(fg termbox.Attribute) {
|
||||||
i.fg = fg
|
c.fg = fg
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetBgColor returns the background color
|
// GetBgColor returns the background color
|
||||||
func (i *Label) GetBgColor() termbox.Attribute { return i.bg }
|
func (c *Label) GetBgColor() termbox.Attribute { return c.bg }
|
||||||
|
|
||||||
// SetBgColor sets the current background color
|
// SetBgColor sets the current background color
|
||||||
func (i *Label) SetBgColor(bg termbox.Attribute) {
|
func (c *Label) SetBgColor(bg termbox.Attribute) {
|
||||||
i.bg = bg
|
c.bg = bg
|
||||||
}
|
}
|
||||||
|
|
||||||
// IsBordered returns true or false if this input field has a border
|
// IsBordered returns true or false if this input field has a border
|
||||||
func (i *Label) IsBordered() bool { return i.bordered }
|
func (c *Label) IsBordered() bool { return c.bordered }
|
||||||
|
|
||||||
// SetBordered sets whether we render a border around the input field
|
// SetBordered sets whether we render a border around the input field
|
||||||
func (i *Label) SetBordered(b bool) {
|
func (c *Label) SetBordered(b bool) {
|
||||||
i.bordered = b
|
c.bordered = b
|
||||||
}
|
}
|
||||||
|
|
||||||
// DoesWrap returns true or false if this input field wraps text
|
// DoesWrap returns true or false if this input field wraps text
|
||||||
func (i *Label) DoesWrap() bool { return i.wrap }
|
func (c *Label) DoesWrap() bool { return c.wrap }
|
||||||
|
|
||||||
// SetWrap sets whether we wrap the text at width.
|
// SetWrap sets whether we wrap the text at width.
|
||||||
func (i *Label) SetWrap(b bool) {
|
func (c *Label) SetWrap(b bool) {
|
||||||
i.wrap = b
|
c.wrap = b
|
||||||
}
|
}
|
||||||
|
|
||||||
// IsMultiline returns true or false if this field can have multiple lines
|
// IsMultiline returns true or false if this field can have multiple lines
|
||||||
func (i *Label) IsMultiline() bool { return i.multiline }
|
func (c *Label) IsMultiline() bool { return c.multiline }
|
||||||
|
|
||||||
// SetMultiline sets whether the field can have multiple lines
|
// SetMultiline sets whether the field can have multiple lines
|
||||||
func (i *Label) SetMultiline(b bool) {
|
func (c *Label) SetMultiline(b bool) {
|
||||||
i.multiline = b
|
c.multiline = b
|
||||||
}
|
}
|
||||||
|
|
||||||
// HandleEvent accepts the termbox event and returns whether it was consumed
|
// HandleEvent accepts the termbox event and returns whether it was consumed
|
||||||
func (i *Label) HandleEvent(event termbox.Event) bool { return false }
|
func (c *Label) HandleEvent(event termbox.Event) bool { return false }
|
||||||
|
|
||||||
// Draw outputs the input field on the screen
|
// Draw outputs the input field on the screen
|
||||||
func (i *Label) Draw() {
|
func (c *Label) Draw() {
|
||||||
maxWidth := i.width
|
maxWidth := c.width
|
||||||
maxHeight := i.height
|
maxHeight := c.height
|
||||||
x, y := i.x, i.y
|
x, y := c.x, c.y
|
||||||
startX := i.x
|
startX := c.x
|
||||||
startY := i.y
|
startY := c.y
|
||||||
if i.bordered {
|
if c.bordered {
|
||||||
DrawBorder(i.x, i.y, i.x+i.GetWidth(), i.y+i.height, i.fg, i.bg)
|
DrawBorder(c.x, c.y, c.x+c.GetWidth(), c.y+c.height, c.fg, c.bg)
|
||||||
maxWidth--
|
maxWidth--
|
||||||
maxHeight--
|
maxHeight--
|
||||||
x++
|
x++
|
||||||
@ -144,5 +144,5 @@ func (i *Label) Draw() {
|
|||||||
startY++
|
startY++
|
||||||
}
|
}
|
||||||
|
|
||||||
DrawStringAtPoint(i.value, x, y, i.fg, i.bg)
|
DrawStringAtPoint(c.value, x, y, c.fg, c.bg)
|
||||||
}
|
}
|
||||||
|
389
termbox_menu.go
389
termbox_menu.go
@ -14,118 +14,134 @@ type Menu struct {
|
|||||||
bg, fg termbox.Attribute
|
bg, fg termbox.Attribute
|
||||||
selectedBg, selectedFg termbox.Attribute
|
selectedBg, selectedFg termbox.Attribute
|
||||||
disabledBg, disabledFg termbox.Attribute
|
disabledBg, disabledFg termbox.Attribute
|
||||||
|
activeFg, activeBg termbox.Attribute
|
||||||
isDone bool
|
isDone bool
|
||||||
bordered bool
|
bordered bool
|
||||||
vimMode bool
|
vimMode bool
|
||||||
tabSkip bool
|
tabSkip bool
|
||||||
|
active bool
|
||||||
}
|
}
|
||||||
|
|
||||||
// CreateMenu Creates a menu with the specified attributes
|
// CreateMenu Creates a menu with the specified attributes
|
||||||
func CreateMenu(title string, options []string, x, y, width, height int, fg, bg termbox.Attribute) *Menu {
|
func CreateMenu(title string, options []string, x, y, width, height int, fg, bg termbox.Attribute) *Menu {
|
||||||
i := Menu{
|
c := Menu{
|
||||||
title: title,
|
title: title,
|
||||||
x: x, y: y, width: width, height: height,
|
x: x, y: y, width: width, height: height,
|
||||||
fg: fg, bg: bg, selectedFg: bg, selectedBg: fg,
|
fg: fg, bg: bg, selectedFg: bg, selectedBg: fg,
|
||||||
disabledFg: bg, disabledBg: bg,
|
disabledFg: bg, disabledBg: bg,
|
||||||
|
activeFg: fg, activeBg: bg,
|
||||||
|
bordered: true,
|
||||||
}
|
}
|
||||||
for _, line := range options {
|
for _, line := range options {
|
||||||
i.options = append(i.options, MenuOption{text: line})
|
c.options = append(c.options, MenuOption{text: line})
|
||||||
}
|
}
|
||||||
if len(i.options) > 0 {
|
if len(c.options) > 0 {
|
||||||
i.SetSelectedOption(&i.options[0])
|
c.SetSelectedOption(&c.options[0])
|
||||||
}
|
}
|
||||||
return &i
|
return &c
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (c *Menu) SetActiveFgColor(fg termbox.Attribute) { c.activeFg = fg }
|
||||||
|
|
||||||
|
func (c *Menu) SetActiveBgColor(bg termbox.Attribute) { c.activeBg = bg }
|
||||||
|
|
||||||
|
func (c *Menu) SetActive(a bool) { c.active = a }
|
||||||
|
|
||||||
|
func (c *Menu) IsActive() bool { return c.active }
|
||||||
|
|
||||||
// GetID returns this control's ID
|
// GetID returns this control's ID
|
||||||
func (i *Menu) GetID() string { return i.id }
|
func (c *Menu) GetID() string { return c.id }
|
||||||
|
|
||||||
// SetID sets this control's ID
|
// SetID sets this control's ID
|
||||||
func (i *Menu) SetID(newID string) {
|
func (c *Menu) SetID(newID string) { c.id = newID }
|
||||||
i.id = newID
|
|
||||||
}
|
// IsTabSkipped is always true for a label
|
||||||
|
func (c *Menu) IsTabSkipped() bool { return true }
|
||||||
|
|
||||||
|
// This doesn't do anything for a label
|
||||||
|
func (c *Menu) SetTabSkip(b bool) {}
|
||||||
|
|
||||||
// GetTitle returns the current title of the menu
|
// GetTitle returns the current title of the menu
|
||||||
func (i *Menu) GetTitle() string { return i.title }
|
func (c *Menu) GetTitle() string { return c.title }
|
||||||
|
|
||||||
// SetTitle sets the current title of the menu to s
|
// SetTitle sets the current title of the menu to s
|
||||||
func (i *Menu) SetTitle(s string) {
|
func (c *Menu) SetTitle(s string) {
|
||||||
i.title = s
|
c.title = s
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetOptions returns the current options of the menu
|
// GetOptions returns the current options of the menu
|
||||||
func (i *Menu) GetOptions() []MenuOption {
|
func (c *Menu) GetOptions() []MenuOption {
|
||||||
return i.options
|
return c.options
|
||||||
}
|
}
|
||||||
|
|
||||||
// SetOptions set the menu's options to opts
|
// SetOptions set the menu's options to opts
|
||||||
func (i *Menu) SetOptions(opts []MenuOption) {
|
func (c *Menu) SetOptions(opts []MenuOption) {
|
||||||
i.options = opts
|
c.options = opts
|
||||||
}
|
}
|
||||||
|
|
||||||
// SetOptionsFromStrings sets the options of this menu from a slice of strings
|
// SetOptionsFromStrings sets the options of this menu from a slice of strings
|
||||||
func (i *Menu) SetOptionsFromStrings(opts []string) {
|
func (c *Menu) SetOptionsFromStrings(opts []string) {
|
||||||
var newOpts []MenuOption
|
var newOpts []MenuOption
|
||||||
for _, v := range opts {
|
for _, v := range opts {
|
||||||
newOpts = append(newOpts, *CreateOptionFromText(v))
|
newOpts = append(newOpts, *CreateOptionFromText(v))
|
||||||
}
|
}
|
||||||
i.SetOptions(newOpts)
|
c.SetOptions(newOpts)
|
||||||
i.SetSelectedOption(i.GetOptionFromIndex(0))
|
c.SetSelectedOption(c.GetOptionFromIndex(0))
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetX returns the current x coordinate of the menu
|
// GetX returns the current x coordinate of the menu
|
||||||
func (i *Menu) GetX() int { return i.x }
|
func (c *Menu) GetX() int { return c.x }
|
||||||
|
|
||||||
// SetX sets the current x coordinate of the menu to x
|
// SetX sets the current x coordinate of the menu to x
|
||||||
func (i *Menu) SetX(x int) {
|
func (c *Menu) SetX(x int) {
|
||||||
i.x = x
|
c.x = x
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetY returns the current y coordinate of the menu
|
// GetY returns the current y coordinate of the menu
|
||||||
func (i *Menu) GetY() int { return i.y }
|
func (c *Menu) GetY() int { return c.y }
|
||||||
|
|
||||||
// SetY sets the current y coordinate of the menu to y
|
// SetY sets the current y coordinate of the menu to y
|
||||||
func (i *Menu) SetY(y int) {
|
func (c *Menu) SetY(y int) {
|
||||||
i.y = y
|
c.y = y
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetWidth returns the current width of the menu
|
// GetWidth returns the current width of the menu
|
||||||
func (i *Menu) GetWidth() int { return i.width }
|
func (c *Menu) GetWidth() int { return c.width }
|
||||||
|
|
||||||
// SetWidth sets the current menu width to width
|
// SetWidth sets the current menu width to width
|
||||||
func (i *Menu) SetWidth(width int) {
|
func (c *Menu) SetWidth(width int) {
|
||||||
i.width = width
|
c.width = width
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetHeight returns the current height of the menu
|
// GetHeight returns the current height of the menu
|
||||||
func (i *Menu) GetHeight() int { return i.height }
|
func (c *Menu) GetHeight() int { return c.height }
|
||||||
|
|
||||||
// SetHeight set the height of the menu to height
|
// SetHeight set the height of the menu to height
|
||||||
func (i *Menu) SetHeight(height int) {
|
func (c *Menu) SetHeight(height int) {
|
||||||
i.height = height
|
c.height = height
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetSelectedOption returns the current selected option
|
// GetSelectedOption returns the current selected option
|
||||||
func (i *Menu) GetSelectedOption() *MenuOption {
|
func (c *Menu) GetSelectedOption() *MenuOption {
|
||||||
idx := i.GetSelectedIndex()
|
idx := c.GetSelectedIndex()
|
||||||
if idx != -1 {
|
if idx != -1 {
|
||||||
return &i.options[idx]
|
return &c.options[idx]
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetOptionFromIndex Returns the
|
// GetOptionFromIndex Returns the
|
||||||
func (i *Menu) GetOptionFromIndex(idx int) *MenuOption {
|
func (c *Menu) GetOptionFromIndex(idx int) *MenuOption {
|
||||||
if idx >= 0 && idx < len(i.options) {
|
if idx >= 0 && idx < len(c.options) {
|
||||||
return &i.options[idx]
|
return &c.options[idx]
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetOptionFromText Returns the first option with the text v
|
// GetOptionFromText Returns the first option with the text v
|
||||||
func (i *Menu) GetOptionFromText(v string) *MenuOption {
|
func (c *Menu) GetOptionFromText(v string) *MenuOption {
|
||||||
for idx := range i.options {
|
for idx := range c.options {
|
||||||
testOption := &i.options[idx]
|
testOption := &c.options[idx]
|
||||||
if testOption.GetText() == v {
|
if testOption.GetText() == v {
|
||||||
return testOption
|
return testOption
|
||||||
}
|
}
|
||||||
@ -135,9 +151,9 @@ func (i *Menu) GetOptionFromText(v string) *MenuOption {
|
|||||||
|
|
||||||
// GetSelectedIndex returns the index of the selected option
|
// GetSelectedIndex returns the index of the selected option
|
||||||
// Returns -1 if nothing is selected
|
// Returns -1 if nothing is selected
|
||||||
func (i *Menu) GetSelectedIndex() int {
|
func (c *Menu) GetSelectedIndex() int {
|
||||||
for idx := range i.options {
|
for idx := range c.options {
|
||||||
if i.options[idx].IsSelected() {
|
if c.options[idx].IsSelected() {
|
||||||
return idx
|
return idx
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -145,267 +161,288 @@ func (i *Menu) GetSelectedIndex() int {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// SetSelectedIndex sets the selection to setIdx
|
// SetSelectedIndex sets the selection to setIdx
|
||||||
func (i *Menu) SetSelectedIndex(idx int) {
|
func (c *Menu) SetSelectedIndex(idx int) {
|
||||||
if len(i.options) > 0 {
|
if len(c.options) > 0 {
|
||||||
if idx < 0 {
|
if idx < 0 {
|
||||||
idx = 0
|
idx = 0
|
||||||
} else if idx >= len(i.options) {
|
} else if idx >= len(c.options) {
|
||||||
idx = len(i.options) - 1
|
idx = len(c.options) - 1
|
||||||
}
|
}
|
||||||
i.SetSelectedOption(&i.options[idx])
|
c.SetSelectedOption(&c.options[idx])
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// SetSelectedOption sets the current selected option to v (if it's valid)
|
// SetSelectedOption sets the current selected option to v (if it's valid)
|
||||||
func (i *Menu) SetSelectedOption(v *MenuOption) {
|
func (c *Menu) SetSelectedOption(v *MenuOption) {
|
||||||
for idx := range i.options {
|
for idx := range c.options {
|
||||||
if &i.options[idx] == v {
|
if &c.options[idx] == v {
|
||||||
i.options[idx].Select()
|
c.options[idx].Select()
|
||||||
} else {
|
} else {
|
||||||
i.options[idx].Unselect()
|
c.options[idx].Unselect()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// SelectPrevOption Decrements the selected option (if it can)
|
// SelectPrevOption Decrements the selected option (if it can)
|
||||||
func (i *Menu) SelectPrevOption() {
|
func (c *Menu) SelectPrevOption() {
|
||||||
idx := i.GetSelectedIndex()
|
idx := c.GetSelectedIndex()
|
||||||
for idx >= 0 {
|
for idx >= 0 {
|
||||||
idx--
|
idx--
|
||||||
testOption := i.GetOptionFromIndex(idx)
|
testOption := c.GetOptionFromIndex(idx)
|
||||||
if testOption != nil && !testOption.IsDisabled() {
|
if testOption != nil && !testOption.IsDisabled() {
|
||||||
i.SetSelectedOption(testOption)
|
c.SetSelectedOption(testOption)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// SelectNextOption Increments the selected option (if it can)
|
// SelectNextOption Increments the selected option (if it can)
|
||||||
func (i *Menu) SelectNextOption() {
|
func (c *Menu) SelectNextOption() {
|
||||||
idx := i.GetSelectedIndex()
|
idx := c.GetSelectedIndex()
|
||||||
for idx < len(i.options) {
|
for idx < len(c.options) {
|
||||||
idx++
|
idx++
|
||||||
testOption := i.GetOptionFromIndex(idx)
|
testOption := c.GetOptionFromIndex(idx)
|
||||||
if testOption != nil && !testOption.IsDisabled() {
|
if testOption != nil && !testOption.IsDisabled() {
|
||||||
i.SetSelectedOption(testOption)
|
c.SetSelectedOption(testOption)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// SelectPageUpOption Goes up 'menu height' options
|
// SelectPageUpOption Goes up 'menu height' options
|
||||||
func (i *Menu) SelectPageUpOption() {
|
func (c *Menu) SelectPageUpOption() {
|
||||||
idx := i.GetSelectedIndex()
|
idx := c.GetSelectedIndex()
|
||||||
idx -= i.height
|
idx -= c.height
|
||||||
if idx < 0 {
|
if idx < 0 {
|
||||||
idx = 0
|
idx = 0
|
||||||
}
|
}
|
||||||
i.SetSelectedIndex(idx)
|
c.SetSelectedIndex(idx)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
// SelectPageDownOption Goes down 'menu height' options
|
// SelectPageDownOption Goes down 'menu height' options
|
||||||
func (i *Menu) SelectPageDownOption() {
|
func (c *Menu) SelectPageDownOption() {
|
||||||
idx := i.GetSelectedIndex()
|
idx := c.GetSelectedIndex()
|
||||||
idx += i.height
|
idx += c.height
|
||||||
if idx >= len(i.options) {
|
if idx >= len(c.options) {
|
||||||
idx = len(i.options) - 1
|
idx = len(c.options) - 1
|
||||||
}
|
}
|
||||||
i.SetSelectedIndex(idx)
|
c.SetSelectedIndex(idx)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
// SelectFirstOption Goes to the top
|
// SelectFirstOption Goes to the top
|
||||||
func (i *Menu) SelectFirstOption() {
|
func (c *Menu) SelectFirstOption() {
|
||||||
i.SetSelectedIndex(0)
|
c.SetSelectedIndex(0)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
// SelectLastOption Goes to the bottom
|
// SelectLastOption Goes to the bottom
|
||||||
func (i *Menu) SelectLastOption() {
|
func (c *Menu) SelectLastOption() {
|
||||||
i.SetSelectedIndex(len(i.options) - 1)
|
c.SetSelectedIndex(len(c.options) - 1)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
// SetOptionDisabled Disables the specified option
|
// SetOptionDisabled Disables the specified option
|
||||||
func (i *Menu) SetOptionDisabled(idx int) {
|
func (c *Menu) SetOptionDisabled(idx int) {
|
||||||
if len(i.options) > idx {
|
if len(c.options) > idx {
|
||||||
i.GetOptionFromIndex(idx).Disable()
|
c.GetOptionFromIndex(idx).Disable()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// SetOptionEnabled Enables the specified option
|
// SetOptionEnabled Enables the specified option
|
||||||
func (i *Menu) SetOptionEnabled(idx int) {
|
func (c *Menu) SetOptionEnabled(idx int) {
|
||||||
if len(i.options) > idx {
|
if len(c.options) > idx {
|
||||||
i.GetOptionFromIndex(idx).Enable()
|
c.GetOptionFromIndex(idx).Enable()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// HelpIsShown returns true or false if the help is displayed
|
// HelpIsShown returns true or false if the help is displayed
|
||||||
func (i *Menu) HelpIsShown() bool { return i.showHelp }
|
func (c *Menu) HelpIsShown() bool { return c.showHelp }
|
||||||
|
|
||||||
// ShowHelp sets whether or not to display the help text
|
// ShowHelp sets whether or not to display the help text
|
||||||
func (i *Menu) ShowHelp(b bool) {
|
func (c *Menu) ShowHelp(b bool) {
|
||||||
i.showHelp = b
|
c.showHelp = b
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetFgColor returns the foreground color
|
// GetFgColor returns the foreground color
|
||||||
func (i *Menu) GetFgColor() termbox.Attribute { return i.fg }
|
func (c *Menu) GetFgColor() termbox.Attribute { return c.fg }
|
||||||
|
|
||||||
// SetFgColor sets the foreground color
|
// SetFgColor sets the foreground color
|
||||||
func (i *Menu) SetFgColor(fg termbox.Attribute) {
|
func (c *Menu) SetFgColor(fg termbox.Attribute) {
|
||||||
i.fg = fg
|
c.fg = fg
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetBgColor returns the background color
|
// GetBgColor returns the background color
|
||||||
func (i *Menu) GetBgColor() termbox.Attribute { return i.bg }
|
func (c *Menu) GetBgColor() termbox.Attribute { return c.bg }
|
||||||
|
|
||||||
// SetBgColor sets the current background color
|
// SetBgColor sets the current background color
|
||||||
func (i *Menu) SetBgColor(bg termbox.Attribute) {
|
func (c *Menu) SetBgColor(bg termbox.Attribute) {
|
||||||
i.bg = bg
|
c.bg = bg
|
||||||
}
|
}
|
||||||
|
|
||||||
// IsDone returns whether the user has answered the modal
|
// IsDone returns whether the user has answered the modal
|
||||||
func (i *Menu) IsDone() bool { return i.isDone }
|
func (c *Menu) IsDone() bool { return c.isDone }
|
||||||
|
|
||||||
// SetDone sets whether the modal has completed it's purpose
|
// SetDone sets whether the modal has completed it's purpose
|
||||||
func (i *Menu) SetDone(b bool) {
|
func (c *Menu) SetDone(b bool) {
|
||||||
i.isDone = b
|
c.isDone = b
|
||||||
}
|
}
|
||||||
|
|
||||||
// IsBordered returns true or false if this menu has a border
|
// IsBordered returns true or false if this menu has a border
|
||||||
func (i *Menu) IsBordered() bool { return i.bordered }
|
func (c *Menu) IsBordered() bool { return c.bordered }
|
||||||
|
|
||||||
// SetBordered sets whether we render a border around the menu
|
// SetBordered sets whether we render a border around the menu
|
||||||
func (i *Menu) SetBordered(b bool) {
|
func (c *Menu) SetBordered(b bool) {
|
||||||
i.bordered = b
|
c.bordered = b
|
||||||
}
|
}
|
||||||
|
|
||||||
// EnableVimMode Enables h,j,k,l navigation
|
// EnableVimMode Enables h,j,k,l navigation
|
||||||
func (i *Menu) EnableVimMode() {
|
func (c *Menu) EnableVimMode() {
|
||||||
i.vimMode = true
|
c.vimMode = true
|
||||||
}
|
}
|
||||||
|
|
||||||
// DisableVimMode Disables h,j,k,l navigation
|
// DisableVimMode Disables h,j,k,l navigation
|
||||||
func (i *Menu) DisableVimMode() {
|
func (c *Menu) DisableVimMode() {
|
||||||
i.vimMode = false
|
c.vimMode = false
|
||||||
}
|
}
|
||||||
|
|
||||||
// HandleEvent handles the termbox event and returns whether it was consumed
|
// HandleEvent handles the termbox event and returns whether it was consumed
|
||||||
func (i *Menu) HandleEvent(event termbox.Event) bool {
|
func (c *Menu) HandleEvent(event termbox.Event) bool {
|
||||||
if event.Key == termbox.KeyEnter || event.Key == termbox.KeySpace {
|
if event.Key == termbox.KeyEnter || event.Key == termbox.KeySpace {
|
||||||
i.isDone = true
|
c.isDone = true
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
currentIdx := i.GetSelectedIndex()
|
currentIdx := c.GetSelectedIndex()
|
||||||
switch event.Key {
|
switch event.Key {
|
||||||
case termbox.KeyArrowUp:
|
case termbox.KeyArrowUp:
|
||||||
i.SelectPrevOption()
|
c.SelectPrevOption()
|
||||||
case termbox.KeyArrowDown:
|
case termbox.KeyArrowDown:
|
||||||
i.SelectNextOption()
|
c.SelectNextOption()
|
||||||
case termbox.KeyArrowLeft:
|
case termbox.KeyArrowLeft:
|
||||||
i.SelectPageUpOption()
|
c.SelectPageUpOption()
|
||||||
case termbox.KeyArrowRight:
|
case termbox.KeyArrowRight:
|
||||||
i.SelectPageDownOption()
|
c.SelectPageDownOption()
|
||||||
}
|
}
|
||||||
if i.vimMode {
|
if c.vimMode {
|
||||||
switch event.Ch {
|
switch event.Ch {
|
||||||
case 'j':
|
case 'j':
|
||||||
i.SelectNextOption()
|
c.SelectNextOption()
|
||||||
case 'k':
|
case 'k':
|
||||||
i.SelectPrevOption()
|
c.SelectPrevOption()
|
||||||
}
|
}
|
||||||
if event.Key == termbox.KeyCtrlF {
|
if event.Key == termbox.KeyCtrlF {
|
||||||
i.SelectPageDownOption()
|
c.SelectPageDownOption()
|
||||||
} else if event.Key == termbox.KeyCtrlB {
|
} else if event.Key == termbox.KeyCtrlB {
|
||||||
i.SelectPageUpOption()
|
c.SelectPageUpOption()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if i.GetSelectedIndex() != currentIdx {
|
if c.GetSelectedIndex() != currentIdx {
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
// Draw draws the modal
|
// Draw draws the modal
|
||||||
func (i *Menu) Draw() {
|
func (c *Menu) Draw() {
|
||||||
|
useFg, useBg := c.fg, c.bg
|
||||||
|
if c.active {
|
||||||
|
useFg, useBg = c.activeFg, c.activeBg
|
||||||
|
}
|
||||||
// First blank out the area we'll be putting the menu
|
// First blank out the area we'll be putting the menu
|
||||||
FillWithChar(' ', i.x, i.y, i.x+i.width, i.y+i.height, i.fg, i.bg)
|
FillWithChar(' ', c.x, c.y, c.x+c.width, c.y+c.height, useFg, useBg)
|
||||||
// Now draw the border
|
// Now draw the border
|
||||||
optionStartX := i.x
|
optionStartX := c.x
|
||||||
optionStartY := i.y
|
optionStartY := c.y
|
||||||
optionWidth := i.width
|
optionWidth := c.width
|
||||||
optionHeight := i.height
|
_ = optionWidth
|
||||||
|
optionHeight := c.height
|
||||||
if optionHeight == -1 {
|
if optionHeight == -1 {
|
||||||
optionHeight = len(i.options)
|
optionHeight = len(c.options)
|
||||||
}
|
}
|
||||||
if i.bordered {
|
if c.bordered {
|
||||||
if i.height == -1 {
|
pct := float64(c.GetSelectedIndex()) / float64(len(c.options))
|
||||||
DrawBorder(i.x, i.y, i.x+i.width, i.y+optionHeight+1, i.fg, i.bg)
|
if c.title == "" {
|
||||||
|
if len(c.options) > c.height-2 {
|
||||||
|
DrawBorderWithPct(c.x, c.y, c.x+c.width, c.y+c.height, pct, useFg, useBg)
|
||||||
} else {
|
} else {
|
||||||
DrawBorder(i.x, i.y, i.x+i.width, i.y+optionHeight, i.fg, i.bg)
|
DrawBorder(c.x, c.y, c.x+c.width, c.y+c.height, useFg, useBg)
|
||||||
}
|
}
|
||||||
optionStartX = i.x + 1
|
} else {
|
||||||
optionStartY = i.y + 1
|
if len(c.options) > c.height-2 {
|
||||||
optionWidth = i.width - 1
|
DrawBorderWithTitleAndPct(c.x, c.y, c.x+c.width, c.y+c.height, " "+c.title+" ", pct, useFg, useBg)
|
||||||
|
} else {
|
||||||
|
DrawBorderWithTitle(c.x, c.y, c.x+c.width, c.y+c.height, " "+c.title+" ", useFg, useBg)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
optionStartX = c.x + 1
|
||||||
|
optionStartY = c.y + 1
|
||||||
|
optionWidth = c.width - 1
|
||||||
optionHeight -= 2
|
optionHeight -= 2
|
||||||
}
|
}
|
||||||
|
|
||||||
// The title
|
if len(c.options) > 0 {
|
||||||
if i.title != "" {
|
firstDispIdx := 0
|
||||||
DrawStringAtPoint(AlignText(i.title, optionWidth, AlignCenter), optionStartX, optionStartY, i.fg, i.bg)
|
lastDispIdx := len(c.options) - 1
|
||||||
|
if len(c.options) > c.height-2 {
|
||||||
|
lastDispIdx = c.height - 2
|
||||||
|
}
|
||||||
|
if c.GetSelectedIndex() > c.height-2 {
|
||||||
|
firstDispIdx = c.GetSelectedIndex() - (c.height - 2)
|
||||||
|
lastDispIdx = c.GetSelectedIndex()
|
||||||
|
}
|
||||||
|
for idx := firstDispIdx; idx < lastDispIdx; idx++ {
|
||||||
|
currOpt := &c.options[idx]
|
||||||
|
outTxt := currOpt.GetText()
|
||||||
|
if currOpt.IsDisabled() {
|
||||||
|
DrawStringAtPoint(outTxt, optionStartX, optionStartY, c.disabledFg, c.disabledBg)
|
||||||
|
} else if c.GetSelectedOption() == currOpt {
|
||||||
|
DrawStringAtPoint(outTxt, optionStartX, optionStartY, c.selectedFg, c.selectedBg)
|
||||||
|
} else {
|
||||||
|
DrawStringAtPoint(outTxt, optionStartX, optionStartY, useFg, useBg)
|
||||||
|
}
|
||||||
optionStartY++
|
optionStartY++
|
||||||
if i.bordered {
|
|
||||||
FillWithChar('-', optionStartX, optionStartY, optionWidth, optionStartY, i.fg, i.bg)
|
|
||||||
optionStartY++
|
|
||||||
optionHeight--
|
|
||||||
}
|
}
|
||||||
optionHeight--
|
|
||||||
}
|
}
|
||||||
|
/*
|
||||||
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
|
// Print the options
|
||||||
bldHeight := (optionHeight / 2)
|
bldHeight := (optionHeight / 2)
|
||||||
startIdx := i.GetSelectedIndex()
|
startIdx := c.GetSelectedIndex()
|
||||||
endIdx := i.GetSelectedIndex()
|
endIdx := c.GetSelectedIndex()
|
||||||
for bldHeight > 0 && startIdx >= 1 {
|
for bldHeight > 0 && startIdx >= 1 {
|
||||||
startIdx--
|
startIdx--
|
||||||
bldHeight--
|
bldHeight--
|
||||||
}
|
}
|
||||||
bldHeight += (optionHeight / 2)
|
bldHeight += (optionHeight / 2)
|
||||||
for bldHeight > 0 && endIdx < len(i.options) {
|
for bldHeight > 0 && endIdx < len(c.options) {
|
||||||
endIdx++
|
endIdx++
|
||||||
bldHeight--
|
bldHeight--
|
||||||
}
|
}
|
||||||
|
|
||||||
for idx := startIdx; idx < endIdx; idx++ { //i.options {
|
for idx := startIdx; idx < endIdx; idx++ {
|
||||||
if i.GetSelectedIndex()-idx >= optionHeight-1 {
|
if c.GetSelectedIndex()-idx >= optionHeight-1 {
|
||||||
// Skip this one
|
// Skip this one
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
currOpt := &i.options[idx]
|
currOpt := &c.options[idx]
|
||||||
outTxt := currOpt.GetText()
|
outTxt := currOpt.GetText()
|
||||||
if len(outTxt) >= i.width {
|
if len(outTxt) >= c.width {
|
||||||
outTxt = outTxt[:i.width]
|
outTxt = outTxt[:c.width]
|
||||||
}
|
}
|
||||||
if currOpt.IsDisabled() {
|
if currOpt.IsDisabled() {
|
||||||
DrawStringAtPoint(outTxt, optionStartX, optionStartY, i.disabledFg, i.disabledBg)
|
DrawStringAtPoint(outTxt, optionStartX, optionStartY, c.disabledFg, c.disabledBg)
|
||||||
} else if i.GetSelectedOption() == currOpt {
|
} else if c.GetSelectedOption() == currOpt {
|
||||||
DrawStringAtPoint(outTxt, optionStartX, optionStartY, i.selectedFg, i.selectedBg)
|
DrawStringAtPoint(outTxt, optionStartX, optionStartY, c.selectedFg, c.selectedBg)
|
||||||
} else {
|
} else {
|
||||||
DrawStringAtPoint(outTxt, optionStartX, optionStartY, i.fg, i.bg)
|
DrawStringAtPoint(outTxt, optionStartX, optionStartY, useFg, useBg)
|
||||||
}
|
}
|
||||||
optionStartY++
|
optionStartY++
|
||||||
if optionStartY > i.y+optionHeight-1 {
|
if optionStartY > c.y+optionHeight-1 {
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
*/
|
||||||
}
|
}
|
||||||
|
|
||||||
/* MenuOption Struct & methods */
|
/* MenuOption Struct & methods */
|
||||||
@ -427,52 +464,52 @@ func CreateOptionFromText(s string) *MenuOption {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// SetText Sets the text for this option
|
// SetText Sets the text for this option
|
||||||
func (i *MenuOption) SetText(s string) {
|
func (c *MenuOption) SetText(s string) {
|
||||||
i.text = s
|
c.text = s
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetText Returns the text for this option
|
// GetText Returns the text for this option
|
||||||
func (i *MenuOption) GetText() string { return i.text }
|
func (c *MenuOption) GetText() string { return c.text }
|
||||||
|
|
||||||
// Disable Sets this option to disabled
|
// Disable Sets this option to disabled
|
||||||
func (i *MenuOption) Disable() {
|
func (c *MenuOption) Disable() {
|
||||||
i.disabled = true
|
c.disabled = true
|
||||||
}
|
}
|
||||||
|
|
||||||
// Enable Sets this option to enabled
|
// Enable Sets this option to enabled
|
||||||
func (i *MenuOption) Enable() {
|
func (c *MenuOption) Enable() {
|
||||||
i.disabled = false
|
c.disabled = false
|
||||||
}
|
}
|
||||||
|
|
||||||
// IsDisabled returns whether this option is enabled
|
// IsDisabled returns whether this option is enabled
|
||||||
func (i *MenuOption) IsDisabled() bool {
|
func (c *MenuOption) IsDisabled() bool {
|
||||||
return i.disabled
|
return c.disabled
|
||||||
}
|
}
|
||||||
|
|
||||||
// IsSelected Returns whether this option is selected
|
// IsSelected Returns whether this option is selected
|
||||||
func (i *MenuOption) IsSelected() bool {
|
func (c *MenuOption) IsSelected() bool {
|
||||||
return i.selected
|
return c.selected
|
||||||
}
|
}
|
||||||
|
|
||||||
// Select Sets this option to selected
|
// Select Sets this option to selected
|
||||||
func (i *MenuOption) Select() {
|
func (c *MenuOption) Select() {
|
||||||
i.selected = true
|
c.selected = true
|
||||||
}
|
}
|
||||||
|
|
||||||
// Unselect Sets this option to not selected
|
// Unselect Sets this option to not selected
|
||||||
func (i *MenuOption) Unselect() {
|
func (c *MenuOption) Unselect() {
|
||||||
i.selected = false
|
c.selected = false
|
||||||
}
|
}
|
||||||
|
|
||||||
// SetHelpText Sets this option's help text to s
|
// SetHelpText Sets this option's help text to s
|
||||||
func (i *MenuOption) SetHelpText(s string) {
|
func (c *MenuOption) SetHelpText(s string) {
|
||||||
i.helpText = s
|
c.helpText = s
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetHelpText Returns the help text for this option
|
// GetHelpText Returns the help text for this option
|
||||||
func (i *MenuOption) GetHelpText() string { return i.helpText }
|
func (c *MenuOption) GetHelpText() string { return c.helpText }
|
||||||
|
|
||||||
// AddToSubMenu adds a slice of MenuOptions to this option
|
// AddToSubMenu adds a slice of MenuOptions to this option
|
||||||
func (i *MenuOption) AddToSubMenu(sub *MenuOption) {
|
func (c *MenuOption) AddToSubMenu(sub *MenuOption) {
|
||||||
i.subMenu = append(i.subMenu, *sub)
|
c.subMenu = append(c.subMenu, *sub)
|
||||||
}
|
}
|
||||||
|
@ -17,155 +17,163 @@ type ProgressBar struct {
|
|||||||
|
|
||||||
x, y int
|
x, y int
|
||||||
width, height int
|
width, height int
|
||||||
bg, fg termbox.Attribute
|
fg, bg termbox.Attribute
|
||||||
|
activeFg, activeBg termbox.Attribute
|
||||||
|
active bool
|
||||||
}
|
}
|
||||||
|
|
||||||
// CreateProgressBar Create a progress bar object
|
// CreateProgressBar Create a progress bar object
|
||||||
func CreateProgressBar(tot, x, y int, fg, bg termbox.Attribute) *ProgressBar {
|
func CreateProgressBar(tot, x, y int, fg, bg termbox.Attribute) *ProgressBar {
|
||||||
i := ProgressBar{total: tot,
|
c := ProgressBar{total: tot,
|
||||||
fullChar: '#', emptyChar: ' ',
|
fullChar: '#', emptyChar: ' ',
|
||||||
x: x, y: y, height: 1, width: 10,
|
x: x, y: y, height: 1, width: 10,
|
||||||
bordered: true, fg: fg, bg: bg,
|
bordered: true, fg: fg, bg: bg,
|
||||||
|
activeFg: fg, activeBg: bg,
|
||||||
alignment: AlignLeft,
|
alignment: AlignLeft,
|
||||||
}
|
}
|
||||||
return &i
|
return &c
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (c *ProgressBar) SetActiveFgColor(fg termbox.Attribute) { c.activeFg = fg }
|
||||||
|
func (c *ProgressBar) SetActiveBgColor(bg termbox.Attribute) { c.activeBg = bg }
|
||||||
|
func (c *ProgressBar) SetActive(a bool) { c.active = a }
|
||||||
|
func (c *ProgressBar) IsActive() bool { return c.active }
|
||||||
|
|
||||||
// GetID returns this control's ID
|
// GetID returns this control's ID
|
||||||
func (i *ProgressBar) GetID() string { return i.id }
|
func (c *ProgressBar) GetID() string { return c.id }
|
||||||
|
|
||||||
// SetID sets this control's ID
|
// SetID sets this control's ID
|
||||||
func (i *ProgressBar) SetID(newID string) {
|
func (c *ProgressBar) SetID(newID string) {
|
||||||
i.id = newID
|
c.id = newID
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetProgress returns the curret progress value
|
// GetProgress returns the curret progress value
|
||||||
func (i *ProgressBar) GetProgress() int {
|
func (c *ProgressBar) GetProgress() int {
|
||||||
return i.progress
|
return c.progress
|
||||||
}
|
}
|
||||||
|
|
||||||
// SetProgress sets the current progress of the bar
|
// SetProgress sets the current progress of the bar
|
||||||
func (i *ProgressBar) SetProgress(p int) {
|
func (c *ProgressBar) SetProgress(p int) {
|
||||||
if (p <= i.total || i.allowOverflow) || (p >= 0 || i.allowUnderflow) {
|
if (p <= c.total || c.allowOverflow) || (p >= 0 || c.allowUnderflow) {
|
||||||
i.progress = p
|
c.progress = p
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// IncrProgress increments the current progress of the bar
|
// IncrProgress increments the current progress of the bar
|
||||||
func (i *ProgressBar) IncrProgress() {
|
func (c *ProgressBar) IncrProgress() {
|
||||||
if i.progress < i.total || i.allowOverflow {
|
if c.progress < c.total || c.allowOverflow {
|
||||||
i.progress++
|
c.progress++
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// DecrProgress decrements the current progress of the bar
|
// DecrProgress decrements the current progress of the bar
|
||||||
func (i *ProgressBar) DecrProgress() {
|
func (c *ProgressBar) DecrProgress() {
|
||||||
if i.progress > 0 || i.allowUnderflow {
|
if c.progress > 0 || c.allowUnderflow {
|
||||||
i.progress--
|
c.progress--
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetPercent returns the percent full of the bar
|
// GetPercent returns the percent full of the bar
|
||||||
func (i *ProgressBar) GetPercent() int {
|
func (c *ProgressBar) GetPercent() int {
|
||||||
return int(float64(i.progress) / float64(i.total) * 100)
|
return int(float64(c.progress) / float64(c.total) * 100)
|
||||||
}
|
}
|
||||||
|
|
||||||
// EnableOverflow Tells the progress bar that it can go over the total
|
// EnableOverflow Tells the progress bar that it can go over the total
|
||||||
func (i *ProgressBar) EnableOverflow() {
|
func (c *ProgressBar) EnableOverflow() {
|
||||||
i.allowOverflow = true
|
c.allowOverflow = true
|
||||||
}
|
}
|
||||||
|
|
||||||
// DisableOverflow Tells the progress bar that it can NOT go over the total
|
// DisableOverflow Tells the progress bar that it can NOT go over the total
|
||||||
func (i *ProgressBar) DisableOverflow() {
|
func (c *ProgressBar) DisableOverflow() {
|
||||||
i.allowOverflow = false
|
c.allowOverflow = false
|
||||||
}
|
}
|
||||||
|
|
||||||
// EnableUnderflow Tells the progress bar that it can go below zero
|
// EnableUnderflow Tells the progress bar that it can go below zero
|
||||||
func (i *ProgressBar) EnableUnderflow() {
|
func (c *ProgressBar) EnableUnderflow() {
|
||||||
i.allowUnderflow = true
|
c.allowUnderflow = true
|
||||||
}
|
}
|
||||||
|
|
||||||
// DisableUnderflow Tells the progress bar that it can NOT go below zero
|
// DisableUnderflow Tells the progress bar that it can NOT go below zero
|
||||||
func (i *ProgressBar) DisableUnderflow() {
|
func (c *ProgressBar) DisableUnderflow() {
|
||||||
i.allowUnderflow = false
|
c.allowUnderflow = false
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetFullChar returns the rune used for 'full'
|
// GetFullChar returns the rune used for 'full'
|
||||||
func (i *ProgressBar) GetFullChar() rune {
|
func (c *ProgressBar) GetFullChar() rune {
|
||||||
return i.fullChar
|
return c.fullChar
|
||||||
}
|
}
|
||||||
|
|
||||||
// SetFullChar sets the rune used for 'full'
|
// SetFullChar sets the rune used for 'full'
|
||||||
func (i *ProgressBar) SetFullChar(f rune) {
|
func (c *ProgressBar) SetFullChar(f rune) {
|
||||||
i.fullChar = f
|
c.fullChar = f
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetEmptyChar gets the rune used for 'empty'
|
// GetEmptyChar gets the rune used for 'empty'
|
||||||
func (i *ProgressBar) GetEmptyChar() rune {
|
func (c *ProgressBar) GetEmptyChar() rune {
|
||||||
return i.emptyChar
|
return c.emptyChar
|
||||||
}
|
}
|
||||||
|
|
||||||
// SetEmptyChar sets the rune used for 'empty'
|
// SetEmptyChar sets the rune used for 'empty'
|
||||||
func (i *ProgressBar) SetEmptyChar(f rune) {
|
func (c *ProgressBar) SetEmptyChar(f rune) {
|
||||||
i.emptyChar = f
|
c.emptyChar = f
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetX Return the x position of the Progress Bar
|
// GetX Return the x position of the Progress Bar
|
||||||
func (i *ProgressBar) GetX() int { return i.x }
|
func (c *ProgressBar) GetX() int { return c.x }
|
||||||
|
|
||||||
// SetX set the x position of the ProgressBar to x
|
// SetX set the x position of the ProgressBar to x
|
||||||
func (i *ProgressBar) SetX(x int) {
|
func (c *ProgressBar) SetX(x int) {
|
||||||
i.x = x
|
c.x = x
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetY Return the y position of the ProgressBar
|
// GetY Return the y position of the ProgressBar
|
||||||
func (i *ProgressBar) GetY() int { return i.y }
|
func (c *ProgressBar) GetY() int { return c.y }
|
||||||
|
|
||||||
// SetY Set the y position of the ProgressBar to y
|
// SetY Set the y position of the ProgressBar to y
|
||||||
func (i *ProgressBar) SetY(y int) {
|
func (c *ProgressBar) SetY(y int) {
|
||||||
i.y = y
|
c.y = y
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetHeight returns the height of the progress bar
|
// GetHeight returns the height of the progress bar
|
||||||
// Defaults to 1 (3 if bordered)
|
// Defaults to 1 (3 if bordered)
|
||||||
func (i *ProgressBar) GetHeight() int {
|
func (c *ProgressBar) GetHeight() int {
|
||||||
return i.height
|
return c.height
|
||||||
}
|
}
|
||||||
|
|
||||||
// SetHeight Sets the height of the progress bar
|
// SetHeight Sets the height of the progress bar
|
||||||
func (i *ProgressBar) SetHeight(h int) {
|
func (c *ProgressBar) SetHeight(h int) {
|
||||||
i.height = h
|
c.height = h
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetWidth returns the width of the progress bar
|
// GetWidth returns the width of the progress bar
|
||||||
func (i *ProgressBar) GetWidth() int {
|
func (c *ProgressBar) GetWidth() int {
|
||||||
return i.width
|
return c.width
|
||||||
}
|
}
|
||||||
|
|
||||||
// SetWidth Sets the width of the progress bar
|
// SetWidth Sets the width of the progress bar
|
||||||
func (i *ProgressBar) SetWidth(w int) {
|
func (c *ProgressBar) SetWidth(w int) {
|
||||||
i.width = w
|
c.width = w
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetFgColor returns the foreground color
|
// GetFgColor returns the foreground color
|
||||||
func (i *ProgressBar) GetFgColor() termbox.Attribute { return i.fg }
|
func (c *ProgressBar) GetFgColor() termbox.Attribute { return c.fg }
|
||||||
|
|
||||||
// SetFgColor sets the foreground color
|
// SetFgColor sets the foreground color
|
||||||
func (i *ProgressBar) SetFgColor(fg termbox.Attribute) {
|
func (c *ProgressBar) SetFgColor(fg termbox.Attribute) {
|
||||||
i.fg = fg
|
c.fg = fg
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetBgColor returns the background color
|
// GetBgColor returns the background color
|
||||||
func (i *ProgressBar) GetBgColor() termbox.Attribute { return i.bg }
|
func (c *ProgressBar) GetBgColor() termbox.Attribute { return c.bg }
|
||||||
|
|
||||||
// SetBgColor sets the current background color
|
// SetBgColor sets the current background color
|
||||||
func (i *ProgressBar) SetBgColor(bg termbox.Attribute) {
|
func (c *ProgressBar) SetBgColor(bg termbox.Attribute) {
|
||||||
i.bg = bg
|
c.bg = bg
|
||||||
}
|
}
|
||||||
|
|
||||||
// Align Tells which direction the progress bar empties
|
// Align Tells which direction the progress bar empties
|
||||||
func (i *ProgressBar) Align(a TextAlignment) {
|
func (c *ProgressBar) Align(a TextAlignment) {
|
||||||
i.alignment = a
|
c.alignment = a
|
||||||
}
|
}
|
||||||
|
|
||||||
// SetColorized sets whether the progress bar should be colored
|
// SetColorized sets whether the progress bar should be colored
|
||||||
@ -173,48 +181,48 @@ func (i *ProgressBar) Align(a TextAlignment) {
|
|||||||
// 10% - Red
|
// 10% - Red
|
||||||
// 50% - Yellow
|
// 50% - Yellow
|
||||||
// 80% - Green
|
// 80% - Green
|
||||||
func (i *ProgressBar) SetColorized(c bool) {
|
func (c *ProgressBar) SetColorized(color bool) {
|
||||||
i.colorized = c
|
c.colorized = color
|
||||||
}
|
}
|
||||||
|
|
||||||
// HandleEvent accepts the termbox event and returns whether it was consumed
|
// HandleEvent accepts the termbox event and returns whether it was consumed
|
||||||
func (i *ProgressBar) HandleEvent(event termbox.Event) bool {
|
func (c *ProgressBar) HandleEvent(event termbox.Event) bool {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
// Draw outputs the input field on the screen
|
// Draw outputs the input field on the screen
|
||||||
func (i *ProgressBar) Draw() {
|
func (c *ProgressBar) Draw() {
|
||||||
// For now, just draw a [#### ] bar
|
// For now, just draw a [#### ] bar
|
||||||
// TODO: make this more advanced
|
// TODO: make this more advanced
|
||||||
useFg := i.fg
|
useFg := c.fg
|
||||||
if i.colorized {
|
if c.colorized {
|
||||||
if i.GetPercent() < 10 {
|
if c.GetPercent() < 10 {
|
||||||
useFg = termbox.ColorRed
|
useFg = termbox.ColorRed
|
||||||
} else if i.GetPercent() < 50 {
|
} else if c.GetPercent() < 50 {
|
||||||
useFg = termbox.ColorYellow
|
useFg = termbox.ColorYellow
|
||||||
} else {
|
} else {
|
||||||
useFg = termbox.ColorGreen
|
useFg = termbox.ColorGreen
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
drawX, drawY := i.x, i.y
|
drawX, drawY := c.x, c.y
|
||||||
fillWidth, fillHeight := i.width-2, i.height
|
fillWidth, fillHeight := c.width-2, c.height
|
||||||
DrawStringAtPoint("[", drawX, drawY, i.fg, i.bg)
|
DrawStringAtPoint("[", drawX, drawY, c.fg, c.bg)
|
||||||
numFull := int(float64(fillWidth) * float64(i.progress) / float64(i.total))
|
numFull := int(float64(fillWidth) * float64(c.progress) / float64(c.total))
|
||||||
FillWithChar(i.fullChar, drawX+1, drawY, drawX+1+numFull, drawY+(fillHeight-1), useFg, i.bg)
|
FillWithChar(c.fullChar, drawX+1, drawY, drawX+1+numFull, drawY+(fillHeight-1), useFg, c.bg)
|
||||||
DrawStringAtPoint("]", drawX+i.width-1, drawY, i.fg, i.bg)
|
DrawStringAtPoint("]", drawX+c.width-1, drawY, c.fg, c.bg)
|
||||||
|
|
||||||
/*
|
/*
|
||||||
drawX, drawY := i.x, i.y
|
drawX, drawY := c.x, c.y
|
||||||
drawWidth, drawHeight := i.width, i.height
|
drawWidth, drawHeight := c.width, c.height
|
||||||
if i.bordered {
|
if c.bordered {
|
||||||
if i.height == 1 && i.width > 2 {
|
if c.height == 1 && c.width > 2 {
|
||||||
// Just using [ & ] for the border
|
// Just using [ & ] for the border
|
||||||
DrawStringAtPoint("[", drawX, drawY, i.fg, i.bg)
|
DrawStringAtPoint("[", drawX, drawY, c.fg, c.bg)
|
||||||
DrawStringAtPoint("]", drawX+i.width-1, drawY, i.fg, i.bg)
|
DrawStringAtPoint("]", drawX+c.width-1, drawY, c.fg, c.bg)
|
||||||
drawX++
|
drawX++
|
||||||
drawWidth -= 2
|
drawWidth -= 2
|
||||||
} else if i.height >= 3 {
|
} else if c.height >= 3 {
|
||||||
DrawBorder(drawX, drawY, drawX+i.width, drawY+i.height, i.fg, i.bg)
|
DrawBorder(drawX, drawY, drawX+c.width, drawY+c.height, c.fg, c.bg)
|
||||||
drawX++
|
drawX++
|
||||||
drawY++
|
drawY++
|
||||||
drawWidth -= 2
|
drawWidth -= 2
|
||||||
@ -223,14 +231,14 @@ func (i *ProgressBar) Draw() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Figure out how many chars are full
|
// Figure out how many chars are full
|
||||||
numFull := drawWidth * (i.progress / i.total)
|
numFull := drawWidth * (c.progress / c.total)
|
||||||
switch i.alignment {
|
switch c.alignment {
|
||||||
case AlignRight: // TODO: Fill from right to left
|
case AlignRight: // TODO: Fill from right to left
|
||||||
case AlignCenter: // TODO: Fill from middle out
|
case AlignCenter: // TODO: Fill from middle out
|
||||||
default: // Fill from left to right
|
default: // Fill from left to right
|
||||||
FillWithChar(i.fullChar, drawX, drawY, drawX+numFull, drawY+(drawHeight-1), i.fg, i.bg)
|
FillWithChar(c.fullChar, drawX, drawY, drawX+numFull, drawY+(drawHeight-1), c.fg, c.bg)
|
||||||
if numFull < drawWidth {
|
if numFull < drawWidth {
|
||||||
FillWithChar(i.emptyChar, drawX+numFull, drawY, drawX+drawWidth-1, drawY+(drawHeight-1), i.fg, i.bg)
|
FillWithChar(c.emptyChar, drawX+numFull, drawY, drawX+drawWidth-1, drawY+(drawHeight-1), c.fg, c.bg)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
*/
|
*/
|
||||||
|
@ -10,126 +10,131 @@ type ScrollFrame struct {
|
|||||||
scrollX, scrollY int
|
scrollX, scrollY int
|
||||||
tabIdx int
|
tabIdx int
|
||||||
fg, bg termbox.Attribute
|
fg, bg termbox.Attribute
|
||||||
|
activeFg, activeBg termbox.Attribute
|
||||||
bordered bool
|
bordered bool
|
||||||
controls []termboxControl
|
controls []termboxControl
|
||||||
|
active bool
|
||||||
}
|
}
|
||||||
|
|
||||||
// CreateScrollFrame creates Scrolling Frame at x, y that is w by h
|
// CreateScrollFrame creates Scrolling Frame at x, y that is w by h
|
||||||
func CreateScrollFrame(x, y, w, h int, fg, bg termbox.Attribute) *ScrollFrame {
|
func CreateScrollFrame(x, y, w, h int, fg, bg termbox.Attribute) *ScrollFrame {
|
||||||
s := ScrollFrame{x: x, y: y, width: w, height: h, fg: fg, bg: bg}
|
c := ScrollFrame{
|
||||||
return &s
|
x: x, y: y, width: w, height: h,
|
||||||
|
fg: fg, bg: bg, activeFg: fg, activeBg: bg,
|
||||||
|
}
|
||||||
|
return &c
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetID returns this control's ID
|
// GetID returns this control's ID
|
||||||
func (i *ScrollFrame) GetID() string { return i.id }
|
func (c *ScrollFrame) GetID() string { return c.id }
|
||||||
|
|
||||||
// SetID sets this control's ID
|
// SetID sets this control's ID
|
||||||
func (i *ScrollFrame) SetID(newID string) {
|
func (c *ScrollFrame) SetID(newID string) {
|
||||||
i.id = newID
|
c.id = newID
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetX returns the x position of the scroll frame
|
// GetX returns the x position of the scroll frame
|
||||||
func (i *ScrollFrame) GetX() int { return i.x }
|
func (c *ScrollFrame) GetX() int { return c.x }
|
||||||
|
|
||||||
// SetX sets the x position of the scroll frame
|
// SetX sets the x position of the scroll frame
|
||||||
func (i *ScrollFrame) SetX(x int) {
|
func (c *ScrollFrame) SetX(x int) {
|
||||||
i.x = x
|
c.x = x
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetY returns the y position of the scroll frame
|
// GetY returns the y position of the scroll frame
|
||||||
func (i *ScrollFrame) GetY() int { return i.y }
|
func (c *ScrollFrame) GetY() int { return c.y }
|
||||||
|
|
||||||
// SetY sets the y position of the scroll frame
|
// SetY sets the y position of the scroll frame
|
||||||
func (i *ScrollFrame) SetY(y int) {
|
func (c *ScrollFrame) SetY(y int) {
|
||||||
i.y = y
|
c.y = y
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetWidth returns the current width of the scroll frame
|
// GetWidth returns the current width of the scroll frame
|
||||||
func (i *ScrollFrame) GetWidth() int { return i.width }
|
func (c *ScrollFrame) GetWidth() int { return c.width }
|
||||||
|
|
||||||
// SetWidth sets the current width of the scroll frame
|
// SetWidth sets the current width of the scroll frame
|
||||||
func (i *ScrollFrame) SetWidth(w int) {
|
func (c *ScrollFrame) SetWidth(w int) {
|
||||||
i.width = w
|
c.width = w
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetHeight returns the current height of the scroll frame
|
// GetHeight returns the current height of the scroll frame
|
||||||
func (i *ScrollFrame) GetHeight() int { return i.height }
|
func (c *ScrollFrame) GetHeight() int { return c.height }
|
||||||
|
|
||||||
// SetHeight sets the current height of the scroll frame
|
// SetHeight sets the current height of the scroll frame
|
||||||
func (i *ScrollFrame) SetHeight(h int) {
|
func (c *ScrollFrame) SetHeight(h int) {
|
||||||
i.height = h
|
c.height = h
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetFgColor returns the foreground color
|
// GetFgColor returns the foreground color
|
||||||
func (i *ScrollFrame) GetFgColor() termbox.Attribute { return i.fg }
|
func (c *ScrollFrame) GetFgColor() termbox.Attribute { return c.fg }
|
||||||
|
|
||||||
// SetFgColor sets the foreground color
|
// SetFgColor sets the foreground color
|
||||||
func (i *ScrollFrame) SetFgColor(fg termbox.Attribute) {
|
func (c *ScrollFrame) SetFgColor(fg termbox.Attribute) {
|
||||||
i.fg = fg
|
c.fg = fg
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetBgColor returns the background color
|
// GetBgColor returns the background color
|
||||||
func (i *ScrollFrame) GetBgColor() termbox.Attribute { return i.bg }
|
func (c *ScrollFrame) GetBgColor() termbox.Attribute { return c.bg }
|
||||||
|
|
||||||
// SetBgColor sets the current background color
|
// SetBgColor sets the current background color
|
||||||
func (i *ScrollFrame) SetBgColor(bg termbox.Attribute) {
|
func (c *ScrollFrame) SetBgColor(bg termbox.Attribute) {
|
||||||
i.bg = bg
|
c.bg = bg
|
||||||
}
|
}
|
||||||
|
|
||||||
// IsBordered returns true or false if this scroll frame has a border
|
// IsBordered returns true or false if this scroll frame has a border
|
||||||
func (i *ScrollFrame) IsBordered() bool { return i.bordered }
|
func (c *ScrollFrame) IsBordered() bool { return c.bordered }
|
||||||
|
|
||||||
// SetBordered sets whether we render a border around the scroll frame
|
// SetBordered sets whether we render a border around the scroll frame
|
||||||
func (i *ScrollFrame) SetBordered(b bool) {
|
func (c *ScrollFrame) SetBordered(b bool) {
|
||||||
i.bordered = b
|
c.bordered = b
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetScrollX returns the x distance scrolled
|
// GetScrollX returns the x distance scrolled
|
||||||
func (i *ScrollFrame) GetScrollX() int {
|
func (c *ScrollFrame) GetScrollX() int {
|
||||||
return i.scrollX
|
return c.scrollX
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetScrollY returns the y distance scrolled
|
// GetScrollY returns the y distance scrolled
|
||||||
func (i *ScrollFrame) GetScrollY() int {
|
func (c *ScrollFrame) GetScrollY() int {
|
||||||
return i.scrollY
|
return c.scrollY
|
||||||
}
|
}
|
||||||
|
|
||||||
// ScrollDown scrolls the frame down
|
// ScrollDown scrolls the frame down
|
||||||
func (i *ScrollFrame) ScrollDown() {
|
func (c *ScrollFrame) ScrollDown() {
|
||||||
i.scrollY++
|
c.scrollY++
|
||||||
}
|
}
|
||||||
|
|
||||||
// ScrollUp scrolls the frame up
|
// ScrollUp scrolls the frame up
|
||||||
func (i *ScrollFrame) ScrollUp() {
|
func (c *ScrollFrame) ScrollUp() {
|
||||||
if i.scrollY > 0 {
|
if c.scrollY > 0 {
|
||||||
i.scrollY--
|
c.scrollY--
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// ScrollLeft scrolls the frame left
|
// ScrollLeft scrolls the frame left
|
||||||
func (i *ScrollFrame) ScrollLeft() {
|
func (c *ScrollFrame) ScrollLeft() {
|
||||||
if i.scrollX > 0 {
|
if c.scrollX > 0 {
|
||||||
i.scrollX--
|
c.scrollX--
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// ScrollRight scrolls the frame right
|
// ScrollRight scrolls the frame right
|
||||||
func (i *ScrollFrame) ScrollRight() {
|
func (c *ScrollFrame) ScrollRight() {
|
||||||
i.scrollX++
|
c.scrollX++
|
||||||
}
|
}
|
||||||
|
|
||||||
// AddControl adds a control to the frame
|
// AddControl adds a control to the frame
|
||||||
func (i *ScrollFrame) AddControl(t termboxControl) {
|
func (c *ScrollFrame) AddControl(t termboxControl) {
|
||||||
i.controls = append(i.controls, t)
|
c.controls = append(c.controls, t)
|
||||||
}
|
}
|
||||||
|
|
||||||
// DrawControl figures out the relative position of the control,
|
// DrawControl figures out the relative position of the control,
|
||||||
// sets it, draws it, then resets it.
|
// sets it, draws it, then resets it.
|
||||||
func (i *ScrollFrame) DrawControl(t termboxControl) {
|
func (c *ScrollFrame) DrawControl(t termboxControl) {
|
||||||
if i.IsVisible(t) {
|
if c.IsVisible(t) {
|
||||||
ctlX, ctlY := t.GetX(), t.GetY()
|
ctlX, ctlY := t.GetX(), t.GetY()
|
||||||
t.SetX((i.GetX() + ctlX))
|
t.SetX((c.GetX() + ctlX))
|
||||||
t.SetY((i.GetY() + ctlY))
|
t.SetY((c.GetY() + ctlY))
|
||||||
t.Draw()
|
t.Draw()
|
||||||
t.SetX(ctlX)
|
t.SetX(ctlX)
|
||||||
t.SetY(ctlY)
|
t.SetY(ctlY)
|
||||||
@ -138,35 +143,35 @@ func (i *ScrollFrame) DrawControl(t termboxControl) {
|
|||||||
|
|
||||||
// IsVisible takes a Termbox Control and returns whether
|
// IsVisible takes a Termbox Control and returns whether
|
||||||
// that control would be visible in the frame
|
// that control would be visible in the frame
|
||||||
func (i *ScrollFrame) IsVisible(t termboxControl) bool {
|
func (c *ScrollFrame) IsVisible(t termboxControl) bool {
|
||||||
// Check if any part of t should be visible
|
// Check if any part of t should be visible
|
||||||
cX, cY := t.GetX(), t.GetY()
|
cX, cY := t.GetX(), t.GetY()
|
||||||
if cX+t.GetWidth() >= i.scrollX && cX <= i.scrollX+i.width {
|
if cX+t.GetWidth() >= c.scrollX && cX <= c.scrollX+c.width {
|
||||||
return cY+t.GetHeight() >= i.scrollY && cY <= i.scrollY+i.height
|
return cY+t.GetHeight() >= c.scrollY && cY <= c.scrollY+c.height
|
||||||
}
|
}
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
// HandleEvent accepts the termbox event and returns whether it was consumed
|
// HandleEvent accepts the termbox event and returns whether it was consumed
|
||||||
func (i *ScrollFrame) HandleEvent(event termbox.Event) bool {
|
func (c *ScrollFrame) HandleEvent(event termbox.Event) bool {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
// DrawToStrings generates a slice of strings with what should
|
// DrawToStrings generates a slice of strings with what should
|
||||||
// be drawn to the screen
|
// be drawn to the screen
|
||||||
func (i *ScrollFrame) DrawToStrings() []string {
|
func (c *ScrollFrame) DrawToStrings() []string {
|
||||||
return []string{}
|
return []string{}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Draw outputs the Scoll Frame on the screen
|
// Draw outputs the Scoll Frame on the screen
|
||||||
func (i *ScrollFrame) Draw() {
|
func (c *ScrollFrame) Draw() {
|
||||||
maxWidth := i.width
|
maxWidth := c.width
|
||||||
maxHeight := i.height
|
maxHeight := c.height
|
||||||
x, y := i.x, i.y
|
x, y := c.x, c.y
|
||||||
startX := i.x
|
startX := c.x
|
||||||
startY := i.y
|
startY := c.y
|
||||||
if i.bordered {
|
if c.bordered {
|
||||||
DrawBorder(i.x, i.y, i.x+i.width, i.y+i.height, i.fg, i.bg)
|
DrawBorder(c.x, c.y, c.x+c.width, c.y+c.height, c.fg, c.bg)
|
||||||
maxWidth--
|
maxWidth--
|
||||||
maxHeight--
|
maxHeight--
|
||||||
x++
|
x++
|
||||||
@ -174,7 +179,7 @@ func (i *ScrollFrame) Draw() {
|
|||||||
startX++
|
startX++
|
||||||
startY++
|
startY++
|
||||||
}
|
}
|
||||||
for idx := range i.controls {
|
for idx := range c.controls {
|
||||||
i.DrawControl(i.controls[idx])
|
c.DrawControl(c.controls[idx])
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
package termboxUtil
|
package termboxUtil
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
@ -27,6 +28,10 @@ type termboxControl interface {
|
|||||||
SetTabSkip(bool)
|
SetTabSkip(bool)
|
||||||
IsTabSkipped() bool
|
IsTabSkipped() bool
|
||||||
Draw()
|
Draw()
|
||||||
|
SetActive(bool)
|
||||||
|
IsActive() bool
|
||||||
|
SetActiveFgColor(termbox.Attribute)
|
||||||
|
SetActiveBgColor(termbox.Attribute)
|
||||||
}
|
}
|
||||||
|
|
||||||
// TextAlignment is an int value for how we're aligning text
|
// TextAlignment is an int value for how we're aligning text
|
||||||
@ -106,17 +111,67 @@ func FillWithChar(r rune, x1, y1, x2, y2 int, fg termbox.Attribute, bg termbox.A
|
|||||||
}
|
}
|
||||||
|
|
||||||
// DrawBorder Draw a border around the area inside x1,y1 -> x2, y2
|
// DrawBorder Draw a border around the area inside x1,y1 -> x2, y2
|
||||||
func DrawBorder(x1, y1, x2, y2 int, fg termbox.Attribute, bg termbox.Attribute) {
|
func DrawBorder(x1, y1, x2, y2 int, fg, bg termbox.Attribute) {
|
||||||
termbox.SetCell(x1, y1, '+', fg, bg)
|
termbox.SetCell(x1, y1, '╔', fg, bg)
|
||||||
FillWithChar('-', x1+1, y1, x2-1, y1, fg, bg)
|
FillWithChar('═', x1+1, y1, x2-1, y1, fg, bg)
|
||||||
termbox.SetCell(x2, y1, '+', fg, bg)
|
termbox.SetCell(x2, y1, '╗', fg, bg)
|
||||||
|
|
||||||
FillWithChar('|', x1, y1+1, x1, y2-1, fg, bg)
|
FillWithChar('║', x1, y1+1, x1, y2-1, fg, bg)
|
||||||
FillWithChar('|', x2, y1+1, x2, y2-1, fg, bg)
|
FillWithChar('║', x2, y1+1, x2, y2-1, fg, bg)
|
||||||
|
|
||||||
termbox.SetCell(x1, y2, '+', fg, bg)
|
termbox.SetCell(x1, y2, '╚', fg, bg)
|
||||||
FillWithChar('-', x1+1, y2, x2-1, y2, fg, bg)
|
FillWithChar('═', x1+1, y2, x2-1, y2, fg, bg)
|
||||||
termbox.SetCell(x2, y2, '+', fg, bg)
|
termbox.SetCell(x2, y2, '╝', fg, bg)
|
||||||
|
}
|
||||||
|
|
||||||
|
func DrawBorderWithPct(x1, y1, x2, y2 int, pct float64, fg, bg termbox.Attribute) {
|
||||||
|
termbox.SetCell(x1, y1, '╔', fg, bg)
|
||||||
|
|
||||||
|
FillWithChar('═', x1+1, y1, x2-1, y1, fg, bg)
|
||||||
|
termbox.SetCell(x2, y1, '╗', fg, bg)
|
||||||
|
|
||||||
|
FillWithChar('║', x1, y1+1, x1, y2-1, fg, bg)
|
||||||
|
FillWithChar('║', x2, y1+1, x2, y2-1, fg, bg)
|
||||||
|
// Now the percent indicator
|
||||||
|
pctY := int(((float64(y2)-float64(y1)-2)*pct)+float64(y1)) + 1
|
||||||
|
termbox.SetCell(x2, pctY, '▒', fg, bg)
|
||||||
|
|
||||||
|
termbox.SetCell(x1, y2, '╚', fg, bg)
|
||||||
|
FillWithChar('═', x1+1, y2, x2-1, y2, fg, bg)
|
||||||
|
termbox.SetCell(x2, y2, '╝', fg, bg)
|
||||||
|
}
|
||||||
|
|
||||||
|
func DrawBorderWithTitle(x1, y1, x2, y2 int, title string, fg, bg termbox.Attribute) {
|
||||||
|
termbox.SetCell(x1, y1, '╔', fg, bg)
|
||||||
|
|
||||||
|
DrawStringAtPoint(title, x1+1, y1, fg, bg)
|
||||||
|
FillWithChar('═', x1+len(title)+1, y1, x2-1, y1, fg, bg)
|
||||||
|
termbox.SetCell(x2, y1, '╗', fg, bg)
|
||||||
|
|
||||||
|
FillWithChar('║', x1, y1+1, x1, y2-1, fg, bg)
|
||||||
|
FillWithChar('║', x2, y1+1, x2, y2-1, fg, bg)
|
||||||
|
|
||||||
|
termbox.SetCell(x1, y2, '╚', fg, bg)
|
||||||
|
FillWithChar('═', x1+1, y2, x2-1, y2, fg, bg)
|
||||||
|
termbox.SetCell(x2, y2, '╝', fg, bg)
|
||||||
|
}
|
||||||
|
|
||||||
|
func DrawBorderWithTitleAndPct(x1, y1, x2, y2 int, title string, pct float64, fg, bg termbox.Attribute) {
|
||||||
|
termbox.SetCell(x1, y1, '╔', fg, bg)
|
||||||
|
|
||||||
|
DrawStringAtPoint(title, x1+1, y1, fg, bg)
|
||||||
|
FillWithChar('═', x1+len(title)+1, y1, x2-1, y1, fg, bg)
|
||||||
|
termbox.SetCell(x2, y1, '╗', fg, bg)
|
||||||
|
|
||||||
|
FillWithChar('║', x1, y1+1, x1, y2-1, fg, bg)
|
||||||
|
FillWithChar('║', x2, y1+1, x2, y2-1, fg, bg)
|
||||||
|
// Now the percent indicator
|
||||||
|
pctY := int(((float64(y2)-float64(y1)-2)*pct)+float64(y1)) + 1
|
||||||
|
termbox.SetCell(x2, pctY, '▒', fg, bg)
|
||||||
|
|
||||||
|
termbox.SetCell(x1, y2, '╚', fg, bg)
|
||||||
|
FillWithChar('═', x1+1, y2, x2-1, y2, fg, bg)
|
||||||
|
termbox.SetCell(x2, y2, '╝', fg, bg)
|
||||||
}
|
}
|
||||||
|
|
||||||
// AlignText Aligns the text txt within width characters using the specified alignment
|
// AlignText Aligns the text txt within width characters using the specified alignment
|
||||||
@ -148,4 +203,19 @@ func AlignTextWithFill(txt string, width int, align TextAlignment, fill rune) st
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func ToLabel(c termboxControl) (*Label, error) {
|
||||||
|
v, ok := c.(*Label)
|
||||||
|
if ok {
|
||||||
|
return v, nil
|
||||||
|
}
|
||||||
|
return nil, errors.New("Control isn't a Label")
|
||||||
|
}
|
||||||
|
func ToInputField(c termboxControl) (*InputField, error) {
|
||||||
|
v, ok := c.(*InputField)
|
||||||
|
if ok {
|
||||||
|
return v, nil
|
||||||
|
}
|
||||||
|
return nil, errors.New("Control isn't an Input Field")
|
||||||
|
}
|
||||||
|
|
||||||
/* More advanced things are in their respective files */
|
/* More advanced things are in their respective files */
|
||||||
|
Loading…
Reference in New Issue
Block a user