Compare commits
5 Commits
810c19d7df
...
5aa29ff836
| Author | SHA1 | Date |
|---|---|---|
|
|
5aa29ff836 | |
|
|
fb095d644d | |
|
|
35eba6f906 | |
|
|
e855732901 | |
|
|
f0476fe650 |
|
|
@ -14,13 +14,15 @@ use crate::modals::{self, ModalState};
|
||||||
use crate::plate::{add_plate, PlateDisplayOptions, PlateUiState};
|
use crate::plate::{add_plate, PlateDisplayOptions, PlateUiState};
|
||||||
use crate::transfer_menu::{transfer_menu, CurrentTransferState, TransferMenuState};
|
use crate::transfer_menu::{transfer_menu, CurrentTransferState, TransferMenuState};
|
||||||
use crate::tree::tree;
|
use crate::tree::tree;
|
||||||
|
use crate::upper_menu;
|
||||||
|
|
||||||
#[non_exhaustive]
|
#[non_exhaustive]
|
||||||
#[derive(Debug, serde::Serialize, serde::Deserialize)]
|
#[derive(Debug, serde::Serialize, serde::Deserialize)]
|
||||||
struct MainWindowState {
|
pub struct MainWindowState {
|
||||||
show_side_panel: bool,
|
pub show_side_panel: bool,
|
||||||
plate_display_options: PlateDisplayOptions,
|
pub plate_display_options: PlateDisplayOptions,
|
||||||
csv_export_type: CsvExportType,
|
pub csv_export_type: CsvExportType,
|
||||||
|
pub show_plates_horizontal: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Default for MainWindowState {
|
impl Default for MainWindowState {
|
||||||
|
|
@ -29,13 +31,14 @@ impl Default for MainWindowState {
|
||||||
show_side_panel: true,
|
show_side_panel: true,
|
||||||
plate_display_options: PlateDisplayOptions::default(),
|
plate_display_options: PlateDisplayOptions::default(),
|
||||||
csv_export_type: CsvExportType::default(),
|
csv_export_type: CsvExportType::default(),
|
||||||
|
show_plates_horizontal: false,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[non_exhaustive]
|
#[non_exhaustive]
|
||||||
#[derive(Debug, serde::Serialize, serde::Deserialize, PartialEq, Eq, std::default::Default)]
|
#[derive(Debug, serde::Serialize, serde::Deserialize, PartialEq, Eq, std::default::Default)]
|
||||||
enum CsvExportType {
|
pub enum CsvExportType {
|
||||||
#[default]
|
#[default]
|
||||||
Normal,
|
Normal,
|
||||||
EchoClient,
|
EchoClient,
|
||||||
|
|
@ -107,127 +110,13 @@ impl eframe::App for PlateToolEframe {
|
||||||
crate::styling::set_visuals(&ctx);
|
crate::styling::set_visuals(&ctx);
|
||||||
|
|
||||||
egui::TopBottomPanel::top("top_panel").show(ctx, |ui| {
|
egui::TopBottomPanel::top("top_panel").show(ctx, |ui| {
|
||||||
egui::menu::bar(ui, |ui| {
|
upper_menu::render_menu_bar(
|
||||||
ui.menu_button("File", |ui| {
|
ui,
|
||||||
if ui.button("New Plate").clicked() {
|
&mut self.main_state,
|
||||||
crate::modals::open_new_plate_modal(&mut self.modal_state);
|
&mut self.modal_state,
|
||||||
}
|
&mut self.current_transfer_state,
|
||||||
ui.menu_button("Export", |ui| {
|
&mut self.main_window_state,
|
||||||
if ui.button("Export as CSV").clicked() {
|
);
|
||||||
let records: Vec<TransferRecord> = self
|
|
||||||
.main_state
|
|
||||||
.transfers
|
|
||||||
.iter()
|
|
||||||
.flat_map(|transfer| {
|
|
||||||
let src_barcode = self
|
|
||||||
.main_state
|
|
||||||
.source_plates
|
|
||||||
.iter()
|
|
||||||
.find(|spi| spi.get_uuid() == transfer.source_id)?;
|
|
||||||
let dest_barcode = self
|
|
||||||
.main_state
|
|
||||||
.destination_plates
|
|
||||||
.iter()
|
|
||||||
.find(|dpi| dpi.get_uuid() == transfer.dest_id)?;
|
|
||||||
|
|
||||||
if self.main_window_state.csv_export_type
|
|
||||||
!= CsvExportType::EchoClient
|
|
||||||
|| self
|
|
||||||
.main_state
|
|
||||||
.get_current_source_uuid()
|
|
||||||
.is_some_and(|x| x != src_barcode.get_uuid())
|
|
||||||
|| self
|
|
||||||
.main_state
|
|
||||||
.get_current_destination_uuid()
|
|
||||||
.is_some_and(|x| x != dest_barcode.get_uuid())
|
|
||||||
{
|
|
||||||
return None;
|
|
||||||
}
|
|
||||||
|
|
||||||
Some(transfer_to_records(
|
|
||||||
transfer,
|
|
||||||
&src_barcode.name,
|
|
||||||
&dest_barcode.name,
|
|
||||||
))
|
|
||||||
})
|
|
||||||
.flatten()
|
|
||||||
.collect();
|
|
||||||
|
|
||||||
let data = match self.main_window_state.csv_export_type {
|
|
||||||
CsvExportType::Normal => records_to_csv(records),
|
|
||||||
CsvExportType::EchoClient => records_to_echo_client_csv(records),
|
|
||||||
};
|
|
||||||
if let Ok(data) = data {
|
|
||||||
let bytes: &[u8] = data.as_bytes();
|
|
||||||
save_file(bytes, Some("transfers.csv"));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if ui.button("Export as JSON").clicked() {
|
|
||||||
let data = serde_json::to_string_pretty(&self.main_state);
|
|
||||||
if let Ok(data) = data {
|
|
||||||
let bytes: &[u8] = data.as_bytes();
|
|
||||||
save_file(bytes, Some("plate_tool_state.json"));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
ui.menu_button("Import", |ui| {
|
|
||||||
if ui.button("Import from JSON").clicked() {}
|
|
||||||
if ui.button("Import transfer from CSV").clicked() {}
|
|
||||||
});
|
|
||||||
if ui.button("Reset All").clicked() {
|
|
||||||
self.main_state = MainState::default();
|
|
||||||
self.current_transfer_state = CurrentTransferState::default();
|
|
||||||
}
|
|
||||||
if ui.button("Dump State").clicked() {
|
|
||||||
log::warn!("{:?}\n{:?}", self.main_state, self.current_transfer_state);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
ui.menu_button("Options", |ui| {
|
|
||||||
ui.menu_button("Styles", |ui| {
|
|
||||||
ui.toggle_value(
|
|
||||||
&mut self
|
|
||||||
.main_window_state
|
|
||||||
.plate_display_options
|
|
||||||
.show_transfer_hashes,
|
|
||||||
"Toggle transfer hashes",
|
|
||||||
);
|
|
||||||
ui.toggle_value(
|
|
||||||
&mut self
|
|
||||||
.main_window_state
|
|
||||||
.plate_display_options
|
|
||||||
.show_volume_heatmap,
|
|
||||||
"Toggle volume heatmap",
|
|
||||||
);
|
|
||||||
ui.toggle_value(
|
|
||||||
&mut self
|
|
||||||
.main_window_state
|
|
||||||
.plate_display_options
|
|
||||||
.show_coordinates,
|
|
||||||
"Toggle coordinate highlighting",
|
|
||||||
);
|
|
||||||
});
|
|
||||||
ui.menu_button("Exports", |ui| {
|
|
||||||
ui.menu_button("CSV Export Type", |ui| {
|
|
||||||
ui.radio_value(
|
|
||||||
&mut self.main_window_state.csv_export_type,
|
|
||||||
CsvExportType::Normal,
|
|
||||||
format!("{}", CsvExportType::Normal),
|
|
||||||
);
|
|
||||||
ui.radio_value(
|
|
||||||
&mut self.main_window_state.csv_export_type,
|
|
||||||
CsvExportType::EchoClient,
|
|
||||||
format!("{}", CsvExportType::EchoClient),
|
|
||||||
);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
ui.menu_button("Windows", |ui| {
|
|
||||||
ui.toggle_value(
|
|
||||||
&mut self.main_window_state.show_side_panel,
|
|
||||||
"Toggle side panel",
|
|
||||||
);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
});
|
|
||||||
});
|
});
|
||||||
|
|
||||||
if self.main_window_state.show_side_panel {
|
if self.main_window_state.show_side_panel {
|
||||||
|
|
@ -262,45 +151,85 @@ impl eframe::App for PlateToolEframe {
|
||||||
ids.sort_unstable();
|
ids.sort_unstable();
|
||||||
ids
|
ids
|
||||||
};
|
};
|
||||||
|
|
||||||
|
fn add_plates(
|
||||||
|
ui: &mut egui::Ui,
|
||||||
|
main_state: &MainState,
|
||||||
|
current_transfer_state: &CurrentTransferState,
|
||||||
|
source_plate_state: &Mutex<PlateUiState>,
|
||||||
|
destination_plate_state: &Mutex<PlateUiState>,
|
||||||
|
main_window_state: &MainWindowState,
|
||||||
|
plate_size: egui::Vec2,
|
||||||
|
ordered_ids: Vec<plate_tool_lib::uuid::Uuid>,
|
||||||
|
) {
|
||||||
|
if let Some(source_pi) = main_state.get_current_source_plateinstance() {
|
||||||
|
add_plate(
|
||||||
|
plate_size,
|
||||||
|
source_pi.plate.plate_format,
|
||||||
|
main_state.get_current_source_transfers(),
|
||||||
|
plate_tool_lib::plate::PlateType::Source,
|
||||||
|
&ordered_ids,
|
||||||
|
&main_state.transfer_region_cache,
|
||||||
|
Some(¤t_transfer_state),
|
||||||
|
ui,
|
||||||
|
source_plate_state.lock().unwrap().deref_mut(),
|
||||||
|
main_window_state.plate_display_options,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
if let Some(destination_pi) = main_state.get_current_destination_plateinstance() {
|
||||||
|
add_plate(
|
||||||
|
plate_size,
|
||||||
|
destination_pi.plate.plate_format,
|
||||||
|
main_state.get_current_destination_transfers(),
|
||||||
|
plate_tool_lib::plate::PlateType::Destination,
|
||||||
|
&ordered_ids,
|
||||||
|
&main_state.transfer_region_cache,
|
||||||
|
Some(¤t_transfer_state),
|
||||||
|
ui,
|
||||||
|
destination_plate_state.lock().unwrap().deref_mut(),
|
||||||
|
main_window_state.plate_display_options,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
egui::CentralPanel::default().show(ctx, |ui| {
|
egui::CentralPanel::default().show(ctx, |ui| {
|
||||||
ui.vertical(|ui| {
|
let available_size = ui.available_size();
|
||||||
let available_size = ui.available_size();
|
if !self.main_window_state.show_plates_horizontal {
|
||||||
let half_height = {
|
ui.vertical(|ui| {
|
||||||
let mut x = available_size;
|
let plate_size = {
|
||||||
x.y /= 2.0;
|
let mut x = available_size;
|
||||||
x
|
x.y /= 2.0;
|
||||||
};
|
x
|
||||||
if let Some(source_pi) = self.main_state.get_current_source_plateinstance() {
|
};
|
||||||
add_plate(
|
add_plates(
|
||||||
half_height,
|
|
||||||
source_pi.plate.plate_format,
|
|
||||||
self.main_state.get_current_source_transfers(),
|
|
||||||
plate_tool_lib::plate::PlateType::Source,
|
|
||||||
&ordered_ids,
|
|
||||||
&self.main_state.transfer_region_cache,
|
|
||||||
Some(&self.current_transfer_state),
|
|
||||||
ui,
|
ui,
|
||||||
self.source_plate_state.lock().unwrap().deref_mut(),
|
&self.main_state,
|
||||||
self.main_window_state.plate_display_options,
|
&self.current_transfer_state,
|
||||||
|
&self.source_plate_state,
|
||||||
|
&self.destination_plate_state,
|
||||||
|
&self.main_window_state,
|
||||||
|
plate_size,
|
||||||
|
ordered_ids,
|
||||||
);
|
);
|
||||||
}
|
});
|
||||||
if let Some(destination_pi) =
|
} else {
|
||||||
self.main_state.get_current_destination_plateinstance()
|
ui.horizontal(|ui| {
|
||||||
{
|
let plate_size = {
|
||||||
add_plate(
|
let mut x = available_size;
|
||||||
half_height,
|
x.x /= 2.0;
|
||||||
destination_pi.plate.plate_format,
|
x
|
||||||
self.main_state.get_current_destination_transfers(),
|
};
|
||||||
plate_tool_lib::plate::PlateType::Destination,
|
add_plates(
|
||||||
&ordered_ids,
|
|
||||||
&self.main_state.transfer_region_cache,
|
|
||||||
Some(&self.current_transfer_state),
|
|
||||||
ui,
|
ui,
|
||||||
self.destination_plate_state.lock().unwrap().deref_mut(),
|
&self.main_state,
|
||||||
self.main_window_state.plate_display_options,
|
&self.current_transfer_state,
|
||||||
|
&self.source_plate_state,
|
||||||
|
&self.destination_plate_state,
|
||||||
|
&self.main_window_state,
|
||||||
|
plate_size,
|
||||||
|
ordered_ids,
|
||||||
);
|
);
|
||||||
}
|
});
|
||||||
});
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
// Modal processing
|
// Modal processing
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,37 @@
|
||||||
|
use eframe::egui;
|
||||||
|
|
||||||
|
pub fn drag_value_with_scroll<T>(
|
||||||
|
ui: &mut egui::Ui,
|
||||||
|
value: &mut T,
|
||||||
|
range: std::ops::RangeInclusive<T>,
|
||||||
|
speed_drag: f64,
|
||||||
|
speed_scroll: f64,
|
||||||
|
) -> egui::Response
|
||||||
|
where
|
||||||
|
T: egui::emath::Numeric + std::ops::Add<Output = T> + std::fmt::Debug
|
||||||
|
{
|
||||||
|
let drag = egui::DragValue::new(value)
|
||||||
|
.speed(speed_drag)
|
||||||
|
.range(range.clone());
|
||||||
|
|
||||||
|
let response = ui.add(drag);
|
||||||
|
|
||||||
|
if response.hovered() {
|
||||||
|
let scroll_diff = ui.input(|i| i.smooth_scroll_delta.y);
|
||||||
|
|
||||||
|
const THRESHOLD: f32 = 10.0;
|
||||||
|
if scroll_diff > THRESHOLD {
|
||||||
|
*value = clamp_partial(*value + T::from_f64(speed_scroll), *range.start(), *range.end());
|
||||||
|
} else if scroll_diff < -THRESHOLD {
|
||||||
|
*value = clamp_partial(*value + T::from_f64(-speed_scroll), *range.start(), *range.end());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
response
|
||||||
|
}
|
||||||
|
|
||||||
|
fn clamp_partial<T: PartialOrd + Copy + std::fmt::Debug>(val: T, min: T, max: T) -> T {
|
||||||
|
if val < min { min }
|
||||||
|
else if val > max { max }
|
||||||
|
else { val }
|
||||||
|
}
|
||||||
|
|
@ -6,4 +6,6 @@ mod main_state;
|
||||||
mod modals;
|
mod modals;
|
||||||
mod styling;
|
mod styling;
|
||||||
mod file_handling;
|
mod file_handling;
|
||||||
|
mod upper_menu;
|
||||||
|
mod extra_widgets;
|
||||||
pub use app::PlateToolEframe;
|
pub use app::PlateToolEframe;
|
||||||
|
|
|
||||||
|
|
@ -3,6 +3,7 @@ use plate_tool_lib::transfer_region::{self, Region, TransferRegion};
|
||||||
use std::hash::{DefaultHasher, Hash, Hasher};
|
use std::hash::{DefaultHasher, Hash, Hasher};
|
||||||
use std::sync::{Arc, Mutex};
|
use std::sync::{Arc, Mutex};
|
||||||
|
|
||||||
|
use crate::extra_widgets;
|
||||||
use crate::main_state::{self, MainState};
|
use crate::main_state::{self, MainState};
|
||||||
|
|
||||||
pub type CurrentTransferState = Arc<Mutex<CurrentTransferStateInterior>>;
|
pub type CurrentTransferState = Arc<Mutex<CurrentTransferStateInterior>>;
|
||||||
|
|
@ -140,18 +141,30 @@ impl CurrentTransferStateInterior {
|
||||||
None
|
None
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn convert_to_transfer(&self, ms: &MainState) -> Option<plate_tool_lib::transfer::Transfer> {
|
pub fn convert_to_transfer(
|
||||||
|
&self,
|
||||||
|
ms: &MainState,
|
||||||
|
) -> Option<plate_tool_lib::transfer::Transfer> {
|
||||||
let source_plate_uuid = ms.get_current_source_uuid()?;
|
let source_plate_uuid = ms.get_current_source_uuid()?;
|
||||||
let destination_plate_uuid = ms.get_current_destination_uuid()?;
|
let destination_plate_uuid = ms.get_current_destination_uuid()?;
|
||||||
let source_plate_instance = ms.source_plates.iter().find(|x| x.get_uuid() == source_plate_uuid)?;
|
let source_plate_instance = ms
|
||||||
let destination_plate_instance = ms.destination_plates.iter().find(|x| x.get_uuid() == destination_plate_uuid)?;
|
.source_plates
|
||||||
|
.iter()
|
||||||
|
.find(|x| x.get_uuid() == source_plate_uuid)?;
|
||||||
|
let destination_plate_instance = ms
|
||||||
|
.destination_plates
|
||||||
|
.iter()
|
||||||
|
.find(|x| x.get_uuid() == destination_plate_uuid)?;
|
||||||
let transfer = Some(plate_tool_lib::transfer::Transfer::new(
|
let transfer = Some(plate_tool_lib::transfer::Transfer::new(
|
||||||
source_plate_instance.clone(),
|
source_plate_instance.clone(),
|
||||||
destination_plate_instance.clone(),
|
destination_plate_instance.clone(),
|
||||||
self.generate_transfer_region(),
|
self.generate_transfer_region(),
|
||||||
self.transfer_name.clone(),
|
self.transfer_name.clone(),
|
||||||
));
|
));
|
||||||
transfer.map(|mut x| {x.volume = plate_tool_lib::transfer_volume::TransferVolume::Single(self.volume); x})
|
transfer.map(|mut x| {
|
||||||
|
x.volume = plate_tool_lib::transfer_volume::TransferVolume::Single(self.volume);
|
||||||
|
x
|
||||||
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -170,7 +183,7 @@ impl Default for TransferMenuState {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
impl TransferMenuState {
|
impl TransferMenuState {
|
||||||
fn new_from_cts(cts: &CurrentTransferState) -> Self {
|
fn _new_from_cts(cts: &CurrentTransferState) -> Self {
|
||||||
let cts = cts.lock().unwrap();
|
let cts = cts.lock().unwrap();
|
||||||
let source_region_string = cts.source_region.to_string();
|
let source_region_string = cts.source_region.to_string();
|
||||||
let destination_region_string = cts.destination_region.to_string();
|
let destination_region_string = cts.destination_region.to_string();
|
||||||
|
|
@ -188,7 +201,7 @@ pub fn transfer_menu(
|
||||||
main_state: &mut MainState,
|
main_state: &mut MainState,
|
||||||
) {
|
) {
|
||||||
// Can we reduce the length of this lock pls
|
// Can we reduce the length of this lock pls
|
||||||
let cts = state;
|
let _cts = state;
|
||||||
let mut state = state.lock().unwrap();
|
let mut state = state.lock().unwrap();
|
||||||
|
|
||||||
ui.horizontal(|ui| {
|
ui.horizontal(|ui| {
|
||||||
|
|
@ -200,6 +213,17 @@ pub fn transfer_menu(
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
ui.horizontal(|ui| {
|
||||||
|
ui.add(egui::Label::new("Volume"));
|
||||||
|
extra_widgets::drag_value_with_scroll(
|
||||||
|
ui,
|
||||||
|
&mut state.volume,
|
||||||
|
0.0..=f32::INFINITY,
|
||||||
|
0.5,
|
||||||
|
1.0,
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
ui.horizontal(|ui| {
|
ui.horizontal(|ui| {
|
||||||
ui.add(egui::Label::new("Source Region"));
|
ui.add(egui::Label::new("Source Region"));
|
||||||
let resp = ui.add(
|
let resp = ui.add(
|
||||||
|
|
@ -245,18 +269,20 @@ pub fn transfer_menu(
|
||||||
ui.label("Source Interleave");
|
ui.label("Source Interleave");
|
||||||
ui.horizontal(|ui| {
|
ui.horizontal(|ui| {
|
||||||
ui.label("Row: ");
|
ui.label("Row: ");
|
||||||
ui.add(
|
extra_widgets::drag_value_with_scroll(
|
||||||
egui::DragValue::new(&mut state.source_row_interleave)
|
ui,
|
||||||
.fixed_decimals(0)
|
&mut state.source_row_interleave,
|
||||||
.range(1..=30)
|
0..=30,
|
||||||
.speed(0.1),
|
0.1,
|
||||||
|
1.0,
|
||||||
);
|
);
|
||||||
ui.label("Col: ");
|
ui.label("Col: ");
|
||||||
ui.add(
|
extra_widgets::drag_value_with_scroll(
|
||||||
egui::DragValue::new(&mut state.source_column_interleave)
|
ui,
|
||||||
.fixed_decimals(0)
|
&mut state.source_column_interleave,
|
||||||
.range(1..=30)
|
0..=30,
|
||||||
.speed(0.1),
|
0.1,
|
||||||
|
1.0,
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
@ -265,18 +291,20 @@ pub fn transfer_menu(
|
||||||
ui.label("Destination Interleave");
|
ui.label("Destination Interleave");
|
||||||
ui.horizontal(|ui| {
|
ui.horizontal(|ui| {
|
||||||
ui.label("Row: ");
|
ui.label("Row: ");
|
||||||
ui.add(
|
extra_widgets::drag_value_with_scroll(
|
||||||
egui::DragValue::new(&mut state.destination_row_interleave)
|
ui,
|
||||||
.fixed_decimals(0)
|
&mut state.destination_row_interleave,
|
||||||
.range(0..=30)
|
0..=30,
|
||||||
.speed(0.1),
|
0.1,
|
||||||
|
1.0,
|
||||||
);
|
);
|
||||||
ui.label("Col: ");
|
ui.label("Col: ");
|
||||||
ui.add(
|
extra_widgets::drag_value_with_scroll(
|
||||||
egui::DragValue::new(&mut state.destination_column_interleave)
|
ui,
|
||||||
.fixed_decimals(0)
|
&mut state.destination_column_interleave,
|
||||||
.range(0..=30)
|
0..=30,
|
||||||
.speed(0.1),
|
0.1,
|
||||||
|
1.0,
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
@ -285,12 +313,17 @@ pub fn transfer_menu(
|
||||||
if ui.button("Save").clicked() {
|
if ui.button("Save").clicked() {
|
||||||
if let Some(transfer_uuid) = main_state.get_current_transfer_uuid() {
|
if let Some(transfer_uuid) = main_state.get_current_transfer_uuid() {
|
||||||
log::info!("should change transfer");
|
log::info!("should change transfer");
|
||||||
if let Some(mut transfer) = main_state.transfers.iter_mut().find(|x| x.id == transfer_uuid) {
|
if let Some(transfer) = main_state
|
||||||
|
.transfers
|
||||||
|
.iter_mut()
|
||||||
|
.find(|x| x.id == transfer_uuid)
|
||||||
|
{
|
||||||
transfer.transfer_region = state.generate_transfer_region();
|
transfer.transfer_region = state.generate_transfer_region();
|
||||||
transfer.name = state.transfer_name.clone();
|
transfer.name = state.transfer_name.clone();
|
||||||
main_state.transfer_region_cache.invalidate(&transfer);
|
main_state.transfer_region_cache.invalidate(&transfer);
|
||||||
}
|
}
|
||||||
} else { // Need to make a new transfer
|
} else {
|
||||||
|
// Need to make a new transfer
|
||||||
if state.transfer_name.is_empty() {
|
if state.transfer_name.is_empty() {
|
||||||
state.transfer_name = "New Transfer".to_string();
|
state.transfer_name = "New Transfer".to_string();
|
||||||
}
|
}
|
||||||
|
|
@ -298,8 +331,10 @@ pub fn transfer_menu(
|
||||||
log::info!("{:?}", new_transfer);
|
log::info!("{:?}", new_transfer);
|
||||||
if let Some(new_transfer) = new_transfer {
|
if let Some(new_transfer) = new_transfer {
|
||||||
main_state.transfers.push(new_transfer);
|
main_state.transfers.push(new_transfer);
|
||||||
let new_transfer = main_state.transfers.last()
|
let new_transfer = main_state
|
||||||
.expect("Cannot be empty, just added a transfer");
|
.transfers
|
||||||
|
.last()
|
||||||
|
.expect("Cannot be empty, just added a transfer");
|
||||||
main_state.transfer_region_cache.add_overwrite(new_transfer);
|
main_state.transfer_region_cache.add_overwrite(new_transfer);
|
||||||
main_state.set_current_transfer(new_transfer.id);
|
main_state.set_current_transfer(new_transfer.id);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,191 @@
|
||||||
|
use crate::app::{CsvExportType, MainWindowState};
|
||||||
|
use crate::file_handling::save_file;
|
||||||
|
use crate::main_state::MainState;
|
||||||
|
use crate::modals::ModalState;
|
||||||
|
use crate::transfer_menu::CurrentTransferState;
|
||||||
|
|
||||||
|
use plate_tool_lib::csv::{
|
||||||
|
records_to_csv, records_to_echo_client_csv, transfer_to_records, TransferRecord,
|
||||||
|
};
|
||||||
|
|
||||||
|
use eframe::egui;
|
||||||
|
|
||||||
|
pub fn render_menu_bar(
|
||||||
|
ui: &mut egui::Ui,
|
||||||
|
main_state: &mut MainState,
|
||||||
|
modal_state: &mut ModalState,
|
||||||
|
current_transfer_state: &mut CurrentTransferState,
|
||||||
|
main_window_state: &mut MainWindowState,
|
||||||
|
) {
|
||||||
|
egui::MenuBar::new().ui(ui, |ui| {
|
||||||
|
ui.menu_button("File", |ui| {
|
||||||
|
render_file_menu(
|
||||||
|
ui,
|
||||||
|
main_state,
|
||||||
|
modal_state,
|
||||||
|
current_transfer_state,
|
||||||
|
main_window_state,
|
||||||
|
);
|
||||||
|
});
|
||||||
|
ui.menu_button("Options", |ui| {
|
||||||
|
render_options_menu(
|
||||||
|
ui,
|
||||||
|
main_state,
|
||||||
|
modal_state,
|
||||||
|
current_transfer_state,
|
||||||
|
main_window_state,
|
||||||
|
);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
fn render_file_menu(
|
||||||
|
ui: &mut egui::Ui,
|
||||||
|
main_state: &mut MainState,
|
||||||
|
modal_state: &mut ModalState,
|
||||||
|
current_transfer_state: &mut CurrentTransferState,
|
||||||
|
main_window_state: &mut MainWindowState,
|
||||||
|
) {
|
||||||
|
if ui.button("New Plate").clicked() {
|
||||||
|
crate::modals::open_new_plate_modal(modal_state);
|
||||||
|
}
|
||||||
|
|
||||||
|
ui.menu_button("Export", |ui| {
|
||||||
|
render_export_menu(
|
||||||
|
ui,
|
||||||
|
main_state,
|
||||||
|
modal_state,
|
||||||
|
current_transfer_state,
|
||||||
|
main_window_state,
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
ui.menu_button("Import", |ui| {
|
||||||
|
render_import_menu(
|
||||||
|
ui,
|
||||||
|
main_state,
|
||||||
|
modal_state,
|
||||||
|
current_transfer_state,
|
||||||
|
main_window_state,
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
if ui.button("Reset All").clicked() {
|
||||||
|
*main_state = MainState::default();
|
||||||
|
*current_transfer_state = CurrentTransferState::default();
|
||||||
|
}
|
||||||
|
if ui.button("Dump State").clicked() {
|
||||||
|
log::warn!("{:?}\n{:?}", main_state, current_transfer_state);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn render_export_menu(
|
||||||
|
ui: &mut egui::Ui,
|
||||||
|
main_state: &mut MainState,
|
||||||
|
_modal_state: &mut ModalState,
|
||||||
|
_current_transfer_state: &mut CurrentTransferState,
|
||||||
|
main_window_state: &mut MainWindowState,
|
||||||
|
) {
|
||||||
|
if ui.button("Export as CSV").clicked() {
|
||||||
|
let records: Vec<TransferRecord> = main_state
|
||||||
|
.transfers
|
||||||
|
.iter()
|
||||||
|
.flat_map(|transfer| {
|
||||||
|
let src_barcode = main_state
|
||||||
|
.source_plates
|
||||||
|
.iter()
|
||||||
|
.find(|spi| spi.get_uuid() == transfer.source_id)?;
|
||||||
|
let dest_barcode = main_state
|
||||||
|
.destination_plates
|
||||||
|
.iter()
|
||||||
|
.find(|dpi| dpi.get_uuid() == transfer.dest_id)?;
|
||||||
|
|
||||||
|
if main_window_state.csv_export_type != CsvExportType::EchoClient
|
||||||
|
|| main_state
|
||||||
|
.get_current_source_uuid()
|
||||||
|
.is_some_and(|x| x != src_barcode.get_uuid())
|
||||||
|
|| main_state
|
||||||
|
.get_current_destination_uuid()
|
||||||
|
.is_some_and(|x| x != dest_barcode.get_uuid())
|
||||||
|
{
|
||||||
|
return None;
|
||||||
|
}
|
||||||
|
|
||||||
|
Some(transfer_to_records(
|
||||||
|
transfer,
|
||||||
|
&src_barcode.name,
|
||||||
|
&dest_barcode.name,
|
||||||
|
))
|
||||||
|
})
|
||||||
|
.flatten()
|
||||||
|
.collect();
|
||||||
|
|
||||||
|
let data = match main_window_state.csv_export_type {
|
||||||
|
CsvExportType::Normal => records_to_csv(records),
|
||||||
|
CsvExportType::EchoClient => records_to_echo_client_csv(records),
|
||||||
|
};
|
||||||
|
if let Ok(data) = data {
|
||||||
|
let bytes: &[u8] = data.as_bytes();
|
||||||
|
save_file(bytes, Some("transfers.csv"));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if ui.button("Export as JSON").clicked() {
|
||||||
|
let data = serde_json::to_string_pretty(main_state);
|
||||||
|
if let Ok(data) = data {
|
||||||
|
let bytes: &[u8] = data.as_bytes();
|
||||||
|
save_file(bytes, Some("plate_tool_state.json"));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn render_import_menu(
|
||||||
|
ui: &mut egui::Ui,
|
||||||
|
_main_state: &mut MainState,
|
||||||
|
_modal_state: &mut ModalState,
|
||||||
|
_current_transfer_state: &mut CurrentTransferState,
|
||||||
|
_main_window_state: &mut MainWindowState,
|
||||||
|
) {
|
||||||
|
if ui.button("Import from JSON").clicked() {}
|
||||||
|
if ui.button("Import transfer from CSV").clicked() {}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn render_options_menu(
|
||||||
|
ui: &mut egui::Ui,
|
||||||
|
_main_state: &mut MainState,
|
||||||
|
_modal_state: &mut ModalState,
|
||||||
|
_current_transfer_state: &mut CurrentTransferState,
|
||||||
|
main_window_state: &mut MainWindowState,
|
||||||
|
) {
|
||||||
|
ui.menu_button("Styles", |ui| {
|
||||||
|
ui.toggle_value(
|
||||||
|
&mut main_window_state.plate_display_options.show_transfer_hashes,
|
||||||
|
"Toggle transfer hashes",
|
||||||
|
);
|
||||||
|
ui.toggle_value(
|
||||||
|
&mut main_window_state.plate_display_options.show_volume_heatmap,
|
||||||
|
"Toggle volume heatmap",
|
||||||
|
);
|
||||||
|
ui.toggle_value(
|
||||||
|
&mut main_window_state.plate_display_options.show_coordinates,
|
||||||
|
"Toggle coordinate highlighting",
|
||||||
|
);
|
||||||
|
});
|
||||||
|
ui.menu_button("Exports", |ui| {
|
||||||
|
ui.menu_button("CSV Export Type", |ui| {
|
||||||
|
ui.radio_value(
|
||||||
|
&mut main_window_state.csv_export_type,
|
||||||
|
CsvExportType::Normal,
|
||||||
|
format!("{}", CsvExportType::Normal),
|
||||||
|
);
|
||||||
|
ui.radio_value(
|
||||||
|
&mut main_window_state.csv_export_type,
|
||||||
|
CsvExportType::EchoClient,
|
||||||
|
format!("{}", CsvExportType::EchoClient),
|
||||||
|
);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
ui.menu_button("Windows", |ui| {
|
||||||
|
ui.toggle_value(&mut main_window_state.show_side_panel, "Toggle side panel");
|
||||||
|
ui.toggle_value(&mut main_window_state.show_plates_horizontal, "Show plates horizontally");
|
||||||
|
});
|
||||||
|
}
|
||||||
Loading…
Reference in New Issue