2
0
mirror of https://github.com/rivo/tview.git synced 2024-11-12 19:10:28 +00:00

The inner area of a Box does not clamp to screen borders anymore. Consequently added some drawing optimization to primitives. Resolves #405

This commit is contained in:
Oliver 2020-02-19 18:31:32 +01:00
parent fe30520195
commit ba670d23ba
6 changed files with 85 additions and 98 deletions

23
box.go
View File

@ -314,29 +314,6 @@ func (b *Box) Draw(screen tcell.Screen) {
b.innerX = -1
b.innerX, b.innerY, b.innerWidth, b.innerHeight = b.GetInnerRect()
}
// Clamp inner rect to screen.
width, height := screen.Size()
if b.innerX < 0 {
b.innerWidth += b.innerX
b.innerX = 0
}
if b.innerX+b.innerWidth >= width {
b.innerWidth = width - b.innerX
}
if b.innerY+b.innerHeight >= height {
b.innerHeight = height - b.innerY
}
if b.innerY < 0 {
b.innerHeight += b.innerY
b.innerY = 0
}
if b.innerWidth < 0 {
b.innerWidth = 0
}
if b.innerHeight < 0 {
b.innerHeight = 0
}
}
// Focus is called when this primitive receives focus.

View File

@ -394,6 +394,10 @@ func (l *List) Draw(screen tcell.Screen) {
// Determine the dimensions.
x, y, width, height := l.GetInnerRect()
bottomLimit := y + height
_, totalHeight := screen.Size()
if bottomLimit > totalHeight {
bottomLimit = totalHeight
}
// Do we show any shortcuts?
var showShortcuts bool

View File

@ -563,6 +563,7 @@ func (t *Table) Draw(screen tcell.Screen) {
t.Box.Draw(screen)
// What's our available screen space?
_, totalHeight := screen.Size()
x, y, width, height := t.GetInnerRect()
if t.borders {
t.visibleRows = height / 2
@ -800,7 +801,7 @@ ColumnLoop:
}
drawBorder(columnX, rowY, ch)
rowY++
if rowY >= height {
if rowY >= height || y+rowY >= totalHeight {
break // No space for the text anymore.
}
drawBorder(columnX, rowY, Borders.Vertical)

View File

@ -752,6 +752,7 @@ func (t *TextView) Draw(screen tcell.Screen) {
t.Lock()
defer t.Unlock()
t.Box.Draw(screen)
totalWidth, totalHeight := screen.Size()
// Get the available size.
x, y, width, height := t.GetInnerRect()
@ -838,7 +839,7 @@ func (t *TextView) Draw(screen tcell.Screen) {
defaultStyle := tcell.StyleDefault.Foreground(t.textColor)
for line := t.lineOffset; line < len(t.index); line++ {
// Are we done?
if line-t.lineOffset >= height {
if line-t.lineOffset >= height || y+line-t.lineOffset >= totalHeight {
break
}
@ -868,82 +869,84 @@ func (t *TextView) Draw(screen tcell.Screen) {
}
// Print the line.
var colorPos, regionPos, escapePos, tagOffset, skipped int
iterateString(strippedText, func(main rune, comb []rune, textPos, textWidth, screenPos, screenWidth int) bool {
// Process tags.
for {
if colorPos < len(colorTags) && textPos+tagOffset >= colorTagIndices[colorPos][0] && textPos+tagOffset < colorTagIndices[colorPos][1] {
// Get the color.
foregroundColor, backgroundColor, attributes = styleFromTag(foregroundColor, backgroundColor, attributes, colorTags[colorPos])
tagOffset += colorTagIndices[colorPos][1] - colorTagIndices[colorPos][0]
colorPos++
} else if regionPos < len(regionIndices) && textPos+tagOffset >= regionIndices[regionPos][0] && textPos+tagOffset < regionIndices[regionPos][1] {
// Get the region.
regionID = regions[regionPos][1]
tagOffset += regionIndices[regionPos][1] - regionIndices[regionPos][0]
regionPos++
} else {
break
}
}
// Skip the second-to-last character of an escape tag.
if escapePos < len(escapeIndices) && textPos+tagOffset == escapeIndices[escapePos][1]-2 {
tagOffset++
escapePos++
}
// 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)
// Do we highlight this character?
var highlighted bool
if len(regionID) > 0 {
if _, ok := t.highlights[regionID]; ok {
highlighted = true
}
}
if highlighted {
fg, bg, _ := style.Decompose()
if bg == tcell.ColorDefault {
r, g, b := fg.RGB()
c := colorful.Color{R: float64(r) / 255, G: float64(g) / 255, B: float64(b) / 255}
_, _, li := c.Hcl()
if li < .5 {
bg = tcell.ColorWhite
if y+line-t.lineOffset >= 0 {
var colorPos, regionPos, escapePos, tagOffset, skipped int
iterateString(strippedText, func(main rune, comb []rune, textPos, textWidth, screenPos, screenWidth int) bool {
// Process tags.
for {
if colorPos < len(colorTags) && textPos+tagOffset >= colorTagIndices[colorPos][0] && textPos+tagOffset < colorTagIndices[colorPos][1] {
// Get the color.
foregroundColor, backgroundColor, attributes = styleFromTag(foregroundColor, backgroundColor, attributes, colorTags[colorPos])
tagOffset += colorTagIndices[colorPos][1] - colorTagIndices[colorPos][0]
colorPos++
} else if regionPos < len(regionIndices) && textPos+tagOffset >= regionIndices[regionPos][0] && textPos+tagOffset < regionIndices[regionPos][1] {
// Get the region.
regionID = regions[regionPos][1]
tagOffset += regionIndices[regionPos][1] - regionIndices[regionPos][0]
regionPos++
} else {
bg = tcell.ColorBlack
break
}
}
style = style.Background(fg).Foreground(bg)
}
// Skip to the right.
if !t.wrap && skipped < skip {
skipped += screenWidth
return false
}
// Stop at the right border.
if posX+screenWidth > width {
return true
}
// Draw the character.
for offset := screenWidth - 1; offset >= 0; offset-- {
if offset == 0 {
screen.SetContent(x+posX+offset, y+line-t.lineOffset, main, comb, style)
} else {
screen.SetContent(x+posX+offset, y+line-t.lineOffset, ' ', nil, style)
// Skip the second-to-last character of an escape tag.
if escapePos < len(escapeIndices) && textPos+tagOffset == escapeIndices[escapePos][1]-2 {
tagOffset++
escapePos++
}
}
// Advance.
posX += screenWidth
return false
})
// 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)
// Do we highlight this character?
var highlighted bool
if len(regionID) > 0 {
if _, ok := t.highlights[regionID]; ok {
highlighted = true
}
}
if highlighted {
fg, bg, _ := style.Decompose()
if bg == tcell.ColorDefault {
r, g, b := fg.RGB()
c := colorful.Color{R: float64(r) / 255, G: float64(g) / 255, B: float64(b) / 255}
_, _, li := c.Hcl()
if li < .5 {
bg = tcell.ColorWhite
} else {
bg = tcell.ColorBlack
}
}
style = style.Background(fg).Foreground(bg)
}
// Skip to the right.
if !t.wrap && skipped < skip {
skipped += screenWidth
return false
}
// Stop at the right border.
if posX+screenWidth > width || x+posX >= totalWidth {
return true
}
// Draw the character.
for offset := screenWidth - 1; offset >= 0; offset-- {
if offset == 0 {
screen.SetContent(x+posX+offset, y+line-t.lineOffset, main, comb, style)
} else {
screen.SetContent(x+posX+offset, y+line-t.lineOffset, ' ', nil, style)
}
}
// Advance.
posX += screenWidth
return false
})
}
}
// If this view is not scrollable, we'll purge the buffer of lines that have

View File

@ -575,6 +575,7 @@ func (t *TreeView) Draw(screen tcell.Screen) {
if t.root == nil {
return
}
_, totalHeight := screen.Size()
t.process()
@ -609,7 +610,7 @@ func (t *TreeView) Draw(screen tcell.Screen) {
lineStyle := tcell.StyleDefault.Background(t.backgroundColor).Foreground(t.graphicsColor)
for index, node := range t.nodes {
// Skip invisible parts.
if posY >= y+height+1 {
if posY >= y+height+1 || posY >= totalHeight {
break
}
if index < t.offsetY {

View File

@ -247,7 +247,8 @@ func Print(screen tcell.Screen, text string, x, y, maxWidth, align int, color tc
// printWithStyle works like Print() but it takes a style instead of just a
// foreground color.
func printWithStyle(screen tcell.Screen, text string, x, y, maxWidth, align int, style tcell.Style) (int, int) {
if maxWidth <= 0 || len(text) == 0 {
totalWidth, totalHeight := screen.Size()
if maxWidth <= 0 || len(text) == 0 || y < 0 || y >= totalHeight {
return 0, 0
}
@ -365,7 +366,7 @@ func printWithStyle(screen tcell.Screen, text string, x, y, maxWidth, align int,
)
iterateString(strippedText, func(main rune, comb []rune, textPos, length, screenPos, screenWidth int) bool {
// Only continue if there is still space.
if drawnWidth+screenWidth > maxWidth {
if drawnWidth+screenWidth > maxWidth || x+drawnWidth >= totalWidth {
return true
}