mirror of
https://github.com/storytold/vectorcraft.git
synced 2026-10-28 03:37:00 -06:00
Merge pull request #1012 from Ni-zav/fix/1000-object-mosaic-input-s20261010T1758Z-a74b
fix(dialogs): preserve integer counts in command parameter fields
This commit is contained in:
@@ -248,7 +248,7 @@ pub(super) fn param_fields(
|
||||
match v {
|
||||
Value::Number(n) => {
|
||||
if let Some(x) = crate::widgets::plain_field(ui, ("fx-num", &k), n.as_f64().unwrap_or(0.0), "", 3, 140.0) {
|
||||
d.fields.insert(k, json!(x));
|
||||
d.fields.insert(k, typed_number(x));
|
||||
changed = true;
|
||||
}
|
||||
}
|
||||
@@ -291,6 +291,13 @@ pub(super) fn param_fields(
|
||||
changed
|
||||
}
|
||||
|
||||
/// A number typed in a command's dialog as JSON: a whole number as an integer, as counts are read
|
||||
/// (`as_u64`: Object Mosaic's columns and rows, #1000), which `12.0` isn't; a fraction stays one.
|
||||
/// Commands that take any number read either.
|
||||
fn typed_number(x: f64) -> Value {
|
||||
if x.fract() == 0.0 && x.abs() < 1e15 { json!(x as i64) } else { json!(x) }
|
||||
}
|
||||
|
||||
/// Editor for a plug-in's parameters from its schema (plug-in filter and effect dialogs): numbers
|
||||
/// within their range, whole numbers, checkboxes and dropdowns, in declaration order. Returns
|
||||
/// true when a value changed. The labels (from the parameter keys) and choices are the plug-in's
|
||||
@@ -552,3 +559,19 @@ pub(super) fn caption(ui: &mut egui::Ui, text: &str) {
|
||||
let t = Tokens::get(ui.ctx());
|
||||
ui.label(egui::RichText::new(tl!(text)).size(11.0).color(t.text_dim));
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod typed_number_tests {
|
||||
use super::*;
|
||||
|
||||
#[test]
|
||||
fn whole_numbers_are_integers_and_fractions_stay_fractions() {
|
||||
// Whatever the field held before: a count typed after a fraction is a count again.
|
||||
assert_eq!(typed_number(24.0).as_u64(), Some(24));
|
||||
assert_eq!(typed_number(-4.0), json!(-4));
|
||||
assert_eq!(typed_number(0.0), json!(0));
|
||||
assert_eq!(typed_number(2.5), json!(2.5));
|
||||
// Numbers past exact integers stay floats.
|
||||
assert!(typed_number(1e20).is_f64());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -434,6 +434,38 @@ fn a_dialog_opens_with_its_first_field_focused_so_typing_and_enter_apply() {
|
||||
assert_eq!(node.appearance.effects.last().map(|e| e.params["scaleH"].clone()), Some(json!(50.0)));
|
||||
}
|
||||
|
||||
/// #1000: a count typed in Object › Create Object Mosaic… reaches the command (a whole number typed
|
||||
/// in a command's dialog is an integer), so the mosaic has that many columns, not the 10 × 10 grid.
|
||||
#[test]
|
||||
fn object_mosaic_makes_the_grid_typed_in_its_dialog() {
|
||||
let mut app = app();
|
||||
app.run("shape.rectangle", json!({"x": 10, "y": 10, "width": 60, "height": 40})).unwrap();
|
||||
app.run("object.rasterize", json!({"ppi": 72})).unwrap();
|
||||
let ctx = egui::Context::default();
|
||||
theme::install_fonts(&ctx);
|
||||
theme::apply(&ctx, Default::default());
|
||||
let frame = |app: &mut VectorcraftApp, events: Vec<egui::Event>| {
|
||||
let mut out = ctx.run_ui(egui::RawInput { events, ..Default::default() }, |ui| show(app, ui.ctx()));
|
||||
out.textures_delta.clear();
|
||||
};
|
||||
let entry = crate::menus::menu_entries(&app).into_iter().find(|e| e.label == "Create Object Mosaic…").expect("menu item");
|
||||
let (cmd, params) = crate::menus::click_target(&entry.label, entry.command.as_deref().unwrap(), &entry.params);
|
||||
crate::menus::invoke(&mut app, &cmd, params);
|
||||
// Its first field, Columns, is focused: type 3 over it and press Enter.
|
||||
frame(&mut app, vec![]);
|
||||
frame(&mut app, vec![egui::Event::Text("3".into())]);
|
||||
let enter = egui::Event::Key { key: egui::Key::Enter, physical_key: None, pressed: true, repeat: false, modifiers: Default::default() };
|
||||
frame(&mut app, vec![enter]);
|
||||
assert!(app.ui.dialog.is_none());
|
||||
let mut tiles = None;
|
||||
app.session.doc().unwrap().doc.walk(|n| {
|
||||
if n.name.as_deref() == Some("Object Mosaic") {
|
||||
tiles = n.children().map(|c| c.len());
|
||||
}
|
||||
});
|
||||
assert_eq!(tiles, Some(3 * 10));
|
||||
}
|
||||
|
||||
/// #793: Artboard Options lists its fields as Name, Width, Height, not by key.
|
||||
#[test]
|
||||
fn artboard_options_lists_name_then_width_and_height() {
|
||||
|
||||
Reference in New Issue
Block a user