forked from 1b-agent/opencadstudio-upstream
fix(style): block edits to xref-dependent dimstyles
This commit is contained in:
1 parent
c0baeda6a6
commit
43bdd18061
3 files changed
+138
-2
No files matched your search
+24
-1
@@ -12050,7 +12050,9 @@ impl OpenCADStudio {
|
|||||||
Message::DimStyleDialogApply => {
|
Message::DimStyleDialogApply => {
|
||||||
let i = self.active_tab;
|
let i = self.active_tab;
|
||||||
self.apply_dimstyle_bufs(i);
|
self.apply_dimstyle_bufs(i);
|
||||||
self.style_stage_commit();
|
if !self.selected_dimstyle_is_read_only() {
|
||||||
|
self.style_stage_commit();
|
||||||
|
}
|
||||||
Task::none()
|
Task::none()
|
||||||
}
|
}
|
||||||
Message::DimStyleDialogSelect(name) => {
|
Message::DimStyleDialogSelect(name) => {
|
||||||
@@ -12073,6 +12075,9 @@ impl OpenCADStudio {
|
|||||||
Message::DimStyleDialogCopy => self.style_copy(crate::app::StyleKind::Dim),
|
Message::DimStyleDialogCopy => self.style_copy(crate::app::StyleKind::Dim),
|
||||||
Message::DimStyleDialogSetCurrent => {
|
Message::DimStyleDialogSetCurrent => {
|
||||||
// Staged: persists on Apply.
|
// Staged: persists on Apply.
|
||||||
|
if self.selected_dimstyle_is_read_only() {
|
||||||
|
return Task::none();
|
||||||
|
}
|
||||||
let i = self.active_tab;
|
let i = self.active_tab;
|
||||||
|
|
||||||
self.tabs[i].scene.document.header.current_dimstyle_name =
|
self.tabs[i].scene.document.header.current_dimstyle_name =
|
||||||
@@ -12093,6 +12098,9 @@ impl OpenCADStudio {
|
|||||||
Task::none()
|
Task::none()
|
||||||
}
|
}
|
||||||
Message::DsToggle(field) => {
|
Message::DsToggle(field) => {
|
||||||
|
if self.selected_dimstyle_is_read_only() {
|
||||||
|
return Task::none();
|
||||||
|
}
|
||||||
let separate_arrows = field == crate::app::DsField::Dimsah;
|
let separate_arrows = field == crate::app::DsField::Dimsah;
|
||||||
self.apply_ds_toggle(field);
|
self.apply_ds_toggle(field);
|
||||||
if separate_arrows && self.ds_dimsah {
|
if separate_arrows && self.ds_dimsah {
|
||||||
@@ -12114,6 +12122,9 @@ impl OpenCADStudio {
|
|||||||
Task::none()
|
Task::none()
|
||||||
}
|
}
|
||||||
Message::DsToleranceMode(mode) => {
|
Message::DsToleranceMode(mode) => {
|
||||||
|
if self.selected_dimstyle_is_read_only() {
|
||||||
|
return Task::none();
|
||||||
|
}
|
||||||
self.ds_dimlim = mode == "limits";
|
self.ds_dimlim = mode == "limits";
|
||||||
self.ds_dimtol = matches!(mode.as_str(), "symmetrical" | "deviation");
|
self.ds_dimtol = matches!(mode.as_str(), "symmetrical" | "deviation");
|
||||||
if mode == "symmetrical" {
|
if mode == "symmetrical" {
|
||||||
@@ -12128,6 +12139,9 @@ impl OpenCADStudio {
|
|||||||
Task::none()
|
Task::none()
|
||||||
}
|
}
|
||||||
Message::DsZeroBase(field, base) => {
|
Message::DsZeroBase(field, base) => {
|
||||||
|
if self.selected_dimstyle_is_read_only() {
|
||||||
|
return Task::none();
|
||||||
|
}
|
||||||
let current = match &field {
|
let current = match &field {
|
||||||
crate::app::DsField::Dimzin => &self.ds_dimzin,
|
crate::app::DsField::Dimzin => &self.ds_dimzin,
|
||||||
crate::app::DsField::Dimaltz => &self.ds_dimaltz,
|
crate::app::DsField::Dimaltz => &self.ds_dimaltz,
|
||||||
@@ -12142,6 +12156,9 @@ impl OpenCADStudio {
|
|||||||
Task::none()
|
Task::none()
|
||||||
}
|
}
|
||||||
Message::DsZeroFlag(field, bit) => {
|
Message::DsZeroFlag(field, bit) => {
|
||||||
|
if self.selected_dimstyle_is_read_only() {
|
||||||
|
return Task::none();
|
||||||
|
}
|
||||||
let current = match &field {
|
let current = match &field {
|
||||||
crate::app::DsField::Dimzin => &self.ds_dimzin,
|
crate::app::DsField::Dimzin => &self.ds_dimzin,
|
||||||
crate::app::DsField::Dimaltz => &self.ds_dimaltz,
|
crate::app::DsField::Dimaltz => &self.ds_dimaltz,
|
||||||
@@ -12156,6 +12173,9 @@ impl OpenCADStudio {
|
|||||||
Task::none()
|
Task::none()
|
||||||
}
|
}
|
||||||
Message::DsCenterMarkMode(mode) => {
|
Message::DsCenterMarkMode(mode) => {
|
||||||
|
if self.selected_dimstyle_is_read_only() {
|
||||||
|
return Task::none();
|
||||||
|
}
|
||||||
let size = self.ds_dimcen.trim().parse::<f64>().unwrap_or(0.09).abs();
|
let size = self.ds_dimcen.trim().parse::<f64>().unwrap_or(0.09).abs();
|
||||||
self.ds_dimcen = match mode.as_str() {
|
self.ds_dimcen = match mode.as_str() {
|
||||||
"mark" => size.max(f64::EPSILON).to_string(),
|
"mark" => size.max(f64::EPSILON).to_string(),
|
||||||
@@ -12165,6 +12185,9 @@ impl OpenCADStudio {
|
|||||||
Task::none()
|
Task::none()
|
||||||
}
|
}
|
||||||
Message::DsColorMore(field) => {
|
Message::DsColorMore(field) => {
|
||||||
|
if self.selected_dimstyle_is_read_only() {
|
||||||
|
return Task::none();
|
||||||
|
}
|
||||||
self.ds_color_open = if self.ds_color_open.as_ref() == Some(&field) {
|
self.ds_color_open = if self.ds_color_open.as_ref() == Some(&field) {
|
||||||
None
|
None
|
||||||
} else {
|
} else {
|
||||||
|
|||||||
@@ -21,6 +21,18 @@ use iced::time::Instant;
|
|||||||
use iced::{mouse, Point, Task};
|
use iced::{mouse, Point, Task};
|
||||||
|
|
||||||
impl OpenCADStudio {
|
impl OpenCADStudio {
|
||||||
|
pub(in crate::app) fn selected_dimstyle_is_read_only(&self) -> bool {
|
||||||
|
let Some(style) = self.tabs[self.active_tab]
|
||||||
|
.scene
|
||||||
|
.document
|
||||||
|
.dim_styles
|
||||||
|
.get(&self.dimstyle_selected)
|
||||||
|
else {
|
||||||
|
return true;
|
||||||
|
};
|
||||||
|
style.xref_dependent || style.name.contains('|')
|
||||||
|
}
|
||||||
|
|
||||||
pub(in crate::app) fn mlstyle_mut(
|
pub(in crate::app) fn mlstyle_mut(
|
||||||
&mut self,
|
&mut self,
|
||||||
tab: usize,
|
tab: usize,
|
||||||
@@ -364,6 +376,17 @@ impl OpenCADStudio {
|
|||||||
pub(in crate::app) fn apply_dimstyle_bufs(&mut self, tab: usize) {
|
pub(in crate::app) fn apply_dimstyle_bufs(&mut self, tab: usize) {
|
||||||
let doc = &mut self.tabs[tab].scene.document;
|
let doc = &mut self.tabs[tab].scene.document;
|
||||||
|
|
||||||
|
// Merged xref dimstyles are identified by their `xref|style` name.
|
||||||
|
// The codec's dependency bit is cleared during merge, so use the
|
||||||
|
// stable imported-name marker here as well as the DWG/DXF flag.
|
||||||
|
let selected_name = self.dimstyle_selected.clone();
|
||||||
|
let Some(selected) = doc.dim_styles.get(&selected_name) else {
|
||||||
|
return;
|
||||||
|
};
|
||||||
|
if selected.xref_dependent || selected.name.contains('|') {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
let text_style_handle = doc
|
let text_style_handle = doc
|
||||||
.text_styles
|
.text_styles
|
||||||
.get(&self.ds_dimtxsty)
|
.get(&self.ds_dimtxsty)
|
||||||
@@ -499,6 +522,9 @@ impl OpenCADStudio {
|
|||||||
/// Update a single string buffer field.
|
/// Update a single string buffer field.
|
||||||
|
|
||||||
pub(in crate::app) fn apply_ds_edit(&mut self, field: crate::app::DsField, val: String) {
|
pub(in crate::app) fn apply_ds_edit(&mut self, field: crate::app::DsField, val: String) {
|
||||||
|
if self.selected_dimstyle_is_read_only() {
|
||||||
|
return;
|
||||||
|
}
|
||||||
use crate::app::DsField::*;
|
use crate::app::DsField::*;
|
||||||
match field {
|
match field {
|
||||||
Dimdle => self.ds_dimdle = val,
|
Dimdle => self.ds_dimdle = val,
|
||||||
@@ -570,6 +596,9 @@ impl OpenCADStudio {
|
|||||||
/// Toggle a boolean buffer field.
|
/// Toggle a boolean buffer field.
|
||||||
|
|
||||||
pub(in crate::app) fn apply_ds_toggle(&mut self, field: crate::app::DsField) {
|
pub(in crate::app) fn apply_ds_toggle(&mut self, field: crate::app::DsField) {
|
||||||
|
if self.selected_dimstyle_is_read_only() {
|
||||||
|
return;
|
||||||
|
}
|
||||||
use crate::app::DsField::*;
|
use crate::app::DsField::*;
|
||||||
match field {
|
match field {
|
||||||
Dimsd1 => self.ds_dimsd1 = !self.ds_dimsd1,
|
Dimsd1 => self.ds_dimsd1 = !self.ds_dimsd1,
|
||||||
@@ -1260,6 +1289,9 @@ impl OpenCADStudio {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub(super) fn on_ds_set_handle(&mut self, field: &'static str, value: String) -> Task<Message> {
|
pub(super) fn on_ds_set_handle(&mut self, field: &'static str, value: String) -> Task<Message> {
|
||||||
|
if self.selected_dimstyle_is_read_only() {
|
||||||
|
return Task::none();
|
||||||
|
}
|
||||||
let i = self.active_tab;
|
let i = self.active_tab;
|
||||||
let name = self.dimstyle_selected.clone();
|
let name = self.dimstyle_selected.clone();
|
||||||
let is_lt = matches!(
|
let is_lt = matches!(
|
||||||
@@ -1358,4 +1390,84 @@ mod ds_set_handle_tests {
|
|||||||
"picking the first arrowhead must not touch the second"
|
"picking the first arrowhead must not touch the second"
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn xref_dimstyle_is_read_only_and_rejects_direct_edits() {
|
||||||
|
let mut app = app_with_arrow_blocks();
|
||||||
|
let i = app.active_tab;
|
||||||
|
let name = app.dimstyle_selected.clone();
|
||||||
|
let before = app.tabs[i]
|
||||||
|
.scene
|
||||||
|
.document
|
||||||
|
.dim_styles
|
||||||
|
.get(&name)
|
||||||
|
.unwrap()
|
||||||
|
.dimdle;
|
||||||
|
app.tabs[i]
|
||||||
|
.scene
|
||||||
|
.document
|
||||||
|
.dim_styles
|
||||||
|
.get_mut(&name)
|
||||||
|
.unwrap()
|
||||||
|
.xref_dependent = true;
|
||||||
|
assert!(app.selected_dimstyle_is_read_only());
|
||||||
|
|
||||||
|
app.ds_dimdle = "123".to_string();
|
||||||
|
app.apply_dimstyle_bufs(i);
|
||||||
|
let _ = app.on_ds_set_handle("dimblk1", "ARROW_A".to_string());
|
||||||
|
|
||||||
|
assert_eq!(
|
||||||
|
app.tabs[i]
|
||||||
|
.scene
|
||||||
|
.document
|
||||||
|
.dim_styles
|
||||||
|
.get(&name)
|
||||||
|
.unwrap()
|
||||||
|
.dimdle,
|
||||||
|
before
|
||||||
|
);
|
||||||
|
assert_eq!(
|
||||||
|
app.tabs[i]
|
||||||
|
.scene
|
||||||
|
.document
|
||||||
|
.dim_styles
|
||||||
|
.get(&name)
|
||||||
|
.unwrap()
|
||||||
|
.dimblk1,
|
||||||
|
codec::types::Handle::NULL
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn merged_xref_dimstyle_name_is_read_only() {
|
||||||
|
let mut app = app_with_arrow_blocks();
|
||||||
|
let i = app.active_tab;
|
||||||
|
let old_name = app.dimstyle_selected.clone();
|
||||||
|
let mut style = app.tabs[i]
|
||||||
|
.scene
|
||||||
|
.document
|
||||||
|
.dim_styles
|
||||||
|
.get(&old_name)
|
||||||
|
.unwrap()
|
||||||
|
.clone();
|
||||||
|
let before = style.dimdle;
|
||||||
|
app.tabs[i].scene.document.dim_styles.remove(&old_name);
|
||||||
|
style.name = "ARCH|Imported".to_string();
|
||||||
|
app.tabs[i].scene.document.dim_styles.add_or_replace(style);
|
||||||
|
app.dimstyle_selected = "ARCH|Imported".to_string();
|
||||||
|
|
||||||
|
assert!(app.selected_dimstyle_is_read_only());
|
||||||
|
app.ds_dimdle = "456".to_string();
|
||||||
|
app.apply_dimstyle_bufs(i);
|
||||||
|
assert_ne!(
|
||||||
|
app.tabs[i]
|
||||||
|
.scene
|
||||||
|
.document
|
||||||
|
.dim_styles
|
||||||
|
.get("ARCH|Imported")
|
||||||
|
.unwrap()
|
||||||
|
.dimdle,
|
||||||
|
before
|
||||||
|
);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
@@ -1477,7 +1477,8 @@ impl OpenCADStudio {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
let ds_sel = doc.dim_styles.get(&self.dimstyle_selected);
|
let ds_sel = doc.dim_styles.get(&self.dimstyle_selected);
|
||||||
let read_only = false;
|
let read_only =
|
||||||
|
ds_sel.is_none_or(|style| style.xref_dependent || style.name.contains('|'));
|
||||||
let in_use = doc.entities().any(|entity| {
|
let in_use = doc.entities().any(|entity| {
|
||||||
matches!(entity, codec::EntityType::Dimension(dimension)
|
matches!(entity, codec::EntityType::Dimension(dimension)
|
||||||
if dimension.base().style_name.eq_ignore_ascii_case(&self.dimstyle_selected))
|
if dimension.base().style_name.eq_ignore_ascii_case(&self.dimstyle_selected))
|
||||||
|
|||||||
Reference in new issue
Block a user