selected_var_format_button
This commit is contained in:
parent
fbdf8090a1
commit
a6da2887c9
3
Cargo.lock
generated
3
Cargo.lock
generated
|
@ -1420,7 +1420,6 @@ checksum = "9fc0510504f03c51ada170672ac806f1f105a88aa97a5281117e1ddc3368e51a"
|
||||||
name = "fastwave"
|
name = "fastwave"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"convert-base",
|
|
||||||
"serde",
|
"serde",
|
||||||
"serde_json",
|
"serde_json",
|
||||||
"shared",
|
"shared",
|
||||||
|
@ -1506,7 +1505,6 @@ dependencies = [
|
||||||
name = "frontend"
|
name = "frontend"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"convert-base",
|
|
||||||
"gloo-file",
|
"gloo-file",
|
||||||
"shared",
|
"shared",
|
||||||
"wasm-bindgen-test",
|
"wasm-bindgen-test",
|
||||||
|
@ -4132,6 +4130,7 @@ dependencies = [
|
||||||
name = "shared"
|
name = "shared"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
|
"convert-base",
|
||||||
"futures-util",
|
"futures-util",
|
||||||
"moonlight",
|
"moonlight",
|
||||||
"wellen",
|
"wellen",
|
||||||
|
|
|
@ -16,7 +16,6 @@ readme = "../README.md"
|
||||||
publish = false
|
publish = false
|
||||||
|
|
||||||
[workspace.dependencies]
|
[workspace.dependencies]
|
||||||
convert-base = "1.1.2"
|
|
||||||
# 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" }
|
||||||
|
|
|
@ -13,7 +13,6 @@ wasm-bindgen-test = "0.3.19"
|
||||||
[dependencies]
|
[dependencies]
|
||||||
zoon.workspace = true
|
zoon.workspace = true
|
||||||
wellen.workspace = true
|
wellen.workspace = true
|
||||||
convert-base.workspace = true
|
|
||||||
shared = { path = "../shared", features = ["frontend"] }
|
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"] }
|
||||||
|
|
|
@ -170,7 +170,8 @@ impl ControlsPanel {
|
||||||
Label::new()
|
Label::new()
|
||||||
.s(Padding::new().x(20).y(10))
|
.s(Padding::new().x(20).y(10))
|
||||||
.s(Background::new().color_signal(
|
.s(Background::new().color_signal(
|
||||||
hovered_signal.map_bool(|| color!("MediumSlateBlue"), || color!("SlateBlue")),
|
hovered_signal
|
||||||
|
.map_bool(|| color!("MediumSlateBlue"), || color!("SlateBlue")),
|
||||||
))
|
))
|
||||||
.s(Align::new().left())
|
.s(Align::new().left())
|
||||||
.s(RoundedCorners::all(15))
|
.s(RoundedCorners::all(15))
|
||||||
|
@ -183,7 +184,9 @@ impl ControlsPanel {
|
||||||
))
|
))
|
||||||
.on_hovered_change(move |is_hovered| hovered.set_neq(is_hovered))
|
.on_hovered_change(move |is_hovered| hovered.set_neq(is_hovered))
|
||||||
.for_input(file_input_id)
|
.for_input(file_input_id)
|
||||||
.on_click_event_with_options(EventOptions::new().preventable(), clone!((hierarchy) move |event| {
|
.on_click_event_with_options(
|
||||||
|
EventOptions::new().preventable(),
|
||||||
|
clone!((hierarchy) move |event| {
|
||||||
let mut hierarchy_lock = hierarchy.lock_mut();
|
let mut hierarchy_lock = hierarchy.lock_mut();
|
||||||
if hierarchy_lock.is_some() {
|
if hierarchy_lock.is_some() {
|
||||||
*hierarchy_lock = None;
|
*hierarchy_lock = None;
|
||||||
|
@ -193,20 +196,21 @@ impl ControlsPanel {
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}))
|
}),
|
||||||
|
),
|
||||||
)
|
)
|
||||||
.item(
|
.item(
|
||||||
// @TODO https://github.com/MoonZoon/MoonZoon/issues/39
|
// @TODO https://github.com/MoonZoon/MoonZoon/issues/39
|
||||||
// + https://developer.mozilla.org/en-US/docs/Web/API/File_API/Using_files_from_web_applications#using_hidden_file_input_elements_using_the_click_method
|
// + https://developer.mozilla.org/en-US/docs/Web/API/File_API/Using_files_from_web_applications#using_hidden_file_input_elements_using_the_click_method
|
||||||
TextInput::new()
|
TextInput::new().id(file_input_id).update_raw_el(|raw_el| {
|
||||||
.id(file_input_id)
|
|
||||||
.update_raw_el(|raw_el| {
|
|
||||||
let dom_element = raw_el.dom_element();
|
let dom_element = raw_el.dom_element();
|
||||||
raw_el
|
raw_el
|
||||||
.style("display", "none")
|
.style("display", "none")
|
||||||
.attr("type", "file")
|
.attr("type", "file")
|
||||||
.event_handler(move |_: events::Input| {
|
.event_handler(move |_: events::Input| {
|
||||||
let Some(file_list) = dom_element.files().map(gloo_file::FileList::from) else {
|
let Some(file_list) =
|
||||||
|
dom_element.files().map(gloo_file::FileList::from)
|
||||||
|
else {
|
||||||
zoon::println!("file list is `None`");
|
zoon::println!("file list is `None`");
|
||||||
return;
|
return;
|
||||||
};
|
};
|
||||||
|
@ -217,13 +221,15 @@ impl ControlsPanel {
|
||||||
let hierarchy = hierarchy.clone();
|
let hierarchy = hierarchy.clone();
|
||||||
let loaded_filename = loaded_filename.clone();
|
let loaded_filename = loaded_filename.clone();
|
||||||
Task::start(async move {
|
Task::start(async move {
|
||||||
if let Some(filename) = platform::pick_and_load_waveform(Some(file)).await {
|
if let Some(filename) =
|
||||||
|
platform::pick_and_load_waveform(Some(file)).await
|
||||||
|
{
|
||||||
loaded_filename.set_neq(Some(filename));
|
loaded_filename.set_neq(Some(filename));
|
||||||
hierarchy.set(Some(Rc::new(platform::get_hierarchy().await)))
|
hierarchy.set(Some(Rc::new(platform::get_hierarchy().await)))
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
})
|
}),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
use zoon::*;
|
|
||||||
use std::rc::Rc;
|
use std::rc::Rc;
|
||||||
|
use zoon::*;
|
||||||
|
|
||||||
mod platform;
|
mod platform;
|
||||||
|
|
||||||
|
@ -42,13 +42,22 @@ fn root() -> impl Element {
|
||||||
selected_var_refs.clone(),
|
selected_var_refs.clone(),
|
||||||
layout.clone(),
|
layout.clone(),
|
||||||
))
|
))
|
||||||
.item_signal(layout.signal().map(|layout| matches!(layout, Layout::Tree)).map_true(clone!((hierarchy, selected_var_refs) move || WaveformPanel::new(
|
.item_signal(
|
||||||
|
layout
|
||||||
|
.signal()
|
||||||
|
.map(|layout| matches!(layout, Layout::Tree))
|
||||||
|
.map_true(
|
||||||
|
clone!((hierarchy, selected_var_refs) move || WaveformPanel::new(
|
||||||
hierarchy.clone(),
|
hierarchy.clone(),
|
||||||
selected_var_refs.clone(),
|
selected_var_refs.clone(),
|
||||||
))))
|
)),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
)
|
||||||
|
.item_signal(
|
||||||
|
layout
|
||||||
|
.signal()
|
||||||
|
.map(|layout| matches!(layout, Layout::Columns))
|
||||||
|
.map_true(move || WaveformPanel::new(hierarchy.clone(), selected_var_refs.clone())),
|
||||||
)
|
)
|
||||||
.item_signal(layout.signal().map(|layout| matches!(layout, Layout::Columns)).map_true(move || WaveformPanel::new(
|
|
||||||
hierarchy.clone(),
|
|
||||||
selected_var_refs.clone(),
|
|
||||||
)))
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -137,13 +137,7 @@ fn signal_to_timeline(
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
// @TODO dynamic formatter
|
let value = shared::VarFormat::default().format(value);
|
||||||
// @TODO optimize it by not using `.to_string` if possible
|
|
||||||
let value = value.to_string();
|
|
||||||
let ones_and_zeros = value.chars().rev().map(|char| char.to_digit(2).unwrap()).collect::<Vec<_>>();
|
|
||||||
let mut base = convert_base::Convert::new(2, 16);
|
|
||||||
let output = base.convert::<u32, u32>(&ones_and_zeros);
|
|
||||||
let value: String = output.into_iter().map(|number| char::from_digit(number, 16).unwrap()).collect();
|
|
||||||
|
|
||||||
let value_width = value.chars().count() as u32 * LETTER_WIDTH;
|
let value_width = value.chars().count() as u32 * LETTER_WIDTH;
|
||||||
let label = if (value_width + (2 * LABEL_X_PADDING)) <= block_width {
|
let label = if (value_width + (2 * LABEL_X_PADDING)) <= block_width {
|
||||||
|
|
|
@ -140,23 +140,56 @@ impl WaveformPanel {
|
||||||
None?
|
None?
|
||||||
};
|
};
|
||||||
let var = hierarchy.get(var_ref);
|
let var = hierarchy.get(var_ref);
|
||||||
let name: &str = var.name(&hierarchy);
|
Row::new()
|
||||||
|
.item(self.selected_var_name_button(var.name(&hierarchy), index))
|
||||||
|
.item(self.selected_var_format_button())
|
||||||
|
.apply(Some)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn selected_var_name_button(
|
||||||
|
&self,
|
||||||
|
name: &str,
|
||||||
|
index: ReadOnlyMutable<Option<usize>>,
|
||||||
|
) -> impl Element {
|
||||||
let selected_var_refs = self.selected_var_refs.clone();
|
let selected_var_refs = self.selected_var_refs.clone();
|
||||||
|
let (hovered, hovered_signal) = Mutable::new_and_signal(false);
|
||||||
Button::new()
|
Button::new()
|
||||||
.s(Height::exact(ROW_HEIGHT))
|
.s(Height::exact(ROW_HEIGHT))
|
||||||
.s(Background::new().color(color!("SlateBlue", 0.8)))
|
.s(Background::new().color_signal(
|
||||||
.s(RoundedCorners::new().left(15))
|
hovered_signal.map_bool(|| color!("SlateBlue"), || color!("SlateBlue", 0.8)),
|
||||||
|
))
|
||||||
|
.s(RoundedCorners::new().left(15).right(5))
|
||||||
.label(
|
.label(
|
||||||
El::new()
|
El::new()
|
||||||
.s(Align::center())
|
.s(Align::center())
|
||||||
.s(Padding::new().left(20).right(17).y(10))
|
.s(Padding::new().left(20).right(17).y(10))
|
||||||
.child(name),
|
.child(name),
|
||||||
)
|
)
|
||||||
|
.on_hovered_change(move |is_hovered| hovered.set_neq(is_hovered))
|
||||||
.on_press(move || {
|
.on_press(move || {
|
||||||
if let Some(index) = index.get() {
|
if let Some(index) = index.get() {
|
||||||
selected_var_refs.lock_mut().remove(index);
|
selected_var_refs.lock_mut().remove(index);
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
.apply(Some)
|
}
|
||||||
|
|
||||||
|
fn selected_var_format_button(&self) -> impl Element {
|
||||||
|
let var_format = Mutable::new(shared::VarFormat::default());
|
||||||
|
let (hovered, hovered_signal) = Mutable::new_and_signal(false);
|
||||||
|
Button::new()
|
||||||
|
.s(Height::exact(ROW_HEIGHT))
|
||||||
|
.s(Width::exact(70))
|
||||||
|
.s(Background::new().color_signal(
|
||||||
|
hovered_signal.map_bool(|| color!("SlateBlue"), || color!("SlateBlue", 0.8)),
|
||||||
|
))
|
||||||
|
.s(RoundedCorners::new().left(5))
|
||||||
|
.label(
|
||||||
|
El::new()
|
||||||
|
.s(Align::center())
|
||||||
|
.s(Padding::new().left(20).right(17).y(10))
|
||||||
|
.child_signal(var_format.signal().map(|format| format.as_static_str())),
|
||||||
|
)
|
||||||
|
.on_hovered_change(move |is_hovered| hovered.set_neq(is_hovered))
|
||||||
|
.on_press(move || var_format.update(|format| format.next()))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
pub use js_bridge::PixiController;
|
|
||||||
use zoon::*;
|
|
||||||
use std::rc::Rc;
|
|
||||||
use crate::platform;
|
use crate::platform;
|
||||||
|
pub use js_bridge::PixiController;
|
||||||
|
use std::rc::Rc;
|
||||||
|
use zoon::*;
|
||||||
|
|
||||||
pub struct PixiCanvas {
|
pub struct PixiCanvas {
|
||||||
raw_el: RawHtmlEl<web_sys::HtmlElement>,
|
raw_el: RawHtmlEl<web_sys::HtmlElement>,
|
||||||
|
@ -41,22 +41,31 @@ impl PixiCanvas {
|
||||||
let height = height.signal() => (*width, *height)
|
let height = height.signal() => (*width, *height)
|
||||||
}
|
}
|
||||||
.throttle(|| Timer::sleep(50))
|
.throttle(|| Timer::sleep(50))
|
||||||
.for_each(clone!((controller) move |(width, height)| clone!((controller) async move {
|
.for_each(
|
||||||
|
clone!((controller) move |(width, height)| clone!((controller) async move {
|
||||||
if let Some(controller) = controller.lock_ref().as_ref() {
|
if let Some(controller) = controller.lock_ref().as_ref() {
|
||||||
controller.resize(width, height).await
|
controller.resize(width, height).await
|
||||||
}
|
}
|
||||||
}))),
|
})),
|
||||||
|
),
|
||||||
);
|
);
|
||||||
let task_with_controller = Mutable::new(None);
|
let task_with_controller = Mutable::new(None);
|
||||||
// -- FastWave-specific --
|
// -- FastWave-specific --
|
||||||
let timeline_getter = Rc::new(Closure::new(|signal_ref_index, screen_width, row_height| {
|
let timeline_getter = Rc::new(Closure::new(
|
||||||
|
|signal_ref_index, screen_width, row_height| {
|
||||||
future_to_promise(async move {
|
future_to_promise(async move {
|
||||||
let signal_ref = wellen::SignalRef::from_index(signal_ref_index).unwrap_throw();
|
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 = platform::load_signal_and_get_timeline(
|
||||||
|
signal_ref,
|
||||||
|
screen_width,
|
||||||
|
row_height,
|
||||||
|
)
|
||||||
|
.await;
|
||||||
let timeline = serde_wasm_bindgen::to_value(&timeline).unwrap_throw();
|
let timeline = serde_wasm_bindgen::to_value(&timeline).unwrap_throw();
|
||||||
Ok(timeline)
|
Ok(timeline)
|
||||||
})
|
})
|
||||||
}));
|
},
|
||||||
|
));
|
||||||
// -- // --
|
// -- // --
|
||||||
Self {
|
Self {
|
||||||
controller: controller.read_only(),
|
controller: controller.read_only(),
|
||||||
|
@ -105,7 +114,8 @@ mod js_bridge {
|
||||||
type SignalRefIndex = usize;
|
type SignalRefIndex = usize;
|
||||||
type ScreenWidth = u32;
|
type ScreenWidth = u32;
|
||||||
type RowHeight = u32;
|
type RowHeight = u32;
|
||||||
type TimelineGetter = Closure<dyn FnMut(SignalRefIndex, ScreenWidth, RowHeight) -> TimelinePromise>;
|
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")]
|
||||||
|
@ -115,7 +125,11 @@ 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, timeline_getter: &TimelineGetter) -> 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);
|
||||||
|
|
|
@ -10,6 +10,7 @@ publish.workspace = true
|
||||||
[dependencies]
|
[dependencies]
|
||||||
wellen.workspace = true
|
wellen.workspace = true
|
||||||
moonlight.workspace = true
|
moonlight.workspace = true
|
||||||
|
convert-base = "1.1.2"
|
||||||
# @TODO update `futures_util_ext` - add feature `sink`, set exact `futures-util` version
|
# @TODO update `futures_util_ext` - add feature `sink`, set exact `futures-util` version
|
||||||
futures-util = { version = "0.3.30", features = ["sink"] }
|
futures-util = { version = "0.3.30", features = ["sink"] }
|
||||||
|
|
||||||
|
|
|
@ -1,5 +1,8 @@
|
||||||
use moonlight::*;
|
use moonlight::*;
|
||||||
|
|
||||||
|
mod var_format;
|
||||||
|
pub use var_format::VarFormat;
|
||||||
|
|
||||||
pub mod wellen_helpers;
|
pub mod wellen_helpers;
|
||||||
|
|
||||||
#[derive(Serialize, Deserialize, Debug, Default)]
|
#[derive(Serialize, Deserialize, Debug, Default)]
|
||||||
|
|
54
shared/src/var_format.rs
Normal file
54
shared/src/var_format.rs
Normal file
|
@ -0,0 +1,54 @@
|
||||||
|
#[derive(Default, Clone, Copy, Debug)]
|
||||||
|
pub enum VarFormat {
|
||||||
|
ASCII,
|
||||||
|
Binary,
|
||||||
|
BinaryWithGroups,
|
||||||
|
#[default]
|
||||||
|
Hexadecimal,
|
||||||
|
Octal,
|
||||||
|
Signed,
|
||||||
|
Unsigned,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl VarFormat {
|
||||||
|
pub fn as_static_str(&self) -> &'static str {
|
||||||
|
match self {
|
||||||
|
VarFormat::ASCII => "Text",
|
||||||
|
VarFormat::Binary => "Bin",
|
||||||
|
VarFormat::BinaryWithGroups => "Bins",
|
||||||
|
VarFormat::Hexadecimal => "Hex",
|
||||||
|
VarFormat::Octal => "Oct",
|
||||||
|
VarFormat::Signed => "i32",
|
||||||
|
VarFormat::Unsigned => "u32",
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn next(&self) -> Self {
|
||||||
|
match self {
|
||||||
|
VarFormat::ASCII => VarFormat::Binary,
|
||||||
|
VarFormat::Binary => VarFormat::BinaryWithGroups,
|
||||||
|
VarFormat::BinaryWithGroups => VarFormat::Hexadecimal,
|
||||||
|
VarFormat::Hexadecimal => VarFormat::Octal,
|
||||||
|
VarFormat::Octal => VarFormat::Signed,
|
||||||
|
VarFormat::Signed => VarFormat::Unsigned,
|
||||||
|
VarFormat::Unsigned => VarFormat::ASCII,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn format(&self, value: wellen::SignalValue) -> String {
|
||||||
|
// @TODO optimize it by not using `.to_string` if possible
|
||||||
|
let value = value.to_string();
|
||||||
|
let ones_and_zeros = value
|
||||||
|
.chars()
|
||||||
|
.rev()
|
||||||
|
.map(|char| char.to_digit(2).unwrap())
|
||||||
|
.collect::<Vec<_>>();
|
||||||
|
let mut base = convert_base::Convert::new(2, 16);
|
||||||
|
let output = base.convert::<u32, u32>(&ones_and_zeros);
|
||||||
|
let value: String = output
|
||||||
|
.into_iter()
|
||||||
|
.map(|number| char::from_digit(number, 16).unwrap())
|
||||||
|
.collect();
|
||||||
|
value
|
||||||
|
}
|
||||||
|
}
|
|
@ -17,7 +17,6 @@ tauri-build = { version = "=2.0.0-beta.17", features = [] }
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
wellen.workspace = true
|
wellen.workspace = true
|
||||||
convert-base.workspace = true
|
|
||||||
shared = { path = "../shared", features = ["backend"] }
|
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"] }
|
||||||
|
|
|
@ -131,13 +131,7 @@ fn signal_to_timeline(
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
// @TODO dynamic formatter
|
let value = shared::VarFormat::default().format(value);
|
||||||
// @TODO optimize it by not using `.to_string` if possible
|
|
||||||
let value = value.to_string();
|
|
||||||
let ones_and_zeros = value.chars().rev().map(|char| char.to_digit(2).unwrap()).collect::<Vec<_>>();
|
|
||||||
let mut base = convert_base::Convert::new(2, 16);
|
|
||||||
let output = base.convert::<u32, u32>(&ones_and_zeros);
|
|
||||||
let value: String = output.into_iter().map(|number| char::from_digit(number, 16).unwrap()).collect();
|
|
||||||
|
|
||||||
let value_width = value.chars().count() as u32 * LETTER_WIDTH;
|
let value_width = value.chars().count() as u32 * LETTER_WIDTH;
|
||||||
let label = if (value_width + (2 * LABEL_X_PADDING)) <= block_width {
|
let label = if (value_width + (2 * LABEL_X_PADDING)) <= block_width {
|
||||||
|
|
Loading…
Reference in a new issue