ATTDEF dialog error band and multi-line editor; ATTDISP sets ATTMODE

Validation messages show in the dialogs, the Default value of a multi-line
definition can be edited in the multi-line text editor, "Specify on-screen"
is kept for the session, ATTDISP sets ATTMODE with the reference prompt
instead of changing the definitions, and Insert > Block gets the Edit
Attribute (Single / Multiple) and attribute display lists.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
This commit is contained in:
ramox81andClaude Opus 5.5 committed 2026-10-01 17:11:45 +03:00
1 parent c992b73cdf
commit 7f55043210
29 files changed
+449 -70

No files matched your search

+95
View File
@@ -32,12 +32,18 @@ pub struct AttdefSession {
pub aflags: u8,
pub annotative: bool,
pub last: Option<AttributeDefinition>,
/// The dialog's "Specify on-screen" choice, kept for the session.
pub on_screen: bool,
/// Text the multi-line editor handed back to the dialog's Default field.
pub editor_value: Option<String>,
}
pub static SESSION: Mutex<AttdefSession> = Mutex::new(AttdefSession {
aflags: AFLAG_LOCK,
annotative: false,
last: None,
on_screen: true,
editor_value: None,
});
pub fn session() -> std::sync::MutexGuard<'static, AttdefSession> {
@@ -1046,3 +1052,92 @@ impl CadCommand for AttdefPickCommand {
CmdResult::Dispatch("_ATTDEF_PICKED".into())
}
}
/// ATTDISP: `Enter attribute visibility setting [Normal/ON/OFF] <current>:`.
/// Hands the chosen setting back as `ATTDISP <word>`; Enter keeps the current
/// one.
pub struct AttdispCommand {
current: &'static str,
}
impl AttdispCommand {
/// `mode` is ATTMODE: 0 OFF, 1 Normal, 2 ON.
pub fn new(mode: i16) -> Self {
Self { current: attdisp_word(mode) }
}
}
/// The ATTDISP keyword for an ATTMODE value.
pub fn attdisp_word(mode: i16) -> &'static str {
match mode {
0 => "OFF",
2 => "ON",
_ => "Normal",
}
}
impl CadCommand for AttdispCommand {
fn name(&self) -> &'static str {
"ATTDISP"
}
fn prompt(&self) -> String {
format!("Enter attribute visibility setting [Normal/ON/OFF] <{}>:", self.current)
}
fn input_kind(&self) -> InputKind {
InputKind::SingleToken
}
fn on_text_input(&mut self, text: &str) -> Option<CmdResult> {
let word = text.trim().trim_start_matches('_').to_ascii_uppercase();
if word.is_empty() {
return Some(self.on_enter());
}
let mode = match word.as_str() {
"N" | "NORMAL" => "NORMAL",
"ON" => "ON",
"OF" | "OFF" => "OFF",
_ => return Some(CmdResult::ReportError("Invalid option keyword.".into())),
};
Some(CmdResult::Dispatch(format!("ATTDISP {mode}")))
}
fn on_point(&mut self, _pt: DVec3) -> CmdResult {
CmdResult::NeedPoint
}
fn on_enter(&mut self) -> CmdResult {
CmdResult::Cancel
}
}
/// The dialog's "…" button: the default value is edited in the multi-line
/// text editor, then handed back to the dialog (`_ATTDEF_VALUE`).
pub struct AttdefValueCommand;
impl CadCommand for AttdefValueCommand {
fn name(&self) -> &'static str {
"ATTDEF"
}
fn prompt(&self) -> String {
String::new()
}
fn on_point(&mut self, _pt: DVec3) -> CmdResult {
CmdResult::NeedPoint
}
fn on_enter(&mut self) -> CmdResult {
CmdResult::NeedPoint
}
fn on_editor_text(&mut self, value: String) {
session().editor_value = Some(value);
}
fn on_editor_closed(&mut self, _committed: bool) -> CmdResult {
CmdResult::Dispatch("_ATTDEF_VALUE".into())
}
}
+22 -1
View File
@@ -105,7 +105,28 @@ impl CadModule for InsertModule {
tools: vec![
RibbonItem::LargeTool(mview_block::tool()),
RibbonItem::LargeTool(insert_block::tool()),
RibbonItem::LargeTool(attedit::tool()),
RibbonItem::LabeledDropdown {
id: "ATTEDIT_DROPDOWN",
label: "Edit Attribute",
icon: attedit::ICON,
items: vec![
("ATTEDIT", "Single", attedit::ICON),
("-ATTEDIT", "Multiple", attedit::ICON),
],
default: "ATTEDIT",
},
// ATTMODE: the face shows the drawing's current setting.
RibbonItem::LabeledDropdown {
id: "ATTMODE_DROPDOWN",
label: "",
icon: attedit::ICON,
items: vec![
("ATTMODE1", "Retain Attribute Display", attedit::ICON),
("ATTMODE2", "Display All Attributes", attedit::ICON),
("ATTMODE0", "Hide All Attributes", attedit::ICON),
],
default: "ATTMODE1",
},
],
},
// ── Block Definition (slide-out: Set Base Point, Synchronize) ─────