Simplify and standardize how data types are presented in user-facing strings (#4147)
* User-facing type formatting * Parse unicode not ASCII chars
This commit is contained in:
parent
696b625a3e
commit
1c9c19a697
|
|
@ -276,7 +276,7 @@ pub(crate) fn property_from_type(
|
|||
widgets.extend_from_slice(&[
|
||||
Separator::new(SeparatorStyle::Unrelated).widget_instance(),
|
||||
TextLabel::new("-")
|
||||
.tooltip_label(format!("Data Type: {concrete_type}"))
|
||||
.tooltip_label(concrete_type.to_string())
|
||||
.tooltip_description("This data can only be supplied through the node graph because no widget exists for its type.")
|
||||
.widget_instance(),
|
||||
]);
|
||||
|
|
|
|||
|
|
@ -94,8 +94,8 @@ impl TypeSource {
|
|||
/// The type to display in the tooltip label.
|
||||
pub fn resolved_type_tooltip_string(&self) -> String {
|
||||
match self {
|
||||
TypeSource::Compiled(compiled_type) => format!("Data Type: {}", compiled_type.nested_type()),
|
||||
TypeSource::TaggedValue(value_type) => format!("Data Type: {}", value_type.nested_type()),
|
||||
TypeSource::Compiled(compiled_type) => compiled_type.nested_type().to_string(),
|
||||
TypeSource::TaggedValue(value_type) => value_type.nested_type().to_string(),
|
||||
TypeSource::Unknown => "Unknown Data Type".to_string(),
|
||||
TypeSource::Invalid => "Invalid Type Combination".to_string(),
|
||||
TypeSource::Error(_) => "Error Getting Data Type".to_string(),
|
||||
|
|
@ -253,8 +253,8 @@ impl NodeNetworkInterface {
|
|||
};
|
||||
let number_of_inputs = self.number_of_inputs(node_id, network_path);
|
||||
implementations
|
||||
.iter()
|
||||
.filter_map(|(node_io, _)| {
|
||||
.keys()
|
||||
.filter_map(|node_io| {
|
||||
// Check if this NodeIOTypes implementation is valid for the other inputs
|
||||
let valid_implementation = (0..number_of_inputs).filter(|iterator_index| iterator_index != input_index).all(|iterator_index| {
|
||||
let input_type = self.input_type_not_invalid(&InputConnector::node(*node_id, iterator_index), network_path);
|
||||
|
|
@ -293,8 +293,8 @@ impl NodeNetworkInterface {
|
|||
let valid_output_types = self.valid_output_types(&OutputConnector::node(*node_id, 0), network_path);
|
||||
|
||||
implementations
|
||||
.iter()
|
||||
.filter_map(|(node_io, _)| {
|
||||
.keys()
|
||||
.filter_map(|node_io| {
|
||||
if !valid_output_types.iter().any(|output_type| output_type.nested_type() == node_io.return_value.nested_type()) {
|
||||
return None;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -188,10 +188,6 @@
|
|||
return `M-2,-2 L${nodeWidth + 2},-2 L${nodeWidth + 2},${nodeHeight + 2} L-2,${nodeHeight + 2}z ${rectangles.join(" ")}`;
|
||||
}
|
||||
|
||||
function dataTypeTooltipLabel(value: FrontendGraphInput | FrontendGraphOutput): string {
|
||||
return `Data Type: ${value.resolvedType}`;
|
||||
}
|
||||
|
||||
function nodeNameTooltipLabel(node: FrontendNode): string {
|
||||
return node.displayName === node.implementationName ? node.displayName : `${node.displayName} (${node.implementationName})`;
|
||||
}
|
||||
|
|
@ -349,7 +345,7 @@
|
|||
viewBox="0 0 8 8"
|
||||
class="connector"
|
||||
data-connector="output"
|
||||
data-tooltip-label={dataTypeTooltipLabel(frontendOutput)}
|
||||
data-tooltip-label={frontendOutput.resolvedType}
|
||||
data-tooltip-description={outputConnectedToText(frontendOutput)}
|
||||
data-datatype={frontendOutput.dataType}
|
||||
style:--data-color={`var(--color-data-${frontendOutput.dataType.toLowerCase()})`}
|
||||
|
|
@ -418,7 +414,7 @@
|
|||
viewBox="0 0 8 8"
|
||||
class="connector"
|
||||
data-connector="input"
|
||||
data-tooltip-label={dataTypeTooltipLabel(frontendInput)}
|
||||
data-tooltip-label={frontendInput.resolvedType}
|
||||
data-tooltip-description={inputConnectedToText(frontendInput)}
|
||||
data-datatype={frontendInput.dataType}
|
||||
style:--data-color={`var(--color-data-${frontendInput.dataType.toLowerCase()})`}
|
||||
|
|
@ -556,7 +552,7 @@
|
|||
viewBox="0 0 8 12"
|
||||
class="connector top"
|
||||
data-connector="output"
|
||||
data-tooltip-label={dataTypeTooltipLabel(node.primaryOutput)}
|
||||
data-tooltip-label={node.primaryOutput.resolvedType}
|
||||
data-tooltip-description={outputConnectedToText(node.primaryOutput)}
|
||||
data-datatype={node.primaryOutput.dataType}
|
||||
style:--data-color={`var(--color-data-${node.primaryOutput.dataType.toLowerCase()})`}
|
||||
|
|
@ -578,7 +574,7 @@
|
|||
viewBox="0 0 8 12"
|
||||
class="connector bottom"
|
||||
data-connector="input"
|
||||
data-tooltip-label={node.primaryInput ? dataTypeTooltipLabel(node.primaryInput) : ""}
|
||||
data-tooltip-label={node.primaryInput ? node.primaryInput.resolvedType : ""}
|
||||
data-tooltip-description={node.primaryInput ? `${validTypesText(node.primaryInput).trim()}\n\n${inputConnectedToText(node.primaryInput)}` : ""}
|
||||
data-datatype={node.primaryInput?.dataType}
|
||||
style:--data-color={`var(--color-data-${(node.primaryInput?.dataType || "General").toLowerCase()})`}
|
||||
|
|
@ -601,7 +597,7 @@
|
|||
xmlns="http://www.w3.org/2000/svg"
|
||||
viewBox="0 0 8 8"
|
||||
class="connector"
|
||||
data-tooltip-label={dataTypeTooltipLabel(stackDataInput)}
|
||||
data-tooltip-label={stackDataInput.resolvedType}
|
||||
data-tooltip-description={`${validTypesText(stackDataInput).trim()}\n\n${inputConnectedToText(stackDataInput)}`}
|
||||
data-connector="input"
|
||||
data-datatype={stackDataInput.dataType}
|
||||
|
|
@ -755,7 +751,7 @@
|
|||
viewBox="0 0 8 8"
|
||||
class="connector primary-connector"
|
||||
data-connector="input"
|
||||
data-tooltip-label={dataTypeTooltipLabel(node.primaryInput)}
|
||||
data-tooltip-label={node.primaryInput.resolvedType}
|
||||
data-tooltip-description={`${validTypesText(node.primaryInput).trim()}\n\n${inputConnectedToText(node.primaryInput)}`}
|
||||
data-datatype={node.primaryInput?.dataType}
|
||||
style:--data-color={`var(--color-data-${node.primaryInput.dataType.toLowerCase()})`}
|
||||
|
|
@ -775,7 +771,7 @@
|
|||
viewBox="0 0 8 8"
|
||||
class="connector"
|
||||
data-connector="input"
|
||||
data-tooltip-label={dataTypeTooltipLabel(secondary)}
|
||||
data-tooltip-label={secondary.resolvedType}
|
||||
data-tooltip-description={`${validTypesText(secondary).trim()}\n\n${inputConnectedToText(secondary)}`}
|
||||
data-datatype={secondary.dataType}
|
||||
style:--data-color={`var(--color-data-${secondary.dataType.toLowerCase()})`}
|
||||
|
|
@ -798,7 +794,7 @@
|
|||
viewBox="0 0 8 8"
|
||||
class="connector primary-connector"
|
||||
data-connector="output"
|
||||
data-tooltip-label={dataTypeTooltipLabel(node.primaryOutput)}
|
||||
data-tooltip-label={node.primaryOutput.resolvedType}
|
||||
data-tooltip-description={`${outputConnectedToText(node.primaryOutput)}`}
|
||||
data-datatype={node.primaryOutput.dataType}
|
||||
style:--data-color={`var(--color-data-${node.primaryOutput.dataType.toLowerCase()})`}
|
||||
|
|
@ -817,7 +813,7 @@
|
|||
viewBox="0 0 8 8"
|
||||
class="connector"
|
||||
data-connector="output"
|
||||
data-tooltip-label={dataTypeTooltipLabel(secondary)}
|
||||
data-tooltip-label={secondary.resolvedType}
|
||||
data-tooltip-description={`${outputConnectedToText(secondary)}`}
|
||||
data-datatype={secondary.dataType}
|
||||
style:--data-color={`var(--color-data-${secondary.dataType.toLowerCase()})`}
|
||||
|
|
|
|||
|
|
@ -1,4 +1,3 @@
|
|||
use crate::transform::Footprint;
|
||||
use std::any::TypeId;
|
||||
pub use std::borrow::Cow;
|
||||
use std::fmt::{Display, Formatter};
|
||||
|
|
@ -346,8 +345,73 @@ pub fn simplify_identifier_name(ty: &str) -> String {
|
|||
.join("<")
|
||||
}
|
||||
|
||||
/// Converts a Rust-internal type name to its user-facing form.
|
||||
pub fn make_type_user_readable(ty: &str) -> String {
|
||||
ty.replace("Option<Arc<OwnedContextImpl>>", "Context").replace("Raster<CPU>", "Raster").replace("Raster<GPU>", "Raster")
|
||||
let ty = ty
|
||||
.replace("Option<Arc<OwnedContextImpl>>", "Context")
|
||||
.replace("Raster<CPU>", "Raster")
|
||||
.replace("Raster<GPU>", "Raster")
|
||||
.replace("DAffine2", "Transform")
|
||||
.replace("Affine2", "Transform")
|
||||
.replace("DVec2", "Vec2")
|
||||
.replace("IVec2", "Vec2")
|
||||
.replace("UVec2", "Vec2")
|
||||
.replace("&str", "String");
|
||||
|
||||
rewrite_list_as_array_brackets(&ty)
|
||||
}
|
||||
|
||||
/// Rewrites `List<T>` as `T[]`. Handles nesting (e.g. `List<List<Vector>>` becomes `Vector[][]`).
|
||||
/// Respects word boundaries so unrelated identifiers that happen to end in `List` are not affected.
|
||||
fn rewrite_list_as_array_brackets(input: &str) -> String {
|
||||
let bytes = input.as_bytes();
|
||||
let mut result = String::with_capacity(input.len());
|
||||
let mut i = 0;
|
||||
|
||||
while i < bytes.len() {
|
||||
let at_word_boundary = i == 0 || !is_identifier_byte(bytes[i - 1]);
|
||||
if at_word_boundary && bytes[i..].starts_with(b"List<") {
|
||||
let inner_start = i + b"List<".len();
|
||||
if let Some(close) = find_matching_angle_bracket(bytes, inner_start) {
|
||||
let inner = &input[inner_start..close];
|
||||
result.push_str(&rewrite_list_as_array_brackets(inner));
|
||||
result.push_str("[]");
|
||||
i = close + 1;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
if bytes[i].is_ascii() {
|
||||
result.push(bytes[i] as char);
|
||||
i += 1;
|
||||
} else {
|
||||
let ch = input[i..].chars().next().unwrap();
|
||||
result.push(ch);
|
||||
i += ch.len_utf8();
|
||||
}
|
||||
}
|
||||
|
||||
result
|
||||
}
|
||||
|
||||
fn is_identifier_byte(byte: u8) -> bool {
|
||||
byte.is_ascii_alphanumeric() || byte == b'_'
|
||||
}
|
||||
|
||||
fn find_matching_angle_bracket(bytes: &[u8], start: usize) -> Option<usize> {
|
||||
let mut depth = 1_usize;
|
||||
for (offset, &byte) in bytes[start..].iter().enumerate() {
|
||||
match byte {
|
||||
b'<' => depth += 1,
|
||||
b'>' => {
|
||||
depth -= 1;
|
||||
if depth == 0 {
|
||||
return Some(start + offset);
|
||||
}
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
None
|
||||
}
|
||||
|
||||
impl std::fmt::Debug for Type {
|
||||
|
|
@ -359,18 +423,10 @@ impl std::fmt::Debug for Type {
|
|||
// Display
|
||||
impl std::fmt::Display for Type {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||
use glam::*;
|
||||
|
||||
match self {
|
||||
Type::Generic(name) => write!(f, "{}", make_type_user_readable(name)),
|
||||
Type::Concrete(ty) => match () {
|
||||
() if self == &concrete!(DVec2) || self == &concrete!(Vec2) || self == &concrete!(IVec2) || self == &concrete!(UVec2) => write!(f, "Vec2"),
|
||||
() if self == &concrete!(glam::DAffine2) => write!(f, "Transform"),
|
||||
() if self == &concrete!(Footprint) => write!(f, "Footprint"),
|
||||
() if self == &concrete!(&str) || self == &concrete!(String) => write!(f, "String"),
|
||||
_ => write!(f, "{}", make_type_user_readable(&simplify_identifier_name(&ty.name))),
|
||||
},
|
||||
Type::Fn(call_arg, return_value) => write!(f, "{return_value} called with {call_arg}"),
|
||||
Type::Concrete(ty) => write!(f, "{ty}"),
|
||||
Type::Fn(_, return_value) => write!(f, "{return_value}"),
|
||||
Type::Future(ty) => write!(f, "{ty}"),
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue