timeline_getter

This commit is contained in:
Martin Kavík 2024-06-07 22:20:49 +02:00
parent 64cc46d4ac
commit c2f49901f6
6 changed files with 66 additions and 23 deletions

View file

Before

Width:  |  Height:  |  Size: 434 KiB

After

Width:  |  Height:  |  Size: 434 KiB

View file

@ -99,7 +99,6 @@ impl ControlsPanel {
Layout::Columns => Height::fill().max(MILLER_COLUMN_MAX_HEIGHT), Layout::Columns => Height::fill().max(MILLER_COLUMN_MAX_HEIGHT),
}, },
))) )))
.s(Scrollbars::both())
.s(Padding::all(20)) .s(Padding::all(20))
.s(Gap::new().y(40)) .s(Gap::new().y(40))
.s(Align::new().top()) .s(Align::new().top())

View file

@ -1,6 +1,6 @@
use crate::{platform, HierarchyAndTimeTable}; use crate::{platform, HierarchyAndTimeTable};
use wellen::GetItem; use wellen::GetItem;
use zoon::{eprintln, *}; use zoon::*;
mod pixi_canvas; mod pixi_canvas;
use pixi_canvas::{PixiCanvas, PixiController}; use pixi_canvas::{PixiCanvas, PixiController};
@ -109,10 +109,6 @@ impl WaveformPanel {
var_ref: wellen::VarRef, var_ref: wellen::VarRef,
) { ) {
let (hierarchy, time_table) = hierarchy_and_time_table.get_cloned().unwrap(); let (hierarchy, time_table) = hierarchy_and_time_table.get_cloned().unwrap();
if time_table.is_empty() {
eprintln!("timetable is empty");
return;
}
let var = hierarchy.get(var_ref); let var = hierarchy.get(var_ref);
let signal_ref = var.signal_ref(); let signal_ref = var.signal_ref();
@ -128,7 +124,9 @@ impl WaveformPanel {
zoon::println!("{timescale:?}"); zoon::println!("{timescale:?}");
// Note: Sync `timeline`'s type with the `Timeline` in `frontend/typescript/pixi_canvas/pixi_canvas.ts' // Note: Sync `timeline`'s type with the `Timeline` in `frontend/typescript/pixi_canvas/pixi_canvas.ts'
controller.push_var(serde_wasm_bindgen::to_value(&timeline).unwrap_throw()); let timeline = serde_wasm_bindgen::to_value(&timeline).unwrap_throw();
let signal_ref_index = signal_ref.index();
controller.push_var(signal_ref_index, timeline);
} }
fn selected_var_panel( fn selected_var_panel(

View file

@ -1,5 +1,7 @@
pub use js_bridge::PixiController; pub use js_bridge::PixiController;
use zoon::*; use zoon::*;
use std::rc::Rc;
use crate::platform;
pub struct PixiCanvas { pub struct PixiCanvas {
raw_el: RawHtmlEl<web_sys::HtmlElement>, raw_el: RawHtmlEl<web_sys::HtmlElement>,
@ -45,6 +47,16 @@ impl PixiCanvas {
})), })),
); );
let task_with_controller = Mutable::new(None); let task_with_controller = Mutable::new(None);
// -- FastWave-specific --
let timeline_getter = Rc::new(Closure::new(|signal_ref_index, screen_width, row_height| {
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(signal_ref, screen_width, row_height).await;
let timeline = serde_wasm_bindgen::to_value(&timeline).unwrap_throw();
Ok(timeline)
})
}));
// -- // --
Self { Self {
controller: controller.read_only(), controller: controller.read_only(),
width: width.read_only(), width: width.read_only(),
@ -56,14 +68,15 @@ impl PixiCanvas {
width.set_neq(new_width); width.set_neq(new_width);
height.set_neq(new_height); height.set_neq(new_height);
})) }))
.after_insert(clone!((controller) move |element| { .after_insert(clone!((controller, timeline_getter) move |element| {
Task::start(async move { Task::start(async move {
let pixi_controller = js_bridge::PixiController::new(row_height, row_gap); let pixi_controller = js_bridge::PixiController::new(row_height, row_gap, &timeline_getter);
pixi_controller.init(&element).await; pixi_controller.init(&element).await;
controller.set(Some(pixi_controller)); controller.set(Some(pixi_controller));
}); });
})) }))
.after_remove(move |_| { .after_remove(move |_| {
drop(timeline_getter);
drop(resize_task); drop(resize_task);
drop(task_with_controller); drop(task_with_controller);
if let Some(controller) = controller.take() { if let Some(controller) = controller.take() {
@ -87,6 +100,12 @@ impl PixiCanvas {
mod js_bridge { mod js_bridge {
use zoon::*; use zoon::*;
type TimelinePromise = js_sys::Promise;
type SignalRefIndex = usize;
type ScreenWidth = u32;
type RowHeight = u32;
type TimelineGetter = Closure<dyn FnMut(SignalRefIndex, ScreenWidth, RowHeight) -> TimelinePromise>;
// Note: Add all corresponding methods to `frontend/typescript/pixi_canvas/pixi_canvas.ts` // Note: Add all corresponding methods to `frontend/typescript/pixi_canvas/pixi_canvas.ts`
#[wasm_bindgen(module = "/typescript/bundles/pixi_canvas.js")] #[wasm_bindgen(module = "/typescript/bundles/pixi_canvas.js")]
extern "C" { extern "C" {
@ -95,7 +114,7 @@ mod js_bridge {
// @TODO `row_height` and `row_gap` is FastWave-specific // @TODO `row_height` and `row_gap` is FastWave-specific
#[wasm_bindgen(constructor)] #[wasm_bindgen(constructor)]
pub fn new(row_height: u32, row_gap: u32) -> PixiController; pub fn new(row_height: u32, row_gap: u32, timeline_getter: &TimelineGetter) -> PixiController;
#[wasm_bindgen(method)] #[wasm_bindgen(method)]
pub async fn init(this: &PixiController, parent_element: &JsValue); pub async fn init(this: &PixiController, parent_element: &JsValue);
@ -115,7 +134,7 @@ mod js_bridge {
pub fn remove_var(this: &PixiController, index: usize); pub fn remove_var(this: &PixiController, index: usize);
#[wasm_bindgen(method)] #[wasm_bindgen(method)]
pub fn push_var(this: &PixiController, timeline: JsValue); pub fn push_var(this: &PixiController, signal_ref_index: usize, timeline: JsValue);
#[wasm_bindgen(method)] #[wasm_bindgen(method)]
pub fn pop_var(this: &PixiController); pub fn pop_var(this: &PixiController);

View file

@ -35136,12 +35136,14 @@ var PixiController = class {
row_height; row_height;
row_gap; row_gap;
previous_parent_width; previous_parent_width;
constructor(row_height, row_gap) { timeline_getter;
constructor(row_height, row_gap, timeline_getter) {
this.app = new Application(); this.app = new Application();
this.row_height = row_height; this.row_height = row_height;
this.row_gap = row_gap; this.row_gap = row_gap;
this.app.stage.addChild(this.var_signal_rows_container); this.app.stage.addChild(this.var_signal_rows_container);
this.previous_parent_width = null; this.previous_parent_width = null;
this.timeline_getter = timeline_getter;
} }
async init(parent_element) { async init(parent_element) {
await this.app.init({ background: "DarkSlateBlue", antialias: true, resizeTo: parent_element }); await this.app.init({ background: "DarkSlateBlue", antialias: true, resizeTo: parent_element });
@ -35174,15 +35176,19 @@ var PixiController = class {
} }
// -- FastWave-specific -- // -- FastWave-specific --
redraw_rows() { redraw_rows() {
this.var_signal_rows.forEach((row) => row.draw()); this.var_signal_rows.forEach(async (row) => {
const timeline = await this.timeline_getter(row.signal_ref_index, this.app.screen.width, this.row_height);
row.redraw(timeline);
});
} }
remove_var(index) { remove_var(index) {
if (typeof this.var_signal_rows[index] !== "undefined") { if (typeof this.var_signal_rows[index] !== "undefined") {
this.var_signal_rows[index].destroy(); this.var_signal_rows[index].destroy();
} }
} }
push_var(timeline) { push_var(signal_ref_index, timeline) {
new VarSignalRow( new VarSignalRow(
signal_ref_index,
timeline, timeline,
this.app, this.app,
this.var_signal_rows, this.var_signal_rows,
@ -35199,8 +35205,9 @@ var PixiController = class {
} }
}; };
var VarSignalRow = class { var VarSignalRow = class {
app; signal_ref_index;
timeline; timeline;
app;
owner; owner;
index_in_owner; index_in_owner;
rows_container; rows_container;
@ -35216,9 +35223,10 @@ var VarSignalRow = class {
fontSize: 16, fontSize: 16,
fontFamily: 'system-ui, -apple-system, "Segoe UI", Roboto, Helvetica, Arial, sans-serif, "Apple Color Emoji", "Segoe UI Emoji"' fontFamily: 'system-ui, -apple-system, "Segoe UI", Roboto, Helvetica, Arial, sans-serif, "Apple Color Emoji", "Segoe UI Emoji"'
}); });
constructor(timeline, app, owner, rows_container, row_height, row_gap) { constructor(signal_ref_index, timeline, app, owner, rows_container, row_height, row_gap) {
this.app = app; this.signal_ref_index = signal_ref_index;
this.timeline = timeline; this.timeline = timeline;
this.app = app;
this.row_height = row_height; this.row_height = row_height;
this.row_gap = row_gap; this.row_gap = row_gap;
this.row_height_with_gap = row_height + row_gap; this.row_height_with_gap = row_height + row_gap;
@ -35241,6 +35249,9 @@ var VarSignalRow = class {
this.draw(); this.draw();
} }
draw() { draw() {
if (this.app.screen === null) {
return;
}
this.row_container_background.width = this.app.screen.width; this.row_container_background.width = this.app.screen.width;
this.signal_blocks_container.removeChildren(); this.signal_blocks_container.removeChildren();
this.timeline.blocks.forEach((timeline_block) => { this.timeline.blocks.forEach((timeline_block) => {

View file

@ -16,6 +16,8 @@ type TimeLineBlockLabel = {
y: number, y: number,
} }
type TimelineGetter = (signal_ref_index: number, screen_width: number, row_height: number) => Promise<Timeline>;
export class PixiController { export class PixiController {
app: Application app: Application
// -- FastWave-specific -- // -- FastWave-specific --
@ -24,14 +26,16 @@ export class PixiController {
row_height: number; row_height: number;
row_gap: number; row_gap: number;
previous_parent_width: number | null; previous_parent_width: number | null;
timeline_getter: TimelineGetter
constructor(row_height: number, row_gap: number) { constructor(row_height: number, row_gap: number, timeline_getter: TimelineGetter) {
this.app = new Application(); this.app = new Application();
// -- FastWave-specific -- // -- FastWave-specific --
this.row_height = row_height; this.row_height = row_height;
this.row_gap = row_gap; this.row_gap = row_gap;
this.app.stage.addChild(this.var_signal_rows_container); this.app.stage.addChild(this.var_signal_rows_container);
this.previous_parent_width = null; this.previous_parent_width = null;
this.timeline_getter = timeline_getter;
} }
async init(parent_element: HTMLElement) { async init(parent_element: HTMLElement) {
@ -71,7 +75,10 @@ export class PixiController {
// -- FastWave-specific -- // -- FastWave-specific --
redraw_rows() { redraw_rows() {
this.var_signal_rows.forEach(row => row.draw()); this.var_signal_rows.forEach(async row => {
const timeline = await this.timeline_getter(row.signal_ref_index, this.app.screen.width, this.row_height);
row.redraw(timeline);
});
} }
remove_var(index: number) { remove_var(index: number) {
@ -80,8 +87,9 @@ export class PixiController {
} }
} }
push_var(timeline: Timeline) { push_var(signal_ref_index: number, timeline: Timeline) {
new VarSignalRow( new VarSignalRow(
signal_ref_index,
timeline, timeline,
this.app, this.app,
this.var_signal_rows, this.var_signal_rows,
@ -101,8 +109,9 @@ export class PixiController {
} }
class VarSignalRow { class VarSignalRow {
app: Application; signal_ref_index: number;
timeline: Timeline; timeline: Timeline;
app: Application;
owner: Array<VarSignalRow>; owner: Array<VarSignalRow>;
index_in_owner: number; index_in_owner: number;
rows_container: Container; rows_container: Container;
@ -120,6 +129,7 @@ class VarSignalRow {
}); });
constructor( constructor(
signal_ref_index: number,
timeline: Timeline, timeline: Timeline,
app: Application, app: Application,
owner: Array<VarSignalRow>, owner: Array<VarSignalRow>,
@ -127,9 +137,9 @@ class VarSignalRow {
row_height: number, row_height: number,
row_gap: number, row_gap: number,
) { ) {
this.app = app; this.signal_ref_index = signal_ref_index;
this.timeline = timeline; this.timeline = timeline;
this.app = app;
this.row_height = row_height; this.row_height = row_height;
this.row_gap = row_gap; this.row_gap = row_gap;
@ -164,6 +174,12 @@ class VarSignalRow {
} }
draw() { draw() {
// Screen can be null when we are, for instance, switching between miller column and tree layout
// and then the canvas has to be recreated
if (this.app.screen === null) {
return;
}
this.row_container_background.width = this.app.screen.width; this.row_container_background.width = this.app.screen.width;
this.signal_blocks_container.removeChildren(); this.signal_blocks_container.removeChildren();