Bladeren bron

more styling+ lidl drawing logic tweaks

Berke 1 jaar geleden
bovenliggende
commit
31cb42df2f
1 gewijzigde bestanden met toevoegingen van 60 en 25 verwijderingen
  1. 60 25
      src/charts/custom_line.rs

+ 60 - 25
src/charts/custom_line.rs

@@ -87,32 +87,37 @@ impl CustomLine {
         let latest: i64 = self.klines_raw.keys().last().map_or(0, |time| time.timestamp() - (self.translation.x*10.0) as i64);
         let earliest: i64 = latest - (6400.0 / (self.scaling / (self.chart_width/800.0))) as i64;
 
-        let (visible_klines, highest, lowest, avg_body_height, _) = self.klines_raw.iter()
+        let (visible_klines, highest, lowest, avg_body_height, _, _) = self.klines_raw.iter()
             .filter(|(time, _)| {
                 let timestamp = time.timestamp();
                 timestamp >= earliest && timestamp <= latest
             })
-            .fold((vec![], f32::MIN, f32::MAX, 0.0f32, 0.0f32), |(mut klines, highest, lowest, total_body_height, max_vol), (time, kline)| {
+            .fold((vec![], f32::MIN, f32::MAX, 0.0f32, 0.0f32, None), |(mut klines, highest, lowest, total_body_height, max_vol, latest_kline), (time, kline)| {
                 let body_height = (kline.0 - kline.3).abs();
                 klines.push((*time, *kline));
+                let total_body_height = match latest_kline {
+                    Some(_) => total_body_height + body_height,
+                    None => total_body_height,
+                };
                 (
                     klines,
                     highest.max(kline.1),
                     lowest.min(kline.2),
-                    total_body_height + body_height,
-                    max_vol.max(kline.4.max(kline.5)) 
+                    total_body_height,
+                    max_vol.max(kline.4.max(kline.5)),
+                    Some(kline)
                 )
             });
 
-        if visible_klines.is_empty() {
+        if visible_klines.is_empty() || visible_klines.len() == 1 {
             return;
         }
-        let avg_body_height = avg_body_height / visible_klines.len() as f32;
+
+        let avg_body_height = avg_body_height / (visible_klines.len() - 1) as f32;
         let (highest, lowest) = (highest + avg_body_height, lowest - avg_body_height);
 
         if earliest != self.x_min_time || latest != self.x_max_time || lowest != self.y_min_price || highest != self.y_max_price {
             self.x_labels_cache.clear();
-            self.y_labels_cache.clear();
             self.mesh_cache.clear();
         }
 
@@ -120,6 +125,8 @@ impl CustomLine {
         self.x_max_time = latest;
         self.y_min_price = lowest;
         self.y_max_price = highest;
+
+        self.y_labels_cache.clear();
     }
 
     pub fn update(&mut self, message: Message) {
@@ -163,18 +170,21 @@ impl CustomLine {
                 labels_cache: &self.x_labels_cache, min: self.x_min_time, max: self.x_max_time 
             })
             .width(Length::FillPortion(10))
-            .height(Length::Fixed(30.0));
+            .height(Length::Fixed(26.0));
+
+        let last_close_price = self.klines_raw.values().last().map_or(0.0, |kline| kline.3);
+        let last_open_price = self.klines_raw.values().last().map_or(0.0, |kline| kline.0);
     
         let axis_labels_y = Canvas::new(
             AxisLabelYCanvas { 
-                labels_cache: &self.y_labels_cache, min: self.y_min_price, max: self.y_max_price 
+                labels_cache: &self.y_labels_cache, min: self.y_min_price, max: self.y_max_price, last_close_price, last_open_price 
             })
-            .width(Length::Fixed(45.0))
+            .width(Length::Fixed(52.0))
             .height(Length::FillPortion(10));
     
         let empty_space = Container::new(Space::new(Length::Fixed(40.0), Length::Fixed(40.0)))
-            .width(Length::Fixed(45.0))
-            .height(Length::Fixed(30.0));
+            .width(Length::Fixed(52.0))
+            .height(Length::Fixed(26.0));
     
         let chart_and_y_labels = Row::new()
             .push(chart)
@@ -334,28 +344,33 @@ impl canvas::Program<Message> for CustomLine {
         let latest: i64 = self.klines_raw.keys().last().map_or(0, |time| time.timestamp() - (self.translation.x*10.0) as i64);
         let earliest: i64 = latest - (6400.0 / (self.scaling / (bounds.width/800.0))) as i64;
     
-        let (visible_klines, highest, lowest, avg_body_height, max_volume) = self.klines_raw.iter()
+        let (visible_klines, highest, lowest, avg_body_height, max_volume, _) = self.klines_raw.iter()
             .filter(|(time, _)| {
                 let timestamp = time.timestamp();
                 timestamp >= earliest && timestamp <= latest
             })
-            .fold((vec![], f32::MIN, f32::MAX, 0.0f32, 0.0f32), |(mut klines, highest, lowest, total_body_height, max_vol), (time, kline)| {
+            .fold((vec![], f32::MIN, f32::MAX, 0.0f32, 0.0f32, None), |(mut klines, highest, lowest, total_body_height, max_vol, latest_kline), (time, kline)| {
                 let body_height = (kline.0 - kline.3).abs();
                 klines.push((*time, *kline));
+                let total_body_height = match latest_kline {
+                    Some(_) => total_body_height + body_height,
+                    None => total_body_height,
+                };
                 (
                     klines,
                     highest.max(kline.1),
                     lowest.min(kline.2),
-                    total_body_height + body_height,
-                    max_vol.max(kline.4.max(kline.5)) 
+                    total_body_height,
+                    max_vol.max(kline.4.max(kline.5)),
+                    Some(kline)
                 )
             });
-    
-        if visible_klines.is_empty() {
+
+        if visible_klines.is_empty() || visible_klines.len() == 1 {
             return vec![];
         }
-    
-        let avg_body_height = avg_body_height / visible_klines.len() as f32;
+
+        let avg_body_height = avg_body_height / (visible_klines.len() - 1) as f32;
         let (highest, lowest) = (highest + avg_body_height, lowest - avg_body_height);
         let y_range = highest - lowest;
 
@@ -616,6 +631,8 @@ pub struct AxisLabelYCanvas<'a> {
     labels_cache: &'a Cache,
     min: f32,
     max: f32,
+    last_close_price: f32,
+    last_open_price: f32,
 }
 impl canvas::Program<Message> for AxisLabelYCanvas<'_> {
     type State = Interaction;
@@ -652,10 +669,10 @@ impl canvas::Program<Message> for AxisLabelYCanvas<'_> {
             frame.with_save(|frame| {
                 let y_range = self.max - self.min;
                 let mut y = rounded_lowest;
-        
+
                 while y <= self.max {
                     let y_position = candlesticks_area_height - ((y - self.min) / y_range * candlesticks_area_height);
-        
+
                     let text_size = 12.0;
                     let decimal_places = if step.fract() == 0.0 { 0 } else { 1 };
                     let label_content = match decimal_places {
@@ -664,19 +681,37 @@ impl canvas::Program<Message> for AxisLabelYCanvas<'_> {
                     };
                     let label = canvas::Text {
                         content: label_content,
-                        position: Point::new(5.0, y_position - text_size / 2.0),
+                        position: Point::new(10.0, y_position - text_size / 2.0),
                         size: iced::Pixels(text_size),
                         color: Color::from_rgba8(200, 200, 200, 1.0),
                         ..canvas::Text::default()
                     };  
-        
+
                     label.draw_with(|path, color| {
                         frame.fill(&path, color);
                     });
+
                     y += step;
                 }
+
+                let last_close_y_position = candlesticks_area_height - ((self.last_close_price - self.min) / y_range * candlesticks_area_height);
+
+                let triangle_color = if self.last_close_price >= self.last_open_price {
+                    Color::from_rgba8(81, 205, 160, 0.9) 
+                } else {
+                    Color::from_rgba8(192, 80, 77, 0.9) 
+                };
+
+                let triangle = Path::new(|path| {
+                    path.move_to(Point::new(5.0, last_close_y_position));
+                    path.line_to(Point::new(0.0, last_close_y_position - 5.0));
+                    path.line_to(Point::new(0.0, last_close_y_position + 5.0));
+                    path.close();
+                });
+
+                frame.fill(&triangle, triangle_color);
             });
-        });   
+        });
 
         vec![labels]
     }