1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
// plotters-iced
//
// Iced backend for Plotters
// Copyright: 2021, Joylei <leingliu@gmail.com>
// License: MIT

use super::backend::IcedChartBackend;
use super::native::Renderer as ChartRenderer;
use iced_graphics::{backend, canvas, canvas::Cursor, Backend, Primitive, Renderer};
use iced_native::{event, mouse::Interaction, Font, Point, Rectangle, Vector};
use plotters::prelude::DrawingArea;
use plotters_backend::{FontFamily, FontStyle};

pub type ChartWidget<'a, Message, C> = super::native::ChartWidget<'a, Message, C>;

impl<B: Backend + backend::Text> ChartRenderer for Renderer<B> {
    fn draw_chart<Message, C>(
        &self,
        chart: &C,
        font_resolver: &Box<dyn Fn(FontFamily, FontStyle) -> Font>,
        _defaults: &Self::Defaults,
        layout: iced_native::Layout<'_>,
        _cursor_position: Point,
        _viewport: &Rectangle,
    ) -> Self::Output
    where
        C: crate::Chart<Message>,
    {
        let bounds = layout.bounds();
        let geometry = chart.draw(bounds.size(), |frame| {
            let backend = IcedChartBackend::new(frame, self.backend(), font_resolver);
            let root: DrawingArea<_, _> = backend.into();
            chart.draw_chart(root);
        });
        let translation = Vector::new(bounds.x, bounds.y);
        let cursor = Interaction::default();
        (
            Primitive::Translate {
                translation,
                content: Box::new(geometry.into()),
            },
            cursor,
        )
    }

    fn on_event<Message, C: crate::Chart<Message>>(
        &self,
        chart: &mut C,
        event: iced_native::Event,
        layout: iced_native::Layout<'_>,
        cursor_position: Point,
        _clipboard: &mut dyn iced_native::Clipboard,
        messages: &mut Vec<Message>,
    ) -> iced_native::event::Status {
        let bounds = layout.bounds();

        let canvas_event = match event {
            iced_native::Event::Mouse(mouse_event) => Some(canvas::Event::Mouse(mouse_event)),
            iced_native::Event::Keyboard(keyboard_event) => {
                Some(canvas::Event::Keyboard(keyboard_event))
            }
            _ => None,
        };
        if let Some(canvas_event) = canvas_event {
            let cursor = Cursor::Available(cursor_position);
            let (status, message) = chart.update(canvas_event, bounds, cursor);
            if let Some(m) = message {
                messages.push(m);
            }
            return status;
        }
        event::Status::Ignored
    }
}