tksheet 7.1.5__py3-none-any.whl → 7.1.6__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.1.5"
7
+ __version__ = "7.1.6"
8
8
 
9
9
  from .colors import (
10
10
  color_map,
tksheet/column_headers.py CHANGED
@@ -13,13 +13,14 @@ from itertools import (
13
13
  islice,
14
14
  )
15
15
  from math import ceil, floor
16
+ from typing import Literal
16
17
 
17
18
  from .colors import (
18
19
  color_map,
19
20
  )
20
21
  from .formatters import is_bool_like, try_to_bool
21
22
  from .functions import (
22
- consecutive_chunks,
23
+ consecutive_ranges,
23
24
  ev_stack_dict,
24
25
  event_dict,
25
26
  get_checkbox_points,
@@ -687,10 +688,10 @@ class ColumnHeaders(tk.Canvas):
687
688
  tag="move_columns",
688
689
  )
689
690
  self.MT.create_resize_line(xpos, y1, xpos, y2, width=3, fill=self.PAR.ops.drag_and_drop_bg, tag="move_columns")
690
- for chunk in consecutive_chunks(cols):
691
+ for boxst, boxend in consecutive_ranges(cols):
691
692
  self.MT.show_ctrl_outline(
692
- start_cell=(chunk[0], 0),
693
- end_cell=(chunk[-1] + 1, len(self.MT.row_positions) - 1),
693
+ start_cell=(boxst, 0),
694
+ end_cell=(boxend, len(self.MT.row_positions) - 1),
694
695
  dash=(),
695
696
  outline=self.PAR.ops.drag_and_drop_bg,
696
697
  delete_on_timer=False,
@@ -1622,14 +1623,13 @@ class ColumnHeaders(tk.Canvas):
1622
1623
  ) -> bool:
1623
1624
  text = None
1624
1625
  extra_func_key = "??"
1625
- datacn = c if self.MT.all_columns_displayed else self.MT.displayed_columns[c]
1626
1626
  if event is None or self.MT.event_opens_dropdown_or_checkbox(event):
1627
1627
  if event is not None:
1628
1628
  if hasattr(event, "keysym") and event.keysym == "Return":
1629
1629
  extra_func_key = "Return"
1630
1630
  elif hasattr(event, "keysym") and event.keysym == "F2":
1631
1631
  extra_func_key = "F2"
1632
- text = self.get_cell_data(datacn, none_to_empty_str=True, redirect_int=True)
1632
+ text = self.get_cell_data(self.MT.datacn(c), none_to_empty_str=True, redirect_int=True)
1633
1633
  elif event is not None and (
1634
1634
  (hasattr(event, "keysym") and event.keysym == "BackSpace") or event.keycode in (8, 855638143)
1635
1635
  ):
@@ -1679,9 +1679,8 @@ class ColumnHeaders(tk.Canvas):
1679
1679
  y = 0
1680
1680
  w = self.MT.col_positions[c + 1] - x
1681
1681
  h = self.current_height + 1
1682
- datacn = c if self.MT.all_columns_displayed else self.MT.displayed_columns[c]
1683
1682
  if text is None:
1684
- text = self.get_cell_data(datacn, none_to_empty_str=True, redirect_int=True)
1683
+ text = self.get_cell_data(self.MT.datacn(c), none_to_empty_str=True, redirect_int=True)
1685
1684
  bg, fg = self.PAR.ops.header_bg, self.PAR.ops.header_fg
1686
1685
  kwargs = {
1687
1686
  "menu_kwargs": DotDict(
@@ -1754,7 +1753,7 @@ class ColumnHeaders(tk.Canvas):
1754
1753
  not check_lines
1755
1754
  or self.MT.get_lines_cell_height(
1756
1755
  self.text_editor.window.get_num_lines() + 1,
1757
- font=self.PAR.ops.header_font,
1756
+ font=self.text_editor.tktext.cget("font"),
1758
1757
  )
1759
1758
  > curr_height
1760
1759
  ):
@@ -1774,36 +1773,45 @@ class ColumnHeaders(tk.Canvas):
1774
1773
  )
1775
1774
  self.itemconfig(self.dropdown.canvas_id, anchor=anchor, height=win_h)
1776
1775
 
1777
- def refresh_open_window_positions(self):
1776
+ def refresh_open_window_positions(self, zoom: Literal["in", "out"]):
1778
1777
  if self.text_editor.open:
1779
1778
  c = self.text_editor.column
1780
- self.text_editor.window.config(height=self.MT.col_positions[c + 1] - self.MT.col_positions[c])
1779
+ self.text_editor.window.config(
1780
+ height=self.current_height,
1781
+ width=self.MT.col_positions[c + 1] - self.MT.col_positions[c] + 1,
1782
+ )
1783
+ self.text_editor.tktext.config(font=self.PAR.ops.header_font)
1781
1784
  self.coords(
1782
1785
  self.text_editor.canvas_id,
1783
- 0,
1784
1786
  self.MT.col_positions[c],
1787
+ 0,
1785
1788
  )
1786
1789
  if self.dropdown.open:
1790
+ if zoom == "in":
1791
+ self.dropdown.window.zoom_in()
1792
+ elif zoom == "out":
1793
+ self.dropdown.window.zoom_out()
1787
1794
  c = self.dropdown.get_coords()
1788
1795
  if self.text_editor.open:
1789
1796
  text_editor_h = self.text_editor.window.winfo_height()
1790
1797
  win_h, anchor = self.get_dropdown_height_anchor(c, text_editor_h)
1791
1798
  else:
1792
- text_editor_h = self.MT.col_positions[c + 1] - self.MT.col_positions[c]
1799
+ text_editor_h = self.current_height
1793
1800
  anchor = self.itemcget(self.dropdown.canvas_id, "anchor")
1794
1801
  # win_h = 0
1802
+ self.dropdown.window.config(width=self.MT.col_positions[c + 1] - self.MT.col_positions[c] + 1)
1795
1803
  if anchor == "nw":
1796
1804
  self.coords(
1797
1805
  self.dropdown.canvas_id,
1798
- 0,
1799
- self.MT.col_positions[c] + text_editor_h - 1,
1806
+ self.MT.col_positions[c],
1807
+ text_editor_h - 1,
1800
1808
  )
1801
1809
  # self.itemconfig(self.dropdown.canvas_id, anchor=anchor, height=win_h)
1802
1810
  elif anchor == "sw":
1803
1811
  self.coords(
1804
1812
  self.dropdown.canvas_id,
1805
- 0,
1806
1813
  self.MT.col_positions[c],
1814
+ 0,
1807
1815
  )
1808
1816
  # self.itemconfig(self.dropdown.canvas_id, anchor=anchor, height=win_h)
1809
1817
 
@@ -1901,11 +1909,9 @@ class ColumnHeaders(tk.Canvas):
1901
1909
  modified_func(event)
1902
1910
  dd_window.search_and_see(event)
1903
1911
 
1904
- def open_dropdown_window(self, c, datacn=None, event: object = None):
1912
+ def open_dropdown_window(self, c, event: object = None):
1905
1913
  self.hide_text_editor("Escape")
1906
- if datacn is None:
1907
- datacn = c if self.MT.all_columns_displayed else self.MT.displayed_columns[c]
1908
- kwargs = self.get_cell_kwargs(datacn, key="dropdown")
1914
+ kwargs = self.get_cell_kwargs(self.MT.datacn(c), key="dropdown")
1909
1915
  if kwargs["state"] == "normal":
1910
1916
  if not self.open_text_editor(event=event, c=c, dropdown=True):
1911
1917
  return
tksheet/functions.py CHANGED
@@ -245,6 +245,12 @@ def is_iterable(o: object) -> bool:
245
245
  return False
246
246
 
247
247
 
248
+ def int_x_iter(i: Iterator[int] | int) -> Iterator[int]:
249
+ if isinstance(i, int):
250
+ return (i,)
251
+ return i
252
+
253
+
248
254
  def unpack(t: tuple[object] | tuple[Iterator[object]]) -> tuple[object]:
249
255
  if not len(t):
250
256
  return t
@@ -345,21 +351,27 @@ def get_seq_without_gaps_at_index(
345
351
  return seq
346
352
 
347
353
 
348
- def consecutive_chunks(seq: list[object]) -> Generator[object]:
349
- if not seq:
350
- yield seq
354
+ def consecutive_chunks(seq: list[int]) -> Generator[list[int]]:
351
355
  start = 0
352
- end = 0
353
- for index, value in enumerate(seq):
354
- if index < len(seq) - 1:
355
- if seq[index + 1] > value + 1:
356
- end = index + 1
357
- yield seq[start:end]
358
- start = end
359
- else:
356
+ for index, value in enumerate(seq, 1):
357
+ try:
358
+ if seq[index] > value + 1:
359
+ yield seq[start:(start := index)]
360
+ except Exception:
360
361
  yield seq[start : len(seq)]
361
362
 
362
363
 
364
+ def consecutive_ranges(seq: Sequence[int]) -> Generator[tuple[int, int]]:
365
+ start = 0
366
+ for index, value in enumerate(seq, 1):
367
+ try:
368
+ if seq[index] > value + 1:
369
+ yield seq[start], seq[index - 1] + 1
370
+ start = index
371
+ except Exception:
372
+ yield seq[start], seq[-1] + 1
373
+
374
+
363
375
  def is_contiguous(seq: list[int]) -> bool:
364
376
  itr = iter(seq)
365
377
  prev = next(itr)
tksheet/main_table.py CHANGED
@@ -49,7 +49,7 @@ from .formatters import (
49
49
  try_to_bool,
50
50
  )
51
51
  from .functions import (
52
- consecutive_chunks,
52
+ consecutive_ranges,
53
53
  decompress_load,
54
54
  diff_gen,
55
55
  diff_list,
@@ -61,6 +61,7 @@ from .functions import (
61
61
  get_seq_without_gaps_at_index,
62
62
  index_exists,
63
63
  insert_items,
64
+ int_x_iter,
64
65
  is_iterable,
65
66
  is_type_int,
66
67
  len_to_idx,
@@ -960,12 +961,12 @@ class MainTable(tk.Canvas):
960
961
  )
961
962
  )
962
963
  if create_selections:
963
- for chunk in consecutive_chunks(sorted(disp_new_idxs.values())):
964
+ for boxst, boxend in consecutive_ranges(sorted(disp_new_idxs.values())):
964
965
  self.create_selection_box(
965
966
  0,
966
- chunk[0],
967
+ boxst,
967
968
  len(self.row_positions) - 1,
968
- chunk[-1] + 1,
969
+ boxend,
969
970
  "columns",
970
971
  run_binding=True,
971
972
  )
@@ -1181,11 +1182,11 @@ class MainTable(tk.Canvas):
1181
1182
  )
1182
1183
  )
