prawn-table-continued 1.0.0.rc1
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.
- checksums.yaml +7 -0
- data/COPYING +2 -0
- data/GPLv2 +340 -0
- data/GPLv3 +674 -0
- data/Gemfile +3 -0
- data/LICENSE +56 -0
- data/lib/prawn/table/cell/image.rb +69 -0
- data/lib/prawn/table/cell/in_table.rb +33 -0
- data/lib/prawn/table/cell/span_dummy.rb +93 -0
- data/lib/prawn/table/cell/subtable.rb +66 -0
- data/lib/prawn/table/cell/text.rb +155 -0
- data/lib/prawn/table/cell.rb +787 -0
- data/lib/prawn/table/cells.rb +261 -0
- data/lib/prawn/table/column_width_calculator.rb +182 -0
- data/lib/prawn/table/version.rb +5 -0
- data/lib/prawn/table.rb +711 -0
- data/manual/contents.rb +13 -0
- data/manual/example_helper.rb +8 -0
- data/manual/images/prawn.png +0 -0
- data/manual/images/stef.jpg +0 -0
- data/manual/table/basic_block.rb +53 -0
- data/manual/table/before_rendering_page.rb +26 -0
- data/manual/table/cell_border_lines.rb +24 -0
- data/manual/table/cell_borders_and_bg.rb +31 -0
- data/manual/table/cell_dimensions.rb +36 -0
- data/manual/table/cell_text.rb +38 -0
- data/manual/table/column_widths.rb +30 -0
- data/manual/table/content_and_subtables.rb +39 -0
- data/manual/table/creation.rb +27 -0
- data/manual/table/filtering.rb +36 -0
- data/manual/table/flow_and_header.rb +17 -0
- data/manual/table/image_cells.rb +33 -0
- data/manual/table/position.rb +29 -0
- data/manual/table/row_colors.rb +20 -0
- data/manual/table/span.rb +30 -0
- data/manual/table/style.rb +33 -0
- data/manual/table/table.rb +52 -0
- data/manual/table/width.rb +27 -0
- data/prawn-table.gemspec +36 -0
- data/spec/cell_spec.rb +652 -0
- data/spec/extensions/encoding_helpers.rb +11 -0
- data/spec/extensions/file_fixture_helper.rb +15 -0
- data/spec/fixtures/files/prawn.png +0 -0
- data/spec/spec_helper.rb +50 -0
- data/spec/table/span_dummy_spec.rb +26 -0
- data/spec/table_spec.rb +1626 -0
- metadata +234 -0
data/LICENSE
ADDED
@@ -0,0 +1,56 @@
|
|
1
|
+
Prawn is copyrighted free software produced by Gregory Brown along with
|
2
|
+
community contributions. See git log for authorship information.
|
3
|
+
|
4
|
+
Licensing terms follow:
|
5
|
+
|
6
|
+
You can redistribute Prawn and/or modify it under either the terms of the GPLv2
|
7
|
+
or GPLv3 (see GPLv2 and GPLv3 files), or the conditions below:
|
8
|
+
|
9
|
+
1. You may make and give away verbatim copies of the source form of the
|
10
|
+
software without restriction, provided that you duplicate all of the
|
11
|
+
original copyright notices and associated disclaimers.
|
12
|
+
|
13
|
+
2. You may modify your copy of the software in any way, provided that
|
14
|
+
you do at least ONE of the following:
|
15
|
+
|
16
|
+
a) place your modifications in the Public Domain or otherwise
|
17
|
+
make them Freely Available, such as by posting said
|
18
|
+
modifications to Usenet or an equivalent medium, or by allowing
|
19
|
+
the author to include your modifications in the software.
|
20
|
+
|
21
|
+
b) use the modified software only within your corporation or
|
22
|
+
organization.
|
23
|
+
|
24
|
+
c) rename any non-standard executables so the names do not conflict
|
25
|
+
with standard executables, which must also be provided.
|
26
|
+
|
27
|
+
d) make other distribution arrangements with the author.
|
28
|
+
|
29
|
+
3. You may distribute the software in object code or executable
|
30
|
+
form, provided that you do at least ONE of the following:
|
31
|
+
|
32
|
+
a) distribute the executables and library files of the software,
|
33
|
+
together with instructions (in the manual page or equivalent)
|
34
|
+
on where to get the original distribution.
|
35
|
+
|
36
|
+
b) accompany the distribution with the machine-readable source of
|
37
|
+
the software.
|
38
|
+
|
39
|
+
c) give non-standard executables non-standard names, with
|
40
|
+
instructions on where to get the original software distribution.
|
41
|
+
|
42
|
+
d) make other distribution arrangements with the author.
|
43
|
+
|
44
|
+
4. You may modify and include the part of the software into any other
|
45
|
+
software (possibly commercial).
|
46
|
+
|
47
|
+
5. The scripts and library files supplied as input to or produced as
|
48
|
+
output from the software do not automatically fall under the
|
49
|
+
copyright of the software, but belong to whomever generated them,
|
50
|
+
and may be sold commercially, and may be aggregated with this
|
51
|
+
software.
|
52
|
+
|
53
|
+
6. THIS SOFTWARE IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR
|
54
|
+
IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
|
55
|
+
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
56
|
+
PURPOSE.
|
@@ -0,0 +1,69 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
|
3
|
+
# image.rb: Table image cells.
|
4
|
+
#
|
5
|
+
# Copyright September 2010, Brad Ediger. All Rights Reserved.
|
6
|
+
#
|
7
|
+
# This is free software. Please see the LICENSE and COPYING files for details.
|
8
|
+
module Prawn
|
9
|
+
class Table
|
10
|
+
class Cell
|
11
|
+
|
12
|
+
# @private
|
13
|
+
class Image < Cell
|
14
|
+
|
15
|
+
def initialize(pdf, point, options={})
|
16
|
+
@image_options = {}
|
17
|
+
super
|
18
|
+
|
19
|
+
@pdf_object, @image_info = @pdf.build_image_object(@file)
|
20
|
+
@natural_width, @natural_height = @image_info.calc_image_dimensions(
|
21
|
+
@image_options)
|
22
|
+
end
|
23
|
+
|
24
|
+
def image=(file)
|
25
|
+
@file = file
|
26
|
+
end
|
27
|
+
|
28
|
+
def scale=(s)
|
29
|
+
@image_options[:scale] = s
|
30
|
+
end
|
31
|
+
|
32
|
+
def fit=(f)
|
33
|
+
@image_options[:fit] = f
|
34
|
+
end
|
35
|
+
|
36
|
+
def image_height=(h)
|
37
|
+
@image_options[:height] = h
|
38
|
+
end
|
39
|
+
|
40
|
+
def image_width=(w)
|
41
|
+
@image_options[:width] = w
|
42
|
+
end
|
43
|
+
|
44
|
+
def position=(p)
|
45
|
+
@image_options[:position] = p
|
46
|
+
end
|
47
|
+
|
48
|
+
def vposition=(vp)
|
49
|
+
@image_options[:vposition] = vp
|
50
|
+
end
|
51
|
+
|
52
|
+
def natural_content_width
|
53
|
+
@natural_width
|
54
|
+
end
|
55
|
+
|
56
|
+
def natural_content_height
|
57
|
+
@natural_height
|
58
|
+
end
|
59
|
+
|
60
|
+
# Draw the image on the page.
|
61
|
+
#
|
62
|
+
def draw_content
|
63
|
+
@pdf.embed_image(@pdf_object, @image_info, @image_options)
|
64
|
+
end
|
65
|
+
|
66
|
+
end
|
67
|
+
end
|
68
|
+
end
|
69
|
+
end
|
@@ -0,0 +1,33 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
|
3
|
+
# Accessors for using a Cell inside a Table.
|
4
|
+
#
|
5
|
+
# Contributed by Brad Ediger.
|
6
|
+
#
|
7
|
+
# This is free software. Please see the LICENSE and COPYING files for details.
|
8
|
+
|
9
|
+
module Prawn
|
10
|
+
class Table
|
11
|
+
|
12
|
+
class Cell
|
13
|
+
|
14
|
+
# This module extends Cell objects when they are used in a table (as
|
15
|
+
# opposed to standalone). Its properties apply to cells-in-tables but not
|
16
|
+
# cells themselves.
|
17
|
+
#
|
18
|
+
# @private
|
19
|
+
module InTable
|
20
|
+
|
21
|
+
# Row number (0-based).
|
22
|
+
#
|
23
|
+
attr_accessor :row
|
24
|
+
|
25
|
+
# Column number (0-based).
|
26
|
+
#
|
27
|
+
attr_accessor :column
|
28
|
+
|
29
|
+
end
|
30
|
+
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
@@ -0,0 +1,93 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
|
3
|
+
# span_dummy.rb: Placeholder for non-master spanned cells.
|
4
|
+
#
|
5
|
+
# Copyright December 2011, Brad Ediger. All Rights Reserved.
|
6
|
+
#
|
7
|
+
# This is free software. Please see the LICENSE and COPYING files for details.
|
8
|
+
module Prawn
|
9
|
+
class Table
|
10
|
+
class Cell
|
11
|
+
|
12
|
+
# A Cell object used to represent all but the topmost cell in a span
|
13
|
+
# group.
|
14
|
+
#
|
15
|
+
# @private
|
16
|
+
class SpanDummy < Cell
|
17
|
+
def initialize(pdf, master_cell)
|
18
|
+
super(pdf, [0, pdf.cursor])
|
19
|
+
@master_cell = master_cell
|
20
|
+
@padding = [0, 0, 0, 0]
|
21
|
+
end
|
22
|
+
|
23
|
+
# By default, a span dummy will never increase the height demand.
|
24
|
+
#
|
25
|
+
def natural_content_height
|
26
|
+
0
|
27
|
+
end
|
28
|
+
|
29
|
+
# By default, a span dummy will never increase the width demand.
|
30
|
+
#
|
31
|
+
def natural_content_width
|
32
|
+
0
|
33
|
+
end
|
34
|
+
|
35
|
+
def avg_spanned_min_width
|
36
|
+
@master_cell.avg_spanned_min_width
|
37
|
+
end
|
38
|
+
|
39
|
+
# Dummy cells have nothing to draw.
|
40
|
+
#
|
41
|
+
def draw_borders(pt)
|
42
|
+
end
|
43
|
+
|
44
|
+
# Dummy cells have nothing to draw.
|
45
|
+
#
|
46
|
+
def draw_bounded_content(pt)
|
47
|
+
end
|
48
|
+
|
49
|
+
def padding_right=(val)
|
50
|
+
@master_cell.padding_right = val if rightmost?
|
51
|
+
end
|
52
|
+
|
53
|
+
def padding_bottom=(val)
|
54
|
+
@master_cell.padding_bottom = val if bottommost?
|
55
|
+
end
|
56
|
+
|
57
|
+
def border_right_color=(val)
|
58
|
+
@master_cell.border_right_color = val if rightmost?
|
59
|
+
end
|
60
|
+
|
61
|
+
def border_bottom_color=(val)
|
62
|
+
@master_cell.border_bottom_color = val if bottommost?
|
63
|
+
end
|
64
|
+
|
65
|
+
def border_right_width=(val)
|
66
|
+
@master_cell.border_right_width = val if rightmost?
|
67
|
+
end
|
68
|
+
|
69
|
+
def border_bottom_width=(val)
|
70
|
+
@master_cell.border_bottom_width = val if bottommost?
|
71
|
+
end
|
72
|
+
|
73
|
+
def background_color
|
74
|
+
@master_cell.background_color
|
75
|
+
end
|
76
|
+
|
77
|
+
private
|
78
|
+
|
79
|
+
# Are we on the right border of the span?
|
80
|
+
#
|
81
|
+
def rightmost?
|
82
|
+
@column == @master_cell.column + @master_cell.colspan - 1
|
83
|
+
end
|
84
|
+
|
85
|
+
# Are we on the bottom border of the span?
|
86
|
+
#
|
87
|
+
def bottommost?
|
88
|
+
@row == @master_cell.row + @master_cell.rowspan - 1
|
89
|
+
end
|
90
|
+
end
|
91
|
+
end
|
92
|
+
end
|
93
|
+
end
|
@@ -0,0 +1,66 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
|
3
|
+
# subtable.rb: Yo dawg.
|
4
|
+
#
|
5
|
+
# Copyright January 2010, Brad Ediger. All Rights Reserved.
|
6
|
+
#
|
7
|
+
# This is free software. Please see the LICENSE and COPYING files for details.
|
8
|
+
module Prawn
|
9
|
+
class Table
|
10
|
+
class Cell
|
11
|
+
|
12
|
+
# A Cell that contains another table.
|
13
|
+
#
|
14
|
+
# @private
|
15
|
+
class Subtable < Cell
|
16
|
+
|
17
|
+
attr_reader :subtable
|
18
|
+
|
19
|
+
def initialize(pdf, point, options={})
|
20
|
+
options[:padding] ||= [0, 0, 0, 0]
|
21
|
+
|
22
|
+
super
|
23
|
+
|
24
|
+
@subtable = options[:content]
|
25
|
+
end
|
26
|
+
|
27
|
+
# Sets the text color of the entire subtable.
|
28
|
+
#
|
29
|
+
def text_color=(color)
|
30
|
+
@subtable.cells.text_color = color
|
31
|
+
end
|
32
|
+
|
33
|
+
# Proxied to subtable.
|
34
|
+
#
|
35
|
+
def natural_content_width
|
36
|
+
@subtable.cells.width
|
37
|
+
end
|
38
|
+
|
39
|
+
# Proxied to subtable.
|
40
|
+
#
|
41
|
+
def min_width
|
42
|
+
@subtable.cells.min_width
|
43
|
+
end
|
44
|
+
|
45
|
+
# Proxied to subtable.
|
46
|
+
#
|
47
|
+
def max_width
|
48
|
+
@subtable.cells.max_width
|
49
|
+
end
|
50
|
+
|
51
|
+
# Proxied to subtable.
|
52
|
+
#
|
53
|
+
def natural_content_height
|
54
|
+
@subtable.cells.height
|
55
|
+
end
|
56
|
+
|
57
|
+
# Draws the subtable.
|
58
|
+
#
|
59
|
+
def draw_content
|
60
|
+
@subtable.draw
|
61
|
+
end
|
62
|
+
|
63
|
+
end
|
64
|
+
end
|
65
|
+
end
|
66
|
+
end
|
@@ -0,0 +1,155 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
|
3
|
+
# text.rb: Text table cells.
|
4
|
+
#
|
5
|
+
# Copyright December 2009, Gregory Brown and Brad Ediger. All Rights Reserved.
|
6
|
+
#
|
7
|
+
# This is free software. Please see the LICENSE and COPYING files for details.
|
8
|
+
module Prawn
|
9
|
+
class Table
|
10
|
+
class Cell
|
11
|
+
|
12
|
+
# A Cell that contains text. Has some limited options to set font family,
|
13
|
+
# size, and style.
|
14
|
+
#
|
15
|
+
# @private
|
16
|
+
class Text < Cell
|
17
|
+
|
18
|
+
TextOptions = [:inline_format, :kerning, :size, :align, :valign,
|
19
|
+
:rotate, :rotate_around, :leading, :single_line, :skip_encoding,
|
20
|
+
:overflow, :min_font_size]
|
21
|
+
|
22
|
+
TextOptions.each do |option|
|
23
|
+
define_method("#{option}=") { |v| @text_options[option] = v }
|
24
|
+
define_method(option) { @text_options[option] }
|
25
|
+
end
|
26
|
+
|
27
|
+
attr_writer :font, :text_color
|
28
|
+
|
29
|
+
def initialize(pdf, point, options={})
|
30
|
+
@text_options = {}
|
31
|
+
super
|
32
|
+
end
|
33
|
+
|
34
|
+
# Returns the font that will be used to draw this cell.
|
35
|
+
#
|
36
|
+
def font
|
37
|
+
with_font { @pdf.font }
|
38
|
+
end
|
39
|
+
|
40
|
+
# Sets the style of the font in use. Equivalent to the Text::Box
|
41
|
+
# +style+ option, but we already have a style method.
|
42
|
+
#
|
43
|
+
def font_style=(style)
|
44
|
+
@text_options[:style] = style
|
45
|
+
end
|
46
|
+
|
47
|
+
# Returns the width of this text with no wrapping. This will be far off
|
48
|
+
# from the final width if the text is long.
|
49
|
+
#
|
50
|
+
def natural_content_width
|
51
|
+
@natural_content_width ||= [styled_width_of(@content), @pdf.bounds.width].min
|
52
|
+
end
|
53
|
+
|
54
|
+
# Returns the natural height of this block of text, wrapped to the
|
55
|
+
# preset width.
|
56
|
+
#
|
57
|
+
def natural_content_height
|
58
|
+
with_font do
|
59
|
+
b = text_box(:width => spanned_content_width + FPTolerance)
|
60
|
+
b.render(:dry_run => true)
|
61
|
+
b.height + b.line_gap
|
62
|
+
end
|
63
|
+
end
|
64
|
+
|
65
|
+
# Draws the text content into its bounding box.
|
66
|
+
#
|
67
|
+
def draw_content
|
68
|
+
with_font do
|
69
|
+
@pdf.move_down((@pdf.font.line_gap + @pdf.font.descender)/2)
|
70
|
+
with_text_color do
|
71
|
+
text_box(:width => spanned_content_width + FPTolerance,
|
72
|
+
:height => spanned_content_height + FPTolerance,
|
73
|
+
:at => [0, @pdf.cursor]).render
|
74
|
+
end
|
75
|
+
end
|
76
|
+
end
|
77
|
+
|
78
|
+
def set_width_constraints
|
79
|
+
# Sets a reasonable minimum width. If the cell has any content, make
|
80
|
+
# sure we have enough width to be at least one character wide. This is
|
81
|
+
# a bit of a hack, but it should work well enough.
|
82
|
+
unless defined?(@min_width) && @min_width
|
83
|
+
min_content_width = [natural_content_width, styled_width_of_single_character].min
|
84
|
+
@min_width = padding_left + padding_right + min_content_width
|
85
|
+
super
|
86
|
+
end
|
87
|
+
end
|
88
|
+
|
89
|
+
protected
|
90
|
+
|
91
|
+
def with_font
|
92
|
+
@pdf.save_font do
|
93
|
+
options = {}
|
94
|
+
options[:style] = @text_options[:style] if @text_options[:style]
|
95
|
+
options[:style] ||= @pdf.font.options[:style] if @pdf.font.options[:style]
|
96
|
+
|
97
|
+
@pdf.font(defined?(@font) && @font || @pdf.font.family, options)
|
98
|
+
|
99
|
+
yield
|
100
|
+
end
|
101
|
+
end
|
102
|
+
|
103
|
+
def with_text_color
|
104
|
+
if defined?(@text_color) && @text_color
|
105
|
+
begin
|
106
|
+
old_color = @pdf.fill_color || '000000'
|
107
|
+
@pdf.fill_color(@text_color)
|
108
|
+
yield
|
109
|
+
ensure
|
110
|
+
@pdf.fill_color(old_color)
|
111
|
+
end
|
112
|
+
else
|
113
|
+
yield
|
114
|
+
end
|
115
|
+
end
|
116
|
+
|
117
|
+
def text_box(extra_options={})
|
118
|
+
if p = @text_options[:inline_format]
|
119
|
+
p = [] unless p.is_a?(Array)
|
120
|
+
options = @text_options.dup
|
121
|
+
options.delete(:inline_format)
|
122
|
+
options.merge!(extra_options)
|
123
|
+
options[:document] = @pdf
|
124
|
+
|
125
|
+
array = @pdf.text_formatter.format(@content, *p)
|
126
|
+
::Prawn::Text::Formatted::Box.new(array,
|
127
|
+
options.merge(extra_options).merge(:document => @pdf))
|
128
|
+
else
|
129
|
+
::Prawn::Text::Box.new(@content, @text_options.merge(extra_options).
|
130
|
+
merge(:document => @pdf))
|
131
|
+
end
|
132
|
+
end
|
133
|
+
|
134
|
+
# Returns the width of +text+ under the given text options.
|
135
|
+
#
|
136
|
+
def styled_width_of(text)
|
137
|
+
options = @text_options.reject { |k| k == :style }
|
138
|
+
with_font { @pdf.width_of(text, options) }
|
139
|
+
end
|
140
|
+
|
141
|
+
private
|
142
|
+
|
143
|
+
# Returns the greatest possible width of any single character
|
144
|
+
# under the given text options.
|
145
|
+
# (We use this to determine the minimum width of a table cell)
|
146
|
+
# (Although we currently determine this by measuring "M", it should really
|
147
|
+
# use whichever character is widest under the current font)
|
148
|
+
#
|
149
|
+
def styled_width_of_single_character
|
150
|
+
styled_width_of("M")
|
151
|
+
end
|
152
|
+
end
|
153
|
+
end
|
154
|
+
end
|
155
|
+
end
|