diff options
author | Gary Bressler <garybressler@nc.rr.com> | 2010-04-27 14:04:50 -0400 |
---|---|---|
committer | Gary Bressler <garybressler@nc.rr.com> | 2010-04-27 14:04:50 -0400 |
commit | df6c90f22f5cdd5b079a9a69a54f30104eab9146 (patch) | |
tree | db68985cc6858faaab1728aa8972e298266b837f /unit_trace/viz/viewer.py | |
parent | e3a1e19e87dbb3df413015bfc714283bc8602999 (diff) |
Colorsgit add .! COLORSgit add .git add .geany index.txt
Diffstat (limited to 'unit_trace/viz/viewer.py')
-rw-r--r-- | unit_trace/viz/viewer.py | 264 |
1 files changed, 210 insertions, 54 deletions
diff --git a/unit_trace/viz/viewer.py b/unit_trace/viz/viewer.py index 5e707b8..33c84ff 100644 --- a/unit_trace/viz/viewer.py +++ b/unit_trace/viz/viewer.py | |||
@@ -4,7 +4,10 @@ | |||
4 | 4 | ||
5 | from schedule import * | 5 | from schedule import * |
6 | from renderer import * | 6 | from renderer import * |
7 | from graph import * | ||
8 | from canvas import * | ||
7 | from windows import * | 9 | from windows import * |
10 | from format import * | ||
8 | 11 | ||
9 | import pygtk | 12 | import pygtk |
10 | import gtk | 13 | import gtk |
@@ -79,6 +82,23 @@ class GraphArea(gtk.DrawingArea): | |||
79 | self.connect('button-release-event', self.button_release) | 82 | self.connect('button-release-event', self.button_release) |
80 | self.connect('motion-notify-event', self.motion_notify) | 83 | self.connect('motion-notify-event', self.motion_notify) |
81 | 84 | ||
85 | def output_to_file(self, filename, ftype): | ||
86 | """Outputs the entire graph to a file.""" | ||
87 | graph = self.renderer.get_graph() | ||
88 | surface = None | ||
89 | if ftype == 'png': | ||
90 | surface = ImageSurface() | ||
91 | elif ftype == 'svg': | ||
92 | surface = SVGSurface() | ||
93 | else: | ||
94 | raise ValueError | ||
95 | |||
96 | surface.renew(graph.get_width(), graph.get_height()) | ||
97 | graph.set_tmp_surface(surface) | ||
98 | graph.render_all(self.renderer.get_schedule()) | ||
99 | surface.write_out(filename) | ||
100 | graph.revert_surface() | ||
101 | |||
82 | def expose(self, widget, expose_event, data=None): | 102 | def expose(self, widget, expose_event, data=None): |
83 | ctx = widget.window.cairo_create() | 103 | ctx = widget.window.cairo_create() |
84 | graph = self.renderer.get_graph() | 104 | graph = self.renderer.get_graph() |
@@ -204,7 +224,11 @@ class GraphArea(gtk.DrawingArea): | |||
204 | graph.get_attrs().y_item_size * GraphArea.VERT_PAGE_SCROLL_FACTOR / scale, | 224 | graph.get_attrs().y_item_size * GraphArea.VERT_PAGE_SCROLL_FACTOR / scale, |
205 | self.height / scale) | 225 | self.height / scale) |
206 | self.set_vvalue(vvalue) | 226 | self.set_vvalue(vvalue) |
207 | 227 | ||
228 | def refresh_all(self): | ||
229 | """Refreshes the entire visible screen.""" | ||
230 | self._dirty(0, 0, self.width, self.height) | ||
231 | |||
208 | def refresh_events(self, sender, new, old, replace): | 232 | def refresh_events(self, sender, new, old, replace): |
209 | """Even if the selected areas change on one graph, they change | 233 | """Even if the selected areas change on one graph, they change |
210 | everywhere, and different events might be in different regions on | 234 | everywhere, and different events might be in different regions on |
@@ -216,7 +240,7 @@ class GraphArea(gtk.DrawingArea): | |||
216 | refreshes the drawing of the graph that requested the change.""" | 240 | refreshes the drawing of the graph that requested the change.""" |
217 | if self is not sender: | 241 | if self is not sender: |
218 | self.renderer.get_graph().render_events(new, True) | 242 | self.renderer.get_graph().render_events(new, True) |
219 | 243 | ||
220 | self._tag_events(new) | 244 | self._tag_events(new) |
221 | 245 | ||
222 | if self is sender: | 246 | if self is sender: |
@@ -228,20 +252,23 @@ class GraphArea(gtk.DrawingArea): | |||
228 | else: | 252 | else: |
229 | self.renderer.get_schedule().remove_selected(old) | 253 | self.renderer.get_schedule().remove_selected(old) |
230 | self.renderer.get_schedule().add_selected(new) | 254 | self.renderer.get_schedule().add_selected(new) |
255 | |||
256 | self.emit('update-sel-changes', self.renderer.get_schedule().get_selected()) | ||
231 | 257 | ||
232 | def _find_max_layer(self, regions): | 258 | def _find_max_layer(self, regions): |
233 | max_layer = Canvas.BOTTOM_LAYER | 259 | max_layer = -1 |
234 | for event in regions: | 260 | for layer in regions: |
235 | if event.get_layer() > max_layer: | 261 | if layer > max_layer: |
236 | max_layer = event.get_layer() | 262 | max_layer = layer |
237 | return max_layer | 263 | return max_layer |
238 | 264 | ||
239 | def _dirty_events(self, events): | 265 | def _dirty_events(self, events): |
240 | # if an event changed selected status, update the bounding area | 266 | # if an event changed selected status, update the bounding area |
241 | for layer in events: | 267 | for layer in events: |
242 | for event in events[layer]: | 268 | for event in events[layer]: |
243 | x, y, width, height = events[layer][event][self].get_dimensions() | 269 | if not events[layer][event][self].is_dummy(): |
244 | self._dirty_inflate((x - self.cur_x) * self.scale, | 270 | x, y, width, height = events[layer][event][self].get_dimensions() |
271 | self._dirty_inflate((x - self.cur_x) * self.scale, | ||
245 | (y - self.cur_y) * self.scale, | 272 | (y - self.cur_y) * self.scale, |
246 | width * self.scale, | 273 | width * self.scale, |
247 | height * self.scale, | 274 | height * self.scale, |
@@ -284,15 +311,14 @@ class GraphArea(gtk.DrawingArea): | |||
284 | graph.render_surface(self.renderer.get_schedule(), [(motion_event.x, motion_event.y, | 311 | graph.render_surface(self.renderer.get_schedule(), [(motion_event.x, motion_event.y, |
285 | 0, 0)], True) | 312 | 0, 0)], True) |
286 | 313 | ||
287 | just_selected = graph.get_selected_regions(motion_event.x, motion_event.y, 0, 0) | 314 | just_selected = graph.get_intersecting_regions(motion_event.x, motion_event.y, 0, 0) |
288 | was_selected = self.renderer.get_schedule().get_selected() | 315 | was_selected = self.renderer.get_schedule().get_selected() |
289 | if not just_selected: | 316 | if not just_selected: |
290 | msg = '' | 317 | msg = '' |
291 | the_event = None | 318 | the_event = None |
292 | else: | 319 | else: |
293 | max_layer = self._find_max_layer(just_selected) | 320 | max_layer = self._find_max_layer(just_selected) |
294 | 321 | for event in just_selected[max_layer]: | |
295 | for event in just_selected: | ||
296 | if event.get_layer() == max_layer: | 322 | if event.get_layer() == max_layer: |
297 | the_event = event | 323 | the_event = event |
298 | break | 324 | break |
@@ -331,9 +357,11 @@ class GraphArea(gtk.DrawingArea): | |||
331 | graph.render_surface(self.renderer.get_schedule(), dirty_list, True) | 357 | graph.render_surface(self.renderer.get_schedule(), dirty_list, True) |
332 | for rect in dirty_list: | 358 | for rect in dirty_list: |
333 | rx, ry, rwidth, rheight = rect | 359 | rx, ry, rwidth, rheight = rect |
334 | for event in graph.get_selected_regions(rx, ry, rwidth, rheight): | 360 | i_regs = graph.get_intersecting_regions(rx, ry, rwidth, rheight) |
335 | if event.get_layer() in was_selected and event in was_selected[event.get_layer()]: | 361 | for layer in i_regs: |
336 | self._select_event(remove_selected, event) | 362 | for event in i_regs[layer]: |
363 | if event.get_layer() in was_selected and event in was_selected[event.get_layer()]: | ||
364 | self._select_event(remove_selected, event) | ||
337 | 365 | ||
338 | add_reg = gtk.gdk.region_rectangle(gtk.gdk.Rectangle(x_p, y_p, width_p, height_p)) | 366 | add_reg = gtk.gdk.region_rectangle(gtk.gdk.Rectangle(x_p, y_p, width_p, height_p)) |
339 | add_reg.subtract(old_reg) | 367 | add_reg.subtract(old_reg) |
@@ -344,8 +372,10 @@ class GraphArea(gtk.DrawingArea): | |||
344 | graph.render_surface(self.renderer.get_schedule(), dirty_list, True) | 372 | graph.render_surface(self.renderer.get_schedule(), dirty_list, True) |
345 | for rect in dirty_list: | 373 | for rect in dirty_list: |
346 | rx, ry, rwidth, rheight = rect | 374 | rx, ry, rwidth, rheight = rect |
347 | for event in graph.get_selected_regions(rx, ry, rwidth, rheight): | 375 | i_regs = graph.get_intersecting_regions(rx, ry, rwidth, rheight) |
348 | self._select_event(add_selected, event) | 376 | for layer in i_regs: |
377 | for event in i_regs[layer]: | ||
378 | self._select_event(add_selected, event) | ||
349 | 379 | ||
350 | self.band_rect = x, y, width, height | 380 | self.band_rect = x, y, width, height |
351 | self.emit('request-refresh-events', self, add_selected, remove_selected, False) | 381 | self.emit('request-refresh-events', self, add_selected, remove_selected, False) |
@@ -362,9 +392,9 @@ class GraphArea(gtk.DrawingArea): | |||
362 | self.left_button_start_coor = (button_event.x, button_event.y) | 392 | self.left_button_start_coor = (button_event.x, button_event.y) |
363 | graph.render_surface(self.renderer.get_schedule(), \ | 393 | graph.render_surface(self.renderer.get_schedule(), \ |
364 | [(button_event.x, button_event.y, 0, 0)], True) | 394 | [(button_event.x, button_event.y, 0, 0)], True) |
365 | 395 | ||
366 | just_selected = graph.get_selected_regions(button_event.x, button_event.y, 0, 0) | 396 | just_selected = graph.get_intersecting_regions(button_event.x, button_event.y, 0, 0) |
367 | 397 | ||
368 | max_layer = self._find_max_layer(just_selected) | 398 | max_layer = self._find_max_layer(just_selected) |
369 | 399 | ||
370 | was_selected = self.renderer.get_schedule().get_selected() | 400 | was_selected = self.renderer.get_schedule().get_selected() |
@@ -382,21 +412,21 @@ class GraphArea(gtk.DrawingArea): | |||
382 | # not intuitive to click something and then have something | 412 | # not intuitive to click something and then have something |
383 | # below it get selected). Also, clicking something that | 413 | # below it get selected). Also, clicking something that |
384 | # is selected deselects it, if it's the only thing selected | 414 | # is selected deselects it, if it's the only thing selected |
385 | for event in just_selected: | 415 | if just_selected: |
386 | if event.get_layer() == max_layer: | 416 | for event in just_selected[max_layer]: |
387 | if not (more_than_one == 1 and event in was_selected): | 417 | if not (more_than_one == 1 and max_layer in was_selected \ |
418 | and event in was_selected[max_layer]): | ||
388 | self._select_event(new_now_selected, event) | 419 | self._select_event(new_now_selected, event) |
389 | break # only pick one event when just clicking | 420 | break # only pick one event when just clicking |
390 | 421 | ||
391 | self.emit('request-refresh-events', self, new_now_selected, was_selected, True) | 422 | self.emit('request-refresh-events', self, new_now_selected, was_selected, True) |
392 | else: | 423 | else: |
393 | remove_selected = {} | 424 | remove_selected = {} |
394 | add_selected = {} | 425 | add_selected = {} |
395 | 426 | ||
396 | for event in just_selected: | 427 | if just_selected: |
397 | layer = event.get_layer() | 428 | for event in just_selected[max_layer]: |
398 | if layer == max_layer: | 429 | if max_layer in was_selected and event in was_selected[max_layer]: |
399 | if layer in was_selected and event in was_selected[layer]: | ||
400 | self._select_event(remove_selected, event) | 430 | self._select_event(remove_selected, event) |
401 | else: | 431 | else: |
402 | self._select_event(add_selected, event) | 432 | self._select_event(add_selected, event) |
@@ -566,40 +596,68 @@ class MainWindow(gtk.Window): | |||
566 | 596 | ||
567 | def __init__(self): | 597 | def __init__(self): |
568 | super(MainWindow, self).__init__(gtk.WINDOW_TOPLEVEL) | 598 | super(MainWindow, self).__init__(gtk.WINDOW_TOPLEVEL) |
569 | 599 | ||
570 | self.add_events(gtk.gdk.BUTTON_PRESS_MASK) | 600 | self.add_events(gtk.gdk.BUTTON_PRESS_MASK) |
571 | 601 | ||
572 | self.connect('delete_event', self.delete_event) | 602 | self.connect('delete_event', self.delete_event) |
573 | self.connect('destroy', self.die) | 603 | self.connect('destroy', self.die) |
574 | 604 | ||
575 | file_menu = gtk.Menu() | 605 | file_menu = gtk.Menu() |
606 | edit_menu = gtk.Menu() | ||
576 | view_menu = gtk.Menu() | 607 | view_menu = gtk.Menu() |
577 | 608 | ||
578 | agr = gtk.AccelGroup() | 609 | agr = gtk.AccelGroup() |
579 | self.add_accel_group(agr) | 610 | self.add_accel_group(agr) |
580 | 611 | ||
612 | # list of file items that are clickable if and only if at | ||
613 | # least one graph is viewable | ||
614 | self.sensitive_menu_items = [] | ||
615 | |||
616 | save_item = gtk.ImageMenuItem('_Save Graph to File') | ||
617 | img = gtk.Image() | ||
618 | img.set_from_stock(gtk.STOCK_SAVE_AS, gtk.ICON_SIZE_MENU) | ||
619 | save_item.set_image(img) | ||
620 | key, mod = gtk.accelerator_parse('<Ctrl>S') | ||
621 | save_item.add_accelerator('activate', agr, key, mod, | ||
622 | gtk.ACCEL_VISIBLE) | ||
623 | save_item.connect('activate', self.save_item_activate) | ||
624 | save_item.set_sensitive(False) | ||
625 | self.sensitive_menu_items.append(save_item) | ||
626 | |||
581 | quit_item = gtk.ImageMenuItem(gtk.STOCK_QUIT, agr) | 627 | quit_item = gtk.ImageMenuItem(gtk.STOCK_QUIT, agr) |
582 | key, mod = gtk.accelerator_parse('Q') | 628 | key, mod = gtk.accelerator_parse('<Ctrl>Q') |
583 | quit_item.add_accelerator('activate', agr, key, mod, | 629 | quit_item.add_accelerator('activate', agr, key, mod, |
584 | gtk.ACCEL_VISIBLE) | 630 | gtk.ACCEL_VISIBLE) |
585 | quit_item.connect('activate', self.quit_item_activate) | 631 | quit_item.connect('activate', self.quit_item_activate) |
586 | quit_item.show() | ||
587 | 632 | ||
633 | file_menu.append(save_item) | ||
588 | file_menu.append(quit_item) | 634 | file_menu.append(quit_item) |
589 | 635 | ||
590 | file_item = gtk.MenuItem('_File', True) | 636 | file_item = gtk.MenuItem('_File', True) |
591 | file_item.set_submenu(file_menu) | 637 | file_item.set_submenu(file_menu) |
592 | file_item.show() | ||
593 | 638 | ||
594 | self.move_item = gtk.ImageMenuItem('_Move to Time') | 639 | move_item = gtk.ImageMenuItem('_Move to Time') |
595 | key, mod = gtk.accelerator_parse('<Ctrl>M') | 640 | key, mod = gtk.accelerator_parse('<Ctrl>M') |
596 | self.move_item.add_accelerator('activate', agr, key, mod, | 641 | move_item.add_accelerator('activate', agr, key, mod, |
597 | gtk.ACCEL_VISIBLE) | 642 | gtk.ACCEL_VISIBLE) |
598 | self.move_item.set_sensitive(False) | 643 | move_item.set_sensitive(False) |
599 | 644 | self.sensitive_menu_items.append(move_item) | |
600 | self.move_item.connect('activate', self.move_to_time_activate) | 645 | |
601 | self.move_item.show() | 646 | move_item.connect('activate', self.move_to_time_activate) |
602 | 647 | ||
648 | self.colors_item = gtk.ImageMenuItem('Co_lors') | ||
649 | key, mod = gtk.accelerator_parse('<Ctrl>L') | ||
650 | self.colors_item.add_accelerator('activate', agr, key, mod, | ||
651 | gtk.ACCEL_VISIBLE) | ||
652 | self.colors_item.set_sensitive(False) | ||
653 | |||
654 | self.colors_item.connect('activate', self.colors_activate) | ||
655 | |||
656 | edit_menu.append(self.colors_item) | ||
657 | |||
658 | edit_item = gtk.MenuItem('_Edit', True) | ||
659 | edit_item.set_submenu(edit_menu) | ||
660 | |||
603 | zoom_in_item = gtk.ImageMenuItem(gtk.STOCK_ZOOM_IN, agr) | 661 | zoom_in_item = gtk.ImageMenuItem(gtk.STOCK_ZOOM_IN, agr) |
604 | key, mod = gtk.accelerator_parse('<Ctrl>plus') | 662 | key, mod = gtk.accelerator_parse('<Ctrl>plus') |
605 | zoom_in_item.add_accelerator('activate', agr, key, mod, | 663 | zoom_in_item.add_accelerator('activate', agr, key, mod, |
@@ -608,7 +666,6 @@ class MainWindow(gtk.Window): | |||
608 | zoom_in_item.add_accelerator('activate', agr, key, mod, 0) | 666 | zoom_in_item.add_accelerator('activate', agr, key, mod, 0) |
609 | 667 | ||
610 | zoom_in_item.connect('activate', self.zoom_in_item_activate) | 668 | zoom_in_item.connect('activate', self.zoom_in_item_activate) |
611 | zoom_in_item.show() | ||
612 | 669 | ||
613 | zoom_out_item = gtk.ImageMenuItem(gtk.STOCK_ZOOM_OUT, agr) | 670 | zoom_out_item = gtk.ImageMenuItem(gtk.STOCK_ZOOM_OUT, agr) |
614 | key, mod = gtk.accelerator_parse('<Ctrl>minus') | 671 | key, mod = gtk.accelerator_parse('<Ctrl>minus') |
@@ -618,21 +675,19 @@ class MainWindow(gtk.Window): | |||
618 | zoom_out_item.add_accelerator('activate', agr, key, mod, 0) | 675 | zoom_out_item.add_accelerator('activate', agr, key, mod, 0) |
619 | 676 | ||
620 | zoom_out_item.connect('activate', self.zoom_out_item_activate) | 677 | zoom_out_item.connect('activate', self.zoom_out_item_activate) |
621 | zoom_out_item.show() | ||
622 | 678 | ||
623 | view_menu.append(self.move_item) | 679 | view_menu.append(move_item) |
624 | view_menu.append(zoom_in_item) | 680 | view_menu.append(zoom_in_item) |
625 | view_menu.append(zoom_out_item) | 681 | view_menu.append(zoom_out_item) |
626 | 682 | ||
627 | view_item = gtk.MenuItem('_View', True) | 683 | view_item = gtk.MenuItem('_View', True) |
628 | view_item.set_submenu(view_menu) | 684 | view_item.set_submenu(view_menu) |
629 | view_item.show() | ||
630 | 685 | ||
631 | menu_bar = gtk.MenuBar() | 686 | menu_bar = gtk.MenuBar() |
632 | menu_bar.append(file_item) | 687 | menu_bar.append(file_item) |
688 | menu_bar.append(edit_item) | ||
633 | menu_bar.append(view_item) | 689 | menu_bar.append(view_item) |
634 | 690 | ||
635 | menu_bar.show() | ||
636 | self.vbox = gtk.VBox(False, 0) | 691 | self.vbox = gtk.VBox(False, 0) |
637 | 692 | ||
638 | self.notebook = gtk.Notebook() | 693 | self.notebook = gtk.Notebook() |
@@ -640,25 +695,24 @@ class MainWindow(gtk.Window): | |||
640 | self.notebook.last_page = -1 | 695 | self.notebook.last_page = -1 |
641 | self.notebook.connect('switch-page', self.switch_page) | 696 | self.notebook.connect('switch-page', self.switch_page) |
642 | 697 | ||
643 | self.notebook.show() | ||
644 | |||
645 | self.desc_label = gtk.Label('') | 698 | self.desc_label = gtk.Label('') |
646 | self.desc_label.set_alignment(0.0, 0.0) | 699 | self.desc_label.set_alignment(0.0, 0.0) |
647 | self.desc_label.show() | ||
648 | 700 | ||
649 | self.vbox.pack_start(menu_bar, False, False, 0) | 701 | self.vbox.pack_start(menu_bar, False, False, 0) |
650 | self.vbox.pack_start(self.notebook, True, True, 0) | 702 | self.vbox.pack_start(self.notebook, True, True, 0) |
651 | self.vbox.pack_start(self.desc_label, False, False, 0) | 703 | self.vbox.pack_start(self.desc_label, False, False, 0) |
652 | self.vbox.show() | ||
653 | 704 | ||
654 | self.add(self.vbox) | 705 | self.add(self.vbox) |
655 | 706 | ||
656 | self.info_win = InfoWindow() | 707 | self.info_win = InfoWindow() |
657 | 708 | self.color_dialog = gtk.ColorSelectionDialog('Choose Item Color') | |
709 | |||
710 | self.cur_item_no = None | ||
711 | |||
658 | self.set_size_request(MainWindow.WINDOW_WIDTH_REQ, MainWindow.WINDOW_HEIGHT_REQ) | 712 | self.set_size_request(MainWindow.WINDOW_WIDTH_REQ, MainWindow.WINDOW_HEIGHT_REQ) |
659 | 713 | ||
660 | self.set_title('Unit-Trace Visualizer') | 714 | self.set_title('Unit-Trace Visualizer') |
661 | self.show() | 715 | self.show_all() |
662 | 716 | ||
663 | def connect_widgets(self, gwindow): | 717 | def connect_widgets(self, gwindow): |
664 | gwindow.get_graph_area().connect('update-event-description', self.update_event_description) | 718 | gwindow.get_graph_area().connect('update-event-description', self.update_event_description) |
@@ -666,6 +720,7 @@ class MainWindow(gtk.Window): | |||
666 | gwindow.get_graph_area().connect('request-refresh-events', self.request_refresh_events) | 720 | gwindow.get_graph_area().connect('request-refresh-events', self.request_refresh_events) |
667 | gwindow.connect('request-zoom-in', self.zoom_in_item_activate) | 721 | gwindow.connect('request-zoom-in', self.zoom_in_item_activate) |
668 | gwindow.connect('request-zoom-out', self.zoom_out_item_activate) | 722 | gwindow.connect('request-zoom-out', self.zoom_out_item_activate) |
723 | gwindow.get_graph_area().connect('update-sel-changes', self.update_sel_changes) | ||
669 | 724 | ||
670 | def set_renderers(self, renderers): | 725 | def set_renderers(self, renderers): |
671 | for i in range(0, self.notebook.get_n_pages()): | 726 | for i in range(0, self.notebook.get_n_pages()): |
@@ -675,15 +730,28 @@ class MainWindow(gtk.Window): | |||
675 | self.connect_widgets(gwindow) | 730 | self.connect_widgets(gwindow) |
676 | gwindow.show() | 731 | gwindow.show() |
677 | self.notebook.append_page(gwindow, gtk.Label(title)) | 732 | self.notebook.append_page(gwindow, gtk.Label(title)) |
733 | |||
678 | if self.notebook.get_n_pages() > 0: | 734 | if self.notebook.get_n_pages() > 0: |
679 | self.notebook.get_nth_page(0).grab_focus() | 735 | self.notebook.get_nth_page(0).grab_focus() |
680 | 736 | ||
681 | if self.notebook.get_n_pages() > 0: | 737 | if self.notebook.get_n_pages() > 0: |
682 | self.move_item.set_sensitive(True) | 738 | for menu_item in self.sensitive_menu_items: |
739 | menu_item.set_sensitive(True) | ||
683 | else: | 740 | else: |
684 | self.move_item.set_sensitive(False) | 741 | for menu_item in self.sensitive_menu_items: |
685 | 742 | menu_item.set_sensitive(False) | |
686 | 743 | ||
744 | def update_sel_changes(self, widget, selected): | ||
745 | """Modify the GUI appropriately to reflect a change in selection.""" | ||
746 | self.selected = selected | ||
747 | |||
748 | self.cur_item_no = self.notebook.get_nth_page(self.notebook.last_page).get_graph_area() \ | ||
749 | .get_graph().all_one_item_selected(selected) | ||
750 | if self.cur_item_no is not None: | ||
751 | self.colors_item.set_sensitive(True) | ||
752 | else: | ||
753 | self.colors_item.set_sensitive(False) | ||
754 | |||
687 | def switch_page(self, widget, page, page_num): | 755 | def switch_page(self, widget, page, page_num): |
688 | if self.notebook.get_nth_page(self.notebook.last_page) is not None: | 756 | if self.notebook.get_nth_page(self.notebook.last_page) is not None: |
689 | old_value = self.notebook.get_nth_page(self.notebook.last_page).get_hadjustment().get_value() | 757 | old_value = self.notebook.get_nth_page(self.notebook.last_page).get_hadjustment().get_value() |
@@ -710,11 +778,12 @@ class MainWindow(gtk.Window): | |||
710 | for i in range(0, self.notebook.get_n_pages()): | 778 | for i in range(0, self.notebook.get_n_pages()): |
711 | if self.notebook.get_nth_page(i).get_graph_area() is not sender: | 779 | if self.notebook.get_nth_page(i).get_graph_area() is not sender: |
712 | self.notebook.get_nth_page(i).get_graph_area().refresh_events(sender, old, new, replace) | 780 | self.notebook.get_nth_page(i).get_graph_area().refresh_events(sender, old, new, replace) |
713 | break | ||
714 | for i in range(0, self.notebook.get_n_pages()): | 781 | for i in range(0, self.notebook.get_n_pages()): |
782 | self.notebook.get_nth_page(i).get_graph_area().renderer.graph | ||
715 | if self.notebook.get_nth_page(i).get_graph_area() is sender: | 783 | if self.notebook.get_nth_page(i).get_graph_area() is sender: |
716 | self.notebook.get_nth_page(i).get_graph_area().refresh_events(sender, old, new, replace) | 784 | self.notebook.get_nth_page(i).get_graph_area().refresh_events(sender, old, new, replace) |
717 | 785 | break | |
786 | |||
718 | def move_to_time_activate(self, widget): | 787 | def move_to_time_activate(self, widget): |
719 | dialog = TextInputDialog('Move to Time', 'What time to move to?', self) | 788 | dialog = TextInputDialog('Move to Time', 'What time to move to?', self) |
720 | 789 | ||
@@ -760,6 +829,93 @@ class MainWindow(gtk.Window): | |||
760 | for i in range(0, self.notebook.get_n_pages()): | 829 | for i in range(0, self.notebook.get_n_pages()): |
761 | self.notebook.get_nth_page(i).get_graph_area().zoom_out() | 830 | self.notebook.get_nth_page(i).get_graph_area().zoom_out() |
762 | 831 | ||
832 | def colors_activate(self, widget): | ||
833 | garea = self.notebook.get_nth_page(self.notebook.last_page).get_graph_area() | ||
834 | graph = garea.get_renderer().get_graph() | ||
835 | |||
836 | |||
837 | pattern = graph.get_bar_pattern(self.cur_item_no) | ||
838 | |||
839 | if len(pattern.get_color_list()) > 1: | ||
840 | print 'striped patterns not yet supported' | ||
841 | |||
842 | r, g, b = pattern.get_color_list()[0] | ||
843 | colorsel = self.color_dialog.get_color_selection() | ||
844 | cur_color = gtk.gdk.Color(int(r * 65535), int(g * 65535), int(b * 65535)) | ||
845 | colorsel.set_previous_color(cur_color) | ||
846 | colorsel.set_current_color(cur_color) | ||
847 | colorsel.set_has_palette(True) | ||
848 | |||
849 | if self.color_dialog.run() == gtk.RESPONSE_OK: | ||
850 | color = colorsel.get_current_color() | ||
851 | r, g, b = color.red / 65535.0, color.green / 65535.0, color.blue / 65535.0 | ||
852 | graph.set_bar_pattern(self.cur_item_no, Pattern([(r, g, b)])) | ||
853 | garea.refresh_all() | ||
854 | |||
855 | self.color_dialog.hide() | ||
856 | |||
857 | def save_item_activate(self, widget): | ||
858 | ACCEPTED_TYPES = ('png', 'svg') | ||
859 | |||
860 | dialog = gtk.FileChooserDialog('Save to Graphics File', self, | ||
861 | gtk.FILE_CHOOSER_ACTION_SAVE, | ||
862 | (gtk.STOCK_CANCEL, gtk.RESPONSE_CANCEL, | ||
863 | gtk.STOCK_SAVE, gtk.RESPONSE_ACCEPT)) | ||
864 | |||
865 | png_filter = gtk.FileFilter() | ||
866 | png_filter.add_mime_type('image/png') | ||
867 | png_filter.set_name('PNG image (*.png)') | ||
868 | dialog.add_filter(png_filter) | ||
869 | |||
870 | svg_filter = gtk.FileFilter() | ||
871 | svg_filter.add_mime_type('image/svg+xml') | ||
872 | svg_filter.set_name('SVG vector image (*.svg)') | ||
873 | dialog.add_filter(svg_filter) | ||
874 | |||
875 | filename = None | ||
876 | ftype = None | ||
877 | while True: | ||
878 | if dialog.run() == gtk.RESPONSE_ACCEPT: | ||
879 | filename = dialog.get_filename() | ||
880 | # parse filename for extension | ||
881 | |||
882 | parts = filename.split('.') | ||
883 | ftype = None | ||
884 | if len(parts) == 1: | ||
885 | filename += '.' + parts[0] | ||
886 | if dialog.get_filter() is png_filter: | ||
887 | ftype = 'png' | ||
888 | elif dialog.get_filter() is svg_filter: | ||
889 | ftype = 'svg' | ||
890 | break | ||
891 | else: | ||
892 | ftype = parts[-1] | ||
893 | if ftype in ACCEPTED_TYPES: | ||
894 | break | ||
895 | else: | ||
896 | err_dialog = gtk.MessageDialog(self, gtk.DIALOG_DESTROY_WITH_PARENT, | ||
897 | gtk.MESSAGE_ERROR, | ||
898 | gtk.BUTTONS_CLOSE, | ||
899 | 'File type "' + ftype + '" not recognized') | ||
900 | err_dialog.set_title('File Type Error') | ||
901 | err_dialog.run() | ||
902 | err_dialog.destroy() | ||
903 | else: | ||
904 | filename = None | ||
905 | ftype = None | ||
906 | break | ||
907 | |||
908 | if filename is not None: | ||
909 | cursor = gtk.gdk.Cursor(gtk.gdk.WATCH) | ||
910 | dialog.get_window().set_cursor(cursor) | ||
911 | def idle_callback(dialog): | ||
912 | self.notebook.get_nth_page(self.notebook.last_page).get_graph_area().output_to_file(filename, ftype) | ||
913 | dialog.get_window().set_cursor(None) | ||
914 | dialog.destroy() | ||
915 | gobject.idle_add(idle_callback, dialog) # needed to get the cursor to display | ||
916 | else: | ||
917 | dialog.destroy() | ||
918 | |||
763 | def quit_item_activate(self, widget): | 919 | def quit_item_activate(self, widget): |
764 | self.destroy() | 920 | self.destroy() |
765 | 921 | ||