[IMP] module loading: iterate on the module graph in deterministic order (by sorting...
[odoo/odoo.git] / openerp / pychart / axis.py
1 # -*- coding: utf-8 -*-
2 #
3 # Copyright (C) 2000-2005 by Yasushi Saito (yasushi.saito@gmail.com)
4
5 # Jockey is free software; you can redistribute it and/or modify it
6 # under the terms of the GNU General Public License as published by the
7 # Free Software Foundation; either version 2, or (at your option) any
8 # later version.
9 #
10 # Jockey is distributed in the hope that it will be useful, but WITHOUT
11 # ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
12 # FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
13 # for more details.
14 #
15 import font
16 import pychart_util
17 import chart_object
18 import line_style
19 import math
20 import theme
21 import axis_doc
22 from pychart_types import *
23 from types import *
24
25 class T(chart_object.T):
26     keys = {
27        "tic_interval" : (IntervalType, None, 
28                          pychart_util.interval_desc("tick marks")),
29        "tic_len" : (UnitType, 6, """The length of tick lines. The value can be negative, in which case the tick lines are drawn right of (or above) the axis."""),
30        "minor_tic_interval" : (IntervalType, None,
31                                pychart_util.interval_desc("minor tick marks")),
32        "minor_tic_len" : (UnitType, 3, """The length of minor tick marks.  The value can be negative, in which case the tick lines are drawn right of (or above) the axis."""),
33        "line_style": (line_style.T, line_style.default, 
34                       "Specifies the style of axis and tick lines."),
35        "label": (types.StringType, "axis label",
36                  "The descriptive string displayed below (or to the left of) the axis. <<font>>."),
37        "format": (FormatType, "%s", 
38                   """The format string for tick labels.
39                   It can be a `printf' style format string, or 
40                   a single-parameter function that takes an X (or Y) value
41                   and returns a string. """ +
42                   pychart_util.string_desc),
43        "label_offset": (CoordOrNoneType, (None,None),
44                         """The location for drawing the axis label, 
45                         relative to the middle point of the axis.
46                         If the value is None, the label is displayed
47                         below (or to the left of) of axis at the middle."""),
48        "tic_label_offset": (CoordType, (0,0),
49                             """The location for drawing tick labels, 
50                             relative to the tip of the tick line."""),
51        "offset": (UnitType, 0,
52                   """The location of the axis. 
53                   The value of 0 draws the
54                   axis at the left (for the Y axis) or bottom (for the X axis)
55                   edge of the drawing area.
56                   """)
57        }
58
59 class X(T):
60     keys = pychart_util.union_dict(T.keys,
61                                    {"draw_tics_above": (IntType, 0,
62                                                         "If true, tick lines and labels are drawn above the axis line.")})
63     __doc__ = axis_doc.doc_x
64 ##AUTOMATICALLY GENERATED
65
66 ##END AUTOMATICALLY GENERATED
67     def draw_below(self, ar, can):
68         self.type_check()
69         self.tic_interval = self.tic_interval or ar.x_grid_interval
70         y_base = ar.loc[1] + self.offset
71       
72         can.line(self.line_style, ar.loc[0], y_base,
73                     ar.loc[0]+ ar.size[0], y_base)
74
75         tic_dic = {}
76         max_tic_height = 0
77       
78         for i in ar.x_tic_points(self.tic_interval):
79             tic_dic[i] = 1
80             ticx = ar.x_pos(i)
81
82             str = "/hC" + pychart_util.apply_format(self.format, (i, ), 0)
83
84             (total_height, base_height) = font.text_height(str)
85             max_tic_height = max(max_tic_height, total_height)
86
87             can.line(self.line_style, ticx, y_base, ticx, y_base-self.tic_len)
88             can.show(ticx+self.tic_label_offset[0], 
89                         y_base-self.tic_len-base_height+self.tic_label_offset[1],
90                         str)
91          
92         if self.minor_tic_interval:
93             for i in ar.x_tic_points(self.minor_tic_interval):
94                 if tic_dic.has_key(i):
95                     # a major tic was drawn already.
96                     pass
97                 else:
98                     ticx = ar.x_pos(i)
99                     can.line(self.line_style, ticx, y_base, ticx,
100                                 y_base-self.minor_tic_len)
101
102         self.draw_label(ar, can, y_base - self.tic_len - max_tic_height - 10)
103         
104     def draw_above(self, ar, can):
105         y_base = ar.loc[1] + self.offset
106       
107         tic_dic = {}
108         max_tic_height = 0
109       
110         for i in ar.x_tic_points(self.tic_interval):
111             tic_dic[i] = 1
112             ticx = ar.x_pos(i)
113
114             str = "/hC" + pychart_util.apply_format(self.format, (i, ), 0)
115
116             (total_height, base_height) = font.text_height(str)
117             max_tic_height = max(max_tic_height, total_height)
118
119             can.line(self.line_style, ticx, y_base, ticx, y_base + self.tic_len)
120             can.show(ticx+self.tic_label_offset[0], 
121                      y_base + self.tic_len + base_height + self.tic_label_offset[1],
122                      str)
123          
124         if self.minor_tic_interval:
125             for i in ar.x_tic_points(self.minor_tic_interval):
126                 if tic_dic.has_key(i):
127                     # a major tic was drawn already.
128                     pass
129                 else:
130                     ticx = ar.x_pos(i)
131                     can.line(self.line_style, ticx, y_base, ticx,
132                              y_base + self.minor_tic_len)
133         self.draw_label(ar, can, y_base + self.tic_len + max_tic_height + 10)
134         
135     def draw_label(self, ar, can, ylabel):
136         if self.label == None: return
137     
138         str = "/hC/vM" + self.label
139         (label_height, base_height) = font.text_height(str)
140         xlabel = ar.loc[0] + ar.size[0]/2.0
141         if self.label_offset[0] != None:
142             xlabel += self.label_offset[0]
143         if self.label_offset[1] != None:
144             ylabel += self.label_offset[1]
145         can.show(xlabel, ylabel, str)
146         
147     def draw(self, ar, can):
148         self.type_check()
149         self.tic_interval = self.tic_interval or ar.x_grid_interval
150         y_base = ar.loc[1] + self.offset
151         can.line(self.line_style, ar.loc[0], y_base,
152                  ar.loc[0]+ ar.size[0], y_base)
153         if self.draw_tics_above:
154             self.draw_above(ar, can)
155         else:
156             self.draw_below(ar, can)
157 class Y(T):
158     __doc__ = axis_doc.doc_y   
159     keys = pychart_util.union_dict(T.keys,
160                                    {"draw_tics_right": (IntType, 0,
161                                                         "If true, tick lines and labels are drawn right of the axis line.")})
162     
163     def draw_left(self, ar, can):
164         x_base = ar.loc[0] + self.offset
165         xmin = 999999
166         tic_dic = {}
167         for i in ar.y_tic_points(self.tic_interval):
168             y_tic = ar.y_pos(i)
169             tic_dic[i] = 1
170             can.line(self.line_style, x_base, y_tic,
171                      x_base - self.tic_len, y_tic)
172             str = pychart_util.apply_format(self.format, (i,), 0)
173             if self.tic_len > 0: str = "/hR" + str
174
175             tic_height, base_height = font.text_height(str)
176             x = x_base - self.tic_len + self.tic_label_offset[0]
177             can.show(x, y_tic - tic_height/2.0 + self.tic_label_offset[1],
178                      str)
179             xmin = min(xmin, x - font.text_width(str))
180             
181         if self.minor_tic_interval:
182             for i in ar.y_tic_points(self.minor_tic_interval):
183                 if tic_dic.has_key(i):
184                     # a major tic line was drawn already.
185                     pass
186                 else:
187                     y_tic = ar.y_pos(i)
188                     can.line(self.line_style, x_base, y_tic,
189                              x_base - self.minor_tic_len, y_tic)
190                
191         self.draw_label(ar, can, xmin - theme.default_font_size/2.0)
192
193     def draw_right(self, ar, can):
194         x_base = ar.loc[0] + self.offset
195         xmax = 0
196         tic_dic = {}
197         for i in ar.y_tic_points(self.tic_interval):
198             y_tic = ar.y_pos(i)
199             tic_dic[i] = 1
200             can.line(self.line_style, x_base, y_tic,
201                      x_base + self.tic_len, y_tic)
202             str = pychart_util.apply_format(self.format, (i,), 0)
203             if self.tic_len > 0: str = "/hL" + str
204
205             tic_height, base_height = font.text_height(str)
206             x = x_base + self.tic_len + self.tic_label_offset[0]
207             can.show(x, y_tic - tic_height/2.0 + self.tic_label_offset[1],
208                      str)
209             xmax = max(xmax, x + font.text_width(str))
210             
211         if self.minor_tic_interval:
212             for i in ar.y_tic_points(self.minor_tic_interval):
213                 if tic_dic.has_key(i):
214                     # a major tic line was drawn already.
215                     pass
216                 else:
217                     y_tic = ar.y_pos(i)
218                     can.line(self.line_style, x_base, y_tic,
219                              x_base + self.minor_tic_len, y_tic)
220
221         self.draw_label(ar, can, xmax + theme.default_font_size)
222         
223     def draw_label(self, ar, can, xlabel):
224         if self.label == None:
225             return
226         ylabel = ar.loc[1] + ar.size[1] / 2
227         if self.label_offset[0] != None:
228             xlabel += self.label_offset[0]
229         if self.label_offset[1] != None:
230             ylabel += self.label_offset[1]
231         can.show(xlabel, ylabel, "/a90/hC" + self.label)
232
233     def draw(self, ar, can):
234         self.type_check()
235         self.tic_interval = self.tic_interval or ar.y_grid_interval
236         
237         x_base = ar.loc[0] + self.offset
238         can.line(self.line_style, x_base, ar.loc[1], x_base, ar.loc[1]+ar.size[1])
239         if self.draw_tics_right:
240             self.draw_right(ar, can)
241         else:
242             self.draw_left(ar, can)