diff options
| author | pinky <> | 2006-12-07 13:41:40 +0000 |
|---|---|---|
| committer | pinky <> | 2006-12-07 13:41:40 +0000 |
| commit | 004a0b996ff8f269451e07346f71a129a1f3fbaf (patch) | |
| tree | 48f43c1fc2ca4c1f4d5648e7e73553d3f4ccae06 /bin/pychart/legend.py | |
New trunk
bzr revid: pinky-3f10ee12cea3c4c75cef44ab04ad33ef47432907
Diffstat (limited to 'bin/pychart/legend.py')
| -rw-r--r-- | bin/pychart/legend.py | 181 |
1 files changed, 181 insertions, 0 deletions
diff --git a/bin/pychart/legend.py b/bin/pychart/legend.py new file mode 100644 index 00000000000..c45f6ff5729 --- /dev/null +++ b/bin/pychart/legend.py @@ -0,0 +1,181 @@ +# +# Copyright (C) 2000-2005 by Yasushi Saito (yasushi.saito@gmail.com) +# +# Jockey is free software; you can redistribute it and/or modify it +# under the terms of the GNU General Public License as published by the +# Free Software Foundation; either version 2, or (at your option) any +# later version. +# +# Jockey is distributed in the hope that it will be useful, but WITHOUT +# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +# for more details. +# +import tick_mark +import font +import line_style +import color +import fill_style +import chart_object +import pychart_util +import types +import legend_doc +import theme + +from pychart_types import * +from types import * + +class Entry(chart_object.T): + keys = {"line_len" : (UnitType, None, + "Length of the sample line for line plots. If omitted, it is set to be theme.default_font_size"), + "rect_size" : (UnitType, None, + "Size of the sample 'blob' for bar range charts. If omitted, it is set to be 70% of theme.default_size"), + "tick_mark": (tick_mark.T, None, ""), + "line_style": (line_style.T, None, ""), + "fill_style": (fill_style.T, None, ""), + "label": (StringType, "???", ""), + } + __doc__ = legend_doc.doc_entry +##AUTOMATICALLY GENERATED + +##END AUTOMATICALLY GENERATED + + def label_width(self): + return font.text_width(" " + self.label) + def get_line_len(self): + return self.line_len or theme.default_font_size + def get_rect_size(self): + return self.rect_size or theme.default_font_size * 7 / 10.0 + + def sample_width(self): + w = 0 + if self.fill_style != None: + w += self.get_line_len() + elif self.line_style != None: + w += self.get_line_len() + elif self.tick_mark != None: + w += self.tick_mark.size + return w + def height(self): + h = font.text_height(self.label)[0] + return h + + def draw(self, ar, can, x_tick, x_label, y): + """Draw a legend entry. X_TICK and X_LABEL are the X location \ + (in points) of where the sample and label are drawn.""" + + rect_size = self.get_rect_size() + line_len = self.get_line_len() + + nr_lines = len(self.label.split("\n")) + text_height = font.text_height(self.label)[0] + line_height = text_height / float(nr_lines) + y_center = y + text_height - line_height/1.5 + + if self.fill_style != None: + can.rectangle(self.line_style, self.fill_style, + x_tick, y_center - rect_size/2.0, + x_tick + rect_size, + y_center + rect_size/2.0) + elif self.line_style != None: + can.line(self.line_style, x_tick, y_center, + x_tick + line_len, y_center) + if self.tick_mark != None: + self.tick_mark.draw(can, x_tick + line_len/2.0, y_center) + elif self.tick_mark != None: + self.tick_mark.draw(can, x_tick, y_center) + + can.show(x_label, y, self.label) + +__doc__ = """Legend is a rectangular box drawn in a chart to describe +the meanings of plots. The contents of a legend box is extracted from +plots' "label", "line-style", and "tick-mark" attributes. + +This module exports a single class, legend.T. Legend.T is a part of +an area.T object, and is drawn automatically when area.draw() method +is called. """ + +class T(chart_object.T): + __doc__ = legend_doc.doc + keys = { + "inter_row_sep": (UnitType, 0, + "Space between each row in the legend."), + "inter_col_sep": (UnitType, 0, + "Space between each column in the legend."), + "frame_line_style": (line_style.T, line_style.default, ""), + "frame_fill_style": (fill_style.T, fill_style.white, ""), + "top_fudge": (UnitType, 0, + "Amount of space above the first line."), + "bottom_fudge": (UnitType, 3, + "Amount of space below the last line."), + "left_fudge": (UnitType, 5, + "Amount of space left of the legend."), + "right_fudge": (UnitType, 5, + "Amount of space right of the legend."), + "loc": (CoordType, None, + """Bottom-left corner of the legend. + The default location of a legend is the bottom-right end of the chart."""), + "shadow": (ShadowType, None, pychart_util.shadow_desc), + "nr_rows": (IntType, 9999, "Number of rows in the legend. If the number of plots in a chart is larger than nr_rows, multiple columns are created in the legend."), + + } +##AUTOMATICALLY GENERATED + +##END AUTOMATICALLY GENERATED + def draw(self, ar, entries, can): + if not self.loc: + x = ar.loc[0] + ar.size[0] * 1.1 + y = ar.loc[1] + else: + x = self.loc[0] + y = self.loc[1] + + nr_rows = min(self.nr_rows, len(entries)) + nr_cols = (len(entries)-1) / nr_rows + 1 + + ymin = y + max_label_width = [0] * nr_cols + max_sample_width = [0] * nr_cols + heights = [0] * nr_rows + + for i in range(len(entries)): + l = entries[i] + (col, row) = divmod(i, nr_rows) + max_label_width[col] = max(l.label_width(), max_label_width[col]) + max_sample_width[col] = max(l.sample_width(), max_sample_width[col]) + heights[row] = max(l.height(), heights[row]) + + for h in heights: + y += h + y += self.inter_row_sep * (nr_rows - 1) + ymax = y + + tot_width = self.inter_col_sep * (nr_cols -1) + for w in max_label_width: + tot_width += w + for w in max_sample_width: + tot_width += w + + can.rectangle(self.frame_line_style, self.frame_fill_style, + x - self.left_fudge, + ymin - self.bottom_fudge, + x + tot_width + self.right_fudge, + ymax + self.top_fudge, + self.shadow) + + for col in range(nr_cols): + this_y = y + this_x = x + for row in range(nr_rows): + idx = col * nr_rows + row + if idx >= len(entries): + continue + this_y -= heights[row] + l = entries[idx] + if row != 0: + this_y -= self.inter_row_sep + + l.draw(ar, can, this_x, this_x + max_sample_width[col], this_y) + x += max_label_width[col] + max_sample_width[col] + self.inter_col_sep + + |
