diff options
author | Mac Mollison <mollison@cs.unc.edu> | 2010-03-13 12:12:37 -0500 |
---|---|---|
committer | Mac Mollison <mollison@cs.unc.edu> | 2010-03-13 12:12:37 -0500 |
commit | 122f457226f54ad23b7cd138512502e430e704dc (patch) | |
tree | fee0690936c3ae95255e559cd0fd09f0fa8c2ad4 /unit_trace/viz/viewer.py | |
parent | 14a40b99735f09f6e70b8e897acbb622f9115ca3 (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.py | 193 |
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 | |||
5 | from schedule import * | ||
6 | from renderer import * | ||
7 | |||
8 | import pygtk | ||
9 | import gtk | ||
10 | import gobject | ||
11 | |||
12 | class 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 | |||
149 | class 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 | |||
160 | class 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 | |||