clear_selected_vars, select_vars, selected_vars
This commit is contained in:
parent
d078f3a470
commit
0cd6dce47c
|
@ -3,6 +3,7 @@ use std::cell::Cell;
|
|||
use std::mem;
|
||||
use std::ops::Not;
|
||||
use std::rc::Rc;
|
||||
use std::sync::Arc;
|
||||
use wellen::GetItem;
|
||||
use zoon::*;
|
||||
|
||||
|
@ -32,7 +33,7 @@ struct ScopeForUI {
|
|||
#[derive(Clone)]
|
||||
pub struct ControlsPanel {
|
||||
selected_scope_ref: Mutable<Option<wellen::ScopeRef>>,
|
||||
hierarchy: Mutable<Option<Rc<wellen::Hierarchy>>>,
|
||||
hierarchy: Mutable<Option<Arc<wellen::Hierarchy>>>,
|
||||
selected_var_refs: MutableVec<wellen::VarRef>,
|
||||
layout: Mutable<Layout>,
|
||||
loaded_filename: Mutable<Option<Filename>>,
|
||||
|
@ -40,7 +41,7 @@ pub struct ControlsPanel {
|
|||
|
||||
impl ControlsPanel {
|
||||
pub fn new(
|
||||
hierarchy: Mutable<Option<Rc<wellen::Hierarchy>>>,
|
||||
hierarchy: Mutable<Option<Arc<wellen::Hierarchy>>>,
|
||||
selected_var_refs: MutableVec<wellen::VarRef>,
|
||||
layout: Mutable<Layout>,
|
||||
loaded_filename: Mutable<Option<Filename>>,
|
||||
|
@ -114,7 +115,7 @@ impl ControlsPanel {
|
|||
))
|
||||
}
|
||||
|
||||
fn scopes_panel(&self, hierarchy: Rc<wellen::Hierarchy>) -> impl Element {
|
||||
fn scopes_panel(&self, hierarchy: Arc<wellen::Hierarchy>) -> impl Element {
|
||||
Column::new()
|
||||
.s(Height::fill())
|
||||
.s(Scrollbars::y_and_clip_x())
|
||||
|
@ -129,7 +130,7 @@ impl ControlsPanel {
|
|||
.item(self.scopes_list(hierarchy))
|
||||
}
|
||||
|
||||
fn scopes_list(&self, hierarchy: Rc<wellen::Hierarchy>) -> impl Element {
|
||||
fn scopes_list(&self, hierarchy: Arc<wellen::Hierarchy>) -> impl Element {
|
||||
let layout = self.layout.clone();
|
||||
let mut scopes_for_ui = Vec::new();
|
||||
let mut max_level_index: usize = 0;
|
||||
|
@ -379,7 +380,7 @@ impl ControlsPanel {
|
|||
.label(scope_for_ui.name)
|
||||
}
|
||||
|
||||
fn vars_panel(&self, hierarchy: Rc<wellen::Hierarchy>) -> impl Element {
|
||||
fn vars_panel(&self, hierarchy: Arc<wellen::Hierarchy>) -> impl Element {
|
||||
let selected_scope_ref = self.selected_scope_ref.clone();
|
||||
Column::new()
|
||||
.s(Align::new().top())
|
||||
|
@ -401,7 +402,7 @@ impl ControlsPanel {
|
|||
fn vars_list(
|
||||
&self,
|
||||
selected_scope_ref: wellen::ScopeRef,
|
||||
hierarchy: Rc<wellen::Hierarchy>,
|
||||
hierarchy: Arc<wellen::Hierarchy>,
|
||||
) -> impl Element {
|
||||
let vars_for_ui = hierarchy
|
||||
.get(selected_scope_ref)
|
||||
|
|
|
@ -1,16 +1,16 @@
|
|||
use crate::{platform, script_bridge, Filename, Layout};
|
||||
use std::rc::Rc;
|
||||
use std::sync::Arc;
|
||||
use zoon::*;
|
||||
|
||||
pub struct HeaderPanel {
|
||||
hierarchy: Mutable<Option<Rc<wellen::Hierarchy>>>,
|
||||
hierarchy: Mutable<Option<Arc<wellen::Hierarchy>>>,
|
||||
layout: Mutable<Layout>,
|
||||
loaded_filename: Mutable<Option<Filename>>,
|
||||
}
|
||||
|
||||
impl HeaderPanel {
|
||||
pub fn new(
|
||||
hierarchy: Mutable<Option<Rc<wellen::Hierarchy>>>,
|
||||
hierarchy: Mutable<Option<Arc<wellen::Hierarchy>>>,
|
||||
layout: Mutable<Layout>,
|
||||
loaded_filename: Mutable<Option<Filename>>,
|
||||
) -> impl Element {
|
||||
|
@ -68,7 +68,7 @@ impl HeaderPanel {
|
|||
Task::start(async move {
|
||||
if let Some(filename) = platform::pick_and_load_waveform(None).await {
|
||||
loaded_filename.set_neq(Some(filename));
|
||||
hierarchy.set(Some(Rc::new(platform::get_hierarchy().await)))
|
||||
hierarchy.set(Some(Arc::new(platform::get_hierarchy().await)))
|
||||
}
|
||||
})
|
||||
})
|
||||
|
@ -267,22 +267,30 @@ impl HeaderPanel {
|
|||
.family([FontFamily::new("Courier New"), FontFamily::Monospace]))
|
||||
.s(Scrollbars::both())
|
||||
.s(Height::default().max(100))
|
||||
.child_signal(command_result.signal_ref(|result| match result {
|
||||
Some(Ok(js_value)) => {
|
||||
if let Some(string_value) = js_value.as_string() {
|
||||
string_value
|
||||
} else if let Some(number_value) = js_value.as_f64() {
|
||||
number_value.to_string()
|
||||
} else if let Some(bool_value) = js_value.as_bool() {
|
||||
bool_value.to_string()
|
||||
} else {
|
||||
format!("{js_value:?}")
|
||||
.child_signal(command_result.signal_ref(|result| {
|
||||
fn format_complex_js_value(js_value: &JsValue) -> String {
|
||||
let value = format!("{js_value:?}");
|
||||
let value = value.strip_prefix("JsValue(").unwrap_throw();
|
||||
let value = value.strip_suffix(')').unwrap_throw();
|
||||
value.to_owned()
|
||||
}
|
||||
match result {
|
||||
Some(Ok(js_value)) => {
|
||||
if let Some(string_value) = js_value.as_string() {
|
||||
string_value
|
||||
} else if let Some(number_value) = js_value.as_f64() {
|
||||
number_value.to_string()
|
||||
} else if let Some(bool_value) = js_value.as_bool() {
|
||||
bool_value.to_string()
|
||||
} else {
|
||||
format_complex_js_value(js_value)
|
||||
}
|
||||
}
|
||||
Some(Err(js_value)) => {
|
||||
format!("ERROR: {}", format_complex_js_value(js_value))
|
||||
}
|
||||
None => "-".to_owned(),
|
||||
}
|
||||
Some(Err(js_value)) => {
|
||||
format!("Error: {js_value:?}")
|
||||
}
|
||||
None => "-".to_owned(),
|
||||
}))
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
use std::rc::Rc;
|
||||
use std::sync::Arc;
|
||||
use zoon::*;
|
||||
|
||||
mod platform;
|
||||
|
@ -25,6 +25,7 @@ type Filename = String;
|
|||
#[derive(Default)]
|
||||
struct Store {
|
||||
selected_var_refs: MutableVec<wellen::VarRef>,
|
||||
hierarchy: Mutable<Option<Arc<wellen::Hierarchy>>>,
|
||||
}
|
||||
|
||||
static STORE: Lazy<Store> = lazy::default();
|
||||
|
@ -39,7 +40,7 @@ fn main() {
|
|||
}
|
||||
|
||||
fn root() -> impl Element {
|
||||
let hierarchy: Mutable<Option<Rc<wellen::Hierarchy>>> = <_>::default();
|
||||
let hierarchy = STORE.hierarchy.clone();
|
||||
let selected_var_refs = STORE.selected_var_refs.clone();
|
||||
let layout: Mutable<Layout> = <_>::default();
|
||||
let loaded_filename: Mutable<Option<Filename>> = <_>::default();
|
||||
|
|
|
@ -1,6 +1,9 @@
|
|||
use crate::STORE;
|
||||
use wellen::GetItem;
|
||||
use zoon::*;
|
||||
|
||||
type FullVarName = String;
|
||||
|
||||
#[wasm_bindgen(
|
||||
inline_js = r#"export function strict_eval(code) { "use strict"; return eval?.(`${code}`) }"#
|
||||
)]
|
||||
|
@ -14,14 +17,53 @@ pub struct FW;
|
|||
|
||||
#[wasm_bindgen]
|
||||
impl FW {
|
||||
/// JS: `FW.say_hello()` -> `Hello!`
|
||||
pub fn say_hello() -> String {
|
||||
"Hello!".to_owned()
|
||||
}
|
||||
|
||||
pub fn clear_variables() -> String {
|
||||
/// JS: `FW.clear_selected_vars()` -> `4`
|
||||
pub fn clear_selected_vars() -> usize {
|
||||
let mut vars = STORE.selected_var_refs.lock_mut();
|
||||
let var_count = vars.len();
|
||||
vars.clear();
|
||||
format!("{var_count} variables cleared")
|
||||
var_count
|
||||
}
|
||||
|
||||
/// JS: `FW.select_vars(["simple_tb.s.A", "simple_tb.s.B"])` -> `2`
|
||||
pub fn select_vars(full_var_names: Vec<FullVarName>) -> usize {
|
||||
if let Some(hierarchy) = STORE.hierarchy.get_cloned() {
|
||||
let mut new_var_refs = Vec::new();
|
||||
for full_var_name in full_var_names {
|
||||
let path_with_name = full_var_name.split_terminator('.').collect::<Vec<_>>();
|
||||
if let Some((name, path)) = path_with_name.split_last() {
|
||||
if let Some(var_ref) = hierarchy.lookup_var(path, name) {
|
||||
new_var_refs.push(var_ref);
|
||||
}
|
||||
}
|
||||
}
|
||||
let var_ref_count = new_var_refs.len();
|
||||
STORE.selected_var_refs.lock_mut().replace(new_var_refs);
|
||||
return var_ref_count;
|
||||
}
|
||||
0
|
||||
}
|
||||
|
||||
pub fn loaded_filename() -> String {
|
||||
format!("todo loaded filename")
|
||||
}
|
||||
|
||||
/// JS: `FW.selected_vars()` -> `["simple_tb.s.A", "simple_tb.s.B"]`
|
||||
pub fn selected_vars() -> Vec<FullVarName> {
|
||||
if let Some(hierarchy) = STORE.hierarchy.get_cloned() {
|
||||
let mut full_var_names = Vec::new();
|
||||
for var_ref in STORE.selected_var_refs.lock_ref().as_slice() {
|
||||
let var = hierarchy.get(*var_ref);
|
||||
let var_name = var.full_name(&hierarchy);
|
||||
full_var_names.push(var_name);
|
||||
}
|
||||
return full_var_names;
|
||||
}
|
||||
Vec::new()
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
use crate::platform;
|
||||
use std::rc::Rc;
|
||||
use std::sync::Arc;
|
||||
use wellen::GetItem;
|
||||
use zoon::*;
|
||||
|
||||
|
@ -12,13 +12,13 @@ const ROW_GAP: u32 = 4;
|
|||
#[derive(Clone)]
|
||||
pub struct WaveformPanel {
|
||||
selected_var_refs: MutableVec<wellen::VarRef>,
|
||||
hierarchy: Mutable<Option<Rc<wellen::Hierarchy>>>,
|
||||
hierarchy: Mutable<Option<Arc<wellen::Hierarchy>>>,
|
||||
canvas_controller: Mutable<ReadOnlyMutable<Option<PixiController>>>,
|
||||
}
|
||||
|
||||
impl WaveformPanel {
|
||||
pub fn new(
|
||||
hierarchy: Mutable<Option<Rc<wellen::Hierarchy>>>,
|
||||
hierarchy: Mutable<Option<Arc<wellen::Hierarchy>>>,
|
||||
selected_var_refs: MutableVec<wellen::VarRef>,
|
||||
) -> impl Element {
|
||||
Self {
|
||||
|
@ -111,7 +111,7 @@ impl WaveformPanel {
|
|||
|
||||
async fn push_var(
|
||||
controller: &PixiController,
|
||||
hierarchy: &Mutable<Option<Rc<wellen::Hierarchy>>>,
|
||||
hierarchy: &Mutable<Option<Arc<wellen::Hierarchy>>>,
|
||||
var_ref: wellen::VarRef,
|
||||
) {
|
||||
let hierarchy = hierarchy.get_cloned().unwrap();
|
||||
|
|
|
@ -35316,10 +35316,12 @@ var VarSignalRow = class {
|
|||
this.draw();
|
||||
}
|
||||
draw() {
|
||||
if (this.app === null || this.app.screen === null) {
|
||||
if (this?.app?.screen?.width === void 0) {
|
||||
return;
|
||||
}
|
||||
this.row_container_background.width = this.app.screen.width;
|
||||
if (this?.row_container_background?._texture?.orig?.width !== void 0) {
|
||||
this.row_container_background.width = this.app.screen.width;
|
||||
}
|
||||
this.signal_blocks_container.removeChildren();
|
||||
this.timeline.blocks.forEach((timeline_block) => {
|
||||
const signal_block = new Container();
|
||||
|
|
|
@ -275,12 +275,14 @@ class VarSignalRow {
|
|||
|
||||
draw() {
|
||||
// Screen can be null when we are, for instance, switching between miller columns and tree layout
|
||||
// and then the canvas has to be recreated
|
||||
if (this.app === null || this.app.screen === null) {
|
||||
// and then the canvas has to be recreated.
|
||||
if (this?.app?.screen?.width === undefined) {
|
||||
return;
|
||||
}
|
||||
|
||||
this.row_container_background.width = this.app.screen.width;
|
||||
// Workaround for "TypeError: Cannot read properties of null (reading 'orig')"
|
||||
if (this?.row_container_background?._texture?.orig?.width !== undefined) {
|
||||
this.row_container_background.width = this.app.screen.width;
|
||||
}
|
||||
|
||||
// @TODO optimize by reusing a pool of blocks instead or removing all children on every redraw?
|
||||
this.signal_blocks_container.removeChildren();
|
||||
|
|
Loading…
Reference in a new issue