plotters_unsable/element/
candlestick.rs1use std::cmp::Ordering;
6
7use crate::drawing::backend::{BackendCoord, DrawingBackend, DrawingErrorKind};
8use crate::element::{Drawable, PointCollection};
9use crate::style::ShapeStyle;
10
11pub struct CandleStick<'a, X, Y: PartialOrd> {
13 style: ShapeStyle<'a>,
14 width: u32,
15 points: [(X, Y); 4],
16}
17
18impl<'a, X: Clone, Y: PartialOrd> CandleStick<'a, X, Y> {
19 #[allow(clippy::too_many_arguments)]
21 pub fn new<GS: Into<ShapeStyle<'a>>, LS: Into<ShapeStyle<'a>>>(
22 x: X,
23 open: Y,
24 high: Y,
25 low: Y,
26 close: Y,
27 gain_style: GS,
28 loss_style: LS,
29 width: u32,
30 ) -> Self {
31 Self {
32 style: match open.partial_cmp(&close) {
33 Some(Ordering::Less) => gain_style.into(),
34 _ => loss_style.into(),
35 },
36 width,
37 points: [
38 (x.clone(), open),
39 (x.clone(), high),
40 (x.clone(), low),
41 (x.clone(), close),
42 ],
43 }
44 }
45}
46
47impl<'b, 'a, X: 'a, Y: PartialOrd + 'a> PointCollection<'a, (X, Y)> for &'a CandleStick<'b, X, Y> {
48 type Borrow = &'a (X, Y);
49 type IntoIter = &'a [(X, Y)];
50 fn point_iter(self) -> &'a [(X, Y)] {
51 &self.points
52 }
53}
54
55impl<'a, X: 'a, Y: 'a + PartialOrd, DB: DrawingBackend> Drawable<DB> for CandleStick<'a, X, Y> {
56 fn draw<I: Iterator<Item = BackendCoord>>(
57 &self,
58 points: I,
59 backend: &mut DB,
60 ) -> Result<(), DrawingErrorKind<DB::ErrorType>> {
61 let mut points: Vec<_> = points.take(4).collect();
62 if points.len() == 4 {
63 let fill = false;
64 if points[0].1 > points[3].1 {
65 points.swap(0, 3);
66 }
67 let (l, r) = (
68 self.width as i32 / 2,
69 self.width as i32 - self.width as i32 / 2,
70 );
71
72 backend.draw_line(points[0], points[1], &Box::new(self.style.color))?;
73 backend.draw_line(points[2], points[3], &Box::new(self.style.color))?;
74
75 points[0].0 -= l;
76 points[3].0 += r;
77
78 backend.draw_rect(points[0], points[3], &Box::new(self.style.color), fill)?;
79 }
80 Ok(())
81 }
82}