Browse Source

Styles are now all classes and parametric styles are explicit. WIP on new default theme based on material design

pull/242/head
Florian Mounier 10 years ago
parent
commit
579a6f91d5
  1. 21
      demo/moulinrouge/__init__.py
  2. 2
      demo/moulinrouge/templates/index.jinja2
  3. 2
      docs/changelog.rst
  4. 4
      docs/documentation/custom_styles.rst
  5. 4
      docs/ext/pygal_sphinx_directives.py
  6. 5
      pygal/css/base.css
  7. 37
      pygal/css/style.css
  8. 2
      pygal/graph/base.py
  9. 2
      pygal/graph/graph.py
  10. 4
      pygal/graph/time.py
  11. 527
      pygal/style.py
  12. 2
      pygal/util.py

21
demo/moulinrouge/__init__.py

@ -30,6 +30,13 @@ import random
import pickle
def get(type):
from importlib import import_module
module = '.'.join(type.split('.')[:-1])
name = type.split('.')[-1]
return getattr(import_module(module), name)
def random_label():
chars = string.ascii_letters + string.digits + u' àéèçêâäëï'
return ''.join(
@ -98,10 +105,7 @@ def create_app():
@app.route("/svg/<type>/<series>/<config>")
def svg(type, series, config):
module = '.'.join(type.split('.')[:-1])
name = type.split('.')[-1]
from importlib import import_module
graph = getattr(import_module(module), name)(
graph = get(type)(
pickle.loads(b64decode(str(config))))
for title, values in pickle.loads(b64decode(str(series))):
graph.add(title, values)
@ -109,7 +113,7 @@ def create_app():
@app.route("/table/<type>/<series>/<config>")
def table(type, series, config):
graph = getattr(pygal, type)(pickle.loads(b64decode(str(config))))
graph = get(type)(pickle.loads(b64decode(str(config))))
for title, values in pickle.loads(b64decode(str(series))):
graph.add(title, values)
return graph.render_table()
@ -186,6 +190,7 @@ def create_app():
else:
style = parametric_styles[style](
color, base_style=styles[base_style or 'default'])
xy_series = _random(data, order)
other_series = []
for title, values in xy_series:
@ -234,7 +239,7 @@ def create_app():
config.title = "%d rotation" % angle
config.x_labels = labels
config.x_label_rotation = angle
svgs.append({'type': 'Bar',
svgs.append({'type': 'pygal.Bar',
'series': series,
'config': b64encode(pickle.dumps(config))})
@ -258,7 +263,7 @@ def create_app():
for interpolation in 'quadratic', 'cubic', 'lagrange', 'trigonometric':
config.title = "%s interpolation" % interpolation
config.interpolate = interpolation
svgs.append({'type': 'StackedLine',
svgs.append({'type': 'pygal.StackedLine',
'series': series,
'config': b64encode(pickle.dumps(config))})
@ -282,7 +287,7 @@ def create_app():
config.title = "Hermite interpolation with params %r" % params
config.interpolate = 'hermite'
config.interpolation_parameters = params
svgs.append({'type': 'StackedLine',
svgs.append({'type': 'pygal.StackedLine',
'series': series,
'config': b64encode(pickle.dumps(config))})

2
demo/moulinrouge/templates/index.jinja2

@ -43,7 +43,7 @@
<h3>Parametric Styles</h3>
<ul>
{% for color in parametric_colors %}
<li><embed src="{{ url_for('sparkline', style='RotateStyle', color=color) }}" type="image/svg+xml" /></li>
<li><embed src="{{ url_for('sparkline', style='rotate', color=color) }}" type="image/svg+xml" /></li>
{% for style in parametric_styles %}
<li>
<a href="{{ url_for('all', style=style, color=color) }}">{{ style }} for {{ color }}</a>

2
docs/changelog.rst

@ -28,6 +28,8 @@ Changelog
* Remove stroke style in style and set it as a global / serie configuration.
* Fix None values in tables
* Fix timezones in DateTimeLine
* Rename in Style foreground_light as foreground_strong
* Rename in Style foreground_dark as foreground_subtle
1.7.0
=====

4
docs/documentation/custom_styles.rst

@ -16,8 +16,8 @@ You can instantiate the ``Style`` class with some customizations for quick styli
background='transparent',
plot_background='transparent',
foreground='#53E89B',
foreground_light='#53A0E8',
foreground_dark='#630C0D',
foreground_strong='#53A0E8',
foreground_subtle='#630C0D',
opacity='.6',
opacity_hover='.9',
transition='400ms ease-in',

4
docs/ext/pygal_sphinx_directives.py

@ -33,8 +33,8 @@ pygal.config.Config.style.value = pygal.style.RotateStyle(
background='#fcfcfc',
plot_background='#ffffff',
foreground='#707070',
foreground_light='#404040',
foreground_dark='#a0a0a0',
foreground_strong='#404040',
foreground_subtle='#a0a0a0',
opacity='.8',
opacity_hover='.9',
transition='400ms ease-in')

5
pygal/css/base.css

@ -22,6 +22,11 @@
* Font-sizes from config, override with care
*/
{{ id }}.graph {
-webkit-user-select: none;
-webkit-font-smoothing: antialiased;
}
{{ id }}.title {
font-family: {{ style.font_family }};
font-size: {{ font_sizes.title }};

37
pygal/css/style.css

@ -48,11 +48,11 @@
}
{{ id }}text.no_data {
fill: {{ style.foreground_light }};
fill: {{ style.foreground_strong }};
}
{{ id }}.title {
fill: {{ style.foreground_light }};
fill: {{ style.foreground_strong }};
}
{{ id }}.legends .legend text {
@ -60,15 +60,15 @@
}
{{ id }}.legends .legend:hover text {
fill: {{ style.foreground_light }};
fill: {{ style.foreground_strong }};
}
{{ id }}.axis .line {
stroke: {{ style.foreground_light }};
stroke: {{ style.foreground_strong }};
}
{{ id }}.axis .guide.line {
stroke: {{ style.foreground_dark }};
stroke: {{ style.foreground_subtle }};
}
{{ id }}.axis .major.line {
@ -76,18 +76,18 @@
}
{{ id }}.axis text.major {
fill: {{ style.foreground_light }};
fill: {{ style.foreground_strong }};
}
{{ 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 }};
stroke: {{ style.foreground_strong }};
}
{{ id }}.axis .guides:hover text {
fill: {{ style.foreground_light }};
fill: {{ style.foreground_strong }};
}
{{ id }}.reactive {
@ -101,30 +101,29 @@
}
{{ id }}.series text {
fill: {{ style.foreground_light }};
fill: {{ style.foreground_strong }};
}
{{ id }}.tooltip rect {
fill: {{ style.plot_background }};
stroke: {{ style.foreground_light }};
-webkit-transition: opacity 250ms;
-moz-transition: opacity 250ms;
transition: opacity 250ms;
stroke: {{ style.foreground_strong }};
-webkit-transition: opacity {{ style.transition }};
-moz-transition: opacity {{ style.transition }};
transition: opacity {{ style.transition }};
}
{{ id }}.tooltip text {
fill: {{ style.foreground_light }};
fill: {{ style.foreground_strong }};
}
{{ id }}.map-element {
fill: {{ style.foreground }};
stroke: {{ style.foreground_dark }} !important;
stroke: {{ style.foreground_subtle }} !important;
opacity: .9;
stroke-width: 3;
-webkit-transition: 250ms;
-moz-transition: 250ms;
-o-transition: 250ms;
transition: 250ms;
-webkit-transition: opacity {{ style.transition }};
-moz-transition: opacity {{ style.transition }};
transition: opacity {{ style.transition }};
}
{{ id }}.map-element:hover {

2
pygal/graph/base.py

@ -182,6 +182,8 @@ class BaseGraph(object):
if getattr(self, 'y_labels', None) is not None:
self.y_labels = list(self.y_labels)
self.state = State(self, **kwargs)
if isinstance(self.style, type):
self.style = self.style()
self.series = self.prepare_values(
self.raw_series) or []
self.secondary_series = self.prepare_values(

2
pygal/graph/graph.py

@ -732,7 +732,7 @@ class Graph(PublicApi):
return any([
len([v for a in (
s[1] if is_list_like(s) else [s])
for v in (a if self._dual else [a])
for v in (a if is_list_like(a) else [a])
if v is not None])
for s in self.raw_series
])

4
pygal/graph/time.py

@ -69,7 +69,9 @@ def time_to_seconds(x):
return ((
((x.hour * 60) + x.minute) * 60 + x.second
) * 10 ** 6 + x.microsecond) / 10 ** 6
return x
# Clamp to valid time
return max(0, min(x, 24 * 3600 - 10 ** -6))
def seconds_to_time(x):

527
pygal/style.py

@ -22,41 +22,48 @@ from __future__ import division
from pygal.util import cycle_fill
from pygal import colors
from pygal.colors import darken, lighten
import sys
class Style(object):
"""Styling class containing colors for the css generation"""
def __init__(
self,
background='black',
plot_background='#111',
foreground='#999',
foreground_light='#eee',
foreground_dark='#555',
font_family='monospace', # Monospaced font is highly encouraged
opacity='.8',
opacity_hover='.9',
transition='250ms',
colors=(
'#ff5995', '#b6e354', '#feed6c', '#8cedff', '#9e6ffe',
'#899ca1', '#f8f8f2', '#bf4646', '#516083', '#f92672',
'#82b414', '#fd971f', '#56c2d6', '#808384', '#8c54fe',
'#465457')):
plot_background = 'rgba(255, 255, 255, 1)'
background = 'rgba(249, 249, 249, 1)'
foreground = 'rgba(0, 0, 0, .87)'
foreground_strong = 'rgba(0, 0, 0, 1)'
foreground_subtle = 'rgba(0, 0, 0, .54)'
# Monospaced font is highly encouraged
font_family = 'Consolas, "Liberation Mono", Menlo, Courier, '
'monospace'
opacity = '.7'
opacity_hover = '.8'
transition = '150ms'
colors = (
'#F44336', # 0
'#3F51B5', # 4
'#009688', # 8
'#FFC107', # 13
'#FF5722', # 15
'#9C27B0', # 2
'#03A9F4', # 6
'#8BC34A', # 10
'#FF9800', # 14
'#E91E63', # 1
'#2196F3', # 5
'#4CAF50', # 9
'#FFEB3B', # 12
'#673AB7', # 3
'#00BCD4', # 7
'#CDDC39', # 11
'#795548', # 16
'#9E9E9E', # 17
'#607D8B', # 18
)
def __init__(self, **kwargs):
"""Create the style"""
self.background = background
self.plot_background = plot_background
self.foreground = foreground
self.foreground_light = foreground_light
self.foreground_dark = foreground_dark
self.font_family = font_family
self.opacity = opacity
self.opacity_hover = opacity_hover
self.transition = transition
self.colors = colors
self.__dict__.update(kwargs)
def get_colors(self, prefix, len_):
"""Get the css color list"""
@ -86,194 +93,249 @@ class Style(object):
return config
DefaultStyle = Style(opacity_hover='.4', opacity='.8')
DefaultStyle = Style
class DarkStyle(Style):
"""A dark style (old default)"""
background = 'black'
plot_background = '#111'
foreground = '#999'
foreground_strong = '#eee'
foreground_subtle = '#555'
opacity = '.8'
opacity_hover = '.4'
transition = '250ms'
colors = (
'#ff5995', '#b6e354', '#feed6c', '#8cedff', '#9e6ffe',
'#899ca1', '#f8f8f2', '#bf4646', '#516083', '#f92672',
'#82b414', '#fd971f', '#56c2d6', '#808384', '#8c54fe',
'#465457')
LightStyle = Style(
background='white',
plot_background='rgba(0, 0, 255, 0.1)',
foreground='rgba(0, 0, 0, 0.7)',
foreground_light='rgba(0, 0, 0, 0.9)',
foreground_dark='rgba(0, 0, 0, 0.5)',
colors=('#242424', '#9f6767', '#92ac68',
class LightStyle(Style):
"""A light style"""
background = 'white'
plot_background = 'rgba(0, 0, 255, 0.1)'
foreground = 'rgba(0, 0, 0, 0.7)'
foreground_strong = 'rgba(0, 0, 0, 0.9)'
foreground_subtle = 'rgba(0, 0, 0, 0.5)'
colors = ('#242424', '#9f6767', '#92ac68',
'#d0d293', '#9aacc3', '#bb77a4',
'#77bbb5', '#777777'))
'#77bbb5', '#777777')
class NeonStyle(DarkStyle):
"""Similar to DarkStyle but with more opacity and effects"""
opacity = '.1'
opacity_hover = '.75'
transition = '1s ease-out'
NeonStyle = Style(
opacity='.1',
opacity_hover='.75',
transition='1s ease-out')
class CleanStyle(Style):
CleanStyle = Style(
background='transparent',
plot_background='rgba(240, 240, 240, 0.7)',
foreground='rgba(0, 0, 0, 0.9)',
foreground_light='rgba(0, 0, 0, 0.9)',
foreground_dark='rgba(0, 0, 0, 0.5)',
colors=(
"""A rather clean style"""
background = 'transparent'
plot_background = 'rgba(240, 240, 240, 0.7)'
foreground = 'rgba(0, 0, 0, 0.9)'
foreground_strong = 'rgba(0, 0, 0, 0.9)'
foreground_subtle = 'rgba(0, 0, 0, 0.5)'
colors = (
'rgb(12,55,149)', 'rgb(117,38,65)', 'rgb(228,127,0)', 'rgb(159,170,0)',
'rgb(149,12,12)'))
'rgb(149,12,12)')
class DarkSolarizedStyle(Style):
"""Dark solarized popular theme"""
solarized_colors = (
background = '#073642'
plot_background = '#002b36'
foreground = '#839496'
foreground_strong = '#fdf6e3'
foreground_subtle = '#657b83'
opacity = '.66'
opacity_hover = '.9'
transition = '500ms ease-in'
colors = (
'#b58900', '#cb4b16', '#dc322f', '#d33682',
'#6c71c4', '#268bd2', '#2aa198', '#859900')
DarkSolarizedStyle = Style(
background='#073642',
plot_background='#002b36',
foreground='#839496',
foreground_light='#fdf6e3',
foreground_dark='#657b83',
opacity='.66',
opacity_hover='.9',
transition='500ms ease-in',
colors=solarized_colors)
LightSolarizedStyle = Style(
background='#fdf6e3',
plot_background='#eee8d5',
foreground='#657b83',
foreground_light='#073642',
foreground_dark='#073642',
opacity='.6',
opacity_hover='.9',
transition='500ms ease-in',
colors=solarized_colors)
RedBlueStyle = Style(
background=lighten('#e6e7e9', 7),
plot_background=lighten('#e6e7e9', 10),
foreground='rgba(0, 0, 0, 0.9)',
foreground_light='rgba(0, 0, 0, 0.9)',
foreground_dark='rgba(0, 0, 0, 0.5)',
opacity='.6',
opacity_hover='.9',
colors=(
class LightSolarizedStyle(DarkSolarizedStyle):
"""Light solarized popular theme"""
background = '#fdf6e3'
plot_background = '#eee8d5'
foreground = '#657b83'
foreground_strong = '#073642'
foreground_subtle = '#073642'
class RedBlueStyle(Style):
"""A red and blue theme"""
background = lighten('#e6e7e9', 7)
plot_background = lighten('#e6e7e9', 10)
foreground = 'rgba(0, 0, 0, 0.9)'
foreground_strong = 'rgba(0, 0, 0, 0.9)'
foreground_subtle = 'rgba(0, 0, 0, 0.5)'
opacity = '.6'
opacity_hover = '.9'
colors = (
'#d94e4c', '#e5884f', '#39929a',
lighten('#d94e4c', 10), darken('#39929a', 15), lighten('#e5884f', 17),
darken('#d94e4c', 10), '#234547'))
LightColorizedStyle = Style(
background='#f8f8f8',
plot_background=lighten('#f8f8f8', 3),
foreground='#333',
foreground_light='#666',
foreground_dark='rgba(0, 0 , 0, 0.5)',
opacity='.5',
opacity_hover='.9',
transition='250ms ease-in',
colors=(
darken('#d94e4c', 10), '#234547')
class LightColorizedStyle(Style):
"""A light colorized style"""
background = '#f8f8f8'
plot_background = lighten('#f8f8f8', 3)
foreground = '#333'
foreground_strong = '#666'
foreground_subtle = 'rgba(0, 0 , 0, 0.5)'
opacity = '.5'
opacity_hover = '.9'
transition = '250ms ease-in'
colors = (
'#fe9592', '#534f4c', '#3ac2c0', '#a2a7a1',
darken('#fe9592', 15), lighten('#534f4c', 15), lighten('#3ac2c0', 15),
lighten('#a2a7a1', 15), lighten('#fe9592', 15), darken('#3ac2c0', 10)))
DarkColorizedStyle = Style(
background=darken('#3a2d3f', 5),
plot_background=lighten('#3a2d3f', 2),
foreground='rgba(255, 255, 255, 0.9)',
foreground_light='rgba(255, 255, 255, 0.9)',
foreground_dark='rgba(255, 255 , 255, 0.5)',
opacity='.2',
opacity_hover='.7',
transition='250ms ease-in',
colors=(
lighten('#a2a7a1', 15), lighten('#fe9592', 15), darken('#3ac2c0', 10))
class DarkColorizedStyle(Style):
"""A dark colorized style"""
background = darken('#3a2d3f', 5)
plot_background = lighten('#3a2d3f', 2)
foreground = 'rgba(255, 255, 255, 0.9)'
foreground_strong = 'rgba(255, 255, 255, 0.9)'
foreground_subtle = 'rgba(255, 255 , 255, 0.5)'
opacity = '.2'
opacity_hover = '.7'
transition = '250ms ease-in'
colors = (
'#c900fe', '#01b8fe', '#59f500', '#ff00e4', '#f9fa00',
darken('#c900fe', 20), darken('#01b8fe', 15), darken('#59f500', 20),
darken('#ff00e4', 15), lighten('#f9fa00', 20)))
TurquoiseStyle = Style(
background=darken('#1b8088', 15),
plot_background=darken('#1b8088', 17),
foreground='rgba(255, 255, 255, 0.9)',
foreground_light='rgba(255, 255, 255, 0.9)',
foreground_dark='rgba(255, 255 , 255, 0.5)',
opacity='.5',
opacity_hover='.9',
transition='250ms ease-in',
colors=(
darken('#ff00e4', 15), lighten('#f9fa00', 20))
class TurquoiseStyle(Style):
"""A turquoise style"""
background = darken('#1b8088', 15)
plot_background = darken('#1b8088', 17)
foreground = 'rgba(255, 255, 255, 0.9)'
foreground_strong = 'rgba(255, 255, 255, 0.9)'
foreground_subtle = 'rgba(255, 255 , 255, 0.5)'
opacity = '.5'
opacity_hover = '.9'
transition = '250ms ease-in'
colors = (
'#93d2d9', '#ef940f', '#8C6243', '#fff',
darken('#93d2d9', 20), lighten('#ef940f', 15),
lighten('#8c6243', 15), '#1b8088'))
LightGreenStyle = Style(
background=lighten('#f3f3f3', 3),
plot_background='#fff',
foreground='#333333',
foreground_light='#666',
foreground_dark='#222222',
opacity='.5',
opacity_hover='.9',
transition='250ms ease-in',
colors=(
lighten('#8c6243', 15), '#1b8088')
class LightGreenStyle(Style):
"""A light green style"""
background = lighten('#f3f3f3', 3)
plot_background = '#fff'
foreground = '#333333'
foreground_strong = '#666'
foreground_subtle = '#222222'
opacity = '.5'
opacity_hover = '.9'
transition = '250ms ease-in'
colors = (
'#7dcf30', '#247fab', lighten('#7dcf30', 10), '#ccc',
darken('#7dcf30', 15), '#ddd', lighten('#247fab', 10),
darken('#247fab', 15)))
DarkGreenStyle = Style(
background=darken('#251e01', 3),
plot_background=darken('#251e01', 1),
foreground='rgba(255, 255, 255, 0.9)',
foreground_light='rgba(255, 255, 255, 0.9)',
foreground_dark='rgba(255, 255, 255, 0.6)',
opacity='.6',
opacity_hover='.9',
transition='250ms ease-in',
colors=(
darken('#247fab', 15))
class DarkGreenStyle(Style):
"""A dark green style"""
background = darken('#251e01', 3)
plot_background = darken('#251e01', 1)
foreground = 'rgba(255, 255, 255, 0.9)'
foreground_strong = 'rgba(255, 255, 255, 0.9)'
foreground_subtle = 'rgba(255, 255, 255, 0.6)'
opacity = '.6'
opacity_hover = '.9'
transition = '250ms ease-in'
colors = (
'#adde09', '#6e8c06', '#4a5e04', '#fcd202', '#C1E34D',
lighten('#fcd202', 25)))
DarkGreenBlueStyle = Style(
background='#000',
plot_background=lighten('#000', 8),
foreground='rgba(255, 255, 255, 0.9)',
foreground_light='rgba(255, 255, 255, 0.9)',
foreground_dark='rgba(255, 255, 255, 0.6)',
opacity='.55',
opacity_hover='.9',
transition='250ms ease-in',
colors=(lighten('#34B8F7', 15), '#7dcf30', '#247fab',
lighten('#fcd202', 25))
class DarkGreenBlueStyle(Style):
"""A dark green and blue style"""
background = '#000'
plot_background = lighten('#000', 8)
foreground = 'rgba(255, 255, 255, 0.9)'
foreground_strong = 'rgba(255, 255, 255, 0.9)'
foreground_subtle = 'rgba(255, 255, 255, 0.6)'
opacity = '.55'
opacity_hover = '.9'
transition = '250ms ease-in'
colors = (lighten('#34B8F7', 15), '#7dcf30', '#247fab',
darken('#7dcf30', 10), lighten('#247fab', 10),
lighten('#7dcf30', 10), darken('#247fab', 10), '#fff'))
BlueStyle = Style(
background=darken('#f8f8f8', 3),
plot_background='#f8f8f8',
foreground='rgba(0, 0, 0, 0.9)',
foreground_light='rgba(0, 0, 0, 0.9)',
foreground_dark='rgba(0, 0, 0, 0.6)',
opacity='.5',
opacity_hover='.9',
transition='250ms ease-in',
colors=(
lighten('#7dcf30', 10), darken('#247fab', 10), '#fff')
class BlueStyle(Style):
"""A blue style"""
background = darken('#f8f8f8', 3)
plot_background = '#f8f8f8'
foreground = 'rgba(0, 0, 0, 0.9)'
foreground_strong = 'rgba(0, 0, 0, 0.9)'
foreground_subtle = 'rgba(0, 0, 0, 0.6)'
opacity = '.5'
opacity_hover = '.9'
transition = '250ms ease-in'
colors = (
'#00b2f0', '#43d9be', '#0662ab', darken('#00b2f0', 20),
lighten('#43d9be', 20), lighten('#7dcf30', 10), darken('#0662ab', 15),
'#ffd541', '#7dcf30', lighten('#00b2f0', 15), darken('#ffd541', 20)))
'#ffd541', '#7dcf30', lighten('#00b2f0', 15), darken('#ffd541', 20))
SolidColorStyle = Style(
background='#FFFFFF',
plot_background='#FFFFFF',
foreground='#000000',
foreground_light='#000000',
foreground_dark='#828282',
opacity='.8',
opacity_hover='.9',
transition='400ms ease-in',
colors=('#FF9900', '#DC3912', '#4674D1', '#109618', '#990099',
'#0099C6', '#DD4477', '#74B217', '#B82E2E', '#316395', '#994499'))
class SolidColorStyle(Style):
"""A light style with strong colors"""
background = '#FFFFFF'
plot_background = '#FFFFFF'
foreground = '#000000'
foreground_strong = '#000000'
foreground_subtle = '#828282'
opacity = '.8'
opacity_hover = '.9'
transition = '400ms ease-in'
colors = (
'#FF9900', '#DC3912', '#4674D1', '#109618', '#990099',
'#0099C6', '#DD4477', '#74B217', '#B82E2E', '#316395', '#994499')
styles = {'default': DefaultStyle,
@ -293,21 +355,16 @@ styles = {'default': DefaultStyle,
'solid_color': SolidColorStyle}
parametric_styles = {}
for op in ('lighten', 'darken', 'saturate', 'desaturate', 'rotate'):
name = op.capitalize() + 'Style'
class ParametricStyleBase(Style):
def get_style_for(op_name):
"""
Return a callable that returns a Style instance
for the given operation
"""
operation = getattr(colors, op_name)
"""Parametric Style base class for all the parametric operations"""
_op = None
def parametric_style(color, step=10, max_=None, base_style=None,
**kwargs):
def __init__(self, color, step=10, max_=None, base_style=None, **kwargs):
"""
Generate a parametric Style instance of the parametric operation
Initialization of the parametric style.
This takes several parameters:
* a `step` which correspond on how many colors will be needed
* a `max_` which defines the maximum amplitude of the color effect
@ -315,6 +372,19 @@ for op in ('lighten', 'darken', 'saturate', 'desaturate', 'rotate'):
except colors
* any keyword arguments setting other style parameters
"""
if self._op is None:
raise RuntimeError('ParametricStyle is not instanciable')
defaults = {}
if base_style is not None:
if isinstance(base_style, type):
base_style = base_style()
defaults.update(base_style.to_dict())
defaults.update(kwargs)
super(ParametricStyleBase, self).__init__(**defaults)
if max_ is None:
violency = {
'darken': 50,
@ -323,25 +393,54 @@ for op in ('lighten', 'darken', 'saturate', 'desaturate', 'rotate'):
'desaturate': 100,
'rotate': 360
}
max__ = violency[op_name]
else:
max__ = max_
max_ = violency[self._op]
def modifier(index):
percent = max__ * index / (step - 1)
return operation(color, percent)
percent = max_ * index / (step - 1)
return getattr(colors, self._op)(color, percent)
self.colors = list(map(modifier, range(0, max(2, step))))
class LightenStyle(ParametricStyleBase):
"""Create a style by lightening the given color"""
_op = 'lighten'
class DarkenStyle(ParametricStyleBase):
"""Create a style by darkening the given color"""
_op = 'darken'
class SaturateStyle(ParametricStyleBase):
"""Create a style by saturating the given color"""
_op = 'saturate'
class DesaturateStyle(ParametricStyleBase):
"""Create a style by desaturating the given color"""
_op = 'desaturate'
class RotateStyle(ParametricStyleBase):
colors = list(map(modifier, range(0, max(2, step))))
"""Create a style by rotating the given color"""
if base_style is None:
return Style(colors=colors, **kwargs)
opts = dict(base_style.__dict__)
opts.update({'colors': colors})
opts.update(kwargs)
return Style(**opts)
_op = 'rotate'
return parametric_style
style = get_style_for(op)
parametric_styles[name] = style
setattr(sys.modules[__name__], name, style)
parametric_styles = {
'lighten': LightenStyle,
'darken': DarkenStyle,
'saturate': SaturateStyle,
'desaturate': DesaturateStyle,
'rotate': RotateStyle
}

2
pygal/util.py

@ -37,6 +37,8 @@ def humanize(number):
"""Format a number to engineer scale"""
if is_list_like(number):
return', '.join(map(humanize, number))
if number is None:
return u('')
order = number and int(floor(log(abs(number)) / log(1000)))
human_readable = ORDERS.split(" ")[int(order > 0)]
if order == 0 or order > len(human_readable):

Loading…
Cancel
Save