fix(ui): Sketch Palette line type buttons follow the selected curves (#422)
With sketch curves selected, the palette's Normal / Construction / Centerline buttons now show the line type of the selection (each type of a mixed selection); with nothing selected they show the drawing mode, as before. Previously no button was highlighted while curves were selected. Co-authored-by: Claude Opus 5.5 <[email protected]>
This commit is contained in:
1 parent
b447adafaa
commit
0bb5b7eb09
1 file changed
+61
-2
@@ -128,6 +128,31 @@ fn selected_curves(app: &SolveApp) -> Vec<String> {
|
||||
app.session.selection.iter().filter_map(|s| if let Sel::SketchCurve { id } = s { Some(id.clone()) } else { None }).collect()
|
||||
}
|
||||
|
||||
/// The line types among the selected curves of the active sketch, indexed like the palette's
|
||||
/// buttons (0 normal, 1 construction, 2 centerline); a mixed selection marks each of its types.
|
||||
fn selected_linetypes(app: &SolveApp) -> [bool; 3] {
|
||||
let mut types = [false; 3];
|
||||
let curves = selected_curves(app);
|
||||
if curves.is_empty() {
|
||||
return types;
|
||||
}
|
||||
let st = app.session.world_state();
|
||||
let Some(ss) = app.session.active_sketch.and_then(|s| st.sketch(s)) else { return types };
|
||||
for c in curves.iter().filter_map(|id| ss.sketch.curve_index(id).and_then(|i| ss.sketch.curves.get(i))) {
|
||||
let k = if c.centerline {
|
||||
2
|
||||
} else if c.construction {
|
||||
1
|
||||
} else {
|
||||
0
|
||||
};
|
||||
if let Some(t) = types.get_mut(k) {
|
||||
*t = true;
|
||||
}
|
||||
}
|
||||
types
|
||||
}
|
||||
|
||||
/// Set the line type of the selected curves: 0 normal, 1 construction, 2 centerline (lines).
|
||||
pub fn set_linetype(app: &mut SolveApp, kind: u8) {
|
||||
let curves = selected_curves(app);
|
||||
@@ -205,6 +230,7 @@ pub fn show(app: &mut SolveApp, ctx: &egui::Context) {
|
||||
let mut look = false;
|
||||
let mut finish = false;
|
||||
let has_curves = !selected_curves(app).is_empty();
|
||||
let selected_types = selected_linetypes(app);
|
||||
let response = crate::frame::docked(
|
||||
app.tr("ui.heading_sketch_palette"),
|
||||
egui::Id::new("sc_sketch_palette"),
|
||||
@@ -241,10 +267,11 @@ pub fn show(app: &mut SolveApp, ctx: &egui::Context) {
|
||||
ui.vertical(|ui| {
|
||||
ui.label(app.tr("ui.linetype"));
|
||||
ui.horizontal(|ui| {
|
||||
// With a selection: convert it; without: the mode new curves are drawn in.
|
||||
// With a selection: its line type, and a click converts it; without:
|
||||
// the mode new curves are drawn in.
|
||||
let current = mode(app);
|
||||
for (i, (label, tip)) in [("—", "Normal"), ("- -", "Construction"), ("-·-", "Centerline")].iter().enumerate() {
|
||||
let on = !has_curves && current == i as u8;
|
||||
let on = if has_curves { selected_types.get(i).copied().unwrap_or(false) } else { current == i as u8 };
|
||||
let tr_tip = app.tr_label(tip);
|
||||
let tip = if has_curves {
|
||||
crate::i18n::format("sketch.make_selection", &[("linetype", tr_tip)])
|
||||
@@ -352,6 +379,38 @@ mod tests {
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn linetype_buttons_follow_the_selection_and_fall_back_to_the_mode() {
|
||||
let mut h = crate::scenario::Harness::new();
|
||||
h.app.run("sketch.create", json!({"plane":"XY"})).unwrap();
|
||||
let curve = |r: Value| r["curves"][0].as_str().unwrap().to_string();
|
||||
let normal = curve(h.app.run("sketch.line", json!({"points":[[0,0],[20,0]],"infer":false,"connect":false})).unwrap());
|
||||
let cons = curve(h.app.run("sketch.line", json!({"points":[[0,10],[20,10]],"infer":false,"connect":false})).unwrap());
|
||||
let center = curve(h.app.run("sketch.line", json!({"points":[[0,20],[20,20]],"infer":false,"connect":false})).unwrap());
|
||||
h.app.run("sketch.construction", json!({"curves":[cons],"value":true})).unwrap();
|
||||
h.app.run("sketch.centerline", json!({"curves":[center],"value":true})).unwrap();
|
||||
// Which of Normal, Construction and Centerline the palette shows pressed.
|
||||
let pressed = |h: &mut crate::scenario::Harness, ids: &[&String]| {
|
||||
h.app.session.selection = ids.iter().map(|id| Sel::SketchCurve { id: (*id).clone() }).collect();
|
||||
h.settle();
|
||||
let tree = h.output.accesskit_update.as_ref().unwrap();
|
||||
["—", "- -", "-·-"]
|
||||
.map(|label| tree.nodes.iter().any(|(_, n)| n.label() == Some(label) && n.toggled() == Some(egui::accesskit::Toggled::True)))
|
||||
};
|
||||
assert_eq!(pressed(&mut h, &[&normal]), [true, false, false]);
|
||||
assert_eq!(pressed(&mut h, &[&cons]), [false, true, false]);
|
||||
assert_eq!(pressed(&mut h, &[¢er]), [false, false, true]);
|
||||
// A mixed selection shows each of its line types.
|
||||
assert_eq!(pressed(&mut h, &[&normal, ¢er]), [true, false, true]);
|
||||
// Nothing selected: the drawing mode.
|
||||
assert_eq!(pressed(&mut h, &[]), [true, false, false]);
|
||||
set_mode(&mut h.app, 1);
|
||||
assert_eq!(pressed(&mut h, &[]), [false, true, false]);
|
||||
// A selection overrides the mode until it is cleared.
|
||||
assert_eq!(pressed(&mut h, &[&normal]), [true, false, false]);
|
||||
assert_eq!(pressed(&mut h, &[]), [false, true, false]);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn dof_readout() {
|
||||
assert_eq!(dof_text(0, true), "Fully constrained");
|
||||
|
||||
Reference in new issue
Block a user