tksheet 7.2.0__py3-none-any.whl → 7.2.2__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/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
- if len(self.MT.data) > self.MT._headers:
165
- maxlines = max(
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
- len(e.rstrip().split("\n")) if isinstance(e, str) else len(f"{e}".rstrip().split("\n"))
176
- for e in self.MT._headers
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()
@@ -903,12 +912,13 @@ class ColumnHeaders(tk.Canvas):
903
912
 
904
913
  def toggle_select_col(
905
914
  self,
906
- column,
907
- add_selection=True,
908
- redraw=True,
909
- run_binding_func=True,
910
- set_as_current=True,
911
- ):
915
+ column: int,
916
+ add_selection: bool = True,
917
+ redraw: bool = True,
918
+ run_binding_func: bool = True,
919
+ set_as_current: bool = True,
920
+ ext: bool = False,
921
+ ) -> int:
912
922
  if add_selection:
913
923
  if self.MT.col_selected(column):
914
924
  fill_iid = self.MT.deselect(c=column, redraw=redraw)
@@ -918,26 +928,40 @@ class ColumnHeaders(tk.Canvas):
918
928
  redraw=redraw,
919
929
  run_binding_func=run_binding_func,
920
930
  set_as_current=set_as_current,
931
+ ext=ext,
921
932
  )
922
933
  else:
923
934
  if self.MT.col_selected(column):
924
935
  fill_iid = self.MT.deselect(c=column, redraw=redraw)
925
936
  else:
926
- fill_iid = self.select_col(column, redraw=redraw)
937
+ fill_iid = self.select_col(column, redraw=redraw, ext=ext)
927
938
  return fill_iid
928
939
 
929
- def select_col(self, c, redraw=False, run_binding_func=True):
940
+ def select_col(
941
+ self,
942
+ c: int,
943
+ redraw: bool = False,
944
+ run_binding_func: bool = True,
945
+ ext: bool = False,
946
+ ) -> int:
930
947
  self.MT.deselect("all", redraw=False)
931
- fill_iid = self.MT.create_selection_box(0, c, len(self.MT.row_positions) - 1, c + 1, "columns")
948
+ fill_iid = self.MT.create_selection_box(0, c, len(self.MT.row_positions) - 1, c + 1, "columns", ext=ext)
932
949
  if redraw:
933
950
  self.MT.main_table_redraw_grid_and_text(redraw_header=True, redraw_row_index=True)
934
951
  if run_binding_func:
935
952
  self.MT.run_selection_binding("columns")
936
953
  return fill_iid
937
954
 
938
- def add_selection(self, c, redraw=False, run_binding_func=True, set_as_current=True):
955
+ def add_selection(
956
+ self,
957
+ c: int,
958
+ redraw: bool = False,
959
+ run_binding_func: bool = True,
960
+ set_as_current: bool = True,
961
+ ext: bool = False,
962
+ ) -> int:
939
963
  box = (0, c, len(self.MT.row_positions) - 1, c + 1, "columns")
940
- fill_iid = self.MT.create_selection_box(*box, set_current=set_as_current)
964
+ fill_iid = self.MT.create_selection_box(*box, set_current=set_as_current, ext=ext)
941
965
  if redraw:
942
966
  self.MT.main_table_redraw_grid_and_text(redraw_header=True, redraw_row_index=True)
943
967
  if run_binding_func:
@@ -982,7 +1006,7 @@ class ColumnHeaders(tk.Canvas):
982
1006
  self.hidd_boxes.add(item)
983
1007
  self.itemconfig(item, state="hidden")
984
1008
 
985
- def get_cell_dimensions(self, datacn):
1009
+ def get_cell_dimensions(self, datacn: int) -> tuple[int, int]:
986
1010
  txt = self.get_valid_cell_data_as_str(datacn, fix=False)
987
1011
  if txt:
988
1012
  self.MT.txt_measure_canvas.itemconfig(
@@ -1000,29 +1024,28 @@ class ColumnHeaders(tk.Canvas):
1000
1024
  return w + self.MT.header_txt_height, h
1001
1025
  return w, h
1002
1026
 
1003
- def set_height_of_header_to_text(self, text=None, only_increase=False):
1004
- if (
1005
- text is None
1006
- and not self.MT._headers
1007
- and isinstance(self.MT._headers, list)
1008
- or isinstance(self.MT._headers, int)
1009
- and self.MT._headers >= len(self.MT.data)
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)
1010
1035
  ):
