def set_zoom(self, req_rect): if not req_rect.width or not req_rect.height: # Bogus dragging. return current_aspect = self.zoom_rect.width / self.zoom_rect.height requested_aspect = req_rect.width / req_rect.height # Make sure all the requested area is in the screen, and no more than # necessary for that. if requested_aspect < current_aspect: # Screen is wider than desired frame. new_width = current_aspect * req_rect.height assert new_width > req_rect.width r = ui.rect(req_rect.center.x - new_width / 2, req_rect.bottom, new_width, req_rect.height) else: # Screen is taller than desired frame. new_height = req_rect.width / current_aspect assert new_height > req_rect.height r = ui.rect(req_rect.left, req_rect.center.y - new_height / 2, req_rect.width, new_height) ratio = self.get_zoom_ratio() self.zoom_rect = ui.rect(self.zoom_rect.left + r.left * ratio, self.zoom_rect.bottom + r.bottom * ratio, r.width * ratio, r.height * ratio)
def __init__(self, **kw): graph = kw.pop('graph') history = kw.pop('history') ui.window.__init__(self, **kw) vertices, edges, start, goal, color_history = parse(file(graph), file(history)) self.vertices = vertices self.start = start self.goal = goal self.history = color_history self.play_position = 0 self.vertex_buffer = pyglet.graphics.vertex_list( len(vertices.buffer) // 2, 'v2f/static', 'c3B/stream') self.edge_buffer = pyglet.graphics.vertex_list( len(edges) // 2, 'v2f/static', 'c3B/stream') copy_buffer(self.vertex_buffer.vertices, self.vertices.buffer) copy_buffer(self.vertex_buffer.colors, self.history[0].vertex_colors) copy_buffer(self.edge_buffer.vertices, edges) copy_buffer(self.edge_buffer.colors, self.history[0].edge_colors) self.dragging = None self.drag_end = None self.closest_vertex = None min_, max_ = self.world_extents() rect = ui.rect(min_.x, min_.y, max_.x - min_.x, max_.y - min_.y) self.bsp_tree = bsp_tree(self.vertices.flat_list)
def _layout(self, rect, blah, parent): mywidth = rect.width // 50 self.range = rect.width - mywidth return (ui.rect(int(self.position * self.range), 0, mywidth, rect.height), rect)
def on_end_drag(self, x, y): if self.zooming: x1, y1 = self.dragging x2, y2 = self.drag_end self.set_zoom(ui.rect(min(x1, x2), min(y1, y2), abs(x1-x2), abs(y1-y2))) self.dragging = self.drag_end = None self.scrolling = self.zooming = False
def extents(vertices): min_ = vec2(*vertices[0][1:]) max_ = vec2(*vertices[0][1:]) for id_, x, y in vertices: if x < min_.x: min_.x = x if x > max_.x: max_.x = x if y < min_.y: min_.y = y if y > max_.y: max_.y = y size = max_ - min_ return ui.rect(min_.x, min_.y, size.x, size.y)
def on_mouse_drag(self, x, y, dx, dy, btn, *etc): if not self.dragging: self.scrolling = (btn == mouse.LEFT) and self.zoom_rect self.zooming = (btn == mouse.RIGHT) self.dragging = x, y ui.start_drag(self) if self.scrolling: ratio = self.get_zoom_ratio() orig_x, orig_y = self.dragging new_x = max(self.world_rect.left, min(self.world_rect.right - self.rect.width * ratio, self.scrolling.left - (x - orig_x) * ratio)) new_y = max(self.world_rect.bottom, min(self.world_rect.top - self.rect.height * ratio, self.scrolling.bottom - (y - orig_y) * ratio)) self.zoom_rect = ui.rect(new_x, new_y, self.zoom_rect.width, self.zoom_rect.height) if self.zooming: self.drag_end = x, y return True
def show_tooltip(self, id_, x, y): height = self.rect.height // 30 try: label = ui.label(layout=ui.fill_layout(), text=repr(id_)[1:-1], color=(1., 1., 1., 1.)) except UnicodeDecodeError: print "Bad string", repr(id_) return lw, lh = label.content_size(height) margin = .2 bg_width = lw * (1 + 2 * margin) bg_height = lh * (1 + 2 * margin) x, y = self.world_to_window(x, y) x = max(0, min(self.rect.width - bg_width, x)) y = max(0, min(self.rect.height - bg_height, y)) bg_rect = ui.rect(x, y, bg_width, bg_height) background = ui.plain_color(id='tooltip', rect=bg_rect, color=(.0, .0, .0, .5)) background.children.append(label) background.layout_children() self.children.append(background)
def layout_children(self): "Fit graph to screen, with some margin." self.remove_closest_display() window_rect = self.absolute_rect = self.find_absolute_rect() min_, max_ = self.world_extents() range_ = max_ - min_ margin = .02 # at each border ww = window_rect.width * (1 - margin * 2) wh = window_rect.height * (1 - margin * 2) # Aspect is larger if something is wider in relation to its height. world_aspect = range_.x / range_.y screen_aspect = ww / wh if world_aspect < screen_aspect: # We are limited by vertical height (most common case). pixels_per_world_unit = wh / range_.y else: pixels_per_world_unit = ww / range_.x world_center = vec2((min_.x + max_.x) / 2, (min_.y + max_.y) / 2) screen_size_in_world_units = ( vec2(window_rect.width, window_rect.height) / pixels_per_world_unit) wleft, wbottom = (world_center - screen_size_in_world_units / 2) wwidth, wheight = screen_size_in_world_units self.world_rect = self.zoom_rect = ui.rect( wleft, wbottom, wwidth, wheight)