Browse Source

Add render_to_file and bug fix

pull/8/head
Florian Mounier 13 years ago
parent
commit
154636df6a
  1. 4
      demo/moulinrouge/__init__.py
  2. 2
      pygal/__init__.py
  3. 2
      pygal/config.py
  4. 6
      pygal/css/graph.css
  5. 6
      pygal/graph/base.py
  6. 15
      pygal/graph/graph.py
  7. 29
      pygal/js/graph.coffee
  8. 39
      pygal/js/graph.js
  9. 6
      pygal/svg.py
  10. 33
      pygal/test/test_graph.py

4
demo/moulinrouge/__init__.py

@ -117,7 +117,7 @@ def create_app():
config = Config()
config.width = width
config.height = height
config.fill = True
config.fill = bool(random.randrange(0, 2))
config.human_readable = True
config.style = styles[style]
config.x_labels = [random_label() for i in range(data)]
@ -148,7 +148,7 @@ def create_app():
series = b64encode(pickle.dumps(_random_series(type, data, order)))
labels = [random_label() for i in range(data)]
svgs = []
config.show_legend = bool(random.randrange(0, 1))
config.show_legend = bool(random.randrange(0, 2))
for angle in range(0, 91, 5):
config.title = "%d rotation" % angle
config.x_labels = labels

2
pygal/__init__.py

@ -16,7 +16,7 @@
#
# You should have received a copy of the GNU Lesser General Public License
# along with pygal. If not, see <http://www.gnu.org/licenses/>.
__version__ = '0.9.11'
__version__ = '0.9.12'
from collections import namedtuple
from pygal.graph.bar import Bar

2
pygal/config.py

@ -88,6 +88,8 @@ class Config(object):
print_values = True
# Print zeroes when graph is in non interactive mode
print_zeroes = False
# Animate tooltip steps (0 disable animation)
animation_steps = 0
def __init__(self, **kwargs):
"""Can be instanciated with config kwargs"""

6
pygal/css/graph.css

