ruport 1.6.3 → 1.7.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,73 +1,73 @@
1
- # Ruport : Extensible Reporting System
1
+ # Ruport : Extensible Reporting System
2
2
  #
3
3
  # formatter.rb provides a generalized base class for creating ruport formatters.
4
- #
4
+ #
5
5
  # Created By Gregory Brown
6
- # Copyright (C) December 2006, All Rights Reserved.
6
+ # Copyright (C) December 2006, All Rights Reserved.
7
7
  #
8
8
  # This is free software distributed under the same terms as Ruby 1.8
9
9
  # See LICENSE and COPYING for details.
10
- module Ruport
10
+ module Ruport
11
11
  # Formatter is the base class for Ruport's format implementations.
12
12
  #
13
13
  # Typically, a Formatter will implement one or more output types,
14
- # and be registered with one or more Controller classes.
14
+ # and be registered with one or more Controller classes.
15
15
  #
16
16
  # This class provides all the necessary base functionality to make
17
17
  # use of Ruport's rendering system, including option handling, data
18
18
  # access, and basic output wrapping.
19
19
  #
20
20
  # The following example should provide a general idea of how formatters
21
- # work, but see the built in formatters for reference implementations.
22
- #
21
+ # work, but see the built in formatters for reference implementations.
22
+ #
23
23
  # A simple Controller definition is included to help show the example in
24
24
  # context, but you can also build your own custom interface to formatter
25
25
  # if you wish.
26
26
  #
27
27
  # class ReverseController < Ruport::Controller
28
- # stage :reversed_header, :reversed_body
28
+ # stage :reversed_header, :reversed_body
29
29
  # end
30
- #
31
- # class ReversedText < Ruport::Formatter
32
- #
30
+ #
31
+ # class ReversedText < Ruport::Formatter
32
+ #
33
33
  # # Hooks formatter up to controller
34
- # renders :txt, :for => ReverseController
35
- #
34
+ # renders :txt, :for => ReverseController
35
+ #
36
36
  # # Implements ReverseController's :reversed_header hook
37
- # # but can be used by any controller
38
- # def build_reversed_header
37
+ # # but can be used by any controller
38
+ # def build_reversed_header
39
39
  # output << "#{options.header_text}\n"
40
40
  # output << "The reversed text will follow\n"
41
- # end
42
- #
41
+ # end
42
+ #
43
43
  # # Implements ReverseController's :reversed_body hook
44
44
  # # but can be used by any controller
45
45
  # def build_reversed_body
46
46
  # output << data.reverse << "\n"
47
- # end
47
+ # end
48
48
  #
49
- # end
49
+ # end
50
50
  #
51
51
  # puts ReverseController.render_txt(:data => "apple",
52
52
  # :header_text => "Hello Mike, Hello Joe!")
53
- #
53
+ #
54
54
  # -----
55
- # OUTPUT:
56
- #
55
+ # OUTPUT:
56
+ #
57
57
  # Hello Mike, Hello Joe!
58
58
  # The reversed text will follow
59
59
  # elppa
60
- #
60
+ #
61
61
  class Formatter
62
-
62
+
63
63
  # Provides shortcuts so that you can use Ruport's default rendering
64
- # capabilities within your custom formatters
64
+ # capabilities within your custom formatters
65
65
  #
66
66
  module RenderingTools
67
67
  # Uses Controller::Row to render the Row object with the
68
68
  # given options.
69
69
  #
70
- # Sets the <tt>:io</tt> attribute by default to the existing
70
+ # Sets the <tt>:io</tt> attribute by default to the existing
71
71
  # formatter's <tt>output</tt> object.
72
72
  def render_row(row,options={},&block)
73
73
  render_helper(Controller::Row,row,options,&block)
@@ -99,12 +99,12 @@ module Ruport
99
99
  def render_grouping(grouping,options={},&block)
100
100
  render_helper(Controller::Grouping,grouping,options,&block)
101
101
  end
102
-
102
+
103
103
  # Iterates through the data in the grouping and renders each group
104
104
  # followed by a newline.
105
105
  #
106
106
  def render_inline_grouping(options={},&block)
107
- data.each do |_,group|
107
+ data.each do |_,group|
108
108
  render_group(group, options, &block)
109
109
  output << "\n"
110
110
  end
@@ -113,10 +113,10 @@ module Ruport
113
113
  private
