Hovering a slot row highlights the half under the pointer and shows a
direction cursor. Pressing on a slot drags a rubber band; dropping on
another slot links them, dropping on a title bar opens the Link dialog
with the dragged slot preselected, and a no-entry cursor marks a slot
that would refuse the link. A right click that never moves still opens
the context menu.
The palette now leaves out types whose facets carry @palette=false, and
kits with nothing placeable left.
Also points the default device host at 192.168.1.251.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
In live mode the device is now written first and the document only takes
what the device accepted. Every live_hooks failure records a reason, and
warn_failure() shows it in a dialog and the status bar instead of failing
silently.
- Move, properties, OX page editor: rejected values are rolled back and listed
- Add/remove link: no longer edits the DOM alone when an end can't be resolved
- Add/delete component: report why the device refused
- Tidy Layout: sends each new position to the device, reverts refusals,
marks the document dirty, and pushes no undo step in live mode
- User Manager: add (one Sox add carrying cred/perm/prov), edit and delete
now go to the device
- Binary Buf slots (e.g. User.cred) are sent as Buf bytes, not as Str text
- Bump version to 0.0.0.136
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
_slot_name_by_id() now resolves SOX link slot IDs against the
inheritance-flattened final_components_registry instead of the
per-type slot_registry whose local IDs were wrong for types with
intermediate parents (e.g. RegFloat→Register→Component). This
produced incorrect link endpoints, inflated linked-slot visibility,
and different box sizes between file and live modes.
Also: tighten routing constants for denser wiring, add wiresheet
PNG print/export (Ctrl+P), sort link routing jobs by gap distance,
remove debug route logging, and fix live tree-expand re-selection.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Right-clicking a component now offers Link View alongside Properties, from
the wiresheet and from the navigation tree alike. It takes over the editor
pane the same way and answers one question -- what is wired to this
component, and where does it go.
The chosen component sits in the middle wearing the stroke a selected box
wears on the sheet, with what links into it on the left and what it links
out to on the right, so every arrow points the way the signal travels.
Pale yellow ground and no grid: nothing here can be positioned, because
the layout is derived from the links every time it is drawn and no part of
it is stored in the file. Read-only throughout -- no drag, no add, no
delete -- so a component's wiring can be read without the risk of
rearranging it.
Every line is grey, since this is not a wiresheet and a wire-blue line
would invite the reader to treat it as one. A link on the same sheet is
solid; one that crosses is dashed, keeps the grey knob that sheet paints
on the slot, and has the far component drawn in with its sheet named
beneath it. A reference the document cannot resolve gets a placeholder
naming the path, because a link the view silently dropped would be the one
thing a reader could not find out from here.
Clicking a wire or a component follows the link: it opens the sheet of the
end that is not the component the view is about, with the link selected in
red. A link that stays on one sheet therefore goes back to that sheet
where both ends are drawn, and one that crosses opens the other sheet --
the end the view could only show as a knob.
Supporting changes:
- draw_component_box is factored out of render_components, so the sheet
and this view paint a component with the same code and a box cannot read
differently between them. draw_knob takes its canvas for the same
reason.
- The editor pane's hand-over is now shared: _take_editor_pane,
_give_editor_pane_back and close_editor_panel replace the
Properties-only versions, so "you have not saved that" is still asked
once, in one place, whichever panel has the pane.
- Fixes the jump to a link's other sheet, which arrived with the link not
selected. An after_idle callback is not late enough -- ttk dispatches
its own selection event later than one of those, so the repaint wiped
the selection. The link is left in _pending_link_selection for
on_tree_select to honour once it has painted.
- Each gap is sized to hold a lane per wire crossing it, and lanes are
handed out nearest-target-first, so a fan of a dozen links nests instead
of crowding a dozen verticals into a 30px band.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Fits the whole painted sheet in the visible canvas and scrolls it into view,
from the View menu, Ctrl/Cmd+9, or the four-corners button after the zoom
percentage. The ladder gains 25% and 33% at the bottom, so a wide sheet has
somewhere to fit into.
Fit is the one scale that is not on the ladder -- a sheet fits at whatever
scale it fits at -- so zoom_step now takes the first level above or below the
scale in force rather than the neighbour of the nearest rung.
The sheet is measured from item coordinates rather than canvas.bbox(), which
is inflated by the outline stroke: a stroke is the same two pixels at every
zoom, so a bbox divided back to 1:1 reports a slightly smaller sheet the
further in it is zoomed, and fitting an already fitted sheet crept from 288%
to 291% instead of standing still. Anything painted left of or above the
canvas origin is measured from the origin, since no amount of scrolling brings
it into view.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
A ladder of scales from 50% to 300%, stepped by Zoom In / Zoom Out / Zoom 100%,
by the two buttons beside the navigation arrows, and by Ctrl and the wheel,
which holds the point under the pointer still. A menu or keyboard zoom holds
the middle of the view instead, so it closes in on what is already being
looked at.
Painting and routing stay at 1:1, because that is where every metric is tuned:
box header and row heights, wire stubs, lane gaps, standoffs, knob radii. Zoom
scales the finished picture, so a zoomed sheet keeps the proportions of a 1:1
one and the router reaches the same decisions at every scale. Text comes along
because the three box fonts are resized once the boxes have been measured with
them.
redraw_links replaces the direct draw_links calls a drag or a drop makes: the
router reads box positions off the canvas, so the boxes go back to 1:1 for the
routing pass and the result is scaled again. Canvas coordinates carry the zoom,
which is why the drag, release and drop handlers now snap against
meta_scale * zoom -- a box dragged the same distance across the screen lands on
the same meta step at 50%, 100% and 200%.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Pushed into the wire-coloured half, the centre filled almost all of it: that
half is only KNOB_RADIUS wide and the centre is KNOB_CORE_RADIUS, so at the
real 8px knob size the wire colour was reduced to a sliver and the marker read
as plain grey. Centred, both halves keep enough colour to tell apart.
Found on a slot carrying two links on its own sheet plus one leaving it, which
is the only arrangement that produces this knob and did not occur in testSax
until now.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Layout rules for tidy and for dragging:
- Boxes snap to whole meta steps live while dragged, not only on release.
- The left-most column and top row clear the canvas edge by at least 30px,
and neighbours by at least 30px, each rounded up to the next step.
- Box widths round up to the grid so a right edge lands on a grid line.
- Column gaps widen only where wires need lanes, so most stay at exactly 30px.
- A sheet too wide for meta's 0..255 range is laid out at 2, then 3, then 4
grid squares per step. The multiplier is derived from the sheet's contents,
so painting and tidying agree on it without recording anything in the file.
The grid size in Preferences is untouched.
Wire routing:
- No wire may pass under a component. A link with no clear route is shown as
knobs on both slots instead of a line hidden behind a box.
- Vertical runs hug a box within 15px, never closer than 10px, and two runs
sharing a gap stand 10px apart.
- Horizontal runs of different links stay 5px apart. Runs from one output pin
may share, since a fan-out is one signal.
- Straight routes claim their rows first, as their segments are pinned to
their slots and cannot move later.
Knobs:
- Wire colour with a small white centre when the far end is on this sheet,
grey when it is on another, half and half when a slot carries both.
- Selectable and deletable like a wire, and raised above the boxes so a click
reaches them.
- Selecting a same-sheet pair draws a red dashed line between the two knobs.
Also:
- get_box_bounds returns the rectangle actually drawn rather than canvas.bbox,
which was inflated by the outline stroke and by selection.
- Preferences offers to round the box width to a multiple of the grid.
- The tidy coordinate-limit warning said to lower the grid size; raising it is
what helps, since the reach is 255 * grid size.
- Tidy Layout moves from its own menu into Edit.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
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>