diff options
Diffstat (limited to 'urwid/container.py')
-rwxr-xr-x | urwid/container.py | 83 |
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() - - |