Merge pull request #126 from benweidig/fix_borders

Refactored semigraphics and configurable borders
This commit is contained in:
rivo 2018-06-15 23:09:46 +02:00 committed by GitHub
commit e643d10b36
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
7 changed files with 383 additions and 152 deletions

45
borders.go Normal file
View File

@ -0,0 +1,45 @@
package tview
// Borders defines various borders used when primitives are drawn.
// These may be changed to accommodate a different look and feel.
var Borders = struct {
Horizontal rune
Vertical rune
TopLeft rune
TopRight rune
BottomLeft rune
BottomRight rune
LeftT rune
RightT rune
TopT rune
BottomT rune
Cross rune
HorizontalFocus rune
VerticalFocus rune
TopLeftFocus rune
TopRightFocus rune
BottomLeftFocus rune
BottomRightFocus rune
}{
Horizontal: BoxDrawingsLightHorizontal,
Vertical: BoxDrawingsLightVertical,
TopLeft: BoxDrawingsLightDownAndRight,
TopRight: BoxDrawingsLightDownAndLeft,
BottomLeft: BoxDrawingsLightUpAndRight,
BottomRight: BoxDrawingsLightUpAndLeft,
LeftT: BoxDrawingsLightVerticalAndRight,
RightT: BoxDrawingsLightVerticalAndLeft,
TopT: BoxDrawingsLightDownAndHorizontal,
BottomT: BoxDrawingsLightUpAndHorizontal,
Cross: BoxDrawingsLightVerticalAndHorizontal,
HorizontalFocus: BoxDrawingsDoubleHorizontal,
VerticalFocus: BoxDrawingsDoubleVertical,
TopLeftFocus: BoxDrawingsDoubleDownAndRight,
TopRightFocus: BoxDrawingsDoubleDownAndLeft,
BottomLeftFocus: BoxDrawingsDoubleUpAndRight,
BottomRightFocus: BoxDrawingsDoubleUpAndLeft,
}

34
box.go
View File

@ -236,27 +236,27 @@ func (b *Box) Draw(screen tcell.Screen) {
border := background.Foreground(b.borderColor)
var vertical, horizontal, topLeft, topRight, bottomLeft, bottomRight rune
if b.focus.HasFocus() {
vertical = GraphicsDbVertBar
horizontal = GraphicsDbHorBar
topLeft = GraphicsDbTopLeftCorner
topRight = GraphicsDbTopRightCorner
bottomLeft = GraphicsDbBottomLeftCorner
bottomRight = GraphicsDbBottomRightCorner
horizontal = Borders.HorizontalFocus
vertical = Borders.VerticalFocus
topLeft = Borders.TopLeftFocus
topRight = Borders.TopRightFocus
bottomLeft = Borders.BottomLeftFocus
bottomRight = Borders.BottomRightFocus
} else {
vertical = GraphicsHoriBar
horizontal = GraphicsVertBar
topLeft = GraphicsTopLeftCorner
topRight = GraphicsTopRightCorner
bottomLeft = GraphicsBottomLeftCorner
bottomRight = GraphicsBottomRightCorner
horizontal = Borders.Horizontal
vertical = Borders.Vertical
topLeft = Borders.TopLeft
topRight = Borders.TopRight
bottomLeft = Borders.BottomLeft
bottomRight = Borders.BottomRight
}
for x := b.x + 1; x < b.x+b.width-1; x++ {
screen.SetContent(x, b.y, vertical, nil, border)
screen.SetContent(x, b.y+b.height-1, vertical, nil, border)
screen.SetContent(x, b.y, horizontal, nil, border)
screen.SetContent(x, b.y+b.height-1, horizontal, nil, border)
}
for y := b.y + 1; y < b.y+b.height-1; y++ {
screen.SetContent(b.x, y, horizontal, nil, border)
screen.SetContent(b.x+b.width-1, y, horizontal, nil, border)
screen.SetContent(b.x, y, vertical, nil, border)
screen.SetContent(b.x+b.width-1, y, vertical, nil, border)
}
screen.SetContent(b.x, b.y, topLeft, nil, border)
screen.SetContent(b.x+b.width-1, b.y, topRight, nil, border)
@ -269,7 +269,7 @@ func (b *Box) Draw(screen tcell.Screen) {
if StringWidth(b.title)-printed > 0 && printed > 0 {
_, _, style, _ := screen.GetContent(b.x+b.width-2, b.y)
fg, _, _ := style.Decompose()
Print(screen, string(GraphicsEllipsis), b.x+b.width-2, b.y, 1, AlignLeft, fg)
Print(screen, string(SemigraphicsHorizontalEllipsis), b.x+b.width-2, b.y, 1, AlignLeft, fg)
}
}
}

View File

