diff --git a/src/components/main_window.rs b/src/components/main_window.rs index 0624f1c..260f04b 100644 --- a/src/components/main_window.rs +++ b/src/components/main_window.rs @@ -4,7 +4,6 @@ use super::plates::plate_container::PlateContainer; use super::tree::Tree; use super::transfer_menu::TransferMenu; - #[function_component] pub fn MainWindow() -> Html { html!{ diff --git a/src/components/mod.rs b/src/components/mod.rs index 6ff64b0..e7265a7 100644 --- a/src/components/mod.rs +++ b/src/components/mod.rs @@ -1,4 +1,5 @@ -pub mod plates; +pub mod states; pub mod main_window; pub mod tree; pub mod transfer_menu; +pub mod plates; diff --git a/src/components/plates/source_plate.rs b/src/components/plates/source_plate.rs index a825e9c..6f3da9f 100644 --- a/src/components/plates/source_plate.rs +++ b/src/components/plates/source_plate.rs @@ -1,6 +1,11 @@ #![allow(non_snake_case)] use yew::prelude::*; +use yewdux::prelude::*; +use std::rc::Rc; + +use super::super::states::NewTransferState; +use super::super::transfer_menu::RegionDisplay; #[derive(PartialEq, Properties)] pub struct SourcePlateProps { @@ -13,27 +18,67 @@ pub fn SourcePlate(props: &SourcePlateProps) -> Html { 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 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| { + log::debug!("Got an updated state!"); + 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 mouseup_callback = Callback::from(move |_: MouseEvent| { - m_stat_handle2.set(false); - }); + }; + let dispatch = Dispatch::::subscribe(menu_sync_callback); + + let mouse_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(); + + 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 = { + let m_start_handle = m_start_handle.clone(); + let m_end_handle = m_end_handle.clone(); + 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 { + dispatch.set(NewTransferState { + source_region: RegionDisplay::try_from((ul.0, ul.1, br.0, br.1)).expect(""), + destination_region: current.destination_region.clone(), + interleave_x: current.interleave_x, + interleave_y: current.interleave_y }) + } + } + }) + }; + let mouseleave_callback = Callback::clone(&mouseup_callback); let rows = (1..=props.height).map(|i| { diff --git a/src/components/plates/source_plate_old.rs b/src/components/plates/source_plate_old.rs deleted file mode 100644 index 3de68e1..0000000 --- a/src/components/plates/source_plate_old.rs +++ /dev/null @@ -1,157 +0,0 @@ -#![allow(non_snake_case)] -use yew::prelude::*; - -#[derive(PartialEq, Properties)] -pub struct SourcePlateProps { - width: u8, - height: u8, -} -struct SelectionState { - m_start: Option<(u8, u8)>, - m_end: Option<(u8, u8)>, - m_stat: bool, -} - -pub fn SourcePlate(props: &SourcePlateProps) -> Html { - use_shared_state_provider(cx, || SelectionState { - m_start: None, - m_end: None, - m_stat: false, - }); - - cx.render(rsx! { - div{ - class: "source_plate", - style { STYLE } - table { - draggable: "false", - for i in 1..=cx.props.height { - tr { - draggable: "false", - for j in 1..=cx.props.width { - SourcePlateCell {i: i, j: j} - } - } - }, - } - } - }) -} - -#[derive(PartialEq, Properties)] -pub struct SourcePlateCellProps { - i: u8, - j: u8, - color: Option -} - -fn SourcePlateCell(props: &SourcePlateCe) -> Element { - let selection_state = use_shared_state::(cx).unwrap(); - let selected = in_rect( - selection_state.read().m_start, - selection_state.read().m_end, - (*i, *j), - ); - let selected_class = match selected { - true => "current_select", - false => "", - }; - let color_string = match color { - Some(c) => c.clone(), - None => "None".to_string(), - }; - - 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)); - } -} diff --git a/src/components/states.rs b/src/components/states.rs new file mode 100644 index 0000000..3c355bb --- /dev/null +++ b/src/components/states.rs @@ -0,0 +1,10 @@ +use yewdux::prelude::*; +use super::transfer_menu::RegionDisplay; + +#[derive(Debug, Default, Clone, PartialEq, Store)] +pub struct NewTransferState { + pub source_region: RegionDisplay, + pub destination_region: RegionDisplay, + pub interleave_x: u8, + pub interleave_y: u8, +} diff --git a/src/components/transfer_menu.rs b/src/components/transfer_menu.rs index e8e55b1..256babd 100644 --- a/src/components/transfer_menu.rs +++ b/src/components/transfer_menu.rs @@ -1,15 +1,46 @@ #![allow(non_snake_case)] + use yew::prelude::*; +use yewdux::prelude::*; +use wasm_bindgen::JsCast; +use web_sys::{EventTarget, HtmlInputElement}; use regex::Regex; use lazy_static::lazy_static; +use super::states::NewTransferState; + #[function_component] pub fn TransferMenu() -> Html { + let (state, dispatch) = use_store::(); + + let on_src_region_change = { + let state = state.clone(); + let dispatch = 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()) { + dispatch.set( NewTransferState { + source_region: rd, + destination_region: state.destination_region.clone(), + interleave_x: state.interleave_x, + interleave_y: state.interleave_y + }); + log::debug!("{:?}", dispatch.get()); + } + } + }) + }; + html! {
- +
@@ -17,13 +48,13 @@ pub fn TransferMenu() -> Html { } } -#[derive(PartialEq, Eq, Debug)] -struct RegionDisplay { - text: String, - col_start: u8, - row_start: u8, - col_end: u8, - row_end: u8, +#[derive(PartialEq, Eq, Debug, Clone, Default)] +pub struct RegionDisplay { + pub text: String, + pub col_start: u8, + pub row_start: u8, + pub col_end: u8, + pub row_end: u8, } impl TryFrom for RegionDisplay {