Give the Move dialog the canvas value box every other dialog already has (#739)
The Move dialog gets the same canvas value box as the other dialogs: X for translating moves, the angle for Rotate, placed clear of the triad.
This commit is contained in:
1 parent
4112189551
commit
6f4a9d96fb
6 files changed
+137
-14
No files matched your search
@@ -0,0 +1,71 @@
|
||||
//! The Move window's main value: the one the canvas box shows and the keyboard types into.
|
||||
//! It follows the move type, because each type uses a different value.
|
||||
use serde_json::json;
|
||||
use solidcraft_engine::Session;
|
||||
|
||||
use super::*;
|
||||
use crate::Services;
|
||||
use crate::dialogs::Dialog;
|
||||
|
||||
fn move_dialog(mode: usize) -> Dialog {
|
||||
let mut s = Session::default();
|
||||
s.execute("solid.box", &json!({"length": 20, "width": 20, "height": 20})).unwrap();
|
||||
let mut app = SolveApp::new(s, Services::default());
|
||||
app.start("solid.move");
|
||||
let mut d = app.dialog.clone().unwrap();
|
||||
d.kind = kind(mode);
|
||||
d.inputs = inputs(mode);
|
||||
if let Some(inp) = d.inputs.first_mut() {
|
||||
inp.items = vec![Sel::Body { name: "Body1".into() }];
|
||||
}
|
||||
d
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn the_main_value_follows_the_move_type() {
|
||||
for mode in [FREE, TRANSLATE, POINT_TO_POSITION] {
|
||||
let mut d = move_dialog(mode);
|
||||
let got = d.primary().map(|p| (p.0, p.1));
|
||||
assert_eq!(got, Some(("X", ValueKind::Length)), "{} types a distance", TYPES[mode]);
|
||||
}
|
||||
|
||||
let mut d = move_dialog(ROTATE);
|
||||
let got = d.primary().map(|p| (p.0, p.1));
|
||||
assert_eq!(got, Some(("Angle", ValueKind::Angle)), "Rotate types an angle, not an X distance");
|
||||
|
||||
let mut d = move_dialog(POINT_TO_POINT);
|
||||
assert!(d.primary().is_none(), "Point to Point is two picks with nothing to type");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn the_main_value_writes_through_to_the_command() {
|
||||
let mut d = move_dialog(ROTATE);
|
||||
if let Some((_, _, value)) = d.primary() {
|
||||
*value = "90 deg".into();
|
||||
}
|
||||
let Kind::Move { angle, .. } = &d.kind else { panic!("not a move") };
|
||||
assert_eq!(angle, "90 deg", "the box edits the angle itself, not a copy of it");
|
||||
|
||||
let mut d = move_dialog(TRANSLATE);
|
||||
if let Some((_, _, value)) = d.primary() {
|
||||
*value = "30 mm".into();
|
||||
}
|
||||
let Kind::Move { x, y, z, .. } = &d.kind else { panic!("not a move") };
|
||||
assert_eq!((x.as_str(), y.as_str(), z.as_str()), ("30 mm", "0 mm", "0 mm"), "the box edits X alone");
|
||||
}
|
||||
|
||||
/// Free Move and Translate carry the triad. The other three have no manipulator yet, so their
|
||||
/// value box is the only way to drive them: it must still have somewhere to sit.
|
||||
#[test]
|
||||
fn every_move_type_has_somewhere_to_put_its_value_box() {
|
||||
let mut s = Session::default();
|
||||
s.execute("solid.box", &json!({"length": 20, "width": 20, "height": 20})).unwrap();
|
||||
let app = SolveApp::new(s, Services::default());
|
||||
for mode in [FREE, TRANSLATE, ROTATE, POINT_TO_POINT, POINT_TO_POSITION] {
|
||||
let d = move_dialog(mode);
|
||||
let has_triad = triad(&app, &d).is_some();
|
||||
assert_eq!(has_triad, matches!(mode, FREE | TRANSLATE), "{} triad", TYPES[mode]);
|
||||
let at = triad(&app, &d).map(|t| t.center).or_else(|| crate::canvas::anchor(&app, &d).map(|(base, _)| base));
|
||||
assert!(at.is_some(), "{} has nowhere to put its value box", TYPES[mode]);
|
||||
}
|
||||
}
|
||||
Reference in new issue
Block a user