Compare commits

..

7 Commits

Author SHA1 Message Date
Aaron Fenyes
9c191ae586 Polish log messages 2024-10-30 00:27:16 -07:00
Aaron Fenyes
9e31037e17 Spread web-sys imports over multiple lines 2024-10-30 00:19:44 -07:00
Aaron Fenyes
c2e3c64d4a Remove debug log from Lorentz product input 2024-10-30 00:16:34 -07:00
Aaron Fenyes
76ad4245d5 Factor out Lorentz product input 2024-10-29 23:43:41 -07:00
Aaron Fenyes
a46ef2c8d6 Work around data binding bug in number input
Setting `bind:value` or `bind:valueAsNumber` for a number input seems to
restrict what you can type in it. We work around this by switching to
text inputs for now. We should probably switch back to number inputs if
we can, though, because they let us take advantage of the browser's
parsing and validation.
2024-10-29 22:53:48 -07:00
Aaron Fenyes
e0880d2ad2 Make constraints editable 2024-10-29 22:32:00 -07:00
Aaron Fenyes
e5f4d523f9 Update the realization when a constraint is activated
Sycamore probably has a better way to do this, but this way works for
now.
2024-10-29 13:46:15 -07:00
6 changed files with 77 additions and 22 deletions

View File

@ -26,6 +26,7 @@ console_error_panic_hook = { version = "0.1.7", optional = true }
version = "0.3.69"
features = [
'HtmlCanvasElement',
'HtmlInputElement',
'Performance',
'WebGl2RenderingContext',
'WebGlBuffer',

View File

@ -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 {

View File

@ -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 */

View File

@ -22,7 +22,9 @@ pub struct Element {
#[derive(Clone)]
pub struct Constraint {
pub args: (usize, usize),
pub rep: f64,
pub rep: Signal<f64>,
pub rep_text: Signal<String>,
pub rep_valid: Signal<bool>,
pub active: Signal<bool>
}
@ -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 {
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);
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() {

View File

@ -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::<f64>() {
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)
}
}
},