diff --git a/widgets/table/content.go b/widgets/table/content.go index 540b66b..790be5f 100644 --- a/widgets/table/content.go +++ b/widgets/table/content.go @@ -230,6 +230,11 @@ func (c *Content) validate() error { return validateContent(c) } +// hasBorder asserts whether the content has a border configured. +func (c *Content) hasBorder() bool { + return c.opts.border != linestyle.None +} + // AddRows adds the rows to the content. func (c *Content) AddRows(rows []*Row) error { c.mu.Lock() diff --git a/widgets/table/layout.go b/widgets/table/layout.go index 868a5e0..50bcc7c 100644 --- a/widgets/table/layout.go +++ b/widgets/table/layout.go @@ -18,6 +18,8 @@ package table import ( "image" + + "github.com/mum4k/termdash/internal/numbers" ) // contentLayout determines how the content gets placed onto the canvas. @@ -59,17 +61,17 @@ func newContentLayout(content *Content, cvsAr image.Rectangle) (*contentLayout, }, nil } -/* -TODO: -- given cvsWidth, determine space available to cells (minus border and padding). -- columnWidths to account for padding -- calculate column widths +// cellUsable determines the usable width for the specified cell given the +// column widths. This accounts for additional space requirements when border +// or padding is used. Can return zero if no width is available for the cell. +func cellUsableWidth(content *Content, cell *Cell, cw columnWidth) int { + sub := 0 + if content.hasBorder() { + // Reserve one terminal cell per table cell for the left border. + sub++ + } + sub += 2 * cell.hierarchical.getHorizontalPadding() -- each row should report its required height - accounting for content of cells + padding -- process to draw row by row - top down and bottom up, account for when doesn't fit. - -- func: given a cell - give me its area -- each cell - draw itself on a canvas, best effort on size. - -- ensure content copies data given by the user to prevent races. -*/ + _, usable := numbers.MinMaxInts([]int{0, int(cw) - sub}) + return usable +} diff --git a/widgets/table/layout_widths.go b/widgets/table/layout_widths.go index 6546411..de8e1a9 100644 --- a/widgets/table/layout_widths.go +++ b/widgets/table/layout_widths.go @@ -29,9 +29,28 @@ type columnWidth int // columnWidths given the content and the available canvas width returns the // widths of individual columns. -// The argument cvsWidth is assumed to exclude space required for any border, -// padding or spacing. +// If a border is configured, the returned column widths will reserve one +// terminal cell for the right-most portion of the border. The calculation of +// column widths accounts for border inside cells and for any horizontal +// padding. The returned column width include the border and padding. +// +// Example: +// +// cvsWidth of 17, returns two columns of width 8 and one terminal cell is +// reserved for the right-most border. +// ----------------- +// | cell1 | cell2 | +// ^ ^ ^ right-most border subtracted from the width. +// padding +// ^ border accounted for per cell. func columnWidths(content *Content, cvsWidth int) ([]columnWidth, error) { + if content.hasBorder() { + // Account for one terminal cell for the right-most part of the border. + // Then account for one terminal cell used by the border at each table + // cell. + cvsWidth-- + } + if wp := content.opts.columnWidthsPercent; len(wp) > 0 { // If the user provided widths for the columns, use those. widths, err := splitToPercent(cvsWidth, wp) @@ -189,6 +208,10 @@ func trimmedRows(content *Content, colIdx int, colWidth columnWidth) int { continue } available := int(colWidth) - 2*tgtCell.hierarchical.getHorizontalPadding() + if content.hasBorder() { + available-- + } + if tgtCell.width > available { trimmed++ } diff --git a/widgets/table/layout_widths_test.go b/widgets/table/layout_widths_test.go index bc5bca0..6fd0484 100644 --- a/widgets/table/layout_widths_test.go +++ b/widgets/table/layout_widths_test.go @@ -18,6 +18,7 @@ import ( "testing" "github.com/kylelemons/godebug/pretty" + "github.com/mum4k/termdash/linestyle" ) func TestColumnWidths(t *testing.T) { @@ -78,6 +79,29 @@ func TestColumnWidths(t *testing.T) { cvsWidth: 6, want: []columnWidth{3, 3}, }, + { + desc: "accounts for space needed for the border", + columns: Columns(2), + rows: []*Row{ + NewRow( + NewCell("ab"), + NewCell("cde"), + ), + NewRow( + NewCell("a"), + NewCell("cde"), + ), + NewRow( + NewCell(""), + NewCell("cde"), + ), + }, + opts: []ContentOption{ + Border(linestyle.Light), + }, + cvsWidth: 7, + want: []columnWidth{2, 4}, + }, { desc: "horizontal padding at content level trims", columns: Columns(2),