Support wrapped text in table cells

This commit is contained in:
Gunnsteinn Hall 2018-07-18 00:03:18 +00:00
parent fc8925b918
commit be8d19b510
3 changed files with 136 additions and 7 deletions

View File

@ -947,6 +947,87 @@ func TestTable(t *testing.T) {
}
}
func TestTableCellWrapping(t *testing.T) {
c := New()
c.NewPage()
table := NewTable(4) // Mx4 table
// Default, equal column sizes (4x0.25)...
table.SetColumnWidths(0.5, 0.2, 0.2, 0.1)
cell := table.NewCell()
p := NewParagraph("A Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.")
cell.SetContent(p)
cell.SetBorder(CellBorderStyleBox, 1)
p.SetEnableWrap(true)
p.SetWidth(cell.Width(c.Context()))
p.SetTextAlignment(TextAlignmentJustify)
cell = table.NewCell()
cell.SetBorder(CellBorderStyleBox, 1)
p = NewParagraph("B Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur.")
p.SetEnableWrap(true)
p.SetTextAlignment(TextAlignmentRight)
cell.SetContent(p)
cell = table.NewCell()
p = NewParagraph("C Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.")
cell.SetContent(p)
cell.SetBorder(CellBorderStyleBox, 1)
p.SetEnableWrap(true)
cell = table.NewCell()
p = NewParagraph("1,4")
cell.SetContent(p)
cell.SetBorder(CellBorderStyleBox, 1)
cell = table.NewCell()
p = NewParagraph("2,1")
cell.SetContent(p)
cell.SetBorder(CellBorderStyleBox, 1)
cell = table.NewCell()
p = NewParagraph("2,2")
cell.SetContent(p)
cell.SetBorder(CellBorderStyleBox, 1)
cell = table.NewCell()
p = NewParagraph("2,2")
cell.SetContent(p)
cell.SetBorder(CellBorderStyleBox, 1)
//table.SkipCells(1) // Skip over 2,3.
cell = table.NewCell()
cell.SetBorder(CellBorderStyleBox, 1)
//p = NewParagraph("D Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.")
p = NewParagraph("X")
p.SetEnableWrap(true)
cell.SetContent(p)
// Skip over two rows.
table.SkipRows(2)
cell = table.NewCell()
cell.SetBorder(CellBorderStyleBox, 1)
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)
cell.SetBackgroundColor(ColorRGBFrom8bit(255, 0, 0))
c.Draw(table)
err := c.WriteToFile("/tmp/tablecell_wrap.pdf")
if err != nil {
t.Errorf("Fail: %v\n", err)
return
}
}
// Test creating and drawing a table.
func TestBorderedTable(t *testing.T) {
table := NewTable(4) // Mx4 table

View File

@ -45,6 +45,11 @@ type Paragraph struct {
enableWrap bool
wrapWidth float64
// defaultWrap defines whether wrapping has been defined explictly or whether default behavior should
// be observed. Default behavior depends on context: normally wrap is expected, except for example in
// table cells wrapping is off by default.
defaultWrap bool
// Rotation angle (degrees).
angle float64
@ -77,6 +82,7 @@ func NewParagraph(text string) *Paragraph {
// TODO: Can we wrap intellectually, only if given width is known?
p.enableWrap = true
p.defaultWrap = true
p.SetColor(ColorRGBFrom8bit(0, 0, 0))
p.alignment = TextAlignmentLeft
p.angle = 0
@ -130,6 +136,7 @@ func (p *Paragraph) Text() string {
// SetEnableWrap sets the line wrapping enabled flag.
func (p *Paragraph) SetEnableWrap(enableWrap bool) {
p.enableWrap = enableWrap
p.defaultWrap = false
}
// SetColor set the color of the Paragraph text.

View File

@ -168,6 +168,50 @@ func (table *Table) GeneratePageBlocks(ctx DrawContext) ([]*Block, DrawContext,
// Start row keeps track of starting row (wraps to 0 on new page).
startrow := 0
// Prepare for drawing: Calculate cell dimensions, row, cell heights.
for _, cell := range table.cells {
// Get total width fraction
wf := float64(0.0)
for i := 0; i < cell.colspan; i++ {
wf += table.colWidths[cell.col+i-1]
}
// Get x pos relative to table upper left corner.
xrel := float64(0.0)
for i := 0; i < cell.col-1; i++ {
xrel += table.colWidths[i] * tableWidth
}
// Get y pos relative to table upper left corner.
yrel := float64(0.0)
for i := startrow; i < cell.row-1; i++ {
yrel += table.rowHeights[i]
}
// Calculate the width out of available width.
w := wf * tableWidth
// Get total height.
h := float64(0.0)
for i := 0; i < cell.rowspan; i++ {
h += table.rowHeights[cell.row+i-1]
}
// For text: Calculate width, height, wrapping within available space if specified.
if p, isp := cell.content.(*Paragraph); isp {
if p.enableWrap {
p.SetWidth(w - cell.indent)
}
newh := p.Height() + p.margins.bottom + p.margins.bottom
newh += 0.5 * p.fontSize * p.lineHeight // TODO: Make the top margin configurable?
if newh > h {
diffh := newh - h
// Add diff to last row
table.rowHeights[cell.row+cell.rowspan-2] += diffh
}
}
}
// Draw cells.
// row height, cell height
for _, cell := range table.cells {
// Get total width fraction
@ -505,14 +549,11 @@ func (cell *TableCell) Width(ctx DrawContext) float64 {
func (cell *TableCell) SetContent(vd VectorDrawable) error {
switch t := vd.(type) {
case *Paragraph:
// Default paragraph settings in table:
t.SetEnableWrap(false) // No wrapping.
h := cell.table.rowHeights[cell.row-1]
nh := t.Height() * 1.5 // Default multiplier 1.5.
// Increase height if needed.
if nh > h {
cell.table.SetRowHeight(cell.row, nh)
if t.defaultWrap {
// Default paragraph settings in table: no wrapping.
t.enableWrap = false // No wrapping.
}
cell.content = vd
default:
common.Log.Debug("Error: unsupported cell content type %T\n", vd)