Add link management: create, select, delete with undo/redo
Implement full link workflow between component slots on the wiresheet: - Link Mark / Link From / Link To context menu items for creating links - Link dialog with slot type validation and source/target swap button - Selectable link wires (click to highlight in red) with right-click delete - Undo/redo support for both add and delete link operations - Component deletion already cascades to remove related links Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
+33
-3
@@ -180,10 +180,16 @@ def draw_knob(x, y):
|
||||
)
|
||||
|
||||
|
||||
LINK_SELECT_COLOR = "#e00000"
|
||||
LINK_SELECT_WIDTH = 2
|
||||
|
||||
|
||||
def draw_links():
|
||||
"""Paints wires between slots on this sheet and knobs for links leaving it."""
|
||||
canvas = app_state.canvas
|
||||
canvas.delete("link")
|
||||
app_state.canvas_link_map.clear()
|
||||
app_state.selected_link_tag = None
|
||||
if app_state.xml_root_element is None:
|
||||
return
|
||||
|
||||
@@ -200,6 +206,7 @@ def draw_links():
|
||||
|
||||
boxes = [b for b in (get_box_bounds(t) for t in path_to_tag.values()) if b]
|
||||
|
||||
link_index = 0
|
||||
for link in links_elem.findall("link"):
|
||||
from_ref = link.get("from", "")
|
||||
to_ref = link.get("to", "")
|
||||
@@ -218,19 +225,21 @@ def draw_links():
|
||||
if src_box is None or dst_box is None:
|
||||
continue
|
||||
|
||||
wire_tag = f"link_wire_{link_index}"
|
||||
link_index += 1
|
||||
app_state.canvas_link_map[wire_tag] = link
|
||||
|
||||
points = route_link_path(src_box, src_y, dst_box, dst_y, boxes)
|
||||
flat = [coord for point in points for coord in point]
|
||||
canvas.create_line(
|
||||
*flat, fill=LINK_COLOR, width=1,
|
||||
arrow=tk.LAST, arrowshape=(8, 9, 3), tags=("link",)
|
||||
arrow=tk.LAST, arrowshape=(8, 9, 3), tags=("link", wire_tag)
|
||||
)
|
||||
elif src_tag:
|
||||
# Source is here, target is on another sheet.
|
||||
src_box, src_y = resolve_slot_anchor(src_tag, from_slot)
|
||||
if src_box is not None:
|
||||
draw_knob(src_box[2] + KNOB_RADIUS, src_y)
|
||||
elif dst_tag:
|
||||
# Target is here, source is on another sheet.
|
||||
dst_box, dst_y = resolve_slot_anchor(dst_tag, to_slot)
|
||||
if dst_box is not None:
|
||||
draw_knob(dst_box[0] - KNOB_RADIUS, dst_y)
|
||||
@@ -240,6 +249,27 @@ def draw_links():
|
||||
canvas.tag_lower("link", "component")
|
||||
|
||||
|
||||
def select_link(wire_tag):
|
||||
"""Highlights a link wire in red."""
|
||||
canvas = app_state.canvas
|
||||
deselect_link()
|
||||
if wire_tag and wire_tag in app_state.canvas_link_map:
|
||||
canvas.itemconfig(wire_tag, fill=LINK_SELECT_COLOR, width=LINK_SELECT_WIDTH)
|
||||
canvas.tag_raise(wire_tag)
|
||||
app_state.selected_link_tag = wire_tag
|
||||
|
||||
|
||||
def deselect_link():
|
||||
"""Resets the selected link wire back to its default colour."""
|
||||
canvas = app_state.canvas
|
||||
if app_state.selected_link_tag:
|
||||
try:
|
||||
canvas.itemconfig(app_state.selected_link_tag, fill=LINK_COLOR, width=1)
|
||||
except tk.TclError:
|
||||
pass
|
||||
app_state.selected_link_tag = None
|
||||
|
||||
|
||||
# --- Component painting ---
|
||||
|
||||
def render_components(components_to_render):
|
||||
|
||||
Reference in New Issue
Block a user