diff --git a/demo/moulinrouge/tests.py b/demo/moulinrouge/tests.py index c641c01..fef07e2 100644 --- a/demo/moulinrouge/tests.py +++ b/demo/moulinrouge/tests.py @@ -351,6 +351,15 @@ def get_test_routes(app): bar.x_labels_major = [4] return bar.render_response() + @app.route('/test/bar/position') + def test_bar_print_values_position(): + bar = Bar(print_values=True, print_values_position='top') + bar.add('1', [1, 2, 3]) + bar.add('2', [4, 5, 6]) + bar.x_labels = [2, 4, 6] + bar.x_labels_major = [4] + return bar.render_response() + @app.route('/test/histogram') def test_histogram(): hist = Histogram(style=styles['neon']) diff --git a/docs/changelog.rst b/docs/changelog.rst index d2450c4..14ee8ed 100644 --- a/docs/changelog.rst +++ b/docs/changelog.rst @@ -2,6 +2,11 @@ Changelog ========= +2.0.13 UNRELEASED +====== + +* Bar label positioning + 2.0.12 ====== diff --git a/pygal/config.py b/pygal/config.py index 123fa43..716e0ee 100644 --- a/pygal/config.py +++ b/pygal/config.py @@ -456,6 +456,15 @@ class Config(CommonConfig): False, bool, "Text", "Display values as text over plot") + dynamic_print_values = Key( + False, bool, + "Text", "Show values only on hover") + + print_values_position = Key( + 'center', str, + "Text", "Customize position of `print_values`. " + "(For bars: `top`, `center` or `bottom`)") + print_zeroes = Key( True, bool, "Text", "Display zero values as well") @@ -464,10 +473,6 @@ class Config(CommonConfig): False, bool, "Text", "Display value labels") - dynamic_print_values = Key( - False, bool, - "Text", "Show values only on hover") - truncate_legend = Key( None, int, "Text", "Legend string length truncation threshold", diff --git a/pygal/graph/bar.py b/pygal/graph/bar.py index 772185c..77c2d5a 100644 --- a/pygal/graph/bar.py +++ b/pygal/graph/bar.py @@ -35,11 +35,6 @@ class Bar(Graph): _series_margin = .06 _serie_margin = .06 - def __init__(self, *args, **kwargs): - """Bar chart creation""" - self._x_ranges = None - super(Bar, self).__init__(*args, **kwargs) - def _bar(self, serie, parent, x, y, i, zero, secondary=False): """Internal bar drawing function""" width = (self.view.x(1) - self.view.x(0)) / self._len @@ -63,8 +58,18 @@ class Bar(Graph): parent, 'rect', x=x, y=y, rx=r, ry=r, width=width, height=height, class_='rect reactive tooltip-trigger'), serie.metadata.get(i)) + return x, y, width, height + + def _tooltip_and_print_values( + self, serie_node, serie, parent, i, val, metadata, + x, y, width, height): transpose = swap if self.horizontal else ident - return transpose((x + width / 2, y + height / 2)) + x_center, y_center = transpose((x + width / 2, y + height / 2)) + self._tooltip_data( + parent, val, x_center, y_center, "centered", + self._get_x_label(i)) + self._static_value( + serie_node, val, x_center, y_center, metadata) def bar(self, serie, rescale=False): """Draw a bar graph for a serie""" @@ -79,19 +84,18 @@ class Bar(Graph): if None in (x, y) or (self.logarithmic and y <= 0): continue metadata = serie.metadata.get(i) + val = self._format(serie.values[i]) bar = decorate( self.svg, self.svg.node(bars, class_='bar'), metadata) - val = self._format(serie.values[i]) - x_center, y_center = self._bar( + bounds = self._bar( serie, bar, x, y, i, self.zero, secondary=rescale) - self._tooltip_data( - bar, val, x_center, y_center, "centered", - self._get_x_label(i)) - self._static_value(serie_node, val, x_center, y_center, metadata) + + self._tooltip_and_print_values( + serie_node, serie, bar, i, val, metadata, *bounds) def _compute(self): """Compute y min and max and y scale and set labels""" diff --git a/pygal/graph/histogram.py b/pygal/graph/histogram.py index a8d5502..45defb3 100644 --- a/pygal/graph/histogram.py +++ b/pygal/graph/histogram.py @@ -24,10 +24,11 @@ as bars of varying width. from __future__ import division from pygal.graph.dual import Dual -from pygal.util import alter, cached_property, decorate, ident, swap +from pygal.graph.bar import Bar +from pygal.util import alter, cached_property, decorate -class Histogram(Dual): +class Histogram(Dual, Bar): """Histogram chart class""" _series_margin = 0 @@ -72,8 +73,7 @@ class Histogram(Dual): parent, 'rect', x=x, y=y, rx=r, ry=r, width=width, height=height, class_='rect reactive tooltip-trigger'), serie.metadata.get(i)) - transpose = swap if self.horizontal else ident - return transpose((x + width / 2, y + height / 2)) + return x, y, width, height def bar(self, serie, rescale=False): """Draw a bar graph for a serie""" @@ -92,12 +92,10 @@ class Histogram(Dual): metadata) val = self._format(serie.values[i][0]) - x_center, y_center = self._bar( + bounds = self._bar( serie, bar, x0, x1, y, i, self.zero, secondary=rescale) - self._tooltip_data( - bar, val, x_center, y_center, "centered", - self._get_x_label(i)) - self._static_value(serie_node, val, x_center, y_center, metadata) + self._tooltip_and_print_values( + serie_node, serie, bar, i, val, metadata, *bounds) def _compute(self): """Compute x/y min and max and x/y scale and set labels""" @@ -122,10 +120,3 @@ class Histogram(Dual): self._box.xmin, self._box.xmax = xmin, xmax if yrng: self._box.ymin, self._box.ymax = ymin, ymax - - def _plot(self): - """Draw bars for series and secondary series""" - for serie in self.series: - self.bar(serie) - for serie in self.secondary_series: - self.bar(serie, True) diff --git a/pygal/graph/stackedbar.py b/pygal/graph/stackedbar.py index 12d0bca..0e29ba7 100644 --- a/pygal/graph/stackedbar.py +++ b/pygal/graph/stackedbar.py @@ -131,8 +131,7 @@ class StackedBar(Bar): parent, 'rect', x=x, y=y, rx=r, ry=r, width=width, height=height, class_='rect reactive tooltip-trigger') - transpose = swap if self.horizontal else ident - return transpose((x + width / 2, y + height / 2)) + return x, y, width, height def _plot(self): """Draw bars for series and secondary series"""