tksheet 7.3.3__py3-none-any.whl → 7.4.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 +11 -11
- tksheet/colors.py +1 -1
- tksheet/column_headers.py +397 -366
- tksheet/constants.py +13 -0
- tksheet/find_window.py +4 -13
- tksheet/functions.py +198 -37
- tksheet/main_table.py +1109 -848
- tksheet/other_classes.py +13 -9
- tksheet/row_index.py +939 -437
- tksheet/sheet.py +470 -619
- tksheet/sheet_options.py +47 -12
- tksheet/sorting.py +369 -0
- tksheet/text_editor.py +4 -15
- tksheet/{types.py → tksheet_types.py} +12 -8
- {tksheet-7.3.3.dist-info → tksheet-7.4.0.dist-info}/METADATA +14 -14
- tksheet-7.4.0.dist-info/RECORD +22 -0
- tksheet-7.3.3.dist-info/RECORD +0 -21
- {tksheet-7.3.3.dist-info → tksheet-7.4.0.dist-info}/LICENSE.txt +0 -0
- {tksheet-7.3.3.dist-info → tksheet-7.4.0.dist-info}/WHEEL +0 -0
- {tksheet-7.3.3.dist-info → tksheet-7.4.0.dist-info}/top_level.txt +0 -0
tksheet/column_headers.py
CHANGED
@@ -2,29 +2,17 @@ from __future__ import annotations
|
|
2
2
|
|
3
3
|
import tkinter as tk
|
4
4
|
from collections import defaultdict
|
5
|
-
from collections.abc import
|
6
|
-
|
7
|
-
|
8
|
-
)
|
9
|
-
from functools import (
|
10
|
-
partial,
|
11
|
-
)
|
12
|
-
from itertools import (
|
13
|
-
cycle,
|
14
|
-
islice,
|
15
|
-
repeat,
|
16
|
-
)
|
5
|
+
from collections.abc import Callable, Hashable, Sequence
|
6
|
+
from functools import partial
|
7
|
+
from itertools import cycle, islice, repeat
|
17
8
|
from math import ceil, floor
|
18
|
-
from operator import
|
19
|
-
itemgetter,
|
20
|
-
)
|
9
|
+
from operator import itemgetter
|
21
10
|
from typing import Literal
|
22
11
|
|
23
|
-
from .colors import
|
24
|
-
color_map,
|
25
|
-
)
|
12
|
+
from .colors import color_map
|
26
13
|
from .constants import (
|
27
14
|
USER_OS,
|
15
|
+
_test_str,
|
28
16
|
rc_binding,
|
29
17
|
text_editor_close_bindings,
|
30
18
|
text_editor_newline_bindings,
|
@@ -39,36 +27,33 @@ from .functions import (
|
|
39
27
|
get_n2a,
|
40
28
|
int_x_tuple,
|
41
29
|
is_contiguous,
|
30
|
+
mod_event_val,
|
42
31
|
new_tk_event,
|
43
32
|
rounded_box_coords,
|
44
33
|
stored_event_dict,
|
34
|
+
try_b_index,
|
45
35
|
try_binding,
|
36
|
+
wrap_text,
|
46
37
|
)
|
47
|
-
from .other_classes import
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
)
|
53
|
-
from .text_editor import (
|
54
|
-
TextEditor,
|
55
|
-
)
|
56
|
-
from .types import (
|
57
|
-
AnyIter,
|
58
|
-
)
|
38
|
+
from .other_classes import DotDict, DraggedRowColumn, DropdownStorage, EventDataDict, TextEditorStorage
|
39
|
+
from .row_index import RowIndex
|
40
|
+
from .sorting import sort_column, sort_rows_by_column, sort_tree_view
|
41
|
+
from .text_editor import TextEditor
|
42
|
+
from .tksheet_types import AnyIter
|
59
43
|
|
60
44
|
|
61
45
|
class ColumnHeaders(tk.Canvas):
|
62
|
-
def __init__(self,
|
46
|
+
def __init__(self, parent, **kwargs):
|
63
47
|
super().__init__(
|
64
|
-
|
65
|
-
background=
|
48
|
+
parent,
|
49
|
+
background=parent.ops.header_bg,
|
66
50
|
highlightthickness=0,
|
67
51
|
)
|
68
|
-
self.PAR =
|
52
|
+
self.PAR = parent
|
53
|
+
self.ops = self.PAR.ops
|
69
54
|
self.current_height = None
|
70
55
|
self.MT = None # is set from within MainTable() __init__
|
71
|
-
self.RI = None # is set from within MainTable() __init__
|
56
|
+
self.RI: RowIndex | None = None # is set from within MainTable() __init__
|
72
57
|
self.TL = None # is set from within TopLeftRectangle() __init__
|
73
58
|
self.popup_menu_loc = None
|
74
59
|
self.extra_begin_edit_cell_func = None
|
@@ -85,6 +70,8 @@ class ColumnHeaders(tk.Canvas):
|
|
85
70
|
self.extra_double_b1_func = None
|
86
71
|
self.ch_extra_begin_drag_drop_func = None
|
87
72
|
self.ch_extra_end_drag_drop_func = None
|
73
|
+
self.ch_extra_begin_sort_rows_func = None
|
74
|
+
self.ch_extra_end_sort_rows_func = None
|
88
75
|
self.extra_rc_func = None
|
89
76
|
self.selection_binding_func = None
|
90
77
|
self.shift_selection_binding_func = None
|
@@ -164,36 +151,8 @@ class ColumnHeaders(tk.Canvas):
|
|
164
151
|
self.unbind("<Button-4>")
|
165
152
|
self.unbind("<Button-5>")
|
166
153
|
|
167
|
-
def mousewheel(self, event:
|
168
|
-
|
169
|
-
maxlines = max(
|
170
|
-
(
|
171
|
-
len(
|
172
|
-
self.MT.get_valid_cell_data_as_str(self.MT._headers, datacn, get_displayed=True)
|
173
|
-
.rstrip()
|
174
|
-
.split("\n")
|
175
|
-
)
|
176
|
-
for datacn in range(len(self.MT.data[self.MT._headers]))
|
177
|
-
),
|
178
|
-
default=0,
|
179
|
-
)
|
180
|
-
elif isinstance(self.MT._headers, (list, tuple)):
|
181
|
-
maxlines = max(
|
182
|
-
(
|
183
|
-
len(e.rstrip().split("\n")) if isinstance(e, str) else len(f"{e}".rstrip().split("\n"))
|
184
|
-
for e in self.MT._headers
|
185
|
-
),
|
186
|
-
default=0,
|
187
|
-
)
|
188
|
-
if maxlines == 1:
|
189
|
-
maxlines = 0
|
190
|
-
if self.lines_start_at > maxlines:
|
191
|
-
self.lines_start_at = maxlines
|
192
|
-
if (event.delta < 0 or event.num == 5) and self.lines_start_at < maxlines:
|
193
|
-
self.lines_start_at += 1
|
194
|
-
elif (event.delta >= 0 or event.num == 4) and self.lines_start_at > 0:
|
195
|
-
self.lines_start_at -= 1
|
196
|
-
self.MT.main_table_redraw_grid_and_text(redraw_header=True, redraw_row_index=False, redraw_table=False)
|
154
|
+
def mousewheel(self, event: tk.Event) -> None:
|
155
|
+
self.MT.mousewheel(event)
|
197
156
|
|
198
157
|
def set_height(self, new_height: int, set_TL: bool = False) -> bool:
|
199
158
|
try:
|
@@ -463,20 +422,22 @@ class ColumnHeaders(tk.Canvas):
|
|
463
422
|
x,
|
464
423
|
self.current_height,
|
465
424
|
width=1,
|
466
|
-
fill=self.
|
467
|
-
tag="rwl",
|
425
|
+
fill=self.ops.resizing_line_fg,
|
426
|
+
tag=("rw", "rwl"),
|
468
427
|
)
|
469
|
-
self.MT.create_resize_line(x, y1, x, y2, width=1, fill=self.
|
428
|
+
self.MT.create_resize_line(x, y1, x, y2, width=1, fill=self.ops.resizing_line_fg, tag=("rw", "rwl"))
|
470
429
|
self.create_resize_line(
|
471
430
|
line2x,
|
472
431
|
0,
|
473
432
|
line2x,
|
474
433
|
self.current_height,
|
475
434
|
width=1,
|
476
|
-
fill=self.
|
477
|
-
tag="rwl2",
|
435
|
+
fill=self.ops.resizing_line_fg,
|
436
|
+
tag=("rw", "rwl2"),
|
437
|
+
)
|
438
|
+
self.MT.create_resize_line(
|
439
|
+
line2x, y1, line2x, y2, width=1, fill=self.ops.resizing_line_fg, tag=("rw", "rwl2")
|
478
440
|
)
|
479
|
-
self.MT.create_resize_line(line2x, y1, line2x, y2, width=1, fill=self.PAR.ops.resizing_line_fg, tag="rwl2")
|
480
441
|
elif self.height_resizing_enabled and self.rsz_w is None and self.rsz_h is not None:
|
481
442
|
self.currently_resizing_height = True
|
482
443
|
elif self.MT.identify_col(x=event.x, allow_end=False) is None:
|
@@ -506,7 +467,7 @@ class ColumnHeaders(tk.Canvas):
|
|
506
467
|
if self.width_resizing_enabled and self.rsz_w is not None and self.currently_resizing_width:
|
507
468
|
x = self.canvasx(event.x)
|
508
469
|
size = x - self.MT.col_positions[self.rsz_w - 1]
|
509
|
-
if size >= self.
|
470
|
+
if size >= self.ops.min_column_width and size < self.ops.max_column_width:
|
510
471
|
self.hide_resize_and_ctrl_lines(ctrl_lines=False)
|
511
472
|
line2x = self.MT.col_positions[self.rsz_w - 1]
|
512
473
|
self.create_resize_line(
|
@@ -515,18 +476,18 @@ class ColumnHeaders(tk.Canvas):
|
|
515
476
|
x,
|
516
477
|
self.current_height,
|
517
478
|
width=1,
|
518
|
-
fill=self.
|
519
|
-
tag="rwl",
|
479
|
+
fill=self.ops.resizing_line_fg,
|
480
|
+
tag=("rw", "rwl"),
|
520
481
|
)
|
521
|
-
self.MT.create_resize_line(x, y1, x, y2, width=1, fill=self.
|
482
|
+
self.MT.create_resize_line(x, y1, x, y2, width=1, fill=self.ops.resizing_line_fg, tag=("rw", "rwl"))
|
522
483
|
self.create_resize_line(
|
523
484
|
line2x,
|
524
485
|
0,
|
525
486
|
line2x,
|
526
487
|
self.current_height,
|
527
488
|
width=1,
|
528
|
-
fill=self.
|
529
|
-
tag="rwl2",
|
489
|
+
fill=self.ops.resizing_line_fg,
|
490
|
+
tag=("rw", "rwl2"),
|
530
491
|
)
|
531
492
|
self.MT.create_resize_line(
|
532
493
|
line2x,
|
@@ -534,15 +495,15 @@ class ColumnHeaders(tk.Canvas):
|
|
534
495
|
line2x,
|
535
496
|
y2,
|
536
497
|
width=1,
|
537
|
-
fill=self.
|
538
|
-
tag="rwl2",
|
498
|
+
fill=self.ops.resizing_line_fg,
|
499
|
+
tag=("rw", "rwl2"),
|
539
500
|
)
|
540
501
|
self.drag_width_resize()
|
541
502
|
elif self.height_resizing_enabled and self.rsz_h is not None and self.currently_resizing_height:
|
542
503
|
evy = event.y
|
543
504
|
if evy > self.current_height:
|
544
|
-
if evy > self.
|
545
|
-
evy = int(self.
|
505
|
+
if evy > self.ops.max_header_height:
|
506
|
+
evy = int(self.ops.max_header_height)
|
546
507
|
self.drag_height_resize(evy)
|
547
508
|
else:
|
548
509
|
if evy < self.MT.min_header_height:
|
@@ -707,16 +668,16 @@ class ColumnHeaders(tk.Canvas):
|
|
707
668
|
xpos,
|
708
669
|
self.current_height,
|
709
670
|
width=3,
|
710
|
-
fill=self.
|
671
|
+
fill=self.ops.drag_and_drop_bg,
|
711
672
|
tag="move_columns",
|
712
673
|
)
|
713
|
-
self.MT.create_resize_line(xpos, y1, xpos, y2, width=3, fill=self.
|
674
|
+
self.MT.create_resize_line(xpos, y1, xpos, y2, width=3, fill=self.ops.drag_and_drop_bg, tag="move_columns")
|
714
675
|
for boxst, boxend in consecutive_ranges(cols):
|
715
676
|
self.MT.show_ctrl_outline(
|
716
677
|
start_cell=(boxst, 0),
|
717
678
|
end_cell=(boxend, len(self.MT.row_positions) - 1),
|
718
679
|
dash=(),
|
719
|
-
outline=self.
|
680
|
+
outline=self.ops.drag_and_drop_bg,
|
720
681
|
delete_on_timer=False,
|
721
682
|
)
|
722
683
|
|
@@ -779,10 +740,10 @@ class ColumnHeaders(tk.Canvas):
|
|
779
740
|
new_col_pos = int(self.coords("rwl")[0])
|
780
741
|
old_width = self.MT.col_positions[self.rsz_w] - self.MT.col_positions[self.rsz_w - 1]
|
781
742
|
size = new_col_pos - self.MT.col_positions[self.rsz_w - 1]
|
782
|
-
if size < self.
|
783
|
-
new_col_pos = ceil(self.MT.col_positions[self.rsz_w - 1] + self.
|
784
|
-
elif size > self.
|
785
|
-
new_col_pos = floor(self.MT.col_positions[self.rsz_w - 1] + self.
|
743
|
+
if size < self.ops.min_column_width:
|
744
|
+
new_col_pos = ceil(self.MT.col_positions[self.rsz_w - 1] + self.ops.min_column_width)
|
745
|
+
elif size > self.ops.max_column_width:
|
746
|
+
new_col_pos = floor(self.MT.col_positions[self.rsz_w - 1] + self.ops.max_column_width)
|
786
747
|
increment = new_col_pos - self.MT.col_positions[self.rsz_w]
|
787
748
|
self.MT.col_positions[self.rsz_w + 1 :] = [
|
788
749
|
e + increment for e in islice(self.MT.col_positions, self.rsz_w + 1, None)
|
@@ -791,7 +752,7 @@ class ColumnHeaders(tk.Canvas):
|
|
791
752
|
new_width = self.MT.col_positions[self.rsz_w] - self.MT.col_positions[self.rsz_w - 1]
|
792
753
|
self.MT.allow_auto_resize_columns = False
|
793
754
|
self.MT.recreate_all_selection_boxes()
|
794
|
-
self.MT.main_table_redraw_grid_and_text(redraw_header=True, redraw_row_index=True)
|
755
|
+
self.MT.main_table_redraw_grid_and_text(redraw_header=True, redraw_row_index=True, set_scrollregion=False)
|
795
756
|
if self.column_width_resize_func is not None and old_width != new_width:
|
796
757
|
self.column_width_resize_func(
|
797
758
|
event_dict(
|
@@ -816,8 +777,8 @@ class ColumnHeaders(tk.Canvas):
|
|
816
777
|
self.MT.bind("<MouseWheel>", self.MT.mousewheel)
|
817
778
|
if self.width_resizing_enabled and self.rsz_w is not None and self.currently_resizing_width:
|
818
779
|
self.drag_width_resize()
|
819
|
-
self.currently_resizing_width = False
|
820
780
|
self.hide_resize_and_ctrl_lines(ctrl_lines=False)
|
781
|
+
self.MT.main_table_redraw_grid_and_text(redraw_header=True, redraw_row_index=True)
|
821
782
|
elif (
|
822
783
|
self.drag_and_drop_enabled
|
823
784
|
and self.col_selection_enabled
|
@@ -843,22 +804,16 @@ class ColumnHeaders(tk.Canvas):
|
|
843
804
|
c += 1
|
844
805
|
if c > len(self.MT.col_positions) - 1:
|
845
806
|
c = len(self.MT.col_positions) - 1
|
846
|
-
event_data =
|
847
|
-
|
848
|
-
sheet=self.PAR.name,
|
849
|
-
widget=self,
|
850
|
-
boxes=self.MT.get_boxes(),
|
851
|
-
selected=self.MT.selected,
|
852
|
-
value=c,
|
853
|
-
)
|
807
|
+
event_data = self.MT.new_event_dict("move_columns", state=True)
|
808
|
+
event_data["value"] = c
|
854
809
|
if try_binding(self.ch_extra_begin_drag_drop_func, event_data, "begin_move_columns"):
|
855
810
|
data_new_idxs, disp_new_idxs, event_data = self.MT.move_columns_adjust_options_dict(
|
856
811
|
*self.MT.get_args_for_move_columns(
|
857
812
|
move_to=c,
|
858
813
|
to_move=self.dragged_col.to_move,
|
859
814
|
),
|
860
|
-
move_data=self.
|
861
|
-
move_widths=self.
|
815
|
+
move_data=self.ops.column_drag_and_drop_perform,
|
816
|
+
move_widths=self.ops.column_drag_and_drop_perform,
|
862
817
|
event_data=event_data,
|
863
818
|
)
|
864
819
|
event_data["moved"]["columns"] = {
|
@@ -904,6 +859,126 @@ class ColumnHeaders(tk.Canvas):
|
|
904
859
|
self.mouse_motion(event)
|
905
860
|
try_binding(self.extra_b1_release_func, event)
|
906
861
|
|
862
|
+
def _sort_columns(
|
863
|
+
self,
|
864
|
+
event: tk.Event | None = None,
|
865
|
+
columns: AnyIter[int] | None = None,
|
866
|
+
reverse: bool = False,
|
867
|
+
validation: bool = True,
|
868
|
+
key: Callable | None = None,
|
869
|
+
undo: bool = True,
|
870
|
+
) -> EventDataDict:
|
871
|
+
if columns is None:
|
872
|
+
columns = self.MT.get_selected_cols()
|
873
|
+
if not columns:
|
874
|
+
columns = list(range(0, len(self.MT.col_positions) - 1))
|
875
|
+
event_data = self.MT.new_event_dict("edit_table")
|
876
|
+
try_binding(self.MT.extra_begin_sort_cells_func, event_data)
|
877
|
+
for c in columns:
|
878
|
+
datacn = self.MT.datacn(c)
|
879
|
+
for r, val in enumerate(
|
880
|
+
sort_column(
|
881
|
+
(self.MT.get_cell_data(row, datacn) for row in range(len(self.MT.data))),
|
882
|
+
reverse=reverse,
|
883
|
+
key=key,
|
884
|
+
)
|
885
|
+
):
|
886
|
+
if (
|
887
|
+
not self.MT.edit_validation_func
|
888
|
+
or not validation
|
889
|
+
or (
|
890
|
+
self.MT.edit_validation_func
|
891
|
+
and (val := self.MT.edit_validation_func(mod_event_val(event_data, val, (r, datacn))))
|
892
|
+
is not None
|
893
|
+
)
|
894
|
+
):
|
895
|
+
event_data = self.MT.event_data_set_cell(
|
896
|
+
datarn=r,
|
897
|
+
datacn=datacn,
|
898
|
+
value=val,
|
899
|
+
event_data=event_data,
|
900
|
+
)
|
901
|
+
if event_data["cells"]["table"]:
|
902
|
+
if undo and self.MT.undo_enabled:
|
903
|
+
self.MT.undo_stack.append(stored_event_dict(event_data))
|
904
|
+
try_binding(self.MT.extra_end_sort_cells_func, event_data, "end_edit_table")
|
905
|
+
self.MT.sheet_modified(event_data)
|
906
|
+
self.PAR.emit_event("<<SheetModified>>", event_data)
|
907
|
+
self.MT.refresh()
|
908
|
+
return event_data
|
909
|
+
|
910
|
+
def _sort_rows_by_column(
|
911
|
+
self,
|
912
|
+
event: tk.Event | None = None,
|
913
|
+
column: int | None = None,
|
914
|
+
reverse: bool = False,
|
915
|
+
key: Callable | None = None,
|
916
|
+
undo: bool = True,
|
917
|
+
) -> EventDataDict:
|
918
|
+
event_data = self.MT.new_event_dict("sort_rows", state=True)
|
919
|
+
if not self.MT.data:
|
920
|
+
return event_data
|
921
|
+
if column is None:
|
922
|
+
if not self.MT.selected:
|
923
|
+
return event_data
|
924
|
+
column = self.MT.selected.column
|
925
|
+
if try_binding(self.ch_extra_begin_sort_rows_func, event_data, "begin_sort_rows"):
|
926
|
+
disp_new_idxs, disp_row_ctr = {}, 0
|
927
|
+
if self.ops.treeview:
|
928
|
+
new_nodes_order, data_new_idxs = sort_tree_view(
|
929
|
+
_row_index=self.MT._row_index,
|
930
|
+
tree_rns=self.RI.tree_rns,
|
931
|
+
tree=self.RI.tree,
|
932
|
+
key=key,
|
933
|
+
reverse=reverse,
|
934
|
+
)
|
935
|
+
for node in new_nodes_order:
|
936
|
+
if (idx := try_b_index(self.MT.displayed_rows, self.RI.tree_rns[node.iid])) is not None:
|
937
|
+
disp_new_idxs[idx] = disp_row_ctr
|
938
|
+
disp_row_ctr += 1
|
939
|
+
else:
|
940
|
+
new_rows_order, data_new_idxs = sort_rows_by_column(
|
941
|
+
self.MT.data, column=column, reverse=reverse, key=key
|
942
|
+
)
|
943
|
+
if self.MT.all_rows_displayed:
|
944
|
+
disp_new_idxs = data_new_idxs
|
945
|
+
else:
|
946
|
+
for old_idx, _ in new_rows_order:
|
947
|
+
if (idx := try_b_index(self.MT.displayed_rows, old_idx)) is not None:
|
948
|
+
disp_new_idxs[idx] = disp_row_ctr
|
949
|
+
disp_row_ctr += 1
|
950
|
+
if self.PAR.ops.treeview:
|
951
|
+
data_new_idxs, disp_new_idxs, event_data = self.MT.move_rows_adjust_options_dict(
|
952
|
+
data_new_idxs=data_new_idxs,
|
953
|
+
data_old_idxs=dict(zip(data_new_idxs.values(), data_new_idxs)),
|
954
|
+
totalrows=None,
|
955
|
+
disp_new_idxs=disp_new_idxs,
|
956
|
+
move_data=True,
|
957
|
+
create_selections=False,
|
958
|
+
event_data=event_data,
|
959
|
+
)
|
960
|
+
else:
|
961
|
+
data_new_idxs, disp_new_idxs, _ = self.PAR.mapping_move_rows(
|
962
|
+
data_new_idxs=data_new_idxs,
|
963
|
+
disp_new_idxs=disp_new_idxs,
|
964
|
+
move_data=True,
|
965
|
+
create_selections=False,
|
966
|
+
undo=False,
|
967
|
+
emit_event=False,
|
968
|
+
redraw=True,
|
969
|
+
)
|
970
|
+
event_data["moved"]["rows"] = {
|
971
|
+
"data": data_new_idxs,
|
972
|
+
"displayed": disp_new_idxs,
|
973
|
+
}
|
974
|
+
if undo and self.MT.undo_enabled:
|
975
|
+
self.MT.undo_stack.append(stored_event_dict(event_data))
|
976
|
+
try_binding(self.ch_extra_end_sort_rows_func, event_data, "end_sort_rows")
|
977
|
+
self.MT.sheet_modified(event_data)
|
978
|
+
self.PAR.emit_event("<<SheetModified>>", event_data)
|
979
|
+
self.MT.refresh()
|
980
|
+
return event_data
|
981
|
+
|
907
982
|
def toggle_select_col(
|
908
983
|
self,
|
909
984
|
column: int,
|
@@ -992,7 +1067,7 @@ class ColumnHeaders(tk.Canvas):
|
|
992
1067
|
y1,
|
993
1068
|
x2,
|
994
1069
|
y2,
|
995
|
-
radius=5 if self.
|
1070
|
+
radius=5 if self.ops.rounded_boxes else 0,
|
996
1071
|
)
|
997
1072
|
if isinstance(iid, int):
|
998
1073
|
self.coords(iid, coords)
|
@@ -1019,13 +1094,13 @@ class ColumnHeaders(tk.Canvas):
|
|
1019
1094
|
self.MT.txt_measure_canvas.itemconfig(
|
1020
1095
|
self.MT.txt_measure_canvas_text,
|
1021
1096
|
text=txt,
|
1022
|
-
font=self.
|
1097
|
+
font=self.ops.header_font,
|
1023
1098
|
)
|
1024
1099
|
b = self.MT.txt_measure_canvas.bbox(self.MT.txt_measure_canvas_text)
|
1025
1100
|
w = b[2] - b[0] + 7
|
1026
1101
|
h = b[3] - b[1] + 5
|
1027
1102
|
else:
|
1028
|
-
w = self.
|
1103
|
+
w = self.ops.min_column_width
|
1029
1104
|
h = self.MT.min_header_height
|
1030
1105
|
if datacn in self.cell_options and (
|
1031
1106
|
self.get_cell_kwargs(datacn, key="dropdown") or self.get_cell_kwargs(datacn, key="checkbox")
|
@@ -1047,7 +1122,7 @@ class ColumnHeaders(tk.Canvas):
|
|
1047
1122
|
qconf = self.MT.txt_measure_canvas.itemconfig
|
1048
1123
|
qbbox = self.MT.txt_measure_canvas.bbox
|
1049
1124
|
qtxtm = self.MT.txt_measure_canvas_text
|
1050
|
-
qfont = self.
|
1125
|
+
qfont = self.ops.header_font
|
1051
1126
|
default_header_height = self.MT.get_default_header_height()
|
1052
1127
|
if text is not None and text:
|
1053
1128
|
qconf(qtxtm, text=text, font=qfont)
|
@@ -1083,8 +1158,8 @@ class ColumnHeaders(tk.Canvas):
|
|
1083
1158
|
h = space_bot
|
1084
1159
|
if h < self.MT.min_header_height:
|
1085
1160
|
h = int(self.MT.min_header_height)
|
1086
|
-
elif h > self.
|
1087
|
-
h = int(self.
|
1161
|
+
elif h > self.ops.max_header_height:
|
1162
|
+
h = int(self.ops.max_header_height)
|
1088
1163
|
if not only_if_too_small or (only_if_too_small and h > self.current_height):
|
1089
1164
|
self.set_height(h, set_TL=True)
|
1090
1165
|
self.MT.main_table_redraw_grid_and_text(redraw_header=True, redraw_row_index=True)
|
@@ -1097,7 +1172,7 @@ class ColumnHeaders(tk.Canvas):
|
|
1097
1172
|
only_if_too_small: bool = False,
|
1098
1173
|
) -> int:
|
1099
1174
|
self.fix_header()
|
1100
|
-
w = self.
|
1175
|
+
w = self.ops.min_column_width
|
1101
1176
|
datacn = col if self.MT.all_columns_displayed else self.MT.displayed_columns[col]
|
1102
1177
|
# header
|
1103
1178
|
hw, hh_ = self.get_cell_dimensions(datacn)
|
@@ -1118,7 +1193,7 @@ class ColumnHeaders(tk.Canvas):
|
|
1118
1193
|
qbbox = self.MT.txt_measure_canvas.bbox
|
1119
1194
|
qtxtm = self.MT.txt_measure_canvas_text
|
1120
1195
|
qtxth = self.MT.table_txt_height
|
1121
|
-
qfont = self.
|
1196
|
+
qfont = self.ops.table_font
|
1122
1197
|
for datarn in iterable:
|
1123
1198
|
if txt := self.MT.get_valid_cell_data_as_str(datarn, datacn, get_displayed=True):
|
1124
1199
|
qconf(qtxtm, text=txt, font=qfont)
|
@@ -1134,10 +1209,10 @@ class ColumnHeaders(tk.Canvas):
|
|
1134
1209
|
w = hw
|
1135
1210
|
if only_if_too_small and w < self.MT.col_positions[col + 1] - self.MT.col_positions[col]:
|
1136
1211
|
w = self.MT.col_positions[col + 1] - self.MT.col_positions[col]
|
1137
|
-
if w <= self.
|
1138
|
-
w = self.
|
1139
|
-
elif w > self.
|
1140
|
-
w = int(self.
|
1212
|
+
if w <= self.ops.min_column_width:
|
1213
|
+
w = self.ops.min_column_width
|
1214
|
+
elif w > self.ops.max_column_width:
|
1215
|
+
w = int(self.ops.max_column_width)
|
1141
1216
|
return w
|
1142
1217
|
|
1143
1218
|
def set_col_width(
|
@@ -1150,10 +1225,10 @@ class ColumnHeaders(tk.Canvas):
|
|
1150
1225
|
) -> int:
|
1151
1226
|
if width is None:
|
1152
1227
|
width = self.get_col_text_width(col=col, visible_only=visible_only)
|
1153
|
-
if width <= self.
|
1154
|
-
width = self.
|
1155
|
-
elif width > self.
|
1156
|
-
width = int(self.
|
1228
|
+
if width <= self.ops.min_column_width:
|
1229
|
+
width = self.ops.min_column_width
|
1230
|
+
elif width > self.ops.max_column_width:
|
1231
|
+
width = int(self.ops.max_column_width)
|
1157
1232
|
if only_if_too_small and width <= self.MT.col_positions[col + 1] - self.MT.col_positions[col]:
|
1158
1233
|
return self.MT.col_positions[col + 1] - self.MT.col_positions[col]
|
1159
1234
|
new_col_pos = self.MT.col_positions[col] + width
|
@@ -1206,8 +1281,8 @@ class ColumnHeaders(tk.Canvas):
|
|
1206
1281
|
fill = color_map[fill]
|
1207
1282
|
if "columns" in selections and c in selections["columns"]:
|
1208
1283
|
txtfg = (
|
1209
|
-
self.
|
1210
|
-
if kwargs[1] is None or self.
|
1284
|
+
self.ops.header_selected_columns_fg
|
1285
|
+
if kwargs[1] is None or self.ops.display_selected_fg_over_highlights
|
1211
1286
|
else kwargs[1]
|
1212
1287
|
)
|
1213
1288
|
if fill:
|
@@ -1218,8 +1293,8 @@ class ColumnHeaders(tk.Canvas):
|
|
1218
1293
|
)
|
1219
1294
|
elif "cells" in selections and c in selections["cells"]:
|
1220
1295
|
txtfg = (
|
1221
|
-
self.
|
1222
|
-
if kwargs[1] is None or self.
|
1296
|
+
self.ops.header_selected_cells_fg
|
1297
|
+
if kwargs[1] is None or self.ops.display_selected_fg_over_highlights
|
1223
1298
|
else kwargs[1]
|
1224
1299
|
)
|
1225
1300
|
if fill:
|
@@ -1229,7 +1304,7 @@ class ColumnHeaders(tk.Canvas):
|
|
1229
1304
|
+ f"{int((int(fill[5:], 16) + int(sel_cells_bg[5:], 16)) / 2):02X}"
|
1230
1305
|
)
|
1231
1306
|
else:
|
1232
|
-
txtfg = self.
|
1307
|
+
txtfg = self.ops.header_fg if kwargs[1] is None else kwargs[1]
|
1233
1308
|
if fill:
|
1234
1309
|
redrawn = self.redraw_highlight(
|
1235
1310
|
fc + 1,
|
@@ -1238,19 +1313,19 @@ class ColumnHeaders(tk.Canvas):
|
|
1238
1313
|
self.current_height - 1,
|
1239
1314
|
fill=fill,
|
1240
1315
|
outline=(
|
1241
|
-
self.
|
1242
|
-
if self.get_cell_kwargs(datacn, key="dropdown") and self.
|
1316
|
+
self.ops.header_fg
|
1317
|
+
if self.get_cell_kwargs(datacn, key="dropdown") and self.ops.show_dropdown_borders
|
1243
1318
|
else ""
|
1244
1319
|
),
|
1245
1320
|
tag="hi",
|
1246
1321
|
)
|
1247
1322
|
elif not kwargs:
|
1248
1323
|
if "columns" in selections and c in selections["columns"]:
|
1249
|
-
txtfg = self.
|
1324
|
+
txtfg = self.ops.header_selected_columns_fg
|
1250
1325
|
elif "cells" in selections and c in selections["cells"]:
|
1251
|
-
txtfg = self.
|
1326
|
+
txtfg = self.ops.header_selected_cells_fg
|
1252
1327
|
else:
|
1253
|
-
txtfg = self.
|
1328
|
+
txtfg = self.ops.header_fg
|
1254
1329
|
return txtfg, redrawn
|
1255
1330
|
|
1256
1331
|
def redraw_highlight(
|
@@ -1271,6 +1346,7 @@ class ColumnHeaders(tk.Canvas):
|
|
1271
1346
|
self.itemconfig(iid, fill=fill, outline=outline)
|
1272
1347
|
else:
|
1273
1348
|
self.itemconfig(iid, fill=fill, outline=outline, tag=tag, state="normal")
|
1349
|
+
self.tag_raise(iid)
|
1274
1350
|
else:
|
1275
1351
|
iid = self.create_rectangle(coords, fill=fill, outline=outline, tag=tag)
|
1276
1352
|
self.disp_high[iid] = True
|
@@ -1291,6 +1367,7 @@ class ColumnHeaders(tk.Canvas):
|
|
1291
1367
|
else:
|
1292
1368
|
self.itemconfig(t, fill=fill, width=width, tag=tag, state="normal")
|
1293
1369
|
self.disp_grid[t] = True
|
1370
|
+
self.tag_raise(t)
|
1294
1371
|
else:
|
1295
1372
|
self.disp_grid[self.create_line(points, fill=fill, width=width, tag=tag)] = True
|
1296
1373
|
|
@@ -1307,8 +1384,8 @@ class ColumnHeaders(tk.Canvas):
|
|
1307
1384
|
draw_arrow: bool = True,
|
1308
1385
|
open_: bool = False,
|
1309
1386
|
) -> None:
|
1310
|
-
if draw_outline and self.
|
1311
|
-
self.redraw_highlight(x1 + 1, y1 + 1, x2, y2, fill="", outline=self.
|
1387
|
+
if draw_outline and self.ops.show_dropdown_borders:
|
1388
|
+
self.redraw_highlight(x1 + 1, y1 + 1, x2, y2, fill="", outline=self.ops.header_fg, tag=tag)
|
1312
1389
|
if draw_arrow:
|
1313
1390
|
mod = (self.MT.header_txt_height - 1) if self.MT.header_txt_height % 2 else self.MT.header_txt_height
|
1314
1391
|
small_mod = int(mod / 5)
|
@@ -1394,15 +1471,33 @@ class ColumnHeaders(tk.Canvas):
|
|
1394
1471
|
t = self.create_polygon(points, fill=fill, outline=outline, tag=tag, smooth=True)
|
1395
1472
|
self.disp_checkbox[t] = True
|
1396
1473
|
|
1397
|
-
def configure_scrollregion(self, last_col_line_pos: float) ->
|
1398
|
-
|
1399
|
-
|
1400
|
-
|
1401
|
-
|
1402
|
-
|
1403
|
-
|
1474
|
+
def configure_scrollregion(self, last_col_line_pos: float) -> bool:
|
1475
|
+
try:
|
1476
|
+
self.configure(
|
1477
|
+
scrollregion=(
|
1478
|
+
0,
|
1479
|
+
0,
|
1480
|
+
last_col_line_pos + self.ops.empty_horizontal + 2,
|
1481
|
+
self.current_height,
|
1482
|
+
)
|
1404
1483
|
)
|
1484
|
+
return True
|
1485
|
+
except Exception:
|
1486
|
+
return False
|
1487
|
+
|
1488
|
+
def wrap_get_char_w(self, c: str) -> int:
|
1489
|
+
self.MT.txt_measure_canvas.itemconfig(
|
1490
|
+
self.MT.txt_measure_canvas_text,
|
1491
|
+
text=_test_str + c,
|
1492
|
+
font=self.header_font,
|
1405
1493
|
)
|
1494
|
+
b = self.MT.txt_measure_canvas.bbox(self.MT.txt_measure_canvas_text)
|
1495
|
+
if c in self.MT.char_widths[self.header_font]:
|
1496
|
+
return self.MT.char_widths[self.header_font][c]
|
1497
|
+
else:
|
1498
|
+
wd = b[2] - b[0] - self.header_test_str_w
|
1499
|
+
self.MT.char_widths[self.header_font][c] = wd
|
1500
|
+
return wd
|
1406
1501
|
|
1407
1502
|
def redraw_grid_and_text(
|
1408
1503
|
self,
|
@@ -1415,11 +1510,11 @@ class ColumnHeaders(tk.Canvas):
|
|
1415
1510
|
text_end_col: int,
|
1416
1511
|
scrollpos_right: float,
|
1417
1512
|
col_pos_exists: bool,
|
1513
|
+
set_scrollregion: bool,
|
1418
1514
|
) -> bool:
|
1419
|
-
|
1420
|
-
self.configure_scrollregion(last_col_line_pos=last_col_line_pos)
|
1421
|
-
|
1422
|
-
return False
|
1515
|
+
if set_scrollregion:
|
1516
|
+
if not self.configure_scrollregion(last_col_line_pos=last_col_line_pos):
|
1517
|
+
return False
|
1423
1518
|
self.hidd_text.update(self.disp_text)
|
1424
1519
|
self.disp_text = {}
|
1425
1520
|
self.hidd_high.update(self.disp_high)
|
@@ -1437,49 +1532,24 @@ class ColumnHeaders(tk.Canvas):
|
|
1437
1532
|
x_stop,
|
1438
1533
|
self.current_height,
|
1439
1534
|
)
|
1440
|
-
yend = self.current_height - 5
|
1441
|
-
if (self.PAR.ops.show_vertical_grid or self.width_resizing_enabled) and col_pos_exists:
|
1442
|
-
points = [
|
1443
|
-
x_stop - 1,
|
1444
|
-
self.current_height - 1,
|
1445
|
-
scrollpos_left - 1,
|
1446
|
-
self.current_height - 1,
|
1447
|
-
scrollpos_left - 1,
|
1448
|
-
-1,
|
1449
|
-
]
|
1450
|
-
for c in range(grid_start_col, grid_end_col):
|
1451
|
-
draw_x = self.MT.col_positions[c]
|
1452
|
-
if c and self.width_resizing_enabled:
|
1453
|
-
self.visible_col_dividers[c] = (draw_x - 2, 1, draw_x + 2, yend)
|
1454
|
-
points.extend(
|
1455
|
-
(
|
1456
|
-
draw_x,
|
1457
|
-
-1,
|
1458
|
-
draw_x,
|
1459
|
-
self.current_height,
|
1460
|
-
draw_x,
|
1461
|
-
-1,
|
1462
|
-
self.MT.col_positions[c + 1] if len(self.MT.col_positions) - 1 > c else draw_x,
|
1463
|
-
-1,
|
1464
|
-
)
|
1465
|
-
)
|
1466
|
-
self.redraw_gridline(points=points, fill=self.PAR.ops.header_grid_fg, width=1, tag="v")
|
1467
1535
|
top = self.canvasy(0)
|
1468
1536
|
sel_cols_bg = (
|
1469
|
-
self.
|
1470
|
-
if self.
|
1471
|
-
else color_map[self.
|
1537
|
+
self.ops.header_selected_cells_bg
|
1538
|
+
if self.ops.header_selected_cells_bg.startswith("#")
|
1539
|
+
else color_map[self.ops.header_selected_cells_bg]
|
1472
1540
|
)
|
1473
1541
|
sel_cells_bg = (
|
1474
|
-
self.
|
1475
|
-
if self.
|
1476
|
-
else color_map[self.
|
1542
|
+
self.ops.header_selected_columns_bg
|
1543
|
+
if self.ops.header_selected_columns_bg.startswith("#")
|
1544
|
+
else color_map[self.ops.header_selected_columns_bg]
|
1477
1545
|
)
|
1478
|
-
font = self.
|
1546
|
+
font = self.ops.header_font
|
1479
1547
|
selections = self.get_redraw_selections(text_start_col, grid_end_col)
|
1480
1548
|
dd_coords = self.dropdown.get_coords()
|
1549
|
+
wrap = self.ops.header_wrap
|
1550
|
+
txt_h = self.MT.header_txt_height
|
1481
1551
|
for c in range(text_start_col, text_end_col):
|
1482
|
-
draw_y =
|
1552
|
+
draw_y = 3
|
1483
1553
|
cleftgridln = self.MT.col_positions[c]
|
1484
1554
|
crightgridln = self.MT.col_positions[c + 1]
|
1485
1555
|
datacn = c if self.MT.all_columns_displayed else self.MT.displayed_columns[c]
|
@@ -1492,80 +1562,45 @@ class ColumnHeaders(tk.Canvas):
|
|
1492
1562
|
selections=selections,
|
1493
1563
|
datacn=datacn,
|
1494
1564
|
)
|
1495
|
-
|
1496
1565
|
if datacn in self.cell_options and "align" in self.cell_options[datacn]:
|
1497
1566
|
align = self.cell_options[datacn]["align"]
|
1498
1567
|
else:
|
1499
1568
|
align = self.align
|
1500
|
-
|
1501
|
-
|
1502
|
-
|
1503
|
-
|
1504
|
-
|
1505
|
-
|
1506
|
-
|
1507
|
-
|
1508
|
-
|
1509
|
-
|
1510
|
-
|
1511
|
-
|
1512
|
-
|
1513
|
-
|
1514
|
-
|
1515
|
-
|
1516
|
-
|
1517
|
-
|
1518
|
-
|
1519
|
-
|
1520
|
-
|
1521
|
-
|
1522
|
-
if
|
1523
|
-
|
1524
|
-
|
1525
|
-
|
1526
|
-
|
1527
|
-
0,
|
1528
|
-
crightgridln,
|
1529
|
-
self.current_height - 1,
|
1530
|
-
fill=fill if kwargs["state"] != "disabled" else self.PAR.ops.header_grid_fg,
|
1531
|
-
outline=fill,
|
1532
|
-
tag="dd",
|
1533
|
-
draw_outline=not dd_drawn,
|
1534
|
-
draw_arrow=mw >= 5,
|
1535
|
-
open_=dd_coords == c,
|
1536
|
-
)
|
1537
|
-
else:
|
1538
|
-
mw = crightgridln - cleftgridln - 1
|
1539
|
-
draw_x = crightgridln - 3
|
1540
|
-
|
1541
|
-
elif align == "center":
|
1542
|
-
if kwargs:
|
1543
|
-
mw = crightgridln - cleftgridln - self.MT.header_txt_height - 2
|
1544
|
-
draw_x = cleftgridln + ceil((crightgridln - cleftgridln - self.MT.header_txt_height) / 2)
|
1545
|
-
self.redraw_dropdown(
|
1546
|
-
cleftgridln,
|
1547
|
-
0,
|
1548
|
-
crightgridln,
|
1549
|
-
self.current_height - 1,
|
1550
|
-
fill=fill if kwargs["state"] != "disabled" else self.PAR.ops.header_grid_fg,
|
1551
|
-
outline=fill,
|
1552
|
-
tag="dd",
|
1553
|
-
draw_outline=not dd_drawn,
|
1554
|
-
draw_arrow=mw >= 5,
|
1555
|
-
open_=dd_coords == c,
|
1556
|
-
)
|
1557
|
-
else:
|
1558
|
-
mw = crightgridln - cleftgridln - 1
|
1569
|
+
if kwargs := self.get_cell_kwargs(datacn, key="dropdown"):
|
1570
|
+
max_width = crightgridln - cleftgridln - txt_h - 2
|
1571
|
+
if align.endswith("w"):
|
1572
|
+
draw_x = cleftgridln + 2
|
1573
|
+
elif align.endswith("e"):
|
1574
|
+
draw_x = crightgridln - 5 - txt_h
|
1575
|
+
elif align.endswith("n"):
|
1576
|
+
draw_x = cleftgridln + ceil((crightgridln - cleftgridln - txt_h) / 2)
|
1577
|
+
self.redraw_dropdown(
|
1578
|
+
cleftgridln,
|
1579
|
+
0,
|
1580
|
+
crightgridln,
|
1581
|
+
self.current_height - 1,
|
1582
|
+
fill=fill if kwargs["state"] != "disabled" else self.ops.header_grid_fg,
|
1583
|
+
outline=fill,
|
1584
|
+
tag="dd",
|
1585
|
+
draw_outline=not dd_drawn,
|
1586
|
+
draw_arrow=max_width >= 5,
|
1587
|
+
open_=dd_coords == c,
|
1588
|
+
)
|
1589
|
+
else:
|
1590
|
+
max_width = crightgridln - cleftgridln - 2
|
1591
|
+
if align.endswith("w"):
|
1592
|
+
draw_x = cleftgridln + 2
|
1593
|
+
elif align.endswith("e"):
|
1594
|
+
draw_x = crightgridln - 2
|
1595
|
+
elif align.endswith("n"):
|
1559
1596
|
draw_x = cleftgridln + floor((crightgridln - cleftgridln) / 2)
|
1560
|
-
|
1561
|
-
|
1562
|
-
|
1563
|
-
box_w = self.MT.header_txt_height + 1
|
1564
|
-
if align == "w":
|
1597
|
+
if (kwargs := self.get_cell_kwargs(datacn, key="checkbox")) and max_width > txt_h + 1:
|
1598
|
+
box_w = txt_h + 1
|
1599
|
+
if align.endswith("w"):
|
1565
1600
|
draw_x += box_w + 3
|
1566
|
-
elif align
|
1601
|
+
elif align.endswith("n"):
|
1567
1602
|
draw_x += ceil(box_w / 2) + 1
|
1568
|
-
|
1603
|
+
max_width -= box_w + 4
|
1569
1604
|
try:
|
1570
1605
|
draw_check = (
|
1571
1606
|
self.MT._headers[datacn]
|
@@ -1577,98 +1612,99 @@ class ColumnHeaders(tk.Canvas):
|
|
1577
1612
|
self.redraw_checkbox(
|
1578
1613
|
cleftgridln + 2,
|
1579
1614
|
2,
|
1580
|
-
cleftgridln +
|
1581
|
-
|
1582
|
-
fill=fill if kwargs["state"] == "normal" else self.
|
1615
|
+
cleftgridln + txt_h + 3,
|
1616
|
+
txt_h + 3,
|
1617
|
+
fill=fill if kwargs["state"] == "normal" else self.ops.header_grid_fg,
|
1583
1618
|
outline="",
|
1584
1619
|
tag="cb",
|
1585
1620
|
draw_check=draw_check,
|
1586
1621
|
)
|
1587
|
-
|
1588
|
-
|
1622
|
+
if (
|
1623
|
+
max_width < self.MT.header_txt_width
|
1624
|
+
or (align.endswith("w") and draw_x > scrollpos_right)
|
1625
|
+
or (align.endswith("e") and cleftgridln + 5 > scrollpos_right)
|
1626
|
+
or (align.endswith("n") and cleftgridln + 5 > scrollpos_right)
|
1627
|
+
):
|
1628
|
+
continue
|
1629
|
+
text = self.get_valid_cell_data_as_str(datacn, fix=False)
|
1630
|
+
if not text:
|
1589
1631
|
continue
|
1590
|
-
|
1591
|
-
|
1592
|
-
|
1593
|
-
|
1594
|
-
|
1632
|
+
max_lines = int((self.current_height - top - 2) / txt_h)
|
1633
|
+
for text in wrap_text(
|
1634
|
+
text=text,
|
1635
|
+
max_width=max_width,
|
1636
|
+
max_lines=max_lines,
|
1637
|
+
char_width_fn=self.wrap_get_char_w,
|
1638
|
+
widths=self.MT.char_widths[font],
|
1639
|
+
wrap=wrap,
|
1595
1640
|
):
|
1596
|
-
|
1597
|
-
|
1598
|
-
self.
|
1599
|
-
|
1600
|
-
|
1601
|
-
|
1602
|
-
|
1603
|
-
|
1604
|
-
|
1605
|
-
|
1606
|
-
|
1607
|
-
|
1608
|
-
|
1609
|
-
|
1610
|
-
|
1611
|
-
|
1612
|
-
|
1613
|
-
|
1614
|
-
|
1615
|
-
|
1616
|
-
|
1617
|
-
|
1618
|
-
|
1619
|
-
|
1620
|
-
|
1621
|
-
|
1622
|
-
|
1623
|
-
|
1624
|
-
|
1625
|
-
|
1626
|
-
|
1627
|
-
|
1628
|
-
|
1629
|
-
|
1630
|
-
|
1631
|
-
|
1632
|
-
|
1633
|
-
|
1634
|
-
|
1635
|
-
|
1636
|
-
|
1637
|
-
|
1638
|
-
|
1639
|
-
|
1640
|
-
|
1641
|
-
|
1642
|
-
|
1643
|
-
|
1644
|
-
|
1645
|
-
|
1646
|
-
|
1647
|
-
|
1648
|
-
|
1649
|
-
|
1650
|
-
|
1651
|
-
|
1652
|
-
|
1653
|
-
|
1654
|
-
|
1655
|
-
|
1656
|
-
txt = txt[tmod - 1 : -tmod]
|
1657
|
-
self.itemconfig(iid, text=txt)
|
1658
|
-
wd = self.bbox(iid)
|
1659
|
-
while wd[2] - wd[0] > mw:
|
1660
|
-
txt = txt[next(self.c_align_cyc)]
|
1661
|
-
self.itemconfig(iid, text=txt)
|
1662
|
-
wd = self.bbox(iid)
|
1663
|
-
self.coords(iid, draw_x, draw_y)
|
1664
|
-
draw_y += self.MT.header_xtra_lines_increment
|
1665
|
-
if draw_y - 1 > self.current_height:
|
1666
|
-
break
|
1641
|
+
if self.hidd_text:
|
1642
|
+
iid, showing = self.hidd_text.popitem()
|
1643
|
+
self.coords(iid, draw_x, draw_y)
|
1644
|
+
if showing:
|
1645
|
+
self.itemconfig(
|
1646
|
+
iid,
|
1647
|
+
text=text,
|
1648
|
+
fill=fill,
|
1649
|
+
font=font,
|
1650
|
+
anchor=align,
|
1651
|
+
)
|
1652
|
+
else:
|
1653
|
+
self.itemconfig(
|
1654
|
+
iid,
|
1655
|
+
text=text,
|
1656
|
+
fill=fill,
|
1657
|
+
font=font,
|
1658
|
+
anchor=align,
|
1659
|
+
state="normal",
|
1660
|
+
)
|
1661
|
+
self.tag_raise(iid)
|
1662
|
+
else:
|
1663
|
+
iid = self.create_text(
|
1664
|
+
draw_x,
|
1665
|
+
draw_y,
|
1666
|
+
text=text,
|
1667
|
+
fill=fill,
|
1668
|
+
font=font,
|
1669
|
+
anchor=align,
|
1670
|
+
tags="t",
|
1671
|
+
)
|
1672
|
+
self.disp_text[iid] = True
|
1673
|
+
draw_y += self.MT.header_txt_height
|
1674
|
+
yend = self.current_height - 5
|
1675
|
+
if (self.ops.show_vertical_grid or self.width_resizing_enabled) and col_pos_exists:
|
1676
|
+
points = [
|
1677
|
+
x_stop - 1,
|
1678
|
+
self.current_height - 1,
|
1679
|
+
scrollpos_left - 1,
|
1680
|
+
self.current_height - 1,
|
1681
|
+
scrollpos_left - 1,
|
1682
|
+
-1,
|
1683
|
+
]
|
1684
|
+
for c in range(grid_start_col, grid_end_col):
|
1685
|
+
draw_x = self.MT.col_positions[c]
|
1686
|
+
if c and self.width_resizing_enabled:
|
1687
|
+
self.visible_col_dividers[c] = (draw_x - 2, 1, draw_x + 2, yend)
|
1688
|
+
points.extend(
|
1689
|
+
(
|
1690
|
+
draw_x,
|
1691
|
+
-1,
|
1692
|
+
draw_x,
|
1693
|
+
self.current_height,
|
1694
|
+
draw_x,
|
1695
|
+
-1,
|
1696
|
+
self.MT.col_positions[c + 1] if len(self.MT.col_positions) - 1 > c else draw_x,
|
1697
|
+
-1,
|
1698
|
+
)
|
1699
|
+
)
|
1700
|
+
self.redraw_gridline(points=points, fill=self.ops.header_grid_fg, width=1, tag="v")
|
1667
1701
|
for dct in (self.hidd_text, self.hidd_high, self.hidd_grid, self.hidd_dropdown, self.hidd_checkbox):
|
1668
1702
|
for iid, showing in dct.items():
|
1669
1703
|
if showing:
|
1670
1704
|
self.itemconfig(iid, state="hidden")
|
1671
1705
|
dct[iid] = False
|
1706
|
+
if self.disp_resize_lines:
|
1707
|
+
self.tag_raise("rw")
|
1672
1708
|
return True
|
1673
1709
|
|
1674
1710
|
def get_redraw_selections(self, startc: int, endc: int) -> dict[str, set[int]]:
|
@@ -1747,7 +1783,7 @@ class ColumnHeaders(tk.Canvas):
|
|
1747
1783
|
return False
|
1748
1784
|
else:
|
1749
1785
|
text = text if isinstance(text, str) else f"{text}"
|
1750
|
-
if self.
|
1786
|
+
if self.ops.cell_auto_resize_enabled:
|
1751
1787
|
if self.height_resizing_enabled:
|
1752
1788
|
self.set_height_of_header_to_text(text)
|
1753
1789
|
self.set_col_width_run_binding(c)
|
@@ -1756,7 +1792,7 @@ class ColumnHeaders(tk.Canvas):
|
|
1756
1792
|
return False
|
1757
1793
|
self.hide_text_editor()
|
1758
1794
|
if not self.MT.see(r=0, c=c, keep_yscroll=True, check_cell_visibility=True):
|
1759
|
-
self.MT.
|
1795
|
+
self.MT.main_table_redraw_grid_and_text(True, True)
|
1760
1796
|
x = self.MT.col_positions[c] + 1
|
1761
1797
|
y = 0
|
1762
1798
|
w = self.MT.col_positions[c + 1] - x
|
@@ -1764,24 +1800,24 @@ class ColumnHeaders(tk.Canvas):
|
|
1764
1800
|
kwargs = {
|
1765
1801
|
"menu_kwargs": DotDict(
|
1766
1802
|
{
|
1767
|
-
"font": self.
|
1768
|
-
"foreground": self.
|
1769
|
-
"background": self.
|
1770
|
-
"activebackground": self.
|
1771
|
-
"activeforeground": self.
|
1803
|
+
"font": self.ops.table_font,
|
1804
|
+
"foreground": self.ops.popup_menu_fg,
|
1805
|
+
"background": self.ops.popup_menu_bg,
|
1806
|
+
"activebackground": self.ops.popup_menu_highlight_bg,
|
1807
|
+
"activeforeground": self.ops.popup_menu_highlight_fg,
|
1772
1808
|
}
|
1773
1809
|
),
|
1774
|
-
"sheet_ops": self.
|
1775
|
-
"border_color": self.
|
1810
|
+
"sheet_ops": self.ops,
|
1811
|
+
"border_color": self.ops.header_selected_columns_bg,
|
1776
1812
|
"text": text,
|
1777
1813
|
"state": state,
|
1778
1814
|
"width": w,
|
1779
1815
|
"height": h,
|
1780
1816
|
"show_border": True,
|
1781
|
-
"bg": self.
|
1782
|
-
"fg": self.
|
1783
|
-
"select_bg": self.
|
1784
|
-
"select_fg": self.
|
1817
|
+
"bg": self.ops.header_editor_bg,
|
1818
|
+
"fg": self.ops.header_editor_fg,
|
1819
|
+
"select_bg": self.ops.header_editor_select_bg,
|
1820
|
+
"select_fg": self.ops.header_editor_select_fg,
|
1785
1821
|
"align": self.get_cell_align(c),
|
1786
1822
|
"c": c,
|
1787
1823
|
}
|
@@ -1841,7 +1877,7 @@ class ColumnHeaders(tk.Canvas):
|
|
1841
1877
|
> curr_height
|
1842
1878
|
):
|
1843
1879
|
c = self.text_editor.column
|
1844
|
-
new_height = curr_height + self.MT.
|
1880
|
+
new_height = curr_height + self.MT.header_txt_height
|
1845
1881
|
space_bot = self.MT.get_space_bot(0)
|
1846
1882
|
if new_height > space_bot:
|
1847
1883
|
new_height = space_bot
|
@@ -1864,7 +1900,7 @@ class ColumnHeaders(tk.Canvas):
|
|
1864
1900
|
height=self.current_height,
|
1865
1901
|
width=self.MT.col_positions[c + 1] - self.MT.col_positions[c] + 1,
|
1866
1902
|
)
|
1867
|
-
self.text_editor.tktext.config(font=self.
|
1903
|
+
self.text_editor.tktext.config(font=self.ops.header_font)
|
1868
1904
|
self.coords(
|
1869
1905
|
self.text_editor.canvas_id,
|
1870
1906
|
self.MT.col_positions[c],
|
@@ -1972,15 +2008,12 @@ class ColumnHeaders(tk.Canvas):
|
|
1972
2008
|
for i, v in enumerate(self.get_cell_kwargs(datacn, key="dropdown")["values"]):
|
1973
2009
|
v_numlines = len(v.split("\n") if isinstance(v, str) else f"{v}".split("\n"))
|
1974
2010
|
if v_numlines > 1:
|
1975
|
-
win_h += (
|
1976
|
-
self.MT.header_first_ln_ins + (v_numlines * self.MT.header_xtra_lines_increment) + 5
|
1977
|
-
) # end of cell
|
2011
|
+
win_h += self.MT.header_txt_height + (v_numlines * self.MT.header_txt_height) + 5 # end of cell
|
1978
2012
|
else:
|
1979
2013
|
win_h += self.MT.min_header_height
|
1980
2014
|
if i == 5:
|
1981
2015
|
break
|
1982
|
-
|
1983
|
-
win_h = 500
|
2016
|
+
win_h = min(win_h, 500)
|
1984
2017
|
space_bot = self.MT.get_space_bot(0, text_editor_h)
|
1985
2018
|
win_h2 = int(win_h)
|
1986
2019
|
if win_h > space_bot:
|
@@ -2029,15 +2062,15 @@ class ColumnHeaders(tk.Canvas):
|
|
2029
2062
|
reset_kwargs = {
|
2030
2063
|
"r": 0,
|
2031
2064
|
"c": c,
|
2032
|
-
"bg": self.
|
2033
|
-
"fg": self.
|
2034
|
-
"select_bg": self.
|
2035
|
-
"select_fg": self.
|
2065
|
+
"bg": self.ops.header_editor_bg,
|
2066
|
+
"fg": self.ops.header_editor_fg,
|
2067
|
+
"select_bg": self.ops.header_editor_select_bg,
|
2068
|
+
"select_fg": self.ops.header_editor_select_fg,
|
2036
2069
|
"width": win_w,
|
2037
2070
|
"height": win_h,
|
2038
|
-
"font": self.
|
2039
|
-
"ops": self.
|
2040
|
-
"outline_color": self.
|
2071
|
+
"font": self.ops.header_font,
|
2072
|
+
"ops": self.ops,
|
2073
|
+
"outline_color": self.ops.header_selected_columns_bg,
|
2041
2074
|
"align": self.get_cell_align(c),
|
2042
2075
|
"values": kwargs["values"],
|
2043
2076
|
"search_function": kwargs["search_function"],
|
@@ -2049,7 +2082,7 @@ class ColumnHeaders(tk.Canvas):
|
|
2049
2082
|
self.coords(self.dropdown.canvas_id, self.MT.col_positions[c], ypos)
|
2050
2083
|
self.dropdown.window.tkraise()
|
2051
2084
|
else:
|
2052
|
-
self.dropdown.window = self.PAR.
|
2085
|
+
self.dropdown.window = self.PAR._dropdown_cls(
|
2053
2086
|
self.winfo_toplevel(),
|
2054
2087
|
**reset_kwargs,
|
2055
2088
|
single_index="c",
|
@@ -2092,13 +2125,11 @@ class ColumnHeaders(tk.Canvas):
|
|
2092
2125
|
if c is not None and selection is not None:
|
2093
2126
|
datacn = c if self.MT.all_columns_displayed else self.MT.displayed_columns[c]
|
2094
2127
|
kwargs = self.get_cell_kwargs(datacn, key="dropdown")
|
2095
|
-
pre_edit_value = self.get_cell_data(datacn)
|
2096
|
-
edited = False
|
2097
2128
|
event_data = event_dict(
|
2098
2129
|
name="end_edit_header",
|
2099
2130
|
sheet=self.PAR.name,
|
2100
2131
|
widget=self,
|
2101
|
-
cells_header={datacn:
|
2132
|
+
cells_header={datacn: self.get_cell_data(datacn)},
|
2102
2133
|
key="??",
|
2103
2134
|
value=selection,
|
2104
2135
|
loc=c,
|
@@ -2106,16 +2137,12 @@ class ColumnHeaders(tk.Canvas):
|
|
2106
2137
|
boxes=self.MT.get_boxes(),
|
2107
2138
|
selected=self.MT.selected,
|
2108
2139
|
)
|
2109
|
-
|
2110
|
-
|
2111
|
-
if
|
2112
|
-
selection = self.MT.edit_validation_func(event_data)
|
2113
|
-
if selection is not None:
|
2114
|
-
edited = self.set_cell_data_undo(c, datacn=datacn, value=selection, redraw=not redraw)
|
2115
|
-
else:
|
2140
|
+
try_binding(kwargs["select_function"], event_data)
|
2141
|
+
selection = selection if not self.MT.edit_validation_func else self.MT.edit_validation_func(event_data)
|
2142
|
+
if selection is not None:
|
2116
2143
|
edited = self.set_cell_data_undo(c, datacn=datacn, value=selection, redraw=not redraw)
|
2117
|
-
|
2118
|
-
|
2144
|
+
if edited:
|
2145
|
+
try_binding(self.extra_end_edit_cell_func, event_data)
|
2119
2146
|
self.MT.recreate_all_selection_boxes()
|
2120
2147
|
self.focus_set()
|
2121
2148
|
self.hide_text_editor_and_dropdown(redraw=redraw)
|
@@ -2191,7 +2218,7 @@ class ColumnHeaders(tk.Canvas):
|
|
2191
2218
|
self.MT.undo_stack.append(stored_event_dict(event_data))
|
2192
2219
|
self.set_cell_data(datacn=datacn, value=value)
|
2193
2220
|
edited = True
|
2194
|
-
if edited and cell_resize and self.
|
2221
|
+
if edited and cell_resize and self.ops.cell_auto_resize_enabled:
|
2195
2222
|
if self.height_resizing_enabled:
|
2196
2223
|
self.set_height_of_header_to_text(self.get_valid_cell_data_as_str(datacn, fix=False))
|
2197
2224
|
self.set_col_width_run_binding(c)
|
@@ -2264,11 +2291,15 @@ class ColumnHeaders(tk.Canvas):
|
|
2264
2291
|
if fix:
|
2265
2292
|
self.fix_header(datacn)
|
2266
2293
|
try:
|
2267
|
-
value =
|
2294
|
+
value = self.MT._headers[datacn]
|
2295
|
+
if value is None:
|
2296
|
+
value = ""
|
2297
|
+
elif not isinstance(value, str):
|
2298
|
+
value = f"{value}"
|
2268
2299
|
except Exception:
|
2269
2300
|
value = ""
|
2270
|
-
if not value and self.
|
2271
|
-
value = get_n2a(datacn, self.
|
2301
|
+
if not value and self.ops.show_default_header_for_empty:
|
2302
|
+
value = get_n2a(datacn, self.ops.default_header)
|
2272
2303
|
return value
|
2273
2304
|
|
2274
2305
|
def get_value_for_empty_cell(self, datacn: int, c_ops: bool = True) -> object:
|