parent
ce0e1f2743
commit
d296854580
|
@ -18,6 +18,16 @@ version = "0.1.8"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "c71b1793ee61086797f5c80b6efa2b8ffa6d5dd703f118545808a7f2e27f7046"
|
checksum = "c71b1793ee61086797f5c80b6efa2b8ffa6d5dd703f118545808a7f2e27f7046"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "accesskit"
|
||||||
|
version = "0.17.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "d3d3b8f9bae46a948369bc4a03e815d4ed6d616bd00de4051133a5019dc31c5a"
|
||||||
|
dependencies = [
|
||||||
|
"enumn",
|
||||||
|
"serde",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "addr2line"
|
name = "addr2line"
|
||||||
version = "0.24.2"
|
version = "0.24.2"
|
||||||
|
@ -42,6 +52,7 @@ dependencies = [
|
||||||
"cfg-if",
|
"cfg-if",
|
||||||
"getrandom",
|
"getrandom",
|
||||||
"once_cell",
|
"once_cell",
|
||||||
|
"serde",
|
||||||
"version_check",
|
"version_check",
|
||||||
"zerocopy",
|
"zerocopy",
|
||||||
]
|
]
|
||||||
|
@ -215,6 +226,12 @@ dependencies = [
|
||||||
"windows-targets 0.52.6",
|
"windows-targets 0.52.6",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "base64"
|
||||||
|
version = "0.21.7"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "9d297deb1925b89f2ccc13d7635fa0714f12c87adce1c75356b39ca9b7178567"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "base64"
|
name = "base64"
|
||||||
version = "0.22.1"
|
version = "0.22.1"
|
||||||
|
@ -256,6 +273,9 @@ name = "bitflags"
|
||||||
version = "2.6.0"
|
version = "2.6.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "b048fb63fd8b5923fc5aa7b340d8e156aec7ec02f0c78fa8a6ddc2613f6f71de"
|
checksum = "b048fb63fd8b5923fc5aa7b340d8e156aec7ec02f0c78fa8a6ddc2613f6f71de"
|
||||||
|
dependencies = [
|
||||||
|
"serde",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "block"
|
name = "block"
|
||||||
|
@ -651,6 +671,7 @@ checksum = "7d72e9c39f6e11a2e922d04a34ec5e7ef522ea3f5a1acfca7a19d16ad5fe50f5"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"bytemuck",
|
"bytemuck",
|
||||||
"emath",
|
"emath",
|
||||||
|
"serde",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
|
@ -669,6 +690,7 @@ dependencies = [
|
||||||
"glow 0.16.0",
|
"glow 0.16.0",
|
||||||
"glutin",
|
"glutin",
|
||||||
"glutin-winit",
|
"glutin-winit",
|
||||||
|
"home",
|
||||||
"image",
|
"image",
|
||||||
"js-sys",
|
"js-sys",
|
||||||
"log",
|
"log",
|
||||||
|
@ -679,6 +701,8 @@ dependencies = [
|
||||||
"percent-encoding",
|
"percent-encoding",
|
||||||
"profiling",
|
"profiling",
|
||||||
"raw-window-handle",
|
"raw-window-handle",
|
||||||
|
"ron",
|
||||||
|
"serde",
|
||||||
"static_assertions",
|
"static_assertions",
|
||||||
"wasm-bindgen",
|
"wasm-bindgen",
|
||||||
"wasm-bindgen-futures",
|
"wasm-bindgen-futures",
|
||||||
|
@ -695,12 +719,15 @@ version = "0.30.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "252d52224d35be1535d7fd1d6139ce071fb42c9097773e79f7665604f5596b5e"
|
checksum = "252d52224d35be1535d7fd1d6139ce071fb42c9097773e79f7665604f5596b5e"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
|
"accesskit",
|
||||||
"ahash",
|
"ahash",
|
||||||
"emath",
|
"emath",
|
||||||
"epaint",
|
"epaint",
|
||||||
"log",
|
"log",
|
||||||
"nohash-hasher",
|
"nohash-hasher",
|
||||||
"profiling",
|
"profiling",
|
||||||
|
"ron",
|
||||||
|
"serde",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
|
@ -735,6 +762,7 @@ dependencies = [
|
||||||
"log",
|
"log",
|
||||||
"profiling",
|
"profiling",
|
||||||
"raw-window-handle",
|
"raw-window-handle",
|
||||||
|
"serde",
|
||||||
"smithay-clipboard",
|
"smithay-clipboard",
|
||||||
"web-time",
|
"web-time",
|
||||||
"webbrowser",
|
"webbrowser",
|
||||||
|
@ -766,6 +794,18 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "c4fe73c1207b864ee40aa0b0c038d6092af1030744678c60188a05c28553515d"
|
checksum = "c4fe73c1207b864ee40aa0b0c038d6092af1030744678c60188a05c28553515d"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"bytemuck",
|
"bytemuck",
|
||||||
|
"serde",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "enumn"
|
||||||
|
version = "0.1.14"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "2f9ed6b3789237c8a0c1c505af1c7eb2c560df6186f01b098c3a1064ea532f38"
|
||||||
|
dependencies = [
|
||||||
|
"proc-macro2",
|
||||||
|
"quote",
|
||||||
|
"syn 2.0.87",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
|
@ -807,6 +847,7 @@ dependencies = [
|
||||||
"nohash-hasher",
|
"nohash-hasher",
|
||||||
"parking_lot",
|
"parking_lot",
|
||||||
"profiling",
|
"profiling",
|
||||||
|
"serde",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
|
@ -2425,6 +2466,7 @@ dependencies = [
|
||||||
"env_logger",
|
"env_logger",
|
||||||
"log",
|
"log",
|
||||||
"plate-tool-lib",
|
"plate-tool-lib",
|
||||||
|
"serde",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
|
@ -2693,6 +2735,18 @@ version = "1.1.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "19b30a45b0cd0bcca8037f3d0dc3421eaf95327a17cad11964fb8179b4fc4832"
|
checksum = "19b30a45b0cd0bcca8037f3d0dc3421eaf95327a17cad11964fb8179b4fc4832"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "ron"
|
||||||
|
version = "0.8.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "b91f7eff05f748767f183df4320a63d6936e9c6107d97c9e6bdd9784f4289c94"
|
||||||
|
dependencies = [
|
||||||
|
"base64 0.21.7",
|
||||||
|
"bitflags 2.6.0",
|
||||||
|
"serde",
|
||||||
|
"serde_derive",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "rustc-demangle"
|
name = "rustc-demangle"
|
||||||
version = "0.1.24"
|
version = "0.1.24"
|
||||||
|
@ -2823,7 +2877,7 @@ version = "3.11.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "8e28bdad6db2b8340e449f7108f020b3b092e8583a9e3fb82713e1d4e71fe817"
|
checksum = "8e28bdad6db2b8340e449f7108f020b3b092e8583a9e3fb82713e1d4e71fe817"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"base64",
|
"base64 0.22.1",
|
||||||
"chrono",
|
"chrono",
|
||||||
"hex",
|
"hex",
|
||||||
"indexmap 1.9.3",
|
"indexmap 1.9.3",
|
||||||
|
|
|
@ -9,7 +9,9 @@ eframe = { version = "0.30", default-features = false, features = [
|
||||||
"default_fonts",
|
"default_fonts",
|
||||||
"glow",
|
"glow",
|
||||||
"wayland",
|
"wayland",
|
||||||
|
"persistence",
|
||||||
]}
|
]}
|
||||||
|
|
||||||
log = "0.4"
|
log = "0.4"
|
||||||
env_logger = "0.11"
|
env_logger = "0.11"
|
||||||
|
serde = { version = "1.0", features = ["derive"] }
|
||||||
|
|
|
@ -4,76 +4,14 @@ use std::sync::Mutex;
|
||||||
use eframe::egui::{self};
|
use eframe::egui::{self};
|
||||||
|
|
||||||
use plate_tool_lib::plate::PlateFormat;
|
use plate_tool_lib::plate::PlateFormat;
|
||||||
use plate_tool_lib::plate_instances;
|
|
||||||
|
|
||||||
use crate::plate::{add_grid, PlateUiState};
|
use crate::plate::{add_plate, PlateUiState};
|
||||||
use crate::transfer_menu::{self, transfer_menu, CurrentTransferState, TransferMenuState};
|
use crate::transfer_menu::{self, transfer_menu, CurrentTransferState, TransferMenuState};
|
||||||
|
use crate::main_state::{MainState, construct_fake_mainstate};
|
||||||
#[derive(Default)]
|
use crate::tree::tree;
|
||||||
pub struct MainState {
|
|
||||||
pub source_plates: Vec<plate_tool_lib::plate_instances::PlateInstance>,
|
|
||||||
pub destination_plates: Vec<plate_tool_lib::plate_instances::PlateInstance>,
|
|
||||||
pub transfers: Vec<plate_tool_lib::transfer::Transfer>,
|
|
||||||
}
|
|
||||||
|
|
||||||
fn construct_fake_mainstate() -> MainState {
|
|
||||||
let src_plate: plate_tool_lib::plate_instances::PlateInstance =
|
|
||||||
plate_instances::PlateInstance::new(
|
|
||||||
plate_tool_lib::plate::PlateType::Source,
|
|
||||||
PlateFormat::W96,
|
|
||||||
"src1".to_owned(),
|
|
||||||
);
|
|
||||||
let dest_plate: plate_tool_lib::plate_instances::PlateInstance =
|
|
||||||
plate_instances::PlateInstance::new(
|
|
||||||
plate_tool_lib::plate::PlateType::Destination,
|
|
||||||
PlateFormat::W96,
|
|
||||||
"dest1".to_owned(),
|
|
||||||
);
|
|
||||||
let well_a1 = plate_tool_lib::Well { row: 1, col: 1 };
|
|
||||||
let well_c3 = plate_tool_lib::Well { row: 3, col: 3 };
|
|
||||||
let well_a5 = plate_tool_lib::Well { row: 1, col: 5 };
|
|
||||||
|
|
||||||
let transfer1_region: plate_tool_lib::transfer_region::TransferRegion =
|
|
||||||
plate_tool_lib::transfer_region::TransferRegion {
|
|
||||||
source_plate: src_plate.plate,
|
|
||||||
source_region: plate_tool_lib::transfer_region::Region::Rect(well_a1, well_c3),
|
|
||||||
dest_plate: dest_plate.plate,
|
|
||||||
dest_region: plate_tool_lib::transfer_region::Region::Point(well_a1),
|
|
||||||
interleave_source: (1, 1),
|
|
||||||
interleave_dest: (1, 1),
|
|
||||||
};
|
|
||||||
let transfer1: plate_tool_lib::transfer::Transfer = plate_tool_lib::transfer::Transfer::new(
|
|
||||||
src_plate.clone(),
|
|
||||||
dest_plate.clone(),
|
|
||||||
transfer1_region,
|
|
||||||
"Shrimp".to_owned(),
|
|
||||||
);
|
|
||||||
|
|
||||||
let transfer2_region: plate_tool_lib::transfer_region::TransferRegion =
|
|
||||||
plate_tool_lib::transfer_region::TransferRegion {
|
|
||||||
source_plate: src_plate.plate,
|
|
||||||
source_region: plate_tool_lib::transfer_region::Region::Rect(well_a1, well_c3),
|
|
||||||
dest_plate: dest_plate.plate,
|
|
||||||
dest_region: plate_tool_lib::transfer_region::Region::Point(well_a5),
|
|
||||||
interleave_source: (1, 1),
|
|
||||||
interleave_dest: (2, 2),
|
|
||||||
};
|
|
||||||
let transfer2: plate_tool_lib::transfer::Transfer = plate_tool_lib::transfer::Transfer::new(
|
|
||||||
src_plate.clone(),
|
|
||||||
dest_plate.clone(),
|
|
||||||
transfer2_region,
|
|
||||||
"Shrimp".to_owned(),
|
|
||||||
);
|
|
||||||
|
|
||||||
|
|
||||||
MainState {
|
|
||||||
source_plates: vec![src_plate],
|
|
||||||
destination_plates: vec![dest_plate],
|
|
||||||
transfers: vec![transfer1, transfer2],
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[non_exhaustive]
|
#[non_exhaustive]
|
||||||
|
#[derive(Debug, serde::Serialize, serde::Deserialize)]
|
||||||
struct MainWindowState {
|
struct MainWindowState {
|
||||||
show_side_panel: bool,
|
show_side_panel: bool,
|
||||||
}
|
}
|
||||||
|
@ -87,12 +25,15 @@ impl Default for MainWindowState {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[non_exhaustive]
|
#[non_exhaustive]
|
||||||
|
#[derive(Debug, serde::Serialize, serde::Deserialize)]
|
||||||
pub struct PlateToolEframe {
|
pub struct PlateToolEframe {
|
||||||
source_plate_state: Mutex<PlateUiState>,
|
source_plate_state: Mutex<PlateUiState>,
|
||||||
destination_plate_state: Mutex<PlateUiState>,
|
destination_plate_state: Mutex<PlateUiState>,
|
||||||
main_window_state: MainWindowState,
|
main_window_state: MainWindowState,
|
||||||
current_transfer_state: CurrentTransferState,
|
current_transfer_state: CurrentTransferState,
|
||||||
|
#[serde(skip)]
|
||||||
transfer_menu_state: TransferMenuState,
|
transfer_menu_state: TransferMenuState,
|
||||||
|
#[serde(skip)]
|
||||||
transfer_region_cache: plate_tool_lib::transfer_region_cache::TransferRegionCache,
|
transfer_region_cache: plate_tool_lib::transfer_region_cache::TransferRegionCache,
|
||||||
main_state: MainState,
|
main_state: MainState,
|
||||||
}
|
}
|
||||||
|
@ -115,21 +56,24 @@ impl Default for PlateToolEframe {
|
||||||
impl PlateToolEframe {
|
impl PlateToolEframe {
|
||||||
pub fn new(cc: &eframe::CreationContext<'_>) -> Self {
|
pub fn new(cc: &eframe::CreationContext<'_>) -> Self {
|
||||||
// Would load state here
|
// Would load state here
|
||||||
|
if let Some(storage) = cc.storage {
|
||||||
|
return eframe::get_value(storage, eframe::APP_KEY).unwrap_or_default();
|
||||||
|
} else {
|
||||||
|
let pte: PlateToolEframe = Default::default();
|
||||||
|
pte.transfer_region_cache.generate_cache(&pte.main_state.transfers);
|
||||||
|
|
||||||
let pte: PlateToolEframe = Default::default();
|
pte
|
||||||
pte.transfer_region_cache.generate_cache(&pte.main_state.transfers);
|
}
|
||||||
|
|
||||||
pte
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl eframe::App for PlateToolEframe {
|
impl eframe::App for PlateToolEframe {
|
||||||
// State storage
|
// State storage
|
||||||
/*
|
|
||||||
fn save(&mut self, storage: &mut dyn eframe::Storage) {
|
fn save(&mut self, storage: &mut dyn eframe::Storage) {
|
||||||
unimplemented!()
|
log::info!("Saving state");
|
||||||
};
|
eframe::set_value(storage, eframe::APP_KEY, self);
|
||||||
*/
|
}
|
||||||
|
|
||||||
fn update(&mut self, ctx: &eframe::egui::Context, _frame: &mut eframe::Frame) {
|
fn update(&mut self, ctx: &eframe::egui::Context, _frame: &mut eframe::Frame) {
|
||||||
let ordered_ids: Vec<plate_tool_lib::uuid::Uuid> = {
|
let ordered_ids: Vec<plate_tool_lib::uuid::Uuid> = {
|
||||||
|
@ -179,6 +123,8 @@ impl eframe::App for PlateToolEframe {
|
||||||
if self.main_window_state.show_side_panel {
|
if self.main_window_state.show_side_panel {
|
||||||
egui::SidePanel::left("side_menus").show(ctx, |ui| {
|
egui::SidePanel::left("side_menus").show(ctx, |ui| {
|
||||||
ui.vertical(|ui| {
|
ui.vertical(|ui| {
|
||||||
|
tree(ui, &mut self.main_state, &self.current_transfer_state);
|
||||||
|
ui.separator();
|
||||||
transfer_menu(ui, &self.current_transfer_state, &mut self.transfer_menu_state);
|
transfer_menu(ui, &self.current_transfer_state, &mut self.transfer_menu_state);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
@ -192,7 +138,7 @@ impl eframe::App for PlateToolEframe {
|
||||||
x.y /= 2.0;
|
x.y /= 2.0;
|
||||||
x
|
x
|
||||||
};
|
};
|
||||||
add_grid(
|
add_plate(
|
||||||
half_height,
|
half_height,
|
||||||
PlateFormat::W96,
|
PlateFormat::W96,
|
||||||
&self.main_state.transfers,
|
&self.main_state.transfers,
|
||||||
|
@ -203,7 +149,7 @@ impl eframe::App for PlateToolEframe {
|
||||||
ui,
|
ui,
|
||||||
self.source_plate_state.lock().unwrap().deref_mut(),
|
self.source_plate_state.lock().unwrap().deref_mut(),
|
||||||
);
|
);
|
||||||
add_grid(
|
add_plate(
|
||||||
half_height,
|
half_height,
|
||||||
PlateFormat::W96,
|
PlateFormat::W96,
|
||||||
&self.main_state.transfers,
|
&self.main_state.transfers,
|
||||||
|
|
|
@ -2,4 +2,5 @@ mod app;
|
||||||
mod plate;
|
mod plate;
|
||||||
mod tree;
|
mod tree;
|
||||||
mod transfer_menu;
|
mod transfer_menu;
|
||||||
|
mod main_state;
|
||||||
pub use app::PlateToolEframe;
|
pub use app::PlateToolEframe;
|
||||||
|
|
|
@ -0,0 +1,123 @@
|
||||||
|
use plate_tool_lib::plate_instances;
|
||||||
|
use plate_tool_lib::plate::PlateFormat;
|
||||||
|
|
||||||
|
#[derive(Default, Debug, serde::Serialize, serde::Deserialize)]
|
||||||
|
pub struct MainState {
|
||||||
|
/// Stores all plates and transfers
|
||||||
|
///
|
||||||
|
/// It is not guaranteed that the current_* variables will refer
|
||||||
|
/// to UUIDs that exist in the lists, only that they did at one time.
|
||||||
|
/// This can happen if a plate or transfer is removed and set_* is not called.
|
||||||
|
pub source_plates: Vec<plate_tool_lib::plate_instances::PlateInstance>,
|
||||||
|
pub destination_plates: Vec<plate_tool_lib::plate_instances::PlateInstance>,
|
||||||
|
pub transfers: Vec<plate_tool_lib::transfer::Transfer>,
|
||||||
|
current_source: Option<plate_tool_lib::uuid::Uuid>,
|
||||||
|
current_destination: Option<plate_tool_lib::uuid::Uuid>,
|
||||||
|
current_transfer: Option<plate_tool_lib::uuid::Uuid>,
|
||||||
|
}
|
||||||
|
impl MainState {
|
||||||
|
pub fn get_current_source(&self) -> Option<plate_tool_lib::uuid::Uuid> {
|
||||||
|
self.current_source
|
||||||
|
}
|
||||||
|
pub fn get_current_destination(&self) -> Option<plate_tool_lib::uuid::Uuid> {
|
||||||
|
self.current_destination
|
||||||
|
}
|
||||||
|
pub fn get_current_transfer(&self) -> Option<plate_tool_lib::uuid::Uuid> {
|
||||||
|
self.current_transfer
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn set_current_source(&mut self, id: plate_tool_lib::uuid::Uuid) -> bool {
|
||||||
|
if self.source_plates.iter().map(|x| x.get_uuid()).find(|x| *x == id).is_some() {
|
||||||
|
self.current_source = Some(id);
|
||||||
|
true
|
||||||
|
} else {
|
||||||
|
false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
pub fn set_current_destination(&mut self, id: plate_tool_lib::uuid::Uuid) -> bool {
|
||||||
|
if self.destination_plates.iter().map(|x| x.get_uuid()).find(|x| *x == id).is_some() {
|
||||||
|
self.current_destination = Some(id);
|
||||||
|
true
|
||||||
|
} else {
|
||||||
|
false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
pub fn set_current_transfer(&mut self, id: plate_tool_lib::uuid::Uuid) -> bool {
|
||||||
|
if self.transfers.iter().map(|x| x.get_uuid()).find(|x| *x == id).is_some() {
|
||||||
|
self.current_transfer = Some(id);
|
||||||
|
true
|
||||||
|
} else {
|
||||||
|
false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
pub fn set_no_current_source(&mut self) {
|
||||||
|
self.current_source = None;
|
||||||
|
}
|
||||||
|
pub fn set_no_current_destination(&mut self) {
|
||||||
|
self.current_destination = None;
|
||||||
|
}
|
||||||
|
pub fn set_no_current_transfer(&mut self) {
|
||||||
|
self.current_transfer = None;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn construct_fake_mainstate() -> MainState {
|
||||||
|
let src_plate: plate_tool_lib::plate_instances::PlateInstance =
|
||||||
|
plate_instances::PlateInstance::new(
|
||||||
|
plate_tool_lib::plate::PlateType::Source,
|
||||||
|
PlateFormat::W96,
|
||||||
|
"src1".to_owned(),
|
||||||
|
);
|
||||||
|
let dest_plate: plate_tool_lib::plate_instances::PlateInstance =
|
||||||
|
plate_instances::PlateInstance::new(
|
||||||
|
plate_tool_lib::plate::PlateType::Destination,
|
||||||
|
PlateFormat::W96,
|
||||||
|
"dest1".to_owned(),
|
||||||
|
);
|
||||||
|
let well_a1 = plate_tool_lib::Well { row: 1, col: 1 };
|
||||||
|
let well_c3 = plate_tool_lib::Well { row: 3, col: 3 };
|
||||||
|
let well_a5 = plate_tool_lib::Well { row: 1, col: 5 };
|
||||||
|
|
||||||
|
let transfer1_region: plate_tool_lib::transfer_region::TransferRegion =
|
||||||
|
plate_tool_lib::transfer_region::TransferRegion {
|
||||||
|
source_plate: src_plate.plate,
|
||||||
|
source_region: plate_tool_lib::transfer_region::Region::Rect(well_a1, well_c3),
|
||||||
|
dest_plate: dest_plate.plate,
|
||||||
|
dest_region: plate_tool_lib::transfer_region::Region::Point(well_a1),
|
||||||
|
interleave_source: (1, 1),
|
||||||
|
interleave_dest: (1, 1),
|
||||||
|
};
|
||||||
|
let transfer1: plate_tool_lib::transfer::Transfer = plate_tool_lib::transfer::Transfer::new(
|
||||||
|
src_plate.clone(),
|
||||||
|
dest_plate.clone(),
|
||||||
|
transfer1_region,
|
||||||
|
"Shrimp".to_owned(),
|
||||||
|
);
|
||||||
|
|
||||||
|
let transfer2_region: plate_tool_lib::transfer_region::TransferRegion =
|
||||||
|
plate_tool_lib::transfer_region::TransferRegion {
|
||||||
|
source_plate: src_plate.plate,
|
||||||
|
source_region: plate_tool_lib::transfer_region::Region::Rect(well_a1, well_c3),
|
||||||
|
dest_plate: dest_plate.plate,
|
||||||
|
dest_region: plate_tool_lib::transfer_region::Region::Point(well_a5),
|
||||||
|
interleave_source: (1, 1),
|
||||||
|
interleave_dest: (2, 2),
|
||||||
|
};
|
||||||
|
let transfer2: plate_tool_lib::transfer::Transfer = plate_tool_lib::transfer::Transfer::new(
|
||||||
|
src_plate.clone(),
|
||||||
|
dest_plate.clone(),
|
||||||
|
transfer2_region,
|
||||||
|
"Shrimp".to_owned(),
|
||||||
|
);
|
||||||
|
|
||||||
|
|
||||||
|
MainState {
|
||||||
|
source_plates: vec![src_plate],
|
||||||
|
destination_plates: vec![dest_plate],
|
||||||
|
transfers: vec![transfer1, transfer2],
|
||||||
|
current_source: None,
|
||||||
|
current_destination: None,
|
||||||
|
current_transfer: None,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -20,7 +20,7 @@ static STROKE_SELECT: LazyLock<egui::Stroke> =
|
||||||
static STROKE_HOVER: LazyLock<egui::Stroke> =
|
static STROKE_HOVER: LazyLock<egui::Stroke> =
|
||||||
LazyLock::new(|| egui::Stroke::new(3.0, egui::Color32::from_gray(255)));
|
LazyLock::new(|| egui::Stroke::new(3.0, egui::Color32::from_gray(255)));
|
||||||
|
|
||||||
#[derive(Clone, Debug)]
|
#[derive(Clone, Debug, serde::Serialize, serde::Deserialize)]
|
||||||
pub struct PlateUiState {
|
pub struct PlateUiState {
|
||||||
pub drag_start_position: Option<egui::Pos2>,
|
pub drag_start_position: Option<egui::Pos2>,
|
||||||
}
|
}
|
||||||
|
@ -109,8 +109,8 @@ fn calculate_shading_for_wells(
|
||||||
|
|
||||||
for transfer in transfers {
|
for transfer in transfers {
|
||||||
let cache_result = match plate_type {
|
let cache_result = match plate_type {
|
||||||
plate_tool_lib::plate::PlateType::Source => cache.get_source(transfer),
|
plate_tool_lib::plate::PlateType::Source => cache.get_or_calculate_source(transfer),
|
||||||
plate_tool_lib::plate::PlateType::Destination => cache.get_destination(transfer),
|
plate_tool_lib::plate::PlateType::Destination => cache.get_or_calculate_destination(transfer),
|
||||||
};
|
};
|
||||||
if let Some(wells) = cache_result {
|
if let Some(wells) = cache_result {
|
||||||
for well in wells.iter().filter(|x| x.row <= rows && x.col <= columns) {
|
for well in wells.iter().filter(|x| x.row <= rows && x.col <= columns) {
|
||||||
|
@ -138,7 +138,7 @@ fn f64_to_color32(x: [f64; 3]) -> Color32 {
|
||||||
Color32::from_rgb(r, g, b)
|
Color32::from_rgb(r, g, b)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn add_grid_sub(
|
fn add_plate_sub(
|
||||||
size: egui::Vec2,
|
size: egui::Vec2,
|
||||||
rows: u8,
|
rows: u8,
|
||||||
columns: u8,
|
columns: u8,
|
||||||
|
@ -226,7 +226,9 @@ fn add_grid_sub(
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
let well_infos = {
|
let well_infos = {
|
||||||
|
// Get non-active transfer info
|
||||||
let mut well_infos = calculate_shading_for_wells(rows, columns, transfers, plate_type, ordered_ids, cache);
|
let mut well_infos = calculate_shading_for_wells(rows, columns, transfers, plate_type, ordered_ids, cache);
|
||||||
|
|
||||||
// Get wells in the current transfer to tack on to well_infos separately
|
// Get wells in the current transfer to tack on to well_infos separately
|
||||||
let current_transfer_wells: Option<Box<[(usize,usize)]>> = {
|
let current_transfer_wells: Option<Box<[(usize,usize)]>> = {
|
||||||
(match plate_type {
|
(match plate_type {
|
||||||
|
@ -351,7 +353,7 @@ fn add_grid_sub(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn add_grid(
|
pub fn add_plate(
|
||||||
size: egui::Vec2,
|
size: egui::Vec2,
|
||||||
pf: PlateFormat,
|
pf: PlateFormat,
|
||||||
transfers: &Vec<plate_tool_lib::transfer::Transfer>,
|
transfers: &Vec<plate_tool_lib::transfer::Transfer>,
|
||||||
|
@ -363,7 +365,7 @@ pub fn add_grid(
|
||||||
state: &mut PlateUiState,
|
state: &mut PlateUiState,
|
||||||
) {
|
) {
|
||||||
match pf {
|
match pf {
|
||||||
PlateFormat::W96 => add_grid_sub(
|
PlateFormat::W96 => add_plate_sub(
|
||||||
size,
|
size,
|
||||||
8,
|
8,
|
||||||
12,
|
12,
|
||||||
|
@ -375,7 +377,7 @@ pub fn add_grid(
|
||||||
ui,
|
ui,
|
||||||
state,
|
state,
|
||||||
),
|
),
|
||||||
PlateFormat::W384 => add_grid_sub(
|
PlateFormat::W384 => add_plate_sub(
|
||||||
size,
|
size,
|
||||||
16,
|
16,
|
||||||
24,
|
24,
|
||||||
|
@ -387,7 +389,7 @@ pub fn add_grid(
|
||||||
ui,
|
ui,
|
||||||
state,
|
state,
|
||||||
),
|
),
|
||||||
PlateFormat::W1536 => add_grid_sub(
|
PlateFormat::W1536 => add_plate_sub(
|
||||||
size,
|
size,
|
||||||
32,
|
32,
|
||||||
48,
|
48,
|
||||||
|
|
|
@ -1,9 +1,12 @@
|
||||||
use eframe::egui;
|
use eframe::egui;
|
||||||
use plate_tool_lib::transfer_region::{Region, TransferRegion};
|
use plate_tool_lib::transfer_region::{self, Region, TransferRegion};
|
||||||
use std::sync::{Arc, Mutex};
|
use std::sync::{Arc, Mutex};
|
||||||
use std::hash::{DefaultHasher, Hash, Hasher};
|
use std::hash::{DefaultHasher, Hash, Hasher};
|
||||||
|
|
||||||
|
use crate::main_state::MainState;
|
||||||
|
|
||||||
pub type CurrentTransferState = Arc<Mutex<CurrentTransferStateInterior>>;
|
pub type CurrentTransferState = Arc<Mutex<CurrentTransferStateInterior>>;
|
||||||
|
#[derive(Debug, serde::Serialize, serde::Deserialize)]
|
||||||
pub struct CurrentTransferStateInterior {
|
pub struct CurrentTransferStateInterior {
|
||||||
pub transfer_name: String,
|
pub transfer_name: String,
|
||||||
pub source_region: plate_tool_lib::transfer_region::Region,
|
pub source_region: plate_tool_lib::transfer_region::Region,
|
||||||
|
@ -15,8 +18,11 @@ pub struct CurrentTransferStateInterior {
|
||||||
pub destination_row_interleave: i8,
|
pub destination_row_interleave: i8,
|
||||||
pub destination_column_interleave: i8,
|
pub destination_column_interleave: i8,
|
||||||
pub volume: f32,
|
pub volume: f32,
|
||||||
|
#[serde(skip)]
|
||||||
transfer_hash: Option<u64>,
|
transfer_hash: Option<u64>,
|
||||||
|
#[serde(skip)]
|
||||||
source_wells: Option<Vec<plate_tool_lib::Well>>,
|
source_wells: Option<Vec<plate_tool_lib::Well>>,
|
||||||
|
#[serde(skip)]
|
||||||
destination_wells: Option<Vec<plate_tool_lib::Well>>,
|
destination_wells: Option<Vec<plate_tool_lib::Well>>,
|
||||||
}
|
}
|
||||||
impl Default for CurrentTransferStateInterior {
|
impl Default for CurrentTransferStateInterior {
|
||||||
|
@ -96,8 +102,40 @@ impl CurrentTransferStateInterior {
|
||||||
interleave_dest: (self.destination_row_interleave, self.destination_column_interleave),
|
interleave_dest: (self.destination_row_interleave, self.destination_column_interleave),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn try_new_from_main_state_transfer(ms: &MainState) -> Option<Self> {
|
||||||
|
let transfer_id = ms.get_current_transfer();
|
||||||
|
let transfer = ms.transfers.iter().find(|x| Some(x.get_uuid()) == transfer_id);
|
||||||
|
if let Some(transfer) = transfer {
|
||||||
|
let volume: f32 = match transfer.volume {
|
||||||
|
plate_tool_lib::transfer_volume::TransferVolume::Single(x) => x,
|
||||||
|
plate_tool_lib::transfer_volume::TransferVolume::WellMap(_) => {
|
||||||
|
log::debug!("COOL BUG: I genuinely don't know when this variant is used and honestly assume that it just never is constructed! Anyway, here's main state:\n{:?}", ms);
|
||||||
|
unreachable!("It better not!");
|
||||||
|
},
|
||||||
|
_ => unreachable!()
|
||||||
|
};
|
||||||
|
return Some(Self {
|
||||||
|
transfer_name: transfer.name.clone(),
|
||||||
|
source_region: transfer.transfer_region.source_region.clone(),
|
||||||
|
destination_region: transfer.transfer_region.dest_region.clone(),
|
||||||
|
source_plate: transfer.transfer_region.source_plate,
|
||||||
|
destination_plate: transfer.transfer_region.dest_plate,
|
||||||
|
source_row_interleave: transfer.transfer_region.interleave_source.0,
|
||||||
|
source_column_interleave: transfer.transfer_region.interleave_source.1,
|
||||||
|
destination_row_interleave: transfer.transfer_region.interleave_dest.0,
|
||||||
|
destination_column_interleave: transfer.transfer_region.interleave_dest.1,
|
||||||
|
volume,
|
||||||
|
source_wells: None,
|
||||||
|
destination_wells: None,
|
||||||
|
transfer_hash: None,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
None
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Debug)]
|
||||||
pub struct TransferMenuState {
|
pub struct TransferMenuState {
|
||||||
pub source_region_string: String,
|
pub source_region_string: String,
|
||||||
pub destination_region_string: String,
|
pub destination_region_string: String,
|
||||||
|
|
|
@ -0,0 +1,103 @@
|
||||||
|
use eframe::egui;
|
||||||
|
|
||||||
|
use crate::{main_state::MainState, transfer_menu::{CurrentTransferState, CurrentTransferStateInterior}};
|
||||||
|
|
||||||
|
use std::sync::LazyLock;
|
||||||
|
|
||||||
|
static SELECT_COLOR: LazyLock<egui::Color32> =
|
||||||
|
LazyLock::new(|| egui::Color32::from_hex("#aa0000").unwrap());
|
||||||
|
|
||||||
|
pub fn tree(ui: &mut egui::Ui, ms: &mut MainState, cts: &CurrentTransferState) {
|
||||||
|
// Add all source plates
|
||||||
|
ui.vertical(|ui| {
|
||||||
|
ui.heading("Source Plates");
|
||||||
|
let mut new_uuid: Option<plate_tool_lib::uuid::Uuid> = None;
|
||||||
|
for (name, uuid) in ms.source_plates.iter().map(|x| (&x.name, x.get_uuid())) {
|
||||||
|
let f = {
|
||||||
|
let mut f = egui::Frame::none();
|
||||||
|
if ms.get_current_source().is_some_and(|x| x == uuid) {
|
||||||
|
f = f.fill(*SELECT_COLOR);
|
||||||
|
}
|
||||||
|
f
|
||||||
|
};
|
||||||
|
f.show(ui, |ui| {
|
||||||
|
let r = ui.add(
|
||||||
|
egui::Label::new(name)
|
||||||
|
.sense(egui::Sense::click())
|
||||||
|
.selectable(false),
|
||||||
|
);
|
||||||
|
if r.clicked() {
|
||||||
|
new_uuid = Some(uuid);
|
||||||
|
log::info!("{:?}", uuid);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
if let Some(uuid) = new_uuid {
|
||||||
|
ms.set_current_source(uuid);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
// Add all destination plates
|
||||||
|
ui.vertical(|ui| {
|
||||||
|
ui.heading("Destination Plates");
|
||||||
|
let mut new_uuid: Option<plate_tool_lib::uuid::Uuid> = None;
|
||||||
|
for (name, uuid) in ms
|
||||||
|
.destination_plates
|
||||||
|
.iter()
|
||||||
|
.map(|x| (&x.name, x.get_uuid()))
|
||||||
|
{
|
||||||
|
let f = {
|
||||||
|
let mut f = egui::Frame::none();
|
||||||
|
if ms.get_current_destination().is_some_and(|x| x == uuid) {
|
||||||
|
f = f.fill(*SELECT_COLOR);
|
||||||
|
}
|
||||||
|
f
|
||||||
|
};
|
||||||
|
f.show(ui, |ui| {
|
||||||
|
let r = ui.add(
|
||||||
|
egui::Label::new(name)
|
||||||
|
.sense(egui::Sense::click())
|
||||||
|
.selectable(false),
|
||||||
|
);
|
||||||
|
if r.clicked() {
|
||||||
|
new_uuid = Some(uuid);
|
||||||
|
log::info!("{:?}", uuid);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
if let Some(uuid) = new_uuid {
|
||||||
|
ms.set_current_destination(uuid);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
// Add all transfers
|
||||||
|
ui.vertical(|ui| {
|
||||||
|
ui.heading("Transfers");
|
||||||
|
let mut new_uuid: Option<plate_tool_lib::uuid::Uuid> = None;
|
||||||
|
for (name, uuid) in ms.transfers.iter().map(|x| (&x.name, x.get_uuid())) {
|
||||||
|
let f = {
|
||||||
|
let mut f = egui::Frame::none();
|
||||||
|
if ms.get_current_transfer().is_some_and(|x| x == uuid) {
|
||||||
|
f = f.fill(*SELECT_COLOR);
|
||||||
|
}
|
||||||
|
f
|
||||||
|
};
|
||||||
|
f.show(ui, |ui| {
|
||||||
|
let r = ui.add(
|
||||||
|
egui::Label::new(name)
|
||||||
|
.sense(egui::Sense::click())
|
||||||
|
.selectable(false),
|
||||||
|
);
|
||||||
|
if r.clicked() {
|
||||||
|
new_uuid = Some(uuid);
|
||||||
|
log::info!("{:?}", uuid);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
if let Some(uuid) = new_uuid {
|
||||||
|
ms.set_current_transfer(uuid);
|
||||||
|
if let Some(new_cts) = CurrentTransferStateInterior::try_new_from_main_state_transfer(ms) {
|
||||||
|
*cts.lock().unwrap() = new_cts;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
|
@ -11,6 +11,11 @@ pub struct TransferRegionCache {
|
||||||
interior: Arc<Mutex<TransferRegionCacheInterior>>,
|
interior: Arc<Mutex<TransferRegionCacheInterior>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl Default for TransferRegionCache {
|
||||||
|
fn default() -> Self {
|
||||||
|
Self::new()
|
||||||
|
}
|
||||||
|
}
|
||||||
impl TransferRegionCache {
|
impl TransferRegionCache {
|
||||||
pub fn new() -> Self {
|
pub fn new() -> Self {
|
||||||
TransferRegionCache {
|
TransferRegionCache {
|
||||||
|
@ -46,10 +51,22 @@ impl TransferRegionCache {
|
||||||
pub fn get_source(&self, tr: &Transfer) -> Option<Arc<[Well]>> {
|
pub fn get_source(&self, tr: &Transfer) -> Option<Arc<[Well]>> {
|
||||||
self.get(tr, true)
|
self.get(tr, true)
|
||||||
}
|
}
|
||||||
|
pub fn get_or_calculate_source(&self, tr: &Transfer) -> Option<Arc<[Well]>> {
|
||||||
|
if !self.has(tr) {
|
||||||
|
self.add_overwrite(tr);
|
||||||
|
}
|
||||||
|
self.get_source(tr)
|
||||||
|
}
|
||||||
|
|
||||||
pub fn get_destination(&self, tr: &Transfer) -> Option<Arc<[Well]>> {
|
pub fn get_destination(&self, tr: &Transfer) -> Option<Arc<[Well]>> {
|
||||||
self.get(tr, false)
|
self.get(tr, false)
|
||||||
}
|
}
|
||||||
|
pub fn get_or_calculate_destination(&self, tr: &Transfer) -> Option<Arc<[Well]>> {
|
||||||
|
if !self.has(tr) {
|
||||||
|
self.add_overwrite(tr);
|
||||||
|
}
|
||||||
|
self.get_destination(tr)
|
||||||
|
}
|
||||||
|
|
||||||
fn get(&self, tr: &Transfer, is_source: bool) -> Option<Arc<[Well]>> {
|
fn get(&self, tr: &Transfer, is_source: bool) -> Option<Arc<[Well]>> {
|
||||||
if let Ok(interior) = self.interior.lock() {
|
if let Ok(interior) = self.interior.lock() {
|
||||||
|
@ -63,6 +80,13 @@ impl TransferRegionCache {
|
||||||
None
|
None
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
fn has(&self, tr: &Transfer) -> bool {
|
||||||
|
if let Ok(interior) = self.interior.lock() {
|
||||||
|
interior.cache.contains_key(&tr.get_uuid())
|
||||||
|
} else {
|
||||||
|
false
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Clone for TransferRegionCache {
|
impl Clone for TransferRegionCache {
|
||||||
|
|
Loading…
Reference in New Issue