From 6c0355d7194c60dcb778bb34a3df5a9bac511f37 Mon Sep 17 00:00:00 2001 From: Agustin Zubiaga Date: Mon, 02 Jul 2012 00:48:34 +0000 Subject: Some charts.py fixes (sugarpycha) --- (limited to 'sugarpycha/line.py') diff --git a/sugarpycha/line.py b/sugarpycha/line.py new file mode 100644 index 0000000..9b12152 --- /dev/null +++ b/sugarpycha/line.py @@ -0,0 +1,129 @@ +# Copyright(c) 2007-2010 by Lorenzo Gil Sanchez +# +# This file is part of PyCha. +# +# PyCha is free software: you can redistribute it and/or modify +# it under the terms of the GNU Lesser General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# PyCha is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public License +# along with PyCha. If not, see . + +from pycha.chart import Chart +from pycha.color import hex2rgb + + +class LineChart(Chart): + + def __init__(self, surface=None, options={}, debug=False): + super(LineChart, self).__init__(surface, options, debug) + self.points = [] + + def _updateChart(self): + """Evaluates measures for line charts""" + self.points = [] + + for i, (name, store) in enumerate(self.datasets): + for item in store: + xval, yval = item + x = (xval - self.minxval) * self.xscale + y = 1.0 - (yval - self.minyval) * self.yscale + point = Point(x, y, xval, yval, name) + + if 0.0 <= point.x <= 1.0 and 0.0 <= point.y <= 1.0: + self.points.append(point) + + def _renderChart(self, cx): + """Renders a line chart""" + + def preparePath(storeName): + cx.new_path() + firstPoint = True + lastX = None + if self.options.shouldFill: + # Go to the (0,0) coordinate to start drawing the area + #cx.move_to(self.layout.chart.x, + # self.layout.chart.y + self.layout.chart.h) + offset = (1.0 - self.origin) * self.layout.chart.h + cx.move_to(self.layout.chart.x, self.layout.chart.y + offset) + + for point in self.points: + if point.name == storeName: + if not self.options.shouldFill and firstPoint: + # starts the first point of the line + cx.move_to(point.x * self.layout.chart.w + + self.layout.chart.x, + point.y * self.layout.chart.h + + self.layout.chart.y) + firstPoint = False + continue + cx.line_to(point.x * self.layout.chart.w + + self.layout.chart.x, + point.y * self.layout.chart.h + + self.layout.chart.y) + # we remember the last X coordinate to close the area + # properly. See bug #4 + lastX = point.x + + if self.options.shouldFill: + # Close the path to the start point + y = ((1.0 - self.origin) * self.layout.chart.h + + self.layout.chart.y) + cx.line_to(lastX * self.layout.chart.w + + self.layout.chart.x, y) + cx.line_to(self.layout.chart.x, y) + cx.close_path() + else: + cx.set_source_rgb(*self.colorScheme[storeName]) + cx.stroke() + + cx.save() + cx.set_line_width(self.options.stroke.width) + if self.options.shouldFill: + + def drawLine(storeName): + if self.options.stroke.shadow: + # draw shadow + cx.save() + cx.set_source_rgba(0, 0, 0, 0.15) + cx.translate(2, -2) + preparePath(storeName) + cx.fill() + cx.restore() + + # fill the line + cx.set_source_rgb(*self.colorScheme[storeName]) + preparePath(storeName) + cx.fill() + + if not self.options.stroke.hide: + # draw stroke + cx.set_source_rgb(*hex2rgb(self.options.stroke.color)) + preparePath(storeName) + cx.stroke() + + # draw the lines + for key in self._getDatasetsKeys(): + drawLine(key) + else: + for key in self._getDatasetsKeys(): + preparePath(key) + + cx.restore() + + +class Point(object): + + def __init__(self, x, y, xval, yval, name): + self.x, self.y = x, y + self.xval, self.yval = xval, yval + self.name = name + + def __str__(self): + return "" % (self.x, self.y) -- cgit v0.9.1