diff --git a/Cargo.lock b/Cargo.lock index 755f3d2..b21e9cb 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -29,8 +29,8 @@ version = "0.1.68" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b9ccdd8f2a161be9bd5c023df56f1b2a0bd1d83872ae53b71a84a12c9bf6e842" dependencies = [ - "proc-macro2", - "quote", + "proc-macro2 1.0.58", + "quote 1.0.27", "syn 2.0.16", ] @@ -61,6 +61,12 @@ version = "3.12.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3c6ed94e98ecff0c12dd1b04c15ec0d7d9458ca8fe806cea6f12954efe74c63b" +[[package]] +name = "cfg-if" +version = "0.1.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4785bdd1c96b2a846b2bd7cc02e86b6b3dbf14e7e53446c4f54c92a361040822" + [[package]] name = "cfg-if" version = "1.0.0" @@ -73,7 +79,7 @@ version = "0.1.7" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a06aeb73f470f66dcdbf7223caeebb85984942f22f1adb2a088cf9668146bbbc" dependencies = [ - "cfg-if", + "cfg-if 1.0.0", "wasm-bindgen", ] @@ -95,8 +101,8 @@ checksum = "859d65a907b6852c9361e3185c862aae7fafd2887876799fa55f5f99dc40d610" dependencies = [ "fnv", "ident_case", - "proc-macro2", - "quote", + "proc-macro2 1.0.58", + "quote 1.0.27", "strsim", "syn 1.0.109", ] @@ -108,7 +114,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9c972679f83bdf9c42bd905396b6c3588a843a17f0f16dfcfa3e2c5d57441835" dependencies = [ "darling_core", - "quote", + "quote 1.0.27", "syn 1.0.109", ] @@ -127,6 +133,12 @@ dependencies = [ "percent-encoding", ] +[[package]] +name = "futures" +version = "0.1.31" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3a471a38ef8ed83cd6e40aa59c1ffe17db6855c18e3604d9c4ed8c08ebc28678" + [[package]] name = "futures" version = "0.3.28" @@ -169,8 +181,8 @@ version = "0.3.28" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "89ca545a94061b6365f2c7355b4b32bd20df3ff95f02da9329b34ccc3bd6ee72" dependencies = [ - "proc-macro2", - "quote", + "proc-macro2 1.0.58", + "quote 1.0.27", "syn 2.0.16", ] @@ -210,7 +222,7 @@ version = "0.2.9" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c85e1d9ab2eadba7e5040d4e09cbd6d072b76a557ad64e797c2cb9d4da21d7e4" dependencies = [ - "cfg-if", + "cfg-if 1.0.0", "js-sys", "libc", "wasi", @@ -313,7 +325,7 @@ dependencies = [ "serde_json", "thiserror", "wasm-bindgen", - "wasm-bindgen-futures", + "wasm-bindgen-futures 0.4.36", "web-sys", ] @@ -378,7 +390,7 @@ dependencies = [ "js-sys", "serde", "wasm-bindgen", - "wasm-bindgen-futures", + "wasm-bindgen-futures 0.4.36", "web-sys", ] @@ -455,7 +467,7 @@ version = "0.4.17" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "abb12e687cfb44aa40f41fc3978ef76448f9b6038cad6aef4259d3c095a2382e" dependencies = [ - "cfg-if", + "cfg-if 1.0.0", ] [[package]] @@ -501,8 +513,8 @@ version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "39407670928234ebc5e6e580247dd567ad73a3578460c5990f9503df207e8f07" dependencies = [ - "proc-macro2", - "quote", + "proc-macro2 1.0.58", + "quote 1.0.27", "syn 2.0.16", ] @@ -524,7 +536,7 @@ version = "0.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a829027bd95e54cfe13e3e258a1ae7b645960553fb82b75ff852c29688ee595b" dependencies = [ - "futures", + "futures 0.3.28", "rustversion", "thiserror", ] @@ -539,6 +551,7 @@ dependencies = [ "serde", "uuid", "wasm-bindgen", + "wasm-bindgen-test", "wasm-logger", "web-sys", "yew", @@ -557,7 +570,7 @@ version = "0.1.25" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6c8646e95016a7a6c4adea95bafa8a16baab64b583356217f2c85db4a39d9a86" dependencies = [ - "proc-macro2", + "proc-macro2 1.0.58", "syn 1.0.109", ] @@ -568,8 +581,8 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "da25490ff9892aab3fcf7c36f08cfb902dd3e71ca0f9f9517bea02a73a5ce38c" dependencies = [ "proc-macro-error-attr", - "proc-macro2", - "quote", + "proc-macro2 1.0.58", + "quote 1.0.27", "syn 1.0.109", "version_check", ] @@ -580,11 +593,20 @@ version = "1.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a1be40180e52ecc98ad80b184934baf3d0d29f979574e439af5a55274b35f869" dependencies = [ - "proc-macro2", - "quote", + "proc-macro2 1.0.58", + "quote 1.0.27", "version_check", ] +[[package]] +name = "proc-macro2" +version = "0.4.30" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cf3d2011ab5c909338f7887f4fc896d35932e29146c12c8d01da6b22a80ba759" +dependencies = [ + "unicode-xid", +] + [[package]] name = "proc-macro2" version = "1.0.58" @@ -600,7 +622,7 @@ version = "0.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "03b55e106e5791fa5a13abd13c85d6127312e8e09098059ca2bc9b03ca4cf488" dependencies = [ - "futures", + "futures 0.3.28", "gloo", "num_cpus", "once_cell", @@ -608,7 +630,16 @@ dependencies = [ "pinned", "tokio", "tokio-stream", - "wasm-bindgen-futures", + "wasm-bindgen-futures 0.4.36", +] + +[[package]] +name = "quote" +version = "0.6.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6ce23b6b870e8f94f81fb0a363d65d86675884b34a09043c81e5562f11c1f8e1" +dependencies = [ + "proc-macro2 0.4.30", ] [[package]] @@ -617,7 +648,7 @@ version = "1.0.27" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8f4f29d145265ec1c483c7c654450edde0bfe043d3938d6972630663356d9500" dependencies = [ - "proc-macro2", + "proc-macro2 1.0.58", ] [[package]] @@ -679,6 +710,12 @@ version = "1.0.13" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f91339c0467de62360649f8d3e185ca8de4224ff281f66000de5eb2a77a79041" +[[package]] +name = "scoped-tls" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e1cf6437eb19a8f4a6cc0f7dca544973b0b78843adbfeb3683d1a94a0024a294" + [[package]] name = "serde" version = "1.0.163" @@ -705,8 +742,8 @@ version = "1.0.163" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8c805777e3930c8883389c602315a24224bcc738b63905ef87cd1420353ea93e" dependencies = [ - "proc-macro2", - "quote", + "proc-macro2 1.0.58", + "quote 1.0.27", "syn 2.0.16", ] @@ -754,8 +791,8 @@ version = "1.0.109" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "72b64191b275b66ffe2469e8af2c1cfe3bafa67b529ead792a6d0160888b4237" dependencies = [ - "proc-macro2", - "quote", + "proc-macro2 1.0.58", + "quote 1.0.27", "unicode-ident", ] @@ -765,8 +802,8 @@ version = "2.0.16" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a6f671d4b5ffdb8eadec19c0ae67fe2639df8684bd7bc4b83d986b8db549cf01" dependencies = [ - "proc-macro2", - "quote", + "proc-macro2 1.0.58", + "quote 1.0.27", "unicode-ident", ] @@ -785,8 +822,8 @@ version = "1.0.40" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f9456a42c5b0d803c8cd86e73dd7cc9edd429499f37a3550d286d5e86720569f" dependencies = [ - "proc-macro2", - "quote", + "proc-macro2 1.0.58", + "quote 1.0.27", "syn 2.0.16", ] @@ -818,7 +855,7 @@ version = "0.1.37" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8ce8c33a8d48bd45d624a6e523445fd21ec13d3653cd51f681abf67418f54eb8" dependencies = [ - "cfg-if", + "cfg-if 1.0.0", "pin-project-lite", "tracing-attributes", "tracing-core", @@ -830,8 +867,8 @@ version = "0.1.24" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0f57e3ca2a01450b1a921183a9c9cbfda207fd822cef4ccb00a65402cbba7a74" dependencies = [ - "proc-macro2", - "quote", + "proc-macro2 1.0.58", + "quote 1.0.27", "syn 2.0.16", ] @@ -850,6 +887,12 @@ version = "1.0.8" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e5464a87b239f13a63a501f2701565754bae92d243d4bb7eb12f6d57d2269bf4" +[[package]] +name = "unicode-xid" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fc72304796d0818e357ead4e000d19c9c174ab23dc11093ac919054d20a6a7fc" + [[package]] name = "uuid" version = "1.3.3" @@ -869,8 +912,8 @@ version = "1.3.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3f67b459f42af2e6e1ee213cb9da4dbd022d3320788c3fb3e1b893093f1e45da" dependencies = [ - "proc-macro2", - "quote", + "proc-macro2 1.0.58", + "quote 1.0.27", "syn 2.0.16", ] @@ -892,7 +935,7 @@ version = "0.2.86" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5bba0e8cb82ba49ff4e229459ff22a191bbe9a1cb3a341610c9c33efc27ddf73" dependencies = [ - "cfg-if", + "cfg-if 1.0.0", "wasm-bindgen-macro", ] @@ -905,19 +948,32 @@ dependencies = [ "bumpalo", "log", "once_cell", - "proc-macro2", - "quote", + "proc-macro2 1.0.58", + "quote 1.0.27", "syn 2.0.16", "wasm-bindgen-shared", ] +[[package]] +name = "wasm-bindgen-futures" +version = "0.3.27" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "83420b37346c311b9ed822af41ec2e82839bfe99867ec6c54e2da43b7538771c" +dependencies = [ + "cfg-if 0.1.10", + "futures 0.1.31", + "js-sys", + "wasm-bindgen", + "web-sys", +] + [[package]] name = "wasm-bindgen-futures" version = "0.4.36" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2d1985d03709c53167ce907ff394f5316aa22cb4e12761295c5dc57dacb6297e" dependencies = [ - "cfg-if", + "cfg-if 1.0.0", "js-sys", "wasm-bindgen", "web-sys", @@ -929,7 +985,7 @@ version = "0.2.86" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "14d6b024f1a526bb0234f52840389927257beb670610081360e5a03c5df9c258" dependencies = [ - "quote", + "quote 1.0.27", "wasm-bindgen-macro-support", ] @@ -939,8 +995,8 @@ version = "0.2.86" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e128beba882dd1eb6200e1dc92ae6c5dbaa4311aa7bb211ca035779e5efc39f8" dependencies = [ - "proc-macro2", - "quote", + "proc-macro2 1.0.58", + "quote 1.0.27", "syn 2.0.16", "wasm-bindgen-backend", "wasm-bindgen-shared", @@ -952,6 +1008,31 @@ version = "0.2.86" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ed9d5b4305409d1fc9482fee2d7f9bcbf24b3972bf59817ef757e23982242a93" +[[package]] +name = "wasm-bindgen-test" +version = "0.2.50" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a2d9693b63a742d481c7f80587e057920e568317b2806988c59cd71618bc26c1" +dependencies = [ + "console_error_panic_hook", + "futures 0.1.31", + "js-sys", + "scoped-tls", + "wasm-bindgen", + "wasm-bindgen-futures 0.3.27", + "wasm-bindgen-test-macro", +] + +[[package]] +name = "wasm-bindgen-test-macro" +version = "0.2.50" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0789dac148a8840bbcf9efe13905463b733fa96543bfbf263790535c11af7ba5" +dependencies = [ + "proc-macro2 0.4.30", + "quote 0.6.13", +] + [[package]] name = "wasm-logger" version = "0.2.0" @@ -1046,7 +1127,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5dbecfe44343b70cc2932c3eb445425969ae21754a8ab3a0966981c1cf7af1cc" dependencies = [ "console_error_panic_hook", - "futures", + "futures 0.3.28", "gloo", "implicit-clone", "indexmap", @@ -1059,7 +1140,7 @@ dependencies = [ "tokio", "tracing", "wasm-bindgen", - "wasm-bindgen-futures", + "wasm-bindgen-futures 0.4.36", "web-sys", "yew-macro", ] @@ -1074,8 +1155,8 @@ dependencies = [ "once_cell", "prettyplease", "proc-macro-error", - "proc-macro2", - "quote", + "proc-macro2 1.0.58", + "quote 1.0.27", "syn 1.0.109", ] @@ -1106,7 +1187,7 @@ checksum = "25bcd923aceaa85cb4affad8657cc36e3d6b6932740e711574182f7817492739" dependencies = [ "darling", "proc-macro-error", - "proc-macro2", - "quote", + "proc-macro2 1.0.58", + "quote 1.0.27", "syn 1.0.109", ] diff --git a/Cargo.toml b/Cargo.toml index 5c40b82..ace9a08 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -16,3 +16,6 @@ regex = "1" lazy_static = "1.4" uuid = { version = "1.3", features = ["v4", "fast-rng", "macro-diagnostics", "js", "serde"] } serde = { version = "1.0", features = ["derive"] } + +[dev-dependencies] +wasm-bindgen-test = "0.2" diff --git a/assets/css/plate.css b/assets/css/plate.css index 1861971..6d52374 100644 --- a/assets/css/plate.css +++ b/assets/css/plate.css @@ -16,10 +16,25 @@ div.plate_cell_inner { td.plate_cell:hover div.plate_cell_inner { background: black !important; } +td.plate_cell.in_transfer div.plate_cell_inner::after { + content: ""; + width: 100%; + height: 100%; + display: block; + border-radius: 50%; + background-image: repeating-linear-gradient( + 45deg, + rgba(0,0,0,0.8), + rgba(0,0,0,0.8) 2px, + transparent 2px, + transparent 4px + ); +} div.source_plate td.current_select div.plate_cell_inner { - background: lightblue !important; + background-image: linear-gradient(lightblue, lightblue); } div.dest_plate td.current_select div.plate_cell_inner { - background: lightcoral !important; + background: lightcoral; } + diff --git a/src/components/main_window.rs b/src/components/main_window.rs index b4e2d30..58512e6 100644 --- a/src/components/main_window.rs +++ b/src/components/main_window.rs @@ -2,7 +2,7 @@ use yew::prelude::*; use yewdux::prelude::*; -use super::states::{MainState, NewTransferState}; +use super::states::{MainState, NewTransferState, CurrentTransfer}; use super::plates::plate_container::PlateContainer; use super::tree::Tree; use super::transfer_menu::TransferMenu; @@ -14,13 +14,24 @@ use crate::data::plate_instances::PlateInstance; pub fn MainWindow() -> Html { let (main_state, main_dispatch) = use_store::(); let (selection_state, selection_dispatch) = use_store::(); + let (ct_state, ct_dispatch) = use_store::(); let source_plate_instance: Option = main_state.source_plates.iter() .find(|spi| {spi.get_uuid() == selection_state.source_id}) .cloned(); + if let Some(spi) = source_plate_instance.clone() { + ct_dispatch.reduce_mut(|state| { + state.transfer.source_plate = spi.plate; + }); + } let destination_plate_instance: Option = main_state.destination_plates.iter() .find(|dpi| {dpi.get_uuid() == selection_state.destination_id}) .cloned(); + if let Some(dpi) = destination_plate_instance.clone() { + ct_dispatch.reduce_mut(|state| { + state.transfer.dest_plate = dpi.plate; + }); + } let new_plate_dialog_is_open = use_state_eq(|| false); let new_plate_dialog_callback = { diff --git a/src/components/plates/destination_plate.rs b/src/components/plates/destination_plate.rs index b1236eb..5a4dcbe 100644 --- a/src/components/plates/destination_plate.rs +++ b/src/components/plates/destination_plate.rs @@ -4,38 +4,34 @@ use yewdux::prelude::*; use std::rc::Rc; use crate::data::plate_instances::PlateInstance; +use crate::data::transfer_region::{TransferRegion, Region}; +use crate::components::states::{NewTransferState, CurrentTransfer}; -use super::super::states::NewTransferState; use super::super::transfer_menu::RegionDisplay; #[derive(Properties, PartialEq)] pub struct DestinationPlateProps { - pub plate: PlateInstance, + pub source_plate: PlateInstance, + pub destination_plate: PlateInstance, } #[function_component] pub fn DestinationPlate(props: &DestinationPlateProps) -> Html { + let (state, dispatch) = use_store::(); + let (ct_state, ct_dispatch) = use_store::(); let m_start_handle: UseStateHandle> = use_state_eq(|| None); let m_end_handle: UseStateHandle> = use_state_eq(|| None); let m_stat_handle: UseStateHandle = use_state_eq(|| false); let m_start = m_start_handle.clone(); let m_end = m_end_handle.clone(); - let menu_sync_callback = { - let m_start_handle = m_start_handle.clone(); - let m_end_handle = m_end_handle.clone(); - let m_stat_handle = m_stat_handle.clone(); - - move |nts: Rc| { - if !(*m_stat_handle) { - let pt1 = (nts.destination_region.col_start, nts.destination_region.row_start); - let pt2 = (nts.destination_region.col_end, nts.destination_region.row_end); - m_start_handle.set(Some(pt1)); - m_end_handle.set(Some(pt2)); - } - } - }; - let dispatch = Dispatch::::subscribe(menu_sync_callback); + if !(*m_stat_handle) { + let pt1 = (state.destination_region.col_start, state.destination_region.row_start); + let pt2 = (state.destination_region.col_end, state.destination_region.row_end); + m_start_handle.set(Some(pt1)); + m_end_handle.set(Some(pt2)); + } + let destination_wells = ct_state.transfer.get_destination_wells(); let mouse_callback = { let m_start_handle = m_start_handle.clone(); @@ -64,11 +60,13 @@ pub fn DestinationPlate(props: &DestinationPlateProps) -> Html { let m_stat_handle = m_stat_handle.clone(); Callback::from(move |_: MouseEvent| { - let current = dispatch.get(); m_stat_handle.set(false); if let Some(ul) = *m_start_handle { if let Some(br) = *m_end_handle { if let Ok(rd) = RegionDisplay::try_from((ul.0, ul.1, br.0, br.1)) { + ct_dispatch.reduce_mut(|state| { + state.transfer.dest_region = Region::from(&rd); + }); dispatch.reduce_mut(|state| { state.destination_region = rd; }); @@ -80,12 +78,14 @@ pub fn DestinationPlate(props: &DestinationPlateProps) -> Html { let mouseleave_callback = Callback::clone(&mouseup_callback); - let rows = (1..=props.plate.plate.size().1).map(|i| { - let row = (1..=props.plate.plate.size().0).map(|j| { + let rows = (1..=props.destination_plate.plate.size().0).map(|i| { + let row = (1..=props.destination_plate.plate.size().1).map(|j| { html! { + mouse={mouse_callback.clone()} + in_transfer={destination_wells.contains(&(i,j))} + /> } }).collect::(); html! { @@ -122,7 +122,7 @@ pub struct DestPlateCellProps { pub j: u8, pub selected: bool, pub mouse: Callback<(u8,u8, MouseEventType)>, - pub color: Option + pub in_transfer: Option, } #[function_component] @@ -131,16 +131,16 @@ fn DestPlateCell(props: &DestPlateCellProps) -> Html { true => Some("current_select"), false => None, }; - let _color_string = match &props.color { - Some(c) => c.clone(), - None => "None".to_string(), + let in_transfer_class = match props.in_transfer { + Some(true) => Some("in_transfer"), + _ => None }; let mouse = Callback::clone(&props.mouse); let mouse2 = Callback::clone(&props.mouse); let (i,j) = (props.i.clone(), props.j.clone()); html! { - Html { html! {
if let Some(spi) = props.source_dims.clone() { -
-

{spi.name.clone()}

- -
- } else { -

{"No Source Plate Selected"}

- } if let Some(dpi) = props.destination_dims.clone() { +
+

{spi.name.clone()}

+ +

{dpi.name.clone()}

- +
} else {

{"No Destination Plate Selected"}

} + } else { +

{"No Source Plate Selected"}

+ }
} } diff --git a/src/components/plates/source_plate.rs b/src/components/plates/source_plate.rs index 6557d80..78f24d9 100644 --- a/src/components/plates/source_plate.rs +++ b/src/components/plates/source_plate.rs @@ -5,39 +5,35 @@ use yewdux::prelude::*; use std::rc::Rc; use crate::data::plate_instances::PlateInstance; -use crate::data::transfer_region::TransferRegion; +use crate::data::transfer_region::{TransferRegion, Region}; +use crate::components::states::{NewTransferState, CurrentTransfer}; -use super::super::states::NewTransferState; use super::super::transfer_menu::RegionDisplay; #[derive(PartialEq, Properties)] pub struct SourcePlateProps { - pub plate: PlateInstance, + pub source_plate: PlateInstance, + pub destination_plate: PlateInstance, } #[function_component] pub fn SourcePlate(props: &SourcePlateProps) -> Html { + let (state, dispatch) = use_store::(); + let (ct_state, ct_dispatch) = use_store::(); let m_start_handle: UseStateHandle> = use_state_eq(|| None); let m_end_handle: UseStateHandle> = use_state_eq(|| None); let m_stat_handle: UseStateHandle = use_state_eq(|| false); let m_start = m_start_handle.clone(); let m_end = m_end_handle.clone(); - let menu_sync_callback = { - let m_start_handle = m_start_handle.clone(); - let m_end_handle = m_end_handle.clone(); - let m_stat_handle = m_stat_handle.clone(); + if !(*m_stat_handle) { + let pt1 = (state.source_region.col_start, state.source_region.row_start); + let pt2 = (state.source_region.col_end, state.source_region.row_end); + m_start_handle.set(Some(pt1)); + m_end_handle.set(Some(pt2)); + } - move |nts: Rc| { - if !(*m_stat_handle) { - let pt1 = (nts.source_region.col_start, nts.source_region.row_start); - let pt2 = (nts.source_region.col_end, nts.source_region.row_end); - m_start_handle.set(Some(pt1)); - m_end_handle.set(Some(pt2)); - } - } - }; - let dispatch = Dispatch::::subscribe(menu_sync_callback); + let source_wells = ct_state.transfer.get_source_wells(); let mouse_callback = { let m_start_handle = m_start_handle.clone(); @@ -70,6 +66,9 @@ pub fn SourcePlate(props: &SourcePlateProps) -> Html { if let Some(ul) = *m_start_handle { if let Some(br) = *m_end_handle { if let Ok(rd) = RegionDisplay::try_from((ul.0, ul.1, br.0, br.1)) { + ct_dispatch.reduce_mut(|state| { + state.transfer.source_region = Region::from(&rd); + }); dispatch.reduce_mut(|state| { state.source_region = rd; }); @@ -81,12 +80,14 @@ pub fn SourcePlate(props: &SourcePlateProps) -> Html { let mouseleave_callback = Callback::clone(&mouseup_callback); - let rows = (1..=props.plate.plate.size().1).map(|i| { - let row = (1..=props.plate.plate.size().0).map(|j| { + let rows = (1..=props.source_plate.plate.size().0).map(|i| { + let row = (1..=props.source_plate.plate.size().1).map(|j| { html! { + mouse={mouse_callback.clone()} + in_transfer={source_wells.contains(&(i,j))} + /> } }).collect::(); html! { @@ -117,7 +118,7 @@ pub struct SourcePlateCellProps { j: u8, selected: bool, mouse: Callback<(u8,u8, MouseEventType)>, - color: Option + in_transfer: Option, } #[derive(Debug)] pub enum MouseEventType { @@ -131,16 +132,16 @@ fn SourcePlateCell(props: &SourcePlateCellProps) -> Html { true => Some("current_select"), false => None, }; - let _color_string = match &props.color { - Some(c) => c.clone(), - None => "None".to_string(), + let in_transfer_class = match props.in_transfer { + Some(true) => Some("in_transfer"), + _ => None }; let mouse = Callback::clone(&props.mouse); let mouse2 = Callback::clone(&props.mouse); let (i,j) = (props.i.clone(), props.j.clone()); html! { - Html { let (state, dispatch) = use_store::(); + let (ct_state, ct_dispatch) = use_store::(); let on_src_region_change = { - let state = state.clone(); let dispatch = dispatch.clone(); + let ct_dispatch = ct_dispatch.clone(); Callback::from(move |e: Event| { - log::debug!("Input changed."); let target: Option = e.target(); let input = target.and_then(|t| t.dyn_into::().ok()); if let Some(input) = input { if let Ok(rd) = RegionDisplay::try_from(input.value()) { + ct_dispatch.reduce_mut(|state| { + state.transfer.source_region = Region::from(&rd); + }); dispatch.reduce_mut(|state| { state.source_region = rd; }); @@ -35,15 +40,17 @@ pub fn TransferMenu() -> Html { }) }; let on_dest_region_change = { - let state = state.clone(); let dispatch = dispatch.clone(); + let ct_dispatch = ct_dispatch.clone(); Callback::from(move |e: Event| { - log::debug!("Input changed."); let target: Option = e.target(); let input = target.and_then(|t| t.dyn_into::().ok()); if let Some(input) = input { if let Ok(rd) = RegionDisplay::try_from(input.value()) { + ct_dispatch.reduce_mut(|state| { + state.transfer.dest_region = Region::from(&rd); + }); dispatch.reduce_mut(|state| { state.destination_region = rd; }); @@ -54,6 +61,51 @@ pub fn TransferMenu() -> Html { } }) }; + + let on_dest_interleave_x_change = { + let dispatch = dispatch.clone(); + let ct_state = ct_state.clone(); + let ct_dispatch = ct_dispatch.clone(); + + Callback::from(move |e: Event| { + let target: Option = e.target(); + let input = target.and_then(|t| t.dyn_into::().ok()); + if let Some(input) = input { + if let Ok(num) = input.value().parse::() { + dispatch.reduce_mut(|state| { + state.interleave_x = num; + }); + if let Some((_,y)) = ct_state.transfer.interleave_dest { + ct_dispatch.reduce_mut(|state| { + state.transfer.interleave_dest = Some((num, y)); + }); + } + } + } + }) + }; + let on_dest_interleave_y_change = { + let dispatch = dispatch.clone(); + let ct_state = ct_state.clone(); + let ct_dispatch = ct_dispatch.clone(); + + Callback::from(move |e: Event| { + let target: Option = e.target(); + let input = target.and_then(|t| t.dyn_into::().ok()); + if let Some(input) = input { + if let Ok(num) = input.value().parse::() { + dispatch.reduce_mut(|state| { + state.interleave_y = num; + }); + if let Some((x,_)) = ct_state.transfer.interleave_dest { + ct_dispatch.reduce_mut(|state| { + state.transfer.interleave_dest = Some((x, num)); + }); + } + } + } + }) + }; html! {
@@ -69,14 +121,17 @@ pub fn TransferMenu() -> Html { onchange={on_dest_region_change} value={state.destination_region.text.clone()}/>
- {"Interleave "} - - - - + {"Destination Interleave "} + + + +
+ } } @@ -116,6 +171,15 @@ impl TryFrom for RegionDisplay { } } +impl From<&RegionDisplay> for Region { + fn from(value: &RegionDisplay) -> Self { + if value.col_start == value.col_end && value.row_start == value.row_end { + Region::Point((value.col_start, value.row_start)) + } else { + Region::Rect((value.col_start, value.row_start), (value.col_end, value.row_end)) + } + } +} impl TryFrom<(u8,u8,u8,u8)> for RegionDisplay { type Error = &'static str; diff --git a/src/components/tree.rs b/src/components/tree.rs index 6638b16..ff56477 100644 --- a/src/components/tree.rs +++ b/src/components/tree.rs @@ -6,9 +6,7 @@ use web_sys::{EventTarget, HtmlElement, HtmlDialogElement}; use yew::prelude::*; use yewdux::prelude::*; -use crate::data::{plate_instances::PlateInstance, transfer::Transfer}; -use crate::data::plate::*; -use crate::components::states::{MainState, NewTransferState}; +use crate::components::states::{MainState, NewTransferState, CurrentTransfer}; use crate::components::transfer_menu::RegionDisplay; #[derive(PartialEq, Properties)] diff --git a/src/data/plate.rs b/src/data/plate.rs index e71c69b..02ee5b4 100644 --- a/src/data/plate.rs +++ b/src/data/plate.rs @@ -1,6 +1,6 @@ use serde::{Serialize, Deserialize}; -#[derive(PartialEq, Eq, Clone, Copy, Serialize, Deserialize, Debug)] +#[derive(PartialEq, Eq, Default, Clone, Copy, Serialize, Deserialize, Debug)] pub struct Plate { pub plate_type: PlateType, pub plate_format: PlateFormat, @@ -24,6 +24,11 @@ pub enum PlateType { Source, Destination, } +impl Default for PlateType { + fn default() -> Self { + Self::Source + } +} #[derive(PartialEq, Eq, Clone, Copy, Serialize, Deserialize, Debug)] pub enum PlateFormat { @@ -36,6 +41,11 @@ pub enum PlateFormat { W1536, W3456, } +impl Default for PlateFormat { + fn default() -> Self { + Self::W96 + } +} impl std::fmt::Display for PlateFormat { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { match self { @@ -53,6 +63,7 @@ impl std::fmt::Display for PlateFormat { impl PlateFormat { pub fn size(&self) -> (u8, u8) { + /* match self { PlateFormat::W6 => (3, 2), PlateFormat::W12 => (4, 3), @@ -63,6 +74,17 @@ impl PlateFormat { PlateFormat::W1536 => (48, 32), PlateFormat::W3456 => (72, 48), } + */ + match self { + PlateFormat::W6 => (2, 3), + PlateFormat::W12 => (3, 4), + PlateFormat::W24 => (4, 6), + PlateFormat::W48 => (6, 8), + PlateFormat::W96 => (8, 12), + PlateFormat::W384 => (16, 24), + PlateFormat::W1536 => (32, 48), + PlateFormat::W3456 => (48, 72), + } } } diff --git a/src/data/transfer_region.rs b/src/data/transfer_region.rs index 3de1eb3..267aa61 100644 --- a/src/data/transfer_region.rs +++ b/src/data/transfer_region.rs @@ -7,6 +7,11 @@ pub enum Region { Rect((u8, u8), (u8, u8)), Point((u8, u8)), } +impl Default for Region { + fn default() -> Self { + Region::Point((1,1)) + } +} impl TryFrom for ((u8, u8), (u8, u8)) { type Error = &'static str; fn try_from(region: Region) -> Result { @@ -19,7 +24,7 @@ impl TryFrom for ((u8, u8), (u8, u8)) { } } -#[derive(PartialEq, Eq, Clone, Copy, Serialize, Deserialize, Debug)] +#[derive(PartialEq, Eq, Default, Clone, Copy, Serialize, Deserialize, Debug)] pub struct TransferRegion { pub source_plate: Plate, pub source_region: Region, // Even if it is just a point, we don't want corners. @@ -31,7 +36,8 @@ pub struct TransferRegion { impl TransferRegion { pub fn get_source_wells(&self) -> Vec<(u8, u8)> { - if let Region::Rect(c1, c2) = self.source_region { + match self.source_region { + Region::Rect(c1, c2) => { let mut wells = Vec::<(u8, u8)>::new(); let (ul, br) = standardize_rectangle(&c1, &c2); let (interleave_i, interleave_j) = self.interleave_source.unwrap_or((1, 1)); @@ -50,21 +56,25 @@ impl TransferRegion { } } return wells; - } else { - panic!("Source region is just a point!") + }, + Region::Point(p) => return vec![p] } } + pub fn get_destination_wells(&self) -> Vec<(u8, u8)> { let map = self.calculate_map(); let source_wells = self.get_source_wells(); let mut wells = Vec::<(u8, u8)>::new(); + log::debug!("GDW:"); for well in source_wells { if let Some(mut dest_wells) = map(well) { + log::debug!("Map {:?} to {:?}", well, dest_wells); wells.append(&mut dest_wells); } } + log::debug!("GDW END."); return wells; } @@ -74,6 +84,7 @@ impl TransferRegion { // this function will not panic. :) if let Err(msg) = self.validate() { eprintln!("{}", msg); + log::debug!("{}", msg); eprintln!("This transfer will be empty."); return Box::new(|(_, _)| None); } @@ -82,10 +93,10 @@ impl TransferRegion { let il_dest = self.interleave_dest.unwrap_or((1, 1)); let il_source = self.interleave_source.unwrap_or((1, 1)); - let source_corners: ((u8, u8), (u8, u8)) = self - .source_region - .try_into() - .expect("Source region should not be a point"); + let source_corners: ((u8, u8), (u8, u8)) = match self.source_region { + Region::Point((x,y)) => ((x,y),(x,y)), + Region::Rect(c1,c2) => (c1,c2) + }; let (source_ul, _) = standardize_rectangle(&source_corners.0, &source_corners.1); // This map is not necessarily injective or surjective, // but we will have these properties in certain cases. @@ -132,24 +143,6 @@ impl TransferRegion { s2.1.checked_sub(s1.1).unwrap() + 1, ); - /* - println!("{} % {} == {}", i, dims.0, i*il_dest.0.abs() as u8 % dims.0); - for a in ds1.0..=ds2.0 { - for b in ds1.1..=ds2.1 { - println!("({},{}): {} % {} == {}", a, b, - a.checked_sub(ds1.0).unwrap()+1, dims.0, - (a.checked_sub(ds1.0).unwrap()+1) % dims.0); - } - } - for a in ds1.0..=ds2.0 { - for b in ds1.1..=ds2.1 { - println!("({},{}): {} % {} == {}", a, b, - a.checked_sub(ds1.0).unwrap()+1, il_dest.0.abs() as u8, - (a.checked_sub(ds1.0).unwrap()+1) % il_dest.0.abs() as u8); - } - } - */ - Some( possible_destination_wells .into_iter() @@ -187,7 +180,8 @@ impl TransferRegion { let il_dest = self.interleave_dest.unwrap_or((1, 1)); match self.source_region { - Region::Point(_) => return Err("Source region should not be a point!"), + Region::Point(_) => return Ok(()), // Should make sure it's actually in the plate, leave for + // later Region::Rect(s1, s2) => { // Check if all source wells exist: if s1.0 == 0 || s1.1 == 0 || s2.0 == 0 || s2.1 == 0 { @@ -199,6 +193,7 @@ impl TransferRegion { return Err("Source region is out-of-bounds! (Too tall)"); } if s1.1 > source_max.1 || s2.1 > source_max.1 { + log::debug!("s1.1: {}, max.1: {}", s1.1, source_max.1); return Err("Source region is out-of-bounds! (Too wide)"); } // Check that source lengths divide destination lengths