Added TODO and DEVELOPMENT.
[faces-project.git] / faces / charting / tools.py
blobc47fbe8c9e85c68b1d70aa90ac343d97584f1ab9
1 ############################################################################
2 # Copyright (C) 2005 by Reithinger GmbH
3 # mreithinger@web.de
5 # This file is part of faces.
6 #
7 # faces is free software; you can redistribute it and/or modify
8 # it under the terms of the GNU General Public License as published by
9 # the Free Software Foundation; either version 2 of the License, or
10 # (at your option) any later version.
12 # faces is distributed in the hope that it will be useful,
13 # but WITHOUT ANY WARRANTY; without even the implied warranty of
14 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 # GNU General Public License for more details.
17 # You should have received a copy of the GNU General Public License
18 # along with this program; if not, write to the
19 # Free Software Foundation, Inc.,
20 # 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
21 ############################################################################
23 import matplotlib.transforms as _mtrans
24 import matplotlib.patches as _patches
25 import matplotlib.numerix as _numerix
26 import matplotlib.font_manager as _font
28 chart_encoding = "iso8859-15"
29 _minus = _mtrans.Value(-1)
30 _value_type = type(_minus)
33 class ChartWrapper(object):
34 forwards = []
35 def _find_property_in_chain(self, name):
36 for f in self.forwards:
37 try:
38 return f._find_property_in_chain(name)
39 except AttributeError:
40 pass
41 except KeyError:
42 pass
44 raise KeyError(name)
47 chart_properties = ChartWrapper()
49 def push_active(chart):
50 chart_properties.forwards.append(chart)
53 def pop_active():
54 chart_properties.forwards.pop()
58 def value(val):
59 if isinstance(val, Lazy):
60 return val.val
62 if type(val) is _value_type:
63 return val
65 return _mtrans.Value(val)
68 def get_verts(artist, renderer, transform):
69 if isinstance(artist, _patches.Patch):
70 return artist.get_verts()
72 if isinstance(artist, dtext.Text):
73 bbox = artist.get_window_extent(renderer)
74 verts = ((bbox.xmin(), bbox.ymin()),
75 (bbox.xmin(), bbox.ymax()),
76 (bbox.xmax(), bbox.ymax()),
77 (bbox.xmax(), bbox.ymin()))
78 verts = map(_mtrans.inverse_xy_tup, verts)
79 return verts
81 raise ValueError("artist not known")
85 #make mtrans Value mor comfortable
86 class Lazy(object):
87 def __init__(self, val):
88 self.val = self.conv(val)
91 def __len__(self):
92 raise TypeError("len() of unsized object")
95 def __float__(self):
96 return self.val.get()
99 def __nonzero__(self):
100 return True
103 def conv(self, other):
104 if type(other) is _value_type:
105 return other
107 try:
108 if other.__class__ is self.__class__:
109 return other.val
110 except:
111 pass
113 return _mtrans.Value(other)
115 def __hash__(self):
116 return hash(float(self))
119 def __add__(self, other): return Lazy(self.val + self.conv(other))
120 def __sub__(self, other): return Lazy(self.val - self.conv(other))
121 def __mul__(self, other): return Lazy(self.val * self.conv(other))
122 def __div__(self, other): return Lazy(self.val / self.conv(other))
123 def __radd__(self, other): return Lazy(self.conv(other) + self.val)
124 def __rsub__(self, other): return Lazy(self.conv(other) - self.val)
125 def __rmul__(self, other): return Lazy(self.conv(other) * self.val)
126 def __rdiv__(self, other): return Lazy(self.conv(other) / self.val)
127 def __neg__(self): return Lazy(_minus * self.val)
129 def set(self, src):
130 if src.__class__ is self.__class__:
131 self.val.set(src.get())
132 return
134 if type(src) is _value_type:
135 self.val.set(src.get())
136 return
138 self.val.set(src)
141 def get(self):
142 return self.val.get()
145 class LazyBbox:
146 def __init__(self, bbox):
147 self.bbox = bbox
149 def ll(self): return self.bbox.ll()
150 def ur(self): return self.bbox.ur()
151 def contains(self, x, y): return self.bbox.contains(x, y)
152 def overlaps(self, bbox): return self.bbox.overlaps(bbox)
153 def overlapsx(self, bbox): return self.bbox.overlapsx(bbox)
154 def overlapsy(self, bbox): return self.bbox.overlapsy(bbox)
155 def intervalx(self, ): return self.bbox.intervalx()
156 def intervaly(self, ): return self.bbox.intervaly()
157 def get_bounds(self, ): return self.bbox.get_bounds()
158 def update(self, xys, ignore): return self.bbox.update(xys, ignore)
159 def width(self, ): return self.bbox.width()
160 def height(self, ): return self.bbox.height()
161 def xmax(self, ): return self.bbox.xmax()
162 def ymax(self, ): return self.bbox.ymax()
163 def xmin(self, ): return self.bbox.xmin()
164 def ymin(self, ): return self.bbox.ymin()
165 def scale(self, sx,sy): return self.bbox.scale(sx,sy)
166 def deepcopy(self, ): return self.bbox.deepcopy()
170 def draw_lines(renderer, gc, xs, ys, trans):
171 xs = map(float, xs)
172 ys = map(float, ys)
173 try:
174 renderer.draw_lines(gc, xs, ys, trans)
175 except TypeError:
176 xs, ys = trans.seq_x_y(xs, ys)
177 xs = _numerix.array(xs, typecode=_numerix.Int16)
178 ys = _numerix.array(ys, typecode=_numerix.Int16)
179 renderer.draw_lines(gc, xs, ys)
182 def draw_line(renderer, gc, x1, y1, x2, y2, trans):
183 #patch because agg_renderer.draw_line has a bug
184 x = _numerix.array([x1,x2], typecode=_numerix.Float)
185 y = _numerix.array([y1,y2], typecode=_numerix.Float)
186 draw_lines(renderer, gc, x, y, trans)
189 VSEP = Lazy(_font.fontManager.get_default_size() / 4)
190 HSEP = Lazy(0)
191 LEFT = Lazy(0)
192 RIGHT = Lazy(0)
193 BOTTOM = Lazy(0)
194 TOP = Lazy(0)
195 VCENTER = Lazy(0)
196 HCENTER = Lazy(0)
197 FACTOR = Lazy(1)
200 def set_helpers(bbox, all_bbox):
201 LEFT.set(bbox.xmin())
202 RIGHT.set(bbox.xmax())
203 TOP.set(bbox.ymax())
204 BOTTOM.set(bbox.ymin())
205 HCENTER.set((max(all_bbox.xmin(), bbox.xmin())\
206 + min(all_bbox.xmax(), bbox.xmax())) / 2)
207 VCENTER.set((bbox.ymin() + bbox.ymax()) / 2)
210 def set_default_size(size):
211 _font.fontManager.set_default_size(size)
212 VSEP.set(size / 4.0)
215 def set_encoding(coding):
216 global chart_encoding
217 chart_encoding = coding
220 def make_properties(props, name):
221 return { "edgecolor" : props(name + ".edgecolor"),
222 "facecolor" : props(name + ".facecolor"),
223 "linewidth" : props(name + ".linewidth"),
224 "antialiased" : props(name + ".antialiased"),
225 "alpha" : props(name + ".alpha"),
226 "fill" : props(name + ".fill") }