Merge pull request #1613 from ramox81/codex/sheet-set-manager

Sheet Set Manager, NEWSHEETSET / OPENSHEETSET and sheet set fields
This commit is contained in:
Hakan Seven committed 2026-10-06 09:17:20 +03:00
commit 078306d8fc
50 files changed
+8974 -27

No files matched your search

-6
View File
@@ -587,12 +587,6 @@ impl OpenCADStudio {
.push_info(crate::t!("TOOLPALETTES: Tool Palettes not yet implemented.").as_ref());
}
// ── SHEETSET — not yet implemented ───────────────────────────────────
"SHEETSET" => {
self.command_line
.push_info(crate::t!("SHEETSET: Sheet Set Manager not yet implemented.").as_ref());
}
// ── XDATA — read/write extended entity data ──────────────────────────
// XDATA LIST — show all xdata records on selected entities
// XDATA SET <app> <str> — append a string xdata value for <app>
+68 -2
View File
@@ -4,7 +4,7 @@
use crate::app::{Message, OpenCADStudio};
use crate::command::CadCommand;
use crate::modules::annotate::field_cmd::{FieldObjectPickCommand, FieldPlaceCommand, FieldTablePickCommand};
use crate::ui::window::field_dialog::{
use crate::ui::window::field_dialog::{nav_props,
fields_of, object_properties, FieldDialogMsg, FieldDialogState, FieldTarget, DATE_FORMATS,
NAMED_TYPES,
};
@@ -103,6 +103,15 @@ impl OpenCADStudio {
.iter()
.map(|f| self.field_value(&format!("\\AcVar Date \\f \"{f}\""), &[]))
.collect();
if let Some(db) = self.sheet_set.db() {
let custom = codec::sheet_set::custom_properties(db.sheet_set());
let names = |flag: i32| custom.iter().filter(|(_, _, f)| f & flag != 0).map(|(n, _, _)| n.clone()).collect();
state.ss_sheet_custom = names(codec::sheet_set::CUSTOM_SHEET_PROP);
state.ss_set_custom = names(codec::sheet_set::CUSTOM_SHEET_SET_PROP);
state.ss_set_name = db.name().to_string();
}
state.ss_sets = self.sheet_set.sets.clone();
state.ss_set = self.sheet_set.current.unwrap_or(0);
self.field_dialog = Some(state);
self.fill_named_objects();
self.refresh_field_preview();
@@ -180,8 +189,65 @@ impl OpenCADStudio {
}
FieldDialogMsg::Name(n) => {
state.name = n;
state.text_case = 0;
// Sheet set fields start in Title case.
state.text_case = if crate::ui::window::field_dialog::SHEET_SET_FIELDS.contains(&n) { 4 } else { 0 };
state.ss_custom.clear();
state.ss_node.clear();
state.ss_prop.clear();
// SheetSet starts on the set and its first property; SheetView on nothing.
if n == "SheetSet" {
if let Some(db) = state.ss_sets.get(state.ss_set) {
state.ss_node = db.sheet_set().id().to_string();
state.ss_prop = nav_props(db, &state.ss_node).first().map(|p| p.0.clone()).unwrap_or_default();
}
}
}
FieldDialogMsg::SsCustom(name) => state.ss_custom = name,
FieldDialogMsg::SsSet(k) => {
state.ss_set = k;
state.ss_node.clear();
state.ss_prop.clear();
}
FieldDialogMsg::SsNode(id) => {
state.ss_prop = state.ss_sets.get(state.ss_set).and_then(|db| nav_props(db, &id).first().map(|p| p.0.clone())).unwrap_or_default();
state.ss_node = id;
}
FieldDialogMsg::SsProp(p) => state.ss_prop = p,
FieldDialogMsg::SsHref(v) => state.ss_href = v,
FieldDialogMsg::SsBrowse => {
return Task::perform(
async {
crate::sys::file_dialog()
.set_title(crate::t!("Open Sheet Set").as_ref())
.add_filter(crate::t!("Sheet Set (*.dst)").as_ref(), &["dst", "DST"])
.pick_file()
.await
.map(|h| crate::sys::handle_path(&h))
},
|p| Message::FieldDialog(FieldDialogMsg::SsPicked(p)),
);
}
FieldDialogMsg::SsPicked(None) => {}
FieldDialogMsg::SsPicked(Some(path)) => match codec::sheet_set::SheetSetDatabase::read(&path.to_string_lossy()) {
Ok(db) => {
let key = codec::sheet_set::path_key(&path.to_string_lossy());
state.ss_set = match state.ss_sets.iter().position(|d| d.path.as_deref().is_some_and(|p| codec::sheet_set::path_key(p) == key)) {
Some(k) => k,
None => {
state.ss_sets.push(db);
state.ss_sets.len() - 1
}
};
state.ss_node.clear();
state.ss_prop.clear();
}
Err(e) => self.command_line.push_error(&format!("{}: {e}", path.display())),
},
FieldDialogMsg::SsPlaceholder(k) => {
state.ss_placeholder = k;
state.ss_custom.clear();
}
FieldDialogMsg::SsScaleFormat(k) => state.ss_scale_format = k,
FieldDialogMsg::DateFormat(f) => state.date_format = f,
FieldDialogMsg::DateExample(k) => {
if let Some(f) = DATE_FORMATS.get(k) {
+23
View File
@@ -803,6 +803,29 @@ impl OpenCADStudio {
.push_output(crate::tf!("View '{}' saved.", name).as_ref());
}
}
"WINDOW" | "W" => {
// A plan view of the window between two corners.
let args: Vec<&str> = parts.get(2).map(|s| s.split_whitespace().collect()).unwrap_or_default();
let corner = |s: &str| {
let mut c = s.split(',');
Some((c.next()?.trim().parse::<f64>().ok()?, c.next()?.trim().parse::<f64>().ok()?))
};
match (args.first(), args.get(1).and_then(|s| corner(s)), args.get(2).and_then(|s| corner(s))) {
(Some(name), Some(a), Some(b)) if a.0 != b.0 && a.1 != b.1 => {
use codec::types::Vector3;
let mut view = self.tabs[i].scene.current_as_named_view(name);
view.target = Vector3 { x: (a.0 + b.0) / 2.0, y: (a.1 + b.1) / 2.0, z: 0.0 };
view.direction = Vector3 { x: 0.0, y: 0.0, z: 1.0 };
view.width = (b.0 - a.0).abs();
view.height = (b.1 - a.1).abs();
self.tabs[i].scene.document.views.add_or_replace(view);
self.command_line.push_output(crate::tf!("View '{}' saved.", name).as_ref());
}
_ => self
.command_line
.push_error(crate::t!("Usage: VIEW WINDOW <name> <x1,y1> <x2,y2>").as_ref()),
}
}
"DELETE" | "DEL" | "D" => {
let name = parts.get(2).map(|s| s.trim()).unwrap_or("").to_string();
if name.is_empty() {
+13
View File
@@ -21,6 +21,7 @@ mod pc_colormap;
mod pc_extract;
mod pdf_underlay;
mod pdf_dialogs;
pub(crate) mod sheet_set;
mod xclip;
mod blockvars;
mod plotvars;
@@ -321,6 +322,9 @@ impl OpenCADStudio {
if let Some(t) = self.dispatch_attdef(cmd, i) {
return Some(t);
}
if let Some(t) = self.dispatch_sheet_set(cmd, i) {
return Some(t);
}
if let Some(t) = self.dispatch_field(cmd, i) {
return Some(t);
}
@@ -882,6 +886,15 @@ inventory::submit!(crate::command::CommandRegistration {
"CREATESKETCH",
"FINISHSKETCH",
"SHEETSET",
"SHEETSETHIDE",
"NEWSHEETSET",
"OPENSHEETSET",
"SSMAUTOOPEN",
"SSLOCATE",
"SSMPOLLTIME",
"SSMSHEETSTATUS",
"SSMSTATE",
"SSFOUND",
"SHORTCUTS",
"SSM",
"STEPOUT",
File diff suppressed because it is too large. Load diff