summaryrefslogtreecommitdiff
path: root/urwid/container.py
diff options
context:
space:
mode:
Diffstat (limited to 'urwid/container.py')
-rwxr-xr-xurwid/container.py83
1 files changed, 58 insertions, 25 deletions
diff --git a/urwid/container.py b/urwid/container.py
index ed4ee59..98d057a 100755
--- a/urwid/container.py
+++ b/urwid/container.py
@@ -1158,7 +1158,7 @@ class Frame(Widget, WidgetContainerMixin):
if not hasattr(self.footer, 'mouse_event'):
return False
return self.footer.mouse_event( (maxcol,), event,
- button, col, row-maxrow+frows, focus )
+ button, col, row-maxrow+ftrim, focus )
# within body
focus = focus and self.focus_part == 'body'
@@ -1171,6 +1171,33 @@ class Frame(Widget, WidgetContainerMixin):
return self.body.mouse_event( (maxcol, maxrow-htrim-ftrim),
event, button, col, row-htrim, focus )
+ def get_cursor_coords(self, size):
+ """Return the cursor coordinates of the focus widget."""
+ if not self.focus.selectable():
+ return None
+ if not hasattr(self.focus, 'get_cursor_coords'):
+ return None
+
+ fp = self.focus_position
+ (maxcol, maxrow) = size
+ (hrows, frows), _ = self.frame_top_bottom(size, True)
+
+ if fp == 'header':
+ row_adjust = 0
+ coords = self.header.get_cursor_coords((maxcol,))
+ elif fp == 'body':
+ row_adjust = hrows
+ coords = self.body.get_cursor_coords((maxcol, maxrow-hrows-frows))
+ else:
+ row_adjust = maxrow - frows
+ coords = self.footer.get_cursor_coords((maxcol,))
+
+ if coords is None:
+ return None
+
+ x, y = coords
+ return x, y + row_adjust
+
def __iter__(self):
"""
Return an iterator over the positions in this Frame top to bottom.
@@ -1227,11 +1254,12 @@ class Pile(Widget, WidgetContainerMixin, WidgetContainerListContentsMixin):
.. note:: If the Pile is treated as a box widget there must be at least
one ``'weight'`` tuple in :attr:`widget_list`.
"""
+ self._selectable = False
self.__super.__init__()
self._contents = MonitoredFocusList()
- self._contents.set_modified_callback(self._invalidate)
+ self._contents.set_modified_callback(self._contents_modified)
self._contents.set_focus_changed_callback(lambda f: self._invalidate())
- self._contents.set_validate_contents_modified(self._contents_modified)
+ self._contents.set_validate_contents_modified(self._validate_contents_modified)
focus_item = focus_item
for i, original in enumerate(widget_list):
@@ -1261,7 +1289,15 @@ class Pile(Widget, WidgetContainerMixin, WidgetContainerListContentsMixin):
self.pref_col = 0
- def _contents_modified(self, slc, new_items):
+ def _contents_modified(self):
+ """
+ Recalculate whether this widget should be selectable whenever the
+ contents has been changed.
+ """
+ self._selectable = any(w.selectable() for w, o in self.contents)
+ self._invalidate()
+
+ def _validate_contents_modified(self, slc, new_items):
for item in new_items:
try:
w, (t, n) = item
@@ -1361,11 +1397,6 @@ class Pile(Widget, WidgetContainerMixin, WidgetContainerListContentsMixin):
raise PileError('invalid height_type: %r' % (height_type,))
return (height_type, height_amount)
- def selectable(self):
- """Return True if the focus item is selectable."""
- w = self.focus
- return w is not None and w.selectable()
-
def set_focus(self, item):
"""
Set the item in focus, for backwards compatibility.
@@ -1736,11 +1767,12 @@ class Columns(Widget, WidgetContainerMixin, WidgetContainerListContentsMixin):
*box_columns* will be displayed with this calculated number of rows,
filling the full height.
"""
+ self._selectable = False
self.__super.__init__()
self._contents = MonitoredFocusList()
- self._contents.set_modified_callback(self._invalidate)
+ self._contents.set_modified_callback(self._contents_modified)
self._contents.set_focus_changed_callback(lambda f: self._invalidate())
- self._contents.set_validate_contents_modified(self._contents_modified)
+ self._contents.set_validate_contents_modified(self._validate_contents_modified)
box_columns = set(box_columns or ())
@@ -1772,13 +1804,19 @@ class Columns(Widget, WidgetContainerMixin, WidgetContainerListContentsMixin):
if self.contents and focus_column is not None:
self.focus_position = focus_column
- if focus_column is None:
- focus_column = 0
self.pref_col = None
self.min_width = min_width
self._cache_maxcol = None
- def _contents_modified(self, slc, new_items):
+ def _contents_modified(self):
+ """
+ Recalculate whether this widget should be selectable whenever the
+ contents has been changed.
+ """
+ self._selectable = any(w.selectable() for w, o in self.contents)
+ self._invalidate()
+
+ def _validate_contents_modified(self, slc, new_items):
for item in new_items:
try:
w, (t, n, b) = item
@@ -2014,7 +2052,7 @@ class Columns(Widget, WidgetContainerMixin, WidgetContainerListContentsMixin):
elif t == PACK:
# FIXME: should be able to pack with a different
# maxcol value
- static_w = w.pack((maxcol,), focus)[0]
+ static_w = w.pack((maxcol,), focus and i == self.focus_position)[0]
else:
static_w = self.min_width
@@ -2265,10 +2303,11 @@ class Columns(Widget, WidgetContainerMixin, WidgetContainerListContentsMixin):
if self._command_map[key] not in ('cursor up', 'cursor down',
'cursor page up', 'cursor page down'):
self.pref_col = None
- if len(size) == 1 and b:
- key = w.keypress((mc, self.rows(size, True)), key)
- else:
- key = w.keypress((mc,) + size[1:], key)
+ if w.selectable():
+ if len(size) == 1 and b:
+ key = w.keypress((mc, self.rows(size, True)), key)
+ else:
+ key = w.keypress((mc,) + size[1:], key)
if self._command_map[key] not in ('cursor left', 'cursor right'):
return key
@@ -2287,12 +2326,6 @@ class Columns(Widget, WidgetContainerMixin, WidgetContainerListContentsMixin):
return key
- def selectable(self):
- """Return the selectable value of the focus column."""
- w = self.focus
- return w is not None and w.selectable()
-
-