mirror of
https://github.com/rivo/tview.git
synced 2025-04-24 13:48:56 +08:00
Upgraded printing and style handling to the new definition of tcell.ColorDefault.
This commit is contained in:
parent
ae065beb93
commit
ae9464cc35
7
box.go
7
box.go
@ -26,6 +26,9 @@ type Box struct {
|
||||
// The box's background color.
|
||||
backgroundColor tcell.Color
|
||||
|
||||
// If set to true, the background of this box is not cleared while drawing.
|
||||
dontClear bool
|
||||
|
||||
// Whether or not a border is drawn, reducing the box's space for content by
|
||||
// two in width and height.
|
||||
border bool
|
||||
@ -66,7 +69,7 @@ func NewBox() *Box {
|
||||
height: 10,
|
||||
innerX: -1, // Mark as uninitialized.
|
||||
backgroundColor: Styles.PrimitiveBackgroundColor,
|
||||
borderStyle: tcell.StyleDefault.Foreground(Styles.BorderColor),
|
||||
borderStyle: tcell.StyleDefault.Foreground(Styles.BorderColor).Background(Styles.PrimitiveBackgroundColor),
|
||||
titleColor: Styles.TitleColor,
|
||||
titleAlign: AlignCenter,
|
||||
}
|
||||
@ -335,7 +338,7 @@ func (b *Box) DrawForSubclass(screen tcell.Screen, p Primitive) {
|
||||
|
||||
// Fill background.
|
||||
background := def.Background(b.backgroundColor)
|
||||
if b.backgroundColor != tcell.ColorDefault {
|
||||
if !b.dontClear {
|
||||
for y := b.y; y < b.y+b.height; y++ {
|
||||
for x := b.x; x < b.x+b.width; x++ {
|
||||
screen.SetContent(x, y, ' ', nil, background)
|
||||
|
@ -189,7 +189,7 @@ func (c *Checkbox) Draw(screen tcell.Screen) {
|
||||
if !c.checked {
|
||||
checkedString = strings.Repeat(" ", checkboxWidth)
|
||||
}
|
||||
printWithStyle(screen, checkedString, x, y, 0, checkboxWidth, AlignLeft, fieldStyle)
|
||||
printWithStyle(screen, checkedString, x, y, 0, checkboxWidth, AlignLeft, fieldStyle, false)
|
||||
}
|
||||
|
||||
// InputHandler returns the handler for this primitive.
|
||||
|
13
flex.go
13
flex.go
@ -42,17 +42,18 @@ type Flex struct {
|
||||
// direction set to FlexColumn. To add primitives to this layout, see AddItem().
|
||||
// To change the direction, see SetDirection().
|
||||
//
|
||||
// Note that Box, the superclass of Flex, will have its background color set to
|
||||
// transparent so that any nil flex items will leave their background unchanged.
|
||||
// To clear a Flex's background before any items are drawn, set it to the
|
||||
// desired color:
|
||||
// Note that Box, the superclass of Flex, will not clear its contents so that
|
||||
// any nil flex items will leave their background unchanged. To clear a Flex's
|
||||
// background before any items are drawn, set it to a box with the desired
|
||||
// color:
|
||||
//
|
||||
// flex.SetBackgroundColor(tview.Styles.PrimitiveBackgroundColor)
|
||||
// flex.Box = NewBox()
|
||||
func NewFlex() *Flex {
|
||||
f := &Flex{
|
||||
Box: NewBox().SetBackgroundColor(tcell.ColorDefault),
|
||||
direction: FlexColumn,
|
||||
}
|
||||
f.Box = NewBox()
|
||||
f.Box.dontClear = true
|
||||
return f
|
||||
}
|
||||
|
||||
|
1
go.mod
1
go.mod
@ -3,6 +3,7 @@ module github.com/rivo/tview
|
||||
go 1.12
|
||||
|
||||
require (
|
||||
github.com/gdamore/tcell v1.4.0 // indirect
|
||||
github.com/gdamore/tcell/v2 v2.2.0
|
||||
github.com/lucasb-eyer/go-colorful v1.2.0
|
||||
github.com/mattn/go-runewidth v0.0.10
|
||||
|
2
go.sum
2
go.sum
@ -1,5 +1,7 @@
|
||||
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/gdamore/tcell/v2 v2.0.1-0.20201017141208-acf90d56d591 h1:0WWUDZ1oxq7NxVyGo8M3KI5jbkiwNAdZFFzAdC68up4=
|
||||
github.com/gdamore/tcell/v2 v2.0.1-0.20201017141208-acf90d56d591/go.mod h1:vSVL/GV5mCSlPC6thFP5kfOFdM9MGZcalipmpTxTgQA=
|
||||
github.com/gdamore/tcell/v2 v2.2.0 h1:vSyEgKwraXPSOkvCk7IwOSyX+Pv3V2cV9CikJMXg4U4=
|
||||
|
30
grid.go
30
grid.go
@ -60,17 +60,18 @@ type Grid struct {
|
||||
|
||||
// NewGrid returns a new grid-based layout container with no initial primitives.
|
||||
//
|
||||
// Note that Box, the superclass of Grid, will have its background color set to
|
||||
// transparent so that any grid areas not covered by any primitives will leave
|
||||
// their background unchanged. To clear a Grid's background before any items are
|
||||
// drawn, set it to the desired color:
|
||||
// Note that Box, the superclass of Grid, will be transparent so that any grid
|
||||
// areas not covered by any primitives will leave their background unchanged. To
|
||||
// clear a Grid's background before any items are drawn, reset its Box to one
|
||||
// with the desired color:
|
||||
//
|
||||
// grid.SetBackgroundColor(tview.Styles.PrimitiveBackgroundColor)
|
||||
// grid.Box = NewBox()
|
||||
func NewGrid() *Grid {
|
||||
g := &Grid{
|
||||
Box: NewBox().SetBackgroundColor(tcell.ColorDefault),
|
||||
bordersColor: Styles.GraphicsColor,
|
||||
}
|
||||
g.Box = NewBox()
|
||||
g.Box.dontClear = true
|
||||
return g
|
||||
}
|
||||
|
||||
@ -586,6 +587,7 @@ func (g *Grid) Draw(screen tcell.Screen) {
|
||||
}
|
||||
|
||||
// Draw primitives and borders.
|
||||
borderStyle := tcell.StyleDefault.Background(g.backgroundColor).Foreground(g.bordersColor)
|
||||
for primitive, item := range items {
|
||||
// Final primitive position.
|
||||
if !item.visible {
|
||||
@ -634,11 +636,11 @@ func (g *Grid) Draw(screen tcell.Screen) {
|
||||
}
|
||||
by := item.y - 1
|
||||
if by >= 0 && by < screenHeight {
|
||||
PrintJoinedSemigraphics(screen, bx, by, Borders.Horizontal, g.bordersColor)
|
||||
PrintJoinedSemigraphics(screen, bx, by, Borders.Horizontal, borderStyle)
|
||||
}
|
||||
by = item.y + item.h
|
||||
if by >= 0 && by < screenHeight {
|
||||
PrintJoinedSemigraphics(screen, bx, by, Borders.Horizontal, g.bordersColor)
|
||||
PrintJoinedSemigraphics(screen, bx, by, Borders.Horizontal, borderStyle)
|
||||
}
|
||||
}
|
||||
for by := item.y; by < item.y+item.h; by++ { // Left/right lines.
|
||||
@ -647,28 +649,28 @@ func (g *Grid) Draw(screen tcell.Screen) {
|
||||
}
|
||||
bx := item.x - 1
|
||||
if bx >= 0 && bx < screenWidth {
|
||||
PrintJoinedSemigraphics(screen, bx, by, Borders.Vertical, g.bordersColor)
|
||||
PrintJoinedSemigraphics(screen, bx, by, Borders.Vertical, borderStyle)
|
||||
}
|
||||
bx = item.x + item.w
|
||||
if bx >= 0 && bx < screenWidth {
|
||||
PrintJoinedSemigraphics(screen, bx, by, Borders.Vertical, g.bordersColor)
|
||||
PrintJoinedSemigraphics(screen, bx, by, Borders.Vertical, borderStyle)
|
||||
}
|
||||
}
|
||||
bx, by := item.x-1, item.y-1 // Top-left corner.
|
||||
if bx >= 0 && bx < screenWidth && by >= 0 && by < screenHeight {
|
||||
PrintJoinedSemigraphics(screen, bx, by, Borders.TopLeft, g.bordersColor)
|
||||
PrintJoinedSemigraphics(screen, bx, by, Borders.TopLeft, borderStyle)
|
||||
}
|
||||
bx, by = item.x+item.w, item.y-1 // Top-right corner.
|
||||
if bx >= 0 && bx < screenWidth && by >= 0 && by < screenHeight {
|
||||
PrintJoinedSemigraphics(screen, bx, by, Borders.TopRight, g.bordersColor)
|
||||
PrintJoinedSemigraphics(screen, bx, by, Borders.TopRight, borderStyle)
|
||||
}
|
||||
bx, by = item.x-1, item.y+item.h // Bottom-left corner.
|
||||
if bx >= 0 && bx < screenWidth && by >= 0 && by < screenHeight {
|
||||
PrintJoinedSemigraphics(screen, bx, by, Borders.BottomLeft, g.bordersColor)
|
||||
PrintJoinedSemigraphics(screen, bx, by, Borders.BottomLeft, borderStyle)
|
||||
}
|
||||
bx, by = item.x+item.w, item.y+item.h // Bottom-right corner.
|
||||
if bx >= 0 && bx < screenWidth && by >= 0 && by < screenHeight {
|
||||
PrintJoinedSemigraphics(screen, bx, by, Borders.BottomRight, g.bordersColor)
|
||||
PrintJoinedSemigraphics(screen, bx, by, Borders.BottomRight, borderStyle)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
4
list.go
4
list.go
@ -477,7 +477,7 @@ func (l *List) Draw(screen tcell.Screen) {
|
||||
}
|
||||
|
||||
// Main text.
|
||||
_, printedWidth, _, end := printWithStyle(screen, item.MainText, x, y, l.horizontalOffset, width, AlignLeft, tcell.StyleDefault.Foreground(l.mainTextColor))
|
||||
_, printedWidth, _, end := printWithStyle(screen, item.MainText, x, y, l.horizontalOffset, width, AlignLeft, tcell.StyleDefault.Foreground(l.mainTextColor), true)
|
||||
if printedWidth > maxWidth {
|
||||
maxWidth = printedWidth
|
||||
}
|
||||
@ -513,7 +513,7 @@ func (l *List) Draw(screen tcell.Screen) {
|
||||
|
||||
// Secondary text.
|
||||
if l.showSecondaryText {
|
||||
_, printedWidth, _, end := printWithStyle(screen, item.SecondaryText, x, y, l.horizontalOffset, width, AlignLeft, tcell.StyleDefault.Foreground(l.secondaryTextColor))
|
||||
_, printedWidth, _, end := printWithStyle(screen, item.SecondaryText, x, y, l.horizontalOffset, width, AlignLeft, tcell.StyleDefault.Foreground(l.secondaryTextColor), true)
|
||||
if printedWidth > maxWidth {
|
||||
maxWidth = printedWidth
|
||||
}
|
||||
|
@ -270,12 +270,10 @@ var SemigraphicJoints = map[string]rune{
|
||||
}
|
||||
|
||||
// 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)
|
||||
// position with the given style, joining it with any existing semigraphics
|
||||
// rune.At this point, only regular single line borders are supported.
|
||||
func PrintJoinedSemigraphics(screen tcell.Screen, x, y int, ch rune, style tcell.Style) {
|
||||
previous, _, _, _ := screen.GetContent(x, y)
|
||||
|
||||
// What's the resulting rune?
|
||||
var result rune
|
||||
|
58
table.go
58
table.go
@ -36,6 +36,10 @@ type TableCell struct {
|
||||
// The background color of the cell.
|
||||
BackgroundColor tcell.Color
|
||||
|
||||
// If set to true, the BackgroundColor is not used and the cell will have
|
||||
// the background color of the table.
|
||||
Transparent bool
|
||||
|
||||
// The style attributes of the cell.
|
||||
Attributes tcell.AttrMask
|
||||
|
||||
@ -59,7 +63,8 @@ func NewTableCell(text string) *TableCell {
|
||||
Text: text,
|
||||
Align: AlignLeft,
|
||||
Color: Styles.PrimaryTextColor,
|
||||
BackgroundColor: tcell.ColorDefault,
|
||||
BackgroundColor: Styles.PrimitiveBackgroundColor,
|
||||
Transparent: true,
|
||||
}
|
||||
}
|
||||
|
||||
@ -111,10 +116,19 @@ func (c *TableCell) SetTextColor(color tcell.Color) *TableCell {
|
||||
return c
|
||||
}
|
||||
|
||||
// SetBackgroundColor sets the cell's background color. Set to
|
||||
// tcell.ColorDefault to use the table's background color.
|
||||
// SetBackgroundColor sets the cell's background color. This will also cause the
|
||||
// cell's Transparent flag to be set to "false".
|
||||
func (c *TableCell) SetBackgroundColor(color tcell.Color) *TableCell {
|
||||
c.BackgroundColor = color
|
||||
c.Transparent = false
|
||||
return c
|
||||
}
|
||||
|
||||
// SetTransparency sets the background transparency of this cell. A value of
|
||||
// "true" will cause the cell to use the table's background color. A value of
|
||||
// "false" will cause it to use its own background color.
|
||||
func (c *TableCell) SetTransparency(transparent bool) *TableCell {
|
||||
c.Transparent = transparent
|
||||
return c
|
||||
}
|
||||
|
||||
@ -326,7 +340,7 @@ func (t *Table) SetBordersColor(color tcell.Color) *Table {
|
||||
//
|
||||
// To reset a previous setting to its default, make the following call:
|
||||
//
|
||||
// table.SetSelectedStyle(tcell.ColorDefault, tcell.ColorDefault, 0)
|
||||
// table.SetSelectedStyle(tcell.Style{})
|
||||
func (t *Table) SetSelectedStyle(style tcell.Style) *Table {
|
||||
t.selectedStyle = style
|
||||
return t
|
||||
@ -886,10 +900,10 @@ ColumnLoop:
|
||||
finalWidth = width - columnX - 1
|
||||
}
|
||||
cell.x, cell.y, cell.width = x+columnX+1, y+rowY, finalWidth
|
||||
_, printed, _, _ := printWithStyle(screen, cell.Text, x+columnX+1, y+rowY, 0, finalWidth, cell.Align, tcell.StyleDefault.Foreground(cell.Color).Attributes(cell.Attributes))
|
||||
_, printed, _, _ := printWithStyle(screen, cell.Text, x+columnX+1, y+rowY, 0, finalWidth, cell.Align, tcell.StyleDefault.Foreground(cell.Color).Attributes(cell.Attributes), true)
|
||||
if TaggedStringWidth(cell.Text)-printed > 0 && printed > 0 {
|
||||
_, _, style, _ := screen.GetContent(x+columnX+finalWidth, y+rowY)
|
||||
printWithStyle(screen, string(SemigraphicsHorizontalEllipsis), x+columnX+finalWidth, 0, y+rowY, 1, AlignLeft, style)
|
||||
printWithStyle(screen, string(SemigraphicsHorizontalEllipsis), x+columnX+finalWidth, 0, y+rowY, 1, AlignLeft, style, false)
|
||||
}
|
||||
}
|
||||
|
||||
@ -927,29 +941,23 @@ ColumnLoop:
|
||||
}
|
||||
|
||||
// Helper function which colors the background of a box.
|
||||
// backgroundColor == tcell.ColorDefault => Don't color the background.
|
||||
// textColor == tcell.ColorDefault => Don't change the text color.
|
||||
// backgroundTransparent == true => Don't modify background color (when invert == false).
|
||||
// textTransparent == true => Don't modify text color (when invert == false).
|
||||
// attr == 0 => Don't change attributes.
|
||||
// invert == true => Ignore attr, set text to backgroundColor or t.backgroundColor;
|
||||
// set background to textColor.
|
||||
colorBackground := func(fromX, fromY, w, h int, backgroundColor, textColor tcell.Color, attr tcell.AttrMask, invert bool) {
|
||||
colorBackground := func(fromX, fromY, w, h int, backgroundColor, textColor tcell.Color, backgroundTransparent, textTransparent bool, attr tcell.AttrMask, invert bool) {
|
||||
for by := 0; by < h && fromY+by < y+height; by++ {
|
||||
for bx := 0; bx < w && fromX+bx < x+width; bx++ {
|
||||
m, c, style, _ := screen.GetContent(fromX+bx, fromY+by)
|
||||
fg, bg, a := style.Decompose()
|
||||
if invert {
|
||||
if fg == textColor || fg == t.bordersColor {
|
||||
fg = backgroundColor
|
||||
}
|
||||
if fg == tcell.ColorDefault {
|
||||
fg = t.backgroundColor
|
||||
}
|
||||
style = style.Background(textColor).Foreground(fg)
|
||||
style = style.Background(textColor).Foreground(backgroundColor)
|
||||
} else {
|
||||
if backgroundColor != tcell.ColorDefault {
|
||||
if !backgroundTransparent {
|
||||
bg = backgroundColor
|
||||
}
|
||||
if textColor != tcell.ColorDefault {
|
||||
if !textTransparent {
|
||||
fg = textColor
|
||||
}
|
||||
if attr != 0 {
|
||||
@ -966,7 +974,7 @@ ColumnLoop:
|
||||
// the drawing of a cell by background color, selected cells last.
|
||||
type cellInfo struct {
|
||||
x, y, w, h int
|
||||
text tcell.Color
|
||||
cell *TableCell
|
||||
selected bool
|
||||
}
|
||||
cellsByBackgroundColor := make(map[tcell.Color][]*cellInfo)
|
||||
@ -994,7 +1002,7 @@ ColumnLoop:
|
||||
y: by,
|
||||
w: bw,
|
||||
h: bh,
|
||||
text: cell.Color,
|
||||
cell: cell,
|
||||
selected: cellSelected,
|
||||
})
|
||||
if !ok {
|
||||
@ -1016,15 +1024,15 @@ ColumnLoop:
|
||||
selFg, selBg, selAttr := t.selectedStyle.Decompose()
|
||||
for _, bgColor := range backgroundColors {
|
||||
entries := cellsByBackgroundColor[bgColor]
|
||||
for _, cell := range entries {
|
||||
if cell.selected {
|
||||
for _, info := range entries {
|
||||
if info.selected {
|
||||
if t.selectedStyle != (tcell.Style{}) {
|
||||
defer colorBackground(cell.x, cell.y, cell.w, cell.h, selBg, selFg, selAttr, false)
|
||||
defer colorBackground(info.x, info.y, info.w, info.h, selBg, selFg, false, false, selAttr, false)
|
||||
} else {
|
||||
defer colorBackground(cell.x, cell.y, cell.w, cell.h, bgColor, cell.text, 0, true)
|
||||
defer colorBackground(info.x, info.y, info.w, info.h, bgColor, info.cell.Color, false, false, 0, true)
|
||||
}
|
||||
} else {
|
||||
colorBackground(cell.x, cell.y, cell.w, cell.h, bgColor, tcell.ColorDefault, 0, false)
|
||||
colorBackground(info.x, info.y, info.w, info.h, bgColor, info.cell.Color, info.cell.Transparent, true, 0, false)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1005,7 +1005,7 @@ func (t *TextView) Draw(screen tcell.Screen) {
|
||||
}
|
||||
|
||||
// Draw the buffer.
|
||||
defaultStyle := tcell.StyleDefault.Foreground(t.textColor)
|
||||
defaultStyle := tcell.StyleDefault.Foreground(t.textColor).Background(t.backgroundColor)
|
||||
for line := t.lineOffset; line < len(t.index); line++ {
|
||||
// Are we done?
|
||||
if line-t.lineOffset >= height || y+line-t.lineOffset >= totalHeight {
|
||||
@ -1089,9 +1089,7 @@ func (t *TextView) Draw(screen tcell.Screen) {
|
||||
}
|
||||
|
||||
// Mix the existing style with the new style.
|
||||
_, _, existingStyle, _ := screen.GetContent(x+posX, y+line-t.lineOffset)
|
||||
_, background, _ := existingStyle.Decompose()
|
||||
style := overlayStyle(background, defaultStyle, foregroundColor, backgroundColor, attributes)
|
||||
style := overlayStyle(defaultStyle, foregroundColor, backgroundColor, attributes)
|
||||
|
||||
// Do we highlight this character?
|
||||
var highlighted bool
|
||||
@ -1102,7 +1100,7 @@ func (t *TextView) Draw(screen tcell.Screen) {
|
||||
}
|
||||
if highlighted {
|
||||
fg, bg, _ := style.Decompose()
|
||||
if bg == tcell.ColorDefault {
|
||||
if bg == t.backgroundColor {
|
||||
r, g, b := fg.RGB()
|
||||
c := colorful.Color{R: float64(r) / 255, G: float64(g) / 255, B: float64(b) / 255}
|
||||
_, _, li := c.Hcl()
|
||||
|
@ -672,7 +672,7 @@ func (t *TreeView) Draw(screen tcell.Screen) {
|
||||
// Draw a branch if this ancestor is not a last child.
|
||||
if ancestor.parent.children[len(ancestor.parent.children)-1] != ancestor {
|
||||
if posY-1 >= y && ancestor.textX > ancestor.graphicsX {
|
||||
PrintJoinedSemigraphics(screen, x+ancestor.graphicsX, posY-1, Borders.Vertical, t.graphicsColor)
|
||||
PrintJoinedSemigraphics(screen, x+ancestor.graphicsX, posY-1, Borders.Vertical, lineStyle)
|
||||
}
|
||||
if posY < y+height {
|
||||
screen.SetContent(x+ancestor.graphicsX, posY, Borders.Vertical, nil, lineStyle)
|
||||
@ -684,7 +684,7 @@ func (t *TreeView) Draw(screen tcell.Screen) {
|
||||
if node.textX > node.graphicsX && node.graphicsX < width {
|
||||
// Connect to the node above.
|
||||
if posY-1 >= y && t.nodes[index-1].graphicsX <= node.graphicsX && t.nodes[index-1].textX > node.graphicsX {
|
||||
PrintJoinedSemigraphics(screen, x+node.graphicsX, posY-1, Borders.TopLeft, t.graphicsColor)
|
||||
PrintJoinedSemigraphics(screen, x+node.graphicsX, posY-1, Borders.TopLeft, lineStyle)
|
||||
}
|
||||
|
||||
// Join this node.
|
||||
@ -707,11 +707,11 @@ func (t *TreeView) Draw(screen tcell.Screen) {
|
||||
|
||||
// Text.
|
||||
if node.textX+prefixWidth < width {
|
||||
style := tcell.StyleDefault.Foreground(node.color)
|
||||
style := tcell.StyleDefault.Background(t.backgroundColor).Foreground(node.color)
|
||||
if node == t.currentNode {
|
||||
style = tcell.StyleDefault.Background(node.color).Foreground(t.backgroundColor)
|
||||
}
|
||||
printWithStyle(screen, node.text, x+node.textX+prefixWidth, posY, 0, width-node.textX-prefixWidth, AlignLeft, style)
|
||||
printWithStyle(screen, node.text, x+node.textX+prefixWidth, posY, 0, width-node.textX-prefixWidth, AlignLeft, style, false)
|
||||
}
|
||||
}
|
||||
|
||||
|
61
util.go
61
util.go
@ -110,27 +110,16 @@ func styleFromTag(fgColor, bgColor, attributes string, tagSubstrings []string) (
|
||||
return fgColor, bgColor, attributes
|
||||
}
|
||||
|
||||
// overlayStyle mixes a background color with a foreground color (fgColor),
|
||||
// a (possibly new) background color (bgColor), and style attributes, and
|
||||
// returns the resulting style. For a definition of the colors and attributes,
|
||||
// see styleFromTag(). Reset instructions cause the corresponding part of the
|
||||
// default style to be used.
|
||||
func overlayStyle(background tcell.Color, defaultStyle tcell.Style, fgColor, bgColor, attributes string) tcell.Style {
|
||||
defFg, defBg, defAttr := defaultStyle.Decompose()
|
||||
style := defaultStyle.Background(background)
|
||||
// overlayStyle calculates a new style based on "style" and applying tag-based
|
||||
// colors/attributes to it (see also styleFromTag()).
|
||||
func overlayStyle(style tcell.Style, fgColor, bgColor, attributes string) tcell.Style {
|
||||
_, _, defAttr := style.Decompose()
|
||||
|
||||
style = style.Foreground(defFg)
|
||||
if fgColor != "" {
|
||||
if fgColor == "-" {
|
||||
style = style.Foreground(defFg)
|
||||
} else {
|
||||
style = style.Foreground(tcell.GetColor(fgColor))
|
||||
}
|
||||
if fgColor != "" && fgColor != "-" {
|
||||
style = style.Foreground(tcell.GetColor(fgColor))
|
||||
}
|
||||
|
||||
if bgColor == "-" || bgColor == "" && defBg != tcell.ColorDefault {
|
||||
style = style.Background(defBg)
|
||||
} else if bgColor != "" {
|
||||
if bgColor != "" && bgColor != "-" {
|
||||
style = style.Background(tcell.GetColor(bgColor))
|
||||
}
|
||||
|
||||
@ -237,15 +226,17 @@ func decomposeString(text string, findColors, findRegions bool) (colorIndices []
|
||||
// Returns the number of actual bytes of the text printed (including color tags)
|
||||
// and the actual width used for the printed runes.
|
||||
func Print(screen tcell.Screen, text string, x, y, maxWidth, align int, color tcell.Color) (int, int) {
|
||||
bytes, width, _, _ := printWithStyle(screen, text, x, y, 0, maxWidth, align, tcell.StyleDefault.Foreground(color))
|
||||
bytes, width, _, _ := printWithStyle(screen, text, x, y, 0, maxWidth, align, tcell.StyleDefault.Foreground(color), true)
|
||||
return bytes, width
|
||||
}
|
||||
|
||||
// printWithStyle works like Print() but it takes a style instead of just a
|
||||
// foreground color. The skipWidth parameter specifies the number of cells
|
||||
// skipped at the beginning of the text. It also returns the start and end index
|
||||
// (exclusively) of the text actually printed.
|
||||
func printWithStyle(screen tcell.Screen, text string, x, y, skipWidth, maxWidth, align int, style tcell.Style) (int, int, int, int) {
|
||||
// (exclusively) of the text actually printed. If maintainBackground is "true",
|
||||
// The existing screen background is not changed (i.e. the style's background
|
||||
// color is ignored).
|
||||
func printWithStyle(screen tcell.Screen, text string, x, y, skipWidth, maxWidth, align int, style tcell.Style, maintainBackground bool) (int, int, int, int) {
|
||||
totalWidth, totalHeight := screen.Size()
|
||||
if maxWidth <= 0 || len(text) == 0 || y < 0 || y >= totalHeight {
|
||||
return 0, 0, 0, 0
|
||||
@ -258,19 +249,19 @@ func printWithStyle(screen tcell.Screen, text string, x, y, skipWidth, maxWidth,
|
||||
if align == AlignRight {
|
||||
if strippedWidth-skipWidth <= maxWidth {
|
||||
// There's enough space for the entire text.
|
||||
return printWithStyle(screen, text, x+maxWidth-strippedWidth+skipWidth, y, skipWidth, maxWidth, AlignLeft, style)
|
||||
return printWithStyle(screen, text, x+maxWidth-strippedWidth+skipWidth, y, skipWidth, maxWidth, AlignLeft, style, maintainBackground)
|
||||
}
|
||||
// Trim characters off the beginning.
|
||||
var (
|
||||
bytes, width, colorPos, escapePos, tagOffset, from, to int
|
||||
foregroundColor, backgroundColor, attributes string
|
||||
)
|
||||
_, originalBackground, _ := style.Decompose()
|
||||
originalStyle := style
|
||||
iterateString(strippedText, func(main rune, comb []rune, textPos, textWidth, screenPos, screenWidth int) bool {
|
||||
// Update color/escape tag offset and style.
|
||||
if colorPos < len(colorIndices) && textPos+tagOffset >= colorIndices[colorPos][0] && textPos+tagOffset < colorIndices[colorPos][1] {
|
||||
foregroundColor, backgroundColor, attributes = styleFromTag(foregroundColor, backgroundColor, attributes, colors[colorPos])
|
||||
style = overlayStyle(originalBackground, style, foregroundColor, backgroundColor, attributes)
|
||||
style = overlayStyle(originalStyle, foregroundColor, backgroundColor, attributes)
|
||||
tagOffset += colorIndices[colorPos][1] - colorIndices[colorPos][0]
|
||||
colorPos++
|
||||
}
|
||||
@ -286,7 +277,7 @@ func printWithStyle(screen tcell.Screen, text string, x, y, skipWidth, maxWidth,
|
||||
text = text[:escapeCharPos] + text[escapeCharPos+1:]
|
||||
}
|
||||
// Print and return.
|
||||
bytes, width, from, to = printWithStyle(screen, text[textPos+tagOffset:], x, y, 0, maxWidth, AlignLeft, style)
|
||||
bytes, width, from, to = printWithStyle(screen, text[textPos+tagOffset:], x, y, 0, maxWidth, AlignLeft, style, maintainBackground)
|
||||
from += textPos + tagOffset
|
||||
to += textPos + tagOffset
|
||||
return true
|
||||
@ -297,11 +288,11 @@ func printWithStyle(screen tcell.Screen, text string, x, y, skipWidth, maxWidth,
|
||||
} else if align == AlignCenter {
|
||||
if strippedWidth-skipWidth == maxWidth {
|
||||
// Use the exact space.
|
||||
return printWithStyle(screen, text, x, y, skipWidth, maxWidth, AlignLeft, style)
|
||||
return printWithStyle(screen, text, x, y, skipWidth, maxWidth, AlignLeft, style, maintainBackground)
|
||||
} else if strippedWidth-skipWidth < maxWidth {
|
||||
// We have more space than we need.
|
||||
half := (maxWidth - strippedWidth + skipWidth) / 2
|
||||
return printWithStyle(screen, text, x+half, y, skipWidth, maxWidth-half, AlignLeft, style)
|
||||
return printWithStyle(screen, text, x+half, y, skipWidth, maxWidth-half, AlignLeft, style, maintainBackground)
|
||||
} else {
|
||||
// Chop off runes until we have a perfect fit.
|
||||
var choppedLeft, choppedRight, leftIndex, rightIndex int
|
||||
@ -334,7 +325,7 @@ func printWithStyle(screen tcell.Screen, text string, x, y, skipWidth, maxWidth,
|
||||
colorPos, escapePos, tagOffset int
|
||||
foregroundColor, backgroundColor, attributes string
|
||||
)
|
||||
_, originalBackground, _ := style.Decompose()
|
||||
originalStyle := style
|
||||
for index := range strippedText {
|
||||
// We only need the offset of the left index.
|
||||
if index > leftIndex {
|
||||
@ -351,7 +342,7 @@ func printWithStyle(screen tcell.Screen, text string, x, y, skipWidth, maxWidth,
|
||||
if colorPos < len(colorIndices) && index+tagOffset >= colorIndices[colorPos][0] && index+tagOffset < colorIndices[colorPos][1] {
|
||||
if index <= leftIndex {
|
||||
foregroundColor, backgroundColor, attributes = styleFromTag(foregroundColor, backgroundColor, attributes, colors[colorPos])
|
||||
style = overlayStyle(originalBackground, style, foregroundColor, backgroundColor, attributes)
|
||||
style = overlayStyle(originalStyle, foregroundColor, backgroundColor, attributes)
|
||||
}
|
||||
tagOffset += colorIndices[colorPos][1] - colorIndices[colorPos][0]
|
||||
colorPos++
|
||||
@ -361,7 +352,7 @@ func printWithStyle(screen tcell.Screen, text string, x, y, skipWidth, maxWidth,
|
||||
escapePos++
|
||||
}
|
||||
}
|
||||
bytes, width, from, to := printWithStyle(screen, text[leftIndex+tagOffset:], x, y, 0, maxWidth, AlignLeft, style)
|
||||
bytes, width, from, to := printWithStyle(screen, text[leftIndex+tagOffset:], x, y, 0, maxWidth, AlignLeft, style, maintainBackground)
|
||||
from += leftIndex + tagOffset
|
||||
to += leftIndex + tagOffset
|
||||
return bytes, width, from, to
|
||||
@ -407,9 +398,13 @@ func printWithStyle(screen tcell.Screen, text string, x, y, skipWidth, maxWidth,
|
||||
|
||||
// Print the rune sequence.
|
||||
finalX := x + drawnWidth
|
||||
_, _, finalStyle, _ := screen.GetContent(finalX, y)
|
||||
_, background, _ := finalStyle.Decompose()
|
||||
finalStyle = overlayStyle(background, style, foregroundColor, backgroundColor, attributes)
|
||||
finalStyle := style
|
||||
if maintainBackground {
|
||||
_, _, existingStyle, _ := screen.GetContent(finalX, y)
|
||||
_, background, _ := existingStyle.Decompose()
|
||||
finalStyle = finalStyle.Background(background)
|
||||
}
|
||||
finalStyle = overlayStyle(finalStyle, foregroundColor, backgroundColor, attributes)
|
||||
for offset := screenWidth - 1; offset >= 0; offset-- {
|
||||
// To avoid undesired effects, we populate all cells.
|
||||
if offset == 0 {
|
||||
|
Loading…
x
Reference in New Issue
Block a user