tksheet 7.2.1__py3-none-any.whl → 7.2.3__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 +1 -1
- tksheet/column_headers.py +247 -201
- tksheet/main_table.py +135 -116
- tksheet/row_index.py +234 -196
- tksheet/sheet.py +86 -47
- tksheet/top_left_rectangle.py +7 -2
- {tksheet-7.2.1.dist-info → tksheet-7.2.3.dist-info}/METADATA +6 -4
- tksheet-7.2.3.dist-info/RECORD +20 -0
- tksheet-7.2.1.dist-info/RECORD +0 -20
- {tksheet-7.2.1.dist-info → tksheet-7.2.3.dist-info}/LICENSE.txt +0 -0
- {tksheet-7.2.1.dist-info → tksheet-7.2.3.dist-info}/WHEEL +0 -0
- {tksheet-7.2.1.dist-info → tksheet-7.2.3.dist-info}/top_level.txt +0 -0
tksheet/column_headers.py
CHANGED
@@ -4,6 +4,7 @@ import tkinter as tk
|
|
4
4
|
from collections import defaultdict
|
5
5
|
from collections.abc import (
|
6
6
|
Callable,
|
7
|
+
Hashable,
|
7
8
|
Sequence,
|
8
9
|
)
|
9
10
|
from functools import (
|
@@ -12,8 +13,12 @@ from functools import (
|
|
12
13
|
from itertools import (
|
13
14
|
cycle,
|
14
15
|
islice,
|
16
|
+
repeat,
|
15
17
|
)
|
16
18
|
from math import ceil, floor
|
19
|
+
from operator import (
|
20
|
+
itemgetter,
|
21
|
+
)
|
17
22
|
from typing import Literal
|
18
23
|
|
19
24
|
from .colors import (
|
@@ -134,7 +139,7 @@ class ColumnHeaders(tk.Canvas):
|
|
134
139
|
else:
|
135
140
|
super().event_generate(*args, **kwargs)
|
136
141
|
|
137
|
-
def basic_bindings(self, enable: bool = True):
|
142
|
+
def basic_bindings(self, enable: bool = True) -> None:
|
138
143
|
if enable:
|
139
144
|
self.bind("<Motion>", self.mouse_motion)
|
140
145
|
self.bind("<ButtonPress-1>", self.b1_press)
|
@@ -158,22 +163,26 @@ class ColumnHeaders(tk.Canvas):
|
|
158
163
|
self.unbind("<Button-4>")
|
159
164
|
self.unbind("<Button-5>")
|
160
165
|
|
161
|
-
def mousewheel(self, event: object):
|
162
|
-
maxlines = 0
|
166
|
+
def mousewheel(self, event: object) -> None:
|
163
167
|
if isinstance(self.MT._headers, int):
|
164
|
-
|
165
|
-
|
168
|
+
maxlines = max(
|
169
|
+
(
|
166
170
|
len(
|
167
171
|
self.MT.get_valid_cell_data_as_str(self.MT._headers, datacn, get_displayed=True)
|
168
172
|
.rstrip()
|
169
173
|
.split("\n")
|
170
174
|
)
|
171
175
|
for datacn in range(len(self.MT.data[self.MT._headers]))
|
172
|
-
)
|
176
|
+
),
|
177
|
+
default=0,
|
178
|
+
)
|
173
179
|
elif isinstance(self.MT._headers, (list, tuple)):
|
174
180
|
maxlines = max(
|
175
|
-
|
176
|
-
|
181
|
+
(
|
182
|
+
len(e.rstrip().split("\n")) if isinstance(e, str) else len(f"{e}".rstrip().split("\n"))
|
183
|
+
for e in self.MT._headers
|
184
|
+
),
|
185
|
+
default=0,
|
177
186
|
)
|
178
187
|
if maxlines == 1:
|
179
188
|
maxlines = 0
|
@@ -390,7 +399,7 @@ class ColumnHeaders(tk.Canvas):
|
|
390
399
|
self.MT.reset_mouse_motion_creations()
|
391
400
|
try_binding(self.extra_motion_func, event)
|
392
401
|
|
393
|
-
def double_b1(self, event: object):
|
402
|
+
def double_b1(self, event: object) -> None:
|
394
403
|
self.mouseclick_outside_editor_or_dropdown_all_canvases(inside=True)
|
395
404
|
self.focus_set()
|
396
405
|
if (
|
@@ -430,7 +439,7 @@ class ColumnHeaders(tk.Canvas):
|
|
430
439
|
self.mouse_motion(event)
|
431
440
|
try_binding(self.extra_double_b1_func, event)
|
432
441
|
|
433
|
-
def b1_press(self, event: object):
|
442
|
+
def b1_press(self, event: object) -> None:
|
434
443
|
self.MT.unbind("<MouseWheel>")
|
435
444
|
self.focus_set()
|
436
445
|
self.closed_dropdown = self.mouseclick_outside_editor_or_dropdown_all_canvases(inside=True)
|
@@ -495,7 +504,7 @@ class ColumnHeaders(tk.Canvas):
|
|
495
504
|
self.toggle_select_col(c, redraw=True)
|
496
505
|
try_binding(self.extra_b1_press_func, event)
|
497
506
|
|
498
|
-
def b1_motion(self, event: object):
|
507
|
+
def b1_motion(self, event: object) -> None:
|
499
508
|
x1, y1, x2, y2 = self.MT.get_canvas_visible_area()
|
500
509
|
if self.width_resizing_enabled and self.rsz_w is not None and self.currently_resizing_width:
|
501
510
|
x = self.canvasx(event.x)
|
@@ -593,13 +602,13 @@ class ColumnHeaders(tk.Canvas):
|
|
593
602
|
self.MT.main_table_redraw_grid_and_text(redraw_header=True, redraw_row_index=False)
|
594
603
|
try_binding(self.extra_b1_motion_func, event)
|
595
604
|
|
596
|
-
def get_b1_motion_box(self, start_col, end_col):
|
605
|
+
def get_b1_motion_box(self, start_col: int, end_col: int) -> tuple[int, int, int, int, Literal["columns"]]:
|
597
606
|
if end_col >= start_col:
|
598
607
|
return 0, start_col, len(self.MT.row_positions) - 1, end_col + 1, "columns"
|
599
608
|
elif end_col < start_col:
|
600
609
|
return 0, end_col, len(self.MT.row_positions) - 1, start_col + 1, "columns"
|
601
610
|
|
602
|
-
def ctrl_b1_motion(self, event: object):
|
611
|
+
def ctrl_b1_motion(self, event: object) -> None:
|
603
612
|
x1, y1, x2, y2 = self.MT.get_canvas_visible_area()
|
604
613
|
if (
|
605
614
|
self.drag_and_drop_enabled
|
@@ -653,7 +662,7 @@ class ColumnHeaders(tk.Canvas):
|
|
653
662
|
elif not self.MT.ctrl_select_enabled:
|
654
663
|
self.b1_motion(event)
|
655
664
|
|
656
|
-
def drag_and_drop_motion(self, event: object):
|
665
|
+
def drag_and_drop_motion(self, event: object) -> float:
|
657
666
|
x = event.x
|
658
667
|
wend = self.winfo_width()
|
659
668
|
xcheck = self.xview()
|
@@ -997,7 +1006,7 @@ class ColumnHeaders(tk.Canvas):
|
|
997
1006
|
self.hidd_boxes.add(item)
|
998
1007
|
self.itemconfig(item, state="hidden")
|
999
1008
|
|
1000
|
-
def get_cell_dimensions(self, datacn):
|
1009
|
+
def get_cell_dimensions(self, datacn: int) -> tuple[int, int]:
|
1001
1010
|
txt = self.get_valid_cell_data_as_str(datacn, fix=False)
|
1002
1011
|
if txt:
|
1003
1012
|
self.MT.txt_measure_canvas.itemconfig(
|
@@ -1015,29 +1024,28 @@ class ColumnHeaders(tk.Canvas):
|
|
1015
1024
|
return w + self.MT.header_txt_height, h
|
1016
1025
|
return w, h
|
1017
1026
|
|
1018
|
-
def set_height_of_header_to_text(
|
1019
|
-
|
1020
|
-
|
1021
|
-
|
1022
|
-
|
1023
|
-
|
1024
|
-
|
1027
|
+
def set_height_of_header_to_text(
|
1028
|
+
self,
|
1029
|
+
text: None | str = None,
|
1030
|
+
only_if_too_small: bool = False,
|
1031
|
+
) -> int:
|
1032
|
+
h = self.MT.min_header_height
|
1033
|
+
if (text is None and not self.MT._headers and isinstance(self.MT._headers, list)) or (
|
1034
|
+
isinstance(self.MT._headers, int) and self.MT._headers >= len(self.MT.data)
|
1025
1035
|
):
|
1026
|
-
return
|
1036
|
+
return h
|
1037
|
+
self.fix_header()
|
1027
1038
|
qconf = self.MT.txt_measure_canvas.itemconfig
|
1028
1039
|
qbbox = self.MT.txt_measure_canvas.bbox
|
1029
1040
|
qtxtm = self.MT.txt_measure_canvas_text
|
1030
1041
|
qfont = self.PAR.ops.header_font
|
1031
|
-
new_height = self.MT.min_header_height
|
1032
1042
|
default_header_height = self.MT.get_default_header_height()
|
1033
|
-
|
1034
|
-
|
1035
|
-
|
1036
|
-
|
1037
|
-
|
1038
|
-
|
1039
|
-
new_height = h
|
1040
|
-
else:
|
1043
|
+
if text is not None and text:
|
1044
|
+
qconf(qtxtm, text=text, font=qfont)
|
1045
|
+
b = qbbox(qtxtm)
|
1046
|
+
if (th := b[3] - b[1] + 5) > h:
|
1047
|
+
h = th
|
1048
|
+
elif text is None:
|
1041
1049
|
if self.MT.all_columns_displayed:
|
1042
1050
|
if isinstance(self.MT._headers, list):
|
1043
1051
|
iterable = range(len(self.MT._headers))
|
@@ -1045,141 +1053,142 @@ class ColumnHeaders(tk.Canvas):
|
|
1045
1053
|
iterable = range(len(self.MT.data[self.MT._headers]))
|
1046
1054
|
else:
|
1047
1055
|
iterable = self.MT.displayed_columns
|
1048
|
-
if
|
1049
|
-
|
1050
|
-
|
1051
|
-
|
1052
|
-
|
1053
|
-
elif h > self.MT.max_header_height:
|
1054
|
-
h = int(self.MT.max_header_height)
|
1055
|
-
if h > new_height:
|
1056
|
-
new_height = h
|
1056
|
+
if (
|
1057
|
+
isinstance(self.MT._headers, list)
|
1058
|
+
and (th := max(map(itemgetter(0), map(self.get_cell_dimensions, iterable)), default=h)) > h
|
1059
|
+
):
|
1060
|
+
h = th
|
1057
1061
|
elif isinstance(self.MT._headers, int):
|
1058
1062
|
datarn = self.MT._headers
|
1059
1063
|
for datacn in iterable:
|
1060
|
-
txt
|
1061
|
-
if txt:
|
1064
|
+
if txt := self.MT.get_valid_cell_data_as_str(datarn, datacn, get_displayed=True):
|
1062
1065
|
qconf(qtxtm, text=txt, font=qfont)
|
1063
1066
|
b = qbbox(qtxtm)
|
1064
|
-
|
1067
|
+
th = b[3] - b[1] + 5
|
1065
1068
|
else:
|
1066
|
-
|
1067
|
-
if
|
1068
|
-
h =
|
1069
|
-
elif h > self.MT.max_header_height:
|
1070
|
-
h = int(self.MT.max_header_height)
|
1071
|
-
if h > new_height:
|
1072
|
-
new_height = h
|
1069
|
+
th = default_header_height
|
1070
|
+
if th > h:
|
1071
|
+
h = th
|
1073
1072
|
space_bot = self.MT.get_space_bot(0)
|
1074
|
-
if
|
1075
|
-
|
1076
|
-
if
|
1077
|
-
self.
|
1073
|
+
if h > space_bot and space_bot > self.MT.min_header_height:
|
1074
|
+
h = space_bot
|
1075
|
+
if h < self.MT.min_header_height:
|
1076
|
+
h = int(self.MT.min_header_height)
|
1077
|
+
elif h > self.MT.max_header_height:
|
1078
|
+
h = int(self.MT.max_header_height)
|
1079
|
+
if not only_if_too_small or (only_if_too_small and h > self.current_height):
|
1080
|
+
self.set_height(h, set_TL=True)
|
1078
1081
|
self.MT.main_table_redraw_grid_and_text(redraw_header=True, redraw_row_index=True)
|
1079
|
-
return
|
1082
|
+
return h
|
1080
1083
|
|
1081
|
-
def
|
1084
|
+
def get_col_text_width(
|
1082
1085
|
self,
|
1083
|
-
col,
|
1084
|
-
|
1085
|
-
|
1086
|
-
|
1087
|
-
recreate=True,
|
1088
|
-
return_new_width=False,
|
1089
|
-
):
|
1090
|
-
if col < 0:
|
1091
|
-
return
|
1092
|
-
qconf = self.MT.txt_measure_canvas.itemconfig
|
1093
|
-
qbbox = self.MT.txt_measure_canvas.bbox
|
1094
|
-
qtxtm = self.MT.txt_measure_canvas_text
|
1095
|
-
qtxth = self.MT.table_txt_height
|
1096
|
-
qfont = self.PAR.ops.table_font
|
1086
|
+
col: int,
|
1087
|
+
visible_only: bool = False,
|
1088
|
+
only_if_too_small: bool = False,
|
1089
|
+
) -> int:
|
1097
1090
|
self.fix_header()
|
1098
|
-
|
1099
|
-
|
1100
|
-
|
1091
|
+
w = self.MT.min_column_width
|
1092
|
+
datacn = col if self.MT.all_columns_displayed else self.MT.displayed_columns[col]
|
1093
|
+
# header
|
1094
|
+
hw, hh_ = self.get_cell_dimensions(datacn)
|
1095
|
+
# table
|
1096
|
+
if self.MT.data:
|
1101
1097
|
if self.MT.all_rows_displayed:
|
1102
|
-
if
|
1103
|
-
|
1104
|
-
start_row, end_row = self.MT.get_visible_rows(y1, y2)
|
1098
|
+
if visible_only:
|
1099
|
+
iterable = range(*self.MT.visible_text_rows)
|
1105
1100
|
else:
|
1106
|
-
|
1107
|
-
iterable = range(start_row, end_row)
|
1101
|
+
iterable = range(0, len(self.MT.data))
|
1108
1102
|
else:
|
1109
|
-
if
|
1110
|
-
|
1111
|
-
start_row, end_row = self.MT.get_visible_rows(y1, y2)
|
1103
|
+
if visible_only:
|
1104
|
+
start_row, end_row = self.MT.visible_text_rows
|
1112
1105
|
else:
|
1113
1106
|
start_row, end_row = 0, len(self.MT.displayed_rows)
|
1114
1107
|
iterable = self.MT.displayed_rows[start_row:end_row]
|
1115
|
-
|
1116
|
-
|
1117
|
-
|
1118
|
-
|
1119
|
-
|
1120
|
-
|
1121
|
-
|
1122
|
-
|
1123
|
-
|
1124
|
-
|
1125
|
-
|
1126
|
-
|
1127
|
-
|
1128
|
-
|
1129
|
-
|
1130
|
-
|
1131
|
-
|
1132
|
-
|
1133
|
-
|
1134
|
-
|
1135
|
-
|
1136
|
-
|
1137
|
-
|
1138
|
-
|
1139
|
-
|
1140
|
-
new_width = int(self.MT.min_column_width)
|
1141
|
-
elif new_width > self.MT.max_column_width:
|
1142
|
-
new_width = int(self.MT.max_column_width)
|
1143
|
-
if only_set_if_too_small:
|
1144
|
-
if new_width <= self.MT.col_positions[col + 1] - self.MT.col_positions[col]:
|
1145
|
-
return self.MT.col_positions[col + 1] - self.MT.col_positions[col]
|
1146
|
-
if not return_new_width:
|
1147
|
-
new_col_pos = self.MT.col_positions[col] + new_width
|
1148
|
-
increment = new_col_pos - self.MT.col_positions[col + 1]
|
1149
|
-
self.MT.col_positions[col + 2 :] = [
|
1150
|
-
e + increment for e in islice(self.MT.col_positions, col + 2, len(self.MT.col_positions))
|
1151
|
-
]
|
1152
|
-
self.MT.col_positions[col + 1] = new_col_pos
|
1153
|
-
if recreate:
|
1154
|
-
self.MT.recreate_all_selection_boxes()
|
1155
|
-
return new_width
|
1108
|
+
qconf = self.MT.txt_measure_canvas.itemconfig
|
1109
|
+
qbbox = self.MT.txt_measure_canvas.bbox
|
1110
|
+
qtxtm = self.MT.txt_measure_canvas_text
|
1111
|
+
qtxth = self.MT.table_txt_height
|
1112
|
+
qfont = self.PAR.ops.table_font
|
1113
|
+
for datarn in iterable:
|
1114
|
+
if txt := self.MT.get_valid_cell_data_as_str(datarn, datacn, get_displayed=True):
|
1115
|
+
qconf(qtxtm, text=txt, font=qfont)
|
1116
|
+
b = qbbox(qtxtm)
|
1117
|
+
if (
|
1118
|
+
self.MT.get_cell_kwargs(datarn, datacn, key="dropdown")
|
1119
|
+
or self.MT.get_cell_kwargs(datarn, datacn, key="checkbox")
|
1120
|
+
) and (tw := b[2] - b[0] + qtxth + 7) > w:
|
1121
|
+
w = tw
|
1122
|
+
elif (tw := b[2] - b[0] + 7) > w:
|
1123
|
+
w = tw
|
1124
|
+
if hw > w:
|
1125
|
+
w = hw
|
1126
|
+
if only_if_too_small and w < self.MT.col_positions[col + 1] - self.MT.col_positions[col]:
|
1127
|
+
w = self.MT.col_positions[col + 1] - self.MT.col_positions[col]
|
1128
|
+
if w <= self.MT.min_column_width:
|
1129
|
+
w = int(self.MT.min_column_width)
|
1130
|
+
elif w > self.MT.max_column_width:
|
1131
|
+
w = int(self.MT.max_column_width)
|
1132
|
+
return w
|
1156
1133
|
|
1157
|
-
def
|
1134
|
+
def set_col_width(
|
1135
|
+
self,
|
1136
|
+
col: int,
|
1137
|
+
width: None | int = None,
|
1138
|
+
only_if_too_small: bool = False,
|
1139
|
+
visible_only: bool = False,
|
1140
|
+
recreate: bool = True,
|
1141
|
+
) -> int:
|
1142
|
+
if width is None:
|
1143
|
+
width = self.get_col_text_width(col=col, visible_only=visible_only)
|
1144
|
+
if width <= self.MT.min_column_width:
|
1145
|
+
width = int(self.MT.min_column_width)
|
1146
|
+
elif width > self.MT.max_column_width:
|
1147
|
+
width = int(self.MT.max_column_width)
|
1148
|
+
if only_if_too_small and width <= self.MT.col_positions[col + 1] - self.MT.col_positions[col]:
|
1149
|
+
return self.MT.col_positions[col + 1] - self.MT.col_positions[col]
|
1150
|
+
new_col_pos = self.MT.col_positions[col] + width
|
1151
|
+
increment = new_col_pos - self.MT.col_positions[col + 1]
|
1152
|
+
self.MT.col_positions[col + 2 :] = [
|
1153
|
+
e + increment for e in islice(self.MT.col_positions, col + 2, len(self.MT.col_positions))
|
1154
|
+
]
|
1155
|
+
self.MT.col_positions[col + 1] = new_col_pos
|
1156
|
+
if recreate:
|
1157
|
+
self.MT.recreate_all_selection_boxes()
|
1158
|
+
return width
|
1159
|
+
|
1160
|
+
def set_width_of_all_cols(
|
1161
|
+
self,
|
1162
|
+
width: None | int = None,
|
1163
|
+
only_if_too_small: bool = False,
|
1164
|
+
recreate: bool = True,
|
1165
|
+
) -> None:
|
1158
1166
|
if width is None:
|
1159
1167
|
if self.MT.all_columns_displayed:
|
1160
1168
|
iterable = range(self.MT.total_data_cols())
|
1161
1169
|
else:
|
1162
1170
|
iterable = range(len(self.MT.displayed_columns))
|
1163
1171
|
self.MT.set_col_positions(
|
1164
|
-
itr=(
|
1165
|
-
self.set_col_width(
|
1166
|
-
cn,
|
1167
|
-
only_set_if_too_small=only_set_if_too_small,
|
1168
|
-
recreate=False,
|
1169
|
-
return_new_width=True,
|
1170
|
-
)
|
1171
|
-
for cn in iterable
|
1172
|
-
)
|
1172
|
+
itr=(self.get_col_text_width(cn, only_if_too_small=only_if_too_small) for cn in iterable)
|
1173
1173
|
)
|
1174
1174
|
elif width is not None:
|
1175
1175
|
if self.MT.all_columns_displayed:
|
1176
|
-
self.MT.set_col_positions(itr=(width
|
1176
|
+
self.MT.set_col_positions(itr=repeat(width, self.MT.total_data_cols()))
|
1177
1177
|
else:
|
1178
|
-
self.MT.set_col_positions(itr=(width
|
1178
|
+
self.MT.set_col_positions(itr=repeat(width, len(self.MT.displayed_columns)))
|
1179
1179
|
if recreate:
|
1180
1180
|
self.MT.recreate_all_selection_boxes()
|
1181
1181
|
|
1182
|
-
def redraw_highlight_get_text_fg(
|
1182
|
+
def redraw_highlight_get_text_fg(
|
1183
|
+
self,
|
1184
|
+
fc: float,
|
1185
|
+
sc: float,
|
1186
|
+
c: int,
|
1187
|
+
c_2: str,
|
1188
|
+
c_3: str,
|
1189
|
+
selections: dict,
|
1190
|
+
datacn: int,
|
1191
|
+
) -> tuple[str, bool]:
|
1183
1192
|
redrawn = False
|
1184
1193
|
kwargs = self.get_cell_kwargs(datacn, key="highlight")
|
1185
1194
|
if kwargs:
|
@@ -1236,7 +1245,16 @@ class ColumnHeaders(tk.Canvas):
|
|
1236
1245
|
tf = self.PAR.ops.header_fg
|
1237
1246
|
return tf, redrawn
|
1238
1247
|
|
1239
|
-
def redraw_highlight(
|
1248
|
+
def redraw_highlight(
|
1249
|
+
self,
|
1250
|
+
x1: float,
|
1251
|
+
y1: float,
|
1252
|
+
x2: float,
|
1253
|
+
y2: float,
|
1254
|
+
fill: str,
|
1255
|
+
outline: str,
|
1256
|
+
tag: str | tuple[str],
|
1257
|
+
) -> bool:
|
1240
1258
|
coords = (x1, y1, x2, y2)
|
1241
1259
|
if self.hidd_high:
|
1242
1260
|
iid, showing = self.hidd_high.popitem()
|
@@ -1250,7 +1268,13 @@ class ColumnHeaders(tk.Canvas):
|
|
1250
1268
|
self.disp_high[iid] = True
|
1251
1269
|
return True
|
1252
1270
|
|
1253
|
-
def redraw_gridline(
|
1271
|
+
def redraw_gridline(
|
1272
|
+
self,
|
1273
|
+
points: Sequence[float],
|
1274
|
+
fill: str,
|
1275
|
+
width: int,
|
1276
|
+
tag: str | tuple[str],
|
1277
|
+
) -> None:
|
1254
1278
|
if self.hidd_grid:
|
1255
1279
|
t, sh = self.hidd_grid.popitem()
|
1256
1280
|
self.coords(t, points)
|
@@ -1264,17 +1288,17 @@ class ColumnHeaders(tk.Canvas):
|
|
1264
1288
|
|
1265
1289
|
def redraw_dropdown(
|
1266
1290
|
self,
|
1267
|
-
x1,
|
1268
|
-
y1,
|
1269
|
-
x2,
|
1270
|
-
y2,
|
1271
|
-
fill,
|
1272
|
-
outline,
|
1273
|
-
tag,
|
1274
|
-
draw_outline=True,
|
1275
|
-
draw_arrow=True,
|
1276
|
-
dd_is_open=False,
|
1277
|
-
):
|
1291
|
+
x1: float,
|
1292
|
+
y1: float,
|
1293
|
+
x2: float,
|
1294
|
+
y2: float,
|
1295
|
+
fill: str,
|
1296
|
+
outline: str,
|
1297
|
+
tag: str | tuple[str],
|
1298
|
+
draw_outline: bool = True,
|
1299
|
+
draw_arrow: bool = True,
|
1300
|
+
dd_is_open: bool = False,
|
1301
|
+
) -> None:
|
1278
1302
|
if draw_outline and self.PAR.ops.show_dropdown_borders:
|
1279
1303
|
self.redraw_highlight(x1 + 1, y1 + 1, x2, y2, fill="", outline=self.PAR.ops.header_fg, tag=tag)
|
1280
1304
|
if draw_arrow:
|
@@ -1318,7 +1342,17 @@ class ColumnHeaders(tk.Canvas):
|
|
1318
1342
|
)
|
1319
1343
|
self.disp_dropdown[t] = True
|
1320
1344
|
|
1321
|
-
def redraw_checkbox(
|
1345
|
+
def redraw_checkbox(
|
1346
|
+
self,
|
1347
|
+
x1: float,
|
1348
|
+
y1: float,
|
1349
|
+
x2: float,
|
1350
|
+
y2: float,
|
1351
|
+
fill: str,
|
1352
|
+
outline: str,
|
1353
|
+
tag: str | tuple[str],
|
1354
|
+
draw_check: bool = False,
|
1355
|
+
) -> None:
|
1322
1356
|
points = rounded_box_coords(x1, y1, x2, y2)
|
1323
1357
|
if self.hidd_checkbox:
|
1324
1358
|
t, sh = self.hidd_checkbox.popitem()
|
@@ -1362,18 +1396,20 @@ class ColumnHeaders(tk.Canvas):
|
|
1362
1396
|
|
1363
1397
|
def redraw_grid_and_text(
|
1364
1398
|
self,
|
1365
|
-
last_col_line_pos,
|
1366
|
-
scrollpos_left,
|
1367
|
-
x_stop,
|
1368
|
-
|
1369
|
-
|
1370
|
-
|
1371
|
-
|
1372
|
-
|
1399
|
+
last_col_line_pos: float,
|
1400
|
+
scrollpos_left: float,
|
1401
|
+
x_stop: float,
|
1402
|
+
grid_start_col: int,
|
1403
|
+
grid_end_col: int,
|
1404
|
+
text_start_col: int,
|
1405
|
+
text_end_col: int,
|
1406
|
+
scrollpos_right: float,
|
1407
|
+
col_pos_exists: bool,
|
1408
|
+
) -> bool:
|
1373
1409
|
try:
|
1374
1410
|
self.configure_scrollregion(last_col_line_pos=last_col_line_pos)
|
1375
1411
|
except Exception:
|
1376
|
-
return
|
1412
|
+
return False
|
1377
1413
|
self.hidd_text.update(self.disp_text)
|
1378
1414
|
self.disp_text = {}
|
1379
1415
|
self.hidd_high.update(self.disp_high)
|
@@ -1391,7 +1427,7 @@ class ColumnHeaders(tk.Canvas):
|
|
1391
1427
|
x_stop,
|
1392
1428
|
self.current_height,
|
1393
1429
|
)
|
1394
|
-
draw_x = self.MT.col_positions[
|
1430
|
+
draw_x = self.MT.col_positions[grid_start_col]
|
1395
1431
|
yend = self.current_height - 5
|
1396
1432
|
if (self.PAR.ops.show_vertical_grid or self.width_resizing_enabled) and col_pos_exists:
|
1397
1433
|
points = [
|
@@ -1402,7 +1438,7 @@ class ColumnHeaders(tk.Canvas):
|
|
1402
1438
|
scrollpos_left - 1,
|
1403
1439
|
-1,
|
1404
1440
|
]
|
1405
|
-
for c in range(
|
1441
|
+
for c in range(grid_start_col, grid_end_col):
|
1406
1442
|
draw_x = self.MT.col_positions[c]
|
1407
1443
|
if self.width_resizing_enabled:
|
1408
1444
|
self.visible_col_dividers[c] = (draw_x - 2, 1, draw_x + 2, yend)
|
@@ -1431,9 +1467,9 @@ class ColumnHeaders(tk.Canvas):
|
|
1431
1467
|
else color_map[self.PAR.ops.header_selected_columns_bg]
|
1432
1468
|
)
|
1433
1469
|
font = self.PAR.ops.header_font
|
1434
|
-
selections = self.get_redraw_selections(
|
1470
|
+
selections = self.get_redraw_selections(text_start_col, grid_end_col)
|
1435
1471
|
dd_coords = self.dropdown.get_coords()
|
1436
|
-
for c in range(
|
1472
|
+
for c in range(text_start_col, text_end_col):
|
1437
1473
|
draw_y = self.MT.header_first_ln_ins
|
1438
1474
|
cleftgridln = self.MT.col_positions[c]
|
1439
1475
|
crightgridln = self.MT.col_positions[c + 1]
|
@@ -1629,7 +1665,7 @@ class ColumnHeaders(tk.Canvas):
|
|
1629
1665
|
d[box.type_ if box.type_ != "rows" else "cells"].add(c)
|
1630
1666
|
return d
|
1631
1667
|
|
1632
|
-
def open_cell(self, event: object = None, ignore_existing_editor=False):
|
1668
|
+
def open_cell(self, event: object = None, ignore_existing_editor: bool = False) -> None:
|
1633
1669
|
if not self.MT.anything_selected() or (not ignore_existing_editor and self.text_editor.open):
|
1634
1670
|
return
|
1635
1671
|
if not self.MT.selected:
|
@@ -1769,14 +1805,19 @@ class ColumnHeaders(tk.Canvas):
|
|
1769
1805
|
self.text_editor.tktext.bind(key, func)
|
1770
1806
|
return True
|
1771
1807
|
|
1772
|
-
# displayed indexes
|
1773
|
-
def text_editor_has_wrapped(
|
1808
|
+
# displayed indexes
|
1809
|
+
def text_editor_has_wrapped(
|
1810
|
+
self,
|
1811
|
+
r: int = 0,
|
1812
|
+
c: int = 0,
|
1813
|
+
check_lines: None = None, # just here to receive text editor arg
|
1814
|
+
) -> None:
|
1774
1815
|
if self.width_resizing_enabled:
|
1775
1816
|
curr_width = self.text_editor.window.winfo_width()
|
1776
1817
|
new_width = curr_width + (self.MT.header_txt_height * 2)
|
1777
1818
|
if new_width != curr_width:
|
1778
1819
|
self.text_editor.window.config(width=new_width)
|
1779
|
-
self.set_col_width_run_binding(c, width=new_width,
|
1820
|
+
self.set_col_width_run_binding(c, width=new_width, only_if_too_small=False)
|
1780
1821
|
if self.dropdown.open and self.dropdown.get_coords() == c:
|
1781
1822
|
self.itemconfig(self.dropdown.canvas_id, width=new_width)
|
1782
1823
|
self.dropdown.window.update_idletasks()
|
@@ -1785,7 +1826,7 @@ class ColumnHeaders(tk.Canvas):
|
|
1785
1826
|
self.coords(self.text_editor.canvas_id, self.MT.col_positions[c] + 1, 0)
|
1786
1827
|
|
1787
1828
|
# displayed indexes
|
1788
|
-
def text_editor_newline_binding(self, event: object = None, check_lines=True):
|
1829
|
+
def text_editor_newline_binding(self, event: object = None, check_lines: bool = True) -> None:
|
1789
1830
|
if not self.height_resizing_enabled:
|
1790
1831
|
return
|
1791
1832
|
curr_height = self.text_editor.window.winfo_height()
|
@@ -1816,7 +1857,7 @@ class ColumnHeaders(tk.Canvas):
|
|
1816
1857
|
)
|
1817
1858
|
self.itemconfig(self.dropdown.canvas_id, anchor=anchor, height=win_h)
|
1818
1859
|
|
1819
|
-
def refresh_open_window_positions(self, zoom: Literal["in", "out"]):
|
1860
|
+
def refresh_open_window_positions(self, zoom: Literal["in", "out"]) -> None:
|
1820
1861
|
if self.text_editor.open:
|
1821
1862
|
c = self.text_editor.column
|
1822
1863
|
self.text_editor.window.config(
|
@@ -1922,7 +1963,11 @@ class ColumnHeaders(tk.Canvas):
|
|
1922
1963
|
self.focus_set()
|
1923
1964
|
return "break"
|
1924
1965
|
|
1925
|
-
def get_dropdown_height_anchor(
|
1966
|
+
def get_dropdown_height_anchor(
|
1967
|
+
self,
|
1968
|
+
c: int,
|
1969
|
+
text_editor_h: None | int = None,
|
1970
|
+
) -> tuple[int, Literal["nw"]]:
|
1926
1971
|
win_h = 5
|
1927
1972
|
datacn = self.MT.datacn(c)
|
1928
1973
|
for i, v in enumerate(self.get_cell_kwargs(datacn, key="dropdown")["values"]):
|
@@ -1957,7 +2002,7 @@ class ColumnHeaders(tk.Canvas):
|
|
1957
2002
|
modified_func(event)
|
1958
2003
|
dd_window.search_and_see(event)
|
1959
2004
|
|
1960
|
-
def open_dropdown_window(self, c, event: object = None):
|
2005
|
+
def open_dropdown_window(self, c: int, event: object = None) -> None:
|
1961
2006
|
self.hide_text_editor("Escape")
|
1962
2007
|
kwargs = self.get_cell_kwargs(self.MT.datacn(c), key="dropdown")
|
1963
2008
|
if kwargs["state"] == "normal":
|
@@ -2030,7 +2075,12 @@ class ColumnHeaders(tk.Canvas):
|
|
2030
2075
|
if redraw:
|
2031
2076
|
self.MT.main_table_redraw_grid_and_text(redraw_header=True, redraw_row_index=False, redraw_table=False)
|
2032
2077
|
|
2033
|
-
def close_dropdown_window(
|
2078
|
+
def close_dropdown_window(
|
2079
|
+
self,
|
2080
|
+
c: None | int = None,
|
2081
|
+
selection: object = None,
|
2082
|
+
redraw: bool = True,
|
2083
|
+
) -> None:
|
2034
2084
|
if c is not None and selection is not None:
|
2035
2085
|
datacn = c if self.MT.all_columns_displayed else self.MT.displayed_columns[c]
|
2036
2086
|
kwargs = self.get_cell_kwargs(datacn, key="dropdown")
|
@@ -2068,7 +2118,7 @@ class ColumnHeaders(tk.Canvas):
|
|
2068
2118
|
if redraw:
|
2069
2119
|
self.MT.refresh()
|
2070
2120
|
|
2071
|
-
def mouseclick_outside_editor_or_dropdown(self, inside: bool = False):
|
2121
|
+
def mouseclick_outside_editor_or_dropdown(self, inside: bool = False) -> int | None:
|
2072
2122
|
closed_dd_coords = self.dropdown.get_coords()
|
2073
2123
|
if self.text_editor.open:
|
2074
2124
|
self.close_text_editor(new_tk_event("ButtonPress-1"))
|
@@ -2082,7 +2132,7 @@ class ColumnHeaders(tk.Canvas):
|
|
2082
2132
|
)
|
2083
2133
|
return closed_dd_coords
|
2084
2134
|
|
2085
|
-
def mouseclick_outside_editor_or_dropdown_all_canvases(self, inside: bool = False):
|
2135
|
+
def mouseclick_outside_editor_or_dropdown_all_canvases(self, inside: bool = False) -> int | None:
|
2086
2136
|
self.RI.mouseclick_outside_editor_or_dropdown()
|
2087
2137
|
self.MT.mouseclick_outside_editor_or_dropdown()
|
2088
2138
|
return self.mouseclick_outside_editor_or_dropdown(inside)
|
@@ -2096,14 +2146,14 @@ class ColumnHeaders(tk.Canvas):
|
|
2096
2146
|
# internal event use
|
2097
2147
|
def set_cell_data_undo(
|
2098
2148
|
self,
|
2099
|
-
c=0,
|
2100
|
-
datacn=None,
|
2101
|
-
value="",
|
2102
|
-
cell_resize=True,
|
2103
|
-
undo=True,
|
2104
|
-
redraw=True,
|
2105
|
-
check_input_valid=True,
|
2106
|
-
):
|
2149
|
+
c: int = 0,
|
2150
|
+
datacn: int | None = None,
|
2151
|
+
value: object = "",
|
2152
|
+
cell_resize: bool = True,
|
2153
|
+
undo: bool = True,
|
2154
|
+
redraw: bool = True,
|
2155
|
+
check_input_valid: bool = True,
|
2156
|
+
) -> bool:
|
2107
2157
|
if datacn is None:
|
2108
2158
|
datacn = c if self.MT.all_columns_displayed else self.MT.displayed_columns[c]
|
2109
2159
|
event_data = event_dict(
|
@@ -2134,7 +2184,7 @@ class ColumnHeaders(tk.Canvas):
|
|
2134
2184
|
self.MT.sheet_modified(event_data)
|
2135
2185
|
return edited
|
2136
2186
|
|
2137
|
-
def set_cell_data(self, datacn=None, value=""):
|
2187
|
+
def set_cell_data(self, datacn: int | None = None, value: object = "") -> None:
|
2138
2188
|
if isinstance(self.MT._headers, int):
|
2139
2189
|
self.MT.set_cell_data(datarn=self.MT._headers, datacn=datacn, value=value)
|
2140
2190
|
else:
|
@@ -2156,7 +2206,7 @@ class ColumnHeaders(tk.Canvas):
|
|
2156
2206
|
return False
|
2157
2207
|
return True
|
2158
2208
|
|
2159
|
-
def cell_equal_to(self, datacn, value):
|
2209
|
+
def cell_equal_to(self, datacn: int, value: object) -> bool:
|
2160
2210
|
self.fix_header(datacn)
|
2161
2211
|
if isinstance(self.MT._headers, list):
|
2162
2212
|
return self.MT._headers[datacn] == value
|
@@ -2165,11 +2215,11 @@ class ColumnHeaders(tk.Canvas):
|
|
2165
2215
|
|
2166
2216
|
def get_cell_data(
|
2167
2217
|
self,
|
2168
|
-
datacn,
|
2169
|
-
get_displayed=False,
|
2170
|
-
none_to_empty_str=False,
|
2171
|
-
redirect_int=False,
|
2172
|
-
):
|
2218
|
+
datacn: int,
|
2219
|
+
get_displayed: bool = False,
|
2220
|
+
none_to_empty_str: bool = False,
|
2221
|
+
redirect_int: bool = False,
|
2222
|
+
) -> object:
|
2173
2223
|
if get_displayed:
|
2174
2224
|
return self.get_valid_cell_data_as_str(datacn, fix=False)
|
2175
2225
|
if redirect_int and isinstance(self.MT._headers, int): # internal use
|
@@ -2183,7 +2233,7 @@ class ColumnHeaders(tk.Canvas):
|
|
2183
2233
|
return ""
|
2184
2234
|
return self.MT._headers[datacn]
|
2185
2235
|
|
2186
|
-
def get_valid_cell_data_as_str(self, datacn, fix=True) -> str:
|
2236
|
+
def get_valid_cell_data_as_str(self, datacn: int, fix: bool = True) -> str:
|
2187
2237
|
kwargs = self.get_cell_kwargs(datacn, key="dropdown")
|
2188
2238
|
if kwargs:
|
2189
2239
|
if kwargs["text"] is not None:
|
@@ -2204,7 +2254,7 @@ class ColumnHeaders(tk.Canvas):
|
|
2204
2254
|
value = get_n2a(datacn, self.default_header)
|
2205
2255
|
return value
|
2206
2256
|
|
2207
|
-
def get_value_for_empty_cell(self, datacn, c_ops=True):
|
2257
|
+
def get_value_for_empty_cell(self, datacn: int, c_ops: bool = True) -> object:
|
2208
2258
|
if self.get_cell_kwargs(datacn, key="checkbox", cell=c_ops):
|
2209
2259
|
return False
|
2210
2260
|
kwargs = self.get_cell_kwargs(datacn, key="dropdown", cell=c_ops)
|
@@ -2212,10 +2262,10 @@ class ColumnHeaders(tk.Canvas):
|
|
2212
2262
|
return kwargs["values"][0]
|
2213
2263
|
return ""
|
2214
2264
|
|
2215
|
-
def get_empty_header_seq(self, end, start=0, c_ops=True):
|
2265
|
+
def get_empty_header_seq(self, end: int, start: int = 0, c_ops: bool = True) -> list[object]:
|
2216
2266
|
return [self.get_value_for_empty_cell(datacn, c_ops=c_ops) for datacn in range(start, end)]
|
2217
2267
|
|
2218
|
-
def fix_header(self, datacn
|
2268
|
+
def fix_header(self, datacn: None | int = None) -> None:
|
2219
2269
|
if isinstance(self.MT._headers, int):
|
2220
2270
|
return
|
2221
2271
|
if isinstance(self.MT._headers, float):
|
@@ -2228,15 +2278,11 @@ class ColumnHeaders(tk.Canvas):
|
|
2228
2278
|
self.MT._headers = []
|
2229
2279
|
if isinstance(datacn, int) and datacn >= len(self.MT._headers):
|
2230
2280
|
self.MT._headers.extend(self.get_empty_header_seq(end=datacn + 1, start=len(self.MT._headers)))
|
2231
|
-
if fix_values:
|
2232
|
-
for cn, v in enumerate(islice(self.MT._headers, fix_values[0], fix_values[1])):
|
2233
|
-
if not self.input_valid_for_cell(cn, v):
|
2234
|
-
self.MT._headers[cn] = self.get_value_for_empty_cell(cn)
|
2235
2281
|
|
2236
2282
|
# displayed indexes
|
2237
|
-
def set_col_width_run_binding(self, c, width=None,
|
2283
|
+
def set_col_width_run_binding(self, c: int, width: int | None = None, only_if_too_small: bool = True) -> None:
|
2238
2284
|
old_width = self.MT.col_positions[c + 1] - self.MT.col_positions[c]
|
2239
|
-
new_width = self.set_col_width(c, width=width,
|
2285
|
+
new_width = self.set_col_width(c, width=width, only_if_too_small=only_if_too_small)
|
2240
2286
|
if self.column_width_resize_func is not None and old_width != new_width:
|
2241
2287
|
self.column_width_resize_func(
|
2242
2288
|
event_dict(
|
@@ -2247,7 +2293,7 @@ class ColumnHeaders(tk.Canvas):
|
|
2247
2293
|
)
|
2248
2294
|
|
2249
2295
|
# internal event use
|
2250
|
-
def click_checkbox(self, c, datacn=None, undo=True, redraw=True):
|
2296
|
+
def click_checkbox(self, c: int, datacn: int | None = None, undo: bool = True, redraw: bool = True) -> None:
|
2251
2297
|
if datacn is None:
|
2252
2298
|
datacn = c if self.MT.all_columns_displayed else self.MT.displayed_columns[c]
|
2253
2299
|
kwargs = self.get_cell_kwargs(datacn, key="checkbox")
|
@@ -2282,7 +2328,7 @@ class ColumnHeaders(tk.Canvas):
|
|
2282
2328
|
if redraw:
|
2283
2329
|
self.MT.refresh()
|
2284
2330
|
|
2285
|
-
def get_cell_kwargs(self, datacn, key="dropdown", cell=True):
|
2331
|
+
def get_cell_kwargs(self, datacn: int, key: Hashable = "dropdown", cell: bool = True) -> dict:
|
2286
2332
|
if cell and datacn in self.cell_options and key in self.cell_options[datacn]:
|
2287
2333
|
return self.cell_options[datacn][key]
|
2288
2334
|
return {}
|