tksheet 7.2.9__tar.gz → 7.2.11__tar.gz

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.
Files changed (24) hide show
  1. {tksheet-7.2.9/tksheet.egg-info → tksheet-7.2.11}/PKG-INFO +1 -1
  2. {tksheet-7.2.9 → tksheet-7.2.11}/pyproject.toml +1 -1
  3. {tksheet-7.2.9 → tksheet-7.2.11}/tksheet/__init__.py +1 -1
  4. {tksheet-7.2.9 → tksheet-7.2.11}/tksheet/column_headers.py +42 -40
  5. {tksheet-7.2.9 → tksheet-7.2.11}/tksheet/main_table.py +27 -27
  6. {tksheet-7.2.9 → tksheet-7.2.11}/tksheet/other_classes.py +57 -18
  7. {tksheet-7.2.9 → tksheet-7.2.11}/tksheet/row_index.py +66 -68
  8. {tksheet-7.2.9 → tksheet-7.2.11}/tksheet/sheet.py +71 -29
  9. {tksheet-7.2.9 → tksheet-7.2.11}/tksheet/themes.py +4 -4
  10. {tksheet-7.2.9 → tksheet-7.2.11}/tksheet/top_left_rectangle.py +9 -10
  11. {tksheet-7.2.9 → tksheet-7.2.11/tksheet.egg-info}/PKG-INFO +1 -1
  12. {tksheet-7.2.9 → tksheet-7.2.11}/LICENSE.txt +0 -0
  13. {tksheet-7.2.9 → tksheet-7.2.11}/README.md +0 -0
  14. {tksheet-7.2.9 → tksheet-7.2.11}/setup.cfg +0 -0
  15. {tksheet-7.2.9 → tksheet-7.2.11}/tksheet/colors.py +0 -0
  16. {tksheet-7.2.9 → tksheet-7.2.11}/tksheet/formatters.py +0 -0
  17. {tksheet-7.2.9 → tksheet-7.2.11}/tksheet/functions.py +0 -0
  18. {tksheet-7.2.9 → tksheet-7.2.11}/tksheet/sheet_options.py +0 -0
  19. {tksheet-7.2.9 → tksheet-7.2.11}/tksheet/text_editor.py +0 -0
  20. {tksheet-7.2.9 → tksheet-7.2.11}/tksheet/types.py +0 -0
  21. {tksheet-7.2.9 → tksheet-7.2.11}/tksheet/vars.py +0 -0
  22. {tksheet-7.2.9 → tksheet-7.2.11}/tksheet.egg-info/SOURCES.txt +0 -0
  23. {tksheet-7.2.9 → tksheet-7.2.11}/tksheet.egg-info/dependency_links.txt +0 -0
  24. {tksheet-7.2.9 → tksheet-7.2.11}/tksheet.egg-info/top_level.txt +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: tksheet
3
- Version: 7.2.9
3
+ Version: 7.2.11
4
4
  Summary: Tkinter table / sheet widget
5
5
  Author-email: ragardner <github@ragardner.simplelogin.com>
6
6
  License: Copyright (c) 2019 ragardner and open source contributors
@@ -6,7 +6,7 @@ build-backend = "setuptools.build_meta"
6
6
  name = "tksheet"
7
7
  description = "Tkinter table / sheet widget"
8
8
  readme = "README.md"
9
- version = "7.2.9"
9
+ version = "7.2.11"
10
10
  authors = [{ name = "ragardner", email = "github@ragardner.simplelogin.com" }]
11
11
  requires-python = ">=3.8"
12
12
  license = {file = "LICENSE.txt"}
@@ -4,7 +4,7 @@
4
4
  tksheet - A Python tkinter table widget
