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:
+70
-24
@@ -843,6 +843,8 @@ def draw_links():
|
||||
app_state.canvas_link_map.clear()
|
||||
app_state.knob_link_ends.clear()
|
||||
app_state.selected_link_tag = None
|
||||
app_state.selected_link_tags.clear()
|
||||
_selected_link_restore.clear()
|
||||
app_state.unroutable_link_count = 0
|
||||
if app_state.xml_root_element is None:
|
||||
return
|
||||
@@ -920,7 +922,8 @@ def draw_links():
|
||||
app_state.unroutable_link_count = len(jobs) - len(routed)
|
||||
|
||||
|
||||
_selected_link_restore = [] # [(item, fill, outline, width)] captured when a link is selected
|
||||
# wire tag -> [(item, fill, outline, width)], captured when that link is selected
|
||||
_selected_link_restore = {}
|
||||
|
||||
|
||||
def trim_to_knobs(x1, y1, x2, y2):
|
||||
@@ -938,31 +941,36 @@ def trim_to_knobs(x1, y1, x2, y2):
|
||||
x2 - ux * inset, y2 - uy * inset)
|
||||
|
||||
|
||||
def select_link(wire_tag):
|
||||
def select_link(wire_tag, add=False):
|
||||
"""Highlights a link in red, remembering what each of its items looked like.
|
||||
|
||||
The colours cannot simply be reset to LINK_COLOR afterwards: a link shown as knobs
|
||||
may be grey, or half grey, and blanket-restoring would repaint it as an ordinary
|
||||
on-sheet marker.
|
||||
|
||||
With `add` the link joins whatever links are already selected (Ctrl+click);
|
||||
otherwise it becomes the only one.
|
||||
"""
|
||||
canvas = app_state.canvas
|
||||
deselect_link()
|
||||
if not add:
|
||||
deselect_link()
|
||||
elif wire_tag in app_state.selected_link_tags:
|
||||
return
|
||||
if wire_tag and wire_tag in app_state.canvas_link_map:
|
||||
# A knob can stand for several links. One already selected through another link
|
||||
# is red by now, so its true colours are taken from that link's record.
|
||||
captured = {entry[0]: entry for entries in _selected_link_restore.values()
|
||||
for entry in entries}
|
||||
restore = _selected_link_restore.setdefault(wire_tag, [])
|
||||
for item in canvas.find_withtag(wire_tag):
|
||||
_selected_link_restore.append((
|
||||
restore.append(captured.get(item) or (
|
||||
item,
|
||||
canvas.itemcget(item, "fill"),
|
||||
canvas.itemcget(item, "outline") if canvas.type(item) != "line" else "",
|
||||
canvas.itemcget(item, "width"),
|
||||
))
|
||||
if canvas.type(item) == "line":
|
||||
canvas.itemconfig(item, fill=LINK_SELECT_COLOR,
|
||||
width=LINK_SELECT_WIDTH)
|
||||
elif "link_knob_core" in canvas.gettags(item):
|
||||
pass # the white centre stays white while selected
|
||||
else:
|
||||
canvas.itemconfig(item, fill=LINK_SELECT_COLOR)
|
||||
canvas.tag_raise(wire_tag)
|
||||
_paint_link_selected(wire_tag)
|
||||
app_state.selected_link_tags.append(wire_tag)
|
||||
app_state.selected_link_tag = wire_tag
|
||||
|
||||
# A link with both ends on this sheet but no drawable route is two knobs with
|
||||
@@ -975,26 +983,64 @@ def select_link(wire_tag):
|
||||
*trim_to_knobs(*ends), fill=LINK_SELECT_COLOR,
|
||||
width=LINK_SELECT_WIDTH, dash=LINK_HINT_DASH,
|
||||
arrow=tk.LAST, arrowshape=(8, 9, 3),
|
||||
tags=("link", "link_select_hint")
|
||||
tags=("link", "link_select_hint", f"link_select_hint_{wire_tag}")
|
||||
)
|
||||
canvas.tag_raise("link_select_hint")
|
||||
canvas.tag_raise("link_knob")
|
||||
|
||||
|
||||
def _paint_link_selected(wire_tag):
|
||||
"""Paints one link's wire and knobs in the selection red."""
|
||||
canvas = app_state.canvas
|
||||
for item in canvas.find_withtag(wire_tag):
|
||||
if canvas.type(item) == "line":
|
||||
canvas.itemconfig(item, fill=LINK_SELECT_COLOR, width=LINK_SELECT_WIDTH)
|
||||
elif "link_knob_core" in canvas.gettags(item):
|
||||
pass # the white centre stays white while selected
|
||||
else:
|
||||
canvas.itemconfig(item, fill=LINK_SELECT_COLOR)
|
||||
canvas.tag_raise(wire_tag)
|
||||
|
||||
|
||||
def toggle_link(wire_tag):
|
||||
"""Ctrl+click: adds a link to the selection, or takes it back out."""
|
||||
if wire_tag in app_state.selected_link_tags:
|
||||
_restore_link(wire_tag)
|
||||
app_state.selected_link_tags.remove(wire_tag)
|
||||
app_state.selected_link_tag = (app_state.selected_link_tags[-1]
|
||||
if app_state.selected_link_tags else None)
|
||||
# A knob shared with a link still selected went back to its own colours above.
|
||||
for still_selected in app_state.selected_link_tags:
|
||||
_paint_link_selected(still_selected)
|
||||
if app_state.canvas.find_withtag("link_select_hint"):
|
||||
app_state.canvas.tag_raise("link_select_hint")
|
||||
app_state.canvas.tag_raise("link_knob")
|
||||
else:
|
||||
select_link(wire_tag, add=True)
|
||||
|
||||
|
||||
def _restore_link(wire_tag):
|
||||
"""Puts one selected link back exactly as it was drawn."""
|
||||
canvas = app_state.canvas
|
||||
canvas.delete(f"link_select_hint_{wire_tag}")
|
||||
for item, fill, outline, width in _selected_link_restore.pop(wire_tag, ()):
|
||||
try:
|
||||
if canvas.type(item) == "line":
|
||||
canvas.itemconfig(item, fill=fill, width=width)
|
||||
else:
|
||||
canvas.itemconfig(item, fill=fill, outline=outline, width=width)
|
||||
except tk.TclError:
|
||||
pass # the item went away with a repaint
|
||||
|
||||
|
||||
def deselect_link():
|
||||
"""Puts the selected link back exactly as it was drawn."""
|
||||
"""Puts every selected link back exactly as it was drawn."""
|
||||
canvas = app_state.canvas
|
||||
canvas.delete("link_select_hint")
|
||||
if app_state.selected_link_tag:
|
||||
for item, fill, outline, width in _selected_link_restore:
|
||||
try:
|
||||
if canvas.type(item) == "line":
|
||||
canvas.itemconfig(item, fill=fill, width=width)
|
||||
else:
|
||||
canvas.itemconfig(item, fill=fill, outline=outline, width=width)
|
||||
except tk.TclError:
|
||||
pass # the item went away with a repaint
|
||||
app_state.selected_link_tag = None
|
||||
for wire_tag in app_state.selected_link_tags:
|
||||
_restore_link(wire_tag)
|
||||
app_state.selected_link_tags.clear()
|
||||
app_state.selected_link_tag = None
|
||||
_selected_link_restore.clear()
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user