From 984fa79189ab20ebf878dbf6622aa34b999de923 Mon Sep 17 00:00:00 2001 From: Hakan Seven Date: Sun, 12 Jul 2026 23:24:34 +0300 Subject: [PATCH] feat(properties): make the Hyperlink field editable MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The General-group Hyperlink row becomes an editable text field; committing a value writes the standard PE_URL XDATA record (an empty value clears it). Adds scene::view::dispatch::set_common_xdata, which rebuilds an entity's XDATA to replace or remove a single application record — ExtendedData only appends, so a plain add_record would leave a stale duplicate the reader would pick first. Co-Authored-By: Claude Opus 4.8 --- src/app/update/command.rs | 14 ++++++++++++++ src/scene/cache/properties.rs | 2 +- src/scene/view/dispatch.rs | 28 ++++++++++++++++++++++++++++ 3 files changed, 43 insertions(+), 1 deletion(-) diff --git a/src/app/update/command.rs b/src/app/update/command.rs index 6286b36b1..18b3c3125 100644 --- a/src/app/update/command.rs +++ b/src/app/update/command.rs @@ -1460,6 +1460,20 @@ pub(super) fn on_tab_close(&mut self, idx: usize) -> Task { entity, field, &val, ); } + "hyperlink" => { + // Stored in the standard PE_URL XDATA + // record; an empty value clears it. + let vals = if val.trim().is_empty() { + None + } else { + Some(vec![acadrust::xdata::XDataValue::String( + val.clone(), + )]) + }; + crate::scene::view::dispatch::set_common_xdata( + entity, "PE_URL", vals, + ); + } _ => { crate::scene::view::dispatch::apply_geom_prop( entity, field, &val, diff --git a/src/scene/cache/properties.rs b/src/scene/cache/properties.rs index 35409d798..31622b85f 100644 --- a/src/scene/cache/properties.rs +++ b/src/scene/cache/properties.rs @@ -85,7 +85,7 @@ pub fn general_section(entity: &EntityType) -> PropSection { Property { label: "Hyperlink".into(), field: "hyperlink", - value: PropValue::ReadOnly(hyperlink), + value: PropValue::EditText(hyperlink), }, ], }; diff --git a/src/scene/view/dispatch.rs b/src/scene/view/dispatch.rs index f1f3b9ef0..3c027c4df 100644 --- a/src/scene/view/dispatch.rs +++ b/src/scene/view/dispatch.rs @@ -85,6 +85,34 @@ pub fn apply_common_prop(entity: &mut EntityType, field: &str, value: &str) { } } +/// Replace — or, when `values` is `None`, remove — the single XDATA record for +/// application `app` on an entity's common data, preserving every other record +/// and the verbatim DWG EED blob. `ExtendedData` only appends, so a plain +/// `add_record` would leave a stale duplicate that the reader picks first; +/// rebuilding the collection is the only way to edit or clear a record. +pub fn set_common_xdata( + entity: &mut EntityType, + app: &str, + values: Option>, +) { + let common = entity.common_mut(); + let mut rebuilt = acadrust::xdata::ExtendedData::new(); + for r in common.extended_data.records() { + if r.application_name != app { + rebuilt.add_record(r.clone()); + } + } + if let Some(vals) = values { + let mut rec = acadrust::xdata::ExtendedDataRecord::new(app); + for v in vals { + rec.add_value(v); + } + rebuilt.add_record(rec); + } + rebuilt.raw_dwg_eed = common.extended_data.raw_dwg_eed.clone(); + common.extended_data = rebuilt; +} + /// The extrusion thickness (DXF 39) of the entities that carry one, or `None` /// for entity types that have none. Thickness is a per-entity field but is /// surfaced in the General group (as in a standard properties palette), so