tksheet 7.2.21__py3-none-any.whl → 7.2.23__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
@@ -51,7 +51,9 @@ from .formatters import (
51
51
  from .functions import (
52
52
  add_to_displayed,
53
53
  b_index,
54
+ box_is_single_cell,
54
55
  cell_right_within_box,
56
+ color_tup,
55
57
  consecutive_ranges,
56
58
  diff_gen,
57
59
  diff_list,
@@ -72,9 +74,9 @@ from .functions import (
72
74
  mod_span_widget,
73
75
  move_elements_by_mapping,
74
76
  new_tk_event,
75
- stored_event_dict,
76
77
  rounded_box_coords,
77
78
  span_idxs_post_move,
79
+ stored_event_dict,
78
80
  try_binding,
79
81
  unpickle_obj,
80
82
  )
@@ -1512,25 +1514,49 @@ class MainTable(tk.Canvas):
1512
1514
  self.purge_redo_stack()
1513
1515
 
1514
1516
  def edit_cells_using_modification(self, modification: dict, event_data: dict) -> EventDataDict:
1517
+ # row index
1515
1518
  if self.PAR.ops.treeview:
1516
1519
  for datarn, v in modification["cells"]["index"].items():
1517
- self._row_index[datarn].text = v
1520
+ if not self.edit_validation_func or (
1521
+ self.edit_validation_func
1522
+ and (v := self.edit_validation_func(mod_event_val(event_data, v, row=datarn))) is not None
1523
+ ):
1524
+ self._row_index[datarn].text = v
1518
1525
  else:
1519
1526
  for datarn, v in modification["cells"]["index"].items():
1520
- self._row_index[datarn] = v
1527
+ if not self.edit_validation_func or (
1528
+ self.edit_validation_func
1529
+ and (v := self.edit_validation_func(mod_event_val(event_data, v, row=datarn))) is not None
1530
+ ):
1531
+ self._row_index[datarn] = v
1532
+
1533
+ # header
1521
1534
  for datacn, v in modification["cells"]["header"].items():
1522
- self._headers[datacn] = v
1523
- for (datarn, datacn), v in modification["cells"]["table"].items():
1524
- self.set_cell_data(datarn, datacn, v)
1535
+ if not self.edit_validation_func or (
1536
+ self.edit_validation_func
1537
+ and (v := self.edit_validation_func(mod_event_val(event_data, v, column=datacn))) is not None
1538
+ ):
1539
+ self._headers[datacn] = v
1540
+
1541
+ # table
1542
+ for k, v in modification["cells"]["table"].items():
1543
+ if not self.edit_validation_func or (
1544
+ self.edit_validation_func
1545
+ and (v := self.edit_validation_func(mod_event_val(event_data, v, loc=k))) is not None
1546
+ ):
1547
+ self.set_cell_data(k[0], k[1], v)
1548
+
1525
1549
  return event_data
1526
1550
 
1527
1551
  def save_cells_using_modification(self, modification: EventDataDict, event_data: EventDataDict) -> EventDataDict:
1528
- for datarn, v in modification["cells"]["index"].items():
1552
+ for datarn in modification["cells"]["index"]:
1529
1553
  event_data["cells"]["index"][datarn] = self.RI.get_cell_data(datarn)
1530
- for datacn, v in modification["cells"]["header"].items():
1554
+
1555
+ for datacn in modification["cells"]["header"]:
1531
1556
  event_data["cells"]["header"][datacn] = self.CH.get_cell_data(datacn)
1532
- for (datarn, datacn), v in modification["cells"]["table"].items():
1533
- event_data["cells"]["table"][(datarn, datacn)] = self.get_cell_data(datarn, datacn)
1557
+
1558
+ for k in modification["cells"]["table"]:
1559
+ event_data["cells"]["table"][k] = self.get_cell_data(k[0], k[1])
1534
1560
  return event_data
1535
1561
 
1536
1562
  def restore_options_named_spans(self, modification: EventDataDict) -> None:
@@ -2760,7 +2786,7 @@ class MainTable(tk.Canvas):
2760
2786
  self.rc_insert_row_enabled = True
2761
2787
  self.rc_popup_menus_enabled = True
2762
2788
  self.rc_select_enabled = True
2763
- if binding in ("all", "right_click_popup_menu", "rc_popup_menu"):
2789
+ if binding in ("all", "right_click_popup_menu", "rc_popup_menu", "rc_menu"):
2764
2790
  self.rc_popup_menus_enabled = True
2765
2791
  self.rc_select_enabled = True
2766
2792
  if binding in ("all", "right_click_select", "rc_select"):
@@ -2823,7 +2849,7 @@ class MainTable(tk.Canvas):
2823
2849
  self.rc_insert_column_enabled = False
2824
2850
  if binding in bind_add_rows:
2825
2851
  self.rc_insert_row_enabled = False
2826
- if binding in ("all", "right_click_popup_menu", "rc_popup_menu"):
2852
+ if binding in ("all", "right_click_popup_menu", "rc_popup_menu", "rc_menu"):
2827
2853
  self.rc_popup_menus_enabled = False
2828
2854
  if binding in ("all", "right_click_select", "rc_select"):
2829
2855
  self.rc_select_enabled = False
@@ -3165,9 +3191,10 @@ class MainTable(tk.Canvas):
3165
3191
  self.b1_motion(event)
3166
3192
 
3167
3193
  def b1_release(self, event=None):
3194
+ to_hide = self.being_drawn_item
3168
3195
  if self.being_drawn_item is not None and (to_sel := self.coords_and_type(self.being_drawn_item)):
3169
3196
  r_to_sel, c_to_sel = self.selected.row, self.selected.column
3170
- self.hide_selection_box(self.being_drawn_item)
3197
+ self.being_drawn_item = None
3171
3198
  self.set_currently_selected(
3172
3199
  r_to_sel,
3173
3200
  c_to_sel,
@@ -3180,12 +3207,9 @@ class MainTable(tk.Canvas):
3180
3207
  ),
3181
3208
  set_current=False,
3182
3209
  ),
3210
+ run_binding=False,
3183
3211
  )
