use super::GridPosition;
use crate::{
chart::{Chart, ChartConfig},
error::ChartResult,
};
use core::any::Any;
use embedded_graphics::{
pixelcolor::PixelColor,
prelude::*,
primitives::Rectangle,
};
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub struct PanelId(pub u16);
trait AnyChart<C: PixelColor>: Any {
fn draw_erased(&self, viewport: Rectangle, target: &mut dyn DrawTarget<Color = C>) -> ChartResult<()>;
fn as_any(&self) -> &dyn Any;
fn as_any_mut(&mut self) -> &mut dyn Any;
}
struct ChartStorage<CH, D, C>
where
CH: Chart<C>,
D: Clone + 'static,
C: PixelColor,
{
chart: CH,
data: D,
config: ChartConfig,
}
impl<CH, D, C> AnyChart<C> for ChartStorage<CH, D, C>
where
CH: Chart<C, Data = D> + 'static,
D: Clone + 'static,
C: PixelColor,
{
fn draw_erased(&self, viewport: Rectangle, target: &mut dyn DrawTarget<Color = C>) -> ChartResult<()> {
self.chart.draw(&self.data, &self.config, viewport, target)
}
fn as_any(&self) -> &dyn Any {
self
}
fn as_any_mut(&mut self) -> &mut dyn Any {
self
}
}
pub struct ChartPanel<C: PixelColor> {
id: PanelId,
position: GridPosition,
chart: Box<dyn AnyChart<C>>,
}
impl<C: PixelColor> ChartPanel<C> {
pub fn new<CH, D>(
id: PanelId,
position: GridPosition,
chart: CH,
data: D,
config: ChartConfig,
) -> ChartResult<Self>
where
CH: Chart<C, Data = D> + 'static,
D: Clone + 'static,
{
let storage = ChartStorage {
chart,
data,
config,
};
Ok(Self {
id,
position,
chart: Box::new(storage),
})
}
pub fn id(&self) -> PanelId {
self.id
}
pub fn position(&self) -> GridPosition {
self.position
}
pub fn update_data<D>(&mut self, _data: D) -> ChartResult<()>
where
D: 'static,
{
Err(crate::error::ChartError::NotImplemented)
}
pub fn draw<DT>(&self, viewport: Rectangle, target: &mut DT) -> ChartResult<()>
where
DT: DrawTarget<Color = C>,
{
self.chart.draw_erased(viewport, target)
}
}
#[cfg(test)]
mod tests {
use super::*;
use crate::chart::LineChart;
use crate::data::{Point2D, StaticDataSeries};
use embedded_graphics::pixelcolor::Rgb565;
#[test]
fn test_panel_creation() {
let chart = LineChart::<Rgb565>::new();
let data: StaticDataSeries<Point2D, 100> = StaticDataSeries::new();
let config = ChartConfig::default();
let panel = ChartPanel::new(
PanelId(0),
GridPosition::new(0, 0),
chart,
data,
config,
).unwrap();
assert_eq!(panel.id(), PanelId(0));
assert_eq!(panel.position(), GridPosition::new(0, 0));
}
}