Commit Graph
55 Commits
Author SHA1 Message Date
ramox81andClaude Opus 5.5 0e1e13e524 WIP: Sheet Set Manager palette, wizard, properties and sheet set fields
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-05 09:10:17 +03:00
ramox81andClaude Opus 5.5 0826101c5e Blocks palette: tabs, options, drag insertion and -INSERT
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 <noreply@anthropic.com>
2026-10-01 11:17:38 +03:00
ramox81andClaude Opus 5.5 7f8f8457c7 Frames: state-following ribbon list, DWF/DGN frames, image frame encoding and profile, frame-only picking
- The Frames list shows the drawing's frame state (hide / display and plot /
  display but not plot / frames vary), follows commands, undo and document
  switches, and lists the mixed state as a disabled item.
- DWFFRAME and DGNFRAME are frame variables of their own, kept in the header,
  and FRAME sets them with the others.
- Out-of-range frame values say "Requires an integer between 0 and 2." and
  ask again; a set value reports "Regenerating model.".
- IMAGEFRAME is stored in the image variables as bits (2 is written as 3) and
  a drawing without them uses the profile value, which setting IMAGEFRAME
  updates and the settings file keeps.
- Raster images, PDF underlays and wipeouts are picked on their frame only;
  underlay snap geometry is never picked.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-28 10:53:53 +03:00
ramox81andClaude Opus 5.5 5a31d2089a Selection tools on the right-edge toolbar instead of contextual tabs
The PDF Underlay and External Reference ribbon tabs are gone. While only
PDF underlays are selected their tools (Display in Monochrome, Create
Clipping Boundary, Remove Clipping, Show Underlay, Enable Snap, External
References, Edit Layers, Import As Objects) sit on the right-edge toolbar,
the switches drawn as on while on; while only xrefs are selected the xref
tools do. Contrast and fade stay in Properties. Toolbar tooltips are
translated.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-25 14:25:22 +03:00
Hakan SevenandClaude Opus 5.5 f537aff75c feat: node graph overlay; move to opencadcodec/opencadkernel/opencadgraph
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 <noreply@anthropic.com>
2026-09-25 07:34:23 +03:00
Hakan Seven 0ea8599f86 Merge pull request #1476 from ramox81:codex/insert-reference-panel 2026-09-24 23:48:30 +03:00
ramox81andClaude Opus 5.5 95e2bae0d2 Insert Reference panel: one Attach, labelled underlay tools, slide-out with Edit Reference and xref fading
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-24 19:39:23 +03:00
ramox81andClaude Opus 5.5 3f6bdf8c59 PDF underlays: attach dialog with pages, underlay tab, layers, import settings and file import, unload on the definition
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-24 18:31:40 +03:00
ramox81andClaude Fable 5.1 aab42e2aa9 DCRADIUS: reference radial dimensional constraint with a dynamic radial dimension
Select arc or circle / Dimension text / dimension line location / value or
name prompts with a radN parameter, invalid-selection, miss, duplicate and
invalid-expression messages, negative values as magnitudes, a dynamic radial
dimension on the constraints layer drawn as the reference does (mid-radius
text on the center-to-rim line, no hook, no center mark, one text grip), the
stored text position following the radius, center-anchored resizing, the
Properties title and Constraint section, DIMCONSTRAINT's Radius default,
the small-button Dimensional ribbon grid and tooltip descriptions.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
2026-09-22 13:09:47 +03:00
Karim Jerbi dcc05f310d perf(statusbar): cache layout/scale derived data behind epochs (major)
Status bar rescanned the whole object map twice per frame (layout_names +
scale_picker_list), deep-cloned an already-cached Arc, and built two
undo/redo label vecs consumed ~never. Cache layout names (epoch key) and
scale picker (epoch + unit-factor + imperial-family + current-scale key)
as Arc behind choke-point invalidation (layout/scale impl methods,
undo/redo swaps, file-open, doc-reset); borrow across the widget boundary
(owned-Arc params; E0515 forbids &'a slices over call-site temporaries);
build undo/redo labels only when their dropdown is open.

Tests:
- cached_layout_names_returns_same_arc_until_bump: hit-path Arc identity
- cached_layout_names_invalidated_by_add_layout: bump yields new Arc + names
- cached_scale_picker_returns_same_arc_until_bump: hit-path Arc identity
- cached_scale_picker_invalidated_by_add_scale: bump yields new Arc + scale
- cached_scale_picker_invalidated_by_current_scale_change: key completeness

Bench (cargo bench ui_statusbar_derived_data, 3k entities): cached hit below
timer granularity vs ~1us uncached scans, PASS (50us threshold).
2026-09-21 22:31:16 +01:00
Hakan Seven 7b4cef41f7 Complete parametric ribbon and constraint tools 2026-09-14 01:05:39 +03:00
ramox81 14b98231f5 Align spline fit properties and menu arrows 2026-09-11 15:53:51 +03:00
Hakan Seven 9b58ca8a93 Harden parametric sketch constraints 2026-09-11 09:45:57 +03:00
Felix Riestra e2d39b049d Merge branch 'main' into feature/parametric-constraint-system
# Conflicts:
#	src/app/automation.rs
#	src/app/mod.rs
#	src/ui/ribbon/widgets.rs
2026-09-09 13:35:07 +02:00
Felix RiestraandClaude Sonnet 5 63a74b19a9 Add persistent sketch-constraint system (ocs_gcs port) and named-parameters handoff docs
Ports FreeCAD's planegcs 2D geometric constraint solver to Rust as a new
crates/ocs_gcs workspace member, and wires it into the document/scene model
as a persistent SketchConstraintSet: Coincident, Horizontal/Vertical,
Parallel/Perpendicular, Equal, Tangent, Distance, Angle and Radius
constraints that re-solve live (including mid-drag, not just on release),
render glyphs and a DOF badge, flag conflicts with a one-click resolver
pill, and round-trip through save/load via an XRecord blob.

Also includes docs/command_reference.md (a statically generated reference
of every registered command and its prompt sequence) and
docs/named_parameters_design.md + docs/backlog.md, which hand off the next
queued feature (a named-parameter/expression table) and consolidate every
deliberate scope-down and open gap found along the way, so a fresh session
has a complete starting point.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-09-08 22:19:23 +02:00
Hakan Seven 5b663bfe38 Fix issues found while integrating contributor PRs 2026-09-08 12:14:28 +03:00
JonathanandCopilot 8497abecfd Fix ribbon command labels wrapping in the middle of words
Replace Wrapping::WordOrGlyph with Wrapping::Word to prevent labels
like 'Dimensions' from breaking as 'Dimensio' + 'ns'. Word-only wrapping
ensures labels only wrap at word boundaries.

Fixes #1046

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
2026-09-08 08:34:58 +02:00
Karim Jerbi 50cb21e4d4 refactor(ribbon): make StyleContext borrowed to avoid 8 clones per view
Replace the 8 owned clones in StyleContext construction (4 Vec<String>
+ 4 String) at ribbon/mod.rs:568 and :1059 with borrowed refs.
StyleContext is now StyleContext<'a> with &'a [String]/&'a str
(widgets.rs:313), RenderCtx holds &'a StyleContext<'a> (:633),
and call sites pass &self.x instead of .clone(). The view-local
borrow is valid for the duration of Ribbon::view() and the style
dropdown overlay.

TDD: RED style_context_tests failed E0308 (owned vs borrowed),
GREEN added lifetime and updated 4 type sites + 2 construction sites.
2026-09-02 18:20:29 +01:00
Karim Jerbi 452749f58c fix(ribbon): align combo panel dropdowns to a shared baseline
Style selectors (Standard, layer, Color/Linetype/Lineweight) sat at
different heights across ribbon panels because each combo panel
vertically centered its content: panels with fewer icon rows
(Multiline Text, Table) centered their dropdown differently than
panels with two rows (Dimensions, Multileader).

- Pin all combo panels (Layers, Properties, style combos) to the top
  of the fixed 3-row panel with a shared COMBO_PANEL_PAD, so every
  primary dropdown shares one baseline regardless of icon-row count
- Extract the duplicated tool-row and panel-container code into
  tool_row() / combo_panel_col() helpers + named spacing constants
- Bundle the per-view render state into RenderCtx, shrinking
  render_large/render_large_dropdown from 12-14 positional args to
  (item, &ctx)
- print_to_printer: silence the Windows-only dead-code warning on
  PrintOptions::quality with the platform split documented (the field
  is read by the CUPS `lp -o print-quality` path)
2026-08-29 11:35:06 +01:00
Hakan Seven 3024869de0 fix(i18n): localize linetype inheritance 2026-08-29 10:10:39 +03: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 SevenandClaude Opus 5 f7590b1aa8 feat(plugin-api): let add-ons ask for a visual style by name
Removing the binary wireframe event left add-ons with no way to set a
visual style except by spelling out a command string. Give them the
intent back, in the vocabulary everything else now speaks.

The name is carried as text rather than the render-mode type: this crate
is dependency-free by default and only pulls acadrust in behind the host
feature, which is not a weight to add to the manifest contract for one
enum. The host resolves it against the same list its ribbon, its picker
and its commands read, so an add-on can offer exactly the styles the
application does and no others. An unknown name says so and lists the
ones that exist, from that same list.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-07 14:29:01 +03:00
Hakan SevenandClaude Opus 5 b5a1146966 feat(view): one list of visual styles behind every way of choosing one
The ribbon offered four styles and dispatched each one's id as a command.
Two of those ids were not visual-style commands: "Shaded" carried SOLID,
which draws a 2D filled polygon, so choosing it started a draw command;
"Hidden" carried HIDDEN, which matched nothing at all, so it did nothing.
The intent had been for the button to fire its tool's event, but the
dropdown never reads one -- it dispatches the id.

Behind that sat two generations of the same feature. The render-mode
picker offered the seven styles a viewport can actually be drawn in;
everything else -- the ribbon, VSCURRENT, SHADEMODE, VISUALSTYLES and a
handful of bare verbs -- went through a binary wireframe-or-shaded flag
that could only approximate them, reporting "Hidden (shown shaded)" and
"X-Ray (shown as wireframe)" when asked for something it had no way to
draw. Four descriptions of one choice, each drifting on its own.

There is one list now. Each style names itself once -- mode, label, icon,
and the command that applies it -- and the ribbon, the picker, the
VISUALSTYLES verb and the interactive prompt all read from it, down to
the line that lists the choices, so what is offered cannot disagree with
what works. Keywords are the render modes' own names, since there is one
set of styles left to name.

The binary path is gone rather than kept alongside: its message, its
module event, the tool definitions that produced it, the ribbon's
special-cased highlight arms, the bare style verbs and the older keyword
spellings. X-Ray goes with it -- no render mode draws one, and it was
already coming out as a plain wireframe. Three files that had been left
holding a single icon constant each fold into the list.

Note: ModuleEvent::SetWireframe leaves the plugin API with it.

Closes #621

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-07 14:15:59 +03:00
Hakan Seven deaecdfb1e fix(ribbon): mask tools on start
Refs #494

Refs #507
2026-08-05 00:52:52 +03:00
Hakan Seven d1f9055901 feat(ui): refine ribbon and view navigation 2026-08-04 18:21:52 +03:00
Hakan Seven 3e6693b93f feat(locale): localize full interface 2026-08-02 22:09:25 +03:00
Hakan Seven 02d15f5d23 feat(ribbon): add layer isolation tools
Closes #589
2026-07-30 18:07:06 +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 28d8246c68 feat(ui): add discussions and semantic theming
Generate web discussion snapshots in CI; native builds use the public
feed and an offline cache.
2026-07-28 11:49:45 +03:00
Hakan Seven 4bf14baea4 feat(ui): add configurable Iced themes 2026-07-28 09:33:12 +03:00
Hakan SevenandClaude Fable 5 b7457ba09d fix(ribbon): highlight follows each tool's mechanism; start-tab dimming (#355)
Tool highlights used to stick: every click set active_tool, but only
interactive commands and a hand-maintained per-modal list ever cleared
it, so one-shots (Cleanup/AUDIT, view actions) and unlisted dialogs
(Customization/ALIASEDIT, CUI, Plugin Manager…) stayed blue forever.

Now the rule is mechanical: state toggles light from state only (the
click highlight drops immediately), interactive commands stay lit
while running, dialog openers stay lit until the modal closes (generic
clear replaces the per-modal list), and one-shots never keep it — the
dispatch site turns the highlight off when nothing stayed running.

On the Start tab, tools whose command the start gate refuses now render
dimmed (grey icon + label) across all button styles, dropdowns and the
quick-access strip; start_allowed() is the single shared authority.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-22 00:13:48 +03:00
Karim Jerbi 8ef65f59f8 fix(ribbon): highlight toggle buttons by their actual state
The UCS Icon, Properties, File Tabs, and Layout Tabs buttons were highlighted unconditionally because their ids fell through to an active_tool equality check in is_active_tool, which activate_tool sets on every click and never clears. Each id is now mapped to its corresponding visibility flag (show_ucs_icon, show_properties, show_file_tabs, show_layout_tabs), and those flags are kept in sync from their toggle handlers so the highlight reflects live state. The per-toggle booleans previously threaded through the render path are consolidated into a single ToggleState struct read from one place, so introducing a further toggle no longer requires changing every render-function signature and call site.
2026-07-12 19:53:48 +03:00
Karim Jerbi 585316945e fix(ribbon): highlight View Cube button by toggle state
NAVVCUBE is a command toggle, so it never set active_tool and is_active_tool never matched it. Add a show_viewcube flag to the ribbon (mirroring wireframe/ortho_mode) and special-case "NAVVCUBE" in is_active_tool to return the live show_viewcube state; ToggleViewCube now calls ribbon.set_viewcube.
2026-07-11 00:40:22 +01:00
Hakan SevenandClaude Opus 4.8 f4ed263425 feat(ui): ribbon collapse-mode selector + start-page recent controls
Ribbon:
- A ▾ selector at the right of the tab row picks the tool-panel density —
  Auto (size to window), Full, Compact, or Collapsed. The choice is persisted.
  It hides itself when the tool row is already tight, giving the cramped tab
  row its space back.

Start page:
- The Recent Documents card is restyled to match the Supporters card
  (rounded corners, 20px padding, matching title + colours).
- Its scrollbar no longer sits on top of the row ✕ remove buttons (a gutter
  is reserved).
- A footer control sets how many recent files to keep: [-] an editable count
  [+] with the max shown. Typing applies on Enter; an over-max entry snaps to
  the max. The limit is persisted and enforced on load and on every open.
- The "Support on Patreon" heart is now the SVG icon instead of a font glyph.

Config:
- Add a shared `config::config_dir()` helper; the recent-files and status-bar
  stores now go through it instead of each re-deriving the path. New minus.svg
  icon for the stepper.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-06 01:06:01 +03:00
Hakan SevenandClaude Opus 4.8 8e6146fd91 feat(ribbon): tighten + squeeze collapsed panels, content-driven height
Adaptive tool-panel row now keeps degrading past the collapsed state instead
of overflowing:

- Panels still shrink from the right one at a time (full -> compact ->
  collapsed). Once every panel is a collapsed button and the row still
  overflows, each button drops its large icon to a small one (tight) together,
  then the buttons are pulled together up to 8px per gap (reclaiming edge
  padding) before anything is clipped.
- Tool-area height now tracks the tallest shown panel, so the ribbon shrinks
  as its panels collapse; the measured height is reported for dropdown
  anchoring.
- Tabs squeeze their inter-tab gaps shut before wrapping to a new row
  (WrapFlow min_spacing_x).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-05 23:58:18 +03:00
Hakan SevenandClaude Opus 4.8 6a5402ccae fix(ribbon): Properties panel compact/collapse, undo-redo anchoring, restore panel dividers
- The Properties panel's Match button now shrinks to a small icon when the
  panel is compacted (render_large gained a `compact` flag), so the panel
  actually gets narrower and joins the from-the-right degradation instead
  of jumping straight to collapsed.
- A collapsed Properties panel now shows its Match button as the
  representative face: item_id recognises PropertiesGroup and
  collapse_button renders its match_prop as a large tool.
- The undo/redo history controls are wrapped in PosReport, so their
  dropdowns anchor directly below the button (and flip at the edge) like
  every other dropdown, instead of falling back to the corner.
- Panel dividers are back: CollapsePanels draws a 1px line between adjacent
  panels, skipped only between two collapsed panels.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-05 19:23:48 +03:00
Hakan SevenandClaude Opus 4.8 39043e6e56 feat(ui): anchor every ribbon dropdown and status-bar popup to its widget, flipping at window edges
All ribbon dropdowns (tool dropdowns, undo/redo history, and the layer /
colour / linetype / lineweight / style combos) and all status-bar popups
(scale, units, OSNAP, isolate, filter, customization menu, layout list)
now open directly at their widget instead of at a layout-estimated
position, and flip to the other side when the panel would cross a window
edge.

Each dropdown/pill widget is wrapped in a transparent PosReport that
records its screen bounds into a thread-local map on draw. The overlays
read those bounds:
- Ribbon: Ribbon::dd_anchor(id, panel_w, win_w) returns
  (align_right, h_pad, top); position_ribbon_dropdown places the panel
  below the widget, flipping right-aligned near the right edge.
- Status bar: popup builders take (pill_bounds, win_size) and call
  popup::position_statusbar_popup / popup_anchor, opening just above the
  pill and flipping left/right at the window edge.

The window size is now tracked (win_size, set on WindowResized). The old
layout estimators compute_dropdown_left / compute_layer_combo_left /
compute_prop_combo_left / compute_history_dropdown_left and
osnap_popup_right_offset are deleted.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-05 18:51:54 +03:00
Hakan SevenandClaude Opus 4.8 56e48b8d0f feat(ribbon): collapse overflowing panels to flyout buttons, anchor dropdowns to their widget
Third stage of the adaptive tool area (shrink -> compact -> collapse).
When even the compact panels don't fit, DensitySwap picks a new
CollapsePanels widget that keeps a left prefix of panels inline and
collapses the rest to buttons; clicking a button opens the full panel as
an overlay flyout anchored below it (closes on outside press, mirroring
color_select's Floating).

A collapsed panel's button shows a live representative tool — the panel's
last-used tool (tracked per panel in Ribbon::note_panel_tool on every
tool click), defaulting to its first — rendered as a large icon. To
support this, render_small now also renders Large* items small and
render_large now renders plain Tool/Dropdown items large. Large dropdowns
render as icon + label + a bottom arrow strip via a shared
render_large_dropdown helper, used in both the full ribbon and collapsed
panels.

Ribbon dropdowns (tool dropdowns + undo/redo history) now anchor their
overlay directly below their widget at any size: a transparent PosReport
wrapper records each dropdown button's screen bounds into a thread-local
map on draw, and the overlays read it via Ribbon::dd_anchor instead of the
layout-estimating compute_*_left helpers.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-05 18:04:55 +03:00
Hakan SevenandClaude Opus 4.8 65dfd4e462 feat(ribbon): shrink large tools to compact icons when the ribbon is narrow
Add a DensitySwap widget that renders the widest variant of the tool
area that fits the current width. The ribbon builds two variants via the
new build_tool_row(compact) helper: full-size panels, and a compact one
where LargeTool/LargeDropdown collapse to small icon columns (the
layer/properties/style combos always stay full). render_small now also
matches the Large* variants so they can be drawn small.

First stage of the adaptive tool area (shrink -> wrap -> collapse).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-05 16:44:44 +03:00
Hakan SevenandClaude Opus 4.8 7bab7c7b8d feat(ui): replace app-menu logo with a quick-access file toolbar
Remove the OCS-logo button and the dropdown menu it opened; the top strip
now shows direct New / Open / Save / Save As / Print buttons ahead of the
undo/redo controls. Drop the HELP and OPTIONS commands (HELP dumped text to
the command line, OPTIONS aliased the drafting-settings popup).

The app-menu overlay is gone, so its rendering code, MENU_ITEMS, four dead
messages, and the LOGO_RED / GEAR / HELP assets are removed. The recents
list it held is the only survivor — moved into OpenCADStudio.recent_files
via a new app/recent.rs, backing the Start page's Recent Documents panel.

Quick-access icons are redrawn in a cleaner style (file-plus, folder-open,
device-floppy, file-export, printer) and tinted light so they read on the
dark strip; FOLDER / DOC keep their old glyphs for the file browser.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-03 09:51:49 +03:00
Karim Jerbi 73b05e1dec perf(core): cache ribbon_groups() with OnceLock, avoid per-frame tree allocations
Change CadModule::ribbon_groups() from -> Vec<RibbonGroup> to -> &[RibbonGroup],
backed by a per-module OnceLock cache. The ribbon group tree is static data
(&'static str, Copy enums) that was being fully reconstructed — Vecs, String
clones, enum discriminants — on every call, including all three per-frame
call sites (view(), dropdown_overlay(), style_combo_overlay()).

- 7 built-in modules + 2 plugin templates cache via function-local OnceLock.
  Safe because each is a unit struct with exactly one instance per process
  (plugins run in isolated child processes; see PluginProcess::spawn()).
- SharedCadModule avoids the static pattern entirely, storing groups in an
  instance field (owned.rs).
- IPC runner converts &RibbonGroup -> OwnedRibbonGroup directly via new
  From<&T> impls, avoiding an intermediate clone.
- render_small/render_large and the two make_tool_row closures now borrow
  (&RibbonItem, &[ToolDef]) instead of taking ownership, so the view loop
  doesn't need to clone items to satisfy the old by-value signatures.
- Various match-ergonomics deref fixes (*id, *default, *icon, etc.) from
  the &RibbonItem pattern change.
2026-07-02 21:00:57 +01:00
Hakan SevenandClaude Opus 4.8 f88c2f8327 style(ribbon): cargo fmt after PR213 merge
PR #213 introduced rustfmt drift in tip_style / swatch indentation and an
inline if-expression in two previously fmt-clean files. Format pass only;
no behaviour change.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-29 01:19:05 +03:00
Karim Jerbi 63c13f0f63 refactor(ribbon): extract repeated inline color literals into named constants
Consolidates 21 occurrences of identical Color literals scattered across widgets.rs and mod.rs into 9 named constants (COMBO_BG, COMBO_HOVER_BG, COMBO_OPEN_BG, COMBO_BORDER, COMBO_ACTIVE_BORDER, COMBO_ARROW, SWATCH_BORDER, TIP_BG, HIST_INACTIVE_BG). -85 net lines, zero behaviour change.
2026-06-28 22:59:14 +01:00
Hakan SevenandClaude Opus 4.8 73497850e2 fix(ribbon): float annotate style dropdowns so they aren't clipped (#153)
The text / dimension / multileader / table style combos rendered their
open list inline inside the ribbon row, so the popup was clipped to the
fixed ribbon-row height and got cut off even with only two entries. The
Draw-tab dropdowns and the layer combo avoid this by rendering as
floating overlays.

Render the style list as an overlay too: the combo now draws only its
button inline, and a new `style_combo_overlay` builds the list as a
floating panel that grows to fit its entries, positioned with the
existing `compute_dropdown_left` (which already accounts for
StyleComboGroup widths) and mirroring `layer_combo_overlay`.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-25 18:35:49 +03:00
Sebastian d0003534a0 Fix 5: Allow backward-compatibility and add plugin-template-v2 2026-06-25 00:02:17 +03:00
Hakan SevenandClaude Opus 4.8 3fc51af41c fix(ribbon): anchor tooltips to the right of their button
Ribbon tooltips were centered below the button, so the cursor resting on
the button covered the tip text. Anchor them to the right instead, clear
of the cursor. (#143)

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-20 11:59:20 +03:00
Hakan SevenandClaude Opus 4.8 864dd6cef7 fix(web): render UI icons as SVG instead of font glyphs
UI chrome (dropdown carets, undo/redo, checkmarks, close/menu/osnap,
layer/file-menu icons) and ribbon tool icons were drawn as Unicode
glyphs. Desktop fills missing glyphs via system-font fallback, but the
web build bundles only Fira Sans with no fallback, so they rendered as
empty tofu boxes (issue #116).

Add a shared src/ui/icons.rs (SVG-backed, tintable) plus bundled assets,
and switch every glyph site and IconKind::Glyph tool def to SVG.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-18 12:29:32 +03:00
Hakan SevenandClaude Opus 4.8 50825b6346 feat(plugin): ModuleEvent::PluginFileDialog for native file import
Add-ons had no way to request a file picker — only the host's own Open
dialog. PluginFileDialog lets a plugin tool ask the host to open a native
picker; on selection the host dispatches "<command> <path>" back to the
plugin with original case preserved (bypassing the command-line
upper-casing that mangles case-sensitive paths on Linux/macOS). The demo
plugin gains an Import tool exercising it.

Part of the #100 extensibility epic (surfaced in #106).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-17 10:22:08 +03:00
Hakan SevenandClaude Opus 4.8 b7c5103891 feat(ui): show RGB for unnamed palette colours instead of "Index"
Picking a colour from the full palette showed a generic "Index" label.
Add color_display_name: standard names for ACI 1-9 / ByLayer / ByBlock,
"R,G,B" (0-255) for every other indexed or true colour. Used by the shared
colour selector button and the ribbon colour combo.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-14 14:27:35 +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 <noreply@anthropic.com>
2026-06-05 00:35:53 +03:00