3184
- sel_event = self.get_select_event(being_drawn_item=self.being_drawn_item)
3185
- try_binding(self.drag_selection_binding_func, sel_event)
3186
- self.PAR.emit_event("<<SheetSelect>>", data=sel_event)
3187
- else:
3188
- self.being_drawn_item = None
3212
+ self.hide_selection_box(to_hide)
3189
3213
  if self.RI.width_resizing_enabled and self.RI.rsz_w is not None and self.RI.currently_resizing_width:
3190
3214
  self.delete_resize_lines()
3191
3215
  self.RI.delete_resize_lines()
@@ -5157,69 +5181,82 @@ class MainTable(tk.Canvas):
5157
5181
  fr: int | float,
5158
5182
  sc: int | float,
5159
5183
  sr: int | float,
5160
- c_2_: tuple[int, int, int],
5161
- c_3_: tuple[int, int, int],
5162
- c_4_: tuple[int, int, int],
5184
+ sel_cells_bg: tuple[int, int, int],
5185
+ sel_cols_bg: tuple[int, int, int],
5186
+ sel_rows_bg: tuple[int, int, int],
5163
5187
  selections: dict,
5164
5188
  datarn: int,
5165
5189
  datacn: int,
5166
5190
  can_width: int | None,
5191
+ dont_blend: bool,
5192
+ alternate_color: Highlight | None,
5167
5193
  ) -> str:
5168
5194
  redrawn = False
5169
5195
  if (datarn, datacn) in self.progress_bars:
5170
5196
  kwargs = self.progress_bars[(datarn, datacn)]
5171
5197
  else:
5172
5198
  kwargs = self.get_cell_kwargs(datarn, datacn, key="highlight")
5173
- if not kwargs and (self.PAR.ops.alternate_color and r % 2):
5174
- kwargs = Highlight(
5175
- bg=self.PAR.ops.alternate_color,
5176
- fg=None,
5177
- end=False,
5178
- )
5199
+ if alt := bool(not kwargs and alternate_color and r % 2):
5200
+ kwargs = alternate_color
5201
+
5179
5202
  if kwargs:
