Wiresheet: Ctrl+click to select several links, delete them together
Ctrl+click toggles a link in the selection; Del or the link popup deletes every selected link after one confirmation, as a single undoable step. On a device, links the device refuses stay and are named in one warning. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
@@ -1014,23 +1014,30 @@ def on_tree_select(event):
|
||||
|
||||
|
||||
def delete_selected_link():
|
||||
"""Removes the currently selected link from the DOM and repaints."""
|
||||
if not app_state.selected_link_tag:
|
||||
return
|
||||
link_elem = app_state.canvas_link_map.get(app_state.selected_link_tag)
|
||||
if link_elem is None:
|
||||
"""Removes every selected link from the DOM, as one undoable step, and repaints."""
|
||||
link_elems = []
|
||||
for wire_tag in app_state.selected_link_tags:
|
||||
link_elem = app_state.canvas_link_map.get(wire_tag)
|
||||
if link_elem is not None and link_elem not in link_elems:
|
||||
link_elems.append(link_elem)
|
||||
if not link_elems:
|
||||
return
|
||||
|
||||
from_ref = link_elem.get("from", "")
|
||||
to_ref = link_elem.get("to", "")
|
||||
confirm = messagebox.askyesno(
|
||||
"Delete Link",
|
||||
f"Delete link?\n\n from: {from_ref}\n to: {to_ref}"
|
||||
)
|
||||
if not confirm:
|
||||
if len(link_elems) == 1:
|
||||
from_ref = link_elems[0].get("from", "")
|
||||
to_ref = link_elems[0].get("to", "")
|
||||
question = f"Delete link?\n\n from: {from_ref}\n to: {to_ref}"
|
||||
else:
|
||||
shown = link_elems[:15]
|
||||
lines = [f" {e.get('from', '')} → {e.get('to', '')}" for e in shown]
|
||||
if len(link_elems) > len(shown):
|
||||
lines.append(f" … and {len(link_elems) - len(shown)} more")
|
||||
question = f"Delete {len(link_elems)} links?\n\n" + "\n".join(lines)
|
||||
|
||||
if not messagebox.askyesno("Delete Link", question):
|
||||
return
|
||||
|
||||
sax_file.remove_link(link_elem)
|
||||
sax_file.remove_links(link_elems)
|
||||
|
||||
|
||||
def link_endpoint_components(link_elem):
|
||||
@@ -1341,7 +1348,6 @@ def _toggle_canvas_box(group_tag):
|
||||
|
||||
def on_canvas_click(event):
|
||||
canvas = app_state.canvas
|
||||
wiresheet.deselect_link()
|
||||
app_state.drag_data["tag"] = None
|
||||
|
||||
cx = canvas.canvasx(event.x)
|
||||
@@ -1351,6 +1357,14 @@ def on_canvas_click(event):
|
||||
group_tag = next((t for t in tags if t.startswith("comp_group_")), None)
|
||||
wire_tag = next((t for t in tags if t.startswith("link_wire_")), None)
|
||||
|
||||
if event.state & CTRL_MASK and wire_tag:
|
||||
# Picking links out one by one. Links and boxes are not selected together, so
|
||||
# Del always knows which of the two it is deleting.
|
||||
select_canvas_boxes([])
|
||||
wiresheet.toggle_link(wire_tag)
|
||||
return
|
||||
|
||||
wiresheet.deselect_link()
|
||||
if event.state & CTRL_MASK and group_tag and not wire_tag:
|
||||
# Picking boxes out one by one, so nothing is picked up to be moved.
|
||||
_toggle_canvas_box(group_tag)
|
||||
@@ -1743,7 +1757,11 @@ def on_canvas_right_click(event):
|
||||
wire_tag = next((t for t in tags if t.startswith("link_wire_")), None)
|
||||
|
||||
if wire_tag:
|
||||
wiresheet.select_link(wire_tag)
|
||||
# Right-clicking one of several selected links acts on all of them; any
|
||||
# other link becomes the selection on its own.
|
||||
if wire_tag not in app_state.selected_link_tags:
|
||||
select_canvas_boxes([])
|
||||
wiresheet.select_link(wire_tag)
|
||||
_rebuild_link_context_menu()
|
||||
link_context_menu.post(event.x_root, event.y_root)
|
||||
return
|
||||
@@ -2862,6 +2880,12 @@ def _rebuild_link_context_menu():
|
||||
left off rather than greyed out.
|
||||
"""
|
||||
link_context_menu.delete(0, tk.END)
|
||||
count = len(app_state.selected_link_tags)
|
||||
if count > 1:
|
||||
# Several links have no single far end, so there is nowhere to jump to.
|
||||
link_context_menu.add_command(label=f"Delete {count} Links",
|
||||
command=delete_selected_link)
|
||||
return
|
||||
link_context_menu.add_command(label="Delete Link", command=delete_selected_link)
|
||||
|
||||
link_elem = app_state.canvas_link_map.get(app_state.selected_link_tag)
|
||||
|
||||
Reference in New Issue
Block a user