From 7ce9d0d1c3205c771ef799f02add867f37326041 Mon Sep 17 00:00:00 2001 From: Toshio Kuratomi Date: Sat, 21 Jan 2017 13:33:35 -0800 Subject: Additional listbox functionality * Add title_align as a new keyword argument to construct a ListBox. It allows justifying a ListBox to the left or right in addition to centering it. This can be useful for constructing columns out of ListBoxes. * Implement borderless sides. If a ListBox is created with lines or corners set to the empty string then do not create a border element for them. This allows adjoining list boxes to share a single border, or two ListBoxes to seamlessly merge into one another. Fixes #211 --- urwid/graphics.py | 93 +++++++++++++++++++++++++++++++++++++++---------------- 1 file changed, 67 insertions(+), 26 deletions(-) diff --git a/urwid/graphics.py b/urwid/graphics.py index cb852b0..3d2046b 100755 --- a/urwid/graphics.py +++ b/urwid/graphics.py @@ -96,7 +96,7 @@ class BigText(Widget): class LineBox(WidgetDecoration, WidgetWrap): - def __init__(self, original_widget, title="", + def __init__(self, original_widget, title="", title_align="center", tlcorner=u'┌', tline=u'─', lline=u'│', trcorner=u'┐', blcorner=u'└', rline=u'│', bline=u'─', brcorner=u'┘'): @@ -106,6 +106,9 @@ class LineBox(WidgetDecoration, WidgetWrap): Use 'title' to set an initial title text with will be centered on top of the box. + Use `title_align` to align the title to the 'left', 'right', or 'center'. + The default is 'center'. + You can also override the widgets used for the lines/corners: tline: top line bline: bottom line @@ -116,37 +119,73 @@ class LineBox(WidgetDecoration, WidgetWrap): blcorner: bottom left corner brcorner: bottom right corner + If empty string is specified for one of the lines/corners, then no + character will be output there. This allows for seamless use of + adjoining LineBoxes. """ - tline, bline = Divider(tline), Divider(bline) - lline, rline = SolidFill(lline), SolidFill(rline) + if tline: + tline = Divider(tline) + if bline: + bline = Divider(bline) + if lline: + lline = SolidFill(lline) + if rline: + rline = SolidFill(rline) tlcorner, trcorner = Text(tlcorner), Text(trcorner) blcorner, brcorner = Text(blcorner), Text(brcorner) + if not tline and title: + raise ValueError('Cannot have a title when tline is empty string') + self.title_widget = Text(self.format_title(title)) - self.tline_widget = Columns([ - tline, - ('flow', self.title_widget), - tline, - ]) - - top = Columns([ - ('fixed', 1, tlcorner), - self.tline_widget, - ('fixed', 1, trcorner) - ]) - - middle = Columns([ - ('fixed', 1, lline), - original_widget, - ('fixed', 1, rline), - ], box_columns=[0, 2], focus_column=1) - - bottom = Columns([ - ('fixed', 1, blcorner), bline, ('fixed', 1, brcorner) - ]) - - pile = Pile([('flow', top), middle, ('flow', bottom)], focus_item=1) + + if tline: + if title_align not in ('left', 'center', 'right'): + raise ValueError('title_align must be one of "left", "right", or "center"') + if title_align == 'left': + tline_widgets = [('flow', self.title_widget), tline] + else: + tline_widgets = [tline, ('flow', self.title_widget)] + if title_align == 'center': + tline_widgets.append(tline) + self.tline_widget = Columns(tline_widgets) + top = Columns([ + ('fixed', 1, tlcorner), + self.tline_widget, + ('fixed', 1, trcorner) + ]) + + else: + self.tline_widget = None + top = None + + middle_widgets = [] + if lline: + middle_widgets.append(('fixed', 1, lline)) + middle_widgets.append(original_widget) + focus_col = len(middle_widgets) - 1 + if rline: + middle_widgets.append(('fixed', 1, rline)) + + middle = Columns(middle_widgets, + box_columns=[0, 2], focus_column=focus_col) + + if bline: + bottom = Columns([ + ('fixed', 1, blcorner), bline, ('fixed', 1, brcorner) + ]) + else: + bottom = None + + pile_widgets = [] + if top: + pile_widgets.append(('flow', top)) + pile_widgets.append(middle) + focus_pos = len(pile_widgets) - 1 + if bottom: + pile_widgets.append(('flow', bottom)) + pile = Pile(pile_widgets, focus_item=focus_pos) WidgetDecoration.__init__(self, original_widget) WidgetWrap.__init__(self, pile) @@ -158,6 +197,8 @@ class LineBox(WidgetDecoration, WidgetWrap): return "" def set_title(self, text): + if not self.title_widget: + raise ValueError('Cannot set title when tline is unset') self.title_widget.set_text(self.format_title(text)) self.tline_widget._invalidate() -- cgit v1.2.1 From 7f4060cd5cb5645153a211d3169b9f7e585586ae Mon Sep 17 00:00:00 2001 From: Toshio Kuratomi Date: Sat, 6 Jan 2018 15:59:19 -0800 Subject: Correct problem with defining no left line character breaking later widget layout --- urwid/graphics.py | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/urwid/graphics.py b/urwid/graphics.py index 3d2046b..43a274f 100755 --- a/urwid/graphics.py +++ b/urwid/graphics.py @@ -163,6 +163,10 @@ class LineBox(WidgetDecoration, WidgetWrap): middle_widgets = [] if lline: middle_widgets.append(('fixed', 1, lline)) + else: + # Note: We need to define a fixed first widget (even if it's 0 width) so that the other + # widgets have something to anchor onto + middle_widgets.append(('fixed', 0, SolidFill(u""))) middle_widgets.append(original_widget) focus_col = len(middle_widgets) - 1 if rline: -- cgit v1.2.1