mirror of
https://github.com/storytold/designcraft.git
synced 2026-10-30 21:26:48 -06:00
Engine with command registry (~100 commands), tool hosting with one-step undo per gesture, InDesign-style egui frontend (app bar, Control panel, Tools panel, rulers, guides, frame edges, ports/threads, Properties/Pages/ Layers dock, panels, dialogs), JSON control channel, headless CLI renderer, generated sample magazine, README/AGENTS/ROADMAP/ASSETS. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
93 lines
3.4 KiB
Rust
93 lines
3.4 KiB
Rust
use designcraft_geom::Rect;
|
|
|
|
use super::*;
|
|
use crate::build::NewDocument;
|
|
|
|
fn doc() -> Document {
|
|
Document::new(&NewDocument { pages: 2, ..Default::default() })
|
|
}
|
|
|
|
#[test]
|
|
fn threading_moves_frames_and_text() {
|
|
let mut d = doc();
|
|
let lid = d.default_layer();
|
|
let (a, sa) = d.add_text_frame(SpreadRef::Doc(0), Rect::new(10.0, 10.0, 100.0, 100.0), lid, "first", ParaFormat::default()).unwrap();
|
|
let (b, sb) = d.add_text_frame(SpreadRef::Doc(0), Rect::new(110.0, 10.0, 200.0, 100.0), lid, "second", ParaFormat::default()).unwrap();
|
|
d.thread(a, b).unwrap();
|
|
d.check().unwrap();
|
|
assert!(d.story(sb).is_none());
|
|
let st = d.story(sa).unwrap();
|
|
assert_eq!(st.text, "first\nsecond");
|
|
assert_eq!(st.frames, vec![a, b]);
|
|
assert_eq!(d.next_frame(a), Some(b));
|
|
assert_eq!(d.prev_frame(b), Some(a));
|
|
d.unthread_after(a).unwrap();
|
|
d.check().unwrap();
|
|
assert_eq!(d.story(sa).unwrap().frames, vec![a]);
|
|
assert_ne!(d.item(b).unwrap().text_frame().unwrap().story, sa);
|
|
}
|
|
|
|
#[test]
|
|
fn thread_to_empty_frame_converts_it() {
|
|
let mut d = doc();
|
|
let lid = d.default_layer();
|
|
let (a, sa) = d.add_text_frame(SpreadRef::Doc(0), Rect::new(10.0, 10.0, 100.0, 100.0), lid, "x", ParaFormat::default()).unwrap();
|
|
let id = ItemId(d.alloc());
|
|
let it = Item::new(id, lid, Shape::Rectangle, designcraft_geom::shapes::rectangle(Rect::new(0.0, 200.0, 50.0, 300.0)));
|
|
d.insert_item(SpreadRef::Doc(0), it, None).unwrap();
|
|
d.thread(a, id).unwrap();
|
|
assert!(d.item(id).unwrap().is_text_frame());
|
|
assert_eq!(d.story(sa).unwrap().frames, vec![a, id]);
|
|
d.check().unwrap();
|
|
assert!(d.thread(a, a).is_err());
|
|
}
|
|
|
|
#[test]
|
|
fn removing_last_frame_deletes_story() {
|
|
let mut d = doc();
|
|
let lid = d.default_layer();
|
|
let (a, sa) = d.add_text_frame(SpreadRef::Doc(0), Rect::new(10.0, 10.0, 100.0, 100.0), lid, "x", ParaFormat::default()).unwrap();
|
|
d.remove_item(a).unwrap();
|
|
assert!(d.story(sa).is_none());
|
|
d.check().unwrap();
|
|
}
|
|
|
|
#[test]
|
|
fn hit_testing_respects_layers() {
|
|
let mut d = doc();
|
|
let lid = d.default_layer();
|
|
let (a, _) = d.add_text_frame(SpreadRef::Doc(0), Rect::new(10.0, 10.0, 100.0, 100.0), lid, "x", ParaFormat::default()).unwrap();
|
|
assert_eq!(d.hit_item(0, designcraft_geom::Point::new(50.0, 50.0), 2.0), Some(a));
|
|
assert_eq!(d.hit_item(0, designcraft_geom::Point::new(300.0, 300.0), 2.0), None);
|
|
d.layer_mut(lid).unwrap().locked = true;
|
|
assert_eq!(d.hit_item(0, designcraft_geom::Point::new(50.0, 50.0), 2.0), None);
|
|
}
|
|
|
|
#[test]
|
|
fn page_names_follow_sections() {
|
|
let mut d = Document::new(&NewDocument { pages: 6, ..Default::default() });
|
|
assert_eq!(d.page_name(0), "1");
|
|
d.sections.push(Section {
|
|
start: 2,
|
|
start_number: Some(1),
|
|
style: NumberStyle::LowerRoman,
|
|
prefix: "A-".into(),
|
|
marker: String::new(),
|
|
include_prefix: true,
|
|
});
|
|
assert_eq!(d.page_name(1), "2");
|
|
assert_eq!(d.page_name(2), "A-i");
|
|
assert_eq!(d.page_name(4), "A-iii");
|
|
}
|
|
|
|
#[test]
|
|
fn document_serde_roundtrip() {
|
|
let mut d = doc();
|
|
let lid = d.default_layer();
|
|
d.add_text_frame(SpreadRef::Doc(0), Rect::new(10.0, 10.0, 100.0, 100.0), lid, "héllo\nworld", ParaFormat::default()).unwrap();
|
|
let s = serde_json::to_string(&d).unwrap();
|
|
let back: Document = serde_json::from_str(&s).unwrap();
|
|
assert_eq!(d, back);
|
|
back.check().unwrap();
|
|
}
|