#!/usr/bin/python """GUI stuff.""" from schedule import * from renderer import * import pygtk import gtk import gobject class GraphArea(gtk.DrawingArea): DAREA_WIDTH_REQ = 500 DAREA_HEIGHT_REQ = 300 HORIZ_PAGE_SCROLL_FACTOR = 4.8 HORIZ_STEP_SCROLL_FACTOR = 0.8 VERT_PAGE_SCROLL_FACTOR = 3.0 VERT_STEP_SCROLL_FACTOR = 0.5 def __init__(self, renderer): super(GraphArea, self).__init__() self.renderer = renderer self.cur_x = 0 self.cur_y = 0 self.width = 0 self.height = 0 self.now_selected = [] self.set_set_scroll_adjustments_signal('set-scroll-adjustments') self.add_events(gtk.gdk.BUTTON_PRESS_MASK | gtk.gdk.POINTER_MOTION_MASK | gtk.gdk.POINTER_MOTION_HINT_MASK) self.connect('expose-event', self.expose) self.connect('size-allocate', self.size_allocate) self.connect('set-scroll-adjustments', self.set_scroll_adjustments) self.connect('button-press-event', self.button_press) self.connect('motion-notify-event', self.motion_notify) self.set_size_request(GraphArea.DAREA_WIDTH_REQ, GraphArea.DAREA_HEIGHT_REQ) def expose(self, widget, event, data=None): ctx = widget.window.cairo_create() graph = self.renderer.get_graph() graph.update_view(self.cur_x, self.cur_y, self.width, self.height, ctx) graph.render_surface(self.renderer.get_schedule()) def set_scroll_adjustments(self, widget, horizontal, vertical, data=None): graph = self.renderer.get_graph() width = graph.get_width() height = graph.get_height() self.horizontal = horizontal self.vertical = vertical self.config_scrollbars(self.cur_x, self.cur_y) self.horizontal.connect('value-changed', self.horizontal_value_changed) self.vertical.connect('value-changed', self.vertical_value_changed) def horizontal_value_changed(self, adjustment): self.cur_x = min(adjustment.value, self.renderer.get_graph().get_width()) self.cur_x = max(adjustment.value, 0.0) rect = gtk.gdk.Rectangle(0, 0, self.width, self.height) self.window.invalidate_rect(rect, True) def vertical_value_changed(self, adjustment): self.cur_y = min(adjustment.value, self.renderer.get_graph().get_height()) self.cur_y = max(adjustment.value, 0.0) rect = gtk.gdk.Rectangle(0, 0, self.width, self.height) self.window.invalidate_rect(rect, True) def size_allocate(self, widget, allocation): self.width = allocation.width self.height = allocation.height self.config_scrollbars(self.cur_x, self.cur_y) def config_scrollbars(self, hvalue, vvalue): graph = self.renderer.get_graph() width = graph.get_width() height = graph.get_height() if self.horizontal is not None: self.horizontal.set_all(hvalue, 0.0, width, graph.get_attrs().maj_sep * GraphArea.HORIZ_STEP_SCROLL_FACTOR, graph.get_attrs().maj_sep * GraphArea.HORIZ_PAGE_SCROLL_FACTOR, self.width) if self.vertical is not None: self.vertical.set_all(vvalue, 0.0, height, graph.get_attrs().y_item_size * GraphArea.VERT_STEP_SCROLL_FACTOR, graph.get_attrs().y_item_size * GraphArea.VERT_PAGE_SCROLL_FACTOR, self.height) def _find_max_layer(self, regions): max_layer = Canvas.BOTTOM_LAYER for event in regions: if event.get_layer() > max_layer: max_layer = event.get_layer() return max_layer def motion_notify(self, widget, motion_event, data=None): msg = None graph = self.renderer.get_graph() just_selected = graph.get_selected_regions(motion_event.x, motion_event.y) if not just_selected: msg = '' the_event = None else: max_layer = self._find_max_layer(just_selected) for event in just_selected: if event.get_layer() == max_layer: the_event = event break msg = str(the_event) self.emit('update-event-description', the_event, msg) def button_press(self, widget, button_event, data=None): graph = self.renderer.get_graph() if button_event.button == 1: just_selected = graph.get_selected_regions(button_event.x, button_event.y) max_layer = self._find_max_layer(just_selected) # only select those events which were in the top layer (it's # not intuitive to click something and then have something # below it get selected). Also, clicking something that # is selected deselects it new_now_selected = {} for event in just_selected: if event.get_layer() == max_layer: if not event.is_selected(): new_now_selected[event] = None event.set_selected(not event.is_selected()) break for event in self.now_selected: if event not in new_now_selected: event.set_selected(False) self.now_selected = new_now_selected rect = gtk.gdk.Rectangle(0, 0, self.width, self.height) self.window.invalidate_rect(rect, True) class GraphWindow(gtk.ScrolledWindow): def __init__(self, renderer): super(GraphWindow, self).__init__(None, None) self.garea = GraphArea(renderer) self.add(self.garea) self.garea.show() def get_graph_area(self): return self.garea class MainWindow(object): def __init__(self, renderer): self.window = gtk.Window(gtk.WINDOW_TOPLEVEL) self.window.connect('delete_event', self.delete_event) self.window.connect('destroy', self.destroy) self.vbox = gtk.VBox(False, 0) self.gwindow = GraphWindow(renderer) self.gwindow.get_graph_area().connect('update-event-description', self.update_event_description) self.gwindow.show() self.desc_label = gtk.Label('') self.desc_label.set_justify(gtk.JUSTIFY_LEFT) self.desc_label.show() self.vbox.pack_start(self.gwindow, True, True, 0) self.vbox.pack_start(self.desc_label, False, False, 0) self.vbox.show() self.window.add(self.vbox) self.window.show() def update_event_description(self, widget, event, msg): self.desc_label.set_text(msg) def delete_event(self, widget, event, data=None): return False def destroy(self, widget, data=None): gtk.main_quit()