Class: Ruport::Formatter::PDF
- Inherits:
-
Ruport::Formatter
- Object
- Ruport::Formatter
- Ruport::Formatter::PDF
- Includes:
- DrawingHelpers
- Defined in:
- lib/ruport/formatter/pdf.rb
Overview
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)
Defined Under Namespace
Modules: DrawingHelpers, PDFWriterProxy
Instance Attribute Summary collapse
-
#pdf_writer ⇒ Object
Returns the current PDF::Writer object or creates a new one if it has not been set yet.
Attributes inherited from Ruport::Formatter
Class Method Summary collapse
-
.proxy_to_pdf_writer ⇒ Object
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.
Instance Method Summary collapse
-
#add_text(text, format_opts = {}) ⇒ Object
Call PDF::Writer#text with the given arguments, using
text_format
defaults, if they are defined. -
#apply_template ⇒ Object
Hook for setting available options using a template.
-
#build_group_body ⇒ Object
Renders the group as a table for Controller::Group.
-
#build_group_header ⇒ Object
Generates a header with the group name for Controller::Group.
-
#build_grouping_body ⇒ Object
Determines which style to use and renders the main body for Controller::Grouping.
-
#build_table_body ⇒ Object
Calls the draw_table method.
-
#center_image_in_box(path, image_opts = {}) ⇒ Object
-
If the image is bigger than the box, it will be scaled down until it fits.
-
-
#draw_table(table_data, format_opts = {}) ⇒ Object
Draws a PDF::SimpleTable using the given data (usually a Data::Table).
-
#finalize_grouping ⇒ Object
Calls
render_pdf
. -
#finalize_table ⇒ Object
Appends the results of PDF::Writer#render to output for your
pdf_writer
object. -
#initialize ⇒ PDF
constructor
A new instance of PDF.
-
#move_cursor(n) ⇒ Object
Adds n to pdf_writer.y, moving the vertical drawing position in the document.
-
#move_cursor_to(n) ⇒ Object
Moves the cursor to a specific y coordinate in the document.
- #move_down(n) ⇒ Object
-
#move_up(n) ⇒ Object
Moves the vertical drawing position in the document upwards by n.
-
#pad(y, &block) ⇒ Object
Adds a specified amount of whitespace above and below the code in your block.
-
#pad_bottom(y, &block) ⇒ Object
Adds a specified amount of whitespace below the code in your block.
-
#pad_top(y, &block) ⇒ Object
Adds a specified amount of whitespace above the code in your block.
-
#render_pdf ⇒ Object
Calls PDF::Writer#render and appends to
output
. -
#rounded_text_box(text) {|opts| ... } ⇒ Object
Draws some text on the canvas, surrounded by a box with rounded corners.
Methods included from DrawingHelpers
#bottom_boundary, #cursor, #draw_text, #draw_text!, #finalize, #horizontal_line, #horizontal_rule, #left_boundary, #right_boundary, #top_boundary, #vertical_line_at
Methods inherited from Ruport::Formatter
build, #clear_output, #erb, formats, #method_missing, #output, renders, save_as_binary_file, #save_output, #template
Methods included from RenderingTools
#render_group, #render_grouping, #render_inline_grouping, #render_row, #render_table
Constructor Details
Dynamic Method Handling
This class handles dynamic methods through the method_missing method in the class Ruport::Formatter
Instance Attribute Details
#pdf_writer ⇒ Object
Returns the current PDF::Writer object or creates a new one if it has not been set yet.
88 89 90 91 92 |
# File 'lib/ruport/formatter/pdf.rb', line 88 def pdf_writer @pdf_writer ||= .formatter || ::PDF::Writer.new( :paper => .paper_size || "LETTER", :orientation => .paper_orientation || :portrait) end |
Class Method Details
.proxy_to_pdf_writer ⇒ Object
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.
61 62 63 |
# File 'lib/ruport/formatter/pdf.rb', line 61 def self.proxy_to_pdf_writer include PDFWriterProxy end |
Instance Method Details
#add_text(text, format_opts = {}) ⇒ Object
Call PDF::Writer#text with the given arguments, using text_format
defaults, if they are defined.
Example:
.text_format { :font_size => 14 }
add_text("Hello Joe") #renders at 14pt
add_text("Hello Mike",:font_size => 16) # renders at 16pt
147 148 149 150 |
# File 'lib/ruport/formatter/pdf.rb', line 147 def add_text(text, format_opts={}) format_opts = .text_format.merge(format_opts) if .text_format pdf_writer.text(text, format_opts) end |
#apply_template ⇒ Object
Hook for setting available options using a template. See the template documentation for the available options and their format.
76 77 78 79 80 81 82 83 |
# 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 ⇒ Object
Renders the group as a table for Controller::Group.
113 114 115 |
# File 'lib/ruport/formatter/pdf.rb', line 113 def build_group_body render_table data, .to_hash.merge(:formatter => pdf_writer) end |
#build_group_header ⇒ Object
Generates a header with the group name for Controller::Group.
108 109 110 |
# 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 ⇒ Object
Determines which style to use and renders the main body for Controller::Grouping.
119 120 121 122 123 124 125 126 127 128 129 130 131 |
# File 'lib/ruport/formatter/pdf.rb', line 119 def build_grouping_body case .style when :inline render_inline_grouping(.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 ⇒ Object
Calls the draw_table method.
96 97 98 |
# File 'lib/ruport/formatter/pdf.rb', line 96 def build_table_body draw_table(data) end |
#center_image_in_box(path, image_opts = {}) ⇒ Object
-
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
167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 |
# 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 = {}) ⇒ Object
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
280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 |
# 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 .table_format format_opts = Marshal.load(Marshal.dump(.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 ⇒ Object
Calls render_pdf
.
134 135 136 |
# File 'lib/ruport/formatter/pdf.rb', line 134 def finalize_grouping render_pdf end |
#finalize_table ⇒ Object
Appends the results of PDF::Writer#render to output for your pdf_writer
object.
103 104 105 |
# File 'lib/ruport/formatter/pdf.rb', line 103 def finalize_table render_pdf unless .skip_finalize_table end |
#move_cursor(n) ⇒ Object
Adds n to pdf_writer.y, moving the vertical drawing position in the document.
225 226 227 |
# File 'lib/ruport/formatter/pdf.rb', line 225 def move_cursor(n) pdf_writer.y += n end |
#move_cursor_to(n) ⇒ Object
Moves the cursor to a specific y coordinate in the document.
230 231 232 |
# File 'lib/ruport/formatter/pdf.rb', line 230 def move_cursor_to(n) pdf_writer.y = n end |
#move_down(n) ⇒ Object
239 240 241 |
# File 'lib/ruport/formatter/pdf.rb', line 239 def move_down(n) pdf_writer.y -= n end |
#move_up(n) ⇒ Object
Moves the vertical drawing position in the document upwards by n.
235 236 237 |
# File 'lib/ruport/formatter/pdf.rb', line 235 def move_up(n) pdf_writer.y += n end |
#pad(y, &block) ⇒ Object
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" }
248 249 250 251 252 |
# 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) ⇒ Object
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" }
269 270 271 272 |
# File 'lib/ruport/formatter/pdf.rb', line 269 def pad_bottom(y,&block) block.call move_cursor(-y) end |
#pad_top(y, &block) ⇒ Object
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" }
259 260 261 262 |
# File 'lib/ruport/formatter/pdf.rb', line 259 def pad_top(y,&block) move_cursor(-y) block.call end |
#render_pdf ⇒ Object
Calls PDF::Writer#render and appends to output
.
153 154 155 |
# File 'lib/ruport/formatter/pdf.rb', line 153 def render_pdf output << pdf_writer.render end |
#rounded_text_box(text) {|opts| ... } ⇒ Object
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(.text) do |o|
o.radius = 5
o.width = .width || 400
o.height = .height || 130
o.font_size = .font_size || 12
o.heading = .heading
o.x = pdf_writer.absolute_x_middle - o.width/2
o.y = 300
end
201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 |
# 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 |