mirror of
https://github.com/storytold/designcraft.git
synced 2026-10-14 19:27:07 -04:00
Merge PR #868
This commit is contained in:
commit
50a6b60072
3 files changed
+57
-4
No files matched your search
@@ -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
|
||||
|
||||
@@ -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}))
|
||||
})
|
||||
}
|
||||
|
||||
@@ -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();
|
||||
|
||||
Reference in new issue
Block a user