diff --git a/README.md b/README.md
index 7cfd3a9..158b34d 100644
--- a/README.md
+++ b/README.md
@@ -4,11 +4,23 @@
---
-
+
+ Browser (Firefox)
-
+
+ Desktop, miller columns and tree
+
+
+
+
+ Zoom, pan and basic number formats
+
+
+
+
+ Zoom and all formats
---
diff --git a/docs/video_simple_vcd.gif b/docs/video_desktop.gif
similarity index 100%
rename from docs/video_simple_vcd.gif
rename to docs/video_desktop.gif
diff --git a/docs/video_zoom_formatting.gif b/docs/video_zoom_formatting.gif
new file mode 100644
index 0000000..0ade85f
Binary files /dev/null and b/docs/video_zoom_formatting.gif differ
diff --git a/docs/video_zoom_formatting_simple.gif b/docs/video_zoom_formatting_simple.gif
new file mode 100644
index 0000000..6df92e1
Binary files /dev/null and b/docs/video_zoom_formatting_simple.gif differ
diff --git a/frontend/src/platform.rs b/frontend/src/platform.rs
index 58903f9..73c7f73 100644
--- a/frontend/src/platform.rs
+++ b/frontend/src/platform.rs
@@ -38,13 +38,14 @@ pub async fn load_signal_and_get_timeline(
var_format: shared::VarFormat,
) -> shared::Timeline {
platform::load_signal_and_get_timeline(
- signal_ref,
+ signal_ref,
timeline_zoom,
timeline_viewport_width,
- timeline_viewport_x,
- block_height,
+ timeline_viewport_x,
+ block_height,
var_format,
- ).await
+ )
+ .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 796f007..09f94fb 100644
--- a/frontend/src/platform/browser.rs
+++ b/frontend/src/platform/browser.rs
@@ -87,16 +87,15 @@ pub(super) async fn load_signal_and_get_timeline(
waveform.load_signals_multi_threaded(&[signal_ref]);
let signal = waveform.get_signal(signal_ref).unwrap();
let time_table = waveform.time_table();
- let timeline =
- shared::signal_to_timeline(
- signal,
- time_table,
- timeline_zoom,
- timeline_viewport_width,
- timeline_viewport_x,
- block_height,
- var_format,
- );
+ let timeline = shared::signal_to_timeline(
+ signal,
+ time_table,
+ timeline_zoom,
+ timeline_viewport_width,
+ timeline_viewport_x,
+ block_height,
+ var_format,
+ );
timeline
}
diff --git a/frontend/src/waveform_panel/pixi_canvas.rs b/frontend/src/waveform_panel/pixi_canvas.rs
index 69e5960..532eded 100644
--- a/frontend/src/waveform_panel/pixi_canvas.rs
+++ b/frontend/src/waveform_panel/pixi_canvas.rs
@@ -53,7 +53,12 @@ impl PixiCanvas {
let task_with_controller = Mutable::new(None);
// -- FastWave-specific --
let timeline_getter = Rc::new(Closure::new(
- |signal_ref_index, timeline_zoom, timeline_viewport_width, timeline_viewport_x, row_height, var_format| {
+ |signal_ref_index,
+ timeline_zoom,
+ timeline_viewport_width,
+ timeline_viewport_x,
+ row_height,
+ var_format| {
future_to_promise(async move {
let signal_ref = wellen::SignalRef::from_index(signal_ref_index).unwrap_throw();
let timeline = platform::load_signal_and_get_timeline(
@@ -84,15 +89,17 @@ impl PixiCanvas {
}))
.update_raw_el(|raw_el| {
// @TODO rewrite to a native Zoon API
- raw_el.event_handler(clone!((controller) move |event: events_extra::WheelEvent| {
- if let Some(controller) = controller.lock_ref().as_ref() {
- controller.zoom_or_pan(
- event.delta_y(),
- event.shift_key(),
- event.offset_x() as u32,
- );
- }
- }))
+ raw_el.event_handler(
+ clone!((controller) move |event: events_extra::WheelEvent| {
+ if let Some(controller) = controller.lock_ref().as_ref() {
+ controller.zoom_or_pan(
+ event.delta_y(),
+ event.shift_key(),
+ event.offset_x() as u32,
+ );
+ }
+ }),
+ )
})
.after_insert(clone!((controller, timeline_getter) move |element| {
Task::start(async move {
@@ -100,8 +107,8 @@ impl PixiCanvas {
1.,
width.get(),
0,
- row_height,
- row_gap,
+ row_height,
+ row_gap,
&timeline_getter
);
pixi_controller.init(&element).await;
@@ -140,8 +147,16 @@ mod js_bridge {
type TimelineViewportX = i32;
type RowHeight = u32;
type VarFormatJs = JsValue;
- type TimelineGetter =
- Closure TimelinePromise>;
+ type TimelineGetter = Closure<
+ dyn FnMut(
+ SignalRefIndex,
+ TimelineZoom,
+ TimelineViewportWidth,
+ TimelineViewportX,
+ RowHeight,
+ VarFormatJs,
+ ) -> TimelinePromise,
+ >;
// Note: Add all corresponding methods to `frontend/typescript/pixi_canvas/pixi_canvas.ts`
#[wasm_bindgen(module = "/typescript/bundles/pixi_canvas.js")]
@@ -184,7 +199,12 @@ mod js_bridge {
pub fn set_var_format(this: &PixiController, index: usize, var_format: JsValue);
#[wasm_bindgen(method)]
- pub fn zoom_or_pan(this: &PixiController, wheel_delta_y: f64, shift_key: bool, offset_x: u32);
+ pub fn zoom_or_pan(
+ this: &PixiController,
+ wheel_delta_y: f64,
+ shift_key: bool,
+ offset_x: u32,
+ );
#[wasm_bindgen(method)]
pub fn remove_var(this: &PixiController, index: usize);
diff --git a/frontend/typescript/bundles/pixi_canvas.js b/frontend/typescript/bundles/pixi_canvas.js
index 27976c4..d542b5e 100644
--- a/frontend/typescript/bundles/pixi_canvas.js
+++ b/frontend/typescript/bundles/pixi_canvas.js
@@ -35223,10 +35223,22 @@ var PixiController = class {
} else {
const offset_x_ratio = offset_x / this.timeline_viewport_width;
const old_timeline_width = this.timeline_viewport_width * this.timeline_zoom;
- this.timeline_zoom -= Math.sign(wheel_delta_y) * this.timeline_zoom * 0.5;
- const new_timeline_width = this.timeline_viewport_width * this.timeline_zoom;
- const timeline_width_difference = new_timeline_width - old_timeline_width;
- this.timeline_viewport_x += timeline_width_difference * offset_x_ratio;
+ const new_zoom = this.timeline_zoom - Math.sign(wheel_delta_y) * this.timeline_zoom * 0.5;
+ const new_timeline_width = this.timeline_viewport_width * new_zoom;
+ if (new_timeline_width < this.timeline_viewport_width) {
+ this.timeline_zoom = 1;
+ this.timeline_viewport_x = 0;
+ } else {
+ const timeline_width_difference = new_timeline_width - old_timeline_width;
+ this.timeline_viewport_x += timeline_width_difference * offset_x_ratio;
+ this.timeline_zoom = new_zoom;
+ }
+ }
+ const timeline_width = this.timeline_viewport_width * this.timeline_zoom;
+ if (this.timeline_viewport_x < 0) {
+ this.timeline_viewport_x = 0;
+ } else if (this.timeline_viewport_x + this.timeline_viewport_width > timeline_width) {
+ this.timeline_viewport_x = timeline_width - this.timeline_viewport_width;
}
this.redraw_all_rows();
}
diff --git a/frontend/typescript/pixi_canvas/pixi_canvas.ts b/frontend/typescript/pixi_canvas/pixi_canvas.ts
index f3c60b9..04e0935 100644
--- a/frontend/typescript/pixi_canvas/pixi_canvas.ts
+++ b/frontend/typescript/pixi_canvas/pixi_canvas.ts
@@ -151,13 +151,24 @@ export class PixiController {
if (shift_key) {
this.timeline_viewport_x += Math.sign(wheel_delta_y) * 20;
} else {
- // @TODO bounds
const offset_x_ratio = offset_x / this.timeline_viewport_width;
const old_timeline_width = this.timeline_viewport_width * this.timeline_zoom;
- this.timeline_zoom -= Math.sign(wheel_delta_y) * this.timeline_zoom * 0.5;
- const new_timeline_width = this.timeline_viewport_width * this.timeline_zoom;
- const timeline_width_difference = new_timeline_width - old_timeline_width;
- this.timeline_viewport_x += timeline_width_difference * offset_x_ratio;
+ const new_zoom = this.timeline_zoom - Math.sign(wheel_delta_y) * this.timeline_zoom * 0.5;
+ const new_timeline_width = this.timeline_viewport_width * new_zoom;
+ if (new_timeline_width < this.timeline_viewport_width) {
+ this.timeline_zoom = 1;
+ this.timeline_viewport_x = 0;
+ } else {
+ const timeline_width_difference = new_timeline_width - old_timeline_width;
+ this.timeline_viewport_x += timeline_width_difference * offset_x_ratio;
+ this.timeline_zoom = new_zoom;
+ }
+ }
+ const timeline_width = this.timeline_viewport_width * this.timeline_zoom;
+ if (this.timeline_viewport_x < 0) {
+ this.timeline_viewport_x = 0;
+ } else if (this.timeline_viewport_x + this.timeline_viewport_width > timeline_width) {
+ this.timeline_viewport_x = timeline_width - this.timeline_viewport_width;
}
this.redraw_all_rows();
}
diff --git a/shared/src/signal_to_timeline.rs b/shared/src/signal_to_timeline.rs
index e9fc24f..f2d05b6 100644
--- a/shared/src/signal_to_timeline.rs
+++ b/shared/src/signal_to_timeline.rs
@@ -38,7 +38,7 @@ pub fn signal_to_timeline(
while let Some((block_x, value)) = x_value_pairs.next() {
if block_x >= (timeline_viewport_width as f64) {
break;
- }
+ }
let next_block_x = if let Some((next_block_x, _)) = x_value_pairs.peek() {
*next_block_x
@@ -52,7 +52,7 @@ pub fn signal_to_timeline(
}
if block_x + (block_width as f64) <= 0. {
continue;
- }
+ }
// @TODO cache?
let value = var_format.format(value);
diff --git a/src-tauri/src/lib.rs b/src-tauri/src/lib.rs
index 3b45d05..d985c1c 100644
--- a/src-tauri/src/lib.rs
+++ b/src-tauri/src/lib.rs
@@ -56,16 +56,15 @@ async fn load_signal_and_get_timeline(
waveform.load_signals_multi_threaded(&[signal_ref]);
let signal = waveform.get_signal(signal_ref).unwrap();
let time_table = waveform.time_table();
- let timeline =
- shared::signal_to_timeline(
- signal,
- time_table,
- timeline_zoom,
- timeline_viewport_width,
- timeline_viewport_x,
- block_height,
- var_format,
- );
+ let timeline = shared::signal_to_timeline(
+ signal,
+ time_table,
+ timeline_zoom,
+ timeline_viewport_width,
+ timeline_viewport_x,
+ block_height,
+ var_format,
+ );
Ok(serde_json::to_value(timeline).unwrap())
}