114
114
 
115
115
  def render_helper(rend_klass, source_data,options={},&block)
116
- options = {:data => source_data,
116
+ options = {:data => source_data,
117
117
  :io => output,
118
- :layout => false }.merge(options)
119
-
118
+ :layout => false }.merge(options)
119
+
120
120
  options[:io] = "" if self.class.kind_of?(Ruport::Formatter::PDF)
121
121
  rend_klass.render(format,options) do |rend|
122
122
  block[rend] if block
@@ -126,13 +126,13 @@ module Ruport
126
126
  end
127
127
 
128
128
  include RenderingTools
129
-
129
+
130
130
  # Set by the <tt>:data</tt> attribute from Controller#render
131
- attr_reader :data
132
-
131
+ attr_reader :data
132
+
133
133
  # Set automatically by Controller#render(format) or Controller#render_format
134
- attr_accessor :format
135
-
134
+ attr_accessor :format
135
+
136
136
  # Set automatically by Controller#render as a Controller::Options object built
137
137
  # by the hash provided.
138
138
  attr_writer :options
@@ -145,24 +145,24 @@ module Ruport
145
145
  #
146
146
  def self.renders(fmts,options={})
147
147
  Array(fmts).each do |format|
148
- Array(options[:for]).each do |o|
149
- o.send(:add_format,self,format)
148
+ Array(options[:for]).each do |o|
149
+ o.send(:add_format,self,format)
150
150
  formats << format unless formats.include?(format)
151
- end
151
+ end
152
152
  end
153
153
  end
154
-
154
+
155
155
  # Allows you to implement stages in your formatter using the
156
156
  # following syntax:
157
157
  #
158
- # class ReversedText < Ruport::Formatter
158
+ # class ReversedText < Ruport::Formatter
159
159
  # renders :txt, :for => ReverseController
160
- #
160
+ #
161
161
  # build :reversed_header do
162
162
  # output << "#{options.header_text}\n"
163
163
  # output << "The reversed text will follow\n"
164
164
  # end
165
- #
165
+ #
166
166
  # build :reversed_body do
167
167
  # output << data.reverse << "\n"
168
168
  # end
@@ -171,12 +171,12 @@ module Ruport
171
171
  def self.build(stage,&block)
172
172
  define_method "build_#{stage}", &block
173
173
  end
174
-
174
+
175
175
  # Gives a list of formats registered for this formatter.
176
176
  def self.formats
177
177
  @formats ||= []
178
- end
179
-
178
+ end
179
+
180
180
  # Returns the template currently set for this formatter.
181
181
  def template
182
182
  Template[options.template] rescue nil || Template[:default]
@@ -191,7 +191,7 @@ module Ruport
191
191
  # Provides a Controller::Options object for storing formatting options.
192
192
  def options
193
193
  @options ||= Controller::Options.new
194
- end
194
+ end
195
195
 
196
196
  # Sets the data object, making a local copy using #dup. This may have
197
197
  # a significant overhead for large tables, so formatters which don't
@@ -204,24 +204,24 @@ module Ruport
204
204
  def clear_output
205
205
  @output.replace("")
206
206
  end
207
-
207
+
208
208
  # Saves the output to a file.
209
209
  def save_output(filename)
210
210
  File.open(filename,"w") {|f| f << output }
211
211
  end
212
-
212
+
213
213
  # Use to define that your formatter should save in binary format
214
214
  def self.save_as_binary_file
215
215
  define_method :save_output do |filename|
216
216
  File.open(filename,"wb") {|f| f << output }
217
217
  end
218
218
  end
219
-
219
+
220
220
  # Evaluates the string using ERB and returns the results.
221
221
  #
222
222
  # If <tt>:binding</tt> is specified, it will evaluate the template
223
223
  # in that context.
224
- def erb(string,options={})
224
+ def erb(string,options={})
225
225
  require "erb"
226
226
  if string =~ /(\.r\w+)|(\.erb)$/
227
227
  ERB.new(File.read(string)).result(options[:binding]||binding)
@@ -245,10 +245,11 @@ module Ruport
245
245
  end
246
246
  end
247
247
  end
248
- end
248
+ end
249
249
 
250
250
  require "ruport/formatter/template"
251
251
  require "ruport/formatter/csv"
252
252
  require "ruport/formatter/html"
253
253
  require "ruport/formatter/text"
