This class provides PDF output for Ruport’s Table, Group, and Grouping controllers. It wraps Austin Ziegler’s PDF::Writer to provide a higher level interface and provides a number of helpers designed to make generating PDF reports much easier. You will typically want to build subclasses of this formatter to customize it as needed.
Many methods forward options to PDF::Writer, so you may wish to consult its API docs.
General: * paper_size #=> "LETTER" * paper_orientation #=> :portrait Text: * text_format (sets options to be passed to add_text by default) Table: * table_format (a hash that can take any of the options available to PDF::SimpleTable) * table_format[:maximum_width] #=> 500 Grouping: * style (:inline,:justified,:separated,:offset)
Call PDF::Writer#text with the given arguments, using
text_format
defaults, if they are defined.
Example:
options.text_format { :font_size => 14 } add_text("Hello Joe") #renders at 14pt add_text("Hello Mike",:font_size => 16) # renders at 16pt
# File lib/ruport/formatter/pdf.rb, line 145 def add_text(text, format_opts={}) format_opts = options.text_format.merge(format_opts) if options.text_format pdf_writer.text(text, format_opts) end
Hook for setting available options using a template. See the template documentation for the available options and their format.
# File lib/ruport/formatter/pdf.rb, line 74 def apply_template apply_page_format_template(template.page) apply_text_format_template(template.text) apply_table_format_template(template.table) apply_column_format_template(template.column) apply_heading_format_template(template.heading) apply_grouping_format_template(template.grouping) end
Renders the group as a table for Controller::Group.
# File lib/ruport/formatter/pdf.rb, line 111 def build_group_body render_table data, options.to_hash.merge(:formatter => pdf_writer) end
Generates a header with the group name for Controller::Group.
# File lib/ruport/formatter/pdf.rb, line 106 def build_group_header pad(10) { add_text data.name.to_s, :justification => :center } end
Determines which style to use and renders the main body for Controller::Grouping.
# File lib/ruport/formatter/pdf.rb, line 117 def build_grouping_body case options.style when :inline render_inline_grouping(options.to_hash.merge(:formatter => pdf_writer, :skip_finalize_table => true)) when :justified, :separated render_justified_or_separated_grouping when :offset render_offset_grouping else raise NotImplementedError, "Unknown style" end end
Calls the #draw_table method.
# File lib/ruport/formatter/pdf.rb, line 94 def build_table_body draw_table(data) end
If the image is bigger than the box, it will be scaled down until it fits.
If the image is smaller than the box, it won’t be resized.
options:
:x: left bound of box
:y: bottom bound of box
:width: width of box
:height: height of box
# File lib/ruport/formatter/pdf.rb, line 165 def center_image_in_box(path, image_opts={}) x = image_opts[:x] y = image_opts[:y] width = image_opts[:width] height = image_opts[:height] info = ::PDF::Writer::Graphics::ImageInfo.new(File.open(path, "rb")) # reduce the size of the image until it fits into the requested box img_width, img_height = fit_image_in_box(info.width,width,info.height,height) # if the image is smaller than the box, calculate the white space buffer x, y = add_white_space(x,y,img_width,width,img_height,height) pdf_writer.add_image_from_file(path, x, y, img_width, img_height) end
Draws a PDF::SimpleTable using the given data (usually a Data::Table). Takes all the options you can set on a PDF::SimpleTable object, see the PDF::Writer API docs for details, or check our quick reference at:
stonecode.svnrepository.com/ruport/trac.cgi/wiki/PdfWriterQuickRef
# File lib/ruport/formatter/pdf.rb, line 278 def draw_table(table_data, format_opts={}) m = "PDF Formatter requires column_names to be defined" raise FormatterError, m if table_data.column_names.empty? table_data.rename_columns { |c| c.to_s } if options.table_format format_opts = Marshal.load(Marshal.dump(options.table_format.merge(format_opts))) end old = pdf_writer.font_size ::PDF::SimpleTable.new do |table| table.maximum_width = 500 table.column_order = table_data.column_names table.data = table_data table.data = [{}] if table.data.empty? apply_pdf_table_column_opts(table,table_data,format_opts) format_opts.each {|k,v| table.send("#{k}=", v) } table.render_on(pdf_writer) end pdf_writer.font_size = old end
Calls render_pdf
.
# File lib/ruport/formatter/pdf.rb, line 132 def finalize_grouping render_pdf end
Appends the results of PDF::Writer#render to output for your
pdf_writer
object.
# File lib/ruport/formatter/pdf.rb, line 101 def finalize_table render_pdf unless options.skip_finalize_table end
Adds n to pdf_writer.y, moving the vertical drawing position in the document.
# File lib/ruport/formatter/pdf.rb, line 223 def move_cursor(n) pdf_writer.y += n end
Moves the cursor to a specific y coordinate in the document.
# File lib/ruport/formatter/pdf.rb, line 228 def move_cursor_to(n) pdf_writer.y = n end
# File lib/ruport/formatter/pdf.rb, line 237 def move_down(n) pdf_writer.y -= n end
Moves the vertical drawing position in the document upwards by n.
# File lib/ruport/formatter/pdf.rb, line 233 def move_up(n) pdf_writer.y += n end
Adds a specified amount of whitespace above and below the code in your block. For example, if you want to surround the top and bottom of a line of text with 5 pixels of whitespace:
pad(5) { add_text "This will be padded top and bottom" }
# File lib/ruport/formatter/pdf.rb, line 246 def pad(y,&block) move_cursor(-y) block.call move_cursor(-y) end
Adds a specified amount of whitespace below the code in your block. For example, if you want to add a 10 pixel buffer to the bottom of a line of text:
pad_bottom(10) { add_text "This will be padded on bottom" }
# File lib/ruport/formatter/pdf.rb, line 267 def pad_bottom(y,&block) block.call move_cursor(-y) end
Adds a specified amount of whitespace above the code in your block. For example, if you want to add a 10 pixel buffer to the top of a line of text:
pad_top(10) { add_text "This will be padded on top" }
# File lib/ruport/formatter/pdf.rb, line 257 def pad_top(y,&block) move_cursor(-y) block.call end
Returns the current PDF::Writer object or creates a new one if it has not been set yet.
# File lib/ruport/formatter/pdf.rb, line 86 def pdf_writer @pdf_writer ||= options.formatter || ::PDF::Writer.new( :paper => options.paper_size || "LETTER", :orientation => options.paper_orientation || :portrait) end
Calls PDF::Writer#render and appends to output
.
# File lib/ruport/formatter/pdf.rb, line 151 def render_pdf output << pdf_writer.render end
Draws some text on the canvas, surrounded by a box with rounded corners.
Yields an OpenStruct which options can be defined on.
Example:
rounded_text_box(options.text) do |o| o.radius = 5 o.width = options.width || 400 o.height = options.height || 130 o.font_size = options.font_size || 12 o.heading = options.heading o.x = pdf_writer.absolute_x_middle - o.width/2 o.y = 300 end
# File lib/ruport/formatter/pdf.rb, line 199 def rounded_text_box(text) opts = OpenStruct.new yield(opts) resize_text_to_box(text, opts) pdf_writer.save_state draw_box(opts.x, opts.y, opts.width, opts.height, opts.radius, opts.fill_color, opts.stroke_color) add_text_with_bottom_border(opts.heading, opts.x, opts.y, opts.width, opts.font_size) if opts.heading pdf_writer.restore_state start_position = opts.heading ? opts.y - 20 : opts.y draw_text(text, :y => start_position, :left => opts.x, :right => opts.x + opts.width, :justification => opts.justification || :center, :font_size => opts.font_size) move_cursor_to(opts.y - opts.height) end
# File lib/ruport/formatter/pdf.rb, line 65 def initialize Ruport.quiet do require "pdf/writer" require "pdf/simpletable" end end
If you use this macro in your formatter, Ruport will automatically forward calls to the underlying PDF::Writer, for any methods that are not wrapped or redefined.
# File lib/ruport/formatter/pdf.rb, line 59 def self.proxy_to_pdf_writer include PDFWriterProxy end