feat(locale): localize full interface

This commit is contained in:
Hakan Seven 2026-08-02 22:09:25 +03:00
commit 3e6693b93f
205 changed files with 32367 additions and 3808 deletions

View file

@ -43,12 +43,12 @@ impl OpenCADStudio {
} else {
"model space"
};
self.command_line.push_output(&format!(
self.command_line.push_output(crate::tf!(
"Base point ({}, {}, {}) set for {space}.",
nums[0], nums[1], z
));
).as_ref());
} else {
self.command_line.push_error("Usage: BASE <x> <y> [z]");
self.command_line.push_error(crate::t!("Usage: BASE <x> <y> [z]").as_ref());
}
}
}
@ -60,7 +60,7 @@ impl OpenCADStudio {
return match self.mtext_selected_text() {
Some(text) => {
self.command_line
.push_info("Copied selected text to clipboard.");
.push_info(crate::t!("Copied selected text to clipboard.").as_ref());
Some(iced::clipboard::write(text).discard())
}
None => Some(Task::none()),
@ -91,10 +91,10 @@ impl OpenCADStudio {
&self.tabs[i].scene.document,
&self.clipboard,
);
self.command_line.push_info(&format!(
self.command_line.push_info(crate::tf!(
"{} object(s) copied to clipboard.",
self.clipboard.len()
));
).as_ref());
}
}
@ -145,12 +145,12 @@ impl OpenCADStudio {
&self.tabs[i].scene.document,
&self.clipboard,
);
self.command_line.push_info(&format!(
self.command_line.push_info(crate::tf!(
"{} object(s) copied to clipboard (base {:.3},{:.3}).",
self.clipboard.len(),
base.x,
base.y
));
).as_ref());
}
}
@ -187,13 +187,13 @@ impl OpenCADStudio {
self.tabs[i].dirty = true;
self.refresh_properties();
self.command_line
.push_info(&format!("{} object(s) cut to clipboard.", count));
.push_info(crate::tf!("{} object(s) cut to clipboard.", count).as_ref());
}
}
"PASTECLIP" => {
if self.clipboard.is_empty() {
self.command_line.push_error("Clipboard is empty.");
self.command_line.push_error(crate::t!("Clipboard is empty.").as_ref());
} else {
let wires = self.tabs[i].scene.wires_for_entities(&self.clipboard);
let base = self.clipboard_base;
@ -210,7 +210,7 @@ impl OpenCADStudio {
"PASTEORIG" => {
if self.clipboard.is_empty() {
self.command_line
.push_error("PASTEORIG: clipboard is empty.");
.push_error(crate::t!("PASTEORIG: clipboard is empty.").as_ref());
} else {
let count = self.clipboard.len();
self.push_undo_snapshot(i, "PASTEORIG");
@ -219,10 +219,10 @@ impl OpenCADStudio {
self.tabs[i].dirty = true;
self.refresh_layer_panel();
self.refresh_properties();
self.command_line.push_output(&format!(
self.command_line.push_output(crate::tf!(
"PASTEORIG: {} object(s) pasted at original coordinates.",
count
));
).as_ref());
}
}
@ -231,7 +231,7 @@ impl OpenCADStudio {
"PASTEBLOCK" => {
if self.clipboard.is_empty() {
self.command_line
.push_error("PASTEBLOCK: clipboard is empty.");
.push_error(crate::t!("PASTEBLOCK: clipboard is empty.").as_ref());
} else {
self.push_undo_snapshot(i, "PASTEBLOCK");
self.merge_clipboard_deps(i);
@ -294,7 +294,7 @@ impl OpenCADStudio {
self.command_line.push_info(&cmd.prompt());
self.tabs[i].active_cmd = Some(Box::new(cmd));
}
Err(e) => self.command_line.push_error(&format!("PASTEBLOCK: {e}")),
Err(e) => self.command_line.push_error(crate::tf!("PASTEBLOCK: {e}").as_ref()),
}
}
}
@ -323,7 +323,7 @@ impl OpenCADStudio {
let blocks = self.tabs[i].scene.custom_block_names();
if blocks.is_empty() {
self.command_line
.push_error("No user-defined blocks found in this drawing.");
.push_error(crate::t!("No user-defined blocks found in this drawing.").as_ref());
} else {
use crate::modules::insert::insert_block::InsertBlockCommand;
let cmd = InsertBlockCommand::new(blocks);
@ -336,7 +336,7 @@ impl OpenCADStudio {
let blocks = self.tabs[i].scene.custom_block_names();
if blocks.is_empty() {
self.command_line
.push_error("No user-defined blocks found in this drawing.");
.push_error(crate::t!("No user-defined blocks found in this drawing.").as_ref());
} else {
use crate::modules::insert::minsert::MinsertCommand;
let cmd = MinsertCommand::new(blocks);
@ -359,20 +359,20 @@ impl OpenCADStudio {
let arg = cmd.trim_start_matches("ATTSYNC").trim();
let blocks = self.tabs[i].scene.custom_block_names();
if arg.is_empty() {
self.command_line.push_info(&format!(
self.command_line.push_info(crate::tf!(
"Usage: ATTSYNC <block name>. Blocks: {}",
if blocks.is_empty() {
"(none)".to_string()
} else {
blocks.join(", ")
}
));
).as_ref());
return Some(Task::none());
}
let Some(block) = blocks.iter().find(|b| b.eq_ignore_ascii_case(arg)).cloned()
else {
self.command_line
.push_error(&format!("ATTSYNC: no block named \"{arg}\"."));
.push_error(crate::tf!("ATTSYNC: no block named \"{arg}\".").as_ref());
return Some(Task::none());
};
// Gather the block's attribute definitions (tag, default value).
@ -422,10 +422,10 @@ impl OpenCADStudio {
}
self.tabs[i].scene.bump_entities(&changes);
self.tabs[i].dirty = true;
self.command_line.push_output(&format!(
self.command_line.push_output(crate::tf!(
"ATTSYNC: synchronised {synced} insert(s) of \"{block}\" against {} attribute definition(s).",
attdefs.len()
));
).as_ref());
}
// ADCENTER / CONTENTBROWSER — report the drawing's named content
@ -440,7 +440,7 @@ impl OpenCADStudio {
.names()
.map(|s| s.to_string())
.collect();
self.command_line.push_output(&format!(
self.command_line.push_output(crate::tf!(
"Blocks ({}): {}",
blocks.len(),
if blocks.is_empty() {
@ -448,12 +448,12 @@ impl OpenCADStudio {
} else {
blocks.join(", ")
}
));
self.command_line.push_output(&format!(
).as_ref());
self.command_line.push_output(crate::tf!(
"Layers ({}): {}",
layers.len(),
layers.join(", ")
));
).as_ref());
}
// BLOCKPALETTE — list the blocks available to insert.
@ -464,11 +464,11 @@ impl OpenCADStudio {
"No user-defined blocks. Define one with BLOCK, then INSERT it.",
);
} else {
self.command_line.push_output(&format!(
self.command_line.push_output(crate::tf!(
"Blocks ({}) — insert with INSERT <name>: {}",
blocks.len(),
blocks.join(", ")
));
).as_ref());
}
}
@ -527,9 +527,9 @@ impl OpenCADStudio {
.collect();
if xrefs.is_empty() {
self.command_line
.push_output("XREF No external references in this drawing.");
.push_output(crate::t!("XREF No external references in this drawing.").as_ref());
} else {
self.command_line.push_output("XREF External references:");
self.command_line.push_output(crate::t!("XREF External references:").as_ref());
for line in xrefs {
self.command_line.push_output(&line);
}
@ -548,19 +548,19 @@ impl OpenCADStudio {
match info.status {
crate::io::xref::XrefStatus::Loaded => {
self.command_line
.push_output(&format!("XREF Reloaded \"{}\"", info.name));
.push_output(crate::tf!("XREF Reloaded \"{}\"", info.name).as_ref());
}
crate::io::xref::XrefStatus::NotFound => {
self.command_line.push_error(&format!(
self.command_line.push_error(crate::tf!(
"XREF Not found: \"{}\" ({})",
info.name, info.path
));
).as_ref());
}
crate::io::xref::XrefStatus::Unloaded => {
self.command_line.push_info(&format!(
self.command_line.push_info(crate::tf!(
"XREF Unloaded (skipped): \"{}\"",
info.name
));
).as_ref());
}
}
}
@ -574,7 +574,7 @@ impl OpenCADStudio {
}
} else {
self.command_line
.push_error("XREF Save the drawing first to resolve relative XREF paths.");
.push_error(crate::t!("XREF Save the drawing first to resolve relative XREF paths.").as_ref());
}
}
@ -604,7 +604,7 @@ impl OpenCADStudio {
}
None => self
.command_line
.push_error("XOPEN: select an external reference (xref) to open."),
.push_error(crate::t!("XOPEN: select an external reference (xref) to open.").as_ref()),
}
}
@ -622,7 +622,7 @@ impl OpenCADStudio {
.collect();
if inserts.is_empty() {
self.command_line
.push_error("NCOPY: select a block reference first.");
.push_error(crate::t!("NCOPY: select a block reference first.").as_ref());
return Some(Task::none());
}
self.push_undo_snapshot(i, "NCOPY");
@ -638,9 +638,9 @@ impl OpenCADStudio {
}
}
self.tabs[i].dirty = true;
self.command_line.push_output(&format!(
self.command_line.push_output(crate::tf!(
"NCOPY: copied {n} nested object(s) into model space (blocks kept)."
));
).as_ref());
}
_ => return None,

View file

@ -85,7 +85,7 @@ impl OpenCADStudio {
.collect();
if handles.is_empty() {
self.command_line
.push_error("JUSTIFYTEXT: select text objects first.");
.push_error(crate::t!("JUSTIFYTEXT: select text objects first.").as_ref());
return Some(Task::none());
}
if opt.is_empty() {
@ -130,7 +130,7 @@ impl OpenCADStudio {
};
if text_align.is_none() && mtext_ap.is_none() {
self.command_line
.push_error("JUSTIFYTEXT: unknown justification option.");
.push_error(crate::t!("JUSTIFYTEXT: unknown justification option.").as_ref());
return Some(Task::none());
}
self.push_undo_snapshot(i, "JUSTIFYTEXT");
@ -175,7 +175,7 @@ impl OpenCADStudio {
.collect();
self.tabs[i].scene.bump_entities(&changes);
self.command_line
.push_output(&format!("JUSTIFYTEXT: updated {n} text object(s)."));
.push_output(crate::tf!("JUSTIFYTEXT: updated {n} text object(s).").as_ref());
}
// TCASE <Upper|Lower|Sentence|Title> — change the case of the text in
@ -207,7 +207,7 @@ impl OpenCADStudio {
.collect();
if handles.is_empty() {
self.command_line
.push_error("TCASE: select text objects first.");
.push_error(crate::t!("TCASE: select text objects first.").as_ref());
return Some(Task::none());
}
if !matches!(
@ -223,7 +223,7 @@ impl OpenCADStudio {
| "TITLE"
) {
self.command_line
.push_info("Usage: TCASE <Upper|Lower|Sentence|Title>");
.push_info(crate::t!("Usage: TCASE <Upper|Lower|Sentence|Title>").as_ref());
return Some(Task::none());
}
let conv = move |s: &str| -> String {
@ -263,7 +263,7 @@ impl OpenCADStudio {
.collect();
self.tabs[i].scene.bump_entities(&changes);
self.command_line
.push_output(&format!("TCASE: updated {n} text object(s)."));
.push_output(crate::tf!("TCASE: updated {n} text object(s).").as_ref());
}
// TEXTMASK — place a wipeout mask sized to each selected text object's
@ -296,7 +296,7 @@ impl OpenCADStudio {
.collect();
if handles.is_empty() {
self.command_line
.push_error("TEXTMASK: select text objects first.");
.push_error(crate::t!("TEXTMASK: select text objects first.").as_ref());
return Some(Task::none());
}
self.push_undo_snapshot(i, "TEXTMASK");
@ -339,7 +339,7 @@ impl OpenCADStudio {
.replace_selection(handles.iter().cloned().collect());
self.tabs[i].dirty = true;
self.command_line
.push_output(&format!("TEXTMASK: masked {n} text object(s)."));
.push_output(crate::tf!("TEXTMASK: masked {n} text object(s).").as_ref());
return self.dispatch_view("DRAWORDER FRONT", i);
}
@ -373,7 +373,7 @@ impl OpenCADStudio {
.collect();
if handles.is_empty() {
self.command_line
.push_error("TEXTFIT: select single-line text first.");
.push_error(crate::t!("TEXTFIT: select single-line text first.").as_ref());
return Some(Task::none());
}
self.push_undo_snapshot(i, "TEXTFIT");
@ -412,9 +412,9 @@ impl OpenCADStudio {
.map(|handle| (handle, crate::scene::ChangeKind::Modified))
.collect();
self.tabs[i].scene.bump_entities(&changes);
self.command_line.push_output(&format!(
self.command_line.push_output(crate::tf!(
"TEXTFIT: fitted {n} text object(s) to width {target}."
));
).as_ref());
}
// (text sequential numbering)
@ -450,7 +450,7 @@ impl OpenCADStudio {
.collect();
if texts.is_empty() {
self.command_line
.push_error("TCOUNT: select single-line text first.");
.push_error(crate::t!("TCOUNT: select single-line text first.").as_ref());
return Some(Task::none());
}
// Reading order: higher Y first, then smaller X.
@ -478,10 +478,10 @@ impl OpenCADStudio {
.map(|(handle, _, _)| (*handle, crate::scene::ChangeKind::Modified))
.collect();
self.tabs[i].scene.bump_entities(&changes);
self.command_line.push_output(&format!(
self.command_line.push_output(crate::tf!(
"TCOUNT: numbered {} text object(s) from {start}.",
texts.len()
));
).as_ref());
}
"MLEADER" => {
@ -575,7 +575,7 @@ impl OpenCADStudio {
}
if pts.len() < 2 {
self.command_line
.push_error("QDIM: no dimensionable endpoints in the selection.");
.push_error(crate::t!("QDIM: no dimensionable endpoints in the selection.").as_ref());
return Some(Task::none());
}
// Choose the dimension axis from the points' spread: a wider X
@ -596,7 +596,7 @@ impl OpenCADStudio {
}
if pts.len() < 2 {
self.command_line
.push_error("QDIM: endpoints collapse to a single position.");
.push_error(crate::t!("QDIM: endpoints collapse to a single position.").as_ref());
return Some(Task::none());
}
self.push_undo_snapshot(i, "QDIM");
@ -628,7 +628,7 @@ impl OpenCADStudio {
}
self.tabs[i].dirty = true;
self.command_line
.push_output(&format!("QDIM {made} dimensions created."));
.push_output(crate::tf!("QDIM {made} dimensions created.").as_ref());
return Some(Task::none());
}
@ -697,28 +697,28 @@ impl OpenCADStudio {
"ZOOM EXTENTS ALL" | "ZOOM EXTENTS ALL VIEWPORTS" | "ZEA" => {
self.tabs[i].scene.fit_all_model_viewports();
self.command_line.push_output("Zoom Extents — All Viewports");
self.command_line.push_output(crate::t!("Zoom Extents — All Viewports").as_ref());
}
"ZOOM EXTENTS" | "ZOOMEXTENTS" | "ZE" => {
self.tabs[i].scene.fit_all();
self.command_line.push_output("Zoom Extents");
self.command_line.push_output(crate::t!("Zoom Extents").as_ref());
}
"ZOOM IN" | "ZI" => {
self.tabs[i].scene.zoom_camera(1.0 / 1.5);
self.command_line.push_output("Zoom In");
self.command_line.push_output(crate::t!("Zoom In").as_ref());
}
"ZOOM OUT" | "ZO" => {
self.tabs[i].scene.zoom_camera(1.5);
self.command_line.push_output("Zoom Out");
self.command_line.push_output(crate::t!("Zoom Out").as_ref());
}
// ZOOM ALL — fit the configured drawing limits.
"ZOOM ALL" | "ZOOM A" | "ZA" => {
self.tabs[i].scene.fit_all_with_limits();
self.command_line.push_output("Zoom All");
self.command_line.push_output(crate::t!("Zoom All").as_ref());
}
// ZOOM SCALE — set zoom factor (e.g. "ZOOM SCALE 2" or "ZS 0.5")
@ -731,7 +731,7 @@ impl OpenCADStudio {
if factor > 0.0 {
self.tabs[i].scene.zoom_camera(1.0 / factor);
self.command_line
.push_output(&format!("Zoom Scale ×{factor:.3}"));
.push_output(crate::tf!("Zoom Scale ×{factor:.3}").as_ref());
}
}
}
@ -992,10 +992,10 @@ impl OpenCADStudio {
self.tabs[i].dirty = true;
self.refresh_properties();
self.command_line
.push_output(&format!("{exploded} object(s) exploded."));
.push_output(crate::tf!("{exploded} object(s) exploded.").as_ref());
} else {
self.command_line
.push_info("EXPLODE: no explodable objects selected.");
.push_info(crate::t!("EXPLODE: no explodable objects selected.").as_ref());
}
}
}
@ -1108,11 +1108,11 @@ impl OpenCADStudio {
});
let Some((center, radius)) = found else {
self.command_line
.push_error("DIMJOGGED: select an arc or circle first.");
.push_error(crate::t!("DIMJOGGED: select an arc or circle first.").as_ref());
return None;
};
if radius <= 0.0 {
self.command_line.push_error("DIMJOGGED: invalid radius.");
self.command_line.push_error(crate::t!("DIMJOGGED: invalid radius.").as_ref());
return None;
}
let k = std::f64::consts::FRAC_1_SQRT_2;
@ -1129,7 +1129,7 @@ impl OpenCADStudio {
.add_entity(acadrust::EntityType::Dimension(Dimension::Radius(dim)));
self.tabs[i].dirty = true;
self.command_line
.push_output("DIMJOGGED: created a jogged radius dimension.");
.push_output(crate::t!("DIMJOGGED: created a jogged radius dimension.").as_ref());
}
// ARCTEXT <text> — lay the text out as one Text entity per character
@ -1166,12 +1166,12 @@ impl OpenCADStudio {
});
let Some(arc) = arc else {
self.command_line
.push_error("ARCTEXT: select an arc first.");
.push_error(crate::t!("ARCTEXT: select an arc first.").as_ref());
return None;
};
let chars: Vec<char> = text.chars().filter(|c| !c.is_control()).collect();
if chars.is_empty() {
self.command_line.push_error("ARCTEXT: no printable text.");
self.command_line.push_error(crate::t!("ARCTEXT: no printable text.").as_ref());
return None;
}
let n = chars.len();
@ -1195,7 +1195,7 @@ impl OpenCADStudio {
}
self.tabs[i].dirty = true;
self.command_line
.push_output(&format!("ARCTEXT: placed {n} character(s) along the arc."));
.push_output(crate::tf!("ARCTEXT: placed {n} character(s) along the arc.").as_ref());
}
_ => return None,

View file

@ -8,7 +8,7 @@ impl OpenCADStudio {
"PAN" => {
self.tabs[i].pan_mode = true;
self.command_line
.push_output("PAN: drag with the left mouse button. Press Esc to exit.");
.push_output(crate::t!("PAN: drag with the left mouse button. Press Esc to exit.").as_ref());
}
// ── TABLE cell editing ─────────────────────────────────────────────
@ -46,18 +46,18 @@ impl OpenCADStudio {
if found {
self.push_undo_snapshot(i, "TABLE CELL");
self.tabs[i].dirty = true;
self.command_line.push_output(&format!(
self.command_line.push_output(crate::tf!(
"TABLE CELL: set [{row},{col}] = \"{text}\"."
));
).as_ref());
} else {
self.command_line.push_error(
"TABLE CELL: select a Table entity first, or row/col out of range."
crate::t!("TABLE CELL: select a Table entity first, or row/col out of range.").as_ref()
);
}
}
_ => {
self.command_line
.push_info("Usage: TABLE CELL <row> <col> <text>");
.push_info(crate::t!("Usage: TABLE CELL <row> <col> <text>").as_ref());
}
}
} else {
@ -111,9 +111,9 @@ impl OpenCADStudio {
}
}
self.tabs[i].dirty = true;
self.command_line.push_output(&format!(
self.command_line.push_output(crate::tf!(
"UCSICON {sub}: updated {count} viewport(s) + model space."
));
).as_ref());
}
"" => {
// Bare UCSICON toggles visibility.
@ -128,11 +128,11 @@ impl OpenCADStudio {
}
self.tabs[i].dirty = true;
let state = if visible { "ON" } else { "OFF" };
self.command_line.push_output(&format!("UCSICON {state}"));
self.command_line.push_output(crate::tf!("UCSICON {state}").as_ref());
}
_ => {
self.command_line
.push_info("Usage: UCSICON ON | OFF | NOORIGIN | ORIGIN");
.push_info(crate::t!("Usage: UCSICON ON | OFF | NOORIGIN | ORIGIN").as_ref());
}
}
}
@ -172,12 +172,12 @@ impl OpenCADStudio {
tokens.iter().map(|value| value.parse()).collect();
let Ok(values) = values else {
self.command_line
.push_error("LIMITS: four numeric coordinates required.");
.push_error(crate::t!("LIMITS: four numeric coordinates required.").as_ref());
return Some(Task::none());
};
if tokens.len() != 4 || !values.iter().all(|value| value.is_finite()) {
self.command_line
.push_error("LIMITS: four finite numeric coordinates required.");
.push_error(crate::t!("LIMITS: four finite numeric coordinates required.").as_ref());
} else {
let first = glam::DVec2::new(values[0], values[1]);
let opposite = glam::DVec2::new(values[2], values[3]);
@ -185,15 +185,15 @@ impl OpenCADStudio {
let max = first.max(opposite);
if min.x == max.x || min.y == max.y {
self.command_line
.push_error("LIMITS: corners must define a non-zero area.");
.push_error(crate::t!("LIMITS: corners must define a non-zero area.").as_ref());
} else {
self.push_undo_snapshot(i, "LIMITS");
self.tabs[i].scene.set_current_drawing_limits(min, max);
self.tabs[i].dirty = true;
self.command_line.push_output(&format!(
self.command_line.push_output(crate::tf!(
"Drawing limits: {:.4},{:.4} to {:.4},{:.4}.",
min.x, min.y, max.x, max.y
));
).as_ref());
}
}
}
@ -249,13 +249,13 @@ impl OpenCADStudio {
// ── TOOLPALETTES — not yet implemented ───────────────────────────────
"TOOLPALETTES" => {
self.command_line
.push_info("TOOLPALETTES: Tool Palettes not yet implemented.");
.push_info(crate::t!("TOOLPALETTES: Tool Palettes not yet implemented.").as_ref());
}
// ── SHEETSET — not yet implemented ───────────────────────────────────
"SHEETSET" => {
self.command_line
.push_info("SHEETSET: Sheet Set Manager not yet implemented.");
.push_info(crate::t!("SHEETSET: Sheet Set Manager not yet implemented.").as_ref());
}
// ── XDATA — read/write extended entity data ──────────────────────────
@ -288,7 +288,7 @@ impl OpenCADStudio {
.collect();
if selected_handles.is_empty() {
self.command_line
.push_error("XDATA: select entities first.");
.push_error(crate::t!("XDATA: select entities first.").as_ref());
} else {
match sub.as_str() {
"LIST" | "" => {
@ -297,18 +297,18 @@ impl OpenCADStudio {
let xd = &entity.common().extended_data;
if xd.is_empty() {
self.command_line
.push_output(&format!(" {:x}: no xdata.", sh.value()));
.push_output(crate::tf!(" {:x}: no xdata.", sh.value()).as_ref());
} else {
for rec in xd.records() {
self.command_line.push_output(&format!(
self.command_line.push_output(crate::tf!(
" {:x} [{}]: {} value(s)",
sh.value(),
rec.application_name,
rec.values.len()
));
).as_ref());
for v in &rec.values {
self.command_line
.push_output(&format!(" {:?}", v));
.push_output(crate::tf!(" {:?}", v).as_ref());
}
}
}
@ -329,10 +329,10 @@ impl OpenCADStudio {
}
}
self.tabs[i].dirty = true;
self.command_line.push_output(&format!(
self.command_line.push_output(crate::tf!(
"XDATA: set [{app}] = \"{val}\" on {} entity/entities.",
selected_handles.len()
));
).as_ref());
}
"CLEAR" => {
let app_filter = parts.get(1).copied();
@ -360,11 +360,11 @@ impl OpenCADStudio {
}
}
self.tabs[i].dirty = true;
self.command_line.push_output("XDATA: cleared.");
self.command_line.push_output(crate::t!("XDATA: cleared.").as_ref());
}
_ => {
self.command_line
.push_info("Usage: XDATA LIST | SET <app> <value> | CLEAR [app]");
.push_info(crate::t!("Usage: XDATA LIST | SET <app> <value> | CLEAR [app]").as_ref());
}
}
}
@ -486,7 +486,7 @@ impl OpenCADStudio {
}
_ => {
self.command_line
.push_error("Usage: PLOTSTYLE [LOAD | CLEAR | STATUS]");
.push_error(crate::t!("Usage: PLOTSTYLE [LOAD | CLEAR | STATUS]").as_ref());
}
}
}
@ -529,7 +529,7 @@ impl OpenCADStudio {
.collect();
if handles.is_empty() {
self.command_line
.push_error("UNDERLAY: select underlay entities first.");
.push_error(crate::t!("UNDERLAY: select underlay entities first.").as_ref());
} else {
let parts: Vec<&str> = sub.splitn(2, char::is_whitespace).collect();
let action = parts.first().copied().unwrap_or("");
@ -589,7 +589,7 @@ impl OpenCADStudio {
},
_ => {
// No sub-command: print status.
self.command_line.push_output(&format!(
self.command_line.push_output(crate::tf!(
"Underlay {:x}: fade={}, contrast={}, on={}, clip={}, mono={}",
h.value(),
ul.fade,
@ -597,7 +597,7 @@ impl OpenCADStudio {
ul.is_on(),
ul.is_clipping(),
ul.is_monochrome(),
));
).as_ref());
}
}
}
@ -605,10 +605,10 @@ impl OpenCADStudio {
if changed > 0 {
self.tabs[i].dirty = true;
self.command_line
.push_info(&format!("Updated {changed} underlay(s)."));
.push_info(crate::tf!("Updated {changed} underlay(s).").as_ref());
} else if !action.is_empty() {
self.command_line.push_error(
"Usage: UNDERLAY [FADE <n>|CONTRAST <n>|ON|OFF|CLIP ON|OFF|MONO ON|OFF]"
crate::t!("Usage: UNDERLAY [FADE <n>|CONTRAST <n>|ON|OFF|CLIP ON|OFF|MONO ON|OFF]").as_ref()
);
}
}
@ -635,13 +635,13 @@ impl OpenCADStudio {
.collect();
if handles.is_empty() {
self.command_line
.push_error("OBJECTSCALE: select objects first.");
.push_error(crate::t!("OBJECTSCALE: select objects first.").as_ref());
return Some(Task::none());
}
self.push_undo_snapshot(i, "OBJECTSCALE");
let Some(scale) = self.tabs[i].scene.creation_annotation_scale_handle() else {
self.command_line
.push_error("OBJECTSCALE: the active annotation scale is unavailable.");
.push_error(crate::t!("OBJECTSCALE: the active annotation scale is unavailable.").as_ref());
return Some(Task::none());
};
let mut n = 0usize;
@ -665,9 +665,9 @@ impl OpenCADStudio {
.collect();
self.tabs[i].scene.bump_entities(&changes);
self.tabs[i].dirty = true;
self.command_line.push_output(&format!(
self.command_line.push_output(crate::tf!(
"OBJECTSCALE: added the active scale to {n} object(s)."
));
).as_ref());
return Some(Task::none());
}
@ -688,13 +688,13 @@ impl OpenCADStudio {
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)");
self.command_line.push_info(crate::t!("Usage: HYPERLINK <url> (select objects first)").as_ref());
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.");
self.command_line.push_error(crate::t!("HYPERLINK: select objects first.").as_ref());
return Some(Task::none());
}
self.push_undo_snapshot(i, "HYPERLINK");
@ -710,7 +710,7 @@ impl OpenCADStudio {
}
self.tabs[i].dirty = true;
self.command_line
.push_output(&format!("HYPERLINK: attached to {n} object(s)."));
.push_output(crate::tf!("HYPERLINK: attached to {n} object(s).").as_ref());
return Some(Task::none());
}
@ -745,10 +745,10 @@ impl OpenCADStudio {
.collect();
if handles.is_empty() {
self.command_line
.push_error("ADJUST: select raster image(s) first.");
.push_error(crate::t!("ADJUST: select raster image(s) first.").as_ref());
} else if action.is_empty() {
self.command_line
.push_info("Usage: ADJUST BRIGHTNESS|CONTRAST|FADE <0-100>");
.push_info(crate::t!("Usage: ADJUST BRIGHTNESS|CONTRAST|FADE <0-100>").as_ref());
} else if let Ok(v) = arg.parse::<u8>() {
let v = v.min(100);
self.push_undo_snapshot(i, "ADJUST");
@ -792,14 +792,14 @@ impl OpenCADStudio {
.collect();
self.tabs[i].scene.bump_entities(&changes);
self.command_line
.push_output(&format!("ADJUST: {action} = {v} on {changed} image(s)."));
.push_output(crate::tf!("ADJUST: {action} = {v} on {changed} image(s).").as_ref());
} else {
self.command_line.push_error(
"ADJUST: no raster images selected, or unknown property (use BRIGHTNESS|CONTRAST|FADE).",
);
}
} else {
self.command_line.push_error("ADJUST: value must be 0-100.");
self.command_line.push_error(crate::t!("ADJUST: value must be 0-100.").as_ref());
}
}
@ -837,7 +837,7 @@ impl OpenCADStudio {
}
_ => self
.command_line
.push_error("ANNOALLVISIBLE: enter 0 or 1."),
.push_error(crate::t!("ANNOALLVISIBLE: enter 0 or 1.").as_ref()),
}
}
"ANNOAUTOSCALE" => {
@ -867,7 +867,7 @@ impl OpenCADStudio {
.collect();
if handles.is_empty() {
self.command_line
.push_error("ANNOUPDATE: select annotation objects first.");
.push_error(crate::t!("ANNOUPDATE: select annotation objects first.").as_ref());
return Some(Task::none());
}
self.push_undo_snapshot(i, "ANNOUPDATE");
@ -891,7 +891,7 @@ impl OpenCADStudio {
self.tabs[i].dirty = true;
}
self.command_line
.push_output(&format!("ANNOUPDATE: updated {updated} object(s)."));
.push_output(crate::tf!("ANNOUPDATE: updated {updated} object(s).").as_ref());
return Some(Task::none());
}
cmd if cmd.starts_with("ANNOSCALE ") || cmd.starts_with("CANNOSCALE ") => {
@ -909,7 +909,7 @@ impl OpenCADStudio {
.current_annotation_scale
.clone();
self.command_line
.push_output(&format!("Current annotation scale: {name}"));
.push_output(crate::tf!("Current annotation scale: {name}").as_ref());
return Some(Task::none());
}
let previous = self.tabs[i].scene.displayed_annotation_scale_handle();
@ -924,11 +924,11 @@ impl OpenCADStudio {
}
self.tabs[i].dirty = true;
self.command_line
.push_output(&format!("Annotation scale: {arg}"));
.push_output(crate::tf!("Annotation scale: {arg}").as_ref());
}
None => self
.command_line
.push_error("Usage: ANNOSCALE <ratio> e.g. 1:50, 2:1, or a factor"),
.push_error(crate::t!("Usage: ANNOSCALE <ratio> e.g. 1:50, 2:1, or a factor").as_ref()),
}
}
@ -962,19 +962,19 @@ impl OpenCADStudio {
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}."));
.push_output(crate::tf!("Added annotation scale {arg}.").as_ref());
} else {
self.command_line
.push_info(&format!("Scale {arg} already exists."));
.push_info(crate::tf!("Scale {arg} already exists.").as_ref());
}
}
_ => self
.command_line
.push_error("SCALELISTEDIT ADD: use a ratio like 1:50."),
.push_error(crate::t!("SCALELISTEDIT ADD: use a ratio like 1:50.").as_ref()),
},
None => self
.command_line
.push_error("SCALELISTEDIT ADD: use a ratio like 1:50."),
.push_error(crate::t!("SCALELISTEDIT ADD: use a ratio like 1:50.").as_ref()),
},
"DELETE" | "REMOVE" => {
let current = self.tabs[i]
@ -984,20 +984,20 @@ impl OpenCADStudio {
.current_annotation_scale
.clone();
if arg.is_empty() {
self.command_line.push_info("Usage: SCALELISTEDIT DELETE <name>");
self.command_line.push_info(crate::t!("Usage: SCALELISTEDIT DELETE <name>").as_ref());
} else if arg.eq_ignore_ascii_case(&current) {
self.command_line.push_error(&format!(
self.command_line.push_error(crate::tf!(
"Cannot delete the current annotation scale ({arg})."
));
).as_ref());
} 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}."));
.push_output(crate::tf!("Removed annotation scale {arg}.").as_ref());
} else {
self.command_line
.push_info(&format!("No annotation scale named {arg}."));
.push_info(crate::tf!("No annotation scale named {arg}.").as_ref());
}
}
}
@ -1009,15 +1009,15 @@ impl OpenCADStudio {
.map(|(n, _, _)| n)
.collect();
if names.is_empty() {
self.command_line.push_info("No annotation scales defined.");
self.command_line.push_info(crate::t!("No annotation scales defined.").as_ref());
} else {
self.command_line
.push_output(&format!("Annotation scales: {}", names.join(", ")));
.push_output(crate::tf!("Annotation scales: {}", names.join(", ")).as_ref());
}
}
_ => self
.command_line
.push_info("Usage: SCALELISTEDIT [ADD 1:50 | DELETE 1:50]"),
.push_info(crate::t!("Usage: SCALELISTEDIT [ADD 1:50 | DELETE 1:50]").as_ref()),
}
}
@ -1056,7 +1056,7 @@ impl OpenCADStudio {
let ncols = rows_data.iter().map(|r| r.len()).max().unwrap_or(0);
if nrows == 0 || ncols == 0 {
self.command_line
.push_error("DATALINK: the CSV file is empty.");
.push_error(crate::t!("DATALINK: the CSV file is empty.").as_ref());
return Some(Task::none());
}
use acadrust::entities::TableBuilder;
@ -1076,13 +1076,13 @@ impl OpenCADStudio {
.scene
.add_entity_clone(acadrust::EntityType::Table(table));
self.tabs[i].dirty = true;
self.command_line.push_output(&format!(
self.command_line.push_output(crate::tf!(
"DATALINK: imported {nrows}×{ncols} cells into a table at the origin."
));
).as_ref());
}
Err(e) => {
self.command_line
.push_error(&format!("DATALINK: cannot read \"{path}\": {e}"));
.push_error(crate::tf!("DATALINK: cannot read \"{path}\": {e}").as_ref());
}
}
}
@ -1110,7 +1110,7 @@ impl OpenCADStudio {
let pts = parse_landxml_cgpoints(&xml);
if pts.is_empty() {
self.command_line
.push_info("LANDXMLIMPORT: no <CgPoint> survey points found.");
.push_info(crate::t!("LANDXMLIMPORT: no <CgPoint> survey points found.").as_ref());
return Some(Task::none());
}
self.push_undo_snapshot(i, "LANDXMLIMPORT");
@ -1122,21 +1122,21 @@ impl OpenCADStudio {
.add_entity_clone(acadrust::EntityType::Point(p));
}
self.tabs[i].dirty = true;
self.command_line.push_output(&format!(
self.command_line.push_output(crate::tf!(
"LANDXMLIMPORT: imported {} survey point(s). Use ZOOM EXTENTS to view.",
pts.len()
));
).as_ref());
}
Err(e) => self
.command_line
.push_error(&format!("LANDXMLIMPORT: cannot read \"{path}\": {e}")),
.push_error(crate::tf!("LANDXMLIMPORT: cannot read \"{path}\": {e}").as_ref()),
}
}
"POINTCLOUDATTACH" | "RECAP" | "SYNCPVIEWPORTS" | "UNDERLAYLAYERS"
| "UOSNAP" => {
self.command_line
.push_info(&format!("{cmd}: not yet implemented."));
.push_info(crate::tf!("{cmd}: not yet implemented.").as_ref());
}
_ => return None,

View file

@ -76,7 +76,7 @@ impl OpenCADStudio {
.collect();
if selected_handles.is_empty() {
self.command_line
.push_error("ATTEDIT: select an Insert entity first.");
.push_error(crate::t!("ATTEDIT: select an Insert entity first.").as_ref());
} else {
let mut found_any = false;
for sh in &selected_handles {
@ -90,17 +90,17 @@ impl OpenCADStudio {
if rest.is_empty() {
// List attributes.
if ins.attributes.is_empty() {
self.command_line.push_output(&format!(
self.command_line.push_output(crate::tf!(
" Insert {:x}: no attributes.",
sh.value()
));
).as_ref());
} else {
for attr in &ins.attributes {
self.command_line.push_output(&format!(
self.command_line.push_output(crate::tf!(
" [{tag}] = {val}",
tag = attr.tag,
val = attr.get_value()
));
).as_ref());
}
}
}
@ -108,7 +108,7 @@ impl OpenCADStudio {
}
if !found_any {
self.command_line
.push_error("ATTEDIT: no Insert entities in selection.");
.push_error(crate::t!("ATTEDIT: no Insert entities in selection.").as_ref());
}
// If tag + value supplied, mutate attributes.
if parts.len() == 2 && !parts[0].is_empty() {
@ -133,13 +133,13 @@ impl OpenCADStudio {
}
if changed > 0 {
self.tabs[i].dirty = true;
self.command_line.push_output(&format!(
self.command_line.push_output(crate::tf!(
"ATTEDIT: updated {changed} attribute(s) [{tag_up}] = {new_val}."
));
).as_ref());
} else {
self.command_line.push_error(&format!(
self.command_line.push_error(crate::tf!(
"ATTEDIT: tag '{tag_up}' not found in selection."
));
).as_ref());
}
}
}
@ -187,13 +187,13 @@ impl OpenCADStudio {
}
}
self.tabs[i].dirty = true;
self.command_line.push_output(&format!(
self.command_line.push_output(crate::tf!(
"ATTDISP {sub}: {count} attribute definition(s) updated."
));
).as_ref());
}
_ => {
self.command_line
.push_info("Usage: ATTDISP ON | OFF | NORMAL");
.push_info(crate::t!("Usage: ATTDISP ON | OFF | NORMAL").as_ref());
}
}
}
@ -327,7 +327,7 @@ impl OpenCADStudio {
}
None => {
self.command_line
.push_info("ARC Continue No previous line or arc to continue.");
.push_info(crate::t!("ARC Continue No previous line or arc to continue.").as_ref());
}
}
}
@ -599,7 +599,7 @@ impl OpenCADStudio {
self.tabs[i].active_cmd = Some(Box::new(cmd));
} else {
self.command_line
.push_error("HATCHEDIT: selected entity is not a hatch.");
.push_error(crate::t!("HATCHEDIT: selected entity is not a hatch.").as_ref());
}
} else {
let cmd = HatcheditCommand::new();
@ -721,7 +721,7 @@ impl OpenCADStudio {
self.tabs[i].dirty = true;
self.refresh_properties();
self.command_line
.push_output(&format!("{n} object(s) erased."));
.push_output(crate::tf!("{n} object(s) erased.").as_ref());
if let Some(pd) = pending {
self.commit_undo_delta(i, pd);
}
@ -783,7 +783,7 @@ impl OpenCADStudio {
return Some(self.solid_polysolid(nums[0], nums[1]));
}
self.command_line
.push_info("Usage: POLYSOLID <width> <height> (select a polyline first)");
.push_info(crate::t!("Usage: POLYSOLID <width> <height> (select a polyline first)").as_ref());
}
// SPLINEFIT — fit a smooth spline through the selected polyline's points.
@ -829,7 +829,7 @@ impl OpenCADStudio {
}
if loops.is_empty() {
self.command_line
.push_error("REGION: select closed polylines or circles.");
.push_error(crate::t!("REGION: select closed polylines or circles.").as_ref());
} else {
self.push_undo_snapshot(i, "REGION");
let count = loops.len();
@ -845,7 +845,7 @@ impl OpenCADStudio {
}
self.tabs[i].dirty = true;
self.command_line
.push_output(&format!("REGION: created {count} region(s)."));
.push_output(crate::tf!("REGION: created {count} region(s).").as_ref());
}
}
@ -871,7 +871,7 @@ impl OpenCADStudio {
return Some(self.solid_pyramid(nums[0], nums[1], sides));
}
self.command_line
.push_info("Usage: PYRAMID <radius> <height> [sides] (default 4 sides)");
.push_info(crate::t!("Usage: PYRAMID <radius> <height> [sides] (default 4 sides)").as_ref());
}
// SECTION [X|Y|Z] <value> — draw the cross-section outline of the solid.
@ -1070,7 +1070,7 @@ impl OpenCADStudio {
}
if sel.len() == 1 {
self.command_line
.push_error("DDEDIT: selected entity is not text.");
.push_error(crate::t!("DDEDIT: selected entity is not text.").as_ref());
} else {
let cmd = DdeditCommand::new();
self.command_line.push_info(&cmd.prompt());
@ -1093,7 +1093,7 @@ impl OpenCADStudio {
"Multiple"
};
self.command_line
.push_output(&format!("Current settings: Edit mode = {}", mode_str));
.push_output(crate::tf!("Current settings: Edit mode = {}", mode_str).as_ref());
let new_cmd = TexteditCommand::new(self.texteditmode);
self.command_line.push_info(&new_cmd.prompt());
self.tabs[i].active_cmd = Some(Box::new(new_cmd));

View file

@ -11,7 +11,7 @@ impl OpenCADStudio {
"SAVEALL" => {
if self.read_only {
self.command_line
.push_error("Read-only session (--read-only): saving is disabled.");
.push_error(crate::t!("Read-only session (--read-only): saving is disabled.").as_ref());
return Some(Task::none());
}
#[cfg(not(target_arch = "wasm32"))]
@ -27,10 +27,10 @@ impl OpenCADStudio {
.active_save_jobs
.contains_key(&self.tabs[t].id)
{
self.command_line.push_info(&format!(
self.command_line.push_info(crate::tf!(
"SAVEALL: {} already has a save running",
path.display()
));
).as_ref());
skipped += 1;
continue;
}
@ -42,28 +42,28 @@ impl OpenCADStudio {
Ok(()) => {
saved += 1;
}
Err(e) => self.command_line.push_error(&format!(
Err(e) => self.command_line.push_error(crate::tf!(
"SAVEALL: {} failed: {e}",
path.display()
)),
).as_ref()),
}
} else {
skipped += 1;
}
}
self.command_line.push_output(&format!(
self.command_line.push_output(crate::tf!(
"SAVEALL: saved {saved} drawing(s){}.",
if skipped > 0 {
format!("; {skipped} need SAVEAS (no file path yet)")
} else {
String::new()
}
));
).as_ref());
}
#[cfg(target_arch = "wasm32")]
{
self.command_line
.push_info("SAVEALL: save each tab individually in the web build.");
.push_info(crate::t!("SAVEALL: save each tab individually in the web build.").as_ref());
}
return Some(Task::none());
}
@ -76,7 +76,7 @@ impl OpenCADStudio {
Ok(n) => return Some(Task::done(Message::UndoMany(n))),
Err(_) => {
self.command_line
.push_error("Usage: UNDO [number of steps]");
.push_error(crate::t!("Usage: UNDO [number of steps]").as_ref());
return Some(Task::none());
}
}
@ -87,7 +87,7 @@ impl OpenCADStudio {
// without undoing any work done since.
"OOPS" => {
if self.oops_cache.is_empty() {
self.command_line.push_info("OOPS: nothing to restore.");
self.command_line.push_info(crate::t!("OOPS: nothing to restore.").as_ref());
} else {
let restored = std::mem::take(&mut self.oops_cache);
let pending = self.begin_undo(i, "OOPS", restored.len(), true);
@ -99,7 +99,7 @@ impl OpenCADStudio {
self.commit_undo_delta(i, pending);
}
self.command_line
.push_output(&format!("OOPS: restored {n} object(s)."));
.push_output(crate::tf!("OOPS: restored {n} object(s).").as_ref());
}
}
"CLEAR" | "CLR" => return Some(Task::done(Message::ClearScene)),
@ -161,7 +161,7 @@ impl OpenCADStudio {
}
};
self.command_line
.push_output(&format!("Visual style: {label}."));
.push_output(crate::tf!("Visual style: {label}.").as_ref());
return Some(Task::done(Message::SetWireframe(wireframe)));
}
// CLOSE — close the active drawing tab (with the unsaved-changes
@ -216,18 +216,18 @@ impl OpenCADStudio {
}
}
}
self.command_line.push_output(&format!(
self.command_line.push_output(crate::tf!(
"{cmd}: packaged {copied} file(s) into {}",
folder.display()
));
).as_ref());
}
Err(e) => self
.command_line
.push_error(&format!("{cmd}: cannot create folder ({e}).")),
.push_error(crate::tf!("{cmd}: cannot create folder ({e}).").as_ref()),
}
} else {
self.command_line
.push_error("ARCHIVE: save the drawing first (it has no file path yet).");
.push_error(crate::t!("ARCHIVE: save the drawing first (it has no file path yet).").as_ref());
}
}
@ -302,7 +302,7 @@ impl OpenCADStudio {
self.tabs[i].scene.recolor_meshes();
self.tabs[i].scene.bump_geometry();
self.command_line
.push_output("Background reset to default.");
.push_output(crate::t!("Background reset to default.").as_ref());
} else if let Some(rgba) = parse_background_color(&args) {
if is_paper {
self.tabs[i].paper_bg_color = Some(rgba);
@ -316,12 +316,12 @@ impl OpenCADStudio {
self.tabs[i].scene.recolor_meshes();
self.tabs[i].scene.bump_geometry();
let [r, g, b, _] = rgba;
self.command_line.push_output(&format!(
self.command_line.push_output(crate::tf!(
"Background: rgb({}, {}, {})",
(r * 255.0).round() as u8,
(g * 255.0).round() as u8,
(b * 255.0).round() as u8
));
).as_ref());
// Persisted centrally after this message via
// `persist_settings_if_changed()`.
} else {
@ -361,20 +361,20 @@ impl OpenCADStudio {
})
.map(|l| Task::done(Message::Command(l.to_string())))
.collect();
self.command_line.push_output(&format!(
self.command_line.push_output(crate::tf!(
"SCRIPT: running {} command(s) from {p}.",
cmds.len()
));
).as_ref());
return Some(Task::batch(cmds));
}
Err(e) => {
self.command_line
.push_error(&format!("SCRIPT: cannot read {p}: {e}"));
.push_error(crate::tf!("SCRIPT: cannot read {p}: {e}").as_ref());
}
},
_ => {
self.command_line
.push_info("Usage: SCRIPT <path to .scr file>");
.push_info(crate::t!("Usage: SCRIPT <path to .scr file>").as_ref());
}
}
}

View file

@ -5,7 +5,7 @@ impl OpenCADStudio {
match cmd {
"3DORBIT" => {
self.command_line
.push_info("3D Orbit: drag with right mouse button.");
.push_info(crate::t!("3D Orbit: drag with right mouse button.").as_ref());
}
// ── Selection utilities ───────────────────────────────────────
@ -24,20 +24,20 @@ impl OpenCADStudio {
self.tabs[i].scene.select_entity(h, false);
}
self.command_line
.push_output(&format!("SELECTALL: {} object(s) selected.", count));
.push_output(crate::tf!("SELECTALL: {} object(s) selected.", count).as_ref());
self.refresh_properties();
}
"DESELECT" | "DESELALL" => {
self.tabs[i].scene.deselect_all();
self.command_line.push_output("Deselected.");
self.command_line.push_output(crate::t!("Deselected.").as_ref());
self.refresh_properties();
}
"SELECTSIMILAR" | "SELSIM" => {
let added = self.tabs[i].scene.select_similar();
self.command_line
.push_output(&format!("Select Similar: {} added.", added));
.push_output(crate::tf!("Select Similar: {} added.", added).as_ref());
self.refresh_properties();
}
@ -68,11 +68,11 @@ impl OpenCADStudio {
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");
.push_info(crate::t!("Usage: CAL <expression> e.g. CAL (2+3)*4").as_ref());
} else {
match arith_eval(expr) {
Ok(v) => self.command_line.push_output(&format!("= {v}")),
Err(e) => self.command_line.push_error(&format!("CAL: {e}")),
Ok(v) => self.command_line.push_output(crate::tf!("= {v}").as_ref()),
Err(e) => self.command_line.push_error(crate::tf!("CAL: {e}").as_ref()),
}
}
}
@ -82,7 +82,7 @@ impl OpenCADStudio {
let selected: Vec<_> = self.tabs[i].scene.selected_entities();
if selected.is_empty() {
self.command_line
.push_error("LIST: no entities selected. Select entities first.");
.push_error(crate::t!("LIST: no entities selected. Select entities first.").as_ref());
} else {
for (handle, _) in &selected {
if let Some(entity) = self.tabs[i].scene.document.get_entity(*handle) {
@ -101,7 +101,7 @@ impl OpenCADStudio {
};
// Entity-specific details
let details = entity_list_details(entity);
self.command_line.push_output(&format!(
self.command_line.push_output(crate::tf!(
"{type_name} Handle:{:X} Layer:{} Color:{} LT:{}{}",
handle.value(),
common.layer,
@ -112,7 +112,7 @@ impl OpenCADStudio {
} else {
format!("\n {details}")
}
));
).as_ref());
}
}
}
@ -127,7 +127,7 @@ impl OpenCADStudio {
let selected = scene.selected_entities();
if selected.is_empty() {
self.command_line
.push_error("SELHANDLES: no entities selected. Select entities first.");
.push_error(crate::t!("SELHANDLES: no entities selected. Select entities first.").as_ref());
} else {
use std::collections::BTreeMap;
let space = if scene.current_layout == "Model" {
@ -207,16 +207,14 @@ impl OpenCADStudio {
.collect();
if lines.is_empty() {
self.command_line
.push_info("DBLIST: drawing has no entities.");
.push_info(crate::t!("DBLIST: drawing has no entities.").as_ref());
} else {
let count = lines.len();
for l in lines {
self.command_line.push_output(&l);
}
self.command_line.push_output(&format!(
"DBLIST: {count} entit{}.",
if count == 1 { "y" } else { "ies" }
));
self.command_line
.push_output(crate::tf!("DBLIST: {count} objects.").as_ref());
}
}
@ -311,7 +309,7 @@ impl OpenCADStudio {
// If a session is already active, tell the user.
if self.tabs[i].refedit_session.is_some() {
self.command_line
.push_error("REFEDIT: a session is already active. Use REFCLOSE first.");
.push_error(crate::t!("REFEDIT: a session is already active. Use REFCLOSE first.").as_ref());
} else {
// Check if a single INSERT is already selected.
let selected: Vec<_> =
@ -337,7 +335,7 @@ impl OpenCADStudio {
use crate::modules::draw::modify::block_edit::BlockEditPickCommand;
if self.tabs[i].refedit_session.is_some() {
self.command_line
.push_error("BEDIT: finish the active REFEDIT (REFCLOSE) first.");
.push_error(crate::t!("BEDIT: finish the active REFEDIT (REFCLOSE) first.").as_ref());
} else {
// Jump straight to begin when a single INSERT is preselected.
let selected: Vec<_> =
@ -369,7 +367,7 @@ impl OpenCADStudio {
Some(acadrust::EntityType::Insert(ins)) => ins.clone(),
_ => {
self.command_line
.push_error("BEDIT: selected object is not a block reference.");
.push_error(crate::t!("BEDIT: selected object is not a block reference.").as_ref());
return Some(Task::none());
}
};
@ -383,16 +381,16 @@ impl OpenCADStudio {
{
Some(br) => (br.handle, br.flags.is_xref),
None => {
self.command_line.push_error(&format!(
self.command_line.push_error(crate::tf!(
"BEDIT: block \"{}\" not found.",
insert.block_name
));
).as_ref());
return Some(Task::none());
}
};
if is_xref {
self.command_line
.push_error("BEDIT: cannot edit an external reference (xref).");
.push_error(crate::t!("BEDIT: cannot edit an external reference (xref).").as_ref());
return Some(Task::none());
}
if self.tabs[i]
@ -519,10 +517,10 @@ impl OpenCADStudio {
self.refresh_properties();
self.tabs[i].active_cmd = None;
self.tabs[i].dirty = true;
self.command_line.push_info(&format!(
self.command_line.push_info(crate::tf!(
"BEDIT: Editing block \"{}\". Use Save Block or Discard to finish.",
insert.block_name
));
).as_ref());
}
"BEDIT_SAVE" => {
@ -532,12 +530,12 @@ impl OpenCADStudio {
}
None => {
self.command_line
.push_error("BEDIT_SAVE: no block editor is open.");
.push_error(crate::t!("BEDIT_SAVE: no block editor is open.").as_ref());
return Some(Task::none());
}
Some(_) => {
self.command_line
.push_error("BEDIT_SAVE: invalid block editor state.");
.push_error(crate::t!("BEDIT_SAVE: invalid block editor state.").as_ref());
return Some(Task::none());
}
};
@ -549,10 +547,10 @@ impl OpenCADStudio {
&session.return_camera,
);
self.tabs[i].dirty = true;
self.command_line.push_output(&format!(
self.command_line.push_output(crate::tf!(
"BEDIT: Block \"{}\" saved. All references updated.",
session.block_name
));
).as_ref());
}
"BEDIT_DISCARD" => {
@ -562,12 +560,12 @@ impl OpenCADStudio {
}
None => {
self.command_line
.push_error("BEDIT_DISCARD: no block editor is open.");
.push_error(crate::t!("BEDIT_DISCARD: no block editor is open.").as_ref());
return Some(Task::none());
}
Some(_) => {
self.command_line
.push_error("BEDIT_DISCARD: invalid block editor state.");
.push_error(crate::t!("BEDIT_DISCARD: invalid block editor state.").as_ref());
return Some(Task::none());
}
};
@ -625,10 +623,10 @@ impl OpenCADStudio {
&return_camera,
);
self.tabs[i].dirty = true;
self.command_line.push_output(&format!(
self.command_line.push_output(crate::tf!(
"BEDIT: Block \"{}\" edit discarded.",
block_name
));
).as_ref());
}
cmd if cmd.starts_with("REFEDIT_BEGIN:") => {
@ -645,7 +643,7 @@ impl OpenCADStudio {
Some(acadrust::EntityType::Insert(ins)) => ins.clone(),
_ => {
self.command_line
.push_error("REFEDIT: selected object is not an INSERT.");
.push_error(crate::t!("REFEDIT: selected object is not an INSERT.").as_ref());
return Some(Task::none());
}
};
@ -681,10 +679,10 @@ impl OpenCADStudio {
{
Some(br) => br.handle,
None => {
self.command_line.push_error(&format!(
self.command_line.push_error(crate::tf!(
"REFEDIT: block \"{}\" not found.",
insert.block_name
));
).as_ref());
return Some(Task::none());
}
};
@ -712,7 +710,7 @@ impl OpenCADStudio {
};
if block_entities.is_empty() {
self.command_line.push_error("REFEDIT: block is empty.");
self.command_line.push_error(crate::t!("REFEDIT: block is empty.").as_ref());
return Some(Task::none());
}
@ -762,10 +760,10 @@ impl OpenCADStudio {
// No active command — the user edits the block's geometry freely
// (move, grips, draw, erase…) and runs REFCLOSE when done. (#136)
self.tabs[i].active_cmd = None;
self.command_line.push_info(&format!(
self.command_line.push_info(crate::tf!(
"REFEDIT: Editing block \"{}\". Run REFCLOSE to save, REFCLOSE_DISCARD to cancel.",
insert.block_name
));
).as_ref());
}
"REFCLOSE" => {
@ -776,7 +774,7 @@ impl OpenCADStudio {
self.tabs[i].active_cmd = Some(Box::new(cmd_obj));
} else {
self.command_line
.push_error("REFCLOSE: no REFEDIT session active.");
.push_error(crate::t!("REFCLOSE: no REFEDIT session active.").as_ref());
}
}
@ -788,7 +786,7 @@ impl OpenCADStudio {
Some(s) => s,
None => {
self.command_line
.push_error("REFCLOSE: no REFEDIT session active.");
.push_error(crate::t!("REFCLOSE: no REFEDIT session active.").as_ref());
return Some(Task::none());
}
};
@ -866,10 +864,10 @@ impl OpenCADStudio {
}
self.tabs[i].dirty = true;
self.command_line.push_output(&format!(
self.command_line.push_output(crate::tf!(
"REFCLOSE: Block \"{}\" saved. All references updated.",
session.block_name
));
).as_ref());
// End the edit fade before rebuilding, so the restored geometry
// recolours bright. (#136)
self.tabs[i].scene.set_refedit_keep(None);
@ -882,7 +880,7 @@ impl OpenCADStudio {
Some(s) => s,
None => {
self.command_line
.push_error("REFCLOSE: no REFEDIT session active.");
.push_error(crate::t!("REFCLOSE: no REFEDIT session active.").as_ref());
return Some(Task::none());
}
};
@ -908,7 +906,7 @@ impl OpenCADStudio {
// End the edit fade — restore the drawing to full brightness.
self.tabs[i].scene.set_refedit_keep(None);
self.command_line
.push_output("REFCLOSE: Changes discarded.");
.push_output(crate::t!("REFCLOSE: Changes discarded.").as_ref());
}
"ALIGN" => {
@ -966,20 +964,20 @@ impl OpenCADStudio {
let selected = self.tabs[i].scene.selected_entities();
if selected.is_empty() {
self.command_line
.push_error("MASSPROP: no entities selected. Select entities first.");
.push_error(crate::t!("MASSPROP: no entities selected. Select entities first.").as_ref());
} else {
for (handle, _) in &selected {
if let Some(entity) = self.tabs[i].scene.document.get_entity(*handle) {
use crate::entities::traits::EntityTypeOps;
if let Some(props) = entity.mass_props() {
self.command_line.push_output(&format!(
self.command_line.push_output(crate::tf!(
"{} Area={:.4} Perimeter={:.4} Centroid=({:.4},{:.4})",
crate::entities::names::dxf_name(entity),
props.area,
props.perimeter,
props.cx,
props.cy,
));
).as_ref());
}
}
}
@ -1003,7 +1001,7 @@ impl OpenCADStudio {
}
};
if handles.is_empty() {
self.command_line.push_error("FLATTEN: no entities.");
self.command_line.push_error(crate::t!("FLATTEN: no entities.").as_ref());
} else {
self.push_undo_snapshot(i, "FLATTEN");
for h in &handles {
@ -1012,10 +1010,10 @@ impl OpenCADStudio {
}
}
self.tabs[i].dirty = true;
self.command_line.push_output(&format!(
self.command_line.push_output(crate::tf!(
"FLATTEN: {} entity(ies) moved to Z=0.",
handles.len()
));
).as_ref());
self.refresh_properties();
}
}
@ -1054,17 +1052,17 @@ impl OpenCADStudio {
if prop.is_empty() {
self.command_line
.push_info("Usage: QSELECT TYPE|LAYER|COLOR|LINETYPE <value>");
.push_info(crate::t!("Usage: QSELECT TYPE|LAYER|COLOR|LINETYPE <value>").as_ref());
} else if matched.is_empty() {
self.command_line
.push_output("QSELECT: no matching entities.");
.push_output(crate::t!("QSELECT: no matching entities.").as_ref());
} else {
self.tabs[i].scene.deselect_all();
for h in &matched {
self.tabs[i].scene.select_entity(*h, false);
}
self.command_line
.push_output(&format!("QSELECT: {} entity(ies) selected.", matched.len()));
.push_output(crate::tf!("QSELECT: {} entity(ies) selected.", matched.len()).as_ref());
self.refresh_properties();
}
}
@ -1102,10 +1100,10 @@ impl OpenCADStudio {
}
let total: usize = counts.values().sum();
for (k, n) in &counts {
self.command_line.push_output(&format!(" {k}: {n}"));
self.command_line.push_output(crate::tf!(" {k}: {n}").as_ref());
}
self.command_line
.push_output(&format!("COUNT: {total} entity(ies) total."));
.push_output(crate::tf!("COUNT: {total} entity(ies) total.").as_ref());
}
"DATAEXTRACTION" | "EATTEXT" | "ATTEXT" => {
@ -1142,7 +1140,7 @@ impl OpenCADStudio {
};
if search.is_empty() {
self.command_line.push_error("FIND: specify search text.");
self.command_line.push_error(crate::t!("FIND: specify search text.").as_ref());
} else {
let search_lc = search.to_lowercase();
let mut count = 0usize;
@ -1170,7 +1168,7 @@ impl OpenCADStudio {
};
if targets.is_empty() {
self.command_line
.push_output(&format!("FIND: \"{}\" not found.", search));
.push_output(crate::tf!("FIND: \"{}\" not found.", search).as_ref());
} else {
self.push_undo_snapshot(i, "FIND/REPLACE");
for h in &targets {
@ -1182,34 +1180,34 @@ impl OpenCADStudio {
}
}
self.tabs[i].dirty = true;
self.command_line.push_output(&format!(
self.command_line.push_output(crate::tf!(
"FIND/REPLACE: replaced {} occurrence(s) of \"{}\" → \"{}\".",
count, search, rep
));
).as_ref());
self.refresh_properties();
}
} else {
// List mode
if handles.is_empty() {
self.command_line
.push_output(&format!("FIND: \"{}\" not found.", search));
.push_output(crate::tf!("FIND: \"{}\" not found.", search).as_ref());
} else {
for h in &handles {
if let Some(e) = self.tabs[i].scene.document.get_entity(*h) {
use crate::entities::traits::EntityTypeOps;
let txt = e.text_content().unwrap_or_default();
self.command_line.push_output(&format!(
self.command_line.push_output(crate::tf!(
" Handle {:X}: \"{}\"",
h.value(),
txt
));
).as_ref());
}
}
self.command_line.push_output(&format!(
self.command_line.push_output(crate::tf!(
"FIND: {} match(es) for \"{}\".",
handles.len(),
search
));
).as_ref());
}
}
}
@ -1309,12 +1307,12 @@ impl OpenCADStudio {
let Some((verb, kind, layer, color, linetype, lt_scale, lw, template_dimstyle)) = info
else {
self.command_line
.push_error("ADDSELECTED: selected object not found.");
.push_error(crate::t!("ADDSELECTED: selected object not found.").as_ref());
return Task::none();
};
let Some(verb) = verb else {
self.command_line
.push_error(&format!("ADDSELECTED: creating a new {kind} is not supported."));
.push_error(crate::tf!("ADDSELECTED: creating a new {kind} is not supported.").as_ref());
return Task::none();
};
@ -1399,9 +1397,9 @@ impl OpenCADStudio {
self.ribbon.active_lineweight = lw;
self.refresh_properties();
self.command_line.push_output(&format!(
self.command_line.push_output(crate::tf!(
"Add Selected: drawing a new {kind} on layer \"{layer}\"."
));
).as_ref());
// Launch the matching draw command (installs its interactive step).
self.dispatch_command(verb)
}

View file

@ -36,15 +36,15 @@ impl OpenCADStudio {
})
.collect();
self.command_line
.push_output(&format!("Layers: {}", info.join(", ")));
.push_output(crate::tf!("Layers: {}", info.join(", ")).as_ref());
}
"NEW" | "N" => {
let name = parts.get(1).map(|s| s.trim()).unwrap_or("").to_string();
if name.is_empty() {
self.command_line.push_error("Usage: LAYER NEW <name>");
self.command_line.push_error(crate::t!("Usage: LAYER NEW <name>").as_ref());
} else if self.tabs[i].scene.document.layers.contains(&name) {
self.command_line
.push_error(&format!("LAYER: '{}' already exists.", name));
.push_error(crate::tf!("LAYER: '{}' already exists.", name).as_ref());
} else {
let mut layer = Layer::new(&name);
// Allocate a unique handle so the layer survives a
@ -54,7 +54,7 @@ impl OpenCADStudio {
self.push_undo_snapshot(i, "LAYER NEW");
self.tabs[i].dirty = true;
self.command_line
.push_output(&format!("LAYER: '{}' created.", name));
.push_output(crate::tf!("LAYER: '{}' created.", name).as_ref());
}
}
"ON" => {
@ -66,7 +66,7 @@ impl OpenCADStudio {
}
self.push_undo_snapshot(i, "LAYER ON");
self.tabs[i].dirty = true;
self.command_line.push_output("LAYER: layers turned on.");
self.command_line.push_output(crate::t!("LAYER: layers turned on.").as_ref());
}
"OFF" => {
for name in &parts[1..] {
@ -76,7 +76,7 @@ impl OpenCADStudio {
}
self.push_undo_snapshot(i, "LAYER OFF");
self.tabs[i].dirty = true;
self.command_line.push_output("LAYER: layers turned off.");
self.command_line.push_output(crate::t!("LAYER: layers turned off.").as_ref());
}
"FREEZE" | "FR" => {
for name in &parts[1..] {
@ -86,7 +86,7 @@ impl OpenCADStudio {
}
self.push_undo_snapshot(i, "LAYER FREEZE");
self.tabs[i].dirty = true;
self.command_line.push_output("LAYER: layers frozen.");
self.command_line.push_output(crate::t!("LAYER: layers frozen.").as_ref());
}
"THAW" | "TH" => {
for name in &parts[1..] {
@ -96,7 +96,7 @@ impl OpenCADStudio {
}
self.push_undo_snapshot(i, "LAYER THAW");
self.tabs[i].dirty = true;
self.command_line.push_output("LAYER: layers thawed.");
self.command_line.push_output(crate::t!("LAYER: layers thawed.").as_ref());
}
"LOCK" | "LO" => {
for name in &parts[1..] {
@ -106,7 +106,7 @@ impl OpenCADStudio {
}
self.push_undo_snapshot(i, "LAYER LOCK");
self.tabs[i].dirty = true;
self.command_line.push_output("LAYER: layers locked.");
self.command_line.push_output(crate::t!("LAYER: layers locked.").as_ref());
}
"UNLOCK" | "UL" => {
for name in &parts[1..] {
@ -116,7 +116,7 @@ impl OpenCADStudio {
}
self.push_undo_snapshot(i, "LAYER UNLOCK");
self.tabs[i].dirty = true;
self.command_line.push_output("LAYER: layers unlocked.");
self.command_line.push_output(crate::t!("LAYER: layers unlocked.").as_ref());
}
"COLOR" | "C" => {
// LAYER COLOR <name> <aci_index>
@ -137,17 +137,17 @@ impl OpenCADStudio {
.invalidate_layer_dependencies(std::slice::from_ref(
&layer_name,
));
self.command_line.push_output(&format!(
self.command_line.push_output(crate::tf!(
"LAYER: '{}' color set to ACI {}.",
layer_name, idx
));
).as_ref());
} else {
self.command_line
.push_error(&format!("LAYER: '{}' not found.", layer_name));
.push_error(crate::tf!("LAYER: '{}' not found.", layer_name).as_ref());
}
} else {
self.command_line
.push_error("Usage: LAYER COLOR <name> <aci_index>");
.push_error(crate::t!("Usage: LAYER COLOR <name> <aci_index>").as_ref());
}
}
"SET" | "S" | "CURRENT" => {
@ -155,15 +155,15 @@ impl OpenCADStudio {
if self.tabs[i].scene.document.layers.contains(&name) {
self.tabs[i].layers.current_layer = name.clone();
self.command_line
.push_output(&format!("LAYER: current layer set to '{}'.", name));
.push_output(crate::tf!("LAYER: current layer set to '{}'.", name).as_ref());
} else {
self.command_line
.push_error(&format!("LAYER: '{}' not found.", name));
.push_error(crate::tf!("LAYER: '{}' not found.", name).as_ref());
}
}
_ => {
self.command_line.push_info(
"Usage: LAYER LIST | NEW <name> | ON/OFF/FREEZE/THAW/LOCK/UNLOCK <name> | COLOR <name> <aci> | SET <name>"
crate::t!("Usage: LAYER LIST | NEW <name> | ON/OFF/FREEZE/THAW/LOCK/UNLOCK <name> | COLOR <name> <aci> | SET <name>").as_ref()
);
}
}
@ -202,22 +202,22 @@ impl OpenCADStudio {
.map(|u| u.name.clone())
.collect();
if names.is_empty() {
self.command_line.push_output(&format!(
self.command_line.push_output(crate::tf!(
"Active UCS: {} | No named UCSs defined.",
active_name
));
).as_ref());
} else {
self.command_line.push_output(&format!(
self.command_line.push_output(crate::tf!(
"Active UCS: {} | Named: {}",
active_name,
names.join(", ")
));
).as_ref());
}
}
"SAVE" | "S" => {
let name = parts.get(2).map(|s| s.trim()).unwrap_or("").to_string();
if name.is_empty() {
self.command_line.push_error("Usage: UCS SAVE <name>");
self.command_line.push_error(crate::t!("Usage: UCS SAVE <name>").as_ref());
} else {
// Save the current active UCS under this name.
let ucs = match &self.tabs[i].active_ucs {
@ -231,27 +231,27 @@ impl OpenCADStudio {
self.tabs[i].scene.document.ucss.add_or_replace(ucs);
self.tabs[i].dirty = true;
self.command_line
.push_output(&format!("UCS '{}' saved.", name));
.push_output(crate::tf!("UCS '{}' saved.", name).as_ref());
}
}
"DELETE" | "DEL" | "D" => {
let name = parts.get(2).map(|s| s.trim()).unwrap_or("").to_string();
if name.is_empty() {
self.command_line.push_error("Usage: UCS DELETE <name>");
self.command_line.push_error(crate::t!("Usage: UCS DELETE <name>").as_ref());
} else if self.tabs[i].scene.document.ucss.remove(&name).is_some() {
self.tabs[i].dirty = true;
self.command_line
.push_output(&format!("UCS '{}' deleted.", name));
.push_output(crate::tf!("UCS '{}' deleted.", name).as_ref());
} else {
self.command_line
.push_error(&format!("UCS '{}' not found.", name));
.push_error(crate::tf!("UCS '{}' not found.", name).as_ref());
}
}
"W" | "WORLD" => {
self.tabs[i].active_ucs = None;
active_changed = true;
self.command_line
.push_output("UCS reset to World Coordinate System.");
.push_output(crate::t!("UCS reset to World Coordinate System.").as_ref());
}
// UCS ORIGIN x,y,z — shift the active UCS origin, keep axes
"ORIGIN" | "O" => {
@ -274,12 +274,12 @@ impl OpenCADStudio {
wcs_origin.z as f64,
);
active_changed = true;
self.command_line.push_output(&format!(
self.command_line.push_output(crate::tf!(
"UCS origin set to ({:.4}, {:.4}, {:.4}).",
wcs_origin.x, wcs_origin.y, wcs_origin.z
));
).as_ref());
} else {
self.command_line.push_error("Usage: UCS ORIGIN x,y,z");
self.command_line.push_error(crate::t!("Usage: UCS ORIGIN x,y,z").as_ref());
}
}
// UCS Z angle — rotate active UCS around its Z axis by degrees
@ -318,9 +318,9 @@ impl OpenCADStudio {
self.tabs[i].active_ucs = Some(new_ucs);
active_changed = true;
self.command_line
.push_output(&format!("UCS rotated {:.2}° around Z.", angle_deg));
.push_output(crate::tf!("UCS rotated {:.2}° around Z.", angle_deg).as_ref());
} else {
self.command_line.push_error("Usage: UCS Z <angle_degrees>");
self.command_line.push_error(crate::t!("Usage: UCS Z <angle_degrees>").as_ref());
}
}
// UCS X angle — rotate around current UCS X axis
@ -346,9 +346,9 @@ impl OpenCADStudio {
ucs.y_axis = Vector3::new(ny.x as f64, ny.y as f64, ny.z as f64);
active_changed = true;
self.command_line
.push_output(&format!("UCS rotated {:.2}° around X.", angle_deg));
.push_output(crate::tf!("UCS rotated {:.2}° around X.", angle_deg).as_ref());
} else {
self.command_line.push_error("Usage: UCS X <angle_degrees>");
self.command_line.push_error(crate::t!("Usage: UCS X <angle_degrees>").as_ref());
}
}
// UCS Y angle — rotate around current UCS Y axis
@ -374,9 +374,9 @@ impl OpenCADStudio {
ucs.x_axis = Vector3::new(nx.x as f64, nx.y as f64, nx.z as f64);
active_changed = true;
self.command_line
.push_output(&format!("UCS rotated {:.2}° around Y.", angle_deg));
.push_output(crate::tf!("UCS rotated {:.2}° around Y.", angle_deg).as_ref());
} else {
self.command_line.push_error("Usage: UCS Y <angle_degrees>");
self.command_line.push_error(crate::t!("Usage: UCS Y <angle_degrees>").as_ref());
}
}
_ => {
@ -386,12 +386,12 @@ impl OpenCADStudio {
self.tabs[i].active_ucs = Some(named);
active_changed = true;
self.command_line
.push_output(&format!("UCS '{}' activated.", name));
.push_output(crate::tf!("UCS '{}' activated.", name).as_ref());
} else {
self.command_line.push_error(&format!(
self.command_line.push_error(crate::tf!(
"UCS '{}' not found. Usage: UCS LIST | SAVE <name> | DELETE <name> | W | ORIGIN x,y,z | X/Y/Z <angle>",
name
));
).as_ref());
}
}
}
@ -429,16 +429,16 @@ impl OpenCADStudio {
"" | "CURRENT" | "C" => {
let r = self.tabs[i].scene.viewcube_ucs_mat();
self.plan_snap(i, r);
self.command_line.push_output("PLAN: current UCS plan view.");
self.command_line.push_output(crate::t!("PLAN: current UCS plan view.").as_ref());
}
"WORLD" | "W" => {
self.plan_snap(i, glam::Mat4::IDENTITY);
self.command_line.push_output("PLAN: world plan view.");
self.command_line.push_output(crate::t!("PLAN: world plan view.").as_ref());
}
"UCS" | "U" => {
let name = parts.get(2).map(|s| s.trim()).unwrap_or("");
if name.is_empty() {
self.command_line.push_info("Usage: PLAN UCS <name>");
self.command_line.push_info(crate::t!("Usage: PLAN UCS <name>").as_ref());
} else {
let ucs = self.tabs[i]
.scene
@ -452,20 +452,20 @@ impl OpenCADStudio {
let r = crate::app::helpers::UcsXform::from_ucs(&u)
.rotation_mat();
self.plan_snap(i, r);
self.command_line.push_output(&format!(
self.command_line.push_output(crate::tf!(
"PLAN: plan view of UCS '{}'.",
u.name
));
).as_ref());
}
None => self
.command_line
.push_error(&format!("UCS '{name}' not found.")),
.push_error(crate::tf!("UCS '{name}' not found.").as_ref()),
}
}
}
_ => self
.command_line
.push_info("Usage: PLAN [CURRENT / UCS <name> / WORLD]"),
.push_info(crate::t!("Usage: PLAN [CURRENT / UCS <name> / WORLD]").as_ref()),
}
}
@ -497,50 +497,50 @@ impl OpenCADStudio {
.map(|v| v.name.clone())
.collect();
if views.is_empty() {
self.command_line.push_output("No named views saved.");
self.command_line.push_output(crate::t!("No named views saved.").as_ref());
} else {
self.command_line
.push_output(&format!("Named views: {}", views.join(", ")));
.push_output(crate::tf!("Named views: {}", views.join(", ")).as_ref());
}
}
"SAVE" | "S" => {
let name = parts.get(2).map(|s| s.trim()).unwrap_or("").to_string();
if name.is_empty() {
self.command_line.push_error("Usage: VIEW SAVE <name>");
self.command_line.push_error(crate::t!("Usage: VIEW SAVE <name>").as_ref());
} else {
let new_view = self.tabs[i].scene.current_as_named_view(&name);
self.tabs[i].scene.document.views.add_or_replace(new_view);
self.command_line
.push_output(&format!("View '{}' saved.", name));
.push_output(crate::tf!("View '{}' saved.", name).as_ref());
}
}
"DELETE" | "DEL" | "D" => {
let name = parts.get(2).map(|s| s.trim()).unwrap_or("").to_string();
if name.is_empty() {
self.command_line.push_error("Usage: VIEW DELETE <name>");
self.command_line.push_error(crate::t!("Usage: VIEW DELETE <name>").as_ref());
} else {
if self.tabs[i].scene.document.views.remove(&name).is_some() {
self.command_line
.push_output(&format!("View '{}' deleted.", name));
.push_output(crate::tf!("View '{}' deleted.", name).as_ref());
} else {
self.command_line
.push_error(&format!("View '{}' not found.", name));
.push_error(crate::tf!("View '{}' not found.", name).as_ref());
}
}
}
"RESTORE" | "R" => {
let name = parts.get(2).map(|s| s.trim()).unwrap_or("").to_string();
if name.is_empty() {
self.command_line.push_error("Usage: VIEW RESTORE <name>");
self.command_line.push_error(crate::t!("Usage: VIEW RESTORE <name>").as_ref());
} else {
let found = self.tabs[i].scene.document.views.get(&name).cloned();
if let Some(v) = found {
self.tabs[i].scene.restore_named_view(&v);
self.command_line
.push_output(&format!("View '{}' restored.", v.name));
.push_output(crate::tf!("View '{}' restored.", v.name).as_ref());
} else {
self.command_line
.push_error(&format!("View '{}' not found.", name));
.push_error(crate::tf!("View '{}' not found.", name).as_ref());
}
}
}
@ -573,10 +573,10 @@ impl OpenCADStudio {
if let Some(v) = found {
self.tabs[i].scene.restore_named_view(&v);
self.command_line
.push_output(&format!("View '{}' restored.", v.name));
.push_output(crate::tf!("View '{}' restored.", v.name).as_ref());
} else {
self.command_line.push_error(
"Usage: VIEW LIST | VIEW SAVE <name> | VIEW RESTORE <name> | VIEW DELETE <name>"
crate::t!("Usage: VIEW LIST | VIEW SAVE <name> | VIEW RESTORE <name> | VIEW DELETE <name>").as_ref()
);
}
}
@ -614,16 +614,16 @@ impl OpenCADStudio {
})
.collect();
if styles.is_empty() {
self.command_line.push_output("No table styles.");
self.command_line.push_output(crate::t!("No table styles.").as_ref());
} else {
self.command_line
.push_output(&format!("TableStyles:\n {}", styles.join("\n ")));
.push_output(crate::tf!("TableStyles:\n {}", styles.join("\n ")).as_ref());
}
}
"NEW" | "N" => {
let name = parts.get(1).copied().unwrap_or("").to_string();
if name.is_empty() {
self.command_line.push_error("Usage: TABLESTYLE NEW <name>");
self.command_line.push_error(crate::t!("Usage: TABLESTYLE NEW <name>").as_ref());
} else {
let doc = &self.tabs[i].scene.document;
let exists = doc.objects.values().any(|o| {
@ -631,7 +631,7 @@ impl OpenCADStudio {
});
if exists {
self.command_line
.push_error(&format!("TABLESTYLE: '{}' already exists.", name));
.push_error(crate::tf!("TABLESTYLE: '{}' already exists.", name).as_ref());
} else {
self.push_undo_snapshot(i, "TABLESTYLE NEW");
let mut style = TableStyle::standard();
@ -647,13 +647,13 @@ impl OpenCADStudio {
.insert(nh, ObjectType::TableStyle(style));
self.tabs[i].dirty = true;
self.command_line
.push_output(&format!("TABLESTYLE: '{}' created.", name));
.push_output(crate::tf!("TABLESTYLE: '{}' created.", name).as_ref());
}
}
}
_ => {
self.command_line
.push_error("Usage: TABLESTYLE [LIST|NEW <name>]");
.push_error(crate::t!("Usage: TABLESTYLE [LIST|NEW <name>]").as_ref());
}
}
}
@ -693,16 +693,16 @@ impl OpenCADStudio {
})
.collect();
if styles.is_empty() {
self.command_line.push_output("No multiline styles.");
self.command_line.push_output(crate::t!("No multiline styles.").as_ref());
} else {
self.command_line
.push_output(&format!("MLineStyles:\n {}", styles.join("\n ")));
.push_output(crate::tf!("MLineStyles:\n {}", styles.join("\n ")).as_ref());
}
}
"NEW" | "N" => {
let name = parts.get(1).copied().unwrap_or("").to_string();
if name.is_empty() {
self.command_line.push_error("Usage: MLSTYLE NEW <name>");
self.command_line.push_error(crate::t!("Usage: MLSTYLE NEW <name>").as_ref());
} else {
let doc = &self.tabs[i].scene.document;
let exists = doc.objects.values().any(|o| {
@ -710,7 +710,7 @@ impl OpenCADStudio {
});
if exists {
self.command_line
.push_error(&format!("MLSTYLE: '{}' already exists.", name));
.push_error(crate::tf!("MLSTYLE: '{}' already exists.", name).as_ref());
} else {
self.push_undo_snapshot(i, "MLSTYLE NEW");
let mut style = MLineStyle::standard();
@ -726,14 +726,14 @@ impl OpenCADStudio {
.insert(nh, ObjectType::MLineStyle(style));
self.tabs[i].dirty = true;
self.command_line
.push_output(&format!("MLSTYLE: '{}' created.", name));
.push_output(crate::tf!("MLSTYLE: '{}' created.", name).as_ref());
}
}
}
"SET" | "S" => {
let name = parts.get(1).copied().unwrap_or("").to_string();
if name.is_empty() {
self.command_line.push_error("Usage: MLSTYLE SET <name>");
self.command_line.push_error(crate::t!("Usage: MLSTYLE SET <name>").as_ref());
} else {
let doc = &self.tabs[i].scene.document;
let exists = doc.objects.values().any(|o| {
@ -743,13 +743,13 @@ impl OpenCADStudio {
self.push_undo_snapshot(i, "MLSTYLE SET");
self.tabs[i].scene.document.header.multiline_style = name.clone();
self.tabs[i].dirty = true;
self.command_line.push_output(&format!(
self.command_line.push_output(crate::tf!(
"MLSTYLE: current style set to '{}'.",
name
));
).as_ref());
} else {
self.command_line
.push_error(&format!("MLSTYLE: '{}' not found.", name));
.push_error(crate::tf!("MLSTYLE: '{}' not found.", name).as_ref());
}
}
}
@ -757,7 +757,7 @@ impl OpenCADStudio {
let name = parts.get(1).copied().unwrap_or("").to_string();
if name.is_empty() || name.eq_ignore_ascii_case("Standard") {
self.command_line
.push_error("Cannot delete the Standard style.");
.push_error(crate::t!("Cannot delete the Standard style.").as_ref());
} else {
let doc = &self.tabs[i].scene.document;
let handle = doc.objects.iter().find_map(|(&h, o)| {
@ -776,16 +776,16 @@ impl OpenCADStudio {
self.tabs[i].scene.document.objects.remove(&h);
self.tabs[i].dirty = true;
self.command_line
.push_output(&format!("MLSTYLE: '{}' deleted.", name));
.push_output(crate::tf!("MLSTYLE: '{}' deleted.", name).as_ref());
} else {
self.command_line
.push_error(&format!("MLSTYLE: '{}' not found.", name));
.push_error(crate::tf!("MLSTYLE: '{}' not found.", name).as_ref());
}
}
}
_ => {
self.command_line
.push_error("Usage: MLSTYLE [LIST|NEW <name>|SET <name>|DEL <name>]");
.push_error(crate::t!("Usage: MLSTYLE [LIST|NEW <name>|SET <name>|DEL <name>]").as_ref());
}
}
}
@ -813,19 +813,19 @@ impl OpenCADStudio {
.map(|s| format!("{}(txt:{:.2} asz:{:.2})", s.name, s.dimtxt, s.dimasz))
.collect();
if styles.is_empty() {
self.command_line.push_output("No dim styles defined.");
self.command_line.push_output(crate::t!("No dim styles defined.").as_ref());
} else {
self.command_line
.push_output(&format!("DimStyles: {}", styles.join(", ")));
.push_output(crate::tf!("DimStyles: {}", styles.join(", ")).as_ref());
}
}
"NEW" | "N" => {
let name = parts.get(1).map(|s| s.trim()).unwrap_or("").to_string();
if name.is_empty() {
self.command_line.push_error("Usage: DIMSTYLE NEW <name>");
self.command_line.push_error(crate::t!("Usage: DIMSTYLE NEW <name>").as_ref());
} else if self.tabs[i].scene.document.dim_styles.contains(&name) {
self.command_line
.push_error(&format!("DIMSTYLE: '{}' already exists.", name));
.push_error(crate::tf!("DIMSTYLE: '{}' already exists.", name).as_ref());
} else {
let undo = self.begin_dim_style_undo(
i,
@ -837,7 +837,7 @@ impl OpenCADStudio {
self.tabs[i].dirty = true;
self.commit_dim_style_undo(i, undo);
self.command_line
.push_output(&format!("DIMSTYLE: '{}' created.", name));
.push_output(crate::tf!("DIMSTYLE: '{}' created.", name).as_ref());
}
}
"SET" | "S" => {
@ -896,9 +896,9 @@ impl OpenCADStudio {
ds.dimfxl = val;
}
_ => {
self.command_line.push_error(&format!(
self.command_line.push_error(crate::tf!(
"DIMSTYLE: unknown property '{}'. Try: dimtxt dimasz dimdli dimexo dimexe dimgap dimscale dimlfac dimdle dimcen dimtsz", prop
));
).as_ref());
return Some(Task::none());
}
}
@ -906,16 +906,16 @@ impl OpenCADStudio {
self.tabs[i].scene
.invalidate_dim_style_dependencies(&style_name);
self.commit_dim_style_undo(i, undo);
self.command_line.push_output(&format!(
self.command_line.push_output(crate::tf!(
"DIMSTYLE: '{style_name}'.{prop} = {val:.3}"
));
).as_ref());
} else {
self.command_line
.push_error(&format!("DIMSTYLE: '{}' not found.", style_name));
.push_error(crate::tf!("DIMSTYLE: '{}' not found.", style_name).as_ref());
}
} else {
self.command_line
.push_error("Usage: DIMSTYLE SET <name> <property> <value>");
.push_error(crate::t!("Usage: DIMSTYLE SET <name> <property> <value>").as_ref());
}
}
_ => {
@ -956,28 +956,28 @@ impl OpenCADStudio {
let current = &self.tabs[i].active_mleader_style;
if styles.is_empty() {
self.command_line
.push_output(&format!("MLeader styles: (none) active: {current}"));
.push_output(crate::tf!("MLeader styles: (none) active: {current}").as_ref());
} else {
self.command_line.push_output(&format!(
self.command_line.push_output(crate::tf!(
"MLeader styles: {} active: {current}",
styles.join(", ")
));
).as_ref());
}
}
"NEW" | "N" => {
let name = parts.get(1).map(|s| s.trim()).unwrap_or("").to_string();
if name.is_empty() {
self.command_line
.push_error("Usage: MLEADERSTYLE NEW <name>");
.push_error(crate::t!("Usage: MLEADERSTYLE NEW <name>").as_ref());
} else {
let already_exists = self.tabs[i].scene.document.objects.values().any(
|o| matches!(o, ObjectType::MultiLeaderStyle(s) if s.name == name),
);
if already_exists {
self.command_line.push_error(&format!(
self.command_line.push_error(crate::tf!(
"MLEADERSTYLE: '{}' already exists.",
name
));
).as_ref());
} else {
let handle = self.tabs[i].scene.document.allocate_handle();
let mut style = MultiLeaderStyle::new(&name);
@ -990,7 +990,7 @@ impl OpenCADStudio {
self.push_undo_snapshot(i, "MLEADERSTYLE NEW");
self.tabs[i].dirty = true;
self.command_line
.push_output(&format!("MLEADERSTYLE: '{}' created.", name));
.push_output(crate::tf!("MLEADERSTYLE: '{}' created.", name).as_ref());
}
}
}
@ -1032,52 +1032,52 @@ impl OpenCADStudio {
s.landing_gap = val;
}
_ => {
self.command_line.push_error(&format!(
self.command_line.push_error(crate::tf!(
"MLEADERSTYLE: unknown property '{}'. Try: text_height arrowhead_size landing_distance landing_gap", prop
));
).as_ref());
return Some(Task::none());
}
}
self.push_undo_snapshot(i, "MLEADERSTYLE SET");
self.tabs[i].dirty = true;
self.command_line.push_output(&format!(
self.command_line.push_output(crate::tf!(
"MLEADERSTYLE: '{style_name}'.{prop} = {val:.3}"
));
).as_ref());
} else {
self.command_line.push_error(&format!(
self.command_line.push_error(crate::tf!(
"MLEADERSTYLE: '{}' not found.",
style_name
));
).as_ref());
}
} else {
self.command_line
.push_error("Usage: MLEADERSTYLE SET <name> <property> <value>");
.push_error(crate::t!("Usage: MLEADERSTYLE SET <name> <property> <value>").as_ref());
}
}
"CURRENT" | "C" | "ACTIVE" => {
let name = parts.get(1).map(|s| s.trim()).unwrap_or("").to_string();
if name.is_empty() {
self.command_line.push_output(&format!(
self.command_line.push_output(crate::tf!(
"Current MLeader style: {}",
self.tabs[i].active_mleader_style
));
).as_ref());
} else {
let exists = name == "Standard" || self.tabs[i].scene.document.objects.values()
.any(|o| matches!(o, ObjectType::MultiLeaderStyle(s) if s.name == name));
if exists {
self.tabs[i].active_mleader_style = name.clone();
self.command_line.push_output(&format!(
self.command_line.push_output(crate::tf!(
"MLEADERSTYLE: current style set to '{name}'."
));
).as_ref());
} else {
self.command_line
.push_error(&format!("MLEADERSTYLE: '{}' not found.", name));
.push_error(crate::tf!("MLEADERSTYLE: '{}' not found.", name).as_ref());
}
}
}
_ => {
self.command_line.push_info(
"Usage: MLEADERSTYLE LIST | NEW <name> | SET <name> <prop> <val> | CURRENT [<name>]"
crate::t!("Usage: MLEADERSTYLE LIST | NEW <name> | SET <name> <prop> <val> | CURRENT [<name>]").as_ref()
);
}
}
@ -1117,10 +1117,10 @@ impl OpenCADStudio {
})
.collect();
if styles.is_empty() {
self.command_line.push_output("No text styles defined.");
self.command_line.push_output(crate::t!("No text styles defined.").as_ref());
} else {
self.command_line
.push_output(&format!("Text styles: {}", styles.join(" | ")));
.push_output(crate::tf!("Text styles: {}", styles.join(" | ")).as_ref());
}
}
"SET" | "S" => {
@ -1128,20 +1128,20 @@ impl OpenCADStudio {
let name = parts.get(1).map(|s| s.trim()).unwrap_or("");
if self.tabs[i].scene.document.text_styles.get(name).is_some() {
self.command_line
.push_output(&format!("{prefix}: active style set to '{name}'."));
.push_output(crate::tf!("{prefix}: active style set to '{name}'.").as_ref());
} else {
self.command_line
.push_error(&format!("{prefix}: style '{name}' not found."));
.push_error(crate::tf!("{prefix}: style '{name}' not found.").as_ref());
}
}
"NEW" | "N" => {
let name = parts.get(1).map(|s| s.trim()).unwrap_or("").to_string();
if name.is_empty() {
self.command_line
.push_error(&format!("Usage: {prefix} NEW <name>"));
.push_error(crate::tf!("Usage: {prefix} NEW <name>").as_ref());
} else if self.tabs[i].scene.document.text_styles.contains(&name) {
self.command_line
.push_error(&format!("{prefix}: style '{name}' already exists."));
.push_error(crate::tf!("{prefix}: style '{name}' already exists.").as_ref());
} else {
let undo = self.begin_text_style_undo(
i,
@ -1153,7 +1153,7 @@ impl OpenCADStudio {
self.tabs[i].dirty = true;
self.commit_text_style_undo(i, undo);
self.command_line
.push_output(&format!("{prefix}: style '{name}' created."));
.push_output(crate::tf!("{prefix}: style '{name}' created.").as_ref());
}
}
"FONT" | "F" => {
@ -1162,7 +1162,7 @@ impl OpenCADStudio {
let font = parts.get(2).map(|s| s.trim()).unwrap_or("").to_string();
if style_name.is_empty() || font.is_empty() {
self.command_line
.push_error(&format!("Usage: {prefix} FONT <style> <font_file>"));
.push_error(crate::tf!("Usage: {prefix} FONT <style> <font_file>").as_ref());
} else {
let undo = self.begin_text_style_undo(
i,
@ -1178,12 +1178,12 @@ impl OpenCADStudio {
.scene
.invalidate_text_style_dependencies(&style_name);
self.commit_text_style_undo(i, undo);
self.command_line.push_output(&format!(
self.command_line.push_output(crate::tf!(
"{prefix}: '{style_name}' font set to '{font}'."
));
).as_ref());
} else {
self.command_line
.push_error(&format!("{prefix}: style '{style_name}' not found."));
.push_error(crate::tf!("{prefix}: style '{style_name}' not found.").as_ref());
}
}
}
@ -1206,17 +1206,17 @@ impl OpenCADStudio {
.scene
.invalidate_text_style_dependencies(&style_name);
self.commit_text_style_undo(i, undo);
self.command_line.push_output(&format!(
self.command_line.push_output(crate::tf!(
"{prefix}: '{style_name}' width factor set to {factor:.3}."
));
).as_ref());
} else {
self.command_line.push_error(&format!(
self.command_line.push_error(crate::tf!(
"{prefix}: style '{style_name}' not found."
));
).as_ref());
}
} else {
self.command_line
.push_error(&format!("Usage: {prefix} WIDTH <style> <factor>"));
.push_error(crate::tf!("Usage: {prefix} WIDTH <style> <factor>").as_ref());
}
}
"OBLIQUE" => {
@ -1238,24 +1238,24 @@ impl OpenCADStudio {
.scene
.invalidate_text_style_dependencies(&style_name);
self.commit_text_style_undo(i, undo);
self.command_line.push_output(&format!(
self.command_line.push_output(crate::tf!(
"{prefix}: '{style_name}' oblique angle set to {deg:.1}°."
));
).as_ref());
} else {
self.command_line.push_error(&format!(
self.command_line.push_error(crate::tf!(
"{prefix}: style '{style_name}' not found."
));
).as_ref());
}
} else {
self.command_line.push_error(&format!(
self.command_line.push_error(crate::tf!(
"Usage: {prefix} OBLIQUE <style> <angle_degrees>"
));
).as_ref());
}
}
_ => {
self.command_line.push_info(&format!(
self.command_line.push_info(crate::tf!(
"Usage: {prefix} LIST | NEW <name> | FONT <style> <file> | WIDTH <style> <factor> | OBLIQUE <style> <angle>"
));
).as_ref());
}
}
}

View file

@ -37,7 +37,7 @@ impl OpenCADStudio {
self.tabs[i].dirty = true;
self.commit_layer_undo(i, undo);
self.refresh_layer_panel();
self.command_line.push_info("Layer(s) turned off.");
self.command_line.push_info(crate::t!("Layer(s) turned off.").as_ref());
}
}
@ -74,7 +74,7 @@ impl OpenCADStudio {
self.tabs[i].dirty = true;
self.commit_layer_undo(i, undo);
self.refresh_layer_panel();
self.command_line.push_info("Layer(s) frozen.");
self.command_line.push_info(crate::t!("Layer(s) frozen.").as_ref());
}
}
@ -88,7 +88,7 @@ impl OpenCADStudio {
cmd if cmd.starts_with("LAYDEL ") => {
let name = cmd.trim_start_matches("LAYDEL").trim();
if name.is_empty() {
self.command_line.push_info("Usage: LAYDEL <layer name>");
self.command_line.push_info(crate::t!("Usage: LAYDEL <layer name>").as_ref());
return Some(Task::none());
}
let resolved = self.tabs[i]
@ -100,12 +100,12 @@ impl OpenCADStudio {
.map(|s| s.to_string());
let Some(layer) = resolved else {
self.command_line
.push_error(&format!("LAYDEL: no layer named \"{name}\"."));
.push_error(crate::tf!("LAYDEL: no layer named \"{name}\".").as_ref());
return Some(Task::none());
};
if layer == "0" {
self.command_line
.push_error("LAYDEL: layer \"0\" cannot be deleted.");
.push_error(crate::t!("LAYDEL: layer \"0\" cannot be deleted.").as_ref());
return Some(Task::none());
}
if layer.eq_ignore_ascii_case(&self.tabs[i].active_layer) {
@ -130,9 +130,9 @@ impl OpenCADStudio {
self.tabs[i].scene.bump_geometry();
self.tabs[i].dirty = true;
self.refresh_layer_panel();
self.command_line.push_output(&format!(
self.command_line.push_output(crate::tf!(
"LAYDEL: deleted layer \"{layer}\" and {n} object(s)."
));
).as_ref());
}
// LAYMRG <source> <target> — move every object from <source> onto
@ -152,7 +152,7 @@ impl OpenCADStudio {
let parts: Vec<&str> = rest.split_whitespace().collect();
if parts.len() != 2 {
self.command_line
.push_info("Usage: LAYMRG <source layer> <target layer>");
.push_info(crate::t!("Usage: LAYMRG <source layer> <target layer>").as_ref());
return Some(Task::none());
}
let keys: Vec<String> = self.tabs[i]
@ -172,17 +172,17 @@ impl OpenCADStudio {
.cloned();
let (Some(src), Some(dst)) = (src, dst) else {
self.command_line
.push_error("LAYMRG: source and target layers must both exist.");
.push_error(crate::t!("LAYMRG: source and target layers must both exist.").as_ref());
return Some(Task::none());
};
if src == dst {
self.command_line
.push_error("LAYMRG: source and target are the same layer.");
.push_error(crate::t!("LAYMRG: source and target are the same layer.").as_ref());
return Some(Task::none());
}
if src == "0" {
self.command_line
.push_error("LAYMRG: layer \"0\" cannot be merged away.");
.push_error(crate::t!("LAYMRG: layer \"0\" cannot be merged away.").as_ref());
return Some(Task::none());
}
if src.eq_ignore_ascii_case(&self.tabs[i].active_layer) {
@ -206,9 +206,9 @@ impl OpenCADStudio {
.invalidate_layer_dependencies(std::slice::from_ref(&dst));
self.tabs[i].dirty = true;
self.refresh_layer_panel();
self.command_line.push_output(&format!(
self.command_line.push_output(crate::tf!(
"LAYMRG: merged \"{src}\" into \"{dst}\" ({moved} object(s))."
));
).as_ref());
}
// LAYERSTATE — save / restore named snapshots of all layer states
@ -241,12 +241,12 @@ impl OpenCADStudio {
states.iter().map(|state| state.name.as_str()).collect();
names.sort_unstable();
self.command_line
.push_output(&format!("Saved layer states: {}", names.join(", ")));
.push_output(crate::tf!("Saved layer states: {}", names.join(", ")).as_ref());
}
}
"SAVE" | "S" => {
if arg.is_empty() {
self.command_line.push_info("Usage: LAYERSTATE SAVE <name>");
self.command_line.push_info(crate::t!("Usage: LAYERSTATE SAVE <name>").as_ref());
} else {
let description = self.tabs[i]
.scene
@ -261,17 +261,17 @@ impl OpenCADStudio {
.capture_layer_state(arg, description);
self.tabs[i].dirty = true;
self.command_line
.push_output(&format!("LAYERSTATE: saved \"{arg}\"."));
.push_output(crate::tf!("LAYERSTATE: saved \"{arg}\".").as_ref());
}
}
"RESTORE" | "R" => {
if arg.is_empty() {
self.command_line
.push_info("Usage: LAYERSTATE RESTORE <name>");
.push_info(crate::t!("Usage: LAYERSTATE RESTORE <name>").as_ref());
} else if self.tabs[i].scene.document.layer_state(arg).is_none() {
self.command_line.push_error(&format!(
self.command_line.push_error(crate::tf!(
"LAYERSTATE: no saved state named \"{arg}\"."
));
).as_ref());
} else {
let names: Vec<String> = self.tabs[i]
.scene
@ -295,30 +295,30 @@ impl OpenCADStudio {
self.tabs[i].scene.invalidate_layer_dependencies(&names);
self.tabs[i].dirty = true;
self.refresh_layer_panel();
self.command_line.push_output(&format!(
self.command_line.push_output(crate::tf!(
"LAYERSTATE: restored \"{arg}\" ({n} layer(s))."
));
).as_ref());
}
}
"DELETE" | "D" => {
if arg.is_empty() {
self.command_line
.push_info("Usage: LAYERSTATE DELETE <name>");
.push_info(crate::t!("Usage: LAYERSTATE DELETE <name>").as_ref());
} else if self.tabs[i].scene.document.layer_state(arg).is_none() {
self.command_line.push_error(&format!(
self.command_line.push_error(crate::tf!(
"LAYERSTATE: no saved state named \"{arg}\"."
));
).as_ref());
} else {
self.push_undo_snapshot(i, "LAYERSTATE DELETE");
self.tabs[i].scene.document.delete_layer_state(arg);
self.tabs[i].dirty = true;
self.command_line
.push_output(&format!("LAYERSTATE: deleted \"{arg}\"."));
.push_output(crate::tf!("LAYERSTATE: deleted \"{arg}\".").as_ref());
}
}
_ => {
self.command_line
.push_info("Usage: LAYERSTATE SAVE|RESTORE|DELETE <name> | ? (list)");
.push_info(crate::t!("Usage: LAYERSTATE SAVE|RESTORE|DELETE <name> | ? (list)").as_ref());
}
}
}
@ -353,7 +353,7 @@ impl OpenCADStudio {
self.tabs[i].dirty = true;
self.commit_layer_undo(i, undo);
self.refresh_layer_panel();
self.command_line.push_info("Layer(s) locked.");
self.command_line.push_info(crate::t!("Layer(s) locked.").as_ref());
}
}
@ -385,7 +385,7 @@ impl OpenCADStudio {
self.tabs[i].layers.current_layer = layer.clone();
self.tabs[i].dirty = true;
self.command_line
.push_info(&format!("Current layer set to \"{layer}\"."));
.push_info(crate::tf!("Current layer set to \"{layer}\".").as_ref());
self.refresh_layer_panel();
}
}
@ -408,7 +408,7 @@ impl OpenCADStudio {
self.tabs[i].dirty = true;
self.commit_layer_undo(i, undo);
self.refresh_layer_panel();
self.command_line.push_info("All layers turned on.");
self.command_line.push_info(crate::t!("All layers turned on.").as_ref());
}
"LAYTHW" => {
@ -429,7 +429,7 @@ impl OpenCADStudio {
self.tabs[i].dirty = true;
self.commit_layer_undo(i, undo);
self.refresh_layer_panel();
self.command_line.push_info("All layers thawed.");
self.command_line.push_info(crate::t!("All layers thawed.").as_ref());
}
"LAYULK" => {
@ -462,7 +462,7 @@ impl OpenCADStudio {
self.tabs[i].dirty = true;
self.commit_layer_undo(i, undo);
self.refresh_layer_panel();
self.command_line.push_info("Layer(s) unlocked.");
self.command_line.push_info(crate::t!("Layer(s) unlocked.").as_ref());
}
}
@ -476,7 +476,7 @@ impl OpenCADStudio {
.collect();
if sel_layers.is_empty() {
self.command_line
.push_error("LAYISO: select entities on the layers to isolate first.");
.push_error(crate::t!("LAYISO: select entities on the layers to isolate first.").as_ref());
} else {
let names: Vec<String> = self.tabs[i]
.scene
@ -498,7 +498,7 @@ impl OpenCADStudio {
self.commit_layer_undo(i, undo);
self.refresh_layer_panel();
self.command_line
.push_info(&format!("LAYISO: isolated {} layer(s).", sel_layers.len()));
.push_info(crate::tf!("LAYISO: isolated {} layer(s).", sel_layers.len()).as_ref());
}
}
@ -506,7 +506,7 @@ impl OpenCADStudio {
"ISOLATEOBJECTS" => {
if self.tabs[i].scene.selected.is_empty() {
self.command_line
.push_error("ISOLATEOBJECTS: select the objects to isolate first.");
.push_error(crate::t!("ISOLATEOBJECTS: select the objects to isolate first.").as_ref());
} else {
let n = self.tabs[i].scene.selected.len();
let before = self.tabs[i].scene.object_isolation.clone();
@ -519,9 +519,9 @@ impl OpenCADStudio {
before,
selected_before,
);
self.command_line.push_info(&format!(
self.command_line.push_info(crate::tf!(
"Isolated {n} object(s). UNISOLATEOBJECTS to restore."
));
).as_ref());
}
}
@ -529,7 +529,7 @@ impl OpenCADStudio {
"HIDEOBJECTS" => {
if self.tabs[i].scene.selected.is_empty() {
self.command_line
.push_error("HIDEOBJECTS: select the objects to hide first.");
.push_error(crate::t!("HIDEOBJECTS: select the objects to hide first.").as_ref());
} else {
let n = self.tabs[i].scene.selected.len();
let before = self.tabs[i].scene.object_isolation.clone();
@ -544,7 +544,7 @@ impl OpenCADStudio {
);
self.refresh_properties();
self.command_line
.push_info(&format!("Hid {n} object(s). UNISOLATEOBJECTS to restore."));
.push_info(crate::tf!("Hid {n} object(s). UNISOLATEOBJECTS to restore.").as_ref());
}
}
@ -562,9 +562,9 @@ impl OpenCADStudio {
selected_before,
);
self.command_line
.push_info("Isolation ended — all objects shown.");
.push_info(crate::t!("Isolation ended — all objects shown.").as_ref());
} else {
self.command_line.push_info("No hidden objects.");
self.command_line.push_info(crate::t!("No hidden objects.").as_ref());
}
}
@ -588,7 +588,7 @@ impl OpenCADStudio {
self.commit_layer_undo(i, undo);
self.refresh_layer_panel();
self.command_line
.push_info("LAYUNISO: all layers restored.");
.push_info(crate::t!("LAYUNISO: all layers restored.").as_ref());
}
"LAYMATCH" | "LAYMCH" => {
@ -653,10 +653,10 @@ impl OpenCADStudio {
self.commit_group_undo(i, undo);
if count > 0 {
self.command_line
.push_info(&format!("{} group(s) dissolved.", count));
.push_info(crate::tf!("{} group(s) dissolved.", count).as_ref());
} else {
self.command_line
.push_info("No groups found for selected objects.");
.push_info(crate::t!("No groups found for selected objects.").as_ref());
}
}
}

View file

@ -116,7 +116,7 @@ impl OpenCADStudio {
// rather than keeping a second, blunter copy (#388, #389).
if self.tabs[i].is_start && !start_allowed(cmd) {
self.command_line
.push_info("No drawing open. Use NEW or OPEN to start a drawing.");
.push_info(crate::t!("No drawing open. Use NEW or OPEN to start a drawing.").as_ref());
return Task::none();
}
@ -164,7 +164,7 @@ impl OpenCADStudio {
}
}
self.command_line
.push_error(&format!("Unknown command: {cmd}"));
.push_error(crate::tf!("Unknown command: {cmd}").as_ref());
self.finish_dispatch(cmd)
}

View file

@ -38,7 +38,7 @@ impl OpenCADStudio {
"" => {
let c = self.tabs[i].scene.document.header.current_entity_color;
self.command_line
.push_output(&format!("Current object colour: {}", describe(&c)));
.push_output(crate::tf!("Current object colour: {}", describe(&c)).as_ref());
return Some(Task::none());
}
"BYLAYER" => Some(Color::ByLayer),
@ -58,7 +58,7 @@ impl OpenCADStudio {
self.ribbon.active_color = c;
self.tabs[i].dirty = true;
self.command_line
.push_output(&format!("Object colour set to {}.", describe(&c)));
.push_output(crate::tf!("Object colour set to {}.", describe(&c)).as_ref());
}
None => {
self.command_line.push_error(
@ -96,10 +96,10 @@ impl OpenCADStudio {
.map(|lt| format!("{} ({})", lt.name, lt.description))
.collect();
if ltypes.is_empty() {
self.command_line.push_output("No linetypes defined.");
self.command_line.push_output(crate::t!("No linetypes defined.").as_ref());
} else {
self.command_line
.push_output(&format!("Linetypes: {}", ltypes.join(", ")));
.push_output(crate::tf!("Linetypes: {}", ltypes.join(", ")).as_ref());
}
}
// Set the current linetype applied to newly drawn entities.
@ -107,7 +107,7 @@ impl OpenCADStudio {
let name = parts.get(1).copied().unwrap_or("");
if name.is_empty() {
self.command_line
.push_info("Usage: LINETYPE SET <name | ByLayer | ByBlock>");
.push_info(crate::t!("Usage: LINETYPE SET <name | ByLayer | ByBlock>").as_ref());
} else {
let canon = if name.eq_ignore_ascii_case("BYLAYER") {
Some(("ByLayer".to_string(), acadrust::types::Handle::NULL))
@ -129,19 +129,19 @@ impl OpenCADStudio {
h.current_linetype_handle = handle;
self.tabs[i].dirty = true;
self.command_line
.push_output(&format!("Current linetype set to {nm}."));
.push_output(crate::tf!("Current linetype set to {nm}.").as_ref());
}
None => {
self.command_line.push_error(&format!(
self.command_line.push_error(crate::tf!(
"LINETYPE: \"{name}\" is not loaded. Use LINETYPE LIST to see available linetypes."
));
).as_ref());
}
}
}
}
_ => {
self.command_line
.push_info("Usage: LINETYPE LIST | SET <name>");
.push_info(crate::t!("Usage: LINETYPE LIST | SET <name>").as_ref());
}
}
}
@ -177,9 +177,9 @@ impl OpenCADStudio {
let do_lts = all || matches!(sub.as_str(), "LINETYPES" | "LT");
let do_blocks = all || matches!(sub.as_str(), "BLOCKS" | "BLOCK" | "B");
if !(do_layers || do_styles || do_lts || do_blocks) {
self.command_line.push_error(&format!(
self.command_line.push_error(crate::tf!(
"PURGE: unknown option \"{sub}\" — use ALL, Blocks, LAyers, LineTypes or STyles."
));
).as_ref());
return Some(Task::none());
}
@ -560,13 +560,13 @@ impl OpenCADStudio {
if n_sortents > 0 {
parts.push(format!("{n_sortents} stale draw-order table(s)"));
}
self.command_line.push_output(&format!(
self.command_line.push_output(crate::tf!(
"PURGE: {} item(s) removed — {}.",
purged + n_sortents,
parts.join(", ")
));
).as_ref());
} else {
self.command_line.push_output("PURGE: nothing to purge.");
self.command_line.push_output(crate::t!("PURGE: nothing to purge.").as_ref());
}
}
@ -610,7 +610,7 @@ impl OpenCADStudio {
.collect();
if handles.is_empty() {
self.command_line
.push_error("CHPROP: no entities selected.");
.push_error(crate::t!("CHPROP: no entities selected.").as_ref());
} else {
// Validate value early to give clear errors
let color_val: Option<acadrust::types::Color> = if prop == "COLOR" {
@ -640,10 +640,10 @@ impl OpenCADStudio {
|| (prop == "LTSCALE" && ltscale_val.is_none())
|| (prop == "TRANSPARENCY" && transparency_val.is_none())
{
self.command_line.push_error(&format!(
self.command_line.push_error(crate::tf!(
"CHPROP: invalid value '{}' for {}.",
value, prop
));
).as_ref());
} else {
let mut changed = 0usize;
for handle in &handles {
@ -673,9 +673,9 @@ impl OpenCADStudio {
changed += 1;
}
_ => {
self.command_line.push_error(&format!(
self.command_line.push_error(crate::tf!(
"CHPROP: unknown property '{}'. Use: LAYER COLOR LINETYPE LTSCALE TRANSPARENCY", prop
));
).as_ref());
break;
}
}
@ -689,10 +689,10 @@ impl OpenCADStudio {
// re-tessellate the changed entities so they
// repaint immediately (issue #231 class).
self.invalidate_property_targets(i, &handles);
self.command_line.push_output(&format!(
self.command_line.push_output(crate::tf!(
"CHPROP: {} entity/entities updated.",
changed
));
).as_ref());
}
}
}
@ -711,7 +711,7 @@ impl OpenCADStudio {
.collect();
if handles.is_empty() {
self.command_line
.push_error("SETBYLAYER: select entities first.");
.push_error(crate::t!("SETBYLAYER: select entities first.").as_ref());
} else {
self.push_undo_snapshot(i, "SETBYLAYER");
let mut changed = 0usize;
@ -730,9 +730,9 @@ impl OpenCADStudio {
.map(|handle| (handle, crate::scene::ChangeKind::Modified))
.collect();
self.tabs[i].scene.bump_entities(&changes);
self.command_line.push_output(&format!(
self.command_line.push_output(crate::tf!(
"SETBYLAYER: reset {changed} entity/entities to ByLayer."
));
).as_ref());
}
}
@ -778,7 +778,7 @@ impl OpenCADStudio {
}
if dups.is_empty() {
self.command_line
.push_output("OVERKILL: no duplicate objects found.");
.push_output(crate::t!("OVERKILL: no duplicate objects found.").as_ref());
} else {
let n = dups.len();
self.push_undo_snapshot(i, "OVERKILL");
@ -786,7 +786,7 @@ impl OpenCADStudio {
self.tabs[i].dirty = true;
self.refresh_properties();
self.command_line
.push_output(&format!("OVERKILL: deleted {n} duplicate object(s)."));
.push_output(crate::tf!("OVERKILL: deleted {n} duplicate object(s).").as_ref());
}
}
@ -813,17 +813,17 @@ impl OpenCADStudio {
} else {
u8::from(self.pick_drag_rect)
};
self.command_line.push_output(&format!(
self.command_line.push_output(crate::tf!(
"{} = {v}",
if is_add { "PICKADD" } else { "PICKDRAG" }
));
).as_ref());
} else {
match arg {
"0" | "1" => {
let on = arg == "1";
if is_add {
self.pick_add = on;
self.command_line.push_output(&format!(
self.command_line.push_output(crate::tf!(
"PICKADD = {} ({})",
arg,
if on {
@ -831,10 +831,10 @@ impl OpenCADStudio {
} else {
"click replaces selection, Shift toggles"
}
));
).as_ref());
} else {
self.pick_drag_rect = on;
self.command_line.push_output(&format!(
self.command_line.push_output(crate::tf!(
"PICKDRAG = {} ({})",
arg,
if on {
@ -842,14 +842,14 @@ impl OpenCADStudio {
} else {
"press-drag lassoes"
}
));
).as_ref());
}
self.persist_settings_if_changed();
}
_ => self.command_line.push_error(&format!(
_ => self.command_line.push_error(crate::tf!(
"{}: expected 0 or 1.",
if is_add { "PICKADD" } else { "PICKDRAG" }
)),
).as_ref()),
}
}
}
@ -1586,9 +1586,9 @@ impl OpenCADStudio {
// prompt for a new value on the next line instead
// of only echoing the current one. Enter keeps it.
let current = msg.split('=').nth(1).map(str::trim).unwrap_or("");
self.command_line.push_output(&format!(
self.command_line.push_output(crate::tf!(
"Enter new value for {name} <{current}>:"
));
).as_ref());
self.pending_setvar = Some(name.clone());
}
}
@ -1667,15 +1667,15 @@ impl OpenCADStudio {
}
};
self.command_line
.push_output("FINDNONPURGEABLE: named objects in use (not purgeable):");
.push_output(crate::t!("FINDNONPURGEABLE: named objects in use (not purgeable):").as_ref());
self.command_line
.push_output(&format!(" Layers: {}", fmt(layers)));
.push_output(crate::tf!(" Layers: {}", fmt(layers)).as_ref());
self.command_line
.push_output(&format!(" Linetypes: {}", fmt(linetypes)));
.push_output(crate::tf!(" Linetypes: {}", fmt(linetypes)).as_ref());
self.command_line
.push_output(&format!(" Text styles: {}", fmt(styles)));
.push_output(crate::tf!(" Text styles: {}", fmt(styles)).as_ref());
self.command_line
.push_output(&format!(" Blocks: {}", fmt(blocks)));
.push_output(crate::tf!(" Blocks: {}", fmt(blocks)).as_ref());
}
// ── AUDIT — report drawing-database integrity issues ─────────
@ -1703,24 +1703,24 @@ impl OpenCADStudio {
}
}
self.command_line
.push_output(&format!("AUDIT: scanned {total} object(s)."));
.push_output(crate::tf!("AUDIT: scanned {total} object(s).").as_ref());
if undefined_layers.is_empty() && undefined_blocks.is_empty() {
self.command_line.push_output("AUDIT: no issues found.");
self.command_line.push_output(crate::t!("AUDIT: no issues found.").as_ref());
} else {
if !undefined_layers.is_empty() {
self.command_line.push_error(&format!(
self.command_line.push_error(crate::tf!(
"AUDIT: reference(s) to undefined layer(s): {}",
undefined_layers.into_iter().collect::<Vec<_>>().join(", ")
));
).as_ref());
}
if !undefined_blocks.is_empty() {
self.command_line.push_error(&format!(
self.command_line.push_error(crate::tf!(
"AUDIT: reference(s) to undefined block(s): {}",
undefined_blocks.into_iter().collect::<Vec<_>>().join(", ")
));
).as_ref());
}
self.command_line
.push_info("AUDIT: report only — no automatic repair performed.");
.push_info(crate::t!("AUDIT: report only — no automatic repair performed.").as_ref());
}
}
@ -1744,7 +1744,7 @@ impl OpenCADStudio {
if type_str.is_empty() || old_name.is_empty() || new_name.is_empty() {
self.command_line.push_info(
"Usage: RENAME <type> <old> <new> (types: LAYER BLOCK STYLE DIMSTYLE LINETYPE UCS VIEW)"
crate::t!("Usage: RENAME <type> <old> <new> (types: LAYER BLOCK STYLE DIMSTYLE LINETYPE UCS VIEW)").as_ref()
);
} else {
// Snapshot BEFORE mutating (undo must restore the old
@ -1789,21 +1789,21 @@ impl OpenCADStudio {
}
self.tabs[i].dirty = true;
self.command_line
.push_output(&format!("RENAME: '{}' → '{}'.", old_name, new_name));
.push_output(crate::tf!("RENAME: '{}' → '{}'.", old_name, new_name).as_ref());
} else {
self.discard_last_undo_entry(i);
if !known {
self.command_line.push_error(&format!("RENAME: unknown type '{}'. Use LAYER BLOCK STYLE DIMSTYLE LINETYPE UCS VIEW", type_str));
self.command_line.push_error(crate::tf!("RENAME: unknown type '{}'. Use LAYER BLOCK STYLE DIMSTYLE LINETYPE UCS VIEW", type_str).as_ref());
} else if type_str == "BLOCK" {
self.command_line.push_error(&format!(
self.command_line.push_error(crate::tf!(
"RENAME: could not rename block '{}' — missing/anonymous/xref, or '{}' is invalid or taken.",
old_name, new_name
));
).as_ref());
} else {
self.command_line.push_error(&format!(
self.command_line.push_error(crate::tf!(
"RENAME: could not rename '{}' in {} — not found or protected, or '{}' is invalid or taken.",
old_name, type_str, new_name
));
).as_ref());
}
}
}
@ -1825,17 +1825,17 @@ impl OpenCADStudio {
if name_arg.is_empty() {
let cur = &self.tabs[i].scene.document.header.current_layer_name;
self.command_line
.push_output(&format!("CLAYER = \"{cur}\""));
.push_output(crate::tf!("CLAYER = \"{cur}\"").as_ref());
} else {
if self.tabs[i].scene.document.layers.contains(name_arg) {
self.tabs[i].scene.document.header.current_layer_name =
name_arg.to_string();
self.tabs[i].dirty = true;
self.command_line
.push_output(&format!("CLAYER set to \"{name_arg}\""));
.push_output(crate::tf!("CLAYER set to \"{name_arg}\"").as_ref());
} else {
self.command_line
.push_error(&format!("CLAYER: layer '{}' not found.", name_arg));
.push_error(crate::tf!("CLAYER: layer '{}' not found.", name_arg).as_ref());
}
}
}
@ -1851,16 +1851,16 @@ impl OpenCADStudio {
if name_arg.is_empty() {
let cur = &self.tabs[i].scene.document.header.current_dimstyle_name;
self.command_line
.push_output(&format!("CDIMSTY = \"{cur}\""));
.push_output(crate::tf!("CDIMSTY = \"{cur}\"").as_ref());
} else {
if self.tabs[i].scene.document.dim_styles.contains(&name_arg) {
self.tabs[i].scene.document.header.current_dimstyle_name = name_arg.clone();
self.tabs[i].dirty = true;
self.command_line
.push_output(&format!("Active dim style set to \"{name_arg}\""));
.push_output(crate::tf!("Active dim style set to \"{name_arg}\"").as_ref());
} else {
self.command_line
.push_error(&format!("CDIMSTY: dim style '{}' not found.", name_arg));
.push_error(crate::tf!("CDIMSTY: dim style '{}' not found.", name_arg).as_ref());
}
}
}
@ -1874,20 +1874,20 @@ impl OpenCADStudio {
let val_str = cmd.trim_start_matches("LTSCALE").trim();
if val_str.is_empty() {
let v = self.tabs[i].scene.document.header.linetype_scale;
self.command_line.push_output(&format!("LTSCALE = {v:.4}"));
self.command_line.push_output(crate::tf!("LTSCALE = {v:.4}").as_ref());
} else if let Ok(v) = val_str.parse::<f64>() {
if v > 0.0 {
self.push_undo_snapshot(i, "LTSCALE");
self.tabs[i].scene.document.header.linetype_scale = v;
self.tabs[i].dirty = true;
self.command_line
.push_output(&format!("LTSCALE set to {v:.4}"));
.push_output(crate::tf!("LTSCALE set to {v:.4}").as_ref());
} else {
self.command_line
.push_error("LTSCALE: value must be positive.");
.push_error(crate::t!("LTSCALE: value must be positive.").as_ref());
}
} else {
self.command_line.push_error("Usage: LTSCALE [value]");
self.command_line.push_error(crate::t!("Usage: LTSCALE [value]").as_ref());
}
}
"PDMODE" => {
@ -1903,14 +1903,14 @@ impl OpenCADStudio {
let val_str = cmd.trim_start_matches("PDMODE").trim();
if val_str.is_empty() {
let v = self.tabs[i].scene.document.header.point_display_mode;
self.command_line.push_output(&format!("PDMODE = {v}"));
self.command_line.push_output(crate::tf!("PDMODE = {v}").as_ref());
} else if let Ok(v) = val_str.parse::<i16>() {
self.push_undo_snapshot(i, "PDMODE");
self.tabs[i].scene.document.header.point_display_mode = v;
// Point glyphs are built at tessellation time — rebuild them.
self.tabs[i].scene.invalidate_point_dependencies();
self.tabs[i].dirty = true;
self.command_line.push_output(&format!("PDMODE set to {v}"));
self.command_line.push_output(crate::tf!("PDMODE set to {v}").as_ref());
} else {
self.command_line.push_error(
"Usage: PDMODE [value] (0=dot 1=none 2=+ 3=x 4=tick; +32 circle, +64 square)",
@ -1922,17 +1922,17 @@ impl OpenCADStudio {
if val_str.is_empty() {
let v = if self.texteditmode { 1 } else { 0 };
self.command_line
.push_output(&format!("TEXTEDITMODE = {v}"));
.push_output(crate::tf!("TEXTEDITMODE = {v}").as_ref());
} else if let Some(v) =
crate::modules::annotate::textedit::parse_texteditmode(&val_str)
{
self.texteditmode = v;
let n = if v { 1 } else { 0 };
self.command_line
.push_output(&format!("TEXTEDITMODE set to {n}"));
.push_output(crate::tf!("TEXTEDITMODE set to {n}").as_ref());
} else {
self.command_line
.push_error("Requires 0 OR 1 OR MULTIPLE OR SINGLE");
.push_error(crate::t!("Requires 0 OR 1 OR MULTIPLE OR SINGLE").as_ref());
}
}
"ISAVEBAK" => {
@ -1946,19 +1946,19 @@ impl OpenCADStudio {
match cmd.trim_start_matches("ISAVEBAK").trim() {
"" => {
let v = if self.backup_on_save { 1 } else { 0 };
self.command_line.push_output(&format!("ISAVEBAK = {v}"));
self.command_line.push_output(crate::tf!("ISAVEBAK = {v}").as_ref());
}
"0" => {
self.backup_on_save = false;
self.persist_settings_if_changed();
self.command_line.push_output("ISAVEBAK set to 0");
self.command_line.push_output(crate::t!("ISAVEBAK set to 0").as_ref());
}
"1" => {
self.backup_on_save = true;
self.persist_settings_if_changed();
self.command_line.push_output("ISAVEBAK set to 1");
self.command_line.push_output(crate::t!("ISAVEBAK set to 1").as_ref());
}
_ => self.command_line.push_error("Requires 0 or 1"),
_ => self.command_line.push_error(crate::t!("Requires 0 or 1").as_ref()),
}
}
"FILEASSOC" => {
@ -1974,7 +1974,7 @@ impl OpenCADStudio {
match cmd.trim_start_matches("FILEASSOC").trim() {
"" => {
let v = if self.file_assoc_enabled { 1 } else { 0 };
self.command_line.push_output(&format!("FILEASSOC = {v}"));
self.command_line.push_output(crate::tf!("FILEASSOC = {v}").as_ref());
}
"1" => {
self.file_assoc_enabled = true;
@ -1985,7 +1985,7 @@ impl OpenCADStudio {
),
Err(e) => self
.command_line
.push_error(&format!("FILEASSOC: registration failed: {e}")),
.push_error(crate::tf!("FILEASSOC: registration failed: {e}").as_ref()),
}
}
"0" => {
@ -1994,13 +1994,13 @@ impl OpenCADStudio {
match crate::io::file_association::unregister_handler() {
Ok(()) => self
.command_line
.push_output("FILEASSOC set to 0 — unregistered as a file handler"),
.push_output(crate::t!("FILEASSOC set to 0 — unregistered as a file handler").as_ref()),
Err(e) => self
.command_line
.push_error(&format!("FILEASSOC: unregister failed: {e}")),
.push_error(crate::tf!("FILEASSOC: unregister failed: {e}").as_ref()),
}
}
_ => self.command_line.push_error("Requires 0 or 1"),
_ => self.command_line.push_error(crate::t!("Requires 0 or 1").as_ref()),
}
}
"SAVETIME" => {
@ -2016,7 +2016,7 @@ impl OpenCADStudio {
let arg = cmd.trim_start_matches("SAVETIME").trim();
if arg.is_empty() {
self.command_line
.push_output(&format!("SAVETIME = {}", self.savetime_min));
.push_output(crate::tf!("SAVETIME = {}", self.savetime_min).as_ref());
return Some(Task::none());
}
match arg.parse::<i32>() {
@ -2032,7 +2032,7 @@ impl OpenCADStudio {
}
_ => self
.command_line
.push_error("Requires a non-negative number of minutes (0 = off)"),
.push_error(crate::t!("Requires a non-negative number of minutes (0 = off)").as_ref()),
}
}
"PDSIZE" => {
@ -2048,14 +2048,14 @@ impl OpenCADStudio {
let val_str = cmd.trim_start_matches("PDSIZE").trim();
if val_str.is_empty() {
let v = self.tabs[i].scene.document.header.point_display_size;
self.command_line.push_output(&format!("PDSIZE = {v:.4}"));
self.command_line.push_output(crate::tf!("PDSIZE = {v:.4}").as_ref());
} else if let Ok(v) = val_str.parse::<f64>() {
self.push_undo_snapshot(i, "PDSIZE");
self.tabs[i].scene.document.header.point_display_size = v;
self.tabs[i].scene.invalidate_point_dependencies();
self.tabs[i].dirty = true;
self.command_line
.push_output(&format!("PDSIZE set to {v:.4}"));
.push_output(crate::tf!("PDSIZE set to {v:.4}").as_ref());
} else {
self.command_line.push_error(
"Usage: PDSIZE [value] (>0 absolute size, <0 percent of viewport, 0 default)",
@ -2087,19 +2087,19 @@ impl OpenCADStudio {
_ => Err(()),
};
match parsed {
Err(_) => self.command_line.push_error("Usage: LWDISPLAY [ON|OFF]"),
Err(_) => self.command_line.push_error(crate::t!("Usage: LWDISPLAY [ON|OFF]").as_ref()),
Ok(Some(v)) => {
self.push_undo_snapshot(i, "LWDISPLAY");
self.tabs[i].scene.document.header.lineweight_display = v;
// No retessellate — the wire shader honours the flag via uniforms.
self.tabs[i].dirty = true;
self.command_line
.push_output(&format!("LWDISPLAY {}", if v { "ON" } else { "OFF" }));
.push_output(crate::tf!("LWDISPLAY {}", if v { "ON" } else { "OFF" }).as_ref());
}
Ok(None) => {
let v = self.tabs[i].scene.document.header.lineweight_display;
self.command_line
.push_output(&format!("LWDISPLAY = {}", if v { "ON" } else { "OFF" }));
.push_output(crate::tf!("LWDISPLAY = {}", if v { "ON" } else { "OFF" }).as_ref());
}
}
}
@ -2121,7 +2121,7 @@ impl OpenCADStudio {
.header
.current_entity_linetype_scale;
self.command_line
.push_output(&format!("CELTSCALE = {v:.4}"));
.push_output(crate::tf!("CELTSCALE = {v:.4}").as_ref());
} else if let Ok(v) = val_str.parse::<f64>() {
if v > 0.0 {
self.tabs[i]
@ -2131,13 +2131,13 @@ impl OpenCADStudio {
.current_entity_linetype_scale = v;
self.tabs[i].dirty = true;
self.command_line
.push_output(&format!("CELTSCALE set to {v:.4}"));
.push_output(crate::tf!("CELTSCALE set to {v:.4}").as_ref());
} else {
self.command_line
.push_error("CELTSCALE: value must be positive.");
.push_error(crate::t!("CELTSCALE: value must be positive.").as_ref());
}
} else {
self.command_line.push_error("Usage: CELTSCALE [value]");
self.command_line.push_error(crate::t!("Usage: CELTSCALE [value]").as_ref());
}
}
@ -2166,7 +2166,7 @@ impl OpenCADStudio {
.collect();
if selected_handles.is_empty() {
self.command_line
.push_error("SCALETEXT: select Text/MText entities first.");
.push_error(crate::t!("SCALETEXT: select Text/MText entities first.").as_ref());
} else {
let (use_absolute, value) = match (
parts.first().map(|s| s.to_uppercase()).as_deref(),
@ -2179,7 +2179,7 @@ impl OpenCADStudio {
if let Some(val) = value {
if val <= 0.0 {
self.command_line
.push_error("SCALETEXT: value must be positive.");
.push_error(crate::t!("SCALETEXT: value must be positive.").as_ref());
} else {
self.push_undo_snapshot(i, "SCALETEXT");
let mut count = 0usize;
@ -2206,17 +2206,17 @@ impl OpenCADStudio {
}
if count > 0 {
self.tabs[i].dirty = true;
self.command_line.push_output(&format!(
self.command_line.push_output(crate::tf!(
"SCALETEXT: scaled {count} text entity(ies)."
));
).as_ref());
} else {
self.command_line
.push_error("SCALETEXT: no Text/MText in selection.");
.push_error(crate::t!("SCALETEXT: no Text/MText in selection.").as_ref());
}
}
} else {
self.command_line
.push_info("Usage: SCALETEXT <factor> or SCALETEXT H <height>");
.push_info(crate::t!("Usage: SCALETEXT <factor> or SCALETEXT H <height>").as_ref());
}
}
}

View file

@ -4,7 +4,7 @@ impl OpenCADStudio {
pub(super) fn dispatch_view(&mut self, cmd: &str, i: usize) -> Option<Task<Message>> {
match cmd {
"DONATE" => {
self.command_line.push_info("Opening Patreon page...");
self.command_line.push_info(crate::t!("Opening Patreon page...").as_ref());
return Some(crate::sys::open_url(
"https://patreon.com/HakanSeven12",
self.main_window,
@ -12,7 +12,7 @@ impl OpenCADStudio {
}
"WEBVERSION" => {
self.command_line.push_info("Opening OCS Web...");
self.command_line.push_info(crate::t!("Opening OCS Web...").as_ref());
return Some(crate::sys::open_url(
"https://hakanseven12.github.io/OpenCADStudio/",
self.main_window,
@ -21,7 +21,7 @@ impl OpenCADStudio {
"HELP" => {
self.command_line
.push_info("Opening OCS Discussions for help and questions...");
.push_info(crate::t!("Opening OCS Discussions for help and questions...").as_ref());
return Some(crate::sys::open_url(
"https://github.com/HakanSeven12/OpenCADStudio/discussions",
self.main_window,
@ -41,78 +41,78 @@ impl OpenCADStudio {
.map(|p| p.display().to_string())
.unwrap_or_else(|| "(unsaved)".to_string());
self.command_line
.push_output(&format!("Drawing: {}", path_label));
.push_output(crate::tf!("Drawing: {}", path_label).as_ref());
self.command_line
.push_output(&format!(" Created (Julian): {:.6}", h.create_date_julian));
.push_output(crate::tf!(" Created (Julian): {:.6}", h.create_date_julian).as_ref());
self.command_line
.push_output(&format!(" Updated (Julian): {:.6}", h.update_date_julian));
.push_output(crate::tf!(" Updated (Julian): {:.6}", h.update_date_julian).as_ref());
self.command_line
.push_output(&format!(" Total edit time: {:.4}", h.total_editing_time));
.push_output(crate::tf!(" Total edit time: {:.4}", h.total_editing_time).as_ref());
self.command_line
.push_output(&format!(" User elapsed: {:.4}", h.user_elapsed_time));
self.command_line.push_output(&format!(
.push_output(crate::tf!(" User elapsed: {:.4}", h.user_elapsed_time).as_ref());
self.command_line.push_output(crate::tf!(
" Last saved by: {}",
if h.last_saved_by.is_empty() {
"(unknown)"
} else {
&h.last_saved_by
}
));
self.command_line.push_output(&format!(
).as_ref());
self.command_line.push_output(crate::tf!(
" Fingerprint GUID: {}",
if h.fingerprint_guid.is_empty() {
"(none)"
} else {
&h.fingerprint_guid
}
));
self.command_line.push_output(&format!(
).as_ref());
self.command_line.push_output(crate::tf!(
" Version GUID: {}",
if h.version_guid.is_empty() {
"(none)"
} else {
&h.version_guid
}
));
).as_ref());
self.command_line
.push_output(&format!(" Code page: {}", h.code_page));
self.command_line.push_output(&format!(
.push_output(crate::tf!(" Code page: {}", h.code_page).as_ref());
self.command_line.push_output(crate::tf!(
" Menu name: {}",
if h.menu_name.is_empty() {
"(none)"
} else {
&h.menu_name
}
));
self.command_line.push_output(&format!(
).as_ref());
self.command_line.push_output(crate::tf!(
" Hyperlink base: {}",
if h.hyperlink_base.is_empty() {
"(none)"
} else {
&h.hyperlink_base
}
));
self.command_line.push_output(&format!(
).as_ref());
self.command_line.push_output(crate::tf!(
" Project name: {}",
if h.project_name.is_empty() {
"(none)"
} else {
&h.project_name
}
));
self.command_line.push_output(&format!(
).as_ref());
self.command_line.push_output(crate::tf!(
" Stylesheet: {}",
if h.stylesheet.is_empty() {
"(none)"
} else {
&h.stylesheet
}
));
self.command_line.push_output(&format!(
).as_ref());
self.command_line.push_output(crate::tf!(
" Required versions: {:#018x}",
h.required_versions
));
self.command_line.push_output(&format!(
).as_ref());
self.command_line.push_output(crate::tf!(
" Measurement: {} ({})",
h.measurement,
if h.measurement == 1 {
@ -120,23 +120,23 @@ impl OpenCADStudio {
} else {
"Imperial"
}
));
).as_ref());
self.command_line
.push_output(&format!(" Proxy graphics: {}", h.proxy_graphics));
.push_output(crate::tf!(" Proxy graphics: {}", h.proxy_graphics).as_ref());
self.command_line
.push_output(&format!(" Tree depth: {}", h.tree_depth));
self.command_line.push_output(&format!(
.push_output(crate::tf!(" Tree depth: {}", h.tree_depth).as_ref());
self.command_line.push_output(crate::tf!(
" User vars (int): {} {} {} {} {}",
h.user_int1, h.user_int2, h.user_int3, h.user_int4, h.user_int5
));
self.command_line.push_output(&format!(
).as_ref());
self.command_line.push_output(crate::tf!(
" User vars (real): {:.6} {:.6} {:.6} {:.6} {:.6}",
h.user_real1, h.user_real2, h.user_real3, h.user_real4, h.user_real5
));
self.command_line.push_output(&format!(
).as_ref());
self.command_line.push_output(crate::tf!(
" User timer: {}",
if h.user_timer { "On" } else { "Off" }
));
).as_ref());
}
// Edit a USERI1..USERI5 / USERR1..USERR5 slot. Lets the user
@ -174,9 +174,9 @@ impl OpenCADStudio {
_ => h.user_real5 = val,
}
self.tabs[i].dirty = true;
self.command_line.push_output(&format!("USERR{n} = {val}"));
self.command_line.push_output(crate::tf!("USERR{n} = {val}").as_ref());
} else {
self.command_line.push_info("Usage: USERR <1-5> <real>");
self.command_line.push_info(crate::t!("Usage: USERR <1-5> <real>").as_ref());
}
}
(Some(n @ 1..=5), v, false) => {
@ -189,14 +189,14 @@ impl OpenCADStudio {
_ => h.user_int5 = val,
}
self.tabs[i].dirty = true;
self.command_line.push_output(&format!("USERI{n} = {val}"));
self.command_line.push_output(crate::tf!("USERI{n} = {val}").as_ref());
} else {
self.command_line.push_info("Usage: USERI <1-5> <integer>");
self.command_line.push_info(crate::t!("Usage: USERI <1-5> <integer>").as_ref());
}
}
_ => self
.command_line
.push_info("Usage: USERI <1-5> <int> | USERR <1-5> <real>"),
.push_info(crate::t!("Usage: USERI <1-5> <int> | USERR <1-5> <real>").as_ref()),
}
}
@ -213,7 +213,7 @@ impl OpenCADStudio {
"https://github.com/HakanSeven12/OpenCADStudio/issues/new?body={}",
crate::sys::percent_encode(&body)
);
self.command_line.push_info("Opening feedback page...");
self.command_line.push_info(crate::t!("Opening feedback page...").as_ref());
return Some(crate::sys::open_url(&url, self.main_window));
}
@ -226,7 +226,7 @@ impl OpenCADStudio {
}
"CHANGELOG" => {
self.command_line.push_info("Opening release notes...");
self.command_line.push_info(crate::t!("Opening release notes...").as_ref());
return Some(crate::sys::open_url(
"https://github.com/HakanSeven12/OpenCADStudio/releases",
self.main_window,
@ -266,12 +266,12 @@ impl OpenCADStudio {
let text: String = keys.iter().map(|(k, v)| format!("{k} {v}\n")).collect();
let count = self.shortcut_overrides.len();
match std::fs::write(path, text) {
Ok(()) => self.command_line.push_output(&format!(
Ok(()) => self.command_line.push_output(crate::tf!(
"CUIEXPORT: wrote {count} shortcut(s) to \"{path}\"."
)),
).as_ref()),
Err(e) => self
.command_line
.push_error(&format!("CUIEXPORT: cannot write \"{path}\": {e}")),
.push_error(crate::tf!("CUIEXPORT: cannot write \"{path}\": {e}").as_ref()),
}
}
@ -308,13 +308,13 @@ impl OpenCADStudio {
n += 1;
}
}
self.command_line.push_output(&format!(
self.command_line.push_output(crate::tf!(
"CUIIMPORT: loaded {n} shortcut(s) from \"{path}\"."
));
).as_ref());
}
Err(e) => self
.command_line
.push_error(&format!("CUIIMPORT: cannot read \"{path}\": {e}")),
.push_error(crate::tf!("CUIIMPORT: cannot read \"{path}\": {e}").as_ref()),
}
}
@ -333,28 +333,28 @@ impl OpenCADStudio {
let key = parts.get(1).map(|s| s.to_uppercase()).unwrap_or_default();
let cmd_str = parts.get(2).map(|s| s.to_uppercase()).unwrap_or_default();
if key.is_empty() || cmd_str.is_empty() {
self.command_line.push_error("Usage: SHORTCUTS SET <key> <command> e.g. SHORTCUTS SET CTRL+D DIST");
self.command_line.push_error(crate::t!("Usage: SHORTCUTS SET <key> <command> e.g. SHORTCUTS SET CTRL+D DIST").as_ref());
} else {
self.shortcut_overrides.insert(key.clone(), cmd_str.clone());
self.command_line
.push_output(&format!("Shortcut set: {key} → {cmd_str}"));
.push_output(crate::tf!("Shortcut set: {key} → {cmd_str}").as_ref());
}
}
"CLEAR" | "DELETE" | "REMOVE" => {
let key = parts.get(1).map(|s| s.to_uppercase()).unwrap_or_default();
if key.is_empty() {
self.command_line.push_error("Usage: SHORTCUTS CLEAR <key>");
self.command_line.push_error(crate::t!("Usage: SHORTCUTS CLEAR <key>").as_ref());
} else if self.shortcut_overrides.remove(&key).is_some() {
self.command_line
.push_output(&format!("Shortcut '{key}' removed."));
.push_output(crate::tf!("Shortcut '{key}' removed.").as_ref());
} else {
self.command_line
.push_error(&format!("Shortcut '{key}' not found."));
.push_error(crate::tf!("Shortcut '{key}' not found.").as_ref());
}
}
_ => {
self.command_line
.push_info("Usage: SHORTCUTS LIST | SET <key> <cmd> | CLEAR <key>");
.push_info(crate::t!("Usage: SHORTCUTS LIST | SET <key> <cmd> | CLEAR <key>").as_ref());
}
}
}
@ -396,17 +396,17 @@ impl OpenCADStudio {
return Some(Task::none());
}
_ => {
self.command_line.push_error(&format!(
self.command_line.push_error(crate::tf!(
"COLORSCHEME: unknown theme '{}'. Type COLORSCHEME LIST for options.",
sub
));
).as_ref());
return Some(Task::none());
}
};
if let Some(t) = theme {
let name = format!("{:?}", t);
self.command_line
.push_output(&format!("Color scheme set to '{name}'."));
.push_output(crate::tf!("Color scheme set to '{name}'.").as_ref());
return Some(Task::done(Message::SetTheme(t)));
}
return Some(Task::none());
@ -421,7 +421,7 @@ impl OpenCADStudio {
"MVIEW" => {
if self.tabs[i].scene.current_layout == "Model" {
self.command_line
.push_error("MVIEW: switch to a paper space layout first.");
.push_error(crate::t!("MVIEW: switch to a paper space layout first.").as_ref());
} else {
use crate::modules::layout::mview::MviewCommand;
let scene = &self.tabs[i].scene;
@ -464,7 +464,7 @@ impl OpenCADStudio {
if sub.is_empty() {
self.awaiting_vports = true;
self.command_line
.push_info("VPORTS Configuration [SIngle/2H/2V/4]:");
.push_info(crate::t!("VPORTS Configuration [SIngle/2H/2V/4]:").as_ref());
return Some(self.focus_cmd_input());
}
// Model space: split the tiled viewport layout via pane_grid.
@ -494,11 +494,11 @@ impl OpenCADStudio {
self.tabs[i].scene.set_model_panes(config);
self.tabs[i].scene.camera_generation += 1;
self.command_line
.push_output(&format!("VPORTS: {n} viewport(s)."));
.push_output(crate::tf!("VPORTS: {n} viewport(s).").as_ref());
}
None => {
self.command_line
.push_error("VPORTS: use SINGLE | 2H | 2V | 4.");
.push_error(crate::t!("VPORTS: use SINGLE | 2H | 2V | 4.").as_ref());
}
}
} else if sub.is_empty() {
@ -532,23 +532,23 @@ impl OpenCADStudio {
})
.collect();
if viewports.is_empty() {
self.command_line.push_info("No viewports. Use MVIEW to create one, or VPORTS 2H / 2V / 4 / SINGLE.");
self.command_line.push_info(crate::t!("No viewports. Use MVIEW to create one, or VPORTS 2H / 2V / 4 / SINGLE.").as_ref());
} else {
self.command_line.push_output(&format!(
self.command_line.push_output(crate::tf!(
"{} viewport(s) in layout \"{}\":",
viewports.len(),
scene.current_layout
));
).as_ref());
for (id, center, w, h, scale, is_on, locked) in &viewports {
let state = match (is_on, locked) {
(true, true) => "On, Locked",
(true, false) => "On",
(false, _) => "Off",
};
self.command_line.push_output(&format!(
self.command_line.push_output(crate::tf!(
" VP #{id}: {w:.1}×{h:.1} @ ({:.1},{:.1}) scale={scale:.4} [{state}]",
center.x, center.y
));
).as_ref());
}
}
} else {
@ -654,7 +654,7 @@ impl OpenCADStudio {
self.tabs[i].scene.auto_fit_viewport(handle);
}
Err(e) => {
self.command_line.push_error(&format!("VPORTS: {e}"));
self.command_line.push_error(crate::tf!("VPORTS: {e}").as_ref());
}
}
}
@ -686,11 +686,11 @@ impl OpenCADStudio {
}
}
self.tabs[i].dirty = true;
self.command_line.push_output(&format!(
self.command_line.push_output(crate::tf!(
"VPORTS: created {} viewport(s) [{}].",
rects.len(),
sub
));
).as_ref());
}
}
}
@ -700,10 +700,10 @@ impl OpenCADStudio {
let scene = &self.tabs[i].scene;
if scene.current_layout == "Model" {
self.command_line
.push_error("VPLAYER: switch to a paper space layout first.");
.push_error(crate::t!("VPLAYER: switch to a paper space layout first.").as_ref());
} else if scene.active_viewport.is_none() {
self.command_line
.push_error("VPLAYER: enter a viewport first (double-click or MS).");
.push_error(crate::t!("VPLAYER: enter a viewport first (double-click or MS).").as_ref());
} else {
use crate::modules::layout::vplayer::VplayerCommand;
let vp_handle = scene.active_viewport.unwrap();
@ -729,12 +729,12 @@ impl OpenCADStudio {
};
if frozen_names.is_empty() {
self.command_line
.push_info("VPLAYER: no frozen layers in active viewport.");
.push_info(crate::t!("VPLAYER: no frozen layers in active viewport.").as_ref());
} else {
self.command_line.push_info(&format!(
self.command_line.push_info(crate::tf!(
"VPLAYER: frozen layers: {}",
frozen_names.join(", ")
));
).as_ref());
}
let new_cmd = VplayerCommand::new(vp_handle);
self.command_line.push_info(&new_cmd.prompt());
@ -763,7 +763,7 @@ impl OpenCADStudio {
.collect();
if handles.is_empty() {
self.command_line
.push_info(&format!("{cmd}: no text or dimension objects."));
.push_info(crate::tf!("{cmd}: no text or dimension objects.").as_ref());
return Some(Task::none());
}
self.tabs[i].scene.replace_selection(handles);
@ -802,7 +802,7 @@ impl OpenCADStudio {
.collect();
if selected.is_empty() {
self.command_line
.push_error("DRAWORDER: select entities first.");
.push_error(crate::t!("DRAWORDER: select entities first.").as_ref());
} else {
// Parse relative target handle for ABOVE/UNDER.
let relative_target: Option<(bool, acadrust::Handle)> = match option.as_str() {
@ -940,12 +940,12 @@ impl OpenCADStudio {
}
}
let rel = if above { "above" } else { "below" };
self.command_line.push_info(&format!(
self.command_line.push_info(crate::tf!(
"DRAWORDER: moved {} entities {} {:x}.",
selected.len(),
rel,
target.value()
));
).as_ref());
} else if let Some(to_front) = to_front_opt {
let (min_eff, max_eff) = fb_baseline.unwrap_or((1, 0));
for (k, h) in selected.iter().enumerate() {
@ -957,11 +957,11 @@ impl OpenCADStudio {
table.add_entry(*h, acadrust::Handle::new(sort));
}
let dir = if to_front { "front" } else { "back" };
self.command_line.push_info(&format!(
self.command_line.push_info(crate::tf!(
"DRAWORDER: moved {} entities to {}.",
selected.len(),
dir
));
).as_ref());
}
}
// Sort order lives in SortEntitiesTable, which the
@ -974,7 +974,7 @@ impl OpenCADStudio {
self.tabs[i].dirty = true;
} else {
self.command_line.push_info(
"Usage: DRAWORDER F|FRONT | B|BACK | A|ABOVE <handle> | U|UNDER <handle>"
crate::t!("Usage: DRAWORDER F|FRONT | B|BACK | A|ABOVE <handle> | U|UNDER <handle>").as_ref()
);
}
}
@ -1000,7 +1000,7 @@ impl OpenCADStudio {
Some(acadrust::EntityType::Viewport(vp)) => vp.clone(),
_ => {
self.command_line
.push_error("SYNCPVIEWPORTS: master is not a viewport.");
.push_error(crate::t!("SYNCPVIEWPORTS: master is not a viewport.").as_ref());
return Some(Task::none());
}
};
@ -1023,9 +1023,9 @@ impl OpenCADStudio {
}
}
self.tabs[i].dirty = true;
self.command_line.push_output(&format!(
self.command_line.push_output(crate::tf!(
"SYNCPVIEWPORTS: synced {n} viewport(s) to the master."
));
).as_ref());
}
// HIDE — hidden-line view of the active viewport.
@ -1088,9 +1088,9 @@ impl CadCommand for DrawOrderRefCommand {
fn prompt(&self) -> String {
if self.above {
"DRAWORDER Select reference object (move selection above):".into()
crate::t!("DRAWORDER Select reference object (move selection above):").into_owned()
} else {
"DRAWORDER Select reference object (move selection under):".into()
crate::t!("DRAWORDER Select reference object (move selection under):").into_owned()
}
}