tksheet 7.5.4__py3-none-any.whl → 7.5.7__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/row_index.py CHANGED
@@ -24,6 +24,7 @@ from .functions import (
24
24
  event_dict,
25
25
  event_has_char_key,
26
26
  event_opens_dropdown_or_checkbox,
27
+ get_bg_fg,
27
28
  get_menu_kwargs,
28
29
  get_n2a,
29
30
  get_new_indexes,
@@ -32,15 +33,21 @@ from .functions import (
32
33
  mod_event_val,
33
34
  new_tk_event,
34
35
  num2alpha,
36
+ push_displayed,
37
+ recursive_bind,
35
38
  rounded_box_coords,
39
+ safe_copy,
36
40
  stored_event_dict,
37
41
  try_b_index,
38
42
  try_binding,
43
+ widget_descendants,
39
44
  wrap_text,
40
45
  )
46
+ from .menus import build_empty_rc_menu, build_index_rc_menu
41
47
  from .other_classes import DraggedRowColumn, DropdownStorage, EventDataDict, Node, TextEditorStorage
42
48
  from .sorting import sort_columns_by_row, sort_row
43
49
  from .text_editor import TextEditor
50
+ from .tooltip import Tooltip
44
51
 
45
52
 
46
53
  class RowIndex(tk.Canvas):
@@ -55,6 +62,18 @@ class RowIndex(tk.Canvas):
55
62
  self.MT = None # is set from within MainTable() __init__
56
63
  self.CH = None # is set from within MainTable() __init__
57
64
  self.TL = None # is set from within TopLeftRectangle() __init__
65
+ self.tooltip = Tooltip(
66
+ **{
67
+ "parent": self,
68
+ "sheet_ops": self.ops,
69
+ "menu_kwargs": get_menu_kwargs(self.ops),
70
+ **get_bg_fg(self.ops),
71
+ "scrollbar_style": f"Sheet{self.PAR.unique_id}.Vertical.TScrollbar",
72
+ }
73
+ )
74
+ self.tooltip_widgets = widget_descendants(self.tooltip)
75
+ self.tooltip_coords, self.tooltip_after_id, self.tooltip_showing = None, None, False
76
+ recursive_bind(self.tooltip, "<Leave>", self.close_tooltip_save)
58
77
  self.current_cursor = ""
59
78
  self.new_iid_ctr = -1
60
79
  self.current_width = None
@@ -108,7 +127,7 @@ class RowIndex(tk.Canvas):
108
127
  self.disp_dropdown = {}
109
128
  self.disp_checkbox = {}
110
129
  self.disp_tree_arrow = {}
111
- self.disp_boxes = set()
130
+ self.disp_corners = set()
112
131
  self.hidd_text = {}
113
132
  self.hidd_high = {}
114
133
  self.hidd_grid = {}
@@ -118,7 +137,7 @@ class RowIndex(tk.Canvas):
118
137
  self.hidd_dropdown = {}
119
138
  self.hidd_checkbox = {}
120
139
  self.hidd_tree_arrow = {}
121
- self.hidd_boxes = set()
140
+ self.hidd_corners = set()
122
141
 
123
142
  self.align = kwargs["row_index_align"]
124
143
 
@@ -168,15 +187,17 @@ class RowIndex(tk.Canvas):
168
187
  popup_menu = None
169
188
  if self.MT.identify_row(y=event.y, allow_end=False) is None:
170
189
  self.MT.deselect("all")
171
- r = len(self.MT.col_positions) - 1
190
+ r = len(self.MT.row_positions) - 1
172
191
  if self.MT.rc_popup_menus_enabled:
173
192
  popup_menu = self.MT.empty_rc_popup_menu
193
+ build_empty_rc_menu(self.MT, popup_menu)
174
194
  elif self.row_selection_enabled and not self.currently_resizing_width and not self.currently_resizing_height:
175
195
  r = self.MT.identify_row(y=event.y)
176
196
  if r < len(self.MT.row_positions) - 1:
177
197
  if self.MT.row_selected(r):
178
198
  if self.MT.rc_popup_menus_enabled:
179
199
  popup_menu = self.ri_rc_popup_menu
200
+ build_index_rc_menu(self.MT, popup_menu, r)
180
201
  else:
181
202
  if self.MT.single_selection_enabled and self.MT.rc_select_enabled:
182
203
  self.select_row(r, redraw=True)
@@ -184,11 +205,10 @@ class RowIndex(tk.Canvas):
184
205
  self.toggle_select_row(r, redraw=True)
185
206
  if self.MT.rc_popup_menus_enabled:
186
207
  popup_menu = self.ri_rc_popup_menu
208
+ build_index_rc_menu(self.MT, popup_menu, r)
187
209
  try_binding(self.extra_rc_func, event)
188
210
  if popup_menu is not None:
189
211
  self.popup_menu_loc = r
190
- self.MT.popup_menu_disable_edit_if_readonly(popup_menu)
191
- self.MT.popup_menu_disable_undo_redo(popup_menu)
192
212
  popup_menu.tk_popup(event.x_root, event.y_root)
193
213
 
194
214
  def ctrl_b1_press(self, event: Any) -> None:
@@ -910,7 +930,7 @@ class RowIndex(tk.Canvas):
910
930
  event_data = self.MT.new_event_dict("edit_table")
911
931
  try_binding(self.MT.extra_begin_sort_cells_func, event_data)
912
932
  if key is None:
913
- key = self.PAR.ops.sort_key
933
+ key = self.ops.sort_key
914
934
  for r in rows:
915
935
  datarn = self.MT.datarn(r)
916
936
  for c, val in enumerate(sort_row(self.MT.data[datarn], reverse=reverse, key=key)):
@@ -956,7 +976,7 @@ class RowIndex(tk.Canvas):
956
976
  row = self.MT.datarn(self.MT.selected.row)
957
977
  if try_binding(self.ri_extra_begin_sort_cols_func, event_data, "begin_move_columns"):
958
978
  if key is None:
959
- key = self.PAR.ops.sort_key
979
+ key = self.ops.sort_key
960
980
  sorted_indices, data_new_idxs = sort_columns_by_row(self.MT.data, row=row, reverse=reverse, key=key)
961
981
  disp_new_idxs = {}
962
982
  if self.MT.all_columns_displayed:
@@ -1294,44 +1314,60 @@ class RowIndex(tk.Canvas):
1294
1314
  redrawn = False
1295
1315
  kwargs = self.get_cell_kwargs(datarn, key="highlight")
1296
1316
  if kwargs:
1297
- fill = kwargs[0]
1298
- if fill and not fill.startswith("#"):
1299
- fill = color_map[fill]
1317
+ high_bg = kwargs[0]
1318
+ if high_bg and not high_bg.startswith("#"):
1319
+ high_bg = color_map[high_bg]
1300
1320
  if "rows" in selections and r in selections["rows"]:
1301
1321
  txtfg = (
1302
1322
  self.ops.index_selected_rows_fg
1303
1323
  if kwargs[1] is None or self.ops.display_selected_fg_over_highlights
1304
1324
  else kwargs[1]
1305
1325
  )
1306
- if fill:
1307
- fill = (
1308
- f"#{int((int(fill[1:3], 16) + int(sel_rows_bg[1:3], 16)) / 2):02X}"
1309
- + f"{int((int(fill[3:5], 16) + int(sel_rows_bg[3:5], 16)) / 2):02X}"
1310
- + f"{int((int(fill[5:], 16) + int(sel_rows_bg[5:], 16)) / 2):02X}"
1311
- )
1326
+ redrawn = self.redraw_highlight(
1327
+ 0,
1328
+ fr + 1,
1329
+ self.current_width - 1,
1330
+ sr,
1331
+ fill=self.ops.index_selected_rows_bg
1332
+ if high_bg is None
1333
+ else (
1334
+ f"#{int((int(high_bg[1:3], 16) + int(sel_rows_bg[1:3], 16)) / 2):02X}"
1335
+ + f"{int((int(high_bg[3:5], 16) + int(sel_rows_bg[3:5], 16)) / 2):02X}"
1336
+ + f"{int((int(high_bg[5:], 16) + int(sel_rows_bg[5:], 16)) / 2):02X}"
1337
+ ),
1338
+ outline=self.ops.index_fg if has_dd and self.ops.show_dropdown_borders else "",
1339
+ )
1312
1340
  elif "cells" in selections and r in selections["cells"]:
1313
1341
  txtfg = (
1314
1342
  self.ops.index_selected_cells_fg
1315
1343
  if kwargs[1] is None or self.ops.display_selected_fg_over_highlights
1316
1344
  else kwargs[1]
1317
1345
  )
1318
- if fill:
1319
- fill = (
1320
- f"#{int((int(fill[1:3], 16) + int(sel_cells_bg[1:3], 16)) / 2):02X}"
1321
- + f"{int((int(fill[3:5], 16) + int(sel_cells_bg[3:5], 16)) / 2):02X}"
1322
- + f"{int((int(fill[5:], 16) + int(sel_cells_bg[5:], 16)) / 2):02X}"
1323
- )
1324
- else:
1325
- txtfg = self.ops.index_fg if kwargs[1] is None else kwargs[1]
1326
- if fill:
1327
1346
  redrawn = self.redraw_highlight(
1328
1347
  0,
1329
1348
  fr + 1,
1330
1349
  self.current_width - 1,
1331
1350
  sr,
1332
- fill=fill,
1351
+ fill=self.ops.index_selected_cells_bg
1352
+ if high_bg is None
1353
+ else (
1354
+ f"#{int((int(high_bg[1:3], 16) + int(sel_cells_bg[1:3], 16)) / 2):02X}"
1355
+ + f"{int((int(high_bg[3:5], 16) + int(sel_cells_bg[3:5], 16)) / 2):02X}"
1356
+ + f"{int((int(high_bg[5:], 16) + int(sel_cells_bg[5:], 16)) / 2):02X}"
1357
+ ),
1333
1358
  outline=self.ops.index_fg if has_dd and self.ops.show_dropdown_borders else "",
1334
1359
  )
1360
+ else:
1361
+ txtfg = self.ops.index_fg if kwargs[1] is None else kwargs[1]
1362
+ if high_bg:
1363
+ redrawn = self.redraw_highlight(
1364
+ 0,
1365
+ fr + 1,
1366
+ self.current_width - 1,
1367
+ sr,
1368
+ fill=high_bg,
1369
+ outline=self.ops.index_fg if has_dd and self.ops.show_dropdown_borders else "",
1370
+ )
1335
1371
  tree_arrow_fg = txtfg
1336
1372
  elif not kwargs:
1337
1373
  if "rows" in selections and r in selections["rows"]:
@@ -1613,6 +1649,17 @@ class RowIndex(tk.Canvas):
1613
1649
  self.MT.char_widths[self.index_font][c] = wd
1614
1650
  return wd
1615
1651
 
1652
+ def redraw_corner(self, x: float, y: float) -> None:
1653
+ if self.hidd_corners:
1654
+ iid = self.hidd_corners.pop()
1655
+ self.coords(iid, x - 10, y, x, y, x, y + 10)
1656
+ self.itemconfig(iid, fill=self.ops.index_grid_fg, state="normal")
1657
+ self.disp_corners.add(iid)
1658
+ else:
1659
+ self.disp_corners.add(
1660
+ self.create_polygon(x - 10, y, x, y, x, y + 10, fill=self.ops.index_grid_fg, tags="lift")
1661
+ )
1662
+
1616
1663
  def redraw_grid_and_text(
1617
1664
  self,
1618
1665
  last_row_line_pos: float,
@@ -1640,6 +1687,8 @@ class RowIndex(tk.Canvas):
1640
1687
  self.disp_checkbox = {}
1641
1688
  self.hidd_tree_arrow.update(self.disp_tree_arrow)
1642
1689
  self.disp_tree_arrow = {}
1690
+ self.hidd_corners.update(self.disp_corners)
1691
+ self.disp_corners = set()
1643
1692
  self.visible_row_dividers = {}
1644
1693
  self.row_width_resize_bbox = (
1645
1694
  self.current_width - 2,
@@ -1691,6 +1740,7 @@ class RowIndex(tk.Canvas):
1691
1740
  dd_coords = self.dropdown.get_coords()
1692
1741
  treeview = self.ops.treeview
1693
1742
  wrap = self.ops.index_wrap
1743
+ note_corners = self.ops.note_corners
1694
1744
  for r in range(text_start_row, text_end_row):
1695
1745
  rtopgridln = self.MT.row_positions[r]
1696
1746
  rbotgridln = self.MT.row_positions[r + 1]
@@ -1786,6 +1836,10 @@ class RowIndex(tk.Canvas):
1786
1836
  open_=self.MT._row_index[datarn].iid in self.tree_open_ids,
1787
1837
  level=level,
1788
1838
  )
1839
+
1840
+ if note_corners and max_width > 5 and datarn in self.cell_options and "note" in self.cell_options[datarn]:
1841
+ self.redraw_corner(self.current_width, rtopgridln)
1842
+
1789
1843
  if max_width <= 1:
1790
1844
  continue
1791
1845
  text = self.cell_str(datarn, fix=False)
@@ -1813,6 +1867,7 @@ class RowIndex(tk.Canvas):
1813
1867
  fill=fill,
1814
1868
  font=font,
1815
1869
  anchor=align,
1870
+ tags=("lift", "t", f"{r}"),
1816
1871
  )
1817
1872
  else:
1818
1873
  self.itemconfig(
@@ -1822,6 +1877,7 @@ class RowIndex(tk.Canvas):
1822
1877
  font=font,
1823
1878
  anchor=align,
1824
1879
  state="normal",
1880
+ tags=("lift", "t", f"{r}"),
1825
1881
  )
1826
1882
  else:
1827
1883
  iid = self.create_text(
@@ -1831,7 +1887,7 @@ class RowIndex(tk.Canvas):
1831
1887
  fill=fill,
1832
1888
  font=font,
1833
1889
  anchor=align,
1834
- tag="lift",
1890
+ tags=("lift", "t", f"{r}"),
1835
1891
  )
1836
1892
  self.disp_text[iid] = True
1837
1893
  else:
@@ -1846,6 +1902,7 @@ class RowIndex(tk.Canvas):
1846
1902
  fill=fill,
1847
1903
  font=font,
1848
1904
  anchor=align,
1905
+ tags=("lift", "t", f"{r}"),
1849
1906
  )
