feat(hatch): editable gradient colors + background color

Gradient Type (One/Two color), Color 1 and Color 2 editable via a generic field-keyed colour picker path. Background colour editable and stored as HATCHBACKGROUNDCOLOR extended data (group 1071 true colour), rendered in OCS as a solid backdrop drawn behind the pattern. Hide Origin X/Y for gradients (pattern-only concept) and drop the redundant gradient rows from the pattern branch.

Co-Authored-By: Claude Opus 4.8 <[email protected]>
This commit is contained in:
Hakan SevenandClaude Opus 4.8 committed 2026-07-08 23:35:27 +03:00
1 parent 22059e138c
commit b5106c82b5
5 files changed
+190 -27

No files matched your search

+6
View File
@@ -1558,6 +1558,12 @@ pub enum Message {
/// User picked an MTEXT background fill colour — sets `background_color`
/// and switches the background mode to Fill so it shows immediately.
PropBgColorChanged(AcadColor),
/// Toggle the generic per-field colour picker (e.g. a hatch gradient colour)
/// identified by its property field name.
PropColorFieldToggle(String),
/// User picked a colour for a generic per-field colour row (hatch gradient
/// `Color 1` / `Color 2`), routed by the field name.
PropColorFieldChanged { field: String, color: AcadColor },
/// Collapse the inline color picker dropdown. Fired when another
/// properties-panel dropdown (a combo_box) opens, so at most one panel
/// dropdown is open at a time and they can't overlap. (#235)
+60 -7
View File
@@ -2279,13 +2279,18 @@ impl OpenCADStudio {
if !handles.is_empty() {
self.push_undo_snapshot(i, "CHPROP");
for &handle in &handles {
if let Some(acadrust::EntityType::MText(m)) =
self.tabs[i].scene.document.get_entity_mut(handle)
{
m.background_color = color.clone();
// Picking a colour turns the background on in Fill
// mode (specific colour), preserving the frame bit.
m.background_fill_flags = (m.background_fill_flags & !0x02) | 0x01;
match self.tabs[i].scene.document.get_entity_mut(handle) {
Some(acadrust::EntityType::MText(m)) => {
m.background_color = color.clone();
// Picking a colour turns the background on in Fill
// mode (specific colour), preserving the frame bit.
m.background_fill_flags =
(m.background_fill_flags & !0x02) | 0x01;
}
Some(acadrust::EntityType::Hatch(h)) => {
crate::entities::hatch::set_background_color(h, &color);
}
_ => {}
}
}
self.invalidate_property_targets(i, &handles);
@@ -2296,6 +2301,54 @@ impl OpenCADStudio {
Task::none()
}
Message::PropColorFieldToggle(field) => {
let i = self.active_tab;
let p = &mut self.tabs[i].properties;
p.open_color_field = if p.open_color_field.as_deref() == Some(field.as_str()) {
None
} else {
Some(field)
};
Task::none()
}
Message::PropColorFieldChanged { field, color } => {
let i = self.active_tab;
let handles = self.property_target_handles(i);
if !handles.is_empty() {
self.push_undo_snapshot(i, "CHPROP");
let idx = if field == "gradient_color_2" { 1 } else { 0 };
for &handle in &handles {
if let Some(acadrust::EntityType::Hatch(h)) =
self.tabs[i].scene.document.get_entity_mut(handle)
{
while h.gradient_color.colors.len() <= idx {
let value = if h.gradient_color.colors.is_empty() {
0.0
} else {
1.0
};
h.gradient_color.colors.push(
acadrust::entities::hatch::GradientColorEntry {
value,
color: acadrust::types::Color::Index(7),
},
);
}
h.gradient_color.colors[idx].color = color.clone();
}
}
// Rebuild hatch seeds so the gradient fill picks up the new
// colour (synced_hatch_models only patches the main colour).
self.tabs[i].scene.populate_hatches_from_document();
self.invalidate_property_targets(i, &handles);
self.tabs[i].properties.open_color_field = None;
self.tabs[i].dirty = true;
self.refresh_properties();
}
Task::none()
}
Message::PropColorPickerClose => {
let i = self.active_tab;
self.tabs[i].properties.color_picker_open = false;