#![allow(non_snake_case)] use yew::prelude::*; #[derive(PartialEq, Properties)] pub struct SourcePlateProps { pub width: u8, pub height: u8, } #[function_component] pub fn SourcePlate(props: &SourcePlateProps) -> Html { /* let selection_state = use_state_eq(|| SelectionState{ m_start: None, m_end: None, m_stat: false }); */ 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_stat_handle2 = m_stat_handle.clone(); let m_start = m_start_handle.clone(); let m_end = m_end_handle.clone(); let mouse_callback = Callback::from(move |(i,j,t)| { match t { MouseEventType::MOUSEDOWN => { m_start_handle.set(Some((i,j))); m_end_handle.set(None); m_stat_handle.set(true); }, MouseEventType::MOUSEENTER => { if *m_stat_handle { m_end_handle.set(Some((i,j))) } } } }); let mouseup_callback = Callback::from(move |_: MouseEvent| { m_stat_handle2.set(false); }); let mouseleave_callback = Callback::clone(&mouseup_callback); let rows = (1..=props.height).map(|i| { let row = (1..=props.width).map(|j| { html! { } }).collect::(); html! { { row } } }).collect::(); html! {
{ rows }
} } #[derive(PartialEq, Properties)] pub struct SourcePlateCellProps { i: u8, j: u8, selected: bool, mouse: Callback<(u8,u8, MouseEventType)>, color: Option } #[derive(Debug)] pub enum MouseEventType { MOUSEDOWN, MOUSEENTER } #[function_component] fn SourcePlateCell(props: &SourcePlateCellProps) -> Html { let selected_class = match props.selected { true => Some("current_select"), false => None, }; let color_string = match &props.color { Some(c) => c.clone(), None => "None".to_string(), }; let mouse = Callback::clone(&props.mouse); let mouse2 = Callback::clone(&props.mouse); let (i,j) = (props.i.clone(), props.j.clone()); html! {
} /* cx.render(rsx! { td { class: "plate_cell {selected_class}", draggable: "false", style: "background: {color_string}", onmousedown: move |_| { selection_state.write().m_start = Some((*i,*j)); selection_state.write().m_end = None; selection_state.write().m_stat = true; }, onmouseenter: move |me: MouseEvent| { if me.data.held_buttons().is_empty() { selection_state.write().m_stat = false; } if selection_state.read().m_stat { selection_state.write().m_end = Some((*i,*j)) } }, onmouseup: move |_| { selection_state.write().m_stat = false }, div { class: "plate_cell_inner" } } }) */ } fn in_rect(corner1: Option<(u8, u8)>, corner2: Option<(u8, u8)>, pt: (u8, u8)) -> bool { if let (Some(c1), Some(c2)) = (corner1, corner2) { return pt.0 <= u8::max(c1.0, c2.0) && pt.0 >= u8::min(c1.0, c2.0) && pt.1 <= u8::max(c1.1, c2.1) && pt.1 >= u8::min(c1.1, c2.1); } else { return false; } } #[cfg(test)] mod tests { use super::in_rect; // in_rect tests #[test] fn test_in_rect1() { // Test in center of rect let c1 = (1, 1); let c2 = (10, 10); let pt = (5, 5); assert!(in_rect(Some(c1), Some(c2), pt)); // Order of the corners should not matter: assert!(in_rect(Some(c2), Some(c1), pt)); } #[test] fn test_in_rect2() { // Test on top/bottom edges of rect let c1 = (1, 1); let c2 = (10, 10); let pt1 = (1, 5); let pt2 = (10, 5); assert!(in_rect(Some(c1), Some(c2), pt1)); assert!(in_rect(Some(c1), Some(c2), pt2)); // Order of the corners should not matter: assert!(in_rect(Some(c2), Some(c1), pt1)); assert!(in_rect(Some(c2), Some(c1), pt2)); } #[test] fn test_in_rect3() { // Test on left/right edges of rect let c1 = (1, 1); let c2 = (10, 10); let pt1 = (5, 1); let pt2 = (5, 10); assert!(in_rect(Some(c1), Some(c2), pt1)); assert!(in_rect(Some(c1), Some(c2), pt2)); // Order of the corners should not matter: assert!(in_rect(Some(c2), Some(c1), pt1)); assert!(in_rect(Some(c2), Some(c1), pt2)); } #[test] fn test_in_rect4() { // Test cases that should fail let c1 = (1, 1); let c2 = (10, 10); let pt1 = (0, 0); let pt2 = (15, 15); assert_eq!(false, in_rect(Some(c1), Some(c2), pt1)); assert_eq!(false, in_rect(Some(c1), Some(c2), pt2)); } }