Skip to content

Commit 5b1396d

Browse files
Feature Improvements tcbee-viz: Consistent Color-Scheme for Graphs | Auto Zoom for Single-Graphs (#8)
* [chore] merge gitlab and github project * [chore] update ascii on startup * [chore tcbee-viz] change theme to gruvbox * [chore tcbee-viz] remove unsued color scheme, change main.rs
1 parent 99b1df3 commit 5b1396d

File tree

10 files changed

+218
-48
lines changed

10 files changed

+218
-48
lines changed

tcbee-viz/src/main.rs

Lines changed: 16 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
1-
// bundling logic for TCP-visual-analysis tool
2-
// authored by Evelyn Stange -> https://scattered-lenity.space
1+
// bundling logic for TCPFlow
2+
// authored by Evelyn Esther Stange -> https://scattered-lenity.de
33

44
// internal imports
55
mod modules {
@@ -46,8 +46,17 @@ use std::time::{Duration, Instant};
4646

4747
// fn main() -> iced::Result {
4848
fn main() -> iced::Result {
49-
println!("Hi, this application was written by Evelyn :>\n this message is a secret");
50-
iced::application("TCPFLOW", StateContainer::update, StateContainer::view)
49+
50+
let ascii_name = r#"
51+
______________ ______ ____ _ __
52+
/_ __/ ___/ _ \/ __/ / / __ \ | /| / /
53+
/ / / /__/ ___/ _// /__/ /_/ / |/ |/ /
54+
/_/ \___/_/ /_/ /____/\____/|__/|__/
55+
56+
"#;
57+
println!("Hi, this application was written by Eve\nThis message is a secret");
58+
println!("{}",ascii_name);
59+
iced::application("TCQueen", StateContainer::update, StateContainer::view)
5160
.theme(StateContainer::theme)
5261
.run()
5362
}
@@ -107,8 +116,8 @@ impl Default for StateContainer {
107116
screen_multi_flow_plotting: ScreenMultiFlowPlotting::new(settings.clone()),
108117
screen_modify_database: ScreenModifyDatabase::new(settings.clone()),
109118
application_settings: settings,
110-
// theme: Theme::CatppuccinFrappe,
111-
theme: Theme::Light,
119+
// theme: Theme::CatppuccinFrappe, // dark mode
120+
theme: Theme::GruvboxLight,
112121
}
113122
}
114123
}
@@ -129,9 +138,7 @@ impl StateContainer {
129138
ActiveScreen::MultipleGraphPlot => {
130139
self.screen_multi_flow_plotting.reset();
131140
}
132-
_ => {
133-
134-
}
141+
_ => {}
135142
}
136143
self.screen = new_screen
137144
}

tcbee-viz/src/modules/backend/app_settings.rs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22

33
// -- internal imports
44
use crate::modules::backend::intermediate_backend::IntermediateBackend;
5+
use crate::modules::backend::plot_data_preprocessing::ColorScheme;
56
use crate::DataSource;
67

78
// -- external imports
@@ -17,6 +18,7 @@ pub struct ApplicationSettings {
1718
pub datavalue_skip_counter: u32,
1819
pub reduce_point_density_on_zoom: bool,
1920
pub amount_to_skip_on_zoom: usize,
21+
pub graph_pointseries_color_scheme: ColorScheme,
2022

2123
// ---- Backend | DataSource-Settings
2224
pub datasource: Option<DataSource>,
@@ -36,6 +38,7 @@ impl ApplicationSettings {
3638
datavalue_skip_counter: 1,
3739
reduce_point_density_on_zoom: false,
3840
amount_to_skip_on_zoom: 400,
41+
graph_pointseries_color_scheme:ColorScheme::RandomHSL,
3942

4043
// ---- Backend | DataSource-Settings
4144
datasource: None,

tcbee-viz/src/modules/backend/intermediate_backend.rs

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
// manages and defines access to database / which source to use etc.
33

44
use crate::modules::{
5-
backend::plot_data_preprocessing::generate_n_random_colors,
5+
backend::plot_data_preprocessing::retrieve_n_colors,
66
ui::{
77
lib_styling::app_style_settings::{DEFAULT_Y_MAX, DEFAULT_Y_MIN},
88
lib_widgets::lib_graphs::{
@@ -394,7 +394,10 @@ impl IntermediateBackend {
394394
};
395395
// --- COLOR Generation
396396
let colors_to_generate = available_time_series.len();
397-
let mut colors_for_series = generate_n_random_colors(colors_to_generate);
397+
let settings_read = app_reference.read().unwrap();
398+
let colorscheme = settings_read.graph_pointseries_color_scheme.clone();
399+
400+
let mut colors_for_series = retrieve_n_colors(colorscheme,colors_to_generate);
398401

399402
let collection_of_flow_series = self.collect_flowseries_from_timeseries(
400403
&db_interface,
@@ -417,6 +420,7 @@ impl IntermediateBackend {
417420
second_pressed_position: None,
418421
current_position: None,
419422
app_settings: app_reference.clone(),
423+
generate_y_bounds: false,
420424
};
421425
Some(resulting_collection)
422426
}

tcbee-viz/src/modules/backend/plot_data_preprocessing.rs

Lines changed: 123 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -5,17 +5,51 @@ use crate::modules::ui::lib_widgets::lib_graphs::{
55
struct_flow_series_data::FlowSeriesData,
66
struct_processed_plot_data::ProcessedPlotData,
77
struct_string_series_wrapper::{view_wrapper, StringSeriesWrapper},
8-
struct_zoom_bounds::{ZoomBound, ZoomBound2D},
8+
struct_zoom_bounds::{merge_two_bounds, ZoomBound, ZoomBound2D},
99
};
1010
use iced::{widget::Column, Color, Element};
11-
use plotters::style::RGBAColor;
11+
use plotters::style::{self, Color as _};
12+
// use plotters::style::{Color, HSLColor, RGBAColor};
1213
use rand::{distr::Uniform, prelude::Distribution};
1314
use ts_storage::DataValue;
14-
use std::f64::{MAX, MIN};
15+
use std::{f64::{MAX, MIN}, usize};
16+
17+
pub fn retrieve_y_bounds_from_plot_data(
18+
plot_data: &ProcessedPlotData,
19+
zoom_bounds: ZoomBound2D,
20+
) -> ZoomBound {
21+
let mut maximum_zoom_bounds = ZoomBound {
22+
lower: MAX,
23+
upper: MIN,
24+
};
25+
for series in &plot_data.point_collection {
26+
// let y_bounds = retrieve_y_bounds_from_selected_range(ser)
27+
let as_bundle: Vec<(f64, DataValue)> = series
28+
.timestamps
29+
.iter()
30+
.zip(series.data.iter())
31+
.map(|collection| (collection.0.clone(), collection.1.clone()))
32+
.collect();
33+
let only_in_bounds = skip_outside_of_bound(&as_bundle, &zoom_bounds);
34+
let amount_of_points = only_in_bounds.len();
35+
println!("amount of points for this series: {:?}", amount_of_points);
36+
if amount_of_points == 0 {
37+
continue;
38+
}
39+
let zoom_bounds = retrieve_y_bounds_from_collection_of_points(&only_in_bounds,&zoom_bounds.y);
40+
maximum_zoom_bounds = merge_two_bounds(&maximum_zoom_bounds, &zoom_bounds);
41+
}
42+
if maximum_zoom_bounds.lower == MAX && maximum_zoom_bounds.upper == MIN {
43+
zoom_bounds.y
44+
} else {
45+
maximum_zoom_bounds
46+
}
47+
}
1548

1649
/// for the given datapoints, receive the upper and lower bounds for Y and return them as ZoomBound
1750
/// assumes that the given Vec<> includes the range to find the max/min in
18-
pub fn retrieve_y_bounds_from_selected_range(
51+
/// FIXMEMERGE
52+
pub fn retrieve_y_bounds_from_collection_of_points(
1953
plot_data: &Vec<(f64, DataValue)>,
2054
current_y_zoom: &ZoomBound,
2155
) -> ZoomBound {
@@ -247,23 +281,101 @@ pub fn filter_and_prepare_string_from_series(
247281
}
248282
}
249283

250-
// MISC: FIXME: should be moved to another location!
251-
/// FIXME: Acts as placeholder, should be replaced with a less random implementation later
284+
#[derive(Clone)]
285+
pub enum ColorScheme{
286+
Random,
287+
RandomHSL,
288+
LightTheme,
289+
DarkTheme,
290+
}
291+
252292
/// returns n random colors of a selection of colors
253-
pub fn generate_n_random_colors(n: usize) -> Vec<RGBAColor> {
254-
let mut colors: Vec<RGBAColor> = Vec::new();
293+
pub fn retrieve_n_colors(selection:ColorScheme,n: usize) -> Vec<style::RGBAColor> {
294+
match selection{
295+
ColorScheme::Random => {
296+
generate_n_random_colors(n)
297+
}
298+
ColorScheme::RandomHSL => {
299+
generate_random_colors_hsl(0.7, 0.5, n)
300+
}
301+
ColorScheme::LightTheme => {
302+
let mut colors= generate_10_colors_scheme1();
303+
if n >= colors.len() {
304+
let mut more_colors = generate_n_random_colors(n-colors.len());
305+
colors.append(&mut more_colors)
306+
}
307+
return colors
308+
}
309+
ColorScheme::DarkTheme => {
310+
let mut colors = generate_12_colors_scheme2();
311+
if n >= colors.len() {
312+
let mut more_colors = generate_n_random_colors(n-colors.len());
313+
colors.append(&mut more_colors);
314+
}
315+
return colors
316+
}
317+
}
318+
}
319+
pub fn convert_rgba_to_iced_color(color: &style::RGBAColor) -> Color {
320+
Color::from_rgb8(color.0, color.1, color.2)
321+
}
322+
323+
fn generate_n_random_colors(n:usize) -> Vec<style::RGBAColor> {
324+
let mut colors: Vec<style::RGBAColor> = Vec::new();
255325
let mut rng_thread = rand::rng();
256326

257327
for _ in 0..n {
258328
let red_channel: u8 = Uniform::new(30, 255).unwrap().sample(&mut rng_thread);
259329
let green_channel: u8 = Uniform::new(20, 255).unwrap().sample(&mut rng_thread);
260330
let blue_channel: u8 = Uniform::new(30, 255).unwrap().sample(&mut rng_thread);
261-
let new_color = RGBAColor(red_channel, green_channel, blue_channel, 1.0);
331+
let new_color = style::RGBAColor(red_channel, green_channel, blue_channel, 1.0);
262332
colors.push(new_color);
263333
}
264334
colors
265335
}
266336

267-
pub fn convert_rgba_to_iced_color(color: &RGBAColor) -> Color {
268-
Color::from_rgb8(color.0, color.1, color.2)
337+
fn generate_random_colors_hsl(saturation:f64, lightness:f64, n:usize) -> Vec<style::RGBAColor> {
338+
let mut colors: Vec<style::RGBAColor> = Vec::new();
339+
// let huedelta = 360/n;
340+
for index in 0..n {
341+
// let hue:f64 = huedelta * (index as f64);
342+
let hue:f64 = (index as f64) / (n as f64);
343+
let as_hsl = style::HSLColor(hue,saturation,lightness);
344+
let as_rgba_color = as_hsl.to_rgba();
345+
colors.push(as_rgba_color);
346+
};
347+
colors
269348
}
349+
350+
fn generate_10_colors_scheme1() -> Vec<style::RGBAColor> {
351+
// of 10 colors
352+
vec![
353+
style::RGBAColor(215,25,28,1.0),
354+
style::RGBAColor(253,174,97,1.0),
355+
style::RGBAColor(255,255,191,1.0),
356+
style::RGBAColor(171,217,233,1.0),
357+
style::RGBAColor(44,123,182,1.0),
358+
style::RGBAColor(23, 34, 109,1.0),
359+
style::RGBAColor(96, 119, 209,1.0),
360+
style::RGBAColor(191, 197, 255,1.0),
361+
style::RGBAColor(210, 233, 206,1.0),
362+
style::RGBAColor(170, 182, 111,1.0)
363+
]
364+
}
365+
366+
fn generate_12_colors_scheme2() -> Vec<style::RGBAColor> {
367+
vec![
368+
style::RGBAColor(166,206,227,1.0),
369+
style::RGBAColor(31,120,180,1.0),
370+
style::RGBAColor(178,223,138,1.0),
371+
style::RGBAColor(51,160,44,1.0),
372+
style::RGBAColor(251,154,153,1.0),
373+
style::RGBAColor(227,26,28,1.0),
374+
style::RGBAColor(253,191,111,1.0),
375+
style::RGBAColor(255,127,0,1.0),
376+
style::RGBAColor(202,178,214,1.0),
377+
style::RGBAColor(106,61,154,1.0),
378+
style::RGBAColor(153, 50, 204,1.0),
379+
style::RGBAColor(177,89,40,1.0),
380+
]
381+
}

tcbee-viz/src/modules/ui/lib_screens/screen_single_flow_plotting.rs

Lines changed: 40 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -14,8 +14,9 @@ use iced_aw::TabLabel;
1414
// backend implementation
1515
use crate::modules::{
1616
backend::plot_data_preprocessing::{
17-
filter_and_prepare_string_from_series, filter_for_string_values, generate_n_random_colors,
18-
prepare_string_from_flow_series,
17+
filter_and_prepare_string_from_series, filter_for_string_values, retrieve_n_colors,
18+
prepare_string_from_flow_series, retrieve_y_bounds_from_collection_of_points,
19+
retrieve_y_bounds_from_plot_data,
1920
},
2021
ui::{
2122
lib_styling::app_style_settings::{
@@ -168,16 +169,28 @@ impl ScreenSingleFlowPlotting {
168169
}
169170
}
170171

171-
pub fn update_zoom_bound_x(&mut self, new_x_bound: &ZoomBound) {
172+
pub fn maybe_set_state_for_y_bound_generation(&mut self, new_state: bool) {
173+
if let Some(plot_data) = &mut self.processed_plot_data {
174+
plot_data.set_state_for_y_bound_generation(new_state);
175+
}
176+
}
177+
178+
pub fn update_zoom_bound_y(&mut self, new_y_bound: &ZoomBound) -> ZoomBound2D {
179+
let new_bound = ZoomBound2D {
180+
x: self.zoom_bounds.clone().unwrap_or_default().x,
181+
y: new_y_bound.clone(),
182+
};
183+
self.zoom_bounds = Some(new_bound.clone());
184+
new_bound
185+
}
186+
187+
pub fn update_zoom_bound_x(&mut self, new_x_bound: &ZoomBound) -> ZoomBound2D {
172188
let new_bound = ZoomBound2D {
173189
x: new_x_bound.clone(),
174-
y: self
175-
.zoom_bounds
176-
.clone()
177-
.expect("no bounds defined, updating impossible?")
178-
.y,
190+
y: self.zoom_bounds.clone().unwrap_or_default().y,
179191
};
180-
self.zoom_bounds = Some(new_bound);
192+
self.zoom_bounds = Some(new_bound.clone());
193+
new_bound
181194
}
182195

183196
pub fn update(&mut self, message: MessagePlotting) {
@@ -237,15 +250,19 @@ impl ScreenSingleFlowPlotting {
237250
self.update_zoom_plot_data_and_cache();
238251
match event {
239252
iced::mouse::Event::ButtonPressed(iced::mouse::Button::Left) => {
253+
self.maybe_set_state_for_y_bound_generation(false);
240254
self.set_current_position(point);
241255
self.pressed_cursor = false;
242256
self.set_cursor_state_and_pos(true);
243257
}
244258
iced::mouse::Event::ButtonReleased(iced::mouse::Button::Left) => {
259+
self.maybe_set_state_for_y_bound_generation(false);
245260
self.set_current_position(point);
246261
self.set_cursor_state_and_pos(false);
247-
let plotting_data = self.processed_plot_data.as_mut().expect("no plotting data");
248-
let new_zoom = generate_zoom_bounds_from_coordinates_in_data(&plotting_data);
262+
let plotting_data =
263+
self.processed_plot_data.as_mut().expect("no plotting data");
264+
let new_zoom =
265+
generate_zoom_bounds_from_coordinates_in_data(&plotting_data);
249266
self.zoom_bounds = Some(new_zoom.clone());
250267
plotting_data.zoom_bounds = new_zoom;
251268
if self.render_chart {
@@ -255,7 +272,11 @@ impl ScreenSingleFlowPlotting {
255272
}
256273
iced::mouse::Event::ButtonPressed(iced::mouse::Button::Right) => {
257274
// resetting zoom to default!
258-
let new_zoom = retrieve_default_zoom_for_one_flow(&self.application_settings, &self.tcp_flow);
275+
self.maybe_set_state_for_y_bound_generation(false);
276+
let new_zoom = retrieve_default_zoom_for_one_flow(
277+
&self.application_settings,
278+
&self.tcp_flow,
279+
);
259280
self.zoom_bounds = Some(new_zoom);
260281
self.update_zoom_plot_data_and_cache();
261282
// self.fetch_and_update_plot_data();
@@ -264,7 +285,8 @@ impl ScreenSingleFlowPlotting {
264285
}
265286
}
266287
MessagePlotting::ZoomResetRequested => {
267-
let new_zoom = retrieve_default_zoom_for_one_flow(&self.application_settings, &self.tcp_flow);
288+
let new_zoom =
289+
retrieve_default_zoom_for_one_flow(&self.application_settings, &self.tcp_flow);
268290
self.zoom_bounds = Some(new_zoom);
269291
self.update_zoom_plot_data_and_cache();
270292
}
@@ -273,15 +295,18 @@ impl ScreenSingleFlowPlotting {
273295
lower: lower_bound_x,
274296
upper: self.zoom_bounds.clone().unwrap_or_default().x.upper,
275297
};
276-
self.update_zoom_bound_x(&new_x_bound);
298+
let _ = self.update_zoom_bound_x(&new_x_bound);
299+
self.maybe_set_state_for_y_bound_generation(true);
277300
self.update_zoom_plot_data_and_cache();
278301
}
279302
MessagePlotting::SliderZoomRX(upper_bound_x) => {
280303
let new_x_bound = ZoomBound {
281304
lower: self.zoom_bounds.clone().unwrap_or_default().x.lower,
282305
upper: upper_bound_x,
283306
};
284-
self.update_zoom_bound_x(&new_x_bound);
307+
308+
let _ = self.update_zoom_bound_x(&new_x_bound);
309+
self.maybe_set_state_for_y_bound_generation(true);
285310
self.update_zoom_plot_data_and_cache();
286311
}
287312
MessagePlotting::SliderSplitChartHeight(new_height) => {

tcbee-viz/src/modules/ui/lib_widgets/app_widgets.rs

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,11 @@ pub fn display_current_mouse_position<'a, Message: 'a>(
4949
new_content
5050
}
5151

52+
//FIXME implement proper color scheme selector
53+
// pub fn display_color_scheme_selector<'a, Message: 'a + Clone>(
54+
// message_on_selection: imp
55+
// )
56+
5257
pub fn display_flow_selector<'a, Message: 'a + Clone>(
5358
ref_backend: &IntermediateBackend,
5459
focused_flow: &TcpFlowWrapper,

0 commit comments

Comments
 (0)