mirror of
https://github.com/storytold/designcraft.git
synced 2026-10-29 12:46:53 -06:00
Merge PR #866
This commit is contained in:
@@ -389,20 +389,35 @@ pub fn specs() -> Vec<CommandSpec> {
|
||||
has_doc,
|
||||
page_options
|
||||
),
|
||||
cmd!(noundo "layout.selectPage", "Select Page", [], None, "{page: 1-based | null} — the page the Page tool selects (its handles, the Control panel)", has_doc, |s, p| {
|
||||
cmd!(
|
||||
noundo "layout.selectPage",
|
||||
"Select Page",
|
||||
[],
|
||||
None,
|
||||
"{page: 1-based | null, ids?: [item ids] (objects selected with it: the Page tool on an object-based page)} — the page the Page tool selects (its handles, the Control panel)",
|
||||
has_doc,
|
||||
|s, p| {
|
||||
let n = s.doc()?.doc.page_count();
|
||||
let page = match p.get("page") {
|
||||
None | Some(Value::Null) => None,
|
||||
Some(v) => Some(v.as_u64().filter(|v| *v >= 1 && *v as usize <= n).ok_or_else(|| bad("layout.selectPage", format!("`page`: 1–{n}")))? as usize - 1),
|
||||
};
|
||||
let ids: Vec<designcraft_doc::ItemId> = {
|
||||
let d = &s.doc()?.doc;
|
||||
p.get("ids")
|
||||
.and_then(Value::as_array)
|
||||
.map(|a| a.iter().filter_map(Value::as_u64).map(designcraft_doc::ItemId).filter(|id| d.item(*id).is_some()).collect())
|
||||
.unwrap_or_default()
|
||||
};
|
||||
let st = s.doc_mut()?;
|
||||
if page.is_some() {
|
||||
st.selection = Default::default();
|
||||
st.selection = designcraft_doc::Selection::items(ids);
|
||||
}
|
||||
st.selection.page = page;
|
||||
st.revision += 1;
|
||||
Ok(json!({"page": page.map(|p| p + 1)}))
|
||||
}),
|
||||
}
|
||||
),
|
||||
cmd!(
|
||||
"layout.section",
|
||||
"Numbering & Section Options…",
|
||||
|
||||
@@ -668,6 +668,62 @@ fn controlled_by_parent_takes_the_parent_pages_rule() {
|
||||
assert!(s.execute("layout.pageOptions", &json!({"pages": [2], "showParentOverlay": true})).is_err());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn page_tool_pins_and_locks_objects_on_object_based_pages() {
|
||||
use designcraft_tools::{CanvasLayout, Mods, PointerEvent, PointerKind};
|
||||
let mut s = Session::new();
|
||||
s.execute("file.new", &json!({"width": 612, "height": 792, "facingPages": false})).unwrap();
|
||||
let id = s.execute("frame.create", &json!({"rect": [256, 72, 356, 132]})).unwrap()["id"].as_u64().unwrap();
|
||||
s.execute("liquid.pageRule", &json!({"rule": "objectBased"})).unwrap();
|
||||
s.execute("edit.deselectAll", &json!({})).unwrap();
|
||||
s.set_tool("page");
|
||||
let v = ViewInfo::at_zoom(1.0);
|
||||
let ev =
|
||||
|kind, p: designcraft_geom::Point, alt: bool| PointerEvent { mods: Mods { alt, ..Default::default() }, ..PointerEvent::new(kind, p.x, p.y) };
|
||||
let canvas = |s: &Session| {
|
||||
let d = &s.doc().unwrap().doc;
|
||||
let l = CanvasLayout::new(d, false);
|
||||
(
|
||||
l.page_rect(d, 0).unwrap(),
|
||||
l.xf(designcraft_doc::SpreadRef::Doc(0)).transform_rect_bbox(d.item(designcraft_doc::ItemId(id)).unwrap().bounds()),
|
||||
)
|
||||
};
|
||||
let click = |s: &mut Session, p: designcraft_geom::Point| {
|
||||
s.pointer(&ev(PointerKind::Down, p, false), v).unwrap();
|
||||
s.pointer(&ev(PointerKind::Up, p, false), v).unwrap();
|
||||
};
|
||||
let liquid = |s: &Session| s.doc().unwrap().doc.item(designcraft_doc::ItemId(id)).unwrap().liquid;
|
||||
// A click on the object selects it with its page; its pins and locks show.
|
||||
let (_, o) = canvas(&s);
|
||||
click(&mut s, o.center());
|
||||
let sel = s.doc().unwrap().selection.clone();
|
||||
assert_eq!((sel.page, sel.items.clone()), (Some(0), vec![designcraft_doc::ItemId(id)]));
|
||||
assert!(
|
||||
s.overlays(v)
|
||||
.iter()
|
||||
.any(|o| matches!(o, designcraft_tools::Overlay::LiquidPins { pins: [false, false, false, false], resize: [true, true], .. }))
|
||||
);
|
||||
// The right pin (14 px outside the right edge) and the width lock (10 px right of the centre).
|
||||
click(&mut s, designcraft_geom::Point::new(o.x1 + 14.0, o.center().y));
|
||||
click(&mut s, designcraft_geom::Point::new(o.center().x + 10.0, o.center().y));
|
||||
let l = liquid(&s).unwrap();
|
||||
assert!(l.pin_right && !l.resize_width && l.resize_height && !l.pin_left, "{l:?}");
|
||||
// Alt-drag the page 100 pt wider: the pinned, width-locked frame keeps its size by the right edge.
|
||||
let (p, _) = canvas(&s);
|
||||
let right = designcraft_geom::Point::new(p.x1, p.center().y);
|
||||
s.pointer(&ev(PointerKind::Down, right, true), v).unwrap();
|
||||
s.pointer(&ev(PointerKind::Drag, right + designcraft_geom::Vec2::new(100.0, 0.0), true), v).unwrap();
|
||||
s.pointer(&ev(PointerKind::Up, right + designcraft_geom::Vec2::new(100.0, 0.0), true), v).unwrap();
|
||||
let d = &s.doc().unwrap().doc;
|
||||
let (pg, b) = (&d.spreads[0].pages[0], d.item(designcraft_doc::ItemId(id)).unwrap().bounds());
|
||||
assert_eq!(pg.width, 712.0);
|
||||
assert!((b.width() - 100.0).abs() < 1e-6 && (pg.x + pg.width - b.x1 - 256.0).abs() < 1e-6, "{b:?}");
|
||||
// Hovering a pin shows its tooltip.
|
||||
let (_, o) = canvas(&s);
|
||||
s.pointer(&ev(PointerKind::Move, designcraft_geom::Point::new(o.x1 + 14.0, o.center().y), false), v).unwrap();
|
||||
assert!(s.overlays(v).iter().any(|o| matches!(o, designcraft_tools::Overlay::Tip { text, .. } if text.starts_with("Object is pinned"))));
|
||||
}
|
||||
|
||||
/// Load the text from a frame's out port with the Selection tool and click on the pasteboard:
|
||||
/// a new frame is threaded there and the overset text flows into it.
|
||||
#[test]
|
||||
|
||||
Reference in New Issue
Block a user