annotate lib/SVG/Graph/BarHorizontal.rb @ 1517:dffacf8a6908 redmine-2.5

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