254
254
  require "ruport/formatter/pdf"
255
+ require "ruport/formatter/prawn_pdf"
@@ -14,16 +14,15 @@
14
14
  module Ruport
15
15
 
16
16
  # This formatter implements the CSV format for Ruport's Row, Table, Group
17
- # and Grouping controllers. It is a light wrapper around
18
- # James Edward Gray II's FasterCSV.
17
+ # and Grouping controllers.
19
18
  #
20
19
  # === Rendering Options
21
20
  #
22
21
  # <tt>:style</tt> Used for grouping (:inline,:justified,:raw)
23
22
  #
24
- # <tt>:format_options</tt> A hash of FasterCSV options
23
+ # <tt>:format_options</tt> A hash of CSV options
25
24
  #
26
- # <tt>:formatter</tt> An existing FasterCSV object to write to
25
+ # <tt>:formatter</tt> An existing CSV object to write to
27
26
  #
28
27
  # <tt>:show_table_headers</tt> True by default
29
28
  #
@@ -35,7 +34,7 @@ module Ruport
35
34
  Controller::Group, Controller::Grouping ]
36
35
 
37
36
  def initialize
38
- require "fastercsv" unless RUBY_VERSION > "1.9"
37
+ require "csv"
39
38
  end
40
39
 
41
40
  attr_writer :csv_writer
@@ -49,14 +48,14 @@ module Ruport
49
48
  options.format_options ||= template.format_options
50
49
  end
51
50
 
52
- # Returns the current FCSV object or creates a new one if it has not
51
+ # Returns the current CSV object or creates a new one if it has not
53
52
  # been set yet. Note that FCSV(sig) has a cache and returns the *same*
54
53
  # FCSV object if writing to the same underlying output with the same
55
54
  # options.
56
55
  #
57
56
  def csv_writer
58
57
  @csv_writer ||= options.formatter ||
59
- FCSV(output, options.format_options || {})
58
+ ::CSV.instance(output, options.format_options || {})
60
59
  end
61
60
 
62
61
  # Generates table header by turning column_names into a CSV row.
@@ -40,12 +40,7 @@ module Ruport
40
40
  # This method does not do anything if options.show_table_headers is false
41
41
  # or the Data::Table has no column names.
42
42
  def build_table_header
43
- output << "\t<table>\n"
44
- unless data.column_names.empty? || !options.show_table_headers
45
- output << "\t\t<tr>\n\t\t\t<th>" +
46
- data.column_names.join("</th>\n\t\t\t<th>") +
47
- "</th>\n\t\t</tr>\n"
48
- end
43
+ output << build_header(options.show_table_headers ? data.column_names : nil)
49
44
  end
50
45
 
51
46
  # Uses the Row controller to build up the table body.
@@ -119,12 +114,19 @@ module Ruport
119
114
  end
120
115
 
121
116
  private
122
-
117
+
118
+ def build_header(columns)
119
+ if !columns || columns.empty?
120
+ "\t<table>\n"
121
+ else
122
+ "\t<table>\n\t\t<thead>\n\t\t<tr>\n\t\t\t<th>" +
123
+ columns.join("</th>\n\t\t\t<th>") +
124
+ "</th>\n\t\t</tr>\n\t\t</thead>\n"
125
+ end
126
+ end
127
+
123
128
  def render_justified_grouping
124
- output << "\t<table>\n\t\t<tr>\n\t\t\t<th>" +
125
- "#{data.grouped_by}</th>\n\t\t\t<th>" +
126
- grouping_columns.join("</th>\n\t\t\t<th>") +
127
- "</th>\n\t\t</tr>\n"
129
+ output << build_header(options.show_group_headers ? ([data.grouped_by] + grouping_columns) : nil)
128
130
  data.each do |name, group|
129
131
  group.each_with_index do |row, i|
130
132
  output << "\t\t<tr>\n\t\t\t"
@@ -1,19 +1,19 @@
1
- # Ruport : Extensible Reporting System
1
+ # Ruport : Extensible Reporting System
2
2
  #
3
3
  # formatter/pdf.rb provides text formatting for Ruport.
4
- #
5
- # Created by Gregory Brown, February 2006
4
+ #
5
+ # Created by Gregory Brown, February 2006
6
6
  # Extended by James Healy, Fall 2006
