Browse Source

Clean up config + organize it

pull/8/head
Florian Mounier 12 years ago
parent
commit
864ee6a6b2
  1. 2
      demo/cabaret/static/css.css
  2. 12
      demo/cabaret/static/js.js
  3. 6
      demo/cabaret/templates/_layout.jinja2
  4. 116
      demo/cabaret/templates/index.jinja2
  5. 11
      demo/moulinrouge/tests.py
  6. 161
      pygal/config.py
  7. 4
      pygal/graph/bar.py
  8. 2
      pygal/graph/line.py
  9. 3
      pygal/util.py

2
demo/cabaret/static/css.css

@ -16,7 +16,7 @@ figure svg {
background: none;
}
textarea {
.nav a {
-webkit-transition: all 500ms ease-out;
-moz-transition: all 500ms ease-out;
transition: all 500ms ease-out;

12
demo/cabaret/static/js.js

@ -9,9 +9,8 @@ function resend() {
var $this = $(this),
val = $this.val();
if($this.attr('type') == 'checkbox') {
val = $this.is(":checked");
}
if(val) {
opts[$this.attr('id').replace('c-', '')] = $this.is(":checked");
} else if(val) {
opts[$this.attr('id').replace('c-', '')] = val;
}
});
@ -29,9 +28,9 @@ function resend() {
// $fig.find('div').get(0).innerHTML = data;
$fig.find('div').html(data);
init_svg($fig.find('svg').get(0));
$('textarea').css({'-webkit-box-shadow': ''});
$('.nav a').css({color: ''});
}).fail(function () {
$('textarea').css({'-webkit-box-shadow': 'inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 8px rgba(255, 0, 0, 0.6)'});
$('.nav a').css({color: 'red'});
});
}
@ -41,7 +40,6 @@ $(function () {
$('#style').on('change', resend);
$('.c-opts:not([type=checkbox])').on('input', resend);
$('.c-opts[type=checkbox]').on('change', resend);
$('label.tt').tooltip({ placement: 'right' });
$('input.tt').tooltip({ placement: 'top' });
$('div.tt').tooltip();
resend();
});

6
demo/cabaret/templates/_layout.jinja2

@ -27,13 +27,13 @@
<div class="container-fluid">
<div class="row-fluid">
<div class="span3">
<div class="well sidebar-nav">
<div class="span4">
<div class="">
{% block side %}
{% endblock side %}
</div>
</div>
<div class="span9">
<div class="span8">
{% block section %}
{% endblock section %}
</div>

116
demo/cabaret/templates/index.jinja2

@ -1,54 +1,80 @@
{% extends '_layout.jinja2' %}
{% block side %}
<ul class="nav nav-list">
<li class="nav-header">Type</li>
<li>
<select id="type">
{% for name in charts_names %}
<option value="{{ name }}">{{ name }}</option>
<form class="form-horizontal">
<div class="tabbable tabs-left">
<ul class="nav nav-tabs">
<li class="active"><a href="#main" data-toggle="tab">Main</a></li>
{% for group in configs[0].categories if group != 'Style' %}
<li><a href="#{{ group }}" data-toggle="tab">{{ group }}</a></li>
{% endfor %}
</select>
</li>
<li class="divider"></li>
<li class="nav-header">Data</li>
<li>
<textarea id="data" rows="3">
</ul>
<div class="tab-content">
<div class="tab-pane active" id="main">
<div class="control-group tt" title="Chose the chart type">
<label class="control-label" for="type">Type</label>
<div class="controls">
<select id="type">
{% for name in charts_names %}
<option value="{{ name }}">{{ name }}</option>
{% endfor %}
</select>
</div>
</div>
<div class="control-group tt" title="Enter the chart data">
<label class="control-label" for="data">Data</label>
<div class="controls">
<textarea id="data" rows="3">
"Serie 1": [4, 5, 2, 8, 2, 0],
"Serie 2": [0, 5, 2, 6, 2]
</textarea>
</li>
<li class="divider"></li>
<li>
<li class="nav-header">Style</li>
<select id="style">
{% for style in styles_names | sort(-1) %}
<option value="{{ style }}">{{ style.replace('_', ' ') | title }}</option>
{% endfor %}
</select>
</li>
<li class="divider"></li>
{% for key in configs if key.name not in ['js', 'css'] %}
{% set doc = 'title="' + key.doc + ' ' + key.subdoc + '"' %}
<li>
<div class="controls">
{% if key.is_boolean %}
<label class="nav-header checkbox tt" for="c-{{ key.name }}" {{ doc }}>
<input type="checkbox" id="c-{{ key.name }}" class="c-opts tt" {{ 'checked' if key.value }} {{ doc }} />{{ key.name }}
</label>
{% else %}
<label class="nav-header tt" for="c-{{ key.name }}" {{ doc }}> {{ key.name }}</label>
{% if key.is_numeric %}
<input type="number" id="c-{{ key.name }}" class="c-opts tt" value="{{ key.value or ''}}" {{ doc }} />
{% elif key.is_string %}
<input type="text" id="c-{{ key.name }}" class="c-opts tt" value="{{ key.value or ''}}" {{ doc }} />
{% elif key.is_list %}
<input type="text" id="c-{{ key.name }}" class="c-opts tt list-of-{{ key.subtype}}" placeholder="value1, value2, ..." value="{{ key.value or ''}}" {{ doc }} />
{% endif %}
{% endif %}
</textarea>
</div>
</div>
<div class="control-group tt" title="Chose the chart style">
<label class="control-label" for="style">Style</label>
<div class="controls">
<select id="style">
{% for style in styles_names | sort(-1) %}
<option value="{{ style }}">{{ style.replace('_', ' ') | title }}</option>
{% endfor %}
</select>
</div>
</div>
</div>
</li>
{% endfor %}
</ul>
{% for group, keys in configs | groupby('category') %}
<div class="tab-pane" id="{{ group }}">
{% for key in keys if key.name not in ['js', 'css', 'style'] %}
{% set doc = 'title="' + key.doc + ' <br /><small>' + key.subdoc + '</small>"' %}
<div class="control-group tt" {{ doc }}>
{% if key.is_boolean %}
<div class="controls">
<label class="checkbox" for="c-{{ key.name }}">
<input type="checkbox" id="c-{{ key.name }}" class="c-opts" {{ 'checked' if key.value }} />{{ key.name.replace('_', ' ') |title }}
</label>
</div>
{% else %}
<label class="control-label" for="c-{{ key.name }}" > {{ key.name.replace('_', ' ') | title }}</label>
<div class="controls">
{% if key.is_numeric %}
<input type="number" id="c-{{ key.name }}" class="c-opts" value="{{ key.value or ''}}" />
{% elif key.is_string %}
<input type="text" id="c-{{ key.name }}" class="c-opts" value="{{ key.value or ''}}" />
{% elif key.is_list %}
<input type="text" id="c-{{ key.name }}" class="c-opts list-of-{{ key.subtype }}" placeholder="value1, value2{{ ', ...' if key.name != 'range' }}" value="{{ key.value or ''}}" />
{% endif %}
</div>
{% endif %}
</div>
{% endfor %}
</div>
{% endfor %}
</div>
</div>
</form>
{% endblock side %}
{% block section %}

11
demo/moulinrouge/tests.py

@ -1,6 +1,8 @@
# -*- coding: utf-8 -*-
# This file is part of pygal
from pygal import Bar, Gauge, Pyramid, Funnel, Dot, StackedBar, CHARTS_BY_NAME, Config
from pygal import (
Bar, Gauge, Pyramid, Funnel, Dot, StackedBar,
CHARTS_BY_NAME, Config, Line)
from pygal.style import styles
@ -111,6 +113,13 @@ def get_test_routes(app):
stacked.add('2', [4, 5, 6])
return stacked.render_response()
@app.route('/test/show_dots')
def test_show_dots():
line = Line(show_dots=False)
line.add('1', [1, 2, 3])
line.add('2', [4, 5, 6])
return line.render_response()
@app.route('/test/config')
def test_config():

161
pygal/config.py

