mirror of
https://github.com/storytold/craft-libs.git
synced 2026-11-10 20:42:12 +00:00
Docking: hide 'Move to group' when no panel accepts the move (lightcraft#1768)
A movable panel's context menu always offered 'Move to group', even
when the layout held no other panel that accepts tabs — one open panel
showed an empty submenu. Layout gains move_targets() (the same filter
the menu applies: every other panel that accepts_tabs), the menu renders
only when it is non-empty, and a test pins the lone-panel and
protected-anchor cases.
(cherry picked from commit 671463c1af)
This commit is contained in:
1 parent
5ac5d26be1
commit
c4b007706d
3 files changed
+25
-3
No files matched your search
@@ -287,6 +287,12 @@ impl<P: Clone + Eq + Hash> Layout<P> {
|
||||
self.panels().contains(&panel)
|
||||
}
|
||||
|
||||
/// The panels `panel` can join as a tab: every other panel whose permissions accept tabs.
|
||||
/// A "Move to group" menu with an empty answer has nothing to offer and stays hidden.
|
||||
pub fn move_targets(&self, panel: &P, permissions: impl Fn(&P) -> Permissions) -> Vec<&P> {
|
||||
self.panels().into_iter().filter(|target| *target != panel && permissions(target).accepts_tabs).collect()
|
||||
}
|
||||
|
||||
/// Capture a panel's nearest surviving group/split neighbor before hiding it.
|
||||
pub fn location(&self, panel: &P) -> Result<Location<P>, DockError> {
|
||||
self.validate()?;
|
||||
|
||||
@@ -712,12 +712,12 @@ impl<P: Clone + Eq + Hash + Debug + Send + Sync + 'static> Renderer<'_, P> {
|
||||
ui.close();
|
||||
}
|
||||
}
|
||||
if policy.movable {
|
||||
if policy.movable && !self.layout.move_targets(panel, self.permissions).is_empty() {
|
||||
let text = self.content.action_label(ui, &self.style.move_label, &self.style.font, self.style.text);
|
||||
let response = ui.menu_button(text, |ui| {
|
||||
egui::ScrollArea::vertical().max_height(360.0).show(ui, |ui| {
|
||||
for target in self.layout.panels() {
|
||||
if target != panel && (self.permissions)(target).accepts_tabs && self.menu_label(ui, target).clicked() {
|
||||
for target in self.layout.move_targets(panel, self.permissions) {
|
||||
if self.menu_label(ui, target).clicked() {
|
||||
self.output.actions.push(Action::Move {
|
||||
panel: panel.clone(),
|
||||
anchor: target.clone(),
|
||||
|
||||
@@ -51,6 +51,22 @@ fn detach_redock_merge_and_collapse_empty_source_containers() {
|
||||
assert_eq!(layout.panels().len(), 6);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn move_targets_skip_the_panel_itself_and_protected_anchors() {
|
||||
let layout = sample();
|
||||
let all = |_: &u32| Permissions::default();
|
||||
let targets = layout.move_targets(&1, all);
|
||||
assert_eq!(targets.len(), 5);
|
||||
assert!(!targets.contains(&&1));
|
||||
let guarded = |p: &u32| if *p == 3 { Permissions::PROTECTED } else { Permissions::default() };
|
||||
assert!(!layout.move_targets(&1, guarded).contains(&&3));
|
||||
|
||||
// A lone panel has nowhere to go — its "Move to group" menu hides
|
||||
// (storytold/lightcraft#1768).
|
||||
let single = Layout { root: Some(tabs(&[1], 0)), floating: Vec::new() };
|
||||
assert!(single.move_targets(&1, all).is_empty());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn invalid_moves_are_atomic_including_after_a_source_would_have_been_removed() {
|
||||
let layout = sample();
|
||||
|
||||
Reference in new issue
Block a user