gerbilcharts 0.0.3
Sign up to get free protection for your applications and to get access to all the features.
- data/History.txt +11 -0
- data/License.txt +21 -0
- data/Manifest.txt +75 -0
- data/PostInstall.txt +7 -0
- data/README.txt +174 -0
- data/Rakefile +4 -0
- data/lib/gerbilcharts.rb +18 -0
- data/lib/gerbilcharts/charts.rb +16 -0
- data/lib/gerbilcharts/charts/area_chart.rb +36 -0
- data/lib/gerbilcharts/charts/bar_chart.rb +33 -0
- data/lib/gerbilcharts/charts/bar_chart_compact.rb +26 -0
- data/lib/gerbilcharts/charts/chart_base.rb +123 -0
- data/lib/gerbilcharts/charts/impulse_chart.rb +30 -0
- data/lib/gerbilcharts/charts/line_chart.rb +35 -0
- data/lib/gerbilcharts/charts/stacked_area_chart.rb +31 -0
- data/lib/gerbilcharts/models.rb +19 -0
- data/lib/gerbilcharts/models/bucketized_timeseries_graph_model.rb +138 -0
- data/lib/gerbilcharts/models/discrete_time_range.rb +63 -0
- data/lib/gerbilcharts/models/graph_model.rb +89 -0
- data/lib/gerbilcharts/models/graph_model_group.rb +240 -0
- data/lib/gerbilcharts/models/monotonous_graph_model.rb +192 -0
- data/lib/gerbilcharts/models/presets.rb +94 -0
- data/lib/gerbilcharts/models/raw_range.rb +68 -0
- data/lib/gerbilcharts/models/round_range.rb +104 -0
- data/lib/gerbilcharts/models/round_time_range.rb +105 -0
- data/lib/gerbilcharts/models/sampled_timeseries_graph_model.rb +80 -0
- data/lib/gerbilcharts/models/simple_timeseries_model_group.rb +68 -0
- data/lib/gerbilcharts/models/time_series_graph_model.rb +34 -0
- data/lib/gerbilcharts/public/brushmetal.css +197 -0
- data/lib/gerbilcharts/public/gerbil.js +327 -0
- data/lib/gerbilcharts/surfaces.rb +32 -0
- data/lib/gerbilcharts/surfaces/area_surface.rb +46 -0
- data/lib/gerbilcharts/surfaces/axis.rb +31 -0
- data/lib/gerbilcharts/surfaces/bar_surface.rb +62 -0
- data/lib/gerbilcharts/surfaces/basic_grid.rb +17 -0
- data/lib/gerbilcharts/surfaces/chart.rb +132 -0
- data/lib/gerbilcharts/surfaces/graph_element.rb +170 -0
- data/lib/gerbilcharts/surfaces/grid.rb +38 -0
- data/lib/gerbilcharts/surfaces/horizontal_axis.rb +32 -0
- data/lib/gerbilcharts/surfaces/horizontal_name_axis.rb +28 -0
- data/lib/gerbilcharts/surfaces/horizontal_time_axis.rb +25 -0
- data/lib/gerbilcharts/surfaces/impulse_surface.rb +47 -0
- data/lib/gerbilcharts/surfaces/legend.rb +59 -0
- data/lib/gerbilcharts/surfaces/line_surface.rb +53 -0
- data/lib/gerbilcharts/surfaces/mark_band.rb +17 -0
- data/lib/gerbilcharts/surfaces/panel.rb +17 -0
- data/lib/gerbilcharts/surfaces/pie_surface.rb +16 -0
- data/lib/gerbilcharts/surfaces/rect.rb +86 -0
- data/lib/gerbilcharts/surfaces/stacked_area_surface.rb +66 -0
- data/lib/gerbilcharts/surfaces/stacked_grid.rb +15 -0
- data/lib/gerbilcharts/surfaces/surface.rb +20 -0
- data/lib/gerbilcharts/surfaces/surface_background.rb +13 -0
- data/lib/gerbilcharts/surfaces/title_panel.rb +44 -0
- data/lib/gerbilcharts/surfaces/tracker.rb +62 -0
- data/lib/gerbilcharts/surfaces/vertical_axis.rb +46 -0
- data/lib/gerbilcharts/svgdc.rb +22 -0
- data/lib/gerbilcharts/svgdc/filters.rb +40 -0
- data/lib/gerbilcharts/svgdc/presentation_attributes.rb +50 -0
- data/lib/gerbilcharts/svgdc/svg_circle.rb +22 -0
- data/lib/gerbilcharts/svgdc/svg_custom_win.rb +36 -0
- data/lib/gerbilcharts/svgdc/svg_element.rb +87 -0
- data/lib/gerbilcharts/svgdc/svg_line.rb +26 -0
- data/lib/gerbilcharts/svgdc/svg_polygon.rb +34 -0
- data/lib/gerbilcharts/svgdc/svg_polyline.rb +27 -0
- data/lib/gerbilcharts/svgdc/svg_rect.rb +29 -0
- data/lib/gerbilcharts/svgdc/svg_shape.rb +10 -0
- data/lib/gerbilcharts/svgdc/svg_text.rb +21 -0
- data/lib/gerbilcharts/svgdc/svg_win.rb +52 -0
- data/lib/gerbilcharts/svgdc/svgdc.rb +335 -0
- data/lib/gerbilcharts/svgdc/transformations.rb +66 -0
- data/lib/gerbilcharts/version.rb +9 -0
- data/setup.rb +1585 -0
- data/test/test_Scratch.rb +21 -0
- data/test/test_charts.rb +119 -0
- data/test/test_gerbilcharts.rb +11 -0
- data/test/test_helper.rb +2 -0
- data/test/test_models.rb +118 -0
- data/test/test_noob.rb +81 -0
- data/test/test_ranges.rb +135 -0
- data/test/test_svgdc.rb +221 -0
- data/test/trafgen.rb +25 -0
- metadata +156 -0
@@ -0,0 +1,132 @@
|
|
1
|
+
module GerbilCharts::Surfaces
|
2
|
+
|
3
|
+
# == Chart - container class
|
4
|
+
# Base from which all chart are derived
|
5
|
+
class Chart < GraphElement
|
6
|
+
|
7
|
+
attr_reader :anchor
|
8
|
+
attr_reader :elements
|
9
|
+
attr_reader :needslayout
|
10
|
+
attr_reader :modelgroup
|
11
|
+
attr_reader :stylesheet
|
12
|
+
attr_reader :filters
|
13
|
+
attr_reader :href
|
14
|
+
attr_reader :javascripts
|
15
|
+
attr_reader :ajaxOptions
|
16
|
+
attr_reader :ajaxContext
|
17
|
+
|
18
|
+
def initialize( opt={})
|
19
|
+
super(opt)
|
20
|
+
set_defaults
|
21
|
+
@children = []
|
22
|
+
@filters = []
|
23
|
+
@stylesheet = opt[:style] if defined? opt[:style]
|
24
|
+
@javascripts = opt[:javascripts] if opt[:javascripts]
|
25
|
+
@needslayout=false
|
26
|
+
end
|
27
|
+
|
28
|
+
def set_defaults
|
29
|
+
@javascripts = { "/javascripts/gerbil.js" => false, "/javascripts/prototype.js" => false }
|
30
|
+
end
|
31
|
+
|
32
|
+
def set_modelgroup(g)
|
33
|
+
@modelgroup=g
|
34
|
+
end
|
35
|
+
|
36
|
+
def usesAjax?
|
37
|
+
if @ajaxOptions
|
38
|
+
return true
|
39
|
+
else
|
40
|
+
return false
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
44
|
+
def set_ajaxOptions(h)
|
45
|
+
@ajaxOptions={} if @ajaxOptions == nil
|
46
|
+
@ajaxOptions.merge!(h)
|
47
|
+
end
|
48
|
+
|
49
|
+
def set_ajaxContext(h)
|
50
|
+
@ajaxContext={} if @ajaxContext == nil
|
51
|
+
@ajaxContext.merge!(h)
|
52
|
+
end
|
53
|
+
|
54
|
+
|
55
|
+
def add_child(e,opts={})
|
56
|
+
@children << e
|
57
|
+
@needslayout=true
|
58
|
+
e.setparent(self)
|
59
|
+
set_anchor(e) if opts[:anchor]
|
60
|
+
end
|
61
|
+
|
62
|
+
def render(ropts={})
|
63
|
+
svgdc = GerbilCharts::SVGDC::SVGDC.new(@bounds.width, @bounds.height)
|
64
|
+
|
65
|
+
dolayout if @needslayout
|
66
|
+
|
67
|
+
@children.each do |ch|
|
68
|
+
ch.render(svgdc)
|
69
|
+
end
|
70
|
+
|
71
|
+
@filters.each do |f|
|
72
|
+
svgdc.add_filter(f)
|
73
|
+
end
|
74
|
+
|
75
|
+
@javascripts.each_pair do |scr,inline|
|
76
|
+
svgdc.add_javascriptfile(scr, inline)
|
77
|
+
end
|
78
|
+
|
79
|
+
# set model hash, and other template contexts
|
80
|
+
if @ajaxOptions
|
81
|
+
@ajaxContext.store(:axdigest,@modelgroup.models_digest)
|
82
|
+
end
|
83
|
+
|
84
|
+
svgdc.set_ajaxOptions(@ajaxOptions) if @ajaxOptions
|
85
|
+
|
86
|
+
svgdc.set_ajaxContext(@ajaxContext) if @ajaxContext
|
87
|
+
|
88
|
+
svgdc.set_stylesheet(@stylesheet) if @stylesheet
|
89
|
+
|
90
|
+
svgdc.render(ropts)
|
91
|
+
end
|
92
|
+
|
93
|
+
def getmodelgroup
|
94
|
+
return @modelgroup
|
95
|
+
end
|
96
|
+
|
97
|
+
def create_filter(f)
|
98
|
+
@filters << f
|
99
|
+
end
|
100
|
+
|
101
|
+
def sethref(h)
|
102
|
+
@href=h
|
103
|
+
end
|
104
|
+
|
105
|
+
protected
|
106
|
+
def dolayout
|
107
|
+
spare = Rect.new
|
108
|
+
spare.from_wh @bounds.width,@bounds.height
|
109
|
+
|
110
|
+
@children.each do |ch|
|
111
|
+
spare=ch.munch spare
|
112
|
+
end
|
113
|
+
|
114
|
+
@anchor.setbounds spare
|
115
|
+
|
116
|
+
@children.each do |ch|
|
117
|
+
ch.align_to_anchor @anchor
|
118
|
+
end
|
119
|
+
|
120
|
+
@needslayout=false
|
121
|
+
end
|
122
|
+
|
123
|
+
private
|
124
|
+
def set_anchor(a)
|
125
|
+
raise "Only one anchor element supported" if @anchor
|
126
|
+
@anchor =a
|
127
|
+
end
|
128
|
+
end
|
129
|
+
|
130
|
+
end
|
131
|
+
|
132
|
+
|
@@ -0,0 +1,170 @@
|
|
1
|
+
module GerbilCharts::Surfaces
|
2
|
+
|
3
|
+
# Graph - base for everything you place on the graph (all rectangular)
|
4
|
+
#
|
5
|
+
class GraphElement
|
6
|
+
|
7
|
+
# constants
|
8
|
+
EXP_FIXED=1
|
9
|
+
EXP_FILL=2
|
10
|
+
|
11
|
+
# orientations
|
12
|
+
ORIENT_NORTH=1
|
13
|
+
ORIENT_SOUTH=2
|
14
|
+
ORIENT_EAST=3
|
15
|
+
ORIENT_WEST=4
|
16
|
+
ORIENT_NORTHEAST=5
|
17
|
+
ORIENT_NORTHWEST=6
|
18
|
+
ORIENT_SOUTHEAST=7
|
19
|
+
ORIENT_SOUTHWEST=8
|
20
|
+
ORIENT_OVERLAY=9
|
21
|
+
|
22
|
+
|
23
|
+
# public ro attributes
|
24
|
+
attr_reader :class
|
25
|
+
attr_reader :group
|
26
|
+
attr_reader :bounds
|
27
|
+
attr_reader :lay_orient
|
28
|
+
attr_reader :lay_expand
|
29
|
+
attr_reader :lay_dimension
|
30
|
+
attr_reader :parent
|
31
|
+
|
32
|
+
def initialize( opt={} )
|
33
|
+
@lay_orient= opt[:orient] if defined? opt[:orient]
|
34
|
+
@lay_expand= opt[:expand] if defined? opt[:expand]
|
35
|
+
@lay_dimension= opt[:dim] if defined? opt[:dim]
|
36
|
+
@bounds = Rect.new
|
37
|
+
if opt[:width] and opt[:height]
|
38
|
+
@bounds.from_wh(opt[:width],opt[:height])
|
39
|
+
end
|
40
|
+
if opt[:class]
|
41
|
+
@class=opt[:class]
|
42
|
+
end
|
43
|
+
@group="default"
|
44
|
+
@global_chart_options=opt
|
45
|
+
end
|
46
|
+
|
47
|
+
def needslayout?
|
48
|
+
if @lay_orient
|
49
|
+
return true
|
50
|
+
else
|
51
|
+
return false
|
52
|
+
end
|
53
|
+
end
|
54
|
+
|
55
|
+
def setparent(par)
|
56
|
+
@parent=par
|
57
|
+
end
|
58
|
+
|
59
|
+
def isoverlay?
|
60
|
+
if defined? @lay_orient and @lay_orient == ORIENT_OVERLAY
|
61
|
+
return true
|
62
|
+
else
|
63
|
+
return false
|
64
|
+
end
|
65
|
+
end
|
66
|
+
|
67
|
+
def scale_x val,range
|
68
|
+
return @bounds.left + @bounds.width * range.scale_factor(val)
|
69
|
+
end
|
70
|
+
|
71
|
+
def scale_y val,range
|
72
|
+
return @bounds.bottom - @bounds.height * range.scale_factor(val)
|
73
|
+
end
|
74
|
+
|
75
|
+
|
76
|
+
def setbounds rcbounds
|
77
|
+
@bounds.initfrom rcbounds
|
78
|
+
end
|
79
|
+
|
80
|
+
# setup SVG group element and call int_render
|
81
|
+
def render(sdc)
|
82
|
+
w=sdc.newwin(@group)
|
83
|
+
# w.add_transformation(TTranslate.new(@bounds.left, @bounds.top))
|
84
|
+
sdc.setactivewindow(w)
|
85
|
+
int_render(sdc)
|
86
|
+
sdc.setactivewindow
|
87
|
+
end
|
88
|
+
|
89
|
+
# render direct - directly render SVG using builder for complex elements
|
90
|
+
def render_direct(sdc)
|
91
|
+
raise "This Graph Element cannot render directly, incorrect usage"
|
92
|
+
end
|
93
|
+
|
94
|
+
def munch(layrect)
|
95
|
+
raise "Element does not need to be laid out" if not needslayout?
|
96
|
+
|
97
|
+
@bounds.initfrom(layrect)
|
98
|
+
case @lay_orient
|
99
|
+
when ORIENT_SOUTH
|
100
|
+
@bounds.clip_b @lay_dimension
|
101
|
+
layrect.crop_b @lay_dimension
|
102
|
+
when ORIENT_NORTH
|
103
|
+
@bounds.clip_t @lay_dimension
|
104
|
+
layrect.crop_t @lay_dimension
|
105
|
+
when ORIENT_EAST
|
106
|
+
@bounds.clip_r @lay_dimension
|
107
|
+
layrect.crop_r @lay_dimension
|
108
|
+
when ORIENT_WEST
|
109
|
+
@bounds.clip_l @lay_dimension
|
110
|
+
layrect.crop_l @lay_dimension
|
111
|
+
when ORIENT_SOUTHEAST
|
112
|
+
@bounds.clip_b @lay_dimension
|
113
|
+
@bounds.clip_r @lay_dimension
|
114
|
+
when ORIENT_NORTHEAST
|
115
|
+
@bounds.clip_t @lay_dimension
|
116
|
+
@bounds.clip_r @lay_dimension
|
117
|
+
when ORIENT_SOUTHWEST
|
118
|
+
@bounds.clip_b @lay_dimension
|
119
|
+
@bounds.clip_l @lay_dimension
|
120
|
+
when ORIENT_NORTHWEST
|
121
|
+
@bounds.clip_t @lay_dimension
|
122
|
+
@bounds.clip_l @lay_dimension
|
123
|
+
end
|
124
|
+
return layrect
|
125
|
+
end
|
126
|
+
|
127
|
+
def align_to_anchor(anc)
|
128
|
+
case @lay_orient
|
129
|
+
when ORIENT_SOUTH
|
130
|
+
@bounds.left= anc.bounds.left
|
131
|
+
@bounds.right=anc.bounds.right
|
132
|
+
when ORIENT_NORTH
|
133
|
+
@bounds.left= anc.bounds.left
|
134
|
+
@bounds.right=anc.bounds.right
|
135
|
+
when ORIENT_EAST
|
136
|
+
@bounds.top= anc.bounds.top
|
137
|
+
@bounds.bottom=anc.bounds.bottom
|
138
|
+
when ORIENT_WEST
|
139
|
+
@bounds.top= anc.bounds.top
|
140
|
+
@bounds.bottom=anc.bounds.bottom
|
141
|
+
when ORIENT_OVERLAY
|
142
|
+
@bounds.initfrom anc.bounds
|
143
|
+
end
|
144
|
+
end
|
145
|
+
|
146
|
+
# query a global option, return the defval if option is not set
|
147
|
+
def get_global_option(optsym, defval)
|
148
|
+
if @global_chart_options[optsym]
|
149
|
+
return @global_chart_options[optsym]
|
150
|
+
else
|
151
|
+
return defval
|
152
|
+
end
|
153
|
+
end
|
154
|
+
|
155
|
+
# utility methods to derived classes
|
156
|
+
protected
|
157
|
+
|
158
|
+
def max(a,b)
|
159
|
+
return (a>b)?a:b
|
160
|
+
end
|
161
|
+
|
162
|
+
def min(a,b)
|
163
|
+
return (a<b)?a:b
|
164
|
+
end
|
165
|
+
|
166
|
+
|
167
|
+
end
|
168
|
+
|
169
|
+
end
|
170
|
+
|
@@ -0,0 +1,38 @@
|
|
1
|
+
module GerbilCharts::Surfaces
|
2
|
+
|
3
|
+
# = Grid - grid overlay
|
4
|
+
# Draws both x and y grids
|
5
|
+
class Grid < GraphElement
|
6
|
+
|
7
|
+
def initialize(opts={})
|
8
|
+
super(opts)
|
9
|
+
end
|
10
|
+
|
11
|
+
def int_render(g)
|
12
|
+
ry = grid_range_y
|
13
|
+
ry.each_label do |val,label|
|
14
|
+
yp = scale_y val,ry
|
15
|
+
g.line(@bounds.left,yp,@bounds.right,yp, {:class => "gridlineh"})
|
16
|
+
end
|
17
|
+
|
18
|
+
rx = grid_range_x
|
19
|
+
rx.each_label do |val,label|
|
20
|
+
xp = scale_x val,rx
|
21
|
+
g.line(xp,@bounds.top,xp,@bounds.bottom, {:class => "gridlinev"})
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
protected
|
26
|
+
|
27
|
+
def grid_range_x
|
28
|
+
return parent.modelgroup.effective_round_range_x
|
29
|
+
end
|
30
|
+
|
31
|
+
def grid_range_y
|
32
|
+
return parent.modelgroup.effective_round_range_y0
|
33
|
+
end
|
34
|
+
|
35
|
+
|
36
|
+
end
|
37
|
+
|
38
|
+
end
|
@@ -0,0 +1,32 @@
|
|
1
|
+
module GerbilCharts::Surfaces
|
2
|
+
|
3
|
+
class HorizontalAxis < Axis
|
4
|
+
|
5
|
+
def initialize(opts={})
|
6
|
+
@class = "haxis"
|
7
|
+
super(opts)
|
8
|
+
end
|
9
|
+
|
10
|
+
def int_render(g)
|
11
|
+
super
|
12
|
+
|
13
|
+
return if parent.modelgroup.empty?
|
14
|
+
|
15
|
+
rx = parent.modelgroup.effective_round_range_x
|
16
|
+
rx.each_label do |val,label|
|
17
|
+
xp = scale_x val,rx
|
18
|
+
|
19
|
+
# make sure edge ones are visible
|
20
|
+
if (xp>=@bounds.right-10)
|
21
|
+
xp = @bounds.right-10
|
22
|
+
end
|
23
|
+
|
24
|
+
g.textout(xp, @bounds.top+10, label, {:class => "axislabel"})
|
25
|
+
g.line(xp,@bounds.top-2,xp,@bounds.top+3, {:class => "axistickmajor"})
|
26
|
+
end
|
27
|
+
|
28
|
+
end
|
29
|
+
|
30
|
+
end
|
31
|
+
|
32
|
+
end
|
@@ -0,0 +1,28 @@
|
|
1
|
+
module GerbilCharts::Surfaces
|
2
|
+
|
3
|
+
# = Horizontal name axis
|
4
|
+
#
|
5
|
+
# Draws names of models instead of values, used for bar charts
|
6
|
+
class HorizontalNameAxis < Axis
|
7
|
+
|
8
|
+
def initialize(opts={})
|
9
|
+
@class = "haxis"
|
10
|
+
super(opts)
|
11
|
+
end
|
12
|
+
|
13
|
+
def int_render(g)
|
14
|
+
super
|
15
|
+
|
16
|
+
# p "Horiz name axis #{parent.anchor.element_spacing} spacing"
|
17
|
+
xp = @bounds.left + parent.anchor.element_spacing + parent.anchor.element_width/2
|
18
|
+
parent.modelgroup.each_model_with_index do |m,i|
|
19
|
+
yoff=get_stagger_off(i,10)
|
20
|
+
g.textout(xp, @bounds.top+15+yoff, m.name, {:class => "axislabel","text-anchor" => "middle"})
|
21
|
+
xp += parent.anchor.element_width + parent.anchor.element_spacing
|
22
|
+
end
|
23
|
+
|
24
|
+
end
|
25
|
+
|
26
|
+
end
|
27
|
+
|
28
|
+
end
|
@@ -0,0 +1,25 @@
|
|
1
|
+
module GerbilCharts::Surfaces
|
2
|
+
|
3
|
+
# = HorizontalTimeAxis
|
4
|
+
# Draws time labels along x-axis
|
5
|
+
# Most charts use this type of x-axis in time series charts
|
6
|
+
class HorizontalTimeAxis < HorizontalAxis
|
7
|
+
|
8
|
+
def initialize(opts={})
|
9
|
+
@class = "haxis"
|
10
|
+
super(opts)
|
11
|
+
end
|
12
|
+
|
13
|
+
def int_render(g)
|
14
|
+
super
|
15
|
+
|
16
|
+
rx = parent.modelgroup.effective_round_range_x
|
17
|
+
sfmt = rx.format_min_value
|
18
|
+
g.textout(@bounds.left-20, @bounds.top+20, sfmt, {:class => "axislabelt0"})
|
19
|
+
g.line(@bounds.left,@bounds.top,@bounds.left,@bounds.top+10,{:class => "axistickmajor"})
|
20
|
+
|
21
|
+
end
|
22
|
+
|
23
|
+
end
|
24
|
+
|
25
|
+
end
|