use std::path::Path;
use egui::{Color32, Pos2, Rect};
use crate::core::colormap::Colormap;
use crate::core::items::{Baseline, ErrorBars, LineStyle, Symbol};
use crate::core::marker::MarkerConstraint;
use crate::core::shape::ShapeKind;
use crate::core::transform::{Margins, YAxis};
use crate::render::gpu_image::{AggregationMode, InterpolationMode};
use crate::render::save::SaveFormat;
pub type ItemHandle = u64;
#[derive(Clone, Copy, Debug, PartialEq)]
pub enum CurveColor<'a> {
Uniform(Color32),
PerVertex(&'a [Color32]),
}
#[derive(Clone, Debug)]
pub struct CurveSpec<'a> {
pub x: &'a [f64],
pub y: &'a [f64],
pub color: CurveColor<'a>,
pub gap_color: Option<Color32>,
pub symbol: Option<Symbol>,
pub line_width: f32,
pub line_style: LineStyle,
pub y_axis: YAxis,
pub x_error: Option<ErrorBars>,
pub y_error: Option<ErrorBars>,
pub fill: bool,
pub alpha: f32,
pub symbol_size: f32,
pub baseline: Baseline,
pub x_label: Option<&'a str>,
pub y_label: Option<&'a str>,
}
impl<'a> CurveSpec<'a> {
pub fn new(x: &'a [f64], y: &'a [f64], color: Color32) -> Self {
Self {
x,
y,
color: CurveColor::Uniform(color),
gap_color: None,
symbol: None,
line_width: 1.0,
line_style: LineStyle::Solid,
y_axis: YAxis::Left,
x_error: None,
y_error: None,
fill: false,
alpha: 1.0,
symbol_size: 7.0,
baseline: Baseline::Scalar(0.0),
x_label: None,
y_label: None,
}
}
}
#[derive(Clone, Debug)]
pub enum ImagePixelsSpec<'a> {
Scalar {
width: u32,
height: u32,
data: &'a [f32],
colormap: Box<Colormap>,
},
Rgba {
width: u32,
height: u32,
data: &'a [[u8; 4]],
},
}
#[derive(Clone, Debug)]
pub struct ImageSpec<'a> {
pub pixels: ImagePixelsSpec<'a>,
pub origin: (f64, f64),
pub scale: (f64, f64),
pub alpha: f32,
pub interpolation: InterpolationMode,
pub aggregation: AggregationMode,
pub aggregation_block: (u32, u32),
pub alpha_map: Option<&'a [f32]>,
}
impl<'a> ImageSpec<'a> {
pub fn scalar(width: u32, height: u32, data: &'a [f32], colormap: Colormap) -> Self {
Self {
pixels: ImagePixelsSpec::Scalar {
width,
height,
data,
colormap: Box::new(colormap),
},
origin: (0.0, 0.0),
scale: (1.0, 1.0),
alpha: 1.0,
interpolation: InterpolationMode::default(),
aggregation: AggregationMode::default(),
aggregation_block: (1, 1),
alpha_map: None,
}
}
pub fn rgba(width: u32, height: u32, data: &'a [[u8; 4]]) -> Self {
Self {
pixels: ImagePixelsSpec::Rgba {
width,
height,
data,
},
origin: (0.0, 0.0),
scale: (1.0, 1.0),
alpha: 1.0,
interpolation: InterpolationMode::default(),
aggregation: AggregationMode::default(),
aggregation_block: (1, 1),
alpha_map: None,
}
}
pub fn with_interpolation(mut self, interpolation: InterpolationMode) -> Self {
self.interpolation = interpolation;
self
}
pub fn with_aggregation(mut self, mode: AggregationMode, block: (u32, u32)) -> Self {
self.aggregation = mode;
self.aggregation_block = block;
self
}
pub fn with_alpha_map(mut self, alpha_map: &'a [f32]) -> Self {
self.alpha_map = Some(alpha_map);
self
}
}
#[derive(Clone, Debug)]
pub struct TriangleSpec<'a> {
pub x: &'a [f64],
pub y: &'a [f64],
pub triangles: &'a [[u32; 3]],
pub colors: &'a [Color32],
pub alpha: f32,
}
#[derive(Clone, Debug)]
pub struct ShapeSpec<'a> {
pub x: &'a [f64],
pub y: &'a [f64],
pub kind: ShapeKind,
pub color: Color32,
pub fill: bool,
pub overlay: bool,
pub line_style: LineStyle,
pub line_width: f32,
pub gap_color: Option<Color32>,
}
#[derive(Clone, Debug)]
pub struct MarkerSpec<'a> {
pub x: Option<f64>,
pub y: Option<f64>,
pub text: Option<&'a str>,
pub color: Color32,
pub symbol: Option<Symbol>,
pub symbol_size: f32,
pub line_style: LineStyle,
pub line_width: f32,
pub y_axis: YAxis,
pub bg_color: Option<Color32>,
pub is_draggable: bool,
pub constraint: MarkerConstraint,
}
#[derive(Clone, Copy, Debug, PartialEq)]
pub enum PickResult {
CurvePoint {
index: usize,
x: f64,
y: f64,
distance_px: f32,
},
ImagePixel { col: u32, row: u32 },
Item { handle: ItemHandle },
}
pub trait Backend {
type SaveError;
fn add_curve(&mut self, curve: CurveSpec<'_>) -> ItemHandle;
fn add_image(&mut self, image: ImageSpec<'_>) -> ItemHandle;
fn add_triangles(&mut self, tris: TriangleSpec<'_>) -> ItemHandle;
fn add_shape(&mut self, shape: ShapeSpec<'_>) -> ItemHandle;
fn add_marker(&mut self, marker: MarkerSpec<'_>) -> ItemHandle;
fn remove(&mut self, item: ItemHandle) -> bool;
fn set_limits(&mut self, xmin: f64, xmax: f64, ymin: f64, ymax: f64, y2: Option<(f64, f64)>);
fn x_limits(&self) -> (f64, f64);
fn y_limits(&self, axis: YAxis) -> Option<(f64, f64)>;
fn set_x_log(&mut self, on: bool);
fn set_y_log(&mut self, on: bool);
fn set_x_inverted(&mut self, on: bool);
fn set_y_inverted(&mut self, on: bool);
fn set_keep_data_aspect_ratio(&mut self, on: bool);
fn data_to_pixel(&self, x: f64, y: f64, axis: YAxis) -> Option<Pos2>;
fn pixel_to_data(&self, p: Pos2, axis: YAxis) -> Option<(f64, f64)>;
fn plot_bounds_in_pixels(&self) -> Option<Rect>;
fn set_axes_margins(&mut self, margins: Margins);
fn set_title(&mut self, title: Option<&str>);
fn set_x_label(&mut self, label: Option<&str>);
fn set_y_label(&mut self, label: Option<&str>, axis: YAxis);
fn set_foreground_colors(&mut self, foreground: Color32, grid: Color32);
fn set_background_colors(&mut self, background: Color32, data_background: Color32);
fn pick_item(&self, p: Pos2, item: ItemHandle) -> Option<PickResult>;
fn items_back_to_front(&self) -> Vec<ItemHandle>;
fn replot(&mut self);
fn save_graph(&self, path: &Path, size: (u32, u32)) -> Result<(), Self::SaveError>;
fn save_graph_with_format(
&self,
path: &Path,
size: (u32, u32),
format: SaveFormat,
dpi: u32,
) -> Result<(), Self::SaveError>;
}