@ -87,7 +87,7 @@ const tableBasic = `[green]func[white] [yellow]main[white]() {
const tableSeparator = `[green]func[white] [yellow]main[white]() {
table := tview.[yellow]NewTable[white]().
[yellow]SetFixed[white]([red]1[white], [red]1[white]).
[yellow]SetSeparator[white](tview.GraphicsVertBar)
[yellow]SetSeparator[white](Borders.Vertical)
[yellow]for[white] row := [red]0[white]; row < [red]40[white]; row++ {
[yellow]for[white] column := [red]0[white]; column < [red]7[white]; column++ {
color := tcell.ColorWhite
@ -295,7 +295,7 @@ func Table(nextSlide func()) (title string, content tview.Primitive) {
separator := func() {
table.SetBorders(false).
SetSelectable(false, false).
SetSeparator(tview.GraphicsVertBar)
SetSeparator(tview.Borders.Vertical)
code.Clear()
fmt.Fprint(code, tableSeparator)
}

16
grid.go
View File

@ -590,11 +590,11 @@ func (g *Grid) Draw(screen tcell.Screen) {
}
by := item.y - 1
if by >= 0 && by < height {
PrintJoinedBorder(screen, x+bx, y+by, GraphicsHoriBar, g.bordersColor)
PrintJoinedSemigraphics(screen, x+bx, y+by, Borders.Horizontal, g.bordersColor)
}
by = item.y + item.h
if by >= 0 && by < height {
PrintJoinedBorder(screen, x+bx, y+by, GraphicsHoriBar, g.bordersColor)
PrintJoinedSemigraphics(screen, x+bx, y+by, Borders.Horizontal, g.bordersColor)
}
}
for by := item.y; by < item.y+item.h; by++ { // Left/right lines.
@ -603,28 +603,28 @@ func (g *Grid) Draw(screen tcell.Screen) {
}
bx := item.x - 1
if bx >= 0 && bx < width {
PrintJoinedBorder(screen, x+bx, y+by, GraphicsVertBar, g.bordersColor)
PrintJoinedSemigraphics(screen, x+bx, y+by, Borders.Vertical, g.bordersColor)
}
bx = item.x + item.w
if bx >= 0 && bx < width {
PrintJoinedBorder(screen, x+bx, y+by, GraphicsVertBar, g.bordersColor)
PrintJoinedSemigraphics(screen, x+bx, y+by, Borders.Vertical, g.bordersColor)
}
}
bx, by := item.x-1, item.y-1 // Top-left corner.
if bx >= 0 && bx < width && by >= 0 && by < height {
PrintJoinedBorder(screen, x+bx, y+by, GraphicsTopLeftCorner, g.bordersColor)
PrintJoinedSemigraphics(screen, x+bx, y+by, Borders.TopLeft, g.bordersColor)
}
bx, by = item.x+item.w, item.y-1 // Top-right corner.
if bx >= 0 && bx < width && by >= 0 && by < height {
PrintJoinedBorder(screen, x+bx, y+by, GraphicsTopRightCorner, g.bordersColor)
PrintJoinedSemigraphics(screen, x+bx, y+by, Borders.TopRight, g.bordersColor)
}
bx, by = item.x-1, item.y+item.h // Bottom-left corner.
if bx >= 0 && bx < width && by >= 0 && by < height {
PrintJoinedBorder(screen, x+bx, y+by, GraphicsBottomLeftCorner, g.bordersColor)
PrintJoinedSemigraphics(screen, x+bx, y+by, Borders.BottomLeft, g.bordersColor)
}
bx, by = item.x+item.w, item.y+item.h // Bottom-right corner.
if bx >= 0 && bx < width && by >= 0 && by < height {
PrintJoinedBorder(screen, x+bx, y+by, GraphicsBottomRightCorner, g.bordersColor)
PrintJoinedSemigraphics(screen, x+bx, y+by, Borders.BottomRight, g.bordersColor)
}
}
}

296
semigraphics.go Normal file
View File

@ -0,0 +1,296 @@
package tview
import "github.com/gdamore/tcell"
// Semigraphics provides an easy way to access unicode characters for drawing.
//
// Named like the unicode characters, 'Semigraphics'-prefix used if unicode block
// isn't prefixed itself.
const (
// Block: General Punctation U+2000-U+206F (http://unicode.org/charts/PDF/U2000.pdf)
SemigraphicsHorizontalEllipsis rune = '\u2026' // …
// Block: Box Drawing U+2500-U+257F (http://unicode.org/charts/PDF/U2500.pdf)
BoxDrawingsLightHorizontal rune = '\u2500' // ─
BoxDrawingsHeavyHorizontal rune = '\u2501' // ━
BoxDrawingsLightVertical rune = '\u2502' // │
BoxDrawingsHeavyVertical rune = '\u2503' // ┃
BoxDrawingsLightTripleDashHorizontal rune = '\u2504' // ┄
BoxDrawingsHeavyTripleDashHorizontal rune = '\u2505' // ┅
BoxDrawingsLightTripleDashVertical rune = '\u2506' // ┆
BoxDrawingsHeavyTripleDashVertical rune = '\u2507' // ┇
BoxDrawingsLightQuadrupleDashHorizontal rune = '\u2508' // ┈
BoxDrawingsHeavyQuadrupleDashHorizontal rune = '\u2509' // ┉
BoxDrawingsLightQuadrupleDashVertical rune = '\u250a' // ┊
BoxDrawingsHeavyQuadrupleDashVertical rune = '\u250b' // ┋
BoxDrawingsLightDownAndRight rune = '\u250c' // ┌
BoxDrawingsDownLighAndRightHeavy rune = '\u250d' // ┍
BoxDrawingsDownHeavyAndRightLight rune = '\u250e' // ┎
BoxDrawingsHeavyDownAndRight rune = '\u250f' // ┏
BoxDrawingsLightDownAndLeft rune = '\u2510' // ┐
BoxDrawingsDownLighAndLeftHeavy rune = '\u2511' // ┑
BoxDrawingsDownHeavyAndLeftLight rune = '\u2512' // ┒
BoxDrawingsHeavyDownAndLeft rune = '\u2513' // ┓
BoxDrawingsLightUpAndRight rune = '\u2514' // └
BoxDrawingsUpLightAndRightHeavy rune = '\u2515' // ┕
BoxDrawingsUpHeavyAndRightLight rune = '\u2516' // ┖
BoxDrawingsHeavyUpAndRight rune = '\u2517' // ┗
BoxDrawingsLightUpAndLeft rune = '\u2518' // ┘
BoxDrawingsUpLightAndLeftHeavy rune = '\u2519' // ┙
BoxDrawingsUpHeavyAndLeftLight rune = '\u251a' // ┚
BoxDrawingsHeavyUpAndLeft rune = '\u251b' // ┛
BoxDrawingsLightVerticalAndRight rune = '\u251c' // ├
BoxDrawingsVerticalLightAndRightHeavy rune = '\u251d' // ┝
BoxDrawingsUpHeavyAndRightDownLight rune = '\u251e' // ┞
BoxDrawingsDownHeacyAndRightUpLight rune = '\u251f' // ┟
BoxDrawingsVerticalHeavyAndRightLight rune = '\u2520' // ┠
BoxDrawingsDownLightAnbdRightUpHeavy rune = '\u2521' // ┡
BoxDrawingsUpLightAndRightDownHeavy rune = '\u2522' // ┢
BoxDrawingsHeavyVerticalAndRight rune = '\u2523' // ┣
BoxDrawingsLightVerticalAndLeft rune = '\u2524' // ┤
BoxDrawingsVerticalLightAndLeftHeavy rune = '\u2525' // ┥
BoxDrawingsUpHeavyAndLeftDownLight rune = '\u2526' // ┦
BoxDrawingsDownHeavyAndLeftUpLight rune = '\u2527' // ┧
BoxDrawingsVerticalheavyAndLeftLight rune = '\u2528' // ┨
BoxDrawingsDownLightAndLeftUpHeavy rune = '\u2529' // ┨
BoxDrawingsUpLightAndLeftDownHeavy rune = '\u252a' // ┪
BoxDrawingsHeavyVerticalAndLeft rune = '\u252b' // ┫
BoxDrawingsLightDownAndHorizontal rune = '\u252c' // ┬
BoxDrawingsLeftHeavyAndRightDownLight rune = '\u252d' // ┭
BoxDrawingsRightHeavyAndLeftDownLight rune = '\u252e' // ┮
BoxDrawingsDownLightAndHorizontalHeavy rune = '\u252f' // ┯
BoxDrawingsDownHeavyAndHorizontalLight rune = '\u2530' // ┰
BoxDrawingsRightLightAndLeftDownHeavy rune = '\u2531' // ┱
BoxDrawingsLeftLightAndRightDownHeavy rune = '\u2532' // ┲
BoxDrawingsHeavyDownAndHorizontal rune = '\u2533' // ┳
BoxDrawingsLightUpAndHorizontal rune = '\u2534' // ┴
BoxDrawingsLeftHeavyAndRightUpLight rune = '\u2535' // ┵
BoxDrawingsRightHeavyAndLeftUpLight rune = '\u2536' // ┶
BoxDrawingsUpLightAndHorizontalHeavy rune = '\u2537' // ┷
BoxDrawingsUpHeavyAndHorizontalLight rune = '\u2538' // ┸
BoxDrawingsRightLightAndLeftUpHeavy rune = '\u2539' // ┹
BoxDrawingsLeftLightAndRightUpHeavy rune = '\u253a' // ┺
BoxDrawingsHeavyUpAndHorizontal rune = '\u253b' // ┻
BoxDrawingsLightVerticalAndHorizontal rune = '\u253c' // ┼
BoxDrawingsLeftHeavyAndRightVerticalLight rune = '\u253d' // ┽
BoxDrawingsRightHeavyAndLeftVerticalLight rune = '\u253e' // ┾
BoxDrawingsVerticalLightAndHorizontalHeavy rune = '\u253f' // ┿
BoxDrawingsUpHeavyAndDownHorizontalLight rune = '\u2540' // ╀
BoxDrawingsDownHeavyAndUpHorizontalLight rune = '\u2541' // ╁
BoxDrawingsVerticalHeavyAndHorizontalLight rune = '\u2542' // ╂
BoxDrawingsLeftUpHeavyAndRightDownLight rune = '\u2543' // ╃
BoxDrawingsRightUpHeavyAndLeftDownLight rune = '\u2544' // ╄
BoxDrawingsLeftDownHeavyAndRightUpLight rune = '\u2545' // ╅
BoxDrawingsRightDownHeavyAndLeftUpLight rune = '\u2546' // ╆
BoxDrawingsDownLightAndUpHorizontalHeavy rune = '\u2547' // ╇
BoxDrawingsUpLightAndDownHorizontalHeavy rune = '\u2548' // ╈
BoxDrawingsRightLightAndLeftVerticalHeavy rune = '\u2549' // ╉
BoxDrawingsLeftLightAndRightVerticalHeavy rune = '\u254a' // ╊
BoxDrawingsHeavyVerticalAndHorizontal rune = '\u254b' // ╋
BoxDrawingsLightDoubleDashHorizontal rune = '\u254c' // ╌
BoxDrawingsHeavyDoubleDashHorizontal rune = '\u254d' // ╍
BoxDrawingsLightDoubleDashVertical rune = '\u254e' // ╎
BoxDrawingsHeavyDoubleDashVertical rune = '\u254f' // ╏
BoxDrawingsDoubleHorizontal rune = '\u2550' // ═
BoxDrawingsDoubleVertical rune = '\u2551' // ║
BoxDrawingsDownSingleAndRightDouble rune = '\u2552' // ╒
BoxDrawingsDownDoubleAndRightSingle rune = '\u2553' // ╓
BoxDrawingsDoubleDownAndRight rune = '\u2554' // ╔
BoxDrawingsDownSingleAndLeftDouble rune = '\u2555' // ╕
BoxDrawingsDownDoubleAndLeftSingle rune = '\u2556' // ╖
BoxDrawingsDoubleDownAndLeft rune = '\u2557' // ╗
BoxDrawingsUpSingleAndRightDouble rune = '\u2558' // ╘
BoxDrawingsUpDoubleAndRightSingle rune = '\u2559' // ╙
BoxDrawingsDoubleUpAndRight rune = '\u255a' // ╚
BoxDrawingsUpSingleAndLeftDouble rune = '\u255b' // ╛
BoxDrawingsUpDobuleAndLeftSingle rune = '\u255c' // ╜
BoxDrawingsDoubleUpAndLeft rune = '\u255d' // ╝
BoxDrawingsVerticalSingleAndRightDouble rune = '\u255e' // ╞
BoxDrawingsVerticalDoubleAndRightSingle rune = '\u255f' // ╟
BoxDrawingsDoubleVerticalAndRight rune = '\u2560' // ╠
BoxDrawingsVerticalSingleAndLeftDouble rune = '\u2561' // ╡
BoxDrawingsVerticalDoubleAndLeftSingle rune = '\u2562' // ╢
BoxDrawingsDoubleVerticalAndLeft rune = '\u2563' // ╣
BoxDrawingsDownSingleAndHorizontalDouble rune = '\u2564' // ╤
BoxDrawingsDownDoubleAndHorizontalSingle rune = '\u2565' // ╥
BoxDrawingsDoubleDownAndHorizontal rune = '\u2566' // ╦
BoxDrawingsUpSingleAndHorizontalDouble rune = '\u2567' // ╧
BoxDrawingsUpDoubleAndHorizontalSingle rune = '\u2568' // ╨
BoxDrawingsDoubleUpAndHorizontal rune = '\u2569' // ╩
BoxDrawingsVerticalSingleAndHorizontalDouble rune = '\u256a' // ╪
BoxDrawingsVerticalDoubleAndHorizontalSingle rune = '\u256b' // ╫
BoxDrawingsDoubleVerticalAndHorizontal rune = '\u256c' // ╬
BoxDrawingsLightArcDownAndRight rune = '\u256d' // ╭
BoxDrawingsLightArcDownAndLeft rune = '\u256e' // ╮
BoxDrawingsLightArcUpAndLeft rune = '\u256f' // ╯
BoxDrawingsLightArcUpAndRight rune = '\u2570' // ╰
BoxDrawingsLightDiagonalUpperRightToLowerLeft rune = '\u2571' //
BoxDrawingsLightDiagonalUpperLeftToLowerRight rune = '\u2572' // ╲
BoxDrawingsLightDiagonalCross rune = '\u2573' //
BoxDrawingsLightLeft rune = '\u2574' // ╴
BoxDrawingsLightUp rune = '\u2575' // ╵
BoxDrawingsLightRight rune = '\u2576' // ╶
BoxDrawingsLightDown rune = '\u2577' // ╷
BoxDrawingsHeavyLeft rune = '\u2578' // ╸
BoxDrawingsHeavyUp rune = '\u2579' // ╹
BoxDrawingsHeavyRight rune = '\u257a' // ╺
BoxDrawingsHeavyDown rune = '\u257b' // ╻
BoxDrawingsLightLeftAndHeavyRight rune = '\u257c' // ╼
BoxDrawingsLightUpAndHeavyDown rune = '\u257d' // ╽
BoxDrawingsHeavyLeftAndLightRight rune = '\u257e' // ╾
BoxDrawingsHeavyUpAndLightDown rune = '\u257f' // ╿
)
// SemigraphicJoints is a map for joining semigraphic (or otherwise) runes.
// So far only light lines are supported but if you want to change the border
// styling you need to provide the joints, too.
// The matching will be sorted ascending by rune value, so you don't need to
// provide all rune combinations,
// e.g. (─) + (│) = (┼) will also match (│) + (─) = (┼)
var SemigraphicJoints = map[string]rune{
// (─) + (│) = (┼)
string([]rune{BoxDrawingsLightHorizontal, BoxDrawingsLightVertical}): BoxDrawingsLightVerticalAndHorizontal,
// (─) + (┌) = (┬)
string([]rune{BoxDrawingsLightHorizontal, BoxDrawingsLightDownAndRight}): BoxDrawingsLightDownAndHorizontal,
// (─) + (┐) = (┬)
string([]rune{BoxDrawingsLightHorizontal, BoxDrawingsLightDownAndLeft}): BoxDrawingsLightDownAndHorizontal,
// (─) + (└) = (┴)
string([]rune{BoxDrawingsLightHorizontal, BoxDrawingsLightUpAndRight}): BoxDrawingsLightUpAndHorizontal,
// (─) + (┘) = (┴)
string([]rune{BoxDrawingsLightHorizontal, BoxDrawingsLightUpAndLeft}): BoxDrawingsLightUpAndHorizontal,
// (─) + (├) = (┼)
string([]rune{BoxDrawingsLightHorizontal, BoxDrawingsLightVerticalAndRight}): BoxDrawingsLightVerticalAndHorizontal,
// (─) + (┤) = (┼)
string([]rune{BoxDrawingsLightHorizontal, BoxDrawingsLightVerticalAndLeft}): BoxDrawingsLightVerticalAndHorizontal,
// (─) + (┬) = (┬)
string([]rune{BoxDrawingsLightHorizontal, BoxDrawingsLightDownAndHorizontal}): BoxDrawingsLightDownAndHorizontal,
// (─) + (┴) = (┴)
string([]rune{BoxDrawingsLightHorizontal, BoxDrawingsLightUpAndHorizontal}): BoxDrawingsLightUpAndHorizontal,
// (─) + (┼) = (┼)
string([]rune{BoxDrawingsLightHorizontal, BoxDrawingsLightVerticalAndHorizontal}): BoxDrawingsLightVerticalAndHorizontal,
// (│) + (┌) = (├)
string([]rune{BoxDrawingsLightVertical, BoxDrawingsLightDownAndRight}): BoxDrawingsLightVerticalAndRight,
// (│) + (┐) = (┤)
string([]rune{BoxDrawingsLightVertical, BoxDrawingsLightDownAndLeft}): BoxDrawingsLightVerticalAndLeft,
// (│) + (└) = (├)
string([]rune{BoxDrawingsLightVertical, BoxDrawingsLightUpAndRight}): BoxDrawingsLightVerticalAndRight,
// (│) + (┘) = (┤)
string([]rune{BoxDrawingsLightVertical, BoxDrawingsLightUpAndLeft}): BoxDrawingsLightVerticalAndLeft,
// (│) + (├) = (├)
string([]rune{BoxDrawingsLightVertical, BoxDrawingsLightVerticalAndRight}): BoxDrawingsLightVerticalAndRight,
// (│) + (┤) = (┤)
string([]rune{BoxDrawingsLightVertical, BoxDrawingsLightVerticalAndLeft}): BoxDrawingsLightVerticalAndLeft,
// (│) + (┬) = (┼)
string([]rune{BoxDrawingsLightVertical, BoxDrawingsLightDownAndHorizontal}): BoxDrawingsLightVerticalAndHorizontal,
// (│) + (┴) = (┼)
string([]rune{BoxDrawingsLightVertical, BoxDrawingsLightUpAndHorizontal}): BoxDrawingsLightVerticalAndHorizontal,
// (│) + (┼) = (┼)
string([]rune{BoxDrawingsLightVertical, BoxDrawingsLightVerticalAndHorizontal}): BoxDrawingsLightVerticalAndHorizontal,
// (┌) + (┐) = (┬)
string([]rune{BoxDrawingsLightDownAndRight, BoxDrawingsLightDownAndLeft}): BoxDrawingsLightDownAndHorizontal,
// (┌) + (└) = (├)
string([]rune{BoxDrawingsLightDownAndRight, BoxDrawingsLightUpAndRight}): BoxDrawingsLightVerticalAndRight,
// (┌) + (┘) = (┼)
string([]rune{BoxDrawingsLightDownAndRight, BoxDrawingsLightUpAndLeft}): BoxDrawingsLightVerticalAndHorizontal,
// (┌) + (├) = (├)
string([]rune{BoxDrawingsLightDownAndRight, BoxDrawingsLightVerticalAndRight}): BoxDrawingsLightVerticalAndRight,
// (┌) + (┤) = (┼)
string([]rune{BoxDrawingsLightDownAndRight, BoxDrawingsLightVerticalAndLeft}): BoxDrawingsLightVerticalAndHorizontal,
// (┌) + (┬) = (┬)
string([]rune{BoxDrawingsLightDownAndRight, BoxDrawingsLightDownAndHorizontal}): BoxDrawingsLightDownAndHorizontal,
// (┌) + (┴) = (┼)
string([]rune{BoxDrawingsLightDownAndRight, BoxDrawingsLightUpAndHorizontal}): BoxDrawingsLightVerticalAndHorizontal,
// (┌) + (┴) = (┼)
string([]rune{BoxDrawingsLightDownAndRight, BoxDrawingsLightVerticalAndHorizontal}): BoxDrawingsLightVerticalAndHorizontal,
// (┐) + (└) = (┼)
string([]rune{BoxDrawingsLightDownAndLeft, BoxDrawingsLightUpAndRight}): BoxDrawingsLightVerticalAndHorizontal,
// (┐) + (┘) = (┤)
string([]rune{BoxDrawingsLightDownAndLeft, BoxDrawingsLightUpAndLeft}): BoxDrawingsLightVerticalAndLeft,
// (┐) + (├) = (┼)
string([]rune{BoxDrawingsLightDownAndLeft, BoxDrawingsLightVerticalAndRight}): BoxDrawingsLightVerticalAndHorizontal,
// (┐) + (┤) = (┤)
string([]rune{BoxDrawingsLightDownAndLeft, BoxDrawingsLightVerticalAndLeft}): BoxDrawingsLightVerticalAndLeft,
// (┐) + (┬) = (┬)
string([]rune{BoxDrawingsLightDownAndLeft, BoxDrawingsLightDownAndHorizontal}): BoxDrawingsLightDownAndHorizontal,
// (┐) + (┴) = (┼)
string([]rune{BoxDrawingsLightDownAndLeft, BoxDrawingsLightUpAndHorizontal}): BoxDrawingsLightVerticalAndHorizontal,
// (┐) + (┼) = (┼)
string([]rune{BoxDrawingsLightDownAndLeft, BoxDrawingsLightVerticalAndHorizontal}): BoxDrawingsLightVerticalAndHorizontal,
// (└) + (┘) = (┴)
string([]rune{BoxDrawingsLightUpAndRight, BoxDrawingsLightUpAndLeft}): BoxDrawingsLightUpAndHorizontal,
// (└) + (├) = (├)
string([]rune{BoxDrawingsLightUpAndRight, BoxDrawingsLightVerticalAndRight}): BoxDrawingsLightVerticalAndRight,
// (└) + (┤) = (┼)
string([]rune{BoxDrawingsLightUpAndRight, BoxDrawingsLightVerticalAndLeft}): BoxDrawingsLightVerticalAndHorizontal,
// (└) + (┬) = (┼)
string([]rune{BoxDrawingsLightUpAndRight, BoxDrawingsLightDownAndHorizontal}): BoxDrawingsLightVerticalAndHorizontal,
// (└) + (┴) = (┴)
string([]rune{BoxDrawingsLightUpAndRight, BoxDrawingsLightUpAndHorizontal}): BoxDrawingsLightUpAndHorizontal,
// (└) + (┼) = (┼)
string([]rune{BoxDrawingsLightUpAndRight, BoxDrawingsLightVerticalAndHorizontal}): BoxDrawingsLightVerticalAndHorizontal,
// (┘) + (├) = (┼)
string([]rune{BoxDrawingsLightUpAndLeft, BoxDrawingsLightVerticalAndRight}): BoxDrawingsLightVerticalAndHorizontal,
// (┘) + (┤) = (┤)
string([]rune{BoxDrawingsLightUpAndLeft, BoxDrawingsLightVerticalAndLeft}): BoxDrawingsLightVerticalAndLeft,
// (┘) + (┬) = (┼)
string([]rune{BoxDrawingsLightUpAndLeft, BoxDrawingsLightDownAndHorizontal}): BoxDrawingsLightVerticalAndHorizontal,
// (┘) + (┴) = (┴)
string([]rune{BoxDrawingsLightUpAndLeft, BoxDrawingsLightUpAndHorizontal}): BoxDrawingsLightUpAndHorizontal,
// (┘) + (┼) = (┼)
string([]rune{BoxDrawingsLightUpAndLeft, BoxDrawingsLightVerticalAndHorizontal}): BoxDrawingsLightVerticalAndHorizontal,
// (├) + (┤) = (┼)
string([]rune{BoxDrawingsLightVerticalAndRight, BoxDrawingsLightVerticalAndLeft}): BoxDrawingsLightVerticalAndHorizontal,
// (├) + (┬) = (┼)
string([]rune{BoxDrawingsLightVerticalAndRight, BoxDrawingsLightDownAndHorizontal}): BoxDrawingsLightVerticalAndHorizontal,
// (├) + (┴) = (┼)
string([]rune{BoxDrawingsLightVerticalAndRight, BoxDrawingsLightUpAndHorizontal}): BoxDrawingsLightVerticalAndHorizontal,
// (├) + (┼) = (┼)
string([]rune{BoxDrawingsLightVerticalAndRight, BoxDrawingsLightVerticalAndHorizontal}): BoxDrawingsLightVerticalAndHorizontal,
// (┤) + (┬) = (┼)
string([]rune{BoxDrawingsLightVerticalAndLeft, BoxDrawingsLightDownAndHorizontal}): BoxDrawingsLightVerticalAndHorizontal,
// (┤) + (┴) = (┼)
string([]rune{BoxDrawingsLightVerticalAndLeft, BoxDrawingsLightUpAndHorizontal}): BoxDrawingsLightVerticalAndHorizontal,
// (┤) + (┼) = (┼)
string([]rune{BoxDrawingsLightVerticalAndLeft, BoxDrawingsLightVerticalAndHorizontal}): BoxDrawingsLightVerticalAndHorizontal,
// (┬) + (┴) = (┼)
string([]rune{BoxDrawingsLightDownAndHorizontal, BoxDrawingsLightUpAndHorizontal}): BoxDrawingsLightVerticalAndHorizontal,
// (┬) + (┼) = (┼)
string([]rune{BoxDrawingsLightDownAndHorizontal, BoxDrawingsLightVerticalAndHorizontal}): BoxDrawingsLightVerticalAndHorizontal,
// (┴) + (┼) = (┼)
string([]rune{BoxDrawingsLightUpAndHorizontal, BoxDrawingsLightVerticalAndHorizontal}): BoxDrawingsLightVerticalAndHorizontal,
}
// PrintJoinedSemigraphics prints a semigraphics rune into the screen at the given
// position with the given color, joining it with any existing semigraphics
// rune. Background colors are preserved. At this point, only regular single
// line borders are supported.
func PrintJoinedSemigraphics(screen tcell.Screen, x, y int, ch rune, color tcell.Color) {
previous, _, style, _ := screen.GetContent(x, y)
style = style.Foreground(color)
// What's the resulting rune?
var result rune
if ch == previous {
result = ch
} else {
if ch < previous {
previous, ch = ch, previous
}
result = SemigraphicJoints[string([]rune{previous, ch})]
}
if result == 0 {
result = ch
}
// We only print something if we have something.
screen.SetContent(x, y, result, nil, style)
}

View File

@ -278,7 +278,7 @@ func (t *Table) SetBordersColor(color tcell.Color) *Table {
// SetSeparator sets the character used to fill the space between two
// neighboring cells. This is a space character ' ' per default but you may
// want to set it to GraphicsVertBar (or any other rune) if the column
// want to set it to Borders.Vertical (or any other rune) if the column
// separation should be more visible. If cell borders are activated, this is
// ignored.
//
@ -668,24 +668,24 @@ ColumnLoop:
// Draw borders.
rowY *= 2
for pos := 0; pos < columnWidth && columnX+1+pos < width; pos++ {
drawBorder(columnX+pos+1, rowY, GraphicsHoriBar)
drawBorder(columnX+pos+1, rowY, Borders.Horizontal)
}
ch := GraphicsCross
ch := Borders.Cross
if columnIndex == 0 {
if rowY == 0 {
ch = GraphicsTopLeftCorner
ch = Borders.TopLeft
} else {
ch = GraphicsLeftT
ch = Borders.LeftT
}
} else if rowY == 0 {
ch = GraphicsTopT
ch = Borders.TopT
}
drawBorder(columnX, rowY, ch)
rowY++
if rowY >= height {
break // No space for the text anymore.
}
drawBorder(columnX, rowY, GraphicsVertBar)
drawBorder(columnX, rowY, Borders.Vertical)
} else if columnIndex > 0 {
// Draw separator.
drawBorder(columnX, rowY, t.separator)
@ -706,18 +706,18 @@ ColumnLoop:
_, printed := printWithStyle(screen, cell.Text, x+columnX+1, y+rowY, finalWidth, cell.Align, tcell.StyleDefault.Foreground(cell.Color)|tcell.Style(cell.Attributes))
if StringWidth(cell.Text)-printed > 0 && printed > 0 {
_, _, style, _ := screen.GetContent(x+columnX+1+finalWidth-1, y+rowY)
printWithStyle(screen, string(GraphicsEllipsis), x+columnX+1+finalWidth-1, y+rowY, 1, AlignLeft, style)
printWithStyle(screen, string(SemigraphicsHorizontalEllipsis), x+columnX+1+finalWidth-1, y+rowY, 1, AlignLeft, style)
}
}
// Draw bottom border.
if rowY := 2 * len(rows); t.borders && rowY < height {
for pos := 0; pos < columnWidth && columnX+1+pos < width; pos++ {
drawBorder(columnX+pos+1, rowY, GraphicsHoriBar)
drawBorder(columnX+pos+1, rowY, Borders.Horizontal)
}
ch := GraphicsBottomT
ch := Borders.BottomT
if columnIndex == 0 {
ch = GraphicsBottomLeftCorner
ch = Borders.BottomLeft
}
drawBorder(columnX, rowY, ch)
}
@ -730,16 +730,16 @@ ColumnLoop:
for rowY := range rows {
rowY *= 2
if rowY+1 < height {
drawBorder(columnX, rowY+1, GraphicsVertBar)
drawBorder(columnX, rowY+1, Borders.Vertical)
}
ch := GraphicsRightT
ch := Borders.RightT
if rowY == 0 {
ch = GraphicsTopRightCorner
ch = Borders.TopRight
}
drawBorder(columnX, rowY, ch)
}
if rowY := 2 * len(rows); rowY < height {
drawBorder(columnX, rowY, GraphicsBottomRightCorner)
drawBorder(columnX, rowY, Borders.BottomRight)
}
}

