gerbilcharts 0.2.4 → 0.2.5

Sign up to get free protection for your applications and to get access to all the features.
@@ -9,41 +9,43 @@ class AreaSurface < Surface
9
9
  end
10
10
 
11
11
  def int_render(g)
12
-
13
-
14
12
  range_options_x = parent.get_global_option(:scaling_x,:auto)
15
13
  range_options_y = parent.get_global_option(:scaling_y,:auto)
14
+ butterfly = parent.get_global_option(:butterfly,false)
15
+
16
16
  rx = parent.modelgroup.effective_range_x(range_options_x)
17
17
  ry = parent.modelgroup.effective_range_y(range_options_y)
18
18
 
19
- p "range y = #{ry}"
20
-
21
19
  # ajax if used
22
20
  if parent.usesAjax?
23
21
  set_ajaxSurfaceContext(rx.rmax,ry.rmax,"AREA")
24
22
  end
25
23
 
24
+ # butterfly chart
25
+ ry.update(-ry.rmax) if butterfly
26
+
27
+ y_zero = scale_y 0,ry
26
28
 
27
29
  parent.modelgroup.each_model_with_index do | mod, i|
28
-
29
30
  g.begin_polygon
30
31
  firstpoint=true
31
32
  xpos=0
32
33
  ypos=0
33
34
  mod.each_tuple do |x,y|
35
+
36
+ y =-y if butterfly and i.odd?
37
+
34
38
  xpos = scale_x x,rx
35
39
  ypos = scale_y y,ry
36
40
  if firstpoint
37
- g.polygon_point xpos,@bounds.bottom
41
+ g.polygon_point xpos,y_zero
38
42
  firstpoint=false
39
43
  end
40
44
  g.polygon_point xpos,ypos
41
45
  end
42
- g.polygon_point xpos,@bounds.bottom
46
+ g.polygon_point xpos,y_zero
43
47
  g.end_polygon(:id => "item#{i}", "opacity"=>"0.3")
44
- g.rectangle(xpos+2*i,ypos,(i+1)*2,@bounds.bottom-ypos,{:id => "item#{i}"})
45
48
  end
46
-
47
49
  end
48
50
 
49
51
  end
@@ -51,8 +51,10 @@ class BarSurface < Surface
51
51
  if parent.get_global_option(:auto_tooltips,false)
52
52
  opts.merge!(:onmouseover => "OpacityDown(evt)", :onmouseout => "OpacityUp(evt)")
53
53
  opts.store(:gerbiltooltip1, mod.name)
54
- opts.store(:gerbiltooltip2, "Val = #{mod.latest_val}")
54
+ opts.store(:gerbiltooltip2, "Val = #{mod.latest_val}")
55
55
  end
56
+
57
+ opts.merge!(:href => mod.href) if mod.hasHref?
56
58
 
57
59
  # draw the bar
58
60
  g.rectangle(xpos, ypos, @element_width, @bounds.bottom - ypos, opts)
@@ -31,7 +31,7 @@ class Chart < GraphElement
31
31
  # The second parameter says if you want the js inlined in the HTML.
32
32
  #
33
33
  def set_defaults
34
- @javascripts = { "/javascripts/gerbil.js" => false, "/javascripts/prototype.js" => false }
34
+ @javascripts = { "gerbil.js" => true }
35
35
  end
36
36
 
37
37
  def set_modelgroup(g)
@@ -79,11 +79,9 @@ class GraphElement
79
79
 
80
80
  # setup SVG group element and call int_render
81
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
82
+ sdc.newwin(@group) do |sdc|
83
+ int_render(sdc)
84
+ end
87
85
  end
88
86
 
89
87
  # render direct - directly render SVG using builder for complex elements
@@ -145,11 +143,7 @@ class GraphElement
145
143
 
146
144
  # query a global option, return the defval if option is not set
147
145
  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
146
+ @global_chart_options[optsym] || defval
153
147
  end
154
148
 
155
149
  # utility methods to derived classes
@@ -12,35 +12,43 @@ class Grid < GraphElement
12
12
  end
