App tree: keep expanded folders open; only the - sign closes one
Rebuilding the tree (live child loads, edits) now restores every row that was expanded, matched by component id or name path. Double-click no longer toggles a row through ttk's default binding. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
+1
-1
@@ -8,7 +8,7 @@ so later rebinding would only ever be seen by the module that did it.
|
||||
import configparser
|
||||
import os
|
||||
|
||||
VERSION = "0.0.0.147"
|
||||
VERSION = "0.0.0.148"
|
||||
PROPERTIES_FILE = os.path.join(os.path.dirname(os.path.abspath(__file__)), "editor.properties")
|
||||
DEFAULT_GRID_SIZE = 10
|
||||
DEFAULT_ADD_TIMESTAMP = True
|
||||
|
||||
@@ -1232,18 +1232,23 @@ def _open_special_view(comp):
|
||||
|
||||
|
||||
def on_tree_double_click(event):
|
||||
"""Double-click on a tree node opens its special view (or Properties)."""
|
||||
"""Double-click on a tree node opens its special view (or Properties).
|
||||
|
||||
Returns "break" so ttk's own double-click does not also toggle the row: only the
|
||||
+/- sign opens or closes a node.
|
||||
"""
|
||||
tree = app_state.tree
|
||||
item_id = tree.identify_row(event.y)
|
||||
if not item_id:
|
||||
return
|
||||
return "break"
|
||||
comp = app_state.tree_element_map.get(item_id)
|
||||
if comp is None:
|
||||
return
|
||||
return "break"
|
||||
if tree.parent(item_id) == "":
|
||||
show_properties(comp)
|
||||
else:
|
||||
_open_special_view(comp)
|
||||
return "break"
|
||||
|
||||
|
||||
def on_canvas_double_click(event):
|
||||
|
||||
+47
-1
@@ -59,9 +59,53 @@ def parse_xml_to_tree(treeview, parent_node, xml_element):
|
||||
parse_xml_to_tree(treeview, node_id, child)
|
||||
|
||||
|
||||
def _expansion_key(treeview, item, parent_key):
|
||||
"""Names a tree row in a way that survives a rebuild of the tree.
|
||||
|
||||
A component's id is stable across edits and across a fresh DOM read from the
|
||||
device; a row without one (the root, or an id-less file component) falls back to
|
||||
its name under its parent's key.
|
||||
"""
|
||||
elem = app_state.tree_element_map.get(item)
|
||||
comp_id = elem.get("id") if elem is not None else None
|
||||
if comp_id is not None and treeview.parent(item) != "":
|
||||
return ("id", comp_id)
|
||||
name = elem.get("name", "") if elem is not None else treeview.item(item, "text")
|
||||
return ("path", parent_key, name)
|
||||
|
||||
|
||||
def _collect_open_keys(treeview, parent="", parent_key=None, found=None):
|
||||
"""Returns the keys of every row that is expanded right now."""
|
||||
if found is None:
|
||||
found = set()
|
||||
for item in treeview.get_children(parent):
|
||||
key = _expansion_key(treeview, item, parent_key)
|
||||
if treeview.item(item, "open"):
|
||||
found.add(key)
|
||||
_collect_open_keys(treeview, item, key, found)
|
||||
return found
|
||||
|
||||
|
||||
def _reopen_keys(treeview, open_keys, parent="", parent_key=None):
|
||||
"""Expands again the rows that were expanded before the rebuild.
|
||||
|
||||
Setting the open flag in code does not raise <<TreeviewOpen>>, so this never
|
||||
starts a live child load of its own.
|
||||
"""
|
||||
for item in treeview.get_children(parent):
|
||||
key = _expansion_key(treeview, item, parent_key)
|
||||
if key in open_keys:
|
||||
treeview.item(item, open=True)
|
||||
_reopen_keys(treeview, open_keys, item, key)
|
||||
|
||||
|
||||
def refresh_treeview_from_dom(xml_root):
|
||||
"""Rebuilds navigation tree structures using current XML DOM trees."""
|
||||
"""Rebuilds navigation tree structures using current XML DOM trees.
|
||||
|
||||
Rows the user had expanded stay expanded; only the user's own "-" closes one.
|
||||
"""
|
||||
tree = app_state.tree
|
||||
open_keys = _collect_open_keys(tree)
|
||||
app_state.tree_element_map.clear()
|
||||
|
||||
for item in tree.get_children():
|
||||
@@ -88,6 +132,8 @@ def refresh_treeview_from_dom(xml_root):
|
||||
else:
|
||||
parse_xml_to_tree(tree, root_node, xml_root)
|
||||
|
||||
_reopen_keys(tree, open_keys)
|
||||
|
||||
if _tree_filled is not None:
|
||||
_tree_filled()
|
||||
|
||||
|
||||
Reference in New Issue
Block a user