Conflicts:
- crates/tools/src/lib.rs: Overlay keeps next's ContentGhost and adds
LiveCornerWidget and LiveCornerDiamond.
- crates/tools/src/select.rs: the module doc keeps next's threading and
content paragraphs and adds the live-corner one. Drag keeps Place and
adds Corner; SelectionTool holds both `loaded` and `live`. pointer()
first ends live-corner editing when the selection changed, then runs
next's loaded-text-cursor and double-click handling. An empty-canvas
press clears `live` and keeps next's `content: false` Pending. drag()
handles Place and Corner. overlays() keeps next's Place marquee and
content ghost and appends the widget or diamonds.
- crates/ui-egui/src/canvas.rs: the overlay pass keeps next's doc/layout
for ContentGhost and next's Path drawing, and adds the two live-corner
arms (the branch's no-op Path arm is dropped). The live-corner render
test goes before next's fast_harness tests.
- crates/engine/src/cmd/object.rs: next's text_wrap stays; the branch's
corner_options function follows it.
- crates/engine/src/tests.rs, crates/tools/src/tests.rs: both sides'
tests kept.
- ROADMAP.md: the live corners progress-log line goes first; the status
line names it too.
Action::Handled is matched in engine tooling.rs; no other crate matches
Action or Overlay exhaustively.
A selected, unlocked rectangle frame at least 40 px on screen shows the
yellow widget near its top-right corner. Clicking it shows a diamond at
each corner. Dragging a diamond along its edge sets the size of all four
corners as one undo step (Shift: that corner only), clamped to half the
shorter side. Alt-click steps that corner's shape; Shift+Alt-click steps
every corner. Escape, a click on empty canvas, another selection or
another tool ends corner editing. Positions follow the frame's transform.
object.cornerOptions takes corners: four {shape, size} entries. Tools
gain Action::Handled and the LiveCornerWidget/LiveCornerDiamond overlays,
drawn by the canvas in the live_corner theme token. Fixes#186.
Conflict: crates/ui-egui/src/canvas.rs draw_tool_overlays: the PR's
Overlay::Path arm (draw_path_overlay) and next's Overlay::ContentGhost
arm both kept; draw_path_overlay sits before draw_content_ghost.
The PR was rebased onto upstream main; its code commits are unchanged
(range-diff shows only ROADMAP lines moved into the new docs commit), so
next already carries them.
Conflicts: crates/ui-egui/src/{dialogs.rs,i18n.rs,i18n/it.rs,lib.rs}:
next's versions (the old PR code plus next's own dialogs, findFont and
numberingSection work). ROADMAP.md and docs/target-app-parity.md take the
PR's New Document entries.
ROADMAP.md was restructured in #355 and its feature list moved to
docs/target-app-parity.md. The smart guides line this branch reworded
is changed there instead.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The Pencil tool's stroke only appeared once the mouse button was
released. The tool reported the stroke so far as a path overlay, but the
canvas skipped path overlays (they were never drawn), so nothing showed
while drawing. The canvas now draws them: curves flattened to about a
quarter of a screen pixel, dashed when asked. That also brings back the
Smooth and Erase tools' dashed drag previews.
The Pencil's preview was black, lost on a dark pasteboard; it is drawn in
the colour of the layer the path goes on, as InDesign does.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Rebased on the progress-docs restructure (#355): the ROADMAP bullets this
PR added moved to the inventory in docs/target-app-parity.md, and the
ROADMAP progress log gets a line for it.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- Recovery: file.recovery.open moves each entry to the reopened document's uid
(written before the old one is removed), so recovered documents stay on disk
until saved or closed, also when the app restarts on another adapter or
stops before its first recovery save.
- First-frame watch: a late first frame is logged and noted in the status bar.
The adapter counts as hanging only when the UI thread has been stuck outside
the app's code (logic/ui mark entry and exit) with no progress for 60 s while
the window isn't known to be minimized, occluded or unfocused. The watch asks
for a repaint on each look, so an idle UI ends it. VectorCraft restarts on
the late frame alone, which a held-back compositor or a long compose can set
off.
- Software renderers (WARP, llvmpipe) are passed over while another backend is
left; once no hardware adapter of any backend could show the window, the app
starts again with them allowed, once.
- A restart clears gpu.json's backend entry just before exec or spawn and puts
it back when starting again fails. Backends a restart left out are no longer
recorded as failed.
- The watch ends a hung process with TerminateProcess on Windows.
- The skip list travels as the restarted app's --gpu-skip= argument instead of
an environment variable, so processes the app starts don't inherit it.
Conflicts: ui-egui dialogs.rs (next's numberingSection arm and the branch's cellOptions arm; the branch's
copies of the dialog test helpers already on next dropped, its cell options test kept); idml tests.rs and
the i18n tables appended at the end on both sides (both kept; the branch's Gap Tint: and Tint: rows that
next already had dropped).
Ported from VectorCraft's start-up fixes (#502, #545, #651, the display-GPU
choice, #806, #964) and reconciled with the backend fallback of #297:
- The app picks the window's adapter itself (eframe's native_adapter_selector,
apps/designcraft/src/gpu.rs): adapters that can't present never, then
WGPU_ADAPTER_NAME, hardware before software, native backends before OpenGL,
the GPU that drives the primary display (Windows EnumDisplayDevices through
winsafe, Linux /sys/class/drm), the power preference (WGPU_POWER_PREF;
otherwise power saving on Windows and macOS, the system's order elsewhere),
then DX12 before Vulkan. Every adapter and the choice are logged.
- wgpu's indirect-call validation is off (WGPU_VALIDATION_INDIRECT_CALL=1 turns
it back on): its compute shader failed to compile on an Intel Mac and lost
the Metal device (#334, first error).
- run_native runs under catch_unwind. A wgpu error or a panic in wgpu,
egui-wgpu or naga during the first frames, or a first frame that doesn't
reach the screen in 20 s, starts the app again without that adapter
(DESIGNCRAFT_GPU_SKIP; exec on Unix, a new process on Windows). When no
adapter of the start's backends is left, it starts again with the next
backend. Each restart leaves out one more adapter or backend, so they end.
Adapters without PCI ids (Metal) are keyed by name.
- The backend fallback (gpu/backend.rs, gpu.json) stays for driver faults that
take the process down. Windows tries DirectX 12, then OpenGL, then Vulkan,
each in its own instance: Vulkan last because creating its instance loads
every installed Vulkan driver, and OpenGL kept out of the DX12 instance
because creating it crashed in AMD's atio6axx.dll (#167).
- main returns an ExitCode and logs why the app stopped to standard error and
the log file, which is all a Windows start without a console leaves (#273).
README, architecture, gaps, hardware and target-app parity docs and ROADMAP
describe the choice, the restarts and the variables.
With cells selected, or the text cursor in a cell, the Stroke panel edits the
cell edges chosen on a drawn edge proxy: weight, type, colour, tint, gap colour
and gap tint. A click toggles a line, a double-click chooses all outer or all
inner lines, a triple-click chooses or clears all. Table › Cell Options ›
Strokes and Fills… has the same proxy and fields plus the cell fill colour and
tint, and applies the changed values in one undoable step. Translations for
the new strings in every interface language.
- object.reorder {ids, above|below: id | index, layer?}: restacks sibling
objects in front of or behind a target, or at an index counted from the
top of a layer, moving them to that layer. Group members stay in their
group. Bad input is an error and leaves the document unchanged.
- layer.move rejects a missing id or an out-of-range index.
- Layers panel: drag a layer row to reorder layers, an object row to
restack it or move it to another layer, and a filled selection square
onto a layer to move the selection there; a line or box shows the drop.
Groups expand to list their members. Layers list top (frontmost) first,
matching the stacking order.
Progress docs per craftrules standards/progress-docs.md: target-app parity, gaps, roadmap with alpha gate, readiness by audience (full / mainstream / essentials) with Opus 5.5 hours, and feature, format, hardware, UI and localization parity docs.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>