Browse Source

Fix a lot of label related things

pull/264/head
Florian Mounier 10 years ago
parent
commit
494d46613a
  1. 2
      demo/moulinrouge/__init__.py
  2. 8
      demo/moulinrouge/tests.py
  3. 7
      docs/api/pygal.adapters.rst
  4. 3
      pygal/adapters.py
  5. 9
      pygal/graph/bar.py
  6. 2
      pygal/graph/base.py
  7. 22
      pygal/graph/box.py
  8. 8
      pygal/graph/dot.py
  9. 4
      pygal/graph/dual.py
  10. 6
      pygal/graph/funnel.py
  11. 7
      pygal/graph/gauge.py
  12. 15
      pygal/graph/graph.py
  13. 9
      pygal/graph/histogram.py
  14. 6
      pygal/graph/horizontal.py
  15. 7
      pygal/graph/line.py
  16. 2
      pygal/graph/map.py
  17. 4
      pygal/graph/pie.py
  18. 12
      pygal/graph/radar.py
  19. 6
      pygal/graph/stackedbar.py
  20. 4
      pygal/graph/time.py
  21. 23
      pygal/graph/treemap.py
  22. 8
      pygal/svg.py

2
demo/moulinrouge/__init__.py

@ -213,7 +213,7 @@ def create_app():
else: else:
config.x_labels = [random_label() for i in range(data)] config.x_labels = [random_label() for i in range(data)]
svgs.append({'type': type, svgs.append({'type': type,
'series': xy_series if type == 'XY' else other_series, 'series': xy_series if chart._dual else other_series,
'config': b64encode(pickle.dumps(config))}) 'config': b64encode(pickle.dumps(config))})
return render_template('svgs.jinja2', return render_template('svgs.jinja2',

8
demo/moulinrouge/tests.py

@ -376,8 +376,8 @@ def get_test_routes(app):
chart.x_label_rotation = 25 chart.x_label_rotation = 25
chart.y_label_rotation = 50 chart.y_label_rotation = 50
chart.add('1', [30, 20, -2]) chart.add('1', [30, 20, -2])
chart.add(10 * '1b', [-4, 50, 6], secondary=True) chart.add('1b', [-4, 50, 6], secondary=True)
chart.add(10 * '2b', [None, 10, 20], secondary=True) chart.add('2b', [None, 10, 20], secondary=True)
chart.add('2', [8, 21, -0]) chart.add('2', [8, 21, -0])
chart.add('3', [None, 20, 10]) chart.add('3', [None, 20, 10])
chart.add('3b', [-1, 2, -3], secondary=True) chart.add('3b', [-1, 2, -3], secondary=True)
@ -395,6 +395,8 @@ def get_test_routes(app):
@app.route('/test/box') @app.route('/test/box')
def test_box(): def test_box():
chart = Box() chart = Box()
chart.js = ('http://l:2343/2.0.x/pygal-tooltips.js',)
chart.box_mode = '1.5IQR'
chart.add('One', [15, 8, 2, -12, 9, 23]) chart.add('One', [15, 8, 2, -12, 9, 23])
chart.add('Two', [5, 8, 2, -9, 23, 12]) chart.add('Two', [5, 8, 2, -9, 23, 12])
chart.add('Three', [8, -2, 12, -5, 9, 3]) chart.add('Three', [8, -2, 12, -5, 9, 3])
@ -408,6 +410,7 @@ def get_test_routes(app):
stacked = StackedLine(stack_from_top=True, logarithmic=True) stacked = StackedLine(stack_from_top=True, logarithmic=True)
stacked.add('1', [1, 2]) stacked.add('1', [1, 2])
stacked.add('2', [10, 12]) stacked.add('2', [10, 12])
stacked.x_labels = ['a', 'b', 'c', 'd']
return stacked.render_response() return stacked.render_response()
@app.route('/test/stacked/reverse') @app.route('/test/stacked/reverse')
@ -415,7 +418,6 @@ def get_test_routes(app):
stacked = StackedBar(stack_from_top=True) stacked = StackedBar(stack_from_top=True)
stacked.add('1', [1, 2, 3]) stacked.add('1', [1, 2, 3])
stacked.add('2', [4, 5, 6]) stacked.add('2', [4, 5, 6])
stacked.x_labels = ['a', 'b', 'c']
return stacked.render_response() return stacked.render_response()
@app.route('/test/show_dots') @app.route('/test/show_dots')

7
docs/api/pygal.adapters.rst

@ -1,7 +0,0 @@
pygal.adapters module
=====================
.. automodule:: pygal.adapters
:members:
:undoc-members:
:show-inheritance:

3
pygal/adapters.py

@ -18,12 +18,15 @@
# along with pygal. If not, see <http://www.gnu.org/licenses/>. # along with pygal. If not, see <http://www.gnu.org/licenses/>.
"""Value adapters to use when a chart doesn't accept all value types""" """Value adapters to use when a chart doesn't accept all value types"""
from decimal import Decimal from decimal import Decimal
from pygal._compat import is_str
def positive(x): def positive(x):
"""Return zero if value is negative""" """Return zero if value is negative"""
if x is None: if x is None:
return return
if is_str(x):
return x
if x < 0: if x < 0:
return 0 return 0
return x return x

9
pygal/graph/bar.py

@ -88,7 +88,8 @@ class Bar(Graph):
x_center, y_center = self._bar( x_center, y_center = self._bar(
serie, bar, x, y, i, self.zero, secondary=rescale) serie, bar, x, y, i, self.zero, secondary=rescale)
self._tooltip_data( self._tooltip_data(
bar, val, x_center, y_center, classes="centered") 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)
def _compute(self): def _compute(self):
@ -98,11 +99,13 @@ class Bar(Graph):
if self._max: if self._max:
self._box.ymax = max(self._max, self.zero) self._box.ymax = max(self._max, self.zero)
x_pos = [ self._x_pos = [
x / self._len for x in range(self._len + 1) x / self._len for x in range(self._len + 1)
] if self._len > 1 else [0, 1] # Center if only one value ] if self._len > 1 else [0, 1] # Center if only one value
self._points(x_pos) self._points(self._x_pos)
self._x_pos = [(i + .5) / self._len for i in range(self._len)]
def _compute_secondary(self): def _compute_secondary(self):
"""Compute parameters for secondary series rendering""" """Compute parameters for secondary series rendering"""

2
pygal/graph/base.py

@ -149,6 +149,8 @@ class BaseGraph(object):
value = (None, None, None) value = (None, None, None)
elif not is_list_like(value): elif not is_list_like(value):
value = (value, self.zero, self.zero) value = (value, self.zero, self.zero)
elif len(value) == 2:
value = (1, value[0], value[1])
value = list(map(adapter, value)) value = list(map(adapter, value))
elif self._dual: elif self._dual:
if value is None: if value is None:

22
pygal/graph/box.py

@ -50,14 +50,16 @@ class Box(Graph):
def format_maybe_quartile(x): def format_maybe_quartile(x):
if is_list_like(x): if is_list_like(x):
if self.box_mode == "extremes": if self.box_mode == "extremes":
return 'Min: %s Q1: %s Q2: %s Q3: %s Max: %s' \ return (
% tuple(map(sup, x[1:6])) 'Min: %s\nQ1 : %s\nQ2 : %s\nQ3 : %s\nMax: %s' %
tuple(map(sup, x[1:6])))
elif self.box_mode in ["tukey", "stdev", "pstdev"]: elif self.box_mode in ["tukey", "stdev", "pstdev"]:
return 'Min: %s Lower Whisker: %s Q1: %s Q2: %s Q3: %s '\ return (
'Upper Whisker: %s Max: %s' % tuple(map(sup, x)) 'Min: %s\nLower Whisker: %s\nQ1: %s\nQ2: %s\nQ3: %s\n'
'Upper Whisker: %s\nMax: %s' % tuple(map(sup, x)))
elif self.box_mode == '1.5IQR': elif self.box_mode == '1.5IQR':
# 1.5IQR mode # 1.5IQR mode
return 'Q1: %s Q2: %s Q3: %s' % tuple(map(sup, x[2:5])) return 'Q1: %s\nQ2: %s\nQ3: %s' % tuple(map(sup, x[2:5]))
else: else:
return sup(x) return sup(x)
return format_maybe_quartile return format_maybe_quartile
@ -71,15 +73,14 @@ class Box(Graph):
serie.values, serie.outliers = \ serie.values, serie.outliers = \
self._box_points(serie.values, self.box_mode) self._box_points(serie.values, self.box_mode)
self._x_pos = [
(i + .5) / self._order for i in range(self._order)]
if self._min: if self._min:
self._box.ymin = min(self._min, self.zero) self._box.ymin = min(self._min, self.zero)
if self._max: if self._max:
self._box.ymax = max(self._max, self.zero) self._box.ymax = max(self._max, self.zero)
def _compute_x_labels(self):
self._x_labels = self.x_labels and list(zip(self.x_labels, [
(i + .5) / self._order for i in range(self._order)]))
def _plot(self): def _plot(self):
"""Plot the series data""" """Plot the series data"""
for serie in self.series: for serie in self.series:
@ -108,7 +109,8 @@ class Box(Graph):
x_center, y_center = self._draw_box( x_center, y_center = self._draw_box(
box, serie.values[1:6], serie.outliers, serie.index, metadata) box, serie.values[1:6], serie.outliers, serie.index, metadata)
self._tooltip_data(box, val, x_center, y_center, classes="centered") 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)
def _draw_box(self, parent_node, quartiles, outliers, box_index, metadata): def _draw_box(self, parent_node, quartiles, outliers, box_index, metadata):

8
pygal/graph/dot.py

@ -68,7 +68,9 @@ class Dot(Graph):
' negative' if value < 0 else '')), metadata) ' negative' if value < 0 else '')), metadata)
value = self._format(value) value = self._format(value)
self._tooltip_data(dots, value, x, y, classes='centered') 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)
def _compute(self): def _compute(self):
@ -86,10 +88,6 @@ class Dot(Graph):
(self._x_pos[i], self._y_pos[j]) (self._x_pos[i], self._y_pos[j])
for i in range(x_len)] for i in range(x_len)]
def _compute_x_labels(self):
self._x_labels = self.x_labels and list(
zip(self.x_labels, self._x_pos))
def _compute_y_labels(self): def _compute_y_labels(self):
self._y_labels = list(zip( self._y_labels = list(zip(
self.y_labels or [ self.y_labels or [

4
pygal/graph/dual.py

@ -51,3 +51,7 @@ class Dual(Graph):
else: else:
self._x_labels = list(zip(map(self._x_format, x_pos), x_pos)) self._x_labels = list(zip(map(self._x_format, x_pos), x_pos))
def _get_x_label(self, i):
"""Convenience function to get the x_label of a value index"""
return

6
pygal/graph/funnel.py

@ -53,11 +53,13 @@ class Funnel(Graph):
points=' '.join(map(fmt, map(self.view, poly))), points=' '.join(map(fmt, map(self.view, poly))),
class_='funnel reactive tooltip-trigger'), metadata) class_='funnel reactive tooltip-trigger'), metadata)
# Poly center from label
x, y = self.view(( x, y = self.view((
# Poly center from label
self._center(self._x_pos[serie.index]), self._center(self._x_pos[serie.index]),
sum([point[1] for point in poly]) / len(poly))) sum([point[1] for point in poly]) / len(poly)))
self._tooltip_data(funnels, value, x, y, classes='centered') 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)
def _center(self, x): def _center(self, x):

7
pygal/graph/gauge.py

@ -86,7 +86,9 @@ class Gauge(Graph):
metadata) metadata)
x, y = self.view((.75, theta)) x, y = self.view((.75, theta))
self._tooltip_data(gauges, value, x, y) 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)
def _y_axis(self, draw_axes=True): def _y_axis(self, draw_axes=True):
@ -138,6 +140,9 @@ class Gauge(Graph):
self.min_, self.min_,
self.max_) self.max_)
def _compute_x_labels(self):
pass
def _compute_y_labels(self): def _compute_y_labels(self):
y_pos = compute_scale( y_pos = compute_scale(
self.min_, self.max_, self.logarithmic, self.min_, self.max_, self.logarithmic,

15
pygal/graph/graph.py

@ -429,7 +429,7 @@ class Graph(PublicApi):
if y is not None else None) if y is not None else None)
for x, y in points] for x, y in points]
def _tooltip_data(self, node, value, x, y, classes=None): def _tooltip_data(self, node, value, x, y, classes=None, xlabel=None):
"""Insert in desc tags informations for the javascript tooltip""" """Insert in desc tags informations for the javascript tooltip"""
self.svg.node(node, 'desc', class_="value").text = value self.svg.node(node, 'desc', class_="value").text = value
if classes is None: if classes is None:
@ -444,6 +444,9 @@ class Graph(PublicApi):
class_="x " + classes).text = str(x) class_="x " + classes).text = str(x)
self.svg.node(node, 'desc', self.svg.node(node, 'desc',
class_="y " + classes).text = str(y) class_="y " + classes).text = str(y)
if xlabel:
self.svg.node(node, 'desc',
class_="x_label").text = str(xlabel)
def _static_value(self, serie_node, value, x, y): def _static_value(self, serie_node, value, x, y):
"""Write the print value""" """Write the print value"""
@ -499,6 +502,12 @@ class Graph(PublicApi):
"""Hook called after compute and before margin computations and plot""" """Hook called after compute and before margin computations and plot"""
pass pass
def _get_x_label(self, i):
"""Convenience function to get the x_label of a value index"""
if not self.x_labels or not self._x_labels or len(self._x_labels) <= i:
return
return self._x_labels[i][0]
@property @property
def all_series(self): def all_series(self):
"""Getter for all series (nomal and secondary)""" """Getter for all series (nomal and secondary)"""
@ -716,8 +725,8 @@ class Graph(PublicApi):
) )
def _compute_x_labels(self): def _compute_x_labels(self):
self._x_labels = self.x_labels and list(zip(self.x_labels, [ self._x_labels = self.x_labels and list(
(i + .5) / self._len for i in range(self._len)])) zip(self.x_labels, self._x_pos))
def _compute_y_labels(self): def _compute_y_labels(self):
y_pos = compute_scale( y_pos = compute_scale(

9
pygal/graph/histogram.py

@ -22,16 +22,14 @@ as bars of varying width.
""" """
from __future__ import division from __future__ import division
from pygal._compat import is_list_like
from pygal.graph.dual import Dual from pygal.graph.dual import Dual
from pygal.util import ( from pygal.util import alter, cached_property, decorate, ident, swap
swap, ident, compute_scale, decorate, cached_property, alter)
class Histogram(Dual): class Histogram(Dual):
"""Histogram chart class""" """Histogram chart class"""
_series_margin = 0 _series_margin = 0
@cached_property @cached_property
@ -97,7 +95,8 @@ class Histogram(Dual):
x_center, y_center = self._bar( x_center, y_center = self._bar(
serie, bar, x0, x1, y, i, self.zero, secondary=rescale) serie, bar, x0, x1, y, i, self.zero, secondary=rescale)
self._tooltip_data( self._tooltip_data(
bar, val, x_center, y_center, classes="centered") 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)
def _compute(self): def _compute(self):

6
pygal/graph/horizontal.py

@ -53,3 +53,9 @@ class HorizontalGraph(Graph):
self.width - self.margin_box.x, self.width - self.margin_box.x,
self.height - self.margin_box.y, self.height - self.margin_box.y,
self._box) self._box)
def _get_x_label(self, i):
"""Convenience function to get the x_label of a value index"""
if not self.x_labels or not self._y_labels or len(self._y_labels) <= i:
return
return self._y_labels[i][0]

