forked from 1b-agent/opencadstudio-upstream
feat(commands): add CLOSE, HIDE, VISUALSTYLES, QUICKCALC, HYPERLINK, XOPEN
Six more standard commands by reusing existing infrastructure: - CLOSE: close the active tab (Message::TabClose) - HIDE / VISUALSTYLES: per-viewport render mode (Message::SetRenderMode) - QUICKCALC / QC: alias the CAL arithmetic evaluator - HYPERLINK <url>: attach a hyperlink via the PE_URL XData record - XOPEN: open a selected xref's source file (Message::OpenRecent) COMMANDS.md updated to 214 done / 15 partial / 33 missing of 262. Co-Authored-By: Claude Opus 4.8 <[email protected]>
This commit is contained in:
1 parent
c19c18c2f2
commit
e2a83a6487
7 files changed
+201
-77
No files matched your search
@@ -565,6 +565,36 @@ impl OpenCADStudio {
|
||||
}
|
||||
}
|
||||
|
||||
// XOPEN — open the source file of the selected external reference in
|
||||
// a new tab (reuses the existence-checked OpenRecent path).
|
||||
"XOPEN" => {
|
||||
let names: Vec<String> = self.tabs[i]
|
||||
.scene
|
||||
.selected_entities()
|
||||
.iter()
|
||||
.filter_map(|(_, e)| match e {
|
||||
acadrust::EntityType::Insert(ins) => Some(ins.block_name.clone()),
|
||||
_ => None,
|
||||
})
|
||||
.collect();
|
||||
let path = names.iter().find_map(|bn| {
|
||||
let br = self.tabs[i].scene.document.block_records.get(bn)?;
|
||||
if br.xref_path.is_empty() {
|
||||
None
|
||||
} else {
|
||||
Some(br.xref_path.clone())
|
||||
}
|
||||
});
|
||||
match path {
|
||||
Some(p) => {
|
||||
return Some(Task::done(Message::OpenRecent(std::path::PathBuf::from(p))))
|
||||
}
|
||||
None => self
|
||||
.command_line
|
||||
.push_error("XOPEN: select an external reference (xref) to open."),
|
||||
}
|
||||
}
|
||||
|
||||
// NCOPY — copy the nested objects of the selected block reference(s)
|
||||
// into model space, keeping the block (a non-destructive extraction;
|
||||
// every nested object is copied — the block is not exploded).
|
||||
|
||||
@@ -566,6 +566,38 @@ impl OpenCADStudio {
|
||||
return Some(Task::none());
|
||||
}
|
||||
|
||||
// HYPERLINK <url> — attach a hyperlink to the selected objects, stored
|
||||
// in the standard PE_URL XData record so it round-trips in the file.
|
||||
cmd if cmd == "HYPERLINK" || cmd.starts_with("HYPERLINK ") => {
|
||||
use acadrust::xdata::{ExtendedDataRecord, XDataValue};
|
||||
let url = cmd.strip_prefix("HYPERLINK").unwrap_or("").trim().to_string();
|
||||
if url.is_empty() {
|
||||
self.command_line.push_info("Usage: HYPERLINK <url> (select objects first)");
|
||||
return Some(Task::none());
|
||||
}
|
||||
let handles: Vec<acadrust::Handle> =
|
||||
self.tabs[i].scene.selected_entities().iter().map(|(h, _)| *h).collect();
|
||||
if handles.is_empty() {
|
||||
self.command_line.push_error("HYPERLINK: select objects first.");
|
||||
return Some(Task::none());
|
||||
}
|
||||
self.push_undo_snapshot(i, "HYPERLINK");
|
||||
let mut n = 0usize;
|
||||
for h in &handles {
|
||||
if let Some(e) = self.tabs[i].scene.document.get_entity_mut(*h) {
|
||||
let xd = &mut e.common_mut().extended_data;
|
||||
let mut rec = ExtendedDataRecord::new("PE_URL");
|
||||
rec.add_value(XDataValue::String(url.clone()));
|
||||
xd.add_record(rec);
|
||||
n += 1;
|
||||
}
|
||||
}
|
||||
self.tabs[i].dirty = true;
|
||||
self.command_line
|
||||
.push_output(&format!("HYPERLINK: attached to {n} object(s)."));
|
||||
return Some(Task::none());
|
||||
}
|
||||
|
||||
// ADJUST — set brightness / contrast / fade on selected raster images
|
||||
// ADJUST BRIGHTNESS|CONTRAST|FADE <0-100>
|
||||
cmd if cmd == "ADJUST" || cmd.starts_with("ADJUST ") => {
|
||||
|
||||
@@ -137,6 +137,12 @@ impl OpenCADStudio {
|
||||
.push_output(&format!("Visual style: {label}."));
|
||||
return Some(Task::done(Message::SetWireframe(wireframe)));
|
||||
}
|
||||
// CLOSE — close the active drawing tab (with the unsaved-changes
|
||||
// prompt the tab-close handler already runs).
|
||||
"CLOSE" => {
|
||||
return Some(Task::done(Message::TabClose(self.active_tab)));
|
||||
}
|
||||
|
||||
"EXIT" | "QUIT" => {
|
||||
// Funnel through the OS close path so the unsaved-changes
|
||||
// dialog runs before `iced::exit()`. Falls back to a hard
|
||||
|
||||
@@ -45,10 +45,16 @@ impl OpenCADStudio {
|
||||
return Some(Task::done(Message::QSelectOpen));
|
||||
}
|
||||
|
||||
// CAL <expression> — evaluate an arithmetic expression
|
||||
// CAL / QUICKCALC <expression> — evaluate an arithmetic expression
|
||||
// (+ - * /, parentheses, unary minus, decimals).
|
||||
cmd if cmd == "CAL" || cmd.starts_with("CAL ") => {
|
||||
let expr = cmd.trim_start_matches("CAL").trim();
|
||||
cmd if cmd == "CAL"
|
||||
|| cmd == "QUICKCALC"
|
||||
|| cmd == "QC"
|
||||
|| cmd.starts_with("CAL ")
|
||||
|| cmd.starts_with("QUICKCALC ")
|
||||
|| cmd.starts_with("QC ") =>
|
||||
{
|
||||
let expr = cmd.splitn(2, char::is_whitespace).nth(1).unwrap_or("").trim();
|
||||
if expr.is_empty() {
|
||||
self.command_line
|
||||
.push_info("Usage: CAL <expression> e.g. CAL (2+3)*4");
|
||||
|
||||
@@ -333,6 +333,15 @@ inventory::submit!(crate::command::CommandRegistration {
|
||||
// Copy nested objects out of a block.
|
||||
"NCOPY",
|
||||
"NCOPYALL",
|
||||
// Close tab, hidden-line / visual styles, calculator, hyperlink.
|
||||
"CLOSE",
|
||||
"HIDE",
|
||||
"HI",
|
||||
"VISUALSTYLES",
|
||||
"QUICKCALC",
|
||||
"QC",
|
||||
"HYPERLINK",
|
||||
"XOPEN",
|
||||
// Slice/section + interference + press-pull/thicken + 3D transforms + wall/pyramid.
|
||||
"SLICE",
|
||||
"SL",
|
||||
|
||||
@@ -988,6 +988,36 @@ impl OpenCADStudio {
|
||||
));
|
||||
}
|
||||
|
||||
// HIDE — hidden-line view of the active viewport.
|
||||
"HIDE" | "HI" => {
|
||||
return Some(Task::done(Message::SetRenderMode(
|
||||
acadrust::entities::ViewportRenderMode::HiddenLine,
|
||||
)));
|
||||
}
|
||||
|
||||
// VISUALSTYLES <name> — apply a built-in visual style to the active
|
||||
// viewport via its render mode (the style-definition manager dialog
|
||||
// is not modelled; this applies the standard styles).
|
||||
cmd if cmd == "VISUALSTYLES" || cmd.starts_with("VISUALSTYLES ") => {
|
||||
use acadrust::entities::ViewportRenderMode as VRM;
|
||||
let name = cmd.strip_prefix("VISUALSTYLES").unwrap_or("").trim().to_uppercase();
|
||||
let mode = match name.as_str() {
|
||||
"2DWIREFRAME" | "2D" => Some(VRM::Wireframe2D),
|
||||
"3DWIREFRAME" | "WIREFRAME" | "3D" => Some(VRM::Wireframe3D),
|
||||
"HIDDEN" | "HIDDENLINE" => Some(VRM::HiddenLine),
|
||||
"FLAT" | "FLATSHADED" => Some(VRM::FlatShaded),
|
||||
"REALISTIC" | "SHADED" | "GOURAUD" => Some(VRM::GouraudShaded),
|
||||
"CONCEPTUAL" | "SHADEDWITHEDGES" => Some(VRM::GouraudShadedWithEdges),
|
||||
_ => None,
|
||||
};
|
||||
match mode {
|
||||
Some(m) => return Some(Task::done(Message::SetRenderMode(m))),
|
||||
None => self.command_line.push_info(
|
||||
"VISUALSTYLES <2DWIREFRAME|3DWIREFRAME|HIDDEN|REALISTIC|CONCEPTUAL|SHADED>",
|
||||
),
|
||||
}
|
||||
}
|
||||
|
||||
_ => return None,
|
||||
}
|
||||
Some(self.finish_dispatch(cmd))
|
||||
|
||||
Reference in new issue
Block a user