* Menu items open their missing dialogs; COUNT shows its result; New Layout asks for a name (#126)
Eight menu items ran their JSON form with no parameters and changed nothing.
Typed or chosen from a menu they now do what the menu promises; JSON calls
still run the command and never open a dialog.
- New crates/ui-egui/src/managers.rs: Linetype Manager (load from the
library, set current, global scale, pattern preview), Point Style
(PDMODE tiles drawn in code, size relative/absolute), Table Style and
Multileader Style (list, set current, new, edit properties), Page Setup
Manager (per layout: paper, orientation, plot area, fit/scale, center,
lineweights) and Constraint Settings (infer, bars, transparency, dynamic
constraints, AutoConstrain types and tolerances). All changes go through
their commands (app.run), so they are undoable and scriptable.
- menus::run_ui_command routes LINETYPE/LT, DDPTYPE, TABLESTYLE/TS,
MLEADERSTYLE/MLS, PAGESETUP and CONSTRAINTSETTINGS/CSETTINGS without
parameters to the dialogs; dialogs::show dispatches them.
- COUNT returns a `message` (per-block counts and total) that the command
line shows; Session::start echoes multi-line messages line by line.
- LAYOUT.NEW from the menu or command line prompts
"Enter name of new layout <LayoutN>:"; Enter takes the default, a taken
or invalid name is reported and asked again.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
* Move COUNT test away from other PRs' hunks to avoid merge conflicts
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
---------
Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
* Properties palette: every control acts or is visibly unavailable (#6)
Several Properties palette controls looked clickable but did nothing: most
current-property rows with nothing selected (linetype, lineweight, thickness,
text/dimension/multileader/table style), the selection-type drop-down, a
circle's circumference and area, a line's length and angle, a dimension's
style, and the All/My switch.
- Nothing selected: Linetype runs `linetype {current}`, Lineweight `lweight`,
Thickness `setvar THICKNESS`, the style rows `style.current`,
`dimstyle.current`, `mleaderstyle` and `tablestyle`. Transparency,
Annotation scale and Plot style(s) have no command yet: greyed with a
"Not available yet" tooltip.
- Header: the type drop-down narrows the selection to one object type
(`select {handles}`), plus Toggle PICKADD (`setvar PICKADD`), Select Objects
(`select`) and Quick Select buttons, with icons drawn in code.
- Geometry: circle circumference/area, line length/angle and dimension style
are editable through `properties.set` (new keys `circumference`, `area`,
`dimStyle`); computed values (line deltas, polyline length/area, block
name) are greyed read-only.
- PICKADD now changes clicking with no command running: off, each pick
replaces the selection and Shift adds.
- Palette text fields keep typed text while the window itself is unfocused
(they read focus from egui memory, not `Response::has_focus`).
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
* Move palette tests away from other PRs' hunks to avoid merge conflicts
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
---------
Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
Edit > Cut / Copy / Copy with Base Point, View > Zoom > Object, Dimension >
Update, Tools > Draw Order > Bring to Front / Send to Back and the Format >
Layer Tools LAYCUR, LAYFRZ, LAYOFF, LAYLCK and LAYULK did nothing when started
from a menu, toolbar or the command line with nothing selected.
- machines::SelectRun: "Select objects:", then run the command's JSON body on
the picked handles. With a pickfirst selection it runs at once, as before.
It replaces the DIMREASSOCIATE/DIMDISASSOCIATE SelectThen in annotate.rs and
calls the command body directly, so the command records one undo step.
- LAYFRZ/LAYOFF/LAYLCK/LAYULK pick one object ("Select an object on the layer
to be frozen" etc.).
- COPYBASE asks for the base point first, then for objects (skipped with a
pickfirst selection).
- Objects picked at the prompt are deselected afterwards.
- JSON/programmatic calls are unchanged and never prompt.
Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
TAN and PER snaps need the other end of the line, so the first point of a
LINE (no base point yet) could never snap tangent: a belt line tangent to
two circles was impossible to draw.
Now, as in AutoCAD, a point prompt can accept *deferred* snaps:
- snap: with no base and the new `deferred` flag, osnap offers "Deferred
Tangent" (circles, arcs) and "Deferred Perpendicular" (circles, arcs,
lines, xlines, rays) where no other snap wins. The hit carries the curve
(`SnapHit::deferred`, `Deferred`, `SnapCurve`).
- `resolve_deferred` solves the line once the other end is known: tangent
or perpendicular from a point, tangent-to-tangent (common tangents of two
circles, new `Circle::common_tangents` in geom) and the perpendicular
mixes. Among several solutions the one nearest the picks wins. No
solution (point inside the circle, concentric or nested circles,
non-finite input) is `None`, never a panic.
- prompt: `Prompt::deferred()` opts a prompt in; `Input::Deferred` reaches
only such prompts, everywhere else the session turns it into the point it
was picked at, so other commands snap as before.
- LINE opts in for its first point (and the next one while the first is
still deferred). No solution reports and re-prompts; Undo drops the
deferred point. The rubber band shows the resolved line, also the
tangent-to-tangent one while hovering the second curve
(`Session::cursor_deferred`, set by the canvas).
- canvas: passes the prompt's flag to osnap and sends a deferred pick as
`Input::Deferred`.
Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
Point picks found the outer boundary by tracing the planar graph of all
curves, but islands only came from single closed objects (circles, closed
polylines, full ellipses, closed splines). A square drawn as four LINEs
inside a rectangle was ignored: HATCH drew through it, GRADIENT filled it
and BOUNDARY created only the outer polyline.
- geom::region::boundary_at returns the outer loop plus islands: every
connected group of curves inside the face that doesn't touch its
boundary and doesn't surround the pick point. Each island is the
outline of the group's outside, traced with the same sharpest-turn
walk from its leftmost vertex after dangling ends are pruned. Islands
report which input curves they came from. Traces are bounded by the
group's edge count and islands are capped at MAX_ISLANDS.
- loops_at (shared by HATCH, GRADIENT and BOUNDARY) adds those islands
when every curve in the group is an open LINE, ARC, elliptical arc,
open polyline or open spline. Groups containing a closed object keep
the existing per-object islands, so closed-polyline and circle islands
are unchanged (bulges kept).
- Tests: geom region tests for separate-line islands, dangling ends,
open and attached curves, nesting and hostile input; engine tests for
HATCH (rendered pattern stays out of the hole), GRADIENT (375 filled,
hole clear) and BOUNDARY (two polylines) with four-line and
closed-polyline islands.
Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
* Programmatic undo/redo ends a running command first (#177)
`undo` or `redo` run through engine.execute, MCP, the control channel or a
script while an interactive command was still running (e.g. TEXT waiting for
another line) swapped the drawing under that command. Interactive commands
push their undo step only when they end, so `undo` popped the previous
command's step instead: it removed the earlier geometry, dropped the running
command's entities, and left the command running from a stale state.
Both commands now first end the running command the way Esc does, exactly as
Session::start already does for Cmd+Z, the menu and the command line. The
command's work so far becomes one undo step, and `undo` then removes that step.
Regression test: programmatic_undo_during_a_command_ends_it_first.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
* Move test away from other PRs' hunks to avoid merge conflicts
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
---------
Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
properties.set documented `transparency` but never read it, nothing reported it,
and DXF dropped group 440. Fixes#132.
- properties.set takes "ByLayer", "ByBlock" or a percentage 0..90 (a number or
"50"/"50%"); anything else (out of range, NaN, junk) is an error and leaves
the selection unchanged.
- properties and drawing.inspect / drawing.entities report it in the same form.
- Properties palette: the Transparency row is a menu (ByLayer, ByBlock, a
0..90 percentage) that acts through properties.set.
- DXF: entities write 440 unless ByLayer (ByBlock 0x01000000, a percentage its
alpha | 0x02000000, the alpha mapping layers use); the reader parses it back,
any other value reads as ByLayer.
Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
- Layer Properties Manager: filter tree (All / All Used Layers) with search, sortable table
(Status, Name, On, Freeze, Lock, Plot, Color, Linetype, Lineweight, Transparency,
New VP Freeze, Description; VP Freeze / VP Color inside an MSPACE viewport), inline
rename and description, ACI + true-colour picker, linetype picker with Load from the
library, lineweight picker, layer states save/restore/delete.
- Engine: qselect rewritten ({type, property, operator =,!=,>,<,*, value, mode new|append|
exclude, applyTo}) + qselect.info; layerstate.list/delete/rename; layer list reports
used layers and states; Layer.vp_freeze_new (DXF flag 2, applied by MVIEW) and
layer.set newVpFreeze; per-viewport layer colours (Viewport.layer_colors, vplayer
colors, honoured by the renderer); vplayer defaults to the active viewport; QPMODE
setting/sysvar/toggle; properties.set length/angle for lines.
- Canvas: constraint bars with code-drawn glyphs and coincident markers, dynamic
dimensional constraints (aligned/horizontal/vertical/radius/diameter/angular) with
name=value labels and lock icon, honouring CONSTRAINTBAR/DCDISPLAY; cached per
drawing revision; double-click a label to edit its expression (parameters).
- Quick Properties palette near the selection (status-bar toggle), Quick Select dialog,
Parameters Manager (edit, add user parameter, delete).
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
A pick after one edit at 200k entities drops from ~110 ms (full rebuild) to ~4 ms;
steady-state picks stay at ~1 us. Adds a parity test against fresh builds and a
perf row for the incremental path.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Annotation (M4):
- TrueType text from system fonts (filled/outlined), shared placement for all text
- MTEXT formatting codes: fonts, heights, colours, under/overline, stacks, wrapping
- Full DIMSTYLE variables, per-dimension overrides, all arrowheads and ticks,
unit formats, tolerances, limits, alternate units, colours by role
- Associative dimensions that follow geometry; DIMREASSOCIATE/DIMDISASSOCIATE
- STYLE/DIMSTYLE management commands, DIMTEDIT, DIMSPACE, TABLE create/edit/merge
Parametric (M9):
- New cadcraft-constraints crate: weighted damped Gauss-Newton solver, conflict
and redundancy detection, expressions, AutoConstrain inference
- All GC*/DC* commands, GEOMCONSTRAINT/DIMCONSTRAINT, PARAMETERS, DELCONSTRAINT,
constraint bar / display settings; re-solve after every edit
Also: MODEL/PAPER status bar toggle, cargo xtask alias, roadmap update
(233/491 menu items, 290 commands).
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Double-click a viewport (or MS) to edit model space inside it; the screen view maps
consistently so picks, snaps, grips and previews work in model units, and zoom/pan
change the viewport's view (or the sheet when the viewport is locked). PS or a
double-click outside returns to paper space.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
DIMLINEAR/ALIGNED/RADIUS/DIAMETER/ANGULAR/ARC/ORDINATE/CONTINUE/BASELINE, QDIM, MLEADER, LEADER;
HATCH/GRADIENT/BOUNDARY/REGION with pick-point boundary tracing (planar face walk with islands);
BLOCK/INSERT/ATTDEF/ATTEDIT/WBLOCK/PURGE/BATTMAN; dimension text gaps and horizontal text;
DXF header writer whitelist (correct group codes).
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>