7
pygal/graph/line.py

@ -120,7 +120,8 @@ class Line(Graph):
dots, 'circle', cx=x, cy=y, r=serie.dots_size, dots, 'circle', cx=x, cy=y, r=serie.dots_size,
class_='dot reactive tooltip-trigger'), metadata) class_='dot reactive tooltip-trigger'), metadata)
self._tooltip_data( self._tooltip_data(
dots, val, x, y) dots, val, x, y,
xlabel=self._get_x_label(i))
self._static_value( self._static_value(
serie_node, val, serie_node, val,
x + self.style.value_font_size, x + self.style.value_font_size,
@ -141,11 +142,11 @@ class Line(Graph):
def _compute(self): def _compute(self):
"""Compute y min and max and y scale and set labels""" """Compute y min and max and y scale and set labels"""
# X Labels # X Labels
x_pos = [ self._x_pos = [
x / (self._len - 1) for x in range(self._len) x / (self._len - 1) for x in range(self._len)
] if self._len != 1 else [.5] # Center if only one value ] if self._len != 1 else [.5] # Center if only one value
self._points(x_pos) self._points(self._x_pos)
if self.include_x_axis: if self.include_x_axis:
# Y Label # Y Label

2
pygal/graph/map.py

@ -121,7 +121,7 @@ class BaseMap(Graph):
alter(node, metadata) alter(node, metadata)
value = self._get_value((area_code, value)) value = self._get_value((area_code, value))
self._tooltip_data(area, value, 0, 0, classes='auto') self._tooltip_data(area, value, 0, 0, 'auto')
self.nodes['plot'].append(map) self.nodes['plot'].append(map)

4
pygal/graph/pie.py

@ -82,7 +82,7 @@ class Pie(Graph):
alter(self.svg.slice( alter(self.svg.slice(
serie_node, slice_, big_radius, small_radius, serie_node, slice_, big_radius, small_radius,
angle, start_angle, center, val), metadata) angle, start_angle, center, val, i), metadata)
start_angle += angle start_angle += angle
total_perc += perc total_perc += perc
@ -91,7 +91,7 @@ class Pie(Graph):
self.svg.slice(serie_node, self.svg.slice(serie_node,
self.svg.node(slices, class_="big_slice"), self.svg.node(slices, class_="big_slice"),
radius * .9, 0, serie_angle, radius * .9, 0, serie_angle,
original_start_angle, center, val) original_start_angle, center, val, i)
return serie_angle return serie_angle
def _compute_x_labels(self): def _compute_x_labels(self):

12
pygal/graph/radar.py

@ -39,7 +39,6 @@ class Radar(Line):
def __init__(self, *args, **kwargs): def __init__(self, *args, **kwargs):
"""Init custom vars""" """Init custom vars"""
self._x_pos = None
self._rmax = None self._rmax = None
super(Radar, self).__init__(*args, **kwargs) super(Radar, self).__init__(*args, **kwargs)
@ -168,14 +167,14 @@ class Radar(Line):
def _compute(self): def _compute(self):
"""Compute r min max and labels position""" """Compute r min max and labels position"""
delta = 2 * pi / self._len if self._len else 0 delta = 2 * pi / self._len if self._len else 0
x_pos = [.5 * pi + i * delta for i in range(self._len + 1)] self._x_pos = [.5 * pi + i * delta for i in range(self._len + 1)]
for serie in self.all_series: for serie in self.all_series:
serie.points = [ serie.points = [
(v, x_pos[i]) (v, self._x_pos[i])
for i, v in enumerate(serie.values)] for i, v in enumerate(serie.values)]
if self.interpolate: if self.interpolate:
extended_x_pos = ( extended_x_pos = (
[.5 * pi - delta] + x_pos) [.5 * pi - delta] + self._x_pos)
extended_vals = (serie.values[-1:] + extended_vals = (serie.values[-1:] +
serie.values) serie.values)
serie.interpolated = list( serie.interpolated = list(
@ -190,11 +189,6 @@ class Radar(Line):
self._rmax = self._max or 1 self._rmax = self._max or 1
self._box.set_polar_box(self._rmin, self._rmax) self._box.set_polar_box(self._rmin, self._rmax)
self._self_close = True self._self_close = True
self._x_pos = x_pos
def _compute_x_labels(self):
self._x_labels = self.x_labels and list(
zip(self.x_labels, self._x_pos))
def _compute_y_labels(self): def _compute_y_labels(self):
y_pos = compute_scale( y_pos = compute_scale(

6
pygal/graph/stackedbar.py

@ -65,11 +65,11 @@ class StackedBar(Bar):
positive_vals = positive_vals or [self.zero] positive_vals = positive_vals or [self.zero]
negative_vals = negative_vals or [self.zero] negative_vals = negative_vals or [self.zero]
x_pos = [ self._x_pos = [
x / self._len for x in range(self._len + 1) x / self._len for x in range(self._len + 1)
] if self._len > 1 else [0, 1] # Center if only one value ] if self._len > 1 else [0, 1] # Center if only one value
self._points(x_pos) self._points(self._x_pos)
self.negative_cumulation = [0] * self._len self.negative_cumulation = [0] * self._len
self.positive_cumulation = [0] * self._len self.positive_cumulation = [0] * self._len
@ -82,6 +82,8 @@ class StackedBar(Bar):
self.secondary_positive_cumulation = [0] * self._len self.secondary_positive_cumulation = [0] * self._len
self._pre_compute_secondary(positive_vals, negative_vals) self._pre_compute_secondary(positive_vals, negative_vals)
self._x_pos = [(i + .5) / self._len for i in range(self._len)]
def _pre_compute_secondary(self, positive_vals, negative_vals): def _pre_compute_secondary(self, positive_vals, negative_vals):
"""Compute secondary y min and max""" """Compute secondary y min and max"""
self._secondary_min = (negative_vals and min( self._secondary_min = (negative_vals and min(

4
pygal/graph/time.py

@ -25,7 +25,7 @@ into float for xy plot and back to their type for display
from pygal.adapters import positive from pygal.adapters import positive
from pygal.graph.xy import XY from pygal.graph.xy import XY
from datetime import datetime, date, time, timedelta from datetime import datetime, date, time, timedelta
from pygal._compat import timestamp, total_seconds from pygal._compat import timestamp, total_seconds, is_str
def datetime_to_timestamp(x): def datetime_to_timestamp(x):
@ -70,6 +70,8 @@ def time_to_seconds(x):
((x.hour * 60) + x.minute) * 60 + x.second ((x.hour * 60) + x.minute) * 60 + x.second
) * 10 ** 6 + x.microsecond) / 10 ** 6 ) * 10 ** 6 + x.microsecond) / 10 ** 6
if is_str(x):
return x
# Clamp to valid time # Clamp to valid time
return x and max(0, min(x, 24 * 3600 - 10 ** -6)) return x and max(0, min(x, 24 * 3600 - 10 ** -6))

23
pygal/graph/treemap.py

@ -55,13 +55,16 @@ class Treemap(Graph):
class_='rect reactive tooltip-trigger'), class_='rect reactive tooltip-trigger'),
metadata) metadata)
self._tooltip_data(rect, value, self._tooltip_data(
rx + rw / 2, rect, value,
ry + rh / 2, rx + rw / 2,
classes='centered') ry + rh / 2,
self._static_value(serie_node, value, 'centered',
rx + rw / 2, self._get_x_label(i))
ry + rh / 2) self._static_value(
serie_node, value,
rx + rw / 2,
ry + rh / 2)
def _binary_tree(self, data, total, x, y, w, h, parent=None): def _binary_tree(self, data, total, x, y, w, h, parent=None):
if total == 0: if total == 0:
@ -115,6 +118,12 @@ class Treemap(Graph):
self._binary_tree( self._binary_tree(
half2, half2_sum, x + x_pivot, y, w - x_pivot, h, parent) half2, half2_sum, x + x_pivot, y, w - x_pivot, h, parent)
def _compute_x_labels(self):
pass
def _compute_y_labels(self):
pass
def _plot(self): def _plot(self):
total = sum(map(sum, map(lambda x: x.values, self.series))) total = sum(map(sum, map(lambda x: x.values, self.series)))
if total == 0: if total == 0:

8
pygal/svg.py

@ -143,7 +143,7 @@ class Svg(object):
dct = get_js_dict() dct = get_js_dict()
# Config adds # Config adds
dct['legends'] = self.graph._legends dct['legends'] = self.graph._legends + self.graph._secondary_legends
common_script.text = " = ".join( common_script.text = " = ".join(
("window.config", json.dumps( ("window.config", json.dumps(
@ -239,7 +239,7 @@ class Svg(object):
def slice( def slice(
self, serie_node, node, radius, small_radius, self, serie_node, node, radius, small_radius,
angle, start_angle, center, val): angle, start_angle, center, val, i):
"""Draw a pie slice""" """Draw a pie slice"""
project = lambda rho, alpha: ( project = lambda rho, alpha: (
rho * sin(-alpha), rho * cos(-alpha)) rho * sin(-alpha), rho * cos(-alpha))
@ -274,7 +274,9 @@ class Svg(object):
x, y = diff(center, project( x, y = diff(center, project(
(radius + small_radius) / 2, start_angle + angle / 2)) (radius + small_radius) / 2, start_angle + angle / 2))
self.graph._tooltip_data(node, val, x, y, classes="centered") self.graph._tooltip_data(
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 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)
return rv return rv

Loading…
Cancel
Save