Files

Ruport::Formatter::PDF

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.

Rendering Options

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)

Attributes

pdf_writer[W]

Public Class Methods

new() click to toggle source
# File lib/ruport/formatter/pdf.rb, line 67
def initialize
  Ruport.quiet do   
    require "pdf/writer"
    require "pdf/simpletable"
  end
end
proxy_to_pdf_writer() click to toggle source

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

Public Instance Methods

add_text(text, format_opts={}) click to toggle source

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
apply_template() click to toggle source

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
build_group_body() click to toggle source

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
build_group_header() click to toggle source

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
build_grouping_body() click to toggle source

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
build_table_body() click to toggle source

Calls the draw_table method.

# File lib/ruport/formatter/pdf.rb, line 96
def build_table_body
  draw_table(data)
end
center_image_in_box(path, image_opts={}) click to toggle source
  • 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
draw_table(table_data, format_opts={}) click to toggle source

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
finalize_grouping() click to toggle source

Calls render_pdf.

# File lib/ruport/formatter/pdf.rb, line 134
def finalize_grouping
  render_pdf
end
finalize_table() click to toggle source

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
move_cursor(n) click to toggle source

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
move_cursor_to(n) click to toggle source

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
move_down(n) click to toggle source
# File lib/ruport/formatter/pdf.rb, line 239
def move_down(n)
  pdf_writer.y -= n
end
move_up(n) click to toggle source

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
pad(y,&block) click to toggle source

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
pad_bottom(y,&block) click to toggle source

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
pad_top(y,&block) click to toggle source

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
pdf_writer() click to toggle source

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
render_pdf() click to toggle source

Calls PDF::Writer#render and appends to output.

# File lib/ruport/formatter/pdf.rb, line 153
def render_pdf
  output << pdf_writer.render
end
rounded_text_box(text) click to toggle source

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

[Validate]

Generated with the Darkfish Rdoc Generator 2.