110 lines
3.2 KiB
Rust
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 = >k::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,
|
|
}
|
|
}
|
|
}
|