Class PDF::SimpleTable
In: lib/pdf/simpletable.rb
Parent: Object
Transaction::Simple SimpleTable TechBook Complex Action Procset FontDescriptor FontEncoding Destination Info Catalog Encryption Contents Pages Outline Outlines Annotation Page Font ViewerPreferences Image Hash OHash QuickRef FontMetrics ARC4 StrokeStyle PolygonPoint ImageInfo StdDev lib/pdf/simpletable.rb lib/pdf/techbook.rb lib/pdf/writer.rb lib/pdf/quickref.rb Math lib/pdf/writer/fontmetrics.rb lib/pdf/writer/ohash.rb lib/pdf/writer/arc4.rb lib/pdf/writer/strokestyle.rb lib/pdf/writer/graphics.rb lib/pdf/writer/object.rb lib/pdf/writer/object/image.rb External EN Lang OffsetReader lib/pdf/writer/graphics/imageinfo.rb Graphics lib/pdf/writer/object/outlines.rb lib/pdf/writer/object/destination.rb lib/pdf/writer/object/viewerpreferences.rb lib/pdf/writer/object/fontencoding.rb lib/pdf/writer/object/page.rb lib/pdf/writer/object/contents.rb lib/pdf/writer/object/procset.rb lib/pdf/writer/object/pages.rb lib/pdf/writer/object/info.rb lib/pdf/writer/object/encryption.rb lib/pdf/writer/object/catalog.rb lib/pdf/writer/object/outline.rb lib/pdf/writer/object/fontdescriptor.rb lib/pdf/writer/object/action.rb lib/pdf/writer/object/font.rb lib/pdf/writer/object/annotation.rb Object Writer lib/pdf/charts/stddev.rb Charts PDF dot/m_33_0.png

This class will create tables with a relatively simple API and internal implementation.

Methods

Included Modules

Transaction::Simple

Classes and Modules

Class PDF::SimpleTable::Column

Constants

WIDTH_FACTOR = 1.01

Attributes

bold_headings  [RW]  Makes the heading text bold if true. Defaults to false.
column_gap  [RW]  The space, in PDF user units, on the left and right sides of each cell. Default 5 units.
column_order  [RW]  An array that defines the order of the columns in the table. The values in this array are the column names in data. The columns will be presented in the order defined here.
columns  [RW]  An array that defines columns and column options for the table. The entries should be PDF::SimpleTable::Column objects.
data  [RW]  An array of Hash entries. Each row is a Hash where the keys are the names of the columns as specified in column_order and the values are the values of the cell.
font_size  [RW]  The font size of the data cells, in points. Defaults to 10 points.
header_gap  [RW]  The number of PDF user units to leave open at the top of a page after a page break. This is typically used for a repeating page header, etc. Defaults to zero units.
heading_color  [RW]  The text colour of the heading. Defaults to Color::RGB::Black.
heading_font_size  [RW]  The font size of the heading cells, in points. Defaults to 12 points.
inner_line_style  [RW]  Defines the inner line style. The default style is a solid line with a thickness of 1 unit.
line_color  [RW]  The colour of the table lines. Defaults to Color::RGB::Black.
maximum_width  [RW]  Specifies the maximum width of the table. The table will not grow larger than this width under any circumstances.

Defaults to zero, which indicates that there is no maximum width (aside from the margin size).

minimum_space  [RW]  The minimum space between the bottom of each row and the bottom margin. If the amount of space is less than this, a new page will be started. Default is 100 PDF user units.
orientation  [RW]  The orientation of the table relative to position.
:left:The table is to the left of position.
:right:The table is to the right of position.
:center:The table is centred at position.
offset:The left of the table is offset from position.
outer_line_style  [RW]  Defines the outer line style. The default style is a solid line with a thickness of 1 unit.
position  [RW]  The x position of the table. This will be one of:
:left:Aligned with the left margin.
:right:Aligned with the right margin.
:center:Centered between the margins. Default.
offset:The absolute position of the table, relative from the left margin.
protect_rows  [RW]  The number of rows to hold with the heading on the page. If there are less than this number of rows on the page, then move the whole lot onto the next page. Default is one row.
row_gap  [RW]  The space, in PDF user units, added to the top and bottom of each row between the text and the lines of the cell. Default 2 units.
shade_color  [RW]  The main row shading colour. Defaults to Color::RGB::Grey80. Used with shade_rows of :shaded and :striped.
shade_color2  [RW]  The alternate row shading colour, used with shade_rows of :striped. Defaults to Color::RGB::Grey70.
shade_heading_color  [RW]  Defines the colour of the background shading for the heading if shade_headings is true. Default is Color::RGB::Grey90.
shade_headings  [RW]  Places a background colour in the heading if true.
shade_rows  [RW]  Controls row shading.
:none:No row shading; all rows are the standard background colour.
:shaded:Alternate lines will be shaded; half of the rows will be the standard background colour; the rest of the rows will be shaded with shade_color. Default
:striped:Alternate lines will be shaded; half of the rows will be shaded with shade_color; the rest of the rows will be shaded with shade_color2.
show_headings  [RW]  Displays the headings for the table if true. The default is true.
show_lines  [RW]  Whether to display the lines on the table or not. Valid values are:
:none:Displays no lines.
:outer:Displays outer lines only. Default
:inner:Displays inner lines only.
:all:Displays all lines, inner and outer.
split_rows  [RW]  Allows a table‘s rows to be split across page boundaries if true. This defaults to false.
text_color  [RW]  The text colour of the body cells. Defaults to Color::RGB::Black.
title  [RW]  The title to be put on the top of the table.
title_color  [RW]  The text colour of the title. Defaults to Color::RGB::Black.
title_font_size  [RW]  The font size of the title, in points. Defaults to 12 points.
title_gap  [RW]  The gap, in PDF units, between the title and the table. Defaults to 5 units.
width  [RW]  Specifies the width of the table. If the table is smaller than the provided width, columns are proportionally stretched to fit the width of the table. If the table is wider than the provided width, columns are proportionally shrunk to fit the width of the table. Content may need to wrap in this case.

Defaults to zero, which indicates that the size whould be determined automatically based on the content and the margins.

Public Class methods

[Source]

     # File lib/pdf/simpletable.rb, line 69
 69:   def initialize
 70:     @column_order = []
 71:     @data         = []
 72:     @columns      = {}
 73: 
 74:     @show_lines           = :outer
 75:     @show_headings        = true
 76:     @shade_rows           = :shaded
 77:     @shade_color          = Color::RGB::Grey80
 78:     @shade_color2         = Color::RGB::Grey70
 79:     @shade_headings       = false
 80:     @shade_heading_color  = Color::RGB::Grey90
 81:     @font_size            = 10
 82:     @heading_font_size    = 12
 83:     @title_font_size      = 12
 84:     @title_gap            = 5
 85:     @title_color          = Color::RGB::Black
 86:     @heading_color        = Color::RGB::Black
 87:     @text_color           = Color::RGB::Black
 88:     @line_color           = Color::RGB::Black
 89:     @position             = :center
 90:     @orientation          = :center
 91:     @bold_headings        = false
 92: 
 93:     @cols                 = PDF::Writer::OHash.new
 94:     @width                = 0
 95:     @maximum_width        = 0
 96: 
 97:     @gap                  = 5
 98:     @row_gap              = 2
 99:     @column_gap           = 5
100:     @header_gap           = 0
101: 
102:     @minimum_space        = 0
103:     @protect_rows         = 1
104:     @split_rows           = false
105: 
106:     @inner_line_style     = PDF::Writer::StrokeStyle.new(1)
107:     @outer_line_style     = PDF::Writer::StrokeStyle.new(1)
108: 
109:     yield self if block_given?
110:   end

Public Instance methods

Render the table on the PDF::Writer document provided.

[Source]

     # File lib/pdf/simpletable.rb, line 238
