def render(self, size, focus): bottom_c = self.bottom_w.render(size, False) if not bottom_c.cols() or not bottom_c.rows(): return urwid.CompositeCanvas(bottom_c) top_size, _ = self._top_size(size, focus) top_c = self.top_w.render(top_size, focus) top_c = urwid.CompositeCanvas(top_c) left = (size[0] - top_size[0]) // 2 top = (size[1] - top_size[1]) // 2 return urwid.CanvasOverlay(top_c, bottom_c, left, top)
def render(self, size, focus=False): maxcol, maxrow = size bottom_c = self.bottom_w.render(size, focus) cursor = bottom_c.cursor if not cursor: # Hide the tooltip if there is no cursor. return bottom_c cursor_x, cursor_y = cursor if cursor_y * 2 < maxrow: # Cursor is in the top half. Tooltip goes below it: y = cursor_y + 1 rows = maxrow - y else: # Cursor is in the bottom half. Tooltip fills the area above: y = 0 rows = cursor_y # HACK: shrink-wrap the tooltip. This is ugly in multiple ways: # - It only works on a listbox. # - It assumes the wrapping LineBox eats one char on each edge. # - It is a loop. # (ideally it would check how much free space there is, # instead of repeatedly trying smaller sizes) while 'bottom' in self.listbox.ends_visible((maxcol - 2, rows - 3)): rows -= 1 # If we're displaying above the cursor move the top edge down: if not y: y = cursor_y - rows # Render *both* windows focused. This is probably not normal in urwid, # but it works nicely. top_c = self.top_w.render((maxcol, rows), focus and self.tooltip_focus) combi_c = urwid.CanvasOverlay(top_c, bottom_c, 0, y) # Use the cursor coordinates from the bottom canvas. canvas = urwid.CompositeCanvas(combi_c) canvas.cursor = cursor return canvas