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)
# File lib/ruport/formatter/pdf.rb, line 67 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 61 def self.proxy_to_pdf_writer include PDFWriterProxy end
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 147 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 76 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 113 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 108 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 119 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 96 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 167 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 280 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 134 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 103 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 225 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 230 def move_cursor_to(n) pdf_writer.y = n end
# File lib/ruport/formatter/pdf.rb, line 239 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 235 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 248 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 269 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 259 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 88 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 153 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 201 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
Generated with the Darkfish Rdoc Generator 2.