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/main_table.py CHANGED
@@ -49,18 +49,19 @@ from .formatters import (
49
49
  try_to_bool,
50
50
  )
51
51
  from .functions import (
52
- consecutive_chunks,
52
+ consecutive_ranges,
53
53
  decompress_load,
54
54
  diff_gen,
55
55
  diff_list,
56
56
  ev_stack_dict,
57
57
  event_dict,
58
58
  gen_formatted,
59
- get_checkbox_points,
59
+ rounded_box_coords,
60
60
  get_new_indexes,
61
61
  get_seq_without_gaps_at_index,
62
62
  index_exists,
63
63
  insert_items,
64
+ int_x_iter,
64
65
  is_iterable,
65
66
  is_type_int,
66
67
  len_to_idx,
@@ -960,12 +961,12 @@ class MainTable(tk.Canvas):
960
961
  )
961
962
  )
962
963
  if create_selections:
963
- for chunk in consecutive_chunks(sorted(disp_new_idxs.values())):
964
+ for boxst, boxend in consecutive_ranges(sorted(disp_new_idxs.values())):
964
965
  self.create_selection_box(
965
966
  0,
966
- chunk[0],
967
+ boxst,
967
968
  len(self.row_positions) - 1,
968
- chunk[-1] + 1,
969
+ boxend,
969
970
  "columns",
970
971
  run_binding=True,
971
972
  )
@@ -998,101 +999,104 @@ class MainTable(tk.Canvas):
998
999
  tags: {full_new_idxs[k] for k in tagged} for tags, tagged in self.tagged_columns.items()
999
1000
  }
1000
1001
  self.CH.cell_options = {full_new_idxs[k]: v for k, v in self.CH.cell_options.items()}
1001
- totalrows = self.total_data_rows()
1002
- new_ops = self.PAR.create_options_from_span
1003
- qkspan = self.span()
1004
- for span in self.named_spans.values():
1005
- # span is neither a cell options nor col options span, continue
1006
- if not isinstance(span["from_c"], int):
1007
- continue
1008
- oldupto_colrange, newupto_colrange, newfrom, newupto = span_idxs_post_move(
1009
- data_new_idxs,
1010
- full_new_idxs,
1011
- totalcols,
1012
- span,
1013
- "c",
1014
- )
1015
- # add cell/col kwargs for columns that are new to the span
1016
- old_span_idxs = set(full_new_idxs[k] for k in range(span["from_c"], oldupto_colrange))
1017
- for k in range(newfrom, newupto_colrange):
1018
- if k not in old_span_idxs:
1019
- oldidx = full_old_idxs[k]
1020
- # event_data is used to preserve old cell value
1021
- # in case cells are modified by
1022
- # formatting, checkboxes, dropdown boxes
1023
- if (
1024
- span["type_"] in val_modifying_options
1025
- and span["header"]
1026
- and oldidx not in event_data["cells"]["header"]
1027
- ):
1028
- event_data["cells"]["header"][oldidx] = self.CH.get_cell_data(k)
1029
- # the span targets columns
1030
- if span["from_r"] is None:
1031
- if span["type_"] in val_modifying_options:
1032
- for datarn in range(len(self.data)):
1033
- if (datarn, oldidx) not in event_data["cells"]["table"]:
1034
- event_data["cells"]["table"][(datarn, oldidx)] = self.get_cell_data(datarn, k)
1035
- # create new col options
1036
- new_ops(
1037
- mod_span(
1038
- qkspan,
1039
- span,
1040
- from_c=k,
1041
- upto_c=k + 1,
1042
- )
1043
- )
1044
- # the span targets cells
1045
- else:
1046
- rng_upto_r = totalrows if span["upto_r"] is None else span["upto_r"]
1047
- for datarn in range(span["from_r"], rng_upto_r):
1048
- if (
1049
- span["type_"] in val_modifying_options
1050
- and (datarn, oldidx) not in event_data["cells"]["table"]
1051
- ):
1052
- event_data["cells"]["table"][(datarn, oldidx)] = self.get_cell_data(datarn, k)
1053
- # create new cell options
1002
+ if self.named_spans:
1003
+ totalrows = self.total_data_rows()
1004
+ new_ops = self.PAR.create_options_from_span
1005
+ qkspan = self.span()
1006
+ for span in self.named_spans.values():
1007
+ # span is neither a cell options nor col options span, continue
1008
+ if not isinstance(span["from_c"], int):
1009
+ continue
1010
+ oldupto_colrange, newupto_colrange, newfrom, newupto = span_idxs_post_move(
1011
+ data_new_idxs,
1012
+ full_new_idxs,
1013
+ totalcols,
1014
+ span,
1015
+ "c",
1016
+ )
1017
+ # add cell/col kwargs for columns that are new to the span
1018
+ old_span_idxs = set(full_new_idxs[k] for k in range(span["from_c"], oldupto_colrange))
1019
+ for k in range(newfrom, newupto_colrange):
1020
+ if k not in old_span_idxs:
1021
+ oldidx = full_old_idxs[k]
1022
+ # event_data is used to preserve old cell value
1023
+ # in case cells are modified by
1024
+ # formatting, checkboxes, dropdown boxes
1025
+ if (
1026
+ span["type_"] in val_modifying_options
1027
+ and span["header"]
1028
+ and oldidx not in event_data["cells"]["header"]
1029
+ ):
1030
+ event_data["cells"]["header"][oldidx] = self.CH.get_cell_data(k)
1031
+ # the span targets columns
1032
+ if span["from_r"] is None:
1033
+ if span["type_"] in val_modifying_options:
1034
+ for datarn in range(len(self.data)):
1035
+ if (datarn, oldidx) not in event_data["cells"]["table"]:
1036
+ event_data["cells"]["table"][(datarn, oldidx)] = self.get_cell_data(
1037
+ datarn, k
1038
+ )
1039
+ # create new col options
1054
1040
  new_ops(
1055
1041
  mod_span(
1056
1042
  qkspan,
1057
1043
  span,
1058
- from_r=datarn,
1059
- upto_r=datarn + 1,
1060
1044
  from_c=k,
1061
1045
  upto_c=k + 1,
1062
1046
  )
1063
1047
  )
1064
- # remove span specific kwargs from cells/columns
1065
- # that are no longer in the span,
1066
- # cell options/col options keys are new idxs
1067
- for k in range(span["from_c"], oldupto_colrange):
1068
- # has it moved outside of new span coords
1069
- if (isinstance(newupto, int) and (full_new_idxs[k] < newfrom or full_new_idxs[k] >= newupto)) or (
1070
- newupto is None and full_new_idxs[k] < newfrom
1071
- ):
1072
- # span includes header
1048
+ # the span targets cells
1049
+ else:
1050
+ rng_upto_r = totalrows if span["upto_r"] is None else span["upto_r"]
1051
+ for datarn in range(span["from_r"], rng_upto_r):
1052
+ if (
1053
+ span["type_"] in val_modifying_options
1054
+ and (datarn, oldidx) not in event_data["cells"]["table"]
1055
+ ):
1056
+ event_data["cells"]["table"][(datarn, oldidx)] = self.get_cell_data(datarn, k)
1057
+ # create new cell options
1058
+ new_ops(
1059
+ mod_span(
1060
+ qkspan,
1061
+ span,
1062
+ from_r=datarn,
1063
+ upto_r=datarn + 1,
1064
+ from_c=k,
1065
+ upto_c=k + 1,
1066
+ )
1067
+ )
1068
+ # remove span specific kwargs from cells/columns
1069
+ # that are no longer in the span,
1070
+ # cell options/col options keys are new idxs
1071
+ for k in range(span["from_c"], oldupto_colrange):
1072
+ # has it moved outside of new span coords
1073
1073
  if (
1074
- span["header"]
1075
- and full_new_idxs[k] in self.CH.cell_options
1076
- and span["type_"] in self.CH.cell_options[full_new_idxs[k]]
1077
- ):
1078
- del self.CH.cell_options[full_new_idxs[k]][span["type_"]]
1079
- # span is for col options
1080
- if span["from_r"] is None:
1074
+ isinstance(newupto, int) and (full_new_idxs[k] < newfrom or full_new_idxs[k] >= newupto)
1075
+ ) or (newupto is None and full_new_idxs[k] < newfrom):
1076
+ # span includes header
1081
1077
  if (
1082
- full_new_idxs[k] in self.col_options
1083
- and span["type_"] in self.col_options[full_new_idxs[k]]
1078
+ span["header"]
1079
+ and full_new_idxs[k] in self.CH.cell_options
1080
+ and span["type_"] in self.CH.cell_options[full_new_idxs[k]]
1084
1081
  ):
