game-of-life-gui/src/factory/cell.rs

110 lines
3.2 KiB
Rust

use mossfets_game_of_life::game::Coord;
use relm4::factory::Position;
use relm4::factory::positions::GridPosition;
use relm4::prelude::{FactoryComponent, DynamicIndex};
use relm4::{gtk, RelmWidgetExt};
use adw::prelude::{AccessibleExtManual, WidgetExt};
use gtk::prelude::ButtonExt;
use crate::app::AppMsg;
/// A cell being rendered to the grid. The coordinates are in grid space.
#[derive(Debug)]
pub struct Cell {
coordinate: (isize, isize),
pub value: bool,
}
impl Cell {
pub fn get_coordinate(&self) -> &(isize, isize) {
&(self.coordinate)
}
pub fn new(coordinate: (isize, isize), value: bool) -> Self {
Self {
coordinate,
value
}
}
}
#[derive(Debug)]
pub enum CellMsg {}
#[derive(Debug)]
pub enum CellOutput {
ChangeAtGridSpacePoint(Coord),
}
#[relm4::factory(pub)]
impl FactoryComponent for Cell {
type Init = (Coord, bool);
type Input = CellMsg;
type Output = CellOutput;
type CommandOutput = ();
type Widgets = FactoryWidgets;
type ParentInput = AppMsg;
//type Factory = FactoryVec<Self>;
//type Root = gtk::AspectFrame;
type ParentWidget = gtk::Grid;
// A grid cell
view! {
root = gtk::AspectFrame {
set_ratio: 10.0,
#[wrap(Some)]
#[name = "button"]
set_child = &gtk::Button {
connect_clicked[sender, coord = self.coordinate] => move |_| {
sender.output(CellOutput::ChangeAtGridSpacePoint(coord));
},
set_hexpand: true,
set_vexpand: true,
set_class_active: ("cell", true),
#[watch]
update_property: &[gtk::accessible::Property::Description(
&format!(
"Cell {} {} {}",
self.coordinate.0,
self.coordinate.1,
if self.value { "live" } else { "dead" }
)
)],
// Set the CSS "live" class to whether the cell is live, and update appropriately
#[watch]
set_class_active: ("live", self.value),
},
}
}
fn init_model(init: Self::Init, _index: &DynamicIndex, _sender: relm4::FactorySender<Self>) -> Self {
let (coordinate, value) = init;
Self { coordinate, value }
}
fn output_to_parent_input(output: Self::Output) -> Option<Self::ParentInput> {
Some(match output {
CellOutput::ChangeAtGridSpacePoint(coordinate) => AppMsg::ChangeAtGridSpacePoint(coordinate),
})
}
/*fn view (
&self,
_key: &<Self::Factory as relm4::factory::Factory<Self, Self::View>>::Key,
widgets: &Self::Widgets,
) {
// The "live" CSS class makes the cell appear white.
widgets.button.child().unwrap().set_class_active("live", self.value)
}*/
}
impl Position<GridPosition> for Cell {
fn position(&self, _index: usize) -> GridPosition {
GridPosition {
column: self.coordinate.0 as i32,
row: self.coordinate.1 as i32,
width: 1,
height: 1,
}
}
}