Wiresheet: left-drag rectangle selection, group move, Ctrl+A select all
Rectangle selection moves to the left button on bare sheet (Ctrl adds); right-click is the menu again. Dragging a selected box by its title bar moves the whole selection as one undoable step. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
+51
-33
@@ -11,9 +11,9 @@ either end. While dragging, the cursor points along the flow of the link over a
|
||||
would take it, and turns into a no-entry sign over one that would not, so a bad drop is
|
||||
visible before the button is released.
|
||||
|
||||
A right press that never moves still opens the component's context menu. A right drag
|
||||
that starts off a slot row draws a selection rectangle instead, and selects the boxes
|
||||
wholly inside it on release; with Ctrl held they join the current selection. A left press
|
||||
A right press that never moves still opens the component's context menu. A left drag
|
||||
that starts on bare sheet draws a selection rectangle, and selects the boxes wholly
|
||||
inside it on release; with Ctrl held they join the current selection. A left press
|
||||
anywhere on a box selects it, but only a press on its title bar moves it; on a slot row
|
||||
it draws a link instead, as in Workbench.
|
||||
"""
|
||||
@@ -41,7 +41,7 @@ CTRL_MASK = 0x0004
|
||||
_cursors = {} # role -> Tk cursor spec, built on first use
|
||||
_press = None # pending right press: {"hit", "x", "y", "event"}
|
||||
_drag = None # live link drag: {"hit", "anchor"}
|
||||
_marquee = None # right press off a slot: {"x", "y", "cx", "cy", "state", "active"}
|
||||
_marquee = None # left press on bare sheet: {"x", "y", "cx", "cy", "state", "active"}
|
||||
_menu_callback = None # opens the ordinary right-click menu for an event
|
||||
_select_boxes = None # makes a list of comp tags the box selection
|
||||
_link_dialog = None # opens the Link dialog: (source, target, src_slot, tgt_slot)
|
||||
@@ -434,9 +434,34 @@ def _finish(event):
|
||||
return "link"
|
||||
|
||||
|
||||
# Right button: on a slot it drags a link. Anywhere else, dragging pulls out a selection
|
||||
# rectangle that selects every box wholly inside it on release (Ctrl adds them to the
|
||||
# current selection). A press that never moves is the menu.
|
||||
# Right button: on a slot it drags a link, and a press that never moves is the menu.
|
||||
|
||||
def on_right_press(event):
|
||||
if _start_press(event) is None:
|
||||
_menu_callback(event)
|
||||
|
||||
|
||||
def on_right_motion(event):
|
||||
_drag_motion(event)
|
||||
|
||||
|
||||
def on_right_release(event):
|
||||
if _finish(event) == "click":
|
||||
_menu_callback(event)
|
||||
|
||||
|
||||
# Left button on bare sheet: dragging pulls out a selection rectangle that selects every
|
||||
# box wholly inside it on release (Ctrl adds them to the current selection).
|
||||
|
||||
def _on_bare_sheet(cx, cy):
|
||||
"""True if no box or link lies under a canvas point."""
|
||||
canvas = app_state.canvas
|
||||
for item in canvas.find_overlapping(cx - 3, cy - 3, cx + 3, cy + 3):
|
||||
tags = canvas.gettags(item)
|
||||
if "component" in tags or "link" in tags:
|
||||
return False
|
||||
return True
|
||||
|
||||
|
||||
def _marquee_motion(event):
|
||||
"""Draws the selection rectangle once the pointer has moved far enough."""
|
||||
@@ -486,30 +511,6 @@ def _marquee_finish(event):
|
||||
return True
|
||||
|
||||
|
||||
def on_right_press(event):
|
||||
global _marquee
|
||||
_marquee = None
|
||||
if _start_press(event) is None:
|
||||
canvas = app_state.canvas
|
||||
_marquee = {"x": event.x, "y": event.y, "cx": canvas.canvasx(event.x),
|
||||
"cy": canvas.canvasy(event.y), "state": event.state, "active": False}
|
||||
|
||||
|
||||
def on_right_motion(event):
|
||||
if _marquee is not None:
|
||||
_marquee_motion(event)
|
||||
else:
|
||||
_drag_motion(event)
|
||||
|
||||
|
||||
def on_right_release(event):
|
||||
if _marquee is not None:
|
||||
if not _marquee_finish(event):
|
||||
_menu_callback(event)
|
||||
elif _finish(event) == "click":
|
||||
_menu_callback(event)
|
||||
|
||||
|
||||
# Left button: anywhere on a box selects it. Only the title bar moves it; a slot row
|
||||
# drags out a link, and the rest of the box does nothing more than select.
|
||||
|
||||
@@ -519,6 +520,19 @@ def _on_title_bar(comp_tag, cy):
|
||||
|
||||
|
||||
def on_left_press(event):
|
||||
global _marquee
|
||||
_marquee = None
|
||||
canvas = app_state.canvas
|
||||
cx, cy = canvas.canvasx(event.x), canvas.canvasy(event.y)
|
||||
if _on_bare_sheet(cx, cy):
|
||||
app_state.drag_data["tag"] = None
|
||||
if not event.state & CTRL_MASK:
|
||||
# A plain click on bare sheet still clears the selection, drag or not.
|
||||
wiresheet.deselect_link()
|
||||
_select_boxes([])
|
||||
_marquee = {"x": event.x, "y": event.y, "cx": cx, "cy": cy,
|
||||
"state": event.state, "active": False}
|
||||
return
|
||||
_box_handlers["press"](event) # selection, and arms a box move
|
||||
if _start_press(event) is not None:
|
||||
app_state.canvas.delete("slot_hover")
|
||||
@@ -528,14 +542,18 @@ def on_left_press(event):
|
||||
|
||||
|
||||
def on_left_motion(event):
|
||||
if _press is not None or _drag is not None:
|
||||
if _marquee is not None:
|
||||
_marquee_motion(event)
|
||||
elif _press is not None or _drag is not None:
|
||||
_drag_motion(event)
|
||||
else:
|
||||
_box_handlers["motion"](event)
|
||||
|
||||
|
||||
def on_left_release(event):
|
||||
if _finish(event) is None:
|
||||
if _marquee is not None:
|
||||
_marquee_finish(event)
|
||||
elif _finish(event) in (None, "click"):
|
||||
_box_handlers["release"](event)
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user