forked from 1b-agent/opencadstudio-upstream
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 <noreply@anthropic.com>
This commit is contained in:
1 parent
c992b73cdf
commit
7f55043210
29 files changed
+449
-70
No files matched your search
@@ -4044,6 +4044,15 @@ insert =
|
||||
.attdef-define-attributes = Define Attributes
|
||||
.attdef-manage-attributes = Manage Attributes
|
||||
.attdef-set-base-point = Set Base Point
|
||||
.attdef-attmode-retain = Retain Attribute Display
|
||||
.attdef-attmode-all = Display All Attributes
|
||||
.attdef-attmode-none = Hide All Attributes
|
||||
.attdef-edit-attribute = Edit Attribute
|
||||
.attdef-multiline-editor = Multiline editor
|
||||
.attdef-tag-empty = The tag cannot be empty.
|
||||
.attdef-tag-spaces = The tag may not contain spaces.
|
||||
.attdef-positive = Value must be positive and nonzero.
|
||||
.attdef-angle = Requires valid numeric angle or second point.
|
||||
model =
|
||||
.create = إنشاء
|
||||
.boolean = عمليات منطقية
|
||||
|
||||
@@ -4031,6 +4031,15 @@ insert =
|
||||
.attdef-define-attributes = Define Attributes
|
||||
.attdef-manage-attributes = Manage Attributes
|
||||
.attdef-set-base-point = Set Base Point
|
||||
.attdef-attmode-retain = Retain Attribute Display
|
||||
.attdef-attmode-all = Display All Attributes
|
||||
.attdef-attmode-none = Hide All Attributes
|
||||
.attdef-edit-attribute = Edit Attribute
|
||||
.attdef-multiline-editor = Multiline editor
|
||||
.attdef-tag-empty = The tag cannot be empty.
|
||||
.attdef-tag-spaces = The tag may not contain spaces.
|
||||
.attdef-positive = Value must be positive and nonzero.
|
||||
.attdef-angle = Requires valid numeric angle or second point.
|
||||
model =
|
||||
.create = Създаване
|
||||
.boolean = Булеви операции
|
||||
|
||||
@@ -4029,6 +4029,15 @@ insert =
|
||||
.attdef-define-attributes = Define Attributes
|
||||
.attdef-manage-attributes = Manage Attributes
|
||||
.attdef-set-base-point = Set Base Point
|
||||
.attdef-attmode-retain = Retain Attribute Display
|
||||
.attdef-attmode-all = Display All Attributes
|
||||
.attdef-attmode-none = Hide All Attributes
|
||||
.attdef-edit-attribute = Edit Attribute
|
||||
.attdef-multiline-editor = Multiline editor
|
||||
.attdef-tag-empty = The tag cannot be empty.
|
||||
.attdef-tag-spaces = The tag may not contain spaces.
|
||||
.attdef-positive = Value must be positive and nonzero.
|
||||
.attdef-angle = Requires valid numeric angle or second point.
|
||||
model =
|
||||
.create = Vytvořit
|
||||
.boolean = Booleovské operace
|
||||
|
||||
@@ -4030,6 +4030,15 @@ insert =
|
||||
.attdef-define-attributes = Define Attributes
|
||||
.attdef-manage-attributes = Manage Attributes
|
||||
.attdef-set-base-point = Set Base Point
|
||||
.attdef-attmode-retain = Retain Attribute Display
|
||||
.attdef-attmode-all = Display All Attributes
|
||||
.attdef-attmode-none = Hide All Attributes
|
||||
.attdef-edit-attribute = Edit Attribute
|
||||
.attdef-multiline-editor = Multiline editor
|
||||
.attdef-tag-empty = The tag cannot be empty.
|
||||
.attdef-tag-spaces = The tag may not contain spaces.
|
||||
.attdef-positive = Value must be positive and nonzero.
|
||||
.attdef-angle = Requires valid numeric angle or second point.
|
||||
model =
|
||||
.create = Erstellen
|
||||
.boolean = Boolesche Operationen
|
||||
|
||||
@@ -4032,6 +4032,15 @@ insert =
|
||||
.attdef-define-attributes = Define Attributes
|
||||
.attdef-manage-attributes = Manage Attributes
|
||||
.attdef-set-base-point = Set Base Point
|
||||
.attdef-attmode-retain = Retain Attribute Display
|
||||
.attdef-attmode-all = Display All Attributes
|
||||
.attdef-attmode-none = Hide All Attributes
|
||||
.attdef-edit-attribute = Edit Attribute
|
||||
.attdef-multiline-editor = Multiline editor
|
||||
.attdef-tag-empty = The tag cannot be empty.
|
||||
.attdef-tag-spaces = The tag may not contain spaces.
|
||||
.attdef-positive = Value must be positive and nonzero.
|
||||
.attdef-angle = Requires valid numeric angle or second point.
|
||||
model =
|
||||
.create = Δημιουργία
|
||||
.boolean = Δυαδική πράξη
|
||||
|
||||
@@ -4033,6 +4033,15 @@ insert =
|
||||
.attdef-define-attributes = Define Attributes
|
||||
.attdef-manage-attributes = Manage Attributes
|
||||
.attdef-set-base-point = Set Base Point
|
||||
.attdef-attmode-retain = Retain Attribute Display
|
||||
.attdef-attmode-all = Display All Attributes
|
||||
.attdef-attmode-none = Hide All Attributes
|
||||
.attdef-edit-attribute = Edit Attribute
|
||||
.attdef-multiline-editor = Multiline editor
|
||||
.attdef-tag-empty = The tag cannot be empty.
|
||||
.attdef-tag-spaces = The tag may not contain spaces.
|
||||
.attdef-positive = Value must be positive and nonzero.
|
||||
.attdef-angle = Requires valid numeric angle or second point.
|
||||
model =
|
||||
.create = Create
|
||||
.boolean = Boolean
|
||||
|
||||
@@ -4032,6 +4032,15 @@ insert =
|
||||
.attdef-define-attributes = Define Attributes
|
||||
.attdef-manage-attributes = Manage Attributes
|
||||
.attdef-set-base-point = Set Base Point
|
||||
.attdef-attmode-retain = Retain Attribute Display
|
||||
.attdef-attmode-all = Display All Attributes
|
||||
.attdef-attmode-none = Hide All Attributes
|
||||
.attdef-edit-attribute = Edit Attribute
|
||||
.attdef-multiline-editor = Multiline editor
|
||||
.attdef-tag-empty = The tag cannot be empty.
|
||||
.attdef-tag-spaces = The tag may not contain spaces.
|
||||
.attdef-positive = Value must be positive and nonzero.
|
||||
.attdef-angle = Requires valid numeric angle or second point.
|
||||
model =
|
||||
.create = Crear
|
||||
.boolean = Booleanas
|
||||
|
||||
@@ -4031,6 +4031,15 @@ insert =
|
||||
.attdef-define-attributes = Define Attributes
|
||||
.attdef-manage-attributes = Manage Attributes
|
||||
.attdef-set-base-point = Set Base Point
|
||||
.attdef-attmode-retain = Retain Attribute Display
|
||||
.attdef-attmode-all = Display All Attributes
|
||||
.attdef-attmode-none = Hide All Attributes
|
||||
.attdef-edit-attribute = Edit Attribute
|
||||
.attdef-multiline-editor = Multiline editor
|
||||
.attdef-tag-empty = The tag cannot be empty.
|
||||
.attdef-tag-spaces = The tag may not contain spaces.
|
||||
.attdef-positive = Value must be positive and nonzero.
|
||||
.attdef-angle = Requires valid numeric angle or second point.
|
||||
model =
|
||||
.create = Luo
|
||||
.boolean = Boolen operaatiot
|
||||
|
||||
@@ -4032,6 +4032,15 @@ insert =
|
||||
.attdef-define-attributes = Define Attributes
|
||||
.attdef-manage-attributes = Manage Attributes
|
||||
.attdef-set-base-point = Set Base Point
|
||||
.attdef-attmode-retain = Retain Attribute Display
|
||||
.attdef-attmode-all = Display All Attributes
|
||||
.attdef-attmode-none = Hide All Attributes
|
||||
.attdef-edit-attribute = Edit Attribute
|
||||
.attdef-multiline-editor = Multiline editor
|
||||
.attdef-tag-empty = The tag cannot be empty.
|
||||
.attdef-tag-spaces = The tag may not contain spaces.
|
||||
.attdef-positive = Value must be positive and nonzero.
|
||||
.attdef-angle = Requires valid numeric angle or second point.
|
||||
model =
|
||||
.create = Créer
|
||||
.boolean = Opérations booléennes
|
||||
|
||||
@@ -4020,6 +4020,15 @@ insert =
|
||||
.attdef-define-attributes = Define Attributes
|
||||
.attdef-manage-attributes = Manage Attributes
|
||||
.attdef-set-base-point = Set Base Point
|
||||
.attdef-attmode-retain = Retain Attribute Display
|
||||
.attdef-attmode-all = Display All Attributes
|
||||
.attdef-attmode-none = Hide All Attributes
|
||||
.attdef-edit-attribute = Edit Attribute
|
||||
.attdef-multiline-editor = Multiline editor
|
||||
.attdef-tag-empty = The tag cannot be empty.
|
||||
.attdef-tag-spaces = The tag may not contain spaces.
|
||||
.attdef-positive = Value must be positive and nonzero.
|
||||
.attdef-angle = Requires valid numeric angle or second point.
|
||||
model =
|
||||
.create = बनाएँ
|
||||
.boolean = बूलियन संक्रियाएँ
|
||||
|
||||
@@ -4031,6 +4031,15 @@ insert =
|
||||
.attdef-define-attributes = Define Attributes
|
||||
.attdef-manage-attributes = Manage Attributes
|
||||
.attdef-set-base-point = Set Base Point
|
||||
.attdef-attmode-retain = Retain Attribute Display
|
||||
.attdef-attmode-all = Display All Attributes
|
||||
.attdef-attmode-none = Hide All Attributes
|
||||
.attdef-edit-attribute = Edit Attribute
|
||||
.attdef-multiline-editor = Multiline editor
|
||||
.attdef-tag-empty = The tag cannot be empty.
|
||||
.attdef-tag-spaces = The tag may not contain spaces.
|
||||
.attdef-positive = Value must be positive and nonzero.
|
||||
.attdef-angle = Requires valid numeric angle or second point.
|
||||
model =
|
||||
.create = Létrehozás
|
||||
.boolean = Logikai műveletek
|
||||
|
||||
@@ -4031,6 +4031,15 @@ insert =
|
||||
.attdef-define-attributes = Define Attributes
|
||||
.attdef-manage-attributes = Manage Attributes
|
||||
.attdef-set-base-point = Set Base Point
|
||||
.attdef-attmode-retain = Retain Attribute Display
|
||||
.attdef-attmode-all = Display All Attributes
|
||||
.attdef-attmode-none = Hide All Attributes
|
||||
.attdef-edit-attribute = Edit Attribute
|
||||
.attdef-multiline-editor = Multiline editor
|
||||
.attdef-tag-empty = The tag cannot be empty.
|
||||
.attdef-tag-spaces = The tag may not contain spaces.
|
||||
.attdef-positive = Value must be positive and nonzero.
|
||||
.attdef-angle = Requires valid numeric angle or second point.
|
||||
model =
|
||||
.create = Crea
|
||||
.boolean = Operazioni booleane
|
||||
|
||||
@@ -4020,6 +4020,15 @@ insert =
|
||||
.attdef-define-attributes = Define Attributes
|
||||
.attdef-manage-attributes = Manage Attributes
|
||||
.attdef-set-base-point = Set Base Point
|
||||
.attdef-attmode-retain = Retain Attribute Display
|
||||
.attdef-attmode-all = Display All Attributes
|
||||
.attdef-attmode-none = Hide All Attributes
|
||||
.attdef-edit-attribute = Edit Attribute
|
||||
.attdef-multiline-editor = Multiline editor
|
||||
.attdef-tag-empty = The tag cannot be empty.
|
||||
.attdef-tag-spaces = The tag may not contain spaces.
|
||||
.attdef-positive = Value must be positive and nonzero.
|
||||
.attdef-angle = Requires valid numeric angle or second point.
|
||||
model =
|
||||
.create = 作成
|
||||
.boolean = ブール演算
|
||||
|
||||
@@ -4031,6 +4031,15 @@ insert =
|
||||
.attdef-define-attributes = Define Attributes
|
||||
.attdef-manage-attributes = Manage Attributes
|
||||
.attdef-set-base-point = Set Base Point
|
||||
.attdef-attmode-retain = Retain Attribute Display
|
||||
.attdef-attmode-all = Display All Attributes
|
||||
.attdef-attmode-none = Hide All Attributes
|
||||
.attdef-edit-attribute = Edit Attribute
|
||||
.attdef-multiline-editor = Multiline editor
|
||||
.attdef-tag-empty = The tag cannot be empty.
|
||||
.attdef-tag-spaces = The tag may not contain spaces.
|
||||
.attdef-positive = Value must be positive and nonzero.
|
||||
.attdef-angle = Requires valid numeric angle or second point.
|
||||
model =
|
||||
.create = 생성
|
||||
.boolean = 불리언 연산
|
||||
|
||||
@@ -4030,6 +4030,15 @@ insert =
|
||||
.attdef-define-attributes = Define Attributes
|
||||
.attdef-manage-attributes = Manage Attributes
|
||||
.attdef-set-base-point = Set Base Point
|
||||
.attdef-attmode-retain = Retain Attribute Display
|
||||
.attdef-attmode-all = Display All Attributes
|
||||
.attdef-attmode-none = Hide All Attributes
|
||||
.attdef-edit-attribute = Edit Attribute
|
||||
.attdef-multiline-editor = Multiline editor
|
||||
.attdef-tag-empty = The tag cannot be empty.
|
||||
.attdef-tag-spaces = The tag may not contain spaces.
|
||||
.attdef-positive = Value must be positive and nonzero.
|
||||
.attdef-angle = Requires valid numeric angle or second point.
|
||||
model =
|
||||
.create = Maken
|
||||
.boolean = Booleaanse bewerkingen
|
||||
|
||||
@@ -4031,6 +4031,15 @@ insert =
|
||||
.attdef-define-attributes = Define Attributes
|
||||
.attdef-manage-attributes = Manage Attributes
|
||||
.attdef-set-base-point = Set Base Point
|
||||
.attdef-attmode-retain = Retain Attribute Display
|
||||
.attdef-attmode-all = Display All Attributes
|
||||
.attdef-attmode-none = Hide All Attributes
|
||||
.attdef-edit-attribute = Edit Attribute
|
||||
.attdef-multiline-editor = Multiline editor
|
||||
.attdef-tag-empty = The tag cannot be empty.
|
||||
.attdef-tag-spaces = The tag may not contain spaces.
|
||||
.attdef-positive = Value must be positive and nonzero.
|
||||
.attdef-angle = Requires valid numeric angle or second point.
|
||||
model =
|
||||
.create = Utwórz
|
||||
.boolean = Operacje boolowskie
|
||||
|
||||
@@ -4032,6 +4032,15 @@ insert =
|
||||
.attdef-define-attributes = Define Attributes
|
||||
.attdef-manage-attributes = Manage Attributes
|
||||
.attdef-set-base-point = Set Base Point
|
||||
.attdef-attmode-retain = Retain Attribute Display
|
||||
.attdef-attmode-all = Display All Attributes
|
||||
.attdef-attmode-none = Hide All Attributes
|
||||
.attdef-edit-attribute = Edit Attribute
|
||||
.attdef-multiline-editor = Multiline editor
|
||||
.attdef-tag-empty = The tag cannot be empty.
|
||||
.attdef-tag-spaces = The tag may not contain spaces.
|
||||
.attdef-positive = Value must be positive and nonzero.
|
||||
.attdef-angle = Requires valid numeric angle or second point.
|
||||
model =
|
||||
.create = Criar
|
||||
.boolean = Operações booleanas
|
||||
|
||||
@@ -4033,6 +4033,15 @@ insert =
|
||||
.attdef-define-attributes = Define Attributes
|
||||
.attdef-manage-attributes = Manage Attributes
|
||||
.attdef-set-base-point = Set Base Point
|
||||
.attdef-attmode-retain = Retain Attribute Display
|
||||
.attdef-attmode-all = Display All Attributes
|
||||
.attdef-attmode-none = Hide All Attributes
|
||||
.attdef-edit-attribute = Edit Attribute
|
||||
.attdef-multiline-editor = Multiline editor
|
||||
.attdef-tag-empty = The tag cannot be empty.
|
||||
.attdef-tag-spaces = The tag may not contain spaces.
|
||||
.attdef-positive = Value must be positive and nonzero.
|
||||
.attdef-angle = Requires valid numeric angle or second point.
|
||||
model =
|
||||
.create = Создание
|
||||
.boolean = Булевы операции
|
||||
|
||||
@@ -3992,6 +3992,15 @@ insert =
|
||||
.attdef-define-attributes = Öznitelik Tanımla
|
||||
.attdef-manage-attributes = Öznitelikleri Yönet
|
||||
.attdef-set-base-point = Taban Noktası Belirle
|
||||
.attdef-attmode-retain = Öznitelik görünümünü koru
|
||||
.attdef-attmode-all = Tüm öznitelikleri göster
|
||||
.attdef-attmode-none = Tüm öznitelikleri gizle
|
||||
.attdef-edit-attribute = Öznitelik Düzenle
|
||||
.attdef-multiline-editor = Çok satırlı düzenleyici
|
||||
.attdef-tag-empty = Etiket boş olamaz.
|
||||
.attdef-tag-spaces = Etiket boşluk içeremez.
|
||||
.attdef-positive = Değer pozitif ve sıfırdan farklı olmalı.
|
||||
.attdef-angle = Geçerli bir sayısal açı veya ikinci nokta gerekir.
|
||||
model =
|
||||
.create = Oluştur
|
||||
.boolean = Boole işlemleri
|
||||
|
||||
@@ -4015,6 +4015,15 @@ insert =
|
||||
.attdef-define-attributes = Define Attributes
|
||||
.attdef-manage-attributes = Manage Attributes
|
||||
.attdef-set-base-point = Set Base Point
|
||||
.attdef-attmode-retain = Retain Attribute Display
|
||||
.attdef-attmode-all = Display All Attributes
|
||||
.attdef-attmode-none = Hide All Attributes
|
||||
.attdef-edit-attribute = Edit Attribute
|
||||
.attdef-multiline-editor = Multiline editor
|
||||
.attdef-tag-empty = The tag cannot be empty.
|
||||
.attdef-tag-spaces = The tag may not contain spaces.
|
||||
.attdef-positive = Value must be positive and nonzero.
|
||||
.attdef-angle = Requires valid numeric angle or second point.
|
||||
model =
|
||||
.create = 创建
|
||||
.boolean = 布尔运算
|
||||
|
||||
@@ -4027,6 +4027,15 @@ insert =
|
||||
.attdef-define-attributes = Define Attributes
|
||||
.attdef-manage-attributes = Manage Attributes
|
||||
.attdef-set-base-point = Set Base Point
|
||||
.attdef-attmode-retain = Retain Attribute Display
|
||||
.attdef-attmode-all = Display All Attributes
|
||||
.attdef-attmode-none = Hide All Attributes
|
||||
.attdef-edit-attribute = Edit Attribute
|
||||
.attdef-multiline-editor = Multiline editor
|
||||
.attdef-tag-empty = The tag cannot be empty.
|
||||
.attdef-tag-spaces = The tag may not contain spaces.
|
||||
.attdef-positive = Value must be positive and nonzero.
|
||||
.attdef-angle = Requires valid numeric angle or second point.
|
||||
model =
|
||||
.create = 建立
|
||||
.boolean = 布林運算
|
||||
|
||||
@@ -46,6 +46,19 @@ impl OpenCADStudio {
|
||||
self.push_ucs_to_cmd(i);
|
||||
Some(Task::none())
|
||||
}
|
||||
"ATTMODE0" => self.dispatch_draw("ATTDISP OFF", i),
|
||||
"ATTMODE1" => self.dispatch_draw("ATTDISP NORMAL", i),
|
||||
"ATTMODE2" => self.dispatch_draw("ATTDISP ON", i),
|
||||
"_ATTDEF_VALUE" => {
|
||||
let value = attdef::session().editor_value.take();
|
||||
if let Some(state) = self.attdef_dialog.as_mut() {
|
||||
if let Some(value) = value {
|
||||
state.default = value;
|
||||
}
|
||||
self.active_modal = Some(crate::app::ModalKind::AttDef);
|
||||
}
|
||||
Some(Task::none())
|
||||
}
|
||||
cmd if cmd == "_ATTDEF_PICKED" || cmd.starts_with("_ATTDEF_PICKED ") => {
|
||||
let mut parts = cmd.split_whitespace().skip(1);
|
||||
if let (Some(kind), Some(value), Some(state)) =
|
||||
@@ -116,10 +129,11 @@ impl OpenCADStudio {
|
||||
height: short(defaults.height),
|
||||
rotation: "0".into(),
|
||||
width: "0".into(),
|
||||
on_screen: true,
|
||||
on_screen: session.on_screen,
|
||||
coords: ["0".into(), "0".into(), "0".into()],
|
||||
align_below: false,
|
||||
can_align_below: session.last.is_some(),
|
||||
error: None,
|
||||
});
|
||||
drop(session);
|
||||
self.tabs[i].active_cmd = None;
|
||||
@@ -139,6 +153,7 @@ impl OpenCADStudio {
|
||||
prompt: a.prompt.clone(),
|
||||
default: a.default_value.clone(),
|
||||
constant: a.flags.constant,
|
||||
error: None,
|
||||
});
|
||||
self.active_modal = Some(crate::app::ModalKind::AttDefEdit);
|
||||
}
|
||||
@@ -155,6 +170,7 @@ impl OpenCADStudio {
|
||||
.as_ref(),
|
||||
),
|
||||
AttdefDialogMsg::EditOk => return self.attdef_edit_ok(i),
|
||||
AttdefDialogMsg::DismissError => edit.error = None,
|
||||
_ => {}
|
||||
}
|
||||
return Task::none();
|
||||
@@ -201,30 +217,50 @@ impl OpenCADStudio {
|
||||
.as_ref(),
|
||||
),
|
||||
AttdefDialogMsg::Ok => return self.attdef_dialog_ok(i),
|
||||
AttdefDialogMsg::DismissError => state.error = None,
|
||||
AttdefDialogMsg::EditValue => {
|
||||
// The dialog waits while the multi-line editor collects the value.
|
||||
let initial = state.default.clone();
|
||||
let height = state.height.trim().parse::<f64>().ok().filter(|h| *h > 0.0).unwrap_or(2.5);
|
||||
self.active_modal = None;
|
||||
attdef::session().editor_value = None;
|
||||
self.tabs[i].active_cmd = Some(Box::new(attdef::AttdefValueCommand));
|
||||
let pos = self.tabs[i].scene.camera.borrow().target;
|
||||
return self.apply_cmd_result(crate::command::CmdResult::SuspendForMTextInput {
|
||||
pos,
|
||||
initial,
|
||||
height,
|
||||
});
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
Task::none()
|
||||
}
|
||||
|
||||
/// Show a validation message in the dialog; it stays open.
|
||||
fn attdef_dialog_error(&mut self, error: &str) -> Task<Message> {
|
||||
if let Some(state) = self.attdef_dialog.as_mut() {
|
||||
state.error = Some(crate::t!(error).into_owned());
|
||||
}
|
||||
Task::none()
|
||||
}
|
||||
|
||||
fn attdef_dialog_ok(&mut self, i: usize) -> Task<Message> {
|
||||
let Some(state) = self.attdef_dialog.clone() else {
|
||||
return Task::none();
|
||||
};
|
||||
if let Some(error) = tag_error(&state.tag) {
|
||||
self.command_line.push_error(error);
|
||||
return Task::none();
|
||||
return self.attdef_dialog_error(error);
|
||||
}
|
||||
let number = |s: &str| s.trim().parse::<f64>().ok().filter(|v| v.is_finite());
|
||||
let height = match number(&state.height) {
|
||||
Some(v) if v > 0.0 => v,
|
||||
_ => {
|
||||
self.command_line.push_error("Value must be positive and nonzero.");
|
||||
return Task::none();
|
||||
return self.attdef_dialog_error("Value must be positive and nonzero.");
|
||||
}
|
||||
};
|
||||
let Some(rotation) = number(&state.rotation) else {
|
||||
self.command_line.push_error("Requires valid numeric angle or second point.");
|
||||
return Task::none();
|
||||
return self.attdef_dialog_error("Requires valid numeric angle or second point.");
|
||||
};
|
||||
let width = number(&state.width).unwrap_or(0.0).max(0.0);
|
||||
let defaults =
|
||||
@@ -250,6 +286,7 @@ impl OpenCADStudio {
|
||||
let mut session = attdef::session();
|
||||
session.aflags = spec.aflags;
|
||||
session.annotative = spec.annotative;
|
||||
session.on_screen = state.on_screen;
|
||||
}
|
||||
self.reset_command_start_state(i);
|
||||
if state.align_below {
|
||||
@@ -288,7 +325,9 @@ impl OpenCADStudio {
|
||||
return Task::none();
|
||||
};
|
||||
if let Some(error) = tag_error(&state.tag) {
|
||||
self.command_line.push_error(error);
|
||||
if let Some(edit) = self.attdef_edit.as_mut() {
|
||||
edit.error = Some(crate::t!(error).into_owned());
|
||||
}
|
||||
return Task::none();
|
||||
}
|
||||
self.attdef_edit = None;
|
||||
|
||||
+19
-55
@@ -183,68 +183,32 @@ impl OpenCADStudio {
|
||||
}
|
||||
}
|
||||
|
||||
// ATTDISP — control attribute display visibility.
|
||||
// ATTDISP ON — make all AttributeDefinitions visible
|
||||
// ATTDISP OFF — make all AttributeDefinitions invisible
|
||||
// ATTDISP NORMAL — restore: show only those without the invisible flag
|
||||
// ATTDISP sets ATTMODE: 0 hides every attribute, 1 shows the
|
||||
// visible ones, 2 shows them all. The definitions are not touched.
|
||||
"ATTDISP" => {
|
||||
use crate::command::KeywordCommand;
|
||||
let c = KeywordCommand::new(
|
||||
"ATTDISP",
|
||||
"ATTDISP attribute display [On / Off / Normal]:",
|
||||
vec![
|
||||
("On", "ON", None),
|
||||
("Off", "OFF", None),
|
||||
("Normal", "NORMAL", None),
|
||||
],
|
||||
let command = crate::modules::draw::draw::attdef::AttdispCommand::new(
|
||||
self.tabs[i].scene.document.header.attribute_visibility,
|
||||
);
|
||||
self.command_line.push_info(&c.prompt());
|
||||
self.tabs[i].active_cmd = Some(Box::new(c));
|
||||
self.command_line.push_info(&command.prompt());
|
||||
self.tabs[i].active_cmd = Some(Box::new(command));
|
||||
}
|
||||
cmd if cmd.starts_with("ATTDISP ") => {
|
||||
let sub = cmd.split_whitespace().nth(1).unwrap_or("").to_uppercase();
|
||||
match sub.as_str() {
|
||||
"ON" | "OFF" | "NORMAL" => {
|
||||
let handles: Vec<_> = self.tabs[i]
|
||||
.scene
|
||||
.document
|
||||
.entities()
|
||||
.filter_map(|entity| {
|
||||
matches!(entity, codec::EntityType::AttributeDefinition(_))
|
||||
.then_some(entity.common().handle)
|
||||
})
|
||||
.filter(|handle| !self.tabs[i].scene.is_layer_locked(*handle))
|
||||
.collect();
|
||||
self.push_undo_snapshot(i, "ATTDISP");
|
||||
let mut count = 0usize;
|
||||
for handle in handles {
|
||||
if let Some(codec::EntityType::AttributeDefinition(ad)) =
|
||||
self.tabs[i].scene.document.get_entity_mut(handle)
|
||||
{
|
||||
match sub.as_str() {
|
||||
"ON" => {
|
||||
ad.flags.invisible = false;
|
||||
count += 1;
|
||||
}
|
||||
"OFF" => {
|
||||
ad.flags.invisible = true;
|
||||
count += 1;
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
}
|
||||
self.tabs[i].dirty = true;
|
||||
self.command_line.push_output(
|
||||
crate::tf!("ATTDISP {sub}: {count} attribute definition(s) updated.")
|
||||
.as_ref(),
|
||||
);
|
||||
}
|
||||
let mode = match cmd[8..].trim().to_ascii_uppercase().as_str() {
|
||||
"OFF" => 0,
|
||||
"ON" => 2,
|
||||
"NORMAL" | "N" => 1,
|
||||
_ => {
|
||||
self.command_line
|
||||
.push_info(crate::t!("Usage: ATTDISP ON | OFF | NORMAL").as_ref());
|
||||
self.command_line.push_error("Invalid option keyword.");
|
||||
return Some(Task::none());
|
||||
}
|
||||
};
|
||||
if self.tabs[i].scene.document.header.attribute_visibility != mode {
|
||||
self.push_undo_snapshot(i, "ATTDISP");
|
||||
self.tabs[i].scene.document.header.attribute_visibility = mode;
|
||||
self.tabs[i].dirty = true;
|
||||
self.tabs[i].scene.bump_geometry();
|
||||
}
|
||||
self.command_line.push_output("Regenerating model.");
|
||||
}
|
||||
|
||||
"DONUT" => {
|
||||
|
||||
@@ -666,6 +666,9 @@ inventory::submit!(crate::command::CommandRegistration {
|
||||
"POINTCLOUDPOINTMAXLEGACY",
|
||||
"XCLIPFRAME",
|
||||
"WIPEOUTFRAME",
|
||||
"ATTMODE0",
|
||||
"ATTMODE1",
|
||||
"ATTMODE2",
|
||||
"FRAMES0",
|
||||
"FRAMES1",
|
||||
"FRAMES3",
|
||||
|
||||
@@ -344,6 +344,12 @@ impl OpenCADStudio {
|
||||
_ => "FRAMES3",
|
||||
};
|
||||
self.ribbon.set_dropdown_current("FRAMES_DROPDOWN", current);
|
||||
let attmode = match tab.scene.document.header.attribute_visibility {
|
||||
0 => "ATTMODE0",
|
||||
2 => "ATTMODE2",
|
||||
_ => "ATTMODE1",
|
||||
};
|
||||
self.ribbon.set_dropdown_current("ATTMODE_DROPDOWN", attmode);
|
||||
}
|
||||
|
||||
fn update_message(&mut self, msg: Message) -> Task<Message> {
|
||||
|
||||
@@ -175,6 +175,15 @@ pub(super) fn message_attribute(source: &str) -> Option<(&'static str, &'static
|
||||
"Define Attributes" => Some(("insert", "attdef-define-attributes")),
|
||||
"Manage Attributes" => Some(("insert", "attdef-manage-attributes")),
|
||||
"Set Base Point" => Some(("insert", "attdef-set-base-point")),
|
||||
"Retain Attribute Display" => Some(("insert", "attdef-attmode-retain")),
|
||||
"Display All Attributes" => Some(("insert", "attdef-attmode-all")),
|
||||
"Hide All Attributes" => Some(("insert", "attdef-attmode-none")),
|
||||
"Edit Attribute" => Some(("insert", "attdef-edit-attribute")),
|
||||
"Multiline editor" => Some(("insert", "attdef-multiline-editor")),
|
||||
"The tag cannot be empty." => Some(("insert", "attdef-tag-empty")),
|
||||
"The tag may not contain spaces." => Some(("insert", "attdef-tag-spaces")),
|
||||
"Value must be positive and nonzero." => Some(("insert", "attdef-positive")),
|
||||
"Requires valid numeric angle or second point." => Some(("insert", "attdef-angle")),
|
||||
"Stylization" => Some(("properties", "stylization")),
|
||||
"Color scheme" => Some(("properties", "color-scheme")),
|
||||
"Scan Colors" => Some(("properties", "scan-colors")),
|
||||
|
||||
@@ -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())
|
||||
}
|
||||
}
|
||||
@@ -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) ─────
|
||||
|
||||
@@ -34,6 +34,9 @@ pub enum AttdefDialogMsg {
|
||||
PickHeight,
|
||||
PickRotation,
|
||||
PickWidth,
|
||||
/// Edit the default value in the multi-line text editor.
|
||||
EditValue,
|
||||
DismissError,
|
||||
Ok,
|
||||
Help,
|
||||
EditTag(String),
|
||||
@@ -71,6 +74,8 @@ pub struct AttdefDialogState {
|
||||
pub align_below: bool,
|
||||
/// A definition was placed before in this session.
|
||||
pub can_align_below: bool,
|
||||
/// Validation message shown above the buttons.
|
||||
pub error: Option<String>,
|
||||
}
|
||||
|
||||
/// The Edit Attribute Definition dialog's fields.
|
||||
@@ -81,6 +86,7 @@ pub struct AttdefEditState {
|
||||
pub prompt: String,
|
||||
pub default: String,
|
||||
pub constant: bool,
|
||||
pub error: Option<String>,
|
||||
}
|
||||
|
||||
fn msg(m: AttdefDialogMsg) -> Message {
|
||||
@@ -131,6 +137,36 @@ fn mode<'a>(label: String, on: bool, bit: u8) -> Element<'a, Message> {
|
||||
.into()
|
||||
}
|
||||
|
||||
/// The validation message band, as in the Write Block dialog.
|
||||
fn error_band<'a>(error: &Option<String>) -> Option<Element<'a, Message>> {
|
||||
let error = error.clone()?;
|
||||
Some(
|
||||
container(
|
||||
row![
|
||||
crate::ui::icons::semantic(ICON_WARN, 14.0),
|
||||
text(error).size(11),
|
||||
Space::new().width(Fill),
|
||||
button(text("×").size(12))
|
||||
.on_press(msg(AttdefDialogMsg::DismissError))
|
||||
.style(button_style(false))
|
||||
.padding([1, 6]),
|
||||
]
|
||||
.spacing(8)
|
||||
.align_y(iced::Center),
|
||||
)
|
||||
.padding([6, 10])
|
||||
.width(Fill)
|
||||
.style(|theme: &iced::Theme| container::Style {
|
||||
background: Some(iced::Background::Color(theme.palette().danger.base.color.scale_alpha(0.18))),
|
||||
border: iced::Border { radius: 4.0.into(), ..Default::default() },
|
||||
..Default::default()
|
||||
})
|
||||
.into(),
|
||||
)
|
||||
}
|
||||
|
||||
static ICON_WARN: &[u8] = include_bytes!("../../../assets/icons/ui/warning_triangle.svg");
|
||||
|
||||
fn footer<'a>(action: std::borrow::Cow<'static, str>, ok: AttdefDialogMsg) -> Element<'a, Message> {
|
||||
row![
|
||||
button(text("?").size(12))
|
||||
@@ -194,11 +230,18 @@ pub fn view<'a>(state: &'a AttdefDialogState, sizing: crate::ui::modal::ModalSiz
|
||||
),
|
||||
labelled(
|
||||
if constant { t!("Value") } else { t!("Default") }.into_owned(),
|
||||
row![
|
||||
input(&state.default, true, AttdefDialogMsg::Default),
|
||||
{
|
||||
let mut value = row![input(&state.default, true, AttdefDialogMsg::Default)].spacing(6);
|
||||
if multiline {
|
||||
value = value.push(pick(
|
||||
"…",
|
||||
t!("Multiline editor").into_owned(),
|
||||
Some(AttdefDialogMsg::EditValue),
|
||||
));
|
||||
}
|
||||
// No field picker in this application yet.
|
||||
pick("ƒ", t!("Insert field").into_owned(), None),
|
||||
]
|
||||
value.push(pick("ƒ", t!("Insert field").into_owned(), None))
|
||||
}
|
||||
.spacing(6)
|
||||
.into(),
|
||||
true
|
||||
@@ -295,7 +338,12 @@ pub fn view<'a>(state: &'a AttdefDialogState, sizing: crate::ui::modal::ModalSiz
|
||||
column![attribute, settings].spacing(10).width(Fill),
|
||||
]
|
||||
.spacing(10);
|
||||
column![body, align, footer(t!("Define"), AttdefDialogMsg::Ok)]
|
||||
let mut content = column![body, align];
|
||||
if let Some(band) = error_band(&state.error) {
|
||||
content = content.push(band);
|
||||
}
|
||||
content
|
||||
.push(footer(t!("Define"), AttdefDialogMsg::Ok))
|
||||
.spacing(10)
|
||||
.padding([10, 12])
|
||||
.width(sizing.width)
|
||||
@@ -331,7 +379,12 @@ pub fn view_edit<'a>(state: &'a AttdefEditState, sizing: crate::ui::modal::Modal
|
||||
]
|
||||
.spacing(8),
|
||||
);
|
||||
column![content, footer(t!("Apply"), AttdefDialogMsg::EditOk)]
|
||||
let mut content = column![content];
|
||||
if let Some(band) = error_band(&state.error) {
|
||||
content = content.push(band);
|
||||
}
|
||||
content
|
||||
.push(footer(t!("Apply"), AttdefDialogMsg::EditOk))
|
||||
.spacing(10)
|
||||
.padding([10, 12])
|
||||
.width(sizing.width)
|
||||
|
||||
Reference in new issue
Block a user