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

2
demo/moulinrouge/templates/index.jinja2

@ -43,7 +43,7 @@
<h3>Parametric Styles</h3> <h3>Parametric Styles</h3>
<ul> <ul>
{% for color in parametric_colors %} {% 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 %} {% for style in parametric_styles %}
<li> <li>
<a href="{{ url_for('all', style=style, color=color) }}">{{ style }} for {{ color }}</a> <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. * Remove stroke style in style and set it as a global / serie configuration.
* Fix None values in tables * Fix None values in tables
* Fix timezones in DateTimeLine * Fix timezones in DateTimeLine
* Rename in Style foreground_light as foreground_strong
* Rename in Style foreground_dark as foreground_subtle
1.7.0 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', background='transparent',
plot_background='transparent', plot_background='transparent',
foreground='#53E89B', foreground='#53E89B',
foreground_light='#53A0E8', foreground_strong='#53A0E8',
foreground_dark='#630C0D', foreground_subtle='#630C0D',
opacity='.6', opacity='.6',
opacity_hover='.9', opacity_hover='.9',
transition='400ms ease-in', 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', background='#fcfcfc',
plot_background='#ffffff', plot_background='#ffffff',
foreground='#707070', foreground='#707070',
foreground_light='#404040', foreground_strong='#404040',
foreground_dark='#a0a0a0', foreground_subtle='#a0a0a0',
opacity='.8', opacity='.8',
opacity_hover='.9', opacity_hover='.9',
transition='400ms ease-in') transition='400ms ease-in')

5
pygal/css/base.css

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

37
pygal/css/style.css

@ -48,11 +48,11 @@
} }
{{ id }}text.no_data { {{ id }}text.no_data {
fill: {{ style.foreground_light }}; fill: {{ style.foreground_strong }};
} }
{{ id }}.title { {{ id }}.title {
fill: {{ style.foreground_light }}; fill: {{ style.foreground_strong }};
} }
{{ id }}.legends .legend text { {{ id }}.legends .legend text {
@ -60,15 +60,15 @@
} }
{{ id }}.legends .legend:hover text { {{ id }}.legends .legend:hover text {
fill: {{ style.foreground_light }}; fill: {{ style.foreground_strong }};
} }
{{ id }}.axis .line { {{ id }}.axis .line {
stroke: {{ style.foreground_light }}; stroke: {{ style.foreground_strong }};
} }
{{ id }}.axis .guide.line { {{ id }}.axis .guide.line {
stroke: {{ style.foreground_dark }}; stroke: {{ style.foreground_subtle }};
} }
{{ id }}.axis .major.line { {{ id }}.axis .major.line {
@ -76,18 +76,18 @@
} }
{{ id }}.axis text.major { {{ id }}.axis text.major {
fill: {{ style.foreground_light }}; fill: {{ style.foreground_strong }};
} }
{{ id }}.axis.y .guides:hover .guide.line, {{ id }}.axis.y .guides:hover .guide.line,
{{ id }}.line-graph .axis.x .guides:hover .guide.line, {{ id }}.line-graph .axis.x .guides:hover .guide.line,
{{ id }}.stackedline-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 { {{ id }}.xy-graph .axis.x .guides:hover .guide.line {
stroke: {{ style.foreground_light }}; stroke: {{ style.foreground_strong }};
} }
{{ id }}.axis .guides:hover text { {{ id }}.axis .guides:hover text {
fill: {{ style.foreground_light }}; fill: {{ style.foreground_strong }};
} }
{{ id }}.reactive { {{ id }}.reactive {
@ -101,30 +101,29 @@
} }
{{ id }}.series text { {{ id }}.series text {
fill: {{ style.foreground_light }}; fill: {{ style.foreground_strong }};
} }
{{ id }}.tooltip rect { {{ id }}.tooltip rect {
fill: {{ style.plot_background }}; fill: {{ style.plot_background }};
stroke: {{ style.foreground_light }}; stroke: {{ style.foreground_strong }};
-webkit-transition: opacity 250ms; -webkit-transition: opacity {{ style.transition }};
-moz-transition: opacity 250ms; -moz-transition: opacity {{ style.transition }};
transition: opacity 250ms; transition: opacity {{ style.transition }};
} }
{{ id }}.tooltip text { {{ id }}.tooltip text {
fill: {{ style.foreground_light }}; fill: {{ style.foreground_strong }};
} }
{{ id }}.map-element { {{ id }}.map-element {
fill: {{ style.foreground }}; fill: {{ style.foreground }};
stroke: {{ style.foreground_dark }} !important; stroke: {{ style.foreground_subtle }} !important;
opacity: .9; opacity: .9;
stroke-width: 3; stroke-width: 3;
-webkit-transition: 250ms; -webkit-transition: opacity {{ style.transition }};
-moz-transition: 250ms; -moz-transition: opacity {{ style.transition }};
-o-transition: 250ms; transition: opacity {{ style.transition }};
transition: 250ms;
} }
{{ id }}.map-element:hover { {{ 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: if getattr(self, 'y_labels', None) is not None:
self.y_labels = list(self.y_labels) self.y_labels = list(self.y_labels)
self.state = State(self, **kwargs) self.state = State(self, **kwargs)
if isinstance(self.style, type):
self.style = self.style()
self.series = self.prepare_values( self.series = self.prepare_values(
self.raw_series) or [] self.raw_series) or []
self.secondary_series = self.prepare_values( self.secondary_series = self.prepare_values(

2
pygal/graph/graph.py

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

4
pygal/graph/time.py

@ -69,7 +69,9 @@ def time_to_seconds(x):
return (( return ((
((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
return x
# Clamp to valid time
return max(0, min(x, 24 * 3600 - 10 ** -6))
def seconds_to_time(x): 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.util import cycle_fill
from pygal import colors from pygal import colors
from pygal.colors import darken, lighten from pygal.colors import darken, lighten
import sys
class Style(object): class Style(object):
"""Styling class containing colors for the css generation""" """Styling class containing colors for the css generation"""
def __init__( plot_background = 'rgba(255, 255, 255, 1)'
self, background = 'rgba(249, 249, 249, 1)'
background='black', foreground = 'rgba(0, 0, 0, .87)'
plot_background='#111', foreground_strong = 'rgba(0, 0, 0, 1)'
foreground='#999', foreground_subtle = 'rgba(0, 0, 0, .54)'
foreground_light='#eee', # Monospaced font is highly encouraged
foreground_dark='#555', font_family = 'Consolas, "Liberation Mono", Menlo, Courier, '
font_family='monospace', # Monospaced font is highly encouraged 'monospace'
opacity='.8', opacity = '.7'
opacity_hover='.9', opacity_hover = '.8'
transition='250ms', transition = '150ms'
colors=( colors = (
'#ff5995', '#b6e354', '#feed6c', '#8cedff', '#9e6ffe', '#F44336', # 0
'#3F51B5', # 4
'#899ca1', '#f8f8f2', '#bf4646', '#516083', '#f92672', '#009688', # 8
'#82b414', '#fd971f', '#56c2d6', '#808384', '#8c54fe', '#FFC107', # 13
'#465457')): '#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""" """Create the style"""
self.background = background self.__dict__.update(kwargs)
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
def get_colors(self, prefix, len_): def get_colors(self, prefix, len_):
"""Get the css color list""" """Get the css color list"""
@ -86,194 +93,249 @@ class Style(object):
return config 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( class LightStyle(Style):
background='white',
plot_background='rgba(0, 0, 255, 0.1)', """A light style"""
foreground='rgba(0, 0, 0, 0.7)',
foreground_light='rgba(0, 0, 0, 0.9)', background = 'white'
foreground_dark='rgba(0, 0, 0, 0.5)', plot_background = 'rgba(0, 0, 255, 0.1)'
colors=('#242424', '#9f6767', '#92ac68', 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', '#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( """A rather clean style"""
background='transparent',
plot_background='rgba(240, 240, 240, 0.7)', background = 'transparent'
foreground='rgba(0, 0, 0, 0.9)', plot_background = 'rgba(240, 240, 240, 0.7)'
foreground_light='rgba(0, 0, 0, 0.9)', foreground = 'rgba(0, 0, 0, 0.9)'
foreground_dark='rgba(0, 0, 0, 0.5)', foreground_strong = 'rgba(0, 0, 0, 0.9)'
colors=( 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(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', '#b58900', '#cb4b16', '#dc322f', '#d33682',
'#6c71c4', '#268bd2', '#2aa198', '#859900') '#6c71c4', '#268bd2', '#2aa198', '#859900')
DarkSolarizedStyle = Style( class LightSolarizedStyle(DarkSolarizedStyle):
background='#073642',
plot_background='#002b36', """Light solarized popular theme"""
foreground='#839496',
foreground_light='#fdf6e3', background = '#fdf6e3'
foreground_dark='#657b83', plot_background = '#eee8d5'
opacity='.66', foreground = '#657b83'
opacity_hover='.9', foreground_strong = '#073642'
transition='500ms ease-in', foreground_subtle = '#073642'
colors=solarized_colors)
class RedBlueStyle(Style):
LightSolarizedStyle = Style(
background='#fdf6e3', """A red and blue theme"""
plot_background='#eee8d5',
foreground='#657b83', background = lighten('#e6e7e9', 7)
foreground_light='#073642', plot_background = lighten('#e6e7e9', 10)
foreground_dark='#073642', foreground = 'rgba(0, 0, 0, 0.9)'
opacity='.6', foreground_strong = 'rgba(0, 0, 0, 0.9)'
opacity_hover='.9', foreground_subtle = 'rgba(0, 0, 0, 0.5)'
transition='500ms ease-in', opacity = '.6'
colors=solarized_colors) opacity_hover = '.9'
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=(
'#d94e4c', '#e5884f', '#39929a', '#d94e4c', '#e5884f', '#39929a',
lighten('#d94e4c', 10), darken('#39929a', 15), lighten('#e5884f', 17), lighten('#d94e4c', 10), darken('#39929a', 15), lighten('#e5884f', 17),
darken('#d94e4c', 10), '#234547')) darken('#d94e4c', 10), '#234547')
LightColorizedStyle = Style( class LightColorizedStyle(Style):
background='#f8f8f8',
plot_background=lighten('#f8f8f8', 3), """A light colorized style"""
foreground='#333',
foreground_light='#666', background = '#f8f8f8'
foreground_dark='rgba(0, 0 , 0, 0.5)', plot_background = lighten('#f8f8f8', 3)
opacity='.5', foreground = '#333'
opacity_hover='.9', foreground_strong = '#666'
transition='250ms ease-in', foreground_subtle = 'rgba(0, 0 , 0, 0.5)'
colors=( opacity = '.5'
opacity_hover = '.9'
transition = '250ms ease-in'
colors = (
'#fe9592', '#534f4c', '#3ac2c0', '#a2a7a1', '#fe9592', '#534f4c', '#3ac2c0', '#a2a7a1',
darken('#fe9592', 15), lighten('#534f4c', 15), lighten('#3ac2c0', 15), darken('#fe9592', 15), lighten('#534f4c', 15), lighten('#3ac2c0', 15),
lighten('#a2a7a1', 15), lighten('#fe9592', 15), darken('#3ac2c0', 10))) lighten('#a2a7a1', 15), lighten('#fe9592', 15), darken('#3ac2c0', 10))
DarkColorizedStyle = Style( class DarkColorizedStyle(Style):
background=darken('#3a2d3f', 5),
plot_background=lighten('#3a2d3f', 2), """A dark colorized style"""
foreground='rgba(255, 255, 255, 0.9)',
foreground_light='rgba(255, 255, 255, 0.9)', background = darken('#3a2d3f', 5)
foreground_dark='rgba(255, 255 , 255, 0.5)', plot_background = lighten('#3a2d3f', 2)
opacity='.2', foreground = 'rgba(255, 255, 255, 0.9)'
opacity_hover='.7', foreground_strong = 'rgba(255, 255, 255, 0.9)'
transition='250ms ease-in', foreground_subtle = 'rgba(255, 255 , 255, 0.5)'
colors=( opacity = '.2'
opacity_hover = '.7'
transition = '250ms ease-in'
colors = (
'#c900fe', '#01b8fe', '#59f500', '#ff00e4', '#f9fa00', '#c900fe', '#01b8fe', '#59f500', '#ff00e4', '#f9fa00',
darken('#c900fe', 20), darken('#01b8fe', 15), darken('#59f500', 20), darken('#c900fe', 20), darken('#01b8fe', 15), darken('#59f500', 20),
darken('#ff00e4', 15), lighten('#f9fa00', 20))) darken('#ff00e4', 15), lighten('#f9fa00', 20))
TurquoiseStyle = Style( class TurquoiseStyle(Style):
background=darken('#1b8088', 15),
plot_background=darken('#1b8088', 17), """A turquoise style"""
foreground='rgba(255, 255, 255, 0.9)',
foreground_light='rgba(255, 255, 255, 0.9)', background = darken('#1b8088', 15)
foreground_dark='rgba(255, 255 , 255, 0.5)', plot_background = darken('#1b8088', 17)
opacity='.5', foreground = 'rgba(255, 255, 255, 0.9)'
opacity_hover='.9', foreground_strong = 'rgba(255, 255, 255, 0.9)'
transition='250ms ease-in', foreground_subtle = 'rgba(255, 255 , 255, 0.5)'
colors=( opacity = '.5'
opacity_hover = '.9'
transition = '250ms ease-in'
colors = (
'#93d2d9', '#ef940f', '#8C6243', '#fff', '#93d2d9', '#ef940f', '#8C6243', '#fff',
darken('#93d2d9', 20), lighten('#ef940f', 15), darken('#93d2d9', 20), lighten('#ef940f', 15),
lighten('#8c6243', 15), '#1b8088')) lighten('#8c6243', 15), '#1b8088')
LightGreenStyle = Style( class LightGreenStyle(Style):
background=lighten('#f3f3f3', 3),
plot_background='#fff', """A light green style"""
foreground='#333333',
foreground_light='#666', background = lighten('#f3f3f3', 3)
foreground_dark='#222222', plot_background = '#fff'
opacity='.5', foreground = '#333333'
opacity_hover='.9', foreground_strong = '#666'
transition='250ms ease-in', foreground_subtle = '#222222'
colors=( opacity = '.5'
opacity_hover = '.9'
transition = '250ms ease-in'
colors = (
'#7dcf30', '#247fab', lighten('#7dcf30', 10), '#ccc', '#7dcf30', '#247fab', lighten('#7dcf30', 10), '#ccc',
darken('#7dcf30', 15), '#ddd', lighten('#247fab', 10), darken('#7dcf30', 15), '#ddd', lighten('#247fab', 10),
darken('#247fab', 15))) darken('#247fab', 15))
DarkGreenStyle = Style( class DarkGreenStyle(Style):
background=darken('#251e01', 3),
plot_background=darken('#251e01', 1), """A dark green style"""
foreground='rgba(255, 255, 255, 0.9)',
foreground_light='rgba(255, 255, 255, 0.9)', background = darken('#251e01', 3)
foreground_dark='rgba(255, 255, 255, 0.6)', plot_background = darken('#251e01', 1)
opacity='.6', foreground = 'rgba(255, 255, 255, 0.9)'
opacity_hover='.9', foreground_strong = 'rgba(255, 255, 255, 0.9)'
transition='250ms ease-in', foreground_subtle = 'rgba(255, 255, 255, 0.6)'
colors=( opacity = '.6'
opacity_hover = '.9'
transition = '250ms ease-in'
colors = (
'#adde09', '#6e8c06', '#4a5e04', '#fcd202', '#C1E34D', '#adde09', '#6e8c06', '#4a5e04', '#fcd202', '#C1E34D',
lighten('#fcd202', 25))) lighten('#fcd202', 25))
DarkGreenBlueStyle = Style( class DarkGreenBlueStyle(Style):
background='#000',
plot_background=lighten('#000', 8), """A dark green and blue style"""
foreground='rgba(255, 255, 255, 0.9)',
foreground_light='rgba(255, 255, 255, 0.9)', background = '#000'
foreground_dark='rgba(255, 255, 255, 0.6)', plot_background = lighten('#000', 8)
opacity='.55', foreground = 'rgba(255, 255, 255, 0.9)'
opacity_hover='.9', foreground_strong = 'rgba(255, 255, 255, 0.9)'
transition='250ms ease-in', foreground_subtle = 'rgba(255, 255, 255, 0.6)'
colors=(lighten('#34B8F7', 15), '#7dcf30', '#247fab', opacity = '.55'
opacity_hover = '.9'
transition = '250ms ease-in'
colors = (lighten('#34B8F7', 15), '#7dcf30', '#247fab',
darken('#7dcf30', 10), lighten('#247fab', 10), darken('#7dcf30', 10), lighten('#247fab', 10),
lighten('#7dcf30', 10), darken('#247fab', 10), '#fff')) lighten('#7dcf30', 10), darken('#247fab', 10), '#fff')
BlueStyle = Style( class BlueStyle(Style):
background=darken('#f8f8f8', 3),
plot_background='#f8f8f8', """A blue style"""
foreground='rgba(0, 0, 0, 0.9)',
foreground_light='rgba(0, 0, 0, 0.9)', background = darken('#f8f8f8', 3)
foreground_dark='rgba(0, 0, 0, 0.6)', plot_background = '#f8f8f8'
opacity='.5', foreground = 'rgba(0, 0, 0, 0.9)'
opacity_hover='.9', foreground_strong = 'rgba(0, 0, 0, 0.9)'
transition='250ms ease-in', foreground_subtle = 'rgba(0, 0, 0, 0.6)'
colors=( opacity = '.5'
opacity_hover = '.9'
transition = '250ms ease-in'
colors = (
'#00b2f0', '#43d9be', '#0662ab', darken('#00b2f0', 20), '#00b2f0', '#43d9be', '#0662ab', darken('#00b2f0', 20),
lighten('#43d9be', 20), lighten('#7dcf30', 10), darken('#0662ab', 15), 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( class SolidColorStyle(Style):
background='#FFFFFF',
plot_background='#FFFFFF', """A light style with strong colors"""
foreground='#000000',
foreground_light='#000000', background = '#FFFFFF'
foreground_dark='#828282', plot_background = '#FFFFFF'
opacity='.8', foreground = '#000000'
opacity_hover='.9', foreground_strong = '#000000'
transition='400ms ease-in', foreground_subtle = '#828282'
colors=('#FF9900', '#DC3912', '#4674D1', '#109618', '#990099', opacity = '.8'
'#0099C6', '#DD4477', '#74B217', '#B82E2E', '#316395', '#994499')) opacity_hover = '.9'
transition = '400ms ease-in'
colors = (
'#FF9900', '#DC3912', '#4674D1', '#109618', '#990099',
'#0099C6', '#DD4477', '#74B217', '#B82E2E', '#316395', '#994499')
styles = {'default': DefaultStyle, styles = {'default': DefaultStyle,
@ -293,21 +355,16 @@ styles = {'default': DefaultStyle,
'solid_color': SolidColorStyle} 'solid_color': SolidColorStyle}
parametric_styles = {} class ParametricStyleBase(Style):
for op in ('lighten', 'darken', 'saturate', 'desaturate', 'rotate'):
name = op.capitalize() + 'Style'
def get_style_for(op_name): """Parametric Style base class for all the parametric operations"""
"""
Return a callable that returns a Style instance _op = None
for the given operation
"""
operation = getattr(colors, op_name)
def parametric_style(color, step=10, max_=None, base_style=None, def __init__(self, color, step=10, max_=None, base_style=None, **kwargs):
**kwargs):
""" """
Generate a parametric Style instance of the parametric operation Initialization of the parametric style.
This takes several parameters: This takes several parameters:
* a `step` which correspond on how many colors will be needed * a `step` which correspond on how many colors will be needed
* a `max_` which defines the maximum amplitude of the color effect * 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 except colors
* any keyword arguments setting other style parameters * 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: if max_ is None:
violency = { violency = {
'darken': 50, 'darken': 50,
@ -323,25 +393,54 @@ for op in ('lighten', 'darken', 'saturate', 'desaturate', 'rotate'):
'desaturate': 100, 'desaturate': 100,
'rotate': 360 'rotate': 360
} }
max__ = violency[op_name] max_ = violency[self._op]
else:
max__ = max_
def modifier(index): def modifier(index):
percent = max__ * index / (step - 1) percent = max_ * index / (step - 1)
return operation(color, percent) 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: _op = 'rotate'
return Style(colors=colors, **kwargs)
opts = dict(base_style.__dict__)
opts.update({'colors': colors})
opts.update(kwargs)
return Style(**opts)
return parametric_style
style = get_style_for(op) parametric_styles = {
parametric_styles[name] = style 'lighten': LightenStyle,
setattr(sys.modules[__name__], name, style) '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""" """Format a number to engineer scale"""
if is_list_like(number): if is_list_like(number):
return', '.join(map(humanize, number)) return', '.join(map(humanize, number))
if number is None:
return u('')
order = number and int(floor(log(abs(number)) / log(1000))) order = number and int(floor(log(abs(number)) / log(1000)))
human_readable = ORDERS.split(" ")[int(order > 0)] human_readable = ORDERS.split(" ")[int(order > 0)]
if order == 0 or order > len(human_readable): if order == 0 or order > len(human_readable):

Loading…
Cancel
Save