- block-def strings in every locale (English until translated); the
catalog test requires each locale to carry them.
- A new block's base point starts at 0, and ATTMAN / BATTMAN report a
drawing without attributed blocks; the tests expect that now.
- Lines over 100 columns wrapped.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
-BLOCK, -WBLOCK, -BEDIT, ATTSYNC, BASE and INSBASE follow the reference
prompts and messages; empty blocks; WBLOCK keeps object coordinates and
stores INSBASE; annotative and hyperlink data on the block record; block
preview images; remembered dialog choices; block aliases.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
ARRAYEDIT picks an associative array (or takes the preselected one) and
its Source option opens the objects every item repeats in the Block
Editor; saving there updates all items at once. Counts and spacings stay
in Properties.
Refs #1109
Co-Authored-By: Claude Opus 5.5 <[email protected]>
PASTESPEC offers the formats on the clipboard: Objects and Block for
objects copied in the application (the PASTECLIP and PASTEBLOCK paths),
and Text for the system clipboard's text, placed as multi-line text in
the current text style with its lines as paragraphs.
Refs #645
Co-Authored-By: Claude Opus 5.5 <[email protected]>
The pasted block is defined around the clipboard base, so its origin
is already that point, but the insertion still subtracted the base and
landed the block offset from the pick. The base now only positions the
world-space preview, and it stays f64.
Fixes#1731
Co-Authored-By: Claude Opus 5.5 <[email protected]>
The last four big web-vs-desktop gaps.
XREFs: XATTACH reads the picked drawing's bytes and registers them
name-keyed (the image/PDF-underlay pattern), pre-parses on the web
worker, and the commit merge produces the same xref block flow as
native. Opened drawings resolve xrefs from the registry (trailing-name
match) before cache build; unresolved references produce ONE warning
listing the names and the fix — drop the referenced files on the page
(drops and picker opens now register their bytes) and reopen or
XRELOAD. XRELOAD works off the registry on unsaved drawings too.
Data Link & Extraction: spreadsheet links read picked xlsx/csv bytes
(calamine from slices / CSV from string) through a session registry,
so preview, refresh, and table-insert work on web; extraction takes
external drawings via a multi-file picker parsed on the worker, and
outputs CSV/TXT/.dxex via download_bytes. The disabled 'Add folder'
button explains why.
ARCHIVE/ETRANSMIT: assembles the drawing plus registered images, PDF
underlays, and session plot tables into a ZIP delivered as
{stem}_transmit.zip; skipped dependencies are reported by name.
Save/autosave off the UI thread: the parse worker gains a serialize
action (protocol v5) — the document is prepared once on the main
thread (clone, styles, dimension bake), then the DWG/DXF writer pass,
the dominant cost, runs on the worker; any worker failure falls back
to inline serialization with the identical shared implementation.
The save path also clears the dirty flag only when the tab didn't
change mid-write, and the runtime-fields sidecar now carries
graphic_data, fixing a pre-existing loss of raw DWG round-trip bytes
on web-opened documents.
(cherry picked from commit 2e100634)
Ported onto main (#1717 review): the new ocs_save crate builds on the
pinned codec; the hand-written ZIP writer is replaced by the zip crate
already in the tree; ARCHIVE packs registered xref bytes too and
serializes document_for_save() like a web Save; the web save prepares
document_for_save() (prepare_document_for_save now takes the copy by
value, so no second clone); the wasm resolve_path consults the xref
registry, so every reference lookup — not just resolve — finds dropped
files; XRELOAD keeps main's undo, unload and stale-baseline handling;
native data extraction streams the source drawings one at a time.
Fixes:
- Hover state no longer drops when the pointer moves up from one strip
icon, group grip or title bar to the one above: iced handles the
element above first, so the old element's "left" (None) cleared the
hover just set. Leave messages now carry the element and only clear
their own hover.
- The drop preview used the pallets' own widths; it now uses the
group's width, matching where the pallet lands.
- Group indexes from messages (group grab, splitter) are looked up
safely, so a message from before a layout change no longer panics.
- Floating placements read from the config are healed (finite, positive,
at least the minimum size), like the group weights already were.
- The shown group's edge bar is centred in its row: a stack takes its
height from its first layer, and the icon column was shorter than the
row. The "Drag to move group" tooltip is removed.
Simplifications (no behaviour change):
- dock_open_at_default / dock_unpeek replace seven copies of "dock on
the right if unplaced, then reveal" and four of "stop peeking".
- The drop target takes the grab offset as a parameter, so a drag
update stores its state once.
- dock_set_open, ensure_settings, the shown-index bookkeeping after a
group is removed and the on-screen width clamp each lose duplication.
- VBarLabel drops options its single caller never varied.
- The drop preview's landing computation is one helper.
Naming and consistency: pallet names in the + menu, the drag ghost and
the floating title bar go through t!(); StripHit::Tab becomes
StripHit::Join; stale comments updated.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
Claude-Session: https://claude.ai/code/session_013RyGiMXcsf9HTKfqDxaQGt
No intended behaviour change except the fixes noted below.
- One drag state: a single `DockDrag` (move pallet / group, width,
splitter, floating size, Layer Manager column) replaces nine fields
(dragging, dragging group, resizing, split, float resizing, origin,
target, grab offset, layer column flag) that had to be kept in sync.
- `dock_expanded` becomes `dock_peek` with one meaning: a pallet revealed
although it auto-hides. `dock_reveal(id)` shows a pallet's group and
peeks it; commands that open a pallet now use it, so opening a pallet
also switches its edge to that pallet's group.
- Each group stores its own width (falling back to its widest pallet's
width until first sized), instead of every pallet's width being kept in
sync. Pallet widths now only size floating pallets and new groups.
- One `dock_set_open(id, open)` holds every pallet's open and close path.
- Leftovers removed: the tab-group config format that never reached main,
the multi-tab drag ghost header, the separate icon-hover message.
Fixes:
- Hovering a strip icon reveals an auto-hiding edge again (the icons had
lost the hover message in the option B strip). Covered by a test that
moves the pointer over the icon in the real view.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
Claude-Session: https://claude.ai/code/session_013RyGiMXcsf9HTKfqDxaQGt
Panels can now float over the workspace, share a docked slot as tabs,
and split an edge at heights the user picks.
- Dropping a panel away from the edges floats it at the pointer. Floating
panels move by their title bar, resize from a corner grip, and come to
the front when clicked.
- Dropping in the top or bottom quarter of a docked slot docks the panel
above or below it, as before. Dropping in the middle adds the panel as
a tab of that slot. Pressing a tab shows that panel; dragging a tab
pulls the panel out again.
- While dragging, a blue ghost previews the result: the new slot, the
slot with its future tab row, or the floating window.
- A splitter between stacked slots sets their heights; double-click it
to make the slots equal again. Heights persist.
- A press only becomes a drag after 5 px of movement, so clicking a title
bar or tab never moves the panel.
The persisted layout now stores each edge as tab groups with a height
weight, plus a list of floating panels. Configs with the old
bare-panel-id stacks still load as single-panel slots.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
Claude-Session: https://claude.ai/code/session_013RyGiMXcsf9HTKfqDxaQGt
#1573's five formatted block messages carried {}/{name} in every locale,
so the catalog never filled them and the UI printed the brace text; they
use the __ocs_fmt_0__ marker now. The Options collapse arrow, the library
up button and the folder picker are SVG icons instead of glyph text, and
the Details header drops its sort glyph. The contrast test follows the
cards to the weak surface pair and the palette test closes with
BLOCKSPALETTECLOSE, since BLOCKSPALETTE now only opens.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
Rebuild the Blocks palette with Current Drawing / Recent / Favorites /
Libraries tabs, wildcard filter, six views, insertion options, click and
drop insertion and a block context menu. INSERT opens the palette, the
new -INSERT runs on the command line, the ribbon Insert button becomes a
block gallery, and BLOCKMRULIST, BLOCKREDEFINEMODE, BLOCKNAVIGATE,
BLOCKSTATE, EXPLMODE and INSNAME are added.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
A crop is drawn on the view plane: it keeps the view's right and up
directions in the cloud's coordinates and its points in 3D, and cuts
along the view. POINTCLOUDUNCROP removes a picked cloud's crops.
POINTCLOUDLOD scales the points shown in tenths.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
Scans (.rcs) and projects (.rcp) are read and their points drawn as
screen-sized dots, coloured by the cloud's stylization. The cloud's
placement carries its scale and rotation; its extents and crops stay in
the scan's coordinates. A missing scan shows the extents with the saved
path. -POINTCLOUDATTACH / POINTCLOUDATTACH, POINTCLOUDCROP and the
POINTCLOUD* settings follow the reference's prompts and messages, the
Properties list is the reference's, and a locked cloud is left alone by
edits.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
- PDFOSNAP, DWFOSNAP and DGNOSNAP are separate; UOSNAP sets them all and
reads 2 while they differ. Enable Snap switches the selected kind's.
- DWFCLIP / DGNCLIP clip their own kind with the kind's prompts and message;
CLIP routes DWF and DGN underlays there; Enter at a corner asks again.
- The right-edge underlay tools show for DWF and DGN too (import is PDF
only).
- Underlay layers: DGN levels (V8 level table, "Default" listed as "0"; V7
used levels named from the level name table), hidden through the layer
override data with the DGN placeholder string first; a plotted DWF has
none.
- V8 colour read from its colour word (by level, index, or a true colour
drawn as its nearest index); 3D V8 elements drawn in plan (lines, line
strings, ellipses and arcs by their orientation, text); a model's extent
includes its text.
- DWF 6 TrueType text (font, height, rotation from the font opcode) and DWFx
glyph runs are drawn; the default W2D colour map is the measured one.
- Contrast pulls lightness towards a per-kind pivot as measured (PDF 0.5,
DWF 0.243, DGN 0.65).
- Zoom extents includes raster images and underlays whose frames are hidden.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
- CLIP continues as IMAGECLIP on a raster image and as VPCLIP on a layout
viewport, with the reference prompts and stored data.
- Image clip boundaries sit on pixel centres, OFF only clears the display
flag, and an inverted boundary cuts the image.
- VPCLIP polygon (Arc/Length/Close/Undo), clipping object and Delete; the
viewport shrinks to the boundary's exact extents, view kept.
- XCLIP Clipdepth: Remove clears only the plane asked, a front plane behind
the back one is rejected with the reference message.
- Attached and imported images carry the reference display flags.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
The codec and kernel repositories and crates are renamed opencadcodec and
opencadkernel. Inside OCS they are depended on under short keys, so code
reads `codec::`, `kernel::` and the new `graph::` (opencadgraph, the node
graph engine). File-format and protocol spellings stay as they were: the
ACIS product id `acadrust`, the ACADRUST_* switches and the plugin
version keys `acadrust_version` / `acadrust_source`.
A button left of MCP on the command line opens a translucent node graph
over the viewport, with a palette of object, input, math, logic, list,
text and geometry nodes added by click or drag. An object node owns
drawing entities and its rows are the Properties panel's own rows for
them: the single-object page is extracted from refresh_properties as
entity_property_sections, values use the control protocol's
property_json, and writes go through set_property_value with a property
target override, so the panel, MCP and the graph share one read/write
path. A list reaching an object row makes one entity per element. Each
graph action is one undo step; the canvas pans and zooms.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
The command driver was split into command_driver/ upstream; the PDF
underlay and XCLIP additions to the old file move with it: their
CmdResult arms into the router (mod.rs) and the block-reference
selection filter with its clip lookup into utilities.rs.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
Publishes app-free domain logic for shared use: match_special_props and PolylineMatchStyle move to entities::match_props; xdict trio usable headlessly; new match_layer, copy_to_clipboard, paste_entities and match_properties kernels over CadDocument. Handlers stay thin shells keeping undo, dirty flags, selection and command-line echo.
Adds cross-document copy, paste and property-match tests plus a headless proof driving copy, paste and match with no app instance.
- `XREF <args>` runs whole: probing the bare verb first now opens the
External References palette, which refreshed every entry and toggled
the palette before `XREF Reload A` / `XREF ?` ran.
- Update the two tests that encoded the old behaviour: `-XREF ?` prints
the reference table, and attaching a missing file is rejected.
- Drop the duplicate "Specify On-screen" catalog entry that shadowed the
translated common key, with its unused ftl keys.
- Move `remove_pipe_symbols`' doc comment back above its function.
- Note in `document_for_save` that resolved xref content stays out.
- Gate the desktop-only preview cap and tab index for wasm.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
Attach External Reference dialog after XATTACH / ATTACH; ATTACH routes
drawings, PDFs and images; placement prompts and messages follow the
reference (presets, Corner/XYZ, nonzero check, existing definition reuse,
missing file, self-reference); name keeps the file's case; overlay and
path type at attach; one undo step for definition and INSERT; -XREF option
prompt and `?` table; XREF opens the palette; ER alias; xref Properties
rows; dependent symbols flagged and remapped and resolved content left out
of the saved file; dialog_ok automation action; localized labels.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
Implement the complete Block Definition dialog window launched via BLOCK
and BMAKE commands, featuring standard CAD layout, workflows, and entity
creation pipelines.
- Dialog UI & Layout:
- 2-column compact CAD grid with synchronized vertical heights (580 × 390px).
- Editable combobox with existing block names, invalid character validation,
and inline redefinition badge.
- Multi-line text editor widget for block descriptions (replacing single-line input).
- Quick Select (QSELECT) button integration restoring dialog state upon completion.
- Confirmation guard when attempting to redefine an existing block definition.
- Centered radio buttons, clean coordinate inputs, and accessible keyboard shortcuts.
- Base Point & On-Screen Workflow:
- BlockOnScreenCommand strictly enforces prompt sequencing: Base point is
prompted before object selection.
- Dynamically recalculates world_to_block and block_to_world affine transforms
when base point is specified on-screen, preventing stale (0,0,0) normalization.
- Supports Retain, Convert to block (INSERT placement), and Delete modes.
- Explode Enforcement:
- Guarded EXPLODE command to prevent decomposing blocks flagged as non-explodable.
- Dynamic Themed Icons:
- Added pick_point.svg, select_objects.svg, quick_select.svg, and warning_triangle.svg.
- Routed all icons through the semantic theming engine so line work (#B4B6B9)
and accents (#6DB7ED) adapt automatically to the active theme.
- Tests:
- Added unit tests for retain/convert/delete modes, redefinition, explodable flag,
on-screen base point transform recalculation, and command sequencing.
XREF command with status, reload, unload, detach, path, pathtype, bind, overlay, and attach options, plus guided XATTACH with unique naming and placement prompts.
- Modify COPYCLIP command to write entities as JSON to system clipboard
- Modify CUTCLIP command to write cut entities as JSON to system clipboard
- Modify COPYBASE_AT command to write copied entities as JSON to system clipboard
- Entities are serialized as JSON with base point coordinates for cross-platform support
- Clipboard data format: OCS_CLIPBOARD_JSON header + base point + entity data
- Works in web (WASM) build via Clipboard API and native builds via iced clipboard
This fixes the issue where copy command didn't persist to system clipboard in web browser,
allowing proper paste operations and clipboard sharing between application instances.
Co-authored-by: Copilot <[email protected]>
INSERT enumerated all block names in a single prompt string, causing unbounded overlay growth and full-screen occlusion in drawings with many blocks. Replace prompt enumeration with a ranked, incrementally filtered suggestion model: BlockPicker maintains precomputed lower/upper caches and usage ranks (MRU/frequency), filters via O(n) substring scan and partial sorting (select_nth_unstable) to O(k), bounded to CLIPROMPTLINES.
Introduce CLIPROMPTLINES (Integer 0-50, Registry, default 3) for the number of temporary prompt lines above the command window; persist in UserSettings, expose via SETVAR and direct entry, enforce in CommandLine::view. Suggestion count is in direct relation to CLIPROMPTLINES (limit = clip, capped to 50).
Make search live without requiring Enter: add CadCommand::on_live_input, implement for INSERT/MINSERT via picker.set_needle, and wire to command-line input paths (Message::CommandInput, on_command_append_char, on_command_backspace). Updates use upper/lower caches and partial sort for <0.2ms per keystroke on 10k blocks, with debounced block-usage persistence (MRU cap 20, freq cap 200) to avoid I/O thrash. Correct tri_count test helper to use display_from_solid.
The ribbon kept its own \show_block_palette\ copy that the app had to
manually sync at every mutation point (the BLOCKPALETTE command and the
dock Close handler). Drop the copy and thread the app's authoritative
\show_block_palette\ into \Ribbon::view\ at render time, so the button
highlight can't drift from the panel's true visibility — those two
handlers are now mutate-points only and the ribbon view is the single
place that reads the state back.