forked from 1b-agent/opencadstudio-upstream
Complete geometric tolerance workflow and properties
This commit is contained in:
1 parent
8c61d89b1e
commit
de294447a9
14 files changed
+1037
-135
No files matched your search
@@ -594,10 +594,7 @@ impl OpenCADStudio {
|
||||
}
|
||||
|
||||
"TOLERANCE" => {
|
||||
use crate::modules::annotate::tolerance_cmd::ToleranceCommand;
|
||||
let cmd = ToleranceCommand::new();
|
||||
self.command_line.push_info(&cmd.prompt());
|
||||
self.tabs[i].active_cmd = Some(Box::new(cmd));
|
||||
self.open_tolerance_dialog(None);
|
||||
}
|
||||
|
||||
"TABLE" => {
|
||||
|
||||
@@ -22,6 +22,7 @@ pub(crate) mod settings;
|
||||
mod shortcuts;
|
||||
mod style_ops;
|
||||
mod text_inline;
|
||||
mod tolerance_dialog;
|
||||
mod update;
|
||||
mod view;
|
||||
mod visibility;
|
||||
@@ -399,6 +400,8 @@ pub(super) struct OpenCADStudio {
|
||||
layer_translator: Option<crate::ui::window::layer_translator::State>,
|
||||
/// Working copy of the Drawing Units dialog; `None` while it is closed.
|
||||
drawing_units: Option<crate::ui::window::drawing_units::State>,
|
||||
/// Working copy of the structured feature-control-frame editor.
|
||||
geometric_tolerance: Option<crate::ui::window::geometric_tolerance::State>,
|
||||
/// PICKDRAG (#226): false (default) = press-drag lassoes; true =
|
||||
/// press-drag draws a rectangle marquee.
|
||||
pick_drag_rect: bool,
|
||||
@@ -1588,6 +1591,7 @@ pub enum ModalKind {
|
||||
LayerStateManager,
|
||||
LayerTranslator,
|
||||
DrawingUnits,
|
||||
GeometricTolerance,
|
||||
DraftingSettings,
|
||||
LayerStateEditor,
|
||||
Plot,
|
||||
@@ -2318,6 +2322,14 @@ pub enum Message {
|
||||
DrawingUnitsField(crate::ui::window::drawing_units::Field),
|
||||
/// Drawing Units OK — write the working copy into the drawing.
|
||||
DrawingUnitsApply,
|
||||
/// One structured feature-control-frame field changed.
|
||||
ToleranceDialogField(crate::ui::window::geometric_tolerance::Field),
|
||||
/// One structured feature-control-frame option changed.
|
||||
ToleranceDialogToggle(crate::ui::window::geometric_tolerance::Toggle),
|
||||
/// Apply edits without closing the structured editor.
|
||||
ToleranceDialogApply,
|
||||
/// Commit edits or continue to insertion-point placement.
|
||||
ToleranceDialogOk,
|
||||
/// Toggle the Isolate pill's action menu open/closed.
|
||||
ToggleIsolatePopup,
|
||||
/// Close the Isolate action menu.
|
||||
@@ -3145,6 +3157,7 @@ impl OpenCADStudio {
|
||||
last_layer_translation: None,
|
||||
layer_translator: None,
|
||||
drawing_units: None,
|
||||
geometric_tolerance: None,
|
||||
pick_drag_rect: false,
|
||||
perf_hud: false,
|
||||
cycle_candidates: None,
|
||||
|
||||
+71
-4
@@ -2,6 +2,7 @@ use super::helpers::{entity_type_key, entity_type_label, title_case_word};
|
||||
use super::{OpenCADStudio, VARIES_LABEL};
|
||||
use crate::io::linetypes;
|
||||
use crate::scene::view::dispatch;
|
||||
use crate::scene::model::object::PropValue;
|
||||
use crate::ui;
|
||||
use crate::t;
|
||||
use acadrust::types::{Transform, Vector3};
|
||||
@@ -1310,11 +1311,77 @@ impl OpenCADStudio {
|
||||
// Feature-control frame: FCF text style is the dimension
|
||||
// style's DIMTXSTY.
|
||||
acadrust::EntityType::Tolerance(tol) => {
|
||||
if let Some(ds) = find_dim_style(doc, &tol.dimension_style_name) {
|
||||
if !ds.dimtxsty.is_empty() {
|
||||
set_row(&mut sections, "tol_text_style", ds.dimtxsty.clone());
|
||||
}
|
||||
use crate::entities::dim_override as dov;
|
||||
let style = crate::entities::tolerance::resolve_dim_style(tol, doc);
|
||||
let style_name = style
|
||||
.map(|entry| entry.name.clone())
|
||||
.unwrap_or_else(|| {
|
||||
if tol.dimension_style_name.trim().is_empty() {
|
||||
"Standard".to_string()
|
||||
} else {
|
||||
tol.dimension_style_name.clone()
|
||||
}
|
||||
});
|
||||
let mut dim_style_names: Vec<String> = doc
|
||||
.dim_styles
|
||||
.iter()
|
||||
.map(|entry| entry.name.clone())
|
||||
.filter(|name| !name.trim().is_empty())
|
||||
.collect();
|
||||
if !dim_style_names
|
||||
.iter()
|
||||
.any(|name| name.eq_ignore_ascii_case(&style_name))
|
||||
{
|
||||
dim_style_names.push(style_name.clone());
|
||||
}
|
||||
set_row_value(
|
||||
&mut sections,
|
||||
"tol_dim_style",
|
||||
PropValue::Choice {
|
||||
selected: style_name,
|
||||
options: dim_style_names,
|
||||
},
|
||||
);
|
||||
|
||||
let text_style_name = dov::handle(
|
||||
&tol.common.extended_data,
|
||||
dov::DIMTXSTY,
|
||||
)
|
||||
.and_then(|handle| {
|
||||
doc.text_styles
|
||||
.iter()
|
||||
.find(|entry| entry.handle == handle)
|
||||
})
|
||||
.map(|entry| entry.name.clone())
|
||||
.or_else(|| style.map(|entry| entry.dimtxsty.clone()))
|
||||
.unwrap_or_else(|| "Standard".to_string());
|
||||
let mut names = text_style_names.clone();
|
||||
if !names
|
||||
.iter()
|
||||
.any(|name| name.eq_ignore_ascii_case(&text_style_name))
|
||||
{
|
||||
names.push(text_style_name.clone());
|
||||
}
|
||||
set_row_value(
|
||||
&mut sections,
|
||||
"tol_text_style",
|
||||
PropValue::Choice {
|
||||
selected: text_style_name,
|
||||
options: names,
|
||||
},
|
||||
);
|
||||
|
||||
let height = dov::real(
|
||||
&tol.common.extended_data,
|
||||
dov::DIMTXT,
|
||||
)
|
||||
.or_else(|| style.map(|entry| entry.dimtxt))
|
||||
.unwrap_or(tol.text_height);
|
||||
set_row_value(
|
||||
&mut sections,
|
||||
"tol_text_height",
|
||||
PropValue::EditText(format!("{height:.4}")),
|
||||
);
|
||||
}
|
||||
// MultiLeader: max points + segment-angle constraints
|
||||
// are MLeaderStyle settings, not stored on the entity.
|
||||
|
||||
@@ -145,6 +145,13 @@ impl super::OpenCADStudio {
|
||||
if self.tabs[i].scene.is_layer_locked(target) {
|
||||
return iced::Task::none();
|
||||
}
|
||||
if matches!(
|
||||
self.tabs[i].scene.document.get_entity(target),
|
||||
Some(EntityType::Tolerance(_))
|
||||
) {
|
||||
self.open_tolerance_dialog(Some(target));
|
||||
return iced::Task::none();
|
||||
}
|
||||
// Snapshot what we need before borrowing `self` mutably to open.
|
||||
let Some(entity) = self.tabs[i].scene.document.get_entity(target) else {
|
||||
return iced::Task::none();
|
||||
|
||||
@@ -0,0 +1,88 @@
|
||||
use acadrust::{EntityType, Handle};
|
||||
|
||||
impl super::OpenCADStudio {
|
||||
pub(super) fn open_tolerance_dialog(&mut self, editing: Option<Handle>) {
|
||||
let i = self.active_tab;
|
||||
if editing.is_some_and(|handle| self.tabs[i].scene.is_layer_locked(handle)) {
|
||||
return;
|
||||
}
|
||||
let text = editing
|
||||
.and_then(|handle| self.tabs[i].scene.document.get_entity(handle))
|
||||
.and_then(|entity| match entity {
|
||||
EntityType::Tolerance(tolerance) => Some(tolerance.text.as_str()),
|
||||
_ => None,
|
||||
})
|
||||
.unwrap_or_default();
|
||||
self.geometric_tolerance = Some(
|
||||
crate::ui::window::geometric_tolerance::State::from_text(editing, text),
|
||||
);
|
||||
self.active_modal = Some(super::ModalKind::GeometricTolerance);
|
||||
self.modal_offset = iced::Vector::ZERO;
|
||||
self.modal_resize = iced::Vector::ZERO;
|
||||
self.modal_content_size = None;
|
||||
self.modal_drag_last = None;
|
||||
self.modal_dragging = false;
|
||||
self.modal_resizing = false;
|
||||
}
|
||||
|
||||
pub(super) fn apply_tolerance_dialog_edit(&mut self) -> bool {
|
||||
let Some(state) = self.geometric_tolerance.as_ref() else {
|
||||
return false;
|
||||
};
|
||||
let Some(handle) = state.editing else {
|
||||
return false;
|
||||
};
|
||||
if !state.is_valid() || self.tabs[self.active_tab].scene.is_layer_locked(handle) {
|
||||
return false;
|
||||
}
|
||||
let text = state.to_text();
|
||||
let i = self.active_tab;
|
||||
let unchanged = self.tabs[i]
|
||||
.scene
|
||||
.document
|
||||
.get_entity(handle)
|
||||
.is_some_and(|entity| {
|
||||
matches!(entity, EntityType::Tolerance(tolerance) if tolerance.text == text)
|
||||
});
|
||||
if unchanged {
|
||||
return true;
|
||||
}
|
||||
self.push_undo_snapshot(i, "TOLERANCE");
|
||||
let Some(EntityType::Tolerance(tolerance)) =
|
||||
self.tabs[i].scene.document.get_entity_mut(handle)
|
||||
else {
|
||||
return false;
|
||||
};
|
||||
tolerance.text = text;
|
||||
self.tabs[i]
|
||||
.scene
|
||||
.bump_entities(&[(handle, crate::scene::ChangeKind::Modified)]);
|
||||
self.tabs[i].dirty = true;
|
||||
self.refresh_properties();
|
||||
true
|
||||
}
|
||||
|
||||
pub(super) fn begin_tolerance_placement(&mut self) -> bool {
|
||||
let Some(state) = self.geometric_tolerance.take() else {
|
||||
return false;
|
||||
};
|
||||
if !state.is_valid() || state.editing.is_some() {
|
||||
self.geometric_tolerance = Some(state);
|
||||
return false;
|
||||
}
|
||||
let i = self.active_tab;
|
||||
let mut command =
|
||||
crate::modules::annotate::tolerance_cmd::ToleranceCommand::with_text(state.to_text());
|
||||
use crate::command::CadCommand;
|
||||
let plane = if self.tabs[i].editing_model_space() {
|
||||
self.tabs[i].ucs_xform().working_plane()
|
||||
} else {
|
||||
crate::command::WorkingPlane::default()
|
||||
};
|
||||
command.set_working_plane(plane);
|
||||
self.command_line.push_info(&command.prompt());
|
||||
self.tabs[i].active_cmd = Some(Box::new(command));
|
||||
self.active_modal = None;
|
||||
true
|
||||
}
|
||||
}
|
||||
@@ -1901,7 +1901,73 @@ pub(super) fn on_tab_close(&mut self, idx: usize) -> Task<Message> {
|
||||
}
|
||||
self.push_undo_snapshot(i, "CHPROP");
|
||||
|
||||
if field.starts_with("dim_") {
|
||||
if field == "tol_text_style" {
|
||||
use crate::entities::dim_override as dov;
|
||||
use acadrust::xdata::XDataValue;
|
||||
let style_handle = self.tabs[i]
|
||||
.scene
|
||||
.document
|
||||
.text_styles
|
||||
.iter()
|
||||
.find(|entry| entry.name.eq_ignore_ascii_case(&value))
|
||||
.map(|entry| entry.handle);
|
||||
if let Some(style_handle) = style_handle {
|
||||
for &handle in &handles {
|
||||
if self.tabs[i].scene.is_layer_locked(handle)
|
||||
|| !matches!(
|
||||
self.tabs[i].scene.document.get_entity(handle),
|
||||
Some(acadrust::EntityType::Tolerance(_))
|
||||
)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
dov::set(
|
||||
&mut self.tabs[i].scene.document,
|
||||
handle,
|
||||
dov::DIMTXSTY,
|
||||
Some(XDataValue::Handle(style_handle)),
|
||||
);
|
||||
}
|
||||
}
|
||||
} else if field == "tol_dim_style" {
|
||||
let style = self.tabs[i]
|
||||
.scene
|
||||
.document
|
||||
.dim_styles
|
||||
.iter()
|
||||
.find(|entry| entry.name.eq_ignore_ascii_case(&value))
|
||||
.map(|entry| (entry.handle, entry.name.clone(), entry.annotative));
|
||||
if let Some((style_handle, style_name, annotative)) = style {
|
||||
let scale = self.tabs[i].scene.creation_annotation_scale_handle();
|
||||
for &handle in &handles {
|
||||
if self.tabs[i].scene.is_layer_locked(handle) {
|
||||
continue;
|
||||
}
|
||||
if let Some(acadrust::EntityType::Tolerance(tolerance)) =
|
||||
self.tabs[i].scene.document.get_entity_mut(handle)
|
||||
{
|
||||
tolerance.dimension_style_handle = Some(style_handle);
|
||||
tolerance.dimension_style_name = style_name.clone();
|
||||
} else {
|
||||
continue;
|
||||
}
|
||||
crate::scene::annotative::set_entity_annotative(
|
||||
&mut self.tabs[i].scene.document,
|
||||
handle,
|
||||
annotative,
|
||||
);
|
||||
if annotative {
|
||||
if let Some(scale) = scale {
|
||||
crate::scene::annotative::create_annotation_context(
|
||||
&mut self.tabs[i].scene.document,
|
||||
handle,
|
||||
scale,
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
} else if field.starts_with("dim_") {
|
||||
for &handle in &handles {
|
||||
if self.tabs[i].scene.is_layer_locked(handle) {
|
||||
continue;
|
||||
@@ -2552,6 +2618,27 @@ pub(super) fn on_tab_close(&mut self, idx: usize) -> Task<Message> {
|
||||
continue;
|
||||
}
|
||||
match field {
|
||||
"tol_text_height" => {
|
||||
use crate::entities::dim_override as dov;
|
||||
let trimmed = val.trim();
|
||||
if trimmed.is_empty() {
|
||||
dov::set(
|
||||
&mut self.tabs[i].scene.document,
|
||||
handle,
|
||||
dov::DIMTXT,
|
||||
None,
|
||||
);
|
||||
} else if let Ok(height) = trimmed.parse::<f64>() {
|
||||
if height > 0.0 {
|
||||
dov::set(
|
||||
&mut self.tabs[i].scene.document,
|
||||
handle,
|
||||
dov::DIMTXT,
|
||||
Some(acadrust::xdata::XDataValue::Real(height)),
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
_ if field.starts_with("dim_") => {
|
||||
if matches!(
|
||||
self.tabs[i].scene.document.get_entity(handle),
|
||||
|
||||
@@ -195,6 +195,7 @@ impl OpenCADStudio {
|
||||
self.attr_editor_selected = 0;
|
||||
self.attr_editor_tab = crate::ui::window::attribute_editor::AttrTab::Attribute;
|
||||
}
|
||||
Some(GeometricTolerance) => self.geometric_tolerance = None,
|
||||
// Closing (✕) discards edits made since the last Apply — matching the
|
||||
// style editors. Committing happens only through the Apply button.
|
||||
Some(Aliases) => self.alias_editor_rows.clear(),
|
||||
@@ -3706,6 +3707,40 @@ impl OpenCADStudio {
|
||||
self.refresh_properties();
|
||||
Task::none()
|
||||
}
|
||||
Message::ToleranceDialogField(field) => {
|
||||
if let Some(state) = self.geometric_tolerance.as_mut() {
|
||||
state.apply_field(field);
|
||||
}
|
||||
Task::none()
|
||||
}
|
||||
Message::ToleranceDialogToggle(toggle) => {
|
||||
if let Some(state) = self.geometric_tolerance.as_mut() {
|
||||
state.apply_toggle(toggle);
|
||||
}
|
||||
Task::none()
|
||||
}
|
||||
Message::ToleranceDialogApply => {
|
||||
self.apply_tolerance_dialog_edit();
|
||||
Task::none()
|
||||
}
|
||||
Message::ToleranceDialogOk => {
|
||||
let editing = self
|
||||
.geometric_tolerance
|
||||
.as_ref()
|
||||
.and_then(|state| state.editing)
|
||||
.is_some();
|
||||
if editing {
|
||||
if self.apply_tolerance_dialog_edit() {
|
||||
self.geometric_tolerance = None;
|
||||
self.active_modal = None;
|
||||
self.reset_modal_geometry();
|
||||
}
|
||||
} else {
|
||||
self.begin_tolerance_placement();
|
||||
self.reset_modal_geometry();
|
||||
}
|
||||
Task::none()
|
||||
}
|
||||
Message::SetLinearFormat(code) => {
|
||||
self.units_popup_open = false;
|
||||
let i = self.active_tab;
|
||||
|
||||
@@ -21,6 +21,7 @@ impl OpenCADStudio {
|
||||
Some(K::LayerStateManager) => crate::tr!("modal", "layer-state-manager"),
|
||||
Some(K::LayerTranslator) => crate::t!("Layer Translator").into_owned(),
|
||||
Some(K::DrawingUnits) => crate::t!("Drawing Units").into_owned(),
|
||||
Some(K::GeometricTolerance) => crate::t!("Geometric Tolerance").into_owned(),
|
||||
Some(K::DraftingSettings) => crate::t!("Drafting Settings").into_owned(),
|
||||
Some(K::LayerStateEditor) => crate::tr!("modal", "edit-layer-state"),
|
||||
Some(K::Plot) => crate::tr!("modal", "plot"),
|
||||
@@ -234,6 +235,12 @@ impl OpenCADStudio {
|
||||
crate::ui::window::drawing_units::view_window(state, flow)
|
||||
})
|
||||
}
|
||||
super::super::ModalKind::GeometricTolerance => {
|
||||
let state = self.geometric_tolerance.as_ref()?;
|
||||
sized_flow(ex, 670, 530, |flow| {
|
||||
crate::ui::window::geometric_tolerance::view_window(state, flow)
|
||||
})
|
||||
}
|
||||
super::super::ModalKind::LayerStateManager => {
|
||||
let states = self.tabs[self.active_tab].scene.document.layer_states();
|
||||
sized_flow(
|
||||
|
||||
Reference in new issue
Block a user