Show
Ignore:
Timestamp:
03/12/09 04:22:03 (3 years ago)
Author:
lgs
Message:

Support for horizontal stacked bars. See #27

Files:
1 modified

Legend:

Unmodified
Added
Removed
  • trunk/pycha/stackedbar.py

    r161 r162  
    1616# along with PyCha.  If not, see <http://www.gnu.org/licenses/>. 
    1717 
    18 from pycha.bar import BarChart, VerticalBarChart 
     18from pycha.bar import BarChart, VerticalBarChart, HorizontalBarChart, Rect 
    1919from pycha.chart import uniqueIndices 
    20 from pycha.color import hex2rgb 
    2120 
    2221 
     
    8180            for item in store: 
    8281                xval, yval = item 
    83                 x = (xval - self.minxval) * self.xscale + self.barMargin 
     82                x = ((xval - self.minxval) * self.xscale) + self.barMargin 
    8483                w = self.barWidth 
    8584                h = abs(yval) * self.yscale 
     
    9998 
    10099 
    101 class StackedHorizontalBarChart(StackedBarChart): 
     100class StackedHorizontalBarChart(StackedBarChart, HorizontalBarChart): 
    102101 
    103102    def _updateChart(self): 
     
    105104        super(StackedHorizontalBarChart, self)._updateChart() 
    106105 
     106        accumulated_widths = {} 
    107107        for i, (name, store) in enumerate(self.datasets): 
    108108            for item in store: 
    109109                xval, yval = item 
    110                 y = (((xval - self.minxval) * self.xscale) 
    111                      + self.barMargin + (i * self.barWidth)) 
     110                y = ((xval - self.minxval) * self.xscale) + self.barMargin 
    112111                h = self.barWidth 
    113112                w = abs(yval) * self.yscale 
     
    116115                else: 
    117116                    x = self.area.origin - w 
     117 
     118                accumulated_width = accumulated_widths.setdefault(xval, 0) 
     119                x += accumulated_width 
     120                accumulated_widths[xval] += w 
     121 
    118122                rect = Rect(x, y, w, h, xval, yval, name) 
    119123 
    120124                if (0.0 <= rect.x <= 1.0) and (0.0 <= rect.y <= 1.0): 
    121125                    self.bars.append(rect) 
    122  
    123     def _updateTicks(self): 
    124         """Evaluates bar ticks""" 
    125         super(StackedBarChart, self)._updateTicks() 
    126         offset = (self.minxdelta * self.xscale) / 2 
    127         tmp = self.xticks 
    128         self.xticks = [(1.0 - tick[0], tick[1]) for tick in self.yticks] 
    129         self.yticks = [(tick[0] + offset, tick[1]) for tick in tmp] 
    130  
    131     def _renderLines(self, cx): 
    132         """Aux function for _renderBackground""" 
    133         ticks = self.xticks 
    134         for tick in ticks: 
    135             self._renderLine(cx, tick, True) 
    136  
    137     def _getShadowRectangle(self, x, y, w, h): 
    138         return (x, y-2, w+2, h+4) 
    139  
    140     def _renderXAxis(self, cx): 
    141         """Draws the horizontal line representing the X axis""" 
    142         cx.new_path() 
    143         cx.move_to(self.area.x, self.area.y + self.area.h) 
    144         cx.line_to(self.area.x + self.area.w, self.area.y + self.area.h) 
    145         cx.close_path() 
    146         cx.stroke() 
    147  
    148     def _renderYAxis(self, cx): 
    149         # draws the vertical line representing the Y axis 
    150         cx.new_path() 
    151         cx.move_to(self.area.x + self.area.origin * self.area.w, 
    152                    self.area.y) 
    153         cx.line_to(self.area.x + self.area.origin * self.area.w, 
    154                    self.area.y + self.area.h) 
    155         cx.close_path() 
    156         cx.stroke() 
    157  
    158     def _renderYVal(self, cx, label, labelW, labelH, barX, barY, barW, barH): 
    159         y = barY + (barH / 2.0) + (labelH / 2.0) 
    160         if self.options.yvals.inside: 
    161             x = barX + barW - (1.2 * labelW) 
    162         else: 
    163             x = barX + barW + 0.2 * labelW 
    164  
    165         # if the label doesn't fit to the left of the bar, put it to the right 
    166         if x < barX: 
    167             x = barX + barW + 0.2 * labelW 
    168  
    169         cx.move_to(x, y) 
    170         cx.show_text(label) 
    171  
    172  
    173 class Rect(object): 
    174  
    175     def __init__(self, x, y, w, h, xval, yval, name): 
    176         self.x, self.y, self.w, self.h = x, y, w, h 
    177         self.xval, self.yval = xval, yval 
    178         self.name = name 
    179  
    180     def __str__(self): 
    181         return ("<pycha.bar.Rect@(%.2f, %.2f) %.2fx%.2f (%.2f, %.2f) %s>" 
    182                 % (self.x, self.y, self.w, self.h, self.xval, self.yval, 
    183                    self.name))