Browse Source

Prefix svg for multiple raw includes in html. Maybe related to #40

pull/58/head
Florian Mounier 12 years ago
parent
commit
4427daf8e4
  1. 17
      demo/moulinrouge/__init__.py
  2. 6
      demo/moulinrouge/templates/_layout.jinja2
  3. 1
      demo/moulinrouge/templates/index.jinja2
  4. 15
      demo/moulinrouge/templates/raw_svgs.jinja2
  5. 4
      pygal/config.py
  6. 14
      pygal/css/base.css
  7. 66
      pygal/css/graph.css
  8. 56
      pygal/css/style.css
  9. 5
      pygal/ghost.py
  10. 3
      pygal/graph/base.py
  11. 18
      pygal/style.py
  12. 11
      pygal/svg.py
  13. 7
      pygal/test/test_config.py
  14. 12
      pygal/test/test_graph.py
  15. 104
      pygal/test/test_style.py

17
demo/moulinrouge/__init__.py

@ -224,4 +224,21 @@ def create_app():
svgs=svgs,
width=width,
height=height)
@app.route("/raw_svgs/")
def raw_svgs():
svgs = []
for color in styles['neon'].colors:
chart = pygal.Pie(style=parametric_styles['RotateStyle'](color))
chart.title = color
chart.disable_xml_declaration = True
chart.explicit_size = True
chart.js = [
'http://l:2343/svg.jquery.js',
'http://l:2343/pygal-tooltips.js']
for i in range(6):
chart.add(str(i), 2 ** i)
svgs.append(chart.render())
return render_template('raw_svgs.jinja2', svgs=svgs)
return app

6
demo/moulinrouge/templates/_layout.jinja2

@ -2,8 +2,10 @@
<html>
<head>
<title>Moulin rouge - pygal test platform</title>
<script src="http://code.jquery.com/jquery.min.js" type="text/javascript"></script>
<script type="text/javascript" src="{{ url_for('static', filename='js.js') }}"></script>
{% block js %}
<script src="http://code.jquery.com/jquery.min.js" type="text/javascript"></script>
<script type="text/javascript" src="{{ url_for('static', filename='js.js') }}"></script>
{% endblock js %}
<link rel="stylesheet" href="{{ url_for('static', filename='css.css') }}" type="text/css" />
</head>
<body>

1
demo/moulinrouge/templates/index.jinja2

@ -22,6 +22,7 @@
</ul>
<a href="{{ url_for('interpolation') }}">Interpolation</a>
<a href="{{ url_for('rotation') }}">Rotations test</a>
<a href="{{ url_for('raw_svgs') }}">Raw svgs</a>
<hr />
<h3>Quick tests</h3>
<dl>

15
demo/moulinrouge/templates/raw_svgs.jinja2

@ -0,0 +1,15 @@
{% extends '_layout.jinja2' %}
{% block js %}
<script type="text/javascript" src="http://l:2343/svg.jquery.js"></script>
<script type="text/javascript" src="http://l:2343/pygal-tooltips.js"></script>
{% endblock js %}
{% block section %}
{% for svg in svgs %}
<figure>
{{ svg | safe }}
<figcaption></figcaption>
</figure>
{% endfor %}
{% endblock section %}

4
pygal/config.py

@ -284,6 +284,10 @@ class Config(object):
False, bool, "Misc",
"If True don't try to adapt / filter wrong values")
no_prefix = Key(
False, bool, "Misc",
"Don't prefix css")
def __init__(self, **kwargs):
"""Can be instanciated with config kwargs"""
for k in dir(self):

14
pygal/css/base.css

