urwid 2.6.0.post0__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Potentially problematic release.
This version of urwid might be problematic. Click here for more details.
- urwid/__init__.py +333 -0
- urwid/canvas.py +1413 -0
- urwid/command_map.py +137 -0
- urwid/container.py +59 -0
- urwid/decoration.py +65 -0
- urwid/display/__init__.py +97 -0
- urwid/display/_posix_raw_display.py +413 -0
- urwid/display/_raw_display_base.py +914 -0
- urwid/display/_web.css +12 -0
- urwid/display/_web.js +462 -0
- urwid/display/_win32.py +171 -0
- urwid/display/_win32_raw_display.py +269 -0
- urwid/display/common.py +1219 -0
- urwid/display/curses.py +690 -0
- urwid/display/escape.py +624 -0
- urwid/display/html_fragment.py +251 -0
- urwid/display/lcd.py +518 -0
- urwid/display/raw.py +37 -0
- urwid/display/web.py +636 -0
- urwid/event_loop/__init__.py +55 -0
- urwid/event_loop/abstract_loop.py +175 -0
- urwid/event_loop/asyncio_loop.py +231 -0
- urwid/event_loop/glib_loop.py +294 -0
- urwid/event_loop/main_loop.py +721 -0
- urwid/event_loop/select_loop.py +230 -0
- urwid/event_loop/tornado_loop.py +206 -0
- urwid/event_loop/trio_loop.py +302 -0
- urwid/event_loop/twisted_loop.py +269 -0
- urwid/event_loop/zmq_loop.py +275 -0
- urwid/font.py +695 -0
- urwid/graphics.py +96 -0
- urwid/highlight.css +19 -0
- urwid/listbox.py +1899 -0
- urwid/monitored_list.py +522 -0
- urwid/numedit.py +376 -0
- urwid/signals.py +330 -0
- urwid/split_repr.py +130 -0
- urwid/str_util.py +358 -0
- urwid/text_layout.py +632 -0
- urwid/treetools.py +515 -0
- urwid/util.py +557 -0
- urwid/version.py +16 -0
- urwid/vterm.py +1806 -0
- urwid/widget/__init__.py +181 -0
- urwid/widget/attr_map.py +161 -0
- urwid/widget/attr_wrap.py +140 -0
- urwid/widget/bar_graph.py +649 -0
- urwid/widget/big_text.py +77 -0
- urwid/widget/box_adapter.py +126 -0
- urwid/widget/columns.py +1145 -0
- urwid/widget/constants.py +574 -0
- urwid/widget/container.py +227 -0
- urwid/widget/divider.py +110 -0
- urwid/widget/edit.py +718 -0
- urwid/widget/filler.py +403 -0
- urwid/widget/frame.py +539 -0
- urwid/widget/grid_flow.py +539 -0
- urwid/widget/line_box.py +194 -0
- urwid/widget/overlay.py +829 -0
- urwid/widget/padding.py +597 -0
- urwid/widget/pile.py +971 -0
- urwid/widget/popup.py +170 -0
- urwid/widget/progress_bar.py +141 -0
- urwid/widget/scrollable.py +597 -0
- urwid/widget/solid_fill.py +44 -0
- urwid/widget/text.py +354 -0
- urwid/widget/widget.py +852 -0
- urwid/widget/widget_decoration.py +166 -0
- urwid/widget/wimp.py +792 -0
- urwid/wimp.py +23 -0
- urwid-2.6.0.post0.dist-info/COPYING +504 -0
- urwid-2.6.0.post0.dist-info/METADATA +332 -0
- urwid-2.6.0.post0.dist-info/RECORD +75 -0
- urwid-2.6.0.post0.dist-info/WHEEL +5 -0
- urwid-2.6.0.post0.dist-info/top_level.txt +1 -0
urwid/widget/line_box.py
ADDED
|
@@ -0,0 +1,194 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
import typing
|
|
4
|
+
|
|
5
|
+
from .columns import Columns
|
|
6
|
+
from .constants import BOX_SYMBOLS, Align, WHSettings
|
|
7
|
+
from .divider import Divider
|
|
8
|
+
from .pile import Pile
|
|
9
|
+
from .solid_fill import SolidFill
|
|
10
|
+
from .text import Text
|
|
11
|
+
from .widget_decoration import WidgetDecoration, delegate_to_widget_mixin
|
|
12
|
+
|
|
13
|
+
if typing.TYPE_CHECKING:
|
|
14
|
+
from typing_extensions import Literal
|
|
15
|
+
|
|
16
|
+
from .widget import Widget
|
|
17
|
+
|
|
18
|
+
WrappedWidget = typing.TypeVar("WrappedWidget")
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
class LineBox(WidgetDecoration[WrappedWidget], delegate_to_widget_mixin("_wrapped_widget")):
|
|
22
|
+
Symbols = BOX_SYMBOLS
|
|
23
|
+
|
|
24
|
+
def __init__(
|
|
25
|
+
self,
|
|
26
|
+
original_widget: WrappedWidget,
|
|
27
|
+
title: str = "",
|
|
28
|
+
title_align: Literal["left", "center", "right"] | Align = Align.CENTER,
|
|
29
|
+
title_attr=None,
|
|
30
|
+
tlcorner: str = BOX_SYMBOLS.LIGHT.TOP_LEFT,
|
|
31
|
+
tline: str = BOX_SYMBOLS.LIGHT.HORIZONTAL,
|
|
32
|
+
lline: str = BOX_SYMBOLS.LIGHT.VERTICAL,
|
|
33
|
+
trcorner: str = BOX_SYMBOLS.LIGHT.TOP_RIGHT,
|
|
34
|
+
blcorner: str = BOX_SYMBOLS.LIGHT.BOTTOM_LEFT,
|
|
35
|
+
rline: str = BOX_SYMBOLS.LIGHT.VERTICAL,
|
|
36
|
+
bline: str = BOX_SYMBOLS.LIGHT.HORIZONTAL,
|
|
37
|
+
brcorner: str = BOX_SYMBOLS.LIGHT.BOTTOM_RIGHT,
|
|
38
|
+
) -> None:
|
|
39
|
+
"""
|
|
40
|
+
Draw a line around original_widget.
|
|
41
|
+
|
|
42
|
+
Use 'title' to set an initial title text with will be centered
|
|
43
|
+
on top of the box.
|
|
44
|
+
|
|
45
|
+
Use `title_attr` to apply a specific attribute to the title text.
|
|
46
|
+
|
|
47
|
+
Use `title_align` to align the title to the 'left', 'right', or 'center'.
|
|
48
|
+
The default is 'center'.
|
|
49
|
+
|
|
50
|
+
You can also override the widgets used for the lines/corners:
|
|
51
|
+
tline: top line
|
|
52
|
+
bline: bottom line
|
|
53
|
+
lline: left line
|
|
54
|
+
rline: right line
|
|
55
|
+
tlcorner: top left corner
|
|
56
|
+
trcorner: top right corner
|
|
57
|
+
blcorner: bottom left corner
|
|
58
|
+
brcorner: bottom right corner
|
|
59
|
+
|
|
60
|
+
If empty string is specified for one of the lines/corners, then no character will be output there.
|
|
61
|
+
If no top/bottom/left/right lines - whole lines will be omitted.
|
|
62
|
+
This allows for seamless use of adjoining LineBoxes.
|
|
63
|
+
|
|
64
|
+
Class attribute `Symbols` can be used as source for standard lines:
|
|
65
|
+
|
|
66
|
+
>>> print(LineBox(Text("Some text")).render(()))
|
|
67
|
+
┌─────────┐
|
|
68
|
+
│Some text│
|
|
69
|
+
└─────────┘
|
|
70
|
+
>>> print(
|
|
71
|
+
... LineBox(
|
|
72
|
+
... Text("Some text"),
|
|
73
|
+
... tlcorner=LineBox.Symbols.LIGHT.TOP_LEFT_ROUNDED,
|
|
74
|
+
... trcorner=LineBox.Symbols.LIGHT.TOP_RIGHT_ROUNDED,
|
|
75
|
+
... blcorner=LineBox.Symbols.LIGHT.BOTTOM_LEFT_ROUNDED,
|
|
76
|
+
... brcorner=LineBox.Symbols.LIGHT.BOTTOM_RIGHT_ROUNDED,
|
|
77
|
+
... ).render(())
|
|
78
|
+
... )
|
|
79
|
+
╭─────────╮
|
|
80
|
+
│Some text│
|
|
81
|
+
╰─────────╯
|
|
82
|
+
>>> print(
|
|
83
|
+
... LineBox(
|
|
84
|
+
... Text("Some text"),
|
|
85
|
+
... tline=LineBox.Symbols.HEAVY.HORIZONTAL,
|
|
86
|
+
... bline=LineBox.Symbols.HEAVY.HORIZONTAL,
|
|
87
|
+
... lline=LineBox.Symbols.HEAVY.VERTICAL,
|
|
88
|
+
... rline=LineBox.Symbols.HEAVY.VERTICAL,
|
|
89
|
+
... tlcorner=LineBox.Symbols.HEAVY.TOP_LEFT,
|
|
90
|
+
... trcorner=LineBox.Symbols.HEAVY.TOP_RIGHT,
|
|
91
|
+
... blcorner=LineBox.Symbols.HEAVY.BOTTOM_LEFT,
|
|
92
|
+
... brcorner=LineBox.Symbols.HEAVY.BOTTOM_RIGHT,
|
|
93
|
+
... ).render(())
|
|
94
|
+
... )
|
|
95
|
+
┏━━━━━━━━━┓
|
|
96
|
+
┃Some text┃
|
|
97
|
+
┗━━━━━━━━━┛
|
|
98
|
+
|
|
99
|
+
To make Table constructions, some lineboxes need to be drawn without sides
|
|
100
|
+
and T or CROSS symbols used for corners of cells.
|
|
101
|
+
"""
|
|
102
|
+
|
|
103
|
+
w_lline = SolidFill(lline)
|
|
104
|
+
w_rline = SolidFill(rline)
|
|
105
|
+
|
|
106
|
+
w_tlcorner, w_tline, w_trcorner = Text(tlcorner), Divider(tline), Text(trcorner)
|
|
107
|
+
w_blcorner, w_bline, w_brcorner = Text(blcorner), Divider(bline), Text(brcorner)
|
|
108
|
+
|
|
109
|
+
if not tline and title:
|
|
110
|
+
raise ValueError("Cannot have a title when tline is empty string")
|
|
111
|
+
|
|
112
|
+
if title_attr:
|
|
113
|
+
self.title_widget = Text((title_attr, self.format_title(title)))
|
|
114
|
+
else:
|
|
115
|
+
self.title_widget = Text(self.format_title(title))
|
|
116
|
+
|
|
117
|
+
if tline:
|
|
118
|
+
if title_align not in {Align.LEFT, Align.CENTER, Align.RIGHT}:
|
|
119
|
+
raise ValueError('title_align must be one of "left", "right", or "center"')
|
|
120
|
+
if title_align == Align.LEFT:
|
|
121
|
+
tline_widgets = [(WHSettings.PACK, self.title_widget), w_tline]
|
|
122
|
+
else:
|
|
123
|
+
tline_widgets = [w_tline, (WHSettings.PACK, self.title_widget)]
|
|
124
|
+
if title_align == Align.CENTER:
|
|
125
|
+
tline_widgets.append(w_tline)
|
|
126
|
+
|
|
127
|
+
self.tline_widget = Columns(tline_widgets)
|
|
128
|
+
top = Columns(
|
|
129
|
+
(
|
|
130
|
+
(int(bool(tlcorner and lline)), w_tlcorner),
|
|
131
|
+
self.tline_widget,
|
|
132
|
+
(int(bool(trcorner and rline)), w_trcorner),
|
|
133
|
+
)
|
|
134
|
+
)
|
|
135
|
+
|
|
136
|
+
else:
|
|
137
|
+
self.tline_widget = None
|
|
138
|
+
top = None
|
|
139
|
+
|
|
140
|
+
# Note: We need to define a fixed first widget (even if it's 0 width) so that the other
|
|
141
|
+
# widgets have something to anchor onto
|
|
142
|
+
middle = Columns(
|
|
143
|
+
((int(bool(lline)), w_lline), original_widget, (int(bool(rline)), w_rline)),
|
|
144
|
+
box_columns=[0, 2],
|
|
145
|
+
focus_column=original_widget,
|
|
146
|
+
)
|
|
147
|
+
|
|
148
|
+
if bline:
|
|
149
|
+
bottom = Columns(
|
|
150
|
+
(
|
|
151
|
+
(int(bool(blcorner and lline)), w_blcorner),
|
|
152
|
+
w_bline,
|
|
153
|
+
(int(bool(brcorner and rline)), w_brcorner),
|
|
154
|
+
)
|
|
155
|
+
)
|
|
156
|
+
else:
|
|
157
|
+
bottom = None
|
|
158
|
+
|
|
159
|
+
pile_widgets = []
|
|
160
|
+
if top:
|
|
161
|
+
pile_widgets.append((WHSettings.PACK, top))
|
|
162
|
+
pile_widgets.append(middle)
|
|
163
|
+
if bottom:
|
|
164
|
+
pile_widgets.append((WHSettings.PACK, bottom))
|
|
165
|
+
|
|
166
|
+
self._wrapped_widget = Pile(pile_widgets, focus_item=middle)
|
|
167
|
+
|
|
168
|
+
super().__init__(original_widget)
|
|
169
|
+
|
|
170
|
+
@property
|
|
171
|
+
def _w(self) -> Pile:
|
|
172
|
+
return self._wrapped_widget
|
|
173
|
+
|
|
174
|
+
def format_title(self, text: str) -> str:
|
|
175
|
+
if text:
|
|
176
|
+
return f" {text} "
|
|
177
|
+
|
|
178
|
+
return ""
|
|
179
|
+
|
|
180
|
+
def set_title(self, text: str) -> None:
|
|
181
|
+
if not self.tline_widget:
|
|
182
|
+
raise ValueError("Cannot set title when tline is unset")
|
|
183
|
+
self.title_widget.set_text(self.format_title(text))
|
|
184
|
+
self.tline_widget._invalidate()
|
|
185
|
+
|
|
186
|
+
@property
|
|
187
|
+
def focus(self) -> Widget | None:
|
|
188
|
+
"""LineBox is partially container.
|
|
189
|
+
|
|
190
|
+
While focus position is a bit hacky
|
|
191
|
+
(formally it's not container and only position 0 available),
|
|
192
|
+
focus widget is always provided by original widget.
|
|
193
|
+
"""
|
|
194
|
+
return self._original_widget.focus
|