Rename Instances<T> to Table<T> and the "instance" terminology to "TableRow" and "element" (#2981)

* Instances -> Table

* instances.rs -> table.rs

* Rename occurrances of the word "instances"

* .instance -> .element

* Instance* -> TableRow*

* Rename Table and TableRow methods to not say "instance"

* Remove presumed unused serde defaults now that tables default to length 0 not 1

* Rename occurences of the word "instance"

* Un-alias the RasterDataTable<Storage>, VectorDataTable, GraphicGroupTable, ArtboardGroupTable typedefs

* Move artboard type and node code out of graphic_element.rs to a new artboard.rs

* Organize the TaggedValues

* Fix tests

* Fix prior regression with Image Value node not upgrading
This commit is contained in:
Keavon Chambers
2025-08-03 04:12:18 -07:00
committed by GitHub
parent 67123f55dc
commit a0ce56d9b6
66 changed files with 1906 additions and 2061 deletions
@@ -1,7 +1,7 @@
use crate::messages::prelude::*;
use crate::node_graph_executor::InspectResult;
/// The spreadsheet UI allows for instance data to be previewed.
/// The spreadsheet UI allows for graph data to be previewed.
#[impl_message(Message, PortfolioMessage, Spreadsheet)]
#[derive(PartialEq, Clone, Debug, serde::Serialize, serde::Deserialize)]
pub enum SpreadsheetMessage {
@@ -12,10 +12,10 @@ pub enum SpreadsheetMessage {
inspect_result: InspectResult,
},
PushToInstancePath {
PushToElementPath {
index: usize,
},
TruncateInstancePath {
TruncateElementPath {
len: usize,
},
@@ -5,23 +5,22 @@ use crate::messages::tool::tool_messages::tool_prelude::*;
use graph_craft::document::NodeId;
use graphene_std::Color;
use graphene_std::Context;
use graphene_std::GraphicGroupTable;
use graphene_std::instances::Instances;
use graphene_std::memo::IORecord;
use graphene_std::raster::Image;
use graphene_std::vector::{VectorData, VectorDataTable};
use graphene_std::{Artboard, ArtboardGroupTable, GraphicElement};
use graphene_std::table::Table;
use graphene_std::vector::VectorData;
use graphene_std::{Artboard, GraphicElement};
use std::any::Any;
use std::sync::Arc;
/// The spreadsheet UI allows for instance data to be previewed.
/// The spreadsheet UI allows for graph data to be previewed.
#[derive(Default, Debug, Clone, ExtractField)]
pub struct SpreadsheetMessageHandler {
/// Sets whether or not the spreadsheet is drawn.
pub spreadsheet_view_open: bool,
inspect_node: Option<NodeId>,
introspected_data: Option<Arc<dyn Any + Send + Sync>>,
instances_path: Vec<usize>,
element_path: Vec<usize>,
viewing_vector_data_domain: VectorDataDomain,
}
@@ -46,12 +45,12 @@ impl MessageHandler<SpreadsheetMessage, ()> for SpreadsheetMessageHandler {
self.update_layout(responses)
}
SpreadsheetMessage::PushToInstancePath { index } => {
self.instances_path.push(index);
SpreadsheetMessage::PushToElementPath { index } => {
self.element_path.push(index);
self.update_layout(responses);
}
SpreadsheetMessage::TruncateInstancePath { len } => {
self.instances_path.truncate(len);
SpreadsheetMessage::TruncateElementPath { len } => {
self.element_path.truncate(len);
self.update_layout(responses);
}
@@ -78,7 +77,7 @@ impl SpreadsheetMessageHandler {
}
let mut layout_data = LayoutData {
current_depth: 0,
desired_path: &mut self.instances_path,
desired_path: &mut self.element_path,
breadcrumbs: Vec::new(),
vector_data_domain: self.viewing_vector_data_domain,
};
@@ -91,7 +90,7 @@ impl SpreadsheetMessageHandler {
if layout_data.breadcrumbs.len() > 1 {
let breadcrumb = BreadcrumbTrailButtons::new(layout_data.breadcrumbs)
.on_update(|&len| SpreadsheetMessage::TruncateInstancePath { len: len as usize }.into())
.on_update(|&len| SpreadsheetMessage::TruncateElementPath { len: len as usize }.into())
.widget_holder();
layout.insert(0, LayoutGroup::Row { widgets: vec![breadcrumb] });
}
@@ -113,17 +112,17 @@ struct LayoutData<'a> {
fn generate_layout(introspected_data: &Arc<dyn std::any::Any + Send + Sync + 'static>, data: &mut LayoutData) -> Option<Vec<LayoutGroup>> {
// We simply try random types. TODO: better strategy.
#[allow(clippy::manual_map)]
if let Some(io) = introspected_data.downcast_ref::<IORecord<Context, ArtboardGroupTable>>() {
if let Some(io) = introspected_data.downcast_ref::<IORecord<Context, Table<Artboard>>>() {
Some(io.output.layout_with_breadcrumb(data))
} else if let Some(io) = introspected_data.downcast_ref::<IORecord<(), ArtboardGroupTable>>() {
} else if let Some(io) = introspected_data.downcast_ref::<IORecord<(), Table<Artboard>>>() {
Some(io.output.layout_with_breadcrumb(data))
} else if let Some(io) = introspected_data.downcast_ref::<IORecord<Context, VectorDataTable>>() {
} else if let Some(io) = introspected_data.downcast_ref::<IORecord<Context, Table<VectorData>>>() {
Some(io.output.layout_with_breadcrumb(data))
} else if let Some(io) = introspected_data.downcast_ref::<IORecord<(), VectorDataTable>>() {
} else if let Some(io) = introspected_data.downcast_ref::<IORecord<(), Table<VectorData>>>() {
Some(io.output.layout_with_breadcrumb(data))
} else if let Some(io) = introspected_data.downcast_ref::<IORecord<Context, GraphicGroupTable>>() {
} else if let Some(io) = introspected_data.downcast_ref::<IORecord<Context, Table<GraphicElement>>>() {
Some(io.output.layout_with_breadcrumb(data))
} else if let Some(io) = introspected_data.downcast_ref::<IORecord<(), GraphicGroupTable>>() {
} else if let Some(io) = introspected_data.downcast_ref::<IORecord<(), Table<GraphicElement>>>() {
Some(io.output.layout_with_breadcrumb(data))
} else {
None
@@ -139,7 +138,7 @@ fn label(x: impl Into<String>) -> Vec<LayoutGroup> {
vec![LayoutGroup::Row { widgets: error }]
}
trait InstanceLayout {
trait TableRowLayout {
fn type_name() -> &'static str;
fn identifier(&self) -> String;
fn layout_with_breadcrumb(&self, data: &mut LayoutData) -> Vec<LayoutGroup> {
@@ -149,14 +148,14 @@ trait InstanceLayout {
fn compute_layout(&self, data: &mut LayoutData) -> Vec<LayoutGroup>;
}
impl InstanceLayout for GraphicElement {
impl TableRowLayout for GraphicElement {
fn type_name() -> &'static str {
"GraphicElement"
}
fn identifier(&self) -> String {
match self {
Self::GraphicGroup(instances) => instances.identifier(),
Self::VectorData(instances) => instances.identifier(),
Self::GraphicGroup(table) => table.identifier(),
Self::VectorData(table) => table.identifier(),
Self::RasterDataCPU(_) => "RasterDataCPU".to_string(),
Self::RasterDataGPU(_) => "RasterDataGPU".to_string(),
}
@@ -167,15 +166,15 @@ impl InstanceLayout for GraphicElement {
}
fn compute_layout(&self, data: &mut LayoutData) -> Vec<LayoutGroup> {
match self {
Self::GraphicGroup(instances) => instances.layout_with_breadcrumb(data),
Self::VectorData(instances) => instances.layout_with_breadcrumb(data),
Self::GraphicGroup(table) => table.layout_with_breadcrumb(data),
Self::VectorData(table) => table.layout_with_breadcrumb(data),
Self::RasterDataCPU(_) => label("Raster frame not supported"),
Self::RasterDataGPU(_) => label("Raster frame not supported"),
}
}
}
impl InstanceLayout for VectorData {
impl TableRowLayout for VectorData {
fn type_name() -> &'static str {
"VectorData"
}
@@ -243,7 +242,7 @@ impl InstanceLayout for VectorData {
}
}
impl InstanceLayout for Image<Color> {
impl TableRowLayout for Image<Color> {
fn type_name() -> &'static str {
"Image"
}
@@ -256,7 +255,7 @@ impl InstanceLayout for Image<Color> {
}
}
impl InstanceLayout for Artboard {
impl TableRowLayout for Artboard {
fn type_name() -> &'static str {
"Artboard"
}
@@ -268,18 +267,18 @@ impl InstanceLayout for Artboard {
}
}
impl<T: InstanceLayout> InstanceLayout for Instances<T> {
impl<T: TableRowLayout> TableRowLayout for Table<T> {
fn type_name() -> &'static str {
"Instances"
"Table"
}
fn identifier(&self) -> String {
format!("Instances<{}> (length={})", T::type_name(), self.len())
format!("Table<{}> (length={})", T::type_name(), self.len())
}
fn compute_layout(&self, data: &mut LayoutData) -> Vec<LayoutGroup> {
if let Some(index) = data.desired_path.get(data.current_depth).copied() {
if let Some(instance) = self.get(index) {
if let Some(row) = self.get(index) {
data.current_depth += 1;
let result = instance.instance.layout_with_breadcrumb(data);
let result = row.element.layout_with_breadcrumb(data);
data.current_depth -= 1;
return result;
} else {
@@ -289,16 +288,16 @@ impl<T: InstanceLayout> InstanceLayout for Instances<T> {
}
let mut rows = self
.instance_ref_iter()
.iter_ref()
.enumerate()
.map(|(index, instance)| {
let (scale, angle, translation) = instance.transform.to_scale_angle_translation();
.map(|(index, row)| {
let (scale, angle, translation) = row.transform.to_scale_angle_translation();
let rotation = if angle == -0. { 0. } else { angle.to_degrees() };
let round = |x: f64| (x * 1e3).round() / 1e3;
vec![
TextLabel::new(format!("{}", index)).widget_holder(),
TextButton::new(instance.instance.identifier())
.on_update(move |_| SpreadsheetMessage::PushToInstancePath { index }.into())
TextButton::new(row.element.identifier())
.on_update(move |_| SpreadsheetMessage::PushToElementPath { index }.into())
.widget_holder(),
TextLabel::new(format!(
"Location: ({} px, {} px) — Rotation: {rotation:2}° — Scale: ({}x, {}x)",
@@ -308,15 +307,15 @@ impl<T: InstanceLayout> InstanceLayout for Instances<T> {
round(scale.y)
))
.widget_holder(),
TextLabel::new(format!("{}", instance.alpha_blending)).widget_holder(),
TextLabel::new(instance.source_node_id.map_or_else(|| "-".to_string(), |id| format!("{}", id.0))).widget_holder(),
TextLabel::new(format!("{}", row.alpha_blending)).widget_holder(),
TextLabel::new(row.source_node_id.map_or_else(|| "-".to_string(), |id| format!("{}", id.0))).widget_holder(),
]
})
.collect::<Vec<_>>();
rows.insert(0, column_headings(&["", "instance", "transform", "alpha_blending", "source_node_id"]));
rows.insert(0, column_headings(&["", "element", "transform", "alpha_blending", "source_node_id"]));
let instances = vec![TextLabel::new("Instances:").widget_holder()];
vec![LayoutGroup::Row { widgets: instances }, LayoutGroup::Table { rows }]
let table = vec![TextLabel::new("Table:").widget_holder()];
vec![LayoutGroup::Row { widgets: table }, LayoutGroup::Table { rows }]
}
}