#![allow(non_snake_case)] use lazy_static::lazy_static; use regex::Regex; use serde::{Deserialize, Serialize}; use yew::prelude::*; use yewdux::prelude::*; use crate::components::callbacks::transfer_menu_callbacks; use plate_tool_lib::transfer_region::Region; use plate_tool_lib::util::{letters_to_num, num_to_letters}; use super::states::{CurrentTransfer, MainState}; #[function_component] pub fn TransferMenu() -> Html { let (main_state, main_dispatch) = use_store::(); let (ct_state, ct_dispatch) = use_store::(); let on_name_change = { let ct_dispatch = ct_dispatch.clone(); transfer_menu_callbacks::on_name_change_callback(ct_dispatch) }; let on_src_region_change = { let ct_dispatch = ct_dispatch.clone(); transfer_menu_callbacks::on_src_region_change_callback(ct_dispatch) }; let on_dest_region_change = { let ct_dispatch = ct_dispatch.clone(); transfer_menu_callbacks::on_dest_region_change_callback(ct_dispatch) }; let on_source_interleave_x_change = { let ct_dispatch = ct_dispatch.clone(); transfer_menu_callbacks::on_source_interleave_x_change_callback(ct_dispatch) }; let on_source_interleave_y_change = { let ct_dispatch = ct_dispatch.clone(); transfer_menu_callbacks::on_source_interleave_y_change_callback(ct_dispatch) }; let on_dest_interleave_x_change = { let ct_dispatch = ct_dispatch.clone(); transfer_menu_callbacks::on_dest_interleave_x_change_callback(ct_dispatch) }; let on_dest_interleave_y_change = { let ct_dispatch = ct_dispatch.clone(); transfer_menu_callbacks::on_dest_interleave_y_change_callback(ct_dispatch) }; let on_volume_change = { let ct_dispatch = ct_dispatch.clone(); transfer_menu_callbacks::on_volume_change_callback(ct_dispatch) }; let new_transfer_button_callback = { let main_dispatch = main_dispatch.clone(); let main_state = main_state.clone(); let ct_dispatch = ct_dispatch.clone(); transfer_menu_callbacks::new_transfer_button_callback_callback( main_dispatch, main_state, ct_dispatch, ) }; let save_transfer_button_callback = { let main_dispatch = main_dispatch.clone(); let main_state = main_state.clone(); let ct_state = ct_state.clone(); let new_transfer_button_callback = new_transfer_button_callback.clone(); transfer_menu_callbacks::save_transfer_button_callback_callback( main_dispatch, main_state, ct_state, new_transfer_button_callback, ) }; let delete_transfer_button_callback = { let main_state = main_state.clone(); let main_dispatch = main_dispatch.clone(); let ct_state = ct_state.clone(); let new_transfer_button_callback = new_transfer_button_callback.clone(); transfer_menu_callbacks::delete_transfer_button_callback( main_state, main_dispatch, ct_state, new_transfer_button_callback, ) }; html! {
// Anything below here is not rendered when a Custom transfer is selected if !matches!(&ct_state.transfer.transfer_region.source_region, Region::Custom(_)) {

{"Source Interleave "}

{"Destination Interleave "}

}
} } #[derive(PartialEq, Eq, Debug, Clone, Default, Serialize, Deserialize)] 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 { type Error = &'static str; fn try_from(value: String) -> Result { lazy_static! { static ref REGION_REGEX: Regex = Regex::new(r"([A-Z]+)(\d+):([A-Z]+)(\d+)").unwrap(); } if let Some(captures) = REGION_REGEX.captures(&value) { if captures.len() != 5 { return Err("Not enough capture groups"); } let col_start = letters_to_num(&captures[1]).ok_or("Column start failed to parse")?; let col_end = letters_to_num(&captures[3]).ok_or("Column end failed to parse")?; let row_start: u8 = captures[2] .parse::() .or(Err("Row start failed to parse"))?; let row_end: u8 = captures[4] .parse::() .or(Err("Row end failed to parse"))?; Ok(RegionDisplay { text: value, col_start, row_start, col_end, row_end, }) } else { Err("Regex match failed") } } } impl TryFrom<&str> for RegionDisplay { type Error = &'static str; fn try_from(value: &str) -> Result { lazy_static! { static ref REGION_REGEX: Regex = Regex::new(r"([A-Z]+)(\d+):([A-Z]+)(\d+)").unwrap(); } if let Some(captures) = REGION_REGEX.captures(value) { if captures.len() != 5 { return Err("Not enough capture groups"); } let col_start = letters_to_num(&captures[1]).ok_or("Column start failed to parse")?; let col_end = letters_to_num(&captures[3]).ok_or("Column end failed to parse")?; let row_start: u8 = captures[2] .parse::() .or(Err("Row start failed to parse"))?; let row_end: u8 = captures[4] .parse::() .or(Err("Row end failed to parse"))?; Ok(RegionDisplay { text: value.to_string(), col_start, row_start, col_end, row_end, }) } else { Err("Regex match failed") } } } impl From<&Region> for RegionDisplay { fn from(value: &Region) -> Self { match *value { Region::Point((col, row)) => { RegionDisplay::try_from((col, row, col, row)).ok().unwrap() } 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, }, } } } 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; fn try_from(value: (u8, u8, u8, u8)) -> Result { // (Column Start, Row Start, Column End, Row End) // This can only possibly fail if one of the coordinates is zero... let cs = num_to_letters(value.0).ok_or("Column start failed to parse")?; let ce = num_to_letters(value.2).ok_or("Column end failed to parse")?; Ok(RegionDisplay { text: format!("{}{}:{}{}", cs, value.1, ce, value.3), col_start: value.0, row_start: value.1, col_end: value.2, row_end: value.3, }) } } #[cfg(test)] mod tests { use wasm_bindgen_test::*; use super::*; #[test] #[wasm_bindgen_test] fn test_try_from_string_for_regiondisplay() { let desired = RegionDisplay { text: "A1:E5".to_string(), row_start: 1, row_end: 5, col_start: 1, col_end: 5, }; assert_eq!(desired, "A1:E5".to_string().try_into().unwrap()); } }