Resolved conflicts:
- app/update/mod.rs: keep the dock's dock_open_at_default for the XREF
manager; take main's stable xref row identity (row_index(&id)).
- app/view/mod.rs: keep the edge layout from app::dock; drop main's copy
of the old edge-stack code (main only reformatted it there).
- ui/window/layers.rs: keep main's new visible_indices next to the
branch's view_panel.
Files the branch only reformatted take main's version. Adds the Lao
(lo-LA) translations for the new dock texts.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
Claude-Session: https://claude.ai/code/session_013RyGiMXcsf9HTKfqDxaQGt
XrefManagerSelect/RightClick/RowOp/PathPick/FindReplace carried positional display indices that rescans could retarget. New XrefRowId{key,saved_path} (the identity refresh uses) in all 5 variants, resolved via row_index at dispatch with graceful no-op; panel selection stays index-based. display.index remains for view-time styling/lookup only. Tests: xref_rowop_unknown_id_is_noop (RED first); existing dialog/simulator/click tests migrated to ids. Full suite: 2044 passed / 0 failed / 25 ignored.
props_asym_scale was app-global keyed by raw handle values, but fresh documents restart numbering at seed 1, leaking one tab's unchecked Uniform box into another tab reusing the value. The set moves to DocumentTab; all uses tab-scoped. Also removes a dead destructure left in overlay.rs. Test: asym_scale_opt_out_does_not_leak_across_tabs with handle-reuse premise assert (RED first). Full suite: 2025 passed / 0 failed / 25 ignored, zero warnings.
- dock_hover_pending is an Option<HoverPending> (Reveal / Hide) instead
of a nested Option.
- dock_float_frame returns a FloatFrame with width() and bar_x(), so the
floating menu no longer repeats the frame-width formula.
- Put dock_reveal's doc comment back on dock_reveal, and the group-move
comment back above the match it describes.
No behaviour change.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
Claude-Session: https://claude.ai/code/session_013RyGiMXcsf9HTKfqDxaQGt
Remove floating groups: a floating window is a single pallet once more,
and the Pallets submenu is gone from its title-bar menu. Kept: the menu
opens at the pointer with Allow docking, Dock left and Dock right;
close / pin show only while the bar is hovered; content is clipped to
its frame. A config saved by the floating-group build still loads, its
windows floating their first pallet. Drops the unused Pallets string.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
Claude-Session: https://claude.ai/code/session_013RyGiMXcsf9HTKfqDxaQGt
- The floating title bar's right-click menu opens where the pointer is,
flipped to stay on screen; the Pallets submenu sits beside it.
- Close and pin on a floating title bar only show while it is hovered,
as on docked title bars.
- New Allow docking check in that menu: off, dragging the window (or a
pallet out of it) only floats it, never docks it on an edge.
- Floating windows and stacked pallets clip their content, so a pallet
sized below its content no longer draws outside its frame.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
Claude-Session: https://claude.ai/code/session_013RyGiMXcsf9HTKfqDxaQGt
- A docked group floats as one window: drag its edge band over the
drawing or double-click the band. Floating windows hold a stack of
pallets with splitters; the vertical title bar shows each pallet's
icon (press one to drag that pallet out). Dragging the bar moves the
whole window; dropping it on an edge docks or joins it as a group.
- Right-click a floating title bar: Pallets submenu (add or hide
pallets in the window), Dock left, Dock right.
- Close on a floating bar closes every pallet in the window; its pin
sets auto-hide for the whole window.
- Older configs with single floating pallets still load.
- Translate the new dock texts (Auto-hide, Dock left/right, New group,
Pallets, Browser, Node Graph) in all 21 languages.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
Claude-Session: https://claude.ai/code/session_013RyGiMXcsf9HTKfqDxaQGt
- LAYERS ribbon button runs a command that opens the Layer Manager pallet;
the ribbon no longer keeps it highlighted.
- Layer Manager: search box stays right-aligned, the column header fills
the row, no stray contour lines when the pallet is taller than its rows.
- Auto-hidden edges don't show the shown-group accent bar.
- Auto-hide reveal and hide wait 150 ms of rest, so passing over the
strip doesn't flash groups open.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
Claude-Session: https://claude.ai/code/session_013RyGiMXcsf9HTKfqDxaQGt
- The dock's state handling and drawing move out of update/dialog.rs and
view/mod.rs into src/app/dock/ (update.rs, view.rs, tests.rs). The
overlay view_main stacked over the workspace (floating pallets, + menu,
drag preview, pointer capture) becomes one `dock_overlay` call. Code is
moved, not changed.
- Strip icons no longer show the pallet name on hover.
- Tests trimmed where they overlapped: the top / bottom half drops are
one test, the two hover tests are one, and the in-group icon reorder,
raise-float, empty floating title bar and slot-span tests are dropped
(each is covered by another test).
Co-Authored-By: Claude Opus 5.5 <[email protected]>
Claude-Session: https://claude.ai/code/session_013RyGiMXcsf9HTKfqDxaQGt
No intended behaviour change except the fixes noted below.
- One drag state: a single `DockDrag` (move pallet / group, width,
splitter, floating size, Layer Manager column) replaces nine fields
(dragging, dragging group, resizing, split, float resizing, origin,
target, grab offset, layer column flag) that had to be kept in sync.
- `dock_expanded` becomes `dock_peek` with one meaning: a pallet revealed
although it auto-hides. `dock_reveal(id)` shows a pallet's group and
peeks it; commands that open a pallet now use it, so opening a pallet
also switches its edge to that pallet's group.
- Each group stores its own width (falling back to its widest pallet's
width until first sized), instead of every pallet's width being kept in
sync. Pallet widths now only size floating pallets and new groups.
- One `dock_set_open(id, open)` holds every pallet's open and close path.
- Leftovers removed: the tab-group config format that never reached main,
the multi-tab drag ghost header, the separate icon-hover message.
Fixes:
- Hovering a strip icon reveals an auto-hiding edge again (the icons had
lost the hover message in the option B strip). Covered by a test that
moves the pointer over the icon in the real view.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
Claude-Session: https://claude.ai/code/session_013RyGiMXcsf9HTKfqDxaQGt
The icon strip follows the agreed "option B" concept:
- Flat 40 px strip; groups are rows of their pallets' icons separated by
hairline dividers, with no grip lines. The + button is a small round
button under the last group.
- The shown group is marked by a blue bar on its window-side edge and
brighter icons. That 8 px edge band is the group grip: hovering it
widens and lights the bar, tints the row, shows a grab cursor and a
"Drag to move group" tooltip; dragging it moves the whole group.
- Icons still drag single pallets: within their group or into another
group (between its icons), or onto a divider to start a new group.
Hovering an icon gives it a soft background and shows its name.
- Drop feedback: a short accent line with end caps between icons means
"join this group here" (the target group's bar lights up); a
full-width line on a divider with a "+ New group" badge means "new
group here". The dragged icon (or whole group) fades in place and a
ghost follows the pointer.
- The zone around a divider (a few px into the icons on either side)
starts a new group; the lower half of a group's last icon still joins
that group at the end.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
Claude-Session: https://claude.ai/code/session_013RyGiMXcsf9HTKfqDxaQGt
A group is now a set of pallets shown together, stacked top to bottom,
and an edge shows one group at a time. The icon strip lists every group
(grip bar over its pallets' icons, the shown group on a grey
background); clicking any icon of a group shows that whole group.
- Dropping a pallet on the top / bottom half of a pallet in the shown
group stacks it above / below; dropping on the strip's icons places it
in that group at that spot, and on a grip or below the last group
starts a new group (which is then shown).
- Splitters set the heights of the pallets within a group; double-click
makes them equal again.
- Each group keeps its own width; the divider sizes only the group it
belongs to, and switching groups switches width.
- A group whose pallets all auto-hide shows only while hovered.
- Layouts saved by older builds load with their stacked pallets as one
group.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
Claude-Session: https://claude.ai/code/session_013RyGiMXcsf9HTKfqDxaQGt
Each dock edge now has a vertical icon strip along the window edge in
place of the horizontal tab row and the auto-hide rail.
- Every shown group gets a grip bar with its pallets' icons below it;
the shown pallet's icon has a grey background. Clicking an icon shows
that pallet in its group; hovering the icons of an auto-hiding group
opens it.
- Dragging an icon within the strip reorders it or moves it into
another group; dropping it on a grip or below the last group makes it
a new group there. On the pallet area, the top / bottom bands still
start a new group above / below and the middle joins the group.
- Dragging a grip moves the whole group to another position or edge.
- A + button under the groups opens the pallet menu (icon, name, check
mark). Opening a pallet from it docks it on that edge as a new group,
or in its existing group there; a checked pallet is hidden.
- Groups keep their width when moved; the divider against the viewport
sizes the whole edge column.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
Claude-Session: https://claude.ai/code/session_013RyGiMXcsf9HTKfqDxaQGt
- LAYERS opens the Layer Manager as a dockable pallet instead of a modal
dialog with a darkened backdrop. It floats over the middle of the
drawing the first time and keeps its place after that; LAYERS again
(or its close button) hides it. The table keeps its natural width and
scrolls sideways when the pallet is narrower, and the Name column
divider now drags through the dock's pointer capture. Ctrl+A selects
all layers while a layer row is selected in the open pallet.
- The Layer Manager is listed in the tab-row pallet menu like the others.
- Double-clicking a docked title bar floats the panel beside its edge;
double-clicking a floating title bar docks the panel on the side its
title bar faces.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
Claude-Session: https://claude.ai/code/session_013RyGiMXcsf9HTKfqDxaQGt
- Dropping on a docked pallet now stacks it above or below over the top
and bottom 35 % of the slot; only the middle 30 % makes it a tab.
- Tabs show the pallet icon (title as tooltip), aligned to the left.
Every docked slot has the tab row, so its menu is always reachable.
- A menu button at the right of the tab row lists every pallet with a
check mark for those shown in this slot. Checking one opens it as a
tab here (moving it from wherever it was docked); unchecking hides it
and keeps its tab for next time.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
Claude-Session: https://claude.ai/code/session_013RyGiMXcsf9HTKfqDxaQGt
- Docked title bars show the pin and close only while the pointer is
over the bar; the bar keeps a fixed height so nothing jumps.
- Auto-hide on is drawn as a 30° tilted pin (new pin_active.svg)
instead of a coloured button background, on docked and floating bars.
- A floating panel's resize grip sits in the bottom corner away from its
title bar. With the bar on the right it is bottom-left (new mirrored
resize_left.svg) and resizing from there keeps the right edge fixed.
The bar stays on its side while resizing.
- While a floating panel is dragged, only the drop preview shows it; the
panel no longer stays drawn at its old place.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
Claude-Session: https://claude.ai/code/session_013RyGiMXcsf9HTKfqDxaQGt
Panels can now float over the workspace, share a docked slot as tabs,
and split an edge at heights the user picks.
- Dropping a panel away from the edges floats it at the pointer. Floating
panels move by their title bar, resize from a corner grip, and come to
the front when clicked.
- Dropping in the top or bottom quarter of a docked slot docks the panel
above or below it, as before. Dropping in the middle adds the panel as
a tab of that slot. Pressing a tab shows that panel; dragging a tab
pulls the panel out again.
- While dragging, a blue ghost previews the result: the new slot, the
slot with its future tab row, or the floating window.
- A splitter between stacked slots sets their heights; double-click it
to make the slots equal again. Heights persist.
- A press only becomes a drag after 5 px of movement, so clicking a title
bar or tab never moves the panel.
The persisted layout now stores each edge as tab groups with a height
weight, plus a list of floating panels. Configs with the old
bare-panel-id stacks still load as single-panel slots.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
Claude-Session: https://claude.ai/code/session_013RyGiMXcsf9HTKfqDxaQGt
On a non-Retina screen macOS draws the interface at 1x, which reads small
on a Full HD monitor, and there was no way to enlarge it. Options >
Display now offers an interface scale of 75–200 % in 25 % steps, applied
through the window's scale factor on top of the display's own and kept
with the user settings. It is a list rather than a slider because the
dialog rescales under the pointer as the value changes.
Fixes#1655
Co-Authored-By: Claude Opus 5.5 <[email protected]>
Outside macOS a touchpad's two-finger drag arrives as wheel scrolls that
nothing tells from a wheel. A new option (Options, off by default) makes
every scroll pan and Ctrl+scroll — what a pinch sends there — zoom.
Fixes#1560
Co-Authored-By: Claude Opus 5.5 <[email protected]>
The paste kernel added every entity to model space. It now takes the
space a new entity goes to: the block being edited, a layout's paper
space when no viewport is active, or model space.
Fixes#1652
Co-Authored-By: Claude Opus 5.5 <[email protected]>
Display gets a command line text colour (blank keeps the theme's); it
covers history, prompts and the input, while errors stay red. Files
lists the fonts folder that text resolution searches, so .shx files can
be added by hand; opening it creates it first.
Discussions #1493, #1372
Co-Authored-By: Claude Opus 5.5 <[email protected]>
- Text styles keep their TrueType typeface through save and reopen (codec
reads and writes the STYLE record's ACAD extended data) (#1633)
- Unnamed shape-file entries no longer show in text style lists (#1634)
- Save As offers DWT 2018; NEW asks for the template to start from, while
Ctrl+N and the quick-access New run QNEW with the default template (#1635)
- An edge next to an earlier fillet of the same radius rounds together with
it (kernel); the solid stays drawn and pickable while edges are chosen
(#1625, #1107)
- A full cache rebuild drops the B-rep cache too, so an undone fillet does
not come back with the next edge operation (#1107)
- Selected solids in shaded styles highlight only their visible edges (#1031)
- VIEW ISO / SWISO / SEISO / NEISO / NWISO snap to the isometric corners
Co-Authored-By: Claude Opus 5.5 <[email protected]>
Fixes:
- Font prompt no longer lists bundled ltypeshp/qcadshp shape files (#1626)
- Wide polylines step at a discontinuous segment width; PEDIT marks the
current vertex; keyword steps refresh the command preview (#1628)
- Radius-0 fillet drops the zero-length segment it left, so the corner
fillets again (#1422)
- FILLET Trim / No trim option (#1558)
- True-colour wires plot in their own colour; colour picker stores the
value it shows (#1621)
- Model tab keeps its page setup; "Save changes to layout" in Model (#1620)
- QNEW default template in Options > Files; .dwt in the open dialog
(#1134, #1113)
- GRIDUNIT / GRIDMODE / PERSPECTIVE variables (#1618, #1524)
- PTYPE (#1433)
- ZOOM nX / nXP (#1465)
- CHSPACE between model and paper space through a viewport (#1428)
- Moving a dimension keeps its automatic text placement
- Shell icon; "&&" button labels (#1554)
- LINETYPE Load from a .lin file (#1588)
- XLINE / RAY hide the crosshair arms (#1437)
- Dynamic-input boxes keep clear of the crosshair and each other (#1546)
- Snap marker colour setting, dark default on light canvases
(#1497, #1229, #1128)
- Dimension style precision as a 0.00 pattern dropdown (#1426)
- Node graph nodes left of the origin no longer clip away (#1592)
- Collapse button in the command history header (#1094)
- Freeze-in-current-viewport toggle in the ribbon layer list (#1466)
- Geometric Center object snap for closed polylines (#1369)
New strings translated in all 21 locales.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
Closes the view-to-dispatch resort race: the nine Layer* variants plus ColorPickTarget::Layer now carry the layer name and resolve to the current panel row at dispatch time via layer_panel_index; unknown names no-op. View sites (layer panel, ribbon dropdown) and the CLI/plugin path send names, so the CLI position lookup and the ribbon enumerate are deleted. Panel-internal selection state stays index-based. Tests: layer_toggle_visible_targets_layer_by_name_after_resort pins name targeting across a re-sort; layer_toggle_visible_unknown_name_is_noop pins the graceful no-op. Full suite: 1974 passed / 0 failed / 25 ignored.
- When the count area's boundary is gone the approved Invalid Area dialog
asks: undo the change (also its X and Cancel) or count all of model space;
"always" keeps the choice in the settings. An edited boundary moves the area.
- A table's *T block is brought up to date whenever the table changes.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
The PR pinned the codec to its fork through [patch]; codec #75 is merged
upstream and main already points at it, so the patch section is dropped.
The two windows-sys features it adds (Globalization, Identity) stay.
The exponential camera step is the right call. `0.9 ^ delta` is strictly
positive for every real delta, in and out cancel exactly where the
subtraction lost a percent of the view on every round trip, and the file's
own header has promised an "exponential feel" since it was written. Three
surfaces were left behind it, and the wider range exposed a fourth thing.
The range of the system variable. 3 to 100 is the range ZOOMFACTOR has, and
the User Preferences page was built against it; `SETVAR ZOOMFACTOR` accepts
that and nothing else again. A faster wheel is the Options window's business
instead: the slider covers the variable's own range, the field beside it
reaches 500, and a read-out says what a notch actually does ("10.0% a
notch") so the number being set is readable rather than implied. A value
above 100 therefore lives only in this application's own configuration file,
where it is nobody else's to read, and a bare `SETVAR ZOOMFACTOR` still
reports it. The bounds and the clamp live in one place now
(`settings::clamp_zoom_factor`): four literal copies of `3, 100` are what
let a surface be missed in the first place.
A floating viewport in MSPACE. It zooms its own view through
`zoom_active_viewport`, which kept subtracting: the factor reached zero at
6.67 steps, so from ZOOMFACTOR 360 up every notch inside a viewport bottomed
out on the clamp — a tenfold jump a notch, and the top third of the slider
doing nothing at all. Exponential there too, from a base of 0.85 so the
default notch still moves a viewport the 15% it always has. Each surface
keeps its own long-standing feel rather than inheriting the other's.
The trackpad pinch. `pinch_zoom_steps` was calibrated against the
subtraction (`1 - step / 10 = 1 / (1 + m)`) so that a pinch of m leaves the
view exactly 1 + m times closer — the property docs/trackpad.md documents
and the reason the gesture tracks the fingers at all. Inverting the zoom law
by hand is what let the two drift apart, so the step is asked of the camera
now (`Camera::zoom_steps_for_ratio`), which cannot drift by construction.
`pinch_is_one_to_one` recomputed the old formula rather than the camera's,
so it kept passing through all of this; it zooms a real camera and measures
the distance it lands at instead.
Also: `zoom` had a floor and no ceiling, and zooming out multiplies. At
ZOOMFACTOR 500 a notch out is x2.4, so about ninety notches — a couple of
seconds of scrolling — ran the distance past what an f32 far plane
(`distance * 1000`) can hold, and the viewport went black on an infinite
projection. A degenerate pinch magnification of -1 or beyond reached the
same place through the other side. Both are bounded now.
Also: two doc comments quoted the linear law (`zoom_view_at_cursor` and the
one on `pinch_zoom_steps`), and docs/trackpad.md stated the pinch identity
and claimed the tests covered it against the camera. All updated, with what
a notch does and where each surface's range comes from written down.
Tests, each confirmed against the behaviour it describes: the zoom law at
every factor the application can hold (positive, monotonic in the setting,
in and out cancelling), the ceiling under a long scroll out in both
projections, the published inverse and what it does with a nonsense ratio,
the viewport factor and a real viewport zoomed three notches at the top of
the range, the SETVAR range including a value the Options field set, the
Options field (above 100, above the ceiling, cleared, not a number), its
agreement with the slider, Close putting both the value and the field back,
and the read-out's percentages. 1882 lib tests pass.
The two new Options strings are not in the locale catalog yet, so they
render in English until it is regenerated.
Co-Authored-By: Claude Opus 5 <[email protected]>
Conflicts with #1573: the locale files and the catalog take both PRs'
entries (one "Insertion Point" mapping kept); the Home and Insert Block
panels take #1574's layout with #1573's Insert Block gallery.
A Field dialog with the fields the application evaluates and the
reference format choices, FIELD placing a field as multi-line text, the
attribute definition dialogs' field buttons, field attachment on commit,
system variable / file size / regional date providers for field
evaluation, and the codec patch with the field authoring API.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
Attribute Definition dialog and Edit Attribute Definition dialog, -ATTDEF
with the reference prompts and modes (AFLAGS), tag shown in the drawing,
justification-aware grips, reworked Properties with validation, Home Block
slide-out and Insert Block Definition panel, and the codec patch for
ATTDEF DXF output and the R2013+ solid wire cache.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
Rebuild the Blocks palette with Current Drawing / Recent / Favorites /
Libraries tabs, wildcard filter, six views, insertion options, click and
drop insertion and a block context menu. INSERT opens the palette, the
new -INSERT runs on the command line, the ribbon Insert button becomes a
block gallery, and BLOCKMRULIST, BLOCKREDEFINEMODE, BLOCKNAVIGATE,
BLOCKSTATE, EXPLMODE and INSNAME are added.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
Point clouds: drawn from their scans, attached, cropped and stylized.
The fork's codec patch is resolved to the upstream pins: the point cloud
records landed in opencadcodec 5ef9376, carried through opencadkernel
68eeda1 and opencadgraph e204966.
Co-Authored-By: Claude Opus 5.5 <[email protected]>