platform::timeline
This commit is contained in:
parent
c0de520811
commit
6e85b7fa35
10
Cargo.lock
generated
10
Cargo.lock
generated
|
@ -1538,9 +1538,9 @@ dependencies = [
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "futures"
|
name = "futures"
|
||||||
version = "0.3.30"
|
version = "0.3.28"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "645c6916888f6cb6350d2550b80fb63e734897a8498abe35cfb732b6487804b0"
|
checksum = "23342abe12aba583913b2e62f22225ff9c950774065e4bfb61a19cd9770fec40"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"futures-channel",
|
"futures-channel",
|
||||||
"futures-core",
|
"futures-core",
|
||||||
|
@ -1568,9 +1568,9 @@ checksum = "dfc6580bb841c5a68e9ef15c77ccc837b40a7504914d52e47b8b0e9bbda25a1d"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "futures-executor"
|
name = "futures-executor"
|
||||||
version = "0.3.30"
|
version = "0.3.28"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "a576fc72ae164fca6b9db127eaa9a9dda0d61316034f33a0a0d4eda41f02b01d"
|
checksum = "ccecee823288125bd88b4d7f565c9e58e41858e47ab72e8ea2d64e93624386e0"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"futures-core",
|
"futures-core",
|
||||||
"futures-task",
|
"futures-task",
|
||||||
|
@ -4124,6 +4124,8 @@ dependencies = [
|
||||||
name = "shared"
|
name = "shared"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
|
"futures-util",
|
||||||
|
"moonlight",
|
||||||
"wellen",
|
"wellen",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
|
|
@ -16,11 +16,12 @@ readme = "../README.md"
|
||||||
publish = false
|
publish = false
|
||||||
|
|
||||||
[workspace.dependencies]
|
[workspace.dependencies]
|
||||||
shared = { path = "./shared" }
|
|
||||||
# wellen = { version = "0.9.9", features = ["serde1"] }
|
# wellen = { version = "0.9.9", features = ["serde1"] }
|
||||||
# wellen = { path = "../wellen/wellen", features = ["serde1"] }
|
# wellen = { path = "../wellen/wellen", features = ["serde1"] }
|
||||||
wellen = { git = "https://github.com/MartinKavik/wellen", features = ["serde1"], branch = "new_pub_types" }
|
wellen = { git = "https://github.com/MartinKavik/wellen", features = ["serde1"], branch = "new_pub_types" }
|
||||||
# moon = { path = "../../crates/moon" }
|
# moon = { path = "../../crates/moon" }
|
||||||
# zoon = { path = "../../crates/zoon" }
|
# zoon = { path = "../../crates/zoon" }
|
||||||
|
# moonlight = { path = "../../crates/zoon" }
|
||||||
zoon = { git = "https://github.com/MoonZoon/MoonZoon", rev = "fc73b0d90bf39be72e70fdcab4f319ea5b8e6cfc" }
|
zoon = { git = "https://github.com/MoonZoon/MoonZoon", rev = "fc73b0d90bf39be72e70fdcab4f319ea5b8e6cfc" }
|
||||||
moon = { git = "https://github.com/MoonZoon/MoonZoon", rev = "fc73b0d90bf39be72e70fdcab4f319ea5b8e6cfc" }
|
moon = { git = "https://github.com/MoonZoon/MoonZoon", rev = "fc73b0d90bf39be72e70fdcab4f319ea5b8e6cfc" }
|
||||||
|
moonlight = { git = "https://github.com/MoonZoon/MoonZoon", rev = "fc73b0d90bf39be72e70fdcab4f319ea5b8e6cfc" }
|
||||||
|
|
|
@ -11,8 +11,8 @@ publish.workspace = true
|
||||||
wasm-bindgen-test = "0.3.19"
|
wasm-bindgen-test = "0.3.19"
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
shared.workspace = true
|
|
||||||
zoon.workspace = true
|
zoon.workspace = true
|
||||||
wellen.workspace = true
|
wellen.workspace = true
|
||||||
|
shared = { path = "../shared", features = ["frontend"] }
|
||||||
web-sys = { version = "*", features = ["FileSystemFileHandle"] }
|
web-sys = { version = "*", features = ["FileSystemFileHandle"] }
|
||||||
gloo-file = { version = "0.3.0", features = ["futures"] }
|
gloo-file = { version = "0.3.0", features = ["futures"] }
|
||||||
|
|
|
@ -37,6 +37,10 @@ pub async fn load_and_get_signal(signal_ref: wellen::SignalRef) -> wellen::Signa
|
||||||
platform::load_and_get_signal(signal_ref).await
|
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 unload_signal(signal_ref: wellen::SignalRef) {
|
pub async fn unload_signal(signal_ref: wellen::SignalRef) {
|
||||||
platform::unload_signal(signal_ref).await
|
platform::unload_signal(signal_ref).await
|
||||||
}
|
}
|
||||||
|
|
|
@ -91,6 +91,10 @@ 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()
|
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 {
|
||||||
|
shared::Timeline { blocks: Vec::new() }
|
||||||
|
}
|
||||||
|
|
||||||
pub(super) async fn unload_signal(signal_ref: wellen::SignalRef) {
|
pub(super) async fn unload_signal(signal_ref: wellen::SignalRef) {
|
||||||
let mut waveform_lock = STORE.waveform.lock().unwrap_throw();
|
let mut waveform_lock = STORE.waveform.lock().unwrap_throw();
|
||||||
let waveform = waveform_lock.as_mut().unwrap_throw();
|
let waveform = waveform_lock.as_mut().unwrap_throw();
|
||||||
|
|
|
@ -30,6 +30,15 @@ pub(super) async fn load_and_get_signal(signal_ref: wellen::SignalRef) -> wellen
|
||||||
.unwrap_throw()
|
.unwrap_throw()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub(super) async fn timeline(signal_ref: wellen::SignalRef, screen_width: u32) -> shared::Timeline {
|
||||||
|
serde_wasm_bindgen::from_value(
|
||||||
|
tauri_glue::timeline(signal_ref.index(), screen_width)
|
||||||
|
.await
|
||||||
|
.unwrap_throw(),
|
||||||
|
)
|
||||||
|
.unwrap_throw()
|
||||||
|
}
|
||||||
|
|
||||||
pub(super) async fn unload_signal(signal_ref: wellen::SignalRef) {
|
pub(super) async fn unload_signal(signal_ref: wellen::SignalRef) {
|
||||||
tauri_glue::unload_signal(signal_ref.index())
|
tauri_glue::unload_signal(signal_ref.index())
|
||||||
.await
|
.await
|
||||||
|
@ -57,6 +66,9 @@ mod tauri_glue {
|
||||||
#[wasm_bindgen(catch)]
|
#[wasm_bindgen(catch)]
|
||||||
pub async fn load_and_get_signal(signal_ref_index: usize) -> Result<JsValue, JsValue>;
|
pub async fn load_and_get_signal(signal_ref_index: usize) -> Result<JsValue, JsValue>;
|
||||||
|
|
||||||
|
#[wasm_bindgen(catch)]
|
||||||
|
pub async fn timeline(signal_ref_index: usize, screen_width: u32) -> Result<JsValue, JsValue>;
|
||||||
|
|
||||||
#[wasm_bindgen(catch)]
|
#[wasm_bindgen(catch)]
|
||||||
pub async fn unload_signal(signal_ref_index: usize) -> Result<(), JsValue>;
|
pub async fn unload_signal(signal_ref_index: usize) -> Result<(), JsValue>;
|
||||||
}
|
}
|
||||||
|
|
|
@ -117,24 +117,19 @@ impl WaveformPanel {
|
||||||
|
|
||||||
let var = hierarchy.get(var_ref);
|
let var = hierarchy.get(var_ref);
|
||||||
let signal_ref = var.signal_ref();
|
let signal_ref = var.signal_ref();
|
||||||
let signal = platform::load_and_get_signal(signal_ref).await;
|
let timeline = platform::timeline(signal_ref, controller.screen_width()).await;
|
||||||
|
|
||||||
|
// @TODO remove
|
||||||
|
zoon::println!("Timeline in Rust: {timeline:#?}");
|
||||||
|
|
||||||
let timescale = hierarchy.timescale();
|
let timescale = hierarchy.timescale();
|
||||||
// @TODO remove
|
// @TODO remove
|
||||||
zoon::println!("{timescale:?}");
|
zoon::println!("{timescale:?}");
|
||||||
|
|
||||||
let mut timeline: Vec<(wellen::Time, String)> = signal
|
if timeline.blocks.is_empty() {
|
||||||
.iter_changes()
|
|
||||||
.map(|(time_index, signal_value)| {
|
|
||||||
(time_table[time_index as usize], signal_value.to_string())
|
|
||||||
})
|
|
||||||
.collect();
|
|
||||||
if timeline.is_empty() {
|
|
||||||
eprintln!("timeline is empty");
|
eprintln!("timeline is empty");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
timeline.push((last_time, timeline.last().cloned().unwrap_throw().1));
|
|
||||||
|
|
||||||
// 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());
|
controller.push_var(serde_wasm_bindgen::to_value(&timeline).unwrap_throw());
|
||||||
}
|
}
|
||||||
|
|
|
@ -100,11 +100,14 @@ mod js_bridge {
|
||||||
#[wasm_bindgen(method)]
|
#[wasm_bindgen(method)]
|
||||||
pub async fn init(this: &PixiController, parent_element: &JsValue);
|
pub async fn init(this: &PixiController, parent_element: &JsValue);
|
||||||
|
|
||||||
|
#[wasm_bindgen(method)]
|
||||||
|
pub fn queue_resize(this: &PixiController);
|
||||||
|
|
||||||
#[wasm_bindgen(method)]
|
#[wasm_bindgen(method)]
|
||||||
pub fn destroy(this: &PixiController);
|
pub fn destroy(this: &PixiController);
|
||||||
|
|
||||||
#[wasm_bindgen(method)]
|
#[wasm_bindgen(method)]
|
||||||
pub fn queue_resize(this: &PixiController);
|
pub fn screen_width(this: &PixiController) -> u32;
|
||||||
|
|
||||||
// -- FastWave-specific --
|
// -- FastWave-specific --
|
||||||
|
|
||||||
|
|
|
@ -35126,7 +35126,6 @@ var import_earcut2 = __toESM(require_earcut(), 1);
|
||||||
extensions.add(browserExt, webworkerExt);
|
extensions.add(browserExt, webworkerExt);
|
||||||
|
|
||||||
// pixi_canvas.ts
|
// pixi_canvas.ts
|
||||||
var MIN_BLOCK_WIDTH = 1;
|
|
||||||
var PixiController = class {
|
var PixiController = class {
|
||||||
app;
|
app;
|
||||||
// -- FastWave-specific --
|
// -- FastWave-specific --
|
||||||
|
@ -35160,6 +35159,9 @@ var PixiController = class {
|
||||||
};
|
};
|
||||||
this.app.destroy(rendererDestroyOptions, options);
|
this.app.destroy(rendererDestroyOptions, options);
|
||||||
}
|
}
|
||||||
|
screen_width() {
|
||||||
|
return this.app.screen.width;
|
||||||
|
}
|
||||||
// -- FastWave-specific --
|
// -- FastWave-specific --
|
||||||
remove_var(index) {
|
remove_var(index) {
|
||||||
if (typeof this.var_signal_rows[index] !== "undefined") {
|
if (typeof this.var_signal_rows[index] !== "undefined") {
|
||||||
|
@ -35167,6 +35169,7 @@ var PixiController = class {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
push_var(timeline) {
|
push_var(timeline) {
|
||||||
|
console.log("Timline in Typescript:", timeline);
|
||||||
new VarSignalRow(
|
new VarSignalRow(
|
||||||
timeline,
|
timeline,
|
||||||
this.app,
|
this.app,
|
||||||
|
@ -35186,17 +35189,13 @@ var PixiController = class {
|
||||||
var VarSignalRow = class {
|
var VarSignalRow = class {
|
||||||
app;
|
app;
|
||||||
timeline;
|
timeline;
|
||||||
last_time;
|
|
||||||
formatter;
|
|
||||||
timeline_for_ui;
|
|
||||||
owner;
|
owner;
|
||||||
index_in_owner;
|
index_in_owner;
|
||||||
rows_container;
|
rows_container;
|
||||||
row_height;
|
row_height;
|
||||||
row_gap;
|
row_gap;
|
||||||
row_height_with_gap;
|
row_height_with_gap;
|
||||||
renderer_resize_callback = () => this.redraw_on_canvas_resize();
|
renderer_resize_callback = () => this.draw();
|
||||||
// -- elements --
|
|
||||||
row_container = new Container();
|
row_container = new Container();
|
||||||
signal_blocks_container = new Container();
|
signal_blocks_container = new Container();
|
||||||
label_style = new TextStyle({
|
label_style = new TextStyle({
|
||||||
|
@ -35208,12 +35207,6 @@ var VarSignalRow = class {
|
||||||
constructor(timeline, app, owner, rows_container, row_height, row_gap) {
|
constructor(timeline, app, owner, rows_container, row_height, row_gap) {
|
||||||
this.app = app;
|
this.app = app;
|
||||||
this.timeline = timeline;
|
this.timeline = timeline;
|
||||||
this.last_time = timeline[timeline.length - 1][0];
|
|
||||||
this.formatter = (signal_value) => parseInt(signal_value, 2).toString(16);
|
|
||||||
this.timeline_for_ui = this.timeline.map(([time, value]) => {
|
|
||||||
const x2 = time / this.last_time * this.app.screen.width;
|
|
||||||
return [x2, this.formatter(value)];
|
|
||||||
});
|
|
||||||
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;
|
||||||
|
@ -35221,90 +35214,26 @@ var VarSignalRow = class {
|
||||||
this.owner = owner;
|
this.owner = owner;
|
||||||
this.owner.push(this);
|
this.owner.push(this);
|
||||||
this.rows_container = rows_container;
|
this.rows_container = rows_container;
|
||||||
this.draw();
|
|
||||||
this.app.renderer.on("resize", this.renderer_resize_callback);
|
|
||||||
}
|
|
||||||
async draw() {
|
|
||||||
this.row_container.y = this.index_in_owner * this.row_height_with_gap;
|
this.row_container.y = this.index_in_owner * this.row_height_with_gap;
|
||||||
this.rows_container.addChild(this.row_container);
|
this.rows_container.addChild(this.row_container);
|
||||||
this.row_container.addChild(this.signal_blocks_container);
|
this.row_container.addChild(this.signal_blocks_container);
|
||||||
for (let index = 0; index < this.timeline_for_ui.length; index++) {
|
this.draw();
|
||||||
if (index == this.timeline_for_ui.length - 1) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
await new Promise((resolve) => setTimeout(resolve, 0));
|
|
||||||
const [x2, value] = this.timeline_for_ui[index];
|
|
||||||
const block_width = this.timeline_for_ui[index + 1][0] - x2;
|
|
||||||
const block_height = this.row_height;
|
|
||||||
if (block_width < MIN_BLOCK_WIDTH) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
const signal_block = new Container();
|
|
||||||
signal_block.x = x2;
|
|
||||||
this.signal_blocks_container.addChild(signal_block);
|
|
||||||
const background = new Graphics().roundRect(0, 0, block_width, block_height, 15).fill("SlateBlue");
|
|
||||||
background.label = "background";
|
|
||||||
signal_block.addChild(background);
|
|
||||||
const label = new Text({ text: value, style: this.label_style });
|
|
||||||
label.x = (block_width - label.width) / 2;
|
|
||||||
label.y = (block_height - label.height) / 2;
|
|
||||||
label.visible = label.width < block_width;
|
|
||||||
label.label = "label";
|
|
||||||
signal_block.addChild(label);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
async redraw_on_canvas_resize() {
|
draw() {
|
||||||
for (let index = 0; index < this.timeline_for_ui.length; index++) {
|
this.signal_blocks_container.removeChildren();
|
||||||
const x2 = this.timeline[index][0] / this.last_time * this.app.screen.width;
|
this.timeline.blocks.forEach((timeline_block) => {
|
||||||
this.timeline_for_ui[index][0] = x2;
|
const signal_block = new Container();
|
||||||
}
|
signal_block.x = timeline_block.x;
|
||||||
for (let index = 0; index < this.timeline_for_ui.length; index++) {
|
this.signal_blocks_container.addChild(signal_block);
|
||||||
if (index == this.timeline_for_ui.length - 1) {
|
const background = new Graphics().roundRect(0, 0, timeline_block.width, this.row_height, 15).fill("SlateBlue");
|
||||||
return;
|
signal_block.addChild(background);
|
||||||
|
if (timeline_block.label !== void 0) {
|
||||||
|
const label = new Text({ text: timeline_block.label.text, style: this.label_style });
|
||||||
|
label.x = timeline_block.label.x;
|
||||||
|
label.y = timeline_block.label.y;
|
||||||
|
signal_block.addChild(label);
|
||||||
}
|
}
|
||||||
await new Promise((resolve) => setTimeout(resolve, 0));
|
});
|
||||||
const [x2, value] = this.timeline_for_ui[index];
|
|
||||||
const block_width = this.timeline_for_ui[index + 1][0] - x2;
|
|
||||||
const block_height = this.row_height;
|
|
||||||
const block_visible = block_width >= MIN_BLOCK_WIDTH;
|
|
||||||
let signal_block = this.signal_blocks_container.children[index];
|
|
||||||
if (signal_block === void 0 && !block_visible) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (signal_block !== void 0 && !block_visible) {
|
|
||||||
signal_block.visible = false;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (signal_block === void 0 && block_visible) {
|
|
||||||
signal_block = new Container();
|
|
||||||
signal_block.x = x2;
|
|
||||||
this.signal_blocks_container.addChild(signal_block);
|
|
||||||
} else if (signal_block !== void 0 && block_visible) {
|
|
||||||
signal_block.visible = true;
|
|
||||||
signal_block.x = x2;
|
|
||||||
}
|
|
||||||
let background = signal_block.getChildByLabel("background");
|
|
||||||
if (background === null) {
|
|
||||||
background = new Graphics().roundRect(0, 0, block_width, block_height, 15).fill("SlateBlue");
|
|
||||||
background.label = "background";
|
|
||||||
signal_block.addChild(background);
|
|
||||||
} else {
|
|
||||||
background.width = block_width;
|
|
||||||
}
|
|
||||||
const label = signal_block.getChildByLabel("label");
|
|
||||||
if (label === null) {
|
|
||||||
const label2 = new Text({ text: value, style: this.label_style });
|
|
||||||
label2.x = (block_width - label2.width) / 2;
|
|
||||||
label2.y = (block_height - label2.height) / 2;
|
|
||||||
label2.visible = label2.width < block_width;
|
|
||||||
label2.label = "label";
|
|
||||||
signal_block.addChild(label2);
|
|
||||||
} else {
|
|
||||||
label.x = (block_width - label.width) / 2;
|
|
||||||
label.y = (block_height - label.height) / 2;
|
|
||||||
label.visible = label.width < block_width;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
decrement_index() {
|
decrement_index() {
|
||||||
this.index_in_owner--;
|
this.index_in_owner--;
|
||||||
|
|
|
@ -2526,6 +2526,9 @@ async function get_time_table() {
|
||||||
async function load_and_get_signal(signal_ref_index) {
|
async function load_and_get_signal(signal_ref_index) {
|
||||||
return await invoke2("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 unload_signal(signal_ref_index) {
|
async function unload_signal(signal_ref_index) {
|
||||||
return await invoke2("unload_signal", { signal_ref_index });
|
return await invoke2("unload_signal", { signal_ref_index });
|
||||||
}
|
}
|
||||||
|
@ -2535,5 +2538,6 @@ export {
|
||||||
load_and_get_signal,
|
load_and_get_signal,
|
||||||
pick_and_load_waveform,
|
pick_and_load_waveform,
|
||||||
show_window,
|
show_window,
|
||||||
|
timeline,
|
||||||
unload_signal
|
unload_signal
|
||||||
};
|
};
|
||||||
|
|
|
@ -1,13 +1,19 @@
|
||||||
import { Application, Text, Graphics, Container, TextStyle, ContainerChild } from "pixi.js";
|
import { Application, Text, Graphics, Container, TextStyle, ContainerChild } from "pixi.js";
|
||||||
|
|
||||||
type Time = number;
|
// @TODO sync with Rust and `tauri_glue.ts`
|
||||||
type BitString = string;
|
type Timeline = {
|
||||||
type Timeline = Array<[Time, BitString]>;
|
blocks: Array<TimelineBlock>
|
||||||
|
}
|
||||||
type X = number;
|
type TimelineBlock = {
|
||||||
type TimelineForUI = Array<[X, string]>;
|
x: number,
|
||||||
|
width: number,
|
||||||
const MIN_BLOCK_WIDTH = 1;
|
label: TimeLineBlockLabel | undefined,
|
||||||
|
}
|
||||||
|
type TimeLineBlockLabel = {
|
||||||
|
text: string,
|
||||||
|
x: number,
|
||||||
|
y: number,
|
||||||
|
}
|
||||||
|
|
||||||
export class PixiController {
|
export class PixiController {
|
||||||
app: Application
|
app: Application
|
||||||
|
@ -48,6 +54,10 @@ export class PixiController {
|
||||||
this.app.destroy(rendererDestroyOptions, options);
|
this.app.destroy(rendererDestroyOptions, options);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
screen_width() {
|
||||||
|
return this.app.screen.width;
|
||||||
|
}
|
||||||
|
|
||||||
// -- FastWave-specific --
|
// -- FastWave-specific --
|
||||||
|
|
||||||
remove_var(index: number) {
|
remove_var(index: number) {
|
||||||
|
@ -57,6 +67,7 @@ export class PixiController {
|
||||||
}
|
}
|
||||||
|
|
||||||
push_var(timeline: Timeline) {
|
push_var(timeline: Timeline) {
|
||||||
|
console.log("Timline in Typescript:", timeline);
|
||||||
new VarSignalRow(
|
new VarSignalRow(
|
||||||
timeline,
|
timeline,
|
||||||
this.app,
|
this.app,
|
||||||
|
@ -79,17 +90,13 @@ export class PixiController {
|
||||||
class VarSignalRow {
|
class VarSignalRow {
|
||||||
app: Application;
|
app: Application;
|
||||||
timeline: Timeline;
|
timeline: Timeline;
|
||||||
last_time: Time;
|
|
||||||
formatter: (signal_value: BitString) => string;
|
|
||||||
timeline_for_ui: TimelineForUI;
|
|
||||||
owner: Array<VarSignalRow>;
|
owner: Array<VarSignalRow>;
|
||||||
index_in_owner: number;
|
index_in_owner: number;
|
||||||
rows_container: Container;
|
rows_container: Container;
|
||||||
row_height: number;
|
row_height: number;
|
||||||
row_gap: number;
|
row_gap: number;
|
||||||
row_height_with_gap: number;
|
row_height_with_gap: number;
|
||||||
renderer_resize_callback = () => this.redraw_on_canvas_resize();
|
renderer_resize_callback = () => this.draw();
|
||||||
// -- elements --
|
|
||||||
row_container = new Container();
|
row_container = new Container();
|
||||||
signal_blocks_container = new Container();
|
signal_blocks_container = new Container();
|
||||||
label_style = new TextStyle({
|
label_style = new TextStyle({
|
||||||
|
@ -110,13 +117,6 @@ class VarSignalRow {
|
||||||
this.app = app;
|
this.app = app;
|
||||||
|
|
||||||
this.timeline = timeline;
|
this.timeline = timeline;
|
||||||
this.last_time = timeline[timeline.length - 1][0];
|
|
||||||
this.formatter = signal_value => parseInt(signal_value, 2).toString(16);
|
|
||||||
|
|
||||||
this.timeline_for_ui = this.timeline.map(([time, value]) => {
|
|
||||||
const x = time / this.last_time * this.app.screen.width;
|
|
||||||
return [x, this.formatter(value)]
|
|
||||||
});
|
|
||||||
|
|
||||||
this.row_height = row_height;
|
this.row_height = row_height;
|
||||||
this.row_gap = row_gap;
|
this.row_gap = row_gap;
|
||||||
|
@ -128,113 +128,43 @@ class VarSignalRow {
|
||||||
|
|
||||||
this.rows_container = rows_container;
|
this.rows_container = rows_container;
|
||||||
|
|
||||||
this.draw();
|
|
||||||
this.app.renderer.on("resize", this.renderer_resize_callback);
|
|
||||||
}
|
|
||||||
|
|
||||||
async draw() {
|
|
||||||
// row_container
|
// row_container
|
||||||
this.row_container.y = this.index_in_owner * this.row_height_with_gap;
|
this.row_container.y = this.index_in_owner * this.row_height_with_gap;
|
||||||
this.rows_container.addChild(this.row_container);
|
this.rows_container.addChild(this.row_container);
|
||||||
|
|
||||||
// signal_block_container
|
// signal_blocks_container
|
||||||
this.row_container.addChild(this.signal_blocks_container);
|
this.row_container.addChild(this.signal_blocks_container);
|
||||||
|
|
||||||
for (let index = 0; index < this.timeline_for_ui.length; index++) {
|
this.draw();
|
||||||
if (index == this.timeline_for_ui.length - 1) {
|
// this.app.renderer.on("resize", (width, height) => {
|
||||||
return;
|
// // @TODO only on `width` change
|
||||||
}
|
// // @TODO inline `renderer_resize_callback`?
|
||||||
await new Promise(resolve => setTimeout(resolve, 0));
|
// this.draw();
|
||||||
const [x, value] = this.timeline_for_ui[index];
|
// });
|
||||||
|
}
|
||||||
|
|
||||||
|
draw() {
|
||||||
|
this.signal_blocks_container.removeChildren();
|
||||||
|
this.timeline.blocks.forEach(timeline_block => {
|
||||||
// signal_block
|
// signal_block
|
||||||
const block_width = this.timeline_for_ui[index+1][0] - x;
|
|
||||||
const block_height = this.row_height;
|
|
||||||
if (block_width < MIN_BLOCK_WIDTH) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
const signal_block = new Container();
|
const signal_block = new Container();
|
||||||
signal_block.x = x;
|
signal_block.x = timeline_block.x;
|
||||||
this.signal_blocks_container.addChild(signal_block);
|
this.signal_blocks_container.addChild(signal_block);
|
||||||
|
|
||||||
// background
|
// background
|
||||||
const background = new Graphics()
|
const background = new Graphics()
|
||||||
.roundRect(0, 0, block_width, block_height, 15)
|
.roundRect(0, 0, timeline_block.width, this.row_height, 15)
|
||||||
.fill("SlateBlue");
|
.fill("SlateBlue");
|
||||||
background.label = "background";
|
|
||||||
signal_block.addChild(background);
|
signal_block.addChild(background);
|
||||||
|
|
||||||
// label
|
// label
|
||||||
const label = new Text({ text: value, style: this.label_style });
|
if (timeline_block.label !== undefined) {
|
||||||
label.x = (block_width - label.width) / 2;
|
const label = new Text({ text: timeline_block.label.text, style: this.label_style });
|
||||||
label.y = (block_height - label.height) / 2;
|
label.x = timeline_block.label.x;
|
||||||
label.visible = label.width < block_width;
|
label.y = timeline_block.label.y;
|
||||||
label.label = "label";
|
|
||||||
signal_block.addChild(label);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
async redraw_on_canvas_resize() {
|
|
||||||
for (let index = 0; index < this.timeline_for_ui.length; index++) {
|
|
||||||
const x = this.timeline[index][0] / this.last_time * this.app.screen.width;
|
|
||||||
this.timeline_for_ui[index][0] = x;
|
|
||||||
}
|
|
||||||
for (let index = 0; index < this.timeline_for_ui.length; index++) {
|
|
||||||
if (index == this.timeline_for_ui.length - 1) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
await new Promise(resolve => setTimeout(resolve, 0));
|
|
||||||
const [x, value] = this.timeline_for_ui[index];
|
|
||||||
|
|
||||||
// signal_block
|
|
||||||
const block_width = this.timeline_for_ui[index+1][0] - x;
|
|
||||||
const block_height = this.row_height;
|
|
||||||
const block_visible = block_width >= MIN_BLOCK_WIDTH;
|
|
||||||
|
|
||||||
let signal_block: ContainerChild | undefined = this.signal_blocks_container.children[index];
|
|
||||||
if (signal_block === undefined && !block_visible) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (signal_block !== undefined && !block_visible) {
|
|
||||||
signal_block.visible = false;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (signal_block === undefined && block_visible) {
|
|
||||||
signal_block = new Container();
|
|
||||||
signal_block.x = x;
|
|
||||||
this.signal_blocks_container.addChild(signal_block);
|
|
||||||
} else if (signal_block !== undefined && block_visible) {
|
|
||||||
signal_block.visible = true;
|
|
||||||
signal_block.x = x;
|
|
||||||
}
|
|
||||||
|
|
||||||
// background
|
|
||||||
let background = signal_block.getChildByLabel("background");
|
|
||||||
if (background === null) {
|
|
||||||
background = new Graphics()
|
|
||||||
.roundRect(0, 0, block_width, block_height, 15)
|
|
||||||
.fill("SlateBlue");
|
|
||||||
background.label = "background";
|
|
||||||
signal_block.addChild(background);
|
|
||||||
} else {
|
|
||||||
background.width = block_width;
|
|
||||||
}
|
|
||||||
|
|
||||||
// label
|
|
||||||
const label = signal_block.getChildByLabel("label");
|
|
||||||
if (label === null ) {
|
|
||||||
const label = new Text({ text: value, style: this.label_style });
|
|
||||||
label.x = (block_width - label.width) / 2;
|
|
||||||
label.y = (block_height - label.height) / 2;
|
|
||||||
label.visible = label.width < block_width;
|
|
||||||
label.label = "label";
|
|
||||||
signal_block.addChild(label);
|
signal_block.addChild(label);
|
||||||
} else {
|
|
||||||
label.x = (block_width - label.width) / 2;
|
|
||||||
label.y = (block_height - label.height) / 2;
|
|
||||||
label.visible = label.width < block_width;
|
|
||||||
}
|
}
|
||||||
}
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
decrement_index() {
|
decrement_index() {
|
||||||
|
|
|
@ -8,6 +8,7 @@ type Filename = string;
|
||||||
type WellenHierarchy = unknown;
|
type WellenHierarchy = unknown;
|
||||||
type WellenTimeTable = unknown;
|
type WellenTimeTable = unknown;
|
||||||
type WellenSignal = unknown;
|
type WellenSignal = unknown;
|
||||||
|
type Timeline = unknown;
|
||||||
|
|
||||||
export async function show_window(): Promise<void> {
|
export async function show_window(): Promise<void> {
|
||||||
return await invoke("show_window");
|
return await invoke("show_window");
|
||||||
|
@ -29,6 +30,10 @@ export async function load_and_get_signal(signal_ref_index: number): Promise<Wel
|
||||||
return await invoke("load_and_get_signal", { signal_ref_index });
|
return await invoke("load_and_get_signal", { signal_ref_index });
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export async function timeline(signal_ref_index: number, screen_width: number): Promise<Timeline> {
|
||||||
|
return await invoke("timeline", { signal_ref_index, screen_width });
|
||||||
|
}
|
||||||
|
|
||||||
export async function unload_signal(signal_ref_index: number): Promise<void> {
|
export async function unload_signal(signal_ref_index: number): Promise<void> {
|
||||||
return await invoke("unload_signal", { signal_ref_index });
|
return await invoke("unload_signal", { signal_ref_index });
|
||||||
}
|
}
|
||||||
|
|
|
@ -9,3 +9,10 @@ publish.workspace = true
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
wellen.workspace = true
|
wellen.workspace = true
|
||||||
|
moonlight.workspace = true
|
||||||
|
# @TODO update `futures_util_ext` - add feature `sink`, set exact `futures-util` version
|
||||||
|
futures-util = { version = "0.3.30", features = ["sink"] }
|
||||||
|
|
||||||
|
[features]
|
||||||
|
frontend = ["moonlight/frontend"]
|
||||||
|
backend = ["moonlight/backend"]
|
||||||
|
|
|
@ -1 +1,25 @@
|
||||||
|
use moonlight::*;
|
||||||
|
|
||||||
pub mod wellen_helpers;
|
pub mod wellen_helpers;
|
||||||
|
|
||||||
|
#[derive(Serialize, Deserialize, Debug)]
|
||||||
|
#[serde(crate = "serde")]
|
||||||
|
pub struct Timeline {
|
||||||
|
pub blocks: Vec<TimelineBlock>
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Serialize, Deserialize, Debug)]
|
||||||
|
#[serde(crate = "serde")]
|
||||||
|
pub struct TimelineBlock {
|
||||||
|
pub x: u32,
|
||||||
|
pub width: u32,
|
||||||
|
pub label: Option<TimeLineBlockLabel>,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Serialize, Deserialize, Debug)]
|
||||||
|
#[serde(crate = "serde")]
|
||||||
|
pub struct TimeLineBlockLabel {
|
||||||
|
pub text: String,
|
||||||
|
pub x: u32,
|
||||||
|
pub y: u32,
|
||||||
|
}
|
||||||
|
|
|
@ -16,8 +16,8 @@ crate-type = ["staticlib", "cdylib", "rlib"]
|
||||||
tauri-build = { version = "=2.0.0-beta.17", features = [] }
|
tauri-build = { version = "=2.0.0-beta.17", features = [] }
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
shared.workspace = true
|
|
||||||
wellen.workspace = true
|
wellen.workspace = true
|
||||||
|
shared = { path = "../shared", features = ["backend"] }
|
||||||
serde_json = "1.0"
|
serde_json = "1.0"
|
||||||
serde = { version = "1.0", features = ["derive"] }
|
serde = { version = "1.0", features = ["derive"] }
|
||||||
tauri = { version = "=2.0.0-beta.22", features = ["macos-private-api", "linux-ipc-protocol"] }
|
tauri = { version = "=2.0.0-beta.22", features = ["macos-private-api", "linux-ipc-protocol"] }
|
||||||
|
|
|
@ -61,6 +61,25 @@ async fn load_and_get_signal(
|
||||||
Ok(serde_json::to_value(signal).unwrap())
|
Ok(serde_json::to_value(signal).unwrap())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[tauri::command(rename_all = "snake_case")]
|
||||||
|
async fn timeline(
|
||||||
|
signal_ref_index: usize,
|
||||||
|
screen_width: u32,
|
||||||
|
store: tauri::State<'_, Store>,
|
||||||
|
) -> Result<serde_json::Value, ()> {
|
||||||
|
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() };
|
||||||
|
|
||||||
|
Ok(serde_json::to_value(timeline).unwrap())
|
||||||
|
}
|
||||||
|
|
||||||
#[tauri::command(rename_all = "snake_case")]
|
#[tauri::command(rename_all = "snake_case")]
|
||||||
async fn unload_signal(signal_ref_index: usize, store: tauri::State<'_, Store>) -> Result<(), ()> {
|
async fn unload_signal(signal_ref_index: usize, store: tauri::State<'_, Store>) -> Result<(), ()> {
|
||||||
let signal_ref = wellen::SignalRef::from_index(signal_ref_index).unwrap();
|
let signal_ref = wellen::SignalRef::from_index(signal_ref_index).unwrap();
|
||||||
|
@ -87,6 +106,7 @@ pub fn run() {
|
||||||
get_hierarchy,
|
get_hierarchy,
|
||||||
get_time_table,
|
get_time_table,
|
||||||
load_and_get_signal,
|
load_and_get_signal,
|
||||||
|
timeline,
|
||||||
unload_signal,
|
unload_signal,
|
||||||
])
|
])
|
||||||
.run(tauri::generate_context!())
|
.run(tauri::generate_context!())
|
||||||
|
|
Loading…
Reference in a new issue