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:
parent
fe30520195
commit
ba670d23ba
23
box.go
23
box.go
@ -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.
|
||||
|
4
list.go
4
list.go
@ -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
|
||||
|
3
table.go
3
table.go
@ -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)
|
||||
|
145
textview.go
145
textview.go
@ -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
|
||||
|
@ -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 {
|
||||
|
5
util.go
5
util.go
@ -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
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user