From d315751d602c94cbaa97259a5844f4a9b934fea4 Mon Sep 17 00:00:00 2001 From: Michael Hudson-Doyle Date: Mon, 11 Jun 2018 12:42:29 +1200 Subject: [PATCH] add our own version of WidgetWrap urwid doesn't know about the _select_first/last_selectable methods our containers use to make tab-cycling work so its WidgetWrap doesn't forward them along. So add a WidgetWrap that does, and use it in the one place that it matters so far (more coming soon!). --- subiquity/ui/views/snaplist.py | 15 +++++++-------- subiquitycore/ui/container.py | 20 ++++++++++++++++++++ 2 files changed, 27 insertions(+), 8 deletions(-) diff --git a/subiquity/ui/views/snaplist.py b/subiquity/ui/views/snaplist.py index 0200d0ba..85b76be8 100644 --- a/subiquity/ui/views/snaplist.py +++ b/subiquity/ui/views/snaplist.py @@ -23,11 +23,16 @@ from urwid import ( SelectableIcon, SimpleFocusListWalker, Text, - WidgetWrap, ) from subiquitycore.ui.buttons import ok_btn, cancel_btn, other_btn -from subiquitycore.ui.container import Columns, ListBox, Pile, ScrollBarListBox +from subiquitycore.ui.container import ( + Columns, + ListBox, + Pile, + ScrollBarListBox, + WidgetWrap, + ) from subiquitycore.ui.utils import button_pile, Color, screen from subiquitycore.view import BaseView @@ -67,12 +72,6 @@ class SnapInfoView(WidgetWrap): # the channel list is given a third of the space. If there is # space for both, they are packed into the upper part of the view. - def _select_first_selectable(self): - self._w._select_first_selectable() - - def _select_last_selectable(self): - self._w._select_last_selectable() - def __init__(self, parent, snap, cur_channel): self.parent = parent self.snap = snap diff --git a/subiquitycore/ui/container.py b/subiquitycore/ui/container.py index 0018f664..046811ea 100644 --- a/subiquitycore/ui/container.py +++ b/subiquitycore/ui/container.py @@ -62,6 +62,7 @@ too many elements in the ListBox. """ import logging +import operator import urwid @@ -496,3 +497,22 @@ def ListBox(body=None): if body is getattr(body, 'get_focus', None) is None: body = urwid.SimpleFocusListWalker(body) return ScrollBarListBox(FocusTrackingListBox(body)) + + +get_delegate = operator.attrgetter("_wrapped_widget") + + +class OurWidgetWrap(urwid.WidgetWrap): + # A wrapped widget needs to have a _select_first/last_selectable + # method if and only if the widget being wrapped does, so we + # define our own WidgetWrap class that uses the same technique to + # forward these methods along if present as urwid's WidgetWrap + # does. + + _select_first_selectable = property( + lambda self: get_delegate(self)._select_first_selectable) + _select_last_selectable = property( + lambda self: get_delegate(self)._select_last_selectable) + + +WidgetWrap = OurWidgetWrap