1011
- return
1036
+ return h
1037
+ self.fix_header()
1012
1038
  qconf = self.MT.txt_measure_canvas.itemconfig
1013
1039
  qbbox = self.MT.txt_measure_canvas.bbox
1014
1040
  qtxtm = self.MT.txt_measure_canvas_text
1015
1041
  qfont = self.PAR.ops.header_font
1016
- new_height = self.MT.min_header_height
1017
1042
  default_header_height = self.MT.get_default_header_height()
1018
- self.fix_header()
1019
- if text is not None:
1020
- if text:
1021
- qconf(qtxtm, text=text, font=qfont)
1022
- b = qbbox(qtxtm)
1023
- if (h := b[3] - b[1] + 5) > new_height:
1024
- new_height = h
1025
- 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:
1026
1049
  if self.MT.all_columns_displayed:
1027
1050
  if isinstance(self.MT._headers, list):
1028
1051
  iterable = range(len(self.MT._headers))
@@ -1030,141 +1053,142 @@ class ColumnHeaders(tk.Canvas):
1030
1053
  iterable = range(len(self.MT.data[self.MT._headers]))
1031
1054
  else:
1032
1055
  iterable = self.MT.displayed_columns
1033
- if isinstance(self.MT._headers, list):
1034
- for datacn in iterable:
1035
- w_, h = self.get_cell_dimensions(datacn)
1036
- if h < self.MT.min_header_height:
1037
- h = int(self.MT.min_header_height)
1038
- elif h > self.MT.max_header_height:
1039
- h = int(self.MT.max_header_height)
1040
- if h > new_height:
1041
- 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
1042
1061
  elif isinstance(self.MT._headers, int):
1043
1062
  datarn = self.MT._headers
1044
1063
  for datacn in iterable:
1045
- txt = self.MT.get_valid_cell_data_as_str(datarn, datacn, get_displayed=True)
1046
- if txt:
1064
+ if txt := self.MT.get_valid_cell_data_as_str(datarn, datacn, get_displayed=True):
1047
1065
  qconf(qtxtm, text=txt, font=qfont)
1048
1066
  b = qbbox(qtxtm)
1049
- h = b[3] - b[1] + 5
1067
+ th = b[3] - b[1] + 5
1050
1068
  else:
1051
- h = default_header_height
1052
- if h < self.MT.min_header_height:
1053
- h = int(self.MT.min_header_height)
1054
- elif h > self.MT.max_header_height:
1055
- h = int(self.MT.max_header_height)
1056
- if h > new_height:
1057
- new_height = h
1069
+ th = default_header_height
1070
+ if th > h:
1071
+ h = th
1058
1072
  space_bot = self.MT.get_space_bot(0)
1059
- if new_height > space_bot and space_bot > self.MT.min_header_height:
1060
- new_height = space_bot
1061
- if not only_increase or (only_increase and new_height > self.current_height):
1062
- self.set_height(new_height, set_TL=True)
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)
1063
1081
  self.MT.main_table_redraw_grid_and_text(redraw_header=True, redraw_row_index=True)
1064
- return new_height
1082
+ return h
1065
1083
 
1066
- def set_col_width(
1084
+ def get_col_text_width(
1067
1085
  self,
1068
- col,
1069
- width=None,
1070
- only_set_if_too_small=False,
1071
- displayed_only=False,
1072
- recreate=True,
1073
- return_new_width=False,
1074
- ):
1075
- if col < 0:
1076
- return
1077
- qconf = self.MT.txt_measure_canvas.itemconfig
1078
- qbbox = self.MT.txt_measure_canvas.bbox
1079
- qtxtm = self.MT.txt_measure_canvas_text
1080
- qtxth = self.MT.table_txt_height
1081
- qfont = self.PAR.ops.table_font
1086
+ col: int,
1087
+ visible_only: bool = False,
1088
+ only_if_too_small: bool = False,
1089
+ ) -> int:
1082
1090
  self.fix_header()
1083
- if width is None:
1084
- w = self.MT.min_column_width
1085
- hw = self.MT.min_column_width
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:
1086
1097
  if self.MT.all_rows_displayed:
