annotate .svn/pristine/7a/7a4b4f0b94cad3a2b4fae68431d483c842aa13c3.svn-base @ 1519:afce8026aaeb redmine-2.4-integration

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