diff --git a/box.go b/box.go index 582d039..fbd0c18 100644 --- a/box.go +++ b/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) diff --git a/checkbox.go b/checkbox.go index 1537a72..d9a8633 100644 --- a/checkbox.go +++ b/checkbox.go @@ -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. diff --git a/flex.go b/flex.go index a574d3c..b4fb2da 100644 --- a/flex.go +++ b/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 } diff --git a/go.mod b/go.mod index c39712d..733291d 100644 --- a/go.mod +++ b/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 diff --git a/go.sum b/go.sum index d5c86cc..dd04904 100644 --- a/go.sum +++ b/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= diff --git a/grid.go b/grid.go index 4933594..5825df6 100644 --- a/grid.go +++ b/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) } } } diff --git a/list.go b/list.go index cd282c9..657baec 100644 --- a/list.go +++ b/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 } diff --git a/semigraphics.go b/semigraphics.go index 1815bfa..c7607a2 100644 --- a/semigraphics.go +++ b/semigraphics.go @@ -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 diff --git a/table.go b/table.go index 9ad0c10..8395140 100644 --- a/table.go +++ b/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) } } } diff --git a/textview.go b/textview.go index aa6191a..1a445bb 100644 --- a/textview.go +++ b/textview.go @@ -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() diff --git a/treeview.go b/treeview.go index 1c424e3..cb15dc5 100644 --- a/treeview.go +++ b/treeview.go @@ -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) } } diff --git a/util.go b/util.go index 47a6b80..440c7be 100644 --- a/util.go +++ b/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 {