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.
|
/// whichever panel the message names.
|
||||||
pub(crate) fn on_dock(&mut self, m: crate::ui::dock::DockMsg) -> iced::Task<Message> {
|
pub(crate) fn on_dock(&mut self, m: crate::ui::dock::DockMsg) -> iced::Task<Message> {
|
||||||
use crate::app::config::DockSide;
|
use crate::app::config::DockSide;
|
||||||
use crate::ui::dock::{DockDrag, DockMsg, DropTarget, FloatPanel};
|
use crate::ui::dock::{DockDrag, DockMsg, DropTarget, FloatPanel, HoverPending};
|
||||||
match m {
|
match m {
|
||||||
DockMsg::DockGrab(id) => self.dock_begin(DockDrag::moving(id, None), Some(id)),
|
DockMsg::DockGrab(id) => self.dock_begin(DockDrag::moving(id, None), Some(id)),
|
||||||
DockMsg::IconPress(id) => {
|
DockMsg::IconPress(id) => {
|
||||||
@@ -160,7 +160,7 @@ impl OpenCADStudio {
|
|||||||
if self.dock_peek == Some(id) {
|
if self.dock_peek == Some(id) {
|
||||||
self.dock_hover_cancel();
|
self.dock_hover_cancel();
|
||||||
} else {
|
} 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()
|
if self.dock_drag.is_none()
|
||||||
&& self.dock_peek.is_some_and(|id| self.dock.auto_hides(id))
|
&& 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.
|
// Left before a pending reveal ran out: it never happens.
|
||||||
self.dock_hover_cancel();
|
self.dock_hover_cancel();
|
||||||
}
|
}
|
||||||
DockMsg::HoverStay => {
|
DockMsg::HoverStay => {
|
||||||
if self.dock_hover_pending == Some(None) {
|
if self.dock_hover_pending == Some(HoverPending::Hide) {
|
||||||
self.dock_hover_cancel();
|
self.dock_hover_cancel();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
DockMsg::HoverSettled(gen) => {
|
DockMsg::HoverSettled(gen) => {
|
||||||
if gen == self.dock_hover_gen && self.dock_drag.is_none() {
|
if gen == self.dock_hover_gen && self.dock_drag.is_none() {
|
||||||
match self.dock_hover_pending.take() {
|
match self.dock_hover_pending.take() {
|
||||||
Some(Some(id)) if self.dock.auto_hides(id) => self.dock_reveal(id),
|
Some(HoverPending::Reveal(id)) if self.dock.auto_hides(id) => {
|
||||||
Some(None) if self.dock_peek.is_some_and(|id| 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;
|
self.dock_peek = None;
|
||||||
}
|
}
|
||||||
_ => {}
|
_ => {}
|
||||||
@@ -280,13 +284,13 @@ impl OpenCADStudio {
|
|||||||
grab
|
grab
|
||||||
};
|
};
|
||||||
let target = if started {
|
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.
|
// A floating panel that may not dock only floats.
|
||||||
let found = match self.dock.float_rect(panel) {
|
let found = match self.dock.float_rect(panel) {
|
||||||
Some(f) if !f.docking => self.dock_float_target(point, grab),
|
Some(f) if !f.docking => self.dock_float_target(point, grab),
|
||||||
_ => self.dock_drop_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) {
|
match (group, found) {
|
||||||
(Some(_), found @ DropTarget::Edge { .. }) | (None, found) => Some(found),
|
(Some(_), found @ DropTarget::Edge { .. }) | (None, found) => Some(found),
|
||||||
(Some(_), _) => None,
|
(Some(_), _) => None,
|
||||||
@@ -381,11 +385,9 @@ impl OpenCADStudio {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Bring `id` into view: show its group on its edge and, where it
|
/// Arm a delayed reveal or hide; it applies when its timer reports back
|
||||||
/// auto-hides, keep it revealed until the pointer leaves.
|
/// unless a newer hover superseded it.
|
||||||
/// Arm a delayed reveal (`Some`) or hide (`None`); it applies when its
|
fn dock_hover_arm(&mut self, target: crate::ui::dock::HoverPending) -> iced::Task<Message> {
|
||||||
/// timer reports back unless a newer hover superseded it.
|
|
||||||
fn dock_hover_arm(&mut self, target: Option<crate::ui::dock::PanelId>) -> iced::Task<Message> {
|
|
||||||
self.dock_hover_gen = self.dock_hover_gen.wrapping_add(1);
|
self.dock_hover_gen = self.dock_hover_gen.wrapping_add(1);
|
||||||
self.dock_hover_pending = Some(target);
|
self.dock_hover_pending = Some(target);
|
||||||
let gen = self.dock_hover_gen;
|
let gen = self.dock_hover_gen;
|
||||||
@@ -400,6 +402,8 @@ impl OpenCADStudio {
|
|||||||
self.dock_hover_pending = None;
|
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) {
|
pub(crate) fn dock_reveal(&mut self, id: crate::ui::dock::PanelId) {
|
||||||
self.dock.show_group_of(id);
|
self.dock.show_group_of(id);
|
||||||
self.dock_peek = Some(id);
|
self.dock_peek = Some(id);
|
||||||
|
|||||||
+46
-13
@@ -444,7 +444,7 @@ impl OpenCADStudio {
|
|||||||
tab: &'a DocumentTab,
|
tab: &'a DocumentTab,
|
||||||
) -> Element<'a, Message> {
|
) -> Element<'a, Message> {
|
||||||
use crate::ui::dock::DockMsg;
|
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 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 bar = floating_title_bar(f.id, self.dock.auto_collapse(f.id), bar_left, hovered);
|
||||||
let content: Element<'_, Message> = if hidden {
|
let content: Element<'_, Message> = if hidden {
|
||||||
@@ -519,10 +519,8 @@ impl OpenCADStudio {
|
|||||||
place_at(panel.into(), x, y)
|
place_at(panel.into(), x, y)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Where floating panel `f` draws: its top-left corner, whether its
|
/// Where floating panel `f` draws.
|
||||||
/// title bar is on the left, and whether it is hidden down to that bar
|
fn dock_float_frame(&self, f: crate::ui::dock::FloatPanel) -> FloatFrame {
|
||||||
/// (auto-hide, not hovered).
|
|
||||||
fn dock_float_frame(&self, f: crate::ui::dock::FloatPanel) -> (f32, f32, bool, bool) {
|
|
||||||
let (ww, wh) = self.dock_workspace_size();
|
let (ww, wh) = self.dock_workspace_size();
|
||||||
// The bar faces the nearer workspace edge; while resizing, it stays
|
// The bar faces the nearer workspace edge; while resizing, it stays
|
||||||
// opposite the grip being dragged so it cannot flip mid-drag.
|
// 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,
|
_ => 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 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.
|
// 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 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.
|
// Keep the panel on screen when the window shrank since it was placed.
|
||||||
let x = x.min(ww - total_w).max(0.0);
|
FloatFrame {
|
||||||
let y = f.y.min(wh - f.h).max(0.0);
|
x: x.min(ww - frame.width(f)).max(0.0),
|
||||||
(x, y, bar_left, hidden)
|
y: f.y.min(wh - f.h).max(0.0),
|
||||||
|
..frame
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// The open right-click menu of a floating title bar: Allow docking,
|
/// The open right-click menu of a floating title bar: Allow docking,
|
||||||
@@ -554,11 +554,12 @@ impl OpenCADStudio {
|
|||||||
return None;
|
return None;
|
||||||
}
|
}
|
||||||
let (ww, wh) = self.dock_workspace_size();
|
let (ww, wh) = self.dock_workspace_size();
|
||||||
let (x, y, bar_left, hidden) = self.dock_float_frame(f);
|
let frame = 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 };
|
|
||||||
// Where the right-click happened, in the workspace.
|
// 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 = 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_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);
|
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.
|
/// Width of a floating panel's vertical title bar.
|
||||||
const DOCK_FLOAT_BAR_W: f32 = 28.0;
|
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)
|
/// 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
|
/// 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.
|
/// 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
|
/// floating frame): hovered, being dragged, or just opened. Cleared when
|
||||||
/// the pointer leaves.
|
/// the pointer leaves.
|
||||||
pub(crate) dock_peek: Option<crate::ui::dock::PanelId>,
|
pub(crate) dock_peek: Option<crate::ui::dock::PanelId>,
|
||||||
/// Reveal (`Some(pallet)`) or hide (`None`) waiting out the hover delay,
|
/// Reveal or hide waiting out the hover delay, with the generation its
|
||||||
/// with the generation its timer carries; any newer hover supersedes it.
|
/// timer carries; any newer hover supersedes it.
|
||||||
pub(crate) dock_hover_pending: Option<Option<crate::ui::dock::PanelId>>,
|
pub(crate) dock_hover_pending: Option<crate::ui::dock::HoverPending>,
|
||||||
pub(crate) dock_hover_gen: u64,
|
pub(crate) dock_hover_gen: u64,
|
||||||
/// What the pointer is dragging in the dock (pallet, group, width,
|
/// What the pointer is dragging in the dock (pallet, group, width,
|
||||||
/// splitter, floating size, Layer Manager column).
|
/// splitter, floating size, Layer Manager column).
|
||||||
|
|||||||
@@ -86,6 +86,15 @@ pub enum DockMsg {
|
|||||||
HoverSettled(u64),
|
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
|
/// How long the pointer must rest before an auto-hiding group reveals or
|
||||||
/// hides, so passing over the strip doesn't flash groups open.
|
/// 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);
|
pub const DOCK_HOVER_DELAY: std::time::Duration = std::time::Duration::from_millis(150);
|
||||||
|
|||||||
Reference in new issue
Block a user