1087
- if displayed_only:
1088
- x1, y1, x2, y2 = self.MT.get_canvas_visible_area()
1089
- start_row, end_row = self.MT.get_visible_rows(y1, y2)
1098
+ if visible_only:
1099
+ iterable = range(*self.MT.visible_text_rows)
1090
1100
  else:
1091
- start_row, end_row = 0, len(self.MT.data)
1092
- iterable = range(start_row, end_row)
1101
+ iterable = range(0, len(self.MT.data))
1093
1102
  else:
1094
- if displayed_only:
1095
- x1, y1, x2, y2 = self.MT.get_canvas_visible_area()
1096
- 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
1097
1105
  else:
1098
1106
  start_row, end_row = 0, len(self.MT.displayed_rows)
1099
1107
  iterable = self.MT.displayed_rows[start_row:end_row]
1100
- datacn = col if self.MT.all_columns_displayed else self.MT.displayed_columns[col]
1101
- # header
1102
- hw, hh_ = self.get_cell_dimensions(datacn)
1103
- # table
1104
- if self.MT.data:
1105
- for datarn in iterable:
1106
- txt = self.MT.get_valid_cell_data_as_str(datarn, datacn, get_displayed=True)
1107
- if txt:
1108
- qconf(qtxtm, text=txt, font=qfont)
1109
- b = qbbox(qtxtm)
1110
- if self.MT.get_cell_kwargs(datarn, datacn, key="dropdown") or self.MT.get_cell_kwargs(
1111
- datarn, datacn, key="checkbox"
1112
- ):
1113
- tw = b[2] - b[0] + qtxth + 7
1114
- else:
1115
- tw = b[2] - b[0] + 7
1116
- if tw > w:
1117
- w = tw
1118
- if w > hw:
1119
- new_width = w
1120
- else:
1121
- new_width = hw
1122
- else:
1123
- new_width = int(width)
1124
- if new_width <= self.MT.min_column_width:
1125
- new_width = int(self.MT.min_column_width)
1126
- elif new_width > self.MT.max_column_width:
1127
- new_width = int(self.MT.max_column_width)
1128
- if only_set_if_too_small:
1129
- if new_width <= self.MT.col_positions[col + 1] - self.MT.col_positions[col]:
1130
- return self.MT.col_positions[col + 1] - self.MT.col_positions[col]
1131
- if not return_new_width:
1132
- new_col_pos = self.MT.col_positions[col] + new_width
1133
- increment = new_col_pos - self.MT.col_positions[col + 1]
1134
- self.MT.col_positions[col + 2 :] = [
1135
- e + increment for e in islice(self.MT.col_positions, col + 2, len(self.MT.col_positions))
1136
- ]
1137
- self.MT.col_positions[col + 1] = new_col_pos
1138
- if recreate:
1139
- self.MT.recreate_all_selection_boxes()
1140
- 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
1133
+
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
1141
1159
 
1142
- def set_width_of_all_cols(self, width=None, only_set_if_too_small=False, recreate=True):
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:
1143
1166
  if width is None:
1144
1167
  if self.MT.all_columns_displayed:
1145
1168
  iterable = range(self.MT.total_data_cols())
1146
1169
  else:
1147
1170
  iterable = range(len(self.MT.displayed_columns))
1148
1171
  self.MT.set_col_positions(
1149
- itr=(
1150
- self.set_col_width(
1151
- cn,
1152
- only_set_if_too_small=only_set_if_too_small,
1153
- recreate=False,
1154
- return_new_width=True,
1155
- )
1156
- for cn in iterable
1157
- )
1172
+ itr=(self.get_col_text_width(cn, only_if_too_small=only_if_too_small) for cn in iterable)
1158
1173
  )
1159
1174
  elif width is not None:
1160
1175
  if self.MT.all_columns_displayed:
1161
- self.MT.set_col_positions(itr=(width for cn in range(self.MT.total_data_cols())))
1176
+ self.MT.set_col_positions(itr=repeat(width, self.MT.total_data_cols()))
1162
1177
  else:
1163
- self.MT.set_col_positions(itr=(width for cn in range(len(self.MT.displayed_columns))))
1178
+ self.MT.set_col_positions(itr=repeat(width, len(self.MT.displayed_columns)))
1164
1179
  if recreate:
1165
1180
  self.MT.recreate_all_selection_boxes()
1166
1181
 
1167
- def redraw_highlight_get_text_fg(self, fc, sc, c, c_2, c_3, selections, datacn):
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]:
1168
1192
  redrawn = False
1169
1193
  kwargs = self.get_cell_kwargs(datacn, key="highlight")
1170
1194
  if kwargs:
@@ -1221,7 +1245,16 @@ class ColumnHeaders(tk.Canvas):
1221
1245
  tf = self.PAR.ops.header_fg
1222
1246
  return tf, redrawn
1223
1247
 
1224
- def redraw_highlight(self, x1, y1, x2, y2, fill, outline, tag):
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:
1225
1258
  coords = (x1, y1, x2, y2)
1226
1259
  if self.hidd_high:
1227
1260
  iid, showing = self.hidd_high.popitem()
@@ -1235,7 +1268,13 @@ class ColumnHeaders(tk.Canvas):
1235
1268
  self.disp_high[iid] = True
1236
1269
  return True
1237
1270
 
1238
- def redraw_gridline(self, points, fill, width, tag):
1271
+ def redraw_gridline(
1272
+ self,
1273
+ points: Sequence[float],
1274
+ fill: str,
1275
+ width: int,
1276
+ tag: str | tuple[str],
1277
+ ) -> None:
1239
1278
  if self.hidd_grid:
1240
1279
  t, sh = self.hidd_grid.popitem()
1241
1280
  self.coords(t, points)
@@ -1249,17 +1288,17 @@ class ColumnHeaders(tk.Canvas):
1249
1288
 
1250
1289
  def redraw_dropdown(
1251
1290
  self,
1252
- x1,
1253
- y1,
1254
- x2,
1255
- y2,
1256
- fill,
1257
- outline,
1258
- tag,
1259
- draw_outline=True,
1260
- draw_arrow=True,
1261
- dd_is_open=False,
1262
- ):
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:
1263
1302
  if draw_outline and self.PAR.ops.show_dropdown_borders:
1264
1303
  self.redraw_highlight(x1 + 1, y1 + 1, x2, y2, fill="", outline=self.PAR.ops.header_fg, tag=tag)
1265
1304
  if draw_arrow:
@@ -1303,7 +1342,17 @@ class ColumnHeaders(tk.Canvas):
1303
1342
  )
1304
1343
  self.disp_dropdown[t] = True
1305
1344
 
1306
- def redraw_checkbox(self, x1, y1, x2, y2, fill, outline, tag, draw_check=False):
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:
1307
1356
  points = rounded_box_coords(x1, y1, x2, y2)
1308
1357
  if self.hidd_checkbox:
1309
1358
  t, sh = self.hidd_checkbox.popitem()
@@ -1347,18 +1396,20 @@ class ColumnHeaders(tk.Canvas):
1347
1396
 
1348
1397
  def redraw_grid_and_text(
1349
1398
  self,
1350
- last_col_line_pos,
1351
- scrollpos_left,
1352
- x_stop,
1353
- start_col,
1354
- end_col,
1355
- scrollpos_right,
1356
- col_pos_exists,
1357
- ):
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:
1358
1409
  try:
1359
1410
  self.configure_scrollregion(last_col_line_pos=last_col_line_pos)
1360
1411
  except Exception:
1361
- return
1412
+ return False
1362
1413
  self.hidd_text.update(self.disp_text)
1363
1414
  self.disp_text = {}
1364
1415
  self.hidd_high.update(self.disp_high)
@@ -1376,7 +1427,7 @@ class ColumnHeaders(tk.Canvas):
1376
1427
  x_stop,
1377
1428
  self.current_height,
1378
1429
  )
1379
- draw_x = self.MT.col_positions[start_col]
1430
+ draw_x = self.MT.col_positions[grid_start_col]
1380
1431
  yend = self.current_height - 5
1381
1432
  if (self.PAR.ops.show_vertical_grid or self.width_resizing_enabled) and col_pos_exists:
1382
1433
  points = [
@@ -1387,7 +1438,7 @@ class ColumnHeaders(tk.Canvas):
1387
1438
  scrollpos_left - 1,
1388
1439
  -1,
1389
1440
  ]
1390
- for c in range(start_col + 1, end_col):
1441
+ for c in range(grid_start_col, grid_end_col):
1391
1442
  draw_x = self.MT.col_positions[c]
1392
1443
  if self.width_resizing_enabled:
1393
1444
  self.visible_col_dividers[c] = (draw_x - 2, 1, draw_x + 2, yend)
@@ -1416,9 +1467,9 @@ class ColumnHeaders(tk.Canvas):
1416
1467
  else color_map[self.PAR.ops.header_selected_columns_bg]
1417
1468
  )
1418
1469
  font = self.PAR.ops.header_font
1419
- selections = self.get_redraw_selections(start_col, end_col)
1470
+ selections = self.get_redraw_selections(text_start_col, grid_end_col)
1420
1471
  dd_coords = self.dropdown.get_coords()
1421
- for c in range(start_col, end_col - 1):
1472
+ for c in range(text_start_col, text_end_col):
1422
1473
  draw_y = self.MT.header_first_ln_ins
1423
1474
  cleftgridln = self.MT.col_positions[c]
1424
1475
  crightgridln = self.MT.col_positions[c + 1]
@@ -1614,7 +1665,7 @@ class ColumnHeaders(tk.Canvas):
1614
1665
  d[box.type_ if box.type_ != "rows" else "cells"].add(c)
1615
1666
  return d
1616
1667
 
1617
- 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:
1618
1669
  if not self.MT.anything_selected() or (not ignore_existing_editor and self.text_editor.open):
1619
1670
  return
1620
1671
  if not self.MT.selected:
@@ -1754,14 +1805,19 @@ class ColumnHeaders(tk.Canvas):
1754
1805
  self.text_editor.tktext.bind(key, func)
1755
1806
  return True
1756
1807
 
1757
- # displayed indexes #just here to receive text editor arg
1758
- def text_editor_has_wrapped(self, r=0, c=0, check_lines=None):
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:
1759
1815
  if self.width_resizing_enabled:
1760
1816
  curr_width = self.text_editor.window.winfo_width()
1761
1817
  new_width = curr_width + (self.MT.header_txt_height * 2)
1762
1818
  if new_width != curr_width:
1763
1819
  self.text_editor.window.config(width=new_width)
1764
- self.set_col_width_run_binding(c, width=new_width, only_set_if_too_small=False)
1820
+ self.set_col_width_run_binding(c, width=new_width, only_if_too_small=False)
1765
1821
  if self.dropdown.open and self.dropdown.get_coords() == c:
1766
1822
  self.itemconfig(self.dropdown.canvas_id, width=new_width)
1767
1823
  self.dropdown.window.update_idletasks()
@@ -1770,7 +1826,7 @@ class ColumnHeaders(tk.Canvas):
1770
1826
  self.coords(self.text_editor.canvas_id, self.MT.col_positions[c] + 1, 0)
1771
1827
 
1772
1828
  # displayed indexes
1773
- 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:
1774
1830
  if not self.height_resizing_enabled:
1775
1831
  return
1776
1832
  curr_height = self.text_editor.window.winfo_height()
@@ -1801,7 +1857,7 @@ class ColumnHeaders(tk.Canvas):
1801
1857
  )
1802
1858
  self.itemconfig(self.dropdown.canvas_id, anchor=anchor, height=win_h)
1803
1859
 
1804
- def refresh_open_window_positions(self, zoom: Literal["in", "out"]):
1860
+ def refresh_open_window_positions(self, zoom: Literal["in", "out"]) -> None:
1805
1861
  if self.text_editor.open:
1806
1862
  c = self.text_editor.column
