1
0
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:
Oliver 2021-03-12 18:48:52 +01:00
parent ae065beb93
commit ae9464cc35
12 changed files with 106 additions and 98 deletions

7
box.go
View File

@ -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)

View File

@ -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
View File

@ -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
View File

@ -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
View File

@ -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
View File

@ -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)
}
}
}

View File

@ -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
}

View File

@ -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

View File

@ -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)
}
}
}

View File

@ -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()

View File

@ -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
View File

@ -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 {