From bd0982f821a0f8d4cd5d1128f4e1c72e88876831 Mon Sep 17 00:00:00 2001 From: Aaron Fenyes Date: Fri, 27 Sep 2024 14:33:49 -0700 Subject: [PATCH] AddRemove: make a button that adds elements In the process, switch selection storage back to `FxHashSet`, reverting commit b3afd6f. --- app-proto/full-interface/Cargo.toml | 1 + app-proto/full-interface/src/add_remove.rs | 68 +++++++++++++--------- app-proto/full-interface/src/assembly.rs | 33 ++++++++++- app-proto/full-interface/src/main.rs | 5 +- 4 files changed, 74 insertions(+), 33 deletions(-) diff --git a/app-proto/full-interface/Cargo.toml b/app-proto/full-interface/Cargo.toml index 7640b07..920469a 100644 --- a/app-proto/full-interface/Cargo.toml +++ b/app-proto/full-interface/Cargo.toml @@ -11,6 +11,7 @@ default = ["console_error_panic_hook"] itertools = "0.13.0" js-sys = "0.3.70" nalgebra = "0.33.0" +rustc-hash = "2.0.0" slab = "0.4.9" sycamore = "0.9.0-beta.3" diff --git a/app-proto/full-interface/src/add_remove.rs b/app-proto/full-interface/src/add_remove.rs index e0ecf0f..f93f31f 100644 --- a/app-proto/full-interface/src/add_remove.rs +++ b/app-proto/full-interface/src/add_remove.rs @@ -6,16 +6,51 @@ use crate::Constraint; #[component] pub fn AddRemove() -> View { - let state = use_context::(); - view! { div(id="add-remove") { button( - on:click=move |_| { + on:click=|_| { + let state = use_context::(); + state.assembly.insert_new_element(); + + /* DEBUG */ + // print updated list of elements by identifier + console::log_1(&JsValue::from("elements by identifier:")); + for (id, key) in state.assembly.elements_by_id.get_clone().iter() { + console::log_3( + &JsValue::from(" "), + &JsValue::from(id), + &JsValue::from(*key) + ); + } + } + ) { "+" } + button( + disabled={ + let state = use_context::(); + state.selection.with(|sel| sel.len() != 2) + }, + on:click=|_| { + let state = use_context::(); + let args = state.selection.with( + |sel| { + let arg_vec: Vec<_> = sel.into_iter().collect(); + (arg_vec[0].clone(), arg_vec[1].clone()) + } + ); + state.assembly.insert_constraint(Constraint { + args: args, + rep: 0.0 + }); + state.selection.update(|sel| sel.clear()); + + /* DEBUG */ + // print updated constraint list console::log_1(&JsValue::from("constraints:")); state.assembly.constraints.with(|csts| { for (_, cst) in csts.into_iter() { - console::log_4( + console::log_5( + &JsValue::from(" "), &JsValue::from(cst.args.0), &JsValue::from(cst.args.1), &JsValue::from(":"), @@ -24,31 +59,6 @@ pub fn AddRemove() -> View { } }); } - ) { "+" } - button( - disabled={ - state.selection.with(|sel| sel.len() != 2) - }, - on:click=move |_| { - let args = state.selection.with( - |sel| { - let arg_vec: Vec<_> = sel.into_iter().collect(); - (arg_vec[0].clone(), arg_vec[1].clone()) - } - ); - console::log_5( - &JsValue::from("add constraint"), - &JsValue::from(args.0), - &JsValue::from(args.1), - &JsValue::from(":"), - &JsValue::from(0.0) - ); - state.assembly.insert_constraint(Constraint { - args: args, - rep: 0.0 - }); - state.selection.update(|sel| sel.clear()); - } ) { "🔗" } } } diff --git a/app-proto/full-interface/src/assembly.rs b/app-proto/full-interface/src/assembly.rs index 1d0a6f8..aa4355e 100644 --- a/app-proto/full-interface/src/assembly.rs +++ b/app-proto/full-interface/src/assembly.rs @@ -1,4 +1,5 @@ use nalgebra::DVector; +use rustc_hash::FxHashMap; use slab::Slab; use std::collections::BTreeSet; use sycamore::prelude::*; @@ -21,18 +22,46 @@ pub struct Constraint { // a complete, view-independent description of an assembly #[derive(Clone)] pub struct Assembly { + // elements and constraints pub elements: Signal>, - pub constraints: Signal> + pub constraints: Signal>, + + // indexing + pub elements_by_id: Signal> } impl Assembly { pub fn new() -> Assembly { Assembly { elements: create_signal(Slab::new()), - constraints: create_signal(Slab::new()) + constraints: create_signal(Slab::new()), + elements_by_id: create_signal(FxHashMap::default()) } } + pub fn insert_new_element(&self) { + // find the next unused identifier in the default sequence + let mut id_num = 1; + let mut id = format!("sphere{}", id_num); + while self.elements_by_id.with( + |elts_by_id| elts_by_id.contains_key(&id) + ) { + id_num += 1; + id = format!("sphere{}", id_num); + } + + // create and insert a new element + let elt = Element { + id: id.clone(), + label: format!("Sphere {}", id_num), + color: [0.75_f32, 0.75_f32, 0.75_f32], + rep: DVector::::from_column_slice(&[0.0, 0.0, 0.0, 0.5, -0.5]), + constraints: BTreeSet::default() + }; + let key = self.elements.update(|elts| elts.insert(elt)); + self.elements_by_id.update(|elts_by_id| elts_by_id.insert(id, key)); + } + pub fn insert_constraint(&self, constraint: Constraint) { let args = constraint.args; let key = self.constraints.update(|csts| csts.insert(constraint)); diff --git a/app-proto/full-interface/src/main.rs b/app-proto/full-interface/src/main.rs index 87e06db..e867ad3 100644 --- a/app-proto/full-interface/src/main.rs +++ b/app-proto/full-interface/src/main.rs @@ -4,6 +4,7 @@ mod display; mod outline; use nalgebra::DVector; +use rustc_hash::FxHashSet; use std::collections::BTreeSet; use sycamore::prelude::*; @@ -15,14 +16,14 @@ use outline::Outline; #[derive(Clone)] struct AppState { assembly: Assembly, - selection: Signal> + selection: Signal> } impl AppState { fn new() -> AppState { AppState { assembly: Assembly::new(), - selection: create_signal(BTreeSet::default()) + selection: create_signal(FxHashSet::default()) } } }