5180
- if kwargs[0] is not None:
5181
- c_1 = kwargs[0] if kwargs[0].startswith("#") else color_map[kwargs[0]]
5182
- if "cells" in selections and (r, c) in selections["cells"]:
5183
- tf = (
5203
+ fill = kwargs[0]
5204
+ if fill and not fill.startswith("#"):
5205
+ fill = color_map[fill]
5206
+
5207
+ # cell is a single currently selected cell box
5208
+ # not highlighted
5209
+ # on an alternate row color
5210
+ if alt and dont_blend:
5211
+ txtfg = self.PAR.ops.table_fg
5212
+
5213
+ # cell is highlighted and cell selected
5214
+ elif "cells" in selections and (r, c) in selections["cells"]:
5215
+ txtfg = (
5184
5216
  self.PAR.ops.table_selected_cells_fg
5185
5217
  if kwargs[1] is None or self.PAR.ops.display_selected_fg_over_highlights
5186
5218
  else kwargs[1]
5187
5219
  )
5188
- if kwargs[0] is not None:
5220
+ if fill:
5189
5221
  fill = (
5190
- f"#{int((int(c_1[1:3], 16) + c_2_[0]) / 2):02X}"
5191
- + f"{int((int(c_1[3:5], 16) + c_2_[1]) / 2):02X}"
5192
- + f"{int((int(c_1[5:], 16) + c_2_[2]) / 2):02X}"
5222
+ f"#{int((int(fill[1:3], 16) + sel_cells_bg[0]) / 2):02X}"
5223
+ + f"{int((int(fill[3:5], 16) + sel_cells_bg[1]) / 2):02X}"
5224
+ + f"{int((int(fill[5:], 16) + sel_cells_bg[2]) / 2):02X}"
5193
5225
  )
5226
+
5227
+ # cell is highlighted and row selected
5194
5228
  elif "rows" in selections and r in selections["rows"]:
5195
- tf = (
5229
+ txtfg = (
5196
5230
  self.PAR.ops.table_selected_rows_fg
5197
5231
  if kwargs[1] is None or self.PAR.ops.display_selected_fg_over_highlights
5198
5232
  else kwargs[1]
5199
5233
  )
5200
- if kwargs[0] is not None:
5234
+ if fill:
5201
5235
  fill = (
5202
- f"#{int((int(c_1[1:3], 16) + c_4_[0]) / 2):02X}"
5203
- + f"{int((int(c_1[3:5], 16) + c_4_[1]) / 2):02X}"
5204
- + f"{int((int(c_1[5:], 16) + c_4_[2]) / 2):02X}"
5236
+ f"#{int((int(fill[1:3], 16) + sel_rows_bg[0]) / 2):02X}"
5237
+ + f"{int((int(fill[3:5], 16) + sel_rows_bg[1]) / 2):02X}"
5238
+ + f"{int((int(fill[5:], 16) + sel_rows_bg[2]) / 2):02X}"
5205
5239
  )
5240
+
5241
+ # cell is highlighted and column selected
5206
5242
  elif "columns" in selections and c in selections["columns"]:
5207
- tf = (
5243
+ txtfg = (
5208
5244
  self.PAR.ops.table_selected_columns_fg
5209
5245
  if kwargs[1] is None or self.PAR.ops.display_selected_fg_over_highlights
5210
5246
  else kwargs[1]
5211
5247
  )
5212
- if kwargs[0] is not None:
5248
+ if fill:
5213
5249
  fill = (
5214
- f"#{int((int(c_1[1:3], 16) + c_3_[0]) / 2):02X}"
5215
- + f"{int((int(c_1[3:5], 16) + c_3_[1]) / 2):02X}"
5216
- + f"{int((int(c_1[5:], 16) + c_3_[2]) / 2):02X}"
5250
+ f"#{int((int(fill[1:3], 16) + sel_cols_bg[0]) / 2):02X}"
5251
+ + f"{int((int(fill[3:5], 16) + sel_cols_bg[1]) / 2):02X}"
5252
+ + f"{int((int(fill[5:], 16) + sel_cols_bg[2]) / 2):02X}"
5217
5253
  )
5254
+
5255
+ # cell is just highlighted
5218
5256
  else:
5219
- tf = self.PAR.ops.table_fg if kwargs[1] is None else kwargs[1]
5220
- if kwargs[0] is not None:
5221
- fill = kwargs[0]
5222
- if kwargs[0] is not None:
5257
+ txtfg = self.PAR.ops.table_fg if kwargs[1] is None else kwargs[1]
5258
+
5259
+ if fill:
5223
5260
  highlight_fn = partial(
5224
5261
  self.redraw_highlight,
5225
5262
  x1=fc + 1,
@@ -5249,14 +5286,14 @@ class MainTable(tk.Canvas):
5249
5286
  )
5250
5287
  elif not kwargs:
5251
5288
  if "cells" in selections and (r, c) in selections["cells"]:
5252
- tf = self.PAR.ops.table_selected_cells_fg
5289
+ txtfg = self.PAR.ops.table_selected_cells_fg
5253
5290
  elif "rows" in selections and r in selections["rows"]:
5254
- tf = self.PAR.ops.table_selected_rows_fg
5291
+ txtfg = self.PAR.ops.table_selected_rows_fg
5255
5292
  elif "columns" in selections and c in selections["columns"]:
5256
- tf = self.PAR.ops.table_selected_columns_fg
5293
+ txtfg = self.PAR.ops.table_selected_columns_fg
5257
5294
  else:
5258
- tf = self.PAR.ops.table_fg
5259
- return tf, redrawn
5295
+ txtfg = self.PAR.ops.table_fg
5296
+ return txtfg, redrawn
5260
5297
 
5261
5298
  def redraw_highlight(self, x1, y1, x2, y2, fill, outline, tag, can_width=None, pc=None):
5262
5299
  if not is_type_int(pc) or pc >= 100:
@@ -5638,24 +5675,36 @@ class MainTable(tk.Canvas):
5638
5675
  )
5639
5676
  if redraw_table:
5640
5677
  selections = self.get_redraw_selections(text_start_row, grid_end_row, text_start_col, grid_end_col)
5641
- c_2 = (
5642
- self.PAR.ops.table_selected_cells_bg
5643
- if self.PAR.ops.table_selected_cells_bg.startswith("#")
5644
- else color_map[self.PAR.ops.table_selected_cells_bg]
5645
- )
5646
- c_2_ = (int(c_2[1:3], 16), int(c_2[3:5], 16), int(c_2[5:], 16))
5647
- c_3 = (
5648
- self.PAR.ops.table_selected_columns_bg
5649
- if self.PAR.ops.table_selected_columns_bg.startswith("#")
5650
- else color_map[self.PAR.ops.table_selected_columns_bg]
5651
- )
5652
- c_3_ = (int(c_3[1:3], 16), int(c_3[3:5], 16), int(c_3[5:], 16))
5653
- c_4 = (
5654
- self.PAR.ops.table_selected_rows_bg
5655
- if self.PAR.ops.table_selected_rows_bg.startswith("#")
5656
- else color_map[self.PAR.ops.table_selected_rows_bg]
5657
- )
5658
- c_4_ = (int(c_4[1:3], 16), int(c_4[3:5], 16), int(c_4[5:], 16))
5678
+ sel_cells_bg = color_tup(self.PAR.ops.table_selected_cells_bg)
5679
+ sel_cols_bg = color_tup(self.PAR.ops.table_selected_columns_bg)
5680
+ sel_rows_bg = color_tup(self.PAR.ops.table_selected_rows_bg)
5681
+ if self.selected:
5682
+ current_loc = (self.selected.row, self.selected.column)
5683
+ else:
5684
+ current_loc = tuple()
5685
+ if self.PAR.ops.alternate_color:
5686
+ alternate_color = Highlight(
5687
+ bg=self.PAR.ops.alternate_color,
5688
+ fg=None,
5689
+ end=False,
5690
+ )
5691
+ if self.selected and box_is_single_cell(*self.selected.box) and self.PAR.ops.show_selected_cells_border:
5692
+ dont_blend = current_loc
5693
+ else:
5694
+ dont_blend = tuple()
5695
+ else:
5696
+ alternate_color = None
5697
+ dont_blend = tuple()
5698
+
5699
+ if not self.PAR.ops.show_selected_cells_border:
5700
+ override = (
5701
+ color_tup(self.PAR.ops.table_selected_cells_fg),
5702
+ color_tup(self.PAR.ops.table_selected_columns_fg),
5703
+ color_tup(self.PAR.ops.table_selected_rows_fg),
5704
+ )
5705
+ else:
5706
+ override = tuple()
5707
+
5659
5708
  rows_ = tuple(range(text_start_row, text_end_row))
5660
5709
  font = self.PAR.ops.table_font
5661
5710
  dd_coords = self.dropdown.get_coords()
@@ -5672,19 +5721,21 @@ class MainTable(tk.Canvas):
5672
5721
  datacn = self.datacn(c)
5673
5722
 
5674
5723
  fill, dd_drawn = self.redraw_highlight_get_text_fg(
5675
- r,
5676
- c,
5677
- cleftgridln,
5678
- rtopgridln,
5679
- crightgridln,
5680
- rbotgridln,
5681
- c_2_,
5682
- c_3_,
5683
- c_4_,
5684
- selections,
5685
- datarn,
5686
- datacn,
5687
- can_width,
5724
+ r=r,
5725
+ c=c,
5726
+ fc=cleftgridln,
5727
+ fr=rtopgridln,
5728
+ sc=crightgridln,
5729
+ sr=rbotgridln,
5730
+ sel_cells_bg=override[0] if override and (r, c) == current_loc else sel_cells_bg,
5731
+ sel_cols_bg=override[1] if override and (r, c) == current_loc else sel_cols_bg,
5732
+ sel_rows_bg=override[2] if override and (r, c) == current_loc else sel_rows_bg,
5733
+ selections=selections,
5734
+ datarn=datarn,
5735
+ datacn=datacn,
5736
+ can_width=can_width,
5737
+ dont_blend=(r, c) == dont_blend,
5738
+ alternate_color=alternate_color,
5688
5739
  )
5689
5740
  align = self.get_cell_kwargs(datarn, datacn, key="align")
5690
5741
  if align:
@@ -5701,7 +5752,7 @@ class MainTable(tk.Canvas):
5701
5752
  rtopgridln,
5702
5753
  crightgridln,
5703
5754
  self.row_positions[r + 1],
5704
- fill=fill,
5755
+ fill=fill if kwargs["state"] != "disabled" else self.PAR.ops.table_grid_fg,
5705
5756
  outline=fill,
5706
5757
  tag=f"dd_{r}_{c}",
5707
5758
  draw_outline=not dd_drawn,
@@ -5719,7 +5770,7 @@ class MainTable(tk.Canvas):
5719
5770
  rtopgridln,
5720
5771
  crightgridln,
5721
5772
  self.row_positions[r + 1],
5722
- fill=fill,
5773
+ fill=fill if kwargs["state"] != "disabled" else self.PAR.ops.table_grid_fg,
5723
5774
  outline=fill,
5724
5775
  tag=f"dd_{r}_{c}",
5725
5776
  draw_outline=not dd_drawn,
@@ -5738,7 +5789,7 @@ class MainTable(tk.Canvas):
5738
5789
  rtopgridln,
5739
5790
  crightgridln,
5740
5791
  self.row_positions[r + 1],
5741
- fill=fill,
5792
+ fill=fill if kwargs["state"] != "disabled" else self.PAR.ops.table_grid_fg,
5742
5793
  outline=fill,
5743
5794
  tag=f"dd_{r}_{c}",
5744
5795
  draw_outline=not dd_drawn,
@@ -6107,7 +6158,7 @@ class MainTable(tk.Canvas):
6107
6158
  self.itemconfig(item, state="hidden")
6108
6159
 
6109
6160
  def hide_selection_box(self, item: int | None) -> bool:
6110
- if item is None or item is True:
6161
+ if item is None or item is True or item not in self.selection_boxes:
6111
6162
  return
6112
6163
  box = self.selection_boxes.pop(item)
6113
6164
  self.hide_box(box.fill_iid)
@@ -6681,7 +6732,6 @@ class MainTable(tk.Canvas):
6681
6732
  h = self.row_positions[r + 1] - y + 1
6682
6733
  if text is None:
6683
6734
  text = f"{self.get_cell_data(self.datarn(r), self.datacn(c), none_to_empty_str = True)}"
6684
- bg, fg = self.PAR.ops.table_bg, self.PAR.ops.table_fg
6685
6735
  kwargs = {
6686
6736
  "menu_kwargs": DotDict(
6687
6737
  {
@@ -6699,8 +6749,10 @@ class MainTable(tk.Canvas):
6699
6749
  "width": w,
6700
6750
  "height": h,
6701
6751
  "show_border": True,
6702
- "bg": bg,
6703
- "fg": fg,
6752
+ "bg": self.PAR.ops.table_editor_bg,
6753
+ "fg": self.PAR.ops.table_editor_fg,
6754
+ "select_bg": self.PAR.ops.table_editor_select_bg,
6755
+ "select_fg": self.PAR.ops.table_editor_select_fg,
6704
6756
  "align": self.get_cell_align(r, c),
6705
6757
  "r": r,
6706
6758
  "c": c,
@@ -6904,6 +6956,8 @@ class MainTable(tk.Canvas):
6904
6956
  new_r, new_c = down_cell_within_box(r, c, r1, c1, r2, c2, numrows, numcols)
6905
6957
  else:
6906
6958
  new_r, new_c = None, None
6959
+ else:
6960
+ new_r, new_c = None, None
6907
6961
  if isinstance(new_r, int):
6908
6962
  self.set_currently_selected(new_r, new_c, item=self.selected.fill_iid)
6909
6963
  self.see(
@@ -6958,6 +7012,8 @@ class MainTable(tk.Canvas):
6958
7012
  bottom_right_corner=True,
6959
7013
  check_cell_visibility=True,
6960
7014
  )
7015
+ if not self.PAR.ops.show_selected_cells_border:
7016
+ self.refresh()
6961
7017
  return "break"
6962
7018
 
6963
7019
  def get_space_bot(self, r: int, text_editor_h: int | None = None) -> int:
@@ -7015,15 +7071,29 @@ class MainTable(tk.Canvas):
7015
7071
 
7016
7072
  def dropdown_text_editor_modified(
7017
7073
  self,
7018
- dd_window: object,
7019
- event: dict,
7020
- modified_func: Callable | None,
7074
+ event: tk.Misc,
7021
7075
  ) -> None:
7022
- if modified_func:
7023
- modified_func(event)
7024
- dd_window.search_and_see(event)
7076
+ r, c = self.dropdown.get_coords()
7077
+ event_data = event_dict(
7078
+ name="table_dropdown_modified",
7079
+ sheet=self.PAR.name,
7080
+ value=self.text_editor.get(),
7081
+ loc=Loc(r, c),
7082
+ row=r,
7083
+ column=c,
7084
+ boxes=self.get_boxes(),
7085
+ selected=self.selected,
7086
+ )
7087
+ try_binding(self.dropdown.window.modified_function, event_data)
7088
+ # return to tk.Text action if control/command is held down
7089
+ # or keysym was not a character
7090
+ if (hasattr(event, "state") and event.state & (0x0004 | 0x00000010)) or (
7091
+ hasattr(event, "keysym") and len(event.keysym) > 2 and event.keysym != "space"
7092
+ ):
7093
+ return
7094
+ self.text_editor.autocomplete(self.dropdown.window.search_and_see(event_data))
7095
+ return "break"
7025
7096
 
7026
- # c is displayed col
7027
7097
  def open_dropdown_window(
7028
7098
  self,
7029
7099
  r: int,
@@ -7034,9 +7104,10 @@ class MainTable(tk.Canvas):
7034
7104
  datarn = self.datarn(r)
7035
7105
  datacn = self.datacn(c)
7036
7106
  kwargs = self.get_cell_kwargs(datarn, datacn, key="dropdown")
7037
- if kwargs["state"] == "normal":
7038
- if not self.open_text_editor(event=event, r=r, c=c, dropdown=True):
7039
- return
7107
+ if kwargs["state"] == "disabled":
7108
+ return
7109
+ if kwargs["state"] == "normal" and not self.open_text_editor(event=event, r=r, c=c, dropdown=True):
7110
+ return
7040
7111
  win_h, anchor = self.get_dropdown_height_anchor(r, c)
7041
7112
  win_w = self.col_positions[c + 1] - self.col_positions[c] + 1
7042
7113
  if anchor == "nw":
@@ -7050,6 +7121,10 @@ class MainTable(tk.Canvas):
7050
7121
  reset_kwargs = {
7051
7122
  "r": r,
7052
7123
  "c": c,
7124
+ "bg": self.PAR.ops.table_editor_bg,
7125
+ "fg": self.PAR.ops.table_editor_fg,
7126
+ "select_bg": self.PAR.ops.table_editor_select_bg,
7127
+ "select_fg": self.PAR.ops.table_editor_select_fg,
7053
7128
  "width": win_w,
7054
7129
  "height": win_h,
7055
7130
  "font": self.PAR.ops.table_font,
@@ -7057,6 +7132,8 @@ class MainTable(tk.Canvas):
7057
7132
  "outline_color": self.get_selected_box_bg_fg(type_="cells")[1],
7058
7133
  "align": self.get_cell_align(r, c),
7059
7134
  "values": kwargs["values"],
7135
+ "search_function": kwargs["search_function"],
7136
+ "modified_function": kwargs["modified_function"],
7060
7137
  }
7061
7138
  if self.dropdown.window:
7062
7139
  self.dropdown.window.reset(**reset_kwargs)
@@ -7068,7 +7145,6 @@ class MainTable(tk.Canvas):
7068
7145
  self.winfo_toplevel(),
7069
7146
  **reset_kwargs,
7070
7147
  close_dropdown_window=self.close_dropdown_window,
7071
- search_function=kwargs["search_function"],
7072
7148
  arrowkey_RIGHT=self.arrowkey_RIGHT,
7073
7149
  arrowkey_LEFT=self.arrowkey_LEFT,
7074
7150
  )
@@ -7077,25 +7153,12 @@ class MainTable(tk.Canvas):
7077
7153
  window=self.dropdown.window,
7078
7154
  anchor=anchor,
7079
7155
  )
7156
+ self.update_idletasks()
7080
7157
  if kwargs["state"] == "normal":
7081
7158
  self.text_editor.tktext.bind(
7082
- "<<TextModified>>",
7083
- lambda _: self.dropdown.window.search_and_see(
7084
- event_dict(
7085
- name="table_dropdown_modified",
7086
- sheet=self.PAR.name,
7087
- value=self.text_editor.get(),
7088
- loc=Loc(r, c),
7089
- row=r,
7090
- column=c,
7091
- boxes=self.get_boxes(),
7092
- selected=self.selected,
7093
- )
7094
- ),
7159
+ "<KeyRelease>",
7160
+ self.dropdown_text_editor_modified,
7095
7161
  )
7096
- if kwargs["modified_function"] is not None:
7097
- self.dropdown.window.modified_function = kwargs["modified_function"]
7098
- self.update_idletasks()
7099
7162
  try:
7100
7163
  self.after(1, lambda: self.text_editor.tktext.focus())
7101
7164
  self.after(2, self.text_editor.window.scroll_to_bottom())
@@ -7103,7 +7166,6 @@ class MainTable(tk.Canvas):
7103
7166
  return
7104
7167
  redraw = False
7105
7168
  else:
7106
- self.update_idletasks()
7107
7169
  self.dropdown.window.bind("<FocusOut>", lambda _: self.close_dropdown_window(r, c))
7108
7170
  self.dropdown.window.bind("<Escape>", self.close_dropdown_window)
7109
7171
  self.dropdown.window.focus_set()
tksheet/other_classes.py CHANGED
@@ -5,6 +5,7 @@ from collections import namedtuple
5
5
  from collections.abc import Callable, Generator, Hashable, Iterator
6
6
  from functools import partial
7
7
  from typing import Literal
8
+ import tkinter as tk
8
9
 
9
10
  pickle_obj = partial(pickle.dumps, protocol=pickle.HIGHEST_PROTOCOL)
10
11
 
@@ -18,7 +19,7 @@ Box_t = namedtuple(
18
19
  "from_r from_c upto_r upto_c type_",
19
20
  )
20
21
  Box_st = namedtuple("Box_st", "coords type_")
21
- Loc = namedtuple("Loc", "row column")
22
+ Loc = namedtuple("Loc", "row column", defaults=(None, None))
22
23
 
23
24
  Highlight = namedtuple(
24
25
  "Highlight",
@@ -490,6 +491,25 @@ class TextEditorStorage:
490
491
  return self.window.get()
491
492
  return ""
492
493
 
494
+ def set(self, value: str) -> None:
495
+ if not self.window:
496
+ return
497
+ self.window.set_text(value)
498
+
499
+ def highlight_from(self, index: tk.Misc, r: int | str, c: int | str) -> None:
500
+ self.window.tktext.tag_add("sel", index, "end")
501
+ self.window.tktext.mark_set("insert", f"{r}.{c}")
502
+
503
+ def autocomplete(self, value: str | None) -> None:
504
+ current_val = self.get()
505
+ if not value or len(current_val) >= len(value) or current_val != value[: len(current_val)]:
506
+ return
507
+ cursor_pos = self.tktext.index("insert")
508
+ line, column = cursor_pos.split(".")
509
+ index = self.window.tktext.index(f"{line}.{column}")
510
+ self.tktext.insert(index, value[len(current_val) :])
511
+ self.highlight_from(index, line, column)
512
+
493
513
  @property
494
514
  def tktext(self) -> object:
495
515
  if self.window: