libisi 0.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (91) hide show
  1. data/LICENSE +677 -0
  2. data/Manifest +89 -0
  3. data/Rakefile +34 -0
  4. data/lib/inifile.rb +119 -0
  5. data/lib/libisi.rb +948 -0
  6. data/lib/libisi/attribute.rb +32 -0
  7. data/lib/libisi/attribute/activerecord.rb +34 -0
  8. data/lib/libisi/attribute/base.rb +33 -0
  9. data/lib/libisi/base.rb +109 -0
  10. data/lib/libisi/bridge.rb +21 -0
  11. data/lib/libisi/bridge/base.rb +23 -0
  12. data/lib/libisi/bridge/java.rb +71 -0
  13. data/lib/libisi/bridge/python.rb +37 -0
  14. data/lib/libisi/cache.rb +21 -0
  15. data/lib/libisi/cache/base.rb +67 -0
  16. data/lib/libisi/cache/file_cache.rb +24 -0
  17. data/lib/libisi/chart.rb +21 -0
  18. data/lib/libisi/chart/base.rb +320 -0
  19. data/lib/libisi/chart/jfreechart.rb +682 -0
  20. data/lib/libisi/chart/jfreechart_generator.rb +206 -0
  21. data/lib/libisi/color.rb +21 -0
  22. data/lib/libisi/color/base.rb +66 -0
  23. data/lib/libisi/color/colortools.rb +92 -0
  24. data/lib/libisi/color/java.rb +44 -0
  25. data/lib/libisi/concept.rb +33 -0
  26. data/lib/libisi/concept/activerecord.rb +39 -0
  27. data/lib/libisi/concept/base.rb +58 -0
  28. data/lib/libisi/doc.rb +35 -0
  29. data/lib/libisi/doc/base.rb +414 -0
  30. data/lib/libisi/doc/html.rb +85 -0
  31. data/lib/libisi/doc/text.rb +98 -0
  32. data/lib/libisi/doc/wiki.rb +55 -0
  33. data/lib/libisi/environment.rb +21 -0
  34. data/lib/libisi/environment/base.rb +36 -0
  35. data/lib/libisi/environment/http.rb +105 -0
  36. data/lib/libisi/environment/rails.rb +27 -0
  37. data/lib/libisi/environment/root.rb +23 -0
  38. data/lib/libisi/fake_logger/logger.rb +61 -0
  39. data/lib/libisi/function/base.rb +30 -0
  40. data/lib/libisi/hal.rb +558 -0
  41. data/lib/libisi/instance.rb +27 -0
  42. data/lib/libisi/instance/activerecord.rb +21 -0
  43. data/lib/libisi/instance/base.rb +42 -0
  44. data/lib/libisi/log.rb +237 -0
  45. data/lib/libisi/mail/base.rb +32 -0
  46. data/lib/libisi/mail/tmail.rb +120 -0
  47. data/lib/libisi/parameter/base.rb +41 -0
  48. data/lib/libisi/property.rb +27 -0
  49. data/lib/libisi/property/base.rb +28 -0
  50. data/lib/libisi/reciever/base.rb +31 -0
  51. data/lib/libisi/reciever/socket.rb +31 -0
  52. data/lib/libisi/relation.rb +23 -0
  53. data/lib/libisi/request.rb +22 -0
  54. data/lib/libisi/request/base.rb +29 -0
  55. data/lib/libisi/request/http.rb +129 -0
  56. data/lib/libisi/response/base.rb +27 -0
  57. data/lib/libisi/task/base.rb +27 -0
  58. data/lib/libisi/task/http.rb +90 -0
  59. data/lib/libisi/tee.rb +296 -0
  60. data/lib/libisi/ui/base.rb +116 -0
  61. data/lib/libisi/ui/console.rb +238 -0
  62. data/lib/libisi/ui/kde.rb +94 -0
  63. data/lib/libisi/ui/nobody.rb +29 -0
  64. data/lib/libisi/ui/rails.rb +150 -0
  65. data/lib/libisi/ui/x11.rb +55 -0
  66. data/lib/libisi/uri.rb +42 -0
  67. data/lib/libisi/uri/activerecord.rb +152 -0
  68. data/lib/libisi/uri/base.rb +115 -0
  69. data/lib/libisi/uri/file.rb +43 -0
  70. data/lib/libisi/uri/ldap.rb +72 -0
  71. data/lib/libisi/uri/mysql.rb +98 -0
  72. data/lib/libisi/value.rb +31 -0
  73. data/lib/libisi/value/attribute_value.rb +19 -0
  74. data/lib/libisi/value/base.rb +55 -0
  75. data/lib/libisi/value/property_value.rb +19 -0
  76. data/lib/libisi/value/relation_value.rb +19 -0
  77. data/lib/ordered_hash.rb +228 -0
  78. data/libisi.gemspec +31 -0
  79. data/test/bridge_test.rb +77 -0
  80. data/test/cache_test.rb +65 -0
  81. data/test/chart_test.rb +179 -0
  82. data/test/color_test.rb +64 -0
  83. data/test/concept_test.rb +56 -0
  84. data/test/doc_test.rb +172 -0
  85. data/test/fixtures/test.db +0 -0
  86. data/test/ordered_hash_test.rb +39 -0
  87. data/test/profile_test.rb +36 -0
  88. data/test/request_test.rb +121 -0
  89. data/test/test +0 -0
  90. data/test/ui_test.rb +62 -0
  91. metadata +244 -0
@@ -0,0 +1,24 @@
1
+ # Copyright (C) 2007-2010 Logintas AG Switzerland
2
+ #
3
+ # This file is part of Libisi.
4
+ #
5
+ # Libisi is free software: you can redistribute it and/or modify
6
+ # it under the terms of the GNU General Public License as published by
7
+ # the Free Software Foundation, either version 3 of the License, or
8
+ # (at your option) any later version.
9
+ #
10
+ # Libisi is distributed in the hope that it will be useful,
11
+ # but WITHOUT ANY WARRANTY; without even the implied warranty of
12
+ # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13
+ # GNU General Public License for more details.
14
+ #
15
+ # You should have received a copy of the GNU General Public License
16
+ # along with Libisi. If not, see <http://www.gnu.org/licenses/>.
17
+
18
+ class FileCache < BaseCache
19
+
20
+ def initialize(file, options = {})
21
+
22
+ end
23
+
24
+ end
@@ -0,0 +1,21 @@
1
+ # Copyright (C) 2007-2010 Logintas AG Switzerland
2
+ #
3
+ # This file is part of Libisi.
4
+ #
5
+ # Libisi is free software: you can redistribute it and/or modify
6
+ # it under the terms of the GNU General Public License as published by
7
+ # the Free Software Foundation, either version 3 of the License, or
8
+ # (at your option) any later version.
9
+ #
10
+ # Libisi is distributed in the hope that it will be useful,
11
+ # but WITHOUT ANY WARRANTY; without even the implied warranty of
12
+ # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13
+ # GNU General Public License for more details.
14
+ #
15
+ # You should have received a copy of the GNU General Public License
16
+ # along with Libisi. If not, see <http://www.gnu.org/licenses/>.
17
+
18
+ require "libisi/base.rb"
19
+ class Chart < Base
20
+
21
+ end
@@ -0,0 +1,320 @@
1
+ # Copyright (C) 2007-2010 Logintas AG Switzerland
2
+ #
3
+ # This file is part of Libisi.
4
+ #
5
+ # Libisi is free software: you can redistribute it and/or modify
6
+ # it under the terms of the GNU General Public License as published by
7
+ # the Free Software Foundation, either version 3 of the License, or
8
+ # (at your option) any later version.
9
+ #
10
+ # Libisi is distributed in the hope that it will be useful,
11
+ # but WITHOUT ANY WARRANTY; without even the implied warranty of
12
+ # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13
+ # GNU General Public License for more details.
14
+ #
15
+ # You should have received a copy of the GNU General Public License
16
+ # along with Libisi. If not, see <http://www.gnu.org/licenses/>.
17
+
18
+ class BaseChart
19
+
20
+ BAR_TYPES = [:bar, :pie, :gantt, :xy]
21
+
22
+ attr_accessor :title, :height, :width, :stacked, :type, :legend_rotation, :legend_chart_ratio
23
+
24
+ DEFAULT_HEIGHT = 480
25
+ DEFAULT_WIDTH = 640
26
+ DEFAULT_STACKED = false
27
+ DEFAULT_CHART_TYPE = :bar
28
+ DEFAULT_LEGEND_ROTATION = 0.0 #Math::PI / 6.0
29
+ DEFAULT_LEGEND_CHART_RATIO = 0.4
30
+
31
+ def initialize(options = {})
32
+ @height = DEFAULT_HEIGHT
33
+ @width = DEFAULT_WIDTH
34
+ @stacked = DEFAULT_STACKED
35
+ @legend_chart_ratio = DEFAULT_LEGEND_CHART_RATIO
36
+ @options = options
37
+ @options ||= {}
38
+ @axes = []
39
+ end
40
+
41
+ def display_legend; data_dimension > 1; end
42
+ def enable_urls; false; end
43
+ def enable_tooltips; true; end
44
+ def orientation
45
+ return @orientation if @orientation
46
+ if @type == :gantt
47
+ :horizontal
48
+ else
49
+ :vertical
50
+ end
51
+ end
52
+ def legend_rotation; @legend_rotation or DEFAULT_LEGEND_ROTATION; end
53
+
54
+ # data
55
+ def save(filename, options = {})
56
+ create_chart unless @chart
57
+ case filename
58
+ when /.html$/
59
+ Pathname.new(filename).open("w") {|f|
60
+ f.write(data("text/html",options))
61
+ }
62
+ when /.png$/
63
+ Pathname.new(filename).open("w") {|f| f.write(data("image/png",options))}
64
+ else
65
+ raise "Dont know how to save to file #{filename}"
66
+ end
67
+ end
68
+
69
+ def ranges
70
+ @ranges
71
+ end
72
+
73
+ # axes
74
+ def xaxis; @axes[0]; end
75
+ def xaxis=(val); @axes[0] = val; end
76
+ def yaxis; @axes[1]; end
77
+ def yaxis=(val); @axes[1] = val; end
78
+ def zaxis; @axes[2]; end
79
+ def zaxis=(val); @axes[2] = val; end
80
+
81
+ # markers
82
+ def mark(name, from = nil, to = nil, options = {})
83
+ raise "Marker value may not be nil" if
84
+ from.nil? and !block_given?
85
+ if to.class == Hash
86
+ options = to
87
+ to = nil
88
+ end
89
+
90
+ if name.class == Hash
91
+ options = name
92
+ name = nil
93
+ end
94
+
95
+ options ||= {}
96
+ options = options.dup
97
+
98
+ if from.nil?
99
+ options[:type] = :category
100
+ options[:key] = name
101
+ else
102
+ if to.nil?
103
+ options[:type] = :value
104
+ options[:value] = from
105
+ else
106
+ options[:type] = :interval
107
+ options[:start] = from
108
+ options[:end] = to
109
+ end
110
+ end
111
+ options[:name] = name
112
+
113
+ if block_given?
114
+ # this is a domain marker
115
+ # add all values that has been added
116
+ # yield
117
+ options[:axis] = :domain
118
+ previous_keys = @current_serie.keys.dup
119
+ yield
120
+ current_keys = @current_serie.keys.dup
121
+ new_keys = current_keys.reject {|k| previous_keys.include?(k)}
122
+
123
+ @current_range_options[:markers] ||= []
124
+ new_keys.each {|k|
125
+ o = options.dup
126
+ o[:key] = k
127
+ @current_range_options[:markers] << o
128
+ }
129
+ else
130
+ options[:axis] = :range
131
+ add_to = @options
132
+ add_to = @current_range_options if @current_range_options
133
+
134
+ add_to[:markers] ||= []
135
+ add_to[:markers] << options
136
+ end
137
+ end
138
+ alias :marker :mark
139
+
140
+ # Adding values
141
+ def range(name = nil, options = {})
142
+ @range_options ||= {}
143
+ @ranges ||= OrderedHash.new
144
+
145
+ raise "Range #{name.inspect} already exist" unless
146
+ @ranges[name].nil?
147
+
148
+ @range_options[name] = options
149
+ @current_range_options = @range_options[name]
150
+
151
+ @current_range = OrderedHash.new
152
+ @ranges[name] = @current_range
153
+ yield
154
+ @current_range = nil
155
+ end
156
+
157
+ def serie(name = nil, options = {})
158
+ unless @current_range
159
+ range {
160
+ return serie(name) {
161
+ yield
162
+ }
163
+ }
164
+ end
165
+
166
+ @series_options ||= {}
167
+ @series_options[name] = {}
168
+
169
+ @current_serie = OrderedHash.new
170
+ @current_range[name] = @current_serie
171
+ yield
172
+ @current_serie = nil
173
+ end
174
+
175
+ def value(name, value)
176
+ @current_serie[name] = value
177
+ end
178
+
179
+ def time_span(name, start_time, end_time, options = {})
180
+ raise "No current serie." unless @current_serie
181
+ @type ||= :gantt
182
+ raise "No time_spans allowed for chart type #{@type}" unless
183
+ @type == :gantt
184
+
185
+ new_span = {:start => start_time, :end => end_time}
186
+ new_span[:percentage] = options[:percentage] if options[:percentage]
187
+
188
+ old_span = @current_timespan
189
+ if @current_timespan
190
+ # ok, we are already in a timespan block
191
+ # add children
192
+ @current_timespan[:children] ||= OrderedHash.new
193
+ raise "There is already a timespan called #{name.inspect}" if
194
+ @current_timespan[:children][name]
195
+ @current_timespan[:children][name] = new_span
196
+ else
197
+ @current_timespan = new_span
198
+ raise "There is already a timespan called #{name.inspect}" if
199
+ @current_serie[name]
200
+ @current_serie[name] = @current_timespan
201
+ end
202
+
203
+ yield if block_given?
204
+ @current_timespan = old_span
205
+ new_span
206
+ end
207
+
208
+ def data_dimension
209
+ # RANGE x SERIE x CATEGORY x ARRAY
210
+ return 0 unless @ranges
211
+ return 4 if @ranges.keys.length > 1
212
+ return 3 if @ranges[0].nil? or @ranges[0].keys > 1
213
+ return 2 if @ranges[0][0].nil? or @ranges[0][0].keys > 1
214
+ return 1
215
+ end
216
+
217
+ # old fashioned loading from alois
218
+ def load(input)
219
+ input = input.split("\n").reverse
220
+ # System.out.println("Chart title?");
221
+ @title = input.pop
222
+
223
+ # System.out.println("Width?");
224
+ @options[:width] = input.pop.to_i
225
+
226
+ # System.out.println("Height?");
227
+ @options[:height] = input.pop.to_i
228
+
229
+ # System.out.println("X-Axis?");
230
+ @axes = []
231
+ @axes[0] = input.pop
232
+
233
+ # System.out.println("Y-Axis?");
234
+ @axes[1] = input.pop
235
+
236
+ # System.out.println("Series count?");
237
+ serie_count = input.pop.to_i
238
+
239
+ # System.out.println("Range count?");
240
+ range_count = input.pop.to_i
241
+
242
+ @ranges = OrderedHash.new
243
+ range_count.times {|range|
244
+ range_name = input.pop
245
+ range_name = nil if range_name == "<<NULL>>"
246
+
247
+ current_range = OrderedHash.new
248
+ @ranges[range_name] = current_range
249
+
250
+ serie_count.times {|serie|
251
+ serie_name = input.pop
252
+ serie_name = nil if serie_name == "<<NULL>>"
253
+ $log.debug("Serie name: #{category_name}")
254
+
255
+ current_serie = OrderedHash.new(serie_name)
256
+ current_range[serie_name] = current_serie
257
+
258
+ rowCount = input.pop.to_i
259
+ columnCount = input.pop.to_i
260
+
261
+ rowCount.times {|row|
262
+ category_name = input.pop
263
+ category_name = nil if category_name == "<<NULL>>"
264
+ $log.debug("Category name: #{category_name}")
265
+
266
+ current_category = []
267
+ current_serie[category_name] = current_category
268
+
269
+ columnCount.times {|col|
270
+ current_category << input.pop
271
+ }
272
+ }
273
+ }
274
+ }
275
+
276
+
277
+ end
278
+
279
+ def create_chart(type = nil, options = {})
280
+ t = (type or @type or DEFAULT_CHART_TYPE)
281
+
282
+ case options[:combined_axis]
283
+ when nil, :x, "x",:xaxis, "xaxis", :domain, "domain"
284
+ options[:combined_axis] = :domain
285
+ when nil, :y, "y",:yaxis, "yaxis", :range, "range"
286
+ options[:combined_axis] = :range
287
+ else
288
+ raise "Unexpected combined axis option: #{options[:combined_axis].inspect}"
289
+ end
290
+
291
+ case t
292
+ when :bar, :line, :gantt, :pie
293
+ plot = nil
294
+ case data_dimension
295
+ when 4
296
+ plot = create_combined_plot(@ranges, options[:combined_axis])
297
+ when 3
298
+ plot = create_plot(nil,@ranges.values[0])
299
+ else
300
+ raise "Unexpected data dimension #{data_dimension}"
301
+ end
302
+
303
+ create_chart_implementation(plot)
304
+ return @chart
305
+ when :xy
306
+ raise "Not implemented yet chart type #{t}"
307
+ else
308
+ raise "Unknown chart type #{t}"
309
+ end
310
+ end
311
+
312
+ def create_combined_plot(data, combination_axis = :category)
313
+ create_combined_plot_implementation(data,combination_axis)
314
+ end
315
+
316
+ def create_plot(name, data)
317
+ create_plot_implementation(name,data)
318
+ end
319
+
320
+ end
@@ -0,0 +1,682 @@
1
+ # Copyright (C) 2007-2010 Logintas AG Switzerland
2
+ #
3
+ # This file is part of Libisi.
4
+ #
5
+ # Libisi is free software: you can redistribute it and/or modify
6
+ # it under the terms of the GNU General Public License as published by
7
+ # the Free Software Foundation, either version 3 of the License, or
8
+ # (at your option) any later version.
9
+ #
10
+ # Libisi is distributed in the hope that it will be useful,
11
+ # but WITHOUT ANY WARRANTY; without even the implied warranty of
12
+ # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13
+ # GNU General Public License for more details.
14
+ #
15
+ # You should have received a copy of the GNU General Public License
16
+ # along with Libisi. If not, see <http://www.gnu.org/licenses/>.
17
+
18
+ require "libisi/bridge/java.rb"
19
+ require "libisi/chart/base.rb"
20
+ require "libisi/chart/jfreechart_generator.rb"
21
+ require "libisi/color.rb"
22
+ require "stringio"
23
+
24
+ JavaBridge.load("/usr/share/java/jfreechart.jar")
25
+
26
+ [
27
+ "org.jfree.ui.RectangleAnchor",
28
+ "org.jfree.ui.TextAnchor",
29
+ "org.jfree.ui.Layer",
30
+ "org.jfree.chart.plot.CategoryMarker",
31
+ "org.jfree.chart.plot.IntervalMarker",
32
+ "org.jfree.chart.plot.ValueMarker",
33
+ "org.jfree.chart.LegendItemCollection",
34
+ "org.jfree.chart.axis.CategoryLabelPositions",
35
+ "org.jfree.chart.axis.CategoryLabelPosition",
36
+ "org.jfree.chart.axis.CategoryLabelWidthType",
37
+ "org.jfree.chart.ChartColor",
38
+ "java.awt.image.BufferedImage",
39
+ "java.awt.Rectangle",
40
+ "java.awt.TexturePaint",
41
+ "java.awt.Font",
42
+ "org.jfree.text.TextBlockAnchor",
43
+ "org.jfree.util.TableOrder",
44
+ "org.jfree.chart.JFreeChart",
45
+ "org.jfree.chart.ChartFactory",
46
+ "org.jfree.chart.axis.CategoryAxis",
47
+ "org.jfree.chart.axis.ExtendedCategoryAxis",
48
+ "org.jfree.chart.axis.NumberAxis",
49
+ "org.jfree.chart.plot.XYPlot",
50
+ "org.jfree.chart.entity.StandardEntityCollection",
51
+ "org.jfree.chart.ChartUtilities",
52
+ "org.jfree.chart.plot.CombinedRangeCategoryPlot",
53
+ "org.jfree.chart.plot.CombinedDomainCategoryPlot",
54
+ "org.jfree.chart.plot.CombinedRangeXYPlot",
55
+ "org.jfree.chart.plot.CombinedDomainXYPlot",
56
+ "org.jfree.chart.axis.DateAxis",
57
+ # produces already initialized constant DEFAULT_TOOL_TIP_FORMAT_STRING at javabridge.import
58
+ # but this class is not needed
59
+ # "org.jfree.chart.labels.IntervalCategoryToolTipGenerator",
60
+ "org.jfree.chart.axis.QuarterDateFormat",
61
+ "java.text.DateFormat",
62
+ "org.jfree.chart.plot.CategoryPlot",
63
+ "org.jfree.chart.plot.PlotOrientation",
64
+
65
+ # rendering
66
+ "org.jfree.chart.renderer.category.IntervalBarRenderer",
67
+ "org.jfree.chart.renderer.category.GanttRenderer",
68
+ "org.jfree.chart.renderer.xy.StackedXYAreaRenderer2",
69
+ "org.jfree.chart.renderer.category.StackedBarRenderer",
70
+ "org.jfree.chart.ChartRenderingInfo",
71
+ "org.jfree.chart.renderer.category.BarRenderer",
72
+ "org.jfree.chart.plot.MultiplePiePlot",
73
+ "org.jfree.chart.renderer.xy.XYBarRenderer",
74
+
75
+ # datasets
76
+ "org.jfree.data.category.DefaultCategoryDataset",
77
+ "org.jfree.data.xy.CategoryTableXYDataset",
78
+
79
+ "org.jfree.data.gantt.Task",
80
+ "org.jfree.data.gantt.TaskSeries",
81
+ "org.jfree.data.gantt.TaskSeriesCollection",
82
+
83
+ "org.jfree.data.time.SimpleTimePeriod",
84
+ "java.util.Calendar"
85
+ ].each {|klass|
86
+ if klass == "org.jfree.chart.labels.IntervalCategoryToolTipGenerator"
87
+ p "kde" if defined?(DEFAULT_TOOL_TIP_FORMAT_STRING)
88
+ p "here"
89
+ end
90
+
91
+ eval("#{klass.split(".")[-1]} = JavaBridge.import(klass)")
92
+ if klass == "org.jfree.chart.labels.IntervalCategoryToolTipGenerator"
93
+ p "end"
94
+ end
95
+ }
96
+
97
+ # same space
98
+ [
99
+ "java.util.Date",
100
+ "java.io.File",
101
+ ].each {|klass|
102
+ eval("J#{klass.split(".")[-1]} = JavaBridge.import(klass, :prefix => 'J')")
103
+ }
104
+
105
+
106
+ class JfreechartChart < BaseChart
107
+
108
+ def data(mime_type, options = {})
109
+ raise "No chart defined" unless @chart
110
+
111
+ temp_file {|temp_image_file|
112
+ info = ChartRenderingInfo.new(StandardEntityCollection.new)
113
+ ChartUtilities.saveChartAsPNG(JFile.new(temp_image_file.to_s),
114
+ @chart, width.to_i, height.to_i, info);
115
+
116
+ case mime_type
117
+ when "image/png"
118
+ temp_image_file.open("r").read
119
+ when "text/html"
120
+ image_file = nil
121
+ image_file = Pathname.new(options[:image_file]) if
122
+ image_file.nil? and options[:image_file]
123
+ image_file = Pathname.new(image_path) + "jfreechart.png" if
124
+ image_file.nil? and options[:image_path]
125
+
126
+ image_map_file = nil
127
+ image_map_file = Pathname.new(option[:image_map_file]) if
128
+ image_map_file.nil? and options[:image_map_file]
129
+
130
+ image_map_file.open("w") {|f|
131
+ f.write(ChartUtilities.getImageMap("chart", info))
132
+ } if image_map_file
133
+
134
+
135
+ html_file = StringIO.new
136
+ # write an HTML page incorporating the image with an image map
137
+ if options[:layout].nil? or !options[:layout]
138
+ html_file.write("<HEAD><TITLE>JFreeChart Image Map</TITLE></HEAD>\n")
139
+ html_file.write("<BODY>\n");
140
+ end
141
+ html_file.write(ChartUtilities.getImageMap("chart", info));
142
+
143
+ if image_file
144
+ FileUtils.mv(temp_image_file, image_file)
145
+ html_file.write("<IMG SRC=\"#{image_file.to_s}\" " +
146
+ "WIDTH=\"#{width}\" HEIGHT=\"#{height}\" BORDER=\"0\" USEMAP=\"#chart\">\n")
147
+ else
148
+ image_data = Base64.encode64(temp_image_file.open("r").read)
149
+ html_file.write("<IMG SRC=\"data:image/png;base64,#{image_data}\" " +
150
+ "WIDTH=\"#{width}\" HEIGHT=\"#{height}\" BORDER=\"0\" USEMAP=\"#chart\">\n")
151
+ end
152
+ if options[:layout].nil? or !options[:layout]
153
+ html_file.write("</BODY>\n");
154
+ html_file.write("</HTML>\n");
155
+ end
156
+ html_file.string
157
+ else
158
+ raise "Cannot render to #{mime_type.inspect}"
159
+ end
160
+ }
161
+ end
162
+
163
+ private
164
+ def jf_orientation(flipped = false)
165
+ case orientation
166
+ when nil, :horizontal
167
+ if flipped
168
+ PlotOrientation.VERTICAL
169
+ else
170
+ PlotOrientation.HORIZONTAL
171
+ end
172
+ when :vertical
173
+ if flipped
174
+ PlotOrientation.HORIZONTAL
175
+ else
176
+ PlotOrientation.VERTICAL
177
+ end
178
+ else
179
+ raise "Unexpected orientation #{orientation.inspect}"
180
+ end
181
+ end
182
+
183
+ def configure_renderer(renderer)
184
+ configure_colors(renderer)
185
+ end
186
+
187
+ def configure_colors(renderer)
188
+ paint_array = ChartColor.createDefaultPaintArray()
189
+ second_color = Color.create("java","white").java_object
190
+ i = 0
191
+ if (false)
192
+ paint_array.each {|item|
193
+ renderer.setSeriesPaint(i, GradientPaint.new(0.0, 0.0, item, 1000, 0.0, second_color))
194
+ i += 1;
195
+ }
196
+ else
197
+ paint_array.each {|item|
198
+ renderer.setSeriesPaint(i, item)
199
+ i += 1;
200
+ }
201
+ end
202
+
203
+ paint_array.each {|item|
204
+ bi = BufferedImage.new(2, 2, BufferedImage.TYPE_INT_RGB);
205
+ big = bi.createGraphics();
206
+ big.setColor(item);
207
+ big.fillRect(0, 0, 1, 1);
208
+ big.fillOval(1, 1, 2, 2);
209
+ big.setColor(second_color);
210
+ big.fillRect(1, 0, 2, 1);
211
+ big.fillOval(0, 1, 1, 2);
212
+ r = Rectangle.new(0, 0, 2, 2);
213
+ renderer.setSeriesPaint(i,TexturePaint.new(bi, r))
214
+ i += 1;
215
+ }
216
+
217
+ paint_array.each {|item|
218
+ bi = BufferedImage.new(2, 2, BufferedImage.TYPE_INT_RGB);
219
+ big = bi.createGraphics();
220
+ big.setColor(item);
221
+ big.fillRect(0, 0, 1, 1);
222
+ big.fillOval(1, 0, 2, 1);
223
+ big.setColor(second_color);
224
+ big.fillRect(0, 1, 1, 2);
225
+ big.fillOval(1, 1, 2, 2);
226
+ r = Rectangle.new(0, 0, 2, 2);
227
+ renderer.setSeriesPaint(i, TexturePaint.new(bi, r))
228
+ i += 1;
229
+ }
230
+ end
231
+
232
+ def jf_xaxis
233
+ name = [name, xaxis].compact.join(" ")
234
+ case type
235
+ when :line, :xy
236
+ axis_obj = NumberAxis.new(name)
237
+ axis_obj.setAutoRangeIncludesZero(false)
238
+ axis_obj.setAutoRangeStickyZero(false)
239
+ axis_obj.setAutoRange(true)
240
+ axis_obj
241
+ else
242
+ axis_obj = CategoryAxis.new(xaxis)
243
+ #axis_obj.setTickLabelFont(Font.new("SansSerif", Font.PLAIN, 8))
244
+ #axis_obj.setTickLabelPaint(Color.create("java","red").java_object)
245
+
246
+
247
+
248
+ clp = CategoryLabelPositions.new(
249
+ # TOP
250
+ CategoryLabelPosition.new(
251
+ RectangleAnchor.BOTTOM,
252
+ TextBlockAnchor.BOTTOM_LEFT,
253
+ TextAnchor.BOTTOM_LEFT,
254
+ -legend_rotation,
255
+ CategoryLabelWidthType.RANGE,
256
+ 0.40),
257
+ # BOTTOM
258
+ CategoryLabelPosition.new(
259
+ RectangleAnchor.TOP,
260
+ TextBlockAnchor.TOP_RIGHT,
261
+ TextAnchor.TOP_RIGHT,
262
+ -legend_rotation,
263
+ CategoryLabelWidthType.RANGE,
264
+ 0.40),
265
+ # LEFT
266
+ CategoryLabelPosition.new(
267
+ RectangleAnchor.RIGHT,
268
+ TextBlockAnchor.BOTTOM_RIGHT,
269
+ TextAnchor.BOTTOM_RIGHT,
270
+ -legend_rotation,
271
+ CategoryLabelWidthType.RANGE,
272
+ 0.40),
273
+ # RIGHT
274
+ CategoryLabelPosition.new(
275
+ RectangleAnchor.LEFT,
276
+ TextBlockAnchor.TOP_LEFT,
277
+ TextAnchor.TOP_LEFT,
278
+ -legend_rotation,
279
+ CategoryLabelWidthType.RANGE,
280
+ 0.40)
281
+ )
282
+
283
+
284
+ # clp = CategoryLabelPositions.createUpRotationLabelPositions(legend_rotation)
285
+
286
+ axis_obj.setCategoryLabelPositions(clp)
287
+ axis_obj.getCategoryLabelPositions
288
+ #axis_obj.setCategoryLabelPositionOffset(10)
289
+
290
+ axis_obj
291
+ end
292
+ end
293
+ def jf_yaxis
294
+ name = [name, yaxis].compact.join(" ")
295
+ case type
296
+ when :gantt
297
+ DateAxis.new(name)
298
+ else
299
+ axis_obj = NumberAxis.new(name)
300
+ axis_obj.setAutoRangeIncludesZero(false)
301
+ axis_obj.setAutoRangeStickyZero(false)
302
+ axis_obj.setAutoRange(true)
303
+ axis_obj
304
+ end
305
+ end
306
+ def jf_zaxis(name = nil)
307
+ name = [name, zaxis].compact.join(" ")
308
+ CategoryAxis.new(name)
309
+ end
310
+
311
+ def jf_yvalue(value)
312
+ case type
313
+ when :gantt
314
+ case value
315
+ when DateTime,Date,Time
316
+ Time.parse(value.strftime("%F %T")).to_f * 1000.0
317
+ else
318
+ Time.parse(value.to_s).to_f * 1000.0
319
+ end
320
+ else
321
+ value.to_f
322
+ end
323
+ end
324
+
325
+ # combined plot
326
+ def create_combined_plot_implementation(data, combination_axis = :domain)
327
+ cap_name = combination_axis.to_s.capitalize
328
+ other_name = if combination_axis == :domain then "Range" else "Domain" end
329
+ combined_axis_name = {:range => "yaxis", :domain => "xaxis"}[combination_axis]
330
+
331
+ axis_obj = eval("jf_#{combined_axis_name}")
332
+
333
+ case type
334
+ when :line,:xy
335
+ plot_class = eval("Combined#{cap_name}XYPlot")
336
+ else
337
+ plot_class = eval("Combined#{cap_name}CategoryPlot")
338
+ end
339
+
340
+ plot = plot_class.new(axis_obj)
341
+
342
+ num = 0
343
+ data.each {|range_name, data|
344
+ range_options = @range_options[range_name] or {}
345
+ subplot = create_plot(range_name,data)
346
+ #subplot.setRangeAxis(nil) if num > 0
347
+
348
+ begin
349
+ plot.add(subplot, data.values.map {|h| h.keys}.flatten.length)
350
+ rescue
351
+ $log.warn("Failed to determine weight #{$!}")
352
+ plot.add(subplot)
353
+ end
354
+
355
+ eval("subplot.get#{other_name}Axis").setLabel(range_name)
356
+
357
+ subplot.setOrientation(jf_orientation(true)) rescue $log.warn("Orientation not set #{$!}")
358
+ }
359
+ plot.setOrientation(jf_orientation) rescue $log.warn("Orientation not set #{$!}")
360
+
361
+ lis = plot.getLegendItems
362
+ new_legend_collection = LegendItemCollection.new
363
+ legend_labels = []
364
+ lis.getItemCount.times {|i|
365
+ li = lis.get(i)
366
+ unless legend_labels.include?(li.getLabel)
367
+ new_legend_collection.add(li)
368
+ legend_labels << li.getLabel
369
+ end
370
+ }
371
+ plot.setFixedLegendItems(new_legend_collection)
372
+ plot
373
+ end
374
+
375
+ def create_plot_implementation(range_name, data, options = {})
376
+ range_options = @range_options[range_name] or {}
377
+ range_options = @range_options.values[0] if range_name.nil?
378
+
379
+ case @type
380
+ when :bar
381
+ if stacked
382
+ my_renderer = StackedBarRenderer.new
383
+ else
384
+ my_renderer = BarRenderer.new
385
+ end
386
+
387
+ #ItemLabelPosition position1 = new ItemLabelPosition(ItemLabelAnchor.OUTSIDE12, TextAnchor.BOTTOM_CENTER);
388
+ #ItemLabelPosition position2 = new ItemLabelPosition(ItemLabelAnchor.OUTSIDE6, TextAnchor.TOP_CENTER);
389
+ #renderer.setPositiveItemLabelPosition(position1);
390
+ #renderer.setNegativeItemLabelPosition(position2);
391
+ #renderer.setDrawBarOutline(false);
392
+ configure_renderer(my_renderer)
393
+
394
+ #MyGenerator generator = new MyGenerator(this.URLPrefix, this.rangeNames[range], this);
395
+ #my_renderer.setBaseItemURLGenerator(generator);
396
+ #my_renderer.setBaseToolTipGenerator(generator);
397
+
398
+ plot = CategoryPlot.new(create_category_dataset(data),
399
+ jf_xaxis,
400
+ jf_yaxis,
401
+ my_renderer)
402
+ when :line
403
+ if @stacked
404
+ my_renderer = StackedXYAreaRenderer2.new;
405
+ else
406
+ raise "not impl"
407
+ my_renderer = StandardXYItemRenderer.new(StandardXYItemRenderer.SHAPES_AND_LINES);
408
+ end
409
+ configure_renderer(my_renderer)
410
+ #MyGenerator generator = new MyGenerator(@URLPrefix, @rangeNames[range], this);
411
+ # my_renderer.setURLGenerator(generator);
412
+ # my_renderer.setBaseToolTipGenerator(generator);
413
+ #
414
+ #
415
+
416
+ plot = XYPlot.new(create_xy_dataset(data),
417
+ jf_xaxis,
418
+ jf_yaxis,
419
+ my_renderer)
420
+ when :gantt
421
+ my_renderer = GanttRenderer.new
422
+
423
+ my_renderer.setBaseItemURLGenerator(StandardCategoryURLGenerator.new) if
424
+ enable_urls
425
+
426
+ configure_renderer(my_renderer)
427
+
428
+ plot = CategoryPlot.new(create_task_series_collection(data),
429
+ jf_xaxis, jf_yaxis, my_renderer)
430
+ when :pie
431
+ plot = MultiplePiePlot.new(create_category_dataset(data));
432
+ plot.setDataExtractOrder(TableOrder.BY_ROW);
433
+ plot.setOutlineStroke(nil);
434
+
435
+ # if (enable_tooltips)
436
+ # tooltipGenerator = StandardPieToolTipGenerator.new();
437
+ # pp = plot.getPieChart().getPlot();
438
+ # pp.setToolTipGenerator(tooltipGenerator);
439
+ # end
440
+
441
+ if (enable_urls)
442
+ urlGenerator = new StandardPieURLGenerator();
443
+ pp = plot.getPieChart().getPlot();
444
+ pp.setURLGenerator(urlGenerator);
445
+ end
446
+
447
+ # plot = @chart.getPlot();
448
+ # subchart = plot.getPieChart();
449
+
450
+ # p = subchart.getPlot();
451
+ # /* p.setLabelGenerator(new StandardPieItemLabelGenerator("{0}"));*/
452
+ # p.setLabelFont(Font.new("SansSerif", Font.PLAIN, 8));
453
+ # p.setInteriorGap(0.30);
454
+ #generator = MyGenerator.new(this.URLPrefix,this.category_datasets[0]);
455
+ #p.setURLGenerator(generator);
456
+ # // p.setToolTipGenerator(generator);
457
+
458
+
459
+ else
460
+ raise "Unexpected chart type #{@type}"
461
+ end
462
+
463
+ if enable_tooltips and my_renderer and my_renderer.getClass.toString =~ /category/
464
+ generator = JfreechartGenerator.new(self, range_name)
465
+ generator = Rjb::bind(generator, "org.jfree.chart.labels.CategoryToolTipGenerator")
466
+ my_renderer.setBaseToolTipGenerator(generator) rescue "Unable to set tooltip generator: #{$!}"
467
+ end
468
+
469
+ plot.setOrientation(jf_orientation) rescue $log.warn("Orientation not set #{$!}")
470
+
471
+ @options ||= {}
472
+ range_options ||= {}
473
+ ((@options[:markers] or []) + (range_options[:markers] or [])).each {|marker|
474
+ new_maker = nil
475
+
476
+ case marker[:type]
477
+ when :value
478
+ # value marker
479
+ marker[:layer] ||= :front
480
+ new_marker = ValueMarker.new(jf_yvalue(marker[:value]))
481
+ new_marker.setLabelTextAnchor(TextAnchor.TOP_LEFT)
482
+ new_marker.setLabel(marker[:name])
483
+ when :interval
484
+ # range marker
485
+ marker[:layer] ||= :back
486
+ new_marker = IntervalMarker.new(jf_yvalue(marker[:start]),jf_yvalue(marker[:end]));
487
+ new_marker.setLabelTextAnchor(TextAnchor.CENTER_LEFT)
488
+ new_marker.setLabelAnchor(RectangleAnchor.LEFT)
489
+ new_marker.setLabel(marker[:name])
490
+ when :category
491
+ marker[:layer] ||= :back
492
+ new_marker = CategoryMarker.new_with_sig("Ljava.lang.Comparable;",marker[:key])
493
+ end
494
+
495
+ new_marker.setLabelFont(Font.new("SansSerif", Font.BOLD, 11))
496
+ new_marker.setPaint(Color.create("java",(marker[:color] or "red")).java_object)
497
+ new_marker.setAlpha(1.0)
498
+
499
+ case marker[:layer].to_s
500
+ when "foreground", "front",""
501
+ layer = Layer.FOREGROUND
502
+ when "back","background"
503
+ layer = Layer.BACKGROUND
504
+ else
505
+ raise "Unexpected layer value #{marker[:layer].inspect}"
506
+ end
507
+
508
+ case marker[:axis]
509
+ when :range
510
+ plot.addRangeMarker(new_marker,layer)
511
+ when :domain
512
+ plot.addDomainMarker(new_marker,layer)
513
+ else
514
+ raise "Unexpected marker axis"
515
+ end
516
+ }
517
+
518
+
519
+ if range_color = range_options[:color]
520
+ plot.setBackgroundPaint(Color.create("java",range_color).java_object)
521
+ else
522
+ plot.setBackgroundPaint(Color.create("java","LightGray").java_object)
523
+ end
524
+
525
+ plot.setDomainGridlinePaint(Color.create("java","white").java_object) rescue $log.warn("setDomainGridlinePaint failed: #{$!}")
526
+ plot.setRangeGridlinePaint(Color.create("java","white").java_object) rescue $log.warn("setRangeGridlinePaint failed: #{$!}")
527
+ #plot.clearDomainAxes();
528
+
529
+ plot
530
+ end
531
+
532
+ def create_chart_implementation(plot)
533
+ @chart = JFreeChart.new(@title, nil, plot, display_legend)
534
+ @chart.setBackgroundPaint(Color.create("java","white").java_object)
535
+
536
+ @chart
537
+ end
538
+
539
+ def to_date(obj)
540
+ c = Calendar.getInstance
541
+ case obj
542
+ when String
543
+ obj = DateTime.parse(obj) rescue raise("#{$!}: #{obj}")
544
+ when Date,DateTime
545
+ else
546
+ raise "Unexpected data class #{obj.class}"
547
+ end
548
+ # !month is 0 based in java!
549
+ c.set(obj.year, obj.month - 1, obj.day, obj.hour, obj.min, obj.sec)
550
+ c.getTime()
551
+ end
552
+
553
+
554
+ # Data Sets
555
+ def create_xy_dataset(data)
556
+ # STRING x VAL x VAL
557
+ # means STRING x STRING x VAL
558
+ # means SERIE x CATEGORY x ARRAY[0]
559
+
560
+ # add(Number x, Number y, String seriesName, boolean notify)
561
+ xy_dataset = CategoryTableXYDataset.new
562
+ data.each {|serie_name, category|
563
+ category.each {|category_name, val|
564
+ xy_dataset.add(category_name.to_f, val.to_f, serie_name)
565
+ }
566
+ }
567
+ xy_dataset
568
+ end
569
+
570
+ def create_category_dataset(data)
571
+ # STRING x STRING x VAL
572
+ # means SERIE x CATEGORY x ARRAY[0]
573
+ category_dataset = DefaultCategoryDataset.new
574
+ data.each {|serie_name, category|
575
+ category.each {|category_name, val|
576
+ # addValue(Number value, Comparable rowKey, Comparable columnKey)
577
+ category_dataset._invoke("addValue",
578
+ "Ljava.lang.Number;Ljava.lang.Comparable;Ljava.lang.Comparable;",
579
+ val.to_i,category_name,serie_name)
580
+ }
581
+ }
582
+ category_dataset
583
+ end
584
+
585
+ # Task Series
586
+ def create_task_series_collection(data)
587
+ # STRING x TASK
588
+ m_series = TaskSeriesCollection.new
589
+ data.each {|serie_name, values|
590
+ m_serie = TaskSeries.new((serie_name or ""))
591
+
592
+ values.each {|key, value|
593
+ task = create_task(key,value)
594
+ m_serie.add(task)
595
+ if value.class == Hash and value[:children]
596
+ value[:children].each {|key, value|
597
+ task.addSubtask(create_task(key,value))
598
+ }
599
+ end
600
+ }
601
+ m_series.add(m_serie)
602
+ }
603
+ m_series
604
+ end
605
+
606
+ # data: [start,end,percentage] or {:start => start, :end => end, :percentage}
607
+ def create_task(name, data)
608
+ data = [data[:start],data[:end], data[:percentage]] if data.class == Hash
609
+
610
+ $log.debug("Create Task #{name.inspect}: #{data[0].inspect} - #{data[1].inspect} (#{data[2].inspect})")
611
+ period = SimpleTimePeriod.new(to_date(data[0]),to_date(data[1]))
612
+ task = Task.new(name.to_s,period)
613
+ task.setPercentComplete(data[2].to_f) if data[2]
614
+ task
615
+ end
616
+ end
617
+ =begin
618
+ public GanttDemo1(final String title) {
619
+
620
+ super(title);
621
+
622
+ final IntervalCategoryDataset dataset = createDataset();
623
+ final JFreeChart chart = createChart(dataset);
624
+
625
+ # add the chart to a panel...
626
+ final ChartPanel chartPanel = new ChartPanel(chart);
627
+ chartPanel.setPreferredSize(new java.awt.Dimension(500, 270));
628
+ setContentPane(chartPanel);
629
+
630
+
631
+
632
+ final TaskSeriesCollection collection = new TaskSeriesCollection();
633
+ collection.add(s1);
634
+ collection.add(s2);
635
+
636
+ return collection;
637
+ }
638
+
639
+ /**
640
+ * Utility method for creating <code>Date</code> objects.
641
+ *
642
+ * @param day the date.
643
+ * @param month the month.
644
+ * @param year the year.
645
+ *
646
+ * @return a date.
647
+ */
648
+ private static Date date(final int day, final int month, final int year) {
649
+
650
+ final Calendar calendar = Calendar.getInstance();
651
+ calendar.set(year, month, day);
652
+ final Date result = calendar.getTime();
653
+ return result;
654
+
655
+ }
656
+
657
+ /**
658
+ * Creates a chart.
659
+ *
660
+ * @param dataset the dataset.
661
+ *
662
+ * @return The chart.
663
+ */
664
+ private JFreeChart createChart(final IntervalCategoryDataset dataset) {
665
+ }
666
+
667
+ /**
668
+ * Starting point for the demonstration application.
669
+ *
670
+ * @param args ignored.
671
+ */
672
+ public static void main(final String[] args) {
673
+
674
+ final GanttDemo1 demo = new GanttDemo1("Gantt Chart Demo 1");
675
+ demo.pack();
676
+ RefineryUtilities.centerFrameOnScreen(demo);
677
+ demo.setVisible(true);
678
+
679
+ }
680
+
681
+ end
682
+ =end