1183
1184
  if create_selections:
1184
- for chunk in consecutive_chunks(sorted(disp_new_idxs.values())):
1185
+ for boxst, boxend in consecutive_ranges(sorted(disp_new_idxs.values())):
1185
1186
  self.create_selection_box(
1186
- chunk[0],
1187
+ boxst,
1187
1188
  0,
1188
- chunk[-1] + 1,
1189
+ boxend,
1189
1190
  len(self.col_positions) - 1,
1190
1191
  "rows",
1191
1192
  run_binding=True,
@@ -1846,7 +1847,6 @@ class MainTable(tk.Canvas):
1846
1847
  "rows",
1847
1848
  set_current=resel and to_sel >= r + 1 and to_sel < r2,
1848
1849
  )
1849
- break
1850
1850
  elif isinstance(c, int) and r is None and cell is None:
1851
1851
  for item, box in self.get_selection_items(rows=False, cells=False):
1852
1852
  r1, c1, r2, c2 = box.coords
@@ -1890,7 +1890,6 @@ class MainTable(tk.Canvas):
1890
1890
  "columns",
1891
1891
  set_current=resel and to_sel >= c + 1 and to_sel < c2,
1892
1892
  )
1893
- break
1894
1893
  elif (isinstance(r, int) and isinstance(c, int) and cell is None) or cell is not None:
1895
1894
  if cell is not None:
1896
1895
  r, c = cell[0], cell[1]
@@ -1898,7 +1897,6 @@ class MainTable(tk.Canvas):
1898
1897
  r1, c1, r2, c2 = box.coords
1899
1898
  if r >= r1 and c >= c1 and r < r2 and c < c2:
1900
1899
  self.hide_selection_box(item)
1901
- break
1902
1900
  if redraw:
1903
1901
  self.main_table_redraw_grid_and_text(redraw_header=True, redraw_row_index=True)
1904
1902
  sel_event = self.get_select_event(being_drawn_item=self.being_drawn_item)
@@ -1906,7 +1904,51 @@ class MainTable(tk.Canvas):
1906
1904
  try_binding(self.deselection_binding_func, sel_event)
1907
1905
  self.PAR.emit_event("<<SheetSelect>>", data=sel_event)
1908
1906
 
1909
- def page_UP(self, event=None):
1907
+ def deselect_any(
1908
+ self,
1909
+ rows: Iterator[int] | int | None = None,
1910
+ columns: Iterator[int] | int | None = None,
1911
+ redraw: bool = True,
1912
+ ) -> None:
1913
+ rows = int_x_iter(rows)
1914
+ columns = int_x_iter(columns)
1915
+ if is_iterable(rows) and is_iterable(columns):
1916
+ rows = tuple(consecutive_ranges(sorted(rows)))
1917
+ columns = tuple(consecutive_ranges(sorted(columns)))
1918
+ for item, box in self.get_selection_items(reverse=True):
1919
+ r1, c1, r2, c2 = box.coords
1920
+ hidden = False
1921
+ for rows_st, rows_end in rows:
1922
+ if hidden:
1923
+ break
1924
+ for cols_st, cols_end in columns:
1925
+ if ((rows_end >= r1 and rows_end <= r2) or (rows_st >= r1 and rows_st < r2)) and (
1926
+ (cols_end >= c1 and cols_end <= c2) or (cols_st >= c1 and cols_st < c2)
1927
+ ):
1928
+ hidden = self.hide_selection_box(item)
1929
+ break
1930
+ elif is_iterable(rows):
1931
+ rows = tuple(consecutive_ranges(sorted(rows)))
1932
+ for item, box in self.get_selection_items(reverse=True):
1933
+ r1, c1, r2, c2 = box.coords
1934
+ for rows_st, rows_end in rows:
1935
+ if (rows_end >= r1 and rows_end <= r2) or (rows_st >= r1 and rows_st < r2):
1936
+ self.hide_selection_box(item)
1937
+ break
1938
+ elif is_iterable(columns):
1939
+ columns = tuple(consecutive_ranges(sorted(columns)))
1940
+ for item, box in self.get_selection_items(reverse=True):
1941
+ r1, c1, r2, c2 = box.coords
1942
+ for cols_st, cols_end in columns:
1943
+ if (cols_end >= c1 and cols_end <= c2) or (cols_st >= c1 and cols_st < c2):
1944
+ self.hide_selection_box(item)
1945
+ break
1946
+ else:
1947
+ self.deselect()
1948
+ if redraw:
1949
+ self.refresh()
1950
+
1951
+ def page_UP(self, event: object = None) -> None:
1910
1952
  height = self.winfo_height()
1911
1953
  top = self.canvasy(0)
1912
1954
  scrollto_y = top - height
@@ -1935,7 +1977,7 @@ class MainTable(tk.Canvas):
1935
1977
  self.RI.yview(*args)
1936
1978
  self.main_table_redraw_grid_and_text(redraw_row_index=True)
1937
1979
 
1938
- def page_DOWN(self, event=None):
1980
+ def page_DOWN(self, event: object = None) -> None:
1939
1981
  height = self.winfo_height()
1940
1982
  top = self.canvasy(0)
1941
1983
  scrollto = top + height
@@ -1965,7 +2007,7 @@ class MainTable(tk.Canvas):
1965
2007
  self.RI.yview(*args)
1966
2008
  self.main_table_redraw_grid_and_text(redraw_row_index=True)
1967
2009
 
1968
- def arrowkey_UP(self, event=None):
2010
+ def arrowkey_UP(self, event: object = None) -> None:
1969
2011
  if not self.selected:
1970
2012
  return
1971
2013
  if self.selected.type_ == "rows":
@@ -1989,7 +2031,7 @@ class MainTable(tk.Canvas):
1989
2031
  self.select_cell(r - 1, c)
1990
2032
  self.see(r - 1, c, keep_xscroll=True, check_cell_visibility=False)
1991
2033
 
1992
- def arrowkey_DOWN(self, event=None):
2034
+ def arrowkey_DOWN(self, event: object = None) -> None:
1993
2035
  if not self.selected:
1994
2036
  return
1995
2037
  if self.selected.type_ == "rows":
@@ -2068,7 +2110,7 @@ class MainTable(tk.Canvas):
2068
2110
  check_cell_visibility=False,
2069
2111
  )
2070
2112
 
2071
- def arrowkey_LEFT(self, event=None):
2113
+ def arrowkey_LEFT(self, event: object = None) -> None:
2072
2114
  if not self.selected:
2073
2115
  return
2074
2116
  if self.selected.type_ == "columns":
@@ -2100,7 +2142,7 @@ class MainTable(tk.Canvas):
2100
2142
  self.select_cell(r, c - 1)
2101
2143
  self.see(r, c - 1, keep_yscroll=True, check_cell_visibility=False)
2102
2144
 
2103
- def arrowkey_RIGHT(self, event=None):
2145
+ def arrowkey_RIGHT(self, event: object = None) -> None:
2104
2146
  if not self.selected:
2105
2147
  return
2106
2148
  if self.selected.type_ == "rows":
@@ -3222,8 +3264,6 @@ class MainTable(tk.Canvas):
3222
3264
 
3223
3265
  def ctrl_mousewheel(self, event):
3224
3266
  if event.delta < 0 or event.num == 5:
3225
- if self.PAR.ops.table_font[1] < 2 or self.PAR.ops.index_font[1] < 2 or self.PAR.ops.header_font[1] < 2:
3226
- return
3227
3267
  self.zoom_out()
3228
3268
  elif event.delta >= 0 or event.num == 4:
3229
3269
  self.zoom_in()
@@ -3231,16 +3271,22 @@ class MainTable(tk.Canvas):
3231
3271
  def zoom_in(self, event=None):
3232
3272
  self.zoom_font(
3233
3273
  (self.PAR.ops.table_font[0], self.PAR.ops.table_font[1] + 1, self.PAR.ops.table_font[2]),
3274
+ (self.PAR.ops.index_font[0], self.PAR.ops.index_font[1] + 1, self.PAR.ops.index_font[2]),
3234
3275
  (self.PAR.ops.header_font[0], self.PAR.ops.header_font[1] + 1, self.PAR.ops.header_font[2]),
3276
+ "in",
3235
3277
  )
3236
3278
 
3237
3279
  def zoom_out(self, event=None):
3280
+ if self.PAR.ops.table_font[1] < 2 or self.PAR.ops.index_font[1] < 2 or self.PAR.ops.header_font[1] < 2:
3281
+ return
3238
3282
  self.zoom_font(
3239
3283
  (self.PAR.ops.table_font[0], self.PAR.ops.table_font[1] - 1, self.PAR.ops.table_font[2]),
3284
+ (self.PAR.ops.index_font[0], self.PAR.ops.index_font[1] - 1, self.PAR.ops.index_font[2]),
3240
3285
  (self.PAR.ops.header_font[0], self.PAR.ops.header_font[1] - 1, self.PAR.ops.header_font[2]),
3286
+ "out",
3241
3287
  )
3242
3288
 
3243
- def zoom_font(self, table_font: tuple, header_font: tuple):
3289
+ def zoom_font(self, table_font: tuple, index_font: tuple, header_font: tuple, zoom: Literal["in", "out"]) -> None:
3244
3290
  self.saved_column_widths = {}
3245
3291
  self.saved_row_heights = {}
3246
3292
  # should record position prior to change and then see after change
@@ -3262,7 +3308,7 @@ class MainTable(tk.Canvas):
3262
3308
  table_font,
3263
3309
  reset_row_positions=False,
3264
3310
  )
3265
- self.set_index_font(table_font)
3311
+ self.set_index_font(index_font)
3266
3312
  self.set_header_font(header_font)
3267
3313
  if self.PAR.ops.set_cell_sizes_on_zoom:
3268
3314
  self.set_all_cell_sizes_to_text()
@@ -3290,18 +3336,18 @@ class MainTable(tk.Canvas):
3290
3336
  )
3291
3337
  self.main_table_redraw_grid_and_text(redraw_header=True, redraw_row_index=True)
3292
3338
  self.recreate_all_selection_boxes()
3293
- self.refresh_open_window_positions()
3294
- self.RI.refresh_open_window_positions()
3295
- self.CH.refresh_open_window_positions()
3339
+ self.main_table_redraw_grid_and_text(redraw_header=True, redraw_row_index=True)
3340
+ self.refresh_open_window_positions(zoom=zoom)
3341
+ self.RI.refresh_open_window_positions(zoom=zoom)
3342
+ self.CH.refresh_open_window_positions(zoom=zoom)
3296
3343
  self.see(
3297
3344
  r,
3298
3345
  c,
3299
3346
  check_cell_visibility=False,
3300
- redraw=False,
3347
+ redraw=True,
3301
3348
  r_pc=r_pc,
3302
3349
  c_pc=c_pc,
3303
3350
  )
3304
- self.main_table_redraw_grid_and_text(redraw_header=True, redraw_row_index=True)
3305
3351
 
3306
3352
  def get_txt_w(self, txt, font=None):
3307
3353
  self.txt_measure_canvas.itemconfig(
@@ -4207,12 +4253,12 @@ class MainTable(tk.Canvas):
4207
4253
  )
4208
4254
  if create_selections:
4209
4255
  self.deselect("all")
4210
- for chunk in consecutive_chunks(tuple(reversed(column_widths))):
4256
+ for boxst, boxend in consecutive_ranges(tuple(reversed(column_widths))):
4211
4257
  self.create_selection_box(
4212
4258
  0,
4213
- chunk[0],
4259
+ boxst,
4214
4260
  len(self.row_positions) - 1,
4215
- chunk[-1] + 1,
4261
+ boxend,
4216
4262
  "columns",
4217
4263
  run_binding=True,
4218
4264
  )
@@ -4336,11 +4382,11 @@ class MainTable(tk.Canvas):
4336
4382
  )
4337
4383
  if create_selections:
4338
4384
  self.deselect("all")
4339
- for chunk in consecutive_chunks(tuple(reversed(row_heights))):
4385
+ for boxst, boxend in consecutive_ranges(tuple(reversed(row_heights))):
4340
4386
  self.create_selection_box(
4341
- chunk[0],
4387
+ boxst,
4342
4388
  0,
4343
- chunk[-1] + 1,
4389
+ boxend,
4344
4390
  len(self.col_positions) - 1,
4345
4391
  "rows",
4346
4392
  run_binding=True,
@@ -5620,7 +5666,7 @@ class MainTable(tk.Canvas):
5620
5666
  if r2 < len(self.row_positions) and c2 < len(self.col_positions):
5621
5667
  self.create_selection_box(r1, c1, r2, c2, v, run_binding=True)
5622
5668
  if selected:
5623
- self.set_currently_selected(selected.row, selected.column, box=selected.coords)
5669
+ self.set_currently_selected(selected.row, selected.column, box=selected.box)
5624
5670
 
5625
5671
  def set_currently_selected(
5626
5672
  self,
@@ -5776,7 +5822,7 @@ class MainTable(tk.Canvas):
5776
5822
  self.hidd_boxes.add(item)
5777
5823
  self.itemconfig(item, state="hidden")
5778
5824
 
5779
- def hide_selection_box(self, item: int | None, set_current: bool = True) -> None:
5825
+ def hide_selection_box(self, item: int | None, set_current: bool = True) -> bool:
5780
5826
  if item is None:
5781
5827
  return
5782
5828
  box = self.selection_boxes.pop(item)
@@ -5787,6 +5833,7 @@ class MainTable(tk.Canvas):
5787
5833
  if self.selected.fill_iid == item:
5788
5834
  self.hide_selected()
5789
5835
  self.set_current_to_last()
5836
+ return True
5790
5837
 
5791
5838
  def hide_selected(self) -> None:
5792
5839
  if self.selected:
@@ -6372,13 +6419,11 @@ class MainTable(tk.Canvas):
6372
6419
  extra_func_key = "Return"
6373
6420
  elif hasattr(event, "keysym") and event.keysym == "F2":
6374
6421
  extra_func_key = "F2"
6375
- datarn = r if self.all_rows_displayed else self.displayed_rows[r]
6376
- datacn = c if self.all_columns_displayed else self.displayed_columns[c]
6377
6422
  if event is not None and (hasattr(event, "keysym") and event.keysym == "BackSpace"):
6378
6423
  extra_func_key = "BackSpace"
6379
6424
  text = ""
6380
6425
  else:
6381
- text = f"{self.get_cell_data(datarn, datacn, none_to_empty_str = True)}"
6426
+ text = f"{self.get_cell_data(self.datarn(r), self.datacn(c), none_to_empty_str = True)}"
6382
6427
  elif event is not None and (
6383
6428
  (hasattr(event, "char") and event.char.isalpha())
6384
6429
  or (hasattr(event, "char") and event.char.isdigit())
@@ -6422,9 +6467,7 @@ class MainTable(tk.Canvas):
6422
6467
  w = self.col_positions[c + 1] - x + 1
6423
6468
  h = self.row_positions[r + 1] - y + 1
6424
6469
  if text is None:
6425
- text = f"""{self.get_cell_data(r if self.all_rows_displayed else self.displayed_rows[r],
6426
- c if self.all_columns_displayed else self.displayed_columns[c],
6427
- none_to_empty_str = True)}"""
6470
+ text = f"{self.get_cell_data(self.datarn(r), self.datacn(c), none_to_empty_str = True)}"
6428
6471
  bg, fg = self.PAR.ops.table_bg, self.PAR.ops.table_fg
6429
6472
  kwargs = {
6430
6473
  "menu_kwargs": DotDict(
@@ -6483,7 +6526,14 @@ class MainTable(tk.Canvas):
6483
6526
  curr_height = self.text_editor.window.winfo_height()
6484
6527
  if curr_height < self.min_row_height:
6485
6528
  return
6486
- if not check_lines or self.get_lines_cell_height(self.text_editor.window.get_num_lines() + 1) > curr_height:
6529
+ if (
6530
+ not check_lines
6531
+ or self.get_lines_cell_height(
6532
+ self.text_editor.window.get_num_lines() + 1,
6533
+ font=self.text_editor.tktext.cget("font"),
6534
+ )
6535
+ > curr_height
6536
+ ):
6487
6537
  new_height = curr_height + self.table_xtra_lines_increment
6488
6538
  space_bot = self.get_space_bot(r)
6489
6539
  if new_height > space_bot:
@@ -6508,24 +6558,30 @@ class MainTable(tk.Canvas):
6508
6558
  )
6509
6559
  self.itemconfig(self.dropdown.canvas_id, anchor=anchor, height=win_h)
6510
6560
 
6511
- def refresh_open_window_positions(self):
6561
+ def refresh_open_window_positions(self, zoom: Literal["in", "out"]):
6512
6562
  if self.text_editor.open:
6513
6563
  r, c = self.text_editor.coords
6514
6564
  self.text_editor.window.config(height=self.row_positions[r + 1] - self.row_positions[r])
6565
+ self.text_editor.tktext.config(font=self.PAR.ops.table_font)
6515
6566
  self.coords(
6516
6567
  self.text_editor.canvas_id,
6517
6568
  self.col_positions[c],
6518
6569
  self.row_positions[r],
6519
6570
  )
6520
6571
  if self.dropdown.open:
6572
+ if zoom == "in":
6573
+ self.dropdown.window.zoom_in()
6574
+ elif zoom == "out":
6575
+ self.dropdown.window.zoom_out()
6521
6576
  r, c = self.dropdown.get_coords()
6522
6577
  if self.text_editor.open:
6523
6578
  text_editor_h = self.text_editor.window.winfo_height()
6524
6579
  win_h, anchor = self.get_dropdown_height_anchor(r, c, text_editor_h)
6525
6580
  else:
6526
- text_editor_h = self.row_positions[r + 1] - self.row_positions[r]
6581
+ text_editor_h = self.row_positions[r + 1] - self.row_positions[r] + 1
6527
6582
  anchor = self.itemcget(self.dropdown.canvas_id, "anchor")
6528
6583
  # win_h = 0
6584
+ self.dropdown.window.config(width=self.col_positions[c + 1] - self.col_positions[c] + 1)
6529
6585
  if anchor == "nw":
6530
6586
  self.coords(
6531
6587
  self.dropdown.canvas_id,
@@ -6548,7 +6604,6 @@ class MainTable(tk.Canvas):
6548
6604
  if reason == "Escape":
6549
6605
  self.focus_set()
6550
6606
 
6551
- # c is displayed col
6552
6607
  def close_text_editor(
6553
6608
  self,
6554
6609
  editor_info: tuple | None = None,
@@ -6671,8 +6726,7 @@ class MainTable(tk.Canvas):
6671
6726
  def tab_key(self, event: object = None) -> str:
6672
6727
  if not self.selected:
6673
6728
  return
6674
- r = self.selected.row
6675
- c = self.selected.column
6729
+ r, c = self.selected.row, self.selected.column
6676
6730
  r1, c1, r2, c2 = self.selection_boxes[self.selected.fill_iid].coords
6677
6731
  numcols = c2 - c1
6678
6732
  numrows = r2 - r1
@@ -6803,7 +6857,7 @@ class MainTable(tk.Canvas):
6803
6857
  }
6804
6858
  if self.dropdown.window:
6805
6859
  self.dropdown.window.reset(**reset_kwargs)
6806
- self.itemconfig(self.dropdown.canvas_id, state="normal")
6860
+ self.itemconfig(self.dropdown.canvas_id, state="normal", anchor=anchor)
6807
6861
  self.coords(self.dropdown.canvas_id, self.col_positions[c], ypos)
6808
6862
  else:
6809
6863
  self.dropdown.window = self.PAR.dropdown_class(
@@ -7100,7 +7154,12 @@ class MainTable(tk.Canvas):
7100
7154
  self.delete_row_format("all", clear_values=clear_values)
7101
7155
  self.delete_column_format("all", clear_values=clear_values)
7102
7156
 
7103
- def delete_cell_format(self, datarn: str | int = "all", datacn: int = 0, clear_values: bool = False) -> None:
7157
+ def delete_cell_format(
7158
+ self,
7159
+ datarn: Literal["all"] | int = "all",
7160
+ datacn: int = 0,
7161
+ clear_values: bool = False,
7162
+ ) -> None:
7104
7163
  if isinstance(datarn, str) and datarn.lower() == "all":
7105
7164
  itr = gen_formatted(self.cell_options)
7106
7165
  else:
@@ -7114,7 +7173,7 @@ class MainTable(tk.Canvas):
7114
7173
  if clear_values:
7115
7174
  self.set_cell_data(*key, get_val(*key), expand_sheet=False)
7116
7175
 
7117
- def delete_row_format(self, datarn: str | int = "all", clear_values: bool = False) -> None:
7176
+ def delete_row_format(self, datarn: Literal["all"] | int = "all", clear_values: bool = False) -> None:
7118
7177
  if isinstance(datarn, str) and datarn.lower() == "all":
7119
7178
  itr = gen_formatted(self.row_options)
7120
7179
  else:
@@ -7129,7 +7188,7 @@ class MainTable(tk.Canvas):
7129
7188
  for datacn in range(len(self.data[datarn])):
7130
7189
  self.set_cell_data(datarn, datacn, get_val(datarn, datacn), expand_sheet=False)
7131
7190
 
7132
- def delete_column_format(self, datacn: str | int = "all", clear_values: bool = False) -> None:
7191
+ def delete_column_format(self, datacn: Literal["all"] | int = "all", clear_values: bool = False) -> None:
7133
7192
  if isinstance(datacn, str) and datacn.lower() == "all":
7134
7193
  itr = gen_formatted(self.col_options)
7135
7194
  else:
tksheet/row_index.py CHANGED
@@ -18,6 +18,7 @@ from math import (
18
18
  ceil,
19
19
  floor,
20
20
  )
21
+ from typing import Literal
21
22
 
22
23
  from .colors import (
23
24
  color_map,
@@ -866,6 +867,8 @@ class RowIndex(tk.Canvas):
866
867
  ):
867
868
  self.open_cell(event)
868
869
  elif (iid := self.event_over_tree_arrow(r, canvasy, event.x)) is not None:
870
+ if self.MT.selection_boxes:
871
+ self.select_row(r, redraw=False)
869
872
  self.PAR.item(iid, open_=iid not in self.tree_open_ids)
870
873
  else:
871
874
  self.mouseclick_outside_editor_or_dropdown_all_canvases(inside=True)
@@ -1014,11 +1017,10 @@ class RowIndex(tk.Canvas):
1014
1017
  x1, y1, x2, y2 = self.MT.get_canvas_visible_area()
1015
1018
  start_col, end_col = self.MT.get_visible_columns(x1, x2)
1016
1019
  else:
1017
- start_col, end_col = (
1018
- 0,
1019
- len(self.MT.data[row]) if self.MT.data else 0,
1020
- )
1021
- iterable = range(start_col, end_col)
1020
+ if not self.MT.data or datarn >= len(self.MT.data):
1021
+ iterable = range(0, 0)
1022
+ else:
1023
+ iterable = range(0, len(self.MT.data[datarn]))
1022
1024
  else:
1023
1025
  if displayed_only:
1024
1026
  x1, y1, x2, y2 = self.MT.get_canvas_visible_area()
@@ -1712,8 +1714,7 @@ class RowIndex(tk.Canvas):
1712
1714
  extra_func_key = "Return"
1713
1715
  elif hasattr(event, "keysym") and event.keysym == "F2":
1714
1716
  extra_func_key = "F2"
1715
- datarn = r if self.MT.all_rows_displayed else self.MT.displayed_rows[r]
1716
- text = self.get_cell_data(datarn, none_to_empty_str=True, redirect_int=True)
1717
+ text = self.get_cell_data(self.MT.datarn(r), none_to_empty_str=True, redirect_int=True)
1717
1718
  elif event is not None and (
1718
1719
  (hasattr(event, "keysym") and event.keysym == "BackSpace") or event.keycode in (8, 855638143)
1719
1720
  ):
@@ -1761,9 +1762,8 @@ class RowIndex(tk.Canvas):
1761
1762
  y = self.MT.row_positions[r]
1762
1763
  w = self.current_width + 1
1763
1764
  h = self.MT.row_positions[r + 1] - y + 1
1764
- datarn = r if self.MT.all_rows_displayed else self.MT.displayed_rows[r]
1765
1765
  if text is None:
1766
- text = self.get_cell_data(datarn, none_to_empty_str=True, redirect_int=True)
1766
+ text = self.get_cell_data(self.MT.datarn(r), none_to_empty_str=True, redirect_int=True)
1767
1767
  bg, fg = self.PAR.ops.index_bg, self.PAR.ops.index_fg
1768
1768
  kwargs = {
1769
1769
  "menu_kwargs": DotDict(
@@ -1820,7 +1820,7 @@ class RowIndex(tk.Canvas):
1820
1820
  not check_lines
1821
1821
  or self.MT.get_lines_cell_height(
1822
1822
  self.text_editor.window.get_num_lines() + 1,
1823
- font=self.PAR.ops.index_font,
1823
+ font=self.text_editor.tktext.cget("font"),
1824
1824
  )
1825
1825
  > curr_height
1826
1826
  ):
@@ -1851,24 +1851,30 @@ class RowIndex(tk.Canvas):
1851
1851
  )
1852
1852
  self.itemconfig(self.dropdown.canvas_id, anchor=anchor, height=win_h)
1853
1853
 
1854
- def refresh_open_window_positions(self):
1854
+ def refresh_open_window_positions(self, zoom: Literal["in", "out"]):
1855
1855
  if self.text_editor.open:
1856
1856
  r = self.text_editor.row
1857
1857
  self.text_editor.window.config(height=self.MT.row_positions[r + 1] - self.MT.row_positions[r])
1858
+ self.text_editor.tktext.config(font=self.PAR.ops.index_font)
1858
1859
  self.coords(
1859
1860
  self.text_editor.canvas_id,
1860
1861
  0,
1861
1862
  self.MT.row_positions[r],
1862
1863
  )
1863
1864
  if self.dropdown.open:
1865
+ if zoom == "in":
1866
+ self.dropdown.window.zoom_in()
1867
+ elif zoom == "out":
1868
+ self.dropdown.window.zoom_out()
1864
1869
  r = self.dropdown.get_coords()
1865
1870
  if self.text_editor.open:
1866
1871
  text_editor_h = self.text_editor.window.winfo_height()
1867
1872
  win_h, anchor = self.get_dropdown_height_anchor(r, text_editor_h)
1868
1873
  else:
1869
- text_editor_h = self.MT.row_positions[r + 1] - self.MT.row_positions[r]
1874
+ text_editor_h = self.MT.row_positions[r + 1] - self.MT.row_positions[r] + 1
1870
1875
  anchor = self.itemcget(self.dropdown.canvas_id, "anchor")
1871
1876
  # win_h = 0
1877
+ self.dropdown.window.config(width=self.current_width + 1)
1872
1878
  if anchor == "nw":
1873
1879
  self.coords(
1874
1880
  self.dropdown.canvas_id,
@@ -1956,15 +1962,22 @@ class RowIndex(tk.Canvas):
1956
1962
  break
1957
1963
  if win_h > 500:
1958
1964
  win_h = 500
1959
- space_bot = self.MT.get_space_bot(0, text_editor_h)
1965
+ space_bot = self.MT.get_space_bot(r, text_editor_h)
1966
+ space_top = int(self.MT.row_positions[r])
1967
+ anchor = "nw"
1960
1968
  win_h2 = int(win_h)
1961
1969
  if win_h > space_bot:
1962
- win_h = space_bot - 1
1970
+ if space_bot >= space_top:
1971
+ anchor = "nw"
1972
+ win_h = space_bot - 1
1973
+ elif space_top > space_bot:
1974
+ anchor = "sw"
1975
+ win_h = space_top - 1
1963
1976
  if win_h < self.MT.index_txt_height + 5:
1964
1977
  win_h = self.MT.index_txt_height + 5
1965
1978
  elif win_h > win_h2:
1966
1979
  win_h = win_h2
1967
- return win_h, "nw"
1980
+ return win_h, anchor
1968
1981
 
1969
1982
  def dropdown_text_editor_modified(
1970
1983
  self,
@@ -1977,17 +1990,21 @@ class RowIndex(tk.Canvas):
1977
1990
  dd_window.search_and_see(event)
1978
1991
 
1979
1992
  # r is displayed row
1980
- def open_dropdown_window(self, r, datarn=None, event: object = None):
1993
+ def open_dropdown_window(self, r, event: object = None):
1981
1994
  self.hide_text_editor("Escape")
1982
- if datarn is None:
1983
- datarn = r if self.MT.all_rows_displayed else self.MT.displayed_rows[r]
1984
- kwargs = self.get_cell_kwargs(datarn, key="dropdown")
1995
+ kwargs = self.get_cell_kwargs(self.MT.datarn(r), key="dropdown")
1985
1996
  if kwargs["state"] == "normal":
1986
1997
  if not self.open_text_editor(event=event, r=r, dropdown=True):
1987
1998
  return
1988
1999
  win_h, anchor = self.get_dropdown_height_anchor(r)
1989
- win_w = self.current_width
1990
- ypos = self.MT.row_positions[r + 1]
2000
+ win_w = self.current_width + 1
2001
+ if anchor == "nw":
2002
+ if kwargs["state"] == "normal":
2003
+ ypos = self.MT.row_positions[r] + self.text_editor.window.winfo_height() - 1
2004
+ else:
2005
+ ypos = self.MT.row_positions[r + 1]
2006
+ else:
2007
+ ypos = self.MT.row_positions[r]
1991
2008
  reset_kwargs = {
1992
2009
  "r": r,
1993
2010
  "c": 0,
@@ -2001,7 +2018,7 @@ class RowIndex(tk.Canvas):
2001
2018
  }
2002
2019
  if self.dropdown.window:
2003
2020
  self.dropdown.window.reset(**reset_kwargs)
2004
- self.itemconfig(self.dropdown.canvas_id, state="normal")
2021
+ self.itemconfig(self.dropdown.canvas_id, state="normal", anchor=anchor)
2005
2022
  self.coords(self.dropdown.canvas_id, 0, ypos)
2006
2023
  else:
2007
2024
  self.dropdown.window = self.PAR.dropdown_class(
tksheet/sheet.py CHANGED
@@ -1092,6 +1092,14 @@ class Sheet(tk.Frame):
1092
1092
  self.TL.focus_set()
1093
1093
  return self
1094
1094
 
1095
+ def zoom_in(self) -> Sheet:
1096
+ self.MT.zoom_in()
1097
+ return self
1098
+
1099
+ def zoom_out(self) -> Sheet:
1100
+ self.MT.zoom_out()
1101
+ return self
1102
+
1095
1103
  @property
1096
1104
  def event(self) -> EventDataDict:
1097
1105
  return self.last_event_data
@@ -3174,6 +3182,16 @@ class Sheet(tk.Frame):
3174
3182
  self.set_refresh_timer(redraw)
3175
3183
  return self
3176
3184
 
3185
+ def deselect_any(
3186
+ self,
3187
+ rows: Iterator[int] | int | None,
3188
+ columns: Iterator[int] | int | None,
3189
+ redraw: bool = True,
3190
+ ) -> Sheet:
3191
+ self.MT.deselect_any(rows=rows, columns=columns, redraw=False)
3192
+ self.set_refresh_timer(redraw)
3193
+ return self
3194
+
3177
3195
  # Row Heights and Column Widths
3178
3196
 
3179
3197
  def default_column_width(self, width: int | None = None) -> int:
@@ -3777,6 +3795,8 @@ class Sheet(tk.Frame):
3777
3795
  )
3778
3796
  if deselect_all:
3779
3797
  self.MT.deselect(redraw=False)
3798
+ else:
3799
+ self.MT.deselect_any(rows=rows, redraw=False)
3780
3800
  self.set_refresh_timer(redraw)
3781
3801
  return self
3782
3802
 
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: tksheet
3
- Version: 7.1.5
3
+ Version: 7.1.6
4
4
  Summary: Tkinter table / sheet widget
5
5
  Author-email: ragardner <github@ragardner.simplelogin.com>
6
6
  License: Copyright (c) 2019 ragardner and open source contributors
@@ -0,0 +1,20 @@
1
+ tksheet/__init__.py,sha256=95JUoulFU3M59S4BSLtmbHtdYN9bUTph238FEb2u0S8,1874
2
+ tksheet/colors.py,sha256=1k06VorynLmnC4FdJg8H4reIA6rXaeXBpdMwXLhN8oc,51594
3
+ tksheet/column_headers.py,sha256=2Y5QcT5WmxjXudPszKHcd7hHuTNRfxoRVyKx2bsBGZI,99449
4
+ tksheet/formatters.py,sha256=DXif00aq9DgFpXwkbiqD86KxtDg0Meop51hLY-KcGNQ,10037
5
+ tksheet/functions.py,sha256=OZdcbYcKpiU_2YhwPWASZ8QfyF3tRhGiwY80sh5Rbx4,39610
6
+ tksheet/main_table.py,sha256=ThNsmwC_e2o5nEjB53RvIMLaj3rcWEfASeMtt2TTNl4,321201
7
+ tksheet/other_classes.py,sha256=Hjr7c0kD2_880xjtGuFn9gQ-7ED5kSiNahniBeXcf84,13604
8
+ tksheet/row_index.py,sha256=TsAYN0cBchH-diKzU3fuZXlgTOmrODq8EIeT2RcTblk,104750
9
+ tksheet/sheet.py,sha256=_VotKhIMM1aAUmDNPZC4h0_q6NP-sB4nGRRIZ-iggSc,257417
10
+ tksheet/sheet_options.py,sha256=Vcy4RxTKvf2HM-Yc53ex0lpBe6ATXc_pdx4oLhfjDgU,11906
11
+ tksheet/text_editor.py,sha256=81_IZKrTVa2KIx2cJ4n3cFvFMAwvbHIQYgqtyat-97I,6681
12
+ tksheet/themes.py,sha256=OwUe31NRbosjw3ZoZsMyB8lNVyYin9YcKLhCturi5q8,13398
13
+ tksheet/top_left_rectangle.py,sha256=-2u9GfOvcqhkKwHEtbqdFvXCY3RbvL5k2Sh9l3r_k04,8275
14
+ tksheet/types.py,sha256=IgoEHMbceKpakcZtanxKaKJ4RdCq7UW6EoEIIz5O59k,340
15
+ tksheet/vars.py,sha256=Iukk7-MMT9X7vv0m3nQPKzbp2Iw2Pg1wJEW7js919Mo,2092
16
+ tksheet-7.1.6.dist-info/LICENSE.txt,sha256=ndbcCPe9SlHfweE_W2RAueWUe2k7yudyxYLq6WjFdn4,1101
17
+ tksheet-7.1.6.dist-info/METADATA,sha256=2ZtrwFvnlwzpFt9hY_C_Mpf5ghtHjmRPz65pfc5N1xI,6013
18
+ tksheet-7.1.6.dist-info/WHEEL,sha256=GJ7t_kWBFywbagK5eo9IoUwLW6oyOeTKmQ-9iHFVNxQ,92
19
+ tksheet-7.1.6.dist-info/top_level.txt,sha256=my61PXCcck_HHAc9cq3NAlyAr3A3FXxCy9gptEOaCN8,8
20
+ tksheet-7.1.6.dist-info/RECORD,,
@@ -1,20 +0,0 @@
1
- tksheet/__init__.py,sha256=bzXUATwg31SEbu5F3bS-MFBDpi4MAuMZ0TPh49RAonU,1874
2
- tksheet/colors.py,sha256=1k06VorynLmnC4FdJg8H4reIA6rXaeXBpdMwXLhN8oc,51594
3
- tksheet/column_headers.py,sha256=9LOi8-Xr7_h0UlF277VDVg_UWQ3UGVwD9fufwq3SbMU,99272
4
- tksheet/formatters.py,sha256=DXif00aq9DgFpXwkbiqD86KxtDg0Meop51hLY-KcGNQ,10037
5
- tksheet/functions.py,sha256=PN2qanv32V4Hg221b-999fEH4yxYNoze925txUP5kA4,39245
6
- tksheet/main_table.py,sha256=QHFqCkCWkiecHBjbiGBJSJ0SoMp2htXBCpkLIMQEeWI,318511
7
- tksheet/other_classes.py,sha256=Hjr7c0kD2_880xjtGuFn9gQ-7ED5kSiNahniBeXcf84,13604
8
- tksheet/row_index.py,sha256=ZPBiKNB5NghU_Q-LEqWrC9-VqaVYj__DodenDSR_oeA,103990
9
- tksheet/sheet.py,sha256=ho4dGIco8GTCJluFZcJhOJNgnJTA_S_dMm-xU4cJPGo,256866
10
- tksheet/sheet_options.py,sha256=Vcy4RxTKvf2HM-Yc53ex0lpBe6ATXc_pdx4oLhfjDgU,11906
11
- tksheet/text_editor.py,sha256=81_IZKrTVa2KIx2cJ4n3cFvFMAwvbHIQYgqtyat-97I,6681
12
- tksheet/themes.py,sha256=OwUe31NRbosjw3ZoZsMyB8lNVyYin9YcKLhCturi5q8,13398
13
- tksheet/top_left_rectangle.py,sha256=-2u9GfOvcqhkKwHEtbqdFvXCY3RbvL5k2Sh9l3r_k04,8275
14
- tksheet/types.py,sha256=IgoEHMbceKpakcZtanxKaKJ4RdCq7UW6EoEIIz5O59k,340
15
- tksheet/vars.py,sha256=Iukk7-MMT9X7vv0m3nQPKzbp2Iw2Pg1wJEW7js919Mo,2092
16
- tksheet-7.1.5.dist-info/LICENSE.txt,sha256=ndbcCPe9SlHfweE_W2RAueWUe2k7yudyxYLq6WjFdn4,1101
17
- tksheet-7.1.5.dist-info/METADATA,sha256=WBm8p-qBsL207lJ6_tznMJE9Vo62iKaZmj-nmyj-UbE,6013
18
- tksheet-7.1.5.dist-info/WHEEL,sha256=GJ7t_kWBFywbagK5eo9IoUwLW6oyOeTKmQ-9iHFVNxQ,92
19
- tksheet-7.1.5.dist-info/top_level.txt,sha256=my61PXCcck_HHAc9cq3NAlyAr3A3FXxCy9gptEOaCN8,8
20
- tksheet-7.1.5.dist-info/RECORD,,