2024-09-13 07:07:49 +00:00
|
|
|
use itertools::Itertools;
|
2024-09-12 22:24:41 +00:00
|
|
|
use sycamore::{prelude::*, web::tags::div};
|
2024-09-20 00:53:07 +00:00
|
|
|
use web_sys::{KeyboardEvent, MouseEvent};
|
2024-09-12 22:24:41 +00:00
|
|
|
|
2024-09-13 22:15:55 +00:00
|
|
|
use crate::AppState;
|
2024-09-12 22:24:41 +00:00
|
|
|
|
|
|
|
#[component]
|
2024-09-13 22:15:55 +00:00
|
|
|
pub fn Outline() -> View {
|
2024-09-13 07:07:49 +00:00
|
|
|
// sort the elements alphabetically by ID
|
2024-09-19 23:08:55 +00:00
|
|
|
let elements_sorted = create_memo(|| {
|
|
|
|
let state = use_context::<AppState>();
|
2024-09-13 07:40:34 +00:00
|
|
|
state.assembly.elements
|
2024-09-13 07:07:49 +00:00
|
|
|
.get_clone()
|
|
|
|
.into_iter()
|
2024-09-19 23:08:55 +00:00
|
|
|
.map(|(_, elt)| elt)
|
2024-09-22 09:21:45 +00:00
|
|
|
.sorted_by_key(|elt| elt.id.clone())
|
2024-09-13 07:07:49 +00:00
|
|
|
.collect()
|
2024-09-19 23:08:55 +00:00
|
|
|
});
|
2024-09-13 07:07:49 +00:00
|
|
|
|
2024-09-12 22:24:41 +00:00
|
|
|
view! {
|
2024-09-20 00:53:07 +00:00
|
|
|
ul(
|
|
|
|
on:click={
|
|
|
|
let state = use_context::<AppState>();
|
|
|
|
move |_| state.selection.update(|sel| sel.clear())
|
|
|
|
}
|
|
|
|
) {
|
2024-09-12 22:24:41 +00:00
|
|
|
Keyed(
|
2024-09-13 07:07:49 +00:00
|
|
|
list=elements_sorted,
|
2024-09-12 22:24:41 +00:00
|
|
|
view=|elt| {
|
2024-09-19 23:08:55 +00:00
|
|
|
let state = use_context::<AppState>();
|
|
|
|
let class = create_memo({
|
|
|
|
move || {
|
2024-09-22 09:21:45 +00:00
|
|
|
if state.selection.with(|sel| sel.contains(&elt.key)) {
|
2024-09-19 23:08:55 +00:00
|
|
|
"selected"
|
|
|
|
} else {
|
|
|
|
""
|
|
|
|
}
|
|
|
|
}
|
|
|
|
});
|
2024-09-13 05:36:54 +00:00
|
|
|
let label = elt.label.clone();
|
2024-09-13 07:43:19 +00:00
|
|
|
let rep_components = elt.rep.iter().map(|u| {
|
|
|
|
let u_coord = u.to_string().replace("-", "\u{2212}");
|
|
|
|
View::from(div().children(u_coord))
|
|
|
|
}).collect::<Vec<_>>();
|
2024-09-12 22:24:41 +00:00
|
|
|
view! {
|
2024-09-13 21:53:12 +00:00
|
|
|
/* [TO DO] switch to integer-valued parameters whenever
|
|
|
|
that becomes possible again */
|
2024-09-16 18:29:44 +00:00
|
|
|
li(
|
|
|
|
class=class.get(),
|
|
|
|
tabindex="0",
|
2024-09-19 23:08:55 +00:00
|
|
|
on:click={
|
2024-09-20 00:53:07 +00:00
|
|
|
move |event: MouseEvent| {
|
|
|
|
if event.shift_key() {
|
|
|
|
state.selection.update(|sel| {
|
2024-09-22 09:21:45 +00:00
|
|
|
if !sel.remove(&elt.key) {
|
|
|
|
sel.insert(elt.key);
|
2024-09-20 00:53:07 +00:00
|
|
|
}
|
|
|
|
});
|
|
|
|
} else {
|
|
|
|
state.selection.update(|sel| {
|
|
|
|
sel.clear();
|
2024-09-22 09:21:45 +00:00
|
|
|
sel.insert(elt.key);
|
2024-09-20 00:53:07 +00:00
|
|
|
});
|
|
|
|
}
|
|
|
|
event.stop_propagation();
|
2024-09-19 23:08:55 +00:00
|
|
|
}
|
2024-09-16 18:29:44 +00:00
|
|
|
},
|
2024-09-19 23:08:55 +00:00
|
|
|
on:keydown={
|
|
|
|
move |event: KeyboardEvent| {
|
|
|
|
if event.key() == "Enter" {
|
2024-09-20 00:53:07 +00:00
|
|
|
if event.shift_key() {
|
|
|
|
state.selection.update(|sel| {
|
2024-09-22 09:21:45 +00:00
|
|
|
if !sel.remove(&elt.key) {
|
|
|
|
sel.insert(elt.key);
|
2024-09-20 00:53:07 +00:00
|
|
|
}
|
|
|
|
});
|
|
|
|
} else {
|
|
|
|
state.selection.update(|sel| {
|
|
|
|
sel.clear();
|
2024-09-22 09:21:45 +00:00
|
|
|
sel.insert(elt.key);
|
2024-09-20 00:53:07 +00:00
|
|
|
});
|
|
|
|
}
|
2024-09-19 23:08:55 +00:00
|
|
|
event.prevent_default();
|
|
|
|
}
|
2024-09-16 18:29:44 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
) {
|
2024-09-13 05:36:54 +00:00
|
|
|
div(class="elt-label") { (label) }
|
2024-09-12 22:24:41 +00:00
|
|
|
div(class="elt-rep") { (rep_components) }
|
|
|
|
}
|
|
|
|
}
|
|
|
|
},
|
2024-09-22 09:21:45 +00:00
|
|
|
key=|elt| elt.key
|
2024-09-12 22:24:41 +00:00
|
|
|
)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|