mirror of
https://github.com/storytold/figcraft.git
synced 2026-10-24 18:36:44 -06:00
#854: no reorder ring on a layer under 16 px on screen, and its hit radius is at most a quarter of the layer, so a small layer still drags the selection
This commit is contained in:
@@ -61,6 +61,15 @@ fn drag_id() -> Id {
|
||||
Id::new("selection_spacing_drag")
|
||||
}
|
||||
|
||||
/// The reorder ring of a layer with world bounds `b`: its centre on screen and hit radius. The
|
||||
/// radius is 8 px, at most a quarter of the layer's smaller side on screen, so most of a small
|
||||
/// layer still drags the selection; a layer under 16 px on screen has no ring.
|
||||
fn ring(app: &FigApp, b: figcraft_geom::Rect) -> Option<(Pos2, f32)> {
|
||||
let zoom = app.session.ds().map_or(1.0, |d| d.view.zoom);
|
||||
let side = ((b.x1 - b.x0).min(b.y1 - b.y0) * zoom) as f32;
|
||||
(side >= 16.0).then(|| (app.to_screen((b.x0 + b.x1) * 0.5, (b.y0 + b.y1) * 0.5), (side / 4.0).min(8.0)))
|
||||
}
|
||||
|
||||
#[derive(Clone)]
|
||||
enum Action {
|
||||
Spacing { axis: Axis, value: f64, last_value: Option<f64> },
|
||||
@@ -279,8 +288,7 @@ pub fn input(app: &mut FigApp, ctx: &egui::Context, pos: Option<Pos2>, hovered:
|
||||
let ids = app.session.selection();
|
||||
if let Some(reorder) = reorder_layout(app, ctx, &ids) {
|
||||
for (id, b) in &reorder.slots {
|
||||
let center = app.to_screen((b.x0 + b.x1) * 0.5, (b.y0 + b.y1) * 0.5);
|
||||
if center.distance(p) <= 8.0 {
|
||||
if ring(app, *b).is_some_and(|(center, r)| center.distance(p) <= r) {
|
||||
ctx.set_cursor_icon(CursorIcon::Grab);
|
||||
if ctx.input(|i| i.pointer.primary_pressed()) {
|
||||
let source = *id;
|
||||
@@ -329,9 +337,8 @@ pub fn draw(app: &FigApp, painter: &egui::Painter) {
|
||||
};
|
||||
if let Some(layout) = reorder {
|
||||
for (id, _) in &layout.slots {
|
||||
let Some(b) = ds.doc.world_bounds(*id) else { continue };
|
||||
let center = app.to_screen((b.x0 + b.x1) * 0.5, (b.y0 + b.y1) * 0.5);
|
||||
let hot = hover.is_some_and(|p| center.distance(p) <= 8.0);
|
||||
let Some((center, r)) = ds.doc.world_bounds(*id).and_then(|b| ring(app, b)) else { continue };
|
||||
let hot = hover.is_some_and(|p| center.distance(p) <= r);
|
||||
let active = matches!(drag.as_ref().map(|d| &d.action), Some(Action::Reorder { source, .. }) if source == id);
|
||||
if active {
|
||||
painter.circle_filled(center, 4.5, PINK);
|
||||
|
||||
@@ -333,3 +333,29 @@ fn an_externally_finished_reorder_cannot_resume_on_later_pointer_motion() {
|
||||
assert_eq!(u.app.session.undo_depth().0, history);
|
||||
assert_eq!(xy(&u, ids[0]), (260., 100.));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn small_layers_on_screen_have_no_reorder_ring_and_drag_the_selection_from_their_middle() {
|
||||
let mut u = Ui::new(Session::new());
|
||||
let z = u.app.session.ds().unwrap().view.zoom;
|
||||
// 12 px squares 36 px apart on screen: a regular row, too small for rings.
|
||||
let ids: Vec<NodeId> = (0..3)
|
||||
.map(|col| {
|
||||
let p = json!({"x": (100. + f64::from(col) * 36.) / z, "y": 100. / z, "width": 12. / z, "height": 12. / z});
|
||||
NodeId(u.app.session.execute("shape.rectangle", &p).unwrap()["id"].as_u64().unwrap())
|
||||
})
|
||||
.collect();
|
||||
u.app.session.execute("select.set", &json!({"ids": ids})).unwrap();
|
||||
let before: Vec<_> = ids.iter().map(|id| xy(&u, *id)).collect();
|
||||
let p = u.app.to_screen(before[0].0 + 6. / z, before[0].1 + 6. / z);
|
||||
let output = u.frame_output(vec![Event::PointerMoved(p)]);
|
||||
assert_ne!(output.platform_output.cursor_icon, egui::CursorIcon::Grab);
|
||||
drag(&mut u, p, vec2(0., 60.), true);
|
||||
let after: Vec<_> = ids.iter().map(|id| xy(&u, *id)).collect();
|
||||
assert!(after[0].1 > before[0].1, "the selection moved: {before:?} -> {after:?}");
|
||||
assert!(
|
||||
before.iter().zip(&after).all(|(b, a)| (a.0 - b.0).abs() < 1e-6 && (a.1 - b.1 - (after[0].1 - before[0].1)).abs() < 1e-6),
|
||||
"all together, in order"
|
||||
);
|
||||
assert_eq!(u.app.session.selection(), ids);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user