mirror of
https://github.com/storytold/figcraft.git
synced 2026-10-27 03:46:50 -06:00
- Compare changes: a ready-for-dev frame or section keeps a snapshot of itself from just before
its first change (Document::dev_snapshots, saved only while changed; dropped on resolve, re-mark,
other status or delete). `dev.compare {id?, show?}` diffs it layer by layer: added/removed
layers, and property changes formatted like Inspect (`width 120 → 136`, `fill #FF0000 →
#E03030`, text, parent, order, component, auto layout, typography, effects). The compare view
shows before / now side by side or overlaid with a slider, changed layers outlined, the list of
changes and Resolve change.
- Focus view: `dev.focus {id? | direction}` / `dev.unfocus`: one frame drawn and hit alone
(render Options::solo), a bar with name, status, Compare changes, previous / next ready frame and
exit; Escape leaves.
- Annotation categories: defaults plus the file's own with colours (`annotation.categories`,
`addCategory`, `editCategory`, `removeCategory`), `category` on annotations, coloured callouts,
a category filter and editor in the Inspect panel; stored backwards-compatibly.
- Shared widgets::icon_button / canvas_banner / dropdown_lead; has_status moved to the engine.
- Tests: devcompare_tests, devfocus_tests, annotation_categories_tests, doc handoff_tests, render
solo_tests, UI dev_mode_tests.
Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
49 lines
2.4 KiB
Rust
49 lines
2.4 KiB
Rust
//! `Options::solo` (Dev Mode's focus view): only one layer of the page is drawn, where it is, also
|
|
//! by the retained renderer.
|
|
|
|
use std::sync::Arc;
|
|
|
|
use figcraft_color::{Color, Paint};
|
|
use figcraft_doc::{Document, NodeKind};
|
|
|
|
use crate::{Options, Retained, View, render_view};
|
|
|
|
fn pixel(p: &crate::Pixmap, x: u32, y: u32) -> [u8; 4] {
|
|
let c = p.pixel(x, y).map(|c| c.demultiply()).map(|c| [c.red(), c.green(), c.blue(), c.alpha()]);
|
|
c.unwrap_or_default()
|
|
}
|
|
|
|
#[test]
|
|
fn solo_draws_one_layer_in_place() {
|
|
let mut d = Document::new("solo");
|
|
let page = d.first_page().unwrap();
|
|
let sec = d.create(page, NodeKind::Section { contents_hidden: false }, "Section", 0.0, 0.0, 400.0, 200.0).unwrap();
|
|
let a = d.create(sec, NodeKind::Frame, "A", 20.0, 20.0, 100.0, 100.0).unwrap();
|
|
let b = d.create(page, NodeKind::Rectangle, "B", 200.0, 20.0, 100.0, 100.0).unwrap();
|
|
d.get_mut(a).unwrap().fills = vec![Paint::solid(Color::from_hex("#FF0000").unwrap())];
|
|
d.get_mut(b).unwrap().fills = vec![Paint::solid(Color::from_hex("#0000FF").unwrap())];
|
|
d.get_mut(sec).unwrap().fills = vec![Paint::solid(Color::from_hex("#00FF00").unwrap())];
|
|
let view = View { origin: (0.0, 0.0), scale: 1.0, width: 400, height: 200 };
|
|
let all = render_view(&d, page, &view, &Options::default()).unwrap();
|
|
assert_eq!(pixel(&all, 250, 50)[2], 255, "B drawn");
|
|
assert_eq!(pixel(&all, 10, 10)[1], 255, "the section drawn");
|
|
let solo = Options { solo: Some(a), ..Default::default() };
|
|
let one = render_view(&d, page, &view, &solo).unwrap();
|
|
assert_eq!(pixel(&one, 50, 50), [255, 0, 0, 255], "A where it is (inside its section)");
|
|
let bg = Color::DEFAULT_PAGE.to_rgba8();
|
|
assert_eq!(pixel(&one, 250, 50), bg, "B left out");
|
|
assert_eq!(pixel(&one, 10, 10), bg, "the section around A left out");
|
|
// A layer of another page (or the page itself) draws the page as usual.
|
|
for other in [page, figcraft_doc::NodeId(999)] {
|
|
let p = render_view(&d, page, &view, &Options { solo: Some(other), ..Default::default() }).unwrap();
|
|
assert_eq!(pixel(&p, 250, 50)[2], 255);
|
|
}
|
|
// The retained renderer redraws when solo changes.
|
|
let doc = Arc::new(d);
|
|
let mut r = Retained::default();
|
|
let (_, p, _) = r.render(&doc, page, &view, &Options::default()).unwrap();
|
|
assert_eq!(pixel(p, 250, 50)[2], 255);
|
|
let (_, p, _) = r.render(&doc, page, &view, &solo).unwrap();
|
|
assert_eq!(pixel(p, 250, 50), bg);
|
|
}
|