diff --git a/backend-dioxus/src/dioxus_backend.rs b/backend-dioxus/src/dioxus_backend.rs index 0665e98..bd6fe7d 100644 --- a/backend-dioxus/src/dioxus_backend.rs +++ b/backend-dioxus/src/dioxus_backend.rs @@ -11,17 +11,35 @@ use plotters_backend::{ use plotters_backend::text_anchor::{ HPos, VPos }; use std::io::Error; +use plotters::prelude::*; use dioxus::prelude::*; use dioxus::core::DynamicNode; +use plotters::coord::Shift; +use std::rc::Rc; use std::fmt::Write as _; -pub struct DioxusBackend<'a> { +pub struct DioxusDrawingBackend<'a> { pub svg_children: Vec>, size: (u32, u32), } +pub struct DioxusBackend<'a> { + register: Rc>>, + pub drawing_area: DrawingArea, Shift>, +} + impl<'a> DioxusBackend<'a> { + pub fn new(size: (u32, u32)) -> Self { + let backend = Rc::new(std::cell::RefCell::new(DioxusDrawingBackend::new(size))); + Self { + register: backend.clone(), + drawing_area: DrawingArea::::from(&backend), + } + } +} + +impl<'a> DioxusDrawingBackend<'a> { pub fn new(size: (u32, u32)) -> Self { Self { svg_children: Vec::>::new(), size: size } } @@ -36,7 +54,7 @@ fn make_svg_opacity(color: BackendColor) -> String { return format!("{}", color.alpha); } -impl<'a> IntoDynNode<'a> for DioxusBackend<'a> { +impl<'a> IntoDynNode<'a> for DioxusDrawingBackend<'a> { fn into_vnode(self, cx: &'a ScopeState) -> DynamicNode<'a> { rsx!( svg { @@ -52,7 +70,17 @@ impl<'a> IntoDynNode<'a> for DioxusBackend<'a> { } } -impl<'a> DrawingBackend for DioxusBackend<'a> { +impl<'a> IntoDynNode<'a> for DioxusBackend<'a> { + fn into_vnode(self, cx: &'a ScopeState) -> DynamicNode<'a> { + drop(self.drawing_area); + Rc::into_inner(self.register) + .expect("Only one strong reference should exist") + .into_inner() + .into_vnode(cx) + } +} + +impl<'a> DrawingBackend for DioxusDrawingBackend<'a> { type ErrorType = Error; fn get_size(&self) -> (u32, u32) { diff --git a/demo/src/main.rs b/demo/src/main.rs index 3ed8e33..4ed4cbb 100644 --- a/demo/src/main.rs +++ b/demo/src/main.rs @@ -2,55 +2,50 @@ use dioxus::prelude::*; use backend_dioxus::DioxusBackend; use plotters::prelude::*; -use plotters::coord::Shift; -use std::rc::Rc; fn main() { dioxus_desktop::launch(App); } fn build_histogram<'a>(size: (u32, u32)) -> DioxusBackend<'a> { - let backend = Rc::new(std::cell::RefCell::new(DioxusBackend::new(size))); - { - let root_area = DrawingArea::::from(&backend); - let _ = root_area.fill(&WHITE); - let mut chart = ChartBuilder::on(&root_area) - .x_label_area_size(35) - .y_label_area_size(40) - .margin(5) - .caption("Histogram Test", ("sans-serif", 50.0)) - .build_cartesian_2d((0u32..10u32).into_segmented(), 0u32..10u32) - .expect("Expect a chart to be build"); + let backend = DioxusBackend::new(size); + let _ = backend.drawing_area.fill(&WHITE); + let mut chart = ChartBuilder::on(&backend.drawing_area) + .x_label_area_size(35) + .y_label_area_size(40) + .margin(5) + .caption("Histogram Test", ("sans-serif", 50.0)) + .build_cartesian_2d((0u32..10u32).into_segmented(), 0u32..10u32) + .expect("Expect a chart to be build"); - let _ = chart - .configure_mesh() - .disable_x_mesh() - .bold_line_style(WHITE.mix(0.3)) - .y_desc("Count") - .x_desc("Bucket") - .axis_desc_style(("sans-serif", 15)) - .draw(); + let _ = chart + .configure_mesh() + .disable_x_mesh() + .bold_line_style(WHITE.mix(0.3)) + .y_desc("Count") + .x_desc("Bucket") + .axis_desc_style(("sans-serif", 15)) + .draw(); - let data = [0u32, 1, 1, 1, 4, 2, 5, 7, 8, 6, 4, 2, 1, 8, 3, 3, 3, 4, 4, 3, 3, 3]; + let data = [0u32, 1, 1, 1, 4, 2, 5, 7, 8, 6, 4, 2, 1, 8, 3, 3, 3, 4, 4, 3, 3, 3]; - let _ = chart.draw_series( - Histogram::vertical(&chart) - .style(RED.mix(0.5).filled()) - .data(data.iter().map(|x: &u32| (*x, 1))) - ); + let _ = chart.draw_series( + Histogram::vertical(&chart) + .style(RED.mix(0.5).filled()) + .data(data.iter().map(|x: &u32| (*x, 1))) + ); - // To avoid the IO failure being ignored silently, we manually call the present function - root_area - .present() - .expect( - "Unable to write result to file, please make sure 'plotters-doc-data' dir exists under current dir" - ); - } - Rc::into_inner(backend).expect("Should be working").into_inner() + // To avoid the IO failure being ignored silently, we manually call the present function + backend.drawing_area + .present() + .expect( + "Unable to write result to file, please make sure 'plotters-doc-data' dir exists under current dir" + ); + drop(chart); + backend } fn App<'a>(cx: Scope<'a>) -> Element { - let size = (400, 400); - let backend = build_histogram(size); + let backend = build_histogram((400, 400)); render!(backend) }