238:   def render_on(pdf)
239:     if @column_order.empty?
240:       raise TypeError, PDF::Writer::Lang[:simpletable_columns_undefined]
241:     end
242:     if @data.empty?
243:       raise TypeError, PDF::Writer::Lang[:simpletable_data_empty]
244:     end
245: 
246:     low_y = descender = y0 = y1 = y = nil
247: 
248:     @cols = PDF::Writer::OHash.new
249:     @column_order.each do |name|
250:       col = @columns[name]
251:       if col
252:         @cols[name] = col
253:       else
254:         @cols[name] = PDF::SimpleTable::Column.new(name)
255:       end
256:     end
257: 
258:     @gap = 2 * @column_gap
259: 
260:     max_width = __find_table_max_width__(pdf)
261:     pos, t, x, adjustment_width, set_width = __find_table_positions__(pdf, max_width)
262: 
263:     # if max_width is specified, and the table is too wide, and the width
264:     # has not been set, then set the width.
265:     if @width.zero? and @maximum_width.nonzero? and ((t - x) > @maximum_width)
266:       @width = @maximum_width
267:     end
268: 
269:     if @width and (adjustment_width > 0) and (set_width < @width)
270:         # First find the current widths of the columns involved in this
271:         # mystery
272:       cols0 = PDF::Writer::OHash.new
273:       cols1 = PDF::Writer::OHash.new
274: 
275:       xq = presentWidth = 0
276:       last = nil
277: 
278:       pos.each do |name, colpos|
279:         if @cols[last].nil? or
280:           @cols[last].width.nil? or
281:           @cols[last].width <= 0
282:           unless last.nil? or last.empty?
283:             cols0[last] = colpos - xq - @gap
284:             presentWidth += (colpos - xq - @gap)
285:           end
286:         else
287:           cols1[last] = colpos - xq
288:         end
289:         last = name
290:         xq = colpos
291:       end
292: 
293:       # cols0 contains the widths of all the columns which are not set
294:       needed_width = @width - set_width
295: 
296:         # If needed width is negative then add it equally to each column,
297:         # else get more tricky.
298:       if presentWidth < needed_width
299:         diff = (needed_width - presentWidth) / cols0.size.to_f
300:         cols0.each_key { |name| cols0[name] += diff }
301:       else
302:         cnt = 0
303:         loop do
304:           break if (presentWidth <= needed_width) or (cnt >= 100)
305:           cnt += 1 # insurance policy
306:             # Find the widest columns and the next to widest width
307:           aWidest = []
308:           nWidest = widest = 0
309:           cols0.each do |name, w|
310:             if w > widest
311:               aWidest = [ name ]
312:               nWidest = widest
313:               widest = w
314:             elsif w == widest
315:               aWidest << name
316:             end
317:           end
318: 
319:           # Then figure out what the width of the widest columns would
320:           # have to be to take up all the slack.
321:           newWidestWidth = widest - (presentWidth - needed_width) / aWidest.size.to_f
322:           if newWidestWidth > nWidest
323:             aWidest.each { |name| cols0[name] = newWidestWidth }
324:             presentWidth = needed_width
325:           else
326:             # There is no space, reduce the size of the widest ones down
327:             # to the next size down, and we will go round again
328:             aWidest.each { |name| cols0[name] = nWidest }
329:             presentWidth -= (widest - nWidest) * aWidest.size
330:           end
331:         end
332:       end
333: 
334:         # cols0 now contains the new widths of the constrained columns. now
335:         # need to update the pos and max_width arrays
336:       xq = 0
337:       pos.each do |name, colpos|
338:         pos[name] = xq
339: 
340:         if @cols[name].nil? or
341:           @cols[name].width.nil? or
342:           @cols[name].width <= 0
343:           if not cols0[name].nil?
344:             xq += cols0[name] + @gap
345:             max_width[name] = cols0[name]
346:           end
347:         else
348:           xq += cols1[name] unless cols1[name].nil?
349:         end
350:       end
351: 
352:       t = x + @width
353:       pos[:__last_column__] = t
354:     end
355: 
356:     # now adjust the table to the correct location across the page
357:     case @position
358:     when :left
359:       xref = pdf.absolute_left_margin
360:     when :right
361:       xref = pdf.absolute_right_margin
362:     when :center
363:       xref = pdf.margin_x_middle
364:     else
365:       xref = @position
366:     end
367: 
368:     case @orientation
369:     when :left
370:       dx = xref - t
371:     when :right
372:       dx = xref
373:     when :center
374:       dx = xref - (t / 2.0)
375:     else
376:       dx = xref + @orientation
377:     end
378: 
379:     pos.each { |k, v| pos[k] = v + dx }
380: 
381:     base_x0 = x0 = x + dx
382:     base_x1 = x1 = t + dx
383: 
384:     base_left_margin = pdf.absolute_left_margin
385:     base_pos = pos.dup
386: 
387:       # Ok, just about ready to make me a table.
388:     pdf.fill_color @text_color
389:     pdf.stroke_color @shade_color 
390: 
391:     middle = (x0 + x1) / 2.0
392: 
393:       # Start a transaction. This transaction will be used to regress the
394:       # table if there are not enough rows protected. 
395:     tg = Transaction::Simple::Group.new(pdf, self)
396:     tg.start_transaction(:table)
397:     moved_once = false if @protect_rows.nonzero?
398: 
399:     abortTable = true
400:     loop do # while abortTable
401:       break unless abortTable
402:       abortTable = false
403: 
404:       dm = pdf.absolute_left_margin - base_left_margin
405:       base_pos.each { |k, v| pos[k] = v + dm }
406:       x0 = base_x0 + dm
407:       x1 = base_x1 + dm
408:       middle = (x0 + x1) / 2.0
409: 
410:         # If the title is set, then render it.
411:       unless @title.nil? or @title.empty?
412:         w = pdf.text_width(@title, @title_font_size)
413:         _y = pdf.y - pdf.font_height(@title_font_size)
414:         if _y < pdf.absolute_bottom_margin
415:           pdf.start_new_page
416: 
417:             # margins may have changed on the new page
418:           dm = pdf.absolute_left_margin - base_left_margin
419:           base_pos.each { |k, v| pos[k] = v + dm }
420:           x0 = base_x0 + dm
421:           x1 = base_x1 + dm
422:           middle = (x0 + x1) / 2.0
423:         end
424: 
425:         pdf.y -= pdf.font_height(@title_font_size)
426:         pdf.fill_color @title_color
427:         pdf.add_text(middle - w / 2.0, pdf.y, title, @title_font_size)
428:         pdf.y -= @title_gap
429:       end
430: 
431:         # Margins may have changed on the new_page.
432:       dm = pdf.absolute_left_margin - base_left_margin
433:       base_pos.each { |k, v| pos[k] = v + dm }
434:       x0 = base_x0 + dm
435:       x1 = base_x1 + dm
436:       middle = (x0 + x1) / 2.0
437: 
438:       y = pdf.y  # simplifies the code a bit
439:       low_y = y if low_y.nil? or y < low_y 
440: 
441:         # Make the table
442:       height = pdf.font_height @font_size
443:       descender = pdf.font_descender @font_size
444: 
445:       y0 = y + descender
446:       dy = 0
447: 
448:       if @show_headings
449:         # This function will move the start of the table to a new page if
450:         # it does not fit on this one.
451:         hOID = __open_new_object__(pdf) if @shade_headings
452:         pdf.fill_color @heading_color
453:         _height, y = __table_column_headings__(pdf, pos, max_width, height,
454:           descender, @row_gap, @heading_font_size, y)
455:         pdf.fill_color @text_color
456:         y0 = y + _height
457:         y1 = y
458: 
459:         if @shade_headings
460:           pdf.close_object
461:           pdf.fill_color! @shade_heading_color
462:           pdf.rectangle(x0 - @gap / 2.0, y, x1 - x0, _height).fill
463:           pdf.reopen_object(hOID)
464:           pdf.close_object
465:           pdf.restore_state
466:         end
467: 
468:           # Margins may have changed on the new_page
469:         dm = pdf.absolute_left_margin - base_left_margin
470:         base_pos.each { |k, v| pos[k] = v + dm }
471:         x0 = base_x0 + dm
472:         x1 = base_x1 + dm
473:         middle = (x0 + x1) / 2.0
474:       else
475:         y1 = y0
476:       end
477: 
478:       first_line = true
479: 
480:       # open an object here so that the text can be put in over the
481:       # shading
482:       tOID = __open_new_object__(pdf) unless :none == @shade_rows
483: 
484:       cnt = 0
485:       cnt = 1 unless @shade_headings
486:       newPage = false
487:       @data.each do |row|
488:         cnt += 1
489:           # Start a transaction that will be used for this row to prevent it
490:           # from being split.
491:         unless @split_rows
492:           pageStart = pdf.pageset.size
493: 
494:           columnStart = pdf.column_number if pdf.columns?
495: 
496:           tg.start_transaction(:row)
497:           row_orig = row
498:           y_orig = y
499:           y0_orig = y0
500:           y1_orig = y1
501:         end # unless @split_rows
502: 
503:         ok = false
504:         second_turn = false
505:         loop do # while !abortTable and !ok
506:           break if abortTable or ok
507: 
508:           mx = 0
509:           newRow = true
510: 
511:           loop do # while !abortTable and (newPage or newRow)
512:             break if abortTable or not (newPage or newRow)
513: 
514:             y -= height
515:             low_y = y if low_y.nil? or y < low_y 
516: 
517:             if newPage or y < (pdf.absolute_bottom_margin + @minimum_space)
518:                 # check that enough rows are with the heading
519:               moved_once = abortTable = true if @protect_rows.nonzero? and not moved_once and cnt <= @protect_rows
520: 
521:               y2 = y - mx + (2 * height) + descender - (newRow ? 1 : 0) * height
522: 
523:               unless :none == @show_lines
524:                 y0 = y1 unless @show_headings
525: 
526:                 __table_draw_lines__(pdf, pos, @gap, x0, x1, y0, y1, y2,
527:                   @line_color, @inner_line_style, @outer_line_style,
528:                   @show_lines)
529:               end
530: 
531:               unless :none == @shade_rows
532:                 pdf.close_object
533:                 pdf.restore_state
534:               end
535: 
536:               pdf.start_new_page
537:               pdf.save_state
538: 
539:                 # and the margins may have changed, this is due to the
540:                 # possibility of the columns being turned on as the columns are
541:                 # managed by manipulating the margins
542:               dm = pdf.absolute_left_margin - base_left_margin
543:               base_pos.each { |k, v| pos[k] = v + dm }
544:               x0 = base_x0 + dm
545:               x1 = base_x1 + dm
546: 
547:               tOID = __open_new_object__(pdf) unless :none == @shade_rows
548: 
549:               pdf.fill_color! @text_color
550: 
551:               y = pdf.absolute_top_margin - @header_gap
552:               low_y = y
553:               y0 = y + descender
554:               mx = 0
555: 
556:               if @show_headings
557:                 old_y = y
558: 
559:                 pdf.fill_color @heading_color
560:                 _height, y = __table_column_headings__(pdf, pos, max_width,
561:                   height, descender, @row_gap, @heading_font_size, y)
562:                 pdf.fill_color @text_color
563: 
564:                 y0 = y + _height
565:                 y1 = y
566: 
567:                 if @shade_headings
568:                   pdf.fill_color! @shade_heading_color
569:                   pdf.rectangle(x0 - @gap / 2, y, x1 - x0, _height).fill
570:                   pdf.fill_color @heading_color
571:                   __table_column_headings__(pdf, pos, max_width, height,
572:                                             descender, @row_gap,
573:                                             @heading_font_size, old_y)
574:                   pdf.fill_color @text_color
575:                 end
576: 
577:                 dm = pdf.absolute_left_margin - base_left_margin
578:                 base_pos.each { |k, v| pos[k] = v + dm }
579:                 x0 = base_x0 + dm
580:                 x1 = base_x1 + dm
581:                 middle = (x0 + x1) / 2.0
582:               else
583:                 y1 = y0
584:               end
585: 
586:               first_line = true
587:               y -= height
588:               low_y = y if low_y.nil? or y < low_y 
589:             end
590: 
591:             newRow = false
592: 
593:               # Write the actual data. If these cells need to be split over
594:               # a page, then newPage will be set, and the remaining text
595:               # will be placed in leftOvers
596:             newPage = false
597:             leftOvers = PDF::Writer::OHash.new
598: 
599:             @cols.each do |name, column|
600:               pdf.pointer = y + height
601:               colNewPage = false
602: 
603:               unless row[name].nil?
604:                 lines = row[name].to_s.split(/\n/)
605:                 if column and column.link_name
606:                   lines.map! do |kk|
607:                     link = row[column.link_name]
608:                     if link
609:                       "<c:alink uri='#{link}'>#{kk}</c:alink>"
610:                     else
611:                       kk
612:                     end
613:                   end
614:                 end
615:               else
616:                 lines = []
617:               end
618: 
619:               pdf.y -= @row_gap
620: 
621:               lines.each do |line|
622:                 pdf.send(:preprocess_text, line)
623:                 start = true
624: 
625:                 loop do
626:                   break if (line.nil? or line.empty?) and not start
627:                   start = false
628: 
629:                   _y = pdf.y - height if not colNewPage
630: 
631:                     # a new page is required
632:                   newPage = colNewPage = true if _y < pdf.absolute_bottom_margin
633: 
634:                   if colNewPage
635:                     if leftOvers[name].nil?
636:                       leftOvers[name] = [line]
637:                     else
638:                       leftOvers[name] << "\n#{line}"
639:                     end
640:                     line = nil
641:                   else
642:                     if column and column.justification
643:                       just = column.justification
644:                     end
645:                     just ||= :left
646: 
647:                     pdf.y = _y
648:                     line = pdf.add_text_wrap(pos[name], pdf.y,
649:                                              max_width[name], line,
650:                                              @font_size, just)
651:                   end
652:                 end
653:               end
654: 
655:               dy = y + height - pdf.y + @row_gap
656:               mx = dy - height * (newPage ? 1 : 0) if (dy - height * (newPage ? 1 : 0)) > mx
657:             end
658: 
659:               # Set row to leftOvers so that they will be processed onto the
660:               # new page
661:             row = leftOvers
662: 
663:             # Now add the shading underneath
664:             unless :none == @shade_rows
665:               pdf.close_object
666: 
667:               if (cnt % 2).zero?
668:                 pdf.fill_color!(@shade_color)
669:                 pdf.rectangle(x0 - @gap / 2.0, y + descender + height - mx, x1 - x0, mx).fill
670:               elsif (cnt % 2).nonzero? and :striped == @shade_rows
671:                 pdf.fill_color!(@shade_color2)
672:                 pdf.rectangle(x0 - @gap / 2.0, y + descender + height - mx, x1 - x0, mx).fill
673:               end
674:               pdf.reopen_object(tOID)
675:             end
676: 
677:             if :inner == @show_lines or :all == @show_lines
678:               # draw a line on the top of the block
679:               pdf.save_state
680:               pdf.stroke_color! @line_color
681:               if first_line
682:                 pdf.stroke_style @outer_line_style
683:                 first_line = false
684:               else
685:                 pdf.stroke_style @inner_line_style
686:               end
687:               pdf.line(x0 - @gap / 2.0, y + descender + height, x1 - @gap / 2.0, y + descender + height).stroke
688:               pdf.restore_state
689:             end
690:           end
691: 
692:           y = y - mx + height
693:           pdf.y = y
694:           low_y = y if low_y.nil? or y < low_y 
695: 
696:             # checking row split over pages
697:           unless @split_rows
698:             if (((pdf.pageset.size != pageStart) or (pdf.columns? and columnStart != pdf.column_number)) and not second_turn)
699:               # then we need to go back and try that again!
700:               newPage = second_turn = true
701:               tg.rewind_transaction(:row)
702:               row = row_orig
703:               low_y = y = y_orig
704:               y0 = y0_orig
705:               y1 = y1_orig
706:               ok = false
707: 
708:               dm = pdf.absolute_left_margin - base_left_margin
709:               base_pos.each { |k, v| pos[k] = v + dm }
710:               x0 = base_x0 + dm
711:               x1 = base_x1 + dm
712:             else
713:               tg.commit_transaction(:row)
714:               ok = true
715:             end
716:           else
717:             ok = true # don't go 'round the loop if splitting rows is allowed
718:           end
719:         end
720: 
721:         if abortTable
722:             # abort_transaction if not ok only the outer transaction should
723:             # be operational.
724:           tg.rewind_transaction(:table)
725:           pdf.start_new_page
726:             # fix a bug where a moved table will take up the whole page.
727:           low_y = nil
728:           pdf.save_state
729:           break
730:         end
731:       end
732:     end
733: 
734:     if low_y <= y
735:       y2 = low_y + descender
736:     else
737:       y2 = y + descender
738:     end
739: 
740:     unless :none == @show_lines
741:       y0 = y1 unless @show_headings
742: 
743:       __table_draw_lines__(pdf, pos, @gap, x0, x1, y0, y1, y2, @line_color,
744:         @inner_line_style, @outer_line_style, @show_lines)
745:     end
746: 
747:     # close the object for drawing the text on top
748:     unless :none == @shade_rows
749:       pdf.close_object
750:       pdf.restore_state
751:     end
752: 
753:     pdf.y = low_y
754: 
755:       # Table has been put on the page, the rows guarded as required; commit.
756:     tg.commit_transaction(:table)
757: 
758:     y
759:   rescue Exception => ex
760:     begin
761:       tg.abort_transaction(:table) if tg.transaction_open?
762:     rescue
763:       nil
764:     end
765:     raise ex
766:   end

