tksheet 7.0.6__py3-none-any.whl → 7.1.0__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 +96 -96
- tksheet/column_headers.py +252 -270
- tksheet/functions.py +37 -9
- tksheet/main_table.py +743 -795
- tksheet/other_classes.py +129 -4
- tksheet/row_index.py +470 -316
- tksheet/sheet.py +994 -177
- tksheet/sheet_options.py +34 -0
- tksheet/text_editor.py +93 -78
- tksheet/themes.py +104 -0
- tksheet/vars.py +35 -0
- {tksheet-7.0.6.dist-info → tksheet-7.1.0.dist-info}/METADATA +1 -1
- tksheet-7.1.0.dist-info/RECORD +20 -0
- {tksheet-7.0.6.dist-info → tksheet-7.1.0.dist-info}/WHEEL +1 -1
- tksheet-7.0.6.dist-info/RECORD +0 -20
- {tksheet-7.0.6.dist-info → tksheet-7.1.0.dist-info}/LICENSE.txt +0 -0
- {tksheet-7.0.6.dist-info → tksheet-7.1.0.dist-info}/top_level.txt +0 -0
tksheet/row_index.py
CHANGED
@@ -4,6 +4,7 @@ import tkinter as tk
|
|
4
4
|
from collections import defaultdict
|
5
5
|
from collections.abc import (
|
6
6
|
Callable,
|
7
|
+
Generator,
|
7
8
|
)
|
8
9
|
from functools import (
|
9
10
|
partial,
|
@@ -27,7 +28,6 @@ from .formatters import (
|
|
27
28
|
)
|
28
29
|
from .functions import (
|
29
30
|
consecutive_chunks,
|
30
|
-
coords_tag_to_int_tuple,
|
31
31
|
ev_stack_dict,
|
32
32
|
event_dict,
|
33
33
|
get_checkbox_points,
|
@@ -39,6 +39,9 @@ from .functions import (
|
|
39
39
|
from .other_classes import (
|
40
40
|
DotDict,
|
41
41
|
DraggedRowColumn,
|
42
|
+
DropdownStorage,
|
43
|
+
Node,
|
44
|
+
TextEditorStorage,
|
42
45
|
)
|
43
46
|
from .text_editor import (
|
44
47
|
TextEditor,
|
@@ -65,12 +68,7 @@ class RowIndex(tk.Canvas):
|
|
65
68
|
self.popup_menu_loc = None
|
66
69
|
self.extra_begin_edit_cell_func = None
|
67
70
|
self.extra_end_edit_cell_func = None
|
68
|
-
self.text_editor = None
|
69
|
-
self.text_editor_id = None
|
70
|
-
self.text_editor_loc = None
|
71
71
|
self.b1_pressed_loc = None
|
72
|
-
self.existing_dropdown_canvas_id = None
|
73
|
-
self.existing_dropdown_window = None
|
74
72
|
self.closed_dropdown = None
|
75
73
|
self.centre_alignment_text_mod_indexes = (slice(1, None), slice(None, -1))
|
76
74
|
self.c_align_cyc = cycle(self.centre_alignment_text_mod_indexes)
|
@@ -106,6 +104,8 @@ class RowIndex(tk.Canvas):
|
|
106
104
|
self.currently_resizing_width = False
|
107
105
|
self.currently_resizing_height = False
|
108
106
|
self.ri_rc_popup_menu = None
|
107
|
+
self.dropdown = DropdownStorage()
|
108
|
+
self.text_editor = TextEditorStorage()
|
109
109
|
|
110
110
|
self.disp_text = {}
|
111
111
|
self.disp_high = {}
|
@@ -115,6 +115,7 @@ class RowIndex(tk.Canvas):
|
|
115
115
|
self.disp_resize_lines = {}
|
116
116
|
self.disp_dropdown = {}
|
117
117
|
self.disp_checkbox = {}
|
118
|
+
self.disp_boxes = set()
|
118
119
|
self.hidd_text = {}
|
119
120
|
self.hidd_high = {}
|
120
121
|
self.hidd_grid = {}
|
@@ -123,9 +124,12 @@ class RowIndex(tk.Canvas):
|
|
123
124
|
self.hidd_resize_lines = {}
|
124
125
|
self.hidd_dropdown = {}
|
125
126
|
self.hidd_checkbox = {}
|
127
|
+
self.hidd_boxes = set()
|
126
128
|
|
127
129
|
self.align = kwargs["row_index_align"]
|
128
130
|
self.default_index = kwargs["default_row_index"].lower()
|
131
|
+
|
132
|
+
self.reset_tree()
|
129
133
|
self.basic_bindings()
|
130
134
|
|
131
135
|
def basic_bindings(self, enable: bool = True) -> None:
|
@@ -144,6 +148,18 @@ class RowIndex(tk.Canvas):
|
|
144
148
|
self.unbind("<Double-Button-1>")
|
145
149
|
self.unbind(rc_binding)
|
146
150
|
|
151
|
+
def reset_tree(self) -> None:
|
152
|
+
# treeview mode
|
153
|
+
self.tree = {}
|
154
|
+
self.tree_open_ids = set()
|
155
|
+
self.tree_rns = {}
|
156
|
+
if self.MT:
|
157
|
+
self.MT.displayed_rows = []
|
158
|
+
self.MT._row_index = []
|
159
|
+
self.MT.data = []
|
160
|
+
self.MT.row_positions = [0]
|
161
|
+
self.MT.saved_row_heights = {}
|
162
|
+
|
147
163
|
def set_width(self, new_width: int, set_TL: bool = False) -> None:
|
148
164
|
self.current_width = new_width
|
149
165
|
try:
|
@@ -218,14 +234,17 @@ class RowIndex(tk.Canvas):
|
|
218
234
|
if r < len(self.MT.row_positions) - 1:
|
219
235
|
r_selected = self.MT.row_selected(r)
|
220
236
|
if not r_selected and self.row_selection_enabled:
|
221
|
-
|
222
|
-
|
223
|
-
|
224
|
-
|
225
|
-
|
237
|
+
if self.MT.selected and self.MT.selected.type_ == "rows":
|
238
|
+
self.being_drawn_item = self.MT.recreate_selection_box(
|
239
|
+
*self.get_shift_select_box(r, self.MT.selected.row),
|
240
|
+
fill_iid=self.MT.selected.fill_iid,
|
241
|
+
)
|
226
242
|
else:
|
227
|
-
self.being_drawn_item = self.add_selection(
|
228
|
-
|
243
|
+
self.being_drawn_item = self.add_selection(
|
244
|
+
r,
|
245
|
+
run_binding_func=False,
|
246
|
+
set_as_current=True,
|
247
|
+
)
|
229
248
|
self.MT.main_table_redraw_grid_and_text(redraw_header=True, redraw_row_index=True)
|
230
249
|
if self.ctrl_selection_binding_func is not None:
|
231
250
|
self.ctrl_selection_binding_func(
|
@@ -247,14 +266,13 @@ class RowIndex(tk.Canvas):
|
|
247
266
|
if r < len(self.MT.row_positions) - 1:
|
248
267
|
r_selected = self.MT.row_selected(r)
|
249
268
|
if not r_selected and self.row_selection_enabled:
|
250
|
-
|
251
|
-
|
269
|
+
if self.MT.selected and self.MT.selected.type_ == "rows":
|
270
|
+
r_to_sel, c_to_sel = self.MT.selected.row, self.MT.selected.column
|
252
271
|
self.MT.deselect("all", redraw=False)
|
253
|
-
|
254
|
-
self.
|
272
|
+
self.being_drawn_item = self.MT.create_selection_box(*self.get_shift_select_box(r, r_to_sel))
|
273
|
+
self.MT.set_currently_selected(r_to_sel, c_to_sel, self.being_drawn_item)
|
255
274
|
else:
|
256
|
-
self.being_drawn_item = self.
|
257
|
-
box = self.MT.get_box_from_item(self.being_drawn_item, get_dict=True)
|
275
|
+
self.being_drawn_item = self.select_row(r, run_binding_func=False)
|
258
276
|
self.MT.main_table_redraw_grid_and_text(redraw_header=True, redraw_row_index=True)
|
259
277
|
if self.shift_selection_binding_func is not None:
|
260
278
|
self.shift_selection_binding_func(
|
@@ -266,11 +284,11 @@ class RowIndex(tk.Canvas):
|
|
266
284
|
to_move=sorted(self.MT.get_selected_rows()),
|
267
285
|
)
|
268
286
|
|
269
|
-
def
|
287
|
+
def get_shift_select_box(self, r: int, min_r: int) -> tuple[int, int, int, int, str]:
|
270
288
|
if r > min_r:
|
271
|
-
return
|
289
|
+
return min_r, 0, r + 1, len(self.MT.col_positions) - 1
|
272
290
|
elif r < min_r:
|
273
|
-
return
|
291
|
+
return r, 0, min_r + 1, len(self.MT.col_positions) - 1
|
274
292
|
|
275
293
|
def create_resize_line(
|
276
294
|
self,
|
@@ -388,6 +406,8 @@ class RowIndex(tk.Canvas):
|
|
388
406
|
or self.edit_cell_enabled
|
389
407
|
):
|
390
408
|
self.open_cell(event)
|
409
|
+
elif (iid := self.event_over_tree_arrow(r, self.canvasy(event.y), event.x)) is not None:
|
410
|
+
self.PAR.item(iid, open_=iid not in self.tree_open_ids)
|
391
411
|
self.rsz_h = None
|
392
412
|
self.mouse_motion(event)
|
393
413
|
if self.extra_double_b1_func is not None:
|
@@ -473,7 +493,7 @@ class RowIndex(tk.Canvas):
|
|
473
493
|
y = self.canvasy(event.y)
|
474
494
|
size = y - self.MT.row_positions[self.rsz_h - 1]
|
475
495
|
if size >= self.MT.min_row_height and size < self.MT.max_row_height:
|
476
|
-
self.
|
496
|
+
self.hide_resize_and_ctrl_lines(ctrl_lines=False)
|
477
497
|
line2y = self.MT.row_positions[self.rsz_h - 1]
|
478
498
|
self.create_resize_line(
|
479
499
|
0,
|
@@ -505,7 +525,7 @@ class RowIndex(tk.Canvas):
|
|
505
525
|
)
|
506
526
|
elif self.width_resizing_enabled and self.rsz_w is not None and self.currently_resizing_width:
|
507
527
|
evx = event.x
|
508
|
-
self.
|
528
|
+
self.hide_resize_and_ctrl_lines(ctrl_lines=False)
|
509
529
|
if evx > self.current_width:
|
510
530
|
x = self.MT.canvasx(evx - self.current_width)
|
511
531
|
if evx > self.MT.max_index_width:
|
@@ -540,20 +560,21 @@ class RowIndex(tk.Canvas):
|
|
540
560
|
):
|
541
561
|
need_redraw = False
|
542
562
|
end_row = self.MT.identify_row(y=event.y)
|
543
|
-
|
544
|
-
|
545
|
-
|
546
|
-
box = self.get_b1_motion_box(currently_selected.row, end_row)
|
563
|
+
if end_row < len(self.MT.row_positions) - 1 and self.MT.selected:
|
564
|
+
if self.MT.selected.type_ == "rows":
|
565
|
+
box = self.get_b1_motion_box(self.MT.selected.row, end_row)
|
547
566
|
if (
|
548
567
|
box is not None
|
549
568
|
and self.being_drawn_item is not None
|
550
|
-
and self.MT.
|
569
|
+
and self.MT.coords_and_type(self.being_drawn_item) != box
|
551
570
|
):
|
552
|
-
self.MT.deselect("all", redraw=False)
|
553
571
|
if box[2] - box[0] != 1:
|
554
|
-
self.being_drawn_item = self.MT.
|
572
|
+
self.being_drawn_item = self.MT.recreate_selection_box(
|
573
|
+
*box[:-1],
|
574
|
+
fill_iid=self.MT.selected.fill_iid,
|
575
|
+
)
|
555
576
|
else:
|
556
|
-
self.being_drawn_item = self.select_row(
|
577
|
+
self.being_drawn_item = self.select_row(self.MT.selected.row, run_binding_func=False)
|
557
578
|
need_redraw = True
|
558
579
|
if self.drag_selection_binding_func is not None:
|
559
580
|
self.drag_selection_binding_func(
|
@@ -568,9 +589,9 @@ class RowIndex(tk.Canvas):
|
|
568
589
|
|
569
590
|
def get_b1_motion_box(self, start_row, end_row):
|
570
591
|
if end_row >= start_row:
|
571
|
-
return
|
592
|
+
return start_row, 0, end_row + 1, len(self.MT.col_positions) - 1, "rows"
|
572
593
|
elif end_row < start_row:
|
573
|
-
return
|
594
|
+
return end_row, 0, start_row + 1, len(self.MT.col_positions) - 1, "rows"
|
574
595
|
|
575
596
|
def ctrl_b1_motion(self, event: object):
|
576
597
|
x1, y1, x2, y2 = self.MT.get_canvas_visible_area()
|
@@ -599,20 +620,22 @@ class RowIndex(tk.Canvas):
|
|
599
620
|
):
|
600
621
|
need_redraw = False
|
601
622
|
end_row = self.MT.identify_row(y=event.y)
|
602
|
-
|
603
|
-
|
604
|
-
|
605
|
-
box = self.get_b1_motion_box(currently_selected.row, end_row)
|
623
|
+
if end_row < len(self.MT.row_positions) - 1 and self.MT.selected:
|
624
|
+
if self.MT.selected.type_ == "rows":
|
625
|
+
box = self.get_b1_motion_box(self.MT.selected.row, end_row)
|
606
626
|
if (
|
607
627
|
box is not None
|
608
628
|
and self.being_drawn_item is not None
|
609
|
-
and self.MT.
|
629
|
+
and self.MT.coords_and_type(self.being_drawn_item) != box
|
610
630
|
):
|
611
|
-
self.MT.delete_item(self.being_drawn_item)
|
612
631
|
if box[2] - box[0] != 1:
|
613
|
-
self.being_drawn_item = self.MT.
|
632
|
+
self.being_drawn_item = self.MT.recreate_selection_box(
|
633
|
+
*box[:-1],
|
634
|
+
self.MT.selected.fill_iid,
|
635
|
+
)
|
614
636
|
else:
|
615
|
-
self.
|
637
|
+
self.MT.hide_selection_box(self.MT.selected.fill_iid)
|
638
|
+
self.being_drawn_item = self.add_selection(box[0], run_binding_func=False)
|
616
639
|
need_redraw = True
|
617
640
|
if self.drag_selection_binding_func is not None:
|
618
641
|
self.drag_selection_binding_func(
|
@@ -667,7 +690,7 @@ class RowIndex(tk.Canvas):
|
|
667
690
|
x2,
|
668
691
|
rows,
|
669
692
|
):
|
670
|
-
self.
|
693
|
+
self.hide_resize_and_ctrl_lines()
|
671
694
|
self.create_resize_line(
|
672
695
|
0,
|
673
696
|
ypos,
|
@@ -687,7 +710,7 @@ class RowIndex(tk.Canvas):
|
|
687
710
|
delete_on_timer=False,
|
688
711
|
)
|
689
712
|
|
690
|
-
def
|
713
|
+
def hide_resize_and_ctrl_lines(self, ctrl_lines=True):
|
691
714
|
self.delete_resize_lines()
|
692
715
|
self.MT.delete_resize_lines()
|
693
716
|
if ctrl_lines:
|
@@ -723,7 +746,7 @@ class RowIndex(tk.Canvas):
|
|
723
746
|
if len(ycheck) > 1 and ycheck[1] > 1:
|
724
747
|
self.MT.set_yviews("moveto", 1)
|
725
748
|
|
726
|
-
def event_over_dropdown(self, r, datarn, event: object, canvasy):
|
749
|
+
def event_over_dropdown(self, r: int, datarn: int, event: object, canvasy: float) -> bool:
|
727
750
|
if (
|
728
751
|
canvasy < self.MT.row_positions[r] + self.MT.index_txt_height
|
729
752
|
and self.get_cell_kwargs(datarn, key="dropdown")
|
@@ -732,7 +755,7 @@ class RowIndex(tk.Canvas):
|
|
732
755
|
return True
|
733
756
|
return False
|
734
757
|
|
735
|
-
def event_over_checkbox(self, r, datarn, event: object, canvasy):
|
758
|
+
def event_over_checkbox(self, r: int, datarn: int, event: object, canvasy: float) -> bool:
|
736
759
|
if (
|
737
760
|
canvasy < self.MT.row_positions[r] + self.MT.index_txt_height
|
738
761
|
and self.get_cell_kwargs(datarn, key="checkbox")
|
@@ -741,13 +764,17 @@ class RowIndex(tk.Canvas):
|
|
741
764
|
return True
|
742
765
|
return False
|
743
766
|
|
744
|
-
def b1_release(self, event: object):
|
767
|
+
def b1_release(self, event: object) -> None:
|
745
768
|
if self.being_drawn_item is not None:
|
746
|
-
|
747
|
-
|
748
|
-
self.MT.
|
769
|
+
to_sel = self.MT.coords_and_type(self.being_drawn_item)
|
770
|
+
r_to_sel, c_to_sel = self.MT.selected.row, self.MT.selected.column
|
771
|
+
self.MT.hide_selection_box(self.being_drawn_item)
|
749
772
|
self.being_drawn_item = None
|
750
|
-
self.MT.
|
773
|
+
self.MT.set_currently_selected(
|
774
|
+
r_to_sel,
|
775
|
+
c_to_sel,
|
776
|
+
item=self.MT.create_selection_box(*to_sel, set_current=False),
|
777
|
+
)
|
751
778
|
if self.drag_selection_binding_func is not None:
|
752
779
|
self.drag_selection_binding_func(
|
753
780
|
self.MT.get_select_event(being_drawn_item=self.being_drawn_item),
|
@@ -756,7 +783,7 @@ class RowIndex(tk.Canvas):
|
|
756
783
|
if self.height_resizing_enabled and self.rsz_h is not None and self.currently_resizing_height:
|
757
784
|
self.currently_resizing_height = False
|
758
785
|
new_row_pos = int(self.coords("rhl")[1])
|
759
|
-
self.
|
786
|
+
self.hide_resize_and_ctrl_lines(ctrl_lines=False)
|
760
787
|
old_height = self.MT.row_positions[self.rsz_h] - self.MT.row_positions[self.rsz_h - 1]
|
761
788
|
size = new_row_pos - self.MT.row_positions[self.rsz_h - 1]
|
762
789
|
if size < self.MT.min_row_height:
|
@@ -782,7 +809,7 @@ class RowIndex(tk.Canvas):
|
|
782
809
|
)
|
783
810
|
elif self.width_resizing_enabled and self.rsz_w is not None and self.currently_resizing_width:
|
784
811
|
self.currently_resizing_width = False
|
785
|
-
self.
|
812
|
+
self.hide_resize_and_ctrl_lines(ctrl_lines=False)
|
786
813
|
self.set_width(self.new_row_width, set_TL=True)
|
787
814
|
self.MT.main_table_redraw_grid_and_text(redraw_header=True, redraw_row_index=True)
|
788
815
|
if (
|
@@ -794,7 +821,7 @@ class RowIndex(tk.Canvas):
|
|
794
821
|
and self.dragged_row is not None
|
795
822
|
and self.find_withtag("move_rows")
|
796
823
|
):
|
797
|
-
self.
|
824
|
+
self.hide_resize_and_ctrl_lines()
|
798
825
|
r = self.MT.identify_row(y=event.y)
|
799
826
|
totalrows = len(self.dragged_row.to_move)
|
800
827
|
if (
|
@@ -812,7 +839,7 @@ class RowIndex(tk.Canvas):
|
|
812
839
|
name="move_rows",
|
813
840
|
sheet=self.PAR.name,
|
814
841
|
boxes=self.MT.get_boxes(),
|
815
|
-
selected=self.MT.
|
842
|
+
selected=self.MT.selected,
|
816
843
|
value=r,
|
817
844
|
)
|
818
845
|
if try_binding(self.ri_extra_begin_drag_drop_func, event_data, "begin_move_rows"):
|
@@ -847,6 +874,8 @@ class RowIndex(tk.Canvas):
|
|
847
874
|
r, datarn, event, canvasy
|
848
875
|
):
|
849
876
|
self.open_cell(event)
|
877
|
+
elif (iid := self.event_over_tree_arrow(r, canvasy, event.x)) is not None:
|
878
|
+
self.PAR.item(iid, open_=iid not in self.tree_open_ids)
|
850
879
|
else:
|
851
880
|
self.mouseclick_outside_editor_or_dropdown_all_canvases(inside=True)
|
852
881
|
self.b1_pressed_loc = None
|
@@ -860,14 +889,30 @@ class RowIndex(tk.Canvas):
|
|
860
889
|
if self.extra_b1_release_func is not None:
|
861
890
|
self.extra_b1_release_func(event)
|
862
891
|
|
892
|
+
def event_over_tree_arrow(
|
893
|
+
self,
|
894
|
+
r: int,
|
895
|
+
canvasy: float,
|
896
|
+
eventx: int,
|
897
|
+
) -> bool:
|
898
|
+
if self.PAR.ops.treeview and (
|
899
|
+
canvasy < self.MT.row_positions[r] + self.MT.index_txt_height + 3
|
900
|
+
and isinstance(self.MT._row_index, list)
|
901
|
+
and (datarn := self.MT.datarn(r)) < len(self.MT._row_index)
|
902
|
+
and eventx
|
903
|
+
< self.get_treeview_indent((iid := self.MT._row_index[datarn].iid)) + self.MT.index_txt_height + 1
|
904
|
+
):
|
905
|
+
return iid
|
906
|
+
return None
|
907
|
+
|
863
908
|
def toggle_select_row(
|
864
909
|
self,
|
865
|
-
row,
|
866
|
-
add_selection=True,
|
867
|
-
redraw=True,
|
868
|
-
run_binding_func=True,
|
869
|
-
set_as_current=True,
|
870
|
-
):
|
910
|
+
row: int,
|
911
|
+
add_selection: bool = True,
|
912
|
+
redraw: bool = True,
|
913
|
+
run_binding_func: bool = True,
|
914
|
+
set_as_current: bool = True,
|
915
|
+
) -> int | None:
|
871
916
|
if add_selection:
|
872
917
|
if self.MT.row_selected(row):
|
873
918
|
fill_iid = self.MT.deselect(r=row, redraw=redraw)
|
@@ -885,7 +930,7 @@ class RowIndex(tk.Canvas):
|
|
885
930
|
fill_iid = self.select_row(row, redraw=redraw)
|
886
931
|
return fill_iid
|
887
932
|
|
888
|
-
def select_row(self, r, redraw=False, run_binding_func=True):
|
933
|
+
def select_row(self, r: int, redraw: bool = False, run_binding_func: bool = True) -> int:
|
889
934
|
self.MT.deselect("all", redraw=False)
|
890
935
|
box = (r, 0, r + 1, len(self.MT.col_positions) - 1, "rows")
|
891
936
|
fill_iid = self.MT.create_selection_box(*box)
|
@@ -895,7 +940,13 @@ class RowIndex(tk.Canvas):
|
|
895
940
|
self.MT.run_selection_binding("rows")
|
896
941
|
return fill_iid
|
897
942
|
|
898
|
-
def add_selection(
|
943
|
+
def add_selection(
|
944
|
+
self,
|
945
|
+
r: int,
|
946
|
+
redraw: bool = False,
|
947
|
+
run_binding_func: bool = True,
|
948
|
+
set_as_current: bool = True,
|
949
|
+
) -> int:
|
899
950
|
box = (r, 0, r + 1, len(self.MT.col_positions) - 1, "rows")
|
900
951
|
fill_iid = self.MT.create_selection_box(*box, set_current=set_as_current)
|
901
952
|
if redraw:
|
@@ -904,7 +955,33 @@ class RowIndex(tk.Canvas):
|
|
904
955
|
self.MT.run_selection_binding("rows")
|
905
956
|
return fill_iid
|
906
957
|
|
907
|
-
def
|
958
|
+
def display_box(
|
959
|
+
self,
|
960
|
+
x1: int,
|
961
|
+
y1: int,
|
962
|
+
x2: int,
|
963
|
+
y2: int,
|
964
|
+
fill: str,
|
965
|
+
outline: str,
|
966
|
+
state: str,
|
967
|
+
tags: str | tuple[str],
|
968
|
+
) -> int:
|
969
|
+
if self.hidd_boxes:
|
970
|
+
iid = self.hidd_boxes.pop()
|
971
|
+
self.coords(iid, x1, y1, x2, y2)
|
972
|
+
self.itemconfig(iid, fill=fill, outline=outline, state=state, tags=tags)
|
973
|
+
else:
|
974
|
+
iid = self.create_rectangle(x1, y1, x2, y2, fill=fill, outline=outline, state=state, tags=tags)
|
975
|
+
self.disp_boxes.add(iid)
|
976
|
+
return iid
|
977
|
+
|
978
|
+
def hide_box(self, item: int | None) -> None:
|
979
|
+
if isinstance(item, int):
|
980
|
+
self.disp_boxes.discard(item)
|
981
|
+
self.hidd_boxes.add(item)
|
982
|
+
self.itemconfig(item, state="hidden")
|
983
|
+
|
984
|
+
def get_cell_dimensions(self, datarn: int) -> tuple[int, int]:
|
908
985
|
txt = self.get_valid_cell_data_as_str(datarn, fix=False)
|
909
986
|
if txt:
|
910
987
|
self.MT.txt_measure_canvas.itemconfig(
|
@@ -917,18 +994,26 @@ class RowIndex(tk.Canvas):
|
|
917
994
|
w = self.PAR.ops.default_row_index_width
|
918
995
|
h = self.MT.min_row_height
|
919
996
|
if self.get_cell_kwargs(datarn, key="dropdown") or self.get_cell_kwargs(datarn, key="checkbox"):
|
920
|
-
|
997
|
+
w += self.MT.index_txt_height
|
998
|
+
if self.PAR.ops.treeview:
|
999
|
+
if datarn in self.cell_options and "align" in self.cell_options[datarn]:
|
1000
|
+
align = self.cell_options[datarn]["align"]
|
1001
|
+
else:
|
1002
|
+
align = self.align
|
1003
|
+
if align == "w":
|
1004
|
+
w += self.MT.index_txt_height
|
1005
|
+
w += self.get_treeview_indent(self.MT._row_index[datarn].iid)
|
921
1006
|
return w, h
|
922
1007
|
|
923
1008
|
def set_row_height(
|
924
1009
|
self,
|
925
|
-
row,
|
926
|
-
height=None,
|
927
|
-
only_set_if_too_small=False,
|
928
|
-
recreate=True,
|
929
|
-
return_new_height=False,
|
930
|
-
displayed_only=False,
|
931
|
-
):
|
1010
|
+
row: int,
|
1011
|
+
height: None | int = None,
|
1012
|
+
only_set_if_too_small: bool = False,
|
1013
|
+
recreate: bool = True,
|
1014
|
+
return_new_height: bool = False,
|
1015
|
+
displayed_only: bool = False,
|
1016
|
+
) -> int:
|
932
1017
|
r_norm = row + 1
|
933
1018
|
r_extra = row + 2
|
934
1019
|
min_rh = self.MT.min_row_height
|
@@ -991,7 +1076,12 @@ class RowIndex(tk.Canvas):
|
|
991
1076
|
self.MT.recreate_all_selection_boxes()
|
992
1077
|
return new_height
|
993
1078
|
|
994
|
-
def set_width_of_index_to_text(
|
1079
|
+
def set_width_of_index_to_text(
|
1080
|
+
self,
|
1081
|
+
text: None | str = None,
|
1082
|
+
only_rows: list = [],
|
1083
|
+
set_width: bool = True,
|
1084
|
+
) -> None | int:
|
995
1085
|
if (
|
996
1086
|
text is None
|
997
1087
|
and not self.MT._row_index
|
@@ -1015,7 +1105,9 @@ class RowIndex(tk.Canvas):
|
|
1015
1105
|
else:
|
1016
1106
|
w = self.PAR.ops.default_row_index_width
|
1017
1107
|
else:
|
1018
|
-
if
|
1108
|
+
if only_rows:
|
1109
|
+
iterable = only_rows
|
1110
|
+
elif self.MT.all_rows_displayed:
|
1019
1111
|
if isinstance(self.MT._row_index, list):
|
1020
1112
|
iterable = range(len(self.MT._row_index))
|
1021
1113
|
else:
|
@@ -1029,10 +1121,6 @@ class RowIndex(tk.Canvas):
|
|
1029
1121
|
w = int(self.MT.min_column_width)
|
1030
1122
|
elif w > self.MT.max_index_width:
|
1031
1123
|
w = int(self.MT.max_index_width)
|
1032
|
-
if self.get_cell_kwargs(datarn, key="checkbox"):
|
1033
|
-
w += self.MT.index_txt_height + 6
|
1034
|
-
elif self.get_cell_kwargs(datarn, key="dropdown"):
|
1035
|
-
w += self.MT.index_txt_height + 4
|
1036
1124
|
if w > new_width:
|
1037
1125
|
new_width = w
|
1038
1126
|
elif isinstance(self.MT._row_index, int):
|
@@ -1053,8 +1141,10 @@ class RowIndex(tk.Canvas):
|
|
1053
1141
|
new_width = w
|
1054
1142
|
if new_width == self.MT.min_column_width:
|
1055
1143
|
new_width = self.MT.min_column_width + 10
|
1056
|
-
|
1057
|
-
|
1144
|
+
if set_width:
|
1145
|
+
self.set_width(new_width, set_TL=True)
|
1146
|
+
self.MT.main_table_redraw_grid_and_text(redraw_header=True, redraw_row_index=True)
|
1147
|
+
return new_width
|
1058
1148
|
|
1059
1149
|
def set_height_of_all_rows(self, height=None, only_set_if_too_small=False, recreate=True):
|
1060
1150
|
if height is None:
|
@@ -1074,23 +1164,24 @@ class RowIndex(tk.Canvas):
|
|
1074
1164
|
if recreate:
|
1075
1165
|
self.MT.recreate_all_selection_boxes()
|
1076
1166
|
|
1077
|
-
def auto_set_index_width(self, end_row):
|
1078
|
-
if
|
1079
|
-
if self.
|
1080
|
-
|
1081
|
-
|
1082
|
-
|
1083
|
-
|
1084
|
-
|
1085
|
-
|
1086
|
-
|
1087
|
-
|
1088
|
-
|
1089
|
-
|
1090
|
-
|
1091
|
-
|
1092
|
-
|
1093
|
-
|
1167
|
+
def auto_set_index_width(self, end_row: int, only_rows: list) -> bool:
|
1168
|
+
if self.PAR.ops.auto_resize_row_index:
|
1169
|
+
if not isinstance(self.MT._row_index, int) and not self.MT._row_index:
|
1170
|
+
if self.default_index == "letters":
|
1171
|
+
new_w = self.MT.get_txt_w(f"{num2alpha(end_row)}") + 20
|
1172
|
+
elif self.default_index == "numbers":
|
1173
|
+
new_w = self.MT.get_txt_w(f"{end_row}") + 20
|
1174
|
+
elif self.default_index == "both":
|
1175
|
+
new_w = self.MT.get_txt_w(f"{end_row + 1} {num2alpha(end_row)}") + 20
|
1176
|
+
elif self.PAR.ops.auto_resize_row_index is True:
|
1177
|
+
new_w = self.set_width_of_index_to_text(only_rows=only_rows, set_width=False)
|
1178
|
+
else:
|
1179
|
+
new_w = None
|
1180
|
+
if new_w is not None and (sheet_w := floor(self.PAR.winfo_width() * 0.5)) < new_w:
|
1181
|
+
new_w = sheet_w
|
1182
|
+
if new_w and (self.current_width - new_w > 15 or new_w - self.current_width > 5):
|
1183
|
+
self.set_width(new_w, set_TL=True)
|
1184
|
+
return True
|
1094
1185
|
return False
|
1095
1186
|
|
1096
1187
|
def redraw_highlight_get_text_fg(self, fr, sr, r, c_2, c_3, selections, datarn):
|
@@ -1185,34 +1276,59 @@ class RowIndex(tk.Canvas):
|
|
1185
1276
|
fill,
|
1186
1277
|
outline,
|
1187
1278
|
tag,
|
1188
|
-
draw_outline=True,
|
1189
|
-
draw_arrow=True,
|
1190
|
-
|
1191
|
-
|
1279
|
+
draw_outline: bool = True,
|
1280
|
+
draw_arrow: bool = True,
|
1281
|
+
open_: bool = False,
|
1282
|
+
indent: None | float = None,
|
1283
|
+
) -> None:
|
1192
1284
|
if draw_outline and self.PAR.ops.show_dropdown_borders:
|
1193
1285
|
self.redraw_highlight(x1 + 1, y1 + 1, x2, y2, fill="", outline=self.PAR.ops.index_fg, tag=tag)
|
1194
1286
|
if draw_arrow:
|
1195
|
-
|
1196
|
-
|
1197
|
-
|
1198
|
-
|
1199
|
-
|
1200
|
-
|
1201
|
-
|
1202
|
-
|
1203
|
-
|
1287
|
+
mod = (self.MT.index_txt_height - 1) if self.MT.index_txt_height % 2 else self.MT.index_txt_height
|
1288
|
+
half_mod = mod / 2
|
1289
|
+
qtr_mod = mod / 4
|
1290
|
+
mid_y = (self.MT.index_first_ln_ins - 1) if self.MT.index_first_ln_ins % 2 else self.MT.index_first_ln_ins
|
1291
|
+
# treeview
|
1292
|
+
if indent is not None:
|
1293
|
+
# up arrow
|
1294
|
+
if open_:
|
1295
|
+
points = (
|
1296
|
+
x1 + 2 + indent,
|
1297
|
+
y1 + mid_y + qtr_mod,
|
1298
|
+
x1 + 2 + half_mod + indent,
|
1299
|
+
y1 + mid_y - qtr_mod,
|
1300
|
+
x1 + 2 + mod + indent,
|
1301
|
+
y1 + mid_y + qtr_mod,
|
1302
|
+
)
|
1303
|
+
# right pointing arrow
|
1304
|
+
else:
|
1305
|
+
points = (
|
1306
|
+
x1 + half_mod + indent,
|
1307
|
+
y1 + mid_y - half_mod + 1,
|
1308
|
+
x1 + mod + indent - 1,
|
1309
|
+
y1 + mid_y,
|
1310
|
+
x1 + half_mod + indent,
|
1311
|
+
y1 + mid_y + half_mod - 1,
|
1312
|
+
)
|
1204
1313
|
else:
|
1205
|
-
|
1206
|
-
|
1207
|
-
|
1208
|
-
|
1209
|
-
|
1210
|
-
|
1211
|
-
|
1212
|
-
|
1213
|
-
|
1214
|
-
|
1215
|
-
|
1314
|
+
if open_:
|
1315
|
+
points = (
|
1316
|
+
x2 - 3 - mod,
|
1317
|
+
y1 + mid_y + qtr_mod,
|
1318
|
+
x2 - 3 - half_mod,
|
1319
|
+
y1 + mid_y - qtr_mod,
|
1320
|
+
x2 - 3,
|
1321
|
+
y1 + mid_y + qtr_mod,
|
1322
|
+
)
|
1323
|
+
else:
|
1324
|
+
points = (
|
1325
|
+
x2 - 3 - mod,
|
1326
|
+
y1 + mid_y - qtr_mod,
|
1327
|
+
x2 - 3 - half_mod,
|
1328
|
+
y1 + mid_y + qtr_mod,
|
1329
|
+
x2 - 3,
|
1330
|
+
y1 + mid_y - qtr_mod,
|
1331
|
+
)
|
1216
1332
|
if self.hidd_dropdown:
|
1217
1333
|
t, sh = self.hidd_dropdown.popitem()
|
1218
1334
|
self.coords(t, points)
|
@@ -1266,14 +1382,14 @@ class RowIndex(tk.Canvas):
|
|
1266
1382
|
|
1267
1383
|
def redraw_grid_and_text(
|
1268
1384
|
self,
|
1269
|
-
last_row_line_pos,
|
1270
|
-
scrollpos_top,
|
1271
|
-
y_stop,
|
1272
|
-
start_row,
|
1273
|
-
end_row,
|
1274
|
-
scrollpos_bot,
|
1275
|
-
row_pos_exists,
|
1276
|
-
):
|
1385
|
+
last_row_line_pos: int,
|
1386
|
+
scrollpos_top: int,
|
1387
|
+
y_stop: int,
|
1388
|
+
start_row: int,
|
1389
|
+
end_row: int,
|
1390
|
+
scrollpos_bot: int,
|
1391
|
+
row_pos_exists: bool,
|
1392
|
+
) -> None:
|
1277
1393
|
try:
|
1278
1394
|
self.configure(
|
1279
1395
|
scrollregion=(
|
@@ -1342,7 +1458,9 @@ class RowIndex(tk.Canvas):
|
|
1342
1458
|
)
|
1343
1459
|
font = self.PAR.ops.index_font
|
1344
1460
|
selections = self.get_redraw_selections(start_row, end_row)
|
1345
|
-
dd_coords = self.
|
1461
|
+
dd_coords = self.dropdown.get_coords()
|
1462
|
+
treeview = self.PAR.ops.treeview
|
1463
|
+
|
1346
1464
|
for r in range(start_row, end_row - 1):
|
1347
1465
|
rtopgridln = self.MT.row_positions[r]
|
1348
1466
|
rbotgridln = self.MT.row_positions[r + 1]
|
@@ -1370,7 +1488,7 @@ class RowIndex(tk.Canvas):
|
|
1370
1488
|
tag="dd",
|
1371
1489
|
draw_outline=not dd_drawn,
|
1372
1490
|
draw_arrow=mw >= 5,
|
1373
|
-
|
1491
|
+
open_=dd_coords == r,
|
1374
1492
|
)
|
1375
1493
|
else:
|
1376
1494
|
mw = self.current_width - 2
|
@@ -1389,7 +1507,7 @@ class RowIndex(tk.Canvas):
|
|
1389
1507
|
tag="dd",
|
1390
1508
|
draw_outline=not dd_drawn,
|
1391
1509
|
draw_arrow=mw >= 5,
|
1392
|
-
|
1510
|
+
open_=dd_coords == r,
|
1393
1511
|
)
|
1394
1512
|
else:
|
1395
1513
|
mw = self.current_width - 2
|
@@ -1409,7 +1527,7 @@ class RowIndex(tk.Canvas):
|
|
1409
1527
|
tag="dd",
|
1410
1528
|
draw_outline=not dd_drawn,
|
1411
1529
|
draw_arrow=mw >= 5,
|
1412
|
-
|
1530
|
+
open_=dd_coords == r,
|
1413
1531
|
)
|
1414
1532
|
else:
|
1415
1533
|
mw = self.current_width - 1
|
@@ -1443,6 +1561,27 @@ class RowIndex(tk.Canvas):
|
|
1443
1561
|
tag="cb",
|
1444
1562
|
draw_check=draw_check,
|
1445
1563
|
)
|
1564
|
+
if treeview and isinstance(self.MT._row_index, list) and len(self.MT._row_index) > datarn:
|
1565
|
+
iid = self.MT._row_index[datarn].iid
|
1566
|
+
mw -= self.MT.index_txt_height
|
1567
|
+
if align == "w":
|
1568
|
+
draw_x += self.MT.index_txt_height + 1
|
1569
|
+
indent = self.get_treeview_indent(iid)
|
1570
|
+
draw_x += indent
|
1571
|
+
if self.tree[iid].children:
|
1572
|
+
self.redraw_dropdown(
|
1573
|
+
0,
|
1574
|
+
rtopgridln,
|
1575
|
+
self.current_width - 1,
|
1576
|
+
rbotgridln - 1,
|
1577
|
+
fill=fill,
|
1578
|
+
outline=fill,
|
1579
|
+
tag="dd",
|
1580
|
+
draw_outline=False,
|
1581
|
+
draw_arrow=True,
|
1582
|
+
open_=self.MT._row_index[datarn].iid in self.tree_open_ids,
|
1583
|
+
indent=indent,
|
1584
|
+
)
|
1446
1585
|
lns = self.get_valid_cell_data_as_str(datarn, fix=False)
|
1447
1586
|
if not lns:
|
1448
1587
|
continue
|
@@ -1530,10 +1669,8 @@ class RowIndex(tk.Canvas):
|
|
1530
1669
|
|
1531
1670
|
def get_redraw_selections(self, startr, endr):
|
1532
1671
|
d = defaultdict(list)
|
1533
|
-
for item in
|
1534
|
-
|
1535
|
-
if tags:
|
1536
|
-
d[tags[0]].append(coords_tag_to_int_tuple(tags[1]))
|
1672
|
+
for item, box in self.MT.get_selection_items(columns=False):
|
1673
|
+
d[box.type_].append(box.coords)
|
1537
1674
|
d2 = {}
|
1538
1675
|
if "cells" in d:
|
1539
1676
|
d2["cells"] = {r for r in range(startr, endr) for r1, c1, r2, c2 in d["cells"] if r1 <= r and r2 > r}
|
@@ -1542,12 +1679,11 @@ class RowIndex(tk.Canvas):
|
|
1542
1679
|
return d2
|
1543
1680
|
|
1544
1681
|
def open_cell(self, event: object = None, ignore_existing_editor=False):
|
1545
|
-
if not self.MT.anything_selected() or (not ignore_existing_editor and self.
|
1682
|
+
if not self.MT.anything_selected() or (not ignore_existing_editor and self.text_editor.open):
|
1546
1683
|
return
|
1547
|
-
|
1548
|
-
if not currently_selected:
|
1684
|
+
if not self.MT.selected:
|
1549
1685
|
return
|
1550
|
-
r =
|
1686
|
+
r = self.MT.selected.row
|
1551
1687
|
datarn = r if self.MT.all_rows_displayed else self.MT.displayed_rows[r]
|
1552
1688
|
if self.get_cell_kwargs(datarn, key="readonly"):
|
1553
1689
|
return
|
@@ -1602,7 +1738,6 @@ class RowIndex(tk.Canvas):
|
|
1602
1738
|
text = event.char
|
1603
1739
|
else:
|
1604
1740
|
return False
|
1605
|
-
self.text_editor_loc = r
|
1606
1741
|
if self.extra_begin_edit_cell_func is not None:
|
1607
1742
|
try:
|
1608
1743
|
text = self.extra_begin_edit_cell_func(
|
@@ -1613,7 +1748,7 @@ class RowIndex(tk.Canvas):
|
|
1613
1748
|
value=text,
|
1614
1749
|
loc=r,
|
1615
1750
|
boxes=self.MT.get_boxes(),
|
1616
|
-
selected=self.MT.
|
1751
|
+
selected=self.MT.selected,
|
1617
1752
|
)
|
1618
1753
|
)
|
1619
1754
|
except Exception:
|
@@ -1625,14 +1760,13 @@ class RowIndex(tk.Canvas):
|
|
1625
1760
|
text = "" if text is None else text
|
1626
1761
|
if self.PAR.ops.cell_auto_resize_enabled:
|
1627
1762
|
self.set_row_height_run_binding(r)
|
1628
|
-
if
|
1763
|
+
if self.text_editor.open and r == self.text_editor.row:
|
1629
1764
|
self.text_editor.set_text(self.text_editor.get() + "" if not isinstance(text, str) else text)
|
1630
1765
|
return
|
1631
|
-
if self.text_editor
|
1632
|
-
self.
|
1766
|
+
if self.text_editor.open:
|
1767
|
+
self.hide_text_editor()
|
1633
1768
|
if not self.MT.see(r=r, c=0, keep_yscroll=True, check_cell_visibility=True):
|
1634
1769
|
self.MT.refresh()
|
1635
|
-
self.text_editor_loc = r
|
1636
1770
|
x = 0
|
1637
1771
|
y = self.MT.row_positions[r] + 1
|
1638
1772
|
w = self.current_width + 1
|
@@ -1641,54 +1775,60 @@ class RowIndex(tk.Canvas):
|
|
1641
1775
|
if text is None:
|
1642
1776
|
text = self.get_cell_data(datarn, none_to_empty_str=True, redirect_int=True)
|
1643
1777
|
bg, fg = self.PAR.ops.index_bg, self.PAR.ops.index_fg
|
1644
|
-
|
1645
|
-
|
1646
|
-
menu_kwargs=DotDict(
|
1778
|
+
kwargs = {
|
1779
|
+
"menu_kwargs": DotDict(
|
1647
1780
|
{
|
1648
|
-
"font": self.PAR.ops.
|
1781
|
+
"font": self.PAR.ops.table_font,
|
1649
1782
|
"foreground": self.PAR.ops.popup_menu_fg,
|
1650
1783
|
"background": self.PAR.ops.popup_menu_bg,
|
1651
1784
|
"activebackground": self.PAR.ops.popup_menu_highlight_bg,
|
1652
1785
|
"activeforeground": self.PAR.ops.popup_menu_highlight_fg,
|
1653
1786
|
}
|
1654
1787
|
),
|
1655
|
-
sheet_ops
|
1656
|
-
border_color
|
1657
|
-
text
|
1658
|
-
state
|
1659
|
-
width
|
1660
|
-
height
|
1661
|
-
show_border
|
1662
|
-
bg
|
1663
|
-
fg
|
1664
|
-
align
|
1665
|
-
r
|
1666
|
-
|
1667
|
-
|
1668
|
-
|
1669
|
-
|
1788
|
+
"sheet_ops": self.PAR.ops,
|
1789
|
+
"border_color": self.PAR.ops.table_selected_cells_border_fg,
|
1790
|
+
"text": text,
|
1791
|
+
"state": state,
|
1792
|
+
"width": w,
|
1793
|
+
"height": h,
|
1794
|
+
"show_border": self.PAR.ops.show_selected_cells_border,
|
1795
|
+
"bg": bg,
|
1796
|
+
"fg": fg,
|
1797
|
+
"align": self.get_cell_align(r),
|
1798
|
+
"r": r,
|
1799
|
+
}
|
1800
|
+
if not self.text_editor.window:
|
1801
|
+
self.text_editor.window = TextEditor(self, newline_binding=self.text_editor_newline_binding)
|
1802
|
+
self.text_editor.canvas_id = self.create_window((x, y), window=self.text_editor.window, anchor="nw")
|
1803
|
+
self.text_editor.window.reset(**kwargs)
|
1804
|
+
if not self.text_editor.open:
|
1805
|
+
self.itemconfig(self.text_editor.canvas_id, state="normal")
|
1806
|
+
self.text_editor.open = True
|
1807
|
+
self.coords(self.text_editor.canvas_id, x, y)
|
1670
1808
|
if not dropdown:
|
1671
|
-
self.text_editor.
|
1672
|
-
self.text_editor.scroll_to_bottom()
|
1673
|
-
self.text_editor.
|
1809
|
+
self.text_editor.tktext.focus_set()
|
1810
|
+
self.text_editor.window.scroll_to_bottom()
|
1811
|
+
self.text_editor.tktext.bind("<Alt-Return>", lambda _x: self.text_editor_newline_binding(r=r))
|
1674
1812
|
if USER_OS == "darwin":
|
1675
|
-
self.text_editor.
|
1813
|
+
self.text_editor.tktext.bind("<Option-Return>", lambda _x: self.text_editor_newline_binding(r=r))
|
1676
1814
|
for key, func in self.MT.text_editor_user_bound_keys.items():
|
1677
|
-
self.text_editor.
|
1678
|
-
self.text_editor.
|
1679
|
-
self.text_editor.
|
1815
|
+
self.text_editor.tktext.bind(key, func)
|
1816
|
+
self.text_editor.tktext.bind("<Tab>", lambda _x: self.close_text_editor((r, "Tab")))
|
1817
|
+
self.text_editor.tktext.bind("<Return>", lambda _x: self.close_text_editor((r, "Return")))
|
1680
1818
|
if not dropdown:
|
1681
|
-
self.text_editor.
|
1682
|
-
self.text_editor.
|
1819
|
+
self.text_editor.tktext.bind("<FocusOut>", lambda _x: self.close_text_editor((r, "FocusOut")))
|
1820
|
+
self.text_editor.tktext.bind("<Escape>", lambda _x: self.close_text_editor((r, "Escape")))
|
1683
1821
|
return True
|
1684
1822
|
|
1685
1823
|
def text_editor_newline_binding(self, r=0, c=0, event: object = None, check_lines=True):
|
1686
1824
|
if self.height_resizing_enabled:
|
1687
|
-
|
1688
|
-
curr_height = self.text_editor.winfo_height()
|
1825
|
+
curr_height = self.text_editor.window.winfo_height()
|
1689
1826
|
if (
|
1690
1827
|
not check_lines
|
1691
|
-
or self.MT.get_lines_cell_height(
|
1828
|
+
or self.MT.get_lines_cell_height(
|
1829
|
+
self.text_editor.window.get_num_lines() + 1,
|
1830
|
+
font=self.PAR.ops.index_font,
|
1831
|
+
)
|
1692
1832
|
> curr_height
|
1693
1833
|
):
|
1694
1834
|
new_height = curr_height + self.MT.index_xtra_lines_increment
|
@@ -1698,78 +1838,63 @@ class RowIndex(tk.Canvas):
|
|
1698
1838
|
if new_height != curr_height:
|
1699
1839
|
self.set_row_height(r, new_height)
|
1700
1840
|
self.MT.refresh()
|
1701
|
-
self.text_editor.config(height=new_height)
|
1702
|
-
self.coords(self.
|
1703
|
-
|
1704
|
-
|
1705
|
-
text_editor_h = self.text_editor.winfo_height()
|
1841
|
+
self.text_editor.window.config(height=new_height)
|
1842
|
+
self.coords(self.text_editor.canvas_id, 0, self.MT.row_positions[r] + 1)
|
1843
|
+
if self.dropdown.open and self.dropdown.get_coords() == r:
|
1844
|
+
text_editor_h = self.text_editor.window.winfo_height()
|
1706
1845
|
win_h, anchor = self.get_dropdown_height_anchor(r, text_editor_h)
|
1707
1846
|
if anchor == "nw":
|
1708
1847
|
self.coords(
|
1709
|
-
|
1848
|
+
self.dropdown.canvas_id,
|
1710
1849
|
self.MT.col_positions[c],
|
1711
1850
|
self.MT.row_positions[r] + text_editor_h - 1,
|
1712
1851
|
)
|
1713
|
-
self.itemconfig(
|
1852
|
+
self.itemconfig(self.dropdown.canvas_id, anchor=anchor, height=win_h)
|
1714
1853
|
elif anchor == "sw":
|
1715
1854
|
self.coords(
|
1716
|
-
|
1855
|
+
self.dropdown.canvas_id,
|
1717
1856
|
self.MT.col_positions[c],
|
1718
1857
|
self.MT.row_positions[r],
|
1719
1858
|
)
|
1720
|
-
self.itemconfig(
|
1859
|
+
self.itemconfig(self.dropdown.canvas_id, anchor=anchor, height=win_h)
|
1721
1860
|
|
1722
1861
|
def refresh_open_window_positions(self):
|
1723
|
-
if self.text_editor
|
1724
|
-
r = self.
|
1725
|
-
self.text_editor.config(height=self.MT.row_positions[r + 1] - self.MT.row_positions[r])
|
1862
|
+
if self.text_editor.open:
|
1863
|
+
r = self.text_editor.row
|
1864
|
+
self.text_editor.window.config(height=self.MT.row_positions[r + 1] - self.MT.row_positions[r])
|
1726
1865
|
self.coords(
|
1727
|
-
self.
|
1866
|
+
self.text_editor.canvas_id,
|
1728
1867
|
0,
|
1729
1868
|
self.MT.row_positions[r],
|
1730
1869
|
)
|
1731
|
-
if self.
|
1732
|
-
r = self.
|
1733
|
-
if self.text_editor
|
1734
|
-
text_editor_h = self.
|
1735
|
-
anchor = self.itemcget(self.existing_dropdown_canvas_id, "anchor")
|
1736
|
-
win_h = 0
|
1737
|
-
else:
|
1738
|
-
text_editor_h = self.text_editor.winfo_height()
|
1870
|
+
if self.dropdown.open:
|
1871
|
+
r = self.dropdown.get_coords()
|
1872
|
+
if self.text_editor.open:
|
1873
|
+
text_editor_h = self.text_editor.window.winfo_height()
|
1739
1874
|
win_h, anchor = self.get_dropdown_height_anchor(r, text_editor_h)
|
1875
|
+
else:
|
1876
|
+
text_editor_h = self.MT.row_positions[r + 1] - self.MT.row_positions[r]
|
1877
|
+
anchor = self.itemcget(self.dropdown.canvas_id, "anchor")
|
1878
|
+
# win_h = 0
|
1740
1879
|
if anchor == "nw":
|
1741
1880
|
self.coords(
|
1742
|
-
self.
|
1881
|
+
self.dropdown.canvas_id,
|
1743
1882
|
0,
|
1744
1883
|
self.MT.row_positions[r] + text_editor_h - 1,
|
1745
1884
|
)
|
1746
|
-
# self.itemconfig(self.
|
1885
|
+
# self.itemconfig(self.dropdown.canvas_id, anchor=anchor, height=win_h)
|
1747
1886
|
elif anchor == "sw":
|
1748
1887
|
self.coords(
|
1749
|
-
self.
|
1888
|
+
self.dropdown.canvas_id,
|
1750
1889
|
0,
|
1751
1890
|
self.MT.row_positions[r],
|
1752
1891
|
)
|
1753
|
-
# self.itemconfig(self.
|
1754
|
-
|
1755
|
-
def bind_text_editor_destroy(self, binding, r):
|
1756
|
-
self.text_editor.textedit.bind("<Return>", lambda _x: binding((r, "Return")))
|
1757
|
-
self.text_editor.textedit.bind("<FocusOut>", lambda _x: binding((r, "FocusOut")))
|
1758
|
-
self.text_editor.textedit.bind("<Escape>", lambda _x: binding((r, "Escape")))
|
1759
|
-
self.text_editor.textedit.focus_set()
|
1892
|
+
# self.itemconfig(self.dropdown.canvas_id, anchor=anchor, height=win_h)
|
1760
1893
|
|
1761
|
-
def
|
1762
|
-
self.
|
1763
|
-
|
1764
|
-
self.
|
1765
|
-
except Exception:
|
1766
|
-
pass
|
1767
|
-
try:
|
1768
|
-
self.text_editor.destroy()
|
1769
|
-
except Exception:
|
1770
|
-
pass
|
1771
|
-
self.text_editor = None
|
1772
|
-
self.text_editor_id = None
|
1894
|
+
def hide_text_editor(self, reason: None | str = None) -> None:
|
1895
|
+
if self.text_editor.open:
|
1896
|
+
self.itemconfig(self.text_editor.canvas_id, state="hidden")
|
1897
|
+
self.text_editor.open = False
|
1773
1898
|
if reason == "Escape":
|
1774
1899
|
self.focus_set()
|
1775
1900
|
|
@@ -1780,18 +1905,16 @@ class RowIndex(tk.Canvas):
|
|
1780
1905
|
) -> str | None:
|
1781
1906
|
focused = self.focus_get()
|
1782
1907
|
try:
|
1783
|
-
if focused == self.text_editor.
|
1908
|
+
if focused == self.text_editor.tktext.rc_popup_menu:
|
1784
1909
|
return "break"
|
1785
1910
|
except Exception:
|
1786
1911
|
pass
|
1787
1912
|
if focused is None and editor_info:
|
1788
1913
|
return "break"
|
1789
1914
|
if editor_info is not None and len(editor_info) >= 2 and editor_info[1] == "Escape":
|
1790
|
-
self.
|
1791
|
-
self.close_dropdown_window()
|
1915
|
+
self.hide_text_editor_and_dropdown()
|
1792
1916
|
return
|
1793
1917
|
self.text_editor_value = self.text_editor.get()
|
1794
|
-
self.destroy_text_editor()
|
1795
1918
|
r = editor_info[0]
|
1796
1919
|
datarn = r if self.MT.all_rows_displayed else self.MT.displayed_rows[r]
|
1797
1920
|
event_data = event_dict(
|
@@ -1802,7 +1925,7 @@ class RowIndex(tk.Canvas):
|
|
1802
1925
|
value=self.text_editor_value,
|
1803
1926
|
loc=r,
|
1804
1927
|
boxes=self.MT.get_boxes(),
|
1805
|
-
selected=self.MT.
|
1928
|
+
selected=self.MT.selected,
|
1806
1929
|
)
|
1807
1930
|
edited = False
|
1808
1931
|
set_data = partial(
|
@@ -1819,9 +1942,8 @@ class RowIndex(tk.Canvas):
|
|
1819
1942
|
edited = set_data(value=self.text_editor_value)
|
1820
1943
|
if edited:
|
1821
1944
|
try_binding(self.extra_end_edit_cell_func, event_data)
|
1822
|
-
self.close_dropdown_window(r)
|
1823
1945
|
self.MT.recreate_all_selection_boxes()
|
1824
|
-
self.
|
1946
|
+
self.hide_text_editor_and_dropdown()
|
1825
1947
|
if editor_info[1] != "FocusOut":
|
1826
1948
|
self.focus_set()
|
1827
1949
|
return "break"
|
@@ -1863,8 +1985,7 @@ class RowIndex(tk.Canvas):
|
|
1863
1985
|
|
1864
1986
|
# r is displayed row
|
1865
1987
|
def open_dropdown_window(self, r, datarn=None, event: object = None):
|
1866
|
-
self.
|
1867
|
-
self.destroy_opened_dropdown_window()
|
1988
|
+
self.hide_text_editor("Escape")
|
1868
1989
|
if datarn is None:
|
1869
1990
|
datarn = r if self.MT.all_rows_displayed else self.MT.displayed_rows[r]
|
1870
1991
|
kwargs = self.get_cell_kwargs(datarn, key="dropdown")
|
@@ -1872,61 +1993,68 @@ class RowIndex(tk.Canvas):
|
|
1872
1993
|
if not self.open_text_editor(event=event, r=r, dropdown=True):
|
1873
1994
|
return
|
1874
1995
|
win_h, anchor = self.get_dropdown_height_anchor(r)
|
1875
|
-
window = self.PAR.dropdown_class(
|
1876
|
-
self.MT.winfo_toplevel(),
|
1877
|
-
r,
|
1878
|
-
0,
|
1879
|
-
width=self.current_width,
|
1880
|
-
height=win_h,
|
1881
|
-
font=self.PAR.ops.index_font,
|
1882
|
-
colors={
|
1883
|
-
"bg": self.PAR.ops.popup_menu_bg,
|
1884
|
-
"fg": self.PAR.ops.popup_menu_fg,
|
1885
|
-
"highlight_bg": self.PAR.ops.popup_menu_highlight_bg,
|
1886
|
-
"highlight_fg": self.PAR.ops.popup_menu_highlight_fg,
|
1887
|
-
},
|
1888
|
-
outline_color=self.PAR.ops.popup_menu_fg,
|
1889
|
-
values=kwargs["values"],
|
1890
|
-
close_dropdown_window=self.close_dropdown_window,
|
1891
|
-
search_function=kwargs["search_function"],
|
1892
|
-
arrowkey_RIGHT=self.MT.arrowkey_RIGHT,
|
1893
|
-
arrowkey_LEFT=self.MT.arrowkey_LEFT,
|
1894
|
-
align="w",
|
1895
|
-
single_index="r",
|
1896
|
-
)
|
1897
1996
|
ypos = self.MT.row_positions[r + 1]
|
1898
|
-
|
1997
|
+
if self.dropdown.window is not None:
|
1998
|
+
self.dropdown.window.search_function = kwargs["search_function"]
|
1999
|
+
self.dropdown.window.r = r
|
2000
|
+
self.dropdown.window.row = -1
|
2001
|
+
self.dropdown.window.set_options()
|
2002
|
+
self.dropdown.window.values(kwargs["values"])
|
2003
|
+
if not self.dropdown.open:
|
2004
|
+
self.itemconfig(self.dropdown.canvas_id, state="normal")
|
2005
|
+
self.coords(self.dropdown.canvas_id, 0, ypos)
|
2006
|
+
else:
|
2007
|
+
self.dropdown.window = self.PAR.dropdown_class(
|
2008
|
+
self.MT.winfo_toplevel(),
|
2009
|
+
r,
|
2010
|
+
0,
|
2011
|
+
width=self.current_width,
|
2012
|
+
height=win_h,
|
2013
|
+
font=self.PAR.ops.index_font,
|
2014
|
+
ops=self.PAR.ops,
|
2015
|
+
outline_color=self.PAR.ops.popup_menu_fg,
|
2016
|
+
values=kwargs["values"],
|
2017
|
+
close_dropdown_window=self.close_dropdown_window,
|
2018
|
+
search_function=kwargs["search_function"],
|
2019
|
+
arrowkey_RIGHT=self.MT.arrowkey_RIGHT,
|
2020
|
+
arrowkey_LEFT=self.MT.arrowkey_LEFT,
|
2021
|
+
align="w",
|
2022
|
+
single_index="r",
|
2023
|
+
)
|
2024
|
+
self.dropdown.canvas_id = self.create_window(
|
2025
|
+
(0, ypos),
|
2026
|
+
window=self.dropdown.window,
|
2027
|
+
anchor=anchor,
|
2028
|
+
)
|
1899
2029
|
if kwargs["state"] == "normal":
|
1900
|
-
self.text_editor.
|
2030
|
+
self.text_editor.tktext.bind(
|
1901
2031
|
"<<TextModified>>",
|
1902
2032
|
lambda _x: self.dropdown_text_editor_modified(
|
1903
|
-
window,
|
2033
|
+
self.dropdown.window,
|
1904
2034
|
event_dict(
|
1905
2035
|
name="index_dropdown_modified",
|
1906
2036
|
sheet=self.PAR.name,
|
1907
2037
|
value=self.text_editor.get(),
|
1908
2038
|
loc=r,
|
1909
2039
|
boxes=self.MT.get_boxes(),
|
1910
|
-
selected=self.MT.
|
2040
|
+
selected=self.MT.selected,
|
1911
2041
|
),
|
1912
2042
|
kwargs["modified_function"],
|
1913
2043
|
),
|
1914
2044
|
)
|
1915
2045
|
self.update_idletasks()
|
1916
2046
|
try:
|
1917
|
-
self.after(1, lambda: self.text_editor.
|
1918
|
-
self.after(2, self.text_editor.scroll_to_bottom())
|
2047
|
+
self.after(1, lambda: self.text_editor.tktext.focus())
|
2048
|
+
self.after(2, self.text_editor.window.scroll_to_bottom())
|
1919
2049
|
except Exception:
|
1920
2050
|
return
|
1921
2051
|
redraw = False
|
1922
2052
|
else:
|
1923
|
-
window.bind("<FocusOut>", lambda _x: self.close_dropdown_window(r))
|
2053
|
+
self.dropdown.window.bind("<FocusOut>", lambda _x: self.close_dropdown_window(r))
|
1924
2054
|
self.update_idletasks()
|
1925
|
-
window.focus_set()
|
2055
|
+
self.dropdown.window.focus_set()
|
1926
2056
|
redraw = True
|
1927
|
-
self.
|
1928
|
-
kwargs["window"] = window
|
1929
|
-
self.existing_dropdown_canvas_id = kwargs["canvas_id"]
|
2057
|
+
self.dropdown.open = True
|
1930
2058
|
if redraw:
|
1931
2059
|
self.MT.main_table_redraw_grid_and_text(redraw_header=False, redraw_row_index=True, redraw_table=False)
|
1932
2060
|
|
@@ -1945,9 +2073,9 @@ class RowIndex(tk.Canvas):
|
|
1945
2073
|
value=selection,
|
1946
2074
|
loc=r,
|
1947
2075
|
boxes=self.MT.get_boxes(),
|
1948
|
-
selected=self.MT.
|
2076
|
+
selected=self.MT.selected,
|
1949
2077
|
)
|
1950
|
-
if kwargs["select_function"] is not None:
|
2078
|
+
if kwargs["select_function"] is not None:
|
1951
2079
|
kwargs["select_function"](event_data)
|
1952
2080
|
if self.MT.edit_validation_func:
|
1953
2081
|
selection = self.MT.edit_validation_func(event_data)
|
@@ -1959,23 +2087,20 @@ class RowIndex(tk.Canvas):
|
|
1959
2087
|
try_binding(self.extra_end_edit_cell_func, event_data)
|
1960
2088
|
self.focus_set()
|
1961
2089
|
self.MT.recreate_all_selection_boxes()
|
1962
|
-
self.
|
1963
|
-
|
2090
|
+
self.hide_text_editor_and_dropdown(redraw=redraw)
|
2091
|
+
|
2092
|
+
def hide_text_editor_and_dropdown(self, redraw: bool = True) -> None:
|
2093
|
+
self.hide_text_editor("Escape")
|
2094
|
+
self.hide_dropdown_window()
|
1964
2095
|
if redraw:
|
1965
2096
|
self.MT.refresh()
|
1966
2097
|
|
1967
|
-
def get_existing_dropdown_coords(self):
|
1968
|
-
if self.existing_dropdown_window is not None:
|
1969
|
-
return int(self.existing_dropdown_window.r)
|
1970
|
-
return None
|
1971
|
-
|
1972
2098
|
def mouseclick_outside_editor_or_dropdown(self, inside: bool = False):
|
1973
|
-
closed_dd_coords = self.
|
1974
|
-
if self.
|
1975
|
-
self.close_text_editor((self.
|
2099
|
+
closed_dd_coords = self.dropdown.get_coords()
|
2100
|
+
if self.text_editor.open:
|
2101
|
+
self.close_text_editor((self.text_editor.row, "ButtonPress-1"))
|
1976
2102
|
if closed_dd_coords is not None:
|
1977
|
-
|
1978
|
-
self.destroy_opened_dropdown_window(closed_dd_coords)
|
2103
|
+
self.hide_dropdown_window()
|
1979
2104
|
if inside:
|
1980
2105
|
self.MT.main_table_redraw_grid_and_text(
|
1981
2106
|
redraw_header=False,
|
@@ -1989,47 +2114,22 @@ class RowIndex(tk.Canvas):
|
|
1989
2114
|
self.MT.mouseclick_outside_editor_or_dropdown()
|
1990
2115
|
return self.mouseclick_outside_editor_or_dropdown(inside)
|
1991
2116
|
|
1992
|
-
|
1993
|
-
|
1994
|
-
|
1995
|
-
|
1996
|
-
if r is not None or datarn is not None:
|
1997
|
-
if datarn is None:
|
1998
|
-
datarn_ = r if self.MT.all_rows_displayed else self.MT.displayed_rows[r]
|
1999
|
-
else:
|
2000
|
-
datarn_ = r
|
2001
|
-
else:
|
2002
|
-
datarn_ = None
|
2003
|
-
try:
|
2004
|
-
self.delete(self.existing_dropdown_canvas_id)
|
2005
|
-
except Exception:
|
2006
|
-
pass
|
2007
|
-
self.existing_dropdown_canvas_id = None
|
2008
|
-
try:
|
2009
|
-
self.existing_dropdown_window.destroy()
|
2010
|
-
except Exception:
|
2011
|
-
pass
|
2012
|
-
kwargs = self.get_cell_kwargs(datarn_, key="dropdown")
|
2013
|
-
if kwargs:
|
2014
|
-
kwargs["canvas_id"] = "no dropdown open"
|
2015
|
-
kwargs["window"] = "no dropdown open"
|
2016
|
-
try:
|
2017
|
-
self.delete(kwargs["canvas_id"])
|
2018
|
-
except Exception:
|
2019
|
-
pass
|
2020
|
-
self.existing_dropdown_window = None
|
2117
|
+
def hide_dropdown_window(self) -> None:
|
2118
|
+
if self.dropdown.open:
|
2119
|
+
self.itemconfig(self.dropdown.canvas_id, state="hidden")
|
2120
|
+
self.dropdown.open = False
|
2021
2121
|
|
2022
2122
|
# internal event use
|
2023
2123
|
def set_cell_data_undo(
|
2024
2124
|
self,
|
2025
|
-
r=0,
|
2026
|
-
datarn=None,
|
2027
|
-
value="",
|
2028
|
-
cell_resize=True,
|
2029
|
-
undo=True,
|
2030
|
-
redraw=True,
|
2031
|
-
check_input_valid=True,
|
2032
|
-
):
|
2125
|
+
r: int = 0,
|
2126
|
+
datarn: None | int = None,
|
2127
|
+
value: str = "",
|
2128
|
+
cell_resize: bool = True,
|
2129
|
+
undo: bool = True,
|
2130
|
+
redraw: bool = True,
|
2131
|
+
check_input_valid: bool = True,
|
2132
|
+
) -> bool:
|
2033
2133
|
if datarn is None:
|
2034
2134
|
datarn = r if self.MT.all_rows_displayed else self.MT.displayed_rows[r]
|
2035
2135
|
event_data = event_dict(
|
@@ -2037,7 +2137,7 @@ class RowIndex(tk.Canvas):
|
|
2037
2137
|
sheet=self.PAR.name,
|
2038
2138
|
cells_index={datarn: self.get_cell_data(datarn)},
|
2039
2139
|
boxes=self.MT.get_boxes(),
|
2040
|
-
selected=self.MT.
|
2140
|
+
selected=self.MT.selected,
|
2041
2141
|
)
|
2042
2142
|
edited = False
|
2043
2143
|
if isinstance(self.MT._row_index, int):
|
@@ -2194,7 +2294,7 @@ class RowIndex(tk.Canvas):
|
|
2194
2294
|
value=value,
|
2195
2295
|
loc=r,
|
2196
2296
|
boxes=self.MT.get_boxes(),
|
2197
|
-
selected=self.MT.
|
2297
|
+
selected=self.MT.selected,
|
2198
2298
|
)
|
2199
2299
|
if kwargs["check_function"] is not None:
|
2200
2300
|
kwargs["check_function"](event_data)
|
@@ -2206,3 +2306,57 @@ class RowIndex(tk.Canvas):
|
|
2206
2306
|
if cell and datarn in self.cell_options and key in self.cell_options[datarn]:
|
2207
2307
|
return self.cell_options[datarn][key]
|
2208
2308
|
return {}
|
2309
|
+
|
2310
|
+
# Treeview Mode
|
2311
|
+
|
2312
|
+
def get_node_level(self, node: Node, level: int = 0) -> Generator[int]:
|
2313
|
+
yield level
|
2314
|
+
if node.parent:
|
2315
|
+
yield from self.get_node_level(node.parent, level + 1)
|
2316
|
+
|
2317
|
+
def ancestors_all_open(self, iid: str, stop_at: str | Node = "") -> bool:
|
2318
|
+
if stop_at:
|
2319
|
+
stop_at = stop_at.iid
|
2320
|
+
for iid in self.get_iid_ancestors(iid):
|
2321
|
+
if iid == stop_at:
|
2322
|
+
return True
|
2323
|
+
if iid not in self.tree_open_ids:
|
2324
|
+
return False
|
2325
|
+
return True
|
2326
|
+
else:
|
2327
|
+
return all(iid in self.tree_open_ids for iid in self.get_iid_ancestors(iid))
|
2328
|
+
|
2329
|
+
def get_iid_ancestors(self, iid: str) -> Generator[str]:
|
2330
|
+
if self.tree[iid].parent:
|
2331
|
+
yield self.tree[iid].parent.iid
|
2332
|
+
yield from self.get_iid_ancestors(self.tree[iid].parent.iid)
|
2333
|
+
|
2334
|
+
def get_iid_descendants(self, iid: str, check_open: bool = False) -> Generator[str]:
|
2335
|
+
for cnode in self.tree[iid].children:
|
2336
|
+
yield cnode.iid
|
2337
|
+
if (check_open and cnode.children and cnode.iid in self.tree_open_ids) or (
|
2338
|
+
not check_open and cnode.children
|
2339
|
+
):
|
2340
|
+
yield from self.get_iid_descendants(cnode.iid, check_open)
|
2341
|
+
|
2342
|
+
def get_treeview_indent(self, iid: str) -> int:
|
2343
|
+
if isinstance(self.PAR.ops.treeview_indent, str):
|
2344
|
+
indent = self.MT.index_txt_height * int(self.PAR.ops.treeview_indent)
|
2345
|
+
else:
|
2346
|
+
indent = self.PAR.ops.treeview_indent
|
2347
|
+
return indent * max(self.get_node_level(self.tree[iid]))
|
2348
|
+
|
2349
|
+
def remove_node_from_parents_children(self, node: Node) -> None:
|
2350
|
+
if node.parent:
|
2351
|
+
node.parent.children.remove(node)
|
2352
|
+
if not node.parent.children:
|
2353
|
+
self.tree_open_ids.discard(node.parent)
|
2354
|
+
|
2355
|
+
def pid_causes_recursive_loop(self, iid: str, pid: str) -> bool:
|
2356
|
+
return any(
|
2357
|
+
i == pid
|
2358
|
+
for i in chain(
|
2359
|
+
self.get_iid_descendants(iid),
|
2360
|
+
islice(self.get_iid_ancestors(iid), 1, None),
|
2361
|
+
)
|
2362
|
+
)
|