diff --git a/lib/prawn/table/cell/text.rb b/lib/prawn/table/cell/text.rb
index ff28789..a556695 100644
--- a/lib/prawn/table/cell/text.rb
+++ b/lib/prawn/table/cell/text.rb
@@ -17,7 +17,7 @@ class Text < Cell
TextOptions = [:inline_format, :kerning, :size, :align, :valign,
:rotate, :rotate_around, :leading, :single_line, :skip_encoding,
- :overflow, :min_font_size]
+ :overflow, :min_font_size, :nowrap]
TextOptions.each do |option|
define_method("#{option}=") { |v| @text_options[option] = v }
@@ -48,7 +48,13 @@ def font_style=(style)
# from the final width if the text is long.
#
def natural_content_width
- @natural_content_width ||= [styled_width_of(@content), @pdf.bounds.width].min
+ if nowrap == :whitespace
+ @natural_content_width ||= [@content.split(/\s/).compact.map { |word| styled_width_of(word) }.max || 0, @pdf.bounds.width || 0].min
+ else
+ @natural_content_width ||= [styled_width_of(@content), @pdf.bounds.width].min
+ end
+
+ @natural_content_width
end
# Returns the natural height of this block of text, wrapped to the
@@ -80,7 +86,7 @@ def set_width_constraints
# sure we have enough width to be at least one character wide. This is
# a bit of a hack, but it should work well enough.
unless defined?(@min_width) && @min_width
- min_content_width = [natural_content_width, styled_width_of_single_character].min
+ min_content_width = nowrap ? natural_content_width : [natural_content_width, styled_width_of_single_character].min
@min_width = padding_left + padding_right + min_content_width
super
end
@@ -135,7 +141,15 @@ def text_box(extra_options={})
#
def styled_width_of(text)
options = @text_options.reject { |k| k == :style }
- with_font { @pdf.width_of(text, options) }
+
+ with_font do
+ @pdf.width_of(text, options)
+ if text.empty?
+ 0
+ else
+ text.lines.map { |line| @pdf.width_of(line, options) }.max
+ end
+ end
end
private
diff --git a/manual/table/nowrap.rb b/manual/table/nowrap.rb
new file mode 100644
index 0000000..5e91323
--- /dev/null
+++ b/manual/table/nowrap.rb
@@ -0,0 +1,27 @@
+# encoding: utf-8
+#
+# Columns specified as nowrap will always fit on to one line forcing others to
+# resize as appropriate. If you want to allow wrapping, but ensure it's never
+# in the middle of a word use :whitespace
as the :nowrap
option's value.
+#
+require File.expand_path(File.join(File.dirname(__FILE__),
+ %w[.. example_helper]))
+
+filename = File.basename(__FILE__).gsub('.rb', '.pdf')
+Prawn::ManualBuilder::Example.generate(filename) do
+ text "Normal widths:"
+ table([["Blah " * 10, "Blah " * 10]])
+ move_down 20
+
+ text "Nowrap widths:"
+ table([[make_cell(:content => "Blah " * 11, :nowrap => true), "Blah " * 12]])
+ move_down 20
+
+ text "Wide content without nowrap:"
+ table([[("wordword" * 7 + " word" * 4), "word " * 10]])
+ move_down 20
+
+ text "Wide content with whitespace nowrap:"
+ table([[make_cell(:content => ("wordword" * 7 + " word" * 4), :nowrap => :whitespace), "word " * 10]])
+ move_down 20
+end
diff --git a/manual/table/table.rb b/manual/table/table.rb
index 779dd29..dea12db 100644
--- a/manual/table/table.rb
+++ b/manual/table/table.rb
@@ -24,6 +24,7 @@
s.example "cell_borders_and_bg"
s.example "cell_border_lines"
s.example "cell_text"
+ s.example "nowrap"
s.example "image_cells"
s.example "span"
s.example "before_rendering_page"
diff --git a/spec/cell_spec.rb b/spec/cell_spec.rb
index 9a5a0fa..6c6d8fa 100644
--- a/spec/cell_spec.rb
+++ b/spec/cell_spec.rb
@@ -154,6 +154,21 @@ def cell(options={})
(5 * @pdf.height_of("text"))
end
+ it "should have a width that can fit @content without wrapping" do
+ c = cell(:content => "text", :padding => 10, :nowrap => true)
+ min_content_width = c.min_width - c.padding[1] - c.padding[3]
+
+ expect(@pdf.height_of("text", :width => min_content_width)).to eq(@pdf.height_of("text"))
+ end
+
+ it "should have a width that can fit @content without wrapping even if it's multiline" do
+ c = cell(:content => "text\nlonger", :padding => 10, :nowrap => true)
+ min_content_width = c.min_width - c.padding[1] - c.padding[3]
+
+ expect(@pdf.height_of("text\nlonger", :width => min_content_width)).to be <
+ (3 * @pdf.height_of("text"))
+ end
+
it "should defer min_width's evaluation of padding" do
c = cell(:content => "text", :padding => 100)
c.padding = 0