[yew-devel] [PATCH yew-comp 13/20] rrd: refactor series related struct and functions into own module
Dominik Csapak
d.csapak at proxmox.com
Fri May 30 14:21:55 CEST 2025
makes the main graph module a bit smaller. While at it, document the
compute_*_path functions.
Signed-off-by: Dominik Csapak <d.csapak at proxmox.com>
---
src/rrd/graph.rs | 101 +------------------------------------------
src/rrd/mod.rs | 3 ++
src/rrd/series.rs | 107 ++++++++++++++++++++++++++++++++++++++++++++++
3 files changed, 112 insertions(+), 99 deletions(-)
create mode 100644 src/rrd/series.rs
diff --git a/src/rrd/graph.rs b/src/rrd/graph.rs
index b58bd58..161269f 100644
--- a/src/rrd/graph.rs
+++ b/src/rrd/graph.rs
@@ -15,20 +15,6 @@ use pwt::widget::{Button, Container, Panel};
use pwt_macros::builder;
-pub struct Series {
- pub label: AttrValue,
- pub data: Vec<f64>,
-}
-
-impl Series {
- pub fn new(label: impl Into<AttrValue>, data: Vec<f64>) -> Self {
- Self {
- label: label.into(),
- data,
- }
- }
-}
-
#[derive(Derivative)]
#[derivative(Clone, PartialEq)]
#[derive(Properties)]
@@ -166,7 +152,9 @@ impl Default for LayoutProps {
use pwt::widget::canvas::{Canvas, Circle, Group, Path, Rect, SvgLength, Text};
+use super::series::{compute_fill_path, compute_outline_path};
use super::units::{get_grid_unit_base10, get_grid_unit_base2, get_time_grid_unit};
+use super::Series;
fn format_date_time(t: i64) -> String {
let (time, date) = format_time(t);
@@ -264,91 +252,6 @@ fn compute_min_max(props: &RRDGraph, data1: &[f64], data2: &[f64]) -> (f64, f64,
(min_data, max_data, grid_unit)
}
-fn compute_outline_path(
- time_data: &[i64],
- values: &[f64],
- compute_x: impl Fn(i64) -> f64,
- compute_y: impl Fn(f64) -> f64,
-) -> String {
- let mut path = String::new();
- let mut last_undefined = true;
- for (i, t) in time_data.iter().enumerate() {
- let value = *values.get(i).unwrap_or(&f64::NAN);
- let x = compute_x(*t);
-
- if last_undefined {
- if value.is_nan() {
- continue;
- }
- last_undefined = false;
- let y = compute_y(value);
- path.push_str(&format!(" M {:.1} {:.1}", x, y));
- } else {
- if value.is_nan() {
- last_undefined = true;
- continue;
- }
- let y = compute_y(value);
- path.push_str(&format!(" L {:.1} {:.1}", x, y));
- }
- }
- path
-}
-
-fn compute_fill_path(
- time_data: &[i64],
- values: &[f64],
- min_data: f64,
- max_data: f64,
- compute_x: impl Fn(i64) -> f64,
- compute_y: impl Fn(f64) -> f64,
-) -> String {
- let mut y0 = compute_y(0.0);
- if min_data > 0.0 {
- y0 = compute_y(min_data)
- }
- if max_data < 0.0 {
- y0 = compute_y(max_data)
- }
- let mut path = String::new();
- let mut last_undefined = true;
- for i in 0..time_data.len() {
- let t = time_data[i];
- let value = *values.get(i).unwrap_or(&f64::NAN);
-
- let x = compute_x(t);
-
- if last_undefined {
- if value.is_nan() {
- continue;
- }
- last_undefined = false;
- path.push_str(&format!(" M {:.1} {:.1}", x, y0));
- } else if value.is_nan() {
- last_undefined = true;
- let x = if i > 0 {
- compute_x(time_data[i - 1])
- } else {
- x
- };
- path.push_str(&format!(" L {:.1} {:.1}", x, y0));
-
- continue;
- }
- let y = compute_y(value);
- path.push_str(&format!(" L {:.1} {:.1}", x, y));
- }
-
- if let Some(t) = time_data.last() {
- if !last_undefined {
- let x = compute_x(*t);
- path.push_str(&format!(" L {:.1} {:.1}", x, y0));
- }
- }
-
- path
-}
-
impl PwtRRDGraph {
fn get_view_data<'a>(&self, ctx: &'a Context<Self>) -> (&'a [i64], &'a [f64], &'a [f64]) {
let props = ctx.props();
diff --git a/src/rrd/mod.rs b/src/rrd/mod.rs
index 7931053..fe63ff5 100644
--- a/src/rrd/mod.rs
+++ b/src/rrd/mod.rs
@@ -1,4 +1,7 @@
mod graph;
pub use graph::*;
+pub(crate) mod series;
+pub use series::Series;
+
pub(crate) mod units;
diff --git a/src/rrd/series.rs b/src/rrd/series.rs
new file mode 100644
index 0000000..8807598
--- /dev/null
+++ b/src/rrd/series.rs
@@ -0,0 +1,107 @@
+use yew::AttrValue;
+
+/// Represents a series of data for an [`crate::RRDGraph`]
+pub struct Series {
+ pub label: AttrValue,
+ pub data: Vec<f64>,
+}
+
+impl Series {
+ pub fn new(label: impl Into<AttrValue>, data: Vec<f64>) -> Self {
+ Self {
+ label: label.into(),
+ data,
+ }
+ }
+}
+
+/// Calculate the outline path of a series of [`f64`] data for [`i64`] points in time.
+///
+/// The line will not be drawn for points that are missing
+pub fn compute_outline_path(
+ time_data: &[i64],
+ values: &[f64],
+ compute_x: impl Fn(i64) -> f64,
+ compute_y: impl Fn(f64) -> f64,
+) -> String {
+ let mut path = String::new();
+ let mut last_undefined = true;
+ for (i, t) in time_data.iter().enumerate() {
+ let value = *values.get(i).unwrap_or(&f64::NAN);
+ let x = compute_x(*t);
+
+ if last_undefined {
+ if value.is_nan() {
+ continue;
+ }
+ last_undefined = false;
+ let y = compute_y(value);
+ path.push_str(&format!(" M {:.1} {:.1}", x, y));
+ } else {
+ if value.is_nan() {
+ last_undefined = true;
+ continue;
+ }
+ let y = compute_y(value);
+ path.push_str(&format!(" L {:.1} {:.1}", x, y));
+ }
+ }
+ path
+}
+
+/// Calculate the fill path for a series of [`f64`] points for [`i64`] points in time.
+///
+/// The area will not be filled for points that are missing
+pub fn compute_fill_path(
+ time_data: &[i64],
+ values: &[f64],
+ min_data: f64,
+ max_data: f64,
+ compute_x: impl Fn(i64) -> f64,
+ compute_y: impl Fn(f64) -> f64,
+) -> String {
+ let mut y0 = compute_y(0.0);
+ if min_data > 0.0 {
+ y0 = compute_y(min_data)
+ }
+ if max_data < 0.0 {
+ y0 = compute_y(max_data)
+ }
+ let mut path = String::new();
+ let mut last_undefined = true;
+ for i in 0..time_data.len() {
+ let t = time_data[i];
+ let value = *values.get(i).unwrap_or(&f64::NAN);
+
+ let x = compute_x(t);
+
+ if last_undefined {
+ if value.is_nan() {
+ continue;
+ }
+ last_undefined = false;
+ path.push_str(&format!(" M {:.1} {:.1}", x, y0));
+ } else if value.is_nan() {
+ last_undefined = true;
+ let x = if i > 0 {
+ compute_x(time_data[i - 1])
+ } else {
+ x
+ };
+ path.push_str(&format!(" L {:.1} {:.1}", x, y0));
+
+ continue;
+ }
+ let y = compute_y(value);
+ path.push_str(&format!(" L {:.1} {:.1}", x, y));
+ }
+
+ if let Some(t) = time_data.last() {
+ if !last_undefined {
+ let x = compute_x(*t);
+ path.push_str(&format!(" L {:.1} {:.1}", x, y0));
+ }
+ }
+
+ path
+}
--
2.39.5
More information about the yew-devel
mailing list