@ -22,37 +22,37 @@
* Font-sizes from config, override with care
*/
.title {
{{ id }}.title {
font-family: monospace;
font-size: {{ font_sizes.title }};
}
.legends .legend text {
{{ id }}.legends .legend text {
font-family: monospace;
font-size: {{ font_sizes.legend }};
}
.axis text {
{{ id }}.axis text {
font-family: monospace;
font-size: {{ font_sizes.label }};
}
.axis text.major {
{{ id }}.axis text.major {
font-family: monospace;
font-size: {{ font_sizes.major_label }};
}
.series text {
{{ id }}.series text {
font-family: monospace;
font-size: {{ font_sizes.value }};
}
#tooltip text {
{{ id }}#tooltip text {
font-family: monospace;
font-size: {{ font_sizes.tooltip }};
}
text.no_data {
{{ id }}text.no_data {
font-size: {{ font_sizes.no_data }};
}

66
pygal/css/graph.css

@ -18,110 +18,110 @@
* along with pygal. If not, see <http://www.gnu.org/licenses/>.
*/
text.no_data {
{{ id }}text.no_data {
text-anchor: middle;
}
.guide.line {
{{ id }}.guide.line {
fill-opacity: 0;
}
.centered {
{{ id }}.centered {
text-anchor: middle;
}
.title {
{{ id }}.title {
text-anchor: middle;
}
.legends .legend text {
{{ id }}.legends .legend text {
fill-opacity: 1;
}
.axis.x text {
{{ id }}.axis.x text {
text-anchor: middle;
}
.axis.x:not(.web) text[transform] {
{{ id }}.axis.x:not(.web) text[transform] {
text-anchor: start;
}
.axis.y text {
{{ id }}.axis.y text {
text-anchor: end;
}
.axis.y2 text {
{{ id }}.axis.y2 text {
text-anchor: start;
}
.axis.y .logarithmic text:not(.major) ,
.axis.y2 .logarithmic text:not(.major) {
{{ id }}.axis.y .logarithmic text:not(.major) ,
{{ id }}.axis.y2 .logarithmic text:not(.major) {
font-size: 50%;
}
.axis .guide.line {
{{ id }}.axis .guide.line {
stroke-dasharray: 4,4;
}
.axis .major.guide.line {
{{ id }}.axis .major.guide.line {
stroke-dasharray: 6,6;
}
.axis text.major {
{{ id }}.axis text.major {
stroke-width: 0.5px;
}
.horizontal .axis.y .guide.line,
.horizontal .axis.y2 .guide.line,
.vertical .axis.x .guide.line {
{{ id }}.horizontal .axis.y .guide.line,
{{ id }}.horizontal .axis.y2 .guide.line,
{{ id }}.vertical .axis.x .guide.line {
opacity: 0;
}
.axis.y .guides:hover .guide.line,
.axis.y2 .guides:hover .guide.line,
.line-graph .axis.x .guides:hover .guide.line,
.gauge-graph .axis.x .guides:hover .guide.line,
.stackedline-graph .axis.x .guides:hover .guide.line,
.xy-graph .axis.x .guides:hover .guide.line {
{{ id }}.axis.y .guides:hover .guide.line,
{{ id }}.axis.y2 .guides:hover .guide.line,
{{ id }}.line-graph .axis.x .guides:hover .guide.line,
{{ id }}.gauge-graph .axis.x .guides:hover .guide.line,
{{ id }}.stackedline-graph .axis.x .guides:hover .guide.line,
{{ id }}.xy-graph .axis.x .guides:hover .guide.line {
opacity: 1;
}
.axis .guides:hover text {
{{ id }}.axis .guides:hover text {
opacity: 1;
}
.nofill {
{{ id }}.nofill {
fill: none;
}
.dot {
{{ id }}.dot {
stroke-width: 1px;
fill-opacity: 1;
}
.dot.active {
{{ id }}.dot.active {
stroke-width: 5px;
}
.series text {
{{ id }}.series text {
stroke: none;
}
.series text.active {
{{ id }}.series text.active {
opacity: 1;
}
#tooltip rect {
{{ id }}#tooltip rect {
fill-opacity: 0.8;
}
#tooltip text {
{{ id }}#tooltip text {
fill-opacity: 1;
}
#tooltip text tspan.label {
{{ id }}#tooltip text tspan.label {
fill-opacity: .8;
}
a:visited {
{{ id }}a:visited {
fill: none;
}

56
pygal/css/style.css

@ -22,94 +22,98 @@
* Styles from config
*/
svg {
{{ id }}{
background-color: {{ style.background }};
}
svg path, svg line, svg rect, svg circle {
{{ id }}path,
{{ id }}line,
{{ id }}rect,
{{ id }}circle {
-webkit-transition: {{ style.transition }};
-moz-transition: {{ style.transition }};
transition: {{ style.transition }};
}
.graph > .background {
{{ id }}.graph > .background {
fill: {{ style.background }};
}
.plot > .background {
{{ id }}.plot > .background {
fill: {{ style.plot_background }};
}
.graph {
{{ id }}.graph {
fill: {{ style.foreground }};
}
text.no_data {
{{ id }}text.no_data {
fill: {{ style.foreground_light }};
}
.title {
{{ id }}.title {
fill: {{ style.foreground_light }};
}
.legends .legend text {
{{ id }}.legends .legend text {
fill: {{ style.foreground }};
}
.legends .legend:hover text {
{{ id }}.legends .legend:hover text {
fill: {{ style.foreground_light }};
}
.axis .line {
{{ id }}.axis .line {
stroke: {{ style.foreground_light }};
}
.axis .guide.line {
{{ id }}.axis .guide.line {
stroke: {{ style.foreground_dark }};
}
.axis .major.line {
{{ id }}.axis .major.line {
stroke: {{ style.foreground }};
}
.axis text.major {
{{ id }}.axis text.major {
stroke: {{ style.foreground_light }};
fill: {{ style.foreground_light }};
}
.axis.y .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 {
{{ id }}.axis.y .guides:hover .guide.line,
{{ id }}.line-graph .axis.x .guides:hover .guide.line,
{{ id }}.stackedline-graph .axis.x .guides:hover .guide.line,
{{ id }}.xy-graph .axis.x .guides:hover .guide.line {
stroke: {{ style.foreground_light }};
}
.axis .guides:hover text {
{{ id }}.axis .guides:hover text {
fill: {{ style.foreground_light }};
}
.reactive {
{{ id }}.reactive {
fill-opacity: {{ style.opacity }};
}
.reactive.active, .active .reactive {
{{ id }}.reactive.active,
{{ id }}.active .reactive {
fill-opacity: {{ style.opacity_hover }};
}
.series text {
{{ id }}.series text {
fill: {{ style.foreground_light }};
}
#tooltip rect {
{{ id }}#tooltip rect {
fill: {{ style.plot_background }};
stroke: {{ style.foreground_light }};
}
#tooltip text {
{{ id }}#tooltip text {
fill: {{ style.foreground_light }};
}
.country {
{{ id }}.country {
fill: {{ style.foreground }};
stroke: {{ style.plot_background }} !important;
opacity: .9;
@ -120,11 +124,11 @@ text.no_data {
transition: 250ms;
}
.country:hover {
{{ id }}.country:hover {
opacity: 1;
stroke-width: 10;
}
{{ style.colors }}
{{ colors }}

5
pygal/ghost.py

@ -30,6 +30,7 @@ from pygal.config import Config
from pygal._compat import u
from pygal.graph import CHARTS_NAMES
from pygal.util import prepare_values
from uuid import uuid4
REAL_CHARTS = {}
@ -46,6 +47,7 @@ class Ghost(object):
"""Init config"""
name = self.__class__.__name__
self.cls = REAL_CHARTS[name]
self.uuid = str(uuid4())
if config and isinstance(config, type):
config = config()
@ -76,7 +78,8 @@ class Ghost(object):
self.config.__dict__.update(overrides)
series = self.make_series(self.raw_series)
secondary_series = self.make_series(self.raw_series2)
self._last__inst = self.cls(self.config, series, secondary_series)
self._last__inst = self.cls(
self.config, series, secondary_series, self.uuid)
return self._last__inst
# Rendering

3
pygal/graph/base.py

@ -35,8 +35,9 @@ class BaseGraph(object):
_adapters = []
def __init__(self, config, series, secondary_series):
def __init__(self, config, series, secondary_series, uuid):
"""Init the graph"""
self.uuid = uuid
self.config = config
self.series = series or []
self.secondary_series = secondary_series or []

18
pygal/style.py

@ -51,20 +51,19 @@ class Style(object):
self.opacity = opacity
self.opacity_hover = opacity_hover
self.transition = transition
self._colors = colors
self.colors = colors
@property
def colors(self):
def get_colors(self, prefix):
"""Get the css color list"""
def color(tupl):
"""Make a color css"""
return (
'.color-{0} {{\n'
return ((
'%s.color-{0} {{\n'
' stroke: {1};\n'
' fill: {1};\n'
'}}\n'.format(*tupl))
return '\n'.join(map(color, enumerate(cycle_fill(self._colors, 16))))
'}}\n') % prefix).format(*tupl)
return '\n'.join(map(color, enumerate(cycle_fill(self.colors, 16))))
def to_dict(self):
config = {}
@ -248,7 +247,8 @@ BlueStyle = Style(
opacity_hover='.9',
transition='250ms ease-in',
colors=('#00b2f0', '#43d9be', '#0662ab', '#ffd541', lighten('#43d9be', 20),
lighten('#7dcf30', 10), darken('#0662ab', 15), '#7dcf30', darken('#ffd541', 20)))
lighten('#7dcf30', 10), darken('#0662ab', 15),
'#7dcf30', darken('#ffd541', 20)))
styles = {'default': DefaultStyle,
@ -297,7 +297,7 @@ for op in ('lighten', 'darken', 'saturate', 'desaturate', 'rotate'):
return Style(colors=colors, **kwargs)
base_style.__dict__.update(kwargs)
base_style._colors = colors
base_style.colors = colors
return base_style
return parametric_style

11
pygal/svg.py

@ -40,6 +40,10 @@ class Svg(object):
def __init__(self, graph):
self.graph = graph
if not graph.no_prefix:
self.id = '#chart-%s ' % graph.uuid
else:
self.id = ''
self.processing_instructions = [
etree.PI(u('xml'), u("version='1.0' encoding='utf-8'"))]
self.root = etree.Element(
@ -48,6 +52,8 @@ class Svg(object):
None: self.ns,
'xlink': 'http://www.w3.org/1999/xlink',
})
self.root.attrib['id'] = self.id.lstrip('#').rstrip()
self.root.attrib['class'] = 'pygal-chart'
self.root.append(
etree.Comment(u(
'Generated with pygal %s ©Kozea 2011-2013 on %s' % (
@ -60,6 +66,7 @@ class Svg(object):
def add_styles(self):
"""Add the css to the svg"""
colors = self.graph.style.get_colors(self.id)
all_css = []
for css in ['base.css'] + list(self.graph.css):
if urlparse(css).scheme:
@ -74,7 +81,9 @@ class Svg(object):
css_text = template(
f.read(),
style=self.graph.style,
font_sizes=self.graph.font_sizes())
colors=colors,
font_sizes=self.graph.font_sizes(),
id=self.id)
if not self.graph.pretty_print:
css_text = minify_css(css_text)
all_css.append(css_text)

7
pygal/test/test_config.py

@ -27,6 +27,7 @@ def test_config_behaviours():
line1.show_legend = False
line1.fill = True
line1.pretty_print = True
line1.no_prefix = True
line1.x_labels = ['a', 'b', 'c']
line1.add('_', [1, 2, 3])
l1 = line1.render()
@ -45,6 +46,7 @@ def test_config_behaviours():
show_legend=False,
fill=True,
pretty_print=True,
no_prefix=True,
x_labels=['a', 'b', 'c'])
line2.add('_', [1, 2, 3])
l2 = line2.render()
@ -54,6 +56,7 @@ def test_config_behaviours():
show_legend = False
fill = True
pretty_print = True
no_prefix = True
x_labels = ['a', 'b', 'c']
line3 = Line(LineConfig)
@ -70,6 +73,7 @@ def test_config_behaviours():
line_config.show_legend = False
line_config.fill = True
line_config.pretty_print = True
line_config.no_prefix = True
line_config.x_labels = ['a', 'b', 'c']
line5 = Line(line_config)
@ -80,6 +84,7 @@ def test_config_behaviours():
def test_config_alterations_class():
class LineConfig(Config):
no_prefix = True
show_legend = False
fill = True
pretty_print = True
@ -101,6 +106,7 @@ def test_config_alterations_class():
def test_config_alterations_instance():
class LineConfig(Config):
no_prefix = True
show_legend = False
fill = True
pretty_print = True
@ -123,6 +129,7 @@ def test_config_alterations_instance():
def test_config_alterations_kwargs():
class LineConfig(Config):
no_prefix = True
show_legend = False
fill = True
pretty_print = True

12
pygal/test/test_graph.py

@ -115,12 +115,12 @@ def test_empty_lists_with_nones(Chart):
def test_non_iterable_value(Chart):
chart = Chart()
chart = Chart(no_prefix=True)
chart.add('A', 1)
chart.add('B', 2)
chart.x_labels = ('red', 'green', 'blue')
chart1 = chart.render()
chart = Chart()
chart = Chart(no_prefix=True)
chart.add('A', [1])
chart.add('B', [2])
chart.x_labels = ('red', 'green', 'blue')
@ -129,13 +129,13 @@ def test_non_iterable_value(Chart):
def test_iterable_types(Chart):
chart = Chart()
chart = Chart(no_prefix=True)
chart.add('A', [1, 2])
chart.add('B', [])
chart.x_labels = ('red', 'green', 'blue')
chart1 = chart.render()
chart = Chart()
chart = Chart(no_prefix=True)
chart.add('A', (1, 2))
chart.add('B', tuple())
chart.x_labels = ('red', 'green', 'blue')
@ -144,8 +144,8 @@ def test_iterable_types(Chart):
def test_values_by_dict(Chart):
chart1 = Chart()
chart2 = Chart()
chart1 = Chart(no_prefix=True)
chart2 = Chart(no_prefix=True)
if Chart != pygal.Worldmap:
chart1.add('A', {'red': 10, 'green': 12, 'blue': 14})

104
pygal/test/test_style.py

@ -1,104 +0,0 @@
# -*- coding: utf-8 -*-
# This file is part of pygal
#
# A python svg graph plotting library
# Copyright © 2012-2013 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/>.
from pygal.style import Style
def test_colors():
style = Style(colors=['red', '#231A3b', '#ff0', 'rgb(12, 231, 3)'])
assert style.colors == '''\
.color-0 {
stroke: red;
fill: red;
}
.color-1 {
stroke: #231A3b;
fill: #231A3b;
}
.color-2 {
stroke: #ff0;
fill: #ff0;
}
.color-3 {
stroke: rgb(12, 231, 3);
fill: rgb(12, 231, 3);
}
.color-4 {
stroke: red;
fill: red;
}
.color-5 {
stroke: #231A3b;
fill: #231A3b;
}
.color-6 {
stroke: #ff0;
fill: #ff0;
}
.color-7 {
stroke: rgb(12, 231, 3);
fill: rgb(12, 231, 3);
}
.color-8 {
stroke: red;
fill: red;
}
.color-9 {
stroke: #231A3b;
fill: #231A3b;
}
.color-10 {
stroke: #ff0;
fill: #ff0;
}
.color-11 {
stroke: rgb(12, 231, 3);
fill: rgb(12, 231, 3);
}
.color-12 {
stroke: red;
fill: red;
}
.color-13 {
stroke: #231A3b;
fill: #231A3b;
}
.color-14 {
stroke: #ff0;
fill: #ff0;
}
.color-15 {
stroke: rgb(12, 231, 3);
fill: rgb(12, 231, 3);
}
'''
Loading…
Cancel
Save