forked from 1b-agent/opencadstudio-upstream
1 parent
204c427d57
commit
4fc8446df7
3 files changed
+90
-20
No files matched your search
@@ -202,6 +202,31 @@ pub struct QSelectState {
|
||||
pub error: Option<String>,
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug)]
|
||||
struct QSelectSettings {
|
||||
scope: QSelectScope,
|
||||
type_filter: Option<String>,
|
||||
property_field: Option<String>,
|
||||
operator: QSelectOp,
|
||||
value: String,
|
||||
mode: QSelectMode,
|
||||
append: bool,
|
||||
}
|
||||
|
||||
impl From<&QSelectState> for QSelectSettings {
|
||||
fn from(state: &QSelectState) -> Self {
|
||||
Self {
|
||||
scope: state.scope,
|
||||
type_filter: state.type_filter.clone(),
|
||||
property_field: state.property.as_ref().map(|property| property.field.clone()),
|
||||
operator: state.operator,
|
||||
value: state.value.clone(),
|
||||
mode: state.mode,
|
||||
append: state.append,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, Default)]
|
||||
pub(crate) struct FindReplaceState {
|
||||
pub search: String,
|
||||
@@ -578,6 +603,7 @@ pub(super) struct OpenCADStudio {
|
||||
/// applied via `Message::QSelectApply`; the panel is dismissed on
|
||||
/// Apply / Cancel / Esc / outside-click.
|
||||
qselect: Option<QSelectState>,
|
||||
qselect_settings: Option<QSelectSettings>,
|
||||
/// Show the UCS icon in the bottom-left corner of model space (UCSICON).
|
||||
show_ucs_icon: bool,
|
||||
/// Anchor the UCS icon to the projected UCS origin when it is on-screen,
|
||||
@@ -3252,6 +3278,7 @@ impl OpenCADStudio {
|
||||
grip_text_verts: Vec::new(),
|
||||
grip_text_slide: false,
|
||||
qselect: None,
|
||||
qselect_settings: None,
|
||||
show_ucs_icon: true,
|
||||
ucs_icon_at_origin: true,
|
||||
show_viewcube: true,
|
||||
|
||||
+59
-19
@@ -826,7 +826,8 @@ pub(super) fn on_tab_close(&mut self, idx: usize) -> Task<Message> {
|
||||
}
|
||||
// Cancel layout rename first, then fall through.
|
||||
let i_e = self.active_tab;
|
||||
if self.qselect.take().is_some() {
|
||||
if let Some(state) = self.qselect.take() {
|
||||
self.qselect_settings = Some((&state).into());
|
||||
self.reset_modal_geometry();
|
||||
return Task::none();
|
||||
}
|
||||
@@ -1546,35 +1547,74 @@ pub(super) fn on_tab_close(&mut self, idx: usize) -> Task<Message> {
|
||||
pub(super) fn on_qselect_open(&mut self) -> Task<Message> {
|
||||
let i = self.active_tab;
|
||||
self.tabs[i].scene.selection.borrow_mut().context_menu = None;
|
||||
// Seed the type filter from the first selected entity so a
|
||||
// right-click → Quick Select on a known object opens the
|
||||
// panel pre-tuned to that entity's type. Property defaults
|
||||
// to "(Any property)" so the user immediately picks what
|
||||
// they want to compare.
|
||||
let mut type_filter: Option<String> = None;
|
||||
if let Some(&h) = self.tabs[i].scene.selected.iter().next() {
|
||||
if let Some(e) = self.tabs[i].scene.document.get_entity(h) {
|
||||
use crate::entities::traits::entity_type_name;
|
||||
type_filter = Some(entity_type_name(e).to_string());
|
||||
}
|
||||
}
|
||||
let scope = crate::app::QSelectScope::CurrentSpace;
|
||||
let remembered = self.qselect_settings.clone();
|
||||
let scope = remembered.as_ref().map_or(
|
||||
crate::app::QSelectScope::CurrentSpace,
|
||||
|settings| settings.scope,
|
||||
);
|
||||
let available_types = self.tabs[i].scene.qselect_entity_type_names(scope);
|
||||
let type_filter = if let Some(settings) = remembered.as_ref() {
|
||||
settings
|
||||
.type_filter
|
||||
.as_ref()
|
||||
.filter(|selected| available_types.iter().any(|item| item == *selected))
|
||||
.cloned()
|
||||
} else {
|
||||
self.tabs[i]
|
||||
.scene
|
||||
.selected
|
||||
.iter()
|
||||
.next()
|
||||
.and_then(|handle| self.tabs[i].scene.document.get_entity(*handle))
|
||||
.map(crate::entities::traits::entity_type_name)
|
||||
.map(str::to_string)
|
||||
};
|
||||
let available_properties = self.tabs[i]
|
||||
.scene
|
||||
.qselect_properties(type_filter.as_deref(), scope);
|
||||
let candidate_count = self.tabs[i].scene.qselect_candidate_count(scope);
|
||||
let property = remembered
|
||||
.as_ref()
|
||||
.and_then(|settings| settings.property_field.as_ref())
|
||||
.and_then(|field| {
|
||||
available_properties
|
||||
.iter()
|
||||
.find(|property| property.field == *field)
|
||||
.cloned()
|
||||
});
|
||||
let mut operator = remembered
|
||||
.as_ref()
|
||||
.map_or(crate::app::QSelectOp::Eq, |settings| settings.operator);
|
||||
if matches!(operator, crate::app::QSelectOp::Gt | crate::app::QSelectOp::Lt)
|
||||
&& !property.as_ref().is_some_and(|property| {
|
||||
matches!(property.editor, crate::app::QSelectValueEditor::Number)
|
||||
})
|
||||
{
|
||||
operator = crate::app::QSelectOp::Eq;
|
||||
}
|
||||
let value = remembered.as_ref().map_or_else(String::new, |settings| {
|
||||
if settings.property_field.is_none() || property.is_some() {
|
||||
settings.value.clone()
|
||||
} else {
|
||||
String::new()
|
||||
}
|
||||
});
|
||||
let mode = remembered
|
||||
.as_ref()
|
||||
.map_or(crate::app::QSelectMode::Include, |settings| settings.mode);
|
||||
let append = matches!(scope, crate::app::QSelectScope::CurrentSpace)
|
||||
&& remembered.as_ref().is_some_and(|settings| settings.append);
|
||||
self.qselect = Some(crate::app::QSelectState {
|
||||
scope,
|
||||
available_types,
|
||||
available_properties,
|
||||
candidate_count,
|
||||
type_filter,
|
||||
property: None,
|
||||
operator: crate::app::QSelectOp::Eq,
|
||||
value: String::new(),
|
||||
mode: crate::app::QSelectMode::Include,
|
||||
append: false,
|
||||
property,
|
||||
operator,
|
||||
value,
|
||||
mode,
|
||||
append,
|
||||
error: None,
|
||||
});
|
||||
self.reset_modal_geometry();
|
||||
|
||||
@@ -4349,7 +4349,9 @@ impl OpenCADStudio {
|
||||
Message::QSelectOpen => self.on_qselect_open(),
|
||||
|
||||
Message::QSelectClose => {
|
||||
self.qselect = None;
|
||||
if let Some(state) = self.qselect.take() {
|
||||
self.qselect_settings = Some((&state).into());
|
||||
}
|
||||
self.reset_modal_geometry();
|
||||
Task::none()
|
||||
}
|
||||
@@ -4530,6 +4532,7 @@ impl OpenCADStudio {
|
||||
let Some(state) = self.qselect.take() else {
|
||||
return Task::none();
|
||||
};
|
||||
self.qselect_settings = Some((&state).into());
|
||||
self.reset_modal_geometry();
|
||||
let i = self.active_tab;
|
||||
let matched = self.tabs[i].scene.qselect(
|
||||
|
||||
Reference in new issue
Block a user