Skip to content

Commit

Permalink
Simpler theming. Closes #37.
Browse files Browse the repository at this point in the history
  • Loading branch information
onyxfish committed May 19, 2016
1 parent 317e034 commit af9574e
Show file tree
Hide file tree
Showing 10 changed files with 81 additions and 44 deletions.
2 changes: 1 addition & 1 deletion docs/example.svg
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
1 change: 1 addition & 0 deletions leather/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,3 +9,4 @@
from leather.scales import Linear, Ordinal
from leather.series import Series
from leather.shapes import Bars, Columns, Dots, Lines
from leather import theme
5 changes: 3 additions & 2 deletions leather/axis.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
import six

from leather.renderable import Renderable
from leather import theme


class Axis(Renderable):
Expand All @@ -14,7 +15,7 @@ class Axis(Renderable):
def __init__(self, ticks=5):
self.ticks = ticks

def estimate_label_margin(self, scale, orient, theme):
def estimate_label_margin(self, scale, orient):
"""
Estimate the space needed for the tick labels.
"""
Expand All @@ -24,7 +25,7 @@ def estimate_label_margin(self, scale, orient, theme):
elif orient == 'bottom':
return theme.tick_font_char_height

def to_svg(self, width, height, scale, orient, theme):
def to_svg(self, width, height, scale, orient):
"""
Render this axis to SVG elements.
"""
Expand Down
63 changes: 33 additions & 30 deletions leather/chart.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
#!/usr/bin/env python

from copy import copy
import os
import xml.etree.ElementTree as ET

Expand All @@ -8,29 +9,19 @@
from leather.axis import Axis
from leather.scales import Scale
from leather.series import Series
from leather.shapes.bars import Bars
from leather.shapes.columns import Columns
from leather.shapes.dots import Dots
from leather.shapes.lines import Lines
from leather.shapes import Bars, Columns, Dots, Lines
import leather.svg as svg
from leather.theme import Theme
from leather import theme
from leather.utils import X, Y, DIMENSIONS, Box

DEFAULT_BARS = Bars()
DEFAULT_COLUMNS = Columns()
DEFAULT_DOTS = Dots()
DEFAULT_LINES = Lines()

DEFAULT_THEME = Theme()


class Chart(object):
"""
Container for all chart types.
"""
def __init__(self, title=None, theme=DEFAULT_THEME):
def __init__(self, title=None):
self._title = title
self._theme = theme
self._series_colors = copy(theme.series_colors)

self._layers = []
self._types = [None, None]
Expand Down Expand Up @@ -85,29 +76,41 @@ def add_series(self, series):

self._layers.append(series)

def add_bars(self, data, name=None):
def add_bars(self, data, name=None, color=None):
"""
Shortcut method for adding a bar series to the chart.
"""
self.add_series(Series(data, DEFAULT_BARS, name=name))
if not color:
color = self._series_colors.pop(0)

self.add_series(Series(data, Bars(color), name=name))

def add_columns(self, data, name=None):
def add_columns(self, data, name=None, color=None):
"""
Shortcut method for adding a column series to the chart.
"""
self.add_series(Series(data, DEFAULT_COLUMNS, name=name))
if not color:
color = self._series_colors.pop(0)

def add_dots(self, data, name=None):
self.add_series(Series(data, Columns(color), name=name))

def add_dots(self, data, name=None, color=None):
"""
Shortcut method for adding a dotted series to the chart.
"""
self.add_series(Series(data, DEFAULT_DOTS, name=name))
if not color:
color = self._series_colors.pop(0)

self.add_series(Series(data, Dots(color), name=name))

def add_lines(self, data, name=None):
def add_lines(self, data, name=None, color=None):
"""
Shortcut method for adding a line series to the chart.
"""
self.add_series(Series(data, DEFAULT_LINES, name=name))
if not color:
color = self._series_colors.pop(0)

self.add_series(Series(data, Lines(color), name=name))

def _validate_dimension(self, dimension):
"""
Expand Down Expand Up @@ -169,14 +172,14 @@ def to_svg_group(self, width, height, margin=None):
label = ET.Element('text',
x=six.text_type(0),
y=six.text_type(0),
fill=self._theme.title_color
fill=theme.title_color
)
label.set('font-family', self._theme.title_font_family)
label.set('font-size', self._theme.title_font_size)
label.set('font-family', theme.title_font_family)
label.set('font-size', theme.title_font_size)
label.text = six.text_type(self._title)

header_group.append(label)
header_margin += self._theme.title_font_char_height
header_margin += theme.title_font_char_height

body_group = ET.Element('g')
body_group.set('transform', svg.translate(0, header_margin))
Expand All @@ -188,17 +191,17 @@ def to_svg_group(self, width, height, margin=None):
x_scale, x_axis = self._validate_dimension(X)
y_scale, y_axis = self._validate_dimension(Y)

bottom_margin = x_axis.estimate_label_margin(x_scale, 'bottom', self._theme)
left_margin = y_axis.estimate_label_margin(y_scale, 'left', self._theme)
bottom_margin = x_axis.estimate_label_margin(x_scale, 'bottom')
left_margin = y_axis.estimate_label_margin(y_scale, 'left')

canvas_width = body_width - left_margin
canvas_height = body_height - bottom_margin

axes_group = ET.Element('g')
axes_group.set('transform', svg.translate(left_margin, 0))

axes_group.append(x_axis.to_svg(canvas_width, canvas_height, x_scale, 'bottom', self._theme))
axes_group.append(y_axis.to_svg(canvas_width, canvas_height, y_scale, 'left', self._theme))
axes_group.append(x_axis.to_svg(canvas_width, canvas_height, x_scale, 'bottom'))
axes_group.append(y_axis.to_svg(canvas_width, canvas_height, y_scale, 'left'))

# Series
series_group = ET.Element('g')
Expand Down
2 changes: 1 addition & 1 deletion leather/shapes/bars.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ class Bars(Shape):
"""
Render a series of data as columns.
"""
def __init__(self, color='green'):
def __init__(self, color):
self.color = color

def to_svg(self, width, height, x_scale, y_scale, series):
Expand Down
2 changes: 1 addition & 1 deletion leather/shapes/columns.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ class Columns(Shape):
"""
Render a series of data as columns.
"""
def __init__(self, color='green'):
def __init__(self, color):
self.color = color

def to_svg(self, width, height, x_scale, y_scale, series):
Expand Down
5 changes: 3 additions & 2 deletions leather/shapes/dots.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,15 +5,16 @@
import six

from leather.shapes.base import Shape
from leather import theme


class Dots(Shape):
"""
Render a series of data as dots.
"""
def __init__(self, radius=3, color='red'):
self.radius = radius
def __init__(self, color, radius=None):
self.color = color
self.radius = radius or theme.dot_radius

def to_svg(self, width, height, x_scale, y_scale, series):
"""
Expand Down
7 changes: 4 additions & 3 deletions leather/shapes/lines.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,15 +5,16 @@
import six

from leather.shapes.base import Shape
from leather import theme


class Lines(Shape):
"""
Render a series of data as a line.
"""
def __init__(self, width='2px', color='blue'):
self.width = width
def __init__(self, color, width=None):
self.color = color
self.width = width or theme.line_width

def to_svg(self, width, height, x_scale, y_scale, series):
"""
Expand All @@ -26,7 +27,7 @@ def to_svg(self, width, height, x_scale, y_scale, series):
stroke=self.color,
fill='none'
)
path.set('stroke-width', self.width)
path.set('stroke-width', six.text_type(self.width))

d = []

Expand Down
30 changes: 30 additions & 0 deletions leather/theme.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
#!/usr/bin/env python

"""
Visual options for all chart elements.
"""

# Chart title
title_color = '#333'
title_font_family = 'Monaco'
title_font_size = '16px'
title_font_char_height = 20
title_font_char_width = 9

# Tick lines
tick_width = '1px'
tick_size = 4
tick_color = '#eee'
label_color = '#9c9c9c'
zero_color = '#a8a8a8'

# Tick labels
tick_font_family = 'Monaco'
tick_font_size = '14px'
tick_font_char_height = 14
tick_font_char_width = 8

# Series
series_colors = ['#d190b6', '#51b2e5', '#d365ba', '#168dd9']
dot_radius = 3
line_width = 2
8 changes: 4 additions & 4 deletions tests/test_shapes.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@

class TestBars(unittest.TestCase):
def setUp(self):
self.shape = leather.Bars()
self.shape = leather.Bars('red')
self.linear = leather.Linear(0, 10)
self.ordinal = leather.Ordinal(['foo', 'bar', 'bing'])

Expand All @@ -31,7 +31,7 @@ def test_to_svg(self):

class TestColumns(unittest.TestCase):
def setUp(self):
self.shape = leather.Columns()
self.shape = leather.Columns('red')
self.linear = leather.Linear(0, 10)
self.ordinal = leather.Ordinal(['foo', 'bar', 'bing'])

Expand All @@ -52,7 +52,7 @@ def test_to_svg(self):

class TestDots(unittest.TestCase):
def setUp(self):
self.shape = leather.Dots()
self.shape = leather.Dots('red')
self.linear = leather.Linear(0, 10)
self.ordinal = leather.Ordinal(['foo', 'bar', 'bing'])

Expand Down Expand Up @@ -87,7 +87,7 @@ def test_ordinal(self):

class TestLines(unittest.TestCase):
def setUp(self):
self.shape = leather.Lines()
self.shape = leather.Lines('red')
self.linear = leather.Linear(0, 10)
self.ordinal = leather.Ordinal(['foo', 'bar', 'bing'])

Expand Down

0 comments on commit af9574e

Please sign in to comment.