boacon 0.0.1__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.
boacon/__init__.py ADDED
@@ -0,0 +1,360 @@
1
+ from .c_BCChar import *
2
+ from .c_BCCoord import *
3
+ from .c_BCError import *
4
+ from .c_BCPane import *
5
+ from .c_BCPostDrawArgs import *
6
+ from .c_BCSetChrFunc import *
7
+ from .c_BCSignal import *
8
+ from .c_BCSignalEmitter import *
9
+ from .c_BCState import *
10
+ from .c_BCStr import *
11
+ from .g_attr import *
12
+ from .g_key import *
13
+ from .p_BCConsolePane import *
14
+
15
+ import curses as _curses
16
+ import numpy as _np
17
+ import numpy.typing as _npt
18
+
19
+ #region const
20
+
21
+ _C_BORDERCHARS = [\
22
+ 0xFF, 0x50, 0x50, 0x50, 0x51, 0x54, 0x5A, 0x50, 0x51, 0x57, 0x5D, 0x50, 0x51, 0x51, 0x51, 0xA1,\
23
+ 0x5D, 0x50, 0x69, 0x50, 0x51, 0x54, 0x5A, 0x50, 0x63, 0x57, 0x5D, 0x50, 0x51, 0x51, 0x51, 0xA1,\
24
+ 0x5A, 0x50, 0x69, 0x50, 0x60, 0x54, 0x5A, 0x50, 0x51, 0x57, 0x5D, 0x50, 0x51, 0x51, 0x51, 0xA1,\
25
+ 0x69, 0x50, 0x69, 0x50, 0x60, 0x54, 0x5A, 0x50, 0x63, 0x57, 0x5D, 0x50, 0x51, 0x51, 0x51, 0xA1,\
26
+ 0x57, 0x66, 0x50, 0x50, 0x51, 0x54, 0x5A, 0x50, 0x63, 0x57, 0x5D, 0x50, 0x51, 0x51, 0x51, 0xA1,\
27
+ 0x63, 0x66, 0x69, 0x50, 0x51, 0x54, 0x5A, 0x50, 0x63, 0x57, 0x5D, 0x50, 0x51, 0x51, 0x51, 0xA1,\
28
+ 0x6C, 0x66, 0x69, 0x50, 0x60, 0x54, 0x5A, 0x50, 0x63, 0x57, 0x5D, 0x50, 0x51, 0x51, 0x51, 0xA1,\
29
+ 0x6C, 0x66, 0x69, 0x50, 0x60, 0x54, 0x5A, 0x50, 0x63, 0x57, 0x5D, 0x50, 0x51, 0x51, 0x51, 0xA1,\
30
+ 0x54, 0x66, 0x50, 0x50, 0x60, 0x54, 0x5A, 0x50, 0x51, 0x57, 0x5D, 0x50, 0x51, 0x51, 0x51, 0xA1,\
31
+ 0x6C, 0x66, 0x69, 0x50, 0x60, 0x54, 0x5A, 0x50, 0x63, 0x57, 0x5D, 0x50, 0x51, 0x51, 0x51, 0xA1,\
32
+ 0x60, 0x66, 0x69, 0x50, 0x60, 0x54, 0x5A, 0x50, 0x51, 0x57, 0x5D, 0x50, 0x51, 0x51, 0x51, 0xA1,\
33
+ 0x6C, 0x66, 0x69, 0x50, 0x60, 0x54, 0x5A, 0x50, 0x63, 0x57, 0x5D, 0x50, 0x51, 0x51, 0x51, 0xA1,\
34
+ 0x66, 0x66, 0x50, 0x50, 0x60, 0x54, 0x5A, 0x50, 0x63, 0x57, 0x5D, 0x50, 0x51, 0x51, 0x51, 0xA1,\
35
+ 0x6C, 0x66, 0x69, 0x50, 0x60, 0x54, 0x5A, 0x50, 0x63, 0x57, 0x5D, 0x50, 0x51, 0x51, 0x51, 0xA1,\
36
+ 0x6C, 0x66, 0x69, 0x50, 0x60, 0x54, 0x5A, 0x50, 0x63, 0x57, 0x5D, 0x50, 0x51, 0x51, 0x51, 0xA1,\
37
+ 0x6C, 0x66, 0x69, 0x50, 0x60, 0x54, 0x5A, 0x50, 0x63, 0x57, 0x5D, 0x50, 0x51, 0x51, 0x51, 0xA1,]
38
+
39
+ #endregion
40
+
41
+ #region variables
42
+
43
+ _f_state = BCState.NORUN
44
+ _f_win:None|_curses.window = None
45
+ _f_win_ok = False
46
+ _f_win_w = 0
47
+ _f_win_h = 0
48
+ _f_color = False
49
+ _f_panes:None|list[BCPane] = None
50
+ _f_bgbuffer:None|_npt.NDArray[_np.bool_] = None
51
+
52
+ _f_border = False
53
+
54
+ _s_on_init_emitter = BCSignalEmitter[()]()
55
+ _s_on_init = BCSignal(_s_on_init_emitter)
56
+ _s_on_final_emitter = BCSignalEmitter[()]()
57
+ _s_on_final = BCSignal(_s_on_final_emitter)
58
+
59
+ _s_postdraw_emitter:None|BCSignalEmitter[BCPostDrawArgs] = None
60
+ _s_postdraw:None|BCSignal[BCPostDrawArgs] = None
61
+
62
+ #endregion
63
+
64
+ #region helper
65
+
66
+ def _m_verify_run():
67
+ global _f_state
68
+ if _f_state == BCState.RUN: return
69
+ raise BCError("boacon system is not currently running.")
70
+
71
+ def _m_setcursor(visible:bool):
72
+ global _f_win, _f_win_ok
73
+ assert _f_win is not None
74
+ # Try to hide normally
75
+ if not _f_win_ok:
76
+ try: _curses.curs_set(1 if visible else 0)
77
+ except _curses.error: _f_win_ok = True
78
+ # Try to hide alternatively
79
+ if _f_win_ok: # Do NOT change to else or elif
80
+ try: _f_win.leaveok(not visible)
81
+ except _curses.error: pass
82
+
83
+ def _m_cursesattr_color(attr:int):
84
+ cattr = _curses.A_STANDOUT if attr_emp(attr) else _curses.A_NORMAL
85
+ return cattr | _curses.color_pair(0b111 ^ attr_color(attr))
86
+
87
+ def _m_cursesattr_nocolor(attr:int):
88
+ return _curses.A_STANDOUT if attr_emp(attr) else _curses.A_NORMAL
89
+
90
+ def _m_setchr_color(x:int, y:int, char:BCChar):
91
+ global _f_win, _f_bgbuffer, _f_win_w
92
+ assert _f_win is not None
93
+ assert _f_bgbuffer is not None
94
+ attr = _m_cursesattr_color(char.attr)
95
+ try:
96
+ _f_win.addch(y, x, chr(char.ord), attr)
97
+ _f_bgbuffer[y * _f_win_w + x] = True
98
+ except: pass
99
+
100
+ def _m_setchr_nocolor(x:int, y:int, char:BCChar):
101
+ global _f_win, _f_bgbuffer, _f_win_w
102
+ assert _f_win is not None
103
+ assert _f_bgbuffer is not None
104
+ attr = _m_cursesattr_nocolor(char.attr)
105
+ try:
106
+ _f_win.addch(y, x, chr(char.ord), attr)
107
+ _f_bgbuffer[y * _f_win_w + x] = True
108
+ except: pass
109
+
110
+ def _m_borderchar(x:int, y:int):
111
+ global _f_win_w, _f_win_h, _f_bgbuffer
112
+ assert _f_bgbuffer is not None
113
+ # Examine neighbors
114
+ index = y * _f_win_w + x
115
+ index_t = index - _f_win_w
116
+ index_b = index + _f_win_w
117
+ notedge_t = y > 0
118
+ notedge_b = (y + 1) < _f_win_h
119
+ notedge_l = x > 0
120
+ notedge_r = (x + 1) < _f_win_w
121
+ if notedge_t:
122
+ neighbor_t = _f_bgbuffer[index_t]
123
+ neighbor_tl = notedge_l and _f_bgbuffer[index_t - 1]
124
+ neighbor_tr = notedge_r and _f_bgbuffer[index_t + 1]
125
+ else:
126
+ neighbor_t = False
127
+ neighbor_tl = False
128
+ neighbor_tr = False
129
+ if notedge_b:
130
+ neighbor_b = _f_bgbuffer[index_b]
131
+ neighbor_bl = notedge_l and _f_bgbuffer[index_b - 1]
132
+ neighbor_br = notedge_r and _f_bgbuffer[index_b + 1]
133
+ else:
134
+ neighbor_b = False
135
+ neighbor_bl = False
136
+ neighbor_br = False
137
+ neighbor_l = notedge_l and _f_bgbuffer[index - 1]
138
+ neighbor_r = notedge_r and _f_bgbuffer[index + 1]
139
+ # Determine character
140
+ index = 0
141
+ if neighbor_t: index |= 0b00000001
142
+ if neighbor_b: index |= 0b00000010
143
+ if neighbor_l: index |= 0b00000100
144
+ if neighbor_r: index |= 0b00001000
145
+ if neighbor_tl: index |= 0b00010000
146
+ if neighbor_tr: index |= 0b00100000
147
+ if neighbor_bl: index |= 0b01000000
148
+ if neighbor_br: index |= 0b10000000
149
+ raw = _C_BORDERCHARS[index]
150
+ return ' ' if (raw == 0xFF) else chr(0x2500 | raw)
151
+
152
+ #endregion
153
+
154
+ #region init/final
155
+
156
+ def init():
157
+ global _f_state
158
+ if _f_state != BCState.NORUN: return
159
+ _f_state = BCState.INIT
160
+ # Global vars
161
+ global _f_win, _f_win_w, _f_win_h, _f_color, _f_panes
162
+ global _f_border
163
+ # Initialize window
164
+ _f_win = _curses.initscr()
165
+ _f_win.keypad(True)
166
+ _f_win.nodelay(True)
167
+ _f_win_w = 0
168
+ _f_win_h = 0
169
+ # Initialize curses
170
+ _curses.noecho()
171
+ _curses.cbreak()
172
+ _m_setcursor(False)
173
+ # Initialize color
174
+ _curses.start_color()
175
+ if _curses.has_colors() and _curses.COLOR_PAIRS >= 8:
176
+ _curses.use_default_colors()
177
+ _curses.init_pair(0b001, _curses.COLOR_CYAN, -1)
178
+ _curses.init_pair(0b010, _curses.COLOR_MAGENTA, -1)
179
+ _curses.init_pair(0b011, _curses.COLOR_BLUE, -1)
180
+ _curses.init_pair(0b100, _curses.COLOR_YELLOW, -1)
181
+ _curses.init_pair(0b101, _curses.COLOR_GREEN, -1)
182
+ _curses.init_pair(0b110, _curses.COLOR_RED, -1)
183
+ _curses.init_pair(0b111, _curses.COLOR_BLACK, -1)
184
+ _f_color = True
185
+ else:
186
+ _f_color = False
187
+ # Initialize panes
188
+ _f_panes = []
189
+ # Initialize border
190
+ _f_border = True
191
+ # Initialize signals
192
+ global _s_postdraw, _s_postdraw_emitter
193
+ _s_postdraw_emitter = BCSignalEmitter[BCPostDrawArgs]()
194
+ _s_postdraw = BCSignal[BCPostDrawArgs](_s_postdraw_emitter)
195
+ # Success!!!
196
+ _f_state = BCState.RUN
197
+ _s_on_init_emitter.emit(())
198
+
199
+ def final():
200
+ global _f_state
201
+ if _f_state != BCState.RUN: return
202
+ _s_on_final_emitter.emit(())
203
+ _f_state = BCState.FINAL
204
+ # Global vars
205
+ global _f_win, _panes
206
+ assert _f_win is not None
207
+ # Finalize curses
208
+ _curses.nocbreak()
209
+ _curses.echo()
210
+ _curses.endwin()
211
+ # Finalize window
212
+ _m_setcursor(True)
213
+ _f_win.nodelay(False)
214
+ _f_win.keypad(False)
215
+ # Success!!!
216
+ _f_state = BCState.NORUN
217
+
218
+ #endregion
219
+
220
+ #region "properties"
221
+
222
+ def state():
223
+ """
224
+ State of the boacon system
225
+ """
226
+ global _f_state
227
+ return _f_state
228
+
229
+ def panes():
230
+ """
231
+ Panes that are being displayed
232
+
233
+ :raise BCError:
234
+ boacon system is not currently running
235
+ """
236
+ _m_verify_run()
237
+ global _f_panes
238
+ assert _f_panes is not None
239
+ return _f_panes
240
+
241
+ def on_init():
242
+ """
243
+ Emitted after the boacon system is initialized
244
+ """
245
+ global _s_on_init
246
+ return _s_on_init
247
+
248
+ def on_final():
249
+ """
250
+ Emitted before the boacon system is finalized
251
+ """
252
+ global _s_on_final
253
+ return _s_on_final
254
+
255
+ def postdraw():
256
+ """
257
+ Emitted after drawing the panes and right before the screen is refreshed
258
+
259
+ :raise BCError:
260
+ boacon system is not currently running
261
+ """
262
+ _m_verify_run()
263
+ global _s_postdraw
264
+ assert _s_postdraw is not None
265
+ return _s_postdraw
266
+
267
+ #endregion
268
+
269
+ #region functions
270
+
271
+ def refresh():
272
+ """
273
+ Refreshes the screen
274
+
275
+ :raise BCError:
276
+ boacon system is not currently running
277
+ """
278
+ _m_verify_run()
279
+ global _f_win, _f_win_w, _f_win_h, _f_color, _f_panes, _f_bgbuffer
280
+ global _f_border
281
+ assert _f_win is not None
282
+ assert _f_panes is not None
283
+ global _s_postdraw_emitter
284
+ assert _s_postdraw_emitter is not None
285
+ # Determine functions
286
+ _func_cursesattr = _m_cursesattr_color if _f_color else _m_cursesattr_nocolor
287
+ _func_setchr = _m_setchr_color if _f_color else _m_setchr_nocolor
288
+ # Update size
289
+ _new_h, _new_w = _f_win.getmaxyx()
290
+ if _f_win_w != _new_w or _f_win_h != _new_h:
291
+ _f_win_w = _new_w
292
+ _f_win_h = _new_h
293
+ _f_bgbuffer = _np.zeros(_f_win_w * _f_win_h, dtype = bool)
294
+ resized = True
295
+ else:
296
+ assert _f_bgbuffer is not None
297
+ resized = False
298
+ # Resolve pane dimensions
299
+ redrawbg = resized
300
+ for _pane in _f_panes:
301
+ if _pane._m_resolve(resized, _f_win_w, _f_win_h):
302
+ redrawbg = True
303
+ if redrawbg:
304
+ _f_bgbuffer.fill(False)
305
+ # Update panes
306
+ for _pane in _f_panes:
307
+ _pane._m_refresh(redrawbg, _func_setchr)
308
+ # Draw background
309
+ if redrawbg:
310
+ for _y in range(_f_win_h):
311
+ for _x in range(_f_win_w):
312
+ _i = _y * _f_win_w + _x
313
+ if _f_bgbuffer[_i]: continue
314
+ # Determine character
315
+ _chr = _m_borderchar(_x, _y) if _f_border else ' '
316
+ # Set character
317
+ try: _f_win.addch(_y, _x, _chr)
318
+ except: pass
319
+ # Post draw
320
+ _s_postdraw_emitter.emit((BCPostDrawArgs(_f_win, _func_cursesattr, _func_setchr),))
321
+ # Success!!!
322
+ _f_win.refresh()
323
+
324
+ def getch():
325
+ """
326
+ Gets a character code from the keyboard
327
+
328
+ :return:
329
+ Character code (or -1 if no character is pressed)
330
+ :raise BCError:
331
+ boacon system is not currently running
332
+ """
333
+ _m_verify_run()
334
+ global _f_win
335
+ assert _f_win is not None
336
+ return _f_win.getch()
337
+
338
+ def get_border():
339
+ """
340
+ Gets whether or not pane borders are enabled
341
+
342
+ :raise BCError:
343
+ boacon system is not currently running
344
+ """
345
+ _m_verify_run()
346
+ global _f_border
347
+ return _f_border
348
+
349
+ def set_border(value:bool):
350
+ """
351
+ Sets whether or not pane borders are enabled
352
+
353
+ :raise BCError:
354
+ boacon system is not currently running
355
+ """
356
+ _m_verify_run()
357
+ global _f_border
358
+ _f_border = value
359
+
360
+ #endregion
boacon/c_BCChar.py ADDED
@@ -0,0 +1,140 @@
1
+ all = ['BCChar']
2
+
3
+ from .g_attr import\
4
+ ATTR_NORMAL as _ATTR_NORMAL
5
+
6
+ class BCChar:
7
+ """
8
+ Represents a text character
9
+ """
10
+
11
+ #region init
12
+
13
+ def __init__(self, ord:int, attr:int = _ATTR_NORMAL):
14
+ """
15
+ Initializer for BBChar
16
+
17
+ :param ord:
18
+ Ordinal code
19
+ :param attr:
20
+ Text attribute
21
+ """
22
+ self.__ord = ord
23
+ self.__attr = attr
24
+
25
+ #endregion
26
+
27
+ #region operators
28
+
29
+ def __repr__(self):
30
+ return f"BCChar({self.__ord}, attr = {self.__attr})"
31
+
32
+ def __str__(self):
33
+ return chr(self.__ord)
34
+
35
+ def __eq__(self, other:object):
36
+ equ = self.__equ(other)
37
+ if equ is None: return NotImplemented
38
+ return equ
39
+
40
+ def __ne__(self, other:object):
41
+ equ = self.__equ(other)
42
+ if equ is None: return NotImplemented
43
+ return not equ
44
+
45
+ def __lt__(self, other:object):
46
+ cmp = self.__cmp(other)
47
+ if cmp is None: return NotImplemented
48
+ return cmp < 0
49
+
50
+ def __le__(self, other:object):
51
+ cmp = self.__cmp(other)
52
+ if cmp is None: return NotImplemented
53
+ return cmp <= 0
54
+
55
+ def __gt__(self, other:object):
56
+ cmp = self.__cmp(other)
57
+ if cmp is None: return NotImplemented
58
+ return cmp > 0
59
+
60
+ def __ge__(self, other:object):
61
+ cmp = self.__cmp(other)
62
+ if cmp is None: return NotImplemented
63
+ return cmp >= 0
64
+
65
+ def __hash__(self):
66
+ return self.__ord
67
+
68
+ #endregion
69
+
70
+ #region properties
71
+
72
+ @property
73
+ def ord(self):
74
+ """
75
+ Ordinal code
76
+ """
77
+ return self.__ord
78
+
79
+ @property
80
+ def attr(self):
81
+ """
82
+ Text attribute
83
+ """
84
+ return self.__attr
85
+
86
+ #endregion
87
+
88
+ #region helper methods
89
+
90
+ def __equ(self, other: object):
91
+ if isinstance(other, BCChar):
92
+ return self.__ord == other.__ord and self.__attr == other.__attr
93
+ if isinstance(other, str):
94
+ return len(other) == 1 and self.__ord == ord(other)
95
+ return None
96
+
97
+ def __cmp(self, other: object) -> None|int:
98
+ if isinstance(other, BCChar):
99
+ if self.__ord != other.__ord: return self.__ord - other.__ord
100
+ return self.__attr - other.__attr
101
+ if isinstance(other, str):
102
+ if len(other) != 1: return None
103
+ return self.__ord - ord(other)
104
+ return None
105
+
106
+ #endregion
107
+
108
+ #region methods
109
+
110
+ def equ(self, other:object):
111
+ """
112
+ Checks if the character is equal to another character
113
+
114
+ :param other:
115
+ Other character
116
+ :return:
117
+ Whether or not the two characters are equal
118
+ """
119
+ equ = self.__equ(other)
120
+ if equ is None: return False
121
+ return equ
122
+
123
+ def cmp(self, other:object):
124
+ """
125
+ Compares the character to another character
126
+
127
+ :param other:
128
+ Other character
129
+ :return:
130
+ lt 0: Current character precedes other character\n
131
+ eq 0: Current character is equal to the other character\n
132
+ gt 0: Current character follows other character
133
+ :raise TypeError:
134
+ Cannot compare with other type
135
+ """
136
+ cmp = self.__cmp(other)
137
+ if cmp is None: raise TypeError(f"Cannot compare BCChar with {type(other)}.")
138
+ return cmp
139
+
140
+ #endregion
boacon/c_BCCoord.py ADDED
@@ -0,0 +1,185 @@
1
+ all = ['BCCoord']
2
+
3
+ class BCCoord:
4
+ """
5
+ Represents coordinates for a single axis
6
+ """
7
+
8
+ #region init
9
+
10
+ def __init__(self, dis0:None|int = None, dis1:None|int = None, len:None|int = None):
11
+ """
12
+ Initializer for BCCoord
13
+
14
+ :param dis0:
15
+ For X-axis: Distance from the left edge of console to left edge of pane\n
16
+ For Y-axis: Distance from the top edge of console to top edge of pane
17
+ :param dis1:
18
+ For X-axis: Distance from the right edge of console to right edge of pane\n
19
+ For Y-axis: Distance from the bottom edge of console to bottom edge of pane
20
+ :param len:
21
+ For X-axis: Width of pane\n
22
+ For Y-axis: Height of pane
23
+ """
24
+ self.__dis0 = dis0
25
+ self.__dis1 = dis1
26
+ self.__len = len
27
+ self.__first = True
28
+ self.__prev_dis0:None|int = None
29
+ self.__prev_dis1:None|int = None
30
+ self.__prev_len:None|int = None
31
+ self.__pnt0:int = 0
32
+ self.__pnt1:int = 0
33
+ self.__pntlen:int = 0
34
+ self.__clip0:int = 0
35
+ self.__clip1:int = 0
36
+ self.__cliplen:int = 0
37
+ self.__clipoff:int = 0
38
+
39
+ #endregion
40
+
41
+ #region properties
42
+
43
+ @property
44
+ def dis0(self):
45
+ """
46
+ For X-axis: Distance from the left edge of console to left edge of pane\n
47
+ For Y-axis: Distance from the top edge of console to top edge of pane
48
+ """
49
+ return self.__dis0
50
+
51
+ @property
52
+ def dis1(self):
53
+ """
54
+ For X-axis: Distance from the right edge of console to right edge of pane\n
55
+ For Y-axis: Distance from the bottom edge of console to bottom edge of pane
56
+ """
57
+ return self.__dis1
58
+
59
+ @property
60
+ def len(self):
61
+ """
62
+ For X-axis: Width of pane\n
63
+ For Y-axis: Height of pane
64
+ """
65
+ return self.__len
66
+
67
+ @property
68
+ def pnt0(self):
69
+ """
70
+ For X-axis: X-coordinate of left edge\n
71
+ For Y-axis: Y-coordinate of top edge
72
+ """
73
+ return self.__pnt0
74
+
75
+ @property
76
+ def pnt1(self):
77
+ """
78
+ For X-axis: X-coordinate of right edge\n
79
+ For Y-axis: Y-coordinate of bottom edge
80
+ """
81
+ return self.__pnt1
82
+
83
+ @property
84
+ def pntlen(self):
85
+ """
86
+ Distance between pnt0 and pnt1\n
87
+ For X-axis: Resolved width\n
88
+ For Y-axis: Resolved height
89
+ """
90
+ return self.__pntlen
91
+
92
+ @property
93
+ def clip0(self):
94
+ """
95
+ For X-axis: X-coordinate of left clip\n
96
+ For Y-axis: Y-coordinate of top clip
97
+ """
98
+ return self.__clip0
99
+
100
+ @property
101
+ def clip1(self):
102
+ """
103
+ For X-axis: X-coordinate of right clip\n
104
+ For Y-axis: Y-coordinate of bottom clip
105
+ """
106
+ return self.__clip1
107
+
108
+ @property
109
+ def cliplen(self):
110
+ """
111
+ Distance between clip0 and clip1\n
112
+ For X-axis: Clip width\n
113
+ For Y-axis: Clip height
114
+ """
115
+ return self.__cliplen
116
+
117
+ @property
118
+ def clipoff(self):
119
+ """
120
+ This is the offset from pnt0 to clip0
121
+ """
122
+ return self.__clipoff
123
+
124
+ @dis0.setter
125
+ def dis0(self, value:None|int): self.__dis0 = value
126
+
127
+ @dis1.setter
128
+ def dis1(self, value:None|int): self.__dis1 = value
129
+
130
+ @len.setter
131
+ def len(self, value:None|int): self.__len = value
132
+
133
+ #endregion
134
+
135
+ #region helper methods
136
+
137
+ def _m_resolve(self, force:bool, containlen:int):
138
+ """
139
+ Also accessed by TPPane
140
+ """
141
+ if not (force or self.__first or\
142
+ self.__prev_dis0 != self.__dis0 or\
143
+ self.__prev_dis1 != self.__dis1 or\
144
+ self.__prev_len != self.__len):
145
+ return False
146
+ # Update previous
147
+ self.__first = False
148
+ self.__prev_dis0 = self.__dis0
149
+ self.__prev_dis1 = self.__dis1
150
+ self.__prev_len = self.__len
151
+ # Resolve
152
+ pnt0 = self.dis0
153
+ pnt1 = None if (self.dis1 is None) else (containlen - self.dis1)
154
+ pntlen = self.len
155
+ if pnt0 is not None:
156
+ if pnt1 is not None:
157
+ pntlen = pnt1 - pnt0
158
+ elif pntlen is not None:
159
+ pnt1 = pnt0 + pntlen
160
+ else:
161
+ pnt1 = pnt0
162
+ pntlen = 0
163
+ elif pnt1 is not None:
164
+ if pntlen is not None:
165
+ pnt0 = pnt1 - pntlen
166
+ else:
167
+ pnt0 = pnt1
168
+ pntlen = 0
169
+ elif pntlen is not None:
170
+ pnt0 = 0
171
+ pnt1 = pntlen
172
+ else:
173
+ pnt0 = 0
174
+ pnt1 = 0
175
+ pntlen = 0
176
+ self.__pnt0 = pnt0
177
+ self.__pnt1 = pnt1
178
+ self.__pntlen = pntlen
179
+ self.__clip0 = max(0, min(containlen, self.__pnt0))
180
+ self.__clip1 = max(0, min(containlen, self.__pnt1))
181
+ self.__cliplen = self.__clip1 - self.__clip0
182
+ self.__clipoff = self.__clip0 - self.pnt0
183
+ return True
184
+
185
+ #endregion
@@ -0,0 +1,14 @@
1
+ all = ['BCCursesAttrFunc']
2
+
3
+ from typing import\
4
+ Callable as _Callable
5
+
6
+ type BCCursesAttrFunc = _Callable[[int], int]
7
+ """
8
+ Function for computing a curses character attribute
9
+
10
+ :param 0:
11
+ boacon character attribute
12
+ :return:
13
+ curses character attribute
14
+ """
boacon/c_BCError.py ADDED
@@ -0,0 +1,7 @@
1
+ all = ['BCError']
2
+
3
+ class BCError(Exception):
4
+ """
5
+ Raised when a boacon-related error occurs
6
+ """
7
+ pass