1085
- del self.col_options[full_new_idxs[k]][span["type_"]]
1086
- # span is for cell options
1087
- else:
1088
- rng_upto_r = totalrows if span["upto_r"] is None else span["upto_r"]
1089
- for r in range(span["from_r"], rng_upto_r):
1090
- if (r, full_new_idxs[k]) in self.cell_options and span["type_"] in self.cell_options[
1091
- (r, full_new_idxs[k])
1092
- ]:
1093
- del self.cell_options[(r, full_new_idxs[k])][span["type_"]]
1094
- # finally, change the span coords
1095
- span["from_c"], span["upto_c"] = newfrom, newupto
1082
+ del self.CH.cell_options[full_new_idxs[k]][span["type_"]]
1083
+ # span is for col options
1084
+ if span["from_r"] is None:
1085
+ if (
1086
+ full_new_idxs[k] in self.col_options
1087
+ and span["type_"] in self.col_options[full_new_idxs[k]]
1088
+ ):
1089
+ del self.col_options[full_new_idxs[k]][span["type_"]]
1090
+ # span is for cell options
1091
+ else:
1092
+ rng_upto_r = totalrows if span["upto_r"] is None else span["upto_r"]
1093
+ for r in range(span["from_r"], rng_upto_r):
1094
+ if (r, full_new_idxs[k]) in self.cell_options and span[
1095
+ "type_"
1096
+ ] in self.cell_options[(r, full_new_idxs[k])]:
1097
+ del self.cell_options[(r, full_new_idxs[k])][span["type_"]]
1098
+ # finally, change the span coords
1099
+ span["from_c"], span["upto_c"] = newfrom, newupto
1096
1100
  if data_indexes:
1097
1101
  self.displayed_columns = sorted(full_new_idxs[k] for k in self.displayed_columns)
1098
1102
  return data_new_idxs, disp_new_idxs, event_data
@@ -1181,11 +1185,11 @@ class MainTable(tk.Canvas):
1181
1185
  )
1182
1186
  )
1183
1187
  if create_selections:
1184
- for chunk in consecutive_chunks(sorted(disp_new_idxs.values())):
1188
+ for boxst, boxend in consecutive_ranges(sorted(disp_new_idxs.values())):
1185
1189
  self.create_selection_box(
1186
- chunk[0],
1190
+ boxst,
1187
1191
  0,
1188
- chunk[-1] + 1,
1192
+ boxend,
1189
1193
  len(self.col_positions) - 1,
1190
1194
  "rows",
1191
1195
  run_binding=True,
@@ -1215,101 +1219,104 @@ class MainTable(tk.Canvas):
1215
1219
  self.row_options = {full_new_idxs[k]: v for k, v in self.row_options.items()}
1216
1220
  self.RI.cell_options = {full_new_idxs[k]: v for k, v in self.RI.cell_options.items()}
1217
1221
  self.RI.tree_rns = {v: full_new_idxs[k] for v, k in self.RI.tree_rns.items()}
1218
- totalcols = self.total_data_cols()
1219
- new_ops = self.PAR.create_options_from_span
1220
- qkspan = self.span()
1221
- for span in self.named_spans.values():
1222
- # span is neither a cell options nor row options span, continue
1223
- if not isinstance(span["from_r"], int):
1224
- continue
1225
- oldupto_rowrange, newupto_rowrange, newfrom, newupto = span_idxs_post_move(
1226
- data_new_idxs,
1227
- full_new_idxs,
1228
- totalrows,
1229
- span,
1230
- "r",
1231
- )
1232
- # add cell/row kwargs for rows that are new to the span
1233
- old_span_idxs = set(full_new_idxs[k] for k in range(span["from_r"], oldupto_rowrange))
1234
- for k in range(newfrom, newupto_rowrange):
1235
- if k not in old_span_idxs:
1236
- oldidx = full_old_idxs[k]
1237
- # event_data is used to preserve old cell value
1238
- # in case cells are modified by
1239
- # formatting, checkboxes, dropdown boxes
1240
- if (
1241
- span["type_"] in val_modifying_options
1242
- and span["index"]
1243
- and oldidx not in event_data["cells"]["index"]
1244
- ):
1245
- event_data["cells"]["index"][oldidx] = self.RI.get_cell_data(k)
1246
- # the span targets rows
1247
- if span["from_c"] is None:
1248
- if span["type_"] in val_modifying_options:
1249
- for datacn in range(len(self.data[k])):
1250
- if (oldidx, datacn) not in event_data["cells"]["table"]:
1251
- event_data["cells"]["table"][(oldidx, datacn)] = self.get_cell_data(k, datacn)
1252
- # create new row options
1253
- new_ops(
1254
- mod_span(
1255
- qkspan,
1256
- span,
1257
- from_r=k,
1258
- upto_r=k + 1,
1259
- )
1260
- )
1261
- # the span targets cells
1262
- else:
1263
- rng_upto_c = totalcols if span["upto_c"] is None else span["upto_c"]
1264
- for datacn in range(span["from_c"], rng_upto_c):
1265
- if (
1266
- span["type_"] in val_modifying_options
1267
- and (oldidx, datacn) not in event_data["cells"]["table"]
1268
- ):
1269
- event_data["cells"]["table"][(oldidx, datacn)] = self.get_cell_data(k, datacn)
1270
- # create new cell options
1222
+ if self.named_spans:
1223
+ totalcols = self.total_data_cols()
1224
+ new_ops = self.PAR.create_options_from_span
1225
+ qkspan = self.span()
1226
+ for span in self.named_spans.values():
1227
+ # span is neither a cell options nor row options span, continue
1228
+ if not isinstance(span["from_r"], int):
1229
+ continue
1230
+ oldupto_rowrange, newupto_rowrange, newfrom, newupto = span_idxs_post_move(
1231
+ data_new_idxs,
1232
+ full_new_idxs,
1233
+ totalrows,
1234
+ span,
1235
+ "r",
1236
+ )
1237
+ # add cell/row kwargs for rows that are new to the span
1238
+ old_span_idxs = set(full_new_idxs[k] for k in range(span["from_r"], oldupto_rowrange))
1239
+ for k in range(newfrom, newupto_rowrange):
1240
+ if k not in old_span_idxs:
1241
+ oldidx = full_old_idxs[k]
1242
+ # event_data is used to preserve old cell value
1243
+ # in case cells are modified by
1244
+ # formatting, checkboxes, dropdown boxes
1245
+ if (
1246
+ span["type_"] in val_modifying_options
1247
+ and span["index"]
1248
+ and oldidx not in event_data["cells"]["index"]
1249
+ ):
1250
+ event_data["cells"]["index"][oldidx] = self.RI.get_cell_data(k)
1251
+ # the span targets rows
1252
+ if span["from_c"] is None:
1253
+ if span["type_"] in val_modifying_options:
1254
+ for datacn in range(len(self.data[k])):
1255
+ if (oldidx, datacn) not in event_data["cells"]["table"]:
1256
+ event_data["cells"]["table"][(oldidx, datacn)] = self.get_cell_data(
1257
+ k, datacn
1258
+ )
1259
+ # create new row options
1271
1260
  new_ops(
1272
1261
  mod_span(
1273
1262
  qkspan,
1274
1263
  span,
1275
1264
  from_r=k,
1276
1265
  upto_r=k + 1,
1277
- from_c=datacn,
1278
- upto_c=datacn + 1,
1279
1266
  )
1280
1267
  )
1281
- # remove span specific kwargs from cells/rows
1282
- # that are no longer in the span,
1283
- # cell options/row options keys are new idxs
1284
- for k in range(span["from_r"], oldupto_rowrange):
1285
- # has it moved outside of new span coords
1286
- if (isinstance(newupto, int) and (full_new_idxs[k] < newfrom or full_new_idxs[k] >= newupto)) or (
1287
- newupto is None and full_new_idxs[k] < newfrom
1288
- ):
1289
- # span includes index
1268
+ # the span targets cells
1269
+ else:
1270
+ rng_upto_c = totalcols if span["upto_c"] is None else span["upto_c"]
1271
+ for datacn in range(span["from_c"], rng_upto_c):
1272
+ if (
1273
+ span["type_"] in val_modifying_options
1274
+ and (oldidx, datacn) not in event_data["cells"]["table"]
1275
+ ):
1276
+ event_data["cells"]["table"][(oldidx, datacn)] = self.get_cell_data(k, datacn)
1277
+ # create new cell options
1278
+ new_ops(
1279
+ mod_span(
1280
+ qkspan,
1281
+ span,
1282
+ from_r=k,
1283
+ upto_r=k + 1,
1284
+ from_c=datacn,
1285
+ upto_c=datacn + 1,
1286
+ )
1287
+ )
1288
+ # remove span specific kwargs from cells/rows
1289
+ # that are no longer in the span,
1290
+ # cell options/row options keys are new idxs
1291
+ for k in range(span["from_r"], oldupto_rowrange):
1292
+ # has it moved outside of new span coords
1290
1293
  if (
1291
- span["index"]
1292
- and full_new_idxs[k] in self.RI.cell_options
1293
- and span["type_"] in self.RI.cell_options[full_new_idxs[k]]
1294
- ):
1295
- del self.RI.cell_options[full_new_idxs[k]][span["type_"]]
1296
- # span is for row options
1297
- if span["from_c"] is None:
1294
+ isinstance(newupto, int) and (full_new_idxs[k] < newfrom or full_new_idxs[k] >= newupto)
1295
+ ) or (newupto is None and full_new_idxs[k] < newfrom):
1296
+ # span includes index
1298
1297
  if (
1299
- full_new_idxs[k] in self.row_options
1300
- and span["type_"] in self.row_options[full_new_idxs[k]]
1298
+ span["index"]
1299
+ and full_new_idxs[k] in self.RI.cell_options
1300
+ and span["type_"] in self.RI.cell_options[full_new_idxs[k]]
1301
1301
  ):
