Class | PDF::SimpleTable |
In: |
lib/pdf/simpletable.rb
|
Parent: | Object |
This class will create tables with a relatively simple API and internal implementation.
WIDTH_FACTOR | = | 1.01 |
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.
|
||||||||
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:
|
||||||||
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.
|
||||||||
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:
|
||||||||
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. |
# 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
Render the table on the PDF::Writer document provided.
# 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
Find the maximum widths of the text within each column. Default to zero.
# 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.
# 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
# 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.
# 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
# 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