| 900 | self.x_tick_producer = Some(producer); |
| 901 | } |
| 902 | |
| 903 | /// Set a custom tick producer for generating tick positions along the y-axis. |
| 904 | pub fn set_y_tick_producer(&mut self, producer: TickProducer) { |
| 905 | self.y_tick_producer = Some(producer); |
| 906 | } |
| 907 | |
| 908 | /// Set the positions of an existing series. |
| 909 | pub fn set_series_positions(&mut self, id: &ShapeId, positions: &[[f64; 2]]) { |
| 910 | if let Some(series) = self.series.get_mut(id) { |
| 911 | series.positions = positions.to_vec(); |
| 912 | if let Some(colors) = &mut series.point_colors |
| 913 | && colors.len() != series.positions.len() |
| 914 | { |
| 915 | colors.resize(series.positions.len(), series.color); |
| 916 | } |
| 917 | self.data_version += 1; |
| 918 | } |
| 919 | } |
| 920 | |
| 921 | /// Append new points to an existing series, dropping the oldest points so |
| 922 | /// the series never exceeds `cap` points (`cap == 0` means unbounded). |
| 923 | /// |
| 924 | /// Intended for streaming telemetry: callers push only the freshly |
| 925 | /// arrived samples instead of rebuilding and re-setting the full window |
| 926 | /// on every update. Non-finite points (e.g. `[x, f64::NAN]`) are allowed |
| 927 | /// and render as gaps in line series. |
| 928 | pub fn append_series_points(&mut self, id: &ShapeId, points: &[[f64; 2]], cap: usize) { |
| 929 | if points.is_empty() { |
| 930 | return; |
| 931 | } |
| 932 | if let Some(series) = self.series.get_mut(id) { |
| 933 | series.positions.extend_from_slice(points); |
| 934 | // Per-point colors must stay aligned with positions: extend with the |
| 935 | // series color for the new points, then drop from the FRONT together |
| 936 | // with the positions (a plain resize would truncate from the back). |
| 937 | if let Some(colors) = &mut series.point_colors { |
| 938 | colors.resize(series.positions.len(), series.color); |
| 939 | } |
| 940 | let len = series.positions.len(); |
| 941 | if cap > 0 && len > cap { |
| 942 | let excess = len - cap; |
| 943 | series.positions.drain(..excess); |
| 944 | if let Some(colors) = &mut series.point_colors { |
| 945 | colors.drain(..excess); |
| 946 | } |
| 947 | } |
| 948 | self.data_version += 1; |
| 949 | } |
| 950 | } |
| 951 | |
| 952 | /// Set per-point colors for an existing series. |
| 953 | pub fn set_series_point_colors(&mut self, id: &ShapeId, mut colors: Vec<Color>) { |
| 954 | if let Some(series) = self.series.get_mut(id) { |
| 955 | if colors.len() != series.positions.len() { |
| 956 | colors.resize(series.positions.len(), series.color); |
| 957 | } |
| 958 | series.point_colors = Some(colors); |
| 959 | self.data_version += 1; |