forked from 1b-agent/opencadstudio-upstream
feat(ui): add dockable properties panel
Preserve panel width across left/right docking and persist resize, position, and auto-collapse preferences. Refs #348 Refs #650
This commit is contained in:
1 parent
e35348525a
commit
4be8d9735c
8 files changed
+355
-27
No files matched your search
@@ -520,6 +520,11 @@ impl OpenCADStudio {
|
||||
section: self.start_section,
|
||||
},
|
||||
statusbar: self.statusbar_config.clone(),
|
||||
properties: crate::app::config::PropertiesDockConfig {
|
||||
side: self.properties_side,
|
||||
width: self.properties_width,
|
||||
auto_collapse: self.properties_auto_collapse,
|
||||
},
|
||||
annotation_auto_scale: self.annotation_auto_scale,
|
||||
ribbon: crate::app::config::RibbonConfig {
|
||||
collapse: self.ribbon.collapse_mode(),
|
||||
@@ -550,6 +555,13 @@ impl OpenCADStudio {
|
||||
// (`refresh_recent_thumbs`) — never here on the boot path.
|
||||
self.start_section = cfg.start.section;
|
||||
self.statusbar_config = cfg.statusbar;
|
||||
self.properties_side = cfg.properties.side;
|
||||
self.properties_width = if cfg.properties.width.is_finite() {
|
||||
cfg.properties.width.clamp(220.0, 600.0)
|
||||
} else {
|
||||
250.0
|
||||
};
|
||||
self.properties_auto_collapse = cfg.properties.auto_collapse;
|
||||
self.annotation_auto_scale = cfg.annotation_auto_scale.clamp(-4, 4);
|
||||
self.ribbon.set_collapse_mode(cfg.ribbon.collapse);
|
||||
self.plot_dialog = cfg.plot;
|
||||
|
||||
@@ -350,6 +350,110 @@ impl OpenCADStudio {
|
||||
Task::none()
|
||||
}
|
||||
|
||||
Message::PropertiesClose => {
|
||||
self.show_properties = false;
|
||||
self.properties_hovered = false;
|
||||
self.properties_dragging = false;
|
||||
self.properties_resizing = false;
|
||||
self.properties_drag_last = None;
|
||||
self.properties_dock_preview = None;
|
||||
self.ribbon.set_properties(false);
|
||||
Task::none()
|
||||
}
|
||||
|
||||
Message::PropertiesAutoCollapseToggle => {
|
||||
self.properties_auto_collapse ^= true;
|
||||
// Keep the panel open while the pointer is still over the
|
||||
// button; leaving the panel performs the first collapse.
|
||||
self.properties_hovered = self.properties_auto_collapse;
|
||||
self.save_config();
|
||||
Task::none()
|
||||
}
|
||||
|
||||
Message::PropertiesHover(hovered) => {
|
||||
if self.properties_auto_collapse
|
||||
&& !self.properties_dragging
|
||||
&& !self.properties_resizing
|
||||
{
|
||||
self.properties_hovered = hovered;
|
||||
}
|
||||
Task::none()
|
||||
}
|
||||
|
||||
Message::PropertiesDockGrab => {
|
||||
self.properties_dragging = true;
|
||||
self.properties_resizing = false;
|
||||
self.properties_drag_last = None;
|
||||
self.properties_dock_preview = Some(self.properties_side);
|
||||
self.properties_hovered = true;
|
||||
Task::none()
|
||||
}
|
||||
|
||||
Message::PropertiesResizeGrab => {
|
||||
self.properties_resizing = true;
|
||||
self.properties_dragging = false;
|
||||
self.properties_drag_last = None;
|
||||
self.properties_dock_preview = None;
|
||||
self.properties_hovered = true;
|
||||
Task::none()
|
||||
}
|
||||
|
||||
Message::PropertiesWidthReset => {
|
||||
self.properties_width = 250.0;
|
||||
self.save_config();
|
||||
Task::none()
|
||||
}
|
||||
|
||||
Message::PropertiesDragMove(point) => {
|
||||
if self.properties_dragging {
|
||||
self.properties_dock_preview = Some(if point.x < self.win_size.0 * 0.5 {
|
||||
crate::app::config::DockSide::Left
|
||||
} else {
|
||||
crate::app::config::DockSide::Right
|
||||
});
|
||||
} else if self.properties_resizing {
|
||||
if let Some(last) = self.properties_drag_last {
|
||||
let dx = point.x - last.x;
|
||||
let delta = match self.properties_side {
|
||||
crate::app::config::DockSide::Left => dx,
|
||||
crate::app::config::DockSide::Right => -dx,
|
||||
};
|
||||
let max_width = (self.win_size.0 * 0.45).clamp(220.0, 600.0);
|
||||
self.properties_width =
|
||||
(self.properties_width + delta).clamp(220.0, max_width);
|
||||
}
|
||||
}
|
||||
if self.properties_dragging || self.properties_resizing {
|
||||
self.properties_drag_last = Some(point);
|
||||
}
|
||||
Task::none()
|
||||
}
|
||||
|
||||
Message::PropertiesDragRelease => {
|
||||
let changed = if self.properties_dragging {
|
||||
if let Some(side) = self.properties_dock_preview {
|
||||
let changed = side != self.properties_side;
|
||||
self.properties_side = side;
|
||||
changed
|
||||
} else {
|
||||
false
|
||||
}
|
||||
} else {
|
||||
self.properties_resizing
|
||||
};
|
||||
self.properties_dragging = false;
|
||||
self.properties_resizing = false;
|
||||
self.properties_drag_last = None;
|
||||
self.properties_dock_preview = None;
|
||||
if self.properties_auto_collapse {
|
||||
self.properties_hovered = false;
|
||||
}
|
||||
if changed {
|
||||
self.save_config();
|
||||
}
|
||||
Task::none()
|
||||
}
|
||||
|
||||
Message::ScrollLayoutTabs(dx) => iced::widget::operation::scroll_by(
|
||||
iced::advanced::widget::Id::new(crate::ui::statusbar::LAYOUT_TABS_SCROLL_ID),
|
||||
iced::widget::scrollable::AbsoluteOffset { x: dx, y: 0.0 },
|
||||
|
||||
Reference in new issue
Block a user