diff options
author | Gary Bressler <garybressler@nc.rr.com> | 2010-04-08 17:11:08 -0400 |
---|---|---|
committer | Gary Bressler <garybressler@nc.rr.com> | 2010-04-08 17:11:08 -0400 |
commit | ceff6457bfeb5642616f4711f14e0bb652d12164 (patch) | |
tree | d05b4ebd1c3ee6e28884c669d65fd31700941086 /unit_trace/viz/canvas.py | |
parent | 01abc8352aa2fd192678b4066b26ea749a203801 (diff) |
Updated the documentation to describe the visualizer, made unit-trace itself not require gtk/cairo, and a few other minor things.
Diffstat (limited to 'unit_trace/viz/canvas.py')
-rw-r--r-- | unit_trace/viz/canvas.py | 340 |
1 files changed, 170 insertions, 170 deletions
diff --git a/unit_trace/viz/canvas.py b/unit_trace/viz/canvas.py index 758dea3..ea73d98 100644 --- a/unit_trace/viz/canvas.py +++ b/unit_trace/viz/canvas.py | |||
@@ -33,19 +33,19 @@ class Surface(object): | |||
33 | self.scale = 1.0 | 33 | self.scale = 1.0 |
34 | self.fname = fname | 34 | self.fname = fname |
35 | self.ctx = ctx | 35 | self.ctx = ctx |
36 | 36 | ||
37 | def renew(self, width, height): | 37 | def renew(self, width, height): |
38 | raise NotImplementedError | 38 | raise NotImplementedError |
39 | 39 | ||
40 | def change_ctx(self, ctx): | 40 | def change_ctx(self, ctx): |
41 | self.ctx = ctx | 41 | self.ctx = ctx |
42 | 42 | ||
43 | def get_fname(self): | 43 | def get_fname(self): |
44 | return self.fname | 44 | return self.fname |
45 | 45 | ||
46 | def write_out(self, fname): | 46 | def write_out(self, fname): |
47 | raise NotImplementedError | 47 | raise NotImplementedError |
48 | 48 | ||
49 | def pan(self, x, y, width, height): | 49 | def pan(self, x, y, width, height): |
50 | """A surface actually represents just a ``window'' into | 50 | """A surface actually represents just a ``window'' into |
51 | what we are drawing on. For instance, if we are scrolling through | 51 | what we are drawing on. For instance, if we are scrolling through |
@@ -57,11 +57,11 @@ class Surface(object): | |||
57 | self.virt_y = y | 57 | self.virt_y = y |
58 | self.width = width | 58 | self.width = width |
59 | self.height = height | 59 | self.height = height |
60 | 60 | ||
61 | def set_scale(self, scale): | 61 | def set_scale(self, scale): |
62 | """Sets the scale factor.""" | 62 | """Sets the scale factor.""" |
63 | self.scale = scale | 63 | self.scale = scale |
64 | 64 | ||
65 | def get_real_coor(self, x, y): | 65 | def get_real_coor(self, x, y): |
66 | """Translates the coordinates (x, y) | 66 | """Translates the coordinates (x, y) |
67 | in the ``theoretical'' plane to the true (x, y) coordinates on this surface | 67 | in the ``theoretical'' plane to the true (x, y) coordinates on this surface |
@@ -69,57 +69,57 @@ class Surface(object): | |||
69 | bounds of the surface, | 69 | bounds of the surface, |
70 | if we want something outside the surface's ``window''.""" | 70 | if we want something outside the surface's ``window''.""" |
71 | return (x - self.virt_x * self.scale, y - self.virt_y * self.scale) | 71 | return (x - self.virt_x * self.scale, y - self.virt_y * self.scale) |
72 | 72 | ||
73 | def get_virt_coor(self, x, y): | 73 | def get_virt_coor(self, x, y): |
74 | """Does the inverse of the last method.""" | 74 | """Does the inverse of the last method.""" |
75 | return (x + self.virt_x * self.scale, y + self.virt_y * self.scale) | 75 | return (x + self.virt_x * self.scale, y + self.virt_y * self.scale) |
76 | 76 | ||
77 | def get_virt_coor_unscaled(self, x, y): | 77 | def get_virt_coor_unscaled(self, x, y): |
78 | """Does the same, but removes the scale factor (i.e. behaves as if | 78 | """Does the same, but removes the scale factor (i.e. behaves as if |
79 | the scale was 1.0 all along).""" | 79 | the scale was 1.0 all along).""" |
80 | return (x / self.scale + self.virt_x, y / self.scale + self.virt_y) | 80 | return (x / self.scale + self.virt_x, y / self.scale + self.virt_y) |
81 | 81 | ||
82 | class SVGSurface(Surface): | 82 | class SVGSurface(Surface): |
83 | def renew(self, width, height): | 83 | def renew(self, width, height): |
84 | iwidth = int(math.ceil(width)) | 84 | iwidth = int(math.ceil(width)) |
85 | iheight = int(math.ceil(height)) | 85 | iheight = int(math.ceil(height)) |
86 | self.surface = cairo.SVGSurface(self.fname, iwidth, iheight) | 86 | self.surface = cairo.SVGSurface(self.fname, iwidth, iheight) |
87 | self.ctx = cairo.Context(self.surface) | 87 | self.ctx = cairo.Context(self.surface) |
88 | 88 | ||
89 | def write_out(self, fname): | 89 | def write_out(self, fname): |
90 | os.execl('cp', self.fname, fname) | 90 | os.execl('cp', self.fname, fname) |
91 | 91 | ||
92 | class ImageSurface(Surface): | 92 | class ImageSurface(Surface): |
93 | def renew(self, width, height): | 93 | def renew(self, width, height): |
94 | iwidth = int(math.ceil(width)) | 94 | iwidth = int(math.ceil(width)) |
95 | iheight = int(math.ceil(height)) | 95 | iheight = int(math.ceil(height)) |
96 | self.surface = cairo.ImageSurface(cairo.FORMAT_ARGB32, iwidth, iheight) | 96 | self.surface = cairo.ImageSurface(cairo.FORMAT_ARGB32, iwidth, iheight) |
97 | self.ctx = cairo.Context(self.surface) | 97 | self.ctx = cairo.Context(self.surface) |
98 | 98 | ||
99 | def write_out(self, fname): | 99 | def write_out(self, fname): |
100 | if self.surface is None: | 100 | if self.surface is None: |
101 | raise ValueError('Don\'t own surface, can\'t write to to file') | 101 | raise ValueError('Don\'t own surface, can\'t write to to file') |
102 | 102 | ||
103 | self.surface.write_to_png(fname) | 103 | self.surface.write_to_png(fname) |
104 | 104 | ||
105 | class Pattern(object): | 105 | class Pattern(object): |
106 | DEF_STRIPE_SIZE = 10 | 106 | DEF_STRIPE_SIZE = 10 |
107 | MAX_FADE_WIDTH = 250 | 107 | MAX_FADE_WIDTH = 250 |
108 | 108 | ||
109 | def __init__(self, color_list, stripe_size=DEF_STRIPE_SIZE): | 109 | def __init__(self, color_list, stripe_size=DEF_STRIPE_SIZE): |
110 | self.color_list = color_list | 110 | self.color_list = color_list |
111 | self.stripe_size = stripe_size | 111 | self.stripe_size = stripe_size |
112 | 112 | ||
113 | def render_on_canvas(self, canvas, x, y, width, height, fade=False): | 113 | def render_on_canvas(self, canvas, x, y, width, height, fade=False): |
114 | fade_span = min(width, Pattern.MAX_FADE_WIDTH) | 114 | fade_span = min(width, Pattern.MAX_FADE_WIDTH) |
115 | 115 | ||
116 | if len(self.color_list) == 1: | 116 | if len(self.color_list) == 1: |
117 | if fade: | 117 | if fade: |
118 | canvas.fill_rect_fade(x, y, fade_span, height, (1.0, 1.0, 1.0), \ | 118 | canvas.fill_rect_fade(x, y, fade_span, height, (1.0, 1.0, 1.0), \ |
119 | self.color_list[0]) | 119 | self.color_list[0]) |
120 | else: | 120 | else: |
121 | canvas.fill_rect(x, y, width, height, self.color_list[0]) | 121 | canvas.fill_rect(x, y, width, height, self.color_list[0]) |
122 | 122 | ||
123 | if width > Pattern.MAX_FADE_WIDTH: | 123 | if width > Pattern.MAX_FADE_WIDTH: |
124 | canvas.fill_rect(x + Pattern.MAX_FADE_WIDTH, y, width - Pattern.MAX_FADE_WIDTH, | 124 | canvas.fill_rect(x + Pattern.MAX_FADE_WIDTH, y, width - Pattern.MAX_FADE_WIDTH, |
125 | height, self.color_list[0]) | 125 | height, self.color_list[0]) |
@@ -133,100 +133,100 @@ class Pattern(object): | |||
133 | min(self.stripe_size, bottom - y), (1.0, 1.0, 1.0), self.color_list[i]) | 133 | min(self.stripe_size, bottom - y), (1.0, 1.0, 1.0), self.color_list[i]) |
134 | else: | 134 | else: |
135 | canvas.fill_rect(x, y, width, min(self.stripe_size, bottom - y), self.color_list[i]) | 135 | canvas.fill_rect(x, y, width, min(self.stripe_size, bottom - y), self.color_list[i]) |
136 | 136 | ||
137 | if width > Pattern.MAX_FADE_WIDTH: | 137 | if width > Pattern.MAX_FADE_WIDTH: |
138 | canvas.fill_rect(x + Pattern.MAX_FADE_WIDTH, y, width - Pattern.MAX_FADE_WIDTH, | 138 | canvas.fill_rect(x + Pattern.MAX_FADE_WIDTH, y, width - Pattern.MAX_FADE_WIDTH, |
139 | min(self.stripe_size, bottom - y), self.color_list[i]) | 139 | min(self.stripe_size, bottom - y), self.color_list[i]) |
140 | 140 | ||
141 | y += self.stripe_size | 141 | y += self.stripe_size |
142 | n += 1 | 142 | n += 1 |
143 | 143 | ||
144 | class Canvas(object): | 144 | class Canvas(object): |
145 | """This is a basic class that stores and draws on a Cairo surface, | 145 | """This is a basic class that stores and draws on a Cairo surface, |
146 | using various primitives related to drawing a real-time graph (up-arrows, | 146 | using various primitives related to drawing a real-time graph (up-arrows, |
147 | down-arrows, bars, ...). | 147 | down-arrows, bars, ...). |
148 | 148 | ||
149 | This is the lowest-level representation (aside perhaps from the Cairo | 149 | This is the lowest-level representation (aside perhaps from the Cairo |
150 | surface itself) of a real-time graph. It allows the user to draw | 150 | surface itself) of a real-time graph. It allows the user to draw |
151 | primitives at certain locations, but for the most part does not know | 151 | primitives at certain locations, but for the most part does not know |
152 | anything about real-time scheduling, just how to draw the basic parts | 152 | anything about real-time scheduling, just how to draw the basic parts |
153 | that make up a schedule graph. For that, see Graph or its descendants.""" | 153 | that make up a schedule graph. For that, see Graph or its descendants.""" |
154 | 154 | ||
155 | BOTTOM_LAYER = 0 | 155 | BOTTOM_LAYER = 0 |
156 | MIDDLE_LAYER = 1 | 156 | MIDDLE_LAYER = 1 |
157 | TOP_LAYER = 2 | 157 | TOP_LAYER = 2 |
158 | 158 | ||
159 | LAYERS = (BOTTOM_LAYER, MIDDLE_LAYER, TOP_LAYER) | 159 | LAYERS = (BOTTOM_LAYER, MIDDLE_LAYER, TOP_LAYER) |
160 | 160 | ||
161 | NULL_PATTERN = -1 | 161 | NULL_PATTERN = -1 |
162 | 162 | ||
163 | SQRT3 = math.sqrt(3.0) | 163 | SQRT3 = math.sqrt(3.0) |
164 | 164 | ||
165 | def __init__(self, width, height, item_clist, bar_plist, surface): | 165 | def __init__(self, width, height, item_clist, bar_plist, surface): |
166 | """Creates a new Canvas of dimensions (width, height). The | 166 | """Creates a new Canvas of dimensions (width, height). The |
167 | parameters ``item_plist'' and ``bar_plist'' each specify a list | 167 | parameters ``item_plist'' and ``bar_plist'' each specify a list |
168 | of patterns to choose from when drawing the items on the y-axis | 168 | of patterns to choose from when drawing the items on the y-axis |
169 | or filling in bars, respectively.""" | 169 | or filling in bars, respectively.""" |
170 | 170 | ||
171 | self.surface = surface | 171 | self.surface = surface |
172 | 172 | ||
173 | self.width = int(math.ceil(width)) | 173 | self.width = int(math.ceil(width)) |
174 | self.height = int(math.ceil(height)) | 174 | self.height = int(math.ceil(height)) |
175 | self.item_clist = item_clist | 175 | self.item_clist = item_clist |
176 | self.bar_plist = bar_plist | 176 | self.bar_plist = bar_plist |
177 | 177 | ||
178 | self.selectable_regions = {} | 178 | self.selectable_regions = {} |
179 | 179 | ||
180 | self.scale = 1.0 | 180 | self.scale = 1.0 |
181 | 181 | ||
182 | # clears the canvas. | 182 | # clears the canvas. |
183 | def clear(self): | 183 | def clear(self): |
184 | raise NotImplementedError | 184 | raise NotImplementedError |
185 | 185 | ||
186 | def set_scale(self, scale): | 186 | def set_scale(self, scale): |
187 | self.scale = scale | 187 | self.scale = scale |
188 | self.surface.set_scale(scale) | 188 | self.surface.set_scale(scale) |
189 | for event in self.selectable_regions: | 189 | for event in self.selectable_regions: |
190 | self.selectable_regions[event].set_scale(scale) | 190 | self.selectable_regions[event].set_scale(scale) |
191 | 191 | ||
192 | def scaled(self, *coors): | 192 | def scaled(self, *coors): |
193 | """Scales a series of coordinates.""" | 193 | """Scales a series of coordinates.""" |
194 | return [coor * self.scale for coor in coors] | 194 | return [coor * self.scale for coor in coors] |
195 | 195 | ||
196 | def unscaled(self, *coors): | 196 | def unscaled(self, *coors): |
197 | """Inverse of scale().""" | 197 | """Inverse of scale().""" |
198 | return [coor / self.scale for coor in coors] | 198 | return [coor / self.scale for coor in coors] |
199 | 199 | ||
200 | def draw_rect(self, x, y, width, height, color, thickness, snap=True): | 200 | def draw_rect(self, x, y, width, height, color, thickness, snap=True): |
201 | """Draws a rectangle somewhere (border only).""" | 201 | """Draws a rectangle somewhere (border only).""" |
202 | raise NotImplementedError | 202 | raise NotImplementedError |
203 | 203 | ||
204 | def fill_rect(self, x, y, width, height, color, snap=True): | 204 | def fill_rect(self, x, y, width, height, color, snap=True): |
205 | """Draws a filled rectangle somewhere. ``color'' is a 3-tuple.""" | 205 | """Draws a filled rectangle somewhere. ``color'' is a 3-tuple.""" |
206 | raise NotImplementedError | 206 | raise NotImplementedError |
207 | 207 | ||
208 | def fill_rect_fade(self, x, y, width, height, lcolor, rcolor, snap=True): | 208 | def fill_rect_fade(self, x, y, width, height, lcolor, rcolor, snap=True): |
209 | """Draws a rectangle somewhere, filled in with the fade.""" | 209 | """Draws a rectangle somewhere, filled in with the fade.""" |
210 | raise NotImplementedError | 210 | raise NotImplementedError |
211 | 211 | ||
212 | def draw_line(self, p0, p1, color, thickness, snap=True): | 212 | def draw_line(self, p0, p1, color, thickness, snap=True): |
213 | """Draws a line from p0 to p1 with a certain color and thickness.""" | 213 | """Draws a line from p0 to p1 with a certain color and thickness.""" |
214 | raise NotImplementedError | 214 | raise NotImplementedError |
215 | 215 | ||
216 | def draw_polyline(self, coor_list, color, thickness, snap=True): | 216 | def draw_polyline(self, coor_list, color, thickness, snap=True): |
217 | """Draws a polyline, where coor_list = [(x_0, y_0), (x_1, y_1), ... (x_m, y_m)] | 217 | """Draws a polyline, where coor_list = [(x_0, y_0), (x_1, y_1), ... (x_m, y_m)] |
218 | specifies a polyline from (x_0, y_0) to (x_1, y_1), etc.""" | 218 | specifies a polyline from (x_0, y_0) to (x_1, y_1), etc.""" |
219 | raise NotImplementedError | 219 | raise NotImplementedError |
220 | 220 | ||
221 | def fill_polyline(self, coor_list, color, thickness, snap=True): | 221 | def fill_polyline(self, coor_list, color, thickness, snap=True): |
222 | """Draws a polyline (probably a polygon) and fills it.""" | 222 | """Draws a polyline (probably a polygon) and fills it.""" |
223 | raise NotImplementedError | 223 | raise NotImplementedError |
224 | 224 | ||
225 | def draw_label(self, text, x, y, fopts=GraphFormat.DEF_FOPTS_LABEL, | 225 | def draw_label(self, text, x, y, fopts=GraphFormat.DEF_FOPTS_LABEL, |
226 | halign=AlignMode.LEFT, valign=AlignMode.BOTTOM, snap=True): | 226 | halign=AlignMode.LEFT, valign=AlignMode.BOTTOM, snap=True): |
227 | """Draws text at a position with a certain alignment.""" | 227 | """Draws text at a position with a certain alignment.""" |
228 | raise NotImplementedError | 228 | raise NotImplementedError |
229 | 229 | ||
230 | def draw_label_with_sscripts(self, text, supscript, subscript, x, y, \ | 230 | def draw_label_with_sscripts(self, text, supscript, subscript, x, y, \ |
231 | textfopts=GraphFormat.DEF_FOPTS_LABEL, | 231 | textfopts=GraphFormat.DEF_FOPTS_LABEL, |
232 | sscriptfopts=GraphFormat.DEF_FOPTS_LABEL_SSCRIPT, \ | 232 | sscriptfopts=GraphFormat.DEF_FOPTS_LABEL_SSCRIPT, \ |
@@ -234,31 +234,31 @@ class Canvas(object): | |||
234 | """Draws text at a position with a certain alignment, along with optionally a superscript and | 234 | """Draws text at a position with a certain alignment, along with optionally a superscript and |
235 | subscript (which are None if either is not used.)""" | 235 | subscript (which are None if either is not used.)""" |
236 | raise NotImplementedError | 236 | raise NotImplementedError |
237 | 237 | ||
238 | def draw_y_axis(self, x, y, height): | 238 | def draw_y_axis(self, x, y, height): |
239 | """Draws the y-axis, starting from the bottom at the point x, y.""" | 239 | """Draws the y-axis, starting from the bottom at the point x, y.""" |
240 | self.surface.ctx.set_source_rgb(0.0, 0.0, 0.0) | 240 | self.surface.ctx.set_source_rgb(0.0, 0.0, 0.0) |
241 | 241 | ||
242 | self.draw_line((x, y), (x, y - height), (0.0, 0.0, 0.0), GraphFormat.AXIS_THICKNESS) | 242 | self.draw_line((x, y), (x, y - height), (0.0, 0.0, 0.0), GraphFormat.AXIS_THICKNESS) |
243 | 243 | ||
244 | def draw_y_axis_labels(self, x, y, height, item_list, item_size, fopts=None): | 244 | def draw_y_axis_labels(self, x, y, height, item_list, item_size, fopts=None): |
245 | """Draws the item labels on the y-axis. ``item_list'' is the list | 245 | """Draws the item labels on the y-axis. ``item_list'' is the list |
246 | of strings to print, while item_size gives the vertical amount of | 246 | of strings to print, while item_size gives the vertical amount of |
247 | space that each item shall take up, in pixels.""" | 247 | space that each item shall take up, in pixels.""" |
248 | if fopts is None: | 248 | if fopts is None: |
249 | fopts = GraphFormat.DEF_FOPTS_ITEM | 249 | fopts = GraphFormat.DEF_FOPTS_ITEM |
250 | 250 | ||
251 | x -= GraphFormat.Y_AXIS_ITEM_GAP | 251 | x -= GraphFormat.Y_AXIS_ITEM_GAP |
252 | y -= height - item_size / 2.0 | 252 | y -= height - item_size / 2.0 |
253 | 253 | ||
254 | orig_color = fopts.color | 254 | orig_color = fopts.color |
255 | for ctr, item in enumerate(item_list): | 255 | for ctr, item in enumerate(item_list): |
256 | fopts.color = self.get_item_color(ctr) | 256 | fopts.color = self.get_item_color(ctr) |
257 | self.draw_label(item, x, y, fopts, AlignMode.RIGHT, AlignMode.CENTER) | 257 | self.draw_label(item, x, y, fopts, AlignMode.RIGHT, AlignMode.CENTER) |
258 | y += item_size | 258 | y += item_size |
259 | 259 | ||
260 | fopts.color = orig_color | 260 | fopts.color = orig_color |
261 | 261 | ||
262 | def draw_x_axis(self, x, y, start_tick, end_tick, maj_sep, min_per_maj): | 262 | def draw_x_axis(self, x, y, start_tick, end_tick, maj_sep, min_per_maj): |
263 | """Draws the x-axis, including all the major and minor ticks (but not the labels). | 263 | """Draws the x-axis, including all the major and minor ticks (but not the labels). |
264 | ``num_maj'' gives the number of major ticks, ``maj_sep'' the number of pixels between | 264 | ``num_maj'' gives the number of major ticks, ``maj_sep'' the number of pixels between |
@@ -271,48 +271,48 @@ class Canvas(object): | |||
271 | for i in range(start_tick, end_tick + 1): | 271 | for i in range(start_tick, end_tick + 1): |
272 | self.draw_line((x, y), (x, y + GraphFormat.MAJ_TICK_SIZE), | 272 | self.draw_line((x, y), (x, y + GraphFormat.MAJ_TICK_SIZE), |
273 | (0.0, 0.0, 0.0), GraphFormat.AXIS_THICKNESS) | 273 | (0.0, 0.0, 0.0), GraphFormat.AXIS_THICKNESS) |
274 | 274 | ||
275 | if (i < end_tick): | 275 | if (i < end_tick): |
276 | for j in range(0, min_per_maj): | 276 | for j in range(0, min_per_maj): |
277 | self.draw_line((x, y), (x + maj_sep / min_per_maj, y), | 277 | self.draw_line((x, y), (x + maj_sep / min_per_maj, y), |
278 | (0.0, 0.0, 0.0), GraphFormat.AXIS_THICKNESS) | 278 | (0.0, 0.0, 0.0), GraphFormat.AXIS_THICKNESS) |
279 | 279 | ||
280 | x += 1.0 * maj_sep / min_per_maj | 280 | x += 1.0 * maj_sep / min_per_maj |
281 | if j < min_per_maj - 1: | 281 | if j < min_per_maj - 1: |
282 | self.draw_line((x, y), (x, y + GraphFormat.MIN_TICK_SIZE), | 282 | self.draw_line((x, y), (x, y + GraphFormat.MIN_TICK_SIZE), |
283 | (0.0, 0.0, 0.0), GraphFormat.AXIS_THICKNESS) | 283 | (0.0, 0.0, 0.0), GraphFormat.AXIS_THICKNESS) |
284 | 284 | ||
285 | def draw_x_axis_labels(self, x, y, start_tick, end_tick, maj_sep, min_per_maj, start=0, incr=1, show_min=False, \ | 285 | def draw_x_axis_labels(self, x, y, start_tick, end_tick, maj_sep, min_per_maj, start=0, incr=1, show_min=False, \ |
286 | majfopts=GraphFormat.DEF_FOPTS_MAJ, minfopts=GraphFormat.DEF_FOPTS_MIN): | 286 | majfopts=GraphFormat.DEF_FOPTS_MAJ, minfopts=GraphFormat.DEF_FOPTS_MIN): |
287 | """Draws the labels for the x-axis. (x, y) should give the origin. | 287 | """Draws the labels for the x-axis. (x, y) should give the origin. |
288 | how far down you want the text. ``incr'' gives the increment per major | 288 | how far down you want the text. ``incr'' gives the increment per major |
289 | tick. ``start'' gives the value of the first tick. ``show_min'' specifies | 289 | tick. ``start'' gives the value of the first tick. ``show_min'' specifies |
290 | whether to draw labels at minor ticks.""" | 290 | whether to draw labels at minor ticks.""" |
291 | 291 | ||
292 | x += GraphFormat.X_AXIS_MEASURE_OFS + start_tick * maj_sep | 292 | x += GraphFormat.X_AXIS_MEASURE_OFS + start_tick * maj_sep |
293 | y += GraphFormat.X_AXIS_LABEL_GAP + GraphFormat.MAJ_TICK_SIZE | 293 | y += GraphFormat.X_AXIS_LABEL_GAP + GraphFormat.MAJ_TICK_SIZE |
294 | 294 | ||
295 | minincr = incr / (min_per_maj * 1.0) | 295 | minincr = incr / (min_per_maj * 1.0) |
296 | 296 | ||
297 | cur = start * 1.0 | 297 | cur = start * 1.0 |
298 | 298 | ||
299 | for i in range(start_tick, end_tick + 1): | 299 | for i in range(start_tick, end_tick + 1): |
300 | text = util.format_float(cur, 2) | 300 | text = util.format_float(cur, 2) |
301 | self.draw_label(text, x, y, majfopts, AlignMode.CENTER, AlignMode.TOP) | 301 | self.draw_label(text, x, y, majfopts, AlignMode.CENTER, AlignMode.TOP) |
302 | 302 | ||
303 | if (i < end_tick): | 303 | if (i < end_tick): |
304 | if show_min: | 304 | if show_min: |
305 | for j in range(0, min_per_maj): | 305 | for j in range(0, min_per_maj): |
306 | x += 1.0 * maj_sep / min_per_maj | 306 | x += 1.0 * maj_sep / min_per_maj |
307 | cur += minincr | 307 | cur += minincr |
308 | text = util.format_float(cur, 2) | 308 | text = util.format_float(cur, 2) |
309 | 309 | ||
310 | if j < min_per_maj - 1: | 310 | if j < min_per_maj - 1: |
311 | self.draw_label(text, x, y, minfopts, AlignMode.CENTER, AlignMode.TOP) | 311 | self.draw_label(text, x, y, minfopts, AlignMode.CENTER, AlignMode.TOP) |
312 | else: | 312 | else: |
313 | x += maj_sep | 313 | x += maj_sep |
314 | cur += incr | 314 | cur += incr |
315 | 315 | ||
316 | def draw_grid(self, x, y, height, start_tick, end_tick, start_item, end_item, maj_sep, item_size, \ | 316 | def draw_grid(self, x, y, height, start_tick, end_tick, start_item, end_item, maj_sep, item_size, \ |
317 | min_per_maj=None, show_min=False): | 317 | min_per_maj=None, show_min=False): |
318 | """Draws a grid dividing along the item boundaries and the major ticks. | 318 | """Draws a grid dividing along the item boundaries and the major ticks. |
@@ -321,22 +321,22 @@ class Canvas(object): | |||
321 | ``start_item'' and ``end_item'' give the item boundaries to start and end drawing horizontal lines.""" | 321 | ``start_item'' and ``end_item'' give the item boundaries to start and end drawing horizontal lines.""" |
322 | if start_tick > end_tick or start_item > end_item: | 322 | if start_tick > end_tick or start_item > end_item: |
323 | return | 323 | return |
324 | 324 | ||
325 | line_width = (end_tick - start_tick) * maj_sep | 325 | line_width = (end_tick - start_tick) * maj_sep |
326 | line_height = (end_item - start_item) * item_size | 326 | line_height = (end_item - start_item) * item_size |
327 | 327 | ||
328 | origin = (x, y) | 328 | origin = (x, y) |
329 | 329 | ||
330 | # draw horizontal lines first | 330 | # draw horizontal lines first |
331 | x = origin[0] + GraphFormat.X_AXIS_MEASURE_OFS + start_tick * maj_sep | 331 | x = origin[0] + GraphFormat.X_AXIS_MEASURE_OFS + start_tick * maj_sep |
332 | y = origin[1] - height + start_item * item_size | 332 | y = origin[1] - height + start_item * item_size |
333 | for i in range(start_item, end_item + 1): | 333 | for i in range(start_item, end_item + 1): |
334 | self.draw_line((x, y), (x + line_width, y), GraphFormat.GRID_COLOR, GraphFormat.GRID_THICKNESS) | 334 | self.draw_line((x, y), (x + line_width, y), GraphFormat.GRID_COLOR, GraphFormat.GRID_THICKNESS) |
335 | y += item_size | 335 | y += item_size |
336 | 336 | ||
337 | x = origin[0] + GraphFormat.X_AXIS_MEASURE_OFS + start_tick * maj_sep | 337 | x = origin[0] + GraphFormat.X_AXIS_MEASURE_OFS + start_tick * maj_sep |
338 | y = origin[1] - height + start_item * item_size | 338 | y = origin[1] - height + start_item * item_size |
339 | 339 | ||
340 | if show_min: | 340 | if show_min: |
341 | for i in range(0, (end_tick - start_tick) * min_per_maj + 1): | 341 | for i in range(0, (end_tick - start_tick) * min_per_maj + 1): |
342 | self.draw_line((x, y), (x, y + line_height), GraphFormat.GRID_COLOR, GraphFormat.GRID_THICKNESS) | 342 | self.draw_line((x, y), (x, y + line_height), GraphFormat.GRID_COLOR, GraphFormat.GRID_THICKNESS) |
@@ -345,222 +345,222 @@ class Canvas(object): | |||
345 | for i in range(start_tick, end_tick + 1): | 345 | for i in range(start_tick, end_tick + 1): |
346 | self.draw_line((x, y), (x, y + line_height), GraphFormat.GRID_COLOR, GraphFormat.GRID_THICKNESS) | 346 | self.draw_line((x, y), (x, y + line_height), GraphFormat.GRID_COLOR, GraphFormat.GRID_THICKNESS) |
347 | x += maj_sep | 347 | x += maj_sep |
348 | 348 | ||
349 | def draw_bar(self, x, y, width, height, n, clip_side, selected): | 349 | def draw_bar(self, x, y, width, height, n, clip_side, selected): |
350 | """Draws a bar with a certain set of dimensions, using pattern ``n'' from the | 350 | """Draws a bar with a certain set of dimensions, using pattern ``n'' from the |
351 | bar pattern list.""" | 351 | bar pattern list.""" |
352 | 352 | ||
353 | color, thickness = {False : (GraphFormat.BORDER_COLOR, GraphFormat.BORDER_THICKNESS), | 353 | color, thickness = {False : (GraphFormat.BORDER_COLOR, GraphFormat.BORDER_THICKNESS), |
354 | True : (GraphFormat.HIGHLIGHT_COLOR, GraphFormat.BORDER_THICKNESS * 2.0)}[selected] | 354 | True : (GraphFormat.HIGHLIGHT_COLOR, GraphFormat.BORDER_THICKNESS * 2.0)}[selected] |
355 | 355 | ||
356 | # use a pattern to be pretty | 356 | # use a pattern to be pretty |
357 | self.get_bar_pattern(n).render_on_canvas(self, x, y, width, height, True) | 357 | self.get_bar_pattern(n).render_on_canvas(self, x, y, width, height, True) |
358 | 358 | ||
359 | self.draw_rect(x, y, width, height, color, thickness, clip_side) | 359 | self.draw_rect(x, y, width, height, color, thickness, clip_side) |
360 | 360 | ||
361 | def add_sel_bar(self, x, y, width, height, event): | 361 | def add_sel_bar(self, x, y, width, height, event): |
362 | self.add_sel_region(SelectableRegion(x, y, width, height, event)) | 362 | self.add_sel_region(SelectableRegion(x, y, width, height, event)) |
363 | 363 | ||
364 | def draw_mini_bar(self, x, y, width, height, n, clip_side, selected): | 364 | def draw_mini_bar(self, x, y, width, height, n, clip_side, selected): |
365 | """Like the above, except it draws a miniature version. This is usually used for | 365 | """Like the above, except it draws a miniature version. This is usually used for |
366 | secondary purposes (i.e. to show jobs that _should_ have been running at a certain time). | 366 | secondary purposes (i.e. to show jobs that _should_ have been running at a certain time). |
367 | 367 | ||
368 | Of course we don't enforce the fact that this is mini, since the user can pass in width | 368 | Of course we don't enforce the fact that this is mini, since the user can pass in width |
369 | and height (but the mini bars do look slightly different: namely the borders are a different | 369 | and height (but the mini bars do look slightly different: namely the borders are a different |
370 | color)""" | 370 | color)""" |
371 | 371 | ||
372 | color, thickness = {False : (GraphFormat.LITE_BORDER_COLOR, GraphFormat.BORDER_THICKNESS), | 372 | color, thickness = {False : (GraphFormat.LITE_BORDER_COLOR, GraphFormat.BORDER_THICKNESS), |
373 | True : (GraphFormat.HIGHLIGHT_COLOR, GraphFormat.BORDER_THICKNESS * 1.5)}[selected] | 373 | True : (GraphFormat.HIGHLIGHT_COLOR, GraphFormat.BORDER_THICKNESS * 1.5)}[selected] |
374 | 374 | ||
375 | self.get_bar_pattern(n).render_on_canvas(self, x, y, width, height, True) | 375 | self.get_bar_pattern(n).render_on_canvas(self, x, y, width, height, True) |
376 | 376 | ||
377 | self.draw_rect(x, y, width, height, color, thickness, clip_side) | 377 | self.draw_rect(x, y, width, height, color, thickness, clip_side) |
378 | 378 | ||
379 | def add_sel_mini_bar(self, x, y, width, height, event): | 379 | def add_sel_mini_bar(self, x, y, width, height, event): |
380 | self.add_sel_region(SelectableRegion(x, y, width, height, event)) | 380 | self.add_sel_region(SelectableRegion(x, y, width, height, event)) |
381 | 381 | ||
382 | def draw_completion_marker(self, x, y, height, selected): | 382 | def draw_completion_marker(self, x, y, height, selected): |
383 | """Draws the symbol that represents a job completion, using a certain height.""" | 383 | """Draws the symbol that represents a job completion, using a certain height.""" |
384 | 384 | ||
385 | color = {False : GraphFormat.BORDER_COLOR, True : GraphFormat.HIGHLIGHT_COLOR}[selected] | 385 | color = {False : GraphFormat.BORDER_COLOR, True : GraphFormat.HIGHLIGHT_COLOR}[selected] |
386 | self.draw_line((x - height * GraphFormat.TEE_FACTOR / 2.0, y), | 386 | self.draw_line((x - height * GraphFormat.TEE_FACTOR / 2.0, y), |
387 | (x + height * GraphFormat.TEE_FACTOR / 2.0, y), | 387 | (x + height * GraphFormat.TEE_FACTOR / 2.0, y), |
388 | color, GraphFormat.BORDER_THICKNESS) | 388 | color, GraphFormat.BORDER_THICKNESS) |
389 | self.draw_line((x, y), (x, y + height), color, GraphFormat.BORDER_THICKNESS) | 389 | self.draw_line((x, y), (x, y + height), color, GraphFormat.BORDER_THICKNESS) |
390 | 390 | ||
391 | def add_sel_completion_marker(self, x, y, height, event): | 391 | def add_sel_completion_marker(self, x, y, height, event): |
392 | self.add_sel_region(SelectableRegion(x - height * GraphFormat.TEE_FACTOR / 2.0, y, | 392 | self.add_sel_region(SelectableRegion(x - height * GraphFormat.TEE_FACTOR / 2.0, y, |
393 | height * GraphFormat.TEE_FACTOR, height, event)) | 393 | height * GraphFormat.TEE_FACTOR, height, event)) |
394 | 394 | ||
395 | def draw_release_arrow_big(self, x, y, height, selected): | 395 | def draw_release_arrow_big(self, x, y, height, selected): |
396 | """Draws a release arrow of a certain height: (x, y) should give the top | 396 | """Draws a release arrow of a certain height: (x, y) should give the top |
397 | (northernmost point) of the arrow. The height includes the arrowhead.""" | 397 | (northernmost point) of the arrow. The height includes the arrowhead.""" |
398 | big_arrowhead_height = GraphFormat.BIG_ARROWHEAD_FACTOR * height | 398 | big_arrowhead_height = GraphFormat.BIG_ARROWHEAD_FACTOR * height |
399 | 399 | ||
400 | color = {False : GraphFormat.BORDER_COLOR, True : GraphFormat.HIGHLIGHT_COLOR}[selected] | 400 | color = {False : GraphFormat.BORDER_COLOR, True : GraphFormat.HIGHLIGHT_COLOR}[selected] |
401 | colors = [(1.0, 1.0, 1.0), color] | 401 | colors = [(1.0, 1.0, 1.0), color] |
402 | draw_funcs = [self.__class__.fill_polyline, self.__class__.draw_polyline] | 402 | draw_funcs = [self.__class__.fill_polyline, self.__class__.draw_polyline] |
403 | for i in range(0, 2): | 403 | for i in range(0, 2): |
404 | color = colors[i] | 404 | color = colors[i] |
405 | draw_func = draw_funcs[i] | 405 | draw_func = draw_funcs[i] |
406 | 406 | ||
407 | draw_func(self, [(x, y), (x - big_arrowhead_height / Canvas.SQRT3, y + big_arrowhead_height), \ | 407 | draw_func(self, [(x, y), (x - big_arrowhead_height / Canvas.SQRT3, y + big_arrowhead_height), \ |
408 | (x + big_arrowhead_height / Canvas.SQRT3, y + big_arrowhead_height), (x, y)], \ | 408 | (x + big_arrowhead_height / Canvas.SQRT3, y + big_arrowhead_height), (x, y)], \ |
409 | color, GraphFormat.BORDER_THICKNESS) | 409 | color, GraphFormat.BORDER_THICKNESS) |
410 | 410 | ||
411 | self.draw_line((x, y + big_arrowhead_height), (x, y + height), color, GraphFormat.BORDER_THICKNESS) | 411 | self.draw_line((x, y + big_arrowhead_height), (x, y + height), color, GraphFormat.BORDER_THICKNESS) |
412 | 412 | ||
413 | def add_sel_release_arrow_big(self, x, y, height, event): | 413 | def add_sel_release_arrow_big(self, x, y, height, event): |
414 | self.add_sel_arrow_big(x, y, height, event) | 414 | self.add_sel_arrow_big(x, y, height, event) |
415 | 415 | ||
416 | def draw_deadline_arrow_big(self, x, y, height, selected): | 416 | def draw_deadline_arrow_big(self, x, y, height, selected): |
417 | """Draws a release arrow: x, y should give the top (northernmost | 417 | """Draws a release arrow: x, y should give the top (northernmost |
418 | point) of the arrow. The height includes the arrowhead.""" | 418 | point) of the arrow. The height includes the arrowhead.""" |
419 | big_arrowhead_height = GraphFormat.BIG_ARROWHEAD_FACTOR * height | 419 | big_arrowhead_height = GraphFormat.BIG_ARROWHEAD_FACTOR * height |
420 | 420 | ||
421 | color = {False : GraphFormat.BORDER_COLOR, True : GraphFormat.HIGHLIGHT_COLOR}[selected] | 421 | color = {False : GraphFormat.BORDER_COLOR, True : GraphFormat.HIGHLIGHT_COLOR}[selected] |
422 | colors = [(1.0, 1.0, 1.0), color] | 422 | colors = [(1.0, 1.0, 1.0), color] |
423 | draw_funcs = [self.__class__.fill_polyline, self.__class__.draw_polyline] | 423 | draw_funcs = [self.__class__.fill_polyline, self.__class__.draw_polyline] |
424 | for i in range(0, 2): | 424 | for i in range(0, 2): |
425 | color = colors[i] | 425 | color = colors[i] |
426 | draw_func = draw_funcs[i] | 426 | draw_func = draw_funcs[i] |
427 | 427 | ||
428 | draw_func(self, [(x, y + height), (x - big_arrowhead_height / Canvas.SQRT3, \ | 428 | draw_func(self, [(x, y + height), (x - big_arrowhead_height / Canvas.SQRT3, \ |
429 | y + height - big_arrowhead_height), \ | 429 | y + height - big_arrowhead_height), \ |
430 | (x + big_arrowhead_height / Canvas.SQRT3, \ | 430 | (x + big_arrowhead_height / Canvas.SQRT3, \ |
431 | y + height - big_arrowhead_height), \ | 431 | y + height - big_arrowhead_height), \ |
432 | (x, y + height)], color, GraphFormat.BORDER_THICKNESS) | 432 | (x, y + height)], color, GraphFormat.BORDER_THICKNESS) |
433 | 433 | ||
434 | self.draw_line((x, y), (x, y + height - big_arrowhead_height), | 434 | self.draw_line((x, y), (x, y + height - big_arrowhead_height), |
435 | color, GraphFormat.BORDER_THICKNESS) | 435 | color, GraphFormat.BORDER_THICKNESS) |
436 | 436 | ||
437 | def add_sel_deadline_arrow_big(self, x, y, height, event): | 437 | def add_sel_deadline_arrow_big(self, x, y, height, event): |
438 | self.add_sel_arrow_big(x, y, height, event) | 438 | self.add_sel_arrow_big(x, y, height, event) |
439 | 439 | ||
440 | def add_sel_arrow_big(self, x, y, height, event): | 440 | def add_sel_arrow_big(self, x, y, height, event): |
441 | big_arrowhead_height = GraphFormat.BIG_ARROWHEAD_FACTOR * height | 441 | big_arrowhead_height = GraphFormat.BIG_ARROWHEAD_FACTOR * height |
442 | 442 | ||
443 | self.add_sel_region(SelectableRegion(x - big_arrowhead_height / Canvas.SQRT3, | 443 | self.add_sel_region(SelectableRegion(x - big_arrowhead_height / Canvas.SQRT3, |
444 | y, 2.0 * big_arrowhead_height / Canvas.SQRT3, height, event)) | 444 | y, 2.0 * big_arrowhead_height / Canvas.SQRT3, height, event)) |
445 | 445 | ||
446 | def draw_release_arrow_small(self, x, y, height, selected): | 446 | def draw_release_arrow_small(self, x, y, height, selected): |
447 | """Draws a small release arrow (most likely coming off the x-axis, although | 447 | """Draws a small release arrow (most likely coming off the x-axis, although |
448 | this method doesn't enforce this): x, y should give the top of the arrow""" | 448 | this method doesn't enforce this): x, y should give the top of the arrow""" |
449 | small_arrowhead_height = GraphFormat.SMALL_ARROWHEAD_FACTOR * height | 449 | small_arrowhead_height = GraphFormat.SMALL_ARROWHEAD_FACTOR * height |
450 | 450 | ||
451 | color = {False : GraphFormat.BORDER_COLOR, True : GraphFormat.HIGHLIGHT_COLOR}[selected] | 451 | color = {False : GraphFormat.BORDER_COLOR, True : GraphFormat.HIGHLIGHT_COLOR}[selected] |
452 | 452 | ||
453 | self.draw_line((x, y), (x - small_arrowhead_height, y + small_arrowhead_height), \ | 453 | self.draw_line((x, y), (x - small_arrowhead_height, y + small_arrowhead_height), \ |
454 | color, GraphFormat.BORDER_THICKNESS) | 454 | color, GraphFormat.BORDER_THICKNESS) |
455 | self.draw_line((x, y), (x + small_arrowhead_height, y + small_arrowhead_height), \ | 455 | self.draw_line((x, y), (x + small_arrowhead_height, y + small_arrowhead_height), \ |
456 | color, GraphFormat.BORDER_THICKNESS) | 456 | color, GraphFormat.BORDER_THICKNESS) |
457 | self.draw_line((x, y), (x, y + height), color, GraphFormat.BORDER_THICKNESS) | 457 | self.draw_line((x, y), (x, y + height), color, GraphFormat.BORDER_THICKNESS) |
458 | 458 | ||
459 | def add_sel_release_arrow_small(self, x, y, height, event): | 459 | def add_sel_release_arrow_small(self, x, y, height, event): |
460 | self.add_sel_arrow_small(x, y, height, event) | 460 | self.add_sel_arrow_small(x, y, height, event) |
461 | 461 | ||
462 | def draw_deadline_arrow_small(self, x, y, height, selected): | 462 | def draw_deadline_arrow_small(self, x, y, height, selected): |
463 | """Draws a small deadline arrow (most likely coming off the x-axis, although | 463 | """Draws a small deadline arrow (most likely coming off the x-axis, although |
464 | this method doesn't enforce this): x, y should give the top of the arrow""" | 464 | this method doesn't enforce this): x, y should give the top of the arrow""" |
465 | small_arrowhead_height = GraphFormat.SMALL_ARROWHEAD_FACTOR * height | 465 | small_arrowhead_height = GraphFormat.SMALL_ARROWHEAD_FACTOR * height |
466 | 466 | ||
467 | color = {False : GraphFormat.BORDER_COLOR, True : GraphFormat.HIGHLIGHT_COLOR}[selected] | 467 | color = {False : GraphFormat.BORDER_COLOR, True : GraphFormat.HIGHLIGHT_COLOR}[selected] |
468 | 468 | ||
469 | self.draw_line((x, y), (x, y + height), color, GraphFormat.BORDER_THICKNESS) | 469 | self.draw_line((x, y), (x, y + height), color, GraphFormat.BORDER_THICKNESS) |
470 | self.draw_line((x - small_arrowhead_height, y + height - small_arrowhead_height), \ | 470 | self.draw_line((x - small_arrowhead_height, y + height - small_arrowhead_height), \ |
471 | (x, y + height), color, GraphFormat.BORDER_THICKNESS) | 471 | (x, y + height), color, GraphFormat.BORDER_THICKNESS) |
472 | self.draw_line((x + small_arrowhead_height, y + height - small_arrowhead_height), \ | 472 | self.draw_line((x + small_arrowhead_height, y + height - small_arrowhead_height), \ |
473 | (x, y + height), color, GraphFormat.BORDER_THICKNESS) | 473 | (x, y + height), color, GraphFormat.BORDER_THICKNESS) |
474 | 474 | ||
475 | def add_sel_deadline_arrow_small(self, x, y, height, event): | 475 | def add_sel_deadline_arrow_small(self, x, y, height, event): |
476 | self.add_sel_arrow_small(x, y, height, event) | 476 | self.add_sel_arrow_small(x, y, height, event) |
477 | 477 | ||
478 | def add_sel_arrow_small(self, x, y, height, event): | 478 | def add_sel_arrow_small(self, x, y, height, event): |
479 | small_arrowhead_height = GraphFormat.SMALL_ARROWHEAD_FACTOR * height | 479 | small_arrowhead_height = GraphFormat.SMALL_ARROWHEAD_FACTOR * height |
480 | 480 | ||
481 | self.add_sel_region(SelectableRegion(x - small_arrowhead_height, y, | 481 | self.add_sel_region(SelectableRegion(x - small_arrowhead_height, y, |
482 | small_arrowhead_height * 2.0, height, event)) | 482 | small_arrowhead_height * 2.0, height, event)) |
483 | 483 | ||
484 | def draw_suspend_triangle(self, x, y, height, selected): | 484 | def draw_suspend_triangle(self, x, y, height, selected): |
485 | """Draws the triangle that marks a suspension. (x, y) gives the topmost (northernmost) point | 485 | """Draws the triangle that marks a suspension. (x, y) gives the topmost (northernmost) point |
486 | of the symbol.""" | 486 | of the symbol.""" |
487 | 487 | ||
488 | color = {False : GraphFormat.BORDER_COLOR, True : GraphFormat.HIGHLIGHT_COLOR}[selected] | 488 | color = {False : GraphFormat.BORDER_COLOR, True : GraphFormat.HIGHLIGHT_COLOR}[selected] |
489 | colors = [(0.0, 0.0, 0.0), color] | 489 | colors = [(0.0, 0.0, 0.0), color] |
490 | 490 | ||
491 | draw_funcs = [self.__class__.fill_polyline, self.__class__.draw_polyline] | 491 | draw_funcs = [self.__class__.fill_polyline, self.__class__.draw_polyline] |
492 | for i in range(0, 2): | 492 | for i in range(0, 2): |
493 | color = colors[i] | 493 | color = colors[i] |
494 | draw_func = draw_funcs[i] | 494 | draw_func = draw_funcs[i] |
495 | draw_func(self, [(x, y), (x + height / 2.0, y + height / 2.0), (x, y + height), (x, y)], \ | 495 | draw_func(self, [(x, y), (x + height / 2.0, y + height / 2.0), (x, y + height), (x, y)], \ |
496 | color, GraphFormat.BORDER_THICKNESS) | 496 | color, GraphFormat.BORDER_THICKNESS) |
497 | 497 | ||
498 | def add_sel_suspend_triangle(self, x, y, height, event): | 498 | def add_sel_suspend_triangle(self, x, y, height, event): |
499 | self.add_sel_region(SelectableRegion(x, y, height / 2.0, height, event)) | 499 | self.add_sel_region(SelectableRegion(x, y, height / 2.0, height, event)) |
500 | 500 | ||
501 | def draw_resume_triangle(self, x, y, height, selected): | 501 | def draw_resume_triangle(self, x, y, height, selected): |
502 | """Draws the triangle that marks a resumption. (x, y) gives the topmost (northernmost) point | 502 | """Draws the triangle that marks a resumption. (x, y) gives the topmost (northernmost) point |
503 | of the symbol.""" | 503 | of the symbol.""" |
504 | 504 | ||
505 | color = {False : GraphFormat.BORDER_COLOR, True : GraphFormat.HIGHLIGHT_COLOR}[selected] | 505 | color = {False : GraphFormat.BORDER_COLOR, True : GraphFormat.HIGHLIGHT_COLOR}[selected] |
506 | colors = [(1.0, 1.0, 1.0), color] | 506 | colors = [(1.0, 1.0, 1.0), color] |
507 | 507 | ||
508 | draw_funcs = [self.__class__.fill_polyline, self.__class__.draw_polyline] | 508 | draw_funcs = [self.__class__.fill_polyline, self.__class__.draw_polyline] |
509 | for i in range(0, 2): | 509 | for i in range(0, 2): |
510 | color = colors[i] | 510 | color = colors[i] |
511 | draw_func = draw_funcs[i] | 511 | draw_func = draw_funcs[i] |
512 | draw_func(self, [(x, y), (x - height / 2.0, y + height / 2.0), (x, y + height), (x, y)], \ | 512 | draw_func(self, [(x, y), (x - height / 2.0, y + height / 2.0), (x, y + height), (x, y)], \ |
513 | color, GraphFormat.BORDER_THICKNESS) | 513 | color, GraphFormat.BORDER_THICKNESS) |
514 | 514 | ||
515 | def add_sel_resume_triangle(self, x, y, height, event): | 515 | def add_sel_resume_triangle(self, x, y, height, event): |
516 | self.add_sel_region(SelectableRegion(x - height / 2.0, y, height / 2.0, height, event)) | 516 | self.add_sel_region(SelectableRegion(x - height / 2.0, y, height / 2.0, height, event)) |
517 | 517 | ||
518 | def clear_selectable_regions(self): | 518 | def clear_selectable_regions(self): |
519 | self.selectable_regions = {} | 519 | self.selectable_regions = {} |
520 | 520 | ||
521 | #def clear_selectable_regions(self, real_x, real_y, width, height): | 521 | #def clear_selectable_regions(self, real_x, real_y, width, height): |
522 | # x, y = self.surface.get_virt_coor(real_x, real_y) | 522 | # x, y = self.surface.get_virt_coor(real_x, real_y) |
523 | # for event in self.selectable_regions.keys(): | 523 | # for event in self.selectable_regions.keys(): |
524 | # if self.selectable_regions[event].intersects(x, y, width, height): | 524 | # if self.selectable_regions[event].intersects(x, y, width, height): |
525 | # del self.selectable_regions[event] | 525 | # del self.selectable_regions[event] |
526 | 526 | ||
527 | def add_sel_region(self, region): | 527 | def add_sel_region(self, region): |
528 | region.set_scale(self.scale) | 528 | region.set_scale(self.scale) |
529 | self.selectable_regions[region.get_event()] = region | 529 | self.selectable_regions[region.get_event()] = region |
530 | 530 | ||
531 | def get_sel_region(self, event): | 531 | def get_sel_region(self, event): |
532 | return self.selectable_regions[event] | 532 | return self.selectable_regions[event] |
533 | 533 | ||
534 | def has_sel_region(self, event): | 534 | def has_sel_region(self, event): |
535 | return event in self.selectable_regions | 535 | return event in self.selectable_regions |
536 | 536 | ||
537 | def get_selected_regions(self, real_x, real_y, width, height): | 537 | def get_selected_regions(self, real_x, real_y, width, height): |
538 | x, y = self.surface.get_virt_coor(real_x, real_y) | 538 | x, y = self.surface.get_virt_coor(real_x, real_y) |
539 | 539 | ||
540 | selected = {} | 540 | selected = {} |
541 | for event in self.selectable_regions: | 541 | for event in self.selectable_regions: |
542 | region = self.selectable_regions[event] | 542 | region = self.selectable_regions[event] |
543 | if region.intersects(x, y, width, height): | 543 | if region.intersects(x, y, width, height): |
544 | selected[event] = region | 544 | selected[event] = region |
545 | 545 | ||
546 | return selected | 546 | return selected |
547 | 547 | ||
548 | def whiteout(self): | 548 | def whiteout(self): |
549 | """Overwrites the surface completely white, but technically doesn't delete anything""" | 549 | """Overwrites the surface completely white, but technically doesn't delete anything""" |
550 | # Make sure we don't scale here (we want to literally white out just this region) | 550 | # Make sure we don't scale here (we want to literally white out just this region) |
551 | 551 | ||
552 | x, y = self.surface.get_virt_coor_unscaled(0, 0) | 552 | x, y = self.surface.get_virt_coor_unscaled(0, 0) |
553 | width, height = self.unscaled(self.surface.width, self.surface.height) | 553 | width, height = self.unscaled(self.surface.width, self.surface.height) |
554 | 554 | ||
555 | self.fill_rect(x, y, width, height, (1.0, 1.0, 1.0), False) | 555 | self.fill_rect(x, y, width, height, (1.0, 1.0, 1.0), False) |
556 | 556 | ||
557 | def get_item_color(self, n): | 557 | def get_item_color(self, n): |
558 | """Gets the nth color in the item color list, which are the colors used to draw the items | 558 | """Gets the nth color in the item color list, which are the colors used to draw the items |
559 | on the y-axis. Note that there are conceptually infinitely | 559 | on the y-axis. Note that there are conceptually infinitely |
560 | many patterns because the patterns repeat -- that is, we just mod out by the size of the pattern | 560 | many patterns because the patterns repeat -- that is, we just mod out by the size of the pattern |
561 | list when indexing.""" | 561 | list when indexing.""" |
562 | return self.item_clist[n % len(self.item_clist)] | 562 | return self.item_clist[n % len(self.item_clist)] |
563 | 563 | ||
564 | def get_bar_pattern(self, n): | 564 | def get_bar_pattern(self, n): |
565 | """Gets the nth pattern in the bar pattern list, which is a list of surfaces that are used to | 565 | """Gets the nth pattern in the bar pattern list, which is a list of surfaces that are used to |
566 | fill in the bars. Note that there are conceptually infinitely | 566 | fill in the bars. Note that there are conceptually infinitely |
@@ -574,38 +574,38 @@ class CairoCanvas(Canvas): | |||
574 | """This is a basic class that stores and draws on a Cairo surface, | 574 | """This is a basic class that stores and draws on a Cairo surface, |
575 | using various primitives related to drawing a real-time graph (up-arrows, | 575 | using various primitives related to drawing a real-time graph (up-arrows, |
576 | down-arrows, bars, ...). | 576 | down-arrows, bars, ...). |
577 | 577 | ||
578 | This is the lowest-level non-abstract representation | 578 | This is the lowest-level non-abstract representation |
579 | (aside perhaps from the Cairo surface itself) of a real-time graph. | 579 | (aside perhaps from the Cairo surface itself) of a real-time graph. |
580 | It allows the user to draw primitives at certain locations, but for | 580 | It allows the user to draw primitives at certain locations, but for |
581 | the most part does not know anything about real-time scheduling, | 581 | the most part does not know anything about real-time scheduling, |
582 | just how to draw the basic parts that make up a schedule graph. | 582 | just how to draw the basic parts that make up a schedule graph. |
583 | For that, see Graph or its descendants.""" | 583 | For that, see Graph or its descendants.""" |
584 | 584 | ||
585 | #def __init__(self, fname, width, height, item_clist, bar_plist, surface): | 585 | #def __init__(self, fname, width, height, item_clist, bar_plist, surface): |
586 | # """Creates a new Canvas of dimensions (width, height). The | 586 | # """Creates a new Canvas of dimensions (width, height). The |
587 | # parameters ``item_plist'' and ``bar_plist'' each specify a list | 587 | # parameters ``item_plist'' and ``bar_plist'' each specify a list |
588 | # of patterns to choose from when drawing the items on the y-axis | 588 | # of patterns to choose from when drawing the items on the y-axis |
589 | # or filling in bars, respectively.""" | 589 | # or filling in bars, respectively.""" |
590 | 590 | ||
591 | # super(CairoCanvas, self).__init__(fname, width, height, item_clist, bar_plist, surface) | 591 | # super(CairoCanvas, self).__init__(fname, width, height, item_clist, bar_plist, surface) |
592 | 592 | ||
593 | #def clear(self): | 593 | #def clear(self): |
594 | # self.surface = self.SurfaceType(self.width, self.height, self.fname) | 594 | # self.surface = self.SurfaceType(self.width, self.height, self.fname) |
595 | # self.whiteout() | 595 | # self.whiteout() |
596 | 596 | ||
597 | def get_surface(self): | 597 | def get_surface(self): |
598 | """Gets the Surface that we are drawing on in its current state.""" | 598 | """Gets the Surface that we are drawing on in its current state.""" |
599 | return self.surface | 599 | return self.surface |
600 | 600 | ||
601 | def _rect_common(self, x, y, width, height, color, thickness, clip_side=None, do_snap=True): | 601 | def _rect_common(self, x, y, width, height, color, thickness, clip_side=None, do_snap=True): |
602 | EXTRA_FACTOR = 2.0 | 602 | EXTRA_FACTOR = 2.0 |
603 | 603 | ||
604 | x, y, width, height = self.scaled(x, y, width, height) | 604 | x, y, width, height = self.scaled(x, y, width, height) |
605 | x, y = self.surface.get_real_coor(x, y) | 605 | x, y = self.surface.get_real_coor(x, y) |
606 | max_width = self.surface.width + EXTRA_FACTOR * thickness | 606 | max_width = self.surface.width + EXTRA_FACTOR * thickness |
607 | max_height = self.surface.height + EXTRA_FACTOR * thickness | 607 | max_height = self.surface.height + EXTRA_FACTOR * thickness |
608 | 608 | ||
609 | # if dimensions are really large this can cause Cairo problems -- | 609 | # if dimensions are really large this can cause Cairo problems -- |
610 | # so clip it to the size of the surface, which is the only part we see anyway | 610 | # so clip it to the size of the surface, which is the only part we see anyway |
611 | if x < 0: | 611 | if x < 0: |
@@ -618,11 +618,11 @@ class CairoCanvas(Canvas): | |||
618 | width = max_width | 618 | width = max_width |
619 | if height > max_height: | 619 | if height > max_height: |
620 | height = max_height | 620 | height = max_height |
621 | 621 | ||
622 | if do_snap: | 622 | if do_snap: |
623 | x = snap(x) | 623 | x = snap(x) |
624 | y = snap(y) | 624 | y = snap(y) |
625 | 625 | ||
626 | if clip_side == AlignMode.LEFT: | 626 | if clip_side == AlignMode.LEFT: |
627 | self.surface.ctx.move_to(x, y) | 627 | self.surface.ctx.move_to(x, y) |
628 | self.surface.ctx.line_to(x + width, y) | 628 | self.surface.ctx.line_to(x + width, y) |
@@ -636,23 +636,23 @@ class CairoCanvas(Canvas): | |||
636 | else: | 636 | else: |
637 | # don't clip one edge of the rectangle -- just draw a Cairo rectangle | 637 | # don't clip one edge of the rectangle -- just draw a Cairo rectangle |
638 | self.surface.ctx.rectangle(x, y, width, height) | 638 | self.surface.ctx.rectangle(x, y, width, height) |
639 | 639 | ||
640 | self.surface.ctx.set_line_width(thickness * self.scale) | 640 | self.surface.ctx.set_line_width(thickness * self.scale) |
641 | self.surface.ctx.set_source_rgb(color[0], color[1], color[2]) | 641 | self.surface.ctx.set_source_rgb(color[0], color[1], color[2]) |
642 | 642 | ||
643 | def draw_rect(self, x, y, width, height, color, thickness, clip_side=None, do_snap=True): | 643 | def draw_rect(self, x, y, width, height, color, thickness, clip_side=None, do_snap=True): |
644 | self._rect_common(x, y, width, height, color, thickness, clip_side, do_snap) | 644 | self._rect_common(x, y, width, height, color, thickness, clip_side, do_snap) |
645 | self.surface.ctx.stroke() | 645 | self.surface.ctx.stroke() |
646 | 646 | ||
647 | def fill_rect(self, x, y, width, height, color, do_snap=True): | 647 | def fill_rect(self, x, y, width, height, color, do_snap=True): |
648 | self._rect_common(x, y, width, height, color, 1, do_snap) | 648 | self._rect_common(x, y, width, height, color, 1, do_snap) |
649 | self.surface.ctx.fill() | 649 | self.surface.ctx.fill() |
650 | 650 | ||
651 | def fill_rect_fade(self, x, y, width, height, lcolor, rcolor, do_snap=True): | 651 | def fill_rect_fade(self, x, y, width, height, lcolor, rcolor, do_snap=True): |
652 | """Draws a rectangle somewhere, filled in with the fade.""" | 652 | """Draws a rectangle somewhere, filled in with the fade.""" |
653 | x, y, width, height = self.scaled(x, y, width, height) | 653 | x, y, width, height = self.scaled(x, y, width, height) |
654 | x, y = self.surface.get_real_coor(x, y) | 654 | x, y = self.surface.get_real_coor(x, y) |
655 | 655 | ||
656 | if do_snap: | 656 | if do_snap: |
657 | linear = cairo.LinearGradient(snap(x), snap(y), \ | 657 | linear = cairo.LinearGradient(snap(x), snap(y), \ |
658 | snap(x + width), snap(y + height)) | 658 | snap(x + width), snap(y + height)) |
@@ -667,7 +667,7 @@ class CairoCanvas(Canvas): | |||
667 | else: | 667 | else: |
668 | self.surface.ctx.rectangle(x, y, width, height) | 668 | self.surface.ctx.rectangle(x, y, width, height) |
669 | self.surface.ctx.fill() | 669 | self.surface.ctx.fill() |
670 | 670 | ||
671 | def draw_line(self, p0, p1, color, thickness, do_snap=True): | 671 | def draw_line(self, p0, p1, color, thickness, do_snap=True): |
672 | """Draws a line from p0 to p1 with a certain color and thickness.""" | 672 | """Draws a line from p0 to p1 with a certain color and thickness.""" |
673 | p0 = self.scaled(p0[0], p0[1]) | 673 | p0 = self.scaled(p0[0], p0[1]) |
@@ -677,36 +677,36 @@ class CairoCanvas(Canvas): | |||
677 | if do_snap: | 677 | if do_snap: |
678 | p0 = (snap(p0[0]), snap(p0[1])) | 678 | p0 = (snap(p0[0]), snap(p0[1])) |
679 | p1 = (snap(p1[0]), snap(p1[1])) | 679 | p1 = (snap(p1[0]), snap(p1[1])) |
680 | 680 | ||
681 | self.surface.ctx.move_to(p0[0], p0[1]) | 681 | self.surface.ctx.move_to(p0[0], p0[1]) |
682 | self.surface.ctx.line_to(p1[0], p1[1]) | 682 | self.surface.ctx.line_to(p1[0], p1[1]) |
683 | self.surface.ctx.set_source_rgb(color[0], color[1], color[2]) | 683 | self.surface.ctx.set_source_rgb(color[0], color[1], color[2]) |
684 | self.surface.ctx.set_line_width(thickness * self.scale) | 684 | self.surface.ctx.set_line_width(thickness * self.scale) |
685 | self.surface.ctx.stroke() | 685 | self.surface.ctx.stroke() |
686 | 686 | ||
687 | def _polyline_common(self, coor_list, color, thickness, do_snap=True): | 687 | def _polyline_common(self, coor_list, color, thickness, do_snap=True): |
688 | scaled_coor_list = [self.scaled(coor[0], coor[1]) for coor in coor_list] | 688 | scaled_coor_list = [self.scaled(coor[0], coor[1]) for coor in coor_list] |
689 | real_coor_list = [self.surface.get_real_coor(coor[0], coor[1]) for coor in scaled_coor_list] | 689 | real_coor_list = [self.surface.get_real_coor(coor[0], coor[1]) for coor in scaled_coor_list] |
690 | 690 | ||
691 | self.surface.ctx.move_to(real_coor_list[0][0], real_coor_list[0][1]) | 691 | self.surface.ctx.move_to(real_coor_list[0][0], real_coor_list[0][1]) |
692 | if do_snap: | 692 | if do_snap: |
693 | for i in range(0, len(real_coor_list)): | 693 | for i in range(0, len(real_coor_list)): |
694 | real_coor_list[i] = (snap(real_coor_list[i][0]), snap(real_coor_list[i][1])) | 694 | real_coor_list[i] = (snap(real_coor_list[i][0]), snap(real_coor_list[i][1])) |
695 | 695 | ||
696 | for coor in real_coor_list[1:]: | 696 | for coor in real_coor_list[1:]: |
697 | self.surface.ctx.line_to(coor[0], coor[1]) | 697 | self.surface.ctx.line_to(coor[0], coor[1]) |
698 | 698 | ||
699 | self.surface.ctx.set_line_width(thickness * self.scale) | 699 | self.surface.ctx.set_line_width(thickness * self.scale) |
700 | self.surface.ctx.set_source_rgb(color[0], color[1], color[2]) | 700 | self.surface.ctx.set_source_rgb(color[0], color[1], color[2]) |
701 | 701 | ||
702 | def draw_polyline(self, coor_list, color, thickness, do_snap=True): | 702 | def draw_polyline(self, coor_list, color, thickness, do_snap=True): |
703 | self._polyline_common(coor_list, color, thickness, do_snap) | 703 | self._polyline_common(coor_list, color, thickness, do_snap) |
704 | self.surface.ctx.stroke() | 704 | self.surface.ctx.stroke() |
705 | 705 | ||
706 | def fill_polyline(self, coor_list, color, thickness, do_snap=True): | 706 | def fill_polyline(self, coor_list, color, thickness, do_snap=True): |
707 | self._polyline_common(coor_list, color, thickness, do_snap) | 707 | self._polyline_common(coor_list, color, thickness, do_snap) |
708 | self.surface.ctx.fill() | 708 | self.surface.ctx.fill() |
709 | 709 | ||
710 | def _draw_label_common(self, text, x, y, fopts, x_bearing_factor, \ | 710 | def _draw_label_common(self, text, x, y, fopts, x_bearing_factor, \ |
711 | f_descent_factor, width_factor, f_height_factor, do_snap=True): | 711 | f_descent_factor, width_factor, f_height_factor, do_snap=True): |
712 | """Helper function for drawing a label with some alignment. Instead of taking in an alignment, | 712 | """Helper function for drawing a label with some alignment. Instead of taking in an alignment, |
@@ -714,30 +714,30 @@ class CairoCanvas(Canvas): | |||
714 | the x and y parameters. Only should be used internally.""" | 714 | the x and y parameters. Only should be used internally.""" |
715 | x, y = self.scaled(x, y) | 715 | x, y = self.scaled(x, y) |
716 | x, y = self.surface.get_real_coor(x, y) | 716 | x, y = self.surface.get_real_coor(x, y) |
717 | 717 | ||
718 | self.surface.ctx.set_source_rgb(0.0, 0.0, 0.0) | 718 | self.surface.ctx.set_source_rgb(0.0, 0.0, 0.0) |
719 | 719 | ||
720 | self.surface.ctx.select_font_face(fopts.name, cairo.FONT_SLANT_NORMAL, cairo.FONT_WEIGHT_BOLD) | 720 | self.surface.ctx.select_font_face(fopts.name, cairo.FONT_SLANT_NORMAL, cairo.FONT_WEIGHT_BOLD) |
721 | self.surface.ctx.set_font_size(fopts.size * self.scale) | 721 | self.surface.ctx.set_font_size(fopts.size * self.scale) |
722 | 722 | ||
723 | fe = self.surface.ctx.font_extents() | 723 | fe = self.surface.ctx.font_extents() |
724 | f_ascent, f_descent, f_height = fe[:3] | 724 | f_ascent, f_descent, f_height = fe[:3] |
725 | 725 | ||
726 | te = self.surface.ctx.text_extents(text) | 726 | te = self.surface.ctx.text_extents(text) |
727 | x_bearing, y_bearing, width, height = te[:4] | 727 | x_bearing, y_bearing, width, height = te[:4] |
728 | 728 | ||
729 | actual_x = x - x_bearing * x_bearing_factor - width * width_factor | 729 | actual_x = x - x_bearing * x_bearing_factor - width * width_factor |
730 | actual_y = y - f_descent * f_descent_factor + f_height * f_height_factor | 730 | actual_y = y - f_descent * f_descent_factor + f_height * f_height_factor |
731 | 731 | ||
732 | self.surface.ctx.set_source_rgb(fopts.color[0], fopts.color[1], fopts.color[2]) | 732 | self.surface.ctx.set_source_rgb(fopts.color[0], fopts.color[1], fopts.color[2]) |
733 | 733 | ||
734 | if do_snap: | 734 | if do_snap: |
735 | self.surface.ctx.move_to(snap(actual_x), snap(actual_y)) | 735 | self.surface.ctx.move_to(snap(actual_x), snap(actual_y)) |
736 | else: | 736 | else: |
737 | self.surface.ctx.move_to(actual_x, actual_y) | 737 | self.surface.ctx.move_to(actual_x, actual_y) |
738 | 738 | ||
739 | self.surface.ctx.show_text(text) | 739 | self.surface.ctx.show_text(text) |
740 | 740 | ||
741 | def draw_label(self, text, x, y, fopts=GraphFormat.DEF_FOPTS_LABEL, halign=AlignMode.LEFT, valign=AlignMode.BOTTOM, do_snap=True): | 741 | def draw_label(self, text, x, y, fopts=GraphFormat.DEF_FOPTS_LABEL, halign=AlignMode.LEFT, valign=AlignMode.BOTTOM, do_snap=True): |
742 | """Draws a label with the given parameters, with the given horizontal and vertical justification. One can override | 742 | """Draws a label with the given parameters, with the given horizontal and vertical justification. One can override |
743 | the color from ``fopts'' by passing something in to ``pattern'', which overrides the color with an arbitrary | 743 | the color from ``fopts'' by passing something in to ``pattern'', which overrides the color with an arbitrary |
@@ -747,21 +747,21 @@ class CairoCanvas(Canvas): | |||
747 | if halign not in halign_factors: | 747 | if halign not in halign_factors: |
748 | raise ValueError('Invalid alignment value') | 748 | raise ValueError('Invalid alignment value') |
749 | x_bearing_factor, width_factor = halign_factors[halign] | 749 | x_bearing_factor, width_factor = halign_factors[halign] |
750 | 750 | ||
751 | valign_factors = {AlignMode.BOTTOM : (0.0, 0.0), AlignMode.CENTER : (1.0, 0.5), AlignMode.TOP : (1.0, 1.0)} | 751 | valign_factors = {AlignMode.BOTTOM : (0.0, 0.0), AlignMode.CENTER : (1.0, 0.5), AlignMode.TOP : (1.0, 1.0)} |
752 | if valign not in valign_factors: | 752 | if valign not in valign_factors: |
753 | raise ValueError('Invalid alignment value') | 753 | raise ValueError('Invalid alignment value') |
754 | f_descent_factor, f_height_factor = valign_factors[valign] | 754 | f_descent_factor, f_height_factor = valign_factors[valign] |
755 | 755 | ||
756 | self._draw_label_common(text, x, y, fopts, x_bearing_factor, \ | 756 | self._draw_label_common(text, x, y, fopts, x_bearing_factor, \ |
757 | f_descent_factor, width_factor, f_height_factor, do_snap) | 757 | f_descent_factor, width_factor, f_height_factor, do_snap) |
758 | 758 | ||
759 | def draw_label_with_sscripts(self, text, supscript, subscript, x, y, \ | 759 | def draw_label_with_sscripts(self, text, supscript, subscript, x, y, \ |
760 | textfopts=GraphFormat.DEF_FOPTS_LABEL, sscriptfopts=GraphFormat.DEF_FOPTS_LABEL_SSCRIPT, \ | 760 | textfopts=GraphFormat.DEF_FOPTS_LABEL, sscriptfopts=GraphFormat.DEF_FOPTS_LABEL_SSCRIPT, \ |
761 | halign=AlignMode.LEFT, valign=AlignMode.BOTTOM, do_snap=True): | 761 | halign=AlignMode.LEFT, valign=AlignMode.BOTTOM, do_snap=True): |
762 | """Draws a label, but also optionally allows a superscript and subscript to be rendered.""" | 762 | """Draws a label, but also optionally allows a superscript and subscript to be rendered.""" |
763 | self.draw_label(text, x, y, textfopts, halign, valign) | 763 | self.draw_label(text, x, y, textfopts, halign, valign) |
764 | 764 | ||
765 | self.surface.ctx.set_source_rgb(0.0, 0.0, 0.0) | 765 | self.surface.ctx.set_source_rgb(0.0, 0.0, 0.0) |
766 | self.surface.ctx.select_font_face(textfopts.name, cairo.FONT_SLANT_NORMAL, cairo.FONT_WEIGHT_BOLD) | 766 | self.surface.ctx.select_font_face(textfopts.name, cairo.FONT_SLANT_NORMAL, cairo.FONT_WEIGHT_BOLD) |
767 | self.surface.ctx.set_font_size(textfopts.size) | 767 | self.surface.ctx.set_font_size(textfopts.size) |
@@ -781,7 +781,7 @@ class CairoCanvas(Canvas): | |||
781 | ytmp = y | 781 | ytmp = y |
782 | ytmp = y + f_height / 4.0 | 782 | ytmp = y + f_height / 4.0 |
783 | self.draw_label(subscript, xtmp, ytmp, sscriptfopts, halign, valign, do_snap) | 783 | self.draw_label(subscript, xtmp, ytmp, sscriptfopts, halign, valign, do_snap) |
784 | 784 | ||
785 | # represents a selectable region of the graph | 785 | # represents a selectable region of the graph |
786 | class SelectableRegion(object): | 786 | class SelectableRegion(object): |
787 | def __init__(self, x, y, width, height, event): | 787 | def __init__(self, x, y, width, height, event): |
@@ -791,19 +791,19 @@ class SelectableRegion(object): | |||
791 | self.height = height | 791 | self.height = height |
792 | self.event = event | 792 | self.event = event |
793 | self.scale = 1.0 | 793 | self.scale = 1.0 |
794 | 794 | ||
795 | def get_dimensions(self): | 795 | def get_dimensions(self): |
796 | return (self.x, self.y, self.width, self.height) | 796 | return (self.x, self.y, self.width, self.height) |
797 | 797 | ||
798 | def get_event(self): | 798 | def get_event(self): |
799 | return self.event | 799 | return self.event |
800 | 800 | ||
801 | def set_scale(self, scale): | 801 | def set_scale(self, scale): |
802 | self.scale = scale | 802 | self.scale = scale |
803 | 803 | ||
804 | def intersects(self, x, y, width, height): | 804 | def intersects(self, x, y, width, height): |
805 | return x <= (self.x + self.width) * self.scale \ | 805 | return x <= (self.x + self.width) * self.scale \ |
806 | and x + width >= self.x * self.scale \ | 806 | and x + width >= self.x * self.scale \ |
807 | and y <= (self.y + self.height) * self.scale \ | 807 | and y <= (self.y + self.height) * self.scale \ |
808 | and y + height >= self.y * self.scale | 808 | and y + height >= self.y * self.scale |
809 | 809 | ||