Changeset 109 for trunk/src/bar.py

Show
Ignore:
Timestamp:
10/27/08 16:49:58 (4 years ago)
Author:
lgs
Message:

Some refactoring and support for negative values in line and bar charts. Inspired by Nicolas patch

Files:
1 modified

Legend:

Unmodified
Added
Removed
  • trunk/src/bar.py

    r97 r109  
    1717 
    1818from pycha.chart import Chart, uniqueIndices 
    19 from pycha.color import hex2rgb, clamp 
     19from pycha.color import hex2rgb 
    2020 
    2121class BarChart(Chart): 
     
    2828        self.barMargin = 0.0 
    2929 
     30    def _updateXY(self): 
     31        super(BarChart, self)._updateXY() 
     32        # each dataset is centered around a line segment. that's why we 
     33        # need n + 1 divisions on the x axis 
     34        self.xscale = 1 / (self.xrange + 1.0) 
     35 
    3036    def _updateChart(self): 
    3137        """Evaluates measures for vertical bars""" 
     
    3642        if len(uniqx) == 1: 
    3743            xdelta = 1.0 
    38             self.xscale = 1.0 
    39             self.minxval = uniqx[0] 
    4044            barWidth = 1.0 * self.options.barWidthFillFraction 
    4145            self.barWidthForSet = barWidth / len(stores) 
     
    4448            xdelta = min([abs(uniqx[j] - uniqx[j-1]) 
    4549                          for j in range(1, len(uniqx))]) 
    46             self.xscale = 1.0 / (self.xrange + 1) 
    4750            barWidth = xdelta * self.xscale * self.options.barWidthFillFraction 
    4851            self.barWidthForSet = barWidth / len(stores) 
     
    5760 
    5861        def drawBar(bar): 
    59             cx.set_line_width(self.options.stroke.width) 
     62            stroke_width = self.options.stroke.width 
     63            ux, uy = cx.device_to_user_distance(stroke_width, stroke_width) 
     64            if ux < uy: 
     65                ux = uy 
     66            cx.set_line_width(ux) 
    6067 
    6168            # gather bar proportions 
     
    7481                cx.fill() 
    7582 
    76             if self.options.shouldFill: 
     83            if self.options.shouldFill or (not self.options.stroke.hide): 
    7784                cx.rectangle(x, y, w, h) 
    78                 cx.set_source_rgb(*self.options.colorScheme[bar.name]) 
    79                 cx.fill_preserve() 
    8085 
    81             if not self.options.stroke.hide: 
    82                 cx.set_source_rgb(*hex2rgb(self.options.stroke.color)) 
    83                 cx.stroke() 
     86                if self.options.shouldFill: 
     87                    cx.set_source_rgb(*self.options.colorScheme[bar.name]) 
     88                    cx.fill_preserve() 
     89     
     90                if not self.options.stroke.hide: 
     91                    cx.set_source_rgb(*hex2rgb(self.options.stroke.color)) 
     92                    cx.stroke() 
    8493 
    8594        cx.save() 
     
    93102        """Evaluates measures for vertical bars""" 
    94103        super(VerticalBarChart, self)._updateChart() 
    95  
    96104        for i, (name, store) in enumerate(self.datasets): 
    97105            for item in store: 
    98106                xval, yval = item 
    99107                x = (((xval - self.minxval) * self.xscale) 
    100                     + (i * self.barWidthForSet) + self.barMargin) 
     108                    + self.barMargin + (i * self.barWidthForSet)) 
    101109                w = self.barWidthForSet 
    102                 h = (yval - self.minyval) * self.yscale 
    103                 y = 1.0 - h 
     110                h = abs(yval) * self.yscale 
     111                if yval > 0: 
     112                    y = (1.0 - h) - self.area.origin 
     113                else: 
     114                    y = 1 - self.area.origin 
    104115                rect = Rect(x, y, w, h, xval, yval, name) 
    105116 
     
    127138                xval, yval = item 
    128139                y = (((xval - self.minxval) * self.xscale) 
    129                      + (i * self.barWidthForSet) + self.barMargin) 
    130                 x = 0.0 
     140                     + self.barMargin  + (i * self.barWidthForSet)) 
    131141                h = self.barWidthForSet 
    132                 w = (yval - self.minyval) * self.yscale 
     142                w = abs(yval) * self.yscale 
     143                if yval > 0: 
     144                    x = self.area.origin 
     145                else: 
     146                    x = self.area.origin - w 
    133147                rect = Rect(x, y, w, h, xval, yval, name) 
    134148 
     
    153167        return (x, y-2, w+2, h+4) 
    154168 
     169    def _renderXAxis(self, cx): 
     170        """Draws the horizontal line representing the X axis""" 
     171        cx.new_path() 
     172        cx.move_to(self.area.x, self.area.y + self.area.h) 
     173        cx.line_to(self.area.x + self.area.w, self.area.y + self.area.h) 
     174        cx.close_path() 
     175        cx.stroke() 
     176 
     177    def _renderYAxis(self, cx): 
     178        # draws the vertical line representing the Y axis 
     179        cx.new_path() 
     180        cx.move_to(self.area.x + self.area.origin * self.area.w, 
     181                   self.area.y) 
     182        cx.line_to(self.area.x + self.area.origin * self.area.w, 
     183                   self.area.y + self.area.h) 
     184        cx.close_path() 
     185        cx.stroke() 
    155186 
    156187class Rect(object): 
     
    161192 
    162193    def __str__(self): 
    163         return "<pycha.bar.Rect@(%.2f, %.2f) %.2fx%.2f>" % (self.x, self.y, 
    164                                                             self.w, self.h) 
     194        return ("<pycha.bar.Rect@(%.2f, %.2f) %.2fx%.2f (%.2f, %.2f) %s>" 
     195                % (self.x, self.y, self.w, self.h, self.xval, self.yval, 
     196                   self.name))