7
- # Copyright (C) 2006-2007 Gregory Brown / James Healy, All Rights Reserved.
7
+ # Copyright (C) 2006-2007 Gregory Brown / James Healy, All Rights Reserved.
8
8
  #
9
9
  # Initially inspired by some ideas and code from Simon Claret,
10
10
  # with many improvements from James Healy and Michael Milner over time.
11
11
  #
12
12
  # This is free software distributed under the same terms as Ruby 1.8
13
- # See LICENSE and COPYING for details.
13
+ # See LICENSE and COPYING for details.
14
14
  #
15
15
  module Ruport
16
-
16
+
17
17
  # This class provides PDF output for Ruport's Table, Group, and Grouping
18
18
  # controllers. It wraps Austin Ziegler's PDF::Writer to provide a higher
19
19
  # level interface and provides a number of helpers designed to make
@@ -29,17 +29,17 @@ module Ruport
29
29
  # * paper_orientation #=> :portrait
30
30
  #
31
31
  # Text:
32
- # * text_format (sets options to be passed to add_text by default)
33
- #
32
+ # * text_format (sets options to be passed to add_text by default)
33
+ #
34
34
  # Table:
35
35
  # * table_format (a hash that can take any of the options available
36
36
  # to PDF::SimpleTable)
37
- # * table_format[:maximum_width] #=> 500
37
+ # * table_format[:maximum_width] #=> 500
38
38
  #
39
39
  # Grouping:
40
40
  # * style (:inline,:justified,:separated,:offset)
41
41
  #
42
- class Formatter::PDF < Formatter
42
+ class Formatter::PDF < Formatter
43
43
 
44
44
  module PDFWriterProxy #:nodoc:
45
45
  def method_missing(id,*args)
@@ -48,13 +48,11 @@ module Ruport
48
48
  pdf_writer.send(id,*args)
49
49
  end
50
50
  end
51
-
51
+
52
52
  renders :pdf, :for => [ Controller::Row, Controller::Table,
53
53
  Controller::Group, Controller::Grouping ]
54
-
55
54
  attr_writer :pdf_writer
56
55
 
57
-
58
56
  # If you use this macro in your formatter, Ruport will automatically forward
59
57
  # calls to the underlying PDF::Writer, for any methods that are not wrapped
60
58
  # or redefined.
@@ -70,8 +68,8 @@ module Ruport
70
68
  require "pdf/simpletable"
71
69
  end
72
70
  end
73
-
74
- # Hook for setting available options using a template. See the template
71
+
72
+ # Hook for setting available options using a template. See the template
75
73
  # documentation for the available options and their format.
76
74
  def apply_template
77
75
  apply_page_format_template(template.page)
@@ -103,20 +101,20 @@ module Ruport
103
101
  def finalize_table
104
102
  render_pdf unless options.skip_finalize_table
105
103
  end
106
-
104
+
107
105
  # Generates a header with the group name for Controller::Group.
108
106
  def build_group_header
109
107
  pad(10) { add_text data.name.to_s, :justification => :center }
110
108
  end
111
-
109
+
112
110
  # Renders the group as a table for Controller::Group.
113
111
  def build_group_body
114
112
  render_table data, options.to_hash.merge(:formatter => pdf_writer)
115
113
  end
116
-
114
+
117
115
  # Determines which style to use and renders the main body for
118
116
  # Controller::Grouping.
119
- def build_grouping_body
117
+ def build_grouping_body
120
118
  case options.style
121
119
  when :inline
