@@ -187,17 +187,21 @@ class Tooltip(urwid.BoxWidget):
187
187
188
188
"""Container inspired by Overlay to position our tooltip.
189
189
190
+ bottom_w should be a BoxWidget.
191
+ The top window currently has to be a listbox to support shrinkwrapping.
192
+
190
193
This passes keyboard events to the bottom instead of the top window.
191
194
192
195
It also positions the top window relative to the cursor position
193
196
from the bottom window and hides it if there is no cursor.
194
197
"""
195
198
196
- def __init__ (self , bottom_w , top_w ):
199
+ def __init__ (self , bottom_w , listbox ):
197
200
self .__super .__init__ ()
198
201
199
202
self .bottom_w = bottom_w
200
- self .top_w = top_w
203
+ self .listbox = listbox
204
+ self .top_w = urwid .LineBox (listbox )
201
205
202
206
def selectable (self ):
203
207
return self .bottom_w .selectable ()
@@ -224,7 +228,6 @@ def render(self, size, focus=False):
224
228
# Hide the tooltip if there is no cursor.
225
229
return bottom_c
226
230
227
- # TODO: deal with the tooltip not needing all the space we have.
228
231
cursor_x , cursor_y = cursor
229
232
if cursor_y * 2 < maxrow :
230
233
# Cursor is in the top half. Tooltip goes below it:
@@ -234,6 +237,20 @@ def render(self, size, focus=False):
234
237
# Cursor is in the bottom half. Tooltip fills the area above:
235
238
y = 0
236
239
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
+
237
254
# The top window never gets focus.
238
255
top_c = self .top_w .render ((maxcol , rows ))
239
256
@@ -469,7 +486,7 @@ def main(args=None, locals_=None, banner=None):
469
486
tooltip = urwid .ListBox (urwid .SimpleListWalker ([
470
487
urwid .Text ('' ), urwid .Text ('' ), urwid .Text ('' )]))
471
488
# TODO: this linebox should use the 'main' color.
472
- overlay = Tooltip (listbox , urwid . LineBox ( tooltip ) )
489
+ overlay = Tooltip (listbox , tooltip )
473
490
474
491
frame = urwid .Frame (overlay , footer = statusbar .widget )
475
492
0 commit comments