diff --git a/src/main.rs b/src/main.rs index 756846c..08066fc 100644 --- a/src/main.rs +++ b/src/main.rs @@ -68,7 +68,10 @@ impl eframe::App for MyApp { egui::TopBottomPanel::top("menu_bar_panel").show(ctx, |ui| { menu::bar(ui, |ui| { ui.menu_button("View", |ui| { - if ui.add_enabled(self.edit_films_window.is_none(), Button::new("Edit films")).clicked() { + if ui + .add_enabled(self.edit_films_window.is_none(), Button::new("Edit films")) + .clicked() + { self.edit_films_window = Some(EditFilmsWindow::new()); } }) @@ -79,7 +82,9 @@ impl eframe::App for MyApp { ui.label("Rolls:"); for (i, roll) in self.state.rolls.iter().enumerate() { let has_view = self.roll_views.iter().any(|view| view.roll() == i); - if ui.add_enabled(!has_view, Button::new(roll.short_str())).clicked() + if ui + .add_enabled(!has_view, Button::new(roll.short_str())) + .clicked() && !has_view { self.roll_views.push(RollViewWindow::new(i)); diff --git a/src/new_roll.rs b/src/new_roll.rs index e7bdfbd..49a89ed 100644 --- a/src/new_roll.rs +++ b/src/new_roll.rs @@ -13,8 +13,10 @@ pub struct NewRollWindow { desc: String, date: NaiveDate, film: FilmKey, + shot_at: Option, exps: u8, show_id_req_err: bool, + show_pp_iso_err: bool, } impl NewRollWindow { @@ -30,8 +32,10 @@ impl NewRollWindow { desc: String::new(), date: Local::now().date_naive(), film, + shot_at: None, exps: 24, show_id_req_err: false, + show_pp_iso_err: false, } } } @@ -54,6 +58,9 @@ impl NewRollWindow { Window::new("New Roll") .open(&mut close_unclicked) .show(ctx, |ui| { + if self.show_id_req_err { + ui.colored_label(Color32::DARK_RED, "Error: ID required"); + } ui.horizontal(|ui| { let label = ui.label("ID: "); ui.text_edit_singleline(&mut self.id).labelled_by(label.id); @@ -82,6 +89,7 @@ impl NewRollWindow { }); ui.horizontal(|ui| { ui.label("Film: "); + let old_film = self.film; egui::ComboBox::from_id_source("new_roll_film") .selected_text(format!("{}", &app_state.films[self.film])) .show_ui(ui, |ui| { @@ -89,25 +97,54 @@ impl NewRollWindow { ui.selectable_value(&mut self.film, i, film.to_string()); } }); + if self.film != old_film && self.shot_at.is_some() { + self.shot_at = Some(app_state.films[self.film].iso); + } + }); + ui.horizontal(|ui| { + ui.label("Pushed/Pulled: "); + let mut check_state = self.shot_at.is_some(); + ui.checkbox(&mut check_state, ""); + if check_state != self.shot_at.is_some() { + if check_state { + self.shot_at = Some(app_state.films[self.film].iso); + } else { + self.shot_at = None; + self.show_pp_iso_err = false; + } + } + }); + if self.show_pp_iso_err { + ui.colored_label( + Color32::DARK_RED, + "Error: Push/pull ISO must be different from the roll's box ISO", + ); + } + ui.horizontal(|ui| { + if let Some(ref mut iso) = self.shot_at { + let label = ui.label("ISO: "); + ui.add(DragValue::new(iso).clamp_range(1..=u32::MAX)) + .labelled_by(label.id); + } }); if ui.button("Submit").clicked() { - if self.id.is_empty() { - self.show_id_req_err = true; - } else { + self.show_id_req_err = self.id.is_empty(); + self.show_pp_iso_err = self + .shot_at + .map_or(false, |iso| iso == app_state.films[self.film].iso); + if !self.show_id_req_err && !self.show_pp_iso_err { app_state.rolls.push(Roll::new( self.id.clone(), self.name.clone(), self.desc.clone(), self.date, self.film, + self.shot_at, self.exps, )); close_window = true; } } - if self.show_id_req_err { - ui.colored_label(Color32::DARK_RED, "Error: ID required"); - } }); !close_unclicked || close_window } diff --git a/src/roll.rs b/src/roll.rs index 1048c35..d9aab7d 100644 --- a/src/roll.rs +++ b/src/roll.rs @@ -21,6 +21,7 @@ pub struct Roll { pub desc: String, pub date: NaiveDate, pub film: FilmKey, + pub shot_at: Option, pub exposures: Vec, } @@ -31,6 +32,7 @@ impl Roll { desc: String, date: NaiveDate, film: FilmKey, + shot_at: Option, num_exposures: u8, ) -> Self { let mut exposures = Vec::new(); @@ -48,6 +50,7 @@ impl Roll { desc, date, film, + shot_at, exposures, } } diff --git a/src/roll_view.rs b/src/roll_view.rs index 7d2c98f..902ff33 100644 --- a/src/roll_view.rs +++ b/src/roll_view.rs @@ -1,6 +1,6 @@ use chrono::NaiveDate; use eframe::{ - egui::{self, Button, RichText, Window}, + egui::{self, Button, DragValue, RichText, Window}, epaint::Color32, }; use egui_datepicker::DatePicker; @@ -22,6 +22,9 @@ pub struct RollViewWindow { edit_date: NaiveDate, editing_film: bool, edit_film: FilmKey, + editing_shot_at: bool, + edit_shot_at: Option, + show_pp_iso_err: bool, } impl RollViewWindow { @@ -40,6 +43,9 @@ impl RollViewWindow { edit_date: NaiveDate::default(), editing_film: false, edit_film: FilmKey::from(0), + editing_shot_at: false, + edit_shot_at: None, + show_pp_iso_err: false, } } @@ -167,6 +173,80 @@ impl RollViewWindow { } } }); + if self.editing_shot_at { + ui.horizontal(|ui| { + ui.label("Pushed/Pulled: "); + let mut check_state = self.edit_shot_at.is_some(); + ui.checkbox(&mut check_state, ""); + if check_state != self.edit_shot_at.is_some() { + if check_state { + if self.editing_film { + self.edit_shot_at = Some(app_state.films[self.edit_film].iso); + } else { + self.edit_shot_at = Some(app_state.films[roll.film].iso); + } + } else { + self.edit_shot_at = None; + self.show_pp_iso_err = false; + } + } + }); + if self.show_pp_iso_err { + ui.colored_label( + Color32::DARK_RED, + "Error: Push/pull ISO must be different from the roll's box ISO", + ); + } + if let Some(ref mut iso) = self.edit_shot_at { + ui.horizontal(|ui| { + let label = ui.label("ISO: "); + ui.add(DragValue::new(iso).clamp_range(1..=u32::MAX)) + .labelled_by(label.id); + }); + } + if ui.button("Done").clicked() { + if self.editing_film { + self.show_pp_iso_err = self + .edit_shot_at + .map_or(false, |iso| iso == app_state.films[self.edit_film].iso); + } else { + self.show_pp_iso_err = self + .edit_shot_at + .map_or(false, |iso| iso == app_state.films[roll.film].iso); + } + if !self.show_pp_iso_err { + roll.shot_at = self.edit_shot_at; + self.editing_shot_at = false; + } + } + if ui.button("Cancel").clicked() { + self.editing_shot_at = false; + } + } else { + ui.horizontal(|ui| { + if let Some(iso) = roll.shot_at { + if iso > app_state.films[roll.film].iso { + ui.label(format!( + "Pushed {:.2} stops (ISO {})", + (iso as f64 / app_state.films[roll.film].iso as f64).log2(), + iso + )); + } else { + ui.label(format!( + "Pulled {:.2} stops (ISO {})", + -((iso as f64 / app_state.films[roll.film].iso as f64).log2()), + iso + )); + } + } else { + ui.label("Shot at box ISO"); + } + if ui.button("Edit").clicked() { + self.editing_shot_at = true; + self.edit_shot_at = roll.shot_at; + } + }); + } ui.label("Exposures:"); ui.horizontal_top(|ui| { ui.vertical(|ui| {