[elbe-devel] [PATCH 06/14] Debianize - Grid widget

Bastian Germann bage at linutronix.de
Thu Aug 1 15:13:42 CEST 2019


> From: Olivier Dion <dion at linutronix.de>
> 
> Urwid is a poor library that offer next to nothing in term of good

offers

> widgets.  The grid widget is a recursive abstraction around column and
> pile widgets.
> 
> One can nest grid inside of grid .. and so on.  Grids also accept the
> emac's keybinding format to move around.
> 
> Signed-off-by: Olivier Dion <dion at linutronix.de>
> ---
>  elbepack/debianize/widgets/grid.py | 130 +++++++++++++++++++++++++++++++++++++
>  1 file changed, 130 insertions(+)
>  create mode 100644 elbepack/debianize/widgets/grid.py
> 
> diff --git a/elbepack/debianize/widgets/grid.py b/elbepack/debianize/widgets/grid.py
> new file mode 100644
> index 00000000..1112fcbd
> --- /dev/null
> +++ b/elbepack/debianize/widgets/grid.py
> @@ -0,0 +1,130 @@
> +# ELBE - Debian Based Embedded Rootfilesystem Builder
> +# Copyright (c) 2019 Olivier Dion <dion at linutronix.de>
> +#
> +# SPDX-License-Identifier: GPL-3.0-or-later
> +
> +
> +from urwid import (
> +    Columns,
> +    Pile as Rows,
> +    WidgetWrap
> +)
> +
> +
> +class Grid(WidgetWrap):
> +
> +    def __init__(self, rows):
> +
> +        m = 1
> +        cols = []
> +
> +        for row in rows:
> +            if len(row) > m:
> +                m = len(row)
> +
> +            for c in row:
> +                if isinstance(c, Grid):
> +                    c.parent = self
> +
> +            cols.append(Columns(row))
> +
> +        super().__init__(Rows(cols))
> +
> +        self.n = len(rows)
> +        self.m = m
> +
> +        self.i = 0
> +        self.j = 0
> +
> +        self.focus(self.i, self.j)
> +
> +        self.keybind = {
> +            "down"     : lambda: self.focus_recursive(forward=True, horizontal=False),
> +            "up"       : lambda: self.focus_recursive(forward=False, horizontal=False),
> +            "tab"      : lambda: self.focus_recursive(forward=True, horizontal=True),
> +            "shift tab": lambda: self.focus_recursive(forward=False, horizontal=True)

We only have one lambda in the current code base. If you can avoid it
here, please do so.

> +        }
> +
> +        self.aliases = {
> +            "ctrl f": "right",
> +            "ctrl b": "left",
> +            "ctrl p": "up",
> +            "ctrl n": "down"
> +        }
> +
> +        self.parent = None
> +
> +    def focus_direction(self, forward: bool, horizontal: bool):
> +
> +        j = self.j
> +        i = self.i
> +        direction = 1 if forward else -1
> +
> +        while True:
> +            if horizontal:
> +                j += direction
> +                i += j // self.m
> +            else:
> +                i += direction
> +                j += i // self.n
> +
> +            i %= self.n
> +            j %= self.m
> +
> +            try:
> +                self.focus(i, j)
> +                break
> +            except IndexError:
> +                pass
> +
> +    def focus_recursive(self, forward: bool, horizontal: bool):
> +        while True:
> +            child = self.current_focus()
> +
> +            if isinstance(child, Grid):
> +                child.focus_recursive(forward, horizontal)
> +            elif not forward and self._is_first():
> +                if self.parent is not None and not self.parent._is_first():
> +                    return self.parent.focus_direction(forward, horizontal)
> +                else:
> +                    self.focus_direction(forward, horizontal)
> +            elif forward and self._is_last():
> +                if self.parent is not None and not self.parent._is_last():
> +                    return self.parent.focus_direction(forward, horizontal)
> +                else:
> +                    self.focus_direction(forward, horizontal)
> +            else:
> +                self.focus_direction(forward, horizontal)
> +
> +            if self.current_focus().selectable():
> +                break
> +
> +    def focus_first(self):
> +        self.focus(0, 0)
> +        self.i = 0
> +        self.j = 0
> +
> +    def focus(self, i, j):
> +        self._w.base_widget.set_focus_path([i, j])
> +        self.i = i
> +        self.j = j
> +
> +    def current_focus(self):
> +        return self._w.base_widget.contents[self.i][0].contents[self.j][0].base_widget
> +
> +    def _is_last(self):
> +        return self.i == self.n - 1 and self.j == self.m - 1
> +
> +    def _is_first(self):
> +        return self.i == 0 and self.j == 0
> +
> +    def keypress(self, size, key):
> +
> +        if key in self.aliases:
> +            key = self.aliases[key]
> +
> +        if key in self.keybind:
> +            self.keybind[key]()
> +            return None
> +
> +        return super().keypress(size, key)
> 

with the suggested changes
Reviewed-by: Bastian Germann <bage at linutronix.de>



More information about the elbe-devel mailing list