Browse / github.com/storytold/designcraft / patch
Rulers: a guide dragged out keeps its resize cursor until it is dropped
A guide dragged out of a ruler loses its resize cursor as soon as the pointer leaves the ruler **What happens:** Pulling a guide out of a ruler shows the up/down (or left/right) resize cursor while the pointer is still over the ruler. As soon as the pointer moves onto the canvas, the cursor turns back into the tool's arrow, although the drag goes on and the guide is placed on release. It looks as if the drag had stopped, and in Preview mode (where guides are hidden) nothing at all shows that it worked. **Steps:** 1. Press in the top ruler and drag down onto the page. 2. The cursor is the resize cursor only over the ruler; over the page it is the Selection tool's arrow. **Expected:** T
- Status
- open
- Score
- 0.00
- Adopters
- 0 other operators
- Author
- PiMinusMax (imported from pull request #1764, open)
- Base
ed8aabd1dc5a88652a076631c2d46886ca60c031- Size
- +36 −0 in 3 files
- Review
- pending
- Shared
- 2026-10-28
- Id
11ecc41d313c7a6face0c54e
How it went
No other operator has reported using it yet.
Diff
raw · ROADMAP.md crates/ui-egui/src/canvas.rs crates/ui-egui/src/guide_selection_tests.rs
@@ -408,6 +408,7 @@ Newest first. - **2026-10-24** · Optical Margin Alignment per story with a size (`story.options {opticalMargin, opticalMarginSize}`, off by default): when it is on, the story's paragraphs hang punctuation and letter edges by amounts set for that type size, except paragraphs with Ignore Optical Margin (`ignoreOpticalMargin` in `type.para` and paragraph styles). Table cells and footnotes don't take the story setting yet. When it is off, the per-paragraph switch still hangs at the text's own size. IDML imports and exports both (`StoryPreference/@OpticalMarginAlignment`, `@OpticalMarginSize`, `IgnoreEdgeAlignment`) (#947). No readiness percentage change. - **2026-10-24** · Text frames: a custom baseline grid's Relative To (Text Frame Options › Baseline Options, `object.textFrameOptions {baselineGrid: {relativeTo}}`, IDML `BaselineFrameGridRelativeOption`) measures the grid's start from the top of the page, the top margin, the top of the frame or its top inset. Text Frame Options had no custom baseline grid controls, imports dropped the setting and every frame grid started from the page top, so grid-aligned text in a frame measured from its own top sat on the wrong lines. No readiness percentage change. - **2026-10-24** · Paragraph Style Options › Indents and Spacing has an Align to Grid menu: None, All Lines or First Line Only. It shows the style's current setting. A First Line Only style could be set only in the CJK Grid Settings section, which shows only with CJK features on, or through commands. No readiness percentage change.+- **2026-10-24** · A guide pulled out of a ruler keeps the resize cursor across it until it is dropped; the tool's cursor took over as soon as the pointer left the ruler, so the drag looked as if it had stopped. No readiness percentage change. - **2026-10-24** · Anchored text frames, such as marginal notes, compose where their host story places them: they align to the baseline grid at that position, and page-number markers and spine-relative alignment inside them read the host's page. They composed against a grid measured from their stored position and on no page, so a note set to Only Align First Line to Grid could sit a fraction of a line off the body text's grid line. No readiness percentage change. - **2026-10-24** · Tables: a gradient swatch in a cell fill draws as a gradient on the canvas and in PDF, in one gradient space for the whole table, so it runs across cells without restarting. Cells showed the gradient's first stop as a solid colour. No readiness percentage change. - **2026-10-24** · New documents start with Hyphenate Capitalized Words, Hyphenate Last Word and Hyphenate Across Column off in [Basic Paragraph], as in InDesign. Opened and imported files keep the values they carry. No readiness percentage change.@@ -743,6 +743,13 @@ pub fn show(app: &mut DesignApp, ui: &mut egui::Ui) { Some(_) => Cursor::ResizeV, None => c, };+ // A ruler guide being dragged keeps the cursor across it until it is dropped, over the+ // canvas too (the tool's cursor took over as soon as the pointer left the ruler).+ let c = match ui.data(|d| d.get_temp::<GuideDrag>(egui::Id::unique(GUIDE_DRAG))).map(|g| g.orientation) {+ Some(designcraft_doc::Orientation::Horizontal) => Cursor::ResizeV,+ Some(designcraft_doc::Orientation::Vertical) => Cursor::ResizeH,+ None => c,+ }; let icon = crate::cursors::show(ui.ctx(), &mut app.cursors, c, p); ui.ctx().set_cursor_icon(icon); draw_cursor_badge(&painter, p, c, &t);@@ -328,3 +328,31 @@ fn a_guide_dragged_out_of_a_ruler_snaps() { drag(&mut h, ruler, dest); assert_eq!(positions(&h), [200.0, 300.0, 400.0, 400.0]); }++/// A guide pulled out of a ruler keeps the resize cursor across it over the canvas until it is+/// dropped; the tool's arrow came back as soon as the pointer left the ruler.+#[test]+fn a_guide_dragged_out_of_a_ruler_keeps_its_cursor_until_dropped() {+ let mut app = DesignApp::new(designcraft_engine::Session::new(), crate::Services::default());+ app.run("file.new", json!({})).unwrap();+ let mut h = harness(app);+ let rect = h.state().canvas_rect.unwrap();+ for (from, icon) in [+ (pos2(rect.center().x, rect.min.y - crate::canvas::RULER / 2.0), egui::CursorIcon::ResizeVertical),+ (pos2(rect.min.x - crate::canvas::RULER / 2.0, rect.center().y), egui::CursorIcon::ResizeHorizontal),+ ] {+ let to = rect.center();+ h.hover_at(from);+ h.step();+ press(&mut h, from, true, Modifiers::NONE);+ for k in 1..=4 {+ h.hover_at(from + (to - from) * (k as f32 / 4.0));+ h.step();+ assert_eq!(h.output().platform_output.cursor_icon, icon, "step {k} of the drag from {from:?}");+ }+ press(&mut h, to, false, Modifiers::NONE);+ h.hover_at(to);+ h.run_steps(2);+ assert_ne!(h.output().platform_output.cursor_icon, icon, "dropped: the tool's cursor again");+ }+}