Skip to content

Commit cba8281

Browse files
committed
Shrink the tooltip if there is more space than the listbox needs.
1 parent 1040bd6 commit cba8281

File tree

1 file changed

+21
-4
lines changed

1 file changed

+21
-4
lines changed

bpython/urwid.py

Lines changed: 21 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -187,17 +187,21 @@ class Tooltip(urwid.BoxWidget):
187187

188188
"""Container inspired by Overlay to position our tooltip.
189189
190+
bottom_w should be a BoxWidget.
191+
The top window currently has to be a listbox to support shrinkwrapping.
192+
190193
This passes keyboard events to the bottom instead of the top window.
191194
192195
It also positions the top window relative to the cursor position
193196
from the bottom window and hides it if there is no cursor.
194197
"""
195198

196-
def __init__(self, bottom_w, top_w):
199+
def __init__(self, bottom_w, listbox):
197200
self.__super.__init__()
198201

199202
self.bottom_w = bottom_w
200-
self.top_w = top_w
203+
self.listbox = listbox
204+
self.top_w = urwid.LineBox(listbox)
201205

202206
def selectable(self):
203207
return self.bottom_w.selectable()
@@ -224,7 +228,6 @@ def render(self, size, focus=False):
224228
# Hide the tooltip if there is no cursor.
225229
return bottom_c
226230

227-
# TODO: deal with the tooltip not needing all the space we have.
228231
cursor_x, cursor_y = cursor
229232
if cursor_y * 2 < maxrow:
230233
# Cursor is in the top half. Tooltip goes below it:
@@ -234,6 +237,20 @@ def render(self, size, focus=False):
234237
# Cursor is in the bottom half. Tooltip fills the area above:
235238
y = 0
236239
rows = cursor_y
240+
241+
# HACK: shrink-wrap the tooltip. This is ugly in multiple ways:
242+
# - It only works on a listbox.
243+
# - It assumes the wrapping LineBox eats one char on each edge.
244+
# - It is a loop.
245+
# (ideally it would check how much free space there is,
246+
# instead of repeatedly trying smaller sizes)
247+
while 'bottom' in self.listbox.ends_visible((maxcol - 2, rows - 3)):
248+
rows -= 1
249+
250+
# If we're displaying above the cursor move the top edge down:
251+
if not y:
252+
y = cursor_y - rows
253+
237254
# The top window never gets focus.
238255
top_c = self.top_w.render((maxcol, rows))
239256

@@ -469,7 +486,7 @@ def main(args=None, locals_=None, banner=None):
469486
tooltip = urwid.ListBox(urwid.SimpleListWalker([
470487
urwid.Text(''), urwid.Text(''), urwid.Text('')]))
471488
# TODO: this linebox should use the 'main' color.
472-
overlay = Tooltip(listbox, urwid.LineBox(tooltip))
489+
overlay = Tooltip(listbox, tooltip)
473490

474491
frame = urwid.Frame(overlay, footer=statusbar.widget)
475492

0 commit comments

Comments
 (0)