- paper_entity_extents() computes the bounding box of actual DXF entities
so the white fill always matches the drawn title-block / frame borders,
regardless of whether Layout min/max_limits match entity positions
- Falls back to paper_limits() (→ A4 297×210) when layout has no entities
- Removed paper_boundary_wire: the white fill now acts as the visual paper
edge so the near-white wire (invisible on white) was redundant
- LayoutCreate sets limits to A4 landscape immediately after add_layout()
to override acadrust's imperial default (12×9)
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Add orbit_active_viewport(), snap_active_viewport_to_angles(),
active_view_rotation_mat(), active_viewport_yaw_pitch() helpers so
navigation gestures modify the DXF viewport entity's view_direction
instead of the paper-space camera.
- Fix "already there → flip opposite" check: the previous code used
rot * Vec4::W (always (0,0,0,1) for a rotation matrix); now reads
(yaw, pitch) directly from camera_for_viewport() via the new helper.
- MSPACE right-drag orbit early-returns after writing the viewport
entity, preventing the paper-space camera from also being modified.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- REPORT opens GitHub new-issue page
- ABOUT opens a dialog window with version, OS and arch info + Copy Info button
- CHANGELOG opens GitHub releases page
- Fix Windows build: add windows-sys as target-specific dependency for PRINT command
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
New StyleComboGroup RibbonItem renders a dropdown combobox for selecting
text style, dimension style, multileader style, or table style. Ribbon
groups in the Annotate tab now match the reference layout: each group
has a large tool on the left and a style combobox with tool rows on the
right.
Each combobox shows the active style name, opens a scrollable item list
on click, and has an optional "Manage…" row that fires the style manager
command (STYLE / DIMSTYLE / MLEADERSTYLE / TABLESTYLE).
Style state is synced from the document on every layer refresh via
sync_ribbon_styles(). RibbonStyleChanged message propagates selections
back to the acadrust document header and the active_mleader_style field.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
New dimension commands: QDIM, DIMEDIT, DIMTEDIT, DIMBREAK, DIMSPACE,
DIMJOGLINE with full command workflows and SVG icons.
New multileader commands: MLEADERADD, MLEADERREMOVE, MLEADERALIGN,
MLEADERCOLLECT with entity injection pattern for in-place editing.
Updated annotate ribbon: all tools exposed across Text, Dimensions,
Leaders, Tables, Markup, and Annotation Scaling groups. Added STYLE,
FIND, DIMSTYLE shortcut buttons.
Added `inject_picked_entity` to the CadCommand trait for commands that
need a cloned copy of the picked entity to modify (DIMTEDIT, MLEADERADD,
MLEADERREMOVE). Sentinel-based dispatch in cmd_result.rs handles
DIMBREAK, DIMSPACE, DIMJOGLINE, MLEADERALIGN, and MLEADERCOLLECT.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Every dialog panel that previously rendered as an in-viewport overlay is
now opened as its own OS window, matching the behaviour of the Layer
Properties Manager:
• Page Setup (520×460, non-resizable)
• Text Style (620×460)
• Table Style (620×420)
• Multiline Style (620×420)
• Layout Manager (640×320)
• Plot Style Editor (780×540)
• Dimension Style Mgr (720×560)
• Keyboard Shortcuts (720×520)
Changes:
- mod.rs: replace *_open: bool fields with *_window: Option<window::Id>;
add window IDs to OsWindowClosed tracker; add per-window title strings.
- update.rs: Open handlers call window::open(); if already open, call
window::gain_focus() instead of reopening. Close handlers call
window::close(). OsWindowClosed clears all panel window IDs.
- view.rs: each window_id is matched at the top of view() and returns
the panel content directly. All overlay let-bindings and stack![]
references removed.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Adds STEPOUT / STPOUT / EXPORTSTEP command that exports all tessellated
Solid3D / Region / Body meshes to an ISO 10303-21 (STEP AP203) file.
Each triangle is encoded as a minimal ADVANCED_FACE with a PLANE surface
and CLOSED_SHELL topology — sufficient for import into all major CAD systems.
A file-save dialog picks the output path; the command line reports success or
errors. Requires at least one tessellated solid in the drawing.
Closes ROADMAP 14.10.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
The PRINT command renders the current layout to a temporary PDF (reusing
the existing PDF export pipeline) and dispatches it to the OS default
printer:
- Linux/macOS: `lp` (CUPS) with `lpr` as fallback.
- Windows: ShellExecute "print" verb (compiled-in, unused on Linux).
PLOT and EXPORT still open the save-file dialog as before.
Status messages are shown in the command line during the async job.
Closes ROADMAP 1.8.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Opens a reference panel listing all built-in keyboard shortcuts
(F3-F12, Ctrl+N/O/S/Z/C/X/V, etc.) and any user-defined overrides.
SHORTCUTS LIST — open the panel
SHORTCUTS SET <k> <c> — add/update a custom shortcut label
SHORTCUTS CLEAR <k> — remove a custom entry
Custom shortcuts are stored in app state (runtime only) and shown
in the panel alongside the hardcoded bindings.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Adds active_theme: Theme field to app state and wires the daemon's
.theme() callback to use it dynamically. COLORSCHEME <name> switches
among all 19 built-in iced themes (Dark, Light, Dracula, Nord, Tokyo
Night, Gruvbox, Kanagawa, Moonfly, Nightfly, etc.).
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Panel overlay showing all layouts with their active status.
Supports: select, rename, new, delete, reorder (◀▶), set current.
Also adds Scene::swap_layout_order() for tab-order resequencing.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Opens a panel overlay showing all 255 ACI entries with their current
overrides (color, lineweight, screening). Allows editing entries
interactively, creating a new identity table when none is loaded,
and saving the modified table back to a CTB/STB file.
Commands: PLOTSTYLEPANEL, PLOTSTYLEEDITOR, STYLESMANAGER
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Parses Wavefront OBJ files (v/vn/f, fan-triangulation, face normals
fallback) and inserts the result as a Solid3D placeholder + MeshModel
visible in the 3D viewport.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Exports all tessellated 3D mesh models in the current drawing to a
binary STL file via a save-file dialog. Normals are taken from the
MeshModel where available, otherwise computed from triangle vertices.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Viewport right-click now shows a proper widget-based context menu:
- When a command is active: Cancel / Enter
- Otherwise: Repeat last commands, Delete/Move/Copy (if selected),
Select All, Zoom Extents
CONSTRUCTIONLINE added as an alias for XLINE (XL).
Canvas-drawn placeholder removed; context menu closes on Escape,
click-outside, or when any action is taken.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- snap/mod.rs: Snapper gains otrack_enabled, tracking_points, dwell state;
update_otrack_dwell() acquires a snap point after DWELL_THRESHOLD=4
consecutive moves near the same position; otrack_snap() returns an
H/V alignment snap position; clear_tracking() resets state on command end
- overlay.rs: selection_overlay accepts ost_points + cursor_screen;
draws light-blue dashed H/V lines from acquired points + small cross marker
- statusbar.rs: OTRACK pill (F11) added next to DYN
- view.rs: projects tracking_points to screen, passes to selection_overlay
- update.rs: calls update_otrack_dwell + otrack_snap in ViewportMove;
overrides effective point with OST alignment when no normal snap is active
- ROADMAP.md: Object Snap Tracking marked ✅
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- overlay.rs: dynamic_input_overlay() canvas widget draws a semi-transparent
coordinate tooltip near the cursor; shows X/Y in absolute mode or
dist/angle relative to last_point when a command base point exists
- statusbar: DYN toggle pill with F12 tooltip (calls ToggleDynInput)
- app/mod.rs: dyn_input: bool field (default true), ToggleDynInput message
- view.rs: builds DYN label and pushes overlay into viewport_stack when
dyn_input=true and a command is active
- document.rs: last_cursor_screen: iced::Point — updated on every ViewportMove
- ROADMAP.md: Dynamic Input overlay marked ✅
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- src/modules/insert/wblock.rs: extract_block_to_doc() copies a named
block's entities into a fresh CadDocument; extract_entities_to_doc()
does the same for a selection set; layer definitions are carried over
- WBLOCK <name> writes the named block; WBLOCK * writes selected entities
- WblockSave / WblockSaveResult messages drive the async save-dialog flow
- ROADMAP.md: 1.10 WBLOCK marked ✅
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Grid snap (F9):
• snap spacing now tracks the visible grid zoom level — computed via
compute_grid_step() (same adaptive pow-of-5 logic as draw_grid),
updated on every ViewportMove so zooming in/out keeps snap aligned
with the grid lines on screen
Polar tracking (F10):
• configurable angle increment stored in polar_increment_deg (default 45°)
• right-click the POLAR pill to cycle through 15 → 30 → 45 → 90°
• pill label shows current angle ("POLAR 45°")
• visual guide line: while drawing with polar on, a dashed cyan line is
drawn from last_point along the snapped direction across the viewport
• SetPolarAngle message + handler; all polar_constrain() calls use the
stored increment instead of the hardcoded 45°
ROADMAP updated: Grid snap and Polar tracking marked ✅.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Add HATCHEDIT (HE alias) command. Works on pre-selected hatch or via
entity pick. Accepts text options: P <pattern>, S <scale>, A <angle>.
Enter applies changes; rebuilds hatch entity and GPU model via add_hatch.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Add DDEDIT (ED alias) command that edits Text/MText/Attribute entities
in-place via the command line. Double-clicking a text entity in model space
now auto-launches DDEDIT for that entity. Supports Text, MText,
AttributeDefinition, and AttributeEntity types.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
CommandLine now records every submitted command in a recall list (up to
50 entries). Pressing ↑ in the command input walks back through the
list, ↓ moves forward, and returning to the newest position restores
the draft text the user had typed before navigating.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Add VP freeze/thaw toggle columns to the layer panel when in a paper
space layout. Each viewport gets its own column (VP 1, VP 2, …) showing
a freeze icon per layer. Clicking toggles frozen_layers on the Viewport
entity and syncs back to the panel.
- scene: viewport_list() → [(handle, label, frozen_handles)]
- LayerPanel: VpCol + vp_frozen per layer, sync_with_viewports()
- Message::LayerToggleVpFreeze(layer_idx, vp_col_idx)
- Sync VP columns on layout switch, VPLAYER cmd, undo/redo, layer ops
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- STYLE DIALOG / TEXTSTYLE DIALOG opens the Text Style Font Browser
- Three-panel dialog: style list | built-in CXF font list | properties
- Properties panel: font file text field, width factor, oblique angle
- Apply button commits edits; Set Current sets the active text style
- Built-in font picker (20 CXF fonts from assets/fonts/) auto-applies
font to the selected style on click
- Preview pane shows "AaBbCc 0123" sample text
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- TABLESTYLE/TS command: LIST, NEW subcommands for managing table styles
- Table Style Manager dialog: style list with details panel showing
name, margins, suppression flags, and row styles (data/header/title)
with text style, height, and alignment per row type
- New / Delete buttons in the dialog
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- MLSTYLE command: LIST, NEW, SET, DEL subcommands
- Multiline Style Manager dialog: style list, element details (offset,
color, linetype), Set Current / New / Delete buttons
- MLINE/ML command now reads document header.multiline_style to apply
the current style to newly created MLine entities
- MlineCommand.with_style() constructor for style-aware multiline drawing
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- src/io/plot_style.rs: PlotStyleTable and PlotStyleEntry data structures;
CTB reader (deflate/zlib decompressed text format) with ACI→RGB and
ACI→lineweight lookup; CTB writer (zlib compressed); LW_TABLE constant
- src/io/pdf_export.rs: accept optional PlotStyleTable; apply ACI color
and lineweight overrides during PDF rendering
- src/scene/wire_model.rs: add `aci: u8` field to carry ACI index
- src/scene/render.rs: render_style() now returns ACI alongside RGBA
- src/scene/mod.rs + tessellate.rs: propagate aci through wire building
- app: PlotStyleLoad/Loaded/Clear messages and handlers;
PLOTSTYLE LOAD | CLEAR | STATUS command; active_plot_style state on H7CAD
- flate2 added as dependency
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Add DimStyleDialogOpen/Close/Apply/Select/Tab/New/SetCurrent/Delete
messages and DsEdit/DsToggle with DsField enum for fine-grained edits
- Store active dialog state (selected style, current tab, edit buffers)
directly on H7CAD for all 28 most-used DimStyle properties
- dimstyle_overlay: 5-tab modal panel (Lines, Arrows, Text,
Scale/Units, Tolerances) with style list, Apply and Close buttons
- DIMSTYLE / DDIM with no sub-command now opens the dialog;
DIMSTYLE LIST / NEW / SET sub-commands remain available
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Add `active_ucs: Option<Ucs>` per-tab state to DocumentTab
- Add `ucs_to_wcs`, `wcs_to_ucs`, `ucs_z_axis`, `ucs_rotated_z` helpers
- Add `Camera::pick_on_plane` for ray–plane intersection against any plane
- Mouse picks project onto the active UCS XY plane instead of world XY
- Typed coordinates are converted from UCS space to WCS before dispatch
- UCS command now really activates/deactivates a UCS:
- `UCS W` resets to WCS (clears active_ucs)
- `UCS <name>` activates a named UCS
- `UCS SAVE <name>` saves the current active UCS
- `UCS ORIGIN x,y,z` shifts origin (in current UCS space)
- `UCS X/Y/Z <angle>` rotates the UCS around its own axes
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- properties.rs: inject 'UCS Name' Choice property for viewports when
document.ucss is non-empty; resolves current handle to display name
- update.rs: intercept PropGeomChoiceChanged for 'vp_ucs_name'; clones
UCS origin/x_axis/y_axis into viewport and sets ucs_handle — no
trait signature change required
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
PageSetup panel:
- Paper size presets (A4/A3/A2/A1/A0 portrait+landscape, Letter)
- Plot area selector: Layout vs Extents
- Center-on-page toggle
- Plot offset X/Y fields
- Rotation picker: 0° / 90° / 180° / 270°
PlotSettings (acadrust object):
- PageSetupCommit finds or creates a PlotSettings object in the document
- Writes paper size, plot type, centering, offset, rotation to it
- DXF round-trip: PlotSettings persisted to file
PDF export:
- Reads PlotSettings for the active layout
- Applies centering (auto-computes offset from wire extents)
- Applies offset X/Y from PlotSettings
- Applies rotation via PDF CTM transformation matrix
- Swaps paper dimensions for 90°/270° rotation
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Snap is now suppressed (both cursor indicator and coordinate snapping)
when a command is in entity-pick mode (needs_entity_pick) or
selection-gathering mode (is_selection_gathering), and restored
automatically when the mode ends.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Selection, snapping and editing are now mode-aware:
PSPACE (paper layout, no active viewport)
- Only paper-space entities (viewport borders, title blocks, etc.) are
hit-testable and selectable. Viewport content wires are invisible to
the interaction layer.
- Drawing commands add entities to the paper-space layout block so
annotations/title blocks land on the sheet, not in model space.
MSPACE (active viewport entered)
- Only model-space entities visible through the active viewport are
hit-testable. Other viewports' content and paper entities are ignored.
- Drawing commands add entities to model space (correct DXF block).
- Snap results from projected viewport-content wires are converted from
paper-space back to model-space via paper_to_model so that placed
coordinates and command previews are consistent.
Entering/exiting MSPACE clears the current selection so no stale
cross-space selection is carried over.
Implementation:
- Scene::hit_test_wires() returns mode-filtered wires for all
hit-tests, snaps, and selections (entity_wires() still returns
everything for rendering and PDF export).
- viewport_content_wires() gains an Option<Handle> filter to render
only the active viewport's content for MSPACE hit-testing.
- Scene::add_entity() routes to the paper-layout block or model-space
block depending on current_layout / active_viewport.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Four bugs prevented viewports from working like AutoCAD model-space windows:
1. Dead-code double-click block: `!is_down2` was always false because
`is_down2 = sel.left_down` is captured while the button is still held
(before the selection block clears it). Changed to `is_down` so the
double-click handler actually fires.
2. Inverted pan direction: pan_active_viewport used `-=` on the delta
returned by screen_delta_to_world, which is the same delta that cam.pan
*adds* to its target — causing reversed drag. Changed to `+=`.
3. Zoom not cursor-centered: zoom_active_viewport now accepts an optional
paper-space cursor position and adjusts view_target so the model point
under the cursor stays fixed (same as cam.zoom_about_point).
4. ESC did not exit MSPACE: CommandEscape now calls ExitViewport when
active_viewport is set and no command is running.
Also added MS/MSPACE and PSPACE command aliases, and MspaceCommand /
PspaceCommand messages so MS auto-enters the first viewport.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Paper limits:
- Change A4 fallback from 12×9 to 297×210 mm in paper_limits()
Context menu:
- Translate layout context menu labels to English (Rename / Delete)
Viewport clipping:
- Replace AABB-only culling with proper Cohen-Sutherland line clipping
in viewport_content_wires(); each projected segment is now clipped at
the exact viewport boundary instead of being included or discarded whole
- Add cs_clip() and clip_polyline_to_rect() free functions in scene/mod.rs
Frozen layers per-viewport UI:
- Inject a "Frozen Layers" EditText property in the Properties panel for
viewport entities (layer names resolved from handles at display time)
- Handle "frozen_layers" in PropGeomCommit: parse comma-separated names,
resolve to layer handles, update vp.frozen_layers in-place
PDF export improvements:
- Add offset_x/offset_y params to export_pdf() for model-space normalization:
coordinates are shifted so the drawing origin maps to the page origin
- Model space export computes extents via model_space_extents() (now public)
and adds a 5 % margin; falls back to A4 landscape for empty drawings
- Skip __paper_boundary__ wire in PDF (white background covers it)
- Map yellow (active viewport border) → black and cyan (vp border) → dark
blue for print-friendly output
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Add printpdf 0.9.1 dependency for native PDF generation.
- New src/io/pdf_export.rs: converts paper-space WireModels to a PDF
page (per-wire stroke color, line weight in Pt, NaN-split segments).
White/near-white colors are inverted to black for print output.
- Add PlotExport / PlotExportPath messages: opens a save-file dialog
and writes a .pdf next to the drawing file.
- Add PageSetupOpen/Close/WidthEdit/HeightEdit/Commit messages: a
centered modal panel lets the user enter paper width and height (mm);
on commit the Layout object's min/max_limits are updated in-place.
- Register PRINT / PLOT / EXPORT and PAGESETUP (PS) commands in
dispatch_command; fix MVIEW error message to English.
- Layout ribbon gains a "Plot" group with Page Setup and Export PDF
ribbon buttons.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Add active_viewport: Option<Handle> field to Scene
- Add EnterViewport(Handle) and ExitViewport messages
- Double-click on a user viewport (id > 1) enters MSPACE;
double-click on empty area while in MSPACE exits to PSPACE
- MSPACE middle-drag pans the viewport's model-space view (view_target)
- MSPACE scroll zooms the viewport's view_height / custom_scale
- Drawing commands inside MSPACE receive model-space coordinates
via paper_to_model() coordinate transform
- Active viewport rendered with yellow dashed border (vs. cyan solid)
- Camera screen_delta_to_world helper for MSPACE pan conversion
- LayoutSwitch clears active_viewport
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Layout sekme sağ-tıklamasında context menüsü (Yeniden Adlandır / Sil)
- Inline rename: sekme metin-giriş alanına dönüşür, Enter ile commit, ✕ ile iptal
- LayoutDelete: layout ve sahip olduğu tüm entity'leri kaldırır
- LayoutRename: Layout nesnesinin adını yerinde günceller
- LayoutCreate çakışma koruması: mevcut isimler arasında benzersiz ad bulur
- Escape tuşu açık rename/context menüsünü kapatır
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>