Commit Graph
96 Commits
Author SHA1 Message Date
Hakan SevenandClaude Opus 4.8 3d050fe1ab feat(ui): move full ACI palette to a separate "Select Color" window (#94)
The colour selector popup now lists only the named colours (ByLayer,
ByBlock, ACI 1-9) plus a "More…" entry. "More…" opens a standalone
"Select Color" window with the full 256-colour grid; picking there applies
to the originating field (dimension/multileader/table style) and closes
the window. Routed via a ColorPickTarget so one window serves every field.

Co-Authored-By: Claude Opus 4.8 <[email protected]>
2026-06-14 11:14:14 +03:00
Hakan SevenandClaude Opus 4.8 3a87a18f32 fix(ui): float the colour-selector popup instead of pushing the form (#94)
The colour list/palette was laid out inline, shifting everything below it
down when opened. Wrap it in a small custom widget (Floating) that renders
the button inline and the popup as an iced overlay anchored below it, so it
floats over the UI like a real dropdown. Picking a colour now also closes
the popup (the style editors clear their open-field state on edit).

Co-Authored-By: Claude Opus 4.8 <[email protected]>
2026-06-14 11:00:43 +03:00
Hakan SevenandClaude Opus 4.8 96a5a32735 feat(ui): show colour swatches beside names in the colour selector (#94)
Reworked the shared colour selector from a plain text pick_list into a
dropdown button that opens a list where each named colour (ByLayer,
ByBlock, ACI 1-9) shows its swatch next to the name, with the full ACI
palette grid below. The dimension/multileader/table style editors pick
it up unchanged.

Co-Authored-By: Claude Opus 4.8 <[email protected]>
2026-06-14 10:47:20 +03:00
Hakan SevenandClaude Opus 4.8 8cdb17a6b4 feat(ui): shared colour selector used across all style editors (#94)
Add a reusable color_selector widget (ui/color_select.rs): a main-colour
dropdown plus a "more colours" button that expands the full 255-entry ACI
palette — the same design the properties panel uses. Replace the flat ACI
swatch rows added earlier in the dimension, multileader and table style
editors with it, wired through each editor's existing colour edit message
(the chosen colour is encoded as an ACI string) plus a per-field
palette-open toggle.

Co-Authored-By: Claude Opus 4.8 <[email protected]>
2026-06-14 10:42:39 +03:00
Hakan SevenandClaude Opus 4.8 3ccda2f129 feat(style): pick colours from ACI swatches in the style editors (#94)
Dimension, multileader and table style editors took colours as raw ACI
integers in a text box. Replace those with a swatch row (the 9 standard
ACI colours + ByLayer) that highlights the current value, reusing each
editor's existing colour edit message (the chosen index is sent as the
field's string value, so no new plumbing).

Text styles carry no colour field, so none was needed there.

Co-Authored-By: Claude Opus 4.8 <[email protected]>
2026-06-14 10:15:14 +03:00
Hakan SevenandClaude Opus 4.8 f93bda1800 feat(dimstyle): use named dropdowns for enum style settings (#94)
The dimension style editor exposed every enum setting (DIMTAD, DIMJUST,
DIMLUNIT, DIMTMOVE, DIMATFIT, DIMTFILL, DIMFRAC, DIMAUNIT, DIMAZIN,
DIMALTU, DIMTOLJ, DIMARCSYM, and the zero-suppression family) as a raw
integer text box, forcing the user to type codes like "1". Replace them
with named pick_list dropdowns via an enum_field helper that maps the
stored code to a label and back. Numeric fields (sizes, colours,
decimals) and obsolete flags (DIMUNIT/DIMFIT) keep their text inputs.

Co-Authored-By: Claude Opus 4.8 <[email protected]>
2026-06-14 09:28:36 +03:00
Hakan SevenandClaude Opus 4.8 57d3e620ea fix(command): keyword/radius input for ribbon-started modify commands (#90)
Starting FILLET/CHAMFER from the ribbon left the command-line field
unfocused, so its Enter arrived as CommandFinalize and discarded a
typed option keyword ("R"/"D"), cancelling the command. Several
related dynamic-input issues surfaced from the same flow:

- CommandFinalize now forwards a non-empty command-line buffer through
  CommandSubmit, so a typed keyword is handled the same whether the
  command was started from the ribbon or the command line.
- sync_dyn_fields shows no coordinate box during an object-pick step
  (needs_entity_pick / needs_structure_point_pick) — there is no point
  to enter there, so typed keywords reach the command line cleanly.
- apply_cmd_result rebuilds the dynamic-input fields on NeedPoint, so a
  step change (object pick -> radius entry) shows the matching box
  immediately and typed digits land in it instead of the command line.
- Object-pick steps now draw a prompt-only hint pill at the cursor
  (no input box).
- FILLET/CHAMFER remember the first pick across a mid-selection radius
  or distance entry, resuming the second pick instead of restarting
  selection.

Co-Authored-By: Claude Opus 4.8 <[email protected]>
2026-06-13 23:58:56 +03:00
Hakan SevenandClaude Opus 4.8 cd4d1c2535 fix(layout): focus inline rename field on RENAME
Renaming a layout tab left keyboard focus on the command line, so typed
characters landed there until the user clicked the tab. Give the inline
rename text_input a stable id and return a focus task when the rename
starts so the user types straight into the field. (issue #86)

Co-Authored-By: Claude Opus 4.8 <[email protected]>
2026-06-12 14:18:31 +03:00
Hakan SevenandClaude Opus 4.8 71837895b0 feat(ui): right-edge side toolbar; drop the paper-space ribbon tab
Switching to a paper layout used to hijack the ribbon with a contextual
"Layout" tab. Replace that with a reusable right-edge vertical toolbar:
a single centred column of icon buttons floated over the canvas, built
from a flat ToolDef list and dispatching through the existing
RibbonToolClick path (ui::side_toolbar). Paper space now shows Viewport /
Page Setup / Export PDF there and leaves the ribbon on the user's tab;
the contextual layout tab and its three auto-switch hooks are removed.
The toolbar is generic infrastructure for future context action sets.

Co-Authored-By: Claude Opus 4.8 <[email protected]>
2026-06-12 02:07:26 +03:00
Hakan SevenandClaude Opus 4.8 b47e1bf706 fix(ribbon): load style/layer dropdowns from the document
The Annotate style dropdowns (text / dimension / multileader / table) and
the layer dropdown were hard-coded to "Standard" / "0" and never synced
from the opened document, so they showed placeholder values even with no
file open and stale values after closing one.

- Start the ribbon's style and layer lists empty instead of with a
  placeholder entry.
- Sync the style dropdowns from the document on file open and on tab
  new/switch/close (the layer sync already ran there).
- Guard sync_ribbon_layers / sync_ribbon_styles / sync_ribbon_from_selection
  for the Start (welcome) tab so all three dropdowns stay empty there.
- When a style family is absent (e.g. no table/multileader styles), fall
  back to empty rather than a non-existent "Standard".

Co-Authored-By: Claude Opus 4.8 <[email protected]>
2026-06-12 01:46:17 +03:00
Hakan SevenandClaude Opus 4.8 b3ba3a53d1 feat(styles): green ✓ for current style + resolve it from DWG files
- The current-style marker is now a green ✓ in its own fixed-width column
  so names stay aligned; rendered as a separate coloured glyph rather than
  baked into the label string.
- Resolve the current text / dimension / multiline style from the handle
  the DWG header stores into the name the app reads (fix_current_style_names
  on load). DXF already provides these as names ($TEXTSTYLE / $DIMSTYLE /
  $CMLSTYLE); DWG only stores handles, so the marker previously always fell
  back to "Standard". Only overrides when the handle resolves.

Note: table and multileader current styles are not surfaced by the file
reader (no header name/handle exposed), so those markers still default to
the app's active selection until acadrust exposes them.

Co-Authored-By: Claude Opus 4.8 <[email protected]>
2026-06-10 15:56:13 +03:00
Hakan SevenandClaude Opus 4.8 885bacd0f6 feat(styles): mark the current style with a ✓ in the list
Every style manager now shows a leading ✓ next to the current style
(current text/dim style, active table/multileader/multiline style), with
the other rows padded so names stay aligned. The marker replaces the
multileader/multiline-only ◀ and is wired for all five managers by
threading the current-style name into each view.

Co-Authored-By: Claude Opus 4.8 <[email protected]>
2026-06-10 15:45:48 +03:00
Hakan SevenandClaude Opus 4.8 de4eb31003 feat(styles): make style managers transactional — persist only on Apply
A style manager is now a staged transaction. When it opens, a snapshot of
the style tables, style objects and current-style pointers is taken. Every
New / Copy / Delete / Rename / Set Current / property edit mutates the
document live so the dialog previews the result, but the tab is not marked
dirty, nothing is pushed to undo, and the drawing is not rebuilt.

- Apply commits: one undo entry (restoring the pre-edit state), the tab is
  marked dirty, the drawing rebuilds, and the baseline is reset so further
  edits stage afresh.
- Closing the window without Apply discards: the opening snapshot is
  restored, so none of the changes persist.

Side effects (dirty / undo / bump_geometry) were removed from every style
edit handler and routed exclusively through the commit. Multiline's Apply
is a structural-only commit since its editor has no editable properties.

Co-Authored-By: Claude Opus 4.8 <[email protected]>
2026-06-10 15:38:32 +03:00
Hakan SevenandClaude Opus 4.8 65a25033bc fix(styles): make double-click inline rename actually fire
The list row wrapped a `button` inside the `mouse_area`. The button
captured the press, so the parent `mouse_area` never saw the second
click and `on_double_click` never fired — double-clicking a style name
did nothing.

Drop the inner button: the row is now a plain `mouse_area` carrying both
`on_press` (select) and `on_double_click` (start rename), with selection
shown via the container background. Focus the rename field on start so
the user can type immediately.

Co-Authored-By: Claude Opus 4.8 <[email protected]>
2026-06-10 15:10:09 +03:00
Hakan SevenandClaude Opus 4.8 f2dfd01795 feat(styles): unify the five style managers behind a shared frame
The text/dimension/table/multileader/multiline managers were hand-copied,
so their list CRUD kept drifting and breaking: Dimension's New created
nothing (#73), new text styles never reached the ribbon dropdown (#74),
and several were added with a NULL handle (dropped on DWG save, #67).

Collapse the duplicated parts into three shared pieces and leave only the
per-manager property editor bespoke:

- app/style_ops.rs: one StyleKind-dispatched CRUD layer (new / copy /
  delete / rename) handling handle allocation, ribbon sync, Table re-key
  and name-reference rewrites in a single place.
- ui/style_manager.rs: the window scaffold — uniform toolbar (New / Copy /
  Delete on the left, Set Current + Apply on the right), style list and
  chrome. Each manager now only builds its editor.
- ui/style_list.rs: the list row — single click selects, double click
  starts an inline rename.

New capabilities, now consistent across all five:
- Copy duplicates the selected style.
- Double-click a name to rename it inline.
- Right side is always Set Current + Apply (added Table set-current;
  MLine apply is a documented placeholder until its editor is editable).

Co-Authored-By: Claude Opus 4.8 <[email protected]>
2026-06-10 15:03:34 +03:00
Hakan Seven 6a70e99dd5 Merge pull request #80 from mf4633/feature/plugin-host
Add plugin host (Phase 1)
2026-06-10 00:37:37 +03:00
Michael Flynn 82993bc1db Add demo_plugin and plugin host integration tests
Minimal in-tree add-on (DP_HELLO) validates registry, ribbon merge, and try_dispatch. Five new lib tests; EntryKind gains PartialEq for test helpers.
2026-06-09 13:52:15 -04:00
Michael Flynn e46701456f Add plugin host architecture and Storm Sewer add-on package
Generic plugin runtime (src/plugin/, HostSession, per-tab plugin_state, command router). QGIS-style add-on layout with plugin.toml and single PluginRegistration. Storm Sewer refactored as reference consumer with dispatch.rs, catchments, LandXML, headless tests (43 passing). Core update.rs decoupled from storm_sewer via CadCommand object-pick hooks. Docs: plugin-architecture.md, plugin-template, PR and issue-78 reply drafts.
2026-06-09 13:41:21 -04:00
Hakan SevenandClaude Opus 4.8 ff10f8a89a feat(ui): elide overflowing text, tooltip full layer name
iced has no built-in ellipsis, so long user content (file names, layer
names, paths, property values) wrapped or spilled past fixed-width
panels. Add an `elide` helper (char-budget truncation with a trailing
ellipsis) and apply it to the layer manager, properties panel, document
tabs, recent-files list and the save dialog.

In the layer manager a truncated name reveals its full text in a
cursor-following tooltip on hover, so the column need not be widened.

Co-Authored-By: Claude Opus 4.8 <[email protected]>
2026-06-09 19:04:18 +03:00
Hakan SevenandClaude Opus 4.8 b3aadf569e fix(commandline): pin active step prompt instead of fading
The current step's prompt was written into the command-line widget
label. Instead, keep it as a normal history line but freeze its
cooldown: the step prompt is pinned so it does not fade while the user
is still on that step. When the step changes the previous line's
cooldown restarts; when the command ends the pin clears and it fades.

`update` is now a thin wrapper that mirrors the active command's prompt
into the command line after each message; the body moved to
`update_inner`.

Co-Authored-By: Claude Opus 4.8 <[email protected]>
2026-06-09 18:46:45 +03:00
Hakan SevenandClaude Opus 4.8 4b878b88c4 feat(input): scalar entry via dynamic input
Text-input steps (OFFSET distance, POLYGON sides, radii, counts) were
swallowed by the dynamic-input overlay: typed digits landed in the field
buffer and Enter committed a point pick, so the value never reached
on_text_input (issue #61). Now each text step shows one scalar box whose
value routes to on_text_input on commit; non-numeric prompts (names,
keywords) keep going to the command line so mixed text like "Bolt12"
isn't split.

OFFSET reworked: object first, then through-mode by default — the offset
follows the cursor at the perpendicular distance to the object. Typing a
number locks the magnitude (cursor then only picks the side); a value
typed and clicked without Enter is applied before the point pick.

The dynamic-input overlay and the command line now show the active
step's prompt and hold it until the step completes.

Co-Authored-By: Claude Opus 4.8 <[email protected]>
2026-06-09 18:32:03 +03:00
Hakan SevenandClaude Opus 4.8 70702d063f perf(hash): swap std HashMap/HashSet for rustc-hash FxHash
Phase 4.1. Handle / u64 keys dominate the hot maps (block_defn,
hatch / image / mesh caches, draw-depth map, viewport wire caches);
the default SipHash is wasted work on integer keys. Alias the std
types to rustc_hash::FxHashMap / FxHashSet crate-wide so every map and
set — including the cross-module draw-depth map shared between scene
and the GPU pipelines — uses the faster hasher consistently.

Mechanical: no behavioural change. Constructors moved from ::new() to
::default() (Fx variants carry no RandomState). Build + 13 tests green.

Co-Authored-By: Claude Opus 4.8 <[email protected]>
2026-06-05 00:35:53 +03:00
Hakan SevenandClaude Opus 4.8 bb54cd034f fix(statusbar): cycling-list hover highlight on row re-entry
Row exit now clears the preview only when the highlight still points at
that row. Moving between rows can fire on_enter before the previous
row's on_exit, so the unconditional clear wiped a freshly highlighted
row (notably when returning to the first row). Guarding the clear fixes
the highlight not reappearing.

Co-Authored-By: Claude Opus 4.8 <[email protected]>
2026-06-05 00:05:15 +03:00
Hakan SevenandClaude Opus 4.8 a9228b9021 feat(statusbar): highlight cycling-list object on row hover
Add a scene hover_highlight handle that renders an entity with the
selection colour without joining the real selection. The cycling list
box sets it on row enter / clears on exit, so hovering a row glows the
matching object in the drawing.

Co-Authored-By: Claude Opus 4.8 <[email protected]>
2026-06-05 00:00:52 +03:00
Hakan SevenandClaude Opus 4.8 bcbda65746 feat(statusbar): selection cycling shows a pick list, adds to selection
Replace the repeat-click cycling with a list box: when a click lands on
two or more overlapping objects (cycling on), a small list of the
candidates opens at the cursor. Picking a row adds that object to the
current selection (accumulate); clicking outside dismisses it. A single
object under the cursor falls through to the normal click.

Co-Authored-By: Claude Opus 4.8 <[email protected]>
2026-06-04 23:56:24 +03:00
Hakan SevenandClaude Opus 4.8 ac042c5dbf feat(statusbar): selection cycling for overlapping objects (SC pill)
Add a click_hits_all hit-test and an SC pill that, when on, makes
repeated clicks at the same spot step through the overlapping objects
there (nearest first) instead of accumulating the selection. The whole
cycling path is gated behind the toggle, so default picking is unchanged
when it is off.

Co-Authored-By: Claude Opus 4.8 <[email protected]>
2026-06-04 23:44:39 +03:00
Hakan SevenandClaude Opus 4.8 f7eac09b55 feat(statusbar): selection filtering by object type (FILTER pill)
Add a per-type selection filter to the scene: the FILTER pill opens a
checklist of the entity types in the layout, and unchecking a type
excludes it from interactive picking (click, box and lasso selection all
honour it). The pill lights up while any type is filtered out.

Co-Authored-By: Claude Opus 4.8 <[email protected]>
2026-06-04 23:39:48 +03:00
Hakan SevenandClaude Opus 4.8 834780ec5d feat(statusbar): quick properties floating panel (QP pill)
When the QP pill is on, a compact floating panel appears at the canvas
top-left on selection, reusing the docked panel's editable section rows.
Toggleable from the status-bar customization menu.

Co-Authored-By: Claude Opus 4.8 <[email protected]>
2026-06-04 23:31:36 +03:00
Hakan SevenandClaude Opus 4.8 66f7d24bc9 feat(statusbar): transparency-display toggle (TPY pill)
Add a transparency_enable uniform read by the wire shader: when the new
TPY pill is off, every line is forced opaque; when on, baked entity
transparency shows through. Toggling is a uniform write, no retessellate
(same mechanism as the lineweight-display toggle). Pill is toggleable
from the status-bar customization menu.

Co-Authored-By: Claude Opus 4.8 <[email protected]>
2026-06-04 23:25:09 +03:00
Hakan SevenandClaude Opus 4.8 28ec360255 feat(statusbar): isolate action menu on the pill and right-click
Clicking the ISO pill now opens a small menu with Isolate Objects, Hide
Objects and End Isolation instead of ending isolation directly; rows
that don't apply (no selection / nothing hidden) are dimmed. The same
actions are added to the viewport right-click menu.

Co-Authored-By: Claude Opus 4.8 <[email protected]>
2026-06-04 23:17:21 +03:00
Hakan SevenandClaude Opus 4.8 e0e7897952 feat(statusbar): isolate / hide objects with status pill
Add a hidden-entity set to the scene that the tessellation visibility
test skips, so hidden objects neither render nor hit-test. New commands
ISOLATEOBJECTS (show only the selection), HIDEOBJECTS (hide the
selection) and UNISOLATEOBJECTS (restore). An ISO status pill lights up
while anything is hidden and restores everything on click.

Co-Authored-By: Claude Opus 4.8 <[email protected]>
2026-06-04 22:51:23 +03:00
Hakan SevenandClaude Opus 4.8 243a0bc923 feat(statusbar): drawing-units pill with INSUNITS picker
Add a Units pill that shows the drawing's current INSUNITS value and
opens a picker to change it (Unitless, mm, cm, m, km, in, ft, mi, yd).
Toggleable from the status-bar customization menu like the other pills.

Co-Authored-By: Claude Opus 4.8 <[email protected]>
2026-06-04 22:06:42 +03:00
Hakan SevenandClaude Opus 4.8 d829f80a04 feat(statusbar): customizable pills with coordinates and clean screen
Add a customization menu (far-right handle) that lists every status-bar
pill with a check mark; toggling a row shows or hides that pill, and the
choice persists across sessions in the config dir.

New pills:
- Coordinates: live cursor readout (re-adds the model-space world offset
  so it shows true drawing coordinates), updated on every move rather
  than only while a command is active.
- Clean Screen: hide the ribbon and side panels for a full canvas.

Co-Authored-By: Claude Opus 4.8 <[email protected]>
2026-06-04 19:14:04 +03:00
Hakan SevenandClaude Opus 4.8 edc8cbc969 feat(scale): drive scales from the drawing's scale list
Read the model-space annotation scale from the standard CANNOSCALE /
CANNOSCALEVALUE header variables instead of a user-variable hack, and
populate both the status-bar scale picker and the viewport Scale
property purely from the drawing's ACAD_SCALELIST — no built-in
fallback set. Xref-derived scales (`_XREF` suffix, `name|` prefix)
are filtered out so only the host drawing's own scales appear.

Bumps the patched acadrust to the commit that adds CANNOSCALE/
CANNOSCALEVALUE read/write.

Co-Authored-By: Claude Opus 4.8 <[email protected]>
2026-06-04 16:18:01 +03:00
Hakan SevenandClaude Opus 4.8 10d674f606 feat(tablestyle): complete field coverage (flow, description, cell data + borders)
Table Style editor now exposes every TableStyle / RowCellStyle field:
- General: description, flow direction (Down/Up dropdown).
- Per cell: data type, unit type, format string, plus all six borders
  (left/right/top/bottom/horizontal-inside/vertical-inside) with line
  type (Single/Double), line weight, color (ACI), double-line spacing
  and a visibility toggle.
Border type/visibility apply immediately; the numeric border fields and
data/unit/format are written by the existing "Apply cell" button.

Co-Authored-By: Claude Opus 4.8 <[email protected]>
2026-06-03 21:09:37 +03:00
Hakan SevenandClaude Opus 4.8 6ae24cceee feat(styles): complete MLeader field coverage + Dimension DIMUNIT
MLeader Style editor now exposes every MultiLeaderStyle field: line
weight, line type / arrowhead block / text style / block-content blocks
(handle dropdowns from the document's tables), the four text attachments
+ attachment direction, the full block-content group (color, connection,
rotation, X/Y/Z scale, enable scale/rotation), leader & multileader draw
order, align space, and description.

Dimension Style editor adds the last uncovered DIMUNIT field.

Co-Authored-By: Claude Opus 4.8 <[email protected]>
2026-06-03 21:04:22 +03:00
Hakan SevenandClaude Opus 4.8 578b8c5d64 fix(styles): keep style-editor scrollbar at the window's right edge
The detail-panel scrollables defaulted to shrink-to-content width, so
their vertical scrollbar landed in the middle of the panel next to the
content instead of at the window edge. Make the scrollables fill width
(and drop the dimstyle panel's right padding so the bar sits flush) in
the Dimension, Table and MLeader style editors.

Co-Authored-By: Claude Opus 4.8 <[email protected]>
2026-06-03 20:48:40 +03:00
Hakan SevenandClaude Opus 4.8 bd120ca307 refactor(styles): replace cycle buttons with dropdowns
The enum/handle pickers in the MLeader, Table and Dimension style
editors used "Cycle" buttons, which were awkward. Replace them with
pick_list dropdowns:
- MLeader: path type, content type, text angle, text alignment.
- Table per-cell: alignment (9 anchors).
- Dimension: arrowhead blocks (DIMBLK/1/2/LDRBLK) and ext-line linetypes
  (DIMLTYPE/LTEX1/LTEX2), options resolved from block_records/line_types.

Co-Authored-By: Claude Opus 4.8 <[email protected]>
2026-06-03 20:44:37 +03:00
Hakan SevenandClaude Opus 4.8 1b7edf6cae feat(dimstyle): block/linetype Handle cyclers for arrowheads & ext lines
The arrowhead-block (DIMBLK/DIMBLK1/DIMBLK2/DIMLDRBLK) and ext-line
linetype (DIMLTYPE/DIMLTEX1/DIMLTEX2) Handle fields are now editable in
the Dimension Style manager. Each shows the resolved block-record /
linetype name and a Cycle button that advances through the available
records (NULL = Default arrowhead / ByBlock linetype). Edits bump
geometry so dimensions re-render with the new arrowheads/linetypes.

Co-Authored-By: Claude Opus 4.8 <[email protected]>
2026-06-03 20:34:09 +03:00
Hakan SevenandClaude Opus 4.8 df44031ae8 feat(tablestyle): per-cell editing for Data/Header/Title rows
Each row's RowCellStyle is now editable in the Table Style manager:
text style name, text height, text & fill color (ACI), background-fill
toggle, and alignment (cycle through the 9 anchor positions). Margin and
per-cell buffers load on open/select via a shared load_tablestyle_bufs;
edits write through objects.values_mut() and bump geometry so tables
using the style re-render.

Co-Authored-By: Claude Opus 4.8 <[email protected]>
2026-06-03 20:28:58 +03:00
Hakan SevenandClaude Opus 4.8 e0c5db9e0c feat(mleaderstyle): add Multileader Style editor window
New dedicated style-manager window for MultiLeaderStyle objects (the
existing mlstyle window edits MLineStyle, not multileader). Opened via
the MLEADERSTYLE command / ribbon manager entry.

Editable across Leader Format / Structure / Content sections:
- path/content/text-angle/text-alignment enums (cycle buttons)
- line & text color (ACI), arrowhead & break-gap sizes
- landing distance/gap, max points, segment angles, scale factor
- default text, text height
- enable landing/dogleg, text frame, text-always-left, annotative
New/Delete/Set-Current style management.

Co-Authored-By: Claude Opus 4.8 <[email protected]>
2026-06-03 20:25:14 +03:00
Hakan SevenandClaude Opus 4.8 0dd86eb658 feat(tablestyle): editable General section (margins, flow-suppress toggles)
The Table Style editor's General fields are now editable: H/V cell margins
(buffers + Apply) and title/header row-suppressed toggles, loaded from the
selected style on select. Per-cell (Data/Header/Title) text/fill/border
editing remains a follow-up.

Co-Authored-By: Claude Opus 4.8 <[email protected]>
2026-06-03 20:13:30 +03:00
Hakan SevenandClaude Opus 4.8 a21caf821b feat(dimstyle): expand Dimension Style editor to the full field set
Adds the remaining ~40 DIMSTYLE variables across the tabs (and a new
Alternate Units tab): dim/ext line colors+lineweights, fixed-length ext
lines, separate arrow blocks, arc symbol, jog angle, text color/justify/
vertical pos/fill/direction, fit options (DIMATFIT/DIMTIX/DIMSOXD/DIMTMOVE/
DIMUPT/DIMTOFL/DIMFIT), decimal separator, rounding, zero suppression,
fraction + angular units, alternate units, and tolerance vert-just/zero
suppression. Only the arrowhead-block / extension-line-linetype Handle
references are left (they need a block/linetype picker).

Co-Authored-By: Claude Opus 4.8 <[email protected]>
2026-06-03 20:09:08 +03:00
Hakan SevenandClaude Opus 4.8 4675a439da feat(tablestyle): add Annotative toggle to the Table Style editor
The table-style details panel gains an Annotative checkbox that flips the
new TableStyle.annotative flag, rounding out annotative across the Text,
Dimension and Table style editors.

Co-Authored-By: Claude Opus 4.8 <[email protected]>
2026-06-03 17:51:45 +03:00
Hakan SevenandClaude Opus 4.8 07a2a05975 feat(dimstyle): add Annotative toggle to the Dimension Style editor
Adds the annotative property (DsField::Annotative) to the dim-style edit
buffers, load/apply, and a checkbox on the Fit/Scale tab — consistent with
the Text Style editor's annotative toggle.

Co-Authored-By: Claude Opus 4.8 <[email protected]>
2026-06-03 17:49:38 +03:00
Hakan SevenandClaude Opus 4.8 52850947d2 feat(textstyle): full Text Style editor — big/TT font, fixed height, flags, annotative
Expands the Text Style manager beyond font/width/oblique: big-font and
TrueType font fields, fixed text height, Backward / Upside-down flags, and
an Annotative toggle (applied live). Bumps acadrust for the annotative
field.

Co-Authored-By: Claude Opus 4.8 <[email protected]>
2026-06-03 17:43:12 +03:00
Hakan SevenandClaude Opus 4.8 c1b33677e2 feat(fonts): switch the text engine from CXF to LibreCAD LFF fonts
Replace the small QCAD CXF stroke-font set with the full LibreCAD LFF font
library (46 fonts) and a new LFF parser/engine in src/scene/lff.rs. The
parser reads the `[hex] char` glyph blocks, tessellates `,A<bulge>` arcs, and
resolves `C<hex>` glyph references. Per LibreCAD's RS_Polyline convention a
vertex's bulge curves the segment ending at that vertex — getting this wrong
turned round letters like O into sideways capsules.

Font name resolution mirrors LibreCAD: match by file stem, map common
AutoCAD/DXF SHX names (txt, isocp, complex, italic, gothic*, gost, …) to the
nearest LFF family, and fall back to `standard`. A missing glyph in the chosen
family falls back to the broad `unicode` font so accented/Cyrillic/Greek text
still renders. Cap height stays 9 units, so the text scale is unchanged.

All text consumers move from cxf:: to lff::; complex linetypes still render
embedded text but no longer draw embedded shapes (LibreCAD ships no shape
file). The CXF module and every *.cxf asset are removed, and the MText / text
style font pickers list the LFF families.

Co-Authored-By: Claude Opus 4.8 <[email protected]>
2026-05-31 03:31:20 +03:00
Hakan Seven 5755c2e130 refactor(grip): square-only marker set + oriented stretch handles
Phase 1 of bringing the grip vocabulary in line with the standard
CAD convention: drop the per-position-type shape encoding (Diamond
for translate, Circle for parameter) and use a plain square for
every endpoint / vertex / centre grip. The behavioural midpoint vs
vertex distinction stays — it lives on `GripDef::is_midpoint` and
drives `Translate` vs `Absolute` in the grip-edit dispatcher — only
the marker shape collapses.

- `GripShape` keeps `Square`, `Rectangle`, `Triangle`. Diamond /
  Circle are gone.
- `GripDef` gains `dir: Option<[f32; 2]>` — a world-XY direction
  vector consumed by `Rectangle` to orient the box along its
  segment.
- `entities::common` exposes `square_grip`, `center_grip` (same
  square marker, flagged as translate), `rectangle_grip(id, world,
  dir)` for oriented mid-segment handles, and a kept-for-Phase-2
  `triangle_grip`.
- `overlay::GripMarker` / `grips_to_screen[_paper]` thread `dir`
  through to the canvas painter; the Rectangle path rotates the
  box around the grip centre using the world-XY direction (flipping
  the sin for screen-Y).

Every existing `diamond_grip(id, w)` call becomes `center_grip(id,
w)` — the visual change is square-replacing-diamond at line
midpoints / arc midpoints / circle centres / ellipse centres /
viewport / hatch loop centroids / dimension grips / image corners /
multileader / ray / underlay / ole2frame / solid3d.

`LwPolyline` grows a stretch handle on every segment (straight or
arc), drawn as the new oriented rectangle. The grip-edit path
translates both segment endpoints for straight segments and
adjusts the arc bulge from the new midpoint for arc segments.
2026-05-29 02:07:34 +03:00
Hakan Seven 1e33a9049c feat(grip): complete standard grip-shape vocabulary
Existing entity grip definitions already followed the conventional
CAD layout: square at vertices / endpoints, diamond at curve
centres / midpoints, triangle for directional control. Round out
the supported shape vocabulary with the two missing standards so
future entities (polyline straight-segment stretch grips, dimension
parameter grips, …) can pick the right marker without inventing
ad-hoc visuals:

- `GripShape::Rectangle` — direction-aware mid-segment stretch
  handle (wider-than-tall box).
- `GripShape::Circle` — parametric control (radius / dimension
  value).

New `rectangle_grip` / `circle_grip` helpers in `entities::common`
mirror the existing `square_grip` / `diamond_grip` / `triangle_grip`
constructors. `SelectionCanvas::draw` renders the two new variants;
the previously-used Square / Diamond / Triangle paths are
unchanged. Both new variants carry `#[allow(dead_code)]` until an
entity adopts them.
2026-05-29 01:46:33 +03:00
Hakan Seven 0ec6d77cb1 fix(snap): correct snap symbols + drop bogus midpoints on circles (#34)
Two bugs from #34:

1. Hovering a circle showed the Center snap as a diamond instead of
   the conventional circle outline.
2. Hovering a circle also showed Midpoint hits (triangle marker)
   even though a closed curve has no midpoint.

(2) came from a "tessellated curve" fallback in the Midpoint snap
path that produced a midpoint for every chord of the polyline
approximation. Drop that fallback — only entities with explicit
`key_vertices` (Line, LwPolyline) contribute per-segment midpoints
now. Curves that DO have a single well-defined midpoint (arcs, and
later splines) declare it explicitly via a new
`SnapHint::Midpoint`; `arc.rs` emits one at the arc-length centre.

(1) — and the broader "everything past Endpoint / Midpoint / Grid
was a diamond" inconsistency — fixed by giving every `SnapType` a
distinct marker in `SelectionCanvas::draw`:

- Center: hollow circle
- Node: circle with inscribed X
- Quadrant: diamond (unchanged)
- Intersection: X
- Apparent Intersection: X inside a square
- Insertion: two overlapping rectangles (tag glyph)
- Perpendicular: right-angle hook
- Tangent: circle with a bar across the top
- Nearest: hourglass / bowtie
- Extension: three dots
- Parallel: two parallel diagonal bars
- Endpoint / Midpoint / Grid: unchanged

Closes #34
2026-05-29 01:39:02 +03:00