@ -21,6 +21,36 @@ class Bar( Graph ):
self . fields = fields
super ( Bar , self ) . __init__ ( * args , * * kargs )
# adapted from Plot
def get_data_values ( self ) :
min_value , max_value , scale_division = self . data_range ( )
result = tuple ( float_range ( min_value , max_value + scale_division , scale_division ) )
if self . scale_integers :
result = map ( int , result )
return result
# adapted from plot (very much like calling data_range('y'))
def data_range ( self ) :
min_value = self . data_min ( )
max_value = self . data_max ( )
range = max_value - min_value
data_pad = range / 20.0 or 10
scale_range = ( max_value + data_pad ) - min_value
scale_division = self . scale_divisions or ( scale_range / 10.0 )
if self . scale_integers :
scale_division = round ( scale_division ) or 1
return min_value , max_value , scale_division
def get_field_labels ( self ) :
return self . fields
def get_data_labels ( self ) :
return map ( str , self . get_data_values ( ) )
def data_max ( self ) :
return max ( chain ( * map ( lambda set : set [ ' data ' ] , self . data ) ) )
# above is same as
@ -32,6 +62,15 @@ class Bar( Graph ):
min_value = min ( min_value , 0 )
return min_value
def get_bar_gap ( self , field_size ) :
bar_gap = 10 # default gap
if field_size < 10 :
# adjust for narrow fields
bar_gap = field_size / 2
# the following zero's out the gap if bar_gap is False
bar_gap = int ( self . bar_gap ) * bar_gap
return bar_gap
def get_css ( self ) :
return """ \
/ * default fill styles for multiple datasets ( probably only use a single dataset on this graph though ) * /
@ -172,36 +211,10 @@ class VerticalBar( Bar ):
top_align = top_font = 1
def get_x_labels ( self ) :
return self . fields
return self . get_ field_label s( )
# adapted from plot (very much like calling data_range('y'))
def data_range ( self ) :
min_value = self . data_min ( )
max_value = self . data_max ( )
range = max_value - min_value
top_pad = range / 20.0 or 10
scale_range = ( max_value + top_pad ) - min_value
scale_division = self . scale_divisions or ( scale_range / 10.0 )
if self . scale_integers :
scale_division = round ( scale_division ) or 1
return min_value , max_value , scale_division
# adapted from Plot
def get_data_values ( self ) :
min_value , max_value , scale_division = self . data_range ( )
result = tuple ( float_range ( min_value , max_value + scale_division , scale_division ) )
if self . scale_integers :
result = map ( int , result )
return result
# adapted from Plot
def get_y_labels ( self ) :
return map ( str , self . get_data_values ( ) )
return self . get_data_labels ( )
def x_label_offset ( self , width ) :
return width / 2.0
@ -210,12 +223,8 @@ class VerticalBar( Bar ):
min_value = self . data_min ( )
unit_size = ( float ( self . graph_height ) - self . font_size * 2 * self . top_font )
unit_size / = ( max ( self . get_data_values ( ) ) - min ( self . get_data_values ( ) ) )
bar_gap = 0
if self . bar_gap :
bar_gap = 10
if self . get_field_width ( ) < 10 :
bar_gap = self . get_field_width ( ) / 2
bar_gap = self . get_bar_gap ( self . get_field_width ( ) )
bar_width = self . get_field_width ( ) - bar_gap
if self . stack == ' side ' :
@ -254,3 +263,62 @@ class VerticalBar( Bar ):
self . graph . appendChild ( rect )
self . make_datapoint_text ( left + bar_width / 2.0 , top - 6 , value )
class HorizontalBar ( Bar ) :
rotate_y_labels = True
show_x_guidelines = True
show_y_guidelines = False
right_align = right_font = True
def get_x_labels ( self ) :
return self . get_data_labels ( )
def get_y_labels ( self ) :
return self . get_field_labels ( )
def y_label_offset ( self , height ) :
return height / - 2.0
def draw_data ( self ) :
min_value = self . data_min ( )
unit_size = float ( self . graph_width )
unit_size - = self . font_size * 2 * self . right_font
unit_size / = max ( self . get_data_values ( ) ) - min ( self . get_data_values ( ) )
bar_gap = self . get_bar_gap ( self . get_field_height ( ) )
bar_height = self . get_field_height ( ) - bar_gap
if self . stack == ' side ' :
bar_height / = len ( self . data )
y_mod = ( bar_height / 2 ) + ( self . font_size / 2 )
for field_count , field in enumerate ( self . fields ) :
for dataset_count , dataset in enumerate ( self . data ) :
value = dataset [ ' data ' ] [ field_count ]
top = self . graph_height - ( self . get_field_height ( ) * ( field_count + 1 ) )
if self . stack == ' side ' :
top + = ( bar_height * dataset_count )
# cases (assume 0 = +ve):
# value min length left
# +ve +ve value.abs - min minvalue.abs
# +ve -ve value.abs - 0 minvalue.abs
# -ve -ve value.abs - 0 minvalue.abs + value
length = ( abs ( value ) - max ( min_value , 0 ) ) * unit_size
# left is 0 if value is negative
left = ( abs ( min_value ) + min ( value , 0 ) ) * unit_size
rect = self . _create_element ( ' rect ' , {
' x ' : str ( left ) ,
' y ' : str ( top ) ,
' width ' : str ( length ) ,
' height ' : str ( bar_height ) ,
' class ' : ' fill %s ' % ( dataset_count + 1 ) ,
} )
self . graph . appendChild ( rect )
self . make_datapoint_text ( left + length + 5 , top + y_mod , value ,
" text-anchor: start; " )