110
util.go
View File

@ -19,90 +19,6 @@ const (
AlignRight
)
// Semigraphical runes.
const (
GraphicsHoriBar = '\u2500'
GraphicsVertBar = '\u2502'
GraphicsTopLeftCorner = '\u250c'
GraphicsTopRightCorner = '\u2510'
GraphicsBottomLeftCorner = '\u2514'
GraphicsBottomRightCorner = '\u2518'
GraphicsLeftT = '\u251c'
GraphicsRightT = '\u2524'
GraphicsTopT = '\u252c'
GraphicsBottomT = '\u2534'
GraphicsCross = '\u253c'
GraphicsDbVertBar = '\u2550'
GraphicsDbHorBar = '\u2551'
GraphicsDbTopLeftCorner = '\u2554'
GraphicsDbTopRightCorner = '\u2557'
GraphicsDbBottomRightCorner = '\u255d'
GraphicsDbBottomLeftCorner = '\u255a'
GraphicsEllipsis = '\u2026'
)
// joints maps combinations of two graphical runes to the rune that results
// when joining the two in the same screen cell. The keys of this map are
// two-rune strings where the value of the first rune is lower than the value
// of the second rune. Identical runes are not contained.
var joints = map[string]rune{
"\u2500\u2502": GraphicsCross,
"\u2500\u250c": GraphicsTopT,
"\u2500\u2510": GraphicsTopT,
"\u2500\u2514": GraphicsBottomT,
"\u2500\u2518": GraphicsBottomT,
"\u2500\u251c": GraphicsCross,
"\u2500\u2524": GraphicsCross,
"\u2500\u252c": GraphicsTopT,
"\u2500\u2534": GraphicsBottomT,
"\u2500\u253c": GraphicsCross,
"\u2502\u250c": GraphicsLeftT,
"\u2502\u2510": GraphicsRightT,
"\u2502\u2514": GraphicsLeftT,
"\u2502\u2518": GraphicsRightT,
"\u2502\u251c": GraphicsLeftT,
"\u2502\u2524": GraphicsRightT,
"\u2502\u252c": GraphicsCross,
"\u2502\u2534": GraphicsCross,
"\u2502\u253c": GraphicsCross,
"\u250c\u2510": GraphicsTopT,
"\u250c\u2514": GraphicsLeftT,
"\u250c\u2518": GraphicsCross,
"\u250c\u251c": GraphicsLeftT,
"\u250c\u2524": GraphicsCross,
"\u250c\u252c": GraphicsTopT,
"\u250c\u2534": GraphicsCross,
"\u250c\u253c": GraphicsCross,
"\u2510\u2514": GraphicsCross,
"\u2510\u2518": GraphicsRightT,
"\u2510\u251c": GraphicsCross,
"\u2510\u2524": GraphicsRightT,
"\u2510\u252c": GraphicsTopT,
"\u2510\u2534": GraphicsCross,
"\u2510\u253c": GraphicsCross,
"\u2514\u2518": GraphicsBottomT,
"\u2514\u251c": GraphicsLeftT,
"\u2514\u2524": GraphicsCross,
"\u2514\u252c": GraphicsCross,
"\u2514\u2534": GraphicsBottomT,
"\u2514\u253c": GraphicsCross,
"\u2518\u251c": GraphicsCross,
"\u2518\u2524": GraphicsRightT,
"\u2518\u252c": GraphicsCross,
"\u2518\u2534": GraphicsBottomT,
"\u2518\u253c": GraphicsCross,
"\u251c\u2524": GraphicsCross,
"\u251c\u252c": GraphicsCross,
"\u251c\u2534": GraphicsCross,
"\u251c\u253c": GraphicsCross,
"\u2524\u252c": GraphicsCross,
"\u2524\u2534": GraphicsCross,
"\u2524\u253c": GraphicsCross,
"\u252c\u2534": GraphicsCross,
"\u252c\u253c": GraphicsCross,
"\u2534\u253c": GraphicsCross,
}
// Common regular expressions.
var (
colorPattern = regexp.MustCompile(`\[([a-zA-Z]+|#[0-9a-zA-Z]{6}|\-)?(:([a-zA-Z]+|#[0-9a-zA-Z]{6}|\-)?(:([lbdru]+|\-)?)?)?\]`)
@ -607,32 +523,6 @@ func WordWrap(text string, width int) (lines []string) {
return
}
// PrintJoinedBorder prints a border graphics rune into the screen at the given
// position with the given color, joining it with any existing border graphics
// rune. Background colors are preserved. At this point, only regular single
// line borders are supported.
func PrintJoinedBorder(screen tcell.Screen, x, y int, ch rune, color tcell.Color) {
previous, _, style, _ := screen.GetContent(x, y)
style = style.Foreground(color)
// What's the resulting rune?
var result rune
if ch == previous {
result = ch
} else {
if ch < previous {
previous, ch = ch, previous
}
result = joints[string(previous)+string(ch)]
}
if result == 0 {
result = ch
}
// We only print something if we have something.
screen.SetContent(x, y, result, nil, style)
}
// Escape escapes the given text such that color and/or region tags are not
// recognized and substituted by the print functions of this package. For
// example, to include a tag-like string in a box title or in a TextView: