feat(props): make dim-line colour editable for leaders and dimensions

The "Dim line color" row on Leader and Dimension entities was
read-only: an earlier attempt wired it to Leader.override_color, which
acadrust never serialises, so the pick was lost on save. Store it
instead as a standard ACAD_DSTYLE per-object dimension-style override
(DXF code 176, an ACI index) through the existing dim_override codec,
so it round-trips through both DWG and DXF like the other dim
overrides. RGB picks collapse to the nearest ACI, matching the rest of
the dim-colour stack (dimension styles are index-only through the file
layer). The renderer prefers the override over the style's DIMCLRD.

The write branch is guarded to leaders and dimensions so a mixed
selection cannot stamp the override onto other entity types.

Bumps acadrust to c9fe982, which carries parsed XDATA onto dimensions
on DXF read (it was dropping common.extended_data), so the dimension
override persists on DXF save as well as DWG.

Co-Authored-By: Claude Opus 4.8 <[email protected]>
This commit is contained in:
Hakan SevenandClaude Opus 4.8 committed 2026-07-13 17:31:09 +03:00
1 parent 04bd49c715
commit d005cc4ab1
8 files changed
+241 -29

No files matched your search

+22 -18
View File
@@ -414,6 +414,20 @@ impl OpenCADStudio {
})
{
sections.extend(crate::entities::dimension::style_sections(style));
// The style groups are a read-only mirror, but the
// dim-line colour is an editable per-object override:
// prefer the ACAD_DSTYLE code-176 (ACI) override, else
// the style's DIMCLRD.
use crate::entities::dim_override as dov;
use crate::scene::model::object::PropValue;
let dim_c = dov::color(&d.base().common.extended_data, dov::DIMCLRD)
.unwrap_or_else(|| acadrust::types::Color::from_index(style.dimclrd));
set_row_value(
&mut sections,
"dim_line_color",
PropValue::ColorChoice(dim_c),
);
}
}
@@ -561,14 +575,16 @@ impl OpenCADStudio {
},
);
// Dim-line colour stays read-only: it lives in the
// leader's override_color, which the file format
// layer does not yet serialise, so making it
// editable would silently lose the pick on save.
set_row(
// Dim-line colour: a per-object ACAD_DSTYLE
// override (code 176, an ACI index) wins over the
// style's DIMCLRD. Editable — the picked colour is
// written back as that override so it round-trips.
let dim_c = dov::color(xd, dov::DIMCLRD)
.unwrap_or_else(|| acadrust::types::Color::from_index(ds.dimclrd));
set_row_value(
&mut sections,
"dim_line_color",
dim_color_label(ds.dimclrd, &ld.override_color),
PropValue::ColorChoice(dim_c),
);
let gap = dov::real(xd, dov::DIMGAP).unwrap_or(ds.dimgap);
@@ -1578,18 +1594,6 @@ fn dim_lineweight_label(dimlwd: i16) -> String {
}
}
/// DIMCLRD color (ACI) → label; ByBlock falls back to the leader's override.
fn dim_color_label(dimclrd: i16, override_color: &acadrust::types::Color) -> String {
match dimclrd {
0 => match override_color.rgb() {
Some((r, g, b)) => format!("RGB({r},{g},{b})"),
None => "ByBlock".to_string(),
},
256 => "ByLayer".to_string(),
n => format!("Color {n}"),
}
}
/// Human-readable INSUNITS name (DXF group 70 unit codes).
fn insunits_name(code: i16) -> &'static str {
match code {
+36
View File
@@ -2620,6 +2620,42 @@ impl OpenCADStudio {
Message::PropColorFieldChanged { field, color } => {
let i = self.active_tab;
let handles = self.property_target_handles(i);
// Dim-line colour override (Leader / Dimension): write it as an
// ACAD_DSTYLE code-176 override (an ACI index) so it round-trips
// through DWG and DXF. RGB picks collapse to the nearest ACI, in
// line with the rest of the dim-colour stack (index-only through
// the file layer). Guarded to leaders / dimensions so a mixed
// selection can't stamp the override onto other entities.
if field == "dim_line_color" {
let aci = color.approximate_index();
let targets: Vec<acadrust::Handle> = handles
.iter()
.copied()
.filter(|&h| {
matches!(
self.tabs[i].scene.document.get_entity(h),
Some(acadrust::EntityType::Leader(_))
| Some(acadrust::EntityType::Dimension(_))
)
})
.collect();
if !targets.is_empty() {
self.push_undo_snapshot(i, "CHPROP");
for &handle in &targets {
crate::entities::dim_override::set(
&mut self.tabs[i].scene.document,
handle,
crate::entities::dim_override::DIMCLRD,
Some(acadrust::xdata::XDataValue::Integer16(aci)),
);
}
self.invalidate_property_targets(i, &targets);
self.tabs[i].properties.open_color_field = None;
self.tabs[i].dirty = true;
self.refresh_properties();
}
return Task::none();
}
if !handles.is_empty() {
self.push_undo_snapshot(i, "CHPROP");
let idx = if field == "gradient_color_2" { 1 } else { 0 };