@ -117,9 +117,9 @@ text.no_data {
}
.axis.y .guides:hover .guide.line,
.Line .axis.x .guides:hover .guide.line,
.StackedLine .axis.x .guides:hover .guide.line,
.XY .axis.x .guides:hover .guide.line {
.line-graph .axis.x .guides:hover .guide.line,
.stackedline-graph .axis.x .guides:hover .guide.line,
.xy-graph .axis.x .guides:hover .guide.line {
stroke: {{ style.foreground_light }};
opacity: 1;
}

6
pygal/graph/base.py

@ -39,6 +39,8 @@ class BaseGraph(object):
def _pos(self, min_, max_, scale, min_scale=4, max_scale=20):
if min_ == 0 and max_ == 0:
return [0]
if max_ - min_ == 0:
return [min_]
if self.logarithmic:
return self._pos_logarithmic(min_, max_)
order = round(log10(max(abs(min_), abs(max_)))) - 1
@ -143,3 +145,7 @@ class BaseGraph(object):
def render_response(self):
from flask import Response
return Response(self.render(), mimetype='image/svg+xml')
def render_to_file(self, filename):
with open(filename, 'w') as f:
f.write(self.render())

15
pygal/graph/graph.py

@ -22,7 +22,7 @@ class Graph(BaseGraph):
def _make_graph(self):
self.graph_node = self.svg.node(
class_='graph %s' % self.__class__.__name__)
class_='graph %s-graph' % self.__class__.__name__.lower())
self.svg.node(self.graph_node, 'rect',
class_='background',
x=0, y=0,
@ -51,19 +51,6 @@ class Graph(BaseGraph):
self.margin.left, self.margin.top))
self.tooltip_node = self.svg.node(tooltip_overlay, id="tooltip",
transform='translate(0 0)')
# self.svg.node(
# self.tooltip_node, 'animateTransform',
# id="tooltip-slide",
# attributeName='transform',
# attributeType='XML',
# type='translate',
# calcMode='spline',
# dur='100ms',
# end='indefinite',
# begin='indefinite',
# from_="0 0",
# to="100 100",
# fill='freeze')
self.svg.node(self.tooltip_node, 'rect',
id="tooltip-box",

29
pygal/js/graph.coffee

@ -3,6 +3,7 @@ __ = (x) -> document.getElementById(x)
padding = 5
tooltip_timeout = 0
tooltip_font_size = parseInt("{{ font_sizes.tooltip }}")
anim_steps = parseInt("{{ animation_steps }}")
class Queue
constructor: (@delay) ->
@ -32,7 +33,7 @@ class Queue
@queue = []
@running = false
tooltip_anim_Q = new Queue 1
tooltip_anim_Q = new Queue 100
has_class = (e, class_name) ->
return if not e
@ -106,19 +107,19 @@ tooltip = (elt) ->
[current_x, current_y] = (parseInt(s) for s in _tooltip.getAttribute('transform').replace('translate(', '').replace(')', '').split ' ')
return if current_x == x and current_y == y
step = 12
x_step = (x - current_x) / step
y_step = (y - current_y) / step
anim_x = current_x
anim_y = current_y
for i in [0..step]
anim_x += x_step
anim_y += y_step
tooltip_anim_Q.add ((_x, _y) ->
_tooltip.setAttribute('transform', "translate(#{_x} #{_y})")), anim_x, anim_y
tooltip_anim_Q.add ((_x, _y) ->
_tooltip.setAttribute('transform', "translate(#{_x} #{_y})")), x, y
if anim_steps
x_step = (x - current_x) / (anim_steps + 1)
y_step = (y - current_y) / (anim_steps + 1)
anim_x = current_x
anim_y = current_y
for i in [0..anim_steps]
anim_x += x_step
anim_y += y_step
tooltip_anim_Q.add ((_x, _y) ->
_tooltip.setAttribute('transform', "translate(#{_x} #{_y})")), anim_x, anim_y
tooltip_anim_Q.add -> _tooltip.setAttribute('transform', "translate(#{x} #{y})")
else
_tooltip.setAttribute('transform', "translate(#{x} #{y})")
untooltip = ->
tooltip_timeout = setTimeout (->

39
pygal/js/graph.js

@ -1,6 +1,6 @@
// Generated by CoffeeScript 1.2.1-pre
(function() {
var Queue, activate, add_class, deactivate, has_class, height, hover, padding, rm_class, svg, tooltip, tooltip_anim_Q, tooltip_font_size, tooltip_timeout, untooltip, width, _, __,
var Queue, activate, add_class, anim_steps, deactivate, has_class, height, hover, padding, rm_class, svg, tooltip, tooltip_anim_Q, tooltip_font_size, tooltip_timeout, untooltip, width, _, __,
__slice = [].slice;
_ = function(x) {
@ -17,6 +17,8 @@
tooltip_font_size = parseInt("{{ font_sizes.tooltip }}");
anim_steps = parseInt("{{ animation_steps }}");
Queue = (function() {
Queue.name = 'Queue';
@ -67,7 +69,7 @@
})();
tooltip_anim_Q = new Queue(1);
tooltip_anim_Q = new Queue(100);
has_class = function(e, class_name) {
var cls, cn, i, _i, _len;
@ -153,7 +155,7 @@
};
tooltip = function(elt) {
var anim_x, anim_y, current_x, current_y, h, i, s, step, value, w, x, x_elt, x_step, y, y_elt, y_step, _i, _rect, _ref, _text, _tooltip;
var anim_x, anim_y, current_x, current_y, h, i, s, value, w, x, x_elt, x_step, y, y_elt, y_step, _i, _rect, _ref, _text, _tooltip;
tooltip_anim_Q.clear();
clearTimeout(tooltip_timeout);
_tooltip = __('tooltip');
@ -185,21 +187,24 @@
return _results;
})(), current_x = _ref[0], current_y = _ref[1];
if (current_x === x && current_y === y) return;
step = 12;
x_step = (x - current_x) / step;
y_step = (y - current_y) / step;
anim_x = current_x;
anim_y = current_y;
for (i = _i = 0; 0 <= step ? _i <= step : _i >= step; i = 0 <= step ? ++_i : --_i) {
anim_x += x_step;
anim_y += y_step;
tooltip_anim_Q.add((function(_x, _y) {
return _tooltip.setAttribute('transform', "translate(" + _x + " " + _y + ")");
}), anim_x, anim_y);
if (anim_steps) {
x_step = (x - current_x) / (anim_steps + 1);
y_step = (y - current_y) / (anim_steps + 1);
anim_x = current_x;
anim_y = current_y;
for (i = _i = 0; 0 <= anim_steps ? _i <= anim_steps : _i >= anim_steps; i = 0 <= anim_steps ? ++_i : --_i) {
anim_x += x_step;
anim_y += y_step;
tooltip_anim_Q.add((function(_x, _y) {
return _tooltip.setAttribute('transform', "translate(" + _x + " " + _y + ")");
}), anim_x, anim_y);
}
return tooltip_anim_Q.add(function() {
return _tooltip.setAttribute('transform', "translate(" + x + " " + y + ")");
});
} else {
return _tooltip.setAttribute('transform', "translate(" + x + " " + y + ")");
}
return tooltip_anim_Q.add((function(_x, _y) {
return _tooltip.setAttribute('transform', "translate(" + _x + " " + _y + ")");
}), x, y);
};
untooltip = function() {

6
pygal/svg.py

@ -59,8 +59,10 @@ class Svg(object):
script = self.node(self.root, 'script', type='text/javascript')
with open(js) as f:
templ = template(
f.read(),
font_sizes=self.graph.font_sizes(False))
f.read(),
font_sizes=self.graph.font_sizes(False),
animation_steps=self.graph.animation_steps
)
script.text = templ.decode('utf-8')
def node(self, parent=None, tag='g', attrib=None, **extras):

33
pygal/test/test_graph.py

@ -0,0 +1,33 @@
# -*- coding: utf-8 -*-
# This file is part of pygal
#
# A python svg graph plotting library
# Copyright © 2012 Kozea
#
# This library is free software: you can redistribute it and/or modify it under
# the terms of the GNU Lesser General Public License as published by the Free
# Software Foundation, either version 3 of the License, or (at your option) any
# later version.
#
# This library is distributed in the hope that it will be useful, but WITHOUT
# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
# FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
# details.
#
# You should have received a copy of the GNU Lesser General Public License
# along with pygal. If not, see <http://www.gnu.org/licenses/>.
import os
from pygal import Line
def test_render_to_file():
file_name = '/tmp/test_graph.svg'
if os.path.exists(file_name):
os.remove(file_name)
line = Line()
line.add('Serie 1', [1])
line.render_to_file(file_name)
with open(file_name) as f:
assert 'pygal' in f.read()
os.remove(file_name)
Loading…
Cancel
Save