bug fix 2714: long note in indiv complete report means infinite loop in cairo

The fix consists in allowing cells to be split, so by extension also 
 rows now split automatically in CairoDoc


svn: r11984
This commit is contained in:
Benny Malengier
2009-02-14 13:12:59 +00:00
parent 7b85d8e4af
commit 917658df34

View File

@@ -439,6 +439,9 @@ class GtkDocParagraph(GtkDocBaseElement):
layout.set_font_description(fontstyle_to_fontdescription(font_style)) layout.set_font_description(fontstyle_to_fontdescription(font_style))
# calculate the height of one line # calculate the height of one line
# FIXME, we should do set_markup(self._text) and get height of entire
# block somehow, as with markup we allow for setting height
# of pieces of text ... only needed for styled notes though...
layout.set_text('Test') layout.set_text('Test')
layout_width, layout_height = layout.get_pixel_size() layout_width, layout_height = layout.get_pixel_size()
line_height = layout_height + self.spacing line_height = layout_height + self.spacing
@@ -446,8 +449,8 @@ class GtkDocParagraph(GtkDocBaseElement):
text_height = height - t_margin - 2 * v_padding text_height = height - t_margin - 2 * v_padding
line_per_height = text_height / line_height line_per_height = text_height / line_height
# if nothing fits return now with result if not a cell (undivisable) # if nothing fits return now with result
if line_per_height < 1 and not self._parent._type == 'CELL': if line_per_height < 1:
return (None, self), 0 return (None, self), 0
# calculate where to cut the paragraph # calculate where to cut the paragraph
@@ -456,15 +459,17 @@ class GtkDocParagraph(GtkDocBaseElement):
line_count = layout.get_line_count() line_count = layout.get_line_count()
# if all paragraph fits we don't need to cut # if all paragraph fits we don't need to cut
# if paragraph part of a cell, we do not divide, table must be split, if line_count <= line_per_height:
# as rows and cells do not divide ...
# ==> note: this means the user must not make one page paragraphs!
if line_count <= line_per_height or self._parent._type == 'CELL':
paragraph_height = (layout_height + t_margin + (2 * v_padding)) paragraph_height = (layout_height + t_margin + (2 * v_padding))
if height - paragraph_height > b_margin: if height - paragraph_height > b_margin:
paragraph_height += b_margin paragraph_height += b_margin
return (self, None), paragraph_height return (self, None), paragraph_height
# if paragraph part of a cell, we do not divide if only small part,
# of paragraph can be shown, instead move to next page
if line_per_height < line_count < 4 and self._parent._type == 'CELL':
return (None, self), 0
# get index of first character which doesn't fit on available height # get index of first character which doesn't fit on available height
layout_line = layout.get_line(int(line_per_height)) layout_line = layout.get_line(int(line_per_height))
index = layout_line.start_index index = layout_line.start_index
@@ -477,9 +482,8 @@ class GtkDocParagraph(GtkDocBaseElement):
self._text = self._text.encode('utf-8')[:index] self._text = self._text.encode('utf-8')[:index]
self._style.set_bottom_margin(0) self._style.set_bottom_margin(0)
# FIXME do we need to return the proper height??? paragraph_height = line_height * line_count + t_margin + 2 * v_padding
# paragraph_height = line_height * line_count + t_margin + 2 * v_padding #paragraph_height = 0
paragraph_height = 0
return (self, new_paragraph), paragraph_height return (self, new_paragraph), paragraph_height
def draw(self, cr, layout, width, dpi_x, dpi_y): def draw(self, cr, layout, width, dpi_x, dpi_y):
@@ -578,7 +582,8 @@ class GtkDocTable(GtkDocBaseElement):
row = self._children[row_index] row = self._children[row_index]
(r1, r2), row_height = row.divide(layout, table_width, height, (r1, r2), row_height = row.divide(layout, table_width, height,
dpi_x, dpi_y) dpi_x, dpi_y)
if table_height + row_height >= height: if r2 is not None:
#break the table in two parts
break break
table_height += row_height table_height += row_height
row_index += 1 row_index += 1
@@ -587,9 +592,11 @@ class GtkDocTable(GtkDocBaseElement):
new_table = None new_table = None
if row_index < len(self._children): if row_index < len(self._children):
new_table = GtkDocTable(self._style) new_table = GtkDocTable(self._style)
for row in self._children[row_index:]: #add the split row
new_table.add_child(r2)
for row in self._children[row_index+1:]:
new_table.add_child(row) new_table.add_child(row)
del self._children[row_index:] del self._children[row_index+1:]
return (self, new_table), table_height return (self, new_table), table_height
@@ -624,7 +631,9 @@ class GtkDocTableRow(GtkDocBaseElement):
def divide(self, layout, width, height, dpi_x, dpi_y): def divide(self, layout, width, height, dpi_x, dpi_y):
# the highest cell gives the height of the row # the highest cell gives the height of the row
cell_heights = [] cell_heights = []
dividedrow = False
cell_width_iter = self._style.__iter__() cell_width_iter = self._style.__iter__()
new_row = GtkDocTableRow(self._style)
for cell in self._children: for cell in self._children:
cell_width = 0 cell_width = 0
for i in range(cell.get_span()): for i in range(cell.get_span()):
@@ -633,13 +642,27 @@ class GtkDocTableRow(GtkDocBaseElement):
(c1, c2), cell_height = cell.divide(layout, cell_width, height, (c1, c2), cell_height = cell.divide(layout, cell_width, height,
dpi_x, dpi_y) dpi_x, dpi_y)
cell_heights.append(cell_height) cell_heights.append(cell_height)
if c2 is None:
emptycell = GtkDocTableCell(c1._style, c1.get_span())
new_row.add_child(emptycell)
else:
dividedrow = True
new_row.add_child(c2)
# save height [inch] of the row to be able to draw exact cell border # save height [inch] of the row to be able to draw exact cell border
row_height = max(cell_heights) row_height = max(cell_heights)
self.height = row_height / dpi_y self.height = row_height / dpi_y
# a row can't be divided, return the height # return the new row if dividing was needed
return (self, None), row_height if dividedrow:
if row_height == 0:
for cell in self._children:
cell._style.set_top_border(False)
cell._style.set_left_border(False)
cell._style.set_right_border(False)
return (self, new_row), row_height
else:
return (self, None), row_height
def draw(self, cr, layout, width, dpi_x, dpi_y): def draw(self, cr, layout, width, dpi_x, dpi_y):
cr.save() cr.save()
@@ -685,19 +708,42 @@ class GtkDocTableCell(GtkDocBaseElement):
# calculate real available width # calculate real available width
width -= 2 * h_padding width -= 2 * h_padding
available_height = height
# calculate height of each child # calculate height of each child
cell_height = 0 cell_height = 0
for child in self._children: new_cell = None
(e1, e2), child_height = child.divide(layout, width, height, e2 = None
dpi_x, dpi_y)
cell_height += child_height
childnr = 0
for child in self._children:
if new_cell is None:
(e1, e2), child_height = child.divide(layout, width,
available_height, dpi_x, dpi_y)
cell_height += child_height
available_height -= child_height
if e2 is not None:
#divide the cell
new_style = BaseDoc.TableCellStyle(self._style)
if e1 is not None:
new_style.set_top_border(False)
new_cell = GtkDocTableCell(new_style, self._span)
new_cell.add_child(e2)
# then update this cell
self._style.set_bottom_border(False)
if e1 is not None:
childnr += 1
else:
#cell has been divided
new_cell.add_child(child)
self._children = self._children[:childnr]
# calculate real height # calculate real height
cell_height += 2 * v_padding if cell_height <> 0:
cell_height += 2 * v_padding
# a cell can't be divided, return the heigth # a cell can't be divided, return the heigth
return (self, None), cell_height return (self, new_cell), cell_height
def draw(self, cr, layout, width, cell_height, dpi_x, dpi_y): def draw(self, cr, layout, width, cell_height, dpi_x, dpi_y):
"""Draw a cell. """Draw a cell.