forked from 1b-agent/opencadstudio-upstream
Dock: floating menu at the pointer, hover-only bar buttons, Allow docking, clip pallets
- The floating title bar's right-click menu opens where the pointer is, flipped to stay on screen; the Pallets submenu sits beside it. - Close and pin on a floating title bar only show while it is hovered, as on docked title bars. - New Allow docking check in that menu: off, dragging the window (or a pallet out of it) only floats it, never docks it on an edge. - Floating windows and stacked pallets clip their content, so a pallet sized below its content no longer draws outside its frame. Co-Authored-By: Claude Opus 5.5 <[email protected]> Claude-Session: https://claude.ai/code/session_013RyGiMXcsf9HTKfqDxaQGt
This commit is contained in:
27 files changed
+161
-25
No files matched your search
@@ -6166,6 +6166,7 @@ count-feature =
|
||||
.invalid-point = نقطة غير صالحة.
|
||||
|
||||
dock =
|
||||
.allow-docking = السماح بالإرساء
|
||||
.auto-hide = إخفاء تلقائي
|
||||
.dock-left = إرساء إلى اليسار
|
||||
.dock-right = إرساء إلى اليمين
|
||||
|
||||
@@ -6154,6 +6154,7 @@ count-feature =
|
||||
.invalid-point = Невалидна точка.
|
||||
|
||||
dock =
|
||||
.allow-docking = Разреши закачане
|
||||
.auto-hide = Автоматично скриване
|
||||
.dock-left = Закачи вляво
|
||||
.dock-right = Закачи вдясно
|
||||
|
||||
@@ -6151,6 +6151,7 @@ count-feature =
|
||||
.invalid-point = Neplatný bod.
|
||||
|
||||
dock =
|
||||
.allow-docking = Povolit ukotvení
|
||||
.auto-hide = Automaticky skrýt
|
||||
.dock-left = Ukotvit vlevo
|
||||
.dock-right = Ukotvit vpravo
|
||||
|
||||
@@ -6152,6 +6152,7 @@ count-feature =
|
||||
.invalid-point = Ungültiger Punkt.
|
||||
|
||||
dock =
|
||||
.allow-docking = Andocken zulassen
|
||||
.auto-hide = Automatisch ausblenden
|
||||
.dock-left = Links andocken
|
||||
.dock-right = Rechts andocken
|
||||
|
||||
@@ -6154,6 +6154,7 @@ count-feature =
|
||||
.invalid-point = Μη έγκυρο σημείο.
|
||||
|
||||
dock =
|
||||
.allow-docking = Να επιτρέπεται η πρόσδεση
|
||||
.auto-hide = Αυτόματη απόκρυψη
|
||||
.dock-left = Πρόσδεση αριστερά
|
||||
.dock-right = Πρόσδεση δεξιά
|
||||
|
||||
@@ -6155,6 +6155,7 @@ count-feature =
|
||||
.invalid-point = Invalid point.
|
||||
|
||||
dock =
|
||||
.allow-docking = Allow docking
|
||||
.auto-hide = Auto-hide
|
||||
.dock-left = Dock left
|
||||
.dock-right = Dock right
|
||||
|
||||
@@ -6154,6 +6154,7 @@ count-feature =
|
||||
.invalid-point = Punto no válido.
|
||||
|
||||
dock =
|
||||
.allow-docking = Permitir acoplar
|
||||
.auto-hide = Ocultar automáticamente
|
||||
.dock-left = Acoplar a la izquierda
|
||||
.dock-right = Acoplar a la derecha
|
||||
|
||||
@@ -6151,6 +6151,7 @@ count-feature =
|
||||
.invalid-point = Virheellinen piste.
|
||||
|
||||
dock =
|
||||
.allow-docking = Salli telakointi
|
||||
.auto-hide = Piilota automaattisesti
|
||||
.dock-left = Telakoi vasemmalle
|
||||
.dock-right = Telakoi oikealle
|
||||
|
||||
@@ -6153,6 +6153,7 @@ count-feature =
|
||||
.invalid-point = Point non valide.
|
||||
|
||||
dock =
|
||||
.allow-docking = Autoriser l'ancrage
|
||||
.auto-hide = Masquage automatique
|
||||
.dock-left = Ancrer à gauche
|
||||
.dock-right = Ancrer à droite
|
||||
|
||||
@@ -6142,6 +6142,7 @@ count-feature =
|
||||
.invalid-point = अमान्य बिंदु।
|
||||
|
||||
dock =
|
||||
.allow-docking = डॉकिंग की अनुमति दें
|
||||
.auto-hide = स्वतः छिपाएँ
|
||||
.dock-left = बाएँ डॉक करें
|
||||
.dock-right = दाएँ डॉक करें
|
||||
|
||||
@@ -6153,6 +6153,7 @@ count-feature =
|
||||
.invalid-point = Érvénytelen pont.
|
||||
|
||||
dock =
|
||||
.allow-docking = Dokkolás engedélyezése
|
||||
.auto-hide = Automatikus elrejtés
|
||||
.dock-left = Dokkolás balra
|
||||
.dock-right = Dokkolás jobbra
|
||||
|
||||
@@ -6153,6 +6153,7 @@ count-feature =
|
||||
.invalid-point = Punto non valido.
|
||||
|
||||
dock =
|
||||
.allow-docking = Consenti ancoraggio
|
||||
.auto-hide = Nascondi automaticamente
|
||||
.dock-left = Ancora a sinistra
|
||||
.dock-right = Ancora a destra
|
||||
|
||||
@@ -6142,6 +6142,7 @@ count-feature =
|
||||
.invalid-point = 点が無効です。
|
||||
|
||||
dock =
|
||||
.allow-docking = ドッキングを許可
|
||||
.auto-hide = 自動的に隠す
|
||||
.dock-left = 左にドッキング
|
||||
.dock-right = 右にドッキング
|
||||
|
||||
@@ -6153,6 +6153,7 @@ count-feature =
|
||||
.invalid-point = 점이 잘못되었습니다.
|
||||
|
||||
dock =
|
||||
.allow-docking = 도킹 허용
|
||||
.auto-hide = 자동 숨기기
|
||||
.dock-left = 왼쪽에 도킹
|
||||
.dock-right = 오른쪽에 도킹
|
||||
|
||||
@@ -6152,6 +6152,7 @@ count-feature =
|
||||
.invalid-point = Ongeldig punt.
|
||||
|
||||
dock =
|
||||
.allow-docking = Koppelen toestaan
|
||||
.auto-hide = Automatisch verbergen
|
||||
.dock-left = Links koppelen
|
||||
.dock-right = Rechts koppelen
|
||||
|
||||
@@ -6153,6 +6153,7 @@ count-feature =
|
||||
.invalid-point = Nieprawidłowy punkt.
|
||||
|
||||
dock =
|
||||
.allow-docking = Zezwalaj na dokowanie
|
||||
.auto-hide = Autoukrywanie
|
||||
.dock-left = Zadokuj po lewej
|
||||
.dock-right = Zadokuj po prawej
|
||||
|
||||
@@ -6154,6 +6154,7 @@ count-feature =
|
||||
.invalid-point = Ponto inválido.
|
||||
|
||||
dock =
|
||||
.allow-docking = Permitir encaixe
|
||||
.auto-hide = Ocultar automaticamente
|
||||
.dock-left = Encaixar à esquerda
|
||||
.dock-right = Encaixar à direita
|
||||
|
||||
@@ -6155,6 +6155,7 @@ count-feature =
|
||||
.invalid-point = Недопустимая точка.
|
||||
|
||||
dock =
|
||||
.allow-docking = Разрешить закрепление
|
||||
.auto-hide = Автоскрытие
|
||||
.dock-left = Закрепить слева
|
||||
.dock-right = Закрепить справа
|
||||
|
||||
@@ -6077,6 +6077,7 @@ count-feature =
|
||||
.invalid-point = Geçersiz nokta.
|
||||
|
||||
dock =
|
||||
.allow-docking = Yerleştirmeye izin ver
|
||||
.auto-hide = Otomatik gizle
|
||||
.dock-left = Sola yerleştir
|
||||
.dock-right = Sağa yerleştir
|
||||
|
||||
@@ -6137,6 +6137,7 @@ count-feature =
|
||||
.invalid-point = 无效的点。
|
||||
|
||||
dock =
|
||||
.allow-docking = 允许停靠
|
||||
.auto-hide = 自动隐藏
|
||||
.dock-left = 停靠到左侧
|
||||
.dock-right = 停靠到右侧
|
||||
|
||||
@@ -6149,6 +6149,7 @@ count-feature =
|
||||
.invalid-point = 無效的點。
|
||||
|
||||
dock =
|
||||
.allow-docking = 允許停駐
|
||||
.auto-hide = 自動隱藏
|
||||
.dock-left = 停駐到左側
|
||||
.dock-right = 停駐到右側
|
||||
|
||||
@@ -628,3 +628,20 @@ fn blockpalette_width_reset() {
|
||||
let _ = app.on_dock(crate::ui::dock::DockMsg::WidthReset(id));
|
||||
assert_eq!(app.dock.group_width(DockSide::Right, 0), 260.0);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn a_window_without_allow_docking_only_floats_when_dragged() {
|
||||
use crate::ui::dock::{DockMsg, DropTarget, PanelId};
|
||||
let mut app = dock_app();
|
||||
let _ = app.on_dock(DockMsg::FloatOut(PanelId::BlockPalette));
|
||||
let _ = app.on_dock(DockMsg::FloatDockingToggle(PanelId::BlockPalette));
|
||||
assert!(!app.dock.float_rect(PanelId::BlockPalette).unwrap().docking);
|
||||
// Dragged onto the left edge's strip, it stays a floating window.
|
||||
let _ = app.on_dock(DockMsg::FloatGrab(PanelId::BlockPalette));
|
||||
let _ = app.on_dock(DockMsg::DragMove(iced::Point::new(500.0, 300.0)));
|
||||
let _ = app.on_dock(DockMsg::DragMove(iced::Point::new(10.0, 60.0)));
|
||||
assert!(matches!(drag_target(&app), Some(DropTarget::Float { .. })));
|
||||
let _ = app.on_dock(DockMsg::DragRelease);
|
||||
assert!(app.dock.float_rect(PanelId::BlockPalette).is_some());
|
||||
assert_eq!(app.dock.location(PanelId::BlockPalette), None);
|
||||
}
|
||||
+38
-4
@@ -149,12 +149,20 @@ impl OpenCADStudio {
|
||||
}
|
||||
DockMsg::FloatMenu(id) => {
|
||||
self.dock_float_menu = id;
|
||||
self.dock_float_menu_at = self.dock_float_pointer;
|
||||
self.dock_float_menu_pallets = false;
|
||||
if let Some(id) = id {
|
||||
self.dock.raise_float(id);
|
||||
}
|
||||
}
|
||||
DockMsg::FloatMenuPallets(open) => self.dock_float_menu_pallets = open,
|
||||
DockMsg::FloatBarPointer(p) => self.dock_float_pointer = p,
|
||||
DockMsg::FloatDockingToggle(id) => {
|
||||
self.dock_float_menu = None;
|
||||
if self.dock.toggle_float_docking(id) {
|
||||
self.save_config();
|
||||
}
|
||||
}
|
||||
DockMsg::FloatMenuToggle(window, id) => {
|
||||
// Checked = open in this window: unchecking hides it.
|
||||
// Anything else (closed, docked, in another window) moves
|
||||
@@ -289,7 +297,13 @@ impl OpenCADStudio {
|
||||
}
|
||||
DropTarget::Float { x, y } => {
|
||||
let (w, h) = self.dock_float_size(panel);
|
||||
self.dock.float(FloatPanel::new(panel, x, y, w, h))
|
||||
// Pulled out of a window, it keeps the
|
||||
// window's 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)
|
||||
})
|
||||
}
|
||||
};
|
||||
}
|
||||
@@ -356,9 +370,18 @@ impl OpenCADStudio {
|
||||
grab
|
||||
};
|
||||
let target = if started {
|
||||
// A window that may not dock (or a pallet pulled out of
|
||||
// one) only floats.
|
||||
let floats_only = group.is_none()
|
||||
&& self.dock.float_rect(panel).is_some_and(|f| !f.docking);
|
||||
let found = if floats_only {
|
||||
self.dock_float_target(point, grab)
|
||||
} else {
|
||||
self.dock_drop_target(point, grab)
|
||||
};
|
||||
// A whole docked group moves between group positions or
|
||||
// floats; it cannot join another group.
|
||||
match (group, self.dock_drop_target(point, grab)) {
|
||||
match (group, found) {
|
||||
(Some(_), DropTarget::Join { .. }) => None,
|
||||
(_, found) => Some(found),
|
||||
}
|
||||
@@ -786,7 +809,7 @@ impl OpenCADStudio {
|
||||
) -> crate::ui::dock::DropTarget {
|
||||
use crate::app::config::DockSide;
|
||||
use crate::ui::dock::{DropTarget, StripHit, DOCK_EDGE_ZONE, DOCK_STRIP_W};
|
||||
let (ww, wh) = self.dock_workspace_size();
|
||||
let (ww, _) = self.dock_workspace_size();
|
||||
for side in [DockSide::Left, DockSide::Right] {
|
||||
let listed = !self.dock_visible_groups(side).is_empty();
|
||||
let from_edge = match side {
|
||||
@@ -841,8 +864,19 @@ impl OpenCADStudio {
|
||||
}
|
||||
}
|
||||
}
|
||||
self.dock_float_target(p, grab)
|
||||
}
|
||||
|
||||
/// Floating at workspace point `p`, held at `grab` from its top-left
|
||||
/// corner (kept on the workspace).
|
||||
pub(crate) fn dock_float_target(
|
||||
&self,
|
||||
p: iced::Point,
|
||||
grab: iced::Vector,
|
||||
) -> crate::ui::dock::DropTarget {
|
||||
let (ww, wh) = self.dock_workspace_size();
|
||||
let x = (p.x - grab.x).clamp(0.0, (ww - 60.0).max(0.0));
|
||||
let y = (p.y - grab.y).clamp(0.0, (wh - 30.0).max(0.0));
|
||||
DropTarget::Float { x, y }
|
||||
crate::ui::dock::DropTarget::Float { x, y }
|
||||
}
|
||||
}
|
||||
+44
-20
@@ -140,6 +140,7 @@ impl OpenCADStudio {
|
||||
.height(Length::FillPortion(crate::ui::dock::portion(
|
||||
group.weights[pos],
|
||||
)))
|
||||
.clip(true)
|
||||
.into(),
|
||||
);
|
||||
prev = Some(pos);
|
||||
@@ -474,7 +475,8 @@ impl OpenCADStudio {
|
||||
let (x, y, bar_left, hidden) = self.dock_float_frame(f);
|
||||
// Messages name the window by its first open pallet.
|
||||
let anchor = visible[0];
|
||||
let bar = floating_title_bar(&visible, self.dock.auto_hides(anchor), bar_left);
|
||||
let hovered = self.dock_title_hover.is_some_and(|p| f.contains(p));
|
||||
let bar = floating_title_bar(&visible, self.dock.auto_hides(anchor), bar_left, hovered);
|
||||
let content: Element<'_, Message> = if hidden {
|
||||
bar
|
||||
} else {
|
||||
@@ -511,6 +513,7 @@ impl OpenCADStudio {
|
||||
pallets.push(
|
||||
container(self.panel_body(*id, f.w, true, tab))
|
||||
.height(Length::FillPortion(crate::ui::dock::portion(weight)))
|
||||
.clip(true)
|
||||
.into(),
|
||||
);
|
||||
prev = Some(pos);
|
||||
@@ -535,8 +538,11 @@ impl OpenCADStudio {
|
||||
row![body, bar].into()
|
||||
}
|
||||
};
|
||||
// Clipped, so a pallet squeezed below its content's height never
|
||||
// draws outside the window.
|
||||
let framed = container(content)
|
||||
.height(Length::Fixed(f.h))
|
||||
.clip(true)
|
||||
.style(|theme: &Theme| container::Style {
|
||||
border: Border {
|
||||
color: theme.palette().background.strong.color,
|
||||
@@ -561,8 +567,8 @@ impl OpenCADStudio {
|
||||
}
|
||||
|
||||
/// The open right-click menu of a floating window: Pallets (a submenu
|
||||
/// to add or hide pallets in the window), Dock left and Dock right. It
|
||||
/// hangs beside the title bar, toward the window's inside.
|
||||
/// to add or hide pallets in the window), Allow docking, Dock left and
|
||||
/// Dock right. It opens at the pointer, flipped to stay on screen.
|
||||
fn dock_float_menu_overlay(&self) -> Option<Element<'_, Message>> {
|
||||
use crate::app::config::DockSide;
|
||||
use crate::ui::dock::{DockMsg, PanelId};
|
||||
@@ -571,17 +577,16 @@ impl OpenCADStudio {
|
||||
if self.dock_float_visible(f).is_empty() {
|
||||
return None;
|
||||
}
|
||||
let (ww, _) = self.dock_workspace_size();
|
||||
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 };
|
||||
// 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 max_x = (ww - DOCK_MENU_W).max(0.0);
|
||||
let menu_x = if bar_left {
|
||||
bar_x + DOCK_FLOAT_BAR_W + 2.0
|
||||
} else {
|
||||
bar_x - DOCK_MENU_W - 2.0
|
||||
}
|
||||
.clamp(0.0, max_x);
|
||||
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, max_x);
|
||||
let menu_y = at.y.min(wh - FLOAT_MENU_H).max(0.0);
|
||||
let open = self.dock_float_menu_pallets;
|
||||
// Hovering a row opens (Pallets) or closes (the others) the submenu.
|
||||
let item = |label: Element<'static, Message>, press: DockMsg, sub: bool| -> Element<'static, Message> {
|
||||
@@ -607,9 +612,17 @@ impl OpenCADStudio {
|
||||
background: Some(Background::Color(theme.palette().background.neutral.color)),
|
||||
..Default::default()
|
||||
});
|
||||
let check: Element<'static, Message> = if f.docking {
|
||||
crate::ui::icons::themed(crate::ui::icons::CHECK, 12.0)
|
||||
} else {
|
||||
Space::new().width(12).height(12).into()
|
||||
};
|
||||
let docking = row![text(t!("Allow docking")).size(12).width(Fill), check]
|
||||
.align_y(iced::Center);
|
||||
let main = column![
|
||||
item(pallets.into(), DockMsg::FloatMenuPallets(!open), true),
|
||||
container(separator).padding([3, 4]),
|
||||
item(docking.into(), DockMsg::FloatDockingToggle(anchor), false),
|
||||
item(
|
||||
text(t!("Dock left")).size(12).into(),
|
||||
DockMsg::DockTo(anchor, DockSide::Left),
|
||||
@@ -623,24 +636,22 @@ impl OpenCADStudio {
|
||||
]
|
||||
.spacing(1)
|
||||
.padding(4);
|
||||
let mut layers = vec![place_at(menu_frame(main.into()), menu_x, y + 4.0)];
|
||||
let mut layers = vec![place_at(menu_frame(main.into()), menu_x, menu_y)];
|
||||
if open {
|
||||
let checked: Vec<_> = PanelId::ALL
|
||||
.iter()
|
||||
.map(|p| (*p, f.contains(*p) && self.dock_panel_visible(*p)))
|
||||
.collect();
|
||||
let toggle = move |id| Message::Dock(DockMsg::FloatMenuToggle(anchor, id));
|
||||
// Beside the menu, on the side it opened toward, unless there is
|
||||
// no room there.
|
||||
let right = menu_x + 2.0 * DOCK_MENU_W + 2.0 <= ww;
|
||||
let left = menu_x - DOCK_MENU_W - 2.0 >= 0.0;
|
||||
let sub_x = if (bar_left && right) || !left {
|
||||
// To the right of the menu, or its left when there is no room.
|
||||
let sub_x = if menu_x + 2.0 * DOCK_MENU_W + 2.0 <= ww {
|
||||
menu_x + DOCK_MENU_W + 2.0
|
||||
} else {
|
||||
menu_x - DOCK_MENU_W - 2.0
|
||||
}
|
||||
.clamp(0.0, max_x);
|
||||
layers.push(place_at(dock_pallet_menu(&checked, toggle), sub_x, y + 4.0));
|
||||
let sub_y = menu_y.min(wh - PALLET_MENU_H).max(0.0);
|
||||
layers.push(place_at(dock_pallet_menu(&checked, toggle), sub_x, sub_y));
|
||||
}
|
||||
Some(
|
||||
iced::widget::Stack::with_children(layers)
|
||||
@@ -954,6 +965,7 @@ fn floating_title_bar(
|
||||
visible: &[crate::ui::dock::PanelId],
|
||||
auto_collapse: bool,
|
||||
on_left: bool,
|
||||
hovered: bool,
|
||||
) -> Element<'static, Message> {
|
||||
use crate::ui::dock::DockMsg;
|
||||
let anchor = visible[0];
|
||||
@@ -962,9 +974,14 @@ fn floating_title_bar(
|
||||
} else {
|
||||
iced::widget::tooltip::Position::Right
|
||||
};
|
||||
let close = crate::ui::dock::close_button(DockMsg::FloatClose(anchor), tip);
|
||||
let pin = crate::ui::dock::pin_button(anchor, auto_collapse, tip);
|
||||
let mut bar = column![close, pin].spacing(2);
|
||||
// Close and pin only show while the pointer is over the bar, as on a
|
||||
// docked title bar.
|
||||
let mut bar = column![].spacing(2);
|
||||
if hovered {
|
||||
bar = bar
|
||||
.push(crate::ui::dock::close_button(DockMsg::FloatClose(anchor), tip))
|
||||
.push(crate::ui::dock::pin_button(anchor, auto_collapse, tip));
|
||||
}
|
||||
if let [id] = visible {
|
||||
let title = canvas(VBarLabel {
|
||||
text: t!(id.title()).into_owned(),
|
||||
@@ -1000,6 +1017,9 @@ fn floating_title_bar(
|
||||
}))
|
||||
.on_press(Message::Dock(DockMsg::FloatGrab(anchor)))
|
||||
.on_right_press(Message::Dock(DockMsg::FloatMenu(Some(anchor))))
|
||||
.on_enter(Message::Dock(DockMsg::TitleHover(anchor)))
|
||||
.on_move(|p| Message::Dock(DockMsg::FloatBarPointer(p)))
|
||||
.on_exit(Message::Dock(DockMsg::TitleHoverEnd(anchor)))
|
||||
// Double-click docks it against the edge its title bar faces.
|
||||
.on_double_click(Message::Dock(DockMsg::DockTo(
|
||||
anchor,
|
||||
@@ -1058,6 +1078,10 @@ fn dock_divider(id: crate::ui::dock::PanelId) -> Element<'static, Message> {
|
||||
|
||||
/// Width of the icon strip's pallet menu.
|
||||
const DOCK_MENU_W: f32 = 230.0;
|
||||
/// Rough heights of a floating window's menu and of a pallet menu, to keep
|
||||
/// them on screen.
|
||||
const FLOAT_MENU_H: f32 = 150.0;
|
||||
const PALLET_MENU_H: f32 = 270.0;
|
||||
|
||||
/// A pallet menu (an edge's + button, a floating window's Pallets
|
||||
/// submenu), styled like the right-click menu: one row per pallet with its
|
||||
|
||||
@@ -869,6 +869,10 @@ pub(super) struct OpenCADStudio {
|
||||
/// is open, and whether its Pallets submenu shows.
|
||||
pub(crate) dock_float_menu: Option<crate::ui::dock::PanelId>,
|
||||
pub(crate) dock_float_menu_pallets: bool,
|
||||
/// Pointer position over a floating title bar (bar-local), and where
|
||||
/// its open menu was asked for.
|
||||
pub(crate) dock_float_pointer: iced::Point,
|
||||
pub(crate) dock_float_menu_at: iced::Point,
|
||||
/// Group whose edge band (group grip) the pointer is over.
|
||||
pub(crate) dock_grip_hover: Option<(crate::app::config::DockSide, usize)>,
|
||||
/// Reference-table column currently being width-resized (column index),
|
||||
@@ -4303,6 +4307,8 @@ impl OpenCADStudio {
|
||||
dock_hover_gen: 0,
|
||||
dock_float_menu: None,
|
||||
dock_float_menu_pallets: false,
|
||||
dock_float_pointer: iced::Point::ORIGIN,
|
||||
dock_float_menu_at: iced::Point::ORIGIN,
|
||||
dock_drag: None,
|
||||
dock_drag_last: None,
|
||||
dock_title_hover: None,
|
||||
|
||||
@@ -5755,6 +5755,7 @@ pub(super) fn message_attribute(source: &str) -> Option<(&'static str, &'static
|
||||
"Block \"{part}\" cannot be found." => Some(("count-feature", "block-not-found")),
|
||||
"Invalid point." => Some(("count-feature", "invalid-point")),
|
||||
"Auto-hide" => Some(("dock", "auto-hide")),
|
||||
"Allow docking" => Some(("dock", "allow-docking")),
|
||||
"Dock left" => Some(("dock", "dock-left")),
|
||||
"Dock right" => Some(("dock", "dock-right")),
|
||||
"New group" => Some(("dock", "new-group")),
|
||||
|
||||
+34
-1
@@ -85,6 +85,12 @@ pub enum DockMsg {
|
||||
FloatMenu(Option<PanelId>),
|
||||
/// Show (`true`) or hide the floating menu's Pallets submenu.
|
||||
FloatMenuPallets(bool),
|
||||
/// Floating menu's Allow docking check: flip it for the window holding
|
||||
/// the pallet.
|
||||
FloatDockingToggle(PanelId),
|
||||
/// The pointer moved over a floating title bar, at this point in it
|
||||
/// (where its right-click menu opens).
|
||||
FloatBarPointer(iced::Point),
|
||||
/// Pallets submenu pick (window, pallet): hide the pallet when it shows
|
||||
/// in the window, else add it to the window and open it.
|
||||
FloatMenuToggle(PanelId, PanelId),
|
||||
@@ -342,6 +348,9 @@ pub struct FloatPanel {
|
||||
pub y: f32,
|
||||
pub w: f32,
|
||||
pub h: f32,
|
||||
/// Dragging the window (or a pallet out of it) may dock it on an edge;
|
||||
/// off, it only ever floats.
|
||||
pub docking: bool,
|
||||
}
|
||||
|
||||
/// On-disk form of a floating window. Configs from before floating groups
|
||||
@@ -358,6 +367,12 @@ struct FloatRepr {
|
||||
y: f32,
|
||||
w: f32,
|
||||
h: f32,
|
||||
#[serde(default = "docking_default")]
|
||||
docking: bool,
|
||||
}
|
||||
|
||||
fn docking_default() -> bool {
|
||||
true
|
||||
}
|
||||
|
||||
impl From<FloatRepr> for FloatPanel {
|
||||
@@ -373,6 +388,7 @@ impl From<FloatRepr> for FloatPanel {
|
||||
y: r.y,
|
||||
w: r.w,
|
||||
h: r.h,
|
||||
docking: r.docking,
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -386,6 +402,7 @@ impl FloatPanel {
|
||||
y,
|
||||
w,
|
||||
h,
|
||||
docking: true,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -830,7 +847,14 @@ impl DockState {
|
||||
}
|
||||
let g = self.groups_mut(side).remove(group);
|
||||
self.after_group_removed(side, group);
|
||||
let mut f = FloatPanel { group: g, x, y, w, h };
|
||||
let mut f = FloatPanel {
|
||||
group: g,
|
||||
x,
|
||||
y,
|
||||
w,
|
||||
h,
|
||||
docking: true,
|
||||
};
|
||||
f.heal();
|
||||
self.floating.push(f);
|
||||
true
|
||||
@@ -902,6 +926,15 @@ impl DockState {
|
||||
true
|
||||
}
|
||||
|
||||
/// Flip whether dragging the floating window holding `id` may dock it.
|
||||
pub fn toggle_float_docking(&mut self, id: PanelId) -> bool {
|
||||
let Some(i) = self.float_index(id) else {
|
||||
return false;
|
||||
};
|
||||
self.floating[i].docking = !self.floating[i].docking;
|
||||
true
|
||||
}
|
||||
|
||||
/// Bring the floating window holding `id` to the front.
|
||||
pub fn raise_float(&mut self, id: PanelId) {
|
||||
if let Some(i) = self.float_index(id) {
|
||||
|
||||
Reference in new issue
Block a user