13
13
 
14
14
  def int_render(g)
15
+ ry = grid_range_y
16
+ rx = grid_range_x
15
17
 
16
18
  # horizontal grid lines
17
- ry = grid_range_y
18
- ry.each_label do |val,label|
19
- yp = scale_y val,ry
20
- g.line(@bounds.left,yp,@bounds.right,yp, {:class => "gridlineh"})
21
- end
19
+ g.newwin('hgrid', {:class => "gridlineh"} ) do |g|
20
+ ry.each_label do |val,label|
21
+ yp = scale_y val,ry
22
+ g.line(@bounds.left,yp,@bounds.right,yp)
23
+ end
24
+ end
22
25
 
23
26
  # horiz subticks
24
- ry = grid_range_y
25
- ry.each_tick(@tick_count) do |val|
26
- yp = scale_y val,ry
27
- g.line(@bounds.left,yp,@bounds.right,yp, {:class => "gridlinesub"})
28
- end
29
-
27
+ g.newwin('hgridsub', {:class => "gridlinesub"} ) do |g|
28
+ ry.each_tick(@tick_count) do |val|
29
+ yp = scale_y val,ry
30
+ g.line(@bounds.left,yp,@bounds.right,yp)
31
+ end
32
+ end
30
33
 
31
34
 
32
35
  # vertical subticks
33
- rx = grid_range_x
34
- rx.each_label do |val,label|
35
- xp = scale_x val,rx
36
- g.line(xp,@bounds.top,xp,@bounds.bottom, {:class => "gridlinev"})
37
- end
38
-
39
- rx.each_tick(0) do |val|
40
- xp = scale_x val,rx
41
- g.line(xp,@bounds.top,xp,@bounds.bottom, {:class => "gridlinesub"})
36
+ g.newwin('vgrid', {:class => "gridlinev"} ) do |g|
37
+ rx.each_label do |val,label|
38
+ xp = scale_x val,rx
39
+ g.line(xp,@bounds.top,xp,@bounds.bottom)
40
+ end
41
+ end
42
+
43
+
44
+ g.newwin('vgridsub', {:class => "gridlinesub"} ) do |g|
45
+ rx.each_tick(0) do |val|
46
+ xp = scale_x val,rx
47
+ g.line(xp,@bounds.top,xp,@bounds.bottom)
48
+ end
42
49
  end
43
50
 
51
+
44
52
  end
45
53
 
46
54
  protected
@@ -17,6 +17,8 @@ class Legend < GraphElement
17
17
  # count determines the bounds
18
18
  @bounds.bottom = @bounds.top + 15 * parent.modelgroup.count
19
19
  g.rectangle_r(@bounds, {:class => @class})
20
+
21
+ g.rectangle(@bounds.left-5,@bounds.top,5,5)
20
22
 
21
23
  rbox = Rect.new
22
24
  rbox.initfrom(@bounds)
@@ -29,7 +31,6 @@ class Legend < GraphElement
29
31
 
30
32
  # Adding tool tips
31
33
  opts = { :class => "legendtext" }
32
- parent.get_global_option(:auto_tooltips,false)
33
34
  opts.merge!(:onmouseover => "OpacityDown(evt)", :onmouseout => "OpacityUp(evt)")
34
35
  opts.store(:gerbiltooltip1, mod.name)
35
36
  opts.store(:gerbiltooltip2, "Val = #{mod.latest_val}")
@@ -44,21 +45,14 @@ class Legend < GraphElement
44
45
 
45
46
  end
46
47
 
47
-
48
48
  def align_to_anchor(anc)
49
49
  super
50
-
51
50
  @bounds.deflate_v(10,10)
52
51
  @bounds.deflate_h(2,4)
53
-
54
52
  if @width
55
53
  @bounds.left = @bounds.right - @width
56
54
  end
57
-
58
55
  end
59
-
60
-
61
56
  end
62
-
63
57
  end
64
58
 
@@ -18,9 +18,13 @@ class LineSurface < Surface
18
18
 
19
19
  range_options_x = parent.get_global_option(:scaling_x,:auto)
20
20
  range_options_y = parent.get_global_option(:scaling_y,:auto)
21
+ butterfly = parent.get_global_option(:butterfly,false)
22
+
21
23
  rx = parent.modelgroup.effective_range_x(range_options_x)
22
24
  ry = parent.modelgroup.effective_range_y(range_options_y)
23
-
25
+
26
+ ry.update(-ry.rmax) if butterfly
27
+
24
28
  # ajax if used
25
29
  if parent.usesAjax?
26
30
  set_ajaxSurfaceContext(rx.rmax,ry.rmax,"LINE")
@@ -30,12 +34,13 @@ class LineSurface < Surface
30
34
 
31
35
  mod.each_tuple do |x,y|
32
36
 
37
+ y = -y if butterfly and i.odd?
38
+
33
39
  # the basic line
34
40
  xpos = scale_x x,rx
35
41
  ypos = scale_y y,ry
36
42
  g.lineto xpos,ypos
37
43
 
38
-
39
44
  # datapoint and a tooltip
40
45
  opts = {:id => "item#{i}"}
41
46
  if parent.get_global_option(:auto_tooltips,false)
@@ -73,6 +73,7 @@ class PieSurface < Surface
73
73
  opts.store(:gerbiltooltip1, mod.name)
74
74
  opts.store(:gerbiltooltip2, "Val = #{mod.latest_val}")
75
75
  end
76
+ opts.merge!(:href => mod.href) if mod.hasHref?
76
77
 
77
78
  # draw the slice
78
79
  g.addshape(GerbilCharts::SVGDC::SVGArc.new(cx,cy,radius,radius,
@@ -11,7 +11,7 @@ class StackedAreaSurface < Surface
11
11
  def int_render(g)
12
12
  rx = parent.modelgroup.effective_round_range_x
13
13
  ry = parent.modelgroup.cumulative_sweep_round_range_y0
14
-
14
+
15
15
  # ajax if used
16
16
  if parent.usesAjax?
17
17
  set_ajaxSurfaceContext(rx.rmax,ry.rmax,"SA")
@@ -21,9 +21,11 @@ class StackedAreaSurface < Surface
21
21
  sweep_pos= rx.rmin
22
22
  sweep_to = rx.rmax
23
23
  polygons = []
24
+ modnames = []
24
25
  parent.modelgroup.each_model do | mod|
25
26
  mod.begin_sweep
26
27
  polygons << GerbilCharts::SVGDC::SVGPolygon.new
28
+ modnames << mod.name
27
29
  end
28
30
 
29
31
  # sweep interval
@@ -46,14 +48,22 @@ class StackedAreaSurface < Surface
46
48
 
47
49
  sweep_pos += sweep_interval
48
50
  end
49
- # layout all polygons in reverse
50
- i=polygons.length-1
51
- last_x = scale_x sweep_to,rx
52
- polygons.reverse_each do |p|
51
+
52
+ # layout all polygons in reverse
53
+ i=polygons.length-1
54
+ last_x = scale_x sweep_to,rx
55
+ polygons.reverse_each do |p|
53
56
  p.addpoint(last_x,@bounds.bottom)
54
- g.addshape(p,{:id => "item#{i}"})
57
+
58
+ opts = {:id => "item#{i}" }
59
+ if parent.get_global_option(:auto_tooltips,false)
60
+ opts.merge!(:onmouseover => "OpacityDown(evt)", :onmouseout => "OpacityUp(evt)")
61
+ opts.store(:gerbiltooltip1, modnames[i])
62
+ end
63
+
64
+ g.addshape(p,opts)
55
65
  i -= 1
56
- end
66
+ end
57
67
 
58
68
  end
59
69
 
@@ -11,7 +11,7 @@ class Surface < GraphElement
11
11
  end
12
12
 
13
13
  def int_render(g)
14
- end
14
+ end
15
15
 
16
16
  def set_ajaxSurfaceContext(mxx, mxy, type)
17
17
  parent.set_ajaxContext(:axmxx => mxx, :axmxy => mxy, :axsurface => type)
@@ -23,6 +23,11 @@ class Tracker < GraphElement
23
23
  # calculate scaling factors
24
24
  rx = parent.modelgroup.effective_round_range_x
25
25
 
26
+ xfrag.g(:id=> 'gtrackerrect', :visibility=>'hidden') {
27
+ xfrag.rect(:id=>"trackerrect", :class=>"trackerrect",
28
+ :height=>parent.anchor.bounds.height, :width=>30, :x=>100, :y=>parent.anchor.bounds.top)
29
+ }
30
+
26
31
  # output the SVG fragment directly
27
32
  xfrag.g(:id => 'gtrackerpanel') {
28
33
  xfrag.rect(:id=>"trackerpanel", :class=>"trackerpanel",
@@ -32,10 +37,6 @@ class Tracker < GraphElement
32
37
  :onmouseup=>"TrackerMouseUp(evt)")
33
38
  }
34
39
 
35
- xfrag.g(:id=> 'gtrackerrect', :visibility=>'hidden') {
36
- xfrag.rect(:id=>"trackerrect", :class=>"trackerrect",
37
- :height=>parent.anchor.bounds.height, :width=>30, :x=>100, :y=>parent.anchor.bounds.top)
38
- }
39
40
 
40
41
  ty = parent.anchor.bounds.height/2
41
42
  xfrag.g(:id=> 'gtrackertext', :visibility=>'hidden', :transform => "translate(200 50)") {
@@ -49,8 +50,11 @@ class Tracker < GraphElement
49
50
  }
50
51
  }
51
52
 
52
- xfrag.g(:id=>"gtrackerdata",
53
- :gerb_fromts=>rx.rmin,
53
+ raise "Time Tracker expects X-Axis to be a time interval " unless rx.rmin.is_a? Time
54
+
55
+
56
+ xfrag.g(:id=>"gtrackerdata", :visibility=>'hidden',
57
+ :gerb_fromts=>rx.rmin.tv_sec,
54
58
  :gerb_scale =>(rx.delta)/parent.anchor.bounds.width,
55
59
  :gerb_selts=>"1",
56
60
  :gerb_selsecs=>"1")
@@ -13,6 +13,7 @@ class VerticalAxis < Axis
13
13
 
14
14
  @use_cumulative_y = false
15
15
  @use_cumulative_y = opts[:cumulative] if opts[:cumulative]
16
+ @butterfly=true
16
17
  end
17
18
 
18
19
  def int_render(g)
@@ -21,13 +22,15 @@ class VerticalAxis < Axis
21
22
 
22
23
  return if parent.modelgroup.empty?
23
24
 
24
- p "axis = #{parent.get_global_option(:scaling_y,false)}"
25
25
  if @use_cumulative_y
26
26
  ry = parent.modelgroup.cumulative_sweep_round_range_y0
27
27
  else
28
28
  ry = parent.modelgroup.effective_range_y(parent.get_global_option(:scaling_y,:auto))
29
29
  end
30
30
 
31
+ ry.update(-ry.rmax) if @butterfly
32
+
33
+
31
34
  ry.each_label do |val,label|
32
35
  yp = scale_y val,ry
33
36
  yp_label=yp
@@ -24,8 +24,9 @@ class SVGDC
24
24
  attr_accessor :height
25
25
  attr_reader :curr_win, :base_win
26
26
  attr_reader :curr_presentation_context
27
- attr_reader :svg_styles
28
27
  attr_reader :svg_predefs
28
+ attr_reader :svg_styles
29
+ attr_reader :ref_styles
29
30
  attr_reader :svg_javascript
30
31
  attr_reader :ref_javascripts
31
32
  attr_reader :ajaxOptions
@@ -46,26 +47,25 @@ class SVGDC
46
47
  # Searches for the stylesheet in the current directory or in the gerbilcharts/public directory
47
48
  # If you want to use your own stylesheets put them in the working directory, or in the
48
49
  # public directory of gerbilcharts.
49
- def set_stylesheet(cssfile)
50
- if File.exists? cssfile
51
- @svg_styles=File.read(cssfile)
50
+ # To inline stylesheet use "inline:<stylesheetname>" , eg "inline:brushmetal.css"
51
+ # Default is to xref a stylesheet
52
+ def set_stylesheet(cssfile_in)
53
+ cssfile=cssfile_in.gsub(/^inline:/,'')
54
+
55
+ if cssfile.length < cssfile_in.length
56
+ @svg_styles = get_file_content(cssfile)
52
57
  else
53
- try_from_gem = File.dirname(__FILE__) + "/../public/" + cssfile
54
- if not File.exists? try_from_gem
55
- p "The stylesheet #{cssfile} was not found. Make sure it exists in the current directory, or in the gem public area"
56
- raise "Stylesheet #{cssfile} not found in current directory or in the gerbilcharts/public folder"
57
- else
58
- @svg_styles=File.read(try_from_gem)
59
- end
58
+ @ref_styles = cssfile
60
59
  end
60
+
61
61
  end
62
62
 
63
63
  def add_javascriptfile(jsfile,inlined)
64
64
  if inlined
65
- @svg_javascript = "" if @svg_javascript == nil
66
- @svg_javascript << File.read(jsfile)
65
+ @svg_javascript ||= ""
66
+ @svg_javascript << get_file_content(jsfile)
67
67
  else
68
- @ref_javascripts = [] if @ref_javascripts == nil
68
+ @ref_javascripts ||= []
69
69
  @ref_javascripts << jsfile
70
70
  end
71
71
  end
@@ -103,9 +103,16 @@ class SVGDC
103
103
  def newwin(name, opts={})
104
104
  w=SVGWin.new(name, opts)
105
105
  @curr_win << w
106
- w
106
+ @curr_win = w
107
+ yield self if block_given?
108
+ reset if block_given?
109
+ return w if not block_given?
107
110
  end
108
111
 
112
+ def reset
113
+ @curr_win = @base_win
114
+ end
115
+
109
116
  def setactivewindow(w=nil)
110
117
  @curr_win = w ? w : @base_win
111
118
  end
@@ -132,9 +139,7 @@ class SVGDC
132
139
  doc.svg(svg_attributes) {
133
140
 
134
141
  # stylesheet (inlined into SVG)
135
- if @svg_styles
136
- doc.style(@svg_styles, :type => "text/css")
137
- end
142
+ doc.style(@svg_styles, :type => "text/css") if @svg_styles
138
143
 
139
144
  # javascripts (ajax, etc) hrefed
140
145
  if @ref_javascripts
@@ -208,8 +213,12 @@ class SVGDC
208
213
  doc = Builder::XmlMarkup.new(:target => svg_string, :indent => 2, :standalone => "no")
209
214
  doc.instruct!
210
215
  doc.declare! :DOCTYPE, :svg, :PUBLIC,"-//W3C//DTD SVG 1.1//EN","http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"
211
-
212
216
 
217
+ # stylesheet instruction if hreferenced
218
+ if @ref_styles
219
+ doc.instruct! "xml-stylesheet", :href => @ref_styles, :type => "text/css"
220
+ end
221
+
213
222
  render_to_frag(doc,opts)
214
223
 
215
224
  # return the svg_string
@@ -331,6 +340,19 @@ class SVGDC
331
340
  @curr_presentation_context = []
332
341
  end
333
342
 
343
+ private
344
+
345
+ # search for the file in the current directory or the gem path
346
+ def get_file_content(fname)
347
+ if File.exists? fname
348
+ return File.read(fname)
349
+ else
350
+ try_from_gem = File.dirname(__FILE__) + "/../public/" + fname
351
+ return File.read(try_from_gem) if File.exists? try_from_gem
352
+ end
353
+ raise "Resource #{fname} not found in current directory or in the gerbilcharts/public folder"
354
+ end
355
+
334
356
  end
335
357
 
336
358
  end