jyurek-prawn-layout 0.8.4
Sign up to get free protection for your applications and to get access to all the features.
- data/README +7 -0
- data/Rakefile +70 -0
- data/examples/example_helper.rb +10 -0
- data/examples/grid/bounding_boxes.rb +21 -0
- data/examples/grid/column_gutter_grid.rb +20 -0
- data/examples/grid/multi_boxes.rb +51 -0
- data/examples/grid/show_grid.rb +13 -0
- data/examples/grid/simple_grid.rb +20 -0
- data/examples/page_layout/lazy_bounding_boxes.rb +27 -0
- data/examples/page_layout/padded_box.rb +23 -0
- data/examples/table/addressbook.csv +6 -0
- data/examples/table/cell.rb +39 -0
- data/examples/table/currency.csv +1834 -0
- data/examples/table/fancy_table.rb +63 -0
- data/examples/table/table.rb +50 -0
- data/examples/table/table_alignment.rb +17 -0
- data/examples/table/table_border_color.rb +16 -0
- data/examples/table/table_colspan.rb +18 -0
- data/examples/table/table_header_color.rb +18 -0
- data/examples/table/table_header_underline.rb +14 -0
- data/examples/table/table_widths.rb +60 -0
- data/lib/prawn/layout.rb +21 -0
- data/lib/prawn/layout/grid.rb +260 -0
- data/lib/prawn/layout/page.rb +76 -0
- data/lib/prawn/table.rb +416 -0
- data/lib/prawn/table/cell.rb +285 -0
- data/spec/grid_spec.rb +85 -0
- data/spec/spec_helper.rb +26 -0
- data/spec/table_spec.rb +337 -0
- metadata +105 -0
@@ -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
|
data/lib/prawn/layout.rb
ADDED
@@ -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
|