31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
|
# File 'lib/text_layout/table.rb', line 31
def layout
spanss = {:row => Hash.new{[]}, :col => Hash.new{[]}}
layout = @array.map{[]}
@array.each_with_index do |cols, row|
cols.each_with_index do |attr, col|
attr = normalize(attr)
unless col = layout[row].index(nil)
col = layout[row].size
end
if !attr[:rowspan] && !attr[:colspan]
layout[row][col] = Cell.new(col, row, attr)
else
span = Span.new(col, row, attr)
spanss[:row][row...row+attr[:rowspan]] <<= span if attr[:rowspan]
spanss[:col][col...col+attr[:colspan]] <<= span if attr[:colspan]
(attr[:rowspan] || 1).times do |rr|
(attr[:colspan] || 1).times do |cc|
layout[row+rr][col+cc] = span
end
end
end
end
end
max = {:row => [], :col => []}
layout.each_with_index do |cols, row|
cols.each_with_index do |cell, col|
next if Span === cell && !cell.main?(col, row)
unless cell.attr[:colspan]
max[:col][col] = [max[:col][col] || 0, cell.width].max
end
unless cell.attr[:rowspan]
max[:row][row] = [max[:row][row] || 0, cell.height].max
end
end
end
[[:col, 3], [:row, 0]].each do |dir, margin|
spanss[dir].each do |range, spans|
range_size = range.end - range.begin
spans.each do |span|
size = sum(max[dir][range]) + margin * (range_size - 1)
diff = (dir == :col ? span.width : span.height) - size
next unless diff > 0
q, r = diff.divmod range_size
range.each_with_index do |i, rr|
max[dir][i] += q + (rr < r ? 1 : 0)
end
end
end
end
result = ""
sum(max[:row]).times do |layout_row|
n = layout_row
row = max[:row].each_with_index do |height, i|
if n - height >= 0
n -= height
else
break i
end
end
line = []
layout[row].each_with_index do |cell, col|
next unless cell.col == col
n = layout_row - sum(max[:row][0...cell.row])
width =
if Span === cell && colspan = cell.attr[:colspan]
sum(max[:col][col...col+colspan]) + 3 * (colspan - 1)
else
max[:col][col]
end
line << justify(cell.attr[:value][n].to_s, width)
end
result += "| " + line.join(" | ") + " |\n"
end
result
end
|