Dock: drop dead pallet-width setters, split on_dock, share span maths

- Only docked pallets have a width divider, so the Width drag and
  WidthReset no longer carry a branch for an undocked pallet; remove the
  then unused DockState::set_width / reset_width. Per-pallet widths are
  still read (older configs, floating size). Tests now size groups.
- on_dock hands hover messages to dock_hover and the release to
  dock_drag_release.
- dock_slot_spans and dock_landing share dock_open_spans.

No behaviour change.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
Claude-Session: https://claude.ai/code/session_013RyGiMXcsf9HTKfqDxaQGt
This commit is contained in:
Claude committed 2026-10-10 12:34:02 +00:00
1 parent 02404301a5
commit cc17d10ca9
4 files changed
+111 -107

No files matched your search

+1 -1
View File
@@ -186,7 +186,7 @@ fn dock_icon_press_switches_the_shown_group() {
assert_eq!(app.dock_shown_group(DockSide::Left), Some(1));
assert_eq!(app.dock_slot_spans(DockSide::Left), vec![(0, 0.0, 900.0)]);
// Each group keeps its own width.
app.dock.set_width(PanelId::Browser, 400.0);
app.dock.set_group_width(DockSide::Left, 1, 400.0);
assert_eq!(app.dock_column_width(DockSide::Left), 400.0);
let _ = app.on_dock(DockMsg::IconPress(PanelId::BlockPalette));
let _ = app.on_dock(DockMsg::DragRelease);
+90 -65
View File
@@ -30,7 +30,7 @@ impl OpenCADStudio {
/// whichever panel the message names.
pub(crate) fn on_dock(&mut self, m: crate::ui::dock::DockMsg) -> iced::Task<Message> {
use crate::app::config::DockSide;
use crate::ui::dock::{DockDrag, DockMsg, DropTarget, FloatPanel, HoverPending};
use crate::ui::dock::{DockDrag, DockMsg, FloatPanel};
match m {
DockMsg::DockGrab(id) => self.dock_begin(DockDrag::moving(id, None), Some(id)),
DockMsg::IconPress(id) => {
@@ -66,12 +66,11 @@ impl OpenCADStudio {
self.save_config();
}
DockMsg::WidthReset(id) => {
// Only docked pallets have the divider that sends this.
if let Some((side, gi)) = self.dock.location(id) {
self.dock.reset_group_width(side, gi);
} else {
self.dock.reset_width(id);
self.save_config();
}
self.save_config();
}
DockMsg::TitleHover(id) => self.dock_title_hover = Some(id),
DockMsg::TitleHoverEnd(id) => {
@@ -150,6 +149,22 @@ impl OpenCADStudio {
self.save_config();
}
DockMsg::Close(id) => return self.dock_set_open(id, false),
DockMsg::Hover(_)
| DockMsg::HoverEnd(_)
| DockMsg::HoverExit
| DockMsg::HoverStay
| DockMsg::HoverSettled(_) => return self.dock_hover(m),
DockMsg::DragMove(point) => self.dock_drag_move(point),
DockMsg::DragRelease => self.dock_drag_release(),
}
iced::Task::none()
}
/// Pointer entering / leaving strip icons, edge columns and floating
/// frames, and the delayed auto-hide reveal / hide that follows.
fn dock_hover(&mut self, m: crate::ui::dock::DockMsg) -> iced::Task<Message> {
use crate::ui::dock::{DockMsg, HoverPending};
match m {
DockMsg::Hover(id) => {
self.dock_icon_hover = Some(id);
// Only an auto-hiding edge (or floating pallet) reacts to
@@ -198,54 +213,57 @@ impl OpenCADStudio {
}
}
}
DockMsg::DragMove(point) => self.dock_drag_move(point),
DockMsg::DragRelease => {
let mut changed = false;
match self.dock_drag.take() {
Some(DockDrag::Move {
group: Some((side, gi)),
target: Some(DropTarget::Edge { side: to, index }),
..
}) => changed = self.dock.move_group(side, gi, to, index),
Some(DockDrag::Move {
panel,
group: None,
target: Some(target),
..
}) => {
changed = match target {
DropTarget::Edge { side, index } => self.dock.dock(panel, side, index),
DropTarget::Join { side, group, index } => {
self.dock.join_group(panel, side, group, index)
}
DropTarget::Float { x, y } => {
let (w, h) = self.dock_float_size(panel);
// A floating panel keeps its docking choice.
let docking = self.dock.float_rect(panel).is_none_or(|f| f.docking);
self.dock.float(FloatPanel {
docking,
..FloatPanel::new(panel, x, y, w, h)
})
}
};
}
Some(DockDrag::Move { .. } | DockDrag::LayerColumn) | None => {}
Some(DockDrag::Width(_) | DockDrag::Split { .. } | DockDrag::FloatSize { .. }) => {
changed = true;
}
}
if changed {
self.save_config();
}
self.dock_drag_last = None;
self.xref_col_drag = None;
self.xref_col_last = None;
self.xref_split_drag = false;
}
_ => {}
}
iced::Task::none()
}
/// Pointer released: land what was dragged and save a changed layout.
fn dock_drag_release(&mut self) {
use crate::ui::dock::{DockDrag, DropTarget, FloatPanel};
let mut changed = false;
match self.dock_drag.take() {
Some(DockDrag::Move {
group: Some((side, gi)),
target: Some(DropTarget::Edge { side: to, index }),
..
}) => changed = self.dock.move_group(side, gi, to, index),
Some(DockDrag::Move {
panel,
group: None,
target: Some(target),
..
}) => {
changed = match target {
DropTarget::Edge { side, index } => self.dock.dock(panel, side, index),
DropTarget::Join { side, group, index } => {
self.dock.join_group(panel, side, group, index)
}
DropTarget::Float { x, y } => {
let (w, h) = self.dock_float_size(panel);
// A floating panel keeps its docking choice.
let docking = self.dock.float_rect(panel).is_none_or(|f| f.docking);
self.dock.float(FloatPanel {
docking,
..FloatPanel::new(panel, x, y, w, h)
})
}
};
}
Some(DockDrag::Move { .. } | DockDrag::LayerColumn) | None => {}
Some(DockDrag::Width(_) | DockDrag::Split { .. } | DockDrag::FloatSize { .. }) => {
changed = true;
}
}
if changed {
self.save_config();
}
self.dock_drag_last = None;
self.xref_col_drag = None;
self.xref_col_last = None;
self.xref_split_drag = false;
}
/// Pointer motion while something in the dock is dragged.
fn dock_drag_move(&mut self, point: iced::Point) {
// NOTE: xref column drags intentionally do NOT ride this path: its
@@ -353,18 +371,12 @@ impl OpenCADStudio {
}
DockDrag::Width(id) => {
let Some(last) = last else { return };
let dx = point.x - last.x;
match self.dock.location(id) {
// The divider sizes the panel's group.
Some((side, gi)) => {
let delta = if side == DockSide::Left { dx } else { -dx };
let cur = self.dock_group_width(side, gi) + delta;
self.dock.set_group_width(side, gi, cur);
}
None => {
let cur = self.dock.settings(id).width + dx;
self.dock.set_width(id, cur);
}
// The divider sizes the docked pallet's group.
if let Some((side, gi)) = self.dock.location(id) {
let dx = point.x - last.x;
let delta = if side == DockSide::Left { dx } else { -dx };
let cur = self.dock_group_width(side, gi) + delta;
self.dock.set_group_width(side, gi, cur);
}
}
}
@@ -634,13 +646,26 @@ impl OpenCADStudio {
&self,
side: crate::app::config::DockSide,
) -> Vec<(usize, f32, f32)> {
let Some(gi) = self.dock_shown_group(side) else {
return Vec::new();
};
match self.dock_shown_group(side) {
Some(gi) => self.dock_open_spans(&self.dock.groups(side)[gi], None),
None => Vec::new(),
}
}
/// The open pallets of `group` (plus `extra`, a pallet about to land
/// there), each as (position in the group, top, bottom) down the
/// workspace height.
pub(crate) fn dock_open_spans(
&self,
group: &crate::ui::dock::DockGroup,
extra: Option<crate::ui::dock::PanelId>,
) -> Vec<(usize, f32, f32)> {
let (_, avail) = self.dock_workspace_size();
let group = &self.dock.groups(side)[gi];
let open: Vec<usize> = (0..group.panels.len())
.filter(|i| self.dock_panel_visible(group.panels[*i]))
.filter(|i| {
let id = group.panels[*i];
Some(id) == extra || self.dock_panel_visible(id)
})
.collect();
let weights: Vec<f32> = open.iter().map(|i| group.weights[*i]).collect();
open.into_iter()
+4 -7
View File
@@ -690,13 +690,10 @@ impl OpenCADStudio {
}
let (side, gi) = after.location(id)?;
let group = &after.groups(side)[gi];
let open: Vec<usize> = (0..group.panels.len())
.filter(|i| group.panels[*i] == id || self.dock_panel_visible(group.panels[*i]))
.collect();
let weights: Vec<f32> = open.iter().map(|i| group.weights[*i]).collect();
let at = open.iter().position(|i| group.panels[*i] == id)?;
let (_, avail) = self.dock_workspace_size();
let (top, bottom) = *crate::ui::dock::slot_spans(&weights, avail).get(at)?;
let (_, top, bottom) = self
.dock_open_spans(group, Some(id))
.into_iter()
.find(|(i, _, _)| group.panels[*i] == id)?;
Some((top, bottom, after.group_width_px(side, gi, self.win_size.0)))
}