Moved matrix yew components to file matrix.rs, minor refactoring

This commit is contained in:
Egor 2024-05-25 02:30:16 +03:00
parent 881236c725
commit f53170b16b
2 changed files with 119 additions and 94 deletions

View file

@ -1,98 +1,7 @@
use math::matrix::Matrix; mod matrix;
use yew::prelude::*; use yew::prelude::*;
use matrix::MatrixComponent;
pub struct MatrixComponent {
matrix: Matrix<f64>
}
pub enum MatrixMsg {
CellChange(Cell),
AddRow,
AddColumn,
RemoveRow,
RemoveColumn
}
impl Component for MatrixComponent {
type Message = MatrixMsg;
type Properties = ();
fn create(_ctx: &Context<Self>) -> Self {
Self { matrix: Matrix::new_zeroes(3, 3) }
}
fn update(&mut self, _ctx: &Context<Self>, msg: Self::Message) -> bool {
match msg {
MatrixMsg::CellChange(cell) => self.matrix[cell.i][cell.j] = cell.value,
MatrixMsg::AddRow => self.matrix.append_row_zeroes(),
MatrixMsg::AddColumn => self.matrix.append_column_zeroes(),
MatrixMsg::RemoveRow => (),
MatrixMsg::RemoveColumn => ()
}
return true;
}
fn view(&self, ctx: &Context<Self>) -> Html {
let on_cell_change = ctx.link().callback(MatrixMsg::CellChange);
let on_click_add_row = ctx.link().callback(|_| MatrixMsg::AddRow);
let on_click_add_column = ctx.link().callback(|_| MatrixMsg::AddColumn);
html! {
<div class={classes!("matrix")}>
<table> {
self.matrix.iter_rows().enumerate().map(|(i, row)| html! {
<tr> {
row.iter().enumerate().map(|(j, e)| {
let cell = Cell { i, j, value: *e };
html! {
<td>
<MatrixCellComponent cell={cell} on_cell_change={on_cell_change.clone()} />
</td>
}
}).collect::<Html>()
}
</tr>
}).collect::<Html>()
}
</table>
<button onclick={on_click_add_row}>{"Add row"}</button>
<button onclick={on_click_add_column}>{"Add column"}</button>
</div>
}
}
}
pub struct MatrixCellComponent;
#[derive(PartialEq, Properties)]
pub struct MatrixCellProps {
pub cell: Cell,
pub on_cell_change: Callback<Cell>
}
#[derive(PartialEq, Clone, Copy)]
pub struct Cell {
i: usize, j: usize, value: f64
}
impl Component for MatrixCellComponent {
type Message = ();
type Properties = MatrixCellProps;
fn create(_ctx: &Context<Self>) -> Self {
Self
}
fn view(&self, ctx: &Context<Self>) -> Html {
let cell = ctx.props().cell.clone();
let oninput = ctx.props().on_cell_change
.reform(move |e: InputEvent|
Cell { i: cell.i, j: cell.j, value: e.as_f64().unwrap_or_default() }
);
html! {
<input type="text" {oninput}/>
}
}
}
#[function_component] #[function_component]
fn App() -> Html { fn App() -> Html {

116
web/src/matrix.rs Normal file
View file

@ -0,0 +1,116 @@
use math::matrix::Matrix;
use yew::prelude::*;
pub enum MatrixMsg {
CellChange(Cell),
AddRow,
AddColumn,
RemoveRow,
RemoveColumn
}
pub struct MatrixComponent {
matrix: Matrix<f64>
}
impl Component for MatrixComponent {
type Message = MatrixMsg;
type Properties = ();
fn create(_ctx: &Context<Self>) -> Self {
Self { matrix: Matrix::new_zeroes(3, 3) }
}
fn update(&mut self, _ctx: &Context<Self>, msg: Self::Message) -> bool {
match msg {
MatrixMsg::CellChange(cell) => self.matrix[cell.i][cell.j] = cell.value,
MatrixMsg::AddRow => self.matrix.append_row_zeroes(),
MatrixMsg::AddColumn => self.matrix.append_column_zeroes(),
MatrixMsg::RemoveRow => {
if self.matrix.height() > 2 {
self.matrix.remove_last_row();
}
},
MatrixMsg::RemoveColumn => {
if self.matrix.width() > 2 {
self.matrix.remove_last_column();
}
}
}
return true;
}
fn view(&self, ctx: &Context<Self>) -> Html {
let on_size_change = ctx.link().callback(|msg| msg);
html! {
<div class={classes!("matrix")}>
<table> {
self.matrix.iter_rows().enumerate().map(|(i, row)| html! {
<tr> {
row.iter().enumerate().map(|(j, e)| {
let cell = Cell { i, j, value: *e };
let on_cell_change = ctx.link().callback(MatrixMsg::CellChange);
html! {
<td>
<MatrixCellComponent {cell} {on_cell_change} />
</td>
}
}).collect::<Html>()
}
</tr>
}).collect::<Html>()
}
</table>
<MatrixSizeControls {on_size_change} />
</div>
}
}
}
#[derive(PartialEq, Properties)]
pub struct MatrixCellProps {
pub cell: Cell,
pub on_cell_change: Callback<Cell>
}
#[derive(PartialEq, Clone, Copy)]
pub struct Cell {
i: usize, j: usize, value: f64
}
#[function_component]
pub fn MatrixCellComponent(props: &MatrixCellProps) -> Html {
let cell = props.cell.clone();
let oninput = props.on_cell_change
.reform(move |e: InputEvent|
Cell { i: cell.i, j: cell.j, value: e.as_f64().unwrap_or_default() }
);
html! {
<input type="text" {oninput}/>
}
}
#[derive(PartialEq, Properties)]
pub struct MatrixSizeControlsProps {
on_size_change: Callback<MatrixMsg>
}
#[function_component]
pub fn MatrixSizeControls(props: &MatrixSizeControlsProps) -> Html {
let on_click_add_row = props.on_size_change.reform(|_| MatrixMsg::AddRow);
let on_click_add_column = props.on_size_change.reform(|_| MatrixMsg::AddColumn);
let on_click_remove_row = props.on_size_change.reform(|_|MatrixMsg::RemoveRow);
let on_click_remove_column = props.on_size_change.reform(|_| MatrixMsg::RemoveColumn);
html! {
<div class={classes!("matrix-size-controls")}>
<div>
<button onclick={on_click_add_row}>{"Add row"}</button>
<button onclick={on_click_remove_row}>{"Remove row"}</button>
</div>
<div>
<button onclick={on_click_add_column}>{"Add column"}</button>
<button onclick={on_click_remove_column}>{"Remove column"}</button>
</div>
</div>
}
}