This commit is contained in:
Brandon Thomas committed 2026-10-14 12:39:59 -04:00
commit 50a6b60072
3 files changed
+57 -4

No files matched your search

+1
View File
@@ -140,6 +140,7 @@ Newest first.
- **2026-10-14** · With the Page tool, the Control panel shows the page as InDesign's does: W/H from a reference point, page-size preset (US Business Card added), orientation, Liquid Page Rule (now with Controlled by Parent) and Show Parent Page Overlay, which draws the parent page's size over a resized page. No readiness percentage change.
- **2026-10-14** · With the Page tool, the Control panel shows the page as InDesign's does: W/H from a reference point, page-size preset (US Business Card added), orientation, Liquid Page Rule and Show Parent Page Overlay, which draws the parent page's size over a resized page. No readiness percentage change.
- **2026-10-14** · The Page tool works as InDesign's: a click selects a page and shows its handles and liquid page rule; dragging a handle previews the rule and springs back, Alt-drag resizes the page from the opposite edge, Shift keeps proportions, with a W/H readout. No readiness percentage change.
- **2026-10-14** · With the Page tool, a guide dragged from a ruler is a liquid guide (dashed), as in InDesign; guide-based pages stretch the objects it crosses. No readiness percentage change.
- **2026-10-12** · Text threads by hand: click a selected text frame's in or out port to load
the text cursor, then click a frame to thread it, click empty space for a column-wide frame or
drag one (it snaps like frame drawing); Shift-click autoflows, Alt-click stays loaded on the
+10 -2
View File
@@ -21,7 +21,7 @@ pub fn specs() -> Vec<CommandSpec> {
"New Guide",
[],
None,
"{orientation: horizontal|vertical, position (spread coordinate), spread?, page? (index in the spread; default: the page under `at` or the position), at? (the other coordinate), spreadGuide?: bool} → {page, index}",
"{orientation: horizontal|vertical, position (spread coordinate), spread?, page? (index in the spread; default: the page under `at` or the position), at? (the other coordinate), spreadGuide?: bool, liquid?: bool (a liquid guide, as the Page tool draws from the rulers)} → {page, index}",
has_doc,
add
),
@@ -98,6 +98,7 @@ fn add(s: &mut Session, p: &Value) -> Result<Value> {
let pos = finite_number(p, "position", "guide.add")?.ok_or_else(|| bad("guide.add", "missing position"))?;
let r = super::spread_param(p, "guide.add")?;
let spread_guide = p.get("spreadGuide").and_then(Value::as_bool).unwrap_or(false);
let liquid = p.get("liquid").and_then(Value::as_bool).unwrap_or(false);
let d = &s.doc()?.doc;
let pi = match optional_usize(p, "page", "guide.add")? {
Some(pi) => pi,
@@ -114,7 +115,14 @@ fn add(s: &mut Session, p: &Value) -> Result<Value> {
s.edit(|d, _| {
let sp = d.spread_mut(r).ok_or_else(|| bad("guide.add", "no such spread"))?;
let pg = sp.pages.get_mut(pi).ok_or_else(|| bad("guide.add", "no such page"))?;
pg.guides.push(Guide { orientation: o, position: pos, spread: spread_guide, locked: false, layer: Some(layer), liquid: false });
pg.guides.push(Guide {
orientation: o,
position: pos,
spread: spread_guide,
locked: false,
layer: Some(layer),
liquid: liquid && !spread_guide,
});
Ok(json!({"page": pi, "index": pg.guides.len() - 1}))
})
}
+46 -2
View File
@@ -312,7 +312,12 @@ pub fn show(app: &mut DesignApp, ui: &mut egui::Ui) {
designcraft_doc::Orientation::Horizontal => (pos2(rect.min.x, p.y), pos2(rect.max.x, p.y)),
designcraft_doc::Orientation::Vertical => (pos2(p.x, rect.min.y), pos2(p.x, rect.max.y)),
};
painter.line_segment([a, b], Stroke::new(1.0, col));
// A new guide from the rulers with the Page tool is a liquid guide: dashed.
if g.from.is_none() && app.session.tool_id() == "page" {
dashed(&painter, a, b, Stroke::new(1.0, col), 6.0, 3.0);
} else {
painter.line_segment([a, b], Stroke::new(1.0, col));
}
}
draw_frames(app, &painter, &xf, &doc, &layout);
if app.ui.hidden_characters {
@@ -1911,7 +1916,10 @@ fn guide_drag(app: &mut DesignApp, ui: &mut egui::Ui, resp: &egui::Response, rec
let _ = app.run("guide.move", json!({"spread": r, "page": pi, "index": gi, "position": pos_of(sp)}));
}
(None, true, Some((r, sp, on_page))) => {
let mut params = json!({"spread": r, "orientation": orient, "position": pos_of(sp), "at": sp.x, "spreadGuide": on_page.is_none()});
// The Page tool draws liquid guides from the rulers.
let liquid = app.session.tool_id() == "page" && on_page.is_some();
let mut params =
json!({"spread": r, "orientation": orient, "position": pos_of(sp), "at": sp.x, "spreadGuide": on_page.is_none(), "liquid": liquid});
if let Some(pi) = on_page {
params["page"] = json!(pi);
}
@@ -1988,6 +1996,42 @@ mod tests {
h
}
/// A primary-button drag from `a` to `b` over a few frames.
fn drag(h: &mut Harness<'_, DesignApp>, a: Pos2, b: Pos2) {
h.hover_at(a);
h.step();
h.event(egui::Event::PointerButton { pos: a, button: egui::PointerButton::Primary, pressed: true, modifiers: Default::default() });
h.step();
for k in 1..=4 {
h.hover_at(a + (b - a) * (k as f32 / 4.0));
h.step();
}
h.event(egui::Event::PointerButton { pos: b, button: egui::PointerButton::Primary, pressed: false, modifiers: Default::default() });
h.run_steps(3);
}
#[test]
fn the_page_tool_draws_liquid_guides_from_the_rulers() {
// Chris Cicchino's Page Tool and Liquid Layout video (11:00): with the Page tool, a guide
// dragged from the ruler is a liquid guide (dashed).
let mut app = DesignApp::new(designcraft_engine::Session::new(), crate::Services::default());
app.run("file.new", json!({})).unwrap();
app.session.set_tool("page");
let mut h = harness(app);
let r = h.state().canvas_rect.unwrap();
let guides = |h: &Harness<'_, DesignApp>| h.state().session.doc().unwrap().doc.spreads[0].pages[0].guides.clone();
drag(&mut h, pos2(r.center().x, r.min.y - 8.0), r.center());
let g = guides(&h);
assert_eq!(g.len(), 1, "{g:?}");
assert!(g[0].liquid && g[0].orientation == designcraft_doc::Orientation::Horizontal);
// With the Selection tool it's a ruler guide.
h.state_mut().session.set_tool("selection");
drag(&mut h, pos2(r.center().x, r.min.y - 8.0), r.center() + vec2(0.0, 40.0));
let g = guides(&h);
assert_eq!(g.len(), 2);
assert!(!g[1].liquid);
}
fn right_click(h: &mut Harness<'_, DesignApp>, p: Pos2) {
h.hover_at(p);
h.step();