1850
1907
  else:
1851
1908
  self.itemconfig(
@@ -1855,6 +1912,7 @@ class RowIndex(tk.Canvas):
1855
1912
  font=font,
1856
1913
  anchor=align,
1857
1914
  state="normal",
1915
+ tags=("lift", "t", f"{r}"),
1858
1916
  )
1859
1917
  else:
1860
1918
  iid = self.create_text(
@@ -1864,7 +1922,7 @@ class RowIndex(tk.Canvas):
1864
1922
  fill=fill,
1865
1923
  font=font,
1866
1924
  anchor=align,
1867
- tag="lift",
1925
+ tags=("lift", "t", f"{r}"),
1868
1926
  )
1869
1927
  self.disp_text[iid] = True
1870
1928
  draw_y += self.MT.header_txt_height
@@ -1881,11 +1939,115 @@ class RowIndex(tk.Canvas):
1881
1939
  if showing:
1882
1940
  self.itemconfig(iid, state="hidden")
1883
1941
  dct[iid] = False
1942
+ for iid in self.hidd_corners:
1943
+ self.itemconfig(iid, state="hidden")
1884
1944
  self.tag_raise("lift")
1885
1945
  if self.disp_resize_lines:
1886
1946
  self.tag_raise("rh")
1947
+ self.tag_bind("t", "<Enter>", self.enter_text)
1948
+ self.tag_bind("t", "<Leave>", self.leave_text)
1887
1949
  return True
1888
1950
 
1951
+ def enter_text(self, event: tk.Event | None = None) -> None:
1952
+ if self.text_editor.open or self.dropdown.open:
1953
+ return
1954
+ can_x, can_y = self.canvasx(event.x), self.canvasy(event.y)
1955
+ for i in self.find_overlapping(can_x - 1, can_y - 1, can_x + 1, can_y + 1):
1956
+ try:
1957
+ if (coords := self.gettags(i)[2]) == self.tooltip_coords:
1958
+ return
1959
+ self.tooltip_coords = coords
1960
+ self.tooltip_last_x, self.tooltip_last_y = self.winfo_pointerx(), self.winfo_pointery()
1961
+ self.start_tooltip_timer()
1962
+ return
1963
+ except Exception:
1964
+ continue
1965
+
1966
+ def leave_text(self, event: tk.Event | None = None) -> None:
1967
+ if self.tooltip_after_id is not None:
1968
+ self.after_cancel(self.tooltip_after_id)
1969
+ self.tooltip_after_id = None
1970
+ if self.tooltip_showing:
1971
+ if self.winfo_containing(self.winfo_pointerx(), self.winfo_pointery()) not in self.tooltip_widgets:
1972
+ self.close_tooltip_save()
1973
+ else:
1974
+ self.tooltip_coords = None
1975
+
1976
+ def start_tooltip_timer(self) -> None:
1977
+ self.tooltip_after_id = self.after(1000, self.check_and_show_tooltip)
1978
+
1979
+ def check_and_show_tooltip(self, event: tk.Event | None = None) -> None:
1980
+ current_x, current_y = self.winfo_pointerx(), self.winfo_pointery()
1981
+ if current_x < 0 or current_y < 0:
1982
+ return
1983
+ if abs(current_x - self.tooltip_last_x) <= 1 and abs(current_y - self.tooltip_last_y) <= 1:
1984
+ self.show_tooltip()
1985
+ else:
1986
+ self.tooltip_last_x, self.tooltip_last_y = current_x, current_y
1987
+ self.tooltip_after_id = self.after(400, self.check_and_show_tooltip)
1988
+
1989
+ def hide_tooltip(self) -> None:
1990
+ self.tooltip.withdraw()
1991
+ self.tooltip_showing, self.tooltip_coords = False, None
1992
+
1993
+ def show_tooltip(self) -> None:
1994
+ r = int(self.tooltip_coords)
1995
+ datarn = self.MT.datarn(r)
1996
+ kws = self.get_cell_kwargs(datarn, key="note")
1997
+ if not self.ops.tooltips and not kws and not self.ops.user_can_create_notes:
1998
+ return
1999
+ cell_readonly = self.get_cell_kwargs(datarn, "readonly") or not self.MT.index_edit_cell_enabled()
2000
+ if kws:
2001
+ note = kws["note"]
2002
+ note_readonly = kws["readonly"]
2003
+ elif self.ops.user_can_create_notes:
2004
+ note = ""
2005
+ note_readonly = bool(cell_readonly)
2006
+ else:
2007
+ note = None
2008
+ note_readonly = True
2009
+ self.tooltip.reset(
2010
+ **{
2011
+ "text": f"{self.get_cell_data(datarn, none_to_empty_str=True)}",
2012
+ "cell_readonly": cell_readonly,
2013
+ "note": note,
2014
+ "note_readonly": note_readonly,
2015
+ "row": r,
2016
+ "col": 0,
2017
+ "menu_kwargs": get_menu_kwargs(self.ops),
2018
+ **get_bg_fg(self.ops),
2019
+ "user_can_create_notes": self.ops.user_can_create_notes,
2020
+ "note_only": not self.ops.tooltips and isinstance(note, str),
2021
+ "width": self.ops.tooltip_width,
2022
+ "height": self.ops.tooltip_height,
2023
+ }
2024
+ )
2025
+ self.tooltip.set_position(self.tooltip_last_x - 4, self.tooltip_last_y - 4)
2026
+ self.tooltip_showing = True
2027
+
2028
+ def close_tooltip_save(self, event: tk.Event | None = None) -> None:
2029
+ widget = self.winfo_containing(self.winfo_pointerx(), self.winfo_pointery())
2030
+ if any(widget == tw for tw in self.tooltip_widgets):
2031
+ try:
2032
+ if self.tooltip.notebook.index("current") == 0:
2033
+ self.tooltip.content_text.focus_set()
2034
+ else:
2035
+ self.tooltip.note_text.focus_set()
2036
+ except Exception:
2037
+ self.tooltip.content_text.focus_set()
2038
+ return
2039
+ if not self.tooltip.cell_readonly:
2040
+ r, _, cell, note = self.tooltip.get()
2041
+ datarn = self.MT.datarn(r)
2042
+ event_data = self.new_single_edit_event(r, datarn, "??", self.get_cell_data(datarn), cell)
2043
+ self.do_single_edit(r, datarn, event_data, cell)
2044
+ if not self.tooltip.note_readonly:
2045
+ span = self.PAR.span(datarn).options(table=False, index=True)
2046
+ self.PAR.note(span, note=note if note else None, readonly=False)
2047
+ self.hide_tooltip()
2048
+ self.MT.refresh()
2049
+ self.focus_set()
2050
+
1889
2051
  def get_redraw_selections(self, startr: int, endr: int) -> dict[str, set[int]]:
1890
2052
  d = defaultdict(set)
1891
2053
  for _, box in self.MT.get_selection_items():
@@ -2099,6 +2261,18 @@ class RowIndex(tk.Canvas):
2099
2261
  self.itemconfig(self.text_editor.canvas_id, state="hidden")
2100
2262
  self.text_editor.open = False
2101
2263
 
2264
+ def do_single_edit(self, r: int, datarn: int, event_data: EventDataDict, val):
2265
+ edited = False
2266
+ set_data = partial(self.set_cell_data_undo, r=r, datarn=datarn, check_input_valid=False)
2267
+ if self.MT.edit_validation_func:
2268
+ val = self.MT.edit_validation_func(event_data)
2269
+ if val is not None and self.input_valid_for_cell(datarn, val):
2270
+ edited = set_data(value=val)
2271
+ elif self.input_valid_for_cell(datarn, val):
2272
+ edited = set_data(value=val)
2273
+ if edited:
2274
+ try_binding(self.extra_end_edit_cell_func, event_data)
2275
+
2102
2276
  # r is displayed row
2103
2277
  def close_text_editor(self, event: tk.Event) -> Literal["break"] | None:
2104
2278
  # checking if text editor should be closed or not
@@ -2121,33 +2295,8 @@ class RowIndex(tk.Canvas):
2121
2295
  text_editor_value = self.text_editor.get()
