181 lines
6.2 KiB
Go
181 lines
6.2 KiB
Go
/*
|
||
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] != ' '
|
||
}
|