From d8c1b0abacd4c522c9973f3759877a391b10fc64 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20Kav=C3=ADk?= Date: Thu, 6 Jun 2024 22:45:20 +0200 Subject: [PATCH] signal_to_timeline --- frontend/src/platform.rs | 4 +- frontend/src/platform/browser.rs | 2 +- frontend/src/platform/tauri.rs | 6 +- frontend/src/waveform_panel.rs | 2 +- frontend/typescript/bundles/pixi_canvas.js | 2 +- frontend/typescript/bundles/tauri_glue.js | 4 +- .../typescript/pixi_canvas/pixi_canvas.ts | 3 +- frontend/typescript/tauri_glue/tauri_glue.ts | 4 +- shared/src/lib.rs | 7 +- src-tauri/src/lib.rs | 79 +++++++++++++++++-- 10 files changed, 92 insertions(+), 21 deletions(-) diff --git a/frontend/src/platform.rs b/frontend/src/platform.rs index 141dc8f..b9661dc 100644 --- a/frontend/src/platform.rs +++ b/frontend/src/platform.rs @@ -37,8 +37,8 @@ pub async fn load_and_get_signal(signal_ref: wellen::SignalRef) -> wellen::Signa platform::load_and_get_signal(signal_ref).await } -pub async fn timeline(signal_ref: wellen::SignalRef, screen_width: u32) -> shared::Timeline { - platform::timeline(signal_ref, screen_width).await +pub async fn timeline(signal_ref: wellen::SignalRef, screen_width: u32, block_height: u32) -> shared::Timeline { + platform::timeline(signal_ref, screen_width, block_height).await } pub async fn unload_signal(signal_ref: wellen::SignalRef) { diff --git a/frontend/src/platform/browser.rs b/frontend/src/platform/browser.rs index e7ef4bc..e4a3be6 100644 --- a/frontend/src/platform/browser.rs +++ b/frontend/src/platform/browser.rs @@ -91,7 +91,7 @@ pub(super) async fn load_and_get_signal(signal_ref: wellen::SignalRef) -> wellen serde_json::from_value(serde_json::to_value(signal).unwrap_throw()).unwrap_throw() } -pub(super) async fn timeline(signal_ref: wellen::SignalRef, screen_width: u32) -> shared::Timeline { +pub(super) async fn timeline(signal_ref: wellen::SignalRef, screen_width: u32, block_height: u32) -> shared::Timeline { shared::Timeline { blocks: Vec::new() } } diff --git a/frontend/src/platform/tauri.rs b/frontend/src/platform/tauri.rs index 44737a7..4058965 100644 --- a/frontend/src/platform/tauri.rs +++ b/frontend/src/platform/tauri.rs @@ -30,9 +30,9 @@ pub(super) async fn load_and_get_signal(signal_ref: wellen::SignalRef) -> wellen .unwrap_throw() } -pub(super) async fn timeline(signal_ref: wellen::SignalRef, screen_width: u32) -> shared::Timeline { +pub(super) async fn timeline(signal_ref: wellen::SignalRef, screen_width: u32, block_height: u32) -> shared::Timeline { serde_wasm_bindgen::from_value( - tauri_glue::timeline(signal_ref.index(), screen_width) + tauri_glue::timeline(signal_ref.index(), screen_width, block_height) .await .unwrap_throw(), ) @@ -67,7 +67,7 @@ mod tauri_glue { pub async fn load_and_get_signal(signal_ref_index: usize) -> Result; #[wasm_bindgen(catch)] - pub async fn timeline(signal_ref_index: usize, screen_width: u32) -> Result; + pub async fn timeline(signal_ref_index: usize, screen_width: u32, block_height: u32) -> Result; #[wasm_bindgen(catch)] pub async fn unload_signal(signal_ref_index: usize) -> Result<(), JsValue>; diff --git a/frontend/src/waveform_panel.rs b/frontend/src/waveform_panel.rs index 244cdaa..178774e 100644 --- a/frontend/src/waveform_panel.rs +++ b/frontend/src/waveform_panel.rs @@ -117,7 +117,7 @@ impl WaveformPanel { let var = hierarchy.get(var_ref); let signal_ref = var.signal_ref(); - let timeline = platform::timeline(signal_ref, controller.screen_width()).await; + let timeline = platform::timeline(signal_ref, controller.screen_width(), ROW_HEIGHT).await; // @TODO remove zoon::println!("Timeline in Rust: {timeline:#?}"); diff --git a/frontend/typescript/bundles/pixi_canvas.js b/frontend/typescript/bundles/pixi_canvas.js index 3c527bd..054527f 100644 --- a/frontend/typescript/bundles/pixi_canvas.js +++ b/frontend/typescript/bundles/pixi_canvas.js @@ -35225,7 +35225,7 @@ var VarSignalRow = class { const signal_block = new Container(); signal_block.x = timeline_block.x; this.signal_blocks_container.addChild(signal_block); - const background = new Graphics().roundRect(0, 0, timeline_block.width, this.row_height, 15).fill("SlateBlue"); + const background = new Graphics().roundRect(0, 0, timeline_block.width, timeline_block.height, 15).fill("SlateBlue"); signal_block.addChild(background); if (timeline_block.label !== void 0) { const label = new Text({ text: timeline_block.label.text, style: this.label_style }); diff --git a/frontend/typescript/bundles/tauri_glue.js b/frontend/typescript/bundles/tauri_glue.js index 0030d54..e24fb27 100644 --- a/frontend/typescript/bundles/tauri_glue.js +++ b/frontend/typescript/bundles/tauri_glue.js @@ -2526,8 +2526,8 @@ async function get_time_table() { async function load_and_get_signal(signal_ref_index) { return await invoke2("load_and_get_signal", { signal_ref_index }); } -async function timeline(signal_ref_index, screen_width) { - return await invoke2("timeline", { signal_ref_index, screen_width }); +async function timeline(signal_ref_index, screen_width, block_height) { + return await invoke2("timeline", { signal_ref_index, screen_width, block_height }); } async function unload_signal(signal_ref_index) { return await invoke2("unload_signal", { signal_ref_index }); diff --git a/frontend/typescript/pixi_canvas/pixi_canvas.ts b/frontend/typescript/pixi_canvas/pixi_canvas.ts index 6b4f783..7a60447 100644 --- a/frontend/typescript/pixi_canvas/pixi_canvas.ts +++ b/frontend/typescript/pixi_canvas/pixi_canvas.ts @@ -7,6 +7,7 @@ type Timeline = { type TimelineBlock = { x: number, width: number, + height: number, label: TimeLineBlockLabel | undefined, } type TimeLineBlockLabel = { @@ -153,7 +154,7 @@ class VarSignalRow { // background const background = new Graphics() - .roundRect(0, 0, timeline_block.width, this.row_height, 15) + .roundRect(0, 0, timeline_block.width, timeline_block.height, 15) .fill("SlateBlue"); signal_block.addChild(background); diff --git a/frontend/typescript/tauri_glue/tauri_glue.ts b/frontend/typescript/tauri_glue/tauri_glue.ts index 0f20e04..8f007dd 100644 --- a/frontend/typescript/tauri_glue/tauri_glue.ts +++ b/frontend/typescript/tauri_glue/tauri_glue.ts @@ -30,8 +30,8 @@ export async function load_and_get_signal(signal_ref_index: number): Promise { - return await invoke("timeline", { signal_ref_index, screen_width }); +export async function timeline(signal_ref_index: number, screen_width: number, block_height: number): Promise { + return await invoke("timeline", { signal_ref_index, screen_width, block_height }); } export async function unload_signal(signal_ref_index: number): Promise { diff --git a/shared/src/lib.rs b/shared/src/lib.rs index 674cdfa..90d80e6 100644 --- a/shared/src/lib.rs +++ b/shared/src/lib.rs @@ -2,21 +2,22 @@ use moonlight::*; pub mod wellen_helpers; -#[derive(Serialize, Deserialize, Debug)] +#[derive(Serialize, Deserialize, Debug, Default)] #[serde(crate = "serde")] pub struct Timeline { pub blocks: Vec } -#[derive(Serialize, Deserialize, Debug)] +#[derive(Serialize, Deserialize, Debug, Default)] #[serde(crate = "serde")] pub struct TimelineBlock { pub x: u32, pub width: u32, + pub height: u32, pub label: Option, } -#[derive(Serialize, Deserialize, Debug)] +#[derive(Serialize, Deserialize, Debug, Default)] #[serde(crate = "serde")] pub struct TimeLineBlockLabel { pub text: String, diff --git a/src-tauri/src/lib.rs b/src-tauri/src/lib.rs index 576aaa9..9d92c72 100644 --- a/src-tauri/src/lib.rs +++ b/src-tauri/src/lib.rs @@ -65,18 +65,17 @@ async fn load_and_get_signal( async fn timeline( signal_ref_index: usize, screen_width: u32, + block_height: u32, store: tauri::State<'_, Store>, ) -> Result { + // @TODO run (all?) in a blocking thread let signal_ref = wellen::SignalRef::from_index(signal_ref_index).unwrap(); let mut waveform_lock = store.waveform.lock().unwrap(); let waveform = waveform_lock.as_mut().unwrap(); - // @TODO maybe run it in a thread to not block the main one or return the result through a Tauri channel waveform.load_signals_multi_threaded(&[signal_ref]); let signal = waveform.get_signal(signal_ref).unwrap(); - - // @TODO create Timeline - let timeline = shared::Timeline { blocks: Vec::new() }; - + let time_table = waveform.time_table(); + let timeline = signal_to_timeline(signal, time_table, screen_width, block_height); Ok(serde_json::to_value(timeline).unwrap()) } @@ -112,3 +111,73 @@ pub fn run() { .run(tauri::generate_context!()) .expect("error while running tauri application"); } + +fn signal_to_timeline( + signal: &wellen::Signal, + time_table: &[wellen::Time], + screen_width: u32, + block_height: u32, +) -> shared::Timeline { + const MIN_BLOCK_WIDTH: u32 = 3; + const LETTER_WIDTH: u32 = 15; + const LETTER_HEIGHT: u32 = 21; + const LABEL_X_PADDING: u32 = 10; + + let Some(last_time) = time_table.last().copied() else { + return shared::Timeline::default() + }; + + let last_time = last_time as f64; + let screen_width = screen_width as f64; + + let mut x_value_pairs = signal + .iter_changes() + .map(|(index, value)| { + let index = index as usize; + let time = time_table[index] as f64; + let x = time / last_time * screen_width; + (x, value) + }) + .peekable(); + + let mut blocks = Vec::new(); + + while let Some((block_x, value)) = x_value_pairs.next() { + let next_block_x = if let Some((next_block_x, _)) = x_value_pairs.peek() { + *next_block_x + } else { + screen_width + }; + + let block_width = (next_block_x - block_x) as u32; + if block_width < MIN_BLOCK_WIDTH { + continue; + } + + let value = value.to_string(); + // @TODO dynamic formatter + let value = u32::from_str_radix(&value, 2).unwrap(); + let value = format!("{value:x}"); + + let value_width = value.chars().count() as u32 * LETTER_WIDTH; + let label = if (value_width + (2 * LABEL_X_PADDING)) <= block_width { + Some(shared::TimeLineBlockLabel { + text: value, + x: (block_width - value_width) / 2, + y: (block_height - LETTER_HEIGHT) / 2, + }) + } else { + None + }; + + let block = shared::TimelineBlock { + x: block_x as u32, + width: block_width, + height: block_height, + label, + }; + blocks.push(block); + } + + shared::Timeline { blocks } +}