Browse Source

Work on refactoring bars (WIP)

pull/8/head
Florian Mounier 12 years ago
parent
commit
5251b614da
  1. 7
      demo/moulinrouge/tests.py
  2. 112
      pygal/graph/bar.py
  3. 12
      pygal/graph/graph.py
  4. 12
      pygal/graph/line.py
  5. 18
      pygal/graph/stackedbar.py
  6. 1
      pygal/graph/stackedline.py

7
demo/moulinrouge/tests.py

@ -131,6 +131,13 @@ def get_test_routes(app):
graph.add('1', [10, 0, -10])
return graph.render_response()
@app.route('/test/bar')
def test_bar():
bar = Bar()
bar.add('1', [1, 2, 3])
bar.add('2', [4, 5, 6])
return bar.render_response()
@app.route('/test/stacked')
def test_stacked():
stacked = StackedBar()

112
pygal/graph/bar.py

@ -33,86 +33,50 @@ class Bar(Graph):
self._x_ranges = None
super(Bar, self).__init__(*args, **kwargs)
def bar(self, serie_node, serie, values, index, stack_vals=None):
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._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)
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,
class_='rect reactive tooltip-trigger')
return (x + width / 2, y + height / 2)
def bar(self, serie_node, serie, index):
"""Draw a bar graph for a serie"""
# value here is a list of tuple range of tuple coord
def view(rng):
"""Project range"""
t, T = rng
fun = swap if self.horizontal else ident
return self.view(fun(t)), self.view(fun(T))
bars = self.svg.node(serie_node['plot'], class_="bars")
view_values = map(view, values)
for i, ((x, y), (X, Y)) in enumerate(view_values):
view_values = map(self.view, serie.points)
for i, (x, y) in enumerate(view_values):
if None in (x, y):
continue
# +-------+
# | |
# | |
# | +-------+
# | | |
# | | |
# | | |
# +-------+-------+
# (x,y) (X,Y)
#
# x and y are left range coords and X, Y right ones
metadata = serie.metadata.get(i)
val = self._format(values[i][1][1])
if self.horizontal:
x, y, X, Y = Y, X, y, x
width = X - x
padding = .1 * width
inner_width = width - 2 * padding
if self.horizontal:
height = self.view.x(self.zero) - y
else:
height = self.view.y(self.zero) - y
if stack_vals is None:
bar_width = inner_width / self._order
bar_padding = .1 * bar_width
bar_inner_width = bar_width - 2 * bar_padding
offset = index * bar_width + bar_padding
shift = 0
else:
offset = 0
bar_inner_width = inner_width
shift = stack_vals[i][int(height < 0)]
stack_vals[i][int(height < 0)] += height
x = x + padding + offset
if height < 0:
y = y + height
height = -height
y -= shift
bar = decorate(
self.svg,
self.svg.node(bars, class_='bar'),
metadata)
self.svg.transposable_node(
bar, '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=bar_inner_width,
height=height,
class_='rect reactive tooltip-trigger')
x += bar_inner_width / 2
y += height / 2
val = self._get_value(serie.points, i)
if self.horizontal:
x, y = y, x
self._tooltip_data(bar, val, x, y, classes="centered")
self._static_value(serie_node, val, x, y)
return stack_vals
x_center, y_center = self._bar(bar, x, y, index)
self._tooltip_data(
bar, val, x_center, y_center, classes="centered")
self._static_value(serie_node, val, x_center, y_center)
def _compute(self):
self._box.ymin = min(self._min, self.zero)
@ -120,18 +84,18 @@ class Bar(Graph):
x_pos = [
x / self._len for x in range(self._len + 1)
] if self._len > 1 else [0, 1] # Center if only one value
self._points(x_pos)
y_pos = compute_scale(
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_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])
self._y_labels = zip(map(self._format, y_pos), y_pos)
def _plot(self):
for index, serie in enumerate(self.series):
serie_node = self._serie(index)
self.bar(serie_node, serie, [
tuple((self._x_ranges[i][j], v) for j in range(2))
for i, v in enumerate(serie.values)], index)
self.bar(self._serie(index), serie, index)

12
pygal/graph/graph.py

@ -322,3 +322,15 @@ class Graph(BaseGraph):
x=x,
y=y + self.value_font_size / 3
).text = value if self.print_zeroes or value != '0' else ''
def _get_value(self, values, i):
"""Get the value formatted for tooltip"""
return self._format(values[i][1])
def _points(self, x_pos):
for serie in self.series:
serie.points = [
(x_pos[i], v)
for i, v in enumerate(serie.values)]
if self.interpolate:
serie.interpolated = self._interpolate(serie.values, x_pos)

12
pygal/graph/line.py

@ -32,10 +32,6 @@ class Line(Graph):
self._self_close = False
super(Line, self).__init__(*args, **kwargs)
def _get_value(self, values, i):
"""Get the value formatted for tooltip"""
return self._format(values[i][1])
@cached_property
def _values(self):
return [
@ -90,14 +86,6 @@ class Line(Graph):
serie_node['plot'], view_values, close=self._self_close,
class_='line reactive' + (' nofill' if not self.fill else ''))
def _points(self, x_pos):
for serie in self.series:
serie.points = [
(x_pos[i], v)
for i, v in enumerate(serie.values)]
if self.interpolate:
serie.interpolated = self._interpolate(serie.values, x_pos)
def _compute(self):
x_pos = [
x / (self._len - 1) for x in range(self._len)

18
pygal/graph/stackedbar.py

@ -57,12 +57,12 @@ class StackedBar(Bar):
sum(x_range) / 2 for x_range in self._x_ranges])
self._y_labels = zip(map(self._format, y_pos), y_pos)
def _plot(self):
stack_vals = [[0, 0] for i in range(self._len)]
for index, serie in enumerate(self.series):
serie_node = self._serie(index)
stack_vals = self.bar(
serie_node, serie, [
tuple((self._x_ranges[i][j], v) for j in range(2))
for i, v in enumerate(serie.values)], index,
stack_vals)
def _points(self, x_pos):
accumulation = [0] * self._len
for serie in self.series:
accumulation = map(sum, zip(accumulation, serie.values))
serie.points = [
(x_pos[i], v)
for i, v in enumerate(accumulation)]
if self.interpolate:
serie.interpolated = self._interpolate(accumulation, x_pos)

1
pygal/graph/stackedline.py

@ -49,6 +49,5 @@ class StackedLine(Line):
serie.points = [
(x_pos[i], v)
for i, v in enumerate(accumulation)]
print serie.points
if self.interpolate:
serie.interpolated = self._interpolate(accumulation, x_pos)

Loading…
Cancel
Save