Link popup: go to the sheet the other end of the link is on

Right-clicking a wire or a knob now offers Go to Link Wire Sheet "<name>",
naming the sheet the far end is on -- the end a grey knob stands in for. A link
with both ends on the open sheet has nowhere to go, so the entry is left off
rather than greyed out.

find_component_by_path turns a link's from/to reference back into the component
it points at, the inverse of get_component_path, and the sheet is that
component's parent; a parent of <app> is the file's root node, which the popup
names after the file.

Arriving selects the same link and scrolls it to the middle of the view. It is
found by its element rather than by the tag it was picked on, since a repaint
hands out fresh wire tags, and it waits for that repaint from an after_idle
callback: ttk queues its selection event rather than dispatching it, so the
sheet is not painted when the tree node is selected -- and painting a sheet
clears the selected link, which was wiping the selection this feature had just
made. The jump is an ordinary sheet opening, so Back returns to where the link
was picked.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
2026-09-04 23:26:46 +03:00
co-authored by Claude Opus 5
parent ad8396ef7b
commit a1f8059c49
4 changed files with 191 additions and 3 deletions
+28
View File
@@ -85,6 +85,34 @@ def find_parent_element(root_elem, child_to_find):
return None
def find_component_by_path(root_elem, path):
"""The component an absolute path names, or None if the document has no such node.
The inverse of get_component_path, and the way a <link>'s from/to reference is
turned back into the component it points at. Paths carry no entry for <app>, so
resolution starts among its children.
"""
if root_elem is None or not path:
return None
names = [part for part in path.split("/") if part]
if not names:
return None
node = root_elem.find("app")
if node is None:
node = root_elem
for name in names:
node = next(
(child for child in node if child.tag == "comp" and child.get("name") == name),
None,
)
if node is None:
return None
return node
def get_component_path(element, root_elem):
"""Computes the absolute path of a component within the application tree hierarchy."""
path_parts = []