Skip to main content

graplot/render/
bar.rs

1use std::fmt::Display;
2
3use litequad::prelude::{clear_background, next_frame, WHITE, draw_line, GRAY, screen_width, screen_height, BLACK, draw_rectangle, draw_text, DARKGRAY, draw_text_rot, is_key_pressed, KeyCode};
4use crate::{Bar, get_font_size_y, min, divs, count_inv_tens, negative};
5use super::{COORD_THICKNESS, YLABEL_SIZE, TITLE_SIZE, DISTANCE_X_AXIS};
6const DISTANCE: f32 = 80.;
7
8pub async fn run(bar: Bar, _min_y: f64, max_y: f64, steps_y: f64) {
9    let min_y = min(&bar.ys);
10    
11    let y_font_size = get_font_size_y(max_y);
12    let y_half_font = y_font_size / 2.;
13
14    let step_y = (max_y) / steps_y;
15
16    let ys = divs(&bar.ys, step_y);
17
18    if min_y >= 0. {
19        return positive_only(bar, step_y, y_half_font, y_font_size, max_y, ys).await;
20    }
21    if negative(&ys) {
22        return negative_only(bar, step_y, y_half_font, y_font_size, max_y, ys).await;
23    }
24    positive_negative(bar, step_y, y_half_font, y_font_size, max_y, ys).await
25}
26
27pub async fn draw_line_with_text<T: Display>(y: f32, val: T, y_half_font: f32, y_font_size: f32) {
28    let text = format!("{}", val);
29    let move_away = text.len();
30
31    draw_text(
32        &text,
33        DISTANCE - 5. - (y_half_font * move_away as f32),
34        y + (y_half_font / 2.),
35        y_font_size,
36        BLACK,
37    );
38    draw_line(DISTANCE - 4., y, DISTANCE + 4., y, 3., DARKGRAY);
39}
40
41pub async fn draw_bars(x_level: f32, ys: &[f64], bar: &Bar) {
42    let mut line_x = DISTANCE;
43    let mut bar_x = DISTANCE + 20.;
44    for (bar_entity, y) in bar.bars.iter().zip(ys) {
45        let y = *y as f32;
46        draw_rectangle(bar_x, x_level-bar.desc.spacing_y * y, bar_entity.width, bar.desc.spacing_y * y, bar_entity.color);
47        
48        line_x += bar_entity.width / 2. + 20.;
49        draw_line(line_x, x_level-6., line_x, x_level+6., COORD_THICKNESS, BLACK);
50
51        let text_pos = line_x - bar_entity.label.len() as f32 * (10. / 2.) + COORD_THICKNESS;
52
53        draw_text(&bar_entity.label, text_pos, x_level + 20. / 2. + 8., 20., BLACK);
54        line_x += bar_entity.width / 2.;
55        bar_x += bar_entity.width + 20.;
56    }
57}
58
59pub async fn negative_only(bar: Bar, step_y: f64, y_half_font: f32, y_font_size: f32, max_y: f64, ys: Vec<f64>) {
60    loop {
61        clear_background(WHITE);
62
63        for (idx, char) in bar.axis_desc.y_label.chars().into_iter().enumerate() {
64            draw_text_rot(&char.to_string(), 7., screen_height() / 2. - (YLABEL_SIZE / 2. * idx as f32) , YLABEL_SIZE, BLACK, -std::f32::consts::PI / 2.,);
65        }
66
67        draw_text(&bar.axis_desc.title, screen_width() / 2., DISTANCE_X_AXIS / 3. + 7., TITLE_SIZE, BLACK);
68        draw_text(&bar.axis_desc.x_label, screen_width() / 2., screen_height() - DISTANCE_X_AXIS / 3., YLABEL_SIZE, BLACK);
69
70        // x axis
71        draw_line(0., DISTANCE_X_AXIS, screen_width(), DISTANCE_X_AXIS, COORD_THICKNESS, GRAY);
72
73        // y axis
74        draw_line(DISTANCE, 0., DISTANCE, screen_height(), COORD_THICKNESS, GRAY);
75
76        if step_y > 1. {
77            for (idx, val) in (step_y as i128..=max_y as i128)
78                .step_by(step_y as usize)
79                .enumerate()
80            {
81                let y = DISTANCE_X_AXIS + bar.desc.spacing_y * idx as f32 + bar.desc.spacing_y;
82                draw_line_with_text(y, -val, y_half_font, y_font_size).await;
83            }
84        } else {
85            let tens_step = count_inv_tens(step_y);
86
87            let max_y = max_y * tens_step as f64;
88            let step_y = step_y * tens_step as f64;
89
90            for (idx, val) in (step_y as i128..=max_y as i128)
91                .step_by(step_y as usize)
92                .enumerate()
93            {
94                let y = (screen_height() / 2.) + bar.desc.spacing_y * idx as f32 + bar.desc.spacing_y;
95                draw_line_with_text(y, -val as f64 / tens_step as f64, y_half_font, y_font_size).await;
96            }
97        }
98        
99        if is_key_pressed(KeyCode::Escape) {
100            break;
101        }
102        draw_bars(DISTANCE_X_AXIS, &ys, &bar).await;
103        next_frame().await;
104        std::thread::sleep(std::time::Duration::from_millis(16));        
105    }
106}
107
108pub async fn positive_negative(bar: Bar, step_y: f64, y_half_font: f32, y_font_size: f32, max_y: f64, ys: Vec<f64>) {
109    loop {
110        clear_background(WHITE);
111
112        for (idx, char) in bar.axis_desc.y_label.chars().into_iter().enumerate() {
113            draw_text_rot(&char.to_string(), 7., screen_height() / 2. - (YLABEL_SIZE / 2. * idx as f32) , YLABEL_SIZE, BLACK, -std::f32::consts::PI / 2.,);
114        }
115
116        draw_text(&bar.axis_desc.title, screen_width() / 2., DISTANCE_X_AXIS / 3. + 7., TITLE_SIZE, BLACK);
117        draw_text(&bar.axis_desc.x_label, screen_width() / 2., screen_height() - DISTANCE_X_AXIS / 3., YLABEL_SIZE, BLACK);
118
119        // x axis
120        draw_line(0., screen_height() / 2., screen_width(), screen_height() / 2., COORD_THICKNESS, GRAY);
121
122        // y axis
123        draw_line(DISTANCE, 0., DISTANCE, screen_height(), COORD_THICKNESS, GRAY);
124
125        if is_key_pressed(KeyCode::Escape) {
126            break;
127        }
128
129        if step_y > 1. {
130            for (idx, val) in (step_y as i128..=max_y as i128)
131                .step_by(step_y as usize)
132                .enumerate()
133            {
134                let y = (screen_height() / 2.) - bar.desc.spacing_y * idx as f32 - bar.desc.spacing_y;
135                draw_line_with_text(y, val, y_half_font, y_font_size).await;
136            }
137        } else {
138            let tens_step = count_inv_tens(step_y);
139
140            let max_y = max_y * tens_step as f64;
141            let step_y = step_y * tens_step as f64;
142
143            for (idx, val) in (step_y as i128..=max_y as i128)
144                .step_by(step_y as usize)
145                .enumerate()
146            {
147                let y = (screen_height() / 2.) - bar.desc.spacing_y * idx as f32 - bar.desc.spacing_y;
148                draw_line_with_text(y, val as f64 / tens_step as f64, y_half_font, y_font_size).await;
149            }
150        }
151
152        if step_y > 1. {
153            for (idx, val) in (step_y as i128..=max_y as i128)
154                .step_by(step_y as usize)
155                .enumerate()
156            {
157                let y = (screen_height() / 2.) + bar.desc.spacing_y * idx as f32 + bar.desc.spacing_y;
158                draw_line_with_text(y, -val, y_half_font, y_font_size).await;
159            }
160        } else {
161            let tens_step = count_inv_tens(step_y);
162
163            let max_y = max_y * tens_step as f64;
164            let step_y = step_y * tens_step as f64;
165
166            for (idx, val) in (step_y as i128..=max_y as i128)
167                .step_by(step_y as usize)
168                .enumerate()
169            {
170                let y = (screen_height() / 2.) + bar.desc.spacing_y * idx as f32 + bar.desc.spacing_y;
171                draw_line_with_text(y, -val as f64 / tens_step as f64, y_half_font, y_font_size).await;
172            }
173        }
174        draw_bars(screen_height() / 2., &ys, &bar).await;
175        
176        next_frame().await;
177        std::thread::sleep(std::time::Duration::from_millis(16));
178    }
179    
180}
181
182pub async fn positive_only(bar: Bar, step_y: f64, y_half_font: f32, y_font_size: f32, max_y: f64, ys: Vec<f64>) {
183    loop {
184        clear_background(WHITE);
185
186        for (idx, char) in bar.axis_desc.y_label.chars().into_iter().enumerate() {
187            draw_text_rot(&char.to_string(), 7., screen_height() / 2. - (YLABEL_SIZE / 2. * idx as f32) , YLABEL_SIZE, BLACK, -std::f32::consts::PI / 2.,);
188        }
189    
190        draw_text(&bar.axis_desc.title, screen_width() / 2., DISTANCE_X_AXIS / 3. + 7., TITLE_SIZE, BLACK);
191        draw_text(&bar.axis_desc.x_label, screen_width() / 2., screen_height() - DISTANCE_X_AXIS / 3., YLABEL_SIZE, BLACK);
192
193        if step_y > 1. {
194            for (idx, val) in (step_y as i128..=max_y as i128)
195                .step_by(step_y as usize)
196                .enumerate()
197            {
198                let y = (screen_height() - bar.desc.spacing_y * idx as f32) - DISTANCE_X_AXIS - bar.desc.spacing_y;
199                draw_line_with_text(y, val, y_half_font, y_font_size).await;
200            }
201
202        } else {
203            let tens_step = count_inv_tens(step_y);
204
205            let max_y = max_y * tens_step as f64;
206            let step_y = step_y * tens_step as f64;
207
208            for (idx, val) in (step_y as i128..=max_y as i128)
209                .step_by(step_y as usize)
210                .enumerate()
211            {
212                let y = (screen_height() - bar.desc.spacing_y * idx as f32) - DISTANCE_X_AXIS - bar.desc.spacing_y;
213                draw_line_with_text(y, val as f64 / tens_step as f64, y_half_font, y_font_size).await;
214            }
215        }
216        
217        let x_level = screen_height()-DISTANCE_X_AXIS;
218        draw_bars(x_level, &ys, &bar).await;
219
220        // x axis
221        draw_line(0., x_level, screen_width(), x_level, COORD_THICKNESS, GRAY);
222
223        // y axis
224        draw_line(DISTANCE, 0., DISTANCE, screen_height(), COORD_THICKNESS, GRAY);
225        
226        if is_key_pressed(KeyCode::Escape) {
227            break;
228        }
229
230        next_frame().await;
231        std::thread::sleep(std::time::Duration::from_millis(16));
232    }
233}