forked from 1b-agent/opencadstudio-upstream
Dock: review cleanups - hover pending enum, FloatFrame, comment fixes
- dock_hover_pending is an Option<HoverPending> (Reveal / Hide) instead of a nested Option. - dock_float_frame returns a FloatFrame with width() and bar_x(), so the floating menu no longer repeats the frame-width formula. - Put dock_reveal's doc comment back on dock_reveal, and the group-move comment back above the match it describes. No behaviour change. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_013RyGiMXcsf9HTKfqDxaQGt
This commit is contained in:
4 files changed
+75
-29
No files matched your search
+17
-13
@@ -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};
|
||||
use crate::ui::dock::{DockDrag, DockMsg, DropTarget, FloatPanel, HoverPending};
|
||||
match m {
|
||||
DockMsg::DockGrab(id) => self.dock_begin(DockDrag::moving(id, None), Some(id)),
|
||||
DockMsg::IconPress(id) => {
|
||||
@@ -160,7 +160,7 @@ impl OpenCADStudio {
|
||||
if self.dock_peek == Some(id) {
|
||||
self.dock_hover_cancel();
|
||||
} else {
|
||||
return self.dock_hover_arm(Some(id));
|
||||
return self.dock_hover_arm(HoverPending::Reveal(id));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -173,21 +173,25 @@ impl OpenCADStudio {
|
||||
if self.dock_drag.is_none()
|
||||
&& self.dock_peek.is_some_and(|id| self.dock.auto_hides(id))
|
||||
{
|
||||
return self.dock_hover_arm(None);
|
||||
return self.dock_hover_arm(HoverPending::Hide);
|
||||
}
|
||||
// Left before a pending reveal ran out: it never happens.
|
||||
self.dock_hover_cancel();
|
||||
}
|
||||
DockMsg::HoverStay => {
|
||||
if self.dock_hover_pending == Some(None) {
|
||||
if self.dock_hover_pending == Some(HoverPending::Hide) {
|
||||
self.dock_hover_cancel();
|
||||
}
|
||||
}
|
||||
DockMsg::HoverSettled(gen) => {
|
||||
if gen == self.dock_hover_gen && self.dock_drag.is_none() {
|
||||
match self.dock_hover_pending.take() {
|
||||
Some(Some(id)) if self.dock.auto_hides(id) => self.dock_reveal(id),
|
||||
Some(None) if self.dock_peek.is_some_and(|id| self.dock.auto_hides(id)) => {
|
||||
Some(HoverPending::Reveal(id)) if self.dock.auto_hides(id) => {
|
||||
self.dock_reveal(id)
|
||||
}
|
||||
Some(HoverPending::Hide)
|
||||
if self.dock_peek.is_some_and(|id| self.dock.auto_hides(id)) =>
|
||||
{
|
||||
self.dock_peek = None;
|
||||
}
|
||||
_ => {}
|
||||
@@ -280,13 +284,13 @@ impl OpenCADStudio {
|
||||
grab
|
||||
};
|
||||
let target = if started {
|
||||
// A whole group only moves between group positions: it
|
||||
// cannot join another group or float.
|
||||
// A floating panel that may not dock only floats.
|
||||
let found = match self.dock.float_rect(panel) {
|
||||
Some(f) if !f.docking => self.dock_float_target(point, grab),
|
||||
_ => self.dock_drop_target(point, grab),
|
||||
};
|
||||
// A whole group only moves between group positions: it
|
||||
// cannot join another group or float.
|
||||
match (group, found) {
|
||||
(Some(_), found @ DropTarget::Edge { .. }) | (None, found) => Some(found),
|
||||
(Some(_), _) => None,
|
||||
@@ -381,11 +385,9 @@ impl OpenCADStudio {
|
||||
}
|
||||
}
|
||||
|
||||
/// Bring `id` into view: show its group on its edge and, where it
|
||||
/// auto-hides, keep it revealed until the pointer leaves.
|
||||
/// Arm a delayed reveal (`Some`) or hide (`None`); it applies when its
|
||||
/// timer reports back unless a newer hover superseded it.
|
||||
fn dock_hover_arm(&mut self, target: Option<crate::ui::dock::PanelId>) -> iced::Task<Message> {
|
||||
/// Arm a delayed reveal or hide; it applies when its timer reports back
|
||||
/// unless a newer hover superseded it.
|
||||
fn dock_hover_arm(&mut self, target: crate::ui::dock::HoverPending) -> iced::Task<Message> {
|
||||
self.dock_hover_gen = self.dock_hover_gen.wrapping_add(1);
|
||||
self.dock_hover_pending = Some(target);
|
||||
let gen = self.dock_hover_gen;
|
||||
@@ -400,6 +402,8 @@ impl OpenCADStudio {
|
||||
self.dock_hover_pending = None;
|
||||
}
|
||||
|
||||
/// Bring `id` into view: show its group on its edge and, where it
|
||||
/// auto-hides, keep it revealed until the pointer leaves.
|
||||
pub(crate) fn dock_reveal(&mut self, id: crate::ui::dock::PanelId) {
|
||||
self.dock.show_group_of(id);
|
||||
self.dock_peek = Some(id);
|
||||
|
||||
+46
-13
@@ -444,7 +444,7 @@ impl OpenCADStudio {
|
||||
tab: &'a DocumentTab,
|
||||
) -> Element<'a, Message> {
|
||||
use crate::ui::dock::DockMsg;
|
||||
let (x, y, bar_left, hidden) = self.dock_float_frame(f);
|
||||
let FloatFrame { x, y, bar_left, hidden } = self.dock_float_frame(f);
|
||||
let hovered = self.dock_title_hover == Some(f.id);
|
||||
let bar = floating_title_bar(f.id, self.dock.auto_collapse(f.id), bar_left, hovered);
|
||||
let content: Element<'_, Message> = if hidden {
|
||||
@@ -519,10 +519,8 @@ impl OpenCADStudio {
|
||||
place_at(panel.into(), x, y)
|
||||
}
|
||||
|
||||
/// Where floating panel `f` draws: its top-left corner, whether its
|
||||
/// title bar is on the left, and whether it is hidden down to that bar
|
||||
/// (auto-hide, not hovered).
|
||||
fn dock_float_frame(&self, f: crate::ui::dock::FloatPanel) -> (f32, f32, bool, bool) {
|
||||
/// Where floating panel `f` draws.
|
||||
fn dock_float_frame(&self, f: crate::ui::dock::FloatPanel) -> FloatFrame {
|
||||
let (ww, wh) = self.dock_workspace_size();
|
||||
// The bar faces the nearer workspace edge; while resizing, it stays
|
||||
// opposite the grip being dragged so it cannot flip mid-drag.
|
||||
@@ -533,13 +531,15 @@ impl OpenCADStudio {
|
||||
_ => f.x + (f.w + DOCK_FLOAT_BAR_W) * 0.5 < ww * 0.5,
|
||||
};
|
||||
let hidden = self.dock.auto_collapse(f.id) && self.dock_peek != Some(f.id);
|
||||
let total_w = if hidden { DOCK_FLOAT_BAR_W } else { f.w + DOCK_FLOAT_BAR_W };
|
||||
// A hidden panel keeps its title bar where it sits when shown.
|
||||
let x = if hidden && !bar_left { f.x + f.w } else { f.x };
|
||||
let frame = FloatFrame { x, y: f.y, bar_left, hidden };
|
||||
// Keep the panel on screen when the window shrank since it was placed.
|
||||
let x = x.min(ww - total_w).max(0.0);
|
||||
let y = f.y.min(wh - f.h).max(0.0);
|
||||
(x, y, bar_left, hidden)
|
||||
FloatFrame {
|
||||
x: x.min(ww - frame.width(f)).max(0.0),
|
||||
y: f.y.min(wh - f.h).max(0.0),
|
||||
..frame
|
||||
}
|
||||
}
|
||||
|
||||
/// The open right-click menu of a floating title bar: Allow docking,
|
||||
@@ -554,11 +554,12 @@ impl OpenCADStudio {
|
||||
return None;
|
||||
}
|
||||
let (ww, wh) = self.dock_workspace_size();
|
||||
let (x, y, bar_left, hidden) = self.dock_float_frame(f);
|
||||
let total_w = if hidden { DOCK_FLOAT_BAR_W } else { f.w + DOCK_FLOAT_BAR_W };
|
||||
let bar_x = if bar_left { x } else { x + total_w - DOCK_FLOAT_BAR_W };
|
||||
let frame = self.dock_float_frame(f);
|
||||
// Where the right-click happened, in the workspace.
|
||||
let at = iced::Point::new(bar_x + self.dock_float_menu_at.x, y + self.dock_float_menu_at.y);
|
||||
let at = iced::Point::new(
|
||||
frame.bar_x(f) + self.dock_float_menu_at.x,
|
||||
frame.y + self.dock_float_menu_at.y,
|
||||
);
|
||||
let menu_x = if at.x + DOCK_MENU_W <= ww { at.x } else { at.x - DOCK_MENU_W };
|
||||
let menu_x = menu_x.clamp(0.0, (ww - DOCK_MENU_W).max(0.0));
|
||||
let menu_y = at.y.min(wh - FLOAT_MENU_H).max(0.0);
|
||||
@@ -880,6 +881,38 @@ impl canvas::Program<Message> for VBarLabel {
|
||||
/// Width of a floating panel's vertical title bar.
|
||||
const DOCK_FLOAT_BAR_W: f32 = 28.0;
|
||||
|
||||
/// Where a floating panel draws: its top-left corner, whether its title bar
|
||||
/// is on the left, and whether it is hidden down to that bar (auto-hide, not
|
||||
/// hovered).
|
||||
#[derive(Debug, Clone, Copy)]
|
||||
struct FloatFrame {
|
||||
x: f32,
|
||||
y: f32,
|
||||
bar_left: bool,
|
||||
hidden: bool,
|
||||
}
|
||||
|
||||
impl FloatFrame {
|
||||
/// On-screen width of panel `f` in this frame: the bar, plus the panel
|
||||
/// unless hidden.
|
||||
fn width(&self, f: crate::ui::dock::FloatPanel) -> f32 {
|
||||
if self.hidden {
|
||||
DOCK_FLOAT_BAR_W
|
||||
} else {
|
||||
f.w + DOCK_FLOAT_BAR_W
|
||||
}
|
||||
}
|
||||
|
||||
/// Left edge of the title bar.
|
||||
fn bar_x(&self, f: crate::ui::dock::FloatPanel) -> f32 {
|
||||
if self.bar_left {
|
||||
self.x
|
||||
} else {
|
||||
self.x + self.width(f) - DOCK_FLOAT_BAR_W
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// A floating panel's vertical title bar: close then the hide (auto-collapse)
|
||||
/// pin at the top, the panel's icon at the bottom with its title reading
|
||||
/// upward above it. Pressing the bar's free area drags the panel.
|
||||
|
||||
+3
-3
@@ -850,9 +850,9 @@ pub(super) struct OpenCADStudio {
|
||||
/// floating frame): hovered, being dragged, or just opened. Cleared when
|
||||
/// the pointer leaves.
|
||||
pub(crate) dock_peek: Option<crate::ui::dock::PanelId>,
|
||||
/// Reveal (`Some(pallet)`) or hide (`None`) waiting out the hover delay,
|
||||
/// with the generation its timer carries; any newer hover supersedes it.
|
||||
pub(crate) dock_hover_pending: Option<Option<crate::ui::dock::PanelId>>,
|
||||
/// Reveal or hide waiting out the hover delay, with the generation its
|
||||
/// timer carries; any newer hover supersedes it.
|
||||
pub(crate) dock_hover_pending: Option<crate::ui::dock::HoverPending>,
|
||||
pub(crate) dock_hover_gen: u64,
|
||||
/// What the pointer is dragging in the dock (pallet, group, width,
|
||||
/// splitter, floating size, Layer Manager column).
|
||||
|
||||
@@ -86,6 +86,15 @@ pub enum DockMsg {
|
||||
HoverSettled(u64),
|
||||
}
|
||||
|
||||
/// An auto-hide change waiting out [`DOCK_HOVER_DELAY`].
|
||||
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
|
||||
pub enum HoverPending {
|
||||
/// Reveal this pallet (its group, or its floating frame).
|
||||
Reveal(PanelId),
|
||||
/// Hide whatever auto-hiding pallet is revealed.
|
||||
Hide,
|
||||
}
|
||||
|
||||
/// How long the pointer must rest before an auto-hiding group reveals or
|
||||
/// hides, so passing over the strip doesn't flash groups open.
|
||||
pub const DOCK_HOVER_DELAY: std::time::Duration = std::time::Duration::from_millis(150);
|
||||
|
||||
Reference in new issue
Block a user