forked from 1b-agent/opencadstudio-upstream
feat(annotative): annotation-scale manager window
Replace the scale popup's inline delete/add affordances with a single "Manage scales..." row that opens a proper manager, matching the style managers: it reuses the shared style-manager palette and chrome (toolbar + list + editor frame), so it looks and behaves like the Text / Dim / MLeader managers. The manager lists the drawing's annotation scales (name + ratio, the current one checked) and edits them through a Name / Paper units / Drawing units editor: New adds a scale from the fields, Apply renames / re-ratios the selected one, Delete removes it (never the current scale), and Set Current makes the selected scale the model-space annotation scale. Backed by Scene::add_scale / remove_scale / edit_scale on ACAD_SCALELIST. Co-Authored-By: Claude Opus 4.8 <[email protected]>
This commit is contained in:
1 parent
b1eba180eb
commit
1071570f40
9 files changed
+427
-67
No files matched your search
+27
-4
@@ -659,6 +659,12 @@ pub(super) struct OpenCADStudio {
|
||||
layout_manager_selected: String,
|
||||
layout_manager_rename_buf: String,
|
||||
|
||||
// ── Annotation-scale Manager ──────────────────────────────────────────
|
||||
scale_manager_selected: String,
|
||||
scale_manager_name_buf: String,
|
||||
scale_manager_paper_buf: String,
|
||||
scale_manager_drawing_buf: String,
|
||||
|
||||
// ── Plot Style Panel ──────────────────────────────────────────────────
|
||||
/// Selected ACI index in the panel (1-255).
|
||||
plotstyle_panel_aci: u8,
|
||||
@@ -1106,6 +1112,7 @@ pub enum ModalKind {
|
||||
AttributeEditor,
|
||||
LayerDeleteWarning,
|
||||
Aliases,
|
||||
ScaleManager,
|
||||
}
|
||||
|
||||
/// Identifies a DimStyle field that can be edited in the dialog.
|
||||
@@ -1455,10 +1462,22 @@ 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,
|
||||
/// Open the annotation-scale manager (from the scale popup's Manage row).
|
||||
ScaleManagerOpen,
|
||||
/// Select a scale row in the manager (loads it into the editor).
|
||||
ScaleManagerSelect(String),
|
||||
/// Add a new scale from the editor fields.
|
||||
ScaleManagerNew,
|
||||
/// Delete the selected scale.
|
||||
ScaleManagerDelete,
|
||||
/// Set the selected scale as the current annotation scale.
|
||||
ScaleManagerSetCurrent,
|
||||
/// Apply the editor fields to the selected scale (rename / re-ratio).
|
||||
ScaleManagerApply,
|
||||
/// Annotation-scale manager editor field edits.
|
||||
ScaleManagerNameBuf(String),
|
||||
ScaleManagerPaperBuf(String),
|
||||
ScaleManagerDrawingBuf(String),
|
||||
/// Toggle the leftmost hamburger's Model/layout list dropdown.
|
||||
ToggleLayoutList,
|
||||
/// Close the Model/layout list dropdown.
|
||||
@@ -2234,6 +2253,10 @@ impl OpenCADStudio {
|
||||
alias_editor_rows: Vec::new(),
|
||||
// Layout Manager
|
||||
layout_manager_selected: "Model".to_string(),
|
||||
scale_manager_selected: String::new(),
|
||||
scale_manager_name_buf: String::new(),
|
||||
scale_manager_paper_buf: String::new(),
|
||||
scale_manager_drawing_buf: String::new(),
|
||||
layout_manager_rename_buf: String::new(),
|
||||
plotstyle_panel_aci: 1,
|
||||
ps_color_buf: String::new(),
|
||||
|
||||
+106
-11
@@ -1647,29 +1647,97 @@ impl OpenCADStudio {
|
||||
self.scale_popup_open = false;
|
||||
Task::none()
|
||||
}
|
||||
Message::ScaleListDelete(name) => {
|
||||
Message::ScaleManagerOpen => {
|
||||
let i = self.active_tab;
|
||||
let current = self.tabs[i]
|
||||
self.scale_popup_open = false;
|
||||
let cur = 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.load_scale_editor(&cur);
|
||||
self.active_modal = Some(crate::app::ModalKind::ScaleManager);
|
||||
Task::none()
|
||||
}
|
||||
Message::ScaleManagerSelect(name) => {
|
||||
self.load_scale_editor(&name);
|
||||
Task::none()
|
||||
}
|
||||
Message::ScaleManagerNameBuf(s) => {
|
||||
self.scale_manager_name_buf = s;
|
||||
Task::none()
|
||||
}
|
||||
Message::ScaleManagerPaperBuf(s) => {
|
||||
self.scale_manager_paper_buf = s;
|
||||
Task::none()
|
||||
}
|
||||
Message::ScaleManagerDrawingBuf(s) => {
|
||||
self.scale_manager_drawing_buf = s;
|
||||
Task::none()
|
||||
}
|
||||
Message::ScaleManagerNew => {
|
||||
let i = self.active_tab;
|
||||
if let (name, Some(paper), Some(drawing)) = self.scale_editor_values() {
|
||||
if !name.is_empty() && paper > 0.0 && drawing > 0.0 {
|
||||
self.push_undo_snapshot(i, "SCALELISTEDIT");
|
||||
if self.tabs[i].scene.add_scale(&name, paper, drawing) {
|
||||
self.scale_manager_selected = name;
|
||||
self.tabs[i].dirty = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
Task::none()
|
||||
}
|
||||
Message::ScaleManagerApply => {
|
||||
let i = self.active_tab;
|
||||
let old = self.scale_manager_selected.clone();
|
||||
if !old.is_empty() {
|
||||
if let (name, Some(paper), Some(drawing)) = self.scale_editor_values() {
|
||||
if !name.is_empty() && paper > 0.0 && drawing > 0.0 {
|
||||
self.push_undo_snapshot(i, "SCALELISTEDIT");
|
||||
if self.tabs[i].scene.edit_scale(&old, &name, paper, drawing) {
|
||||
self.scale_manager_selected = name;
|
||||
self.tabs[i].dirty = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Task::none()
|
||||
}
|
||||
Message::ScaleManagerDelete => {
|
||||
let i = self.active_tab;
|
||||
let sel = self.scale_manager_selected.clone();
|
||||
let cur = self.tabs[i]
|
||||
.scene
|
||||
.document
|
||||
.header
|
||||
.current_annotation_scale
|
||||
.clone();
|
||||
if !sel.is_empty() && !sel.eq_ignore_ascii_case(&cur) {
|
||||
self.push_undo_snapshot(i, "SCALELISTEDIT");
|
||||
if self.tabs[i].scene.remove_scale(&name) {
|
||||
if self.tabs[i].scene.remove_scale(&sel) {
|
||||
self.scale_manager_selected.clear();
|
||||
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();
|
||||
Message::ScaleManagerSetCurrent => {
|
||||
let i = self.active_tab;
|
||||
let sel = self.scale_manager_selected.clone();
|
||||
if let Some((_, anno, _)) = self
|
||||
.tabs[i]
|
||||
.scene
|
||||
.scale_list()
|
||||
.into_iter()
|
||||
.find(|(n, _, _)| n.eq_ignore_ascii_case(&sel))
|
||||
{
|
||||
self.tabs[i].scene.annotation_scale = anno;
|
||||
self.tabs[i].scene.document.header.current_annotation_scale = sel;
|
||||
self.tabs[i].scene.bump_geometry();
|
||||
self.tabs[i].dirty = true;
|
||||
}
|
||||
Task::none()
|
||||
}
|
||||
Message::ToggleLayoutList => {
|
||||
@@ -3953,4 +4021,31 @@ impl OpenCADStudio {
|
||||
Message::DsSetHandle { field, value } => self.on_ds_set_handle(field, value),
|
||||
}
|
||||
}
|
||||
|
||||
/// Load a named scale into the scale-manager editor buffers (name + the
|
||||
/// paper / drawing units); blank ratios when the scale isn't found.
|
||||
fn load_scale_editor(&mut self, name: &str) {
|
||||
let i = self.active_tab;
|
||||
self.scale_manager_selected = name.to_string();
|
||||
self.scale_manager_name_buf = name.to_string();
|
||||
match self.tabs[i].scene.scale_paper_drawing(name) {
|
||||
Some((p, d)) => {
|
||||
self.scale_manager_paper_buf = format!("{p}");
|
||||
self.scale_manager_drawing_buf = format!("{d}");
|
||||
}
|
||||
None => {
|
||||
self.scale_manager_paper_buf.clear();
|
||||
self.scale_manager_drawing_buf.clear();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// The scale-manager editor's (name, paper?, drawing?) parsed from buffers.
|
||||
fn scale_editor_values(&self) -> (String, Option<f64>, Option<f64>) {
|
||||
(
|
||||
self.scale_manager_name_buf.trim().to_string(),
|
||||
self.scale_manager_paper_buf.trim().parse::<f64>().ok(),
|
||||
self.scale_manager_drawing_buf.trim().parse::<f64>().ok(),
|
||||
)
|
||||
}
|
||||
}
|
||||
@@ -1573,6 +1573,7 @@ impl OpenCADStudio {
|
||||
AttributeEditor => (640, 500),
|
||||
LayerDeleteWarning => (440, 200),
|
||||
Aliases => (480, 520),
|
||||
ScaleManager => (520, 360),
|
||||
};
|
||||
Some((w as f32 + EXTRA_W, h as f32 + EXTRA_H))
|
||||
}
|
||||
|
||||
@@ -65,6 +65,35 @@ impl OpenCADStudio {
|
||||
320,
|
||||
)
|
||||
}
|
||||
super::super::ModalKind::ScaleManager => {
|
||||
let tab = &self.tabs[self.active_tab];
|
||||
let scales: Vec<(String, String)> = tab
|
||||
.scene
|
||||
.scale_list()
|
||||
.into_iter()
|
||||
.map(|(name, _, _)| {
|
||||
let ratio = tab
|
||||
.scene
|
||||
.scale_paper_drawing(&name)
|
||||
.map(|(p, d)| format!("{p}:{d}"))
|
||||
.unwrap_or_default();
|
||||
(name, ratio)
|
||||
})
|
||||
.collect();
|
||||
let current = tab.scene.document.header.current_annotation_scale.clone();
|
||||
sized(
|
||||
crate::ui::style::scale_manager::view_window(
|
||||
&scales,
|
||||
&self.scale_manager_selected,
|
||||
¤t,
|
||||
&self.scale_manager_name_buf,
|
||||
&self.scale_manager_paper_buf,
|
||||
&self.scale_manager_drawing_buf,
|
||||
),
|
||||
520,
|
||||
360,
|
||||
)
|
||||
}
|
||||
super::super::ModalKind::Plotstyle => sized(
|
||||
crate::ui::style::plotstyle::view_window(
|
||||
self.active_plot_style.as_ref(),
|
||||
|
||||
Reference in new issue
Block a user