plotters_iced/chart.rs
1// plotters-iced
2//
3// Iced backend for Plotters
4// Copyright: 2022, Joylei <leingliu@gmail.com>
5// License: MIT
6
7use iced_widget::canvas::Cache;
8use iced_widget::core::event::Status;
9use iced_widget::core::mouse::Interaction;
10use iced_widget::core::Rectangle;
11use iced_widget::{
12 canvas::{Event, Frame, Geometry},
13 core::{mouse::Cursor, Size},
14};
15use plotters::{chart::ChartBuilder, coord::Shift, drawing::DrawingArea};
16use plotters_backend::DrawingBackend;
17
18/// graphics renderer
19pub trait Renderer {
20 /// draw frame
21 fn draw<F: Fn(&mut Frame)>(&self, bounds: Size, draw_fn: F) -> Geometry;
22
23 /// draw frame with cache
24 fn draw_cache<F: Fn(&mut Frame)>(&self, cache: &Cache, bounds: Size, draw_fn: F) -> Geometry;
25}
26
27impl<Message, C: ?Sized> Chart<Message> for &C
28where
29 C: Chart<Message>,
30{
31 type State = C::State;
32 #[inline]
33 fn build_chart<DB: DrawingBackend>(&self, state: &Self::State, builder: ChartBuilder<DB>) {
34 C::build_chart(self, state, builder);
35 }
36 #[inline]
37 fn draw_chart<DB: DrawingBackend>(&self, state: &Self::State, root: DrawingArea<DB, Shift>) {
38 C::draw_chart(self, state, root);
39 }
40 #[inline]
41 fn draw<R: Renderer, F: Fn(&mut Frame)>(&self, renderer: &R, size: Size, f: F) -> Geometry {
42 C::draw(self, renderer, size, f)
43 }
44 #[inline]
45 fn update(
46 &self,
47 state: &mut Self::State,
48 event: Event,
49 bounds: Rectangle,
50 cursor: Cursor,
51 ) -> (Status, Option<Message>) {
52 C::update(self, state, event, bounds, cursor)
53 }
54 #[inline]
55 fn mouse_interaction(
56 &self,
57 state: &Self::State,
58 bounds: Rectangle,
59 cursor: Cursor,
60 ) -> Interaction {
61 C::mouse_interaction(self, state, bounds, cursor)
62 }
63}
64
65/// Chart View Model
66///
67/// ## Example
68/// ```rust,ignore
69/// use plotters::prelude::*;
70/// use plotters_iced::{Chart,ChartWidget};
71/// struct MyChart;
72/// impl Chart<Message> for MyChart {
73/// type State = ();
74/// fn build_chart<DB:DrawingBackend>(&self, state: &Self::State, builder: ChartBuilder<DB>) {
75/// //build your chart here, please refer to plotters for more details
76/// }
77/// }
78///
79/// impl MyChart {
80/// fn view(&mut self)->Element<Message> {
81/// ChartWidget::new(self)
82/// .width(Length::Fixed(200))
83/// .height(Length::Fixed(200))
84/// .into()
85/// }
86/// }
87/// ```
88pub trait Chart<Message> {
89 /// state data of chart
90 type State: Default + 'static;
91
92 /// draw chart with [`ChartBuilder`]
93 ///
94 /// for simple chart, you impl this method
95 fn build_chart<DB: DrawingBackend>(&self, state: &Self::State, builder: ChartBuilder<DB>);
96
97 /// override this method if you want more freedom of drawing area
98 ///
99 /// ## Example
100 /// ```rust,ignore
101 /// use plotters::prelude::*;
102 /// use plotters_iced::{Chart,ChartWidget};
103 ///
104 /// struct MyChart{}
105 ///
106 /// impl Chart<Message> for MyChart {
107 /// // leave it empty
108 /// fn build_chart<DB: DrawingBackend>(&self, state: &Self::State, builder: ChartBuilder<DB>){}
109 /// fn draw_chart<DB: DrawingBackend>(&self, state: &Self::State, root: DrawingArea<DB, Shift>){
110 /// let children = root.split_evenly((3,3));
111 /// for (area, color) in children.into_iter().zip(0..) {
112 /// area.fill(&Palette99::pick(color)).unwrap();
113 /// }
114 /// }
115 /// }
116 /// ```
117 #[inline]
118 fn draw_chart<DB: DrawingBackend>(&self, state: &Self::State, root: DrawingArea<DB, Shift>) {
119 let builder = ChartBuilder::on(&root);
120 self.build_chart(state, builder);
121 }
122
123 /// draw on [`iced_widget::canvas::Canvas`]
124 ///
125 /// override this method if you want to use [`iced_widget::canvas::Cache`]
126 ///
127 /// ## Example
128 /// ```rust,ignore
129 ///
130 /// impl Chart<Message> for CpuUsageChart {
131 ///
132 /// #[inline]
133 /// fn draw<R: Renderer, F: Fn(&mut Frame)>(&self, renderer: &R, bounds: Size, draw_fn: F) -> Geometry {
134 /// R::draw_cache(renderer, &self.cache, size, draw_fn)
135 /// }
136 /// //...
137 /// }
138 /// ```
139 #[inline]
140 fn draw<R: Renderer, F: Fn(&mut Frame)>(&self, renderer: &R, size: Size, f: F) -> Geometry {
141 R::draw(renderer, size, f)
142 }
143
144 /// react on event
145 #[allow(unused_variables)]
146 #[inline]
147 #[allow(unused)]
148 fn update(
149 &self,
150 state: &mut Self::State,
151 event: Event,
152 bounds: Rectangle,
153 cursor: Cursor,
154 ) -> (Status, Option<Message>) {
155 (Status::Ignored, None)
156 }
157
158 /// Returns the current mouse interaction of the [`Chart`]
159 #[inline]
160 #[allow(unused)]
161 fn mouse_interaction(
162 &self,
163 state: &Self::State,
164 bounds: Rectangle,
165 cursor: Cursor,
166 ) -> Interaction {
167 Interaction::Idle
168 }
169}