mirror of
https://github.com/storytold/designcraft.git
synced 2026-11-12 05:12:39 +00:00
Rectangle dialog: width and height in the ruler units, not always picas (#1964)
A click with a frame tool opened the Rectangle dialog in picas whatever Preferences > Units & Increments or the rulers' unit menus said. It now shows the width in the horizontal ruler unit and the height in the vertical one, and reads bare numbers typed in each field the same way. The properties panel and the control channel open it the same way. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
1 parent
ea08e4c2ba
commit
cdb2057aab
5 files changed
+63
-11
No files matched your search
@@ -83,6 +83,7 @@ impl DesignApp {
|
||||
let was_find = self.ui.dialog.as_ref().is_some_and(|d| d.id == "findChange");
|
||||
match r {
|
||||
UiRequest::Dialog { id, params } if id == "colorTheme" => dialogs::open_color_theme(self, params),
|
||||
UiRequest::Dialog { id, params } if id == "frameSize" => self.ui.dialog = Some(dialogs::frame_size_dialog(self, params)),
|
||||
UiRequest::Dialog { id, params } => self.ui.dialog = Some(dialogs::Dialog::new(&id, params)),
|
||||
UiRequest::View { params } => canvas::apply_view_request(self, ¶ms),
|
||||
UiRequest::Pick { purpose, params } => {
|
||||
|
||||
@@ -389,7 +389,8 @@ fn handle_request(app: &mut DesignApp, ctx: &egui::Context, req: &ControlRequest
|
||||
if id == "findChange" || app.ui.dialog.as_ref().is_some_and(|d| d.id == "findChange") {
|
||||
app.session.reset_find_scope();
|
||||
}
|
||||
let d = crate::dialogs::Dialog::new(id, p.get("fields").cloned().unwrap_or(Value::Null));
|
||||
let fields = p.get("fields").cloned().unwrap_or(Value::Null);
|
||||
let d = if id == "frameSize" { crate::dialogs::frame_size_dialog(app, fields) } else { crate::dialogs::Dialog::new(id, fields) };
|
||||
let v = serde_json::to_value(&d).unwrap_or_default();
|
||||
app.ui.dialog = Some(d);
|
||||
ok(v)
|
||||
|
||||
@@ -79,13 +79,6 @@ impl Dialog {
|
||||
if id == "ruby" {
|
||||
fields.entry("section".to_string()).or_insert(json!("cjk.rubyPlacement"));
|
||||
}
|
||||
if id == "frameSize" {
|
||||
for k in ["width", "height"] {
|
||||
if let Some(v) = fields.get(k).and_then(Value::as_f64) {
|
||||
fields.insert(k.into(), json!(format_measure(v, Unit::Picas)));
|
||||
}
|
||||
}
|
||||
}
|
||||
Dialog { id: id.into(), fields, unit: Unit::Picas }
|
||||
}
|
||||
/// Set a field and report a genuine Find domain/mode transition to the caller.
|
||||
@@ -106,9 +99,13 @@ impl Dialog {
|
||||
}
|
||||
}
|
||||
fn m(&self, k: &str) -> Option<f64> {
|
||||
self.m_in(k, self.unit)
|
||||
}
|
||||
/// A measure where a bare number is in `unit`.
|
||||
fn m_in(&self, k: &str, unit: Unit) -> Option<f64> {
|
||||
match self.fields.get(k) {
|
||||
Some(Value::Number(n)) => n.as_f64(),
|
||||
Some(Value::String(s)) => parse_measure(s, self.unit).ok(),
|
||||
Some(Value::String(s)) => parse_measure(s, unit).ok(),
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
@@ -934,6 +931,25 @@ fn doc_unit(app: &DesignApp) -> Unit {
|
||||
app.session.active().map(|s| s.doc.settings.horizontal_units).unwrap_or(Unit::Picas)
|
||||
}
|
||||
|
||||
/// The document's vertical ruler unit: what a bare number means in a height field.
|
||||
fn doc_vertical_unit(app: &DesignApp) -> Unit {
|
||||
app.session.active().map(|s| s.doc.settings.vertical_units).unwrap_or(Unit::Picas)
|
||||
}
|
||||
|
||||
/// The Rectangle dialog a click with a frame tool opens: the width (points in `params`) shown in
|
||||
/// the horizontal ruler unit, the height in the vertical one, as Preferences › Units &
|
||||
/// Increments and the rulers' menus set them (#1964).
|
||||
pub fn frame_size_dialog(app: &DesignApp, params: Value) -> Dialog {
|
||||
let mut d = Dialog::new("frameSize", params);
|
||||
for (k, unit) in [("width", doc_unit(app)), ("height", doc_vertical_unit(app))] {
|
||||
if let Some(v) = d.fields.get(k).and_then(Value::as_f64) {
|
||||
d.fields.insert(k.into(), json!(format_measure(v, unit)));
|
||||
}
|
||||
}
|
||||
d.unit = doc_unit(app);
|
||||
d
|
||||
}
|
||||
|
||||
/// Layout › Create Guides…: guides go on the page in view (or the parent page being edited), not
|
||||
/// on the first page, and the gutters are typed in the document's ruler unit.
|
||||
pub fn open_create_guides(app: &mut DesignApp) {
|
||||
@@ -3277,7 +3293,7 @@ fn confirm_part1(app: &mut DesignApp, d: Dialog) -> Result<Value, String> {
|
||||
let x = d.fields.get("x").and_then(Value::as_f64).unwrap_or(0.0);
|
||||
let y = d.fields.get("y").and_then(Value::as_f64).unwrap_or(0.0);
|
||||
let w = d.m("width").unwrap_or(72.0);
|
||||
let h = d.m("height").unwrap_or(72.0);
|
||||
let h = d.m_in("height", doc_vertical_unit(app)).unwrap_or(72.0);
|
||||
app.run(
|
||||
"frame.create",
|
||||
json!({"spread": d.fields.get("spread").cloned().unwrap_or(json!(0)), "shape": d.s("shape"), "content": d.s("content"), "rect": [x, y, x + w, y + h]}),
|
||||
|
||||
@@ -3521,3 +3521,37 @@ fn character_style_options_set_the_digits() {
|
||||
assert_eq!(ctl(&mut app, "ui.dialog.confirm", json!({}))["ok"], true);
|
||||
assert_eq!(char_style(&app, "Emphasis").unwrap().chars.digits, Some(designcraft_doc::Digits::Farsi));
|
||||
}
|
||||
|
||||
/// The Rectangle dialog a frame-tool click opens shows the width in the horizontal ruler unit and
|
||||
/// the height in the vertical one, not always picas, and reads bare numbers the same way (#1964).
|
||||
#[test]
|
||||
fn frame_size_dialog_follows_the_ruler_units() {
|
||||
let mut app = DesignApp::new(designcraft_engine::Session::new(), crate::Services::default());
|
||||
app.run("file.new", json!({})).unwrap();
|
||||
app.run("document.preferences", json!({"horizontalUnits": "inches", "verticalUnits": "millimeters"})).unwrap();
|
||||
// As the frame tool asks: a click at (36, 36), 72 pt by 72 pt.
|
||||
app.session.ui_requests.push(designcraft_engine::UiRequest::Dialog {
|
||||
id: "frameSize".into(),
|
||||
params: json!({"spread": 0, "shape": "rectangle", "content": "graphic", "x": 36.0, "y": 36.0, "width": 72.0, "height": 72.0}),
|
||||
});
|
||||
app.after_engine();
|
||||
let d = app.ui.dialog.as_ref().expect("the Rectangle dialog");
|
||||
assert_eq!((d.id.as_str(), d.unit), ("frameSize", Unit::Inches));
|
||||
assert_eq!(d.s("width"), format_measure(72.0, Unit::Inches));
|
||||
assert_eq!(d.s("height"), format_measure(72.0, Unit::Millimeters));
|
||||
assert!(!d.s("width").contains('p') && !d.s("height").contains('p'), "no picas: {} x {}", d.s("width"), d.s("height"));
|
||||
// Bare numbers typed in each field are in that field's unit: 2 in by 50 mm.
|
||||
let d = app.ui.dialog.as_mut().unwrap();
|
||||
d.fields.insert("width".into(), json!("2"));
|
||||
d.fields.insert("height".into(), json!("50"));
|
||||
let before = app.session.doc().unwrap().doc.clone();
|
||||
confirm(&mut app).unwrap();
|
||||
let after = &app.session.doc().unwrap().doc;
|
||||
let added: Vec<_> = after.spreads[0].items.iter().filter(|i| !before.spreads[0].items.iter().any(|b| b.id == i.id)).collect();
|
||||
assert_eq!(added.len(), 1, "one frame");
|
||||
let b = added[0].bounds();
|
||||
assert!((b.width() - 144.0).abs() < 0.01 && (b.height() - 50.0 / 25.4 * 72.0).abs() < 0.01, "{b:?}");
|
||||
// The properties panel's link opens it in the same units.
|
||||
let d = frame_size_dialog(&app, json!({"width": 36.0, "height": 36.0}));
|
||||
assert_eq!((d.s("width"), d.s("height")), (format_measure(36.0, Unit::Inches), format_measure(36.0, Unit::Millimeters)));
|
||||
}
|
||||
@@ -327,7 +327,7 @@ pub(super) fn appearance_section(app: &mut DesignApp, ui: &mut Ui, i: &SelInfo)
|
||||
let b = block(ui, FIELD_H);
|
||||
icons::paint(ui.painter(), sub(b, 3.0, 1.0, 19.0, 19.0), "corner", t.accent);
|
||||
if place(ui, sub(b, 34.0, 0.0, 56.0, FIELD_H), |ui| link_label(ui, crate::i18n::tr(&app.ui.language, "Corner"), 56.0)).clicked() {
|
||||
app.ui.dialog = Some(crate::dialogs::Dialog::new("frameSize", json!({})));
|
||||
app.ui.dialog = Some(crate::dialogs::frame_size_dialog(app, json!({})));
|
||||
}
|
||||
let (shape, size) = i.corner;
|
||||
if let Some(v) = place(ui, sub(b, 96.0, 0.0, 69.0, FIELD_H), |ui| {
|
||||
|
||||
Reference in new issue
Block a user