1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
//! Generic snap-layout system for movable + resizable rects.
//!
//! Reusable across `agg-gui`'s `Window`, AdamArtist's node graph,
//! and any third-party widget whose primary state is a rect that
//! drags and resizes. The engine is pure — it knows nothing about
//! widgets, events, or paint — so it can be wired into any drag
//! handler that produces a candidate rect and wants a snapped result.
//!
//! ## Pattern
//!
//! 1. Implement [`Snappable`] on your movable type — three accessors
//! (`snap_id`, `snap_rect`, `set_snap_rect`) and two opt-in flags.
//! 2. When the user drags, collect `(SnapId, Rect)` tuples for every
//! *other* visible Snappable in the scene (skip the dragger).
//! 3. Call [`compute_snap`] with the dragger's candidate rect, the
//! target list, a pixel threshold, and a [`SnapMode`].
//! 4. Apply the returned [`SnapResult::rect`] back through
//! `set_snap_rect`; render the returned [`SnapGuide`]s as overlay
//! lines.
//!
//! ## Global enable flag
//!
//! Snapping is gated behind a thread-local flag managed via
//! [`is_enabled`] and [`set_enabled`]. Drag handlers should check
//! `is_enabled()` first and skip the engine entirely when off — keeps
//! the gate at the call site so individual widgets don't pay any cost
//! when snapping is disabled. The flag defaults to `true` so any
//! consumer of agg-gui gets window/node snapping out of the box;
//! call [`set_enabled(false)`] to opt out.
pub use compute_snap;
pub use ;
pub use SnapOverlay;
pub use ;
/// Default pixel distance at which an alignment / spacing match
/// engages. Apps can pass a different value to [`compute_snap`]
/// directly; this is the value drag handlers should reach for when
/// they have no specific reason to override it.
pub const DEFAULT_THRESHOLD: f64 = 8.0;
/// Mint a fresh [`SnapId`] from a process-wide atomic counter.
/// Cheap — single relaxed increment — so widgets can call it from
/// their constructor without caring about contention.
use Cell;
thread_local!
/// `true` if snapping should run during drag/resize operations.
/// Drag handlers must check this and skip the snap path entirely
/// when off.
/// Toggle the global snap-enable flag. Persists for the lifetime of
/// the thread — typically wired to a UI checkbox (see the demo's
/// `View > Window Snapping` menu item) and to saved-state
/// persistence so the user's preference survives a relaunch.