Colors, Icons #16
12
.vscode/settings.json
vendored
Normal file
|
@ -0,0 +1,12 @@
|
|||
{
|
||||
"rust-analyzer.cargo.cfgs": {
|
||||
"FASTWAVE_PLATFORM": "TAURI",
|
||||
// "FASTWAVE_PLATFORM": "BROWSER",
|
||||
},
|
||||
// https://github.com/rustwasm/wasm-bindgen/issues/2339#issuecomment-2147636233
|
||||
"rust-analyzer.cargo.extraEnv": {
|
||||
"RUSTFLAGS": "--cfg=web_sys_unstable_apis"
|
||||
},
|
||||
// to prevent rebuilding from scratch on each change
|
||||
"rust-analyzer.cargo.target": "wasm32-unknown-unknown"
|
||||
}
|
29
README.md
|
@ -3,6 +3,27 @@
|
|||
|
||||
---
|
||||
|
||||
<p align="center">Default state - Dark (new design)</p>
|
||||
<p align="center">
|
||||
<img width="800" src="docs/home_dark.png" alt="Fastwave - Default state - Dark (not implemented yet)" />
|
||||
</p>
|
||||
|
||||
<p align="center">Loaded files - Dark (new design)</p>
|
||||
<p align="center">
|
||||
<img width="800" src="docs/loaded_files_dark.png" alt="Fastwave - Loaded files - Dark (not implemented yet)" />
|
||||
</p>
|
||||
|
||||
<p align="center">Default state - Light (new design)</p>
|
||||
<p align="center">
|
||||
<img width="800" src="docs/home_light.png" alt="Fastwave - Default state - Light (not implemented yet)" />
|
||||
</p>
|
||||
|
||||
<p align="center">Loaded files - Light (new design)</p>
|
||||
<p align="center">
|
||||
<img width="800" src="docs/loaded_files_light.png" alt="Fastwave - Loaded files - Light (not implemented yet)" />
|
||||
</p>
|
||||
|
||||
|
||||
<p align="center">Browser (Firefox)</p>
|
||||
<p align="center">
|
||||
<img width="800" src="docs/screenshot_firefox.png" alt="Fastwave - Browser (Firefox)" />
|
||||
|
@ -33,7 +54,7 @@
|
|||
<img width="800" src="docs/video_load_save_selected_vars.gif" alt="Fastwave - Load and save selected variables" />
|
||||
</p>
|
||||
|
||||
<p align="center">Decoders Demo</p>
|
||||
<p align="center">Decoders (Plugins) Demo</p>
|
||||
<p align="center">
|
||||
<img width="800" src="docs/video_decoders.gif" alt="Fastwave - Decoders demo" />
|
||||
</p>
|
||||
|
@ -97,7 +118,13 @@ Troubleshooting:
|
|||
|
||||
1. `makers format`
|
||||
|
||||
---
|
||||
|
||||
### Rebuild Decoders:
|
||||
|
||||
See `test_files/components/[language]_decoder/README.md`
|
||||
|
||||
---
|
||||
|
||||
### Test files
|
||||
|
||||
|
|
8
backend/favicon.html
Normal file
|
@ -0,0 +1,8 @@
|
|||
<link rel="apple-touch-icon" sizes="180x180" href="/_api/public/favicon/apple-touch-icon.png">
|
||||
<link rel="icon" type="image/png" sizes="32x32" href="/_api/public/favicon/favicon-32x32.png">
|
||||
<link rel="icon" type="image/png" sizes="16x16" href="/_api/public/favicon/favicon-16x16.png">
|
||||
<link rel="manifest" href="/_api/public/favicon/site.webmanifest">
|
||||
<link rel="shortcut icon" href="/_api/public/favicon/favicon.ico">
|
||||
<meta name="msapplication-TileColor" content="#00a300">
|
||||
<meta name="msapplication-config" content="/_api/public/favicon/browserconfig.xml">
|
||||
<meta name="theme-color" content="#ffffff">
|
|
@ -3,6 +3,7 @@ use moon::*;
|
|||
async fn frontend() -> Frontend {
|
||||
Frontend::new()
|
||||
.title("FastWave")
|
||||
.append_to_head(include_str!("../favicon.html")) // realfavicongenerator.net
|
||||
.append_to_head(concat!("<style>", include_str!("../style.css"), "</style>"))
|
||||
.append_to_head(concat!(
|
||||
"<script type=\"module\">",
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
html {
|
||||
background-color: DarkSlateBlue;
|
||||
}
|
||||
/* background-color: DarkSlateBlue; */
|
||||
background-color: oklch(41.43% 0.125 262.26);
|
||||
}
|
||||
|
|
BIN
docs/fastwave_logo.png
Normal file
After Width: | Height: | Size: 546 KiB |
BIN
docs/fastwave_logo_square.png
Normal file
After Width: | Height: | Size: 378 KiB |
BIN
docs/home_dark.png
Normal file
After Width: | Height: | Size: 94 KiB |
BIN
docs/home_light.png
Normal file
After Width: | Height: | Size: 92 KiB |
BIN
docs/loaded_files_dark.png
Normal file
After Width: | Height: | Size: 168 KiB |
BIN
docs/loaded_files_light.png
Normal file
After Width: | Height: | Size: 166 KiB |
|
@ -10,6 +10,9 @@ publish.workspace = true
|
|||
[dev-dependencies]
|
||||
wasm-bindgen-test = "0.3.19"
|
||||
|
||||
[lints.rust]
|
||||
unexpected_cfgs = { level = "allow", check-cfg = ['cfg(FASTWAVE_PLATFORM)'] }
|
||||
|
||||
[dependencies]
|
||||
zoon.workspace = true
|
||||
wellen.workspace = true
|
||||
|
|
141
frontend/src/command_panel.rs
Normal file
|
@ -0,0 +1,141 @@
|
|||
use crate::{script_bridge, theme::*};
|
||||
use zoon::*;
|
||||
|
||||
pub struct CommandPanel {}
|
||||
|
||||
impl CommandPanel {
|
||||
pub fn new() -> impl Element {
|
||||
Self {}.root()
|
||||
}
|
||||
|
||||
fn root(&self) -> impl Element {
|
||||
let command_result: Mutable<Option<Result<JsValue, JsValue>>> = <_>::default();
|
||||
Row::new()
|
||||
.s(Align::new().top())
|
||||
.s(Gap::both(30))
|
||||
.s(Width::fill())
|
||||
.s(Padding::new().x(20).bottom(20))
|
||||
.item(self.command_editor_panel(command_result.clone()))
|
||||
.item(self.command_result_panel(command_result.read_only()))
|
||||
}
|
||||
|
||||
fn command_editor_panel(
|
||||
&self,
|
||||
command_result: Mutable<Option<Result<JsValue, JsValue>>>,
|
||||
) -> impl Element {
|
||||
Column::new()
|
||||
.s(Align::new().top())
|
||||
.s(Gap::new().y(10))
|
||||
.s(Width::growable())
|
||||
.item(
|
||||
Row::new()
|
||||
.s(Gap::new().x(15))
|
||||
.s(Padding::new().x(5))
|
||||
.item(El::new().child("Javascript commands"))
|
||||
.item(El::new().s(Align::new().right()).child("Shift + Enter")),
|
||||
)
|
||||
.item(self.command_editor(command_result))
|
||||
}
|
||||
|
||||
fn command_editor(
|
||||
&self,
|
||||
command_result: Mutable<Option<Result<JsValue, JsValue>>>,
|
||||
) -> impl Element {
|
||||
let (script, script_signal) = Mutable::new_and_signal_cloned(String::new());
|
||||
// @TODO perhaps replace with an element with syntax highlighter like https://github.com/WebCoder49/code-input later
|
||||
TextArea::new()
|
||||
.s(Background::new().color(COLOR_SLATE_BLUE))
|
||||
.s(Padding::new().x(10).y(8))
|
||||
.s(RoundedCorners::all(15))
|
||||
.s(Height::default().min(50))
|
||||
.s(Width::fill().min(300))
|
||||
.s(Font::new()
|
||||
.tracking(1)
|
||||
.weight(FontWeight::Medium)
|
||||
.color(COLOR_WHITE)
|
||||
.family([FontFamily::new("Courier New"), FontFamily::Monospace]))
|
||||
.s(Shadows::new([Shadow::new()
|
||||
.inner()
|
||||
.color(COLOR_DARK_SLATE_BLUE)
|
||||
.blur(4)]))
|
||||
// @TODO `spellcheck` and `resize` to MZ API? (together with autocomplete and others?)
|
||||
.update_raw_el(|raw_el| {
|
||||
raw_el
|
||||
.attr("spellcheck", "false")
|
||||
.style("resize", "vertical")
|
||||
})
|
||||
.placeholder(Placeholder::new("FW.say_hello()").s(Font::new().color(COLOR_LIGHT_BLUE)))
|
||||
.label_hidden("command editor panel")
|
||||
.text_signal(script_signal)
|
||||
.on_change(clone!((script, command_result) move |text| {
|
||||
script.set_neq(text);
|
||||
command_result.set_neq(None);
|
||||
}))
|
||||
.on_key_down_event_with_options(EventOptions::new().preventable(), move |event| {
|
||||
if event.key() == &Key::Enter {
|
||||
let RawKeyboardEvent::KeyDown(raw_event) = event.raw_event.clone();
|
||||
if raw_event.shift_key() {
|
||||
// @TODO move `prevent_default` to MZ API (next to the `pass_to_parent` method?)
|
||||
raw_event.prevent_default();
|
||||
Task::start(clone!((script, command_result) async move {
|
||||
let result = script_bridge::strict_eval(&script.lock_ref()).await;
|
||||
command_result.set(Some(result));
|
||||
}));
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
fn command_result_panel(
|
||||
&self,
|
||||
command_result: ReadOnlyMutable<Option<Result<JsValue, JsValue>>>,
|
||||
) -> impl Element {
|
||||
Column::new()
|
||||
.s(Gap::new().y(10))
|
||||
.s(Align::new().top())
|
||||
.s(Scrollbars::both())
|
||||
.s(Padding::new().x(5))
|
||||
.s(Width::growable().max(750))
|
||||
.item(El::new().child("Command result"))
|
||||
.item(self.command_result_el(command_result))
|
||||
}
|
||||
|
||||
fn command_result_el(
|
||||
&self,
|
||||
command_result: ReadOnlyMutable<Option<Result<JsValue, JsValue>>>,
|
||||
) -> impl Element {
|
||||
El::new()
|
||||
.s(Font::new()
|
||||
.tracking(1)
|
||||
.weight(FontWeight::Medium)
|
||||
.color(COLOR_WHITE)
|
||||
.family([FontFamily::new("Courier New"), FontFamily::Monospace]))
|
||||
.s(Scrollbars::both())
|
||||
.s(Height::default().max(100))
|
||||
.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(),
|
||||
}
|
||||
}))
|
||||
}
|
||||
}
|
|
@ -1,4 +1,4 @@
|
|||
use crate::{Filename, Layout};
|
||||
use crate::{theme::*, Filename, Layout};
|
||||
use std::cell::Cell;
|
||||
use std::mem;
|
||||
use std::ops::Not;
|
||||
|
@ -238,9 +238,9 @@ impl ControlsPanel {
|
|||
let background_color = map_ref! {
|
||||
let is_selected = is_selected,
|
||||
let is_hovered = button_hovered_signal => match (*is_selected, *is_hovered) {
|
||||
(true, _) => color!("BlueViolet"),
|
||||
(false, true) => color!("MediumSlateBlue"),
|
||||
(false, false) => color!("SlateBlue"),
|
||||
(true, _) => COLOR_BLUE_VIOLET,
|
||||
(false, true) => COLOR_MEDIUM_SLATE_BLUE,
|
||||
(false, false) => COLOR_SLATE_BLUE,
|
||||
}
|
||||
};
|
||||
let task_collapse_on_parent_collapse = {
|
||||
|
@ -332,7 +332,7 @@ impl ControlsPanel {
|
|||
.map_true(|| 10),
|
||||
))
|
||||
.s(Height::fill())
|
||||
.s(Font::new().color_signal(hovered_signal.map_true(|| color!("LightBlue"))))
|
||||
.s(Font::new().color_signal(hovered_signal.map_true(|| COLOR_LIGHT_BLUE)))
|
||||
.label(
|
||||
El::new()
|
||||
.s(Transform::with_signal_self(layout_and_expanded.map(
|
||||
|
@ -488,7 +488,7 @@ impl ControlsPanel {
|
|||
Button::new()
|
||||
.s(Padding::new().x(15).y(5))
|
||||
.s(Background::new().color_signal(
|
||||
hovered_signal.map_bool(|| color!("MediumSlateBlue"), || color!("SlateBlue")),
|
||||
hovered_signal.map_bool(|| COLOR_MEDIUM_SLATE_BLUE, || COLOR_SLATE_BLUE),
|
||||
))
|
||||
.s(RoundedCorners::all(15))
|
||||
.on_hovered_change(move |is_hovered| hovered.set_neq(is_hovered))
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
use crate::{platform, script_bridge, Filename, Layout};
|
||||
use crate::{platform, theme::*, Filename, Layout};
|
||||
use std::sync::Arc;
|
||||
use zoon::*;
|
||||
|
||||
|
@ -34,7 +34,6 @@ impl HeaderPanel {
|
|||
.item(self.load_button())
|
||||
.item(self.layout_switcher()),
|
||||
)
|
||||
.item(self.command_panel())
|
||||
}
|
||||
|
||||
#[cfg(FASTWAVE_PLATFORM = "TAURI")]
|
||||
|
@ -45,7 +44,7 @@ impl HeaderPanel {
|
|||
Button::new()
|
||||
.s(Padding::new().x(20).y(10))
|
||||
.s(Background::new().color_signal(
|
||||
hovered_signal.map_bool(|| color!("MediumSlateBlue"), || color!("SlateBlue")),
|
||||
hovered_signal.map_bool(|| COLOR_MEDIUM_SLATE_BLUE, || COLOR_SLATE_BLUE),
|
||||
))
|
||||
.s(Align::new().left())
|
||||
.s(RoundedCorners::all(15))
|
||||
|
@ -85,8 +84,7 @@ impl HeaderPanel {
|
|||
Label::new()
|
||||
.s(Padding::new().x(20).y(10))
|
||||
.s(Background::new().color_signal(
|
||||
hovered_signal
|
||||
.map_bool(|| color!("MediumSlateBlue"), || color!("SlateBlue")),
|
||||
hovered_signal.map_bool(|| COLOR_MEDIUM_SLATE_BLUE, || COLOR_SLATE_BLUE),
|
||||
))
|
||||
.s(Align::new().left())
|
||||
.s(RoundedCorners::all(15))
|
||||
|
@ -154,7 +152,7 @@ impl HeaderPanel {
|
|||
Button::new()
|
||||
.s(Padding::new().x(20).y(10))
|
||||
.s(Background::new().color_signal(
|
||||
hovered_signal.map_bool(|| color!("MediumSlateBlue"), || color!("SlateBlue")),
|
||||
hovered_signal.map_bool(|| COLOR_MEDIUM_SLATE_BLUE, || COLOR_SLATE_BLUE),
|
||||
))
|
||||
.s(RoundedCorners::all(15))
|
||||
.label_signal(layout.signal().map(|layout| match layout {
|
||||
|
@ -169,137 +167,4 @@ impl HeaderPanel {
|
|||
})
|
||||
})
|
||||
}
|
||||
|
||||
fn command_panel(&self) -> impl Element {
|
||||
let command_result: Mutable<Option<Result<JsValue, JsValue>>> = <_>::default();
|
||||
Row::new()
|
||||
.s(Align::new().top())
|
||||
.s(Gap::both(30))
|
||||
.s(Scrollbars::both())
|
||||
.s(Width::fill())
|
||||
.item(self.command_editor_panel(command_result.clone()))
|
||||
.item(self.command_result_panel(command_result.read_only()))
|
||||
}
|
||||
|
||||
fn command_editor_panel(
|
||||
&self,
|
||||
command_result: Mutable<Option<Result<JsValue, JsValue>>>,
|
||||
) -> impl Element {
|
||||
Column::new()
|
||||
.s(Align::new().top())
|
||||
.s(Gap::new().y(10))
|
||||
.s(Width::growable())
|
||||
.item(
|
||||
Row::new()
|
||||
.s(Gap::new().x(15))
|
||||
.s(Padding::new().x(5))
|
||||
.item(El::new().child("Javascript commands"))
|
||||
.item(El::new().s(Align::new().right()).child("Shift + Enter")),
|
||||
)
|
||||
.item(self.command_editor(command_result))
|
||||
}
|
||||
|
||||
fn command_editor(
|
||||
&self,
|
||||
command_result: Mutable<Option<Result<JsValue, JsValue>>>,
|
||||
) -> impl Element {
|
||||
let (script, script_signal) = Mutable::new_and_signal_cloned(String::new());
|
||||
// @TODO perhaps replace with an element with syntax highlighter like https://github.com/WebCoder49/code-input later
|
||||
TextArea::new()
|
||||
.s(Background::new().color(color!("SlateBlue")))
|
||||
.s(Padding::new().x(10).y(8))
|
||||
.s(RoundedCorners::all(15))
|
||||
.s(Height::default().min(50))
|
||||
.s(Width::fill().min(300))
|
||||
.s(Font::new()
|
||||
.tracking(1)
|
||||
.weight(FontWeight::Medium)
|
||||
.color(color!("White"))
|
||||
.family([FontFamily::new("Courier New"), FontFamily::Monospace]))
|
||||
.s(Shadows::new([Shadow::new()
|
||||
.inner()
|
||||
.color(color!("DarkSlateBlue"))
|
||||
.blur(4)]))
|
||||
// @TODO `spellcheck` and `resize` to MZ API? (together with autocomplete and others?)
|
||||
.update_raw_el(|raw_el| {
|
||||
raw_el
|
||||
.attr("spellcheck", "false")
|
||||
.style("resize", "vertical")
|
||||
})
|
||||
.placeholder(
|
||||
Placeholder::new("FW.say_hello()").s(Font::new().color(color!("LightBlue"))),
|
||||
)
|
||||
.label_hidden("command editor panel")
|
||||
.text_signal(script_signal)
|
||||
.on_change(clone!((script, command_result) move |text| {
|
||||
script.set_neq(text);
|
||||
command_result.set_neq(None);
|
||||
}))
|
||||
.on_key_down_event_with_options(EventOptions::new().preventable(), move |event| {
|
||||
if event.key() == &Key::Enter {
|
||||
let RawKeyboardEvent::KeyDown(raw_event) = event.raw_event.clone();
|
||||
if raw_event.shift_key() {
|
||||
// @TODO move `prevent_default` to MZ API (next to the `pass_to_parent` method?)
|
||||
raw_event.prevent_default();
|
||||
Task::start(clone!((script, command_result) async move {
|
||||
let result = script_bridge::strict_eval(&script.lock_ref()).await;
|
||||
command_result.set(Some(result));
|
||||
}));
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
fn command_result_panel(
|
||||
&self,
|
||||
command_result: ReadOnlyMutable<Option<Result<JsValue, JsValue>>>,
|
||||
) -> impl Element {
|
||||
Column::new()
|
||||
.s(Gap::new().y(10))
|
||||
.s(Align::new().top())
|
||||
.s(Scrollbars::both())
|
||||
.s(Padding::new().x(5))
|
||||
.s(Width::growable().max(750))
|
||||
.item(El::new().child("Command result"))
|
||||
.item(self.command_result_el(command_result))
|
||||
}
|
||||
|
||||
fn command_result_el(
|
||||
&self,
|
||||
command_result: ReadOnlyMutable<Option<Result<JsValue, JsValue>>>,
|
||||
) -> impl Element {
|
||||
El::new()
|
||||
.s(Font::new()
|
||||
.tracking(1)
|
||||
.weight(FontWeight::Medium)
|
||||
.color(color!("White"))
|
||||
.family([FontFamily::new("Courier New"), FontFamily::Monospace]))
|
||||
.s(Scrollbars::both())
|
||||
.s(Height::default().max(100))
|
||||
.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(),
|
||||
}
|
||||
}))
|
||||
}
|
||||
}
|
||||
|
|
|
@ -13,6 +13,12 @@ use waveform_panel::{PixiController, WaveformPanel};
|
|||
mod header_panel;
|
||||
use header_panel::HeaderPanel;
|
||||
|
||||
mod command_panel;
|
||||
use command_panel::CommandPanel;
|
||||
|
||||
pub mod theme;
|
||||
use theme::*;
|
||||
|
||||
#[derive(Clone, Copy, Default)]
|
||||
enum Layout {
|
||||
Tree,
|
||||
|
@ -50,7 +56,7 @@ fn root() -> impl Element {
|
|||
Column::new()
|
||||
.s(Height::fill())
|
||||
.s(Scrollbars::y_and_clip_x())
|
||||
.s(Font::new().color(color!("Lavender")))
|
||||
.s(Font::new().color(COLOR_LAVENDER))
|
||||
.item(HeaderPanel::new(
|
||||
hierarchy.clone(),
|
||||
layout.clone(),
|
||||
|
@ -98,4 +104,5 @@ fn root() -> impl Element {
|
|||
}
|
||||
}
|
||||
)
|
||||
.item(CommandPanel::new())
|
||||
}
|
||||
|
|
27
frontend/src/theme.rs
Normal file
|
@ -0,0 +1,27 @@
|
|||
use zoon::*;
|
||||
|
||||
// https://oklch.com/
|
||||
|
||||
// pub const COLOR_BLUE_VIOLET: Rgba = color!("BlueViolet"); // oklch(53.38% 0.25 301.37)
|
||||
pub const COLOR_BLUE_VIOLET: Oklch = color!("oklch(53.38% 0.25 262.59)");
|
||||
|
||||
// pub const COLOR_MEDIUM_SLATE_BLUE: Rgba = color!("MediumSlateBlue"); // oklch(60.45% 0.194 285.5)
|
||||
pub const COLOR_MEDIUM_SLATE_BLUE: Oklch = color!("oklch(60.45% 0.194 262.26)");
|
||||
|
||||
// pub const COLOR_SLATE_BLUE_WITH_ALPHA: Rgba = color!("SlateBlue", 0.8); // oklch(54.36% 0.171 285.54)
|
||||
pub const COLOR_SLATE_BLUE_WITH_ALPHA: Oklch = color!("oklch(54.36% 0.171 262.26)", 0.8);
|
||||
|
||||
// pub const COLOR_SLATE_BLUE: Rgba = color!("SlateBlue"); // oklch(54.36% 0.171 285.54)
|
||||
pub const COLOR_SLATE_BLUE: Oklch = color!("oklch(54.36% 0.171 262.26)");
|
||||
|
||||
// pub const COLOR_LIGHT_BLUE: Rgba = color!("LightBlue"); // oklch(85.62% 0.049 219.65)
|
||||
pub const COLOR_LIGHT_BLUE: Oklch = color!("oklch(85.62% 0.049 262.26)");
|
||||
|
||||
// pub const COLOR_WHITE: Rgba = color!("White"); // oklch(100% 3.5594404384177905e-8 106.37411429114086)
|
||||
pub const COLOR_WHITE: Oklch = color!("oklch(100% 3.5594404384177905e-8 105.88)");
|
||||
|
||||
// pub const COLOR_DARK_SLATE_BLUE: Rgba = color!("DarkSlateBlue"); // oklch(41.43% 0.125 286.04)
|
||||
pub const COLOR_DARK_SLATE_BLUE: Oklch = color!("oklch(41.43% 0.125 262.26)");
|
||||
|
||||
// pub const COLOR_LAVENDER: Rgba = color!("Lavender"); // oklch(93.09% 0.027 285.86)
|
||||
pub const COLOR_LAVENDER: Oklch = color!("oklch(93.09% 0.027 262.26)");
|
|
@ -1,4 +1,4 @@
|
|||
use crate::{platform, script_bridge, Filename};
|
||||
use crate::{platform, script_bridge, theme::*, Filename};
|
||||
use std::sync::Arc;
|
||||
use wellen::GetItem;
|
||||
use zoon::*;
|
||||
|
@ -87,7 +87,7 @@ impl WaveformPanel {
|
|||
Button::new()
|
||||
.s(Padding::new().x(20).y(10))
|
||||
.s(Background::new().color_signal(
|
||||
hovered_signal.map_bool(|| color!("MediumSlateBlue"), || color!("SlateBlue")),
|
||||
hovered_signal.map_bool(|| COLOR_MEDIUM_SLATE_BLUE, || COLOR_SLATE_BLUE),
|
||||
))
|
||||
.s(Align::new().left())
|
||||
.s(RoundedCorners::all(15))
|
||||
|
@ -122,8 +122,7 @@ impl WaveformPanel {
|
|||
Label::new()
|
||||
.s(Padding::new().x(20).y(10))
|
||||
.s(Background::new().color_signal(
|
||||
hovered_signal
|
||||
.map_bool(|| color!("MediumSlateBlue"), || color!("SlateBlue")),
|
||||
hovered_signal.map_bool(|| COLOR_MEDIUM_SLATE_BLUE, || COLOR_SLATE_BLUE),
|
||||
))
|
||||
.s(Align::new().left())
|
||||
.s(RoundedCorners::all(15))
|
||||
|
@ -178,7 +177,7 @@ impl WaveformPanel {
|
|||
Button::new()
|
||||
.s(Padding::new().x(20).y(10))
|
||||
.s(Background::new().color_signal(
|
||||
hovered_signal.map_bool(|| color!("MediumSlateBlue"), || color!("SlateBlue")),
|
||||
hovered_signal.map_bool(|| COLOR_MEDIUM_SLATE_BLUE, || COLOR_SLATE_BLUE),
|
||||
))
|
||||
.s(RoundedCorners::all(15))
|
||||
.label("Save")
|
||||
|
@ -349,7 +348,7 @@ impl WaveformPanel {
|
|||
.s(Height::exact(ROW_HEIGHT))
|
||||
.s(Width::growable())
|
||||
.s(Background::new().color_signal(
|
||||
hovered_signal.map_bool(|| color!("SlateBlue"), || color!("SlateBlue", 0.8)),
|
||||
hovered_signal.map_bool(|| COLOR_SLATE_BLUE, || COLOR_SLATE_BLUE_WITH_ALPHA),
|
||||
))
|
||||
.s(RoundedCorners::new().left(15).right(5))
|
||||
.label(
|
||||
|
@ -384,7 +383,7 @@ impl WaveformPanel {
|
|||
.s(Height::exact(ROW_HEIGHT))
|
||||
.s(Width::exact(70))
|
||||
.s(Background::new().color_signal(
|
||||
hovered_signal.map_bool(|| color!("SlateBlue"), || color!("SlateBlue", 0.8)),
|
||||
hovered_signal.map_bool(|| COLOR_SLATE_BLUE, || COLOR_SLATE_BLUE_WITH_ALPHA),
|
||||
))
|
||||
.s(RoundedCorners::new().left(5))
|
||||
.label(
|
||||
|
|
|
@ -35128,6 +35128,10 @@ var import_earcut2 = __toESM(require_earcut(), 1);
|
|||
extensions.add(browserExt, webworkerExt);
|
||||
|
||||
// pixi_canvas.ts
|
||||
var color_dark_slate_blue = "#24478e";
|
||||
var color_white = "#ffffff";
|
||||
var color_slate_blue = "#3d7af3";
|
||||
var color_dark_violet_with_x = "0x002ca9";
|
||||
var PixiController = class {
|
||||
app;
|
||||
// -- FastWave-specific --
|
||||
|
@ -35151,7 +35155,7 @@ var PixiController = class {
|
|||
this.timeline_getter = timeline_getter;
|
||||
}
|
||||
async init(parent_element) {
|
||||
await this.app.init({ background: "DarkSlateBlue", antialias: true, resizeTo: parent_element });
|
||||
await this.app.init({ background: color_dark_slate_blue, antialias: true, resizeTo: parent_element });
|
||||
parent_element.appendChild(this.app.canvas);
|
||||
}
|
||||
// Default automatic Pixi resizing according to the parent is not reliable
|
||||
|
@ -35284,7 +35288,7 @@ var VarSignalRow = class {
|
|||
signal_blocks_container = new Container();
|
||||
label_style = new TextStyle({
|
||||
align: "center",
|
||||
fill: "White",
|
||||
fill: color_white,
|
||||
fontSize: 16,
|
||||
fontFamily: '"Courier New", monospace'
|
||||
});
|
||||
|
@ -35304,7 +35308,7 @@ var VarSignalRow = class {
|
|||
this.rows_container.addChild(this.row_container);
|
||||
this.row_container_background = new Sprite();
|
||||
this.row_container_background.texture = Texture.WHITE;
|
||||
this.row_container_background.tint = "0x550099";
|
||||
this.row_container_background.tint = color_dark_violet_with_x;
|
||||
this.row_container_background.height = this.row_height;
|
||||
this.row_container.addChild(this.row_container_background);
|
||||
this.row_container.addChild(this.signal_blocks_container);
|
||||
|
@ -35330,7 +35334,7 @@ var VarSignalRow = class {
|
|||
signal_block.x = timeline_block.x;
|
||||
this.signal_blocks_container.addChild(signal_block);
|
||||
const gap_between_blocks = 2;
|
||||
const background = new Graphics().rect(gap_between_blocks / 2, 0, timeline_block.width - gap_between_blocks, timeline_block.height).fill("SlateBlue");
|
||||
const background = new Graphics().rect(gap_between_blocks / 2, 0, timeline_block.width - gap_between_blocks, timeline_block.height).fill(color_slate_blue);
|
||||
signal_block.addChild(background);
|
||||
if (timeline_block.label !== void 0) {
|
||||
const label = new Text();
|
||||
|
|
|
@ -1,5 +1,17 @@
|
|||
import { Application, Text, Graphics, Container, TextStyle, Sprite, Texture } from "pixi.js";
|
||||
|
||||
// const color_dark_slate_blue = 'DarkSlateBlue'
|
||||
const color_dark_slate_blue = '#24478e' // oklch(41.43% 0.125 262.26)'
|
||||
|
||||
// const color_white = 'White'
|
||||
const color_white = '#ffffff' // oklch(100% 3.5594404384177905e-8 105.88)
|
||||
|
||||
// const color_slate_blue = 'SlateBlue'
|
||||
const color_slate_blue = '#3d7af3' // oklch(60.45% 0.194 262.26)
|
||||
|
||||
// const color_dark_violet_with_x = '0x550099' // oklch(37.6% 0.201 299.56)
|
||||
const color_dark_violet_with_x = '0x002ca9' // oklch(37.6% 0.201 263.53)
|
||||
|
||||
// @TODO sync with Rust and `tauri_glue.ts`
|
||||
type Timeline = {
|
||||
blocks: Array<TimelineBlock>
|
||||
|
@ -69,7 +81,7 @@ export class PixiController {
|
|||
}
|
||||
|
||||
async init(parent_element: HTMLElement) {
|
||||
await this.app.init({ background: 'DarkSlateBlue', antialias: true, resizeTo: parent_element });
|
||||
await this.app.init({ background: color_dark_slate_blue, antialias: true, resizeTo: parent_element });
|
||||
parent_element.appendChild(this.app.canvas);
|
||||
}
|
||||
|
||||
|
@ -221,7 +233,7 @@ class VarSignalRow {
|
|||
signal_blocks_container = new Container();
|
||||
label_style = new TextStyle({
|
||||
align: "center",
|
||||
fill: "White",
|
||||
fill: color_white,
|
||||
fontSize: 16,
|
||||
fontFamily: '"Courier New", monospace',
|
||||
});
|
||||
|
@ -258,7 +270,7 @@ class VarSignalRow {
|
|||
// row background
|
||||
this.row_container_background = new Sprite();
|
||||
this.row_container_background.texture = Texture.WHITE;
|
||||
this.row_container_background.tint = '0x550099';
|
||||
this.row_container_background.tint = color_dark_violet_with_x;
|
||||
this.row_container_background.height = this.row_height;
|
||||
this.row_container.addChild(this.row_container_background);
|
||||
|
||||
|
@ -300,7 +312,7 @@ class VarSignalRow {
|
|||
const gap_between_blocks = 2;
|
||||
const background = new Graphics()
|
||||
.rect(gap_between_blocks / 2, 0, timeline_block.width - gap_between_blocks, timeline_block.height)
|
||||
.fill('SlateBlue');
|
||||
.fill(color_slate_blue);
|
||||
signal_block.addChild(background);
|
||||
|
||||
// label
|
||||
|
|
BIN
public/favicon/android-chrome-192x192.png
Normal file
After Width: | Height: | Size: 27 KiB |
BIN
public/favicon/android-chrome-512x512.png
Normal file
After Width: | Height: | Size: 113 KiB |
BIN
public/favicon/apple-touch-icon.png
Normal file
After Width: | Height: | Size: 20 KiB |
9
public/favicon/browserconfig.xml
Normal file
|
@ -0,0 +1,9 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<browserconfig>
|
||||
<msapplication>
|
||||
<tile>
|
||||
<square150x150logo src="/_api/public/favicon/mstile-150x150.png"/>
|
||||
<TileColor>#00a300</TileColor>
|
||||
</tile>
|
||||
</msapplication>
|
||||
</browserconfig>
|
BIN
public/favicon/favicon-16x16.png
Normal file
After Width: | Height: | Size: 1.3 KiB |
BIN
public/favicon/favicon-32x32.png
Normal file
After Width: | Height: | Size: 2.5 KiB |
BIN
public/favicon/favicon.ico
Normal file
After Width: | Height: | Size: 15 KiB |
BIN
public/favicon/mstile-150x150.png
Normal file
After Width: | Height: | Size: 17 KiB |
19
public/favicon/site.webmanifest
Normal file
|
@ -0,0 +1,19 @@
|
|||
{
|
||||
"name": "",
|
||||
"short_name": "",
|
||||
"icons": [
|
||||
{
|
||||
"src": "/_api/public/favicon/android-chrome-192x192.png",
|
||||
"sizes": "192x192",
|
||||
"type": "image/png"
|
||||
},
|
||||
{
|
||||
"src": "/_api/public/favicon/android-chrome-512x512.png",
|
||||
"sizes": "512x512",
|
||||
"type": "image/png"
|
||||
}
|
||||
],
|
||||
"theme_color": "#ffffff",
|
||||
"background_color": "#ffffff",
|
||||
"display": "standalone"
|
||||
}
|
Before Width: | Height: | Size: 11 KiB After Width: | Height: | Size: 17 KiB |
Before Width: | Height: | Size: 23 KiB After Width: | Height: | Size: 44 KiB |
Before Width: | Height: | Size: 2.2 KiB After Width: | Height: | Size: 2.6 KiB |
Before Width: | Height: | Size: 9 KiB After Width: | Height: | Size: 14 KiB |
Before Width: | Height: | Size: 12 KiB After Width: | Height: | Size: 20 KiB |
Before Width: | Height: | Size: 13 KiB After Width: | Height: | Size: 21 KiB |
Before Width: | Height: | Size: 25 KiB After Width: | Height: | Size: 50 KiB |
Before Width: | Height: | Size: 2 KiB After Width: | Height: | Size: 2.4 KiB |
Before Width: | Height: | Size: 28 KiB After Width: | Height: | Size: 57 KiB |
Before Width: | Height: | Size: 3.3 KiB After Width: | Height: | Size: 4.2 KiB |
Before Width: | Height: | Size: 5.9 KiB After Width: | Height: | Size: 8.1 KiB |
Before Width: | Height: | Size: 7.4 KiB After Width: | Height: | Size: 11 KiB |
Before Width: | Height: | Size: 3.9 KiB After Width: | Height: | Size: 5.1 KiB |
BIN
src-tauri/icons/android/mipmap-hdpi/ic_launcher.png
Normal file
After Width: | Height: | Size: 5 KiB |
BIN
src-tauri/icons/android/mipmap-hdpi/ic_launcher_foreground.png
Normal file
After Width: | Height: | Size: 24 KiB |
BIN
src-tauri/icons/android/mipmap-hdpi/ic_launcher_round.png
Normal file
After Width: | Height: | Size: 5 KiB |
BIN
src-tauri/icons/android/mipmap-mdpi/ic_launcher.png
Normal file
After Width: | Height: | Size: 4.7 KiB |
BIN
src-tauri/icons/android/mipmap-mdpi/ic_launcher_foreground.png
Normal file
After Width: | Height: | Size: 14 KiB |
BIN
src-tauri/icons/android/mipmap-mdpi/ic_launcher_round.png
Normal file
After Width: | Height: | Size: 4.7 KiB |
BIN
src-tauri/icons/android/mipmap-xhdpi/ic_launcher.png
Normal file
After Width: | Height: | Size: 12 KiB |
BIN
src-tauri/icons/android/mipmap-xhdpi/ic_launcher_foreground.png
Normal file
After Width: | Height: | Size: 35 KiB |
BIN
src-tauri/icons/android/mipmap-xhdpi/ic_launcher_round.png
Normal file
After Width: | Height: | Size: 12 KiB |
BIN
src-tauri/icons/android/mipmap-xxhdpi/ic_launcher.png
Normal file
After Width: | Height: | Size: 20 KiB |
BIN
src-tauri/icons/android/mipmap-xxhdpi/ic_launcher_foreground.png
Normal file
After Width: | Height: | Size: 61 KiB |
BIN
src-tauri/icons/android/mipmap-xxhdpi/ic_launcher_round.png
Normal file
After Width: | Height: | Size: 20 KiB |
BIN
src-tauri/icons/android/mipmap-xxxhdpi/ic_launcher.png
Normal file
After Width: | Height: | Size: 29 KiB |
After Width: | Height: | Size: 96 KiB |
BIN
src-tauri/icons/android/mipmap-xxxhdpi/ic_launcher_round.png
Normal file
After Width: | Height: | Size: 29 KiB |
Before Width: | Height: | Size: 37 KiB After Width: | Height: | Size: 62 KiB |
Before Width: | Height: | Size: 49 KiB After Width: | Height: | Size: 128 KiB |
BIN
src-tauri/icons/ios/AppIcon-20x20@1x.png
Normal file
After Width: | Height: | Size: 1.2 KiB |
BIN
src-tauri/icons/ios/AppIcon-20x20@2x-1.png
Normal file
After Width: | Height: | Size: 3.3 KiB |
BIN
src-tauri/icons/ios/AppIcon-20x20@2x.png
Normal file
After Width: | Height: | Size: 3.3 KiB |
BIN
src-tauri/icons/ios/AppIcon-20x20@3x.png
Normal file
After Width: | Height: | Size: 5.8 KiB |
BIN
src-tauri/icons/ios/AppIcon-29x29@1x.png
Normal file
After Width: | Height: | Size: 2.1 KiB |
BIN
src-tauri/icons/ios/AppIcon-29x29@2x-1.png
Normal file
After Width: | Height: | Size: 5.5 KiB |
BIN
src-tauri/icons/ios/AppIcon-29x29@2x.png
Normal file
After Width: | Height: | Size: 5.5 KiB |
BIN
src-tauri/icons/ios/AppIcon-29x29@3x.png
Normal file
After Width: | Height: | Size: 9.5 KiB |
BIN
src-tauri/icons/ios/AppIcon-40x40@1x.png
Normal file
After Width: | Height: | Size: 3.3 KiB |
BIN
src-tauri/icons/ios/AppIcon-40x40@2x-1.png
Normal file
After Width: | Height: | Size: 8.4 KiB |
BIN
src-tauri/icons/ios/AppIcon-40x40@2x.png
Normal file
After Width: | Height: | Size: 8.4 KiB |
BIN
src-tauri/icons/ios/AppIcon-40x40@3x.png
Normal file
After Width: | Height: | Size: 14 KiB |
BIN
src-tauri/icons/ios/AppIcon-512@2x.png
Normal file
After Width: | Height: | Size: 427 KiB |
BIN
src-tauri/icons/ios/AppIcon-60x60@2x.png
Normal file
After Width: | Height: | Size: 14 KiB |
BIN
src-tauri/icons/ios/AppIcon-60x60@3x.png
Normal file
After Width: | Height: | Size: 24 KiB |
BIN
src-tauri/icons/ios/AppIcon-76x76@1x.png
Normal file
After Width: | Height: | Size: 8 KiB |
BIN
src-tauri/icons/ios/AppIcon-76x76@2x.png
Normal file
After Width: | Height: | Size: 19 KiB |
BIN
src-tauri/icons/ios/AppIcon-83.5x83.5@2x.png
Normal file
After Width: | Height: | Size: 22 KiB |
10
test_files/components/rust_decoder/.vscode/settings.json
vendored
Normal file
|
@ -0,0 +1,10 @@
|
|||
{
|
||||
"rust-analyzer.check.overrideCommand": [
|
||||
"cargo",
|
||||
"component",
|
||||
"check",
|
||||
"--workspace",
|
||||
"--all-targets",
|
||||
"--message-format=json"
|
||||
],
|
||||
}
|