diff --git a/assets/scss/default_theme/components/_plates.scss b/assets/scss/default_theme/components/_plates.scss index e91cf79..9cc31b3 100644 --- a/assets/scss/default_theme/components/_plates.scss +++ b/assets/scss/default_theme/components/_plates.scss @@ -43,10 +43,10 @@ td.plate_cell.in_transfer div.plate_cell_inner::after { } div.source_plate td.current_select div.plate_cell_inner { - background-image: linear-gradient(lightblue, lightblue); + background: lightblue !important; } div.dest_plate td.current_select div.plate_cell_inner { - background: lightcoral; + background: lightcoral !important; } diff --git a/src/components/plates/destination_plate.rs b/src/components/plates/destination_plate.rs index 9de0048..c17fa85 100644 --- a/src/components/plates/destination_plate.rs +++ b/src/components/plates/destination_plate.rs @@ -1,12 +1,17 @@ #![allow(non_snake_case)] -use std::rc::Rc; + +use std::collections::HashMap; use yew::prelude::*; use yewdux::prelude::*; -use crate::components::states::CurrentTransfer; +use crate::components::states::{CurrentTransfer, MainState}; use crate::data::plate_instances::PlateInstance; use crate::data::transfer_region::{Region, TransferRegion}; +// Color Palette for the Source Plates, can be changed here +use crate::components::plates::util::Palettes; +const PALETTE: super::util::ColorPalette = Palettes::YELLOW_PINK; + use super::super::transfer_menu::RegionDisplay; #[derive(Properties, PartialEq)] @@ -17,6 +22,7 @@ pub struct DestinationPlateProps { #[function_component] pub fn DestinationPlate(props: &DestinationPlateProps) -> Html { + let (main_state, _) = 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); @@ -53,6 +59,20 @@ pub fn DestinationPlate(props: &DestinationPlateProps) -> Html { }) }; + let mut color_counter: u8 = 0; + let color_map = { + let ts = main_state.transfers.iter().filter(|t| t.dest_id == props.destination_plate.get_uuid()); + let mut color_map: HashMap<(u8,u8), u8> = HashMap::new(); + for t in ts { + color_counter += 1; + let dws = t.transfer_region.get_destination_wells(); + for dw in dws { + color_map.insert(dw, color_counter); + } + } + color_map + }; + let mouseup_callback = { let m_start_handle = m_start_handle.clone(); let m_end_handle = m_end_handle.clone(); @@ -82,6 +102,7 @@ pub fn DestinationPlate(props: &DestinationPlateProps) -> Html { selected={super::source_plate::in_rect(*m_start.clone(), *m_end.clone(), (i,j))} mouse={mouse_callback.clone()} in_transfer={destination_wells.contains(&(i,j))} + color={color_map.get(&(i,j)).map(|x| *x).and_then(|y| Some((y,color_counter)))} /> } }).collect::(); @@ -121,6 +142,7 @@ pub struct DestPlateCellProps { pub selected: bool, pub mouse: Callback<(u8, u8, MouseEventType)>, pub in_transfer: Option, + color: Option<(u8,u8)>, } #[function_component] @@ -133,6 +155,10 @@ fn DestPlateCell(props: &DestPlateCellProps) -> Html { Some(true) => Some("in_transfer"), _ => None, }; + let color = match props.color { + Some(num) => PALETTE.get_u8(num.0,num.1), + None => [255.0,255.0,255.0] + }; let mouse = Callback::clone(&props.mouse); let mouse2 = Callback::clone(&props.mouse); let (i, j) = (props.i.clone(), props.j.clone()); @@ -145,7 +171,8 @@ fn DestPlateCell(props: &DestPlateCellProps) -> Html { onmouseenter={move |_| { mouse2.emit((i,j, MouseEventType::MOUSEENTER)) }}> -
+
} } diff --git a/src/components/plates/mod.rs b/src/components/plates/mod.rs index e93c903..fe8968e 100644 --- a/src/components/plates/mod.rs +++ b/src/components/plates/mod.rs @@ -1,3 +1,4 @@ pub mod destination_plate; pub mod plate_container; pub mod source_plate; +mod util; diff --git a/src/components/plates/source_plate.rs b/src/components/plates/source_plate.rs index f911d3d..221858b 100644 --- a/src/components/plates/source_plate.rs +++ b/src/components/plates/source_plate.rs @@ -1,13 +1,17 @@ #![allow(non_snake_case)] -use std::rc::Rc; +use std::collections::HashMap; use yew::prelude::*; use yewdux::prelude::*; -use crate::components::states::CurrentTransfer; +use crate::components::states::{CurrentTransfer, MainState}; use crate::data::plate_instances::PlateInstance; use crate::data::transfer_region::{Region, TransferRegion}; +// Color Palette for the Source Plates, can be changed here +use crate::components::plates::util::Palettes; +const PALETTE: super::util::ColorPalette = Palettes::RAINBOW; + use super::super::transfer_menu::RegionDisplay; #[derive(PartialEq, Properties)] @@ -18,6 +22,7 @@ pub struct SourcePlateProps { #[function_component] pub fn SourcePlate(props: &SourcePlateProps) -> Html { + let (main_state, _) = 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); @@ -34,6 +39,20 @@ pub fn SourcePlate(props: &SourcePlateProps) -> Html { m_end_handle.set(Some(pt2)); } + let mut color_counter: u8 = 0; + let color_map = { + let ts = main_state.transfers.iter().filter(|t| t.source_id == props.source_plate.get_uuid()); + let mut color_map: HashMap<(u8,u8), u8> = HashMap::new(); + for t in ts { + color_counter += 1; + let sws = t.transfer_region.get_source_wells(); + for sw in sws { + color_map.insert(sw, color_counter); + } + } + color_map + }; + let source_wells = ct_state.transfer.transfer_region.get_source_wells(); let mouse_callback = { @@ -85,6 +104,7 @@ pub fn SourcePlate(props: &SourcePlateProps) -> Html { selected={in_rect(*m_start.clone(), *m_end.clone(), (i,j))} mouse={mouse_callback.clone()} in_transfer={source_wells.contains(&(i,j))} + color={color_map.get(&(i,j)).map(|x| *x).and_then(|y| Some((y,color_counter)))} /> } }) @@ -119,6 +139,7 @@ pub struct SourcePlateCellProps { selected: bool, mouse: Callback<(u8, u8, MouseEventType)>, in_transfer: Option, + color: Option<(u8,u8)>, } #[derive(Debug)] pub enum MouseEventType { @@ -136,19 +157,25 @@ fn SourcePlateCell(props: &SourcePlateCellProps) -> Html { Some(true) => Some("in_transfer"), _ => None, }; + let color = match props.color { + Some(num) => PALETTE.get_u8(num.0,num.1), + None => [255.0,255.0,255.0] + }; let mouse = Callback::clone(&props.mouse); let mouse2 = Callback::clone(&props.mouse); let (i, j) = (props.i.clone(), props.j.clone()); html! { -
+
} } diff --git a/src/components/plates/util.rs b/src/components/plates/util.rs new file mode 100644 index 0000000..7a6847f --- /dev/null +++ b/src/components/plates/util.rs @@ -0,0 +1,50 @@ +// Sources: +// https://iquilezles.org/articles/palettes/ +// http://dev.thi.ng/gradients/ + +#[derive(Clone, Copy, PartialEq, Debug)] +pub struct ColorPalette { + a: [f64; 3], + b: [f64; 3], + c: [f64; 3], + d: [f64; 3], +} + +impl ColorPalette { + pub fn new(a: [f64; 3], b: [f64; 3], c: [f64; 3], d: [f64; 3]) -> Self { + ColorPalette { a, b, c, d } + } + + pub fn get(&self, t: f64) -> [f64; 3] { + [ + (self.a[0] + self.b[0]*f64::cos(6.28318*(self.c[0]*t+self.d[0])))*255.0, + (self.a[1] + self.b[1]*f64::cos(6.28318*(self.c[1]*t+self.d[1])))*255.0, + (self.a[2] + self.b[2]*f64::cos(6.28318*(self.c[2]*t+self.d[2])))*255.0, + ] + } + + pub fn get_u8(&self, t: u8, n: u8) -> [f64; 3] { + assert!(t>0, "t must be greater than zero!"); + assert!(n>0, "There cannot be zero points!"); + self.get((t-1) as f64 / (n-1) as f64) + } +} + +#[non_exhaustive] +pub struct Palettes; + +#[allow(dead_code)] +impl Palettes { + pub const RAINBOW: ColorPalette = ColorPalette { + a: [0.500,0.500,0.500], + b: [0.500,0.500,0.500], + c: [0.800,0.800,0.800], + d: [0.000,0.333,0.667], + }; + pub const YELLOW_PINK: ColorPalette = ColorPalette { + a: [0.500,0.500,0.320], + b: [0.500,0.500,0.500], + c: [0.100,0.500,0.360], + d: [0.000,0.000,0.650], + }; +} diff --git a/src/components/states.rs b/src/components/states.rs index 3d81e29..26ee615 100644 --- a/src/components/states.rs +++ b/src/components/states.rs @@ -87,4 +87,20 @@ impl MainState { self.destination_plates.swap_remove(index); } } + pub fn rename_plate(&mut self, id: Uuid, new_name: &str) { + if let Some(index) = self + .source_plates + .iter() + .position(|spi| spi.get_uuid() == id) + { + self.source_plates[index].change_name(new_name.to_string()); + } + if let Some(index) = self + .destination_plates + .iter() + .position(|dpi| dpi.get_uuid() == id) + { + self.destination_plates[index].change_name(new_name.to_string()); + } + } }