use crate::constants::{COLS, INFO_TEXT_HEIGHT, INFO_TEXT_MAX_ITEMS}; use crate::state::{BoardState, MessageBus, SharedState, Turn}; use std::cell::{Cell, RefCell}; use std::rc::Rc; use yew::prelude::*; pub struct Slot {} pub enum SlotMessage { Press(u8), } #[derive(Clone, PartialEq, Properties)] pub struct SlotProperties { idx: u8, state: Rc>, bus: Rc>, } impl Component for Slot { type Message = SlotMessage; type Properties = SlotProperties; fn create(_ctx: &Context) -> Self { Self {} } fn view(&self, ctx: &Context) -> Html { let idx = ctx.props().idx; let state = match ctx.props().state.as_ref().get() { BoardState::Empty => "open", BoardState::Cyan => "cyan", BoardState::Magenta => "magenta", }; let idx_copy = idx; let onclick = ctx.link().callback(move |_| SlotMessage::Press(idx_copy)); let col = idx % COLS; let row = idx / COLS; html! { } } fn update(&mut self, ctx: &Context, msg: Self::Message) -> bool { match msg { SlotMessage::Press(idx) => { let (shared, _) = ctx .link() .context::(Callback::noop()) .expect("shared to be set"); let result = shared.bus.borrow_mut().push_msg(format!("pressed {idx}")); if let Err(e) = result { log::error!("Error pushing msg to bus: {}", e); } else { // DEBUG //log::info!("Pushed \"pressed {idx}\" msg to bus"); } } } // notify Wrapper with message if let Some(p) = ctx.link().get_parent() { p.clone().downcast::().send_message(()); } true } } pub struct Wrapper {} impl Component for Wrapper { type Message = (); type Properties = (); fn create(_ctx: &Context) -> Self { Self {} } fn view(&self, ctx: &Context) -> Html { let (shared, _) = ctx .link() .context::(Callback::noop()) .expect("state to be set"); html! {
// wrapper } } fn rendered(&mut self, ctx: &Context, _first_render: bool) { let (shared, _) = ctx .link() .context::(Callback::noop()) .expect("state to be set"); while let Some(msg) = shared.bus.borrow_mut().get_next_msg() { let split_str: Vec<&str> = msg.split_whitespace().collect(); if split_str.len() == 2 { if split_str[0] == "pressed" { if let Ok(idx) = split_str[1].parse::() { let output_str: String = format!("Got {idx} pressed."); // DEBUG //log::info!("{}", &output_str); if let Some(info_text) = shared.info_text_ref.cast::() { // create the new text to be appended in the output let window = web_sys::window().expect("no window exists"); let document = window.document().expect("window should have a document"); let p = document .create_element("p") .expect("document should be able to create

"); p.set_text_content(Some(&output_str)); // check if scrolled to top // DEBUG //log::info!( // "pre: scroll top is {}, scroll height is {}", // info_text.scroll_top(), // info_text.scroll_height() //); let at_top: bool = info_text.scroll_top() <= INFO_TEXT_HEIGHT - info_text.scroll_height(); // append text to output info_text .append_with_node_1(&p) .expect("should be able to append to info_text"); while info_text.child_element_count() > INFO_TEXT_MAX_ITEMS { info_text .remove_child(&info_text.first_child().unwrap()) .expect("should be able to limit items in info_text"); } // scroll to bottom only if at bottom // DEBUG //log::info!("at_top is {}", if at_top { "true" } else { "false" }); if at_top { info_text .set_scroll_top(INFO_TEXT_HEIGHT - info_text.scroll_height()); } // DEBUG //log::info!( // "post: scroll top is {}, scroll height is {}", // info_text.scroll_top(), // info_text.scroll_height() //); } else { log::warn!("Failed to get \"info_text\""); } } } } } } fn update(&mut self, _ctx: &Context, _msg: Self::Message) -> bool { true } } #[derive(Clone, Debug, PartialEq, Eq)] pub struct InfoText {} impl Component for InfoText { type Message = (); type Properties = (); fn create(_ctx: &Context) -> Self { Self {} } fn view(&self, ctx: &Context) -> Html { let (shared, _) = ctx .link() .context::(Callback::noop()) .expect("state to be set"); html! {

{"Hello"}
} } }