mirror of
https://github.com/storytold/vectorcraft.git
synced 2026-11-15 21:57:04 +00:00
Merge pull request #7859 from dotCooCoo/fix/peek-stays-until-pointer-moves
Window: panels shown from the edge hide only after the pointer moves away or a hold ends
This commit is contained in:
@@ -41,6 +41,8 @@ struct Shown {
|
||||
edge: Edge,
|
||||
/// When the pointer left them; `None` while it is over them or has not moved since they showed.
|
||||
left_at: Option<f64>,
|
||||
/// Whether a press, a modal dialog, a popup or a flyout held them open last frame.
|
||||
held: bool,
|
||||
}
|
||||
|
||||
/// The session's state of the panels shown from the edges.
|
||||
@@ -102,9 +104,11 @@ pub(super) fn update(app: &mut VectorcraftApp, ctx: &egui::Context, area: egui::
|
||||
return None;
|
||||
}
|
||||
let (now, pointer, down, moved) = ctx.input(|i| {
|
||||
// A release counts as moving away: a press may have held the panels while it left them.
|
||||
let moved =
|
||||
i.pointer.delta() != egui::Vec2::ZERO || i.pointer.any_released() || i.events.iter().any(|e| matches!(e, egui::Event::PointerGone));
|
||||
// A release counts as moving away: a press may have held the panels while it left them. A
|
||||
// pointer entering the window has no delta on its first frame, so the move event counts too.
|
||||
let moved = i.pointer.delta() != egui::Vec2::ZERO
|
||||
|| i.pointer.any_released()
|
||||
|| i.events.iter().any(|e| matches!(e, egui::Event::PointerMoved(_) | egui::Event::PointerGone));
|
||||
(i.time, i.pointer.hover_pos(), i.pointer.any_down(), moved)
|
||||
});
|
||||
// A workspace switched to while panels show may dock none on that side.
|
||||
@@ -123,11 +127,15 @@ pub(super) fn update(app: &mut VectorcraftApp, ctx: &egui::Context, area: egui::
|
||||
Edge::Right => p.x > uncovered.right(),
|
||||
}
|
||||
});
|
||||
if over || down || blocked || flyout {
|
||||
let held = down || blocked || flyout;
|
||||
if over || held {
|
||||
shown.left_at = None;
|
||||
} else if moved || pointer.is_none() {
|
||||
} else if moved || shown.held {
|
||||
// A hold that ends with the pointer away from them counts as moving away, as closing a
|
||||
// popup or flyout with Escape does not move the pointer.
|
||||
shown.left_at.get_or_insert(now);
|
||||
}
|
||||
shown.held = held;
|
||||
match shown.left_at {
|
||||
Some(left) if now - left >= GRACE => {
|
||||
st.shown = None;
|
||||
@@ -160,7 +168,7 @@ pub(super) fn update(app: &mut VectorcraftApp, ctx: &egui::Context, area: egui::
|
||||
};
|
||||
if now - since >= DELAY {
|
||||
st.resting = None;
|
||||
st.shown = Some(Shown { edge, left_at: None });
|
||||
st.shown = Some(Shown { edge, left_at: None, held: false });
|
||||
return Some(edge);
|
||||
}
|
||||
st.resting = Some((edge, since));
|
||||
@@ -233,7 +241,7 @@ pub(super) fn command(app: &mut VectorcraftApp, params: &Value) -> Result<Value,
|
||||
}
|
||||
let st = &mut app.dock_rt.peek;
|
||||
st.resting = None;
|
||||
st.shown = Some(Shown { edge, left_at: None });
|
||||
st.shown = Some(Shown { edge, left_at: None, held: false });
|
||||
Ok(json!(edge.id()))
|
||||
}
|
||||
None => {
|
||||
|
||||
@@ -642,6 +642,45 @@ fn window_panels_peek_rejects_what_it_cannot_show_and_changes_nothing() {
|
||||
h.app.ui.screen_mode = 0;
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn panels_shown_by_window_panels_peek_stay_until_the_pointer_moves_or_leaves_the_window() {
|
||||
let mut h = Harness::new();
|
||||
let wide = hide_with_tab(&mut h);
|
||||
assert_eq!(h.app.run("window.panels.peek", json!({"side": "right"})).unwrap(), json!("right"));
|
||||
wait(&mut h, peek::GRACE * 2.0);
|
||||
assert!(h.tab("properties").is_some(), "with no pointer movement, the panels stay");
|
||||
assert_eq!(inspect(&h.app, &h.ctx)["peek"], json!("right"));
|
||||
h.frame(vec![Event::PointerMoved(wide.center())]);
|
||||
wait(&mut h, peek::GRACE * 2.0);
|
||||
assert!(h.tab("properties").is_none(), "the pointer moved away from them, so they hide");
|
||||
// The pointer leaving the window counts as moving away.
|
||||
h.app.run("window.panels.peek", json!({"side": "right"})).unwrap();
|
||||
wait(&mut h, peek::GRACE * 2.0);
|
||||
assert!(h.tab("properties").is_some());
|
||||
h.frame(vec![Event::PointerGone]);
|
||||
wait(&mut h, peek::GRACE * 2.0);
|
||||
assert!(h.tab("properties").is_none(), "the pointer left the window, so they hide");
|
||||
assert_eq!(inspect(&h.app, &h.ctx)["peek"], Value::Null);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn panels_held_by_a_flyout_hide_after_it_closes_with_the_pointer_still_away_from_them() {
|
||||
let mut h = Harness::new();
|
||||
let wide = hide_with_tab(&mut h);
|
||||
// The pointer rests on the canvas, then outside the window, while a flyout holds the panels.
|
||||
for away in [vec![Event::PointerMoved(wide.center())], vec![Event::PointerGone]] {
|
||||
h.app.run("window.panels.peek", json!({"side": "right"})).unwrap();
|
||||
h.app.ui.open_panel = Some("swatches".into());
|
||||
h.frame(away);
|
||||
wait(&mut h, peek::GRACE * 2.0);
|
||||
assert!(h.tab("properties").is_some(), "an open flyout keeps them");
|
||||
h.app.ui.open_panel = None;
|
||||
wait(&mut h, peek::GRACE * 2.0);
|
||||
assert!(h.tab("properties").is_none(), "the flyout closed with the pointer away from them, so they hide");
|
||||
assert_eq!(inspect(&h.app, &h.ctx)["peek"], Value::Null);
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn edge_panels_are_the_docked_panels_on_each_side_of_the_canvas() {
|
||||
let layout = default_from(DockTab::ALL[0], &[], false, None, None);
|
||||
|
||||
Reference in New Issue
Block a user