From 6fef3d2823ba409bbb85bba7e4981dadaec7f4bc Mon Sep 17 00:00:00 2001 From: Florian Mounier Date: Tue, 23 Jun 2015 15:42:44 +0200 Subject: [PATCH] Allow line to be horizontal. Fix #204 --- demo/moulinrouge/tests.py | 26 ++++++++++++++++++++++++++ pygal/graph/line.py | 5 +++-- pygal/svg.py | 9 +++++++-- pygal/util.py | 4 ---- 4 files changed, 36 insertions(+), 8 deletions(-) diff --git a/demo/moulinrouge/tests.py b/demo/moulinrouge/tests.py index 5cc365b..b62c6ff 100644 --- a/demo/moulinrouge/tests.py +++ b/demo/moulinrouge/tests.py @@ -9,6 +9,7 @@ from pygal import ( from pygal.style import styles, Style, RotateStyle from pygal.colors import rotate +from pygal.graph.horizontal import HorizontalGraph from pygal.graph.frenchmap import DEPARTMENTS, REGIONS from pygal.graph.swissmap import CANTONS from random import randint, choice @@ -631,6 +632,31 @@ def get_test_routes(app): graph.legend_at_bottom = True return graph.render_response() + @app.route('/test/normal/') + def test_normal_for(chart): + graph = CHARTS_BY_NAME[chart]() + graph.add('1', [1, 3, 12, 3, 4, None, 9]) + graph.add('2', [7, -4, 10, None, 8, 3, 1]) + graph.add('3', [7, -14, -10, None, 8, 3, 1]) + graph.add('4', [7, 4, -10, None, 8, 3, 1]) + graph.x_labels = ('a', 'b', 'c', 'd', 'e', 'f', 'g') + graph.legend_at_bottom = True + return graph.render_response() + + @app.route('/test/horizontal_force/') + def test_horizontal_force_for(chart): + class H(CHARTS_BY_NAME[chart], HorizontalGraph): + pass + graph = H() + + graph.add('1', [1, 3, 12, 3, 4, None, 9]) + graph.add('2', [7, -4, 10, None, 8, 3, 1]) + graph.add('3', [7, -14, -10, None, 8, 3, 1]) + graph.add('4', [7, 4, -10, None, 8, 3, 1]) + graph.x_labels = ('a', 'b', 'c', 'd', 'e', 'f', 'g') + graph.legend_at_bottom = True + return graph.render_response() + @app.route('/test/inverse_y_axis/') def test_inverse_y_axis_for(chart): graph = CHARTS_BY_NAME[chart](**dict(inverse_y_axis=True)) diff --git a/pygal/graph/line.py b/pygal/graph/line.py index fe16568..d368e9b 100644 --- a/pygal/graph/line.py +++ b/pygal/graph/line.py @@ -109,8 +109,9 @@ class Line(Graph): self.svg.node(serie_node['overlay'], class_="dots"), metadata) val = self._get_value(serie.points, i) - self.svg.node(dots, 'circle', cx=x, cy=y, r=serie.dots_size, - class_='dot reactive tooltip-trigger') + self.svg.transposable_node( + dots, 'circle', cx=x, cy=y, r=serie.dots_size, + class_='dot reactive tooltip-trigger') self._tooltip_data( dots, val, x, y) self._static_value( diff --git a/pygal/svg.py b/pygal/svg.py index 21b1747..c0a5375 100644 --- a/pygal/svg.py +++ b/pygal/svg.py @@ -30,7 +30,7 @@ import json from datetime import date, datetime from numbers import Number from math import cos, sin, pi -from pygal.util import template, coord_format, minify_css +from pygal.util import template, minify_css from pygal import __version__ @@ -183,7 +183,7 @@ class Svg(object): def transposable_node(self, parent=None, tag='g', attrib=None, **extras): """Make a new svg node which can be transposed if horizontal""" if self.graph.horizontal: - for key1, key2 in (('x', 'y'), ('width', 'height')): + for key1, key2 in (('x', 'y'), ('width', 'height'), ('cx', 'cy')): attr1 = extras.get(key1, None) attr2 = extras.get(key2, None) extras[key1], extras[key2] = attr2, attr1 @@ -219,6 +219,11 @@ class Svg(object): origin_index += 1 if origin_index == line_len: return + if self.graph.horizontal: + coord_format = lambda xy: '%f %f' % (xy[1], xy[0]) + else: + coord_format = lambda xy: '%f %f' % xy + origin = coord_format(coords[origin_index]) line = ' '.join([coord_format(c) for c in coords[origin_index + 1:] diff --git a/pygal/util.py b/pygal/util.py index 563fda7..69d1f39 100644 --- a/pygal/util.py +++ b/pygal/util.py @@ -131,10 +131,6 @@ def template(string, **kwargs): return _swap_curly(string).format(**kwargs) -def coord_format(xy): - """Format x y coords to svg""" - return '%f %f' % xy - swap = lambda tuple_: tuple(reversed(tuple_)) ident = lambda x: x