Private Instance methods

Find the maximum widths of the text within each column. Default to zero.

[Source]

     # File lib/pdf/simpletable.rb, line 772
772:   def __find_table_max_width__(pdf)     
773:     max_width = PDF::Writer::OHash.new(-1)
774: 
775:     # Find the maximum cell widths based on the data and the headings.
776:     # Passing through the data multiple times is unavoidable as we must
777:     # do some analysis first.
778:     @data.each do |row|
779:      @cols.each do |name, column|
780:        w = pdf.text_width(row[name].to_s, @font_size)
781:        w *= PDF::SimpleTable::WIDTH_FACTOR
782: 
783:        max_width[name] = w if w > max_width[name]
784:      end
785:     end
786: 
787:     @cols.each do |name, column|
788:      title = column.heading.title if column.heading
789:      title ||= column.name
790:      w = pdf.text_width(title, @heading_font_size)
791:      w *= PDF::SimpleTable::WIDTH_FACTOR  
792:      max_width[name] = w if w > max_width[name]
793:     end
794:     max_width  
795:   end

Calculate the start positions of each of the columns. This is based on max_width, but may be modified with column options.

[Source]

     # File lib/pdf/simpletable.rb, line 800
800:   def __find_table_positions__(pdf, max_width)
801:     pos = PDF::Writer::OHash.new
802:     x = t = adjustment_width = set_width = 0
803: 
804:     max_width.each do |name, w|
805:       pos[name] = t
806:         # If the column width has been specified then set that here, also
807:         # total the width avaliable for adjustment.
808:       if not @cols[name].nil? and
809:          not @cols[name].width.nil? and
810:          @cols[name].width > 0
811:         t += @cols[name].width
812:         max_width[name] = @cols[name].width - @gap
813:         set_width += @cols[name].width
814:       else
815:         t += w + @gap
816:         adjustment_width += w
817:         set_width += @gap
818:       end
819:     end
820:     pos[:__last_column__] = t
821: 
822:     [pos, t, x, adjustment_width, set_width]
823:   end

