forked from 1b-agent/opencadstudio-upstream
fix(statusbar): scale pill number, label and badge follow one viewport
The pill number used the first-content fallback while the label and sync badge used explicit-only resolution, showing e.g. a 1:50 number beside a 1:1 label with no badge. Label and badge now resolve through target_viewport_handle like the number; render-path handle fn, set-paths and Model branches untouched. Tests: scale_pill_sources_agree_without_targeted_viewport (RED: live probe Some(0.02)/1:1/None) plus Model-unchanged pin. Full suite: 2027 passed / 0 failed / 25 ignored.
This commit is contained in:
1 parent
d1da26feb6
commit
b66f890546
1 file changed
+51
-2
+51
-2
@@ -6386,7 +6386,13 @@ impl Scene {
|
||||
if self.current_layout == "Model" {
|
||||
return self.document.header.current_annotation_scale.clone();
|
||||
}
|
||||
self.explicit_viewport_handle()
|
||||
// Same viewport the pill number comes from (active → selected →
|
||||
// first-content fallback), so label, number and badge always describe
|
||||
// one viewport (#48). Degenerate case: with zero Scale objects the
|
||||
// name falls back to paper/"1:1" while the number stays factual.
|
||||
// The render paths use displayed_annotation_scale_HANDLE, which stays
|
||||
// explicit-only — untouched by this fix.
|
||||
self.target_viewport_handle()
|
||||
.and_then(|viewport| self.viewport_scale_handle(viewport))
|
||||
.and_then(|handle| match self.document.objects.get(&handle) {
|
||||
Some(ObjectType::Scale(scale)) => Some(scale.name.clone()),
|
||||
@@ -6480,7 +6486,8 @@ impl Scene {
|
||||
}
|
||||
|
||||
pub fn viewport_annotation_scale_synced(&self) -> Option<bool> {
|
||||
let viewport = self.explicit_viewport_handle()?;
|
||||
// Same viewport as the pill number and label (#48).
|
||||
let viewport = self.target_viewport_handle()?;
|
||||
let EntityType::Viewport(vp) = self.document.get_entity(viewport)? else {
|
||||
return None;
|
||||
};
|
||||
@@ -14447,6 +14454,48 @@ mod layout_cache_tests {
|
||||
);
|
||||
assert!(after.iter().any(|n| n == "TEST_CACHED_UCS"));
|
||||
}
|
||||
|
||||
// #48: with no active/selected viewport, the pill number, label and sync
|
||||
// badge must all describe the SAME viewport (the first-content fallback
|
||||
// the number already used) — not a mix of viewport number, paper label
|
||||
// and hidden badge.
|
||||
#[test]
|
||||
fn scale_pill_sources_agree_without_targeted_viewport() {
|
||||
let mut scene = Scene::new();
|
||||
scene.add_layout("P1").unwrap();
|
||||
scene.current_layout = "P1".to_string();
|
||||
assert!(scene.add_scale("1:50", 1.0, 50.0));
|
||||
let mut vp = codec::entities::Viewport::new();
|
||||
vp.width = 100.0;
|
||||
vp.height = 100.0;
|
||||
let handle = scene
|
||||
.document
|
||||
.add_entity_to_layout(codec::EntityType::Viewport(vp), "P1")
|
||||
.unwrap();
|
||||
assert!(scene.set_viewport_scale_named_for(handle, "1:50").is_some());
|
||||
assert!(scene.active_viewport.is_none());
|
||||
let number = scene.first_viewport_scale();
|
||||
let name = scene.displayed_annotation_scale_name();
|
||||
let synced = scene.viewport_annotation_scale_synced();
|
||||
eprintln!("number={number:?} name={name:?} synced={synced:?}");
|
||||
assert!(
|
||||
number.is_some() && name == "1:50" && synced == Some(true),
|
||||
"pill trio must agree"
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn scale_pill_model_layout_unchanged() {
|
||||
// Model layout has no viewports: number None, header label, no badge.
|
||||
let scene = Scene::new();
|
||||
assert!(scene.current_layout == "Model");
|
||||
assert!(scene.first_viewport_scale().is_none());
|
||||
assert_eq!(
|
||||
scene.displayed_annotation_scale_name(),
|
||||
scene.document.header.current_annotation_scale
|
||||
);
|
||||
assert!(scene.viewport_annotation_scale_synced().is_none());
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
|
||||
Reference in new issue
Block a user