Skip to content

Commit

Permalink
Finally fix horizontal bar
Browse files Browse the repository at this point in the history
  • Loading branch information
paradoxxxzero committed Oct 3, 2012
1 parent 5251b61 commit de14bc1
Show file tree
Hide file tree
Showing 6 changed files with 90 additions and 28 deletions.
15 changes: 15 additions & 0 deletions demo/moulinrouge/tests.py
Original file line number Diff line number Diff line change
Expand Up @@ -99,6 +99,21 @@ def test_dot():

return dot.render_response()

@app.route('/test/<chart>')
def test_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.x_labels = ('a', 'b', 'c', 'd', 'e', 'f', 'g')
return graph.render_response()

@app.route('/test/one/<chart>')
def test_one_for(chart):
graph = CHARTS_BY_NAME[chart]()
graph.add('1', [1, 2])
graph.x_labels = 'a',
return graph.render_response()

@app.route('/test/interpolate/<chart>')
def test_interpolate_for(chart):
graph = CHARTS_BY_NAME[chart](interpolate='cubic')
Expand Down
38 changes: 17 additions & 21 deletions pygal/graph/bar.py
Original file line number Diff line number Diff line change
Expand Up @@ -29,34 +29,31 @@
class Bar(Graph):
"""Bar graph"""

_series_margin = .06
_serie_margin = .06

def __init__(self, *args, **kwargs):
self._x_ranges = None
super(Bar, self).__init__(*args, **kwargs)

def _bar(self, parent, x, y, index):
width = self.view.x(1 / self._len)
margin = width * .1 * 0
x += margin
width -= 2 * margin
width = (self.view.x(1) - self.view.x(0)) / self._len
series_margin = width * self._series_margin
x += series_margin
width -= 2 * series_margin
width /= self._order
x += index * width
padding = width * .005 * 0
x += padding
width -= 2 * padding

y_0 = self.view.y(self.zero)
height = abs(y - y_0)
serie_margin = width * self._serie_margin
x += serie_margin
width -= 2 * serie_margin
height = self.view.y(self.zero) - y
r = self.rounded_bars * 1 if self.rounded_bars else 0
self.svg.transposable_node(
parent,
'rect',
x=x,
y=y,
rx=self.rounded_bars * 1 if self.rounded_bars else 0,
ry=self.rounded_bars * 1 if self.rounded_bars else 0,
width=width,
height=height,
parent, 'rect',
x=x, y=y, rx=r, ry=r, width=width, height=height,
class_='rect reactive tooltip-trigger')
return (x + width / 2, y + height / 2)
transpose = swap if self.horizontal else ident
return transpose((x + width / 2, y + height / 2))

def bar(self, serie_node, serie, index):
"""Draw a bar graph for a serie"""
Expand Down Expand Up @@ -91,9 +88,8 @@ def _compute(self):
self._box.ymin, self._box.ymax, self.logarithmic, self.order_min
) if not self.y_labels else map(float, self.y_labels)

# self._x_ranges = zip(x_pos, x_pos[1:])
self._x_labels = self.x_labels and zip(self.x_labels, [
sum(x_range) / 2 for x_range in self._x_ranges])
(i + .5) / self._len for i in range(self._len)])
self._y_labels = zip(map(self._format, y_pos), y_pos)

def _plot(self):
Expand Down
7 changes: 2 additions & 5 deletions pygal/graph/graph.py
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@
from __future__ import division
from pygal.interpolate import interpolation
from pygal.graph.base import BaseGraph
from pygal.view import View, XLogView, YLogView, XYLogView
from pygal.view import View, XLogView, YLogView, XYLogView, HorizontalView
from pygal.util import is_major, truncate, reverse_text_len
from math import isnan, pi, sqrt, ceil

Expand All @@ -50,8 +50,6 @@ def _set_view(self):
if self.logarithmic:
if self.__class__.__name__ == 'XY':
view_class = XYLogView
elif self.horizontal:
view_class = XLogView
else:
view_class = YLogView
else:
Expand Down Expand Up @@ -104,7 +102,7 @@ def _make_graph(self):
self.svg.node(a, 'rect',
id="tooltip-box",
rx=5, ry=5, width=0, height=0
)
)
text = self.svg.node(a, 'text', class_='text')
self.svg.node(text, 'tspan', class_='label')
self.svg.node(text, 'tspan', class_='value')
Expand All @@ -113,7 +111,6 @@ def _x_axis(self, draw_axes=True):
"""Make the x axis: labels and guides"""
if not self._x_labels:
return

axis = self.svg.node(self.nodes['plot'], class_="axis x")
truncation = self.truncate_label
if not truncation:
Expand Down
19 changes: 18 additions & 1 deletion pygal/graph/horizontal.py
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@
"""
from pygal.graph.graph import Graph
from pygal.view import HorizontalView, XLogView


class HorizontalGraph(Graph):
Expand All @@ -32,4 +33,20 @@ def __init__(self, *args, **kwargs):
def _compute(self):
super(HorizontalGraph, self)._compute()
self._x_labels, self._y_labels = self._y_labels, self._x_labels
self._box.swap()

def _axes(self):
self.view._force_vertical = True
super(HorizontalGraph, self)._axes()
self.view._force_vertical = False

def _set_view(self):
"""Assign a view to current graph"""
if self.logarithmic:
view_class = XLogView
else:
view_class = HorizontalView

self.view = view_class(
self.width - self.margin.x,
self.height - self.margin.y,
self._box)
11 changes: 11 additions & 0 deletions pygal/svg.py
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@
import os
import json
from datetime import date
from numbers import Number
from lxml import etree
from math import cos, sin, pi
from urlparse import urlparse
Expand Down Expand Up @@ -96,6 +97,16 @@ def node(self, parent=None, tag='g', attrib=None, **extras):
parent = self.root
attrib = attrib or {}
attrib.update(extras)

def in_attrib_and_number(key):
return key in attrib and isinstance(attrib[key], Number)

for pos, dim in (('x', 'width'), ('y', 'height')):
if in_attrib_and_number(dim) and attrib[dim] < 0:
attrib[dim] = - attrib[dim]
if in_attrib_and_number(pos):
attrib[pos] = attrib[pos] - attrib[dim]

for key, value in attrib.items():
if value is None:
del attrib[key]
Expand Down
28 changes: 27 additions & 1 deletion pygal/view.py
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,7 @@ def height(self):
return self.ymax - self.ymin

def swap(self):
"""Return the box (for horizontal qraphs)"""
"""Return the box (for horizontal graphs)"""
self.xmin, self.ymin = self.ymin, self.xmin
self.xmax, self.ymax = self.ymax, self.xmax

Expand Down Expand Up @@ -111,6 +111,32 @@ def __call__(self, xy):
return (self.x(x), self.y(y))


class HorizontalView(View):
def __init__(self, width, height, box):
self._force_vertical = None
self.width = width
self.height = height

self.box = box
self.box.fix()
self.box.swap()

def x(self, x):
"""Project x"""
if x is None:
return None
if self._force_vertical:
return super(HorizontalView, self).x(x)
return super(HorizontalView, self).y(x)

def y(self, y):
if y is None:
return None
if self._force_vertical:
return super(HorizontalView, self).y(y)
return super(HorizontalView, self).x(y)


class PolarView(View):
"""Polar projection for pie like graphs"""

Expand Down

0 comments on commit de14bc1

Please sign in to comment.