forked from 1b-agent/opencadstudio-upstream
feat(xref): row-level context menu actions and unified split-button toolbar
Right-click actions bound to the row under the cursor, split-button toolbar groups with shared borders and hover states, and a notice when an operation needs a selection first.
This commit is contained in:
1 parent
494a872e8d
commit
22a9bd602c
28 files changed
+352
-168
No files matched your search
+12
-4
@@ -712,6 +712,8 @@ pub(super) struct OpenCADStudio {
|
||||
/// with the last pointer position. Mirrors the Layers Name-column drag.
|
||||
pub(crate) xref_col_drag: Option<usize>,
|
||||
pub(crate) xref_col_last: Option<iced::Point>,
|
||||
/// Table/lower-pane split divider drag in progress.
|
||||
pub(crate) xref_split_drag: bool,
|
||||
/// Docked Insert Block panel state (search, preview size, cached thumbnails).
|
||||
pub(crate) block_palette: crate::ui::window::block_palette::BlockPalette,
|
||||
/// Reference Manager palette state (display-only in Task 7).
|
||||
@@ -2369,6 +2371,12 @@ pub enum Message {
|
||||
XrefColMove(iced::Point),
|
||||
/// Pointer released during a column drag.
|
||||
XrefColRelease,
|
||||
/// Start a table/lower-pane split divider drag.
|
||||
XrefSplitGrab,
|
||||
/// Pointer moved (panel space) during a split drag.
|
||||
XrefSplitMove(iced::Point),
|
||||
/// Pointer released during a split drag.
|
||||
XrefSplitRelease,
|
||||
/// Flip the palette's details/preview lower pane.
|
||||
XrefManagerTogglePreview,
|
||||
/// Toggle the Attach dropdown menu.
|
||||
@@ -2389,10 +2397,9 @@ pub enum Message {
|
||||
XrefManagerToggleExpand(u64),
|
||||
/// Selection-scoped palette operation (detach/unload/reload/overlay/pathtype).
|
||||
XrefManagerOp(crate::ui::window::xref_manager::XrefPaletteOp),
|
||||
/// Details-pane "new path" draft text.
|
||||
XrefManagerPathInput(String),
|
||||
/// Apply the "new path" draft to the anchor entry.
|
||||
XrefManagerPathApply,
|
||||
/// Row-scoped palette operation: selects row `index`, then applies the
|
||||
/// operation to it.
|
||||
XrefRowOp(usize, crate::ui::window::xref_manager::XrefPaletteOp),
|
||||
/// Prefill the command line for Find & Replace across references
|
||||
/// (`XREF Path Find <old> <new>`); the CLI parses and runs it.
|
||||
XrefFindReplacePrompt,
|
||||
@@ -3772,6 +3779,7 @@ impl OpenCADStudio {
|
||||
dock_drag_target: None,
|
||||
xref_col_drag: None,
|
||||
xref_col_last: None,
|
||||
xref_split_drag: false,
|
||||
show_file_tabs: true,
|
||||
show_layout_tabs: true,
|
||||
last_point: None,
|
||||
|
||||
@@ -686,6 +686,7 @@ pub(super) fn on_ribbon_tool_click(&mut self, tool_id: String, event: ModuleEven
|
||||
self.dock_drag_target = None;
|
||||
self.xref_col_drag = None;
|
||||
self.xref_col_last = None;
|
||||
self.xref_split_drag = false;
|
||||
iced::Task::none()
|
||||
}
|
||||
}
|
||||
@@ -908,6 +909,8 @@ pub(super) fn on_ribbon_tool_click(&mut self, tool_id: String, event: ModuleEven
|
||||
.collect()
|
||||
};
|
||||
if picked.is_empty() {
|
||||
self.command_line
|
||||
.push_info(crate::t!("Select a reference first.").as_ref());
|
||||
return;
|
||||
}
|
||||
let needs_host = matches!(
|
||||
@@ -1241,43 +1244,6 @@ pub(super) fn on_ribbon_tool_click(&mut self, tool_id: String, event: ModuleEven
|
||||
self.post_ref_op(i);
|
||||
self.refresh_xref_manager();
|
||||
}
|
||||
|
||||
/// Apply the details-pane path draft to the anchor entry (verbatim
|
||||
/// store, same engine fn as `XREF Path`).
|
||||
pub(crate) fn xref_manager_path_apply(&mut self) {
|
||||
if cfg!(target_arch = "wasm32") {
|
||||
self.command_line.push_error(crate::t!("Reference changes are not available on web — the reference list is read-only.").as_ref());
|
||||
return;
|
||||
}
|
||||
let i = self.active_tab;
|
||||
let anchor = self.xref_manager.anchor.and_then(|a| {
|
||||
self.xref_manager
|
||||
.entries
|
||||
.get(a)
|
||||
.filter(|_| !self.xref_manager.nested.contains(&a))
|
||||
.map(|e| (e.key, e.name.clone()))
|
||||
});
|
||||
let Some((key, _)) = anchor else {
|
||||
return;
|
||||
};
|
||||
let new_raw = self.xref_manager.path_input.clone();
|
||||
if new_raw.is_empty() {
|
||||
return;
|
||||
}
|
||||
self.push_undo_snapshot(i, "XREF-PATH");
|
||||
match crate::io::xref::set_ref_path(&mut self.tabs[i].scene.document, key, &new_raw)
|
||||
{
|
||||
Ok(name) => {
|
||||
self.command_line.push_output(crate::tf!(
|
||||
"XREF: Path set for \"{}\" — Reload to apply.",
|
||||
name
|
||||
).as_ref());
|
||||
self.post_ref_op(i);
|
||||
}
|
||||
Err(msg) => self.command_line.push_error(msg.as_str()),
|
||||
}
|
||||
self.refresh_xref_manager();
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
|
||||
+23
-6
@@ -2192,6 +2192,25 @@ impl OpenCADStudio {
|
||||
self.xref_col_last = None;
|
||||
Task::none()
|
||||
}
|
||||
Message::XrefSplitGrab => {
|
||||
self.xref_split_drag = true;
|
||||
self.xref_col_last = None;
|
||||
Task::none()
|
||||
}
|
||||
Message::XrefSplitMove(p) => {
|
||||
if self.xref_split_drag {
|
||||
if let Some(last) = self.xref_col_last {
|
||||
self.xref_manager.drag_table_by(p.y - last.y);
|
||||
}
|
||||
self.xref_col_last = Some(p);
|
||||
}
|
||||
Task::none()
|
||||
}
|
||||
Message::XrefSplitRelease => {
|
||||
self.xref_split_drag = false;
|
||||
self.xref_col_last = None;
|
||||
Task::none()
|
||||
}
|
||||
Message::XrefManagerTogglePreview => {
|
||||
self.xref_manager.show_preview ^= true;
|
||||
Task::none()
|
||||
@@ -2284,12 +2303,10 @@ impl OpenCADStudio {
|
||||
self.xref_manager_op(op);
|
||||
Task::none()
|
||||
}
|
||||
Message::XrefManagerPathInput(text) => {
|
||||
self.xref_manager.path_input = text;
|
||||
Task::none()
|
||||
}
|
||||
Message::XrefManagerPathApply => {
|
||||
self.xref_manager_path_apply();
|
||||
Message::XrefRowOp(index, op) => {
|
||||
// Row-scoped op: select the row first, then run the op.
|
||||
self.xref_manager.right_click_select(index);
|
||||
self.xref_manager_op(op);
|
||||
Task::none()
|
||||
}
|
||||
Message::XrefFindReplacePrompt => {
|
||||
|
||||
+2
-1
@@ -1875,7 +1875,8 @@ bg={bg_ms:.1}ms n={view_count}"
|
||||
let workspace: Element<'_, Message> = row(parts).width(Fill).height(Fill).into();
|
||||
|
||||
let any_dragging = self.dock_dragging.is_some();
|
||||
let any_resizing = self.dock_resizing.is_some() || self.xref_col_drag.is_some();
|
||||
let any_resizing =
|
||||
self.dock_resizing.is_some() || self.xref_col_drag.is_some() || self.xref_split_drag;
|
||||
let workspace = if any_dragging {
|
||||
let id = self.dock_dragging.expect("guarded by any_dragging");
|
||||
let side = self.dock_drag_target.map(|(s, _)| s).unwrap_or(
|
||||
|
||||
Reference in new issue
Block a user