reportbuilder 0.2.0 → 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -9,20 +9,19 @@ class ReportBuilder
9
9
  @out=""
10
10
  end
11
11
  def parse
12
- @out="Report: #{@builder.name}\n"
12
+ @out="#{@builder.name}\n" unless @builder.no_title
13
13
  parse_cycle(@builder)
14
- @out << "\n"
15
14
  end
16
- def add_text(t)
17
- ws=" "*parse_level*2
15
+ def text(t)
16
+ ws=" "*((parse_level-1)*2)
18
17
  @out << ws << t << "\n"
19
18
  end
20
- def add_preformatted(t)
21
- @out << t
19
+ def preformatted(t)
20
+ @out << t << "\n"
22
21
  end
23
- def add_html(t)
22
+ def html(t)
24
23
  # Nothing printed
25
24
  end
26
25
  end
27
26
  end
28
- end
27
+ end
@@ -1,4 +1,5 @@
1
- # Creates a Section
1
+ # Creates an Image
2
+ #
2
3
  class ReportBuilder::Image
3
4
  @@n=1
4
5
  attr_reader :name
@@ -20,12 +21,12 @@ class ReportBuilder::Image
20
21
  @filename=filename
21
22
  end
22
23
  # Based on http://rubyquiz.com/quiz50.html
23
- def to_reportbuilder_text(generator)
24
+ def report_building_text(generator)
24
25
  require 'RMagick'
25
-
26
-
26
+
27
+
27
28
  img = Magick::Image.read(@filename).first
28
-
29
+
29
30
  # Resize too-large images. The resulting image is going to be
30
31
  # about twice the size of the input, so if the original image is too
31
32
  # large we need to make it smaller so the ASCII version won't be too
@@ -38,7 +39,7 @@ class ReportBuilder::Image
38
39
  img.change_geometry('320x320>') do |cols, rows|
39
40
  img.resize!(cols, rows) if cols != img.columns || rows != img.rows
40
41
  end
41
-
42
+
42
43
  # Compute the image size in ASCII "pixels" and resize the image to have
43
44
  # those dimensions. The resulting image does not have the same aspect
44
45
  # ratio as the original, but since our "pixels" are twice as tall as
@@ -46,10 +47,10 @@ class ReportBuilder::Image
46
47
  pr = img.rows / @options[:font_rows]
47
48
  pc = img.columns / @options[:font_cols]
48
49
  img.resize!(pc, pr)
49
-
50
+
50
51
  img = img.quantize(@options[:chars].size, Magick::GRAYColorspace)
51
52
  img = img.normalize
52
-
53
+
53
54
  out=""
54
55
  # Draw the image surrounded by a border. The `view' method is slow but
55
56
  # it makes it easy to address individual pixels. In grayscale images,
@@ -62,17 +63,24 @@ class ReportBuilder::Image
62
63
  pr.times do |i|
63
64
  out+= '|'
64
65
  pc.times do |j|
65
- out+= @options[:chars][view[i][j].red / (2**16/@options[:chars].size)]
66
+ out+= @options[:chars][view[i][j].red / (2**16/@options[:chars].size)]
66
67
  end
67
68
  out+= '|'+"\n"
68
69
  end
69
70
  end
70
71
  out+= border
71
- generator.add_raw(out)
72
+ generator.preformatted(out)
72
73
  end
73
-
74
- def to_reportbuilder_html(generator)
75
- src=generator.add_image(@filename)
76
- generator.add_raw("<img src='#{src}' alt='#{@options[:alt]}' />")
74
+
75
+ def report_building_html(generator)
76
+ basedir=generator.directory+"/images"
77
+ out=basedir+"/"+File.basename(@filename)
78
+ if(File.exists? @filename)
79
+ if !File.exists? out
80
+ FileUtils.mkdir_p basedir
81
+ FileUtils.cp @filename, out
82
+ end
83
+ end
84
+ generator.html("<img src='images/#{File.basename(@filename)}' alt='#{@options[:alt]}' />")
77
85
  end
78
86
  end
@@ -1,16 +1,22 @@
1
- # Creates a Section
1
+ # Creates a Section.
2
+ # A section have a name and contains other elements.
3
+ # Sections could be nested inside anothers
4
+
2
5
  class ReportBuilder::Section
3
6
  @@n=1
4
7
  attr_reader :parent, :elements, :name
5
- def initialize(options={})
8
+ def initialize(options=Hash.new, &block)
6
9
  if !options.has_key? :name
7
- @name="Section #{@nn}"
8
- @nn+=1
10
+ @name="Section #{@@n}"
11
+ @@n+=1
9
12
  else
