mirror of
https://github.com/unidoc/unipdf.git
synced 2025-05-09 19:29:34 +08:00
Implement AddSubtable method for the Table component (#400)
* Implement AddSubtable method for the table component with test case.
This commit is contained in:
parent
d21dab045b
commit
3712670413
@ -7,6 +7,7 @@ package creator
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"sort"
|
||||
|
||||
"github.com/unidoc/unidoc/common"
|
||||
"github.com/unidoc/unidoc/pdf/contentstream/draw"
|
||||
@ -64,12 +65,7 @@ func newTable(cols int) *Table {
|
||||
cells: []*TableCell{},
|
||||
}
|
||||
|
||||
// Initialize column widths as all equal.
|
||||
colWidth := float64(1.0) / float64(cols)
|
||||
for i := 0; i < cols; i++ {
|
||||
t.colWidths = append(t.colWidths, colWidth)
|
||||
}
|
||||
|
||||
t.resetColumnWidths()
|
||||
return t
|
||||
}
|
||||
|
||||
@ -86,6 +82,16 @@ func (table *Table) SetColumnWidths(widths ...float64) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (table *Table) resetColumnWidths() {
|
||||
table.colWidths = []float64{}
|
||||
colWidth := float64(1.0) / float64(table.cols)
|
||||
|
||||
// Initialize column widths as all equal.
|
||||
for i := 0; i < table.cols; i++ {
|
||||
table.colWidths = append(table.colWidths, colWidth)
|
||||
}
|
||||
}
|
||||
|
||||
// Height returns the total height of all rows.
|
||||
func (table *Table) Height() float64 {
|
||||
sum := float64(0.0)
|
||||
@ -166,6 +172,53 @@ func (table *Table) SetHeaderRows(startRow, endRow int) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
// AddSubtable copies the cells of the subtable in the table, starting with the
|
||||
// specified position. The table row and column indices are 1-based, which
|
||||
// makes the position of the first cell of the first row of the table 1,1.
|
||||
// The table is automatically extended if the subtable exceeds its columns.
|
||||
// This can happen when the subtable has more columns than the table or when
|
||||
// one or more columns of the subtable starting from the specified position
|
||||
// exceed the last column of the table.
|
||||
func (table *Table) AddSubtable(row, col int, subtable *Table) {
|
||||
for _, cell := range subtable.cells {
|
||||
c := &TableCell{}
|
||||
*c = *cell
|
||||
c.table = table
|
||||
|
||||
// Adjust added cell column. Add extra columns to the table to
|
||||
// accomodate the new cell, if needed.
|
||||
c.col += col - 1
|
||||
if colsLeft := table.cols - (c.col - 1); colsLeft < c.colspan {
|
||||
table.cols += c.colspan - colsLeft
|
||||
table.resetColumnWidths()
|
||||
common.Log.Debug("Table: subtable exceeds destination table. Expanding table to %d columns.", table.cols)
|
||||
}
|
||||
|
||||
// Extend number of rows, if needed.
|
||||
c.row += row - 1
|
||||
for c.row > table.rows {
|
||||
table.rows++
|
||||
table.rowHeights = append(table.rowHeights, table.defaultRowHeight)
|
||||
}
|
||||
|
||||
table.cells = append(table.cells, c)
|
||||
}
|
||||
|
||||
// Sort cells by row, column.
|
||||
sort.Slice(table.cells, func(i, j int) bool {
|
||||
rowA := table.cells[i].row
|
||||
rowB := table.cells[j].row
|
||||
if rowA < rowB {
|
||||
return true
|
||||
}
|
||||
if rowA > rowB {
|
||||
return false
|
||||
}
|
||||
|
||||
return table.cells[i].col < table.cells[j].col
|
||||
})
|
||||
}
|
||||
|
||||
// GeneratePageBlocks generate the page blocks. Multiple blocks are generated if the contents wrap
|
||||
// over multiple pages.
|
||||
// Implements the Drawable interface.
|
||||
|
@ -406,3 +406,94 @@ func TestTableHeaderTest(t *testing.T) {
|
||||
t.Fatalf("Fail: %v\n", err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestTableSubtables(t *testing.T) {
|
||||
c := New()
|
||||
headerColor := ColorRGBFrom8bit(255, 255, 0)
|
||||
footerColor := ColorRGBFrom8bit(0, 255, 0)
|
||||
|
||||
generateSubtable := func(rows, cols, index int, rightBorder bool) *Table {
|
||||
subtable := c.NewTable(cols)
|
||||
|
||||
// Add header row.
|
||||
sp := c.NewStyledParagraph()
|
||||
sp.Append(fmt.Sprintf("Header of subtable %d", index))
|
||||
|
||||
cell := subtable.MultiColCell(cols)
|
||||
cell.SetContent(sp)
|
||||
cell.SetBorder(CellBorderSideAll, CellBorderStyleSingle, 1)
|
||||
cell.SetHorizontalAlignment(CellHorizontalAlignmentCenter)
|
||||
cell.SetBackgroundColor(headerColor)
|
||||
|
||||
for i := 0; i < rows; i++ {
|
||||
for j := 0; j < cols; j++ {
|
||||
sp = c.NewStyledParagraph()
|
||||
sp.Append(fmt.Sprintf("%d-%d", i+1, j+1))
|
||||
cell = subtable.NewCell()
|
||||
cell.SetContent(sp)
|
||||
|
||||
if j == 0 {
|
||||
cell.SetBorder(CellBorderSideLeft, CellBorderStyleSingle, 1)
|
||||
}
|
||||
if rightBorder && j == cols-1 {
|
||||
cell.SetBorder(CellBorderSideRight, CellBorderStyleSingle, 1)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Add footer row.
|
||||
sp = c.NewStyledParagraph()
|
||||
sp.Append(fmt.Sprintf("Footer of subtable %d", index))
|
||||
|
||||
cell = subtable.MultiColCell(cols)
|
||||
cell.SetContent(sp)
|
||||
cell.SetBorder(CellBorderSideAll, CellBorderStyleSingle, 1)
|
||||
cell.SetHorizontalAlignment(CellHorizontalAlignmentCenter)
|
||||
cell.SetBackgroundColor(footerColor)
|
||||
|
||||
return subtable
|
||||
}
|
||||
|
||||
table := c.NewTable(6)
|
||||
|
||||
// Add subtable 1 on row 1, col 1 (4x4)
|
||||
table.AddSubtable(1, 1, generateSubtable(4, 4, 1, false))
|
||||
|
||||
// Add subtable 2 on row 1, col 5 (4x4)
|
||||
// Table will be expanded to 8 columns because the subtable does not fit.
|
||||
table.AddSubtable(1, 5, generateSubtable(4, 4, 2, true))
|
||||
|
||||
// Add subtable 3 on row 7, col 1 (4x4)
|
||||
table.AddSubtable(7, 1, generateSubtable(4, 4, 3, false))
|
||||
|
||||
// Add subtable 4 on row 7, col 5 (4x4)
|
||||
table.AddSubtable(7, 5, generateSubtable(4, 4, 4, true))
|
||||
|
||||
// Add subtable 5 on row 13, col 3 (4x4)
|
||||
table.AddSubtable(13, 3, generateSubtable(4, 4, 5, true))
|
||||
|
||||
// Add subtable 6 on row 13, col 1 (3x2)
|
||||
table.AddSubtable(13, 1, generateSubtable(3, 2, 6, false))
|
||||
|
||||
// Add subtable 7 on row 13, col 7 (3x2)
|
||||
table.AddSubtable(13, 7, generateSubtable(3, 2, 7, true))
|
||||
|
||||
// Add subtable 8 on row 18, col 1 (3x2)
|
||||
table.AddSubtable(18, 1, generateSubtable(3, 2, 8, false))
|
||||
|
||||
// Add subtable 9 on row 19, col 3 (2x4)
|
||||
table.AddSubtable(19, 3, generateSubtable(2, 4, 9, true))
|
||||
|
||||
// Add subtable 10 on row 18, col 7 (3x2)
|
||||
table.AddSubtable(18, 7, generateSubtable(3, 2, 10, true))
|
||||
|
||||
err := c.Draw(table)
|
||||
if err != nil {
|
||||
t.Fatalf("Error drawing: %v", err)
|
||||
}
|
||||
|
||||
err = c.WriteToFile(tempFile("table_add_subtables.pdf"))
|
||||
if err != nil {
|
||||
t.Fatalf("Fail: %v\n", err)
|
||||
}
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user