tksheet 7.4.10__tar.gz → 7.4.12__tar.gz

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.
Files changed (26) hide show
  1. {tksheet-7.4.10/tksheet.egg-info → tksheet-7.4.12}/PKG-INFO +3 -3
  2. {tksheet-7.4.10 → tksheet-7.4.12}/README.md +2 -2
  3. {tksheet-7.4.10 → tksheet-7.4.12}/pyproject.toml +1 -1
  4. {tksheet-7.4.10 → tksheet-7.4.12}/tksheet/__init__.py +1 -1
  5. {tksheet-7.4.10 → tksheet-7.4.12}/tksheet/column_headers.py +26 -47
  6. {tksheet-7.4.10 → tksheet-7.4.12}/tksheet/functions.py +92 -33
  7. {tksheet-7.4.10 → tksheet-7.4.12}/tksheet/main_table.py +199 -221
  8. {tksheet-7.4.10 → tksheet-7.4.12}/tksheet/other_classes.py +3 -1
  9. {tksheet-7.4.10 → tksheet-7.4.12}/tksheet/row_index.py +28 -56
  10. {tksheet-7.4.10 → tksheet-7.4.12/tksheet.egg-info}/PKG-INFO +3 -3
  11. {tksheet-7.4.10 → tksheet-7.4.12}/LICENSE.txt +0 -0
  12. {tksheet-7.4.10 → tksheet-7.4.12}/setup.cfg +0 -0
  13. {tksheet-7.4.10 → tksheet-7.4.12}/tksheet/colors.py +0 -0
  14. {tksheet-7.4.10 → tksheet-7.4.12}/tksheet/constants.py +0 -0
  15. {tksheet-7.4.10 → tksheet-7.4.12}/tksheet/find_window.py +0 -0
  16. {tksheet-7.4.10 → tksheet-7.4.12}/tksheet/formatters.py +0 -0
  17. {tksheet-7.4.10 → tksheet-7.4.12}/tksheet/sheet.py +0 -0
  18. {tksheet-7.4.10 → tksheet-7.4.12}/tksheet/sheet_options.py +0 -0
  19. {tksheet-7.4.10 → tksheet-7.4.12}/tksheet/sorting.py +0 -0
  20. {tksheet-7.4.10 → tksheet-7.4.12}/tksheet/text_editor.py +0 -0
  21. {tksheet-7.4.10 → tksheet-7.4.12}/tksheet/themes.py +0 -0
  22. {tksheet-7.4.10 → tksheet-7.4.12}/tksheet/tksheet_types.py +0 -0
  23. {tksheet-7.4.10 → tksheet-7.4.12}/tksheet/top_left_rectangle.py +0 -0
  24. {tksheet-7.4.10 → tksheet-7.4.12}/tksheet.egg-info/SOURCES.txt +0 -0
  25. {tksheet-7.4.10 → tksheet-7.4.12}/tksheet.egg-info/dependency_links.txt +0 -0
  26. {tksheet-7.4.10 → tksheet-7.4.12}/tksheet.egg-info/top_level.txt +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.2
2
2
  Name: tksheet
3
- Version: 7.4.10
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>
@@ -18,11 +18,11 @@
18
18
  <tbody>
19
19
  <tr>
20
20
  <td style="color: LightCoral">Versions 6.x.x &#8594;</td>
21
- <td><a href="https://github.com/ragardner/tksheet/wiki/Version-6">Documentation Wiki</a></td>
21
+ <td><a href="https://github.com/ragardner/tksheet/wiki/Version-6">Documentation</a></td>
22
22
  </tr>
23
23
  <tr>
24
24
  <td style="color: lightgreen">Versions 7.x.x &#8594;</td>
25
- <td><a href="https://github.com/ragardner/tksheet/wiki/Version-7">Documentation Wiki</a></td>
25
+ <td><a href="https://ragardner.github.io/tksheet/DOCUMENTATION.html">Documentation</a></td>
26
26
  </tr>
27
27
  <tr>
28
28
  <td align="right" colspan="2"><a href="https://github.com/ragardner/tksheet/blob/master/docs/CHANGELOG.md">Changelog</a></td>
@@ -6,7 +6,7 @@ build-backend = "setuptools.build_meta"
6
6
  name = "tksheet"
7
7
  description = "Tkinter table / sheet and treeview widget"
8
8
  readme = "README.md"
9
- version = "7.4.10"
9
+ version = "7.4.12"
10
10
  authors = [{ name = "ragardner", email = "github@ragardner.simplelogin.com" }]
11
11
  requires-python = ">=3.8"
12
12
  license = {file = "LICENSE.txt"}
@@ -4,7 +4,7 @@
4
4
  tksheet - A Python tkinter table widget
5
5
  """
6
6
 
7
- __version__ = "7.4.10"
7
+ __version__ = "7.4.12"
8
8
 
9
9
  from .colors import (
10
10
  color_map,
@@ -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
 
@@ -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
+ )