From c175c08d8b53da551d4d49d647f28426950ff04c Mon Sep 17 00:00:00 2001 From: Florian Mounier Date: Mon, 27 Jul 2015 18:07:24 +0200 Subject: [PATCH] Add ``print_labels`` option to print label too. (Fix #197) Add ``value_label_font_family`` and ``value_label_font_size`` style options for ``print_labels``. Default ``print_zeroes`` to True (Re)Add xlink in desc to show on tooltip Activate element on tooltip hovering. (Fix #106) --- demo/moulinrouge/tests.py | 53 ++++++++++++++--------- docs/changelog.rst | 5 +++ docs/documentation/configuration/data.rst | 41 ++++++++++++++++-- docs/documentation/custom_styles.rst | 8 ++-- pygal/config.py | 8 +++- pygal/css/base.css | 7 ++- pygal/css/style.css | 5 +++ pygal/graph/bar.py | 2 +- pygal/graph/box.py | 2 +- pygal/graph/dot.py | 2 +- pygal/graph/funnel.py | 2 +- pygal/graph/gauge.py | 2 +- pygal/graph/graph.py | 16 ++++++- pygal/graph/histogram.py | 2 +- pygal/graph/line.py | 3 +- pygal/graph/pie.py | 4 +- pygal/graph/treemap.py | 3 +- pygal/style.py | 4 +- pygal/svg.py | 4 +- pygal/util.py | 2 + 20 files changed, 129 insertions(+), 46 deletions(-) diff --git a/demo/moulinrouge/tests.py b/demo/moulinrouge/tests.py index 0601400..0c1532d 100644 --- a/demo/moulinrouge/tests.py +++ b/demo/moulinrouge/tests.py @@ -50,7 +50,7 @@ def get_test_routes(app): def test_bar_links(): bar = StackedLine(style=styles['default']( font_family='googlefont:Raleway')) - # bar.js = ('http://l:2343/2.0.x/pygal-tooltips.js',) + bar.js = ('http://l:2343/2.0.x/pygal-tooltips.js',) bar.title = 'Wow ! Such Chart !' bar.x_title = 'Many x labels' bar.y_title = 'Much y labels' @@ -145,31 +145,42 @@ def get_test_routes(app): bar.x_labels = range(1, 4) return bar.render_response() - @app.route('/test/print_values') - def test_bar_print_values(): - bar = Bar(print_values=True, js=[], - style=styles['default']( - value_font_family='googlefont:Raleway', - value_font_size=30, - value_colors=(None, None, 'blue', 'red', 'green') - )) + @app.route('/test/print_values/') + def test_print_values_for(chart): + graph = CHARTS_BY_NAME[chart]( + print_values=True, print_labels=True, print_zeroes=True, + style=styles['default']( + value_font_family='googlefont:Raleway', + value_colors=(None, None, 'blue', 'red', 'green') + )) + graph.js = ('http://l:2343/2.0.x/pygal-tooltips.js',) for i in range(12): - bar.add('', i) - return bar.render_response() + graph.add('', [{ + 'value': i + j, + 'label': 'abcdefghijklmnopqrstuvwxyz'[i + j] + } for j in range(5)]) + return graph.render_response() @app.route('/test/treemap') def test_treemap(): - treemap = Treemap(style=RotateStyle('#ff5995', opacity=.6)) + treemap = Treemap(style=RotateStyle('#ff5995', opacity=.6, + value_font_size=32, + value_colors=['#ffffff'])) treemap.title = 'Binary TreeMap' - treemap.add('A', [2, 1, 12, 4, 2, 1, 1, 3, 12, 3, 4, None, 9]) - treemap.add('B', [4, 2, 5, 10, 3, 4, 2, 7, 4, -10, None, 8, 3, 1]) - treemap.add('C', [3, 8, 3, 3, 5, 3, 3, 5, 4, 12]) - treemap.add('D', [23, 18]) - treemap.add('E', [1, 2, 1, 2, 3, 3, 1, 2, 3, - 4, 3, 1, 2, 1, 1, 1, 1, 1]) - treemap.add('F', [31]) - treemap.add('G', [5, 9.3, 8.1, 12, 4, 3, 2]) - treemap.add('H', [12, 3, 3]) + treemap.print_values = True + treemap.print_labels = True + for i in range(1, 5): + treemap.add('', [{'label': 'Area %d' % i, 'value': i}]) + treemap.add('', [2]) + # treemap.add('A', [2, 1, 12, 4, 2, 1, 1, 3, 12, 3, 4, None, 9]) + # treemap.add('B', [4, 2, 5, 10, 3, 4, 2, 7, 4, -10, None, 8, 3, 1]) + # treemap.add('C', [3, 8, 3, 3, 5, 3, 3, 5, 4, 12]) + # treemap.add('D', [23, 18]) + # treemap.add('E', [1, 2, 1, 2, 3, 3, 1, 2, 3, + # 4, 3, 1, 2, 1, 1, 1, 1, 1]) + # treemap.add('F', [31]) + # treemap.add('G', [5, 9.3, 8.1, 12, 4, 3, 2]) + # treemap.add('H', [12, 3, 3]) return treemap.render_response() @app.route('/test/gauge') diff --git a/docs/changelog.rst b/docs/changelog.rst index 7884c04..4f1e776 100644 --- a/docs/changelog.rst +++ b/docs/changelog.rst @@ -7,6 +7,11 @@ Changelog * Fix the missing title on x_labels with labels. * Auto cast to str x labels in non dual charts (#178) +* Add ``print_labels`` option to print label too. (#197) +* Add ``value_label_font_family`` and ``value_label_font_size`` style options for ``print_labels``. +* Default ``print_zeroes`` to True +* (Re)Add xlink in desc to show on tooltip +* Activate element on tooltip hovering. (#106) 2.0.0 ===== diff --git a/docs/documentation/configuration/data.rst b/docs/documentation/configuration/data.rst index 8367908..6d9fad0 100644 --- a/docs/documentation/configuration/data.rst +++ b/docs/documentation/configuration/data.rst @@ -28,12 +28,12 @@ Same on x axis for xy like charts: print_values ------------ -When using pygal without javascript for printing for example you can chose to activate this option to print all values as text. +When using pygal to display static charts for printing for example you can chose to activate this option to print all values as text. .. pygal-code:: from pygal.style import DefaultStyle - chart = pygal.Bar(js=[], print_values=True, style=DefaultStyle( + chart = pygal.Bar(print_values=True, style=DefaultStyle( value_font_family='googlefont:Raleway', value_font_size=30, value_colors=('white',))) @@ -43,14 +43,47 @@ When using pygal without javascript for printing for example you can chose to ac print_zeroes ------------ -zero values are hidden by default but you can use this option to print them anyway. +zero values are shown by default but you can use this option to hide them. .. pygal-code:: - chart = pygal.Bar(js=[], print_values=True, print_zeroes=True) + chart = pygal.Bar(print_values=True, print_zeroes=False) chart.add('line', [0, 12, 31, 8, 28, 0]) +print_labels +------------ + +You can activate value label display: + +.. pygal-code:: + + chart = pygal.Bar(print_labels=True) + chart.add('line', [ + 0, + {'value': 12, 'label': 'Twelve'}, + 31, + {'value': 8, 'label': 'eight'}, + 28, + 0 + ]) + + +Displaying both is also possible: + +.. pygal-code:: + + chart = pygal.Bar(print_labels=True, print_values=True) + chart.add('line', [ + 0, + {'value': 12, 'label': 'Twelve'}, + 31, + {'value': 8, 'label': 'eight'}, + 28, + 0 + ]) + + human_readable -------------- diff --git a/docs/documentation/custom_styles.rst b/docs/documentation/custom_styles.rst index 876e8a6..4728e1f 100644 --- a/docs/documentation/custom_styles.rst +++ b/docs/documentation/custom_styles.rst @@ -47,7 +47,8 @@ Properties Description ``font_family`` The main font family ``label_font_family`` The label font family ``major_label_font_family`` The major label font family -``value_font_family`` The ``print_value`` font family +``value_font_family`` The ``print_values`` font family +``value_label_font_family`` The ``print_labels`` font family ``tooltip_font_family`` The tooltip font family ``title_font_family`` The title font family ``legend_font_family`` The legend font family @@ -56,7 +57,8 @@ Properties Description ``major_guide_stroke_dasharray`` The dasharray for major guide line ``label_font_size`` The label font size ``major_label_font_size`` The major label font size -``value_font_size`` The ``print_value`` font size +``value_font_size`` The ``print_values`` font size +``value_label_font_size`` The ``print_labels`` font size ``tooltip_font_size`` The tooltip font size ``title_font_size`` The title font size ``legend_font_size`` The legend font size @@ -65,7 +67,7 @@ Properties Description ``opacity_hover`` The opacity of chart element on mouse hover ``transition`` Define the global transition property for animation ``colors`` The serie color list -``value_colors`` The ``print_value`` color list +``value_colors`` The ``print_values`` color list ================================ ========================= diff --git a/pygal/config.py b/pygal/config.py index 324e0a1..b56c174 100644 --- a/pygal/config.py +++ b/pygal/config.py @@ -448,11 +448,15 @@ class Config(CommonConfig): print_values = Key( False, bool, - "Text", "Print values when graph is in non interactive mode") + "Text", "Display values as text over plot") print_zeroes = Key( + True, bool, + "Text", "Display zero values as well") + + print_labels = Key( False, bool, - "Text", "Print zeroes when graph is in non interactive mode") + "Text", "Display value labels") truncate_legend = Key( None, int, "Text", diff --git a/pygal/css/base.css b/pygal/css/base.css index 2623d37..01f5d5b 100644 --- a/pygal/css/base.css +++ b/pygal/css/base.css @@ -48,11 +48,16 @@ font-size: {{ style.major_label_font_size }}px; } -{{ id }}.series text { +{{ id }}.text-overlay text.value { font-family: {{ style.value_font_family }}; font-size: {{ style.value_font_size }}px; } +{{ id }}.text-overlay text.label { + font-family: {{ style.value_label_font_family }}; + font-size: {{ style.value_label_font_size }}px; +} + {{ id }}.tooltip { font-family: {{ style.tooltip_font_family }}; font-size: {{ style.tooltip_font_size }}px; diff --git a/pygal/css/style.css b/pygal/css/style.css index a6749c1..4471b44 100644 --- a/pygal/css/style.css +++ b/pygal/css/style.css @@ -130,6 +130,11 @@ fill: {{ style.foreground_strong }}; } +{{ id }}.tooltip .xlink { + font-size: .5em; + text-decoration: underline; +} + {{ id }}.tooltip .value { font-size: 1.5em; } diff --git a/pygal/graph/bar.py b/pygal/graph/bar.py index 0126d0e..25475af 100644 --- a/pygal/graph/bar.py +++ b/pygal/graph/bar.py @@ -91,7 +91,7 @@ class Bar(Graph): 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) + self._static_value(serie_node, val, x_center, y_center, metadata) def _compute(self): """Compute y min and max and y scale and set labels""" diff --git a/pygal/graph/box.py b/pygal/graph/box.py index aa0e3e9..182697b 100644 --- a/pygal/graph/box.py +++ b/pygal/graph/box.py @@ -113,7 +113,7 @@ class Box(Graph): box, serie.values[1:6], serie.outliers, serie.index, metadata) self._tooltip_data(box, val, x_center, y_center, "centered", self._get_x_label(serie.index)) - self._static_value(serie_node, val, x_center, y_center) + self._static_value(serie_node, val, x_center, y_center, metadata) def _draw_box(self, parent_node, quartiles, outliers, box_index, metadata): """ diff --git a/pygal/graph/dot.py b/pygal/graph/dot.py index 733fceb..fe1ce38 100644 --- a/pygal/graph/dot.py +++ b/pygal/graph/dot.py @@ -71,7 +71,7 @@ class Dot(Graph): self._tooltip_data( dots, value, x, y, 'centered', self._get_x_label(i)) - self._static_value(serie_node, value, x, y) + self._static_value(serie_node, value, x, y, metadata) def _compute(self): """Compute y min and max and y scale and set labels""" diff --git a/pygal/graph/funnel.py b/pygal/graph/funnel.py index f76c1fa..8d68bf7 100644 --- a/pygal/graph/funnel.py +++ b/pygal/graph/funnel.py @@ -62,7 +62,7 @@ class Funnel(Graph): self._tooltip_data( funnels, value, x, y, 'centered', self._get_x_label(serie.index)) - self._static_value(serie_node, value, x, y) + self._static_value(serie_node, value, x, y, metadata) def _center(self, x): return x - 1 / (2 * self._order) diff --git a/pygal/graph/gauge.py b/pygal/graph/gauge.py index 325cc17..40b08c2 100644 --- a/pygal/graph/gauge.py +++ b/pygal/graph/gauge.py @@ -90,7 +90,7 @@ class Gauge(Graph): self._tooltip_data( gauges, value, x, y, xlabel=self._get_x_label(i)) - self._static_value(serie_node, value, x, y) + self._static_value(serie_node, value, x, y, metadata) def _y_axis(self, draw_axes=True): """Override y axis to plot a polar axis""" diff --git a/pygal/graph/graph.py b/pygal/graph/graph.py index e786bb1..beb9dae 100644 --- a/pygal/graph/graph.py +++ b/pygal/graph/graph.py @@ -457,12 +457,24 @@ class Graph(PublicApi): self.svg.node(node, 'desc', class_="x_label").text = to_str(xlabel) - def _static_value(self, serie_node, value, x, y): + def _static_value(self, serie_node, value, x, y, metadata): """Write the print value""" + label = metadata and metadata.get('label') + if self.print_labels and label: + if self.print_values: + y -= self.style.value_font_size / 2 + self.svg.node( + serie_node['text_overlay'], 'text', + class_='centered label', + x=x, + y=y + self.style.value_font_size / 3 + ).text = label + y += self.style.value_font_size + if self.print_values: self.svg.node( serie_node['text_overlay'], 'text', - class_='centered', + class_='centered value', x=x, y=y + self.style.value_font_size / 3 ).text = value if self.print_zeroes or value != '0' else '' diff --git a/pygal/graph/histogram.py b/pygal/graph/histogram.py index 5e10514..a8d5502 100644 --- a/pygal/graph/histogram.py +++ b/pygal/graph/histogram.py @@ -97,7 +97,7 @@ class Histogram(Dual): 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) + self._static_value(serie_node, val, x_center, y_center, metadata) def _compute(self): """Compute x/y min and max and x/y scale and set labels""" diff --git a/pygal/graph/line.py b/pygal/graph/line.py index 38d448f..e26c35d 100644 --- a/pygal/graph/line.py +++ b/pygal/graph/line.py @@ -125,7 +125,8 @@ class Line(Graph): self._static_value( serie_node, val, x + self.style.value_font_size, - y + self.style.value_font_size) + y + self.style.value_font_size, + metadata) if serie.stroke: if self.interpolate: diff --git a/pygal/graph/pie.py b/pygal/graph/pie.py index 980c46f..1efa053 100644 --- a/pygal/graph/pie.py +++ b/pygal/graph/pie.py @@ -84,7 +84,7 @@ class Pie(Graph): alter(self.svg.slice( serie_node, slice_, big_radius, small_radius, - angle, start_angle, center, val, i), metadata) + angle, start_angle, center, val, i, metadata), metadata) start_angle += angle total_perc += perc @@ -93,7 +93,7 @@ class Pie(Graph): self.svg.slice(serie_node, self.svg.node(slices, class_="big_slice"), radius * .9, 0, serie_angle, - original_start_angle, center, val, i) + original_start_angle, center, val, i, metadata) return serie_angle def _compute_x_labels(self): diff --git a/pygal/graph/treemap.py b/pygal/graph/treemap.py index 60f746a..d6d925e 100644 --- a/pygal/graph/treemap.py +++ b/pygal/graph/treemap.py @@ -65,7 +65,8 @@ class Treemap(Graph): self._static_value( serie_node, value, rx + rw / 2, - ry + rh / 2) + ry + rh / 2, + metadata) def _binary_tree(self, data, total, x, y, w, h, parent=None): if total == 0: diff --git a/pygal/style.py b/pygal/style.py index aeabe28..883c579 100644 --- a/pygal/style.py +++ b/pygal/style.py @@ -43,6 +43,7 @@ class Style(object): label_font_family = None major_label_font_family = None value_font_family = None + value_label_font_family = None tooltip_font_family = None title_font_family = None legend_font_family = None @@ -50,7 +51,8 @@ class Style(object): label_font_size = 10 major_label_font_size = 10 - value_font_size = 8 + value_font_size = 16 + value_label_font_size = 10 tooltip_font_size = 14 title_font_size = 16 legend_font_size = 14 diff --git a/pygal/svg.py b/pygal/svg.py index 137c93e..ef80915 100644 --- a/pygal/svg.py +++ b/pygal/svg.py @@ -239,7 +239,7 @@ class Svg(object): def slice( self, serie_node, node, radius, small_radius, - angle, start_angle, center, val, i): + angle, start_angle, center, val, i, metadata): """Draw a pie slice""" project = lambda rho, alpha: ( rho * sin(-alpha), rho * cos(-alpha)) @@ -278,7 +278,7 @@ class Svg(object): node, val, x, y, "centered", self.graph._x_labels and self.graph._x_labels[i][0]) if angle >= 0.3: # 0.3 radians is about 17 degrees - self.graph._static_value(serie_node, val, x, y) + self.graph._static_value(serie_node, val, x, y, metadata) return rv def pre_render(self): diff --git a/pygal/util.py b/pygal/util.py index 4b92012..6f68dd5 100644 --- a/pygal/util.py +++ b/pygal/util.py @@ -232,6 +232,8 @@ def decorate(svg, node, metadata): if not isinstance(xlink, dict): xlink = {'href': xlink, 'target': '_blank'} node = svg.node(node, 'a', **xlink) + svg.node(node, 'desc', class_='xlink').text = to_unicode( + xlink.get('href')) if 'color' in metadata: color = metadata.pop('color')