tksheet 7.3.0__py3-none-any.whl → 7.3.2__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 +2 -2
- tksheet/column_headers.py +41 -40
- tksheet/find_window.py +251 -0
- tksheet/formatters.py +1 -1
- tksheet/functions.py +80 -50
- tksheet/main_table.py +531 -286
- tksheet/other_classes.py +6 -9
- tksheet/row_index.py +43 -40
- tksheet/sheet.py +165 -75
- tksheet/sheet_options.py +30 -1
- tksheet/text_editor.py +1 -1
- tksheet/top_left_rectangle.py +1 -1
- tksheet/types.py +8 -0
- {tksheet-7.3.0.dist-info → tksheet-7.3.2.dist-info}/METADATA +10 -11
- tksheet-7.3.2.dist-info/RECORD +21 -0
- {tksheet-7.3.0.dist-info → tksheet-7.3.2.dist-info}/WHEEL +1 -1
- tksheet-7.3.0.dist-info/RECORD +0 -20
- /tksheet/{vars.py → constants.py} +0 -0
- {tksheet-7.3.0.dist-info → tksheet-7.3.2.dist-info}/LICENSE.txt +0 -0
- {tksheet-7.3.0.dist-info → tksheet-7.3.2.dist-info}/top_level.txt +0 -0
tksheet/main_table.py
CHANGED
@@ -15,7 +15,6 @@ from collections.abc import (
|
|
15
15
|
Callable,
|
16
16
|
Generator,
|
17
17
|
Hashable,
|
18
|
-
Iterator,
|
19
18
|
Sequence,
|
20
19
|
)
|
21
20
|
from functools import (
|
@@ -40,6 +39,22 @@ from typing import Literal
|
|
40
39
|
from .colors import (
|
41
40
|
color_map,
|
42
41
|
)
|
42
|
+
from .constants import (
|
43
|
+
USER_OS,
|
44
|
+
bind_add_columns,
|
45
|
+
bind_add_rows,
|
46
|
+
bind_del_columns,
|
47
|
+
bind_del_rows,
|
48
|
+
ctrl_key,
|
49
|
+
rc_binding,
|
50
|
+
text_editor_close_bindings,
|
51
|
+
text_editor_newline_bindings,
|
52
|
+
text_editor_to_unbind,
|
53
|
+
val_modifying_options,
|
54
|
+
)
|
55
|
+
from .find_window import (
|
56
|
+
FindWindow,
|
57
|
+
)
|
43
58
|
from .formatters import (
|
44
59
|
data_to_str,
|
45
60
|
format_data,
|
@@ -51,6 +66,7 @@ from .formatters import (
|
|
51
66
|
from .functions import (
|
52
67
|
add_to_displayed,
|
53
68
|
b_index,
|
69
|
+
bisect_in,
|
54
70
|
box_is_single_cell,
|
55
71
|
cell_right_within_box,
|
56
72
|
color_tup,
|
@@ -59,6 +75,8 @@ from .functions import (
|
|
59
75
|
diff_list,
|
60
76
|
down_cell_within_box,
|
61
77
|
event_dict,
|
78
|
+
event_has_char_key,
|
79
|
+
event_opens_dropdown_or_checkbox,
|
62
80
|
float_to_int,
|
63
81
|
gen_formatted,
|
64
82
|
get_data_from_clipboard,
|
@@ -87,6 +105,7 @@ from .other_classes import (
|
|
87
105
|
Box_t,
|
88
106
|
DotDict,
|
89
107
|
DropdownStorage,
|
108
|
+
EditorStorageBase,
|
90
109
|
EventDataDict,
|
91
110
|
FontTuple,
|
92
111
|
Highlight,
|
@@ -99,19 +118,8 @@ from .other_classes import (
|
|
99
118
|
from .text_editor import (
|
100
119
|
TextEditor,
|
101
120
|
)
|
102
|
-
from .
|
103
|
-
|
104
|
-
bind_add_columns,
|
105
|
-
bind_add_rows,
|
106
|
-
bind_del_columns,
|
107
|
-
bind_del_rows,
|
108
|
-
ctrl_key,
|
109
|
-
rc_binding,
|
110
|
-
symbols_set,
|
111
|
-
text_editor_close_bindings,
|
112
|
-
text_editor_newline_bindings,
|
113
|
-
text_editor_to_unbind,
|
114
|
-
val_modifying_options,
|
121
|
+
from .types import (
|
122
|
+
AnyIter,
|
115
123
|
)
|
116
124
|
|
117
125
|
|
@@ -138,6 +146,7 @@ class MainTable(tk.Canvas):
|
|
138
146
|
self.synced_scrolls = set()
|
139
147
|
self.dropdown = DropdownStorage()
|
140
148
|
self.text_editor = TextEditorStorage()
|
149
|
+
self.find_window = EditorStorageBase()
|
141
150
|
self.event_linker = {
|
142
151
|
"<<Copy>>": self.ctrl_c,
|
143
152
|
"<<Cut>>": self.ctrl_x,
|
@@ -246,6 +255,7 @@ class MainTable(tk.Canvas):
|
|
246
255
|
self.drag_selection_enabled = False
|
247
256
|
self.select_all_enabled = False
|
248
257
|
self.undo_enabled = False
|
258
|
+
self.find_enabled = False
|
249
259
|
self.cut_enabled = False
|
250
260
|
self.copy_enabled = False
|
251
261
|
self.paste_enabled = False
|
@@ -405,7 +415,9 @@ class MainTable(tk.Canvas):
|
|
405
415
|
("<Control-MouseWheel>", self.ctrl_mousewheel),
|
406
416
|
("<Control-plus>", self.zoom_in),
|
407
417
|
("<Control-equal>", self.zoom_in),
|
418
|
+
("<Meta-Command-equal>", self.zoom_in),
|
408
419
|
("<Control-minus>", self.zoom_out),
|
420
|
+
("<Meta-Command-minus>", self.zoom_out),
|
409
421
|
)
|
410
422
|
mt_ri_canvas_linux_bindings = {
|
411
423
|
("<Button-4>", self.mousewheel),
|
@@ -472,6 +484,250 @@ class MainTable(tk.Canvas):
|
|
472
484
|
if delete_on_timer:
|
473
485
|
self.after(1500, self.delete_ctrl_outlines)
|
474
486
|
|
487
|
+
def escape(self, event: tk.Misc | None) -> None:
|
488
|
+
if self.find_window.open:
|
489
|
+
self.close_find_window()
|
490
|
+
else:
|
491
|
+
self.deselect()
|
492
|
+
|
493
|
+
def get_find_window_dimensions_coords(self, w_width: int) -> tuple[int, int, int, int]:
|
494
|
+
width = min(self.get_txt_w("X" * 23), w_width - 7)
|
495
|
+
# w, h, x, y
|
496
|
+
return width, self.min_row_height, self.canvasx(max(0, w_width - width - 7)), self.canvasy(7)
|
497
|
+
|
498
|
+
def open_find_window(
|
499
|
+
self,
|
500
|
+
event: tk.Misc | None = None,
|
501
|
+
focus: bool = True,
|
502
|
+
) -> Literal["break"]:
|
503
|
+
if self.find_window.open:
|
504
|
+
self.close_find_window()
|
505
|
+
return "break"
|
506
|
+
width, height, x, y = self.get_find_window_dimensions_coords(w_width=self.winfo_width())
|
507
|
+
if not self.find_window.window:
|
508
|
+
self.find_window.window = FindWindow(
|
509
|
+
self,
|
510
|
+
find_prev_func=self.find_previous,
|
511
|
+
find_next_func=self.find_next,
|
512
|
+
close_func=self.close_find_window,
|
513
|
+
)
|
514
|
+
self.find_window.canvas_id = self.create_window((x, y), window=self.find_window.window, anchor="nw")
|
515
|
+
for b in chain(self.PAR.ops.escape_bindings, self.PAR.ops.find_bindings):
|
516
|
+
self.find_window.tktext.bind(b, self.close_find_window)
|
517
|
+
for b in chain(self.PAR.ops.find_next_bindings, ("<Return>", "<KP_Enter>")):
|
518
|
+
self.find_window.tktext.bind(b, self.find_next)
|
519
|
+
for b in self.PAR.ops.find_previous_bindings:
|
520
|
+
self.find_window.tktext.bind(b, self.find_previous)
|
521
|
+
else:
|
522
|
+
self.coords(self.find_window.canvas_id, x, y)
|
523
|
+
if not self.find_window.open:
|
524
|
+
self.itemconfig(self.find_window.canvas_id, state="normal")
|
525
|
+
self.find_window.open = True
|
526
|
+
self.find_window.window.reset(
|
527
|
+
**{
|
528
|
+
"menu_kwargs": DotDict(
|
529
|
+
{
|
530
|
+
"font": self.PAR.ops.table_font,
|
531
|
+
"foreground": self.PAR.ops.popup_menu_fg,
|
532
|
+
"background": self.PAR.ops.popup_menu_bg,
|
533
|
+
"activebackground": self.PAR.ops.popup_menu_highlight_bg,
|
534
|
+
"activeforeground": self.PAR.ops.popup_menu_highlight_fg,
|
535
|
+
}
|
536
|
+
),
|
537
|
+
"sheet_ops": self.PAR.ops,
|
538
|
+
"border_color": self.PAR.ops.table_selected_box_cells_fg,
|
539
|
+
"bg": self.PAR.ops.table_editor_bg,
|
540
|
+
"fg": self.PAR.ops.table_editor_fg,
|
541
|
+
"select_bg": self.PAR.ops.table_editor_select_bg,
|
542
|
+
"select_fg": self.PAR.ops.table_editor_select_fg,
|
543
|
+
}
|
544
|
+
)
|
545
|
+
self.itemconfig(self.find_window.canvas_id, width=width, height=height)
|
546
|
+
if focus:
|
547
|
+
self.find_window.tktext.focus_set()
|
548
|
+
return "break"
|
549
|
+
|
550
|
+
def find_see_and_set(self, coords: tuple[int, int] | None, just_see: bool = False) -> tuple[int, int]:
|
551
|
+
if coords:
|
552
|
+
if not self.all_rows_displayed:
|
553
|
+
coords = (self.disprn(coords[0]), coords[1])
|
554
|
+
if not self.all_columns_displayed:
|
555
|
+
coords = (coords[0], self.dispcn(coords[1]))
|
556
|
+
if not just_see:
|
557
|
+
if self.find_window.window.find_in_selection:
|
558
|
+
self.set_currently_selected(*coords)
|
559
|
+
else:
|
560
|
+
self.select_cell(*coords, redraw=False)
|
561
|
+
if not self.see(
|
562
|
+
*coords,
|
563
|
+
keep_yscroll=False,
|
564
|
+
keep_xscroll=False,
|
565
|
+
bottom_right_corner=False,
|
566
|
+
check_cell_visibility=True,
|
567
|
+
redraw=True,
|
568
|
+
):
|
569
|
+
self.refresh()
|
570
|
+
return coords
|
571
|
+
|
572
|
+
def find_gen_all_cells(
|
573
|
+
self,
|
574
|
+
start_row: int,
|
575
|
+
start_col: int,
|
576
|
+
total_cols: int | None = None,
|
577
|
+
reverse: bool = False,
|
578
|
+
) -> Generator[tuple[int, int]]:
|
579
|
+
if total_cols is None:
|
580
|
+
total_cols = self.total_data_cols(include_header=False)
|
581
|
+
total_rows = self.total_data_rows(include_index=False)
|
582
|
+
if reverse:
|
583
|
+
# yield start cell
|
584
|
+
yield (start_row, start_col)
|
585
|
+
# yield any remaining cells in the starting row before the start column
|
586
|
+
if start_col:
|
587
|
+
for col in reversed(range(start_col)):
|
588
|
+
yield (start_row, col)
|
589
|
+
# yield any cells above start row
|
590
|
+
for row in reversed(range(start_row)):
|
591
|
+
for col in reversed(range(total_cols)):
|
592
|
+
yield (row, col)
|
593
|
+
# yield cells from bottom of table upward
|
594
|
+
for row in range(total_rows - 1, start_row, -1):
|
595
|
+
for col in reversed(range(total_cols)):
|
596
|
+
yield (row, col)
|
597
|
+
# yield any remaining cells in start row
|
598
|
+
for col in range(total_cols - 1, start_col, -1):
|
599
|
+
yield (start_row, col)
|
600
|
+
else:
|
601
|
+
# Yield cells from the start position to the end of the current row
|
602
|
+
for col in range(start_col, total_cols):
|
603
|
+
yield (start_row, col)
|
604
|
+
# yield from the next row to the last row
|
605
|
+
for row in range(start_row + 1, total_rows):
|
606
|
+
for col in range(total_cols):
|
607
|
+
yield (row, col)
|
608
|
+
# yield from the beginning up to the start
|
609
|
+
for row in range(start_row):
|
610
|
+
for col in range(total_cols):
|
611
|
+
yield (row, col)
|
612
|
+
# yield any remaining cells in the starting row before the start column
|
613
|
+
for col in range(start_col):
|
614
|
+
yield (start_row, col)
|
615
|
+
|
616
|
+
def find_get_start_coords(
|
617
|
+
self,
|
618
|
+
plus_one: bool = True,
|
619
|
+
within: None | list = None,
|
620
|
+
reverse: bool = False,
|
621
|
+
) -> tuple[int, int, int]:
|
622
|
+
selected = self.selected
|
623
|
+
if not selected:
|
624
|
+
return 0, 0, 0
|
625
|
+
max_row = len(self.row_positions) - 2
|
626
|
+
max_col = len(self.col_positions) - 2
|
627
|
+
row, col = selected.row, selected.column
|
628
|
+
if plus_one and within:
|
629
|
+
curridx = bisect_left(within, (row, col)) + (1 if not reverse else -1)
|
630
|
+
return row, col, curridx % len(within)
|
631
|
+
if plus_one:
|
632
|
+
if reverse:
|
633
|
+
if col == 0:
|
634
|
+
col = max_col
|
635
|
+
row = max_row if row == 0 else row - 1
|
636
|
+
else:
|
637
|
+
col -= 1
|
638
|
+
else:
|
639
|
+
col = (col + 1) % (max_col + 1)
|
640
|
+
if col == 0:
|
641
|
+
row = (row + 1) % (max_row + 1)
|
642
|
+
return row, col, 0
|
643
|
+
|
644
|
+
def find_match(self, find: str, r: int, c: int) -> bool:
|
645
|
+
return (
|
646
|
+
not find
|
647
|
+
and (not self.get_valid_cell_data_as_str(r, c, True).lower() or not f"{self.get_cell_data(r, c)}".lower())
|
648
|
+
) or (
|
649
|
+
find
|
650
|
+
and (
|
651
|
+
find in self.get_valid_cell_data_as_str(r, c, True).lower()
|
652
|
+
or find in f"{self.get_cell_data(r, c)}".lower()
|
653
|
+
)
|
654
|
+
)
|
655
|
+
|
656
|
+
def find_within_sels(
|
657
|
+
self,
|
658
|
+
find: str,
|
659
|
+
reverse: bool = False,
|
660
|
+
) -> tuple[int, int] | None:
|
661
|
+
sels = self.PAR.get_selected_cells(
|
662
|
+
get_rows=True,
|
663
|
+
get_columns=True,
|
664
|
+
sort_by_row=True,
|
665
|
+
sort_by_column=True,
|
666
|
+
)
|
667
|
+
_, _, from_idx = self.find_get_start_coords(plus_one=True, within=sels, reverse=reverse)
|
668
|
+
for r, c in chain(islice(sels, from_idx, None), islice(sels, 0, from_idx)):
|
669
|
+
if not self.all_rows_displayed:
|
670
|
+
r = self.datarn(r)
|
671
|
+
if not self.all_columns_displayed:
|
672
|
+
c = self.datacn(c)
|
673
|
+
if self.find_match(find, r, c):
|
674
|
+
return (r, c)
|
675
|
+
return None
|
676
|
+
|
677
|
+
def find_all_cells(
|
678
|
+
self,
|
679
|
+
find: str,
|
680
|
+
reverse: bool = False,
|
681
|
+
) -> tuple[int, int] | None:
|
682
|
+
row, col, _ = self.find_get_start_coords(plus_one=True, reverse=reverse)
|
683
|
+
row, col = self.datarn(row), self.datacn(col)
|
684
|
+
return next(
|
685
|
+
(
|
686
|
+
(r, c)
|
687
|
+
for r, c in self.find_gen_all_cells(
|
688
|
+
start_row=row,
|
689
|
+
start_col=col,
|
690
|
+
total_cols=self.total_data_cols(include_header=False),
|
691
|
+
reverse=reverse,
|
692
|
+
)
|
693
|
+
if (
|
694
|
+
(self.all_rows_displayed or bisect_in(self.displayed_rows, r))
|
695
|
+
and (self.all_columns_displayed or bisect_in(self.displayed_columns, c))
|
696
|
+
and self.find_match(find, r, c)
|
697
|
+
)
|
698
|
+
),
|
699
|
+
None,
|
700
|
+
)
|
701
|
+
|
702
|
+
def find_next(self, event: tk.Misc | None = None) -> Literal["break"]:
|
703
|
+
find = self.find_window.get().lower()
|
704
|
+
if not self.find_window.open:
|
705
|
+
self.open_find_window(focus=False)
|
706
|
+
if self.find_window.window.find_in_selection:
|
707
|
+
self.find_see_and_set(self.find_within_sels(find))
|
708
|
+
else:
|
709
|
+
self.find_see_and_set(self.find_all_cells(find))
|
710
|
+
return "break"
|
711
|
+
|
712
|
+
def find_previous(self, event: tk.Misc | None = None) -> Literal["break"]:
|
713
|
+
find = self.find_window.get().lower()
|
714
|
+
if not self.find_window.open:
|
715
|
+
self.open_find_window(focus=False)
|
716
|
+
if self.find_window.window.find_in_selection:
|
717
|
+
self.find_see_and_set(self.find_within_sels(find, reverse=True))
|
718
|
+
else:
|
719
|
+
self.find_see_and_set(self.find_all_cells(find, reverse=True))
|
720
|
+
return "break"
|
721
|
+
|
722
|
+
def close_find_window(
|
723
|
+
self,
|
724
|
+
event: tk.Misc | None = None,
|
725
|
+
) -> None:
|
726
|
+
if self.find_window.open:
|
727
|
+
self.itemconfig(self.find_window.canvas_id, state="hidden")
|
728
|
+
self.find_window.open = False
|
729
|
+
self.focus_set()
|
730
|
+
|
475
731
|
def create_ctrl_outline(
|
476
732
|
self,
|
477
733
|
x1: int,
|
@@ -523,19 +779,19 @@ class MainTable(tk.Canvas):
|
|
523
779
|
self.hidd_ctrl_outline[t] = False
|
524
780
|
|
525
781
|
def get_ctrl_x_c_boxes(self) -> tuple[dict[tuple[int, int, int, int], str], int]:
|
526
|
-
boxes = {}
|
527
782
|
maxrows = 0
|
528
783
|
if not self.selected:
|
529
|
-
return
|
784
|
+
return {}, maxrows
|
530
785
|
if self.selected.type_ in ("cells", "columns"):
|
531
786
|
curr_box = self.selection_boxes[self.selected.fill_iid].coords
|
532
787
|
maxrows = curr_box[2] - curr_box[0]
|
533
|
-
|
534
|
-
|
535
|
-
|
788
|
+
boxes = {
|
789
|
+
box.coords: box.type_
|
790
|
+
for _, box in self.get_selection_items(rows=False)
|
791
|
+
if maxrows >= box.coords[2] - box.coords[0]
|
792
|
+
}
|
536
793
|
else:
|
537
|
-
for
|
538
|
-
boxes[box.coords] = "rows"
|
794
|
+
boxes = {box.coords: "rows" for _, box in self.get_selection_items(columns=False, cells=False)}
|
539
795
|
return boxes, maxrows
|
540
796
|
|
541
797
|
def io_csv_writer(self) -> tuple[io.StringIO, csv.writer]:
|
@@ -1746,23 +2002,23 @@ class MainTable(tk.Canvas):
|
|
1746
2002
|
y = self.row_positions[r]
|
1747
2003
|
else:
|
1748
2004
|
y = self.row_positions[r + 1] + 1 - winfo_height
|
2005
|
+
y = y / (self.row_positions[-1] + self.PAR.ops.empty_vertical)
|
1749
2006
|
args = [
|
1750
2007
|
"moveto",
|
1751
|
-
y
|
2008
|
+
y - 1 if y > 1 else y,
|
1752
2009
|
]
|
1753
|
-
if args[1] > 1:
|
1754
|
-
args[1] = args[1] - 1
|
1755
2010
|
self.set_yviews(*args, redraw=False)
|
1756
2011
|
need_redraw = True
|
1757
2012
|
else:
|
1758
2013
|
if r is not None and not keep_yscroll:
|
1759
|
-
y = self.row_positions[r] + ((self.row_positions[r + 1] - self.row_positions[r]) * r_pc)
|
2014
|
+
y = int(self.row_positions[r] + ((self.row_positions[r + 1] - self.row_positions[r]) * r_pc)) - 2
|
2015
|
+
if y < 0:
|
2016
|
+
y = 0
|
2017
|
+
y = y / (self.row_positions[-1] + self.PAR.ops.empty_vertical)
|
1760
2018
|
args = [
|
1761
2019
|
"moveto",
|
1762
|
-
y
|
2020
|
+
y - 1 if y > 1 else y,
|
1763
2021
|
]
|
1764
|
-
if args[1] > 1:
|
1765
|
-
args[1] = args[1] - 1
|
1766
2022
|
self.set_yviews(*args, redraw=False)
|
1767
2023
|
need_redraw = True
|
1768
2024
|
if not xvis and len(self.col_positions) > 1:
|
@@ -1773,18 +2029,22 @@ class MainTable(tk.Canvas):
|
|
1773
2029
|
x = self.col_positions[c]
|
1774
2030
|
else:
|
1775
2031
|
x = self.col_positions[c + 1] + 1 - winfo_width
|
2032
|
+
x = x / (self.col_positions[-1] + self.PAR.ops.empty_horizontal)
|
1776
2033
|
args = [
|
1777
2034
|
"moveto",
|
1778
|
-
x
|
2035
|
+
x - 1 if x > 1 else x,
|
1779
2036
|
]
|
1780
2037
|
self.set_xviews(*args, redraw=False)
|
1781
2038
|
need_redraw = True
|
1782
2039
|
else:
|
1783
2040
|
if c is not None and not keep_xscroll:
|
1784
|
-
x = self.col_positions[c] + ((self.col_positions[c + 1] - self.col_positions[c]) * c_pc)
|
2041
|
+
x = int(self.col_positions[c] + ((self.col_positions[c + 1] - self.col_positions[c]) * c_pc)) - 2
|
2042
|
+
if x < 0:
|
2043
|
+
x = 0
|
2044
|
+
x = x / (self.col_positions[-1] + self.PAR.ops.empty_horizontal)
|
1785
2045
|
args = [
|
1786
2046
|
"moveto",
|
1787
|
-
x
|
2047
|
+
x - 1 if x > 1 else x,
|
1788
2048
|
]
|
1789
2049
|
self.set_xviews(*args, redraw=False)
|
1790
2050
|
need_redraw = True
|
@@ -1806,20 +2066,12 @@ class MainTable(tk.Canvas):
|
|
1806
2066
|
r: int | None = 0,
|
1807
2067
|
c: int | None = 0,
|
1808
2068
|
separate_axes: bool = False,
|
1809
|
-
) -> bool:
|
2069
|
+
) -> bool | tuple[bool, bool]:
|
1810
2070
|
cx1, cy1, cx2, cy2 = self.get_canvas_visible_area()
|
1811
2071
|
x1, y1, x2, y2 = self.get_cell_coords(r, c)
|
1812
|
-
x_vis =
|
1813
|
-
y_vis =
|
1814
|
-
|
1815
|
-
x_vis = False
|
1816
|
-
if cy1 > y1 or cy2 < y2:
|
1817
|
-
y_vis = False
|
1818
|
-
if separate_axes:
|
1819
|
-
return y_vis, x_vis
|
1820
|
-
if not y_vis or not x_vis:
|
1821
|
-
return False
|
1822
|
-
return True
|
2072
|
+
x_vis = cx1 <= x1 and cx2 >= x2
|
2073
|
+
y_vis = cy1 <= y1 and cy2 >= y2
|
2074
|
+
return (y_vis, x_vis) if separate_axes else y_vis and x_vis
|
1823
2075
|
|
1824
2076
|
def cell_visible(self, r: int = 0, c: int = 0) -> bool:
|
1825
2077
|
cx1, cy1, cx2, cy2 = self.get_canvas_visible_area()
|
@@ -1844,14 +2096,43 @@ class MainTable(tk.Canvas):
|
|
1844
2096
|
if redraw:
|
1845
2097
|
self.main_table_redraw_grid_and_text(redraw_header=True, redraw_row_index=True)
|
1846
2098
|
if run_binding_func:
|
1847
|
-
if self.select_all_binding_func:
|
1848
|
-
self.select_all_binding_func(
|
1849
|
-
self.get_select_event(being_drawn_item=self.being_drawn_item),
|
1850
|
-
)
|
1851
2099
|
event_data = self.get_select_event(self.being_drawn_item)
|
2100
|
+
try_binding(self.select_all_binding_func, event_data)
|
1852
2101
|
self.PAR.emit_event("<<SheetSelect>>", data=event_data)
|
1853
2102
|
self.PAR.emit_event("<<SelectAll>>", data=event_data)
|
1854
2103
|
|
2104
|
+
def select_columns(self, event: object) -> None:
|
2105
|
+
if not self.selected:
|
2106
|
+
return
|
2107
|
+
r1, c1, r2, c2 = self.selection_boxes[self.selected.fill_iid].coords
|
2108
|
+
r, c = self.selected.row, self.selected.column
|
2109
|
+
self.set_currently_selected(
|
2110
|
+
r=r,
|
2111
|
+
c=c,
|
2112
|
+
item=self.CH.select_col(range(c1, c2), redraw=True),
|
2113
|
+
)
|
2114
|
+
|
2115
|
+
def select_rows(self, event: object) -> None:
|
2116
|
+
if not self.selected:
|
2117
|
+
return
|
2118
|
+
r1, c1, r2, c2 = self.selection_boxes[self.selected.fill_iid].coords
|
2119
|
+
r, c = self.selected.row, self.selected.column
|
2120
|
+
self.set_currently_selected(
|
2121
|
+
r=r,
|
2122
|
+
c=c,
|
2123
|
+
item=self.RI.select_row(range(r1, r2), redraw=True),
|
2124
|
+
)
|
2125
|
+
|
2126
|
+
def select_row_start(self, event: object) -> None:
|
2127
|
+
if self.selected:
|
2128
|
+
self.see(self.selected.row, 0)
|
2129
|
+
self.select_cell(self.selected.row, 0, redraw=True)
|
2130
|
+
|
2131
|
+
def select_a1(self, event: object) -> None:
|
2132
|
+
if len(self.row_positions) > 1 and len(self.col_positions) > 1:
|
2133
|
+
self.see(0, 0)
|
2134
|
+
self.select_cell(0, 0, redraw=True)
|
2135
|
+
|
1855
2136
|
def select_cell(
|
1856
2137
|
self,
|
1857
2138
|
r: int,
|
@@ -1934,7 +2215,9 @@ class MainTable(tk.Canvas):
|
|
1934
2215
|
) -> None:
|
1935
2216
|
if not self.selected:
|
1936
2217
|
return
|
2218
|
+
curr_box = self.selected.fill_iid
|
1937
2219
|
if r == "all" or (r is None and c is None and cell is None):
|
2220
|
+
self.hide_dropdown_editor_all_canvases()
|
1938
2221
|
for item, box in self.get_selection_items():
|
1939
2222
|
self.hide_selection_box(item)
|
1940
2223
|
elif r in ("allrows", "allcols"):
|
@@ -1944,6 +2227,8 @@ class MainTable(tk.Canvas):
|
|
1944
2227
|
cells=False,
|
1945
2228
|
):
|
1946
2229
|
self.hide_selection_box(item)
|
2230
|
+
if item == curr_box:
|
2231
|
+
self.hide_dropdown_editor_all_canvases()
|
1947
2232
|
elif isinstance(r, int) and c is None and cell is None:
|
1948
2233
|
for item, box in self.get_selection_items(columns=False, cells=False):
|
1949
2234
|
r1, c1, r2, c2 = box.coords
|
@@ -1951,6 +2236,8 @@ class MainTable(tk.Canvas):
|
|
1951
2236
|
resel = self.selected.fill_iid == item
|
1952
2237
|
to_sel = self.selected.row
|
1953
2238
|
self.hide_selection_box(item)
|
2239
|
+
if item == curr_box:
|
2240
|
+
self.hide_dropdown_editor_all_canvases()
|
1954
2241
|
if r2 - r1 != 1:
|
1955
2242
|
if r == r1:
|
1956
2243
|
self.create_selection_box(
|
@@ -1994,6 +2281,8 @@ class MainTable(tk.Canvas):
|
|
1994
2281
|
resel = self.selected.fill_iid == item
|
1995
2282
|
to_sel = self.selected.column
|
1996
2283
|
self.hide_selection_box(item)
|
2284
|
+
if item == curr_box:
|
2285
|
+
self.hide_dropdown_editor_all_canvases()
|
1997
2286
|
if c2 - c1 != 1:
|
1998
2287
|
if c == c1:
|
1999
2288
|
self.create_selection_box(
|
@@ -2037,6 +2326,8 @@ class MainTable(tk.Canvas):
|
|
2037
2326
|
r1, c1, r2, c2 = box.coords
|
2038
2327
|
if r >= r1 and c >= c1 and r < r2 and c < c2:
|
2039
2328
|
self.hide_selection_box(item)
|
2329
|
+
if item == curr_box:
|
2330
|
+
self.hide_text_editor_and_dropdown(redraw=False)
|
2040
2331
|
if redraw:
|
2041
2332
|
self.main_table_redraw_grid_and_text(redraw_header=True, redraw_row_index=True)
|
2042
2333
|
sel_event = self.get_select_event(being_drawn_item=self.being_drawn_item)
|
@@ -2046,12 +2337,15 @@ class MainTable(tk.Canvas):
|
|
2046
2337
|
|
2047
2338
|
def deselect_any(
|
2048
2339
|
self,
|
2049
|
-
rows:
|
2050
|
-
columns:
|
2340
|
+
rows: AnyIter[int] | int | None = None,
|
2341
|
+
columns: AnyIter[int] | int | None = None,
|
2051
2342
|
redraw: bool = True,
|
2052
2343
|
) -> None:
|
2344
|
+
if not self.selected:
|
2345
|
+
return
|
2053
2346
|
rows = int_x_iter(rows)
|
2054
2347
|
columns = int_x_iter(columns)
|
2348
|
+
curr_box = self.selected.fill_iid
|
2055
2349
|
if is_iterable(rows) and is_iterable(columns):
|
2056
2350
|
rows = tuple(consecutive_ranges(sorted(rows)))
|
2057
2351
|
columns = tuple(consecutive_ranges(sorted(columns)))
|
@@ -2066,6 +2360,8 @@ class MainTable(tk.Canvas):
|
|
2066
2360
|
(cols_end >= c1 and cols_end <= c2) or (cols_st >= c1 and cols_st < c2)
|
2067
2361
|
):
|
2068
2362
|
hidden = self.hide_selection_box(item)
|
2363
|
+
if item == curr_box:
|
2364
|
+
self.hide_dropdown_editor_all_canvases()
|
2069
2365
|
break
|
2070
2366
|
elif is_iterable(rows):
|
2071
2367
|
rows = tuple(consecutive_ranges(sorted(rows)))
|
@@ -2074,6 +2370,8 @@ class MainTable(tk.Canvas):
|
|
2074
2370
|
for rows_st, rows_end in rows:
|
2075
2371
|
if (rows_end >= r1 and rows_end <= r2) or (rows_st >= r1 and rows_st < r2):
|
2076
2372
|
self.hide_selection_box(item)
|
2373
|
+
if item == curr_box:
|
2374
|
+
self.hide_dropdown_editor_all_canvases()
|
2077
2375
|
break
|
2078
2376
|
elif is_iterable(columns):
|
2079
2377
|
columns = tuple(consecutive_ranges(sorted(columns)))
|
@@ -2082,6 +2380,8 @@ class MainTable(tk.Canvas):
|
|
2082
2380
|
for cols_st, cols_end in columns:
|
2083
2381
|
if (cols_end >= c1 and cols_end <= c2) or (cols_st >= c1 and cols_st < c2):
|
2084
2382
|
self.hide_selection_box(item)
|
2383
|
+
if item == curr_box:
|
2384
|
+
self.hide_dropdown_editor_all_canvases()
|
2085
2385
|
break
|
2086
2386
|
else:
|
2087
2387
|
self.deselect()
|
@@ -2161,9 +2461,8 @@ class MainTable(tk.Canvas):
|
|
2161
2461
|
elif self.selected.type_ in ("cells", "columns"):
|
2162
2462
|
r = self.selected.row
|
2163
2463
|
c = self.selected.column
|
2164
|
-
if not r and self.CH.col_selection_enabled:
|
2165
|
-
|
2166
|
-
self.see(r, c, check_cell_visibility=False)
|
2464
|
+
if not r and self.CH.col_selection_enabled and not self.cell_completely_visible(r=r, c=c):
|
2465
|
+
self.see(r, c, check_cell_visibility=False)
|
2167
2466
|
elif r and (self.single_selection_enabled or self.toggle_selection_enabled):
|
2168
2467
|
if self.cell_completely_visible(r=r - 1, c=c):
|
2169
2468
|
self.select_cell(r - 1, c, redraw=True)
|
@@ -2177,32 +2476,18 @@ class MainTable(tk.Canvas):
|
|
2177
2476
|
if self.selected.type_ == "rows":
|
2178
2477
|
r = self.selected.row
|
2179
2478
|
if r < len(self.row_positions) - 2 and self.RI.row_selection_enabled:
|
2180
|
-
if self.cell_completely_visible(r=
|
2479
|
+
if self.cell_completely_visible(r=r + 1, c=0):
|
2181
2480
|
self.RI.select_row(r + 1, redraw=True)
|
2182
2481
|
else:
|
2183
2482
|
self.RI.select_row(r + 1)
|
2184
|
-
|
2185
|
-
r +
|
2186
|
-
|
2187
|
-
|
2188
|
-
|
2189
|
-
|
2190
|
-
)
|
2191
|
-
|
2192
|
-
r + 2,
|
2193
|
-
0,
|
2194
|
-
keep_xscroll=True,
|
2195
|
-
bottom_right_corner=True,
|
2196
|
-
check_cell_visibility=False,
|
2197
|
-
)
|
2198
|
-
elif not self.cell_completely_visible(r=r + 1, c=0):
|
2199
|
-
self.see(
|
2200
|
-
r + 1,
|
2201
|
-
0,
|
2202
|
-
keep_xscroll=True,
|
2203
|
-
bottom_right_corner=False if self.PAR.ops.arrow_key_down_right_scroll_page else True,
|
2204
|
-
check_cell_visibility=False,
|
2205
|
-
)
|
2483
|
+
self.see(
|
2484
|
+
r + 1,
|
2485
|
+
0,
|
2486
|
+
keep_xscroll=True,
|
2487
|
+
bottom_right_corner=False if self.PAR.ops.arrow_key_down_right_scroll_page else True,
|
2488
|
+
check_cell_visibility=False,
|
2489
|
+
)
|
2490
|
+
|
2206
2491
|
elif self.selected.type_ == "columns":
|
2207
2492
|
c = self.selected.column
|
2208
2493
|
if self.single_selection_enabled or self.toggle_selection_enabled:
|
@@ -2223,32 +2508,17 @@ class MainTable(tk.Canvas):
|
|
2223
2508
|
r = self.selected.row
|
2224
2509
|
c = self.selected.column
|
2225
2510
|
if r < len(self.row_positions) - 2 and (self.single_selection_enabled or self.toggle_selection_enabled):
|
2226
|
-
if self.cell_completely_visible(r=
|
2511
|
+
if self.cell_completely_visible(r=r + 1, c=c):
|
2227
2512
|
self.select_cell(r + 1, c, redraw=True)
|
2228
2513
|
else:
|
2229
2514
|
self.select_cell(r + 1, c)
|
2230
|
-
|
2231
|
-
r +
|
2232
|
-
|
2233
|
-
|
2234
|
-
|
2235
|
-
|
2236
|
-
)
|
2237
|
-
self.see(
|
2238
|
-
r + 2,
|
2239
|
-
c,
|
2240
|
-
keep_xscroll=True,
|
2241
|
-
bottom_right_corner=True,
|
2242
|
-
check_cell_visibility=False,
|
2243
|
-
)
|
2244
|
-
elif not self.cell_completely_visible(r=r + 1, c=c):
|
2245
|
-
self.see(
|
2246
|
-
r + 1,
|
2247
|
-
c,
|
2248
|
-
keep_xscroll=True,
|
2249
|
-
bottom_right_corner=False if self.PAR.ops.arrow_key_down_right_scroll_page else True,
|
2250
|
-
check_cell_visibility=False,
|
2251
|
-
)
|
2515
|
+
self.see(
|
2516
|
+
r + 1,
|
2517
|
+
c,
|
2518
|
+
keep_xscroll=True,
|
2519
|
+
bottom_right_corner=False if self.PAR.ops.arrow_key_down_right_scroll_page else True,
|
2520
|
+
check_cell_visibility=False,
|
2521
|
+
)
|
2252
2522
|
|
2253
2523
|
def arrowkey_LEFT(self, event: object = None) -> None:
|
2254
2524
|
if not self.selected:
|
@@ -2273,7 +2543,7 @@ class MainTable(tk.Canvas):
|
|
2273
2543
|
elif self.selected.type_ == "cells":
|
2274
2544
|
r = self.selected.row
|
2275
2545
|
c = self.selected.column
|
2276
|
-
if not c and not self.cell_completely_visible(r=r, c=
|
2546
|
+
if not c and not self.cell_completely_visible(r=r, c=c):
|
2277
2547
|
self.see(r, c, keep_yscroll=True, check_cell_visibility=False)
|
2278
2548
|
elif c and (self.single_selection_enabled or self.toggle_selection_enabled):
|
2279
2549
|
if self.cell_completely_visible(r=r, c=c - 1):
|
@@ -2658,7 +2928,7 @@ class MainTable(tk.Canvas):
|
|
2658
2928
|
**mnkwgs,
|
2659
2929
|
)
|
2660
2930
|
|
2661
|
-
def enable_bindings(self, bindings):
|
2931
|
+
def enable_bindings(self, bindings: object) -> None:
|
2662
2932
|
if not bindings:
|
2663
2933
|
self._enable_binding("all")
|
2664
2934
|
elif isinstance(bindings, (list, tuple)):
|
@@ -2672,7 +2942,7 @@ class MainTable(tk.Canvas):
|
|
2672
2942
|
self._enable_binding(bindings.lower())
|
2673
2943
|
self.create_rc_menus()
|
2674
2944
|
|
2675
|
-
def disable_bindings(self, bindings):
|
2945
|
+
def disable_bindings(self, bindings: object) -> None:
|
2676
2946
|
if not bindings:
|
2677
2947
|
self._disable_binding("all")
|
2678
2948
|
elif isinstance(bindings, (list, tuple)):
|
@@ -2686,21 +2956,34 @@ class MainTable(tk.Canvas):
|
|
2686
2956
|
self._disable_binding(bindings)
|
2687
2957
|
self.create_rc_menus()
|
2688
2958
|
|
2689
|
-
def _enable_binding(self, binding):
|
2959
|
+
def _enable_binding(self, binding: str) -> None:
|
2690
2960
|
if binding == "enable_all":
|
2691
2961
|
binding = "all"
|
2692
|
-
if binding in (
|
2693
|
-
|
2694
|
-
|
2695
|
-
|
2696
|
-
|
2697
|
-
|
2962
|
+
if binding in (
|
2963
|
+
"all",
|
2964
|
+
"single",
|
2965
|
+
"single_selection_mode",
|
2966
|
+
"single_select",
|
2967
|
+
"toggle",
|
2968
|
+
"toggle_selection_mode",
|
2969
|
+
"toggle_select",
|
2970
|
+
):
|
2971
|
+
self._tksheet_bind("row_start_bindings", self.select_row_start)
|
2972
|
+
self._tksheet_bind("table_start_bindings", self.select_a1)
|
2973
|
+
self._tksheet_bind("escape_bindings", self.escape)
|
2974
|
+
if binding in ("all", "single", "single_selection_mode", "single_select"):
|
2975
|
+
self.single_selection_enabled = True
|
2976
|
+
self.toggle_selection_enabled = False
|
2977
|
+
elif binding in ("toggle", "toggle_selection_mode", "toggle_select"):
|
2978
|
+
self.toggle_selection_enabled = True
|
2979
|
+
self.single_selection_enabled = False
|
2698
2980
|
if binding in ("all", "drag_select"):
|
2699
2981
|
self.drag_selection_enabled = True
|
2700
2982
|
if binding in ("all", "column_width_resize"):
|
2701
2983
|
self.CH.width_resizing_enabled = True
|
2702
2984
|
if binding in ("all", "column_select"):
|
2703
2985
|
self.CH.col_selection_enabled = True
|
2986
|
+
self._tksheet_bind("select_columns_bindings", self.select_columns)
|
2704
2987
|
if binding in ("all", "column_height_resize"):
|
2705
2988
|
self.CH.height_resizing_enabled = True
|
2706
2989
|
self.TL.rh_state()
|
@@ -2717,6 +3000,7 @@ class MainTable(tk.Canvas):
|
|
2717
3000
|
self.TL.rw_state()
|
2718
3001
|
if binding in ("all", "row_select"):
|
2719
3002
|
self.RI.row_selection_enabled = True
|
3003
|
+
self._tksheet_bind("select_rows_bindings", self.select_rows)
|
2720
3004
|
if binding in ("all", "row_drag_and_drop", "move_rows"):
|
2721
3005
|
self.RI.drag_and_drop_enabled = True
|
2722
3006
|
if binding in ("all", "select_all"):
|
@@ -2764,6 +3048,11 @@ class MainTable(tk.Canvas):
|
|
2764
3048
|
self.undo_enabled = True
|
2765
3049
|
self._tksheet_bind("undo_bindings", self.undo)
|
2766
3050
|
self._tksheet_bind("redo_bindings", self.redo)
|
3051
|
+
if binding in ("find",):
|
3052
|
+
self.find_enabled = True
|
3053
|
+
self._tksheet_bind("find_bindings", self.open_find_window)
|
3054
|
+
self._tksheet_bind("find_next_bindings", self.find_next)
|
3055
|
+
self._tksheet_bind("find_previous_bindings", self.find_previous)
|
2767
3056
|
if binding in bind_del_columns:
|
2768
3057
|
self.rc_delete_column_enabled = True
|
2769
3058
|
self.rc_popup_menus_enabled = True
|
@@ -2802,21 +3091,30 @@ class MainTable(tk.Canvas):
|
|
2802
3091
|
for binding in self.PAR.ops[bindings_key]:
|
2803
3092
|
widget.bind(binding, func)
|
2804
3093
|
|
2805
|
-
def _disable_binding(self, binding):
|
3094
|
+
def _disable_binding(self, binding: str) -> None:
|
2806
3095
|
if binding == "disable_all":
|
2807
3096
|
binding = "all"
|
2808
|
-
if binding in (
|
3097
|
+
if binding in (
|
3098
|
+
"all",
|
3099
|
+
"single",
|
3100
|
+
"single_selection_mode",
|
3101
|
+
"single_select",
|
3102
|
+
"toggle",
|
3103
|
+
"toggle_selection_mode",
|
3104
|
+
"toggle_select",
|
3105
|
+
):
|
3106
|
+
self._tksheet_unbind("row_start_bindings")
|
3107
|
+
self._tksheet_unbind("table_start_bindings")
|
3108
|
+
self._tksheet_unbind("escape_bindings")
|
2809
3109
|
self.single_selection_enabled = False
|
2810
3110
|
self.toggle_selection_enabled = False
|
2811
|
-
elif binding in ("toggle", "toggle_selection_mode", "toggle_select"):
|
2812
|
-
self.toggle_selection_enabled = False
|
2813
|
-
self.single_selection_enabled = False
|
2814
3111
|
if binding in ("all", "drag_select"):
|
2815
3112
|
self.drag_selection_enabled = False
|
2816
3113
|
if binding in ("all", "column_width_resize"):
|
2817
3114
|
self.CH.width_resizing_enabled = False
|
2818
3115
|
if binding in ("all", "column_select"):
|
2819
3116
|
self.CH.col_selection_enabled = False
|
3117
|
+
self._tksheet_unbind("select_columns_bindings")
|
2820
3118
|
if binding in ("all", "column_height_resize"):
|
2821
3119
|
self.CH.height_resizing_enabled = False
|
2822
3120
|
self.TL.rh_state("hidden")
|
@@ -2833,6 +3131,7 @@ class MainTable(tk.Canvas):
|
|
2833
3131
|
self.TL.rw_state("hidden")
|
2834
3132
|
if binding in ("all", "row_select"):
|
2835
3133
|
self.RI.row_selection_enabled = False
|
3134
|
+
self._tksheet_unbind("select_rows_bindings")
|
2836
3135
|
if binding in ("all", "row_drag_and_drop", "move_rows"):
|
2837
3136
|
self.RI.drag_and_drop_enabled = False
|
2838
3137
|
if binding in bind_del_columns:
|
@@ -2897,6 +3196,12 @@ class MainTable(tk.Canvas):
|
|
2897
3196
|
if binding in ("all", "undo", "redo", "edit_bindings", "edit"):
|
2898
3197
|
self.undo_enabled = False
|
2899
3198
|
self._tksheet_unbind("undo_bindings", "redo_bindings")
|
3199
|
+
if binding in ("all", "find"):
|
3200
|
+
self.find_enabled = False
|
3201
|
+
self._tksheet_unbind("find_bindings")
|
3202
|
+
self._tksheet_unbind("find_next_bindings")
|
3203
|
+
self._tksheet_unbind("find_previous_bindings")
|
3204
|
+
self.close_find_window()
|
2900
3205
|
|
2901
3206
|
def _tksheet_unbind(self, *keys) -> None:
|
2902
3207
|
for widget in (self, self.RI, self.CH, self.TL):
|
@@ -3383,26 +3688,42 @@ class MainTable(tk.Canvas):
|
|
3383
3688
|
if move_synced:
|
3384
3689
|
self.y_move_synced_scrolls(*args, use_scrollbar=True)
|
3385
3690
|
|
3386
|
-
def set_xviews(
|
3691
|
+
def set_xviews(
|
3692
|
+
self,
|
3693
|
+
*args,
|
3694
|
+
move_synced: bool = True,
|
3695
|
+
redraw: bool = True,
|
3696
|
+
) -> None:
|
3387
3697
|
self.main_table_redraw_grid_and_text(setting_views=True)
|
3388
|
-
self.
|
3698
|
+
if not self.PAR._startup_complete:
|
3699
|
+
self.update_idletasks()
|
3389
3700
|
self.xview(*args)
|
3390
3701
|
if self.show_header:
|
3391
|
-
self.
|
3702
|
+
if not self.PAR._startup_complete:
|
3703
|
+
self.CH.update_idletasks()
|
3392
3704
|
self.CH.xview(*args)
|
3393
|
-
|
3705
|
+
if redraw:
|
3706
|
+
self.main_table_redraw_grid_and_text(redraw_header=True, redraw_row_index=False)
|
3394
3707
|
if move_synced:
|
3395
3708
|
self.x_move_synced_scrolls(*args)
|
3396
3709
|
self.fix_views()
|
3397
3710
|
|
3398
|
-
def set_yviews(
|
3711
|
+
def set_yviews(
|
3712
|
+
self,
|
3713
|
+
*args,
|
3714
|
+
move_synced: bool = True,
|
3715
|
+
redraw: bool = True,
|
3716
|
+
) -> None:
|
3399
3717
|
self.main_table_redraw_grid_and_text(setting_views=True)
|
3400
|
-
self.
|
3718
|
+
if not self.PAR._startup_complete:
|
3719
|
+
self.update_idletasks()
|
3401
3720
|
self.yview(*args)
|
3402
3721
|
if self.show_index:
|
3403
|
-
self.
|
3722
|
+
if not self.PAR._startup_complete:
|
3723
|
+
self.RI.update_idletasks()
|
3404
3724
|
self.RI.yview(*args)
|
3405
|
-
|
3725
|
+
if redraw:
|
3726
|
+
self.main_table_redraw_grid_and_text(redraw_header=False, redraw_row_index=True)
|
3406
3727
|
if move_synced:
|
3407
3728
|
self.y_move_synced_scrolls(*args)
|
3408
3729
|
self.fix_views()
|
@@ -3544,7 +3865,7 @@ class MainTable(tk.Canvas):
|
|
3544
3865
|
b = self.txt_measure_canvas.bbox(self.txt_measure_canvas_text)
|
3545
3866
|
return b[3] - b[1]
|
3546
3867
|
|
3547
|
-
def get_txt_dimensions(self, txt: str, font: None | FontTuple = None) -> int:
|
3868
|
+
def get_txt_dimensions(self, txt: str, font: None | FontTuple = None) -> tuple[int, int]:
|
3548
3869
|
self.txt_measure_canvas.itemconfig(
|
3549
3870
|
self.txt_measure_canvas_text,
|
3550
3871
|
text=txt,
|
@@ -3565,7 +3886,6 @@ class MainTable(tk.Canvas):
|
|
3565
3886
|
def set_min_column_width(self, width: int) -> None:
|
3566
3887
|
if width:
|
3567
3888
|
self.PAR.ops.min_column_width = width
|
3568
|
-
|
3569
3889
|
if self.PAR.ops.min_column_width > self.PAR.ops.max_column_width:
|
3570
3890
|
self.PAR.ops.max_column_width = self.PAR.ops.min_column_width + 20
|
3571
3891
|
if (
|
@@ -3595,12 +3915,12 @@ class MainTable(tk.Canvas):
|
|
3595
3915
|
def set_table_font(self, newfont: tuple | None = None, reset_row_positions: bool = False) -> tuple[str, int, str]:
|
3596
3916
|
if newfont:
|
3597
3917
|
if not isinstance(newfont, tuple):
|
3598
|
-
raise ValueError("Argument must be tuple e.g.
|
3918
|
+
raise ValueError("Argument must be tuple e.g. ('Carlito', 12, 'normal')")
|
3599
3919
|
if len(newfont) != 3:
|
3600
3920
|
raise ValueError("Argument must be three-tuple")
|
3601
3921
|
if not isinstance(newfont[0], str) or not isinstance(newfont[1], int) or not isinstance(newfont[2], str):
|
3602
3922
|
raise ValueError(
|
3603
|
-
"Argument must be font, size and 'normal', 'bold' or
|
3923
|
+
"Argument must be font, size and 'normal', 'bold' or'italic' e.g. ('Carlito',12,'normal')"
|
3604
3924
|
)
|
3605
3925
|
self.PAR.ops.table_font = FontTuple(*newfont)
|
3606
3926
|
self.set_table_font_help()
|
@@ -3632,7 +3952,7 @@ class MainTable(tk.Canvas):
|
|
3632
3952
|
raise ValueError("Argument must be three-tuple")
|
3633
3953
|
if not isinstance(newfont[0], str) or not isinstance(newfont[1], int) or not isinstance(newfont[2], str):
|
3634
3954
|
raise ValueError(
|
3635
|
-
"Argument must be font, size and 'normal', 'bold' or
|
3955
|
+
"Argument must be font, size and 'normal', 'bold' or'italic' e.g. ('Carlito',12,'normal')"
|
3636
3956
|
)
|
3637
3957
|
self.PAR.ops.header_font = FontTuple(*newfont)
|
3638
3958
|
self.set_header_font_help()
|
@@ -3663,7 +3983,7 @@ class MainTable(tk.Canvas):
|
|
3663
3983
|
raise ValueError("Argument must be three-tuple")
|
3664
3984
|
if not isinstance(newfont[0], str) or not isinstance(newfont[1], int) or not isinstance(newfont[2], str):
|
3665
3985
|
raise ValueError(
|
3666
|
-
"Argument must be font, size and 'normal', 'bold' or
|
3986
|
+
"Argument must be font, size and 'normal', 'bold' or'italic' e.g. ('Carlito',12,'normal')"
|
3667
3987
|
)
|
3668
3988
|
self.PAR.ops.index_font = FontTuple(*newfont)
|
3669
3989
|
self.set_index_font_help()
|
@@ -3880,7 +4200,7 @@ class MainTable(tk.Canvas):
|
|
3880
4200
|
self.recreate_all_selection_boxes()
|
3881
4201
|
return self.row_positions, self.col_positions
|
3882
4202
|
|
3883
|
-
def set_col_positions(self, itr:
|
4203
|
+
def set_col_positions(self, itr: AnyIter[float]) -> None:
|
3884
4204
|
self.col_positions = list(accumulate(chain([0], itr)))
|
3885
4205
|
|
3886
4206
|
def reset_col_positions(self, ncols: int | None = None):
|
@@ -3892,7 +4212,7 @@ class MainTable(tk.Canvas):
|
|
3892
4212
|
else:
|
3893
4213
|
self.set_col_positions(itr=repeat(colpos, len(self.displayed_columns)))
|
3894
4214
|
|
3895
|
-
def set_row_positions(self, itr:
|
4215
|
+
def set_row_positions(self, itr: AnyIter[float]) -> None:
|
3896
4216
|
self.row_positions = list(accumulate(chain([0], itr)))
|
3897
4217
|
|
3898
4218
|
def reset_row_positions(self, nrows: int | None = None):
|
@@ -3926,7 +4246,7 @@ class MainTable(tk.Canvas):
|
|
3926
4246
|
del self.row_positions[idx]
|
3927
4247
|
self.row_positions[idx:] = [e - w for e in islice(self.row_positions, idx, len(self.row_positions))]
|
3928
4248
|
|
3929
|
-
def del_col_positions(self, idxs:
|
4249
|
+
def del_col_positions(self, idxs: AnyIter[int] | None = None):
|
3930
4250
|
if idxs is None:
|
3931
4251
|
del self.col_positions[-1]
|
3932
4252
|
else:
|
@@ -3934,7 +4254,7 @@ class MainTable(tk.Canvas):
|
|
3934
4254
|
idxs = set(idxs)
|
3935
4255
|
self.set_col_positions(itr=(w for i, w in enumerate(self.gen_column_widths()) if i not in idxs))
|
3936
4256
|
|
3937
|
-
def del_row_positions(self, idxs:
|
4257
|
+
def del_row_positions(self, idxs: AnyIter[int] | None = None):
|
3938
4258
|
if idxs is None:
|
3939
4259
|
del self.row_positions[-1]
|
3940
4260
|
else:
|
@@ -4678,8 +4998,8 @@ class MainTable(tk.Canvas):
|
|
4678
4998
|
data_ins_col: int,
|
4679
4999
|
displayed_ins_col: int,
|
4680
5000
|
numcols: int,
|
4681
|
-
columns: list | None = None,
|
4682
|
-
widths: list | None = None,
|
5001
|
+
columns: list[list[object]] | None = None,
|
5002
|
+
widths: list[int] | tuple[int] | None = None,
|
4683
5003
|
headers: bool = False,
|
4684
5004
|
) -> tuple[dict, dict, dict]:
|
4685
5005
|
header_data = {}
|
@@ -4728,10 +5048,10 @@ class MainTable(tk.Canvas):
|
|
4728
5048
|
data_ins_row: int,
|
4729
5049
|
displayed_ins_row: int,
|
4730
5050
|
numrows: int,
|
4731
|
-
rows: list | None = None,
|
4732
|
-
heights: list | None = None,
|
5051
|
+
rows: list[list[object]] | None = None,
|
5052
|
+
heights: list[int] | tuple[int] | None = None,
|
4733
5053
|
row_index: bool = False,
|
4734
|
-
total_data_cols=None,
|
5054
|
+
total_data_cols: int | None = None,
|
4735
5055
|
) -> tuple[dict, dict, dict]:
|
4736
5056
|
index_data = {}
|
4737
5057
|
if isinstance(self._row_index, list):
|
@@ -4934,7 +5254,7 @@ class MainTable(tk.Canvas):
|
|
4934
5254
|
|
4935
5255
|
def display_rows(
|
4936
5256
|
self,
|
4937
|
-
rows: int |
|
5257
|
+
rows: int | AnyIter[int] | None = None,
|
4938
5258
|
all_rows_displayed: bool | None = None,
|
4939
5259
|
reset_row_positions: bool = True,
|
4940
5260
|
deselect_all: bool = True,
|
@@ -4963,7 +5283,7 @@ class MainTable(tk.Canvas):
|
|
4963
5283
|
|
4964
5284
|
def display_columns(
|
4965
5285
|
self,
|
4966
|
-
columns: int |
|
5286
|
+
columns: int | AnyIter[int] | None = None,
|
4967
5287
|
all_columns_displayed: bool | None = None,
|
4968
5288
|
reset_col_positions: bool = True,
|
4969
5289
|
deselect_all: bool = True,
|
@@ -5568,11 +5888,18 @@ class MainTable(tk.Canvas):
|
|
5568
5888
|
if resized_cols or resized_rows or changed_w:
|
5569
5889
|
self.recreate_all_selection_boxes()
|
5570
5890
|
if changed_w:
|
5571
|
-
self.
|
5572
|
-
|
5573
|
-
self.CH.update_idletasks()
|
5574
|
-
self.TL.update_idletasks()
|
5891
|
+
for widget in (self, self.RI, self.CH, self.TL):
|
5892
|
+
widget.update_idletasks()
|
5575
5893
|
return False
|
5894
|
+
if self.find_window.open:
|
5895
|
+
w, h, x, y = self.get_find_window_dimensions_coords(w_width=self.winfo_width())
|
5896
|
+
self.coords(self.find_window.canvas_id, x, y)
|
5897
|
+
self.itemconfig(
|
5898
|
+
self.find_window.canvas_id,
|
5899
|
+
width=w,
|
5900
|
+
height=h,
|
5901
|
+
state="normal",
|
5902
|
+
)
|
5576
5903
|
self.hidd_text.update(self.disp_text)
|
5577
5904
|
self.disp_text = {}
|
5578
5905
|
self.hidd_high.update(self.disp_high)
|
@@ -5603,13 +5930,13 @@ class MainTable(tk.Canvas):
|
|
5603
5930
|
chain.from_iterable(
|
5604
5931
|
[
|
5605
5932
|
(
|
5606
|
-
|
5933
|
+
scrollpos_left - 1,
|
5607
5934
|
self.row_positions[r],
|
5608
5935
|
x_grid_stop,
|
5609
5936
|
self.row_positions[r],
|
5610
|
-
|
5937
|
+
scrollpos_left - 1,
|
5611
5938
|
self.row_positions[r],
|
5612
|
-
|
5939
|
+
scrollpos_left - 1,
|
5613
5940
|
self.row_positions[r + 1] if len(self.row_positions) - 1 > r else self.row_positions[r],
|
5614
5941
|
)
|
5615
5942
|
for r in range(grid_start_row, grid_end_row)
|
@@ -5971,56 +6298,35 @@ class MainTable(tk.Canvas):
|
|
5971
6298
|
box: tuple[int, int, int, int] | None = None,
|
5972
6299
|
run_binding: bool = True,
|
5973
6300
|
) -> None:
|
6301
|
+
def box_created(r: int, c: int, box: SelectionBox) -> bool:
|
6302
|
+
r1, c1, r2, c2 = box.coords
|
6303
|
+
if r1 <= r and c1 <= c and r2 >= r and c2 >= c:
|
6304
|
+
self.create_currently_selected_box(r, c, box.type_, box.fill_iid)
|
6305
|
+
if run_binding:
|
6306
|
+
self.run_selection_binding(box.type_)
|
6307
|
+
return True
|
6308
|
+
return False
|
6309
|
+
|
6310
|
+
# set current to a particular existing selection box
|
5974
6311
|
if isinstance(item, int) and item in self.selection_boxes:
|
5975
6312
|
selection_box = self.selection_boxes[item]
|
5976
6313
|
r1, c1, r2, c2 = selection_box.coords
|
5977
|
-
if r is None:
|
5978
|
-
r = r1
|
5979
|
-
if c is None:
|
5980
|
-
c = c1
|
5981
|
-
if r1 <= r and c1 <= c and r2 >= r and c2 >= c:
|
5982
|
-
self.create_currently_selected_box(
|
5983
|
-
r,
|
5984
|
-
c,
|
5985
|
-
selection_box.type_,
|
5986
|
-
selection_box.fill_iid,
|
5987
|
-
)
|
5988
|
-
if run_binding:
|
5989
|
-
self.run_selection_binding(selection_box.type_)
|
6314
|
+
if box_created(r1 if r is None else r, c1 if c is None else c, selection_box):
|
5990
6315
|
return
|
5991
|
-
|
6316
|
+
|
6317
|
+
# set current to any existing selection box with coordinates: box
|
5992
6318
|
if isinstance(box, tuple):
|
5993
|
-
if r is None:
|
5994
|
-
r = box[0]
|
5995
|
-
if c is None:
|
5996
|
-
c = box[1]
|
5997
6319
|
for item, selection_box in self.get_selection_items(reverse=True):
|
5998
|
-
|
5999
|
-
|
6000
|
-
|
6001
|
-
|
6002
|
-
|
6003
|
-
|
6004
|
-
selection_box.fill_iid,
|
6005
|
-
)
|
6006
|
-
if run_binding:
|
6007
|
-
self.run_selection_binding(selection_box.type_)
|
6008
|
-
return
|
6009
|
-
# currently selected is just pointed at a coordinate
|
6010
|
-
# find the top most box there, requires r and c
|
6011
|
-
if r is not None and c is not None:
|
6320
|
+
if box == selection_box.coords:
|
6321
|
+
if box_created(box[0] if r is None else r, box[1] if c is None else c, selection_box):
|
6322
|
+
return
|
6323
|
+
|
6324
|
+
# set current to a coordinate, find the top most box there
|
6325
|
+
if isinstance(r, int) and isinstance(c, int):
|
6012
6326
|
for item, selection_box in self.get_selection_items(reverse=True):
|
6013
|
-
|
6014
|
-
if r1 <= r and c1 <= c and r2 >= r and c2 >= c:
|
6015
|
-
self.create_currently_selected_box(
|
6016
|
-
r,
|
6017
|
-
c,
|
6018
|
-
selection_box.type_,
|
6019
|
-
selection_box.fill_iid,
|
6020
|
-
)
|
6021
|
-
if run_binding:
|
6022
|
-
self.run_selection_binding(selection_box.type_)
|
6327
|
+
if box_created(r, c, selection_box):
|
6023
6328
|
return
|
6329
|
+
|
6024
6330
|
# wasn't provided an item and couldn't find a box at coords so select cell
|
6025
6331
|
if r < len(self.row_positions) - 1 and c < len(self.col_positions) - 1:
|
6026
6332
|
self.select_cell(r, c, redraw=True)
|
@@ -6141,7 +6447,7 @@ class MainTable(tk.Canvas):
|
|
6141
6447
|
|
6142
6448
|
def hide_selection_box(self, item: int | None) -> bool:
|
6143
6449
|
if item is None or item is True or item not in self.selection_boxes:
|
6144
|
-
return
|
6450
|
+
return False
|
6145
6451
|
box = self.selection_boxes.pop(item)
|
6146
6452
|
self.hide_box(box.fill_iid)
|
6147
6453
|
self.hide_box(box.bd_iid)
|
@@ -6391,50 +6697,30 @@ class MainTable(tk.Canvas):
|
|
6391
6697
|
def recreate_all_selection_boxes(self) -> None:
|
6392
6698
|
if not self.selected:
|
6393
6699
|
return
|
6700
|
+
|
6394
6701
|
modified = False
|
6702
|
+
row_limit = len(self.row_positions) - 1
|
6703
|
+
col_limit = len(self.col_positions) - 1
|
6704
|
+
|
6395
6705
|
for item, box in self.get_selection_items():
|
6396
6706
|
r1, c1, r2, c2 = box.coords
|
6397
|
-
|
6398
|
-
|
6399
|
-
|
6400
|
-
|
6401
|
-
|
6402
|
-
|
6403
|
-
|
6404
|
-
if r1 >= len(self.row_positions) - 1:
|
6405
|
-
if len(self.row_positions) > 1:
|
6406
|
-
r1 = len(self.row_positions) - 2
|
6407
|
-
else:
|
6408
|
-
r1 = 0
|
6409
|
-
if c1 >= len(self.col_positions) - 1:
|
6410
|
-
if len(self.col_positions) > 1:
|
6411
|
-
c1 = len(self.col_positions) - 2
|
6412
|
-
else:
|
6413
|
-
c1 = 0
|
6414
|
-
if r2 > len(self.row_positions) - 1:
|
6415
|
-
r2 = len(self.row_positions) - 1
|
6416
|
-
if c2 > len(self.col_positions) - 1:
|
6417
|
-
c2 = len(self.col_positions) - 1
|
6707
|
+
# check coordinates
|
6708
|
+
r1 = min(r1, row_limit - (1 if row_limit > 0 else 0))
|
6709
|
+
c1 = min(c1, col_limit - (1 if col_limit > 0 else 0))
|
6710
|
+
r2 = min(r2, row_limit)
|
6711
|
+
c2 = min(c2, col_limit)
|
6712
|
+
|
6713
|
+
modified = modified or (r1 >= row_limit or c1 >= col_limit or r2 > row_limit or c2 > col_limit)
|
6418
6714
|
self.recreate_selection_box(r1, c1, r2, c2, item, run_binding=False)
|
6419
6715
|
|
6420
6716
|
if self.selected:
|
6421
|
-
r = self.selected.row
|
6422
|
-
c
|
6423
|
-
|
6424
|
-
self.set_currently_selected(
|
6425
|
-
r,
|
6426
|
-
c,
|
6427
|
-
item=self.selected.fill_iid,
|
6428
|
-
run_binding=False,
|
6429
|
-
)
|
6717
|
+
r, c = self.selected.row, self.selected.column
|
6718
|
+
if r < row_limit and c < col_limit:
|
6719
|
+
self.set_currently_selected(r, c, item=self.selected.fill_iid, run_binding=False)
|
6430
6720
|
else:
|
6431
6721
|
box = self.selection_boxes[self.selected.fill_iid]
|
6432
|
-
self.set_currently_selected(
|
6433
|
-
|
6434
|
-
box.coords.from_c,
|
6435
|
-
item=box.fill_iid,
|
6436
|
-
run_binding=False,
|
6437
|
-
)
|
6722
|
+
self.set_currently_selected(box.coords[0], box.coords[1], item=box.fill_iid, run_binding=False)
|
6723
|
+
|
6438
6724
|
if modified:
|
6439
6725
|
self.PAR.emit_event(
|
6440
6726
|
"<<SheetSelect>>",
|
@@ -6461,23 +6747,17 @@ class MainTable(tk.Canvas):
|
|
6461
6747
|
return d
|
6462
6748
|
|
6463
6749
|
def get_selected_min_max(self) -> tuple[int, int, int, int] | tuple[None, None, None, None]:
|
6464
|
-
|
6465
|
-
|
6466
|
-
|
6467
|
-
max_y = 0
|
6468
|
-
|
6750
|
+
if not self.get_selection_items():
|
6751
|
+
return None, None, None, None
|
6752
|
+
min_y, min_x = float("inf"), float("inf")
|
6753
|
+
max_y, max_x = 0, 0
|
6754
|
+
|
6755
|
+
for _, box in self.get_selection_items():
|
6469
6756
|
r1, c1, r2, c2 = box.coords
|
6470
|
-
|
6471
|
-
|
6472
|
-
|
6473
|
-
|
6474
|
-
if r2 > max_y:
|
6475
|
-
max_y = r2
|
6476
|
-
if c2 > max_x:
|
6477
|
-
max_x = c2
|
6478
|
-
if min_x != float("inf") and min_y != float("inf") and max_x > 0 and max_y > 0:
|
6479
|
-
return min_y, min_x, max_y, max_x
|
6480
|
-
return None, None, None, None
|
6757
|
+
min_y, min_x = min(min_y, r1), min(min_x, c1)
|
6758
|
+
max_y, max_x = max(max_y, r2), max(max_x, c2)
|
6759
|
+
|
6760
|
+
return (min_y, min_x, max_y, max_x) if min_y != float("inf") else (None, None, None, None)
|
6481
6761
|
|
6482
6762
|
def get_selected_rows(
|
6483
6763
|
self,
|
@@ -6632,7 +6912,7 @@ class MainTable(tk.Canvas):
|
|
6632
6912
|
elif self.get_cell_kwargs(datarn, datacn, key="dropdown") or self.get_cell_kwargs(
|
6633
6913
|
datarn, datacn, key="checkbox"
|
6634
6914
|
):
|
6635
|
-
if
|
6915
|
+
if event_opens_dropdown_or_checkbox(event):
|
6636
6916
|
if self.get_cell_kwargs(datarn, datacn, key="dropdown"):
|
6637
6917
|
self.open_dropdown_window(r, c, event=event)
|
6638
6918
|
elif self.get_cell_kwargs(datarn, datacn, key="checkbox"):
|
@@ -6640,27 +6920,6 @@ class MainTable(tk.Canvas):
|
|
6640
6920
|
else:
|
6641
6921
|
self.open_text_editor(event=event, r=r, c=c, dropdown=False)
|
6642
6922
|
|
6643
|
-
def event_opens_dropdown_or_checkbox(self, event=None) -> bool:
|
6644
|
-
if event is None:
|
6645
|
-
return False
|
6646
|
-
elif event == "rc":
|
6647
|
-
return True
|
6648
|
-
elif (
|
6649
|
-
(hasattr(event, "keysym") and event.keysym == "Return")
|
6650
|
-
or (hasattr(event, "keysym") and event.keysym == "F2")
|
6651
|
-
or (
|
6652
|
-
event is not None
|
6653
|
-
and hasattr(event, "keycode")
|
6654
|
-
and event.keycode == "??"
|
6655
|
-
and hasattr(event, "num")
|
6656
|
-
and event.num == 1
|
6657
|
-
) # mouseclick
|
6658
|
-
or (hasattr(event, "keysym") and event.keysym == "BackSpace")
|
6659
|
-
):
|
6660
|
-
return True
|
6661
|
-
else:
|
6662
|
-
return False
|
6663
|
-
|
6664
6923
|
# displayed indexes
|
6665
6924
|
def get_cell_align(self, r: int, c: int) -> str:
|
6666
6925
|
datarn = self.datarn(r)
|
@@ -6680,27 +6939,16 @@ class MainTable(tk.Canvas):
|
|
6680
6939
|
state: str = "normal",
|
6681
6940
|
dropdown: bool = False,
|
6682
6941
|
) -> bool:
|
6683
|
-
text =
|
6942
|
+
text = f"{self.get_cell_data(self.datarn(r), self.datacn(c), none_to_empty_str=True)}"
|
6684
6943
|
extra_func_key = "??"
|
6685
|
-
if
|
6686
|
-
if event
|
6687
|
-
|
6688
|
-
|
6689
|
-
|
6690
|
-
|
6691
|
-
|
6692
|
-
|
6693
|
-
text = ""
|
6694
|
-
else:
|
6695
|
-
text = f"{self.get_cell_data(self.datarn(r), self.datacn(c), none_to_empty_str = True)}"
|
6696
|
-
elif event is not None and (
|
6697
|
-
(hasattr(event, "char") and event.char.isalpha())
|
6698
|
-
or (hasattr(event, "char") and event.char.isdigit())
|
6699
|
-
or (hasattr(event, "char") and event.char in symbols_set)
|
6700
|
-
):
|
6701
|
-
extra_func_key = event.char
|
6702
|
-
text = event.char
|
6703
|
-
else:
|
6944
|
+
if event_opens_dropdown_or_checkbox(event):
|
6945
|
+
if hasattr(event, "keysym") and event.keysym in ("Return", "F2", "BackSpace"):
|
6946
|
+
extra_func_key = event.keysym
|
6947
|
+
if event.keysym == "BackSpace":
|
6948
|
+
text = ""
|
6949
|
+
elif event_has_char_key(event):
|
6950
|
+
extra_func_key = text = event.char
|
6951
|
+
elif event is not None:
|
6704
6952
|
return False
|
6705
6953
|
if self.extra_begin_edit_cell_func:
|
6706
6954
|
try:
|
@@ -6723,12 +6971,11 @@ class MainTable(tk.Canvas):
|
|
6723
6971
|
return False
|
6724
6972
|
else:
|
6725
6973
|
text = text if isinstance(text, str) else f"{text}"
|
6726
|
-
text = "" if text is None else text
|
6727
6974
|
if self.PAR.ops.cell_auto_resize_enabled:
|
6728
6975
|
self.set_cell_size_to_text(r, c, only_if_too_small=True, redraw=True, run_binding=True)
|
6729
6976
|
if self.text_editor.open and (r, c) == self.text_editor.coords:
|
6730
6977
|
self.text_editor.window.set_text(self.text_editor.get() + "" if not isinstance(text, str) else text)
|
6731
|
-
return
|
6978
|
+
return False
|
6732
6979
|
self.hide_text_editor()
|
6733
6980
|
if not self.see(r=r, c=c, check_cell_visibility=True):
|
6734
6981
|
self.refresh()
|
@@ -6736,8 +6983,6 @@ class MainTable(tk.Canvas):
|
|
6736
6983
|
y = self.row_positions[r]
|
6737
6984
|
w = self.col_positions[c + 1] - x + 1
|
6738
6985
|
h = self.row_positions[r + 1] - y + 1
|
6739
|
-
if text is None:
|
6740
|
-
text = f"{self.get_cell_data(self.datarn(r), self.datacn(c), none_to_empty_str = True)}"
|
6741
6986
|
kwargs = {
|
6742
6987
|
"menu_kwargs": DotDict(
|
6743
6988
|
{
|