Skip to content

Commit

Permalink
Merge pull request #6 from KG32/feat/gui
Browse files Browse the repository at this point in the history
Feat/gui
  • Loading branch information
KG32 authored May 19, 2024
2 parents 7f5a458 + 87a8a4d commit cbb4a43
Show file tree
Hide file tree
Showing 4 changed files with 127 additions and 30 deletions.
4 changes: 2 additions & 2 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

144 changes: 121 additions & 23 deletions src/app.rs
Original file line number Diff line number Diff line change
@@ -1,14 +1,34 @@
#![cfg_attr(not(debug_assertions), windows_subsystem = "windows")] // hide console window on Windows in release

use eframe::egui::{self, InnerResponse, Ui};
use std::future::Future;
use std::{future::Future, path::PathBuf};
use std::error::Error;
use rfd::FileDialog;
use crate::{dive, stats::{Stats, StatsOutput}};

#[derive(Clone)]
pub struct App {
title: String,
stats: Stats,
stats_output: StatsOutput,
config: AppConfig,
state: AppState,
}

#[derive(Clone)]
struct AppState {
error: Option<AppError>
}

#[derive(Clone)]
struct AppError {
text: String,
}

#[derive(Clone)]
struct AppConfig {
path: Option<String>,
gradient_factors: (u8, u8),
}