122
120
  render_inline_grouping(options.to_hash.merge(:formatter => pdf_writer,
@@ -129,14 +127,14 @@ module Ruport
129
127
  raise NotImplementedError, "Unknown style"
130
128
  end
131
129
  end
132
-
130
+
133
131
  # Calls <tt>render_pdf</tt>.
134
132
  def finalize_grouping
135
133
  render_pdf
136
134
  end
137
135
 
138
136
  # Call PDF::Writer#text with the given arguments, using
139
- # <tt>text_format</tt> defaults, if they are defined.
137
+ # <tt>text_format</tt> defaults, if they are defined.
140
138
  #
141
139
  # Example:
142
140
  #
@@ -153,7 +151,7 @@ module Ruport
153
151
  def render_pdf
154
152
  output << pdf_writer.render
155
153
  end
156
-
154
+
157
155
  # - If the image is bigger than the box, it will be scaled down until
158
156
  # it fits.
159
157
  # - If the image is smaller than the box, it won't be resized.
@@ -164,7 +162,7 @@ module Ruport
164
162
  # - :width: width of box
165
163
  # - :height: height of box
166
164
  #
167
- def center_image_in_box(path, image_opts={})
165
+ def center_image_in_box(path, image_opts={})
168
166
  x = image_opts[:x]
169
167
  y = image_opts[:y]
170
168
  width = image_opts[:width]
@@ -174,7 +172,7 @@ module Ruport
174
172
  # reduce the size of the image until it fits into the requested box
175
173
  img_width, img_height =
176
174
  fit_image_in_box(info.width,width,info.height,height)
177
-
175
+
178
176
  # if the image is smaller than the box, calculate the white space buffer
179
177
  x, y = add_white_space(x,y,img_width,width,img_height,height)
180
178
 
@@ -184,7 +182,7 @@ module Ruport
184
182
  # Draws some text on the canvas, surrounded by a box with rounded corners.
185
183
  #
186
184
  # Yields an OpenStruct which options can be defined on.
187
- #
185
+ #
188
186
  # Example:
189
187
  #
190
188
  # rounded_text_box(options.text) do |o|
@@ -201,7 +199,7 @@ module Ruport
201
199
  def rounded_text_box(text)
202
200
  opts = OpenStruct.new
203
201
  yield(opts)
204
-
202
+
205
203
  resize_text_to_box(text, opts)
206
204
 
207
205
  pdf_writer.save_state
@@ -225,7 +223,7 @@ module Ruport
225
223
  def move_cursor(n)
226
224
  pdf_writer.y += n
227
225
  end
228
-
226
+
229
227
  # Moves the cursor to a specific y coordinate in the document.
230
228
  def move_cursor_to(n)
231
229
  pdf_writer.y = n
@@ -239,7 +237,7 @@ module Ruport
239
237
  def move_down(n)
240
238
  pdf_writer.y -= n
241
239
  end
242
-
240
+
243
241
  # Adds a specified amount of whitespace above and below the code
244
242
  # in your block. For example, if you want to surround the top and
245
243
  # bottom of a line of text with 5 pixels of whitespace:
@@ -250,8 +248,8 @@ module Ruport
250
248
  block.call
251
249
  move_cursor(-y)
252
250
  end
253
-
254
- # Adds a specified amount of whitespace above the code in your block.
251
+
252
+ # Adds a specified amount of whitespace above the code in your block.
255
253
  # For example, if you want to add a 10 pixel buffer to the top of a
256
254
  # line of text:
257
255
  #
@@ -260,8 +258,8 @@ module Ruport
260
258
  move_cursor(-y)
261
259
  block.call
262
260
  end
263
-
264
- # Adds a specified amount of whitespace below the code in your block.
261
+
262
+ # Adds a specified amount of whitespace below the code in your block.
265
263
  # For example, if you want to add a 10 pixel buffer to the bottom of a
266
264
  # line of text:
267
265
  #
@@ -270,19 +268,19 @@ module Ruport
270
268
  block.call
271
269
  move_cursor(-y)
272
270
  end
273
-
271
+
274
272
  # Draws a PDF::SimpleTable using the given data (usually a Data::Table).
275
273
  # Takes all the options you can set on a PDF::SimpleTable object,
276
274
  # see the PDF::Writer API docs for details, or check our quick reference
277
- # at:
278
- #
275
+ # at:
276
+ #
279
277
  # http://stonecode.svnrepository.com/ruport/trac.cgi/wiki/PdfWriterQuickRef
280
278
  def draw_table(table_data, format_opts={})
281
279
  m = "PDF Formatter requires column_names to be defined"
282
280
  raise FormatterError, m if table_data.column_names.empty?
283
-
284
- table_data.rename_columns { |c| c.to_s }
285
-
281
+
282
+ table_data.rename_columns { |c| c.to_s }
283
+
286
284
  if options.table_format
287
285
  format_opts =
288
286
  Marshal.load(Marshal.dump(options.table_format.merge(format_opts)))
@@ -294,7 +292,7 @@ module Ruport
294
292
  table.maximum_width = 500
295
293
  table.column_order = table_data.column_names
296
294
  table.data = table_data
297
- table.data = [{}] if table.data.empty?
295
+ table.data = [{}] if table.data.empty?
298
296
  apply_pdf_table_column_opts(table,table_data,format_opts)
299
297
 
300
298
  format_opts.each {|k,v| table.send("#{k}=", v) }
@@ -303,12 +301,12 @@ module Ruport
303
301
 
304
302
  pdf_writer.font_size = old
305
303
  end
306
-
304
+
307
305
  # This module provides tools to simplify some common drawing operations.
308
306
  # It is included by default in the PDF formatter.
309
307
  #
310
308
  module DrawingHelpers
311
-
309
+
312
310
  # Draws a horizontal line from x1 to x2
313
311
  def horizontal_line(x1,x2)
314
312
  pdf_writer.line(x1,cursor,x2,cursor)
@@ -317,45 +315,45 @@ module Ruport
317
315
 
318
316
  # Draws a horizontal line from left_boundary to right_boundary
319
317
  def horizontal_rule
320
- horizontal_line(left_boundary,right_boundary)
321
- end
322
-
318
+ horizontal_line(left_boundary,right_boundary)
319
+ end
320
+
323
321
  alias_method :hr, :horizontal_rule
324
-
322
+
325
323
  # Draws a vertical line at x from y1 to y2
326
324
  def vertical_line_at(x,y1,y2)
327
325
  pdf_writer.line(x,y1,x,y2)
328
326
  pdf_writer.stroke
329
327
  end
330
-
328
+
331
329
  # Alias for PDF::Writer#absolute_left_margin
332
330
  def left_boundary
333
331
  pdf_writer.absolute_left_margin
334
332
  end
335
-
333
+
336
334
  # Alias for PDF::Writer#absolute_right_margin
337
335
  def right_boundary
338
336
  pdf_writer.absolute_right_margin
339
337
  end
340
-
338
+
341
339
  # Alias for PDF::Writer#absolute_top_margin
342
340
  def top_boundary
343
341
  pdf_writer.absolute_top_margin
344
342
  end
345
-
343
+
346
344
  # Alias for PDF::Writer#absolute_bottom_margin
347
345
  def bottom_boundary
348
346
  pdf_writer.absolute_bottom_margin
349
347
  end
350
-
348
+
351
349
  # Alias for PDF::Writer#y
352
350
  def cursor
353
351
  pdf_writer.y
354
352
  end
355
-
353
+
356
354
  # Draws text at an absolute location, defined by
357
355
  # :y, :x1|:left, :x2|:right
358
- #
356
+ #
359
357
  # All options to add_text are also supported.
360
358
  def draw_text(text,text_opts)
361
359
  ypos = cursor
@@ -365,13 +363,13 @@ module Ruport
365
363
  :absolute_right => text_opts[:x2] || text_opts[:right]))
366
364
  move_cursor_to(ypos)
367
365
  end
368
-
366
+
369
367
  # Draws text at an absolute location, defined by
370
368
  # :y, :x1|:left
371
369
  #
372
370
  # The x position defaults to the left margin and the
373
371
  # y position defaults to the current cursor location.
374
- #
372
+ #
375
373
  # Uses PDF::Writer#add_text, so it will ignore any options not supported
376
374
  # by that method.
377
375
  def draw_text!(text,text_opts)
@@ -382,17 +380,17 @@ module Ruport
382
380
  text_opts[:font_size],
383
381
  text_opts[:angle] || 0)
384
382
  move_cursor_to(ypos)
385
- end
386
-
383
+ end
384
+
387
385
  def finalize
388
386
  render_pdf
389
387
  end
390
- end
388
+ end
391
389
 
392
390
  include DrawingHelpers
393
-
391
+
394
392
  private
395
-
393
+
396
394
  def apply_pdf_table_column_opts(table,table_data,format_opts)
397
395
  column_opts = format_opts.delete(:column_options)
398
396
 
@@ -408,7 +406,7 @@ module Ruport
408
406
  column_opts)
409
407
  columns = table_data.column_names.inject({}) { |s,c|
410
408
  s.merge( c => ::PDF::SimpleTable::Column.new(c) { |col|
411
- col.heading = create_heading(heading_opts)
409
+ col.heading = create_heading(heading_opts)
412
410
  column_opts.each { |k,v| col.send("#{k}=",v) }
413
411
  # use the specific column names now
414
412
  specific[c].each { |k,v| col.send("#{k}=",v) }
@@ -427,22 +425,22 @@ module Ruport
427
425
  s.merge(c => opts)
428
426
  end
429
427
  end
430
-
428
+
431
429
  def create_heading(heading_opts)
432
430
  heading_opts ||= {}
433
431
  ::PDF::SimpleTable::Column::Heading.new {|head|
434
432
  heading_opts.each {|k,v| head.send("#{k}=",v) }
435
433
  }
436
434
  end
437
-
435
+
438
436
  def grouping_columns
439
437
  data.data.to_a[0][1].column_names.dup.unshift(data.grouped_by)
440
438
  end
441
-
439
+
442
440
  def table_with_grouped_by_column
443
441
  Ruport::Data::Table.new(:column_names => grouping_columns)
444
442
  end
445
-
443
+
446
444
  def render_justified_or_separated_grouping
447
445
  table = table_with_grouped_by_column
448
446
  data.each do |name,group|
@@ -457,7 +455,7 @@ module Ruport
457
455
  end
458
456
  render_table table, options.to_hash.merge(:formatter => pdf_writer)
459
457
  end
460
-
458
+
461
459
  def render_offset_grouping
462
460
  table = table_with_grouped_by_column
463
461
  data.each do |name,group|
@@ -466,11 +464,11 @@ module Ruport
466
464
  end
467
465
  render_table table, options.to_hash.merge(:formatter => pdf_writer)
468
466
  end
469
-
467
+
470
468
  def image_fits_in_box?(img_width,box_width,img_height,box_height)
471
469
  !(img_width > box_width || img_height > box_height)
472
470
  end
473
-
471
+
474
472
  def fit_image_in_box(img_width,box_width,img_height,box_height)
475
473
  img_ratio = img_height.to_f / img_width.to_f
476
474
  until image_fits_in_box?(img_width,box_width,img_height,box_height)
@@ -491,7 +489,7 @@ module Ruport
491
489
  end
492
490
  return x, y
493
491
  end
494
-
492
+
495
493
  def resize_text_to_box(text,opts)
496
494
  loop do
497
495
  sz = pdf_writer.text_width(text, opts.font_size)
@@ -499,13 +497,13 @@ module Ruport
499
497
  opts.font_size -= 1
500
498
  end
501
499
  end
502
-
500
+
503
501
  def draw_box(x,y,width,height,radius,fill_color=nil,stroke_color=nil)
504
502
  pdf_writer.fill_color(fill_color || Color::RGB::White)
505
503
  pdf_writer.stroke_color(stroke_color || Color::RGB::Black)
506
504
  pdf_writer.rounded_rectangle(x, y, width, height, radius).fill_stroke
507
505
  end
508
-
506
+
509
507
  def add_text_with_bottom_border(text,x,y,width,font_size)
510
508
  pdf_writer.line( x, y - 20,
511
509
  x + width, y - 20).stroke
@@ -515,13 +513,13 @@ module Ruport
515
513
  :absolute_left => x, :absolute_right => x + width,
516
514
  :justification => :center, :font_size => font_size)
517
515
  end
518
-
516
+
519
517
  def apply_page_format_template(t)
520
518
  t = (t || {}).merge(options.page_format || {})
521
519
  options.paper_size ||= t[:size]
522
520
  options.paper_orientation ||= t[:layout]
523
521
  end
524
-
522
+
525
523
  def apply_text_format_template(t)
526
524
  t = (t || {}).merge(options.text_format || {})
527
525
  options.text_format = t unless t.empty?
@@ -531,7 +529,7 @@ module Ruport
531
529
  t = (t || {}).merge(options.table_format || {})
532
530
  options.table_format = t unless t.empty?
533
531
  end
534
-
532
+
535
533
  def apply_column_format_template(t)
536
534
  t = (t || {}).merge(options.column_format || {})
537
535
  column_opts = {}
@@ -550,7 +548,7 @@ module Ruport
550
548
  end
551
549
  end
552
550
  end
553
-
551
+
554
552
  def apply_heading_format_template(t)
555
553
  t = (t || {}).merge(options.heading_format || {})
556
554
  heading_opts = {}
@@ -582,7 +580,7 @@ module Ruport
582
580
  end
583
581
  end
584
582
  end
585
-
583
+
586
584
  def apply_grouping_format_template(t)
587
585
  t = (t || {}).merge(options.grouping_format || {})
588
586
  options.style ||= t[:style]