gerbilcharts 0.2.4 → 0.2.5

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.
@@ -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