Add Graphic Attributes palette toggle and persistence

This commit is contained in:
Marcel committed 2026-09-29 21:34:31 +02:00
1 parent 3b74c7e7ea
commit 3e45331de1
14 files changed
+220 -71

No files matched your search

+5
View File
@@ -472,6 +472,11 @@ impl OpenCADStudio {
return Some(Task::done(Message::ToggleProperties));
}
// ── GRAPHICATTRIBUTES — toggle Graphic Attributes palette ───────────
"GRAPHICATTRIBUTES" => {
return Some(Task::done(Message::ToggleGraphicAttributes));
}
// ── FILETAB — toggle file/document tabs ──────────────────────────────
"FILETAB" => {
return Some(Task::done(Message::ToggleFileTabs));
+1
View File
@@ -386,6 +386,7 @@ inventory::submit!(crate::command::CommandRegistration {
"DSETTINGS",
"PARAMETERS",
"GRID",
"GRAPHICATTRIBUTES",
"ISODRAFT",
"ISOPLANE",
"OSNAP",
+15
View File
@@ -30,6 +30,8 @@ pub struct AppConfig {
/// General edge-stack dock layout (which panels are docked, side, order,
/// width and auto-collapse) for the Properties panel and block palette.
pub dock: crate::ui::dock::DockState,
/// Whether the optional Graphic Attributes palette is visible.
pub show_graphic_attributes: bool,
/// Add a newly selected annotation scale to existing annotative objects.
pub annotation_auto_scale: i8,
/// Ribbon collapse density.
@@ -52,6 +54,7 @@ impl Default for AppConfig {
start: StartConfig::default(),
statusbar: StatusBarConfig::default(),
dock: crate::ui::dock::DockState::default(),
show_graphic_attributes: false,
annotation_auto_scale: -4,
ribbon: RibbonConfig::default(),
plot: PlotDialogState::default(),
@@ -601,6 +604,18 @@ mod tests {
assert_eq!(deserialized.model_space.selection_window_color, 5);
}
#[test]
fn graphic_attributes_visibility_defaults_off_and_round_trips() {
let missing: AppConfig = serde_json::from_str("{}").expect("deserialize old config");
assert!(!missing.show_graphic_attributes);
let mut original = AppConfig::default();
original.show_graphic_attributes = true;
let serialized = serde_json::to_string(&original).expect("serialize config");
let restored: AppConfig = serde_json::from_str(&serialized).expect("deserialize config");
assert!(restored.show_graphic_attributes);
}
#[test]
fn test_parse_theme_name() {
assert_eq!(parse_theme_name("light"), Some(iced::Theme::Light));
+3 -1
View File
@@ -2807,6 +2807,8 @@ pub enum Message {
ToggleViewCube,
/// Toggle the Properties panel visibility (PROPERTIES).
ToggleProperties,
/// Toggle the Graphic Attributes panel visibility (GRAPHICATTRIBUTES).
ToggleGraphicAttributes,
/// Toggle the document file tabs at the top (FILETAB).
ToggleFileTabs,
/// Toggle the layout tabs at the bottom (LAYOUTTAB).
@@ -4167,7 +4169,7 @@ impl OpenCADStudio {
render_mode_menu_open: false,
render_mode_preview: None,
show_properties: true,
show_graphic_attributes: true,
show_graphic_attributes: false,
graphic_attributes_header_menu_open: false,
graphic_attribute_menu_open: false,
line_color_menu_open: false,
+32 -6
View File
@@ -130,7 +130,6 @@ fn close_fill_boundary(entity: &mut acadrust::EntityType) -> bool {
}
}
#[derive(Clone)]
struct ConcreteGraphicAttributes {
color: acadrust::types::Color,
linetype: String,
@@ -212,10 +211,11 @@ fn valid_layer_name(name: &str) -> bool {
!name.is_empty()
&& name.chars().count() <= 255
&& !name.chars().any(|character| {
matches!(
character,
'<' | '>' | '/' | '\\' | '"' | ':' | ';' | '?' | '*' | '|' | '=' | '`'
)
character.is_control()
|| matches!(
character,
'<' | '>' | '/' | '\\' | '"' | ':' | ';' | '?' | '*' | '|' | '=' | '`'
)
})
}
@@ -918,7 +918,10 @@ impl OpenCADStudio {
}
pub(super) fn on_line_linetype_scale(&mut self, scale: f64) -> iced::Task<Message> {
let scale = ((scale * 10.0).round() / 10.0).clamp(0.1, 1000.0);
let Some(scale) = crate::ui::window::graphic_attributes::normalized_linetype_scale(scale)
else {
return iced::Task::none();
};
let i = self.active_tab;
let selected = self.tabs[i].scene.selected_handles_in_order();
if selected.is_empty() {
@@ -1595,8 +1598,12 @@ impl OpenCADStudio {
}
PanelId::GraphicAttributes => {
self.show_graphic_attributes = false;
self.ribbon.set_graphic_attributes(false);
self.graphic_attributes_header_menu_open = false;
self.graphic_attribute_menu_open = false;
self.gradient_editor = None;
self.hatch_editor_handles = None;
self.save_config();
}
}
if self.dock_expanded == Some(id) {
@@ -2588,6 +2595,17 @@ mod tests {
.abs()
< f64::EPSILON
);
let _ = app.update(Message::LineLinetypeScaleChanged(f64::NAN));
assert_eq!(
app.tabs[i]
.scene
.document
.get_entity(line)
.expect("line")
.common()
.linetype_scale,
2.5
);
let _ = app.update(Message::LineLinetypeScaleChanged(1.2000000000000002));
assert_eq!(
app.tabs[i]
@@ -2817,6 +2835,14 @@ mod tests {
let _ = app.on_line_lineweight(acadrust::types::LineWeight::Value(35));
let _ = app.on_line_transparency(acadrust::types::Transparency::from_percent(0.3));
let _ = app.create_graphic_attributes_layer("Invalid\nLayer");
assert!(app.tabs[i]
.scene
.document
.layers
.get("Invalid\nLayer")
.is_none());
let _ = app.update(Message::GraphicAttributesCreateLayer);
assert_eq!(
app.tabs[i]
+4
View File
@@ -1086,6 +1086,7 @@ impl OpenCADStudio {
dock.ensure_settings();
dock
},
show_graphic_attributes: self.show_graphic_attributes,
annotation_auto_scale: self.annotation_auto_scale,
ribbon: crate::app::config::RibbonConfig {
collapse: self.ribbon.collapse_mode(),
@@ -1144,6 +1145,9 @@ impl OpenCADStudio {
let mut dock = cfg.dock;
dock.ensure_settings();
self.dock = dock;
self.show_graphic_attributes = cfg.show_graphic_attributes;
self.ribbon
.set_graphic_attributes(self.show_graphic_attributes);
self.annotation_auto_scale = cfg.annotation_auto_scale.clamp(-4, 4);
self.ribbon.set_collapse_mode(cfg.ribbon.collapse);
self.plot_dialog = cfg.plot;
+37
View File
@@ -4229,6 +4229,19 @@ impl OpenCADStudio {
self.ribbon.set_properties(self.show_properties);
Task::none()
}
Message::ToggleGraphicAttributes => {
self.show_graphic_attributes ^= true;
self.ribbon
.set_graphic_attributes(self.show_graphic_attributes);
if !self.show_graphic_attributes {
self.graphic_attributes_header_menu_open = false;
self.graphic_attribute_menu_open = false;
self.gradient_editor = None;
self.hatch_editor_handles = None;
}
self.save_config();
Task::none()
}
Message::ToggleFileTabs => {
self.show_file_tabs ^= true;
self.ribbon.set_file_tabs(self.show_file_tabs);
@@ -11220,6 +11233,30 @@ mod prop_pointer_tests {
}
}
#[cfg(test)]
mod graphic_attributes_visibility_tests {
use super::Message;
use crate::app::OpenCADStudio;
#[test]
fn graphic_attributes_starts_hidden_and_toggle_is_persisted() {
let mut app = OpenCADStudio::new_for_test();
app.apply_config(crate::app::config::AppConfig::default());
assert!(!app.show_graphic_attributes);
assert!(!app.ribbon.show_graphic_attributes);
let _ = app.update(Message::ToggleGraphicAttributes);
assert!(app.show_graphic_attributes);
assert!(app.ribbon.show_graphic_attributes);
assert!(app.current_config().show_graphic_attributes);
let _ = app.update(Message::ToggleGraphicAttributes);
assert!(!app.show_graphic_attributes);
assert!(!app.ribbon.show_graphic_attributes);
assert!(!app.current_config().show_graphic_attributes);
}
}
#[cfg(test)]
mod free_text_entry_tests {
//! The free-form text prompts (table cell content, TEXT / MTEXT bodies)