ruport-util 0.8.0 → 0.9.0
Sign up to get free protection for your applications and to get access to all the features.
- data/Rakefile +2 -3
- data/example/data/amline_graph.xml +34 -0
- data/example/data/amline_settings.xml +268 -0
- data/example/draw_graph.rb +27 -0
- data/example/graph_report.rb +12 -7
- data/example/gruff_report.rb +23 -0
- data/lib/ruport/util.rb +1 -1
- data/lib/ruport/util/graph.rb +39 -152
- data/lib/ruport/util/graph/amline.rb +200 -0
- data/lib/ruport/util/graph/gruff.rb +59 -0
- data/lib/ruport/util/graph/scruffy.rb +71 -0
- data/test/test_graph_renderer.rb +2 -63
- data/test/test_hpricot_traverser.rb +45 -0
- metadata +14 -13
data/Rakefile
CHANGED
@@ -33,7 +33,7 @@ end
|
|
33
33
|
|
34
34
|
spec = Gem::Specification.new do |spec|
|
35
35
|
spec.name = "ruport-util"
|
36
|
-
spec.version = "0.
|
36
|
+
spec.version = "0.9.0"
|
37
37
|
spec.platform = Gem::Platform::RUBY
|
38
38
|
spec.summary = "A set of tools and helper libs for Ruby Reports"
|
39
39
|
spec.files = Dir.glob("{example,lib,test,bin}/**/**/*") +
|
@@ -48,8 +48,7 @@ spec = Gem::Specification.new do |spec|
|
|
48
48
|
spec.extra_rdoc_files = %w{INSTALL}
|
49
49
|
spec.rdoc_options << '--title' << 'ruport-util Documentation' <<
|
50
50
|
'--main' << 'INSTALL' << '-q'
|
51
|
-
spec.add_dependency('ruport', ">=1.2.
|
52
|
-
spec.add_dependency('scruffy', ">=0.2.2")
|
51
|
+
spec.add_dependency('ruport', ">=1.2.2")
|
53
52
|
spec.add_dependency('mailfactory',">=1.2.3")
|
54
53
|
spec.add_dependency('rubyzip','>=0.9.1')
|
55
54
|
spec.author = "Gregory Brown"
|
@@ -0,0 +1,34 @@
|
|
1
|
+
<graph gid=""> <!-- if you are using XML data file, graph "gid" must match graph "gid" in data file -->
|
2
|
+
|
3
|
+
<axis></axis> <!-- [left] (left/ right) indicates which y axis should be used -->
|
4
|
+
<title></title> <!-- [] (graph title) -->
|
5
|
+
<color></color> <!-- [] (hex color code) if not defined, uses colors from this array: #FF0000, #0000FF, #00FF00, #FF9900, #CC00CC, #00CCCC, #33FF00, #990000, #000066 -->
|
6
|
+
<color_hover></color_hover> <!-- [#BBBB00] (hex color code) -->
|
7
|
+
<line_alpha></line_alpha> <!-- [100] (0 - 100) -->
|
8
|
+
<line_width></line_width> <!-- [0] (Number) 0 for hairline -->
|
9
|
+
<fill_alpha></fill_alpha> <!-- [0] (0 - 100) if you want the chart to be area chart, use bigger than 0 value -->
|
10
|
+
<fill_color></fill_color> <!-- [grpah.color] (hex color code) -->
|
11
|
+
<balloon_color></balloon_color> <!-- [graph color] (hex color code) leave empty to use the same color as graph -->
|
12
|
+
<balloon_alpha></balloon_alpha> <!-- [100] (0 - 100) -->
|
13
|
+
<balloon_text_color></balloon_text_color> <!-- [#FFFFFF] (hex color code) -->
|
14
|
+
<bullet></bullet> <!-- [] (square, round, square_outlined, round_outlined, filename.swf) can be used predefined bullets or loaded custom bullets. Leave empty if you don't want to have bullets at all. Outlined bullets use plot area color for outline color -->
|
15
|
+
<!-- The chart will look for this file in amline_path folder (amline_path is set in HTML) -->
|
16
|
+
<bullet_size></bullet_size> <!-- [6](Number) affects only predefined (square and round) bullets, does not change size of custom loaded bullets -->
|
17
|
+
<bullet_color></bullet_color> <!-- [graph color] (hex color code) affects only predefined (square and round) bullets, does not change color of custom loaded bullets. Leave empty to use the same color as graph -->
|
18
|
+
<bullet_alpha></bullet_alpha> <!-- [graph alpha] (hex color code) Leave empty to use the same alpha as graph -->
|
19
|
+
<hidden></hidden> <!-- [false] (true / false) vill not be visible until you check corresponding checkbox in the legend -->
|
20
|
+
<selected></selected> <!-- [true] (true / false) if true, balloon indicating value will be visible then roll over plot area -->
|
21
|
+
<balloon_text>
|
22
|
+
<![CDATA[]]> <!-- [<b>{value}</b><br>{description}] ({title} {value} {series} {description} {percents}) You can format any balloon text: {title} will be replaced with real title, {value} - with value and so on. You can add your own text or html code too. -->
|
23
|
+
</balloon_text>
|
24
|
+
<data_labels>
|
25
|
+
<![CDATA[]]> <!-- [] ({title} {value} {series} {description} {percents}) Data labels can display value (and more) near your point on the plot area. -->
|
26
|
+
<!-- to avoid overlapping, data labels, the same as bullets are not visible if there are more then hide_bullets_count data points on plot area. -->
|
27
|
+
</data_labels>
|
28
|
+
<data_labels_text_color></data_labels_text_color> <!-- [text_color] (hex color code) -->
|
29
|
+
<data_labels_text_size></data_labels_text_size> <!-- [text_size] (Number) -->
|
30
|
+
<data_labels_position></data_labels_position> <!-- [above] (below / above) -->
|
31
|
+
<vertical_lines></vertical_lines> <!-- [false] (true / false) whether to draw vertical lines or not. If you want to show vertical lines only (without the graph, set line_alpha to 0 -->
|
32
|
+
<visible_in_legend></visible_in_legend> <!-- [true] (true / false) whether to show legend entry for this graph or not -->
|
33
|
+
</graph>
|
34
|
+
|
@@ -0,0 +1,268 @@
|
|
1
|
+
<!-- Value between [] brackets, for example [#FFFFFF] shows default value which is used if this parameter is not set -->
|
2
|
+
<!-- This means, that if you are happy with this value, you can delete this line at all and reduce file size -->
|
3
|
+
<!-- value or explanation between () brackets shows the range or type of values you should use for this parameter -->
|
4
|
+
<settings>
|
5
|
+
<width></width> <!-- [] (Number) if empty, will be equal to width of your flash movie -->
|
6
|
+
<height></height> <!-- [] (Number) if empty, will be equal to height of your flash movie -->
|
7
|
+
|
8
|
+
<data_type></data_type> <!-- [xml] (xml / csv) -->
|
9
|
+
<type></type> <!-- [line] (line, stacked, 100% stacked) -->
|
10
|
+
<csv_separator></csv_separator> <!-- [;] (string) csv file data separator (you need it only if you are using csv file for your data) -->
|
11
|
+
<skip_rows></skip_rows> <!-- [0] (Number) if you are using csv data type, you can set the number of rows which should be skipped here -->
|
12
|
+
<font></font> <!-- [Arial] (font name) use device fonts, such as Arial, Times New Roman, Tahoma, Verdana... -->
|
13
|
+
<text_size></text_size> <!-- [11] (Number) text size of all texts. Every text size can be set individually in the settings below -->
|
14
|
+
<text_color></text_color> <!-- [#000000] (hex color code) main text color. Every text color can be set individually in the settings below-->
|
15
|
+
<decimals_separator>.</decimals_separator> <!-- [,] (string) decimal separator. Note, that this is for displaying data only. Decimals in data xml file must be separated with dot -->
|
16
|
+
<thousands_separator></thousands_separator> <!-- [ ] (string) thousand separator -->
|
17
|
+
<redraw></redraw> <!-- [false] (true / false) if your chart's width or height is set in percents, and redraw is set to true, the chart will be redrawn then screen size changes -->
|
18
|
+
<!-- Legend, buttons labels will not be repositioned if you set your x and y values for these objects -->
|
19
|
+
<reload_data_interval></reload_data_interval> <!-- [0] (Number) how often data should be reloaded (time in seconds) If you are using this feature I strongly recommend to turn off zoom function (set <zoomable>false</zoomable>) -->
|
20
|
+
<add_time_stamp></add_time_stamp> <!-- [false] (true / false) if true, a unique number will be added every time flash loads data. Mainly this feature is useful if you set reload _data_interval >0 -->
|
21
|
+
<precision></precision> <!-- [2] (Number) shows how many numbers should be shown after comma for calculated values (percents, used only in stacked charts) -->
|
22
|
+
<connect></connect> <!-- [false] (true / false) whether to connect points if y data is missing -->
|
23
|
+
<hide_bullets_count></hide_bullets_count> <!-- [] (Number) if there are more then hideBulletsCount points on the screen, bullets can be hidden, to avoid mess. Leave empty, or 0 to show bullets all the time. This rule doesn't influence if custom bullet is defined near y value, in data file -->
|
24
|
+
<link_target></link_target> <!-- [] (_blank, _top ...) -->
|
25
|
+
<start_on_axis></start_on_axis> <!-- [true] (true / false) if set to false, graph is moved 1/2 of one series interval from Y axis -->
|
26
|
+
|
27
|
+
<background> <!-- BACKGROUND -->
|
28
|
+
<color></color> <!-- [#FFFFFF] (hex color code) -->
|
29
|
+
<alpha></alpha> <!-- [0] (0 - 100) use 0 if you are using custom swf or jpg for background -->
|
30
|
+
<border_color></border_color> <!-- [#FFFFFF] (hex color code) -->
|
31
|
+
<border_alpha></border_alpha> <!-- [0] (0 - 100) -->
|
32
|
+
<file></file> <!-- [] (filename) swf or jpg file of a background. Do not use progressive jpg file, it will be not visible with flash player 7 -->
|
33
|
+
<!-- The chart will look for this file in amline_path folder (amline_path is set in HTML) -->
|
34
|
+
</background>
|
35
|
+
|
36
|
+
|
37
|
+
<plot_area> <!-- PLOT AREA (the area between axes) -->
|
38
|
+
<color></color> <!-- [#FFFFFF](hex color code) -->
|
39
|
+
<alpha></alpha> <!-- [0] (0 - 100) if you want it to be different than background color, use bigger than 0 value -->
|
40
|
+
<border_color></border_color> <!-- [#000000] (hex color code) -->
|
41
|
+
<border_alpha></border_alpha> <!-- [0] (0 - 100) -->
|
42
|
+
<margins> <!-- plot area margins -->
|
43
|
+
<left></left> <!-- [60](Number) -->
|
44
|
+
<top></top> <!-- [60](Number) -->
|
45
|
+
<right></right> <!-- [60](Number) -->
|
46
|
+
<bottom></bottom> <!-- [80](Number) -->
|
47
|
+
</margins>
|
48
|
+
</plot_area>
|
49
|
+
|
50
|
+
<scroller>
|
51
|
+
<enabled></enabled> <!-- [true] (true / false) whether to show scroller when chart is zoomed or not -->
|
52
|
+
<y></y> <!-- [] (Number) Y position of scroller. If not set here, will be displayed above plot area -->
|
53
|
+
<color></color> <!-- [#DADADA] (hex color code) scrollbar color -->
|
54
|
+
<alpha></alpha> <!-- [100] (Number) scrollbar alpha -->
|
55
|
+
<bg_color></bg_color> <!-- [#F0F0F0] (hex color code) scroller background color -->
|
56
|
+
<bg_alpha></bg_alpha> <!-- [100] (Number) scroller background alpha -->
|
57
|
+
<height></height> <!-- [10] (Number) scroller height -->
|
58
|
+
</scroller>
|
59
|
+
|
60
|
+
<grid> <!-- GRID -->
|
61
|
+
<x> <!-- vertical grid -->
|
62
|
+
<enabled></enabled> <!-- [true] (true / false) -->
|
63
|
+
<color></color> <!-- [#000000] (hex color code) -->
|
64
|
+
<alpha></alpha> <!-- [15] (0 - 100) -->
|
65
|
+
<dashed></dashed> <!-- [false](true / false) -->
|
66
|
+
<dash_length></dash_length> <!-- [5] (Number) -->
|
67
|
+
<approx_count></approx_count> <!-- [4] (Number) approximate number of gridlines -->
|
68
|
+
</x>
|
69
|
+
<y_left> <!-- horizontal grid, Y left axis. Visible only if there is at least one graph assigned to left axis -->
|
70
|
+
<enabled></enabled> <!-- [true] (true / false) -->
|
71
|
+
<color></color> <!-- [#000000] (hex color code) -->
|
72
|
+
<alpha></alpha> <!-- [15] (0 - 100) -->
|
73
|
+
<dashed></dashed> <!-- [false] (true / false) -->
|
74
|
+
<dash_length></dash_length> <!-- [5] (Number) -->
|
75
|
+
<approx_count></approx_count> <!-- [10] (Number) approximate number of gridlines -->
|
76
|
+
</y_left>
|
77
|
+
<y_right> <!-- horizontal grid, Y right axis. Visible only if there is at least one graph assigned to right axis -->
|
78
|
+
<enabled></enabled> <!-- [true] (true / false) -->
|
79
|
+
<color></color> <!-- [#000000] (hex color code) -->
|
80
|
+
<alpha></alpha> <!-- [15] (0 - 100) -->
|
81
|
+
<dashed></dashed> <!-- [false] (true / false) -->
|
82
|
+
<dash_length></dash_length> <!-- [5] (Number) -->
|
83
|
+
<approx_count></approx_count> <!-- [10] (Number) approximate number of gridlines -->
|
84
|
+
</y_right>
|
85
|
+
</grid>
|
86
|
+
|
87
|
+
<values> <!-- VALUES -->
|
88
|
+
<x> <!-- x axis -->
|
89
|
+
<enabled></enabled> <!-- [true] (true / false) -->
|
90
|
+
<rotate></rotate> <!-- [0] (0 - 90) angle of rotation. If you want to rotate by degree from 1 to 89, you must have font.swf file in fonts folder -->
|
91
|
+
<frequency></frequency> <!-- [1] (Number) how often values should be placed, 1 - near every gridline, 2 - near every second gridline... -->
|
92
|
+
<skip_first></skip_first> <!-- [false] (true / false) to skip or not first value -->
|
93
|
+
<skip_last></skip_last> <!-- [false] (true / false) to skip or not last value -->
|
94
|
+
<color></color> <!-- [text_color] (hex color code) -->
|
95
|
+
<text_size></text_size> <!-- [text_size] (Number) -->
|
96
|
+
</x>
|
97
|
+
<y_left> <!-- y left axis -->
|
98
|
+
<enabled></enabled> <!-- [true] (true / false) -->
|
99
|
+
<reverse></reverse> <!-- [false] (true / false) whether to reverse this axis values or not. If set to true, values will start from biggest number and will end with a smallest number -->
|
100
|
+
<rotate></rotate> <!-- [0] (0 - 90) angle of rotation. If you want to rotate by degree from 1 to 89, you must have font.swf file in fonts folder -->
|
101
|
+
<min></min> <!-- [] (Number) minimum value of this axis. If empty, this value will be calculated automatically. -->
|
102
|
+
<max></max> <!-- [] (Number) maximum value of this axis. If empty, this value will be calculated automatically -->
|
103
|
+
<strict_min_max></strict_min_max> <!-- [false] (true / false) by default, if your values are bigger then defined max (or smaller then defined min), max and min is changed so that all the chart would fit to chart area. If you don't want this, set this option to false. -->
|
104
|
+
<frequency></frequency> <!-- [1] (Number) how often values should be placed, 1 - near every gridline, 2 - near every second gridline... -->
|
105
|
+
<skip_first></skip_first> <!-- [true] (true / false) to skip or not first value -->
|
106
|
+
<skip_last></skip_last> <!-- [false] (true / false) to skip or not last value -->
|
107
|
+
<color></color> <!-- [text_color] (hex color code) -->
|
108
|
+
<text_size></text_size> <!-- [text_size] (Number) -->
|
109
|
+
<unit></unit> <!-- [] (text) unit which will be added to values on y axis-->
|
110
|
+
<unit_position></unit_position> <!-- [right] (left / right) -->
|
111
|
+
<integers_only></integers_only> <!-- [false] (true / false) if set to true, values with decimals will be omitted -->
|
112
|
+
</y_left>
|
113
|
+
<y_right> <!-- y right axis -->
|
114
|
+
<enabled></enabled> <!-- [true] (true / false) -->
|
115
|
+
<reverse></reverse> <!-- [false] (true / false) whether to reverse this axis values or not. If set to true, values will start from biggest number and will end with a smallest number -->
|
116
|
+
<rotate></rotate> <!-- [0] (0 - 90) angle of rotation. If you want to rotate by degree from 1 to 89, you must have font.swf file in fonts folder -->
|
117
|
+
<min></min> <!-- [] (Number) minimum value of this axis. If empty, this value will be calculated automatically. -->
|
118
|
+
<max></max> <!-- [] (Number) maximum value of this axis. If empty, this value will be calculated automatically -->
|
119
|
+
<strict_min_max></strict_min_max> <!-- [false] (true / false) by default, if your values are bigger then defined max (or smaller then defined min), max and min is changed so that all the chart would fit to chart area. If you don't want this, set this option to false. -->
|
120
|
+
<frequency></frequency> <!-- [1] (Number) how often values should be placed, 1 - near every gridline, 2 - near every second gridline... -->
|
121
|
+
<skip_first></skip_first> <!-- [true] (true / false) to skip or not first value -->
|
122
|
+
<skip_last></skip_last> <!-- [false] (true / false) to skip or not last value -->
|
123
|
+
<color></color> <!-- [text_color] (hex color code) -->
|
124
|
+
<text_size></text_size> <!-- [text_size] (Number) -->
|
125
|
+
<unit></unit> <!-- [] (text) unit which will be added to values on y axis-->
|
126
|
+
<unit_position></unit_position> <!-- [right] (left / right) -->
|
127
|
+
<integers_only></integers_only> <!-- [false] (true / false) if set to true, values with decimals will be omitted -->
|
128
|
+
</y_right>
|
129
|
+
</values>
|
130
|
+
|
131
|
+
<axes> <!-- axes -->
|
132
|
+
<x> <!-- X axis -->
|
133
|
+
<color></color> <!-- [#000000] (hex color code) -->
|
134
|
+
<alpha></alpha> <!-- [100] (0 - 100) -->
|
135
|
+
<width></width> <!-- [2] (Number) line width, 0 for hairline -->
|
136
|
+
<tick_length></tick_length> <!-- [7] (Number) -->
|
137
|
+
</x>
|
138
|
+
<y_left> <!-- Y left axis, visible only if at least one graph is assigned to this axis -->
|
139
|
+
<color></color> <!-- [#000000] (hex color code) -->
|
140
|
+
<alpha></alpha> <!-- [100] (0 - 100) -->
|
141
|
+
<width></width> <!-- [2] (Number) line width, 0 for hairline -->
|
142
|
+
<tick_length></tick_length> <!-- [7] (Number) -->
|
143
|
+
</y_left>
|
144
|
+
<y_right> <!-- Y right axis, visible only if at least one graph is assigned to this axis -->
|
145
|
+
<color></color> <!-- [#000000] (hex color code) -->
|
146
|
+
<alpha></alpha> <!-- [100] (0 - 100) -->
|
147
|
+
<width></width> <!-- [2] (Number) line width, 0 for hairline -->
|
148
|
+
<tick_length></tick_length> <!-- [7] (Number) -->
|
149
|
+
</y_right>
|
150
|
+
</axes>
|
151
|
+
|
152
|
+
<indicator> <!-- INDICATOR -->
|
153
|
+
<enabled></enabled> <!-- [true] (true / false) -->
|
154
|
+
<zoomable></zoomable> <!-- [true] (true / false) -->
|
155
|
+
<color></color> <!-- [#BBBB00] (hex color code) line and x balloon background color -->
|
156
|
+
<line_alpha></line_alpha> <!-- [100] (0 - 100) -->
|
157
|
+
<selection_color></selection_color> <!-- [#BBBB00] (hex color code) -->
|
158
|
+
<selection_alpha></selection_alpha> <!-- [25] (0 - 100) -->
|
159
|
+
<x_balloon_enabled></x_balloon_enabled> <!-- [true] (true / false) -->
|
160
|
+
<x_balloon_text_color></x_balloon_text_color> <!-- [text_color] (hex color code) -->
|
161
|
+
<y_balloon_text_size></y_balloon_text_size> <!-- [text_color] (hex color code) -->
|
162
|
+
<y_balloon_on_off></y_balloon_on_off> <!-- [true] (true / false) whether it is possible to turn on/off y balloon by clicking on graphs or legend. Works only if indicator is enabled -->
|
163
|
+
<one_y_balloon></one_y_balloon> <!-- [false] (true / false) if you set it to true, only one y balloon will be visible at a time -->
|
164
|
+
</indicator>
|
165
|
+
|
166
|
+
<legend> <!-- LEGEND -->
|
167
|
+
<enabled></enabled> <!-- [true] (true / false) -->
|
168
|
+
<x></x> <!-- [] (Number) if empty, will be equal to left margin -->
|
169
|
+
<y></y> <!-- [] (Number) if empty, will be 20px below x axis values -->
|
170
|
+
<width></width> <!-- [] (Number) if empty, will be equal to plot area width -->
|
171
|
+
<max_columns></max_columns> <!-- [] (Number) the maximum number of columns in the legend -->
|
172
|
+
<color></color> <!-- [#FFFFFF] (hex color code) background color -->
|
173
|
+
<alpha></alpha> <!-- [0] (0 - 100) background alpha -->
|
174
|
+
<border_color></border_color> <!-- [#000000] (hex color code) border color -->
|
175
|
+
<border_alpha></border_alpha> <!-- [0] (0 - 100) border alpha -->
|
176
|
+
<text_color></text_color> <!-- [text_color] (hex color code) -->
|
177
|
+
<text_color_hover></text_color_hover> <!-- [#BBBB00] (hex color code) -->
|
178
|
+
<text_size></text_size> <!-- [text_size] (Number) -->
|
179
|
+
<spacing></spacing> <!-- [10] (Number) vertical and horizontal gap between legend entries -->
|
180
|
+
<margins></margins> <!-- [0] (Number) legend margins (space between legend border and legend entries, recommended to use only if legend border is visible or background color is different from chart area background color) -->
|
181
|
+
<graph_on_off></graph_on_off> <!-- [true] (true / false) if true, color box gains "checkbox" function - it is possible to make graphs visible/invisible by clicking on this checkbox -->
|
182
|
+
<key> <!-- KEY (the color box near every legend entry) -->
|
183
|
+
<size></size> <!-- [16] (Number) key size-->
|
184
|
+
<border_color></border_color> <!-- [] (hex color code) leave empty if you don't want to have border-->
|
185
|
+
<key_mark_color></key_mark_color> <!-- [#FFFFFF] (hex color code) key tick mark color -->
|
186
|
+
</key>
|
187
|
+
<values> <!-- VALUES -->
|
188
|
+
<enabled></enabled> <!-- [false] (true / false) whether to show values near legend entries or not -->
|
189
|
+
<width></width> <!-- [80] (Number) width of text field for value -->
|
190
|
+
<align>left</align> <!-- [right] (right / left) -->
|
191
|
+
<text><![CDATA[: ${value}]]></text> <!-- [{value}] ({title} {value} {series} {description} {percents}) You can format any text: {value} will be replaced with value, {description} - with description and so on. You can add your own text or html code too. -->
|
192
|
+
</values>
|
193
|
+
</legend>
|
194
|
+
|
195
|
+
<zoom_out_button>
|
196
|
+
<x></x> <!-- [] (Number) x position of zoom out button, if not defined, will be aligned to right of plot area -->
|
197
|
+
<y></y> <!-- [] (Number) y position of zoom out button, if not defined, will be aligned to top of plot area -->
|
198
|
+
<color></color> <!-- [#BBBB00] (hex color code) background color -->
|
199
|
+
<alpha></alpha> <!-- [0] (0 - 100) background alpha -->
|
200
|
+
<text_color></text_color> <!-- [text_color] (hex color code) button text and magnifying glass icon color -->
|
201
|
+
<text_color_hover></text_color_hover> <!-- [#BBBB00] (hex color code) button text and magnifying glass icon roll over color -->
|
202
|
+
<text_size></text_size> <!-- [text_size] (Number) button text size -->
|
203
|
+
<text></text> <!-- [Show all] (text) -->
|
204
|
+
</zoom_out_button>
|
205
|
+
|
206
|
+
<help> <!-- HELP button and balloon -->
|
207
|
+
<button> <!-- help button is only visible if balloon text is defined -->
|
208
|
+
<x></x> <!-- [] (Number) x position of help button, if not defined, will be aligned to right of chart area -->
|
209
|
+
<y></y> <!-- [] (Number) y position of help button, if not defined, will be aligned to top of chart area -->
|
210
|
+
<color></color> <!-- [#000000] (hex color code) background color -->
|
211
|
+
<alpha></alpha> <!-- [100] (0 - 100) background alpha -->
|
212
|
+
<text_color></text_color> <!-- [#FFFFFF] (hex color code) button text color -->
|
213
|
+
<text_color_hover></text_color_hover> <!-- [#BBBB00](hex color code) button text roll over color -->
|
214
|
+
<text_size></text_size> <!-- [] (Number) button text size -->
|
215
|
+
<text></text> <!-- [?] (text) -->
|
216
|
+
</button>
|
217
|
+
<balloon> <!-- help balloon -->
|
218
|
+
<color></color> <!-- [#000000] (hex color code) background color -->
|
219
|
+
<alpha></alpha> <!-- [100] (0 - 100) background alpha -->
|
220
|
+
<width></width> <!-- [300] (Number) -->
|
221
|
+
<text_color></text_color> <!-- [#FFFFFF] (hex color code) button text color -->
|
222
|
+
<text_size></text_size> <!-- [] (Number) button text size -->
|
223
|
+
<text><![CDATA[]]></text> <!-- [] (text) some html tags may be used (supports <b>, <i>, <u>, <font>, <br/>. Enter text between []: <![CDATA[your <b>bold</b> and <i>italic</i> text]]>-->
|
224
|
+
</balloon>
|
225
|
+
</help>
|
226
|
+
|
227
|
+
<export_as_image> <!-- export_as_image feature works only on a web server -->
|
228
|
+
<file></file> <!-- [] (filename) if you set filename here, context menu (then user right clicks on flash movie) "Export as image" will appear. This will allow user to export chart as an image. Collected image data will be posted to this file name (use amline/export.php or amline/export.aspx) -->
|
229
|
+
<target></target> <!-- [] (_blank, _top ...) target of a window in which export file must be called -->
|
230
|
+
<x></x> <!-- [0] (Number) x position of "Collecting data" text -->
|
231
|
+
<y></y> <!-- [] (Number) y position of "Collecting data" text. If not set, will be aligned to the bottom of flash movie -->
|
232
|
+
<color></color> <!-- [#BBBB00] (hex color code) background color of "Collecting data" text -->
|
233
|
+
<alpha></alpha> <!-- [0] (0 - 100) background alpha -->
|
234
|
+
<text_color></text_color> <!-- [text_color] (hex color code) -->
|
235
|
+
<text_size></text_size> <!-- [text_size] (Number) -->
|
236
|
+
</export_as_image>
|
237
|
+
|
238
|
+
<error_messages> <!-- "error_messages" settings will be applied for all error messages except the one which is showed if settings file wasn't found -->
|
239
|
+
<enabled></enabled> <!-- [true] (true / false) -->
|
240
|
+
<x></x> <!-- [] (Number) x position of error message. If not set, will be aligned to the center -->
|
241
|
+
<y></y> <!-- [] (Number) y position of error message. If not set, will be aligned to the center -->
|
242
|
+
<color></color> <!-- [#BBBB00] (hex color code) background color of error message -->
|
243
|
+
<alpha></alpha> <!-- [100] (0 - 100) background alpha -->
|
244
|
+
<text_color></text_color> <!-- [#FFFFFF] (hex color code) -->
|
245
|
+
<text_size></text_size> <!-- [text_size] (Number) -->
|
246
|
+
</error_messages>
|
247
|
+
|
248
|
+
<strings>
|
249
|
+
<no_data></no_data> <!-- [No data for selected period] (text) if data for selected period is missing, this message will be displayed -->
|
250
|
+
<export_as_image></export_as_image> <!-- [Export as image] (text) text for right click menu -->
|
251
|
+
<error_in_data_file></error_in_data_file> <!-- [Error in data file] (text) this text is displayed if there is an error in data file or there is no data in file. "There is no data" means that there should actually be at least one space in data file. If data file will be completly empty, it will display "error loading file" text -->
|
252
|
+
<collecting_data></collecting_data> <!-- [Collecting data] (text) this text is displayed while exporting chart to an image -->
|
253
|
+
<wrong_zoom_value></wrong_zoom_value> <!-- [Incorrect values] (text) this text is displayed if you set zoom through JavaScript and entered from or to value was not find between series -->
|
254
|
+
</strings>
|
255
|
+
|
256
|
+
|
257
|
+
<labels> <!-- LABELS -->
|
258
|
+
|
259
|
+
|
260
|
+
</labels>
|
261
|
+
|
262
|
+
<graphs> <!-- GRAPHS SETTINGS. These settings can also be specified in data file, as attributes of <graph>, in this case you can delete everything from <graphs> to </graphs> (including) -->
|
263
|
+
|
264
|
+
|
265
|
+
</graphs>
|
266
|
+
|
267
|
+
|
268
|
+
</settings>
|
@@ -0,0 +1,27 @@
|
|
1
|
+
require 'ruport'
|
2
|
+
require 'ruport/util'
|
3
|
+
|
4
|
+
class Example < Ruport::Renderer
|
5
|
+
stage :report
|
6
|
+
|
7
|
+
def setup
|
8
|
+
graph = Graph(%w[a b c d e])
|
9
|
+
graph.series [1,2,3,4,5], "foo"
|
10
|
+
graph.series [11,22,70,2,19], "bar"
|
11
|
+
self.data = graph
|
12
|
+
end
|
13
|
+
|
14
|
+
class PDF < Ruport::Formatter::PDF
|
15
|
+
renders :pdf, :for => Example
|
16
|
+
|
17
|
+
def build_report
|
18
|
+
add_text "Report With Graph", :font_size => 20
|
19
|
+
draw_graph(data, :x => 40, :y => 400, :width => 300, :height => 300)
|
20
|
+
|
21
|
+
render_pdf
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
end
|
26
|
+
|
27
|
+
Example.render_pdf(:file => "example.pdf")
|
data/example/graph_report.rb
CHANGED
@@ -2,19 +2,24 @@ require "ruport"
|
|
2
2
|
|
3
3
|
require "ruport/util"
|
4
4
|
|
5
|
-
class GraphReport < Ruport::Report
|
5
|
+
class GraphReport < Ruport::Report
|
6
6
|
|
7
7
|
renders_as_graph
|
8
8
|
|
9
|
-
def
|
10
|
-
graph =
|
11
|
-
graph.
|
12
|
-
graph.
|
9
|
+
def renderable_data(format)
|
10
|
+
graph = Graph(%w[a b c d e])
|
11
|
+
graph.series [1,2,3,4,5], "foo"
|
12
|
+
graph.series [11,22,70,2,19], "bar"
|
13
13
|
return graph
|
14
14
|
end
|
15
15
|
|
16
|
-
end
|
16
|
+
end
|
17
17
|
|
18
|
+
Ruport::Formatter::Template.create(:graph) do |t|
|
19
|
+
t.y_max = 100
|
20
|
+
end
|
21
|
+
|
22
|
+
# you need scruffy installed for svg, gruff for jpg / png
|
18
23
|
GraphReport.generate do |r|
|
19
|
-
r.save_as("foo.svg")
|
24
|
+
r.save_as("foo.svg", :template => :graph)
|
20
25
|
end
|
@@ -0,0 +1,23 @@
|
|
1
|
+
require "ruport"
|
2
|
+
|
3
|
+
require "ruport/util"
|
4
|
+
|
5
|
+
class GraphReport < Ruport::Report
|
6
|
+
|
7
|
+
renders_as_graph
|
8
|
+
|
9
|
+
def renderable_data(format)
|
10
|
+
graph = Graph(%w[a b c d e])
|
11
|
+
graph.series [1,2,3,4,5], "foo"
|
12
|
+
graph.series [11,22,70,2,19], "bar"
|
13
|
+
return graph
|
14
|
+
end
|
15
|
+
|
16
|
+
end
|
17
|
+
|
18
|
+
GraphReport.generate do |r|
|
19
|
+
r.as(:png, :title => "My Graph",
|
20
|
+
:labels => {0 => '2003', 2 => '2004', 4 => '2005'},
|
21
|
+
:file => "my_graph.png"
|
22
|
+
)
|
23
|
+
end
|
data/lib/ruport/util.rb
CHANGED
data/lib/ruport/util/graph.rb
CHANGED
@@ -7,180 +7,67 @@
|
|
7
7
|
#
|
8
8
|
begin
|
9
9
|
require "rubygems"
|
10
|
-
gem "ruport", ">=
|
10
|
+
gem "ruport", ">= 1.2.2"
|
11
11
|
rescue LoadError
|
12
12
|
nil
|
13
|
-
end
|
13
|
+
end
|
14
14
|
|
15
15
|
module Ruport
|
16
16
|
|
17
17
|
module Renderer::Hooks
|
18
18
|
module ClassMethods
|
19
|
-
def renders_as_graph
|
20
|
-
renders_with Ruport::Renderer::Graph
|
19
|
+
def renders_as_graph(options={})
|
20
|
+
renders_with Ruport::Renderer::Graph, options
|
21
21
|
end
|
22
22
|
end
|
23
23
|
end
|
24
|
-
|
25
|
-
def Graph(*args)
|
26
|
-
Graph.new(*args)
|
27
|
-
end
|
28
|
-
|
29
|
-
module_function :Graph
|
30
|
-
|
31
|
-
# This class implements the basic graphing engine for Ruport.
|
32
|
-
#
|
33
|
-
# == Supported Format Plugins
|
34
|
-
#
|
35
|
-
# * Formatter::XML
|
36
|
-
# * Formatter::SVG
|
37
|
-
#
|
38
|
-
# == Default layout options
|
39
|
-
#
|
40
|
-
# * height #=> 350
|
41
|
-
# * width #=> 500
|
42
|
-
# * style #=> :line
|
43
|
-
#
|
44
|
-
# == Plugin hooks called (in order)
|
45
|
-
#
|
46
|
-
# * prepare_graph
|
47
|
-
# * build_graph
|
48
|
-
# * finalize_graph
|
49
|
-
class Renderer::Graph < Renderer
|
50
|
-
|
51
|
-
options { |o| o.style = :line }
|
52
|
-
|
53
|
-
prepare :graph
|
54
|
-
|
55
|
-
stage :graph
|
56
|
-
|
57
|
-
finalize :graph
|
58
|
-
|
59
|
-
end
|
60
24
|
|
61
|
-
class
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
25
|
+
class Renderer
|
26
|
+
class Graph < Renderer
|
27
|
+
|
28
|
+
prepare :graph
|
29
|
+
stage :graph
|
30
|
+
finalize :graph
|
67
31
|
|
68
|
-
def initialize_copy(from)
|
69
|
-
@name = from.name.dup if from.name
|
70
|
-
end
|
71
|
-
end
|
72
|
-
|
73
|
-
def initialize(options={})
|
74
|
-
super({:record_class => Line}.merge(options))
|
75
|
-
end
|
76
|
-
|
77
|
-
def add_line(row_data,options={})
|
78
|
-
self << row_data
|
79
|
-
self[-1].name = options[:name]
|
80
|
-
end
|
81
|
-
|
82
|
-
def dup
|
83
|
-
obj = self.class.new(:column_names => column_names)
|
84
|
-
data.each { |r| obj.add_line(r.to_a,:name => r.name)}
|
85
|
-
return obj
|
86
|
-
end
|
87
|
-
|
88
|
-
end
|
89
|
-
|
90
|
-
class Formatter::SVG < Formatter
|
91
|
-
|
92
|
-
renders :svg, :for => Renderer::Graph
|
93
|
-
|
94
|
-
# a hash of Scruffy themes.
|
95
|
-
#
|
96
|
-
# You can use these by setting options.theme like this:
|
97
|
-
#
|
98
|
-
# Graph.render_svg(:theme => :mephisto)
|
99
|
-
#
|
100
|
-
# Available themes: ( :mephisto, :keynote, :ruby_blog )
|
101
|
-
#
|
102
|
-
def themes
|
103
|
-
{ :mephisto => Scruffy::Themes::Mephisto.new,
|
104
|
-
:keynote => Scruffy::Themes::Keynote.new,
|
105
|
-
:ruby_blog => Scruffy::Themes::RubyBlog.new }
|
106
|
-
end
|
107
|
-
|
108
|
-
# generates a scruffy graph object
|
109
|
-
def initialize
|
110
|
-
Ruport.quiet { require 'scruffy' }
|
111
|
-
|
112
|
-
@graph = Scruffy::Graph.new
|
113
32
|
end
|
33
|
+
end
|
34
|
+
|
35
|
+
module Data
|
36
|
+
class Graph < Table
|
114
37
|
|
115
|
-
|
116
|
-
attr_reader :graph
|
38
|
+
renders_as_graph
|
117
39
|
|
118
|
-
|
119
|
-
|
120
|
-
|
121
|
-
|
122
|
-
# title may be specified by options.title
|
123
|
-
#
|
124
|
-
def prepare_graph
|
125
|
-
@graph.title ||= options.title
|
126
|
-
@graph.theme = themes[options.theme] if options.theme
|
127
|
-
@graph.point_markers ||= data.column_names
|
128
|
-
end
|
40
|
+
def series(data,gid=nil)
|
41
|
+
self << data
|
42
|
+
self[-1].gid = gid
|
43
|
+
end
|
129
44
|
|
130
|
-
|
131
|
-
|
132
|
-
|
133
|
-
|
45
|
+
def initialize_copy(from)
|
46
|
+
super
|
47
|
+
data.zip(from.data).each do |new_row,old_row|
|
48
|
+
new_row.gid = old_row.gid
|
49
|
+
end
|
134
50
|
end
|
135
51
|
|
136
|
-
|
137
|
-
|
138
|
-
:min_value => options[:min], :max_value => options[:max]
|
139
|
-
)
|
140
|
-
end
|
141
|
-
|
142
|
-
# Uses Scruffy::Graph#add to add a new line to the graph.
|
143
|
-
#
|
144
|
-
# Line style is determined by options.style
|
145
|
-
#
|
146
|
-
def add_line(row,label)
|
147
|
-
@graph.add( options.style, label, row )
|
148
|
-
end
|
52
|
+
alias_method :x_labels, :column_names
|
53
|
+
alias_method :x_labels=, :column_names=
|
149
54
|
|
150
|
-
end
|
151
|
-
|
152
|
-
class Formatter::XML_SWF < Formatter
|
153
|
-
|
154
|
-
renders :xml_swf, :for => Renderer::Graph
|
155
|
-
|
156
|
-
def prepare_graph
|
157
|
-
gem "builder"
|
158
|
-
require "builder"
|
159
|
-
@builder = Builder::XmlMarkup.new(:indent => 2)
|
160
55
|
end
|
161
56
|
|
162
|
-
|
163
|
-
|
164
|
-
b.chart_type(options.style.to_s)
|
165
|
-
|
166
|
-
b.chart_data do |cd|
|
167
|
-
|
168
|
-
cd.row { |first|
|
169
|
-
first.null
|
170
|
-
data.column_names.each { |c| first.string(c) }
|
171
|
-
}
|
172
|
-
|
173
|
-
data.each_with_index { |r,i|
|
174
|
-
label = r.name || "Region #{i}"
|
175
|
-
cd.row { |data_row|
|
176
|
-
data_row.string(label)
|
177
|
-
r.each { |e| data_row.number(e) }
|
178
|
-
}
|
179
|
-
}
|
180
|
-
end
|
181
|
-
end
|
57
|
+
class GraphData < Ruport::Data::Record
|
58
|
+
attr_accessor :gid
|
182
59
|
end
|
60
|
+
end
|
61
|
+
|
62
|
+
end
|
183
63
|
|
64
|
+
module Kernel
|
65
|
+
def Graph(x_labels=[], data=[])
|
66
|
+
Ruport::Data::Graph.new(:column_names => x_labels, :data => data,
|
67
|
+
:record_class => Ruport::Data::GraphData )
|
184
68
|
end
|
69
|
+
end
|
185
70
|
|
186
|
-
|
71
|
+
require "ruport/util/graph/scruffy"
|
72
|
+
require "ruport/util/graph/amline"
|
73
|
+
require "ruport/util/graph/gruff"
|
@@ -0,0 +1,200 @@
|
|
1
|
+
require "rubygems"
|
2
|
+
require "hpricot"
|
3
|
+
|
4
|
+
class Ruport::Formatter
|
5
|
+
module Graph
|
6
|
+
class Amline < Ruport::Formatter
|
7
|
+
renders :amline, :for => Ruport::Renderer::Graph
|
8
|
+
|
9
|
+
def build_graph
|
10
|
+
generate_config_file
|
11
|
+
data_out << "<chart>"
|
12
|
+
data_out << "<xaxis>"
|
13
|
+
data.x_labels.each_with_index do |e,i|
|
14
|
+
data_out << %Q{<value xid="#{i}" show="true">#{e}</value>}
|
15
|
+
end
|
16
|
+
data_out << "</xaxis>"
|
17
|
+
data_out << "<graphs>"
|
18
|
+
data.each do |r|
|
19
|
+
data_out << %Q{<graph gid="#{r.gid}">}
|
20
|
+
r.each_with_index do |e,i|
|
21
|
+
data_out << %Q{<value xid="#{i}">#{e}</value>}
|
22
|
+
end
|
23
|
+
data_out << "</graph>"
|
24
|
+
end
|
25
|
+
data_out << "</graphs>"
|
26
|
+
|
27
|
+
data_out << "</chart>"
|
28
|
+
|
29
|
+
if options.data_file
|
30
|
+
File.open(options.data_file,"w") { |f| f << data_out }
|
31
|
+
end
|
32
|
+
|
33
|
+
if options.settings_file
|
34
|
+
File.open(options.settings_file,"w") { |f| f << settings_out }
|
35
|
+
end
|
36
|
+
|
37
|
+
end
|
38
|
+
|
39
|
+
def apply_template
|
40
|
+
options.templated_settings_proc = lambda do |s|
|
41
|
+
s.config do |c|
|
42
|
+
c.values.y_left.max = template.y_max
|
43
|
+
c.values.y_right.max = template.y_max
|
44
|
+
c.values.y_left.min = template.y_min
|
45
|
+
c.values.y_right.min = template.y_min
|
46
|
+
c.width = template.width
|
47
|
+
c.height = template.height
|
48
|
+
c.legend.enabled = template.show_legend
|
49
|
+
if template.config
|
50
|
+
template.config[c]
|
51
|
+
end
|
52
|
+
end
|
53
|
+
if template.graph_options
|
54
|
+
default = template.graph_options[:_default] || lambda { }
|
55
|
+
template.graph_options.each do |k,v|
|
56
|
+
next if k == :_default
|
57
|
+
s.graph(k,&default)
|
58
|
+
s.graph(k,&v)
|
59
|
+
end
|
60
|
+
end
|
61
|
+
end
|
62
|
+
end
|
63
|
+
|
64
|
+
|
65
|
+
def generate_config_file
|
66
|
+
settings = ::Amline::Settings.new
|
67
|
+
data.each do |r|
|
68
|
+
settings.add_graph(r.gid)
|
69
|
+
settings.graph(r.gid) { |g|
|
70
|
+
g.title = r.gid
|
71
|
+
}
|
72
|
+
end
|
73
|
+
|
74
|
+
options.templated_settings_proc[settings] if options.templated_settings_proc
|
75
|
+
format_settings[settings]
|
76
|
+
settings_out << settings.to_xml
|
77
|
+
end
|
78
|
+
|
79
|
+
def format_settings
|
80
|
+
options.format_settings || lambda {}
|
81
|
+
end
|
82
|
+
|
83
|
+
def output
|
84
|
+
{ :data => data_out, :settings => settings_out }
|
85
|
+
end
|
86
|
+
|
87
|
+
def data_out
|
88
|
+
@data_out ||= ""
|
89
|
+
end
|
90
|
+
|
91
|
+
def settings_out
|
92
|
+
@settings_out ||= ""
|
93
|
+
end
|
94
|
+
|
95
|
+
end
|
96
|
+
end
|
97
|
+
end
|
98
|
+
|
99
|
+
class Amline
|
100
|
+
|
101
|
+
class UnknownOption < StandardError; end
|
102
|
+
|
103
|
+
class BlankSlate
|
104
|
+
instance_methods.each { |m| undef_method m unless m =~ /^__/ }
|
105
|
+
end
|
106
|
+
|
107
|
+
class HpricotTraverser < BlankSlate
|
108
|
+
|
109
|
+
|
110
|
+
def initialize(some_root)
|
111
|
+
@root = some_root
|
112
|
+
end
|
113
|
+
|
114
|
+
attr :root
|
115
|
+
|
116
|
+
def method_missing(id, *args, &block)
|
117
|
+
if id.to_s =~ /^(\w+)=/
|
118
|
+
@root.at($1).innerHTML = args[0].to_s
|
119
|
+
elsif id.to_s =~ /^(\w+)!/
|
120
|
+
@root.at($1)
|
121
|
+
else
|
122
|
+
new_root = @root.at(id) or raise
|
123
|
+
HpricotTraverser.new(new_root)
|
124
|
+
end
|
125
|
+
rescue
|
126
|
+
raise UnknownOption
|
127
|
+
end
|
128
|
+
|
129
|
+
def ==(other)
|
130
|
+
@root == other
|
131
|
+
end
|
132
|
+
|
133
|
+
def inspect
|
134
|
+
@root
|
135
|
+
end
|
136
|
+
|
137
|
+
def to_s
|
138
|
+
@root.to_s
|
139
|
+
end
|
140
|
+
|
141
|
+
alias_method :to_xml, :to_s
|
142
|
+
|
143
|
+
end
|
144
|
+
|
145
|
+
class Settings
|
146
|
+
|
147
|
+
SETTINGS_FILE = File.join(Ruport::Util::BASEDIR, 'example', 'data',
|
148
|
+
'amline_settings.xml')
|
149
|
+
GRAPH_FILE = File.join(Ruport::Util::BASEDIR, 'example','data',
|
150
|
+
'amline_graph.xml')
|
151
|
+
|
152
|
+
def initialize(settings_file=SETTINGS_FILE,graph_file=GRAPH_FILE)
|
153
|
+
@config = HpricotTraverser.new(Hpricot(File.read(settings_file)))
|
154
|
+
@graph_file = graph_file
|
155
|
+
end
|
156
|
+
|
157
|
+
def config
|
158
|
+
yield @config.settings if block_given?
|
159
|
+
@config.settings
|
160
|
+
end
|
161
|
+
|
162
|
+
def add_label(label,options)
|
163
|
+
xml = %Q{
|
164
|
+
<label>
|
165
|
+
<x>#{options[:x]}</x>
|
166
|
+
<y>#{options[:y]}20</y>
|
167
|
+
<rotate>#{options[:rotate]}</rotate>
|
168
|
+
<width>#{options[:width]}</width>
|
169
|
+
<align>#{options[:align]}</align>
|
170
|
+
<text_color>#{options[:text_color]}</text_color>
|
171
|
+
<text_size>#{options[:text_size]}</text_size>
|
172
|
+
<text>
|
173
|
+
<![CDATA[#{label}]]>
|
174
|
+
</text>
|
175
|
+
</label>
|
176
|
+
}
|
177
|
+
@config.root.search("labels").append(xml)
|
178
|
+
end
|
179
|
+
|
180
|
+
def add_graph(gid)
|
181
|
+
new_graph = Hpricot(File.read(@graph_file))
|
182
|
+
new_graph.at("graph")["gid"] = gid
|
183
|
+
@config.root.search("graphs").append new_graph.to_s
|
184
|
+
end
|
185
|
+
|
186
|
+
def graph(gid)
|
187
|
+
yield HpricotTraverser.new(@config.root.search("graph[@gid=#{gid}]"))
|
188
|
+
end
|
189
|
+
|
190
|
+
def to_xml
|
191
|
+
@config.to_xml
|
192
|
+
end
|
193
|
+
|
194
|
+
def save(file)
|
195
|
+
File.open(file,"w") { |f| f << @config.to_s }
|
196
|
+
end
|
197
|
+
|
198
|
+
end
|
199
|
+
|
200
|
+
end
|
@@ -0,0 +1,59 @@
|
|
1
|
+
class Ruport::Formatter
|
2
|
+
module Graph
|
3
|
+
|
4
|
+
class Gruff < Ruport::Formatter
|
5
|
+
|
6
|
+
renders [:png,:jpg], :for => Ruport::Renderer::Graph
|
7
|
+
|
8
|
+
def initialize
|
9
|
+
Ruport.quiet { require 'gruff' }
|
10
|
+
end
|
11
|
+
|
12
|
+
def apply_template
|
13
|
+
options.min = template.y_min
|
14
|
+
options.max = template.y_max
|
15
|
+
options.width = template.width
|
16
|
+
options.height = template.height
|
17
|
+
end
|
18
|
+
|
19
|
+
def build_graph
|
20
|
+
graph = ::Gruff::Line.new("#{options.width || 800}x#{options.height || 600}")
|
21
|
+
graph.title = options.title if options.title
|
22
|
+
graph.labels = options.labels if options.labels
|
23
|
+
data.each do |r|
|
24
|
+
graph.data(r.gid,r.to_a)
|
25
|
+
end
|
26
|
+
|
27
|
+
graph.maximum_value = options.max if options.max
|
28
|
+
graph.minimum_value = options.min if options.min
|
29
|
+
|
30
|
+
output << graph.to_blob(format.to_s)
|
31
|
+
end
|
32
|
+
|
33
|
+
# Save the output to a file.
|
34
|
+
def save_output(filename)
|
35
|
+
File.open(filename,"wb") {|f| f << output }
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
class PDF
|
41
|
+
def draw_graph(graph, opts={})
|
42
|
+
x = opts[:x]
|
43
|
+
y = opts[:y]
|
44
|
+
width = opts[:width]
|
45
|
+
height = opts[:height]
|
46
|
+
g = graph.as(:jpg)
|
47
|
+
info = ::PDF::Writer::Graphics::ImageInfo.new(g)
|
48
|
+
|
49
|
+
# reduce the size of the image until it fits into the requested box
|
50
|
+
img_width, img_height =
|
51
|
+
fit_image_in_box(info.width,width,info.height,height)
|
52
|
+
|
53
|
+
# if the image is smaller than the box, calculate the white space buffer
|
54
|
+
x, y = add_white_space(x,y,img_width,width,img_height,height)
|
55
|
+
|
56
|
+
pdf_writer.add_image(g, x, y, img_width, img_height)
|
57
|
+
end
|
58
|
+
end
|
59
|
+
end
|
@@ -0,0 +1,71 @@
|
|
1
|
+
class Ruport::Formatter
|
2
|
+
module Graph
|
3
|
+
class Scruffy < Ruport::Formatter
|
4
|
+
|
5
|
+
renders :svg, :for => Ruport::Renderer::Graph
|
6
|
+
|
7
|
+
# a hash of Scruffy themes.
|
8
|
+
#
|
9
|
+
# You can use these by setting options.theme like this:
|
10
|
+
#
|
11
|
+
# Graph.render_svg(:theme => :mephisto)
|
12
|
+
#
|
13
|
+
# Available themes: ( :mephisto, :keynote, :ruby_blog )
|
14
|
+
#
|
15
|
+
def themes
|
16
|
+
{ :mephisto => Scruffy::Themes::Mephisto.new,
|
17
|
+
:keynote => Scruffy::Themes::Keynote.new,
|
18
|
+
:ruby_blog => Scruffy::Themes::RubyBlog.new }
|
19
|
+
end
|
20
|
+
|
21
|
+
# generates a scruffy graph object
|
22
|
+
def initialize
|
23
|
+
Ruport.quiet { require 'scruffy' }
|
24
|
+
@graph = ::Scruffy::Graph.new
|
25
|
+
end
|
26
|
+
|
27
|
+
# the Scruffy::Graph object
|
28
|
+
attr_reader :graph
|
29
|
+
|
30
|
+
# sets the graph title, theme, and column_names
|
31
|
+
#
|
32
|
+
# column_names are defined by the Data::Table,
|
33
|
+
# theme may be specified by options.theme (see SVG#themes)
|
34
|
+
# title may be specified by options.title
|
35
|
+
#
|
36
|
+
def prepare_graph
|
37
|
+
@graph.title ||= options.title
|
38
|
+
@graph.theme = themes[options.theme] if options.theme
|
39
|
+
@graph.point_markers ||= data.x_labels
|
40
|
+
end
|
41
|
+
|
42
|
+
# Generates an SVG using Scruffy.
|
43
|
+
def build_graph
|
44
|
+
|
45
|
+
data.each_with_index do |r,i|
|
46
|
+
add_line(r.to_a,r.gid||"series #{i+1}")
|
47
|
+
end
|
48
|
+
|
49
|
+
output << @graph.render(
|
50
|
+
:size => [options.width||500, options.height||300],
|
51
|
+
:min_value => options.min, :max_value => options.max
|
52
|
+
)
|
53
|
+
end
|
54
|
+
|
55
|
+
def apply_template
|
56
|
+
options.min = template.y_min
|
57
|
+
options.max = template.y_max
|
58
|
+
options.width = template.width
|
59
|
+
options.height = template.height
|
60
|
+
end
|
61
|
+
|
62
|
+
# Uses Scruffy::Graph#add to add a new line to the graph.
|
63
|
+
#
|
64
|
+
# Line style is determined by options.style
|
65
|
+
#
|
66
|
+
def add_line(row,label)
|
67
|
+
@graph.add( options.style || :line, label, row )
|
68
|
+
end
|
69
|
+
end
|
70
|
+
end
|
71
|
+
end
|
data/test/test_graph_renderer.rb
CHANGED
@@ -18,16 +18,11 @@ end
|
|
18
18
|
describe 'Graph Renderer' do
|
19
19
|
before :all do
|
20
20
|
@graph = Ruport::Renderer::Graph
|
21
|
-
@data =
|
21
|
+
@data = Graph(%w[a b c],[[1,2,3],[4,5,6]])
|
22
22
|
end
|
23
23
|
|
24
24
|
it 'should render' do
|
25
|
-
out = @graph.render_mock
|
26
|
-
r.options do |l|
|
27
|
-
l.style.should == :line
|
28
|
-
end
|
29
|
-
end
|
30
|
-
|
25
|
+
out = @graph.render_mock
|
31
26
|
out.should == 'preparebuildfinalize'
|
32
27
|
end
|
33
28
|
|
@@ -35,61 +30,5 @@ describe 'Graph Renderer' do
|
|
35
30
|
@graph.render_svg{|r| r.data = @data}.should_not be_nil
|
36
31
|
end
|
37
32
|
|
38
|
-
it 'should render XMLSWF via block' do
|
39
|
-
expected = <<-EOS
|
40
|
-
<chart>
|
41
|
-
<chart_type>line</chart_type>
|
42
|
-
<chart_data>
|
43
|
-
<row>
|
44
|
-
<null/>
|
45
|
-
</row>
|
46
|
-
<row>
|
47
|
-
<string>Region 0</string>
|
48
|
-
<number>1</number>
|
49
|
-
<number>2</number>
|
50
|
-
<number>3</number>
|
51
|
-
</row>
|
52
|
-
<row>
|
53
|
-
<string>Region 1</string>
|
54
|
-
<number>4</number>
|
55
|
-
<number>5</number>
|
56
|
-
<number>6</number>
|
57
|
-
</row>
|
58
|
-
</chart_data>
|
59
|
-
</chart>
|
60
|
-
EOS
|
61
|
-
|
62
|
-
@graph.render_xml_swf{|r| r.data = @data}.should == expected
|
63
|
-
end
|
64
33
|
|
65
|
-
it 'should render XMLSWF via add_line' do
|
66
|
-
expected = <<-EOS
|
67
|
-
<chart>
|
68
|
-
<chart_type>line</chart_type>
|
69
|
-
<chart_data>
|
70
|
-
<row>
|
71
|
-
<null/>
|
72
|
-
</row>
|
73
|
-
<row>
|
74
|
-
<string>Alpha</string>
|
75
|
-
<number>1</number>
|
76
|
-
<number>2</number>
|
77
|
-
<number>3</number>
|
78
|
-
</row>
|
79
|
-
<row>
|
80
|
-
<string>Beta</string>
|
81
|
-
<number>4</number>
|
82
|
-
<number>5</number>
|
83
|
-
<number>6</number>
|
84
|
-
</row>
|
85
|
-
</chart_data>
|
86
|
-
</chart>
|
87
|
-
EOS
|
88
|
-
|
89
|
-
graph = Ruport::Graph()
|
90
|
-
graph.add_line [1,2,3], :name => "Alpha"
|
91
|
-
graph.add_line [4,5,6], :name => "Beta"
|
92
|
-
|
93
|
-
graph.to_xml_swf.should == expected
|
94
|
-
end
|
95
34
|
end
|
@@ -0,0 +1,45 @@
|
|
1
|
+
require 'test/helper'
|
2
|
+
require 'ruport/util/graph/amline'
|
3
|
+
require 'hpricot'
|
4
|
+
|
5
|
+
describe "A simple traversal" do
|
6
|
+
|
7
|
+
before :each do
|
8
|
+
xml = "<foo><bar><baz></baz></bar></foo>"
|
9
|
+
@root = Hpricot(xml)
|
10
|
+
@traverser = Amline::HpricotTraverser.new(@root)
|
11
|
+
end
|
12
|
+
|
13
|
+
it "should allow accessing nested attributes" do
|
14
|
+
@root.at("foo").at("bar").at("baz").should ==
|
15
|
+
@traverser.foo.bar.baz.root
|
16
|
+
end
|
17
|
+
|
18
|
+
it "should allow setting nested attributes" do
|
19
|
+
@traverser.foo.bar.baz = "kittens"
|
20
|
+
@root.at("foo/bar/baz").innerHTML.should == "kittens"
|
21
|
+
end
|
22
|
+
|
23
|
+
it "should be a true bro about missing elements" do
|
24
|
+
|
25
|
+
lambda { @traverser.foo.bart.baz }.
|
26
|
+
should raise_error(Amline::UnknownOption)
|
27
|
+
|
28
|
+
lambda { @traverser.foo.bart = "baz" }.
|
29
|
+
should raise_error(Amline::UnknownOption)
|
30
|
+
|
31
|
+
lambda { @traverser.foot }.
|
32
|
+
should raise_error(Amline::UnknownOption)
|
33
|
+
|
34
|
+
end
|
35
|
+
|
36
|
+
it "should allow accessing the Hpricot elements via !" do
|
37
|
+
@traverser.foo!().class.should == Hpricot::Elem
|
38
|
+
end
|
39
|
+
|
40
|
+
it "should convert values to strings when setting tags" do
|
41
|
+
@traverser.foo.bar.baz = 10
|
42
|
+
@traverser.foo.bar.baz!().innerHTML.should == "10"
|
43
|
+
end
|
44
|
+
|
45
|
+
end
|
metadata
CHANGED
@@ -1,10 +1,10 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
|
-
rubygems_version: 0.9.
|
2
|
+
rubygems_version: 0.9.4
|
3
3
|
specification_version: 1
|
4
4
|
name: ruport-util
|
5
5
|
version: !ruby/object:Gem::Version
|
6
|
-
version: 0.
|
7
|
-
date: 2007-
|
6
|
+
version: 0.9.0
|
7
|
+
date: 2007-11-09 00:00:00 -05:00
|
8
8
|
summary: A set of tools and helper libs for Ruby Reports
|
9
9
|
require_paths:
|
10
10
|
- lib
|
@@ -30,18 +30,23 @@ authors:
|
|
30
30
|
- Gregory Brown
|
31
31
|
files:
|
32
32
|
- example/data
|
33
|
+
- example/draw_graph.rb
|
33
34
|
- example/form.rb
|
34
35
|
- example/graph_report.rb
|
36
|
+
- example/gruff_report.rb
|
35
37
|
- example/invoice_report.rb
|
36
38
|
- example/mailer.rb
|
37
39
|
- example/managed_report.rb
|
38
40
|
- example/ods.rb
|
41
|
+
- example/data/amline_graph.xml
|
42
|
+
- example/data/amline_settings.xml
|
39
43
|
- example/data/blank.ods
|
40
44
|
- lib/ruport
|
41
45
|
- lib/ruport/util
|
42
46
|
- lib/ruport/util.rb
|
43
47
|
- lib/ruport/util/bench.rb
|
44
48
|
- lib/ruport/util/generator.rb
|
49
|
+
- lib/ruport/util/graph
|
45
50
|
- lib/ruport/util/graph.rb
|
46
51
|
- lib/ruport/util/invoice.rb
|
47
52
|
- lib/ruport/util/mailer.rb
|
@@ -49,12 +54,16 @@ files:
|
|
49
54
|
- lib/ruport/util/pdf
|
50
55
|
- lib/ruport/util/report.rb
|
51
56
|
- lib/ruport/util/report_manager.rb
|
57
|
+
- lib/ruport/util/graph/amline.rb
|
58
|
+
- lib/ruport/util/graph/gruff.rb
|
59
|
+
- lib/ruport/util/graph/scruffy.rb
|
52
60
|
- lib/ruport/util/pdf/form.rb
|
53
61
|
- test/helper
|
54
62
|
- test/helper.rb
|
55
63
|
- test/samples
|
56
64
|
- test/test_format_ods.rb
|
57
65
|
- test/test_graph_renderer.rb
|
66
|
+
- test/test_hpricot_traverser.rb
|
58
67
|
- test/test_invoice.rb
|
59
68
|
- test/test_mailer.rb
|
60
69
|
- test/test_report.rb
|
@@ -70,6 +79,7 @@ files:
|
|
70
79
|
test_files:
|
71
80
|
- test/test_format_ods.rb
|
72
81
|
- test/test_graph_renderer.rb
|
82
|
+
- test/test_hpricot_traverser.rb
|
73
83
|
- test/test_invoice.rb
|
74
84
|
- test/test_mailer.rb
|
75
85
|
- test/test_report.rb
|
@@ -97,16 +107,7 @@ dependencies:
|
|
97
107
|
requirements:
|
98
108
|
- - ">="
|
99
109
|
- !ruby/object:Gem::Version
|
100
|
-
version: 1.2.
|
101
|
-
version:
|
102
|
-
- !ruby/object:Gem::Dependency
|
103
|
-
name: scruffy
|
104
|
-
version_requirement:
|
105
|
-
version_requirements: !ruby/object:Gem::Version::Requirement
|
106
|
-
requirements:
|
107
|
-
- - ">="
|
108
|
-
- !ruby/object:Gem::Version
|
109
|
-
version: 0.2.2
|
110
|
+
version: 1.2.2
|
110
111
|
version:
|
111
112
|
- !ruby/object:Gem::Dependency
|
112
113
|
name: mailfactory
|