mirror of
https://github.com/unidoc/unipdf.git
synced 2025-04-27 13:48:51 +08:00
Support wrapped text in table cells
This commit is contained in:
parent
fc8925b918
commit
be8d19b510
@ -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
|
||||
|
@ -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.
|
||||
|
@ -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)
|
||||
|
Loading…
x
Reference in New Issue
Block a user