Compare commits
No commits in common. "62f529184010a279b57784d9e2c71d131b665e3f" and "45f81d240920bd0c304d4e785e9234da928fc7c2" have entirely different histories.
62f5291840
...
45f81d2409
|
|
@ -1473,7 +1473,6 @@ version = "0.3.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "97563d71863fb2824b2e974e754a81d19c4a7ec47b09ced8a0e6656b6d54bd1f"
|
checksum = "97563d71863fb2824b2e974e754a81d19c4a7ec47b09ced8a0e6656b6d54bd1f"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"futures-channel",
|
|
||||||
"gloo-events 0.2.0",
|
"gloo-events 0.2.0",
|
||||||
"js-sys",
|
"js-sys",
|
||||||
"wasm-bindgen",
|
"wasm-bindgen",
|
||||||
|
|
@ -1621,8 +1620,6 @@ version = "0.3.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "bbb143cf96099802033e0d4f4963b19fd2e0b728bcf076cd9cf7f6634f092994"
|
checksum = "bbb143cf96099802033e0d4f4963b19fd2e0b728bcf076cd9cf7f6634f092994"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"futures-channel",
|
|
||||||
"futures-core",
|
|
||||||
"js-sys",
|
"js-sys",
|
||||||
"wasm-bindgen",
|
"wasm-bindgen",
|
||||||
]
|
]
|
||||||
|
|
@ -2375,7 +2372,7 @@ version = "0.7.3"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "af1844ef2428cc3e1cb900be36181049ef3d3193c63e43026cfe202983b27a56"
|
checksum = "af1844ef2428cc3e1cb900be36181049ef3d3193c63e43026cfe202983b27a56"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"proc-macro-crate 3.4.0",
|
"proc-macro-crate 1.3.1",
|
||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
"quote",
|
"quote",
|
||||||
"syn 2.0.87",
|
"syn 2.0.87",
|
||||||
|
|
@ -2797,16 +2794,10 @@ version = "0.1.0"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"eframe",
|
"eframe",
|
||||||
"env_logger",
|
"env_logger",
|
||||||
"gloo-file 0.3.0",
|
|
||||||
"gloo-timers 0.3.0",
|
|
||||||
"js-sys",
|
|
||||||
"log",
|
"log",
|
||||||
"plate-tool-lib",
|
"plate-tool-lib",
|
||||||
"poll-promise",
|
|
||||||
"rfd",
|
"rfd",
|
||||||
"serde",
|
"serde",
|
||||||
"serde_json",
|
|
||||||
"wasm-bindgen",
|
|
||||||
"wasm-bindgen-futures",
|
"wasm-bindgen-futures",
|
||||||
"web-sys",
|
"web-sys",
|
||||||
]
|
]
|
||||||
|
|
@ -2863,18 +2854,6 @@ dependencies = [
|
||||||
"miniz_oxide",
|
"miniz_oxide",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "poll-promise"
|
|
||||||
version = "0.3.0"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "5f6a58fecbf9da8965bcdb20ce4fd29788d1acee68ddbb64f0ba1b81bccdb7df"
|
|
||||||
dependencies = [
|
|
||||||
"document-features",
|
|
||||||
"static_assertions",
|
|
||||||
"wasm-bindgen",
|
|
||||||
"wasm-bindgen-futures",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "polling"
|
name = "polling"
|
||||||
version = "3.7.4"
|
version = "3.7.4"
|
||||||
|
|
|
||||||
|
|
@ -23,20 +23,7 @@ rfd = "0.15"
|
||||||
|
|
||||||
[target.'cfg(target_arch = "wasm32")'.dependencies]
|
[target.'cfg(target_arch = "wasm32")'.dependencies]
|
||||||
wasm-bindgen-futures = "0.4"
|
wasm-bindgen-futures = "0.4"
|
||||||
web-sys = { version = "0.3", features = [
|
web-sys = "0.3"
|
||||||
"Window",
|
|
||||||
"Document",
|
|
||||||
"HtmlInputElement",
|
|
||||||
"HtmlAnchorElement",
|
|
||||||
"FileList",
|
|
||||||
"Blob",
|
|
||||||
"Url"
|
|
||||||
] }
|
|
||||||
wasm-bindgen = "0.2"
|
|
||||||
js-sys = "0.3"
|
|
||||||
gloo-file = { version = "0.3", features = ["futures"] }
|
|
||||||
gloo-timers = { version = "0.3", features = ["futures"] }
|
|
||||||
poll-promise = { version = "0.3", features = ["web"] }
|
|
||||||
|
|
||||||
#[profile.release]
|
#[profile.release]
|
||||||
#opt-level = 2
|
#opt-level = 2
|
||||||
|
|
|
||||||
|
|
@ -16,10 +16,8 @@ use crate::transfer_menu::{transfer_menu, CurrentTransferState, TransferMenuStat
|
||||||
use crate::tree::tree;
|
use crate::tree::tree;
|
||||||
use crate::upper_menu;
|
use crate::upper_menu;
|
||||||
|
|
||||||
// Make sure all fields are either skipped by serde or impl default!
|
|
||||||
#[non_exhaustive]
|
#[non_exhaustive]
|
||||||
#[derive(Debug, serde::Serialize, serde::Deserialize)]
|
#[derive(Debug, serde::Serialize, serde::Deserialize)]
|
||||||
#[serde(default)]
|
|
||||||
pub struct MainWindowState {
|
pub struct MainWindowState {
|
||||||
pub show_side_panel: bool,
|
pub show_side_panel: bool,
|
||||||
pub plate_display_options: PlateDisplayOptions,
|
pub plate_display_options: PlateDisplayOptions,
|
||||||
|
|
|
||||||
|
|
@ -1,3 +1,4 @@
|
||||||
|
#[cfg(not(target_arch = "wasm32"))]
|
||||||
use crate::app;
|
use crate::app;
|
||||||
|
|
||||||
// Native case, use rfd
|
// Native case, use rfd
|
||||||
|
|
@ -48,7 +49,7 @@ pub fn upload_file(filetype: &str, extension: &str) -> app::FileUploadPromise {
|
||||||
// Web case, use web_sys
|
// Web case, use web_sys
|
||||||
// Not tested yet!!
|
// Not tested yet!!
|
||||||
#[cfg(target_arch = "wasm32")]
|
#[cfg(target_arch = "wasm32")]
|
||||||
pub fn save_file(data: &[u8], default_filename: Option<&str>) {
|
pub fn save_file(default_filename: Option<&str>, data: &[u8]) {
|
||||||
use wasm_bindgen::JsCast;
|
use wasm_bindgen::JsCast;
|
||||||
use web_sys::{Blob, HtmlAnchorElement, Url};
|
use web_sys::{Blob, HtmlAnchorElement, Url};
|
||||||
|
|
||||||
|
|
@ -70,43 +71,3 @@ pub fn save_file(data: &[u8], default_filename: Option<&str>) {
|
||||||
|
|
||||||
Url::revoke_object_url(&url).unwrap();
|
Url::revoke_object_url(&url).unwrap();
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(target_arch = "wasm32")]
|
|
||||||
pub fn upload_file(filetype: &str, extension: &str) -> app::FileUploadPromise {
|
|
||||||
use poll_promise;
|
|
||||||
use wasm_bindgen::JsCast;
|
|
||||||
use web_sys::{window, HtmlInputElement};
|
|
||||||
use gloo_file::futures::read_as_bytes;
|
|
||||||
|
|
||||||
let extension = extension.to_owned();
|
|
||||||
|
|
||||||
app::FileUploadPromise(poll_promise::Promise::spawn_local(async move {
|
|
||||||
let document = window()?.document()?;
|
|
||||||
|
|
||||||
let input: HtmlInputElement = document
|
|
||||||
.create_element("input")
|
|
||||||
.ok()?
|
|
||||||
.dyn_into()
|
|
||||||
.ok()?;
|
|
||||||
|
|
||||||
input.set_type("file");
|
|
||||||
input.set_accept(&format!(".{}", extension));
|
|
||||||
input.click();
|
|
||||||
|
|
||||||
// Wait for file to be selected
|
|
||||||
let file_list = loop {
|
|
||||||
if let Some(files) = input.files() {
|
|
||||||
if files.length() > 0 {
|
|
||||||
break files;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
gloo_timers::future::TimeoutFuture::new(100).await;
|
|
||||||
};
|
|
||||||
|
|
||||||
let file = file_list.get(0)?;
|
|
||||||
let data = read_as_bytes(&file.into()).await.ok()?;
|
|
||||||
|
|
||||||
log::info!("Read {} bytes", data.len());
|
|
||||||
Some(data)
|
|
||||||
}))
|
|
||||||
}
|
|
||||||
|
|
|
||||||
|
|
@ -5,7 +5,6 @@ use plate_tool_lib::transfer_region::Region;
|
||||||
use plate_tool_lib::uuid::Uuid;
|
use plate_tool_lib::uuid::Uuid;
|
||||||
use plate_tool_lib::Well;
|
use plate_tool_lib::Well;
|
||||||
|
|
||||||
use crate::main_state;
|
|
||||||
use crate::transfer_menu::CurrentTransferState;
|
use crate::transfer_menu::CurrentTransferState;
|
||||||
|
|
||||||
use std::sync::LazyLock;
|
use std::sync::LazyLock;
|
||||||
|
|
@ -55,10 +54,8 @@ impl WellInfo {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, Copy, Debug, serde::Serialize, serde::Deserialize)]
|
#[derive(Clone, Copy, Debug, serde::Serialize, serde::Deserialize)]
|
||||||
#[serde(default)]
|
|
||||||
pub struct PlateDisplayOptions {
|
pub struct PlateDisplayOptions {
|
||||||
pub show_transfer_hashes: bool,
|
pub show_transfer_hashes: bool,
|
||||||
pub show_well_volumes: bool,
|
|
||||||
pub show_volume_heatmap: bool,
|
pub show_volume_heatmap: bool,
|
||||||
pub show_coordinates: bool,
|
pub show_coordinates: bool,
|
||||||
}
|
}
|
||||||
|
|
@ -66,7 +63,6 @@ impl Default for PlateDisplayOptions {
|
||||||
fn default() -> Self {
|
fn default() -> Self {
|
||||||
Self {
|
Self {
|
||||||
show_transfer_hashes: true,
|
show_transfer_hashes: true,
|
||||||
show_well_volumes: true,
|
|
||||||
show_volume_heatmap: false,
|
show_volume_heatmap: false,
|
||||||
show_coordinates: true,
|
show_coordinates: true,
|
||||||
}
|
}
|
||||||
|
|
@ -180,38 +176,28 @@ fn calculate_shading_for_wells(
|
||||||
cache.get_or_calculate_destination(transfer)
|
cache.get_or_calculate_destination(transfer)
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
let volume = if let plate_tool_lib::transfer_volume::TransferVolume::Single(x) =
|
||||||
|
transfer.volume
|
||||||
|
{
|
||||||
|
x
|
||||||
|
} else {
|
||||||
|
0.0
|
||||||
|
};
|
||||||
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) {
|
||||||
let volume = match &transfer.volume {
|
if let Some(Some(mut x)) = well_infos.get_mut(
|
||||||
plate_tool_lib::transfer_volume::TransferVolume::Single(x) => *x,
|
|
||||||
plate_tool_lib::transfer_volume::TransferVolume::WellMap(wm) => {
|
|
||||||
match plate_type {
|
|
||||||
plate_tool_lib::plate::PlateType::Source => wm.source_only[well],
|
|
||||||
plate_tool_lib::plate::PlateType::Destination => {
|
|
||||||
wm.destination_only[well]
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
_ => 0.0,
|
|
||||||
};
|
|
||||||
|
|
||||||
if let Some(well_info_slot) = well_infos.get_mut(
|
|
||||||
(well.row - 1) as usize * columns as usize + (well.col - 1) as usize,
|
(well.row - 1) as usize * columns as usize + (well.col - 1) as usize,
|
||||||
) {
|
) {
|
||||||
if let Some(ref mut x) = well_info_slot {
|
|
||||||
// Well info already existed.
|
|
||||||
x.volume += volume;
|
x.volume += volume;
|
||||||
|
|
||||||
x.color = if display_options.show_volume_heatmap {
|
x.color = if display_options.show_volume_heatmap {
|
||||||
PALETTE.get_linear(x.volume.into(), max_volume.into())
|
PALETTE.get_linear(volume.into(), max_volume.into())
|
||||||
} else {
|
} else {
|
||||||
PALETTE.get_ordered(transfer.id, ordered_ids)
|
PALETTE.get_ordered(transfer.id, ordered_ids)
|
||||||
};
|
};
|
||||||
} else {
|
} else {
|
||||||
// Well info does not already exist, we need to make it.
|
|
||||||
if let Some(mut wi) = well_infos.get_mut(
|
if let Some(mut wi) = well_infos.get_mut(
|
||||||
(well.row - 1) as usize * columns as usize
|
(well.row - 1) as usize * columns as usize + (well.col - 1) as usize,
|
||||||
+ (well.col - 1) as usize,
|
|
||||||
) {
|
) {
|
||||||
*wi = Some(WellInfo::new(
|
*wi = Some(WellInfo::new(
|
||||||
volume,
|
volume,
|
||||||
|
|
@ -227,7 +213,6 @@ fn calculate_shading_for_wells(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
well_infos
|
well_infos
|
||||||
}
|
}
|
||||||
|
|
@ -340,15 +325,8 @@ fn add_plate_sub(
|
||||||
};
|
};
|
||||||
let well_infos = {
|
let well_infos = {
|
||||||
// Get non-active transfer info
|
// Get non-active transfer info
|
||||||
let mut well_infos = calculate_shading_for_wells(
|
let mut well_infos =
|
||||||
rows,
|
calculate_shading_for_wells(rows, columns, transfers, plate_type, ordered_ids, cache, display_options);
|
||||||
columns,
|
|
||||||
transfers,
|
|
||||||
plate_type,
|
|
||||||
ordered_ids,
|
|
||||||
cache,
|
|
||||||
display_options,
|
|
||||||
);
|
|
||||||
|
|
||||||
// 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)]>> = {
|
||||||
|
|
@ -371,13 +349,17 @@ fn add_plate_sub(
|
||||||
if let Some(mut well_info) =
|
if let Some(mut well_info) =
|
||||||
well_infos.get_mut((w.0 - 1) * columns as usize + (w.1 - 1))
|
well_infos.get_mut((w.0 - 1) * columns as usize + (w.1 - 1))
|
||||||
{
|
{
|
||||||
let volume = well_info.map(|x| x.volume).unwrap_or(0.0);
|
let volume = well_info.map(|x| x.volume).unwrap_or(0.0)
|
||||||
|
+ current_transfer_state
|
||||||
|
.and_then(|x| x.lock().ok())
|
||||||
|
.map(|x| x.volume)
|
||||||
|
.unwrap_or(0.0);
|
||||||
let color = well_info.map(|x| x.color).unwrap_or([255.0, 255.0, 255.0]);
|
let color = well_info.map(|x| x.color).unwrap_or([255.0, 255.0, 255.0]);
|
||||||
let fill = well_info.map(|x| x.color).is_some();
|
let fill = well_info.map(|x| x.color).is_some();
|
||||||
|
|
||||||
*well_info = Some(WellInfo {
|
*well_info = Some(WellInfo {
|
||||||
color,
|
color,
|
||||||
volume: volume,
|
volume: 1.0,
|
||||||
fill,
|
fill,
|
||||||
highlight: true,
|
highlight: true,
|
||||||
})
|
})
|
||||||
|
|
@ -424,22 +406,6 @@ fn add_plate_sub(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Draw volume text
|
|
||||||
|
|
||||||
if display_options.show_well_volumes {
|
|
||||||
if let Some(well_info) =
|
|
||||||
well_infos[(c_row - 1) as usize * columns as usize + (c_column - 1) as usize]
|
|
||||||
{
|
|
||||||
painter.text(
|
|
||||||
center,
|
|
||||||
egui::Align2::CENTER_CENTER,
|
|
||||||
format!("{:.1}", well_info.volume),
|
|
||||||
egui::FontId::proportional(radius * 0.6),
|
|
||||||
egui::Color32::BLACK,
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
//
|
//
|
||||||
// Draw stroke on top
|
// Draw stroke on top
|
||||||
//
|
//
|
||||||
|
|
|
||||||
|
|
@ -116,7 +116,9 @@ impl CurrentTransferStateInterior {
|
||||||
if let Some(transfer) = transfer {
|
if let Some(transfer) = transfer {
|
||||||
let volume: f32 = match transfer.volume {
|
let volume: f32 = match transfer.volume {
|
||||||
plate_tool_lib::transfer_volume::TransferVolume::Single(x) => x,
|
plate_tool_lib::transfer_volume::TransferVolume::Single(x) => x,
|
||||||
plate_tool_lib::transfer_volume::TransferVolume::WellMap(_) => f32::NAN,
|
plate_tool_lib::transfer_volume::TransferVolume::WellMap(_) => {
|
||||||
|
f32::NAN
|
||||||
|
}
|
||||||
_ => unreachable!(),
|
_ => unreachable!(),
|
||||||
};
|
};
|
||||||
return Some(Self {
|
return Some(Self {
|
||||||
|
|
@ -319,13 +321,6 @@ pub fn transfer_menu(
|
||||||
{
|
{
|
||||||
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();
|
||||||
if matches!(
|
|
||||||
transfer.volume,
|
|
||||||
plate_tool_lib::transfer_volume::TransferVolume::Single(_)
|
|
||||||
) {
|
|
||||||
transfer.volume =
|
|
||||||
plate_tool_lib::transfer_volume::TransferVolume::Single(state.volume);
|
|
||||||
}
|
|
||||||
main_state.transfer_region_cache.invalidate(&transfer);
|
main_state.transfer_region_cache.invalidate(&transfer);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
|
@ -351,21 +346,6 @@ pub fn transfer_menu(
|
||||||
set_plates(main_state, &mut state);
|
set_plates(main_state, &mut state);
|
||||||
main_state.set_no_current_transfer();
|
main_state.set_no_current_transfer();
|
||||||
}
|
}
|
||||||
if ui.button("Delete").clicked() {
|
|
||||||
if let Some(transfer_uuid) = main_state.get_current_transfer_uuid() {
|
|
||||||
if let Some(index) = main_state
|
|
||||||
.transfers
|
|
||||||
.iter()
|
|
||||||
.position(|x| x.id == transfer_uuid)
|
|
||||||
{
|
|
||||||
let removed_transfer = main_state.transfers.remove(index);
|
|
||||||
main_state.transfer_region_cache.invalidate(&removed_transfer);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
*state = CurrentTransferStateInterior::default();
|
|
||||||
set_plates(main_state, &mut state);
|
|
||||||
main_state.set_no_current_transfer();
|
|
||||||
}
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -127,10 +127,7 @@ fn render_export_menu(
|
||||||
};
|
};
|
||||||
if let Ok(data) = data {
|
if let Ok(data) = data {
|
||||||
let bytes: &[u8] = data.as_bytes();
|
let bytes: &[u8] = data.as_bytes();
|
||||||
log::info!(
|
log::info!("There are {} bytes to be written to chosen file", bytes.len());
|
||||||
"There are {} bytes to be written to chosen file",
|
|
||||||
bytes.len()
|
|
||||||
);
|
|
||||||
save_file(bytes, Some("transfers.csv"));
|
save_file(bytes, Some("transfers.csv"));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -161,7 +158,7 @@ fn render_import_menu(
|
||||||
Ok(new_main_state) => {
|
Ok(new_main_state) => {
|
||||||
log::info!("Loaded new main state from file.");
|
log::info!("Loaded new main state from file.");
|
||||||
*main_state = new_main_state
|
*main_state = new_main_state
|
||||||
}
|
},
|
||||||
Err(e) => log::error!("Failed loading imported state JSON: {}", e),
|
Err(e) => log::error!("Failed loading imported state JSON: {}", e),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -179,9 +176,7 @@ fn render_import_menu(
|
||||||
if let Ok(data) = String::from_utf8(data.to_vec()) {
|
if let Ok(data) = String::from_utf8(data.to_vec()) {
|
||||||
let auto_output = plate_tool_lib::csv::read_csv_auto(&data);
|
let auto_output = plate_tool_lib::csv::read_csv_auto(&data);
|
||||||
main_state.source_plates.extend(auto_output.sources);
|
main_state.source_plates.extend(auto_output.sources);
|
||||||
main_state
|
main_state.destination_plates.extend(auto_output.destinations);
|
||||||
.destination_plates
|
|
||||||
.extend(auto_output.destinations);
|
|
||||||
main_state.transfers.extend(auto_output.transfers);
|
main_state.transfers.extend(auto_output.transfers);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -202,10 +197,6 @@ fn render_options_menu(
|
||||||
&mut main_window_state.plate_display_options.show_transfer_hashes,
|
&mut main_window_state.plate_display_options.show_transfer_hashes,
|
||||||
"Toggle transfer hashes",
|
"Toggle transfer hashes",
|
||||||
);
|
);
|
||||||
ui.toggle_value(
|
|
||||||
&mut main_window_state.plate_display_options.show_well_volumes,
|
|
||||||
"Show volumes in wells",
|
|
||||||
);
|
|
||||||
ui.toggle_value(
|
ui.toggle_value(
|
||||||
&mut main_window_state.plate_display_options.show_volume_heatmap,
|
&mut main_window_state.plate_display_options.show_volume_heatmap,
|
||||||
"Toggle volume heatmap",
|
"Toggle volume heatmap",
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue