forked from 1b-agent/opencadstudio-upstream
Fix: paper limits, Cohen-Sutherland clipping, frozen layers UI, PDF improvements
Paper limits: - Change A4 fallback from 12×9 to 297×210 mm in paper_limits() Context menu: - Translate layout context menu labels to English (Rename / Delete) Viewport clipping: - Replace AABB-only culling with proper Cohen-Sutherland line clipping in viewport_content_wires(); each projected segment is now clipped at the exact viewport boundary instead of being included or discarded whole - Add cs_clip() and clip_polyline_to_rect() free functions in scene/mod.rs Frozen layers per-viewport UI: - Inject a "Frozen Layers" EditText property in the Properties panel for viewport entities (layer names resolved from handles at display time) - Handle "frozen_layers" in PropGeomCommit: parse comma-separated names, resolve to layer handles, update vp.frozen_layers in-place PDF export improvements: - Add offset_x/offset_y params to export_pdf() for model-space normalization: coordinates are shifted so the drawing origin maps to the page origin - Model space export computes extents via model_space_extents() (now public) and adds a 5 % margin; falls back to A4 landscape for empty drawings - Skip __paper_boundary__ wire in PDF (white background covers it) - Map yellow (active viewport border) → black and cyan (vp border) → dark blue for print-friendly output Co-Authored-By: Claude Sonnet 4.6 <[email protected]>
This commit is contained in:
1 parent
e1d296da10
commit
845770938c
5 files changed
+262
-67
No files matched your search
@@ -55,6 +55,29 @@ impl H7CAD {
|
||||
let group_names = self.tabs[i].scene.group_names_for_entity(handle);
|
||||
let mut sections =
|
||||
dispatch::properties_sectioned(handle, entity, &text_style_names);
|
||||
|
||||
// Inject frozen-layer property for viewports (requires doc access).
|
||||
if let acadrust::EntityType::Viewport(vp) = entity {
|
||||
let frozen_names: Vec<String> = vp
|
||||
.frozen_layers
|
||||
.iter()
|
||||
.filter_map(|&h| {
|
||||
self.tabs[i].scene.document.layers.iter()
|
||||
.find(|l| l.handle == h)
|
||||
.map(|l| l.name.clone())
|
||||
})
|
||||
.collect();
|
||||
if let Some(geom) = sections.last_mut() {
|
||||
geom.props.push(crate::scene::object::Property {
|
||||
label: "Frozen Layers".to_string(),
|
||||
field: "frozen_layers",
|
||||
value: crate::scene::object::PropValue::EditText(
|
||||
frozen_names.join(", "),
|
||||
),
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
if !group_names.is_empty() {
|
||||
let label = group_names.join(", ");
|
||||
if let Some(general) = sections.first_mut() {
|
||||
|
||||
+46
-17
@@ -1457,14 +1457,35 @@ impl H7CAD {
|
||||
if !handles.is_empty() {
|
||||
if let Some(val) = self.tabs[i].properties.edit_buf.remove(field) {
|
||||
self.push_undo_snapshot(i, "CHPROP");
|
||||
for handle in handles {
|
||||
if let Some(entity) = self.tabs[i].scene.document.get_entity_mut(handle) {
|
||||
match field {
|
||||
"linetype_scale" | "transparency" => {
|
||||
crate::scene::dispatch::apply_common_prop(entity, field, &val);
|
||||
}
|
||||
_ => {
|
||||
crate::scene::dispatch::apply_geom_prop(entity, field, &val);
|
||||
if field == "frozen_layers" {
|
||||
// Resolve layer names → handles, then apply to viewports.
|
||||
let layer_handles: Vec<acadrust::Handle> = val
|
||||
.split(',')
|
||||
.map(|s| s.trim())
|
||||
.filter(|s| !s.is_empty())
|
||||
.filter_map(|name| {
|
||||
self.tabs[i].scene.document.layers.iter()
|
||||
.find(|l| l.name.eq_ignore_ascii_case(name))
|
||||
.map(|l| l.handle)
|
||||
})
|
||||
.collect();
|
||||
for handle in handles {
|
||||
if let Some(acadrust::EntityType::Viewport(vp)) =
|
||||
self.tabs[i].scene.document.get_entity_mut(handle)
|
||||
{
|
||||
vp.frozen_layers = layer_handles.clone();
|
||||
}
|
||||
}
|
||||
} else {
|
||||
for handle in handles {
|
||||
if let Some(entity) = self.tabs[i].scene.document.get_entity_mut(handle) {
|
||||
match field {
|
||||
"linetype_scale" | "transparency" => {
|
||||
crate::scene::dispatch::apply_common_prop(entity, field, &val);
|
||||
}
|
||||
_ => {
|
||||
crate::scene::dispatch::apply_geom_prop(entity, field, &val);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1725,15 +1746,23 @@ impl H7CAD {
|
||||
Message::PlotExportPath(Some(path)) => {
|
||||
let i = self.active_tab;
|
||||
let wires = self.tabs[i].scene.entity_wires();
|
||||
let (paper_w, paper_h) = if let Some(((_, _), (w, h))) =
|
||||
self.tabs[i].scene.paper_limits()
|
||||
{
|
||||
(w, h)
|
||||
} else {
|
||||
// Model space: use extents or default A4 landscape.
|
||||
(297.0, 210.0)
|
||||
};
|
||||
match crate::io::pdf_export::export_pdf(&wires, paper_w, paper_h, &path) {
|
||||
let (paper_w, paper_h, offset_x, offset_y) =
|
||||
if let Some(((x0, y0), (x1, y1))) = self.tabs[i].scene.paper_limits() {
|
||||
(x1 - x0, y1 - y0, -x0, -y0)
|
||||
} else {
|
||||
// Model space: fit wires to computed extents with 5 % margin.
|
||||
let margin = 1.05_f64;
|
||||
if let Some((mn, mx)) = self.tabs[i].scene.model_space_extents() {
|
||||
let w = ((mx.x - mn.x) as f64 * margin).max(1.0);
|
||||
let h = ((mx.y - mn.y) as f64 * margin).max(1.0);
|
||||
let pad_x = (w - (mx.x - mn.x) as f64) * 0.5;
|
||||
let pad_y = (h - (mx.y - mn.y) as f64) * 0.5;
|
||||
(w, h, -(mn.x as f64) + pad_x, -(mn.y as f64) + pad_y)
|
||||
} else {
|
||||
(297.0, 210.0, 0.0, 0.0)
|
||||
}
|
||||
};
|
||||
match crate::io::pdf_export::export_pdf(&wires, paper_w, paper_h, offset_x as f32, offset_y as f32, &path) {
|
||||
Ok(()) => self.command_line.push_info(&format!(
|
||||
"Exported: {}",
|
||||
path.file_name().unwrap_or_default().to_string_lossy()
|
||||
|
||||
+2
-2
@@ -415,8 +415,8 @@ fn layout_context_menu_overlay(name: &str) -> Element<'_, Message> {
|
||||
|
||||
let menu = container(
|
||||
column![
|
||||
item("Yeniden Adlandır", Message::LayoutRenameStart(rename_name)),
|
||||
item("Sil", Message::LayoutDelete(delete_name)),
|
||||
item("Rename", Message::LayoutRenameStart(rename_name)),
|
||||
item("Delete", Message::LayoutDelete(delete_name)),
|
||||
]
|
||||
.spacing(0)
|
||||
.width(160),
|
||||
|
||||
Reference in new issue
Block a user