1807
1863
  self.text_editor.window.config(
@@ -1907,7 +1963,11 @@ class ColumnHeaders(tk.Canvas):
1907
1963
  self.focus_set()
1908
1964
  return "break"
1909
1965
 
1910
- def get_dropdown_height_anchor(self, c, text_editor_h=None):
1966
+ def get_dropdown_height_anchor(
1967
+ self,
1968
+ c: int,
1969
+ text_editor_h: None | int = None,
1970
+ ) -> tuple[int, Literal["nw"]]:
1911
1971
  win_h = 5
1912
1972
  datacn = self.MT.datacn(c)
1913
1973
  for i, v in enumerate(self.get_cell_kwargs(datacn, key="dropdown")["values"]):
@@ -1942,7 +2002,7 @@ class ColumnHeaders(tk.Canvas):
1942
2002
  modified_func(event)
1943
2003
  dd_window.search_and_see(event)
1944
2004
 
1945
- def open_dropdown_window(self, c, event: object = None):
2005
+ def open_dropdown_window(self, c: int, event: object = None) -> None:
1946
2006
  self.hide_text_editor("Escape")
1947
2007
  kwargs = self.get_cell_kwargs(self.MT.datacn(c), key="dropdown")
1948
2008
  if kwargs["state"] == "normal":
@@ -2015,7 +2075,12 @@ class ColumnHeaders(tk.Canvas):
2015
2075
  if redraw:
2016
2076
  self.MT.main_table_redraw_grid_and_text(redraw_header=True, redraw_row_index=False, redraw_table=False)
2017
2077
 
2018
- def close_dropdown_window(self, c=None, selection=None, redraw=True):
2078
+ def close_dropdown_window(
2079
+ self,
2080
+ c: None | int = None,
2081
+ selection: object = None,
2082
+ redraw: bool = True,
2083
+ ) -> None:
2019
2084
  if c is not None and selection is not None:
2020
2085
  datacn = c if self.MT.all_columns_displayed else self.MT.displayed_columns[c]
2021
2086
  kwargs = self.get_cell_kwargs(datacn, key="dropdown")
@@ -2053,7 +2118,7 @@ class ColumnHeaders(tk.Canvas):
2053
2118
  if redraw:
2054
2119
  self.MT.refresh()
2055
2120
 
2056
- def mouseclick_outside_editor_or_dropdown(self, inside: bool = False):
2121
+ def mouseclick_outside_editor_or_dropdown(self, inside: bool = False) -> int | None:
2057
2122
  closed_dd_coords = self.dropdown.get_coords()
2058
2123
  if self.text_editor.open:
2059
2124
  self.close_text_editor(new_tk_event("ButtonPress-1"))
@@ -2067,7 +2132,7 @@ class ColumnHeaders(tk.Canvas):
2067
2132
  )
2068
2133
  return closed_dd_coords
2069
2134
 
2070
- 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:
2071
2136
  self.RI.mouseclick_outside_editor_or_dropdown()
2072
2137
  self.MT.mouseclick_outside_editor_or_dropdown()
2073
2138
  return self.mouseclick_outside_editor_or_dropdown(inside)
@@ -2081,14 +2146,14 @@ class ColumnHeaders(tk.Canvas):
2081
2146
  # internal event use
2082
2147
  def set_cell_data_undo(
2083
2148
  self,
2084
- c=0,
2085
- datacn=None,
2086
- value="",
2087
- cell_resize=True,
2088
- undo=True,
2089
- redraw=True,
2090
- check_input_valid=True,
2091
- ):
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:
2092
2157
  if datacn is None:
2093
2158
  datacn = c if self.MT.all_columns_displayed else self.MT.displayed_columns[c]
2094
2159
  event_data = event_dict(
@@ -2119,7 +2184,7 @@ class ColumnHeaders(tk.Canvas):
2119
2184
  self.MT.sheet_modified(event_data)
2120
2185
  return edited
2121
2186
 
2122
- def set_cell_data(self, datacn=None, value=""):
2187
+ def set_cell_data(self, datacn: int | None = None, value: object = "") -> None:
2123
2188
  if isinstance(self.MT._headers, int):
2124
2189
  self.MT.set_cell_data(datarn=self.MT._headers, datacn=datacn, value=value)
2125
2190
  else:
@@ -2141,7 +2206,7 @@ class ColumnHeaders(tk.Canvas):
2141
2206
  return False
2142
2207
  return True
2143
2208
 
2144
- def cell_equal_to(self, datacn, value):
2209
+ def cell_equal_to(self, datacn: int, value: object) -> bool:
2145
2210
  self.fix_header(datacn)
2146
2211
  if isinstance(self.MT._headers, list):
2147
2212
  return self.MT._headers[datacn] == value
@@ -2150,11 +2215,11 @@ class ColumnHeaders(tk.Canvas):
2150
2215
 
2151
2216
  def get_cell_data(
2152
2217
  self,
2153
- datacn,
2154
- get_displayed=False,
2155
- none_to_empty_str=False,
2156
- redirect_int=False,
2157
- ):
2218
+ datacn: int,
2219
+ get_displayed: bool = False,
2220
+ none_to_empty_str: bool = False,
2221
+ redirect_int: bool = False,
2222
+ ) -> object:
2158
2223
  if get_displayed:
2159
2224
  return self.get_valid_cell_data_as_str(datacn, fix=False)
2160
2225
  if redirect_int and isinstance(self.MT._headers, int): # internal use
@@ -2168,7 +2233,7 @@ class ColumnHeaders(tk.Canvas):
2168
2233
  return ""
2169
2234
  return self.MT._headers[datacn]
2170
2235
 
2171
- 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:
2172
2237
  kwargs = self.get_cell_kwargs(datacn, key="dropdown")
2173
2238
  if kwargs:
2174
2239
  if kwargs["text"] is not None:
@@ -2189,7 +2254,7 @@ class ColumnHeaders(tk.Canvas):
2189
2254
  value = get_n2a(datacn, self.default_header)
2190
2255
  return value
2191
2256
 
2192
- 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:
2193
2258
  if self.get_cell_kwargs(datacn, key="checkbox", cell=c_ops):
2194
2259
  return False
2195
2260
  kwargs = self.get_cell_kwargs(datacn, key="dropdown", cell=c_ops)
@@ -2197,10 +2262,10 @@ class ColumnHeaders(tk.Canvas):
2197
2262
  return kwargs["values"][0]
2198
2263
  return ""
2199
2264
 
2200
- 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]:
2201
2266
  return [self.get_value_for_empty_cell(datacn, c_ops=c_ops) for datacn in range(start, end)]
2202
2267
 
2203
- def fix_header(self, datacn=None, fix_values=tuple()):
2268
+ def fix_header(self, datacn: None | int = None) -> None:
2204
2269
  if isinstance(self.MT._headers, int):
2205
2270
  return
2206
2271
  if isinstance(self.MT._headers, float):
@@ -2213,15 +2278,11 @@ class ColumnHeaders(tk.Canvas):
2213
2278
  self.MT._headers = []
2214
2279
  if isinstance(datacn, int) and datacn >= len(self.MT._headers):
2215
2280
  self.MT._headers.extend(self.get_empty_header_seq(end=datacn + 1, start=len(self.MT._headers)))
2216
- if fix_values:
2217
- for cn, v in enumerate(islice(self.MT._headers, fix_values[0], fix_values[1])):
2218
- if not self.input_valid_for_cell(cn, v):
2219
- self.MT._headers[cn] = self.get_value_for_empty_cell(cn)
2220
2281
 
2221
2282
  # displayed indexes
2222
- def set_col_width_run_binding(self, c, width=None, only_set_if_too_small=True):
2283
+ def set_col_width_run_binding(self, c: int, width: int | None = None, only_if_too_small: bool = True) -> None:
2223
2284
  old_width = self.MT.col_positions[c + 1] - self.MT.col_positions[c]
2224
- new_width = self.set_col_width(c, width=width, only_set_if_too_small=only_set_if_too_small)
2285
+ new_width = self.set_col_width(c, width=width, only_if_too_small=only_if_too_small)
2225
2286
  if self.column_width_resize_func is not None and old_width != new_width:
2226
2287
  self.column_width_resize_func(
2227
2288
  event_dict(
@@ -2232,7 +2293,7 @@ class ColumnHeaders(tk.Canvas):
2232
2293
  )
2233
2294
 
2234
2295
  # internal event use
2235
- 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:
2236
2297
  if datacn is None:
2237
2298
  datacn = c if self.MT.all_columns_displayed else self.MT.displayed_columns[c]
2238
2299
  kwargs = self.get_cell_kwargs(datacn, key="checkbox")
@@ -2267,7 +2328,7 @@ class ColumnHeaders(tk.Canvas):
2267
2328
  if redraw:
2268
2329
  self.MT.refresh()
2269
2330
 
2270
- 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:
2271
2332
  if cell and datacn in self.cell_options and key in self.cell_options[datacn]:
2272
2333
  return self.cell_options[datacn][key]
2273
2334
  return {}