Commit Graph
27 Commits
Author SHA1 Message Date
Hakan Seven 7a523a0f44 fix(clipboard): share COPY across drawings 2026-08-29 23:12:26 +03:00
Hakan Seven 217f20d8bc fix(clipboard): preserve pasted content
Reset cross-document ownership, include non-wire and locked objects, and rebuild image caches for embedded OLE content.

Refs #934
2026-08-29 22:40:59 +03:00
Hakan Seven 8c61d89b1e fix(layout): complete paperspace integration
Apply each layout's embedded page setup and plot style consistently across display, PDF, printing, and multi-layout output.\n\nRefs #844
2026-08-26 08:58:44 +03:00
Karim Jerbi 9c8f841f71 fix(insert): capped interactive block search and CLIPROMPTLINES
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.
2026-08-25 23:18:05 +01:00
Karim Jerbi b4da342f0e refactor(ribbon): derive the Block Palette button highlight from app state
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.
2026-08-15 14:42:08 +01:00
Karim Jerbi fbab4c4934 feat(ribbon): Block Palette button reflects panel open state
The Insert tab's Block Palette button now behaves like the View tab toggles
(UCS Icon, View Cube, Ortho, Properties, File Tabs, Layout Tabs): it stays
highlighted while the block palette panel is open and clears when closed.

The Ribbon gains a show_block_palette flag with a set_block_palette setter,
fed into ToggleState and mapped in is_active_tool for the BLOCKPALETTE tool
id. show_block_palette on the app remains the single source of truth; both
mutation paths now mirror it onto the ribbon:

- BLOCKPALETTE / BLOCKSPALETTE command toggles ribbon state alongside the
  panel (src/app/commands/blocks.rs).
- Closing the panel via the dock rail close button clears the ribbon state,
  matching how Close(Properties) already syncs (src/app/update/dialog.rs).
2026-08-14 23:33:45 +01:00
Hakan Seven 0be9c41773 fix(layers): protect locked entities
Keep locked-layer objects selectable for inspection while suppressing grips, property edits, command mutations, and stale editor writes.
2026-08-12 12:46:41 +03:00
Karim Jerbi 10a1d89f19 feat(dock): migrate block palette onto general edge-stack dock
Pin/close/resize/drag-between-edges/auto-collapse hover, themed and
persisted, mirroring the properties panel chrome.
2026-08-11 23:13:05 +01:00
Karim Jerbi 8f009d0058 feat(insert): add docked block palette
Add a searchable block palette with previews, file import, collision-safe nested definitions, and dependency/table-record import. Keep palette thumbnails current across drawing switches and block-definition edits.
2026-08-06 11:02:52 +03:00
Hakan Seven 9cf0c9f945 fix(ui): refine command line and clipboard
- preserve command history colors after reopening
- remove collapsed command bar residue and split the unsaved prompt
- read system text when the drawing clipboard is empty

Refs #467
Refs #468
Refs #470
2026-08-04 18:53:08 +03:00
Hakan Seven 9e90e50662 feat(io): add user-approved recovery 2026-08-03 12:47:48 +03:00
Hakan Seven 3e6693b93f feat(locale): localize full interface 2026-08-02 22:09:25 +03:00
Hakan Seven e03e091b3c feat(annotation): integrate object contexts 2026-08-02 12:00:15 +03:00
Hakan Seven 3ab8dc3ca5 fix(ui): make modal layouts intrinsic
Pin Iced 0.15 so dialogs can measure content before distributing the resolved frame across child panels. Keep the web plugin notice compact and non-resizable.\n\nCloses #582
2026-07-30 14:47:28 +03:00
Hakan Seven 05b044f367 perf(scene): make geometry edits incremental
Avoid full document, cache, and GPU rebuilds for entity deltas so add, delete, history, selection, and live polyline edits stay responsive on large drawings.
2026-07-28 17:16:27 +03:00
Hakan SevenandClaude Fable 5 0cd991e42f fix(xref): show merged xref layers in Layer Manager on attach (#407)
XATTACH / XRELOAD merge the xref's layer and linetype tables into the
document, but the Layers panel cache only rebuilds via
sync_with_viewports - which nothing triggered until the file was saved
and reopened. Refresh the layer panel (and ribbon mirrors) right after
the merge in both paths.

Co-Authored-By: Claude Fable 5 <[email protected]>
2026-07-21 15:59:26 +03:00
Hakan Seven 4c3509fa51 feat(commands): step the rest of the keyword/value commands
Convert the remaining bucket-B commands to prompt step by step instead of
requiring arguments or printing usage:

- KeywordCommand (buttons): VIEW, LINETYPE, SCALELISTEDIT, UCSICON, VSCURRENT.
- ValuePromptCommand (one value): LAYDEL (layer), ATTSYNC (block).
- TwoValuePromptCommand (new; two values): LAYMRG (source + target),
  SETVAR (variable + value, blank second reads).

Each bare form now starts the stepped front-end and delegates to the existing
inline handler; the argument form is kept and is the dispatch target. The
direct visual-style shortcuts (HIDDENLINE / XRAY / …) and UCSICON's argument
form are untouched.

COUNT is intentionally left alone: bare COUNT already reports the tally (a
useful inquiry action, not a usage line), so prompting would only add friction.
2026-07-16 13:29:04 +03:00
Hakan SevenandClaude Opus 4.8 8ed10ceb2a feat(mtext): structured editor with selection, copy, and visible bold
Rewrite the in-app MTEXT editor to run on acadrust's structured
MTextDocument model end-to-end: load via parse_mtext, edit a flat Cell
model, serialize via to_mtext_string. Retires the hand-rolled format-code
string handling, the parallel visible_spans parser, the composed_value
prefix, and the Edit-raw-code tab.

Selection and copy:
- double-click selects the word, triple-click selects all (click-counting)
- Ctrl+A selects all text
- Ctrl+C copies the selected text to the clipboard

Formatting:
- per-selection Bold/Italic/Underline/Overline/Strike/Case/Alignment
- Bold renders as a visibly thicker SDF pen, keyed (family, char, bold)
  through the whole text pipeline; the resolved style font name is stamped
  so the \f...|b1; code survives serialization
- per-selection font and color changes
- editor color dropdown reuses the Properties panel color selector

Global toolbar defaults (font/color/oblique/width/tracking) fold onto the
document as real span properties instead of a leading code prefix; a
trailing empty paragraph is preserved so Enter at the end keeps its line.

Co-Authored-By: Claude Opus 4.8 <[email protected]>
2026-07-11 20:18:50 +03:00
Hakan SevenandClaude Opus 4.8 2a72227d5d feat(attribute): route ATTMAN/BATTMAN to the attribute editor (ATTEDIT)
ATTMAN and BATTMAN previously produced a command-line listing of block
attributes. Route both to the attribute editor instead: extract the bare
ATTEDIT behavior into a shared open_attedit_dialog helper (edit the
selected block, or start the block-pick command) and call it from the
ATTEDIT, ATTMAN, and BATTMAN arms.

Kept as a match arm rather than an ocad.pgp alias so it works for
existing users, whose config pgp is only seeded on first run.

Replace the listing regression tests with one asserting ATTMAN and
BATTMAN behave byte-for-byte like ATTEDIT.

Co-Authored-By: Claude Opus 4.8 <[email protected]>
2026-07-11 09:37:54 +03:00
Kevin GriffinandClaude Opus 4.8 0f6999a838 fix(blocks): make BATTMAN work instead of erroring like ATTMAN (#295)
BATTMAN matched the ATTMAN command arm but the argument was extracted
with `cmd.trim_start_matches("ATTMAN")`. "BATTMAN" has no leading
"ATTMAN" to strip, so the whole word survived as a bogus block-name
argument — BATTMAN always reported "ATTMAN: no matching block" instead
of listing attributes. `BATTMAN <name>` never matched at all.

Strip whichever keyword was actually typed (BATTMAN first, since ATTMAN
is a suffix of it) with `strip_prefix`, and match the `BATTMAN ` prefix
form too. BATTMAN now behaves identically to ATTMAN.

Adds headless regression tests driving the real dispatcher; they fail on
the previous code with the reported symptom and pass with the fix.

Co-Authored-By: Claude Opus 4.8 <[email protected]>
2026-07-10 15:06:12 -07:00
Hakan SevenandClaude Opus 4.8 91ba9f7699 feat(alias): centralize command aliases in user-editable ocad.pgp (#286/#288)
Command aliases (L→LINE, CC→COPYCLIP) were scattered across dispatch match
arms and CommandRegistration name arrays. Move them all into a single
user-editable file:

- assets/ocad.pgp: shipped default alias table (ALIAS,*COMMAND format),
  embedded and copied to config/ocad.pgp on first launch; only that user
  copy is read after. AA→AREA default closes #286.
- resolve_alias() rewrites the leading command token at the top of
  dispatch_command_inner, so aliases resolve for every path (families,
  plugins, Repeat menu). Args after the first space are untouched.
- Autocomplete hides alias keys and, when the whole input is an alias,
  surfaces its target command as the top (highlighted) suggestion so the
  highlight matches what Enter runs (AA→AREA, L→LINE).
- ALIASEDIT opens a new editor modal (add/edit/delete rows) with an Apply
  button; Apply persists to ocad.pgp, closing discards unapplied edits.
- Strip alias tokens from all 8 dispatch match-arm files and 71 module
  CommandRegistration arrays, keeping canonical/synonym/distinct-command
  names. ocad.pgp is now the sole source: deleting or remapping an alias
  there takes effect. CUI stays on the keyboard-shortcut panel.

Co-Authored-By: Claude Opus 4.8 <[email protected]>
2026-07-10 12:39:22 +03:00
Hakan SevenandClaude Opus 4.8 c249a99d4c fix(clipboard): paste anchor at bounding-box lower-left, not center (#285)
COPYCLIP/CUTCLIP used the mean of each entity's bounding-box centre as the
paste anchor. Standard clipboard behaviour puts the lower-left corner of the
box enclosing all copied items under the cursor. Union each entity's bbox min
corner instead, and rename clipboard_centroid -> clipboard_base (COPYBASE also
stores a picked point there, so "centroid" was inaccurate).

Co-Authored-By: Claude Opus 4.8 <[email protected]>
2026-07-10 11:16:13 +03:00
sLuCHa 56835791af perf(clipboard): derive the paste anchor from bounding boxes
COPYCLIP/CUTCLIP computed the clipboard anchor by tessellating every
selected entity and averaging all wire vertices — O(total geometry),
~250 ms when copying a whole drawing. The anchor only fixes which point
of the selection sits under the cursor at paste, so the mean of each
entity's bounding-box centre is an equally valid, far cheaper origin.
2026-07-08 18:57:11 +02:00
Hakan SevenandClaude Opus 4.8 e2a83a6487 feat(commands): add CLOSE, HIDE, VISUALSTYLES, QUICKCALC, HYPERLINK, XOPEN
Six more standard commands by reusing existing infrastructure:
- CLOSE: close the active tab (Message::TabClose)
- HIDE / VISUALSTYLES: per-viewport render mode (Message::SetRenderMode)
- QUICKCALC / QC: alias the CAL arithmetic evaluator
- HYPERLINK <url>: attach a hyperlink via the PE_URL XData record
- XOPEN: open a selected xref's source file (Message::OpenRecent)

COMMANDS.md updated to 214 done / 15 partial / 33 missing of 262.

Co-Authored-By: Claude Opus 4.8 <[email protected]>
2026-06-29 09:04:18 +03:00
Hakan SevenandClaude Opus 4.8 c19c18c2f2 feat(commands): expand standard CAD command coverage
Integrate a large batch of standard CAD commands and fix several
name/behaviour mismatches, with no product references in code.

3D solids (reusing the truck B-rep pipeline):
- SLICE, INTERFERE, PRESSPULL, POLYSOLID, PYRAMID, SECTION
- 3DROTATE, 3DMIRROR, 3DALIGN (cached-solid transforms)

Annotation / text:
- ARCTEXT, SPLINEFIT (Catmull-Rom to Bezier), DIMJOGGED, OBJECTSCALE
  (XData markers honoured by the existing geometry-gen / tessellator)

Blocks / misc:
- NCOPY (block-content extraction via explode_entity)
- OPTIONS, SYNCPVIEWPORTS, THICKEN, plus earlier toggles, aliases,
  system variables, and layer/style/view commands

POINTCLOUD/RECAP and UNDERLAYLAYERS/UOSNAP are intentionally left out:
they require a proprietary binary / PDF-layer parser, a GPU point
renderer, and real test files.

Co-Authored-By: Claude Opus 4.8 <[email protected]>
2026-06-29 08:23:58 +03:00
Hakan SevenandClaude Opus 4.8 0ca3954b5d feat(commands): integrate standard CAD commands and fix behavior gaps
Broad pass over the command set: integrate missing commands, wire
previously-unreachable ribbon/menu buttons, and correct name/behaviour
mismatches. Every UI command token now resolves (real handler where the
infrastructure exists, an honest "not yet implemented" status otherwise).

New commands:
- Draw: 3DPOLY, 2D solid (SO/SOLID2D), HELIX, TRACE, SKETCH, DIMCENTER
  (DCE/CENTERMARK)
- Modify/inquiry: REVERSE, MEASUREGEOM (MEA), DBLIST
- Data/manage: BASE, OVERKILL (exact-duplicate removal), AUDIT (read-only
  integrity report), SETVAR (system-variable get/set), SCRIPT (.scr runner),
  FINDNONPURGEABLE

Behaviour fixes:
- LINE and SPLINE gain Close/Undo; AREA computes area/perimeter in f64
  (correct at large coordinates)
- ATTEDIT/ATE unified so the alias and the ribbon button open the
  interactive editor; -ATTEDIT is the command-line form
- Linear/aligned/radius/diameter dimensions gain a text override (Text) and
  text angle (Angle) option
- INSERT gains Scale/Rotate options; COPY gains an Array option
- LINETYPE SET sets the current entity linetype; SETBYLAYER resets overrides
- UNDO accepts a step count

Integrations: standard dimension/block aliases (DLI/DRA/DAN, BMAKE,
EXPORTPDF, DDIM), drafting-aid and screen toggles (GRID/SNAP/POLAR/OSNAP/
DSETTINGS/CLEANSCREEN/QUICKPROPERTIES), viewport tiling
(CASCADE/HORIZONTAL/VERTICAL/VPJOIN), and customization entry points
(CUI/ALIASEDIT).

Co-Authored-By: Claude Opus 4.8 <[email protected]>
2026-06-28 19:27:35 +03:00
Hakan SevenandClaude Opus 4.8 bddc050b3e refactor: split four oversized files into submodule trees
Break up the four giant files (~29k lines total) into focused submodule
directories, one concern per file. Pure mechanical moves — behavior is
unchanged.

- app/update.rs (9650) -> app/update/{mod,viewport,command,style,file,
  dynamic,dialog,util}. The 384-arm update_inner match stays in mod.rs
  with thin delegating arms; the 66 fattest arm bodies move to topic
  methods. Arm set preserved exactly (384 -> 384).
- scene/mod.rs (9017) -> scene/{mod,entity,tess,hittest,layout,paper,
  mspace,project,selection,modify,group_layer,preview}. The impl Scene
  body is split across files via inherent-impl-per-file; struct, ctor,
  fields and load-time helpers stay in the root. fn count 123 -> 123.
- app/commands.rs (6082) -> app/commands/* grouped by command family.
  The 233-arm dispatch match becomes source-ordered per-family
  dispatch_* handlers, preserving first-match precedence (233 -> 233).
- app/view.rs (4686) -> app/view/{mod,overlay,modal,viewcube,controls}.

Largest file drops from 9650 to 3343. Builds clean; app launches and
loads plugins with no panic.

Co-Authored-By: Claude Opus 4.8 <[email protected]>
2026-06-26 22:51:29 +03:00