10
13
  @name=options[:name]
11
14
  end
12
15
  @parent = nil
13
16
  @elements = []
17
+ if block
18
+ add(block)
19
+ end
14
20
  end
15
21
  def parent=(sect)
16
22
  if sect.is_a? ReportBuilder::Section
@@ -19,20 +25,20 @@ class ReportBuilder::Section
19
25
  raise ArgumentError("Parent should be a Section")
20
26
  end
21
27
  end
22
-
23
- def to_reportbuilder_text(generator)
24
- generator.add_text(("="*generator.parse_level)+" "+name)
28
+
29
+ def report_building_text(generator)
30
+ generator.text(("="*generator.parse_level)+" "+name)
25
31
  generator.parse_cycle(self)
26
32
  end
27
-
28
- def to_reportbuilder_html(generator)
33
+
34
+ def report_building_html(generator)
29
35
  htag="h#{generator.parse_level+1}"
30
- anchor=generator.add_toc_entry(name)
31
- generator.add_html "<div class='section'><#{htag}>#{name}</#{htag}><a name='#{anchor}'></a>"
36
+ anchor=generator.toc_entry(name)
37
+ generator.html "<div class='section'><#{htag}>#{name}</#{htag}><a name='#{anchor}'></a>"
32
38
  generator.parse_cycle(self)
33
- generator.add_html "</div>"
39
+ generator.html "</div>"
34
40
  end
35
-
41
+
36
42
  def add(element)
37
43
  if element.is_a? ReportBuilder::Section
38
44
  element.parent=self
@@ -2,11 +2,11 @@ class ReportBuilder
2
2
  # Creates a table.
3
3
  # Use:
4
4
  # table=ReportBuilder::Table.new(:header =>["id","city","name","code1","code2"])
5
- # table.add_row([1, Table.rowspan("New York",3), "Ringo", Table.colspan("no code",2),nil])
6
- # table.add_row([2, nil,"John", "ab-1","ab-2"])
7
- # table.add_row([3, nil,"Paul", "ab-3"])
8
- # table.add_hr
9
- # table.add_row([4, "London","George", Table.colspan("ab-4",2),nil])
5
+ # table.row([1, Table.rowspan("New York",3), "Ringo", Table.colspan("no code",2),nil])
6
+ # table.row([2, nil,"John", "ab-1","ab-2"])
7
+ # table.row([3, nil,"Paul", "ab-3"])
8
+ # table.hr
9
+ # table.row([4, "London","George", Table.colspan("ab-4",2),nil])
10
10
  # puts table
11
11
  # ==>
12
12
  # -----------------------------------------
@@ -20,7 +20,7 @@ class ReportBuilder
20
20
  # -----------------------------------------
21
21
  class Table
22
22
  @@n=1 # :nodoc:
23
-
23
+
24
24
  DEFAULT_OPTIONS={
25
25
  :header => [],
26
26
  :name => nil
@@ -35,7 +35,7 @@ class ReportBuilder
35
35
  # Options: :name, :header
36
36
  # Use:
37
37
  # table=ReportBuilder::Table.new(:header =>["var1","var2"])
38
- def initialize(opts=Hash.new)
38
+ def initialize(opts=Hash.new, &block)
39
39
  raise ArgumentError,"opts should be a Hash" if !opts.is_a? Hash
40
40
  opts=DEFAULT_OPTIONS.merge opts
41
41
  if opts[:name].nil?
@@ -47,18 +47,21 @@ class ReportBuilder
47
47
  @header=opts[:header]
48
48
  @rows=[]
49
49
  @max_cols=[]
50
+ if block
51
+ block.arity<1 ? self.instance_eval(&block) : block.call(self)
52
+ end
50
53
  end
51
54
  # Adds a row
52
55
  # table.add_row(%w{1 2})
53
- def add_row(row)
56
+ def row(row)
54
57
  @rows.push(row)
55
58
  end
56
59
  # Adds a horizontal rule
57
60
  # table.add_hr
58
- def add_hr
61
+ def hr
59
62
  @rows.push(:hr)
60
63
  end
61
- alias_method :add_horizontal_line, :add_hr
64
+ alias_method :horizontal_line, :hr
62
65
  # Adds a rowspan on a cell
63
66
  # table.add_row(["a",table.rowspan("b",2)])
64
67
  def rowspan(data,n)
@@ -66,72 +69,76 @@ class ReportBuilder
66
69
  end
67
70
  # Adds a colspan on a cell
68
71
  # table.add_row(["a",table.colspan("b",2)])
69
-
72
+
70
73
  def colspan(data,n)
71
74
  Colspan.new(data,n)
72
75
  end
73
76
  def calculate_widths # :nodoc:
74
- @max_cols=[]
75
- rows_cal=[header]+@rows
76
- rows_cal.each{|row|
77
- next if row==:hr
78
- row.each_index{|i|
77
+ @max_cols=[]
78
+ rows_cal=[header]+@rows
79
+ rows_cal.each{|row|
80
+ next if row==:hr
81
+ row.each_index{|i|
79
82
  if row[i].nil?
80
- next
83
+ next
81
84
  elsif row[i].is_a? Colspan
82
- size_total=row[i].data.to_s.size
83
- size_per_column=(size_total / row[i].cols)+1
84
- for mi in i...i+row[i].cols
85
- @max_cols[mi] = size_per_column if @max_cols[mi].nil? or @max_cols[mi]<size_per_column
86
- end
85
+ size_total=row[i].data.to_s.size
86
+ size_per_column=(size_total / row[i].cols)+1
87
+ for mi in i...i+row[i].cols
88
+ @max_cols[mi] = size_per_column if @max_cols[mi].nil? or @max_cols[mi]<size_per_column
89
+ end
87
90
  elsif row[i].is_a? Rowspan
88
- size=row[i].data.to_s.size
89
- @max_cols[i]= size if @max_cols[i].nil? or @max_cols[i] < size
91
+ size=row[i].data.to_s.size
92
+ @max_cols[i]= size if @max_cols[i].nil? or @max_cols[i] < size
90
93
  else
91
-
92
- size=row[i].to_s.size
93
- @max_cols[i]= size if @max_cols[i].nil? or @max_cols[i] < size
94
+
95
+ size=row[i].to_s.size
96
+ @max_cols[i]= size if @max_cols[i].nil? or @max_cols[i] < size
94
97
  end
98
+ }
95
99
  }
96
- }
97
100
  end
98
- def to_reportbuilder_text(generator)
101
+ def report_building_text(generator)
99
102
  require 'reportbuilder/table/textgenerator'
100
103
  table_generator=ReportBuilder::Table::TextGenerator.new( generator, self)
101
104
  table_generator.generate
102
105
  end
103
- def to_reportbuilder_html(generator)
106
+ def report_building_html(generator)
104
107
  require 'reportbuilder/table/htmlgenerator'
105
108
  table_generator=ReportBuilder::Table::HtmlGenerator.new(generator, self)
106
109
  table_generator.generate
107
110
  end
108
111
 
109
112
  def total_width # :nodoc:
110
- @max_cols.inject(0){|a,v| a+(v+3)}+1
113
+ if @max_cols.size>0
114
+ @max_cols.inject(0){|a,v| a+(v+3)}+1
115
+ else
116
+ 0
117
+ end
111
118
  end
112
- ######################
113
- # INTERNAL CLASSES #
114
- ######################
115
-
119
+ ######################
120
+ # INTERNAL CLASSES #
121
+ ######################
122
+
116
123
  class Rowspan # :nodoc:
117
124
  attr_accessor :data, :rows
118
125
  def initialize(data,rows)
119
- @data=data
120
- @rows=rows
126
+ @data=data
127
+ @rows=rows
121
128
  end
122
129
  def to_s
123
- @data.to_s
130
+ @data.to_s
124
131
  end
125
132
  end
126
-
133
+
127
134
  class Colspan # :nodoc:
128
135
  attr_accessor :data, :cols
129
136
  def initialize(data,cols)
130
- @data=data
131
- @cols=cols
137
+ @data=data
138
+ @cols=cols
132
139
  end
133
140
  def to_s
134
- @data.to_s
141
+ @data.to_s
135
142
  end
136
143
  end
137
144
  end
@@ -1,17 +1,17 @@
1
1
  class ReportBuilder
2
2
  class Table
3
3
  class HtmlGenerator < ElementGenerator
4
- def generate()
5
- t=@element
6
- anchor=@generator.add_table_entry(t.name)
7
- out="<a name='#{anchor}'></a><table><caption>#{t.name}</caption>"
8
- @rowspans=[]
9
- if t.header.size>0
10
- out+="<thead>"+parse_row(t,t.header,"th")+"</thead>\n"
11
- end
12
- out+="<tbody>\n"
13
- next_class=""
14
- t.rows.each{|row|
4
+ def generate()
5
+ t=@element
6
+ anchor=@generator.table_entry(t.name)
7
+ out="<a name='#{anchor}'></a><table><caption>#{t.name}</caption>"
8
+ @rowspans=[]
9
+ if t.header.size>0
10
+ out+="<thead>"+parse_row(t,t.header,"th")+"</thead>\n"
11
+ end
12
+ out+="<tbody>\n"
13
+ next_class=""
14
+ t.rows.each{|row|
15
15
  if row==:hr
16
16
  next_class="top"
17
17
  else
@@ -19,32 +19,32 @@ class ReportBuilder
19
19
  out+="<tr#{class_tag}>"+parse_row(t,row)+"</tr>\n"
20
20
  next_class=""
21
21
  end
22
- }
23
- out+="</tbody>\n</table>\n"
24
- @generator.add_html(out)
25
- end
26
- def parse_row(t,row,tag="td")
27
- row_ary=[]
28
- colspan_i=0
29
- row.each_index do |i|
30
- if !@rowspans[i].nil? and @rowspans[i]>0
31
- @rowspans[i]-=1
32
- elsif colspan_i>0
33
- colspan_i-=1
34
- elsif row[i].is_a? Table::Colspan
35
- row_ary.push(sprintf("<%s colspan=\"%d\">%s</%s>",tag, row[i].cols, row[i].data,tag))
36
- colspan_i=row[i].cols-1
37
- elsif row[i].nil?
38
- row_ary.push("<#{tag}></#{tag}>")
39
- elsif row[i].is_a? Table::Rowspan
40
- row_ary.push(sprintf("<%s rowspan=\"%d\">%s</%s>", tag, row[i].rows, row[i].data, tag))
41
- @rowspans[i]=row[i].rows-1
42
- else
43
- row_ary.push("<#{tag}>#{row[i]}</#{tag}>")
44
- end
22
+ }
23
+ out+="</tbody>\n</table>\n"
24
+ @generator.html(out)
25
+ end
26
+ def parse_row(t,row,tag="td")
27
+ row_ary=[]
28
+ colspan_i=0
29
+ row.each_index do |i|
30
+ if !@rowspans[i].nil? and @rowspans[i]>0
31
+ @rowspans[i]-=1
32
+ elsif colspan_i>0
33
+ colspan_i-=1
34
+ elsif row[i].is_a? Table::Colspan
35
+ row_ary.push(sprintf("<%s colspan=\"%d\">%s</%s>",tag, row[i].cols, row[i].data,tag))
36
+ colspan_i=row[i].cols-1
37
+ elsif row[i].nil?
38
+ row_ary.push("<#{tag}></#{tag}>")
39
+ elsif row[i].is_a? Table::Rowspan
40
+ row_ary.push(sprintf("<%s rowspan=\"%d\">%s</%s>", tag, row[i].rows, row[i].data, tag))
41
+ @rowspans[i]=row[i].rows-1
42
+ else
43
+ row_ary.push("<#{tag}>#{row[i]}</#{tag}>")
45
44
  end
46
- row_ary.join("")
47
45
  end
46
+ row_ary.join("")
47
+ end
48
48
  end
49
49
  end
50
50
  end
@@ -1,26 +1,28 @@
1
1
  class ReportBuilder
2
2
  class Table
3
3
  class TextGenerator < ElementGenerator
4
-
4
+
5
5
  def generate()
6
6
  t=@element
7
7
  t.calculate_widths
8
8
  total_width=t.total_width
9
- out="Table: #{t.name}\n"
10
- if t.header.size>0
11
- out+=parse_hr(total_width)+"\n"
12
- out+=parse_row(t,t.header)+"\n"
13
- out+=parse_hr(total_width)+"\n"
14
- end
15
- t.rows.each do |row|
16
- if row==:hr
9
+ out="#{t.name}\n"
10
+ if total_width>0
11
+ if t.header.size>0
12
+ out+=parse_hr(total_width)+"\n"
13
+ out+=parse_row(t,t.header)+"\n"
17
14
  out+=parse_hr(total_width)+"\n"
18
- else
19
- out+=parse_row(t,row)+"\n"
20
15
  end
16
+ t.rows.each do |row|
17
+ if row==:hr
18
+ out+=parse_hr(total_width)+"\n"
19
+ else
20
+ out+=parse_row(t,row)+"\n"
21
+ end
22
+ end
23
+ out+=parse_hr(total_width)+"\n"
21
24
  end
22
- out+=parse_hr(total_width)+"\n"
23
- @generator.add_text(out)
25
+ @generator.text(out)
24
26
  end
25
27
  # Parse a row
26
28
  def parse_row(t,row)
@@ -48,6 +50,6 @@ class ReportBuilder
48
50
  def parse_hr(l)
49
51
  "-"*l
50
52
  end
51
- end
52
53
  end
54
+ end
53
55
  end