1302
- del self.row_options[full_new_idxs[k]][span["type_"]]
1303
- # span is for cell options
1304
- else:
1305
- rng_upto_c = totalcols if span["upto_c"] is None else span["upto_c"]
1306
- for c in range(span["from_c"], rng_upto_c):
1307
- if (full_new_idxs[k], c) in self.cell_options and span["type_"] in self.cell_options[
1308
- (full_new_idxs[k], c)
1309
- ]:
1310
- del self.cell_options[(full_new_idxs[k], c)][span["type_"]]
1311
- # finally, change the span coords
1312
- span["from_r"], span["upto_r"] = newfrom, newupto
1302
+ del self.RI.cell_options[full_new_idxs[k]][span["type_"]]
1303
+ # span is for row options
1304
+ if span["from_c"] is None:
1305
+ if (
1306
+ full_new_idxs[k] in self.row_options
1307
+ and span["type_"] in self.row_options[full_new_idxs[k]]
1308
+ ):
1309
+ del self.row_options[full_new_idxs[k]][span["type_"]]
1310
+ # span is for cell options
1311
+ else:
1312
+ rng_upto_c = totalcols if span["upto_c"] is None else span["upto_c"]
1313
+ for c in range(span["from_c"], rng_upto_c):
1314
+ if (full_new_idxs[k], c) in self.cell_options and span[
1315
+ "type_"
1316
+ ] in self.cell_options[(full_new_idxs[k], c)]:
1317
+ del self.cell_options[(full_new_idxs[k], c)][span["type_"]]
1318
+ # finally, change the span coords
1319
+ span["from_r"], span["upto_r"] = newfrom, newupto
1313
1320
  if data_indexes:
1314
1321
  self.displayed_rows = sorted(full_new_idxs[k] for k in self.displayed_rows)
1315
1322
  return data_new_idxs, disp_new_idxs, event_data
@@ -1846,7 +1853,6 @@ class MainTable(tk.Canvas):
1846
1853
  "rows",
1847
1854
  set_current=resel and to_sel >= r + 1 and to_sel < r2,
1848
1855
  )
1849
- break
1850
1856
  elif isinstance(c, int) and r is None and cell is None:
1851
1857
  for item, box in self.get_selection_items(rows=False, cells=False):
1852
1858
  r1, c1, r2, c2 = box.coords
@@ -1890,7 +1896,6 @@ class MainTable(tk.Canvas):
1890
1896
  "columns",
1891
1897
  set_current=resel and to_sel >= c + 1 and to_sel < c2,
1892
1898
  )
1893
- break
1894
1899
  elif (isinstance(r, int) and isinstance(c, int) and cell is None) or cell is not None:
1895
1900
  if cell is not None:
1896
1901
  r, c = cell[0], cell[1]
@@ -1898,7 +1903,6 @@ class MainTable(tk.Canvas):
1898
1903
  r1, c1, r2, c2 = box.coords
1899
1904
  if r >= r1 and c >= c1 and r < r2 and c < c2:
1900
1905
  self.hide_selection_box(item)
1901
- break
1902
1906
  if redraw:
1903
1907
  self.main_table_redraw_grid_and_text(redraw_header=True, redraw_row_index=True)
1904
1908
  sel_event = self.get_select_event(being_drawn_item=self.being_drawn_item)
@@ -1906,7 +1910,51 @@ class MainTable(tk.Canvas):
1906
1910
  try_binding(self.deselection_binding_func, sel_event)
1907
1911
  self.PAR.emit_event("<<SheetSelect>>", data=sel_event)
1908
1912
 
1909
- def page_UP(self, event=None):
1913
+ def deselect_any(
1914
+ self,
1915
+ rows: Iterator[int] | int | None = None,
1916
+ columns: Iterator[int] | int | None = None,
1917
+ redraw: bool = True,
1918
+ ) -> None:
1919
+ rows = int_x_iter(rows)
1920
+ columns = int_x_iter(columns)
1921
+ if is_iterable(rows) and is_iterable(columns):
1922
+ rows = tuple(consecutive_ranges(sorted(rows)))
1923
+ columns = tuple(consecutive_ranges(sorted(columns)))
1924
+ for item, box in self.get_selection_items(reverse=True):
1925
+ r1, c1, r2, c2 = box.coords
1926
+ hidden = False
1927
+ for rows_st, rows_end in rows:
1928
+ if hidden:
1929
+ break
1930
+ for cols_st, cols_end in columns:
1931
+ if ((rows_end >= r1 and rows_end <= r2) or (rows_st >= r1 and rows_st < r2)) and (
1932
+ (cols_end >= c1 and cols_end <= c2) or (cols_st >= c1 and cols_st < c2)
1933
+ ):
1934
+ hidden = self.hide_selection_box(item)
1935
+ break
1936
+ elif is_iterable(rows):
1937
+ rows = tuple(consecutive_ranges(sorted(rows)))
1938
+ for item, box in self.get_selection_items(reverse=True):
1939
+ r1, c1, r2, c2 = box.coords
1940
+ for rows_st, rows_end in rows:
1941
+ if (rows_end >= r1 and rows_end <= r2) or (rows_st >= r1 and rows_st < r2):
1942
+ self.hide_selection_box(item)
1943
+ break
1944
+ elif is_iterable(columns):
1945
+ columns = tuple(consecutive_ranges(sorted(columns)))
1946
+ for item, box in self.get_selection_items(reverse=True):
1947
+ r1, c1, r2, c2 = box.coords
1948
+ for cols_st, cols_end in columns:
1949
+ if (cols_end >= c1 and cols_end <= c2) or (cols_st >= c1 and cols_st < c2):
1950
+ self.hide_selection_box(item)
1951
+ break
1952
+ else:
1953
+ self.deselect()
1954
+ if redraw:
1955
+ self.refresh()
1956
+
1957
+ def page_UP(self, event: object = None) -> None:
1910
1958
  height = self.winfo_height()
1911
1959
  top = self.canvasy(0)
1912
1960
  scrollto_y = top - height
@@ -1935,7 +1983,7 @@ class MainTable(tk.Canvas):
1935
1983
  self.RI.yview(*args)
1936
1984
  self.main_table_redraw_grid_and_text(redraw_row_index=True)
1937
1985
 
1938
- def page_DOWN(self, event=None):
1986
+ def page_DOWN(self, event: object = None) -> None:
1939
1987
  height = self.winfo_height()
1940
1988
  top = self.canvasy(0)
1941
1989
  scrollto = top + height
@@ -1965,7 +2013,7 @@ class MainTable(tk.Canvas):
1965
2013
  self.RI.yview(*args)
1966
2014
  self.main_table_redraw_grid_and_text(redraw_row_index=True)
1967
2015
 
1968
- def arrowkey_UP(self, event=None):
2016
+ def arrowkey_UP(self, event: object = None) -> None:
1969
2017
  if not self.selected:
1970
2018
  return
1971
2019
  if self.selected.type_ == "rows":
@@ -1989,7 +2037,7 @@ class MainTable(tk.Canvas):
1989
2037
  self.select_cell(r - 1, c)
1990
2038
  self.see(r - 1, c, keep_xscroll=True, check_cell_visibility=False)
1991
2039
 
1992
- def arrowkey_DOWN(self, event=None):
2040
+ def arrowkey_DOWN(self, event: object = None) -> None:
1993
2041
  if not self.selected:
1994
2042
  return
1995
2043
  if self.selected.type_ == "rows":
@@ -2068,7 +2116,7 @@ class MainTable(tk.Canvas):
2068
2116
  check_cell_visibility=False,
2069
2117
  )
2070
2118
 
2071
- def arrowkey_LEFT(self, event=None):
2119
+ def arrowkey_LEFT(self, event: object = None) -> None:
2072
2120
  if not self.selected:
2073
2121
  return
2074
2122
  if self.selected.type_ == "columns":
@@ -2100,7 +2148,7 @@ class MainTable(tk.Canvas):
2100
2148
  self.select_cell(r, c - 1)
2101
2149
  self.see(r, c - 1, keep_yscroll=True, check_cell_visibility=False)
2102
2150
 
2103
- def arrowkey_RIGHT(self, event=None):
2151
+ def arrowkey_RIGHT(self, event: object = None) -> None:
2104
2152
  if not self.selected:
2105
2153
  return
2106
2154
  if self.selected.type_ == "rows":
@@ -2743,6 +2791,7 @@ class MainTable(tk.Canvas):
2743
2791
  c = self.identify_col(x=event.x)
2744
2792
  if self.single_selection_enabled and self.not_currently_resizing():
2745
2793
  if r < len(self.row_positions) - 1 and c < len(self.col_positions) - 1:
2794
+ self.being_drawn_item = True
2746
2795
  self.being_drawn_item = self.select_cell(r, c, redraw=True)
2747
2796
  elif self.toggle_selection_enabled and self.not_currently_resizing():
2748
2797
  r = self.identify_row(y=event.y)
@@ -2979,7 +3028,11 @@ class MainTable(tk.Canvas):
2979
3028
  c_to_sel,
2980
3029
  item=self.create_selection_box(
2981
3030
  *to_sel,
2982
- state="hidden" if (to_sel[2] - to_sel[0] == 1 and to_sel[3] - to_sel[1] == 1) else "normal",
3031
+ state=(
3032
+ "hidden"
3033
+ if (to_sel.upto_r - to_sel.from_r == 1 and to_sel.upto_c - to_sel.from_c == 1)
3034
+ else "normal"
3035
+ ),
2983
3036
  set_current=False,
2984
3037
  ),
2985
3038
  )
@@ -3222,8 +3275,6 @@ class MainTable(tk.Canvas):
3222
3275
 
3223
3276
  def ctrl_mousewheel(self, event):
3224
3277
  if event.delta < 0 or event.num == 5:
3225
- if self.PAR.ops.table_font[1] < 2 or self.PAR.ops.index_font[1] < 2 or self.PAR.ops.header_font[1] < 2:
3226
- return
3227
3278
  self.zoom_out()
3228
3279
  elif event.delta >= 0 or event.num == 4:
3229
3280
  self.zoom_in()
@@ -3231,16 +3282,22 @@ class MainTable(tk.Canvas):
3231
3282
  def zoom_in(self, event=None):
3232
3283
  self.zoom_font(
3233
3284
  (self.PAR.ops.table_font[0], self.PAR.ops.table_font[1] + 1, self.PAR.ops.table_font[2]),
3285
+ (self.PAR.ops.index_font[0], self.PAR.ops.index_font[1] + 1, self.PAR.ops.index_font[2]),
3234
3286
  (self.PAR.ops.header_font[0], self.PAR.ops.header_font[1] + 1, self.PAR.ops.header_font[2]),
3287
+ "in",
3235
3288
  )
3236
3289
 
3237
3290
  def zoom_out(self, event=None):
3291
+ if self.PAR.ops.table_font[1] < 2 or self.PAR.ops.index_font[1] < 2 or self.PAR.ops.header_font[1] < 2:
3292
+ return
3238
3293
  self.zoom_font(
3239
3294
  (self.PAR.ops.table_font[0], self.PAR.ops.table_font[1] - 1, self.PAR.ops.table_font[2]),
3295
+ (self.PAR.ops.index_font[0], self.PAR.ops.index_font[1] - 1, self.PAR.ops.index_font[2]),
3240
3296
  (self.PAR.ops.header_font[0], self.PAR.ops.header_font[1] - 1, self.PAR.ops.header_font[2]),
3297
+ "out",
3241
3298
  )
3242
3299
 
3243
- def zoom_font(self, table_font: tuple, header_font: tuple):
3300
+ def zoom_font(self, table_font: tuple, index_font: tuple, header_font: tuple, zoom: Literal["in", "out"]) -> None:
3244
3301
  self.saved_column_widths = {}
3245
3302
  self.saved_row_heights = {}
3246
3303
  # should record position prior to change and then see after change
@@ -3262,7 +3319,7 @@ class MainTable(tk.Canvas):
3262
3319
  table_font,
3263
3320
  reset_row_positions=False,
3264
3321
  )
3265
- self.set_index_font(table_font)
3322
+ self.set_index_font(index_font)
3266
3323
  self.set_header_font(header_font)
3267
3324
  if self.PAR.ops.set_cell_sizes_on_zoom:
3268
3325
  self.set_all_cell_sizes_to_text()
@@ -3290,18 +3347,18 @@ class MainTable(tk.Canvas):
3290
3347
  )
3291
3348
  self.main_table_redraw_grid_and_text(redraw_header=True, redraw_row_index=True)
3292
3349
  self.recreate_all_selection_boxes()
3293
- self.refresh_open_window_positions()
3294
- self.RI.refresh_open_window_positions()
3295
- self.CH.refresh_open_window_positions()
3350
+ self.main_table_redraw_grid_and_text(redraw_header=True, redraw_row_index=True)
3351
+ self.refresh_open_window_positions(zoom=zoom)
3352
+ self.RI.refresh_open_window_positions(zoom=zoom)
3353
+ self.CH.refresh_open_window_positions(zoom=zoom)
3296
3354
  self.see(
3297
3355
  r,
3298
3356
  c,
3299
3357
  check_cell_visibility=False,
3300
- redraw=False,
3358
+ redraw=True,
3301
3359
  r_pc=r_pc,
3302
3360
  c_pc=c_pc,
3303
3361
  )
3304
- self.main_table_redraw_grid_and_text(redraw_header=True, redraw_row_index=True)
3305
3362
 
3306
3363
  def get_txt_w(self, txt, font=None):
3307
3364
  self.txt_measure_canvas.itemconfig(
@@ -4207,12 +4264,12 @@ class MainTable(tk.Canvas):
4207
4264
  )
4208
4265
  if create_selections:
4209
4266
  self.deselect("all")
4210
- for chunk in consecutive_chunks(tuple(reversed(column_widths))):
4267
+ for boxst, boxend in consecutive_ranges(tuple(reversed(column_widths))):
4211
4268
  self.create_selection_box(
4212
4269
  0,
4213
- chunk[0],
4270
+ boxst,
4214
4271
  len(self.row_positions) - 1,
4215
- chunk[-1] + 1,
4272
+ boxend,
4216
4273
  "columns",
4217
4274
  run_binding=True,
4218
4275
  )
@@ -4336,11 +4393,11 @@ class MainTable(tk.Canvas):
4336
4393
  )
4337
4394
  if create_selections:
4338
4395
  self.deselect("all")
4339
- for chunk in consecutive_chunks(tuple(reversed(row_heights))):
4396
+ for boxst, boxend in consecutive_ranges(tuple(reversed(row_heights))):
4340
4397
  self.create_selection_box(
4341
- chunk[0],
4398
+ boxst,
4342
4399
  0,
4343
- chunk[-1] + 1,
4400
+ boxend,
4344
4401
  len(self.col_positions) - 1,
4345
4402
  "rows",
4346
4403
  run_binding=True,
@@ -5101,7 +5158,7 @@ class MainTable(tk.Canvas):
5101
5158
  tag: str | tuple,
5102
5159
  draw_check: bool = False,
5103
5160
  ) -> None:
5104
- points = get_checkbox_points(x1, y1, x2, y2)
5161
+ points = rounded_box_coords(x1, y1, x2, y2)
5105
5162
  if self.hidd_checkbox:
5106
5163
  t, sh = self.hidd_checkbox.popitem()
5107
5164
  self.coords(t, points)
@@ -5118,7 +5175,7 @@ class MainTable(tk.Canvas):
5118
5175
  y1 = y1 + 4
5119
5176
  x2 = x2 - 3
5120
5177
  y2 = y2 - 3
5121
- points = get_checkbox_points(x1, y1, x2, y2, radius=4)
5178
+ points = rounded_box_coords(x1, y1, x2, y2, radius=4)
5122
5179
  if self.hidd_checkbox:
5123
5180
  t, sh = self.hidd_checkbox.popitem()
5124
5181
  self.coords(t, points)
@@ -5620,7 +5677,7 @@ class MainTable(tk.Canvas):
5620
5677
  if r2 < len(self.row_positions) and c2 < len(self.col_positions):
5621
5678
  self.create_selection_box(r1, c1, r2, c2, v, run_binding=True)
5622
5679
  if selected:
5623
- self.set_currently_selected(selected.row, selected.column, box=selected.coords)
5680
+ self.set_currently_selected(selected.row, selected.column, box=selected.box)
5624
5681
 
5625
5682
  def set_currently_selected(
5626
5683
  self,
@@ -5750,24 +5807,34 @@ class MainTable(tk.Canvas):
5750
5807
  state: str,
5751
5808
  tags: str | tuple[str],
5752
5809
  width: int,
5810
+ iid: None | int = None,
5753
5811
  ) -> int:
5754
- if self.hidd_boxes:
5755
- iid = self.hidd_boxes.pop()
5812
+ coords = rounded_box_coords(
5813
+ x1,
5814
+ y1,
5815
+ x2,
5816
+ y2,
5817
+ radius=9 if self.PAR.ops.rounded_boxes else 0,
5818
+ )
5819
+ if isinstance(iid, int):
5756
5820
  self.itemconfig(iid, fill=fill, outline=outline, state=state, tags=tags, width=width)
5757
- self.coords(iid, x1, y1, x2, y2)
5821
+ self.coords(iid, coords)
5758
5822
  else:
5759
- iid = self.create_rectangle(
5760
- x1,
5761
- y1,
5762
- x2,
5763
- y2,
5764
- fill=fill,
5765
- outline=outline,
5766
- state=state,
5767
- tags=tags,
5768
- width=width,
5769
- )
5770
- self.disp_boxes.add(iid)
5823
+ if self.hidd_boxes:
5824
+ iid = self.hidd_boxes.pop()
5825
+ self.itemconfig(iid, fill=fill, outline=outline, state=state, tags=tags, width=width)
5826
+ self.coords(iid, coords)
5827
+ else:
5828
+ iid = self.create_polygon(
5829
+ coords,
5830
+ fill=fill,
5831
+ outline=outline,
5832
+ state=state,
5833
+ tags=tags,
5834
+ width=width,
5835
+ smooth=True,
5836
+ )
5837
+ self.disp_boxes.add(iid)
5771
5838
  return iid
5772
5839
 
5773
5840
  def hide_box(self, item: int | None) -> None:
@@ -5776,7 +5843,7 @@ class MainTable(tk.Canvas):
5776
5843
  self.hidd_boxes.add(item)
5777
5844
  self.itemconfig(item, state="hidden")
5778
5845
 
5779
- def hide_selection_box(self, item: int | None, set_current: bool = True) -> None:
5846
+ def hide_selection_box(self, item: int | None, set_current: bool = True) -> bool:
5780
5847
  if item is None:
5781
5848
  return
5782
5849
  box = self.selection_boxes.pop(item)
@@ -5787,6 +5854,7 @@ class MainTable(tk.Canvas):
5787
5854
  if self.selected.fill_iid == item:
5788
5855
  self.hide_selected()
5789
5856
  self.set_current_to_last()
5857
+ return True
5790
5858
 
5791
5859
  def hide_selected(self) -> None:
5792
5860
  if self.selected:
@@ -5819,29 +5887,32 @@ class MainTable(tk.Canvas):
5819
5887
  elif type_ == "columns":
5820
5888
  mt_bg = self.PAR.ops.table_selected_columns_bg
5821
5889
  mt_border_col = self.PAR.ops.table_selected_columns_border_fg
5890
+ if self.selection_boxes:
5891
+ self.itemconfig(next(reversed(self.selection_boxes)), state="normal")
5892
+ x1, y1, x2, y2 = self.box_sheet_coords_x_canvas_coords(r1, c1, r2, c2, type_)
5822
5893
  fill_iid = self.display_box(
5823
- self.col_positions[c1],
5824
- self.row_positions[r1],
5825
- self.canvasx(self.winfo_width()) if self.PAR.ops.selected_rows_to_end_of_window else self.col_positions[c2],
5826
- self.row_positions[r2],
5894
+ x1,
5895
+ y1,
5896
+ x2,
5897
+ y2,
5827
5898
  fill=mt_bg,
5828
5899
  outline="",
5829
- state=state,
5900
+ state=state if self.PAR.ops.show_selected_cells_border else "normal",
5830
5901
  tags=type_,
5831
5902
  width=1,
5832
5903
  )
5833
5904
  index_iid = self.RI.display_box(
5834
- 0,
5835
- self.row_positions[r1],
5905
+ 1,
5906
+ y1,
5836
5907
  self.RI.current_width - 1,
5837
- self.row_positions[r2],
5908
+ y2,
5838
5909
  fill=self.PAR.ops.index_selected_rows_bg if type_ == "rows" else self.PAR.ops.index_selected_cells_bg,
5839
5910
  outline="",
5840
5911
  state="normal",
5841
5912
  tags="cells" if type_ == "columns" else type_,
5842
5913
  )
5843
5914
  header_iid = self.CH.display_box(
5844
- self.col_positions[c1],
5915
+ x1,
5845
5916
  0,
5846
5917
  self.col_positions[c2],
5847
5918
  self.CH.current_height - 1,
@@ -5858,10 +5929,10 @@ class MainTable(tk.Canvas):
5858
5929
  or self.selection_boxes
5859
5930
  ):
5860
5931
  bd_iid = self.display_box(
5861
- self.col_positions[c1],
5862
- self.row_positions[r1],
5863
- self.col_positions[c2],
5864
- self.row_positions[r2],
5932
+ x1,
5933
+ y1,
5934
+ x2,
5935
+ y2,
5865
5936
  fill="",
5866
5937
  outline=mt_border_col,
5867
5938
  state="normal",
@@ -5904,6 +5975,23 @@ class MainTable(tk.Canvas):
5904
5975
  if self.PAR.ops.show_selected_cells_border:
5905
5976
  self.tag_raise(self.selected.iid)
5906
5977
 
5978
+ def box_sheet_coords_x_canvas_coords(
5979
+ self,
5980
+ r1: int,
5981
+ c1: int,
5982
+ r2: int,
5983
+ c2: int,
5984
+ type_: Literal["cells", "rows", "columns"],
5985
+ ) -> tuple[float, float, float, float]:
5986
+ x1 = self.col_positions[c1]
5987
+ y1 = self.row_positions[r1]
5988
+ y2 = self.row_positions[r2]
5989
+ if type_ == "rows" and self.PAR.ops.selected_rows_to_end_of_window:
5990
+ x2 = self.canvasx(self.winfo_width())
5991
+ else:
5992
+ x2 = self.col_positions[c2]
5993
+ return x1, y1, x2, y2
5994
+
5907
5995
  def recreate_selection_box(
5908
5996
  self,
5909
5997
  r1: int,
@@ -5926,66 +6014,53 @@ class MainTable(tk.Canvas):
5926
6014
  mt_bg = self.PAR.ops.table_selected_columns_bg
5927
6015
  mt_border_col = self.PAR.ops.table_selected_columns_border_fg
5928
6016
  if not state:
5929
- state = "normal" if (r2 - r1 > 1 or c2 - c1 > 1) else "hidden"
6017
+ if r2 - r1 > 1 or c2 - c1 > 1:
6018
+ state = "normal"
6019
+ elif next(reversed(self.selection_boxes)) == fill_iid:
6020
+ state = "hidden"
6021
+ else:
6022
+ state = "normal"
5930
6023
  if self.selected.fill_iid == fill_iid:
5931
6024
  self.selected = self.selected._replace(box=Box_nt(r1, c1, r2, c2))
5932
- self.coords(
5933
- fill_iid,
5934
- self.col_positions[c1],
5935
- self.row_positions[r1],
5936
- self.canvasx(self.winfo_width()) if self.PAR.ops.selected_rows_to_end_of_window else self.col_positions[c2],
5937
- self.row_positions[r2],
5938
- )
5939
- self.itemconfig(
5940
- fill_iid,
5941
- fill=mt_bg,
5942
- outline="",
5943
- tags=type_,
5944
- state=state,
5945
- )
5946
- self.RI.coords(
5947
- self.selection_boxes[fill_iid].index,
5948
- 0,
5949
- self.row_positions[r1],
6025
+ x1, y1, x2, y2 = self.box_sheet_coords_x_canvas_coords(r1, c1, r2, c2, type_)
6026
+ self.display_box(x1, y1, x2, y2, fill=mt_bg, outline="", state=state, tags=type_, width=1, iid=fill_iid)
6027
+ self.RI.display_box(
6028
+ 1,
6029
+ y1,
5950
6030
  self.RI.current_width - 1,
5951
- self.row_positions[r2],
5952
- )
5953
- self.RI.itemconfig(
5954
- self.selection_boxes[fill_iid].index,
6031
+ y2,
5955
6032
  fill=self.PAR.ops.index_selected_rows_bg if type_ == "rows" else self.PAR.ops.index_selected_cells_bg,
5956
6033
  outline="",
6034
+ state="normal",
5957
6035
  tags="cells" if type_ == "columns" else type_,
6036
+ iid=self.selection_boxes[fill_iid].index,
5958
6037
  )
5959
- self.CH.coords(
5960
- self.selection_boxes[fill_iid].header,
5961
- self.col_positions[c1],
6038
+ self.CH.display_box(
6039
+ x1,
5962
6040
  0,
5963
6041
  self.col_positions[c2],
5964
6042
  self.CH.current_height - 1,
5965
- )
5966
- self.CH.itemconfig(
5967
- self.selection_boxes[fill_iid].header,
5968
6043
  fill=(
5969
6044
  self.PAR.ops.header_selected_columns_bg if type_ == "columns" else self.PAR.ops.header_selected_cells_bg
5970
6045
  ),
5971
6046
  outline="",
6047
+ state="normal",
5972
6048
  tags="cells" if type_ == "rows" else type_,
6049
+ iid=self.selection_boxes[fill_iid].header,
5973
6050
  )
5974
- if bd_iid := self.selection_boxes[fill_iid].bd_iid:
6051
+ if (bd_iid := self.selection_boxes[fill_iid].bd_iid):
5975
6052
  if self.PAR.ops.show_selected_cells_border:
5976
- self.coords(
5977
- bd_iid,
5978
- self.col_positions[c1],
5979
- self.row_positions[r1],
5980
- self.col_positions[c2],
5981
- self.row_positions[r2],
5982
- )
5983
- self.itemconfig(
5984
- bd_iid,
6053
+ self.display_box(
6054
+ x1,
6055
+ y1,
6056
+ x2,
6057
+ y2,
5985
6058
  fill="",
5986
6059
  outline=mt_border_col,
5987
- tags=f"{type_}bd",
5988
6060
  state="normal",
6061
+ tags=f"{type_}bd",
6062
+ width=1,
6063
+ iid=bd_iid,
5989
6064
  )
5990
6065
  self.tag_raise(bd_iid)
5991
6066
  else:
@@ -6032,23 +6107,23 @@ class MainTable(tk.Canvas):
6032
6107
  self.set_currently_selected(box.coords.from_r, box.coords.from_c, item=box.fill_iid)
6033
6108
 
6034
6109
  def get_redraw_selections(self, startr: int, endr: int, startc: int, endc: int) -> dict:
6035
- d = defaultdict(list)
6110
+ d = defaultdict(set)
6036
6111
  for item, box in self.get_selection_items():
6037
- d[box.type_].append(box.coords)
6038
- d2 = {}
6039
- if "cells" in d:
6040
- d2["cells"] = {
6041
- (r, c)
6042
- for r in range(startr, endr)
6043
- for c in range(startc, endc)
6044
- for r1, c1, r2, c2 in d["cells"]
6045
- if r1 <= r and c1 <= c and r2 > r and c2 > c
6046
- }
6047
- if "rows" in d:
6048
- d2["rows"] = {r for r in range(startr, endr) for r1, c1, r2, c2 in d["rows"] if r1 <= r and r2 > r}
6049
- if "columns" in d:
6050
- d2["columns"] = {c for c in range(startc, endc) for r1, c1, r2, c2 in d["columns"] if c1 <= c and c2 > c}
6051
- return d2
6112
+ r1, c1, r2, c2 = box.coords
6113
+ if box.type_ == "cells":
6114
+ for r in range(startr, endr):
6115
+ for c in range(startc, endc):
6116
+ if r1 <= r and c1 <= c and r2 > r and c2 > c:
6117
+ d["cells"].add((r, c))
6118
+ elif box.type_ == "rows":
6119
+ for r in range(startr, endr):
6120
+ if r1 <= r and r2 > r:
6121
+ d["rows"].add(r)
6122
+ elif box.type_ == "columns":
6123
+ for c in range(startc, endc):
6124
+ if c1 <= c and c2 > c:
6125
+ d["columns"].add(c)
6126
+ return d
6052
6127
 
6053
6128
  def get_selected_min_max(self) -> tuple[int, int, int, int] | tuple[None, None, None, None]:
6054
6129
  min_x = float("inf")
@@ -6372,13 +6447,11 @@ class MainTable(tk.Canvas):
6372
6447
  extra_func_key = "Return"
6373
6448
  elif hasattr(event, "keysym") and event.keysym == "F2":
6374
6449
  extra_func_key = "F2"
6375
- datarn = r if self.all_rows_displayed else self.displayed_rows[r]
6376
- datacn = c if self.all_columns_displayed else self.displayed_columns[c]
6377
6450
  if event is not None and (hasattr(event, "keysym") and event.keysym == "BackSpace"):
6378
6451
  extra_func_key = "BackSpace"
6379
6452
  text = ""
6380
6453
  else:
6381
- text = f"{self.get_cell_data(datarn, datacn, none_to_empty_str = True)}"
6454
+ text = f"{self.get_cell_data(self.datarn(r), self.datacn(c), none_to_empty_str = True)}"
6382
6455
  elif event is not None and (
6383
6456
  (hasattr(event, "char") and event.char.isalpha())
6384
6457
  or (hasattr(event, "char") and event.char.isdigit())
@@ -6422,9 +6495,7 @@ class MainTable(tk.Canvas):
6422
6495
  w = self.col_positions[c + 1] - x + 1
6423
6496
  h = self.row_positions[r + 1] - y + 1
6424
6497
  if text is None:
6425
- text = f"""{self.get_cell_data(r if self.all_rows_displayed else self.displayed_rows[r],
6426
- c if self.all_columns_displayed else self.displayed_columns[c],
6427
- none_to_empty_str = True)}"""
6498
+ text = f"{self.get_cell_data(self.datarn(r), self.datacn(c), none_to_empty_str = True)}"
6428
6499
  bg, fg = self.PAR.ops.table_bg, self.PAR.ops.table_fg
6429
6500
  kwargs = {
6430
6501
  "menu_kwargs": DotDict(
@@ -6483,7 +6554,14 @@ class MainTable(tk.Canvas):
6483
6554
  curr_height = self.text_editor.window.winfo_height()
6484
6555
  if curr_height < self.min_row_height:
6485
6556
  return
6486
- if not check_lines or self.get_lines_cell_height(self.text_editor.window.get_num_lines() + 1) > curr_height:
6557
+ if (
6558
+ not check_lines
6559
+ or self.get_lines_cell_height(
6560
+ self.text_editor.window.get_num_lines() + 1,
6561
+ font=self.text_editor.tktext.cget("font"),
6562
+ )
6563
+ > curr_height
6564
+ ):
6487
6565
  new_height = curr_height + self.table_xtra_lines_increment
6488
6566
  space_bot = self.get_space_bot(r)
6489
6567
  if new_height > space_bot:
@@ -6508,24 +6586,30 @@ class MainTable(tk.Canvas):
6508
6586
  )
6509
6587
  self.itemconfig(self.dropdown.canvas_id, anchor=anchor, height=win_h)
6510
6588
 
6511
- def refresh_open_window_positions(self):
6589
+ def refresh_open_window_positions(self, zoom: Literal["in", "out"]):
6512
6590
  if self.text_editor.open:
6513
6591
  r, c = self.text_editor.coords
6514
6592
  self.text_editor.window.config(height=self.row_positions[r + 1] - self.row_positions[r])
6593
+ self.text_editor.tktext.config(font=self.PAR.ops.table_font)
6515
6594
  self.coords(
6516
6595
  self.text_editor.canvas_id,
6517
6596
  self.col_positions[c],
6518
6597
  self.row_positions[r],
6519
6598
  )
6520
6599
  if self.dropdown.open:
6600
+ if zoom == "in":
6601
+ self.dropdown.window.zoom_in()
6602
+ elif zoom == "out":
6603
+ self.dropdown.window.zoom_out()
6521
6604
  r, c = self.dropdown.get_coords()
6522
6605
  if self.text_editor.open:
6523
6606
  text_editor_h = self.text_editor.window.winfo_height()
6524
6607
  win_h, anchor = self.get_dropdown_height_anchor(r, c, text_editor_h)
6525
6608
  else:
6526
- text_editor_h = self.row_positions[r + 1] - self.row_positions[r]
6609
+ text_editor_h = self.row_positions[r + 1] - self.row_positions[r] + 1
6527
6610
  anchor = self.itemcget(self.dropdown.canvas_id, "anchor")
6528
6611
  # win_h = 0
6612
+ self.dropdown.window.config(width=self.col_positions[c + 1] - self.col_positions[c] + 1)
6529
6613
  if anchor == "nw":
6530
6614
  self.coords(
6531
6615
  self.dropdown.canvas_id,
@@ -6543,12 +6627,13 @@ class MainTable(tk.Canvas):
6543
6627
 
6544
6628
  def hide_text_editor(self, reason: None | str = None) -> None:
6545
6629
  if self.text_editor.open:
6630
+ for b in ("<Alt-Return>", "<Option-Return>", "<Tab>", "<Return>", "<FocusOut>", "<Escape>"):
6631
+ self.text_editor.tktext.unbind(b)
6546
6632
  self.itemconfig(self.text_editor.canvas_id, state="hidden")
6547
6633
  self.text_editor.open = False
6548
6634
  if reason == "Escape":
6549
6635
  self.focus_set()
6550
6636
 
6551
- # c is displayed col
6552
6637
  def close_text_editor(
6553
6638
  self,
6554
6639
  editor_info: tuple | None = None,
@@ -6566,15 +6651,15 @@ class MainTable(tk.Canvas):
6566
6651
  self.hide_text_editor_and_dropdown()
6567
6652
  return
6568
6653
  # setting cell data with text editor value
6569
- self.text_editor_value = self.text_editor.get()
6654
+ text_editor_value = self.text_editor.get()
6570
6655
  r, c = editor_info[0], editor_info[1]
6571
6656
  datarn, datacn = self.datarn(r), self.datacn(c)
6572
6657
  event_data = event_dict(
6573
6658
  name="end_edit_table",
6574
6659
  sheet=self.PAR.name,
6575
- cells_table={(datarn, datacn): self.text_editor_value},
6660
+ cells_table={(datarn, datacn): text_editor_value},
6576
6661
  key=editor_info[2],
6577
- value=self.text_editor_value,
6662
+ value=text_editor_value,
6578
6663
  loc=(r, c),
6579
6664
  boxes=self.get_boxes(),
6580
6665
  selected=self.selected,
@@ -6590,11 +6675,11 @@ class MainTable(tk.Canvas):
6590
6675
  check_input_valid=False,
6591
6676
  )
6592
6677
  if self.edit_validation_func:
6593
- self.text_editor_value = self.edit_validation_func(event_data)
6594
- if self.text_editor_value is not None and self.input_valid_for_cell(datarn, datacn, self.text_editor_value):
6595
- edited = set_data(value=self.text_editor_value)
6596
- elif self.input_valid_for_cell(datarn, datacn, self.text_editor_value):
6597
- edited = set_data(value=self.text_editor_value)
6678
+ text_editor_value = self.edit_validation_func(event_data)
6679
+ if text_editor_value is not None and self.input_valid_for_cell(datarn, datacn, text_editor_value):
6680
+ edited = set_data(value=text_editor_value)
6681
+ elif self.input_valid_for_cell(datarn, datacn, text_editor_value):
6682
+ edited = set_data(value=text_editor_value)
6598
6683
  if edited:
6599
6684
  try_binding(self.extra_end_edit_cell_func, event_data)
6600
6685
  if (
@@ -6604,7 +6689,7 @@ class MainTable(tk.Canvas):
6604
6689
  and r == self.selected.row
6605
6690
  and c == self.selected.column
6606
6691
  and (self.single_selection_enabled or self.toggle_selection_enabled)
6607
- and (edited or self.cell_equal_to(datarn, datacn, self.text_editor_value))
6692
+ and (edited or self.cell_equal_to(datarn, datacn, text_editor_value))
6608
6693
  ):
6609
6694
  r1, c1, r2, c2 = self.selection_boxes[self.selected.fill_iid].coords
6610
6695
  numcols = c2 - c1
@@ -6671,8 +6756,7 @@ class MainTable(tk.Canvas):
6671
6756
  def tab_key(self, event: object = None) -> str:
6672
6757
  if not self.selected:
6673
6758
  return
6674
- r = self.selected.row
6675
- c = self.selected.column
6759
+ r, c = self.selected.row, self.selected.column
6676
6760
  r1, c1, r2, c2 = self.selection_boxes[self.selected.fill_iid].coords
6677
6761
  numcols = c2 - c1
6678
6762
  numrows = r2 - r1
@@ -6803,7 +6887,7 @@ class MainTable(tk.Canvas):
6803
6887
  }
6804
6888
  if self.dropdown.window:
6805
6889
  self.dropdown.window.reset(**reset_kwargs)
6806
- self.itemconfig(self.dropdown.canvas_id, state="normal")
6890
+ self.itemconfig(self.dropdown.canvas_id, state="normal", anchor=anchor)
6807
6891
  self.coords(self.dropdown.canvas_id, self.col_positions[c], ypos)
6808
6892
  else:
6809
6893
  self.dropdown.window = self.PAR.dropdown_class(
@@ -6923,6 +7007,7 @@ class MainTable(tk.Canvas):
6923
7007
 
6924
7008
  def hide_dropdown_window(self) -> None:
6925
7009
  if self.dropdown.open:
7010
+ self.dropdown.window.unbind("<FocusOut>")
6926
7011
  self.itemconfig(self.dropdown.canvas_id, state="hidden")
6927
7012
  self.dropdown.open = False
6928
7013
 
@@ -6974,12 +7059,14 @@ class MainTable(tk.Canvas):
6974
7059
  c: int = 0,
6975
7060
  datarn: int | None = None,
6976
7061
  datacn: int | None = None,
6977
- value: str = "",
7062
+ value: str | None = None,
6978
7063
  undo: bool = True,
6979
7064
  cell_resize: bool = True,
6980
7065
  redraw: bool = True,
6981
7066
  check_input_valid: bool = True,
6982
7067
  ) -> bool:
7068
+ if value is None:
7069
+ value = ""
6983
7070
  if datacn is None:
6984
7071
  datacn = self.datacn(c)
6985
7072
  if datarn is None:
@@ -7100,7 +7187,12 @@ class MainTable(tk.Canvas):
7100
7187
  self.delete_row_format("all", clear_values=clear_values)
7101
7188
  self.delete_column_format("all", clear_values=clear_values)
7102
7189
 
7103
- def delete_cell_format(self, datarn: str | int = "all", datacn: int = 0, clear_values: bool = False) -> None:
7190
+ def delete_cell_format(
7191
+ self,
7192
+ datarn: Literal["all"] | int = "all",
7193
+ datacn: int = 0,
7194
+ clear_values: bool = False,
7195
+ ) -> None:
7104
7196
  if isinstance(datarn, str) and datarn.lower() == "all":
7105
7197
  itr = gen_formatted(self.cell_options)
7106
7198
  else:
@@ -7114,7 +7206,7 @@ class MainTable(tk.Canvas):
7114
7206
  if clear_values:
7115
7207
  self.set_cell_data(*key, get_val(*key), expand_sheet=False)
7116
7208
 
7117
- def delete_row_format(self, datarn: str | int = "all", clear_values: bool = False) -> None:
7209
+ def delete_row_format(self, datarn: Literal["all"] | int = "all", clear_values: bool = False) -> None:
7118
7210
  if isinstance(datarn, str) and datarn.lower() == "all":
7119
7211
  itr = gen_formatted(self.row_options)
7120
7212
  else:
@@ -7129,7 +7221,7 @@ class MainTable(tk.Canvas):
7129
7221
  for datacn in range(len(self.data[datarn])):
7130
7222
  self.set_cell_data(datarn, datacn, get_val(datarn, datacn), expand_sheet=False)
7131
7223
 
7132
- def delete_column_format(self, datacn: str | int = "all", clear_values: bool = False) -> None:
7224
+ def delete_column_format(self, datacn: Literal["all"] | int = "all", clear_values: bool = False) -> None:
7133
7225
  if isinstance(datacn, str) and datacn.lower() == "all":
7134
7226
  itr = gen_formatted(self.col_options)
7135
7227
  else: