diff --git a/src/components/plates/destination_plate.rs b/src/components/plates/destination_plate.rs index 5e0d5d6..e124b94 100644 --- a/src/components/plates/destination_plate.rs +++ b/src/components/plates/destination_plate.rs @@ -34,6 +34,7 @@ pub fn DestinationPlate(props: &DestinationPlateProps) -> Html { let (pt1, pt2) = match ct_state.transfer.transfer_region.dest_region { Region::Point((x, y)) => ((x, y), (x, y)), Region::Rect(c1, c2) => (c1, c2), + Region::Custom(_) => ((0,0), (0,0)), }; m_start_handle.set(Some(pt1)); m_end_handle.set(Some(pt2)); diff --git a/src/components/plates/source_plate.rs b/src/components/plates/source_plate.rs index 4605521..2c475a6 100644 --- a/src/components/plates/source_plate.rs +++ b/src/components/plates/source_plate.rs @@ -34,6 +34,7 @@ pub fn SourcePlate(props: &SourcePlateProps) -> Html { let (pt1, pt2) = match ct_state.transfer.transfer_region.source_region { Region::Point((x, y)) => ((x, y), (x, y)), Region::Rect(c1, c2) => (c1, c2), + Region::Custom(_) => ((0,0), (0,0)), }; m_start_handle.set(Some(pt1)); m_end_handle.set(Some(pt2)); diff --git a/src/components/transfer_menu.rs b/src/components/transfer_menu.rs index f17b71c..145a2f9 100644 --- a/src/components/transfer_menu.rs +++ b/src/components/transfer_menu.rs @@ -353,6 +353,7 @@ impl From<&Region> for RegionDisplay { Region::Rect(c1, c2) => RegionDisplay::try_from((c1.0, c1.1, c2.0, c2.1)) .ok() .unwrap(), + Region::Custom(_) => RegionDisplay { text: "CUSTOM".to_string(), col_start: 0, row_start: 0, col_end: 0, row_end: 0 } } } } diff --git a/src/data/transfer_region.rs b/src/data/transfer_region.rs index 301aa92..b68ca3a 100644 --- a/src/data/transfer_region.rs +++ b/src/data/transfer_region.rs @@ -2,10 +2,17 @@ use serde::{Deserialize, Serialize}; use super::plate::Plate; +#[derive(Clone, PartialEq, Eq, Serialize, Deserialize, Debug)] +pub struct CustomRegion { + src: Vec<(u8, u8)>, + dest: Vec<(u8, u8)>, +} + #[derive(Clone, PartialEq, Eq, Serialize, Deserialize, Debug)] pub enum Region { Rect((u8, u8), (u8, u8)), Point((u8, u8)), + Custom(CustomRegion), } impl Default for Region { fn default() -> Self { @@ -49,7 +56,7 @@ impl Default for TransferRegion { impl TransferRegion { pub fn get_source_wells(&self) -> Vec<(u8, u8)> { - match 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); @@ -71,7 +78,8 @@ impl TransferRegion { } wells } - Region::Point(p) => vec![p], + Region::Point(p) => vec![*p], + Region::Custom(c) => c.src.clone(), } } @@ -112,6 +120,7 @@ impl TransferRegion { 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), + Region::Custom(_) => ((0, 0), (0, 0)), }; let (source_ul, _) = standardize_rectangle(&source_corners.0, &source_corners.1); // This map is not necessarily injective or surjective, @@ -120,7 +129,7 @@ impl TransferRegion { // and simple then we *will* have injectivity. // Non-replicate transfers: - match self.dest_region { + match &self.dest_region { Region::Point((x, y)) => { Box::new(move |(i, j)| { if source_wells.contains(&(i, j)) { @@ -224,6 +233,22 @@ impl TransferRegion { } }) } + Region::Custom(c) => Box::new(move |(i, j)| { + let src = c.src.clone(); + let dest = c.dest.clone(); + + let points: Vec<(u8, u8)> = src + .iter() + .enumerate() + .filter(|(_index, (x, y))| *x == i && *y == j) + .map(|(index, _)| dest[index]) + .collect(); + if points.is_empty() { + None + } else { + Some(points) + } + }), } } @@ -256,7 +281,8 @@ impl TransferRegion { // log::debug!("s1.1: {}, max.1: {}", s1.1, source_max.1); return Err("Source region is out-of-bounds! (Too wide)"); } - } + }, + Region::Custom(_) => return Ok(()), } if il_source.0 == 0 || il_dest.1 == 0 {