tksheet 7.2.4__tar.gz → 7.2.6__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 (24) hide show
  1. {tksheet-7.2.4/tksheet.egg-info → tksheet-7.2.6}/PKG-INFO +1 -1
  2. {tksheet-7.2.4 → tksheet-7.2.6}/pyproject.toml +1 -1
  3. {tksheet-7.2.4 → tksheet-7.2.6}/tksheet/__init__.py +2 -1
  4. {tksheet-7.2.4 → tksheet-7.2.6}/tksheet/column_headers.py +7 -3
  5. {tksheet-7.2.4 → tksheet-7.2.6}/tksheet/functions.py +7 -12
  6. {tksheet-7.2.4 → tksheet-7.2.6}/tksheet/main_table.py +35 -29
  7. {tksheet-7.2.4 → tksheet-7.2.6}/tksheet/row_index.py +12 -2
  8. {tksheet-7.2.4 → tksheet-7.2.6}/tksheet/sheet.py +103 -54
  9. {tksheet-7.2.4 → tksheet-7.2.6/tksheet.egg-info}/PKG-INFO +1 -1
  10. {tksheet-7.2.4 → tksheet-7.2.6}/LICENSE.txt +0 -0
  11. {tksheet-7.2.4 → tksheet-7.2.6}/README.md +0 -0
  12. {tksheet-7.2.4 → tksheet-7.2.6}/setup.cfg +0 -0
  13. {tksheet-7.2.4 → tksheet-7.2.6}/tksheet/colors.py +0 -0
  14. {tksheet-7.2.4 → tksheet-7.2.6}/tksheet/formatters.py +0 -0
  15. {tksheet-7.2.4 → tksheet-7.2.6}/tksheet/other_classes.py +0 -0
  16. {tksheet-7.2.4 → tksheet-7.2.6}/tksheet/sheet_options.py +0 -0
  17. {tksheet-7.2.4 → tksheet-7.2.6}/tksheet/text_editor.py +0 -0
  18. {tksheet-7.2.4 → tksheet-7.2.6}/tksheet/themes.py +0 -0
  19. {tksheet-7.2.4 → tksheet-7.2.6}/tksheet/top_left_rectangle.py +0 -0
  20. {tksheet-7.2.4 → tksheet-7.2.6}/tksheet/types.py +0 -0
  21. {tksheet-7.2.4 → tksheet-7.2.6}/tksheet/vars.py +0 -0
  22. {tksheet-7.2.4 → tksheet-7.2.6}/tksheet.egg-info/SOURCES.txt +0 -0
  23. {tksheet-7.2.4 → tksheet-7.2.6}/tksheet.egg-info/dependency_links.txt +0 -0
  24. {tksheet-7.2.4 → tksheet-7.2.6}/tksheet.egg-info/top_level.txt +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: tksheet
3
- Version: 7.2.4
3
+ Version: 7.2.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
@@ -6,7 +6,7 @@ build-backend = "setuptools.build_meta"
6
6
  name = "tksheet"
7
7
  description = "Tkinter table / sheet widget"
8
8
  readme = "README.md"
9
- version = "7.2.4"
9
+ version = "7.2.6"
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.2.4"
7
+ __version__ = "7.2.6"
8
8
 
9
9
  from .colors import (
10
10
  color_map,
@@ -53,6 +53,7 @@ from .functions import (
53
53
  get_new_indexes,
54
54
  get_seq_without_gaps_at_index,
55
55
  insert_items,
56
+ is_contiguous,
56
57
  is_iterable,
57
58
  move_elements_by_mapping,
58
59
  move_elements_to,
@@ -847,8 +847,10 @@ class ColumnHeaders(tk.Canvas):
847
847
  and is_contiguous(self.dragged_col.to_move)
848
848
  )
849
849
  ):
850
- if c >= len(self.MT.col_positions) - 1:
851
- c -= 1
850
+ if c > self.dragged_col.to_move[-1]:
851
+ c += 1
852
+ if c > len(self.MT.col_positions) - 1:
853
+ c = len(self.MT.col_positions) - 1
852
854
  event_data = event_dict(
853
855
  name="move_columns",
854
856
  sheet=self.PAR.name,
@@ -1010,7 +1012,9 @@ class ColumnHeaders(tk.Canvas):
1010
1012
  txt = self.get_valid_cell_data_as_str(datacn, fix=False)
1011
1013
  if txt:
1012
1014
  self.MT.txt_measure_canvas.itemconfig(
1013
- self.MT.txt_measure_canvas_text, text=txt, font=self.PAR.ops.header_font
1015
+ self.MT.txt_measure_canvas_text,
1016
+ text=txt,
1017
+ font=self.PAR.ops.header_font,
1014
1018
  )
1015
1019
  b = self.MT.txt_measure_canvas.bbox(self.MT.txt_measure_canvas_text)
1016
1020
  w = b[2] - b[0] + 7
@@ -412,8 +412,8 @@ def consecutive_ranges(seq: Sequence[int]) -> Generator[tuple[int, int]]:
412
412
  yield seq[start], seq[-1] + 1
413
413
 
414
414
 
415
- def is_contiguous(seq: list[int]) -> bool:
416
- itr = iter(seq)
415
+ def is_contiguous(iterable: Iterator[int]) -> bool:
416
+ itr = iter(iterable)
417
417
  prev = next(itr)
418
418
  return all(i == (prev := prev + 1) for i in itr)
419
419
 
@@ -485,7 +485,6 @@ def move_elements_to(
485
485
  return move_elements_by_mapping(
486
486
  seq,
487
487
  *get_new_indexes(
488
- len(seq),
489
488
  move_to,
490
489
  to_move,
491
490
  get_inverse=True,
@@ -494,19 +493,15 @@ def move_elements_to(
494
493
 
495
494
 
496
495
  def get_new_indexes(
497
- seqlen: int,
498
496
  move_to: int,
499
497
  to_move: list[int],
500
- keep_len: bool = True,
501
498
  get_inverse: bool = False,
502
499
  ) -> tuple[dict]:
503
- # returns
504
- # {old idx: new idx, ...}
505
- offset = len(to_move) - 1
506
- if move_to <= to_move[0]:
507
- new_idxs = range(move_to, move_to + len(to_move))
508
- else:
509
- new_idxs = range(move_to - offset, move_to - offset + len(to_move))
500
+ """
501
+ returns {old idx: new idx, ...}
502
+ """
503
+ offset = sum(1 for i in to_move if i < move_to)
504
+ new_idxs = range(move_to - offset, move_to - offset + len(to_move))
510
505
  new_idxs = {old: new for old, new in zip(to_move, new_idxs)}
511
506
  if get_inverse:
512
507
  return new_idxs, dict(zip(new_idxs.values(), new_idxs))
@@ -996,18 +996,16 @@ class MainTable(tk.Canvas):
996
996
  data_indexes: bool = False,
997
997
  ) -> tuple[dict[int, int], dict[int, int], int, dict[int, int]]:
998
998
  if not data_indexes or self.all_columns_displayed:
999
- disp_new_idxs = get_new_indexes(
1000
- seqlen=len(self.col_positions) - 1,
1001
- move_to=move_to,
1002
- to_move=to_move,
1003
- )
999
+ disp_new_idxs = get_new_indexes(move_to=move_to, to_move=to_move)
1004
1000
  else:
1005
1001
  disp_new_idxs = {}
1006
- totalcols = self.equalize_data_row_lengths(at_least_cols=move_to + 1)
1007
- if self.all_columns_displayed or data_indexes:
1008
- data_new_idxs = get_new_indexes(seqlen=totalcols, move_to=move_to, to_move=to_move)
1009
- elif not self.all_columns_displayed and not data_indexes:
1010
- data_new_idxs = get_new_indexes(seqlen=len(self.displayed_columns), move_to=move_to, to_move=to_move)
1002
+ # at_least_cols should not be len in this case as move_to can be len
1003
+ if not self.all_columns_displayed and not data_indexes:
1004
+ totalcols = self.equalize_data_row_lengths(at_least_cols=self.datacn(move_to))
1005
+ else:
1006
+ totalcols = self.equalize_data_row_lengths(at_least_cols=move_to)
1007
+ data_new_idxs = get_new_indexes(move_to=move_to, to_move=to_move)
1008
+ if not self.all_columns_displayed and not data_indexes:
1011
1009
  moved = {self.displayed_columns[i] for i in to_move}
1012
1010
  data_new_idxs = dict(
1013
1011
  filter(
@@ -1233,22 +1231,18 @@ class MainTable(tk.Canvas):
1233
1231
  data_indexes: bool = False,
1234
1232
  ) -> tuple[dict[int, int], dict[int, int], int, dict[int, int]]:
1235
1233
  if not data_indexes or self.all_rows_displayed:
1236
- disp_new_idxs = get_new_indexes(
1237
- seqlen=len(self.row_positions) - 1,
1238
- move_to=move_to,
1239
- to_move=to_move,
1240
- )
1234
+ disp_new_idxs = get_new_indexes(move_to=move_to, to_move=to_move)
1241
1235
  else:
1242
1236
  disp_new_idxs = {}
1243
- self.fix_data_len(move_to)
1244
- totalrows = max(
1245
- self.total_data_rows(),
1246
- len(self.row_positions) - 1,
1247
- )
1248
- if self.all_rows_displayed or data_indexes:
1249
- data_new_idxs = get_new_indexes(seqlen=totalrows, move_to=move_to, to_move=to_move)
1250
- elif not self.all_rows_displayed and not data_indexes:
1251
- data_new_idxs = get_new_indexes(seqlen=len(self.displayed_rows), move_to=move_to, to_move=to_move)
1237
+ # move_to can be len and fix_data_len() takes index so - 1
1238
+ if not self.all_rows_displayed and not data_indexes:
1239
+ fix_len = self.datarn(move_to) - 1
1240
+ else:
1241
+ fix_len = move_to - 1
1242
+ self.fix_data_len(fix_len)
1243
+ totalrows = max(self.total_data_rows(), len(self.row_positions) - 1)
1244
+ data_new_idxs = get_new_indexes(move_to=move_to, to_move=to_move)
1245
+ if not self.all_rows_displayed and not data_indexes:
1252
1246
  moved = {self.displayed_rows[i] for i in to_move}
1253
1247
  data_new_idxs = dict(
1254
1248
  filter(
@@ -1284,7 +1278,7 @@ class MainTable(tk.Canvas):
1284
1278
  len(self.row_positions) - 1,
1285
1279
  max(data_new_idxs.values(), default=0),
1286
1280
  )
1287
- self.fix_data_len(totalrows)
1281
+ self.fix_data_len(totalrows - 1)
1288
1282
  if event_data is None:
1289
1283
  event_data = event_dict(
1290
1284
  name="move_rows",
@@ -3703,10 +3697,9 @@ class MainTable(tk.Canvas):
3703
3697
  else:
3704
3698
  return False
3705
3699
 
3706
- def set_all_cell_sizes_to_text(self, w: int | None = None, slim: bool = False) -> tuple[list[float], list[float]]:
3700
+ def set_all_cell_sizes_to_text(self, width: int | None = None, slim: bool = False) -> tuple[list[float], list[float]]:
3707
3701
  min_column_width = int(self.min_column_width)
3708
3702
  min_rh = int(self.min_row_height)
3709
- w = min_column_width if w is None else w
3710
3703
  h = min_rh
3711
3704
  rhs = defaultdict(lambda: int(min_rh))
3712
3705
  cws = []
@@ -3736,6 +3729,7 @@ class MainTable(tk.Canvas):
3736
3729
  rhs[datarn] = h
3737
3730
  added_w_space = 1 if slim else 7
3738
3731
  for datacn in itercols:
3732
+ w = min_column_width if width is None else width
3739
3733
  if (hw := self.CH.get_cell_dimensions(datacn)[0]) > w:
3740
3734
  w = hw
3741
3735
  else:
@@ -4373,7 +4367,7 @@ class MainTable(tk.Canvas):
4373
4367
  create_ops=create_ops,
4374
4368
  )
4375
4369
  if create_selections:
4376
- self.deselect("all")
4370
+ self.deselect("all", redraw=False)
4377
4371
  for boxst, boxend in consecutive_ranges(tuple(reversed(column_widths))):
4378
4372
  self.create_selection_box(
4379
4373
  0,
@@ -4517,7 +4511,7 @@ class MainTable(tk.Canvas):
4517
4511
  create_ops=create_ops,
4518
4512
  )
4519
4513
  if create_selections:
4520
- self.deselect("all")
4514
+ self.deselect("all", redraw=False)
4521
4515
  for boxst, boxend in consecutive_ranges(tuple(reversed(row_heights))):
4522
4516
  self.create_selection_box(
4523
4517
  boxst,
@@ -6378,6 +6372,18 @@ class MainTable(tk.Canvas):
6378
6372
  for c in range(box.coords.from_c, box.coords.upto_c)
6379
6373
  }
6380
6374
 
6375
+ def gen_selected_cells(
6376
+ self,
6377
+ get_rows: bool = False,
6378
+ get_cols: bool = False,
6379
+ ) -> Generator[tuple[int, int]]:
6380
+ yield from (
6381
+ (r, c)
6382
+ for item, box in self.get_selection_items(rows=get_rows, columns=get_cols)
6383
+ for r in range(box.coords.from_r, box.coords.upto_r)
6384
+ for c in range(box.coords.from_c, box.coords.upto_c)
6385
+ )
6386
+
6381
6387
  def get_all_selection_boxes(self) -> tuple[tuple[int, int, int, int]]:
6382
6388
  return tuple(box.coords for item, box in self.get_selection_items())
6383
6389
 
@@ -846,8 +846,10 @@ class RowIndex(tk.Canvas):
846
846
  and is_contiguous(self.dragged_row.to_move)
847
847
  )
848
848
  ):
849
- if r >= len(self.MT.row_positions) - 1:
850
- r -= 1
849
+ if r > self.dragged_row.to_move[-1]:
850
+ r += 1
851
+ if r > len(self.MT.row_positions) - 1:
852
+ r = len(self.MT.row_positions) - 1
851
853
  event_data = event_dict(
852
854
  name="move_rows",
853
855
  sheet=self.PAR.name,
@@ -2488,6 +2490,14 @@ class RowIndex(tk.Canvas):
2488
2490
  ):
2489
2491
  yield from self.get_iid_descendants(cnode.iid, check_open)
2490
2492
 
2493
+ def items_parent(self, iid: str) -> str:
2494
+ if self.tree[iid].parent:
2495
+ return self.tree[iid].parent.iid
2496
+ return ""
2497
+
2498
+ def gen_top_nodes(self) -> Generator[Node]:
2499
+ yield from (node for node in self.MT._row_index if node.parent == "")
2500
+
2491
2501
  def get_treeview_indent(self, iid: str) -> int:
2492
2502
  if isinstance(self.PAR.ops.treeview_indent, str):
2493
2503
  indent = self.MT.index_txt_width * int(self.PAR.ops.treeview_indent)
@@ -19,6 +19,7 @@ from .column_headers import ColumnHeaders
19
19
  from .functions import (
20
20
  add_highlight,
21
21
  add_to_options,
22
+ consecutive_ranges,
22
23
  convert_align,
23
24
  data_to_displayed_idxs,
24
25
  del_from_options,
@@ -2440,23 +2441,29 @@ class Sheet(tk.Frame):
2440
2441
  include_header=include_header,
2441
2442
  )
2442
2443
 
2443
- def full_move_rows_idxs(self, data_idxs: dict[int, int]) -> dict[int, int]:
2444
+ def full_move_rows_idxs(self, data_idxs: dict[int, int], max_idx: int | None = None) -> dict[int, int]:
2444
2445
  """
2445
2446
  Converts the dict provided by moving rows event data
2446
2447
  Under the keys ['moved']['rows']['data']
2447
2448
  Into a dict of {old index: new index} for every row
2448
2449
  Includes row numbers in cell options, spans, etc.
2449
2450
  """
2450
- return self.MT.get_full_new_idxs(self.MT.get_max_row_idx(), data_idxs)
2451
+ return self.MT.get_full_new_idxs(
2452
+ self.MT.get_max_row_idx() if max_idx is None else max_idx,
2453
+ data_idxs,
2454
+ )
2451
2455
 
2452
- def full_move_columns_idxs(self, data_idxs: dict[int, int]) -> dict[int, int]:
2456
+ def full_move_columns_idxs(self, data_idxs: dict[int, int], max_idx: int | None = None) -> dict[int, int]:
2453
2457
  """
2454
2458
  Converts the dict provided by moving columns event data
2455
2459
  Under the keys ['moved']['columns']['data']
2456
2460
  Into a dict of {old index: new index} for every column
2457
2461
  Includes column numbers in cell options, spans, etc.
2458
2462
  """
2459
- return self.MT.get_full_new_idxs(self.MT.get_max_column_idx(), data_idxs)
2463
+ return self.MT.get_full_new_idxs(
2464
+ self.MT.get_max_column_idx() if max_idx is None else max_idx,
2465
+ data_idxs,
2466
+ )
2460
2467
 
2461
2468
  # Highlighting Cells
2462
2469
 
@@ -3005,8 +3012,8 @@ class Sheet(tk.Frame):
3005
3012
  box=selected[3],
3006
3013
  )
3007
3014
  else:
3008
- self.MT.deselect()
3009
- return self
3015
+ self.MT.deselect(redraw=False)
3016
+ return self.set_refresh_timer()
3010
3017
 
3011
3018
  def get_selected_rows(
3012
3019
  self,
@@ -3053,6 +3060,13 @@ class Sheet(tk.Frame):
3053
3060
  )
3054
3061
  return self.MT.get_selected_cells(get_rows=get_rows, get_cols=get_columns)
3055
3062
 
3063
+ def gen_selected_cells(
3064
+ self,
3065
+ get_rows: bool = False,
3066
+ get_columns: bool = False,
3067
+ ) -> Generator[tuple[int, int]]:
3068
+ yield from self.MT.gen_selected_cells(get_rows=get_rows, get_cols=get_columns)
3069
+
3056
3070
  def get_all_selection_boxes(self) -> tuple[tuple[int, int, int, int]]:
3057
3071
  return self.MT.get_all_selection_boxes()
3058
3072
 
@@ -3065,11 +3079,11 @@ class Sheet(tk.Frame):
3065
3079
 
3066
3080
  @boxes.setter
3067
3081
  def boxes(self, boxes: Sequence[tuple[tuple[int, int, int, int], str]]) -> Sheet:
3068
- self.MT.deselect()
3082
+ self.MT.deselect(redraw=False)
3069
3083
  self.MT.reselect_from_get_boxes(
3070
3084
  boxes={box[0] if isinstance(box[0], tuple) else tuple(box[0]): box[1] for box in boxes}
3071
3085
  )
3072
- return self
3086
+ return self.set_refresh_timer()
3073
3087
 
3074
3088
  @property
3075
3089
  def canvas_boxes(self) -> dict[int, SelectionBox]:
@@ -3348,7 +3362,7 @@ class Sheet(tk.Frame):
3348
3362
  width: int | None = None,
3349
3363
  slim: bool = False,
3350
3364
  ) -> tuple[list[float], list[float]]:
3351
- self.MT.set_all_cell_sizes_to_text(w=width, slim=slim)
3365
+ self.MT.set_all_cell_sizes_to_text(width=width, slim=slim)
3352
3366
  self.set_refresh_timer(redraw)
3353
3367
  return self.MT.row_positions, self.MT.col_positions
3354
3368
 
@@ -4700,6 +4714,7 @@ class Sheet(tk.Frame):
4700
4714
  create_selections=False,
4701
4715
  fill=False,
4702
4716
  push_ops=push_ops,
4717
+ redraw=False,
4703
4718
  )
4704
4719
  self.MT.all_rows_displayed = False
4705
4720
  self.MT.displayed_rows = list(range(len(self.MT._row_index)))
@@ -4740,9 +4755,8 @@ class Sheet(tk.Frame):
4740
4755
  open_ids = set(filter(self.exists, map(str.lower, open_ids)))
4741
4756
  self.RI.tree_open_ids = set()
4742
4757
  if open_ids:
4743
- to_open = self._tree_open(open_ids)
4744
4758
  self.show_rows(
4745
- rows=to_open,
4759
+ rows=self._tree_open(open_ids),
4746
4760
  redraw=False,
4747
4761
  deselect_all=False,
4748
4762
  )
@@ -4991,13 +5005,11 @@ class Sheet(tk.Frame):
4991
5005
  self.move(iid, parent)
4992
5006
  return self
4993
5007
 
4994
- def find_rn_at_top_index(self, index: int) -> int:
4995
- wo_par = 0
4996
- for rn, n in enumerate(self.MT._row_index):
4997
- if not n.parent:
4998
- if wo_par == index:
4999
- return rn
5000
- wo_par += 1
5008
+ def top_index_row(self, index: int) -> int:
5009
+ try:
5010
+ return next(self.RI.tree_rns[n.iid] for i, n in enumerate(self.RI.gen_top_nodes()) if i == index)
5011
+ except Exception:
5012
+ return None
5001
5013
 
5002
5014
  def move(self, item: str, parent: str, index: int | None = None) -> Sheet:
5003
5015
  """
@@ -5020,8 +5032,6 @@ class Sheet(tk.Frame):
5020
5032
  index = len(parent_node.children) - 1
5021
5033
  item_r = self.RI.tree_rns[item]
5022
5034
  new_r = self.RI.tree_rns[parent_node.children[index].iid]
5023
- if item_node not in parent_node.children:
5024
- new_r += 1
5025
5035
  new_r_desc = sum(1 for _ in self.RI.get_iid_descendants(parent_node.children[index].iid))
5026
5036
  item_desc = sum(1 for _ in self.RI.get_iid_descendants(item))
5027
5037
  if item_r < new_r:
@@ -5029,6 +5039,8 @@ class Sheet(tk.Frame):
5029
5039
  else:
5030
5040
  r_ctr = new_r
5031
5041
  else:
5042
+ if index is None:
5043
+ index = 0
5032
5044
  r_ctr = self.RI.tree_rns[parent_node.iid] + 1
5033
5045
  mapping[item_r] = r_ctr
5034
5046
  if parent in self.RI.tree_open_ids and self.item_displayed(parent):
@@ -5039,11 +5051,19 @@ class Sheet(tk.Frame):
5039
5051
  if to_show and self.RI.ancestors_all_open(did, item_node.parent):
5040
5052
  to_show.append(r_ctr)
5041
5053
  r_ctr += 1
5042
- self.RI.remove_node_from_parents_children(item_node)
5043
- item_node.parent = parent_node
5044
- parent_node.children.append(item_node)
5054
+ if parent == self.RI.items_parent(item):
5055
+ pop_index = parent_node.children.index(item_node)
5056
+ parent_node.children.insert(index, parent_node.children.pop(pop_index))
5057
+ else:
5058
+ self.RI.remove_node_from_parents_children(item_node)
5059
+ item_node.parent = parent_node
5060
+ parent_node.children.insert(index, item_node)
5045
5061
  else:
5046
- new_r = self.find_rn_at_top_index((sum(1 for _ in self.get_children("")) - 1) if index is None else index)
5062
+ if index is None:
5063
+ new_r = self.top_index_row((sum(1 for _ in self.RI.gen_top_nodes()) - 1))
5064
+ else:
5065
+ if (new_r := self.top_index_row(index)) is None:
5066
+ new_r = self.top_index_row((sum(1 for _ in self.RI.gen_top_nodes()) - 1))
5047
5067
  item_r = self.RI.tree_rns[item]
5048
5068
  if item_r < new_r:
5049
5069
  par_desc = sum(1 for _ in self.RI.get_iid_descendants(self.rowitem(new_r, data_index=True)))
@@ -5086,7 +5106,7 @@ class Sheet(tk.Frame):
5086
5106
  if (item := item.lower()) not in self.RI.tree:
5087
5107
  raise ValueError(f"Item '{item}' does not exist.")
5088
5108
  if not self.RI.tree[item].parent:
5089
- return sorted(self.RI.tree_rns[iid] for iid in self.get_children("")).index(self.RI.tree_rns[item])
5109
+ return next(index for index, node in enumerate(self.RI.gen_top_nodes()) if node == self.RI.tree[item])
5090
5110
  return self.RI.tree[item].parent.children.index(self.RI.tree[item])
5091
5111
 
5092
5112
  def item_displayed(self, item: str) -> bool:
@@ -5098,7 +5118,7 @@ class Sheet(tk.Frame):
5098
5118
  raise ValueError(f"Item '{item}' does not exist.")
5099
5119
  return self.RI.tree_rns[item] in self.MT.displayed_rows
5100
5120
 
5101
- def display_item(self, item: str) -> Sheet:
5121
+ def display_item(self, item: str, redraw=False) -> Sheet:
5102
5122
  """
5103
5123
  Ensure that item is displayed in the tree
5104
5124
  - Opens all of an item's ancestors
@@ -5109,16 +5129,22 @@ class Sheet(tk.Frame):
5109
5129
  raise ValueError(f"Item '{item}' does not exist.")
5110
5130
  if self.RI.tree[item].parent:
5111
5131
  for iid in self.RI.get_iid_ancestors(item):
5112
- self.item(iid, open_=True)
5132
+ self.item(iid, open_=True, redraw=False)
5133
+ return self.set_refresh_timer(redraw)
5113
5134
 
5114
- def scroll_to_item(self, item: str) -> Sheet:
5135
+ def scroll_to_item(self, item: str, redraw=False) -> Sheet:
5115
5136
  """
5116
5137
  Scrolls to an item and ensures that it is displayed
5117
5138
  """
5118
5139
  if (item := item.lower()) not in self.RI.tree:
5119
5140
  raise ValueError(f"Item '{item}' does not exist.")
5120
- self.display_item(item)
5121
- self.see(row=bisect_left(self.MT.displayed_rows, self.RI.tree_rns[item]), keep_xscroll=True)
5141
+ self.display_item(item, redraw=False)
5142
+ self.see(
5143
+ row=bisect_left(self.MT.displayed_rows, self.RI.tree_rns[item]),
5144
+ keep_xscroll=True,
5145
+ redraw=False,
5146
+ )
5147
+ return self.set_refresh_timer(redraw)
5122
5148
 
5123
5149
  def selection(self, cells: bool = False) -> list[str]:
5124
5150
  """
@@ -5129,45 +5155,68 @@ class Sheet(tk.Frame):
5129
5155
  for rn in self.get_selected_rows(get_cells_as_rows=cells)
5130
5156
  ]
5131
5157
 
5132
- def selection_set(self, *items) -> Sheet:
5158
+ def selection_set(self, *items, redraw: bool = True) -> Sheet:
5133
5159
  if any(item.lower() in self.RI.tree for item in unpack(items)):
5134
- self.deselect()
5135
- self.selection_add(*items)
5136
- return self
5160
+ self.deselect(redraw=False)
5161
+ self.selection_add(*items, redraw=False)
5162
+ return self.set_refresh_timer(redraw)
5137
5163
 
5138
- def selection_add(self, *items) -> Sheet:
5164
+ def selection_add(self, *items, redraw: bool = True) -> Sheet:
5165
+ to_open = []
5166
+ quick_displayed_check = set(self.MT.displayed_rows)
5139
5167
  for item in unpack(items):
5140
- if (item := item.lower()) not in self.RI.tree:
5141
- continue
5142
- if not self.item_displayed(item):
5143
- self.display_item(item)
5144
- self.add_row_selection(bisect_left(self.MT.displayed_rows, self.RI.tree_rns[item]))
5145
- return self
5168
+ if self.RI.tree_rns[(item := item.lower())] not in quick_displayed_check and self.RI.tree[item].parent:
5169
+ to_open.extend(list(self.RI.get_iid_ancestors(item)))
5170
+ if to_open:
5171
+ self.show_rows(
5172
+ rows=self._tree_open(to_open),
5173
+ redraw=False,
5174
+ deselect_all=False,
5175
+ )
5176
+ for startr, endr in consecutive_ranges(
5177
+ sorted(
5178
+ bisect_left(
5179
+ self.MT.displayed_rows,
5180
+ self.RI.tree_rns[item.lower()],
5181
+ )
5182
+ for item in unpack(items)
5183
+ )
5184
+ ):
5185
+ self.MT.create_selection_box(
5186
+ startr,
5187
+ 0,
5188
+ endr,
5189
+ len(self.MT.col_positions) - 1,
5190
+ "rows",
5191
+ set_current=True,
5192
+ ext=True,
5193
+ )
5194
+ self.MT.run_selection_binding("rows")
5195
+ return self.set_refresh_timer(redraw)
5146
5196
 
5147
- def selection_remove(self, *items) -> Sheet:
5197
+ def selection_remove(self, *items, redraw: bool = True) -> Sheet:
5148
5198
  for item in unpack(items):
5149
5199
  if (item := item.lower()) not in self.RI.tree:
5150
5200
  continue
5151
5201
  try:
5152
- self.deselect(bisect_left(self.MT.displayed_rows, self.RI.tree_rns[item]))
5202
+ self.deselect(bisect_left(self.MT.displayed_rows, self.RI.tree_rns[item]), redraw=False)
5153
5203
  except Exception:
5154
5204
  continue
5155
- return self
5205
+ return self.set_refresh_timer(redraw)
5156
5206
 
5157
- def selection_toggle(self, *items) -> Sheet:
5207
+ def selection_toggle(self, *items, redraw: bool = True) -> Sheet:
5158
5208
  selected = set(self.MT._row_index[self.displayed_row_to_data(rn)].iid for rn in self.get_selected_rows())
5159
5209
  add = []
5160
5210
  remove = []
5161
5211
  for item in unpack(items):
5162
- if (item := item.lower()) not in self.RI.tree:
5163
- continue
5164
- if item in selected:
5165
- remove.append(item)
5166
- else:
5167
- add.append(item)
5168
- self.selection_remove(*remove)
5169
- self.selection_add(*add)
5170
- return self
5212
+ if (item := item.lower()) in self.RI.tree:
5213
+ if item in selected:
5214
+ remove.append(item)
5215
+ else:
5216
+ add.append(item)
5217
+ self.selection_remove(*remove, redraw=False)
5218
+ self.selection_add(*add, redraw=False)
5219
+ return self.set_refresh_timer(redraw)
5171
5220
 
5172
5221
  # Functions not in docs
5173
5222
 
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: tksheet
3
- Version: 7.2.4
3
+ Version: 7.2.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
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes