annotate .svn/pristine/7a/7a4b4f0b94cad3a2b4fae68431d483c842aa13c3.svn-base @ 1298:4f746d8966dd redmine_2.3_integration

Merge from redmine-2.3 branch to create new branch redmine-2.3-integration
author Chris Cannam
date Fri, 14 Jun 2013 09:28:30 +0100
parents 622f24f53b42
children
rev   line source
Chris@1295 1 require 'rexml/document'
Chris@1295 2 require 'SVG/Graph/BarBase'
Chris@1295 3
Chris@1295 4 module SVG
Chris@1295 5 module Graph
Chris@1295 6 # === Create presentation quality SVG horitonzal bar graphs easily
Chris@1295 7 #
Chris@1295 8 # = Synopsis
Chris@1295 9 #
Chris@1295 10 # require 'SVG/Graph/BarHorizontal'
Chris@1295 11 #
Chris@1295 12 # fields = %w(Jan Feb Mar)
Chris@1295 13 # data_sales_02 = [12, 45, 21]
Chris@1295 14 #
Chris@1295 15 # graph = SVG::Graph::BarHorizontal.new({
Chris@1295 16 # :height => 500,
Chris@1295 17 # :width => 300,
Chris@1295 18 # :fields => fields,
Chris@1295 19 # })
Chris@1295 20 #
Chris@1295 21 # graph.add_data({
Chris@1295 22 # :data => data_sales_02,
Chris@1295 23 # :title => 'Sales 2002',
Chris@1295 24 # })
Chris@1295 25 #
Chris@1295 26 # print "Content-type: image/svg+xml\r\n\r\n"
Chris@1295 27 # print graph.burn
Chris@1295 28 #
Chris@1295 29 # = Description
Chris@1295 30 #
Chris@1295 31 # This object aims to allow you to easily create high quality
Chris@1295 32 # SVG horitonzal bar graphs. You can either use the default style sheet
Chris@1295 33 # or supply your own. Either way there are many options which can
Chris@1295 34 # be configured to give you control over how the graph is
Chris@1295 35 # generated - with or without a key, data elements at each point,
Chris@1295 36 # title, subtitle etc.
Chris@1295 37 #
Chris@1295 38 # = Examples
Chris@1295 39 #
Chris@1295 40 # * http://germane-software.com/repositories/public/SVG/test/test.rb
Chris@1295 41 #
Chris@1295 42 # = See also
Chris@1295 43 #
Chris@1295 44 # * SVG::Graph::Graph
Chris@1295 45 # * SVG::Graph::Bar
Chris@1295 46 # * SVG::Graph::Line
Chris@1295 47 # * SVG::Graph::Pie
Chris@1295 48 # * SVG::Graph::Plot
Chris@1295 49 # * SVG::Graph::TimeSeries
Chris@1295 50 #
Chris@1295 51 # == Author
Chris@1295 52 #
Chris@1295 53 # Sean E. Russell <serATgermaneHYPHENsoftwareDOTcom>
Chris@1295 54 #
Chris@1295 55 # Copyright 2004 Sean E. Russell
Chris@1295 56 # This software is available under the Ruby license[LICENSE.txt]
Chris@1295 57 #
Chris@1295 58 class BarHorizontal < BarBase
Chris@1295 59 # In addition to the defaults set in BarBase::set_defaults, sets
Chris@1295 60 # [rotate_y_labels] true
Chris@1295 61 # [show_x_guidelines] true
Chris@1295 62 # [show_y_guidelines] false
Chris@1295 63 def set_defaults
Chris@1295 64 super
Chris@1295 65 init_with(
Chris@1295 66 :rotate_y_labels => true,
Chris@1295 67 :show_x_guidelines => true,
Chris@1295 68 :show_y_guidelines => false
Chris@1295 69 )
Chris@1295 70 self.right_align = self.right_font = 1
Chris@1295 71 end
Chris@1295 72
Chris@1295 73 protected
Chris@1295 74
Chris@1295 75 def get_x_labels
Chris@1295 76 maxvalue = max_value
Chris@1295 77 minvalue = min_value
Chris@1295 78 range = maxvalue - minvalue
Chris@1295 79 top_pad = range == 0 ? 10 : range / 20.0
Chris@1295 80 scale_range = (maxvalue + top_pad) - minvalue
Chris@1295 81
Chris@1295 82 scale_division = scale_divisions || (scale_range / 10.0)
Chris@1295 83
Chris@1295 84 if scale_integers
Chris@1295 85 scale_division = scale_division < 1 ? 1 : scale_division.round
Chris@1295 86 end
Chris@1295 87
Chris@1295 88 rv = []
Chris@1295 89 maxvalue = maxvalue%scale_division == 0 ?
Chris@1295 90 maxvalue : maxvalue + scale_division
Chris@1295 91 minvalue.step( maxvalue, scale_division ) {|v| rv << v}
Chris@1295 92 return rv
Chris@1295 93 end
Chris@1295 94
Chris@1295 95 def get_y_labels
Chris@1295 96 @config[:fields]
Chris@1295 97 end
Chris@1295 98
Chris@1295 99 def y_label_offset( height )
Chris@1295 100 height / -2.0
Chris@1295 101 end
Chris@1295 102
Chris@1295 103 def draw_data
Chris@1295 104 minvalue = min_value
Chris@1295 105 fieldheight = field_height
Chris@1295 106
Chris@1295 107 unit_size = (@graph_width.to_f - font_size*2*right_font ) /
Chris@1295 108 (get_x_labels.max - get_x_labels.min )
Chris@1295 109 bargap = bar_gap ? (fieldheight < 10 ? fieldheight / 2 : 10) : 0
Chris@1295 110
Chris@1295 111 bar_height = fieldheight - bargap
Chris@1295 112 bar_height /= @data.length if stack == :side
Chris@1295 113 y_mod = (bar_height / 2) + (font_size / 2)
Chris@1295 114
Chris@1295 115 field_count = 1
Chris@1295 116 @config[:fields].each_index { |i|
Chris@1295 117 dataset_count = 0
Chris@1295 118 for dataset in @data
Chris@1295 119 value = dataset[:data][i]
Chris@1295 120
Chris@1295 121 top = @graph_height - (fieldheight * field_count)
Chris@1295 122 top += (bar_height * dataset_count) if stack == :side
Chris@1295 123 # cases (assume 0 = +ve):
Chris@1295 124 # value min length left
Chris@1295 125 # +ve +ve value.abs - min minvalue.abs
Chris@1295 126 # +ve -ve value.abs - 0 minvalue.abs
Chris@1295 127 # -ve -ve value.abs - 0 minvalue.abs + value
Chris@1295 128 length = (value.abs - (minvalue > 0 ? minvalue : 0)) * unit_size
Chris@1295 129 left = (minvalue.abs + (value < 0 ? value : 0)) * unit_size
Chris@1295 130
Chris@1295 131 @graph.add_element( "rect", {
Chris@1295 132 "x" => left.to_s,
Chris@1295 133 "y" => top.to_s,
Chris@1295 134 "width" => length.to_s,
Chris@1295 135 "height" => bar_height.to_s,
Chris@1295 136 "class" => "fill#{dataset_count+1}"
Chris@1295 137 })
Chris@1295 138
Chris@1295 139 make_datapoint_text(
Chris@1295 140 left+length+5, top+y_mod, value, "text-anchor: start; "
Chris@1295 141 )
Chris@1295 142 dataset_count += 1
Chris@1295 143 end
Chris@1295 144 field_count += 1
Chris@1295 145 }
Chris@1295 146 end
Chris@1295 147 end
Chris@1295 148 end
Chris@1295 149 end