jyurek-prawn-layout 0.8.4

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.
@@ -0,0 +1,285 @@
1
+ # encoding: utf-8
2
+
3
+ # cell.rb : Table support functions
4
+ #
5
+ # Copyright June 2008, Gregory Brown. All Rights Reserved.
6
+ #
7
+ # This is free software. Please see the LICENSE and COPYING files for details.
8
+ module Prawn
9
+
10
+ class Document
11
+ # Builds and renders a Table::Cell. A cell is essentially a
12
+ # special-purpose bounding box designed for flowing text within a bordered
13
+ # area. For available options, see Table::Cell#new.
14
+ #
15
+ # Prawn::Document.generate("cell.pdf") do
16
+ # cell [100,500],
17
+ # :width => 200,
18
+ # :text => "The rain in Spain falls mainly on the plains"
19
+ # end
20
+ #
21
+ def cell(point, options={})
22
+ Prawn::Table::Cell.new(
23
+ options.merge(:document => self, :point => point)).draw
24
+ end
25
+ end
26
+
27
+ class Table
28
+ # A cell is a special-purpose bounding box designed to flow text within a
29
+ # bordered area. This is used by Prawn's Document::Table implementation but
30
+ # can also be used standalone for drawing text boxes via Document#cell
31
+ #
32
+ class Cell
33
+
34
+ # Creates a new cell object. Generally used indirectly via Document#cell
35
+ #
36
+ # Of the available options listed below, <tt>:point</tt>, <tt>:width</tt>,
37
+ # and <tt>:text</tt> must be provided. If you are not using the
38
+ # Document#cell shortcut, the <tt>:document</tt> must also be provided.
39
+ #
40
+ # <tt>:point</tt>:: Absolute [x,y] coordinate of the top-left corner of the cell.
41
+ # <tt>:document</tt>:: The Prawn::Document object to render on.
42
+ # <tt>:text</tt>:: The text to be flowed within the cell
43
+ # <tt>:text_color</tt>:: The color of the text to be displayed
44
+ # <tt>:width</tt>:: The width in PDF points of the cell.
45
+ # <tt>:height</tt>:: The height in PDF points of the cell.
46
+ # <tt>:horizontal_padding</tt>:: The horizontal padding in PDF points
47
+ # <tt>:vertical_padding</tt>:: The vertical padding in PDF points
48
+ # <tt>:padding</tt>:: Overrides both horizontal and vertical padding
49
+ # <tt>:align</tt>:: One of <tt>:left</tt>, <tt>:right</tt>, <tt>:center</tt>
50
+ # <tt>:borders</tt>:: An array of sides which should have a border. Any of <tt>:top</tt>, <tt>:left</tt>, <tt>:right</tt>, <tt>:bottom</tt>
51
+ # <tt>:border_width</tt>:: The border line width. Defaults to 1.
52
+ # <tt>:border_style</tt>:: One of <tt>:all</tt>, <tt>:no_top</tt>, <tt>:no_bottom</tt>, <tt>:sides</tt>, <tt>:none</tt>, <tt>:bottom_only</tt>. Defaults to :all.
53
+ # <tt>:border_color</tt>:: The color of the cell border.
54
+ # <tt>:font_size</tt>:: The font size for the cell text.
55
+ # <tt>:font_style</tt>:: The font style for the cell text.
56
+ #
57
+ def initialize(options={})
58
+ @point = options[:point]
59
+ @document = options[:document]
60
+ @text = options[:text].to_s
61
+ @text_color = options[:text_color]
62
+ @width = options[:width]
63
+ @height = options[:height]
64
+ @borders = options[:borders]
65
+ @border_width = options[:border_width] || 1
66
+ @border_style = options[:border_style] || :all
67
+ @border_color = options[:border_color]
68
+ @background_color = options[:background_color]
69
+ @align = options[:align] || :left
70
+ @font_size = options[:font_size]
71
+ @font_style = options[:font_style]
72
+
73
+ @horizontal_padding = options[:horizontal_padding] || 0
74
+ @vertical_padding = options[:vertical_padding] || 0
75
+
76
+ if options[:padding]
77
+ @horizontal_padding = @vertical_padding = options[:padding]
78
+ end
79
+
80
+ end
81
+
82
+ attr_accessor :point, :border_style, :border_width, :background_color,
83
+ :document, :horizontal_padding, :vertical_padding, :align,
84
+ :borders, :text_color, :border_color, :font_size, :font_style
85
+
86
+ attr_writer :height, :width #:nodoc:
87
+
88
+ # Returns the cell's text as a string.
89
+ #
90
+ def to_s
91
+ @text
92
+ end
93
+
94
+ # The width of the text area excluding the horizonal padding
95
+ #
96
+ def text_area_width
97
+ width - 2*@horizontal_padding
98
+ end
99
+
100
+ # The width of the cell in PDF points
101
+ #
102
+ def width
103
+ @width || (@document.width_of(@text, :size => @font_size)) + 2*@horizontal_padding
104
+ end
105
+
106
+ # The height of the cell in PDF points
107
+ #
108
+ def height
109
+ @height || text_area_height + 2*@vertical_padding
110
+ end
111
+
112
+ # The height of the text area excluding the vertical padding
113
+ #
114
+ def text_area_height
115
+ text_height = 0
116
+ if @font_size
117
+ @document.font_size(@font_size) do
118
+ text_height = @document.height_of(@text, :width => text_area_width)
119
+ end
120
+ else
121
+ text_height = @document.height_of(@text, :width => text_area_width)
122
+ end
123
+ text_height
124
+ end
125
+
126
+ # Draws the cell onto the PDF document
127
+ #
128
+ def draw
129
+ margin = @border_width / 2.0
130
+
131
+ if @background_color
132
+ old_color = @document.fill_color || "000000"
133
+ @document.fill_color(@background_color)
134
+ h = borders.include?(:bottom) ?
135
+ height - ( 2 * margin ) : height + margin
136
+ @document.fill_rectangle [x, y ], width, h
137
+
138
+ @document.fill_color(old_color)
139
+ end
140
+
141
+ if @border_width > 0
142
+ @document.mask(:line_width) do
143
+ @document.line_width = @border_width
144
+
145
+ @document.mask(:stroke_color) do
146
+ @document.stroke_color @border_color if @border_color
147
+
148
+ if borders.include?(:left)
149
+ @document.stroke_line [x, y + margin],
150
+ [x, y - height - margin ]
151
+ end
152
+
153
+ if borders.include?(:right)
154
+ @document.stroke_line(
155
+ [x + width, y + margin],
156
+ [x + width, y - height - margin] )
157
+ end
158
+
159
+ if borders.include?(:top)
160
+ @document.stroke_line(
161
+ [ x, y ],
162
+ [ x + width, y ])
163
+ end
164
+
165
+ if borders.include?(:bottom)
166
+ @document.stroke_line [x, y - height ],
167
+ [x + width, y - height]
168
+ end
169
+ end
170
+
171
+ end
172
+
173
+ borders
174
+
175
+ end
176
+
177
+ @document.bounding_box( [x + @horizontal_padding,
178
+ y - @vertical_padding],
179
+ :width => text_area_width,
180
+ :height => height - @vertical_padding) do
181
+ @document.move_down((@document.font.line_gap +
182
+ @document.font.descender) / 2)
183
+
184
+ options = {:align => @align, :final_gap => false}
185
+
186
+ options[:size] = @font_size if @font_size
187
+ options[:style] = @font_style if @font_style
188
+
189
+ old_color = @document.fill_color || "000000"
190
+ @document.fill_color @text_color if @text_color
191
+ @document.text @text, options
192
+ @document.fill_color old_color
193
+ end
194
+ end
195
+
196
+ private
197
+
198
+ # x-position of the cell
199
+ def x
200
+ @point[0]
201
+ end
202
+
203
+ # y-position of the cell
204
+ def y
205
+ @point[1]
206
+ end
207
+
208
+ def borders
209
+ @borders ||= case @border_style
210
+ when :all
211
+ [:top,:left,:right,:bottom]
212
+ when :sides
213
+ [:left,:right]
214
+ when :no_top
215
+ [:left,:right,:bottom]
216
+ when :no_bottom
217
+ [:left,:right,:top]
218
+ when :bottom_only
219
+ [:bottom]
220
+ when :none
221
+ []
222
+ end
223
+ end
224
+
225
+ end
226
+
227
+ class CellBlock #:nodoc:
228
+
229
+ # Not sure if this class is something I want to expose in the public API.
230
+
231
+ def initialize(document)
232
+ @document = document
233
+ @cells = []
234
+ @width = 0
235
+ @height = 0
236
+ end
237
+
238
+ attr_reader :width, :height, :cells
239
+ attr_accessor :background_color, :text_color, :border_color
240
+
241
+ def <<(cell)
242
+ @cells << cell
243
+ @height = cell.height if cell.height > @height
244
+ @width += cell.width
245
+ self
246
+ end
247
+
248
+ def draw
249
+ y = @document.y
250
+ x = @document.bounds.left_side
251
+
252
+ @cells.each do |e|
253
+ e.point = [x - @document.bounds.absolute_left,
254
+ y - @document.bounds.absolute_bottom]
255
+ e.height = @height
256
+ e.background_color ||= @background_color
257
+ e.text_color ||= @text_color
258
+ e.border_color ||= @border_color
259
+ e.draw
260
+ x += e.width
261
+ end
262
+
263
+ @document.y = y - @height
264
+ end
265
+
266
+ def border_width
267
+ @cells[0].border_width
268
+ end
269
+
270
+ def border_style=(s)
271
+ @cells.each { |e| e.border_style = s }
272
+ end
273
+
274
+ def align=(align)
275
+ @cells.each { |e| e.align = align }
276
+ end
277
+
278
+ def border_style
279
+ @cells[0].border_style
280
+ end
281
+
282
+ end
283
+ end
284
+
285
+ end
data/spec/grid_spec.rb ADDED
@@ -0,0 +1,85 @@
1
+ # encoding: utf-8
2
+ require File.join(File.expand_path(File.dirname(__FILE__)), "spec_helper")
3
+
4
+ describe "A document's grid" do
5
+ before do
6
+ @pdf = Prawn::Document.new
7
+ end
8
+
9
+ it "should allow definition of a grid" do
10
+ @pdf.define_grid(:columns => 5, :rows => 8, :gutter => 0.1)
11
+ @pdf.grid.columns.should == 5
12
+ @pdf.grid.rows.should == 8
13
+ @pdf.grid.gutter.should == 0.1
14
+ end
15
+
16
+ describe "when a grid is defined" do
17
+ before do
18
+ @num_columns = 5
19
+ @num_rows = 8
20
+ @gutter = 10.0
21
+ @pdf.define_grid(
22
+ :columns => @num_columns,
23
+ :rows => @num_rows,
24
+ :gutter => @gutter
25
+ )
26
+ end
27
+
28
+ it "should compute the column width" do
29
+ (@pdf.grid.column_width * @num_columns.to_f +
30
+ @gutter * (@num_columns - 1).to_f).should == @pdf.bounds.width
31
+ end
32
+
33
+ it "should compute the row height" do
34
+ (@pdf.grid.row_height * @num_rows.to_f +
35
+ @gutter * (@num_rows - 1).to_f).should == @pdf.bounds.height
36
+ end
37
+
38
+ it "should give the edges of a grid box" do
39
+ grid_width = (@pdf.bounds.width.to_f -
40
+ (@gutter * (@num_columns - 1).to_f )) / @num_columns.to_f
41
+ grid_height = (@pdf.bounds.height.to_f -
42
+ (@gutter * (@num_rows - 1).to_f ))/ @num_rows.to_f
43
+
44
+ exp_tl_x = (grid_width + @gutter.to_f) * 4.0
45
+ exp_tl_y = @pdf.bounds.height.to_f - (grid_height + @gutter.to_f)
46
+
47
+ @pdf.grid(1,4).top_left.should == [exp_tl_x, exp_tl_y]
48
+ @pdf.grid(1,4).top_right.should == [exp_tl_x + grid_width, exp_tl_y]
49
+ @pdf.grid(1,4).bottom_left.should == [exp_tl_x, exp_tl_y - grid_height]
50
+ @pdf.grid(1,4).bottom_right.should == [exp_tl_x + grid_width, exp_tl_y - grid_height]
51
+ end
52
+
53
+ it "should give the edges of a multiple grid boxes" do
54
+ # Hand verified. Cheating a bit. Don't tell.
55
+ @pdf.grid([1,3], [2,5]).top_left.should == [330.0, 628.75]
56
+ @pdf.grid([1,3], [2,5]).top_right.should == [650.0, 628.75]
57
+ @pdf.grid([1,3], [2,5]).bottom_left.should == [330.0, 456.25]
58
+ @pdf.grid([1,3], [2,5]).bottom_right.should == [650.0, 456.25]
59
+ end
60
+
61
+ it "should draw outlines without changing global default colors to grid color" do
62
+ @pdf.grid.show_all('cccccc')
63
+
64
+ colors = PDF::Inspector::Graphics::Color.analyze(@pdf.render)
65
+ colors.fill_color.should.not == [0.8,0.8,0.8]
66
+ colors.stroke_color.should.not == [0.8,0.8,0.8]
67
+
68
+ # Hardcoded default color as I haven't been able to come up with a stable converter
69
+ # between fill_color without lots code.
70
+ colors.fill_color.should == [0.0,0.0,0.0]
71
+ colors.stroke_color.should == [0.0,0.0,0.0]
72
+ end
73
+
74
+ it "should draw outlines without curent color settings" do
75
+ @pdf.fill_color "ccff00"
76
+ @pdf.stroke_color "ffcc00"
77
+
78
+ @pdf.grid.show_all
79
+
80
+ colors = PDF::Inspector::Graphics::Color.analyze(@pdf.render)
81
+ colors.fill_color.should == [0.8,1.0,0.0]
82
+ colors.stroke_color.should == [1.0,0.8,0.0]
83
+ end
84
+ end
85
+ end
@@ -0,0 +1,26 @@
1
+ # encoding: utf-8
2
+
3
+ puts "Prawn specs: Running on Ruby Version: #{RUBY_VERSION}"
4
+
5
+ require "rubygems"
6
+ require "test/spec"
7
+ require "mocha"
8
+ $LOAD_PATH.unshift File.join(File.dirname(__FILE__), '..', 'lib')
9
+
10
+ $LOAD_PATH << File.join(File.dirname(__FILE__), %w[.. vendor prawn-core lib])
11
+ require "prawn/core"
12
+ require "prawn/layout"
13
+ $LOAD_PATH << File.join(Prawn::BASEDIR, 'vendor','pdf-inspector','lib')
14
+
15
+ Prawn.debug = true
16
+
17
+ gem 'pdf-reader', ">=0.7.3"
18
+ require "pdf/reader"
19
+ require "pdf/inspector"
20
+
21
+ def create_pdf(klass=Prawn::Document)
22
+ @pdf = klass.new(:left_margin => 0,
23
+ :right_margin => 0,
24
+ :top_margin => 0,
25
+ :bottom_margin => 0)
26
+ end
@@ -0,0 +1,337 @@
1
+ # encoding: utf-8
2
+
3
+ require File.join(File.expand_path(File.dirname(__FILE__)), "spec_helper")
4
+
5
+ describe "A table's width" do
6
+ it "should equal sum(column_widths)" do
7
+ pdf = Prawn::Document.new
8
+ table = Prawn::Table.new( [%w[ a b c ], %w[d e f]], pdf,
9
+ :column_widths => { 0 => 50, 1 => 100, 2 => 150 })
10
+
11
+ table.width.should == 300
12
+ end
13
+ it "should calculate unspecified column widths even " +
14
+ "with colspan cells declared" do
15
+ pdf = Prawn::Document.new
16
+ hpad, fs = 3, 5
17
+ columns = 3
18
+
19
+ data = [ [ { :text => 'foo', :colspan => 2 }, "foobar" ],
20
+ [ "foo", "foo", "foo" ] ]
21
+ table = Prawn::Table.new( data, pdf,
22
+ :horizontal_padding => hpad,
23
+ :font_size => fs )
24
+
25
+ col0_width = pdf.width_of("foo", :size => fs) # cell 1, 0
26
+ col1_width = pdf.width_of("foo", :size => fs) # cell 1, 1
27
+ col2_width = pdf.width_of("foobar", :size => fs) # cell 0, 1 (at col 2)
28
+
29
+ table.width.should == col0_width.ceil + col1_width.ceil +
30
+ col2_width.ceil + 2*columns*hpad
31
+ end
32
+
33
+ it "should calculate unspecified column widths as "+
34
+ "(max(string_width).ceil + 2*horizontal_padding)" do
35
+ pdf = Prawn::Document.new
36
+ hpad, fs = 3, 12
37
+ columns = 2
38
+ table = Prawn::Table.new( [%w[ foo b ], %w[d foobar]], pdf,
39
+ :horizontal_padding => hpad, :font_size => fs)
40
+
41
+ col0_width = pdf.width_of("foo", :size => fs)
42
+ col1_width = pdf.width_of("foobar", :size => fs)
43
+
44
+ table.width.should == col0_width.ceil + col1_width.ceil + 2*columns*hpad
45
+ end
46
+
47
+ it "should allow mixing autocalculated and preset"+
48
+ "column widths within a single table" do
49
+
50
+ pdf = Prawn::Document.new
51
+ hpad, fs = 10, 6
52
+ stretchy_columns = 2
53
+
54
+ col0_width = 50
55
+ col1_width = pdf.width_of("foo", :size => fs)
56
+ col2_width = pdf.width_of("foobar", :size => fs)
57
+ col3_width = 150
58
+
59
+ table = Prawn::Table.new( [%w[snake foo b apple],
60
+ %w[kitten d foobar banana]], pdf,
61
+ :horizontal_padding => hpad, :font_size => fs,
62
+ :column_widths => { 0 => col0_width, 3 => col3_width } )
63
+
64
+ table.width.should == col1_width.ceil + col2_width.ceil +
65
+ 2*stretchy_columns*hpad +
66
+ col0_width.ceil + col3_width.ceil
67
+
68
+ end
69
+
70
+ it "should not exceed the maximum width of the margin_box" do
71
+
72
+ pdf = Prawn::Document.new
73
+ expected_width = pdf.margin_box.width
74
+
75
+ data = [
76
+ ['This is a column with a lot of text that should comfortably exceed '+
77
+ 'the width of a normal document margin_box width', 'Some more text',
78
+ 'and then some more', 'Just a bit more to be extra sure']
79
+ ]
80
+
81
+ table = Prawn::Table.new(data, pdf)
82
+
83
+ table.width.should == expected_width
84
+
85
+ end
86
+
87
+ it "should not exceed the maximum width of the margin_box even with manual widths specified" do
88
+
89
+ pdf = Prawn::Document.new
90
+ expected_width = pdf.margin_box.width
91
+
92
+ data = [
93
+ ['This is a column with a lot of text that should comfortably exceed '+
94
+ 'the width of a normal document margin_box width', 'Some more text',
95
+ 'and then some more', 'Just a bit more to be extra sure']
96
+ ]
97
+
98
+
99
+ table = Prawn::Table.new(data, pdf, :column_widths => { 1 => 100 })
100
+
101
+ table.width.should == expected_width
102
+
103
+ end
104
+
105
+ it "should be the width of the :width parameter" do
106
+
107
+ pdf = Prawn::Document.new
108
+ expected_width = 300
109
+
110
+ table = Prawn::Table.new( [%w[snake foo b apple],
111
+ %w[kitten d foobar banana]], pdf,
112
+ :width => expected_width
113
+ )
114
+
115
+ table.width.should == expected_width
116
+
117
+ end
118
+
119
+ it "should not exceed the :width option" do
120
+
121
+ pdf = Prawn::Document.new
122
+ expected_width = 400
123
+
124
+ data = [
125
+ ['This is a column with a lot of text that should comfortably exceed '+
126
+ 'the width of a normal document margin_box width', 'Some more text',
127
+ 'and then some more', 'Just a bit more to be extra sure']
128
+ ]
129
+
130
+ table = Prawn::Table.new(data, pdf, :width => expected_width)
131
+
132
+ table.width.should == expected_width
133
+
134
+ end
135
+
136
+ it "should not exceed the :width option even with manual widths specified" do
137
+
138
+ pdf = Prawn::Document.new
139
+ expected_width = 400
140
+
141
+ data = [
142
+ ['This is a column with a lot of text that should comfortably exceed '+
143
+ 'the width of a normal document margin_box width', 'Some more text',
144
+ 'and then some more', 'Just a bit more to be extra sure']
145
+ ]
146
+
147
+ table = Prawn::Table.new(data, pdf, :column_widths => { 1 => 100 }, :width => expected_width)
148
+
149
+ table.width.should == expected_width
150
+
151
+ end
152
+
153
+ end
154
+
155
+ describe "A table's height" do
156
+
157
+ before :each do
158
+ data = [["foo"],["bar"],["baaaz"]]
159
+ pdf = Prawn::Document.new
160
+ @num_rows = data.length
161
+
162
+ @vpad = 4
163
+ origin = pdf.y
164
+ pdf.table data, :vertical_padding => @vpad
165
+
166
+ @table_height = origin - pdf.y
167
+
168
+ @font_height = pdf.font.height
169
+ end
170
+
171
+ it "should have a height of n rows" do
172
+ @table_height.should.be.close(
173
+ @num_rows*@font_height + 2*@vpad*@num_rows, 0.001 )
174
+ end
175
+
176
+ end
177
+
178
+ describe "A table's content" do
179
+
180
+ it "should not cause an error if rendering the very first row causes a page break" do
181
+ Prawn::Document.new( :page_layout => :portrait ) do
182
+ arr = Array(1..5).collect{|i| ["cell #{i}"] }
183
+
184
+ move_down( y - (bounds.absolute_bottom + 3) )
185
+
186
+ lambda {
187
+ table( arr,
188
+ :font_size => 9,
189
+ :horizontal_padding => 3,
190
+ :vertical_padding => 3,
191
+ :border_width => 0.05,
192
+ :border_style => :none,
193
+ :row_colors => %w{ffffff eeeeee},
194
+ :column_widths => {0 =>110},
195
+ :position => :left,
196
+ :headers => ["exploding header"],
197
+ :align => :left,
198
+ :align_headers => :center)
199
+ }.should.not.raise
200
+ end
201
+ end
202
+
203
+ it "should output content cell by cell, row by row" do
204
+ data = [["foo","bar"],["baz","bang"]]
205
+ @pdf = Prawn::Document.new
206
+ @pdf.table(data)
207
+ output = PDF::Inspector::Text.analyze(@pdf.render)
208
+ output.strings.should == data.flatten
209
+ end
210
+
211
+ it "should add headers to output when specified" do
212
+ data = [["foo","bar"],["baz","bang"]]
213
+ headers = %w[a b]
214
+ @pdf = Prawn::Document.new
215
+ @pdf.table(data, :headers => headers)
216
+ output = PDF::Inspector::Text.analyze(@pdf.render)
217
+ output.strings.should == headers + data.flatten
218
+ end
219
+
220
+ it "should repeat headers across pages" do
221
+ data = [["foo","bar"]]*30
222
+ headers = ["baz","foobar"]
223
+ @pdf = Prawn::Document.new
224
+ @pdf.table(data, :headers => headers)
225
+ output = PDF::Inspector::Text.analyze(@pdf.render)
226
+ output.strings.should == headers + data.flatten[0..-3] + headers +
227
+ data.flatten[-2..-1]
228
+ end
229
+
230
+ it "should allow empty fields" do
231
+ lambda {
232
+ data = [["foo","bar"],["baz",""]]
233
+ @pdf = Prawn::Document.new
234
+ @pdf.table(data)
235
+ }.should.not.raise
236
+ end
237
+
238
+ it "should paginate for large tables" do
239
+ # 30 rows fit on the table with default setting, 31 exceed.
240
+ data = [["foo"]] * 31
241
+ pdf = Prawn::Document.new
242
+
243
+ pdf.table data
244
+ pdf.page_count.should == 2
245
+
246
+ pdf.table data
247
+ pdf.page_count.should == 3
248
+ end
249
+
250
+ it "should accurately count columns from data" do
251
+ # First data row may contain colspan which would hide true column count
252
+ data = [["Name:",{:text => "Some very long name", :colspan => 5}]]
253
+ pdf = Prawn::Document.new
254
+ table = Prawn::Table.new data, pdf
255
+ table.column_widths.length.should == 6
256
+ end
257
+
258
+ it "should allow array syntax for :row_colors" do
259
+ data = [["foo"], ["bar"], ['baz']]
260
+ pdf = Prawn::Document.new
261
+
262
+ # fill_color() is used to retrieve fill color; ignore it
263
+ pdf.stubs(:fill_color)
264
+
265
+ # Verify that fill_color is called in proper sequence for row colors.
266
+ seq = sequence('row_colors')
267
+ %w[cccccc ffffff cccccc].each do |color|
268
+ pdf.expects(:fill_color).with(color).in_sequence(seq)
269
+ end
270
+
271
+ pdf.table(data, :row_colors => ['cccccc', 'ffffff'])
272
+ end
273
+
274
+ it "should allow hash syntax for :row_colors" do
275
+ data = [["foo"], ["bar"], ['baz']]
276
+ pdf = Prawn::Document.new
277
+
278
+ # fill_color() is used to retrieve fill color; ignore it
279
+ pdf.stubs(:fill_color)
280
+
281
+ # Verify that fill_color is called in proper sequence for row colors.
282
+ seq = sequence('row_colors')
283
+ %w[cccccc dddddd eeeeee].each do |color|
284
+ pdf.expects(:fill_color).with(color).in_sequence(seq)
285
+ end
286
+
287
+ pdf.table(data, :row_colors => {0 => 'cccccc', 1 => 'dddddd',
288
+ 2 => 'eeeeee'})
289
+ end
290
+ end
291
+
292
+ describe "An invalid table" do
293
+
294
+ before(:each) do
295
+ @pdf = Prawn::Document.new
296
+ @bad_data = ["Single Nested Array"]
297
+ end
298
+
299
+ it "should raise error when invalid table data is given" do
300
+ assert_raises(Prawn::Errors::InvalidTableData) do
301
+ @pdf.table(@bad_data)
302
+ end
303
+ end
304
+
305
+ it "should raise an EmptyTableError with empty table data" do
306
+ lambda {
307
+ data = []
308
+ @pdf = Prawn::Document.new
309
+ @pdf.table(data)
310
+ }.should.raise( Prawn::Errors::EmptyTable )
311
+ end
312
+
313
+ it "should raise an EmptyTableError with nil table data" do
314
+ lambda {
315
+ data = nil
316
+ @pdf = Prawn::Document.new
317
+ @pdf.table(data)
318
+ }.should.raise( Prawn::Errors::EmptyTable )
319
+ end
320
+
321
+ end
322
+
323
+ describe "A table, in a column box" do
324
+
325
+ it "should flow to the next column rather than always the next page" do
326
+ pdf = Prawn::Document.new do
327
+ column_box [0, cursor], :width => bounds.width, :columns => 2 do
328
+ # 35 rows fit on two columns but not one
329
+ table [["data"]] * 35
330
+ end
331
+ end
332
+
333
+ pdf.page_count.should == 1
334
+ end
335
+
336
+ end
337
+