summaryrefslogtreecommitdiffstats
path: root/unit_trace/viz/viewer.py
diff options
context:
space:
mode:
authorMac Mollison <mollison@cs.unc.edu>2010-03-13 12:12:37 -0500
committerMac Mollison <mollison@cs.unc.edu>2010-03-13 12:12:37 -0500
commit122f457226f54ad23b7cd138512502e430e704dc (patch)
treefee0690936c3ae95255e559cd0fd09f0fa8c2ad4 /unit_trace/viz/viewer.py
parent14a40b99735f09f6e70b8e897acbb622f9115ca3 (diff)
Further restructuring to create 'unit_trace' pkg
The unit_trace folder should be placed in /usr/local/lib/pythonX.Y/site-packages. This makes unit-trace submodules available from anywhere on the system.
Diffstat (limited to 'unit_trace/viz/viewer.py')
-rw-r--r--unit_trace/viz/viewer.py193
1 files changed, 193 insertions, 0 deletions
diff --git a/unit_trace/viz/viewer.py b/unit_trace/viz/viewer.py
new file mode 100644
index 0000000..a695473
--- /dev/null
+++ b/unit_trace/viz/viewer.py
@@ -0,0 +1,193 @@
1#!/usr/bin/python
2
3"""GUI stuff."""
4
5from schedule import *
6from renderer import *
7
8import pygtk
9import gtk
10import gobject
11
12class GraphArea(gtk.DrawingArea):
13 DAREA_WIDTH_REQ = 500
14 DAREA_HEIGHT_REQ = 300
15 HORIZ_PAGE_SCROLL_FACTOR = 4.8
16 HORIZ_STEP_SCROLL_FACTOR = 0.8
17 VERT_PAGE_SCROLL_FACTOR = 3.0
18 VERT_STEP_SCROLL_FACTOR = 0.5
19
20 def __init__(self, renderer):
21 super(GraphArea, self).__init__()
22
23 self.renderer = renderer
24
25 self.cur_x = 0
26 self.cur_y = 0
27 self.width = 0
28 self.height = 0
29
30 self.now_selected = []
31
32 self.set_set_scroll_adjustments_signal('set-scroll-adjustments')
33
34 self.add_events(gtk.gdk.BUTTON_PRESS_MASK | gtk.gdk.POINTER_MOTION_MASK | gtk.gdk.POINTER_MOTION_HINT_MASK)
35
36 self.connect('expose-event', self.expose)
37 self.connect('size-allocate', self.size_allocate)
38 self.connect('set-scroll-adjustments', self.set_scroll_adjustments)
39 self.connect('button-press-event', self.button_press)
40 self.connect('motion-notify-event', self.motion_notify)
41
42 self.set_size_request(GraphArea.DAREA_WIDTH_REQ, GraphArea.DAREA_HEIGHT_REQ)
43
44 def expose(self, widget, event, data=None):
45 ctx = widget.window.cairo_create()
46 graph = self.renderer.get_graph()
47 graph.update_view(self.cur_x, self.cur_y, self.width, self.height, ctx)
48 graph.render_surface(self.renderer.get_schedule())
49
50 def set_scroll_adjustments(self, widget, horizontal, vertical, data=None):
51 graph = self.renderer.get_graph()
52 width = graph.get_width()
53 height = graph.get_height()
54
55 self.horizontal = horizontal
56 self.vertical = vertical
57 self.config_scrollbars(self.cur_x, self.cur_y)
58
59 self.horizontal.connect('value-changed', self.horizontal_value_changed)
60 self.vertical.connect('value-changed', self.vertical_value_changed)
61
62 def horizontal_value_changed(self, adjustment):
63 self.cur_x = min(adjustment.value, self.renderer.get_graph().get_width())
64 self.cur_x = max(adjustment.value, 0.0)
65
66 rect = gtk.gdk.Rectangle(0, 0, self.width, self.height)
67 self.window.invalidate_rect(rect, True)
68
69 def vertical_value_changed(self, adjustment):
70 self.cur_y = min(adjustment.value, self.renderer.get_graph().get_height())
71 self.cur_y = max(adjustment.value, 0.0)
72
73 rect = gtk.gdk.Rectangle(0, 0, self.width, self.height)
74 self.window.invalidate_rect(rect, True)
75
76 def size_allocate(self, widget, allocation):
77 self.width = allocation.width
78 self.height = allocation.height
79 self.config_scrollbars(self.cur_x, self.cur_y)
80
81 def config_scrollbars(self, hvalue, vvalue):
82 graph = self.renderer.get_graph()
83 width = graph.get_width()
84 height = graph.get_height()
85
86 if self.horizontal is not None:
87 self.horizontal.set_all(hvalue, 0.0, width, graph.get_attrs().maj_sep * GraphArea.HORIZ_STEP_SCROLL_FACTOR,
88 graph.get_attrs().maj_sep * GraphArea.HORIZ_PAGE_SCROLL_FACTOR, self.width)
89 if self.vertical is not None:
90 self.vertical.set_all(vvalue, 0.0, height, graph.get_attrs().y_item_size * GraphArea.VERT_STEP_SCROLL_FACTOR,
91 graph.get_attrs().y_item_size * GraphArea.VERT_PAGE_SCROLL_FACTOR, self.height)
92
93 def _find_max_layer(self, regions):
94 max_layer = Canvas.BOTTOM_LAYER
95 for event in regions:
96 if event.get_layer() > max_layer:
97 max_layer = event.get_layer()
98 return max_layer
99
100 def motion_notify(self, widget, motion_event, data=None):
101 msg = None
102
103 graph = self.renderer.get_graph()
104 just_selected = graph.get_selected_regions(motion_event.x, motion_event.y)
105 if not just_selected:
106 msg = ''
107 the_event = None
108 else:
109 max_layer = self._find_max_layer(just_selected)
110
111 for event in just_selected:
112 if event.get_layer() == max_layer:
113 the_event = event
114 break
115
116 msg = str(the_event)
117
118 self.emit('update-event-description', the_event, msg)
119
120 def button_press(self, widget, button_event, data=None):
121 graph = self.renderer.get_graph()
122
123 if button_event.button == 1:
124 just_selected = graph.get_selected_regions(button_event.x, button_event.y)
125
126 max_layer = self._find_max_layer(just_selected)
127
128 # only select those events which were in the top layer (it's
129 # not intuitive to click something and then have something
130 # below it get selected). Also, clicking something that
131 # is selected deselects it
132 new_now_selected = {}
133 for event in just_selected:
134 if event.get_layer() == max_layer:
135 if not event.is_selected():
136 new_now_selected[event] = None
137 event.set_selected(not event.is_selected())
138 break
139
140 for event in self.now_selected:
141 if event not in new_now_selected:
142 event.set_selected(False)
143
144 self.now_selected = new_now_selected
145
146 rect = gtk.gdk.Rectangle(0, 0, self.width, self.height)
147 self.window.invalidate_rect(rect, True)
148
149class GraphWindow(gtk.ScrolledWindow):
150 def __init__(self, renderer):
151 super(GraphWindow, self).__init__(None, None)
152
153 self.garea = GraphArea(renderer)
154 self.add(self.garea)
155 self.garea.show()
156
157 def get_graph_area(self):
158 return self.garea
159
160class MainWindow(object):
161 def __init__(self, renderer):
162 self.window = gtk.Window(gtk.WINDOW_TOPLEVEL)
163
164 self.window.connect('delete_event', self.delete_event)
165 self.window.connect('destroy', self.destroy)
166
167 self.vbox = gtk.VBox(False, 0)
168
169 self.gwindow = GraphWindow(renderer)
170 self.gwindow.get_graph_area().connect('update-event-description',
171 self.update_event_description)
172 self.gwindow.show()
173
174 self.desc_label = gtk.Label('')
175 self.desc_label.set_justify(gtk.JUSTIFY_LEFT)
176 self.desc_label.show()
177
178 self.vbox.pack_start(self.gwindow, True, True, 0)
179 self.vbox.pack_start(self.desc_label, False, False, 0)
180 self.vbox.show()
181
182 self.window.add(self.vbox)
183 self.window.show()
184
185 def update_event_description(self, widget, event, msg):
186 self.desc_label.set_text(msg)
187
188 def delete_event(self, widget, event, data=None):
189 return False
190
191 def destroy(self, widget, data=None):
192 gtk.main_quit()
193