impl Default for App {
Expand All @@ -17,6 +37,13 @@ impl Default for App {
title: "Dive reporter".to_owned(),
stats: Stats::new(),
stats_output: vec![],
config: AppConfig {
path: None,
gradient_factors: (30, 70)
},
state: AppState {
error: None,
}
}
}
}
Expand All @@ -25,30 +52,29 @@ impl eframe::App for App {
fn update(&mut self, ctx: &egui::Context, _frame: &mut eframe::Frame) {
egui::CentralPanel::default().show(ctx, |ui| {
ui.heading(&self.title);
// a simple button opening the dialog
if ui.button("📂 Open UDDF file").clicked() {
let file = FileDialog::new()
.set_directory("/")
.pick_file();
ui.separator();

if let Some(file_path) = file {
// todo err handling
self.stats = Stats::new().from_path(file_path.to_str().unwrap()).unwrap();
}
}
// config
self.render_pair(ui, "Path:", &self.config.path.clone().unwrap_or("-".to_string()));
ui.separator();

let stats = &self.stats;
if stats.dives_no > 0 {
ui.vertical(|ui| {
self.render_pair(ui, "Dives:", &stats.dives_no.to_string());
self.render_pair(ui, "Total time:", &Stats::seconds_to_readable(stats.total_time));
self.render_pair(ui, "Max depth", &stats.depth_max.to_string());
self.render_pair(ui, "Deco dives:", &stats.deco_dives_no.to_string());
self.render_pair(ui, "Total time in deco:", &&Stats::seconds_to_readable(stats.time_in_deco));
self.render_pair(ui, "Max surface GF:", &stats.gf_surf_max.round().to_string());
self.render_pair(ui, "Max GF99:", &stats.gf_99_max.round().to_string());
self.render_pair(ui, "Max end GF:", &stats.gf_end_max.round().to_string());
});
// open file btn
self.render_file_btns(ui);

ui.separator();

// stats container
match &self.state.error {
None => {
let stats = self.stats.clone();
if stats.dives_no > 0 {
self.state.error = None;
self.render_stats(ui, &stats)
}
},
Some(err) => {
self.render_error(ui, &err);
}
}
});
}
Expand All @@ -58,6 +84,8 @@ impl App {
pub fn init(&self) -> Result<(), eframe::Error> {
let options = eframe::NativeOptions {
viewport: egui::ViewportBuilder::default().with_inner_size([300.0, 600.0]),
follow_system_theme: false,
default_theme: eframe::Theme::Dark,
..Default::default()
};
eframe::run_native(
Expand All @@ -69,10 +97,80 @@ impl App {
)
}

fn render_file_btns(&mut self, ui: &mut Ui) {
if ui.button("📂 Open UDDF file").clicked() {
let file = FileDialog::new()
.set_directory("/")
.pick_file();

if let Some(file_path) = file {
self.run_stats(&file_path);
}
}
}

fn render_stats(&mut self, ui: &mut Ui, stats: &Stats) {
let depth_max = stats.depth_max.to_string();
let gf_surf_max = stats.gf_surf_max.round().to_string();
let gf_99_max = stats.gf_99_max.round().to_string();
let gf_end_max = stats.gf_end_max.round().to_string();

ui.vertical(|ui| {
self.render_pair(ui, "Dives:", &stats.dives_no.to_string());
self.render_pair(ui, "Total time:", &Stats::seconds_to_readable(stats.total_time));
self.render_pair(ui, "Max depth", &format!("{depth_max}m"));
self.render_pair(ui, "Deco dives:", &stats.deco_dives_no.to_string());
self.render_pair(ui, "Total time in deco:", &Stats::seconds_to_readable(stats.time_in_deco));
self.render_pair(ui, "Max surface GF:", &format!("{gf_surf_max}%"));
self.render_pair(ui, "Max GF99:", &format!("{gf_99_max}%"));
self.render_pair(ui, "Max end GF:", &format!("{gf_end_max}%"));
self.render_pair(ui, "Time below:", "");
for record in stats.time_below.iter() {
let (depth, time) = record;
ui.indent("", |ui| {
self.render_pair(ui, &format!("-{depth}:"), &Stats::seconds_to_readable(*time));
});
}
});
}

pub fn render_pair(&self, ui: &mut Ui, v1: &str, v2: &str) -> InnerResponse<()> {
ui.horizontal(|ui| {
ui.label(v1);
ui.label(v2);
})
}

fn render_error(&self, ui: &mut Ui, err: &AppError) {
let err_details_text = err.text.to_string();

ui.vertical(|ui| {
ui.heading("Error while reading stats");
ui.label(format!("Details: {err_details_text}"));
});
}

fn update_path(&mut self, new_path: String) {
self.config.path = Some(new_path);
}

fn run_stats(&mut self, file_path: &PathBuf) {
let selected_path = file_path.to_str().unwrap();
self.update_path(selected_path.to_string());
let stats_res = Stats::new().from_path(file_path.to_str().unwrap());
match stats_res {
Ok(stats) => {
if let Some(err) = &self.state.error {
self.state.error = None;
}
self.stats = stats
},
Err(err) => {
let app_err = AppError {
text: err.to_string()
};
self.state.error = Some(app_err);
}
}
}
}
6 changes: 3 additions & 3 deletions src/dive.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
use dive_deco::{BuehlmannConfig, BuehlmannModel, DecoModel, Gas, Pressure};
use dive_deco::{BuehlmannConfig, BuehlmannModel, DecoModel, Gas, Pressure, Supersaturation};

use crate::common::{GradientFactorsSetting, GF};
use crate::parser::WaypointElem;
Expand Down Expand Up @@ -105,8 +105,8 @@ impl Dive {
model.step(&data_point.depth, &step_time, gas);

// GFs
let gfs = model.gfs_current();
self.register_gfs(gfs, &step_time, &data_point.depth);
let Supersaturation { gf_99, gf_surf } = model.supersaturation();
self.register_gfs((gf_99, gf_surf), &step_time, &data_point.depth);

// deco time
if model.ceiling() > 0. {
Expand Down
3 changes: 1 addition & 2 deletions src/stats.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,7 @@ use crate::parser::{self, UDDFDoc, Mix, DiveElem, WaypointElem};
use crate::dive::{Dive, DiveConfig};
use colored::*;

#[derive(Debug)]

#[derive(Clone, Debug)]
pub struct Stats {
pub dives_no: usize,
pub total_time: Seconds,
Expand Down

0 comments on commit cbb4a43

Please sign in to comment.