Match active view properties palette

This commit is contained in:
ramox81 committed 2026-09-14 16:56:48 +03:00
1 parent fc1788df65
commit 88839b783a
2 files changed
+333 -60

No files matched your search

+94 -60
View File
@@ -247,28 +247,63 @@ impl OpenCADStudio {
.then(|| header.stylesheet.clone())
})
.unwrap_or_else(|| "None".to_string());
let ucs_per_viewport = scene
let active_model_vport = doc.vports.iter().find(|viewport| {
viewport
.name
.trim_start_matches('*')
.eq_ignore_ascii_case("active")
});
let active_entity_viewport = scene
.active_viewport
.and_then(|handle| doc.get_entity(handle))
.and_then(|entity| match entity {
acadrust::EntityType::Viewport(viewport) => {
Some(viewport.ucs_per_viewport)
}
acadrust::EntityType::Viewport(viewport) => Some(viewport),
_ => None,
})
.unwrap_or(false);
});
let ucs_icon_on = active_entity_viewport
.map(|viewport| viewport.ucs_icon_visible)
.or_else(|| active_model_vport.map(|viewport| viewport.ucsicon_lower))
.unwrap_or(self.show_ucs_icon);
let ucs_icon_at_origin = active_entity_viewport
.map(|viewport| viewport.ucs_icon_at_origin)
.or_else(|| active_model_vport.map(|viewport| viewport.ucsicon_origin))
.unwrap_or(self.ucs_icon_at_origin);
let ucs_per_viewport = active_entity_viewport
.map(|viewport| viewport.ucs_per_viewport)
.or_else(|| active_model_vport.map(|viewport| viewport.ucs_per_viewport))
.unwrap_or(true);
let ucs_name = tab
.active_ucs
.as_ref()
.map(|ucs| ucs.name.trim())
.filter(|name| !name.is_empty())
.unwrap_or("World")
.unwrap_or("")
.to_string();
let annotation_scale = if header.current_annotation_scale.trim().is_empty() {
"1:1".to_string()
} else {
header.current_annotation_scale.clone()
};
let annotation_scale_options = scene
.scale_list()
.into_iter()
.map(|(name, _, _)| name)
.collect();
let mut plot_table_options = vec!["None".to_string()];
plot_table_options.extend(crate::io::plot_style::available_ctb_names());
let visual_style = match tab.visual_style.as_str() {
"Wireframe 2D" => t!("2D Wireframe").into_owned(),
"Wireframe 3D" => t!("3D Wireframe").into_owned(),
value => value.to_string(),
};
let visual_style_options = crate::modules::view::visual_style::VISUAL_STYLES
.iter()
.map(|style| match style.label {
"Wireframe 2D" => t!("2D Wireframe").into_owned(),
"Wireframe 3D" => t!("3D Wireframe").into_owned(),
value => value.to_string(),
})
.collect();
let sections = vec![
PropSection {
title: t!("General").into_owned(),
@@ -356,18 +391,23 @@ impl OpenCADStudio {
}
},
},
read_only(t!("Plot style table").as_ref(), plot_table.clone()),
Property {
label: t!("Plot style table").into_owned(),
field: "view_plot_style_table",
value: PropValue::Choice {
selected: plot_table.clone(),
options: plot_table_options,
},
},
read_only(
t!("Plot table attached to").as_ref(),
if plot_table == "None" {
"None".to_string()
} else {
scene.current_layout.clone()
},
scene.current_layout.clone(),
),
read_only(
t!("Plot table type").as_ref(),
if header.plotstyle_mode {
if plot_table == "None" {
t!("Not available").into_owned()
} else if header.plotstyle_mode {
t!("Color-dependent plot styles").into_owned()
} else {
t!("Named plot styles").into_owned()
@@ -388,55 +428,49 @@ impl OpenCADStudio {
PropSection {
title: t!("Misc").into_owned(),
props: vec![
read_only(t!("Annotation scale").as_ref(), annotation_scale),
read_only(
t!("UCS icon On").as_ref(),
if self.show_ucs_icon { "Yes" } else { "No" }.to_string(),
),
read_only(
t!("UCS icon at origin").as_ref(),
if self.ucs_icon_at_origin { "Yes" } else { "No" }
.to_string(),
),
read_only(
t!("UCS per viewport").as_ref(),
if ucs_per_viewport { "Yes" } else { "No" }.to_string(),
),
Property {
label: t!("Annotation scale").into_owned(),
field: "view_annotation_scale",
value: PropValue::Choice {
selected: annotation_scale,
options: annotation_scale_options,
},
},
Property {
label: t!("UCS icon On").into_owned(),
field: "view_ucs_icon_on",
value: PropValue::Choice {
selected: if ucs_icon_on { "Yes" } else { "No" }.to_string(),
options: vec!["Yes".to_string(), "No".to_string()],
},
},
Property {
label: t!("UCS icon at origin").into_owned(),
field: "view_ucs_icon_at_origin",
value: PropValue::Choice {
selected: if ucs_icon_at_origin { "Yes" } else { "No" }.to_string(),
options: vec!["Yes".to_string(), "No".to_string()],
},
},
Property {
label: t!("UCS per viewport").into_owned(),
field: "view_ucs_per_viewport",
value: PropValue::Choice {
selected: if ucs_per_viewport { "Yes" } else { "No" }.to_string(),
options: vec!["Yes".to_string(), "No".to_string()],
},
},
read_only(t!("UCS Name").as_ref(), ucs_name),
read_only(t!("Visual Style").as_ref(), tab.visual_style.clone()),
Property {
label: t!("Visual Style").into_owned(),
field: "view_visual_style",
value: PropValue::Choice {
selected: visual_style,
options: visual_style_options,
},
},
],
},
// Document-wide named-parameter table embedded here
// instead of a separate modal — see `PropValue::
// ParamRow`'s doc comment. Belongs on the no-
// selection (drawing-level) page, not a per-entity
// one: a parameter isn't owned by any one entity.
PropSection {
title: t!("Parameters").into_owned(),
props: {
let mut props: Vec<Property> = scene
.named_parameters()
.iter()
.enumerate()
.map(|(index, p)| Property {
label: String::new(),
field: "named_parameter",
value: PropValue::ParamRow {
index,
name: p.name.clone(),
formula: p.source.clone(),
resolved: scene.named_parameters().resolve(&p.name).map_err(|e| e.to_string()),
},
})
.collect();
props.push(Property {
label: String::new(),
field: "named_parameter_add",
value: PropValue::ParamAddRow,
});
props
},
},
];
ui::PropertiesPanel {
title: t!("No selection").into_owned(),
+239
View File
@@ -2993,6 +2993,245 @@ pub(super) fn on_tab_close(&mut self, idx: usize) -> Task<Message> {
self.tabs[i].dirty = true;
self.refresh_properties();
}
"view_plot_style_table" => {
let next = if value.eq_ignore_ascii_case("None") {
String::new()
} else {
value.clone()
};
let layout_name = self.tabs[i].scene.current_layout.clone();
let current = self.tabs[i]
.scene
.document
.objects
.values()
.find_map(|object| {
let acadrust::objects::ObjectType::Layout(layout) = object
else {
return None;
};
layout
.name
.eq_ignore_ascii_case(&layout_name)
.then(|| layout.plot_style_sheet.clone())
})
.unwrap_or_else(|| {
self.tabs[i].scene.document.header.stylesheet.clone()
});
if current != next {
self.push_undo_snapshot(i, "PLOTSTYLE");
for object in self.tabs[i].scene.document.objects.values_mut() {
if let acadrust::objects::ObjectType::Layout(layout) = object {
if layout.name.eq_ignore_ascii_case(&layout_name) {
layout.plot_style_sheet = next.clone();
layout.plot_flags.plot_plot_styles = !next.is_empty();
layout.plot_flags.show_plot_styles = !next.is_empty();
}
}
}
self.tabs[i].scene.document.header.stylesheet = next;
self.tabs[i].dirty = true;
}
self.refresh_properties();
}
"view_annotation_scale" => {
let current = self.tabs[i]
.scene
.document
.header
.current_annotation_scale
.clone();
if !current.eq_ignore_ascii_case(&value) {
self.push_undo_snapshot(i, "CANNOSCALE");
if self.tabs[i].scene.set_annotation_scale_named(&value).is_some() {
self.tabs[i].dirty = true;
} else {
self.discard_last_undo_entry(i);
}
}
self.refresh_properties();
}
"view_ucs_icon_on" => {
let next = value.eq_ignore_ascii_case("Yes");
let active_viewport = self.tabs[i].scene.active_viewport;
let current = active_viewport
.and_then(|handle| self.tabs[i].scene.document.get_entity(handle))
.and_then(|entity| match entity {
acadrust::EntityType::Viewport(viewport) => {
Some(viewport.ucs_icon_visible)
}
_ => None,
})
.or_else(|| {
self.tabs[i]
.scene
.document
.vports
.iter()
.find(|viewport| {
viewport
.name
.trim_start_matches('*')
.eq_ignore_ascii_case("active")
})
.map(|viewport| viewport.ucsicon_lower)
})
.unwrap_or(self.show_ucs_icon);
if current != next {
self.push_undo_snapshot(i, "UCSICON");
if let Some(handle) = active_viewport {
if let Some(acadrust::EntityType::Viewport(viewport)) =
self.tabs[i].scene.document.get_entity_mut(handle)
{
viewport.ucs_icon_visible = next;
}
} else if let Some(viewport) = self.tabs[i]
.scene
.document
.vports
.iter_mut()
.find(|viewport| {
viewport
.name
.trim_start_matches('*')
.eq_ignore_ascii_case("active")
})
{
viewport.ucsicon_lower = next;
}
self.show_ucs_icon = next;
self.persist_settings_if_changed();
self.tabs[i].dirty = true;
}
self.refresh_properties();
}
"view_ucs_icon_at_origin" => {
let next = value.eq_ignore_ascii_case("Yes");
let active_viewport = self.tabs[i].scene.active_viewport;
let current = active_viewport
.and_then(|handle| self.tabs[i].scene.document.get_entity(handle))
.and_then(|entity| match entity {
acadrust::EntityType::Viewport(viewport) => {
Some(viewport.ucs_icon_at_origin)
}
_ => None,
})
.or_else(|| {
self.tabs[i]
.scene
.document
.vports
.iter()
.find(|viewport| {
viewport
.name
.trim_start_matches('*')
.eq_ignore_ascii_case("active")
})
.map(|viewport| viewport.ucsicon_origin)
})
.unwrap_or(self.ucs_icon_at_origin);
if current != next {
self.push_undo_snapshot(i, "UCSICON");
if let Some(handle) = active_viewport {
if let Some(acadrust::EntityType::Viewport(viewport)) =
self.tabs[i].scene.document.get_entity_mut(handle)
{
viewport.ucs_icon_at_origin = next;
}
} else if let Some(viewport) = self.tabs[i]
.scene
.document
.vports
.iter_mut()
.find(|viewport| {
viewport
.name
.trim_start_matches('*')
.eq_ignore_ascii_case("active")
})
{
viewport.ucsicon_origin = next;
}
self.ucs_icon_at_origin = next;
self.persist_settings_if_changed();
self.tabs[i].dirty = true;
}
self.refresh_properties();
}
"view_ucs_per_viewport" => {
let next = value.eq_ignore_ascii_case("Yes");
let active_viewport = self.tabs[i].scene.active_viewport;
let current = active_viewport
.and_then(|handle| self.tabs[i].scene.document.get_entity(handle))
.and_then(|entity| match entity {
acadrust::EntityType::Viewport(viewport) => {
Some(viewport.ucs_per_viewport)
}
_ => None,
})
.or_else(|| {
self.tabs[i]
.scene
.document
.vports
.iter()
.find(|viewport| {
viewport
.name
.trim_start_matches('*')
.eq_ignore_ascii_case("active")
})
.map(|viewport| viewport.ucs_per_viewport)
})
.unwrap_or(true);
if current != next {
self.push_undo_snapshot(i, "UCSVP");
if let Some(handle) = active_viewport {
if let Some(acadrust::EntityType::Viewport(viewport)) =
self.tabs[i].scene.document.get_entity_mut(handle)
{
viewport.ucs_per_viewport = next;
}
} else if let Some(viewport) = self.tabs[i]
.scene
.document
.vports
.iter_mut()
.find(|viewport| {
viewport
.name
.trim_start_matches('*')
.eq_ignore_ascii_case("active")
})
{
viewport.ucs_per_viewport = next;
}
self.tabs[i].dirty = true;
}
self.refresh_properties();
}
"view_visual_style" => {
use acadrust::entities::ViewportRenderMode as Mode;
let mode = match value.as_str() {
"2D Wireframe" | "Wireframe 2D" => Some(Mode::Wireframe2D),
"3D Wireframe" | "Wireframe 3D" => Some(Mode::Wireframe3D),
"Hidden Line" => Some(Mode::HiddenLine),
"Flat Shaded" => Some(Mode::FlatShaded),
"Gouraud Shaded" => Some(Mode::GouraudShaded),
"Flat Shaded + Edges" => Some(Mode::FlatShadedWithEdges),
"Gouraud Shaded + Edges" => {
Some(Mode::GouraudShadedWithEdges)
}
_ => None,
};
if let Some(mode) = mode {
let task = self.on_set_render_mode(mode);
self.refresh_properties();
return task;
}
self.refresh_properties();
}
_ => {}
}
}