tksheet 7.1.6__py3-none-any.whl → 7.1.8__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
@@ -26,7 +26,6 @@ from itertools import (
26
26
  chain,
27
27
  cycle,
28
28
  islice,
29
- product,
30
29
  repeat,
31
30
  )
32
31
  from math import (
@@ -56,7 +55,6 @@ from .functions import (
56
55
  ev_stack_dict,
57
56
  event_dict,
58
57
  gen_formatted,
59
- get_checkbox_points,
60
58
  get_new_indexes,
61
59
  get_seq_without_gaps_at_index,
62
60
  index_exists,
@@ -67,10 +65,11 @@ from .functions import (
67
65
  len_to_idx,
68
66
  mod_event_val,
69
67
  mod_span,
68
+ mod_span_widget,
70
69
  move_elements_by_mapping,
71
70
  pickle_obj,
71
+ rounded_box_coords,
72
72
  span_idxs_post_move,
73
- mod_span_widget,
74
73
  try_binding,
75
74
  unpickle_obj,
76
75
  )
@@ -82,6 +81,7 @@ from .other_classes import (
82
81
  DropdownStorage,
83
82
  EventDataDict,
84
83
  FontTuple,
84
+ Loc,
85
85
  Selected,
86
86
  SelectionBox,
87
87
  TextEditorStorage,
@@ -94,6 +94,7 @@ from .vars import (
94
94
  ctrl_key,
95
95
  rc_binding,
96
96
  symbols_set,
97
+ text_editor_to_unbind,
97
98
  val_modifying_options,
98
99
  )
99
100
 
@@ -675,7 +676,7 @@ class MainTable(tk.Canvas):
675
676
  if lastbox_numrows > new_data_numrows and not lastbox_numrows % new_data_numrows:
676
677
  nd = []
677
678
  for _ in range(int(lastbox_numrows / new_data_numrows)):
678
- nd.extend([r.copy() for r in data])
679
+ nd.extend(r.copy() for r in data)
679
680
  data.extend(nd)
680
681
  new_data_numrows *= int(lastbox_numrows / new_data_numrows)
681
682
 
@@ -971,14 +972,14 @@ class MainTable(tk.Canvas):
971
972
  run_binding=True,
972
973
  )
973
974
  if move_data:
974
- self.data[:] = [
975
- move_elements_by_mapping(
976
- r,
977
- data_new_idxs,
978
- data_old_idxs,
979
- )
980
- for r in self.data
981
- ]
975
+ self.data = list(
976
+ map(
977
+ move_elements_by_mapping,
978
+ self.data,
979
+ repeat(data_new_idxs),
980
+ repeat(data_old_idxs),
981
+ ),
982
+ )
982
983
  maxidx = len_to_idx(totalcols)
983
984
  self.CH.fix_header(maxidx)
984
985
  if isinstance(self._headers, list) and self._headers:
@@ -999,101 +1000,104 @@ class MainTable(tk.Canvas):
999
1000
  tags: {full_new_idxs[k] for k in tagged} for tags, tagged in self.tagged_columns.items()
1000
1001
  }
1001
1002
  self.CH.cell_options = {full_new_idxs[k]: v for k, v in self.CH.cell_options.items()}
1002
- totalrows = self.total_data_rows()
1003
- new_ops = self.PAR.create_options_from_span
1004
- qkspan = self.span()
1005
- for span in self.named_spans.values():
1006
- # span is neither a cell options nor col options span, continue
1007
- if not isinstance(span["from_c"], int):
1008
- continue
1009
- oldupto_colrange, newupto_colrange, newfrom, newupto = span_idxs_post_move(
1010
- data_new_idxs,
1011
- full_new_idxs,
1012
- totalcols,
1013
- span,
1014
- "c",
1015
- )
1016
- # add cell/col kwargs for columns that are new to the span
1017
- old_span_idxs = set(full_new_idxs[k] for k in range(span["from_c"], oldupto_colrange))
1018
- for k in range(newfrom, newupto_colrange):
1019
- if k not in old_span_idxs:
1020
- oldidx = full_old_idxs[k]
1021
- # event_data is used to preserve old cell value
1022
- # in case cells are modified by
1023
- # formatting, checkboxes, dropdown boxes
1024
- if (
1025
- span["type_"] in val_modifying_options
1026
- and span["header"]
1027
- and oldidx not in event_data["cells"]["header"]
1028
- ):
1029
- event_data["cells"]["header"][oldidx] = self.CH.get_cell_data(k)
1030
- # the span targets columns
1031
- if span["from_r"] is None:
1032
- if span["type_"] in val_modifying_options:
1033
- for datarn in range(len(self.data)):
1034
- if (datarn, oldidx) not in event_data["cells"]["table"]:
1035
- event_data["cells"]["table"][(datarn, oldidx)] = self.get_cell_data(datarn, k)
1036
- # create new col options
1037
- new_ops(
1038
- mod_span(
1039
- qkspan,
1040
- span,
1041
- from_c=k,
1042
- upto_c=k + 1,
1043
- )
1044
- )
1045
- # the span targets cells
1046
- else:
1047
- rng_upto_r = totalrows if span["upto_r"] is None else span["upto_r"]
1048
- for datarn in range(span["from_r"], rng_upto_r):
1049
- if (
1050
- span["type_"] in val_modifying_options
1051
- and (datarn, oldidx) not in event_data["cells"]["table"]
1052
- ):
1053
- event_data["cells"]["table"][(datarn, oldidx)] = self.get_cell_data(datarn, k)
1054
- # create new cell options
1003
+ if self.named_spans:
1004
+ totalrows = self.total_data_rows()
1005
+ new_ops = self.PAR.create_options_from_span
1006
+ qkspan = self.span()
1007
+ for span in self.named_spans.values():
1008
+ # span is neither a cell options nor col options span, continue
1009
+ if not isinstance(span["from_c"], int):
1010
+ continue
1011
+ oldupto_colrange, newupto_colrange, newfrom, newupto = span_idxs_post_move(
1012
+ data_new_idxs,
1013
+ full_new_idxs,
1014
+ totalcols,
1015
+ span,
1016
+ "c",
1017
+ )
1018
+ # add cell/col kwargs for columns that are new to the span
1019
+ old_span_idxs = set(full_new_idxs[k] for k in range(span["from_c"], oldupto_colrange))
1020
+ for k in range(newfrom, newupto_colrange):
1021
+ if k not in old_span_idxs:
1022
+ oldidx = full_old_idxs[k]
1023
+ # event_data is used to preserve old cell value
1024
+ # in case cells are modified by
1025
+ # formatting, checkboxes, dropdown boxes
1026
+ if (
1027
+ span["type_"] in val_modifying_options
1028
+ and span["header"]
1029
+ and oldidx not in event_data["cells"]["header"]
1030
+ ):
1031
+ event_data["cells"]["header"][oldidx] = self.CH.get_cell_data(k)
1032
+ # the span targets columns
1033
+ if span["from_r"] is None:
1034
+ if span["type_"] in val_modifying_options:
1035
+ for datarn in range(len(self.data)):
1036
+ if (datarn, oldidx) not in event_data["cells"]["table"]:
1037
+ event_data["cells"]["table"][(datarn, oldidx)] = self.get_cell_data(
1038
+ datarn, k
1039
+ )
1040
+ # create new col options
1055
1041
  new_ops(
1056
1042
  mod_span(
1057
1043
  qkspan,
1058
1044
  span,
1059
- from_r=datarn,
1060
- upto_r=datarn + 1,
1061
1045
  from_c=k,
1062
1046
  upto_c=k + 1,
1063
1047
  )
1064
1048
  )
1065
- # remove span specific kwargs from cells/columns
1066
- # that are no longer in the span,
1067
- # cell options/col options keys are new idxs
1068
- for k in range(span["from_c"], oldupto_colrange):
1069
- # has it moved outside of new span coords
1070
- if (isinstance(newupto, int) and (full_new_idxs[k] < newfrom or full_new_idxs[k] >= newupto)) or (
1071
- newupto is None and full_new_idxs[k] < newfrom
1072
- ):
1073
- # span includes header
1049
+ # the span targets cells
1050
+ else:
1051
+ rng_upto_r = totalrows if span["upto_r"] is None else span["upto_r"]
1052
+ for datarn in range(span["from_r"], rng_upto_r):
1053
+ if (
1054
+ span["type_"] in val_modifying_options
1055
+ and (datarn, oldidx) not in event_data["cells"]["table"]
1056
+ ):
1057
+ event_data["cells"]["table"][(datarn, oldidx)] = self.get_cell_data(datarn, k)
1058
+ # create new cell options
1059
+ new_ops(
1060
+ mod_span(
1061
+ qkspan,
1062
+ span,
1063
+ from_r=datarn,
1064
+ upto_r=datarn + 1,
1065
+ from_c=k,
1066
+ upto_c=k + 1,
1067
+ )
1068
+ )
1069
+ # remove span specific kwargs from cells/columns
1070
+ # that are no longer in the span,
1071
+ # cell options/col options keys are new idxs
1072
+ for k in range(span["from_c"], oldupto_colrange):
1073
+ # has it moved outside of new span coords
1074
1074
  if (
1075
- span["header"]
1076
- and full_new_idxs[k] in self.CH.cell_options
1077
- and span["type_"] in self.CH.cell_options[full_new_idxs[k]]
1078
- ):
1079
- del self.CH.cell_options[full_new_idxs[k]][span["type_"]]
1080
- # span is for col options
1081
- if span["from_r"] is None:
1075
+ isinstance(newupto, int) and (full_new_idxs[k] < newfrom or full_new_idxs[k] >= newupto)
1076
+ ) or (newupto is None and full_new_idxs[k] < newfrom):
1077
+ # span includes header
1082
1078
  if (
1083
- full_new_idxs[k] in self.col_options
1084
- and span["type_"] in self.col_options[full_new_idxs[k]]
1079
+ span["header"]
1080
+ and full_new_idxs[k] in self.CH.cell_options
1081
+ and span["type_"] in self.CH.cell_options[full_new_idxs[k]]
1085
1082
  ):