5
5
  """
6
6
 
7
- __version__ = "7.2.9"
7
+ __version__ = "7.2.11"
8
8
 
9
9
  from .colors import (
10
10
  color_map,
@@ -481,7 +481,6 @@ class ColumnHeaders(tk.Canvas):
481
481
  if y < self.MT.min_header_height:
482
482
  y = int(self.MT.min_header_height)
483
483
  self.new_col_height = y
484
- self.create_resize_line(x1, y, x2, y, width=1, fill=self.PAR.ops.resizing_line_fg, tag="rhl")
485
484
  elif self.MT.identify_col(x=event.x, allow_end=False) is None:
486
485
  self.MT.deselect("all")
487
486
  elif self.col_selection_enabled and self.rsz_w is None and self.rsz_h is None:
@@ -540,22 +539,21 @@ class ColumnHeaders(tk.Canvas):
540
539
  fill=self.PAR.ops.resizing_line_fg,
541
540
  tag="rwl2",
542
541
  )
542
+ self.drag_width_resize()
543
543
  elif self.height_resizing_enabled and self.rsz_h is not None and self.currently_resizing_height:
544
544
  evy = event.y
545
- self.hide_resize_and_ctrl_lines(ctrl_lines=False)
546
545
  if evy > self.current_height:
547
546
  y = self.MT.canvasy(evy - self.current_height)
548
547
  if evy > self.MT.max_header_height:
549
548
  evy = int(self.MT.max_header_height)
550
549
  y = self.MT.canvasy(evy - self.current_height)
551
550
  self.new_col_height = evy
552
- self.MT.create_resize_line(x1, y, x2, y, width=1, fill=self.PAR.ops.resizing_line_fg, tag="rhl")
553
551
  else:
554
552
  y = evy
555
553
  if y < self.MT.min_header_height:
556
554
  y = int(self.MT.min_header_height)
557
555
  self.new_col_height = y
558
- self.create_resize_line(x1, y, x2, y, width=1, fill=self.PAR.ops.resizing_line_fg, tag="rhl")
556
+ self.drag_height_resize()
559
557
  elif (
560
558
  self.drag_and_drop_enabled
561
559
  and self.col_selection_enabled
@@ -601,6 +599,10 @@ class ColumnHeaders(tk.Canvas):
601
599
  if need_redraw:
602
600
  self.MT.main_table_redraw_grid_and_text(redraw_header=True, redraw_row_index=False)
603
601
  try_binding(self.extra_b1_motion_func, event)
602
+
603
+ def drag_height_resize(self) -> None:
604
+ self.set_height(self.new_col_height, set_TL=True)
605
+ self.MT.main_table_redraw_grid_and_text(redraw_header=True, redraw_row_index=True)
604
606
 
605
607
  def get_b1_motion_box(self, start_col: int, end_col: int) -> tuple[int, int, int, int, Literal["columns"]]:
606
608
  if end_col >= start_col:
@@ -779,6 +781,32 @@ class ColumnHeaders(tk.Canvas):
779
781
  return True
780
782
  return False
781
783
 
784
+ def drag_width_resize(self) -> None:
785
+ new_col_pos = int(self.coords("rwl")[0])
786
+ old_width = self.MT.col_positions[self.rsz_w] - self.MT.col_positions[self.rsz_w - 1]
787
+ size = new_col_pos - self.MT.col_positions[self.rsz_w - 1]
788
+ if size < self.MT.min_column_width:
789
+ new_col_pos = ceil(self.MT.col_positions[self.rsz_w - 1] + self.MT.min_column_width)
790
+ elif size > self.MT.max_column_width:
791
+ new_col_pos = floor(self.MT.col_positions[self.rsz_w - 1] + self.MT.max_column_width)
792
+ increment = new_col_pos - self.MT.col_positions[self.rsz_w]
793
+ self.MT.col_positions[self.rsz_w + 1 :] = [
794
+ e + increment for e in islice(self.MT.col_positions, self.rsz_w + 1, None)
795
+ ]
796
+ self.MT.col_positions[self.rsz_w] = new_col_pos
797
+ new_width = self.MT.col_positions[self.rsz_w] - self.MT.col_positions[self.rsz_w - 1]
798
+ self.MT.allow_auto_resize_columns = False
799
+ self.MT.recreate_all_selection_boxes()
800
+ self.MT.main_table_redraw_grid_and_text(redraw_header=True, redraw_row_index=True)
801
+ if self.column_width_resize_func is not None and old_width != new_width:
802
+ self.column_width_resize_func(
803
+ event_dict(
804
+ name="resize",
805
+ sheet=self.PAR.name,
806
+ resized_columns={self.rsz_w - 1: {"old_size": old_width, "new_size": new_width}},
807
+ )
808
+ )
809
+
782
810
  def b1_release(self, event: object) -> None:
783
811
  if self.being_drawn_item is not None and (to_sel := self.MT.coords_and_type(self.being_drawn_item)):
784
812
  r_to_sel, c_to_sel = self.MT.selected.row, self.MT.selected.column
@@ -795,37 +823,12 @@ class ColumnHeaders(tk.Canvas):
795
823
  self.being_drawn_item = None
796
824
  self.MT.bind("<MouseWheel>", self.MT.mousewheel)
797
825
  if self.width_resizing_enabled and self.rsz_w is not None and self.currently_resizing_width:
826
+ self.drag_width_resize()
798
827
  self.currently_resizing_width = False
799
- new_col_pos = int(self.coords("rwl")[0])
800
828
  self.hide_resize_and_ctrl_lines(ctrl_lines=False)
801
- old_width = self.MT.col_positions[self.rsz_w] - self.MT.col_positions[self.rsz_w - 1]
802
- size = new_col_pos - self.MT.col_positions[self.rsz_w - 1]
803
- if size < self.MT.min_column_width:
804
- new_col_pos = ceil(self.MT.col_positions[self.rsz_w - 1] + self.MT.min_column_width)
805
- elif size > self.MT.max_column_width:
806
- new_col_pos = floor(self.MT.col_positions[self.rsz_w - 1] + self.MT.max_column_width)
807
- increment = new_col_pos - self.MT.col_positions[self.rsz_w]
808
- self.MT.col_positions[self.rsz_w + 1 :] = [
809
- e + increment for e in islice(self.MT.col_positions, self.rsz_w + 1, len(self.MT.col_positions))
810
- ]
811
- self.MT.col_positions[self.rsz_w] = new_col_pos
812
- new_width = self.MT.col_positions[self.rsz_w] - self.MT.col_positions[self.rsz_w - 1]
813
- self.MT.allow_auto_resize_columns = False
814
- self.MT.recreate_all_selection_boxes()
815
- self.MT.main_table_redraw_grid_and_text(redraw_header=True, redraw_row_index=True)
816
- if self.column_width_resize_func is not None and old_width != new_width:
817
- self.column_width_resize_func(
818
- event_dict(
819
- name="resize",
820
- sheet=self.PAR.name,
821
- resized_columns={self.rsz_w - 1: {"old_size": old_width, "new_size": new_width}},
822
- )
823
- )
824
829
  elif self.height_resizing_enabled and self.rsz_h is not None and self.currently_resizing_height:
825
830
  self.currently_resizing_height = False
826
- self.hide_resize_and_ctrl_lines(ctrl_lines=False)
827
- self.set_height(self.new_col_height, set_TL=True)
828
- self.MT.main_table_redraw_grid_and_text(redraw_header=True, redraw_row_index=True)
831
+ self.drag_height_resize()
829
832
  elif (
830
833
  self.drag_and_drop_enabled
831
834
  and self.col_selection_enabled
@@ -1760,8 +1763,7 @@ class ColumnHeaders(tk.Canvas):
1760
1763
  if self.text_editor.open and c == self.text_editor.column:
1761
1764
  self.text_editor.set_text(self.text_editor.get() + "" if not isinstance(text, str) else text)
1762
1765
  return
1763
- if self.text_editor.open:
1764
- self.hide_text_editor()
1766
+ self.hide_text_editor()
1765
1767
  if not self.MT.see(r=0, c=c, keep_yscroll=True, check_cell_visibility=True):
1766
1768
  self.MT.refresh()
1767
1769
  x = self.MT.col_positions[c] + 1
@@ -1907,14 +1909,12 @@ class ColumnHeaders(tk.Canvas):
1907
1909
  )
1908
1910
  # self.itemconfig(self.dropdown.canvas_id, anchor=anchor, height=win_h)
1909
1911
 
1910
- def hide_text_editor(self, reason: None | str = None) -> None:
1912
+ def hide_text_editor(self) -> None:
1911
1913
  if self.text_editor.open:
1912
1914
  for binding in text_editor_to_unbind:
1913
1915
  self.text_editor.tktext.unbind(binding)
1914
1916
  self.itemconfig(self.text_editor.canvas_id, state="hidden")
1915
1917
  self.text_editor.open = False
1916
- if reason == "Escape":
1917
- self.focus_set()
1918
1918
 
1919
1919
  # c is displayed col
1920
1920
  def close_text_editor(self, event: tk.Event) -> Literal["break"] | None:
@@ -1933,6 +1933,7 @@ class ColumnHeaders(tk.Canvas):
1933
1933
  return "break"
1934
1934
  if event.keysym == "Escape":
1935
1935
  self.hide_text_editor_and_dropdown()
1936
+ self.focus_set()
1936
1937
  return
1937
1938
  # setting cell data with text editor value
1938
1939
  text_editor_value = self.text_editor.get()
@@ -2011,7 +2012,7 @@ class ColumnHeaders(tk.Canvas):
2011
2012
  dd_window.search_and_see(event)
2012
2013
 
2013
2014
  def open_dropdown_window(self, c: int, event: object = None) -> None:
2014
- self.hide_text_editor("Escape")
2015
+ self.hide_text_editor()
2015
2016
  kwargs = self.get_cell_kwargs(self.MT.datacn(c), key="dropdown")
2016
2017
  if kwargs["state"] == "normal":
2017
2018
  if not self.open_text_editor(event=event, c=c, dropdown=True):
@@ -2075,8 +2076,9 @@ class ColumnHeaders(tk.Canvas):
2075
2076
  return
2076
2077
  redraw = False
2077
2078
  else:
2078
- self.dropdown.window.bind("<FocusOut>", lambda _x: self.close_dropdown_window(c))
2079
2079
  self.update_idletasks()
2080
+ self.dropdown.window.bind("<FocusOut>", lambda _x: self.close_dropdown_window(c))
2081
+ self.dropdown.window.bind("<Escape>", self.close_dropdown_window)
2080
2082
  self.dropdown.window.focus_set()
2081
2083
  redraw = True
2082
2084
  self.dropdown.open = True
@@ -2116,12 +2118,12 @@ class ColumnHeaders(tk.Canvas):
2116
2118
  edited = self.set_cell_data_undo(c, datacn=datacn, value=selection, redraw=not redraw)
2117
2119
  if edited:
2118
2120
  try_binding(self.extra_end_edit_cell_func, event_data)
2119
- self.focus_set()
2120
2121
  self.MT.recreate_all_selection_boxes()
2122
+ self.focus_set()
2121
2123
  self.hide_text_editor_and_dropdown(redraw=redraw)
2122
2124
 
2123
2125
  def hide_text_editor_and_dropdown(self, redraw: bool = True) -> None:
2124
- self.hide_text_editor("Escape")
2126
+ self.hide_text_editor()
2125
2127
  self.hide_dropdown_window()
2126
2128
  if redraw:
2127
2129
  self.MT.refresh()
@@ -1778,7 +1778,12 @@ class MainTable(tk.Canvas):
1778
1778
  0 if not r else self.row_positions[r + 1],
1779
1779
  )
1780
1780
 
1781
- def cell_completely_visible(self, r: int = 0, c: int = 0, separate_axes: bool = False) -> bool:
1781
+ def cell_completely_visible(
1782
+ self,
1783
+ r: int | None = 0,
1784
+ c: int | None = 0,
1785
+ separate_axes: bool = False,
1786
+ ) -> bool:
1782
1787
  cx1, cy1, cx2, cy2 = self.get_canvas_visible_area()
1783
1788
  x1, y1, x2, y2 = self.get_cell_coords(r, c)
1784
1789
  x_vis = True
@@ -1796,9 +1801,7 @@ class MainTable(tk.Canvas):
1796
1801
  def cell_visible(self, r: int = 0, c: int = 0) -> bool:
1797
1802
  cx1, cy1, cx2, cy2 = self.get_canvas_visible_area()
1798
1803
  x1, y1, x2, y2 = self.get_cell_coords(r, c)
1799
- if x1 <= cx2 or y1 <= cy2 or x2 >= cx1 or y2 >= cy1:
1800
- return True
1801
- return False
1804
+ return x1 <= cx2 or y1 <= cy2 or x2 >= cx1 or y2 >= cy1
1802
1805
 
1803
1806
  def select_all(self, redraw: bool = True, run_binding_func: bool = True) -> None:
1804
1807
  selected = self.selected
@@ -1834,8 +1837,10 @@ class MainTable(tk.Canvas):
1834
1837
  run_binding_func: bool = True,
1835
1838
  ext: bool = False,
1836
1839
  ) -> int:
1837
- self.deselect("all", redraw=False)
1840
+ boxes_to_hide = tuple(self.selection_boxes)
1838
1841
  fill_iid = self.create_selection_box(r, c, r + 1, c + 1, state="hidden", ext=ext)
1842
+ for iid in boxes_to_hide:
1843
+ self.hide_selection_box(iid)
1839
1844
  if redraw:
1840
1845
  self.main_table_redraw_grid_and_text(redraw_header=True, redraw_row_index=True)
1841
1846
  if run_binding_func:
@@ -2986,12 +2991,10 @@ class MainTable(tk.Canvas):
2986
2991
  and self.selected.type_ == "cells"
2987
2992
  ):
2988
2993
  box = self.get_b1_motion_box(
2989
- *(
2990
- self.selected.row,
2991
- self.selected.column,
2992
- end_row,
2993
- end_col,
2994
- )
2994
+ self.selected.row,
2995
+ self.selected.column,
2996
+ end_row,
2997
+ end_col,
2995
2998
  )
2996
2999
  if (
2997
3000
  box is not None
@@ -3029,12 +3032,10 @@ class MainTable(tk.Canvas):
3029
3032
  and self.selected.type_ == "cells"
3030
3033
  ):
3031
3034
  box = self.get_b1_motion_box(
3032
- *(
3033
- self.selected.row,
3034
- self.selected.column,
3035
- end_row,
3036
- end_col,
3037
- )
3035
+ self.selected.row,
3036
+ self.selected.column,
3037
+ end_row,
3038
+ end_col,
3038
3039
  )
3039
3040
  if (
3040
3041
  box is not None
@@ -5457,7 +5458,7 @@ class MainTable(tk.Canvas):
5457
5458
  if self.PAR.ops.auto_resize_row_index and redraw_row_index and self.show_index:
5458
5459
  changed_w = self.RI.auto_set_index_width(
5459
5460
  end_row=grid_end_row,
5460
- only_rows=[self.datarn(r) for r in range(text_start_row, text_end_row)],
5461
+ only_rows=map(self.datarn, range(text_start_row, text_end_row)),
5461
5462
  )
5462
5463
  if resized_cols or resized_rows or changed_w:
5463
5464
  self.recreate_all_selection_boxes()
@@ -6572,8 +6573,7 @@ class MainTable(tk.Canvas):
6572
6573
  if self.text_editor.open and (r, c) == self.text_editor.coords:
6573
6574
  self.text_editor.window.set_text(self.text_editor.get() + "" if not isinstance(text, str) else text)
6574
6575
  return
6575
- if self.text_editor.open:
6576
- self.hide_text_editor()
6576
+ self.hide_text_editor()
6577
6577
  if not self.see(r=r, c=c, check_cell_visibility=True):
6578
6578
  self.refresh()
6579
6579
  x = self.col_positions[c]
@@ -6707,14 +6707,12 @@ class MainTable(tk.Canvas):
6707
6707
  )
6708
6708
  # self.itemconfig(self.dropdown.canvas_id, anchor=anchor, height=win_h)
6709
6709
 
6710
- def hide_text_editor(self, reason: None | str = None) -> None:
6710
+ def hide_text_editor(self) -> None:
6711
6711
  if self.text_editor.open:
6712
6712
  for binding in text_editor_to_unbind:
6713
6713
  self.text_editor.tktext.unbind(binding)
6714
6714
  self.itemconfig(self.text_editor.canvas_id, state="hidden")
6715
6715
  self.text_editor.open = False
6716
- if reason == "Escape":
6717
- self.focus_set()
6718
6716
 
6719
6717
  def close_text_editor(self, event: tk.Event) -> Literal["break"] | None:
6720
6718
  # checking if text editor should be closed or not
@@ -6732,6 +6730,7 @@ class MainTable(tk.Canvas):
6732
6730
  return "break"
6733
6731
  if event.keysym == "Escape":
6734
6732
  self.hide_text_editor_and_dropdown()
6733
+ self.focus_set()
6735
6734
  return
6736
6735
  # setting cell data with text editor value
6737
6736
  text_editor_value = self.text_editor.get()
@@ -6944,7 +6943,7 @@ class MainTable(tk.Canvas):
6944
6943
  c: int,
6945
6944
  event: object = None,
6946
6945
  ) -> None:
6947
- self.hide_text_editor("Escape")
6946
+ self.hide_text_editor()
6948
6947
  datarn = self.datarn(r)
6949
6948
  datacn = self.datacn(c)
6950
6949
  kwargs = self.get_cell_kwargs(datarn, datacn, key="dropdown")
@@ -7019,7 +7018,8 @@ class MainTable(tk.Canvas):
7019
7018
  else:
7020
7019
  self.update_idletasks()
7021
7020
  self.dropdown.window.bind("<FocusOut>", lambda _: self.close_dropdown_window(r, c))
7022
- self.dropdown.window.focus()
7021
+ self.dropdown.window.bind("<Escape>", self.close_dropdown_window)
7022
+ self.dropdown.window.focus_set()
7023
7023
  redraw = True
7024
7024
  self.dropdown.open = True
7025
7025
  if redraw:
@@ -7075,12 +7075,12 @@ class MainTable(tk.Canvas):
7075
7075
  )
7076
7076
  if edited:
7077
7077
  try_binding(self.extra_end_edit_cell_func, event_data)
7078
- self.focus_set()
7079
7078
  self.recreate_all_selection_boxes()
7079
+ self.focus_set()
7080
7080
  self.hide_text_editor_and_dropdown(redraw=redraw)
7081
7081
 
7082
7082
  def hide_text_editor_and_dropdown(self, redraw: bool = True) -> None:
7083
- self.hide_text_editor("Escape")
7083
+ self.hide_text_editor()
7084
7084
  self.hide_dropdown_window()
7085
7085
  if redraw:
7086
7086
  self.refresh()
@@ -6,6 +6,7 @@ from collections.abc import Callable, Generator, Hashable, Iterator
6
6
  from functools import partial
7
7
  from typing import Literal
8
8
 
9
+
9
10
  pickle_obj = partial(pickle.dumps, protocol=pickle.HIGHEST_PROTOCOL)
10
11
 
11
12
  FontTuple = namedtuple("FontTuple", "family size style")
@@ -152,18 +153,16 @@ class Span(dict):
152
153
  redraw: bool = True,
153
154
  **kwargs,
154
155
  ) -> Span:
155
- self["widget"].format(
156
+ return self["widget"].format(
156
157
  self,
157
158
  formatter_options={"formatter": formatter_class, **formatter_options, **kwargs},
158
159
  formatter_class=formatter_class,
159
160
  redraw=redraw,
160
161
  **kwargs,
161
162
  )
162
- return self
163
163
 
164
164
  def del_format(self) -> Span:
165
- self["widget"].del_format(self)
166
- return self
165
+ return self["widget"].del_format(self)
167
166
 
168
167
  def highlight(
169
168
  self,
@@ -173,7 +172,7 @@ class Span(dict):
173
172
  overwrite: bool = False,
174
173
  redraw: bool = True,
175
174
  ) -> Span:
176
- self["widget"].highlight(
175
+ return self["widget"].highlight(
177
176
  self,
178
177
  bg=bg,
179
178
  fg=fg,
@@ -181,34 +180,74 @@ class Span(dict):
181
180
  overwrite=overwrite,
182
181
  redraw=redraw,
183
182
  )
184
- return self
185
183
 
186
184
  def dehighlight(self, redraw: bool = True) -> Span:
187
- self["widget"].dehighlight(self, redraw=redraw)
185
+ return self["widget"].dehighlight(self, redraw=redraw)
188
186
 
189
187
  del_highlight = dehighlight
190
188
 
191
189
  def readonly(self, readonly: bool = True) -> Span:
192
- self["widget"].readonly(self, readonly=readonly)
193
- return self
190
+ return self["widget"].readonly(self, readonly=readonly)
194
191
 
195
- def dropdown(self, *args, **kwargs) -> Span:
196
- self["widget"].dropdown(self, *args, **kwargs)
192
+ def dropdown(
193
+ self,
194
+ values: list = [],
195
+ edit_data: bool = True,
196
+ set_values: dict[tuple[int, int], object] = {},
197
+ set_value: object = None,
198
+ state: str = "normal",
199
+ redraw: bool = True,
200
+ selection_function: Callable | None = None,
201
+ modified_function: Callable | None = None,
202
+ search_function: Callable | None = None,
203
+ validate_input: bool = True,
204
+ text: None | str = None,
205
+ ) -> Span:
206
+ return self["widget"].dropdown(
207
+ self,
208
+ values=values,
209
+ edit_data=edit_data,
210
+ set_values=set_values,
211
+ set_value=set_value,
212
+ state=state,
213
+ redraw=redraw,
214
+ selection_function=selection_function,
215
+ modified_function=modified_function,
216
+ search_function=search_function,
217
+ validate_input=validate_input,
218
+ text=text,
219
+ )
197
220
 
198
221
  def del_dropdown(self) -> Span:
199
- self["widget"].del_dropdown(self)
222
+ return self["widget"].del_dropdown(self)
200
223
 
201
- def checkbox(self, *args, **kwargs) -> Span:
202
- self["widget"].dropdown(self, *args, **kwargs)
224
+ def checkbox(
225
+ self,
226
+ edit_data: bool = True,
227
+ checked: bool | None = None,
228
+ state: str = "normal",
229
+ redraw: bool = True,
230
+ check_function: Callable | None = None,
231
+ text: str = "",
232
+ ) -> Span:
233
+ return self["widget"].checkbox(
234
+ self,
235
+ edit_data=edit_data,
236
+ checked=checked,
237
+ state=state,
238
+ redraw=redraw,
239
+ check_function=check_function,
240
+ text=text,
241
+ )
203
242
 
204
243
  def del_checkbox(self) -> Span:
205
- self["widget"].del_checkbox(self)
244
+ return self["widget"].del_checkbox(self)
206
245
 
207
246
  def align(self, align: str | None, redraw: bool = True) -> Span:
208
- self["widget"].align(self, align=align, redraw=redraw)
247
+ return self["widget"].align(self, align=align, redraw=redraw)
209
248
 
210
249
  def del_align(self, redraw: bool = True) -> Span:
211
- self["widget"].del_align(self, redraw=redraw)
250
+ return self["widget"].del_align(self, redraw=redraw)
212
251
 
213
252
  def clear(self, undo: bool | None = None, redraw: bool = True) -> Span:
214
253
  if undo is not None:
@@ -304,7 +343,7 @@ class Span(dict):
304
343
  self["transposed"] = not self["transposed"]
305
344
  return self
306
345
 
307
- def expand(self, direction: str = "both") -> Span:
346
+ def expand(self, direction: Literal["both", "table", "down", "right"] = "both") -> Span:
308
347
  if direction == "both" or direction == "table":
309
348
  self["upto_r"], self["upto_c"] = None, None
310
349
  elif direction == "down":
@@ -358,7 +358,16 @@ class RowIndex(tk.Canvas):
358
358
  self.MT.current_cursor = "sb_v_double_arrow"
359
359
  else:
360
360
  self.rsz_h = None
361
- if self.width_resizing_enabled and not mouse_over_resize:
361
+ if (
362
+ self.width_resizing_enabled
363
+ and not mouse_over_resize
364
+ and self.PAR.ops.auto_resize_row_index is not True
365
+ and not (
366
+ self.PAR.ops.auto_resize_row_index == "empty"
367
+ and not isinstance(self.MT._row_index, int)
368
+ and not self.MT._row_index
369
+ )
370
+ ):
362
371
  try:
363
372
  x1, y1, x2, y2 = (
364
373
  self.row_width_resize_bbox[0],
@@ -480,7 +489,6 @@ class RowIndex(tk.Canvas):
480
489
  if x < self.MT.min_column_width:
481
490
  x = int(self.MT.min_column_width)
482
491
  self.new_row_width = x
483
- self.create_resize_line(x, y1, x, y2, width=1, fill=self.PAR.ops.resizing_line_fg, tag="rwl")
484
492
  elif self.MT.identify_row(y=event.y, allow_end=False) is None:
485
493
  self.MT.deselect("all")
486
494
  elif self.row_selection_enabled and self.rsz_h is None and self.rsz_w is None:
@@ -540,22 +548,21 @@ class RowIndex(tk.Canvas):
540
548
  fill=self.PAR.ops.resizing_line_fg,
541
549
  tag="rhl2",
542
550
  )
551
+ self.drag_height_resize()
543
552
  elif self.width_resizing_enabled and self.rsz_w is not None and self.currently_resizing_width:
544
553
  evx = event.x
545
- self.hide_resize_and_ctrl_lines(ctrl_lines=False)
546
554
  if evx > self.current_width:
547
555
  x = self.MT.canvasx(evx - self.current_width)
548
556
  if evx > self.MT.max_index_width:
549
557
  evx = int(self.MT.max_index_width)
550
558
  x = self.MT.canvasx(evx - self.current_width)
551
559
  self.new_row_width = evx
552
- self.MT.create_resize_line(x, y1, x, y2, width=1, fill=self.PAR.ops.resizing_line_fg, tag="rwl")
553
560
  else:
554
561
  x = evx
555
562
  if x < self.MT.min_column_width:
556
563
  x = int(self.MT.min_column_width)
557
564
  self.new_row_width = x
558
- self.create_resize_line(x, y1, x, y2, width=1, fill=self.PAR.ops.resizing_line_fg, tag="rwl")
565
+ self.drag_width_resize()
559
566
  if (
560
567
  self.drag_and_drop_enabled
561
568
  and self.row_selection_enabled
@@ -761,22 +768,48 @@ class RowIndex(tk.Canvas):
761
768
  self.MT.set_yviews("moveto", 1)
762
769
 
763
770
  def event_over_dropdown(self, r: int, datarn: int, event: object, canvasy: float) -> bool:
764
- if (
771
+ return (
765
772
  canvasy < self.MT.row_positions[r] + self.MT.index_txt_height
766
773
  and self.get_cell_kwargs(datarn, key="dropdown")
767
774
  and event.x > self.current_width - self.MT.index_txt_height - 4
768
- ):
769
- return True
770
- return False
775
+ )
771
776
 
772
777
  def event_over_checkbox(self, r: int, datarn: int, event: object, canvasy: float) -> bool:
773
- if (
778
+ return (
774
779
  canvasy < self.MT.row_positions[r] + self.MT.index_txt_height
775
780
  and self.get_cell_kwargs(datarn, key="checkbox")
776
781
  and event.x < self.MT.index_txt_height + 4
777
- ):
778
- return True
779
- return False
782
+ )
783
+
784
+ def drag_width_resize(self) -> None:
785
+ self.set_width(self.new_row_width, set_TL=True)
786
+ self.MT.main_table_redraw_grid_and_text(redraw_header=True, redraw_row_index=True)
787
+
788
+ def drag_height_resize(self) -> None:
789
+ new_row_pos = int(self.coords("rhl")[1])
790
+ old_height = self.MT.row_positions[self.rsz_h] - self.MT.row_positions[self.rsz_h - 1]
791
+ size = new_row_pos - self.MT.row_positions[self.rsz_h - 1]
792
+ if size < self.MT.min_row_height:
793
+ new_row_pos = ceil(self.MT.row_positions[self.rsz_h - 1] + self.MT.min_row_height)
794
+ elif size > self.MT.max_row_height:
795
+ new_row_pos = floor(self.MT.row_positions[self.rsz_h - 1] + self.MT.max_row_height)
796
+ increment = new_row_pos - self.MT.row_positions[self.rsz_h]
797
+ self.MT.row_positions[self.rsz_h + 1 :] = [
798
+ e + increment for e in islice(self.MT.row_positions, self.rsz_h + 1, None)
799
+ ]
800
+ self.MT.row_positions[self.rsz_h] = new_row_pos
801
+ new_height = self.MT.row_positions[self.rsz_h] - self.MT.row_positions[self.rsz_h - 1]
802
+ self.MT.allow_auto_resize_rows = False
803
+ self.MT.recreate_all_selection_boxes()
804
+ self.MT.main_table_redraw_grid_and_text(redraw_header=True, redraw_row_index=True)
805
+ if self.row_height_resize_func is not None and old_height != new_height:
806
+ self.row_height_resize_func(
807
+ event_dict(
808
+ name="resize",
809
+ sheet=self.PAR.name,
810
+ resized_rows={self.rsz_h - 1: {"old_size": old_height, "new_size": new_height}},
811
+ )
812
+ )
780
813
 
781
814
  def b1_release(self, event: object) -> None:
782
815
  if self.being_drawn_item is not None and (to_sel := self.MT.coords_and_type(self.being_drawn_item)):
@@ -794,37 +827,12 @@ class RowIndex(tk.Canvas):
794
827
  self.being_drawn_item = None
795
828
  self.MT.bind("<MouseWheel>", self.MT.mousewheel)
796
829
  if self.height_resizing_enabled and self.rsz_h is not None and self.currently_resizing_height:
830
+ self.drag_height_resize()
797
831
  self.currently_resizing_height = False
798
- new_row_pos = int(self.coords("rhl")[1])
799
832
  self.hide_resize_and_ctrl_lines(ctrl_lines=False)
800
- old_height = self.MT.row_positions[self.rsz_h] - self.MT.row_positions[self.rsz_h - 1]
801
- size = new_row_pos - self.MT.row_positions[self.rsz_h - 1]
802
- if size < self.MT.min_row_height:
803
- new_row_pos = ceil(self.MT.row_positions[self.rsz_h - 1] + self.MT.min_row_height)
804
- elif size > self.MT.max_row_height:
805
- new_row_pos = floor(self.MT.row_positions[self.rsz_h - 1] + self.MT.max_row_height)
806
- increment = new_row_pos - self.MT.row_positions[self.rsz_h]
807
- self.MT.row_positions[self.rsz_h + 1 :] = [
808
- e + increment for e in islice(self.MT.row_positions, self.rsz_h + 1, len(self.MT.row_positions))
809
- ]
810
- self.MT.row_positions[self.rsz_h] = new_row_pos
811
- new_height = self.MT.row_positions[self.rsz_h] - self.MT.row_positions[self.rsz_h - 1]
812
- self.MT.allow_auto_resize_rows = False
813
- self.MT.recreate_all_selection_boxes()
814
- self.MT.main_table_redraw_grid_and_text(redraw_header=True, redraw_row_index=True)
815
- if self.row_height_resize_func is not None and old_height != new_height:
816
- self.row_height_resize_func(
817
- event_dict(
818
- name="resize",
819
- sheet=self.PAR.name,
820
- resized_rows={self.rsz_h - 1: {"old_size": old_height, "new_size": new_height}},
821
- )
822
- )
823
833
  elif self.width_resizing_enabled and self.rsz_w is not None and self.currently_resizing_width:
824
834
  self.currently_resizing_width = False
825
- self.hide_resize_and_ctrl_lines(ctrl_lines=False)
826
- self.set_width(self.new_row_width, set_TL=True)
827
- self.MT.main_table_redraw_grid_and_text(redraw_header=True, redraw_row_index=True)
835
+ self.drag_width_resize()
828
836
  if (
829
837
  self.drag_and_drop_enabled
830
838
  and self.MT.anything_selected(exclude_cells=True, exclude_columns=True)
@@ -1049,7 +1057,7 @@ class RowIndex(tk.Canvas):
1049
1057
  align = self.align
1050
1058
  if align == "w":
1051
1059
  w += self.MT.index_txt_height
1052
- w += self.get_treeview_indent(self.MT._row_index[datarn].iid) + 5
1060
+ w += self.get_treeview_indent(self.MT._row_index[datarn].iid) + 10
1053
1061
  return w, h
1054
1062
 
1055
1063
  def get_row_text_height(
@@ -1129,9 +1137,6 @@ class RowIndex(tk.Canvas):
1129
1137
  isinstance(self.MT._row_index, int) and self.MT._row_index >= len(self.MT.data)
1130
1138
  ):
1131
1139
  return w
1132
- qconf = self.MT.txt_measure_canvas.itemconfig
1133
- qbbox = self.MT.txt_measure_canvas.bbox
1134
- qtxtm = self.MT.txt_measure_canvas_text
1135
1140
  if only_rows:
1136
1141
  iterable = only_rows
1137
1142
  elif self.MT.all_rows_displayed:
@@ -1141,19 +1146,8 @@ class RowIndex(tk.Canvas):
1141
1146
  iterable = range(len(self.MT.data))
1142
1147
  else:
1143
1148
  iterable = self.MT.displayed_rows
1144
- if (
1145
- isinstance(self.MT._row_index, list)
1146
- and (tw := max(map(itemgetter(0), map(self.get_cell_dimensions, iterable)), default=w)) > w
1147
- ):
1148
- w = tw
1149
- elif isinstance(self.MT._row_index, int):
1150
- datacn = self.MT._row_index
1151
- for datarn in iterable:
1152
- if txt := self.MT.get_valid_cell_data_as_str(datarn, datacn, get_displayed=True):
1153
- qconf(qtxtm, text=txt)
1154
- b = qbbox(qtxtm)
1155
- if (tw := b[2] - b[0] + 10) > w:
1156
- w = tw
1149
+ if (new_w := max(map(itemgetter(0), map(self.get_cell_dimensions, iterable)), default=w)) > w:
1150
+ w = new_w
1157
1151
  if w > self.MT.max_index_width:
1158
1152
  w = int(self.MT.max_index_width)
1159
1153
  return w
@@ -1708,7 +1702,6 @@ class RowIndex(tk.Canvas):
1708
1702
  lns = self.get_valid_cell_data_as_str(datarn, fix=False)
1709
1703
  if not lns:
1710
1704
  continue
1711
- lns = lns.split("\n")
1712
1705
  draw_y = rtopgridln + self.MT.index_first_ln_ins
1713
1706
  if mw > 5:
1714
1707
  draw_y = rtopgridln + self.MT.index_first_ln_ins
@@ -1716,6 +1709,7 @@ class RowIndex(tk.Canvas):
1716
1709
  if start_ln < 0:
1717
1710
  start_ln = 0
1718
1711
  draw_y += start_ln * self.MT.index_xtra_lines_increment
1712
+ lns = lns.split("\n")
1719
1713
  if draw_y + self.MT.index_half_txt_height - 1 <= rbotgridln and len(lns) > start_ln:
1720
1714
  for txt in islice(lns, start_ln, None):
1721
1715
  if self.hidd_text:
@@ -1891,8 +1885,7 @@ class RowIndex(tk.Canvas):
1891
1885
  if self.text_editor.open and r == self.text_editor.row:
1892
1886
  self.text_editor.set_text(self.text_editor.get() + "" if not isinstance(text, str) else text)
1893
1887
  return
1894
- if self.text_editor.open:
1895
- self.hide_text_editor()
1888
+ self.hide_text_editor()
1896
1889
  if not self.MT.see(r=r, c=0, keep_yscroll=True, check_cell_visibility=True):
1897
1890
  self.MT.refresh()
1898
1891
  x = 0
@@ -2025,14 +2018,12 @@ class RowIndex(tk.Canvas):
2025
2018
  )
2026
2019
  # self.itemconfig(self.dropdown.canvas_id, anchor=anchor, height=win_h)
2027
2020
 
2028
- def hide_text_editor(self, reason: None | str = None) -> None:
2021
+ def hide_text_editor(self) -> None:
2029
2022
  if self.text_editor.open:
2030
2023
  for binding in text_editor_to_unbind:
2031
2024
  self.text_editor.tktext.unbind(binding)
2032
2025
  self.itemconfig(self.text_editor.canvas_id, state="hidden")
2033
2026
  self.text_editor.open = False
2034
- if reason == "Escape":
2035
- self.focus_set()
2036
2027
 
2037
2028
  # r is displayed row
2038
2029
  def close_text_editor(self, event: tk.Event) -> Literal["break"] | None:
@@ -2051,6 +2042,7 @@ class RowIndex(tk.Canvas):
2051
2042
  return "break"
2052
2043
  if event.keysym == "Escape":
2053
2044
  self.hide_text_editor_and_dropdown()
2045
+ self.focus_set()
2054
2046
  return
2055
2047
  text_editor_value = self.text_editor.get()
2056
2048
  r = self.text_editor.row
@@ -2132,7 +2124,7 @@ class RowIndex(tk.Canvas):
2132
2124
 
2133
2125
  # r is displayed row
2134
2126
  def open_dropdown_window(self, r: int, event: object = None) -> None:
2135
- self.hide_text_editor("Escape")
2127
+ self.hide_text_editor()
2136
2128
  kwargs = self.get_cell_kwargs(self.MT.datarn(r), key="dropdown")
2137
2129
  if kwargs["state"] == "normal":
2138
2130
  if not self.open_text_editor(event=event, r=r, dropdown=True):
@@ -2203,8 +2195,9 @@ class RowIndex(tk.Canvas):
2203
2195
  return
2204
2196
  redraw = False
2205
2197
  else:
2206
- self.dropdown.window.bind("<FocusOut>", lambda _x: self.close_dropdown_window(r))
2207
2198
  self.update_idletasks()
2199
+ self.dropdown.window.bind("<FocusOut>", lambda _x: self.close_dropdown_window(r))
2200
+ self.dropdown.window.bind("<Escape>", self.close_dropdown_window)
2208
2201
  self.dropdown.window.focus_set()
2209
2202
  redraw = True
2210
2203
  self.dropdown.open = True
@@ -2245,12 +2238,12 @@ class RowIndex(tk.Canvas):
2245
2238
  edited = self.set_cell_data_undo(r, datarn=datarn, value=selection, redraw=not redraw)
2246
2239
  if edited:
2247
2240
  try_binding(self.extra_end_edit_cell_func, event_data)
2248
- self.focus_set()
2249
2241
  self.MT.recreate_all_selection_boxes()
2242
+ self.focus_set()
2250
2243
  self.hide_text_editor_and_dropdown(redraw=redraw)
2251
2244
 
2252
2245
  def hide_text_editor_and_dropdown(self, redraw: bool = True) -> None:
2253
- self.hide_text_editor("Escape")
2246
+ self.hide_text_editor()
2254
2247
  self.hide_dropdown_window()
2255
2248
  if redraw:
2256
2249
  self.MT.refresh()
@@ -2520,7 +2513,7 @@ class RowIndex(tk.Canvas):
2520
2513
  if not node.parent.children:
2521
2514
  self.tree_open_ids.discard(node.parent)
2522
2515
 
2523
- def pid_causes_recursive_loop(self, iid: str, pid: str) -> bool:
2516
+ def build_pid_causes_recursive_loop(self, iid: str, pid: str) -> bool:
2524
2517
  return any(
2525
2518
  i == pid
2526
2519
  for i in chain(
@@ -2528,3 +2521,8 @@ class RowIndex(tk.Canvas):
2528
2521
  islice(self.get_iid_ancestors(iid), 1, None),
2529
2522
  )
2530
2523
  )
2524
+
2525
+ def move_pid_causes_recursive_loop(self, to_move_iid: str, move_to_parent: str) -> bool:
2526
+ # if the parent the item is being moved under is one of the item's descendants
2527
+ # then it is a recursive loop
2528
+ return any(move_to_parent == diid for diid in self.get_iid_descendants(to_move_iid))
@@ -1556,6 +1556,14 @@ class Sheet(tk.Frame):
1556
1556
  @data.setter
1557
1557
  def data(self, value: list[list[object]]) -> None:
1558
1558
  self.data_reference(value)
1559
+
1560
+ def new_tksheet_event(self) -> EventDataDict:
1561
+ return event_dict(
1562
+ name="",
1563
+ sheet=self.name,
1564
+ widget=self,
1565
+ selected=self.MT.selected,
1566
+ )
1559
1567
 
1560
1568
  def set_data(
1561
1569
  self,
@@ -2185,6 +2193,7 @@ class Sheet(tk.Frame):
2185
2193
  emit_event: bool = False,
2186
2194
  redraw: bool = True,
2187
2195
  ) -> EventDataDict:
2196
+ self.MT.deselect("all", redraw=False)
2188
2197
  rows = [rows] if isinstance(rows, int) else sorted(rows)
2189
2198
  event_data = event_dict(
2190
2199
  name="delete_rows",
@@ -2213,7 +2222,6 @@ class Sheet(tk.Frame):
2213
2222
  self.MT.undo_stack.append(pickled_event_dict(event_data))
2214
2223
  if emit_event:
2215
2224
  self.emit_event("<<SheetModified>>", event_data)
2216
- self.MT.deselect("all", redraw=False)
2217
2225
  self.set_refresh_timer(redraw)
2218
2226
  return event_data
2219
2227
 
@@ -2227,6 +2235,7 @@ class Sheet(tk.Frame):
2227
2235
  emit_event: bool = False,
2228
2236
  redraw: bool = True,
2229
2237
  ) -> EventDataDict:
2238
+ self.MT.deselect("all", redraw=False)
2230
2239
  columns = [columns] if isinstance(columns, int) else sorted(columns)
2231
2240
  event_data = event_dict(
2232
2241
  name="delete_columns",
@@ -2255,7 +2264,6 @@ class Sheet(tk.Frame):
2255
2264
  self.MT.undo_stack.append(pickled_event_dict(event_data))
2256
2265
  if emit_event:
2257
2266
  self.emit_event("<<SheetModified>>", event_data)
2258
- self.MT.deselect("all", redraw=False)
2259
2267
  self.set_refresh_timer(redraw)
2260
2268
  return event_data
2261
2269
 
@@ -2557,10 +2565,12 @@ class Sheet(tk.Frame):
2557
2565
  redraw: bool = True,
2558
2566
  selection_function: Callable | None = None,
2559
2567
  modified_function: Callable | None = None,
2560
- search_function: Callable = dropdown_search_function,
2568
+ search_function: Callable | None = None,
2561
2569
  validate_input: bool = True,
2562
2570
  text: None | str = None,
2563
2571
  ) -> Span:
2572
+ if not search_function:
2573
+ search_function = dropdown_search_function
2564
2574
  v = set_value if set_value is not None else values[0] if values else ""
2565
2575
  kwargs = {
2566
2576
  "values": values,
@@ -3902,7 +3912,7 @@ class Sheet(tk.Frame):
3902
3912
  idx = bisect_left(self.MT.displayed_columns, column)
3903
3913
  if len(self.MT.displayed_columns) == idx or self.MT.displayed_columns[idx] != column:
3904
3914
  self.MT.displayed_columns.insert(idx, column)
3905
- cws.insert(idx, self.MT.saved_column_widths.pop(column, self.PAR.ops.default_column_width))
3915
+ cws.insert(idx, self.MT.saved_column_widths.pop(column, self.ops.default_column_width))
3906
3916
  self.MT.set_col_positions(cws)
3907
3917
  if deselect_all:
3908
3918
  self.MT.deselect(redraw=False)
@@ -4711,7 +4721,7 @@ class Sheet(tk.Frame):
4711
4721
  self.RI.tree[iid].text = row[text_column]
4712
4722
  else:
4713
4723
  self.RI.tree[iid] = Node(row[text_column], iid, "")
4714
- if safety and (iid == pid or self.RI.pid_causes_recursive_loop(iid, pid)):
4724
+ if safety and (iid == pid or self.RI.build_pid_causes_recursive_loop(iid, pid)):
4715
4725
  row[parent_column] = ""
4716
4726
  pid = ""
4717
4727
  if pid:
@@ -5041,7 +5051,8 @@ class Sheet(tk.Frame):
5041
5051
  def move(self, item: str, parent: str, index: int | None = None) -> Sheet:
5042
5052
  """
5043
5053
  Moves item to be under parent as child at index
5044
- 'parent' can be empty string which will make item a top node
5054
+ 'parent' can be an empty str which will put the item at top level
5055
+ Performance is not great
5045
5056
  """
5046
5057
  if (item := item.lower()) and item not in self.RI.tree:
5047
5058
  raise ValueError(f"Item '{item}' does not exist.")
@@ -5050,25 +5061,61 @@ class Sheet(tk.Frame):
5050
5061
  mapping = {}
5051
5062
  to_show = []
5052
5063
  item_node = self.RI.tree[item]
5064
+ item_r = self.RI.tree_rns[item]
5053
5065
  if parent:
5054
- if self.RI.pid_causes_recursive_loop(item, parent):
5066
+ if self.RI.move_pid_causes_recursive_loop(item, parent):
5055
5067
  raise ValueError(f"iid '{item}' causes a recursive loop with parent '{parent}'.")
5056
5068
  parent_node = self.RI.tree[parent]
5057
5069
  if parent_node.children:
5058
5070
  if index is None or index >= len(parent_node.children):
5059
- index = len(parent_node.children) - 1
5060
- item_r = self.RI.tree_rns[item]
5061
- new_r = self.RI.tree_rns[parent_node.children[index].iid]
5062
- new_r_desc = sum(1 for _ in self.RI.get_iid_descendants(parent_node.children[index].iid))
5063
- item_desc = sum(1 for _ in self.RI.get_iid_descendants(item))
5064
- if item_r < new_r:
5065
- r_ctr = new_r + new_r_desc - item_desc
5071
+ index = len(parent_node.children)
5072
+ new_r = self.RI.tree_rns[parent] + sum(1 for _ in self.RI.get_iid_descendants(parent))
5073
+ # new parent has children
5074
+ # index is on end
5075
+ # item row is less than move to row
5076
+ if item_r < new_r:
5077
+ r_ctr = new_r - sum(1 for _ in self.RI.get_iid_descendants(item))
5078
+
5079
+ # new parent has children
5080
+ # index is on end
5081
+ # item row is greater than move to row
5082
+ else:
5083
+ r_ctr = new_r + 1
5066
5084
  else:
5067
- r_ctr = new_r
5085
+ new_r = self.RI.tree_rns[parent_node.children[index].iid]
5086
+ # new parent has children
5087
+ # index is not end
5088
+ # item row is less than move to row
5089
+ if item_r < new_r:
5090
+ if self.RI.items_parent(item) == parent:
5091
+ r_ctr = (
5092
+ new_r
5093
+ + sum(1 for _ in self.RI.get_iid_descendants(parent_node.children[index].iid))
5094
+ - sum(1 for _ in self.RI.get_iid_descendants(item))
5095
+ )
5096
+ else:
5097
+ r_ctr = new_r - sum(1 for _ in self.RI.get_iid_descendants(item)) - 1
5098
+
5099
+ # new parent has children
5100
+ # index is not end
5101
+ # item row is greater than move to row
5102
+ else:
5103
+ r_ctr = new_r
5068
5104
  else:
5069
- if index is None:
5070
- index = 0
5071
- r_ctr = self.RI.tree_rns[parent_node.iid] + 1
5105
+ index = 0
5106
+ new_r = self.RI.tree_rns[parent_node.iid]
5107
+
5108
+ # new parent doesn't have children
5109
+ # index always start
5110
+ # item row is less than move to row
5111
+ if item_r < new_r:
5112
+ r_ctr = new_r - sum(1 for _ in self.RI.get_iid_descendants(item))
5113
+
5114
+ # new parent doesn't have children
5115
+ # index always start
5116
+ # item row is greater than move to row
5117
+ else:
5118
+ r_ctr = new_r + 1
5072
5119
  mapping[item_r] = r_ctr
5073
5120
  if parent in self.RI.tree_open_ids and self.item_displayed(parent):
5074
5121
  to_show.append(r_ctr)
@@ -5091,11 +5138,12 @@ class Sheet(tk.Frame):
5091
5138
  else:
5092
5139
  if (new_r := self.top_index_row(index)) is None:
5093
5140
  new_r = self.top_index_row((sum(1 for _ in self.RI.gen_top_nodes()) - 1))
5094
- item_r = self.RI.tree_rns[item]
5095
5141
  if item_r < new_r:
5096
- par_desc = sum(1 for _ in self.RI.get_iid_descendants(self.rowitem(new_r, data_index=True)))
5097
- item_desc = sum(1 for _ in self.RI.get_iid_descendants(item))
5098
- r_ctr = new_r + par_desc - item_desc
5142
+ r_ctr = (
5143
+ new_r
5144
+ + sum(1 for _ in self.RI.get_iid_descendants(self.rowitem(new_r, data_index=True)))
5145
+ - sum(1 for _ in self.RI.get_iid_descendants(item))
5146
+ )
5099
5147
  else:
5100
5148
  r_ctr = new_r
5101
5149
  mapping[item_r] = r_ctr
@@ -6258,13 +6306,7 @@ class Sheet(tk.Frame):
6258
6306
  ) -> Sheet:
6259
6307
  kwargs = get_dropdown_kwargs(*args, **kwargs)
6260
6308
  d = get_dropdown_dict(**kwargs)
6261
- if kwargs["set_value"] is None:
6262
- if kwargs["values"] and (v := self.MT.get_cell_data(r, c)) not in kwargs["values"]:
6263
- v = kwargs["values"][0]
6264
- else:
6265
- v == ""
6266
- else:
6267
- v = kwargs["set_value"]
6309
+ v = kwargs["set_value"] if kwargs["set_value"] is not None else kwargs["values"][0] if kwargs["values"] else ""
6268
6310
  if isinstance(r, str) and r.lower() == "all" and isinstance(c, int):
6269
6311
  for r_ in range(self.MT.total_data_rows()):
6270
6312
  self._create_dropdown(r_, c, v, d)
@@ -163,13 +163,13 @@ theme_dark: dict[str, str] = DotDict({
163
163
  "header_border_fg": "#505054",
164
164
  "header_grid_fg": "#8C8C8C",
165
165
  "header_fg": "gray70",
166
- "header_selected_cells_bg": "#545454",
166
+ "header_selected_cells_bg": "#4b4b4b",
167
167
  "header_selected_cells_fg": "#6aa2fc",
168
168
  "index_bg": "#141414",
169
169
  "index_border_fg": "#505054",
170
170
  "index_grid_fg": "#8C8C8C",
171
171
  "index_fg": "gray70",
172
- "index_selected_cells_bg": "#545454",
172
+ "index_selected_cells_bg": "#4b4b4b",
173
173
  "index_selected_cells_fg": "#6aa2fc",
174
174
  "top_left_bg": "#28282a",
175
175
  "top_left_fg": "#505054",
@@ -238,13 +238,13 @@ theme_black: dict[str, str] = DotDict({
238
238
  "header_border_fg": "#505054",
239
239
  "header_grid_fg": "#8C8C8C",
240
240
  "header_fg": "#FBB86C",
241
- "header_selected_cells_bg": "#545454",
241
+ "header_selected_cells_bg": "#4b4b4b",
242
242
  "header_selected_cells_fg": "#FBB86C",
243
243
  "index_bg": "#000000",
244
244
  "index_border_fg": "#505054",
245
245
  "index_grid_fg": "#8C8C8C",
246
246
  "index_fg": "#FBB86C",
247
- "index_selected_cells_bg": "#545454",
247
+ "index_selected_cells_bg": "#4b4b4b",
248
248
  "index_selected_cells_fg": "#FBB86C",
249
249
  "top_left_bg": "#141416",
250
250
  "top_left_fg": "#505054",
@@ -163,17 +163,16 @@ class TopLeftRectangle(tk.Canvas):
163
163
  recreate_selection_boxes: bool = True,
164
164
  ) -> None:
165
165
  try:
166
- self.update_idletasks()
167
- if new_h is None:
168
- h = self.winfo_height()
169
- if new_w is None:
170
- w = self.winfo_width()
171
- if new_w:
172
- self.config(width=new_w)
173
- w = new_w
174
- if new_h:
175
- self.config(height=new_h)
166
+ if isinstance(new_h, int):
176
167
  h = new_h
168
+ self.config(height=h)
169
+ else:
170
+ h = self.CH.current_height
171
+ if isinstance(new_w, int):
172
+ w = new_w
173
+ self.config(width=w)
174
+ else:
175
+ w = self.RI.current_width
177
176
  except Exception:
178
177
  return
179
178
  self.coords(self.rw_box, 0, h - 5, w, h)
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: tksheet
3
- Version: 7.2.9
3
+ Version: 7.2.11
4
4
  Summary: Tkinter table / sheet widget
5
5
  Author-email: ragardner <github@ragardner.simplelogin.com>
6
6
  License: Copyright (c) 2019 ragardner and open source contributors
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes