Skip to main content

ggplot_rs/position/
mod.rs

1pub mod dodge;
2pub mod dodge2;
3pub mod fill;
4pub mod identity;
5pub mod jitter;
6pub mod jitterdodge;
7pub mod nudge;
8pub mod stack;
9
10use crate::data::DataFrame;
11
12/// Parameters for position adjustments.
13#[derive(Clone, Debug)]
14pub struct PositionParams {
15    pub width: f64,
16    pub height: f64,
17}
18
19impl Default for PositionParams {
20    fn default() -> Self {
21        PositionParams {
22            width: 0.9,
23            height: 0.0,
24        }
25    }
26}
27
28/// Trait for position adjustments.
29pub trait Position: Send + Sync {
30    /// Adjust positions for data.
31    fn compute(&self, data: &mut DataFrame, params: &PositionParams);
32
33    fn name(&self) -> &str;
34
35    /// Whether this position must run separately per facet panel rather
36    /// than once on the pooled rows before facets are split (B3-3, D8).
37    /// Default `false`. `PositionStack`/`PositionFill` override this to
38    /// `true` — a shared x category's stack height must not mix rows from
39    /// different panels. Dodge and jitter stay pooled across panels for
40    /// now (a follow-up, sipemu/ggplot-rs#154).
41    fn per_panel(&self) -> bool {
42        false
43    }
44
45    /// Validate this position's own parameters once per layer (D2);
46    /// default no-op. Implementations push a warning and fall back to a
47    /// sane default rather than panicking or silently miscomputing.
48    fn validate(&self, _warnings: &mut Vec<String>) {}
49}
50
51/// Column in which stacking positions keep each row's original (pre-stack)
52/// `y`, so hover metadata (`data-value`, tooltips) can report the measured
53/// value rather than the cumulative stack top.
54pub const RAW_Y_COL: &str = ".y_raw";
55
56/// Remember the pre-position `y` in [`RAW_Y_COL`] (first adjustment wins).
57pub(crate) fn preserve_raw_y(data: &mut DataFrame, y: &[crate::data::Value]) {
58    if !data.has_column(RAW_Y_COL) {
59        data.add_column(RAW_Y_COL.to_string(), y.to_vec());
60    }
61}
62
63/// Column in which dodging positions store each row's offset (in category
64/// units) when x is *discrete*: the category itself can't move, so geoms add
65/// `offset / n_levels` to the mapped x (see `geom::support::XMapper`).
66pub const DODGE_OFFSET_COL: &str = ".x_dodge_offset";
67/// Number of dodged groups sharing a row's discrete x position (stored next to
68/// [`DODGE_OFFSET_COL`]); bar-like geoms divide their width by it.
69pub const DODGE_N_COL: &str = ".x_dodge_n";