mirror of
https://github.com/emilk/egui.git
synced 2026-06-26 22:53:14 -04:00
Drag-to-close panels (#8182)
* Closes https://github.com/emilk/egui/pull/7254 You can now drag-to-close a panel. Also drag-to-expand panels. This is a breaking change: the animated panel functions now take a `open: &mut bool` instead of `open: bool`. This is only enabled for resizable panels
This commit is contained in:
@@ -0,0 +1,3 @@
|
||||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:eba6e690937fbbd22c8edfce14078f50998e968324d8073d5db5829493d957e0
|
||||
size 5292
|
||||
@@ -0,0 +1,3 @@
|
||||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:84e6030760561e308a190d2eb9781f53b896fbea5d11a3548b73d68c49f4d525
|
||||
size 65797
|
||||
@@ -0,0 +1,3 @@
|
||||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:84e6030760561e308a190d2eb9781f53b896fbea5d11a3548b73d68c49f4d525
|
||||
size 65797
|
||||
@@ -0,0 +1,3 @@
|
||||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:bcf9871c19199c94cfbc83818b4f70fe9fab5c396a3fb32cb79b713e9145bcae
|
||||
size 3001
|
||||
@@ -0,0 +1,3 @@
|
||||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:cf09470a6628e62421bfa754ce238dd13820ba0bf8146ae835e539874d39a150
|
||||
size 4882
|
||||
157
tests/egui_tests/tests/test_panel_drag.rs
Normal file
157
tests/egui_tests/tests/test_panel_drag.rs
Normal file
@@ -0,0 +1,157 @@
|
||||
//! Snapshot tests for `Panel`'s drag-to-close and drag-to-expand gestures.
|
||||
//!
|
||||
//! Covers:
|
||||
//! * [`Panel::show_animated_inside`] — drag-to-close on a `Left` panel.
|
||||
//! * [`Panel::show_animated_between_inside`] — drag-to-close on the expanded panel
|
||||
//! followed by drag-to-expand on the collapsed panel, both via the shared
|
||||
//! resize handle.
|
||||
|
||||
use egui::{Panel, Pos2, Vec2};
|
||||
use egui_kittest::{Harness, SnapshotResults};
|
||||
|
||||
/// Pure-data state for the kittest UI closure.
|
||||
#[derive(Default)]
|
||||
struct State {
|
||||
is_expanded: bool,
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn drag_to_close_animated_inside() {
|
||||
let mut results = SnapshotResults::new();
|
||||
|
||||
let mut harness = Harness::builder()
|
||||
.with_size(Vec2::new(400.0, 200.0))
|
||||
.build_ui_state(
|
||||
|ui, state: &mut State| {
|
||||
Panel::left("test_left_panel")
|
||||
.resizable(true)
|
||||
.default_size(120.0)
|
||||
.min_size(60.0)
|
||||
.show_animated_inside(ui, &mut state.is_expanded, |ui| {
|
||||
ui.label("Left panel content");
|
||||
});
|
||||
egui::CentralPanel::default().show_inside(ui, |ui| {
|
||||
ui.label("Central");
|
||||
});
|
||||
},
|
||||
State { is_expanded: true },
|
||||
);
|
||||
|
||||
harness.run();
|
||||
assert!(harness.state().is_expanded, "should start expanded");
|
||||
results.add(harness.try_snapshot("panel_drag/inside_initial"));
|
||||
|
||||
// Query the actual resize edge from PanelState (avoids assumptions about
|
||||
// Frame margins and the harness's ui padding).
|
||||
let panel_state = egui::PanelState::load(&harness.ctx, egui::Id::new("test_left_panel"))
|
||||
.expect("PanelState should be persisted after the first frame");
|
||||
let resize_x = panel_state.outer_rect.right();
|
||||
let resize_y = panel_state.outer_rect.center().y;
|
||||
|
||||
let drag_start = Pos2::new(resize_x, resize_y);
|
||||
let drag_end = Pos2::new(resize_x - 200.0, resize_y);
|
||||
|
||||
harness.drag_at(drag_start);
|
||||
harness.run();
|
||||
harness.hover_at(drag_end);
|
||||
harness.run();
|
||||
harness.drop_at(drag_end);
|
||||
harness.run();
|
||||
|
||||
assert!(
|
||||
!harness.state().is_expanded,
|
||||
"drag past min_size should have closed the panel"
|
||||
);
|
||||
results.add(harness.try_snapshot("panel_drag/inside_closed"));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn drag_to_close_and_reopen_animated_between() {
|
||||
let mut results = SnapshotResults::new();
|
||||
|
||||
let panel_size = 400.0_f32;
|
||||
let expanded_size = 120.0_f32;
|
||||
let collapsed_size = 28.0_f32;
|
||||
|
||||
let mut harness = Harness::builder()
|
||||
.with_size(Vec2::new(panel_size, 300.0))
|
||||
.build_ui_state(
|
||||
|ui, state: &mut State| {
|
||||
let collapsed = Panel::bottom("between_collapsed")
|
||||
.resizable(true)
|
||||
.exact_size(collapsed_size);
|
||||
let expanded = Panel::bottom("between_expanded")
|
||||
.resizable(true)
|
||||
.default_size(expanded_size);
|
||||
Panel::show_animated_between_inside(
|
||||
ui,
|
||||
&mut state.is_expanded,
|
||||
collapsed,
|
||||
expanded,
|
||||
|ui, expanded| {
|
||||
if expanded {
|
||||
ui.heading("Expanded panel");
|
||||
ui.separator();
|
||||
for i in 0..6 {
|
||||
ui.label(format!(
|
||||
"Row {i}: filler content so the \
|
||||
expanded panel is clearly taller than the \
|
||||
collapsed one in the snapshot."
|
||||
));
|
||||
}
|
||||
} else {
|
||||
ui.label("Collapsed");
|
||||
}
|
||||
},
|
||||
);
|
||||
egui::CentralPanel::default().show_inside(ui, |ui| {
|
||||
ui.label("Central");
|
||||
});
|
||||
},
|
||||
State { is_expanded: true },
|
||||
);
|
||||
|
||||
harness.run();
|
||||
assert!(harness.state().is_expanded, "should start expanded");
|
||||
results.add(harness.try_snapshot("panel_drag/between_initial_expanded"));
|
||||
|
||||
// Drag-to-close: grab the top edge of the expanded bottom panel and drag
|
||||
// it down past the panel's minimum height to collapse.
|
||||
let expanded_state = egui::PanelState::load(&harness.ctx, egui::Id::new("between_expanded"))
|
||||
.expect("expanded PanelState should be persisted");
|
||||
let expanded_resize_y = expanded_state.outer_rect.top();
|
||||
let drag_x = expanded_state.outer_rect.center().x;
|
||||
let bottom_y = expanded_state.outer_rect.bottom();
|
||||
|
||||
harness.drag_at(Pos2::new(drag_x, expanded_resize_y));
|
||||
harness.run();
|
||||
harness.hover_at(Pos2::new(drag_x, bottom_y - 1.0));
|
||||
harness.run();
|
||||
harness.drop_at(Pos2::new(drag_x, bottom_y - 1.0));
|
||||
harness.run();
|
||||
|
||||
assert!(
|
||||
!harness.state().is_expanded,
|
||||
"drag past min should have closed the expanded panel"
|
||||
);
|
||||
results.add(harness.try_snapshot("panel_drag/between_collapsed"));
|
||||
|
||||
// Drag-to-expand: grab the top edge of the (now visible) collapsed panel
|
||||
// and drag it upward past the collapsed panel's exact_size cap.
|
||||
let collapsed_state = egui::PanelState::load(&harness.ctx, egui::Id::new("between_collapsed"))
|
||||
.expect("collapsed PanelState should be persisted");
|
||||
let collapsed_resize_y = collapsed_state.outer_rect.top();
|
||||
|
||||
harness.drag_at(Pos2::new(drag_x, collapsed_resize_y));
|
||||
harness.run();
|
||||
harness.hover_at(Pos2::new(drag_x, collapsed_resize_y - 200.0));
|
||||
harness.run();
|
||||
harness.drop_at(Pos2::new(drag_x, collapsed_resize_y - 200.0));
|
||||
harness.run();
|
||||
|
||||
assert!(
|
||||
harness.state().is_expanded,
|
||||
"drag past collapsed exact_size should have reopened the panel"
|
||||
);
|
||||
results.add(harness.try_snapshot("panel_drag/between_reopened"));
|
||||
}
|
||||
Reference in New Issue
Block a user