Combine the Edit menu (Undo, Redo, Select All) and restore the whole
part selection by index after an Undo or Redo, now that the canvas
selects several parts.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The plate view routes left and right clicks to the shared Select tool,
draws the selection, the blue/green selection window and selected
cut-offs as WinForms does, pans with a middle drag and handles Escape.
Edit > Select All (Ctrl+A) is added, and the status bar shows the tool
and the selection's bounds.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
PlateToolManager keeps one active tool with the WinForms action rules
(Escape cancels, then returns to Select, then resumes the ended tool) and
status text. SelectTool selects by click, Ctrl+click and window
(contains/intersect), takes common-line groups together and picks
cut-offs by their strokes. PlateHitTester hit-tests the shared display
geometry; PlateSelection reads and sets by part index.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
File > Export Plate... and Export All Plates... write the shown plate (each
plate in turn, shown while its file is chosen; cancel or a failure stops
the rest) as DXF, the view's image, the placement list or SVG, chosen by
the picked file's extension, under the WinForms suggested names. The image
is the plate canvas drawn by its Skia painter at the screen's density, PNG
or JPEG. Plate > View in CAD writes <nest>-P<n>.dxf to the temp folder and
opens it in the system's CAD program. File > Nest Report... writes the PDF
to a private temp folder and opens it in the system's PDF viewer, which
saves and prints it (older viewed reports are removed); File > Export Nest
Report... saves it to a chosen file. Reports refuse while Auto Nest runs on
the nest and are written off the UI thread from a detached snapshot.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
ExternalFileLauncher.OpenAsync waits for xdg-open or open without blocking
and explains a failed exit code (no program set up for the file type, file
not found), which the shell-less platforms otherwise swallow. File > Export
no longer takes .bmp as an image: no cross-platform encoder writes it, so
the image formats are .png, .jpg and .jpeg.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Edit > Undo/Redo name the next step and follow the active tab's history;
Ctrl+Z, Ctrl+Y and Ctrl+Shift+Z undo the nest unless a text box has focus.
A restore keeps the plate, zoom, pan and selection. Auto Nest's commit is
one undo step and blocks Undo on its nest while it runs. DEBUG builds warn
about edits made outside a change scope.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Move the toolkit-neutral parts of File > Export/Export All, Plate > View
in CAD and the nest report commands into OpenNest.Desktop: export formats
and suggested per-plate file names (now free of characters any platform
refuses), the placement list, DXF/SVG writing with the view image left to
the front end, opening a file in its associated program on Windows, macOS
and Linux, the report file name check, capture with catalog density, the
machine's thickness name and saved cut-time settings, and viewed-report
temp folders. WinForms calls the shared code; its behaviour is unchanged.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
NestTab starts a NestUndoRecorder once the trailing empty plate is in
place, so opening is not an edit. Modified now follows the history's save
point and unscoped edits (undoing back to the saved state clears it), and
SaveAs records an unscoped edit before marking the save point.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Auto-size factor, colour scheme, cut planning effort, clone push
placement, new nest on startup and the fill strategy grid save to the
user settings both apps share and apply at once (open nests take the new
scheme's colours); the saved fill strategies apply at startup. Set /
Change Server writes storage.json keeping the storage mode, and the next
server request uses it; Save Feed URL and Include development builds
save for the updater. MaterialLedger stays in the WinForms app: its API
key is DPAPI-protected.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The pair search slid part 2 in from offsets on a 0.25 step grid, so a pair
that locks in a corner (two interlocking channels) stopped up to a step short
of the tightest fit. Each resting position is now also slid sideways, both
ways, and the new resting positions join the candidates.
Co-Authored-By: Claude Fable 5.2 <noreply@anthropic.com>
Scopes, the fingerprint safety net, Undo/Redo stepping, the unsaved check,
identity carry-over and the Edit menu labels move from EditNestForm to
OpenNest.Desktop. The WinForms window keeps only its rebinding swap-in and
its guards; behavior is unchanged.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
DesktopOptions reads and writes the Tools > Options values under the
WinForms user-setting names, with the clone placement choices, the fill
strategy grid rows and DisabledStrategies parsing/applying, and the
server URL and update feed URL validation and messages.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Move the File > New rules into OpenNest.Desktop (NewNestSource): nest
defaults, the default machine with its clamps and support grid, Made By
and the year's next name, from the nest server in Database mode and the
counter both apps keep in user-settings.json otherwise. The WinForms
factory now delegates to it.
The Avalonia app opens a new nest in a tab with no file (NestTabs.Add),
off the UI thread and one at a time, and its nest view keeps an empty
last plate as the WinForms nest window does, so a new nest shows Plate 1.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The coarse bounding-box pass only stopped at obstacles whose box lay in
the push path, so a copy could drop past a neighbor beside the path and
end inside its spacing. A box push now also stops at an obstacle nearer
than the spacing to the side of the path.
A push ignores a part the copy starts on, so a settle could slide out of
that part and stop clear of it yet inside its spacing. SettlePlacement
now prefers a push order that keeps the part spacing, and a named order
that ends too close falls back to the other order.
Co-Authored-By: Claude Fable 5.2 <noreply@anthropic.com>
The formatter rewrote ExecuteSqlRaw to ExecuteSql, which passes the
column name and type as parameters; SQLite rejects that and the bare
catch hid it, so older databases never gained their missing columns.
Co-Authored-By: Claude Fable 5.2 <noreply@anthropic.com>
Moves whole members verbatim into Plate.CommonLines.cs, Plate.Clamps.cs, Plate.CutOffs.cs, Plate.Transforms.cs and Plate.Sizing.cs. No behavior or API change.
Co-Authored-By: Claude Fable 5.2 <noreply@anthropic.com>
Drawing.PartColors (a public array aliasing the active scheme's), Drawing.UseGoldenAngleColors and a non-atomic colour counter were process-global display state. PartPalette now holds a copy of the colours and the golden-angle flag; PartColorPalette.Current/Use swap it as a whole, Drawing.GetPartColor/GetNextColor read it, and the counter increments atomically. Colours shown are unchanged.
Co-Authored-By: Claude Fable 5.2 <noreply@anthropic.com>
Area and the canonical angle were refreshed together only by the Program setter; an in-place program edit needed two separate calls, and UpdateArea kept a stale Area when no material was left. ProgramChanged is now the single entry point (the setter calls it), a program with no material or a null program gives Area 0, and UpdateArea/RecomputeCanonicalAngle are private.
Co-Authored-By: Claude Fable 5.2 <noreply@anthropic.com>
Move ContourSampler to OpenNest.CNC and DrawingAligner with its
AlignmentResult types to OpenNest.Converters: they were the only Geometry
files importing CNC and Converters. Their tests move with them.
CoreLayeringTests scans the Math and Geometry sources against the type
names reflection finds in Core, so neither can name a higher layer again.
Geometry keeps six root-namespace types on an explicit allowlist, and the
files declaring them may reference only Math and Geometry.
Co-Authored-By: Claude Fable 5.2 <noreply@anthropic.com>
Its last callers were four strategy tests; they now use
PartOverlapChecker.FindOverlappingPairs, which also reports
contained and stacked parts.
Co-Authored-By: Claude Fable 5.2 <noreply@anthropic.com>
The console overlap check and the MCP check_overlaps tool counted
crossing points, so a part contained in or stacked on another reported
no overlap. Both now list pairs from PartOverlapChecker.FindOverlappingPairs,
which uses the Intersects verdict and skips cut-off parts.
Plate.HasOverlappingParts stays for now: two test files outside this
change still call it.
Co-Authored-By: Claude Fable 5.2 <noreply@anthropic.com>
BuildPartPerimeter swallowed every exception. It now guards a missing
program and an outline that forms no shape, and catches only geometry
failures; a null perimeter still makes a cut-off exclude the part's whole
bounding-box span.
Co-Authored-By: Claude Fable 5.2 <noreply@anthropic.com>
Part.CloneAtOffset hands the copy the source's Program instance. The copy
cloned before rotating, but the source still owned the program, so rotating
the source turned the program under every tiled copy while their location
and bounds stayed put.
Program now carries a sticky SharedByParts flag that CloneAtOffset sets, and
a part copies its program before rotating when it does not own it or the
program is shared. The flag lives on the program rather than the part so a
restored cutting state, which reinstates ownership field for field, cannot
re-alias a shared program. Unrotated copies keep sharing one instance, which
the fill and overlap caches key on.
Update, ApplyLeadIns and ApplySingleLeadIn install a fresh program and now
own it, saving a needless copy on the next rotate.
Co-Authored-By: Claude Fable 5.2 <noreply@anthropic.com>
Nothing called MoveTo on a geometry entity or the OffsetEntity(distance,
point) overload. Shape and Arc threw NotImplementedException for them, and
the Line and Polygon versions were wrong and untested. Remove the abstract
declarations and every override; the OffsetSide overload stays.
Co-Authored-By: Claude Fable 5.2 <noreply@anthropic.com>
Nest Info filled a blank Made By with the current user every time it
opened, so pressing OK on an existing nest's info (from a tab or Saved
Nests) signed someone else's nest. The author is now stamped once when a
nest is made (File > New, drawing set Make Nests, BOM import), and Nest
Info shows the stored value as is, leaving a blank one blank.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
v0.8.0 documents the drawing library's Filter dialog and its Size and Holes
columns (b9fc618a), with recaptured library screenshots and a new
library-filter topic. The zip's SHA-256 was checked against the release's
published hash.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
On an enclosed machine a cutout slug that tips once cut free can stand up
above the sheet and catch the enclosure door when the pallet changes. The
head already keeps off cut cutouts, so this is about clearing the door, not
the head.
Cutting Settings > Cutouts > "Slice slugs the support grid can't hold
level" (CuttingParameters.SliceTippingSlugs, off by default, saved per
machine thickness and written only when on) makes Plan Cutting cut each
such slug along the bed's contact lines (grid rows and columns, slat center
lines) before the cutout, so no piece keeps a contact and the pieces drop
between the supports. Each slice stops a kerf short of the cutout, so the
pieces stay attached until the cutout's own kerf frees them together. A
slug the bed holds level, or one on no contact, is left whole; a cutout
holding another part or another of its part's cuts is never sliced.
Slices are break cuts emitted right after the drawing's own break cuts,
pierced on themselves and led straight back to their start. The
released-contour proof now leaves out straight break cuts lying wholly
inside one of the part's closed holes, since the grid cells they free are
scrap; break cuts in material still take part. The plan fingerprint only
changes when the setting is on.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Finding a part on the nest server meant scrolling 40k drawings: the library
could only match an exact thickness or customer and knew nothing about a
drawing's size or holes. The library browser gets a Filter dialog with
inclusive ranges, and the query API takes them.
The server never parses packages and stays off IO, so the server worker now
measures each package beside its nest jobs (bounding sides, net area, closed
cutouts inside the outline) and stores the summary keyed by package hash
(schema v19). Identical geometry is measured once, an unreadable package is
recorded once instead of retried forever, and size or hole limits match only
measured drawings. Thickness ranges compare in inches across units and keep
the library's rule that a drawing saved without a thickness suits any.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The guides now use the regrouped File menu labels from ecd0bba4 and show a
recaptured File menu. The release also carries the earlier unreleased guide
updates for part printouts, plate list delete/duplicate and clone push
placement, all of which are on master.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
ecd0bba4 removed File > Export Nest Report..., so its cancel test went
away and three report tests were renamed for the viewer path. The Windows
acceptance manifest still required the old names and failed with "expected
at least 1 cases, found 0" although every test passed. List the current
names, and add the two viewer tests now that the viewer is the only way to
get the PDF.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The File menu ran six output commands together with no separators, and
"Export" / "Export All" didn't say what they exported. Group them by what
they produce:
- Save Copy as .nest File... (was Export .nest...) moves next to Save As,
since it writes the nest file rather than exporting a plate.
- Export Plate... / Export All Plates... (were Export / Export All) get their
own group and the "..." their save dialogs call for.
- Nest Report... / Part Printouts... (were View ...) form a reports group.
- Storage Mode... gets its own separator above Exit.
Export Nest Report... is removed: the report viewer already has Save As
(available even without WebView2), so it was a second path to the same PDF.
Its guard and failure tests now drive the viewer path, and the atomic-write
test calls WriteNestReport directly. The Avalonia prototype's matching
command is renamed too.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
A part printout showed the part but not its size on the drawing, so the
operator had to read the table to know which way was which. Each page now
draws the overall X extent below the part and the Y extent to its right,
as the Shape Library does: arrows, a boxed label and extension lines that
stop 6 pt short of the outline itself rather than its bounding box.
Each dimension line moves out far enough to keep its label 14 pt clear of
the part (a wide label centered on an 18 pt line nearly touched it), and
the part and its dimensions sit 28 pt inside the drawing border, double
the old padding.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The nest report already leads its thickness with the machine config's
Name / Gauge; the part printout's THICKNESS cell now does the same
(16 ga - 0.0598"), from the same lookup in the desktop.
Thickness names are typed into the machine config, so both writers now check
them against the bundled font's Latin-1 limit like other free text, instead
of failing partway through rendering.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Thicknesses saved before the auto-fill kept a blank Name / Gauge until someone
edited their value, so their nest reports showed only the decimal. Opening
Machine Configuration now names every blank thickness that matches a standard
gauge or plate fraction and marks the form changed, so closing offers to save
them. Thicknesses matching none stay blank, and once saved a reopen finds
nothing to fill and does not ask again.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Reports now take a thickness's name from the machine config, so a blank
Name / Gauge leaves the report with just the decimal. Machine Configuration
now fills a blank name from the standard steel gauge or plate fraction table
when the thickness value changes, and keeps following the value while the
name is still the old value's standard one; a typed name is never replaced.
A new thickness starts named for its default 0.25 (1/4").
Existing blank names are not filled on open, so viewing a machine never marks
it dirty; editing the value fills them.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Each machine thickness already has a Name / Gauge field the shop fills in, so
the report now shows that name instead of guessing one from the standard
gauge table. It is matched the way the machine cutting defaults match the
nest's material, grade and thickness; a thickness without a name shows just
the decimal.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Every size, thickness and weight on the report already carries its own unit,
so the summary's Units row only repeated them and took a header line from the
part cards. The plate pages' ruler note still names the units, since ruler
numbers are bare.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The generated date sat among the summary's report details and printed a UTC
offset nobody on the shop floor reads. It now goes in every page's footer,
left of "Page X of Y", in the computer's own time zone without the offset.
The thickness now leads with its gauge or plate fraction ("16 ga - 0.0598 in")
when it matches one, as the thickness box lists it. Reporting references Core
only, so the desktop looks the name up in StandardThicknesses and passes it on
the snapshot.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Shops used CutSend to get a part printout (the part drawn to fit a Letter
page over a details table) because OpenNest had no way to make one. File >
View Part Printouts prints every part drawing of the nest, and the drawing
list's View Part Printout prints one; both open the report viewer to save
or print.
Cut length and pierce count walk the program as it is cut, so etch marks,
tab spans and display-only moves add neither, a tabbed cutout counts one
pierce per piece, and breakoff and common-line cuts count. The drawing list
item reaches the main window directly so nests made by BOM import get it
too. Rendering shares the nest report's lock, fonts and Latin-1 limit.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Write PlateViewDrawRapid/PlateViewDrawBounds only when changed from the default
or already saved, as the WinForms settings provider does, so a later default
change still applies. Give the render thread a copy of a broken common-line
part's box, and prune the label-point cache with the part paths.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>