tksheet 7.4.11__py3-none-any.whl → 7.4.13__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
@@ -8,7 +8,6 @@ from collections import defaultdict, deque
8
8
  from collections.abc import Callable, Generator, Hashable, Iterator, Sequence
9
9
  from functools import partial
10
10
  from itertools import accumulate, chain, cycle, filterfalse, islice, repeat
11
- from math import ceil, floor
12
11
  from operator import itemgetter
13
12
  from re import IGNORECASE, escape, sub
14
13
  from tkinter import TclError
@@ -60,9 +59,11 @@ from .functions import (
60
59
  gen_formatted,
61
60
  get_bg_fg,
62
61
  get_data_from_clipboard,
62
+ get_horizontal_gridline_points,
63
63
  get_menu_kwargs,
64
64
  get_new_indexes,
65
65
  get_seq_without_gaps_at_index,
66
+ get_vertical_gridline_points,
66
67
  index_exists,
67
68
  insert_items,
68
69
  int_x_iter,
@@ -73,8 +74,8 @@ from .functions import (
73
74
  mod_event_val,
74
75
  mod_span,
75
76
  mod_span_widget,
76
- move_elements_by_mapping,
77
77
  move_elements_by_mapping_gen,
78
+ move_fast,
78
79
  new_tk_event,
79
80
  next_cell,
80
81
  push_n,
@@ -149,6 +150,9 @@ class MainTable(tk.Canvas):
149
150
  "<<SelectAll>>": self.select_all,
150
151
  }
151
152
  self.enabled_bindings = set()
153
+ self.selection_box_ctr = 0
154
+ self.disp_selection_fills = set()
155
+ self.hidd_selection_fills = set()
152
156
 
153
157
  self.disp_ctrl_outline = {}
154
158
  self.disp_text = {}
@@ -318,7 +322,7 @@ class MainTable(tk.Canvas):
318
322
  and kwargs["total_rows"] > 0
319
323
  and kwargs["total_cols"] > 0
320
324
  ):
321
- self.data = [list(repeat("", kwargs["total_cols"])) for i in range(kwargs["total_rows"])]
325
+ self.data = [list(repeat("", kwargs["total_cols"])) for _ in range(kwargs["total_rows"])]
322
326
  _header = kwargs["header"] if kwargs["header"] is not None else kwargs["headers"]
323
327
  if isinstance(_header, int):
324
328
  self._headers = _header
@@ -1493,11 +1497,6 @@ class MainTable(tk.Canvas):
1493
1497
  event_data: EventDataDict | None = None,
1494
1498
  ) -> tuple[dict[int, int], dict[int, int], EventDataDict]:
1495
1499
  self.saved_column_widths = {}
1496
- if not isinstance(totalcols, int):
1497
- totalcols = max(data_new_idxs.values(), default=0)
1498
- if totalcols:
1499
- totalcols += 1
1500
- totalcols = self.equalize_data_row_lengths(at_least_cols=totalcols)
1501
1500
  if not event_data:
1502
1501
  event_data = self.new_event_dict("move_columns", state=True)
1503
1502
  if not event_data["moved"]["columns"]:
@@ -1534,26 +1533,26 @@ class MainTable(tk.Canvas):
1534
1533
  )
1535
1534
  else:
1536
1535
  self.recreate_all_selection_boxes()
1536
+
1537
1537
  if move_data:
1538
- self.data = list(
1539
- map(
1540
- move_elements_by_mapping,
1541
- self.data,
1542
- repeat(data_new_idxs),
1543
- repeat(data_old_idxs),
1544
- ),
1545
- )
1538
+ if not isinstance(totalcols, int):
1539
+ totalcols = max(data_new_idxs.values(), default=0)
1540
+ if totalcols:
1541
+ totalcols += 1
1542
+ totalcols = self.equalize_data_row_lengths(at_least_cols=totalcols)
1543
+
1544
+ self.data = [move_fast(k, data_new_idxs, data_old_idxs) for k in self.data]
1546
1545
  maxidx = len_to_idx(totalcols)
1547
1546
  self.CH.fix_header(maxidx)
1548
1547
  if isinstance(self._headers, list) and self._headers:
1549
- self._headers = move_elements_by_mapping(self._headers, data_new_idxs, data_old_idxs)
1548
+ self._headers = move_fast(self._headers, data_new_idxs, data_old_idxs)
1550
1549
  maxidx = self.get_max_column_idx(maxidx)
1551
- full_new_idxs = self.get_full_new_idxs(
1550
+ full_new_idxs, full_old_idxs = self.get_full_new_idxs(
1552
1551
  max_idx=maxidx,
1553
1552
  new_idxs=data_new_idxs,
1554
1553
  old_idxs=data_old_idxs,
1554
+ get_inverse=True,
1555
1555
  )
1556
- full_old_idxs = dict(zip(full_new_idxs.values(), full_new_idxs))
1557
1556
  self.tagged_cells = {
1558
1557
  tags: {(k[0], full_new_idxs[k[1]]) for k in tagged} for tags, tagged in self.tagged_cells.items()
1559
1558
  }
@@ -1726,14 +1725,14 @@ class MainTable(tk.Canvas):
1726
1725
  data_old_idxs: dict[int, int],
1727
1726
  maxidx: int,
1728
1727
  ) -> None:
1729
- self.data = move_elements_by_mapping(
1728
+ self.data = move_fast(
1730
1729
  self.data,
1731
1730
  data_new_idxs,
1732
1731
  data_old_idxs,
1733
1732
  )
1734
1733
  self.RI.fix_index(maxidx)
1735
1734
  if isinstance(self._row_index, list) and self._row_index:
1736
- self._row_index = move_elements_by_mapping(self._row_index, data_new_idxs, data_old_idxs)
1735
+ self._row_index = move_fast(self._row_index, data_new_idxs, data_old_idxs)
1737
1736
 
1738
1737
  def move_rows_adjust_options_dict(
1739
1738
  self,
@@ -1785,12 +1784,12 @@ class MainTable(tk.Canvas):
1785
1784
  else:
1786
1785
  self.move_rows_data(data_new_idxs, data_old_idxs, maxidx)
1787
1786
  maxidx = self.get_max_row_idx(maxidx)
1788
- full_new_idxs = self.get_full_new_idxs(
1787
+ full_new_idxs, full_old_idxs = self.get_full_new_idxs(
1789
1788
  max_idx=maxidx,
1790
1789
  new_idxs=data_new_idxs,
1791
1790
  old_idxs=data_old_idxs,
1791
+ get_inverse=True,
1792
1792
  )
1793
- full_old_idxs = dict(zip(full_new_idxs.values(), full_new_idxs))
1794
1793
  self.tagged_cells = {
1795
1794
  tags: {(full_new_idxs[k[0]], k[1]) for k in tagged} for tags, tagged in self.tagged_cells.items()
1796
1795
  }
@@ -1951,6 +1950,7 @@ class MainTable(tk.Canvas):
1951
1950
  max_idx: int,
1952
1951
  new_idxs: dict[int, int],
1953
1952
  old_idxs: None | dict[int, int] = None,
1953
+ get_inverse: bool = False,
1954
1954
  ) -> dict[int, int]:
1955
1955
  # return a dict of all row or column indexes
1956
1956
  # old indexes and new indexes, not just the
@@ -1958,13 +1958,18 @@ class MainTable(tk.Canvas):
1958
1958
  # {old index: new index, ...}
1959
1959
  # all the way from 0 to max_idx
1960
1960
  if old_idxs is None:
1961
- old_idxs = dict(zip(new_idxs.values(), new_idxs))
1962
- return dict(
1963
- zip(
1964
- move_elements_by_mapping_gen(tuple(range(max_idx + 1)), new_idxs, old_idxs),
1965
- range(max_idx + 1),
1966
- )
1967
- )
1961
+ old_idxs = {v: k for k, v in new_idxs.items()}
1962
+ if get_inverse:
1963
+ d = {}
1964
+ d_in = {}
1965
+ for v, k in enumerate(move_elements_by_mapping_gen(tuple(range(max_idx + 1)), new_idxs, old_idxs)):
1966
+ d[k] = v
1967
+ d_in[v] = k
1968
+ return d, d_in
1969
+ else:
1970
+ return {
1971
+ k: v for v, k in enumerate(move_elements_by_mapping_gen(tuple(range(max_idx + 1)), new_idxs, old_idxs))
1972
+ }
1968
1973
 
1969
1974
  def undo(self, event: Any = None) -> None | EventDataDict:
1970
1975
  if not self.undo_stack:
@@ -2662,58 +2667,37 @@ class MainTable(tk.Canvas):
2662
2667
  self.refresh()
2663
2668
 
2664
2669
  def page_UP(self, event: Any = None) -> None:
2665
- height = self.winfo_height()
2666
- top = self.canvasy(0)
2667
- scrollto_y = max(0, top - height)
2670
+ r, end = self.visible_text_rows
2671
+ if r == end - 1:
2672
+ r = max(0, r - 1)
2668
2673
  if self.PAR.ops.page_up_down_select_row:
2669
- r = bisect_left(self.row_positions, scrollto_y)
2670
- if self.selected and self.selected.row == r:
2671
- r = max(0, r - 1)
2672
2674
  if self.RI.row_selection_enabled and (
2673
- self.anything_selected(exclude_columns=True, exclude_cells=True) or not self.anything_selected()
2675
+ self.selected and self.selected.type_ == "rows" or not self.anything_selected()
2674
2676
  ):
2675
- self.RI.select_row(r)
2676
- self.see(r, 0, keep_xscroll=True, check_cell_visibility=False)
2677
+ self.RI.select_row(r, redraw=False)
2677
2678
  elif (self.single_selection_enabled or self.toggle_selection_enabled) and self.anything_selected(
2678
2679
  exclude_columns=True, exclude_rows=True
2679
2680
  ):
2680
- c = next(reversed(self.selection_boxes.values())).coords.from_c
2681
- self.see(r, c, keep_xscroll=True, check_cell_visibility=False)
2682
- self.select_cell(r, c)
2683
- else:
2684
- args = ("moveto", scrollto_y / (self.row_positions[-1] + 100))
2685
- self.yview(*args)
2686
- self.RI.yview(*args)
2681
+ self.select_cell(r, self.selected.column, redraw=False)
2682
+ if not self.see(r, keep_xscroll=True, bottom_right_corner=True):
2687
2683
  self.main_table_redraw_grid_and_text(redraw_row_index=True)
2688
2684
 
2689
2685
  def page_DOWN(self, event: Any = None) -> None:
2690
- height = self.winfo_height()
2691
- top = self.canvasy(0)
2692
- scrollto = top + height
2693
- if self.PAR.ops.page_up_down_select_row and self.RI.row_selection_enabled:
2694
- r = bisect_left(self.row_positions, scrollto) - 1
2695
- if self.selected and self.selected.row == r:
2696
- r += 1
2697
- if r > len(self.row_positions) - 2:
2698
- r = len(self.row_positions) - 2
2686
+ st, r = self.visible_text_rows
2687
+ r -= 1
2688
+ if st == r:
2689
+ r = min(len(self.row_positions) - 2, r + 1)
2690
+ if self.PAR.ops.page_up_down_select_row:
2699
2691
  if self.RI.row_selection_enabled and (
2700
- self.anything_selected(exclude_columns=True, exclude_cells=True) or not self.anything_selected()
2692
+ self.selected and self.selected.type_ == "rows" or not self.anything_selected()
2701
2693
  ):
2702
- self.RI.select_row(r)
2703
- self.see(r, 0, keep_xscroll=True, check_cell_visibility=False)
2694
+ self.RI.select_row(r, redraw=False)
2695
+
2704
2696
  elif (self.single_selection_enabled or self.toggle_selection_enabled) and self.anything_selected(
2705
2697
  exclude_columns=True, exclude_rows=True
2706
2698
  ):
2707
- c = next(reversed(self.selection_boxes.values())).coords.from_c
2708
- self.see(r, c, keep_xscroll=True, check_cell_visibility=False)
2709
- self.select_cell(r, c)
2710
- else:
2711
- end = self.row_positions[-1]
2712
- if scrollto > end + 100:
2713
- scrollto = end
2714
- args = ("moveto", scrollto / (end + 100))
2715
- self.yview(*args)
2716
- self.RI.yview(*args)
2699
+ self.select_cell(r, self.selected.column, redraw=False)
2700
+ if not self.see(r, keep_xscroll=True, bottom_right_corner=False):
2717
2701
  self.main_table_redraw_grid_and_text(redraw_row_index=True)
2718
2702
 
2719
2703
  def arrowkey_UP(self, event: Any = None) -> None:
@@ -4063,7 +4047,7 @@ class MainTable(tk.Canvas):
4063
4047
  self.yview_scroll(-1, "units")
4064
4048
  self.RI.yview_scroll(-1, "units")
4065
4049
  self.y_move_synced_scrolls("moveto", self.yview()[0])
4066
- self.main_table_redraw_grid_and_text(redraw_header=True, redraw_row_index=True)
4050
+ self.main_table_redraw_grid_and_text(redraw_header=False, redraw_row_index=True)
4067
4051
 
4068
4052
  def shift_mousewheel(self, event: Any) -> None:
4069
4053
  if event.delta < 0 or event.num == 5:
@@ -4076,7 +4060,7 @@ class MainTable(tk.Canvas):
4076
4060
  self.xview_scroll(-1, "units")
4077
4061
  self.CH.xview_scroll(-1, "units")
4078
4062
  self.x_move_synced_scrolls("moveto", self.xview()[0])
4079
- self.main_table_redraw_grid_and_text(redraw_header=True, redraw_row_index=True)
4063
+ self.main_table_redraw_grid_and_text(redraw_header=True, redraw_row_index=False)
4080
4064
 
4081
4065
  def ctrl_mousewheel(self, event: Any) -> None:
4082
4066
  if event.delta < 0 or event.num == 5:
@@ -4457,7 +4441,7 @@ class MainTable(tk.Canvas):
4457
4441
  self.cells_cache = self._redraw_precache_cells(disprn, disprn + 1, 0, len(self.col_positions) - 1)
4458
4442
  if not (align := self.get_cell_kwargs(datarn, datacn, key="align")):
4459
4443
  align = self.align
4460
- if align.endswith("w"):
4444
+ if align[-1] == "w":
4461
4445
  max_width += sum(
4462
4446
  self._overflow(
4463
4447
  self.cells_cache,
@@ -4465,7 +4449,7 @@ class MainTable(tk.Canvas):
4465
4449
  datarn,
4466
4450
  )
4467
4451
  )
4468
- elif align.endswith("e"):
4452
+ elif align[-1] == "e":
4469
4453
  max_width += sum(
4470
4454
  self._overflow(
4471
4455
  self.cells_cache,
@@ -4784,6 +4768,7 @@ class MainTable(tk.Canvas):
4784
4768
  self,
4785
4769
  rows: list[int] | tuple[int],
4786
4770
  create_ops: bool = True,
4771
+ tree: bool = True,
4787
4772
  ) -> None:
4788
4773
  self.tagged_cells = {
4789
4774
  tags: {(push_n(r, rows), c) for (r, c) in tagged} for tags, tagged in self.tagged_cells.items()
@@ -4793,7 +4778,8 @@ class MainTable(tk.Canvas):
4793
4778
  self.tagged_rows = {tags: {push_n(r, rows) for r in tagged} for tags, tagged in self.tagged_rows.items()}
4794
4779
  self.row_options = {push_n(r, rows): v for r, v in self.row_options.items()}
4795
4780
  self.RI.cell_options = {push_n(r, rows): v for r, v in self.RI.cell_options.items()}
4796
- self.RI.rns = {k: push_n(r, rows) for k, r in self.RI.rns.items()}
4781
+ if tree:
4782
+ self.RI.rns = {k: push_n(r, rows) for k, r in self.RI.rns.items()}
4797
4783
  # if there are named spans where rows were added
4798
4784
  # add options to gap which was created by adding rows
4799
4785
  totalcols = None
@@ -5060,7 +5046,7 @@ class MainTable(tk.Canvas):
5060
5046
  event_data["added"]["rows"] = {
5061
5047
  "table": {},
5062
5048
  "index": {},
5063
- "row_heights": {rn: default_height for rn in range(len(self.row_positions) - 1, maxrn + 1)},
5049
+ "row_heights": dict.fromkeys(range(len(self.row_positions) - 1, maxrn + 1), default_height),
5064
5050
  }
5065
5051
  if not from_undo:
5066
5052
  self.set_row_positions(
@@ -5184,7 +5170,7 @@ class MainTable(tk.Canvas):
5184
5170
  event_data["added"]["columns"] = {
5185
5171
  "table": {},
5186
5172
  "header": {},
5187
- "column_widths": {cn: default_width for cn in range(len(self.col_positions) - 1, maxcn + 1)},
5173
+ "column_widths": dict.fromkeys(range(len(self.col_positions) - 1, maxcn + 1), default_width),
5188
5174
  }
5189
5175
  if not from_undo:
5190
5176
  self.set_col_positions(
@@ -5197,6 +5183,7 @@ class MainTable(tk.Canvas):
5197
5183
  self.adjust_options_post_add_rows(
5198
5184
  rows=tuple(rows),
5199
5185
  create_ops=create_ops,
5186
+ tree=tree,
5200
5187
  )
5201
5188
  event_data["added"]["rows"] = {
5202
5189
  "table": rows,
@@ -5875,12 +5862,20 @@ class MainTable(tk.Canvas):
5875
5862
  can_width: int | None,
5876
5863
  dont_blend: bool,
5877
5864
  alternate_color: Highlight | None,
5865
+ has_dd: bool = False,
5878
5866
  ) -> tuple[str, bool]:
5879
5867
  redrawn = False
5880
5868
  if (datarn, datacn) in self.progress_bars:
5881
5869
  kwargs = self.progress_bars[(datarn, datacn)]
5882
5870
  else:
5883
- kwargs = self.get_cell_kwargs(datarn, datacn, key="highlight")
5871
+ if (datarn, datacn) in self.cell_options and "highlight" in self.cell_options[(datarn, datacn)]:
5872
+ kwargs = self.cell_options[(datarn, datacn)]["highlight"]
5873
+ elif datarn in self.row_options and "highlight" in self.row_options[datarn]:
5874
+ kwargs = self.row_options[datarn]["highlight"]
5875
+ elif datacn in self.col_options and "highlight" in self.col_options[datacn]:
5876
+ kwargs = self.col_options[datacn]["highlight"]
5877
+ else:
5878
+ kwargs = {}
5884
5879
  if alt := bool(not kwargs and alternate_color and r % 2):
5885
5880
  kwargs = alternate_color
5886
5881
 
@@ -5942,39 +5937,68 @@ class MainTable(tk.Canvas):
5942
5937
  txtfg = self.PAR.ops.table_fg if kwargs[1] is None else kwargs[1]
5943
5938
 
5944
5939
  if fill:
5945
- highlight_fn = partial(
5946
- self.redraw_highlight,
5947
- x1=fc + 1,
5948
- y1=fr + 1,
5949
- x2=sc,
5950
- y2=sr,
5951
- fill=fill,
5952
- outline=(
5953
- self.PAR.ops.table_fg
5954
- if self.get_cell_kwargs(datarn, datacn, key="dropdown") and self.PAR.ops.show_dropdown_borders
5955
- else ""
5956
- ),
5957
- )
5958
- if isinstance(kwargs, ProgressBar):
5940
+ if not isinstance(kwargs, ProgressBar):
5941
+ redrawn = self.redraw_highlight(
5942
+ x1=fc + 1,
5943
+ y1=fr + 1,
5944
+ x2=sc,
5945
+ y2=sr,
5946
+ fill=fill,
5947
+ outline=self.PAR.ops.table_fg if has_dd and self.PAR.ops.show_dropdown_borders else "",
5948
+ can_width=can_width if (len(kwargs) > 2 and kwargs[2]) else None,
5949
+ pc=None,
5950
+ )
5951
+ else:
5959
5952
  if kwargs.del_when_done and kwargs.percent >= 100:
5960
5953
  del self.progress_bars[(datarn, datacn)]
5961
5954
  else:
5962
- redrawn = highlight_fn(
5955
+ redrawn = self.redraw_highlight(
5956
+ x1=fc + 1,
5957
+ y1=fr + 1,
5958
+ x2=sc,
5959
+ y2=sr,
5960
+ fill=fill,
5961
+ outline=self.PAR.ops.table_fg if has_dd and self.PAR.ops.show_dropdown_borders else "",
5963
5962
  can_width=None,
5964
5963
  pc=kwargs.percent,
5965
5964
  )
5966
- else:
5967
- redrawn = highlight_fn(
5968
- can_width=can_width if (len(kwargs) > 2 and kwargs[2]) else None,
5969
- pc=None,
5970
- )
5971
5965
  elif not kwargs:
5972
5966
  if "cells" in selections and (r, c) in selections["cells"]:
5973
5967
  txtfg = self.PAR.ops.table_selected_cells_fg
5968
+ redrawn = self.redraw_highlight(
5969
+ x1=fc + 1,
5970
+ y1=fr + 1,
5971
+ x2=sc,
5972
+ y2=sr,
5973
+ fill=self.PAR.ops.table_selected_cells_bg,
5974
+ outline=self.PAR.ops.table_fg if has_dd and self.PAR.ops.show_dropdown_borders else "",
5975
+ can_width=None,
5976
+ pc=None,
5977
+ )
5974
5978
  elif "rows" in selections and r in selections["rows"]:
5975
5979
  txtfg = self.PAR.ops.table_selected_rows_fg
5980
+ redrawn = self.redraw_highlight(
5981
+ x1=fc + 1,
5982
+ y1=fr + 1,
5983
+ x2=sc,
5984
+ y2=sr,
5985
+ fill=self.PAR.ops.table_selected_rows_bg,
5986
+ outline=self.PAR.ops.table_fg if has_dd and self.PAR.ops.show_dropdown_borders else "",
5987
+ can_width=None,
5988
+ pc=None,
5989
+ )
5976
5990
  elif "columns" in selections and c in selections["columns"]:
5977
5991
  txtfg = self.PAR.ops.table_selected_columns_fg
5992
+ redrawn = self.redraw_highlight(
5993
+ x1=fc + 1,
5994
+ y1=fr + 1,
5995
+ x2=sc,
5996
+ y2=sr,
5997
+ fill=self.PAR.ops.table_selected_columns_bg,
5998
+ outline=self.PAR.ops.table_fg if has_dd and self.PAR.ops.show_dropdown_borders else "",
5999
+ can_width=None,
6000
+ pc=None,
6001
+ )
5978
6002
  else:
5979
6003
  txtfg = self.PAR.ops.table_fg
5980
6004
  return txtfg, redrawn
@@ -6063,7 +6087,7 @@ class MainTable(tk.Canvas):
6063
6087
  if draw_arrow:
6064
6088
  mod = (self.table_txt_height - 1) if self.table_txt_height % 2 else self.table_txt_height
6065
6089
  small_mod = int(mod / 5)
6066
- mid_y = floor(self.min_row_height / 2)
6090
+ mid_y = int(self.min_row_height / 2)
6067
6091
  if open_:
6068
6092
  # up arrow
6069
6093
  points = (
@@ -6257,11 +6281,30 @@ class MainTable(tk.Canvas):
6257
6281
  else:
6258
6282
  datacn = c if self.all_columns_displayed else self.displayed_columns[c]
6259
6283
  cells["datacn"][c] = datacn
6260
- if kwargs := self.get_cell_kwargs(datarn, datacn, key="dropdown"):
6261
- cells["dropdown"][(datarn, datacn)] = kwargs
6262
- elif kwargs := self.get_cell_kwargs(datarn, datacn, key="checkbox"):
6263
- cells["checkbox"][(datarn, datacn)] = kwargs
6264
- cells[(datarn, datacn)] = self.cell_str(datarn, datacn, get_displayed=True)
6284
+ t = (datarn, datacn)
6285
+
6286
+ # self.get_cell_kwargs not used here to boost performance
6287
+ if t in self.cell_options and "dropdown" in self.cell_options[t]:
6288
+ cells["dropdown"][t] = self.cell_options[t]["dropdown"]
6289
+
6290
+ elif datarn in self.row_options and "dropdown" in self.row_options[datarn]:
6291
+ cells["dropdown"][t] = self.row_options[datarn]["dropdown"]
6292
+
6293
+ elif datacn in self.col_options and "dropdown" in self.col_options[datacn]:
6294
+ cells["dropdown"][t] = self.col_options[datacn]["dropdown"]
6295
+
6296
+ else:
6297
+ if t in self.cell_options and "checkbox" in self.cell_options[t]:
6298
+ cells["checkbox"][t] = self.cell_options[t]["checkbox"]
6299
+
6300
+ elif datarn in self.row_options and "checkbox" in self.row_options[datarn]:
6301
+ cells["checkbox"][t] = self.row_options[datarn]["checkbox"]
6302
+
6303
+ elif datacn in self.col_options and "checkbox" in self.col_options[datacn]:
6304
+ cells["checkbox"][t] = self.col_options[datacn]["checkbox"]
6305
+
6306
+ cells[t] = self.cell_str(datarn, datacn, get_displayed=True)
6307
+
6265
6308
  return cells
6266
6309
 
6267
6310
  def wrap_get_char_w(self, c: str) -> int:
@@ -6346,7 +6389,7 @@ class MainTable(tk.Canvas):
6346
6389
  if changed_w:
6347
6390
  for widget in (self, self.RI, self.CH, self.TL):
6348
6391
  widget.update_idletasks()
6349
- return False
6392
+ return
6350
6393
  # important vars
6351
6394
  x_stop = min(last_col_line_pos, scrollpos_right)
6352
6395
  y_stop = min(last_row_line_pos, scrollpos_bot)
@@ -6363,27 +6406,20 @@ class MainTable(tk.Canvas):
6363
6406
  self.disp_dropdown = {}
6364
6407
  self.hidd_checkbox.update(self.disp_checkbox)
6365
6408
  self.disp_checkbox = {}
6409
+ points = []
6366
6410
  # manage horizontal grid lines
6367
6411
  if self.PAR.ops.show_horizontal_grid and row_pos_exists:
6368
6412
  if self.PAR.ops.horizontal_grid_to_end_of_window:
6369
6413
  x_grid_stop = scrollpos_right + can_width
6370
6414
  else:
6371
6415
  x_grid_stop = x_stop + 1 if last_col_line_pos > scrollpos_right else x_stop - 1
6372
- self.redraw_gridline(
6373
- points=tuple(
6374
- chain.from_iterable(
6375
- (
6376
- scrollpos_left - 1,
6377
- self.row_positions[r],
6378
- x_grid_stop,
6379
- self.row_positions[r],
6380
- scrollpos_left - 1,
6381
- self.row_positions[r],
6382
- scrollpos_left - 1,
6383
- self.row_positions[r + 1] if len(self.row_positions) - 1 > r else self.row_positions[r],
6384
- )
6385
- for r in range(grid_start_row, grid_end_row)
6386
- )
6416
+ points.extend(
6417
+ get_horizontal_gridline_points(
6418
+ left=scrollpos_left,
6419
+ stop=x_grid_stop,
6420
+ positions=self.row_positions,
6421
+ start=grid_start_row,
6422
+ end=grid_end_row,
6387
6423
  )
6388
6424
  )
6389
6425
  # manage vertical grid lines
@@ -6392,23 +6428,20 @@ class MainTable(tk.Canvas):
6392
6428
  y_grid_stop = scrollpos_bot + can_height
6393
6429
  else:
6394
6430
  y_grid_stop = y_stop + 1 if last_row_line_pos > scrollpos_bot else y_stop - 1
6395
- self.redraw_gridline(
6396
- points=tuple(
6397
- chain.from_iterable(
6398
- (
6399
- self.col_positions[c],
6400
- scrollpos_top - 1,
6401
- self.col_positions[c],
6402
- y_grid_stop,
6403
- self.col_positions[c],
6404
- scrollpos_top - 1,
6405
- self.col_positions[c + 1] if len(self.col_positions) - 1 > c else self.col_positions[c],
6406
- scrollpos_top - 1,
6407
- )
6408
- for c in range(grid_start_col, grid_end_col)
6409
- )
6410
- ),
6431
+ if self.PAR.ops.show_horizontal_grid:
6432
+ points.extend([scrollpos_left - 2, grid_end_row, grid_start_col - 2, scrollpos_top - 2])
6433
+ points.extend(
6434
+ get_vertical_gridline_points(
6435
+ top=scrollpos_top,
6436
+ stop=y_grid_stop,
6437
+ positions=self.col_positions,
6438
+ start=grid_start_col,
6439
+ end=grid_end_col,
6440
+ )
6411
6441
  )
6442
+ if points:
6443
+ self.redraw_gridline(points)
6444
+
6412
6445
  font = self.PAR.ops.table_font
6413
6446
  dd_coords = self.dropdown.get_coords()
6414
6447
  selections = self.get_redraw_selections(text_start_row, grid_end_row, text_start_col, grid_end_col)
@@ -6429,14 +6462,14 @@ class MainTable(tk.Canvas):
6429
6462
  else:
6430
6463
  alternate_color = None
6431
6464
  dont_blend = ()
6432
- if not self.PAR.ops.show_selected_cells_border:
6465
+ if self.PAR.ops.show_selected_cells_border:
6466
+ override = ()
6467
+ else:
6433
6468
  override = (
6434
6469
  color_tup(self.PAR.ops.table_selected_cells_fg),
6435
6470
  color_tup(self.PAR.ops.table_selected_columns_fg),
6436
6471
  color_tup(self.PAR.ops.table_selected_rows_fg),
6437
6472
  )
6438
- else:
6439
- override = ()
6440
6473
  allow_overflow = self.PAR.ops.allow_cell_overflow
6441
6474
  wrap = self.PAR.ops.table_wrap
6442
6475
  cells = self._redraw_precache_cells(
@@ -6454,6 +6487,8 @@ class MainTable(tk.Canvas):
6454
6487
  cleftgridln = self.col_positions[c]
6455
6488
  crightgridln = self.col_positions[c + 1]
6456
6489
  datacn = cells["datacn"][c]
6490
+ t = (datarn, datacn)
6491
+
6457
6492
  fill, dd_drawn = self.redraw_highlight_get_text_fg(
6458
6493
  r=r,
6459
6494
  c=c,
@@ -6470,24 +6505,32 @@ class MainTable(tk.Canvas):
6470
6505
  can_width=can_width,
6471
6506
  dont_blend=(r, c) == dont_blend,
6472
6507
  alternate_color=alternate_color,
6508
+ has_dd=t in cells["dropdown"],
6473
6509
  )
6474
- if not (align := self.get_cell_kwargs(datarn, datacn, key="align")):
6510
+ if t in self.cell_options and "align" in self.cell_options[(datarn, datacn)]:
6511
+ align = self.cell_options[(datarn, datacn)]["align"]
6512
+ elif datarn in self.row_options and "align" in self.row_options[datarn]:
6513
+ align = self.row_options[datarn]["align"]
6514
+ elif datacn in self.col_options and "align" in self.col_options[datacn]:
6515
+ align = self.col_options[datacn]["align"]
6516
+ else:
6475
6517
  align = self.align
6476
6518
 
6477
- if kwargs := cells["dropdown"].get((datarn, datacn), None):
6519
+ kws = cells["dropdown"][t] if t in cells["dropdown"] else None # noqa: SIM401
6520
+ if kws:
6478
6521
  max_width = crightgridln - cleftgridln - self.table_txt_height - 5
6479
- if align.endswith("w"):
6522
+ if align[-1] == "w":
6480
6523
  draw_x = cleftgridln + 2
6481
- elif align.endswith("e"):
6524
+ elif align[-1] == "e":
6482
6525
  draw_x = crightgridln - 5 - self.table_txt_height
6483
- elif align.endswith("n"):
6484
- draw_x = cleftgridln + ceil((crightgridln - cleftgridln - self.table_txt_height) / 2)
6526
+ elif align[-1] == "n":
6527
+ draw_x = cleftgridln + (crightgridln - cleftgridln - self.table_txt_height) / 2
6485
6528
  self.redraw_dropdown(
6486
6529
  cleftgridln,
6487
6530
  rtopgridln,
6488
6531
  crightgridln,
6489
6532
  self.row_positions[r + 1],
6490
- fill=fill if kwargs["state"] != "disabled" else self.PAR.ops.table_grid_fg,
6533
+ fill=fill if kws["state"] != "disabled" else self.PAR.ops.table_grid_fg,
6491
6534
  outline=fill,
6492
6535
  draw_outline=not dd_drawn,
6493
6536
  draw_arrow=max_width >= 5,
@@ -6495,50 +6538,43 @@ class MainTable(tk.Canvas):
6495
6538
  )
6496
6539
  else:
6497
6540
  max_width = crightgridln - cleftgridln - 2
6498
- if align.endswith("w"):
6541
+ if align[-1] == "w":
6499
6542
  draw_x = cleftgridln + 2
6500
- elif align.endswith("e"):
6543
+ elif align[-1] == "e":
6501
6544
  draw_x = crightgridln - 2
6502
- elif align.endswith("n"):
6503
- draw_x = cleftgridln + floor((crightgridln - cleftgridln) / 2)
6504
-
6505
- if (
6506
- kwargs := cells["checkbox"].get((datarn, datacn), None)
6507
- ) and max_width > self.table_txt_height + 1:
6508
- box_w = self.table_txt_height + 1
6509
- if align.endswith("w"):
6510
- draw_x += box_w + 3
6511
- elif align.endswith("n"):
6512
- draw_x += ceil(box_w / 2) + 1
6513
- max_width -= box_w + 4
6514
- try:
6515
- draw_check = bool(self.data[datarn][datacn])
6516
- except Exception:
6517
- draw_check = False
6518
- self.redraw_checkbox(
6519
- cleftgridln + 2,
6520
- rtopgridln + 2,
6521
- cleftgridln + self.table_txt_height + 3,
6522
- rtopgridln + self.table_txt_height + 3,
6523
- fill=fill if kwargs["state"] == "normal" else self.PAR.ops.table_grid_fg,
6524
- outline="",
6525
- draw_check=draw_check,
6526
- )
6527
- text = cells[(datarn, datacn)]
6528
- if (
6529
- not text
6530
- or (align.endswith("w") and draw_x > scrollpos_right)
6531
- or (align.endswith("e") and cleftgridln + 5 > scrollpos_right)
6532
- or (align.endswith("n") and cleftgridln + 5 > scrollpos_right)
6533
- ):
6545
+ elif align[-1] == "n":
6546
+ draw_x = cleftgridln + (crightgridln - cleftgridln) / 2
6547
+
6548
+ if t in cells["checkbox"]:
6549
+ kws = cells["checkbox"][t]
6550
+ if max_width > self.table_txt_height + 1:
6551
+ box_w = self.table_txt_height + 1
6552
+ if align[-1] == "w":
6553
+ draw_x += box_w + 3
6554
+ elif align[-1] == "n":
6555
+ draw_x += box_w / 2 + 1
6556
+ max_width -= box_w + 4
6557
+ try:
6558
+ draw_check = bool(self.data[datarn][datacn])
6559
+ except Exception:
6560
+ draw_check = False
6561
+ self.redraw_checkbox(
6562
+ cleftgridln + 2,
6563
+ rtopgridln + 2,
6564
+ cleftgridln + self.table_txt_height + 3,
6565
+ rtopgridln + self.table_txt_height + 3,
6566
+ fill=fill if kws["state"] == "normal" else self.PAR.ops.table_grid_fg,
6567
+ outline="",
6568
+ draw_check=draw_check,
6569
+ )
6570
+ text = cells[t]
6571
+ if not text or (align[-1] == "w" and draw_x > scrollpos_right) or cleftgridln + 5 > scrollpos_right:
6534
6572
  continue
6535
- if allow_overflow and not kwargs:
6536
- if align.endswith("w"):
6573
+ if allow_overflow and not kws:
6574
+ if align[-1] == "w":
6537
6575
  max_width += sum(self._overflow(cells, range(c + 1, text_end_col), datarn))
6538
- elif align.endswith("e"):
6576
+ elif align[-1] == "e":
6539
6577
  max_width += sum(self._overflow(cells, reversed(range(text_start_col, c)), datarn))
6540
- elif align.endswith("n"):
6541
- ...
6542
6578
  if max_width <= 1:
6543
6579
  continue
6544
6580
  start_line = max(0, int((scrollpos_top - rtopgridln) / self.table_txt_height))
@@ -6552,7 +6588,7 @@ class MainTable(tk.Canvas):
6552
6588
  wrap=wrap,
6553
6589
  start_line=start_line,
6554
6590
  )
6555
- if align.endswith(("w", "e")):
6591
+ if align[-1] == "w" or align[-1] == "e":
6556
6592
  if self.hidd_text:
6557
6593
  iid, showing = self.hidd_text.popitem()
6558
6594
  self.coords(iid, draw_x, draw_y)
@@ -6573,7 +6609,6 @@ class MainTable(tk.Canvas):
6573
6609
  anchor=align,
6574
6610
  state="normal",
6575
6611
  )
6576
- self.tag_raise(iid)
6577
6612
  else:
6578
6613
  iid = self.create_text(
6579
6614
  draw_x,
@@ -6586,15 +6621,15 @@ class MainTable(tk.Canvas):
6586
6621
  )
6587
6622
  self.disp_text[iid] = True
6588
6623
 
6589
- elif align.endswith("n"):
6590
- for text in gen_lines:
6624
+ elif align[-1] == "n":
6625
+ for t in gen_lines:
6591
6626
  if self.hidd_text:
6592
6627
  iid, showing = self.hidd_text.popitem()
6593
6628
  self.coords(iid, draw_x, draw_y)
6594
6629
  if showing:
6595
6630
  self.itemconfig(
6596
6631
  iid,
6597
- text=text,
6632
+ text=t,
6598
6633
  fill=fill,
6599
6634
  font=font,
6600
6635
  anchor=align,
@@ -6602,18 +6637,17 @@ class MainTable(tk.Canvas):
6602
6637
  else:
6603
6638
  self.itemconfig(
6604
6639
  iid,
6605
- text=text,
6640
+ text=t,
6606
6641
  fill=fill,
6607
6642
  font=font,
6608
6643
  anchor=align,
6609
6644
  state="normal",
6610
6645
  )
6611
- self.tag_raise(iid)
6612
6646
  else:
6613
6647
  iid = self.create_text(
6614
6648
  draw_x,
6615
6649
  draw_y,
6616
- text=text,
6650
+ text=t,
6617
6651
  fill=fill,
6618
6652
  font=font,
6619
6653
  anchor=align,
@@ -6642,6 +6676,7 @@ class MainTable(tk.Canvas):
6642
6676
  self.tag_raise("rh")
6643
6677
  if self.CH.disp_resize_lines:
6644
6678
  self.tag_raise("rw")
6679
+ self.tag_raise("t")
6645
6680
  if redraw_header and self.show_header:
6646
6681
  self.CH.redraw_grid_and_text(
6647
6682
  last_col_line_pos=last_col_line_pos,
@@ -6750,7 +6785,7 @@ class MainTable(tk.Canvas):
6750
6785
  box = next(iter(reversed(self.selection_boxes.values())))
6751
6786
  r1, c1, r2, c2 = box.coords
6752
6787
  if r2 - r1 == 1 and c2 - c1 == 1:
6753
- self.itemconfig(box.fill_iid, state="hidden")
6788
+ box.state = "hidden"
6754
6789
  self.set_currently_selected(item=box.fill_iid)
6755
6790
 
6756
6791
  def coords_and_type(self, item: int) -> tuple:
@@ -6772,26 +6807,20 @@ class MainTable(tk.Canvas):
6772
6807
  c: int,
6773
6808
  type_: Literal["cells", "rows", "columns"],
6774
6809
  fill_iid: int,
6775
- lower_selection_boxes: bool = True,
6776
6810
  ) -> int:
6777
- fill, outline = self.get_selected_box_bg_fg(type_=type_)
6811
+ _, outline = self.get_selected_box_bg_fg(type_=type_)
6778
6812
  x1 = self.col_positions[c] + 1
6779
6813
  y1 = self.row_positions[r] + 1
6780
6814
  x2 = self.col_positions[c + 1] if index_exists(self.col_positions, c + 1) else self.col_positions[c] + 1
6781
6815
  y2 = self.row_positions[r + 1] if index_exists(self.row_positions, r + 1) else self.row_positions[r] + 1
6782
6816
  self.hide_selected()
6783
- if self.PAR.ops.show_selected_cells_border:
6784
- fill = ""
6785
- else:
6786
- fill = outline
6787
- outline = ""
6788
6817
  iid = self.display_box(
6789
6818
  x1,
6790
6819
  y1,
6791
6820
  x2,
6792
6821
  y2,
6793
- fill=fill,
6794
- outline=outline,
6822
+ fill="",
6823
+ outline=outline if self.PAR.ops.show_selected_cells_border else "",
6795
6824
  state="normal",
6796
6825
  tags="selected",
6797
6826
  width=2,
@@ -6804,8 +6833,6 @@ class MainTable(tk.Canvas):
6804
6833
  iid=iid,
6805
6834
  fill_iid=fill_iid,
6806
6835
  )
6807
- if lower_selection_boxes:
6808
- self.lower_selection_boxes()
6809
6836
  return iid
6810
6837
 
6811
6838
  def display_box(
@@ -6856,14 +6883,17 @@ class MainTable(tk.Canvas):
6856
6883
  self.hidd_boxes.add(item)
6857
6884
  self.itemconfig(item, state="hidden")
6858
6885
 
6886
+ def hide_box_fill(self, item: int | None) -> None:
6887
+ if isinstance(item, int):
6888
+ self.disp_selection_fills.discard(item)
6889
+ self.hidd_selection_fills.add(item)
6890
+
6859
6891
  def hide_selection_box(self, item: int | None) -> bool:
6860
6892
  if item is None or item is True or item not in self.selection_boxes:
6861
6893
  return False
6862
6894
  box = self.selection_boxes.pop(item)
6863
- self.hide_box(box.fill_iid)
6895
+ self.hide_box_fill(box.fill_iid)
6864
6896
  self.hide_box(box.bd_iid)
6865
- self.RI.hide_box(box.index)
6866
- self.CH.hide_box(box.header)
6867
6897
  if self.selected.fill_iid == item:
6868
6898
  self.hide_selected()
6869
6899
  self.set_current_to_last()
@@ -6880,6 +6910,15 @@ class MainTable(tk.Canvas):
6880
6910
  self.hide_box(self.selected.iid)
6881
6911
  self.selected = ()
6882
6912
 
6913
+ def get_selection_fill(self) -> int:
6914
+ if self.hidd_selection_fills:
6915
+ iid = self.hidd_selection_fills.pop()
6916
+ else:
6917
+ self.selection_box_ctr += 1
6918
+ iid = self.selection_box_ctr
6919
+ self.disp_selection_fills.add(iid)
6920
+ return iid
6921
+
6883
6922
  def create_selection_box(
6884
6923
  self,
6885
6924
  r1: int,
@@ -6899,52 +6938,35 @@ class MainTable(tk.Canvas):
6899
6938
  r1 = 0
6900
6939
  r2 = 0
6901
6940
  if type_ == "cells":
6902
- mt_bg = self.PAR.ops.table_selected_cells_bg
6903
6941
  mt_border_col = self.PAR.ops.table_selected_cells_border_fg
6904
6942
  elif type_ == "rows":
6905
- mt_bg = self.PAR.ops.table_selected_rows_bg
6906
6943
  mt_border_col = self.PAR.ops.table_selected_rows_border_fg
6907
6944
  elif type_ == "columns":
6908
- mt_bg = self.PAR.ops.table_selected_columns_bg
6909
6945
  mt_border_col = self.PAR.ops.table_selected_columns_border_fg
6910
6946
  if self.selection_boxes:
6911
- self.itemconfig(next(reversed(self.selection_boxes)), state="normal")
6947
+ next(reversed(self.selection_boxes.values())).state = "normal"
6912
6948
  x1, y1, x2, y2 = self.box_coords_x_canvas_coords(r1, c1, r2, c2, type_)
6913
- fill_iid = self.display_box(
6914
- x1,
6915
- y1,
6916
- x2,
6917
- y2,
6918
- fill=mt_bg,
6919
- outline="",
6920
- state=state if self.PAR.ops.show_selected_cells_border else "normal",
6921
- tags=type_,
6922
- width=1,
6923
- )
6924
- index_iid = self.RI.display_box(
6925
- 0,
6926
- y1,
6927
- self.RI.current_width - 1,
6928
- y2,
6929
- fill=self.PAR.ops.index_selected_rows_bg if type_ == "rows" else self.PAR.ops.index_selected_cells_bg,
6930
- outline="",
6931
- state="normal",
6932
- tags="cells" if type_ == "columns" else type_,
6933
- )
6934
- header_iid = self.CH.display_box(
6935
- x1,
6936
- 0,
6937
- self.col_positions[c2],
6938
- self.CH.current_height - 1,
6939
- fill=(
6940
- self.PAR.ops.header_selected_columns_bg if type_ == "columns" else self.PAR.ops.header_selected_cells_bg
6941
- ),
6942
- outline="",
6943
- state="normal",
6944
- tags="cells" if type_ == "rows" else type_,
6945
- )
6949
+ fill_iid = self.get_selection_fill()
6946
6950
  bd_iid = None
6947
- if self.PAR.ops.show_selected_cells_border and (
6951
+ # fill might not display if canvas is wider than 32k pixels
6952
+ if self.PAR.ops.selected_rows_to_end_of_window and type_ == "rows":
6953
+ bd_iid = self.display_box(
6954
+ x1,
6955
+ y1,
6956
+ x2,
6957
+ y2,
6958
+ fill=self.PAR.ops.table_selected_rows_bg,
6959
+ outline=""
6960
+ if self.PAR.name == "!SheetDropdown"
6961
+ else mt_border_col
6962
+ if self.PAR.ops.show_selected_cells_border
6963
+ else "",
6964
+ state="normal",
6965
+ tags=f"{type_}bd",
6966
+ width=1,
6967
+ )
6968
+ self.tag_lower(bd_iid)
6969
+ elif self.PAR.ops.show_selected_cells_border and (
6948
6970
  ext
6949
6971
  or self.ctrl_b1_pressed
6950
6972
  or (self.being_drawn_item is None and self.RI.being_drawn_item is None and self.CH.being_drawn_item is None)
@@ -6964,10 +6986,11 @@ class MainTable(tk.Canvas):
6964
6986
  self.selection_boxes[fill_iid] = SelectionBox(
6965
6987
  fill_iid=fill_iid,
6966
6988
  bd_iid=bd_iid,
6967
- index=index_iid,
6968
- header=header_iid,
6989
+ index=fill_iid,
6990
+ header=fill_iid,
6969
6991
  coords=Box_nt(r1, c1, r2, c2),
6970
6992
  type_=type_,
6993
+ state=state,
6971
6994
  )
6972
6995
  if set_current:
6973
6996
  if set_current is True:
@@ -6976,26 +6999,11 @@ class MainTable(tk.Canvas):
6976
6999
  elif isinstance(set_current, tuple):
6977
7000
  curr_r = set_current[0]
6978
7001
  curr_c = set_current[1]
6979
- self.create_currently_selected_box(curr_r, curr_c, type_, fill_iid, lower_selection_boxes=False)
6980
- self.lower_selection_boxes()
7002
+ self.create_currently_selected_box(curr_r, curr_c, type_, fill_iid)
6981
7003
  if run_binding:
6982
7004
  self.run_selection_binding(type_)
6983
7005
  return fill_iid
6984
7006
 
6985
- def lower_selection_boxes(self) -> None:
6986
- if self.selected:
6987
- if not self.PAR.ops.show_selected_cells_border:
6988
- self.tag_lower(self.selected.iid)
6989
- self.tag_lower("rows")
6990
- self.tag_lower("columns")
6991
- self.tag_lower("cells")
6992
- self.RI.tag_lower("rows")
6993
- self.RI.tag_lower("cells")
6994
- self.CH.tag_lower("columns")
6995
- self.CH.tag_lower("cells")
6996
- if self.PAR.ops.show_selected_cells_border:
6997
- self.tag_raise(self.selected.iid)
6998
-
6999
7007
  def box_coords_x_canvas_coords(
7000
7008
  self,
7001
7009
  r1: int,
@@ -7026,13 +7034,10 @@ class MainTable(tk.Canvas):
7026
7034
  type_ = self.selection_boxes[fill_iid].type_
7027
7035
  self.selection_boxes[fill_iid].coords = Box_nt(r1, c1, r2, c2)
7028
7036
  if type_ == "cells":
7029
- mt_bg = self.PAR.ops.table_selected_cells_bg
7030
7037
  mt_border_col = self.PAR.ops.table_selected_cells_border_fg
7031
7038
  elif type_ == "rows":
7032
- mt_bg = self.PAR.ops.table_selected_rows_bg
7033
7039
  mt_border_col = self.PAR.ops.table_selected_rows_border_fg
7034
7040
  elif type_ == "columns":
7035
- mt_bg = self.PAR.ops.table_selected_columns_bg
7036
7041
  mt_border_col = self.PAR.ops.table_selected_columns_border_fg
7037
7042
  if not state:
7038
7043
  if r2 - r1 > 1 or c2 - c1 > 1:
@@ -7044,31 +7049,7 @@ class MainTable(tk.Canvas):
7044
7049
  if self.selected.fill_iid == fill_iid:
7045
7050
  self.selected = self.selected._replace(box=Box_nt(r1, c1, r2, c2))
7046
7051
  x1, y1, x2, y2 = self.box_coords_x_canvas_coords(r1, c1, r2, c2, type_)
7047
- self.display_box(x1, y1, x2, y2, fill=mt_bg, outline="", state=state, tags=type_, width=1, iid=fill_iid)
7048
- self.RI.display_box(
7049
- 0,
7050
- y1,
7051
- self.RI.current_width - 1,
7052
- y2,
7053
- fill=self.PAR.ops.index_selected_rows_bg if type_ == "rows" else self.PAR.ops.index_selected_cells_bg,
7054
- outline="",
7055
- state="normal",
7056
- tags="cells" if type_ == "columns" else type_,
7057
- iid=self.selection_boxes[fill_iid].index,
7058
- )
7059
- self.CH.display_box(
7060
- x1,
7061
- 0,
7062
- self.col_positions[c2],
7063
- self.CH.current_height - 1,
7064
- fill=(
7065
- self.PAR.ops.header_selected_columns_bg if type_ == "columns" else self.PAR.ops.header_selected_cells_bg
7066
- ),
7067
- outline="",
7068
- state="normal",
7069
- tags="cells" if type_ == "rows" else type_,
7070
- iid=self.selection_boxes[fill_iid].header,
7071
- )
7052
+ self.selection_boxes[fill_iid].state = state
7072
7053
  if bd_iid := self.selection_boxes[fill_iid].bd_iid:
7073
7054
  if self.PAR.ops.show_selected_cells_border:
7074
7055
  self.display_box(
@@ -7140,21 +7121,23 @@ class MainTable(tk.Canvas):
7140
7121
 
7141
7122
  def get_redraw_selections(self, startr: int, endr: int, startc: int, endc: int) -> dict:
7142
7123
  d = defaultdict(set)
7124
+ ignore_hidd_current = not self.PAR.ops.show_selected_cells_border
7143
7125
  for _, box in self.get_selection_items():
7144
7126
  r1, c1, r2, c2 = box.coords
7145
- if box.type_ == "cells":
7146
- for r in range(startr, endr):
7127
+ if box.state == "normal" or ignore_hidd_current:
7128
+ if box.type_ == "cells":
7129
+ for r in range(startr, endr):
7130
+ for c in range(startc, endc):
7131
+ if r1 <= r and c1 <= c and r2 > r and c2 > c:
7132
+ d["cells"].add((r, c))
7133
+ elif box.type_ == "rows":
7134
+ for r in range(startr, endr):
7135
+ if r1 <= r and r2 > r:
7136
+ d["rows"].add(r)
7137
+ elif box.type_ == "columns":
7147
7138
  for c in range(startc, endc):
7148
- if r1 <= r and c1 <= c and r2 > r and c2 > c:
7149
- d["cells"].add((r, c))
7150
- elif box.type_ == "rows":
7151
- for r in range(startr, endr):
7152
- if r1 <= r and r2 > r:
7153
- d["rows"].add(r)
7154
- elif box.type_ == "columns":
7155
- for c in range(startc, endc):
7156
- if c1 <= c and c2 > c:
7157
- d["columns"].add(c)
7139
+ if c1 <= c and c2 > c:
7140
+ d["columns"].add(c)
7158
7141
  return d
7159
7142
 
7160
7143
  def get_selected_min_max(self) -> tuple[int, int, int, int] | tuple[None, None, None, None]:
@@ -8001,8 +7984,8 @@ class MainTable(tk.Canvas):
8001
7984
  )
8002
7985
  if "checkbox" in kwargs:
8003
7986
  return False
8004
- elif (kwargs := kwargs.get("dropdown", {})) and kwargs["validate_input"] and kwargs["values"]:
8005
- return kwargs["values"][0]
7987
+ elif "dropdown" in kwargs and kwargs["dropdown"]["validate_input"] and kwargs["dropdown"]["values"]:
7988
+ return kwargs["dropdown"]["values"][0]
8006
7989
  else:
8007
7990
  return ""
8008
7991
 
@@ -8103,23 +8086,49 @@ class MainTable(tk.Canvas):
8103
8086
  cell value is not in datatypes kwarg
8104
8087
  if get displayed is true then Nones are replaced by
8105
8088
  """
8106
- kwargs = self.get_cell_kwargs(datarn, datacn, key=None)
8107
8089
  if get_displayed:
8108
- if kwargs and "dropdown" in kwargs:
8109
- if kwargs["dropdown"]["text"] is not None:
8110
- return f"{kwargs['dropdown']['text']}"
8111
- elif kwargs and "checkbox" in kwargs:
8112
- return f"{kwargs['checkbox']['text']}"
8090
+ # check for dropdown
8091
+ if (datarn, datacn) in self.cell_options and "dropdown" in self.cell_options[(datarn, datacn)]:
8092
+ kws = self.cell_options[(datarn, datacn)]["dropdown"]
8093
+ elif datarn in self.row_options and "dropdown" in self.row_options[datarn]:
8094
+ kws = self.row_options[datarn]["dropdown"]
8095
+ elif datacn in self.col_options and "dropdown" in self.col_options[datacn]:
8096
+ kws = self.col_options[datacn]["dropdown"]
8097
+ else:
8098
+ kws = None
8099
+ if kws and kws["text"] is not None:
8100
+ return f"{kws['text']}"
8101
+
8102
+ # check for checkbox
8103
+ if (datarn, datacn) in self.cell_options and "checkbox" in self.cell_options[(datarn, datacn)]:
8104
+ kws = self.cell_options[(datarn, datacn)]["checkbox"]
8105
+ elif datarn in self.row_options and "checkbox" in self.row_options[datarn]:
8106
+ kws = self.row_options[datarn]["checkbox"]
8107
+ elif datacn in self.col_options and "checkbox" in self.col_options[datacn]:
8108
+ kws = self.col_options[datacn]["checkbox"]
8109
+ else:
8110
+ kws = None
8111
+ if kws:
8112
+ return f"{kws['text']}"
8113
8113
  try:
8114
8114
  value = self.data[datarn][datacn]
8115
8115
  except Exception:
8116
8116
  value = ""
8117
- if "format" in kwargs:
8118
- if kwargs["format"]["formatter"] is None:
8117
+ # check for format
8118
+ if (datarn, datacn) in self.cell_options and "format" in self.cell_options[(datarn, datacn)]:
8119
+ kws = self.cell_options[(datarn, datacn)]["format"]
8120
+ elif datarn in self.row_options and "format" in self.row_options[datarn]:
8121
+ kws = self.row_options[datarn]["format"]
8122
+ elif datacn in self.col_options and "format" in self.col_options[datacn]:
8123
+ kws = self.col_options[datacn]["format"]
8124
+ else:
8125
+ kws = None
8126
+ if kws:
8127
+ if kws["formatter"] is None:
8119
8128
  if get_displayed:
8120
- return data_to_str(value, **kwargs["format"])
8129
+ return data_to_str(value, **kws)
8121
8130
  else:
8122
- return f"{get_data_with_valid_check(value, **kwargs['format'])}"
8131
+ return f"{get_data_with_valid_check(value, **kws)}"
8123
8132
  else:
8124
8133
  if get_displayed:
8125
8134
  # assumed given formatter class has __str__()
@@ -8128,7 +8137,7 @@ class MainTable(tk.Canvas):
8128
8137
  # assumed given formatter class has get_data_with_valid_check()
8129
8138
  return f"{value.get_data_with_valid_check()}"
8130
8139
  else:
8131
- return "" if value is None else value if isinstance(value, str) else f"{value}"
8140
+ return "" if value is None else str(value)
8132
8141
 
8133
8142
  def get_cell_data(
8134
8143
  self,
@@ -8168,7 +8177,7 @@ class MainTable(tk.Canvas):
8168
8177
  elif "format" in kwargs:
8169
8178
  return True
8170
8179
  elif self.cell_equal_to(datarn, datacn, value, ignore_empty=ignore_empty, check_fmt=False) or (
8171
- (dropdown := kwargs.get("dropdown", {})) and dropdown["validate_input"] and value not in dropdown["values"]
8180
+ "dropdown" in kwargs and kwargs["dropdown"]["validate_input"] and value not in kwargs["dropdown"]["values"]
8172
8181
  ):
8173
8182
  return False
8174
8183
  elif "checkbox" in kwargs: