plotters-dioxus 0.2.2

A plotters-rs component for dioxus
#![allow(non_snake_case)]

use dioxus::prelude::*;

use plotters_bitmap::BitMapBackend;

use plotters::prelude::*;
use plotters::coord::Shift;

use base64::prelude::*;

use image::ImageEncoder;
use image::codecs::png::PngEncoder;

use std::io::Cursor;

pub type DioxusDrawingArea<'a> = DrawingArea<BitMapBackend<'a>, Shift>;

#[derive(Props)]
pub struct PlottersProps<'a, F: Fn(DioxusDrawingArea)> {
    pub size: (u32, u32),
    pub init: F,
    pub on_click: Option<EventHandler<'a, Event<MouseData>>>,
    pub on_dblclick: Option<EventHandler<'a, Event<MouseData>>>,
    pub on_mousemove: Option<EventHandler<'a, Event<MouseData>>>,
    pub on_mouseout: Option<EventHandler<'a, Event<MouseData>>>,
    pub on_mouseup: Option<EventHandler<'a, Event<MouseData>>>,
    pub on_mousedown: Option<EventHandler<'a, Event<MouseData>>>,
    pub on_mouseover: Option<EventHandler<'a, Event<MouseData>>>,
    pub on_wheel: Option<EventHandler<'a, Event<WheelData>>>,
    #[props(default = false)]
    pub draggable: bool,
    pub on_drag: Option<EventHandler<'a, Event<DragData>>>,
    pub on_dragend: Option<EventHandler<'a, Event<DragData>>>,
    pub on_dragenter: Option<EventHandler<'a, Event<DragData>>>,
    pub on_dragleave: Option<EventHandler<'a, Event<DragData>>>,
    pub on_dragover: Option<EventHandler<'a, Event<DragData>>>,
    pub on_dragstart: Option<EventHandler<'a, Event<DragData>>>,
    pub on_drop: Option<EventHandler<'a, Event<DragData>>>,
    pub on_scroll: Option<EventHandler<'a, Event<ScrollData>>>,
}

impl<'a, F: Fn(DioxusDrawingArea)> PartialEq for PlottersProps<'a, F> {
    fn eq(&self, other: &PlottersProps<F>) -> bool {
        self.size == other.size
    }
}

pub fn Plotters<'a, F: Fn(DioxusDrawingArea)>(cx: Scope<'a, PlottersProps<'a, F>>) -> Element<'a> {
    let buffer_size = ((cx.props.size.1 * cx.props.size.0) as usize) * 3usize;
    let mut buffer = vec![0u8; buffer_size];
    let drawing_area = BitMapBackend::with_buffer(
        buffer.as_mut_slice(),
        cx.props.size
    ).into_drawing_area();
    (cx.props.init)(drawing_area);

    let mut data = vec![0; 0];
    let cursor = Cursor::new(&mut data);
    let encoder = PngEncoder::new(cursor);
    let color = image::ColorType::Rgb8;

    encoder
        .write_image(buffer.as_slice(), cx.props.size.0, cx.props.size.1, color)
        .expect("The Png encoder is expected to write the image");

    let buffer_base64 = BASE64_STANDARD.encode(data);

    render!(img {
        onclick: |e| {
            if let Some(callback) = cx.props.on_click.as_ref() {
                callback.call(e)
            };
        },
        ondblclick: |e| {
            if let Some(callback) = cx.props.on_dblclick.as_ref() {
                callback.call(e)
            };
        },
        onmousemove: |e| {
            if let Some(callback) = cx.props.on_mousemove.as_ref() {
                callback.call(e)
            };
        },
        onmousedown: |e| {
            if let Some(callback) = cx.props.on_mousedown.as_ref() {
                callback.call(e)
            };
        },
        onmouseup: |e| {
            if let Some(callback) = cx.props.on_mouseup.as_ref() {
                callback.call(e)
            };
        },
        onmouseout: |e| {
            if let Some(callback) = cx.props.on_mouseout.as_ref() {
                callback.call(e)
            };
        },
        onmouseover: |e| {
            if let Some(callback) = cx.props.on_mouseout.as_ref() {
                callback.call(e)
            };
        },
        onwheel: |e| {
            if let Some(callback) = cx.props.on_wheel.as_ref() {
                callback.call(e)
            };
        },
        onwheel: |e| {
            if let Some(callback) = cx.props.on_wheel.as_ref() {
                callback.call(e)
            };
        },
        draggable: cx.props.draggable,
        ondrag: |e| {
            if let Some(callback) = cx.props.on_drag.as_ref() {
                callback.call(e)
            };
        },
        ondragend: |e| {
            if let Some(callback) = cx.props.on_dragend.as_ref() {
                callback.call(e)
            };
        },
        ondragenter: |e| {
            if let Some(callback) = cx.props.on_dragenter.as_ref() {
                callback.call(e)
            };
        },
        ondragleave: |e| {
            if let Some(callback) = cx.props.on_dragleave.as_ref() {
                callback.call(e)
            };
        },
        ondragover: |e| {
            if let Some(callback) = cx.props.on_dragover.as_ref() {
                callback.call(e)
            };
        },
        ondragstart: |e| {
            if let Some(callback) = cx.props.on_dragstart.as_ref() {
                callback.call(e)
            };
        },
        ondrop: |e| {
            if let Some(callback) = cx.props.on_drop.as_ref() {
                callback.call(e)
            };
        },
        onscroll: |e| {
            if let Some(callback) = cx.props.on_scroll.as_ref() {
                callback.call(e)
            };
        },
        src: "data:image/png;base64,{buffer_base64}",
    })
}