Merge current main while preserving text property behavior. Bound column allocations and correct boundary, UCS, caret, and column-flow calculations.
180 lines
6.2 KiB
Rust
180 lines
6.2 KiB
Rust
use acadrust::{EntityType, Handle};
|
|
use crate::t;
|
|
|
|
use crate::scene::model::object::{PropSection, PropValue, Property};
|
|
|
|
pub fn general_section(entity: &EntityType) -> PropSection {
|
|
let common = entity.common();
|
|
let linetype_display = if common.linetype.is_empty() {
|
|
"ByLayer".to_string()
|
|
} else {
|
|
common.linetype.clone()
|
|
};
|
|
// Alpha 0 is ByLayer, Alpha 1 is ByBlock; show them by name and fall back
|
|
// to a rounded percentage for explicit values.
|
|
let transp_display = match common.transparency.alpha() {
|
|
0 => "ByLayer".to_string(),
|
|
1 => "ByBlock".to_string(),
|
|
alpha => format!(
|
|
"{}",
|
|
(alpha as f64 / 255.0 * 100.0).round() as u32
|
|
),
|
|
};
|
|
|
|
// Hyperlink is stored in XDATA under the "PE_URL" application.
|
|
let hyperlink = common
|
|
.extended_data
|
|
.get_record("PE_URL")
|
|
.and_then(|r| {
|
|
r.values.iter().find_map(|v| match v {
|
|
acadrust::xdata::XDataValue::String(s) if !s.is_empty() => Some(s.clone()),
|
|
_ => None,
|
|
})
|
|
})
|
|
.unwrap_or_default();
|
|
|
|
let mut section = PropSection {
|
|
title: t!("General").into_owned(),
|
|
props: vec![
|
|
Property {
|
|
label: t!("Handle").into_owned(),
|
|
field: "handle",
|
|
value: PropValue::ReadOnly(common.handle.value().to_string()),
|
|
},
|
|
Property {
|
|
label: t!("Color").into_owned(),
|
|
field: "color",
|
|
value: PropValue::ColorChoice(common.color),
|
|
},
|
|
Property {
|
|
label: t!("Layer").into_owned(),
|
|
field: "layer",
|
|
value: PropValue::LayerChoice(common.layer.clone()),
|
|
},
|
|
Property {
|
|
label: t!("Linetype").into_owned(),
|
|
field: "linetype",
|
|
value: PropValue::LinetypeChoice(linetype_display),
|
|
},
|
|
Property {
|
|
label: t!("Linetype scale").into_owned(),
|
|
field: "linetype_scale",
|
|
value: PropValue::EditText(format!("{:.4}", common.linetype_scale)),
|
|
},
|
|
Property {
|
|
label: t!("Plot style").into_owned(),
|
|
field: "plot_style",
|
|
value: PropValue::ReadOnly(
|
|
match common.plotstyle_flags {
|
|
0 => "ByLayer",
|
|
1 => "ByBlock",
|
|
_ => "ByColor",
|
|
}
|
|
.into(),
|
|
),
|
|
},
|
|
Property {
|
|
label: t!("Lineweight").into_owned(),
|
|
field: "lineweight",
|
|
value: PropValue::LwChoice(common.line_weight),
|
|
},
|
|
Property {
|
|
label: t!("Transparency").into_owned(),
|
|
field: "transparency",
|
|
value: PropValue::EditChoice {
|
|
value: transp_display,
|
|
options: vec!["ByLayer".to_string(), "ByBlock".to_string()],
|
|
},
|
|
},
|
|
Property {
|
|
label: t!("Hyperlink").into_owned(),
|
|
field: "hyperlink",
|
|
value: PropValue::PlainText(hyperlink),
|
|
},
|
|
],
|
|
};
|
|
|
|
if matches!(entity, EntityType::Text(_))
|
|
|| matches!(entity, EntityType::LwPolyline(polyline) if crate::entities::lwpolyline::is_rectangle(polyline))
|
|
|| matches!(entity, EntityType::MText(_))
|
|
{
|
|
section.props.retain(|prop| prop.field != "handle");
|
|
}
|
|
|
|
if matches!(entity, EntityType::Point(_)) {
|
|
section.props.retain(|prop| prop.field != "handle");
|
|
let hyperlink = section.props.iter().position(|prop| prop.field == "hyperlink");
|
|
let transparency = section.props.iter().position(|prop| prop.field == "transparency");
|
|
if let (Some(hyperlink), Some(transparency)) = (hyperlink, transparency) {
|
|
section.props.swap(hyperlink, transparency);
|
|
}
|
|
}
|
|
|
|
// Thickness (DXF 39) is a General-group property, but only the entity
|
|
// types that carry an extrusion thickness expose it (line, circle, arc,
|
|
// polyline, text, 2D solid, …). Show it right after Hyperlink for those.
|
|
if let Some(t) = crate::scene::view::dispatch::entity_thickness(entity) {
|
|
section
|
|
.props
|
|
.push(crate::entities::common::edit_prop(t!("Thickness").as_ref(), "thickness", t));
|
|
}
|
|
|
|
section
|
|
}
|
|
|
|
/// The "3D Visualization" group (Material), common to every graphical object.
|
|
/// Material source is flag-based; a custom material handle is shown as "Custom"
|
|
/// (name resolution needs the doc).
|
|
pub fn visualization_section(entity: &EntityType) -> Option<PropSection> {
|
|
if matches!(
|
|
entity,
|
|
EntityType::Block(_)
|
|
| EntityType::BlockEnd(_)
|
|
| EntityType::Seqend(_)
|
|
| EntityType::Leader(_)
|
|
| EntityType::Unknown(_)
|
|
// Non-plotting drawing-view border: never rendered, no properties.
|
|
| EntityType::ViewBorder(_)
|
|
) {
|
|
return None;
|
|
}
|
|
let common = entity.common();
|
|
let material = match common.material_flags {
|
|
0 => "ByLayer",
|
|
1 => "ByBlock",
|
|
2 => "Global",
|
|
_ => "Custom",
|
|
};
|
|
let mut options = vec![
|
|
"ByLayer".to_string(),
|
|
"ByBlock".to_string(),
|
|
"Global".to_string(),
|
|
];
|
|
if !options.iter().any(|o| o == material) && !material.is_empty() {
|
|
options.push(material.to_string());
|
|
}
|
|
Some(PropSection {
|
|
title: t!("3D Visualization").into_owned(),
|
|
props: vec![Property {
|
|
label: t!("Material").into_owned(),
|
|
field: "material",
|
|
value: PropValue::Choice {
|
|
selected: material.to_string(),
|
|
options,
|
|
},
|
|
}],
|
|
})
|
|
}
|
|
|
|
pub fn fallback_properties(_handle: Handle, entity: &EntityType) -> PropSection {
|
|
PropSection {
|
|
title: t!("Geometry").into_owned(),
|
|
props: vec![Property {
|
|
label: t!("Type").into_owned(),
|
|
field: "type",
|
|
value: PropValue::ReadOnly(
|
|
crate::t!(crate::entities::names::ui_name_or_class(entity)).into_owned(),
|
|
),
|
|
}],
|
|
}
|
|
}
|