diff --git a/app-proto/Cargo.toml b/app-proto/Cargo.toml index 04ea271..e5bc05e 100644 --- a/app-proto/Cargo.toml +++ b/app-proto/Cargo.toml @@ -26,6 +26,7 @@ console_error_panic_hook = { version = "0.1.7", optional = true } version = "0.3.69" features = [ 'HtmlCanvasElement', + 'HtmlInputElement', 'Performance', 'WebGl2RenderingContext', 'WebGlBuffer', diff --git a/app-proto/main.css b/app-proto/main.css index bdbacfb..32ae5bf 100644 --- a/app-proto/main.css +++ b/app-proto/main.css @@ -93,7 +93,7 @@ details[open]:has(li) .elt-switch::after { display: flex; } -.elt-rep > div, .cst-rep { +.elt-rep > div { padding: 2px 0px 0px 0px; font-size: 10pt; text-align: center; @@ -104,10 +104,17 @@ details[open]:has(li) .elt-switch::after { font-style: italic; } -.cst > input { +.cst > input[type=checkbox] { margin: 0px 8px 0px 0px; } +.cst > input[type=text] { + color: #fcfcfc; + background-color: inherit; + border: 1px solid #555; + border-radius: 2px; +} + /* display */ canvas { diff --git a/app-proto/src/add_remove.rs b/app-proto/src/add_remove.rs index 7066089..92ae4be 100644 --- a/app-proto/src/add_remove.rs +++ b/app-proto/src/add_remove.rs @@ -214,17 +214,21 @@ pub fn AddRemove() -> View { (arg_vec[0].clone(), arg_vec[1].clone()) } ); + let rep = create_signal(0.0); + let active = create_signal(true); state.assembly.insert_constraint(Constraint { args: args, - rep: 0.0, - active: create_signal(true) + rep: rep, + rep_text: create_signal(String::new()), + rep_valid: create_signal(false), + active: active, }); state.assembly.realize(); state.selection.update(|sel| sel.clear()); /* DEBUG */ // print updated constraint list - console::log_1(&JsValue::from("constraints:")); + console::log_1(&JsValue::from("Constraints:")); state.assembly.constraints.with(|csts| { for (_, cst) in csts.into_iter() { console::log_5( @@ -232,10 +236,23 @@ pub fn AddRemove() -> View { &JsValue::from(cst.args.0), &JsValue::from(cst.args.1), &JsValue::from(":"), - &JsValue::from(cst.rep) + &JsValue::from(cst.rep.get_untracked()) ); } }); + + // update the realization when the constraint activated, or + // edited while active + create_effect(move || { + rep.track(); + console::log_2( + &JsValue::from("Lorentz product updated to"), + &JsValue::from(rep.get_untracked()) + ); + if active.get() { + state.assembly.realize(); + } + }); } ) { "🔗" } select(bind:value=assembly_name) { /* DEBUG */ diff --git a/app-proto/src/assembly.rs b/app-proto/src/assembly.rs index 228357e..0970932 100644 --- a/app-proto/src/assembly.rs +++ b/app-proto/src/assembly.rs @@ -22,7 +22,9 @@ pub struct Element { #[derive(Clone)] pub struct Constraint { pub args: (usize, usize), - pub rep: f64, + pub rep: Signal, + pub rep_text: Signal, + pub rep_valid: Signal, pub active: Signal } @@ -97,7 +99,7 @@ impl Assembly { self.elements.update(|elts| { elts[args.0].constraints.insert(key); elts[args.1].constraints.insert(key); - }) + }); } // --- realization --- @@ -116,10 +118,12 @@ impl Assembly { let mut gram_to_be = PartialMatrix::new(); self.constraints.with_untracked(|csts| { for (_, cst) in csts { - let args = cst.args; - let row = elts[args.0].index; - let col = elts[args.1].index; - gram_to_be.push_sym(row, col, cst.rep); + if cst.active.get_untracked() && cst.rep_valid.get_untracked() { + let args = cst.args; + let row = elts[args.0].index; + let col = elts[args.1].index; + gram_to_be.push_sym(row, col, cst.rep.get_untracked()); + } } }); @@ -142,7 +146,7 @@ impl Assembly { /* DEBUG */ // log the initial configuration matrix - console::log_1(&JsValue::from("old configuration:")); + console::log_1(&JsValue::from("Old configuration:")); for j in 0..guess.nrows() { let mut row_str = String::new(); for k in 0..guess.ncols() { diff --git a/app-proto/src/engine.rs b/app-proto/src/engine.rs index 2971750..2978a9a 100644 --- a/app-proto/src/engine.rs +++ b/app-proto/src/engine.rs @@ -60,7 +60,7 @@ impl PartialMatrix { pub fn log_to_console(&self) { let PartialMatrix(entries) = self; for ent in entries { - let ent_str = format!("{} {} {}", ent.index.0, ent.index.1, ent.value); + let ent_str = format!(" {} {} {}", ent.index.0, ent.index.1, ent.value); console::log_1(&JsValue::from(ent_str.as_str())); } } diff --git a/app-proto/src/outline.rs b/app-proto/src/outline.rs index 4e4de9c..8edbe07 100644 --- a/app-proto/src/outline.rs +++ b/app-proto/src/outline.rs @@ -1,12 +1,40 @@ use itertools::Itertools; use sycamore::{prelude::*, web::tags::div}; -use web_sys::{Element, KeyboardEvent, MouseEvent, wasm_bindgen::JsCast}; +use web_sys::{ + Element, + Event, + HtmlInputElement, + KeyboardEvent, + MouseEvent, + wasm_bindgen::JsCast +}; -use crate::AppState; +use crate::{AppState, assembly::Constraint}; -// this component lists the elements of the assembly, showing the constraints -// on each element as a collapsible sub-list. its implementation is based on -// Kate Morley's HTML + CSS tree views: +// an editable view of the Lorentz product representing a constraint +#[component(inline_props)] +fn LorentzProductInput(constraint: Constraint) -> View { + view! { + input( + r#type="text", + bind:value=constraint.rep_text, + on:change=move |event: Event| { + let target: HtmlInputElement = event.target().unwrap().unchecked_into(); + match target.value().parse::() { + Ok(rep) => batch(|| { + constraint.rep.set(rep); + constraint.rep_valid.set(true); + }), + Err(_) => constraint.rep_valid.set(false) + }; + } + ) + } +} + +// a component that lists the elements of the current assembly, showing the +// constraints on each element as a collapsible sub-list. its implementation +// is based on Kate Morley's HTML + CSS tree views: // // https://iamkate.com/code/tree-views/ // @@ -51,8 +79,6 @@ pub fn Outline() -> View { let constrained = elt.constraints.len() > 0; let details_node = create_node_ref(); view! { - /* [TO DO] switch to integer-valued parameters whenever - that becomes possible again */ li { details(ref=details_node) { summary( @@ -138,7 +164,7 @@ pub fn Outline() -> View { li(class="cst") { input(r#type="checkbox", bind:checked=cst.active) div(class="cst-label") { (other_arg_label) } - div(class="cst-rep") { (cst.rep) } + LorentzProductInput(constraint=cst) } } },