tksheet 7.1.8__py3-none-any.whl → 7.1.10__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.8"
7
+ __version__ = "7.1.10"
8
8
 
9
9
  from .colors import (
10
10
  color_map,
@@ -49,6 +49,7 @@ from .functions import (
49
49
  get_n2a,
50
50
  get_new_indexes,
51
51
  get_seq_without_gaps_at_index,
52
+ insert_items,
52
53
  is_iterable,
53
54
  move_elements_by_mapping,
54
55
  move_elements_to,
tksheet/column_headers.py CHANGED
@@ -1320,6 +1320,16 @@ class ColumnHeaders(tk.Canvas):
1320
1320
  t = self.create_polygon(points, fill=fill, outline=outline, tag=tag, smooth=True)
1321
1321
  self.disp_checkbox[t] = True
1322
1322
 
1323
+ def configure_scrollregion(self, last_col_line_pos: float) -> None:
1324
+ self.configure(
1325
+ scrollregion=(
1326
+ 0,
1327
+ 0,
1328
+ last_col_line_pos + self.PAR.ops.empty_horizontal + 2,
1329
+ self.current_height,
1330
+ )
1331
+ )
1332
+
1323
1333
  def redraw_grid_and_text(
1324
1334
  self,
1325
1335
  last_col_line_pos,
@@ -1331,14 +1341,7 @@ class ColumnHeaders(tk.Canvas):
1331
1341
  col_pos_exists,
1332
1342
  ):
1333
1343
  try:
1334
- self.configure(
1335
- scrollregion=(
1336
- 0,
1337
- 0,
1338
- last_col_line_pos + self.PAR.ops.empty_horizontal + 2,
1339
- self.current_height,
1340
- )
1341
- )
1344
+ self.configure_scrollregion(last_col_line_pos=last_col_line_pos)
1342
1345
  except Exception:
1343
1346
  return
1344
1347
  self.hidd_text.update(self.disp_text)
tksheet/functions.py CHANGED
@@ -614,7 +614,7 @@ def try_binding(
614
614
  event: dict,
615
615
  new_name: None | str = None,
616
616
  ) -> bool:
617
- if binding is not None:
617
+ if binding:
618
618
  try:
619
619
  if new_name is None:
620
620
  binding(event)
tksheet/main_table.py CHANGED
@@ -1130,7 +1130,11 @@ class MainTable(tk.Canvas):
1130
1130
  )
1131
1131
  else:
1132
1132
  disp_new_idxs = {}
1133
- totalrows = self.fix_data_len(move_to)
1133
+ self.fix_data_len(move_to)
1134
+ totalrows = max(
1135
+ self.total_data_rows(),
1136
+ len(self.row_positions) - 1,
1137
+ )
1134
1138
  if self.all_rows_displayed or data_indexes:
1135
1139
  data_new_idxs = get_new_indexes(seqlen=totalrows, move_to=move_to, to_move=to_move)
1136
1140
  elif not self.all_rows_displayed and not data_indexes:
@@ -1157,7 +1161,12 @@ class MainTable(tk.Canvas):
1157
1161
  ) -> tuple[dict[int, int], dict[int, int], EventDataDict]:
1158
1162
  self.saved_row_heights = {}
1159
1163
  if not isinstance(totalrows, int):
1160
- totalrows = self.fix_data_len(max(data_new_idxs.values(), default=0))
1164
+ totalrows = max(
1165
+ self.total_data_rows(),
1166
+ len(self.row_positions) - 1,
1167
+ max(data_new_idxs.values(), default=0),
1168
+ )
1169
+ totalrows = self.fix_data_len(totalrows)
1161
1170
  if event_data is None:
1162
1171
  event_data = event_dict(
1163
1172
  name="move_rows",
@@ -1444,9 +1453,7 @@ class MainTable(tk.Canvas):
1444
1453
  saved_cells = True
1445
1454
 
1446
1455
  if modification["moved"]["columns"]:
1447
- totalcols = self.equalize_data_row_lengths()
1448
- if totalcols < (mx_k := max(modification["moved"]["columns"]["data"].values())):
1449
- totalcols = mx_k
1456
+ totalcols = max(self.equalize_data_row_lengths(), max(modification["moved"]["columns"]["data"].values()))
1450
1457
  data_new_idxs, disp_new_idxs, event_data = self.move_columns_adjust_options_dict(
1451
1458
  data_new_idxs=dict(
1452
1459
  zip(
@@ -1471,9 +1478,7 @@ class MainTable(tk.Canvas):
1471
1478
  self.restore_options_named_spans(modification)
1472
1479
 
1473
1480
  if modification["moved"]["rows"]:
1474
- totalrows = self.total_data_rows()
1475
- if totalrows < (mx_k := max(modification["moved"]["rows"]["data"].values())):
1476
- totalrows = mx_k
1481
+ totalrows = max(self.total_data_rows(), max(modification["moved"]["rows"]["data"].values()))
1477
1482
  data_new_idxs, disp_new_idxs, event_data = self.move_rows_adjust_options_dict(
1478
1483
  data_new_idxs=dict(
1479
1484
  zip(
@@ -2198,98 +2203,6 @@ class MainTable(tk.Canvas):
2198
2203
  check_cell_visibility=False,
2199
2204
  )
2200
2205
 
2201
- def key_bindings(self) -> None:
2202
- for widget in (self, self.RI, self.CH, self.TL):
2203
- for binding in self.PAR.ops.copy_bindings:
2204
- if self.copy_enabled:
2205
- widget.bind(binding, self.ctrl_c)
2206
- else:
2207
- widget.unbind(binding)
2208
-
2209
- for binding in self.PAR.ops.cut_bindings:
2210
- if self.cut_enabled:
2211
- widget.bind(binding, self.ctrl_x)
2212
- else:
2213
- widget.unbind(binding)
2214
-
2215
- for binding in self.PAR.ops.paste_bindings:
2216
- if self.paste_enabled:
2217
- widget.bind(binding, self.ctrl_v)
2218
- else:
2219
- widget.unbind(binding)
2220
-
2221
- if self.undo_enabled:
2222
- for binding in self.PAR.ops.undo_bindings:
2223
- widget.bind(binding, self.undo)
2224
- for binding in self.PAR.ops.redo_bindings:
2225
- widget.bind(binding, self.redo)
2226
- else:
2227
- for binding in self.PAR.ops.undo_bindings:
2228
- widget.unbind(binding)
2229
- for binding in self.PAR.ops.redo_bindings:
2230
- widget.unbind(binding)
2231
-
2232
- for binding in self.PAR.ops.delete_bindings:
2233
- if self.delete_key_enabled:
2234
- widget.bind(binding, self.delete_key)
2235
- else:
2236
- widget.unbind(binding)
2237
-
2238
- for binding in self.PAR.ops.select_all_bindings:
2239
- if self.select_all_enabled:
2240
- widget.bind(binding, self.select_all)
2241
- else:
2242
- widget.unbind(binding)
2243
-
2244
- for binding in self.PAR.ops.tab_bindings:
2245
- if self.tab_enabled:
2246
- widget.bind(binding, self.tab_key)
2247
- else:
2248
- widget.unbind(binding)
2249
-
2250
- for binding in self.PAR.ops.up_bindings:
2251
- if self.up_enabled:
2252
- widget.bind(binding, self.arrowkey_UP)
2253
- else:
2254
- widget.unbind(binding)
2255
-
2256
- for binding in self.PAR.ops.right_bindings:
2257
- if self.right_enabled:
2258
- widget.bind(binding, self.arrowkey_RIGHT)
2259
- else:
2260
- widget.unbind(binding)
2261
-
2262
- for binding in self.PAR.ops.down_bindings:
2263
- if self.down_enabled:
2264
- widget.bind(binding, self.arrowkey_DOWN)
2265
- else:
2266
- widget.unbind(binding)
2267
-
2268
- for binding in self.PAR.ops.left_bindings:
2269
- if self.left_enabled:
2270
- widget.bind(binding, self.arrowkey_LEFT)
2271
- else:
2272
- widget.unbind(binding)
2273
-
2274
- for binding in self.PAR.ops.prior_bindings:
2275
- if self.prior_enabled:
2276
- widget.bind(binding, self.page_UP)
2277
- else:
2278
- widget.unbind(binding)
2279
-
2280
- for binding in self.PAR.ops.next_bindings:
2281
- if self.next_enabled:
2282
- widget.bind(binding, self.page_DOWN)
2283
- else:
2284
- widget.unbind(binding)
2285
-
2286
- if self.edit_cell_enabled:
2287
- for w in (self, self.RI, self.CH):
2288
- w.bind("<Key>", self.open_cell)
2289
- else:
2290
- for w in (self, self.RI, self.CH):
2291
- w.unbind("<Key>")
2292
-
2293
2206
  def menu_add_command(self, menu: tk.Menu, **kwargs) -> None:
2294
2207
  if "label" not in kwargs:
2295
2208
  return
@@ -2523,35 +2436,33 @@ class MainTable(tk.Canvas):
2523
2436
 
2524
2437
  def enable_bindings(self, bindings):
2525
2438
  if not bindings:
2526
- self.enable_bindings_internal("all")
2439
+ self._enable_binding("all")
2527
2440
  elif isinstance(bindings, (list, tuple)):
2528
2441
  for binding in bindings:
2529
2442
  if isinstance(binding, (list, tuple)):
2530
2443
  for bind in binding:
2531
- self.enable_bindings_internal(bind.lower())
2444
+ self._enable_binding(bind.lower())
2532
2445
  elif isinstance(binding, str):
2533
- self.enable_bindings_internal(binding.lower())
2446
+ self._enable_binding(binding.lower())
2534
2447
  elif isinstance(bindings, str):
2535
- self.enable_bindings_internal(bindings.lower())
2448
+ self._enable_binding(bindings.lower())
2536
2449
  self.create_rc_menus()
2537
- self.key_bindings()
2538
2450
 
2539
2451
  def disable_bindings(self, bindings):
2540
2452
  if not bindings:
2541
- self.disable_bindings_internal("all")
2453
+ self._disable_binding("all")
2542
2454
  elif isinstance(bindings, (list, tuple)):
2543
2455
  for binding in bindings:
2544
2456
  if isinstance(binding, (list, tuple)):
2545
2457
  for bind in binding:
2546
- self.disable_bindings_internal(bind.lower())
2458
+ self._disable_binding(bind.lower())
2547
2459
  elif isinstance(binding, str):
2548
- self.disable_bindings_internal(binding.lower())
2460
+ self._disable_binding(binding.lower())
2549
2461
  elif isinstance(bindings, str):
2550
- self.disable_bindings_internal(bindings)
2462
+ self._disable_binding(bindings)
2551
2463
  self.create_rc_menus()
2552
- self.key_bindings()
2553
2464
 
2554
- def enable_bindings_internal(self, binding):
2465
+ def _enable_binding(self, binding):
2555
2466
  if binding == "enable_all":
2556
2467
  binding = "all"
2557
2468
  if binding in ("all", "single", "single_selection_mode", "single_select"):
@@ -2562,9 +2473,6 @@ class MainTable(tk.Canvas):
2562
2473
  self.single_selection_enabled = False
2563
2474
  if binding in ("all", "drag_select"):
2564
2475
  self.drag_selection_enabled = True
2565
- if binding in ("all", "select_all"):
2566
- self.select_all_enabled = True
2567
- self.TL.sa_state()
2568
2476
  if binding in ("all", "column_width_resize"):
2569
2477
  self.CH.width_resizing_enabled = True
2570
2478
  if binding in ("all", "column_select"):
@@ -2587,20 +2495,47 @@ class MainTable(tk.Canvas):
2587
2495
  self.RI.row_selection_enabled = True
2588
2496
  if binding in ("all", "row_drag_and_drop", "move_rows"):
2589
2497
  self.RI.drag_and_drop_enabled = True
2498
+ if binding in ("all", "select_all"):
2499
+ self.select_all_enabled = True
2500
+ self.TL.sa_state()
2501
+ self._tksheet_bind("select_all_bindings", self.select_all)
2590
2502
  if binding in ("all", "arrowkeys", "tab"):
2591
2503
  self.tab_enabled = True
2504
+ self._tksheet_bind("tab_bindings", self.tab_key)
2592
2505
  if binding in ("all", "arrowkeys", "up"):
2593
2506
  self.up_enabled = True
2507
+ self._tksheet_bind("up_bindings", self.arrowkey_UP)
2594
2508
  if binding in ("all", "arrowkeys", "right"):
2595
2509
  self.right_enabled = True
2510
+ self._tksheet_bind("right_bindings", self.arrowkey_RIGHT)
2596
2511
  if binding in ("all", "arrowkeys", "down"):
2597
2512
  self.down_enabled = True
2513
+ self._tksheet_bind("down_bindings", self.arrowkey_DOWN)
2598
2514
  if binding in ("all", "arrowkeys", "left"):
2599
2515
  self.left_enabled = True
2516
+ self._tksheet_bind("left_bindings", self.arrowkey_LEFT)
2600
2517
  if binding in ("all", "arrowkeys", "prior"):
2601
2518
  self.prior_enabled = True
2519
+ self._tksheet_bind("prior_bindings", self.page_UP)
2602
2520
  if binding in ("all", "arrowkeys", "next"):
2603
2521
  self.next_enabled = True
2522
+ self._tksheet_bind("next_bindings", self.page_DOWN)
2523
+ if binding in ("all", "copy", "edit_bindings", "edit"):
2524
+ self.copy_enabled = True
2525
+ self._tksheet_bind("copy_bindings", self.ctrl_c)
2526
+ if binding in ("all", "cut", "edit_bindings", "edit"):
2527
+ self.cut_enabled = True
2528
+ self._tksheet_bind("cut_bindings", self.ctrl_x)
2529
+ if binding in ("all", "paste", "edit_bindings", "edit"):
2530
+ self.paste_enabled = True
2531
+ self._tksheet_bind("paste_bindings", self.ctrl_v)
2532
+ if binding in ("all", "delete", "edit_bindings", "edit"):
2533
+ self.delete_key_enabled = True
2534
+ self._tksheet_bind("delete_bindings", self.delete_key)
2535
+ if binding in ("all", "undo", "redo", "edit_bindings", "edit"):
2536
+ self.undo_enabled = True
2537
+ self._tksheet_bind("undo_bindings", self.undo)
2538
+ self._tksheet_bind("redo_bindings", self.redo)
2604
2539
  if binding in ("all", "rc_delete_column"):
2605
2540
  self.rc_delete_column_enabled = True
2606
2541
  self.rc_popup_menus_enabled = True
@@ -2617,23 +2552,15 @@ class MainTable(tk.Canvas):
2617
2552
  self.rc_insert_row_enabled = True
2618
2553
  self.rc_popup_menus_enabled = True
2619
2554
  self.rc_select_enabled = True
2620
- if binding in ("all", "copy", "edit_bindings"):
2621
- self.copy_enabled = True
2622
- if binding in ("all", "cut", "edit_bindings"):
2623
- self.cut_enabled = True
2624
- if binding in ("all", "paste", "edit_bindings"):
2625
- self.paste_enabled = True
2626
- if binding in ("all", "delete", "edit_bindings"):
2627
- self.delete_key_enabled = True
2628
2555
  if binding in ("all", "right_click_popup_menu", "rc_popup_menu"):
2629
2556
  self.rc_popup_menus_enabled = True
2630
2557
  self.rc_select_enabled = True
2631
2558
  if binding in ("all", "right_click_select", "rc_select"):
2632
2559
  self.rc_select_enabled = True
2633
- if binding in ("all", "undo", "edit_bindings"):
2634
- self.undo_enabled = True
2635
- if binding in ("all", "edit_cell", "edit_bindings"):
2560
+ if binding in ("all", "edit_cell", "edit_bindings", "edit"):
2636
2561
  self.edit_cell_enabled = True
2562
+ for w in (self, self.RI, self.CH):
2563
+ w.bind("<Key>", self.open_cell)
2637
2564
  if binding in ("edit_header"):
2638
2565
  self.CH.edit_cell_enabled = True
2639
2566
  if binding in ("edit_index"):
@@ -2642,7 +2569,12 @@ class MainTable(tk.Canvas):
2642
2569
  if binding in ("ctrl_click_select", "ctrl_select"):
2643
2570
  self.ctrl_select_enabled = True
2644
2571
 
2645
- def disable_bindings_internal(self, binding):
2572
+ def _tksheet_bind(self, bindings_key: str, func: Callable) -> None:
2573
+ for widget in (self, self.RI, self.CH, self.TL):
2574
+ for binding in self.PAR.ops[bindings_key]:
2575
+ widget.bind(binding, func)
2576
+
2577
+ def _disable_binding(self, binding):
2646
2578
  if binding == "disable_all":
2647
2579
  binding = "all"
2648
2580
  if binding in ("all", "single", "single_selection_mode", "single_select"):
@@ -2653,9 +2585,6 @@ class MainTable(tk.Canvas):
2653
2585
  self.single_selection_enabled = False
2654
2586
  if binding in ("all", "drag_select"):
2655
2587
  self.drag_selection_enabled = False
2656
- if binding in ("all", "select_all"):
2657
- self.select_all_enabled = False
2658
- self.TL.sa_state("hidden")
2659
2588
  if binding in ("all", "column_width_resize"):
2660
2589
  self.CH.width_resizing_enabled = False
2661
2590
  if binding in ("all", "column_select"):
@@ -2678,20 +2607,6 @@ class MainTable(tk.Canvas):
2678
2607
  self.RI.row_selection_enabled = False
2679
2608
  if binding in ("all", "row_drag_and_drop", "move_rows"):
2680
2609
  self.RI.drag_and_drop_enabled = False
2681
- if binding in ("all", "arrowkeys", "tab"):
2682
- self.tab_enabled = False
2683
- if binding in ("all", "arrowkeys", "up"):
2684
- self.up_enabled = False
2685
- if binding in ("all", "arrowkeys", "right"):
2686
- self.right_enabled = False
2687
- if binding in ("all", "arrowkeys", "down"):
2688
- self.down_enabled = False
2689
- if binding in ("all", "arrowkeys", "left"):
2690
- self.left_enabled = False
2691
- if binding in ("all", "arrowkeys", "prior"):
2692
- self.prior_enabled = False
2693
- if binding in ("all", "arrowkeys", "next"):
2694
- self.next_enabled = False
2695
2610
  if binding in ("all", "rc_delete_column"):
2696
2611
  self.rc_delete_column_enabled = False
2697
2612
  self.rc_popup_menus_enabled = False
@@ -2708,29 +2623,67 @@ class MainTable(tk.Canvas):
2708
2623
  self.rc_insert_row_enabled = False
2709
2624
  self.rc_popup_menus_enabled = False
2710
2625
  self.rc_select_enabled = False
2711
- if binding in ("all", "copy", "edit_bindings"):
2712
- self.copy_enabled = False
2713
- if binding in ("all", "cut", "edit_bindings"):
2714
- self.cut_enabled = False
2715
- if binding in ("all", "paste", "edit_bindings"):
2716
- self.paste_enabled = False
2717
- if binding in ("all", "delete", "edit_bindings"):
2718
- self.delete_key_enabled = False
2719
2626
  if binding in ("all", "right_click_popup_menu", "rc_popup_menu"):
2720
2627
  self.rc_popup_menus_enabled = False
2721
2628
  self.rc_select_enabled = False
2722
2629
  if binding in ("all", "right_click_select", "rc_select"):
2723
2630
  self.rc_select_enabled = False
2724
- if binding in ("all", "undo", "edit_bindings"):
2725
- self.undo_enabled = False
2726
- if binding in ("all", "edit_cell", "edit_bindings"):
2631
+ if binding in ("all", "edit_cell", "edit_bindings", "edit"):
2727
2632
  self.edit_cell_enabled = False
2728
- if binding in ("all", "edit_header", "edit_bindings"):
2633
+ for w in (self, self.RI, self.CH):
2634
+ w.unbind("<Key>")
2635
+ if binding in ("all", "edit_header", "edit_bindings", "edit"):
2729
2636
  self.CH.edit_cell_enabled = False
2730
- if binding in ("all", "edit_index", "edit_bindings"):
2637
+ if binding in ("all", "edit_index", "edit_bindings", "edit"):
2731
2638
  self.RI.edit_cell_enabled = False
2732
2639
  if binding in ("all", "ctrl_click_select", "ctrl_select"):
2733
2640
  self.ctrl_select_enabled = False
2641
+ if binding in ("all", "select_all"):
2642
+ self.select_all_enabled = False
2643
+ self.TL.sa_state("hidden")
2644
+ self._tksheet_unbind("select_all_bindings")
2645
+ if binding in ("all", "copy", "edit_bindings", "edit"):
2646
+ self.copy_enabled = False
2647
+ self._tksheet_unbind("copy_bindings")
2648
+ if binding in ("all", "cut", "edit_bindings", "edit"):
2649
+ self.cut_enabled = False
2650
+ self._tksheet_unbind("cut_bindings")
2651
+ if binding in ("all", "paste", "edit_bindings", "edit"):
2652
+ self.paste_enabled = False
2653
+ self._tksheet_unbind("paste_bindings")
2654
+ if binding in ("all", "delete", "edit_bindings", "edit"):
2655
+ self.delete_key_enabled = False
2656
+ self._tksheet_unbind("delete_bindings")
2657
+ if binding in ("all", "arrowkeys", "tab"):
2658
+ self.tab_enabled = False
2659
+ self._tksheet_unbind("tab_bindings")
2660
+ if binding in ("all", "arrowkeys", "up"):
2661
+ self.up_enabled = False
2662
+ self._tksheet_unbind("up_bindings")
2663
+ if binding in ("all", "arrowkeys", "right"):
2664
+ self.right_enabled = False
2665
+ self._tksheet_unbind("right_bindings")
2666
+ if binding in ("all", "arrowkeys", "down"):
2667
+ self.down_enabled = False
2668
+ self._tksheet_unbind("down_bindings")
2669
+ if binding in ("all", "arrowkeys", "left"):
2670
+ self.left_enabled = False
2671
+ self._tksheet_unbind("left_bindings")
2672
+ if binding in ("all", "arrowkeys", "prior"):
2673
+ self.prior_enabled = False
2674
+ self._tksheet_unbind("prior_bindings")
2675
+ if binding in ("all", "arrowkeys", "next"):
2676
+ self.next_enabled = False
2677
+ self._tksheet_unbind("next_bindings")
2678
+ if binding in ("all", "undo", "redo", "edit_bindings", "edit"):
2679
+ self.undo_enabled = False
2680
+ self._tksheet_unbind("undo_bindings", "redo_bindings")
2681
+
2682
+ def _tksheet_unbind(self, *keys) -> None:
2683
+ for widget in (self, self.RI, self.CH, self.TL):
2684
+ for bindings_key in keys:
2685
+ for binding in self.PAR.ops[bindings_key]:
2686
+ widget.unbind(binding)
2734
2687
 
2735
2688
  def reset_mouse_motion_creations(self) -> None:
2736
2689
  if self.current_cursor != "":
@@ -2745,8 +2698,7 @@ class MainTable(tk.Canvas):
2745
2698
 
2746
2699
  def mouse_motion(self, event: object):
2747
2700
  self.reset_mouse_motion_creations()
2748
- if self.extra_motion_func:
2749
- self.extra_motion_func(event)
2701
+ try_binding(self.extra_motion_func, event)
2750
2702
 
2751
2703
  def not_currently_resizing(self) -> bool:
2752
2704
  return all(v is None for v in (self.RI.rsz_h, self.RI.rsz_w, self.CH.rsz_h, self.CH.rsz_w))
@@ -2759,12 +2711,15 @@ class MainTable(tk.Canvas):
2759
2711
  r = self.identify_row(y=event.y)
2760
2712
  c = self.identify_col(x=event.x)
2761
2713
  if r < len(self.row_positions) - 1 and c < len(self.col_positions) - 1:
2762
- if self.col_selected(c) and self.rc_popup_menus_enabled:
2763
- popup_menu = self.CH.ch_rc_popup_menu
2764
- elif self.row_selected(r) and self.rc_popup_menus_enabled:
2765
- popup_menu = self.RI.ri_rc_popup_menu
2766
- elif self.cell_selected(r, c) and self.rc_popup_menus_enabled:
2767
- popup_menu = self.rc_popup_menu
2714
+ if self.col_selected(c):
2715
+ if self.rc_popup_menus_enabled:
2716
+ popup_menu = self.CH.ch_rc_popup_menu
2717
+ elif self.row_selected(r):
2718
+ if self.rc_popup_menus_enabled:
2719
+ popup_menu = self.RI.ri_rc_popup_menu
2720
+ elif self.cell_selected(r, c):
2721
+ if self.rc_popup_menus_enabled:
2722
+ popup_menu = self.rc_popup_menu
2768
2723
  else:
2769
2724
  if self.rc_select_enabled:
2770
2725
  if self.single_selection_enabled:
@@ -2774,9 +2729,9 @@ class MainTable(tk.Canvas):
2774
2729
  if self.rc_popup_menus_enabled:
2775
2730
  popup_menu = self.rc_popup_menu
2776
2731
  else:
2732
+ self.deselect("all")
2777
2733
  popup_menu = self.empty_rc_popup_menu
2778
- if self.extra_rc_func:
2779
- self.extra_rc_func(event)
2734
+ try_binding(self.extra_rc_func, event)
2780
2735
  if popup_menu is not None:
2781
2736
  popup_menu.tk_popup(event.x_root, event.y_root)
2782
2737
 
@@ -2800,8 +2755,7 @@ class MainTable(tk.Canvas):
2800
2755
  if r < len(self.row_positions) - 1 and c < len(self.col_positions) - 1:
2801
2756
  self.toggle_select_cell(r, c, redraw=True)
2802
2757
  self.b1_pressed_loc = (r, c)
2803
- if self.extra_b1_press_func:
2804
- self.extra_b1_press_func(event)
2758
+ try_binding(self.extra_b1_press_func, event)
2805
2759
 
2806
2760
  def create_resize_line(self, x1, y1, x2, y2, width, fill, tag):
2807
2761
  if self.hidd_resize_lines:
@@ -2969,8 +2923,7 @@ class MainTable(tk.Canvas):
2969
2923
  need_redraw = True
2970
2924
  if need_redraw:
2971
2925
  self.main_table_redraw_grid_and_text(redraw_header=True, redraw_row_index=True, redraw_table=True)
2972
- if self.extra_b1_motion_func:
2973
- self.extra_b1_motion_func(event)
2926
+ try_binding(self.extra_b1_motion_func, event)
2974
2927
 
2975
2928
  def ctrl_b1_motion(self, event: object):
2976
2929
  if self.ctrl_select_enabled and self.drag_selection_enabled and self.not_currently_resizing():
@@ -3082,8 +3035,7 @@ class MainTable(tk.Canvas):
3082
3035
  self.mouseclick_outside_editor_or_dropdown_all_canvases()
3083
3036
  self.b1_pressed_loc = None
3084
3037
  self.closed_dropdown = None
3085
- if self.extra_b1_release_func:
3086
- self.extra_b1_release_func(event)
3038
+ try_binding(self.extra_b1_release_func, event)
3087
3039
 
3088
3040
  def double_b1(self, event=None):
3089
3041
  self.mouseclick_outside_editor_or_dropdown_all_canvases()
@@ -3107,8 +3059,7 @@ class MainTable(tk.Canvas):
3107
3059
  self.toggle_select_cell(r, c, redraw=True)
3108
3060
  if self.edit_cell_enabled:
3109
3061
  self.open_cell(event)
3110
- if self.extra_double_b1_func:
3111
- self.extra_double_b1_func(event)
3062
+ try_binding(self.extra_double_b1_func, event)
3112
3063
 
3113
3064
  def identify_row(self, event=None, y=None, allow_end=True):
3114
3065
  if event is None:
@@ -3193,47 +3144,71 @@ class MainTable(tk.Canvas):
3193
3144
  self.y_move_synced_scrolls("moveto", self.yview()[0])
3194
3145
  return need_redraw
3195
3146
 
3196
- def x_move_synced_scrolls(self, *args, redraw: bool = True):
3147
+ def x_move_synced_scrolls(self, *args, redraw: bool = True, use_scrollbar: bool = False):
3197
3148
  for widget in self.synced_scrolls:
3198
3149
  # try:
3199
3150
  if hasattr(widget, "MT"):
3200
- widget.MT.set_xviews(*args, move_synced=False, redraw=redraw)
3151
+ if use_scrollbar:
3152
+ widget.MT._xscrollbar(*args, move_synced=False)
3153
+ else:
3154
+ widget.MT.set_xviews(*args, move_synced=False, redraw=redraw)
3201
3155
  else:
3202
3156
  widget.xview(*args)
3203
3157
  # except Exception:
3204
3158
  # continue
3205
3159
 
3206
- def y_move_synced_scrolls(self, *args, redraw: bool = True):
3160
+ def y_move_synced_scrolls(self, *args, redraw: bool = True, use_scrollbar: bool = False):
3207
3161
  for widget in self.synced_scrolls:
3208
3162
  # try:
3209
3163
  if hasattr(widget, "MT"):
3210
- widget.MT.set_yviews(*args, move_synced=False, redraw=redraw)
3164
+ if use_scrollbar:
3165
+ widget.MT._yscrollbar(*args, move_synced=False)
3166
+ else:
3167
+ widget.MT.set_yviews(*args, move_synced=False, redraw=redraw)
3211
3168
  else:
3212
3169
  widget.yview(*args)
3213
3170
  # except Exception:
3214
3171
  # continue
3215
3172
 
3173
+ def _xscrollbar(self, *args, move_synced: bool = True):
3174
+ self.xview(*args)
3175
+ if self.show_header:
3176
+ self.CH.xview(*args)
3177
+ self.main_table_redraw_grid_and_text(redraw_header=True, redraw_row_index=False)
3178
+ if move_synced:
3179
+ self.x_move_synced_scrolls(*args, use_scrollbar=True)
3180
+
3181
+ def _yscrollbar(self, *args, move_synced: bool = True):
3182
+ self.yview(*args)
3183
+ if self.show_index:
3184
+ self.RI.yview(*args)
3185
+ self.main_table_redraw_grid_and_text(redraw_header=False, redraw_row_index=True)
3186
+ if move_synced:
3187
+ self.y_move_synced_scrolls(*args, use_scrollbar=True)
3188
+
3216
3189
  def set_xviews(self, *args, move_synced: bool = True, redraw: bool = True) -> None:
3217
3190
  self.main_table_redraw_grid_and_text(setting_views=True)
3218
3191
  self.update_idletasks()
3219
3192
  self.xview(*args)
3220
3193
  if self.show_header:
3194
+ self.CH.update_idletasks()
3221
3195
  self.CH.xview(*args)
3196
+ self.main_table_redraw_grid_and_text(redraw_header=True, redraw_row_index=False)
3222
3197
  if move_synced:
3223
3198
  self.x_move_synced_scrolls(*args)
3224
3199
  self.fix_views()
3225
- self.PAR.set_refresh_timer(redraw)
3226
3200
 
3227
3201
  def set_yviews(self, *args, move_synced: bool = True, redraw: bool = True) -> None:
3228
3202
  self.main_table_redraw_grid_and_text(setting_views=True)
3229
3203
  self.update_idletasks()
3230
3204
  self.yview(*args)
3231
3205
  if self.show_index:
3206
+ self.RI.update_idletasks()
3232
3207
  self.RI.yview(*args)
3208
+ self.main_table_redraw_grid_and_text(redraw_header=False, redraw_row_index=True)
3233
3209
  if move_synced:
3234
3210
  self.y_move_synced_scrolls(*args)
3235
3211
  self.fix_views()
3236
- self.PAR.set_refresh_timer(redraw)
3237
3212
 
3238
3213
  def set_view(self, x_args: list[str, float], y_args: list[str, float]) -> None:
3239
3214
  self.set_xviews(*x_args)
@@ -3329,7 +3304,9 @@ class MainTable(tk.Canvas):
3329
3304
  else (
3330
3305
  default_row_height
3331
3306
  if h == old_default_row_height
3332
- else self.min_row_height if h < self.min_row_height else h
3307
+ else self.min_row_height
3308
+ if h < self.min_row_height
3309
+ else h
3333
3310
  )
3334
3311
  )
3335
3312
  for h in self.gen_row_heights()
@@ -4274,7 +4251,7 @@ class MainTable(tk.Canvas):
4274
4251
  return event_data
4275
4252
 
4276
4253
  def rc_add_columns(self, event: object = None):
4277
- rowlen = self.equalize_data_row_lengths(include_header=False)
4254
+ rowlen = self.equalize_data_row_lengths()
4278
4255
  selcols = sorted(self.get_selected_cols())
4279
4256
  if (
4280
4257
  selcols
@@ -4860,24 +4837,15 @@ class MainTable(tk.Canvas):
4860
4837
  return self._row_index
4861
4838
 
4862
4839
  def total_data_cols(self, include_header: bool = True) -> int:
4863
- h_total = 0
4864
- d_total = 0
4865
- if include_header:
4866
- if isinstance(self._headers, (list, tuple)):
4867
- h_total = len(self._headers)
4868
- # map() for some reason is 15% faster than max(key=len)
4869
- # using python 3.11 windows 11
4840
+ h_total = len(self._headers) if include_header and isinstance(self._headers, (list, tuple)) else 0
4841
+ # map() for some reason is 15% faster than max(key=len) using python 3.11 windows 11
4870
4842
  d_total = max(map(len, self.data), default=0)
4871
- return h_total if h_total > d_total else d_total
4843
+ return max(h_total, d_total)
4872
4844
 
4873
4845
  def total_data_rows(self, include_index: bool = True) -> int:
4874
- i_total = 0
4875
- d_total = 0
4876
- if include_index:
4877
- if isinstance(self._row_index, (list, tuple)):
4878
- i_total = len(self._row_index)
4846
+ i_total = len(self._row_index) if include_index and isinstance(self._row_index, (list, tuple)) else 0
4879
4847
  d_total = len(self.data)
4880
- return i_total if i_total > d_total else d_total
4848
+ return max(i_total, d_total)
4881
4849
 
4882
4850
  def data_dimensions(self, total_rows: int | None = None, total_columns: int | None = None):
4883
4851
  if total_rows is None and total_columns is None:
@@ -4897,7 +4865,7 @@ class MainTable(tk.Canvas):
4897
4865
 
4898
4866
  def equalize_data_row_lengths(
4899
4867
  self,
4900
- include_header: bool = False,
4868
+ include_header: bool = True,
4901
4869
  total_data_cols: int | None = None,
4902
4870
  at_least_cols: int | None = None,
4903
4871
  ) -> int:
@@ -4905,6 +4873,7 @@ class MainTable(tk.Canvas):
4905
4873
  total_data_cols = self.total_data_cols(include_header=include_header)
4906
4874
  if isinstance(at_least_cols, int) and at_least_cols > total_data_cols:
4907
4875
  total_data_cols = at_least_cols
4876
+ total_data_cols = max(total_data_cols, len(self.col_positions) - 1)
4908
4877
  if include_header and total_data_cols > len(self._headers):
4909
4878
  self.CH.fix_header(total_data_cols)
4910
4879
  for rn, r in enumerate(self.data):
@@ -5197,8 +5166,7 @@ class MainTable(tk.Canvas):
5197
5166
  resized_cols = False
5198
5167
  resized_rows = False
5199
5168
  if self.PAR.ops.auto_resize_columns and self.allow_auto_resize_columns and col_pos_exists:
5200
- max_w = int(can_width)
5201
- max_w -= self.PAR.ops.empty_horizontal
5169
+ max_w = can_width - self.PAR.ops.empty_horizontal
5202
5170
  if self.PAR.ops.auto_resize_columns < self.min_column_width:
5203
5171
  min_column_width = self.column_width
5204
5172
  else:
@@ -5222,8 +5190,7 @@ class MainTable(tk.Canvas):
5222
5190
  widths[i] -= change
5223
5191
  self.set_col_positions(itr=widths)
5224
5192
  if self.PAR.ops.auto_resize_rows and self.allow_auto_resize_rows and row_pos_exists:
5225
- max_h = int(can_height)
5226
- max_h -= self.PAR.ops.empty_vertical
5193
+ max_h = can_height - self.PAR.ops.empty_vertical
5227
5194
  if self.PAR.ops.auto_resize_rows < self.min_row_height:
5228
5195
  min_row_height = self.min_row_height
5229
5196
  else:
@@ -5276,11 +5243,13 @@ class MainTable(tk.Canvas):
5276
5243
  last_col_line_pos + self.PAR.ops.empty_horizontal + 2,
5277
5244
  last_row_line_pos + self.PAR.ops.empty_vertical + 2,
5278
5245
  )
5279
- if scrollregion != self.scrollregion:
5246
+ if setting_views or scrollregion != self.scrollregion:
5280
5247
  self.configure(scrollregion=scrollregion)
5281
5248
  self.scrollregion = scrollregion
5282
- if setting_views:
5283
- return False
5249
+ self.CH.configure_scrollregion(last_col_line_pos)
5250
+ self.RI.configure_scrollregion(last_row_line_pos)
5251
+ if setting_views:
5252
+ return False
5284
5253
  scrollpos_bot = self.canvasy(can_height)
5285
5254
  end_row = bisect_right(self.row_positions, scrollpos_bot)
5286
5255
  if not scrollpos_bot >= self.row_positions[-1]:
tksheet/row_index.py CHANGED
@@ -391,13 +391,15 @@ class RowIndex(tk.Canvas):
391
391
  )
392
392
  elif self.width_resizing_enabled and self.rsz_h is None and self.rsz_w is True:
393
393
  self.set_width_of_index_to_text()
394
- elif self.row_selection_enabled and self.rsz_h is None and self.rsz_w is None:
394
+ elif (self.row_selection_enabled or self.PAR.ops.treeview) and self.rsz_h is None and self.rsz_w is None:
395
395
  r = self.MT.identify_row(y=event.y)
396
396
  if r < len(self.MT.row_positions) - 1:
397
- if self.MT.single_selection_enabled:
398
- self.select_row(r, redraw=True)
399
- elif self.MT.toggle_selection_enabled:
400
- self.toggle_select_row(r, redraw=True)
397
+ iid = self.event_over_tree_arrow(r, self.canvasy(event.y), event.x)
398
+ if self.row_selection_enabled:
399
+ if self.MT.single_selection_enabled:
400
+ self.select_row(r, redraw=iid is None)
401
+ elif self.MT.toggle_selection_enabled:
402
+ self.toggle_select_row(r, redraw=iid is None)
401
403
  datarn = r if self.MT.all_rows_displayed else self.MT.displayed_rows[r]
402
404
  if (
403
405
  self.get_cell_kwargs(datarn, key="dropdown")
@@ -405,8 +407,8 @@ class RowIndex(tk.Canvas):
405
407
  or self.edit_cell_enabled
406
408
  ):
407
409
  self.open_cell(event)
408
- elif (iid := self.event_over_tree_arrow(r, self.canvasy(event.y), event.x)) is not None:
409
- self.PAR.item(iid, open_=iid not in self.tree_open_ids, redraw=False)
410
+ elif iid is not None:
411
+ self.PAR.item(iid, open_=iid not in self.tree_open_ids)
410
412
  self.rsz_h = None
411
413
  self.mouse_motion(event)
412
414
  try_binding(self.extra_double_b1_func, event)
@@ -870,7 +872,7 @@ class RowIndex(tk.Canvas):
870
872
  elif (iid := self.event_over_tree_arrow(r, canvasy, event.x)) is not None:
871
873
  if self.MT.selection_boxes:
872
874
  self.select_row(r, redraw=False)
873
- self.PAR.item(iid, open_=iid not in self.tree_open_ids, redraw=False)
875
+ self.PAR.item(iid, open_=iid not in self.tree_open_ids)
874
876
  else:
875
877
  self.mouseclick_outside_editor_or_dropdown_all_canvases(inside=True)
876
878
  self.b1_pressed_loc = None
@@ -1189,8 +1191,8 @@ class RowIndex(tk.Canvas):
1189
1191
  new_w = self.set_width_of_index_to_text(only_rows=only_rows, set_width=False)
1190
1192
  else:
1191
1193
  new_w = None
1192
- if new_w is not None and (sheet_w := floor(self.PAR.winfo_width() * 0.5)) < new_w:
1193
- new_w = sheet_w
1194
+ if new_w is not None and (sheet_w_x := floor(self.PAR.winfo_width() * 0.8)) < new_w:
1195
+ new_w = sheet_w_x
1194
1196
  if new_w and (self.current_width - new_w > 15 or new_w - self.current_width > 5):
1195
1197
  self.set_width(new_w, set_TL=True)
1196
1198
  return True
@@ -1392,9 +1394,19 @@ class RowIndex(tk.Canvas):
1392
1394
  t = self.create_polygon(points, fill=fill, outline=outline, tag=tag, smooth=True)
1393
1395
  self.disp_checkbox[t] = True
1394
1396
 
1397
+ def configure_scrollregion(self, last_row_line_pos: float) -> None:
1398
+ self.configure(
1399
+ scrollregion=(
1400
+ 0,
1401
+ 0,
1402
+ self.current_width,
1403
+ last_row_line_pos + self.PAR.ops.empty_vertical + 2,
1404
+ )
1405
+ )
1406
+
1395
1407
  def redraw_grid_and_text(
1396
1408
  self,
1397
- last_row_line_pos: int,
1409
+ last_row_line_pos: float,
1398
1410
  scrollpos_top: int,
1399
1411
  y_stop: int,
1400
1412
  start_row: int,
@@ -1403,14 +1415,7 @@ class RowIndex(tk.Canvas):
1403
1415
  row_pos_exists: bool,
1404
1416
  ) -> None:
1405
1417
  try:
1406
- self.configure(
1407
- scrollregion=(
1408
- 0,
1409
- 0,
1410
- self.current_width,
1411
- last_row_line_pos + self.PAR.ops.empty_vertical + 2,
1412
- )
1413
- )
1418
+ self.configure_scrollregion(last_row_line_pos=last_row_line_pos)
1414
1419
  except Exception:
1415
1420
  return
1416
1421
  self.hidd_text.update(self.disp_text)
tksheet/sheet.py CHANGED
@@ -46,6 +46,7 @@ from .other_classes import (
46
46
  GeneratedMouseEvent,
47
47
  Node,
48
48
  Selected,
49
+ SelectionBox,
49
50
  Span,
50
51
  )
51
52
  from .row_index import RowIndex
@@ -401,13 +402,13 @@ class Sheet(tk.Frame):
401
402
  self.set_scrollbar_options()
402
403
  self.yscroll = ttk.Scrollbar(
403
404
  self,
404
- command=self.MT.set_yviews,
405
+ command=self.MT._yscrollbar,
405
406
  orient="vertical",
406
407
  style=f"Sheet{self.unique_id}.Vertical.TScrollbar",
407
408
  )
408
409
  self.xscroll = ttk.Scrollbar(
409
410
  self,
410
- command=self.MT.set_xviews,
411
+ command=self.MT._xscrollbar,
411
412
  orient="horizontal",
412
413
  style=f"Sheet{self.unique_id}.Horizontal.TScrollbar",
413
414
  )
@@ -592,9 +593,12 @@ class Sheet(tk.Frame):
592
593
 
593
594
  def extra_bindings(
594
595
  self,
595
- bindings: str | list | tuple,
596
+ bindings: str | list | tuple | None = None,
596
597
  func: Callable | None = None,
597
598
  ) -> Sheet:
599
+ # bindings is None, unbind all
600
+ if bindings is None:
601
+ bindings = "all"
598
602
  # bindings is str, func arg is None or Callable
599
603
  if isinstance(bindings, str):
600
604
  iterable = [(bindings, func)]
@@ -1070,6 +1074,17 @@ class Sheet(tk.Frame):
1070
1074
  self.MT.redo(event)
1071
1075
  return self
1072
1076
 
1077
+ def has_focus(
1078
+ self,
1079
+ ) -> bool:
1080
+ """
1081
+ Check if any Sheet widgets have focus
1082
+ Includes child widgets such as scroll bars
1083
+ Returns bool
1084
+ """
1085
+ widget = self.focus_get()
1086
+ return widget == self or any(widget == c for c in self.children.values())
1087
+
1073
1088
  def focus_set(
1074
1089
  self,
1075
1090
  canvas: Literal[
@@ -1391,11 +1406,7 @@ class Sheet(tk.Frame):
1391
1406
  # retrieving a list of index cells or
1392
1407
  elif (index and not span.transposed and not table and not header) or (
1393
1408
  # it's a column that's spread across sublists
1394
- table
1395
- and res
1396
- and not span.transposed
1397
- and len(res[0]) == 1
1398
- and len(res[-1]) == 1
1409
+ table and res and not span.transposed and len(res[0]) == 1 and len(res[-1]) == 1
1399
1410
  ):
1400
1411
  res = list(chain.from_iterable(res))
1401
1412
  elif span.ndim == 1:
@@ -1927,6 +1938,7 @@ class Sheet(tk.Frame):
1927
1938
  undo: bool = False,
1928
1939
  emit_event: bool = False,
1929
1940
  create_selections: bool = True,
1941
+ add_column_widths: bool = True,
1930
1942
  redraw: bool = True,
1931
1943
  ) -> EventDataDict:
1932
1944
  total_cols = None
@@ -1985,6 +1997,7 @@ class Sheet(tk.Frame):
1985
1997
  heights=heights,
1986
1998
  row_index=row_index,
1987
1999
  ),
2000
+ add_col_positions=add_column_widths,
1988
2001
  event_data=event_dict(
1989
2002
  name="add_rows",
1990
2003
  sheet=self.name,
@@ -2010,6 +2023,7 @@ class Sheet(tk.Frame):
2010
2023
  undo: bool = False,
2011
2024
  emit_event: bool = False,
2012
2025
  create_selections: bool = True,
2026
+ add_row_heights: bool = True,
2013
2027
  redraw: bool = True,
2014
2028
  ) -> EventDataDict:
2015
2029
  old_total = self.MT.equalize_data_row_lengths()
@@ -2076,6 +2090,7 @@ class Sheet(tk.Frame):
2076
2090
  widths=widths,
2077
2091
  headers=headers,
2078
2092
  ),
2093
+ add_row_positions=add_row_heights,
2079
2094
  event_data=event_dict(
2080
2095
  name="add_columns",
2081
2096
  sheet=self.name,
@@ -2389,8 +2404,31 @@ class Sheet(tk.Frame):
2389
2404
  self.set_refresh_timer(redraw)
2390
2405
  return data_idxs, disp_idxs, event_data
2391
2406
 
2392
- def equalize_data_row_lengths(self, include_header: bool = False) -> int:
2393
- return self.MT.equalize_data_row_lengths(include_header=include_header)
2407
+ def equalize_data_row_lengths(
2408
+ self,
2409
+ include_header: bool = True,
2410
+ ) -> int:
2411
+ return self.MT.equalize_data_row_lengths(
2412
+ include_header=include_header,
2413
+ )
2414
+
2415
+ def full_move_rows_idxs(self, data_idxs: dict[int, int]) -> dict[int, int]:
2416
+ """
2417
+ Converts the dict provided by moving rows event data
2418
+ Under the keys ['moved']['rows']['data']
2419
+ Into a dict of {old index: new index} for every row
2420
+ Includes row numbers in cell options, spans, etc.
2421
+ """
2422
+ return self.MT.get_full_new_idxs(self.MT.get_max_row_idx(), data_idxs)
2423
+
2424
+ def full_move_columns_idxs(self, data_idxs: dict[int, int]) -> dict[int, int]:
2425
+ """
2426
+ Converts the dict provided by moving columns event data
2427
+ Under the keys ['moved']['columns']['data']
2428
+ Into a dict of {old index: new index} for every column
2429
+ Includes column numbers in cell options, spans, etc.
2430
+ """
2431
+ return self.MT.get_full_new_idxs(self.MT.get_max_column_idx(), data_idxs)
2394
2432
 
2395
2433
  # Highlighting Cells
2396
2434
 
@@ -2976,6 +3014,10 @@ class Sheet(tk.Frame):
2976
3014
  )
2977
3015
  return self
2978
3016
 
3017
+ @property
3018
+ def canvas_boxes(self) -> dict[int, SelectionBox]:
3019
+ return self.MT.selection_boxes
3020
+
2979
3021
  def cell_selected(
2980
3022
  self,
2981
3023
  r: int,
@@ -3008,8 +3050,17 @@ class Sheet(tk.Frame):
3008
3050
  def all_selected(self) -> bool:
3009
3051
  return self.MT.all_selected()
3010
3052
 
3011
- def get_ctrl_x_c_boxes(self) -> tuple[dict[tuple[int, int, int, int], str], int]:
3012
- return self.MT.get_ctrl_x_c_boxes()
3053
+ def get_ctrl_x_c_boxes(
3054
+ self,
3055
+ nrows: bool = True,
3056
+ ) -> tuple[dict[tuple[int, int, int, int], str], int] | dict[tuple[int, int, int, int], str]:
3057
+ if nrows:
3058
+ return self.MT.get_ctrl_x_c_boxes()
3059
+ return self.MT.get_ctrl_x_c_boxes()[0]
3060
+
3061
+ @property
3062
+ def ctrl_boxes(self) -> dict[tuple[int, int, int, int], str]:
3063
+ return self.MT.get_ctrl_x_c_boxes()[0]
3013
3064
 
3014
3065
  def get_selected_min_max(
3015
3066
  self,
@@ -4073,7 +4124,11 @@ class Sheet(tk.Frame):
4073
4124
  def set_options(self, redraw: bool = True, **kwargs) -> Sheet:
4074
4125
  for k, v in kwargs.items():
4075
4126
  if k in self.ops and v != self.ops[k]:
4127
+ if k.endswith("bindings"):
4128
+ self.MT._disable_binding(k.split("_")[0])
4076
4129
  self.ops[k] = v
4130
+ if k.endswith("bindings"):
4131
+ self.MT._enable_binding(k.split("_")[0])
4077
4132
  if "from_clipboard_delimiters" in kwargs:
4078
4133
  self.ops.from_clipboard_delimiters = (
4079
4134
  self.ops.from_clipboard_delimiters
@@ -4128,7 +4183,6 @@ class Sheet(tk.Frame):
4128
4183
  if any(k in kwargs for k in scrollbar_options_keys):
4129
4184
  self.set_scrollbar_options()
4130
4185
  self.MT.create_rc_menus()
4131
- self.MT.key_bindings()
4132
4186
  self.set_refresh_timer(redraw)
4133
4187
  return self
4134
4188
 
@@ -4436,7 +4490,9 @@ class Sheet(tk.Frame):
4436
4490
  x += 1
4437
4491
  tally_of_ids[iid] += 1
4438
4492
  row[iid_column] = new
4439
- if iid not in self.RI.tree:
4493
+ if iid in self.RI.tree:
4494
+ self.RI.tree[iid].text = row[text_column]
4495
+ else:
4440
4496
  self.RI.tree[iid] = Node(row[text_column], iid, "")
4441
4497
  if iid == pid or self.RI.pid_causes_recursive_loop(iid, pid):
4442
4498
  row[parent_column] = ""
@@ -4466,7 +4522,7 @@ class Sheet(tk.Frame):
4466
4522
  self.RI.tree_rns = {n.iid: i for i, n in enumerate(self.MT._row_index)}
4467
4523
  self.hide_rows(
4468
4524
  set(self.RI.tree_rns[iid] for iid in self.get_children() if self.RI.tree[iid].parent),
4469
- deselect_all=True,
4525
+ deselect_all=False,
4470
4526
  data_indexes=True,
4471
4527
  )
4472
4528
  return self
@@ -4487,7 +4543,6 @@ class Sheet(tk.Frame):
4487
4543
  Accepts set[str] of iids that are open in the treeview
4488
4544
  Closes everything else
4489
4545
  """
4490
- self.RI.tree_open_ids = open_ids if isinstance(open_ids, set) else set(open_ids)
4491
4546
  self.hide_rows(
4492
4547
  set(self.MT.displayed_rows),
4493
4548
  redraw=False,
@@ -4499,16 +4554,18 @@ class Sheet(tk.Frame):
4499
4554
  redraw=False,
4500
4555
  deselect_all=True,
4501
4556
  )
4557
+ open_ids = set(filter(self.exists, map(str.lower, open_ids)))
4558
+ self.RI.tree_open_ids = open_ids
4502
4559
  if open_ids:
4503
- self.tree_open(*open_ids)
4560
+ self.tree_open(open_ids)
4504
4561
  return self
4505
4562
 
4506
4563
  def tree_open(self, *items) -> Sheet:
4507
4564
  """
4508
4565
  If used without args all items are opened
4509
4566
  """
4510
- if items:
4511
- for item in unpack(items):
4567
+ if items := set(unpack(items)):
4568
+ for item in filter(items.__contains__, self.get_children()):
4512
4569
  self.item(item, open_=True)
4513
4570
  else:
4514
4571
  for item in self.get_children():
@@ -4553,9 +4610,6 @@ class Sheet(tk.Frame):
4553
4610
  text = iid
4554
4611
  parent_node = self.RI.tree[pid] if parent else ""
4555
4612
  self.RI.tree[iid] = Node(text, iid, parent_node)
4556
- if self.RI.pid_causes_recursive_loop(iid, pid):
4557
- del self.RI.tree[iid]
4558
- raise ValueError(f"iid '{iid}' causes a recursive loop with parent '{parent}'.")
4559
4613
  if parent_node:
4560
4614
  if isinstance(index, int):
4561
4615
  idx = self.RI.tree_rns[pid] + index + 1
@@ -4622,24 +4676,25 @@ class Sheet(tk.Frame):
4622
4676
  if self.RI.tree[item].children:
4623
4677
  if open_:
4624
4678
  self.RI.tree_open_ids.add(item)
4625
- self.show_rows(
4626
- (self.RI.tree_rns[did] for did in self.RI.get_iid_descendants(item, check_open=True)),
4627
- redraw=False,
4628
- deselect_all=False,
4629
- )
4679
+ if self.item_displayed(item):
4680
+ self.show_rows(
4681
+ rows=(self.RI.tree_rns[did] for did in self.RI.get_iid_descendants(item, check_open=True)),
4682
+ redraw=False,
4683
+ deselect_all=False,
4684
+ )
4630
4685
  else:
4631
4686
  self.RI.tree_open_ids.discard(item)
4632
- rows = {self.RI.tree_rns[did] for did in self.RI.get_iid_descendants(item, check_open=True)}
4633
- self.hide_rows(
4634
- rows,
4635
- redraw=False,
4636
- deselect_all=False,
4637
- data_indexes=True,
4638
- )
4687
+ if self.item_displayed(item):
4688
+ self.hide_rows(
4689
+ rows={self.RI.tree_rns[did] for did in self.RI.get_iid_descendants(item, check_open=True)},
4690
+ redraw=False,
4691
+ deselect_all=False,
4692
+ data_indexes=True,
4693
+ )
4639
4694
  else:
4640
4695
  self.RI.tree_open_ids.discard(item)
4641
4696
  get = not (isinstance(iid, str) or isinstance(text, str) or isinstance(values, list) or isinstance(open_, bool))
4642
- self.set_refresh_timer(redraw=not get or redraw)
4697
+ self.set_refresh_timer(redraw=not get and redraw)
4643
4698
  if get:
4644
4699
  return DotDict(
4645
4700
  text=self.RI.tree[item].text,
@@ -4793,7 +4848,7 @@ class Sheet(tk.Frame):
4793
4848
  reattach = move
4794
4849
 
4795
4850
  def exists(self, item: str) -> bool:
4796
- return item in self.RI.tree
4851
+ return item.lower() in self.RI.tree
4797
4852
 
4798
4853
  def parent(self, item: str) -> str:
4799
4854
  if (item := item.lower()) not in self.RI.tree:
@@ -5419,7 +5474,7 @@ class Sheet(tk.Frame):
5419
5474
  row: int = 0,
5420
5475
  column: int = 0,
5421
5476
  cells: list = [],
5422
- canvas: str = "table",
5477
+ canvas: Literal["table", "index", "header"] = "table",
5423
5478
  bg: bool | None | str = False,
5424
5479
  fg: bool | None | str = False,
5425
5480
  redraw: bool = True,
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: tksheet
3
- Version: 7.1.8
3
+ Version: 7.1.10
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=B-CIT1taBCzsRGcV4R7iv1vUtnLH5fwzUka5wQC2STQ,2014
2
+ tksheet/colors.py,sha256=1k06VorynLmnC4FdJg8H4reIA6rXaeXBpdMwXLhN8oc,51594
3
+ tksheet/column_headers.py,sha256=UEnaaqTUy4eNsJw7uGMnqjNoZWnuu5HCMVBDeHYk4lQ,100325
4
+ tksheet/formatters.py,sha256=DXif00aq9DgFpXwkbiqD86KxtDg0Meop51hLY-KcGNQ,10037
5
+ tksheet/functions.py,sha256=ytmHQtSa8cN6dKYLFra5G0393-4sU7bivvT_U4wxksI,39697
6
+ tksheet/main_table.py,sha256=NlEWXb5SEU89AkE0fdmULHW9FX6-GJ565lSxnCeVeDk,318311
7
+ tksheet/other_classes.py,sha256=P3FYUYreLhstATvHCNow8sDQoCsD_02KB6oXcca3ahE,13628
8
+ tksheet/row_index.py,sha256=BnQF-lxH50MfPWlXW94oYSEJXoPewoX29VS7j0X1Jwc,105895
9
+ tksheet/sheet.py,sha256=dvYtZpNJsu6WfjdUKt6RKcwKeDY5c7wZ-tQfL1rjglQ,259484
10
+ tksheet/sheet_options.py,sha256=mh0rTvWrFvIKaiv88jtMZy0TSA8zTS1GXSe88u8_rzk,11978
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=8Qxas-m5nU-yMaeAweO4Z30FM9cOQoRTiOsH4kgZp5s,2288
16
+ tksheet-7.1.10.dist-info/LICENSE.txt,sha256=ndbcCPe9SlHfweE_W2RAueWUe2k7yudyxYLq6WjFdn4,1101
17
+ tksheet-7.1.10.dist-info/METADATA,sha256=2xqqeNuI6pZOFMJ15XWePN15NBcLURYz0PLOvhleu3I,6014
18
+ tksheet-7.1.10.dist-info/WHEEL,sha256=GJ7t_kWBFywbagK5eo9IoUwLW6oyOeTKmQ-9iHFVNxQ,92
19
+ tksheet-7.1.10.dist-info/top_level.txt,sha256=my61PXCcck_HHAc9cq3NAlyAr3A3FXxCy9gptEOaCN8,8
20
+ tksheet-7.1.10.dist-info/RECORD,,
@@ -1,20 +0,0 @@
1
- tksheet/__init__.py,sha256=QkLl7gG86v_1GMYTSGmOr137dpoTBZE2IpCEgCB40d8,1994
2
- tksheet/colors.py,sha256=1k06VorynLmnC4FdJg8H4reIA6rXaeXBpdMwXLhN8oc,51594
3
- tksheet/column_headers.py,sha256=u5SRsI3VAoqxpUpPQZfu2Zimmf2OmZUBD_hMJKso-pw,100204
4
- tksheet/formatters.py,sha256=DXif00aq9DgFpXwkbiqD86KxtDg0Meop51hLY-KcGNQ,10037
5
- tksheet/functions.py,sha256=__21LS0cft9quuzFXcJ0BMbB0DEntvS4NQvreGk2U8Y,39709
6
- tksheet/main_table.py,sha256=zY5RNV2AyJ3jM8JPMmYrwCXGsnefnVVlXcjaqYxdxvg,318290
7
- tksheet/other_classes.py,sha256=P3FYUYreLhstATvHCNow8sDQoCsD_02KB6oXcca3ahE,13628
8
- tksheet/row_index.py,sha256=wfOPHitGfipTysCMfQA-Nl4mJawmkv9gm5CAtIlKgxo,105673
9
- tksheet/sheet.py,sha256=WvCuIszL31oJLhf0XJpvc0kHxa1yMAwEjiPrjeLkAQ8,257298
10
- tksheet/sheet_options.py,sha256=mh0rTvWrFvIKaiv88jtMZy0TSA8zTS1GXSe88u8_rzk,11978
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=8Qxas-m5nU-yMaeAweO4Z30FM9cOQoRTiOsH4kgZp5s,2288
16
- tksheet-7.1.8.dist-info/LICENSE.txt,sha256=ndbcCPe9SlHfweE_W2RAueWUe2k7yudyxYLq6WjFdn4,1101
17
- tksheet-7.1.8.dist-info/METADATA,sha256=eyi1aRtOSI35o-qYZpAJSZMyYjisRqRyZk_qg1JWx74,6013
18
- tksheet-7.1.8.dist-info/WHEEL,sha256=GJ7t_kWBFywbagK5eo9IoUwLW6oyOeTKmQ-9iHFVNxQ,92
19
- tksheet-7.1.8.dist-info/top_level.txt,sha256=my61PXCcck_HHAc9cq3NAlyAr3A3FXxCy9gptEOaCN8,8
20
- tksheet-7.1.8.dist-info/RECORD,,