tksheet 7.4.11__py3-none-any.whl → 7.4.12__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/__init__.py CHANGED
@@ -4,7 +4,7 @@
4
4
  tksheet - A Python tkinter table widget
5
5
  """
6
6
 
7
- __version__ = "7.4.11"
7
+ __version__ = "7.4.12"
8
8
 
9
9
  from .colors import (
10
10
  color_map,
tksheet/column_headers.py CHANGED
@@ -1058,44 +1058,6 @@ class ColumnHeaders(tk.Canvas):
1058
1058
  self.MT.run_selection_binding("columns")
1059
1059
  return fill_iid
1060
1060
 
1061
- def display_box(
1062
- self,
1063
- x1: int,
1064
- y1: int,
1065
- x2: int,
1066
- y2: int,
1067
- fill: str,
1068
- outline: str,
1069
- state: str,
1070
- tags: str | tuple[str],
1071
- iid: None | int = None,
1072
- ) -> int:
1073
- coords = rounded_box_coords(
1074
- x1,
1075
- y1,
1076
- x2,
1077
- y2,
1078
- radius=5 if self.ops.rounded_boxes else 0,
1079
- )
1080
- if isinstance(iid, int):
1081
- self.coords(iid, coords)
1082
- self.itemconfig(iid, fill=fill, outline=outline, state=state, tags=tags)
1083
- else:
1084
- if self.hidd_boxes:
1085
- iid = self.hidd_boxes.pop()
1086
- self.coords(iid, coords)
1087
- self.itemconfig(iid, fill=fill, outline=outline, state=state, tags=tags)
1088
- else:
1089
- iid = self.create_polygon(coords, fill=fill, outline=outline, state=state, tags=tags, smooth=True)
1090
- self.disp_boxes.add(iid)
1091
- return iid
1092
-
1093
- def hide_box(self, item: int) -> None:
1094
- if isinstance(item, int):
1095
- self.disp_boxes.discard(item)
1096
- self.hidd_boxes.add(item)
1097
- self.itemconfig(item, state="hidden")
1098
-
1099
1061
  def get_cell_dimensions(self, datacn: int) -> tuple[int, int]:
1100
1062
  txt = self.cell_str(datacn, fix=False)
1101
1063
  if txt:
@@ -1279,6 +1241,7 @@ class ColumnHeaders(tk.Canvas):
1279
1241
  sel_cols_bg: str,
1280
1242
  selections: dict,
1281
1243
  datacn: int,
1244
+ has_dd: bool,
1282
1245
  ) -> tuple[str, bool]:
1283
1246
  redrawn = False
1284
1247
  kwargs = self.get_cell_kwargs(datacn, key="highlight")
@@ -1319,18 +1282,32 @@ class ColumnHeaders(tk.Canvas):
1319
1282
  sc,
1320
1283
  self.current_height - 1,
1321
1284
  fill=fill,
1322
- outline=(
1323
- self.ops.header_fg
1324
- if self.get_cell_kwargs(datacn, key="dropdown") and self.ops.show_dropdown_borders
1325
- else ""
1326
- ),
1285
+ outline=self.ops.header_fg if has_dd and self.ops.show_dropdown_borders else "",
1327
1286
  tag="hi",
1328
1287
  )
1329
1288
  elif not kwargs:
1330
1289
  if "columns" in selections and c in selections["columns"]:
1331
1290
  txtfg = self.ops.header_selected_columns_fg
1291
+ redrawn = self.redraw_highlight(
1292
+ fc + 1,
1293
+ 0,
1294
+ sc,
1295
+ self.current_height - 1,
1296
+ fill=self.ops.header_selected_columns_bg,
1297
+ outline=self.ops.header_fg if has_dd and self.ops.show_dropdown_borders else "",
1298
+ tag="hi",
1299
+ )
1332
1300
  elif "cells" in selections and c in selections["cells"]:
1333
1301
  txtfg = self.ops.header_selected_cells_fg
1302
+ redrawn = self.redraw_highlight(
1303
+ fc + 1,
1304
+ 0,
1305
+ sc,
1306
+ self.current_height - 1,
1307
+ fill=self.ops.header_selected_cells_bg,
1308
+ outline=self.ops.header_fg if has_dd and self.ops.show_dropdown_borders else "",
1309
+ tag="hi",
1310
+ )
1334
1311
  else:
1335
1312
  txtfg = self.ops.header_fg
1336
1313
  return txtfg, redrawn
@@ -1559,6 +1536,7 @@ class ColumnHeaders(tk.Canvas):
1559
1536
  cleftgridln = self.MT.col_positions[c]
1560
1537
  crightgridln = self.MT.col_positions[c + 1]
1561
1538
  datacn = c if self.MT.all_columns_displayed else self.MT.displayed_columns[c]
1539
+ kwargs = self.get_cell_kwargs(datacn, key="dropdown")
1562
1540
  fill, dd_drawn = self.redraw_highlight_get_text_fg(
1563
1541
  fc=cleftgridln,
1564
1542
  sc=crightgridln,
@@ -1567,12 +1545,13 @@ class ColumnHeaders(tk.Canvas):
1567
1545
  sel_cols_bg=sel_cols_bg,
1568
1546
  selections=selections,
1569
1547
  datacn=datacn,
1548
+ has_dd=bool(kwargs),
1570
1549
  )
1571
1550
  if datacn in self.cell_options and "align" in self.cell_options[datacn]:
1572
1551
  align = self.cell_options[datacn]["align"]
1573
1552
  else:
1574
1553
  align = self.align
1575
- if kwargs := self.get_cell_kwargs(datacn, key="dropdown"):
1554
+ if kwargs:
1576
1555
  max_width = crightgridln - cleftgridln - txt_h - 2
1577
1556
  if align.endswith("w"):
1578
1557
  draw_x = cleftgridln + 2
@@ -1664,7 +1643,6 @@ class ColumnHeaders(tk.Canvas):
1664
1643
  anchor=align,
1665
1644
  state="normal",
1666
1645
  )
1667
- self.tag_raise(iid)
1668
1646
  else:
1669
1647
  iid = self.create_text(
1670
1648
  draw_x,
@@ -1709,6 +1687,7 @@ class ColumnHeaders(tk.Canvas):
1709
1687
  if showing:
1710
1688
  self.itemconfig(iid, state="hidden")
1711
1689
  dct[iid] = False
1690
+ self.tag_raise("t")
1712
1691
  if self.disp_resize_lines:
1713
1692
  self.tag_raise("rw")
1714
1693
  return True
@@ -2314,8 +2293,8 @@ class ColumnHeaders(tk.Canvas):
2314
2293
  kwargs = self.get_cell_kwargs(datacn, key=None, cell=c_ops)
2315
2294
  if "checkbox" in kwargs:
2316
2295
  return False
2317
- elif (kwargs := kwargs.get("dropdown", {})) and kwargs["validate_input"] and kwargs["values"]:
2318
- return kwargs["values"][0]
2296
+ elif "dropdown" in kwargs and kwargs["dropdown"]["validate_input"] and kwargs["dropdown"]["values"]:
2297
+ return kwargs["dropdown"]["values"][0]
2319
2298
  else:
2320
2299
  return ""
2321
2300
 
tksheet/functions.py CHANGED
@@ -9,7 +9,7 @@ from bisect import bisect_left
9
9
  from collections import deque
10
10
  from collections.abc import Callable, Generator, Hashable, Iterable, Iterator, Sequence
11
11
  from difflib import SequenceMatcher
12
- from itertools import islice, repeat
12
+ from itertools import chain, islice, repeat
13
13
  from typing import Any, Literal
14
14
 
15
15
  from .colors import color_map
@@ -31,34 +31,16 @@ def wrap_text(
31
31
  wrap: Literal["", "c", "w"] = "",
32
32
  start_line: int = 0,
33
33
  ) -> Generator[str]:
34
- lines = (match.group() for match in lines_re.finditer(text))
35
- current_line = []
36
34
  total_lines = 0
37
35
  line_width = 0
38
-
39
- if not wrap:
40
- for line in lines:
41
- line_width = 0
42
- current_line = []
43
- for char in line:
44
- char_width = widths.get(char, char_width_fn(char))
45
- line_width += char_width
46
- if line_width >= max_width:
47
- break
48
- current_line.append(char)
49
-
50
- if total_lines >= start_line:
51
- yield "".join(current_line)
52
-
53
- # Count the line whether it's empty or not
54
- total_lines += 1
55
- if total_lines >= max_lines:
56
- return
57
-
58
- elif wrap == "c":
59
- for line in lines:
60
- for char in line:
61
- char_width = widths.get(char, char_width_fn(char))
36
+ if wrap == "c":
37
+ current_line = []
38
+ for match in lines_re.finditer(text):
39
+ for char in match.group():
40
+ try:
41
+ char_width = widths[char]
42
+ except KeyError:
43
+ char_width = char_width_fn(char)
62
44
 
63
45
  # adding char to line would result in wrap
64
46
  if line_width + char_width >= max_width:
@@ -89,11 +71,14 @@ def wrap_text(
89
71
  line_width = 0
90
72
 
91
73
  elif wrap == "w":
92
- space_width = widths.get(" ", char_width_fn(" "))
74
+ try:
75
+ space_width = widths[" "]
76
+ except KeyError:
77
+ space_width = char_width_fn(" ")
78
+ current_line = []
93
79
 
94
- for line in lines:
95
- words = line.split()
96
- for i, word in enumerate(words):
80
+ for match in lines_re.finditer(text):
81
+ for i, word in enumerate(match.group().split()):
97
82
  # if we're going to next word and
98
83
  # if a space fits on the end of the current line we add one
99
84
  if i and line_width + space_width < max_width:
@@ -104,8 +89,12 @@ def wrap_text(
104
89
  word_width = 0
105
90
  word_char_widths = []
106
91
  for char in word:
107
- word_char_widths.append((w := widths.get(char, char_width_fn(char))))
108
- word_width += w
92
+ try:
93
+ char_width = widths[char]
94
+ except KeyError:
95
+ char_width = char_width_fn(char)
96
+ word_char_widths.append(char_width)
97
+ word_width += char_width
109
98
 
110
99
  # we only wrap by character if the whole word alone wont fit max width
111
100
  # word won't fit at all we resort to char wrapping it
@@ -167,6 +156,28 @@ def wrap_text(
167
156
  current_line = [] # Reset for next line
168
157
  line_width = 0
169
158
 
159
+ else:
160
+ for match in lines_re.finditer(text):
161
+ line_width = 0
162
+ current_line = []
163
+ for char in match.group():
164
+ try:
165
+ char_width = widths[char]
166
+ except KeyError:
167
+ char_width = char_width_fn(char)
168
+ line_width += char_width
169
+ if line_width >= max_width:
170
+ break
171
+ current_line.append(char)
172
+
173
+ if total_lines >= start_line:
174
+ yield "".join(current_line)
175
+
176
+ # Count the line whether it's empty or not
177
+ total_lines += 1
178
+ if total_lines >= max_lines:
179
+ return
180
+
170
181
 
171
182
  def get_csv_str_dialect(s: str, delimiters: str) -> csv.Dialect:
172
183
  if len(s) > 6000:
@@ -1684,3 +1695,51 @@ def pop_positions(
1684
1695
  save_to[to_pop[i]] = pos
1685
1696
  else:
1686
1697
  yield pos
1698
+
1699
+
1700
+ def get_horizontal_gridline_points(
1701
+ left: float,
1702
+ stop: float,
1703
+ positions: list[float],
1704
+ start: int,
1705
+ end: int,
1706
+ ) -> list[int | float]:
1707
+ return list(
1708
+ chain.from_iterable(
1709
+ (
1710
+ left - 1,
1711
+ positions[r],
1712
+ stop,
1713
+ positions[r],
1714
+ left - 1,
1715
+ positions[r],
1716
+ left - 1,
1717
+ positions[r + 1] if len(positions) - 1 > r else positions[r],
1718
+ )
1719
+ for r in range(start, end)
1720
+ )
1721
+ )
1722
+
1723
+
1724
+ def get_vertical_gridline_points(
1725
+ top: float,
1726
+ stop: float,
1727
+ positions: list[float],
1728
+ start: int,
1729
+ end: int,
1730
+ ) -> list[float]:
1731
+ return list(
1732
+ chain.from_iterable(
1733
+ (
1734
+ positions[c],
1735
+ top - 1,
1736
+ positions[c],
1737
+ stop,
1738
+ positions[c],
1739
+ top - 1,
1740
+ positions[c + 1] if len(positions) - 1 > c else positions[c],
1741
+ top - 1,
1742
+ )
1743
+ for c in range(start, end)
1744
+ )
1745
+ )
tksheet/main_table.py CHANGED
@@ -60,9 +60,11 @@ from .functions import (
60
60
  gen_formatted,
61
61
  get_bg_fg,
62
62
  get_data_from_clipboard,
63
+ get_horizontal_gridline_points,
63
64
  get_menu_kwargs,
64
65
  get_new_indexes,
65
66
  get_seq_without_gaps_at_index,
67
+ get_vertical_gridline_points,
66
68
  index_exists,
67
69
  insert_items,
68
70
  int_x_iter,
@@ -149,6 +151,9 @@ class MainTable(tk.Canvas):
149
151
  "<<SelectAll>>": self.select_all,
150
152
  }
151
153
  self.enabled_bindings = set()
154
+ self.selection_box_ctr = 0
155
+ self.disp_selection_fills = set()
156
+ self.hidd_selection_fills = set()
152
157
 
153
158
  self.disp_ctrl_outline = {}
154
159
  self.disp_text = {}
@@ -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:
@@ -5875,12 +5859,20 @@ class MainTable(tk.Canvas):
5875
5859
  can_width: int | None,
5876
5860
  dont_blend: bool,
5877
5861
  alternate_color: Highlight | None,
5862
+ has_dd: bool = False,
5878
5863
  ) -> tuple[str, bool]:
5879
5864
  redrawn = False
5880
5865
  if (datarn, datacn) in self.progress_bars:
5881
5866
  kwargs = self.progress_bars[(datarn, datacn)]
5882
5867
  else:
5883
- kwargs = self.get_cell_kwargs(datarn, datacn, key="highlight")
5868
+ if (datarn, datacn) in self.cell_options and "highlight" in self.cell_options[(datarn, datacn)]:
5869
+ kwargs = self.cell_options[(datarn, datacn)]["highlight"]
5870
+ elif datarn in self.row_options and "highlight" in self.row_options[datarn]:
5871
+ kwargs = self.row_options[datarn]["highlight"]
5872
+ elif datacn in self.col_options and "highlight" in self.col_options[datacn]:
5873
+ kwargs = self.col_options[datacn]["highlight"]
5874
+ else:
5875
+ kwargs = {}
5884
5876
  if alt := bool(not kwargs and alternate_color and r % 2):
5885
5877
  kwargs = alternate_color
5886
5878
 
@@ -5942,39 +5934,68 @@ class MainTable(tk.Canvas):
5942
5934
  txtfg = self.PAR.ops.table_fg if kwargs[1] is None else kwargs[1]
5943
5935
 
5944
5936
  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):
5937
+ if not isinstance(kwargs, ProgressBar):
5938
+ redrawn = self.redraw_highlight(
5939
+ x1=fc + 1,
5940
+ y1=fr + 1,
5941
+ x2=sc,
5942
+ y2=sr,
5943
+ fill=fill,
5944
+ outline=self.PAR.ops.table_fg if has_dd and self.PAR.ops.show_dropdown_borders else "",
5945
+ can_width=can_width if (len(kwargs) > 2 and kwargs[2]) else None,
5946
+ pc=None,
5947
+ )
5948
+ else:
5959
5949
  if kwargs.del_when_done and kwargs.percent >= 100:
5960
5950
  del self.progress_bars[(datarn, datacn)]
5961
5951
  else:
5962
- redrawn = highlight_fn(
5952
+ redrawn = self.redraw_highlight(
5953
+ x1=fc + 1,
5954
+ y1=fr + 1,
5955
+ x2=sc,
5956
+ y2=sr,
5957
+ fill=fill,
5958
+ outline=self.PAR.ops.table_fg if has_dd and self.PAR.ops.show_dropdown_borders else "",
5963
5959
  can_width=None,
5964
5960
  pc=kwargs.percent,
5965
5961
  )
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
5962
  elif not kwargs:
5972
5963
  if "cells" in selections and (r, c) in selections["cells"]:
5973
5964
  txtfg = self.PAR.ops.table_selected_cells_fg
5965
+ redrawn = self.redraw_highlight(
5966
+ x1=fc + 1,
5967
+ y1=fr + 1,
5968
+ x2=sc,
5969
+ y2=sr,
5970
+ fill=self.PAR.ops.table_selected_cells_bg,
5971
+ outline=self.PAR.ops.table_fg if has_dd and self.PAR.ops.show_dropdown_borders else "",
5972
+ can_width=None,
5973
+ pc=None,
5974
+ )
5974
5975
  elif "rows" in selections and r in selections["rows"]:
5975
5976
  txtfg = self.PAR.ops.table_selected_rows_fg
5977
+ redrawn = self.redraw_highlight(
5978
+ x1=fc + 1,
5979
+ y1=fr + 1,
5980
+ x2=sc,
5981
+ y2=sr,
5982
+ fill=self.PAR.ops.table_selected_rows_bg,
5983
+ outline=self.PAR.ops.table_fg if has_dd and self.PAR.ops.show_dropdown_borders else "",
5984
+ can_width=None,
5985
+ pc=None,
5986
+ )
5976
5987
  elif "columns" in selections and c in selections["columns"]:
5977
5988
  txtfg = self.PAR.ops.table_selected_columns_fg
5989
+ redrawn = self.redraw_highlight(
5990
+ x1=fc + 1,
5991
+ y1=fr + 1,
5992
+ x2=sc,
5993
+ y2=sr,
5994
+ fill=self.PAR.ops.table_selected_columns_bg,
5995
+ outline=self.PAR.ops.table_fg if has_dd and self.PAR.ops.show_dropdown_borders else "",
5996
+ can_width=None,
5997
+ pc=None,
5998
+ )
5978
5999
  else:
5979
6000
  txtfg = self.PAR.ops.table_fg
5980
6001
  return txtfg, redrawn
@@ -6257,11 +6278,24 @@ class MainTable(tk.Canvas):
6257
6278
  else:
6258
6279
  datacn = c if self.all_columns_displayed else self.displayed_columns[c]
6259
6280
  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)
6281
+ t = (datarn, datacn)
6282
+
6283
+ # self.get_cell_kwargs not used here to boost performance
6284
+ if t in self.cell_options and "dropdown" in self.cell_options[t]:
6285
+ cells["dropdown"][t] = self.cell_options[t]["dropdown"]
6286
+ elif datarn in self.row_options and "dropdown" in self.row_options[datarn]:
6287
+ cells["dropdown"][t] = self.row_options[datarn]["dropdown"]
6288
+ elif datacn in self.col_options and "dropdown" in self.col_options[datacn]:
6289
+ cells["dropdown"][t] = self.col_options[datacn]["dropdown"]
6290
+ else:
6291
+ if t in self.cell_options and "checkbox" in self.cell_options[t]:
6292
+ cells["checkbox"][t] = self.cell_options[t]["checkbox"]
6293
+ elif datarn in self.row_options and "checkbox" in self.row_options[datarn]:
6294
+ cells["checkbox"][t] = self.row_options[datarn]["checkbox"]
6295
+ elif datacn in self.col_options and "checkbox" in self.col_options[datacn]:
6296
+ cells["checkbox"][t] = self.col_options[datacn]["checkbox"]
6297
+
6298
+ cells[t] = self.cell_str(datarn, datacn, get_displayed=True)
6265
6299
  return cells
6266
6300
 
6267
6301
  def wrap_get_char_w(self, c: str) -> int:
@@ -6346,7 +6380,6 @@ class MainTable(tk.Canvas):
6346
6380
  if changed_w:
6347
6381
  for widget in (self, self.RI, self.CH, self.TL):
6348
6382
  widget.update_idletasks()
6349
- return False
6350
6383
  # important vars
6351
6384
  x_stop = min(last_col_line_pos, scrollpos_right)
6352
6385
  y_stop = min(last_row_line_pos, scrollpos_bot)
@@ -6363,27 +6396,20 @@ class MainTable(tk.Canvas):
6363
6396
  self.disp_dropdown = {}
6364
6397
  self.hidd_checkbox.update(self.disp_checkbox)
6365
6398
  self.disp_checkbox = {}
6399
+ points = []
6366
6400
  # manage horizontal grid lines
6367
6401
  if self.PAR.ops.show_horizontal_grid and row_pos_exists:
6368
6402
  if self.PAR.ops.horizontal_grid_to_end_of_window:
6369
6403
  x_grid_stop = scrollpos_right + can_width
6370
6404
  else:
6371
6405
  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
- )
6406
+ points.extend(
6407
+ get_horizontal_gridline_points(
6408
+ left=scrollpos_left,
6409
+ stop=x_grid_stop,
6410
+ positions=self.row_positions,
6411
+ start=grid_start_row,
6412
+ end=grid_end_row,
6387
6413
  )
6388
6414
  )
6389
6415
  # manage vertical grid lines
@@ -6392,23 +6418,20 @@ class MainTable(tk.Canvas):
6392
6418
  y_grid_stop = scrollpos_bot + can_height
6393
6419
  else:
6394
6420
  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
- ),
6421
+ if self.PAR.ops.show_horizontal_grid:
6422
+ points.extend([scrollpos_left - 2, grid_end_row, grid_start_col - 2, scrollpos_top - 2])
6423
+ points.extend(
6424
+ get_vertical_gridline_points(
6425
+ top=scrollpos_top,
6426
+ stop=y_grid_stop,
6427
+ positions=self.col_positions,
6428
+ start=grid_start_col,
6429
+ end=grid_end_col,
6430
+ )
6411
6431
  )
6432
+ if points:
6433
+ self.redraw_gridline(points)
6434
+
6412
6435
  font = self.PAR.ops.table_font
6413
6436
  dd_coords = self.dropdown.get_coords()
6414
6437
  selections = self.get_redraw_selections(text_start_row, grid_end_row, text_start_col, grid_end_col)
@@ -6454,6 +6477,8 @@ class MainTable(tk.Canvas):
6454
6477
  cleftgridln = self.col_positions[c]
6455
6478
  crightgridln = self.col_positions[c + 1]
6456
6479
  datacn = cells["datacn"][c]
6480
+ t = (datarn, datacn)
6481
+
6457
6482
  fill, dd_drawn = self.redraw_highlight_get_text_fg(
6458
6483
  r=r,
6459
6484
  c=c,
@@ -6470,11 +6495,19 @@ class MainTable(tk.Canvas):
6470
6495
  can_width=can_width,
6471
6496
  dont_blend=(r, c) == dont_blend,
6472
6497
  alternate_color=alternate_color,
6498
+ has_dd=t in cells["dropdown"],
6473
6499
  )
6474
- if not (align := self.get_cell_kwargs(datarn, datacn, key="align")):
6500
+ if t in self.cell_options and "align" in self.cell_options[(datarn, datacn)]:
6501
+ align = self.cell_options[(datarn, datacn)]["align"]
6502
+ elif datarn in self.row_options and "align" in self.row_options[datarn]:
6503
+ align = self.row_options[datarn]["align"]
6504
+ elif datacn in self.col_options and "align" in self.col_options[datacn]:
6505
+ align = self.col_options[datacn]["align"]
6506
+ else:
6475
6507
  align = self.align
6476
6508
 
6477
- if kwargs := cells["dropdown"].get((datarn, datacn), None):
6509
+ kws = cells["dropdown"][t] if t in cells["dropdown"] else None # noqa: SIM401
6510
+ if kws:
6478
6511
  max_width = crightgridln - cleftgridln - self.table_txt_height - 5
6479
6512
  if align.endswith("w"):
6480
6513
  draw_x = cleftgridln + 2
@@ -6487,7 +6520,7 @@ class MainTable(tk.Canvas):
6487
6520
  rtopgridln,
6488
6521
  crightgridln,
6489
6522
  self.row_positions[r + 1],
6490
- fill=fill if kwargs["state"] != "disabled" else self.PAR.ops.table_grid_fg,
6523
+ fill=fill if kws["state"] != "disabled" else self.PAR.ops.table_grid_fg,
6491
6524
  outline=fill,
6492
6525
  draw_outline=not dd_drawn,
6493
6526
  draw_arrow=max_width >= 5,
@@ -6502,9 +6535,8 @@ class MainTable(tk.Canvas):
6502
6535
  elif align.endswith("n"):
6503
6536
  draw_x = cleftgridln + floor((crightgridln - cleftgridln) / 2)
6504
6537
 
6505
- if (
6506
- kwargs := cells["checkbox"].get((datarn, datacn), None)
6507
- ) and max_width > self.table_txt_height + 1:
6538
+ kws = cells["checkbox"][t] if t in cells["checkbox"] else None # noqa: SIM401
6539
+ if kws and max_width > self.table_txt_height + 1:
6508
6540
  box_w = self.table_txt_height + 1
6509
6541
  if align.endswith("w"):
6510
6542
  draw_x += box_w + 3
@@ -6520,11 +6552,11 @@ class MainTable(tk.Canvas):
6520
6552
  rtopgridln + 2,
6521
6553
  cleftgridln + self.table_txt_height + 3,
6522
6554
  rtopgridln + self.table_txt_height + 3,
6523
- fill=fill if kwargs["state"] == "normal" else self.PAR.ops.table_grid_fg,
6555
+ fill=fill if kws["state"] == "normal" else self.PAR.ops.table_grid_fg,
6524
6556
  outline="",
6525
6557
  draw_check=draw_check,
6526
6558
  )
6527
- text = cells[(datarn, datacn)]
6559
+ text = cells[t]
6528
6560
  if (
6529
6561
  not text
6530
6562
  or (align.endswith("w") and draw_x > scrollpos_right)
@@ -6532,7 +6564,7 @@ class MainTable(tk.Canvas):
6532
6564
  or (align.endswith("n") and cleftgridln + 5 > scrollpos_right)
6533
6565
  ):
6534
6566
  continue
6535
- if allow_overflow and not kwargs:
6567
+ if allow_overflow and not kws:
6536
6568
  if align.endswith("w"):
6537
6569
  max_width += sum(self._overflow(cells, range(c + 1, text_end_col), datarn))
6538
6570
  elif align.endswith("e"):
@@ -6573,7 +6605,6 @@ class MainTable(tk.Canvas):
6573
6605
  anchor=align,
6574
6606
  state="normal",
6575
6607
  )
6576
- self.tag_raise(iid)
6577
6608
  else:
6578
6609
  iid = self.create_text(
6579
6610
  draw_x,
@@ -6608,7 +6639,6 @@ class MainTable(tk.Canvas):
6608
6639
  anchor=align,
6609
6640
  state="normal",
6610
6641
  )
6611
- self.tag_raise(iid)
6612
6642
  else:
6613
6643
  iid = self.create_text(
6614
6644
  draw_x,
@@ -6638,6 +6668,7 @@ class MainTable(tk.Canvas):
6638
6668
  self.tag_raise(box.bd_iid)
6639
6669
  if self.selected:
6640
6670
  self.tag_raise(self.selected.iid)
6671
+ self.tag_raise("t")
6641
6672
  if self.RI.disp_resize_lines:
6642
6673
  self.tag_raise("rh")
6643
6674
  if self.CH.disp_resize_lines:
@@ -6772,26 +6803,20 @@ class MainTable(tk.Canvas):
6772
6803
  c: int,
6773
6804
  type_: Literal["cells", "rows", "columns"],
6774
6805
  fill_iid: int,
6775
- lower_selection_boxes: bool = True,
6776
6806
  ) -> int:
6777
- fill, outline = self.get_selected_box_bg_fg(type_=type_)
6807
+ _, outline = self.get_selected_box_bg_fg(type_=type_)
6778
6808
  x1 = self.col_positions[c] + 1
6779
6809
  y1 = self.row_positions[r] + 1
6780
6810
  x2 = self.col_positions[c + 1] if index_exists(self.col_positions, c + 1) else self.col_positions[c] + 1
6781
6811
  y2 = self.row_positions[r + 1] if index_exists(self.row_positions, r + 1) else self.row_positions[r] + 1
6782
6812
  self.hide_selected()
6783
- if self.PAR.ops.show_selected_cells_border:
6784
- fill = ""
6785
- else:
6786
- fill = outline
6787
- outline = ""
6788
6813
  iid = self.display_box(
6789
6814
  x1,
6790
6815
  y1,
6791
6816
  x2,
6792
6817
  y2,
6793
- fill=fill,
6794
- outline=outline,
6818
+ fill="",
6819
+ outline=outline if self.PAR.ops.show_selected_cells_border else "",
6795
6820
  state="normal",
6796
6821
  tags="selected",
6797
6822
  width=2,
@@ -6804,8 +6829,6 @@ class MainTable(tk.Canvas):
6804
6829
  iid=iid,
6805
6830
  fill_iid=fill_iid,
6806
6831
  )
6807
- if lower_selection_boxes:
6808
- self.lower_selection_boxes()
6809
6832
  return iid
6810
6833
 
6811
6834
  def display_box(
@@ -6856,14 +6879,17 @@ class MainTable(tk.Canvas):
6856
6879
  self.hidd_boxes.add(item)
6857
6880
  self.itemconfig(item, state="hidden")
6858
6881
 
6882
+ def hide_box_fill(self, item: int | None) -> None:
6883
+ if isinstance(item, int):
6884
+ self.disp_selection_fills.discard(item)
6885
+ self.hidd_selection_fills.add(item)
6886
+
6859
6887
  def hide_selection_box(self, item: int | None) -> bool:
6860
6888
  if item is None or item is True or item not in self.selection_boxes:
6861
6889
  return False
6862
6890
  box = self.selection_boxes.pop(item)
6863
- self.hide_box(box.fill_iid)
6891
+ self.hide_box_fill(box.fill_iid)
6864
6892
  self.hide_box(box.bd_iid)
6865
- self.RI.hide_box(box.index)
6866
- self.CH.hide_box(box.header)
6867
6893
  if self.selected.fill_iid == item:
6868
6894
  self.hide_selected()
6869
6895
  self.set_current_to_last()
@@ -6880,6 +6906,15 @@ class MainTable(tk.Canvas):
6880
6906
  self.hide_box(self.selected.iid)
6881
6907
  self.selected = ()
6882
6908
 
6909
+ def get_selection_fill(self) -> int:
6910
+ if self.hidd_selection_fills:
6911
+ iid = self.hidd_selection_fills.pop()
6912
+ else:
6913
+ self.selection_box_ctr += 1
6914
+ iid = self.selection_box_ctr
6915
+ self.disp_selection_fills.add(iid)
6916
+ return iid
6917
+
6883
6918
  def create_selection_box(
6884
6919
  self,
6885
6920
  r1: int,
@@ -6899,52 +6934,35 @@ class MainTable(tk.Canvas):
6899
6934
  r1 = 0
6900
6935
  r2 = 0
6901
6936
  if type_ == "cells":
6902
- mt_bg = self.PAR.ops.table_selected_cells_bg
6903
6937
  mt_border_col = self.PAR.ops.table_selected_cells_border_fg
6904
6938
  elif type_ == "rows":
6905
- mt_bg = self.PAR.ops.table_selected_rows_bg
6906
6939
  mt_border_col = self.PAR.ops.table_selected_rows_border_fg
6907
6940
  elif type_ == "columns":
6908
- mt_bg = self.PAR.ops.table_selected_columns_bg
6909
6941
  mt_border_col = self.PAR.ops.table_selected_columns_border_fg
6910
6942
  if self.selection_boxes:
6911
- self.itemconfig(next(reversed(self.selection_boxes)), state="normal")
6943
+ next(reversed(self.selection_boxes.values())).state = "normal"
6912
6944
  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
- )
6945
+ fill_iid = self.get_selection_fill()
6946
6946
  bd_iid = None
6947
- if self.PAR.ops.show_selected_cells_border and (
6947
+ # fill might not display if canvas is wider than 32k pixels
6948
+ if self.PAR.ops.selected_rows_to_end_of_window and type_ == "rows":
6949
+ bd_iid = self.display_box(
6950
+ x1,
6951
+ y1,
6952
+ x2,
6953
+ y2,
6954
+ fill=self.PAR.ops.table_selected_rows_bg,
6955
+ outline=""
6956
+ if self.PAR.name == "!SheetDropdown"
6957
+ else mt_border_col
6958
+ if self.PAR.ops.show_selected_cells_border
6959
+ else "",
6960
+ state="normal",
6961
+ tags=f"{type_}bd",
6962
+ width=1,
6963
+ )
6964
+ self.tag_lower(bd_iid)
6965
+ elif self.PAR.ops.show_selected_cells_border and (
6948
6966
  ext
6949
6967
  or self.ctrl_b1_pressed
6950
6968
  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 +6982,11 @@ class MainTable(tk.Canvas):
6964
6982
  self.selection_boxes[fill_iid] = SelectionBox(
6965
6983
  fill_iid=fill_iid,
6966
6984
  bd_iid=bd_iid,
6967
- index=index_iid,
6968
- header=header_iid,
6985
+ index=fill_iid,
6986
+ header=fill_iid,
6969
6987
  coords=Box_nt(r1, c1, r2, c2),
6970
6988
  type_=type_,
6989
+ state=state,
6971
6990
  )
6972
6991
  if set_current:
6973
6992
  if set_current is True:
@@ -6976,26 +6995,11 @@ class MainTable(tk.Canvas):
6976
6995
  elif isinstance(set_current, tuple):
6977
6996
  curr_r = set_current[0]
6978
6997
  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()
6998
+ self.create_currently_selected_box(curr_r, curr_c, type_, fill_iid)
6981
6999
  if run_binding:
6982
7000
  self.run_selection_binding(type_)
6983
7001
  return fill_iid
6984
7002
 
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
7003
  def box_coords_x_canvas_coords(
7000
7004
  self,
7001
7005
  r1: int,
@@ -7026,13 +7030,10 @@ class MainTable(tk.Canvas):
7026
7030
  type_ = self.selection_boxes[fill_iid].type_
7027
7031
  self.selection_boxes[fill_iid].coords = Box_nt(r1, c1, r2, c2)
7028
7032
  if type_ == "cells":
7029
- mt_bg = self.PAR.ops.table_selected_cells_bg
7030
7033
  mt_border_col = self.PAR.ops.table_selected_cells_border_fg
7031
7034
  elif type_ == "rows":
7032
- mt_bg = self.PAR.ops.table_selected_rows_bg
7033
7035
  mt_border_col = self.PAR.ops.table_selected_rows_border_fg
7034
7036
  elif type_ == "columns":
7035
- mt_bg = self.PAR.ops.table_selected_columns_bg
7036
7037
  mt_border_col = self.PAR.ops.table_selected_columns_border_fg
7037
7038
  if not state:
7038
7039
  if r2 - r1 > 1 or c2 - c1 > 1:
@@ -7044,31 +7045,7 @@ class MainTable(tk.Canvas):
7044
7045
  if self.selected.fill_iid == fill_iid:
7045
7046
  self.selected = self.selected._replace(box=Box_nt(r1, c1, r2, c2))
7046
7047
  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
- )
7048
+ self.selection_boxes[fill_iid].state = state
7072
7049
  if bd_iid := self.selection_boxes[fill_iid].bd_iid:
7073
7050
  if self.PAR.ops.show_selected_cells_border:
7074
7051
  self.display_box(
@@ -7142,19 +7119,20 @@ class MainTable(tk.Canvas):
7142
7119
  d = defaultdict(set)
7143
7120
  for _, box in self.get_selection_items():
7144
7121
  r1, c1, r2, c2 = box.coords
7145
- if box.type_ == "cells":
7146
- for r in range(startr, endr):
7122
+ if box.state == "normal":
7123
+ if box.type_ == "cells":
7124
+ for r in range(startr, endr):
7125
+ for c in range(startc, endc):
7126
+ if r1 <= r and c1 <= c and r2 > r and c2 > c:
7127
+ d["cells"].add((r, c))
7128
+ elif box.type_ == "rows":
7129
+ for r in range(startr, endr):
7130
+ if r1 <= r and r2 > r:
7131
+ d["rows"].add(r)
7132
+ elif box.type_ == "columns":
7147
7133
  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)
7134
+ if c1 <= c and c2 > c:
7135
+ d["columns"].add(c)
7158
7136
  return d
7159
7137
 
7160
7138
  def get_selected_min_max(self) -> tuple[int, int, int, int] | tuple[None, None, None, None]:
@@ -8001,8 +7979,8 @@ class MainTable(tk.Canvas):
8001
7979
  )
8002
7980
  if "checkbox" in kwargs:
8003
7981
  return False
8004
- elif (kwargs := kwargs.get("dropdown", {})) and kwargs["validate_input"] and kwargs["values"]:
8005
- return kwargs["values"][0]
7982
+ elif "dropdown" in kwargs and kwargs["dropdown"]["validate_input"] and kwargs["dropdown"]["values"]:
7983
+ return kwargs["dropdown"]["values"][0]
8006
7984
  else:
8007
7985
  return ""
8008
7986
 
@@ -8168,7 +8146,7 @@ class MainTable(tk.Canvas):
8168
8146
  elif "format" in kwargs:
8169
8147
  return True
8170
8148
  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"]
8149
+ "dropdown" in kwargs and kwargs["dropdown"]["validate_input"] and value not in kwargs["dropdown"]["values"]
8172
8150
  ):
8173
8151
  return False
8174
8152
  elif "checkbox" in kwargs:
tksheet/other_classes.py CHANGED
@@ -40,7 +40,7 @@ DraggedRowColumn = namedtuple("DraggedRowColumn", "dragged to_move")
40
40
 
41
41
 
42
42
  class SelectionBox:
43
- __slots__ = ("fill_iid", "bd_iid", "index", "header", "coords", "type_")
43
+ __slots__ = ("fill_iid", "bd_iid", "index", "header", "coords", "type_", "state")
44
44
 
45
45
  def __init__(
46
46
  self,
@@ -50,6 +50,7 @@ class SelectionBox:
50
50
  header: int | None = None,
51
51
  coords: tuple[int, int, int, int] = None,
52
52
  type_: Literal["cells", "rows", "columns"] = "cells",
53
+ state: Literal["normal", "hidden"] = "normal",
53
54
  ) -> None:
54
55
  self.fill_iid = fill_iid
55
56
  self.bd_iid = bd_iid
@@ -57,6 +58,7 @@ class SelectionBox:
57
58
  self.header = header
58
59
  self.coords = coords
59
60
  self.type_ = type_
61
+ self.state = state
60
62
 
61
63
 
62
64
  Selected = namedtuple(
tksheet/row_index.py CHANGED
@@ -1054,51 +1054,6 @@ class RowIndex(tk.Canvas):
1054
1054
  self.MT.run_selection_binding("rows")
1055
1055
  return fill_iid
1056
1056
 
1057
- def display_box(
1058
- self,
1059
- x1: int,
1060
- y1: int,
1061
- x2: int,
1062
- y2: int,
1063
- fill: str,
1064
- outline: str,
1065
- state: str,
1066
- tags: str | tuple[str],
1067
- iid: None | int = None,
1068
- ) -> int:
1069
- coords = rounded_box_coords(
1070
- x1,
1071
- y1,
1072
- x2,
1073
- y2,
1074
- radius=5 if self.ops.rounded_boxes else 0,
1075
- )
1076
- if isinstance(iid, int):
1077
- self.coords(iid, coords)
1078
- self.itemconfig(iid, fill=fill, outline=outline, state=state, tags=tags)
1079
- else:
1080
- if self.hidd_boxes:
1081
- iid = self.hidd_boxes.pop()
1082
- self.coords(iid, coords)
1083
- self.itemconfig(iid, fill=fill, outline=outline, state=state, tags=tags)
1084
- else:
1085
- iid = self.create_polygon(
1086
- coords,
1087
- fill=fill,
1088
- outline=outline,
1089
- state=state,
1090
- tags=tags,
1091
- smooth=True,
1092
- )
1093
- self.disp_boxes.add(iid)
1094
- return iid
1095
-
1096
- def hide_box(self, item: int | None) -> None:
1097
- if isinstance(item, int):
1098
- self.disp_boxes.discard(item)
1099
- self.hidd_boxes.add(item)
1100
- self.itemconfig(item, state="hidden")
1101
-
1102
1057
  def get_cell_dimensions(self, datarn: int) -> tuple[int, int]:
1103
1058
  txt = self.cell_str(datarn, fix=False)
1104
1059
  if txt:
@@ -1308,6 +1263,7 @@ class RowIndex(tk.Canvas):
1308
1263
  sel_rows_bg: str,
1309
1264
  selections: dict,
1310
1265
  datarn: int,
1266
+ has_dd: bool,
1311
1267
  ) -> tuple[str, str, bool]:
1312
1268
  redrawn = False
1313
1269
  kwargs = self.get_cell_kwargs(datarn, key="highlight")
@@ -1348,11 +1304,7 @@ class RowIndex(tk.Canvas):
1348
1304
  self.current_width - 1,
1349
1305
  sr,
1350
1306
  fill=fill,
1351
- outline=(
1352
- self.ops.index_fg
1353
- if self.get_cell_kwargs(datarn, key="dropdown") and self.ops.show_dropdown_borders
1354
- else ""
1355
- ),
1307
+ outline=self.ops.index_fg if has_dd and self.ops.show_dropdown_borders else "",
1356
1308
  tag="s",
1357
1309
  )
1358
1310
  tree_arrow_fg = txtfg
@@ -1360,9 +1312,27 @@ class RowIndex(tk.Canvas):
1360
1312
  if "rows" in selections and r in selections["rows"]:
1361
1313
  txtfg = self.ops.index_selected_rows_fg
1362
1314
  tree_arrow_fg = self.ops.selected_rows_tree_arrow_fg
1315
+ redrawn = self.redraw_highlight(
1316
+ 0,
1317
+ fr + 1,
1318
+ self.current_width - 1,
1319
+ sr,
1320
+ fill=self.ops.index_selected_rows_bg,
1321
+ outline=self.ops.index_fg if has_dd and self.ops.show_dropdown_borders else "",
1322
+ tag="s",
1323
+ )
1363
1324
  elif "cells" in selections and r in selections["cells"]:
1364
1325
  txtfg = self.ops.index_selected_cells_fg
1365
1326
  tree_arrow_fg = self.ops.selected_cells_tree_arrow_fg
1327
+ redrawn = self.redraw_highlight(
1328
+ 0,
1329
+ fr + 1,
1330
+ self.current_width - 1,
1331
+ sr,
1332
+ fill=self.ops.index_selected_cells_bg,
1333
+ outline=self.ops.index_fg if has_dd and self.ops.show_dropdown_borders else "",
1334
+ tag="s",
1335
+ )
1366
1336
  else:
1367
1337
  txtfg = self.ops.index_fg
1368
1338
  tree_arrow_fg = self.ops.tree_arrow_fg
@@ -1686,6 +1656,7 @@ class RowIndex(tk.Canvas):
1686
1656
  continue
1687
1657
  checkbox_kwargs = {}
1688
1658
  datarn = r if self.MT.all_rows_displayed else self.MT.displayed_rows[r]
1659
+ dropdown_kwargs = self.get_cell_kwargs(datarn, key="dropdown")
1689
1660
  fill, tree_arrow_fg, dd_drawn = self.redraw_highlight_get_text_fg(
1690
1661
  fr=rtopgridln,
1691
1662
  sr=rbotgridln,
@@ -1694,12 +1665,14 @@ class RowIndex(tk.Canvas):
1694
1665
  sel_rows_bg=sel_rows_bg,
1695
1666
  selections=selections,
1696
1667
  datarn=datarn,
1668
+ has_dd=bool(dropdown_kwargs),
1697
1669
  )
1670
+
1698
1671
  if datarn in self.cell_options and "align" in self.cell_options[datarn]:
1699
1672
  align = self.cell_options[datarn]["align"]
1700
1673
  else:
1701
1674
  align = self.align
1702
- if dropdown_kwargs := self.get_cell_kwargs(datarn, key="dropdown"):
1675
+ if dropdown_kwargs:
1703
1676
  max_width = self.current_width - self.MT.index_txt_height - 2
1704
1677
  if align.endswith("w"):
1705
1678
  draw_x = 3
@@ -1811,7 +1784,6 @@ class RowIndex(tk.Canvas):
1811
1784
  anchor=align,
1812
1785
  state="normal",
1813
1786
  )
1814
- self.tag_raise(iid)
1815
1787
  else:
1816
1788
  iid = self.create_text(
1817
1789
  draw_x,
@@ -1845,7 +1817,6 @@ class RowIndex(tk.Canvas):
1845
1817
  anchor=align,
1846
1818
  state="normal",
1847
1819
  )
1848
- self.tag_raise(iid)
1849
1820
  else:
1850
1821
  iid = self.create_text(
1851
1822
  draw_x,
@@ -1898,6 +1869,7 @@ class RowIndex(tk.Canvas):
1898
1869
  if showing:
1899
1870
  self.itemconfig(iid, state="hidden")
1900
1871
  dct[iid] = False
1872
+ self.tag_raise("t")
1901
1873
  if self.disp_resize_lines:
1902
1874
  self.tag_raise("rh")
1903
1875
  return True
@@ -2505,8 +2477,8 @@ class RowIndex(tk.Canvas):
2505
2477
  kwargs = self.get_cell_kwargs(datarn, key=None, cell=r_ops)
2506
2478
  if "checkbox" in kwargs:
2507
2479
  return False
2508
- elif (kwargs := kwargs.get("dropdown", {})) and kwargs["validate_input"] and kwargs["values"]:
2509
- return kwargs["values"][0]
2480
+ elif "dropdown" in kwargs and kwargs["dropdown"]["validate_input"] and kwargs["dropdown"]["values"]:
2481
+ return kwargs["dropdown"]["values"][0]
2510
2482
  else:
2511
2483
  return ""
2512
2484
 
@@ -2760,7 +2732,7 @@ class RowIndex(tk.Canvas):
2760
2732
  if new_loc_is_displayed:
2761
2733
  if disp_insert_row is None:
2762
2734
  if new_parent or insert_row > move_to_row:
2763
- disp_insert_row = self.MT.disprn(self.rns[move_to_iid]) + 1
2735
+ disp_insert_row = self.MT.disprn(self.rns[move_to_iid]) + 1 # TODO: maybe issues here
2764
2736
  else:
2765
2737
  disp_insert_row = self.MT.disprn(self.rns[move_to_iid])
2766
2738
  if (disp_from_row := self.MT.try_disprn(self.rns[item])) is not None:
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.2
2
2
  Name: tksheet
3
- Version: 7.4.11
3
+ Version: 7.4.12
4
4
  Summary: Tkinter table / sheet and treeview widget
5
5
  Author-email: ragardner <github@ragardner.simplelogin.com>
6
6
  License: Copyright (c) 2019 ragardner and open source contributors
@@ -63,11 +63,11 @@ License-File: LICENSE.txt
63
63
  <tbody>
64
64
  <tr>
65
65
  <td style="color: LightCoral">Versions 6.x.x &#8594;</td>
66
- <td><a href="https://github.com/ragardner/tksheet/wiki/Version-6">Documentation Wiki</a></td>
66
+ <td><a href="https://github.com/ragardner/tksheet/wiki/Version-6">Documentation</a></td>
67
67
  </tr>
68
68
  <tr>
69
69
  <td style="color: lightgreen">Versions 7.x.x &#8594;</td>
70
- <td><a href="https://github.com/ragardner/tksheet/wiki/Version-7">Documentation Wiki</a></td>
70
+ <td><a href="https://ragardner.github.io/tksheet/DOCUMENTATION.html">Documentation</a></td>
71
71
  </tr>
72
72
  <tr>
73
73
  <td align="right" colspan="2"><a href="https://github.com/ragardner/tksheet/blob/master/docs/CHANGELOG.md">Changelog</a></td>
@@ -1,13 +1,13 @@
1
- tksheet/__init__.py,sha256=1b9l4y5i0jLE4wVnad_Xu_WSHysrpf1dhK8uTjBH734,2327
1
+ tksheet/__init__.py,sha256=6B6RTt5-41j4-VcGxzbvcO6Ggfd56Ooy0GwxL_kfLhI,2327
2
2
  tksheet/colors.py,sha256=dHhmdFuQDlwohDHsAfT9VdrKoSl_R33L72a3HCin5zo,51591
3
- tksheet/column_headers.py,sha256=tCIjq9sv5MfOfhC1hXzWU20RO1icdox1AvlYIESIQl4,103215
3
+ tksheet/column_headers.py,sha256=CIQwGNY0PSWb8q3Yl5lOBCGckZ83BDefFH1e4qKoLfs,102720
4
4
  tksheet/constants.py,sha256=aiDvUSaPtl_TSNtRRJ_p87c9iTBz9ksMd5IsSXzz4Hk,13316
5
5
  tksheet/find_window.py,sha256=TvbSqO42cw1o1AO0tQ0Q1iZogouNr4ObMo7JfkZCxgA,19877
6
6
  tksheet/formatters.py,sha256=DGcRiMsDJnySNpQcjfiX84oJ7TmOSMdU6u9injIhA4g,10095
7
- tksheet/functions.py,sha256=Lfo605jYI87KLWo6okQhfUlr-c93ZxuOR5VJKCNY6UM,51019
8
- tksheet/main_table.py,sha256=0vArmPujf0Q8NI2GYDShp8Qys4A9qQ0dlru9Wg-fYlQ,363942
9
- tksheet/other_classes.py,sha256=pe9_Cj6d3rdeMif9nGvUz0MEUChf0l4d669RNqcNhY4,16578
10
- tksheet/row_index.py,sha256=_lCilwJfc5Eem22S7WZH_85zWQGGLGMa1upHUGCj_Y0,140328
7
+ tksheet/functions.py,sha256=Ffw6yDHj83oubcp4P9VCQhTRWtGkMI2CBob4JFld91E,52567
8
+ tksheet/main_table.py,sha256=40MAVfBxQ6FycJcuqm9ZsMOjVYKWhISjht3FFZ-UQOI,363608
9
+ tksheet/other_classes.py,sha256=g6LYYHXO9RMy2mN_e-HmGa3Wuzhdxt5voO8-Ug19_Ag,16671
10
+ tksheet/row_index.py,sha256=2aiADtsPskfHZeU0JK7fD4kZm-25ooSjO3mguG9vTM4,139671
11
11
  tksheet/sheet.py,sha256=ZgryLoqfkm2vtJDIVhXAvSUQ8G7TXztiID8Ftt3V2qo,269531
12
12
  tksheet/sheet_options.py,sha256=ob-XYgGfBoi2TaFAvUUmlWUkw9xB-yXmJw17gu9__Lw,9948
13
13
  tksheet/sorting.py,sha256=zcZPpRtP1h_xJGtGkG3E43H7deKQFnh9cMwZ1B2-aGc,17502
@@ -15,8 +15,8 @@ tksheet/text_editor.py,sha256=rU8Fz0-ltkM63W9io2DoZJPyzUGzCc9Z0qBtc4D1H40,7404
15
15
  tksheet/themes.py,sha256=AoNAxibnQi04MN0Zpbn9-kyDnkiiV8TDNWP9FYjpuf0,18473
16
16
  tksheet/tksheet_types.py,sha256=1MjXR34EmvP1KfHlLTvKKVnf0VMz_LU_WOM2q4o5hfI,4598
17
17
  tksheet/top_left_rectangle.py,sha256=M52IrPIeMoYE3jSpooZmqw_0W5Fz_R-Yu1ZqA685EZ8,8557
18
- tksheet-7.4.11.dist-info/LICENSE.txt,sha256=ndbcCPe9SlHfweE_W2RAueWUe2k7yudyxYLq6WjFdn4,1101
19
- tksheet-7.4.11.dist-info/METADATA,sha256=-oNnevhplE5S5kakZod7QpcSOb4RQUf8ZTrSTVXNoKs,8006
20
- tksheet-7.4.11.dist-info/WHEEL,sha256=jB7zZ3N9hIM9adW7qlTAyycLYW9npaWKLRzaoVcLKcM,91
21
- tksheet-7.4.11.dist-info/top_level.txt,sha256=my61PXCcck_HHAc9cq3NAlyAr3A3FXxCy9gptEOaCN8,8
22
- tksheet-7.4.11.dist-info/RECORD,,
18
+ tksheet-7.4.12.dist-info/LICENSE.txt,sha256=ndbcCPe9SlHfweE_W2RAueWUe2k7yudyxYLq6WjFdn4,1101
19
+ tksheet-7.4.12.dist-info/METADATA,sha256=0WsLK9P5f8h788tKDhCSQjtYad1UD9mDmIOuFz7eNjE,7999
20
+ tksheet-7.4.12.dist-info/WHEEL,sha256=52BFRY2Up02UkjOa29eZOS2VxUrpPORXg1pkohGGUS8,91
21
+ tksheet-7.4.12.dist-info/top_level.txt,sha256=my61PXCcck_HHAc9cq3NAlyAr3A3FXxCy9gptEOaCN8,8
22
+ tksheet-7.4.12.dist-info/RECORD,,
@@ -1,5 +1,5 @@
1
1
  Wheel-Version: 1.0
2
- Generator: setuptools (75.8.2)
2
+ Generator: setuptools (76.0.0)
3
3
  Root-Is-Purelib: true
4
4
  Tag: py3-none-any
5
5