forked from 1b-agent/opencadstudio-upstream
feat(array): ARRAYEDIT Source edits what an associative array repeats
ARRAYEDIT picks an associative array (or takes the preselected one) and its Source option opens the objects every item repeats in the Block Editor; saving there updates all items at once. Counts and spacings stay in Properties. Refs #1109 Co-Authored-By: Claude Opus 5.5 <[email protected]>
This commit is contained in:
1 parent
780b54489e
commit
881d237629
26 files changed
+187
No files matched your search
@@ -301,6 +301,45 @@ impl OpenCADStudio {
|
||||
}
|
||||
}
|
||||
|
||||
// ARRAYEDIT — edit an associative array; a preselected one skips
|
||||
// the pick.
|
||||
"ARRAYEDIT" => {
|
||||
use crate::modules::draw::modify::arrayedit::ArrayEditCommand;
|
||||
let selected = self.tabs[i].scene.selected_handles_in_order();
|
||||
let array = match selected.as_slice() {
|
||||
[handle] => Some(*handle),
|
||||
_ => None,
|
||||
};
|
||||
self.tabs[i].scene.deselect_all();
|
||||
let command = ArrayEditCommand::new(array);
|
||||
self.command_line.push_info(&command.prompt());
|
||||
self.tabs[i].active_cmd = Some(Box::new(command));
|
||||
}
|
||||
|
||||
// ARRAYEDIT Source: edit the objects the array repeats in the
|
||||
// Block Editor; every item follows when it is saved.
|
||||
cmd if cmd.starts_with("ARRAYEDIT_SOURCE:") => {
|
||||
let handle = codec::Handle::new(
|
||||
cmd["ARRAYEDIT_SOURCE:".len()..].parse().unwrap_or(0),
|
||||
);
|
||||
let document = &self.tabs[i].scene.document;
|
||||
let source = crate::scene::assoc_array::array_of_insert(document, handle)
|
||||
.and_then(|array| {
|
||||
document
|
||||
.block_records
|
||||
.iter()
|
||||
.find(|record| record.handle == array.source_block)
|
||||
.map(|record| record.name.clone())
|
||||
});
|
||||
match source {
|
||||
Some(name) => return Some(self.dispatch_command(&format!("BEDIT_OPEN:{name}"))),
|
||||
None => self.command_line.push_error(
|
||||
crate::t!("ARRAYEDIT: the selected object is not an associative array.")
|
||||
.as_ref(),
|
||||
),
|
||||
}
|
||||
}
|
||||
|
||||
// PASTESPEC — offer the copied objects now; the system clipboard's
|
||||
// text joins the formats once read (Message::PasteSpecial).
|
||||
"PASTESPEC" => {
|
||||
|
||||
@@ -802,6 +802,9 @@ pub(super) fn message_attribute(source: &str) -> Option<(&'static str, &'static
|
||||
"BACKGROUND colour [Default/Black/DarkGray/Gray/LightGray/White] or R G B (0–255):" => Some(("file", "background-colour-default-black-darkgray-gray")),
|
||||
"BASE Specify base point:" => Some(("insert", "base-specify-base-point")),
|
||||
"BEDIT Select block reference to edit:" => Some(("modify", "bedit-select-block-reference-to-edit")),
|
||||
"ARRAYEDIT Select array:" => Some(("modify", "arrayedit-select-array")),
|
||||
"ARRAYEDIT Enter an option [Source/eXit] <eXit>:" => Some(("modify", "arrayedit-options")),
|
||||
"ARRAYEDIT: the selected object is not an associative array." => Some(("modify", "arrayedit-not-an-array")),
|
||||
"BEDIT: Block \"{}\" edit discarded." => Some(("inquiry", "bedit-block-edit-discarded")),
|
||||
"BEDIT: Block \"{}\" saved. All references updated." => Some(("inquiry", "bedit-block-saved-all-references-updated")),
|
||||
"BEDIT: Editing block \"{}\". Use Save Block or Discard to finish." => Some(("inquiry", "bedit-editing-block-use-save-block-or-discard")),
|
||||
|
||||
@@ -0,0 +1,78 @@
|
||||
// ARRAYEDIT — edit an associative array. Counts and spacings are edited in
|
||||
// Properties; Source opens the objects every item repeats in the Block
|
||||
// Editor, and closing it updates all items at once.
|
||||
|
||||
use crate::command::{CadCommand, CmdOption, CmdResult};
|
||||
use codec::Handle;
|
||||
use glam::DVec3;
|
||||
|
||||
pub struct ArrayEditCommand {
|
||||
array: Option<Handle>,
|
||||
}
|
||||
|
||||
impl ArrayEditCommand {
|
||||
pub fn new(array: Option<Handle>) -> Self {
|
||||
Self { array }
|
||||
}
|
||||
}
|
||||
|
||||
impl CadCommand for ArrayEditCommand {
|
||||
fn name(&self) -> &'static str {
|
||||
"ARRAYEDIT"
|
||||
}
|
||||
|
||||
fn prompt(&self) -> String {
|
||||
match self.array {
|
||||
None => crate::t!("ARRAYEDIT Select array:").into_owned(),
|
||||
Some(_) => crate::t!("ARRAYEDIT Enter an option [Source/eXit] <eXit>:").into_owned(),
|
||||
}
|
||||
}
|
||||
|
||||
fn options(&self) -> Vec<CmdOption> {
|
||||
match self.array {
|
||||
None => Vec::new(),
|
||||
Some(_) => vec![
|
||||
CmdOption::new(crate::t!("Source").as_ref(), "S"),
|
||||
CmdOption::new(crate::t!("eXit").as_ref(), "X"),
|
||||
],
|
||||
}
|
||||
}
|
||||
|
||||
fn needs_entity_pick(&self) -> bool {
|
||||
self.array.is_none()
|
||||
}
|
||||
|
||||
fn on_entity_pick(&mut self, handle: Handle, _pt: DVec3) -> CmdResult {
|
||||
if handle.is_null() {
|
||||
return CmdResult::NeedPoint;
|
||||
}
|
||||
self.array = Some(handle);
|
||||
CmdResult::NeedPoint
|
||||
}
|
||||
|
||||
fn wants_text_input(&self) -> bool {
|
||||
self.array.is_some()
|
||||
}
|
||||
|
||||
fn on_text_input(&mut self, text: &str) -> Option<CmdResult> {
|
||||
let array = self.array?;
|
||||
match text.trim().trim_start_matches('_').to_ascii_uppercase().as_str() {
|
||||
"S" | "SOURCE" => Some(CmdResult::Dispatch(format!(
|
||||
"ARRAYEDIT_SOURCE:{}",
|
||||
array.value()
|
||||
))),
|
||||
"X" | "EXIT" => Some(CmdResult::Cancel),
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
|
||||
fn on_point(&mut self, _pt: DVec3) -> CmdResult {
|
||||
CmdResult::NeedPoint
|
||||
}
|
||||
|
||||
fn on_enter(&mut self) -> CmdResult {
|
||||
CmdResult::Cancel
|
||||
}
|
||||
}
|
||||
|
||||
inventory::submit!(crate::command::CommandRegistration { names: &["ARRAYEDIT"] });
|
||||
@@ -1,5 +1,6 @@
|
||||
pub mod align;
|
||||
pub mod array;
|
||||
pub mod arrayedit;
|
||||
pub mod attedit;
|
||||
pub mod blend;
|
||||
pub mod block_edit;
|
||||
|
||||
Reference in new issue
Block a user