@ -32,13 +32,22 @@ CONFIG_ITEMS = []
class Key(object):
def __init__(self, default_value, type_, doc, subdoc="", subtype=None):
categories = []
def __init__(
self, default_value, type_, category, doc,
subdoc="", subtype=None):
self.value = default_value
self.type = type_
self.doc = doc
self.category = category
self.subdoc = subdoc
self.subtype = subtype
self.name = "Unbound"
if not category in self.categories:
self.categories.append(category)
CONFIG_ITEMS.append(self)
@property
@ -81,124 +90,152 @@ class Config(object):
__metaclass__ = MetaConfig
width = Key(800, int, "Graph width")
height = Key(600, int, "Graph height")
human_readable = Key(
False, bool, "Display values in human readable format",
"(ie: 12.4M)")
logarithmic = Key(False, bool, "Display values in logarithmic scale")
order_min = Key(None, int, "Minimum order of scale, defaults to None")
style = Key(
DefaultStyle, Style, "Style", "Style holding values injected in css")
css = Key(
('style.css', 'graph.css'), list,
('style.css', 'graph.css'), list, "Style",
"List of css file",
"It can be an absolute file path or an external link",
str)
js = Key(
('https://raw.github.com/Kozea/pygal.js/master/svg.jquery.js',
'https://raw.github.com/Kozea/pygal.js/master/pygal-tooltips.js'),
list, "List of js file",
"It can be a filepath or an external link",
str)
style = Key(DefaultStyle, Style, "Style holding values injected in css")
label_font_size = Key(10, int, "Label font size")
############ Look ############
value_font_size = Key(8, int, "Value font size")
title = Key(
None, str, "Look",
"Graph title.", "Leave it to None to disable title.")
tooltip_font_size = Key(20, int, "Tooltip font size")
width = Key(
800, int, "Look", "Graph width")
title_font_size = Key(16, int, "Title font size")
height = Key(
600, int, "Look", "Graph height")
legend_font_size = Key(14, int, "Legend font size")
show_dots = Key(True, bool, "Look", "Set to false to remove dots")
x_label_rotation = Key(
0, int, "Specify x labels rotation angles", "in degrees")
stroke = Key(
True, bool, "Look",
"Line dots (set it to false to get a scatter plot)")
y_label_rotation = Key(
0, int, "Specify y labels rotation angles", "in degrees")
fill = Key(
False, bool, "Look", "Fill areas under lines")
show_legend = Key(True, bool, "Set to false to remove legend")
show_legend = Key(
True, bool, "Look", "Set to false to remove legend")
legend_at_bottom = Key(
False, bool, "Set to true to position legend at bottom")
False, bool, "Look", "Set to true to position legend at bottom")
show_dots = Key(True, bool, "Set to false to remove dots")
legend_box_size = Key(
12, int, "Look", "Size of legend boxes")
legend_box_size = Key(12, int, "Size of legend boxes")
rounded_bars = Key(
None, int, "Look", "Set this to the desired radius in px")
############ Label ############
x_labels = Key(
None, list,
None, list, "Label",
"X labels, must have same len than data.",
"Leave it to None to disable x labels display.",
str)
y_labels = Key(
None, list,
None, list, "Label",
"You can specify explicit y labels",
"(must be list(int))", int)
"Must be a list of numbers", float)
title = Key(
None, str, "Graph title.", "Leave it to None to disable title.")
x_label_rotation = Key(
0, int, "Label", "Specify x labels rotation angles", "in degrees")
rounded_bars = Key(False, bool, "Set this to the desired radius in px")
y_label_rotation = Key(
0, int, "Label", "Specify y labels rotation angles", "in degrees")
include_x_axis = Key(False, bool, "Always include x axis")
############ Value ############
human_readable = Key(
False, bool, "Value", "Display values in human readable format",
"(ie: 12.4M)")
fill = Key(False, bool, "Fill areas under lines")
stroke = Key(
True, bool, "Line dots (set it to false to get a scatter plot)")
logarithmic = Key(
False, bool, "Value", "Display values in logarithmic scale")
interpolate = Key(
None, str, "Interpolation, this requires scipy module",
None, str, "Value", "Interpolation, this requires scipy module",
"May be any of 'linear', 'nearest', 'zero', 'slinear', 'quadratic,"
"'cubic', 'krogh', 'barycentric', 'univariate',"
"or an integer specifying the order"
"of the spline interpolator")
interpolation_precision = Key(
250, int, "Number of interpolated points between two values")
250, int, "Value", "Number of interpolated points between two values")
order_min = Key(
None, int, "Value", "Minimum order of scale, defaults to None")
range = Key(
None, list, "Explicitly specify min and max of values",
None, list, "Value", "Explicitly specify min and max of values",
"(ie: (0, 100))", int)
include_x_axis = Key(
False, bool, "Value", "Always include x axis")
zero = Key(
0, int, "Set the ordinate zero value", "(for filling)")
0, int, "Value",
"Set the ordinate zero value",
"Useful for filling to another base than abscissa")
############ Text ############
no_data_text = Key(
"No data", str, "Text to display when no data is given")
"No data", str, "Text", "Text to display when no data is given")
label_font_size = Key(10, int, "Text", "Label font size")
value_font_size = Key(8, int, "Text", "Value font size")
tooltip_font_size = Key(20, int, "Text", "Tooltip font size")
title_font_size = Key(16, int, "Text", "Title font size")
legend_font_size = Key(14, int, "Text", "Legend font size")
print_values = Key(
True, bool, "Print values when graph is in non interactive mode")
True, bool,
"Text", "Print values when graph is in non interactive mode")
print_zeroes = Key(
False, bool, "Print zeroes when graph is in non interactive mode")
disable_xml_declaration = Key(
False, bool,
"Don't write xml declaration and return str instead of string",
"usefull for writing output directly in html")
explicit_size = Key(False, bool, "Write width and height attributes")
"Text", "Print zeroes when graph is in non interactive mode")
truncate_legend = Key(
None, int, "Legend string length truncation threshold (None = auto)")
None, int, "Text",
"Legend string length truncation threshold", "None = auto")
truncate_label = Key(
None, int, "Label string length truncation threshold (None = auto)")
None, int, "Text",
"Label string length truncation threshold", "None = auto")
############ Misc ############
js = Key(
('https://raw.github.com/Kozea/pygal.js/master/svg.jquery.js',
'https://raw.github.com/Kozea/pygal.js/master/pygal-tooltips.js'),
list, "Misc", "List of js file",
"It can be a filepath or an external link",
str)
disable_xml_declaration = Key(
False, bool, "Misc",
"Don't write xml declaration and return str instead of string",
"usefull for writing output directly in html")
explicit_size = Key(
False, bool, "Misc", "Write width and height attributes")
pretty_print = Key(False, bool, "Pretty print the svg")
pretty_print = Key(
False, bool, "Misc", "Pretty print the svg")
strict = Key(
False, bool, "If True don't try to adapt / filter wrong values")
False, bool, "Misc",
"If True don't try to adapt / filter wrong values")
def __init__(self, **kwargs):
"""Can be instanciated with config kwargs"""

4
pygal/graph/bar.py

@ -97,8 +97,8 @@ class Bar(Graph):
bar, 'rect',
x=x,
y=y,
rx=self.rounded_bars * 1,
ry=self.rounded_bars * 1,
rx=self.rounded_bars * 1 if self.rounded_bars else 0,
ry=self.rounded_bars * 1 if self.rounded_bars else 0,
width=bar_inner_width,
height=height,
class_='rect reactive tooltip-trigger')

2
pygal/graph/line.py

@ -43,7 +43,7 @@ class Line(Graph):
for serie in self.series
for val in (serie.interpolated
if self.interpolate else serie.points)
if val[1] is not None and (not self.logarithmic or val[1] > 0)]
if val[1] is not None]
def _fill(self, values):
"""Add extra values to fill the line"""

3
pygal/util.py

@ -299,10 +299,11 @@ def prepare_values(raw, config, cls):
if fun in adapters:
adapters.remove(fun)
adapters = [not_zero, positive] + adapters
adapter = reduce(compose, adapters)
adapter = reduce(compose, adapters) if not config.strict else ident
series = []
width = max([len(values) for _, values in raw] +
[len(config.x_labels or [])])
for title, raw_values in raw:
metadata = {}
values = []

Loading…
Cancel
Save