tksheet 7.1.5__py3-none-any.whl → 7.1.7__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.
- tksheet/__init__.py +99 -96
- tksheet/column_headers.py +63 -44
- tksheet/functions.py +27 -15
- tksheet/listbox.py +19 -0
- tksheet/main_table.py +407 -315
- tksheet/row_index.py +85 -48
- tksheet/sheet.py +74 -81
- tksheet/sheet_options.py +3 -1
- {tksheet-7.1.5.dist-info → tksheet-7.1.7.dist-info}/METADATA +1 -1
- tksheet-7.1.7.dist-info/RECORD +21 -0
- tksheet-7.1.5.dist-info/RECORD +0 -20
- {tksheet-7.1.5.dist-info → tksheet-7.1.7.dist-info}/LICENSE.txt +0 -0
- {tksheet-7.1.5.dist-info → tksheet-7.1.7.dist-info}/WHEEL +0 -0
- {tksheet-7.1.5.dist-info → tksheet-7.1.7.dist-info}/top_level.txt +0 -0
tksheet/__init__.py
CHANGED
@@ -1,96 +1,99 @@
|
|
1
|
-
# ruff: noqa: F401
|
2
|
-
|
3
|
-
"""
|
4
|
-
tksheet - A Python tkinter table widget
|
5
|
-
"""
|
6
|
-
|
7
|
-
__version__ = "7.1.
|
8
|
-
|
9
|
-
from .colors import (
|
10
|
-
color_map,
|
11
|
-
)
|
12
|
-
from .column_headers import ColumnHeaders
|
13
|
-
from .formatters import (
|
14
|
-
Formatter,
|
15
|
-
bool_formatter,
|
16
|
-
data_to_str,
|
17
|
-
float_formatter,
|
18
|
-
float_to_str,
|
19
|
-
format_data,
|
20
|
-
formatter,
|
21
|
-
get_clipboard_data,
|
22
|
-
get_data_with_valid_check,
|
23
|
-
int_formatter,
|
24
|
-
is_bool_like,
|
25
|
-
is_none_like,
|
26
|
-
percentage_formatter,
|
27
|
-
percentage_to_str,
|
28
|
-
to_bool,
|
29
|
-
to_float,
|
30
|
-
to_int,
|
31
|
-
to_str,
|
32
|
-
try_to_bool,
|
33
|
-
)
|
34
|
-
from .functions import (
|
35
|
-
alpha2idx,
|
36
|
-
alpha2num,
|
37
|
-
consecutive_chunks,
|
38
|
-
data_to_displayed_idxs,
|
39
|
-
displayed_to_data_idxs,
|
40
|
-
dropdown_search_function,
|
41
|
-
event_dict,
|
42
|
-
get_checkbox_dict,
|
43
|
-
get_checkbox_kwargs,
|
44
|
-
|
45
|
-
get_dropdown_dict,
|
46
|
-
get_dropdown_kwargs,
|
47
|
-
get_index_of_gap_in_sorted_integer_seq_forward,
|
48
|
-
get_index_of_gap_in_sorted_integer_seq_reverse,
|
49
|
-
get_n2a,
|
50
|
-
get_new_indexes,
|
51
|
-
get_seq_without_gaps_at_index,
|
52
|
-
is_iterable,
|
53
|
-
move_elements_by_mapping,
|
54
|
-
move_elements_to,
|
55
|
-
num2alpha,
|
56
|
-
span_dict,
|
57
|
-
tksheet_type_error,
|
58
|
-
)
|
59
|
-
from .
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
from .
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
|
96
|
-
|
1
|
+
# ruff: noqa: F401
|
2
|
+
|
3
|
+
"""
|
4
|
+
tksheet - A Python tkinter table widget
|
5
|
+
"""
|
6
|
+
|
7
|
+
__version__ = "7.1.7"
|
8
|
+
|
9
|
+
from .colors import (
|
10
|
+
color_map,
|
11
|
+
)
|
12
|
+
from .column_headers import ColumnHeaders
|
13
|
+
from .formatters import (
|
14
|
+
Formatter,
|
15
|
+
bool_formatter,
|
16
|
+
data_to_str,
|
17
|
+
float_formatter,
|
18
|
+
float_to_str,
|
19
|
+
format_data,
|
20
|
+
formatter,
|
21
|
+
get_clipboard_data,
|
22
|
+
get_data_with_valid_check,
|
23
|
+
int_formatter,
|
24
|
+
is_bool_like,
|
25
|
+
is_none_like,
|
26
|
+
percentage_formatter,
|
27
|
+
percentage_to_str,
|
28
|
+
to_bool,
|
29
|
+
to_float,
|
30
|
+
to_int,
|
31
|
+
to_str,
|
32
|
+
try_to_bool,
|
33
|
+
)
|
34
|
+
from .functions import (
|
35
|
+
alpha2idx,
|
36
|
+
alpha2num,
|
37
|
+
consecutive_chunks,
|
38
|
+
data_to_displayed_idxs,
|
39
|
+
displayed_to_data_idxs,
|
40
|
+
dropdown_search_function,
|
41
|
+
event_dict,
|
42
|
+
get_checkbox_dict,
|
43
|
+
get_checkbox_kwargs,
|
44
|
+
rounded_box_coords,
|
45
|
+
get_dropdown_dict,
|
46
|
+
get_dropdown_kwargs,
|
47
|
+
get_index_of_gap_in_sorted_integer_seq_forward,
|
48
|
+
get_index_of_gap_in_sorted_integer_seq_reverse,
|
49
|
+
get_n2a,
|
50
|
+
get_new_indexes,
|
51
|
+
get_seq_without_gaps_at_index,
|
52
|
+
is_iterable,
|
53
|
+
move_elements_by_mapping,
|
54
|
+
move_elements_to,
|
55
|
+
num2alpha,
|
56
|
+
span_dict,
|
57
|
+
tksheet_type_error,
|
58
|
+
)
|
59
|
+
from .listbox import (
|
60
|
+
ListBox,
|
61
|
+
)
|
62
|
+
from .main_table import MainTable
|
63
|
+
from .other_classes import (
|
64
|
+
DotDict,
|
65
|
+
DraggedRowColumn,
|
66
|
+
DrawnItem,
|
67
|
+
EventDataDict,
|
68
|
+
GeneratedMouseEvent,
|
69
|
+
Selected,
|
70
|
+
Span,
|
71
|
+
SpanRange,
|
72
|
+
TextCfg,
|
73
|
+
)
|
74
|
+
from .row_index import RowIndex
|
75
|
+
from .sheet import Dropdown, Sheet
|
76
|
+
from .sheet_options import new_sheet_options
|
77
|
+
from .text_editor import (
|
78
|
+
TextEditor,
|
79
|
+
TextEditorTkText,
|
80
|
+
)
|
81
|
+
from .themes import (
|
82
|
+
theme_black,
|
83
|
+
theme_dark,
|
84
|
+
theme_dark_blue,
|
85
|
+
theme_dark_green,
|
86
|
+
theme_light_blue,
|
87
|
+
theme_light_green,
|
88
|
+
)
|
89
|
+
from .top_left_rectangle import TopLeftRectangle
|
90
|
+
from .vars import (
|
91
|
+
USER_OS,
|
92
|
+
ctrl_key,
|
93
|
+
emitted_events,
|
94
|
+
falsy,
|
95
|
+
nonelike,
|
96
|
+
rc_binding,
|
97
|
+
symbols_set,
|
98
|
+
truthy,
|
99
|
+
)
|
tksheet/column_headers.py
CHANGED
@@ -13,16 +13,17 @@ from itertools import (
|
|
13
13
|
islice,
|
14
14
|
)
|
15
15
|
from math import ceil, floor
|
16
|
+
from typing import Literal
|
16
17
|
|
17
18
|
from .colors import (
|
18
19
|
color_map,
|
19
20
|
)
|
20
21
|
from .formatters import is_bool_like, try_to_bool
|
21
22
|
from .functions import (
|
22
|
-
|
23
|
+
consecutive_ranges,
|
23
24
|
ev_stack_dict,
|
24
25
|
event_dict,
|
25
|
-
|
26
|
+
rounded_box_coords,
|
26
27
|
get_n2a,
|
27
28
|
is_contiguous,
|
28
29
|
try_binding,
|
@@ -687,10 +688,10 @@ class ColumnHeaders(tk.Canvas):
|
|
687
688
|
tag="move_columns",
|
688
689
|
)
|
689
690
|
self.MT.create_resize_line(xpos, y1, xpos, y2, width=3, fill=self.PAR.ops.drag_and_drop_bg, tag="move_columns")
|
690
|
-
for
|
691
|
+
for boxst, boxend in consecutive_ranges(cols):
|
691
692
|
self.MT.show_ctrl_outline(
|
692
|
-
start_cell=(
|
693
|
-
end_cell=(
|
693
|
+
start_cell=(boxst, 0),
|
694
|
+
end_cell=(boxend, len(self.MT.row_positions) - 1),
|
694
695
|
dash=(),
|
695
696
|
outline=self.PAR.ops.drag_and_drop_bg,
|
696
697
|
delete_on_timer=False,
|
@@ -934,14 +935,26 @@ class ColumnHeaders(tk.Canvas):
|
|
934
935
|
outline: str,
|
935
936
|
state: str,
|
936
937
|
tags: str | tuple[str],
|
938
|
+
iid: None | int = None,
|
937
939
|
) -> int:
|
938
|
-
|
939
|
-
|
940
|
-
|
940
|
+
coords = rounded_box_coords(
|
941
|
+
x1,
|
942
|
+
y1,
|
943
|
+
x2,
|
944
|
+
y2,
|
945
|
+
radius=9 if self.PAR.ops.rounded_boxes else 0,
|
946
|
+
)
|
947
|
+
if isinstance(iid, int):
|
948
|
+
self.coords(iid, coords)
|
941
949
|
self.itemconfig(iid, fill=fill, outline=outline, state=state, tags=tags)
|
942
950
|
else:
|
943
|
-
|
944
|
-
|
951
|
+
if self.hidd_boxes:
|
952
|
+
iid = self.hidd_boxes.pop()
|
953
|
+
self.coords(iid, coords)
|
954
|
+
self.itemconfig(iid, fill=fill, outline=outline, state=state, tags=tags)
|
955
|
+
else:
|
956
|
+
iid = self.create_polygon(coords, fill=fill, outline=outline, state=state, tags=tags, smooth=True)
|
957
|
+
self.disp_boxes.add(iid)
|
945
958
|
return iid
|
946
959
|
|
947
960
|
def hide_box(self, item: int) -> None:
|
@@ -1275,7 +1288,7 @@ class ColumnHeaders(tk.Canvas):
|
|
1275
1288
|
self.disp_dropdown[t] = True
|
1276
1289
|
|
1277
1290
|
def redraw_checkbox(self, x1, y1, x2, y2, fill, outline, tag, draw_check=False):
|
1278
|
-
points =
|
1291
|
+
points = rounded_box_coords(x1, y1, x2, y2)
|
1279
1292
|
if self.hidd_checkbox:
|
1280
1293
|
t, sh = self.hidd_checkbox.popitem()
|
1281
1294
|
self.coords(t, points)
|
@@ -1293,7 +1306,7 @@ class ColumnHeaders(tk.Canvas):
|
|
1293
1306
|
y1 = y1 + 4
|
1294
1307
|
x2 = x2 - 3
|
1295
1308
|
y2 = y2 - 3
|
1296
|
-
points =
|
1309
|
+
points = rounded_box_coords(x1, y1, x2, y2, radius=4)
|
1297
1310
|
if self.hidd_checkbox:
|
1298
1311
|
t, sh = self.hidd_checkbox.popitem()
|
1299
1312
|
self.coords(t, points)
|
@@ -1573,16 +1586,14 @@ class ColumnHeaders(tk.Canvas):
|
|
1573
1586
|
dct[iid] = False
|
1574
1587
|
return True
|
1575
1588
|
|
1576
|
-
def get_redraw_selections(self, startc, endc):
|
1577
|
-
d = defaultdict(
|
1589
|
+
def get_redraw_selections(self, startc: int, endc: int) -> dict[str, set[int]]:
|
1590
|
+
d = defaultdict(set)
|
1578
1591
|
for item, box in self.MT.get_selection_items(rows=False):
|
1579
|
-
|
1580
|
-
|
1581
|
-
|
1582
|
-
|
1583
|
-
|
1584
|
-
d2["columns"] = {c for c in range(startc, endc) for r1, c1, r2, c2 in d["columns"] if c1 <= c and c2 > c}
|
1585
|
-
return d2
|
1592
|
+
r1, c1, r2, c2 = box.coords
|
1593
|
+
for c in range(startc, endc):
|
1594
|
+
if c1 <= c and c2 > c:
|
1595
|
+
d[box.type_].add(c)
|
1596
|
+
return d
|
1586
1597
|
|
1587
1598
|
def open_cell(self, event: object = None, ignore_existing_editor=False):
|
1588
1599
|
if not self.MT.anything_selected() or (not ignore_existing_editor and self.text_editor.open):
|
@@ -1622,14 +1633,13 @@ class ColumnHeaders(tk.Canvas):
|
|
1622
1633
|
) -> bool:
|
1623
1634
|
text = None
|
1624
1635
|
extra_func_key = "??"
|
1625
|
-
datacn = c if self.MT.all_columns_displayed else self.MT.displayed_columns[c]
|
1626
1636
|
if event is None or self.MT.event_opens_dropdown_or_checkbox(event):
|
1627
1637
|
if event is not None:
|
1628
1638
|
if hasattr(event, "keysym") and event.keysym == "Return":
|
1629
1639
|
extra_func_key = "Return"
|
1630
1640
|
elif hasattr(event, "keysym") and event.keysym == "F2":
|
1631
1641
|
extra_func_key = "F2"
|
1632
|
-
text = self.get_cell_data(datacn, none_to_empty_str=True, redirect_int=True)
|
1642
|
+
text = self.get_cell_data(self.MT.datacn(c), none_to_empty_str=True, redirect_int=True)
|
1633
1643
|
elif event is not None and (
|
1634
1644
|
(hasattr(event, "keysym") and event.keysym == "BackSpace") or event.keycode in (8, 855638143)
|
1635
1645
|
):
|
@@ -1679,9 +1689,8 @@ class ColumnHeaders(tk.Canvas):
|
|
1679
1689
|
y = 0
|
1680
1690
|
w = self.MT.col_positions[c + 1] - x
|
1681
1691
|
h = self.current_height + 1
|
1682
|
-
datacn = c if self.MT.all_columns_displayed else self.MT.displayed_columns[c]
|
1683
1692
|
if text is None:
|
1684
|
-
text = self.get_cell_data(datacn, none_to_empty_str=True, redirect_int=True)
|
1693
|
+
text = self.get_cell_data(self.MT.datacn(c), none_to_empty_str=True, redirect_int=True)
|
1685
1694
|
bg, fg = self.PAR.ops.header_bg, self.PAR.ops.header_fg
|
1686
1695
|
kwargs = {
|
1687
1696
|
"menu_kwargs": DotDict(
|
@@ -1754,7 +1763,7 @@ class ColumnHeaders(tk.Canvas):
|
|
1754
1763
|
not check_lines
|
1755
1764
|
or self.MT.get_lines_cell_height(
|
1756
1765
|
self.text_editor.window.get_num_lines() + 1,
|
1757
|
-
font=self.
|
1766
|
+
font=self.text_editor.tktext.cget("font"),
|
1758
1767
|
)
|
1759
1768
|
> curr_height
|
1760
1769
|
):
|
@@ -1774,41 +1783,52 @@ class ColumnHeaders(tk.Canvas):
|
|
1774
1783
|
)
|
1775
1784
|
self.itemconfig(self.dropdown.canvas_id, anchor=anchor, height=win_h)
|
1776
1785
|
|
1777
|
-
def refresh_open_window_positions(self):
|
1786
|
+
def refresh_open_window_positions(self, zoom: Literal["in", "out"]):
|
1778
1787
|
if self.text_editor.open:
|
1779
1788
|
c = self.text_editor.column
|
1780
|
-
self.text_editor.window.config(
|
1789
|
+
self.text_editor.window.config(
|
1790
|
+
height=self.current_height,
|
1791
|
+
width=self.MT.col_positions[c + 1] - self.MT.col_positions[c] + 1,
|
1792
|
+
)
|
1793
|
+
self.text_editor.tktext.config(font=self.PAR.ops.header_font)
|
1781
1794
|
self.coords(
|
1782
1795
|
self.text_editor.canvas_id,
|
1783
|
-
0,
|
1784
1796
|
self.MT.col_positions[c],
|
1797
|
+
0,
|
1785
1798
|
)
|
1786
1799
|
if self.dropdown.open:
|
1800
|
+
if zoom == "in":
|
1801
|
+
self.dropdown.window.zoom_in()
|
1802
|
+
elif zoom == "out":
|
1803
|
+
self.dropdown.window.zoom_out()
|
1787
1804
|
c = self.dropdown.get_coords()
|
1788
1805
|
if self.text_editor.open:
|
1789
1806
|
text_editor_h = self.text_editor.window.winfo_height()
|
1790
1807
|
win_h, anchor = self.get_dropdown_height_anchor(c, text_editor_h)
|
1791
1808
|
else:
|
1792
|
-
text_editor_h = self.
|
1809
|
+
text_editor_h = self.current_height
|
1793
1810
|
anchor = self.itemcget(self.dropdown.canvas_id, "anchor")
|
1794
1811
|
# win_h = 0
|
1812
|
+
self.dropdown.window.config(width=self.MT.col_positions[c + 1] - self.MT.col_positions[c] + 1)
|
1795
1813
|
if anchor == "nw":
|
1796
1814
|
self.coords(
|
1797
1815
|
self.dropdown.canvas_id,
|
1798
|
-
|
1799
|
-
|
1816
|
+
self.MT.col_positions[c],
|
1817
|
+
text_editor_h - 1,
|
1800
1818
|
)
|
1801
1819
|
# self.itemconfig(self.dropdown.canvas_id, anchor=anchor, height=win_h)
|
1802
1820
|
elif anchor == "sw":
|
1803
1821
|
self.coords(
|
1804
1822
|
self.dropdown.canvas_id,
|
1805
|
-
0,
|
1806
1823
|
self.MT.col_positions[c],
|
1824
|
+
0,
|
1807
1825
|
)
|
1808
1826
|
# self.itemconfig(self.dropdown.canvas_id, anchor=anchor, height=win_h)
|
1809
1827
|
|
1810
1828
|
def hide_text_editor(self, reason: None | str = None) -> None:
|
1811
1829
|
if self.text_editor.open:
|
1830
|
+
for b in ("<Alt-Return>", "<Option-Return>", "<Tab>", "<Return>", "<FocusOut>", "<Escape>"):
|
1831
|
+
self.text_editor.tktext.unbind(b)
|
1812
1832
|
self.itemconfig(self.text_editor.canvas_id, state="hidden")
|
1813
1833
|
self.text_editor.open = False
|
1814
1834
|
if reason == "Escape":
|
@@ -1832,7 +1852,7 @@ class ColumnHeaders(tk.Canvas):
|
|
1832
1852
|
self.hide_text_editor_and_dropdown()
|
1833
1853
|
return
|
1834
1854
|
# setting cell data with text editor value
|
1835
|
-
|
1855
|
+
text_editor_value = self.text_editor.get()
|
1836
1856
|
c = editor_info[0]
|
1837
1857
|
datacn = c if self.MT.all_columns_displayed else self.MT.displayed_columns[c]
|
1838
1858
|
event_data = event_dict(
|
@@ -1840,7 +1860,7 @@ class ColumnHeaders(tk.Canvas):
|
|
1840
1860
|
sheet=self.PAR.name,
|
1841
1861
|
cells_header={datacn: self.get_cell_data(datacn)},
|
1842
1862
|
key=editor_info[1] if len(editor_info) >= 2 else "FocusOut",
|
1843
|
-
value=
|
1863
|
+
value=text_editor_value,
|
1844
1864
|
loc=c,
|
1845
1865
|
boxes=self.MT.get_boxes(),
|
1846
1866
|
selected=self.MT.selected,
|
@@ -1853,11 +1873,11 @@ class ColumnHeaders(tk.Canvas):
|
|
1853
1873
|
check_input_valid=False,
|
1854
1874
|
)
|
1855
1875
|
if self.MT.edit_validation_func:
|
1856
|
-
|
1857
|
-
if
|
1858
|
-
edited = set_data(value=
|
1859
|
-
elif self.input_valid_for_cell(datacn,
|
1860
|
-
edited = set_data(value=
|
1876
|
+
text_editor_value = self.MT.edit_validation_func(event_data)
|
1877
|
+
if text_editor_value is not None and self.input_valid_for_cell(datacn, text_editor_value):
|
1878
|
+
edited = set_data(value=text_editor_value)
|
1879
|
+
elif self.input_valid_for_cell(datacn, text_editor_value):
|
1880
|
+
edited = set_data(value=text_editor_value)
|
1861
1881
|
if edited:
|
1862
1882
|
try_binding(self.extra_end_edit_cell_func, event_data)
|
1863
1883
|
self.MT.recreate_all_selection_boxes()
|
@@ -1901,11 +1921,9 @@ class ColumnHeaders(tk.Canvas):
|
|
1901
1921
|
modified_func(event)
|
1902
1922
|
dd_window.search_and_see(event)
|
1903
1923
|
|
1904
|
-
def open_dropdown_window(self, c,
|
1924
|
+
def open_dropdown_window(self, c, event: object = None):
|
1905
1925
|
self.hide_text_editor("Escape")
|
1906
|
-
|
1907
|
-
datacn = c if self.MT.all_columns_displayed else self.MT.displayed_columns[c]
|
1908
|
-
kwargs = self.get_cell_kwargs(datacn, key="dropdown")
|
1926
|
+
kwargs = self.get_cell_kwargs(self.MT.datacn(c), key="dropdown")
|
1909
1927
|
if kwargs["state"] == "normal":
|
1910
1928
|
if not self.open_text_editor(event=event, c=c, dropdown=True):
|
1911
1929
|
return
|
@@ -2031,6 +2049,7 @@ class ColumnHeaders(tk.Canvas):
|
|
2031
2049
|
|
2032
2050
|
def hide_dropdown_window(self) -> None:
|
2033
2051
|
if self.dropdown.open:
|
2052
|
+
self.dropdown.window.unbind("<FocusOut>")
|
2034
2053
|
self.itemconfig(self.dropdown.canvas_id, state="hidden")
|
2035
2054
|
self.dropdown.open = False
|
2036
2055
|
|
tksheet/functions.py
CHANGED
@@ -245,6 +245,12 @@ def is_iterable(o: object) -> bool:
|
|
245
245
|
return False
|
246
246
|
|
247
247
|
|
248
|
+
def int_x_iter(i: Iterator[int] | int) -> Iterator[int]:
|
249
|
+
if isinstance(i, int):
|
250
|
+
return (i,)
|
251
|
+
return i
|
252
|
+
|
253
|
+
|
248
254
|
def unpack(t: tuple[object] | tuple[Iterator[object]]) -> tuple[object]:
|
249
255
|
if not len(t):
|
250
256
|
return t
|
@@ -345,21 +351,27 @@ def get_seq_without_gaps_at_index(
|
|
345
351
|
return seq
|
346
352
|
|
347
353
|
|
348
|
-
def consecutive_chunks(seq: list[
|
349
|
-
if not seq:
|
350
|
-
yield seq
|
354
|
+
def consecutive_chunks(seq: list[int]) -> Generator[list[int]]:
|
351
355
|
start = 0
|
352
|
-
|
353
|
-
|
354
|
-
|
355
|
-
|
356
|
-
|
357
|
-
yield seq[start:end]
|
358
|
-
start = end
|
359
|
-
else:
|
356
|
+
for index, value in enumerate(seq, 1):
|
357
|
+
try:
|
358
|
+
if seq[index] > value + 1:
|
359
|
+
yield seq[start : (start := index)]
|
360
|
+
except Exception:
|
360
361
|
yield seq[start : len(seq)]
|
361
362
|
|
362
363
|
|
364
|
+
def consecutive_ranges(seq: Sequence[int]) -> Generator[tuple[int, int]]:
|
365
|
+
start = 0
|
366
|
+
for index, value in enumerate(seq, 1):
|
367
|
+
try:
|
368
|
+
if seq[index] > value + 1:
|
369
|
+
yield seq[start], seq[index - 1] + 1
|
370
|
+
start = index
|
371
|
+
except Exception:
|
372
|
+
yield seq[start], seq[-1] + 1
|
373
|
+
|
374
|
+
|
363
375
|
def is_contiguous(seq: list[int]) -> bool:
|
364
376
|
itr = iter(seq)
|
365
377
|
prev = next(itr)
|
@@ -492,14 +504,14 @@ def displayed_to_data_idxs(
|
|
492
504
|
return [displayed[e] for e in to_convert]
|
493
505
|
|
494
506
|
|
495
|
-
def
|
507
|
+
def rounded_box_coords(
|
496
508
|
x1: float,
|
497
509
|
y1: float,
|
498
510
|
x2: float,
|
499
511
|
y2: float,
|
500
512
|
radius: int = 8,
|
501
|
-
) ->
|
502
|
-
return
|
513
|
+
) -> tuple[float]:
|
514
|
+
return (
|
503
515
|
x1 + radius,
|
504
516
|
y1,
|
505
517
|
x1 + radius,
|
@@ -540,7 +552,7 @@ def get_checkbox_points(
|
|
540
552
|
y1 + radius,
|
541
553
|
x1,
|
542
554
|
y1,
|
543
|
-
|
555
|
+
)
|
544
556
|
|
545
557
|
|
546
558
|
def diff_list(seq: list[float]) -> list[int]:
|
tksheet/listbox.py
ADDED
@@ -0,0 +1,19 @@
|
|
1
|
+
from __future__ import annotations
|
2
|
+
import tkinter as tk
|
3
|
+
# from collections.abc import Callable, Generator, Iterator, Sequence
|
4
|
+
|
5
|
+
from .sheet import (
|
6
|
+
Sheet,
|
7
|
+
)
|
8
|
+
|
9
|
+
|
10
|
+
class ListBox(Sheet):
|
11
|
+
def __init__(
|
12
|
+
self,
|
13
|
+
parent: tk.Misc,
|
14
|
+
) -> None:
|
15
|
+
Sheet.__init__(
|
16
|
+
self,
|
17
|
+
parent=parent,
|
18
|
+
)
|
19
|
+
self.parent = parent
|