forked from 1b-agent/opencadstudio-upstream
feat(block-editor): add functional Visibility ribbon controls
Add the current-state selector, Visibility States dialog and mode/show/hide controls to the contextual ribbon, using shared icons, tooltips, modal UI and adaptive flyouts. Disable the controls until a Visibility parameter exists. Stage state creation, rename, deletion, current-state changes and reordering until OK. Support copied, show-all and hide-all new states in one undo step, preserve native graph metadata, and restore current-state identity on undo/redo. Implement nonsaved BVMODE and display-only reveal during BVSHOW selection. Cancelling selection leaves saved visibility flags and history unchanged. Keep the existing command-line state workflows available. Validation: 6 targeted tests; 277 block, 31 app dock, 35 ribbon and 12 history checks passed (overlapping filters). All 17 local DWG fixtures passed in-memory DWG/DXF preservation checks with unchanged original checksums.
This commit is contained in:
1 parent
308990e672
commit
daa26007f9
24 files changed
+1341
-34
No files matched your search
@@ -97,12 +97,16 @@ impl OpenCADStudio {
|
||||
}
|
||||
|
||||
/// The state the block shows in the editor.
|
||||
fn visibility_current(&self, i: usize, block: Handle) -> usize {
|
||||
pub(in crate::app) fn visibility_current(&self, i: usize, block: Handle) -> usize {
|
||||
let scene = &self.tabs[i].scene;
|
||||
scene
|
||||
.visibility_states
|
||||
.get(&block)
|
||||
.copied()
|
||||
.filter(|index| {
|
||||
visibility::parameter(&scene.document, block)
|
||||
.is_some_and(|parameter| *index < parameter.states.len())
|
||||
})
|
||||
.unwrap_or_else(|| {
|
||||
visibility::parameter(&scene.document, block).map_or(0, |parameter| {
|
||||
visibility::shown_state(&scene.document, parameter.handle)
|
||||
@@ -110,7 +114,13 @@ impl OpenCADStudio {
|
||||
})
|
||||
}
|
||||
|
||||
fn show_visibility_state(&mut self, i: usize, block: Handle, parameter: Handle, state: usize) {
|
||||
pub(in crate::app) fn show_visibility_state(
|
||||
&mut self,
|
||||
i: usize,
|
||||
block: Handle,
|
||||
parameter: Handle,
|
||||
state: usize,
|
||||
) {
|
||||
visibility::apply_state(&mut self.tabs[i].scene.document, parameter, state);
|
||||
self.tabs[i].scene.visibility_states.insert(block, state);
|
||||
self.tabs[i].scene.bump_geometry();
|
||||
@@ -143,6 +153,40 @@ impl OpenCADStudio {
|
||||
}
|
||||
}
|
||||
}
|
||||
let variable = cmd.strip_prefix("SETVAR ").unwrap_or(cmd);
|
||||
if variable == "BVMODE" || variable.starts_with("BVMODE ") {
|
||||
let value = variable.strip_prefix("BVMODE").unwrap().trim();
|
||||
// Inline command probing may have opened the bare variable prompt.
|
||||
if !value.is_empty() && self.pending_setvar.as_deref() == Some("BVMODE") {
|
||||
self.pending_setvar = None;
|
||||
}
|
||||
match value {
|
||||
"" => {
|
||||
self.command_line.push_output(
|
||||
crate::tf!(
|
||||
"BVMODE: enter 0 (hide) or 1 (show dimmed) <{}>:",
|
||||
u8::from(self.block_visibility_mode)
|
||||
)
|
||||
.as_ref(),
|
||||
);
|
||||
self.pending_setvar = Some("BVMODE".into());
|
||||
}
|
||||
"TOGGLE" => {
|
||||
self.block_visibility_mode = !self.block_visibility_mode;
|
||||
self.sync_block_visibility_display();
|
||||
}
|
||||
value @ ("0" | "1") => {
|
||||
self.block_visibility_mode = value == "1";
|
||||
self.sync_block_visibility_display();
|
||||
self.command_line
|
||||
.push_output(crate::tf!("BVMODE = {}", value).as_ref());
|
||||
}
|
||||
_ => self
|
||||
.command_line
|
||||
.push_error(crate::t!("BVMODE: only 0 or 1 is allowed.").as_ref()),
|
||||
}
|
||||
return Some(Task::none());
|
||||
}
|
||||
match cmd {
|
||||
cmd if cmd == "BPARAMETER" || cmd.starts_with("BPARAMETER ") => {
|
||||
let Some(block) = self.visibility_block(i, "BPARAMETER") else {
|
||||
@@ -165,6 +209,17 @@ impl OpenCADStudio {
|
||||
self.tabs[i].active_cmd = Some(Box::new(command));
|
||||
Some(Task::none())
|
||||
}
|
||||
"BVSTATE DIALOG" => {
|
||||
if let Some(context) = self.block_visibility_context() {
|
||||
return Some(self.handle_block_visibility(
|
||||
crate::ui::window::block_visibility::Action::Open(context.target),
|
||||
));
|
||||
}
|
||||
self.command_line.push_error(
|
||||
crate::t!("Place a Visibility parameter in the Block Editor first.").as_ref(),
|
||||
);
|
||||
Some(Task::none())
|
||||
}
|
||||
"BVSTATE" => {
|
||||
let block = self.visibility_block(i, "BVSTATE")?;
|
||||
let document = &self.tabs[i].scene.document;
|
||||
@@ -221,25 +276,8 @@ impl OpenCADStudio {
|
||||
Some(Task::none())
|
||||
}
|
||||
"BVHIDE" | "BVSHOW" => {
|
||||
let block = self.visibility_block(i, cmd)?;
|
||||
self.visibility_block(i, cmd)?;
|
||||
let hide = cmd == "BVHIDE";
|
||||
if !hide {
|
||||
// Every object of the block shows while they are picked;
|
||||
// the state is put back once the pick ends.
|
||||
let document = &mut self.tabs[i].scene.document;
|
||||
let members: Vec<Handle> = document
|
||||
.block_records
|
||||
.iter()
|
||||
.find(|record| record.handle == block)
|
||||
.map(|record| record.entity_handles.clone())
|
||||
.unwrap_or_default();
|
||||
for handle in members {
|
||||
if let Some(entity) = document.get_entity_mut(handle) {
|
||||
entity.common_mut().invisible = false;
|
||||
}
|
||||
}
|
||||
self.tabs[i].scene.bump_geometry();
|
||||
}
|
||||
let pending = if hide { "_BVHIDE" } else { "_BVSHOW" };
|
||||
if !self.tabs[i].scene.selected.is_empty() {
|
||||
return Some(self.dispatch_command(pending));
|
||||
|
||||
Reference in new issue
Block a user