forked from 1b-agent/opencadstudio-upstream
feat(xref): row selection, resizable columns, tree view, and find-replace
Single, multi, and range row selection, resizable table columns, hierarchical tree presentation, and find-and-replace through the command line.
This commit is contained in:
1 parent
019422d220
commit
494a872e8d
7 files changed
+565
-237
No files matched your search
+18
-5
@@ -708,6 +708,10 @@ pub(super) struct OpenCADStudio {
|
||||
pub(crate) dock_drag_last: Option<iced::Point>,
|
||||
/// Live drag target (side + index), shown as a highlight while dragging.
|
||||
pub(crate) dock_drag_target: Option<(crate::app::config::DockSide, usize)>,
|
||||
/// Reference-table column currently being width-resized (column index),
|
||||
/// 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>,
|
||||
/// 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).
|
||||
@@ -2354,8 +2358,17 @@ pub enum Message {
|
||||
XrefManagerRefresh,
|
||||
/// Toggle one palette row (entry index) in the multi-selection set.
|
||||
XrefManagerSelect(usize),
|
||||
/// Right-click on a palette row: single-select it when outside the
|
||||
/// selection (the context menu then acts on the selection).
|
||||
XrefRowRightClick(usize),
|
||||
/// Flip the palette's list/tree presentation.
|
||||
XrefManagerToggleTree,
|
||||
/// Start a reference-table column divider drag (column index).
|
||||
XrefColGrab(usize),
|
||||
/// Pointer moved (table header space) during a column drag.
|
||||
XrefColMove(iced::Point),
|
||||
/// Pointer released during a column drag.
|
||||
XrefColRelease,
|
||||
/// Flip the palette's details/preview lower pane.
|
||||
XrefManagerTogglePreview,
|
||||
/// Toggle the Attach dropdown menu.
|
||||
@@ -2380,11 +2393,9 @@ pub enum Message {
|
||||
XrefManagerPathInput(String),
|
||||
/// Apply the "new path" draft to the anchor entry.
|
||||
XrefManagerPathApply,
|
||||
/// Find & Replace row drafts.
|
||||
XrefManagerFindInput(String),
|
||||
XrefManagerReplaceInput(String),
|
||||
/// Apply Find & Replace across all direct references.
|
||||
XrefManagerFindReplaceApply,
|
||||
/// Prefill the command line for Find & Replace across references
|
||||
/// (`XREF Path Find <old> <new>`); the CLI parses and runs it.
|
||||
XrefFindReplacePrompt,
|
||||
LayerToggleVisible(usize),
|
||||
LayerToggleLock(usize),
|
||||
LayerToggleFreeze(usize),
|
||||
@@ -3759,6 +3770,8 @@ impl OpenCADStudio {
|
||||
dock_resizing: None,
|
||||
dock_drag_last: None,
|
||||
dock_drag_target: None,
|
||||
xref_col_drag: None,
|
||||
xref_col_last: None,
|
||||
show_file_tabs: true,
|
||||
show_layout_tabs: true,
|
||||
last_point: None,
|
||||
|
||||
@@ -638,6 +638,11 @@ pub(super) fn on_ribbon_tool_click(&mut self, tool_id: String, event: ModuleEven
|
||||
iced::Task::none()
|
||||
}
|
||||
DockMsg::DragMove(point) => {
|
||||
// NOTE: xref column drags intentionally do NOT ride this
|
||||
// path: its points live in workspace space while the header
|
||||
// tracker reports header-local points, and mixing the two
|
||||
// produced a one-time jump plus a stuck drag. Column moves
|
||||
// arrive via Message::XrefColMove only.
|
||||
if self.dock_dragging.is_some() {
|
||||
let avail = self.tabs[self.active_tab].scene.selection.borrow().vp_size.1;
|
||||
let side = if point.x < self.win_size.0 * 0.5 {
|
||||
@@ -679,6 +684,8 @@ pub(super) fn on_ribbon_tool_click(&mut self, tool_id: String, event: ModuleEven
|
||||
self.dock_resizing = None;
|
||||
self.dock_drag_last = None;
|
||||
self.dock_drag_target = None;
|
||||
self.xref_col_drag = None;
|
||||
self.xref_col_last = None;
|
||||
iced::Task::none()
|
||||
}
|
||||
}
|
||||
@@ -1271,37 +1278,6 @@ pub(super) fn on_ribbon_tool_click(&mut self, tool_id: String, event: ModuleEven
|
||||
}
|
||||
self.refresh_xref_manager();
|
||||
}
|
||||
|
||||
/// Apply Find & Replace across all direct references (same engine fn
|
||||
/// as `XREF Path Find`).
|
||||
pub(crate) fn xref_manager_find_replace_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 old = self.xref_manager.find_input.clone();
|
||||
let new = self.xref_manager.replace_input.clone();
|
||||
if old.is_empty() || new.is_empty() {
|
||||
self.command_line
|
||||
.push_error(crate::t!("Usage: XREF Path Find <old> <new>").as_ref());
|
||||
return;
|
||||
}
|
||||
self.push_undo_snapshot(i, "XREF-PATH");
|
||||
let n = crate::io::xref::replace_path_prefix(
|
||||
&mut self.tabs[i].scene.document,
|
||||
&old,
|
||||
&new,
|
||||
);
|
||||
self.command_line.push_output(crate::tf!(
|
||||
"XREF: updated {} reference(s).",
|
||||
n
|
||||
).as_ref());
|
||||
if n > 0 {
|
||||
self.post_ref_op(i);
|
||||
}
|
||||
self.refresh_xref_manager();
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
|
||||
+45
-12
@@ -2148,13 +2148,50 @@ impl OpenCADStudio {
|
||||
Task::none()
|
||||
}
|
||||
Message::XrefManagerSelect(index) => {
|
||||
self.xref_manager.toggle_select(index);
|
||||
use crate::ui::window::xref_manager::SelectExtend;
|
||||
// Normal GUI list behavior off the globally tracked
|
||||
// modifiers (same source as the layer list): plain click
|
||||
// selects one row, Ctrl/Cmd toggles, Shift extends a range.
|
||||
let extend = if self.ctrl_down {
|
||||
SelectExtend::Toggle
|
||||
} else if self.shift_down {
|
||||
SelectExtend::Range
|
||||
} else {
|
||||
SelectExtend::Single
|
||||
};
|
||||
self.xref_manager.click_select(index, extend);
|
||||
Task::none()
|
||||
}
|
||||
Message::XrefRowRightClick(index) => {
|
||||
self.xref_manager.right_click_select(index);
|
||||
Task::none()
|
||||
}
|
||||
Message::XrefManagerToggleTree => {
|
||||
self.xref_manager.toggle_tree();
|
||||
Task::none()
|
||||
}
|
||||
Message::XrefColGrab(i) => {
|
||||
// Start a table-column divider drag; moves arrive via the
|
||||
// header's mouse_area (XrefColMove), like the Layers
|
||||
// Name-column divider rides ModalDragMove.
|
||||
self.xref_col_drag = Some(i);
|
||||
self.xref_col_last = None;
|
||||
Task::none()
|
||||
}
|
||||
Message::XrefColMove(p) => {
|
||||
if let Some(i) = self.xref_col_drag {
|
||||
if let Some(last) = self.xref_col_last {
|
||||
self.xref_manager.drag_col_by(i, p.x - last.x);
|
||||
}
|
||||
self.xref_col_last = Some(p);
|
||||
}
|
||||
Task::none()
|
||||
}
|
||||
Message::XrefColRelease => {
|
||||
self.xref_col_drag = None;
|
||||
self.xref_col_last = None;
|
||||
Task::none()
|
||||
}
|
||||
Message::XrefManagerTogglePreview => {
|
||||
self.xref_manager.show_preview ^= true;
|
||||
Task::none()
|
||||
@@ -2255,17 +2292,13 @@ impl OpenCADStudio {
|
||||
self.xref_manager_path_apply();
|
||||
Task::none()
|
||||
}
|
||||
Message::XrefManagerFindInput(text) => {
|
||||
self.xref_manager.find_input = text;
|
||||
Task::none()
|
||||
}
|
||||
Message::XrefManagerReplaceInput(text) => {
|
||||
self.xref_manager.replace_input = text;
|
||||
Task::none()
|
||||
}
|
||||
Message::XrefManagerFindReplaceApply => {
|
||||
self.xref_manager_find_replace_apply();
|
||||
Task::none()
|
||||
Message::XrefFindReplacePrompt => {
|
||||
// No fields in the panel: prefill the command line so the
|
||||
// existing `XREF Path Find <old> <new>` parsing runs it.
|
||||
self.command_line.input = "XREF Path Find ".to_string();
|
||||
self.command_line.autocomplete_cursor = None;
|
||||
self.command_line.cancel_history_navigation();
|
||||
return self.focus_cmd_input();
|
||||
}
|
||||
|
||||
Message::LayerStateManagerOpen => {
|
||||
|
||||
+1
-1
@@ -1875,7 +1875,7 @@ 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();
|
||||
let any_resizing = self.dock_resizing.is_some() || self.xref_col_drag.is_some();
|
||||
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