2122
2296
  r = self.text_editor.row
2123
2297
  datarn = r if self.MT.all_rows_displayed else self.MT.displayed_rows[r]
2124
- event_data = event_dict(
2125
- name="end_edit_index",
2126
- sheet=self.PAR.name,
2127
- widget=self,
2128
- cells_index={datarn: self.get_cell_data(datarn)},
2129
- key=event.keysym,
2130
- value=text_editor_value,
2131
- loc=r,
2132
- row=r,
2133
- boxes=self.MT.get_boxes(),
2134
- selected=self.MT.selected,
2135
- )
2136
- edited = False
2137
- set_data = partial(
2138
- self.set_cell_data_undo,
2139
- r=r,
2140
- datarn=datarn,
2141
- check_input_valid=False,
2142
- )
2143
- if self.MT.edit_validation_func:
2144
- text_editor_value = self.MT.edit_validation_func(event_data)
2145
- if text_editor_value is not None and self.input_valid_for_cell(datarn, text_editor_value):
2146
- edited = set_data(value=text_editor_value)
2147
- elif self.input_valid_for_cell(datarn, text_editor_value):
2148
- edited = set_data(value=text_editor_value)
2149
- if edited:
2150
- try_binding(self.extra_end_edit_cell_func, event_data)
2298
+ event_data = self.new_single_edit_event(r, datarn, event.keysym, self.get_cell_data(datarn), text_editor_value)
2299
+ self.do_single_edit(r, datarn, event_data, text_editor_value)
2151
2300
  self.MT.recreate_all_selection_boxes()
2152
2301
  self.hide_text_editor_and_dropdown()
2153
2302
  if event.keysym != "FocusOut":
@@ -2283,27 +2432,11 @@ class RowIndex(tk.Canvas):
2283
2432
  self.MT.main_table_redraw_grid_and_text(redraw_header=False, redraw_row_index=True, redraw_table=False)
2284
2433
 
2285
2434
  # r is displayed row
2286
- def close_dropdown_window(
2287
- self,
2288
- r: int | None = None,
2289
- selection: Any = None,
2290
- redraw: bool = True,
2291
- ) -> None:
2435
+ def close_dropdown_window(self, r: int | None = None, selection: Any = None, redraw: bool = True) -> None:
2292
2436
  if r is not None and selection is not None:
2293
2437
  datarn = r if self.MT.all_rows_displayed else self.MT.displayed_rows[r]
2294
2438
  kwargs = self.get_cell_kwargs(datarn, key="dropdown")
2295
- event_data = event_dict(
2296
- name="end_edit_index",
2297
- sheet=self.PAR.name,
2298
- widget=self,
2299
- cells_header={datarn: self.get_cell_data(datarn)},
2300
- key="??",
2301
- value=selection,
2302
- loc=r,
2303
- row=r,
2304
- boxes=self.MT.get_boxes(),
2305
- selected=self.MT.selected,
2306
- )
2439
+ event_data = self.new_single_edit_event(r, datarn, "??", self.get_cell_data(datarn), selection)
2307
2440
  try_binding(kwargs["select_function"], event_data)
2308
2441
  selection = selection if not self.MT.edit_validation_func else self.MT.edit_validation_func(event_data)
2309
2442
  if selection is not None:
@@ -2482,12 +2615,14 @@ class RowIndex(tk.Canvas):
2482
2615
  return Node(text=iid, iid=iid, parent=self.get_row_parent(datarn))
2483
2616
  if self.get_cell_kwargs(datarn, key="checkbox", cell=r_ops):
2484
2617
  return False
2485
- elif (
2486
- (kwargs := self.get_cell_kwargs(datarn, key="dropdown", cell=r_ops))
2487
- and kwargs["validate_input"]
2488
- and kwargs["values"]
2489
- ):
2490
- return kwargs["values"][0]
2618
+ elif (kwargs := self.get_cell_kwargs(datarn, key="dropdown", cell=r_ops)) and kwargs["validate_input"]:
2619
+ if kwargs["default_value"] is None:
2620
+ if kwargs["values"]:
2621
+ return safe_copy(kwargs["values"][0])
2622
+ else:
2623
+ return ""
2624
+ else:
2625
+ return safe_copy(kwargs["default_value"])
2491
2626
  else:
2492
2627
  return ""
2493
2628
 
@@ -2538,18 +2673,7 @@ class RowIndex(tk.Canvas):
2538
2673
  else:
2539
2674
  value = False
2540
2675
  self.set_cell_data_undo(r, datarn=datarn, value=value, cell_resize=False)
2541
- event_data = event_dict(
2542
- name="end_edit_index",
2543
- sheet=self.PAR.name,
2544
- widget=self,
2545
- cells_index={datarn: pre_edit_value},
2546
- key="??",
2547
- value=value,
2548
- loc=r,
2549
- row=r,
2550
- boxes=self.MT.get_boxes(),
2551
- selected=self.MT.selected,
2552
- )
2676
+ event_data = self.new_single_edit_event(r, datarn, "??", pre_edit_value, value)
2553
2677
  if kwargs["check_function"] is not None:
2554
2678
  kwargs["check_function"](event_data)
2555
2679
  try_binding(self.extra_end_edit_cell_func, event_data)
@@ -2562,6 +2686,21 @@ class RowIndex(tk.Canvas):
2562
2686
  else:
2563
2687
  return {}
2564
2688
 
2689
+ def new_single_edit_event(self, r: int, datarn: int, k: str, before_val: Any, after_val: Any) -> EventDataDict:
2690
+ return event_dict(
2691
+ name="end_edit_index",
2692
+ sheet=self.PAR.name,
2693
+ widget=self,
2694
+ cells_index={datarn: before_val},
2695
+ key=k,
2696
+ value=after_val,
2697
+ loc=r,
2698
+ row=r,
2699
+ boxes=self.MT.get_boxes(),
2700
+ selected=self.MT.selected,
2701
+ data={datarn: after_val},
2702
+ )
2703
+
2565
2704
  # Treeview Mode
2566
2705
 
2567
2706
  def tree_reset(self) -> None:
@@ -2632,13 +2771,17 @@ class RowIndex(tk.Canvas):
2632
2771
 
2633
2772
  # handle displaying the new rows
2634
2773
  event_data["added"]["rows"]["row_heights"] = {}
2774
+ # parent exists and it's displayed and it's open
2635
2775
  if parent and self.PAR.item_displayed(parent) and parent in self.tree_open_ids:
2636
2776
  self.MT.displayed_rows = add_to_displayed(self.MT.displayed_rows, event_data["added"]["rows"]["index"])
2637
2777
  disp_idx = self.MT.disprn(self.rns[a_node.iid]) # first node, they're contiguous because not undo
2638
2778
  h = self.MT.get_default_row_height()
2639
2779
  for i in range(len(event_data["added"]["rows"]["index"])):
2640
2780
  event_data["added"]["rows"]["row_heights"][disp_idx + i] = h
2641
-
2781
+ # parent exists and either it's not displayed or not open
2782
+ elif parent:
2783
+ self.MT.displayed_rows = push_displayed(self.MT.displayed_rows, event_data["added"]["rows"]["index"])
2784
+ # no parent, top level
2642
2785
  elif not parent:
2643
2786
  self.MT.displayed_rows = add_to_displayed(self.MT.displayed_rows, event_data["added"]["rows"]["index"])
2644
2787
  h = self.MT.get_default_row_height()