curses-utils2 0.3.2__tar.gz → 0.4.0__tar.gz
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.
- {curses_utils2-0.3.2 → curses_utils2-0.4.0}/PKG-INFO +1 -1
- curses_utils2-0.4.0/curses_utils2/__init__.py +1 -0
- curses_utils2-0.4.0/curses_utils2/list1_v2.py +183 -0
- curses_utils2-0.4.0/curses_utils2/list1m_v2.py +56 -0
- curses_utils2-0.4.0/curses_utils2/list3_v2.py +208 -0
- curses_utils2-0.4.0/curses_utils2/proto.py +12 -0
- curses_utils2-0.4.0/curses_utils2/winbox.py +58 -0
- curses_utils2-0.3.2/curses_utils2/__init__.py +0 -1
- {curses_utils2-0.3.2 → curses_utils2-0.4.0}/LICENSE +0 -0
- {curses_utils2-0.3.2 → curses_utils2-0.4.0}/README.rst +0 -0
- {curses_utils2-0.3.2 → curses_utils2-0.4.0}/curses_utils2/app.py +0 -0
- {curses_utils2-0.3.2 → curses_utils2-0.4.0}/curses_utils2/list1.py +0 -0
- {curses_utils2-0.3.2 → curses_utils2-0.4.0}/curses_utils2/list1m.py +0 -0
- {curses_utils2-0.3.2 → curses_utils2-0.4.0}/curses_utils2/list3.py +0 -0
- {curses_utils2-0.3.2 → curses_utils2-0.4.0}/curses_utils2/listbox.py +0 -0
- {curses_utils2-0.3.2 → curses_utils2-0.4.0}/curses_utils2/py.typed +0 -0
- {curses_utils2-0.3.2 → curses_utils2-0.4.0}/curses_utils2/text.py +0 -0
- {curses_utils2-0.3.2 → curses_utils2-0.4.0}/curses_utils2/win.py +0 -0
- {curses_utils2-0.3.2 → curses_utils2-0.4.0}/pyproject.toml +0 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
__version__ = '0.4.0'
|
|
@@ -0,0 +1,183 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
import curses
|
|
4
|
+
from typing import Protocol
|
|
5
|
+
|
|
6
|
+
from .proto import WinProto
|
|
7
|
+
from .win import win_addstr
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
class ListProto(Protocol):
|
|
11
|
+
def get_record_str(self, i: int) -> str:
|
|
12
|
+
pass
|
|
13
|
+
|
|
14
|
+
def records_len(self) -> int:
|
|
15
|
+
pass
|
|
16
|
+
|
|
17
|
+
def refresh_win_deps(self):
|
|
18
|
+
pass
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
class ListV2(WinProto):
|
|
22
|
+
'''
|
|
23
|
+
A projection of an array of records r0...rX to a window lines of string s0...sY
|
|
24
|
+
where si = get_record_str(j) = rj -> str, s(i+1) = get_record_str(j+1), j < records_len()
|
|
25
|
+
and changing cursor (i) leads to call refresh_win_deps()
|
|
26
|
+
'''
|
|
27
|
+
|
|
28
|
+
def __init__(
|
|
29
|
+
self,
|
|
30
|
+
proto: ListProto,
|
|
31
|
+
current_color: int = curses.A_BOLD,
|
|
32
|
+
):
|
|
33
|
+
self.proto = proto
|
|
34
|
+
self.current_color = current_color
|
|
35
|
+
|
|
36
|
+
self.cur = 0 # cursor y
|
|
37
|
+
self.idx = 0 # source index
|
|
38
|
+
|
|
39
|
+
self.win: curses.window | None = None
|
|
40
|
+
|
|
41
|
+
def set_win(self, win: curses.window | None):
|
|
42
|
+
self.win = win
|
|
43
|
+
if win:
|
|
44
|
+
win.keypad(True)
|
|
45
|
+
|
|
46
|
+
def refresh(self):
|
|
47
|
+
if not self.win:
|
|
48
|
+
self.proto.refresh_win_deps()
|
|
49
|
+
return
|
|
50
|
+
self.win.erase()
|
|
51
|
+
len_ = self.proto.records_len()
|
|
52
|
+
if len_:
|
|
53
|
+
rows, _ = self.win.getmaxyx()
|
|
54
|
+
if not self.idx < len_: # deleted
|
|
55
|
+
self.idx = len_ - 1
|
|
56
|
+
if not self.cur < rows: # new win < old win
|
|
57
|
+
self.cur = rows - 1
|
|
58
|
+
if (rows - self.cur) > (di := len_ - self.idx):
|
|
59
|
+
# gap at bottom
|
|
60
|
+
self.cur = rows - di
|
|
61
|
+
self.cur = min(self.cur, self.idx)
|
|
62
|
+
for i in range(rows):
|
|
63
|
+
idx = self.idx - self.cur + i
|
|
64
|
+
if not idx < len_:
|
|
65
|
+
break
|
|
66
|
+
s = self.proto.get_record_str(idx)
|
|
67
|
+
if i == self.cur:
|
|
68
|
+
win_addstr(self.win, i, 0, s, attr=self.current_color)
|
|
69
|
+
else:
|
|
70
|
+
win_addstr(self.win, i, 0, s)
|
|
71
|
+
self.win.move(self.cur, 0)
|
|
72
|
+
self.win.refresh()
|
|
73
|
+
self.proto.refresh_win_deps()
|
|
74
|
+
|
|
75
|
+
def scroll_top(self):
|
|
76
|
+
self.idx = self.cur = 0
|
|
77
|
+
self.refresh()
|
|
78
|
+
|
|
79
|
+
def scroll_bottom(self):
|
|
80
|
+
if not self.win:
|
|
81
|
+
return
|
|
82
|
+
len_ = self.proto.records_len()
|
|
83
|
+
if not len_:
|
|
84
|
+
return
|
|
85
|
+
rows, _ = self.win.getmaxyx()
|
|
86
|
+
self.cur = min(rows - 1, len_ - 1)
|
|
87
|
+
self.idx = len_ - 1
|
|
88
|
+
self.refresh()
|
|
89
|
+
|
|
90
|
+
def scroll_down(self):
|
|
91
|
+
if not self.win:
|
|
92
|
+
return
|
|
93
|
+
len_ = self.proto.records_len()
|
|
94
|
+
if not len_ or not self.idx + 1 < len_:
|
|
95
|
+
return
|
|
96
|
+
rows, _ = self.win.getmaxyx()
|
|
97
|
+
prev_s = self.proto.get_record_str(self.idx)
|
|
98
|
+
next_s = self.proto.get_record_str(self.idx + 1)
|
|
99
|
+
win_addstr(self.win, self.cur, 0, prev_s)
|
|
100
|
+
if self.cur + 1 < rows:
|
|
101
|
+
self.cur += 1
|
|
102
|
+
else:
|
|
103
|
+
self.win.move(0, 0)
|
|
104
|
+
self.win.deleteln()
|
|
105
|
+
self.cur = rows - 1
|
|
106
|
+
win_addstr(self.win, self.cur, 0, next_s, attr=self.current_color)
|
|
107
|
+
self.idx += 1
|
|
108
|
+
self.win.refresh()
|
|
109
|
+
self.proto.refresh_win_deps()
|
|
110
|
+
|
|
111
|
+
def scroll_up(self):
|
|
112
|
+
if not self.win:
|
|
113
|
+
return
|
|
114
|
+
len_ = self.proto.records_len()
|
|
115
|
+
if not len_ or self.idx - 1 < 0:
|
|
116
|
+
return
|
|
117
|
+
prev_s = self.proto.get_record_str(self.idx)
|
|
118
|
+
next_s = self.proto.get_record_str(self.idx - 1)
|
|
119
|
+
win_addstr(self.win, self.cur, 0, prev_s)
|
|
120
|
+
if self.cur > 0:
|
|
121
|
+
self.cur -= 1
|
|
122
|
+
else:
|
|
123
|
+
self.win.move(0, 0)
|
|
124
|
+
self.win.insdelln(1)
|
|
125
|
+
win_addstr(self.win, self.cur, 0, next_s, attr=self.current_color)
|
|
126
|
+
self.idx -= 1
|
|
127
|
+
self.win.refresh()
|
|
128
|
+
self.proto.refresh_win_deps()
|
|
129
|
+
|
|
130
|
+
def scroll_page_down(self):
|
|
131
|
+
if not self.win:
|
|
132
|
+
return
|
|
133
|
+
len_ = self.proto.records_len()
|
|
134
|
+
if not len_:
|
|
135
|
+
return
|
|
136
|
+
rows, _ = self.win.getmaxyx()
|
|
137
|
+
idx = self.idx + rows
|
|
138
|
+
if idx < len_:
|
|
139
|
+
self.idx = idx
|
|
140
|
+
self.refresh()
|
|
141
|
+
else:
|
|
142
|
+
idx = len_ - 1
|
|
143
|
+
delta = idx - self.idx
|
|
144
|
+
if not delta:
|
|
145
|
+
self.scroll_bottom()
|
|
146
|
+
elif self.cur + delta < rows:
|
|
147
|
+
self.cur += delta
|
|
148
|
+
self.idx = idx
|
|
149
|
+
self.refresh()
|
|
150
|
+
else:
|
|
151
|
+
self.scroll_bottom()
|
|
152
|
+
|
|
153
|
+
def scroll_page_up(self):
|
|
154
|
+
if not self.win:
|
|
155
|
+
return
|
|
156
|
+
len_ = self.proto.records_len()
|
|
157
|
+
if not len_:
|
|
158
|
+
return
|
|
159
|
+
rows, _ = self.win.getmaxyx()
|
|
160
|
+
idx = self.idx - rows
|
|
161
|
+
if not idx < 0:
|
|
162
|
+
self.idx = idx
|
|
163
|
+
self.refresh()
|
|
164
|
+
else:
|
|
165
|
+
self.scroll_top()
|
|
166
|
+
|
|
167
|
+
def handle_input(self, ch: int) -> bool:
|
|
168
|
+
char = chr(ch)
|
|
169
|
+
if char.upper() == 'J' or ch == curses.KEY_DOWN: # Down or J
|
|
170
|
+
self.scroll_down()
|
|
171
|
+
elif char.upper() == 'K' or ch == curses.KEY_UP: # Up or K
|
|
172
|
+
self.scroll_up()
|
|
173
|
+
elif char == 'g' or ch == curses.KEY_HOME: # Move to top
|
|
174
|
+
self.scroll_top()
|
|
175
|
+
elif char == 'G' or ch == curses.KEY_END: # Move to last item
|
|
176
|
+
self.scroll_bottom()
|
|
177
|
+
elif ch == curses.KEY_NPAGE: # Page down
|
|
178
|
+
self.scroll_page_down()
|
|
179
|
+
elif ch == curses.KEY_PPAGE: # Page up
|
|
180
|
+
self.scroll_page_up()
|
|
181
|
+
else:
|
|
182
|
+
return False
|
|
183
|
+
return True
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
import curses
|
|
2
|
+
|
|
3
|
+
from .list1_v2 import ListProto, ListV2
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
class List1mProto(ListProto):
|
|
7
|
+
def record_move_up(self, i: int) -> bool: # type: ignore[empty-body]
|
|
8
|
+
pass
|
|
9
|
+
|
|
10
|
+
def record_move_down(self, i: int) -> bool: # type: ignore[empty-body]
|
|
11
|
+
pass
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
class List1mV2(ListV2):
|
|
15
|
+
'List + move_up(), move_down()'
|
|
16
|
+
|
|
17
|
+
def __init__(
|
|
18
|
+
self,
|
|
19
|
+
proto: List1mProto,
|
|
20
|
+
current_color: int = curses.A_BOLD,
|
|
21
|
+
):
|
|
22
|
+
super().__init__(proto, current_color)
|
|
23
|
+
self.proto: List1mProto = proto
|
|
24
|
+
|
|
25
|
+
def move_up(self, i: int):
|
|
26
|
+
if not self.proto.record_move_up(i):
|
|
27
|
+
return
|
|
28
|
+
if self.idx > 0:
|
|
29
|
+
self.idx -= 1
|
|
30
|
+
if self.cur > 0:
|
|
31
|
+
self.cur -= 1
|
|
32
|
+
self.refresh()
|
|
33
|
+
|
|
34
|
+
def move_down(self, i: int):
|
|
35
|
+
if not self.win:
|
|
36
|
+
return
|
|
37
|
+
if not self.proto.record_move_down(i):
|
|
38
|
+
return
|
|
39
|
+
len_ = self.proto.records_len()
|
|
40
|
+
rows, _ = self.win.getmaxyx()
|
|
41
|
+
if self.idx < len_ - 1:
|
|
42
|
+
self.idx += 1
|
|
43
|
+
if self.cur < rows - 1:
|
|
44
|
+
self.cur += 1
|
|
45
|
+
self.refresh()
|
|
46
|
+
|
|
47
|
+
def handle_input(self, ch: int) -> bool:
|
|
48
|
+
if super().handle_input(ch):
|
|
49
|
+
return True
|
|
50
|
+
if ch == curses.KEY_SR: # Shift-Up
|
|
51
|
+
self.move_up(self.idx)
|
|
52
|
+
elif ch == curses.KEY_SF: # Shift-Down
|
|
53
|
+
self.move_down(self.idx)
|
|
54
|
+
else:
|
|
55
|
+
return False
|
|
56
|
+
return True
|
|
@@ -0,0 +1,208 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
import curses
|
|
4
|
+
from collections.abc import Generator
|
|
5
|
+
from typing import Protocol
|
|
6
|
+
|
|
7
|
+
from .proto import WinProto
|
|
8
|
+
from .win import win_addstr
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
class ListProto3(Protocol):
|
|
12
|
+
def get_record_str(self, i: int) -> Generator[str]:
|
|
13
|
+
'yields <height> lines'
|
|
14
|
+
|
|
15
|
+
def records_len(self) -> int:
|
|
16
|
+
pass
|
|
17
|
+
|
|
18
|
+
def refresh_win_deps(self):
|
|
19
|
+
pass
|
|
20
|
+
|
|
21
|
+
|
|
22
|
+
class List3v2(WinProto):
|
|
23
|
+
'List + every record projects to <height> window lines'
|
|
24
|
+
|
|
25
|
+
def __init__(
|
|
26
|
+
self,
|
|
27
|
+
proto: ListProto3,
|
|
28
|
+
height: int = 1,
|
|
29
|
+
current_color: int = curses.A_BOLD,
|
|
30
|
+
):
|
|
31
|
+
self.height = height
|
|
32
|
+
self.proto = proto
|
|
33
|
+
self.current_color = current_color
|
|
34
|
+
|
|
35
|
+
self.cur = 0 # cursor y, = 0..(maxy // height), real cursor = cur * height
|
|
36
|
+
self.idx = 0 # source index
|
|
37
|
+
|
|
38
|
+
self.win: curses.window | None = None
|
|
39
|
+
|
|
40
|
+
def set_win(self, win: curses.window | None):
|
|
41
|
+
self.win = win
|
|
42
|
+
if win:
|
|
43
|
+
win.keypad(True)
|
|
44
|
+
|
|
45
|
+
def addstr(self, i: int, g: Generator[str], attr: int = 0):
|
|
46
|
+
if not self.win:
|
|
47
|
+
return
|
|
48
|
+
i2 = i * self.height
|
|
49
|
+
j = -1
|
|
50
|
+
for j, s in enumerate(g):
|
|
51
|
+
if j >= self.height:
|
|
52
|
+
break
|
|
53
|
+
if not j:
|
|
54
|
+
# first line
|
|
55
|
+
win_addstr(self.win, i2 + j, 0, s, attr=attr | curses.A_BOLD)
|
|
56
|
+
else:
|
|
57
|
+
# rest of lines
|
|
58
|
+
win_addstr(self.win, i2 + j, 0, s, attr=attr | curses.A_DIM)
|
|
59
|
+
if j < self.height - 1:
|
|
60
|
+
# print rest lines
|
|
61
|
+
from_ = j + 1
|
|
62
|
+
for j in range(from_, self.height):
|
|
63
|
+
win_addstr(self.win, i2 + j, 0, '', attr=attr)
|
|
64
|
+
|
|
65
|
+
def refresh(self):
|
|
66
|
+
if not self.win:
|
|
67
|
+
self.proto.refresh_win_deps()
|
|
68
|
+
return
|
|
69
|
+
self.win.erase()
|
|
70
|
+
len_ = self.proto.records_len()
|
|
71
|
+
if len_:
|
|
72
|
+
rows, _ = self.win.getmaxyx()
|
|
73
|
+
rows //= self.height
|
|
74
|
+
if not self.idx < len_: # deleted
|
|
75
|
+
self.idx = len_ - 1
|
|
76
|
+
if not self.cur < rows: # new win < old win
|
|
77
|
+
self.cur = rows - 1
|
|
78
|
+
if (rows - self.cur) > (di := len_ - self.idx):
|
|
79
|
+
# gap at bottom
|
|
80
|
+
self.cur = rows - di
|
|
81
|
+
self.cur = min(self.cur, self.idx)
|
|
82
|
+
for i in range(rows):
|
|
83
|
+
idx = self.idx - self.cur + i
|
|
84
|
+
if not idx < len_:
|
|
85
|
+
break
|
|
86
|
+
s = self.proto.get_record_str(idx)
|
|
87
|
+
if i == self.cur:
|
|
88
|
+
self.addstr(i, s, attr=self.current_color)
|
|
89
|
+
else:
|
|
90
|
+
self.addstr(i, s)
|
|
91
|
+
self.win.move(self.cur * self.height, 0)
|
|
92
|
+
self.win.refresh()
|
|
93
|
+
self.proto.refresh_win_deps()
|
|
94
|
+
|
|
95
|
+
def scroll_top(self):
|
|
96
|
+
self.idx = self.cur = 0
|
|
97
|
+
self.refresh()
|
|
98
|
+
|
|
99
|
+
def scroll_bottom(self):
|
|
100
|
+
if not self.win:
|
|
101
|
+
return
|
|
102
|
+
len_ = self.proto.records_len()
|
|
103
|
+
if not len_:
|
|
104
|
+
return
|
|
105
|
+
rows, _ = self.win.getmaxyx()
|
|
106
|
+
rows //= self.height
|
|
107
|
+
self.cur = min(rows - 1, len_ - 1)
|
|
108
|
+
self.idx = len_ - 1
|
|
109
|
+
self.refresh()
|
|
110
|
+
|
|
111
|
+
def scroll_down(self):
|
|
112
|
+
if not self.win:
|
|
113
|
+
return
|
|
114
|
+
len_ = self.proto.records_len()
|
|
115
|
+
if not len_ or not self.idx + 1 < len_:
|
|
116
|
+
return
|
|
117
|
+
rows, _ = self.win.getmaxyx()
|
|
118
|
+
rows //= self.height
|
|
119
|
+
prev_s = self.proto.get_record_str(self.idx)
|
|
120
|
+
next_s = self.proto.get_record_str(self.idx + 1)
|
|
121
|
+
self.addstr(self.cur, prev_s)
|
|
122
|
+
if self.cur + 1 < rows:
|
|
123
|
+
self.cur += 1
|
|
124
|
+
else:
|
|
125
|
+
self.win.move(0, 0)
|
|
126
|
+
self.win.deleteln()
|
|
127
|
+
self.win.deleteln()
|
|
128
|
+
self.cur = rows - 1
|
|
129
|
+
self.addstr(self.cur, next_s, attr=self.current_color)
|
|
130
|
+
self.idx += 1
|
|
131
|
+
self.win.refresh()
|
|
132
|
+
self.proto.refresh_win_deps()
|
|
133
|
+
|
|
134
|
+
def scroll_up(self):
|
|
135
|
+
if not self.win:
|
|
136
|
+
return
|
|
137
|
+
len_ = self.proto.records_len()
|
|
138
|
+
if not len_ or self.idx - 1 < 0:
|
|
139
|
+
return
|
|
140
|
+
prev_s = self.proto.get_record_str(self.idx)
|
|
141
|
+
next_s = self.proto.get_record_str(self.idx - 1)
|
|
142
|
+
self.addstr(self.cur, prev_s)
|
|
143
|
+
if self.cur > 0:
|
|
144
|
+
self.cur -= 1
|
|
145
|
+
else:
|
|
146
|
+
self.win.move(0, 0)
|
|
147
|
+
self.win.insdelln(self.height)
|
|
148
|
+
self.addstr(self.cur, next_s, attr=self.current_color)
|
|
149
|
+
self.idx -= 1
|
|
150
|
+
self.win.refresh()
|
|
151
|
+
self.proto.refresh_win_deps()
|
|
152
|
+
|
|
153
|
+
def scroll_page_down(self):
|
|
154
|
+
if not self.win:
|
|
155
|
+
return
|
|
156
|
+
len_ = self.proto.records_len()
|
|
157
|
+
if not len_:
|
|
158
|
+
return
|
|
159
|
+
rows, _ = self.win.getmaxyx()
|
|
160
|
+
rows //= self.height
|
|
161
|
+
idx = self.idx + rows
|
|
162
|
+
if idx < len_:
|
|
163
|
+
self.idx = idx
|
|
164
|
+
self.refresh()
|
|
165
|
+
else:
|
|
166
|
+
idx = len_ - 1
|
|
167
|
+
delta = idx - self.idx
|
|
168
|
+
if not delta:
|
|
169
|
+
self.scroll_bottom()
|
|
170
|
+
elif self.cur + delta < rows:
|
|
171
|
+
self.cur += delta
|
|
172
|
+
self.idx = idx
|
|
173
|
+
self.refresh()
|
|
174
|
+
else:
|
|
175
|
+
self.scroll_bottom()
|
|
176
|
+
|
|
177
|
+
def scroll_page_up(self):
|
|
178
|
+
if not self.win:
|
|
179
|
+
return
|
|
180
|
+
len_ = self.proto.records_len()
|
|
181
|
+
if not len_:
|
|
182
|
+
return
|
|
183
|
+
rows, _ = self.win.getmaxyx()
|
|
184
|
+
rows //= self.height
|
|
185
|
+
idx = self.idx - rows
|
|
186
|
+
if idx >= 0:
|
|
187
|
+
self.idx = idx
|
|
188
|
+
self.refresh()
|
|
189
|
+
else:
|
|
190
|
+
self.scroll_top()
|
|
191
|
+
|
|
192
|
+
def handle_input(self, ch: int) -> bool:
|
|
193
|
+
char = chr(ch)
|
|
194
|
+
if char.upper() == 'J' or ch == curses.KEY_DOWN: # Down or J
|
|
195
|
+
self.scroll_down()
|
|
196
|
+
elif char.upper() == 'K' or ch == curses.KEY_UP: # Up or K
|
|
197
|
+
self.scroll_up()
|
|
198
|
+
elif char == 'g' or ch == curses.KEY_HOME: # Move to top
|
|
199
|
+
self.scroll_top()
|
|
200
|
+
elif char == 'G' or ch == curses.KEY_END: # Move to last item
|
|
201
|
+
self.scroll_bottom()
|
|
202
|
+
elif ch == curses.KEY_NPAGE: # Page down
|
|
203
|
+
self.scroll_page_down()
|
|
204
|
+
elif ch == curses.KEY_PPAGE: # Page up
|
|
205
|
+
self.scroll_page_up()
|
|
206
|
+
else:
|
|
207
|
+
return False
|
|
208
|
+
return True
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
import curses
|
|
4
|
+
|
|
5
|
+
from .proto import WinProto
|
|
6
|
+
from .win import win_addstr
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
class WinBox:
|
|
10
|
+
'''
|
|
11
|
+
win (box) + internal win (body)
|
|
12
|
+
|
|
13
|
+
'''
|
|
14
|
+
|
|
15
|
+
def __init__(self, body: WinProto, offy: int = 0, offx: int = 0):
|
|
16
|
+
'offy: y offset, offx: x offset'
|
|
17
|
+
self.body = body
|
|
18
|
+
self.offy, self.offx = offy, offx
|
|
19
|
+
|
|
20
|
+
def set_win(self, win: curses.window | None):
|
|
21
|
+
# pylint: disable=attribute-defined-outside-init
|
|
22
|
+
self.win = win
|
|
23
|
+
|
|
24
|
+
if not win:
|
|
25
|
+
self.body.set_win(None)
|
|
26
|
+
return
|
|
27
|
+
|
|
28
|
+
# body win
|
|
29
|
+
rows, cols = win.getmaxyx()
|
|
30
|
+
rows2 = rows - 2 - self.offy # 2 - border
|
|
31
|
+
cols2 = cols - 2 - 2 * self.offx # 2 - border
|
|
32
|
+
if rows2 < 0 or cols < 2:
|
|
33
|
+
self.win = None
|
|
34
|
+
self.body.set_win(None)
|
|
35
|
+
return
|
|
36
|
+
if rows2 < 1 or cols2 < 1:
|
|
37
|
+
self.body.set_win(None)
|
|
38
|
+
return
|
|
39
|
+
win2 = win.derwin(
|
|
40
|
+
rows2,
|
|
41
|
+
cols2,
|
|
42
|
+
1 + self.offy, # 1 - border
|
|
43
|
+
1 + self.offx, # 1 - border
|
|
44
|
+
)
|
|
45
|
+
self.body.set_win(win2)
|
|
46
|
+
|
|
47
|
+
def refresh(self, header: str = ''):
|
|
48
|
+
if not self.win:
|
|
49
|
+
return
|
|
50
|
+
|
|
51
|
+
self.win.erase()
|
|
52
|
+
if header:
|
|
53
|
+
# put header above body
|
|
54
|
+
win_addstr(self.win, 1, 1 + self.offx, header, border=1 + self.offx)
|
|
55
|
+
self.win.box()
|
|
56
|
+
self.win.refresh()
|
|
57
|
+
|
|
58
|
+
self.body.refresh()
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
__version__ = '0.3.2'
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|