[Source]

     # File lib/pdf/simpletable.rb, line 938
938:   def __open_new_object__(pdf)
939:     pdf.save_state
940:     tOID = pdf.open_object
941:     pdf.close_object
942:     pdf.add_object(tOID)
943:     pdf.reopen_object(tOID)
944:     tOID
945:   end

Uses ezText to add the text, and returns the height taken by the largest heading. This page will move the headings to a new page if they will not fit completely on this one transaction support will be used to implement this.

[Source]

     # File lib/pdf/simpletable.rb, line 830
830:   def __table_column_headings__(pdf, pos, max_width, height, descender, gap, size, y)
831:     mx = second_go = 0
832:     start_page = pdf.pageset.size
833: 
834:       # y is the position at which the top of the table should start, so the
835:       # base of the first text, is y-height-gap-descender, but ezText starts
836:       # by dropping height.
837: 
838:       # The return from this function is the total cell height, including
839:       # gaps, and y is adjusted to be the postion of the bottom line.
840:     tg = Transaction::Simple::Group.new(pdf, self)
841:     tg.start_transaction(:column_headings)
842: 
843:     ok = false
844:     y -= gap
845:     loop do
846:       break if ok
847:       @cols.each do |name, column|
848:         pdf.pointer = y
849: 
850:         if column.heading
851:           justification = column.heading.justification
852:           bold          = column.heading.bold
853:           title         = column.heading.title
854:         end
855: 
856:         justification ||= :left
857:         bold ||= @bold_headings
858:         title ||= column.name
859: 
860:         title = "<b>#{title}</b>" if bold
861: 
862:         pdf.text(title, :font_size => size, :absolute_left => pos[name],
863:                 :absolute_right => (max_width[name] + pos[name]),
864:                 :justification => justification)
865:         dy = y - pdf.y
866:         mx = dy if dy > mx
867:       end
868: 
869:       y -= (mx + gap) - descender # y = y - mx - gap + descender
870: 
871:         # If this has been moved to a new page, then abort the transaction;
872:         # move to a new page, and put it there. Do not check on the second
873:         # time around to avoid an infinite loop.
874:       if (pdf.pageset.size != start_page and not second_go)
875:         tg.rewind_transaction(:column_headings)
876: 
877:         pdf.start_new_page
878:         save_state
879:         y = @y - gap - descender
880:         ok = false
881:         second_go = true
882:         mx = 0
883:       else
884:         tg.commit_transaction(:column_headings)
885:         ok = true
886:       end
887:     end
888: 
889:     return [mx + gap * 2 - descender, y]
890:   rescue Exception => ex
891:     begin
892:       tg.abort_transaction(:column_headings) if tg.transaction_open?(:column_headings)
893:     rescue
894:       nil
895:     end
896:     raise ex
897:   end

