// TODO: is there a way to put that in the macro itself, or to avoid // putting `..Default::default()` at the end when all parameters exist? #![allow(clippy::needless_update)] use appy::{components::*, hooks::*, types::*, *}; use std::rc::Rc; mod calculator_model; use calculator_model::CalculatorModel; #[derive_component(Default, ComponentBuilder, SnakeFactory)] pub struct Button { on_click: Option<Rc<dyn Fn(char)>>, id: char, } #[function_component] fn _button(props: Button) -> Elements { let hover_state_ref = use_hover_state_ref(); let self_on_click = props.on_click.as_ref().unwrap().clone(); let self_id = props.id.clone(); let on_click = rc_with_clone!([], move || { (self_on_click)(self_id) }); let color = match *hover_state_ref { HoverState::Normal => 0xD58936, HoverState::Hover => 0xDEA260, HoverState::Active => 0xB36F25, }; apx!( <blk left=pct(10) top=pct(10) right=pct(10) bottom=pct(10)> <interaction on_click=on_click hover_state_ref=hover_state_ref/> <bg color=color/> <text text=&*props.id.to_string() size=pct(65) align=Align::Center color=0x000000/> </blk> ) } #[derive_component(Default, ComponentBuilder, SnakeFactory)] pub struct ButtonBg { pub on_click: Option<Rc<dyn Fn()>>, pub normal: u32, pub active: u32, pub hover: u32, } #[function_component] fn _button_bg(props: ButtonBg) -> Elements { let hover_state = use_hover_state_ref(); //println!("state: {:?}",*hover_state); let c = match *hover_state { HoverState::Normal => props.normal, HoverState::Hover => props.hover, HoverState::Active => props.active, }; apx! { <bg color=c/> <interaction on_click=props.on_click.unwrap() hover_state_ref=hover_state/> } } #[main_window] fn app() -> Elements { let model = use_reducer(CalculatorModel::action, CalculatorModel::new); let show_info = use_state(|| false); let on_click = rc_with_clone!([model], move |c: char| { model.dispatch(c); }); let on_info_click = rc_with_clone!([show_info], move || { show_info.set(!*show_info); }); apx!( <blk height=pct(25) top=0> <bg color=0x3C1518/> <blk left=pct(5) right=pct(5)> <text align=Align::Right text=&*model.get_display_value() size=pct(50) color=0xffffff/> </blk> </blk> <blk top=pct(25)> <bg color=0x69140E/> <blk margin=10> <grid rows=5 cols=4> {"C«%/789*456-123+±0.=".chars().into_iter().flat_map(|c| { apx!{ <button id=c on_click=on_click.clone() /> } }).collect()} </grid> </blk> </blk> <blk top=pct(5) left=pct(5) width=pct(10) height=pct(10)> <button_bg normal=0x000000 active=0x404040 hover=0x808080 on_click=on_info_click.clone()/> <text text="i" size=pct(100) align=Align::Center color=0xffffff/> </blk> {if *show_info { apx!( <blk top=pct(10) left=pct(10) right=pct(10) bottom=pct(10)> <bg color=0x102030/> <blk bottom=pct(10) width=pct(50) height=pct(10)> <button_bg normal=0x0000f0 active=0x4040f0 hover=0x8080f0 on_click=on_info_click.clone()/> <text text="Ok" align=Align::Center size=pct(100) color=0xffffff/> </blk> <text text="This is a little calculator..." align=Align::Center size=32 color=0xffffff/> </blk> ) } else {apx!()}} ) }