mirror of
https://github.com/storytold/figcraft.git
synced 2026-10-26 19:36:46 -06:00
#272: refuse page drops released outside the visible pages list
A page drag released over the Layers below could still reorder against a row scrolled out of view, and a layer dropped there could move to that page. The drop now counts only inside the list's visible area. The guard is ported from #366 by Skyfuller1303 (@Skyfuller1303).
This commit is contained in:
@@ -217,7 +217,7 @@ fn pages(app: &mut FigApp, ui: &mut Ui) {
|
||||
let mut reorder = crate::list_drag::ListDrag::in_order(ui, "pages");
|
||||
// A long list scrolls in its own area, so the layers keep their room below it.
|
||||
let max_h = (ui.available_height() * 0.4).max(3.0 * ROW);
|
||||
let moved = egui::ScrollArea::vertical().id_salt("pages_list").max_height(max_h).show(ui, |ui| {
|
||||
let mut moved = egui::ScrollArea::vertical().id_salt("pages_list").max_height(max_h).show(ui, |ui| {
|
||||
for (k, (id, name, divider)) in pages.iter().cloned().enumerate() {
|
||||
let (r, resp) = ui.allocate_exact_size(vec2(w, 32.0), Sense::click_and_drag());
|
||||
reorder.row_by(&resp, k, r, || if divider { tr("Divider").to_string() } else { name.clone() });
|
||||
@@ -279,6 +279,12 @@ fn pages(app: &mut FigApp, ui: &mut Ui) {
|
||||
}
|
||||
reorder.finish(ui)
|
||||
});
|
||||
// A drop outside the list's visible area (and the row gap at its edges) isn't on a page row,
|
||||
// even one scrolled out of view.
|
||||
if !ui.input(|i| i.pointer.latest_pos()).is_some_and(|p| moved.inner_rect.expand2(vec2(0.0, 3.0)).contains(p)) {
|
||||
moved.inner = None;
|
||||
move_to = None;
|
||||
}
|
||||
if let Some((from, to)) = moved.inner
|
||||
&& let Some((id, ..)) = pages.get(from)
|
||||
{
|
||||
|
||||
@@ -271,6 +271,26 @@ fn a_long_pages_list_scrolls_and_leaves_room_for_the_layers() {
|
||||
assert!(top > 30, "the list scrolled past its first pages (top row: page {top})");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn a_page_dropped_below_the_pages_list_stays_where_it_was() {
|
||||
let mut s = Session::new();
|
||||
let first = s.page().unwrap();
|
||||
let rect = id(s.execute("shape.rectangle", &json!({"x": 0, "y": 0, "width": 10, "height": 10})).unwrap());
|
||||
let second = id(s.execute("page.add", &json!({})).unwrap());
|
||||
for _ in 0..58 {
|
||||
s.execute("page.add", &json!({})).unwrap();
|
||||
}
|
||||
let pages = s.doc().unwrap().pages.clone();
|
||||
s.execute("page.select", &json!({"id": first})).unwrap();
|
||||
s.execute("select.none", &json!({})).unwrap();
|
||||
let mut u = Ui::new(s);
|
||||
let (row, layer) = (page_row(&mut u, second, first), u.row_at(rect));
|
||||
// Released over the layers, where pages scrolled out of view would be: no page row is there.
|
||||
u.drag_to(row, layer);
|
||||
u.button(layer, false);
|
||||
assert_eq!(u.app.session.doc().unwrap().pages, pages, "the pages keep their order");
|
||||
}
|
||||
|
||||
/// A double click at `p`, with the screen reader tree checked on every frame: the platform adapter
|
||||
/// (UI Automation on Windows) aborts the app when the focused node isn't in the tree.
|
||||
fn double_click_checking_focus(u: &mut Ui, p: Pos2) {
|
||||
|
||||
Reference in New Issue
Block a user