Initial Commit
This commit is contained in:
@@ -22,7 +22,7 @@ THE SOFTWARE.
|
|||||||
package widgets
|
package widgets
|
||||||
|
|
||||||
import (
|
import (
|
||||||
h "git.bullercodeworks.com/brian/dhcli/helpers"
|
h "git.bullercodeworks.com/brian/tcell-widgets/helpers"
|
||||||
"github.com/gdamore/tcell"
|
"github.com/gdamore/tcell"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|||||||
@@ -25,7 +25,7 @@ import (
|
|||||||
"fmt"
|
"fmt"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
h "git.bullercodeworks.com/brian/dhcli/helpers"
|
h "git.bullercodeworks.com/brian/tcell-widgets/helpers"
|
||||||
"github.com/gdamore/tcell"
|
"github.com/gdamore/tcell"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|||||||
@@ -24,7 +24,7 @@ package widgets
|
|||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
|
|
||||||
h "git.bullercodeworks.com/brian/dhcli/helpers"
|
h "git.bullercodeworks.com/brian/tcell-widgets/helpers"
|
||||||
"github.com/gdamore/tcell"
|
"github.com/gdamore/tcell"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|||||||
2
field.go
2
field.go
@@ -24,7 +24,7 @@ package widgets
|
|||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
|
|
||||||
h "git.bullercodeworks.com/brian/dhcli/helpers"
|
h "git.bullercodeworks.com/brian/tcell-widgets/helpers"
|
||||||
"github.com/gdamore/tcell"
|
"github.com/gdamore/tcell"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|||||||
13
go.mod
Normal file
13
go.mod
Normal file
@@ -0,0 +1,13 @@
|
|||||||
|
module git.bullercodeworks.com/brian/tcell-widgets
|
||||||
|
|
||||||
|
go 1.24.2
|
||||||
|
|
||||||
|
require github.com/gdamore/tcell v1.4.0
|
||||||
|
|
||||||
|
require (
|
||||||
|
github.com/gdamore/encoding v1.0.0 // indirect
|
||||||
|
github.com/lucasb-eyer/go-colorful v1.0.3 // indirect
|
||||||
|
github.com/mattn/go-runewidth v0.0.7 // indirect
|
||||||
|
golang.org/x/sys v0.0.0-20190626150813-e07cf5db2756 // indirect
|
||||||
|
golang.org/x/text v0.3.0 // indirect
|
||||||
|
)
|
||||||
12
go.sum
Normal file
12
go.sum
Normal file
@@ -0,0 +1,12 @@
|
|||||||
|
github.com/gdamore/encoding v1.0.0 h1:+7OoQ1Bc6eTm5niUzBa0Ctsh6JbMW6Ra+YNuAtDBdko=
|
||||||
|
github.com/gdamore/encoding v1.0.0/go.mod h1:alR0ol34c49FCSBLjhosxzcPHQbf2trDkoo5dl+VrEg=
|
||||||
|
github.com/gdamore/tcell v1.4.0 h1:vUnHwJRvcPQa3tzi+0QI4U9JINXYJlOz9yiaiPQ2wMU=
|
||||||
|
github.com/gdamore/tcell v1.4.0/go.mod h1:vxEiSDZdW3L+Uhjii9c3375IlDmR05bzxY404ZVSMo0=
|
||||||
|
github.com/lucasb-eyer/go-colorful v1.0.3 h1:QIbQXiugsb+q10B+MI+7DI1oQLdmnep86tWFlaaUAac=
|
||||||
|
github.com/lucasb-eyer/go-colorful v1.0.3/go.mod h1:R4dSotOR9KMtayYi1e77YzuveK+i7ruzyGqttikkLy0=
|
||||||
|
github.com/mattn/go-runewidth v0.0.7 h1:Ei8KR0497xHyKJPAv59M1dkC+rOZCMBJ+t3fZ+twI54=
|
||||||
|
github.com/mattn/go-runewidth v0.0.7/go.mod h1:H031xJmbD/WCDINGzjvQ9THkh0rPKHF+m2gUSrubnMI=
|
||||||
|
golang.org/x/sys v0.0.0-20190626150813-e07cf5db2756 h1:9nuHUbU8dRnRRfj9KjWUVrJeoexdbeMjttk6Oh1rD10=
|
||||||
|
golang.org/x/sys v0.0.0-20190626150813-e07cf5db2756/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
|
golang.org/x/text v0.3.0 h1:g61tztE5qeGQ89tm6NTjjM9VPIm088od1l6aSorWRWg=
|
||||||
|
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||||
97
helpers/event_helpers.go
Normal file
97
helpers/event_helpers.go
Normal file
@@ -0,0 +1,97 @@
|
|||||||
|
/*
|
||||||
|
Copyright © Brian Buller <brian@bullercodeworks.com>
|
||||||
|
|
||||||
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
of this software and associated documentation files (the "Software"), to deal
|
||||||
|
in the Software without restriction, including without limitation the rights
|
||||||
|
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
copies of the Software, and to permit persons to whom the Software is
|
||||||
|
furnished to do so, subject to the following conditions:
|
||||||
|
|
||||||
|
The above copyright notice and this permission notice shall be included in
|
||||||
|
all copies or substantial portions of the Software.
|
||||||
|
|
||||||
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||||
|
THE SOFTWARE.
|
||||||
|
*/
|
||||||
|
package helpers
|
||||||
|
|
||||||
|
import (
|
||||||
|
"github.com/gdamore/tcell"
|
||||||
|
)
|
||||||
|
|
||||||
|
func IsKeyEvent(e tcell.Event) bool {
|
||||||
|
_, ok := e.(*tcell.EventKey)
|
||||||
|
return ok
|
||||||
|
}
|
||||||
|
|
||||||
|
func IsKey(e tcell.EventKey, opts ...tcell.Key) bool {
|
||||||
|
for i := range opts {
|
||||||
|
if e.Key() == opts[i] {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
func IsBS(e tcell.EventKey) bool {
|
||||||
|
return IsKey(e, tcell.KeyBackspace, tcell.KeyBackspace2)
|
||||||
|
}
|
||||||
|
|
||||||
|
func KeyIsDisplayable(ev tcell.EventKey) bool {
|
||||||
|
return KeyIsSpace(ev) || KeyIsAlphaNumeric(ev) || KeyIsSymbol(ev)
|
||||||
|
}
|
||||||
|
|
||||||
|
func KeyIsSpace(ev tcell.EventKey) bool {
|
||||||
|
r := ev.Rune()
|
||||||
|
return r == ' '
|
||||||
|
}
|
||||||
|
|
||||||
|
func KeyIsAlphaNumeric(ev tcell.EventKey) bool {
|
||||||
|
return KeyIsAlpha(ev) || KeyIsNumeric(ev)
|
||||||
|
}
|
||||||
|
|
||||||
|
func KeyIsAlpha(ev tcell.EventKey) bool {
|
||||||
|
r := ev.Rune()
|
||||||
|
return (r >= 'a' && r <= 'z') || (r >= 'A' && r <= 'Z')
|
||||||
|
}
|
||||||
|
|
||||||
|
// KeyIsNumeric Returns whether the event is a
|
||||||
|
// numeric Key press
|
||||||
|
func KeyIsNumeric(ev tcell.EventKey) bool {
|
||||||
|
r := ev.Rune()
|
||||||
|
return (r >= '0' && r <= '9')
|
||||||
|
}
|
||||||
|
|
||||||
|
// KeyIsSymbol Returns whether the event is a
|
||||||
|
// symbol Key press
|
||||||
|
func KeyIsSymbol(ev tcell.EventKey) bool {
|
||||||
|
symbols := []rune{
|
||||||
|
'!', '@', '#', '$', '%', '^', '&', '*',
|
||||||
|
'(', ')', '-', '_', '=', '+', '[', ']', '{', '}', '|',
|
||||||
|
';', ':', '"', '\'', ',', '<', '.', '>', '/', '?', '`', '~', '\\',
|
||||||
|
}
|
||||||
|
k := ev.Rune()
|
||||||
|
for i := range symbols {
|
||||||
|
if k == symbols[i] {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
func HandleKeys(ev tcell.EventKey, keys map[tcell.Key]func() bool) bool {
|
||||||
|
for k, v := range keys {
|
||||||
|
if ev.Key() == k {
|
||||||
|
return v()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
func HasCtrl(ev *tcell.EventKey) bool { return ev.Modifiers()&tcell.ModCtrl == tcell.ModCtrl }
|
||||||
50
helpers/number_helpers.go
Normal file
50
helpers/number_helpers.go
Normal file
@@ -0,0 +1,50 @@
|
|||||||
|
/*
|
||||||
|
Copyright © Brian Buller <brian@bullercodeworks.com>
|
||||||
|
|
||||||
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
of this software and associated documentation files (the "Software"), to deal
|
||||||
|
in the Software without restriction, including without limitation the rights
|
||||||
|
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
copies of the Software, and to permit persons to whom the Software is
|
||||||
|
furnished to do so, subject to the following conditions:
|
||||||
|
|
||||||
|
The above copyright notice and this permission notice shall be included in
|
||||||
|
all copies or substantial portions of the Software.
|
||||||
|
|
||||||
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||||
|
THE SOFTWARE.
|
||||||
|
*/
|
||||||
|
package helpers
|
||||||
|
|
||||||
|
import "cmp"
|
||||||
|
|
||||||
|
func Max[E cmp.Ordered](of ...E) E {
|
||||||
|
var m E
|
||||||
|
if len(of) > 0 {
|
||||||
|
m = of[0]
|
||||||
|
}
|
||||||
|
for i := range of {
|
||||||
|
if of[i] > m {
|
||||||
|
m = of[i]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return m
|
||||||
|
}
|
||||||
|
|
||||||
|
func Min[E cmp.Ordered](of ...E) E {
|
||||||
|
var m E
|
||||||
|
if len(of) > 0 {
|
||||||
|
m = of[0]
|
||||||
|
}
|
||||||
|
for i := range of {
|
||||||
|
if of[i] < m {
|
||||||
|
m = of[i]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return m
|
||||||
|
}
|
||||||
180
helpers/tcell_borders.go
Normal file
180
helpers/tcell_borders.go
Normal file
@@ -0,0 +1,180 @@
|
|||||||
|
/*
|
||||||
|
Copyright © Brian Buller <brian@bullercodeworks.com>
|
||||||
|
|
||||||
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
of this software and associated documentation files (the "Software"), to deal
|
||||||
|
in the Software without restriction, including without limitation the rights
|
||||||
|
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
copies of the Software, and to permit persons to whom the Software is
|
||||||
|
furnished to do so, subject to the following conditions:
|
||||||
|
|
||||||
|
The above copyright notice and this permission notice shall be included in
|
||||||
|
all copies or substantial portions of the Software.
|
||||||
|
|
||||||
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||||
|
THE SOFTWARE.
|
||||||
|
*/
|
||||||
|
package helpers
|
||||||
|
|
||||||
|
import (
|
||||||
|
"github.com/gdamore/tcell"
|
||||||
|
)
|
||||||
|
|
||||||
|
/*
|
||||||
|
The Border template starts at North and goes clockwise:
|
||||||
|
─, ┐, │, ┘, ─, └, │, ┌
|
||||||
|
Then it has the crossing lines:
|
||||||
|
├, ─, ┤, ┬, │, ┴
|
||||||
|
So a full border might look like this:
|
||||||
|
|
||||||
|
[]rune{
|
||||||
|
'─', '┐', '│', '┘', '─', '└', '│', '┌',
|
||||||
|
'├', '─', '┤', '┬', '│', '┴',
|
||||||
|
}
|
||||||
|
|
||||||
|
U+250x ─ ━ │ ┃ ┄ ┅ ┆ ┇ ┈ ┉ ┊ ┋ ┌ ┍ ┎ ┏
|
||||||
|
U+251x ┐ ┑ ┒ ┓ └ ┕ ┖ ┗ ┘ ┙ ┚ ┛ ├ ┝ ┞ ┟
|
||||||
|
U+252x ┠ ┡ ┢ ┣ ┤ ┥ ┦ ┧ ┨ ┩ ┪ ┫ ┬ ┭ ┮ ┯
|
||||||
|
U+253x ┰ ┱ ┲ ┳ ┴ ┵ ┶ ┷ ┸ ┹ ┺ ┻ ┼ ┽ ┾ ┿
|
||||||
|
U+254x ╀ ╁ ╂ ╃ ╄ ╅ ╆ ╇ ╈ ╉ ╊ ╋ ╌ ╍ ╎ ╏
|
||||||
|
U+255x ═ ║ ╒ ╓ ╔ ╕ ╖ ╗ ╘ ╙ ╚ ╛ ╜ ╝ ╞ ╟
|
||||||
|
U+256x ╠ ╡ ╢ ╣ ╤ ╥ ╦ ╧ ╨ ╩ ╪ ╫ ╬ ╭ ╮ ╯
|
||||||
|
U+257x ╰ ╱ ╲ ╳ ╴ ╵ ╶ ╷ ╸ ╹ ╺ ╻ ╼ ╽ ╾ ╿
|
||||||
|
*/
|
||||||
|
const (
|
||||||
|
BRD_N = iota
|
||||||
|
BRD_NE
|
||||||
|
BRD_E
|
||||||
|
BRD_SE
|
||||||
|
BRD_S
|
||||||
|
BRD_SW
|
||||||
|
BRD_W
|
||||||
|
BRD_NW
|
||||||
|
BRD_CROSS_E
|
||||||
|
BRD_CROSS_H
|
||||||
|
BRD_CROSS_W
|
||||||
|
BRD_CROSS_S
|
||||||
|
BRD_CROSS_V
|
||||||
|
BRD_CROSS_N
|
||||||
|
BRD_CROSS_ALL
|
||||||
|
)
|
||||||
|
|
||||||
|
var (
|
||||||
|
BRD_SIMPLE = []rune{'─', '┐', '│', '┘', '─', '└', '│', '┌', '├', '─', '┤', '┬', '│', '┴', '┼'}
|
||||||
|
BRD_CSIMPLE = []rune{'─', '╮', '│', '╯', '─', '╰', '│', '╭', '├', '─', '┤', '┬', '│', '┴', '┼'}
|
||||||
|
BRD_DOUBLE = []rune{'═', '╗', '║', '╝', '═', '╚', '║', '╔', '╠', '═', '╣', '╦', '║', '╩', '╬'}
|
||||||
|
BRD_CSIMPLE_DOTSPLIT = []rune{'─', '╮', '│', '╯', '─', '╰', '│', '╭', '├', '┄', '┤', '┬', '┊', '┴', '┼'}
|
||||||
|
BRD_BLOCK_SHADOW = []rune{'░', '░', '▓', '▓', '▓', '░', '░', '░', '░', '░', '░', '░', '░', '░', '░'}
|
||||||
|
)
|
||||||
|
|
||||||
|
// Horizontal/Vertical Rules
|
||||||
|
const (
|
||||||
|
RULE_START = iota
|
||||||
|
RULE_FILL
|
||||||
|
RULE_END
|
||||||
|
)
|
||||||
|
|
||||||
|
var (
|
||||||
|
HRULE_SIMPLE = []rune{'├', '─', '┤'}
|
||||||
|
HRULE_DOUBLE = []rune{'╠', '═', '╣'}
|
||||||
|
|
||||||
|
VRULE_SIMPLE = []rune{'┬', '│', '┴'}
|
||||||
|
VRULE_DOUBLE = []rune{'╦', '║', '╩'}
|
||||||
|
)
|
||||||
|
|
||||||
|
func ValidateBorder(border []rune) []rune {
|
||||||
|
for len(border) < BRD_CROSS_ALL+1 {
|
||||||
|
border = append(border, ' ')
|
||||||
|
}
|
||||||
|
return border
|
||||||
|
}
|
||||||
|
|
||||||
|
func ValidateRule(rule []rune) []rune {
|
||||||
|
for len(rule) < RULE_END+1 {
|
||||||
|
rule = append(rule, ' ')
|
||||||
|
}
|
||||||
|
return rule
|
||||||
|
}
|
||||||
|
|
||||||
|
func HRule(x1, x2, y int, rule []rune, s tcell.Style, screen tcell.Screen) {
|
||||||
|
Fill(x1, y, x2, y, rule[RULE_FILL], s, screen)
|
||||||
|
screen.SetContent(x1, y, rule[RULE_START], nil, s)
|
||||||
|
screen.SetContent(x2, y, rule[RULE_END], nil, s)
|
||||||
|
}
|
||||||
|
|
||||||
|
func VRule(x, y1, y2 int, rule []rune, s tcell.Style, screen tcell.Screen) {
|
||||||
|
Fill(x, y1, x, y2, rule[RULE_FILL], s, screen)
|
||||||
|
screen.SetContent(x, y1, rule[RULE_START], nil, s)
|
||||||
|
screen.SetContent(x, y2, rule[RULE_END], nil, s)
|
||||||
|
}
|
||||||
|
|
||||||
|
func BorderFilled(x1, y1, x2, y2 int, border []rune, s tcell.Style, screen tcell.Screen) {
|
||||||
|
Border(x1, y1, x2, y2, border, s, screen)
|
||||||
|
Fill(x1+1, y1+1, x2-1, y2-1, ' ', s, screen)
|
||||||
|
}
|
||||||
|
|
||||||
|
func Border(x1, y1, x2, y2 int, border []rune, s tcell.Style, screen tcell.Screen) {
|
||||||
|
border = ValidateBorder(border)
|
||||||
|
Fill(x1+1, y1, x2-1, y1, border[BRD_N], s, screen)
|
||||||
|
Fill(x2, y1+1, x2, y2-1, border[BRD_E], s, screen)
|
||||||
|
Fill(x1+1, y2, x2-1, y2, border[BRD_S], s, screen)
|
||||||
|
Fill(x1, y1+1, x1, y2-1, border[BRD_W], s, screen)
|
||||||
|
screen.SetContent(x1, y1, border[BRD_NW], nil, s)
|
||||||
|
screen.SetContent(x2, y1, border[BRD_NE], nil, s)
|
||||||
|
screen.SetContent(x1, y2, border[BRD_SW], nil, s)
|
||||||
|
screen.SetContent(x2, y2, border[BRD_SE], nil, s)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TitledBorderFilled(x1, y1, x2, y2 int, ttl string, border []rune, s tcell.Style, screen tcell.Screen) {
|
||||||
|
TitledBorder(x1, y1, x2, y2, ttl, border, s, screen)
|
||||||
|
Fill(x1+1, y1+1, x2-1, y2-1, ' ', s, screen)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TitledBorder(x1, y1, x2, y2 int, ttl string, border []rune, s tcell.Style, screen tcell.Screen) {
|
||||||
|
if ttl == "" {
|
||||||
|
Border(x1, y1, x2, y2, border, s, screen)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
border = ValidateBorder(border)
|
||||||
|
ttlLength, maxTtlLength := len(ttl), (x2 - x1 - 2)
|
||||||
|
if ttlLength > maxTtlLength {
|
||||||
|
if maxTtlLength-3 > 0 {
|
||||||
|
ttlLength = maxTtlLength
|
||||||
|
ttl = ttl[0:maxTtlLength-3] + "..."
|
||||||
|
}
|
||||||
|
}
|
||||||
|
DrawText(x1+1, y1, ttl, s, screen)
|
||||||
|
Fill(x1+1+ttlLength, y1, x2-1, y1, border[BRD_N], s, screen)
|
||||||
|
Fill(x2, y1+1, x2, y2-1, border[BRD_E], s, screen)
|
||||||
|
Fill(x1+1, y2, x2-1, y2, border[BRD_S], s, screen)
|
||||||
|
Fill(x1, y1+1, x1, y2-1, border[BRD_W], s, screen)
|
||||||
|
screen.SetContent(x1, y1, border[BRD_NW], nil, s)
|
||||||
|
screen.SetContent(x2, y1, border[BRD_NE], nil, s)
|
||||||
|
screen.SetContent(x1, y2, border[BRD_SW], nil, s)
|
||||||
|
screen.SetContent(x2, y2, border[BRD_SE], nil, s)
|
||||||
|
}
|
||||||
|
|
||||||
|
func BorderHasEast(border []rune) bool {
|
||||||
|
border = ValidateBorder(border)
|
||||||
|
return border[BRD_E] != ' ' || border[BRD_NE] != ' ' || border[BRD_SE] != ' '
|
||||||
|
}
|
||||||
|
|
||||||
|
func BorderHasWest(border []rune) bool {
|
||||||
|
border = ValidateBorder(border)
|
||||||
|
return border[BRD_W] != ' ' || border[BRD_NW] != ' ' || border[BRD_SW] != ' '
|
||||||
|
}
|
||||||
|
|
||||||
|
func BorderHasNorth(border []rune) bool {
|
||||||
|
border = ValidateBorder(border)
|
||||||
|
return border[BRD_N] != ' ' || border[BRD_NE] != ' ' || border[BRD_NW] != ' '
|
||||||
|
}
|
||||||
|
|
||||||
|
func BorderHasSouth(border []rune) bool {
|
||||||
|
border = ValidateBorder(border)
|
||||||
|
return border[BRD_S] != ' ' || border[BRD_NW] != ' ' || border[BRD_SW] != ' '
|
||||||
|
}
|
||||||
45
helpers/tcell_helpers.go
Normal file
45
helpers/tcell_helpers.go
Normal file
@@ -0,0 +1,45 @@
|
|||||||
|
/*
|
||||||
|
Copyright © Brian Buller <brian@bullercodeworks.com>
|
||||||
|
|
||||||
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
of this software and associated documentation files (the "Software"), to deal
|
||||||
|
in the Software without restriction, including without limitation the rights
|
||||||
|
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
copies of the Software, and to permit persons to whom the Software is
|
||||||
|
furnished to do so, subject to the following conditions:
|
||||||
|
|
||||||
|
The above copyright notice and this permission notice shall be included in
|
||||||
|
all copies or substantial portions of the Software.
|
||||||
|
|
||||||
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||||
|
THE SOFTWARE.
|
||||||
|
*/
|
||||||
|
package helpers
|
||||||
|
|
||||||
|
import "github.com/gdamore/tcell"
|
||||||
|
|
||||||
|
func DrawText(x, y int, text string, style tcell.Style, screen tcell.Screen) {
|
||||||
|
for _, r := range text {
|
||||||
|
screen.SetContent(x, y, r, nil, style)
|
||||||
|
x++
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func Fill(x1, y1, x2, y2 int, r rune, style tcell.Style, screen tcell.Screen) {
|
||||||
|
if x1 > x2 {
|
||||||
|
x1, x2 = x2, x1
|
||||||
|
}
|
||||||
|
if y1 > y2 {
|
||||||
|
y1, y2 = y2, y1
|
||||||
|
}
|
||||||
|
for x := x1; x <= x2; x++ {
|
||||||
|
for y := y1; y <= y2; y++ {
|
||||||
|
screen.SetContent(x, y, r, nil, style)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
159
helpers/text_helpers.go
Normal file
159
helpers/text_helpers.go
Normal file
@@ -0,0 +1,159 @@
|
|||||||
|
/*
|
||||||
|
Copyright © Brian Buller <brian@bullercodeworks.com>
|
||||||
|
|
||||||
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
of this software and associated documentation files (the "Software"), to deal
|
||||||
|
in the Software without restriction, including without limitation the rights
|
||||||
|
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
copies of the Software, and to permit persons to whom the Software is
|
||||||
|
furnished to do so, subject to the following conditions:
|
||||||
|
|
||||||
|
The above copyright notice and this permission notice shall be included in
|
||||||
|
all copies or substantial portions of the Software.
|
||||||
|
|
||||||
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||||
|
THE SOFTWARE.
|
||||||
|
*/
|
||||||
|
package helpers
|
||||||
|
|
||||||
|
import (
|
||||||
|
"bytes"
|
||||||
|
"fmt"
|
||||||
|
"strings"
|
||||||
|
"unicode"
|
||||||
|
)
|
||||||
|
|
||||||
|
type Align int
|
||||||
|
|
||||||
|
const (
|
||||||
|
AlignLeft = iota
|
||||||
|
AlignCenter
|
||||||
|
AlignRight
|
||||||
|
)
|
||||||
|
|
||||||
|
func Center(txt string, width int) string {
|
||||||
|
if len(txt) >= width {
|
||||||
|
// Trim from beg & end until width
|
||||||
|
for len(txt) > width {
|
||||||
|
txt = txt[:len(txt)-1]
|
||||||
|
if len(txt) > width {
|
||||||
|
txt = txt[1:]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return txt
|
||||||
|
}
|
||||||
|
for len(txt) < width {
|
||||||
|
txt = fmt.Sprintf(" %s", txt)
|
||||||
|
if len(txt) < width {
|
||||||
|
txt = fmt.Sprintf("%s ", txt)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return txt
|
||||||
|
}
|
||||||
|
|
||||||
|
func CenterBetween(txt, left, right string, width int) string {
|
||||||
|
if len(txt) >= width {
|
||||||
|
return Center(txt, width)
|
||||||
|
}
|
||||||
|
for len(txt) < width {
|
||||||
|
txt = fmt.Sprintf("%s%s", left, txt)
|
||||||
|
if len(txt) < width {
|
||||||
|
txt = fmt.Sprintf("%s%s", txt, right)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return txt
|
||||||
|
}
|
||||||
|
|
||||||
|
func PadR(txt string, width int) string {
|
||||||
|
if len(txt) < width {
|
||||||
|
txt = fmt.Sprintf("%s%s", txt, strings.Repeat(" ", width-len(txt)))
|
||||||
|
}
|
||||||
|
return txt
|
||||||
|
}
|
||||||
|
|
||||||
|
func PadL(txt string, width int) string {
|
||||||
|
if len(txt) < width {
|
||||||
|
txt = fmt.Sprintf("%s%s", strings.Repeat(" ", width-len(txt)), txt)
|
||||||
|
}
|
||||||
|
return txt
|
||||||
|
}
|
||||||
|
|
||||||
|
// WrapText inserts new lines to make the text
|
||||||
|
// wrap at width 'w'
|
||||||
|
func WrapText(txt string, w int) string {
|
||||||
|
init := make([]byte, 0, len(txt))
|
||||||
|
buf := bytes.NewBuffer(init)
|
||||||
|
var current uint
|
||||||
|
var wordBuf, spaceBuf bytes.Buffer
|
||||||
|
var wordBufLen, spaceBufLen uint
|
||||||
|
writeBufs := func() {
|
||||||
|
current += spaceBufLen + wordBufLen
|
||||||
|
spaceBuf.WriteTo(buf)
|
||||||
|
spaceBuf.Reset()
|
||||||
|
spaceBufLen = 0
|
||||||
|
wordBuf.WriteTo(buf)
|
||||||
|
wordBuf.Reset()
|
||||||
|
wordBufLen = 0
|
||||||
|
}
|
||||||
|
for _, char := range txt {
|
||||||
|
if char == '\n' {
|
||||||
|
// _Must_ wrap at newline
|
||||||
|
if wordBuf.Len() == 0 {
|
||||||
|
if int(current+spaceBufLen) > w {
|
||||||
|
current = 0
|
||||||
|
} else {
|
||||||
|
current += spaceBufLen
|
||||||
|
spaceBuf.WriteTo(buf)
|
||||||
|
}
|
||||||
|
spaceBuf.Reset()
|
||||||
|
spaceBufLen = 0
|
||||||
|
} else {
|
||||||
|
writeBufs()
|
||||||
|
}
|
||||||
|
buf.WriteRune(char)
|
||||||
|
current = 0
|
||||||
|
} else if unicode.IsSpace(char) && char != 0xA0 {
|
||||||
|
// Can wrap at whitespace
|
||||||
|
if spaceBuf.Len() == 0 || wordBuf.Len() > 0 {
|
||||||
|
writeBufs()
|
||||||
|
}
|
||||||
|
spaceBuf.WriteRune(char)
|
||||||
|
spaceBufLen++
|
||||||
|
} else {
|
||||||
|
wordBuf.WriteRune(char)
|
||||||
|
wordBufLen++
|
||||||
|
if int(current+wordBufLen+spaceBufLen) > w && int(wordBufLen) < w {
|
||||||
|
buf.WriteRune('\n')
|
||||||
|
current = 0
|
||||||
|
spaceBuf.Reset()
|
||||||
|
spaceBufLen = 0
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if wordBuf.Len() == 0 {
|
||||||
|
if int(current+spaceBufLen) <= w {
|
||||||
|
spaceBuf.WriteTo(buf)
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
spaceBuf.WriteTo(buf)
|
||||||
|
wordBuf.WriteTo(buf)
|
||||||
|
}
|
||||||
|
return buf.String()
|
||||||
|
}
|
||||||
|
|
||||||
|
func Longest(of []string) int {
|
||||||
|
var ret int
|
||||||
|
for i := range of {
|
||||||
|
tst := len(of[i])
|
||||||
|
if tst > ret {
|
||||||
|
ret = tst
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return ret
|
||||||
|
}
|
||||||
2
menu.go
2
menu.go
@@ -22,7 +22,7 @@ THE SOFTWARE.
|
|||||||
package widgets
|
package widgets
|
||||||
|
|
||||||
import (
|
import (
|
||||||
h "git.bullercodeworks.com/brian/dhcli/helpers"
|
h "git.bullercodeworks.com/brian/tcell-widgets/helpers"
|
||||||
"github.com/gdamore/tcell"
|
"github.com/gdamore/tcell"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|||||||
@@ -22,7 +22,7 @@ THE SOFTWARE.
|
|||||||
package widgets
|
package widgets
|
||||||
|
|
||||||
import (
|
import (
|
||||||
h "git.bullercodeworks.com/brian/dhcli/helpers"
|
h "git.bullercodeworks.com/brian/tcell-widgets/helpers"
|
||||||
"github.com/gdamore/tcell"
|
"github.com/gdamore/tcell"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|||||||
@@ -25,7 +25,7 @@ import (
|
|||||||
"fmt"
|
"fmt"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
h "git.bullercodeworks.com/brian/dhcli/helpers"
|
h "git.bullercodeworks.com/brian/tcell-widgets/helpers"
|
||||||
"github.com/gdamore/tcell"
|
"github.com/gdamore/tcell"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|||||||
2
table.go
2
table.go
@@ -25,7 +25,7 @@ import (
|
|||||||
"fmt"
|
"fmt"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
h "git.bullercodeworks.com/brian/dhcli/helpers"
|
h "git.bullercodeworks.com/brian/tcell-widgets/helpers"
|
||||||
"github.com/gdamore/tcell"
|
"github.com/gdamore/tcell"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user