mirror of
https://github.com/unidoc/unipdf.git
synced 2025-04-27 13:48:51 +08:00
Tables with dynamic rows. Closes #66.
This commit is contained in:
parent
8710257e17
commit
b056abb552
@ -693,12 +693,10 @@ func TestSubchaptersSimple(t *testing.T) {
|
||||
ch.GetHeading().SetFontSize(28)
|
||||
ch.GetHeading().SetMargins(0, 0, 0, 30)
|
||||
|
||||
numRows := len(toc.entries)
|
||||
table := NewTable(numRows, 2) // Nx3 table
|
||||
table := NewTable(2) // 2 column table.
|
||||
// Default, equal column sizes (4x0.25)...
|
||||
table.SetColumnWidths(0.9, 0.1)
|
||||
|
||||
row := 1
|
||||
for _, entry := range toc.entries {
|
||||
// Col 1. Chapter number, title.
|
||||
var str string
|
||||
@ -709,19 +707,17 @@ func TestSubchaptersSimple(t *testing.T) {
|
||||
}
|
||||
p := NewParagraph(str)
|
||||
p.SetFontSize(14)
|
||||
cell := table.NewCell(row, 1)
|
||||
cell := table.NewCell()
|
||||
cell.SetContent(p)
|
||||
// Set the paragraph width to the cell width.
|
||||
p.SetWidth(cell.Width(c.Context()))
|
||||
table.SetRowHeight(row, p.Height()*1.2)
|
||||
table.SetRowHeight(table.CurRow(), p.Height()*1.2)
|
||||
|
||||
// Col 1. Page number.
|
||||
p = NewParagraph(fmt.Sprintf("%d", entry.PageNumber))
|
||||
p.SetFontSize(14)
|
||||
cell = table.NewCell(row, 2)
|
||||
cell = table.NewCell()
|
||||
cell.SetContent(p)
|
||||
|
||||
row++
|
||||
}
|
||||
err := ch.Add(table)
|
||||
if err != nil {
|
||||
@ -810,12 +806,10 @@ func TestSubchapters(t *testing.T) {
|
||||
ch.GetHeading().SetFontSize(28)
|
||||
ch.GetHeading().SetMargins(0, 0, 0, 30)
|
||||
|
||||
numRows := len(toc.entries)
|
||||
table := NewTable(numRows, 2) // Nx3 table
|
||||
table := NewTable(2)
|
||||
// Default, equal column sizes (4x0.25)...
|
||||
table.SetColumnWidths(0.9, 0.1)
|
||||
|
||||
row := 1
|
||||
for _, entry := range toc.entries {
|
||||
// Col 1. Chapter number, title.
|
||||
var str string
|
||||
@ -826,19 +820,17 @@ func TestSubchapters(t *testing.T) {
|
||||
}
|
||||
p := NewParagraph(str)
|
||||
p.SetFontSize(14)
|
||||
cell := table.NewCell(row, 1)
|
||||
cell := table.NewCell()
|
||||
cell.SetContent(p)
|
||||
// Set the paragraph width to the cell width.
|
||||
p.SetWidth(cell.Width(c.Context()))
|
||||
table.SetRowHeight(row, p.Height()*1.2)
|
||||
table.SetRowHeight(table.CurRow(), p.Height()*1.2)
|
||||
|
||||
// Col 1. Page number.
|
||||
p = NewParagraph(fmt.Sprintf("%d", entry.PageNumber))
|
||||
p.SetFontSize(14)
|
||||
cell = table.NewCell(row, 2)
|
||||
cell = table.NewCell()
|
||||
cell.SetContent(p)
|
||||
|
||||
row++
|
||||
}
|
||||
err := ch.Add(table)
|
||||
if err != nil {
|
||||
@ -860,42 +852,52 @@ func TestSubchapters(t *testing.T) {
|
||||
|
||||
// Test creating and drawing a table.
|
||||
func TestTable(t *testing.T) {
|
||||
table := NewTable(4, 4) // 4x4 table
|
||||
table := NewTable(4) // Mx4 table
|
||||
// Default, equal column sizes (4x0.25)...
|
||||
table.SetColumnWidths(0.5, 0.2, 0.2, 0.1)
|
||||
|
||||
cell := table.NewCell(1, 1)
|
||||
cell := table.NewCell()
|
||||
p := NewParagraph("1,1")
|
||||
cell.SetContent(p)
|
||||
|
||||
cell = table.NewCell(1, 2)
|
||||
cell = table.NewCell()
|
||||
p = NewParagraph("1,2")
|
||||
cell.SetContent(p)
|
||||
|
||||
cell = table.NewCell(1, 3)
|
||||
cell = table.NewCell()
|
||||
p = NewParagraph("1,3")
|
||||
cell.SetContent(p)
|
||||
|
||||
cell = table.NewCell(1, 4)
|
||||
cell = table.NewCell()
|
||||
p = NewParagraph("1,4")
|
||||
cell.SetContent(p)
|
||||
|
||||
cell = table.NewCell(2, 1)
|
||||
cell = table.NewCell()
|
||||
p = NewParagraph("2,1")
|
||||
cell.SetContent(p)
|
||||
|
||||
cell = table.NewCell(2, 2)
|
||||
cell = table.NewCell()
|
||||
p = NewParagraph("2,2")
|
||||
cell.SetContent(p)
|
||||
|
||||
cell = table.NewCell(2, 4)
|
||||
table.SkipCells(1) // Skip over 2,3.
|
||||
|
||||
cell = table.NewCell()
|
||||
p = NewParagraph("2,4")
|
||||
cell.SetContent(p)
|
||||
|
||||
cell = table.NewCell(4, 4)
|
||||
// Skip over two rows.
|
||||
table.SkipRows(2)
|
||||
cell = table.NewCell()
|
||||
p = NewParagraph("4,4")
|
||||
cell.SetContent(p)
|
||||
|
||||
// Move down 3 rows, 2 to the left.
|
||||
table.SkipOver(3, -2)
|
||||
cell = table.NewCell()
|
||||
p = NewParagraph("7,2")
|
||||
cell.SetContent(p)
|
||||
|
||||
c := New()
|
||||
c.Draw(table)
|
||||
|
||||
|
@ -17,6 +17,11 @@ type Table struct {
|
||||
rows int
|
||||
cols int
|
||||
|
||||
// Current cell. Current cell in the table.
|
||||
// For 4x4 table, if in the 2nd row, 3rd column, then
|
||||
// curCell = 4+3 = 7
|
||||
curCell int
|
||||
|
||||
// Column width fractions: should add up to 1.
|
||||
colWidths []float64
|
||||
|
||||
@ -24,7 +29,7 @@ type Table struct {
|
||||
rowHeights []float64
|
||||
|
||||
// Default row height.
|
||||
rowHeight float64
|
||||
defaultRowHeight float64
|
||||
|
||||
// Content cells.
|
||||
cells []*tableCell
|
||||
@ -40,11 +45,13 @@ type Table struct {
|
||||
}
|
||||
|
||||
// Create a new table with a fixed rows and column size.
|
||||
func NewTable(rows, cols int) *Table {
|
||||
func NewTable(cols int) *Table {
|
||||
t := &Table{}
|
||||
t.rows = rows
|
||||
t.rows = 0
|
||||
t.cols = cols
|
||||
|
||||
t.curCell = 0
|
||||
|
||||
// Initialize column widths as all equal.
|
||||
t.colWidths = []float64{}
|
||||
colWidth := float64(1.0) / float64(cols)
|
||||
@ -52,13 +59,11 @@ func NewTable(rows, cols int) *Table {
|
||||
t.colWidths = append(t.colWidths, colWidth)
|
||||
}
|
||||
|
||||
// Initialize row heights all to 10.
|
||||
t.rowHeights = []float64{}
|
||||
for i := 0; i < rows; i++ {
|
||||
t.rowHeights = append(t.rowHeights, 10.0)
|
||||
}
|
||||
|
||||
// Default row height
|
||||
t.rowHeight = 10.0
|
||||
// XXX/TODO: Base on contents instead?
|
||||
t.defaultRowHeight = 10.0
|
||||
|
||||
t.cells = []*tableCell{}
|
||||
|
||||
@ -78,11 +83,6 @@ func (table *Table) SetColumnWidths(widths ...float64) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
// Table occupies whatever width is available. Returns -1.
|
||||
func (table *Table) Width() float64 {
|
||||
return -1 // Occupy whatever width is available.
|
||||
}
|
||||
|
||||
// Total height of all rows.
|
||||
func (table *Table) Height() float64 {
|
||||
sum := float64(0.0)
|
||||
@ -116,8 +116,21 @@ func (table *Table) SetRowHeight(row int, h float64) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
// Get row of the current cell position.
|
||||
func (table *Table) CurRow() int {
|
||||
curRow := (table.curCell-1)/table.cols + 1
|
||||
return curRow
|
||||
}
|
||||
|
||||
// Get column of the current cell position.
|
||||
func (table *Table) CurCol() int {
|
||||
curCol := (table.curCell-1)%(table.cols) + 1
|
||||
return curCol
|
||||
}
|
||||
|
||||
// Set absolute coordinates.
|
||||
// Note that this is only sensible to use when the table does not wrap over multiple pages.
|
||||
// XXX/TODO: Should be able to set width too (not just based on context/relative positioning mode).
|
||||
func (table *Table) SetPos(x, y float64) {
|
||||
table.positioning = positionAbsolute
|
||||
table.xPos = x
|
||||
@ -172,7 +185,7 @@ func (table *Table) GeneratePageBlocks(ctx DrawContext) ([]*Block, DrawContext,
|
||||
// Get total height.
|
||||
h := float64(0.0)
|
||||
for i := 0; i < cell.rowspan; i++ {
|
||||
h += table.rowHeights[cell.col+i-1]
|
||||
h += table.rowHeights[cell.row+i-1]
|
||||
}
|
||||
|
||||
ctx.Height = origHeight - yrel
|
||||
@ -224,10 +237,19 @@ type tableCell struct {
|
||||
}
|
||||
|
||||
// Make a new cell and insert into the table at specified row and column.
|
||||
func (table *Table) NewCell(row, col int) *tableCell {
|
||||
func (table *Table) NewCell() *tableCell {
|
||||
table.curCell++
|
||||
|
||||
curRow := (table.curCell-1)/table.cols + 1
|
||||
for curRow > table.rows {
|
||||
table.rows++
|
||||
table.rowHeights = append(table.rowHeights, table.defaultRowHeight)
|
||||
}
|
||||
curCol := (table.curCell-1)%(table.cols) + 1
|
||||
|
||||
cell := &tableCell{}
|
||||
cell.row = row
|
||||
cell.col = col
|
||||
cell.row = curRow
|
||||
cell.col = curCol
|
||||
|
||||
cell.rowspan = 1
|
||||
cell.colspan = 1
|
||||
@ -240,6 +262,35 @@ func (table *Table) NewCell(row, col int) *tableCell {
|
||||
return cell
|
||||
}
|
||||
|
||||
// Skip over a specified number of cells.
|
||||
func (table *Table) SkipCells(num int) {
|
||||
if num < 0 {
|
||||
common.Log.Debug("Table: cannot skip back to previous cells")
|
||||
return
|
||||
}
|
||||
table.curCell += num
|
||||
}
|
||||
|
||||
// Skip over a specified number of rows.
|
||||
func (table *Table) SkipRows(num int) {
|
||||
ncells := num*table.cols - 1
|
||||
if ncells < 0 {
|
||||
common.Log.Debug("Table: cannot skip back to previous cells")
|
||||
return
|
||||
}
|
||||
table.curCell += ncells
|
||||
}
|
||||
|
||||
// Skip over rows, cols.
|
||||
func (table *Table) SkipOver(rows, cols int) {
|
||||
ncells := rows*table.cols + cols - 1
|
||||
if ncells < 0 {
|
||||
common.Log.Debug("Table: cannot skip back to previous cells")
|
||||
return
|
||||
}
|
||||
table.curCell += ncells
|
||||
}
|
||||
|
||||
// Get cell width based on input draw context.
|
||||
func (cell *tableCell) Width(ctx DrawContext) float64 {
|
||||
fraction := float64(0.0)
|
||||
|
Loading…
x
Reference in New Issue
Block a user