[Source]

     # File lib/pdf/simpletable.rb, line 900
900:   def __table_draw_lines__(pdf, pos, gap, x0, x1, y0, y1, y2, col, inner, outer, opt = :outer)
901:     x0 = 1000
902:     x1 = 0
903: 
904:     pdf.stroke_color(col)
905: 
906:     cnt = 0
907:     n = pos.size
908: 
909:     pos.each do |name, x|
910:       cnt += 1
911: 
912:       if (cnt == 1 or cnt == n)
913:         pdf.stroke_style outer
914:       else
915:         pdf.stroke_style inner
916:       end
917: 
918:       pdf.line(x - gap / 2.0, y0, x - gap / 2.0, y2).stroke
919:       x1 = x if x > x1
920:       x0 = x if x < x0
921:     end
922: 
923:     pdf.stroke_style outer
924: 
925:     pdf.line(x0 - (gap / 2.0) - (outer.width / 2.0), y0,
926:              x1 - (gap / 2.0) + (outer.width / 2.0), y0).stroke
927: 
928:       # Only do the second line if it is different than the first AND each
929:       # row does not have a line on it.
930:     if y0 != y1 and @show_lines == :outer
931:       pdf.line(x0 - gap / 2.0, y1, x1 - gap / 2.0, y1).stroke
932:     end
933:     pdf.line(x0 - (gap / 2.0) - (outer.width / 2.0), y2,
934:              x1 - (gap / 2.0) + (outer.width / 2.0), y2).stroke
935:   end

[Validate]