1086
- del self.col_options[full_new_idxs[k]][span["type_"]]
1087
- # span is for cell options
1088
- else:
1089
- rng_upto_r = totalrows if span["upto_r"] is None else span["upto_r"]
1090
- for r in range(span["from_r"], rng_upto_r):
1091
- if (r, full_new_idxs[k]) in self.cell_options and span["type_"] in self.cell_options[
1092
- (r, full_new_idxs[k])
1093
- ]:
1094
- del self.cell_options[(r, full_new_idxs[k])][span["type_"]]
1095
- # finally, change the span coords
1096
- span["from_c"], span["upto_c"] = newfrom, newupto
1083
+ del self.CH.cell_options[full_new_idxs[k]][span["type_"]]
1084
+ # span is for col options
1085
+ if span["from_r"] is None:
1086
+ if (
1087
+ full_new_idxs[k] in self.col_options
1088
+ and span["type_"] in self.col_options[full_new_idxs[k]]
1089
+ ):
1090
+ del self.col_options[full_new_idxs[k]][span["type_"]]
1091
+ # span is for cell options
1092
+ else:
1093
+ rng_upto_r = totalrows if span["upto_r"] is None else span["upto_r"]
1094
+ for r in range(span["from_r"], rng_upto_r):
1095
+ if (r, full_new_idxs[k]) in self.cell_options and span[
1096
+ "type_"
1097
+ ] in self.cell_options[(r, full_new_idxs[k])]:
1098
+ del self.cell_options[(r, full_new_idxs[k])][span["type_"]]
1099
+ # finally, change the span coords
1100
+ span["from_c"], span["upto_c"] = newfrom, newupto
1097
1101
  if data_indexes:
1098
1102
  self.displayed_columns = sorted(full_new_idxs[k] for k in self.displayed_columns)
1099
1103
  return data_new_idxs, disp_new_idxs, event_data
@@ -1192,7 +1196,7 @@ class MainTable(tk.Canvas):
1192
1196
  run_binding=True,
1193
1197
  )
1194
1198
  if move_data:
1195
- self.data[:] = move_elements_by_mapping(
1199
+ self.data = move_elements_by_mapping(
1196
1200
  self.data,
1197
1201
  data_new_idxs,
1198
1202
  data_old_idxs,
@@ -1216,101 +1220,104 @@ class MainTable(tk.Canvas):
1216
1220
  self.row_options = {full_new_idxs[k]: v for k, v in self.row_options.items()}
1217
1221
  self.RI.cell_options = {full_new_idxs[k]: v for k, v in self.RI.cell_options.items()}
1218
1222
  self.RI.tree_rns = {v: full_new_idxs[k] for v, k in self.RI.tree_rns.items()}
1219
- totalcols = self.total_data_cols()
1220
- new_ops = self.PAR.create_options_from_span
1221
- qkspan = self.span()
1222
- for span in self.named_spans.values():
1223
- # span is neither a cell options nor row options span, continue
1224
- if not isinstance(span["from_r"], int):
1225
- continue
1226
- oldupto_rowrange, newupto_rowrange, newfrom, newupto = span_idxs_post_move(
1227
- data_new_idxs,
1228
- full_new_idxs,
1229
- totalrows,
1230
- span,
1231
- "r",
1232
- )
1233
- # add cell/row kwargs for rows that are new to the span
1234
- old_span_idxs = set(full_new_idxs[k] for k in range(span["from_r"], oldupto_rowrange))
1235
- for k in range(newfrom, newupto_rowrange):
1236
- if k not in old_span_idxs:
1237
- oldidx = full_old_idxs[k]
1238
- # event_data is used to preserve old cell value
1239
- # in case cells are modified by
1240
- # formatting, checkboxes, dropdown boxes
1241
- if (
1242
- span["type_"] in val_modifying_options
1243
- and span["index"]
1244
- and oldidx not in event_data["cells"]["index"]
1245
- ):
1246
- event_data["cells"]["index"][oldidx] = self.RI.get_cell_data(k)
1247
- # the span targets rows
1248
- if span["from_c"] is None:
1249
- if span["type_"] in val_modifying_options:
1250
- for datacn in range(len(self.data[k])):
1251
- if (oldidx, datacn) not in event_data["cells"]["table"]:
1252
- event_data["cells"]["table"][(oldidx, datacn)] = self.get_cell_data(k, datacn)
1253
- # create new row options
1254
- new_ops(
1255
- mod_span(
1256
- qkspan,
1257
- span,
1258
- from_r=k,
1259
- upto_r=k + 1,
1260
- )
1261
- )
1262
- # the span targets cells
1263
- else:
1264
- rng_upto_c = totalcols if span["upto_c"] is None else span["upto_c"]
1265
- for datacn in range(span["from_c"], rng_upto_c):
1266
- if (
1267
- span["type_"] in val_modifying_options
1268
- and (oldidx, datacn) not in event_data["cells"]["table"]
1269
- ):
1270
- event_data["cells"]["table"][(oldidx, datacn)] = self.get_cell_data(k, datacn)
1271
- # create new cell options
1223
+ if self.named_spans:
1224
+ totalcols = self.total_data_cols()
1225
+ new_ops = self.PAR.create_options_from_span
1226
+ qkspan = self.span()
1227
+ for span in self.named_spans.values():
1228
+ # span is neither a cell options nor row options span, continue
1229
+ if not isinstance(span["from_r"], int):
1230
+ continue
1231
+ oldupto_rowrange, newupto_rowrange, newfrom, newupto = span_idxs_post_move(
1232
+ data_new_idxs,
1233
+ full_new_idxs,
1234
+ totalrows,
1235
+ span,
1236
+ "r",
1237
+ )
1238
+ # add cell/row kwargs for rows that are new to the span
1239
+ old_span_idxs = set(full_new_idxs[k] for k in range(span["from_r"], oldupto_rowrange))
1240
+ for k in range(newfrom, newupto_rowrange):
1241
+ if k not in old_span_idxs:
1242
+ oldidx = full_old_idxs[k]
1243
+ # event_data is used to preserve old cell value
1244
+ # in case cells are modified by
1245
+ # formatting, checkboxes, dropdown boxes
1246
+ if (
1247
+ span["type_"] in val_modifying_options
1248
+ and span["index"]
1249
+ and oldidx not in event_data["cells"]["index"]
1250
+ ):
1251
+ event_data["cells"]["index"][oldidx] = self.RI.get_cell_data(k)
1252
+ # the span targets rows
1253
+ if span["from_c"] is None:
1254
+ if span["type_"] in val_modifying_options:
1255
+ for datacn in range(len(self.data[k])):
1256
+ if (oldidx, datacn) not in event_data["cells"]["table"]:
1257
+ event_data["cells"]["table"][(oldidx, datacn)] = self.get_cell_data(
1258
+ k, datacn
1259
+ )
1260
+ # create new row options
1272
1261
  new_ops(
1273
1262
  mod_span(
1274
1263
  qkspan,
1275
1264
  span,
1276
1265
  from_r=k,
1277
1266
  upto_r=k + 1,
1278
- from_c=datacn,
1279
- upto_c=datacn + 1,
1280
1267
  )
1281
1268
  )
1282
- # remove span specific kwargs from cells/rows
1283
- # that are no longer in the span,
1284
- # cell options/row options keys are new idxs
1285
- for k in range(span["from_r"], oldupto_rowrange):
1286
- # has it moved outside of new span coords
1287
- if (isinstance(newupto, int) and (full_new_idxs[k] < newfrom or full_new_idxs[k] >= newupto)) or (
1288
- newupto is None and full_new_idxs[k] < newfrom
1289
- ):
1290
- # span includes index
1269
+ # the span targets cells
1270
+ else:
1271
+ rng_upto_c = totalcols if span["upto_c"] is None else span["upto_c"]
1272
+ for datacn in range(span["from_c"], rng_upto_c):
1273
+ if (
1274
+ span["type_"] in val_modifying_options
1275
+ and (oldidx, datacn) not in event_data["cells"]["table"]
1276
+ ):
1277
+ event_data["cells"]["table"][(oldidx, datacn)] = self.get_cell_data(k, datacn)
1278
+ # create new cell options
1279
+ new_ops(
1280
+ mod_span(
1281
+ qkspan,
1282
+ span,
1283
+ from_r=k,
1284
+ upto_r=k + 1,
1285
+ from_c=datacn,
1286
+ upto_c=datacn + 1,
1287
+ )
1288
+ )
1289
+ # remove span specific kwargs from cells/rows
1290
+ # that are no longer in the span,
1291
+ # cell options/row options keys are new idxs
1292
+ for k in range(span["from_r"], oldupto_rowrange):
1293
+ # has it moved outside of new span coords
1291
1294
  if (
1292
- span["index"]
1293
- and full_new_idxs[k] in self.RI.cell_options
1294
- and span["type_"] in self.RI.cell_options[full_new_idxs[k]]
1295
- ):
1296
- del self.RI.cell_options[full_new_idxs[k]][span["type_"]]
1297
- # span is for row options
1298
- if span["from_c"] is None:
1295
+ isinstance(newupto, int) and (full_new_idxs[k] < newfrom or full_new_idxs[k] >= newupto)
1296
+ ) or (newupto is None and full_new_idxs[k] < newfrom):
1297
+ # span includes index
1299
1298
  if (
1300
- full_new_idxs[k] in self.row_options
1301
- and span["type_"] in self.row_options[full_new_idxs[k]]
1299
+ span["index"]
1300
+ and full_new_idxs[k] in self.RI.cell_options
1301
+ and span["type_"] in self.RI.cell_options[full_new_idxs[k]]
1302
1302
  ):
1303
- del self.row_options[full_new_idxs[k]][span["type_"]]
1304
- # span is for cell options
1305
- else:
1306
- rng_upto_c = totalcols if span["upto_c"] is None else span["upto_c"]
1307
- for c in range(span["from_c"], rng_upto_c):
1308
- if (full_new_idxs[k], c) in self.cell_options and span["type_"] in self.cell_options[
1309
- (full_new_idxs[k], c)
1310
- ]:
1311
- del self.cell_options[(full_new_idxs[k], c)][span["type_"]]
1312
- # finally, change the span coords
1313
- span["from_r"], span["upto_r"] = newfrom, newupto
1303
+ del self.RI.cell_options[full_new_idxs[k]][span["type_"]]
1304
+ # span is for row options
1305
+ if span["from_c"] is None:
1306
+ if (
1307
+ full_new_idxs[k] in self.row_options
1308
+ and span["type_"] in self.row_options[full_new_idxs[k]]
1309
+ ):
1310
+ del self.row_options[full_new_idxs[k]][span["type_"]]
1311
+ # span is for cell options
1312
+ else:
1313
+ rng_upto_c = totalcols if span["upto_c"] is None else span["upto_c"]
1314
+ for c in range(span["from_c"], rng_upto_c):
1315
+ if (full_new_idxs[k], c) in self.cell_options and span[
1316
+ "type_"
1317
+ ] in self.cell_options[(full_new_idxs[k], c)]:
1318
+ del self.cell_options[(full_new_idxs[k], c)][span["type_"]]
1319
+ # finally, change the span coords
1320
+ span["from_r"], span["upto_r"] = newfrom, newupto
1314
1321
  if data_indexes:
1315
1322
  self.displayed_rows = sorted(full_new_idxs[k] for k in self.displayed_rows)
1316
1323
  return data_new_idxs, disp_new_idxs, event_data
@@ -2785,6 +2792,7 @@ class MainTable(tk.Canvas):
2785
2792
  c = self.identify_col(x=event.x)
2786
2793
  if self.single_selection_enabled and self.not_currently_resizing():
2787
2794
  if r < len(self.row_positions) - 1 and c < len(self.col_positions) - 1:
2795
+ self.being_drawn_item = True
2788
2796
  self.being_drawn_item = self.select_cell(r, c, redraw=True)
2789
2797
  elif self.toggle_selection_enabled and self.not_currently_resizing():
2790
2798
  r = self.identify_row(y=event.y)
@@ -3021,7 +3029,11 @@ class MainTable(tk.Canvas):
3021
3029
  c_to_sel,
3022
3030
  item=self.create_selection_box(
3023
3031
  *to_sel,
3024
- state="hidden" if (to_sel[2] - to_sel[0] == 1 and to_sel[3] - to_sel[1] == 1) else "normal",
3032
+ state=(
3033
+ "hidden"
3034
+ if (to_sel.upto_r - to_sel.from_r == 1 and to_sel.upto_c - to_sel.from_c == 1)
3035
+ else "normal"
3036
+ ),
3025
3037
  set_current=False,
3026
3038
  ),
3027
3039
  )
@@ -3202,39 +3214,30 @@ class MainTable(tk.Canvas):
3202
3214
  # continue
3203
3215
 
3204
3216
  def set_xviews(self, *args, move_synced: bool = True, redraw: bool = True) -> None:
3217
+ self.main_table_redraw_grid_and_text(setting_views=True)
3218
+ self.update_idletasks()
3205
3219
  self.xview(*args)
3206
3220
  if self.show_header:
3207
3221
  self.CH.xview(*args)
3208
3222
  if move_synced:
3209
3223
  self.x_move_synced_scrolls(*args)
3210
3224
  self.fix_views()
3211
- if redraw:
3212
- self.main_table_redraw_grid_and_text(redraw_header=True if self.show_header else False)
3225
+ self.PAR.set_refresh_timer(redraw)
3213
3226
 
3214
3227
  def set_yviews(self, *args, move_synced: bool = True, redraw: bool = True) -> None:
3228
+ self.main_table_redraw_grid_and_text(setting_views=True)
3229
+ self.update_idletasks()
3215
3230
  self.yview(*args)
3216
3231
  if self.show_index:
3217
3232
  self.RI.yview(*args)
3218
3233
  if move_synced:
3219
3234
  self.y_move_synced_scrolls(*args)
3220
3235
  self.fix_views()
3221
- if redraw:
3222
- self.main_table_redraw_grid_and_text(redraw_row_index=True if self.show_index else False)
3236
+ self.PAR.set_refresh_timer(redraw)
3223
3237
 
3224
3238
  def set_view(self, x_args: list[str, float], y_args: list[str, float]) -> None:
3225
- self.xview(*x_args)
3226
- if self.show_header:
3227
- self.CH.xview(*x_args)
3228
- self.yview(*y_args)
3229
- if self.show_index:
3230
- self.RI.yview(*y_args)
3231
- self.x_move_synced_scrolls(*x_args)
3232
- self.y_move_synced_scrolls(*y_args)
3233
- self.fix_views()
3234
- self.main_table_redraw_grid_and_text(
3235
- redraw_row_index=True if self.show_index else False,
3236
- redraw_header=True if self.show_header else False,
3237
- )
3239
+ self.set_xviews(*x_args)
3240
+ self.set_yviews(*y_args)
3238
3241
 
3239
3242
  def mousewheel(self, event: object) -> None:
3240
3243
  if event.delta < 0 or event.num == 5:
@@ -4882,7 +4885,7 @@ class MainTable(tk.Canvas):
4882
4885
  if total_rows is not None:
4883
4886
  if len(self.data) < total_rows:
4884
4887
  ncols = self.total_data_cols() if total_columns is None else total_columns
4885
- self.data.extend([self.get_empty_row_seq(r, ncols) for r in range(total_rows - len(self.data))])
4888
+ self.data.extend(self.get_empty_row_seq(r, ncols) for r in range(total_rows - len(self.data)))
4886
4889
  else:
4887
4890
  self.data[total_rows:] = []
4888
4891
  if total_columns is not None:
@@ -5147,7 +5150,7 @@ class MainTable(tk.Canvas):
5147
5150
  tag: str | tuple,
5148
5151
  draw_check: bool = False,
5149
5152
  ) -> None:
5150
- points = get_checkbox_points(x1, y1, x2, y2)
5153
+ points = rounded_box_coords(x1, y1, x2, y2)
5151
5154
  if self.hidd_checkbox:
5152
5155
  t, sh = self.hidd_checkbox.popitem()
5153
5156
  self.coords(t, points)
@@ -5164,7 +5167,7 @@ class MainTable(tk.Canvas):
5164
5167
  y1 = y1 + 4
5165
5168
  x2 = x2 - 3
5166
5169
  y2 = y2 - 3
5167
- points = get_checkbox_points(x1, y1, x2, y2, radius=4)
5170
+ points = rounded_box_coords(x1, y1, x2, y2, radius=4)
5168
5171
  if self.hidd_checkbox:
5169
5172
  t, sh = self.hidd_checkbox.popitem()
5170
5173
  self.coords(t, points)
@@ -5182,6 +5185,7 @@ class MainTable(tk.Canvas):
5182
5185
  redraw_header: bool = False,
5183
5186
  redraw_row_index: bool = False,
5184
5187
  redraw_table: bool = True,
5188
+ setting_views: bool = False,
5185
5189
  ) -> bool:
5186
5190
  try:
5187
5191
  can_width = self.winfo_width()
@@ -5275,6 +5279,8 @@ class MainTable(tk.Canvas):
5275
5279
  if scrollregion != self.scrollregion:
5276
5280
  self.configure(scrollregion=scrollregion)
5277
5281
  self.scrollregion = scrollregion
5282
+ if setting_views:
5283
+ return False
5278
5284
  scrollpos_bot = self.canvasy(can_height)
5279
5285
  end_row = bisect_right(self.row_positions, scrollpos_bot)
5280
5286
  if not scrollpos_bot >= self.row_positions[-1]:
@@ -5754,8 +5760,8 @@ class MainTable(tk.Canvas):
5754
5760
  fill, outline = self.get_selected_box_bg_fg(type_=type_)
5755
5761
  x1 = self.col_positions[c] + 1
5756
5762
  y1 = self.row_positions[r] + 1
5757
- x2 = self.col_positions[c + 1] if index_exists(self.col_positions, c + 1) else self.col_positions[c]
5758
- y2 = self.row_positions[r + 1] if index_exists(self.row_positions, r + 1) else self.row_positions[r]
5763
+ x2 = self.col_positions[c + 1] if index_exists(self.col_positions, c + 1) else self.col_positions[c] + 1
5764
+ y2 = self.row_positions[r + 1] if index_exists(self.row_positions, r + 1) else self.row_positions[r] + 1
5759
5765
  self.hide_selected()
5760
5766
  if self.PAR.ops.show_selected_cells_border:
5761
5767
  fill = ""
@@ -5796,24 +5802,38 @@ class MainTable(tk.Canvas):
5796
5802
  state: str,
5797
5803
  tags: str | tuple[str],
5798
5804
  width: int,
5805
+ iid: None | int = None,
5799
5806
  ) -> int:
5800
- if self.hidd_boxes:
5801
- iid = self.hidd_boxes.pop()
5807
+ if not self.PAR.ops.rounded_boxes or not x2 - x1 or not y2 - y1:
5808
+ radius = 0
5809
+ else:
5810
+ radius = 8
5811
+ coords = rounded_box_coords(
5812
+ x1,
5813
+ y1,
5814
+ x2,
5815
+ y2,
5816
+ radius=radius,
5817
+ )
5818
+ if isinstance(iid, int):
5802
5819
  self.itemconfig(iid, fill=fill, outline=outline, state=state, tags=tags, width=width)
5803
- self.coords(iid, x1, y1, x2, y2)
5820
+ self.coords(iid, coords)
5804
5821
  else:
5805
- iid = self.create_rectangle(
5806
- x1,
5807
- y1,
5808
- x2,
5809
- y2,
5810
- fill=fill,
5811
- outline=outline,
5812
- state=state,
5813
- tags=tags,
5814
- width=width,
5815
- )
5816
- self.disp_boxes.add(iid)
5822
+ if self.hidd_boxes:
5823
+ iid = self.hidd_boxes.pop()
5824
+ self.itemconfig(iid, fill=fill, outline=outline, state=state, tags=tags, width=width)
5825
+ self.coords(iid, coords)
5826
+ else:
5827
+ iid = self.create_polygon(
5828
+ coords,
5829
+ fill=fill,
5830
+ outline=outline,
5831
+ state=state,
5832
+ tags=tags,
5833
+ width=width,
5834
+ smooth=True,
5835
+ )
5836
+ self.disp_boxes.add(iid)
5817
5837
  return iid
5818
5838
 
5819
5839
  def hide_box(self, item: int | None) -> None:
@@ -5823,7 +5843,7 @@ class MainTable(tk.Canvas):
5823
5843
  self.itemconfig(item, state="hidden")
5824
5844
 
5825
5845
  def hide_selection_box(self, item: int | None, set_current: bool = True) -> bool:
5826
- if item is None:
5846
+ if item is None or item is True:
5827
5847
  return
5828
5848
  box = self.selection_boxes.pop(item)
5829
5849
  self.hide_box(box.fill_iid)
@@ -5866,29 +5886,32 @@ class MainTable(tk.Canvas):
5866
5886
  elif type_ == "columns":
5867
5887
  mt_bg = self.PAR.ops.table_selected_columns_bg
5868
5888
  mt_border_col = self.PAR.ops.table_selected_columns_border_fg
5889
+ if self.selection_boxes:
5890
+ self.itemconfig(next(reversed(self.selection_boxes)), state="normal")
5891
+ x1, y1, x2, y2 = self.box_sheet_coords_x_canvas_coords(r1, c1, r2, c2, type_)
5869
5892
  fill_iid = self.display_box(
5870
- self.col_positions[c1],
5871
- self.row_positions[r1],
5872
- self.canvasx(self.winfo_width()) if self.PAR.ops.selected_rows_to_end_of_window else self.col_positions[c2],
5873
- self.row_positions[r2],
5893
+ x1,
5894
+ y1,
5895
+ x2,
5896
+ y2,
5874
5897
  fill=mt_bg,
5875
5898
  outline="",
5876
- state=state,
5899
+ state=state if self.PAR.ops.show_selected_cells_border else "normal",
5877
5900
  tags=type_,
5878
5901
  width=1,
5879
5902
  )
5880
5903
  index_iid = self.RI.display_box(
5881
- 0,
5882
- self.row_positions[r1],
5904
+ 1,
5905
+ y1,
5883
5906
  self.RI.current_width - 1,
5884
- self.row_positions[r2],
5907
+ y2,
5885
5908
  fill=self.PAR.ops.index_selected_rows_bg if type_ == "rows" else self.PAR.ops.index_selected_cells_bg,
5886
5909
  outline="",
5887
5910
  state="normal",
5888
5911
  tags="cells" if type_ == "columns" else type_,
5889
5912
  )
5890
5913
  header_iid = self.CH.display_box(
5891
- self.col_positions[c1],
5914
+ x1,
5892
5915
  0,
5893
5916
  self.col_positions[c2],
5894
5917
  self.CH.current_height - 1,
@@ -5905,10 +5928,10 @@ class MainTable(tk.Canvas):
5905
5928
  or self.selection_boxes
5906
5929
  ):
5907
5930
  bd_iid = self.display_box(
5908
- self.col_positions[c1],
5909
- self.row_positions[r1],
5910
- self.col_positions[c2],
5911
- self.row_positions[r2],
5931
+ x1,
5932
+ y1,
5933
+ x2,
5934
+ y2,
5912
5935
  fill="",
5913
5936
  outline=mt_border_col,
5914
5937
  state="normal",
@@ -5951,6 +5974,23 @@ class MainTable(tk.Canvas):
5951
5974
  if self.PAR.ops.show_selected_cells_border:
5952
5975
  self.tag_raise(self.selected.iid)
5953
5976
 
5977
+ def box_sheet_coords_x_canvas_coords(
5978
+ self,
5979
+ r1: int,
5980
+ c1: int,
5981
+ r2: int,
5982
+ c2: int,
5983
+ type_: Literal["cells", "rows", "columns"],
5984
+ ) -> tuple[float, float, float, float]:
5985
+ x1 = self.col_positions[c1]
5986
+ y1 = self.row_positions[r1]
5987
+ y2 = self.row_positions[r2]
5988
+ if type_ == "rows" and self.PAR.ops.selected_rows_to_end_of_window:
5989
+ x2 = self.canvasx(self.winfo_width())
5990
+ else:
5991
+ x2 = self.col_positions[c2]
5992
+ return x1, y1, x2, y2
5993
+
5954
5994
  def recreate_selection_box(
5955
5995
  self,
5956
5996
  r1: int,
@@ -5973,66 +6013,53 @@ class MainTable(tk.Canvas):
5973
6013
  mt_bg = self.PAR.ops.table_selected_columns_bg
5974
6014
  mt_border_col = self.PAR.ops.table_selected_columns_border_fg
5975
6015
  if not state:
5976
- state = "normal" if (r2 - r1 > 1 or c2 - c1 > 1) else "hidden"
6016
+ if r2 - r1 > 1 or c2 - c1 > 1:
6017
+ state = "normal"
6018
+ elif next(reversed(self.selection_boxes)) == fill_iid:
6019
+ state = "hidden"
6020
+ else:
6021
+ state = "normal"
5977
6022
  if self.selected.fill_iid == fill_iid:
5978
6023
  self.selected = self.selected._replace(box=Box_nt(r1, c1, r2, c2))
5979
- self.coords(
5980
- fill_iid,
5981
- self.col_positions[c1],
5982
- self.row_positions[r1],
5983
- self.canvasx(self.winfo_width()) if self.PAR.ops.selected_rows_to_end_of_window else self.col_positions[c2],
5984
- self.row_positions[r2],
5985
- )
5986
- self.itemconfig(
5987
- fill_iid,
5988
- fill=mt_bg,
5989
- outline="",
5990
- tags=type_,
5991
- state=state,
5992
- )
5993
- self.RI.coords(
5994
- self.selection_boxes[fill_iid].index,
5995
- 0,
5996
- self.row_positions[r1],
6024
+ x1, y1, x2, y2 = self.box_sheet_coords_x_canvas_coords(r1, c1, r2, c2, type_)
6025
+ self.display_box(x1, y1, x2, y2, fill=mt_bg, outline="", state=state, tags=type_, width=1, iid=fill_iid)
6026
+ self.RI.display_box(
6027
+ 1,
6028
+ y1,
5997
6029
  self.RI.current_width - 1,
5998
- self.row_positions[r2],
5999
- )
6000
- self.RI.itemconfig(
6001
- self.selection_boxes[fill_iid].index,
6030
+ y2,
6002
6031
  fill=self.PAR.ops.index_selected_rows_bg if type_ == "rows" else self.PAR.ops.index_selected_cells_bg,
6003
6032
  outline="",
6033
+ state="normal",
6004
6034
  tags="cells" if type_ == "columns" else type_,
6035
+ iid=self.selection_boxes[fill_iid].index,
6005
6036
  )
6006
- self.CH.coords(
6007
- self.selection_boxes[fill_iid].header,
6008
- self.col_positions[c1],
6037
+ self.CH.display_box(
6038
+ x1,
6009
6039
  0,
6010
6040
  self.col_positions[c2],
6011
6041
  self.CH.current_height - 1,
6012
- )
6013
- self.CH.itemconfig(
6014
- self.selection_boxes[fill_iid].header,
6015
6042
  fill=(
6016
6043
  self.PAR.ops.header_selected_columns_bg if type_ == "columns" else self.PAR.ops.header_selected_cells_bg
6017
6044
  ),
6018
6045
  outline="",
6046
+ state="normal",
6019
6047
  tags="cells" if type_ == "rows" else type_,
6048
+ iid=self.selection_boxes[fill_iid].header,
6020
6049
  )
6021
6050
  if bd_iid := self.selection_boxes[fill_iid].bd_iid:
6022
6051
  if self.PAR.ops.show_selected_cells_border:
6023
- self.coords(
6024
- bd_iid,
6025
- self.col_positions[c1],
6026
- self.row_positions[r1],
6027
- self.col_positions[c2],
6028
- self.row_positions[r2],
6029
- )
6030
- self.itemconfig(
6031
- bd_iid,
6052
+ self.display_box(
6053
+ x1,
6054
+ y1,
6055
+ x2,
6056
+ y2,
6032
6057
  fill="",
6033
6058
  outline=mt_border_col,
6034
- tags=f"{type_}bd",
6035
6059
  state="normal",
6060
+ tags=f"{type_}bd",
6061
+ width=1,
6062
+ iid=bd_iid,
6036
6063
  )
6037
6064
  self.tag_raise(bd_iid)
6038
6065
  else:
@@ -6079,23 +6106,23 @@ class MainTable(tk.Canvas):
6079
6106
  self.set_currently_selected(box.coords.from_r, box.coords.from_c, item=box.fill_iid)
6080
6107
 
6081
6108
  def get_redraw_selections(self, startr: int, endr: int, startc: int, endc: int) -> dict:
6082
- d = defaultdict(list)
6109
+ d = defaultdict(set)
6083
6110
  for item, box in self.get_selection_items():
6084
- d[box.type_].append(box.coords)
6085
- d2 = {}
6086
- if "cells" in d:
6087
- d2["cells"] = {
6088
- (r, c)
6089
- for r in range(startr, endr)
6090
- for c in range(startc, endc)
6091
- for r1, c1, r2, c2 in d["cells"]
6092
- if r1 <= r and c1 <= c and r2 > r and c2 > c
6093
- }
6094
- if "rows" in d:
6095
- d2["rows"] = {r for r in range(startr, endr) for r1, c1, r2, c2 in d["rows"] if r1 <= r and r2 > r}
6096
- if "columns" in d:
6097
- d2["columns"] = {c for c in range(startc, endc) for r1, c1, r2, c2 in d["columns"] if c1 <= c and c2 > c}
6098
- return d2
6111
+ r1, c1, r2, c2 = box.coords
6112
+ if box.type_ == "cells":
6113
+ for r in range(startr, endr):
6114
+ for c in range(startc, endc):
6115
+ if r1 <= r and c1 <= c and r2 > r and c2 > c:
6116
+ d["cells"].add((r, c))
6117
+ elif box.type_ == "rows":
6118
+ for r in range(startr, endr):
6119
+ if r1 <= r and r2 > r:
6120
+ d["rows"].add(r)
6121
+ elif box.type_ == "columns":
6122
+ for c in range(startc, endc):
6123
+ if c1 <= c and c2 > c:
6124
+ d["columns"].add(c)
6125
+ return d
6099
6126
 
6100
6127
  def get_selected_min_max(self) -> tuple[int, int, int, int] | tuple[None, None, None, None]:
6101
6128
  min_x = float("inf")
@@ -6119,168 +6146,62 @@ class MainTable(tk.Canvas):
6119
6146
  def get_selected_rows(
6120
6147
  self,
6121
6148
  get_cells: bool = False,
6122
- within_range: tuple | None = None,
6123
6149
  get_cells_as_rows: bool = False,
6124
6150
  ) -> set[int] | set[tuple[int, int]]:
6125
- s = set()
6126
- if within_range is not None:
6127
- within_r1 = within_range[0]
6128
- within_r2 = within_range[1]
6129
6151
  if get_cells:
6130
- if within_range is None:
6131
- for item, box in self.get_selection_items(cells=False, columns=False):
6132
- r1, c1, r2, c2 = box.coords
6133
- s.update(set(product(range(r1, r2), range(0, len(self.col_positions) - 1))))
6134
- if get_cells_as_rows:
6135
- s.update(self.get_selected_cells())
6136
- else:
6137
- for item, box in self.get_selection_items(cells=False, columns=False):
6138
- r1, c1, r2, c2 = box.coords
6139
- if r1 >= within_r1 or r2 <= within_r2:
6140
- s.update(
6141
- set(
6142
- product(
6143
- range(r1 if r1 > within_r1 else within_r1, r2 if r2 < within_r2 else within_r2),
6144
- range(0, len(self.col_positions) - 1),
6145
- )
6146
- )
6147
- )
6148
- if get_cells_as_rows:
6149
- s.update(
6150
- self.get_selected_cells(
6151
- within_range=(
6152
- within_r1,
6153
- 0,
6154
- within_r2,
6155
- len(self.col_positions) - 1,
6156
- )
6157
- )
6158
- )
6152
+ s = {
6153
+ (r, c)
6154
+ for item, box in self.get_selection_items(cells=False, columns=False)
6155
+ for r in range(box.coords.from_r, box.coords.upto_r)
6156
+ for c in range(0, len(self.col_positions) - 1)
6157
+ }
6158
+ if get_cells_as_rows:
6159
+ return s | self.get_selected_cells()
6159
6160
  else:
6160
- if within_range is None:
6161
- for item, box in self.get_selection_items(cells=False, columns=False):
6162
- r1, c1, r2, c2 = box.coords
6163
- s.update(set(range(r1, r2)))
6164
- if get_cells_as_rows:
6165
- s.update(set(tup[0] for tup in self.get_selected_cells()))
6166
- else:
6167
- for item, box in self.get_selection_items(cells=False, columns=False):
6168
- r1, c1, r2, c2 = box.coords
6169
- if r1 >= within_r1 or r2 <= within_r2:
6170
- s.update(set(range(r1 if r1 > within_r1 else within_r1, r2 if r2 < within_r2 else within_r2)))
6171
- if get_cells_as_rows:
6172
- s.update(
6173
- set(
6174
- tup[0]
6175
- for tup in self.get_selected_cells(
6176
- within_range=(
6177
- within_r1,
6178
- 0,
6179
- within_r2,
6180
- len(self.col_positions) - 1,
6181
- )
6182
- )
6183
- )
6184
- )
6161
+ s = {
6162
+ r
6163
+ for item, box in self.get_selection_items(cells=False, columns=False)
6164
+ for r in range(box.coords.from_r, box.coords.upto_r)
6165
+ }
6166
+ if get_cells_as_rows:
6167
+ return s | set(tup[0] for tup in self.get_selected_cells())
6185
6168
  return s
6186
6169
 
6187
6170
  def get_selected_cols(
6188
6171
  self,
6189
6172
  get_cells: bool = False,
6190
- within_range: tuple | None = None,
6191
6173
  get_cells_as_cols: bool = False,
6192
6174
  ) -> set[int] | set[tuple[int, int]]:
6193
- s = set()
6194
- if within_range is not None:
6195
- within_c1 = within_range[0]
6196
- within_c2 = within_range[1]
6197
6175
  if get_cells:
6198
- if within_range is None:
6199
- for item, box in self.get_selection_items(cells=False, rows=False):
6200
- r1, c1, r2, c2 = box.coords
6201
- s.update(set(product(range(c1, c2), range(0, len(self.row_positions) - 1))))
6202
- if get_cells_as_cols:
6203
- s.update(self.get_selected_cells())
6204
- else:
6205
- for item, box in self.get_selection_items(cells=False, rows=False):
6206
- r1, c1, r2, c2 = box.coords
6207
- if c1 >= within_c1 or c2 <= within_c2:
6208
- s.update(
6209
- set(
6210
- product(
6211
- range(c1 if c1 > within_c1 else within_c1, c2 if c2 < within_c2 else within_c2),
6212
- range(0, len(self.row_positions) - 1),
6213
- )
6214
- )
6215
- )
6216
- if get_cells_as_cols:
6217
- s.update(
6218
- self.get_selected_cells(
6219
- within_range=(
6220
- 0,
6221
- within_c1,
6222
- len(self.row_positions) - 1,
6223
- within_c2,
6224
- )
6225
- )
6226
- )
6176
+ s = {
6177
+ (r, c)
6178
+ for item, box in self.get_selection_items(cells=False, rows=False)
6179
+ for r in range(0, len(self.row_positions) - 1)
6180
+ for c in range(box.coords.from_c, box.coords.upto_c)
6181
+ }
6182
+ if get_cells_as_cols:
6183
+ return s | self.get_selected_cells()
6227
6184
  else:
6228
- if within_range is None:
6229
- for item, box in self.get_selection_items(cells=False, rows=False):
6230
- r1, c1, r2, c2 = box.coords
6231
- s.update(set(range(c1, c2)))
6232
- if get_cells_as_cols:
6233
- s.update(set(tup[1] for tup in self.get_selected_cells()))
6234
- else:
6235
- for item in self.get_selection_items(cells=False, rows=False):
6236
- r1, c1, r2, c2 = box.coords
6237
- if c1 >= within_c1 or c2 <= within_c2:
6238
- s.update(set(range(c1 if c1 > within_c1 else within_c1, c2 if c2 < within_c2 else within_c2)))
6239
- if get_cells_as_cols:
6240
- s.update(
6241
- set(
6242
- tup[0]
6243
- for tup in self.get_selected_cells(
6244
- within_range=(
6245
- 0,
6246
- within_c1,
6247
- len(self.row_positions) - 1,
6248
- within_c2,
6249
- )
6250
- )
6251
- )
6252
- )
6185
+ s = {
6186
+ c
6187
+ for item, box in self.get_selection_items(cells=False, rows=False)
6188
+ for c in range(box.coords.from_c, box.coords.upto_c)
6189
+ }
6190
+ if get_cells_as_cols:
6191
+ return s | set(tup[1] for tup in self.get_selected_cells())
6253
6192
  return s
6254
6193
 
6255
6194
  def get_selected_cells(
6256
6195
  self,
6257
6196
  get_rows: bool = False,
6258
6197
  get_cols: bool = False,
6259
- within_range: bool = None,
6260
6198
  ) -> set[tuple[int, int]]:
6261
- s = set()
6262
- if within_range is not None:
6263
- within_r1 = within_range[0]
6264
- within_c1 = within_range[1]
6265
- within_r2 = within_range[2]
6266
- within_c2 = within_range[3]
6267
- if within_range is None:
6268
- for item, box in self.get_selection_items(rows=get_rows, columns=get_cols):
6269
- r1, c1, r2, c2 = box.coords
6270
- s.update(set(product(range(r1, r2), range(c1, c2))))
6271
- else:
6272
- for item in self.get_selection_items(rows=get_rows, columns=get_cols):
6273
- r1, c1, r2, c2 = box.coords
6274
- if r1 >= within_r1 or c1 >= within_c1 or r2 <= within_r2 or c2 <= within_c2:
6275
- s.update(
6276
- set(
6277
- product(
6278
- range(r1 if r1 > within_r1 else within_r1, r2 if r2 < within_r2 else within_r2),
6279
- range(c1 if c1 > within_c1 else within_c1, c2 if c2 < within_c2 else within_c2),
6280
- )
6281
- )
6282
- )
6283
- return s
6199
+ return {
6200
+ (r, c)
6201
+ for item, box in self.get_selection_items(rows=get_rows, columns=get_cols)
6202
+ for r in range(box.coords.from_r, box.coords.upto_r)
6203
+ for c in range(box.coords.from_c, box.coords.upto_c)
6204
+ }
6284
6205
 
6285
6206
  def get_all_selection_boxes(self) -> tuple[tuple[int, int, int, int]]:
6286
6207
  return tuple(box.coords for item, box in self.get_selection_items())
@@ -6441,7 +6362,9 @@ class MainTable(tk.Canvas):
6441
6362
  sheet=self.PAR.name,
6442
6363
  key=extra_func_key,
6443
6364
  value=text,
6444
- loc=(r, c),
6365
+ loc=Loc(r, c),
6366
+ row=r,
6367
+ column=c,
6445
6368
  boxes=self.get_boxes(),
6446
6369
  selected=self.selected,
6447
6370
  )
@@ -6504,12 +6427,14 @@ class MainTable(tk.Canvas):
6504
6427
  self.text_editor.tktext.focus_set()
6505
6428
  self.text_editor.window.scroll_to_bottom()
6506
6429
  self.text_editor.tktext.bind("<Alt-Return>", lambda _x: self.text_editor_newline_binding(r, c))
6430
+ self.text_editor.tktext.bind("<Alt-KP_Enter>", lambda _x: self.text_editor_newline_binding(r, c))
6507
6431
  if USER_OS == "darwin":
6508
6432
  self.text_editor.tktext.bind("<Option-Return>", lambda _x: self.text_editor_newline_binding(r, c))
6509
6433
  for key, func in self.text_editor_user_bound_keys.items():
6510
6434
  self.text_editor.tktext.bind(key, func)
6511
6435
  self.text_editor.tktext.bind("<Tab>", lambda _x: self.close_text_editor((r, c, "Tab")))
6512
6436
  self.text_editor.tktext.bind("<Return>", lambda _x: self.close_text_editor((r, c, "Return")))
6437
+ self.text_editor.tktext.bind("<KP_Enter>", lambda _x: self.close_text_editor((r, c, "Return")))
6513
6438
  if not dropdown:
6514
6439
  self.text_editor.tktext.bind("<FocusOut>", lambda _x: self.close_text_editor((r, c, "FocusOut")))
6515
6440
  self.text_editor.tktext.bind("<Escape>", lambda _x: self.close_text_editor((r, c, "Escape")))
@@ -6599,6 +6524,8 @@ class MainTable(tk.Canvas):
6599
6524
 
6600
6525
  def hide_text_editor(self, reason: None | str = None) -> None:
6601
6526
  if self.text_editor.open:
6527
+ for binding in text_editor_to_unbind:
6528
+ self.text_editor.tktext.unbind(binding)
6602
6529
  self.itemconfig(self.text_editor.canvas_id, state="hidden")
6603
6530
  self.text_editor.open = False
6604
6531
  if reason == "Escape":
@@ -6621,16 +6548,18 @@ class MainTable(tk.Canvas):
6621
6548
  self.hide_text_editor_and_dropdown()
6622
6549
  return
6623
6550
  # setting cell data with text editor value
6624
- self.text_editor_value = self.text_editor.get()
6551
+ text_editor_value = self.text_editor.get()
6625
6552
  r, c = editor_info[0], editor_info[1]
6626
6553
  datarn, datacn = self.datarn(r), self.datacn(c)
6627
6554
  event_data = event_dict(
6628
6555
  name="end_edit_table",
6629
6556
  sheet=self.PAR.name,
6630
- cells_table={(datarn, datacn): self.text_editor_value},
6557
+ cells_table={(datarn, datacn): text_editor_value},
6631
6558
  key=editor_info[2],
6632
- value=self.text_editor_value,
6633
- loc=(r, c),
6559
+ value=text_editor_value,
6560
+ loc=Loc(r, c),
6561
+ row=r,
6562
+ column=c,
6634
6563
  boxes=self.get_boxes(),
6635
6564
  selected=self.selected,
6636
6565
  )
@@ -6645,11 +6574,11 @@ class MainTable(tk.Canvas):
6645
6574
  check_input_valid=False,
6646
6575
  )
6647
6576
  if self.edit_validation_func:
6648
- self.text_editor_value = self.edit_validation_func(event_data)
6649
- if self.text_editor_value is not None and self.input_valid_for_cell(datarn, datacn, self.text_editor_value):
6650
- edited = set_data(value=self.text_editor_value)
6651
- elif self.input_valid_for_cell(datarn, datacn, self.text_editor_value):
6652
- edited = set_data(value=self.text_editor_value)
6577
+ text_editor_value = self.edit_validation_func(event_data)
6578
+ if text_editor_value is not None and self.input_valid_for_cell(datarn, datacn, text_editor_value):
6579
+ edited = set_data(value=text_editor_value)
6580
+ elif self.input_valid_for_cell(datarn, datacn, text_editor_value):
6581
+ edited = set_data(value=text_editor_value)
6653
6582
  if edited:
6654
6583
  try_binding(self.extra_end_edit_cell_func, event_data)
6655
6584
  if (
@@ -6659,7 +6588,7 @@ class MainTable(tk.Canvas):
6659
6588
  and r == self.selected.row
6660
6589
  and c == self.selected.column
6661
6590
  and (self.single_selection_enabled or self.toggle_selection_enabled)
6662
- and (edited or self.cell_equal_to(datarn, datacn, self.text_editor_value))
6591
+ and (edited or self.cell_equal_to(datarn, datacn, text_editor_value))
6663
6592
  ):
6664
6593
  r1, c1, r2, c2 = self.selection_boxes[self.selected.fill_iid].coords
6665
6594
  numcols = c2 - c1
@@ -6881,7 +6810,9 @@ class MainTable(tk.Canvas):
6881
6810
  name="table_dropdown_modified",
6882
6811
  sheet=self.PAR.name,
6883
6812
  value=self.text_editor.get(),
6884
- loc=(r, c),
6813
+ loc=Loc(r, c),
6814
+ row=r,
6815
+ column=c,
6885
6816
  boxes=self.get_boxes(),
6886
6817
  selected=self.selected,
6887
6818
  )
@@ -6924,7 +6855,9 @@ class MainTable(tk.Canvas):
6924
6855
  cells_table={(datarn, datacn): pre_edit_value},
6925
6856
  key="??",
6926
6857
  value=selection,
6927
- loc=(r, c),
6858
+ loc=Loc(r, c),
6859
+ row=r,
6860
+ column=c,
6928
6861
  boxes=self.get_boxes(),
6929
6862
  selected=self.selected,
6930
6863
  )
@@ -6977,6 +6910,7 @@ class MainTable(tk.Canvas):
6977
6910
 
6978
6911
  def hide_dropdown_window(self) -> None:
6979
6912
  if self.dropdown.open:
6913
+ self.dropdown.window.unbind("<FocusOut>")
6980
6914
  self.itemconfig(self.dropdown.canvas_id, state="hidden")
6981
6915
  self.dropdown.open = False
6982
6916
 
@@ -7011,7 +6945,9 @@ class MainTable(tk.Canvas):
7011
6945
  cells_table={(datarn, datacn): pre_edit_value},
7012
6946
  key="??",
7013
6947
  value=value,
7014
- loc=(r, c),
6948
+ loc=Loc(r, c),
6949
+ row=r,
6950
+ column=c,
7015
6951
  boxes=self.get_boxes(),
7016
6952
  selected=self.selected,
7017
6953
  )
@@ -7028,12 +6964,14 @@ class MainTable(tk.Canvas):
7028
6964
  c: int = 0,
7029
6965
  datarn: int | None = None,
7030
6966
  datacn: int | None = None,
7031
- value: str = "",
6967
+ value: str | None = None,
7032
6968
  undo: bool = True,
7033
6969
  cell_resize: bool = True,
7034
6970
  redraw: bool = True,
7035
6971
  check_input_valid: bool = True,
7036
6972
  ) -> bool:
6973
+ if value is None:
6974
+ value = ""
7037
6975
  if datacn is None:
7038
6976
  datacn = self.datacn(c)
7039
6977
  if datarn is None:
@@ -7128,7 +7066,7 @@ class MainTable(tk.Canvas):
7128
7066
 
7129
7067
  def fix_data_len(self, datarn: int, datacn: int | None = None) -> int:
7130
7068
  ncols = self.total_data_cols() if datacn is None else datacn + 1
7131
- self.data.extend([self.get_empty_row_seq(rn, end=ncols, start=0) for rn in range(len(self.data), datarn + 1)])
7069
+ self.data.extend(self.get_empty_row_seq(rn, end=ncols, start=0) for rn in range(len(self.data), datarn + 1))
7132
7070
  return len(self.data)
7133
7071
 
7134
7072
  def reapply_formatting(self) -> None: