tksheet 7.3.1__py3-none-any.whl → 7.3.3__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 +22 -36
- tksheet/find_window.py +251 -0
- tksheet/formatters.py +1 -1
- tksheet/functions.py +154 -45
- tksheet/main_table.py +458 -284
- tksheet/other_classes.py +6 -9
- tksheet/row_index.py +23 -35
- tksheet/sheet.py +75 -21
- tksheet/sheet_options.py +16 -1
- tksheet/text_editor.py +1 -1
- tksheet/top_left_rectangle.py +1 -1
- {tksheet-7.3.1.dist-info → tksheet-7.3.3.dist-info}/METADATA +10 -11
- tksheet-7.3.3.dist-info/RECORD +21 -0
- {tksheet-7.3.1.dist-info → tksheet-7.3.3.dist-info}/WHEEL +1 -1
- tksheet-7.3.1.dist-info/RECORD +0 -20
- /tksheet/{vars.py → constants.py} +0 -0
- {tksheet-7.3.1.dist-info → tksheet-7.3.3.dist-info}/LICENSE.txt +0 -0
- {tksheet-7.3.1.dist-info → tksheet-7.3.3.dist-info}/top_level.txt +0 -0
tksheet/main_table.py
CHANGED
@@ -39,6 +39,22 @@ from typing import Literal
|
|
39
39
|
from .colors import (
|
40
40
|
color_map,
|
41
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
|
+
)
|
42
58
|
from .formatters import (
|
43
59
|
data_to_str,
|
44
60
|
format_data,
|
@@ -50,6 +66,8 @@ from .formatters import (
|
|
50
66
|
from .functions import (
|
51
67
|
add_to_displayed,
|
52
68
|
b_index,
|
69
|
+
bisect_in,
|
70
|
+
box_gen_coords,
|
53
71
|
box_is_single_cell,
|
54
72
|
cell_right_within_box,
|
55
73
|
color_tup,
|
@@ -58,7 +76,10 @@ from .functions import (
|
|
58
76
|
diff_list,
|
59
77
|
down_cell_within_box,
|
60
78
|
event_dict,
|
79
|
+
event_has_char_key,
|
80
|
+
event_opens_dropdown_or_checkbox,
|
61
81
|
float_to_int,
|
82
|
+
gen_coords,
|
62
83
|
gen_formatted,
|
63
84
|
get_data_from_clipboard,
|
64
85
|
get_new_indexes,
|
@@ -67,6 +88,7 @@ from .functions import (
|
|
67
88
|
insert_items,
|
68
89
|
int_x_iter,
|
69
90
|
is_iterable,
|
91
|
+
is_last_cell,
|
70
92
|
is_type_int,
|
71
93
|
len_to_idx,
|
72
94
|
mod_event_val,
|
@@ -74,6 +96,7 @@ from .functions import (
|
|
74
96
|
mod_span_widget,
|
75
97
|
move_elements_by_mapping,
|
76
98
|
new_tk_event,
|
99
|
+
next_cell,
|
77
100
|
rounded_box_coords,
|
78
101
|
span_idxs_post_move,
|
79
102
|
stored_event_dict,
|
@@ -86,6 +109,7 @@ from .other_classes import (
|
|
86
109
|
Box_t,
|
87
110
|
DotDict,
|
88
111
|
DropdownStorage,
|
112
|
+
EditorStorageBase,
|
89
113
|
EventDataDict,
|
90
114
|
FontTuple,
|
91
115
|
Highlight,
|
@@ -101,20 +125,6 @@ from .text_editor import (
|
|
101
125
|
from .types import (
|
102
126
|
AnyIter,
|
103
127
|
)
|
104
|
-
from .vars import (
|
105
|
-
USER_OS,
|
106
|
-
bind_add_columns,
|
107
|
-
bind_add_rows,
|
108
|
-
bind_del_columns,
|
109
|
-
bind_del_rows,
|
110
|
-
ctrl_key,
|
111
|
-
rc_binding,
|
112
|
-
symbols_set,
|
113
|
-
text_editor_close_bindings,
|
114
|
-
text_editor_newline_bindings,
|
115
|
-
text_editor_to_unbind,
|
116
|
-
val_modifying_options,
|
117
|
-
)
|
118
128
|
|
119
129
|
|
120
130
|
class MainTable(tk.Canvas):
|
@@ -140,6 +150,7 @@ class MainTable(tk.Canvas):
|
|
140
150
|
self.synced_scrolls = set()
|
141
151
|
self.dropdown = DropdownStorage()
|
142
152
|
self.text_editor = TextEditorStorage()
|
153
|
+
self.find_window = EditorStorageBase()
|
143
154
|
self.event_linker = {
|
144
155
|
"<<Copy>>": self.ctrl_c,
|
145
156
|
"<<Cut>>": self.ctrl_x,
|
@@ -248,6 +259,7 @@ class MainTable(tk.Canvas):
|
|
248
259
|
self.drag_selection_enabled = False
|
249
260
|
self.select_all_enabled = False
|
250
261
|
self.undo_enabled = False
|
262
|
+
self.find_enabled = False
|
251
263
|
self.cut_enabled = False
|
252
264
|
self.copy_enabled = False
|
253
265
|
self.paste_enabled = False
|
@@ -476,6 +488,250 @@ class MainTable(tk.Canvas):
|
|
476
488
|
if delete_on_timer:
|
477
489
|
self.after(1500, self.delete_ctrl_outlines)
|
478
490
|
|
491
|
+
def escape(self, event: tk.Misc | None) -> None:
|
492
|
+
if self.find_window.open:
|
493
|
+
self.close_find_window()
|
494
|
+
else:
|
495
|
+
self.deselect()
|
496
|
+
|
497
|
+
def get_find_window_dimensions_coords(self, w_width: int) -> tuple[int, int, int, int]:
|
498
|
+
width = min(self.get_txt_w("X" * 23), w_width - 7)
|
499
|
+
# w, h, x, y
|
500
|
+
return width, self.min_row_height, self.canvasx(max(0, w_width - width - 7)), self.canvasy(7)
|
501
|
+
|
502
|
+
def open_find_window(
|
503
|
+
self,
|
504
|
+
event: tk.Misc | None = None,
|
505
|
+
focus: bool = True,
|
506
|
+
) -> Literal["break"]:
|
507
|
+
if self.find_window.open:
|
508
|
+
self.close_find_window()
|
509
|
+
return "break"
|
510
|
+
width, height, x, y = self.get_find_window_dimensions_coords(w_width=self.winfo_width())
|
511
|
+
if not self.find_window.window:
|
512
|
+
self.find_window.window = FindWindow(
|
513
|
+
self,
|
514
|
+
find_prev_func=self.find_previous,
|
515
|
+
find_next_func=self.find_next,
|
516
|
+
close_func=self.close_find_window,
|
517
|
+
)
|
518
|
+
self.find_window.canvas_id = self.create_window((x, y), window=self.find_window.window, anchor="nw")
|
519
|
+
for b in chain(self.PAR.ops.escape_bindings, self.PAR.ops.find_bindings):
|
520
|
+
self.find_window.tktext.bind(b, self.close_find_window)
|
521
|
+
for b in chain(self.PAR.ops.find_next_bindings, ("<Return>", "<KP_Enter>")):
|
522
|
+
self.find_window.tktext.bind(b, self.find_next)
|
523
|
+
for b in self.PAR.ops.find_previous_bindings:
|
524
|
+
self.find_window.tktext.bind(b, self.find_previous)
|
525
|
+
else:
|
526
|
+
self.coords(self.find_window.canvas_id, x, y)
|
527
|
+
if not self.find_window.open:
|
528
|
+
self.itemconfig(self.find_window.canvas_id, state="normal")
|
529
|
+
self.find_window.open = True
|
530
|
+
self.find_window.window.reset(
|
531
|
+
**{
|
532
|
+
"menu_kwargs": DotDict(
|
533
|
+
{
|
534
|
+
"font": self.PAR.ops.table_font,
|
535
|
+
"foreground": self.PAR.ops.popup_menu_fg,
|
536
|
+
"background": self.PAR.ops.popup_menu_bg,
|
537
|
+
"activebackground": self.PAR.ops.popup_menu_highlight_bg,
|
538
|
+
"activeforeground": self.PAR.ops.popup_menu_highlight_fg,
|
539
|
+
}
|
540
|
+
),
|
541
|
+
"sheet_ops": self.PAR.ops,
|
542
|
+
"border_color": self.PAR.ops.table_selected_box_cells_fg,
|
543
|
+
"bg": self.PAR.ops.table_editor_bg,
|
544
|
+
"fg": self.PAR.ops.table_editor_fg,
|
545
|
+
"select_bg": self.PAR.ops.table_editor_select_bg,
|
546
|
+
"select_fg": self.PAR.ops.table_editor_select_fg,
|
547
|
+
}
|
548
|
+
)
|
549
|
+
self.itemconfig(self.find_window.canvas_id, width=width, height=height)
|
550
|
+
if focus:
|
551
|
+
self.find_window.tktext.focus_set()
|
552
|
+
return "break"
|
553
|
+
|
554
|
+
def find_see_and_set(
|
555
|
+
self,
|
556
|
+
coords: tuple[int, int, int | None] | None,
|
557
|
+
just_see: bool = False,
|
558
|
+
) -> tuple[int, int]:
|
559
|
+
if coords:
|
560
|
+
row, column, item = coords
|
561
|
+
if not self.all_rows_displayed:
|
562
|
+
row = self.disprn(row)
|
563
|
+
if not self.all_columns_displayed:
|
564
|
+
column = self.dispcn(column)
|
565
|
+
if not just_see:
|
566
|
+
if self.find_window.window.find_in_selection:
|
567
|
+
self.set_currently_selected(row, column, item=item)
|
568
|
+
else:
|
569
|
+
self.select_cell(row, column, redraw=False)
|
570
|
+
if not self.see(
|
571
|
+
row,
|
572
|
+
column,
|
573
|
+
keep_yscroll=False,
|
574
|
+
keep_xscroll=False,
|
575
|
+
bottom_right_corner=False,
|
576
|
+
check_cell_visibility=True,
|
577
|
+
redraw=True,
|
578
|
+
):
|
579
|
+
self.refresh()
|
580
|
+
return coords
|
581
|
+
|
582
|
+
def find_match(self, find: str, r: int, c: int) -> bool:
|
583
|
+
return (
|
584
|
+
not find
|
585
|
+
and (not self.get_valid_cell_data_as_str(r, c, True).lower() or not f"{self.get_cell_data(r, c)}".lower())
|
586
|
+
) or (
|
587
|
+
find
|
588
|
+
and (
|
589
|
+
find in self.get_valid_cell_data_as_str(r, c, True).lower()
|
590
|
+
or find in f"{self.get_cell_data(r, c)}".lower()
|
591
|
+
)
|
592
|
+
)
|
593
|
+
|
594
|
+
def find_within_match(self, find: str, r: int, c: int) -> bool:
|
595
|
+
if not self.all_rows_displayed:
|
596
|
+
r = self.datarn(r)
|
597
|
+
if not self.all_columns_displayed:
|
598
|
+
c = self.datacn(c)
|
599
|
+
return self.find_match(find, r, c)
|
600
|
+
|
601
|
+
def find_within_current_box(
|
602
|
+
self,
|
603
|
+
current_box: SelectionBox,
|
604
|
+
find: str,
|
605
|
+
reverse: bool,
|
606
|
+
) -> None | tuple[int, int]:
|
607
|
+
start_row, start_col = next_cell(
|
608
|
+
*current_box.coords,
|
609
|
+
self.selected.row,
|
610
|
+
self.selected.column,
|
611
|
+
reverse=reverse,
|
612
|
+
)
|
613
|
+
_, _, r2, c2 = current_box.coords
|
614
|
+
for r, c in box_gen_coords(start_row, start_col, c2, r2, reverse=reverse):
|
615
|
+
if self.find_within_match(find, r, c):
|
616
|
+
return (r, c, current_box.fill_iid)
|
617
|
+
return None
|
618
|
+
|
619
|
+
def find_within_non_current_boxes(
|
620
|
+
self,
|
621
|
+
current_id: int,
|
622
|
+
find: str,
|
623
|
+
reverse: bool,
|
624
|
+
) -> None | tuple[int, int]:
|
625
|
+
if reverse:
|
626
|
+
# iterate backwards through selection boxes from the box before current
|
627
|
+
idx = next(i for i, k in enumerate(reversed(self.selection_boxes)) if k == current_id)
|
628
|
+
for item, box in chain(
|
629
|
+
islice(reversed(self.selection_boxes.items()), idx + 1, None),
|
630
|
+
islice(reversed(self.selection_boxes.items()), 0, idx),
|
631
|
+
):
|
632
|
+
for r, c in gen_coords(*box.coords, reverse=reverse):
|
633
|
+
if self.find_within_match(find, r, c):
|
634
|
+
return (r, c, item)
|
635
|
+
else:
|
636
|
+
# iterate forwards through selection boxes from the box after current
|
637
|
+
idx = next(i for i, k in enumerate(self.selection_boxes) if k == current_id)
|
638
|
+
for item, box in chain(
|
639
|
+
islice(self.selection_boxes.items(), idx + 1, None),
|
640
|
+
islice(self.selection_boxes.items(), 0, idx),
|
641
|
+
):
|
642
|
+
for r, c in gen_coords(*box.coords, reverse=reverse):
|
643
|
+
if self.find_within_match(find, r, c):
|
644
|
+
return (r, c, item)
|
645
|
+
return None
|
646
|
+
|
647
|
+
def find_within(
|
648
|
+
self,
|
649
|
+
find: str,
|
650
|
+
reverse: bool = False,
|
651
|
+
) -> tuple[int, int, int] | None:
|
652
|
+
current_box = self.selection_boxes[self.selected.fill_iid]
|
653
|
+
current_id = self.selected.fill_iid
|
654
|
+
if is_last_cell(*current_box.coords, self.selected.row, self.selected.column, reverse=reverse):
|
655
|
+
if coord := self.find_within_non_current_boxes(current_id=current_id, find=find, reverse=reverse):
|
656
|
+
return coord
|
657
|
+
if coord := self.find_within_current_box(current_box=current_box, find=find, reverse=reverse):
|
658
|
+
return coord
|
659
|
+
else:
|
660
|
+
if coord := self.find_within_current_box(current_box=current_box, find=find, reverse=reverse):
|
661
|
+
return coord
|
662
|
+
if coord := self.find_within_non_current_boxes(current_id=current_id, find=find, reverse=reverse):
|
663
|
+
return coord
|
664
|
+
return None
|
665
|
+
|
666
|
+
def find_all_cells(
|
667
|
+
self,
|
668
|
+
find: str,
|
669
|
+
reverse: bool = False,
|
670
|
+
) -> tuple[int, int, None] | None:
|
671
|
+
if self.selected:
|
672
|
+
row, col = next_cell(
|
673
|
+
0,
|
674
|
+
0,
|
675
|
+
len(self.row_positions) - 1,
|
676
|
+
len(self.col_positions) - 1,
|
677
|
+
self.selected.row,
|
678
|
+
self.selected.column,
|
679
|
+
reverse=reverse,
|
680
|
+
)
|
681
|
+
else:
|
682
|
+
row, col = 0, 0
|
683
|
+
row, col = self.datarn(row), self.datacn(col)
|
684
|
+
result = next(
|
685
|
+
(
|
686
|
+
(r, c)
|
687
|
+
for r, c in box_gen_coords(
|
688
|
+
start_row=row,
|
689
|
+
start_col=col,
|
690
|
+
total_cols=self.total_data_cols(include_header=False),
|
691
|
+
total_rows=self.total_data_rows(include_index=False),
|
692
|
+
reverse=reverse,
|
693
|
+
)
|
694
|
+
if (
|
695
|
+
(self.all_rows_displayed or bisect_in(self.displayed_rows, r))
|
696
|
+
and (self.all_columns_displayed or bisect_in(self.displayed_columns, c))
|
697
|
+
and self.find_match(find, r, c)
|
698
|
+
)
|
699
|
+
),
|
700
|
+
None,
|
701
|
+
)
|
702
|
+
if result:
|
703
|
+
return result + (None,)
|
704
|
+
return None
|
705
|
+
|
706
|
+
def find_next(self, event: tk.Misc | None = None) -> Literal["break"]:
|
707
|
+
find = self.find_window.get().lower()
|
708
|
+
if not self.find_window.open:
|
709
|
+
self.open_find_window(focus=False)
|
710
|
+
if self.find_window.window.find_in_selection:
|
711
|
+
self.find_see_and_set(self.find_within(find))
|
712
|
+
else:
|
713
|
+
self.find_see_and_set(self.find_all_cells(find))
|
714
|
+
return "break"
|
715
|
+
|
716
|
+
def find_previous(self, event: tk.Misc | None = None) -> Literal["break"]:
|
717
|
+
find = self.find_window.get().lower()
|
718
|
+
if not self.find_window.open:
|
719
|
+
self.open_find_window(focus=False)
|
720
|
+
if self.find_window.window.find_in_selection:
|
721
|
+
self.find_see_and_set(self.find_within(find, reverse=True))
|
722
|
+
else:
|
723
|
+
self.find_see_and_set(self.find_all_cells(find, reverse=True))
|
724
|
+
return "break"
|
725
|
+
|
726
|
+
def close_find_window(
|
727
|
+
self,
|
728
|
+
event: tk.Misc | None = None,
|
729
|
+
) -> None:
|
730
|
+
if self.find_window.open:
|
731
|
+
self.itemconfig(self.find_window.canvas_id, state="hidden")
|
732
|
+
self.find_window.open = False
|
733
|
+
self.focus_set()
|
734
|
+
|
479
735
|
def create_ctrl_outline(
|
480
736
|
self,
|
481
737
|
x1: int,
|
@@ -527,19 +783,19 @@ class MainTable(tk.Canvas):
|
|
527
783
|
self.hidd_ctrl_outline[t] = False
|
528
784
|
|
529
785
|
def get_ctrl_x_c_boxes(self) -> tuple[dict[tuple[int, int, int, int], str], int]:
|
530
|
-
boxes = {}
|
531
786
|
maxrows = 0
|
532
787
|
if not self.selected:
|
533
|
-
return
|
788
|
+
return {}, maxrows
|
534
789
|
if self.selected.type_ in ("cells", "columns"):
|
535
790
|
curr_box = self.selection_boxes[self.selected.fill_iid].coords
|
536
791
|
maxrows = curr_box[2] - curr_box[0]
|
537
|
-
|
538
|
-
|
539
|
-
|
792
|
+
boxes = {
|
793
|
+
box.coords: box.type_
|
794
|
+
for _, box in self.get_selection_items(rows=False)
|
795
|
+
if maxrows >= box.coords[2] - box.coords[0]
|
796
|
+
}
|
540
797
|
else:
|
541
|
-
for
|
542
|
-
boxes[box.coords] = "rows"
|
798
|
+
boxes = {box.coords: "rows" for _, box in self.get_selection_items(columns=False, cells=False)}
|
543
799
|
return boxes, maxrows
|
544
800
|
|
545
801
|
def io_csv_writer(self) -> tuple[io.StringIO, csv.writer]:
|
@@ -964,25 +1220,24 @@ class MainTable(tk.Canvas):
|
|
964
1220
|
event_data["selection_boxes"] = boxes
|
965
1221
|
if not try_binding(self.extra_begin_delete_key_func, event_data, "begin_delete"):
|
966
1222
|
return
|
967
|
-
for
|
968
|
-
for r in
|
969
|
-
|
970
|
-
|
971
|
-
|
972
|
-
|
973
|
-
|
974
|
-
|
975
|
-
|
976
|
-
|
977
|
-
|
978
|
-
|
979
|
-
|
980
|
-
|
981
|
-
|
982
|
-
|
983
|
-
|
984
|
-
|
985
|
-
)
|
1223
|
+
for box in boxes:
|
1224
|
+
for r, c in gen_coords(*box):
|
1225
|
+
datarn, datacn = self.datarn(r), self.datacn(c)
|
1226
|
+
val = self.get_value_for_empty_cell(datarn, datacn)
|
1227
|
+
if (
|
1228
|
+
not self.edit_validation_func
|
1229
|
+
or not validation
|
1230
|
+
or (
|
1231
|
+
self.edit_validation_func
|
1232
|
+
and (val := self.edit_validation_func(mod_event_val(event_data, val, (r, c)))) is not None
|
1233
|
+
)
|
1234
|
+
):
|
1235
|
+
event_data = self.event_data_set_cell(
|
1236
|
+
datarn,
|
1237
|
+
datacn,
|
1238
|
+
val,
|
1239
|
+
event_data,
|
1240
|
+
)
|
986
1241
|
if event_data["cells"]["table"]:
|
987
1242
|
self.refresh()
|
988
1243
|
self.undo_stack.append(stored_event_dict(event_data))
|
@@ -1750,23 +2005,23 @@ class MainTable(tk.Canvas):
|
|
1750
2005
|
y = self.row_positions[r]
|
1751
2006
|
else:
|
1752
2007
|
y = self.row_positions[r + 1] + 1 - winfo_height
|
2008
|
+
y = y / (self.row_positions[-1] + self.PAR.ops.empty_vertical)
|
1753
2009
|
args = [
|
1754
2010
|
"moveto",
|
1755
|
-
y
|
2011
|
+
y - 1 if y > 1 else y,
|
1756
2012
|
]
|
1757
|
-
if args[1] > 1:
|
1758
|
-
args[1] = args[1] - 1
|
1759
2013
|
self.set_yviews(*args, redraw=False)
|
1760
2014
|
need_redraw = True
|
1761
2015
|
else:
|
1762
2016
|
if r is not None and not keep_yscroll:
|
1763
|
-
y = self.row_positions[r] + ((self.row_positions[r + 1] - self.row_positions[r]) * r_pc)
|
2017
|
+
y = int(self.row_positions[r] + ((self.row_positions[r + 1] - self.row_positions[r]) * r_pc)) - 2
|
2018
|
+
if y < 0:
|
2019
|
+
y = 0
|
2020
|
+
y = y / (self.row_positions[-1] + self.PAR.ops.empty_vertical)
|
1764
2021
|
args = [
|
1765
2022
|
"moveto",
|
1766
|
-
y
|
2023
|
+
y - 1 if y > 1 else y,
|
1767
2024
|
]
|
1768
|
-
if args[1] > 1:
|
1769
|
-
args[1] = args[1] - 1
|
1770
2025
|
self.set_yviews(*args, redraw=False)
|
1771
2026
|
need_redraw = True
|
1772
2027
|
if not xvis and len(self.col_positions) > 1:
|
@@ -1777,18 +2032,22 @@ class MainTable(tk.Canvas):
|
|
1777
2032
|
x = self.col_positions[c]
|
1778
2033
|
else:
|
1779
2034
|
x = self.col_positions[c + 1] + 1 - winfo_width
|
2035
|
+
x = x / (self.col_positions[-1] + self.PAR.ops.empty_horizontal)
|
1780
2036
|
args = [
|
1781
2037
|
"moveto",
|
1782
|
-
x
|
2038
|
+
x - 1 if x > 1 else x,
|
1783
2039
|
]
|
1784
2040
|
self.set_xviews(*args, redraw=False)
|
1785
2041
|
need_redraw = True
|
1786
2042
|
else:
|
1787
2043
|
if c is not None and not keep_xscroll:
|
1788
|
-
x = self.col_positions[c] + ((self.col_positions[c + 1] - self.col_positions[c]) * c_pc)
|
2044
|
+
x = int(self.col_positions[c] + ((self.col_positions[c + 1] - self.col_positions[c]) * c_pc)) - 2
|
2045
|
+
if x < 0:
|
2046
|
+
x = 0
|
2047
|
+
x = x / (self.col_positions[-1] + self.PAR.ops.empty_horizontal)
|
1789
2048
|
args = [
|
1790
2049
|
"moveto",
|
1791
|
-
x
|
2050
|
+
x - 1 if x > 1 else x,
|
1792
2051
|
]
|
1793
2052
|
self.set_xviews(*args, redraw=False)
|
1794
2053
|
need_redraw = True
|
@@ -1810,20 +2069,12 @@ class MainTable(tk.Canvas):
|
|
1810
2069
|
r: int | None = 0,
|
1811
2070
|
c: int | None = 0,
|
1812
2071
|
separate_axes: bool = False,
|
1813
|
-
) -> bool:
|
2072
|
+
) -> bool | tuple[bool, bool]:
|
1814
2073
|
cx1, cy1, cx2, cy2 = self.get_canvas_visible_area()
|
1815
2074
|
x1, y1, x2, y2 = self.get_cell_coords(r, c)
|
1816
|
-
x_vis =
|
1817
|
-
y_vis =
|
1818
|
-
|
1819
|
-
x_vis = False
|
1820
|
-
if cy1 > y1 or cy2 < y2:
|
1821
|
-
y_vis = False
|
1822
|
-
if separate_axes:
|
1823
|
-
return y_vis, x_vis
|
1824
|
-
if not y_vis or not x_vis:
|
1825
|
-
return False
|
1826
|
-
return True
|
2075
|
+
x_vis = cx1 <= x1 and cx2 >= x2
|
2076
|
+
y_vis = cy1 <= y1 and cy2 >= y2
|
2077
|
+
return (y_vis, x_vis) if separate_axes else y_vis and x_vis
|
1827
2078
|
|
1828
2079
|
def cell_visible(self, r: int = 0, c: int = 0) -> bool:
|
1829
2080
|
cx1, cy1, cx2, cy2 = self.get_canvas_visible_area()
|
@@ -1877,13 +2128,13 @@ class MainTable(tk.Canvas):
|
|
1877
2128
|
|
1878
2129
|
def select_row_start(self, event: object) -> None:
|
1879
2130
|
if self.selected:
|
1880
|
-
self.select_cell(self.selected.row, 0)
|
1881
2131
|
self.see(self.selected.row, 0)
|
2132
|
+
self.select_cell(self.selected.row, 0, redraw=True)
|
1882
2133
|
|
1883
2134
|
def select_a1(self, event: object) -> None:
|
1884
2135
|
if len(self.row_positions) > 1 and len(self.col_positions) > 1:
|
1885
|
-
self.select_cell(0, 0)
|
1886
2136
|
self.see(0, 0)
|
2137
|
+
self.select_cell(0, 0, redraw=True)
|
1887
2138
|
|
1888
2139
|
def select_cell(
|
1889
2140
|
self,
|
@@ -2213,9 +2464,8 @@ class MainTable(tk.Canvas):
|
|
2213
2464
|
elif self.selected.type_ in ("cells", "columns"):
|
2214
2465
|
r = self.selected.row
|
2215
2466
|
c = self.selected.column
|
2216
|
-
if not r and self.CH.col_selection_enabled:
|
2217
|
-
|
2218
|
-
self.see(r, c, check_cell_visibility=False)
|
2467
|
+
if not r and self.CH.col_selection_enabled and not self.cell_completely_visible(r=r, c=c):
|
2468
|
+
self.see(r, c, check_cell_visibility=False)
|
2219
2469
|
elif r and (self.single_selection_enabled or self.toggle_selection_enabled):
|
2220
2470
|
if self.cell_completely_visible(r=r - 1, c=c):
|
2221
2471
|
self.select_cell(r - 1, c, redraw=True)
|
@@ -2229,32 +2479,18 @@ class MainTable(tk.Canvas):
|
|
2229
2479
|
if self.selected.type_ == "rows":
|
2230
2480
|
r = self.selected.row
|
2231
2481
|
if r < len(self.row_positions) - 2 and self.RI.row_selection_enabled:
|
2232
|
-
if self.cell_completely_visible(r=
|
2482
|
+
if self.cell_completely_visible(r=r + 1, c=0):
|
2233
2483
|
self.RI.select_row(r + 1, redraw=True)
|
2234
2484
|
else:
|
2235
2485
|
self.RI.select_row(r + 1)
|
2236
|
-
|
2237
|
-
r +
|
2238
|
-
|
2239
|
-
|
2240
|
-
|
2241
|
-
|
2242
|
-
)
|
2243
|
-
|
2244
|
-
r + 2,
|
2245
|
-
0,
|
2246
|
-
keep_xscroll=True,
|
2247
|
-
bottom_right_corner=True,
|
2248
|
-
check_cell_visibility=False,
|
2249
|
-
)
|
2250
|
-
elif not self.cell_completely_visible(r=r + 1, c=0):
|
2251
|
-
self.see(
|
2252
|
-
r + 1,
|
2253
|
-
0,
|
2254
|
-
keep_xscroll=True,
|
2255
|
-
bottom_right_corner=False if self.PAR.ops.arrow_key_down_right_scroll_page else True,
|
2256
|
-
check_cell_visibility=False,
|
2257
|
-
)
|
2486
|
+
self.see(
|
2487
|
+
r + 1,
|
2488
|
+
0,
|
2489
|
+
keep_xscroll=True,
|
2490
|
+
bottom_right_corner=False if self.PAR.ops.arrow_key_down_right_scroll_page else True,
|
2491
|
+
check_cell_visibility=False,
|
2492
|
+
)
|
2493
|
+
|
2258
2494
|
elif self.selected.type_ == "columns":
|
2259
2495
|
c = self.selected.column
|
2260
2496
|
if self.single_selection_enabled or self.toggle_selection_enabled:
|
@@ -2275,32 +2511,17 @@ class MainTable(tk.Canvas):
|
|
2275
2511
|
r = self.selected.row
|
2276
2512
|
c = self.selected.column
|
2277
2513
|
if r < len(self.row_positions) - 2 and (self.single_selection_enabled or self.toggle_selection_enabled):
|
2278
|
-
if self.cell_completely_visible(r=
|
2514
|
+
if self.cell_completely_visible(r=r + 1, c=c):
|
2279
2515
|
self.select_cell(r + 1, c, redraw=True)
|
2280
2516
|
else:
|
2281
2517
|
self.select_cell(r + 1, c)
|
2282
|
-
|
2283
|
-
r +
|
2284
|
-
|
2285
|
-
|
2286
|
-
|
2287
|
-
|
2288
|
-
)
|
2289
|
-
self.see(
|
2290
|
-
r + 2,
|
2291
|
-
c,
|
2292
|
-
keep_xscroll=True,
|
2293
|
-
bottom_right_corner=True,
|
2294
|
-
check_cell_visibility=False,
|
2295
|
-
)
|
2296
|
-
elif not self.cell_completely_visible(r=r + 1, c=c):
|
2297
|
-
self.see(
|
2298
|
-
r + 1,
|
2299
|
-
c,
|
2300
|
-
keep_xscroll=True,
|
2301
|
-
bottom_right_corner=False if self.PAR.ops.arrow_key_down_right_scroll_page else True,
|
2302
|
-
check_cell_visibility=False,
|
2303
|
-
)
|
2518
|
+
self.see(
|
2519
|
+
r + 1,
|
2520
|
+
c,
|
2521
|
+
keep_xscroll=True,
|
2522
|
+
bottom_right_corner=False if self.PAR.ops.arrow_key_down_right_scroll_page else True,
|
2523
|
+
check_cell_visibility=False,
|
2524
|
+
)
|
2304
2525
|
|
2305
2526
|
def arrowkey_LEFT(self, event: object = None) -> None:
|
2306
2527
|
if not self.selected:
|
@@ -2325,7 +2546,7 @@ class MainTable(tk.Canvas):
|
|
2325
2546
|
elif self.selected.type_ == "cells":
|
2326
2547
|
r = self.selected.row
|
2327
2548
|
c = self.selected.column
|
2328
|
-
if not c and not self.cell_completely_visible(r=r, c=
|
2549
|
+
if not c and not self.cell_completely_visible(r=r, c=c):
|
2329
2550
|
self.see(r, c, keep_yscroll=True, check_cell_visibility=False)
|
2330
2551
|
elif c and (self.single_selection_enabled or self.toggle_selection_enabled):
|
2331
2552
|
if self.cell_completely_visible(r=r, c=c - 1):
|
@@ -2710,7 +2931,7 @@ class MainTable(tk.Canvas):
|
|
2710
2931
|
**mnkwgs,
|
2711
2932
|
)
|
2712
2933
|
|
2713
|
-
def enable_bindings(self, bindings):
|
2934
|
+
def enable_bindings(self, bindings: object) -> None:
|
2714
2935
|
if not bindings:
|
2715
2936
|
self._enable_binding("all")
|
2716
2937
|
elif isinstance(bindings, (list, tuple)):
|
@@ -2752,6 +2973,7 @@ class MainTable(tk.Canvas):
|
|
2752
2973
|
):
|
2753
2974
|
self._tksheet_bind("row_start_bindings", self.select_row_start)
|
2754
2975
|
self._tksheet_bind("table_start_bindings", self.select_a1)
|
2976
|
+
self._tksheet_bind("escape_bindings", self.escape)
|
2755
2977
|
if binding in ("all", "single", "single_selection_mode", "single_select"):
|
2756
2978
|
self.single_selection_enabled = True
|
2757
2979
|
self.toggle_selection_enabled = False
|
@@ -2829,6 +3051,11 @@ class MainTable(tk.Canvas):
|
|
2829
3051
|
self.undo_enabled = True
|
2830
3052
|
self._tksheet_bind("undo_bindings", self.undo)
|
2831
3053
|
self._tksheet_bind("redo_bindings", self.redo)
|
3054
|
+
if binding in ("find",):
|
3055
|
+
self.find_enabled = True
|
3056
|
+
self._tksheet_bind("find_bindings", self.open_find_window)
|
3057
|
+
self._tksheet_bind("find_next_bindings", self.find_next)
|
3058
|
+
self._tksheet_bind("find_previous_bindings", self.find_previous)
|
2832
3059
|
if binding in bind_del_columns:
|
2833
3060
|
self.rc_delete_column_enabled = True
|
2834
3061
|
self.rc_popup_menus_enabled = True
|
@@ -2881,6 +3108,7 @@ class MainTable(tk.Canvas):
|
|
2881
3108
|
):
|
2882
3109
|
self._tksheet_unbind("row_start_bindings")
|
2883
3110
|
self._tksheet_unbind("table_start_bindings")
|
3111
|
+
self._tksheet_unbind("escape_bindings")
|
2884
3112
|
self.single_selection_enabled = False
|
2885
3113
|
self.toggle_selection_enabled = False
|
2886
3114
|
if binding in ("all", "drag_select"):
|
@@ -2971,6 +3199,12 @@ class MainTable(tk.Canvas):
|
|
2971
3199
|
if binding in ("all", "undo", "redo", "edit_bindings", "edit"):
|
2972
3200
|
self.undo_enabled = False
|
2973
3201
|
self._tksheet_unbind("undo_bindings", "redo_bindings")
|
3202
|
+
if binding in ("all", "find"):
|
3203
|
+
self.find_enabled = False
|
3204
|
+
self._tksheet_unbind("find_bindings")
|
3205
|
+
self._tksheet_unbind("find_next_bindings")
|
3206
|
+
self._tksheet_unbind("find_previous_bindings")
|
3207
|
+
self.close_find_window()
|
2974
3208
|
|
2975
3209
|
def _tksheet_unbind(self, *keys) -> None:
|
2976
3210
|
for widget in (self, self.RI, self.CH, self.TL):
|
@@ -3457,26 +3691,42 @@ class MainTable(tk.Canvas):
|
|
3457
3691
|
if move_synced:
|
3458
3692
|
self.y_move_synced_scrolls(*args, use_scrollbar=True)
|
3459
3693
|
|
3460
|
-
def set_xviews(
|
3694
|
+
def set_xviews(
|
3695
|
+
self,
|
3696
|
+
*args,
|
3697
|
+
move_synced: bool = True,
|
3698
|
+
redraw: bool = True,
|
3699
|
+
) -> None:
|
3461
3700
|
self.main_table_redraw_grid_and_text(setting_views=True)
|
3462
|
-
self.
|
3701
|
+
if not self.PAR._startup_complete:
|
3702
|
+
self.update_idletasks()
|
3463
3703
|
self.xview(*args)
|
3464
3704
|
if self.show_header:
|
3465
|
-
self.
|
3705
|
+
if not self.PAR._startup_complete:
|
3706
|
+
self.CH.update_idletasks()
|
3466
3707
|
self.CH.xview(*args)
|
3467
|
-
|
3708
|
+
if redraw:
|
3709
|
+
self.main_table_redraw_grid_and_text(redraw_header=True, redraw_row_index=False)
|
3468
3710
|
if move_synced:
|
3469
3711
|
self.x_move_synced_scrolls(*args)
|
3470
3712
|
self.fix_views()
|
3471
3713
|
|
3472
|
-
def set_yviews(
|
3714
|
+
def set_yviews(
|
3715
|
+
self,
|
3716
|
+
*args,
|
3717
|
+
move_synced: bool = True,
|
3718
|
+
redraw: bool = True,
|
3719
|
+
) -> None:
|
3473
3720
|
self.main_table_redraw_grid_and_text(setting_views=True)
|
3474
|
-
self.
|
3721
|
+
if not self.PAR._startup_complete:
|
3722
|
+
self.update_idletasks()
|
3475
3723
|
self.yview(*args)
|
3476
3724
|
if self.show_index:
|
3477
|
-
self.
|
3725
|
+
if not self.PAR._startup_complete:
|
3726
|
+
self.RI.update_idletasks()
|
3478
3727
|
self.RI.yview(*args)
|
3479
|
-
|
3728
|
+
if redraw:
|
3729
|
+
self.main_table_redraw_grid_and_text(redraw_header=False, redraw_row_index=True)
|
3480
3730
|
if move_synced:
|
3481
3731
|
self.y_move_synced_scrolls(*args)
|
3482
3732
|
self.fix_views()
|
@@ -3618,7 +3868,7 @@ class MainTable(tk.Canvas):
|
|
3618
3868
|
b = self.txt_measure_canvas.bbox(self.txt_measure_canvas_text)
|
3619
3869
|
return b[3] - b[1]
|
3620
3870
|
|
3621
|
-
def get_txt_dimensions(self, txt: str, font: None | FontTuple = None) -> int:
|
3871
|
+
def get_txt_dimensions(self, txt: str, font: None | FontTuple = None) -> tuple[int, int]:
|
3622
3872
|
self.txt_measure_canvas.itemconfig(
|
3623
3873
|
self.txt_measure_canvas_text,
|
3624
3874
|
text=txt,
|
@@ -3639,7 +3889,6 @@ class MainTable(tk.Canvas):
|
|
3639
3889
|
def set_min_column_width(self, width: int) -> None:
|
3640
3890
|
if width:
|
3641
3891
|
self.PAR.ops.min_column_width = width
|
3642
|
-
|
3643
3892
|
if self.PAR.ops.min_column_width > self.PAR.ops.max_column_width:
|
3644
3893
|
self.PAR.ops.max_column_width = self.PAR.ops.min_column_width + 20
|
3645
3894
|
if (
|
@@ -3669,12 +3918,12 @@ class MainTable(tk.Canvas):
|
|
3669
3918
|
def set_table_font(self, newfont: tuple | None = None, reset_row_positions: bool = False) -> tuple[str, int, str]:
|
3670
3919
|
if newfont:
|
3671
3920
|
if not isinstance(newfont, tuple):
|
3672
|
-
raise ValueError("Argument must be tuple e.g.
|
3921
|
+
raise ValueError("Argument must be tuple e.g. ('Carlito', 12, 'normal')")
|
3673
3922
|
if len(newfont) != 3:
|
3674
3923
|
raise ValueError("Argument must be three-tuple")
|
3675
3924
|
if not isinstance(newfont[0], str) or not isinstance(newfont[1], int) or not isinstance(newfont[2], str):
|
3676
3925
|
raise ValueError(
|
3677
|
-
"Argument must be font, size and 'normal', 'bold' or
|
3926
|
+
"Argument must be font, size and 'normal', 'bold' or'italic' e.g. ('Carlito',12,'normal')"
|
3678
3927
|
)
|
3679
3928
|
self.PAR.ops.table_font = FontTuple(*newfont)
|
3680
3929
|
self.set_table_font_help()
|
@@ -3706,7 +3955,7 @@ class MainTable(tk.Canvas):
|
|
3706
3955
|
raise ValueError("Argument must be three-tuple")
|
3707
3956
|
if not isinstance(newfont[0], str) or not isinstance(newfont[1], int) or not isinstance(newfont[2], str):
|
3708
3957
|
raise ValueError(
|
3709
|
-
"Argument must be font, size and 'normal', 'bold' or
|
3958
|
+
"Argument must be font, size and 'normal', 'bold' or'italic' e.g. ('Carlito',12,'normal')"
|
3710
3959
|
)
|
3711
3960
|
self.PAR.ops.header_font = FontTuple(*newfont)
|
3712
3961
|
self.set_header_font_help()
|
@@ -3737,7 +3986,7 @@ class MainTable(tk.Canvas):
|
|
3737
3986
|
raise ValueError("Argument must be three-tuple")
|
3738
3987
|
if not isinstance(newfont[0], str) or not isinstance(newfont[1], int) or not isinstance(newfont[2], str):
|
3739
3988
|
raise ValueError(
|
3740
|
-
"Argument must be font, size and 'normal', 'bold' or
|
3989
|
+
"Argument must be font, size and 'normal', 'bold' or'italic' e.g. ('Carlito',12,'normal')"
|
3741
3990
|
)
|
3742
3991
|
self.PAR.ops.index_font = FontTuple(*newfont)
|
3743
3992
|
self.set_index_font_help()
|
@@ -4752,8 +5001,8 @@ class MainTable(tk.Canvas):
|
|
4752
5001
|
data_ins_col: int,
|
4753
5002
|
displayed_ins_col: int,
|
4754
5003
|
numcols: int,
|
4755
|
-
columns: list | None = None,
|
4756
|
-
widths: list | None = None,
|
5004
|
+
columns: list[list[object]] | None = None,
|
5005
|
+
widths: list[int] | tuple[int] | None = None,
|
4757
5006
|
headers: bool = False,
|
4758
5007
|
) -> tuple[dict, dict, dict]:
|
4759
5008
|
header_data = {}
|
@@ -4802,10 +5051,10 @@ class MainTable(tk.Canvas):
|
|
4802
5051
|
data_ins_row: int,
|
4803
5052
|
displayed_ins_row: int,
|
4804
5053
|
numrows: int,
|
4805
|
-
rows: list | None = None,
|
4806
|
-
heights: list | None = None,
|
5054
|
+
rows: list[list[object]] | None = None,
|
5055
|
+
heights: list[int] | tuple[int] | None = None,
|
4807
5056
|
row_index: bool = False,
|
4808
|
-
total_data_cols=None,
|
5057
|
+
total_data_cols: int | None = None,
|
4809
5058
|
) -> tuple[dict, dict, dict]:
|
4810
5059
|
index_data = {}
|
4811
5060
|
if isinstance(self._row_index, list):
|
@@ -5008,7 +5257,7 @@ class MainTable(tk.Canvas):
|
|
5008
5257
|
|
5009
5258
|
def display_rows(
|
5010
5259
|
self,
|
5011
|
-
rows: int | AnyIter | None = None,
|
5260
|
+
rows: int | AnyIter[int] | None = None,
|
5012
5261
|
all_rows_displayed: bool | None = None,
|
5013
5262
|
reset_row_positions: bool = True,
|
5014
5263
|
deselect_all: bool = True,
|
@@ -5037,7 +5286,7 @@ class MainTable(tk.Canvas):
|
|
5037
5286
|
|
5038
5287
|
def display_columns(
|
5039
5288
|
self,
|
5040
|
-
columns: int | AnyIter | None = None,
|
5289
|
+
columns: int | AnyIter[int] | None = None,
|
5041
5290
|
all_columns_displayed: bool | None = None,
|
5042
5291
|
reset_col_positions: bool = True,
|
5043
5292
|
deselect_all: bool = True,
|
@@ -5642,11 +5891,18 @@ class MainTable(tk.Canvas):
|
|
5642
5891
|
if resized_cols or resized_rows or changed_w:
|
5643
5892
|
self.recreate_all_selection_boxes()
|
5644
5893
|
if changed_w:
|
5645
|
-
self.
|
5646
|
-
|
5647
|
-
self.CH.update_idletasks()
|
5648
|
-
self.TL.update_idletasks()
|
5894
|
+
for widget in (self, self.RI, self.CH, self.TL):
|
5895
|
+
widget.update_idletasks()
|
5649
5896
|
return False
|
5897
|
+
if self.find_window.open:
|
5898
|
+
w, h, x, y = self.get_find_window_dimensions_coords(w_width=self.winfo_width())
|
5899
|
+
self.coords(self.find_window.canvas_id, x, y)
|
5900
|
+
self.itemconfig(
|
5901
|
+
self.find_window.canvas_id,
|
5902
|
+
width=w,
|
5903
|
+
height=h,
|
5904
|
+
state="normal",
|
5905
|
+
)
|
5650
5906
|
self.hidd_text.update(self.disp_text)
|
5651
5907
|
self.disp_text = {}
|
5652
5908
|
self.hidd_high.update(self.disp_high)
|
@@ -5677,13 +5933,13 @@ class MainTable(tk.Canvas):
|
|
5677
5933
|
chain.from_iterable(
|
5678
5934
|
[
|
5679
5935
|
(
|
5680
|
-
|
5936
|
+
scrollpos_left - 1,
|
5681
5937
|
self.row_positions[r],
|
5682
5938
|
x_grid_stop,
|
5683
5939
|
self.row_positions[r],
|
5684
|
-
|
5940
|
+
scrollpos_left - 1,
|
5685
5941
|
self.row_positions[r],
|
5686
|
-
|
5942
|
+
scrollpos_left - 1,
|
5687
5943
|
self.row_positions[r + 1] if len(self.row_positions) - 1 > r else self.row_positions[r],
|
5688
5944
|
)
|
5689
5945
|
for r in range(grid_start_row, grid_end_row)
|
@@ -6045,56 +6301,35 @@ class MainTable(tk.Canvas):
|
|
6045
6301
|
box: tuple[int, int, int, int] | None = None,
|
6046
6302
|
run_binding: bool = True,
|
6047
6303
|
) -> None:
|
6304
|
+
def box_created(r: int, c: int, box: SelectionBox) -> bool:
|
6305
|
+
r1, c1, r2, c2 = box.coords
|
6306
|
+
if r1 <= r and c1 <= c and r2 >= r and c2 >= c:
|
6307
|
+
self.create_currently_selected_box(r, c, box.type_, box.fill_iid)
|
6308
|
+
if run_binding:
|
6309
|
+
self.run_selection_binding(box.type_)
|
6310
|
+
return True
|
6311
|
+
return False
|
6312
|
+
|
6313
|
+
# set current to a particular existing selection box
|
6048
6314
|
if isinstance(item, int) and item in self.selection_boxes:
|
6049
6315
|
selection_box = self.selection_boxes[item]
|
6050
6316
|
r1, c1, r2, c2 = selection_box.coords
|
6051
|
-
if r is None:
|
6052
|
-
r = r1
|
6053
|
-
if c is None:
|
6054
|
-
c = c1
|
6055
|
-
if r1 <= r and c1 <= c and r2 >= r and c2 >= c:
|
6056
|
-
self.create_currently_selected_box(
|
6057
|
-
r,
|
6058
|
-
c,
|
6059
|
-
selection_box.type_,
|
6060
|
-
selection_box.fill_iid,
|
6061
|
-
)
|
6062
|
-
if run_binding:
|
6063
|
-
self.run_selection_binding(selection_box.type_)
|
6317
|
+
if box_created(r1 if r is None else r, c1 if c is None else c, selection_box):
|
6064
6318
|
return
|
6065
|
-
|
6319
|
+
|
6320
|
+
# set current to any existing selection box with coordinates: box
|
6066
6321
|
if isinstance(box, tuple):
|
6067
|
-
if r is None:
|
6068
|
-
r = box[0]
|
6069
|
-
if c is None:
|
6070
|
-
c = box[1]
|
6071
6322
|
for item, selection_box in self.get_selection_items(reverse=True):
|
6072
|
-
|
6073
|
-
|
6074
|
-
|
6075
|
-
|
6076
|
-
|
6077
|
-
|
6078
|
-
selection_box.fill_iid,
|
6079
|
-
)
|
6080
|
-
if run_binding:
|
6081
|
-
self.run_selection_binding(selection_box.type_)
|
6082
|
-
return
|
6083
|
-
# currently selected is just pointed at a coordinate
|
6084
|
-
# find the top most box there, requires r and c
|
6085
|
-
if r is not None and c is not None:
|
6323
|
+
if box == selection_box.coords:
|
6324
|
+
if box_created(box[0] if r is None else r, box[1] if c is None else c, selection_box):
|
6325
|
+
return
|
6326
|
+
|
6327
|
+
# set current to a coordinate, find the top most box there
|
6328
|
+
if isinstance(r, int) and isinstance(c, int):
|
6086
6329
|
for item, selection_box in self.get_selection_items(reverse=True):
|
6087
|
-
|
6088
|
-
if r1 <= r and c1 <= c and r2 >= r and c2 >= c:
|
6089
|
-
self.create_currently_selected_box(
|
6090
|
-
r,
|
6091
|
-
c,
|
6092
|
-
selection_box.type_,
|
6093
|
-
selection_box.fill_iid,
|
6094
|
-
)
|
6095
|
-
if run_binding:
|
6096
|
-
self.run_selection_binding(selection_box.type_)
|
6330
|
+
if box_created(r, c, selection_box):
|
6097
6331
|
return
|
6332
|
+
|
6098
6333
|
# wasn't provided an item and couldn't find a box at coords so select cell
|
6099
6334
|
if r < len(self.row_positions) - 1 and c < len(self.col_positions) - 1:
|
6100
6335
|
self.select_cell(r, c, redraw=True)
|
@@ -6215,7 +6450,7 @@ class MainTable(tk.Canvas):
|
|
6215
6450
|
|
6216
6451
|
def hide_selection_box(self, item: int | None) -> bool:
|
6217
6452
|
if item is None or item is True or item not in self.selection_boxes:
|
6218
|
-
return
|
6453
|
+
return False
|
6219
6454
|
box = self.selection_boxes.pop(item)
|
6220
6455
|
self.hide_box(box.fill_iid)
|
6221
6456
|
self.hide_box(box.bd_iid)
|
@@ -6465,50 +6700,30 @@ class MainTable(tk.Canvas):
|
|
6465
6700
|
def recreate_all_selection_boxes(self) -> None:
|
6466
6701
|
if not self.selected:
|
6467
6702
|
return
|
6703
|
+
|
6468
6704
|
modified = False
|
6705
|
+
row_limit = len(self.row_positions) - 1
|
6706
|
+
col_limit = len(self.col_positions) - 1
|
6707
|
+
|
6469
6708
|
for item, box in self.get_selection_items():
|
6470
6709
|
r1, c1, r2, c2 = box.coords
|
6471
|
-
|
6472
|
-
|
6473
|
-
|
6474
|
-
|
6475
|
-
|
6476
|
-
|
6477
|
-
|
6478
|
-
if r1 >= len(self.row_positions) - 1:
|
6479
|
-
if len(self.row_positions) > 1:
|
6480
|
-
r1 = len(self.row_positions) - 2
|
6481
|
-
else:
|
6482
|
-
r1 = 0
|
6483
|
-
if c1 >= len(self.col_positions) - 1:
|
6484
|
-
if len(self.col_positions) > 1:
|
6485
|
-
c1 = len(self.col_positions) - 2
|
6486
|
-
else:
|
6487
|
-
c1 = 0
|
6488
|
-
if r2 > len(self.row_positions) - 1:
|
6489
|
-
r2 = len(self.row_positions) - 1
|
6490
|
-
if c2 > len(self.col_positions) - 1:
|
6491
|
-
c2 = len(self.col_positions) - 1
|
6710
|
+
# check coordinates
|
6711
|
+
r1 = min(r1, row_limit - (1 if row_limit > 0 else 0))
|
6712
|
+
c1 = min(c1, col_limit - (1 if col_limit > 0 else 0))
|
6713
|
+
r2 = min(r2, row_limit)
|
6714
|
+
c2 = min(c2, col_limit)
|
6715
|
+
|
6716
|
+
modified = modified or (r1 >= row_limit or c1 >= col_limit or r2 > row_limit or c2 > col_limit)
|
6492
6717
|
self.recreate_selection_box(r1, c1, r2, c2, item, run_binding=False)
|
6493
6718
|
|
6494
6719
|
if self.selected:
|
6495
|
-
r = self.selected.row
|
6496
|
-
c
|
6497
|
-
|
6498
|
-
self.set_currently_selected(
|
6499
|
-
r,
|
6500
|
-
c,
|
6501
|
-
item=self.selected.fill_iid,
|
6502
|
-
run_binding=False,
|
6503
|
-
)
|
6720
|
+
r, c = self.selected.row, self.selected.column
|
6721
|
+
if r < row_limit and c < col_limit:
|
6722
|
+
self.set_currently_selected(r, c, item=self.selected.fill_iid, run_binding=False)
|
6504
6723
|
else:
|
6505
6724
|
box = self.selection_boxes[self.selected.fill_iid]
|
6506
|
-
self.set_currently_selected(
|
6507
|
-
|
6508
|
-
box.coords.from_c,
|
6509
|
-
item=box.fill_iid,
|
6510
|
-
run_binding=False,
|
6511
|
-
)
|
6725
|
+
self.set_currently_selected(box.coords[0], box.coords[1], item=box.fill_iid, run_binding=False)
|
6726
|
+
|
6512
6727
|
if modified:
|
6513
6728
|
self.PAR.emit_event(
|
6514
6729
|
"<<SheetSelect>>",
|
@@ -6535,23 +6750,17 @@ class MainTable(tk.Canvas):
|
|
6535
6750
|
return d
|
6536
6751
|
|
6537
6752
|
def get_selected_min_max(self) -> tuple[int, int, int, int] | tuple[None, None, None, None]:
|
6538
|
-
|
6539
|
-
|
6540
|
-
|
6541
|
-
max_y = 0
|
6542
|
-
|
6753
|
+
if not self.get_selection_items():
|
6754
|
+
return None, None, None, None
|
6755
|
+
min_y, min_x = float("inf"), float("inf")
|
6756
|
+
max_y, max_x = 0, 0
|
6757
|
+
|
6758
|
+
for _, box in self.get_selection_items():
|
6543
6759
|
r1, c1, r2, c2 = box.coords
|
6544
|
-
|
6545
|
-
|
6546
|
-
|
6547
|
-
|
6548
|
-
if r2 > max_y:
|
6549
|
-
max_y = r2
|
6550
|
-
if c2 > max_x:
|
6551
|
-
max_x = c2
|
6552
|
-
if min_x != float("inf") and min_y != float("inf") and max_x > 0 and max_y > 0:
|
6553
|
-
return min_y, min_x, max_y, max_x
|
6554
|
-
return None, None, None, None
|
6760
|
+
min_y, min_x = min(min_y, r1), min(min_x, c1)
|
6761
|
+
max_y, max_x = max(max_y, r2), max(max_x, c2)
|
6762
|
+
|
6763
|
+
return (min_y, min_x, max_y, max_x) if min_y != float("inf") else (None, None, None, None)
|
6555
6764
|
|
6556
6765
|
def get_selected_rows(
|
6557
6766
|
self,
|
@@ -6706,7 +6915,7 @@ class MainTable(tk.Canvas):
|
|
6706
6915
|
elif self.get_cell_kwargs(datarn, datacn, key="dropdown") or self.get_cell_kwargs(
|
6707
6916
|
datarn, datacn, key="checkbox"
|
6708
6917
|
):
|
6709
|
-
if
|
6918
|
+
if event_opens_dropdown_or_checkbox(event):
|
6710
6919
|
if self.get_cell_kwargs(datarn, datacn, key="dropdown"):
|
6711
6920
|
self.open_dropdown_window(r, c, event=event)
|
6712
6921
|
elif self.get_cell_kwargs(datarn, datacn, key="checkbox"):
|
@@ -6714,27 +6923,6 @@ class MainTable(tk.Canvas):
|
|
6714
6923
|
else:
|
6715
6924
|
self.open_text_editor(event=event, r=r, c=c, dropdown=False)
|
6716
6925
|
|
6717
|
-
def event_opens_dropdown_or_checkbox(self, event=None) -> bool:
|
6718
|
-
if event is None:
|
6719
|
-
return False
|
6720
|
-
elif event == "rc":
|
6721
|
-
return True
|
6722
|
-
elif (
|
6723
|
-
(hasattr(event, "keysym") and event.keysym == "Return")
|
6724
|
-
or (hasattr(event, "keysym") and event.keysym == "F2")
|
6725
|
-
or (
|
6726
|
-
event is not None
|
6727
|
-
and hasattr(event, "keycode")
|
6728
|
-
and event.keycode == "??"
|
6729
|
-
and hasattr(event, "num")
|
6730
|
-
and event.num == 1
|
6731
|
-
) # mouseclick
|
6732
|
-
or (hasattr(event, "keysym") and event.keysym == "BackSpace")
|
6733
|
-
):
|
6734
|
-
return True
|
6735
|
-
else:
|
6736
|
-
return False
|
6737
|
-
|
6738
6926
|
# displayed indexes
|
6739
6927
|
def get_cell_align(self, r: int, c: int) -> str:
|
6740
6928
|
datarn = self.datarn(r)
|
@@ -6754,27 +6942,16 @@ class MainTable(tk.Canvas):
|
|
6754
6942
|
state: str = "normal",
|
6755
6943
|
dropdown: bool = False,
|
6756
6944
|
) -> bool:
|
6757
|
-
text =
|
6945
|
+
text = f"{self.get_cell_data(self.datarn(r), self.datacn(c), none_to_empty_str=True)}"
|
6758
6946
|
extra_func_key = "??"
|
6759
|
-
if
|
6760
|
-
if event
|
6761
|
-
|
6762
|
-
|
6763
|
-
|
6764
|
-
|
6765
|
-
|
6766
|
-
|
6767
|
-
text = ""
|
6768
|
-
else:
|
6769
|
-
text = f"{self.get_cell_data(self.datarn(r), self.datacn(c), none_to_empty_str = True)}"
|
6770
|
-
elif event is not None and (
|
6771
|
-
(hasattr(event, "char") and event.char.isalpha())
|
6772
|
-
or (hasattr(event, "char") and event.char.isdigit())
|
6773
|
-
or (hasattr(event, "char") and event.char in symbols_set)
|
6774
|
-
):
|
6775
|
-
extra_func_key = event.char
|
6776
|
-
text = event.char
|
6777
|
-
else:
|
6947
|
+
if event_opens_dropdown_or_checkbox(event):
|
6948
|
+
if hasattr(event, "keysym") and event.keysym in ("Return", "F2", "BackSpace"):
|
6949
|
+
extra_func_key = event.keysym
|
6950
|
+
if event.keysym == "BackSpace":
|
6951
|
+
text = ""
|
6952
|
+
elif event_has_char_key(event):
|
6953
|
+
extra_func_key = text = event.char
|
6954
|
+
elif event is not None:
|
6778
6955
|
return False
|
6779
6956
|
if self.extra_begin_edit_cell_func:
|
6780
6957
|
try:
|
@@ -6797,12 +6974,11 @@ class MainTable(tk.Canvas):
|
|
6797
6974
|
return False
|
6798
6975
|
else:
|
6799
6976
|
text = text if isinstance(text, str) else f"{text}"
|
6800
|
-
text = "" if text is None else text
|
6801
6977
|
if self.PAR.ops.cell_auto_resize_enabled:
|
6802
6978
|
self.set_cell_size_to_text(r, c, only_if_too_small=True, redraw=True, run_binding=True)
|
6803
6979
|
if self.text_editor.open and (r, c) == self.text_editor.coords:
|
6804
6980
|
self.text_editor.window.set_text(self.text_editor.get() + "" if not isinstance(text, str) else text)
|
6805
|
-
return
|
6981
|
+
return False
|
6806
6982
|
self.hide_text_editor()
|
6807
6983
|
if not self.see(r=r, c=c, check_cell_visibility=True):
|
6808
6984
|
self.refresh()
|
@@ -6810,8 +6986,6 @@ class MainTable(tk.Canvas):
|
|
6810
6986
|
y = self.row_positions[r]
|
6811
6987
|
w = self.col_positions[c + 1] - x + 1
|
6812
6988
|
h = self.row_positions[r + 1] - y + 1
|
6813
|
-
if text is None:
|
6814
|
-
text = f"{self.get_cell_data(self.datarn(r), self.datacn(c), none_to_empty_str = True)}"
|
6815
6989
|
kwargs = {
|
6816
6990
|
"menu_kwargs": DotDict(
|
6817
6991
|
{
|