forked from 1b-agent/opencadstudio-upstream
feat(annotative): add/remove drawing annotation scales
The drawing's annotation-scale list (ACAD_SCALELIST) is now editable, so the set of scales offered by the status-bar scale pill can be grown or trimmed: - Scene::add_scale / remove_scale create or drop a Scale object and its SCALELIST dictionary entry (creating the SCALELIST dictionary, and registering it in the root, for drawings that carry none). - SCALELISTEDIT gains ADD <ratio> / DELETE <name> alongside the existing listing (e.g. `SCALELISTEDIT ADD 1:50`). - The scale popup (model space) grows a delete affordance on each non-active scale and a "+ Add scale..." row that primes the command line. The current annotation scale is protected from deletion. Co-Authored-By: Claude Opus 4.8 <[email protected]>
This commit is contained in:
1 parent
fc5e93dcc1
commit
b1eba180eb
5 files changed
+233
-20
No files matched your search
+72
-12
@@ -704,19 +704,79 @@ impl OpenCADStudio {
|
||||
}
|
||||
}
|
||||
|
||||
// SCALELISTEDIT — list the drawing's annotation scales.
|
||||
// SCALELISTEDIT — list / add / delete the drawing's annotation scales.
|
||||
// SCALELISTEDIT list
|
||||
// SCALELISTEDIT ADD 1:50 add (name is a paper:drawing ratio)
|
||||
// SCALELISTEDIT DELETE 1:50 remove (not the current scale)
|
||||
cmd if cmd == "SCALELISTEDIT" || cmd.starts_with("SCALELISTEDIT ") => {
|
||||
let names: Vec<String> = self.tabs[i]
|
||||
.scene
|
||||
.scale_list()
|
||||
.into_iter()
|
||||
.map(|(n, _, _)| n)
|
||||
.collect();
|
||||
if names.is_empty() {
|
||||
self.command_line.push_info("No annotation scales defined.");
|
||||
} else {
|
||||
self.command_line
|
||||
.push_output(&format!("Annotation scales: {}", names.join(", ")));
|
||||
let rest = cmd.trim_start_matches("SCALELISTEDIT").trim();
|
||||
let mut parts = rest.splitn(2, char::is_whitespace);
|
||||
let sub = parts.next().unwrap_or("").to_uppercase();
|
||||
let arg = parts.next().unwrap_or("").trim();
|
||||
match sub.as_str() {
|
||||
"ADD" => match arg.split_once(':') {
|
||||
Some((p, d)) => match (p.trim().parse::<f64>(), d.trim().parse::<f64>()) {
|
||||
(Ok(paper), Ok(drawing)) if paper > 0.0 && drawing > 0.0 => {
|
||||
self.push_undo_snapshot(i, "SCALELISTEDIT");
|
||||
if self.tabs[i].scene.add_scale(arg, paper, drawing) {
|
||||
self.tabs[i].dirty = true;
|
||||
self.command_line
|
||||
.push_output(&format!("Added annotation scale {arg}."));
|
||||
} else {
|
||||
self.command_line
|
||||
.push_info(&format!("Scale {arg} already exists."));
|
||||
}
|
||||
}
|
||||
_ => self
|
||||
.command_line
|
||||
.push_error("SCALELISTEDIT ADD: use a ratio like 1:50."),
|
||||
},
|
||||
None => self
|
||||
.command_line
|
||||
.push_error("SCALELISTEDIT ADD: use a ratio like 1:50."),
|
||||
},
|
||||
"DELETE" | "REMOVE" => {
|
||||
let current = self.tabs[i]
|
||||
.scene
|
||||
.document
|
||||
.header
|
||||
.current_annotation_scale
|
||||
.clone();
|
||||
if arg.is_empty() {
|
||||
self.command_line.push_info("Usage: SCALELISTEDIT DELETE <name>");
|
||||
} else if arg.eq_ignore_ascii_case(¤t) {
|
||||
self.command_line.push_error(&format!(
|
||||
"Cannot delete the current annotation scale ({arg})."
|
||||
));
|
||||
} else {
|
||||
self.push_undo_snapshot(i, "SCALELISTEDIT");
|
||||
if self.tabs[i].scene.remove_scale(arg) {
|
||||
self.tabs[i].dirty = true;
|
||||
self.command_line
|
||||
.push_output(&format!("Removed annotation scale {arg}."));
|
||||
} else {
|
||||
self.command_line
|
||||
.push_info(&format!("No annotation scale named {arg}."));
|
||||
}
|
||||
}
|
||||
}
|
||||
"" => {
|
||||
let names: Vec<String> = self.tabs[i]
|
||||
.scene
|
||||
.scale_list()
|
||||
.into_iter()
|
||||
.map(|(n, _, _)| n)
|
||||
.collect();
|
||||
if names.is_empty() {
|
||||
self.command_line.push_info("No annotation scales defined.");
|
||||
} else {
|
||||
self.command_line
|
||||
.push_output(&format!("Annotation scales: {}", names.join(", ")));
|
||||
}
|
||||
}
|
||||
_ => self
|
||||
.command_line
|
||||
.push_info("Usage: SCALELISTEDIT [ADD 1:50 | DELETE 1:50]"),
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1455,6 +1455,10 @@ pub enum Message {
|
||||
ToggleScalePopup,
|
||||
/// Close the scale picker popup.
|
||||
CloseScalePopup,
|
||||
/// Delete a named annotation scale from the drawing's ACAD_SCALELIST.
|
||||
ScaleListDelete(String),
|
||||
/// Prime the command line to add a new annotation scale.
|
||||
ScaleListAddPrompt,
|
||||
/// Toggle the leftmost hamburger's Model/layout list dropdown.
|
||||
ToggleLayoutList,
|
||||
/// Close the Model/layout list dropdown.
|
||||
|
||||
@@ -1647,6 +1647,31 @@ impl OpenCADStudio {
|
||||
self.scale_popup_open = false;
|
||||
Task::none()
|
||||
}
|
||||
Message::ScaleListDelete(name) => {
|
||||
let i = self.active_tab;
|
||||
let current = self.tabs[i]
|
||||
.scene
|
||||
.document
|
||||
.header
|
||||
.current_annotation_scale
|
||||
.clone();
|
||||
// Keep the popup open so several can be removed in a row; never
|
||||
// remove the current annotation scale out from under the drawing.
|
||||
if !name.eq_ignore_ascii_case(¤t) {
|
||||
self.push_undo_snapshot(i, "SCALELISTEDIT");
|
||||
if self.tabs[i].scene.remove_scale(&name) {
|
||||
self.tabs[i].dirty = true;
|
||||
}
|
||||
}
|
||||
Task::none()
|
||||
}
|
||||
Message::ScaleListAddPrompt => {
|
||||
// Close the popup and prime the command line; the user types the
|
||||
// ratio (e.g. 1:50) and commits it via SCALELISTEDIT ADD.
|
||||
self.scale_popup_open = false;
|
||||
self.command_line.input = "SCALELISTEDIT ADD ".to_string();
|
||||
Task::none()
|
||||
}
|
||||
Message::ToggleLayoutList => {
|
||||
self.layout_list_open ^= true;
|
||||
Task::none()
|
||||
|
||||
Reference in new issue
Block a user