jyurek-prawn-layout 0.8.4

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,63 @@
1
+ # encoding: utf-8
2
+ #
3
+ # Demonstrates various table and cell features.
4
+ #
5
+ require "#{File.dirname(__FILE__)}/../example_helper.rb"
6
+
7
+ headers, body = nil, nil
8
+
9
+ dir = File.expand_path(File.dirname(__FILE__))
10
+
11
+ ruby_18 do
12
+ require "fastercsv"
13
+ headers, *body = FasterCSV.read("#{dir}/addressbook.csv")
14
+ end
15
+
16
+ ruby_19 do
17
+ require "csv"
18
+ headers, *body = CSV.read("#{dir}/addressbook.csv",
19
+ :encoding => "utf-8")
20
+ end
21
+
22
+ Prawn::Document.generate("fancy_table.pdf", :page_layout => :landscape) do
23
+
24
+ #font "#{Prawn::BASEDIR}/data/fonts/DejaVuSans.ttf"
25
+
26
+ mask(:y) { table body, :headers => headers,
27
+ :align => :center,
28
+ :border_style => :grid }
29
+
30
+ table [["This is", "A Test" ],
31
+ [ Prawn::Table::Cell.new( :text => "Of tables",
32
+ :background_color => "ffccff" ),
33
+ "Drawn Side"], ["By side", "and stuff" ]],
34
+ :position => 600,
35
+ :headers => ["Col A", "Col B"],
36
+ :border_width => 1,
37
+ :vertical_padding => 5,
38
+ :horizontal_padding => 3,
39
+ :font_size => 10,
40
+ :row_colors => :pdf_writer,
41
+ :column_widths => { 1 => 50 }
42
+
43
+ move_down 150
44
+
45
+ table [%w[1 2 3],%w[4 5 6],%w[7 8 9]],
46
+ :position => :center,
47
+ :border_width => 0,
48
+ :font_size => 40
49
+
50
+ cell [500,300],
51
+ :text => "This free flowing textbox shows how you can use Prawn's "+
52
+ "cells outside of a table with ease. Think of a 'cell' as " +
53
+ "simply a limited purpose bounding box that is meant for laying " +
54
+ "out blocks of text and optionally placing a border around it",
55
+ :width => 225, :padding => 10, :border_width => 2
56
+
57
+ font_size 24
58
+
59
+ cell [50,75],
60
+ :text => "This document demonstrates a number of Prawn's table features",
61
+ :border_style => :no_top, # :all, :no_bottom, :sides
62
+ :horizontal_padding => 5
63
+ end
@@ -0,0 +1,50 @@
1
+ # encoding: utf-8
2
+ #
3
+ # Generates a couple simple tables, including some UTF-8 text cells.
4
+ # Although this does not show all of the options available to table, the most
5
+ # common are used here. See fancy_table.rb for a more comprehensive example.
6
+ #
7
+ require "#{File.dirname(__FILE__)}/../example_helper.rb"
8
+
9
+ Prawn::Document.generate("table.pdf") do
10
+ font "#{Prawn::BASEDIR}/data/fonts/DejaVuSans.ttf"
11
+ table [["ὕαλον ϕαγεῖν", "baaar", "1" ],
12
+ ["This is","a sample", "2" ],
13
+ ["Table", "dont\ncha\nknow?", "3" ],
14
+ [ "It", "Rules", "4" ],
15
+ [ "It", "Rules", "4" ],
16
+ [ "It", "Rules", "4123231" ],
17
+ [ "It", "Rules", "22.5" ],
18
+ [ "It", "Rules", "4" ],
19
+ [ "It", "Rules", "4" ],
20
+ [ "It", "Rules", "4" ],
21
+ [ "It", "Rules", "4" ],
22
+ [ "It", "Rules", "4" ],
23
+ [ "It", "Rules\nwith an iron fist", "x" ],
24
+ [ "It", "Rules", "4" ],
25
+ [ "It", "Rules", "4" ],
26
+ [ "It", "Rules", "4" ],
27
+ [ "It", "Rules", "4" ],
28
+ [ "It", "Rules", "4" ],
29
+ [ "It", "Rules", "4" ],
30
+ [ "It", "Rules", "4" ],
31
+ [ "It", "Rules", "4" ],
32
+ [ "It", "Rules", "4" ]],
33
+
34
+ :font_size => 24,
35
+ :horizontal_padding => 10,
36
+ :vertical_padding => 3,
37
+ :border_width => 2,
38
+ :position => :center,
39
+ :headers => ["Column A","Column B","#"],
40
+ :align => {1 => :center},
41
+ :align_headers => :center
42
+
43
+ text "This should appear in the original font size, just below the table"
44
+ move_down 10
45
+
46
+ table [[ "Wide", "columns", "streeetch"],
47
+ ["are","mighty fine", "streeeeeeeech"]],
48
+ :column_widths => { 0 => 200, 1 => 200 }, :position => 5
49
+
50
+ end
@@ -0,0 +1,17 @@
1
+ # encoding: utf-8
2
+ #
3
+ # Demonstrates the many controls over alignment and positioning in Prawn
4
+ # tables.
5
+ #
6
+ require "#{File.dirname(__FILE__)}/../example_helper.rb"
7
+
8
+ Prawn::Document.generate "table_header_align.pdf" do
9
+ table [ ['01/01/2008', 'John Doe', '4.2', '125.00', '525.00'],
10
+ ['01/12/2008', 'Jane Doe', '3.2', { :text => '75.5', :align => :center }, '241.60'] ] * 20,
11
+ :position => :center,
12
+ :headers => ['Date', 'Employee', 'Hours', 'Rate', 'Total'],
13
+ :column_widths => { 0 => 75, 1 => 100, 2 => 50, 3 => 50, 4 => 50},
14
+ :border_style => :grid,
15
+ :align => { 0 => :right, 1 => :left, 2 => :right, 3 => :right, 4 => :right },
16
+ :align_headers => { 0 => :center, 2 => :left, 3 => :left, 4 => :right }
17
+ end
@@ -0,0 +1,16 @@
1
+ # encoding: utf-8
2
+ #
3
+ # Demonstrates how to set the table border color with the :border_color
4
+ # attribute.
5
+ #
6
+ require "#{File.dirname(__FILE__)}/../example_helper.rb"
7
+
8
+ Prawn::Document.generate "table_border_color.pdf" do
9
+ table [ ['01/01/2008', 'John Doe', '4.2', '125.00', '525.00'],
10
+ ['01/12/2008', 'Jane Doe', '3.2', '75.50', '241.60'] ] * 20,
11
+ :position => :center,
12
+ :headers => ['Date', 'Employee', 'Hours', 'Rate', 'Total'],
13
+ :column_widths => { 0 => 75, 1 => 100, 2 => 50, 3 => 50, 4 => 50},
14
+ :border_style => :grid,
15
+ :border_color => "ff0000"
16
+ end
@@ -0,0 +1,18 @@
1
+ # encoding: utf-8
2
+ #
3
+ # Demonstrates the use of the :col_span option when using Document#table
4
+ #
5
+ require "#{File.dirname(__FILE__)}/../example_helper.rb"
6
+
7
+ Prawn::Document.generate "table_colspan.pdf" do
8
+ data = [ ['01/01/2008', 'John Doe', '4.2', '125.00', '525.00'],
9
+ ['01/12/2008', 'Jane Doe', '3.2', '75.50', '241.60'] ] * 5
10
+
11
+ data << [{:text => 'Total', :colspan => 2, :align => :center}, '37.0', '1002.5', '3833']
12
+
13
+ table data,
14
+ :position => :center,
15
+ :headers => ['Date', 'Employee', 'Hours', 'Rate', 'Total'],
16
+ :column_widths => { 0 => 75, 1 => 100, 2 => 50, 3 => 50, 4 => 50},
17
+ :border_style => :grid
18
+ end
@@ -0,0 +1,18 @@
1
+ # encoding: utf-8
2
+ #
3
+ # Demonstrates explicitly setting the :header_color rather than inferring
4
+ # it from :row_colors in Document#table
5
+ #
6
+ require "#{File.dirname(__FILE__)}/../example_helper.rb"
7
+
8
+ Prawn::Document.generate "table_header_color.pdf" do
9
+ table [ ['01/01/2008', 'John Doe', '4.2', '125.00', '525.00'],
10
+ ['01/12/2008', 'Jane Doe', '3.2', '75.50', '241.60'] ] * 20,
11
+ :position => :center,
12
+ :headers => ['Date', 'Employee', 'Hours', 'Rate', 'Total'],
13
+ :column_widths => { 0 => 75, 1 => 100, 2 => 50, 3 => 50, 4 => 50},
14
+ :border_style => :grid,
15
+ :header_color => 'f07878',
16
+ :header_text_color => "990000",
17
+ :row_colors => ["FFCCFF","CCFFCC"]
18
+ end
@@ -0,0 +1,14 @@
1
+ # encoding: utf-8
2
+ #
3
+ # Demonstrates the :underline_header border style for Document#table.
4
+ #
5
+ require "#{File.dirname(__FILE__)}/../example_helper.rb"
6
+
7
+ Prawn::Document.generate "table_header_underline.pdf" do
8
+ table [ ['01/01/2008', 'John Doe', '4.2', '125.00', '525.00'],
9
+ ['01/12/2008', 'Jane Doe', '3.2', '75.50', '241.60'] ] * 5,
10
+ :position => :center,
11
+ :headers => ['Date', 'Employee', 'Hours', 'Rate', 'Total'],
12
+ :column_widths => { 0 => 75, 1 => 100, 2 => 50, 3 => 50, 4 => 50},
13
+ :border_style => :underline_header
14
+ end
@@ -0,0 +1,60 @@
1
+ # encoding: utf-8
2
+ #
3
+ # Generates a couple simple tables, including some UTF-8 text cells.
4
+ # Although this does not show all of the options available to table, the most
5
+ # common are used here. See fancy_table.rb for a more comprehensive example.
6
+ #
7
+ require "#{File.dirname(__FILE__)}/../example_helper.rb"
8
+
9
+ Prawn::Document.generate("table_widths.pdf") do
10
+
11
+ data = [
12
+ %w(one two three four),
13
+ %w(five six seven eight),
14
+ %w(nine ten eleven twelve),
15
+ %w(thirteen fourteen fifteen sixteen),
16
+ %w(seventeen eighteen nineteen twenty)
17
+ ]
18
+ headers = ["Column A","Column B","Column C", "Column D"]
19
+
20
+ text "A table with a specified width of the document width (within margins)"
21
+ move_down 10
22
+
23
+ table data,
24
+ :position => :center,
25
+ :headers => headers,
26
+ :width => margin_box.width
27
+
28
+
29
+ move_down 20
30
+ text "A table with a specified width of the document width (within margins) and two fixed width columns"
31
+ move_down 10
32
+
33
+ table data,
34
+ :position => :center,
35
+ :headers => headers,
36
+ :width => margin_box.width,
37
+ :column_widths => {0 => 70, 1 => 70}
38
+
39
+
40
+ move_down 20
41
+ text "A table with a specified width of 300"
42
+ move_down 10
43
+
44
+ table data,
45
+ :position => :center,
46
+ :headers => headers,
47
+ :width => 300
48
+
49
+
50
+ move_down 20
51
+ text "A table with too much data is automatically limited to the document width"
52
+ move_down 10
53
+
54
+ data << ['some text', 'A long piece of text that will make this cell too wide for the page', 'some more text', 'And more text']
55
+
56
+ table data,
57
+ :position => :center,
58
+ :headers => headers
59
+
60
+ end
@@ -0,0 +1,21 @@
1
+ require "prawn/table"
2
+ require "prawn/layout/page"
3
+ require 'prawn/layout/grid'
4
+
5
+ module Prawn
6
+
7
+ module Errors
8
+
9
+ # This error is raised when table data is malformed
10
+ #
11
+ InvalidTableData = Class.new(StandardError)
12
+
13
+ # This error is raised when an empty or nil table is rendered
14
+ #
15
+ EmptyTable = Class.new(StandardError)
16
+ end
17
+
18
+ module Layout
19
+
20
+ end
21
+ end
@@ -0,0 +1,260 @@
1
+ module Prawn
2
+ class Document
3
+
4
+ # Defines the grid system for a particular document. Takes the number of
5
+ # rows and columns and the width to use for the gutter as the
6
+ # keys :rows, :columns, :gutter, :row_gutter, :column_gutter
7
+ #
8
+ def define_grid(options = {})
9
+ @grid = Grid.new(self, options)
10
+ end
11
+
12
+ # A method that can either be used to access a particular grid on the page
13
+ # or work with the grid system directly.
14
+ #
15
+ # @pdf.grid # Get the Grid directly
16
+ # @pdf.grid([0,1]) # Get the box at [0,1]
17
+ # @pdf.grid([0,1], [1,2]) # Get a multi-box spanning from [0,1] to [1,2]
18
+ #
19
+ def grid(*args)
20
+ @boxes ||= {}
21
+ @boxes[args] ||= if args.empty?
22
+ @grid
23
+ else
24
+ g1, g2 = args
25
+ if(g1.class == Array && g2.class == Array &&
26
+ g1.length == 2 && g2.length == 2)
27
+ multi_box(single_box(*g1), single_box(*g2))
28
+ else
29
+ single_box(g1, g2)
30
+ end
31
+ end
32
+ end
33
+
34
+ # A Grid represents the entire grid system of a Page and calculates
35
+ # the column width and row height of the base box.
36
+ class Grid
37
+ attr_reader :pdf, :columns, :rows, :gutter, :row_gutter, :column_gutter
38
+ # :nodoc
39
+ def initialize(pdf, options = {})
40
+ valid_options = [:columns, :rows, :gutter, :row_gutter, :column_gutter]
41
+ Prawn.verify_options valid_options, options
42
+
43
+ @pdf = pdf
44
+ @columns = options[:columns]
45
+ @rows = options[:rows]
46
+ set_gutter(options)
47
+ end
48
+
49
+ # Calculates the base width of boxes.
50
+ def column_width
51
+ @column_width ||= subdivide(pdf.bounds.width, columns, column_gutter)
52
+ end
53
+
54
+ # Calculates the base height of boxes.
55
+ def row_height
56
+ @row_height ||= subdivide(pdf.bounds.height, rows, row_gutter)
57
+ end
58
+
59
+ # Diagnostic tool to show all of the grids. Defaults to gray.
60
+ def show_all(color = "CCCCCC")
61
+ self.rows.times do |i|
62
+ self.columns.times do |j|
63
+ pdf.grid(i,j).show(color)
64
+ end
65
+ end
66
+ end
67
+
68
+ private
69
+
70
+ def subdivide(total, num, gutter)
71
+ (total.to_f - (gutter * (num - 1).to_f)) / num.to_f
72
+ end
73
+
74
+ def set_gutter(options)
75
+ if options.has_key?(:gutter)
76
+ @gutter = options[:gutter].to_f
77
+ @row_gutter, @column_gutter = @gutter, @gutter
78
+ else
79
+ @row_gutter = options[:row_gutter].to_f
80
+ @column_gutter = options[:column_gutter].to_f
81
+ @gutter = 0
82
+ end
83
+ end
84
+ end
85
+
86
+ # A Box is a class that represents a bounded area of a page.
87
+ # A Grid object has methods that allow easy access to the coordinates of
88
+ # its corners, which can be plugged into most existing prawnmethods.
89
+ #
90
+ class Box
91
+ attr_reader :pdf
92
+
93
+ def initialize(pdf, i, j)
94
+ @pdf = pdf
95
+ @i = i
96
+ @j = j
97
+ end
98
+
99
+ # Mostly diagnostic method that outputs the name of a box as
100
+ # col_num, row_num
101
+ #
102
+ def name
103
+ "#{@i.to_s},#{@j.to_s}"
104
+ end
105
+
106
+ # :nodoc
107
+ def total_height
108
+ pdf.bounds.height.to_f
109
+ end
110
+
111
+ # Width of a box
112
+ def width
113
+ grid.column_width.to_f
114
+ end
115
+
116
+ # Height of a box
117
+ def height
118
+ grid.row_height.to_f
119
+ end
120
+
121
+ # Width of the gutter
122
+ def gutter
123
+ grid.gutter.to_f
124
+ end
125
+
126
+ # x-coordinate of left side
127
+ def left
128
+ @left ||= (width + grid.column_gutter) * @j.to_f
129
+ end
130
+
131
+ # x-coordinate of right side
132
+ def right
133
+ @right ||= left + width
134
+ end
135
+
136
+ # y-coordinate of the top
137
+ def top
138
+ @top ||= total_height - ((height + grid.row_gutter) * @i.to_f)
139
+ end
140
+
141
+ # y-coordinate of the bottom
142
+ def bottom
143
+ @bottom ||= top - height
144
+ end
145
+
146
+ # x,y coordinates of top left corner
147
+ def top_left
148
+ [left, top]
149
+ end
150
+
151
+ # x,y coordinates of top right corner
152
+ def top_right
153
+ [right, top]
154
+ end
155
+
156
+ # x,y coordinates of bottom left corner
157
+ def bottom_left
158
+ [left, bottom]
159
+ end
160
+
161
+ # x,y coordinates of bottom right corner
162
+ def bottom_right
163
+ [right, bottom]
164
+ end
165
+
166
+ # Creates a standard bounding box based on the grid box.
167
+ def bounding_box(&blk)
168
+ pdf.bounding_box(top_left, :width => width, :height => height, &blk)
169
+ end
170
+
171
+ # Diagnostic method
172
+ def show(grid_color = "CCCCCC")
173
+ self.bounding_box do
174
+ original_stroke_color = pdf.stroke_color
175
+
176
+ pdf.stroke_color = grid_color
177
+ pdf.text self.name
178
+ pdf.stroke_bounds
179
+
180
+ pdf.stroke_color = original_stroke_color
181
+ end
182
+ end
183
+
184
+ private
185
+ def grid
186
+ pdf.grid
187
+ end
188
+ end
189
+
190
+ # A MultiBox is specified by 2 Boxes and spans the areas between.
191
+ class MultiBox < Box
192
+ def initialize(pdf, b1, b2)
193
+ @pdf = pdf
194
+ @bs = [b1, b2]
195
+ end
196
+
197
+ def name
198
+ @bs.map {|b| b.name}.join(":")
199
+ end
200
+
201
+ def total_height
202
+ @bs[0].total_height
203
+ end
204
+
205
+ def width
206
+ right_box.right - left_box.left
207
+ end
208
+
209
+ def height
210
+ top_box.top - bottom_box.bottom
211
+ end
212
+
213
+ def gutter
214
+ @bs[0].gutter
215
+ end
216
+
217
+ def left
218
+ left_box.left
219
+ end
220
+
221
+ def right
222
+ right_box.right
223
+ end
224
+
225
+ def top
226
+ top_box.top
227
+ end
228
+
229
+ def bottom
230
+ bottom_box.bottom
231
+ end
232
+
233
+ private
234
+ def left_box
235
+ @left_box ||= @bs.min {|a,b| a.left <=> b.left}
236
+ end
237
+
238
+ def right_box
239
+ @right_box ||= @bs.max {|a,b| a.right <=> b.right}
240
+ end
241
+
242
+ def top_box
243
+ @top_box ||= @bs.max {|a,b| a.top <=> b.top}
244
+ end
245
+
246
+ def bottom_box
247
+ @bottom_box ||= @bs.min {|a,b| a.bottom <=> b.bottom}
248
+ end
249
+ end
250
+
251
+ private
252
+ def single_box(i, j)
253
+ Box.new(self, i, j)
254
+ end
255
+
256
+ def multi_box(b1, b2)
257
+ MultiBox.new(self, b1, b2)
258
+ end
259
+ end
260
+ end